diff --git a/devtools/antglob.py b/devtools/antglob.py new file mode 100644 index 0000000..bbb6fec --- /dev/null +++ b/devtools/antglob.py @@ -0,0 +1,201 @@ +#!/usr/bin/env python +# encoding: utf-8 +# Baptiste Lepilleur, 2009 + +from dircache import listdir +import re +import fnmatch +import os.path + + +# These fnmatch expressions are used by default to prune the directory tree +# while doing the recursive traversal in the glob_impl method of glob function. +prune_dirs = '.git .bzr .hg .svn _MTN _darcs CVS SCCS ' + +# These fnmatch expressions are used by default to exclude files and dirs +# while doing the recursive traversal in the glob_impl method of glob function. +##exclude_pats = prune_pats + '*~ #*# .#* %*% ._* .gitignore .cvsignore vssver.scc .DS_Store'.split() + +# These ant_glob expressions are used by default to exclude files and dirs and also prune the directory tree +# while doing the recursive traversal in the glob_impl method of glob function. +default_excludes = ''' +**/*~ +**/#*# +**/.#* +**/%*% +**/._* +**/CVS +**/CVS/** +**/.cvsignore +**/SCCS +**/SCCS/** +**/vssver.scc +**/.svn +**/.svn/** +**/.git +**/.git/** +**/.gitignore +**/.bzr +**/.bzr/** +**/.hg +**/.hg/** +**/_MTN +**/_MTN/** +**/_darcs +**/_darcs/** +**/.DS_Store ''' + +DIR = 1 +FILE = 2 +DIR_LINK = 4 +FILE_LINK = 8 +LINKS = DIR_LINK | FILE_LINK +ALL_NO_LINK = DIR | FILE +ALL = DIR | FILE | LINKS + +_ANT_RE = re.compile( r'(/\*\*/)|(\*\*/)|(/\*\*)|(\*)|(/)|([^\*/]*)' ) + +def ant_pattern_to_re( ant_pattern ): + """Generates a regular expression from the ant pattern. + Matching convention: + **/a: match 'a', 'dir/a', 'dir1/dir2/a' + a/**/b: match 'a/b', 'a/c/b', 'a/d/c/b' + *.py: match 'script.py' but not 'a/script.py' + """ + rex = ['^'] + next_pos = 0 + sep_rex = r'(?:/|%s)' % re.escape( os.path.sep ) +## print 'Converting', ant_pattern + for match in _ANT_RE.finditer( ant_pattern ): +## print 'Matched', match.group() +## print match.start(0), next_pos + if match.start(0) != next_pos: + raise ValueError( "Invalid ant pattern" ) + if match.group(1): # /**/ + rex.append( sep_rex + '(?:.*%s)?' % sep_rex ) + elif match.group(2): # **/ + rex.append( '(?:.*%s)?' % sep_rex ) + elif match.group(3): # /** + rex.append( sep_rex + '.*' ) + elif match.group(4): # * + rex.append( '[^/%s]*' % re.escape(os.path.sep) ) + elif match.group(5): # / + rex.append( sep_rex ) + else: # somepath + rex.append( re.escape(match.group(6)) ) + next_pos = match.end() + rex.append('$') + return re.compile( ''.join( rex ) ) + +def _as_list( l ): + if isinstance(l, basestring): + return l.split() + return l + +def glob(dir_path, + includes = '**/*', + excludes = default_excludes, + entry_type = FILE, + prune_dirs = prune_dirs, + max_depth = 25): + include_filter = [ant_pattern_to_re(p) for p in _as_list(includes)] + exclude_filter = [ant_pattern_to_re(p) for p in _as_list(excludes)] + prune_dirs = [p.replace('/',os.path.sep) for p in _as_list(prune_dirs)] + dir_path = dir_path.replace('/',os.path.sep) + entry_type_filter = entry_type + + def is_pruned_dir( dir_name ): + for pattern in prune_dirs: + if fnmatch.fnmatch( dir_name, pattern ): + return True + return False + + def apply_filter( full_path, filter_rexs ): + """Return True if at least one of the filter regular expression match full_path.""" + for rex in filter_rexs: + if rex.match( full_path ): + return True + return False + + def glob_impl( root_dir_path ): + child_dirs = [root_dir_path] + while child_dirs: + dir_path = child_dirs.pop() + for entry in listdir( dir_path ): + full_path = os.path.join( dir_path, entry ) +## print 'Testing:', full_path, + is_dir = os.path.isdir( full_path ) + if is_dir and not is_pruned_dir( entry ): # explore child directory ? +## print '===> marked for recursion', + child_dirs.append( full_path ) + included = apply_filter( full_path, include_filter ) + rejected = apply_filter( full_path, exclude_filter ) + if not included or rejected: # do not include entry ? +## print '=> not included or rejected' + continue + link = os.path.islink( full_path ) + is_file = os.path.isfile( full_path ) + if not is_file and not is_dir: +## print '=> unknown entry type' + continue + if link: + entry_type = is_file and FILE_LINK or DIR_LINK + else: + entry_type = is_file and FILE or DIR +## print '=> type: %d' % entry_type, + if (entry_type & entry_type_filter) != 0: +## print ' => KEEP' + yield os.path.join( dir_path, entry ) +## else: +## print ' => TYPE REJECTED' + return list( glob_impl( dir_path ) ) + + +if __name__ == "__main__": + import unittest + + class AntPatternToRETest(unittest.TestCase): +## def test_conversion( self ): +## self.assertEqual( '^somepath$', ant_pattern_to_re( 'somepath' ).pattern ) + + def test_matching( self ): + test_cases = [ ( 'path', + ['path'], + ['somepath', 'pathsuffix', '/path', '/path'] ), + ( '*.py', + ['source.py', 'source.ext.py', '.py'], + ['path/source.py', '/.py', 'dir.py/z', 'z.pyc', 'z.c'] ), + ( '**/path', + ['path', '/path', '/a/path', 'c:/a/path', '/a/b/path', '//a/path', '/a/path/b/path'], + ['path/', 'a/path/b', 'dir.py/z', 'somepath', 'pathsuffix', 'a/somepath'] ), + ( 'path/**', + ['path/a', 'path/path/a', 'path//'], + ['path', 'somepath/a', 'a/path', 'a/path/a', 'pathsuffix/a'] ), + ( '/**/path', + ['/path', '/a/path', '/a/b/path/path', '/path/path'], + ['path', 'path/', 'a/path', '/pathsuffix', '/somepath'] ), + ( 'a/b', + ['a/b'], + ['somea/b', 'a/bsuffix', 'a/b/c'] ), + ( '**/*.py', + ['script.py', 'src/script.py', 'a/b/script.py', '/a/b/script.py'], + ['script.pyc', 'script.pyo', 'a.py/b'] ), + ( 'src/**/*.py', + ['src/a.py', 'src/dir/a.py'], + ['a/src/a.py', '/src/a.py'] ), + ] + for ant_pattern, accepted_matches, rejected_matches in list(test_cases): + def local_path( paths ): + return [ p.replace('/',os.path.sep) for p in paths ] + test_cases.append( (ant_pattern, local_path(accepted_matches), local_path( rejected_matches )) ) + for ant_pattern, accepted_matches, rejected_matches in test_cases: + rex = ant_pattern_to_re( ant_pattern ) + print 'ant_pattern:', ant_pattern, ' => ', rex.pattern + for accepted_match in accepted_matches: + print 'Accepted?:', accepted_match + self.assert_( rex.match( accepted_match ) is not None ) + for rejected_match in rejected_matches: + print 'Rejected?:', rejected_match + self.assert_( rex.match( rejected_match ) is None ) + + unittest.main() diff --git a/devtools/fixeol.py b/devtools/fixeol.py new file mode 100644 index 0000000..5d8372d --- /dev/null +++ b/devtools/fixeol.py @@ -0,0 +1,63 @@ +import os.path + +def fix_source_eol( path, is_dry_run = True, verbose = True, eol = '\n' ): + """Makes sure that all sources have the specified eol sequence (default: unix).""" + if not os.path.isfile( path ): + raise ValueError( 'Path "%s" is not a file' % path ) + try: + f = open(path, 'rb') + except IOError, msg: + print >> sys.stderr, "%s: I/O Error: %s" % (file, str(msg)) + return False + try: + raw_lines = f.readlines() + finally: + f.close() + fixed_lines = [line.rstrip('\r\n') + eol for line in raw_lines] + if raw_lines != fixed_lines: + print '%s =>' % path, + if not is_dry_run: + f = open(path, "wb") + try: + f.writelines(fixed_lines) + finally: + f.close() + if verbose: + print is_dry_run and ' NEED FIX' or ' FIXED' + return True +## +## +## +##def _do_fix( is_dry_run = True ): +## from waftools import antglob +## python_sources = antglob.glob( '.', +## includes = '**/*.py **/wscript **/wscript_build', +## excludes = antglob.default_excludes + './waf.py', +## prune_dirs = antglob.prune_dirs + 'waf-* ./build' ) +## for path in python_sources: +## _fix_python_source( path, is_dry_run ) +## +## cpp_sources = antglob.glob( '.', +## includes = '**/*.cpp **/*.h **/*.inl', +## prune_dirs = antglob.prune_dirs + 'waf-* ./build' ) +## for path in cpp_sources: +## _fix_source_eol( path, is_dry_run ) +## +## +##def dry_fix(context): +## _do_fix( is_dry_run = True ) +## +##def fix(context): +## _do_fix( is_dry_run = False ) +## +##def shutdown(): +## pass +## +##def check(context): +## # Unit tests are run when "check" target is used +## ut = UnitTest.unit_test() +## ut.change_to_testfile_dir = True +## ut.want_to_see_test_output = True +## ut.want_to_see_test_error = True +## ut.run() +## ut.print_results() diff --git a/doxybuild.py b/doxybuild.py index 82bdea6..792bff7 100644 --- a/doxybuild.py +++ b/doxybuild.py @@ -6,47 +6,7 @@ import os import os.path import sys import shutil -import gzip -import tarfile - -TARGZ_DEFAULT_COMPRESSION_LEVEL = 9 - -def make_tarball(tarball_path, sources, base_dir, prefix_dir=''): - """Parameters: - tarball_path: output path of the .tar.gz file - sources: list of sources to include in the tarball, relative to the current directory - base_dir: if a source file is in a sub-directory of base_dir, then base_dir is stripped - from path in the tarball. - prefix_dir: all files stored in the tarball be sub-directory of prefix_dir. Set to '' - to make them child of root. - """ - base_dir = os.path.normpath( os.path.abspath( base_dir ) ) - def archive_name( path ): - """Makes path relative to base_dir.""" - path = os.path.normpath( os.path.abspath( path ) ) - common_path = os.path.commonprefix( (base_dir, path) ) - archive_name = path[len(common_path):] - if os.path.isabs( archive_name ): - archive_name = archive_name[1:] - return os.path.join( prefix_dir, archive_name ) - def visit(tar, dirname, names): - for name in names: - path = os.path.join(dirname, name) - if os.path.isfile(path): - path_in_tar = archive_name(path) - tar.add(path, path_in_tar ) - compression = TARGZ_DEFAULT_COMPRESSION_LEVEL - fileobj = gzip.GzipFile( tarball_path, 'wb', compression ) - tar = tarfile.TarFile(os.path.splitext(tarball_path)[0], 'w', fileobj) - for source in sources: - source_path = source - if os.path.isdir( source ): - os.path.walk(source_path, visit, tar) - else: - path_in_tar = archive_name(source_path) - tar.add(source_path, path_in_tar ) # filename, arcname - tar.close() - +from devtools import tarball def find_program(filename): """find a program in folders path_lst, and sets env[var] @@ -171,7 +131,7 @@ def build_doc( options, make_release=False ): 'version' ] tarball_basedir = os.path.join( full_output_dir, html_output_dirname ) - make_tarball( tarball_path, tarball_sources, tarball_basedir, html_output_dirname ) + tarball.make_tarball( tarball_path, tarball_sources, tarball_basedir, html_output_dirname ) def main(): usage = """%prog diff --git a/makefiles/vs71/lib_json.vcproj b/makefiles/vs71/lib_json.vcproj index 1aa5978..2d7bf99 100644 --- a/makefiles/vs71/lib_json.vcproj +++ b/makefiles/vs71/lib_json.vcproj @@ -1,214 +1,214 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/makerelease.py b/makerelease.py new file mode 100644 index 0000000..b928c62 --- /dev/null +++ b/makerelease.py @@ -0,0 +1,178 @@ +"""Tag the sandbox for release, make source and doc tarballs. + +Requires Python 2.6 + +Example of invocation (use to test the script): +python makerelease.py --force --retag 0.5.0 0.6.0-dev + +Example of invocation when doing a release: +python makerelease.py 0.5.0 0.6.0-dev +""" +import os.path +import subprocess +import sys +import doxybuild +import subprocess +import xml.etree.ElementTree as ElementTree +import shutil +from devtools import antglob, fixeol, tarball + +SVN_ROOT = 'https://jsoncpp.svn.sourceforge.net/svnroot/jsoncpp/' +SVN_TAG_ROOT = SVN_ROOT + 'tags/jsoncpp' + +def set_version( version ): + with open('version','wb') as f: + f.write( version.strip() ) + +class SVNError(Exception): + pass + +def svn_command( command, *args ): + cmd = ['svn', '--non-interactive', command] + list(args) + print 'Running:', ' '.join( cmd ) + process = subprocess.Popen( cmd, + stdout=subprocess.PIPE, + stderr=subprocess.STDOUT ) + stdout = process.communicate()[0] + if process.returncode: + error = SVNError( 'SVN command failed:\n' + stdout ) + error.returncode = process.returncode + raise error + return stdout + +def check_no_pending_commit(): + """Checks that there is no pending commit in the sandbox.""" + stdout = svn_command( 'status', '--xml' ) + etree = ElementTree.fromstring( stdout ) + msg = [] + for entry in etree.getiterator( 'entry' ): + path = entry.get('path') + status = entry.find('wc-status').get('item') + if status != 'unversioned': + msg.append( 'File "%s" has pending change (status="%s")' % (path, status) ) + if msg: + msg.insert(0, 'Pending change to commit found in sandbox. Commit them first!' ) + return '\n'.join( msg ) + +def svn_join_url( base_url, suffix ): + if not base_url.endswith('/'): + base_url += '/' + if suffix.startswith('/'): + suffix = suffix[1:] + return base_url + suffix + +def svn_check_if_tag_exist( tag_url ): + """Checks if a tag exist. + Returns: True if the tag exist, False otherwise. + """ + try: + list_stdout = svn_command( 'list', tag_url ) + except SVNError, e: + if e.returncode != 1 or not str(e).find('tag_url'): + raise e + # otherwise ignore error, meaning tag does not exist + return False + return True + +def svn_tag_sandbox( tag_url, message ): + """Makes a tag based on the sandbox revisions. + """ + svn_command( 'copy', '-m', message, '.', tag_url ) + +def svn_remove_tag( tag_url, message ): + """Removes an existing tag. + """ + svn_command( 'delete', '-m', message, tag_url ) + +def svn_export( tag_url, export_dir ): + """Exports the tag_url revision to export_dir. + Target directory, including its parent is created if it does not exist. + If the directory export_dir exist, it is deleted before export proceed. + """ + if os.path.isdir( export_dir ): + shutil.rmtree( export_dir ) + svn_command( 'export', tag_url, export_dir ) + +def fix_sources_eol( dist_dir ): + """Set file EOL for tarball distribution. + """ + print 'Preparing exported source file EOL for distribution...' + prune_dirs = antglob.prune_dirs + 'scons-local* ./build* ./libs ./dist' + win_sources = antglob.glob( dist_dir, + includes = '**/*.sln **/*.vcproj', + prune_dirs = prune_dirs ) + unix_sources = antglob.glob( dist_dir, + includes = '''**/*.h **/*.cpp **/*.inl **/*.txt **/*.dox **/*.py **/*.html **/*.in + sconscript *.json *.expected AUTHORS LICENSE''', + excludes = antglob.default_excludes + 'scons.py sconsign.py scons-*', + prune_dirs = prune_dirs ) + for path in win_sources: + fixeol.fix_source_eol( path, is_dry_run = False, verbose = True, eol = '\r\n' ) + for path in unix_sources: + fixeol.fix_source_eol( path, is_dry_run = False, verbose = True, eol = '\n' ) + +def main(): + usage = """%prog release_version next_dev_version +Update 'version' file to release_version and commit. +Generates the document tarball. +Tags the sandbox revision with release_version. +Update 'version' file to next_dev_version and commit. + +Performs an svn export of tag release version, and build a source tarball. + +Must be started in the project top directory. +""" + from optparse import OptionParser + parser = OptionParser(usage=usage) + parser.allow_interspersed_args = False + parser.add_option('--dot', dest="dot_path", action='store', default=doxybuild.find_program('dot'), + help="""Path to GraphViz dot tool. Must be full qualified path. [Default: %default]""") + parser.add_option('--doxygen', dest="doxygen_path", action='store', default=doxybuild.find_program('doxygen'), + help="""Path to Doxygen tool. [Default: %default]""") + parser.add_option('--force', dest="ignore_pending_commit", action='store_true', default=False, + help="""Ignore pending commit. [Default: %default]""") + parser.add_option('--retag', dest="retag_release", action='store_true', default=False, + help="""Overwrite release existing tag if it exist. [Default: %default]""") + parser.enable_interspersed_args() + options, args = parser.parse_args() + + if len(args) < 1: + parser.error( 'release_version missing on command-line.' ) + release_version = args[0] + + if options.ignore_pending_commit: + msg = '' + else: + msg = check_no_pending_commit() + if not msg: + print 'Setting version to', release_version + set_version( release_version ) + tag_url = svn_join_url( SVN_TAG_ROOT, release_version ) + if svn_check_if_tag_exist( tag_url ): + if options.retag_release: + svn_remove_tag( tag_url, 'Overwriting previous tag' ) + else: + print 'Aborting, tag %s already exist. Use --retag to overwrite it!' % tag_url + sys.exit( 1 ) + svn_tag_sandbox( tag_url, 'Release ' + release_version ) + + print 'Generated doxygen document...' + doxybuild.build_doc( options, make_release=True ) + + export_dir = 'dist/export' + svn_export( tag_url, export_dir ) + fix_sources_eol( export_dir ) + + source_dir = 'jsoncpp-src-' + release_version + source_tarball_path = 'dist/%s.tar.gz' % source_dir + print 'Generating source tarball to', source_tarball_path + tarball.make_tarball( source_tarball_path, [export_dir], export_dir, prefix_dir=source_dir ) + #@todo: + # decompress source tarball + # ?compile & run & check + # ?upload documentation + else: + sys.stderr.write( msg + '\n' ) + +if __name__ == '__main__': + main() diff --git a/src/test_lib_json/jsontest.h b/src/test_lib_json/jsontest.h index 325b1d2..8f0bd31 100644 --- a/src/test_lib_json/jsontest.h +++ b/src/test_lib_json/jsontest.h @@ -1,254 +1,254 @@ -#ifndef JSONTEST_H_INCLUDED -# define JSONTEST_H_INCLUDED - -# include -# include -# include -# include - -// ////////////////////////////////////////////////////////////////// -// ////////////////////////////////////////////////////////////////// -// Mini Unit Testing framework -// ////////////////////////////////////////////////////////////////// -// ////////////////////////////////////////////////////////////////// - - - -/** \brief Unit testing framework. - * \warning: all assertions are non-aborting, test case execution will continue - * even if an assertion namespace. - * This constraint is for portability: the framework needs to compile - * on Visual Studio 6 and must not require exception usage. - */ -namespace JsonTest { - - - class Failure - { - public: - const char *file_; - unsigned int line_; - std::string expr_; - std::string message_; - unsigned int nestingLevel_; - }; - - - /// Context used to create the assertion callstack on failure. - /// Must be a POD to allow inline initialisation without stepping - /// into the debugger. - struct PredicateContext - { - typedef unsigned int Id; - Id id_; - const char *file_; - unsigned int line_; - const char *expr_; - PredicateContext *next_; - /// Related Failure, set when the PredicateContext is converted - /// into a Failure. - Failure *failure_; - }; - - class TestResult - { - public: - TestResult(); - - /// \internal Implementation detail for assertion macros - /// Not encapsulated to prevent step into when debugging failed assertions - /// Incremented by one on assertion predicate entry, decreased by one - /// by addPredicateContext(). - PredicateContext::Id predicateId_; - - /// \internal Implementation detail for predicate macros - PredicateContext *predicateStackTail_; - - void setTestName( const std::string &name ); - - /// Adds an assertion failure. - TestResult &addFailure( const char *file, unsigned int line, - const char *expr = 0 ); - - /// Removes the last PredicateContext added to the predicate stack - /// chained list. - /// Next messages will be targed at the PredicateContext that was removed. - TestResult &popPredicateContext(); - - bool failed() const; - - void printFailure( bool printTestName ) const; - - TestResult &operator << ( bool value ); - TestResult &operator << ( int value ); - TestResult &operator << ( unsigned int value ); - TestResult &operator << ( double value ); - TestResult &operator << ( const char *value ); - TestResult &operator << ( const std::string &value ); - - private: - TestResult &addToLastFailure( const std::string &message ); - unsigned int getAssertionNestingLevel() const; - /// Adds a failure or a predicate context - void addFailureInfo( const char *file, unsigned int line, - const char *expr, unsigned int nestingLevel ); - static std::string indentText( const std::string &text, - const std::string &indent ); - - typedef std::deque Failures; - Failures failures_; - std::string name_; - PredicateContext rootPredicateNode_; - PredicateContext::Id lastUsedPredicateId_; - /// Failure which is the target of the messages added using operator << - Failure *messageTarget_; - }; - - - class TestCase - { - public: - TestCase(); - - virtual ~TestCase(); - - void run( TestResult &result ); - - virtual const char *testName() const = 0; - - protected: - TestResult *result_; - - private: - virtual void runTestCase() = 0; - }; - - /// Function pointer type for TestCase factory - typedef TestCase *(*TestCaseFactory)(); - - class Runner - { - public: - Runner(); - - /// Adds a test to the suite - Runner &add( TestCaseFactory factory ); - - /// Runs test as specified on the command-line - /// If no command-line arguments are provided, run all tests. - /// If --list-tests is provided, then print the list of all test cases - /// If --test is provided, then run test testname. - int runCommandLine( int argc, const char *argv[] ) const; - - /// Runs all the test cases - bool runAllTest( bool printSummary ) const; - - /// Returns the number of test case in the suite - unsigned int testCount() const; - - /// Returns the name of the test case at the specified index - std::string testNameAt( unsigned int index ) const; - - /// Runs the test case at the specified index using the specified TestResult - void runTestAt( unsigned int index, TestResult &result ) const; - - static void printUsage( const char *appName ); - - private: // prevents copy construction and assignment - Runner( const Runner &other ); - Runner &operator =( const Runner &other ); - - private: - void listTests() const; - bool testIndex( const std::string &testName, unsigned int &index ) const; - static void preventDialogOnCrash(); - - private: - typedef std::deque Factories; - Factories tests_; - }; - - template - TestResult & - checkEqual( TestResult &result, const T &expected, const T &actual, - const char *file, unsigned int line, const char *expr ) - { - if ( expected != actual ) - { - result.addFailure( file, line, expr ); - result << "Expected: " << expected << "\n"; - result << "Actual : " << actual; - } - return result; - } - - TestResult & - checkStringEqual( TestResult &result, - const std::string &expected, const std::string &actual, - const char *file, unsigned int line, const char *expr ); - -} // namespace JsonTest - - -/// \brief Asserts that the given expression is true. -/// JSONTEST_ASSERT( x == y ) << "x=" << x << ", y=" << y; -/// JSONTEST_ASSERT( x == y ); -#define JSONTEST_ASSERT( expr ) \ - if ( condition ) \ - { \ - } \ - else \ - result_->addFailure( __FILE__, __LINE__, #expr ) - -/// \brief Asserts that the given predicate is true. -/// The predicate may do other assertions and be a member function of the fixture. -#define JSONTEST_ASSERT_PRED( expr ) \ - { \ - JsonTest::PredicateContext _minitest_Context = { \ - result_->predicateId_, __FILE__, __LINE__, #expr }; \ - result_->predicateStackTail_->next_ = &_minitest_Context; \ - result_->predicateId_ += 1; \ - result_->predicateStackTail_ = &_minitest_Context; \ - (expr); \ - result_->popPredicateContext(); \ - } \ - *result_ - -/// \brief Asserts that two values are equals. -#define JSONTEST_ASSERT_EQUAL( expected, actual ) \ - JsonTest::checkEqual( *result_, expected, actual, \ - __FILE__, __LINE__, \ - #expected " == " #actual ) - -/// \brief Asserts that two values are equals. -#define JSONTEST_ASSERT_STRING_EQUAL( expected, actual ) \ - JsonTest::checkStringEqual( *result_, \ - std::string(expected), std::string(actual), \ - #expected " == " #actual ) - -/// \brief Begin a fixture test case. -#define JSONTEST_FIXTURE( FixtureType, name ) \ - class Test##FixtureType##name : public FixtureType \ - { \ - public: \ - static JsonTest::TestCase *factory() \ - { \ - return new Test##FixtureType##name(); \ - } \ - public: /* overidden from TestCase */ \ - virtual const char *testName() const \ - { \ - return #FixtureType "/" #name; \ - } \ - virtual void runTestCase(); \ - }; \ - \ - void Test##FixtureType##name::runTestCase() - -#define JSONTEST_FIXTURE_FACTORY( FixtureType, name ) \ - &Test##FixtureType##name::factory - -#define JSONTEST_REGISTER_FIXTURE( runner, FixtureType, name ) \ - (runner).add( JSONTEST_FIXTURE_FACTORY( FixtureType, name ) ) - -#endif // ifndef JSONTEST_H_INCLUDED +#ifndef JSONTEST_H_INCLUDED +# define JSONTEST_H_INCLUDED + +# include +# include +# include +# include + +// ////////////////////////////////////////////////////////////////// +// ////////////////////////////////////////////////////////////////// +// Mini Unit Testing framework +// ////////////////////////////////////////////////////////////////// +// ////////////////////////////////////////////////////////////////// + + + +/** \brief Unit testing framework. + * \warning: all assertions are non-aborting, test case execution will continue + * even if an assertion namespace. + * This constraint is for portability: the framework needs to compile + * on Visual Studio 6 and must not require exception usage. + */ +namespace JsonTest { + + + class Failure + { + public: + const char *file_; + unsigned int line_; + std::string expr_; + std::string message_; + unsigned int nestingLevel_; + }; + + + /// Context used to create the assertion callstack on failure. + /// Must be a POD to allow inline initialisation without stepping + /// into the debugger. + struct PredicateContext + { + typedef unsigned int Id; + Id id_; + const char *file_; + unsigned int line_; + const char *expr_; + PredicateContext *next_; + /// Related Failure, set when the PredicateContext is converted + /// into a Failure. + Failure *failure_; + }; + + class TestResult + { + public: + TestResult(); + + /// \internal Implementation detail for assertion macros + /// Not encapsulated to prevent step into when debugging failed assertions + /// Incremented by one on assertion predicate entry, decreased by one + /// by addPredicateContext(). + PredicateContext::Id predicateId_; + + /// \internal Implementation detail for predicate macros + PredicateContext *predicateStackTail_; + + void setTestName( const std::string &name ); + + /// Adds an assertion failure. + TestResult &addFailure( const char *file, unsigned int line, + const char *expr = 0 ); + + /// Removes the last PredicateContext added to the predicate stack + /// chained list. + /// Next messages will be targed at the PredicateContext that was removed. + TestResult &popPredicateContext(); + + bool failed() const; + + void printFailure( bool printTestName ) const; + + TestResult &operator << ( bool value ); + TestResult &operator << ( int value ); + TestResult &operator << ( unsigned int value ); + TestResult &operator << ( double value ); + TestResult &operator << ( const char *value ); + TestResult &operator << ( const std::string &value ); + + private: + TestResult &addToLastFailure( const std::string &message ); + unsigned int getAssertionNestingLevel() const; + /// Adds a failure or a predicate context + void addFailureInfo( const char *file, unsigned int line, + const char *expr, unsigned int nestingLevel ); + static std::string indentText( const std::string &text, + const std::string &indent ); + + typedef std::deque Failures; + Failures failures_; + std::string name_; + PredicateContext rootPredicateNode_; + PredicateContext::Id lastUsedPredicateId_; + /// Failure which is the target of the messages added using operator << + Failure *messageTarget_; + }; + + + class TestCase + { + public: + TestCase(); + + virtual ~TestCase(); + + void run( TestResult &result ); + + virtual const char *testName() const = 0; + + protected: + TestResult *result_; + + private: + virtual void runTestCase() = 0; + }; + + /// Function pointer type for TestCase factory + typedef TestCase *(*TestCaseFactory)(); + + class Runner + { + public: + Runner(); + + /// Adds a test to the suite + Runner &add( TestCaseFactory factory ); + + /// Runs test as specified on the command-line + /// If no command-line arguments are provided, run all tests. + /// If --list-tests is provided, then print the list of all test cases + /// If --test is provided, then run test testname. + int runCommandLine( int argc, const char *argv[] ) const; + + /// Runs all the test cases + bool runAllTest( bool printSummary ) const; + + /// Returns the number of test case in the suite + unsigned int testCount() const; + + /// Returns the name of the test case at the specified index + std::string testNameAt( unsigned int index ) const; + + /// Runs the test case at the specified index using the specified TestResult + void runTestAt( unsigned int index, TestResult &result ) const; + + static void printUsage( const char *appName ); + + private: // prevents copy construction and assignment + Runner( const Runner &other ); + Runner &operator =( const Runner &other ); + + private: + void listTests() const; + bool testIndex( const std::string &testName, unsigned int &index ) const; + static void preventDialogOnCrash(); + + private: + typedef std::deque Factories; + Factories tests_; + }; + + template + TestResult & + checkEqual( TestResult &result, const T &expected, const T &actual, + const char *file, unsigned int line, const char *expr ) + { + if ( expected != actual ) + { + result.addFailure( file, line, expr ); + result << "Expected: " << expected << "\n"; + result << "Actual : " << actual; + } + return result; + } + + TestResult & + checkStringEqual( TestResult &result, + const std::string &expected, const std::string &actual, + const char *file, unsigned int line, const char *expr ); + +} // namespace JsonTest + + +/// \brief Asserts that the given expression is true. +/// JSONTEST_ASSERT( x == y ) << "x=" << x << ", y=" << y; +/// JSONTEST_ASSERT( x == y ); +#define JSONTEST_ASSERT( expr ) \ + if ( condition ) \ + { \ + } \ + else \ + result_->addFailure( __FILE__, __LINE__, #expr ) + +/// \brief Asserts that the given predicate is true. +/// The predicate may do other assertions and be a member function of the fixture. +#define JSONTEST_ASSERT_PRED( expr ) \ + { \ + JsonTest::PredicateContext _minitest_Context = { \ + result_->predicateId_, __FILE__, __LINE__, #expr }; \ + result_->predicateStackTail_->next_ = &_minitest_Context; \ + result_->predicateId_ += 1; \ + result_->predicateStackTail_ = &_minitest_Context; \ + (expr); \ + result_->popPredicateContext(); \ + } \ + *result_ + +/// \brief Asserts that two values are equals. +#define JSONTEST_ASSERT_EQUAL( expected, actual ) \ + JsonTest::checkEqual( *result_, expected, actual, \ + __FILE__, __LINE__, \ + #expected " == " #actual ) + +/// \brief Asserts that two values are equals. +#define JSONTEST_ASSERT_STRING_EQUAL( expected, actual ) \ + JsonTest::checkStringEqual( *result_, \ + std::string(expected), std::string(actual), \ + #expected " == " #actual ) + +/// \brief Begin a fixture test case. +#define JSONTEST_FIXTURE( FixtureType, name ) \ + class Test##FixtureType##name : public FixtureType \ + { \ + public: \ + static JsonTest::TestCase *factory() \ + { \ + return new Test##FixtureType##name(); \ + } \ + public: /* overidden from TestCase */ \ + virtual const char *testName() const \ + { \ + return #FixtureType "/" #name; \ + } \ + virtual void runTestCase(); \ + }; \ + \ + void Test##FixtureType##name::runTestCase() + +#define JSONTEST_FIXTURE_FACTORY( FixtureType, name ) \ + &Test##FixtureType##name::factory + +#define JSONTEST_REGISTER_FIXTURE( runner, FixtureType, name ) \ + (runner).add( JSONTEST_FIXTURE_FACTORY( FixtureType, name ) ) + +#endif // ifndef JSONTEST_H_INCLUDED diff --git a/src/test_lib_json/main.cpp b/src/test_lib_json/main.cpp index 9864178..b80776d 100644 --- a/src/test_lib_json/main.cpp +++ b/src/test_lib_json/main.cpp @@ -1,244 +1,244 @@ -#include -#include "jsontest.h" - - -// TODO: -// - boolean value returns that they are integral. Should not be. -// - unsigned integer in integer range are not considered to be valid integer. Should check range. - - -// ////////////////////////////////////////////////////////////////// -// ////////////////////////////////////////////////////////////////// -// Json Library test cases -// ////////////////////////////////////////////////////////////////// -// ////////////////////////////////////////////////////////////////// - - -struct ValueTest : JsonTest::TestCase -{ - Json::Value null_; - Json::Value emptyArray_; - Json::Value emptyObject_; - Json::Value integer_; - Json::Value unsignedInteger_; - Json::Value smallUnsignedInteger_; - Json::Value real_; - Json::Value array1_; - Json::Value object1_; - Json::Value emptyString_; - Json::Value string1_; - Json::Value string_; - Json::Value true_; - Json::Value false_; - - ValueTest() - : emptyArray_( Json::arrayValue ) - , emptyObject_( Json::objectValue ) - , integer_( 123456789 ) - , smallUnsignedInteger_( Json::Value::UInt( Json::Value::maxInt ) ) - , unsignedInteger_( 34567890u ) - , real_( 1234.56789 ) - , emptyString_( "" ) - , string1_( "a" ) - , string_( "sometext with space" ) - , true_( true ) - , false_( false ) - { - array1_.append( 1234 ); - object1_["id"] = 1234; - } - - struct IsCheck - { - /// Initialize all checks to \c false by default. - IsCheck(); - - bool isObject_; - bool isArray_; - bool isBool_; - bool isDouble_; - bool isInt_; - bool isUInt_; - bool isIntegral_; - bool isNumeric_; - bool isString_; - bool isNull_; - }; - - void checkConstMemberCount( const Json::Value &value, unsigned int expectedCount ); - - void checkMemberCount( Json::Value &value, unsigned int expectedCount ); - - void checkIs( const Json::Value &value, const IsCheck &check ); -}; - - -JSONTEST_FIXTURE( ValueTest, size ) -{ - JSONTEST_ASSERT_PRED( checkMemberCount(emptyArray_, 0) ); - JSONTEST_ASSERT_PRED( checkMemberCount(emptyObject_, 0) ); - JSONTEST_ASSERT_PRED( checkMemberCount(array1_, 1) ); - JSONTEST_ASSERT_PRED( checkMemberCount(object1_, 1) ); - JSONTEST_ASSERT_PRED( checkMemberCount(null_, 0) ); - JSONTEST_ASSERT_PRED( checkMemberCount(integer_, 0) ); - JSONTEST_ASSERT_PRED( checkMemberCount(real_, 0) ); - JSONTEST_ASSERT_PRED( checkMemberCount(emptyString_, 0) ); - JSONTEST_ASSERT_PRED( checkMemberCount(string_, 0) ); - JSONTEST_ASSERT_PRED( checkMemberCount(true_, 0) ); -} - - -JSONTEST_FIXTURE( ValueTest, isObject ) -{ - IsCheck checks; - checks.isObject_ = true; - JSONTEST_ASSERT_PRED( checkIs( emptyObject_, checks ) ); - JSONTEST_ASSERT_PRED( checkIs( object1_, checks ) ); -} - - -JSONTEST_FIXTURE( ValueTest, isArray ) -{ - IsCheck checks; - checks.isArray_ = true; - JSONTEST_ASSERT_PRED( checkIs( emptyArray_, checks ) ); - JSONTEST_ASSERT_PRED( checkIs( array1_, checks ) ); -} - - -JSONTEST_FIXTURE( ValueTest, isNull ) -{ - IsCheck checks; - checks.isNull_ = true; - checks.isObject_ = true; - checks.isArray_ = true; - JSONTEST_ASSERT_PRED( checkIs( null_, checks ) ); -} - - -JSONTEST_FIXTURE( ValueTest, isString ) -{ - IsCheck checks; - checks.isString_ = true; - JSONTEST_ASSERT_PRED( checkIs( emptyString_, checks ) ); - JSONTEST_ASSERT_PRED( checkIs( string_, checks ) ); - JSONTEST_ASSERT_PRED( checkIs( string1_, checks ) ); -} - - -JSONTEST_FIXTURE( ValueTest, isBool ) -{ - IsCheck checks; - checks.isBool_ = true; - checks.isIntegral_ = true; - checks.isNumeric_ = true; - JSONTEST_ASSERT_PRED( checkIs( false_, checks ) ); - JSONTEST_ASSERT_PRED( checkIs( true_, checks ) ); -} - - -JSONTEST_FIXTURE( ValueTest, isDouble ) -{ - IsCheck checks; - checks.isDouble_ = true; - checks.isNumeric_ = true; - JSONTEST_ASSERT_PRED( checkIs( real_, checks ) ); -} - - -JSONTEST_FIXTURE( ValueTest, isInt ) -{ - IsCheck checks; - checks.isInt_ = true; - checks.isNumeric_ = true; - checks.isIntegral_ = true; - JSONTEST_ASSERT_PRED( checkIs( integer_, checks ) ); -} - - -JSONTEST_FIXTURE( ValueTest, isUInt ) -{ - IsCheck checks; - checks.isUInt_ = true; - checks.isNumeric_ = true; - checks.isIntegral_ = true; - JSONTEST_ASSERT_PRED( checkIs( unsignedInteger_, checks ) ); - JSONTEST_ASSERT_PRED( checkIs( smallUnsignedInteger_, checks ) ); -} - - -void -ValueTest::checkConstMemberCount( const Json::Value &value, unsigned int expectedCount ) -{ - unsigned int count = 0; - Json::Value::const_iterator itEnd = value.end(); - for ( Json::Value::const_iterator it = value.begin(); it != itEnd; ++it ) - { - ++count; - } - JSONTEST_ASSERT_EQUAL( expectedCount, count ) << "Json::Value::const_iterator"; -} - -void -ValueTest::checkMemberCount( Json::Value &value, unsigned int expectedCount ) -{ - JSONTEST_ASSERT_EQUAL( expectedCount, value.size() ); - - unsigned int count = 0; - Json::Value::iterator itEnd = value.end(); - for ( Json::Value::iterator it = value.begin(); it != itEnd; ++it ) - { - ++count; - } - JSONTEST_ASSERT_EQUAL( expectedCount, count ) << "Json::Value::iterator"; - - JSONTEST_ASSERT_PRED( checkConstMemberCount(value, expectedCount) ); -} - - -ValueTest::IsCheck::IsCheck() - : isObject_( false ) - , isArray_( false ) - , isBool_( false ) - , isDouble_( false ) - , isInt_( false ) - , isUInt_( false ) - , isIntegral_( false ) - , isNumeric_( false ) - , isString_( false ) - , isNull_( false ) -{ -} - - -void -ValueTest::checkIs( const Json::Value &value, const IsCheck &check ) -{ - JSONTEST_ASSERT_EQUAL( check.isObject_, value.isObject() ); - JSONTEST_ASSERT_EQUAL( check.isArray_, value.isArray() ); - JSONTEST_ASSERT_EQUAL( check.isBool_, value.isBool() ); - JSONTEST_ASSERT_EQUAL( check.isDouble_, value.isDouble() ); - JSONTEST_ASSERT_EQUAL( check.isInt_, value.isInt() ); - JSONTEST_ASSERT_EQUAL( check.isUInt_, value.isUInt() ); - JSONTEST_ASSERT_EQUAL( check.isIntegral_, value.isIntegral() ); - JSONTEST_ASSERT_EQUAL( check.isNumeric_, value.isNumeric() ); - JSONTEST_ASSERT_EQUAL( check.isString_, value.isString() ); - JSONTEST_ASSERT_EQUAL( check.isNull_, value.isNull() ); -} - - - -int main( int argc, const char *argv[] ) -{ - JsonTest::Runner runner; - JSONTEST_REGISTER_FIXTURE( runner, ValueTest, size ); - JSONTEST_REGISTER_FIXTURE( runner, ValueTest, isObject ); - JSONTEST_REGISTER_FIXTURE( runner, ValueTest, isArray ); - JSONTEST_REGISTER_FIXTURE( runner, ValueTest, isBool ); - JSONTEST_REGISTER_FIXTURE( runner, ValueTest, isInt ); - JSONTEST_REGISTER_FIXTURE( runner, ValueTest, isUInt ); - JSONTEST_REGISTER_FIXTURE( runner, ValueTest, isDouble ); - JSONTEST_REGISTER_FIXTURE( runner, ValueTest, isString ); - JSONTEST_REGISTER_FIXTURE( runner, ValueTest, isNull ); - return runner.runCommandLine( argc, argv ); -} +#include +#include "jsontest.h" + + +// TODO: +// - boolean value returns that they are integral. Should not be. +// - unsigned integer in integer range are not considered to be valid integer. Should check range. + + +// ////////////////////////////////////////////////////////////////// +// ////////////////////////////////////////////////////////////////// +// Json Library test cases +// ////////////////////////////////////////////////////////////////// +// ////////////////////////////////////////////////////////////////// + + +struct ValueTest : JsonTest::TestCase +{ + Json::Value null_; + Json::Value emptyArray_; + Json::Value emptyObject_; + Json::Value integer_; + Json::Value unsignedInteger_; + Json::Value smallUnsignedInteger_; + Json::Value real_; + Json::Value array1_; + Json::Value object1_; + Json::Value emptyString_; + Json::Value string1_; + Json::Value string_; + Json::Value true_; + Json::Value false_; + + ValueTest() + : emptyArray_( Json::arrayValue ) + , emptyObject_( Json::objectValue ) + , integer_( 123456789 ) + , smallUnsignedInteger_( Json::Value::UInt( Json::Value::maxInt ) ) + , unsignedInteger_( 34567890u ) + , real_( 1234.56789 ) + , emptyString_( "" ) + , string1_( "a" ) + , string_( "sometext with space" ) + , true_( true ) + , false_( false ) + { + array1_.append( 1234 ); + object1_["id"] = 1234; + } + + struct IsCheck + { + /// Initialize all checks to \c false by default. + IsCheck(); + + bool isObject_; + bool isArray_; + bool isBool_; + bool isDouble_; + bool isInt_; + bool isUInt_; + bool isIntegral_; + bool isNumeric_; + bool isString_; + bool isNull_; + }; + + void checkConstMemberCount( const Json::Value &value, unsigned int expectedCount ); + + void checkMemberCount( Json::Value &value, unsigned int expectedCount ); + + void checkIs( const Json::Value &value, const IsCheck &check ); +}; + + +JSONTEST_FIXTURE( ValueTest, size ) +{ + JSONTEST_ASSERT_PRED( checkMemberCount(emptyArray_, 0) ); + JSONTEST_ASSERT_PRED( checkMemberCount(emptyObject_, 0) ); + JSONTEST_ASSERT_PRED( checkMemberCount(array1_, 1) ); + JSONTEST_ASSERT_PRED( checkMemberCount(object1_, 1) ); + JSONTEST_ASSERT_PRED( checkMemberCount(null_, 0) ); + JSONTEST_ASSERT_PRED( checkMemberCount(integer_, 0) ); + JSONTEST_ASSERT_PRED( checkMemberCount(real_, 0) ); + JSONTEST_ASSERT_PRED( checkMemberCount(emptyString_, 0) ); + JSONTEST_ASSERT_PRED( checkMemberCount(string_, 0) ); + JSONTEST_ASSERT_PRED( checkMemberCount(true_, 0) ); +} + + +JSONTEST_FIXTURE( ValueTest, isObject ) +{ + IsCheck checks; + checks.isObject_ = true; + JSONTEST_ASSERT_PRED( checkIs( emptyObject_, checks ) ); + JSONTEST_ASSERT_PRED( checkIs( object1_, checks ) ); +} + + +JSONTEST_FIXTURE( ValueTest, isArray ) +{ + IsCheck checks; + checks.isArray_ = true; + JSONTEST_ASSERT_PRED( checkIs( emptyArray_, checks ) ); + JSONTEST_ASSERT_PRED( checkIs( array1_, checks ) ); +} + + +JSONTEST_FIXTURE( ValueTest, isNull ) +{ + IsCheck checks; + checks.isNull_ = true; + checks.isObject_ = true; + checks.isArray_ = true; + JSONTEST_ASSERT_PRED( checkIs( null_, checks ) ); +} + + +JSONTEST_FIXTURE( ValueTest, isString ) +{ + IsCheck checks; + checks.isString_ = true; + JSONTEST_ASSERT_PRED( checkIs( emptyString_, checks ) ); + JSONTEST_ASSERT_PRED( checkIs( string_, checks ) ); + JSONTEST_ASSERT_PRED( checkIs( string1_, checks ) ); +} + + +JSONTEST_FIXTURE( ValueTest, isBool ) +{ + IsCheck checks; + checks.isBool_ = true; + checks.isIntegral_ = true; + checks.isNumeric_ = true; + JSONTEST_ASSERT_PRED( checkIs( false_, checks ) ); + JSONTEST_ASSERT_PRED( checkIs( true_, checks ) ); +} + + +JSONTEST_FIXTURE( ValueTest, isDouble ) +{ + IsCheck checks; + checks.isDouble_ = true; + checks.isNumeric_ = true; + JSONTEST_ASSERT_PRED( checkIs( real_, checks ) ); +} + + +JSONTEST_FIXTURE( ValueTest, isInt ) +{ + IsCheck checks; + checks.isInt_ = true; + checks.isNumeric_ = true; + checks.isIntegral_ = true; + JSONTEST_ASSERT_PRED( checkIs( integer_, checks ) ); +} + + +JSONTEST_FIXTURE( ValueTest, isUInt ) +{ + IsCheck checks; + checks.isUInt_ = true; + checks.isNumeric_ = true; + checks.isIntegral_ = true; + JSONTEST_ASSERT_PRED( checkIs( unsignedInteger_, checks ) ); + JSONTEST_ASSERT_PRED( checkIs( smallUnsignedInteger_, checks ) ); +} + + +void +ValueTest::checkConstMemberCount( const Json::Value &value, unsigned int expectedCount ) +{ + unsigned int count = 0; + Json::Value::const_iterator itEnd = value.end(); + for ( Json::Value::const_iterator it = value.begin(); it != itEnd; ++it ) + { + ++count; + } + JSONTEST_ASSERT_EQUAL( expectedCount, count ) << "Json::Value::const_iterator"; +} + +void +ValueTest::checkMemberCount( Json::Value &value, unsigned int expectedCount ) +{ + JSONTEST_ASSERT_EQUAL( expectedCount, value.size() ); + + unsigned int count = 0; + Json::Value::iterator itEnd = value.end(); + for ( Json::Value::iterator it = value.begin(); it != itEnd; ++it ) + { + ++count; + } + JSONTEST_ASSERT_EQUAL( expectedCount, count ) << "Json::Value::iterator"; + + JSONTEST_ASSERT_PRED( checkConstMemberCount(value, expectedCount) ); +} + + +ValueTest::IsCheck::IsCheck() + : isObject_( false ) + , isArray_( false ) + , isBool_( false ) + , isDouble_( false ) + , isInt_( false ) + , isUInt_( false ) + , isIntegral_( false ) + , isNumeric_( false ) + , isString_( false ) + , isNull_( false ) +{ +} + + +void +ValueTest::checkIs( const Json::Value &value, const IsCheck &check ) +{ + JSONTEST_ASSERT_EQUAL( check.isObject_, value.isObject() ); + JSONTEST_ASSERT_EQUAL( check.isArray_, value.isArray() ); + JSONTEST_ASSERT_EQUAL( check.isBool_, value.isBool() ); + JSONTEST_ASSERT_EQUAL( check.isDouble_, value.isDouble() ); + JSONTEST_ASSERT_EQUAL( check.isInt_, value.isInt() ); + JSONTEST_ASSERT_EQUAL( check.isUInt_, value.isUInt() ); + JSONTEST_ASSERT_EQUAL( check.isIntegral_, value.isIntegral() ); + JSONTEST_ASSERT_EQUAL( check.isNumeric_, value.isNumeric() ); + JSONTEST_ASSERT_EQUAL( check.isString_, value.isString() ); + JSONTEST_ASSERT_EQUAL( check.isNull_, value.isNull() ); +} + + + +int main( int argc, const char *argv[] ) +{ + JsonTest::Runner runner; + JSONTEST_REGISTER_FIXTURE( runner, ValueTest, size ); + JSONTEST_REGISTER_FIXTURE( runner, ValueTest, isObject ); + JSONTEST_REGISTER_FIXTURE( runner, ValueTest, isArray ); + JSONTEST_REGISTER_FIXTURE( runner, ValueTest, isBool ); + JSONTEST_REGISTER_FIXTURE( runner, ValueTest, isInt ); + JSONTEST_REGISTER_FIXTURE( runner, ValueTest, isUInt ); + JSONTEST_REGISTER_FIXTURE( runner, ValueTest, isDouble ); + JSONTEST_REGISTER_FIXTURE( runner, ValueTest, isString ); + JSONTEST_REGISTER_FIXTURE( runner, ValueTest, isNull ); + return runner.runCommandLine( argc, argv ); +} diff --git a/src/test_lib_json/sconscript b/src/test_lib_json/sconscript index 84f56b6..915fd01 100644 --- a/src/test_lib_json/sconscript +++ b/src/test_lib_json/sconscript @@ -1,10 +1,10 @@ -Import( 'env_testing buildUnitTests' ) - -buildUnitTests( env_testing, Split( """ - main.cpp - jsontest.cpp - """ ), - 'test_lib_json' ) - -# For 'check' to work, 'libs' must be built first. -env_testing.Depends('test_lib_json', '#libs') +Import( 'env_testing buildUnitTests' ) + +buildUnitTests( env_testing, Split( """ + main.cpp + jsontest.cpp + """ ), + 'test_lib_json' ) + +# For 'check' to work, 'libs' must be built first. +env_testing.Depends('test_lib_json', '#libs')