[run_web_tests] Add option to run virtual tests in parallel

This reduced the local runtime of virtual/layout_ng_flex_box from 2m22s
down to 0m18s. I had previously been jumping through hoops locally to
not run the virtual suite at all.

Change-Id: Idf4ba1c6cf6d7fc43d5873b873c7eb8be313e474
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1999185
Commit-Queue: David Grogan <dgrogan@chromium.org>
Reviewed-by: Xianzhu Wang <wangxianzhu@chromium.org>
Cr-Commit-Position: refs/heads/master@{#731765}
diff --git a/third_party/blink/tools/blinkpy/web_tests/controllers/web_test_runner.py b/third_party/blink/tools/blinkpy/web_tests/controllers/web_test_runner.py
index 921224e..6418a8b9 100644
--- a/third_party/blink/tools/blinkpy/web_tests/controllers/web_test_runner.py
+++ b/third_party/blink/tools/blinkpy/web_tests/controllers/web_test_runner.py
@@ -105,6 +105,7 @@
             test_inputs,
             int(self._options.child_processes),
             self._options.fully_parallel,
+            self._options.virtual_parallel,
             batch_size == 1)
 
         self._reorder_tests_by_args(locked_shards)
@@ -376,7 +377,7 @@
         self._split = test_split_fn
         self._max_locked_shards = max_locked_shards
 
-    def shard_tests(self, test_inputs, num_workers, fully_parallel, run_singly):
+    def shard_tests(self, test_inputs, num_workers, fully_parallel, parallel_includes_virtual, run_singly):
         """Groups tests into batches.
         This helps ensure that tests that depend on each other (aka bad tests!)
         continue to run together as most cross-tests dependencies tend to
@@ -392,7 +393,7 @@
         if num_workers == 1:
             return self._shard_in_two(test_inputs)
         elif fully_parallel:
-            return self._shard_every_file(test_inputs, run_singly)
+            return self._shard_every_file(test_inputs, run_singly, parallel_includes_virtual)
         return self._shard_by_directory(test_inputs)
 
     def _shard_in_two(self, test_inputs):
@@ -417,7 +418,7 @@
 
         return locked_shards, unlocked_shards
 
-    def _shard_every_file(self, test_inputs, run_singly):
+    def _shard_every_file(self, test_inputs, run_singly, virtual_is_unlocked):
         """Returns two lists of shards, each shard containing a single test file.
 
         This mode gets maximal parallelism at the cost of much higher flakiness.
@@ -432,7 +433,7 @@
             # which would be really redundant.
             if test_input.requires_lock:
                 locked_shards.append(TestShard('.', [test_input]))
-            elif test_input.test_name.startswith('virtual') and not run_singly:
+            elif test_input.test_name.startswith('virtual') and not run_singly and not virtual_is_unlocked:
                 # This violates the spirit of sharding every file, but in practice, since the
                 # virtual test suites require a different commandline flag and thus a restart
                 # of content_shell, it's too slow to shard them fully.
diff --git a/third_party/blink/tools/blinkpy/web_tests/controllers/web_test_runner_unittest.py b/third_party/blink/tools/blinkpy/web_tests/controllers/web_test_runner_unittest.py
index e83e182d..6d2c46d 100644
--- a/third_party/blink/tools/blinkpy/web_tests/controllers/web_test_runner_unittest.py
+++ b/third_party/blink/tools/blinkpy/web_tests/controllers/web_test_runner_unittest.py
@@ -185,7 +185,7 @@
         self.sharder = Sharder(port.split_test, max_locked_shards)
         test_list = test_list or self.test_list
         return self.sharder.shard_tests([self.get_test_input(test) for test in test_list],
-                                        num_workers, fully_parallel, run_singly)
+                                        num_workers, fully_parallel, False, run_singly)
 
     def assert_shards(self, actual_shards, expected_shard_names):
         self.assertEqual(len(actual_shards), len(expected_shard_names))
diff --git a/third_party/blink/tools/blinkpy/web_tests/run_web_tests.py b/third_party/blink/tools/blinkpy/web_tests/run_web_tests.py
index f341257..e670c5d2 100644
--- a/third_party/blink/tools/blinkpy/web_tests/run_web_tests.py
+++ b/third_party/blink/tools/blinkpy/web_tests/run_web_tests.py
@@ -481,6 +481,11 @@
                 action='store_true',
                 help='run all tests in parallel'),
             optparse.make_option(
+                '--virtual-parallel',
+                action='store_true',
+                help='When running in parallel, include virtual tests. Useful for running a single '
+                     'virtual test suite, but will be slower in other cases.'),
+            optparse.make_option(
                 '-i', '--ignore-tests',
                 action='append',
                 default=[],