Bug 1523303 - [taskgraph] Define suite "categories" rather than flavours task configs, r=gbrown
authorAndrew Halberstadt <ahalberstadt@mozilla.com>
Mon, 22 Apr 2019 20:44:01 +0000
changeset 470487 00c2b2449639493d03dbed26e5765838c017db7d
parent 470486 305284b53c3c2cf72248c63930f287f4ba909e59
child 470488 60c512bab3e986b609d7fda44d827c21d90612d2
push id35906
push useraciure@mozilla.com
push dateTue, 23 Apr 2019 22:14:56 +0000
treeherdermozilla-central@0ce3633f8b80 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersgbrown
bugs1523303
milestone68.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1523303 - [taskgraph] Define suite "categories" rather than flavours task configs, r=gbrown Currently we have the concept of a "suite" and a "flavour" in our task configuration. Typically, the "suite" refers to the high-level test harness like "mochitest" or "reftest", whereas the flavour is more specific, e.g "browser-chrome-instrumentation" or "crashtest". However the line between suite and flavour is not applied with any semblance of consistency which results in inconsistent naming throughout the tree. This patch gets rid of the concept of "flavours" entirely (at least when it comes to task configuration). A suite is a type of test run, for example: - mochitest-plain - mochitest-devtools-chrome - mochitest-browser-chrome-instrumentation - jsreftest - reftest - firefox-ui-functional-remote etc There is no confusion here between suites and flavours because flavours don't exist. However, there are a couple of places where we *do* need to know what "test harness" is used to run a suite. These cases are: 1. For SCHEDULES moz.build rules 2. For the desktop_unittest.py mozharness script which takes arguments like --mochitest-suite=browser (this is not a compelling use of this information and should be refactored to work more like the android_emulator_unittest.py script) So to get this information, this patch introduces a new concept of a "category" which is the overall "test harness" that runs the suite. For many suites, the "category" is identical to the suite name. Unlike flavours, "categories" have no bearing on how we call or refer to the suite. Differential Revision: https://phabricator.services.mozilla.com/D27554
taskcluster/ci/test/compiled.yml
taskcluster/ci/test/firefox-ui.yml
taskcluster/ci/test/misc.yml
taskcluster/ci/test/mochitest.yml
taskcluster/ci/test/reftest.yml
taskcluster/ci/test/web-platform.yml
taskcluster/ci/test/xpcshell.yml
taskcluster/docs/attributes.rst
taskcluster/taskgraph/transforms/tests.py
tools/tryselect/selectors/chooser/app.py
tools/tryselect/test/test_chooser.py
--- a/taskcluster/ci/test/compiled.yml
+++ b/taskcluster/ci/test/compiled.yml
@@ -62,17 +62,19 @@ gtest:
             windows10-64-shippable.*: 3
             windows10-64-pgo.*: 3
             windows10-64-asan.*: 3
             windows10-aarch64.*: 2
             default: default
 
 jittest:
     description: "JIT Test run"
-    suite: jittest/jittest-chunked
+    suite:
+        category: jittest
+        name: jittest-chunked
     treeherder-symbol: Jit
     instance-size:
         by-test-platform:
             android-em.*: xlarge
             default: default
     run-on-projects:
         by-test-platform:
             # Turn off for all linux and windows platforms, since it is
--- a/taskcluster/ci/test/firefox-ui.yml
+++ b/taskcluster/ci/test/firefox-ui.yml
@@ -1,33 +1,33 @@
 job-defaults:
+    suite:
+        category: firefox-ui
     max-run-time: 5400
     mozharness:
         script: firefox_ui_tests/functional.py
         config:
             by-test-platform:
                 windows.*:
                     - firefox_ui_tests/taskcluster_windows.py
                 macosx.*:
                     - firefox_ui_tests/taskcluster.py
                     - firefox_ui_tests/taskcluster_mac.py
                 linux.*:
                     - firefox_ui_tests/taskcluster.py
                     - remove_executables.py
 
 firefox-ui-functional-local:
     description: "Firefox-ui-tests functional run"
-    suite: "firefox-ui/functional local"
     treeherder-symbol: Fxfn-l(en-US)
     mozharness:
         extra-options:
             - "--tag"
             - "local"
 
 firefox-ui-functional-remote:
     description: "Firefox-ui-tests functional run"
-    suite: "firefox-ui/functional remote"
     treeherder-symbol: Fxfn-r(en-US)
     mozharness:
         extra-options:
             - "--tag"
             - "remote"
     tier: 2
--- a/taskcluster/ci/test/misc.yml
+++ b/taskcluster/ci/test/misc.yml
@@ -116,17 +116,20 @@ test-verify:
                     - unittests/mac_unittest.py
                 windows.*:
                     - unittests/win_unittest.py
         extra-options:
             - --verify
 
 test-verify-gpu:
     description: "Extra verification of tests modified on this push on gpu instances"
-    suite: test-verify
+    suite:
+        category: test-verify
+        name: test-verify-gpu
+    schedules-component: test-verify-gpu
     treeherder-symbol: TVg
     loopback-video: true
     virtualization: virtual-with-gpu
     instance-size:
         by-test-platform:
             android-em.*: xlarge
             default: default
     max-run-time: 10800
--- a/taskcluster/ci/test/mochitest.yml
+++ b/taskcluster/ci/test/mochitest.yml
@@ -1,9 +1,11 @@
 job-defaults:
+    suite:
+        category: mochitest
     target:
         by-test-platform:
             android-em-7.*: geckoview-androidTest.apk
             default: null
     variants:
         by-test-platform:
             linux64/debug: ['serviceworker']
             default: []
@@ -34,17 +36,18 @@ job-defaults:
                     - remove_executables.py
                 macosx.*:
                     - unittests/mac_unittest.py
                 windows.*:
                     - unittests/win_unittest.py
 
 mochitest:
     description: "Mochitest plain run"
-    suite: mochitest/plain-chunked
+    suite:
+        name: plain-chunked
     treeherder-symbol: M()
     loopback-video: true
     tier:
         by-test-platform:
             android-em-7.*/opt: 2
             windows10-aarch64.*: 2
             default: default
     instance-size:
@@ -84,31 +87,33 @@ mochitest:
                 default: []
         chunked:
             by-test-platform:
                 android-em.*: false
                 default: true
 
 mochitest-a11y:
     description: "Mochitest a11y run"
-    suite: mochitest/a11y
+    suite:
+        name: a11y
     treeherder-symbol: M(a11y)
     loopback-video: true
     tier:
         by-test-platform:
             windows10-aarch64.*: 2
             default: default
     e10s: false
     run-on-projects: built-projects
     mozharness:
         mochitest-flavor: a11y
 
 mochitest-browser-chrome:
     description: "Mochitest browser-chrome run"
-    suite: mochitest/browser-chrome-chunked
+    suite:
+        name: browser-chrome-chunked
     treeherder-symbol: M(bc)
     loopback-video: true
     tier:
         by-test-platform:
             windows10-aarch64.*: 2
             default: default
     chunks:
         by-test-platform:
@@ -128,32 +133,34 @@ mochitest-browser-chrome:
         mochitest-flavor: browser
         chunked: true
     # Bug 1281241: migrating to m3.large instances
     instance-size: default
     allow-software-gl-layers: false
 
 browser-instrumentation:
     description: "Extra instrumentation for a browser-chrome run (XUL, XBL, etc)"
-    suite: mochitest/browser-chrome-instrumentation
+    suite:
+        name: browser-chrome-instrumentation
     treeherder-symbol: M(inst)
     loopback-video: true
     tier: 3
     run-on-projects:
         by-test-platform:
             windows.*-(?:nightly|shippable)/.*: ["mozilla-central"]
             default: []
     max-run-time: 14400
     mozharness:
         mochitest-flavor: browser
     allow-software-gl-layers: false
 
 browser-screenshots:
     description: "Browser Screenshots"
-    suite: mochitest/browser-chrome-screenshots
+    suite:
+        name: browser-chrome-screenshots
     treeherder-symbol: M(ss)
     loopback-video: true
     run-on-projects:
         by-test-platform:
             windows7-32(?:-pgo|-shippable)(?:-qr)?/opt: ['mozilla-central', 'integration']
             windows10-64(?:-pgo|-shippable)(?:-qr)?/opt: ['mozilla-central', 'integration']
             (?:windows10-64|windows7-32|linux64)(?:-qr)?/opt: ['mozilla-central']
             linux64-(?:pgo|shippable)(?:-qr)?/opt: ['mozilla-central', 'integration']
@@ -161,17 +168,18 @@ browser-screenshots:
             default: []
     max-run-time: 3600
     mozharness:
         mochitest-flavor: browser
     allow-software-gl-layers: false
 
 mochitest-chrome:
     description: "Mochitest chrome run"
-    suite: mochitest/chrome
+    suite:
+        name: chrome
     treeherder-symbol: M(c)
     loopback-video: true
     tier:
         by-test-platform:
             windows10-aarch64.*: 2
             default: default
     instance-size:
         by-test-platform:
@@ -197,17 +205,16 @@ mochitest-chrome:
                 default: []
         chunked:
             by-test-platform:
                 android-em.*: false
                 default: true
 
 mochitest-clipboard:
     description: "Mochitest clipboard run"
-    suite: mochitest/clipboard
     treeherder-symbol: M(cl)
     loopback-video: true
     tier:
         by-test-platform:
             windows10-aarch64.*: 2
             default: default
     instance-size: xlarge
     max-run-time:
@@ -226,17 +233,18 @@ mochitest-clipboard:
                 android-em.*:
                     # note that Android runs fewer suites than other platforms
                     - --test-suite=mochitest-plain-clipboard
                 default:
                     - --mochitest-suite=plain-clipboard,chrome-clipboard,browser-chrome-clipboard
 
 mochitest-devtools-chrome:
     description: "Mochitest devtools-chrome run"
-    suite: mochitest/mochitest-devtools-chrome-chunked
+    suite:
+        name: mochitest-devtools-chrome-chunked
     treeherder-symbol: M(dt)
     loopback-video: true
     tier:
         by-test-platform:
             windows10-aarch64.*: 2
             default: default
     max-run-time:
         by-test-platform:
@@ -258,33 +266,33 @@ mochitest-devtools-chrome:
         by-test-platform:
             linux64-asan/opt: xlarge  # runs out of memory on default/m3.large
             default: default
     # Bug 1296086: high number of intermittents observed with software GL and large instances
     allow-software-gl-layers: false
 
 mochitest-devtools-webreplay:
     description: "Mochitest devtools-webreplay run"
-    suite: mochitest/mochitest-devtools-webreplay
     treeherder-symbol: M(dt-wr)
     loopback-video: true
     tier: 2
     max-run-time: 900
     mozharness:
         mochitest-flavor: chrome
     allow-software-gl-layers: false
     run-on-projects:
         by-test-platform:
             macosx64/opt: ['mozilla-central', 'try']
             macosx64.*/opt: ['trunk', 'try']
             default: []
 
 mochitest-gpu:
     description: "Mochitest GPU run"
-    suite: mochitest/gpu
+    suite:
+        name: plain-gpu
     treeherder-symbol: M(gpu)
     loopback-video: true
     tier:
         by-test-platform:
             windows10-aarch64.*: 2
             default: default
     instance-size:
         by-test-platform:
@@ -302,17 +310,16 @@ mochitest-gpu:
                 android-em.*:
                     # note that Android runs fewer suites than other platforms
                     - --test-suite=mochitest-plain-gpu
                 default:
                     - --mochitest-suite=plain-gpu,chrome-gpu,browser-chrome-gpu
 
 mochitest-media:
     description: "Mochitest media run"
-    suite: mochitest/mochitest-media
     treeherder-symbol: M(mda)
     max-run-time:
         by-test-platform:
             windows10-64-ccov/debug: 7200
             macosx64-ccov/debug: 7200
             default: 5400
     run-on-projects:
         by-test-platform:
@@ -351,17 +358,18 @@ mochitest-media:
     tier:
         by-test-platform:
             android-hw.*: 2
             windows10-aarch64.*: 2
             default: default
 
 mochitest-plain-headless:
     description: "Mochitest plain headless run"
-    suite: mochitest/plain-chunked
+    suite:
+        name: plain-chunked
     treeherder-symbol: M(h)
     loopback-video: true
     chunks:
         by-test-platform:
             linux.*/debug: 16
             default: 5
     e10s: true
     max-run-time: 5400
@@ -373,17 +381,18 @@ mochitest-plain-headless:
     mozharness:
         mochitest-flavor: plain
         chunked: true
         extra-options:
             - --headless
 
 mochitest-valgrind:
     description: "Mochitest plain Valgrind run"
-    suite: mochitest/valgrind-plain
+    suite:
+        name: valgrind-plain
     treeherder-symbol: M-V()
     run-on-projects: []
     tier: 3
     loopback-video: true
     chunks: 40
     max-run-time: 14400
     # We could re-enable e10s later.
     # There's no intrinsic reason not to use it.
@@ -391,17 +400,16 @@ mochitest-valgrind:
     variants: []
     allow-software-gl-layers: false
     mozharness:
         mochitest-flavor: plain
         chunked: true
 
 mochitest-webgl1-core:
     description: "Mochitest webgl1-core run"
-    suite: mochitest/mochitest-webgl1-core
     treeherder-symbol: M(gl1c)
     run-on-projects:
         by-test-platform:
             windows10-aarch64/opt: ['try', 'mozilla-central']
             default: built-projects
     virtualization: virtual-with-gpu
     e10s:
         by-test-platform:
@@ -419,17 +427,16 @@ mochitest-webgl1-core:
             default: 3600
     # Bug 1296733: llvmpipe with mesa 9.2.1 lacks thread safety
     allow-software-gl-layers: false
     mozharness:
         mochitest-flavor: plain
 
 mochitest-webgl1-ext:
     description: "Mochitest webgl1-ext run"
-    suite: mochitest/mochitest-webgl1-ext
     treeherder-symbol: M(gl1e)
     run-on-projects:
         by-test-platform:
             windows10-aarch64/opt: ['try', 'mozilla-central']
             default: built-projects
     virtualization: virtual-with-gpu
     e10s:
         by-test-platform:
@@ -446,17 +453,16 @@ mochitest-webgl1-ext:
             default: 3600
     # Bug 1296733: llvmpipe with mesa 9.2.1 lacks thread safety
     allow-software-gl-layers: false
     mozharness:
         mochitest-flavor: plain
 
 mochitest-webgl2-core:
     description: "Mochitest webgl2-core run"
-    suite: mochitest/mochitest-webgl2-core
     treeherder-symbol: M(gl2c)
     run-on-projects:
         by-test-platform:
             windows10-aarch64/opt: ['try', 'mozilla-central']
             default: built-projects
     virtualization: virtual-with-gpu
     e10s:
         by-test-platform:
@@ -473,17 +479,16 @@ mochitest-webgl2-core:
             default: 3600
     # Bug 1296733: llvmpipe with mesa 9.2.1 lacks thread safety
     allow-software-gl-layers: false
     mozharness:
         mochitest-flavor: plain
 
 mochitest-webgl2-ext:
     description: "Mochitest webgl2-ext run"
-    suite: mochitest/mochitest-webgl2-ext
     treeherder-symbol: M(gl2e)
     run-on-projects:
         by-test-platform:
             windows10-aarch64/opt: ['try', 'mozilla-central']
             default: built-projects
     virtualization: virtual-with-gpu
     chunks: 4
     e10s:
@@ -502,17 +507,16 @@ mochitest-webgl2-ext:
     # Bug 1296733: llvmpipe with mesa 9.2.1 lacks thread safety
     allow-software-gl-layers: false
     mozharness:
         mochitest-flavor: plain
         chunked: true
 
 mochitest-webgl2-deqp:
     description: "Mochitest webgl2-deqp run"
-    suite: mochitest/mochitest-webgl2-deqp
     treeherder-symbol: M(gl2d)
     run-on-projects: []  # Don't run this for now.
     virtualization: virtual-with-gpu
     chunks: 4
     e10s:
         by-test-platform:
             linux32/debug: both
             default: true
--- a/taskcluster/ci/test/reftest.yml
+++ b/taskcluster/ci/test/reftest.yml
@@ -1,9 +1,11 @@
 job-defaults:
+    suite:
+        category: reftest
     target:
         by-test-platform:
             android-em-7.*: geckoview-androidTest.apk
             default: null
     variants:
         by-test-platform:
             linux64/debug: ['serviceworker']
             default: []
@@ -30,17 +32,16 @@ job-defaults:
                     - remove_executables.py
                 macosx.*:
                     - unittests/mac_unittest.py
                 windows.*:
                     - unittests/win_unittest.py
 
 crashtest:
     description: "Crashtest run"
-    suite: reftest/crashtest
     treeherder-symbol: R(C)
     instance-size:
         by-test-platform:
             android-em.*: xlarge
             default: default
     virtualization:
         by-test-platform:
             windows10-64(?:-pgo|-shippable)?-qr/.*: virtual-with-gpu
@@ -62,18 +63,17 @@ crashtest:
             default: 3600
     tier:
         by-test-platform:
             windows10-aarch64.*: 2
             default: default
 
 jsreftest:
     description: "JS Reftest run"
-    suite: reftest/jsreftest
-    schedules-component: jsreftest  # scheduling for this reftest is different from the others..
+    schedules-component: jsreftest
     treeherder-symbol: R(J)
     instance-size:
         by-test-platform:
             android-em.*: xlarge
             default: default
     chunks:
         by-test-platform:
             android-em-4.3-arm7-api-16/debug: 100
@@ -97,17 +97,16 @@ jsreftest:
             default: 3600
     tier:
         by-test-platform:
             windows10-aarch64.*: 2
             default: default
 
 reftest:
     description: "Reftest run"
-    suite: reftest/reftest
     treeherder-symbol: R(R)
     instance-size:
         by-test-platform:
             android-em.*: xlarge
             default: default
     virtualization: virtual-with-gpu
     chunks:
         by-test-platform:
@@ -141,17 +140,16 @@ reftest:
                 default: true
     tier:
         by-test-platform:
             windows10-aarch64.*: 2
             default: default
 
 reftest-gpu:
     description: "Reftest GPU run"
-    suite: reftest/reftest-gpu
     treeherder-symbol: R(Rg)
     chunks:
         by-test-platform:
             windows.*/opt: 2
             default: 4
     run-on-projects:
         by-test-platform:
             windows10.*: []
@@ -160,17 +158,16 @@ reftest-gpu:
     virtualization: virtual-with-gpu
     max-run-time: 3600
     mozharness:
         chunked: true
     tier: default
 
 reftest-no-accel:
     description: "Reftest not accelerated run"
-    suite: reftest/reftest-no-accel
     treeherder-symbol: R(Ru)
     virtualization: virtual-with-gpu
     run-on-projects:
         by-test-platform:
             windows10.*: []
             default: built-projects
     chunks:
         by-test-platform:
--- a/taskcluster/ci/test/web-platform.yml
+++ b/taskcluster/ci/test/web-platform.yml
@@ -1,9 +1,11 @@
 job-defaults:
+    suite:
+        category: web-platform-tests
     instance-size: xlarge
     max-run-time: 5400
     variants:
         by-test-platform:
             linux64/debug: ['serviceworker']
             default: []
     virtualization:
         by-test-platform:
@@ -89,17 +91,19 @@ web-platform-tests-headless:
                     - --headless-width=1024
                     - --headless-height=768
                 default:
                     - --test-type=testharness
                     - --headless
 
 web-platform-tests-reftests:
     description: "Web platform reftest run"
-    suite: web-platform-tests-reftests
+    suite:
+        name: web-platform-tests-reftests
+    schedules-component: web-platform-tests-reftests
     treeherder-symbol: W(Wr)
     chunks:
         by-test-platform:
             android.*: 12
             default: 6
     e10s:
         by-test-platform:
             linux32/debug: both
@@ -116,17 +120,19 @@ web-platform-tests-reftests:
             windows10-aarch64.*: 2
             default: default
     mozharness:
         extra-options:
             - --test-type=reftest
 
 web-platform-tests-reftests-headless:
     description: "Web platform reftest headless run"
-    suite: web-platform-tests-reftests
+    suite:
+        name: web-platform-tests-reftests
+    schedules-component: web-platform-tests-reftests
     treeherder-symbol: W(WrH)
     chunks: 6
     e10s:
         by-test-platform:
             linux32/debug: both
             default: true
     run-on-projects: []  # disabled pending releng approval
     mozharness:
@@ -137,17 +143,19 @@ web-platform-tests-reftests-headless:
                     - --headless
                     - --headless-width=1024
                     - --headless-height=768
                 default:
                     - --test-type=reftest
 
 web-platform-tests-wdspec:
     description: "Web platform webdriver-spec run"
-    suite: web-platform-tests-wdspec
+    suite:
+        name: web-platform-tests-wdspec
+    schedules-component: web-platform-tests-wdspec
     treeherder-symbol: W(Wd)
     chunks:
         by-test-platform:
             linux64-ccov/debug: 4
             windows10-64-ccov/debug: 4
             default: 2
     mozharness:
         extra-options:
@@ -162,34 +170,39 @@ web-platform-tests-wdspec:
         by-test-platform:
             android.*: 3
             linux64-asan/opt: 2
             .*-qr/.*: 2  # can't be tier-1 if it's not running on integration branches
             default: default
 
 web-platform-tests-wdspec-headless:
     description: "Web platform webdriver-spec headless run"
-    suite: web-platform-tests-wdspec
+    suite:
+        name: web-platform-tests-wdspec
+    schedules-component: web-platform-tests-wdspec
     treeherder-symbol: W(WdH)
     run-on-projects: []  # disabled pending releng approval
     mozharness:
         extra-options:
             by-test-platform:
                 windows.*:
                     - --test-type=wdspec
                     - --headless
                     - --headless-width=1024
                     - --headless-height=768
                 default:
                     - --test-type=wdspec
                     - --headless
 
 test-verify-wpt:
     description: "Extra verification of web-platform tests modified on this push"
-    suite: test-verify
+    suite:
+        category: test-verify
+        name: test-verify-wpt
+    schedules-component: test-verify-wpt
     treeherder-symbol: TVw
     max-run-time: 10800
     run-on-projects:
         by-test-platform:
             # do not run on ccov
             .*-ccov/.*: []
             .*-asan/.*: []
             (?:windows10-64|windows7-32|linux64)(?:-qr)?/opt: ['mozilla-central', 'try']
@@ -198,17 +211,20 @@ test-verify-wpt:
             default: ['trunk', 'try']
     tier: 2
     mozharness:
         extra-options:
             - --verify
 
 test-coverage-wpt:
     description: "Per web-platform test coverage"
-    suite: test-coverage-wpt
+    suite:
+        category: test-coverage
+        name: test-coverage-wpt
+    schedules-component: test-coverage-wpt
     treeherder-symbol: TCw
     max-run-time: 10800
     run-on-projects:
         by-test-platform:
             .*-ccov/.*: built-projects
             default: []
     tier: 2
     mozharness:
--- a/taskcluster/ci/test/xpcshell.yml
+++ b/taskcluster/ci/test/xpcshell.yml
@@ -1,9 +1,10 @@
 job-defaults:
+    suite: xpcshell
     variants:
         by-test-platform:
             linux64/debug: ['serviceworker']
             default: []
     mozharness:
         script:
             by-test-platform:
                 android-em.*: android_emulator_unittest.py
@@ -23,17 +24,16 @@ job-defaults:
         requires-signed-builds:
             by-test-platform:
                 windows10-64-asan/opt: false    # No XPCShell on ASAN yet
                 windows.*: true
                 default: false
 
 xpcshell:
     description: "xpcshell test run"
-    suite: xpcshell
     treeherder-symbol: X(X)
     run-on-projects:
         by-test-platform:
             windows10-64-asan/opt: []  # No XPCShell on ASAN yet
             windows10-aarch64/opt: ['try', 'mozilla-central']
             android-em-4.3-arm7-api-16/opt: ['try']
             default: built-projects
     chunks:
--- a/taskcluster/docs/attributes.rst
+++ b/taskcluster/docs/attributes.rst
@@ -90,28 +90,27 @@ Unlike build_platform, the test platform
 format, e.g., ``linux64/opt``.
 
 unittest_suite
 ==============
 
 This is the unit test suite being run in a unit test task.  For example,
 ``mochitest`` or ``cppunittest``.
 
-unittest_flavor
-===============
+unittest_category
+=================
 
-If a unittest suite has subdivisions, those are represented as flavors.  Not
-all suites have flavors, in which case this attribute should be set to match
-the suite.  Examples: ``mochitest-devtools-chrome-chunked`` or ``a11y``.
+This is the high-level category of test the suite corresponds to. This is
+usually the test harness used to run the suite.
 
 unittest_try_name
 =================
 
 This is the name used to refer to a unit test via try syntax.  It
-may not match either of ``unittest_suite`` or ``unittest_flavor``.
+may not match ``unittest_suite``.
 
 unittest_variant
 ================
 
 The configuration variant the test suite is running with. If set, this usually
 means the tests are running with a special pref enabled. These are defined in
 ``taskgraph.transforms.tests.TEST_VARIANTS``.
 
--- a/taskcluster/taskgraph/transforms/tests.py
+++ b/taskcluster/taskgraph/transforms/tests.py
@@ -193,20 +193,21 @@ transforms = TransformSequence()
 # everyone move more slowly.  Be considerate of your fellow hackers!
 # See the warnings in taskcluster/docs/how-tos.rst
 #
 # *****WARNING*****
 test_description_schema = Schema({
     # description of the suite, for the task metadata
     'description': basestring,
 
-    # test suite name, or <suite>/<flavor>
-    Required('suite'): optionally_keyed_by(
-        'test-platform',
-        basestring),
+    # test suite category and name
+    Optional('suite'): Any(
+        basestring,
+        {Optional('category'): basestring, Optional('name'): basestring},
+    ),
 
     # base work directory used to set up the task.
     Optional('workdir'): optionally_keyed_by(
         'test-platform',
         Any(basestring, 'default')),
 
     # the name by which this test suite is addressed in try syntax; defaults to
     # the test-name.  This will translate to the `unittest_try_name` or
@@ -477,18 +478,27 @@ test_description_schema = Schema({
         basestring: optionally_keyed_by('test-platform', [basestring])
     },
 }, required=True)
 
 
 @transforms.add
 def handle_keyed_by_mozharness(config, tests):
     """Resolve a mozharness field if it is keyed by something"""
+    fields = [
+        'mozharness',
+        'mozharness.chunked',
+        'mozharness.config',
+        'mozharness.extra-options',
+        'mozharness.requires-signed-builds',
+        'mozharness.script',
+    ]
     for test in tests:
-        resolve_keyed_by(test, 'mozharness', item_name=test['test-name'])
+        for field in fields:
+            resolve_keyed_by(test, field, item_name=test['test-name'])
         yield test
 
 
 @transforms.add
 def set_defaults(config, tests):
     for test in tests:
         build_platform = test['build-platform']
         if build_platform.startswith('android'):
@@ -556,16 +566,51 @@ def resolve_keys(config, tests):
             **{
                 'release-type': config.params['release_type'],
             }
         )
         yield test
 
 
 @transforms.add
+def handle_suite_category(config, tests):
+    for test in tests:
+        test.setdefault('suite', {})
+
+        if isinstance(test['suite'], basestring):
+            test['suite'] = {'name': test['suite']}
+
+        suite = test['suite'].setdefault('name', test['test-name'])
+        category = test['suite'].setdefault('category', suite)
+
+        test.setdefault('attributes', {})
+        test['attributes']['unittest_suite'] = suite
+        test['attributes']['unittest_category'] = category
+
+        script = test['mozharness']['script']
+        category_arg = None
+        if suite.startswith('test-verify') or suite.startswith('test-coverage'):
+            pass
+        elif script in ('android_emulator_unittest.py', 'android_hardware_unittest.py'):
+            category_arg = '--test-suite'
+        elif script == 'desktop_unittest.py':
+            category_arg = '--{}-suite'.format(category)
+
+        if category_arg:
+            test['mozharness'].setdefault('extra-options', [])
+            extra = test['mozharness']['extra-options']
+            if not any(arg.startswith(category_arg) for arg in extra):
+                extra.append('{}={}'.format(category_arg, suite))
+
+        # From here on out we only use the suite name.
+        test['suite'] = suite
+        yield test
+
+
+@transforms.add
 def setup_talos(config, tests):
     """Add options that are specific to talos jobs (identified by suite=talos)"""
     for test in tests:
         if test['suite'] not in ['talos', 'raptor']:
             yield test
             continue
 
         if test['suite'] == 'talos':
@@ -792,66 +837,29 @@ def handle_keyed_by(config, tests):
         'max-run-time',
         'chunks',
         'variants',
         'e10s',
         'suite',
         'run-on-projects',
         'os-groups',
         'run-as-administrator',
-        'mozharness.chunked',
-        'mozharness.config',
-        'mozharness.extra-options',
-        'mozharness.requires-signed-builds',
-        'mozharness.script',
         'workdir',
         'worker-type',
         'virtualization',
         'fetches.fetch',
         'fetches.toolchain',
     ]
     for test in tests:
         for field in fields:
             resolve_keyed_by(test, field, item_name=test['test-name'],
                              project=config.params['project'])
         yield test
 
 
-@transforms.add
-def handle_suite_category(config, tests):
-    for test in tests:
-        if '/' in test['suite']:
-            suite, flavor = test['suite'].split('/', 1)
-        else:
-            suite = flavor = test['suite']
-
-        test.setdefault('attributes', {})
-        test['attributes']['unittest_suite'] = suite
-        test['attributes']['unittest_flavor'] = flavor
-
-        script = test['mozharness']['script']
-        category_arg = None
-        if suite.startswith('test-verify') or suite.startswith('test-coverage'):
-            pass
-        elif script == 'android_emulator_unittest.py':
-            category_arg = '--test-suite'
-        elif script == 'android_hardware_unittest.py':
-            category_arg = '--test-suite'
-        elif script == 'desktop_unittest.py':
-            category_arg = '--{}-suite'.format(suite)
-
-        if category_arg:
-            test['mozharness'].setdefault('extra-options', [])
-            extra = test['mozharness']['extra-options']
-            if not any(arg.startswith(category_arg) for arg in extra):
-                extra.append('{}={}'.format(category_arg, flavor))
-
-        yield test
-
-
 def get_mobile_project(test):
     """Returns the mobile project of the specified task or None."""
 
     if not test['build-platform'].startswith('android'):
         return
 
     mobile_projects = (
         'fenix',
@@ -1255,42 +1263,39 @@ def make_job_description(config, tests):
         jobdesc['run-on-projects'] = test['run-on-projects']
         jobdesc['scopes'] = []
         jobdesc['tags'] = test.get('tags', {})
         jobdesc['extra'] = {
             'chunks': {
                 'current': test['this-chunk'],
                 'total': test['chunks'],
             },
-            'suite': {
-                'name': attributes['unittest_suite'],
-                'flavor': attributes['unittest_flavor'],
-            },
+            'suite': attributes['unittest_suite'],
         }
         jobdesc['treeherder'] = {
             'symbol': test['treeherder-symbol'],
             'kind': 'test',
             'tier': test['tier'],
             'platform': test.get('treeherder-machine-platform', test['build-platform']),
         }
 
-        suite = test.get('schedules-component', attributes['unittest_suite'])
-        if suite in INCLUSIVE_COMPONENTS:
+        category = test.get('schedules-component', attributes['unittest_category'])
+        if category in INCLUSIVE_COMPONENTS:
             # if this is an "inclusive" test, then all files which might
             # cause it to run are annotated with SCHEDULES in moz.build,
             # so do not include the platform or any other components here
-            schedules = [suite]
+            schedules = [category]
         else:
-            schedules = [suite, platform_family(test['build-platform'])]
+            schedules = [category, platform_family(test['build-platform'])]
 
         if test.get('when'):
             jobdesc['when'] = test['when']
         elif 'optimization' in test:
             jobdesc['optimization'] = test['optimization']
-        elif not config.params.is_try() and suite not in INCLUSIVE_COMPONENTS:
+        elif not config.params.is_try() and category not in INCLUSIVE_COMPONENTS:
             # for non-try branches and non-inclusive suites, include SETA
             jobdesc['optimization'] = {'skip-unless-schedules-or-seta': schedules}
         else:
             # otherwise just use skip-unless-schedules
             jobdesc['optimization'] = {'skip-unless-schedules': schedules}
 
         run = jobdesc['run'] = {}
         run['using'] = 'mozharness-test'
--- a/tools/tryselect/selectors/chooser/app.py
+++ b/tools/tryselect/selectors/chooser/app.py
@@ -88,48 +88,38 @@ class Platform(Section):
         return task.task['tags'].get('android-stuff', False) != "true"
 
 
 @register_section
 class Test(Section):
     name = 'test'
     kind = 'test'
     title = 'Test Suites'
-    attrs = ['unittest_suite', 'unittest_flavor']
+    attrs = ['unittest_suite']
 
     def labelfn(self, task):
         suite = task['unittest_suite'].replace(' ', '-')
-        flavor = task['unittest_flavor'].replace(' ', '-')
-
-        if flavor.endswith('chunked'):
-            flavor = flavor[:-len('chunked')]
 
-        if flavor.startswith(suite):
-            flavor = flavor[len(suite):]
-        flavor = flavor.strip('-')
+        if suite.endswith('-chunked'):
+            suite = suite[:-len('-chunked')]
 
-        if flavor in ('crashtest', 'jsreftest'):
-            return flavor
-
-        if flavor:
-            return '{}-{}'.format(suite, flavor)
         return suite
 
     def contains(self, task):
         if not Section.contains(self, task):
             return False
         return task.attributes['unittest_suite'] not in ('raptor', 'talos')
 
 
 @register_section
 class Perf(Section):
     name = 'perf'
     kind = 'test'
     title = 'Performance'
-    attrs = ['unittest_suite', 'unittest_flavor', 'raptor_try_name', 'talos_try_name']
+    attrs = ['unittest_suite', 'raptor_try_name', 'talos_try_name']
 
     def labelfn(self, task):
         suite = task['unittest_suite']
         label = task['{}_try_name'.format(suite)]
 
         if not label.startswith(suite):
             label = '{}-{}'.format(suite, label)
 
--- a/tools/tryselect/test/test_chooser.py
+++ b/tools/tryselect/test/test_chooser.py
@@ -17,19 +17,18 @@ TASKS = [
         'attributes': {
             'build_platform': 'windows',
         },
     },
     {
         'kind': 'test',
         'label': 'test-windows-mochitest-e10s',
         'attributes': {
-            'unittest_suite': 'mochitest',
-            'unittest_flavor': 'browser-chrome',
-            'mochitest_try_name': 'mochitest',
+            'unittest_suite': 'mochitest-browser-chrome',
+            'mochitest_try_name': 'mochitest-browser-chrome',
         },
     },
 ]
 
 
 @pytest.fixture
 def app(tg):
     app = create_application(tg)
@@ -45,17 +44,17 @@ def test_try_chooser(app):
     client = app.test_client()
 
     response = client.get('/')
     assert response.status_code == 200
 
     expected_output = [
         """<title>Try Chooser Enhanced</title>""",
         """<input class="filter" type="checkbox" id=windows name="build" value='{"build_platform": ["windows"]}' onchange="console.log('checkbox onchange triggered');apply();">""",  # noqa
-        """<input class="filter" type="checkbox" id=mochitest-browser-chrome name="test" value='{"unittest_flavor": ["browser-chrome"], "unittest_suite": ["mochitest"]}' onchange="console.log('checkbox onchange triggered');apply();">""",  # noqa
+        """<input class="filter" type="checkbox" id=mochitest-browser-chrome name="test" value='{"unittest_suite": ["mochitest-browser-chrome"]}' onchange="console.log('checkbox onchange triggered');apply();">""",  # noqa
     ]
 
     for expected in expected_output:
         assert expected in response.data
 
     response = client.post('/', data={'action': 'Cancel'})
     assert response.status_code == 200
     assert "You may now close this page" in response.data