dequeue abandoned changes

Whenever a change is abandoned, we should probably remove it from queues
and cancel all jobs.

Added a patchset to the getChangeRestoredEvent() event to match Gerrit.

Change-Id: I1e9c9985606c04def7cd37a1284b5addb7553354
diff --git a/tests/base.py b/tests/base.py
index 2af75c7..a86de82 100755
--- a/tests/base.py
+++ b/tests/base.py
@@ -210,6 +210,21 @@
                             "owner": {"name": "User Name"},
                             "url": "https://hostname/3"},
                  "restorer": {"name": "User Name"},
+                 "patchSet": self.patchsets[-1],
+                 "reason": ""}
+        return event
+
+    def getChangeAbandonedEvent(self):
+        event = {"type": "change-abandoned",
+                 "change": {"project": self.project,
+                            "branch": self.branch,
+                            "id": "I5459869c07352a31bfb1e7a8cac379cabfcb25af",
+                            "number": str(self.number),
+                            "subject": self.subject,
+                            "owner": {"name": "User Name"},
+                            "url": "https://hostname/3"},
+                 "abandoner": {"name": "User Name"},
+                 "patchSet": self.patchsets[-1],
                  "reason": ""}
         return event
 
@@ -920,7 +935,8 @@
 
     def assertFinalState(self):
         # Make sure that the change cache is cleared
-        self.assertEqual(len(self.gerrit._change_cache.keys()), 0)
+        self.assertEqual(len(self.gerrit._change_cache.keys()), 0,
+                         "Change cache should have been cleared")
         # Make sure that git.Repo objects have been garbage collected.
         repos = []
         gc.collect()
@@ -1181,7 +1197,8 @@
                 if len(queue.queue) != 0:
                     print 'pipeline %s queue %s contents %s' % (
                         pipeline.name, queue.name, queue.queue)
-                self.assertEqual(len(queue.queue), 0)
+                self.assertEqual(len(queue.queue), 0,
+                                 "Pipelines queues should be empty")
 
     def assertReportedStat(self, key, value=None, kind=None):
         start = time.time()
diff --git a/tests/test_scheduler.py b/tests/test_scheduler.py
index 6e65774..a5e4d5c 100755
--- a/tests/test_scheduler.py
+++ b/tests/test_scheduler.py
@@ -39,6 +39,7 @@
 
 
 class TestScheduler(ZuulTestCase):
+
     def test_jobs_launched(self):
         "Test that jobs are launched and a change is merged"
 
@@ -1431,6 +1432,36 @@
         self.assertEqual(D.reported, 2)
         self.assertEqual(len(self.history), 9)  # 3 each for A, B, D.
 
+    def test_abandoned_change_dequeues(self):
+        "Test that an abandoned change is dequeued"
+
+        self.worker.hold_jobs_in_build = True
+
+        A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
+        self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
+        self.waitUntilSettled()
+        self.assertEqual(len(self.builds), 1, "One job being built (on hold)")
+        self.assertEqual(self.builds[0].name, 'project-merge')
+
+        self.fake_gerrit.addEvent(A.getChangeAbandonedEvent())
+        self.waitUntilSettled()
+
+        # For debugging purposes...
+        #for pipeline in self.sched.layout.pipelines.values():
+        #    for queue in pipeline.queues:
+        #        self.log.info("pipepline %s queue %s contents %s" % (
+        #            pipeline.name, queue.name, queue.queue))
+
+        self.worker.release('.*-merge')
+        self.waitUntilSettled()
+
+        self.assertEqual(len(self.builds), 0, "No job running")
+        self.assertEmptyQueues()
+        self.assertEqual(len(self.history), 1, "Only one build in history")
+        self.assertEqual(self.history[0].result, 'ABORTED',
+                         'Build should have been aborted')
+        self.assertEqual(A.reported, 0, "Abandoned change should not report")
+
     def test_zuul_url_return(self):
         "Test if ZUUL_URL is returning when zuul_url is set in zuul.conf"
         self.assertTrue(self.sched.config.has_option('merger', 'zuul_url'))