1 /* 2 This file is part of Valgrind, a dynamic binary instrumentation 3 framework. 4 5 Copyright (C) 2008-2008 Google Inc 6 opensource (at) google.com 7 8 This program is free software; you can redistribute it and/or 9 modify it under the terms of the GNU General Public License as 10 published by the Free Software Foundation; either version 2 of the 11 License, or (at your option) any later version. 12 13 This program is distributed in the hope that it will be useful, but 14 WITHOUT ANY WARRANTY; without even the implied warranty of 15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16 General Public License for more details. 17 18 You should have received a copy of the GNU General Public License 19 along with this program; if not, write to the Free Software 20 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 21 02111-1307, USA. 22 23 The GNU General Public License is contained in the file COPYING. 24 */ 25 26 /* Author: Konstantin Serebryany <opensource (at) google.com> 27 28 This file contains a simple test suite for some of our old unit-tests. 29 These tests are likely to be moved to googletest framework over time. 30 */ 31 32 #include <algorithm> 33 #include <gtest/gtest.h> 34 #include <string> 35 #include <ostream> 36 37 #include "old_test_suite.h" 38 39 Mutex printf_mu; 40 std::map<int, Test> *TheMapOfTests = NULL; 41 std::vector<int> tests_to_run; 42 std::set<int> tests_to_exclude; 43 44 #ifndef MAIN_INIT_ACTION 45 #define MAIN_INIT_ACTION 46 #endif 47 48 int ParseInt(const char *str) { 49 int ret = 0; 50 const char *cur = str; 51 do { 52 if (!isdigit(*cur)) { 53 printf("\"%s\" is not a valid number\n", str); 54 exit(1); 55 } 56 57 ret = ret*10 + (*cur - '0'); 58 } while (*(++cur)); 59 return ret; 60 } 61 62 class RandomGenerator { 63 public: 64 RandomGenerator(int seed) { srand(seed); } 65 size_t operator( )(size_t n) const { return rand() % n; } 66 }; 67 68 TEST(NonGtestTests, All) { 69 for (size_t i = 0; i < tests_to_run.size(); i++) { 70 int test_id = tests_to_run[i]; 71 if (tests_to_exclude.count(test_id) > 0) { 72 printf("test%i was excluded\n", test_id); 73 } else { 74 (*TheMapOfTests)[test_id].Run(); 75 ANNOTATE_FLUSH_EXPECTED_RACES(); 76 } 77 } 78 } 79 80 #ifndef ANDROID // GTest version is too old. 81 class PerformanceTestEventListener: public ::testing::EmptyTestEventListener { 82 public: 83 virtual void OnTestEnd(const ::testing::TestInfo& test_info) { 84 if (strcmp(test_info.test_case_name(), "StressTests") == 0 || 85 strcmp(test_info.test_case_name(), "PerformanceTests") == 0) { 86 const ::testing::TestResult* result = test_info.result(); 87 times_[test_info.name()].push_back(result->elapsed_time()); 88 } 89 } 90 91 virtual void OnTestProgramEnd(const ::testing::UnitTest& unit_test) { 92 for (std::map<string, std::vector<long long int> >::iterator it = times_.begin(); 93 it != times_.end(); ++it) { 94 printf("*RESULT %s: time= %s ms\n", it->first.c_str(), join_str(it->second).c_str()); 95 } 96 } 97 98 private: 99 std::map<string, std::vector<long long int> > times_; 100 101 string join_str(std::vector<long long int> values) { 102 bool first = true; 103 bool single = (values.size() == 1); 104 std::ostringstream st; 105 if (!single) { 106 st << "["; 107 } 108 for (std::vector<long long int>::iterator it = values.begin(); 109 it != values.end(); ++it) { 110 if (first) { 111 first = false; 112 } else { 113 st << " "; 114 } 115 st << *it; 116 } 117 if (!single) { 118 st << "]"; 119 } 120 return st.str(); 121 } 122 }; 123 #endif 124 125 int main(int argc, char** argv) { 126 MAIN_INIT_ACTION; 127 testing::InitGoogleTest(&argc, argv); 128 printf("FLAGS [phb=%i, rv=%i]\n", Tsan_PureHappensBefore(), 129 Tsan_RaceVerifier()); 130 131 int shuffle_seed = 0; // non-zero to shuffle. 132 133 int id = 1; 134 while (id < argc) { 135 char *cur_arg = argv[id]; 136 if (!strcmp(cur_arg, "benchmark")) { 137 for (std::map<int,Test>::iterator it = TheMapOfTests->begin(); 138 it != TheMapOfTests->end(); ++it) { 139 if(it->second.flags_ & PERFORMANCE) 140 tests_to_run.push_back(it->first); 141 } 142 } else if (!strcmp(cur_arg, "demo")) { 143 for (std::map<int,Test>::iterator it = TheMapOfTests->begin(); 144 it != TheMapOfTests->end(); ++it) { 145 if(it->second.flags_ & RACE_DEMO) 146 tests_to_run.push_back(it->first); 147 } 148 } else if (!strncmp(cur_arg, "shuffle", 7)) { 149 if (strlen(cur_arg) == 7) { 150 shuffle_seed = GetTimeInMs(); 151 printf("Shuffling with seed = %i\n", shuffle_seed); 152 } else { 153 CHECK(cur_arg[7] == '='); 154 shuffle_seed = ParseInt(cur_arg + 8); 155 } 156 } else { 157 if (isdigit(cur_arg[0])) { 158 // Enqueue the test specified. 159 int test_id = ParseInt(cur_arg); 160 if (!TheMapOfTests->count(test_id)) { 161 printf("Unknown test id: %d\n", test_id); 162 exit(1); 163 } 164 tests_to_run.push_back(test_id); 165 } else if (cur_arg[0] == '-') { 166 // Exclude the test specified. 167 int test_id = ParseInt(cur_arg + 1); 168 if (!TheMapOfTests->count(test_id)) { 169 printf("Unknown test id: %d\n", test_id); 170 exit(1); 171 } 172 tests_to_exclude.insert(test_id); 173 } else { 174 printf("Unknown argument: %s\n", cur_arg); 175 exit(1); 176 } 177 } 178 179 id++; 180 } 181 182 if (tests_to_run.size() == 0) { 183 printf("No tests specified.\nRunning default set of tests...\n"); 184 for (std::map<int,Test>::iterator it = TheMapOfTests->begin(); 185 it != TheMapOfTests->end(); 186 ++it) { 187 if(it->second.flags_ & EXCLUDE_FROM_ALL) continue; 188 if(it->second.flags_ & RACE_DEMO) continue; 189 tests_to_run.push_back(it->first); 190 } 191 } 192 193 if (shuffle_seed > 0) { 194 RandomGenerator rnd(shuffle_seed); 195 random_shuffle(tests_to_run.begin(), tests_to_run.end(), rnd); 196 } 197 198 #ifndef ANDROID // GTest version is too old. 199 ::testing::TestEventListeners& listeners = 200 ::testing::UnitTest::GetInstance()->listeners(); 201 // Adds a listener to the end. Google Test takes the ownership. 202 listeners.Append(new PerformanceTestEventListener()); 203 #endif 204 205 return RUN_ALL_TESTS(); 206 } 207 // End {{{1 208 // vim:shiftwidth=2:softtabstop=2:expandtab:foldmethod=marker 209