Index: cfe/trunk/bindings/python/README.txt =================================================================== --- cfe/trunk/bindings/python/README.txt +++ cfe/trunk/bindings/python/README.txt @@ -5,11 +5,12 @@ This directory implements Python bindings for Clang. You may need to alter LD_LIBRARY_PATH so that the Clang library can be -found. The unit tests are designed to be run with 'nosetests'. For example: +found. The unit tests are designed to be run with any standard test +runner. For example: -- $ env PYTHONPATH=$(echo ~/llvm/tools/clang/bindings/python/) \ LD_LIBRARY_PATH=$(llvm-config --libdir) \ - nosetests -v + python -m unittest discover -v tests.cindex.test_index.test_create ... ok ... Index: cfe/trunk/bindings/python/tests/cindex/test_access_specifiers.py =================================================================== --- cfe/trunk/bindings/python/tests/cindex/test_access_specifiers.py +++ cfe/trunk/bindings/python/tests/cindex/test_access_specifiers.py @@ -6,10 +6,14 @@ from .util import get_cursor from .util import get_tu -def test_access_specifiers(): - """Ensure that C++ access specifiers are available on cursors""" +import unittest - tu = get_tu(""" + +class TestAccessSpecifiers(unittest.TestCase): + def test_access_specifiers(self): + """Ensure that C++ access specifiers are available on cursors""" + + tu = get_tu(""" class test_class { public: void public_member_function(); @@ -20,15 +24,14 @@ }; """, lang = 'cpp') - test_class = get_cursor(tu, "test_class") - assert test_class.access_specifier == AccessSpecifier.INVALID; - - public = get_cursor(tu.cursor, "public_member_function") - assert public.access_specifier == AccessSpecifier.PUBLIC + test_class = get_cursor(tu, "test_class") + self.assertEqual(test_class.access_specifier, AccessSpecifier.INVALID) - protected = get_cursor(tu.cursor, "protected_member_function") - assert protected.access_specifier == AccessSpecifier.PROTECTED + public = get_cursor(tu.cursor, "public_member_function") + self.assertEqual(public.access_specifier, AccessSpecifier.PUBLIC) - private = get_cursor(tu.cursor, "private_member_function") - assert private.access_specifier == AccessSpecifier.PRIVATE + protected = get_cursor(tu.cursor, "protected_member_function") + self.assertEqual(protected.access_specifier, AccessSpecifier.PROTECTED) + private = get_cursor(tu.cursor, "private_member_function") + self.assertEqual(private.access_specifier, AccessSpecifier.PRIVATE) Index: cfe/trunk/bindings/python/tests/cindex/test_cdb.py =================================================================== --- cfe/trunk/bindings/python/tests/cindex/test_cdb.py +++ cfe/trunk/bindings/python/tests/cindex/test_cdb.py @@ -4,114 +4,116 @@ from clang.cindex import CompileCommand import os import gc +import unittest + kInputsDir = os.path.join(os.path.dirname(__file__), 'INPUTS') -def test_create_fail(): - """Check we fail loading a database with an assertion""" - path = os.path.dirname(__file__) - try: - cdb = CompilationDatabase.fromDirectory(path) - except CompilationDatabaseError as e: - assert e.cdb_error == CompilationDatabaseError.ERROR_CANNOTLOADDATABASE - else: - assert False - -def test_create(): - """Check we can load a compilation database""" - cdb = CompilationDatabase.fromDirectory(kInputsDir) - -def test_lookup_fail(): - """Check file lookup failure""" - cdb = CompilationDatabase.fromDirectory(kInputsDir) - assert cdb.getCompileCommands('file_do_not_exist.cpp') == None - -def test_lookup_succeed(): - """Check we get some results if the file exists in the db""" - cdb = CompilationDatabase.fromDirectory(kInputsDir) - cmds = cdb.getCompileCommands('/home/john.doe/MyProject/project.cpp') - assert len(cmds) != 0 - -def test_all_compilecommand(): - """Check we get all results from the db""" - cdb = CompilationDatabase.fromDirectory(kInputsDir) - cmds = cdb.getAllCompileCommands() - assert len(cmds) == 3 - expected = [ - { 'wd': '/home/john.doe/MyProject', - 'file': '/home/john.doe/MyProject/project.cpp', - 'line': ['clang++', '-o', 'project.o', '-c', - '/home/john.doe/MyProject/project.cpp']}, - { 'wd': '/home/john.doe/MyProjectA', - 'file': '/home/john.doe/MyProject/project2.cpp', - 'line': ['clang++', '-o', 'project2.o', '-c', - '/home/john.doe/MyProject/project2.cpp']}, - { 'wd': '/home/john.doe/MyProjectB', - 'file': '/home/john.doe/MyProject/project2.cpp', - 'line': ['clang++', '-DFEATURE=1', '-o', 'project2-feature.o', '-c', - '/home/john.doe/MyProject/project2.cpp']}, - - ] - for i in range(len(cmds)): - assert cmds[i].directory == expected[i]['wd'] - assert cmds[i].filename == expected[i]['file'] - for arg, exp in zip(cmds[i].arguments, expected[i]['line']): - assert arg == exp - -def test_1_compilecommand(): - """Check file with single compile command""" - cdb = CompilationDatabase.fromDirectory(kInputsDir) - file = '/home/john.doe/MyProject/project.cpp' - cmds = cdb.getCompileCommands(file) - assert len(cmds) == 1 - assert cmds[0].directory == os.path.dirname(file) - assert cmds[0].filename == file - expected = [ 'clang++', '-o', 'project.o', '-c', - '/home/john.doe/MyProject/project.cpp'] - for arg, exp in zip(cmds[0].arguments, expected): - assert arg == exp - -def test_2_compilecommand(): - """Check file with 2 compile commands""" - cdb = CompilationDatabase.fromDirectory(kInputsDir) - cmds = cdb.getCompileCommands('/home/john.doe/MyProject/project2.cpp') - assert len(cmds) == 2 - expected = [ - { 'wd': '/home/john.doe/MyProjectA', - 'line': ['clang++', '-o', 'project2.o', '-c', - '/home/john.doe/MyProject/project2.cpp']}, - { 'wd': '/home/john.doe/MyProjectB', - 'line': ['clang++', '-DFEATURE=1', '-o', 'project2-feature.o', '-c', - '/home/john.doe/MyProject/project2.cpp']} - ] - for i in range(len(cmds)): - assert cmds[i].directory == expected[i]['wd'] - for arg, exp in zip(cmds[i].arguments, expected[i]['line']): - assert arg == exp - -def test_compilecommand_iterator_stops(): - """Check that iterator stops after the correct number of elements""" - cdb = CompilationDatabase.fromDirectory(kInputsDir) - count = 0 - for cmd in cdb.getCompileCommands('/home/john.doe/MyProject/project2.cpp'): - count += 1 - assert count <= 2 - -def test_compilationDB_references(): - """Ensure CompilationsCommands are independent of the database""" - cdb = CompilationDatabase.fromDirectory(kInputsDir) - cmds = cdb.getCompileCommands('/home/john.doe/MyProject/project.cpp') - del cdb - gc.collect() - workingdir = cmds[0].directory - -def test_compilationCommands_references(): - """Ensure CompilationsCommand keeps a reference to CompilationCommands""" - cdb = CompilationDatabase.fromDirectory(kInputsDir) - cmds = cdb.getCompileCommands('/home/john.doe/MyProject/project.cpp') - del cdb - cmd0 = cmds[0] - del cmds - gc.collect() - workingdir = cmd0.directory +class TestCDB(unittest.TestCase): + def test_create_fail(self): + """Check we fail loading a database with an assertion""" + path = os.path.dirname(__file__) + with self.assertRaises(CompilationDatabaseError) as cm: + cdb = CompilationDatabase.fromDirectory(path) + e = cm.exception + self.assertEqual(e.cdb_error, + CompilationDatabaseError.ERROR_CANNOTLOADDATABASE) + + def test_create(self): + """Check we can load a compilation database""" + cdb = CompilationDatabase.fromDirectory(kInputsDir) + + def test_lookup_fail(self): + """Check file lookup failure""" + cdb = CompilationDatabase.fromDirectory(kInputsDir) + self.assertIsNone(cdb.getCompileCommands('file_do_not_exist.cpp')) + + def test_lookup_succeed(self): + """Check we get some results if the file exists in the db""" + cdb = CompilationDatabase.fromDirectory(kInputsDir) + cmds = cdb.getCompileCommands('/home/john.doe/MyProject/project.cpp') + self.assertNotEqual(len(cmds), 0) + + def test_all_compilecommand(self): + """Check we get all results from the db""" + cdb = CompilationDatabase.fromDirectory(kInputsDir) + cmds = cdb.getAllCompileCommands() + self.assertEqual(len(cmds), 3) + expected = [ + { 'wd': '/home/john.doe/MyProject', + 'file': '/home/john.doe/MyProject/project.cpp', + 'line': ['clang++', '-o', 'project.o', '-c', + '/home/john.doe/MyProject/project.cpp']}, + { 'wd': '/home/john.doe/MyProjectA', + 'file': '/home/john.doe/MyProject/project2.cpp', + 'line': ['clang++', '-o', 'project2.o', '-c', + '/home/john.doe/MyProject/project2.cpp']}, + { 'wd': '/home/john.doe/MyProjectB', + 'file': '/home/john.doe/MyProject/project2.cpp', + 'line': ['clang++', '-DFEATURE=1', '-o', 'project2-feature.o', '-c', + '/home/john.doe/MyProject/project2.cpp']}, + + ] + for i in range(len(cmds)): + self.assertEqual(cmds[i].directory, expected[i]['wd']) + self.assertEqual(cmds[i].filename, expected[i]['file']) + for arg, exp in zip(cmds[i].arguments, expected[i]['line']): + self.assertEqual(arg, exp) + + def test_1_compilecommand(self): + """Check file with single compile command""" + cdb = CompilationDatabase.fromDirectory(kInputsDir) + file = '/home/john.doe/MyProject/project.cpp' + cmds = cdb.getCompileCommands(file) + self.assertEqual(len(cmds), 1) + self.assertEqual(cmds[0].directory, os.path.dirname(file)) + self.assertEqual(cmds[0].filename, file) + expected = [ 'clang++', '-o', 'project.o', '-c', + '/home/john.doe/MyProject/project.cpp'] + for arg, exp in zip(cmds[0].arguments, expected): + self.assertEqual(arg, exp) + + def test_2_compilecommand(self): + """Check file with 2 compile commands""" + cdb = CompilationDatabase.fromDirectory(kInputsDir) + cmds = cdb.getCompileCommands('/home/john.doe/MyProject/project2.cpp') + self.assertEqual(len(cmds), 2) + expected = [ + { 'wd': '/home/john.doe/MyProjectA', + 'line': ['clang++', '-o', 'project2.o', '-c', + '/home/john.doe/MyProject/project2.cpp']}, + { 'wd': '/home/john.doe/MyProjectB', + 'line': ['clang++', '-DFEATURE=1', '-o', 'project2-feature.o', '-c', + '/home/john.doe/MyProject/project2.cpp']} + ] + for i in range(len(cmds)): + self.assertEqual(cmds[i].directory, expected[i]['wd']) + for arg, exp in zip(cmds[i].arguments, expected[i]['line']): + self.assertEqual(arg, exp) + + def test_compilecommand_iterator_stops(self): + """Check that iterator stops after the correct number of elements""" + cdb = CompilationDatabase.fromDirectory(kInputsDir) + count = 0 + for cmd in cdb.getCompileCommands('/home/john.doe/MyProject/project2.cpp'): + count += 1 + self.assertLessEqual(count, 2) + + def test_compilationDB_references(self): + """Ensure CompilationsCommands are independent of the database""" + cdb = CompilationDatabase.fromDirectory(kInputsDir) + cmds = cdb.getCompileCommands('/home/john.doe/MyProject/project.cpp') + del cdb + gc.collect() + workingdir = cmds[0].directory + + def test_compilationCommands_references(self): + """Ensure CompilationsCommand keeps a reference to CompilationCommands""" + cdb = CompilationDatabase.fromDirectory(kInputsDir) + cmds = cdb.getCompileCommands('/home/john.doe/MyProject/project.cpp') + del cdb + cmd0 = cmds[0] + del cmds + gc.collect() + workingdir = cmd0.directory Index: cfe/trunk/bindings/python/tests/cindex/test_code_completion.py =================================================================== --- cfe/trunk/bindings/python/tests/cindex/test_code_completion.py +++ cfe/trunk/bindings/python/tests/cindex/test_code_completion.py @@ -1,16 +1,20 @@ from clang.cindex import TranslationUnit -def check_completion_results(cr, expected): - assert cr is not None - assert len(cr.diagnostics) == 0 +import unittest - completions = [str(c) for c in cr.results] - for c in expected: - assert c in completions +class TestCodeCompletion(unittest.TestCase): + def check_completion_results(self, cr, expected): + self.assertIsNotNone(cr) + self.assertEqual(len(cr.diagnostics), 0) -def test_code_complete(): - files = [('fake.c', """ + completions = [str(c) for c in cr.results] + + for c in expected: + self.assertIn(c, completions) + + def test_code_complete(self): + files = [('fake.c', """ /// Aaa. int test1; @@ -22,20 +26,20 @@ } """)] - tu = TranslationUnit.from_source('fake.c', ['-std=c99'], unsaved_files=files, - options=TranslationUnit.PARSE_INCLUDE_BRIEF_COMMENTS_IN_CODE_COMPLETION) + tu = TranslationUnit.from_source('fake.c', ['-std=c99'], unsaved_files=files, + options=TranslationUnit.PARSE_INCLUDE_BRIEF_COMMENTS_IN_CODE_COMPLETION) - cr = tu.codeComplete('fake.c', 9, 1, unsaved_files=files, include_brief_comments=True) + cr = tu.codeComplete('fake.c', 9, 1, unsaved_files=files, include_brief_comments=True) - expected = [ - "{'int', ResultType} | {'test1', TypedText} || Priority: 50 || Availability: Available || Brief comment: Aaa.", - "{'void', ResultType} | {'test2', TypedText} | {'(', LeftParen} | {')', RightParen} || Priority: 50 || Availability: Available || Brief comment: Bbb.", - "{'return', TypedText} || Priority: 40 || Availability: Available || Brief comment: None" - ] - check_completion_results(cr, expected) + expected = [ + "{'int', ResultType} | {'test1', TypedText} || Priority: 50 || Availability: Available || Brief comment: Aaa.", + "{'void', ResultType} | {'test2', TypedText} | {'(', LeftParen} | {')', RightParen} || Priority: 50 || Availability: Available || Brief comment: Bbb.", + "{'return', TypedText} || Priority: 40 || Availability: Available || Brief comment: None" + ] + self.check_completion_results(cr, expected) -def test_code_complete_availability(): - files = [('fake.cpp', """ + def test_code_complete_availability(self): + files = [('fake.cpp', """ class P { protected: int member; @@ -52,24 +56,24 @@ } """)] - tu = TranslationUnit.from_source('fake.cpp', ['-std=c++98'], unsaved_files=files) + tu = TranslationUnit.from_source('fake.cpp', ['-std=c++98'], unsaved_files=files) - cr = tu.codeComplete('fake.cpp', 12, 5, unsaved_files=files) + cr = tu.codeComplete('fake.cpp', 12, 5, unsaved_files=files) - expected = [ - "{'const', TypedText} || Priority: 40 || Availability: Available || Brief comment: None", - "{'volatile', TypedText} || Priority: 40 || Availability: Available || Brief comment: None", - "{'operator', TypedText} || Priority: 40 || Availability: Available || Brief comment: None", - "{'P', TypedText} | {'::', Text} || Priority: 75 || Availability: Available || Brief comment: None", - "{'Q', TypedText} | {'::', Text} || Priority: 75 || Availability: Available || Brief comment: None" - ] - check_completion_results(cr, expected) - - cr = tu.codeComplete('fake.cpp', 13, 5, unsaved_files=files) - expected = [ - "{'P', TypedText} | {'::', Text} || Priority: 75 || Availability: Available || Brief comment: None", - "{'P &', ResultType} | {'operator=', TypedText} | {'(', LeftParen} | {'const P &', Placeholder} | {')', RightParen} || Priority: 79 || Availability: Available || Brief comment: None", - "{'int', ResultType} | {'member', TypedText} || Priority: 35 || Availability: NotAccessible || Brief comment: None", - "{'void', ResultType} | {'~P', TypedText} | {'(', LeftParen} | {')', RightParen} || Priority: 79 || Availability: Available || Brief comment: None" - ] - check_completion_results(cr, expected) + expected = [ + "{'const', TypedText} || Priority: 40 || Availability: Available || Brief comment: None", + "{'volatile', TypedText} || Priority: 40 || Availability: Available || Brief comment: None", + "{'operator', TypedText} || Priority: 40 || Availability: Available || Brief comment: None", + "{'P', TypedText} | {'::', Text} || Priority: 75 || Availability: Available || Brief comment: None", + "{'Q', TypedText} | {'::', Text} || Priority: 75 || Availability: Available || Brief comment: None" + ] + self.check_completion_results(cr, expected) + + cr = tu.codeComplete('fake.cpp', 13, 5, unsaved_files=files) + expected = [ + "{'P', TypedText} | {'::', Text} || Priority: 75 || Availability: Available || Brief comment: None", + "{'P &', ResultType} | {'operator=', TypedText} | {'(', LeftParen} | {'const P &', Placeholder} | {')', RightParen} || Priority: 79 || Availability: Available || Brief comment: None", + "{'int', ResultType} | {'member', TypedText} || Priority: 35 || Availability: NotAccessible || Brief comment: None", + "{'void', ResultType} | {'~P', TypedText} | {'(', LeftParen} | {')', RightParen} || Priority: 79 || Availability: Available || Brief comment: None" + ] + self.check_completion_results(cr, expected) Index: cfe/trunk/bindings/python/tests/cindex/test_comment.py =================================================================== --- cfe/trunk/bindings/python/tests/cindex/test_comment.py +++ cfe/trunk/bindings/python/tests/cindex/test_comment.py @@ -1,8 +1,12 @@ from clang.cindex import TranslationUnit from tests.cindex.util import get_cursor -def test_comment(): - files = [('fake.c', """ +import unittest + + +class TestComment(unittest.TestCase): + def test_comment(self): + files = [('fake.c', """ /// Aaa. int test1; @@ -14,27 +18,25 @@ } """)] - # make a comment-aware TU - tu = TranslationUnit.from_source('fake.c', ['-std=c99'], unsaved_files=files, - options=TranslationUnit.PARSE_INCLUDE_BRIEF_COMMENTS_IN_CODE_COMPLETION) - test1 = get_cursor(tu, 'test1') - assert test1 is not None, "Could not find test1." - assert test1.type.is_pod() - raw = test1.raw_comment - brief = test1.brief_comment - assert raw == """/// Aaa.""" - assert brief == """Aaa.""" - - test2 = get_cursor(tu, 'test2') - raw = test2.raw_comment - brief = test2.brief_comment - assert raw == """/// Bbb.\n/// x""" - assert brief == """Bbb. x""" - - f = get_cursor(tu, 'f') - raw = f.raw_comment - brief = f.brief_comment - assert raw is None - assert brief is None - - + # make a comment-aware TU + tu = TranslationUnit.from_source('fake.c', ['-std=c99'], unsaved_files=files, + options=TranslationUnit.PARSE_INCLUDE_BRIEF_COMMENTS_IN_CODE_COMPLETION) + test1 = get_cursor(tu, 'test1') + self.assertIsNotNone(test1, "Could not find test1.") + self.assertTrue(test1.type.is_pod()) + raw = test1.raw_comment + brief = test1.brief_comment + self.assertEqual(raw, """/// Aaa.""") + self.assertEqual(brief, """Aaa.""") + + test2 = get_cursor(tu, 'test2') + raw = test2.raw_comment + brief = test2.brief_comment + self.assertEqual(raw, """/// Bbb.\n/// x""") + self.assertEqual(brief, """Bbb. x""") + + f = get_cursor(tu, 'f') + raw = f.raw_comment + brief = f.brief_comment + self.assertIsNone(raw) + self.assertIsNone(brief) Index: cfe/trunk/bindings/python/tests/cindex/test_cursor.py =================================================================== --- cfe/trunk/bindings/python/tests/cindex/test_cursor.py +++ cfe/trunk/bindings/python/tests/cindex/test_cursor.py @@ -1,5 +1,6 @@ import ctypes import gc +import unittest from clang.cindex import AvailabilityKind from clang.cindex import CursorKind @@ -10,6 +11,7 @@ from .util import get_cursors from .util import get_tu + kInput = """\ struct s0 { int a; @@ -30,257 +32,6 @@ } """ -def test_get_children(): - tu = get_tu(kInput) - - it = tu.cursor.get_children() - tu_nodes = list(it) - - assert len(tu_nodes) == 3 - for cursor in tu_nodes: - assert cursor.translation_unit is not None - - assert tu_nodes[0] != tu_nodes[1] - assert tu_nodes[0].kind == CursorKind.STRUCT_DECL - assert tu_nodes[0].spelling == 's0' - assert tu_nodes[0].is_definition() == True - assert tu_nodes[0].location.file.name == 't.c' - assert tu_nodes[0].location.line == 1 - assert tu_nodes[0].location.column == 8 - assert tu_nodes[0].hash > 0 - assert tu_nodes[0].translation_unit is not None - - s0_nodes = list(tu_nodes[0].get_children()) - assert len(s0_nodes) == 2 - assert s0_nodes[0].kind == CursorKind.FIELD_DECL - assert s0_nodes[0].spelling == 'a' - assert s0_nodes[0].type.kind == TypeKind.INT - assert s0_nodes[1].kind == CursorKind.FIELD_DECL - assert s0_nodes[1].spelling == 'b' - assert s0_nodes[1].type.kind == TypeKind.INT - - assert tu_nodes[1].kind == CursorKind.STRUCT_DECL - assert tu_nodes[1].spelling == 's1' - assert tu_nodes[1].displayname == 's1' - assert tu_nodes[1].is_definition() == False - - assert tu_nodes[2].kind == CursorKind.FUNCTION_DECL - assert tu_nodes[2].spelling == 'f0' - assert tu_nodes[2].displayname == 'f0(int, int)' - assert tu_nodes[2].is_definition() == True - -def test_references(): - """Ensure that references to TranslationUnit are kept.""" - tu = get_tu('int x;') - cursors = list(tu.cursor.get_children()) - assert len(cursors) > 0 - - cursor = cursors[0] - assert isinstance(cursor.translation_unit, TranslationUnit) - - # Delete reference to TU and perform a full GC. - del tu - gc.collect() - assert isinstance(cursor.translation_unit, TranslationUnit) - - # If the TU was destroyed, this should cause a segfault. - parent = cursor.semantic_parent - -def test_canonical(): - source = 'struct X; struct X; struct X { int member; };' - tu = get_tu(source) - - cursors = [] - for cursor in tu.cursor.get_children(): - if cursor.spelling == 'X': - cursors.append(cursor) - - assert len(cursors) == 3 - assert cursors[1].canonical == cursors[2].canonical - -def test_is_const_method(): - """Ensure Cursor.is_const_method works.""" - source = 'class X { void foo() const; void bar(); };' - tu = get_tu(source, lang='cpp') - - cls = get_cursor(tu, 'X') - foo = get_cursor(tu, 'foo') - bar = get_cursor(tu, 'bar') - assert cls is not None - assert foo is not None - assert bar is not None - - assert foo.is_const_method() - assert not bar.is_const_method() - -def test_is_converting_constructor(): - """Ensure Cursor.is_converting_constructor works.""" - source = 'class X { explicit X(int); X(double); X(); };' - tu = get_tu(source, lang='cpp') - - xs = get_cursors(tu, 'X') - - assert len(xs) == 4 - assert xs[0].kind == CursorKind.CLASS_DECL - cs = xs[1:] - assert cs[0].kind == CursorKind.CONSTRUCTOR - assert cs[1].kind == CursorKind.CONSTRUCTOR - assert cs[2].kind == CursorKind.CONSTRUCTOR - - assert not cs[0].is_converting_constructor() - assert cs[1].is_converting_constructor() - assert not cs[2].is_converting_constructor() - - -def test_is_copy_constructor(): - """Ensure Cursor.is_copy_constructor works.""" - source = 'class X { X(); X(const X&); X(X&&); };' - tu = get_tu(source, lang='cpp') - - xs = get_cursors(tu, 'X') - assert xs[0].kind == CursorKind.CLASS_DECL - cs = xs[1:] - assert cs[0].kind == CursorKind.CONSTRUCTOR - assert cs[1].kind == CursorKind.CONSTRUCTOR - assert cs[2].kind == CursorKind.CONSTRUCTOR - - assert not cs[0].is_copy_constructor() - assert cs[1].is_copy_constructor() - assert not cs[2].is_copy_constructor() - -def test_is_default_constructor(): - """Ensure Cursor.is_default_constructor works.""" - source = 'class X { X(); X(int); };' - tu = get_tu(source, lang='cpp') - - xs = get_cursors(tu, 'X') - assert xs[0].kind == CursorKind.CLASS_DECL - cs = xs[1:] - assert cs[0].kind == CursorKind.CONSTRUCTOR - assert cs[1].kind == CursorKind.CONSTRUCTOR - - assert cs[0].is_default_constructor() - assert not cs[1].is_default_constructor() - -def test_is_move_constructor(): - """Ensure Cursor.is_move_constructor works.""" - source = 'class X { X(); X(const X&); X(X&&); };' - tu = get_tu(source, lang='cpp') - - xs = get_cursors(tu, 'X') - assert xs[0].kind == CursorKind.CLASS_DECL - cs = xs[1:] - assert cs[0].kind == CursorKind.CONSTRUCTOR - assert cs[1].kind == CursorKind.CONSTRUCTOR - assert cs[2].kind == CursorKind.CONSTRUCTOR - - assert not cs[0].is_move_constructor() - assert not cs[1].is_move_constructor() - assert cs[2].is_move_constructor() - -def test_is_default_method(): - """Ensure Cursor.is_default_method works.""" - source = 'class X { X() = default; }; class Y { Y(); };' - tu = get_tu(source, lang='cpp') - - xs = get_cursors(tu, 'X') - ys = get_cursors(tu, 'Y') - - assert len(xs) == 2 - assert len(ys) == 2 - - xc = xs[1] - yc = ys[1] - - assert xc.is_default_method() - assert not yc.is_default_method() - -def test_is_mutable_field(): - """Ensure Cursor.is_mutable_field works.""" - source = 'class X { int x_; mutable int y_; };' - tu = get_tu(source, lang='cpp') - - cls = get_cursor(tu, 'X') - x_ = get_cursor(tu, 'x_') - y_ = get_cursor(tu, 'y_') - assert cls is not None - assert x_ is not None - assert y_ is not None - - assert not x_.is_mutable_field() - assert y_.is_mutable_field() - -def test_is_static_method(): - """Ensure Cursor.is_static_method works.""" - - source = 'class X { static void foo(); void bar(); };' - tu = get_tu(source, lang='cpp') - - cls = get_cursor(tu, 'X') - foo = get_cursor(tu, 'foo') - bar = get_cursor(tu, 'bar') - assert cls is not None - assert foo is not None - assert bar is not None - - assert foo.is_static_method() - assert not bar.is_static_method() - -def test_is_pure_virtual_method(): - """Ensure Cursor.is_pure_virtual_method works.""" - source = 'class X { virtual void foo() = 0; virtual void bar(); };' - tu = get_tu(source, lang='cpp') - - cls = get_cursor(tu, 'X') - foo = get_cursor(tu, 'foo') - bar = get_cursor(tu, 'bar') - assert cls is not None - assert foo is not None - assert bar is not None - - assert foo.is_pure_virtual_method() - assert not bar.is_pure_virtual_method() - -def test_is_virtual_method(): - """Ensure Cursor.is_virtual_method works.""" - source = 'class X { virtual void foo(); void bar(); };' - tu = get_tu(source, lang='cpp') - - cls = get_cursor(tu, 'X') - foo = get_cursor(tu, 'foo') - bar = get_cursor(tu, 'bar') - assert cls is not None - assert foo is not None - assert bar is not None - - assert foo.is_virtual_method() - assert not bar.is_virtual_method() - -def test_is_scoped_enum(): - """Ensure Cursor.is_scoped_enum works.""" - source = 'class X {}; enum RegularEnum {}; enum class ScopedEnum {};' - tu = get_tu(source, lang='cpp') - - cls = get_cursor(tu, 'X') - regular_enum = get_cursor(tu, 'RegularEnum') - scoped_enum = get_cursor(tu, 'ScopedEnum') - assert cls is not None - assert regular_enum is not None - assert scoped_enum is not None - - assert not cls.is_scoped_enum() - assert not regular_enum.is_scoped_enum() - assert scoped_enum.is_scoped_enum() - -def test_underlying_type(): - tu = get_tu('typedef int foo;') - typedef = get_cursor(tu, 'foo') - assert typedef is not None - - assert typedef.kind.is_declaration() - underlying = typedef.underlying_typedef_type - assert underlying.kind == TypeKind.INT - kParentTest = """\ class C { void f(); @@ -288,250 +39,503 @@ void C::f() { } """ -def test_semantic_parent(): - tu = get_tu(kParentTest, 'cpp') - curs = get_cursors(tu, 'f') - decl = get_cursor(tu, 'C') - assert(len(curs) == 2) - assert(curs[0].semantic_parent == curs[1].semantic_parent) - assert(curs[0].semantic_parent == decl) - -def test_lexical_parent(): - tu = get_tu(kParentTest, 'cpp') - curs = get_cursors(tu, 'f') - decl = get_cursor(tu, 'C') - assert(len(curs) == 2) - assert(curs[0].lexical_parent != curs[1].lexical_parent) - assert(curs[0].lexical_parent == decl) - assert(curs[1].lexical_parent == tu.cursor) - -def test_enum_type(): - tu = get_tu('enum TEST { FOO=1, BAR=2 };') - enum = get_cursor(tu, 'TEST') - assert enum is not None - - assert enum.kind == CursorKind.ENUM_DECL - enum_type = enum.enum_type - assert enum_type.kind == TypeKind.UINT - -def test_enum_type_cpp(): - tu = get_tu('enum TEST : long long { FOO=1, BAR=2 };', lang="cpp") - enum = get_cursor(tu, 'TEST') - assert enum is not None - - assert enum.kind == CursorKind.ENUM_DECL - assert enum.enum_type.kind == TypeKind.LONGLONG - -def test_objc_type_encoding(): - tu = get_tu('int i;', lang='objc') - i = get_cursor(tu, 'i') - - assert i is not None - assert i.objc_type_encoding == 'i' - -def test_enum_values(): - tu = get_tu('enum TEST { SPAM=1, EGG, HAM = EGG * 20};') - enum = get_cursor(tu, 'TEST') - assert enum is not None - - assert enum.kind == CursorKind.ENUM_DECL - - enum_constants = list(enum.get_children()) - assert len(enum_constants) == 3 - - spam, egg, ham = enum_constants - - assert spam.kind == CursorKind.ENUM_CONSTANT_DECL - assert spam.enum_value == 1 - assert egg.kind == CursorKind.ENUM_CONSTANT_DECL - assert egg.enum_value == 2 - assert ham.kind == CursorKind.ENUM_CONSTANT_DECL - assert ham.enum_value == 40 - -def test_enum_values_cpp(): - tu = get_tu('enum TEST : long long { SPAM = -1, HAM = 0x10000000000};', lang="cpp") - enum = get_cursor(tu, 'TEST') - assert enum is not None - - assert enum.kind == CursorKind.ENUM_DECL - - enum_constants = list(enum.get_children()) - assert len(enum_constants) == 2 - - spam, ham = enum_constants - - assert spam.kind == CursorKind.ENUM_CONSTANT_DECL - assert spam.enum_value == -1 - assert ham.kind == CursorKind.ENUM_CONSTANT_DECL - assert ham.enum_value == 0x10000000000 - -def test_annotation_attribute(): - tu = get_tu('int foo (void) __attribute__ ((annotate("here be annotation attribute")));') - - foo = get_cursor(tu, 'foo') - assert foo is not None - - for c in foo.get_children(): - if c.kind == CursorKind.ANNOTATE_ATTR: - assert c.displayname == "here be annotation attribute" - break - else: - assert False, "Couldn't find annotation" - -def test_annotation_template(): - annotation = '__attribute__ ((annotate("annotation")))' - for source, kind in [ - ('int foo (T value) %s;', CursorKind.FUNCTION_TEMPLATE), - ('class %s foo {};', CursorKind.CLASS_TEMPLATE), - ]: - source = 'template ' + (source % annotation) - tu = get_tu(source, lang="cpp") +kTemplateArgTest = """\ + template + void foo(); + + template<> + void foo<-7, float, true>(); + """ + +class TestCursor(unittest.TestCase): + def test_get_children(self): + tu = get_tu(kInput) + + it = tu.cursor.get_children() + tu_nodes = list(it) + + self.assertEqual(len(tu_nodes), 3) + for cursor in tu_nodes: + self.assertIsNotNone(cursor.translation_unit) + + self.assertNotEqual(tu_nodes[0], tu_nodes[1]) + self.assertEqual(tu_nodes[0].kind, CursorKind.STRUCT_DECL) + self.assertEqual(tu_nodes[0].spelling, 's0') + self.assertEqual(tu_nodes[0].is_definition(), True) + self.assertEqual(tu_nodes[0].location.file.name, 't.c') + self.assertEqual(tu_nodes[0].location.line, 1) + self.assertEqual(tu_nodes[0].location.column, 8) + self.assertGreater(tu_nodes[0].hash, 0) + self.assertIsNotNone(tu_nodes[0].translation_unit) + + s0_nodes = list(tu_nodes[0].get_children()) + self.assertEqual(len(s0_nodes), 2) + self.assertEqual(s0_nodes[0].kind, CursorKind.FIELD_DECL) + self.assertEqual(s0_nodes[0].spelling, 'a') + self.assertEqual(s0_nodes[0].type.kind, TypeKind.INT) + self.assertEqual(s0_nodes[1].kind, CursorKind.FIELD_DECL) + self.assertEqual(s0_nodes[1].spelling, 'b') + self.assertEqual(s0_nodes[1].type.kind, TypeKind.INT) + + self.assertEqual(tu_nodes[1].kind, CursorKind.STRUCT_DECL) + self.assertEqual(tu_nodes[1].spelling, 's1') + self.assertEqual(tu_nodes[1].displayname, 's1') + self.assertEqual(tu_nodes[1].is_definition(), False) + + self.assertEqual(tu_nodes[2].kind, CursorKind.FUNCTION_DECL) + self.assertEqual(tu_nodes[2].spelling, 'f0') + self.assertEqual(tu_nodes[2].displayname, 'f0(int, int)') + self.assertEqual(tu_nodes[2].is_definition(), True) + + def test_references(self): + """Ensure that references to TranslationUnit are kept.""" + tu = get_tu('int x;') + cursors = list(tu.cursor.get_children()) + self.assertGreater(len(cursors), 0) + + cursor = cursors[0] + self.assertIsInstance(cursor.translation_unit, TranslationUnit) + + # Delete reference to TU and perform a full GC. + del tu + gc.collect() + self.assertIsInstance(cursor.translation_unit, TranslationUnit) + + # If the TU was destroyed, this should cause a segfault. + parent = cursor.semantic_parent + + def test_canonical(self): + source = 'struct X; struct X; struct X { int member; };' + tu = get_tu(source) + + cursors = [] + for cursor in tu.cursor.get_children(): + if cursor.spelling == 'X': + cursors.append(cursor) + + self.assertEqual(len(cursors), 3) + self.assertEqual(cursors[1].canonical, cursors[2].canonical) + + def test_is_const_method(self): + """Ensure Cursor.is_const_method works.""" + source = 'class X { void foo() const; void bar(); };' + tu = get_tu(source, lang='cpp') + + cls = get_cursor(tu, 'X') + foo = get_cursor(tu, 'foo') + bar = get_cursor(tu, 'bar') + self.assertIsNotNone(cls) + self.assertIsNotNone(foo) + self.assertIsNotNone(bar) + + self.assertTrue(foo.is_const_method()) + self.assertFalse(bar.is_const_method()) + + def test_is_converting_constructor(self): + """Ensure Cursor.is_converting_constructor works.""" + source = 'class X { explicit X(int); X(double); X(); };' + tu = get_tu(source, lang='cpp') + + xs = get_cursors(tu, 'X') + + self.assertEqual(len(xs), 4) + self.assertEqual(xs[0].kind, CursorKind.CLASS_DECL) + cs = xs[1:] + self.assertEqual(cs[0].kind, CursorKind.CONSTRUCTOR) + self.assertEqual(cs[1].kind, CursorKind.CONSTRUCTOR) + self.assertEqual(cs[2].kind, CursorKind.CONSTRUCTOR) + + self.assertFalse(cs[0].is_converting_constructor()) + self.assertTrue(cs[1].is_converting_constructor()) + self.assertFalse(cs[2].is_converting_constructor()) + + + def test_is_copy_constructor(self): + """Ensure Cursor.is_copy_constructor works.""" + source = 'class X { X(); X(const X&); X(X&&); };' + tu = get_tu(source, lang='cpp') + + xs = get_cursors(tu, 'X') + self.assertEqual(xs[0].kind, CursorKind.CLASS_DECL) + cs = xs[1:] + self.assertEqual(cs[0].kind, CursorKind.CONSTRUCTOR) + self.assertEqual(cs[1].kind, CursorKind.CONSTRUCTOR) + self.assertEqual(cs[2].kind, CursorKind.CONSTRUCTOR) + + self.assertFalse(cs[0].is_copy_constructor()) + self.assertTrue(cs[1].is_copy_constructor()) + self.assertFalse(cs[2].is_copy_constructor()) + + def test_is_default_constructor(self): + """Ensure Cursor.is_default_constructor works.""" + source = 'class X { X(); X(int); };' + tu = get_tu(source, lang='cpp') + + xs = get_cursors(tu, 'X') + self.assertEqual(xs[0].kind, CursorKind.CLASS_DECL) + cs = xs[1:] + self.assertEqual(cs[0].kind, CursorKind.CONSTRUCTOR) + self.assertEqual(cs[1].kind, CursorKind.CONSTRUCTOR) + + self.assertTrue(cs[0].is_default_constructor()) + self.assertFalse(cs[1].is_default_constructor()) + + def test_is_move_constructor(self): + """Ensure Cursor.is_move_constructor works.""" + source = 'class X { X(); X(const X&); X(X&&); };' + tu = get_tu(source, lang='cpp') + + xs = get_cursors(tu, 'X') + self.assertEqual(xs[0].kind, CursorKind.CLASS_DECL) + cs = xs[1:] + self.assertEqual(cs[0].kind, CursorKind.CONSTRUCTOR) + self.assertEqual(cs[1].kind, CursorKind.CONSTRUCTOR) + self.assertEqual(cs[2].kind, CursorKind.CONSTRUCTOR) + + self.assertFalse(cs[0].is_move_constructor()) + self.assertFalse(cs[1].is_move_constructor()) + self.assertTrue(cs[2].is_move_constructor()) + + def test_is_default_method(self): + """Ensure Cursor.is_default_method works.""" + source = 'class X { X() = default; }; class Y { Y(); };' + tu = get_tu(source, lang='cpp') + + xs = get_cursors(tu, 'X') + ys = get_cursors(tu, 'Y') + + self.assertEqual(len(xs), 2) + self.assertEqual(len(ys), 2) + + xc = xs[1] + yc = ys[1] + + self.assertTrue(xc.is_default_method()) + self.assertFalse(yc.is_default_method()) + + def test_is_mutable_field(self): + """Ensure Cursor.is_mutable_field works.""" + source = 'class X { int x_; mutable int y_; };' + tu = get_tu(source, lang='cpp') + + cls = get_cursor(tu, 'X') + x_ = get_cursor(tu, 'x_') + y_ = get_cursor(tu, 'y_') + self.assertIsNotNone(cls) + self.assertIsNotNone(x_) + self.assertIsNotNone(y_) + + self.assertFalse(x_.is_mutable_field()) + self.assertTrue(y_.is_mutable_field()) + + def test_is_static_method(self): + """Ensure Cursor.is_static_method works.""" + + source = 'class X { static void foo(); void bar(); };' + tu = get_tu(source, lang='cpp') + + cls = get_cursor(tu, 'X') + foo = get_cursor(tu, 'foo') + bar = get_cursor(tu, 'bar') + self.assertIsNotNone(cls) + self.assertIsNotNone(foo) + self.assertIsNotNone(bar) + + self.assertTrue(foo.is_static_method()) + self.assertFalse(bar.is_static_method()) + + def test_is_pure_virtual_method(self): + """Ensure Cursor.is_pure_virtual_method works.""" + source = 'class X { virtual void foo() = 0; virtual void bar(); };' + tu = get_tu(source, lang='cpp') + + cls = get_cursor(tu, 'X') foo = get_cursor(tu, 'foo') - assert foo is not None - assert foo.kind == kind + bar = get_cursor(tu, 'bar') + self.assertIsNotNone(cls) + self.assertIsNotNone(foo) + self.assertIsNotNone(bar) + + self.assertTrue(foo.is_pure_virtual_method()) + self.assertFalse(bar.is_pure_virtual_method()) + + def test_is_virtual_method(self): + """Ensure Cursor.is_virtual_method works.""" + source = 'class X { virtual void foo(); void bar(); };' + tu = get_tu(source, lang='cpp') + + cls = get_cursor(tu, 'X') + foo = get_cursor(tu, 'foo') + bar = get_cursor(tu, 'bar') + self.assertIsNotNone(cls) + self.assertIsNotNone(foo) + self.assertIsNotNone(bar) + + self.assertTrue(foo.is_virtual_method()) + self.assertFalse(bar.is_virtual_method()) + + def test_is_scoped_enum(self): + """Ensure Cursor.is_scoped_enum works.""" + source = 'class X {}; enum RegularEnum {}; enum class ScopedEnum {};' + tu = get_tu(source, lang='cpp') + + cls = get_cursor(tu, 'X') + regular_enum = get_cursor(tu, 'RegularEnum') + scoped_enum = get_cursor(tu, 'ScopedEnum') + self.assertIsNotNone(cls) + self.assertIsNotNone(regular_enum) + self.assertIsNotNone(scoped_enum) + + self.assertFalse(cls.is_scoped_enum()) + self.assertFalse(regular_enum.is_scoped_enum()) + self.assertTrue(scoped_enum.is_scoped_enum()) + + def test_underlying_type(self): + tu = get_tu('typedef int foo;') + typedef = get_cursor(tu, 'foo') + self.assertIsNotNone(typedef) + + self.assertTrue(typedef.kind.is_declaration()) + underlying = typedef.underlying_typedef_type + self.assertEqual(underlying.kind, TypeKind.INT) + + def test_semantic_parent(self): + tu = get_tu(kParentTest, 'cpp') + curs = get_cursors(tu, 'f') + decl = get_cursor(tu, 'C') + self.assertEqual(len(curs), 2) + self.assertEqual(curs[0].semantic_parent, curs[1].semantic_parent) + self.assertEqual(curs[0].semantic_parent, decl) + + def test_lexical_parent(self): + tu = get_tu(kParentTest, 'cpp') + curs = get_cursors(tu, 'f') + decl = get_cursor(tu, 'C') + self.assertEqual(len(curs), 2) + self.assertNotEqual(curs[0].lexical_parent, curs[1].lexical_parent) + self.assertEqual(curs[0].lexical_parent, decl) + self.assertEqual(curs[1].lexical_parent, tu.cursor) + + def test_enum_type(self): + tu = get_tu('enum TEST { FOO=1, BAR=2 };') + enum = get_cursor(tu, 'TEST') + self.assertIsNotNone(enum) + + self.assertEqual(enum.kind, CursorKind.ENUM_DECL) + enum_type = enum.enum_type + self.assertEqual(enum_type.kind, TypeKind.UINT) + + def test_enum_type_cpp(self): + tu = get_tu('enum TEST : long long { FOO=1, BAR=2 };', lang="cpp") + enum = get_cursor(tu, 'TEST') + self.assertIsNotNone(enum) + + self.assertEqual(enum.kind, CursorKind.ENUM_DECL) + self.assertEqual(enum.enum_type.kind, TypeKind.LONGLONG) + + def test_objc_type_encoding(self): + tu = get_tu('int i;', lang='objc') + i = get_cursor(tu, 'i') + + self.assertIsNotNone(i) + self.assertEqual(i.objc_type_encoding, 'i') + + def test_enum_values(self): + tu = get_tu('enum TEST { SPAM=1, EGG, HAM = EGG * 20};') + enum = get_cursor(tu, 'TEST') + self.assertIsNotNone(enum) + + self.assertEqual(enum.kind, CursorKind.ENUM_DECL) + + enum_constants = list(enum.get_children()) + self.assertEqual(len(enum_constants), 3) + + spam, egg, ham = enum_constants + + self.assertEqual(spam.kind, CursorKind.ENUM_CONSTANT_DECL) + self.assertEqual(spam.enum_value, 1) + self.assertEqual(egg.kind, CursorKind.ENUM_CONSTANT_DECL) + self.assertEqual(egg.enum_value, 2) + self.assertEqual(ham.kind, CursorKind.ENUM_CONSTANT_DECL) + self.assertEqual(ham.enum_value, 40) + + def test_enum_values_cpp(self): + tu = get_tu('enum TEST : long long { SPAM = -1, HAM = 0x10000000000};', lang="cpp") + enum = get_cursor(tu, 'TEST') + self.assertIsNotNone(enum) + + self.assertEqual(enum.kind, CursorKind.ENUM_DECL) + + enum_constants = list(enum.get_children()) + self.assertEqual(len(enum_constants), 2) + + spam, ham = enum_constants + + self.assertEqual(spam.kind, CursorKind.ENUM_CONSTANT_DECL) + self.assertEqual(spam.enum_value, -1) + self.assertEqual(ham.kind, CursorKind.ENUM_CONSTANT_DECL) + self.assertEqual(ham.enum_value, 0x10000000000) + + def test_annotation_attribute(self): + tu = get_tu('int foo (void) __attribute__ ((annotate("here be annotation attribute")));') + + foo = get_cursor(tu, 'foo') + self.assertIsNotNone(foo) for c in foo.get_children(): if c.kind == CursorKind.ANNOTATE_ATTR: - assert c.displayname == "annotation" + self.assertEqual(c.displayname, "here be annotation attribute") break else: - assert False, "Couldn't find annotation for {}".format(kind) + self.fail("Couldn't find annotation") -def test_result_type(): - tu = get_tu('int foo();') - foo = get_cursor(tu, 'foo') - - assert foo is not None - t = foo.result_type - assert t.kind == TypeKind.INT - -def test_availability(): - tu = get_tu('class A { A(A const&) = delete; };', lang='cpp') - - # AvailabilityKind.AVAILABLE - cursor = get_cursor(tu, 'A') - assert cursor.kind == CursorKind.CLASS_DECL - assert cursor.availability == AvailabilityKind.AVAILABLE - - # AvailabilityKind.NOT_AVAILABLE - cursors = get_cursors(tu, 'A') - for c in cursors: - if c.kind == CursorKind.CONSTRUCTOR: - assert c.availability == AvailabilityKind.NOT_AVAILABLE - break - else: - assert False, "Could not find cursor for deleted constructor" - - # AvailabilityKind.DEPRECATED - tu = get_tu('void test() __attribute__((deprecated));', lang='cpp') - cursor = get_cursor(tu, 'test') - assert cursor.availability == AvailabilityKind.DEPRECATED - - # AvailabilityKind.NOT_ACCESSIBLE is only used in the code completion results - -def test_get_tokens(): - """Ensure we can map cursors back to tokens.""" - tu = get_tu('int foo(int i);') - foo = get_cursor(tu, 'foo') - - tokens = list(foo.get_tokens()) - assert len(tokens) == 6 - assert tokens[0].spelling == 'int' - assert tokens[1].spelling == 'foo' - -def test_get_token_cursor(): - """Ensure we can map tokens to cursors.""" - tu = get_tu('class A {}; int foo(A var = A());', lang='cpp') - foo = get_cursor(tu, 'foo') - - for cursor in foo.walk_preorder(): - if cursor.kind.is_expression() and not cursor.kind.is_statement(): - break - else: - assert False, "Could not find default value expression" - - tokens = list(cursor.get_tokens()) - assert len(tokens) == 4, [t.spelling for t in tokens] - assert tokens[0].spelling == '=' - assert tokens[1].spelling == 'A' - assert tokens[2].spelling == '(' - assert tokens[3].spelling == ')' - t_cursor = tokens[1].cursor - assert t_cursor.kind == CursorKind.TYPE_REF - r_cursor = t_cursor.referenced # should not raise an exception - assert r_cursor.kind == CursorKind.CLASS_DECL - -def test_get_arguments(): - tu = get_tu('void foo(int i, int j);') - foo = get_cursor(tu, 'foo') - arguments = list(foo.get_arguments()) - - assert len(arguments) == 2 - assert arguments[0].spelling == "i" - assert arguments[1].spelling == "j" + def test_annotation_template(self): + annotation = '__attribute__ ((annotate("annotation")))' + for source, kind in [ + ('int foo (T value) %s;', CursorKind.FUNCTION_TEMPLATE), + ('class %s foo {};', CursorKind.CLASS_TEMPLATE), + ]: + source = 'template ' + (source % annotation) + tu = get_tu(source, lang="cpp") + + foo = get_cursor(tu, 'foo') + self.assertIsNotNone(foo) + self.assertEqual(foo.kind, kind) + + for c in foo.get_children(): + if c.kind == CursorKind.ANNOTATE_ATTR: + self.assertEqual(c.displayname, "annotation") + break + else: + self.fail("Couldn't find annotation for {}".format(kind)) -kTemplateArgTest = """\ - template - void foo(); + def test_result_type(self): + tu = get_tu('int foo();') + foo = get_cursor(tu, 'foo') - template<> - void foo<-7, float, true>(); - """ + self.assertIsNotNone(foo) + t = foo.result_type + self.assertEqual(t.kind, TypeKind.INT) + + def test_availability(self): + tu = get_tu('class A { A(A const&) = delete; };', lang='cpp') + + # AvailabilityKind.AVAILABLE + cursor = get_cursor(tu, 'A') + self.assertEqual(cursor.kind, CursorKind.CLASS_DECL) + self.assertEqual(cursor.availability, AvailabilityKind.AVAILABLE) + + # AvailabilityKind.NOT_AVAILABLE + cursors = get_cursors(tu, 'A') + for c in cursors: + if c.kind == CursorKind.CONSTRUCTOR: + self.assertEqual(c.availability, AvailabilityKind.NOT_AVAILABLE) + break + else: + self.fail("Could not find cursor for deleted constructor") -def test_get_num_template_arguments(): - tu = get_tu(kTemplateArgTest, lang='cpp') - foos = get_cursors(tu, 'foo') - - assert foos[1].get_num_template_arguments() == 3 - -def test_get_template_argument_kind(): - tu = get_tu(kTemplateArgTest, lang='cpp') - foos = get_cursors(tu, 'foo') - - assert foos[1].get_template_argument_kind(0) == TemplateArgumentKind.INTEGRAL - assert foos[1].get_template_argument_kind(1) == TemplateArgumentKind.TYPE - assert foos[1].get_template_argument_kind(2) == TemplateArgumentKind.INTEGRAL - -def test_get_template_argument_type(): - tu = get_tu(kTemplateArgTest, lang='cpp') - foos = get_cursors(tu, 'foo') - - assert foos[1].get_template_argument_type(1).kind == TypeKind.FLOAT - -def test_get_template_argument_value(): - tu = get_tu(kTemplateArgTest, lang='cpp') - foos = get_cursors(tu, 'foo') - - assert foos[1].get_template_argument_value(0) == -7 - assert foos[1].get_template_argument_value(2) == True - -def test_get_template_argument_unsigned_value(): - tu = get_tu(kTemplateArgTest, lang='cpp') - foos = get_cursors(tu, 'foo') - - assert foos[1].get_template_argument_unsigned_value(0) == 2 ** 32 - 7 - assert foos[1].get_template_argument_unsigned_value(2) == True - -def test_referenced(): - tu = get_tu('void foo(); void bar() { foo(); }') - foo = get_cursor(tu, 'foo') - bar = get_cursor(tu, 'bar') - for c in bar.get_children(): - if c.kind == CursorKind.CALL_EXPR: - assert c.referenced.spelling == foo.spelling - break - -def test_mangled_name(): - kInputForMangling = """\ - int foo(int, int); - """ - tu = get_tu(kInputForMangling, lang='cpp') - foo = get_cursor(tu, 'foo') + # AvailabilityKind.DEPRECATED + tu = get_tu('void test() __attribute__((deprecated));', lang='cpp') + cursor = get_cursor(tu, 'test') + self.assertEqual(cursor.availability, AvailabilityKind.DEPRECATED) + + # AvailabilityKind.NOT_ACCESSIBLE is only used in the code completion results + + def test_get_tokens(self): + """Ensure we can map cursors back to tokens.""" + tu = get_tu('int foo(int i);') + foo = get_cursor(tu, 'foo') + + tokens = list(foo.get_tokens()) + self.assertEqual(len(tokens), 6) + self.assertEqual(tokens[0].spelling, 'int') + self.assertEqual(tokens[1].spelling, 'foo') + + def test_get_token_cursor(self): + """Ensure we can map tokens to cursors.""" + tu = get_tu('class A {}; int foo(A var = A());', lang='cpp') + foo = get_cursor(tu, 'foo') + + for cursor in foo.walk_preorder(): + if cursor.kind.is_expression() and not cursor.kind.is_statement(): + break + else: + self.fail("Could not find default value expression") + + tokens = list(cursor.get_tokens()) + self.assertEqual(len(tokens), 4, [t.spelling for t in tokens]) + self.assertEqual(tokens[0].spelling, '=') + self.assertEqual(tokens[1].spelling, 'A') + self.assertEqual(tokens[2].spelling, '(') + self.assertEqual(tokens[3].spelling, ')') + t_cursor = tokens[1].cursor + self.assertEqual(t_cursor.kind, CursorKind.TYPE_REF) + r_cursor = t_cursor.referenced # should not raise an exception + self.assertEqual(r_cursor.kind, CursorKind.CLASS_DECL) + + def test_get_arguments(self): + tu = get_tu('void foo(int i, int j);') + foo = get_cursor(tu, 'foo') + arguments = list(foo.get_arguments()) + + self.assertEqual(len(arguments), 2) + self.assertEqual(arguments[0].spelling, "i") + self.assertEqual(arguments[1].spelling, "j") + + def test_get_num_template_arguments(self): + tu = get_tu(kTemplateArgTest, lang='cpp') + foos = get_cursors(tu, 'foo') + + self.assertEqual(foos[1].get_num_template_arguments(), 3) + + def test_get_template_argument_kind(self): + tu = get_tu(kTemplateArgTest, lang='cpp') + foos = get_cursors(tu, 'foo') + + self.assertEqual(foos[1].get_template_argument_kind(0), TemplateArgumentKind.INTEGRAL) + self.assertEqual(foos[1].get_template_argument_kind(1), TemplateArgumentKind.TYPE) + self.assertEqual(foos[1].get_template_argument_kind(2), TemplateArgumentKind.INTEGRAL) + + def test_get_template_argument_type(self): + tu = get_tu(kTemplateArgTest, lang='cpp') + foos = get_cursors(tu, 'foo') + + self.assertEqual(foos[1].get_template_argument_type(1).kind, TypeKind.FLOAT) + + def test_get_template_argument_value(self): + tu = get_tu(kTemplateArgTest, lang='cpp') + foos = get_cursors(tu, 'foo') + + self.assertEqual(foos[1].get_template_argument_value(0), -7) + self.assertEqual(foos[1].get_template_argument_value(2), True) + + def test_get_template_argument_unsigned_value(self): + tu = get_tu(kTemplateArgTest, lang='cpp') + foos = get_cursors(tu, 'foo') + + self.assertEqual(foos[1].get_template_argument_unsigned_value(0), 2 ** 32 - 7) + self.assertEqual(foos[1].get_template_argument_unsigned_value(2), True) + + def test_referenced(self): + tu = get_tu('void foo(); void bar() { foo(); }') + foo = get_cursor(tu, 'foo') + bar = get_cursor(tu, 'bar') + for c in bar.get_children(): + if c.kind == CursorKind.CALL_EXPR: + self.assertEqual(c.referenced.spelling, foo.spelling) + break + + def test_mangled_name(self): + kInputForMangling = """\ + int foo(int, int); + """ + tu = get_tu(kInputForMangling, lang='cpp') + foo = get_cursor(tu, 'foo') - # Since libclang does not link in targets, we cannot pass a triple to it - # and force the target. To enable this test to pass on all platforms, accept - # all valid manglings. - # [c-index-test handles this by running the source through clang, emitting - # an AST file and running libclang on that AST file] - assert foo.mangled_name in ('_Z3fooii', '__Z3fooii', '?foo@@YAHHH') + # Since libclang does not link in targets, we cannot pass a triple to it + # and force the target. To enable this test to pass on all platforms, accept + # all valid manglings. + # [c-index-test handles this by running the source through clang, emitting + # an AST file and running libclang on that AST file] + self.assertIn(foo.mangled_name, ('_Z3fooii', '__Z3fooii', '?foo@@YAHHH')) Index: cfe/trunk/bindings/python/tests/cindex/test_cursor_kind.py =================================================================== --- cfe/trunk/bindings/python/tests/cindex/test_cursor_kind.py +++ cfe/trunk/bindings/python/tests/cindex/test_cursor_kind.py @@ -1,49 +1,53 @@ from clang.cindex import CursorKind -def test_name(): - assert CursorKind.UNEXPOSED_DECL.name is 'UNEXPOSED_DECL' +import unittest -def test_get_all_kinds(): - kinds = CursorKind.get_all_kinds() - assert CursorKind.UNEXPOSED_DECL in kinds - assert CursorKind.TRANSLATION_UNIT in kinds - assert CursorKind.VARIABLE_REF in kinds - assert CursorKind.LAMBDA_EXPR in kinds - assert CursorKind.OBJ_BOOL_LITERAL_EXPR in kinds - assert CursorKind.OBJ_SELF_EXPR in kinds - assert CursorKind.MS_ASM_STMT in kinds - assert CursorKind.MODULE_IMPORT_DECL in kinds - assert CursorKind.TYPE_ALIAS_TEMPLATE_DECL in kinds - -def test_kind_groups(): - """Check that every kind classifies to exactly one group.""" - - assert CursorKind.UNEXPOSED_DECL.is_declaration() - assert CursorKind.TYPE_REF.is_reference() - assert CursorKind.DECL_REF_EXPR.is_expression() - assert CursorKind.UNEXPOSED_STMT.is_statement() - assert CursorKind.INVALID_FILE.is_invalid() - - assert CursorKind.TRANSLATION_UNIT.is_translation_unit() - assert not CursorKind.TYPE_REF.is_translation_unit() - - assert CursorKind.PREPROCESSING_DIRECTIVE.is_preprocessing() - assert not CursorKind.TYPE_REF.is_preprocessing() - - assert CursorKind.UNEXPOSED_DECL.is_unexposed() - assert not CursorKind.TYPE_REF.is_unexposed() - - for k in CursorKind.get_all_kinds(): - group = [n for n in ('is_declaration', 'is_reference', 'is_expression', - 'is_statement', 'is_invalid', 'is_attribute') - if getattr(k, n)()] - - if k in ( CursorKind.TRANSLATION_UNIT, - CursorKind.MACRO_DEFINITION, - CursorKind.MACRO_INSTANTIATION, - CursorKind.INCLUSION_DIRECTIVE, - CursorKind.PREPROCESSING_DIRECTIVE, - CursorKind.OVERLOAD_CANDIDATE): - assert len(group) == 0 - else: - assert len(group) == 1 + +class TestCursorKind(unittest.TestCase): + def test_name(self): + self.assertTrue(CursorKind.UNEXPOSED_DECL.name is 'UNEXPOSED_DECL') + + def test_get_all_kinds(self): + kinds = CursorKind.get_all_kinds() + self.assertIn(CursorKind.UNEXPOSED_DECL, kinds) + self.assertIn(CursorKind.TRANSLATION_UNIT, kinds) + self.assertIn(CursorKind.VARIABLE_REF, kinds) + self.assertIn(CursorKind.LAMBDA_EXPR, kinds) + self.assertIn(CursorKind.OBJ_BOOL_LITERAL_EXPR, kinds) + self.assertIn(CursorKind.OBJ_SELF_EXPR, kinds) + self.assertIn(CursorKind.MS_ASM_STMT, kinds) + self.assertIn(CursorKind.MODULE_IMPORT_DECL, kinds) + self.assertIn(CursorKind.TYPE_ALIAS_TEMPLATE_DECL, kinds) + + def test_kind_groups(self): + """Check that every kind classifies to exactly one group.""" + + self.assertTrue(CursorKind.UNEXPOSED_DECL.is_declaration()) + self.assertTrue(CursorKind.TYPE_REF.is_reference()) + self.assertTrue(CursorKind.DECL_REF_EXPR.is_expression()) + self.assertTrue(CursorKind.UNEXPOSED_STMT.is_statement()) + self.assertTrue(CursorKind.INVALID_FILE.is_invalid()) + + self.assertTrue(CursorKind.TRANSLATION_UNIT.is_translation_unit()) + self.assertFalse(CursorKind.TYPE_REF.is_translation_unit()) + + self.assertTrue(CursorKind.PREPROCESSING_DIRECTIVE.is_preprocessing()) + self.assertFalse(CursorKind.TYPE_REF.is_preprocessing()) + + self.assertTrue(CursorKind.UNEXPOSED_DECL.is_unexposed()) + self.assertFalse(CursorKind.TYPE_REF.is_unexposed()) + + for k in CursorKind.get_all_kinds(): + group = [n for n in ('is_declaration', 'is_reference', 'is_expression', + 'is_statement', 'is_invalid', 'is_attribute') + if getattr(k, n)()] + + if k in ( CursorKind.TRANSLATION_UNIT, + CursorKind.MACRO_DEFINITION, + CursorKind.MACRO_INSTANTIATION, + CursorKind.INCLUSION_DIRECTIVE, + CursorKind.PREPROCESSING_DIRECTIVE, + CursorKind.OVERLOAD_CANDIDATE): + self.assertEqual(len(group), 0) + else: + self.assertEqual(len(group), 1) Index: cfe/trunk/bindings/python/tests/cindex/test_diagnostics.py =================================================================== --- cfe/trunk/bindings/python/tests/cindex/test_diagnostics.py +++ cfe/trunk/bindings/python/tests/cindex/test_diagnostics.py @@ -1,102 +1,105 @@ from clang.cindex import * from .util import get_tu +import unittest + + # FIXME: We need support for invalid translation units to test better. -def test_diagnostic_warning(): - tu = get_tu('int f0() {}\n') - assert len(tu.diagnostics) == 1 - assert tu.diagnostics[0].severity == Diagnostic.Warning - assert tu.diagnostics[0].location.line == 1 - assert tu.diagnostics[0].location.column == 11 - assert (tu.diagnostics[0].spelling == - 'control reaches end of non-void function') - -def test_diagnostic_note(): - # FIXME: We aren't getting notes here for some reason. - tu = get_tu('#define A x\nvoid *A = 1;\n') - assert len(tu.diagnostics) == 1 - assert tu.diagnostics[0].severity == Diagnostic.Warning - assert tu.diagnostics[0].location.line == 2 - assert tu.diagnostics[0].location.column == 7 - assert 'incompatible' in tu.diagnostics[0].spelling -# assert tu.diagnostics[1].severity == Diagnostic.Note -# assert tu.diagnostics[1].location.line == 1 -# assert tu.diagnostics[1].location.column == 11 -# assert tu.diagnostics[1].spelling == 'instantiated from' - -def test_diagnostic_fixit(): - tu = get_tu('struct { int f0; } x = { f0 : 1 };') - assert len(tu.diagnostics) == 1 - assert tu.diagnostics[0].severity == Diagnostic.Warning - assert tu.diagnostics[0].location.line == 1 - assert tu.diagnostics[0].location.column == 26 - assert tu.diagnostics[0].spelling.startswith('use of GNU old-style') - assert len(tu.diagnostics[0].fixits) == 1 - assert tu.diagnostics[0].fixits[0].range.start.line == 1 - assert tu.diagnostics[0].fixits[0].range.start.column == 26 - assert tu.diagnostics[0].fixits[0].range.end.line == 1 - assert tu.diagnostics[0].fixits[0].range.end.column == 30 - assert tu.diagnostics[0].fixits[0].value == '.f0 = ' - -def test_diagnostic_range(): - tu = get_tu('void f() { int i = "a" + 1; }') - assert len(tu.diagnostics) == 1 - assert tu.diagnostics[0].severity == Diagnostic.Warning - assert tu.diagnostics[0].location.line == 1 - assert tu.diagnostics[0].location.column == 16 - assert tu.diagnostics[0].spelling.startswith('incompatible pointer to') - assert len(tu.diagnostics[0].fixits) == 0 - assert len(tu.diagnostics[0].ranges) == 1 - assert tu.diagnostics[0].ranges[0].start.line == 1 - assert tu.diagnostics[0].ranges[0].start.column == 20 - assert tu.diagnostics[0].ranges[0].end.line == 1 - assert tu.diagnostics[0].ranges[0].end.column == 27 - try: - tu.diagnostics[0].ranges[1].start.line - except IndexError: - assert True - else: - assert False - -def test_diagnostic_category(): - """Ensure that category properties work.""" - tu = get_tu('int f(int i) { return 7; }', all_warnings=True) - assert len(tu.diagnostics) == 1 - d = tu.diagnostics[0] - - assert d.severity == Diagnostic.Warning - assert d.location.line == 1 - assert d.location.column == 11 - - assert d.category_number == 2 - assert d.category_name == 'Semantic Issue' - -def test_diagnostic_option(): - """Ensure that category option properties work.""" - tu = get_tu('int f(int i) { return 7; }', all_warnings=True) - assert len(tu.diagnostics) == 1 - d = tu.diagnostics[0] - - assert d.option == '-Wunused-parameter' - assert d.disable_option == '-Wno-unused-parameter' - -def test_diagnostic_children(): - tu = get_tu('void f(int x) {} void g() { f(); }') - assert len(tu.diagnostics) == 1 - d = tu.diagnostics[0] - - children = d.children - assert len(children) == 1 - assert children[0].severity == Diagnostic.Note - assert children[0].spelling.endswith('declared here') - assert children[0].location.line == 1 - assert children[0].location.column == 1 - -def test_diagnostic_string_repr(): - tu = get_tu('struct MissingSemicolon{}') - assert len(tu.diagnostics) == 1 - d = tu.diagnostics[0] - assert repr(d) == ', spelling "expected \';\' after struct">' - +class TestDiagnostics(unittest.TestCase): + def test_diagnostic_warning(self): + tu = get_tu('int f0() {}\n') + self.assertEqual(len(tu.diagnostics), 1) + self.assertEqual(tu.diagnostics[0].severity, Diagnostic.Warning) + self.assertEqual(tu.diagnostics[0].location.line, 1) + self.assertEqual(tu.diagnostics[0].location.column, 11) + self.assertEqual(tu.diagnostics[0].spelling, + 'control reaches end of non-void function') + + def test_diagnostic_note(self): + # FIXME: We aren't getting notes here for some reason. + tu = get_tu('#define A x\nvoid *A = 1;\n') + self.assertEqual(len(tu.diagnostics), 1) + self.assertEqual(tu.diagnostics[0].severity, Diagnostic.Warning) + self.assertEqual(tu.diagnostics[0].location.line, 2) + self.assertEqual(tu.diagnostics[0].location.column, 7) + self.assertIn('incompatible', tu.diagnostics[0].spelling) +# self.assertEqual(tu.diagnostics[1].severity, Diagnostic.Note) +# self.assertEqual(tu.diagnostics[1].location.line, 1) +# self.assertEqual(tu.diagnostics[1].location.column, 11) +# self.assertEqual(tu.diagnostics[1].spelling, 'instantiated from') + + def test_diagnostic_fixit(self): + tu = get_tu('struct { int f0; } x = { f0 : 1 };') + self.assertEqual(len(tu.diagnostics), 1) + self.assertEqual(tu.diagnostics[0].severity, Diagnostic.Warning) + self.assertEqual(tu.diagnostics[0].location.line, 1) + self.assertEqual(tu.diagnostics[0].location.column, 26) + self.assertRegexpMatches(tu.diagnostics[0].spelling, + 'use of GNU old-style.*') + self.assertEqual(len(tu.diagnostics[0].fixits), 1) + self.assertEqual(tu.diagnostics[0].fixits[0].range.start.line, 1) + self.assertEqual(tu.diagnostics[0].fixits[0].range.start.column, 26) + self.assertEqual(tu.diagnostics[0].fixits[0].range.end.line, 1) + self.assertEqual(tu.diagnostics[0].fixits[0].range.end.column, 30) + self.assertEqual(tu.diagnostics[0].fixits[0].value, '.f0 = ') + + def test_diagnostic_range(self): + tu = get_tu('void f() { int i = "a" + 1; }') + self.assertEqual(len(tu.diagnostics), 1) + self.assertEqual(tu.diagnostics[0].severity, Diagnostic.Warning) + self.assertEqual(tu.diagnostics[0].location.line, 1) + self.assertEqual(tu.diagnostics[0].location.column, 16) + self.assertRegexpMatches(tu.diagnostics[0].spelling, + 'incompatible pointer to.*') + self.assertEqual(len(tu.diagnostics[0].fixits), 0) + self.assertEqual(len(tu.diagnostics[0].ranges), 1) + self.assertEqual(tu.diagnostics[0].ranges[0].start.line, 1) + self.assertEqual(tu.diagnostics[0].ranges[0].start.column, 20) + self.assertEqual(tu.diagnostics[0].ranges[0].end.line, 1) + self.assertEqual(tu.diagnostics[0].ranges[0].end.column, 27) + with self.assertRaises(IndexError): + tu.diagnostics[0].ranges[1].start.line + + def test_diagnostic_category(self): + """Ensure that category properties work.""" + tu = get_tu('int f(int i) { return 7; }', all_warnings=True) + self.assertEqual(len(tu.diagnostics), 1) + d = tu.diagnostics[0] + + self.assertEqual(d.severity, Diagnostic.Warning) + self.assertEqual(d.location.line, 1) + self.assertEqual(d.location.column, 11) + + self.assertEqual(d.category_number, 2) + self.assertEqual(d.category_name, 'Semantic Issue') + + def test_diagnostic_option(self): + """Ensure that category option properties work.""" + tu = get_tu('int f(int i) { return 7; }', all_warnings=True) + self.assertEqual(len(tu.diagnostics), 1) + d = tu.diagnostics[0] + + self.assertEqual(d.option, '-Wunused-parameter') + self.assertEqual(d.disable_option, '-Wno-unused-parameter') + + def test_diagnostic_children(self): + tu = get_tu('void f(int x) {} void g() { f(); }') + self.assertEqual(len(tu.diagnostics), 1) + d = tu.diagnostics[0] + + children = d.children + self.assertEqual(len(children), 1) + self.assertEqual(children[0].severity, Diagnostic.Note) + self.assertRegexpMatches(children[0].spelling, + '.*declared here') + self.assertEqual(children[0].location.line, 1) + self.assertEqual(children[0].location.column, 1) + + def test_diagnostic_string_repr(self): + tu = get_tu('struct MissingSemicolon{}') + self.assertEqual(len(tu.diagnostics), 1) + d = tu.diagnostics[0] + + self.assertEqual(repr(d), ', spelling "expected \';\' after struct">') Index: cfe/trunk/bindings/python/tests/cindex/test_exception_specification_kind.py =================================================================== --- cfe/trunk/bindings/python/tests/cindex/test_exception_specification_kind.py +++ cfe/trunk/bindings/python/tests/cindex/test_exception_specification_kind.py @@ -2,6 +2,8 @@ from clang.cindex import ExceptionSpecificationKind from .util import get_tu +import unittest + def find_function_declarations(node, declarations=[]): if node.kind == clang.cindex.CursorKind.FUNCTION_DECL: @@ -11,17 +13,18 @@ return declarations -def test_exception_specification_kind(): - source = """int square1(int x); - int square2(int x) noexcept; - int square3(int x) noexcept(noexcept(x * x));""" - - tu = get_tu(source, lang='cpp', flags=['-std=c++14']) - - declarations = find_function_declarations(tu.cursor) - expected = [ - ('square1', ExceptionSpecificationKind.NONE), - ('square2', ExceptionSpecificationKind.BASIC_NOEXCEPT), - ('square3', ExceptionSpecificationKind.COMPUTED_NOEXCEPT) - ] - assert declarations == expected +class TestExceptionSpecificationKind(unittest.TestCase): + def test_exception_specification_kind(self): + source = """int square1(int x); + int square2(int x) noexcept; + int square3(int x) noexcept(noexcept(x * x));""" + + tu = get_tu(source, lang='cpp', flags=['-std=c++14']) + + declarations = find_function_declarations(tu.cursor) + expected = [ + ('square1', ExceptionSpecificationKind.NONE), + ('square2', ExceptionSpecificationKind.BASIC_NOEXCEPT), + ('square3', ExceptionSpecificationKind.COMPUTED_NOEXCEPT) + ] + self.assertListEqual(declarations, expected) Index: cfe/trunk/bindings/python/tests/cindex/test_file.py =================================================================== --- cfe/trunk/bindings/python/tests/cindex/test_file.py +++ cfe/trunk/bindings/python/tests/cindex/test_file.py @@ -1,9 +1,13 @@ from clang.cindex import Index, File -def test_file(): - index = Index.create() - tu = index.parse('t.c', unsaved_files = [('t.c', "")]) - file = File.from_name(tu, "t.c") - assert str(file) == "t.c" - assert file.name == "t.c" - assert repr(file) == "" +import unittest + + +class TestFile(unittest.TestCase): + def test_file(self): + index = Index.create() + tu = index.parse('t.c', unsaved_files = [('t.c', "")]) + file = File.from_name(tu, "t.c") + self.assertEqual(str(file), "t.c") + self.assertEqual(file.name, "t.c") + self.assertEqual(repr(file), "") Index: cfe/trunk/bindings/python/tests/cindex/test_index.py =================================================================== --- cfe/trunk/bindings/python/tests/cindex/test_index.py +++ cfe/trunk/bindings/python/tests/cindex/test_index.py @@ -1,17 +1,21 @@ from clang.cindex import * import os +import unittest + kInputsDir = os.path.join(os.path.dirname(__file__), 'INPUTS') -def test_create(): - index = Index.create() -# FIXME: test Index.read +class TestIndex(unittest.TestCase): + def test_create(self): + index = Index.create() + + # FIXME: test Index.read -def test_parse(): - index = Index.create() - assert isinstance(index, Index) - tu = index.parse(os.path.join(kInputsDir, 'hello.cpp')) - assert isinstance(tu, TranslationUnit) - tu = index.parse(None, ['-c', os.path.join(kInputsDir, 'hello.cpp')]) - assert isinstance(tu, TranslationUnit) + def test_parse(self): + index = Index.create() + self.assertIsInstance(index, Index) + tu = index.parse(os.path.join(kInputsDir, 'hello.cpp')) + self.assertIsInstance(tu, TranslationUnit) + tu = index.parse(None, ['-c', os.path.join(kInputsDir, 'hello.cpp')]) + self.assertIsInstance(tu, TranslationUnit) Index: cfe/trunk/bindings/python/tests/cindex/test_linkage.py =================================================================== --- cfe/trunk/bindings/python/tests/cindex/test_linkage.py +++ cfe/trunk/bindings/python/tests/cindex/test_linkage.py @@ -1,4 +1,3 @@ - from clang.cindex import LinkageKind from clang.cindex import Cursor from clang.cindex import TranslationUnit @@ -6,25 +5,28 @@ from .util import get_cursor from .util import get_tu -def test_linkage(): - """Ensure that linkage specifers are available on cursors""" +import unittest + - tu = get_tu(""" +class TestLinkage(unittest.TestCase): + def test_linkage(self): + """Ensure that linkage specifers are available on cursors""" + + tu = get_tu(""" void foo() { int no_linkage; } static int internal; namespace { extern int unique_external; } extern int external; """, lang = 'cpp') - no_linkage = get_cursor(tu.cursor, 'no_linkage') - assert no_linkage.linkage == LinkageKind.NO_LINKAGE; - - internal = get_cursor(tu.cursor, 'internal') - assert internal.linkage == LinkageKind.INTERNAL + no_linkage = get_cursor(tu.cursor, 'no_linkage') + self.assertEqual(no_linkage.linkage, LinkageKind.NO_LINKAGE) - unique_external = get_cursor(tu.cursor, 'unique_external') - assert unique_external.linkage == LinkageKind.UNIQUE_EXTERNAL + internal = get_cursor(tu.cursor, 'internal') + self.assertEqual(internal.linkage, LinkageKind.INTERNAL) - external = get_cursor(tu.cursor, 'external') - assert external.linkage == LinkageKind.EXTERNAL + unique_external = get_cursor(tu.cursor, 'unique_external') + self.assertEqual(unique_external.linkage, LinkageKind.UNIQUE_EXTERNAL) + external = get_cursor(tu.cursor, 'external') + self.assertEqual(external.linkage, LinkageKind.EXTERNAL) Index: cfe/trunk/bindings/python/tests/cindex/test_location.py =================================================================== --- cfe/trunk/bindings/python/tests/cindex/test_location.py +++ cfe/trunk/bindings/python/tests/cindex/test_location.py @@ -5,91 +5,96 @@ from .util import get_cursor from .util import get_tu +import unittest + + baseInput="int one;\nint two;\n" -def assert_location(loc, line, column, offset): - assert loc.line == line - assert loc.column == column - assert loc.offset == offset - -def test_location(): - tu = get_tu(baseInput) - one = get_cursor(tu, 'one') - two = get_cursor(tu, 'two') - - assert one is not None - assert two is not None - - assert_location(one.location,line=1,column=5,offset=4) - assert_location(two.location,line=2,column=5,offset=13) - - # adding a linebreak at top should keep columns same - tu = get_tu('\n' + baseInput) - one = get_cursor(tu, 'one') - two = get_cursor(tu, 'two') - - assert one is not None - assert two is not None - - assert_location(one.location,line=2,column=5,offset=5) - assert_location(two.location,line=3,column=5,offset=14) - - # adding a space should affect column on first line only - tu = get_tu(' ' + baseInput) - one = get_cursor(tu, 'one') - two = get_cursor(tu, 'two') - - assert_location(one.location,line=1,column=6,offset=5) - assert_location(two.location,line=2,column=5,offset=14) - - # define the expected location ourselves and see if it matches - # the returned location - tu = get_tu(baseInput) - - file = File.from_name(tu, 't.c') - location = SourceLocation.from_position(tu, file, 1, 5) - cursor = Cursor.from_location(tu, location) - - one = get_cursor(tu, 'one') - assert one is not None - assert one == cursor - - # Ensure locations referring to the same entity are equivalent. - location2 = SourceLocation.from_position(tu, file, 1, 5) - assert location == location2 - location3 = SourceLocation.from_position(tu, file, 1, 4) - assert location2 != location3 - - offset_location = SourceLocation.from_offset(tu, file, 5) - cursor = Cursor.from_location(tu, offset_location) - verified = False - for n in [n for n in tu.cursor.get_children() if n.spelling == 'one']: - assert n == cursor - verified = True - - assert verified - -def test_extent(): - tu = get_tu(baseInput) - one = get_cursor(tu, 'one') - two = get_cursor(tu, 'two') - - assert_location(one.extent.start,line=1,column=1,offset=0) - assert_location(one.extent.end,line=1,column=8,offset=7) - assert baseInput[one.extent.start.offset:one.extent.end.offset] == "int one" - - assert_location(two.extent.start,line=2,column=1,offset=9) - assert_location(two.extent.end,line=2,column=8,offset=16) - assert baseInput[two.extent.start.offset:two.extent.end.offset] == "int two" - - file = File.from_name(tu, 't.c') - location1 = SourceLocation.from_position(tu, file, 1, 1) - location2 = SourceLocation.from_position(tu, file, 1, 8) - - range1 = SourceRange.from_locations(location1, location2) - range2 = SourceRange.from_locations(location1, location2) - assert range1 == range2 - - location3 = SourceLocation.from_position(tu, file, 1, 6) - range3 = SourceRange.from_locations(location1, location3) - assert range1 != range3 + +class TestLocation(unittest.TestCase): + def assert_location(self, loc, line, column, offset): + self.assertEqual(loc.line, line) + self.assertEqual(loc.column, column) + self.assertEqual(loc.offset, offset) + + def test_location(self): + tu = get_tu(baseInput) + one = get_cursor(tu, 'one') + two = get_cursor(tu, 'two') + + self.assertIsNotNone(one) + self.assertIsNotNone(two) + + self.assert_location(one.location,line=1,column=5,offset=4) + self.assert_location(two.location,line=2,column=5,offset=13) + + # adding a linebreak at top should keep columns same + tu = get_tu('\n' + baseInput) + one = get_cursor(tu, 'one') + two = get_cursor(tu, 'two') + + self.assertIsNotNone(one) + self.assertIsNotNone(two) + + self.assert_location(one.location,line=2,column=5,offset=5) + self.assert_location(two.location,line=3,column=5,offset=14) + + # adding a space should affect column on first line only + tu = get_tu(' ' + baseInput) + one = get_cursor(tu, 'one') + two = get_cursor(tu, 'two') + + self.assert_location(one.location,line=1,column=6,offset=5) + self.assert_location(two.location,line=2,column=5,offset=14) + + # define the expected location ourselves and see if it matches + # the returned location + tu = get_tu(baseInput) + + file = File.from_name(tu, 't.c') + location = SourceLocation.from_position(tu, file, 1, 5) + cursor = Cursor.from_location(tu, location) + + one = get_cursor(tu, 'one') + self.assertIsNotNone(one) + self.assertEqual(one, cursor) + + # Ensure locations referring to the same entity are equivalent. + location2 = SourceLocation.from_position(tu, file, 1, 5) + self.assertEqual(location, location2) + location3 = SourceLocation.from_position(tu, file, 1, 4) + self.assertNotEqual(location2, location3) + + offset_location = SourceLocation.from_offset(tu, file, 5) + cursor = Cursor.from_location(tu, offset_location) + verified = False + for n in [n for n in tu.cursor.get_children() if n.spelling == 'one']: + self.assertEqual(n, cursor) + verified = True + + self.assertTrue(verified) + + def test_extent(self): + tu = get_tu(baseInput) + one = get_cursor(tu, 'one') + two = get_cursor(tu, 'two') + + self.assert_location(one.extent.start,line=1,column=1,offset=0) + self.assert_location(one.extent.end,line=1,column=8,offset=7) + self.assertEqual(baseInput[one.extent.start.offset:one.extent.end.offset], "int one") + + self.assert_location(two.extent.start,line=2,column=1,offset=9) + self.assert_location(two.extent.end,line=2,column=8,offset=16) + self.assertEqual(baseInput[two.extent.start.offset:two.extent.end.offset], "int two") + + file = File.from_name(tu, 't.c') + location1 = SourceLocation.from_position(tu, file, 1, 1) + location2 = SourceLocation.from_position(tu, file, 1, 8) + + range1 = SourceRange.from_locations(location1, location2) + range2 = SourceRange.from_locations(location1, location2) + self.assertEqual(range1, range2) + + location3 = SourceLocation.from_position(tu, file, 1, 6) + range3 = SourceRange.from_locations(location1, location3) + self.assertNotEqual(range1, range3) Index: cfe/trunk/bindings/python/tests/cindex/test_tls_kind.py =================================================================== --- cfe/trunk/bindings/python/tests/cindex/test_tls_kind.py +++ cfe/trunk/bindings/python/tests/cindex/test_tls_kind.py @@ -1,4 +1,3 @@ - from clang.cindex import TLSKind from clang.cindex import Cursor from clang.cindex import TranslationUnit @@ -6,42 +5,45 @@ from .util import get_cursor from .util import get_tu -def test_tls_kind(): - """Ensure that thread-local storage kinds are available on cursors.""" +import unittest + - tu = get_tu(""" +class TestTLSKind(unittest.TestCase): + def test_tls_kind(self): + """Ensure that thread-local storage kinds are available on cursors.""" + + tu = get_tu(""" int tls_none; thread_local int tls_dynamic; _Thread_local int tls_static; """, lang = 'cpp') - tls_none = get_cursor(tu.cursor, 'tls_none') - assert tls_none.tls_kind == TLSKind.NONE; + tls_none = get_cursor(tu.cursor, 'tls_none') + self.assertEqual(tls_none.tls_kind, TLSKind.NONE) - tls_dynamic = get_cursor(tu.cursor, 'tls_dynamic') - assert tls_dynamic.tls_kind == TLSKind.DYNAMIC + tls_dynamic = get_cursor(tu.cursor, 'tls_dynamic') + self.assertEqual(tls_dynamic.tls_kind, TLSKind.DYNAMIC) - tls_static = get_cursor(tu.cursor, 'tls_static') - assert tls_static.tls_kind == TLSKind.STATIC + tls_static = get_cursor(tu.cursor, 'tls_static') + self.assertEqual(tls_static.tls_kind, TLSKind.STATIC) - # The following case tests '__declspec(thread)'. Since it is a Microsoft - # specific extension, specific flags are required for the parser to pick - # these up. - flags = ['-fms-extensions', '-target', 'x86_64-unknown-windows-win32', - '-fms-compatibility-version=18'] - tu = get_tu(""" + # The following case tests '__declspec(thread)'. Since it is a Microsoft + # specific extension, specific flags are required for the parser to pick + # these up. + flags = ['-fms-extensions', '-target', 'x86_64-unknown-windows-win32', + '-fms-compatibility-version=18'] + tu = get_tu(""" __declspec(thread) int tls_declspec_msvc18; """, lang = 'cpp', flags=flags) - tls_declspec_msvc18 = get_cursor(tu.cursor, 'tls_declspec_msvc18') - assert tls_declspec_msvc18.tls_kind == TLSKind.STATIC + tls_declspec_msvc18 = get_cursor(tu.cursor, 'tls_declspec_msvc18') + self.assertEqual(tls_declspec_msvc18.tls_kind, TLSKind.STATIC) - flags = ['-fms-extensions', '-target', 'x86_64-unknown-windows-win32', - '-fms-compatibility-version=19'] - tu = get_tu(""" + flags = ['-fms-extensions', '-target', 'x86_64-unknown-windows-win32', + '-fms-compatibility-version=19'] + tu = get_tu(""" __declspec(thread) int tls_declspec_msvc19; """, lang = 'cpp', flags=flags) - tls_declspec_msvc19 = get_cursor(tu.cursor, 'tls_declspec_msvc19') - assert tls_declspec_msvc19.tls_kind == TLSKind.DYNAMIC - + tls_declspec_msvc19 = get_cursor(tu.cursor, 'tls_declspec_msvc19') + self.assertEqual(tls_declspec_msvc19.tls_kind, TLSKind.DYNAMIC) Index: cfe/trunk/bindings/python/tests/cindex/test_token_kind.py =================================================================== --- cfe/trunk/bindings/python/tests/cindex/test_token_kind.py +++ cfe/trunk/bindings/python/tests/cindex/test_token_kind.py @@ -1,43 +1,44 @@ from clang.cindex import TokenKind -from nose.tools import eq_ -from nose.tools import ok_ -from nose.tools import raises -def test_constructor(): - """Ensure TokenKind constructor works as expected.""" +import unittest - t = TokenKind(5, 'foo') - eq_(t.value, 5) - eq_(t.name, 'foo') +class TestTokenKind(unittest.TestCase): + def test_constructor(self): + """Ensure TokenKind constructor works as expected.""" -@raises(ValueError) -def test_bad_register(): - """Ensure a duplicate value is rejected for registration.""" + t = TokenKind(5, 'foo') - TokenKind.register(2, 'foo') + self.assertEqual(t.value, 5) + self.assertEqual(t.name, 'foo') -@raises(ValueError) -def test_unknown_value(): - """Ensure trying to fetch an unknown value raises.""" + def test_bad_register(self): + """Ensure a duplicate value is rejected for registration.""" - TokenKind.from_value(-1) + with self.assertRaises(ValueError): + TokenKind.register(2, 'foo') -def test_registration(): - """Ensure that items registered appear as class attributes.""" - ok_(hasattr(TokenKind, 'LITERAL')) - literal = TokenKind.LITERAL + def test_unknown_value(self): + """Ensure trying to fetch an unknown value raises.""" - ok_(isinstance(literal, TokenKind)) + with self.assertRaises(ValueError): + TokenKind.from_value(-1) -def test_from_value(): - """Ensure registered values can be obtained from from_value().""" - t = TokenKind.from_value(3) - ok_(isinstance(t, TokenKind)) - eq_(t, TokenKind.LITERAL) + def test_registration(self): + """Ensure that items registered appear as class attributes.""" + self.assertTrue(hasattr(TokenKind, 'LITERAL')) + literal = TokenKind.LITERAL -def test_repr(): - """Ensure repr() works.""" + self.assertIsInstance(literal, TokenKind) - r = repr(TokenKind.LITERAL) - eq_(r, 'TokenKind.LITERAL') + def test_from_value(self): + """Ensure registered values can be obtained from from_value().""" + t = TokenKind.from_value(3) + self.assertIsInstance(t, TokenKind) + self.assertEqual(t, TokenKind.LITERAL) + + def test_repr(self): + """Ensure repr() works.""" + + r = repr(TokenKind.LITERAL) + self.assertEqual(r, 'TokenKind.LITERAL') Index: cfe/trunk/bindings/python/tests/cindex/test_tokens.py =================================================================== --- cfe/trunk/bindings/python/tests/cindex/test_tokens.py +++ cfe/trunk/bindings/python/tests/cindex/test_tokens.py @@ -3,50 +3,52 @@ from clang.cindex import SourceLocation from clang.cindex import SourceRange from clang.cindex import TokenKind -from nose.tools import eq_ -from nose.tools import ok_ from .util import get_tu -def test_token_to_cursor(): - """Ensure we can obtain a Cursor from a Token instance.""" - tu = get_tu('int i = 5;') - r = tu.get_extent('t.c', (0, 9)) - tokens = list(tu.get_tokens(extent=r)) - - assert len(tokens) == 4 - assert tokens[1].spelling == 'i' - assert tokens[1].kind == TokenKind.IDENTIFIER - - cursor = tokens[1].cursor - assert cursor.kind == CursorKind.VAR_DECL - assert tokens[1].cursor == tokens[2].cursor - -def test_token_location(): - """Ensure Token.location works.""" - - tu = get_tu('int foo = 10;') - r = tu.get_extent('t.c', (0, 11)) - - tokens = list(tu.get_tokens(extent=r)) - eq_(len(tokens), 4) - - loc = tokens[1].location - ok_(isinstance(loc, SourceLocation)) - eq_(loc.line, 1) - eq_(loc.column, 5) - eq_(loc.offset, 4) - -def test_token_extent(): - """Ensure Token.extent works.""" - tu = get_tu('int foo = 10;') - r = tu.get_extent('t.c', (0, 11)) +import unittest - tokens = list(tu.get_tokens(extent=r)) - eq_(len(tokens), 4) - extent = tokens[1].extent - ok_(isinstance(extent, SourceRange)) +class TestTokens(unittest.TestCase): + def test_token_to_cursor(self): + """Ensure we can obtain a Cursor from a Token instance.""" + tu = get_tu('int i = 5;') + r = tu.get_extent('t.c', (0, 9)) + tokens = list(tu.get_tokens(extent=r)) - eq_(extent.start.offset, 4) - eq_(extent.end.offset, 7) + self.assertEqual(len(tokens), 4) + self.assertEqual(tokens[1].spelling, 'i') + self.assertEqual(tokens[1].kind, TokenKind.IDENTIFIER) + + cursor = tokens[1].cursor + self.assertEqual(cursor.kind, CursorKind.VAR_DECL) + self.assertEqual(tokens[1].cursor, tokens[2].cursor) + + def test_token_location(self): + """Ensure Token.location works.""" + + tu = get_tu('int foo = 10;') + r = tu.get_extent('t.c', (0, 11)) + + tokens = list(tu.get_tokens(extent=r)) + self.assertEqual(len(tokens), 4) + + loc = tokens[1].location + self.assertIsInstance(loc, SourceLocation) + self.assertEqual(loc.line, 1) + self.assertEqual(loc.column, 5) + self.assertEqual(loc.offset, 4) + + def test_token_extent(self): + """Ensure Token.extent works.""" + tu = get_tu('int foo = 10;') + r = tu.get_extent('t.c', (0, 11)) + + tokens = list(tu.get_tokens(extent=r)) + self.assertEqual(len(tokens), 4) + + extent = tokens[1].extent + self.assertIsInstance(extent, SourceRange) + + self.assertEqual(extent.start.offset, 4) + self.assertEqual(extent.end.offset, 7) Index: cfe/trunk/bindings/python/tests/cindex/test_translation_unit.py =================================================================== --- cfe/trunk/bindings/python/tests/cindex/test_translation_unit.py +++ cfe/trunk/bindings/python/tests/cindex/test_translation_unit.py @@ -1,6 +1,7 @@ import gc import os import tempfile +import unittest from clang.cindex import CursorKind from clang.cindex import Cursor @@ -14,83 +15,9 @@ from .util import get_cursor from .util import get_tu -kInputsDir = os.path.join(os.path.dirname(__file__), 'INPUTS') -def test_spelling(): - path = os.path.join(kInputsDir, 'hello.cpp') - tu = TranslationUnit.from_source(path) - assert tu.spelling == path - -def test_cursor(): - path = os.path.join(kInputsDir, 'hello.cpp') - tu = get_tu(path) - c = tu.cursor - assert isinstance(c, Cursor) - assert c.kind is CursorKind.TRANSLATION_UNIT - -def test_parse_arguments(): - path = os.path.join(kInputsDir, 'parse_arguments.c') - tu = TranslationUnit.from_source(path, ['-DDECL_ONE=hello', '-DDECL_TWO=hi']) - spellings = [c.spelling for c in tu.cursor.get_children()] - assert spellings[-2] == 'hello' - assert spellings[-1] == 'hi' - -def test_reparse_arguments(): - path = os.path.join(kInputsDir, 'parse_arguments.c') - tu = TranslationUnit.from_source(path, ['-DDECL_ONE=hello', '-DDECL_TWO=hi']) - tu.reparse() - spellings = [c.spelling for c in tu.cursor.get_children()] - assert spellings[-2] == 'hello' - assert spellings[-1] == 'hi' - -def test_unsaved_files(): - tu = TranslationUnit.from_source('fake.c', ['-I./'], unsaved_files = [ - ('fake.c', """ -#include "fake.h" -int x; -int SOME_DEFINE; -"""), - ('./fake.h', """ -#define SOME_DEFINE y -""") - ]) - spellings = [c.spelling for c in tu.cursor.get_children()] - assert spellings[-2] == 'x' - assert spellings[-1] == 'y' - -def test_unsaved_files_2(): - try: - from StringIO import StringIO - except: - from io import StringIO - tu = TranslationUnit.from_source('fake.c', unsaved_files = [ - ('fake.c', StringIO('int x;'))]) - spellings = [c.spelling for c in tu.cursor.get_children()] - assert spellings[-1] == 'x' - -def normpaths_equal(path1, path2): - """ Compares two paths for equality after normalizing them with - os.path.normpath - """ - return os.path.normpath(path1) == os.path.normpath(path2) +kInputsDir = os.path.join(os.path.dirname(__file__), 'INPUTS') -def test_includes(): - def eq(expected, actual): - if not actual.is_input_file: - return normpaths_equal(expected[0], actual.source.name) and \ - normpaths_equal(expected[1], actual.include.name) - else: - return normpaths_equal(expected[1], actual.include.name) - - src = os.path.join(kInputsDir, 'include.cpp') - h1 = os.path.join(kInputsDir, "header1.h") - h2 = os.path.join(kInputsDir, "header2.h") - h3 = os.path.join(kInputsDir, "header3.h") - inc = [(src, h1), (h1, h3), (src, h2), (h2, h3)] - - tu = TranslationUnit.from_source(src) - for i in zip(inc, tu.get_includes()): - assert eq(i[0], i[1]) def save_tu(tu): """Convenience API to save a TranslationUnit to a file. @@ -102,153 +29,227 @@ return path -def test_save(): - """Ensure TranslationUnit.save() works.""" - - tu = get_tu('int foo();') - - path = save_tu(tu) - assert os.path.exists(path) - assert os.path.getsize(path) > 0 - os.unlink(path) -def test_save_translation_errors(): - """Ensure that saving to an invalid directory raises.""" - - tu = get_tu('int foo();') - - path = '/does/not/exist/llvm-test.ast' - assert not os.path.exists(os.path.dirname(path)) +class TestTranslationUnit(unittest.TestCase): + def test_spelling(self): + path = os.path.join(kInputsDir, 'hello.cpp') + tu = TranslationUnit.from_source(path) + self.assertEqual(tu.spelling, path) - try: - tu.save(path) - assert False - except TranslationUnitSaveError as ex: + def test_cursor(self): + path = os.path.join(kInputsDir, 'hello.cpp') + tu = get_tu(path) + c = tu.cursor + self.assertIsInstance(c, Cursor) + self.assertIs(c.kind, CursorKind.TRANSLATION_UNIT) + + def test_parse_arguments(self): + path = os.path.join(kInputsDir, 'parse_arguments.c') + tu = TranslationUnit.from_source(path, ['-DDECL_ONE=hello', '-DDECL_TWO=hi']) + spellings = [c.spelling for c in tu.cursor.get_children()] + self.assertEqual(spellings[-2], 'hello') + self.assertEqual(spellings[-1], 'hi') + + def test_reparse_arguments(self): + path = os.path.join(kInputsDir, 'parse_arguments.c') + tu = TranslationUnit.from_source(path, ['-DDECL_ONE=hello', '-DDECL_TWO=hi']) + tu.reparse() + spellings = [c.spelling for c in tu.cursor.get_children()] + self.assertEqual(spellings[-2], 'hello') + self.assertEqual(spellings[-1], 'hi') + + def test_unsaved_files(self): + tu = TranslationUnit.from_source('fake.c', ['-I./'], unsaved_files = [ + ('fake.c', """ +#include "fake.h" +int x; +int SOME_DEFINE; +"""), + ('./fake.h', """ +#define SOME_DEFINE y +""") + ]) + spellings = [c.spelling for c in tu.cursor.get_children()] + self.assertEqual(spellings[-2], 'x') + self.assertEqual(spellings[-1], 'y') + + def test_unsaved_files_2(self): + try: + from StringIO import StringIO + except: + from io import StringIO + tu = TranslationUnit.from_source('fake.c', unsaved_files = [ + ('fake.c', StringIO('int x;'))]) + spellings = [c.spelling for c in tu.cursor.get_children()] + self.assertEqual(spellings[-1], 'x') + + def assert_normpaths_equal(self, path1, path2): + """ Compares two paths for equality after normalizing them with + os.path.normpath + """ + self.assertEqual(os.path.normpath(path1), + os.path.normpath(path2)) + + def test_includes(self): + def eq(expected, actual): + if not actual.is_input_file: + self.assert_normpaths_equal(expected[0], actual.source.name) + self.assert_normpaths_equal(expected[1], actual.include.name) + else: + self.assert_normpaths_equal(expected[1], actual.include.name) + + src = os.path.join(kInputsDir, 'include.cpp') + h1 = os.path.join(kInputsDir, "header1.h") + h2 = os.path.join(kInputsDir, "header2.h") + h3 = os.path.join(kInputsDir, "header3.h") + inc = [(src, h1), (h1, h3), (src, h2), (h2, h3)] + + tu = TranslationUnit.from_source(src) + for i in zip(inc, tu.get_includes()): + eq(i[0], i[1]) + + def test_save(self): + """Ensure TranslationUnit.save() works.""" + + tu = get_tu('int foo();') + + path = save_tu(tu) + self.assertTrue(os.path.exists(path)) + self.assertGreater(os.path.getsize(path), 0) + os.unlink(path) + + def test_save_translation_errors(self): + """Ensure that saving to an invalid directory raises.""" + + tu = get_tu('int foo();') + + path = '/does/not/exist/llvm-test.ast' + self.assertFalse(os.path.exists(os.path.dirname(path))) + + with self.assertRaises(TranslationUnitSaveError) as cm: + tu.save(path) + ex = cm.exception expected = TranslationUnitSaveError.ERROR_UNKNOWN - assert ex.save_error == expected + self.assertEqual(ex.save_error, expected) -def test_load(): - """Ensure TranslationUnits can be constructed from saved files.""" + def test_load(self): + """Ensure TranslationUnits can be constructed from saved files.""" - tu = get_tu('int foo();') - assert len(tu.diagnostics) == 0 - path = save_tu(tu) - - assert os.path.exists(path) - assert os.path.getsize(path) > 0 - - tu2 = TranslationUnit.from_ast_file(filename=path) - assert len(tu2.diagnostics) == 0 - - foo = get_cursor(tu2, 'foo') - assert foo is not None - - # Just in case there is an open file descriptor somewhere. - del tu2 - - os.unlink(path) - -def test_index_parse(): - path = os.path.join(kInputsDir, 'hello.cpp') - index = Index.create() - tu = index.parse(path) - assert isinstance(tu, TranslationUnit) - -def test_get_file(): - """Ensure tu.get_file() works appropriately.""" - - tu = get_tu('int foo();') - - f = tu.get_file('t.c') - assert isinstance(f, File) - assert f.name == 't.c' - - try: - f = tu.get_file('foobar.cpp') - except: - pass - else: - assert False - -def test_get_source_location(): - """Ensure tu.get_source_location() works.""" - - tu = get_tu('int foo();') - - location = tu.get_location('t.c', 2) - assert isinstance(location, SourceLocation) - assert location.offset == 2 - assert location.file.name == 't.c' - - location = tu.get_location('t.c', (1, 3)) - assert isinstance(location, SourceLocation) - assert location.line == 1 - assert location.column == 3 - assert location.file.name == 't.c' - -def test_get_source_range(): - """Ensure tu.get_source_range() works.""" - - tu = get_tu('int foo();') - - r = tu.get_extent('t.c', (1,4)) - assert isinstance(r, SourceRange) - assert r.start.offset == 1 - assert r.end.offset == 4 - assert r.start.file.name == 't.c' - assert r.end.file.name == 't.c' - - r = tu.get_extent('t.c', ((1,2), (1,3))) - assert isinstance(r, SourceRange) - assert r.start.line == 1 - assert r.start.column == 2 - assert r.end.line == 1 - assert r.end.column == 3 - assert r.start.file.name == 't.c' - assert r.end.file.name == 't.c' - - start = tu.get_location('t.c', 0) - end = tu.get_location('t.c', 5) - - r = tu.get_extent('t.c', (start, end)) - assert isinstance(r, SourceRange) - assert r.start.offset == 0 - assert r.end.offset == 5 - assert r.start.file.name == 't.c' - assert r.end.file.name == 't.c' - -def test_get_tokens_gc(): - """Ensures get_tokens() works properly with garbage collection.""" - - tu = get_tu('int foo();') - r = tu.get_extent('t.c', (0, 10)) - tokens = list(tu.get_tokens(extent=r)) - - assert tokens[0].spelling == 'int' - gc.collect() - assert tokens[0].spelling == 'int' - - del tokens[1] - gc.collect() - assert tokens[0].spelling == 'int' - - # May trigger segfault if we don't do our job properly. - del tokens - gc.collect() - gc.collect() # Just in case. - -def test_fail_from_source(): - path = os.path.join(kInputsDir, 'non-existent.cpp') - try: - tu = TranslationUnit.from_source(path) - except TranslationUnitLoadError: - tu = None - assert tu == None - -def test_fail_from_ast_file(): - path = os.path.join(kInputsDir, 'non-existent.ast') - try: - tu = TranslationUnit.from_ast_file(path) - except TranslationUnitLoadError: - tu = None - assert tu == None + tu = get_tu('int foo();') + self.assertEqual(len(tu.diagnostics), 0) + path = save_tu(tu) + + self.assertTrue(os.path.exists(path)) + self.assertGreater(os.path.getsize(path), 0) + + tu2 = TranslationUnit.from_ast_file(filename=path) + self.assertEqual(len(tu2.diagnostics), 0) + + foo = get_cursor(tu2, 'foo') + self.assertIsNotNone(foo) + + # Just in case there is an open file descriptor somewhere. + del tu2 + + os.unlink(path) + + def test_index_parse(self): + path = os.path.join(kInputsDir, 'hello.cpp') + index = Index.create() + tu = index.parse(path) + self.assertIsInstance(tu, TranslationUnit) + + def test_get_file(self): + """Ensure tu.get_file() works appropriately.""" + + tu = get_tu('int foo();') + + f = tu.get_file('t.c') + self.assertIsInstance(f, File) + self.assertEqual(f.name, 't.c') + + with self.assertRaises(Exception): + f = tu.get_file('foobar.cpp') + + def test_get_source_location(self): + """Ensure tu.get_source_location() works.""" + + tu = get_tu('int foo();') + + location = tu.get_location('t.c', 2) + self.assertIsInstance(location, SourceLocation) + self.assertEqual(location.offset, 2) + self.assertEqual(location.file.name, 't.c') + + location = tu.get_location('t.c', (1, 3)) + self.assertIsInstance(location, SourceLocation) + self.assertEqual(location.line, 1) + self.assertEqual(location.column, 3) + self.assertEqual(location.file.name, 't.c') + + def test_get_source_range(self): + """Ensure tu.get_source_range() works.""" + + tu = get_tu('int foo();') + + r = tu.get_extent('t.c', (1,4)) + self.assertIsInstance(r, SourceRange) + self.assertEqual(r.start.offset, 1) + self.assertEqual(r.end.offset, 4) + self.assertEqual(r.start.file.name, 't.c') + self.assertEqual(r.end.file.name, 't.c') + + r = tu.get_extent('t.c', ((1,2), (1,3))) + self.assertIsInstance(r, SourceRange) + self.assertEqual(r.start.line, 1) + self.assertEqual(r.start.column, 2) + self.assertEqual(r.end.line, 1) + self.assertEqual(r.end.column, 3) + self.assertEqual(r.start.file.name, 't.c') + self.assertEqual(r.end.file.name, 't.c') + + start = tu.get_location('t.c', 0) + end = tu.get_location('t.c', 5) + + r = tu.get_extent('t.c', (start, end)) + self.assertIsInstance(r, SourceRange) + self.assertEqual(r.start.offset, 0) + self.assertEqual(r.end.offset, 5) + self.assertEqual(r.start.file.name, 't.c') + self.assertEqual(r.end.file.name, 't.c') + + def test_get_tokens_gc(self): + """Ensures get_tokens() works properly with garbage collection.""" + + tu = get_tu('int foo();') + r = tu.get_extent('t.c', (0, 10)) + tokens = list(tu.get_tokens(extent=r)) + + self.assertEqual(tokens[0].spelling, 'int') + gc.collect() + self.assertEqual(tokens[0].spelling, 'int') + + del tokens[1] + gc.collect() + self.assertEqual(tokens[0].spelling, 'int') + + # May trigger segfault if we don't do our job properly. + del tokens + gc.collect() + gc.collect() # Just in case. + + def test_fail_from_source(self): + path = os.path.join(kInputsDir, 'non-existent.cpp') + try: + tu = TranslationUnit.from_source(path) + except TranslationUnitLoadError: + tu = None + self.assertEqual(tu, None) + + def test_fail_from_ast_file(self): + path = os.path.join(kInputsDir, 'non-existent.ast') + try: + tu = TranslationUnit.from_ast_file(path) + except TranslationUnitLoadError: + tu = None + self.assertEqual(tu, None) Index: cfe/trunk/bindings/python/tests/cindex/test_type.py =================================================================== --- cfe/trunk/bindings/python/tests/cindex/test_type.py +++ cfe/trunk/bindings/python/tests/cindex/test_type.py @@ -1,12 +1,13 @@ import gc +import unittest from clang.cindex import CursorKind from clang.cindex import TranslationUnit from clang.cindex import TypeKind -from nose.tools import raises from .util import get_cursor from .util import get_tu + kInput = """\ typedef int I; @@ -24,400 +25,414 @@ """ -def test_a_struct(): - tu = get_tu(kInput) - - teststruct = get_cursor(tu, 'teststruct') - assert teststruct is not None, "Could not find teststruct." - fields = list(teststruct.get_children()) - assert all(x.kind == CursorKind.FIELD_DECL for x in fields) - assert all(x.translation_unit is not None for x in fields) - - assert fields[0].spelling == 'a' - assert not fields[0].type.is_const_qualified() - assert fields[0].type.kind == TypeKind.INT - assert fields[0].type.get_canonical().kind == TypeKind.INT - assert fields[0].type.get_typedef_name() == '' - - assert fields[1].spelling == 'b' - assert not fields[1].type.is_const_qualified() - assert fields[1].type.kind == TypeKind.TYPEDEF - assert fields[1].type.get_canonical().kind == TypeKind.INT - assert fields[1].type.get_declaration().spelling == 'I' - assert fields[1].type.get_typedef_name() == 'I' - - assert fields[2].spelling == 'c' - assert not fields[2].type.is_const_qualified() - assert fields[2].type.kind == TypeKind.LONG - assert fields[2].type.get_canonical().kind == TypeKind.LONG - assert fields[2].type.get_typedef_name() == '' - - assert fields[3].spelling == 'd' - assert not fields[3].type.is_const_qualified() - assert fields[3].type.kind == TypeKind.ULONG - assert fields[3].type.get_canonical().kind == TypeKind.ULONG - assert fields[3].type.get_typedef_name() == '' - - assert fields[4].spelling == 'e' - assert not fields[4].type.is_const_qualified() - assert fields[4].type.kind == TypeKind.LONG - assert fields[4].type.get_canonical().kind == TypeKind.LONG - assert fields[4].type.get_typedef_name() == '' - - assert fields[5].spelling == 'f' - assert fields[5].type.is_const_qualified() - assert fields[5].type.kind == TypeKind.INT - assert fields[5].type.get_canonical().kind == TypeKind.INT - assert fields[5].type.get_typedef_name() == '' - - assert fields[6].spelling == 'g' - assert not fields[6].type.is_const_qualified() - assert fields[6].type.kind == TypeKind.POINTER - assert fields[6].type.get_pointee().kind == TypeKind.INT - assert fields[6].type.get_typedef_name() == '' - - assert fields[7].spelling == 'h' - assert not fields[7].type.is_const_qualified() - assert fields[7].type.kind == TypeKind.POINTER - assert fields[7].type.get_pointee().kind == TypeKind.POINTER - assert fields[7].type.get_pointee().get_pointee().kind == TypeKind.POINTER - assert fields[7].type.get_pointee().get_pointee().get_pointee().kind == TypeKind.INT - assert fields[7].type.get_typedef_name() == '' - -def test_references(): - """Ensure that a Type maintains a reference to a TranslationUnit.""" - - tu = get_tu('int x;') - children = list(tu.cursor.get_children()) - assert len(children) > 0 - - cursor = children[0] - t = cursor.type - - assert isinstance(t.translation_unit, TranslationUnit) - - # Delete main TranslationUnit reference and force a GC. - del tu - gc.collect() - assert isinstance(t.translation_unit, TranslationUnit) - - # If the TU was destroyed, this should cause a segfault. - decl = t.get_declaration() constarrayInput=""" struct teststruct { void *A[2]; }; """ -def testConstantArray(): - tu = get_tu(constarrayInput) - teststruct = get_cursor(tu, 'teststruct') - assert teststruct is not None, "Didn't find teststruct??" - fields = list(teststruct.get_children()) - assert fields[0].spelling == 'A' - assert fields[0].type.kind == TypeKind.CONSTANTARRAY - assert fields[0].type.get_array_element_type() is not None - assert fields[0].type.get_array_element_type().kind == TypeKind.POINTER - assert fields[0].type.get_array_size() == 2 - -def test_equal(): - """Ensure equivalence operators work on Type.""" - source = 'int a; int b; void *v;' - tu = get_tu(source) - - a = get_cursor(tu, 'a') - b = get_cursor(tu, 'b') - v = get_cursor(tu, 'v') - - assert a is not None - assert b is not None - assert v is not None - - assert a.type == b.type - assert a.type != v.type - - assert a.type != None - assert a.type != 'foo' - -def test_type_spelling(): - """Ensure Type.spelling works.""" - tu = get_tu('int c[5]; void f(int i[]); int x; int v[x];') - c = get_cursor(tu, 'c') - i = get_cursor(tu, 'i') - x = get_cursor(tu, 'x') - v = get_cursor(tu, 'v') - assert c is not None - assert i is not None - assert x is not None - assert v is not None - assert c.type.spelling == "int [5]" - assert i.type.spelling == "int []" - assert x.type.spelling == "int" - assert v.type.spelling == "int [x]" - -def test_typekind_spelling(): - """Ensure TypeKind.spelling works.""" - tu = get_tu('int a;') - a = get_cursor(tu, 'a') - - assert a is not None - assert a.type.kind.spelling == 'Int' - -def test_function_argument_types(): - """Ensure that Type.argument_types() works as expected.""" - tu = get_tu('void f(int, int);') - f = get_cursor(tu, 'f') - assert f is not None - - args = f.type.argument_types() - assert args is not None - assert len(args) == 2 - - t0 = args[0] - assert t0 is not None - assert t0.kind == TypeKind.INT - - t1 = args[1] - assert t1 is not None - assert t1.kind == TypeKind.INT - - args2 = list(args) - assert len(args2) == 2 - assert t0 == args2[0] - assert t1 == args2[1] - -@raises(TypeError) -def test_argument_types_string_key(): - """Ensure that non-int keys raise a TypeError.""" - tu = get_tu('void f(int, int);') - f = get_cursor(tu, 'f') - assert f is not None - - args = f.type.argument_types() - assert len(args) == 2 - - args['foo'] - -@raises(IndexError) -def test_argument_types_negative_index(): - """Ensure that negative indexes on argument_types Raises an IndexError.""" - tu = get_tu('void f(int, int);') - f = get_cursor(tu, 'f') - args = f.type.argument_types() - - args[-1] - -@raises(IndexError) -def test_argument_types_overflow_index(): - """Ensure that indexes beyond the length of Type.argument_types() raise.""" - tu = get_tu('void f(int, int);') - f = get_cursor(tu, 'f') - args = f.type.argument_types() - - args[2] - -@raises(Exception) -def test_argument_types_invalid_type(): - """Ensure that obtaining argument_types on a Type without them raises.""" - tu = get_tu('int i;') - i = get_cursor(tu, 'i') - assert i is not None - - i.type.argument_types() - -def test_is_pod(): - """Ensure Type.is_pod() works.""" - tu = get_tu('int i; void f();') - i = get_cursor(tu, 'i') - f = get_cursor(tu, 'f') - - assert i is not None - assert f is not None - assert i.type.is_pod() - assert not f.type.is_pod() +class TestType(unittest.TestCase): + def test_a_struct(self): + tu = get_tu(kInput) -def test_function_variadic(): - """Ensure Type.is_function_variadic works.""" + teststruct = get_cursor(tu, 'teststruct') + self.assertIsNotNone(teststruct, "Could not find teststruct.") + fields = list(teststruct.get_children()) - source =""" -#include + self.assertEqual(fields[0].kind, CursorKind.FIELD_DECL) + self.assertIsNotNone(fields[0].translation_unit) + self.assertEqual(fields[0].spelling, 'a') + self.assertFalse(fields[0].type.is_const_qualified()) + self.assertEqual(fields[0].type.kind, TypeKind.INT) + self.assertEqual(fields[0].type.get_canonical().kind, TypeKind.INT) + self.assertEqual(fields[0].type.get_typedef_name(), '') + + self.assertEqual(fields[1].kind, CursorKind.FIELD_DECL) + self.assertIsNotNone(fields[1].translation_unit) + self.assertEqual(fields[1].spelling, 'b') + self.assertFalse(fields[1].type.is_const_qualified()) + self.assertEqual(fields[1].type.kind, TypeKind.TYPEDEF) + self.assertEqual(fields[1].type.get_canonical().kind, TypeKind.INT) + self.assertEqual(fields[1].type.get_declaration().spelling, 'I') + self.assertEqual(fields[1].type.get_typedef_name(), 'I') + + self.assertEqual(fields[2].kind, CursorKind.FIELD_DECL) + self.assertIsNotNone(fields[2].translation_unit) + self.assertEqual(fields[2].spelling, 'c') + self.assertFalse(fields[2].type.is_const_qualified()) + self.assertEqual(fields[2].type.kind, TypeKind.LONG) + self.assertEqual(fields[2].type.get_canonical().kind, TypeKind.LONG) + self.assertEqual(fields[2].type.get_typedef_name(), '') + + self.assertEqual(fields[3].kind, CursorKind.FIELD_DECL) + self.assertIsNotNone(fields[3].translation_unit) + self.assertEqual(fields[3].spelling, 'd') + self.assertFalse(fields[3].type.is_const_qualified()) + self.assertEqual(fields[3].type.kind, TypeKind.ULONG) + self.assertEqual(fields[3].type.get_canonical().kind, TypeKind.ULONG) + self.assertEqual(fields[3].type.get_typedef_name(), '') + + self.assertEqual(fields[4].kind, CursorKind.FIELD_DECL) + self.assertIsNotNone(fields[4].translation_unit) + self.assertEqual(fields[4].spelling, 'e') + self.assertFalse(fields[4].type.is_const_qualified()) + self.assertEqual(fields[4].type.kind, TypeKind.LONG) + self.assertEqual(fields[4].type.get_canonical().kind, TypeKind.LONG) + self.assertEqual(fields[4].type.get_typedef_name(), '') + + self.assertEqual(fields[5].kind, CursorKind.FIELD_DECL) + self.assertIsNotNone(fields[5].translation_unit) + self.assertEqual(fields[5].spelling, 'f') + self.assertTrue(fields[5].type.is_const_qualified()) + self.assertEqual(fields[5].type.kind, TypeKind.INT) + self.assertEqual(fields[5].type.get_canonical().kind, TypeKind.INT) + self.assertEqual(fields[5].type.get_typedef_name(), '') + + self.assertEqual(fields[6].kind, CursorKind.FIELD_DECL) + self.assertIsNotNone(fields[6].translation_unit) + self.assertEqual(fields[6].spelling, 'g') + self.assertFalse(fields[6].type.is_const_qualified()) + self.assertEqual(fields[6].type.kind, TypeKind.POINTER) + self.assertEqual(fields[6].type.get_pointee().kind, TypeKind.INT) + self.assertEqual(fields[6].type.get_typedef_name(), '') + + self.assertEqual(fields[7].kind, CursorKind.FIELD_DECL) + self.assertIsNotNone(fields[7].translation_unit) + self.assertEqual(fields[7].spelling, 'h') + self.assertFalse(fields[7].type.is_const_qualified()) + self.assertEqual(fields[7].type.kind, TypeKind.POINTER) + self.assertEqual(fields[7].type.get_pointee().kind, TypeKind.POINTER) + self.assertEqual(fields[7].type.get_pointee().get_pointee().kind, TypeKind.POINTER) + self.assertEqual(fields[7].type.get_pointee().get_pointee().get_pointee().kind, TypeKind.INT) + self.assertEqual(fields[7].type.get_typedef_name(), '') + + def test_references(self): + """Ensure that a Type maintains a reference to a TranslationUnit.""" + + tu = get_tu('int x;') + children = list(tu.cursor.get_children()) + self.assertGreater(len(children), 0) + + cursor = children[0] + t = cursor.type + + self.assertIsInstance(t.translation_unit, TranslationUnit) + + # Delete main TranslationUnit reference and force a GC. + del tu + gc.collect() + self.assertIsInstance(t.translation_unit, TranslationUnit) -void foo(int a, ...); -void bar(int a, int b); -""" + # If the TU was destroyed, this should cause a segfault. + decl = t.get_declaration() - tu = get_tu(source) - foo = get_cursor(tu, 'foo') - bar = get_cursor(tu, 'bar') - - assert foo is not None - assert bar is not None - - assert isinstance(foo.type.is_function_variadic(), bool) - assert foo.type.is_function_variadic() - assert not bar.type.is_function_variadic() - -def test_element_type(): - """Ensure Type.element_type works.""" - tu = get_tu('int c[5]; void f(int i[]); int x; int v[x];') - c = get_cursor(tu, 'c') - i = get_cursor(tu, 'i') - v = get_cursor(tu, 'v') - assert c is not None - assert i is not None - assert v is not None - - assert c.type.kind == TypeKind.CONSTANTARRAY - assert c.type.element_type.kind == TypeKind.INT - assert i.type.kind == TypeKind.INCOMPLETEARRAY - assert i.type.element_type.kind == TypeKind.INT - assert v.type.kind == TypeKind.VARIABLEARRAY - assert v.type.element_type.kind == TypeKind.INT - -@raises(Exception) -def test_invalid_element_type(): - """Ensure Type.element_type raises if type doesn't have elements.""" - tu = get_tu('int i;') - i = get_cursor(tu, 'i') - assert i is not None - i.element_type - -def test_element_count(): - """Ensure Type.element_count works.""" - tu = get_tu('int i[5]; int j;') - i = get_cursor(tu, 'i') - j = get_cursor(tu, 'j') - - assert i is not None - assert j is not None - - assert i.type.element_count == 5 - - try: - j.type.element_count - assert False - except: - assert True - -def test_is_volatile_qualified(): - """Ensure Type.is_volatile_qualified works.""" - - tu = get_tu('volatile int i = 4; int j = 2;') - - i = get_cursor(tu, 'i') - j = get_cursor(tu, 'j') - - assert i is not None - assert j is not None - - assert isinstance(i.type.is_volatile_qualified(), bool) - assert i.type.is_volatile_qualified() - assert not j.type.is_volatile_qualified() - -def test_is_restrict_qualified(): - """Ensure Type.is_restrict_qualified works.""" - - tu = get_tu('struct s { void * restrict i; void * j; };') - - i = get_cursor(tu, 'i') - j = get_cursor(tu, 'j') - - assert i is not None - assert j is not None - - assert isinstance(i.type.is_restrict_qualified(), bool) - assert i.type.is_restrict_qualified() - assert not j.type.is_restrict_qualified() - -def test_record_layout(): - """Ensure Cursor.type.get_size, Cursor.type.get_align and - Cursor.type.get_offset works.""" - - source =""" -struct a { - long a1; - long a2:3; - long a3:4; - long long a4; -}; -""" - tries=[(['-target','i386-linux-gnu'],(4,16,0,32,35,64)), - (['-target','nvptx64-unknown-unknown'],(8,24,0,64,67,128)), - (['-target','i386-pc-win32'],(8,16,0,32,35,64)), - (['-target','msp430-none-none'],(2,14,0,32,35,48))] - for flags, values in tries: - align,total,a1,a2,a3,a4 = values + def testConstantArray(self): + tu = get_tu(constarrayInput) - tu = get_tu(source, flags=flags) - teststruct = get_cursor(tu, 'a') + teststruct = get_cursor(tu, 'teststruct') + self.assertIsNotNone(teststruct, "Didn't find teststruct??") fields = list(teststruct.get_children()) + self.assertEqual(fields[0].spelling, 'A') + self.assertEqual(fields[0].type.kind, TypeKind.CONSTANTARRAY) + self.assertIsNotNone(fields[0].type.get_array_element_type()) + self.assertEqual(fields[0].type.get_array_element_type().kind, TypeKind.POINTER) + self.assertEqual(fields[0].type.get_array_size(), 2) + + def test_equal(self): + """Ensure equivalence operators work on Type.""" + source = 'int a; int b; void *v;' + tu = get_tu(source) + + a = get_cursor(tu, 'a') + b = get_cursor(tu, 'b') + v = get_cursor(tu, 'v') + + self.assertIsNotNone(a) + self.assertIsNotNone(b) + self.assertIsNotNone(v) + + self.assertEqual(a.type, b.type) + self.assertNotEqual(a.type, v.type) + + self.assertNotEqual(a.type, None) + self.assertNotEqual(a.type, 'foo') + + def test_type_spelling(self): + """Ensure Type.spelling works.""" + tu = get_tu('int c[5]; void f(int i[]); int x; int v[x];') + c = get_cursor(tu, 'c') + i = get_cursor(tu, 'i') + x = get_cursor(tu, 'x') + v = get_cursor(tu, 'v') + self.assertIsNotNone(c) + self.assertIsNotNone(i) + self.assertIsNotNone(x) + self.assertIsNotNone(v) + self.assertEqual(c.type.spelling, "int [5]") + self.assertEqual(i.type.spelling, "int []") + self.assertEqual(x.type.spelling, "int") + self.assertEqual(v.type.spelling, "int [x]") + + def test_typekind_spelling(self): + """Ensure TypeKind.spelling works.""" + tu = get_tu('int a;') + a = get_cursor(tu, 'a') + + self.assertIsNotNone(a) + self.assertEqual(a.type.kind.spelling, 'Int') + + def test_function_argument_types(self): + """Ensure that Type.argument_types() works as expected.""" + tu = get_tu('void f(int, int);') + f = get_cursor(tu, 'f') + self.assertIsNotNone(f) + + args = f.type.argument_types() + self.assertIsNotNone(args) + self.assertEqual(len(args), 2) + + t0 = args[0] + self.assertIsNotNone(t0) + self.assertEqual(t0.kind, TypeKind.INT) + + t1 = args[1] + self.assertIsNotNone(t1) + self.assertEqual(t1.kind, TypeKind.INT) + + args2 = list(args) + self.assertEqual(len(args2), 2) + self.assertEqual(t0, args2[0]) + self.assertEqual(t1, args2[1]) + + def test_argument_types_string_key(self): + """Ensure that non-int keys raise a TypeError.""" + tu = get_tu('void f(int, int);') + f = get_cursor(tu, 'f') + self.assertIsNotNone(f) + + args = f.type.argument_types() + self.assertEqual(len(args), 2) + + with self.assertRaises(TypeError): + args['foo'] + + def test_argument_types_negative_index(self): + """Ensure that negative indexes on argument_types Raises an IndexError.""" + tu = get_tu('void f(int, int);') + f = get_cursor(tu, 'f') + args = f.type.argument_types() + + with self.assertRaises(IndexError): + args[-1] + + def test_argument_types_overflow_index(self): + """Ensure that indexes beyond the length of Type.argument_types() raise.""" + tu = get_tu('void f(int, int);') + f = get_cursor(tu, 'f') + args = f.type.argument_types() + + with self.assertRaises(IndexError): + args[2] + + def test_argument_types_invalid_type(self): + """Ensure that obtaining argument_types on a Type without them raises.""" + tu = get_tu('int i;') + i = get_cursor(tu, 'i') + self.assertIsNotNone(i) + + with self.assertRaises(Exception): + i.type.argument_types() + + def test_is_pod(self): + """Ensure Type.is_pod() works.""" + tu = get_tu('int i; void f();') + i = get_cursor(tu, 'i') + f = get_cursor(tu, 'f') + + self.assertIsNotNone(i) + self.assertIsNotNone(f) + + self.assertTrue(i.type.is_pod()) + self.assertFalse(f.type.is_pod()) + + def test_function_variadic(self): + """Ensure Type.is_function_variadic works.""" + + source =""" +#include + + void foo(int a, ...); + void bar(int a, int b); + """ - assert teststruct.type.get_align() == align - assert teststruct.type.get_size() == total - assert teststruct.type.get_offset(fields[0].spelling) == a1 - assert teststruct.type.get_offset(fields[1].spelling) == a2 - assert teststruct.type.get_offset(fields[2].spelling) == a3 - assert teststruct.type.get_offset(fields[3].spelling) == a4 - assert fields[0].is_bitfield() == False - assert fields[1].is_bitfield() == True - assert fields[1].get_bitfield_width() == 3 - assert fields[2].is_bitfield() == True - assert fields[2].get_bitfield_width() == 4 - assert fields[3].is_bitfield() == False - -def test_offset(): - """Ensure Cursor.get_record_field_offset works in anonymous records""" - source=""" -struct Test { - struct {int a;} typeanon; - struct { - int bariton; - union { - int foo; - }; - }; - int bar; -};""" - tries=[(['-target','i386-linux-gnu'],(4,16,0,32,64,96)), - (['-target','nvptx64-unknown-unknown'],(8,24,0,32,64,96)), - (['-target','i386-pc-win32'],(8,16,0,32,64,96)), - (['-target','msp430-none-none'],(2,14,0,32,64,96))] - for flags, values in tries: - align,total,f1,bariton,foo,bar = values tu = get_tu(source) - teststruct = get_cursor(tu, 'Test') - children = list(teststruct.get_children()) - fields = list(teststruct.type.get_fields()) - assert children[0].kind == CursorKind.STRUCT_DECL - assert children[0].spelling != "typeanon" - assert children[1].spelling == "typeanon" - assert fields[0].kind == CursorKind.FIELD_DECL - assert fields[1].kind == CursorKind.FIELD_DECL - assert fields[1].is_anonymous() - assert teststruct.type.get_offset("typeanon") == f1 - assert teststruct.type.get_offset("bariton") == bariton - assert teststruct.type.get_offset("foo") == foo - assert teststruct.type.get_offset("bar") == bar - - -def test_decay(): - """Ensure decayed types are handled as the original type""" - - tu = get_tu("void foo(int a[]);") - foo = get_cursor(tu, 'foo') - a = foo.type.argument_types()[0] - - assert a.kind == TypeKind.INCOMPLETEARRAY - assert a.element_type.kind == TypeKind.INT - assert a.get_canonical().kind == TypeKind.INCOMPLETEARRAY - -def test_addrspace(): - """Ensure the address space can be queried""" - tu = get_tu('__attribute__((address_space(2))) int testInteger = 3;', 'c') + foo = get_cursor(tu, 'foo') + bar = get_cursor(tu, 'bar') + + self.assertIsNotNone(foo) + self.assertIsNotNone(bar) + + self.assertIsInstance(foo.type.is_function_variadic(), bool) + self.assertTrue(foo.type.is_function_variadic()) + self.assertFalse(bar.type.is_function_variadic()) + + def test_element_type(self): + """Ensure Type.element_type works.""" + tu = get_tu('int c[5]; void f(int i[]); int x; int v[x];') + c = get_cursor(tu, 'c') + i = get_cursor(tu, 'i') + v = get_cursor(tu, 'v') + self.assertIsNotNone(c) + self.assertIsNotNone(i) + self.assertIsNotNone(v) + + self.assertEqual(c.type.kind, TypeKind.CONSTANTARRAY) + self.assertEqual(c.type.element_type.kind, TypeKind.INT) + self.assertEqual(i.type.kind, TypeKind.INCOMPLETEARRAY) + self.assertEqual(i.type.element_type.kind, TypeKind.INT) + self.assertEqual(v.type.kind, TypeKind.VARIABLEARRAY) + self.assertEqual(v.type.element_type.kind, TypeKind.INT) + + def test_invalid_element_type(self): + """Ensure Type.element_type raises if type doesn't have elements.""" + tu = get_tu('int i;') + i = get_cursor(tu, 'i') + self.assertIsNotNone(i) + with self.assertRaises(Exception): + i.element_type + + def test_element_count(self): + """Ensure Type.element_count works.""" + tu = get_tu('int i[5]; int j;') + i = get_cursor(tu, 'i') + j = get_cursor(tu, 'j') + + self.assertIsNotNone(i) + self.assertIsNotNone(j) + + self.assertEqual(i.type.element_count, 5) + + with self.assertRaises(Exception): + j.type.element_count + + def test_is_volatile_qualified(self): + """Ensure Type.is_volatile_qualified works.""" + + tu = get_tu('volatile int i = 4; int j = 2;') + + i = get_cursor(tu, 'i') + j = get_cursor(tu, 'j') + + self.assertIsNotNone(i) + self.assertIsNotNone(j) + + self.assertIsInstance(i.type.is_volatile_qualified(), bool) + self.assertTrue(i.type.is_volatile_qualified()) + self.assertFalse(j.type.is_volatile_qualified()) + + def test_is_restrict_qualified(self): + """Ensure Type.is_restrict_qualified works.""" + + tu = get_tu('struct s { void * restrict i; void * j; };') + + i = get_cursor(tu, 'i') + j = get_cursor(tu, 'j') + + self.assertIsNotNone(i) + self.assertIsNotNone(j) + + self.assertIsInstance(i.type.is_restrict_qualified(), bool) + self.assertTrue(i.type.is_restrict_qualified()) + self.assertFalse(j.type.is_restrict_qualified()) + + def test_record_layout(self): + """Ensure Cursor.type.get_size, Cursor.type.get_align and + Cursor.type.get_offset works.""" + + source =""" + struct a { + long a1; + long a2:3; + long a3:4; + long long a4; + }; + """ + tries=[(['-target','i386-linux-gnu'],(4,16,0,32,35,64)), + (['-target','nvptx64-unknown-unknown'],(8,24,0,64,67,128)), + (['-target','i386-pc-win32'],(8,16,0,32,35,64)), + (['-target','msp430-none-none'],(2,14,0,32,35,48))] + for flags, values in tries: + align,total,a1,a2,a3,a4 = values + + tu = get_tu(source, flags=flags) + teststruct = get_cursor(tu, 'a') + fields = list(teststruct.get_children()) + + self.assertEqual(teststruct.type.get_align(), align) + self.assertEqual(teststruct.type.get_size(), total) + self.assertEqual(teststruct.type.get_offset(fields[0].spelling), a1) + self.assertEqual(teststruct.type.get_offset(fields[1].spelling), a2) + self.assertEqual(teststruct.type.get_offset(fields[2].spelling), a3) + self.assertEqual(teststruct.type.get_offset(fields[3].spelling), a4) + self.assertEqual(fields[0].is_bitfield(), False) + self.assertEqual(fields[1].is_bitfield(), True) + self.assertEqual(fields[1].get_bitfield_width(), 3) + self.assertEqual(fields[2].is_bitfield(), True) + self.assertEqual(fields[2].get_bitfield_width(), 4) + self.assertEqual(fields[3].is_bitfield(), False) + + def test_offset(self): + """Ensure Cursor.get_record_field_offset works in anonymous records""" + source=""" + struct Test { + struct {int a;} typeanon; + struct { + int bariton; + union { + int foo; + }; + }; + int bar; + };""" + tries=[(['-target','i386-linux-gnu'],(4,16,0,32,64,96)), + (['-target','nvptx64-unknown-unknown'],(8,24,0,32,64,96)), + (['-target','i386-pc-win32'],(8,16,0,32,64,96)), + (['-target','msp430-none-none'],(2,14,0,32,64,96))] + for flags, values in tries: + align,total,f1,bariton,foo,bar = values + tu = get_tu(source) + teststruct = get_cursor(tu, 'Test') + children = list(teststruct.get_children()) + fields = list(teststruct.type.get_fields()) + self.assertEqual(children[0].kind, CursorKind.STRUCT_DECL) + self.assertNotEqual(children[0].spelling, "typeanon") + self.assertEqual(children[1].spelling, "typeanon") + self.assertEqual(fields[0].kind, CursorKind.FIELD_DECL) + self.assertEqual(fields[1].kind, CursorKind.FIELD_DECL) + self.assertTrue(fields[1].is_anonymous()) + self.assertEqual(teststruct.type.get_offset("typeanon"), f1) + self.assertEqual(teststruct.type.get_offset("bariton"), bariton) + self.assertEqual(teststruct.type.get_offset("foo"), foo) + self.assertEqual(teststruct.type.get_offset("bar"), bar) + + def test_decay(self): + """Ensure decayed types are handled as the original type""" + + tu = get_tu("void foo(int a[]);") + foo = get_cursor(tu, 'foo') + a = foo.type.argument_types()[0] + + self.assertEqual(a.kind, TypeKind.INCOMPLETEARRAY) + self.assertEqual(a.element_type.kind, TypeKind.INT) + self.assertEqual(a.get_canonical().kind, TypeKind.INCOMPLETEARRAY) + + def test_addrspace(self): + """Ensure the address space can be queried""" + tu = get_tu('__attribute__((address_space(2))) int testInteger = 3;', 'c') - testInteger = get_cursor(tu, 'testInteger') + testInteger = get_cursor(tu, 'testInteger') - assert testInteger is not None, "Could not find testInteger." - assert testInteger.type.get_address_space() == 2 + self.assertIsNotNone(testInteger, "Could not find testInteger.") + self.assertEqual(testInteger.type.get_address_space(), 2)