michael@0: #!/usr/bin/env python michael@0: # michael@0: # Copyright 2006, Google Inc. michael@0: # All rights reserved. michael@0: # michael@0: # Redistribution and use in source and binary forms, with or without michael@0: # modification, are permitted provided that the following conditions are michael@0: # met: michael@0: # michael@0: # * Redistributions of source code must retain the above copyright michael@0: # notice, this list of conditions and the following disclaimer. michael@0: # * Redistributions in binary form must reproduce the above michael@0: # copyright notice, this list of conditions and the following disclaimer michael@0: # in the documentation and/or other materials provided with the michael@0: # distribution. michael@0: # * Neither the name of Google Inc. nor the names of its michael@0: # contributors may be used to endorse or promote products derived from michael@0: # this software without specific prior written permission. michael@0: # michael@0: # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS michael@0: # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT michael@0: # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR michael@0: # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT michael@0: # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, michael@0: # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT michael@0: # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, michael@0: # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY michael@0: # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT michael@0: # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE michael@0: # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. michael@0: michael@0: """gen_gtest_pred_impl.py v0.1 michael@0: michael@0: Generates the implementation of Google Test predicate assertions and michael@0: accompanying tests. michael@0: michael@0: Usage: michael@0: michael@0: gen_gtest_pred_impl.py MAX_ARITY michael@0: michael@0: where MAX_ARITY is a positive integer. michael@0: michael@0: The command generates the implementation of up-to MAX_ARITY-ary michael@0: predicate assertions, and writes it to file gtest_pred_impl.h in the michael@0: directory where the script is. It also generates the accompanying michael@0: unit test in file gtest_pred_impl_unittest.cc. michael@0: """ michael@0: michael@0: __author__ = 'wan@google.com (Zhanyong Wan)' michael@0: michael@0: import os michael@0: import sys michael@0: import time michael@0: michael@0: # Where this script is. michael@0: SCRIPT_DIR = os.path.dirname(sys.argv[0]) michael@0: michael@0: # Where to store the generated header. michael@0: HEADER = os.path.join(SCRIPT_DIR, '../include/gtest/gtest_pred_impl.h') michael@0: michael@0: # Where to store the generated unit test. michael@0: UNIT_TEST = os.path.join(SCRIPT_DIR, '../test/gtest_pred_impl_unittest.cc') michael@0: michael@0: michael@0: def HeaderPreamble(n): michael@0: """Returns the preamble for the header file. michael@0: michael@0: Args: michael@0: n: the maximum arity of the predicate macros to be generated. michael@0: """ michael@0: michael@0: # A map that defines the values used in the preamble template. michael@0: DEFS = { michael@0: 'today' : time.strftime('%m/%d/%Y'), michael@0: 'year' : time.strftime('%Y'), michael@0: 'command' : '%s %s' % (os.path.basename(sys.argv[0]), n), michael@0: 'n' : n michael@0: } michael@0: michael@0: return ( michael@0: """// Copyright 2006, Google Inc. michael@0: // All rights reserved. michael@0: // michael@0: // Redistribution and use in source and binary forms, with or without michael@0: // modification, are permitted provided that the following conditions are michael@0: // met: michael@0: // michael@0: // * Redistributions of source code must retain the above copyright michael@0: // notice, this list of conditions and the following disclaimer. michael@0: // * Redistributions in binary form must reproduce the above michael@0: // copyright notice, this list of conditions and the following disclaimer michael@0: // in the documentation and/or other materials provided with the michael@0: // distribution. michael@0: // * Neither the name of Google Inc. nor the names of its michael@0: // contributors may be used to endorse or promote products derived from michael@0: // this software without specific prior written permission. michael@0: // michael@0: // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS michael@0: // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT michael@0: // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR michael@0: // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT michael@0: // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, michael@0: // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT michael@0: // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, michael@0: // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY michael@0: // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT michael@0: // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE michael@0: // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. michael@0: michael@0: // This file is AUTOMATICALLY GENERATED on %(today)s by command michael@0: // '%(command)s'. DO NOT EDIT BY HAND! michael@0: // michael@0: // Implements a family of generic predicate assertion macros. michael@0: michael@0: #ifndef GTEST_INCLUDE_GTEST_GTEST_PRED_IMPL_H_ michael@0: #define GTEST_INCLUDE_GTEST_GTEST_PRED_IMPL_H_ michael@0: michael@0: // Makes sure this header is not included before gtest.h. michael@0: #ifndef GTEST_INCLUDE_GTEST_GTEST_H_ michael@0: # error Do not include gtest_pred_impl.h directly. Include gtest.h instead. michael@0: #endif // GTEST_INCLUDE_GTEST_GTEST_H_ michael@0: michael@0: // This header implements a family of generic predicate assertion michael@0: // macros: michael@0: // michael@0: // ASSERT_PRED_FORMAT1(pred_format, v1) michael@0: // ASSERT_PRED_FORMAT2(pred_format, v1, v2) michael@0: // ... michael@0: // michael@0: // where pred_format is a function or functor that takes n (in the michael@0: // case of ASSERT_PRED_FORMATn) values and their source expression michael@0: // text, and returns a testing::AssertionResult. See the definition michael@0: // of ASSERT_EQ in gtest.h for an example. michael@0: // michael@0: // If you don't care about formatting, you can use the more michael@0: // restrictive version: michael@0: // michael@0: // ASSERT_PRED1(pred, v1) michael@0: // ASSERT_PRED2(pred, v1, v2) michael@0: // ... michael@0: // michael@0: // where pred is an n-ary function or functor that returns bool, michael@0: // and the values v1, v2, ..., must support the << operator for michael@0: // streaming to std::ostream. michael@0: // michael@0: // We also define the EXPECT_* variations. michael@0: // michael@0: // For now we only support predicates whose arity is at most %(n)s. michael@0: // Please email googletestframework@googlegroups.com if you need michael@0: // support for higher arities. michael@0: michael@0: // GTEST_ASSERT_ is the basic statement to which all of the assertions michael@0: // in this file reduce. Don't use this in your code. michael@0: michael@0: #define GTEST_ASSERT_(expression, on_failure) \\ michael@0: GTEST_AMBIGUOUS_ELSE_BLOCKER_ \\ michael@0: if (const ::testing::AssertionResult gtest_ar = (expression)) \\ michael@0: ; \\ michael@0: else \\ michael@0: on_failure(gtest_ar.failure_message()) michael@0: """ % DEFS) michael@0: michael@0: michael@0: def Arity(n): michael@0: """Returns the English name of the given arity.""" michael@0: michael@0: if n < 0: michael@0: return None michael@0: elif n <= 3: michael@0: return ['nullary', 'unary', 'binary', 'ternary'][n] michael@0: else: michael@0: return '%s-ary' % n michael@0: michael@0: michael@0: def Title(word): michael@0: """Returns the given word in title case. The difference between michael@0: this and string's title() method is that Title('4-ary') is '4-ary' michael@0: while '4-ary'.title() is '4-Ary'.""" michael@0: michael@0: return word[0].upper() + word[1:] michael@0: michael@0: michael@0: def OneTo(n): michael@0: """Returns the list [1, 2, 3, ..., n].""" michael@0: michael@0: return range(1, n + 1) michael@0: michael@0: michael@0: def Iter(n, format, sep=''): michael@0: """Given a positive integer n, a format string that contains 0 or michael@0: more '%s' format specs, and optionally a separator string, returns michael@0: the join of n strings, each formatted with the format string on an michael@0: iterator ranged from 1 to n. michael@0: michael@0: Example: michael@0: michael@0: Iter(3, 'v%s', sep=', ') returns 'v1, v2, v3'. michael@0: """ michael@0: michael@0: # How many '%s' specs are in format? michael@0: spec_count = len(format.split('%s')) - 1 michael@0: return sep.join([format % (spec_count * (i,)) for i in OneTo(n)]) michael@0: michael@0: michael@0: def ImplementationForArity(n): michael@0: """Returns the implementation of n-ary predicate assertions.""" michael@0: michael@0: # A map the defines the values used in the implementation template. michael@0: DEFS = { michael@0: 'n' : str(n), michael@0: 'vs' : Iter(n, 'v%s', sep=', '), michael@0: 'vts' : Iter(n, '#v%s', sep=', '), michael@0: 'arity' : Arity(n), michael@0: 'Arity' : Title(Arity(n)) michael@0: } michael@0: michael@0: impl = """ michael@0: michael@0: // Helper function for implementing {EXPECT|ASSERT}_PRED%(n)s. Don't use michael@0: // this in your code. michael@0: template michael@0: AssertionResult AssertPred%(n)sHelper(const char* pred_text""" % DEFS michael@0: michael@0: impl += Iter(n, """, michael@0: const char* e%s""") michael@0: michael@0: impl += """, michael@0: Pred pred""" michael@0: michael@0: impl += Iter(n, """, michael@0: const T%s& v%s""") michael@0: michael@0: impl += """) { michael@0: if (pred(%(vs)s)) return AssertionSuccess(); michael@0: michael@0: """ % DEFS michael@0: michael@0: impl += ' return AssertionFailure() << pred_text << "("' michael@0: michael@0: impl += Iter(n, """ michael@0: << e%s""", sep=' << ", "') michael@0: michael@0: impl += ' << ") evaluates to false, where"' michael@0: michael@0: impl += Iter(n, """ michael@0: << "\\n" << e%s << " evaluates to " << v%s""") michael@0: michael@0: impl += """; michael@0: } michael@0: michael@0: // Internal macro for implementing {EXPECT|ASSERT}_PRED_FORMAT%(n)s. michael@0: // Don't use this in your code. michael@0: #define GTEST_PRED_FORMAT%(n)s_(pred_format, %(vs)s, on_failure)\\ michael@0: GTEST_ASSERT_(pred_format(%(vts)s, %(vs)s), \\ michael@0: on_failure) michael@0: michael@0: // Internal macro for implementing {EXPECT|ASSERT}_PRED%(n)s. Don't use michael@0: // this in your code. michael@0: #define GTEST_PRED%(n)s_(pred, %(vs)s, on_failure)\\ michael@0: GTEST_ASSERT_(::testing::AssertPred%(n)sHelper(#pred""" % DEFS michael@0: michael@0: impl += Iter(n, """, \\ michael@0: #v%s""") michael@0: michael@0: impl += """, \\ michael@0: pred""" michael@0: michael@0: impl += Iter(n, """, \\ michael@0: v%s""") michael@0: michael@0: impl += """), on_failure) michael@0: michael@0: // %(Arity)s predicate assertion macros. michael@0: #define EXPECT_PRED_FORMAT%(n)s(pred_format, %(vs)s) \\ michael@0: GTEST_PRED_FORMAT%(n)s_(pred_format, %(vs)s, GTEST_NONFATAL_FAILURE_) michael@0: #define EXPECT_PRED%(n)s(pred, %(vs)s) \\ michael@0: GTEST_PRED%(n)s_(pred, %(vs)s, GTEST_NONFATAL_FAILURE_) michael@0: #define ASSERT_PRED_FORMAT%(n)s(pred_format, %(vs)s) \\ michael@0: GTEST_PRED_FORMAT%(n)s_(pred_format, %(vs)s, GTEST_FATAL_FAILURE_) michael@0: #define ASSERT_PRED%(n)s(pred, %(vs)s) \\ michael@0: GTEST_PRED%(n)s_(pred, %(vs)s, GTEST_FATAL_FAILURE_) michael@0: michael@0: """ % DEFS michael@0: michael@0: return impl michael@0: michael@0: michael@0: def HeaderPostamble(): michael@0: """Returns the postamble for the header file.""" michael@0: michael@0: return """ michael@0: michael@0: #endif // GTEST_INCLUDE_GTEST_GTEST_PRED_IMPL_H_ michael@0: """ michael@0: michael@0: michael@0: def GenerateFile(path, content): michael@0: """Given a file path and a content string, overwrites it with the michael@0: given content.""" michael@0: michael@0: print 'Updating file %s . . .' % path michael@0: michael@0: f = file(path, 'w+') michael@0: print >>f, content, michael@0: f.close() michael@0: michael@0: print 'File %s has been updated.' % path michael@0: michael@0: michael@0: def GenerateHeader(n): michael@0: """Given the maximum arity n, updates the header file that implements michael@0: the predicate assertions.""" michael@0: michael@0: GenerateFile(HEADER, michael@0: HeaderPreamble(n) michael@0: + ''.join([ImplementationForArity(i) for i in OneTo(n)]) michael@0: + HeaderPostamble()) michael@0: michael@0: michael@0: def UnitTestPreamble(): michael@0: """Returns the preamble for the unit test file.""" michael@0: michael@0: # A map that defines the values used in the preamble template. michael@0: DEFS = { michael@0: 'today' : time.strftime('%m/%d/%Y'), michael@0: 'year' : time.strftime('%Y'), michael@0: 'command' : '%s %s' % (os.path.basename(sys.argv[0]), sys.argv[1]), michael@0: } michael@0: michael@0: return ( michael@0: """// Copyright 2006, Google Inc. michael@0: // All rights reserved. michael@0: // michael@0: // Redistribution and use in source and binary forms, with or without michael@0: // modification, are permitted provided that the following conditions are michael@0: // met: michael@0: // michael@0: // * Redistributions of source code must retain the above copyright michael@0: // notice, this list of conditions and the following disclaimer. michael@0: // * Redistributions in binary form must reproduce the above michael@0: // copyright notice, this list of conditions and the following disclaimer michael@0: // in the documentation and/or other materials provided with the michael@0: // distribution. michael@0: // * Neither the name of Google Inc. nor the names of its michael@0: // contributors may be used to endorse or promote products derived from michael@0: // this software without specific prior written permission. michael@0: // michael@0: // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS michael@0: // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT michael@0: // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR michael@0: // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT michael@0: // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, michael@0: // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT michael@0: // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, michael@0: // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY michael@0: // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT michael@0: // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE michael@0: // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. michael@0: michael@0: // This file is AUTOMATICALLY GENERATED on %(today)s by command michael@0: // '%(command)s'. DO NOT EDIT BY HAND! michael@0: michael@0: // Regression test for gtest_pred_impl.h michael@0: // michael@0: // This file is generated by a script and quite long. If you intend to michael@0: // learn how Google Test works by reading its unit tests, read michael@0: // gtest_unittest.cc instead. michael@0: // michael@0: // This is intended as a regression test for the Google Test predicate michael@0: // assertions. We compile it as part of the gtest_unittest target michael@0: // only to keep the implementation tidy and compact, as it is quite michael@0: // involved to set up the stage for testing Google Test using Google michael@0: // Test itself. michael@0: // michael@0: // Currently, gtest_unittest takes ~11 seconds to run in the testing michael@0: // daemon. In the future, if it grows too large and needs much more michael@0: // time to finish, we should consider separating this file into a michael@0: // stand-alone regression test. michael@0: michael@0: #include michael@0: michael@0: #include "gtest/gtest.h" michael@0: #include "gtest/gtest-spi.h" michael@0: michael@0: // A user-defined data type. michael@0: struct Bool { michael@0: explicit Bool(int val) : value(val != 0) {} michael@0: michael@0: bool operator>(int n) const { return value > Bool(n).value; } michael@0: michael@0: Bool operator+(const Bool& rhs) const { return Bool(value + rhs.value); } michael@0: michael@0: bool operator==(const Bool& rhs) const { return value == rhs.value; } michael@0: michael@0: bool value; michael@0: }; michael@0: michael@0: // Enables Bool to be used in assertions. michael@0: std::ostream& operator<<(std::ostream& os, const Bool& x) { michael@0: return os << (x.value ? "true" : "false"); michael@0: } michael@0: michael@0: """ % DEFS) michael@0: michael@0: michael@0: def TestsForArity(n): michael@0: """Returns the tests for n-ary predicate assertions.""" michael@0: michael@0: # A map that defines the values used in the template for the tests. michael@0: DEFS = { michael@0: 'n' : n, michael@0: 'es' : Iter(n, 'e%s', sep=', '), michael@0: 'vs' : Iter(n, 'v%s', sep=', '), michael@0: 'vts' : Iter(n, '#v%s', sep=', '), michael@0: 'tvs' : Iter(n, 'T%s v%s', sep=', '), michael@0: 'int_vs' : Iter(n, 'int v%s', sep=', '), michael@0: 'Bool_vs' : Iter(n, 'Bool v%s', sep=', '), michael@0: 'types' : Iter(n, 'typename T%s', sep=', '), michael@0: 'v_sum' : Iter(n, 'v%s', sep=' + '), michael@0: 'arity' : Arity(n), michael@0: 'Arity' : Title(Arity(n)), michael@0: } michael@0: michael@0: tests = ( michael@0: """// Sample functions/functors for testing %(arity)s predicate assertions. michael@0: michael@0: // A %(arity)s predicate function. michael@0: template <%(types)s> michael@0: bool PredFunction%(n)s(%(tvs)s) { michael@0: return %(v_sum)s > 0; michael@0: } michael@0: michael@0: // The following two functions are needed to circumvent a bug in michael@0: // gcc 2.95.3, which sometimes has problem with the above template michael@0: // function. michael@0: bool PredFunction%(n)sInt(%(int_vs)s) { michael@0: return %(v_sum)s > 0; michael@0: } michael@0: bool PredFunction%(n)sBool(%(Bool_vs)s) { michael@0: return %(v_sum)s > 0; michael@0: } michael@0: """ % DEFS) michael@0: michael@0: tests += """ michael@0: // A %(arity)s predicate functor. michael@0: struct PredFunctor%(n)s { michael@0: template <%(types)s> michael@0: bool operator()(""" % DEFS michael@0: michael@0: tests += Iter(n, 'const T%s& v%s', sep=""", michael@0: """) michael@0: michael@0: tests += """) { michael@0: return %(v_sum)s > 0; michael@0: } michael@0: }; michael@0: """ % DEFS michael@0: michael@0: tests += """ michael@0: // A %(arity)s predicate-formatter function. michael@0: template <%(types)s> michael@0: testing::AssertionResult PredFormatFunction%(n)s(""" % DEFS michael@0: michael@0: tests += Iter(n, 'const char* e%s', sep=""", michael@0: """) michael@0: michael@0: tests += Iter(n, """, michael@0: const T%s& v%s""") michael@0: michael@0: tests += """) { michael@0: if (PredFunction%(n)s(%(vs)s)) michael@0: return testing::AssertionSuccess(); michael@0: michael@0: return testing::AssertionFailure() michael@0: << """ % DEFS michael@0: michael@0: tests += Iter(n, 'e%s', sep=' << " + " << ') michael@0: michael@0: tests += """ michael@0: << " is expected to be positive, but evaluates to " michael@0: << %(v_sum)s << "."; michael@0: } michael@0: """ % DEFS michael@0: michael@0: tests += """ michael@0: // A %(arity)s predicate-formatter functor. michael@0: struct PredFormatFunctor%(n)s { michael@0: template <%(types)s> michael@0: testing::AssertionResult operator()(""" % DEFS michael@0: michael@0: tests += Iter(n, 'const char* e%s', sep=""", michael@0: """) michael@0: michael@0: tests += Iter(n, """, michael@0: const T%s& v%s""") michael@0: michael@0: tests += """) const { michael@0: return PredFormatFunction%(n)s(%(es)s, %(vs)s); michael@0: } michael@0: }; michael@0: """ % DEFS michael@0: michael@0: tests += """ michael@0: // Tests for {EXPECT|ASSERT}_PRED_FORMAT%(n)s. michael@0: michael@0: class Predicate%(n)sTest : public testing::Test { michael@0: protected: michael@0: virtual void SetUp() { michael@0: expected_to_finish_ = true; michael@0: finished_ = false;""" % DEFS michael@0: michael@0: tests += """ michael@0: """ + Iter(n, 'n%s_ = ') + """0; michael@0: } michael@0: """ michael@0: michael@0: tests += """ michael@0: virtual void TearDown() { michael@0: // Verifies that each of the predicate's arguments was evaluated michael@0: // exactly once.""" michael@0: michael@0: tests += ''.join([""" michael@0: EXPECT_EQ(1, n%s_) << michael@0: "The predicate assertion didn't evaluate argument %s " michael@0: "exactly once.";""" % (i, i + 1) for i in OneTo(n)]) michael@0: michael@0: tests += """ michael@0: michael@0: // Verifies that the control flow in the test function is expected. michael@0: if (expected_to_finish_ && !finished_) { michael@0: FAIL() << "The predicate assertion unexpactedly aborted the test."; michael@0: } else if (!expected_to_finish_ && finished_) { michael@0: FAIL() << "The failed predicate assertion didn't abort the test " michael@0: "as expected."; michael@0: } michael@0: } michael@0: michael@0: // true iff the test function is expected to run to finish. michael@0: static bool expected_to_finish_; michael@0: michael@0: // true iff the test function did run to finish. michael@0: static bool finished_; michael@0: """ % DEFS michael@0: michael@0: tests += Iter(n, """ michael@0: static int n%s_;""") michael@0: michael@0: tests += """ michael@0: }; michael@0: michael@0: bool Predicate%(n)sTest::expected_to_finish_; michael@0: bool Predicate%(n)sTest::finished_; michael@0: """ % DEFS michael@0: michael@0: tests += Iter(n, """int Predicate%%(n)sTest::n%s_; michael@0: """) % DEFS michael@0: michael@0: tests += """ michael@0: typedef Predicate%(n)sTest EXPECT_PRED_FORMAT%(n)sTest; michael@0: typedef Predicate%(n)sTest ASSERT_PRED_FORMAT%(n)sTest; michael@0: typedef Predicate%(n)sTest EXPECT_PRED%(n)sTest; michael@0: typedef Predicate%(n)sTest ASSERT_PRED%(n)sTest; michael@0: """ % DEFS michael@0: michael@0: def GenTest(use_format, use_assert, expect_failure, michael@0: use_functor, use_user_type): michael@0: """Returns the test for a predicate assertion macro. michael@0: michael@0: Args: michael@0: use_format: true iff the assertion is a *_PRED_FORMAT*. michael@0: use_assert: true iff the assertion is a ASSERT_*. michael@0: expect_failure: true iff the assertion is expected to fail. michael@0: use_functor: true iff the first argument of the assertion is michael@0: a functor (as opposed to a function) michael@0: use_user_type: true iff the predicate functor/function takes michael@0: argument(s) of a user-defined type. michael@0: michael@0: Example: michael@0: michael@0: GenTest(1, 0, 0, 1, 0) returns a test that tests the behavior michael@0: of a successful EXPECT_PRED_FORMATn() that takes a functor michael@0: whose arguments have built-in types.""" michael@0: michael@0: if use_assert: michael@0: assrt = 'ASSERT' # 'assert' is reserved, so we cannot use michael@0: # that identifier here. michael@0: else: michael@0: assrt = 'EXPECT' michael@0: michael@0: assertion = assrt + '_PRED' michael@0: michael@0: if use_format: michael@0: pred_format = 'PredFormat' michael@0: assertion += '_FORMAT' michael@0: else: michael@0: pred_format = 'Pred' michael@0: michael@0: assertion += '%(n)s' % DEFS michael@0: michael@0: if use_functor: michael@0: pred_format_type = 'functor' michael@0: pred_format += 'Functor%(n)s()' michael@0: else: michael@0: pred_format_type = 'function' michael@0: pred_format += 'Function%(n)s' michael@0: if not use_format: michael@0: if use_user_type: michael@0: pred_format += 'Bool' michael@0: else: michael@0: pred_format += 'Int' michael@0: michael@0: test_name = pred_format_type.title() michael@0: michael@0: if use_user_type: michael@0: arg_type = 'user-defined type (Bool)' michael@0: test_name += 'OnUserType' michael@0: if expect_failure: michael@0: arg = 'Bool(n%s_++)' michael@0: else: michael@0: arg = 'Bool(++n%s_)' michael@0: else: michael@0: arg_type = 'built-in type (int)' michael@0: test_name += 'OnBuiltInType' michael@0: if expect_failure: michael@0: arg = 'n%s_++' michael@0: else: michael@0: arg = '++n%s_' michael@0: michael@0: if expect_failure: michael@0: successful_or_failed = 'failed' michael@0: expected_or_not = 'expected.' michael@0: test_name += 'Failure' michael@0: else: michael@0: successful_or_failed = 'successful' michael@0: expected_or_not = 'UNEXPECTED!' michael@0: test_name += 'Success' michael@0: michael@0: # A map that defines the values used in the test template. michael@0: defs = DEFS.copy() michael@0: defs.update({ michael@0: 'assert' : assrt, michael@0: 'assertion' : assertion, michael@0: 'test_name' : test_name, michael@0: 'pf_type' : pred_format_type, michael@0: 'pf' : pred_format, michael@0: 'arg_type' : arg_type, michael@0: 'arg' : arg, michael@0: 'successful' : successful_or_failed, michael@0: 'expected' : expected_or_not, michael@0: }) michael@0: michael@0: test = """ michael@0: // Tests a %(successful)s %(assertion)s where the michael@0: // predicate-formatter is a %(pf_type)s on a %(arg_type)s. michael@0: TEST_F(%(assertion)sTest, %(test_name)s) {""" % defs michael@0: michael@0: indent = (len(assertion) + 3)*' ' michael@0: extra_indent = '' michael@0: michael@0: if expect_failure: michael@0: extra_indent = ' ' michael@0: if use_assert: michael@0: test += """ michael@0: expected_to_finish_ = false; michael@0: EXPECT_FATAL_FAILURE({ // NOLINT""" michael@0: else: michael@0: test += """ michael@0: EXPECT_NONFATAL_FAILURE({ // NOLINT""" michael@0: michael@0: test += '\n' + extra_indent + """ %(assertion)s(%(pf)s""" % defs michael@0: michael@0: test = test % defs michael@0: test += Iter(n, ',\n' + indent + extra_indent + '%(arg)s' % defs) michael@0: test += ');\n' + extra_indent + ' finished_ = true;\n' michael@0: michael@0: if expect_failure: michael@0: test += ' }, "");\n' michael@0: michael@0: test += '}\n' michael@0: return test michael@0: michael@0: # Generates tests for all 2**6 = 64 combinations. michael@0: tests += ''.join([GenTest(use_format, use_assert, expect_failure, michael@0: use_functor, use_user_type) michael@0: for use_format in [0, 1] michael@0: for use_assert in [0, 1] michael@0: for expect_failure in [0, 1] michael@0: for use_functor in [0, 1] michael@0: for use_user_type in [0, 1] michael@0: ]) michael@0: michael@0: return tests michael@0: michael@0: michael@0: def UnitTestPostamble(): michael@0: """Returns the postamble for the tests.""" michael@0: michael@0: return '' michael@0: michael@0: michael@0: def GenerateUnitTest(n): michael@0: """Returns the tests for up-to n-ary predicate assertions.""" michael@0: michael@0: GenerateFile(UNIT_TEST, michael@0: UnitTestPreamble() michael@0: + ''.join([TestsForArity(i) for i in OneTo(n)]) michael@0: + UnitTestPostamble()) michael@0: michael@0: michael@0: def _Main(): michael@0: """The entry point of the script. Generates the header file and its michael@0: unit test.""" michael@0: michael@0: if len(sys.argv) != 2: michael@0: print __doc__ michael@0: print 'Author: ' + __author__ michael@0: sys.exit(1) michael@0: michael@0: n = int(sys.argv[1]) michael@0: GenerateHeader(n) michael@0: GenerateUnitTest(n) michael@0: michael@0: michael@0: if __name__ == '__main__': michael@0: _Main()