Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(544)

Side by Side Diff: content/test/gpu/gpu_test_expectations_parser.cc

Issue 15827008: Move gpu_test_config stuff from content/ to gpu/ (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: Created 7 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
1 // Copyright (c) 2012 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 "content/test/gpu/gpu_test_expectations_parser.h"
6
7 #include "base/base_paths.h"
8 #include "base/file_util.h"
9 #include "base/logging.h"
10 #include "base/path_service.h"
11 #include "base/string_number_conversions.h"
12 #include "base/string_util.h"
13 #include "base/stringprintf.h"
14 #include "base/strings/string_split.h"
15 #include "content/public/common/content_paths.h"
16
17 namespace {
18
19 enum LineParserStage {
20 kLineParserBegin = 0,
21 kLineParserBugID,
22 kLineParserConfigs,
23 kLineParserColon,
24 kLineParserTestName,
25 kLineParserEqual,
26 kLineParserExpectations,
27 };
28
29 enum Token {
30 // os
31 kConfigWinXP = 0,
32 kConfigWinVista,
33 kConfigWin7,
34 kConfigWin8,
35 kConfigWin,
36 kConfigMacLeopard,
37 kConfigMacSnowLeopard,
38 kConfigMacLion,
39 kConfigMacMountainLion,
40 kConfigMac,
41 kConfigLinux,
42 kConfigChromeOS,
43 kConfigAndroid,
44 // gpu vendor
45 kConfigNVidia,
46 kConfigAMD,
47 kConfigIntel,
48 kConfigVMWare,
49 // build type
50 kConfigRelease,
51 kConfigDebug,
52 // expectation
53 kExpectationPass,
54 kExpectationFail,
55 kExpectationFlaky,
56 kExpectationTimeout,
57 kExpectationSkip,
58 // separator
59 kSeparatorColon,
60 kSeparatorEqual,
61
62 kNumberOfExactMatchTokens,
63
64 // others
65 kConfigGPUDeviceID,
66 kTokenComment,
67 kTokenWord,
68 };
69
70 struct TokenInfo {
71 const char* name;
72 int32 flag;
73 };
74
75 const TokenInfo kTokenData[] = {
76 { "xp", GPUTestConfig::kOsWinXP },
77 { "vista", GPUTestConfig::kOsWinVista },
78 { "win7", GPUTestConfig::kOsWin7 },
79 { "win8", GPUTestConfig::kOsWin8 },
80 { "win", GPUTestConfig::kOsWin },
81 { "leopard", GPUTestConfig::kOsMacLeopard },
82 { "snowleopard", GPUTestConfig::kOsMacSnowLeopard },
83 { "lion", GPUTestConfig::kOsMacLion },
84 { "mountainlion", GPUTestConfig::kOsMacMountainLion },
85 { "mac", GPUTestConfig::kOsMac },
86 { "linux", GPUTestConfig::kOsLinux },
87 { "chromeos", GPUTestConfig::kOsChromeOS },
88 { "android", GPUTestConfig::kOsAndroid },
89 { "nvidia", 0x10DE },
90 { "amd", 0x1002 },
91 { "intel", 0x8086 },
92 { "vmware", 0x15ad },
93 { "release", GPUTestConfig::kBuildTypeRelease },
94 { "debug", GPUTestConfig::kBuildTypeDebug },
95 { "pass", GPUTestExpectationsParser::kGpuTestPass },
96 { "fail", GPUTestExpectationsParser::kGpuTestFail },
97 { "flaky", GPUTestExpectationsParser::kGpuTestFlaky },
98 { "timeout", GPUTestExpectationsParser::kGpuTestTimeout },
99 { "skip", GPUTestExpectationsParser::kGpuTestSkip },
100 { ":", 0 },
101 { "=", 0 },
102 };
103
104 enum ErrorType {
105 kErrorFileIO = 0,
106 kErrorIllegalEntry,
107 kErrorInvalidEntry,
108 kErrorEntryWithOsConflicts,
109 kErrorEntryWithGpuVendorConflicts,
110 kErrorEntryWithBuildTypeConflicts,
111 kErrorEntryWithGpuDeviceIdConflicts,
112 kErrorEntryWithExpectationConflicts,
113 kErrorEntriesOverlap,
114
115 kNumberOfErrors,
116 };
117
118 const char* kErrorMessage[] = {
119 "file IO failed",
120 "entry with wrong format",
121 "entry invalid, likely wrong modifiers combination",
122 "entry with OS modifier conflicts",
123 "entry with GPU vendor modifier conflicts",
124 "entry with GPU build type conflicts",
125 "entry with GPU device id conflicts or malformat",
126 "entry with expectation modifier conflicts",
127 "two entries's configs overlap",
128 };
129
130 Token ParseToken(const std::string& word) {
131 if (StartsWithASCII(word, "//", false))
132 return kTokenComment;
133 if (StartsWithASCII(word, "0x", false))
134 return kConfigGPUDeviceID;
135
136 for (int32 i = 0; i < kNumberOfExactMatchTokens; ++i) {
137 if (LowerCaseEqualsASCII(word, kTokenData[i].name))
138 return static_cast<Token>(i);
139 }
140 return kTokenWord;
141 }
142
143 // reference name can have the last character as *.
144 bool NamesMatching(const std::string& ref, const std::string& test_name) {
145 size_t len = ref.length();
146 if (len == 0)
147 return false;
148 if (ref[len - 1] == '*') {
149 if (test_name.length() > len -1 &&
150 ref.compare(0, len - 1, test_name, 0, len - 1) == 0)
151 return true;
152 return false;
153 }
154 return (ref == test_name);
155 }
156
157 } // namespace anonymous
158
159 GPUTestExpectationsParser::GPUTestExpectationsParser() {
160 // Some sanity check.
161 DCHECK_EQ(static_cast<unsigned int>(kNumberOfExactMatchTokens),
162 sizeof(kTokenData) / sizeof(kTokenData[0]));
163 DCHECK_EQ(static_cast<unsigned int>(kNumberOfErrors),
164 sizeof(kErrorMessage) / sizeof(kErrorMessage[0]));
165 }
166
167 GPUTestExpectationsParser::~GPUTestExpectationsParser() {
168 }
169
170 bool GPUTestExpectationsParser::LoadTestExpectations(const std::string& data) {
171 entries_.clear();
172 error_messages_.clear();
173
174 std::vector<std::string> lines;
175 base::SplitString(data, '\n', &lines);
176 bool rt = true;
177 for (size_t i = 0; i < lines.size(); ++i) {
178 if (!ParseLine(lines[i], i + 1))
179 rt = false;
180 }
181 if (DetectConflictsBetweenEntries()) {
182 entries_.clear();
183 rt = false;
184 }
185
186 return rt;
187 }
188
189 bool GPUTestExpectationsParser::LoadTestExpectations(
190 const base::FilePath& path) {
191 entries_.clear();
192 error_messages_.clear();
193
194 std::string data;
195 if (!file_util::ReadFileToString(path, &data)) {
196 error_messages_.push_back(kErrorMessage[kErrorFileIO]);
197 return false;
198 }
199 return LoadTestExpectations(data);
200 }
201
202 bool GPUTestExpectationsParser::LoadTestExpectations(
203 GPUTestProfile profile) {
204 base::FilePath path;
205 if (!GetExpectationsPath(profile, &path))
206 return false;
207 return LoadTestExpectations(path);
208 }
209
210 int32 GPUTestExpectationsParser::GetTestExpectation(
211 const std::string& test_name,
212 const GPUTestBotConfig& bot_config) const {
213 for (size_t i = 0; i < entries_.size(); ++i) {
214 if (NamesMatching(entries_[i].test_name, test_name) &&
215 bot_config.Matches(entries_[i].test_config))
216 return entries_[i].test_expectation;
217 }
218 return kGpuTestPass;
219 }
220
221 const std::vector<std::string>&
222 GPUTestExpectationsParser::GetErrorMessages() const {
223 return error_messages_;
224 }
225
226 bool GPUTestExpectationsParser::ParseConfig(
227 const std::string& config_data, GPUTestConfig* config) {
228 DCHECK(config);
229 std::vector<std::string> tokens;
230 base::SplitStringAlongWhitespace(config_data, &tokens);
231
232 for (size_t i = 0; i < tokens.size(); ++i) {
233 Token token = ParseToken(tokens[i]);
234 switch (token) {
235 case kConfigWinXP:
236 case kConfigWinVista:
237 case kConfigWin7:
238 case kConfigWin8:
239 case kConfigWin:
240 case kConfigMacLeopard:
241 case kConfigMacSnowLeopard:
242 case kConfigMacLion:
243 case kConfigMacMountainLion:
244 case kConfigMac:
245 case kConfigLinux:
246 case kConfigChromeOS:
247 case kConfigAndroid:
248 case kConfigNVidia:
249 case kConfigAMD:
250 case kConfigIntel:
251 case kConfigVMWare:
252 case kConfigRelease:
253 case kConfigDebug:
254 case kConfigGPUDeviceID:
255 if (token == kConfigGPUDeviceID) {
256 if (!UpdateTestConfig(config, tokens[i], 0))
257 return false;
258 } else {
259 if (!UpdateTestConfig(config, token, 0))
260 return false;
261 }
262 break;
263 default:
264 return false;
265 }
266 }
267 return true;
268 }
269
270 bool GPUTestExpectationsParser::ParseLine(
271 const std::string& line_data, size_t line_number) {
272 std::vector<std::string> tokens;
273 base::SplitStringAlongWhitespace(line_data, &tokens);
274 int32 stage = kLineParserBegin;
275 GPUTestExpectationEntry entry;
276 entry.line_number = line_number;
277 GPUTestConfig& config = entry.test_config;
278 bool comments_encountered = false;
279 for (size_t i = 0; i < tokens.size() && !comments_encountered; ++i) {
280 Token token = ParseToken(tokens[i]);
281 switch (token) {
282 case kTokenComment:
283 comments_encountered = true;
284 break;
285 case kConfigWinXP:
286 case kConfigWinVista:
287 case kConfigWin7:
288 case kConfigWin8:
289 case kConfigWin:
290 case kConfigMacLeopard:
291 case kConfigMacSnowLeopard:
292 case kConfigMacLion:
293 case kConfigMacMountainLion:
294 case kConfigMac:
295 case kConfigLinux:
296 case kConfigChromeOS:
297 case kConfigAndroid:
298 case kConfigNVidia:
299 case kConfigAMD:
300 case kConfigIntel:
301 case kConfigVMWare:
302 case kConfigRelease:
303 case kConfigDebug:
304 case kConfigGPUDeviceID:
305 // MODIFIERS, could be in any order, need at least one.
306 if (stage != kLineParserConfigs && stage != kLineParserBugID) {
307 PushErrorMessage(kErrorMessage[kErrorIllegalEntry],
308 line_number);
309 return false;
310 }
311 if (token == kConfigGPUDeviceID) {
312 if (!UpdateTestConfig(&config, tokens[i], line_number))
313 return false;
314 } else {
315 if (!UpdateTestConfig(&config, token, line_number))
316 return false;
317 }
318 if (stage == kLineParserBugID)
319 stage++;
320 break;
321 case kSeparatorColon:
322 // :
323 if (stage != kLineParserConfigs) {
324 PushErrorMessage(kErrorMessage[kErrorIllegalEntry],
325 line_number);
326 return false;
327 }
328 stage++;
329 break;
330 case kSeparatorEqual:
331 // =
332 if (stage != kLineParserTestName) {
333 PushErrorMessage(kErrorMessage[kErrorIllegalEntry],
334 line_number);
335 return false;
336 }
337 stage++;
338 break;
339 case kTokenWord:
340 // BUG_ID or TEST_NAME
341 if (stage == kLineParserBegin) {
342 // Bug ID is not used for anything; ignore it.
343 } else if (stage == kLineParserColon) {
344 entry.test_name = tokens[i];
345 } else {
346 PushErrorMessage(kErrorMessage[kErrorIllegalEntry],
347 line_number);
348 return false;
349 }
350 stage++;
351 break;
352 case kExpectationPass:
353 case kExpectationFail:
354 case kExpectationFlaky:
355 case kExpectationTimeout:
356 case kExpectationSkip:
357 // TEST_EXPECTATIONS
358 if (stage != kLineParserEqual && stage != kLineParserExpectations) {
359 PushErrorMessage(kErrorMessage[kErrorIllegalEntry],
360 line_number);
361 return false;
362 }
363 if ((kTokenData[token].flag & entry.test_expectation) != 0) {
364 PushErrorMessage(kErrorMessage[kErrorEntryWithExpectationConflicts],
365 line_number);
366 return false;
367 }
368 entry.test_expectation =
369 (kTokenData[token].flag | entry.test_expectation);
370 if (stage == kLineParserEqual)
371 stage++;
372 break;
373 default:
374 DCHECK(false);
375 break;
376 }
377 }
378 if (stage == kLineParserBegin) {
379 // The whole line is empty or all comments
380 return true;
381 }
382 if (stage == kLineParserExpectations) {
383 if (!config.IsValid()) {
384 PushErrorMessage(kErrorMessage[kErrorInvalidEntry], line_number);
385 return false;
386 }
387 entries_.push_back(entry);
388 return true;
389 }
390 PushErrorMessage(kErrorMessage[kErrorIllegalEntry], line_number);
391 return false;
392 }
393
394 bool GPUTestExpectationsParser::UpdateTestConfig(
395 GPUTestConfig* config, int32 token, size_t line_number) {
396 DCHECK(config);
397 switch (token) {
398 case kConfigWinXP:
399 case kConfigWinVista:
400 case kConfigWin7:
401 case kConfigWin8:
402 case kConfigWin:
403 case kConfigMacLeopard:
404 case kConfigMacSnowLeopard:
405 case kConfigMacLion:
406 case kConfigMacMountainLion:
407 case kConfigMac:
408 case kConfigLinux:
409 case kConfigChromeOS:
410 case kConfigAndroid:
411 if ((config->os() & kTokenData[token].flag) != 0) {
412 PushErrorMessage(kErrorMessage[kErrorEntryWithOsConflicts],
413 line_number);
414 return false;
415 }
416 config->set_os(config->os() | kTokenData[token].flag);
417 break;
418 case kConfigNVidia:
419 case kConfigAMD:
420 case kConfigIntel:
421 case kConfigVMWare:
422 {
423 uint32 gpu_vendor =
424 static_cast<uint32>(kTokenData[token].flag);
425 for (size_t i = 0; i < config->gpu_vendor().size(); ++i) {
426 if (config->gpu_vendor()[i] == gpu_vendor) {
427 PushErrorMessage(
428 kErrorMessage[kErrorEntryWithGpuVendorConflicts],
429 line_number);
430 return false;
431 }
432 }
433 config->AddGPUVendor(gpu_vendor);
434 }
435 break;
436 case kConfigRelease:
437 case kConfigDebug:
438 if ((config->build_type() & kTokenData[token].flag) != 0) {
439 PushErrorMessage(
440 kErrorMessage[kErrorEntryWithBuildTypeConflicts],
441 line_number);
442 return false;
443 }
444 config->set_build_type(
445 config->build_type() | kTokenData[token].flag);
446 break;
447 default:
448 DCHECK(false);
449 break;
450 }
451 return true;
452 }
453
454 bool GPUTestExpectationsParser::UpdateTestConfig(
455 GPUTestConfig* config,
456 const std::string& gpu_device_id,
457 size_t line_number) {
458 DCHECK(config);
459 uint32 device_id = 0;
460 if (config->gpu_device_id() != 0 ||
461 !base::HexStringToInt(gpu_device_id,
462 reinterpret_cast<int*>(&device_id)) ||
463 device_id == 0) {
464 PushErrorMessage(kErrorMessage[kErrorEntryWithGpuDeviceIdConflicts],
465 line_number);
466 return false;
467 }
468 config->set_gpu_device_id(device_id);
469 return true;
470 }
471
472 bool GPUTestExpectationsParser::DetectConflictsBetweenEntries() {
473 bool rt = false;
474 for (size_t i = 0; i < entries_.size(); ++i) {
475 for (size_t j = i + 1; j < entries_.size(); ++j) {
476 if (entries_[i].test_name == entries_[j].test_name &&
477 entries_[i].test_config.OverlapsWith(entries_[j].test_config)) {
478 PushErrorMessage(kErrorMessage[kErrorEntriesOverlap],
479 entries_[i].line_number,
480 entries_[j].line_number);
481 rt = true;
482 }
483 }
484 }
485 return rt;
486 }
487
488 void GPUTestExpectationsParser::PushErrorMessage(
489 const std::string& message, size_t line_number) {
490 error_messages_.push_back(
491 base::StringPrintf("Line %d : %s",
492 static_cast<int>(line_number), message.c_str()));
493 }
494
495 void GPUTestExpectationsParser::PushErrorMessage(
496 const std::string& message,
497 size_t entry1_line_number,
498 size_t entry2_line_number) {
499 error_messages_.push_back(
500 base::StringPrintf("Line %d and %d : %s",
501 static_cast<int>(entry1_line_number),
502 static_cast<int>(entry2_line_number),
503 message.c_str()));
504 }
505
506 // static
507 bool GPUTestExpectationsParser::GetExpectationsPath(
508 GPUTestProfile profile, base::FilePath* path) {
509 DCHECK(path);
510
511 bool rt = true;
512 switch (profile) {
513 case kWebGLConformanceTest:
514 rt = PathService::Get(content::DIR_TEST_DATA, path);
515 if (rt) {
516 *path = path->Append(FILE_PATH_LITERAL("gpu"))
517 .Append(FILE_PATH_LITERAL(
518 "webgl_conformance_test_expectations.txt"));
519 rt = file_util::PathExists(*path);
520 }
521 break;
522 default:
523 DCHECK(false);
524 }
525 return rt;
526 }
527
528 GPUTestExpectationsParser:: GPUTestExpectationEntry::GPUTestExpectationEntry()
529 : test_expectation(0),
530 line_number(0) {
531 }
532
OLDNEW
« no previous file with comments | « content/test/gpu/gpu_test_expectations_parser.h ('k') | content/test/gpu/gpu_test_expectations_parser_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698