blob: c42146675788224addf2eabf193a912dc2f32da1 [file] [log] [blame]
# Copyright 2016 The Chromium Authors
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
import os
import sys
from typing import Any, List, Optional, Union
import unittest
import six
import dataclasses # Built-in, but pylint gives an ordering false positive.
from gpu_tests import common_typing as ct
from gpu_tests import constants
from gpu_tests import gpu_integration_test
from gpu_tests import overlay_support
from gpu_tests.util import host_information
from telemetry.internal.platform import gpu_info as gi
@dataclasses.dataclass
class InfoCollectionTestArgs():
"""Struct-like class for passing args to an InfoCollection test."""
expected_vendor_id_str: Optional[str] = None
expected_device_id_strs: Optional[List[str]] = None
gpu: Optional[gi.GPUInfo] = None
class InfoCollectionTest(gpu_integration_test.GpuIntegrationTest):
@classmethod
def Name(cls) -> str:
return 'info_collection'
@classmethod
def AddCommandlineArgs(cls, parser: ct.CmdArgParser) -> None:
super(InfoCollectionTest, cls).AddCommandlineArgs(parser)
parser.add_argument(
'--expected-device-id',
action='append',
dest='expected_device_ids',
default=[],
help='The expected device id. Can be specified multiple times.')
parser.add_argument('--expected-vendor-id', help='The expected vendor id')
@classmethod
def GenerateGpuTests(cls, options: ct.ParsedCmdArgs) -> ct.TestGenerator:
yield ('InfoCollection_basic', '_', [
'_RunBasicTest',
InfoCollectionTestArgs(
expected_vendor_id_str=options.expected_vendor_id,
expected_device_id_strs=options.expected_device_ids)
])
yield ('InfoCollection_direct_composition', '_',
['_RunDirectCompositionTest',
InfoCollectionTestArgs()])
yield ('InfoCollection_dx12_vulkan', '_',
['_RunDX12VulkanTest',
InfoCollectionTestArgs()])
yield ('InfoCollection_asan_info_surfaced', '_',
['_RunAsanInfoTest', InfoCollectionTestArgs()])
yield ('InfoCollection_clang_coverage_info_surfaced', '_',
['_RunClangCoverageInfoTest',
InfoCollectionTestArgs()])
yield ('InfoCollection_host_information_matches_browser', '_', [
'_RunHostInformationTest',
InfoCollectionTestArgs(
expected_vendor_id_str=options.expected_vendor_id,
expected_device_id_strs=options.expected_device_ids)
])
@classmethod
def SetUpProcess(cls) -> None:
super(cls, InfoCollectionTest).SetUpProcess()
cls.CustomizeBrowserArgs([])
cls.StartBrowser()
def RunActualGpuTest(self, test_path: str, args: ct.TestArgs) -> None:
del test_path # Unused in this particular GPU test.
# Make sure the GPU process is started
self.tab.action_runner.Navigate('chrome:gpu')
# Gather the IDs detected by the GPU process
system_info = self.browser.GetSystemInfo()
if not system_info:
self.fail("Browser doesn't support GetSystemInfo")
assert len(args) == 2
test_func = args[0]
test_args = args[1]
test_args.gpu = system_info.gpu
getattr(self, test_func)(test_args)
######################################
# Helper functions for the tests below
def _RunBasicTest(self, test_args: InfoCollectionTestArgs) -> None:
device = test_args.gpu.devices[0]
if not device:
self.fail("System Info doesn't have a gpu")
detected_vendor_id = device.vendor_id
detected_device_id = device.device_id
# Gather the expected IDs passed on the command line
if (not test_args.expected_vendor_id_str
or not test_args.expected_device_id_strs):
self.fail('Missing --expected-[vendor|device]-id command line args')
expected_vendor_id = int(test_args.expected_vendor_id_str, 16)
expected_device_ids = [
int(id_str, 16) for id_str in test_args.expected_device_id_strs
]
# Check expected and detected GPUs match
if detected_vendor_id != expected_vendor_id:
self.fail('Vendor ID mismatch, expected %s but got %s.' %
(expected_vendor_id, detected_vendor_id))
if detected_device_id not in expected_device_ids:
self.fail('Device ID mismatch, expected %s but got %s.' %
(expected_device_ids, detected_device_id))
def _RunDirectCompositionTest(self,
test_args: InfoCollectionTestArgs) -> None:
os_name = self.browser.platform.GetOSName()
if os_name and os_name.lower() == 'win':
overlay_bot_config = overlay_support.GetOverlayConfigForGpu(
test_args.gpu.devices[0])
aux_attributes = test_args.gpu.aux_attributes
if not aux_attributes:
self.fail('GPU info does not have aux_attributes.')
expected_values = {
'direct_composition': overlay_bot_config.direct_composition,
'supports_overlays': overlay_bot_config.supports_overlays,
'nv12_overlay_support': overlay_bot_config.nv12_overlay_support,
'yuy2_overlay_support': overlay_bot_config.yuy2_overlay_support,
'bgra8_overlay_support': overlay_bot_config.bgra8_overlay_support,
}
for field, expected in expected_values.items():
detected = aux_attributes.get(field, 'NONE')
if expected != detected:
self.fail(
'%s mismatch, expected %s but got %s.' %
(field, self._ValueToStr(expected), self._ValueToStr(detected)))
def _RunDX12VulkanTest(self, _: InfoCollectionTestArgs) -> None:
os_name = self.browser.platform.GetOSName()
if os_name and os_name.lower() == 'win':
self.RestartBrowserIfNecessaryWithArgs(
['--no-delay-for-dx12-vulkan-info-collection'])
# Need to re-request system info for DX12/Vulkan bits.
system_info = self.browser.GetSystemInfo()
if not system_info:
self.fail("Browser doesn't support GetSystemInfo")
gpu = system_info.gpu
if gpu is None:
raise Exception("System Info doesn't have a gpu")
aux_attributes = gpu.aux_attributes
if not aux_attributes:
self.fail('GPU info does not have aux_attributes.')
dx12_vulkan_bot_config = self._GetDx12VulkanBotConfig()
for field, expected in dx12_vulkan_bot_config.items():
detected = aux_attributes.get(field)
if expected != detected:
self.fail(
'%s mismatch, expected %s but got %s.' %
(field, self._ValueToStr(expected), self._ValueToStr(detected)))
def _RunAsanInfoTest(self, _: InfoCollectionTestArgs) -> None:
gpu_info = self.browser.GetSystemInfo().gpu
self.assertIn('is_asan', gpu_info.aux_attributes)
def _RunClangCoverageInfoTest(self, _: InfoCollectionTestArgs) -> None:
gpu_info = self.browser.GetSystemInfo().gpu
self.assertIn('is_clang_coverage', gpu_info.aux_attributes)
def _RunHostInformationTest(self, test_args: InfoCollectionTestArgs) -> None:
# This is used to verify that the functions in host_information align with
# the information we pull from the browser.
tags = self.GetPlatformTags(self.browser)
if any(os_tag in tags for os_tag in ('android', 'chromeos', 'fuchsia')):
self.skipTest('Test does not support remote platforms')
if 'win' in tags:
self.assertTrue(host_information.IsWindows())
elif 'linux' in tags:
self.assertTrue(host_information.IsLinux())
elif 'mac' in tags:
self.assertTrue(host_information.IsMac())
else:
self.fail('Running on unknown platform')
expected_vendor_id = int(test_args.expected_vendor_id_str, 16)
if expected_vendor_id == constants.GpuVendor.QUALCOMM:
self.assertTrue(host_information.IsArmCpu())
self.assertFalse(host_information.Isx86Cpu())
self.assertTrue(host_information.IsQualcommGpu())
elif expected_vendor_id == constants.GpuVendor.APPLE:
self.assertTrue(host_information.IsArmCpu())
self.assertFalse(host_information.Isx86Cpu())
self.assertTrue(host_information.IsAppleGpu())
else:
self.assertTrue(host_information.Isx86Cpu())
self.assertFalse(host_information.IsArmCpu())
if expected_vendor_id == constants.GpuVendor.AMD:
self.assertTrue(host_information.IsAmdGpu())
elif expected_vendor_id == constants.GpuVendor.INTEL:
self.assertTrue(host_information.IsIntelGpu())
elif expected_vendor_id == constants.GpuVendor.NVIDIA:
self.assertTrue(host_information.IsNvidiaGpu())
else:
self.fail('Running with unknown GPU vendor')
@staticmethod
def _ValueToStr(value: Union[str, bool]) -> str:
if isinstance(value, six.string_types):
return value
if isinstance(value, bool):
return 'supported' if value else 'unsupported'
assert False
return False
@classmethod
def ExpectationsFiles(cls) -> List[str]:
return [
os.path.join(os.path.dirname(os.path.abspath(__file__)),
'test_expectations', 'info_collection_expectations.txt')
]
def load_tests(loader: unittest.TestLoader, tests: Any,
pattern: Any) -> unittest.TestSuite:
del loader, tests, pattern # Unused.
return gpu_integration_test.LoadAllTestsInModule(sys.modules[__name__])