ONOS-5504: Added REST API for administering OFAgent.

Change-Id: Idc9a18fc82ec23fbb8348fe213f8007e362253ac
diff --git a/apps/ofagent/src/test/java/org/onosproject/ofagent/rest/OFAgentWebResourceTest.java b/apps/ofagent/src/test/java/org/onosproject/ofagent/rest/OFAgentWebResourceTest.java
new file mode 100644
index 0000000..026a9bc
--- /dev/null
+++ b/apps/ofagent/src/test/java/org/onosproject/ofagent/rest/OFAgentWebResourceTest.java
@@ -0,0 +1,525 @@
+/*
+ * Copyright 2017-present 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.ofagent.rest;
+
+import com.eclipsesource.json.Json;
+import com.eclipsesource.json.JsonObject;
+import com.google.common.collect.Sets;
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.test.JerseyTest;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.onlab.osgi.ServiceDirectory;
+import org.onlab.osgi.TestServiceDirectory;
+import org.onlab.packet.IpAddress;
+import org.onlab.packet.TpPort;
+import org.onlab.rest.BaseResource;
+import org.onosproject.incubator.net.virtual.NetworkId;
+import org.onosproject.ofagent.api.OFAgent;
+import org.onosproject.ofagent.api.OFAgentAdminService;
+import org.onosproject.ofagent.api.OFAgentService;
+import org.onosproject.ofagent.api.OFController;
+import org.onosproject.ofagent.impl.DefaultOFAgent;
+import org.onosproject.ofagent.impl.DefaultOFController;
+
+import javax.ws.rs.client.Entity;
+import javax.ws.rs.client.WebTarget;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.HttpURLConnection;
+import java.util.Set;
+
+import static org.easymock.EasyMock.*;
+import static org.hamcrest.Matchers.*;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertThat;
+import static org.onosproject.ofagent.api.OFAgent.State.STOPPED;
+
+
+/**
+ * Test class for OFAgent application REST resource.
+ */
+public class OFAgentWebResourceTest extends JerseyTest {
+
+
+    private static final Set<OFController> CONTROLLER_SET_1 = Sets.newHashSet(
+            DefaultOFController.of(
+                    IpAddress.valueOf("147.91.1.4"),
+                    TpPort.tpPort(6633)));
+
+    private static final Set<OFController> CONTROLLER_SET_2 = Sets.newHashSet(
+            DefaultOFController.of(
+                    IpAddress.valueOf("147.91.4.25"),
+                    TpPort.tpPort(6633)),
+            DefaultOFController.of(
+                    IpAddress.valueOf("147.91.4.27"),
+                    TpPort.tpPort(6653)));
+
+    private static final Set<OFController> CONTROLLER_SET = Sets.newHashSet(
+            DefaultOFController.of(
+                    IpAddress.valueOf("147.91.2.11"),
+                    TpPort.tpPort(6633)),
+            DefaultOFController.of(
+                    IpAddress.valueOf("147.91.2.9"),
+                    TpPort.tpPort(6633)),
+            DefaultOFController.of(
+                    IpAddress.valueOf("147.91.2.17"),
+                    TpPort.tpPort(6653)));
+
+    private static final NetworkId NETWORK_1 = NetworkId.networkId(1);
+    private static final NetworkId NETWORK_2 = NetworkId.networkId(2);
+    private static final NetworkId NETWORK = NetworkId.networkId(3);
+
+    private static final OFAgent OF_AGENT = DefaultOFAgent.builder()
+            .networkId(NETWORK)
+            .controllers(CONTROLLER_SET)
+            .state(STOPPED)
+            .build();
+
+    private Set<OFAgent> agents = Sets.newHashSet(DefaultOFAgent.builder()
+                                                  .networkId(NETWORK_1)
+                                                  .controllers(CONTROLLER_SET_1)
+                                                  .state(STOPPED)
+                                                  .build(),
+                                          DefaultOFAgent.builder()
+                                                  .networkId(NETWORK_2)
+                                                  .controllers(CONTROLLER_SET_2)
+                                                  .state(STOPPED)
+                                                  .build(),
+                                          OF_AGENT);
+
+    private Set<OFAgent> empty = Sets.newHashSet();
+
+    private final OFAgentAdminService mockOFAgentAdminService = createMock(OFAgentAdminService.class);
+    private final OFAgentService mockOFAgentService = createMock(OFAgentService.class);
+
+    /**
+     * Constructs OFAgent Web application test instance.
+     */
+    public OFAgentWebResourceTest() {
+        super(ResourceConfig.forApplicationClass(OFAgentWebApplication.class));
+    }
+
+    /**
+     * Sets up the global values for all the tests.
+     */
+    @Before
+    public void setUpMocks() {
+        ServiceDirectory testDirectory = new TestServiceDirectory()
+                .add(OFAgentAdminService.class, mockOFAgentAdminService)
+                .add(OFAgentService.class, mockOFAgentService);
+        BaseResource.setServiceDirectory(testDirectory);
+    }
+
+    /**
+     * Cleans up.
+     */
+    @After
+    public void tearDownMocks() {
+    }
+
+    /**
+     * Tests the result of the rest api GET when there are OFAgents.
+     *
+     * @throws IOException
+     */
+    @Test
+    public void testNonEmptyOFAgentSet() throws IOException {
+        expect(mockOFAgentService.agents()).andReturn(agents).anyTimes();
+        replay(mockOFAgentService);
+
+        final WebTarget wt = target();
+        assertNotNull("WebTarget is null", wt);
+        assertNotNull("WebTarget request is null", wt.request());
+        final String response = wt.path("service/ofagents").request().get(String.class);
+        final JsonObject result = Json.parse(response).asObject();
+        assertThat(result, notNullValue());
+        assertThat(result.names(), hasSize(1));
+        assertThat(result.names().get(0), is("ofAgents"));
+
+        mockOFAgentService.agents().forEach(ofAgent -> {
+
+            String expectedJsonStringNetworkId = "\"networkId\":\"" + ofAgent.networkId().id() + "\"";
+            assertThat(response, containsString(expectedJsonStringNetworkId));
+
+            String expectedJsonStringState = "\"state\":\"" + ofAgent.state() + "\"";
+            assertThat(response, containsString(expectedJsonStringState));
+
+            ofAgent.controllers().forEach(ofController -> {
+                String expectedJsonStringIP = "\"ip\":\"" + ofController.ip() + "\"";
+                assertThat(response, containsString(expectedJsonStringIP));
+
+                String expectedJsonStringPort = "\"port\":\"" + ofController.port() + "\"";
+                assertThat(response, containsString(expectedJsonStringPort));
+            });
+        });
+
+        verify(mockOFAgentService);
+    }
+
+    /**
+     * Tests the result of the rest api GET when there are no OFAgents.
+     *
+     * @throws IOException
+     */
+    @Test
+    public void testEmptyOFAgentSet() throws IOException {
+        expect(mockOFAgentService.agents()).andReturn(empty).anyTimes();
+        replay(mockOFAgentService);
+
+        final WebTarget wt = target();
+        assertNotNull("WebTarget is null", wt);
+        assertNotNull("WebTarget request is null", wt.request());
+        final String response = wt.path("service/ofagents").request().get(String.class);
+        final JsonObject result = Json.parse(response).asObject();
+        assertThat(result, notNullValue());
+        assertThat(result.names(), hasSize(1));
+        assertThat(response, is("{\"ofAgents\":[]}"));
+
+        verify(mockOFAgentService);
+    }
+
+    /**
+     * Tests the result of the rest api GET for OFAgent.
+     *
+     * @throws IOException
+     */
+    @Test
+    public void testOFAgent() throws IOException {
+        expect(mockOFAgentService.agent(eq(NETWORK))).andReturn(OF_AGENT).anyTimes();
+        replay(mockOFAgentService);
+
+        final WebTarget wt = target();
+        assertNotNull("WebTarget is null", wt);
+        assertNotNull("WebTarget request is null", wt.request());
+        final Response response = wt.path("service/ofagent/" + NETWORK).request().get();
+        final JsonObject result = Json.parse(response.readEntity(String.class)).asObject();
+        assertThat(result, notNullValue());
+        assertThat(result.names(), hasSize(3));
+        assertThat(result.get("networkId").asString(), is(NETWORK.id().toString()));
+        assertThat(result.get("state").asString(), is(STOPPED.toString()));
+
+        verify(mockOFAgentService);
+    }
+
+
+    /**
+     * Tests the result of the rest api GET for non-existent OFAgent.
+     *
+     * @throws IOException
+     */
+    @Test
+    public void testNonExistentOFAgent() throws IOException {
+        expect(mockOFAgentService.agent(anyObject())).andReturn(null).anyTimes();
+        replay(mockOFAgentService);
+
+        final WebTarget wt = target();
+        assertNotNull("WebTarget is null", wt);
+        assertNotNull("WebTarget request is null", wt.request());
+        final Response response = wt.path("service/ofagent/" + NETWORK_1).request().get();
+        assertThat(response.getStatus(), is(HttpURLConnection.HTTP_NOT_FOUND));
+
+        verify(mockOFAgentService);
+    }
+
+
+    /**
+     * Tests creating an OFAgent with POST.
+     */
+    @Test
+    public void testOFAgentCreate() {
+        mockOFAgentAdminService.createAgent(anyObject());
+        expectLastCall().anyTimes();
+        replay(mockOFAgentAdminService);
+
+
+        InputStream jsonStream = OFAgentWebResourceTest.class
+                .getResourceAsStream("post-ofagent-create.json");
+        assertNotNull("post-ofagent-create.json is null", jsonStream);
+        WebTarget wt = target();
+
+        Response response = wt.path("service/ofagent-create")
+                .request(MediaType.APPLICATION_JSON_TYPE)
+                .post(Entity.json(jsonStream));
+        assertThat(response.getStatus(), is(HttpURLConnection.HTTP_CREATED));
+
+        verify(mockOFAgentAdminService);
+    }
+
+    /**
+     * Tests creating an OFAgent with bad POST request.
+     */
+    @Test
+    public void testOFAgentCreateBadRequest() {
+        InputStream jsonStream = OFAgentWebResourceTest.class
+                .getResourceAsStream("post-bad-request.json");
+        assertNotNull("post-bad-request.json is null", jsonStream);
+        WebTarget wt = target();
+
+        Response response = wt.path("service/ofagent-create")
+                .request(MediaType.APPLICATION_JSON_TYPE)
+                .post(Entity.json(jsonStream));
+        assertThat(response.getStatus(), is(HttpURLConnection.HTTP_INTERNAL_ERROR));
+    }
+
+    /**
+     * Tests updating an OFAgent with PUT.
+     */
+    @Test
+    public void testOFAgentUpdate() {
+        expect(mockOFAgentService.agent(eq(NETWORK))).andReturn(OF_AGENT).anyTimes();
+        replay(mockOFAgentService);
+
+        mockOFAgentAdminService.updateAgent(anyObject());
+        expectLastCall().anyTimes();
+        replay(mockOFAgentAdminService);
+
+        InputStream jsonStream = OFAgentWebResourceTest.class
+                .getResourceAsStream("put-ofagent-update.json");
+        assertNotNull("put-ofagent-update.json is null", jsonStream);
+        WebTarget wt = target();
+        Response response = wt.path("service/ofagent-update")
+                .request(MediaType.APPLICATION_JSON_TYPE)
+                .put(Entity.json(jsonStream));
+        assertThat(response.getStatus(), is(HttpURLConnection.HTTP_OK));
+        assertThat(response.readEntity(String.class), containsString("OFAgent updated"));
+
+        verify(mockOFAgentService);
+        verify(mockOFAgentAdminService);
+
+    }
+
+    /**
+     * Tests non-existent OFAgent updating with PUT.
+     */
+    @Test
+    public void testNonExistentOFAgentUpdate() {
+        expect(mockOFAgentService.agent(anyObject())).andReturn(null).anyTimes();
+        replay(mockOFAgentService);
+
+        InputStream jsonStream = OFAgentWebResourceTest.class
+                .getResourceAsStream("put-non-existent-ofagent-update.json");
+        assertNotNull("put-non-existent-ofagent-update.json is null", jsonStream);
+        WebTarget wt = target();
+        Response response = wt.path("service/ofagent-update")
+                .request(MediaType.APPLICATION_JSON_TYPE)
+                .put(Entity.json(jsonStream));
+        assertThat(response.getStatus(), is(HttpURLConnection.HTTP_NOT_FOUND));
+
+        verify(mockOFAgentService);
+
+    }
+
+    /**
+     * Tests OFAgent updating with bad PUT request.
+     */
+    @Test
+    public void testOFAgentUpdateBadRequest() {
+        expect(mockOFAgentService.agent(anyObject())).andReturn(null).anyTimes();
+        replay(mockOFAgentService);
+
+        InputStream jsonStream = OFAgentWebResourceTest.class
+                .getResourceAsStream("put-bad-request.json");
+        assertNotNull("put-bad-request.json is null", jsonStream);
+        WebTarget wt = target();
+        Response response = wt.path("service/ofagent-update")
+                .request(MediaType.APPLICATION_JSON_TYPE)
+                .put(Entity.json(jsonStream));
+        assertThat(response.getStatus(), is(HttpURLConnection.HTTP_INTERNAL_ERROR));
+
+        verify(mockOFAgentService);
+    }
+
+    /**
+     * Tests starting an OFAgent with POST.
+     */
+    @Test
+    public void testOFAgentStart() {
+        expect(mockOFAgentService.agent(eq(NETWORK))).andReturn(OF_AGENT).anyTimes();
+        replay(mockOFAgentService);
+
+        mockOFAgentAdminService.startAgent(anyObject());
+        expectLastCall().anyTimes();
+        replay(mockOFAgentAdminService);
+
+        InputStream jsonStream = OFAgentWebResourceTest.class
+                .getResourceAsStream("post-ofagent-start.json");
+        assertNotNull("post-ofagent-create.json is null", jsonStream);
+        WebTarget wt = target();
+
+        Response response = wt.path("service/ofagent-start")
+                .request(MediaType.APPLICATION_JSON_TYPE)
+                .post(Entity.json(jsonStream));
+        assertThat(response.getStatus(), is(HttpURLConnection.HTTP_OK));
+//        assertThat(response.readEntity(String.class), containsString("OFAgent started"));
+        assertThat(response.readEntity(String.class), is("OFAgent started"));
+
+        verify(mockOFAgentService);
+        verify(mockOFAgentAdminService);
+    }
+
+    /**
+     * Tests non-existent OFAgent starting with POST.
+     */
+    @Test
+    public void testNonExistentOFAgentStart() {
+        expect(mockOFAgentService.agent(eq(NETWORK))).andReturn(null).anyTimes();
+        replay(mockOFAgentService);
+
+        InputStream jsonStream = OFAgentWebResourceTest.class
+                .getResourceAsStream("post-non-existent-ofagent-start.json");
+        assertNotNull("post-non-existent-ofagent-start.json is null", jsonStream);
+        WebTarget wt = target();
+
+        Response response = wt.path("service/ofagent-start")
+                .request(MediaType.APPLICATION_JSON_TYPE)
+                .post(Entity.json(jsonStream));
+        assertThat(response.getStatus(), is(HttpURLConnection.HTTP_NOT_FOUND));
+
+        verify(mockOFAgentService);
+    }
+
+    /**
+     * Tests OFAgent starting with bad POST request.
+     */
+    @Test
+    public void testOFAgentStartBadRequest() {
+
+        InputStream jsonStream = OFAgentWebResourceTest.class
+                .getResourceAsStream("post-bad-request.json");
+        assertNotNull("post-bad-request.json is null", jsonStream);
+        WebTarget wt = target();
+
+        Response response = wt.path("service/ofagent-start")
+                .request(MediaType.APPLICATION_JSON_TYPE)
+                .post(Entity.json(jsonStream));
+        assertThat(response.getStatus(), is(HttpURLConnection.HTTP_BAD_REQUEST));
+
+    }
+
+    /**
+     * Tests stopping an OFAgent with POST.
+     */
+    @Test
+    public void testOFAgentStop() {
+        expect(mockOFAgentService.agent(eq(NETWORK))).andReturn(OF_AGENT).anyTimes();
+        replay(mockOFAgentService);
+
+        mockOFAgentAdminService.stopAgent(anyObject());
+        expectLastCall().anyTimes();
+        replay(mockOFAgentAdminService);
+
+        InputStream jsonStream = OFAgentWebResourceTest.class
+                .getResourceAsStream("post-ofagent-stop.json");
+        assertNotNull("post-ofagent-stop.json is null", jsonStream);
+        WebTarget wt = target();
+        Response response = wt.path("service/ofagent-stop")
+                .request(MediaType.APPLICATION_JSON_TYPE)
+                .post(Entity.json(jsonStream));
+        assertThat(response.getStatus(), is(HttpURLConnection.HTTP_NO_CONTENT));
+
+        verify(mockOFAgentService);
+        verify(mockOFAgentAdminService);
+    }
+
+    /**
+     * Tests stopping non-existent OFAgent with POST.
+     */
+    @Test
+    public void testNonExistentOFAgentStop() {
+        expect(mockOFAgentService.agent(NETWORK)).andReturn(null).anyTimes();
+        replay(mockOFAgentService);
+
+        InputStream jsonStream = OFAgentWebResourceTest.class
+                .getResourceAsStream("post-non-existent-ofagent-stop.json");
+        assertNotNull("post-non-existent-ofagent-stop.json is null", jsonStream);
+        WebTarget wt = target();
+
+        Response response = wt.path("service/ofagent-stop")
+                .request(MediaType.APPLICATION_JSON_TYPE)
+                .post(Entity.json(jsonStream));
+        assertThat(response.getStatus(), is(HttpURLConnection.HTTP_NOT_FOUND));
+
+        verify(mockOFAgentService);
+    }
+
+    /**
+     * Tests stopping FAgent with bad POST request.
+     */
+    @Test
+    public void testOFAgentStopBadRequest() {
+        InputStream jsonStream = OFAgentWebResourceTest.class
+                .getResourceAsStream("post-bad-request.json");
+        assertNotNull("post-bad-request.json is null", jsonStream);
+        WebTarget wt = target();
+
+        Response response = wt.path("service/ofagent-stop")
+                .request(MediaType.APPLICATION_JSON_TYPE)
+                .post(Entity.json(jsonStream));
+        assertThat(response.getStatus(), is(HttpURLConnection.HTTP_INTERNAL_ERROR));
+    }
+
+
+    /**
+     * Tests deleting an OFAgent with DELETE.
+     */
+    @Test
+    public void testOFAgentRemove() {
+        expect(mockOFAgentService.agent(eq(NETWORK))).andReturn(OF_AGENT).anyTimes();
+        replay(mockOFAgentService);
+
+        expect(mockOFAgentAdminService.removeAgent(NETWORK)).andReturn(OF_AGENT).anyTimes();
+        replay(mockOFAgentAdminService);
+
+        WebTarget wt = target();
+        Response response = wt.path("service/ofagent-remove/" + NETWORK.toString())
+                .request(MediaType.APPLICATION_JSON_TYPE)
+                .delete();
+        assertThat(response.getStatus(), is(HttpURLConnection.HTTP_OK));
+        final JsonObject result = Json.parse(response.readEntity(String.class)).asObject();
+        assertThat(result.get("networkId").asString(), is(NETWORK.id().toString()));
+        assertThat(result.get("state").asString(), is(STOPPED.toString()));
+
+        verify(mockOFAgentService);
+        verify(mockOFAgentAdminService);
+    }
+
+    /**
+     * Tests deleting a non-existent OFAgent with DELETE.
+     */
+    @Test
+    public void testNonExistentOFAgentRemove() {
+        expect(mockOFAgentService.agent(eq(NETWORK))).andReturn(null).anyTimes();
+        replay(mockOFAgentService);
+
+        expect(mockOFAgentAdminService.removeAgent(NETWORK)).andReturn(null).anyTimes();
+        replay(mockOFAgentAdminService);
+
+        WebTarget wt = target();
+        Response response = wt.path("service/ofagent-remove/" + NETWORK.toString())
+                .request(MediaType.APPLICATION_JSON_TYPE)
+                .delete();
+        assertThat(response.getStatus(), is(HttpURLConnection.HTTP_BAD_REQUEST));
+        assertThat(response.readEntity(String.class), containsString("OFAgent not found"));
+
+        verify(mockOFAgentService);
+        verify(mockOFAgentAdminService);
+    }
+}