Require a base job

This makes base jobs required and allows for a per-tenant default.

Story: 2001110
Task: 4793
Change-Id: I26ffddad8358c156cfac749ce98af70f3447f671
diff --git a/tests/unit/test_v3.py b/tests/unit/test_v3.py
index 7038471..15cb561 100755
--- a/tests/unit/test_v3.py
+++ b/tests/unit/test_v3.py
@@ -1120,3 +1120,43 @@
         self.waitUntilSettled()
         self.assertNotIn("exceeds tenant max-nodes", B.messages[0],
                          "B should not fail because of nodes limit")
+
+
+class TestBaseJobs(ZuulTestCase):
+    tenant_config_file = 'config/base-jobs/main.yaml'
+
+    def test_multiple_base_jobs(self):
+        A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
+        self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
+        self.waitUntilSettled()
+        self.assertHistory([
+            dict(name='my-job', result='SUCCESS', changes='1,1'),
+            dict(name='other-job', result='SUCCESS', changes='1,1'),
+        ], ordered=False)
+        self.assertEqual(self.getJobFromHistory('my-job').
+                         parameters['zuul']['jobtags'],
+                         ['mybase'])
+        self.assertEqual(self.getJobFromHistory('other-job').
+                         parameters['zuul']['jobtags'],
+                         ['otherbase'])
+
+    def test_untrusted_base_job(self):
+        """Test that a base job may not be defined in an untrusted repo"""
+        in_repo_conf = textwrap.dedent(
+            """
+            - job:
+                name: fail-base
+                parent: null
+            """)
+
+        file_dict = {'.zuul.yaml': in_repo_conf}
+        A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
+                                           files=file_dict)
+        self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
+        self.waitUntilSettled()
+        self.assertEqual(A.reported, 1,
+                         "A should report failure")
+        self.assertEqual(A.patchsets[0]['approvals'][0]['value'], "-1")
+        self.assertIn('Base jobs must be defined in config projects',
+                      A.messages[0])
+        self.assertHistory([])