2020-09-04 15:29:19 +02:00
|
|
|
|
|
|
|
# python -m pytest test-clang-import.py
|
|
|
|
|
|
|
|
import os
|
|
|
|
import re
|
|
|
|
import subprocess
|
|
|
|
from testutils import create_gui_project_file, cppcheck
|
|
|
|
|
|
|
|
|
|
|
|
def get_debug_section(title, stdout):
|
|
|
|
s = re.sub(r'0x[0-9a-fA-F]+', '0x12345678', stdout)
|
|
|
|
s = re.sub(r'nestedIn: Struct', 'nestedIn: Class', s)
|
|
|
|
s = re.sub(r'classDef: struct', 'classDef: class', s)
|
|
|
|
s = re.sub(r'isInline: [a-z]+', 'isInline: ---', s)
|
|
|
|
s = re.sub(r'definedType: .*', 'definedType: ---', s)
|
|
|
|
s = re.sub(r'needInitialization: .*', 'needInitialization: ---', s)
|
|
|
|
s = re.sub(r'functionOf: .*', 'functionOf: ---', s)
|
|
|
|
s = re.sub(r'0x12345678 Struct', '0x12345678 Class', s)
|
2020-10-29 21:43:35 +01:00
|
|
|
|
|
|
|
if title == '##AST':
|
|
|
|
# TODO set types
|
|
|
|
s = re.sub(r"return '[a-zA-Z0-9: *]+'", "return", s)
|
|
|
|
|
2020-09-04 15:29:19 +02:00
|
|
|
pos1 = s.find(title)
|
|
|
|
assert pos1 > 0
|
|
|
|
pos1 = s.find('\n', pos1) + 1
|
|
|
|
assert pos1 > 0
|
|
|
|
pos2 = s.find("\n##", pos1)
|
|
|
|
if pos2 < 0:
|
|
|
|
return s[pos1:]
|
|
|
|
return s[pos1:pos2-1]
|
|
|
|
|
|
|
|
|
|
|
|
def check_symbol_database(code):
|
|
|
|
# Only compare symboldatabases if clang is found in PATH
|
|
|
|
try:
|
|
|
|
subprocess.call(['clang', '--version'])
|
|
|
|
except OSError:
|
|
|
|
return
|
|
|
|
|
|
|
|
testfile = 'test.cpp'
|
|
|
|
with open(testfile, 'w+t') as f:
|
|
|
|
f.write(code)
|
|
|
|
ret1, stdout1, stderr1 = cppcheck(['--clang', '--debug', '-v', testfile])
|
|
|
|
ret2, stdout2, stderr2 = cppcheck(['--debug', '-v', testfile])
|
|
|
|
os.remove(testfile)
|
|
|
|
assert get_debug_section('### Symbol database', stdout1) == get_debug_section('### Symbol database', stdout2)
|
|
|
|
|
|
|
|
|
2020-10-04 11:27:31 +02:00
|
|
|
def check_ast(code):
|
|
|
|
# Only compare syntax trees if clang is found in PATH
|
|
|
|
try:
|
|
|
|
subprocess.call(['clang', '--version'])
|
|
|
|
except OSError:
|
|
|
|
return
|
|
|
|
|
|
|
|
testfile = 'test.cpp'
|
|
|
|
with open(testfile, 'w+t') as f:
|
|
|
|
f.write(code)
|
|
|
|
ret1, stdout1, stderr1 = cppcheck(['--clang', '--debug', '-v', testfile])
|
|
|
|
ret2, stdout2, stderr2 = cppcheck(['--debug', '-v', testfile])
|
|
|
|
os.remove(testfile)
|
|
|
|
assert get_debug_section('##AST', stdout1) == get_debug_section('##AST', stdout2)
|
|
|
|
|
|
|
|
|
|
|
|
def todo_check_ast(code):
|
|
|
|
# Only compare syntax trees if clang is found in PATH
|
|
|
|
try:
|
|
|
|
subprocess.call(['clang', '--version'])
|
|
|
|
except OSError:
|
|
|
|
return
|
|
|
|
|
|
|
|
testfile = 'test.cpp'
|
|
|
|
with open(testfile, 'w+t') as f:
|
|
|
|
f.write(code)
|
|
|
|
ret1, stdout1, stderr1 = cppcheck(['--clang', '--debug', '-v', testfile])
|
|
|
|
ret2, stdout2, stderr2 = cppcheck(['--debug', '-v', testfile])
|
|
|
|
os.remove(testfile)
|
|
|
|
assert get_debug_section('##AST', stdout1) != get_debug_section('##AST', stdout2)
|
|
|
|
|
|
|
|
|
|
|
|
|
2020-10-06 19:06:10 +02:00
|
|
|
def test_symbol_database_1():
|
2020-09-04 15:29:19 +02:00
|
|
|
check_symbol_database('int main(){return 0;}')
|
|
|
|
|
2020-10-06 19:06:10 +02:00
|
|
|
def test_symbol_database_2():
|
2020-11-03 17:52:38 +01:00
|
|
|
check_symbol_database('struct Foo { void f(); }; void Foo::f() {}')
|
2020-09-04 15:29:19 +02:00
|
|
|
|
2020-10-06 19:06:10 +02:00
|
|
|
def test_symbol_database_3():
|
|
|
|
check_symbol_database('struct Fred { int a; }; int b; void f(int c, int d) { int e; }')
|
|
|
|
|
2020-10-31 17:43:36 +01:00
|
|
|
def test_symbol_database_4():
|
|
|
|
check_symbol_database('void f(const int x) {}')
|
|
|
|
|
2020-11-02 20:58:43 +01:00
|
|
|
def test_symbol_database_5():
|
|
|
|
check_symbol_database('void f(int);')
|
|
|
|
|
2020-11-03 17:52:38 +01:00
|
|
|
def test_symbol_database_6():
|
|
|
|
check_symbol_database('inline static int foo(int x) { return x; }')
|
|
|
|
|
2020-11-03 21:37:28 +01:00
|
|
|
def test_symbol_database_7():
|
|
|
|
check_symbol_database('struct S {int x;}; void f(struct S *s) {}')
|
|
|
|
|
2020-11-08 17:02:19 +01:00
|
|
|
def test_symbol_database_class_access_1():
|
|
|
|
check_symbol_database('class Fred { void foo ( ) {} } ;')
|
|
|
|
|
|
|
|
def test_symbol_database_class_access_2():
|
|
|
|
check_symbol_database('class Fred { protected: void foo ( ) {} } ;')
|
|
|
|
|
|
|
|
def test_symbol_database_class_access_3():
|
|
|
|
check_symbol_database('class Fred { public: void foo ( ) {} } ;')
|
|
|
|
|
2020-11-01 15:30:40 +01:00
|
|
|
def test_symbol_database_operator():
|
|
|
|
check_symbol_database('struct Fred { void operator=(int x); };')
|
|
|
|
|
2020-11-01 09:12:58 +01:00
|
|
|
def test_symbol_database_struct_1():
|
|
|
|
check_symbol_database('struct S {};')
|
|
|
|
|
2020-10-04 11:27:31 +02:00
|
|
|
def test_ast_calculations():
|
|
|
|
check_ast('int x = 5; int y = (x + 4) * 2;')
|
2020-10-04 20:02:19 +02:00
|
|
|
check_ast('long long dostuff(int x) { return x ? 3 : 5; }')
|
2020-10-04 11:27:31 +02:00
|
|
|
|
|
|
|
def test_ast_control_flow():
|
|
|
|
check_ast('void foo(int x) { if (x > 5){} }')
|
|
|
|
check_ast('int dostuff() { for (int x = 0; x < 10; x++); }')
|
2020-10-04 19:33:16 +02:00
|
|
|
check_ast('void foo(int x) { switch (x) {case 1: break; } }')
|
2020-10-09 07:54:16 +02:00
|
|
|
check_ast('void foo(int a, int b, int c) { foo(a,b,c); }')
|
2020-10-04 11:27:31 +02:00
|
|
|
|
2020-10-29 21:43:35 +01:00
|
|
|
def test_ast():
|
2020-11-07 18:12:47 +01:00
|
|
|
check_ast('struct S { int x; }; S* foo() { return new S(); }')
|
2020-09-04 15:29:19 +02:00
|
|
|
|