1610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov/*
2610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  This file is part of Valgrind, a dynamic binary instrumentation
3610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  framework.
4610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
5610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  Copyright (C) 2008-2008 Google Inc
6610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov     opensource@google.com
7610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
8610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  This program is free software; you can redistribute it and/or
9610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  modify it under the terms of the GNU General Public License as
10610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  published by the Free Software Foundation; either version 2 of the
11610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  License, or (at your option) any later version.
12610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
13610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  This program is distributed in the hope that it will be useful, but
14610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  WITHOUT ANY WARRANTY; without even the implied warranty of
15610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  General Public License for more details.
17610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
18610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  You should have received a copy of the GNU General Public License
19610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  along with this program; if not, write to the Free Software
20610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
21610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  02111-1307, USA.
22610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
23610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  The GNU General Public License is contained in the file COPYING.
24610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov*/
25610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
26610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov/* Author: Konstantin Serebryany <opensource@google.com>
27610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
28610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov This file contains a simple test suite for some of our old unit-tests.
29610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov These tests are likely to be moved to googletest framework over time.
30610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov*/
31610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
32610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov#include <algorithm>
33610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov#include <gtest/gtest.h>
34610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov#include <string>
35610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov#include <ostream>
36610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
37610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov#include "old_test_suite.h"
38610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
39610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovMutex printf_mu;
40610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovstd::map<int, Test> *TheMapOfTests = NULL;
41610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovstd::vector<int> tests_to_run;
42610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovstd::set<int> tests_to_exclude;
43610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
44610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov#ifndef MAIN_INIT_ACTION
45610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov#define MAIN_INIT_ACTION
46610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov#endif
47610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
48610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovint ParseInt(const char *str) {
49610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  int ret = 0;
50610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  const char *cur = str;
51610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  do {
52610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    if (!isdigit(*cur)) {
53610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov      printf("\"%s\" is not a valid number\n", str);
54610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov      exit(1);
55610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    }
56610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
57610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    ret = ret*10 + (*cur - '0');
58610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  } while (*(++cur));
59610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  return ret;
60610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
61610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
62610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovclass RandomGenerator {
63610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov public:
64610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  RandomGenerator(int seed) { srand(seed); }
65610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  size_t operator( )(size_t n) const { return rand() % n; }
66610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov};
67610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
68610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovTEST(NonGtestTests, All) {
69610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  for (size_t i = 0; i < tests_to_run.size(); i++) {
70610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    int test_id = tests_to_run[i];
71610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    if (tests_to_exclude.count(test_id) > 0) {
72610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov      printf("test%i was excluded\n", test_id);
73610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    } else {
74610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov      (*TheMapOfTests)[test_id].Run();
75610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov      ANNOTATE_FLUSH_EXPECTED_RACES();
76610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    }
77610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  }
78610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
79610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
80610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov#ifndef ANDROID // GTest version is too old.
81610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovclass PerformanceTestEventListener: public ::testing::EmptyTestEventListener {
82610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov public:
83610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  virtual void OnTestEnd(const ::testing::TestInfo& test_info) {
84610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    if (strcmp(test_info.test_case_name(), "StressTests") == 0 ||
85610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov        strcmp(test_info.test_case_name(), "PerformanceTests") == 0) {
86610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov      const ::testing::TestResult* result = test_info.result();
87610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov      times_[test_info.name()].push_back(result->elapsed_time());
88610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    }
89610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  }
90610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
91610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  virtual void OnTestProgramEnd(const ::testing::UnitTest& unit_test) {
92610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    for (std::map<string, std::vector<long long int> >::iterator it = times_.begin();
93610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov         it != times_.end(); ++it) {
94610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov      printf("*RESULT %s: time= %s ms\n", it->first.c_str(), join_str(it->second).c_str());
95610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    }
96610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  }
97610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
98610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov private:
99610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  std::map<string, std::vector<long long int> > times_;
100610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
101610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  string join_str(std::vector<long long int> values) {
102610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    bool first = true;
103610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    bool single = (values.size() == 1);
104610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    std::ostringstream st;
105610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    if (!single) {
106610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov      st << "[";
107610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    }
108610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    for (std::vector<long long int>::iterator it = values.begin();
109610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov         it != values.end(); ++it) {
110610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov      if (first) {
111610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov        first = false;
112610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov      } else {
113610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov        st << " ";
114610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov      }
115610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov      st << *it;
116610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    }
117610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    if (!single) {
118610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov      st << "]";
119610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    }
120610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    return st.str();
121610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  }
122610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov};
123610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov#endif
124610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
125610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovint main(int argc, char** argv) {
126610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MAIN_INIT_ACTION;
127610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  testing::InitGoogleTest(&argc, argv);
128610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  printf("FLAGS [phb=%i, rv=%i]\n", Tsan_PureHappensBefore(),
129610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov      Tsan_RaceVerifier());
130610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
131610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  int shuffle_seed = 0;  // non-zero to shuffle.
132610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
133610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  int id = 1;
134610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  while (id < argc) {
135610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    char *cur_arg = argv[id];
136610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    if (!strcmp(cur_arg, "benchmark")) {
137610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov      for (std::map<int,Test>::iterator it = TheMapOfTests->begin();
138610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov        it != TheMapOfTests->end(); ++it) {
139610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov        if(it->second.flags_ & PERFORMANCE)
140610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov          tests_to_run.push_back(it->first);
141610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov      }
142610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    } else if (!strcmp(cur_arg, "demo")) {
143610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov      for (std::map<int,Test>::iterator it = TheMapOfTests->begin();
144610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov        it != TheMapOfTests->end();  ++it) {
145610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov        if(it->second.flags_ & RACE_DEMO)
146610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov          tests_to_run.push_back(it->first);
147610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov      }
148610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    } else if (!strncmp(cur_arg, "shuffle", 7)) {
149610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov      if (strlen(cur_arg) == 7) {
150610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov        shuffle_seed = GetTimeInMs();
151610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov        printf("Shuffling with seed = %i\n", shuffle_seed);
152610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov      } else {
153610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov        CHECK(cur_arg[7] == '=');
154610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov        shuffle_seed = ParseInt(cur_arg + 8);
155610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov      }
156610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    } else {
157610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov      if (isdigit(cur_arg[0])) {
158610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov        // Enqueue the test specified.
159610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov        int test_id = ParseInt(cur_arg);
160610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov        if (!TheMapOfTests->count(test_id)) {
161610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov          printf("Unknown test id: %d\n", test_id);
162610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov          exit(1);
163610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov        }
164610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov        tests_to_run.push_back(test_id);
165610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov      } else if (cur_arg[0] == '-') {
166610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov        // Exclude the test specified.
167610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov        int test_id = ParseInt(cur_arg + 1);
168610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov        if (!TheMapOfTests->count(test_id)) {
169610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov          printf("Unknown test id: %d\n", test_id);
170610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov          exit(1);
171610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov        }
172610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov        tests_to_exclude.insert(test_id);
173610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov      } else {
174610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov        printf("Unknown argument: %s\n", cur_arg);
175610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov        exit(1);
176610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov      }
177610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    }
178610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
179610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    id++;
180610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  }
181610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
182610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  if (tests_to_run.size() == 0) {
183610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    printf("No tests specified.\nRunning default set of tests...\n");
184610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    for (std::map<int,Test>::iterator it = TheMapOfTests->begin();
185610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov        it != TheMapOfTests->end();
186610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov        ++it) {
187610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov      if(it->second.flags_ & EXCLUDE_FROM_ALL) continue;
188610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov      if(it->second.flags_ & RACE_DEMO) continue;
189610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov      tests_to_run.push_back(it->first);
190610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    }
191610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  }
192610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
193610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  if (shuffle_seed > 0) {
194610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    RandomGenerator rnd(shuffle_seed);
195610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    random_shuffle(tests_to_run.begin(), tests_to_run.end(), rnd);
196610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  }
197610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
198610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov#ifndef ANDROID // GTest version is too old.
199610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  ::testing::TestEventListeners& listeners =
200610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov        ::testing::UnitTest::GetInstance()->listeners();
201610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  // Adds a listener to the end.  Google Test takes the ownership.
202610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  listeners.Append(new PerformanceTestEventListener());
203610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov#endif
204610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
205610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  return RUN_ALL_TESTS();
206610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
207610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// End {{{1
208610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov // vim:shiftwidth=2:softtabstop=2:expandtab:foldmethod=marker
209