2 * ============LICENSE_START===================================================
3 * Copyright (c) 2018 Amdocs
4 * ============================================================================
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
9 * http://www.apache.org/licenses/LICENSE-2.0
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 * ============LICENSE_END=====================================================
19 package org.onap.sdnc.apps.pomba.servicedecomposition.test;
21 import static com.github.tomakehurst.wiremock.client.WireMock.get;
22 import static com.github.tomakehurst.wiremock.client.WireMock.notFound;
23 import static com.github.tomakehurst.wiremock.client.WireMock.okJson;
24 import static com.github.tomakehurst.wiremock.core.WireMockConfiguration.wireMockConfig;
25 import static org.junit.Assert.assertEquals;
26 import static org.junit.Assert.assertNull;
27 import static org.junit.Assert.assertTrue;
28 import static org.junit.Assert.fail;
30 import com.github.tomakehurst.wiremock.junit.WireMockRule;
31 import java.io.IOException;
32 import java.io.InputStream;
33 import java.io.InputStreamReader;
34 import java.util.Base64;
35 import javax.servlet.http.HttpServletRequest;
36 import javax.ws.rs.core.HttpHeaders;
37 import javax.ws.rs.core.Response;
38 import javax.ws.rs.core.Response.Status;
39 import org.eclipse.jetty.util.security.Password;
40 import org.json.JSONArray;
41 import org.json.JSONObject;
42 import org.junit.Rule;
43 import org.junit.Test;
44 import org.junit.runner.RunWith;
45 import org.mockito.Mockito;
46 import org.onap.logging.ref.slf4j.ONAPLogConstants;
47 import org.onap.sdnc.apps.pomba.servicedecomposition.service.rs.RestService;
48 import org.springframework.beans.factory.annotation.Autowired;
49 import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
50 import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
51 import org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration;
52 import org.springframework.boot.test.context.SpringBootTest;
53 import org.springframework.test.context.TestPropertySource;
54 import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
55 import org.springframework.test.context.web.WebAppConfiguration;
57 @RunWith(SpringJUnit4ClassRunner.class)
58 @EnableAutoConfiguration(exclude = { DataSourceAutoConfiguration.class, HibernateJpaAutoConfiguration.class })
61 @TestPropertySource(properties = {
62 "aai.httpProtocol=http",
63 "aai.serviceName=localhost",
64 "aai.servicePort=8081",
65 "basicAuth.username=admin",
66 "basicAuth.password=OBF:1u2a1toa1w8v1tok1u30"
69 public class ServiceDecompositionTest {
71 private static final String AUTH = "Basic " + Base64.getEncoder().encodeToString((
72 "admin:" + Password.deobfuscate("OBF:1u2a1toa1w8v1tok1u30")).getBytes());
74 private HttpServletRequest httpRequest = Mockito.mock(HttpServletRequest.class);
76 // TODO missing code coverage for VNFC resources
79 public WireMockRule aai = new WireMockRule(wireMockConfig().port(8081));
82 private RestService service;
85 * Simulation of the firewall demo service, using json captured from real A&AI queries.
86 * The resource relationship looks something like.
97 public void testDemoFirewallService() throws Exception {
98 // setup A&AI responses
100 "/aai/v13/nodes/service-instance/c6456519-6acf-4adb-997c-3c363dd4caaf?depth=2",
101 "junit/aai-service-instance.json");
103 "/aai/v13/network/generic-vnfs/generic-vnf/6700c313-fbb7-4cf9-ac70-0293ec56df68?depth=2",
104 "junit/aai-generic-vnf1.json");
106 "/aai/v13/network/generic-vnfs/generic-vnf/8a9ddb25-2e79-449c-a40d-5011bac0da39?depth=2",
107 "junit/aai-generic-vnf2.json");
109 "/aai/v13/cloud-infrastructure/cloud-regions/cloud-region/CloudOwner/RegionOne/tenants/tenant"
110 + "/b49b830686654191bb1e952a74b014ad/vservers/vserver/b494cd6e-b9f3-45e0-afe7-e1d1a5f5d74a?depth=2",
111 "junit/aai-vserver.json");
113 "/aai/v13/network/l3-networks/l3-network/HNP1d77c-1094-41ec-b7f3-94bb30951870?depth=2",
114 "junit/aai-l3-network1.json");
116 "/aai/v13/network/l3-networks/l3-network/HNP1d77c-1094-41ec-b7f3-94bb30951872?depth=2",
117 "junit/aai-l3-network2.json");
119 final String serviceInstanceId = "c6456519-6acf-4adb-997c-3c363dd4caaf";
120 final String vnfId1 = "6700c313-fbb7-4cf9-ac70-0293ec56df68";
121 final String vnfId2 = "8a9ddb25-2e79-449c-a40d-5011bac0da39";
122 final String vserverId = "b494cd6e-b9f3-45e0-afe7-e1d1a5f5d74a";
123 final String networkId1 = "HNP1d77c-1094-41ec-b7f3-94bb30951870";
124 final String networkId2 = "HNP1d77c-1094-41ec-b7f3-94bb30951872";
126 Response response = this.service.getContext(httpRequest, AUTH, "network-discovery-context-builder", null,
128 assertEquals(200, response.getStatus());
130 JSONObject serviceInstance = new JSONObject((String)response.getEntity());
132 // verify two generic-vnfs added to service instance data
133 verifyResource(serviceInstance, "generic-vnfs", "vnf-id", vnfId1);
134 verifyResource(serviceInstance, "generic-vnfs", "vnf-id", vnfId2);
136 JSONArray vnfs = serviceInstance.getJSONArray("generic-vnfs");
137 for (int i = 0; i < vnfs.length(); i++) {
138 JSONObject vnf = vnfs.getJSONObject(i);
139 String vnfId = vnf.getString("vnf-id");
142 // verify vserver resource
143 verifyResource(vnf, "vservers", "vserver-id", vserverId);
146 // verify network resources
147 verifyResource(vnf, "l3-networks", "network-id", networkId1);
148 verifyResource(vnf, "l3-networks", "network-id", networkId2);
151 fail("Unexpected generic-vnf " + vnfId);
157 public void testDemoFirewallServiceWithL3Networks() throws Exception {
158 // setup A&AI responses
160 "/aai/v13/nodes/service-instance/c6456519-6acf-4adb-997c-3c363dd4caaf?depth=2",
161 "junit/aai-service-instance2.json");
163 "/aai/v13/network/generic-vnfs/generic-vnf/6700c313-fbb7-4cf9-ac70-0293ec56df68?depth=2",
164 "junit/aai-generic-vnf1.json");
166 "/aai/v13/network/generic-vnfs/generic-vnf/8a9ddb25-2e79-449c-a40d-5011bac0da39?depth=2",
167 "junit/aai-generic-vnf2.json");
169 "/aai/v13/cloud-infrastructure/cloud-regions/cloud-region/CloudOwner/RegionOne/tenants/tenant"
170 + "/b49b830686654191bb1e952a74b014ad/vservers/vserver/b494cd6e-b9f3-45e0-afe7-e1d1a5f5d74a?depth=2",
171 "junit/aai-vserver.json");
173 "/aai/v13/network/l3-networks/l3-network/HNP1d77c-1094-41ec-b7f3-94bb30951870?depth=2",
174 "junit/aai-l3-network1.json");
176 "/aai/v13/network/l3-networks/l3-network/HNP1d77c-1094-41ec-b7f3-94bb30951872?depth=2",
177 "junit/aai-l3-network2.json");
179 final String serviceInstanceId = "c6456519-6acf-4adb-997c-3c363dd4caaf";
180 final String vnfId1 = "6700c313-fbb7-4cf9-ac70-0293ec56df68";
181 final String vnfId2 = "8a9ddb25-2e79-449c-a40d-5011bac0da39";
182 final String vserverId = "b494cd6e-b9f3-45e0-afe7-e1d1a5f5d74a";
183 final String networkId1 = "HNP1d77c-1094-41ec-b7f3-94bb30951870";
184 final String networkId2 = "HNP1d77c-1094-41ec-b7f3-94bb30951872";
186 Response response = this.service.getContext(httpRequest, AUTH, "network-discovery-context-builder", null,
188 assertEquals(200, response.getStatus());
190 JSONObject serviceInstance = new JSONObject((String)response.getEntity());
192 // verify two generic-vnfs added to service instance data
193 verifyResource(serviceInstance, "generic-vnfs", "vnf-id", vnfId1);
194 verifyResource(serviceInstance, "generic-vnfs", "vnf-id", vnfId2);
195 verifyResource(serviceInstance, "l3-networks", "network-id", networkId1);
197 JSONArray vnfs = serviceInstance.getJSONArray("generic-vnfs");
198 for (int i = 0; i < vnfs.length(); i++) {
199 JSONObject vnf = vnfs.getJSONObject(i);
200 String vnfId = vnf.getString("vnf-id");
203 // verify vserver resource
204 verifyResource(vnf, "vservers", "vserver-id", vserverId);
207 // verify network resources
208 verifyResource(vnf, "l3-networks", "network-id", networkId1);
209 verifyResource(vnf, "l3-networks", "network-id", networkId2);
210 JSONObject vfmodules = vnf.getJSONObject("vf-modules");
211 JSONArray vfmoduleList = vfmodules.getJSONArray("vf-module");
212 for (int j = 0; j < vfmoduleList.length(); j++) {
213 JSONObject vfmodule = vfmoduleList.getJSONObject(j);
214 verifyResource(vfmodule, "l3-networks", "network-id", networkId1);
218 fail("Unexpected generic-vnf " + vnfId);
224 public void testNoAuthHeader() throws Exception {
225 String fromAppId = "junit";
226 String transactionId = null;
227 String serviceInstanceId = "aServiceInstanceId";
228 // no Authorization header
229 Response response = this.service.getContext(httpRequest, null, fromAppId, transactionId,
231 assertEquals(Status.UNAUTHORIZED.getStatusCode(), response.getStatus());
232 // should get WWW-Authenticate header in response
233 assertTrue(response.getHeaderString(HttpHeaders.WWW_AUTHENTICATE).startsWith("Basic realm"));
237 public void testUnauthorized() throws Exception {
239 String authorization = "Basic " + Base64.getEncoder().encodeToString("aaa:bbb".getBytes());
240 String fromAppId = "junit";
241 String transactionId = null;
242 String serviceInstanceId = "aServiceInstanceId";
244 Response response = this.service.getContext(httpRequest, authorization, fromAppId,
245 transactionId, serviceInstanceId);
246 assertEquals(Status.UNAUTHORIZED.getStatusCode(), response.getStatus());
247 // should not get WWW-Authenticate header in response
248 assertNull(response.getHeaderString(HttpHeaders.WWW_AUTHENTICATE));
251 /** Fail if calling app name is missing. */
253 public void verifyFromAppId() throws Exception {
254 String fromAppId = null;
255 String transactionId = null;
256 String serviceInstanceId = "someValue";
258 Response response = this.service.getContext(httpRequest, AUTH, fromAppId, transactionId,
260 assertEquals(Status.BAD_REQUEST.getStatusCode(), response.getStatus());
261 assertTrue(((String)response.getEntity()).contains(ONAPLogConstants.Headers.PARTNER_NAME));
264 /** Fail if service instance id is missing. */
266 public void verifyServiceInstanceId() throws Exception {
267 String fromAppId = "junit";
268 String transactionId = null;
269 String serviceInstanceId = null;
271 Response response = this.service.getContext(httpRequest, AUTH, fromAppId, transactionId,
273 assertEquals(Status.BAD_REQUEST.getStatusCode(), response.getStatus());
274 assertTrue(((String)response.getEntity()).contains("service-instance-id"));
277 /** Unknown service-instance-id return HTTP 404. */
279 public void testInvalidServiceId() throws Exception {
280 aai.stubFor(get("/aai/v13/nodes/service-instance/noSuchServiceId?depth=2").willReturn(notFound()));
283 this.service.getContext(httpRequest, AUTH, "junit", null, "noSuchServiceId");
285 assertEquals(Status.NOT_FOUND.getStatusCode(), response.getStatus());
288 private void verifyResource(JSONObject parent, String arrayName, String field, String value) {
289 JSONArray array = parent.getJSONArray(arrayName);
290 for (int i = 0; i < array.length(); i++) {
291 JSONObject item = array.getJSONObject(i);
292 if (value.equals(item.getString(field))) {
296 fail("Did not find " + field + "=" + value + " in " + arrayName + " array");
299 private void addResponse(String path, String classpathResource) throws IOException {
300 String payload = readFully(ClassLoader.getSystemResourceAsStream(classpathResource));
301 aai.stubFor(get(path).willReturn(okJson(payload)));
304 private String readFully(InputStream in) throws IOException {
305 char[] cbuf = new char[1024];
306 StringBuilder content = new StringBuilder();
307 try (InputStreamReader reader = new InputStreamReader(in, "UTF-8")) {
309 while ((count = reader.read(cbuf)) >= 0) {
310 content.append(cbuf, 0, count);
313 return content.toString();