6f3a0909698499a070875c2dc1ecf8d4f49d44d2
[dcaegen2/services/sdk.git] / rest-services / http-client / src / test / java / org / onap / dcaegen2 / services / sdk / rest / services / adapters / http / RxHttpClientIT.java
1 /*
2  * ============LICENSE_START====================================
3  * DCAEGEN2-SERVICES-SDK
4  * =========================================================
5  * Copyright (C) 2019-2020 Nokia. All rights reserved.
6  * =========================================================
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  *       http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  * ============LICENSE_END=====================================
19  */
20
21 package org.onap.dcaegen2.services.sdk.rest.services.adapters.http;
22
23 import io.netty.handler.codec.http.HttpResponseStatus;
24 import io.netty.handler.timeout.ReadTimeoutException;
25 import org.junit.jupiter.api.AfterAll;
26 import org.junit.jupiter.api.BeforeAll;
27 import org.junit.jupiter.api.Test;
28 import org.onap.dcaegen2.services.sdk.rest.services.adapters.http.exceptions.HttpException;
29 import org.onap.dcaegen2.services.sdk.rest.services.adapters.http.test.DummyHttpServer;
30 import reactor.core.publisher.Mono;
31 import reactor.test.StepVerifier;
32
33 import java.net.MalformedURLException;
34 import java.net.URL;
35 import java.time.Duration;
36
37 import static org.assertj.core.api.Assertions.assertThat;
38 import static org.onap.dcaegen2.services.sdk.rest.services.adapters.http.test.DummyHttpServer.sendString;
39
40 class RxHttpClientIT {
41
42     private static final Duration TIMEOUT = Duration.ofHours(5);
43     private final RxHttpClient cut = RxHttpClientFactory.create();
44     private static DummyHttpServer httpServer;
45
46     @BeforeAll
47     static void setUpClass() {
48         httpServer = DummyHttpServer.start(routes -> routes
49                 .get("/sample-get", (req, resp) -> sendString(resp, Mono.just("OK")))
50                 .get("/delayed-get", (req, resp) -> sendString(resp, Mono.just("OK").delayElement(Duration.ofMinutes(1))))
51                 .get("/sample-get-500", (req, resp) -> resp.status(HttpResponseStatus.INTERNAL_SERVER_ERROR).send())
52                 .post("/headers-post", (req, resp) -> resp
53                         .sendString(Mono.just(req.requestHeaders().toString())))
54                 .post("/echo-post", (req, resp) -> resp.send(req.receive().retain()))
55         );
56     }
57
58     @AfterAll
59     static void tearDownClass() {
60         httpServer.close();
61     }
62
63     private ImmutableHttpRequest.Builder requestFor(String path) throws MalformedURLException {
64         return ImmutableHttpRequest.builder()
65                 .url(new URL("http", httpServer.host(), httpServer.port(), path).toString());
66     }
67
68     @Test
69     void simpleGet() throws Exception {
70         // given
71         final HttpRequest httpRequest = requestFor("/sample-get")
72                 .method(HttpMethod.GET)
73                 .build();
74
75         // when
76         final Mono<String> bodyAsString = cut.call(httpRequest)
77                 .doOnNext(HttpResponse::throwIfUnsuccessful)
78                 .map(HttpResponse::bodyAsString);
79
80         // then
81         StepVerifier.create(bodyAsString)
82                 .expectNext("OK")
83                 .expectComplete()
84                 .verify(TIMEOUT);
85     }
86
87     @Test
88     void getWithError() throws Exception {
89         // given
90         final HttpRequest httpRequest = requestFor("/sample-get-500")
91                 .method(HttpMethod.GET)
92                 .build();
93
94         // when
95         final Mono<String> bodyAsString = cut.call(httpRequest)
96                 .doOnNext(HttpResponse::throwIfUnsuccessful)
97                 .map(HttpResponse::bodyAsString);
98
99         // then
100         StepVerifier.create(bodyAsString)
101                 .expectError(HttpException.class)
102                 .verify(TIMEOUT);
103     }
104
105     @Test
106     void simplePost() throws Exception {
107         // given
108         final String requestBody = "hello world";
109         final HttpRequest httpRequest = requestFor("/echo-post")
110                 .method(HttpMethod.POST)
111                 .body(RequestBody.fromString(requestBody))
112                 .build();
113
114         // when
115         final Mono<String> bodyAsString = cut.call(httpRequest)
116                 .doOnNext(HttpResponse::throwIfUnsuccessful)
117                 .map(HttpResponse::bodyAsString);
118
119         // then
120         StepVerifier.create(bodyAsString)
121                 .expectNext(requestBody)
122                 .expectComplete()
123                 .verify(TIMEOUT);
124     }
125
126     @Test
127     void testChunkedEncoding() throws Exception {
128         // given
129         final String requestBody = "hello world";
130         final HttpRequest httpRequest = requestFor("/headers-post")
131                 .method(HttpMethod.POST)
132                 .body(RequestBody.chunkedFromString(Mono.just(requestBody)))
133                 .build();
134
135         // when
136         final Mono<String> bodyAsString = cut.call(httpRequest)
137                 .doOnNext(HttpResponse::throwIfUnsuccessful)
138                 .map(HttpResponse::bodyAsString);
139
140         // then
141         StepVerifier.create(bodyAsString.map(String::toLowerCase))
142                 .consumeNextWith(responseBody -> {
143                     assertThat(responseBody).contains("transfer-encoding: chunked");
144                     assertThat(responseBody).doesNotContain("content-length");
145                 })
146                 .expectComplete()
147                 .verify(TIMEOUT);
148     }
149
150     @Test
151     void testUnchunkedEncoding() throws Exception {
152         // given
153         final String requestBody = "hello world";
154         final HttpRequest httpRequest = requestFor("/headers-post")
155                 .method(HttpMethod.POST)
156                 .body(RequestBody.fromString(requestBody))
157                 .build();
158
159         // when
160         final Mono<String> bodyAsString = cut.call(httpRequest)
161                 .doOnNext(HttpResponse::throwIfUnsuccessful)
162                 .map(HttpResponse::bodyAsString);
163
164         // then
165         StepVerifier.create(bodyAsString.map(String::toLowerCase))
166                 .consumeNextWith(responseBody -> {
167                     assertThat(responseBody).doesNotContain("transfer-encoding");
168                     assertThat(responseBody).contains("content-length");
169                 })
170                 .expectComplete()
171                 .verify(TIMEOUT);
172     }
173
174     @Test
175     void getWithTimeoutError() throws Exception {
176         // given
177         final HttpRequest httpRequest = requestFor("/delayed-get")
178                 .method(HttpMethod.GET)
179                 .timeout(Duration.ofSeconds(1))
180                 .build();
181
182         // when
183         final Mono<HttpResponse> response = cut.call(httpRequest);
184
185         // then
186         StepVerifier.create(response)
187                 .expectError(ReadTimeoutException.class)
188                 .verify(TIMEOUT);
189     }
190 }