Make GPU tests Python 3 compatible

Makes the necessary changes to make the GPU Telemetry-based integration
tests fully Python 3-compatible. This has been tested on the bots, but
this CL does not actually enable use of Python 3 since we want to
verify that important functionality (such as minidump symbolization)
works properly before switching all testing to Python 3.

Bug: 1198237
Change-Id: I377ddea05421ee524fcb104ef17a06b208c96ce8
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2976737
Auto-Submit: Brian Sheedy <bsheedy@chromium.org>
Commit-Queue: Brian Sheedy <bsheedy@chromium.org>
Reviewed-by: Robbie Iannucci <iannucci@chromium.org>
Reviewed-by: Dirk Pranke <dpranke@google.com>
Reviewed-by: Yuly Novikov <ynovikov@chromium.org>
Cr-Commit-Position: refs/heads/main@{#924578}
diff --git a/.vpython3 b/.vpython3
index fc530f6..45fd1b7 100644
--- a/.vpython3
+++ b/.vpython3
@@ -54,14 +54,11 @@
 >
 
 # Common utilities.
-# For Python 2, this version needed to be compatible with the version range
-# specified by
-# //third_party/catapult/telemetry/telemetry/internal/util/external_modules.py
-# However, the hope is that Telemetry's Python 3 migration will fix this, so
-# use the newer version that's currently available in CIPD for now.
+# Use the same versions specified by //third_party/catapult/.vpython3 so that
+# Chromium tests using Telemetry function properly.
 wheel: <
   name: "infra/python/wheels/numpy/${vpython_platform}"
-  version: "version:1.19.5"
+  version: "version:1.20.3"
 >
 wheel: <
   name: "infra/python/wheels/psutil/${vpython_platform}"
@@ -286,3 +283,13 @@
     platform: "win_amd64"
   >
 >
+
+# Used by:
+#   //content/test/gpu/gpu_tests/color_profile_manager_mac.py
+wheel: <
+  name: "infra/python/wheels/pyobjc/${vpython_platform}"
+  version: "version:7.3.chromium.1"
+  match_tag: <
+    platform: "macosx_10_10_intel"
+  >
+>
diff --git a/build/skia_gold_common/output_managerless_skia_gold_session.py b/build/skia_gold_common/output_managerless_skia_gold_session.py
index b22487f..a74b68f 100644
--- a/build/skia_gold_common/output_managerless_skia_gold_session.py
+++ b/build/skia_gold_common/output_managerless_skia_gold_session.py
@@ -10,6 +10,8 @@
 import subprocess
 import time
 
+import six
+
 from skia_gold_common import skia_gold_session
 
 
@@ -62,7 +64,11 @@
   @staticmethod
   def _RunCmdForRcAndOutput(cmd):
     try:
-      output = subprocess.check_output(cmd, stderr=subprocess.STDOUT)
+      output = subprocess.check_output(cmd,
+                                       stderr=subprocess.STDOUT).decode('utf-8')
       return 0, output
     except subprocess.CalledProcessError as e:
-      return e.returncode, e.output
+      output = e.output
+      if not isinstance(output, six.string_types):
+        output = output.decode('utf-8')
+      return e.returncode, output
diff --git a/content/test/gpu/gpu_tests/color_profile_manager_mac.py b/content/test/gpu/gpu_tests/color_profile_manager_mac.py
index c1714e3..19d451d 100644
--- a/content/test/gpu/gpu_tests/color_profile_manager_mac.py
+++ b/content/test/gpu/gpu_tests/color_profile_manager_mac.py
@@ -68,7 +68,7 @@
 def GetSRGBProfileURL():
   srgb_profile_path = '/System/Library/ColorSync/Profiles/sRGB Profile.icc'
   srgb_profile_url = Foundation.CFURLCreateFromFileSystemRepresentation(
-      None, srgb_profile_path, len(srgb_profile_path), False)
+      None, srgb_profile_path.encode('utf-8'), len(srgb_profile_path), False)
   return srgb_profile_url
 
 
diff --git a/content/test/gpu/gpu_tests/gpu_helper.py b/content/test/gpu/gpu_tests/gpu_helper.py
index 60fcda7..6064658 100644
--- a/content/test/gpu/gpu_tests/gpu_helper.py
+++ b/content/test/gpu/gpu_tests/gpu_helper.py
@@ -177,7 +177,7 @@
   # display server.
   if browser_type in REMOTE_BROWSER_TYPES:
     return None
-  if sys.platform == 'linux2':
+  if sys.platform.startswith('linux'):
     if 'WAYLAND_DISPLAY' in os.environ:
       return 'display-server-wayland'
     else:
diff --git a/content/test/gpu/gpu_tests/gpu_integration_test_unittest.py b/content/test/gpu/gpu_tests/gpu_integration_test_unittest.py
index 9761ad95..3992e01b 100644
--- a/content/test/gpu/gpu_tests/gpu_integration_test_unittest.py
+++ b/content/test/gpu/gpu_tests/gpu_integration_test_unittest.py
@@ -262,6 +262,7 @@
       for t in tags:
         self.assertFalse(t.startswith('display-server'))
 
+    # Python 2's return value.
     with mock.patch('sys.platform', 'linux2'):
       tags = gpu_integration_test.GpuIntegrationTest.GetPlatformTags(browser)
       self.assertIn('display-server-x', tags)
@@ -270,6 +271,16 @@
       tags = gpu_integration_test.GpuIntegrationTest.GetPlatformTags(browser)
       self.assertIn('display-server-wayland', tags)
 
+    # Python 3's return value.
+    with mock.patch('sys.platform', 'linux'):
+      del os.environ['WAYLAND_DISPLAY']
+      tags = gpu_integration_test.GpuIntegrationTest.GetPlatformTags(browser)
+      self.assertIn('display-server-x', tags)
+
+      os.environ['WAYLAND_DISPLAY'] = 'wayland-0'
+      tags = gpu_integration_test.GpuIntegrationTest.GetPlatformTags(browser)
+      self.assertIn('display-server-wayland', tags)
+
   def testSimpleIntegrationTest(self):
     test_args = _IntegrationTestArgs('simple_integration_unittest')
     test_args.failures = [
diff --git a/content/test/gpu/gpu_tests/info_collection_test.py b/content/test/gpu/gpu_tests/info_collection_test.py
index 5dd9aa8..ac1c3f5 100644
--- a/content/test/gpu/gpu_tests/info_collection_test.py
+++ b/content/test/gpu/gpu_tests/info_collection_test.py
@@ -109,7 +109,7 @@
       aux_attributes = test_args.gpu.aux_attributes
       if not aux_attributes:
         self.fail('GPU info does not have aux_attributes.')
-      for field, expected in overlay_bot_config.iteritems():
+      for field, expected in overlay_bot_config.items():
         detected = aux_attributes.get(field, 'NONE')
         if expected != detected:
           self.fail(
@@ -133,7 +133,7 @@
         self.fail('GPU info does not have aux_attributes.')
 
       dx12_vulkan_bot_config = self.GetDx12VulkanBotConfig()
-      for field, expected in dx12_vulkan_bot_config.iteritems():
+      for field, expected in dx12_vulkan_bot_config.items():
         detected = aux_attributes.get(field)
         if expected != detected:
           self.fail(
diff --git a/content/test/gpu/gpu_tests/ipg_utils.py b/content/test/gpu/gpu_tests/ipg_utils.py
index 78cc97d7..dd1e6a8 100644
--- a/content/test/gpu/gpu_tests/ipg_utils.py
+++ b/content/test/gpu/gpu_tests/ipg_utils.py
@@ -163,7 +163,7 @@
       the 'mean' and 'stdev' for the metric.
     """
     summary = {}
-    for key, data in metrics.iteritems():
+    for key, data in metrics.items():
       assert data and len(data) > 1
       n = len(data)
       if outliers > 0:
diff --git a/content/test/gpu/gpu_tests/maps_integration_test.py b/content/test/gpu/gpu_tests/maps_integration_test.py
index a11ac07f..deb3ac94e 100644
--- a/content/test/gpu/gpu_tests/maps_integration_test.py
+++ b/content/test/gpu/gpu_tests/maps_integration_test.py
@@ -113,10 +113,13 @@
     # The bottom corners of Mac screenshots have black triangles due to the
     # rounded corners of Mac windows. So, crop the bottom few rows off now to
     # get rid of those. The triangles appear to be 5 pixels wide and tall
-    # regardless of DPI, so 10 pixels should be sufficient.
+    # regardless of DPI, so 10 pixels should be sufficient. However, when
+    # running under Python 3, 10 isn't quite enough for some reason, so use
+    # 20 instead.
     if self.browser.platform.GetOSName() == 'mac':
-      img_height, img_width = screenshot.shape[:2]
-      screenshot = image_util.Crop(screenshot, 0, 0, img_width, img_height - 10)
+      img_height = image_util.Height(screenshot)
+      img_width = image_util.Width(screenshot)
+      screenshot = image_util.Crop(screenshot, 0, 0, img_width, img_height - 20)
     x1, y1, x2, y2 = _GetCropBoundaries(screenshot)
     screenshot = image_util.Crop(screenshot, x1, y1, x2 - x1, y2 - y1)
 
@@ -163,7 +166,8 @@
     A 4-tuple (x1, y1, x2, y2) denoting the top left and bottom right
     coordinates to crop to.
   """
-  img_height, img_width = screenshot.shape[:2]
+  img_height = image_util.Height(screenshot)
+  img_width = image_util.Width(screenshot)
 
   def RowIsWhite(row):
     for col in range(img_width):
diff --git a/content/test/gpu/unexpected_pass_finder.py b/content/test/gpu/unexpected_pass_finder.py
index 1497765c..7e94185f 100755
--- a/content/test/gpu/unexpected_pass_finder.py
+++ b/content/test/gpu/unexpected_pass_finder.py
@@ -206,7 +206,7 @@
   stale_message = ''
   if args.remove_stale_expectations:
     stale_expectations = []
-    for _, expectation_map in stale.iteritems():
+    for _, expectation_map in stale.items():
       stale_expectations.extend(expectation_map.keys())
     stale_expectations.extend(unused_expectations)
     affected_urls |= expectations_instance.RemoveExpectationsFromFile(
diff --git a/testing/buildbot/gn_isolate_map.pyl b/testing/buildbot/gn_isolate_map.pyl
index 44b7a50..7db4f1280 100644
--- a/testing/buildbot/gn_isolate_map.pyl
+++ b/testing/buildbot/gn_isolate_map.pyl
@@ -869,6 +869,7 @@
     "label": "//content/test:fuchsia_telemetry_gpu_integration_test",
     "script": "//testing/scripts/run_gpu_integration_test_as_googletest.py",
     "type": "script",
+    "python3": True,
   },
   "gcm_unit_tests": {
     "label": "//google_apis/gcm:gcm_unit_tests",
@@ -1695,6 +1696,7 @@
     "label": "//chrome/test:telemetry_gpu_integration_test",
     "script": "//testing/scripts/run_gpu_integration_test_as_googletest.py",
     "type": "script",
+    "python3": True,
   },
   "telemetry_gpu_integration_test_android_chrome": {
     "args": [
@@ -1703,6 +1705,7 @@
     "label": "//chrome/test:telemetry_gpu_integration_test_android_chrome",
     "script": "//testing/scripts/run_gpu_integration_test_as_googletest.py",
     "type": "script",
+    "python3": True,
   },
   "telemetry_gpu_integration_test_android_webview": {
     "args": [
@@ -1711,6 +1714,7 @@
     "label": "//chrome/test:telemetry_gpu_integration_test_android_webview",
     "script": "//testing/scripts/run_gpu_integration_test_as_googletest.py",
     "type": "script",
+    "python3": True,
   },
   "telemetry_gpu_integration_test_scripts_only": {
     "label": "//chrome/test:telemetry_gpu_integration_test_scripts_only",