diff --git a/.clang-format b/.clang-format new file mode 100644 index 0000000..a04f49b --- /dev/null +++ b/.clang-format @@ -0,0 +1,120 @@ +# Style file for MLSE Libraries based on the modified rocBLAS style + +# Common settings +BasedOnStyle: WebKit +TabWidth: 4 +IndentWidth: 4 +UseTab: Never +ColumnLimit: 100 + +# Other languages JavaScript, Proto + +--- +Language: Cpp + +# http://releases.llvm.org/6.0.1/tools/clang/docs/ClangFormatStyleOptions.html#disabling-formatting-on-a-piece-of-code +# int formatted_code; +# // clang-format off +# void unformatted_code ; +# // clang-format on +# void formatted_code_again; + +DisableFormat: false +Standard: Cpp11 + +AccessModifierOffset: -4 +AlignAfterOpenBracket: true +AlignConsecutiveAssignments: true +AlignConsecutiveDeclarations: true +AlignEscapedNewlinesLeft: true +AlignOperands: true +AlignTrailingComments: false +AllowAllParametersOfDeclarationOnNextLine: true +AllowShortBlocksOnASingleLine: false +AllowShortCaseLabelsOnASingleLine: false +AllowShortFunctionsOnASingleLine: Empty +AllowShortIfStatementsOnASingleLine: false +AllowShortLoopsOnASingleLine: false +AlwaysBreakAfterDefinitionReturnType: false +AlwaysBreakAfterReturnType: None +AlwaysBreakBeforeMultilineStrings: false +AlwaysBreakTemplateDeclarations: true +BinPackArguments: false +BinPackParameters: false + +# Configure each individual brace in BraceWrapping +BreakBeforeBraces: Custom +# Control of individual brace wrapping cases +BraceWrapping: { + AfterClass: 'true' + AfterControlStatement: 'true' + AfterEnum : 'true' + AfterFunction : 'true' + AfterNamespace : 'true' + AfterStruct : 'true' + AfterUnion : 'true' + BeforeCatch : 'true' + BeforeElse : 'true' + IndentBraces : 'false' +# AfterExternBlock : 'true' +} + +#BreakAfterJavaFieldAnnotations: true +#BreakBeforeInheritanceComma: false +#BreakBeforeBinaryOperators: None +#BreakBeforeTernaryOperators: true +#BreakConstructorInitializersBeforeComma: true +#BreakStringLiterals: true + +CommentPragmas: '^ IWYU pragma:' +#CompactNamespaces: false +ConstructorInitializerAllOnOneLineOrOnePerLine: false +ConstructorInitializerIndentWidth: 4 +ContinuationIndentWidth: 4 +Cpp11BracedListStyle: true +#SpaceBeforeCpp11BracedList: false +DerivePointerAlignment: false +ExperimentalAutoDetectBinPacking: false +ForEachMacros: [ foreach, Q_FOREACH, BOOST_FOREACH ] +IndentCaseLabels: false +#FixNamespaceComments: true +IndentWrappedFunctionNames: true +KeepEmptyLinesAtTheStartOfBlocks: true +MacroBlockBegin: '' +MacroBlockEnd: '' +#JavaScriptQuotes: Double +MaxEmptyLinesToKeep: 1 +NamespaceIndentation: All +ObjCBlockIndentWidth: 4 +#ObjCSpaceAfterProperty: true +#ObjCSpaceBeforeProtocolList: true +PenaltyBreakBeforeFirstCallParameter: 19 +PenaltyBreakComment: 300 +PenaltyBreakFirstLessLess: 120 +PenaltyBreakString: 1000 + +PenaltyExcessCharacter: 1000000 +PenaltyReturnTypeOnItsOwnLine: 60 +PointerAlignment: Left +SpaceAfterCStyleCast: false +SpaceBeforeAssignmentOperators: true +SpaceBeforeParens: Never +SpaceInEmptyParentheses: false +SpacesBeforeTrailingComments: 1 +SpacesInAngles: false +SpacesInContainerLiterals: true +SpacesInCStyleCastParentheses: false +SpacesInParentheses: false +SpacesInSquareBrackets: false +#SpaceAfterTemplateKeyword: true +#SpaceBeforeInheritanceColon: true + +#SortUsingDeclarations: true +SortIncludes: true + +# Comments are for developers, they should arrange them +ReflowComments: false + +#IncludeBlocks: Preserve +#IndentPPDirectives: AfterHash +--- diff --git a/.githooks/install b/.githooks/install new file mode 100755 index 0000000..cbb0569 --- /dev/null +++ b/.githooks/install @@ -0,0 +1,8 @@ +#!/usr/bin/env bash + +cd $(git rev-parse --git-dir) +cd hooks + +echo "Installing hooks..." +ln -s ../../.githooks/pre-commit pre-commit +echo "Done!" diff --git a/.githooks/pre-commit b/.githooks/pre-commit new file mode 100755 index 0000000..aea1a69 --- /dev/null +++ b/.githooks/pre-commit @@ -0,0 +1,43 @@ +#!/bin/sh +# +# This pre-commit hook checks if any versions of clang-format +# are installed, and if so, uses the installed version to format +# the staged changes. + +base=/opt/rocm/hcc/bin/clang-format +format="" + +# Redirect output to stderr. +exec 1>&2 + + # check if clang-format is installed +type "$base" >/dev/null 2>&1 && format="$base" + +# no versions of clang-format are installed +if [ -z "$format" ] +then + echo "$base is not installed. Pre-commit hook will not be executed." + exit 0 +fi + +# Do everything from top - level +cd $(git rev-parse --show-toplevel) + +if git rev-parse --verify HEAD >/dev/null 2>&1 +then + against=HEAD +else + # Initial commit: diff against an empty tree object + against=4b825dc642cb6eb9a060e54bf8d69288fbee4904 +fi + +# do the formatting +for file in $(git diff-index --cached --name-only $against | grep -E '\.h$|\.hpp$|\.cpp$|\.cl$|\.h\.in$|\.hpp\.in$|\.cpp\.in$') +do + if [ -e "$file" ] + then + echo "$format $file" + "$format" -i -style=file "$file" + fi +done + diff --git a/Jenkinsfile b/Jenkinsfile index 0d3d81d..fbadf4e 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -1,6 +1,6 @@ #!/usr/bin/env groovy // This shared library is available at https://github.com/ROCmSoftwarePlatform/rocJENKINS/ -@Library('rocJenkins') _ +@Library('rocJenkins@clang9') _ // This is file for internal AMD use. // If you are interested in running your own Jenkins, please raise a github issue for assistance. diff --git a/examples/cpp_integration/device.h b/examples/cpp_integration/device.h index e398edf..0ecf9d0 100644 --- a/examples/cpp_integration/device.h +++ b/examples/cpp_integration/device.h @@ -4,4 +4,3 @@ // function prototype void sort_on_device(thrust::host_vector& V); - diff --git a/examples/cpp_integration/host.cpp b/examples/cpp_integration/host.cpp index 009f3fa..2a17568 100644 --- a/examples/cpp_integration/host.cpp +++ b/examples/cpp_integration/host.cpp @@ -1,10 +1,10 @@ -#include -#include -#include -#include #include #include #include +#include +#include +#include +#include // defines the function prototype #include "device.h" @@ -12,7 +12,7 @@ int main(void) { // generate 20 random numbers on the host - thrust::host_vector h_vec(20); + thrust::host_vector h_vec(20); thrust::default_random_engine rng; thrust::generate(h_vec.begin(), h_vec.end(), rng); @@ -24,4 +24,3 @@ int main(void) return 0; } - diff --git a/examples/include/timer.h b/examples/include/timer.h index 66c1d2d..bfd91cf 100644 --- a/examples/include/timer.h +++ b/examples/include/timer.h @@ -22,53 +22,53 @@ // use CUDA's high-resolution timers when possible #include +#include #include #include -#include void cuda_safe_call(hipError_t error, const std::string& message = "") { - if(error) - throw thrust::system_error(error, thrust::cuda_category(), message); + if(error) + throw thrust::system_error(error, thrust::cuda_category(), message); } struct timer { - hipEvent_t start; - hipEvent_t end; - - timer(void) - { - cuda_safe_call(hipEventCreate(&start)); - cuda_safe_call(hipEventCreate(&end)); - restart(); - } - - ~timer(void) - { - cuda_safe_call(hipEventDestroy(start)); - cuda_safe_call(hipEventDestroy(end)); - } - - void restart(void) - { - cuda_safe_call(hipEventRecord(start, 0)); - } - - double elapsed(void) - { - cuda_safe_call(hipEventRecord(end, 0)); - cuda_safe_call(hipEventSynchronize(end)); - - float ms_elapsed; - cuda_safe_call(hipEventElapsedTime(&ms_elapsed, start, end)); - return ms_elapsed / 1e3; - } - - double epsilon(void) - { - return 0.5e-6; - } + hipEvent_t start; + hipEvent_t end; + + timer(void) + { + cuda_safe_call(hipEventCreate(&start)); + cuda_safe_call(hipEventCreate(&end)); + restart(); + } + + ~timer(void) + { + cuda_safe_call(hipEventDestroy(start)); + cuda_safe_call(hipEventDestroy(end)); + } + + void restart(void) + { + cuda_safe_call(hipEventRecord(start, 0)); + } + + double elapsed(void) + { + cuda_safe_call(hipEventRecord(end, 0)); + cuda_safe_call(hipEventSynchronize(end)); + + float ms_elapsed; + cuda_safe_call(hipEventElapsedTime(&ms_elapsed, start, end)); + return ms_elapsed / 1e3; + } + + double epsilon(void) + { + return 0.5e-6; + } }; #else @@ -78,35 +78,32 @@ struct timer struct timer { - clock_t start; - clock_t end; - - timer(void) - { - restart(); - } - - ~timer(void) - { - } - - void restart(void) - { - start = clock(); - } - - double elapsed(void) - { - end = clock(); - - return static_cast(end - start) / static_cast(CLOCKS_PER_SEC); - } - - double epsilon(void) - { - return 1.0 / static_cast(CLOCKS_PER_SEC); - } + clock_t start; + clock_t end; + + timer(void) + { + restart(); + } + + ~timer(void) {} + + void restart(void) + { + start = clock(); + } + + double elapsed(void) + { + end = clock(); + + return static_cast(end - start) / static_cast(CLOCKS_PER_SEC); + } + + double epsilon(void) + { + return 1.0 / static_cast(CLOCKS_PER_SEC); + } }; #endif - diff --git a/performance/build/perftest.h b/performance/build/perftest.h index 4dc195c..b61c52e 100644 --- a/performance/build/perftest.h +++ b/performance/build/perftest.h @@ -1,53 +1,76 @@ -#include +#include #include #include -#include - +#include #include //#include -#define RECORD_RESULT(name, value, units) { std::cout << " " << std::endl; } -#define RECORD_TIME() RECORD_RESULT("Time", best_time, "seconds") -#define RECORD_RATE(name, value, units) RECORD_RESULT(name, (double(value)/best_time), units) -#define RECORD_BANDWIDTH(bytes) RECORD_RATE("Bandwidth", double(bytes) / 1e9, "GBytes/s") -#define RECORD_THROUGHPUT(value) RECORD_RATE("Throughput", double(value) / 1e9, "GOp/s") -#define RECORD_SORTING_RATE(size) RECORD_RATE("Sorting", double(size) / 1e6, "MKeys/s") -#define RECORD_VARIABLE(name, value) { std::cout << " " << std::endl; } -#define RECORD_TEST_STATUS(result, message) { std::cout << " " << std::endl; } -#define RECORD_TEST_SUCCESS() RECORD_TEST_STATUS("Success", "") -#define RECORD_TEST_FAILURE(message) RECORD_TEST_STATUS("Failure", message) -#define BEGIN_TEST(name) { std::cout << "" << std::endl; } -#define END_TEST() { std::cout << "" << std::endl; } -#define BEGIN_TESTSUITE(name) { std::cout << "" << std::endl << "" << std::endl; } -#define END_TESTSUITE() { std::cout << "" << std::endl; } - +#define RECORD_RESULT(name, value, units) \ + { \ + std::cout << " " << std::endl; \ + } +#define RECORD_TIME() RECORD_RESULT("Time", best_time, "seconds") +#define RECORD_RATE(name, value, units) RECORD_RESULT(name, (double(value) / best_time), units) +#define RECORD_BANDWIDTH(bytes) RECORD_RATE("Bandwidth", double(bytes) / 1e9, "GBytes/s") +#define RECORD_THROUGHPUT(value) RECORD_RATE("Throughput", double(value) / 1e9, "GOp/s") +#define RECORD_SORTING_RATE(size) RECORD_RATE("Sorting", double(size) / 1e6, "MKeys/s") +#define RECORD_VARIABLE(name, value) \ + { \ + std::cout << " " \ + << std::endl; \ + } +#define RECORD_TEST_STATUS(result, message) \ + { \ + std::cout << " " \ + << std::endl; \ + } +#define RECORD_TEST_SUCCESS() RECORD_TEST_STATUS("Success", "") +#define RECORD_TEST_FAILURE(message) RECORD_TEST_STATUS("Failure", message) +#define BEGIN_TEST(name) \ + { \ + std::cout << "" << std::endl; \ + } +#define END_TEST() \ + { \ + std::cout << "" << std::endl; \ + } +#define BEGIN_TESTSUITE(name) \ + { \ + std::cout << "" << std::endl \ + << "" << std::endl; \ + } +#define END_TESTSUITE() \ + { \ + std::cout << "" << std::endl; \ + } -#if defined(__GNUC__) // GCC +#if defined(__GNUC__) // GCC #define __HOST_COMPILER_NAME__ "GCC" -# if defined(__GNUC_PATCHLEVEL__) +#if defined(__GNUC_PATCHLEVEL__) #define __HOST_COMPILER_VERSION__ (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) -# else +#else #define __HOST_COMPILER_VERSION__ (__GNUC__ * 10000 + __GNUC_MINOR__ * 100) -# endif +#endif #elif defined(_MSC_VER) // Microsoft Visual C++ #define __HOST_COMPILER_NAME__ "MSVC" -#define __HOST_COMPILER_VERSION__ _MSC_VER +#define __HOST_COMPILER_VERSION__ _MSC_VER #elif defined(__INTEL_COMPILER) // Intel Compiler #define __HOST_COMPILER_NAME__ "ICC" -#define __HOST_COMPILER_VERSION__ __INTEL_COMPILER +#define __HOST_COMPILER_VERSION__ __INTEL_COMPILER #else // Unknown #define __HOST_COMPILER_NAME__ "UNKNOWN" #define __HOST_COMPILER_VERSION__ 0 #endif - inline void RECORD_PLATFORM_INFO(void) { -#if THRUST_DEVICE_SYSTEM==THRUST_DEVICE_SYSTEM_CUDA +#if THRUST_DEVICE_SYSTEM == THRUST_DEVICE_SYSTEM_CUDA int deviceCount; hipGetDeviceCount(&deviceCount); - if (deviceCount == 0){ + if(deviceCount == 0) + { std::cerr << "There is no device supporting CUDA" << std::endl; exit(1); } @@ -57,28 +80,49 @@ inline void RECORD_PLATFORM_INFO(void) hipDeviceProp_t deviceProp; hipGetDeviceProperties(&deviceProp, dev); - if (dev == 0 && deviceProp.major == 9999 && deviceProp.minor == 9999){ + if(dev == 0 && deviceProp.major == 9999 && deviceProp.minor == 9999) + { std::cerr << "There is no device supporting CUDA" << std::endl; exit(1); } std::cout << "" << std::endl; std::cout << " " << std::endl; - std::cout << " " << std::endl; - std::cout << " " << std::endl; - std::cout << " " << std::endl; - std::cout << " " << std::endl; - std::cout << " " << std::endl; - std::cout << " " << std::endl; - std::cout << " " << std::endl; - std::cout << " " << std::endl; - std::cout << " " << std::endl; + std::cout << " " << std::endl; + std::cout << " " << std::endl; + std::cout << " " << std::endl; + std::cout << " " << std::endl; + std::cout << " " << std::endl; + std::cout << " " << std::endl; + std::cout << " " << std::endl; + std::cout << " " << std::endl; + std::cout << " " << std::endl; std::cout << " " << std::endl; std::cout << " " << std::endl; - #ifdef __HIP_PLATFORM_NVCC__ - std::cout << " " << std::endl; - #endif - std::cout << " " << std::endl; +#ifdef __HIP_PLATFORM_NVCC__ + std::cout << " " + << std::endl; +#endif + std::cout << " " << std::endl; std::cout << " " << std::endl; std::cout << " " << std::endl; std::cout << " " << std::endl; @@ -86,26 +130,23 @@ inline void RECORD_PLATFORM_INFO(void) #endif } - -inline void PROCESS_ARGUMENTS(int argc, char **argv) +inline void PROCESS_ARGUMENTS(int argc, char** argv) { - for(int i = 1; i < argc; ++i) - { - if(std::string(argv[i]) == "--device") + for(int i = 1; i < argc; ++i) { - ++i; - if(i == argc) - { - std::cerr << "usage: --device n" << std::endl; - exit(-1); - } + if(std::string(argv[i]) == "--device") + { + ++i; + if(i == argc) + { + std::cerr << "usage: --device n" << std::endl; + exit(-1); + } -#if THRUST_DEVICE_SYSTEM==THRUST_DEVICE_SYSTEM_CUDA - int device_index = atoi(argv[i]); - hipSetDevice(device_index); +#if THRUST_DEVICE_SYSTEM == THRUST_DEVICE_SYSTEM_CUDA + int device_index = atoi(argv[i]); + hipSetDevice(device_index); #endif + } } - } } - - diff --git a/performance/build/timer.h b/performance/build/timer.h index f3f6066..9400abd 100644 --- a/performance/build/timer.h +++ b/performance/build/timer.h @@ -22,53 +22,53 @@ // use CUDA's high-resolution timers when possible #include +#include #include #include -#include void cuda_safe_call(hipError_t error, const std::string& message = "") { - if(error) - throw thrust::system_error(error, thrust::cuda_category(), message); + if(error) + throw thrust::system_error(error, thrust::cuda_category(), message); } struct timer { - hipEvent_t start; - hipEvent_t end; - - timer(void) - { - cuda_safe_call(hipEventCreate(&start)); - cuda_safe_call(hipEventCreate(&end)); - restart(); - } - - ~timer(void) - { - cuda_safe_call(hipEventDestroy(start)); - cuda_safe_call(hipEventDestroy(end)); - } - - void restart(void) - { - cuda_safe_call(hipEventRecord(start, 0)); - } - - double elapsed(void) - { - cuda_safe_call(hipEventRecord(end, 0)); - cuda_safe_call(hipEventSynchronize(end)); - - float ms_elapsed; - cuda_safe_call(hipEventElapsedTime(&ms_elapsed, start, end)); - return ms_elapsed / 1e3; - } - - double epsilon(void) - { - return 0.5e-6; - } + hipEvent_t start; + hipEvent_t end; + + timer(void) + { + cuda_safe_call(hipEventCreate(&start)); + cuda_safe_call(hipEventCreate(&end)); + restart(); + } + + ~timer(void) + { + cuda_safe_call(hipEventDestroy(start)); + cuda_safe_call(hipEventDestroy(end)); + } + + void restart(void) + { + cuda_safe_call(hipEventRecord(start, 0)); + } + + double elapsed(void) + { + cuda_safe_call(hipEventRecord(end, 0)); + cuda_safe_call(hipEventSynchronize(end)); + + float ms_elapsed; + cuda_safe_call(hipEventElapsedTime(&ms_elapsed, start, end)); + return ms_elapsed / 1e3; + } + + double epsilon(void) + { + return 0.5e-6; + } }; #elif defined(__linux__) @@ -77,34 +77,33 @@ struct timer struct timer { - timeval start; - timeval end; - - timer(void) - { - restart(); - } - - ~timer(void) - { - } - - void restart(void) - { - gettimeofday(&start, NULL); - } - - double elapsed(void) - { - gettimeofday(&end, NULL); - - return static_cast(end.tv_sec - start.tv_sec) + 1e-6 * static_cast((int)end.tv_usec - (int)start.tv_usec); - } - - double epsilon(void) - { - return 0.5e-6; - } + timeval start; + timeval end; + + timer(void) + { + restart(); + } + + ~timer(void) {} + + void restart(void) + { + gettimeofday(&start, NULL); + } + + double elapsed(void) + { + gettimeofday(&end, NULL); + + return static_cast(end.tv_sec - start.tv_sec) + + 1e-6 * static_cast((int)end.tv_usec - (int)start.tv_usec); + } + + double epsilon(void) + { + return 0.5e-6; + } }; #else @@ -114,35 +113,32 @@ struct timer struct timer { - clock_t start; - clock_t end; - - timer(void) - { - restart(); - } - - ~timer(void) - { - } - - void restart(void) - { - start = clock(); - } - - double elapsed(void) - { - end = clock(); - - return static_cast(end - start) / static_cast(CLOCKS_PER_SEC); - } - - double epsilon(void) - { - return 1.0 / static_cast(CLOCKS_PER_SEC); - } + clock_t start; + clock_t end; + + timer(void) + { + restart(); + } + + ~timer(void) {} + + void restart(void) + { + start = clock(); + } + + double elapsed(void) + { + end = clock(); + + return static_cast(end - start) / static_cast(CLOCKS_PER_SEC); + } + + double epsilon(void) + { + return 1.0 / static_cast(CLOCKS_PER_SEC); + } }; #endif - diff --git a/testing/backend/omp/nvcc_independence.cpp b/testing/backend/omp/nvcc_independence.cpp index c870928..2613de4 100644 --- a/testing/backend/omp/nvcc_independence.cpp +++ b/testing/backend/omp/nvcc_independence.cpp @@ -1,75 +1,74 @@ -#include #include -#include #include #include #include #include +#include +#include void TestNvccIndependenceTransform(void) { - typedef int T; - const int n = 10; + typedef int T; + const int n = 10; + + thrust::host_vector h_input = unittest::random_integers(n); + thrust::device_vector d_input = h_input; - thrust::host_vector h_input = unittest::random_integers(n); - thrust::device_vector d_input = h_input; + thrust::host_vector h_output(n); + thrust::device_vector d_output(n); - thrust::host_vector h_output(n); - thrust::device_vector d_output(n); + thrust::transform(h_input.begin(), h_input.end(), h_output.begin(), thrust::negate()); + thrust::transform(d_input.begin(), d_input.end(), d_output.begin(), thrust::negate()); - thrust::transform(h_input.begin(), h_input.end(), h_output.begin(), thrust::negate()); - thrust::transform(d_input.begin(), d_input.end(), d_output.begin(), thrust::negate()); - - ASSERT_EQUAL(h_output, d_output); + ASSERT_EQUAL(h_output, d_output); } DECLARE_UNITTEST(TestNvccIndependenceTransform); void TestNvccIndependenceReduce(void) { - typedef int T; - const int n = 10; + typedef int T; + const int n = 10; - thrust::host_vector h_data = unittest::random_integers(n); - thrust::device_vector d_data = h_data; + thrust::host_vector h_data = unittest::random_integers(n); + thrust::device_vector d_data = h_data; - T init = 13; + T init = 13; - T h_result = thrust::reduce(h_data.begin(), h_data.end(), init); - T d_result = thrust::reduce(d_data.begin(), d_data.end(), init); + T h_result = thrust::reduce(h_data.begin(), h_data.end(), init); + T d_result = thrust::reduce(d_data.begin(), d_data.end(), init); - ASSERT_ALMOST_EQUAL(h_result, d_result); + ASSERT_ALMOST_EQUAL(h_result, d_result); } DECLARE_UNITTEST(TestNvccIndependenceReduce); void TestNvccIndependenceExclusiveScan(void) { - typedef int T; - const int n = 10; - - thrust::host_vector h_input = unittest::random_integers(n); - thrust::device_vector d_input = h_input; - - thrust::host_vector h_output(n); - thrust::device_vector d_output(n); - - thrust::inclusive_scan(h_input.begin(), h_input.end(), h_output.begin()); - thrust::inclusive_scan(d_input.begin(), d_input.end(), d_output.begin()); - ASSERT_EQUAL(d_output, h_output); + typedef int T; + const int n = 10; + + thrust::host_vector h_input = unittest::random_integers(n); + thrust::device_vector d_input = h_input; + + thrust::host_vector h_output(n); + thrust::device_vector d_output(n); + + thrust::inclusive_scan(h_input.begin(), h_input.end(), h_output.begin()); + thrust::inclusive_scan(d_input.begin(), d_input.end(), d_output.begin()); + ASSERT_EQUAL(d_output, h_output); } DECLARE_UNITTEST(TestNvccIndependenceExclusiveScan); void TestNvccIndependenceSort(void) { - typedef int T; - const int n = 10; + typedef int T; + const int n = 10; - thrust::host_vector h_data = unittest::random_integers(n); - thrust::device_vector d_data = h_data; + thrust::host_vector h_data = unittest::random_integers(n); + thrust::device_vector d_data = h_data; - thrust::sort(h_data.begin(), h_data.end(), thrust::less()); - thrust::sort(d_data.begin(), d_data.end(), thrust::less()); + thrust::sort(h_data.begin(), h_data.end(), thrust::less()); + thrust::sort(d_data.begin(), d_data.end(), thrust::less()); - ASSERT_EQUAL(h_data, d_data); + ASSERT_EQUAL(h_data, d_data); } DECLARE_UNITTEST(TestNvccIndependenceSort); - diff --git a/testing/testframework.cpp b/testing/testframework.cpp index 57006b0..a5b6a35 100644 --- a/testing/testframework.cpp +++ b/testing/testframework.cpp @@ -2,520 +2,614 @@ #include "unittest/exceptions.h" #include -// #include backends' testframework.h, if they exist and are required for the build +// #include backends' testframework.h, if they exist and are required for the +// build #if THRUST_DEVICE_SYSTEM == THRUST_DEVICE_SYSTEM_CUDA #include "backend/cuda/testframework.h" #endif -#include -#include -#include #include -#include -#include -#include +#include #include +#include +#include #include +#include +#include - -const size_t standard_test_sizes[] = -{ - 0, 1, 2, 3, 4, 5, 8, 10, 13, 16, 17, 19, 27, 30, 31, 32, - 33, 35, 42, 53, 58, 63, 64, 65, 72, 97, 100, 127, 128, 129, 142, 183, 192, 201, 240, 255, 256, - 257, 302, 511, 512, 513, 687, 900, 1023, 1024, 1025, 1565, 1786, 1973, 2047, 2048, 2049, 3050, 4095, 4096, - 4097, 5030, 7791, 10000, 10027, 12345, 16384, 17354, 26255, 32768, 43718, 65533, 65536, - 65539, 123456, 131072, 731588, 1048575, 1048576, - 3398570, 9760840, (1 << 24) - 1, (1 << 24), - (1 << 24) + 1, (1 << 25) - 1, (1 << 25), (1 << 25) + 1, (1 << 26) - 1, 1 << 26, - (1 << 26) + 1, (1 << 27) - 1, (1 << 27) -}; - - -const size_t tiny_threshold = 1 << 5; // 32 -const size_t small_threshold = 1 << 8; // 256 -const size_t medium_threshold = 1 << 12; // 4K -const size_t default_threshold = 1 << 16; // 64K -const size_t large_threshold = 1 << 20; // 1M -const size_t huge_threshold = 1 << 24; // 16M -const size_t epic_threshold = 1 << 26; // 64M +const size_t standard_test_sizes[] = {0, + 1, + 2, + 3, + 4, + 5, + 8, + 10, + 13, + 16, + 17, + 19, + 27, + 30, + 31, + 32, + 33, + 35, + 42, + 53, + 58, + 63, + 64, + 65, + 72, + 97, + 100, + 127, + 128, + 129, + 142, + 183, + 192, + 201, + 240, + 255, + 256, + 257, + 302, + 511, + 512, + 513, + 687, + 900, + 1023, + 1024, + 1025, + 1565, + 1786, + 1973, + 2047, + 2048, + 2049, + 3050, + 4095, + 4096, + 4097, + 5030, + 7791, + 10000, + 10027, + 12345, + 16384, + 17354, + 26255, + 32768, + 43718, + 65533, + 65536, + 65539, + 123456, + 131072, + 731588, + 1048575, + 1048576, + 3398570, + 9760840, + (1 << 24) - 1, + (1 << 24), + (1 << 24) + 1, + (1 << 25) - 1, + (1 << 25), + (1 << 25) + 1, + (1 << 26) - 1, + 1 << 26, + (1 << 26) + 1, + (1 << 27) - 1, + (1 << 27)}; + +const size_t tiny_threshold = 1 << 5; // 32 +const size_t small_threshold = 1 << 8; // 256 +const size_t medium_threshold = 1 << 12; // 4K +const size_t default_threshold = 1 << 16; // 64K +const size_t large_threshold = 1 << 20; // 1M +const size_t huge_threshold = 1 << 24; // 16M +const size_t epic_threshold = 1 << 26; // 64M const size_t max_threshold = std::numeric_limits::max(); - std::vector test_sizes; - std::vector get_test_sizes(void) { - return test_sizes; + return test_sizes; } - void set_test_sizes(const std::string& val) { - size_t threshold = 0; - - if(val == "tiny") - threshold = tiny_threshold; - else if(val == "small") - threshold = small_threshold; - else if(val == "medium") - threshold = medium_threshold; - else if(val == "default") - threshold = default_threshold; - else if(val == "large") - threshold = large_threshold; - else if(val == "huge") - threshold = huge_threshold; - else if(val == "epic") - threshold = epic_threshold; - else if(val == "max") - threshold = max_threshold; - else - { - std::cerr << "invalid test size \"" << val << "\"" << std::endl; - exit(1); - } - - for(size_t i = 0; i < sizeof(standard_test_sizes) / sizeof(*standard_test_sizes); i++) - { - if(standard_test_sizes[i] <= threshold) - test_sizes.push_back(standard_test_sizes[i]); - } -} + size_t threshold = 0; + + if(val == "tiny") + threshold = tiny_threshold; + else if(val == "small") + threshold = small_threshold; + else if(val == "medium") + threshold = medium_threshold; + else if(val == "default") + threshold = default_threshold; + else if(val == "large") + threshold = large_threshold; + else if(val == "huge") + threshold = huge_threshold; + else if(val == "epic") + threshold = epic_threshold; + else if(val == "max") + threshold = max_threshold; + else + { + std::cerr << "invalid test size \"" << val << "\"" << std::endl; + exit(1); + } + for(size_t i = 0; i < sizeof(standard_test_sizes) / sizeof(*standard_test_sizes); i++) + { + if(standard_test_sizes[i] <= threshold) + test_sizes.push_back(standard_test_sizes[i]); + } +} -void UnitTestDriver::register_test(UnitTest * test) +void UnitTestDriver::register_test(UnitTest* test) { - if(UnitTestDriver::s_driver().test_map.count(test->name) ) - { - std::cout << "[WARNING] Test name \"" << test->name << " already encountered " << std::endl; - } + if(UnitTestDriver::s_driver().test_map.count(test->name)) + { + std::cout << "[WARNING] Test name \"" << test->name << " already encountered " << std::endl; + } - UnitTestDriver::s_driver().test_map[test->name] = test; + UnitTestDriver::s_driver().test_map[test->name] = test; } - -UnitTest::UnitTest(const char * _name) : name(_name) +UnitTest::UnitTest(const char* _name) + : name(_name) { - UnitTestDriver::s_driver().register_test(this); + UnitTestDriver::s_driver().register_test(this); } - -void process_args(int argc, char ** argv, - ArgumentSet& args, - ArgumentMap& kwargs) +void process_args(int argc, char** argv, ArgumentSet& args, ArgumentMap& kwargs) { - for(int i = 1; i < argc; i++) - { - std::string arg(argv[i]); - - // look for --key or --key=value arguments - if(arg.substr(0,2) == "--") - { - std::string::size_type n = arg.find('=',2); - - if(n == std::string::npos) - { - kwargs[arg.substr(2)] = std::string(); // (key,"") - } - else - { - kwargs[arg.substr(2, n - 2)] = arg.substr(n + 1); // (key,value) - } - } - else + for(int i = 1; i < argc; i++) { - args.insert(arg); + std::string arg(argv[i]); + + // look for --key or --key=value arguments + if(arg.substr(0, 2) == "--") + { + std::string::size_type n = arg.find('=', 2); + + if(n == std::string::npos) + { + kwargs[arg.substr(2)] = std::string(); // (key,"") + } + else + { + kwargs[arg.substr(2, n - 2)] = arg.substr(n + 1); // (key,value) + } + } + else + { + args.insert(arg); + } } - } } - void usage(int argc, char** argv) { - std::string indent = " "; - - std::cout << "Example Usage:\n"; - std::cout << indent << argv[0] << "\n"; - std::cout << indent << argv[0] << " TestName1 [TestName2 ...] \n"; - std::cout << indent << argv[0] << " PartialTestName1* [PartialTestName2* ...] \n"; - std::cout << indent << argv[0] << " --device=1\n"; - std::cout << indent << argv[0] << " --sizes={tiny,small,medium,default,large,huge,epic,max}\n"; - std::cout << indent << argv[0] << " --verbose or --concise\n"; - std::cout << indent << argv[0] << " --list\n"; - std::cout << indent << argv[0] << " --help\n"; - std::cout << "\n"; - std::cout << "Options:\n"; - std::cout << indent << "The sizes option determines which input sizes are tested.\n"; - std::cout << indent << indent << "--sizes=tiny tests sizes up to " << tiny_threshold << "\n"; - std::cout << indent << indent << "--sizes=small tests sizes up to " << small_threshold << "\n"; - std::cout << indent << indent << "--sizes=medium tests sizes up to " << medium_threshold << "\n"; - std::cout << indent << indent << "--sizes=default tests sizes up to " << default_threshold << "\n"; - std::cout << indent << indent << "--sizes=large tests sizes up to " << large_threshold << " (0.25 GB memory)\n"; - std::cout << indent << indent << "--sizes=huge tests sizes up to " << huge_threshold << " (1.50 GB memory)\n"; - std::cout << indent << indent << "--sizes=epic tests sizes up to " << epic_threshold << " (3.00 GB memory)\n"; - std::cout << indent << indent << "--sizes=max tests all available sizes\n"; + std::string indent = " "; + + std::cout << "Example Usage:\n"; + std::cout << indent << argv[0] << "\n"; + std::cout << indent << argv[0] << " TestName1 [TestName2 ...] \n"; + std::cout << indent << argv[0] << " PartialTestName1* [PartialTestName2* ...] \n"; + std::cout << indent << argv[0] << " --device=1\n"; + std::cout << indent << argv[0] << " --sizes={tiny,small,medium,default,large,huge,epic,max}\n"; + std::cout << indent << argv[0] << " --verbose or --concise\n"; + std::cout << indent << argv[0] << " --list\n"; + std::cout << indent << argv[0] << " --help\n"; + std::cout << "\n"; + std::cout << "Options:\n"; + std::cout << indent << "The sizes option determines which input sizes are tested.\n"; + std::cout << indent << indent << "--sizes=tiny tests sizes up to " << tiny_threshold << "\n"; + std::cout << indent << indent << "--sizes=small tests sizes up to " << small_threshold + << "\n"; + std::cout << indent << indent << "--sizes=medium tests sizes up to " << medium_threshold + << "\n"; + std::cout << indent << indent << "--sizes=default tests sizes up to " << default_threshold + << "\n"; + std::cout << indent << indent << "--sizes=large tests sizes up to " << large_threshold + << " (0.25 GB memory)\n"; + std::cout << indent << indent << "--sizes=huge tests sizes up to " << huge_threshold + << " (1.50 GB memory)\n"; + std::cout << indent << indent << "--sizes=epic tests sizes up to " << epic_threshold + << " (3.00 GB memory)\n"; + std::cout << indent << indent << "--sizes=max tests all available sizes\n"; } - struct TestResult { - TestStatus status; - std::string name; - std::string message; - - // XXX use a c++11 timer result when available - /*std::*/clock_t elapsed; - - TestResult(const TestStatus status, /*std::*/clock_t elapsed, const UnitTest& u, const std::string& message = "") - : status(status), name(u.name), message(message), elapsed(elapsed) - {} - - bool operator<(const TestResult& tr) const - { - if(status < tr.status) + TestStatus status; + std::string name; + std::string message; + + // XXX use a c++11 timer result when available + /*std::*/ clock_t elapsed; + + TestResult(const TestStatus status, + /*std::*/ clock_t elapsed, + const UnitTest& u, + const std::string& message = "") + : status(status) + , name(u.name) + , message(message) + , elapsed(elapsed) { - return true; } - else if(tr.status < status) + + bool operator<(const TestResult& tr) const { - return false; + if(status < tr.status) + { + return true; + } + else if(tr.status < status) + { + return false; + } + else + { + return name < tr.name; + } } - else +}; + +void record_result(const TestResult& test_result, std::vector& test_results) +{ + test_results.push_back(test_result); +} + +void report_results(std::vector& test_results, double elapsed_minutes) +{ + std::cout << std::endl; + + std::string hline = "================================================================"; + + std::sort(test_results.begin(), test_results.end()); + + size_t num_passes = 0; + size_t num_failures = 0; + size_t num_known_failures = 0; + size_t num_errors = 0; + + for(size_t i = 0; i < test_results.size(); i++) { - return name < tr.name; + const TestResult& tr = test_results[i]; + + if(tr.status == Pass) + { + num_passes++; + } + else + { + std::cout << hline << std::endl; + + switch(tr.status) + { + case Failure: + std::cout << "FAILURE"; + num_failures++; + break; + case KnownFailure: + std::cout << "KNOWN FAILURE"; + num_known_failures++; + break; + case Error: + std::cout << "ERROR"; + num_errors++; + break; + default: + break; + } + + std::cout << ": " << tr.name << std::endl << tr.message << std::endl; + } } - } -}; + std::cout << hline << std::endl; + + std::cout << "Totals: "; + std::cout << num_failures << " failures, "; + std::cout << num_known_failures << " known failures, "; + std::cout << num_errors << " errors, and "; + std::cout << num_passes << " passes." << std::endl; + std::cout << "Time: " << elapsed_minutes << " minutes" << std::endl; +} -void record_result(const TestResult& test_result, std::vector< TestResult >& test_results) +void UnitTestDriver::list_tests(void) { - test_results.push_back(test_result); + for(TestMap::iterator iter = test_map.begin(); iter != test_map.end(); iter++) + { + std::cout << iter->second->name << std::endl; + } } +bool UnitTestDriver::post_test_sanity_check(const UnitTest& test, bool concise) +{ + return true; +} -void report_results(std::vector< TestResult >& test_results, double elapsed_minutes) +bool UnitTestDriver::run_tests(std::vector& tests_to_run, const ArgumentMap& kwargs) { - std::cout << std::endl; - - std::string hline = "================================================================"; - - std::sort(test_results.begin(), test_results.end()); - - size_t num_passes = 0; - size_t num_failures = 0; - size_t num_known_failures = 0; - size_t num_errors = 0; - - for(size_t i = 0; i < test_results.size(); i++) - { - const TestResult& tr = test_results[i]; - - if(tr.status == Pass) + std::time_t start_time = std::time(0); + + bool verbose = kwargs.count("verbose"); + bool concise = kwargs.count("concise"); + + std::vector test_results; + + if(verbose && concise) { - num_passes++; + std::cout << "--verbose and --concise cannot be used together" << std::endl; + exit(EXIT_FAILURE); } - else + + if(!concise) { - std::cout << hline << std::endl; - - switch(tr.status) - { - case Failure: - std::cout << "FAILURE"; num_failures++; break; - case KnownFailure: - std::cout << "KNOWN FAILURE"; num_known_failures++; break; - case Error: - std::cout << "ERROR"; num_errors++; break; - default: - break; - } - - std::cout << ": " << tr.name << std::endl << tr.message << std::endl; + std::cout << "Running " << tests_to_run.size() << " unit tests." << std::endl; } - } - - std::cout << hline << std::endl; - - std::cout << "Totals: "; - std::cout << num_failures << " failures, "; - std::cout << num_known_failures << " known failures, "; - std::cout << num_errors << " errors, and "; - std::cout << num_passes << " passes." << std::endl; - std::cout << "Time: " << elapsed_minutes << " minutes" << std::endl; -} + for(size_t i = 0; i < tests_to_run.size(); i++) + { + UnitTest& test = *tests_to_run[i]; -void UnitTestDriver::list_tests(void) -{ - for(TestMap::iterator iter = test_map.begin(); iter != test_map.end(); iter++) - { - std::cout << iter->second->name << std::endl; - } -} + if(verbose) + { + std::cout << "Running " << test.name << "..." << std::flush; + } + try + { + // time the test + /*std::*/ clock_t start = std::clock(); -bool UnitTestDriver::post_test_sanity_check(const UnitTest &test, bool concise) -{ - return true; -} + // run the test + test.run(); + + // test passed + record_result(TestResult(Pass, std::clock() - start, test), test_results); + } + catch(unittest::UnitTestFailure& f) + { + record_result( + TestResult(Failure, std::numeric_limits::max(), test, f.message), + test_results); + } + catch(unittest::UnitTestKnownFailure& f) + { + record_result( + TestResult( + KnownFailure, std::numeric_limits::max(), test, f.message), + test_results); + } + catch(std::bad_alloc& e) + { + record_result( + TestResult(Error, std::numeric_limits::max(), test, e.what()), + test_results); + } + catch(unittest::UnitTestError& e) + { + record_result( + TestResult(Error, std::numeric_limits::max(), test, e.message), + test_results); + } + // immediate report + if(!concise) + { + if(verbose) + { + switch(test_results.back().status) + { + case Pass: + std::cout << "\r[PASS] "; + std::cout << std::setw(10) + << 1000.f * float(test_results.back().elapsed) / CLOCKS_PER_SEC + << " ms"; + break; + case Failure: + std::cout << "\r[FAILURE] "; + break; + case KnownFailure: + std::cout << "\r[KNOWN FAILURE] "; + break; + case Error: + std::cout << "\r[ERROR] "; + break; + default: + break; + } + + std::cout << " " << test.name << std::endl; + } + else + { + switch(test_results.back().status) + { + case Pass: + std::cout << "."; + break; + case Failure: + std::cout << "F"; + break; + case KnownFailure: + std::cout << "K"; + break; + case Error: + std::cout << "E"; + break; + default: + break; + } + } + } -bool UnitTestDriver::run_tests(std::vector& tests_to_run, const ArgumentMap& kwargs) -{ - std::time_t start_time = std::time(0); - - bool verbose = kwargs.count("verbose"); - bool concise = kwargs.count("concise"); - - std::vector< TestResult > test_results; - - if(verbose && concise) - { - std::cout << "--verbose and --concise cannot be used together" << std::endl; - exit(EXIT_FAILURE); - } - - if(!concise) - { - std::cout << "Running " << tests_to_run.size() << " unit tests." << std::endl; - } - - for(size_t i = 0; i < tests_to_run.size(); i++) - { - UnitTest& test = *tests_to_run[i]; - - if(verbose) - { - std::cout << "Running " << test.name << "..." << std::flush; - } - - try - { - // time the test - /*std::*/clock_t start = std::clock(); - - // run the test - test.run(); - - // test passed - record_result(TestResult(Pass, std::clock() - start, test), test_results); - } - catch(unittest::UnitTestFailure& f) - { - record_result(TestResult(Failure, std::numeric_limits::max(), test, f.message), test_results); - } - catch(unittest::UnitTestKnownFailure& f) - { - record_result(TestResult(KnownFailure, std::numeric_limits::max(), test, f.message), test_results); - } - catch(std::bad_alloc& e) - { - record_result(TestResult(Error, std::numeric_limits::max(), test, e.what()), test_results); - } - catch(unittest::UnitTestError& e) - { - record_result(TestResult(Error, std::numeric_limits::max(), test, e.message), test_results); - } - - // immediate report - if(!concise) - { - if(verbose) - { - switch(test_results.back().status) - { - case Pass: - std::cout << "\r[PASS] "; - std::cout << std::setw(10) << 1000.f * float(test_results.back().elapsed) / CLOCKS_PER_SEC << " ms"; - break; - case Failure: - std::cout << "\r[FAILURE] "; break; - case KnownFailure: - std::cout << "\r[KNOWN FAILURE] "; break; - case Error: - std::cout << "\r[ERROR] "; break; - default: - break; - } - - std::cout << " " << test.name << std::endl; - } - else - { - switch(test_results.back().status) - { - case Pass: - std::cout << "."; break; - case Failure: - std::cout << "F"; break; - case KnownFailure: - std::cout << "K"; break; - case Error: - std::cout << "E"; break; - default: - break; - } - } - } - - if(!post_test_sanity_check(test, concise)) - { - return false; - } - - std::cout.flush(); - } - - double elapsed_minutes = double(std::time(0) - start_time) / 60; - - // summary report - if(!concise) - { - report_results(test_results, elapsed_minutes); - } - - - // if any failures or errors return false - for(size_t i = 0; i < test_results.size(); i++) - { - if(test_results[i].status != Pass && test_results[i].status != KnownFailure) + if(!post_test_sanity_check(test, concise)) + { + return false; + } + + std::cout.flush(); + } + + double elapsed_minutes = double(std::time(0) - start_time) / 60; + + // summary report + if(!concise) { - return false; + report_results(test_results, elapsed_minutes); + } + + // if any failures or errors return false + for(size_t i = 0; i < test_results.size(); i++) + { + if(test_results[i].status != Pass && test_results[i].status != KnownFailure) + { + return false; + } } - } - - // all tests pass or are known failures - return true; -} + // all tests pass or are known failures + return true; +} bool UnitTestDriver::run_tests(const ArgumentSet& args, const ArgumentMap& kwargs) { - if(args.empty()) - { - // run all tests - std::vector tests_to_run; - - for(TestMap::iterator iter = test_map.begin(); iter != test_map.end(); iter++) - { - tests_to_run.push_back(iter->second); - } - - return run_tests(tests_to_run, kwargs); - } - else - { - // all non-keyword arguments are assumed to be test names or partial test names - - typedef TestMap::iterator TestMapIterator; - - // vector to accumulate tests - std::vector tests_to_run; - - for(ArgumentSet::const_iterator iter = args.begin(); iter != args.end(); iter++) + if(args.empty()) { - const std::string& arg = *iter; - - size_t len = arg.size(); - size_t matches = 0; - - if(arg[len-1] == '*') - { - // wildcard search - std::string search = arg.substr(0,len-1); - - TestMapIterator lb = test_map.lower_bound(search); - while(lb != test_map.end()) + // run all tests + std::vector tests_to_run; + + for(TestMap::iterator iter = test_map.begin(); iter != test_map.end(); iter++) { - if(search != lb->first.substr(0,len-1)) - { - break; - } - - tests_to_run.push_back(lb->second); - lb++; - matches++; + tests_to_run.push_back(iter->second); } - } - else - { - // non-wildcard search - TestMapIterator lb = test_map.find(arg); - - if(lb != test_map.end()) + + return run_tests(tests_to_run, kwargs); + } + else + { + // all non-keyword arguments are assumed to be test names or partial test + // names + + typedef TestMap::iterator TestMapIterator; + + // vector to accumulate tests + std::vector tests_to_run; + + for(ArgumentSet::const_iterator iter = args.begin(); iter != args.end(); iter++) { - tests_to_run.push_back(lb->second); - matches++; + const std::string& arg = *iter; + + size_t len = arg.size(); + size_t matches = 0; + + if(arg[len - 1] == '*') + { + // wildcard search + std::string search = arg.substr(0, len - 1); + + TestMapIterator lb = test_map.lower_bound(search); + while(lb != test_map.end()) + { + if(search != lb->first.substr(0, len - 1)) + { + break; + } + + tests_to_run.push_back(lb->second); + lb++; + matches++; + } + } + else + { + // non-wildcard search + TestMapIterator lb = test_map.find(arg); + + if(lb != test_map.end()) + { + tests_to_run.push_back(lb->second); + matches++; + } + } + + if(matches == 0) + { + std::cout << "[ERROR] found no test names matching the pattern: " << arg + << std::endl; + return false; + } } - } - - if(matches == 0) - { - std::cout << "[ERROR] found no test names matching the pattern: " << arg << std::endl; - return false; - } + + return run_tests(tests_to_run, kwargs); } - - return run_tests(tests_to_run, kwargs); - } } - // driver_instance maps a DeviceSystem to a singleton UnitTestDriver -//template -UnitTestDriver &driver_instance(/*DeviceSystem tag*/) +// template +UnitTestDriver& driver_instance(/*DeviceSystem tag*/) { - static UnitTestDriver s_instance; - return s_instance; + static UnitTestDriver s_instance; + return s_instance; } - // if we need a special kind of UnitTestDriver, overload // driver_instance in that function -UnitTestDriver &UnitTestDriver::s_driver() +UnitTestDriver& UnitTestDriver::s_driver() { - return driver_instance(/*thrust::device_system_tag()*/); + return driver_instance(/*thrust::device_system_tag()*/); } - -int main(int argc, char **argv) +int main(int argc, char** argv) { - ArgumentSet args; - ArgumentMap kwargs; - - process_args(argc, argv, args, kwargs); - - if(kwargs.count("help")) - { - usage(argc, argv); - return 0; - } - - if(kwargs.count("list")) - { - UnitTestDriver::s_driver().list_tests(); - return 0; - } - - if(kwargs.count("sizes")) - { - set_test_sizes(kwargs["sizes"]); - } - else - { - set_test_sizes("default"); - } - - bool passed = UnitTestDriver::s_driver().run_tests(args, kwargs); - - if(kwargs.count("concise")) - { - std::cout << ((passed) ? "PASSED" : "FAILED") << std::endl; - } - - return (passed) ? EXIT_SUCCESS : EXIT_FAILURE; -} + ArgumentSet args; + ArgumentMap kwargs; + process_args(argc, argv, args, kwargs); + + if(kwargs.count("help")) + { + usage(argc, argv); + return 0; + } + + if(kwargs.count("list")) + { + UnitTestDriver::s_driver().list_tests(); + return 0; + } + + if(kwargs.count("sizes")) + { + set_test_sizes(kwargs["sizes"]); + } + else + { + set_test_sizes("default"); + } + + bool passed = UnitTestDriver::s_driver().run_tests(args, kwargs); + + if(kwargs.count("concise")) + { + std::cout << ((passed) ? "PASSED" : "FAILED") << std::endl; + } + + return (passed) ? EXIT_SUCCESS : EXIT_FAILURE; +} diff --git a/testing/unittest/assertions.h b/testing/unittest/assertions.h index 0e9f308..92d112c 100644 --- a/testing/unittest/assertions.h +++ b/testing/unittest/assertions.h @@ -1,357 +1,444 @@ #pragma once #include -#include +#include #include +#include #include -#include #include #include -#define ASSERT_EQUAL_QUIET(X,Y) unittest::assert_equal_quiet((X),(Y), __FILE__, __LINE__) -#define ASSERT_EQUAL(X,Y) unittest::assert_equal((X),(Y), __FILE__, __LINE__) -#define ASSERT_LEQUAL(X,Y) unittest::assert_lequal((X),(Y), __FILE__, __LINE__) -#define ASSERT_GEQUAL(X,Y) unittest::assert_gequal((X),(Y), __FILE__, __LINE__) -#define ASSERT_ALMOST_EQUAL(X,Y) unittest::assert_almost_equal((X),(Y), __FILE__, __LINE__) -#define KNOWN_FAILURE { unittest::UnitTestKnownFailure f; f << "[" << __FILE__ ":" << __LINE__ << "]"; throw f;} - -#define ASSERT_EQUAL_RANGES(X,Y,Z) unittest::assert_equal((X),(Y),(Z), __FILE__, __LINE__) - -#define ASSERT_THROWS(X,Y) \ - { bool thrown = false; try { X; } catch (Y) { thrown = true; } \ - if (!thrown) { unittest::UnitTestFailure f; f << "[" << __FILE__ << ":" << __LINE__ << "] did not throw " << #Y; throw f; } \ +#define ASSERT_EQUAL_QUIET(X, Y) unittest::assert_equal_quiet((X), (Y), __FILE__, __LINE__) +#define ASSERT_EQUAL(X, Y) unittest::assert_equal((X), (Y), __FILE__, __LINE__) +#define ASSERT_LEQUAL(X, Y) unittest::assert_lequal((X), (Y), __FILE__, __LINE__) +#define ASSERT_GEQUAL(X, Y) unittest::assert_gequal((X), (Y), __FILE__, __LINE__) +#define ASSERT_ALMOST_EQUAL(X, Y) unittest::assert_almost_equal((X), (Y), __FILE__, __LINE__) +#define KNOWN_FAILURE \ + { \ + unittest::UnitTestKnownFailure f; \ + f << "[" << __FILE__ ":" << __LINE__ << "]"; \ + throw f; \ } +#define ASSERT_EQUAL_RANGES(X, Y, Z) unittest::assert_equal((X), (Y), (Z), __FILE__, __LINE__) + +#define ASSERT_THROWS(X, Y) \ + { \ + bool thrown = false; \ + try \ + { \ + X; \ + } \ + catch(Y) \ + { \ + thrown = true; \ + } \ + if(!thrown) \ + { \ + unittest::UnitTestFailure f; \ + f << "[" << __FILE__ << ":" << __LINE__ << "] did not throw " << #Y; \ + throw f; \ + } \ + } namespace unittest { -static size_t MAX_OUTPUT_LINES = 10; + static size_t MAX_OUTPUT_LINES = 10; -static double DEFAULT_RELATIVE_TOL = 1e-4; -static double DEFAULT_ABSOLUTE_TOL = 1e-4; + static double DEFAULT_RELATIVE_TOL = 1e-4; + static double DEFAULT_ABSOLUTE_TOL = 1e-4; -template - struct value_type -{ - typedef typename thrust::detail::remove_const< - typename thrust::detail::remove_reference< - T - >::type - >::type type; -}; - -template - struct value_type< thrust::device_reference > -{ - typedef typename value_type::type type; -}; - -//// -// check scalar values -template -void assert_equal(const T1& a, const T2& b, - const std::string& filename = "unknown", int lineno = -1) -{ - // convert a & b to a's value_type to avoid warning upon comparison - typedef typename value_type::type T; + template + struct value_type + { + typedef typename thrust::detail::remove_const< + typename thrust::detail::remove_reference::type>::type type; + }; - if(!(T(a) == T(b))){ - unittest::UnitTestFailure f; - f << "[" << filename << ":" << lineno << "] "; - f << "values are not equal: " << a << " " << b; - f << " [type='" << type_name() << "']"; - throw f; - } -} + template + struct value_type> + { + typedef typename value_type::type type; + }; + + //// + // check scalar values + template + void assert_equal(const T1& a, + const T2& b, + const std::string& filename = "unknown", + int lineno = -1) + { + // convert a & b to a's value_type to avoid warning upon comparison + typedef typename value_type::type T; -// sometimes it's not possible to << a type -template -void assert_equal_quiet(const T1& a, const T2& b, - const std::string& filename = "unknown", int lineno = -1) -{ - if(!(a == b)){ - unittest::UnitTestFailure f; - f << "[" << filename << ":" << lineno << "] "; - f << "values are not equal."; - f << " [type='" << type_name() << "']"; - throw f; + if(!(T(a) == T(b))) + { + unittest::UnitTestFailure f; + f << "[" << filename << ":" << lineno << "] "; + f << "values are not equal: " << a << " " << b; + f << " [type='" << type_name() << "']"; + throw f; + } } -} -template -void assert_lequal(const T1& a, const T2& b, - const std::string& filename = "unknown", int lineno = -1) -{ - if(!(a <= b)){ - unittest::UnitTestFailure f; - f << "[" << filename << ":" << lineno << "] "; - f << a << " is greater than " << b; - f << " [type='" << type_name() << "']"; - throw f; + // sometimes it's not possible to << a type + template + void assert_equal_quiet(const T1& a, + const T2& b, + const std::string& filename = "unknown", + int lineno = -1) + { + if(!(a == b)) + { + unittest::UnitTestFailure f; + f << "[" << filename << ":" << lineno << "] "; + f << "values are not equal."; + f << " [type='" << type_name() << "']"; + throw f; + } } -} -template -void assert_gequal(const T1& a, const T2& b, - const std::string& filename = "unknown", int lineno = -1) -{ - if(!(a >= T1(b))){ - unittest::UnitTestFailure f; - f << "[" << filename << ":" << lineno << "] "; - f << a << " is less than " << b; - f << " [type='" << type_name() << "']"; - throw f; + template + void assert_lequal(const T1& a, + const T2& b, + const std::string& filename = "unknown", + int lineno = -1) + { + if(!(a <= b)) + { + unittest::UnitTestFailure f; + f << "[" << filename << ":" << lineno << "] "; + f << a << " is greater than " << b; + f << " [type='" << type_name() << "']"; + throw f; + } } -} -// define our own abs() because std::abs() isn't portable for all types for some reason -template - T abs(const T &x) -{ - return x > 0 ? x : -x; -} + template + void assert_gequal(const T1& a, + const T2& b, + const std::string& filename = "unknown", + int lineno = -1) + { + if(!(a >= T1(b))) + { + unittest::UnitTestFailure f; + f << "[" << filename << ":" << lineno << "] "; + f << a << " is less than " << b; + f << " [type='" << type_name() << "']"; + throw f; + } + } + // define our own abs() because std::abs() isn't portable for all types for some + // reason + template + T abs(const T& x) + { + return x > 0 ? x : -x; + } -inline -bool almost_equal(const double& a, const double& b, const double& a_tol, const double& r_tol) -{ - if(abs(a - b) > r_tol * (abs(a) + abs(b)) + a_tol) - return false; - else - return true; -} + inline bool + almost_equal(const double& a, const double& b, const double& a_tol, const double& r_tol) + { + if(abs(a - b) > r_tol * (abs(a) + abs(b)) + a_tol) + return false; + else + return true; + } -template -void assert_almost_equal(const T1& a, const T2& b, - const std::string& filename = "unknown", int lineno = -1, - double a_tol = DEFAULT_ABSOLUTE_TOL, double r_tol = DEFAULT_RELATIVE_TOL) + template + void assert_almost_equal(const T1& a, + const T2& b, + const std::string& filename = "unknown", + int lineno = -1, + double a_tol = DEFAULT_ABSOLUTE_TOL, + double r_tol = DEFAULT_RELATIVE_TOL) -{ - if(!almost_equal(a, b, a_tol, r_tol)){ - unittest::UnitTestFailure f; - f << "[" << filename << ":" << lineno << "] "; - f << "values are not approximately equal: " << (double) a << " " << (double) b; - f << " [type='" << type_name() << "']"; - throw f; + { + if(!almost_equal(a, b, a_tol, r_tol)) + { + unittest::UnitTestFailure f; + f << "[" << filename << ":" << lineno << "] "; + f << "values are not approximately equal: " << (double)a << " " << (double)b; + f << " [type='" << type_name() << "']"; + throw f; + } } -} + template + void assert_almost_equal(const thrust::complex& a, + const thrust::complex& b, + const std::string& filename = "unknown", + int lineno = -1, + double a_tol = DEFAULT_ABSOLUTE_TOL, + double r_tol = DEFAULT_RELATIVE_TOL) -template - void assert_almost_equal(const thrust::complex& a, const thrust::complex& b, - const std::string& filename = "unknown", int lineno = -1, - double a_tol = DEFAULT_ABSOLUTE_TOL, double r_tol = DEFAULT_RELATIVE_TOL) - -{ - if(!almost_equal(a.real(), b.real(), a_tol, r_tol)){ - unittest::UnitTestFailure f; - f << "[" << filename << ":" << lineno << "] "; - f << "values are not approximately equal: " << a << " " << b; - f << " [type='" << type_name() << "']"; - throw f; + { + if(!almost_equal(a.real(), b.real(), a_tol, r_tol)) + { + unittest::UnitTestFailure f; + f << "[" << filename << ":" << lineno << "] "; + f << "values are not approximately equal: " << a << " " << b; + f << " [type='" << type_name() << "']"; + throw f; + } } -} + template + void assert_almost_equal(const thrust::complex& a, + const std::complex& b, + const std::string& filename = "unknown", + int lineno = -1, + double a_tol = DEFAULT_ABSOLUTE_TOL, + double r_tol = DEFAULT_RELATIVE_TOL) -template - void assert_almost_equal(const thrust::complex& a, const std::complex& b, - const std::string& filename = "unknown", int lineno = -1, - double a_tol = DEFAULT_ABSOLUTE_TOL, double r_tol = DEFAULT_RELATIVE_TOL) - -{ - if(!almost_equal(a.real(), b.real(), a_tol, r_tol)){ - unittest::UnitTestFailure f; - f << "[" << filename << ":" << lineno << "] "; - f << "values are not approximately equal: " << a << " " << b; - f << " [type='" << type_name() << "']"; - throw f; + { + if(!almost_equal(a.real(), b.real(), a_tol, r_tol)) + { + unittest::UnitTestFailure f; + f << "[" << filename << ":" << lineno << "] "; + f << "values are not approximately equal: " << a << " " << b; + f << " [type='" << type_name() << "']"; + throw f; + } } -} -template -class almost_equal_to -{ + template + class almost_equal_to + { public: double a_tol, r_tol; - almost_equal_to(double _a_tol = DEFAULT_ABSOLUTE_TOL, double _r_tol = DEFAULT_RELATIVE_TOL) : a_tol(_a_tol), r_tol(_r_tol) {} - bool operator()(const T& a, const T& b) const { - return almost_equal((double) a, (double) b, a_tol, r_tol); + almost_equal_to(double _a_tol = DEFAULT_ABSOLUTE_TOL, double _r_tol = DEFAULT_RELATIVE_TOL) + : a_tol(_a_tol) + , r_tol(_r_tol) + { } -}; - + bool operator()(const T& a, const T& b) const + { + return almost_equal((double)a, (double)b, a_tol, r_tol); + } + }; -template -class almost_equal_to > -{ + template + class almost_equal_to> + { public: double a_tol, r_tol; - almost_equal_to(double _a_tol = DEFAULT_ABSOLUTE_TOL, double _r_tol = DEFAULT_RELATIVE_TOL) : a_tol(_a_tol), r_tol(_r_tol) {} - bool operator()(const thrust::complex& a, const thrust::complex& b) const { - return almost_equal((double) a.real(), (double) b.real(), a_tol, r_tol) && - almost_equal((double) a.imag(), (double) b.imag(), a_tol, r_tol); + almost_equal_to(double _a_tol = DEFAULT_ABSOLUTE_TOL, double _r_tol = DEFAULT_RELATIVE_TOL) + : a_tol(_a_tol) + , r_tol(_r_tol) + { + } + bool operator()(const thrust::complex& a, const thrust::complex& b) const + { + return almost_equal((double)a.real(), (double)b.real(), a_tol, r_tol) + && almost_equal((double)a.imag(), (double)b.imag(), a_tol, r_tol); } -}; + }; + + //// + // check sequences + + template + void assert_equal(ForwardIterator1 first1, + ForwardIterator1 last1, + ForwardIterator2 first2, + ForwardIterator2 last2, + BinaryPredicate op, + const std::string& filename = "unknown", + int lineno = -1) + { + typedef typename thrust::iterator_difference::type difference_type; + typedef typename thrust::iterator_value::type InputType; -//// -// check sequences + bool failure = false; -template -void assert_equal(ForwardIterator1 first1, ForwardIterator1 last1, ForwardIterator2 first2, ForwardIterator2 last2, BinaryPredicate op, - const std::string& filename = "unknown", int lineno = -1) -{ - typedef typename thrust::iterator_difference::type difference_type; - typedef typename thrust::iterator_value::type InputType; - - bool failure = false; + difference_type length1 = thrust::distance(first1, last1); + difference_type length2 = thrust::distance(first2, last2); - difference_type length1 = thrust::distance(first1, last1); - difference_type length2 = thrust::distance(first2, last2); - - difference_type min_length = thrust::min(length1, length2); + difference_type min_length = thrust::min(length1, length2); - unittest::UnitTestFailure f; - f << "[" << filename << ":" << lineno << "] "; + unittest::UnitTestFailure f; + f << "[" << filename << ":" << lineno << "] "; - // check lengths - if (length1 != length2) - { - failure = true; - f << "Sequences have different sizes (" << length1 << " != " << length2 << ")\n"; - } + // check lengths + if(length1 != length2) + { + failure = true; + f << "Sequences have different sizes (" << length1 << " != " << length2 << ")\n"; + } - // check values - - size_t mismatches = 0; + // check values - for (difference_type i = 0; i < min_length; i++) - { - if(!op(*first1, *first2)) - { - if (mismatches == 0) + size_t mismatches = 0; + + for(difference_type i = 0; i < min_length; i++) { - failure = true; - f << "Sequences are not equal [type='" << type_name() << "']\n"; - f << "--------------------------------\n"; + if(!op(*first1, *first2)) + { + if(mismatches == 0) + { + failure = true; + f << "Sequences are not equal [type='" << type_name() << "']\n"; + f << "--------------------------------\n"; + } + + mismatches++; + + if(mismatches <= MAX_OUTPUT_LINES) + { + if(sizeof(InputType) == 1) + f << " [" << i << "] " << *first1 + InputType() << " " + << *first2 + InputType() << "\n"; // unprintable chars are a problem + else + f << " [" << i << "] " << *first1 << " " << *first2 << "\n"; + } + } + + first1++; + first2++; } - mismatches++; - - if(mismatches <= MAX_OUTPUT_LINES) + if(mismatches > 0) { - if (sizeof(InputType) == 1) - f << " [" << i << "] " << *first1 + InputType() << " " << *first2 + InputType() << "\n"; // unprintable chars are a problem - else - f << " [" << i << "] " << *first1 << " " << *first2 << "\n"; + if(mismatches > MAX_OUTPUT_LINES) + f << " (output limit reached)\n"; + f << "--------------------------------\n"; + f << "Sequences differ at " << mismatches << " of " << min_length << " positions" + << "\n"; + } + else if(length1 != length2) + { + f << "Sequences agree through " << min_length << " positions [type='" + << type_name() << "']\n"; } - } - first1++; - first2++; + if(failure) + throw f; } - if (mismatches > 0) + template + void assert_equal(ForwardIterator1 first1, + ForwardIterator1 last1, + ForwardIterator2 first2, + ForwardIterator2 last2, + const std::string& filename = "unknown", + int lineno = -1) { - if(mismatches > MAX_OUTPUT_LINES) - f << " (output limit reached)\n"; - f << "--------------------------------\n"; - f << "Sequences differ at " << mismatches << " of " << min_length << " positions" << "\n"; + typedef typename thrust::iterator_traits::value_type InputType; + assert_equal(first1, last1, first2, last2, thrust::equal_to(), filename, lineno); } - else if (length1 != length2) + + template + void assert_almost_equal(ForwardIterator1 first1, + ForwardIterator1 last1, + ForwardIterator2 first2, + ForwardIterator2 last2, + const std::string& filename = "unknown", + int lineno = -1, + const double a_tol = DEFAULT_ABSOLUTE_TOL, + const double r_tol = DEFAULT_RELATIVE_TOL) { - f << "Sequences agree through " << min_length << " positions [type='" << type_name() << "']\n"; + typedef typename thrust::iterator_traits::value_type InputType; + assert_equal(first1, + last1, + first2, + last2, + almost_equal_to(a_tol, r_tol), + filename, + lineno); } - if (failure) - throw f; -} - -template -void assert_equal(ForwardIterator1 first1, ForwardIterator1 last1, ForwardIterator2 first2, ForwardIterator2 last2, - const std::string& filename = "unknown", int lineno = -1) -{ - typedef typename thrust::iterator_traits::value_type InputType; - assert_equal(first1, last1, first2, last2, thrust::equal_to(), filename, lineno); -} - + template + void assert_equal(const thrust::host_vector& A, + const thrust::host_vector& B, + const std::string& filename = "unknown", + int lineno = -1) + { + assert_equal(A.begin(), A.end(), B.begin(), B.end(), filename, lineno); + } -template -void assert_almost_equal(ForwardIterator1 first1, ForwardIterator1 last1, ForwardIterator2 first2, ForwardIterator2 last2, - const std::string& filename = "unknown", int lineno = -1, - const double a_tol = DEFAULT_ABSOLUTE_TOL, const double r_tol = DEFAULT_RELATIVE_TOL) -{ - typedef typename thrust::iterator_traits::value_type InputType; - assert_equal(first1, last1, first2, last2, almost_equal_to(a_tol, r_tol), filename, lineno); -} + template + void assert_almost_equal(const thrust::host_vector& A, + const thrust::host_vector& B, + const std::string& filename = "unknown", + int lineno = -1, + const double a_tol = DEFAULT_ABSOLUTE_TOL, + const double r_tol = DEFAULT_RELATIVE_TOL) + { + assert_almost_equal(A.begin(), A.end(), B.begin(), B.end(), filename, lineno, a_tol, r_tol); + } + template + void assert_equal(const thrust::host_vector& A, + const thrust::device_vector& B, + const std::string& filename = "unknown", + int lineno = -1) + { + thrust::host_vector B_host = B; + assert_equal(A, B_host, filename, lineno); + } -template -void assert_equal(const thrust::host_vector& A, const thrust::host_vector& B, - const std::string& filename = "unknown", int lineno = -1) -{ - assert_equal(A.begin(), A.end(), B.begin(), B.end(), filename, lineno); -} + template + void assert_equal(const thrust::device_vector& A, + const thrust::host_vector& B, + const std::string& filename = "unknown", + int lineno = -1) + { + thrust::host_vector A_host = A; + assert_equal(A_host, B, filename, lineno); + } -template -void assert_almost_equal(const thrust::host_vector& A, const thrust::host_vector& B, - const std::string& filename = "unknown", int lineno = -1, - const double a_tol = DEFAULT_ABSOLUTE_TOL, const double r_tol = DEFAULT_RELATIVE_TOL) -{ - assert_almost_equal(A.begin(), A.end(), B.begin(), B.end(), filename, lineno, a_tol, r_tol); -} + template + void assert_equal(const thrust::device_vector& A, + const thrust::device_vector& B, + const std::string& filename = "unknown", + int lineno = -1) + { + thrust::host_vector A_host = A; + thrust::host_vector B_host = B; + assert_equal(A_host, B_host, filename, lineno); + } -template -void assert_equal(const thrust::host_vector& A, const thrust::device_vector& B, - const std::string& filename = "unknown", int lineno = -1) -{ - thrust::host_vector B_host = B; - assert_equal(A, B_host, filename, lineno); -} + template + void assert_almost_equal(const thrust::host_vector& A, + const thrust::device_vector& B, + const std::string& filename = "unknown", + int lineno = -1, + const double a_tol = DEFAULT_ABSOLUTE_TOL, + const double r_tol = DEFAULT_RELATIVE_TOL) + { + thrust::host_vector B_host = B; + assert_almost_equal(A, B_host, filename, lineno, a_tol, r_tol); + } -template -void assert_equal(const thrust::device_vector& A, const thrust::host_vector& B, - const std::string& filename = "unknown", int lineno = -1) -{ - thrust::host_vector A_host = A; - assert_equal(A_host, B, filename, lineno); -} + template + void assert_almost_equal(const thrust::device_vector& A, + const thrust::host_vector& B, + const std::string& filename = "unknown", + int lineno = -1, + const double a_tol = DEFAULT_ABSOLUTE_TOL, + const double r_tol = DEFAULT_RELATIVE_TOL) + { + thrust::host_vector A_host = A; + assert_almost_equal(A_host, B, filename, lineno, a_tol, r_tol); + } -template -void assert_equal(const thrust::device_vector& A, const thrust::device_vector& B, - const std::string& filename = "unknown", int lineno = -1) -{ - thrust::host_vector A_host = A; - thrust::host_vector B_host = B; - assert_equal(A_host, B_host, filename, lineno); -} - -template -void assert_almost_equal(const thrust::host_vector& A, const thrust::device_vector& B, - const std::string& filename = "unknown", int lineno = -1, - const double a_tol = DEFAULT_ABSOLUTE_TOL, const double r_tol = DEFAULT_RELATIVE_TOL) -{ - thrust::host_vector B_host = B; - assert_almost_equal(A, B_host, filename, lineno, a_tol, r_tol); -} - -template -void assert_almost_equal(const thrust::device_vector& A, const thrust::host_vector& B, - const std::string& filename = "unknown", int lineno = -1, - const double a_tol = DEFAULT_ABSOLUTE_TOL, const double r_tol = DEFAULT_RELATIVE_TOL) -{ - thrust::host_vector A_host = A; - assert_almost_equal(A_host, B, filename, lineno, a_tol, r_tol); -} - -template -void assert_almost_equal(const thrust::device_vector& A, const thrust::device_vector& B, - const std::string& filename = "unknown", int lineno = -1, - const double a_tol = DEFAULT_ABSOLUTE_TOL, const double r_tol = DEFAULT_RELATIVE_TOL) -{ - thrust::host_vector A_host = A; - thrust::host_vector B_host = B; - assert_almost_equal(A_host, B_host, filename, lineno, a_tol, r_tol); -} + template + void assert_almost_equal(const thrust::device_vector& A, + const thrust::device_vector& B, + const std::string& filename = "unknown", + int lineno = -1, + const double a_tol = DEFAULT_ABSOLUTE_TOL, + const double r_tol = DEFAULT_RELATIVE_TOL) + { + thrust::host_vector A_host = A; + thrust::host_vector B_host = B; + assert_almost_equal(A_host, B_host, filename, lineno, a_tol, r_tol); + } -}; //end namespace unittest +}; // end namespace unittest diff --git a/testing/unittest/exceptions.h b/testing/unittest/exceptions.h index 3f3633f..5674af3 100644 --- a/testing/unittest/exceptions.h +++ b/testing/unittest/exceptions.h @@ -1,56 +1,66 @@ #pragma once -#include #include #include +#include namespace unittest { -class UnitTestException -{ + class UnitTestException + { public: - std::string message; + std::string message; - UnitTestException() {} - UnitTestException(const std::string& msg) : message(msg) {} + UnitTestException() {} + UnitTestException(const std::string& msg) + : message(msg) + { + } - friend std::ostream& operator<<(std::ostream& os, const UnitTestException& e) - { - return os << e.message; - } - - template - UnitTestException& operator<<(const T& t) - { - std::ostringstream oss; - oss << t; - message += oss.str(); - return *this; - } -}; + friend std::ostream& operator<<(std::ostream& os, const UnitTestException& e) + { + return os << e.message; + } + template + UnitTestException& operator<<(const T& t) + { + std::ostringstream oss; + oss << t; + message += oss.str(); + return *this; + } + }; -class UnitTestError : public UnitTestException -{ + class UnitTestError : public UnitTestException + { public: - UnitTestError() {} - UnitTestError(const std::string& msg) : UnitTestException(msg) {} -}; + UnitTestError() {} + UnitTestError(const std::string& msg) + : UnitTestException(msg) + { + } + }; -class UnitTestFailure : public UnitTestException -{ + class UnitTestFailure : public UnitTestException + { public: - UnitTestFailure() {} - UnitTestFailure(const std::string& msg) : UnitTestException(msg) {} -}; + UnitTestFailure() {} + UnitTestFailure(const std::string& msg) + : UnitTestException(msg) + { + } + }; -class UnitTestKnownFailure : public UnitTestException -{ + class UnitTestKnownFailure : public UnitTestException + { public: - UnitTestKnownFailure() {} - UnitTestKnownFailure(const std::string& msg) : UnitTestException(msg) {} -}; - + UnitTestKnownFailure() {} + UnitTestKnownFailure(const std::string& msg) + : UnitTestException(msg) + { + } + }; -}; //end namespace unittest +}; // end namespace unittest diff --git a/testing/unittest/meta.h b/testing/unittest/meta.h index 9a2b6d8..76ba1bf 100644 --- a/testing/unittest/meta.h +++ b/testing/unittest/meta.h @@ -9,252 +9,417 @@ namespace unittest { -// mark the absence of a type -struct null_type {}; + // mark the absence of a type + struct null_type + { + }; -// this type encapsulates a list of -// up to 10 types -template - struct type_list -{ - typedef T0 type_0; - typedef T1 type_1; - typedef T2 type_2; - typedef T3 type_3; - typedef T4 type_4; - typedef T5 type_5; - typedef T6 type_6; - typedef T7 type_7; - typedef T8 type_8; - typedef T9 type_9; - typedef T10 type_10; - typedef T11 type_11; - typedef T12 type_12; - typedef T13 type_13; - typedef T14 type_14; - typedef T15 type_15; - typedef T16 type_16; - typedef T17 type_17; - typedef T18 type_18; - typedef T19 type_19; -}; + // this type encapsulates a list of + // up to 10 types + template + struct type_list + { + typedef T0 type_0; + typedef T1 type_1; + typedef T2 type_2; + typedef T3 type_3; + typedef T4 type_4; + typedef T5 type_5; + typedef T6 type_6; + typedef T7 type_7; + typedef T8 type_8; + typedef T9 type_9; + typedef T10 type_10; + typedef T11 type_11; + typedef T12 type_12; + typedef T13 type_13; + typedef T14 type_14; + typedef T15 type_15; + typedef T16 type_16; + typedef T17 type_17; + typedef T18 type_18; + typedef T19 type_19; + }; -// this type provides a way of indexing -// into a type_list -template - struct get_type -{ - typedef null_type type; -}; + // this type provides a way of indexing + // into a type_list + template + struct get_type + { + typedef null_type type; + }; -template struct get_type { typedef typename List::type_0 type; }; -template struct get_type { typedef typename List::type_1 type; }; -template struct get_type { typedef typename List::type_2 type; }; -template struct get_type { typedef typename List::type_3 type; }; -template struct get_type { typedef typename List::type_4 type; }; -template struct get_type { typedef typename List::type_5 type; }; -template struct get_type { typedef typename List::type_6 type; }; -template struct get_type { typedef typename List::type_7 type; }; -template struct get_type { typedef typename List::type_8 type; }; -template struct get_type { typedef typename List::type_9 type; }; -template struct get_type { typedef typename List::type_10 type; }; -template struct get_type { typedef typename List::type_11 type; }; -template struct get_type { typedef typename List::type_12 type; }; -template struct get_type { typedef typename List::type_13 type; }; -template struct get_type { typedef typename List::type_14 type; }; -template struct get_type { typedef typename List::type_15 type; }; -template struct get_type { typedef typename List::type_16 type; }; -template struct get_type { typedef typename List::type_17 type; }; -template struct get_type { typedef typename List::type_18 type; }; -template struct get_type { typedef typename List::type_19 type; }; + template + struct get_type + { + typedef typename List::type_0 type; + }; + template + struct get_type + { + typedef typename List::type_1 type; + }; + template + struct get_type + { + typedef typename List::type_2 type; + }; + template + struct get_type + { + typedef typename List::type_3 type; + }; + template + struct get_type + { + typedef typename List::type_4 type; + }; + template + struct get_type + { + typedef typename List::type_5 type; + }; + template + struct get_type + { + typedef typename List::type_6 type; + }; + template + struct get_type + { + typedef typename List::type_7 type; + }; + template + struct get_type + { + typedef typename List::type_8 type; + }; + template + struct get_type + { + typedef typename List::type_9 type; + }; + template + struct get_type + { + typedef typename List::type_10 type; + }; + template + struct get_type + { + typedef typename List::type_11 type; + }; + template + struct get_type + { + typedef typename List::type_12 type; + }; + template + struct get_type + { + typedef typename List::type_13 type; + }; + template + struct get_type + { + typedef typename List::type_14 type; + }; + template + struct get_type + { + typedef typename List::type_15 type; + }; + template + struct get_type + { + typedef typename List::type_16 type; + }; + template + struct get_type + { + typedef typename List::type_17 type; + }; + template + struct get_type + { + typedef typename List::type_18 type; + }; + template + struct get_type + { + typedef typename List::type_19 type; + }; -// this type and its specialization provides a way to -// iterate over a type_list, and -// applying a unary function to each type -template class Function, - typename T, - unsigned int i = 0> - struct for_each_type -{ - template - void operator()(U n) - { - // run the function on type T - Function f; - f(n); + // this type and its specialization provides a way to + // iterate over a type_list, and + // applying a unary function to each type + template class Function, typename T, unsigned int i = 0> + struct for_each_type + { + template + void operator()(U n) + { + // run the function on type T + Function f; + f(n); - // get the next type - typedef typename get_type::type next_type; + // get the next type + typedef typename get_type::type next_type; - // recurse to i + 1 - for_each_type loop; - loop(n); - } + // recurse to i + 1 + for_each_type loop; + loop(n); + } - void operator()(void) - { - // run the function on type T - Function f; - f(); + void operator()(void) + { + // run the function on type T + Function f; + f(); - // get the next type - typedef typename get_type::type next_type; + // get the next type + typedef typename get_type::type next_type; - // recurse to i + 1 - for_each_type loop; - loop(); - } -}; + // recurse to i + 1 + for_each_type loop; + loop(); + } + }; -// terminal case: do nothing when encountering null_type -template class Function, - unsigned int i> - struct for_each_type -{ - template - void operator()(U n) - { - // no-op - } + // terminal case: do nothing when encountering null_type + template class Function, unsigned int i> + struct for_each_type + { + template + void operator()(U n) + { + // no-op + } - void operator()(void) - { - // no-op - } -}; + void operator()(void) + { + // no-op + } + }; -// this type and its specialization instantiates -// a template by applying T to Template. -// if T == null_type, then its result is also null_type -template