Unit tests for network config REST API.

Change-Id: I1b09035ff7aaa463889f62bbc9709a37a920d800
diff --git a/web/api/src/test/java/org/onosproject/rest/resources/NetworkConfigWebResourceTest.java b/web/api/src/test/java/org/onosproject/rest/resources/NetworkConfigWebResourceTest.java
new file mode 100644
index 0000000..2b341af
--- /dev/null
+++ b/web/api/src/test/java/org/onosproject/rest/resources/NetworkConfigWebResourceTest.java
@@ -0,0 +1,352 @@
+/*
+ * 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.rest.resources;
+
+import java.net.HttpURLConnection;
+import java.util.HashSet;
+import java.util.Set;
+
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+import org.onlab.osgi.ServiceDirectory;
+import org.onlab.osgi.TestServiceDirectory;
+import org.onlab.rest.BaseResource;
+import org.onosproject.net.DefaultDevice;
+import org.onosproject.net.Device;
+import org.onosproject.net.Link;
+import org.onosproject.net.config.Config;
+import org.onosproject.net.config.NetworkConfigService;
+import org.onosproject.net.config.NetworkConfigServiceAdapter;
+import org.onosproject.net.config.SubjectFactory;
+import org.onosproject.rest.ResourceTest;
+
+import com.eclipsesource.json.JsonObject;
+import com.eclipsesource.json.JsonValue;
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.google.common.collect.ImmutableSet;
+import com.sun.jersey.api.client.UniformInterfaceException;
+import com.sun.jersey.api.client.WebResource;
+
+import static org.easymock.EasyMock.createMock;
+import static org.easymock.EasyMock.replay;
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.containsString;
+import static org.hamcrest.Matchers.hasSize;
+import static org.hamcrest.Matchers.is;
+import static org.hamcrest.Matchers.notNullValue;
+import static org.junit.Assert.fail;
+
+/**
+ * Unit tests for network config web resource.
+ */
+public class NetworkConfigWebResourceTest extends ResourceTest {
+
+    MockNetworkConfigService mockNetworkConfigService;
+
+    public class MockDeviceConfig extends Config<Device> {
+
+        final String field1Value;
+        final String field2Value;
+
+        MockDeviceConfig(String value1, String value2) {
+            field1Value = value1;
+            field2Value = value2;
+        }
+
+        @Override
+        public String key() {
+            return "basic";
+        }
+
+        @Override
+        public JsonNode node() {
+            return new ObjectMapper()
+                    .createObjectNode()
+                    .put("field1", field1Value)
+                    .put("field2", field2Value);
+        }
+    }
+
+    /**
+     * Mock config factory for devices.
+     */
+    private final SubjectFactory<Device> mockDevicesSubjectFactory =
+            new SubjectFactory<Device>(Device.class, "devices") {
+                @Override
+                public Device createSubject(String subjectKey) {
+                    DefaultDevice device = createMock(DefaultDevice.class);
+                    replay(device);
+                    return device;
+                }
+
+                @Override
+                public Class<Device> subjectClass() {
+                    return Device.class;
+                }
+            };
+
+    /**
+     * Mock config factory for links.
+     */
+    private final SubjectFactory<Link> mockLinksSubjectFactory =
+            new SubjectFactory<Link>(Link.class, "links") {
+                @Override
+                public Link createSubject(String subjectKey) {
+                    return null;
+                }
+
+                @Override
+                public Class<Link> subjectClass() {
+                    return Link.class;
+                }
+            };
+
+    /**
+     * Mocked config service.
+     */
+    class MockNetworkConfigService extends NetworkConfigServiceAdapter {
+
+        Set devicesSubjects = new HashSet<>();
+        Set devicesConfigs = new HashSet<>();
+        Set linksSubjects = new HashSet();
+        Set linksConfigs = new HashSet<>();
+
+        @Override
+        public Set<Class> getSubjectClasses() {
+            return ImmutableSet.of(Device.class, Link.class);
+        }
+
+        @Override
+        public SubjectFactory getSubjectFactory(Class subjectClass) {
+            if (subjectClass == Device.class) {
+                return mockDevicesSubjectFactory;
+            } else if (subjectClass == Link.class) {
+                return mockLinksSubjectFactory;
+            }
+            return null;
+        }
+
+        @Override
+        public SubjectFactory getSubjectFactory(String subjectClassKey) {
+            if (subjectClassKey.equals("devices")) {
+                return mockDevicesSubjectFactory;
+            } else if (subjectClassKey.equals("links")) {
+                return mockLinksSubjectFactory;
+            }
+            return null;
+        }
+
+        @SuppressWarnings("unchecked")
+        @Override
+        public <S> Set<S> getSubjects(Class<S> subjectClass) {
+            if (subjectClass == Device.class) {
+                return devicesSubjects;
+            } else if (subjectClass == Link.class) {
+                return linksSubjects;
+            }
+            return null;
+        }
+
+        @SuppressWarnings("unchecked")
+        @Override
+        public <S> Set<? extends Config<S>> getConfigs(S subject) {
+            if (subject instanceof Device || subject.toString().contains("device")) {
+                return devicesConfigs;
+            } else if (subject.toString().contains("link")) {
+                return linksConfigs;
+            }
+            return null;
+        }
+
+        @SuppressWarnings("unchecked")
+        @Override
+        public <S, C extends Config<S>> C getConfig(S subject, Class<C> configClass) {
+
+            if (configClass == MockDeviceConfig.class) {
+                return (C) devicesConfigs.toArray()[0];
+            }
+            return null;
+        }
+
+        @Override
+        public Class<? extends Config> getConfigClass(String subjectClassKey, String configKey) {
+            return MockDeviceConfig.class;
+        }
+    }
+
+    /**
+     * Sets up mocked config service.
+     */
+    @Before
+    public void setUp() {
+        mockNetworkConfigService = new MockNetworkConfigService();
+        ServiceDirectory testDirectory =
+                new TestServiceDirectory()
+                .add(NetworkConfigService.class, mockNetworkConfigService);
+        BaseResource.setServiceDirectory(testDirectory);
+    }
+
+    /**
+     * Sets up test config data.
+     */
+    @SuppressWarnings("unchecked")
+    public void setUpConfigData() {
+        mockNetworkConfigService.devicesSubjects.add("device1");
+        mockNetworkConfigService.devicesConfigs.add(new MockDeviceConfig("v1", "v2"));
+    }
+
+    /**
+     * Tests the result of the rest api GET when there are no configs.
+     */
+    @Test
+    public void testEmptyConfigs() {
+        final WebResource rs = resource();
+        final String response = rs.path("network/configuration").get(String.class);
+
+        assertThat(response, containsString("\"devices\":{}"));
+        assertThat(response, containsString("\"links\":{}"));
+    }
+
+    /**
+     * Tests the result of the rest api GET for a single subject with no configs.
+     */
+    @Test
+    public void testEmptyConfig() {
+        final WebResource rs = resource();
+        final String response = rs.path("network/configuration/devices").get(String.class);
+
+        assertThat(response, is("{}"));
+    }
+
+    /**
+     * Tests the result of the rest api GET for a single subject that
+     * is undefined.
+     */
+    @Test
+    public void testNonExistentConfig() {
+        final WebResource rs = resource();
+
+        try {
+            final String response = rs.path("network/configuration/nosuchkey").get(String.class);
+            fail("GET of non-existent key does not produce an exception " + response);
+        } catch (UniformInterfaceException e) {
+            assertThat(e.getResponse().getStatus(), is(HttpURLConnection.HTTP_NOT_FOUND));
+        }
+    }
+
+    private void checkBasicAttributes(JsonValue basic) {
+        Assert.assertThat(basic.asObject().get("field1").asString(), is("v1"));
+        Assert.assertThat(basic.asObject().get("field2").asString(), is("v2"));
+    }
+
+    /**
+     * Tests the result of the rest api GET when there is a config.
+     */
+    @Test
+
+    public void testConfigs() {
+        setUpConfigData();
+        final WebResource rs = resource();
+        final String response = rs.path("network/configuration").get(String.class);
+
+        final JsonObject result = JsonObject.readFrom(response);
+        Assert.assertThat(result, notNullValue());
+
+        Assert.assertThat(result.names(), hasSize(2));
+
+        JsonValue devices = result.get("devices");
+        Assert.assertThat(devices, notNullValue());
+
+        JsonValue device1 = devices.asObject().get("device1");
+        Assert.assertThat(device1, notNullValue());
+
+        JsonValue basic = device1.asObject().get("basic");
+        Assert.assertThat(basic, notNullValue());
+
+        checkBasicAttributes(basic);
+    }
+
+    /**
+     * Tests the result of the rest api single subject key GET when
+     * there is a config.
+     */
+    @Test
+    public void testSingleSubjectKeyConfig() {
+        setUpConfigData();
+        final WebResource rs = resource();
+        final String response = rs.path("network/configuration/devices").get(String.class);
+
+        final JsonObject result = JsonObject.readFrom(response);
+        Assert.assertThat(result, notNullValue());
+
+        Assert.assertThat(result.names(), hasSize(1));
+
+        JsonValue device1 = result.asObject().get("device1");
+        Assert.assertThat(device1, notNullValue());
+
+        JsonValue basic = device1.asObject().get("basic");
+        Assert.assertThat(basic, notNullValue());
+
+        checkBasicAttributes(basic);
+    }
+
+    /**
+     * Tests the result of the rest api single subject GET when
+     * there is a config.
+     */
+    @Test
+    public void testSingleSubjectConfig() {
+        setUpConfigData();
+        final WebResource rs = resource();
+        final String response =
+                rs.path("network/configuration/devices/device1")
+                        .get(String.class);
+
+        final JsonObject result = JsonObject.readFrom(response);
+        Assert.assertThat(result, notNullValue());
+
+        Assert.assertThat(result.names(), hasSize(1));
+
+        JsonValue basic = result.asObject().get("basic");
+        Assert.assertThat(basic, notNullValue());
+
+        checkBasicAttributes(basic);
+    }
+
+    /**
+     * Tests the result of the rest api single subject single config GET when
+     * there is a config.
+     */
+    @Test
+    public void testSingleSubjectSingleConfig() {
+        setUpConfigData();
+        final WebResource rs = resource();
+        final String response =
+                rs.path("network/configuration/devices/device1/basic")
+                        .get(String.class);
+
+        final JsonObject result = JsonObject.readFrom(response);
+        Assert.assertThat(result, notNullValue());
+
+        Assert.assertThat(result.names(), hasSize(2));
+
+        checkBasicAttributes(result);
+    }
+
+    // TODO: Add test for DELETE and POST
+}