From e6249ad007adeec2010ef8a8f8f7907b4d60fdfd Mon Sep 17 00:00:00 2001 From: Simon Feltman Date: Tue, 17 Dec 2013 22:56:22 -0800 Subject: scanner: Fix get_symbols/comments to maintain the scanner lists Use g_slist_copy prior to returning the lists run through g_slist_reverse. This preserves the source scanners internally held lists where previously they would only point to a single element after a call, leaking memory and breaking subsequent calls. Note the functions as (transfer container) and use g_slist_free after calls in the Python bindings. Add new unittest file: test_sourcescanner.py for isolated unittesting of the SourceScanner. https://bugzilla.gnome.org/show_bug.cgi?id=581525 --- giscanner/giscannermodule.c | 2 ++ giscanner/sourcescanner.c | 18 ++++++++++++++-- tests/scanner/Makefile.am | 6 +++++- tests/scanner/test_sourcescanner.py | 41 +++++++++++++++++++++++++++++++++++++ 4 files changed, 64 insertions(+), 3 deletions(-) create mode 100644 tests/scanner/test_sourcescanner.py diff --git a/giscanner/giscannermodule.c b/giscanner/giscannermodule.c index 925b3e0a..b9512275 100644 --- a/giscanner/giscannermodule.c +++ b/giscanner/giscannermodule.c @@ -575,6 +575,7 @@ pygi_source_scanner_get_symbols (PyGISourceScanner *self) PyList_SetItem (list, i++, item); } + g_slist_free (symbols); Py_INCREF (list); return list; } @@ -598,6 +599,7 @@ pygi_source_scanner_get_comments (PyGISourceScanner *self) PyList_SetItem (list, i++, item); } + g_slist_free (comments); Py_INCREF (list); return list; } diff --git a/giscanner/sourcescanner.c b/giscanner/sourcescanner.c index 070397b4..7de891f5 100644 --- a/giscanner/sourcescanner.c +++ b/giscanner/sourcescanner.c @@ -309,14 +309,28 @@ gi_source_scanner_take_comment (GISourceScanner *scanner, comment); } +/** + * gi_source_scanner_get_symbols: + * @scanner: scanner instance + * + * Returns: (transfer container): List of GISourceSymbol. + * Free resulting list with g_slist_free(). + */ GSList * gi_source_scanner_get_symbols (GISourceScanner *scanner) { - return g_slist_reverse (scanner->symbols); + return g_slist_reverse (g_slist_copy (scanner->symbols)); } +/** + * gi_source_scanner_get_comments: + * @scanner: scanner instance + * + * Returns: (transfer container): List of GISourceComment. + * Free resulting list with g_slist_free(). + */ GSList * gi_source_scanner_get_comments(GISourceScanner *scanner) { - return g_slist_reverse (scanner->comments); + return g_slist_reverse (g_slist_copy (scanner->comments)); } diff --git a/tests/scanner/Makefile.am b/tests/scanner/Makefile.am index d72d2557..e3fd4321 100644 --- a/tests/scanner/Makefile.am +++ b/tests/scanner/Makefile.am @@ -192,12 +192,16 @@ else CHECKDOCS = endif +PYTESTS = test_sourcescanner.py + XFAIL_TESTS = Typedefs-1.0.gir -TESTS = Headeronly-1.0.gir $(CHECKGIRS) $(CHECKDOCS) $(TYPELIBS) +TESTS = Headeronly-1.0.gir $(CHECKGIRS) $(CHECKDOCS) $(TYPELIBS) $(PYTESTS) TESTS_ENVIRONMENT = srcdir=$(srcdir) top_srcdir=$(top_srcdir) builddir=$(builddir) top_builddir=$(top_builddir) \ + PYTHON=$(PYTHON) UNINSTALLED_INTROSPECTION_SRCDIR=$(top_srcdir) \ $(top_srcdir)/tests/gi-tester EXTRA_DIST += \ + $(PYTESTS) \ Regress-1.0-C-expected \ Regress-1.0-Gjs-expected \ Regress-1.0-Python-expected \ diff --git a/tests/scanner/test_sourcescanner.py b/tests/scanner/test_sourcescanner.py new file mode 100644 index 00000000..3963683d --- /dev/null +++ b/tests/scanner/test_sourcescanner.py @@ -0,0 +1,41 @@ +import unittest +import tempfile +import os + +from giscanner.sourcescanner import SourceScanner + + +two_typedefs_source = """ +/** + * Spam: + */ +typedef struct _spam Spam; + +/** + * Eggs: + */ +typedef struct _eggs Eggs; +""" + + +class Test(unittest.TestCase): + def setUp(self): + self.ss = SourceScanner() + tmp_fd, tmp_name = tempfile.mkstemp() + file = os.fdopen(tmp_fd, 'wt') + file.write(two_typedefs_source) + file.close() + + self.ss.parse_files([tmp_name]) + + def test_get_symbols_length_consistency(self): + self.assertEqual(len(list(self.ss.get_symbols())), 2) + self.assertEqual(len(list(self.ss.get_symbols())), 2) + + def test_get_comments_length_consistency(self): + self.assertEqual(len(list(self.ss.get_comments())), 2) + self.assertEqual(len(list(self.ss.get_comments())), 2) + + +if __name__ == '__main__': + unittest.main() -- cgit v1.2.1