Unit tests and manager changes for failure cases

Add unit tests for intent intallation failures:
- compilation error
- installation exception
- installation returns error future

Change-Id: Idc5e19980032cc5c1b9804c7627833fb126b7a81
diff --git a/core/net/src/test/java/org/onlab/onos/net/intent/impl/IntentManagerTest.java b/core/net/src/test/java/org/onlab/onos/net/intent/impl/IntentManagerTest.java
index 8528228..8709295 100644
--- a/core/net/src/test/java/org/onlab/onos/net/intent/impl/IntentManagerTest.java
+++ b/core/net/src/test/java/org/onlab/onos/net/intent/impl/IntentManagerTest.java
@@ -206,6 +206,56 @@
                      flowRuleService.flows.iterator().next().priority());
     }
 
+    /**
+     * Tests for proper behavior of installation of an intent that triggers
+     * a compilation error.
+     */
+    @Test
+    public void errorIntentCompile() {
+        final TestIntentCompilerError errorCompiler = new TestIntentCompilerError();
+        extensionService.registerCompiler(MockIntent.class, errorCompiler);
+        MockIntent intent = new MockIntent(MockIntent.nextId());
+        listener.setLatch(1, Type.INSTALL_REQ);
+        listener.setLatch(1, Type.FAILED);
+        service.submit(intent);
+        listener.await(Type.INSTALL_REQ);
+        listener.await(Type.FAILED);
+    }
+
+    /**
+     * Tests handling a future that contains an error as a result of
+     * installing an intent.
+     */
+    @Test
+    public void errorIntentInstallFromFlows() {
+        final Long id = MockIntent.nextId();
+        flowRuleService.setFuture(false, 1);
+        MockIntent intent = new MockIntent(id);
+        listener.setLatch(1, Type.FAILED);
+        listener.setLatch(1, Type.INSTALL_REQ);
+        service.submit(intent);
+        listener.await(Type.INSTALL_REQ);
+        delay(10); // need to make sure we have some failed futures returned first
+        flowRuleService.setFuture(true, 0);
+        listener.await(Type.FAILED);
+    }
+
+    /**
+     * Tests handling of an error that is generated by the intent installer.
+     */
+    @Test
+    public void errorIntentInstallFromInstaller() {
+        final TestIntentErrorInstaller errorInstaller = new TestIntentErrorInstaller();
+        extensionService.registerInstaller(MockInstallableIntent.class, errorInstaller);
+        MockIntent intent = new MockIntent(MockIntent.nextId());
+        listener.setLatch(1, Type.INSTALL_REQ);
+        listener.setLatch(1, Type.FAILED);
+        service.submit(intent);
+        listener.await(Type.INSTALL_REQ);
+        listener.await(Type.FAILED);
+
+    }
+
     private static class TestListener implements IntentListener {
         final Multimap<IntentEvent.Type, IntentEvent> events = HashMultimap.create();
         Map<IntentEvent.Type, CountDownLatch> latchMap = Maps.newHashMap();
@@ -229,7 +279,7 @@
         public void await(IntentEvent.Type type) {
             try {
                 assertTrue("Timed out waiting for: " + type,
-                           latchMap.get(type).await(5, TimeUnit.SECONDS));
+                        latchMap.get(type).await(5, TimeUnit.SECONDS));
             } catch (InterruptedException e) {
                 e.printStackTrace();
             }
@@ -299,6 +349,14 @@
         }
     }
 
+    private static class TestIntentCompilerError implements IntentCompiler<MockIntent> {
+        @Override
+        public List<Intent> compile(MockIntent intent, List<Intent> installable,
+                                    Set<LinkResourceAllocations> resources) {
+            throw new IntentCompilationException("Compilation always fails");
+        }
+    }
+
     private static class TestIntentInstaller implements IntentInstaller<MockInstallableIntent> {
         @Override
         public List<FlowRuleBatchOperation> install(MockInstallableIntent intent) {
@@ -327,6 +385,23 @@
         }
     }
 
+    private static class TestIntentErrorInstaller implements IntentInstaller<MockInstallableIntent> {
+        @Override
+        public List<FlowRuleBatchOperation> install(MockInstallableIntent intent) {
+            throw new IntentInstallationException("install() always fails");
+        }
+
+        @Override
+        public List<FlowRuleBatchOperation> uninstall(MockInstallableIntent intent) {
+            throw new IntentRemovalException("uninstall() always fails");
+        }
+
+        @Override
+        public List<FlowRuleBatchOperation> replace(MockInstallableIntent oldIntent, MockInstallableIntent newIntent) {
+            throw new IntentInstallationException("replace() always fails");
+        }
+    }
+
     /**
      * Hamcrest matcher to check that a conllection of Intents contains an
      * Intent with the specified Intent Id.