summaryrefslogtreecommitdiffstats
path: root/gpu
diff options
context:
space:
mode:
authorzmo@chromium.org <zmo@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-05-28 23:38:02 +0000
committerzmo@chromium.org <zmo@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-05-28 23:38:02 +0000
commit129f019eaa2016c4a7cf3fffd486d76baf22369c (patch)
tree779588af03563c46f69dd98bd4afb26887f16cb2 /gpu
parent8623d0c2c5c9929ce0b1f27ea3915dc5d14eac8c (diff)
downloadchromium_src-129f019eaa2016c4a7cf3fffd486d76baf22369c.zip
chromium_src-129f019eaa2016c4a7cf3fffd486d76baf22369c.tar.gz
chromium_src-129f019eaa2016c4a7cf3fffd486d76baf22369c.tar.bz2
Move gpu_test_config stuff from content/ to gpu/
Again, these code is not depending on any content stuff, so moving it to gpu/ side will allow us to disable more gpu tests per GPU. BUG=230477 TEST=gpu_unittests,tree TBR=kbr@chromium.org, piman@chromium.org Review URL: https://codereview.chromium.org/15827008 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@202690 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'gpu')
-rw-r--r--gpu/config/gpu_test_config.cc272
-rw-r--r--gpu/config/gpu_test_config.h124
-rw-r--r--gpu/config/gpu_test_config_unittest.cc255
-rw-r--r--gpu/config/gpu_test_expectations_parser.cc503
-rw-r--r--gpu/config/gpu_test_expectations_parser.h88
-rw-r--r--gpu/config/gpu_test_expectations_parser_unittest.cc245
-rw-r--r--gpu/gpu.gyp2
-rw-r--r--gpu/gpu_config.gypi4
8 files changed, 1493 insertions, 0 deletions
diff --git a/gpu/config/gpu_test_config.cc b/gpu/config/gpu_test_config.cc
new file mode 100644
index 0000000..ffb6e5f
--- /dev/null
+++ b/gpu/config/gpu_test_config.cc
@@ -0,0 +1,272 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "gpu/config/gpu_test_config.h"
+
+#include "base/logging.h"
+#include "base/sys_info.h"
+#include "gpu/config/gpu_info.h"
+#include "gpu/config/gpu_info_collector.h"
+#include "gpu/config/gpu_test_expectations_parser.h"
+
+namespace gpu {
+
+namespace {
+
+GPUTestConfig::OS GetCurrentOS() {
+#if defined(OS_CHROMEOS)
+ return GPUTestConfig::kOsChromeOS;
+#elif defined(OS_LINUX) || defined(OS_OPENBSD)
+ return GPUTestConfig::kOsLinux;
+#elif defined(OS_WIN)
+ int32 major_version = 0;
+ int32 minor_version = 0;
+ int32 bugfix_version = 0;
+ base::SysInfo::OperatingSystemVersionNumbers(
+ &major_version, &minor_version, &bugfix_version);
+ if (major_version == 5)
+ return GPUTestConfig::kOsWinXP;
+ if (major_version == 6 && minor_version == 0)
+ return GPUTestConfig::kOsWinVista;
+ if (major_version == 6 && minor_version == 1)
+ return GPUTestConfig::kOsWin7;
+ if (major_version == 6 && minor_version == 2)
+ return GPUTestConfig::kOsWin8;
+#elif defined(OS_MACOSX)
+ int32 major_version = 0;
+ int32 minor_version = 0;
+ int32 bugfix_version = 0;
+ base::SysInfo::OperatingSystemVersionNumbers(
+ &major_version, &minor_version, &bugfix_version);
+ if (major_version == 10) {
+ switch (minor_version) {
+ case 5:
+ return GPUTestConfig::kOsMacLeopard;
+ case 6:
+ return GPUTestConfig::kOsMacSnowLeopard;
+ case 7:
+ return GPUTestConfig::kOsMacLion;
+ case 8:
+ return GPUTestConfig::kOsMacMountainLion;
+ }
+ }
+#elif defined(OS_ANDROID)
+ return GPUTestConfig::kOsAndroid;
+#endif
+ return GPUTestConfig::kOsUnknown;
+}
+
+} // namespace anonymous
+
+GPUTestConfig::GPUTestConfig()
+ : validate_gpu_info_(true),
+ os_(kOsUnknown),
+ gpu_device_id_(0),
+ build_type_(kBuildTypeUnknown) {
+}
+
+GPUTestConfig::~GPUTestConfig() {
+}
+
+void GPUTestConfig::set_os(int32 os) {
+ DCHECK_EQ(0, os & ~(kOsAndroid | kOsWin | kOsMac | kOsLinux | kOsChromeOS));
+ os_ = os;
+}
+
+void GPUTestConfig::AddGPUVendor(uint32 gpu_vendor) {
+ DCHECK_NE(0u, gpu_vendor);
+ for (size_t i = 0; i < gpu_vendor_.size(); ++i)
+ DCHECK_NE(gpu_vendor_[i], gpu_vendor);
+ gpu_vendor_.push_back(gpu_vendor);
+}
+
+void GPUTestConfig::set_gpu_device_id(uint32 id) {
+ gpu_device_id_ = id;
+}
+
+void GPUTestConfig::set_build_type(int32 build_type) {
+ DCHECK_EQ(0, build_type & ~(kBuildTypeRelease | kBuildTypeDebug));
+ build_type_ = build_type;
+}
+
+bool GPUTestConfig::IsValid() const {
+ if (!validate_gpu_info_)
+ return true;
+ if (gpu_device_id_ != 0 && (gpu_vendor_.size() != 1 || gpu_vendor_[0] == 0))
+ return false;
+ return true;
+}
+
+bool GPUTestConfig::OverlapsWith(const GPUTestConfig& config) const {
+ DCHECK(IsValid());
+ DCHECK(config.IsValid());
+ if (config.os_ != kOsUnknown && os_ != kOsUnknown &&
+ (os_ & config.os_) == 0)
+ return false;
+ if (config.gpu_vendor_.size() > 0 && gpu_vendor_.size() > 0) {
+ bool shared = false;
+ for (size_t i = 0; i < config.gpu_vendor_.size() && !shared; ++i) {
+ for (size_t j = 0; j < gpu_vendor_.size(); ++j) {
+ if (config.gpu_vendor_[i] == gpu_vendor_[j]) {
+ shared = true;
+ break;
+ }
+ }
+ }
+ if (!shared)
+ return false;
+ }
+ if (config.gpu_device_id_ != 0 && gpu_device_id_ != 0 &&
+ gpu_device_id_ != config.gpu_device_id_)
+ return false;
+ if (config.build_type_ != kBuildTypeUnknown &&
+ build_type_ != kBuildTypeUnknown &&
+ (build_type_ & config.build_type_) == 0)
+ return false;
+ return true;
+}
+
+void GPUTestConfig::DisableGPUInfoValidation() {
+ validate_gpu_info_ = false;
+}
+
+void GPUTestConfig::ClearGPUVendor() {
+ gpu_vendor_.clear();
+}
+
+GPUTestBotConfig::~GPUTestBotConfig() {
+}
+
+void GPUTestBotConfig::AddGPUVendor(uint32 gpu_vendor) {
+ DCHECK_EQ(0u, GPUTestConfig::gpu_vendor().size());
+ GPUTestConfig::AddGPUVendor(gpu_vendor);
+}
+
+bool GPUTestBotConfig::SetGPUInfo(const GPUInfo& gpu_info) {
+ DCHECK(validate_gpu_info_);
+ if (gpu_info.gpu.device_id == 0 || gpu_info.gpu.vendor_id == 0)
+ return false;
+ ClearGPUVendor();
+ AddGPUVendor(gpu_info.gpu.vendor_id);
+ set_gpu_device_id(gpu_info.gpu.device_id);
+ return true;
+}
+
+bool GPUTestBotConfig::IsValid() const {
+ switch (os()) {
+ case kOsWinXP:
+ case kOsWinVista:
+ case kOsWin7:
+ case kOsWin8:
+ case kOsMacLeopard:
+ case kOsMacSnowLeopard:
+ case kOsMacLion:
+ case kOsMacMountainLion:
+ case kOsLinux:
+ case kOsChromeOS:
+ case kOsAndroid:
+ break;
+ default:
+ return false;
+ }
+ if (validate_gpu_info_) {
+ if (gpu_vendor().size() != 1 || gpu_vendor()[0] == 0)
+ return false;
+ if (gpu_device_id() == 0)
+ return false;
+ }
+ switch (build_type()) {
+ case kBuildTypeRelease:
+ case kBuildTypeDebug:
+ break;
+ default:
+ return false;
+ }
+ return true;
+}
+
+bool GPUTestBotConfig::Matches(const GPUTestConfig& config) const {
+ DCHECK(IsValid());
+ DCHECK(config.IsValid());
+ if (config.os() != kOsUnknown && (os() & config.os()) == 0)
+ return false;
+ if (config.gpu_vendor().size() > 0) {
+ bool contained = false;
+ for (size_t i = 0; i < config.gpu_vendor().size(); ++i) {
+ if (config.gpu_vendor()[i] == gpu_vendor()[0]) {
+ contained = true;
+ break;
+ }
+ }
+ if (!contained)
+ return false;
+ }
+ if (config.gpu_device_id() != 0 &&
+ gpu_device_id() != config.gpu_device_id())
+ return false;
+ if (config.build_type() != kBuildTypeUnknown &&
+ (build_type() & config.build_type()) == 0)
+ return false;
+ return true;
+}
+
+bool GPUTestBotConfig::Matches(const std::string& config_data) const {
+ GPUTestExpectationsParser parser;
+ GPUTestConfig config;
+
+ if (!parser.ParseConfig(config_data, &config))
+ return false;
+ return Matches(config);
+}
+
+bool GPUTestBotConfig::LoadCurrentConfig(const GPUInfo* gpu_info) {
+ bool rt;
+ if (gpu_info == NULL) {
+ GPUInfo my_gpu_info;
+ GpuIDResult result;
+ result = CollectGpuID(&my_gpu_info.gpu.vendor_id,
+ &my_gpu_info.gpu.device_id);
+ if (result == kGpuIDNotSupported) {
+ DisableGPUInfoValidation();
+ rt = true;
+ } else {
+ rt = SetGPUInfo(my_gpu_info);
+ }
+ } else {
+ rt = SetGPUInfo(*gpu_info);
+ }
+ set_os(GetCurrentOS());
+ if (os() == kOsUnknown)
+ rt = false;
+#if defined(NDEBUG)
+ set_build_type(kBuildTypeRelease);
+#else
+ set_build_type(kBuildTypeDebug);
+#endif
+ return rt;
+}
+
+// static
+bool GPUTestBotConfig::CurrentConfigMatches(const std::string& config_data) {
+ GPUTestBotConfig my_config;
+ if (!my_config.LoadCurrentConfig(NULL))
+ return false;
+ return my_config.Matches(config_data);
+}
+
+// static
+bool GPUTestBotConfig::CurrentConfigMatches(
+ const std::vector<std::string>& configs) {
+ GPUTestBotConfig my_config;
+ if (!my_config.LoadCurrentConfig(NULL))
+ return false;
+ for (size_t i = 0 ; i < configs.size(); ++i) {
+ if (my_config.Matches(configs[i]))
+ return true;
+ }
+ return false;
+}
+
+} // namespace gpu
+
diff --git a/gpu/config/gpu_test_config.h b/gpu/config/gpu_test_config.h
new file mode 100644
index 0000000..3c7b038
--- /dev/null
+++ b/gpu/config/gpu_test_config.h
@@ -0,0 +1,124 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef GPU_CONFIG_GPU_TEST_CONFIG_H_
+#define GPU_CONFIG_GPU_TEST_CONFIG_H_
+
+#include <string>
+#include <vector>
+
+#include "base/basictypes.h"
+#include "base/compiler_specific.h"
+#include "gpu/gpu_export.h"
+
+namespace gpu {
+
+struct GPUInfo;
+
+class GPU_EXPORT GPUTestConfig {
+ public:
+ enum OS {
+ kOsUnknown = 0,
+ kOsWinXP = 1 << 0,
+ kOsWinVista = 1 << 1,
+ kOsWin7 = 1 << 2,
+ kOsWin8 = 1 << 3,
+ kOsWin = kOsWinXP | kOsWinVista | kOsWin7 | kOsWin8,
+ kOsMacLeopard = 1 << 4,
+ kOsMacSnowLeopard = 1 << 5,
+ kOsMacLion = 1 << 6,
+ kOsMacMountainLion = 1 << 7,
+ kOsMac = kOsMacLeopard | kOsMacSnowLeopard | kOsMacLion |
+ kOsMacMountainLion,
+ kOsLinux = 1 << 8,
+ kOsChromeOS = 1 << 9,
+ kOsAndroid = 1 << 10,
+ };
+
+ enum BuildType {
+ kBuildTypeUnknown = 0,
+ kBuildTypeRelease = 1 << 0,
+ kBuildTypeDebug = 1 << 1,
+ };
+
+ GPUTestConfig();
+ virtual ~GPUTestConfig();
+
+ void set_os(int32 os);
+ void set_gpu_device_id(uint32 id);
+ void set_build_type(int32 build_type);
+
+ virtual void AddGPUVendor(uint32 gpu_vendor);
+
+ int32 os() const { return os_; }
+ const std::vector<uint32>& gpu_vendor() const { return gpu_vendor_; }
+ uint32 gpu_device_id() const { return gpu_device_id_; }
+ int32 build_type() const { return build_type_; }
+
+ // Check if the config is valid. For example, if gpu_device_id_ is set, but
+ // gpu_vendor_ is unknown, then it's invalid.
+ virtual bool IsValid() const;
+
+ // Check if two configs overlap, i.e., if there exists a config that matches
+ // both configs.
+ bool OverlapsWith(const GPUTestConfig& config) const;
+
+ // Disable validation of GPU vendor and device ids.
+ void DisableGPUInfoValidation();
+
+ protected:
+ void ClearGPUVendor();
+
+ // Indicates that the OS has the notion of a numeric GPU vendor and device id
+ // and this data should be validated.
+ bool validate_gpu_info_;
+
+ private:
+ // operating system.
+ int32 os_;
+
+ // GPU vendor.
+ std::vector<uint32> gpu_vendor_;
+
+ // GPU device id (unique to each vendor).
+ uint32 gpu_device_id_;
+
+ // Release or Debug.
+ int32 build_type_;
+};
+
+class GPU_EXPORT GPUTestBotConfig : public GPUTestConfig {
+ public:
+ GPUTestBotConfig() { }
+ virtual ~GPUTestBotConfig();
+
+ // This should only be called when no gpu_vendor is added.
+ virtual void AddGPUVendor(uint32 gpu_vendor) OVERRIDE;
+
+ // Return false if gpu_info does not have valid vendor_id and device_id.
+ bool SetGPUInfo(const GPUInfo& gpu_info);
+
+ // Check if the bot config is valid, i.e., if it is one valid test-bot
+ // environment. For example, if a field is unknown, or if OS is not one
+ // fully defined OS, then it's valid.
+ virtual bool IsValid() const OVERRIDE;
+
+ // Check if a bot config matches a test config, i.e., the test config is a
+ // superset of the bot config.
+ bool Matches(const GPUTestConfig& config) const;
+ bool Matches(const std::string& config_data) const;
+
+ // Setup the config with the current gpu testing environment.
+ // If gpu_info is NULL, collect GPUInfo first.
+ bool LoadCurrentConfig(const GPUInfo* gpu_info);
+
+ // Check if this bot's config matches |config_data| or any of the |configs|.
+ static bool CurrentConfigMatches(const std::string& config_data);
+ static bool CurrentConfigMatches(const std::vector<std::string>& configs);
+};
+
+} // namespace gpu
+
+#endif // GPU_CONFIG_GPU_TEST_CONFIG_H_
+
diff --git a/gpu/config/gpu_test_config_unittest.cc b/gpu/config/gpu_test_config_unittest.cc
new file mode 100644
index 0000000..b9411dc
--- /dev/null
+++ b/gpu/config/gpu_test_config_unittest.cc
@@ -0,0 +1,255 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "gpu/config/gpu_info.h"
+#include "gpu/config/gpu_test_config.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace gpu {
+
+class GPUTestConfigTest : public testing::Test {
+ public:
+ GPUTestConfigTest() { }
+
+ virtual ~GPUTestConfigTest() { }
+
+ protected:
+ virtual void SetUp() { }
+
+ virtual void TearDown() { }
+};
+
+TEST_F(GPUTestConfigTest, EmptyValues) {
+ GPUTestConfig config;
+ EXPECT_EQ(GPUTestConfig::kOsUnknown, config.os());
+ EXPECT_EQ(0u, config.gpu_vendor().size());
+ EXPECT_EQ(0u, config.gpu_device_id());
+ EXPECT_EQ(GPUTestConfig::kBuildTypeUnknown, config.build_type());
+}
+
+TEST_F(GPUTestConfigTest, SetGPUInfo) {
+ GPUInfo gpu_info;
+ gpu_info.gpu.vendor_id = 0x10de;
+ gpu_info.gpu.device_id = 0x0640;
+ GPUTestBotConfig config;
+ EXPECT_TRUE(config.SetGPUInfo(gpu_info));
+ EXPECT_EQ(1u, config.gpu_vendor().size());
+ EXPECT_EQ(gpu_info.gpu.vendor_id, config.gpu_vendor()[0]);
+ EXPECT_EQ(gpu_info.gpu.device_id, config.gpu_device_id());
+
+ gpu_info.gpu.vendor_id = 0x8086;
+ gpu_info.gpu.device_id = 0x0046;
+ EXPECT_TRUE(config.SetGPUInfo(gpu_info));
+ EXPECT_EQ(1u, config.gpu_vendor().size());
+ EXPECT_EQ(gpu_info.gpu.vendor_id, config.gpu_vendor()[0]);
+ EXPECT_EQ(gpu_info.gpu.device_id, config.gpu_device_id());
+}
+
+TEST_F(GPUTestConfigTest, IsValid) {
+ {
+ GPUTestConfig config;
+ config.set_gpu_device_id(0x0640);
+ EXPECT_FALSE(config.IsValid());
+ config.AddGPUVendor(0x10de);
+ EXPECT_TRUE(config.IsValid());
+ }
+
+ {
+ GPUTestBotConfig config;
+ config.set_build_type(GPUTestConfig::kBuildTypeRelease);
+ config.set_os(GPUTestConfig::kOsWin7);
+ config.set_gpu_device_id(0x0640);
+ EXPECT_FALSE(config.IsValid());
+ config.AddGPUVendor(0x10de);
+ EXPECT_TRUE(config.IsValid());
+
+ config.set_gpu_device_id(0);
+ EXPECT_FALSE(config.IsValid());
+ config.set_gpu_device_id(0x0640);
+ EXPECT_TRUE(config.IsValid());
+
+ config.set_os(GPUTestConfig::kOsWin);
+ EXPECT_FALSE(config.IsValid());
+ config.set_os(GPUTestConfig::kOsWin7 | GPUTestConfig::kOsWinXP);
+ EXPECT_FALSE(config.IsValid());
+ config.set_os(GPUTestConfig::kOsWin7);
+ EXPECT_TRUE(config.IsValid());
+
+ config.set_build_type(GPUTestConfig::kBuildTypeUnknown);
+ EXPECT_FALSE(config.IsValid());
+ config.set_build_type(GPUTestConfig::kBuildTypeRelease);
+ EXPECT_TRUE(config.IsValid());
+ }
+}
+
+TEST_F(GPUTestConfigTest, Matches) {
+ GPUTestBotConfig config;
+ config.set_os(GPUTestConfig::kOsWin7);
+ config.set_build_type(GPUTestConfig::kBuildTypeRelease);
+ config.AddGPUVendor(0x10de);
+ config.set_gpu_device_id(0x0640);
+ EXPECT_TRUE(config.IsValid());
+
+ { // os matching
+ GPUTestConfig config2;
+ EXPECT_TRUE(config.Matches(config2));
+ config2.set_os(GPUTestConfig::kOsWin);
+ EXPECT_TRUE(config.Matches(config2));
+ config2.set_os(GPUTestConfig::kOsWin7);
+ EXPECT_TRUE(config.Matches(config2));
+ config2.set_os(GPUTestConfig::kOsMac);
+ EXPECT_FALSE(config.Matches(config2));
+ config2.set_os(GPUTestConfig::kOsWin7 | GPUTestConfig::kOsLinux);
+ EXPECT_TRUE(config.Matches(config2));
+ }
+
+ { // gpu vendor matching
+ {
+ GPUTestConfig config2;
+ config2.AddGPUVendor(0x10de);
+ EXPECT_TRUE(config.Matches(config2));
+ config2.AddGPUVendor(0x1004);
+ EXPECT_TRUE(config.Matches(config2));
+ }
+ {
+ GPUTestConfig config2;
+ config2.AddGPUVendor(0x8086);
+ EXPECT_FALSE(config.Matches(config2));
+ }
+ }
+
+ { // build type matching
+ GPUTestConfig config2;
+ config2.set_build_type(GPUTestConfig::kBuildTypeRelease);
+ EXPECT_TRUE(config.Matches(config2));
+ config2.set_build_type(GPUTestConfig::kBuildTypeRelease |
+ GPUTestConfig::kBuildTypeDebug);
+ EXPECT_TRUE(config.Matches(config2));
+ config2.set_build_type(GPUTestConfig::kBuildTypeDebug);
+ EXPECT_FALSE(config.Matches(config2));
+ }
+
+ { // exact matching
+ GPUTestConfig config2;
+ config2.set_os(GPUTestConfig::kOsWin7);
+ config2.set_build_type(GPUTestConfig::kBuildTypeRelease);
+ config2.AddGPUVendor(0x10de);
+ config2.set_gpu_device_id(0x0640);
+ EXPECT_TRUE(config.Matches(config2));
+ config2.set_gpu_device_id(0x0641);
+ EXPECT_FALSE(config.Matches(config2));
+ }
+}
+
+TEST_F(GPUTestConfigTest, StringMatches) {
+ GPUTestBotConfig config;
+ config.set_os(GPUTestConfig::kOsWin7);
+ config.set_build_type(GPUTestConfig::kBuildTypeRelease);
+ config.AddGPUVendor(0x10de);
+ config.set_gpu_device_id(0x0640);
+ EXPECT_TRUE(config.IsValid());
+
+ EXPECT_TRUE(config.Matches(std::string()));
+
+ // os matching
+ EXPECT_TRUE(config.Matches("WIN"));
+ EXPECT_TRUE(config.Matches("WIN7"));
+ EXPECT_FALSE(config.Matches("MAC"));
+ EXPECT_TRUE(config.Matches("WIN7 LINUX"));
+
+ // gpu vendor matching
+ EXPECT_TRUE(config.Matches("NVIDIA"));
+ EXPECT_TRUE(config.Matches("NVIDIA AMD"));
+ EXPECT_FALSE(config.Matches("INTEL"));
+
+ // build type matching
+ EXPECT_TRUE(config.Matches("RELEASE"));
+ EXPECT_TRUE(config.Matches("RELEASE DEBUG"));
+ EXPECT_FALSE(config.Matches("DEBUG"));
+
+ // exact matching
+ EXPECT_TRUE(config.Matches("WIN7 RELEASE NVIDIA 0X0640"));
+ EXPECT_FALSE(config.Matches("WIN7 RELEASE NVIDIA 0X0641"));
+}
+
+TEST_F(GPUTestConfigTest, OverlapsWith) {
+ { // os
+ // win vs win7
+ GPUTestConfig config;
+ config.set_os(GPUTestConfig::kOsWin);
+ GPUTestConfig config2;
+ config2.set_os(GPUTestConfig::kOsWin7);
+ EXPECT_TRUE(config.OverlapsWith(config2));
+ EXPECT_TRUE(config2.OverlapsWith(config));
+ // win vs win7+linux
+ config2.set_os(GPUTestConfig::kOsWin7 | GPUTestConfig::kOsLinux);
+ EXPECT_TRUE(config.OverlapsWith(config2));
+ EXPECT_TRUE(config2.OverlapsWith(config));
+ // win vs mac
+ config2.set_os(GPUTestConfig::kOsMac);
+ EXPECT_FALSE(config.OverlapsWith(config2));
+ EXPECT_FALSE(config2.OverlapsWith(config));
+ // win vs unknown
+ config2.set_os(GPUTestConfig::kOsUnknown);
+ EXPECT_TRUE(config.OverlapsWith(config2));
+ EXPECT_TRUE(config2.OverlapsWith(config));
+ }
+
+ { // gpu vendor
+ GPUTestConfig config;
+ config.AddGPUVendor(0x10de);
+ // nvidia vs unknown
+ GPUTestConfig config2;
+ EXPECT_TRUE(config.OverlapsWith(config2));
+ EXPECT_TRUE(config2.OverlapsWith(config));
+ // nvidia vs intel
+ config2.AddGPUVendor(0x1086);
+ EXPECT_FALSE(config.OverlapsWith(config2));
+ EXPECT_FALSE(config2.OverlapsWith(config));
+ // nvidia vs nvidia+intel
+ config2.AddGPUVendor(0x10de);
+ EXPECT_TRUE(config.OverlapsWith(config2));
+ EXPECT_TRUE(config2.OverlapsWith(config));
+ }
+
+ { // build type
+ // release vs debug
+ GPUTestConfig config;
+ config.set_build_type(GPUTestConfig::kBuildTypeRelease);
+ GPUTestConfig config2;
+ config2.set_build_type(GPUTestConfig::kBuildTypeDebug);
+ EXPECT_FALSE(config.OverlapsWith(config2));
+ EXPECT_FALSE(config2.OverlapsWith(config));
+ // release vs release+debug
+ config2.set_build_type(GPUTestConfig::kBuildTypeRelease |
+ GPUTestConfig::kBuildTypeDebug);
+ EXPECT_TRUE(config.OverlapsWith(config2));
+ EXPECT_TRUE(config2.OverlapsWith(config));
+ // release vs unknown
+ config2.set_build_type(GPUTestConfig::kBuildTypeUnknown);
+ EXPECT_TRUE(config.OverlapsWith(config2));
+ EXPECT_TRUE(config2.OverlapsWith(config));
+ }
+
+ { // win7 vs nvidia
+ GPUTestConfig config;
+ config.set_os(GPUTestConfig::kOsWin7);
+ GPUTestConfig config2;
+ config2.AddGPUVendor(0x10de);
+ EXPECT_TRUE(config.OverlapsWith(config2));
+ EXPECT_TRUE(config2.OverlapsWith(config));
+ }
+}
+
+TEST_F(GPUTestConfigTest, LoadCurrentConfig) {
+ GPUTestBotConfig config;
+ GPUInfo gpu_info;
+ gpu_info.gpu.vendor_id = 0x10de;
+ gpu_info.gpu.device_id = 0x0640;
+ EXPECT_TRUE(config.LoadCurrentConfig(&gpu_info));
+ EXPECT_TRUE(config.IsValid());
+}
+
+} // namespace gpu
+
diff --git a/gpu/config/gpu_test_expectations_parser.cc b/gpu/config/gpu_test_expectations_parser.cc
new file mode 100644
index 0000000..8cc2b3c
--- /dev/null
+++ b/gpu/config/gpu_test_expectations_parser.cc
@@ -0,0 +1,503 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "gpu/config/gpu_test_expectations_parser.h"
+
+#include "base/file_util.h"
+#include "base/logging.h"
+#include "base/string_number_conversions.h"
+#include "base/string_util.h"
+#include "base/stringprintf.h"
+#include "base/strings/string_split.h"
+
+namespace gpu {
+
+namespace {
+
+enum LineParserStage {
+ kLineParserBegin = 0,
+ kLineParserBugID,
+ kLineParserConfigs,
+ kLineParserColon,
+ kLineParserTestName,
+ kLineParserEqual,
+ kLineParserExpectations,
+};
+
+enum Token {
+ // os
+ kConfigWinXP = 0,
+ kConfigWinVista,
+ kConfigWin7,
+ kConfigWin8,
+ kConfigWin,
+ kConfigMacLeopard,
+ kConfigMacSnowLeopard,
+ kConfigMacLion,
+ kConfigMacMountainLion,
+ kConfigMac,
+ kConfigLinux,
+ kConfigChromeOS,
+ kConfigAndroid,
+ // gpu vendor
+ kConfigNVidia,
+ kConfigAMD,
+ kConfigIntel,
+ kConfigVMWare,
+ // build type
+ kConfigRelease,
+ kConfigDebug,
+ // expectation
+ kExpectationPass,
+ kExpectationFail,
+ kExpectationFlaky,
+ kExpectationTimeout,
+ kExpectationSkip,
+ // separator
+ kSeparatorColon,
+ kSeparatorEqual,
+
+ kNumberOfExactMatchTokens,
+
+ // others
+ kConfigGPUDeviceID,
+ kTokenComment,
+ kTokenWord,
+};
+
+struct TokenInfo {
+ const char* name;
+ int32 flag;
+};
+
+const TokenInfo kTokenData[] = {
+ { "xp", GPUTestConfig::kOsWinXP },
+ { "vista", GPUTestConfig::kOsWinVista },
+ { "win7", GPUTestConfig::kOsWin7 },
+ { "win8", GPUTestConfig::kOsWin8 },
+ { "win", GPUTestConfig::kOsWin },
+ { "leopard", GPUTestConfig::kOsMacLeopard },
+ { "snowleopard", GPUTestConfig::kOsMacSnowLeopard },
+ { "lion", GPUTestConfig::kOsMacLion },
+ { "mountainlion", GPUTestConfig::kOsMacMountainLion },
+ { "mac", GPUTestConfig::kOsMac },
+ { "linux", GPUTestConfig::kOsLinux },
+ { "chromeos", GPUTestConfig::kOsChromeOS },
+ { "android", GPUTestConfig::kOsAndroid },
+ { "nvidia", 0x10DE },
+ { "amd", 0x1002 },
+ { "intel", 0x8086 },
+ { "vmware", 0x15ad },
+ { "release", GPUTestConfig::kBuildTypeRelease },
+ { "debug", GPUTestConfig::kBuildTypeDebug },
+ { "pass", GPUTestExpectationsParser::kGpuTestPass },
+ { "fail", GPUTestExpectationsParser::kGpuTestFail },
+ { "flaky", GPUTestExpectationsParser::kGpuTestFlaky },
+ { "timeout", GPUTestExpectationsParser::kGpuTestTimeout },
+ { "skip", GPUTestExpectationsParser::kGpuTestSkip },
+ { ":", 0 },
+ { "=", 0 },
+};
+
+enum ErrorType {
+ kErrorFileIO = 0,
+ kErrorIllegalEntry,
+ kErrorInvalidEntry,
+ kErrorEntryWithOsConflicts,
+ kErrorEntryWithGpuVendorConflicts,
+ kErrorEntryWithBuildTypeConflicts,
+ kErrorEntryWithGpuDeviceIdConflicts,
+ kErrorEntryWithExpectationConflicts,
+ kErrorEntriesOverlap,
+
+ kNumberOfErrors,
+};
+
+const char* kErrorMessage[] = {
+ "file IO failed",
+ "entry with wrong format",
+ "entry invalid, likely wrong modifiers combination",
+ "entry with OS modifier conflicts",
+ "entry with GPU vendor modifier conflicts",
+ "entry with GPU build type conflicts",
+ "entry with GPU device id conflicts or malformat",
+ "entry with expectation modifier conflicts",
+ "two entries's configs overlap",
+};
+
+Token ParseToken(const std::string& word) {
+ if (StartsWithASCII(word, "//", false))
+ return kTokenComment;
+ if (StartsWithASCII(word, "0x", false))
+ return kConfigGPUDeviceID;
+
+ for (int32 i = 0; i < kNumberOfExactMatchTokens; ++i) {
+ if (LowerCaseEqualsASCII(word, kTokenData[i].name))
+ return static_cast<Token>(i);
+ }
+ return kTokenWord;
+}
+
+// reference name can have the last character as *.
+bool NamesMatching(const std::string& ref, const std::string& test_name) {
+ size_t len = ref.length();
+ if (len == 0)
+ return false;
+ if (ref[len - 1] == '*') {
+ if (test_name.length() > len -1 &&
+ ref.compare(0, len - 1, test_name, 0, len - 1) == 0)
+ return true;
+ return false;
+ }
+ return (ref == test_name);
+}
+
+} // namespace anonymous
+
+GPUTestExpectationsParser::GPUTestExpectationsParser() {
+ // Some sanity check.
+ DCHECK_EQ(static_cast<unsigned int>(kNumberOfExactMatchTokens),
+ sizeof(kTokenData) / sizeof(kTokenData[0]));
+ DCHECK_EQ(static_cast<unsigned int>(kNumberOfErrors),
+ sizeof(kErrorMessage) / sizeof(kErrorMessage[0]));
+}
+
+GPUTestExpectationsParser::~GPUTestExpectationsParser() {
+}
+
+bool GPUTestExpectationsParser::LoadTestExpectations(const std::string& data) {
+ entries_.clear();
+ error_messages_.clear();
+
+ std::vector<std::string> lines;
+ base::SplitString(data, '\n', &lines);
+ bool rt = true;
+ for (size_t i = 0; i < lines.size(); ++i) {
+ if (!ParseLine(lines[i], i + 1))
+ rt = false;
+ }
+ if (DetectConflictsBetweenEntries()) {
+ entries_.clear();
+ rt = false;
+ }
+
+ return rt;
+}
+
+bool GPUTestExpectationsParser::LoadTestExpectations(
+ const base::FilePath& path) {
+ entries_.clear();
+ error_messages_.clear();
+
+ std::string data;
+ if (!file_util::ReadFileToString(path, &data)) {
+ error_messages_.push_back(kErrorMessage[kErrorFileIO]);
+ return false;
+ }
+ return LoadTestExpectations(data);
+}
+
+int32 GPUTestExpectationsParser::GetTestExpectation(
+ const std::string& test_name,
+ const GPUTestBotConfig& bot_config) const {
+ for (size_t i = 0; i < entries_.size(); ++i) {
+ if (NamesMatching(entries_[i].test_name, test_name) &&
+ bot_config.Matches(entries_[i].test_config))
+ return entries_[i].test_expectation;
+ }
+ return kGpuTestPass;
+}
+
+const std::vector<std::string>&
+GPUTestExpectationsParser::GetErrorMessages() const {
+ return error_messages_;
+}
+
+bool GPUTestExpectationsParser::ParseConfig(
+ const std::string& config_data, GPUTestConfig* config) {
+ DCHECK(config);
+ std::vector<std::string> tokens;
+ base::SplitStringAlongWhitespace(config_data, &tokens);
+
+ for (size_t i = 0; i < tokens.size(); ++i) {
+ Token token = ParseToken(tokens[i]);
+ switch (token) {
+ case kConfigWinXP:
+ case kConfigWinVista:
+ case kConfigWin7:
+ case kConfigWin8:
+ case kConfigWin:
+ case kConfigMacLeopard:
+ case kConfigMacSnowLeopard:
+ case kConfigMacLion:
+ case kConfigMacMountainLion:
+ case kConfigMac:
+ case kConfigLinux:
+ case kConfigChromeOS:
+ case kConfigAndroid:
+ case kConfigNVidia:
+ case kConfigAMD:
+ case kConfigIntel:
+ case kConfigVMWare:
+ case kConfigRelease:
+ case kConfigDebug:
+ case kConfigGPUDeviceID:
+ if (token == kConfigGPUDeviceID) {
+ if (!UpdateTestConfig(config, tokens[i], 0))
+ return false;
+ } else {
+ if (!UpdateTestConfig(config, token, 0))
+ return false;
+ }
+ break;
+ default:
+ return false;
+ }
+ }
+ return true;
+}
+
+bool GPUTestExpectationsParser::ParseLine(
+ const std::string& line_data, size_t line_number) {
+ std::vector<std::string> tokens;
+ base::SplitStringAlongWhitespace(line_data, &tokens);
+ int32 stage = kLineParserBegin;
+ GPUTestExpectationEntry entry;
+ entry.line_number = line_number;
+ GPUTestConfig& config = entry.test_config;
+ bool comments_encountered = false;
+ for (size_t i = 0; i < tokens.size() && !comments_encountered; ++i) {
+ Token token = ParseToken(tokens[i]);
+ switch (token) {
+ case kTokenComment:
+ comments_encountered = true;
+ break;
+ case kConfigWinXP:
+ case kConfigWinVista:
+ case kConfigWin7:
+ case kConfigWin8:
+ case kConfigWin:
+ case kConfigMacLeopard:
+ case kConfigMacSnowLeopard:
+ case kConfigMacLion:
+ case kConfigMacMountainLion:
+ case kConfigMac:
+ case kConfigLinux:
+ case kConfigChromeOS:
+ case kConfigAndroid:
+ case kConfigNVidia:
+ case kConfigAMD:
+ case kConfigIntel:
+ case kConfigVMWare:
+ case kConfigRelease:
+ case kConfigDebug:
+ case kConfigGPUDeviceID:
+ // MODIFIERS, could be in any order, need at least one.
+ if (stage != kLineParserConfigs && stage != kLineParserBugID) {
+ PushErrorMessage(kErrorMessage[kErrorIllegalEntry],
+ line_number);
+ return false;
+ }
+ if (token == kConfigGPUDeviceID) {
+ if (!UpdateTestConfig(&config, tokens[i], line_number))
+ return false;
+ } else {
+ if (!UpdateTestConfig(&config, token, line_number))
+ return false;
+ }
+ if (stage == kLineParserBugID)
+ stage++;
+ break;
+ case kSeparatorColon:
+ // :
+ if (stage != kLineParserConfigs) {
+ PushErrorMessage(kErrorMessage[kErrorIllegalEntry],
+ line_number);
+ return false;
+ }
+ stage++;
+ break;
+ case kSeparatorEqual:
+ // =
+ if (stage != kLineParserTestName) {
+ PushErrorMessage(kErrorMessage[kErrorIllegalEntry],
+ line_number);
+ return false;
+ }
+ stage++;
+ break;
+ case kTokenWord:
+ // BUG_ID or TEST_NAME
+ if (stage == kLineParserBegin) {
+ // Bug ID is not used for anything; ignore it.
+ } else if (stage == kLineParserColon) {
+ entry.test_name = tokens[i];
+ } else {
+ PushErrorMessage(kErrorMessage[kErrorIllegalEntry],
+ line_number);
+ return false;
+ }
+ stage++;
+ break;
+ case kExpectationPass:
+ case kExpectationFail:
+ case kExpectationFlaky:
+ case kExpectationTimeout:
+ case kExpectationSkip:
+ // TEST_EXPECTATIONS
+ if (stage != kLineParserEqual && stage != kLineParserExpectations) {
+ PushErrorMessage(kErrorMessage[kErrorIllegalEntry],
+ line_number);
+ return false;
+ }
+ if ((kTokenData[token].flag & entry.test_expectation) != 0) {
+ PushErrorMessage(kErrorMessage[kErrorEntryWithExpectationConflicts],
+ line_number);
+ return false;
+ }
+ entry.test_expectation =
+ (kTokenData[token].flag | entry.test_expectation);
+ if (stage == kLineParserEqual)
+ stage++;
+ break;
+ default:
+ DCHECK(false);
+ break;
+ }
+ }
+ if (stage == kLineParserBegin) {
+ // The whole line is empty or all comments
+ return true;
+ }
+ if (stage == kLineParserExpectations) {
+ if (!config.IsValid()) {
+ PushErrorMessage(kErrorMessage[kErrorInvalidEntry], line_number);
+ return false;
+ }
+ entries_.push_back(entry);
+ return true;
+ }
+ PushErrorMessage(kErrorMessage[kErrorIllegalEntry], line_number);
+ return false;
+}
+
+bool GPUTestExpectationsParser::UpdateTestConfig(
+ GPUTestConfig* config, int32 token, size_t line_number) {
+ DCHECK(config);
+ switch (token) {
+ case kConfigWinXP:
+ case kConfigWinVista:
+ case kConfigWin7:
+ case kConfigWin8:
+ case kConfigWin:
+ case kConfigMacLeopard:
+ case kConfigMacSnowLeopard:
+ case kConfigMacLion:
+ case kConfigMacMountainLion:
+ case kConfigMac:
+ case kConfigLinux:
+ case kConfigChromeOS:
+ case kConfigAndroid:
+ if ((config->os() & kTokenData[token].flag) != 0) {
+ PushErrorMessage(kErrorMessage[kErrorEntryWithOsConflicts],
+ line_number);
+ return false;
+ }
+ config->set_os(config->os() | kTokenData[token].flag);
+ break;
+ case kConfigNVidia:
+ case kConfigAMD:
+ case kConfigIntel:
+ case kConfigVMWare:
+ {
+ uint32 gpu_vendor =
+ static_cast<uint32>(kTokenData[token].flag);
+ for (size_t i = 0; i < config->gpu_vendor().size(); ++i) {
+ if (config->gpu_vendor()[i] == gpu_vendor) {
+ PushErrorMessage(
+ kErrorMessage[kErrorEntryWithGpuVendorConflicts],
+ line_number);
+ return false;
+ }
+ }
+ config->AddGPUVendor(gpu_vendor);
+ }
+ break;
+ case kConfigRelease:
+ case kConfigDebug:
+ if ((config->build_type() & kTokenData[token].flag) != 0) {
+ PushErrorMessage(
+ kErrorMessage[kErrorEntryWithBuildTypeConflicts],
+ line_number);
+ return false;
+ }
+ config->set_build_type(
+ config->build_type() | kTokenData[token].flag);
+ break;
+ default:
+ DCHECK(false);
+ break;
+ }
+ return true;
+}
+
+bool GPUTestExpectationsParser::UpdateTestConfig(
+ GPUTestConfig* config,
+ const std::string& gpu_device_id,
+ size_t line_number) {
+ DCHECK(config);
+ uint32 device_id = 0;
+ if (config->gpu_device_id() != 0 ||
+ !base::HexStringToInt(gpu_device_id,
+ reinterpret_cast<int*>(&device_id)) ||
+ device_id == 0) {
+ PushErrorMessage(kErrorMessage[kErrorEntryWithGpuDeviceIdConflicts],
+ line_number);
+ return false;
+ }
+ config->set_gpu_device_id(device_id);
+ return true;
+}
+
+bool GPUTestExpectationsParser::DetectConflictsBetweenEntries() {
+ bool rt = false;
+ for (size_t i = 0; i < entries_.size(); ++i) {
+ for (size_t j = i + 1; j < entries_.size(); ++j) {
+ if (entries_[i].test_name == entries_[j].test_name &&
+ entries_[i].test_config.OverlapsWith(entries_[j].test_config)) {
+ PushErrorMessage(kErrorMessage[kErrorEntriesOverlap],
+ entries_[i].line_number,
+ entries_[j].line_number);
+ rt = true;
+ }
+ }
+ }
+ return rt;
+}
+
+void GPUTestExpectationsParser::PushErrorMessage(
+ const std::string& message, size_t line_number) {
+ error_messages_.push_back(
+ base::StringPrintf("Line %d : %s",
+ static_cast<int>(line_number), message.c_str()));
+}
+
+void GPUTestExpectationsParser::PushErrorMessage(
+ const std::string& message,
+ size_t entry1_line_number,
+ size_t entry2_line_number) {
+ error_messages_.push_back(
+ base::StringPrintf("Line %d and %d : %s",
+ static_cast<int>(entry1_line_number),
+ static_cast<int>(entry2_line_number),
+ message.c_str()));
+}
+
+GPUTestExpectationsParser:: GPUTestExpectationEntry::GPUTestExpectationEntry()
+ : test_expectation(0),
+ line_number(0) {
+}
+
+} // namespace gpu
+
diff --git a/gpu/config/gpu_test_expectations_parser.h b/gpu/config/gpu_test_expectations_parser.h
new file mode 100644
index 0000000..a69f7e9
--- /dev/null
+++ b/gpu/config/gpu_test_expectations_parser.h
@@ -0,0 +1,88 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef GPU_CONFIG_GPU_TEST_EXPECTATIONS_PARSER_H_
+#define GPU_CONFIG_GPU_TEST_EXPECTATIONS_PARSER_H_
+
+#include <string>
+#include <vector>
+
+#include "base/basictypes.h"
+#include "base/files/file_path.h"
+#include "gpu/config/gpu_test_config.h"
+#include "gpu/gpu_export.h"
+
+namespace gpu {
+
+class GPU_EXPORT GPUTestExpectationsParser {
+ public:
+ enum GPUTestExpectation {
+ kGpuTestPass = 1 << 0,
+ kGpuTestFail = 1 << 1,
+ kGpuTestFlaky = 1 << 2,
+ kGpuTestTimeout = 1 << 3,
+ kGpuTestSkip = 1 << 4,
+ };
+
+ GPUTestExpectationsParser();
+ ~GPUTestExpectationsParser();
+
+ // Parse the text expectations, and if no error is encountered,
+ // save all the entries. Otherwise, generate error messages.
+ // Return true if parsing succeeds.
+ bool LoadTestExpectations(const std::string& data);
+ bool LoadTestExpectations(const base::FilePath& path);
+
+ // Query error messages from the last LoadTestExpectations() call.
+ const std::vector<std::string>& GetErrorMessages() const;
+
+ // Get the test expectation of a given test on a given bot.
+ int32 GetTestExpectation(const std::string& test_name,
+ const GPUTestBotConfig& bot_config) const;
+
+ // Parse a list of config modifiers. If we have a valid entry with no
+ // conflicts, | config | stores it, and the function returns true.
+ bool ParseConfig(const std::string& config_data, GPUTestConfig* config);
+
+ private:
+ struct GPUTestExpectationEntry {
+ GPUTestExpectationEntry();
+
+ std::string test_name;
+ GPUTestConfig test_config;
+ int32 test_expectation;
+ size_t line_number;
+ };
+
+ // Parse a line of text. If we have a valid entry, save it; otherwise,
+ // generate error messages.
+ bool ParseLine(const std::string& line_data, size_t line_number);
+
+ // Update OS/GPUVendor/BuildType modifiers. May generate an error message.
+ bool UpdateTestConfig(
+ GPUTestConfig* config, int32 token, size_t line_number);
+
+ // Update GPUDeviceID modifier. May generate an error message.
+ bool UpdateTestConfig(GPUTestConfig* config,
+ const std::string & gpu_device_id,
+ size_t line_number);
+
+ // Check if two entries' config overlap with each other. May generate an
+ // error message.
+ bool DetectConflictsBetweenEntries();
+
+ // Save an error message, which can be queried later.
+ void PushErrorMessage(const std::string& message, size_t line_number);
+ void PushErrorMessage(const std::string& message,
+ size_t entry1_line_number,
+ size_t entry2_line_number);
+
+ std::vector<GPUTestExpectationEntry> entries_;
+ std::vector<std::string> error_messages_;
+};
+
+} // namespace gpu
+
+#endif // GPU_CONFIG_GPU_TEST_EXPECTATIONS_PARSER_H_
+
diff --git a/gpu/config/gpu_test_expectations_parser_unittest.cc b/gpu/config/gpu_test_expectations_parser_unittest.cc
new file mode 100644
index 0000000..79c169c
--- /dev/null
+++ b/gpu/config/gpu_test_expectations_parser_unittest.cc
@@ -0,0 +1,245 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/logging.h"
+#include "gpu/config/gpu_test_expectations_parser.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace gpu {
+
+class GPUTestExpectationsParserTest : public testing::Test {
+ public:
+ GPUTestExpectationsParserTest() { }
+
+ virtual ~GPUTestExpectationsParserTest() { }
+
+ const GPUTestBotConfig& bot_config() const {
+ return bot_config_;
+ }
+
+ protected:
+ virtual void SetUp() {
+ bot_config_.set_os(GPUTestConfig::kOsWin7);
+ bot_config_.set_build_type(GPUTestConfig::kBuildTypeRelease);
+ bot_config_.AddGPUVendor(0x10de);
+ bot_config_.set_gpu_device_id(0x0640);
+ ASSERT_TRUE(bot_config_.IsValid());
+ }
+
+ virtual void TearDown() { }
+
+ private:
+ GPUTestBotConfig bot_config_;
+};
+
+TEST_F(GPUTestExpectationsParserTest, CommentOnly) {
+ const std::string text =
+ " \n"
+ "// This is just some comment\n"
+ "";
+ GPUTestExpectationsParser parser;
+ EXPECT_TRUE(parser.LoadTestExpectations(text));
+ EXPECT_EQ(0u, parser.GetErrorMessages().size());
+ EXPECT_EQ(GPUTestExpectationsParser::kGpuTestPass,
+ parser.GetTestExpectation("some_test", bot_config()));
+}
+
+TEST_F(GPUTestExpectationsParserTest, ValidFullEntry) {
+ const std::string text =
+ "BUG12345 WIN7 RELEASE NVIDIA 0x0640 : MyTest = FAIL";
+
+ GPUTestExpectationsParser parser;
+ EXPECT_TRUE(parser.LoadTestExpectations(text));
+ EXPECT_EQ(0u, parser.GetErrorMessages().size());
+ EXPECT_EQ(GPUTestExpectationsParser::kGpuTestFail,
+ parser.GetTestExpectation("MyTest", bot_config()));
+}
+
+TEST_F(GPUTestExpectationsParserTest, ValidPartialEntry) {
+ const std::string text =
+ "BUG12345 WIN NVIDIA : MyTest = TIMEOUT";
+
+ GPUTestExpectationsParser parser;
+ EXPECT_TRUE(parser.LoadTestExpectations(text));
+ EXPECT_EQ(0u, parser.GetErrorMessages().size());
+ EXPECT_EQ(GPUTestExpectationsParser::kGpuTestTimeout,
+ parser.GetTestExpectation("MyTest", bot_config()));
+}
+
+TEST_F(GPUTestExpectationsParserTest, ValidUnrelatedOsEntry) {
+ const std::string text =
+ "BUG12345 LEOPARD : MyTest = TIMEOUT";
+
+ GPUTestExpectationsParser parser;
+ EXPECT_TRUE(parser.LoadTestExpectations(text));
+ EXPECT_EQ(0u, parser.GetErrorMessages().size());
+ EXPECT_EQ(GPUTestExpectationsParser::kGpuTestPass,
+ parser.GetTestExpectation("MyTest", bot_config()));
+}
+
+TEST_F(GPUTestExpectationsParserTest, ValidUnrelatedTestEntry) {
+ const std::string text =
+ "BUG12345 WIN7 RELEASE NVIDIA 0x0640 : AnotherTest = FAIL";
+
+ GPUTestExpectationsParser parser;
+ EXPECT_TRUE(parser.LoadTestExpectations(text));
+ EXPECT_EQ(0u, parser.GetErrorMessages().size());
+ EXPECT_EQ(GPUTestExpectationsParser::kGpuTestPass,
+ parser.GetTestExpectation("MyTest", bot_config()));
+}
+
+TEST_F(GPUTestExpectationsParserTest, AllModifiers) {
+ const std::string text =
+ "BUG12345 XP VISTA WIN7 WIN8 LEOPARD SNOWLEOPARD LION MOUNTAINLION "
+ "LINUX CHROMEOS ANDROID "
+ "NVIDIA INTEL AMD VMWARE RELEASE DEBUG : MyTest = "
+ "PASS FAIL FLAKY TIMEOUT SKIP";
+
+ GPUTestExpectationsParser parser;
+ EXPECT_TRUE(parser.LoadTestExpectations(text));
+ EXPECT_EQ(0u, parser.GetErrorMessages().size());
+ EXPECT_EQ(GPUTestExpectationsParser::kGpuTestPass |
+ GPUTestExpectationsParser::kGpuTestFail |
+ GPUTestExpectationsParser::kGpuTestFlaky |
+ GPUTestExpectationsParser::kGpuTestTimeout |
+ GPUTestExpectationsParser::kGpuTestSkip,
+ parser.GetTestExpectation("MyTest", bot_config()));
+}
+
+TEST_F(GPUTestExpectationsParserTest, DuplicateModifiers) {
+ const std::string text =
+ "BUG12345 WIN7 WIN7 RELEASE NVIDIA 0x0640 : MyTest = FAIL";
+
+ GPUTestExpectationsParser parser;
+ EXPECT_FALSE(parser.LoadTestExpectations(text));
+ EXPECT_NE(0u, parser.GetErrorMessages().size());
+}
+
+TEST_F(GPUTestExpectationsParserTest, AllModifiersLowerCase) {
+ const std::string text =
+ "BUG12345 xp vista win7 leopard snowleopard lion linux chromeos android "
+ "nvidia intel amd vmware release debug : MyTest = "
+ "pass fail flaky timeout skip";
+
+ GPUTestExpectationsParser parser;
+ EXPECT_TRUE(parser.LoadTestExpectations(text));
+ EXPECT_EQ(0u, parser.GetErrorMessages().size());
+ EXPECT_EQ(GPUTestExpectationsParser::kGpuTestPass |
+ GPUTestExpectationsParser::kGpuTestFail |
+ GPUTestExpectationsParser::kGpuTestFlaky |
+ GPUTestExpectationsParser::kGpuTestTimeout |
+ GPUTestExpectationsParser::kGpuTestSkip,
+ parser.GetTestExpectation("MyTest", bot_config()));
+}
+
+TEST_F(GPUTestExpectationsParserTest, MissingColon) {
+ const std::string text =
+ "BUG12345 XP MyTest = FAIL";
+
+ GPUTestExpectationsParser parser;
+ EXPECT_FALSE(parser.LoadTestExpectations(text));
+ EXPECT_NE(0u, parser.GetErrorMessages().size());
+}
+
+TEST_F(GPUTestExpectationsParserTest, MissingEqual) {
+ const std::string text =
+ "BUG12345 XP : MyTest FAIL";
+
+ GPUTestExpectationsParser parser;
+ EXPECT_FALSE(parser.LoadTestExpectations(text));
+ EXPECT_NE(0u, parser.GetErrorMessages().size());
+}
+
+TEST_F(GPUTestExpectationsParserTest, IllegalModifier) {
+ const std::string text =
+ "BUG12345 XP XXX : MyTest = FAIL";
+
+ GPUTestExpectationsParser parser;
+ EXPECT_FALSE(parser.LoadTestExpectations(text));
+ EXPECT_NE(0u, parser.GetErrorMessages().size());
+}
+
+TEST_F(GPUTestExpectationsParserTest, OsConflicts) {
+ const std::string text =
+ "BUG12345 XP WIN : MyTest = FAIL";
+
+ GPUTestExpectationsParser parser;
+ EXPECT_FALSE(parser.LoadTestExpectations(text));
+ EXPECT_NE(0u, parser.GetErrorMessages().size());
+}
+
+TEST_F(GPUTestExpectationsParserTest, InvalidModifierCombination) {
+ const std::string text =
+ "BUG12345 XP NVIDIA INTEL 0x0640 : MyTest = FAIL";
+
+ GPUTestExpectationsParser parser;
+ EXPECT_FALSE(parser.LoadTestExpectations(text));
+ EXPECT_NE(0u, parser.GetErrorMessages().size());
+}
+
+TEST_F(GPUTestExpectationsParserTest, BadGpuDeviceID) {
+ const std::string text =
+ "BUG12345 XP NVIDIA 0xU07X : MyTest = FAIL";
+
+ GPUTestExpectationsParser parser;
+ EXPECT_FALSE(parser.LoadTestExpectations(text));
+ EXPECT_NE(0u, parser.GetErrorMessages().size());
+}
+
+TEST_F(GPUTestExpectationsParserTest, MoreThanOneGpuDeviceID) {
+ const std::string text =
+ "BUG12345 XP NVIDIA 0x0640 0x0641 : MyTest = FAIL";
+
+ GPUTestExpectationsParser parser;
+ EXPECT_FALSE(parser.LoadTestExpectations(text));
+ EXPECT_NE(0u, parser.GetErrorMessages().size());
+}
+
+TEST_F(GPUTestExpectationsParserTest, MultipleEntriesConflicts) {
+ const std::string text =
+ "BUG12345 WIN7 RELEASE NVIDIA 0x0640 : MyTest = FAIL\n"
+ "BUG12345 WIN : MyTest = FAIL";
+
+ GPUTestExpectationsParser parser;
+ EXPECT_FALSE(parser.LoadTestExpectations(text));
+ EXPECT_NE(0u, parser.GetErrorMessages().size());
+}
+
+TEST_F(GPUTestExpectationsParserTest, MultipleTests) {
+ const std::string text =
+ "BUG12345 WIN7 RELEASE NVIDIA 0x0640 : MyTest = FAIL\n"
+ "BUG12345 WIN : AnotherTest = FAIL";
+
+ GPUTestExpectationsParser parser;
+ EXPECT_TRUE(parser.LoadTestExpectations(text));
+ EXPECT_EQ(0u, parser.GetErrorMessages().size());
+}
+
+TEST_F(GPUTestExpectationsParserTest, ValidMultipleEntries) {
+ const std::string text =
+ "BUG12345 WIN7 RELEASE NVIDIA 0x0640 : MyTest = FAIL\n"
+ "BUG12345 LINUX : MyTest = TIMEOUT";
+
+ GPUTestExpectationsParser parser;
+ EXPECT_TRUE(parser.LoadTestExpectations(text));
+ EXPECT_EQ(0u, parser.GetErrorMessages().size());
+ EXPECT_EQ(GPUTestExpectationsParser::kGpuTestFail,
+ parser.GetTestExpectation("MyTest", bot_config()));
+}
+
+TEST_F(GPUTestExpectationsParserTest, StarMatching) {
+ const std::string text =
+ "BUG12345 WIN7 RELEASE NVIDIA 0x0640 : MyTest* = FAIL";
+
+ GPUTestExpectationsParser parser;
+ EXPECT_TRUE(parser.LoadTestExpectations(text));
+ EXPECT_EQ(0u, parser.GetErrorMessages().size());
+ EXPECT_EQ(GPUTestExpectationsParser::kGpuTestFail,
+ parser.GetTestExpectation("MyTest0", bot_config()));
+ EXPECT_EQ(GPUTestExpectationsParser::kGpuTestPass,
+ parser.GetTestExpectation("OtherTest", bot_config()));
+}
+
+} // namespace gpu
+
diff --git a/gpu/gpu.gyp b/gpu/gpu.gyp
index 78c44c2..9c72995 100644
--- a/gpu/gpu.gyp
+++ b/gpu/gpu.gyp
@@ -218,6 +218,8 @@
'config/gpu_info_collector_unittest.cc',
'config/gpu_info_unittest.cc',
'config/gpu_switching_list_unittest.cc',
+ 'config/gpu_test_config_unittest.cc',
+ 'config/gpu_test_expectations_parser_unittest.cc',
'config/gpu_util_unittest.cc',
],
'conditions': [
diff --git a/gpu/gpu_config.gypi b/gpu/gpu_config.gypi
index 5c33f91..7ea4b56 100644
--- a/gpu/gpu_config.gypi
+++ b/gpu/gpu_config.gypi
@@ -38,6 +38,10 @@
'config/gpu_switching_list.cc',
'config/gpu_switching_list.h',
'config/gpu_switching_option.h',
+ 'config/gpu_test_config.cc',
+ 'config/gpu_test_config.h',
+ 'config/gpu_test_expectations_parser.cc',
+ 'config/gpu_test_expectations_parser.h',
'config/gpu_util.cc',
'config/gpu_util.h',
'config/software_rendering_list_json.cc',