| OLD | NEW |
| (Empty) |
| 1 // Copyright (c) 2009 The Chromium Authors. All rights reserved. | |
| 2 // Use of this source code is governed by a BSD-style license that can be | |
| 3 // found in the LICENSE file. | |
| 4 | |
| 5 #include <windows.h> | |
| 6 | |
| 7 #include <vector> | |
| 8 | |
| 9 #include "base/command_line.h" | |
| 10 #include "base/logging.h" | |
| 11 #include "base/process_util.h" | |
| 12 #include "base/string_util.h" | |
| 13 | |
| 14 namespace { | |
| 15 | |
| 16 const wchar_t* const kBrowserTestDLLName = L"browser_tests.dll"; | |
| 17 const wchar_t* const kGTestListTestsFlag = L"gtest_list_tests"; | |
| 18 } | |
| 19 | |
| 20 // TestEnvContext takes care of loading/unloading the DLL containing the tests. | |
| 21 class TestEnvContext { | |
| 22 public: | |
| 23 TestEnvContext() | |
| 24 : module_(NULL), | |
| 25 run_test_proc_(NULL) { | |
| 26 } | |
| 27 | |
| 28 ~TestEnvContext() { | |
| 29 if (!module_) | |
| 30 return; | |
| 31 BOOL r = ::FreeLibrary(module_); | |
| 32 DCHECK(r); | |
| 33 LOG(INFO) << "Unloaded " << kBrowserTestDLLName; | |
| 34 } | |
| 35 | |
| 36 bool Init() { | |
| 37 module_ = ::LoadLibrary(kBrowserTestDLLName); | |
| 38 if (!module_) { | |
| 39 LOG(ERROR) << "Failed to find " << kBrowserTestDLLName; | |
| 40 return false; | |
| 41 } | |
| 42 | |
| 43 run_test_proc_ = reinterpret_cast<RunTestProc>( | |
| 44 ::GetProcAddress(module_, "RunTests")); | |
| 45 if (!run_test_proc_) { | |
| 46 LOG(ERROR) << | |
| 47 "Failed to find RunTest function in " << kBrowserTestDLLName; | |
| 48 return false; | |
| 49 } | |
| 50 | |
| 51 return true; | |
| 52 } | |
| 53 | |
| 54 // Returns true if the test succeeded, false if it failed. | |
| 55 bool RunTest(const std::string& test_name) { | |
| 56 std::string filter_flag = StringPrintf("--gtest_filter=%s", | |
| 57 test_name.c_str()); | |
| 58 char* argv[2]; | |
| 59 argv[0] = ""; | |
| 60 argv[1] = const_cast<char*>(filter_flag.c_str()); | |
| 61 return RunAsIs(2, argv) == 0; | |
| 62 } | |
| 63 | |
| 64 // Calls-in to GTest with the arguments we were started with. | |
| 65 int RunAsIs(int argc, char** argv) { | |
| 66 return (run_test_proc_)(argc, argv); | |
| 67 } | |
| 68 | |
| 69 private: | |
| 70 typedef int (__cdecl *RunTestProc)(int, char**); | |
| 71 | |
| 72 HMODULE module_; | |
| 73 RunTestProc run_test_proc_; | |
| 74 }; | |
| 75 | |
| 76 // Retrieves the list of tests to run. | |
| 77 // Simply uses the --gtest_list_tests option which honor the filter. | |
| 78 // Sadly there is no dry-run option (or willingness to get such an option) in | |
| 79 // GTest. So we'll have to process disabled and repeat options ourselves. | |
| 80 bool GetTestList(const CommandLine& command_line, | |
| 81 std::vector<std::string>* test_list) { | |
| 82 DCHECK(!command_line.HasSwitch(kGTestListTestsFlag)); | |
| 83 | |
| 84 // Run ourselves with the --gtest_list_tests option and read the output. | |
| 85 std::wstring new_command_line = command_line.command_line_string() + L" --" + | |
| 86 kGTestListTestsFlag; | |
| 87 std::string output; | |
| 88 if (!base::GetAppOutput(new_command_line, &output)) | |
| 89 return false; | |
| 90 | |
| 91 // Now let's parse the returned output. | |
| 92 // It looks like: | |
| 93 // TestCase. | |
| 94 // Test1 | |
| 95 // Test2 | |
| 96 // OtherTestCase. | |
| 97 // FooTest | |
| 98 // ... | |
| 99 std::vector<std::string> lines; | |
| 100 SplitString(output, '\n', &lines); | |
| 101 | |
| 102 std::string test_case; | |
| 103 for (std::vector<std::string>::const_iterator iter = lines.begin(); | |
| 104 iter != lines.end(); ++iter) { | |
| 105 std::string line = *iter; | |
| 106 if (line.empty()) | |
| 107 continue; // Just ignore empty lines if any. | |
| 108 | |
| 109 if (line[line.size() - 1] == '.') { | |
| 110 // This is a new test case. | |
| 111 test_case = line; | |
| 112 continue; | |
| 113 } | |
| 114 // We are dealing with a test. | |
| 115 test_list->push_back(test_case + line); | |
| 116 } | |
| 117 return true; | |
| 118 } | |
| 119 | |
| 120 int main(int argc, char** argv) { | |
| 121 CommandLine::Init(argc, argv); | |
| 122 const CommandLine* command_line = CommandLine::ForCurrentProcess(); | |
| 123 | |
| 124 if (command_line->HasSwitch(kGTestListTestsFlag)) { | |
| 125 TestEnvContext test_context; | |
| 126 if (!test_context.Init()) | |
| 127 return 1; | |
| 128 return test_context.RunAsIs(argc, argv); | |
| 129 } | |
| 130 | |
| 131 // First let's get the list of tests we need to run. | |
| 132 std::vector<std::string> test_list; | |
| 133 if (!GetTestList(*command_line, &test_list)) { | |
| 134 printf("Failed to retrieve the tests to run.\n"); | |
| 135 return 0; | |
| 136 } | |
| 137 | |
| 138 if (test_list.empty()) { | |
| 139 printf("No tests to run.\n"); | |
| 140 return 0; | |
| 141 } | |
| 142 | |
| 143 // Run the tests. | |
| 144 int test_run_count = 0; | |
| 145 std::vector<std::string> failed_tests; | |
| 146 for (std::vector<std::string>::const_iterator iter = test_list.begin(); | |
| 147 iter != test_list.end(); ++iter) { | |
| 148 std::string test_name = *iter; | |
| 149 TestEnvContext test_context; | |
| 150 if (!test_context.Init()) | |
| 151 return 1; | |
| 152 test_run_count++; | |
| 153 if (!test_context.RunTest(test_name.c_str())) { | |
| 154 if (std::find(failed_tests.begin(), failed_tests.end(), test_name) == | |
| 155 failed_tests.end()) { | |
| 156 failed_tests.push_back(*iter); | |
| 157 } | |
| 158 } | |
| 159 } | |
| 160 | |
| 161 printf("%d test%s run\n", test_run_count, test_run_count > 1 ? "s" : ""); | |
| 162 printf("%d test%s failed\n", failed_tests.size(), | |
| 163 failed_tests.size() > 1 ? "s" : ""); | |
| 164 if (failed_tests.empty()) | |
| 165 return 0; | |
| 166 | |
| 167 printf("Failing tests:\n"); | |
| 168 for (std::vector<std::string>::const_iterator iter = failed_tests.begin(); | |
| 169 iter != failed_tests.end(); ++iter) { | |
| 170 printf("%s\n", iter->c_str()); | |
| 171 } | |
| 172 | |
| 173 return 1; | |
| 174 } | |
| OLD | NEW |