blob: 704ae5ffcd5490f3d09d3f0cbcfb41a01e9b2a38 [file] [log] [blame]
margaretha92ad2ec2023-05-15 14:10:00 +02001package de.ids_mannheim.korap.web.lite;
margaretha1d1c73e2019-12-03 18:07:28 +01002
Marc Kupietzd43a98d2023-09-22 17:11:46 +02003import static org.junit.jupiter.api.Assertions.assertEquals;
4import static org.junit.jupiter.api.Assertions.assertTrue;
margaretha0ddaed62021-01-21 17:10:33 +01005import static org.mockserver.integration.ClientAndServer.startClientAndServer;
6import static org.mockserver.model.HttpRequest.request;
7import static org.mockserver.model.HttpResponse.response;
margaretha1d1c73e2019-12-03 18:07:28 +01008
margaretha0ddaed62021-01-21 17:10:33 +01009import java.io.BufferedReader;
margaretha1d1c73e2019-12-03 18:07:28 +010010import java.io.IOException;
margaretha0ddaed62021-01-21 17:10:33 +010011import java.io.InputStreamReader;
12import java.io.OutputStream;
13import java.net.HttpURLConnection;
14import java.net.URISyntaxException;
15import java.net.URL;
16import java.net.URLEncoder;
17import java.nio.charset.StandardCharsets;
margaretha1d1c73e2019-12-03 18:07:28 +010018
margaretha0ddaed62021-01-21 17:10:33 +010019import org.apache.commons.io.IOUtils;
Marc Kupietzd43a98d2023-09-22 17:11:46 +020020import org.junit.jupiter.api.AfterEach;
21import org.junit.jupiter.api.BeforeEach;
22import org.junit.jupiter.api.Test;
margaretha0ddaed62021-01-21 17:10:33 +010023import org.mockserver.client.MockServerClient;
24import org.mockserver.integration.ClientAndServer;
25import org.mockserver.model.Header;
margaretha1d1c73e2019-12-03 18:07:28 +010026import com.fasterxml.jackson.databind.JsonNode;
abcpro173fe8f22022-11-08 19:56:52 +000027
margaretha96c309d2023-08-16 12:24:12 +020028import jakarta.ws.rs.core.Response;
29import jakarta.ws.rs.core.Response.Status;
margaretha1d1c73e2019-12-03 18:07:28 +010030
margaretha1d1c73e2019-12-03 18:07:28 +010031import de.ids_mannheim.korap.config.LiteJerseyTest;
32import de.ids_mannheim.korap.exceptions.KustvaktException;
margaretha137d4ee2019-12-13 14:49:15 +010033import de.ids_mannheim.korap.exceptions.StatusCodes;
margaretha1d1c73e2019-12-03 18:07:28 +010034import de.ids_mannheim.korap.utils.JsonUtils;
35
36public class LiteSearchPipeTest extends LiteJerseyTest {
37
margaretha0ddaed62021-01-21 17:10:33 +010038 private ClientAndServer mockServer;
Marc Kupietzd43a98d2023-09-22 17:11:46 +020039
margaretha0ddaed62021-01-21 17:10:33 +010040 private MockServerClient mockClient;
41
margaretha4dee07a2022-05-27 11:45:28 +020042 private int port = 6070;
Marc Kupietzd43a98d2023-09-22 17:11:46 +020043
margaretha0ddaed62021-01-21 17:10:33 +010044 private String pipeJson, pipeWithParamJson;
margaretha0ddaed62021-01-21 17:10:33 +010045
Marc Kupietzd43a98d2023-09-22 17:11:46 +020046 private String glemmUri = "http://localhost:" + port + "/glemm";
margaretha0ddaed62021-01-21 17:10:33 +010047
margaretha35e1ca22023-11-16 22:00:01 +010048 public LiteSearchPipeTest () throws IOException {
49 pipeJson = IOUtils.toString(
50 ClassLoader.getSystemResourceAsStream(
51 "pipe-output/test-pipes.jsonld"),
52 StandardCharsets.UTF_8);
53 pipeWithParamJson = IOUtils.toString(
54 ClassLoader.getSystemResourceAsStream(
55 "pipe-output/with-param.jsonld"),
56 StandardCharsets.UTF_8);
margaretha0ddaed62021-01-21 17:10:33 +010057 }
58
Marc Kupietzd43a98d2023-09-22 17:11:46 +020059 @BeforeEach
margaretha35e1ca22023-11-16 22:00:01 +010060 public void startMockServer () {
margaretha4dee07a2022-05-27 11:45:28 +020061 mockServer = startClientAndServer(port);
margaretha0ddaed62021-01-21 17:10:33 +010062 mockClient = new MockServerClient("localhost", mockServer.getPort());
63 }
64
Marc Kupietzd43a98d2023-09-22 17:11:46 +020065 @AfterEach
margaretha35e1ca22023-11-16 22:00:01 +010066 public void stopMockServer () {
margaretha0ddaed62021-01-21 17:10:33 +010067 mockServer.stop();
68 }
69
margaretha1d1c73e2019-12-03 18:07:28 +010070 @Test
margaretha35e1ca22023-11-16 22:00:01 +010071 public void testMockServer () throws IOException {
72 mockClient.reset()
73 .when(request().withMethod("POST").withPath("/test")
74 .withHeader(new Header("Content-Type",
75 "application/json; charset=utf-8")))
76 .respond(response()
77 .withHeader(new Header("Content-Type",
78 "application/json; charset=utf-8"))
79 .withBody("{test}").withStatusCode(200));
Marc Kupietzd43a98d2023-09-22 17:11:46 +020080 URL url = new URL("http://localhost:" + port + "/test");
margaretha0ddaed62021-01-21 17:10:33 +010081 HttpURLConnection connection = (HttpURLConnection) url.openConnection();
82 connection.setRequestMethod("POST");
margaretha35e1ca22023-11-16 22:00:01 +010083 connection.setRequestProperty("Content-Type",
84 "application/json; charset=UTF-8");
margaretha0ddaed62021-01-21 17:10:33 +010085 connection.setRequestProperty("Accept", "application/json");
86 connection.setDoOutput(true);
margaretha0ddaed62021-01-21 17:10:33 +010087 String json = "{\"name\" : \"dory\"}";
88 try (OutputStream os = connection.getOutputStream()) {
89 byte[] input = json.getBytes("utf-8");
90 os.write(input, 0, input.length);
91 }
margaretha0ddaed62021-01-21 17:10:33 +010092 assertEquals(200, connection.getResponseCode());
margaretha35e1ca22023-11-16 22:00:01 +010093 BufferedReader br = new BufferedReader(
94 new InputStreamReader(connection.getInputStream(), "utf-8"));
Marc Kupietzd43a98d2023-09-22 17:11:46 +020095 assertEquals(br.readLine(), "{test}");
margaretha0ddaed62021-01-21 17:10:33 +010096 }
97
98 @Test
margaretha35e1ca22023-11-16 22:00:01 +010099 public void testSearchWithPipes ()
100 throws IOException, KustvaktException, URISyntaxException {
101 mockClient.reset()
102 .when(request().withMethod("POST").withPath("/glemm")
103 .withHeaders(
104 new Header("Content-Type",
105 "application/json; charset=utf-8"),
106 new Header("Accept", "application/json")))
107 .respond(response()
108 .withHeader(new Header("Content-Type",
109 "application/json; charset=utf-8"))
110 .withBody(pipeJson).withStatusCode(200));
111 Response response = target().path(API_VERSION).path("search")
112 .queryParam("q", "[orth=der]").queryParam("ql", "poliqarp")
113 .queryParam("pipes", glemmUri).request().get();
Marc Kupietzd43a98d2023-09-22 17:11:46 +0200114 assertEquals(Status.OK.getStatusCode(), response.getStatus());
abcpro173fe8f22022-11-08 19:56:52 +0000115 String entity = response.readEntity(String.class);
margaretha1d1c73e2019-12-03 18:07:28 +0100116 JsonNode node = JsonUtils.readTree(entity);
margaretha137d4ee2019-12-13 14:49:15 +0100117 assertEquals(2, node.at("/query/wrap/key").size());
margaretha1d1c73e2019-12-03 18:07:28 +0100118 node = node.at("/query/wrap/rewrites");
119 assertEquals(2, node.size());
Marc Kupietzd43a98d2023-09-22 17:11:46 +0200120 assertEquals(node.at("/0/src").asText(), "Glemm");
121 assertEquals(node.at("/0/operation").asText(), "operation:override");
122 assertEquals(node.at("/0/scope").asText(), "key");
123 assertEquals(node.at("/1/src").asText(), "Kustvakt");
124 assertEquals(node.at("/1/operation").asText(), "operation:injection");
125 assertEquals(node.at("/1/scope").asText(), "foundry");
margaretha1d1c73e2019-12-03 18:07:28 +0100126 }
margaretha137d4ee2019-12-13 14:49:15 +0100127
128 @Test
margaretha35e1ca22023-11-16 22:00:01 +0100129 public void testSearchWithUrlEncodedPipes ()
130 throws IOException, KustvaktException {
131 mockClient.reset()
132 .when(request().withMethod("POST").withPath("/glemm")
133 .withHeaders(
134 new Header("Content-Type",
135 "application/json; charset=utf-8"),
136 new Header("Accept", "application/json")))
137 .respond(response()
138 .withHeader(new Header("Content-Type",
139 "application/json; charset=utf-8"))
140 .withBody(pipeJson).withStatusCode(200));
margaretha0ddaed62021-01-21 17:10:33 +0100141 glemmUri = URLEncoder.encode(glemmUri, "utf-8");
margaretha35e1ca22023-11-16 22:00:01 +0100142 Response response = target().path(API_VERSION).path("search")
143 .queryParam("q", "[orth=der]").queryParam("ql", "poliqarp")
144 .queryParam("pipes", glemmUri).request().get();
abcpro173fe8f22022-11-08 19:56:52 +0000145 String entity = response.readEntity(String.class);
margaretha0ddaed62021-01-21 17:10:33 +0100146 JsonNode node = JsonUtils.readTree(entity);
147 assertEquals(2, node.at("/query/wrap/key").size());
148 }
149
150 @Test
margaretha35e1ca22023-11-16 22:00:01 +0100151 public void testSearchWithMultiplePipes () throws KustvaktException {
152 mockClient.reset()
153 .when(request().withMethod("POST").withPath("/glemm")
154 .withQueryStringParameter("param").withHeaders(
155 new Header("Content-Type",
156 "application/json; charset=utf-8"),
157 new Header("Accept", "application/json")))
158 .respond(response()
159 .withHeader(new Header("Content-Type",
160 "application/json; charset=utf-8"))
161 .withBody(pipeWithParamJson).withStatusCode(200));
margaretha137d4ee2019-12-13 14:49:15 +0100162 String glemmUri2 = glemmUri + "?param=blah";
margaretha35e1ca22023-11-16 22:00:01 +0100163 Response response = target().path(API_VERSION).path("search")
164 .queryParam("q", "[orth=der]").queryParam("ql", "poliqarp")
165 .queryParam("pipes", glemmUri + "," + glemmUri2).request()
166 .get();
Marc Kupietzd43a98d2023-09-22 17:11:46 +0200167 assertEquals(Status.OK.getStatusCode(), response.getStatus());
abcpro173fe8f22022-11-08 19:56:52 +0000168 String entity = response.readEntity(String.class);
margaretha137d4ee2019-12-13 14:49:15 +0100169 JsonNode node = JsonUtils.readTree(entity);
170 assertEquals(3, node.at("/query/wrap/key").size());
171 }
172
173 @Test
margaretha35e1ca22023-11-16 22:00:01 +0100174 public void testSearchWithUnknownURL ()
175 throws IOException, KustvaktException {
176 String url = target().getUri().toString() + API_VERSION
177 + "/test/tralala";
178 Response response = target().path(API_VERSION).path("search")
179 .queryParam("q", "[orth=der]").queryParam("ql", "poliqarp")
180 .queryParam("pipes", url).request().get();
Marc Kupietzd43a98d2023-09-22 17:11:46 +0200181 assertEquals(Status.OK.getStatusCode(), response.getStatus());
abcpro173fe8f22022-11-08 19:56:52 +0000182 String entity = response.readEntity(String.class);
margaretha137d4ee2019-12-13 14:49:15 +0100183 JsonNode node = JsonUtils.readTree(entity);
184 assertEquals(StatusCodes.PIPE_FAILED, node.at("/warnings/0/0").asInt());
Marc Kupietzd43a98d2023-09-22 17:11:46 +0200185 assertEquals(node.at("/warnings/0/3").asText(), "404 Not Found");
margaretha137d4ee2019-12-13 14:49:15 +0100186 }
187
188 @Test
margaretha35e1ca22023-11-16 22:00:01 +0100189 public void testSearchWithUnknownHost () throws KustvaktException {
190 Response response = target().path(API_VERSION).path("search")
191 .queryParam("q", "[orth=der]").queryParam("ql", "poliqarp")
192 .queryParam("pipes", "http://glemm").request().get();
Marc Kupietzd43a98d2023-09-22 17:11:46 +0200193 assertEquals(Status.OK.getStatusCode(), response.getStatus());
abcpro173fe8f22022-11-08 19:56:52 +0000194 String entity = response.readEntity(String.class);
margaretha137d4ee2019-12-13 14:49:15 +0100195 JsonNode node = JsonUtils.readTree(entity);
margaretha137d4ee2019-12-13 14:49:15 +0100196 assertEquals(StatusCodes.PIPE_FAILED, node.at("/warnings/0/0").asInt());
Marc Kupietzd43a98d2023-09-22 17:11:46 +0200197 assertEquals(node.at("/warnings/0/3").asText(), "glemm");
margaretha137d4ee2019-12-13 14:49:15 +0100198 }
199
200 @Test
margaretha35e1ca22023-11-16 22:00:01 +0100201 public void testSearchUnsupportedMediaType () throws KustvaktException {
202 mockClient.reset()
203 .when(request().withMethod("POST").withPath("/non-json-pipe"))
204 .respond(response().withStatusCode(415));
Marc Kupietzd43a98d2023-09-22 17:11:46 +0200205 String pipeUri = "http://localhost:" + port + "/non-json-pipe";
margaretha35e1ca22023-11-16 22:00:01 +0100206 Response response = target().path(API_VERSION).path("search")
207 .queryParam("q", "[orth=der]").queryParam("ql", "poliqarp")
208 .queryParam("pipes", pipeUri).request().get();
abcpro173fe8f22022-11-08 19:56:52 +0000209 String entity = response.readEntity(String.class);
Marc Kupietzd43a98d2023-09-22 17:11:46 +0200210 assertEquals(Status.OK.getStatusCode(), response.getStatus());
margaretha137d4ee2019-12-13 14:49:15 +0100211 JsonNode node = JsonUtils.readTree(entity);
212 assertEquals(StatusCodes.PIPE_FAILED, node.at("/warnings/0/0").asInt());
margaretha35e1ca22023-11-16 22:00:01 +0100213 assertEquals(node.at("/warnings/0/3").asText(),
214 "415 Unsupported Media Type");
margaretha137d4ee2019-12-13 14:49:15 +0100215 }
216
217 @Test
margaretha35e1ca22023-11-16 22:00:01 +0100218 public void testSearchWithMultiplePipeWarnings () throws KustvaktException {
219 String url = target().getUri().toString() + API_VERSION
220 + "/test/tralala";
221 Response response = target().path(API_VERSION).path("search")
222 .queryParam("q", "[orth=der]").queryParam("ql", "poliqarp")
223 .queryParam("pipes", url + "," + "http://glemm").request()
224 .get();
Marc Kupietzd43a98d2023-09-22 17:11:46 +0200225 assertEquals(Status.OK.getStatusCode(), response.getStatus());
abcpro173fe8f22022-11-08 19:56:52 +0000226 String entity = response.readEntity(String.class);
margaretha137d4ee2019-12-13 14:49:15 +0100227 JsonNode node = JsonUtils.readTree(entity);
margaretha137d4ee2019-12-13 14:49:15 +0100228 assertEquals(2, node.at("/warnings").size());
229 assertEquals(StatusCodes.PIPE_FAILED, node.at("/warnings/0/0").asInt());
230 assertEquals(url, node.at("/warnings/0/2").asText());
Marc Kupietzd43a98d2023-09-22 17:11:46 +0200231 assertEquals(node.at("/warnings/0/3").asText(), "404 Not Found");
margaretha137d4ee2019-12-13 14:49:15 +0100232 assertEquals(StatusCodes.PIPE_FAILED, node.at("/warnings/1/0").asInt());
Marc Kupietzd43a98d2023-09-22 17:11:46 +0200233 assertEquals(node.at("/warnings/1/2").asText(), "http://glemm");
234 assertEquals(node.at("/warnings/1/3").asText(), "glemm");
margaretha137d4ee2019-12-13 14:49:15 +0100235 }
236
237 @Test
margaretha35e1ca22023-11-16 22:00:01 +0100238 public void testSearchWithInvalidJsonResponse () throws KustvaktException {
239 mockClient.reset()
240 .when(request().withMethod("POST").withPath("/invalid-response")
241 .withHeaders(
242 new Header("Content-Type",
243 "application/json; charset=utf-8"),
244 new Header("Accept", "application/json")))
245 .respond(response().withBody("{blah:}").withStatusCode(200)
246 .withHeaders(new Header("Content-Type",
247 "application/json; charset=utf-8")));
Marc Kupietzd43a98d2023-09-22 17:11:46 +0200248 String pipeUri = "http://localhost:" + port + "/invalid-response";
margaretha35e1ca22023-11-16 22:00:01 +0100249 Response response = target().path(API_VERSION).path("search")
250 .queryParam("q", "[orth=der]").queryParam("ql", "poliqarp")
251 .queryParam("pipes", pipeUri).request().get();
abcpro173fe8f22022-11-08 19:56:52 +0000252 String entity = response.readEntity(String.class);
Marc Kupietzd43a98d2023-09-22 17:11:46 +0200253 assertEquals(Status.BAD_REQUEST.getStatusCode(), response.getStatus());
margaretha137d4ee2019-12-13 14:49:15 +0100254 JsonNode node = JsonUtils.readTree(entity);
margaretha35e1ca22023-11-16 22:00:01 +0100255 assertEquals(StatusCodes.DESERIALIZATION_FAILED,
256 node.at("/errors/0/0").asInt());
margaretha137d4ee2019-12-13 14:49:15 +0100257 }
258
259 @Test
margaretha35e1ca22023-11-16 22:00:01 +0100260 public void testSearchWithPlainTextResponse () throws KustvaktException {
261 mockClient.reset()
262 .when(request().withMethod("POST").withPath("/plain-text")
263 .withHeaders(
264 new Header("Content-Type",
265 "application/json; charset=utf-8"),
266 new Header("Accept", "application/json")))
267 .respond(response().withBody("blah").withStatusCode(200));
Marc Kupietzd43a98d2023-09-22 17:11:46 +0200268 String pipeUri = "http://localhost:" + port + "/plain-text";
margaretha35e1ca22023-11-16 22:00:01 +0100269 Response response = target().path(API_VERSION).path("search")
270 .queryParam("q", "[orth=der]").queryParam("ql", "poliqarp")
271 .queryParam("pipes", pipeUri).request().get();
abcpro173fe8f22022-11-08 19:56:52 +0000272 String entity = response.readEntity(String.class);
Marc Kupietzd43a98d2023-09-22 17:11:46 +0200273 assertEquals(Status.BAD_REQUEST.getStatusCode(), response.getStatus());
margaretha137d4ee2019-12-13 14:49:15 +0100274 JsonNode node = JsonUtils.readTree(entity);
margaretha35e1ca22023-11-16 22:00:01 +0100275 assertEquals(StatusCodes.DESERIALIZATION_FAILED,
276 node.at("/errors/0/0").asInt());
margaretha137d4ee2019-12-13 14:49:15 +0100277 }
278
279 @Test
margaretha35e1ca22023-11-16 22:00:01 +0100280 public void testSearchWithMultipleAndUnknownPipes ()
281 throws KustvaktException {
282 mockClient.reset()
283 .when(request().withMethod("POST").withPath("/glemm")
284 .withHeaders(
285 new Header("Content-Type",
286 "application/json; charset=utf-8"),
287 new Header("Accept", "application/json")))
288 .respond(response()
289 .withHeader(new Header("Content-Type",
290 "application/json; charset=utf-8"))
291 .withBody(pipeJson).withStatusCode(200));
292 Response response = target().path(API_VERSION).path("search")
293 .queryParam("q", "[orth=der]").queryParam("ql", "poliqarp")
294 .queryParam("pipes", "http://unknown" + "," + glemmUri)
295 .request().get();
Marc Kupietzd43a98d2023-09-22 17:11:46 +0200296 assertEquals(Status.OK.getStatusCode(), response.getStatus());
abcpro173fe8f22022-11-08 19:56:52 +0000297 String entity = response.readEntity(String.class);
margaretha137d4ee2019-12-13 14:49:15 +0100298 JsonNode node = JsonUtils.readTree(entity);
margaretha137d4ee2019-12-13 14:49:15 +0100299 assertEquals(2, node.at("/query/wrap/key").size());
margaretha0ddaed62021-01-21 17:10:33 +0100300 assertTrue(node.at("/warnings").isMissingNode());
margaretha35e1ca22023-11-16 22:00:01 +0100301 response = target().path(API_VERSION).path("search")
302 .queryParam("q", "[orth=der]").queryParam("ql", "poliqarp")
303 .queryParam("pipes", glemmUri + ",http://unknown").request()
304 .get();
Marc Kupietzd43a98d2023-09-22 17:11:46 +0200305 assertEquals(Status.OK.getStatusCode(), response.getStatus());
abcpro173fe8f22022-11-08 19:56:52 +0000306 entity = response.readEntity(String.class);
margaretha0ddaed62021-01-21 17:10:33 +0100307 node = JsonUtils.readTree(entity);
308 assertEquals(StatusCodes.PIPE_FAILED, node.at("/warnings/0/0").asInt());
margaretha137d4ee2019-12-13 14:49:15 +0100309 }
margaretha1d1c73e2019-12-03 18:07:28 +0100310}