Unit test for the gossip intent store

This change also implements a unit test harness for the
EventuallyConsistentMap that is intended to be reusable
to test other stores.

Change-Id: I2257da9b19412b97a3aa0f127be7263a7732b852
diff --git a/core/store/dist/src/test/java/org/onosproject/store/intent/impl/GossipIntentStoreTest.java b/core/store/dist/src/test/java/org/onosproject/store/intent/impl/GossipIntentStoreTest.java
new file mode 100644
index 0000000..a74c3a2
--- /dev/null
+++ b/core/store/dist/src/test/java/org/onosproject/store/intent/impl/GossipIntentStoreTest.java
@@ -0,0 +1,234 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.store.intent.impl;
+
+import java.util.LinkedList;
+import java.util.List;
+import java.util.stream.IntStream;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.onosproject.cluster.ClusterServiceAdapter;
+import org.onosproject.core.IdGenerator;
+import org.onosproject.net.intent.HostToHostIntent;
+import org.onosproject.net.intent.Intent;
+import org.onosproject.net.intent.IntentData;
+import org.onosproject.net.intent.IntentState;
+import org.onosproject.net.intent.IntentTestsMocks;
+import org.onosproject.net.intent.MockIdGenerator;
+import org.onosproject.net.intent.PartitionServiceAdapter;
+import org.onosproject.store.service.TestStorageService;
+
+import static org.hamcrest.Matchers.is;
+import static org.hamcrest.Matchers.nullValue;
+import static org.junit.Assert.assertThat;
+import static org.onosproject.net.NetTestTools.APP_ID;
+import static org.onosproject.net.NetTestTools.hid;
+
+/**
+ * Gossip Intent Store test using database adapter.
+ */
+public class GossipIntentStoreTest {
+
+    private GossipIntentStore intentStore;
+    private IdGenerator idGenerator;
+    private HostToHostIntent.Builder builder1;
+
+    @Before
+    public void setUp() {
+        intentStore = new GossipIntentStore();
+        intentStore.storageService = new TestStorageService();
+        intentStore.partitionService = new PartitionServiceAdapter();
+        intentStore.clusterService = new ClusterServiceAdapter();
+        idGenerator = new MockIdGenerator();
+        Intent.bindIdGenerator(idGenerator);
+        builder1 = HostToHostIntent
+                        .builder()
+                        .one(hid("12:34:56:78:91:ab/1"))
+                        .two(hid("12:34:56:78:91:ac/1"))
+                        .appId(APP_ID);
+        intentStore.activate();
+    }
+
+    @After
+    public void cleanUp() {
+        intentStore.deactivate();
+        Intent.unbindIdGenerator(idGenerator);
+    }
+
+    /**
+     * Generates a list of test intent data.
+     *
+     * @param count how many intent data objects are needed
+     * @return list of intent data
+     */
+    private List<IntentData> generateIntentList(int count) {
+        LinkedList<IntentData> intents = new LinkedList<>();
+        IntStream.rangeClosed(1, count)
+                .forEach(i ->
+                        intents.add(
+                                new IntentData(
+                                        builder1
+                                                .priority(i)
+                                                .build(),
+                                        IntentState.INSTALLED,
+                                        new IntentTestsMocks.MockTimestamp(12))));
+        return intents;
+    }
+
+    /**
+     * Tests the intent count APIs.
+     */
+    @Test
+    public void testGetIntentCount() {
+        assertThat(intentStore.getIntentCount(), is(0L));
+
+        generateIntentList(5).forEach(intentStore::write);
+
+        assertThat(intentStore.getIntentCount(), is(5L));
+    }
+
+    /**
+     * Tests the batch add API.
+     */
+    @Test
+    public void testBatchAdd() {
+        assertThat(intentStore.getIntentCount(), is(0L));
+
+        List<IntentData> intents = generateIntentList(5);
+
+        intentStore.batchWrite(intents);
+        assertThat(intentStore.getIntentCount(), is(5L));
+    }
+
+
+    /**
+     * Tests adding and withdrawing an Intent.
+     */
+    @Test
+    public void testAddAndWithdrawIntent() {
+        // build and install one intent
+        Intent intent = builder1.build();
+        IntentData installed = new IntentData(
+                intent,
+                IntentState.INSTALLED,
+                new IntentTestsMocks.MockTimestamp(12));
+        intentStore.write(installed);
+
+        // check that the intent count includes the new one
+        assertThat(intentStore.getIntentCount(), is(1L));
+
+        // check that the getIntents() API returns the new intent
+        intentStore.getIntents()
+                .forEach(item -> assertThat(item, is(intent)));
+
+        // check that the getInstallableIntents() API returns the new intent
+        intentStore.getInstallableIntents(intent.key())
+                .forEach(item -> assertThat(item, is(intent)));
+
+        // check that the getIntent() API can find the new intent
+        Intent queried = intentStore.getIntent(intent.key());
+        assertThat(queried, is(intent));
+
+        // check that the state of the new intent is correct
+        IntentState state = intentStore.getIntentState(intent.key());
+        assertThat(state, is(IntentState.INSTALLED));
+
+        // check that the getIntentData() API returns the proper value for the
+        // new intent
+        IntentData dataByQuery = intentStore.getIntentData(intent.key());
+        assertThat(dataByQuery, is(installed));
+
+        // check that the getIntentData() API returns the new intent when given
+        // a time stamp to look for
+        Iterable<IntentData> dataIteratorByTime = intentStore.getIntentData(true, 10L);
+        assertThat(dataIteratorByTime.iterator().hasNext(), is(true));
+        dataIteratorByTime.forEach(
+                data -> assertThat(data, is(installed))
+        );
+
+        // check that the getIntentData() API returns the new intent when asked to
+        // find all intents
+        Iterable<IntentData> dataIteratorAll = intentStore.getIntentData(false, 0L);
+        assertThat(dataIteratorAll.iterator().hasNext(), is(true));
+        dataIteratorAll.forEach(
+                data -> assertThat(data, is(installed))
+        );
+
+        // now purge the intent that was created
+        IntentData purge = new IntentData(
+                intent,
+                IntentState.PURGE_REQ,
+                new IntentTestsMocks.MockTimestamp(12));
+        intentStore.write(purge);
+
+        // check that no intents are left
+        assertThat(intentStore.getIntentCount(), is(0L));
+
+        // check that a getIntent() operation on the key of the purged intent
+        // returns null
+        Intent queriedAfterWithdrawal = intentStore.getIntent(intent.key());
+        assertThat(queriedAfterWithdrawal, nullValue());
+    }
+
+    /**
+     * Tests the operation of the APIs for the pending map.
+     */
+    @Test
+    public void testPending() {
+        // crete a new intent and add it as pending
+        Intent intent = builder1.build();
+        IntentData installed = new IntentData(
+                intent,
+                IntentState.INSTALLED,
+                new IntentTestsMocks.MockTimestamp(11));
+        intentStore.addPending(installed);
+
+        // check that the getPending() API returns the new pending intent
+        Iterable<Intent> pendingIntentIteratorAll = intentStore.getPending();
+        assertThat(pendingIntentIteratorAll.iterator().hasNext(), is(true));
+        pendingIntentIteratorAll.forEach(
+                data -> assertThat(data, is(intent))
+        );
+
+        // check that the getPendingData() API returns the IntentData for the
+        // new pending intent
+        Iterable<IntentData> pendingDataIteratorAll = intentStore.getPendingData();
+        assertThat(pendingDataIteratorAll.iterator().hasNext(), is(true));
+        pendingDataIteratorAll.forEach(
+                data -> assertThat(data, is(installed))
+        );
+
+        // check that the new pending intent is returned by the getPendingData()
+        // API when a time stamp is provided
+        Iterable<IntentData> pendingDataIteratorSelected =
+                intentStore.getPendingData(true, 10L);
+        assertThat(pendingDataIteratorSelected.iterator().hasNext(), is(true));
+        pendingDataIteratorSelected.forEach(
+                data -> assertThat(data, is(installed))
+        );
+
+        // check that the new pending intent is returned by the getPendingData()
+        // API when a time stamp is provided
+        Iterable<IntentData> pendingDataIteratorAllFromTimestamp =
+                intentStore.getPendingData(false, 0L);
+        assertThat(pendingDataIteratorAllFromTimestamp.iterator().hasNext(), is(true));
+        pendingDataIteratorSelected.forEach(
+                data -> assertThat(data, is(installed))
+        );
+    }
+}