blob: 27a1487b937bbde5f84d2a84ca18aea8dd04439e [file] [log] [blame]
[email protected]db78bca52012-01-27 01:53:581// 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
[email protected]129f019e2013-05-28 23:38:025#include "gpu/config/gpu_test_expectations_parser.h"
[email protected]db78bca52012-01-27 01:53:586
thestigc9e38a22014-09-13 01:02:117#include "base/files/file_util.h"
[email protected]db78bca52012-01-27 01:53:588#include "base/logging.h"
[email protected]f4390962013-06-11 07:29:229#include "base/strings/string_number_conversions.h"
[email protected]27c05732013-02-15 21:55:4910#include "base/strings/string_split.h"
[email protected]f4390962013-06-11 07:29:2211#include "base/strings/string_util.h"
12#include "base/strings/stringprintf.h"
[email protected]129f019e2013-05-28 23:38:0213
14namespace gpu {
[email protected]db78bca52012-01-27 01:53:5815
16namespace {
17
18enum LineParserStage {
19 kLineParserBegin = 0,
20 kLineParserBugID,
21 kLineParserConfigs,
22 kLineParserColon,
23 kLineParserTestName,
24 kLineParserEqual,
25 kLineParserExpectations,
26};
27
28enum Token {
29 // os
30 kConfigWinXP = 0,
31 kConfigWinVista,
32 kConfigWin7,
[email protected]c9fc22f2012-11-16 23:39:5633 kConfigWin8,
wfh0355eead2015-07-22 04:15:0034 kConfigWin10,
[email protected]db78bca52012-01-27 01:53:5835 kConfigWin,
36 kConfigMacLeopard,
37 kConfigMacSnowLeopard,
38 kConfigMacLion,
[email protected]c9fc22f2012-11-16 23:39:5639 kConfigMacMountainLion,
[email protected]710089b92014-02-04 01:16:0940 kConfigMacMavericks,
iceman3197ce82015-04-15 11:02:3241 kConfigMacYosemite,
[email protected]db78bca52012-01-27 01:53:5842 kConfigMac,
43 kConfigLinux,
44 kConfigChromeOS,
[email protected]61d7e5e2012-07-27 04:08:5745 kConfigAndroid,
[email protected]db78bca52012-01-27 01:53:5846 // gpu vendor
47 kConfigNVidia,
48 kConfigAMD,
49 kConfigIntel,
[email protected]830631c2012-06-13 05:06:0850 kConfigVMWare,
[email protected]db78bca52012-01-27 01:53:5851 // build type
52 kConfigRelease,
53 kConfigDebug,
jmadill073a3232015-07-22 21:10:5254 // ANGLE renderer
55 kConfigD3D9,
56 kConfigD3D11,
57 kConfigGLDesktop,
58 kConfigGLES,
[email protected]db78bca52012-01-27 01:53:5859 // expectation
60 kExpectationPass,
61 kExpectationFail,
62 kExpectationFlaky,
63 kExpectationTimeout,
[email protected]55ab0192012-05-11 20:12:3764 kExpectationSkip,
[email protected]db78bca52012-01-27 01:53:5865 // separator
66 kSeparatorColon,
67 kSeparatorEqual,
68
69 kNumberOfExactMatchTokens,
70
71 // others
72 kConfigGPUDeviceID,
73 kTokenComment,
74 kTokenWord,
75};
76
77struct TokenInfo {
78 const char* name;
79 int32 flag;
80};
81
82const TokenInfo kTokenData[] = {
jmadill073a3232015-07-22 21:10:5283 {"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},
[email protected]db78bca52012-01-27 01:53:58116};
117
118enum ErrorType {
119 kErrorFileIO = 0,
120 kErrorIllegalEntry,
121 kErrorInvalidEntry,
122 kErrorEntryWithOsConflicts,
123 kErrorEntryWithGpuVendorConflicts,
124 kErrorEntryWithBuildTypeConflicts,
jmadill073a3232015-07-22 21:10:52125 kErrorEntryWithAPIConflicts,
[email protected]db78bca52012-01-27 01:53:58126 kErrorEntryWithGpuDeviceIdConflicts,
127 kErrorEntryWithExpectationConflicts,
128 kErrorEntriesOverlap,
129
130 kNumberOfErrors,
131};
132
133const char* kErrorMessage[] = {
jmadill073a3232015-07-22 21:10:52134 "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",
[email protected]db78bca52012-01-27 01:53:58144};
145
146Token ParseToken(const std::string& word) {
brettw95509312015-07-16 23:57:33147 if (base::StartsWith(word, "//", base::CompareCase::INSENSITIVE_ASCII))
[email protected]db78bca52012-01-27 01:53:58148 return kTokenComment;
brettw95509312015-07-16 23:57:33149 if (base::StartsWith(word, "0x", base::CompareCase::INSENSITIVE_ASCII))
[email protected]db78bca52012-01-27 01:53:58150 return kConfigGPUDeviceID;
151
152 for (int32 i = 0; i < kNumberOfExactMatchTokens; ++i) {
brettwbc17d2c82015-06-09 22:39:08153 if (base::LowerCaseEqualsASCII(word, kTokenData[i].name))
[email protected]db78bca52012-01-27 01:53:58154 return static_cast<Token>(i);
155 }
156 return kTokenWord;
157}
158
[email protected]55ab0192012-05-11 20:12:37159// reference name can have the last character as *.
160bool 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;
169 }
170 return (ref == test_name);
171}
172
[email protected]db78bca52012-01-27 01:53:58173} // namespace anonymous
174
175GPUTestExpectationsParser::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]));
181}
182
183GPUTestExpectationsParser::~GPUTestExpectationsParser() {
184}
185
186bool GPUTestExpectationsParser::LoadTestExpectations(const std::string& data) {
187 entries_.clear();
188 error_messages_.clear();
189
brettw26dab8f02015-08-08 00:28:47190 std::vector<std::string> lines = base::SplitString(
191 data, "\n", base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL);
[email protected]db78bca52012-01-27 01:53:58192 bool rt = true;
193 for (size_t i = 0; i < lines.size(); ++i) {
194 if (!ParseLine(lines[i], i + 1))
195 rt = false;
196 }
197 if (DetectConflictsBetweenEntries()) {
198 entries_.clear();
199 rt = false;
200 }
201
202 return rt;
203}
204
[email protected]d30a36f2013-02-07 04:16:26205bool GPUTestExpectationsParser::LoadTestExpectations(
206 const base::FilePath& path) {
[email protected]db78bca52012-01-27 01:53:58207 entries_.clear();
208 error_messages_.clear();
209
210 std::string data;
[email protected]82f84b92013-08-30 18:23:50211 if (!base::ReadFileToString(path, &data)) {
[email protected]db78bca52012-01-27 01:53:58212 error_messages_.push_back(kErrorMessage[kErrorFileIO]);
213 return false;
214 }
215 return LoadTestExpectations(data);
216}
217
218int32 GPUTestExpectationsParser::GetTestExpectation(
219 const std::string& test_name,
220 const GPUTestBotConfig& bot_config) const {
221 for (size_t i = 0; i < entries_.size(); ++i) {
[email protected]55ab0192012-05-11 20:12:37222 if (NamesMatching(entries_[i].test_name, test_name) &&
[email protected]db78bca52012-01-27 01:53:58223 bot_config.Matches(entries_[i].test_config))
224 return entries_[i].test_expectation;
225 }
226 return kGpuTestPass;
227}
228
229const std::vector<std::string>&
230GPUTestExpectationsParser::GetErrorMessages() const {
231 return error_messages_;
232}
233
[email protected]830631c2012-06-13 05:06:08234bool GPUTestExpectationsParser::ParseConfig(
235 const std::string& config_data, GPUTestConfig* config) {
236 DCHECK(config);
brettw26dab8f02015-08-08 00:28:47237 std::vector<std::string> tokens = base::SplitString(
238 config_data, base::kWhitespaceASCII, base::KEEP_WHITESPACE,
239 base::SPLIT_WANT_NONEMPTY);
[email protected]830631c2012-06-13 05:06:08240
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:
[email protected]c9fc22f2012-11-16 23:39:56247 case kConfigWin8:
wfh0355eead2015-07-22 04:15:00248 case kConfigWin10:
[email protected]830631c2012-06-13 05:06:08249 case kConfigWin:
250 case kConfigMacLeopard:
251 case kConfigMacSnowLeopard:
252 case kConfigMacLion:
[email protected]c9fc22f2012-11-16 23:39:56253 case kConfigMacMountainLion:
[email protected]710089b92014-02-04 01:16:09254 case kConfigMacMavericks:
iceman3197ce82015-04-15 11:02:32255 case kConfigMacYosemite:
[email protected]830631c2012-06-13 05:06:08256 case kConfigMac:
257 case kConfigLinux:
258 case kConfigChromeOS:
[email protected]61d7e5e2012-07-27 04:08:57259 case kConfigAndroid:
[email protected]830631c2012-06-13 05:06:08260 case kConfigNVidia:
261 case kConfigAMD:
262 case kConfigIntel:
263 case kConfigVMWare:
264 case kConfigRelease:
265 case kConfigDebug:
jmadill073a3232015-07-22 21:10:52266 case kConfigD3D9:
267 case kConfigD3D11:
268 case kConfigGLDesktop:
269 case kConfigGLES:
[email protected]830631c2012-06-13 05:06:08270 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;
277 }
278 break;
279 default:
280 return false;
281 }
282 }
283 return true;
284}
285
[email protected]db78bca52012-01-27 01:53:58286bool GPUTestExpectationsParser::ParseLine(
287 const std::string& line_data, size_t line_number) {
brettw26dab8f02015-08-08 00:28:47288 std::vector<std::string> tokens = base::SplitString(
289 line_data, base::kWhitespaceASCII, base::KEEP_WHITESPACE,
290 base::SPLIT_WANT_NONEMPTY);
[email protected]db78bca52012-01-27 01:53:58291 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:
[email protected]c9fc22f2012-11-16 23:39:56305 case kConfigWin8:
wfh0355eead2015-07-22 04:15:00306 case kConfigWin10:
[email protected]db78bca52012-01-27 01:53:58307 case kConfigWin:
308 case kConfigMacLeopard:
309 case kConfigMacSnowLeopard:
310 case kConfigMacLion:
[email protected]c9fc22f2012-11-16 23:39:56311 case kConfigMacMountainLion:
[email protected]710089b92014-02-04 01:16:09312 case kConfigMacMavericks:
iceman3197ce82015-04-15 11:02:32313 case kConfigMacYosemite:
[email protected]db78bca52012-01-27 01:53:58314 case kConfigMac:
315 case kConfigLinux:
316 case kConfigChromeOS:
[email protected]61d7e5e2012-07-27 04:08:57317 case kConfigAndroid:
[email protected]db78bca52012-01-27 01:53:58318 case kConfigNVidia:
319 case kConfigAMD:
320 case kConfigIntel:
[email protected]830631c2012-06-13 05:06:08321 case kConfigVMWare:
[email protected]db78bca52012-01-27 01:53:58322 case kConfigRelease:
323 case kConfigDebug:
jmadill073a3232015-07-22 21:10:52324 case kConfigD3D9:
325 case kConfigD3D11:
326 case kConfigGLDesktop:
327 case kConfigGLES:
[email protected]db78bca52012-01-27 01:53:58328 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;
334 }
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;
341 }
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;
351 }
352 stage++;
353 break;
354 case kSeparatorEqual:
355 // =
356 if (stage != kLineParserTestName) {
357 PushErrorMessage(kErrorMessage[kErrorIllegalEntry],
358 line_number);
359 return false;
360 }
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;
373 }
374 stage++;
375 break;
376 case kExpectationPass:
377 case kExpectationFail:
378 case kExpectationFlaky:
379 case kExpectationTimeout:
[email protected]55ab0192012-05-11 20:12:37380 case kExpectationSkip:
[email protected]db78bca52012-01-27 01:53:58381 // TEST_EXPECTATIONS
382 if (stage != kLineParserEqual && stage != kLineParserExpectations) {
383 PushErrorMessage(kErrorMessage[kErrorIllegalEntry],
384 line_number);
385 return false;
386 }
387 if ((kTokenData[token].flag & entry.test_expectation) != 0) {
388 PushErrorMessage(kErrorMessage[kErrorEntryWithExpectationConflicts],
389 line_number);
390 return false;
391 }
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;
400 }
401 }
402 if (stage == kLineParserBegin) {
403 // The whole line is empty or all comments
404 return true;
405 }
406 if (stage == kLineParserExpectations) {
407 if (!config.IsValid()) {
408 PushErrorMessage(kErrorMessage[kErrorInvalidEntry], line_number);
409 return false;
410 }
411 entries_.push_back(entry);
412 return true;
413 }
414 PushErrorMessage(kErrorMessage[kErrorIllegalEntry], line_number);
415 return false;
416}
417
418bool 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:
[email protected]c9fc22f2012-11-16 23:39:56425 case kConfigWin8:
wfh0355eead2015-07-22 04:15:00426 case kConfigWin10:
[email protected]db78bca52012-01-27 01:53:58427 case kConfigWin:
428 case kConfigMacLeopard:
429 case kConfigMacSnowLeopard:
430 case kConfigMacLion:
[email protected]c9fc22f2012-11-16 23:39:56431 case kConfigMacMountainLion:
[email protected]710089b92014-02-04 01:16:09432 case kConfigMacMavericks:
iceman3197ce82015-04-15 11:02:32433 case kConfigMacYosemite:
[email protected]db78bca52012-01-27 01:53:58434 case kConfigMac:
435 case kConfigLinux:
436 case kConfigChromeOS:
[email protected]61d7e5e2012-07-27 04:08:57437 case kConfigAndroid:
[email protected]db78bca52012-01-27 01:53:58438 if ((config->os() & kTokenData[token].flag) != 0) {
439 PushErrorMessage(kErrorMessage[kErrorEntryWithOsConflicts],
440 line_number);
441 return false;
442 }
443 config->set_os(config->os() | kTokenData[token].flag);
444 break;
445 case kConfigNVidia:
446 case kConfigAMD:
447 case kConfigIntel:
[email protected]830631c2012-06-13 05:06:08448 case kConfigVMWare:
[email protected]db78bca52012-01-27 01:53:58449 {
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;
458 }
459 }
460 config->AddGPUVendor(gpu_vendor);
461 }
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;
470 }
471 config->set_build_type(
472 config->build_type() | kTokenData[token].flag);
473 break;
jmadill073a3232015-07-22 21:10:52474 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;
482 }
483 config->set_api(config->api() | kTokenData[token].flag);
484 break;
[email protected]db78bca52012-01-27 01:53:58485 default:
486 DCHECK(false);
487 break;
488 }
489 return true;
490}
491
492bool 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 ||
[email protected]3fb01692013-10-23 13:37:04499 !base::HexStringToUInt(gpu_device_id, &device_id) ||
[email protected]db78bca52012-01-27 01:53:58500 device_id == 0) {
501 PushErrorMessage(kErrorMessage[kErrorEntryWithGpuDeviceIdConflicts],
502 line_number);
503 return false;
504 }
505 config->set_gpu_device_id(device_id);
506 return true;
507}
508
509bool 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;
519 }
520 }
521 }
522 return rt;
523}
524
525void 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()));
530}
531
532void 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()));
541}
542
[email protected]db78bca52012-01-27 01:53:58543GPUTestExpectationsParser:: GPUTestExpectationEntry::GPUTestExpectationEntry()
544 : test_expectation(0),
545 line_number(0) {
546}
547
[email protected]129f019e2013-05-28 23:38:02548} // namespace gpu
549