PageRenderTime 68ms CodeModel.GetById 20ms RepoModel.GetById 1ms app.codeStats 0ms

/test/test_cxxtest.py

https://github.com/kindkaktus/cxxtest
Python | 899 lines | 886 code | 4 blank | 9 comment | 6 complexity | a79102ae10dd79f40f1a10c668df32d3 MD5 | raw file
Possible License(s): LGPL-3.0
  1. #-------------------------------------------------------------------------
  2. # CxxTest: A lightweight C++ unit testing library.
  3. # Copyright (c) 2008 Sandia Corporation.
  4. # This software is distributed under the LGPL License v3
  5. # For more information, see the COPYING file in the top CxxTest directory.
  6. # Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
  7. # the U.S. Government retains certain rights in this software.
  8. #-------------------------------------------------------------------------
  9. import time
  10. import sys
  11. import os
  12. import os.path
  13. import glob
  14. import difflib
  15. import subprocess
  16. import re
  17. import string
  18. if sys.version_info < (2,7):
  19. import unittest2 as unittest
  20. else:
  21. import unittest
  22. try:
  23. import ply
  24. ply_available=True
  25. except:
  26. ply_available=False
  27. try:
  28. import cxxtest
  29. cxxtest_available=True
  30. import cxxtest.cxxtestgen
  31. except:
  32. cxxtest_available=False
  33. currdir = os.path.dirname(os.path.abspath(__file__))+os.sep
  34. sampledir = os.path.dirname(os.path.dirname(currdir))+'/sample'+os.sep
  35. cxxtestdir = os.path.dirname(os.path.dirname(currdir))+os.sep
  36. compilerre = re.compile("^(?P<path>[^:]+)(?P<rest>:.*)$")
  37. dirre = re.compile("^([^%s]*/)*" % re.escape(os.sep))
  38. xmlre = re.compile("\"(?P<path>[^\"]*/[^\"]*)\"")
  39. datere = re.compile("date=\"[^\"]*\"")
  40. # Headers from the cxxtest/sample directory
  41. samples = ' '.join(file for file in sorted(glob.glob(sampledir+'*.h')))
  42. guiInputs=currdir+'../sample/gui/GreenYellowRed.h'
  43. if sys.platform.startswith('win'):
  44. target_suffix = '.exe'
  45. command_separator = ' && '
  46. cxxtestdir = '/'.join(cxxtestdir.split('\\'))
  47. remove_extra_path_prefixes_on_windows = True
  48. else:
  49. target_suffix = ''
  50. command_separator = '; '
  51. remove_extra_path_prefixes_on_windows = False
  52. def find(filename, executable=False, isfile=True, validate=None):
  53. #
  54. # Use the PATH environment if it is defined and not empty
  55. #
  56. if "PATH" in os.environ and os.environ["PATH"] != "":
  57. search_path = os.environ['PATH'].split(os.pathsep)
  58. else:
  59. search_path = os.defpath.split(os.pathsep)
  60. for path in search_path:
  61. test_fname = os.path.join(path, filename)
  62. if os.path.exists(test_fname) \
  63. and (not isfile or os.path.isfile(test_fname)) \
  64. and (not executable or os.access(test_fname, os.X_OK)):
  65. return os.path.abspath(test_fname)
  66. return None
  67. def join_commands(command_one, command_two):
  68. return command_separator.join([command_one, command_two])
  69. _available = {}
  70. def available(compiler, exe_option):
  71. if (compiler,exe_option) in _available:
  72. return _available[compiler,exe_option]
  73. cmd = join_commands("cd %s" % currdir,
  74. "%s %s %s %s > %s 2>&1" % (compiler, exe_option, currdir+'anything', currdir+'anything.cpp', currdir+'anything.log'))
  75. print("Testing for compiler "+compiler)
  76. print("Command: "+cmd)
  77. status = subprocess.call(cmd, shell=True)
  78. executable = currdir+'anything'+target_suffix
  79. flag = status == 0 and os.path.exists(executable)
  80. os.remove(currdir+'anything.log')
  81. if os.path.exists(executable):
  82. os.remove(executable)
  83. print("Status: "+str(flag))
  84. _available[compiler,exe_option] = flag
  85. return flag
  86. def remove_absdir(filename):
  87. INPUT=open(filename, 'r')
  88. lines = [line.strip() for line in INPUT]
  89. INPUT.close()
  90. OUTPUT=open(filename, 'w')
  91. for line in lines:
  92. # remove basedir at front of line
  93. match = compilerre.match(line) # see if we can remove the basedir
  94. if match:
  95. parts = match.groupdict()
  96. line = dirre.sub("", parts['path']) + parts['rest']
  97. OUTPUT.write(line+'\n')
  98. OUTPUT.close()
  99. def normalize_line_for_diff(line):
  100. # add spaces around {}<>()
  101. line = re.sub("[{}<>()]", r" \0 ", line)
  102. # beginnig and ending whitespace
  103. line = line.strip()
  104. # remove all whitespace
  105. # and leave a single space
  106. line = ' '.join(line.split())
  107. # remove spaces around "="
  108. line = re.sub(" ?= ?", "=", line)
  109. # remove all absolute path prefixes
  110. line = ''.join(line.split(cxxtestdir))
  111. if remove_extra_path_prefixes_on_windows:
  112. # Take care of inconsistent path prefixes like
  113. # "e:\path\to\cxxtest\test", "E:/path/to/cxxtest/test" etc
  114. # in output.
  115. line = ''.join(line.split(os.path.normcase(cxxtestdir)))
  116. line = ''.join(line.split(os.path.normpath(cxxtestdir)))
  117. # And some extra relative paths left behind
  118. line= re.sub(r'^.*[\\/]([^\\/]+\.(h|cpp))', r'\1', line)
  119. # for xml, remove prefixes from everything that looks like a
  120. # file path inside ""
  121. line = xmlre.sub(
  122. lambda match: '"'+re.sub("^[^/]+/", "", match.group(1))+'"',
  123. line
  124. )
  125. # Remove date info
  126. line = datere.sub( lambda match: 'date=""', line)
  127. return line
  128. def make_diff_readable(diff):
  129. i = 0
  130. while i+1 < len(diff):
  131. if diff[i][0] == '-' and diff[i+1][0] == '+':
  132. l1 = diff[i]
  133. l2 = diff[i+1]
  134. for j in range(1, min([len(l1), len(l2)])):
  135. if l1[j] != l2[j]:
  136. if j > 4:
  137. j = j-2;
  138. l1 = l1[j:]
  139. l2 = l2[j:]
  140. diff[i] = '-(...)' + l1
  141. diff[i+1] = '+(...)' + l2
  142. break
  143. i+=1
  144. def file_diff(filename1, filename2, filtered_reader):
  145. remove_absdir(filename1)
  146. remove_absdir(filename2)
  147. #
  148. INPUT=open(filename1, 'r')
  149. lines1 = list(filtered_reader(INPUT))
  150. INPUT.close()
  151. #
  152. INPUT=open(filename2, 'r')
  153. lines2 = list(filtered_reader(INPUT))
  154. INPUT.close()
  155. #
  156. diff = list(difflib.unified_diff(lines2, lines1,
  157. fromfile=filename2, tofile=filename1))
  158. if diff:
  159. make_diff_readable(diff)
  160. raise Exception("ERROR: \n\n%s\n\n%s\n\n" % (lines1, lines2))
  161. diff = '\n'.join(diff)
  162. return diff
  163. class BaseTestCase(object):
  164. fog=''
  165. valgrind=''
  166. cxxtest_import=False
  167. def setUp(self):
  168. sys.stderr.write("("+self.__class__.__name__+") ")
  169. self.passed=False
  170. self.prefix=''
  171. self.py_out=''
  172. self.py_cpp=''
  173. self.px_pre=''
  174. self.px_out=''
  175. self.build_log=''
  176. self.build_target=''
  177. def tearDown(self):
  178. if not self.passed:
  179. return
  180. files = []
  181. if os.path.exists(self.py_out):
  182. files.append(self.py_out)
  183. if os.path.exists(self.py_cpp) and not 'CXXTEST_GCOV_FLAGS' in os.environ:
  184. files.append(self.py_cpp)
  185. if os.path.exists(self.px_pre):
  186. files.append(self.px_pre)
  187. if os.path.exists(self.px_out):
  188. files.append(self.px_out)
  189. if os.path.exists(self.build_log):
  190. files.append(self.build_log)
  191. if os.path.exists(self.build_target) and not 'CXXTEST_GCOV_FLAGS' in os.environ:
  192. files.append(self.build_target)
  193. for file in files:
  194. try:
  195. os.remove(file)
  196. except:
  197. time.sleep(2)
  198. try:
  199. os.remove(file)
  200. except:
  201. print( "Error removing file '%s'" % file)
  202. # This is a "generator" that just reads a file and normalizes the lines
  203. def file_filter(self, file):
  204. for line in file:
  205. yield normalize_line_for_diff(line)
  206. def check_if_supported(self, filename, msg):
  207. target=currdir+'check'+'px'+target_suffix
  208. log=currdir+'check'+'_build.log'
  209. cmd = join_commands("cd %s" % currdir,
  210. "%s %s %s %s. %s%s../ %s > %s 2>&1" % (self.compiler, self.exe_option, target, self.include_option, self.include_option, currdir, filename, log))
  211. status = subprocess.call(cmd, shell=True)
  212. os.remove(log)
  213. if status != 0 or not os.path.exists(target):
  214. self.skipTest(msg)
  215. os.remove(target)
  216. def init(self, prefix):
  217. #
  218. self.prefix = self.__class__.__name__+'_'+prefix
  219. self.py_out = currdir+self.prefix+'_py.out'
  220. self.py_cpp = currdir+self.prefix+'_py.cpp'
  221. self.px_pre = currdir+self.prefix+'_px.pre'
  222. self.px_out = currdir+self.prefix+'_px.out'
  223. self.build_log = currdir+self.prefix+'_build.log'
  224. self.build_target = currdir+self.prefix+'px'+target_suffix
  225. def check_root(self, prefix='', output=None):
  226. self.init(prefix)
  227. args = "--have-eh --abort-on-fail --root --error-printer"
  228. if self.cxxtest_import:
  229. os.chdir(currdir)
  230. cxxtest.cxxtestgen.main(['cxxtestgen', self.fog, '-o', self.py_cpp]+re.split('[ ]+',args), True)
  231. else:
  232. cmd = join_commands("cd %s" % currdir,
  233. "%s %s../bin/cxxtestgen %s -o %s %s > %s 2>&1" % (sys.executable, currdir, self.fog, self.py_cpp, args, self.py_out))
  234. status = subprocess.call(cmd, shell=True)
  235. self.assertEqual(status, 0, 'Error executing cxxtestgen')
  236. #
  237. files = [self.py_cpp]
  238. for i in [1,2]:
  239. args = "--have-eh --abort-on-fail --part Part%s.h" % str(i)
  240. file = currdir+self.prefix+'_py%s.cpp' % str(i)
  241. files.append(file)
  242. if self.cxxtest_import:
  243. os.chdir(currdir)
  244. cxxtest.cxxtestgen.main(['cxxtestgen', self.fog, '-o', file]+re.split('[ ]+',args), True)
  245. else:
  246. cmd = join_commands("cd %s" % currdir,
  247. "%s %s../bin/cxxtestgen %s -o %s %s > %s 2>&1" % (sys.executable, currdir, self.fog, file, args, self.py_out))
  248. status = subprocess.call(cmd, shell=True)
  249. self.assertEqual(status, 0, 'Error executing cxxtestgen')
  250. #
  251. cmd = join_commands("cd %s" % currdir,
  252. "%s %s %s %s. %s%s../ %s > %s 2>&1" % (self.compiler, self.exe_option, self.build_target, self.include_option, self.include_option, currdir, ' '.join(files), self.build_log))
  253. status = subprocess.call(cmd, shell=True)
  254. for file in files:
  255. if os.path.exists(file):
  256. os.remove(file)
  257. self.assertEqual(status, 0, 'Error executing command: '+cmd)
  258. #
  259. cmd = join_commands("cd %s" % currdir,
  260. "%s %s -v > %s 2>&1" % (self.valgrind, self.build_target, self.px_pre))
  261. status = subprocess.call(cmd, shell=True)
  262. OUTPUT = open(self.px_pre,'a')
  263. OUTPUT.write('Error level = '+str(status)+'\n')
  264. OUTPUT.close()
  265. diffstr = file_diff(self.px_pre, currdir+output, self.file_filter)
  266. if not diffstr == '':
  267. self.fail("Unexpected differences in output:\n"+diffstr)
  268. if self.valgrind != '':
  269. self.parse_valgrind(self.px_pre)
  270. #
  271. self.passed=True
  272. def compile(self, prefix='', args=None, compile='', output=None, main=None, failGen=False, run=None, logfile=None, failBuild=False):
  273. """Run cxxtestgen and compile the code that is generated"""
  274. self.init(prefix)
  275. #
  276. if self.cxxtest_import:
  277. try:
  278. os.chdir(currdir)
  279. status = cxxtest.cxxtestgen.main(['cxxtestgen', self.fog, '-o', self.py_cpp]+re.split('[ ]+',args), True)
  280. except:
  281. status = 1
  282. else:
  283. cmd = join_commands("cd %s" % currdir,
  284. "%s %s../bin/cxxtestgen %s -o %s %s > %s 2>&1" % (sys.executable, currdir, self.fog, self.py_cpp, args, self.py_out))
  285. status = subprocess.call(cmd, shell=True)
  286. if failGen:
  287. if status == 0:
  288. self.fail('Expected cxxtestgen to fail.')
  289. else:
  290. self.passed=True
  291. return
  292. if not self.cxxtest_import:
  293. self.assertEqual(status, 0, 'Error executing command: '+cmd)
  294. #
  295. if not main is None:
  296. # Compile with main
  297. cmd = join_commands("cd %s" % currdir,
  298. "%s %s %s %s. %s%s../ %s main.cpp %s > %s 2>&1" % (self.compiler, self.exe_option, self.build_target, self.include_option, self.include_option, currdir, compile, self.py_cpp, self.build_log))
  299. else:
  300. # Compile without main
  301. cmd = join_commands("cd %s" % currdir,
  302. "%s %s %s %s. %s%s../ %s %s > %s 2>&1" % (self.compiler, self.exe_option, self.build_target, self.include_option, self.include_option, currdir, compile, self.py_cpp, self.build_log))
  303. status = subprocess.call(cmd, shell=True)
  304. if failBuild:
  305. if status == 0:
  306. self.fail('Expected compiler to fail.')
  307. else:
  308. self.passed=True
  309. return
  310. else:
  311. self.assertEqual(status, 0, 'Error executing command: '+cmd)
  312. #
  313. if compile == '' and not output is None:
  314. if run is None:
  315. cmd = join_commands("cd %s" % currdir,
  316. "%s %s -v > %s 2>&1" % (self.valgrind, self.build_target, self.px_pre))
  317. else:
  318. cmd = run % (self.valgrind, self.build_target, self.px_pre)
  319. status = subprocess.call(cmd, shell=True)
  320. OUTPUT = open(self.px_pre,'a')
  321. OUTPUT.write('Error level = '+str(status)+'\n')
  322. OUTPUT.close()
  323. if logfile is None:
  324. diffstr = file_diff(self.px_pre, currdir+output, self.file_filter)
  325. else:
  326. diffstr = file_diff(currdir+logfile, currdir+output, self.file_filter)
  327. if not diffstr == '':
  328. self.fail("Unexpected differences in output:\n"+diffstr)
  329. if self.valgrind != '':
  330. self.parse_valgrind(self.px_pre)
  331. if not logfile is None:
  332. os.remove(currdir+logfile)
  333. #
  334. if compile == '' and output is None and os.path.exists(self.py_cpp):
  335. self.fail("Output cpp file %s should not have been generated." % self.py_cpp)
  336. #
  337. self.passed=True
  338. #
  339. # Tests for cxxtestgen
  340. #
  341. def test_root_or_part(self):
  342. """Root/Part"""
  343. self.check_root(prefix='root_or_part', output="parts.out")
  344. def test_root_plus_part(self):
  345. """Root + Part"""
  346. self.compile(prefix='root_plus_part', args="--error-printer --root --part "+samples, output="error.out")
  347. def test_wildcard(self):
  348. """Wildcard input"""
  349. self.compile(prefix='wildcard', args='../sample/*.h', main=True, output="wildcard.out")
  350. def test_stdio_printer(self):
  351. """Stdio printer"""
  352. self.compile(prefix='stdio_printer', args="--runner=StdioPrinter "+samples, output="error.out")
  353. def test_paren_printer(self):
  354. """Paren printer"""
  355. self.compile(prefix='paren_printer', args="--runner=ParenPrinter "+samples, output="paren.out")
  356. def test_yn_runner(self):
  357. """Yes/No runner"""
  358. self.compile(prefix='yn_runner', args="--runner=YesNoRunner "+samples, output="runner.out")
  359. def test_no_static_init(self):
  360. """No static init"""
  361. self.compile(prefix='no_static_init', args="--error-printer --no-static-init "+samples, output="error.out")
  362. def test_samples_file(self):
  363. """Samples file"""
  364. # Create a file with the list of sample files
  365. OUTPUT = open(currdir+'Samples.txt','w')
  366. for line in sorted(glob.glob(sampledir+'*.h')):
  367. OUTPUT.write(line+'\n')
  368. OUTPUT.close()
  369. self.compile(prefix='samples_file', args="--error-printer --headers Samples.txt", output="error.out")
  370. os.remove(currdir+'Samples.txt')
  371. def test_have_std(self):
  372. """Have Std"""
  373. self.compile(prefix='have_std', args="--runner=StdioPrinter --have-std HaveStd.h", output="std.out")
  374. def test_comments(self):
  375. """Comments"""
  376. self.compile(prefix='comments', args="--error-printer Comments.h", output="comments.out")
  377. def test_longlong(self):
  378. """Long long"""
  379. self.check_if_supported('longlong.cpp', "Long long is not supported by this compiler")
  380. self.compile(prefix='longlong', args="--error-printer --longlong=\"long long\" LongLong.h", output="longlong.out")
  381. def test_int64(self):
  382. """Int64"""
  383. self.check_if_supported('int64.cpp', "64-bit integers are not supported by this compiler")
  384. self.compile(prefix='int64', args="--error-printer --longlong=__int64 Int64.h", output="int64.out")
  385. def test_include(self):
  386. """Include"""
  387. self.compile(prefix='include', args="--include=VoidTraits.h --include=LongTraits.h --error-printer IncludeTest.h", output="include.out")
  388. #
  389. # Template file tests
  390. #
  391. def test_preamble(self):
  392. """Preamble"""
  393. self.compile(prefix='preamble', args="--template=preamble.tpl "+samples, output="preamble.out")
  394. def test_activate_all(self):
  395. """Activate all"""
  396. self.compile(prefix='activate_all', args="--template=activate.tpl "+samples, output="error.out")
  397. def test_only_suite(self):
  398. """Only Suite"""
  399. self.compile(prefix='only_suite', args="--template=%s../sample/only.tpl %s" % (currdir, samples), run="%s %s SimpleTest > %s 2>&1", output="suite.out")
  400. def test_only_test(self):
  401. """Only Test"""
  402. self.compile(prefix='only_test', args="--template=%s../sample/only.tpl %s" % (currdir, samples), run="%s %s SimpleTest testAddition > %s 2>&1", output="suite_test.out")
  403. def test_have_std_tpl(self):
  404. """Have Std - Template"""
  405. self.compile(prefix='have_std_tpl', args="--template=HaveStd.tpl HaveStd.h", output="std.out")
  406. def test_exceptions_tpl(self):
  407. """Exceptions - Template"""
  408. self.compile(prefix='exceptions_tpl', args="--template=HaveEH.tpl "+self.ehNormals, output="eh_normals.out")
  409. #
  410. # Test cases which do not require exception handling
  411. #
  412. def test_no_errors(self):
  413. """No errors"""
  414. self.compile(prefix='no_errors', args="--error-printer GoodSuite.h", output="good.out")
  415. def test_infinite_values(self):
  416. """Infinite values"""
  417. self.compile(prefix='infinite_values', args="--error-printer --have-std TestNonFinite.h", output="infinite.out")
  418. def test_max_dump_size(self):
  419. """Max dump size"""
  420. self.compile(prefix='max_dump_size', args="--error-printer --include=MaxDump.h DynamicMax.h SameData.h", output='max.out')
  421. def test_wide_char(self):
  422. """Wide char"""
  423. self.check_if_supported('wchar.cpp', "The file wchar.cpp is not supported.")
  424. self.compile(prefix='wide_char', args="--error-printer WideCharTest.h", output="wchar.out")
  425. #def test_factor(self):
  426. #"""Factor"""
  427. #self.compile(prefix='factor', args="--error-printer --factor Factor.h", output="factor.out")
  428. def test_user_traits(self):
  429. """User traits"""
  430. self.compile(prefix='user_traits', args="--template=UserTraits.tpl UserTraits.h", output='user.out')
  431. normals = " ".join(currdir+file for file in ["LessThanEquals.h","Relation.h","DefaultTraits.h","DoubleCall.h","SameData.h","SameFiles.h","Tsm.h","TraitsTest.h","MockTest.h","SameZero.h"])
  432. def test_normal_behavior_xunit(self):
  433. """Normal Behavior with XUnit Output"""
  434. self.compile(prefix='normal_behavior_xunit', args="--xunit-printer "+self.normals, logfile='TEST-cxxtest.xml', output="normal.xml")
  435. def test_normal_behavior(self):
  436. """Normal Behavior"""
  437. self.compile(prefix='normal_behavior', args="--error-printer "+self.normals, output="normal.out")
  438. def test_normal_plus_abort(self):
  439. """Normal + Abort"""
  440. self.compile(prefix='normal_plus_abort', args="--error-printer --have-eh --abort-on-fail "+self.normals, output="abort.out")
  441. def test_stl_traits(self):
  442. """STL Traits"""
  443. self.check_if_supported('stpltpl.cpp', "The file stpltpl.cpp is not supported.")
  444. self.compile(prefix='stl_traits', args="--error-printer StlTraits.h", output="stl.out")
  445. def test_normal_behavior_world(self):
  446. """Normal Behavior with World"""
  447. self.compile(prefix='normal_behavior_world', args="--error-printer --world=myworld "+self.normals, output="world.out")
  448. #
  449. # Test cases which do require exception handling
  450. #
  451. def test_throw_wo_std(self):
  452. """Throw w/o Std"""
  453. self.compile(prefix='test_throw_wo_std', args="--template=ThrowNoStd.tpl ThrowNoStd.h", output='throw.out')
  454. ehNormals = "Exceptions.h DynamicAbort.h"
  455. def test_exceptions(self):
  456. """Exceptions"""
  457. self.compile(prefix='exceptions', args="--error-printer --have-eh "+self.ehNormals, output="eh_normals.out")
  458. def test_exceptions_plus_abort(self):
  459. """Exceptions plus abort"""
  460. self.compile(prefix='exceptions', args="--error-printer --abort-on-fail --have-eh DynamicAbort.h DeepAbort.h ThrowsAssert.h", output="eh_plus_abort.out")
  461. def test_default_abort(self):
  462. """Default abort"""
  463. self.compile(prefix='default_abort', args="--error-printer --include=DefaultAbort.h "+self.ehNormals+ " DeepAbort.h ThrowsAssert.h", output="default_abort.out")
  464. def test_default_no_abort(self):
  465. """Default no abort"""
  466. self.compile(prefix='default_no_abort', args="--error-printer "+self.ehNormals+" DeepAbort.h ThrowsAssert.h", output="default_abort.out")
  467. #
  468. # Global Fixtures
  469. #
  470. def test_global_fixtures(self):
  471. """Global fixtures"""
  472. self.compile(prefix='global_fixtures', args="--error-printer GlobalFixtures.h WorldFixtures.h", output="gfxs.out")
  473. def test_gf_suw_fails(self):
  474. """GF:SUW fails"""
  475. self.compile(prefix='gf_suw_fails', args="--error-printer SetUpWorldFails.h", output="suwf.out")
  476. def test_gf_suw_error(self):
  477. """GF:SUW error"""
  478. self.compile(prefix='gf_suw_error', args="--error-printer SetUpWorldError.h", output="suwe.out")
  479. def test_gf_suw_throws(self):
  480. """GF:SUW throws"""
  481. self.compile(prefix='gf_suw_throws', args="--error-printer SetUpWorldThrows.h", output="suwt.out")
  482. def test_gf_su_fails(self):
  483. """GF:SU fails"""
  484. self.compile(prefix='gf_su_fails', args="--error-printer GfSetUpFails.h", output="gfsuf.out")
  485. def test_gf_su_throws(self):
  486. """GF:SU throws"""
  487. self.compile(prefix='gf_su_throws', args="--error-printer GfSetUpThrows.h", output="gfsut.out")
  488. def test_gf_td_fails(self):
  489. """GF:TD fails"""
  490. self.compile(prefix='gf_td_fails', args="--error-printer GfTearDownFails.h", output="gftdf.out")
  491. def test_gf_td_throws(self):
  492. """GF:TD throws"""
  493. self.compile(prefix='gf_td_throws', args="--error-printer GfTearDownThrows.h", output="gftdt.out")
  494. def test_gf_tdw_fails(self):
  495. """GF:TDW fails"""
  496. self.compile(prefix='gf_tdw_fails', args="--error-printer TearDownWorldFails.h", output="tdwf.out")
  497. def test_gf_tdw_throws(self):
  498. """GF:TDW throws"""
  499. self.compile(prefix='gf_tdw_throws', args="--error-printer TearDownWorldThrows.h", output="tdwt.out")
  500. #
  501. # GUI
  502. #
  503. def test_gui(self):
  504. """GUI"""
  505. self.compile(prefix='gui', args='--gui=DummyGui %s' % guiInputs, output ="gui.out")
  506. def test_gui_runner(self):
  507. """GUI + runner"""
  508. self.compile(prefix='gui_runner', args="--gui=DummyGui --runner=ParenPrinter %s" % guiInputs, output="gui_paren.out")
  509. def test_qt_gui(self):
  510. """QT GUI"""
  511. self.compile(prefix='qt_gui', args="--gui=QtGui GoodSuite.h", compile=self.qtFlags)
  512. def test_win32_gui(self):
  513. """Win32 GUI"""
  514. self.compile(prefix='win32_gui', args="--gui=Win32Gui GoodSuite.h", compile=self.w32Flags)
  515. def test_win32_unicode(self):
  516. """Win32 Unicode"""
  517. self.compile(prefix='win32_unicode', args="--gui=Win32Gui GoodSuite.h", compile=self.w32Flags+' -DUNICODE')
  518. def test_x11_gui(self):
  519. """X11 GUI"""
  520. self.check_if_supported('wchar.cpp', "Cannot compile wchar.cpp")
  521. self.compile(prefix='x11_gui', args="--gui=X11Gui GoodSuite.h", compile=self.x11Flags)
  522. #
  523. # Tests for when the compiler doesn't support exceptions
  524. #
  525. def test_no_exceptions(self):
  526. """No exceptions"""
  527. if self.no_eh_option is None:
  528. self.skipTest("This compiler does not have an exception handling option")
  529. self.compile(prefix='no_exceptions', args='--runner=StdioPrinter NoEh.h', output="no_eh.out", compile=self.no_eh_option)
  530. def test_force_no_eh(self):
  531. """Force no EH"""
  532. if self.no_eh_option is None:
  533. self.skipTest("This compiler does not have an exception handling option")
  534. self.compile(prefix="force_no_eh", args="--runner=StdioPrinter --no-eh ForceNoEh.h", output="no_eh.out", compile=self.no_eh_option)
  535. #
  536. # Invalid input to cxxtestgen
  537. #
  538. def test_no_tests(self):
  539. """No tests"""
  540. self.compile(prefix='no_tests', args='EmptySuite.h', failGen=True)
  541. def test_missing_input(self):
  542. """Missing input"""
  543. self.compile(prefix='missing_input', args='--template=NoSuchFile.h', failGen=True)
  544. def test_missing_template(self):
  545. """Missing template"""
  546. self.compile(prefix='missing_template', args='--template=NoSuchFile.h '+samples, failGen=True)
  547. def test_inheritance(self):
  548. """Test relying on inheritance"""
  549. self.compile(prefix='inheritance', args='--error-printer InheritedTest.h', output='inheritance_old.out')
  550. #
  551. # Tests that illustrate differences between the different C++ parsers
  552. #
  553. def test_namespace1(self):
  554. """Nested namespace declarations"""
  555. if self.fog == '':
  556. self.compile(prefix='namespace1', args='Namespace1.h', main=True, failBuild=True)
  557. else:
  558. self.compile(prefix='namespace1', args='Namespace1.h', main=True, output="namespace.out")
  559. def test_namespace2(self):
  560. """Explicit namespace declarations"""
  561. self.compile(prefix='namespace2', args='Namespace2.h', main=True, output="namespace.out")
  562. def test_inheritance(self):
  563. """Test relying on inheritance"""
  564. if self.fog == '':
  565. self.compile(prefix='inheritance', args='--error-printer InheritedTest.h', failGen=True)
  566. else:
  567. self.compile(prefix='inheritance', args='--error-printer InheritedTest.h', output='inheritance.out')
  568. def test_simple_inheritance(self):
  569. """Test relying on simple inheritance"""
  570. self.compile(prefix='simple_inheritance', args='--error-printer SimpleInheritedTest.h', output='simple_inheritance.out')
  571. def test_simple_inheritance2(self):
  572. """Test relying on simple inheritance (2)"""
  573. if self.fog == '':
  574. self.compile(prefix='simple_inheritance2', args='--error-printer SimpleInheritedTest2.h', failGen=True)
  575. else:
  576. self.compile(prefix='simple_inheritance2', args='--error-printer SimpleInheritedTest2.h', output='simple_inheritance2.out')
  577. def test_comments2(self):
  578. """Comments2"""
  579. if self.fog == '':
  580. self.compile(prefix='comments2', args="--error-printer Comments2.h", failBuild=True)
  581. else:
  582. self.compile(prefix='comments2', args="--error-printer Comments2.h", output='comments2.out')
  583. def test_cpp_template1(self):
  584. """C++ Templates"""
  585. if self.fog == '':
  586. self.compile(prefix='cpp_template1', args="--error-printer CppTemplateTest.h", failGen=True)
  587. else:
  588. self.compile(prefix='cpp_template1', args="--error-printer CppTemplateTest.h", output='template.out')
  589. def test_bad1(self):
  590. """BadTest1"""
  591. if self.fog == '':
  592. self.compile(prefix='bad1', args="--error-printer BadTest.h", failGen=True)
  593. else:
  594. self.compile(prefix='bad1', args="--error-printer BadTest.h", output='bad.out')
  595. class TestCpp(BaseTestCase, unittest.TestCase):
  596. # Compiler specifics
  597. exe_option = '-o'
  598. include_option = '-I'
  599. compiler='c++ -Wall -W -Werror -g'
  600. no_eh_option = None
  601. qtFlags='-Ifake'
  602. x11Flags='-Ifake'
  603. w32Flags='-Ifake'
  604. def run(self, *args, **kwds):
  605. if available('c++', '-o'):
  606. return unittest.TestCase.run(self, *args, **kwds)
  607. def setUp(self):
  608. BaseTestCase.setUp(self)
  609. def tearDown(self):
  610. BaseTestCase.tearDown(self)
  611. class TestCppFOG(TestCpp):
  612. fog='-f'
  613. def run(self, *args, **kwds):
  614. if ply_available:
  615. return TestCpp.run(self, *args, **kwds)
  616. class TestGpp(BaseTestCase, unittest.TestCase):
  617. # Compiler specifics
  618. exe_option = '-o'
  619. include_option = '-I'
  620. compiler='g++ -g -ansi -pedantic -Wmissing-declarations -Werror -Wall -W -Wshadow -Woverloaded-virtual -Wnon-virtual-dtor -Wreorder -Wsign-promo %s' % os.environ.get('CXXTEST_GCOV_FLAGS','')
  621. no_eh_option = '-fno-exceptions'
  622. qtFlags='-Ifake'
  623. x11Flags='-Ifake'
  624. w32Flags='-Ifake'
  625. def run(self, *args, **kwds):
  626. if available('g++', '-o'):
  627. return unittest.TestCase.run(self, *args, **kwds)
  628. def setUp(self):
  629. BaseTestCase.setUp(self)
  630. def tearDown(self):
  631. BaseTestCase.tearDown(self)
  632. class TestGppPy(TestGpp):
  633. def run(self, *args, **kwds):
  634. if cxxtest_available:
  635. self.cxxtest_import = True
  636. status = TestGpp.run(self, *args, **kwds)
  637. self.cxxtest_import = False
  638. return status
  639. class TestGppFOG(TestGpp):
  640. fog='-f'
  641. def run(self, *args, **kwds):
  642. if ply_available:
  643. return TestGpp.run(self, *args, **kwds)
  644. class TestGppFOGPy(TestGppFOG):
  645. def run(self, *args, **kwds):
  646. if cxxtest_available:
  647. self.cxxtest_import = True
  648. status = TestGppFOG.run(self, *args, **kwds)
  649. self.cxxtest_import = False
  650. return status
  651. class TestGppValgrind(TestGpp):
  652. valgrind='valgrind --tool=memcheck --leak-check=yes'
  653. def file_filter(self, file):
  654. for line in file:
  655. if line.startswith('=='):
  656. continue
  657. # Some *very* old versions of valgrind produce lines like:
  658. # free: in use at exit: 0 bytes in 0 blocks.
  659. # free: 2 allocs, 2 frees, 360 bytes allocated.
  660. if line.startswith('free: '):
  661. continue
  662. yield normalize_line_for_diff(line)
  663. def run(self, *args, **kwds):
  664. if find('valgrind') is None:
  665. return
  666. return TestGpp.run(self, *args, **kwds)
  667. def parse_valgrind(self, fname):
  668. # There is a well-known leak on Mac OSX platforms...
  669. if sys.platform == 'darwin':
  670. min_leak = 16
  671. else:
  672. min_leak = 0
  673. #
  674. INPUT = open(fname, 'r')
  675. for line in INPUT:
  676. if not line.startswith('=='):
  677. continue
  678. tokens = re.split('[ \t]+', line)
  679. if len(tokens) < 4:
  680. continue
  681. if tokens[1] == 'definitely' and tokens[2] == 'lost:':
  682. if eval(tokens[3]) > min_leak:
  683. self.fail("Valgrind Error: "+ ' '.join(tokens[1:]))
  684. if tokens[1] == 'possibly' and tokens[2] == 'lost:':
  685. if eval(tokens[3]) > min_leak:
  686. self.fail("Valgrind Error: "+ ' '.join(tokens[1:]))
  687. class TestGppFOGValgrind(TestGppValgrind):
  688. fog='-f'
  689. def run(self, *args, **kwds):
  690. if ply_available:
  691. return TestGppValgrind.run(self, *args, **kwds)
  692. class TestClang(BaseTestCase, unittest.TestCase):
  693. # Compiler specifics
  694. exe_option = '-o'
  695. include_option = '-I'
  696. compiler='clang++ -v -g -Wall -W -Wshadow -Woverloaded-virtual -Wnon-virtual-dtor -Wreorder -Wsign-promo'
  697. no_eh_option = '-fno-exceptions'
  698. qtFlags='-Ifake'
  699. x11Flags='-Ifake'
  700. w32Flags='-Ifake'
  701. def run(self, *args, **kwds):
  702. if available('clang++', '-o'):
  703. return unittest.TestCase.run(self, *args, **kwds)
  704. def setUp(self):
  705. BaseTestCase.setUp(self)
  706. def tearDown(self):
  707. BaseTestCase.tearDown(self)
  708. class TestClangFOG(TestClang):
  709. fog='-f'
  710. def run(self, *args, **kwds):
  711. if ply_available:
  712. return TestClang.run(self, *args, **kwds)
  713. class TestCL(BaseTestCase, unittest.TestCase):
  714. # Compiler specifics
  715. exe_option = '-o'
  716. include_option = '-I'
  717. compiler='cl -nologo -GX -W4'# -WX'
  718. no_eh_option = '-GX-'
  719. qtFlags='-Ifake'
  720. x11Flags='-Ifake'
  721. w32Flags='-Ifake'
  722. def run(self, *args, **kwds):
  723. if available('cl', '-o'):
  724. return unittest.TestCase.run(self, *args, **kwds)
  725. def setUp(self):
  726. BaseTestCase.setUp(self)
  727. def tearDown(self):
  728. BaseTestCase.tearDown(self)
  729. class TestCLFOG(TestCL):
  730. fog='-f'
  731. def run(self, *args, **kwds):
  732. if ply_available:
  733. return TestCL.run(self, *args, **kwds)
  734. if __name__ == '__main__':
  735. unittest.main()