Home | History | Annotate | Download | only in unittest
      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