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.
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"
12 const char kOsVersion
[] = "10.6.4";
13 const uint32 kIntelVendorId
= 0x8086;
14 const uint32 kNvidiaVendorId
= 0x10de;
15 const uint32 kAmdVendorId
= 0x10de;
17 #define LONG_STRING_CONST(...) #__VA_ARGS__
19 #define EXPECT_EMPTY_SET(feature_set) EXPECT_EQ(0u, feature_set.size())
20 #define EXPECT_SINGLE_FEATURE(feature_set, feature) \
21 EXPECT_TRUE(feature_set.size() == 1 && feature_set.count(feature) == 1)
25 enum TestFeatureType
{
27 TEST_FEATURE_1
= 1 << 2,
28 TEST_FEATURE_2
= 1 << 3,
31 class GpuControlListTest
: public testing::Test
{
33 GpuControlListTest() { }
35 virtual ~GpuControlListTest() { }
37 const GPUInfo
& gpu_info() const {
41 GpuControlList
* Create() {
42 GpuControlList
* rt
= new GpuControlList();
43 rt
->AddSupportedFeature("test_feature_0", TEST_FEATURE_0
);
44 rt
->AddSupportedFeature("test_feature_1", TEST_FEATURE_1
);
45 rt
->AddSupportedFeature("test_feature_2", TEST_FEATURE_2
);
50 virtual void SetUp() {
51 gpu_info_
.gpu
.vendor_id
= kNvidiaVendorId
;
52 gpu_info_
.gpu
.device_id
= 0x0640;
53 gpu_info_
.driver_vendor
= "NVIDIA";
54 gpu_info_
.driver_version
= "1.6.18";
55 gpu_info_
.driver_date
= "7-14-2009";
56 gpu_info_
.machine_model_name
= "MacBookPro";
57 gpu_info_
.machine_model_version
= "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;
65 virtual void TearDown() {
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
);
80 TEST_F(GpuControlListTest
, EmptyControlList
) {
81 // Empty list: all features are allowed.
82 const std::string empty_list_json
= LONG_STRING_CONST(
84 "name": "gpu control list",
90 scoped_ptr
<GpuControlList
> control_list(Create());
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
);
100 TEST_F(GpuControlListTest
, DetailedEntryAndInvalidJson
) {
102 const std::string exact_list_json
= LONG_STRING_CONST(
104 "name": "gpu control list",
116 "vendor_id": "0x10de",
117 "device_id": ["0x0640"],
129 scoped_ptr
<GpuControlList
> control_list(Create());
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
);
136 // Invalid json input should not change the current control_list settings.
137 const std::string invalid_json
= "invalid";
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());
150 TEST_F(GpuControlListTest
, VendorOnAllOsEntry
) {
151 // ControlList a vendor on all OS.
152 const std::string vendor_json
= LONG_STRING_CONST(
154 "name": "gpu control list",
159 "vendor_id": "0x10de",
167 scoped_ptr
<GpuControlList
> control_list(Create());
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) || \
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
);
197 TEST_F(GpuControlListTest
, UnknownField
) {
198 const std::string unknown_field_json
= LONG_STRING_CONST(
200 "name": "gpu control list",
219 scoped_ptr
<GpuControlList
> control_list(Create());
221 EXPECT_FALSE(control_list
->LoadList(
222 unknown_field_json
, GpuControlList::kAllOs
));
225 TEST_F(GpuControlListTest
, UnknownExceptionField
) {
226 const std::string unknown_exception_field_json
= LONG_STRING_CONST(
228 "name": "gpu control list",
258 scoped_ptr
<GpuControlList
> control_list(Create());
260 EXPECT_FALSE(control_list
->LoadList(
261 unknown_exception_field_json
, GpuControlList::kAllOs
));
264 TEST_F(GpuControlListTest
, DisabledEntry
) {
265 const std::string disabled_json
= LONG_STRING_CONST(
267 "name": "gpu control list",
280 scoped_ptr
<GpuControlList
> control_list(Create());
281 EXPECT_TRUE(control_list
->LoadList(disabled_json
, GpuControlList::kAllOs
));
282 std::set
<int> features
= control_list
->MakeDecision(
283 GpuControlList::kOsWin
, kOsVersion
, gpu_info());
284 EXPECT_EMPTY_SET(features
);
285 std::vector
<uint32
> flag_entries
;
286 control_list
->GetDecisionEntries(&flag_entries
, false);
287 EXPECT_EQ(0u, flag_entries
.size());
288 control_list
->GetDecisionEntries(&flag_entries
, true);
289 EXPECT_EQ(1u, flag_entries
.size());
292 TEST_F(GpuControlListTest
, NeedsMoreInfoForExceptions
) {
293 const std::string json
= LONG_STRING_CONST(
295 "name": "gpu control list",
303 "vendor_id": "0x8086",
320 gpu_info
.gpu
.vendor_id
= kIntelVendorId
;
322 scoped_ptr
<GpuControlList
> control_list(Create());
323 EXPECT_TRUE(control_list
->LoadList(json
, GpuControlList::kAllOs
));
325 // The case this entry does not apply.
326 std::set
<int> features
= control_list
->MakeDecision(
327 GpuControlList::kOsMacosx
, kOsVersion
, gpu_info
);
328 EXPECT_EMPTY_SET(features
);
329 EXPECT_FALSE(control_list
->needs_more_info());
331 // The case this entry might apply, but need more info.
332 features
= control_list
->MakeDecision(
333 GpuControlList::kOsLinux
, kOsVersion
, gpu_info
);
334 EXPECT_EMPTY_SET(features
);
335 EXPECT_TRUE(control_list
->needs_more_info());
337 // The case we have full info, and the exception applies (so the entry
339 gpu_info
.gl_renderer
= "mesa";
340 features
= control_list
->MakeDecision(
341 GpuControlList::kOsLinux
, kOsVersion
, gpu_info
);
342 EXPECT_EMPTY_SET(features
);
343 EXPECT_FALSE(control_list
->needs_more_info());
345 // The case we have full info, and this entry applies.
346 gpu_info
.gl_renderer
= "my renderer";
347 features
= control_list
->MakeDecision(GpuControlList::kOsLinux
, kOsVersion
,
349 EXPECT_SINGLE_FEATURE(features
, TEST_FEATURE_0
);
350 EXPECT_FALSE(control_list
->needs_more_info());
353 TEST_F(GpuControlListTest
, IgnorableEntries
) {
354 // If an entry will not change the control_list decisions, then it should not
355 // trigger the needs_more_info flag.
356 const std::string json
= LONG_STRING_CONST(
358 "name": "gpu control list",
366 "vendor_id": "0x8086",
376 "vendor_id": "0x8086",
389 gpu_info
.gpu
.vendor_id
= kIntelVendorId
;
391 scoped_ptr
<GpuControlList
> control_list(Create());
392 EXPECT_TRUE(control_list
->LoadList(json
, GpuControlList::kAllOs
));
393 std::set
<int> features
= control_list
->MakeDecision(
394 GpuControlList::kOsLinux
, kOsVersion
, gpu_info
);
395 EXPECT_SINGLE_FEATURE(features
, TEST_FEATURE_0
);
396 EXPECT_FALSE(control_list
->needs_more_info());
399 TEST_F(GpuControlListTest
, ExceptionWithoutVendorId
) {
400 const std::string json
= LONG_STRING_CONST(
402 "name": "gpu control list",
410 "vendor_id": "0x8086",
413 "device_id": ["0x2a06"],
420 "device_id": ["0x2a02"],
435 gpu_info
.gpu
.vendor_id
= kIntelVendorId
;
436 gpu_info
.gpu
.device_id
= 0x2a02;
437 gpu_info
.driver_version
= "9.1";
439 scoped_ptr
<GpuControlList
> control_list(Create());
440 EXPECT_TRUE(control_list
->LoadList(json
, GpuControlList::kAllOs
));
442 std::set
<int> features
= control_list
->MakeDecision(
443 GpuControlList::kOsLinux
, kOsVersion
, gpu_info
);
444 EXPECT_EMPTY_SET(features
);
446 gpu_info
.driver_version
= "9.0";
447 features
= control_list
->MakeDecision(
448 GpuControlList::kOsLinux
, kOsVersion
, gpu_info
);
449 EXPECT_SINGLE_FEATURE(features
, TEST_FEATURE_0
);
452 TEST_F(GpuControlListTest
, AMDSwitchable
) {
454 gpu_info
.amd_switchable
= true;
455 gpu_info
.gpu
.vendor_id
= kAmdVendorId
;
456 gpu_info
.gpu
.device_id
= 0x6760;
457 GPUInfo::GPUDevice integrated_gpu
;
458 integrated_gpu
.vendor_id
= kIntelVendorId
;
459 integrated_gpu
.device_id
= 0x0116;
460 gpu_info
.secondary_gpus
.push_back(integrated_gpu
);
462 { // amd_switchable_discrete entry
463 const std::string json
= LONG_STRING_CONST(
465 "name": "gpu control list",
473 "multi_gpu_style": "amd_switchable_discrete",
482 scoped_ptr
<GpuControlList
> control_list(Create());
483 EXPECT_TRUE(control_list
->LoadList(json
, GpuControlList::kAllOs
));
485 // Integrated GPU is active
486 gpu_info
.gpu
.active
= false;
487 gpu_info
.secondary_gpus
[0].active
= true;
488 std::set
<int> features
= control_list
->MakeDecision(
489 GpuControlList::kOsWin
, kOsVersion
, gpu_info
);
490 EXPECT_EMPTY_SET(features
);
492 // Discrete GPU is active
493 gpu_info
.gpu
.active
= true;
494 gpu_info
.secondary_gpus
[0].active
= false;
495 features
= control_list
->MakeDecision(
496 GpuControlList::kOsWin
, kOsVersion
, gpu_info
);
497 EXPECT_SINGLE_FEATURE(features
, TEST_FEATURE_0
);
500 { // amd_switchable_integrated entry
501 const std::string json
= LONG_STRING_CONST(
503 "name": "gpu control list",
511 "multi_gpu_style": "amd_switchable_integrated",
520 scoped_ptr
<GpuControlList
> control_list(Create());
521 EXPECT_TRUE(control_list
->LoadList(json
, GpuControlList::kAllOs
));
523 // Discrete GPU is active
524 gpu_info
.gpu
.active
= true;
525 gpu_info
.secondary_gpus
[0].active
= false;
526 std::set
<int> features
= control_list
->MakeDecision(
527 GpuControlList::kOsWin
, kOsVersion
, gpu_info
);
528 EXPECT_EMPTY_SET(features
);
530 // Integrated GPU is active
531 gpu_info
.gpu
.active
= false;
532 gpu_info
.secondary_gpus
[0].active
= true;
533 features
= control_list
->MakeDecision(
534 GpuControlList::kOsWin
, kOsVersion
, gpu_info
);
535 EXPECT_SINGLE_FEATURE(features
, TEST_FEATURE_0
);
537 // For non AMD switchable
538 gpu_info
.amd_switchable
= false;
539 features
= control_list
->MakeDecision(
540 GpuControlList::kOsWin
, kOsVersion
, gpu_info
);
541 EXPECT_EMPTY_SET(features
);