blob: d44e5bb29846adb915f6104d7b497c6156317fa1 [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
190 std::vector<std::string> lines;
191 base::SplitString(data, '\n', &lines);
192 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);
237 std::vector<std::string> tokens;
238 base::SplitStringAlongWhitespace(config_data, &tokens);
239
240 for (size_t i = 0; i < tokens.size(); ++i) {
241 Token token = ParseToken(tokens[i]);
242 switch (token) {
243 case kConfigWinXP:
244 case kConfigWinVista:
245 case kConfigWin7:
[email protected]c9fc22f2012-11-16 23:39:56246 case kConfigWin8:
wfh0355eead2015-07-22 04:15:00247 case kConfigWin10:
[email protected]830631c2012-06-13 05:06:08248 case kConfigWin:
249 case kConfigMacLeopard:
250 case kConfigMacSnowLeopard:
251 case kConfigMacLion:
[email protected]c9fc22f2012-11-16 23:39:56252 case kConfigMacMountainLion:
[email protected]710089b92014-02-04 01:16:09253 case kConfigMacMavericks:
iceman3197ce82015-04-15 11:02:32254 case kConfigMacYosemite:
[email protected]830631c2012-06-13 05:06:08255 case kConfigMac:
256 case kConfigLinux:
257 case kConfigChromeOS:
[email protected]61d7e5e2012-07-27 04:08:57258 case kConfigAndroid:
[email protected]830631c2012-06-13 05:06:08259 case kConfigNVidia:
260 case kConfigAMD:
261 case kConfigIntel:
262 case kConfigVMWare:
263 case kConfigRelease:
264 case kConfigDebug:
jmadill073a3232015-07-22 21:10:52265 case kConfigD3D9:
266 case kConfigD3D11:
267 case kConfigGLDesktop:
268 case kConfigGLES:
[email protected]830631c2012-06-13 05:06:08269 case kConfigGPUDeviceID:
270 if (token == kConfigGPUDeviceID) {
271 if (!UpdateTestConfig(config, tokens[i], 0))
272 return false;
273 } else {
274 if (!UpdateTestConfig(config, token, 0))
275 return false;
276 }
277 break;
278 default:
279 return false;
280 }
281 }
282 return true;
283}
284
[email protected]db78bca52012-01-27 01:53:58285bool GPUTestExpectationsParser::ParseLine(
286 const std::string& line_data, size_t line_number) {
287 std::vector<std::string> tokens;
288 base::SplitStringAlongWhitespace(line_data, &tokens);
289 int32 stage = kLineParserBegin;
290 GPUTestExpectationEntry entry;
291 entry.line_number = line_number;
292 GPUTestConfig& config = entry.test_config;
293 bool comments_encountered = false;
294 for (size_t i = 0; i < tokens.size() && !comments_encountered; ++i) {
295 Token token = ParseToken(tokens[i]);
296 switch (token) {
297 case kTokenComment:
298 comments_encountered = true;
299 break;
300 case kConfigWinXP:
301 case kConfigWinVista:
302 case kConfigWin7:
[email protected]c9fc22f2012-11-16 23:39:56303 case kConfigWin8:
wfh0355eead2015-07-22 04:15:00304 case kConfigWin10:
[email protected]db78bca52012-01-27 01:53:58305 case kConfigWin:
306 case kConfigMacLeopard:
307 case kConfigMacSnowLeopard:
308 case kConfigMacLion:
[email protected]c9fc22f2012-11-16 23:39:56309 case kConfigMacMountainLion:
[email protected]710089b92014-02-04 01:16:09310 case kConfigMacMavericks:
iceman3197ce82015-04-15 11:02:32311 case kConfigMacYosemite:
[email protected]db78bca52012-01-27 01:53:58312 case kConfigMac:
313 case kConfigLinux:
314 case kConfigChromeOS:
[email protected]61d7e5e2012-07-27 04:08:57315 case kConfigAndroid:
[email protected]db78bca52012-01-27 01:53:58316 case kConfigNVidia:
317 case kConfigAMD:
318 case kConfigIntel:
[email protected]830631c2012-06-13 05:06:08319 case kConfigVMWare:
[email protected]db78bca52012-01-27 01:53:58320 case kConfigRelease:
321 case kConfigDebug:
jmadill073a3232015-07-22 21:10:52322 case kConfigD3D9:
323 case kConfigD3D11:
324 case kConfigGLDesktop:
325 case kConfigGLES:
[email protected]db78bca52012-01-27 01:53:58326 case kConfigGPUDeviceID:
327 // MODIFIERS, could be in any order, need at least one.
328 if (stage != kLineParserConfigs && stage != kLineParserBugID) {
329 PushErrorMessage(kErrorMessage[kErrorIllegalEntry],
330 line_number);
331 return false;
332 }
333 if (token == kConfigGPUDeviceID) {
334 if (!UpdateTestConfig(&config, tokens[i], line_number))
335 return false;
336 } else {
337 if (!UpdateTestConfig(&config, token, line_number))
338 return false;
339 }
340 if (stage == kLineParserBugID)
341 stage++;
342 break;
343 case kSeparatorColon:
344 // :
345 if (stage != kLineParserConfigs) {
346 PushErrorMessage(kErrorMessage[kErrorIllegalEntry],
347 line_number);
348 return false;
349 }
350 stage++;
351 break;
352 case kSeparatorEqual:
353 // =
354 if (stage != kLineParserTestName) {
355 PushErrorMessage(kErrorMessage[kErrorIllegalEntry],
356 line_number);
357 return false;
358 }
359 stage++;
360 break;
361 case kTokenWord:
362 // BUG_ID or TEST_NAME
363 if (stage == kLineParserBegin) {
364 // Bug ID is not used for anything; ignore it.
365 } else if (stage == kLineParserColon) {
366 entry.test_name = tokens[i];
367 } else {
368 PushErrorMessage(kErrorMessage[kErrorIllegalEntry],
369 line_number);
370 return false;
371 }
372 stage++;
373 break;
374 case kExpectationPass:
375 case kExpectationFail:
376 case kExpectationFlaky:
377 case kExpectationTimeout:
[email protected]55ab0192012-05-11 20:12:37378 case kExpectationSkip:
[email protected]db78bca52012-01-27 01:53:58379 // TEST_EXPECTATIONS
380 if (stage != kLineParserEqual && stage != kLineParserExpectations) {
381 PushErrorMessage(kErrorMessage[kErrorIllegalEntry],
382 line_number);
383 return false;
384 }
385 if ((kTokenData[token].flag & entry.test_expectation) != 0) {
386 PushErrorMessage(kErrorMessage[kErrorEntryWithExpectationConflicts],
387 line_number);
388 return false;
389 }
390 entry.test_expectation =
391 (kTokenData[token].flag | entry.test_expectation);
392 if (stage == kLineParserEqual)
393 stage++;
394 break;
395 default:
396 DCHECK(false);
397 break;
398 }
399 }
400 if (stage == kLineParserBegin) {
401 // The whole line is empty or all comments
402 return true;
403 }
404 if (stage == kLineParserExpectations) {
405 if (!config.IsValid()) {
406 PushErrorMessage(kErrorMessage[kErrorInvalidEntry], line_number);
407 return false;
408 }
409 entries_.push_back(entry);
410 return true;
411 }
412 PushErrorMessage(kErrorMessage[kErrorIllegalEntry], line_number);
413 return false;
414}
415
416bool GPUTestExpectationsParser::UpdateTestConfig(
417 GPUTestConfig* config, int32 token, size_t line_number) {
418 DCHECK(config);
419 switch (token) {
420 case kConfigWinXP:
421 case kConfigWinVista:
422 case kConfigWin7:
[email protected]c9fc22f2012-11-16 23:39:56423 case kConfigWin8:
wfh0355eead2015-07-22 04:15:00424 case kConfigWin10:
[email protected]db78bca52012-01-27 01:53:58425 case kConfigWin:
426 case kConfigMacLeopard:
427 case kConfigMacSnowLeopard:
428 case kConfigMacLion:
[email protected]c9fc22f2012-11-16 23:39:56429 case kConfigMacMountainLion:
[email protected]710089b92014-02-04 01:16:09430 case kConfigMacMavericks:
iceman3197ce82015-04-15 11:02:32431 case kConfigMacYosemite:
[email protected]db78bca52012-01-27 01:53:58432 case kConfigMac:
433 case kConfigLinux:
434 case kConfigChromeOS:
[email protected]61d7e5e2012-07-27 04:08:57435 case kConfigAndroid:
[email protected]db78bca52012-01-27 01:53:58436 if ((config->os() & kTokenData[token].flag) != 0) {
437 PushErrorMessage(kErrorMessage[kErrorEntryWithOsConflicts],
438 line_number);
439 return false;
440 }
441 config->set_os(config->os() | kTokenData[token].flag);
442 break;
443 case kConfigNVidia:
444 case kConfigAMD:
445 case kConfigIntel:
[email protected]830631c2012-06-13 05:06:08446 case kConfigVMWare:
[email protected]db78bca52012-01-27 01:53:58447 {
448 uint32 gpu_vendor =
449 static_cast<uint32>(kTokenData[token].flag);
450 for (size_t i = 0; i < config->gpu_vendor().size(); ++i) {
451 if (config->gpu_vendor()[i] == gpu_vendor) {
452 PushErrorMessage(
453 kErrorMessage[kErrorEntryWithGpuVendorConflicts],
454 line_number);
455 return false;
456 }
457 }
458 config->AddGPUVendor(gpu_vendor);
459 }
460 break;
461 case kConfigRelease:
462 case kConfigDebug:
463 if ((config->build_type() & kTokenData[token].flag) != 0) {
464 PushErrorMessage(
465 kErrorMessage[kErrorEntryWithBuildTypeConflicts],
466 line_number);
467 return false;
468 }
469 config->set_build_type(
470 config->build_type() | kTokenData[token].flag);
471 break;
jmadill073a3232015-07-22 21:10:52472 case kConfigD3D9:
473 case kConfigD3D11:
474 case kConfigGLDesktop:
475 case kConfigGLES:
476 if ((config->api() & kTokenData[token].flag) != 0) {
477 PushErrorMessage(kErrorMessage[kErrorEntryWithAPIConflicts],
478 line_number);
479 return false;
480 }
481 config->set_api(config->api() | kTokenData[token].flag);
482 break;
[email protected]db78bca52012-01-27 01:53:58483 default:
484 DCHECK(false);
485 break;
486 }
487 return true;
488}
489
490bool GPUTestExpectationsParser::UpdateTestConfig(
491 GPUTestConfig* config,
492 const std::string& gpu_device_id,
493 size_t line_number) {
494 DCHECK(config);
495 uint32 device_id = 0;
496 if (config->gpu_device_id() != 0 ||
[email protected]3fb01692013-10-23 13:37:04497 !base::HexStringToUInt(gpu_device_id, &device_id) ||
[email protected]db78bca52012-01-27 01:53:58498 device_id == 0) {
499 PushErrorMessage(kErrorMessage[kErrorEntryWithGpuDeviceIdConflicts],
500 line_number);
501 return false;
502 }
503 config->set_gpu_device_id(device_id);
504 return true;
505}
506
507bool GPUTestExpectationsParser::DetectConflictsBetweenEntries() {
508 bool rt = false;
509 for (size_t i = 0; i < entries_.size(); ++i) {
510 for (size_t j = i + 1; j < entries_.size(); ++j) {
511 if (entries_[i].test_name == entries_[j].test_name &&
512 entries_[i].test_config.OverlapsWith(entries_[j].test_config)) {
513 PushErrorMessage(kErrorMessage[kErrorEntriesOverlap],
514 entries_[i].line_number,
515 entries_[j].line_number);
516 rt = true;
517 }
518 }
519 }
520 return rt;
521}
522
523void GPUTestExpectationsParser::PushErrorMessage(
524 const std::string& message, size_t line_number) {
525 error_messages_.push_back(
526 base::StringPrintf("Line %d : %s",
527 static_cast<int>(line_number), message.c_str()));
528}
529
530void GPUTestExpectationsParser::PushErrorMessage(
531 const std::string& message,
532 size_t entry1_line_number,
533 size_t entry2_line_number) {
534 error_messages_.push_back(
535 base::StringPrintf("Line %d and %d : %s",
536 static_cast<int>(entry1_line_number),
537 static_cast<int>(entry2_line_number),
538 message.c_str()));
539}
540
[email protected]db78bca52012-01-27 01:53:58541GPUTestExpectationsParser:: GPUTestExpectationEntry::GPUTestExpectationEntry()
542 : test_expectation(0),
543 line_number(0) {
544}
545
[email protected]129f019e2013-05-28 23:38:02546} // namespace gpu
547