├── CPPLINT.cfg ├── test ├── Makefile └── gtestx_test.cc ├── examples ├── Makefile ├── simple_test.cc ├── misc_features.cc ├── fixture_test.cc ├── template_fixture_test.cc └── param_fixture_test.cc ├── BUILD ├── README.md └── src └── gtestx ├── gtestx.cc └── gtestx.h /CPPLINT.cfg: -------------------------------------------------------------------------------- 1 | root=src 2 | linelength=100 3 | -------------------------------------------------------------------------------- /test/Makefile: -------------------------------------------------------------------------------- 1 | all: gtestx_test 2 | 3 | # change to your gtest source directory 4 | GTEST_SRC_DIR = /usr/src/gtest 5 | 6 | gtestx_test: gtestx_test.cc ../src/gtestx/gtestx.cc $(GTEST_SRC_DIR)/src/gtest-all.cc 7 | g++ -Wall -std=c++0x -I../src -I$(GTEST_SRC_DIR)/include -I$(GTEST_SRC_DIR) -o $@ $^ -pthread -lgflags 8 | 9 | clean: 10 | rm -f gtestx_test 11 | 12 | .PHONY: all clean 13 | -------------------------------------------------------------------------------- /examples/Makefile: -------------------------------------------------------------------------------- 1 | all: gtestx_examples 2 | 3 | # change to your gtest source directory 4 | GTEST_SRC_DIR = /usr/src/gtest 5 | 6 | gtestx_examples: $(wildcard *.cc) ../src/gtestx/gtestx.cc $(GTEST_SRC_DIR)/src/gtest-all.cc 7 | g++ -Wall -std=c++0x -I../src -I$(GTEST_SRC_DIR)/include -I$(GTEST_SRC_DIR) -o $@ $^ -pthread -lgflags 8 | 9 | clean: 10 | rm -f gtestx_examples 11 | 12 | .PHONY: all clean 13 | -------------------------------------------------------------------------------- /BUILD: -------------------------------------------------------------------------------- 1 | package(default_visibility = ["//visibility:public"]) 2 | 3 | cc_library( 4 | name = "gtestx", 5 | includes = ["src"], 6 | copts = [ 7 | "-g", 8 | "-Wall", 9 | ], 10 | linkstatic = 1, 11 | srcs = glob([ 12 | "src/gtestx/gtestx.cc", 13 | "src/gtestx/gtestx.h", 14 | ]), 15 | deps = [ 16 | "//third_party/gtest-170", 17 | "//third_party/gflags-20", 18 | ], 19 | ) 20 | 21 | cc_test( 22 | name = "test", 23 | copts = [ 24 | "-g", 25 | "-Wall", 26 | ], 27 | srcs = glob(["test/*_test.cc"]), 28 | deps = [ 29 | ":gtestx", 30 | ], 31 | ) 32 | 33 | cc_binary( 34 | name = "examples", 35 | copts = [ 36 | "-g", 37 | "-Wall", 38 | ], 39 | srcs = glob(["examples/*.cc"]), 40 | deps = [ 41 | ":gtestx", 42 | ], 43 | ) 44 | -------------------------------------------------------------------------------- /examples/simple_test.cc: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2016-2017, Bin Wei 2 | * All rights reserved. 3 | * 4 | * Redistribution and use in source and binary forms, with or without 5 | * modification, are permitted provided that the following conditions are 6 | * met: 7 | * 8 | * * Redistributions of source code must retain the above copyright 9 | * notice, this list of conditions and the following disclaimer. 10 | * * Redistributions in binary form must reproduce the above 11 | * copyright notice, this list of conditions and the following disclaimer 12 | * in the documentation and/or other materials provided with the 13 | * distribution. 14 | * * The names of its contributors may not be used to endorse or 15 | * promote products derived from this software without specific prior 16 | * written permission. 17 | * 18 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 21 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 22 | * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 23 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 24 | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | */ 30 | #include 31 | #include 32 | #include "gtestx/gtestx.h" 33 | 34 | TEST(SimpleTest, SysCall) { 35 | ASSERT_NE(0, getppid()); 36 | } 37 | 38 | // Just like TEST macro, use PERF_TEST for performance testing 39 | PERF_TEST(SimpleTest, SysCallPerf) { 40 | getppid(); 41 | } 42 | -------------------------------------------------------------------------------- /examples/misc_features.cc: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2016-2017, Bin Wei 2 | * All rights reserved. 3 | * 4 | * Redistribution and use in source and binary forms, with or without 5 | * modification, are permitted provided that the following conditions are 6 | * met: 7 | * 8 | * * Redistributions of source code must retain the above copyright 9 | * notice, this list of conditions and the following disclaimer. 10 | * * Redistributions in binary form must reproduce the above 11 | * copyright notice, this list of conditions and the following disclaimer 12 | * in the documentation and/or other materials provided with the 13 | * distribution. 14 | * * The names of its contributors may not be used to endorse or 15 | * promote products derived from this software without specific prior 16 | * written permission. 17 | * 18 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 21 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 22 | * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 23 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 24 | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | */ 30 | #include 31 | #include 32 | #include "gtestx/gtestx.h" 33 | 34 | // use XXX_OPT to override default HZ, TIME parameters 35 | // e.g. test below will be called 10000 times/s for 5000 ms 36 | PERF_TEST_OPT(MiscFeaturesTest, SysCallPerf, 10000, 5000) { 37 | getppid(); 38 | } 39 | 40 | // If you want to use ASSERT_XXX in PERF_XXX, add < 2 | * All rights reserved. 3 | * 4 | * Redistribution and use in source and binary forms, with or without 5 | * modification, are permitted provided that the following conditions are 6 | * met: 7 | * 8 | * * Redistributions of source code must retain the above copyright 9 | * notice, this list of conditions and the following disclaimer. 10 | * * Redistributions in binary form must reproduce the above 11 | * copyright notice, this list of conditions and the following disclaimer 12 | * in the documentation and/or other materials provided with the 13 | * distribution. 14 | * * The names of its contributors may not be used to endorse or 15 | * promote products derived from this software without specific prior 16 | * written permission. 17 | * 18 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 21 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 22 | * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 23 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 24 | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | */ 30 | #include 31 | #include "gtestx/gtestx.h" 32 | 33 | class StdMapTest : public testing::Test { 34 | protected: 35 | virtual ~StdMapTest() {} 36 | void SetUp() override { 37 | for (int i = 0; i < 1000; i++) { 38 | map_.emplace(i, 1); 39 | } 40 | } 41 | void TearDown() override {} 42 | 43 | std::map map_; 44 | }; 45 | 46 | TEST_F(StdMapTest, Find) { 47 | ASSERT_NE(map_.find(999), map_.end()); 48 | } 49 | 50 | // use PERF_TEST_F for performance testing 51 | PERF_TEST_F(StdMapTest, FindPerf) { 52 | map_.find(999); 53 | } 54 | -------------------------------------------------------------------------------- /examples/template_fixture_test.cc: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2016-2017, Bin Wei 2 | * All rights reserved. 3 | * 4 | * Redistribution and use in source and binary forms, with or without 5 | * modification, are permitted provided that the following conditions are 6 | * met: 7 | * 8 | * * Redistributions of source code must retain the above copyright 9 | * notice, this list of conditions and the following disclaimer. 10 | * * Redistributions in binary form must reproduce the above 11 | * copyright notice, this list of conditions and the following disclaimer 12 | * in the documentation and/or other materials provided with the 13 | * distribution. 14 | * * The names of its contributors may not be used to endorse or 15 | * promote products derived from this software without specific prior 16 | * written permission. 17 | * 18 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 21 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 22 | * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 23 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 24 | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | */ 30 | #include 31 | #include "gtestx/gtestx.h" 32 | 33 | template 34 | class QueueTest : public testing::Test { 35 | protected: 36 | virtual ~QueueTest() {} 37 | void SetUp() override {} 38 | void TearDown() override {} 39 | 40 | std::queue queue_; 41 | }; 42 | 43 | 44 | typedef testing::Types> TestTypes; 45 | TYPED_TEST_CASE(QueueTest, TestTypes); 46 | 47 | TYPED_TEST(QueueTest, PushPop) { 48 | this->queue_.push(TypeParam()); 49 | this->queue_.pop(); 50 | } 51 | 52 | // use TYPED_PERF_TEST for performance testing 53 | TYPED_PERF_TEST(QueueTest, PushPopPerf) { 54 | this->queue_.push(TypeParam()); 55 | this->queue_.pop(); 56 | } 57 | -------------------------------------------------------------------------------- /examples/param_fixture_test.cc: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2016-2017, Bin Wei 2 | * All rights reserved. 3 | * 4 | * Redistribution and use in source and binary forms, with or without 5 | * modification, are permitted provided that the following conditions are 6 | * met: 7 | * 8 | * * Redistributions of source code must retain the above copyright 9 | * notice, this list of conditions and the following disclaimer. 10 | * * Redistributions in binary form must reproduce the above 11 | * copyright notice, this list of conditions and the following disclaimer 12 | * in the documentation and/or other materials provided with the 13 | * distribution. 14 | * * The names of its contributors may not be used to endorse or 15 | * promote products derived from this software without specific prior 16 | * written permission. 17 | * 18 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 21 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 22 | * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 23 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 24 | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | */ 30 | #include 31 | #include "gtestx/gtestx.h" 32 | 33 | class HashMapTest : public testing::TestWithParam { 34 | protected: 35 | virtual ~HashMapTest() {} 36 | void SetUp() override { 37 | map_.max_load_factor(GetParam()); 38 | for (int i = 0; i < 1000; i++) { 39 | map_.emplace(i, 1); 40 | } 41 | } 42 | void TearDown() override {} 43 | 44 | std::unordered_map map_; 45 | int search_key_ = 0; 46 | }; 47 | 48 | INSTANTIATE_TEST_CASE_P(LoadFactor, HashMapTest, 49 | testing::Values(3.0, 1.0, 0.3)); 50 | 51 | TEST_P(HashMapTest, Find) { 52 | ASSERT_NE(map_.find(999), map_.end()); 53 | } 54 | 55 | // use PERF_TEST_P for performance testing 56 | PERF_TEST_P(HashMapTest, FindPerf) { 57 | map_.find(++search_key_); 58 | } 59 | -------------------------------------------------------------------------------- /test/gtestx_test.cc: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2012-2015, Bin Wei 2 | * All rights reserved. 3 | * 4 | * Redistribution and use in source and binary forms, with or without 5 | * modification, are permitted provided that the following conditions are 6 | * met: 7 | * 8 | * * Redistributions of source code must retain the above copyright 9 | * notice, this list of conditions and the following disclaimer. 10 | * * Redistributions in binary form must reproduce the above 11 | * copyright notice, this list of conditions and the following disclaimer 12 | * in the documentation and/or other materials provided with the 13 | * distribution. 14 | * * The names of its contributors may not be used to endorse or 15 | * promote products derived from this software without specific prior 16 | * written permission. 17 | * 18 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 21 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 22 | * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 23 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 24 | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | */ 30 | #include "gtestx/gtestx.h" 31 | 32 | TEST(Nop, test) { 33 | } 34 | 35 | PERF_TEST(Nop, perf) { 36 | } 37 | 38 | /////////////////////////////////////////////// 39 | 40 | class Empty : public testing::Test { 41 | }; 42 | 43 | TEST_F(Empty, test) { 44 | } 45 | 46 | PERF_TEST_F(Empty, perf) { 47 | } 48 | 49 | /////////////////////////////////////////////// 50 | 51 | class EmptyP : public testing::TestWithParam { 52 | }; 53 | 54 | TEST_P(EmptyP, test) { 55 | } 56 | 57 | PERF_TEST_P(EmptyP, perf) { 58 | } 59 | 60 | INSTANTIATE_TEST_CASE_P(Inst, EmptyP, testing::Values(1, 2, 3)); 61 | 62 | /////////////////////////////////////////////// 63 | 64 | template 65 | class EmptyTmplt : public testing::Test { 66 | }; 67 | 68 | typedef testing::Types TestTypes; 69 | TYPED_TEST_CASE(EmptyTmplt, TestTypes); 70 | 71 | TYPED_TEST(EmptyTmplt, Test) { 72 | } 73 | 74 | TYPED_PERF_TEST(EmptyTmplt, Perf) { 75 | } 76 | 77 | /////////////////////////////////////////////// 78 | 79 | template 80 | class EmptyTmpltP : public testing::Test { 81 | }; 82 | 83 | TYPED_TEST_CASE_P(EmptyTmpltP); 84 | 85 | TYPED_TEST_P(EmptyTmpltP, Test) { 86 | } 87 | 88 | TYPED_PERF_TEST_P(EmptyTmpltP, Perf) { 89 | } 90 | 91 | REGISTER_TYPED_TEST_CASE_P(EmptyTmpltP, Test, Perf); 92 | 93 | typedef testing::Types TestTypesP; 94 | INSTANTIATE_TYPED_TEST_CASE_P(TestEmptyTmpltP, EmptyTmpltP, TestTypesP); 95 | 96 | /////////////////////////////////////////////// 97 | 98 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## GTESTX - A C++ benchmark extension for gtest 2 | 3 | Benchmark or performance-testing is often as important as unit test in many environment such as server side development. GTESTX is just a convenient and simple C++ benchmark tool. It is based on gtest framework, so if you are familiar with gtest you can write benchmark code easily only by knowing some extended macros. 4 | 5 | ### Examples 6 | 7 | PERF\_TEST (similar with TEST macro) is a simplest gtestx macro. By default the function body will be called in a dead loop for a period of time and then the performance counter recorded is reported. 8 | 9 | This is an example: 10 | 11 | ```C++ 12 | #include 13 | #include 14 | #include "gtestx/gtestx.h" 15 | 16 | TEST(SimpleTest, SysCall) 17 | { 18 | ASSERT_NE(0, getppid()); 19 | } 20 | 21 | // Just like TEST macro, use PERF_TEST for performance testing 22 | PERF_TEST(SimpleTest, SysCallPerf) 23 | { 24 | getppid(); 25 | } 26 | ``` 27 | 28 | We can run it as normal gtest tests: 29 | 30 | ``` 31 | $ ./gtestx_examples --gtest_filter='SimpleTest*' 32 | [==========] Running 2 tests from 1 test case. 33 | [----------] Global test environment set-up. 34 | [----------] 2 tests from SimpleTest 35 | [ RUN ] SimpleTest.SysCall 36 | [ OK ] SimpleTest.SysCall (0 ms) 37 | [ RUN ] SimpleTest.SysCallPerf 38 | count: 25,369,636 39 | time: 1.508939 s 40 | HZ: 16,812,897.009090 41 | 1/HZ: 0.000000059 s 42 | [ OK ] SimpleTest.SysCallPerf (1509 ms) 43 | [----------] 2 tests from SimpleTest (1509 ms total) 44 | 45 | [----------] Global test environment tear-down 46 | [==========] 2 tests from 1 test case ran. (1510 ms total) 47 | [ PASSED ] 2 tests. 48 | ``` 49 | 50 | Another example: 51 | 52 | ```C++ 53 | class StdMapTest : public testing::Test 54 | { 55 | protected: 56 | virtual ~StdMapTest() {} 57 | virtual void SetUp() override { 58 | for (int i = 0; i < 1000; i++) { 59 | map_.emplace(i, 1); 60 | } 61 | } 62 | virtual void TearDown() override {} 63 | 64 | std::map map_; 65 | }; 66 | 67 | PERF_TEST_F(StdMapTest, FindPerf) 68 | { 69 | map_.find(999); 70 | } 71 | ``` 72 | 73 | ### Macros 74 | 75 | Almost all gtest macro has a GTESTX version: 76 | 77 | - PERF\_TEST 78 | - PERF\_TEST\_F 79 | - PERF\_TEST\_P 80 | - TYPED\_PERF\_TEST 81 | - TYPED\_PERF\_TEST\_P 82 | 83 | And there are some more macros which can be used with additional options: 84 | 85 | - PERF\_TEST\_OPT 86 | - PERF\_TEST\_F\_OPT 87 | - PERF\_TEST\_P\_OPT 88 | - TYPED\_PERF\_TEST\_OPT 89 | - TYPED\_PERF\_TEST\_P\_OPT 90 | 91 | You can learn how to use them by read example code in _examples_ directory. 92 | 93 | ### Dependencies 94 | 95 | - gtest (>= 1.7 is well tested) 96 | - gflags (>= 2.0 is well tested) 97 | 98 | ### Compile 99 | 100 | Actually all gtestx code (without tests and examples) are only two files - gtestx.h and gtestx.cc, so you can import them into your projects easily. 101 | 102 | #### Compile using Bazel 103 | 104 | A [Bazel](http://bazel.io) BUILD file is also available, you can use it to build tests and examples or linked it to other bazel project. Note that this bazel BUILD depends on gtest and gflags modules which are modified-for-bazel version on my github. 105 | 106 | For example you can build examples as follows: 107 | 108 | ``` 109 | mkdir work 110 | cd work 111 | touch WORKSPACE 112 | git clone https://github.com/mikewei/gtestx.git 113 | git clone https://github.com/mikewei/third_party.git 114 | bazel build gtestx:examples 115 | ``` 116 | 117 | #### Compile using make 118 | 119 | You can also build tests and examples using Makefile: 120 | 121 | ``` 122 | git clone https://github.com/mikewei/gtestx.git 123 | cd examples 124 | # change some directory setting in Makefile 125 | make 126 | ``` 127 | 128 | ### Run 129 | 130 | Run GTESTX benchmark tests just as normal gtest tests. e.g. 131 | 132 | ./gtestx_examples --gtest_filters='SimpleTest.*' 133 | 134 | Or run within bazel: 135 | 136 | bazel run gtestx:examples -- --gtest_filter='SimpleTest.*' 137 | 138 | Also GTESTX supply two more command line options: 139 | 140 | -hz CALLS_PER_SECOND 141 | -time RUNNING_MILLISECONDS 142 | 143 | For example if you want run SimpleTest with 10000 times/sec for 10 seconds, use commonds bellow: 144 | 145 | ./gtestx_examples --gtest_filters='SimpleTest.*' -hz=10000 -time=10000 146 | 147 | 148 | ### Tutorial (Chinese) 149 | 150 | 这里有一篇介绍[如何使用gtestx的文章](http://codinginet.com/articles/view/201606-use_gtestx_for_benchmark)。 151 | -------------------------------------------------------------------------------- /src/gtestx/gtestx.cc: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2012-2017, Bin Wei 2 | * All rights reserved. 3 | * 4 | * Redistribution and use in source and binary forms, with or without 5 | * modification, are permitted provided that the following conditions are 6 | * met: 7 | * 8 | * * Redistributions of source code must retain the above copyright 9 | * notice, this list of conditions and the following disclaimer. 10 | * * Redistributions in binary form must reproduce the above 11 | * copyright notice, this list of conditions and the following disclaimer 12 | * in the documentation and/or other materials provided with the 13 | * distribution. 14 | * * The name of of its contributors may not be used to endorse or 15 | * promote products derived from this software without specific prior 16 | * written permission. 17 | * 18 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 21 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 22 | * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 23 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 24 | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | */ 30 | #include 31 | #include 32 | #include 33 | #include 34 | #include 35 | #include 36 | #include 37 | #include // NOLINT 38 | #include "gtestx/gtestx.h" 39 | 40 | #define TV2US(ptv) ((ptv)->tv_sec * 1000000 + (ptv)->tv_usec) 41 | 42 | DEFINE_uint64(hz, 0, "loops per second"); 43 | DEFINE_uint64(time, 1500, "testing time long (ms)"); 44 | 45 | namespace { 46 | 47 | class TokenBucket { 48 | public: 49 | TokenBucket(uint32_t tokens_per_sec, uint32_t bucket_size, uint32_t init_tokens); 50 | void Gen(struct timeval *tv_now = NULL); 51 | bool Get(uint32_t need_tokens); 52 | 53 | private: 54 | uint32_t tokens_per_sec_; 55 | uint32_t bucket_size_; 56 | int64_t token_count_; 57 | uint64_t last_gen_time_; 58 | uint64_t last_calc_delta_; 59 | }; 60 | 61 | TokenBucket::TokenBucket(uint32_t tokens_per_sec, 62 | uint32_t bucket_size, 63 | uint32_t init_tokens) { 64 | struct timeval tv; 65 | tokens_per_sec_ = tokens_per_sec; 66 | bucket_size_ = bucket_size; 67 | token_count_ = init_tokens; 68 | gettimeofday(&tv, NULL); 69 | last_gen_time_ = TV2US(&tv); 70 | last_calc_delta_ = 0; 71 | } 72 | 73 | void TokenBucket::Gen(struct timeval *tv_now) { 74 | struct timeval tv; 75 | uint64_t us_now, us_past; 76 | uint64_t new_tokens, calc_delta; 77 | int64_t new_token_count; 78 | 79 | if (tv_now == NULL) { 80 | tv_now = &tv; 81 | gettimeofday(tv_now, NULL); 82 | } 83 | us_now = TV2US(tv_now); 84 | if (us_now < last_gen_time_) { 85 | last_gen_time_ = us_now; 86 | return; 87 | } 88 | 89 | us_past = us_now - last_gen_time_; 90 | new_tokens = (((uint64_t)tokens_per_sec_ * us_past + last_calc_delta_) / 1000000); 91 | calc_delta = (((uint64_t)tokens_per_sec_ * us_past + last_calc_delta_) % 1000000); 92 | 93 | last_gen_time_ = us_now; 94 | last_calc_delta_ = calc_delta; 95 | new_token_count = token_count_ + new_tokens; 96 | if (new_token_count < token_count_) { 97 | token_count_ = bucket_size_; 98 | return; 99 | } 100 | if (new_token_count > bucket_size_) { 101 | new_token_count = bucket_size_; 102 | } 103 | token_count_ = new_token_count; 104 | 105 | return; 106 | } 107 | 108 | bool TokenBucket::Get(uint32_t need_tokens) { 109 | if (token_count_ < (int64_t)need_tokens) { 110 | return false; 111 | } 112 | token_count_ -= need_tokens; 113 | return true; 114 | } 115 | 116 | } // anonymous namespace 117 | 118 | namespace gtestx { 119 | 120 | void Perf::Run() { 121 | struct timeval tv_begin, tv_end, tv_use; 122 | unsigned long long count = 0; // NOLINT 123 | 124 | stop_ = false; 125 | hz_ = FLAGS_hz; 126 | time_ = FLAGS_time; 127 | 128 | TokenBucket tb(hz_, hz_/5, hz_/500); 129 | std::thread alarm([this] { 130 | int unit = 10; 131 | for (int ms = time_; !stop_ && ms > 0; ms -= unit) 132 | std::this_thread::sleep_for(std::chrono::milliseconds(ms > unit ? unit : ms)); 133 | stop_ = true; 134 | }); 135 | 136 | gettimeofday(&tv_begin, NULL); 137 | 138 | while (!stop_) { 139 | if (!hz_ || tb.Get(1)) { 140 | TestCode(); 141 | count++; 142 | } else { 143 | usleep(1000); 144 | tb.Gen(); 145 | } 146 | } 147 | 148 | gettimeofday(&tv_end, NULL); 149 | timersub(&tv_end, &tv_begin, &tv_use); 150 | 151 | setlocale(LC_ALL, ""); 152 | printf(" count: %'llu\n", count); 153 | printf(" time: %'d.%06d s\n", static_cast(tv_use.tv_sec), 154 | static_cast(tv_use.tv_usec)); 155 | printf(" HZ: %'f\n", count/(tv_use.tv_sec+0.000001*tv_use.tv_usec)); 156 | printf(" 1/HZ: %'.9f s\n", (tv_use.tv_sec+0.000001*tv_use.tv_usec)/count); 157 | 158 | alarm.join(); 159 | } 160 | 161 | void Perf::Abort() { 162 | stop_ = true; 163 | } 164 | 165 | } // namespace gtestx 166 | 167 | PERF_TEST_MAIN 168 | 169 | -------------------------------------------------------------------------------- /src/gtestx/gtestx.h: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2012-2017, Bin Wei 2 | * All rights reserved. 3 | * 4 | * Redistribution and use in source and binary forms, with or without 5 | * modification, are permitted provided that the following conditions are 6 | * met: 7 | * 8 | * * Redistributions of source code must retain the above copyright 9 | * notice, this list of conditions and the following disclaimer. 10 | * * Redistributions in binary form must reproduce the above 11 | * copyright notice, this list of conditions and the following disclaimer 12 | * in the documentation and/or other materials provided with the 13 | * distribution. 14 | * * The names of its contributors may not be used to endorse or 15 | * promote products derived from this software without specific prior 16 | * written permission. 17 | * 18 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 21 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 22 | * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 23 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 24 | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | */ 30 | #ifndef GTESTX_GTESTX_H_ 31 | #define GTESTX_GTESTX_H_ 32 | 33 | #include "gtest/gtest.h" 34 | #include "gflags/gflags.h" 35 | 36 | /* GTESTX is a benchmark extension for gtest 37 | * 38 | * Added Macro: 39 | * - PERF_TEST 40 | * - PERF_TEST_F 41 | * - PERF_TEST_P 42 | * - TYPED_PERF_TEST 43 | * - TYPED_PERF_TEST_P 44 | * - {ALL_ABOVE}_OPT 45 | */ 46 | 47 | // conform to Semantic Versioning (http://semver.org) 48 | #define GTESTX_MAJOR_VERSION 1 49 | #define GTESTX_MINOR_VERSION 0 50 | #define GTESTX_PATCH_VERSION 0 51 | #define GTESTX_PRERLEASE_VERSION beta2 52 | 53 | #define PERF_ABORT (Perf::Abort(), "Perf loop aborted!") 54 | 55 | /////////////////////////////////////////////// 56 | 57 | #define _TO_STR(sym) #sym 58 | #define _PERF_TEST_BODY(opt_hz, opt_time) \ 59 | google::FlagSaver flag_saver;\ 60 | if (opt_hz >= 0)\ 61 | google::SetCommandLineOptionWithMode("hz", _TO_STR(opt_hz), google::SET_FLAG_IF_DEFAULT);\ 62 | if (opt_time >= 0)\ 63 | google::SetCommandLineOptionWithMode("time", _TO_STR(opt_time), google::SET_FLAG_IF_DEFAULT);\ 64 | gtestx::Perf::Run(); 65 | 66 | #define PERF_TEST_CLASS_NAME_(test_case_name, test_name) \ 67 | test_case_name##_##test_name##_PerfTest 68 | 69 | /////////////////////////////////////////////// 70 | 71 | #define PERF_TEST_(test_case_name, test_name, parent_class, parent_id, opt_hz, opt_time) \ 72 | class PERF_TEST_CLASS_NAME_(test_case_name, test_name) :\ 73 | public parent_class, public gtestx::Perf {\ 74 | public:\ 75 | PERF_TEST_CLASS_NAME_(test_case_name, test_name)() {}\ 76 | private:\ 77 | virtual void TestCode();\ 78 | };\ 79 | GTEST_TEST_(test_case_name, test_name, \ 80 | PERF_TEST_CLASS_NAME_(test_case_name, test_name), parent_id) {\ 81 | _PERF_TEST_BODY(opt_hz, opt_time)\ 82 | }\ 83 | void PERF_TEST_CLASS_NAME_(test_case_name, test_name)::TestCode() 84 | 85 | #define PERF_TEST(test_case_name, test_name) \ 86 | PERF_TEST_(test_case_name, test_name, \ 87 | ::testing::Test, ::testing::internal::GetTestTypeId(), \ 88 | -1, -1) 89 | 90 | #define PERF_TEST_OPT(test_case_name, test_name, opt_hz, opt_time) \ 91 | PERF_TEST_(test_case_name, test_name, \ 92 | ::testing::Test, ::testing::internal::GetTestTypeId(), \ 93 | opt_hz, opt_time) 94 | 95 | #define PERF_TEST_F(test_fixture, test_name) \ 96 | PERF_TEST_(test_fixture, test_name, \ 97 | test_fixture, ::testing::internal::GetTypeId(), \ 98 | -1, -1) 99 | 100 | #define PERF_TEST_F_OPT(test_fixture, test_name, opt_hz, opt_time) \ 101 | PERF_TEST_(test_fixture, test_name, \ 102 | test_fixture, ::testing::internal::GetTypeId(), \ 103 | opt_hz, opt_time) 104 | 105 | /////////////////////////////////////////////// 106 | 107 | # define TEST_P_(test_case_name, test_name, parent_class) \ 108 | class GTEST_TEST_CLASS_NAME_(test_case_name, test_name) \ 109 | : public parent_class { \ 110 | public: \ 111 | GTEST_TEST_CLASS_NAME_(test_case_name, test_name)() {} \ 112 | virtual void TestBody(); \ 113 | private: \ 114 | static int AddToRegistry() { \ 115 | ::testing::UnitTest::GetInstance()->parameterized_test_registry(). \ 116 | GetTestCasePatternHolder(\ 117 | #test_case_name, __FILE__, __LINE__)->AddTestPattern(\ 118 | #test_case_name, \ 119 | #test_name, \ 120 | new ::testing::internal::TestMetaFactory< \ 121 | GTEST_TEST_CLASS_NAME_(test_case_name, test_name)>()); \ 122 | return 0; \ 123 | } \ 124 | static int gtest_registering_dummy_; \ 125 | GTEST_DISALLOW_COPY_AND_ASSIGN_(\ 126 | GTEST_TEST_CLASS_NAME_(test_case_name, test_name)); \ 127 | }; \ 128 | int GTEST_TEST_CLASS_NAME_(test_case_name, \ 129 | test_name)::gtest_registering_dummy_ = \ 130 | GTEST_TEST_CLASS_NAME_(test_case_name, test_name)::AddToRegistry(); \ 131 | void GTEST_TEST_CLASS_NAME_(test_case_name, test_name)::TestBody() 132 | 133 | # define PERF_TEST_P_(test_case_name, test_name, opt_hz, opt_time) \ 134 | class PERF_TEST_CLASS_NAME_(test_case_name, test_name) :\ 135 | public test_case_name, public gtestx::Perf {\ 136 | public:\ 137 | PERF_TEST_CLASS_NAME_(test_case_name, test_name)() {}\ 138 | private:\ 139 | virtual void TestCode();\ 140 | };\ 141 | TEST_P_(test_case_name, test_name, \ 142 | PERF_TEST_CLASS_NAME_(test_case_name, test_name)) {\ 143 | _PERF_TEST_BODY(opt_hz, opt_time)\ 144 | }\ 145 | void PERF_TEST_CLASS_NAME_(test_case_name, test_name)::TestCode() 146 | 147 | #define PERF_TEST_P(test_case_name, test_name) \ 148 | PERF_TEST_P_(test_case_name, test_name, -1, -1) 149 | 150 | #define PERF_TEST_P_OPT(test_case_name, test_name, opt_hz, opt_time) \ 151 | PERF_TEST_P_(test_case_name, test_name, opt_hz, opt_time) 152 | 153 | /////////////////////////////////////////////// 154 | 155 | #define TYPED_TEST_(CaseName, TestName, ParentClass, FixtureClass) \ 156 | template \ 157 | class GTEST_TEST_CLASS_NAME_(CaseName, TestName) \ 158 | : public ParentClass { \ 159 | private: \ 160 | typedef ParentClass TestFixture; \ 161 | typedef gtest_TypeParam_ TypeParam; \ 162 | virtual void TestBody(); \ 163 | }; \ 164 | bool gtest_##CaseName##_##TestName##_registered_ = \ 165 | ::testing::internal::TypeParameterizedTest< \ 166 | FixtureClass, \ 167 | ::testing::internal::TemplateSel< \ 168 | GTEST_TEST_CLASS_NAME_(CaseName, TestName)>, \ 169 | GTEST_TYPE_PARAMS_(CaseName)>::Register(\ 170 | "", #CaseName, #TestName, 0); \ 171 | template \ 172 | void GTEST_TEST_CLASS_NAME_(CaseName, TestName)::TestBody() 173 | 174 | #define TYPED_PERF_TEST_(test_case_name, test_name, opt_hz, opt_time) \ 175 | template \ 176 | class PERF_TEST_CLASS_NAME_(test_case_name, test_name) :\ 177 | public test_case_name, public gtestx::Perf {\ 178 | public:\ 179 | PERF_TEST_CLASS_NAME_(test_case_name, test_name)() {}\ 180 | private:\ 181 | typedef test_case_name TestFixture; \ 182 | typedef T TypeParam; \ 183 | virtual void TestCode();\ 184 | };\ 185 | TYPED_TEST_(test_case_name, test_name, \ 186 | PERF_TEST_CLASS_NAME_(test_case_name, test_name), test_case_name) {\ 187 | _PERF_TEST_BODY(opt_hz, opt_time)\ 188 | }\ 189 | template \ 190 | void PERF_TEST_CLASS_NAME_(test_case_name, test_name)::TestCode() 191 | 192 | #define TYPED_PERF_TEST_CASE(CaseName, Types) TYPED_TEST_CASE(CaseName, Types) 193 | 194 | #define TYPED_PERF_TEST(test_case_name, test_name) \ 195 | TYPED_PERF_TEST_(test_case_name, test_name, -1, -1) 196 | 197 | #define TYPED_PERF_TEST_OPT(test_case_name, test_name, opt_hz, opt_time) \ 198 | TYPED_PERF_TEST_(test_case_name, test_name, opt_hz, opt_time) 199 | 200 | /////////////////////////////////////////////// 201 | 202 | #define TYPED_TEST_P_(CaseName, TestName, ParentClass) \ 203 | namespace GTEST_CASE_NAMESPACE_(CaseName) { \ 204 | template \ 205 | class TestName : public ParentClass { \ 206 | private: \ 207 | typedef ParentClass TestFixture; \ 208 | typedef gtest_TypeParam_ TypeParam; \ 209 | virtual void TestBody(); \ 210 | }; \ 211 | static bool gtest_##TestName##_defined_ = \ 212 | GTEST_TYPED_TEST_CASE_P_STATE_(CaseName).AddTestName(\ 213 | __FILE__, __LINE__, #CaseName, #TestName); \ 214 | } /* NOLINT */ \ 215 | template \ 216 | void GTEST_CASE_NAMESPACE_(CaseName)::TestName::TestBody() 217 | 218 | #define TYPED_PERF_TEST_P_(test_case_name, test_name, opt_hz, opt_time) \ 219 | template \ 220 | class PERF_TEST_CLASS_NAME_(test_case_name, test_name) :\ 221 | public test_case_name, public gtestx::Perf {\ 222 | public:\ 223 | PERF_TEST_CLASS_NAME_(test_case_name, test_name)() {}\ 224 | private:\ 225 | typedef test_case_name TestFixture; \ 226 | typedef T TypeParam; \ 227 | virtual void TestCode();\ 228 | };\ 229 | TYPED_TEST_P_(test_case_name, test_name, \ 230 | PERF_TEST_CLASS_NAME_(test_case_name, test_name)) {\ 231 | _PERF_TEST_BODY(opt_hz, opt_time)\ 232 | }\ 233 | template \ 234 | void PERF_TEST_CLASS_NAME_(test_case_name, test_name)::TestCode() 235 | 236 | #define TYPED_PERF_TEST_CASE_P(ClassName) TYPED_TEST_CASE_P(CaseName) 237 | 238 | #define TYPED_PERF_TEST_P(test_case_name, test_name) \ 239 | TYPED_PERF_TEST_P_(test_case_name, test_name, -1, -1) 240 | 241 | #define TYPED_PERF_TEST_P_OPT(test_case_name, test_name, opt_hz, opt_time) \ 242 | TYPED_PERF_TEST_P_(test_case_name, test_name, opt_hz, opt_time) 243 | 244 | #define REGISTER_TYPED_PERF_TEST_CASE_P(CaseName, ...) \ 245 | REGISTER_TYPED_TEST_CASE_P(CaseName, __VA_ARGS__) 246 | 247 | #define INSTANTIATE_TYPED_PERF_TEST_CASE_P(Prefix, CaseName, Types) \ 248 | INSTANTIATE_TYPED_TEST_CASE_P(Prefix, CaseName, Types) 249 | 250 | /////////////////////////////////////////////// 251 | 252 | #define PERF_TEST_MAIN \ 253 | int main(int argc, char** argv) { \ 254 | testing::InitGoogleTest(&argc, argv); \ 255 | google::ParseCommandLineFlags(&argc, &argv, true); \ 256 | return RUN_ALL_TESTS(); \ 257 | } 258 | 259 | /////////////////////////////////////////////// 260 | 261 | namespace gtestx { 262 | 263 | class Perf { 264 | public: 265 | virtual ~Perf() {} 266 | virtual void TestCode() = 0; 267 | void Run(); 268 | void Abort(); 269 | 270 | private: 271 | size_t hz_; 272 | time_t time_; 273 | volatile bool stop_; 274 | }; 275 | 276 | } // namespace gtestx 277 | 278 | #endif // GTESTX_GTESTX_H_ 279 | --------------------------------------------------------------------------------