Home | History | Annotate | Download | only in config
      1 // Copyright (c) 2013 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #include <vector>
      6 
      7 #include "base/memory/scoped_ptr.h"
      8 #include "gpu/config/gpu_control_list.h"
      9 #include "gpu/config/gpu_info.h"
     10 #include "testing/gtest/include/gtest/gtest.h"
     11 
     12 const char kOsVersion[] = "10.6.4";
     13 const uint32 kIntelVendorId = 0x8086;
     14 const uint32 kIntelDeviceId = 0x0166;  // 3rd Gen Core Graphics
     15 const uint32 kNvidiaVendorId = 0x10de;
     16 const uint32 kNvidiaDeviceId = 0x0fd5;  // GeForce GT 650M
     17 
     18 #define LONG_STRING_CONST(...) #__VA_ARGS__
     19 
     20 #define EXPECT_EMPTY_SET(feature_set) EXPECT_EQ(0u, feature_set.size())
     21 #define EXPECT_SINGLE_FEATURE(feature_set, feature) \
     22     EXPECT_TRUE(feature_set.size() == 1 && feature_set.count(feature) == 1)
     23 
     24 namespace gpu {
     25 
     26 enum TestFeatureType {
     27   TEST_FEATURE_0 = 1,
     28   TEST_FEATURE_1 = 1 << 2,
     29   TEST_FEATURE_2 = 1 << 3,
     30 };
     31 
     32 class GpuControlListTest : public testing::Test {
     33  public:
     34   GpuControlListTest() { }
     35 
     36   virtual ~GpuControlListTest() { }
     37 
     38   const GPUInfo& gpu_info() const {
     39     return gpu_info_;
     40   }
     41 
     42   GpuControlList* Create() {
     43     GpuControlList* rt = new GpuControlList();
     44     rt->AddSupportedFeature("test_feature_0", TEST_FEATURE_0);
     45     rt->AddSupportedFeature("test_feature_1", TEST_FEATURE_1);
     46     rt->AddSupportedFeature("test_feature_2", TEST_FEATURE_2);
     47     return rt;
     48   }
     49 
     50  protected:
     51   virtual void SetUp() {
     52     gpu_info_.gpu.vendor_id = kNvidiaVendorId;
     53     gpu_info_.gpu.device_id = 0x0640;
     54     gpu_info_.driver_vendor = "NVIDIA";
     55     gpu_info_.driver_version = "1.6.18";
     56     gpu_info_.driver_date = "7-14-2009";
     57     gpu_info_.machine_model = "MacBookPro 7.1";
     58     gpu_info_.gl_vendor = "NVIDIA Corporation";
     59     gpu_info_.gl_renderer = "NVIDIA GeForce GT 120 OpenGL Engine";
     60     gpu_info_.performance_stats.graphics = 5.0;
     61     gpu_info_.performance_stats.gaming = 5.0;
     62     gpu_info_.performance_stats.overall = 5.0;
     63   }
     64 
     65   virtual void TearDown() {
     66   }
     67 
     68  private:
     69   GPUInfo gpu_info_;
     70 };
     71 
     72 TEST_F(GpuControlListTest, DefaultControlListSettings) {
     73   scoped_ptr<GpuControlList> control_list(Create());
     74   // Default control list settings: all feature are allowed.
     75   std::set<int> features = control_list->MakeDecision(
     76       GpuControlList::kOsMacosx, kOsVersion, gpu_info());
     77   EXPECT_EMPTY_SET(features);
     78 }
     79 
     80 TEST_F(GpuControlListTest, EmptyControlList) {
     81   // Empty list: all features are allowed.
     82   const std::string empty_list_json = LONG_STRING_CONST(
     83       {
     84         "name": "gpu control list",
     85         "version": "2.5",
     86         "entries": [
     87         ]
     88       }
     89   );
     90   scoped_ptr<GpuControlList> control_list(Create());
     91 
     92   EXPECT_TRUE(control_list->LoadList(empty_list_json,
     93                                      GpuControlList::kAllOs));
     94   EXPECT_EQ("2.5", control_list->version());
     95   std::set<int> features = control_list->MakeDecision(
     96       GpuControlList::kOsMacosx, kOsVersion, gpu_info());
     97   EXPECT_EMPTY_SET(features);
     98 }
     99 
    100 TEST_F(GpuControlListTest, DetailedEntryAndInvalidJson) {
    101   // exact setting.
    102   const std::string exact_list_json = LONG_STRING_CONST(
    103       {
    104         "name": "gpu control list",
    105         "version": "0.1",
    106         "entries": [
    107           {
    108             "id": 5,
    109             "os": {
    110               "type": "macosx",
    111               "version": {
    112                 "op": "=",
    113                 "number": "10.6.4"
    114               }
    115             },
    116             "vendor_id": "0x10de",
    117             "device_id": ["0x0640"],
    118             "driver_version": {
    119               "op": "=",
    120               "number": "1.6.18"
    121             },
    122             "features": [
    123               "test_feature_0"
    124             ]
    125           }
    126         ]
    127       }
    128   );
    129   scoped_ptr<GpuControlList> control_list(Create());
    130 
    131   EXPECT_TRUE(control_list->LoadList(exact_list_json, GpuControlList::kAllOs));
    132   std::set<int> features = control_list->MakeDecision(
    133       GpuControlList::kOsMacosx, kOsVersion, gpu_info());
    134   EXPECT_SINGLE_FEATURE(features, TEST_FEATURE_0);
    135 
    136   // Invalid json input should not change the current control_list settings.
    137   const std::string invalid_json = "invalid";
    138 
    139   EXPECT_FALSE(control_list->LoadList(invalid_json, GpuControlList::kAllOs));
    140   features = control_list->MakeDecision(
    141       GpuControlList::kOsMacosx, kOsVersion, gpu_info());
    142   EXPECT_SINGLE_FEATURE(features, TEST_FEATURE_0);
    143   std::vector<uint32> entries;
    144   control_list->GetDecisionEntries(&entries, false);
    145   ASSERT_EQ(1u, entries.size());
    146   EXPECT_EQ(5u, entries[0]);
    147   EXPECT_EQ(5u, control_list->max_entry_id());
    148 }
    149 
    150 TEST_F(GpuControlListTest, VendorOnAllOsEntry) {
    151   // ControlList a vendor on all OS.
    152   const std::string vendor_json = LONG_STRING_CONST(
    153       {
    154         "name": "gpu control list",
    155         "version": "0.1",
    156         "entries": [
    157           {
    158             "id": 1,
    159             "vendor_id": "0x10de",
    160             "features": [
    161               "test_feature_0"
    162             ]
    163           }
    164         ]
    165       }
    166   );
    167   scoped_ptr<GpuControlList> control_list(Create());
    168 
    169   // ControlList entries won't be filtered to the current OS only upon loading.
    170   EXPECT_TRUE(control_list->LoadList(vendor_json, GpuControlList::kAllOs));
    171   std::set<int> features = control_list->MakeDecision(
    172       GpuControlList::kOsMacosx, kOsVersion, gpu_info());
    173   EXPECT_SINGLE_FEATURE(features, TEST_FEATURE_0);
    174   features = control_list->MakeDecision(
    175       GpuControlList::kOsWin, kOsVersion, gpu_info());
    176   EXPECT_SINGLE_FEATURE(features, TEST_FEATURE_0);
    177   features = control_list->MakeDecision(
    178       GpuControlList::kOsLinux, kOsVersion, gpu_info());
    179   EXPECT_SINGLE_FEATURE(features, TEST_FEATURE_0);
    180 #if defined(OS_WIN) || defined(OS_LINUX) || defined(OS_MACOSX) || \
    181     defined(OS_OPENBSD)
    182   // ControlList entries will be filtered to the current OS only upon loading.
    183   EXPECT_TRUE(control_list->LoadList(
    184       vendor_json, GpuControlList::kCurrentOsOnly));
    185   features = control_list->MakeDecision(
    186       GpuControlList::kOsMacosx, kOsVersion, gpu_info());
    187   EXPECT_SINGLE_FEATURE(features, TEST_FEATURE_0);
    188   features = control_list->MakeDecision(
    189       GpuControlList::kOsWin, kOsVersion, gpu_info());
    190   EXPECT_SINGLE_FEATURE(features, TEST_FEATURE_0);
    191   features = control_list->MakeDecision(
    192       GpuControlList::kOsLinux, kOsVersion, gpu_info());
    193   EXPECT_SINGLE_FEATURE(features, TEST_FEATURE_0);
    194 #endif
    195 }
    196 
    197 TEST_F(GpuControlListTest, ChromeVersionEntry) {
    198   const std::string browser_version_json = LONG_STRING_CONST(
    199       {
    200         "name": "gpu control list",
    201         "version": "0.1",
    202         "entries": [
    203           {
    204             "id": 1,
    205             "browser_version": {
    206               "op": ">=",
    207               "number": "10"
    208             },
    209             "features": [
    210               "test_feature_0"
    211             ]
    212           }
    213         ]
    214       }
    215   );
    216   scoped_ptr<GpuControlList> control_list9(Create());
    217   EXPECT_TRUE(control_list9->LoadList(
    218       "9.0", browser_version_json, GpuControlList::kAllOs));
    219   std::set<int> features = control_list9->MakeDecision(
    220       GpuControlList::kOsWin, kOsVersion, gpu_info());
    221   EXPECT_EMPTY_SET(features);
    222 
    223   scoped_ptr<GpuControlList> control_list10(Create());
    224   EXPECT_TRUE(control_list10->LoadList(
    225       "10.0", browser_version_json, GpuControlList::kAllOs));
    226   features = control_list10->MakeDecision(
    227       GpuControlList::kOsWin, kOsVersion, gpu_info());
    228   EXPECT_SINGLE_FEATURE(features, TEST_FEATURE_0);
    229 }
    230 
    231 TEST_F(GpuControlListTest, UnknownField) {
    232   const std::string unknown_field_json = LONG_STRING_CONST(
    233       {
    234         "name": "gpu control list",
    235         "version": "0.1",
    236         "entries": [
    237           {
    238             "id": 1,
    239             "unknown_field": 0,
    240             "features": [
    241               "test_feature_1"
    242             ]
    243           },
    244           {
    245             "id": 2,
    246             "features": [
    247               "test_feature_0"
    248             ]
    249           }
    250         ]
    251       }
    252   );
    253   scoped_ptr<GpuControlList> control_list(Create());
    254 
    255   EXPECT_TRUE(control_list->LoadList(
    256       unknown_field_json, GpuControlList::kAllOs));
    257   EXPECT_EQ(1u, control_list->num_entries());
    258   EXPECT_TRUE(control_list->contains_unknown_fields());
    259   std::set<int> features = control_list->MakeDecision(
    260       GpuControlList::kOsWin, kOsVersion, gpu_info());
    261   EXPECT_SINGLE_FEATURE(features, TEST_FEATURE_0);
    262 }
    263 
    264 TEST_F(GpuControlListTest, UnknownExceptionField) {
    265   const std::string unknown_exception_field_json = LONG_STRING_CONST(
    266       {
    267         "name": "gpu control list",
    268         "version": "0.1",
    269         "entries": [
    270           {
    271             "id": 1,
    272             "unknown_field": 0,
    273             "features": [
    274               "test_feature_2"
    275             ]
    276           },
    277           {
    278             "id": 2,
    279             "exceptions": [
    280               {
    281                 "unknown_field": 0
    282               }
    283             ],
    284             "features": [
    285               "test_feature_1"
    286             ]
    287           },
    288           {
    289             "id": 3,
    290             "features": [
    291               "test_feature_0"
    292             ]
    293           }
    294         ]
    295       }
    296   );
    297   scoped_ptr<GpuControlList> control_list(Create());
    298 
    299   EXPECT_TRUE(control_list->LoadList(
    300       unknown_exception_field_json, GpuControlList::kAllOs));
    301   EXPECT_EQ(1u, control_list->num_entries());
    302   EXPECT_TRUE(control_list->contains_unknown_fields());
    303   std::set<int> features = control_list->MakeDecision(
    304       GpuControlList::kOsWin, kOsVersion, gpu_info());
    305   EXPECT_SINGLE_FEATURE(features, TEST_FEATURE_0);
    306 }
    307 
    308 TEST_F(GpuControlListTest, DisabledEntry) {
    309   const std::string disabled_json = LONG_STRING_CONST(
    310       {
    311         "name": "gpu control list",
    312         "version": "0.1",
    313         "entries": [
    314           {
    315             "id": 1,
    316             "disabled": true,
    317             "features": [
    318               "test_feature_0"
    319             ]
    320           }
    321         ]
    322       }
    323   );
    324   scoped_ptr<GpuControlList> control_list(Create());
    325   EXPECT_TRUE(control_list->LoadList(disabled_json, GpuControlList::kAllOs));
    326   std::set<int> features = control_list->MakeDecision(
    327       GpuControlList::kOsWin, kOsVersion, gpu_info());
    328   EXPECT_EMPTY_SET(features);
    329   std::vector<uint32> flag_entries;
    330   control_list->GetDecisionEntries(&flag_entries, false);
    331   EXPECT_EQ(0u, flag_entries.size());
    332   control_list->GetDecisionEntries(&flag_entries, true);
    333   EXPECT_EQ(1u, flag_entries.size());
    334 }
    335 
    336 TEST_F(GpuControlListTest, NeedsMoreInfoForExceptions) {
    337   const std::string json = LONG_STRING_CONST(
    338       {
    339         "name": "gpu control list",
    340         "version": "0.1",
    341         "entries": [
    342           {
    343             "id": 1,
    344             "os": {
    345               "type": "linux"
    346             },
    347             "vendor_id": "0x8086",
    348             "exceptions": [
    349               {
    350                 "gl_renderer": {
    351                   "op": "contains",
    352                   "value": "mesa"
    353                 }
    354               }
    355             ],
    356             "features": [
    357               "test_feature_0"
    358             ]
    359           }
    360         ]
    361       }
    362   );
    363   GPUInfo gpu_info;
    364   gpu_info.gpu.vendor_id = kIntelVendorId;
    365 
    366   scoped_ptr<GpuControlList> control_list(Create());
    367   EXPECT_TRUE(control_list->LoadList(json, GpuControlList::kAllOs));
    368 
    369   // The case this entry does not apply.
    370   std::set<int> features = control_list->MakeDecision(
    371       GpuControlList::kOsMacosx, kOsVersion, gpu_info);
    372   EXPECT_EMPTY_SET(features);
    373   EXPECT_FALSE(control_list->needs_more_info());
    374 
    375   // The case this entry might apply, but need more info.
    376   features = control_list->MakeDecision(
    377       GpuControlList::kOsLinux, kOsVersion, gpu_info);
    378   EXPECT_EMPTY_SET(features);
    379   EXPECT_TRUE(control_list->needs_more_info());
    380 
    381   // The case we have full info, and the exception applies (so the entry
    382   // does not apply).
    383   gpu_info.gl_renderer = "mesa";
    384   features = control_list->MakeDecision(
    385       GpuControlList::kOsLinux, kOsVersion, gpu_info);
    386   EXPECT_EMPTY_SET(features);
    387   EXPECT_FALSE(control_list->needs_more_info());
    388 
    389   // The case we have full info, and this entry applies.
    390   gpu_info.gl_renderer = "my renderer";
    391   features = control_list->MakeDecision(GpuControlList::kOsLinux, kOsVersion,
    392       gpu_info);
    393   EXPECT_SINGLE_FEATURE(features, TEST_FEATURE_0);
    394   EXPECT_FALSE(control_list->needs_more_info());
    395 }
    396 
    397 TEST_F(GpuControlListTest, IgnorableEntries) {
    398   // If an entry will not change the control_list decisions, then it should not
    399   // trigger the needs_more_info flag.
    400   const std::string json = LONG_STRING_CONST(
    401       {
    402         "name": "gpu control list",
    403         "version": "0.1",
    404         "entries": [
    405           {
    406             "id": 1,
    407             "os": {
    408               "type": "linux"
    409             },
    410             "vendor_id": "0x8086",
    411             "features": [
    412               "test_feature_0"
    413             ]
    414           },
    415           {
    416             "id": 2,
    417             "os": {
    418               "type": "linux"
    419             },
    420             "vendor_id": "0x8086",
    421             "driver_version": {
    422               "op": "<",
    423               "number": "10.7"
    424             },
    425             "features": [
    426               "test_feature_0"
    427             ]
    428           }
    429         ]
    430       }
    431   );
    432   GPUInfo gpu_info;
    433   gpu_info.gpu.vendor_id = kIntelVendorId;
    434 
    435   scoped_ptr<GpuControlList> control_list(Create());
    436   EXPECT_TRUE(control_list->LoadList(json, GpuControlList::kAllOs));
    437   std::set<int> features = control_list->MakeDecision(
    438       GpuControlList::kOsLinux, kOsVersion, gpu_info);
    439   EXPECT_SINGLE_FEATURE(features, TEST_FEATURE_0);
    440   EXPECT_FALSE(control_list->needs_more_info());
    441 }
    442 
    443 TEST_F(GpuControlListTest, ExceptionWithoutVendorId) {
    444   const std::string json = LONG_STRING_CONST(
    445       {
    446         "name": "gpu control list",
    447         "version": "0.1",
    448         "entries": [
    449           {
    450             "id": 1,
    451             "os": {
    452               "type": "linux"
    453             },
    454             "vendor_id": "0x8086",
    455             "exceptions": [
    456               {
    457                 "device_id": ["0x2a06"],
    458                 "driver_version": {
    459                   "op": ">=",
    460                   "number": "8.1"
    461                 }
    462               },
    463               {
    464                 "device_id": ["0x2a02"],
    465                 "driver_version": {
    466                   "op": ">=",
    467                   "number": "9.1"
    468                 }
    469               }
    470             ],
    471             "features": [
    472               "test_feature_0"
    473             ]
    474           }
    475         ]
    476       }
    477   );
    478   GPUInfo gpu_info;
    479   gpu_info.gpu.vendor_id = kIntelVendorId;
    480   gpu_info.gpu.device_id = 0x2a02;
    481   gpu_info.driver_version = "9.1";
    482 
    483   scoped_ptr<GpuControlList> control_list(Create());
    484   EXPECT_TRUE(control_list->LoadList(json, GpuControlList::kAllOs));
    485 
    486   std::set<int> features = control_list->MakeDecision(
    487       GpuControlList::kOsLinux, kOsVersion, gpu_info);
    488   EXPECT_EMPTY_SET(features);
    489 
    490   gpu_info.driver_version = "9.0";
    491   features = control_list->MakeDecision(
    492       GpuControlList::kOsLinux, kOsVersion, gpu_info);
    493   EXPECT_SINGLE_FEATURE(features, TEST_FEATURE_0);
    494 }
    495 
    496 }  // namespace gpu
    497 
    498