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 ~GpuControlListTest() override
{}
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 void SetUp() override
{
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";
62 void TearDown() override
{}
68 TEST_F(GpuControlListTest
, DefaultControlListSettings
) {
69 scoped_ptr
<GpuControlList
> control_list(Create());
70 // Default control list settings: all feature are allowed.
71 std::set
<int> features
= control_list
->MakeDecision(
72 GpuControlList::kOsMacosx
, kOsVersion
, gpu_info());
73 EXPECT_EMPTY_SET(features
);
76 TEST_F(GpuControlListTest
, EmptyControlList
) {
77 // Empty list: all features are allowed.
78 const std::string empty_list_json
= LONG_STRING_CONST(
80 "name": "gpu control list",
86 scoped_ptr
<GpuControlList
> control_list(Create());
88 EXPECT_TRUE(control_list
->LoadList(empty_list_json
,
89 GpuControlList::kAllOs
));
90 EXPECT_EQ("2.5", control_list
->version());
91 std::set
<int> features
= control_list
->MakeDecision(
92 GpuControlList::kOsMacosx
, kOsVersion
, gpu_info());
93 EXPECT_EMPTY_SET(features
);
96 TEST_F(GpuControlListTest
, DetailedEntryAndInvalidJson
) {
98 const std::string exact_list_json
= LONG_STRING_CONST(
100 "name": "gpu control list",
112 "vendor_id": "0x10de",
113 "device_id": ["0x0640"],
125 scoped_ptr
<GpuControlList
> control_list(Create());
127 EXPECT_TRUE(control_list
->LoadList(exact_list_json
, GpuControlList::kAllOs
));
128 std::set
<int> features
= control_list
->MakeDecision(
129 GpuControlList::kOsMacosx
, kOsVersion
, gpu_info());
130 EXPECT_SINGLE_FEATURE(features
, TEST_FEATURE_0
);
132 // Invalid json input should not change the current control_list settings.
133 const std::string invalid_json
= "invalid";
135 EXPECT_FALSE(control_list
->LoadList(invalid_json
, GpuControlList::kAllOs
));
136 features
= control_list
->MakeDecision(
137 GpuControlList::kOsMacosx
, kOsVersion
, gpu_info());
138 EXPECT_SINGLE_FEATURE(features
, TEST_FEATURE_0
);
139 std::vector
<uint32
> entries
;
140 control_list
->GetDecisionEntries(&entries
, false);
141 ASSERT_EQ(1u, entries
.size());
142 EXPECT_EQ(5u, entries
[0]);
143 EXPECT_EQ(5u, control_list
->max_entry_id());
146 TEST_F(GpuControlListTest
, VendorOnAllOsEntry
) {
147 // ControlList a vendor on all OS.
148 const std::string vendor_json
= LONG_STRING_CONST(
150 "name": "gpu control list",
155 "vendor_id": "0x10de",
163 scoped_ptr
<GpuControlList
> control_list(Create());
165 // ControlList entries won't be filtered to the current OS only upon loading.
166 EXPECT_TRUE(control_list
->LoadList(vendor_json
, GpuControlList::kAllOs
));
167 std::set
<int> features
= control_list
->MakeDecision(
168 GpuControlList::kOsMacosx
, kOsVersion
, gpu_info());
169 EXPECT_SINGLE_FEATURE(features
, TEST_FEATURE_0
);
170 features
= control_list
->MakeDecision(
171 GpuControlList::kOsWin
, kOsVersion
, gpu_info());
172 EXPECT_SINGLE_FEATURE(features
, TEST_FEATURE_0
);
173 features
= control_list
->MakeDecision(
174 GpuControlList::kOsLinux
, kOsVersion
, gpu_info());
175 EXPECT_SINGLE_FEATURE(features
, TEST_FEATURE_0
);
176 #if defined(OS_WIN) || defined(OS_LINUX) || defined(OS_MACOSX) || \
178 // ControlList entries will be filtered to the current OS only upon loading.
179 EXPECT_TRUE(control_list
->LoadList(
180 vendor_json
, GpuControlList::kCurrentOsOnly
));
181 features
= control_list
->MakeDecision(
182 GpuControlList::kOsMacosx
, kOsVersion
, gpu_info());
183 EXPECT_SINGLE_FEATURE(features
, TEST_FEATURE_0
);
184 features
= control_list
->MakeDecision(
185 GpuControlList::kOsWin
, kOsVersion
, gpu_info());
186 EXPECT_SINGLE_FEATURE(features
, TEST_FEATURE_0
);
187 features
= control_list
->MakeDecision(
188 GpuControlList::kOsLinux
, kOsVersion
, gpu_info());
189 EXPECT_SINGLE_FEATURE(features
, TEST_FEATURE_0
);
193 TEST_F(GpuControlListTest
, UnknownField
) {
194 const std::string unknown_field_json
= LONG_STRING_CONST(
196 "name": "gpu control list",
215 scoped_ptr
<GpuControlList
> control_list(Create());
217 EXPECT_FALSE(control_list
->LoadList(
218 unknown_field_json
, GpuControlList::kAllOs
));
221 TEST_F(GpuControlListTest
, UnknownExceptionField
) {
222 const std::string unknown_exception_field_json
= LONG_STRING_CONST(
224 "name": "gpu control list",
254 scoped_ptr
<GpuControlList
> control_list(Create());
256 EXPECT_FALSE(control_list
->LoadList(
257 unknown_exception_field_json
, GpuControlList::kAllOs
));
260 TEST_F(GpuControlListTest
, DisabledEntry
) {
261 const std::string disabled_json
= LONG_STRING_CONST(
263 "name": "gpu control list",
276 scoped_ptr
<GpuControlList
> control_list(Create());
277 EXPECT_TRUE(control_list
->LoadList(disabled_json
, GpuControlList::kAllOs
));
278 std::set
<int> features
= control_list
->MakeDecision(
279 GpuControlList::kOsWin
, kOsVersion
, gpu_info());
280 EXPECT_EMPTY_SET(features
);
281 std::vector
<uint32
> flag_entries
;
282 control_list
->GetDecisionEntries(&flag_entries
, false);
283 EXPECT_EQ(0u, flag_entries
.size());
284 control_list
->GetDecisionEntries(&flag_entries
, true);
285 EXPECT_EQ(1u, flag_entries
.size());
288 TEST_F(GpuControlListTest
, NeedsMoreInfo
) {
289 const std::string json
= LONG_STRING_CONST(
291 "name": "gpu control list",
299 "vendor_id": "0x10de",
312 gpu_info
.gpu
.vendor_id
= kNvidiaVendorId
;
314 scoped_ptr
<GpuControlList
> control_list(Create());
315 EXPECT_TRUE(control_list
->LoadList(json
, GpuControlList::kAllOs
));
317 std::set
<int> features
= control_list
->MakeDecision(
318 GpuControlList::kOsWin
, kOsVersion
, gpu_info
);
319 EXPECT_EMPTY_SET(features
);
320 EXPECT_TRUE(control_list
->needs_more_info());
321 std::vector
<uint32
> decision_entries
;
322 control_list
->GetDecisionEntries(&decision_entries
, false);
323 EXPECT_EQ(0u, decision_entries
.size());
325 gpu_info
.driver_version
= "11";
326 features
= control_list
->MakeDecision(
327 GpuControlList::kOsWin
, kOsVersion
, gpu_info
);
328 EXPECT_SINGLE_FEATURE(features
, TEST_FEATURE_0
);
329 EXPECT_FALSE(control_list
->needs_more_info());
330 control_list
->GetDecisionEntries(&decision_entries
, false);
331 EXPECT_EQ(1u, decision_entries
.size());
334 TEST_F(GpuControlListTest
, NeedsMoreInfoForExceptions
) {
335 const std::string json
= LONG_STRING_CONST(
337 "name": "gpu control list",
345 "vendor_id": "0x8086",
348 "gl_renderer": ".*mesa.*"
359 gpu_info
.gpu
.vendor_id
= kIntelVendorId
;
361 scoped_ptr
<GpuControlList
> control_list(Create());
362 EXPECT_TRUE(control_list
->LoadList(json
, GpuControlList::kAllOs
));
364 // The case this entry does not apply.
365 std::set
<int> features
= control_list
->MakeDecision(
366 GpuControlList::kOsMacosx
, kOsVersion
, gpu_info
);
367 EXPECT_EMPTY_SET(features
);
368 EXPECT_FALSE(control_list
->needs_more_info());
370 // The case this entry might apply, but need more info.
371 features
= control_list
->MakeDecision(
372 GpuControlList::kOsLinux
, kOsVersion
, gpu_info
);
373 // Ignore exceptions if main entry info matches
374 EXPECT_SINGLE_FEATURE(features
, TEST_FEATURE_0
);
375 EXPECT_TRUE(control_list
->needs_more_info());
377 // The case we have full info, and the exception applies (so the entry
379 gpu_info
.gl_renderer
= "mesa";
380 features
= control_list
->MakeDecision(
381 GpuControlList::kOsLinux
, kOsVersion
, gpu_info
);
382 EXPECT_EMPTY_SET(features
);
383 EXPECT_FALSE(control_list
->needs_more_info());
385 // The case we have full info, and this entry applies.
386 gpu_info
.gl_renderer
= "my renderer";
387 features
= control_list
->MakeDecision(GpuControlList::kOsLinux
, kOsVersion
,
389 EXPECT_SINGLE_FEATURE(features
, TEST_FEATURE_0
);
390 EXPECT_FALSE(control_list
->needs_more_info());
393 TEST_F(GpuControlListTest
, IgnorableEntries
) {
394 // If an entry will not change the control_list decisions, then it should not
395 // trigger the needs_more_info flag.
396 const std::string json
= LONG_STRING_CONST(
398 "name": "gpu control list",
406 "vendor_id": "0x8086",
416 "vendor_id": "0x8086",
429 gpu_info
.gpu
.vendor_id
= kIntelVendorId
;
431 scoped_ptr
<GpuControlList
> control_list(Create());
432 EXPECT_TRUE(control_list
->LoadList(json
, GpuControlList::kAllOs
));
433 std::set
<int> features
= control_list
->MakeDecision(
434 GpuControlList::kOsLinux
, kOsVersion
, gpu_info
);
435 EXPECT_SINGLE_FEATURE(features
, TEST_FEATURE_0
);
436 EXPECT_FALSE(control_list
->needs_more_info());
439 TEST_F(GpuControlListTest
, ExceptionWithoutVendorId
) {
440 const std::string json
= LONG_STRING_CONST(
442 "name": "gpu control list",
450 "vendor_id": "0x8086",
453 "device_id": ["0x2a06"],
460 "device_id": ["0x2a02"],
475 gpu_info
.gpu
.vendor_id
= kIntelVendorId
;
476 gpu_info
.gpu
.device_id
= 0x2a02;
477 gpu_info
.driver_version
= "9.1";
479 scoped_ptr
<GpuControlList
> control_list(Create());
480 EXPECT_TRUE(control_list
->LoadList(json
, GpuControlList::kAllOs
));
482 std::set
<int> features
= control_list
->MakeDecision(
483 GpuControlList::kOsLinux
, kOsVersion
, gpu_info
);
484 EXPECT_EMPTY_SET(features
);
486 gpu_info
.driver_version
= "9.0";
487 features
= control_list
->MakeDecision(
488 GpuControlList::kOsLinux
, kOsVersion
, gpu_info
);
489 EXPECT_SINGLE_FEATURE(features
, TEST_FEATURE_0
);
492 TEST_F(GpuControlListTest
, AMDSwitchable
) {
494 gpu_info
.amd_switchable
= true;
495 gpu_info
.gpu
.vendor_id
= kAmdVendorId
;
496 gpu_info
.gpu
.device_id
= 0x6760;
497 GPUInfo::GPUDevice integrated_gpu
;
498 integrated_gpu
.vendor_id
= kIntelVendorId
;
499 integrated_gpu
.device_id
= 0x0116;
500 gpu_info
.secondary_gpus
.push_back(integrated_gpu
);
502 { // amd_switchable_discrete entry
503 const std::string json
= LONG_STRING_CONST(
505 "name": "gpu control list",
513 "multi_gpu_style": "amd_switchable_discrete",
522 scoped_ptr
<GpuControlList
> control_list(Create());
523 EXPECT_TRUE(control_list
->LoadList(json
, GpuControlList::kAllOs
));
525 // Integrated GPU is active
526 gpu_info
.gpu
.active
= false;
527 gpu_info
.secondary_gpus
[0].active
= true;
528 std::set
<int> features
= control_list
->MakeDecision(
529 GpuControlList::kOsWin
, kOsVersion
, gpu_info
);
530 EXPECT_EMPTY_SET(features
);
532 // Discrete GPU is active
533 gpu_info
.gpu
.active
= true;
534 gpu_info
.secondary_gpus
[0].active
= false;
535 features
= control_list
->MakeDecision(
536 GpuControlList::kOsWin
, kOsVersion
, gpu_info
);
537 EXPECT_SINGLE_FEATURE(features
, TEST_FEATURE_0
);
540 { // amd_switchable_integrated entry
541 const std::string json
= LONG_STRING_CONST(
543 "name": "gpu control list",
551 "multi_gpu_style": "amd_switchable_integrated",
560 scoped_ptr
<GpuControlList
> control_list(Create());
561 EXPECT_TRUE(control_list
->LoadList(json
, GpuControlList::kAllOs
));
563 // Discrete GPU is active
564 gpu_info
.gpu
.active
= true;
565 gpu_info
.secondary_gpus
[0].active
= false;
566 std::set
<int> features
= control_list
->MakeDecision(
567 GpuControlList::kOsWin
, kOsVersion
, gpu_info
);
568 EXPECT_EMPTY_SET(features
);
570 // Integrated GPU is active
571 gpu_info
.gpu
.active
= false;
572 gpu_info
.secondary_gpus
[0].active
= true;
573 features
= control_list
->MakeDecision(
574 GpuControlList::kOsWin
, kOsVersion
, gpu_info
);
575 EXPECT_SINGLE_FEATURE(features
, TEST_FEATURE_0
);
577 // For non AMD switchable
578 gpu_info
.amd_switchable
= false;
579 features
= control_list
->MakeDecision(
580 GpuControlList::kOsWin
, kOsVersion
, gpu_info
);
581 EXPECT_EMPTY_SET(features
);
585 TEST_F(GpuControlListTest
, DisabledExtensionTest
) {
587 const std::string exact_list_json
= LONG_STRING_CONST(
589 "name": "gpu control list",
597 "disabled_extensions": [
607 "disabled_extensions": [
615 scoped_ptr
<GpuControlList
> control_list(Create());
617 EXPECT_TRUE(control_list
->LoadList(exact_list_json
, GpuControlList::kAllOs
));
619 control_list
->MakeDecision(GpuControlList::kOsWin
, kOsVersion
, gpu_info
);
621 std::vector
<std::string
> disabled_extensions
=
622 control_list
->GetDisabledExtensions();
624 ASSERT_EQ(3u, disabled_extensions
.size());
625 ASSERT_STREQ("test_extension1", disabled_extensions
[0].c_str());
626 ASSERT_STREQ("test_extension2", disabled_extensions
[1].c_str());
627 ASSERT_STREQ("test_extension3", disabled_extensions
[2].c_str());