llvm_tools: Add --cq_trybot option to specify cq trybots using cq

The users now can specify one of {llvm,llvm-next,llvm-tot} when
using cq to run the tests with this patch. Invalid cq trybots will
be denied.

BUG=chromium:1072063
TEST=Unittest pass
TEST=crrev.com/c/2163157

Change-Id: Ib1f57267a2e37ebe0e71042e8b24cb2281380f3c
Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/third_party/toolchain-utils/+/2163257
Commit-Queue: Tiancong Wang <tcwang@google.com>
Tested-by: Tiancong Wang <tcwang@google.com>
Reviewed-by: George Burgess <gbiv@chromium.org>
diff --git a/llvm_tools/update_packages_and_run_tests.py b/llvm_tools/update_packages_and_run_tests.py
index f47b5cd..b54ba65 100755
--- a/llvm_tools/update_packages_and_run_tests.py
+++ b/llvm_tools/update_packages_and_run_tests.py
@@ -19,6 +19,8 @@
 import get_llvm_hash
 import update_chromeos_llvm_hash
 
+VALID_CQ_TRYBOTS = ['llvm', 'llvm-next', 'llvm-tot']
+
 
 def GetCommandLineArgs():
   """Parses the command line for the command line arguments.
@@ -130,9 +132,17 @@
       help='recipe builders to launch')
 
   # Testing with CQ.
-  subparsers.add_parser('cq')
+  cq_subparser = subparsers.add_parser('cq')
   subparser_names.append('cq')
 
+  # Add argument for specify a cq trybot to test along with other cq builders
+  # e.g. llvm, llvm-next or llvm-tot
+  cq_subparser.add_argument(
+      '--cq_trybot',
+      choices=VALID_CQ_TRYBOTS,
+      help='include the trybot to test together with other cq builders '
+      'available: %(choices)s')
+
   args_output = parser.parse_args()
 
   if args_output.subparser_name not in subparser_names:
@@ -351,6 +361,20 @@
   return '\nCq-Depend: ' + ', '.join(('chromium:%s' % i) for i in dependent_cls)
 
 
+def GetCQIncludeTrybotsString(trybot):
+  """Get Cq-Include-Trybots string, for more llvm testings"""
+
+  if not trybot:
+    return None
+
+  if trybot not in VALID_CQ_TRYBOTS:
+    raise ValueError('%s is not a valid llvm trybot' % trybot)
+
+  # Cq-Include-Trybots must start a new paragraph prefixed
+  # with "Cq-Include-Trybots".
+  return '\nCq-Include-Trybots:chromeos/cq:cq-%s-orchestrator' % trybot
+
+
 def StartCQDryRun(cl, dependent_cls, chroot_path):
   """Start CQ dry run for the changelist and dependencies."""
 
@@ -415,7 +439,12 @@
   update_chromeos_llvm_hash.verbose = args_output.verbose
   extra_commit_msg = None
   if args_output.subparser_name == 'cq':
-    extra_commit_msg = GetCQDependString(args_output.extra_change_lists)
+    cq_depend_msg = GetCQDependString(args_output.extra_change_lists)
+    if cq_depend_msg:
+      extra_commit_msg = cq_depend_msg
+    cq_trybot_msg = GetCQIncludeTrybotsString(args_output.cq_trybot)
+    if cq_trybot_msg:
+      extra_commit_msg += cq_trybot_msg
 
   change_list = update_chromeos_llvm_hash.UpdatePackages(
       update_packages,
diff --git a/llvm_tools/update_packages_and_run_tests_unittest.py b/llvm_tools/update_packages_and_run_tests_unittest.py
index 25a8f83..a4e9242 100755
--- a/llvm_tools/update_packages_and_run_tests_unittest.py
+++ b/llvm_tools/update_packages_and_run_tests_unittest.py
@@ -300,9 +300,8 @@
     test_single_changelist = [1234]
     test_multiple_changelists = [1234, 5678]
 
-    self.assertEqual(
-        update_packages_and_run_tests.GetCQDependString(test_no_changelists),
-        None)
+    self.assertIsNone(
+        update_packages_and_run_tests.GetCQDependString(test_no_changelists))
 
     self.assertEqual(
         update_packages_and_run_tests.GetCQDependString(test_single_changelist),
@@ -313,6 +312,25 @@
             test_multiple_changelists),
         '\nCq-Depend: chromium:1234, chromium:5678')
 
+  def testGetCQIncludeTrybotsString(self):
+    test_no_trybot = None
+    test_valid_trybot = 'llvm-next'
+    test_invalid_trybot = 'invalid-name'
+
+    self.assertIsNone(
+        update_packages_and_run_tests.GetCQIncludeTrybotsString(test_no_trybot))
+
+    self.assertEqual(
+        update_packages_and_run_tests.GetCQIncludeTrybotsString(
+            test_valid_trybot),
+        '\nCq-Include-Trybots:chromeos/cq:cq-llvm-next-orchestrator')
+
+    with self.assertRaises(ValueError) as context:
+      update_packages_and_run_tests.GetCQIncludeTrybotsString(
+          test_invalid_trybot)
+
+    self.assertIn('is not a valid llvm trybot', str(context.exception))
+
   # Mock ExecCommandAndCaptureOutput for the gerrit command execution.
   @mock.patch.object(subprocess, 'check_output', return_value=None)
   def testStartCQDryRunNoDeps(self, mock_exec_cmd):