diff --git a/core/store/persistence/src/main/test/test/PersistentMapTest.java b/core/store/persistence/src/main/test/test/PersistentMapTest.java
new file mode 100644
index 0000000..b059f18
--- /dev/null
+++ b/core/store/persistence/src/main/test/test/PersistentMapTest.java
@@ -0,0 +1,245 @@
+/*
+ * 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 test;
+
+import com.google.common.collect.Maps;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.mapdb.DB;
+import org.mapdb.DBMaker;
+import org.onosproject.persistence.impl.PersistentMap;
+import org.onosproject.store.service.Serializer;
+
+import java.nio.file.Paths;
+import java.util.Map;
+import java.util.Set;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+
+/**
+ * Test suite for Persistent Map.
+ */
+public class PersistentMapTest {
+
+    private Map<Integer, Integer> map = null;
+    private DB fakeDB = null;
+
+
+    /**
+     * Set up the database, create a map and a direct executor to handle it.
+     *
+     * @throws Exception if instantiation fails
+     */
+    @Before
+    public void setUp() throws Exception {
+        //Creates a db, a map within it and a basic integer serializer (async writing is off)
+        fakeDB = DBMaker
+                .newFileDB(Paths.get("../testDb").toFile())
+                .asyncWriteEnable()
+                .closeOnJvmShutdown()
+                .make();
+        map = new PersistentMap<Integer, Integer>(new Serializer() {
+            @Override
+            public <T> byte[] encode(T object) {
+                if (object == null) {
+                    return null;
+                }
+                int num = (Integer) object;
+                byte[] result = new byte[4];
+
+                result[0] = (byte) (num >> 24);
+                result[1] = (byte) (num >> 16);
+                result[2] = (byte) (num >> 8);
+                result[3] = (byte) num;
+                return result;
+            }
+
+            @Override
+            public <T> T decode(byte[] bytes) {
+                if (bytes == null) {
+                    return null;
+                }
+                int num = 0x00000000;
+
+                num = num | bytes[0] << 24;
+                num = num | bytes[1] << 16;
+                num = num | bytes[2] << 8;
+                num = num | bytes[3];
+
+                return (T) new java.lang.Integer(num);
+            }
+        }, fakeDB, "map");
+    }
+
+    /**
+     * Clears and deletes the map, closes the datbase and deletes the file.
+     *
+     * @throws Exception if shutdown fails
+     */
+    @After
+    public void tearDown() throws Exception {
+        map.clear();
+        fakeDB.delete("map:map");
+        fakeDB.commit();
+        fakeDB.close();
+        //This is key to prevent artifacts persisting between tests.
+        Paths.get("../testDB").toFile().delete();
+
+
+    }
+
+    @Test
+    public void testRemove() throws Exception {
+        //Checks removal and return values
+        fillMap(10);
+        assertEquals(10, map.size());
+        for (int i = 0; i < 10; i++) {
+            assertEquals("The previous value was wrong.", new Integer(i), map.remove(i));
+            assertNull("The previous value was wrong.", map.remove(i));
+            //(i+1) compensates for base zero.
+            assertEquals("The size was wrong.", 10 - (i + 1), map.size());
+        }
+    }
+
+    @Test
+    public void testSize() throws Exception {
+        //Checks size values throughout addition and removal
+        for (int i = 0; i < 10; i++) {
+            map.put(i, i);
+            assertEquals("The map size is wrong.", i + 1, map.size());
+        }
+        for (int i = 0; i < 10; i++) {
+            map.remove(i);
+            assertEquals("The map size is wrong.", 9 - i, map.size());
+        }
+    }
+
+    @Test
+    public void testIsEmpty() throws Exception {
+        //Checks empty condition
+        //asserts that the map starts out empty
+        assertTrue("Map should be empty", map.isEmpty());
+        map.put(1, 1);
+        assertFalse("Map shouldn't be empty.", map.isEmpty());
+        map.remove(1);
+        assertTrue("Map should be empty", map.isEmpty());
+    }
+
+    @Test
+    public void testContains() throws Exception {
+        //Checks both containsKey and containsValue be aware the implementations vary widely (value does not use mapDB
+        //due to object '=='being an insufficient check)
+        for (int i = 0; i < 10; i++) {
+            assertFalse("Map should not contain the key", map.containsKey(i));
+            assertFalse("Map should not contain the value", map.containsValue(i));
+            map.put(i, i);
+            assertTrue("Map should contain the key", map.containsKey(i));
+            assertTrue("Map should contain the value", map.containsValue(i));
+        }
+    }
+
+    @Test
+    public void testGet() throws Exception {
+        //Tests value retrieval and nonexistent key return values
+        for (int i = 0; i < 10; i++) {
+            map.put(i, i);
+            for (int j = 0; j <= i; j++) {
+                assertEquals("The value was wrong.", new Integer(j), map.get(j));
+            }
+        }
+        assertNull("Null return value for nonexistent keys.", map.get(10));
+    }
+
+    @Test
+    public void testPutAll() throws Exception {
+        //Tests adding of an outside map
+        Map<Integer, Integer> testMap = Maps.newHashMap();
+        fillMap(10);
+        map.putAll(testMap);
+        for (int i = 0; i < 10; i++) {
+            assertTrue("The map should contain the current 'i' value.", map.containsKey(i));
+            assertTrue("The map should contain the current 'i' value.", map.containsValue(i));
+        }
+    }
+
+    @Test
+    public void testClear() throws Exception {
+        //Tests clearing the map
+        assertTrue("Map was initialized incorrectly, should be empty.", map.isEmpty());
+        fillMap(10);
+        assertFalse("Map should contain entries now.", map.isEmpty());
+        map.clear();
+        assertTrue("Map should have been cleared of entries.", map.isEmpty());
+
+    }
+
+    @Test
+    public void testKeySet() throws Exception {
+        //Tests key set generation
+        fillMap(10);
+        Set<Integer> keys = map.keySet();
+        for (int i = 0; i < 10; i++) {
+            assertTrue("The key set doesn't contain all keys 0-9", keys.contains(i));
+        }
+        assertEquals("The key set has an incorrect number of entries", 10, keys.size());
+    }
+
+    @Test
+    public void testValues() throws Exception {
+        //Tests value set generation
+        fillMap(10);
+        Set<Integer> values = (Set<Integer>) map.values();
+        for (int i = 0; i < 10; i++) {
+            assertTrue("The key set doesn't contain all keys 0-9", values.contains(i));
+        }
+        assertEquals("The key set has an incorrect number of entries", 10, values.size());
+    }
+
+    @Test
+    public void testEntrySet() throws Exception {
+        //Test entry set generation (violates abstraction by knowing the type of the returned entries)
+        fillMap(10);
+        Set<Map.Entry<Integer, Integer>> entries = map.entrySet();
+        for (int i = 0; i < 10; i++) {
+            assertTrue("The key set doesn't contain all keys 0-9", entries.contains(Maps.immutableEntry(i, i)));
+        }
+        assertEquals("The key set has an incorrect number of entries", 10, entries.size());
+    }
+
+    @Test public void testPut() throws Exception {
+        //Tests insertion behavior (particularly the returning of previous value)
+        fillMap(10);
+        for (int i = 0; i < 10; i++) {
+            assertEquals("Put should return the previous value", new Integer(i), map.put(i, i + 1));
+        }
+        assertNull(map.put(11, 11));
+    }
+
+    /**
+     * Populated the map with pairs of integers from (0, 0) up to (numEntries - 1, numEntries -1).
+     * @param numEntries number of entries to add
+     */
+    private void fillMap(int numEntries) {
+        for (int i = 0; i < numEntries; i++) {
+            map.put(i, i);
+        }
+    }
+}
diff --git a/core/store/persistence/src/main/test/test/PersistentSetTest.java b/core/store/persistence/src/main/test/test/PersistentSetTest.java
new file mode 100644
index 0000000..3107ab3
--- /dev/null
+++ b/core/store/persistence/src/main/test/test/PersistentSetTest.java
@@ -0,0 +1,274 @@
+/*
+ * 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 test;
+
+import com.google.common.collect.Sets;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.mapdb.DB;
+import org.mapdb.DBMaker;
+import org.onosproject.persistence.impl.PersistentSet;
+import org.onosproject.store.service.Serializer;
+
+import java.nio.file.Paths;
+import java.util.HashSet;
+import java.util.Set;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotEquals;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+
+/**
+ * Test suite for Persistent Set.
+ */
+public class PersistentSetTest {
+
+    private Set<Integer> set = null;
+    private DB fakeDB = null;
+
+    @Before
+    public void setUp() throws Exception {
+        //Creates a db, a set within it and a basic integer serializer (async writing is off)
+        fakeDB = DBMaker
+                .newFileDB(Paths.get("../testDb").toFile())
+                .asyncWriteEnable()
+                .closeOnJvmShutdown()
+                .make();
+        set = new PersistentSet<Integer>(new Serializer() {
+            @Override
+            public <T> byte[] encode(T object) {
+                if (object == null) {
+                    return null;
+                }
+                int num = (Integer) object;
+                byte[] result = new byte[4];
+
+                result[0] = (byte) (num >> 24);
+                result[1] = (byte) (num >> 16);
+                result[2] = (byte) (num >> 8);
+                result[3] = (byte) num;
+                return result;
+            }
+
+            @Override
+            public <T> T decode(byte[] bytes) {
+                if (bytes == null) {
+                    return null;
+                }
+                int num = 0x00000000;
+
+                num = num | bytes[0] << 24;
+                num = num | bytes[1] << 16;
+                num = num | bytes[2] << 8;
+                num = num | bytes[3];
+
+                return (T) new java.lang.Integer(num);
+            }
+        }, fakeDB, "set");
+
+    }
+
+    @After
+    public void tearDown() throws Exception {
+        set.clear();
+        fakeDB.delete("map:map");
+        fakeDB.commit();
+        fakeDB.close();
+        //This is key to prevent artifacts persisting between tests.
+        Paths.get("../testDB").toFile().delete();
+    }
+
+    @Test
+    public void testSize() throws Exception {
+        //Check correct sizing throughout population
+        for (int i = 0; i < 10; i++) {
+            set.add(i);
+            assertEquals("The set should have i + 1 entries.", i + 1, set.size());
+        }
+    }
+
+    @Test
+    public void testIsEmpty() throws Exception {
+        //test empty condition
+        assertTrue("The set should be initialized empty.", set.isEmpty());
+        fillSet(5, this.set);
+        assertFalse("The set should no longer be empty.", set.isEmpty());
+        set.clear();
+        assertTrue("The set should have been cleared.", set.isEmpty());
+    }
+
+    @Test
+    public void testContains() throws Exception {
+        //Test contains
+        assertFalse("The set should not contain anything", set.contains(1));
+        fillSet(10, this.set);
+        for (int i = 0; i < 10; i++) {
+            assertTrue("The set should contain all values 0-9.", set.contains(i));
+        }
+    }
+
+    @Test
+    public void testIterator() throws Exception {
+        //Test iterator behavior (no order guarantees are made)
+        Set<Integer> validationSet = Sets.newHashSet();
+        fillSet(10, this.set);
+        fillSet(10, validationSet);
+        set.iterator().forEachRemaining(item -> assertTrue("Items were mismatched.", validationSet.remove(item)));
+        //All values should have been seen and removed
+        assertTrue("All entries in the validation set should have been removed.", validationSet.isEmpty());
+    }
+
+    @Test
+    public void testToArray() throws Exception {
+        //Test creation of a new array of the values
+        fillSet(10, set);
+        Object[] arr = set.toArray();
+        assertEquals("The array should be of length 10.", 10, arr.length);
+        for (int i = 0; i < 10; i++) {
+            assertTrue("All elements of the array should be in the set.", set.contains((Integer) arr[i]));
+        }
+    }
+
+    @Test
+    public void testToArray1() throws Exception {
+        //Test creation of a new array with the possibility of populating passed array if space allows
+        Integer[] originalArray = new Integer[9];
+        fillSet(9, set);
+        //Test the case where the array and set match in size
+        Object[] retArray = set.toArray(originalArray);
+        assertEquals("If the set can fit the array should be the one passed in.", originalArray, retArray);
+        //Test the case where the passe array is too small to fit the set
+        set.add(9);
+        assertNotEquals("A new set should be generated if the contents will not fit in the passed set",
+                        set.toArray(originalArray), originalArray);
+        //Now test the case where there should be a null terminator
+        set.clear();
+        fillSet(5, set);
+        assertNull("The character one after last should be null if the array is larger than the set.",
+                   set.toArray(originalArray)[5]);
+    }
+
+    @Test
+    public void testAdd() throws Exception {
+        //Test of add
+        for (int i = 0; i < 10; i++) {
+            assertEquals("The size of the set is wrong.", i, set.size());
+            assertTrue("The first add of an element should be true.", set.add(i));
+            assertFalse("The second add of an element should be false.", set.add(i));
+        }
+    }
+
+    @Test
+    public void testRemove() throws Exception {
+        //Test removal
+        fillSet(10, set);
+        for (int i = 0; i < 10; i++) {
+            assertEquals("The size of the set is wrong.", 10 - i, set.size());
+            assertTrue("The first removal should be true.", set.remove(i));
+            assertFalse("The second removal should be false (item no longer contained).", set.remove(i));
+        }
+        assertTrue("All elements should have been removed.", set.isEmpty());
+    }
+
+    @Test
+    public void testContainsAll() throws Exception {
+        //Test contains with short circuiting
+        Set<Integer> integersToCheck = Sets.newHashSet();
+        fillSet(10, integersToCheck);
+        fillSet(10, set);
+        assertTrue("The sets should be identical so mutual subsets.", set.containsAll(integersToCheck));
+        set.remove(9);
+        assertFalse("The set should contain one fewer value.", set.containsAll(integersToCheck));
+    }
+
+    @Test
+    public void testAddAll() throws Exception {
+        //Test multi-adds with change checking
+        Set<Integer> integersToCheck = Sets.newHashSet();
+        fillSet(10, integersToCheck);
+        assertFalse("Set should be empty and so integers to check should not be a subset.",
+                    set.containsAll(integersToCheck));
+        assertTrue("The set should have changed as a result of add all.", set.addAll(integersToCheck));
+        assertFalse("The set should not have changed as a result of add all a second time.",
+                    set.addAll(integersToCheck));
+        assertTrue("The sets should now be equivalent.", set.containsAll(integersToCheck));
+        assertTrue("The sets should now be equivalent.", integersToCheck.containsAll(set));
+    }
+
+    @Test
+    public void testRetainAll() throws Exception {
+        //Test ability to generate the intersection set
+        Set<Integer> retainSet = Sets.newHashSet();
+        fillSet(10, set);
+        assertTrue("The set should have changed.", set.retainAll(retainSet));
+        assertTrue("The set should have been emptied.", set.isEmpty());
+        fillSet(10, set);
+        fillSet(10, retainSet);
+        Set<Integer> duplicateSet = new HashSet<>(set);
+        assertFalse("The set should not have changed.", set.retainAll(retainSet));
+        assertEquals("The set should be the same as the duplicate.", duplicateSet, set);
+        retainSet.remove(9);
+        assertTrue("The set should have changed.", set.retainAll(retainSet));
+        duplicateSet.remove(9);
+        assertEquals("The set should have had the nine element removed.", duplicateSet, set);
+    }
+
+    @Test
+    public void testRemoveAll() throws Exception {
+        //Test for mass removal and change checking
+        Set<Integer> removeSet = Sets.newHashSet();
+        fillSet(10, set);
+        Set<Integer> duplicateSet = Sets.newHashSet(set);
+        assertFalse("No elements should change.", set.removeAll(removeSet));
+        assertEquals("Set should not have diverged from the duplicate.", duplicateSet, set);
+        fillSet(5, removeSet);
+        assertTrue("Elements should have been removed.", set.removeAll(removeSet));
+        assertNotEquals("Duplicate set should no longer be equivalent.", duplicateSet, set);
+        assertEquals("Five elements should have been removed from set.", 5, set.size());
+        for (Integer item : removeSet) {
+            assertFalse("No element of remove set should remain.", set.contains(item));
+        }
+    }
+
+    @Test
+    public void testClear() throws Exception {
+        //Test set emptying
+        assertTrue("The set should be initialized empty.", set.isEmpty());
+        set.clear();
+        assertTrue("Clear should have no effect on an empty set.", set.isEmpty());
+        fillSet(10, set);
+        assertFalse("The set should no longer be empty.", set.isEmpty());
+        set.clear();
+        assertTrue("The set should be empty after clear.", set.isEmpty());
+    }
+
+    /**
+     * Populated the map with integers from (0) up to (numEntries - 1).
+     *
+     * @param numEntries number of entries to add
+     */
+    private void fillSet(int numEntries, Set<Integer> set) {
+        checkNotNull(set);
+        for (int i = 0; i < numEntries; i++) {
+            set.add(i);
+        }
+    }
+}
