Handled invalid pipes and added tests.

Change-Id: Iba20cbbfb60fa10a769bee697295943b0e4a1772
diff --git a/lite/Changes b/lite/Changes
index 0a06d87..287819e 100644
--- a/lite/Changes
+++ b/lite/Changes
@@ -3,7 +3,9 @@
    - Implemented pipe extension in the search API (margaretha)
 12/12/2019
    - Added support for multiple cq parameters (margaretha, resolved #46)
-
+13/12/2019
+   - Handled pipe errors and added tests (margaretha)
+   
 # version 0.62.2
 13/11/2019
    - Added tests for issue #43 (margaretha)
@@ -17,21 +19,21 @@
 
 version 0.62
 19/03/2019
-  - Added close index controller (margaretha)  
+   - Added close index controller (margaretha)
 
 version 0.61.3
 05/02/2019
-  - Updated kustvakt-lite.conf (margaretha)
+   - Updated kustvakt-lite.conf (margaretha)
 18/02/2019
-  - Updated core version (margaretha)
+   - Updated core version (margaretha)
 
 version 0.61.2
 14/11/2018
    - Integrated lite and full services and controllers in core (margaretha)
    - Added annotation services (margaretha)
 19/12/2018
-  - Fixed getUser in DummyAuthenticationManager (margaretha)
-  - Fixed search test with fields parameter (margaretha)
+   - Fixed getUser in DummyAuthenticationManager (margaretha)
+   - Fixed search test with fields parameter (margaretha)
 
 version 0.61.1
 22/10/2018
@@ -39,9 +41,9 @@
 29/10/2018
    - Added rewrite handler post construct (margaretha)
 07/11/2018
-    - OpenJDK8u181-workaround (see Debian Bug report #911925; diewald)
+   - OpenJDK8u181-workaround (see Debian Bug report #911925; diewald)
 13/11/2018
-    - Added shutdown handler (margaretha)
+   - Added shutdown handler (margaretha)
 
 version 0.61.0
 30/08/2018
@@ -50,38 +52,38 @@
 
 version 0.60.2
 05/07/2018
-    - Added support for unrestricted corpus statistics (ndiewald)
-    - Do not pass broken queries to Krill (diewald)
+   - Added support for unrestricted corpus statistics (ndiewald)
+   - Do not pass broken queries to Krill (diewald)
 27/08/2018
-    - Added vc reference test (margaretha)
+   - Added vc reference test (margaretha)
 28/08/2018
    - Added API URL versioning (margaretha)
 
 version 0.60.1
 12/06/2018
-    - removed kustvakt_encryption (margaretha)
-    - updated kustvakt core version (margaretha)
-    - adopted statistics query parameter from full (ndiewald)
-  
+   - removed kustvakt_encryption (margaretha)
+   - updated kustvakt core version (margaretha)
+   - adopted statistics query parameter from full (ndiewald)
+   
 version 0.60
-23/03/2018  
-    - updated field type:date in the metadata test (margaretha)
-    - removed loading application context via BeanFactory (margaretha)
-    - fixed missing kustvakt-lite.conf (margaretha)
-    - added support for highlights in matchinfo (diewald)
+23/03/2018
+   - updated field type:date in the metadata test (margaretha)
+   - removed loading application context via BeanFactory (margaretha)
+   - fixed missing kustvakt-lite.conf (margaretha)
+   - added support for highlights in matchinfo (diewald)
 
 version 0.59.9 
 01/02/2018
-    - renamed light to lite (margaretha)
-    - added Changes file (margaretha)
-    - updated library versions and java environment (margaretha)
-    - added metadata test (diewald)
-  
+   - renamed light to lite (margaretha)
+   - added Changes file (margaretha)
+   - updated library versions and java environment (margaretha)
+   - added metadata test (diewald)
+   
 version 0.59.8 
 17/01/2018 
-    - restructured Kustvakt and created /lite project
-    - removed version from service paths (margaretha)
-    - updated query serialization tests (margaretha)
-    - added statistic service test (margaretha)
-    - updated KustvaktResponseHandler (margaretha)
-    - removed FastJerseyLight and simplified Jersey test configuration (margaretha)
\ No newline at end of file
+   - restructured Kustvakt and created /lite project
+   - removed version from service paths (margaretha)
+   - updated query serialization tests (margaretha)
+   - added statistic service test (margaretha)
+   - updated KustvaktResponseHandler (margaretha)
+   - removed FastJerseyLight and simplified Jersey test configuration (margaretha)
\ No newline at end of file
diff --git a/lite/src/test/java/de/ids_mannheim/korap/web/service/LiteSearchPipeTest.java b/lite/src/test/java/de/ids_mannheim/korap/web/service/LiteSearchPipeTest.java
index 5e8d77f..3f0c0bb 100644
--- a/lite/src/test/java/de/ids_mannheim/korap/web/service/LiteSearchPipeTest.java
+++ b/lite/src/test/java/de/ids_mannheim/korap/web/service/LiteSearchPipeTest.java
@@ -2,64 +2,191 @@
 
 import static org.junit.Assert.assertEquals;
 
-import java.io.File;
-import java.io.FileOutputStream;
 import java.io.IOException;
-import java.io.OutputStreamWriter;
 
 import org.junit.Test;
-import org.springframework.beans.factory.annotation.Autowired;
 
 import com.fasterxml.jackson.databind.JsonNode;
 import com.sun.jersey.api.client.ClientResponse;
 
-import de.ids_mannheim.korap.config.KustvaktConfiguration;
 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 {
 
-    @Autowired
-    private KustvaktConfiguration config;
-
-    private void setTestPipes () throws IOException {
-        String filename = "test-pipes";
-        File f = new File(filename);
-        if (f.exists()) {
-            f.delete();
-        }
-        f.createNewFile();
-        OutputStreamWriter writer =
-                new OutputStreamWriter(new FileOutputStream(f));
-        writer.append("glemm\t");
-        writer.append(resource().getURI().toString());
-        writer.append(API_VERSION);
-        writer.append("/test/glemm");
-        writer.flush();
-        writer.close();
-
-        config.readPipesFile(filename);
-    }
-
     @Test
     public void testSearchWithPipes () throws IOException, KustvaktException {
-        setTestPipes();
+        String glemmUri =
+                resource().getURI().toString() + API_VERSION + "/test/glemm";
         ClientResponse response = resource().path(API_VERSION).path("search")
                 .queryParam("q", "[orth=der]").queryParam("ql", "poliqarp")
-                .queryParam("pipes", "glemm").get(ClientResponse.class);
+                .queryParam("pipes", glemmUri).get(ClientResponse.class);
+
+        assertEquals(ClientResponse.Status.OK.getStatusCode(),
+                response.getStatus());
 
         String entity = response.getEntity(String.class);
+
         JsonNode node = JsonUtils.readTree(entity);
-        assertEquals(3, node.at("/query/wrap/key").size());
+        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 testSearchWithMultiplePipes () throws KustvaktException {
+        String glemmUri =
+                resource().getURI().toString() + API_VERSION + "/test/glemm";
+        String glemmUri2 = glemmUri + "?param=blah";
+        ClientResponse response = resource().path(API_VERSION).path("search")
+                .queryParam("q", "[orth=der]").queryParam("ql", "poliqarp")
+                .queryParam("pipes", glemmUri + "," + glemmUri2)
+                .get(ClientResponse.class);
+
+        assertEquals(ClientResponse.Status.OK.getStatusCode(),
+                response.getStatus());
+
+        String entity = response.getEntity(String.class);
+        JsonNode node = JsonUtils.readTree(entity);
+        assertEquals(3, node.at("/query/wrap/key").size());
+    }
+
+    @Test
+    public void testSearchWithUnknownURL ()
+            throws IOException, KustvaktException {
+        String url =
+                resource().getURI().toString() + API_VERSION + "/test/tralala";
+        ClientResponse response = resource().path(API_VERSION).path("search")
+                .queryParam("q", "[orth=der]").queryParam("ql", "poliqarp")
+                .queryParam("pipes", url).get(ClientResponse.class);
+
+        assertEquals(ClientResponse.Status.OK.getStatusCode(),
+                response.getStatus());
+        String entity = response.getEntity(String.class);
+
+        JsonNode node = JsonUtils.readTree(entity);
+        assertEquals(StatusCodes.PIPE_FAILED, node.at("/warnings/0/0").asInt());
+    }
+
+    @Test
+    public void testSearchWithUnknownHost () throws KustvaktException {
+        ClientResponse response = resource().path(API_VERSION).path("search")
+                .queryParam("q", "[orth=der]").queryParam("ql", "poliqarp")
+                .queryParam("pipes", "http://glemm").get(ClientResponse.class);
+
+        assertEquals(ClientResponse.Status.OK.getStatusCode(),
+                response.getStatus());
+
+        String entity = response.getEntity(String.class);
+        JsonNode node = JsonUtils.readTree(entity);
+
+        assertEquals(StatusCodes.PIPE_FAILED, node.at("/warnings/0/0").asInt());
+    }
+
+    @Test
+    public void testSearchWithUrlEncodedPipe () throws KustvaktException {
+        String pipe = resource().getURI().toString() + API_VERSION
+                + "/test/urlencoded-pipe";
+        ClientResponse response = resource().path(API_VERSION).path("search")
+                .queryParam("q", "[orth=der]").queryParam("ql", "poliqarp")
+                .queryParam("pipes", pipe).get(ClientResponse.class);
+
+        String entity = response.getEntity(String.class);
+        assertEquals(ClientResponse.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 =
+                resource().getURI().toString() + API_VERSION + "/test/tralala";
+        ClientResponse response = resource().path(API_VERSION).path("search")
+                .queryParam("q", "[orth=der]").queryParam("ql", "poliqarp")
+                .queryParam("pipes", url + "," + "http://glemm")
+                .get(ClientResponse.class);
+
+        assertEquals(ClientResponse.Status.OK.getStatusCode(),
+                response.getStatus());
+
+        String entity = response.getEntity(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("java.net.UnknownHostException: glemm",
+                node.at("/warnings/1/3").asText());
+
+    }
+
+    @Test
+    public void testSearchWithInvalidJsonResponse () throws KustvaktException {
+        String pipe = resource().getURI().toString() + API_VERSION
+                + "/test/invalid-json-pipe";
+        ClientResponse response = resource().path(API_VERSION).path("search")
+                .queryParam("q", "[orth=der]").queryParam("ql", "poliqarp")
+                .queryParam("pipes", pipe).get(ClientResponse.class);
+
+        String entity = response.getEntity(String.class);
+        assertEquals(ClientResponse.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 {
+        String pipe = resource().getURI().toString() + API_VERSION
+                + "/test/plain-response-pipe";
+        ClientResponse response = resource().path(API_VERSION).path("search")
+                .queryParam("q", "[orth=der]").queryParam("ql", "poliqarp")
+                .queryParam("pipes", pipe).get(ClientResponse.class);
+
+        String entity = response.getEntity(String.class);
+        assertEquals(ClientResponse.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 {
+        String glemmUri =
+                resource().getURI().toString() + API_VERSION + "/test/glemm";
+        ClientResponse response = resource().path(API_VERSION).path("search")
+                .queryParam("q", "[orth=der]").queryParam("ql", "poliqarp")
+                .queryParam("pipes", "http://unknown" + "," + glemmUri)
+                .get(ClientResponse.class);
+
+        assertEquals(ClientResponse.Status.OK.getStatusCode(),
+                response.getStatus());
+
+        String entity = response.getEntity(String.class);
+        JsonNode node = JsonUtils.readTree(entity);
+        assertEquals(StatusCodes.PIPE_FAILED, node.at("/warnings/0/0").asInt());
+        assertEquals(2, node.at("/query/wrap/key").size());
+    }
 }