senfscons: Implement COMPILE_FAILS tests
g0dil [Sun, 13 Apr 2008 04:02:18 +0000 (04:02 +0000)]
git-svn-id: https://svn.berlios.de/svnroot/repos/senf/trunk@808 270642c3-0616-0410-b53a-bc976706d245

Console/Mainpage.dox
Console/ParsedCommand.test.cc
Utils/auto_unit_test.hh
senfscons/CompileCheck.py [new file with mode: 0644]
senfscons/SENFSCons.py

index 7323fbf..42187b7 100644 (file)
     ok
     server:/$ help test4
     Usage:
-        test4 n:unsigned [text:string]
+        test4 [n:unsigned] text:string
     
     With:
         n         Number of repetitions
index c850ca8..3487d9c 100644 (file)
@@ -223,6 +223,19 @@ BOOST_AUTO_UNIT_TEST(memberParsedCommand)
         BOOST_CHECK_EQUAL( ss.str(), "bar: foo\n" );
     }
 }
+
+#ifdef COMPILE_CHECK
+
+COMPILE_FAIL(argParser)
+{
+    senf::console::ScopedDirectory<> dir;
+    dir.add("cb", &cb1)
+        .arg()
+        .arg()
+        .arg();
+}
+
+#endif
     
 ///////////////////////////////cc.e////////////////////////////////////////
 #undef prefix_
index 70487e3..c45d6fd 100644 (file)
@@ -50,6 +50,8 @@
 
 #include <boost/test/auto_unit_test.hpp>
 
+#define COMPILE_FAIL(n) void n()
+
 ///////////////////////////////hh.e////////////////////////////////////////
 //#include "auto_unit_test.cci"
 //#include "auto_unit_test.ct"
diff --git a/senfscons/CompileCheck.py b/senfscons/CompileCheck.py
new file mode 100644 (file)
index 0000000..171578f
--- /dev/null
@@ -0,0 +1,63 @@
+import os, os.path, sys
+from SCons.Script import *
+import SCons.Scanner.C
+
+def scanTests(f):
+    tests = {}
+    name = start = None
+    linenr= 0
+    for line in f:
+        linenr += 1
+        if line.startswith('COMPILE_FAIL(') and ')' in line:
+            name = line.split('(',1)[-1].split(')',1)[0]
+            start = linenr
+        elif line.startswith('}') and name and start:
+            tests[name] = (start, linenr)
+    return tests
+            
+def CompileCheck(target, source, env):
+    tests = scanTests(file(source[0].abspath))
+    errf = os.popen(env.subst('$CXXCOM -DCOMPILE_CHECK 2>&1', source=source, target=target))
+    passedTests = {}
+    for error in errf:
+        elts = error.split(':',2)
+        if len(elts) != 3 : continue
+        filename, line, message = elts
+        if not os.path.exists(filename) : continue
+        try: line = int(line)
+        except ValueError : continue
+        filename = os.path.abspath(filename)
+        if filename != source[0].abspath : continue
+
+        for name,lines in tests.iteritems():
+            if line >= lines[0] and line <= lines[1]:
+                passedTests[name] = 1
+                print "Passed test '%s': %s" % (name, message.strip())
+    failedTests = set(tests.iterkeys()) - set(passedTests.iterkeys())
+    if failedTests:
+        for test in failedTests:
+            print "Test '%s' FAILED" % test
+        print
+        print "*** %d tests FAILED" % len(failedTests)
+        if os.path.exists(target[0].abspath):
+            os.unlink(target[0].abspath)
+        return 1
+    file(target[0].abspath,"w").close()
+    return 0
+
+CompileCheck = Action(CompileCheck)
+
+def generate(env):
+
+    builder = env.Builder(
+        action = CompileCheck,
+        suffix = '.tsto',
+        src_suffix = '.cc',
+        source_scanner = SCons.Scanner.C.CScanner(),
+        single_source=1
+    )
+
+    env.Append(BUILDERS = { 'CompileCheck': builder })
+
+def exists(env):
+    return True
index d31c844..1d38d62 100644 (file)
@@ -52,6 +52,7 @@ SCONS_TOOLS = [
     "CopyToDir",
     "InstallIncludes",
     "ProgramNoScan",
+    "CompileCheck",
 ]
 
 opts = None
@@ -304,13 +305,17 @@ def GlobalTargets(env):
 def LibPath(lib): return '${LOCALLIBDIR}/${LIBPREFIX}%s${LIBADDSUFFIX}${LIBSUFFIX}' % lib
 
 def Test(env, sources, LIBS = [], OBJECTS = []):
-    test = env.BoostUnitTests(
+    test = [ env.BoostUnitTests(
         target = 'test',
         objects = [],
         test_sources = sources,
         LIBS = [ x + '$LIBADDSUFFIX' for x in LIBS ],
         OBJECTS = OBJECTS,
-        DEPENDS = [ env.File(LibPath(x)) for x in LIBS ])
+        DEPENDS = [ env.File(LibPath(x)) for x in LIBS ]) ]
+    compileTestSources = [ src for src in sources
+                           if 'COMPILE_CHECK' in file(src).read() ]
+    if compileTestSources:
+        test.extend(env.CompileCheck(source = compileTestSources))
     env.Alias('all_tests', test)
     env.Alias(env.File('test'), test)
     
@@ -351,13 +356,17 @@ def Objects(env, sources, testSources = None, LIBS = [], OBJECTS = [], no_includ
             objects += env.Object(obsources)
 
     if testSources:
-        test = env.BoostUnitTests(
+        test = [ env.BoostUnitTests(
             target = 'test',
             objects = objects,
             test_sources = testSources,
             LIBS = [ x + '$LIBADDSUFFIX' for x in LIBS ],
             OBJECTS = OBJECTS,
-            DEPENDS = [ env.File(LibPath(x)) for x in LIBS ])
+            DEPENDS = [ env.File(LibPath(x)) for x in LIBS ]) ]
+        compileTestSources = [ src for src in testSources
+                               if 'COMPILE_CHECK' in file(src).read() ]
+        if compileTestSources:
+            test.extend(env.CompileCheck(source = compileTestSources))
         env.Alias('all_tests', test)
         # Hmm ... here I'd like to use an Alias instead of a file
         # however the alias does not seem to live in the subdirectory