Validate that a job has a run playbook on freeze

We now know, before attempting to run a job, whether the inheritance
hierarchy has produced a main playbook for the job.  If there is none,
error early.

Also, in the executor, assume that any specified playbooks are
required to exist, and use the more specific version of the error
message if they don't.

Change-Id: Id7dc5934c665cf939820b12b5ded53adeb60c0a8
diff --git a/tests/unit/test_scheduler.py b/tests/unit/test_scheduler.py
index e30a43d..b0df2b2 100755
--- a/tests/unit/test_scheduler.py
+++ b/tests/unit/test_scheduler.py
@@ -2486,6 +2486,15 @@
         self.assertEqual([x['path'] for x in p['playbooks']],
                          ['playbooks/python27.yaml'])
 
+    @simple_layout("layouts/no-run.yaml")
+    def test_job_without_run(self):
+        "Test that a job without a run playbook errors"
+        A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
+        self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
+        self.waitUntilSettled()
+        self.assertIn('Job base does not specify a run playbook',
+                      A.messages[-1])
+
     def test_queue_names(self):
         "Test shared change queue names"
         tenant = self.sched.abide.tenants.get('tenant-one')