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 |