Revert "Reland c91b178b07b0d - Delete dead signin code (SigninGlobalError)"
[chromium-blink-merge.git] / gpu / config / gpu_test_expectations_parser.cc
blob27a1487b937bbde5f84d2a84ca18aea8dd04439e
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.
5 #include "gpu/config/gpu_test_expectations_parser.h"
7 #include "base/files/file_util.h"
8 #include "base/logging.h"
9 #include "base/strings/string_number_conversions.h"
10 #include "base/strings/string_split.h"
11 #include "base/strings/string_util.h"
12 #include "base/strings/stringprintf.h"
14 namespace gpu {
16 namespace {
18 enum LineParserStage {
19 kLineParserBegin = 0,
20 kLineParserBugID,
21 kLineParserConfigs,
22 kLineParserColon,
23 kLineParserTestName,
24 kLineParserEqual,
25 kLineParserExpectations,
28 enum Token {
29 // os
30 kConfigWinXP = 0,
31 kConfigWinVista,
32 kConfigWin7,
33 kConfigWin8,
34 kConfigWin10,
35 kConfigWin,
36 kConfigMacLeopard,
37 kConfigMacSnowLeopard,
38 kConfigMacLion,
39 kConfigMacMountainLion,
40 kConfigMacMavericks,
41 kConfigMacYosemite,
42 kConfigMac,
43 kConfigLinux,
44 kConfigChromeOS,
45 kConfigAndroid,
46 // gpu vendor
47 kConfigNVidia,
48 kConfigAMD,
49 kConfigIntel,
50 kConfigVMWare,
51 // build type
52 kConfigRelease,
53 kConfigDebug,
54 // ANGLE renderer
55 kConfigD3D9,
56 kConfigD3D11,
57 kConfigGLDesktop,
58 kConfigGLES,
59 // expectation
60 kExpectationPass,
61 kExpectationFail,
62 kExpectationFlaky,
63 kExpectationTimeout,
64 kExpectationSkip,
65 // separator
66 kSeparatorColon,
67 kSeparatorEqual,
69 kNumberOfExactMatchTokens,
71 // others
72 kConfigGPUDeviceID,
73 kTokenComment,
74 kTokenWord,
77 struct TokenInfo {
78 const char* name;
79 int32 flag;
82 const TokenInfo kTokenData[] = {
83 {"xp", GPUTestConfig::kOsWinXP},
84 {"vista", GPUTestConfig::kOsWinVista},
85 {"win7", GPUTestConfig::kOsWin7},
86 {"win8", GPUTestConfig::kOsWin8},
87 {"win10", GPUTestConfig::kOsWin10},
88 {"win", GPUTestConfig::kOsWin},
89 {"leopard", GPUTestConfig::kOsMacLeopard},
90 {"snowleopard", GPUTestConfig::kOsMacSnowLeopard},
91 {"lion", GPUTestConfig::kOsMacLion},
92 {"mountainlion", GPUTestConfig::kOsMacMountainLion},
93 {"mavericks", GPUTestConfig::kOsMacMavericks},
94 {"yosemite", GPUTestConfig::kOsMacYosemite},
95 {"mac", GPUTestConfig::kOsMac},
96 {"linux", GPUTestConfig::kOsLinux},
97 {"chromeos", GPUTestConfig::kOsChromeOS},
98 {"android", GPUTestConfig::kOsAndroid},
99 {"nvidia", 0x10DE},
100 {"amd", 0x1002},
101 {"intel", 0x8086},
102 {"vmware", 0x15ad},
103 {"release", GPUTestConfig::kBuildTypeRelease},
104 {"debug", GPUTestConfig::kBuildTypeDebug},
105 {"d3d9", GPUTestConfig::kAPID3D9},
106 {"d3d11", GPUTestConfig::kAPID3D11},
107 {"opengl", GPUTestConfig::kAPIGLDesktop},
108 {"gles", GPUTestConfig::kAPIGLES},
109 {"pass", GPUTestExpectationsParser::kGpuTestPass},
110 {"fail", GPUTestExpectationsParser::kGpuTestFail},
111 {"flaky", GPUTestExpectationsParser::kGpuTestFlaky},
112 {"timeout", GPUTestExpectationsParser::kGpuTestTimeout},
113 {"skip", GPUTestExpectationsParser::kGpuTestSkip},
114 {":", 0},
115 {"=", 0},
118 enum ErrorType {
119 kErrorFileIO = 0,
120 kErrorIllegalEntry,
121 kErrorInvalidEntry,
122 kErrorEntryWithOsConflicts,
123 kErrorEntryWithGpuVendorConflicts,
124 kErrorEntryWithBuildTypeConflicts,
125 kErrorEntryWithAPIConflicts,
126 kErrorEntryWithGpuDeviceIdConflicts,
127 kErrorEntryWithExpectationConflicts,
128 kErrorEntriesOverlap,
130 kNumberOfErrors,
133 const char* kErrorMessage[] = {
134 "file IO failed",
135 "entry with wrong format",
136 "entry invalid, likely wrong modifiers combination",
137 "entry with OS modifier conflicts",
138 "entry with GPU vendor modifier conflicts",
139 "entry with GPU build type conflicts",
140 "entry with GPU API conflicts",
141 "entry with GPU device id conflicts or malformat",
142 "entry with expectation modifier conflicts",
143 "two entries' configs overlap",
146 Token ParseToken(const std::string& word) {
147 if (base::StartsWith(word, "//", base::CompareCase::INSENSITIVE_ASCII))
148 return kTokenComment;
149 if (base::StartsWith(word, "0x", base::CompareCase::INSENSITIVE_ASCII))
150 return kConfigGPUDeviceID;
152 for (int32 i = 0; i < kNumberOfExactMatchTokens; ++i) {
153 if (base::LowerCaseEqualsASCII(word, kTokenData[i].name))
154 return static_cast<Token>(i);
156 return kTokenWord;
159 // reference name can have the last character as *.
160 bool NamesMatching(const std::string& ref, const std::string& test_name) {
161 size_t len = ref.length();
162 if (len == 0)
163 return false;
164 if (ref[len - 1] == '*') {
165 if (test_name.length() > len -1 &&
166 ref.compare(0, len - 1, test_name, 0, len - 1) == 0)
167 return true;
168 return false;
170 return (ref == test_name);
173 } // namespace anonymous
175 GPUTestExpectationsParser::GPUTestExpectationsParser() {
176 // Some sanity check.
177 DCHECK_EQ(static_cast<unsigned int>(kNumberOfExactMatchTokens),
178 sizeof(kTokenData) / sizeof(kTokenData[0]));
179 DCHECK_EQ(static_cast<unsigned int>(kNumberOfErrors),
180 sizeof(kErrorMessage) / sizeof(kErrorMessage[0]));
183 GPUTestExpectationsParser::~GPUTestExpectationsParser() {
186 bool GPUTestExpectationsParser::LoadTestExpectations(const std::string& data) {
187 entries_.clear();
188 error_messages_.clear();
190 std::vector<std::string> lines = base::SplitString(
191 data, "\n", base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL);
192 bool rt = true;
193 for (size_t i = 0; i < lines.size(); ++i) {
194 if (!ParseLine(lines[i], i + 1))
195 rt = false;
197 if (DetectConflictsBetweenEntries()) {
198 entries_.clear();
199 rt = false;
202 return rt;
205 bool GPUTestExpectationsParser::LoadTestExpectations(
206 const base::FilePath& path) {
207 entries_.clear();
208 error_messages_.clear();
210 std::string data;
211 if (!base::ReadFileToString(path, &data)) {
212 error_messages_.push_back(kErrorMessage[kErrorFileIO]);
213 return false;
215 return LoadTestExpectations(data);
218 int32 GPUTestExpectationsParser::GetTestExpectation(
219 const std::string& test_name,
220 const GPUTestBotConfig& bot_config) const {
221 for (size_t i = 0; i < entries_.size(); ++i) {
222 if (NamesMatching(entries_[i].test_name, test_name) &&
223 bot_config.Matches(entries_[i].test_config))
224 return entries_[i].test_expectation;
226 return kGpuTestPass;
229 const std::vector<std::string>&
230 GPUTestExpectationsParser::GetErrorMessages() const {
231 return error_messages_;
234 bool GPUTestExpectationsParser::ParseConfig(
235 const std::string& config_data, GPUTestConfig* config) {
236 DCHECK(config);
237 std::vector<std::string> tokens = base::SplitString(
238 config_data, base::kWhitespaceASCII, base::KEEP_WHITESPACE,
239 base::SPLIT_WANT_NONEMPTY);
241 for (size_t i = 0; i < tokens.size(); ++i) {
242 Token token = ParseToken(tokens[i]);
243 switch (token) {
244 case kConfigWinXP:
245 case kConfigWinVista:
246 case kConfigWin7:
247 case kConfigWin8:
248 case kConfigWin10:
249 case kConfigWin:
250 case kConfigMacLeopard:
251 case kConfigMacSnowLeopard:
252 case kConfigMacLion:
253 case kConfigMacMountainLion:
254 case kConfigMacMavericks:
255 case kConfigMacYosemite:
256 case kConfigMac:
257 case kConfigLinux:
258 case kConfigChromeOS:
259 case kConfigAndroid:
260 case kConfigNVidia:
261 case kConfigAMD:
262 case kConfigIntel:
263 case kConfigVMWare:
264 case kConfigRelease:
265 case kConfigDebug:
266 case kConfigD3D9:
267 case kConfigD3D11:
268 case kConfigGLDesktop:
269 case kConfigGLES:
270 case kConfigGPUDeviceID:
271 if (token == kConfigGPUDeviceID) {
272 if (!UpdateTestConfig(config, tokens[i], 0))
273 return false;
274 } else {
275 if (!UpdateTestConfig(config, token, 0))
276 return false;
278 break;
279 default:
280 return false;
283 return true;
286 bool GPUTestExpectationsParser::ParseLine(
287 const std::string& line_data, size_t line_number) {
288 std::vector<std::string> tokens = base::SplitString(
289 line_data, base::kWhitespaceASCII, base::KEEP_WHITESPACE,
290 base::SPLIT_WANT_NONEMPTY);
291 int32 stage = kLineParserBegin;
292 GPUTestExpectationEntry entry;
293 entry.line_number = line_number;
294 GPUTestConfig& config = entry.test_config;
295 bool comments_encountered = false;
296 for (size_t i = 0; i < tokens.size() && !comments_encountered; ++i) {
297 Token token = ParseToken(tokens[i]);
298 switch (token) {
299 case kTokenComment:
300 comments_encountered = true;
301 break;
302 case kConfigWinXP:
303 case kConfigWinVista:
304 case kConfigWin7:
305 case kConfigWin8:
306 case kConfigWin10:
307 case kConfigWin:
308 case kConfigMacLeopard:
309 case kConfigMacSnowLeopard:
310 case kConfigMacLion:
311 case kConfigMacMountainLion:
312 case kConfigMacMavericks:
313 case kConfigMacYosemite:
314 case kConfigMac:
315 case kConfigLinux:
316 case kConfigChromeOS:
317 case kConfigAndroid:
318 case kConfigNVidia:
319 case kConfigAMD:
320 case kConfigIntel:
321 case kConfigVMWare:
322 case kConfigRelease:
323 case kConfigDebug:
324 case kConfigD3D9:
325 case kConfigD3D11:
326 case kConfigGLDesktop:
327 case kConfigGLES:
328 case kConfigGPUDeviceID:
329 // MODIFIERS, could be in any order, need at least one.
330 if (stage != kLineParserConfigs && stage != kLineParserBugID) {
331 PushErrorMessage(kErrorMessage[kErrorIllegalEntry],
332 line_number);
333 return false;
335 if (token == kConfigGPUDeviceID) {
336 if (!UpdateTestConfig(&config, tokens[i], line_number))
337 return false;
338 } else {
339 if (!UpdateTestConfig(&config, token, line_number))
340 return false;
342 if (stage == kLineParserBugID)
343 stage++;
344 break;
345 case kSeparatorColon:
346 // :
347 if (stage != kLineParserConfigs) {
348 PushErrorMessage(kErrorMessage[kErrorIllegalEntry],
349 line_number);
350 return false;
352 stage++;
353 break;
354 case kSeparatorEqual:
355 // =
356 if (stage != kLineParserTestName) {
357 PushErrorMessage(kErrorMessage[kErrorIllegalEntry],
358 line_number);
359 return false;
361 stage++;
362 break;
363 case kTokenWord:
364 // BUG_ID or TEST_NAME
365 if (stage == kLineParserBegin) {
366 // Bug ID is not used for anything; ignore it.
367 } else if (stage == kLineParserColon) {
368 entry.test_name = tokens[i];
369 } else {
370 PushErrorMessage(kErrorMessage[kErrorIllegalEntry],
371 line_number);
372 return false;
374 stage++;
375 break;
376 case kExpectationPass:
377 case kExpectationFail:
378 case kExpectationFlaky:
379 case kExpectationTimeout:
380 case kExpectationSkip:
381 // TEST_EXPECTATIONS
382 if (stage != kLineParserEqual && stage != kLineParserExpectations) {
383 PushErrorMessage(kErrorMessage[kErrorIllegalEntry],
384 line_number);
385 return false;
387 if ((kTokenData[token].flag & entry.test_expectation) != 0) {
388 PushErrorMessage(kErrorMessage[kErrorEntryWithExpectationConflicts],
389 line_number);
390 return false;
392 entry.test_expectation =
393 (kTokenData[token].flag | entry.test_expectation);
394 if (stage == kLineParserEqual)
395 stage++;
396 break;
397 default:
398 DCHECK(false);
399 break;
402 if (stage == kLineParserBegin) {
403 // The whole line is empty or all comments
404 return true;
406 if (stage == kLineParserExpectations) {
407 if (!config.IsValid()) {
408 PushErrorMessage(kErrorMessage[kErrorInvalidEntry], line_number);
409 return false;
411 entries_.push_back(entry);
412 return true;
414 PushErrorMessage(kErrorMessage[kErrorIllegalEntry], line_number);
415 return false;
418 bool GPUTestExpectationsParser::UpdateTestConfig(
419 GPUTestConfig* config, int32 token, size_t line_number) {
420 DCHECK(config);
421 switch (token) {
422 case kConfigWinXP:
423 case kConfigWinVista:
424 case kConfigWin7:
425 case kConfigWin8:
426 case kConfigWin10:
427 case kConfigWin:
428 case kConfigMacLeopard:
429 case kConfigMacSnowLeopard:
430 case kConfigMacLion:
431 case kConfigMacMountainLion:
432 case kConfigMacMavericks:
433 case kConfigMacYosemite:
434 case kConfigMac:
435 case kConfigLinux:
436 case kConfigChromeOS:
437 case kConfigAndroid:
438 if ((config->os() & kTokenData[token].flag) != 0) {
439 PushErrorMessage(kErrorMessage[kErrorEntryWithOsConflicts],
440 line_number);
441 return false;
443 config->set_os(config->os() | kTokenData[token].flag);
444 break;
445 case kConfigNVidia:
446 case kConfigAMD:
447 case kConfigIntel:
448 case kConfigVMWare:
450 uint32 gpu_vendor =
451 static_cast<uint32>(kTokenData[token].flag);
452 for (size_t i = 0; i < config->gpu_vendor().size(); ++i) {
453 if (config->gpu_vendor()[i] == gpu_vendor) {
454 PushErrorMessage(
455 kErrorMessage[kErrorEntryWithGpuVendorConflicts],
456 line_number);
457 return false;
460 config->AddGPUVendor(gpu_vendor);
462 break;
463 case kConfigRelease:
464 case kConfigDebug:
465 if ((config->build_type() & kTokenData[token].flag) != 0) {
466 PushErrorMessage(
467 kErrorMessage[kErrorEntryWithBuildTypeConflicts],
468 line_number);
469 return false;
471 config->set_build_type(
472 config->build_type() | kTokenData[token].flag);
473 break;
474 case kConfigD3D9:
475 case kConfigD3D11:
476 case kConfigGLDesktop:
477 case kConfigGLES:
478 if ((config->api() & kTokenData[token].flag) != 0) {
479 PushErrorMessage(kErrorMessage[kErrorEntryWithAPIConflicts],
480 line_number);
481 return false;
483 config->set_api(config->api() | kTokenData[token].flag);
484 break;
485 default:
486 DCHECK(false);
487 break;
489 return true;
492 bool GPUTestExpectationsParser::UpdateTestConfig(
493 GPUTestConfig* config,
494 const std::string& gpu_device_id,
495 size_t line_number) {
496 DCHECK(config);
497 uint32 device_id = 0;
498 if (config->gpu_device_id() != 0 ||
499 !base::HexStringToUInt(gpu_device_id, &device_id) ||
500 device_id == 0) {
501 PushErrorMessage(kErrorMessage[kErrorEntryWithGpuDeviceIdConflicts],
502 line_number);
503 return false;
505 config->set_gpu_device_id(device_id);
506 return true;
509 bool GPUTestExpectationsParser::DetectConflictsBetweenEntries() {
510 bool rt = false;
511 for (size_t i = 0; i < entries_.size(); ++i) {
512 for (size_t j = i + 1; j < entries_.size(); ++j) {
513 if (entries_[i].test_name == entries_[j].test_name &&
514 entries_[i].test_config.OverlapsWith(entries_[j].test_config)) {
515 PushErrorMessage(kErrorMessage[kErrorEntriesOverlap],
516 entries_[i].line_number,
517 entries_[j].line_number);
518 rt = true;
522 return rt;
525 void GPUTestExpectationsParser::PushErrorMessage(
526 const std::string& message, size_t line_number) {
527 error_messages_.push_back(
528 base::StringPrintf("Line %d : %s",
529 static_cast<int>(line_number), message.c_str()));
532 void GPUTestExpectationsParser::PushErrorMessage(
533 const std::string& message,
534 size_t entry1_line_number,
535 size_t entry2_line_number) {
536 error_messages_.push_back(
537 base::StringPrintf("Line %d and %d : %s",
538 static_cast<int>(entry1_line_number),
539 static_cast<int>(entry2_line_number),
540 message.c_str()));
543 GPUTestExpectationsParser:: GPUTestExpectationEntry::GPUTestExpectationEntry()
544 : test_expectation(0),
545 line_number(0) {
548 } // namespace gpu