* ============LICENSE_START=======================================================
* ONAP
* ================================================================================
- * Copyright (C) 2020 AT&T Intellectual Property. All rights reserved.
+ * Copyright (C) 2020-2021 AT&T Intellectual Property. All rights reserved.
+ * Modifications Copyright (C) 2023 Nordix Foundation.
* ================================================================================
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatCode;
+import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException;
import static org.assertj.core.api.Assertions.assertThatThrownBy;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertSame;
import static org.junit.Assert.assertTrue;
-import static org.mockito.Mockito.spy;
+import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.when;
-import ch.qos.logback.classic.Logger;
+import jakarta.ws.rs.Consumes;
+import jakarta.ws.rs.DELETE;
+import jakarta.ws.rs.GET;
+import jakarta.ws.rs.POST;
+import jakarta.ws.rs.PUT;
+import jakarta.ws.rs.Path;
+import jakarta.ws.rs.Produces;
+import jakarta.ws.rs.client.Entity;
+import jakarta.ws.rs.client.InvocationCallback;
+import jakarta.ws.rs.core.MediaType;
+import jakarta.ws.rs.core.Response;
+import jakarta.ws.rs.core.Response.Status;
import java.util.Collections;
-import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.UUID;
import java.util.concurrent.CancellationException;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
+import java.util.concurrent.Executor;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import java.util.concurrent.atomic.AtomicReference;
-import javax.ws.rs.Consumes;
-import javax.ws.rs.DELETE;
-import javax.ws.rs.GET;
-import javax.ws.rs.POST;
-import javax.ws.rs.PUT;
-import javax.ws.rs.Path;
-import javax.ws.rs.Produces;
-import javax.ws.rs.client.Entity;
-import javax.ws.rs.client.InvocationCallback;
-import javax.ws.rs.core.MediaType;
-import javax.ws.rs.core.Response;
-import javax.ws.rs.core.Response.Status;
import lombok.Getter;
import lombok.Setter;
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
+import org.junit.runner.RunWith;
import org.mockito.Mock;
-import org.mockito.MockitoAnnotations;
+import org.mockito.junit.MockitoJUnitRunner;
+import org.onap.policy.common.endpoints.event.comm.Topic.CommInfrastructure;
import org.onap.policy.common.endpoints.event.comm.bus.internal.BusTopicParams;
import org.onap.policy.common.endpoints.event.comm.bus.internal.BusTopicParams.TopicParamsBuilder;
import org.onap.policy.common.endpoints.http.client.HttpClient;
+import org.onap.policy.common.endpoints.http.client.HttpClientFactory;
import org.onap.policy.common.endpoints.http.client.HttpClientFactoryInstance;
import org.onap.policy.common.endpoints.http.server.HttpServletServer;
import org.onap.policy.common.endpoints.http.server.HttpServletServerFactoryInstance;
import org.onap.policy.common.endpoints.properties.PolicyEndPointProperties;
+import org.onap.policy.common.endpoints.utils.NetLoggerUtil.EventType;
import org.onap.policy.common.gson.GsonMessageBodyHandler;
-import org.onap.policy.common.utils.coder.Coder;
import org.onap.policy.common.utils.coder.CoderException;
-import org.onap.policy.common.utils.coder.StandardCoder;
import org.onap.policy.common.utils.network.NetworkUtil;
-import org.onap.policy.common.utils.test.log.logback.ExtractAppender;
-import org.onap.policy.controlloop.VirtualControlLoopEvent;
-import org.onap.policy.controlloop.actorserviceprovider.Operation;
import org.onap.policy.controlloop.actorserviceprovider.OperationOutcome;
-import org.onap.policy.controlloop.actorserviceprovider.Util;
-import org.onap.policy.controlloop.actorserviceprovider.controlloop.ControlLoopEventContext;
+import org.onap.policy.controlloop.actorserviceprovider.OperationResult;
import org.onap.policy.controlloop.actorserviceprovider.parameters.ControlLoopOperationParams;
+import org.onap.policy.controlloop.actorserviceprovider.parameters.HttpConfig;
import org.onap.policy.controlloop.actorserviceprovider.parameters.HttpParams;
-import org.onap.policy.controlloop.policy.PolicyResult;
-import org.slf4j.LoggerFactory;
+@RunWith(MockitoJUnitRunner.class)
public class HttpOperationTest {
private static final IllegalStateException EXPECTED_EXCEPTION = new IllegalStateException("expected exception");
private static final String HTTP_CLIENT = "my-client";
private static final String HTTP_NO_SERVER = "my-http-no-server-client";
private static final String MEDIA_TYPE_APPLICATION_JSON = "application/json";
- private static final String MY_REQUEST = "my-request";
private static final String BASE_URI = "oper";
private static final String PATH = "/my-path";
private static final String TEXT = "my-text";
private static final UUID REQ_ID = UUID.randomUUID();
- /**
- * Used to attach an appender to the class' logger.
- */
- private static final Logger logger = (Logger) LoggerFactory.getLogger(HttpOperation.class);
- private static final ExtractAppender appender = new ExtractAppender();
-
/**
* {@code True} if the server should reject the request, {@code false} otherwise.
*/
@Mock
private HttpClient client;
-
+ @Mock
+ private HttpClientFactory clientFactory;
@Mock
private Response response;
+ @Mock
+ private Executor executor;
- private VirtualControlLoopEvent event;
- private ControlLoopEventContext context;
private ControlLoopOperationParams params;
private OperationOutcome outcome;
private AtomicReference<InvocationCallback<Response>> callback;
private Future<Response> future;
- private HttpOperator operator;
+ private HttpConfig config;
private MyGetOperation<String> oper;
/**
/*
* Start the clients, one to the server, and one to a non-existent server.
*/
- TopicParamsBuilder builder = BusTopicParams.builder().managed(true).hostname("localhost").basePath(BASE_URI)
- .serializationProvider(GsonMessageBodyHandler.class.getName());
+ TopicParamsBuilder builder = BusTopicParams.builder().managed(true).hostname("localhost").basePath(BASE_URI);
HttpClientFactoryInstance.getClientFactory().build(builder.clientName(HTTP_CLIENT).port(port).build());
HttpClientFactoryInstance.getClientFactory()
.build(builder.clientName(HTTP_NO_SERVER).port(NetworkUtil.allocPort()).build());
-
- /**
- * Attach appender to the logger.
- */
- appender.setContext(logger.getLoggerContext());
- appender.start();
-
- logger.addAppender(appender);
}
/**
*/
@AfterClass
public static void tearDownAfterClass() {
- appender.stop();
-
HttpClientFactoryInstance.getClientFactory().destroy();
HttpServletServerFactoryInstance.getServerFactory().destroy();
}
*/
@Before
public void setUp() {
- MockitoAnnotations.initMocks(this);
-
- appender.clearExtractions();
-
rejectRequest = false;
nget = 0;
npost = 0;
when(response.readEntity(String.class)).thenReturn(TEXT);
when(response.getStatus()).thenReturn(200);
- event = new VirtualControlLoopEvent();
- event.setRequestId(REQ_ID);
-
- context = new ControlLoopEventContext(event);
- params = ControlLoopOperationParams.builder().actor(ACTOR).operation(OPERATION).context(context).build();
+ params = ControlLoopOperationParams.builder().actor(ACTOR).operation(OPERATION).requestId(REQ_ID).build();
outcome = params.makeOutcome();
callback = new AtomicReference<>();
future = new CompletableFuture<>();
- operator = new HttpOperator(ACTOR, OPERATION) {
- @Override
- public Operation buildOperation(ControlLoopOperationParams params) {
- return null;
- }
-
- @Override
- public HttpClient getClient() {
- return client;
- }
- };
+ when(clientFactory.get(any())).thenReturn(client);
- initOper(operator, HTTP_CLIENT);
+ initConfig(HTTP_CLIENT);
oper = new MyGetOperation<>(String.class);
}
}
@Test
- public void testMakePath() {
- assertEquals(PATH, oper.makePath());
+ public void testGetPath() {
+ assertEquals(PATH, oper.getPath());
}
@Test
public void testMakeUrl() {
// use a real client
- client = HttpClientFactoryInstance.getClientFactory().get(HTTP_CLIENT);
+ initRealConfig(HTTP_CLIENT);
+
+ oper = new MyGetOperation<>(String.class);
- assertThat(oper.makeUrl()).endsWith("/" + BASE_URI + PATH);
+ assertThat(oper.getUrl()).endsWith("/" + BASE_URI + PATH);
}
@Test
public void testDoConfigureMapOfStringObject_testGetClient_testGetPath_testGetTimeoutMs() {
- // no default yet
- assertEquals(0L, oper.getTimeoutMs(null));
- assertEquals(0L, oper.getTimeoutMs(0));
+ // use value from operator
+ assertEquals(1000L, oper.getTimeoutMs(null));
+ assertEquals(1000L, oper.getTimeoutMs(0));
// should use given value
assertEquals(20 * 1000L, oper.getTimeoutMs(20));
-
- // indicate we have a timeout value
- operator = spy(operator);
- when(operator.getTimeoutMs()).thenReturn(30L);
-
- oper = new MyGetOperation<String>(String.class);
-
- // should use default
- assertEquals(30L, oper.getTimeoutMs(null));
- assertEquals(30L, oper.getTimeoutMs(0));
-
- // should use given value
- assertEquals(40 * 1000L, oper.getTimeoutMs(40));
}
/**
callback.get().completed(response);
assertSame(outcome, future2.get(5, TimeUnit.SECONDS));
+ assertSame(TEXT, outcome.getResponse());
- assertEquals(PolicyResult.SUCCESS, outcome.getResult());
+ assertEquals(OperationResult.SUCCESS, outcome.getResult());
}
/**
* Tests processResponse() when it's a success and the response type is a String.
*/
@Test
- public void testProcessResponseSuccessString() {
- assertSame(outcome, oper.processResponse(outcome, PATH, response));
- assertEquals(PolicyResult.SUCCESS, outcome.getResult());
+ public void testProcessResponseSuccessString() throws Exception {
+ CompletableFuture<OperationOutcome> result = oper.processResponse(outcome, PATH, response);
+ assertTrue(result.isDone());
+ assertSame(outcome, result.get());
+ assertEquals(OperationResult.SUCCESS, outcome.getResult());
+ assertSame(TEXT, outcome.getResponse());
}
/**
* Tests processResponse() when it's a failure.
*/
@Test
- public void testProcessResponseFailure() {
+ public void testProcessResponseFailure() throws Exception {
when(response.getStatus()).thenReturn(555);
- assertSame(outcome, oper.processResponse(outcome, PATH, response));
- assertEquals(PolicyResult.FAILURE, outcome.getResult());
+ CompletableFuture<OperationOutcome> result = oper.processResponse(outcome, PATH, response);
+ assertTrue(result.isDone());
+ assertSame(outcome, result.get());
+ assertEquals(OperationResult.FAILURE, outcome.getResult());
+ assertSame(TEXT, outcome.getResponse());
}
/**
* Tests processResponse() when the decoder succeeds.
*/
@Test
- public void testProcessResponseDecodeOk() throws CoderException {
+ public void testProcessResponseDecodeOk() throws Exception {
when(response.readEntity(String.class)).thenReturn("10");
MyGetOperation<Integer> oper2 = new MyGetOperation<>(Integer.class);
- assertSame(outcome, oper2.processResponse(outcome, PATH, response));
- assertEquals(PolicyResult.SUCCESS, outcome.getResult());
+ CompletableFuture<OperationOutcome> result = oper2.processResponse(outcome, PATH, response);
+ assertTrue(result.isDone());
+ assertSame(outcome, result.get());
+ assertEquals(OperationResult.SUCCESS, outcome.getResult());
+ assertEquals(Integer.valueOf(10), outcome.getResponse());
}
/**
public void testProcessResponseDecodeExcept() throws CoderException {
MyGetOperation<Integer> oper2 = new MyGetOperation<>(Integer.class);
- assertSame(outcome, oper2.processResponse(outcome, PATH, response));
- assertEquals(PolicyResult.FAILURE_EXCEPTION, outcome.getResult());
+ assertThatIllegalArgumentException().isThrownBy(() -> oper2.processResponse(outcome, PATH, response));
}
@Test
@Test
public void testGet() throws Exception {
// use a real client
- client = HttpClientFactoryInstance.getClientFactory().get(HTTP_CLIENT);
+ initRealConfig(HTTP_CLIENT);
MyGetOperation<MyResponse> oper2 = new MyGetOperation<>(MyResponse.class);
OperationOutcome outcome = runOperation(oper2);
assertNotNull(outcome);
assertEquals(1, nget);
- assertEquals(PolicyResult.SUCCESS, outcome.getResult());
+ assertEquals(OperationResult.SUCCESS, outcome.getResult());
+ assertTrue(outcome.getResponse() instanceof MyResponse);
}
/**
@Test
public void testDelete() throws Exception {
// use a real client
- client = HttpClientFactoryInstance.getClientFactory().get(HTTP_CLIENT);
+ initRealConfig(HTTP_CLIENT);
MyDeleteOperation oper2 = new MyDeleteOperation();
OperationOutcome outcome = runOperation(oper2);
assertNotNull(outcome);
assertEquals(1, ndelete);
- assertEquals(PolicyResult.SUCCESS, outcome.getResult());
+ assertEquals(OperationResult.SUCCESS, outcome.getResult());
+ assertTrue(outcome.getResponse() instanceof String);
}
/**
@Test
public void testPost() throws Exception {
// use a real client
- client = HttpClientFactoryInstance.getClientFactory().get(HTTP_CLIENT);
-
+ initRealConfig(HTTP_CLIENT);
MyPostOperation oper2 = new MyPostOperation();
OperationOutcome outcome = runOperation(oper2);
assertNotNull(outcome);
assertEquals(1, npost);
- assertEquals(PolicyResult.SUCCESS, outcome.getResult());
+ assertEquals(OperationResult.SUCCESS, outcome.getResult());
+ assertTrue(outcome.getResponse() instanceof MyResponse);
}
/**
@Test
public void testPut() throws Exception {
// use a real client
- client = HttpClientFactoryInstance.getClientFactory().get(HTTP_CLIENT);
+ initRealConfig(HTTP_CLIENT);
MyPutOperation oper2 = new MyPutOperation();
OperationOutcome outcome = runOperation(oper2);
assertNotNull(outcome);
assertEquals(1, nput);
- assertEquals(PolicyResult.SUCCESS, outcome.getResult());
- }
-
- @Test
- public void testLogRestRequest() throws CoderException {
- // log structured data
- appender.clearExtractions();
- oper.logRestRequest(PATH, new MyRequest());
- List<String> output = appender.getExtracted();
- assertEquals(1, output.size());
-
- assertThat(output.get(0)).contains(PATH).contains("{\n \"input\": \"some input\"\n}");
-
- // log a plain string
- appender.clearExtractions();
- oper.logRestRequest(PATH, MY_REQUEST);
- output = appender.getExtracted();
- assertEquals(1, output.size());
-
- assertThat(output.get(0)).contains(PATH).contains(MY_REQUEST);
-
- // log a null request
- appender.clearExtractions();
- oper.logRestRequest(PATH, null);
- output = appender.getExtracted();
- assertEquals(1, output.size());
-
- // exception from coder
- oper = new MyGetOperation<>(String.class) {
- @Override
- protected Coder makeCoder() {
- return new StandardCoder() {
- @Override
- public String encode(Object object, boolean pretty) throws CoderException {
- throw new CoderException(EXPECTED_EXCEPTION);
- }
- };
- }
- };
-
- appender.clearExtractions();
- oper.logRestRequest(PATH, new MyRequest());
- output = appender.getExtracted();
- assertEquals(2, output.size());
- assertThat(output.get(0)).contains("cannot pretty-print request");
- assertThat(output.get(1)).contains(PATH);
- }
-
- @Test
- public void testLogRestResponse() throws CoderException {
- // log structured data
- appender.clearExtractions();
- oper.logRestResponse(PATH, new MyResponse());
- List<String> output = appender.getExtracted();
- assertEquals(1, output.size());
-
- assertThat(output.get(0)).contains(PATH).contains("{\n \"output\": \"some output\"\n}");
-
- // log a plain string
- appender.clearExtractions();
- oper.logRestResponse(PATH, MY_REQUEST);
- output = appender.getExtracted();
- assertEquals(1, output.size());
-
- // log a null response
- appender.clearExtractions();
- oper.logRestResponse(PATH, null);
- output = appender.getExtracted();
- assertEquals(1, output.size());
-
- assertThat(output.get(0)).contains(PATH).contains("null");
-
- // exception from coder
- oper = new MyGetOperation<>(String.class) {
- @Override
- protected Coder makeCoder() {
- return new StandardCoder() {
- @Override
- public String encode(Object object, boolean pretty) throws CoderException {
- throw new CoderException(EXPECTED_EXCEPTION);
- }
- };
- }
- };
-
- appender.clearExtractions();
- oper.logRestResponse(PATH, new MyResponse());
- output = appender.getExtracted();
- assertEquals(2, output.size());
- assertThat(output.get(0)).contains("cannot pretty-print response");
- assertThat(output.get(1)).contains(PATH);
+ assertEquals(OperationResult.SUCCESS, outcome.getResult());
+ assertTrue(outcome.getResponse() instanceof MyResponse);
}
@Test
public void testMakeDecoder() {
- assertNotNull(oper.makeCoder());
+ assertNotNull(oper.getCoder());
}
/**
}
/**
- * Initializes the given operator.
+ * Initializes the configuration.
*
- * @param operator operator to be initialized
* @param clientName name of the client which it should use
*/
- private void initOper(HttpOperator operator, String clientName) {
- operator.stop();
+ private void initConfig(String clientName) {
+ initConfig(clientName, clientFactory);
+ }
- HttpParams params = HttpParams.builder().clientName(clientName).path(PATH).build();
- Map<String, Object> mapParams = Util.translateToMap(OPERATION, params);
- operator.configure(mapParams);
- operator.start();
+ /**
+ * Initializes the configuration with a real client.
+ *
+ * @param clientName name of the client which it should use
+ */
+ private void initConfig(String clientName, HttpClientFactory factory) {
+ HttpParams params = HttpParams.builder().clientName(clientName).path(PATH).timeoutSec(1).build();
+ config = new HttpConfig(executor, params, factory);
+ }
+
+ /**
+ * Initializes the configuration with a real client.
+ *
+ * @param clientName name of the client which it should use
+ */
+ private void initRealConfig(String clientName) {
+ initConfig(clientName, HttpClientFactoryInstance.getClientFactory());
}
/**
private class MyGetOperation<T> extends HttpOperation<T> {
public MyGetOperation(Class<T> responseClass) {
- super(HttpOperationTest.this.params, HttpOperationTest.this.operator, responseClass);
+ super(HttpOperationTest.this.params, HttpOperationTest.this.config, responseClass, Collections.emptyList());
}
@Override
Map<String, Object> headers = makeHeaders();
headers.put("Accept", MediaType.APPLICATION_JSON);
- String url = makeUrl();
+ String url = getUrl();
- logRestRequest(url, null);
+ logMessage(EventType.OUT, CommInfrastructure.REST, url, null);
// @formatter:off
return handleResponse(outcome, url,
- callback -> operator.getClient().get(callback, makePath(), headers));
+ callback -> getClient().get(callback, getPath(), headers));
// @formatter:on
}
}
private class MyPostOperation extends HttpOperation<MyResponse> {
public MyPostOperation() {
- super(HttpOperationTest.this.params, HttpOperationTest.this.operator, MyResponse.class);
+ super(HttpOperationTest.this.params, HttpOperationTest.this.config, MyResponse.class,
+ Collections.emptyList());
}
@Override
MyRequest request = new MyRequest();
- Entity<MyRequest> entity = Entity.entity(request, MediaType.APPLICATION_JSON);
-
Map<String, Object> headers = makeHeaders();
headers.put("Accept", MediaType.APPLICATION_JSON);
- String url = makeUrl();
+ String url = getUrl();
- logRestRequest(url, request);
+ String strRequest = prettyPrint(request);
+ logMessage(EventType.OUT, CommInfrastructure.REST, url, strRequest);
+
+ Entity<String> entity = Entity.entity(strRequest, MediaType.APPLICATION_JSON);
// @formatter:off
return handleResponse(outcome, url,
- callback -> operator.getClient().post(callback, makePath(), entity, headers));
+ callback -> getClient().post(callback, getPath(), entity, headers));
// @formatter:on
}
}
private class MyPutOperation extends HttpOperation<MyResponse> {
public MyPutOperation() {
- super(HttpOperationTest.this.params, HttpOperationTest.this.operator, MyResponse.class);
+ super(HttpOperationTest.this.params, HttpOperationTest.this.config, MyResponse.class,
+ Collections.emptyList());
}
@Override
MyRequest request = new MyRequest();
- Entity<MyRequest> entity = Entity.entity(request, MediaType.APPLICATION_JSON);
-
Map<String, Object> headers = makeHeaders();
headers.put("Accept", MediaType.APPLICATION_JSON);
- String url = makeUrl();
+ String url = getUrl();
+
+ String strRequest = prettyPrint(request);
+ logMessage(EventType.OUT, CommInfrastructure.REST, url, strRequest);
- logRestRequest(url, request);
+ Entity<String> entity = Entity.entity(strRequest, MediaType.APPLICATION_JSON);
// @formatter:off
return handleResponse(outcome, url,
- callback -> operator.getClient().put(callback, makePath(), entity, headers));
+ callback -> getClient().put(callback, getPath(), entity, headers));
// @formatter:on
}
}
private class MyDeleteOperation extends HttpOperation<String> {
public MyDeleteOperation() {
- super(HttpOperationTest.this.params, HttpOperationTest.this.operator, String.class);
+ super(HttpOperationTest.this.params, HttpOperationTest.this.config, String.class, Collections.emptyList());
}
@Override
Map<String, Object> headers = makeHeaders();
headers.put("Accept", MediaType.APPLICATION_JSON);
- String url = makeUrl();
+ String url = getUrl();
- logRestRequest(url, null);
+ logMessage(EventType.OUT, CommInfrastructure.REST, url, null);
// @formatter:off
return handleResponse(outcome, url,
- callback -> operator.getClient().delete(callback, makePath(), headers));
+ callback -> getClient().delete(callback, getPath(), headers));
// @formatter:on
}
}