blob: da7b7e96c05370f688f9bcacb9c5eaf97ffa1013 [file] [log] [blame]
package de.ids_mannheim.korap.web.lite;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.mockserver.integration.ClientAndServer.startClientAndServer;
import static org.mockserver.model.HttpRequest.request;
import static org.mockserver.model.HttpResponse.response;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.URISyntaxException;
import java.net.URL;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import org.apache.commons.io.IOUtils;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.mockserver.client.MockServerClient;
import org.mockserver.integration.ClientAndServer;
import org.mockserver.model.Header;
import com.fasterxml.jackson.databind.JsonNode;
import jakarta.ws.rs.core.Response;
import jakarta.ws.rs.core.Response.Status;
import de.ids_mannheim.korap.config.LiteJerseyTest;
import de.ids_mannheim.korap.exceptions.KustvaktException;
import de.ids_mannheim.korap.exceptions.StatusCodes;
import de.ids_mannheim.korap.utils.JsonUtils;
public class LiteSearchPipeTest extends LiteJerseyTest {
private ClientAndServer mockServer;
private MockServerClient mockClient;
private int port = 6070;
private String pipeJson, pipeWithParamJson;
private String glemmUri = "http://localhost:" + port + "/glemm";
public LiteSearchPipeTest () throws IOException {
pipeJson = IOUtils.toString(
ClassLoader.getSystemResourceAsStream(
"pipe-output/test-pipes.jsonld"),
StandardCharsets.UTF_8);
pipeWithParamJson = IOUtils.toString(
ClassLoader.getSystemResourceAsStream(
"pipe-output/with-param.jsonld"),
StandardCharsets.UTF_8);
}
@BeforeEach
public void startMockServer () {
mockServer = startClientAndServer(port);
mockClient = new MockServerClient("localhost", mockServer.getPort());
}
@AfterEach
public void stopMockServer () {
mockServer.stop();
}
@Test
public void testMockServer () throws IOException {
mockClient.reset()
.when(request().withMethod("POST").withPath("/test")
.withHeader(new Header("Content-Type",
"application/json; charset=utf-8")))
.respond(response()
.withHeader(new Header("Content-Type",
"application/json; charset=utf-8"))
.withBody("{test}").withStatusCode(200));
URL url = new URL("http://localhost:" + port + "/test");
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setRequestMethod("POST");
connection.setRequestProperty("Content-Type",
"application/json; charset=UTF-8");
connection.setRequestProperty("Accept", "application/json");
connection.setDoOutput(true);
String json = "{\"name\" : \"dory\"}";
try (OutputStream os = connection.getOutputStream()) {
byte[] input = json.getBytes("utf-8");
os.write(input, 0, input.length);
}
assertEquals(200, connection.getResponseCode());
BufferedReader br = new BufferedReader(
new InputStreamReader(connection.getInputStream(), "utf-8"));
assertEquals(br.readLine(), "{test}");
}
@Test
public void testSearchWithPipes ()
throws IOException, KustvaktException, URISyntaxException {
mockClient.reset()
.when(request().withMethod("POST").withPath("/glemm")
.withHeaders(
new Header("Content-Type",
"application/json; charset=utf-8"),
new Header("Accept", "application/json")))
.respond(response()
.withHeader(new Header("Content-Type",
"application/json; charset=utf-8"))
.withBody(pipeJson).withStatusCode(200));
Response response = target().path(API_VERSION).path("search")
.queryParam("q", "[orth=der]").queryParam("ql", "poliqarp")
.queryParam("pipes", glemmUri).request().get();
assertEquals(Status.OK.getStatusCode(), response.getStatus());
String entity = response.readEntity(String.class);
JsonNode node = JsonUtils.readTree(entity);
assertEquals(2, node.at("/query/wrap/key").size());
node = node.at("/query/wrap/rewrites");
assertEquals(2, node.size());
assertEquals("Glemm", node.at("/0/src").asText());
assertEquals("operation:override", node.at("/0/operation").asText());
assertEquals("key", node.at("/0/scope").asText());
assertEquals("Kustvakt", node.at("/1/src").asText());
assertEquals("operation:injection", node.at("/1/operation").asText());
assertEquals("foundry", node.at("/1/scope").asText());
}
@Test
public void testSearchWithUrlEncodedPipes ()
throws IOException, KustvaktException {
mockClient.reset()
.when(request().withMethod("POST").withPath("/glemm")
.withHeaders(
new Header("Content-Type",
"application/json; charset=utf-8"),
new Header("Accept", "application/json")))
.respond(response()
.withHeader(new Header("Content-Type",
"application/json; charset=utf-8"))
.withBody(pipeJson).withStatusCode(200));
glemmUri = URLEncoder.encode(glemmUri, "utf-8");
Response response = target().path(API_VERSION).path("search")
.queryParam("q", "[orth=der]").queryParam("ql", "poliqarp")
.queryParam("pipes", glemmUri).request().get();
String entity = response.readEntity(String.class);
JsonNode node = JsonUtils.readTree(entity);
assertEquals(2, node.at("/query/wrap/key").size());
}
@Test
public void testSearchWithMultiplePipes () throws KustvaktException {
mockClient.reset()
.when(request().withMethod("POST").withPath("/glemm")
.withQueryStringParameter("param").withHeaders(
new Header("Content-Type",
"application/json; charset=utf-8"),
new Header("Accept", "application/json")))
.respond(response()
.withHeader(new Header("Content-Type",
"application/json; charset=utf-8"))
.withBody(pipeWithParamJson).withStatusCode(200));
String glemmUri2 = glemmUri + "?param=blah";
Response response = target().path(API_VERSION).path("search")
.queryParam("q", "[orth=der]").queryParam("ql", "poliqarp")
.queryParam("pipes", glemmUri + "," + glemmUri2).request()
.get();
assertEquals(Status.OK.getStatusCode(), response.getStatus());
String entity = response.readEntity(String.class);
JsonNode node = JsonUtils.readTree(entity);
assertEquals(3, node.at("/query/wrap/key").size());
}
@Test
public void testSearchWithUnknownURL ()
throws IOException, KustvaktException {
String url = target().getUri().toString() + API_VERSION
+ "/test/tralala";
Response response = target().path(API_VERSION).path("search")
.queryParam("q", "[orth=der]").queryParam("ql", "poliqarp")
.queryParam("pipes", url).request().get();
assertEquals(Status.OK.getStatusCode(), response.getStatus());
String entity = response.readEntity(String.class);
JsonNode node = JsonUtils.readTree(entity);
assertEquals(StatusCodes.PIPE_FAILED, node.at("/warnings/0/0").asInt());
assertEquals("404 Not Found", node.at("/warnings/0/3").asText());
}
@Test
public void testSearchWithUnknownHost () throws KustvaktException {
Response response = target().path(API_VERSION).path("search")
.queryParam("q", "[orth=der]").queryParam("ql", "poliqarp")
.queryParam("pipes", "http://glemm").request().get();
assertEquals(Status.OK.getStatusCode(), response.getStatus());
String entity = response.readEntity(String.class);
JsonNode node = JsonUtils.readTree(entity);
assertEquals(StatusCodes.PIPE_FAILED, node.at("/warnings/0/0").asInt());
assertEquals("Unrecognized pipe URL", node.at("/warnings/0/3").asText());
}
@Test
public void testSearchUnsupportedMediaType () throws KustvaktException {
mockClient.reset()
.when(request().withMethod("POST").withPath("/non-json-pipe"))
.respond(response().withStatusCode(415));
String pipeUri = "http://localhost:" + port + "/non-json-pipe";
Response response = target().path(API_VERSION).path("search")
.queryParam("q", "[orth=der]").queryParam("ql", "poliqarp")
.queryParam("pipes", pipeUri).request().get();
String entity = response.readEntity(String.class);
assertEquals(Status.OK.getStatusCode(), response.getStatus());
JsonNode node = JsonUtils.readTree(entity);
assertEquals(StatusCodes.PIPE_FAILED, node.at("/warnings/0/0").asInt());
assertEquals("415 Unsupported Media Type",
node.at("/warnings/0/3").asText() );
}
@Test
public void testSearchWithMultiplePipeWarnings () throws KustvaktException {
String url = target().getUri().toString() + API_VERSION
+ "/test/tralala";
Response response = target().path(API_VERSION).path("search")
.queryParam("q", "[orth=der]").queryParam("ql", "poliqarp")
.queryParam("pipes", url + "," + "http://glemm").request()
.get();
assertEquals(Status.OK.getStatusCode(), response.getStatus());
String entity = response.readEntity(String.class);
JsonNode node = JsonUtils.readTree(entity);
assertEquals(2, node.at("/warnings").size());
assertEquals(StatusCodes.PIPE_FAILED, node.at("/warnings/0/0").asInt());
assertEquals(url, node.at("/warnings/0/2").asText());
assertEquals("404 Not Found", node.at("/warnings/0/3").asText());
assertEquals(StatusCodes.PIPE_FAILED, node.at("/warnings/1/0").asInt());
assertEquals("http://glemm", node.at("/warnings/1/2").asText());
assertEquals("Unrecognized pipe URL",
node.at("/warnings/1/3").asText());
}
@Test
public void testSearchWithInvalidJsonResponse () throws KustvaktException {
mockClient.reset()
.when(request().withMethod("POST").withPath("/invalid-response")
.withHeaders(
new Header("Content-Type",
"application/json; charset=utf-8"),
new Header("Accept", "application/json")))
.respond(response().withBody("{blah:}").withStatusCode(200)
.withHeaders(new Header("Content-Type",
"application/json; charset=utf-8")));
String pipeUri = "http://localhost:" + port + "/invalid-response";
Response response = target().path(API_VERSION).path("search")
.queryParam("q", "[orth=der]").queryParam("ql", "poliqarp")
.queryParam("pipes", pipeUri).request().get();
String entity = response.readEntity(String.class);
assertEquals(Status.BAD_REQUEST.getStatusCode(), response.getStatus());
JsonNode node = JsonUtils.readTree(entity);
assertEquals(StatusCodes.DESERIALIZATION_FAILED,
node.at("/errors/0/0").asInt());
}
@Test
public void testSearchWithPlainTextResponse () throws KustvaktException {
mockClient.reset()
.when(request().withMethod("POST").withPath("/plain-text")
.withHeaders(
new Header("Content-Type",
"application/json; charset=utf-8"),
new Header("Accept", "application/json")))
.respond(response().withBody("blah").withStatusCode(200));
String pipeUri = "http://localhost:" + port + "/plain-text";
Response response = target().path(API_VERSION).path("search")
.queryParam("q", "[orth=der]").queryParam("ql", "poliqarp")
.queryParam("pipes", pipeUri).request().get();
String entity = response.readEntity(String.class);
assertEquals(Status.BAD_REQUEST.getStatusCode(), response.getStatus());
JsonNode node = JsonUtils.readTree(entity);
assertEquals(StatusCodes.DESERIALIZATION_FAILED,
node.at("/errors/0/0").asInt());
}
@Test
public void testSearchWithMultipleAndUnknownPipes ()
throws KustvaktException {
mockClient.reset()
.when(request().withMethod("POST").withPath("/glemm")
.withHeaders(
new Header("Content-Type",
"application/json; charset=utf-8"),
new Header("Accept", "application/json")))
.respond(response()
.withHeader(new Header("Content-Type",
"application/json; charset=utf-8"))
.withBody(pipeJson).withStatusCode(200));
Response response = target().path(API_VERSION).path("search")
.queryParam("q", "[orth=der]").queryParam("ql", "poliqarp")
.queryParam("pipes", "http://unknown" + "," + glemmUri)
.request().get();
assertEquals(Status.OK.getStatusCode(), response.getStatus());
String entity = response.readEntity(String.class);
JsonNode node = JsonUtils.readTree(entity);
assertEquals(2, node.at("/query/wrap/key").size());
assertTrue(node.at("/warnings").isMissingNode());
response = target().path(API_VERSION).path("search")
.queryParam("q", "[orth=der]").queryParam("ql", "poliqarp")
.queryParam("pipes", glemmUri + ",http://unknown").request()
.get();
assertEquals(Status.OK.getStatusCode(), response.getStatus());
entity = response.readEntity(String.class);
node = JsonUtils.readTree(entity);
assertEquals(StatusCodes.PIPE_FAILED, node.at("/warnings/0/0").asInt());
}
}