1 // 2 // Copyright 2016 Pixar 3 // 4 // Licensed under the Apache License, Version 2.0 (the "Apache License") 5 // with the following modification; you may not use this file except in 6 // compliance with the Apache License and the following modification to it: 7 // Section 6. Trademarks. is deleted and replaced with: 8 // 9 // 6. Trademarks. This License does not grant permission to use the trade 10 // names, trademarks, service marks, or product names of the Licensor 11 // and its affiliates, except as required to comply with Section 4(c) of 12 // the License and to reproduce the content of the NOTICE file. 13 // 14 // You may obtain a copy of the Apache License at 15 // 16 // http://www.apache.org/licenses/LICENSE-2.0 17 // 18 // Unless required by applicable law or agreed to in writing, software 19 // distributed under the Apache License with the above modification is 20 // distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 21 // KIND, either express or implied. See the Apache License for the specific 22 // language governing permissions and limitations under the Apache License. 23 // 24 #ifndef PXR_BASE_TF_REG_TEST_H 25 #define PXR_BASE_TF_REG_TEST_H 26 27 /// \file tf/regTest.h 28 /// \ingroup group_tf_Internal 29 /// Support for simple regression tests. 30 31 #include "pxr/pxr.h" 32 33 #include "pxr/base/tf/api.h" 34 #include "pxr/base/tf/singleton.h" 35 #include "pxr/base/tf/hash.h" 36 #include "pxr/base/tf/hashmap.h" 37 #include <string> 38 39 PXR_NAMESPACE_OPEN_SCOPE 40 41 /// \class TfRegTest 42 /// \ingroup group_tf_Internal 43 /// 44 /// \c TfRegTest is a singleton class, which is used to register functions 45 /// with either type \c bool \c (*)(int, char*[]), or functions returning type 46 /// \c bool and taking no arguments. 47 /// 48 /// Here is how \c TfRegTest is used to create tests in separate files, which 49 /// are then compiled into a single standalone executable (and not part of any 50 /// library): 51 /// 52 /// // file: main.cpp 53 /// \include test/main.cpp 54 /// 55 /// // file: hammer.cpp 56 /// \code 57 /// #include "pxr/base/tf/regTest.h" 58 /// 59 /// static bool 60 /// Test_PtHammer() 61 /// { 62 /// bool success; 63 /// ... 64 /// return success; 65 /// } 66 /// TF_ADD_REGTEST(PtHammer); 67 /// \endcode 68 /// 69 /// \code 70 /// // file: drill.cpp 71 /// static bool 72 /// Test_PtDrill(int argc, char *argv[]) 73 /// { 74 /// bool success; 75 /// ... 76 /// return success; 77 /// } 78 /// TF_ADD_REGTEST(PtDrill); 79 /// \endcode 80 /// 81 /// When \c main.cpp, \c drill.cpp and \c hammer.cpp are compiled into 82 /// an executable, then a test can be run by invoking the executable 83 /// with a first argument of either \p PtHammer or \p PtDrill. 84 /// Since \p PtHammer is a function without arguments, supplying additional 85 /// arguments is an error; but \p PtDrill takes arguments, so additional 86 /// command-line arguments specified are passed to the function. 87 /// (Most library test functions shouldn't need any arguments.) 88 /// 89 class TfRegTest { 90 public: 91 /// Run a single regression test function, returning 0 if the function 92 /// succeeded and 1 otherwise. 93 /// 94 /// This function is intended to be called as follows: 95 /// \code 96 /// int main(int argc, char *argv[]) { 97 /// return TfRegTest::Main(argc, argv); 98 /// } 99 /// \endcode 100 /// 101 /// The first argument is the name of the test to be run. If the 102 /// registered test function run takes no arguments, then no arguments 103 /// other than the test name should be supplied. Otherwise, the \c Main() 104 /// passes \c argc-1 and \c argv+1 to the test function, and the test 105 /// function is responsible for argument checking. Main(int argc,char * argv[])106 static int Main(int argc, char *argv[]) { 107 return GetInstance()._Main(argc, argv); 108 } 109 110 TF_API 111 static TfRegTest& GetInstance(); 112 113 /// Type of a function with no arguments. 114 typedef bool (*RegFunc)(); 115 116 /// Type of a function with arguments. 117 /// 118 /// When \c Main(argc,argv) is requested to run a function of type 119 /// \c RegFuncWithArgs, it invokes the function with arguments \c argc-1 120 /// and \c argv+1. 121 typedef bool (*RegFuncWithArgs)(int argc, char *argv[]); 122 123 TF_API 124 bool Register(const char* name, RegFunc); 125 TF_API 126 bool Register(const char* name, RegFuncWithArgs); 127 128 private: 129 friend class TfSingleton<TfRegTest>; 130 TF_API 131 int _Main(int argc, char *argv[]); 132 133 void _PrintTestNames(); 134 135 typedef TfHashMap<std::string, RegFunc, TfHash> _Hash; 136 typedef TfHashMap<std::string, RegFuncWithArgs, TfHash> _HashWithArgs; 137 _Hash _functionTable; 138 _HashWithArgs _functionTableWithArgs; 139 }; 140 141 TF_API_TEMPLATE_CLASS(TfSingleton<TfRegTest>); 142 143 /// Adds the function Test_\p name, under name \p name, as a runnable 144 /// regression test. Test_\p name must be of type \c RegFunc or 145 /// \c RegFuncWithArgs. 146 /// 147 /// \ingroup group_tf_Internal 148 /// \hideinitializer 149 #define TF_ADD_REGTEST(name) \ 150 bool Tf_RegTst##name = TfRegTest::GetInstance().Register(#name, Test_##name) 151 152 PXR_NAMESPACE_CLOSE_SCOPE 153 154 #endif 155