| // Copyright 2012 Google Inc. All Rights Reserved. |
| // |
| // Licensed under the Apache License, Version 2.0 (the "License"); |
| // you may not use this file except in compliance with the License. |
| // You may obtain a copy of the License at |
| // |
| // http://www.apache.org/licenses/LICENSE-2.0 |
| // |
| // Unless required by applicable law or agreed to in writing, software |
| // distributed under the License is distributed on an "AS IS" BASIS, |
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| // See the License for the specific language governing permissions and |
| // limitations under the License. |
| |
| package com.google.enterprise.adaptor; |
| |
| import static org.junit.Assert.*; |
| |
| import com.sun.net.httpserver.Headers; |
| import com.sun.net.httpserver.HttpExchange; |
| import com.sun.net.httpserver.HttpHandler; |
| import com.sun.net.httpserver.HttpServer; |
| import com.sun.net.httpserver.HttpsConfigurator; |
| import com.sun.net.httpserver.HttpsServer; |
| |
| import org.junit.*; |
| import org.junit.rules.ExpectedException; |
| |
| import java.io.*; |
| import java.net.*; |
| import java.nio.charset.Charset; |
| import java.util.zip.GZIPInputStream; |
| |
| import javax.net.ssl.SSLContext; |
| |
| /** |
| * Test cases for {@link GsaFeedFileSender}. |
| */ |
| public class GsaFeedFileSenderTest { |
| @Rule |
| public ExpectedException thrown = ExpectedException.none(); |
| |
| private Charset charset = Charset.forName("UTF-8"); |
| private HttpServer server; |
| private int port; |
| private GsaFeedFileSender sender; |
| |
| @Before |
| public void startup() throws IOException { |
| server = HttpServer.create(new InetSocketAddress(0), 0); |
| port = server.getAddress().getPort(); |
| server.start(); |
| URL metadataAndUrlUrl = new URL("http://localhost:" + port + "/xmlfeed"); |
| URL groupsUrl = new URL("http://localhost:" + port + "/xmlgroups"); |
| sender = new GsaFeedFileSender(metadataAndUrlUrl, groupsUrl, charset); |
| } |
| |
| @After |
| public void shutdown() { |
| if (server != null) { |
| server.stop(0); |
| } |
| } |
| |
| @Test |
| public void testMetadataAndUrlSuccess() throws Exception { |
| final String payload = "<someXmlString/>"; |
| final String datasource = "test-DataSource_09AZaz"; |
| final String goldenResponse |
| = "--<<\r\n" |
| + "Content-Disposition: form-data; name=\"datasource\"\r\n" |
| + "Content-Type: text/plain\r\n" |
| + "\r\n" |
| + datasource + "\r\n" |
| + "--<<\r\n" |
| + "Content-Disposition: form-data; name=\"feedtype\"\r\n" |
| + "Content-Type: text/plain\r\n" |
| + "\r\n" |
| + "metadata-and-url\r\n" |
| + "--<<\r\n" |
| + "Content-Disposition: form-data; name=\"data\"\r\n" |
| + "Content-Type: text/xml\r\n" |
| + "\r\n" |
| + payload + "\r\n" |
| + "--<<--\r\n"; |
| |
| MockHttpHandler handler |
| = new MockHttpHandler(200, "Success".getBytes(charset)); |
| server.createContext("/xmlfeed", handler); |
| |
| sender.sendMetadataAndUrl(datasource, payload, false); |
| assertEquals("POST", handler.getRequestMethod()); |
| assertEquals(URI.create("/xmlfeed"), handler.getRequestUri()); |
| assertEquals("multipart/form-data; boundary=<<", |
| handler.getRequestHeaders().getFirst("Content-Type")); |
| assertEquals(goldenResponse, |
| new String(handler.getRequestBytes(), charset)); |
| } |
| |
| @Test |
| public void testMetadataAndUrlHttpsSuccess() throws Exception { |
| final String payload = "<someXmlString/>"; |
| final String datasource = "testDataSource"; |
| final String goldenResponse |
| = "--<<\r\n" |
| + "Content-Disposition: form-data; name=\"datasource\"\r\n" |
| + "Content-Type: text/plain\r\n" |
| + "\r\n" |
| + datasource + "\r\n" |
| + "--<<\r\n" |
| + "Content-Disposition: form-data; name=\"feedtype\"\r\n" |
| + "Content-Type: text/plain\r\n" |
| + "\r\n" |
| + "metadata-and-url\r\n" |
| + "--<<\r\n" |
| + "Content-Disposition: form-data; name=\"data\"\r\n" |
| + "Content-Type: text/xml\r\n" |
| + "\r\n" |
| + payload + "\r\n" |
| + "--<<--\r\n"; |
| |
| // Unfortunately this test requires a fixed port. |
| server = HttpsServer.create(new InetSocketAddress(19902), 0); |
| HttpsConfigurator httpsConf |
| = new HttpsConfigurator(SSLContext.getDefault()); |
| ((HttpsServer) server).setHttpsConfigurator(httpsConf); |
| server.start(); |
| MockHttpHandler handler |
| = new MockHttpHandler(200, "Success".getBytes(charset)); |
| server.createContext("/xmlfeed", handler); |
| |
| URL metadataAndUrlUrl = new URL("https://localhost:19902/xmlfeed"); |
| URL groupsUrl = new URL("https://localhost:19902/xmlgroups"); |
| GsaFeedFileSender secureSender = new GsaFeedFileSender(metadataAndUrlUrl, |
| groupsUrl, charset); |
| secureSender.sendMetadataAndUrl(datasource, payload, false); |
| assertEquals("POST", handler.getRequestMethod()); |
| assertEquals(URI.create("/xmlfeed"), handler.getRequestUri()); |
| assertEquals("multipart/form-data; boundary=<<", |
| handler.getRequestHeaders().getFirst("Content-Type")); |
| assertEquals(goldenResponse, |
| new String(handler.getRequestBytes(), charset)); |
| } |
| |
| @Test |
| public void testMetadataAndUrlSuccessGzipped() throws Exception { |
| final String payload = "<someXmlString/>"; |
| final String datasource = "testDataSource"; |
| final String goldenResponse |
| = "--<<\r\n" |
| + "Content-Disposition: form-data; name=\"datasource\"\r\n" |
| + "Content-Type: text/plain\r\n" |
| + "\r\n" |
| + datasource + "\r\n" |
| + "--<<\r\n" |
| + "Content-Disposition: form-data; name=\"feedtype\"\r\n" |
| + "Content-Type: text/plain\r\n" |
| + "\r\n" |
| + "metadata-and-url\r\n" |
| + "--<<\r\n" |
| + "Content-Disposition: form-data; name=\"data\"\r\n" |
| + "Content-Type: text/xml\r\n" |
| + "\r\n" |
| + payload + "\r\n" |
| + "--<<--\r\n"; |
| |
| MockHttpHandler handler |
| = new MockHttpHandler(200, "Success".getBytes(charset)); |
| server.createContext("/xmlfeed", handler); |
| |
| sender.sendMetadataAndUrl(datasource, payload, true); |
| assertEquals("POST", handler.getRequestMethod()); |
| assertEquals(URI.create("/xmlfeed"), handler.getRequestUri()); |
| assertEquals("multipart/form-data; boundary=<<", |
| handler.getRequestHeaders().getFirst("Content-Type")); |
| assertEquals("gzip", |
| handler.getRequestHeaders().getFirst("Content-Encoding")); |
| InputStream uncompressed = new GZIPInputStream( |
| new ByteArrayInputStream(handler.getRequestBytes())); |
| String response = new String( |
| IOHelper.readInputStreamToByteArray(uncompressed), charset); |
| assertEquals(goldenResponse, response); |
| } |
| |
| @Test |
| public void testMetadataAndUrlInvalidDataSource() throws Exception { |
| thrown.expect(IllegalArgumentException.class); |
| sender.sendMetadataAndUrl("bad#source", "<payload/>", false); |
| } |
| |
| @Test |
| public void testMetadataAndUrlInvalidDataSource2() throws Exception { |
| thrown.expect(IllegalArgumentException.class); |
| sender.sendMetadataAndUrl("9badsource", "<payload/>", false); |
| } |
| |
| @Test(expected = IllegalArgumentException.class) |
| public void testMetadataAndUrlInvalidUrl() throws Exception { |
| new GsaFeedFileSender("badname:", false, charset); |
| } |
| |
| @Test |
| public void testMetadataAndUrlFailureWriting() throws Exception { |
| server.createContext("/xmlfeed", new HttpHandler() { |
| @Override |
| public void handle(HttpExchange ex) throws IOException { |
| throw new IOException(); |
| } |
| }); |
| String longMsg = "Some random really long string\n"; |
| int numRepeats = 1024 * 256; |
| StringBuilder sb = new StringBuilder(longMsg.length() * numRepeats); |
| for (int i = 0; i < numRepeats; i++) { |
| sb.append(longMsg); |
| } |
| // This payload has to be enough to exhaust output buffers, otherwise the |
| // exception will be noticed when reading the response. |
| String longPayload = sb.toString(); |
| sb = null; |
| thrown.expect(IOException.class); |
| sender.sendMetadataAndUrl("datasource", longPayload, false); |
| } |
| |
| @Test |
| public void testMetadataAndUrlGsaReturnedFailure() throws Exception { |
| MockHttpHandler handler |
| = new MockHttpHandler(200, "Some failure".getBytes(charset)); |
| server.createContext("/xmlfeed", handler); |
| |
| thrown.expect(IllegalStateException.class); |
| sender.sendMetadataAndUrl("datasource", "<payload/>", false); |
| } |
| |
| @Test |
| public void testMetadataAndUrlCantReadResponse() throws Exception { |
| server.createContext("/xmlfeed", new HttpHandler() { |
| @Override |
| public void handle(HttpExchange ex) throws IOException { |
| throw new IOException(); |
| } |
| }); |
| |
| thrown.expect(IOException.class); |
| sender.sendMetadataAndUrl("datasource", "<payload/>", false); |
| } |
| |
| @Test |
| public void testGroupsSuccess() throws Exception { |
| final String payload = "<someXmlString/>"; |
| final String groupsource = "docspot"; |
| final String goldenResponse |
| = "--<<\r\n" |
| + "Content-Disposition: form-data; name=\"groupsource\"\r\n" |
| + "Content-Type: text/plain\r\n" |
| + "\r\n" |
| + groupsource + "\r\n" |
| + "--<<\r\n" |
| + "Content-Disposition: form-data; name=\"data\"\r\n" |
| + "Content-Type: text/xml\r\n" |
| + "\r\n" |
| + payload + "\r\n" |
| + "--<<--\r\n"; |
| MockHttpHandler handler |
| = new MockHttpHandler(200, "Success".getBytes(charset)); |
| server.createContext("/xmlgroups", handler); |
| sender.sendGroups(groupsource, payload, false); |
| assertEquals("POST", handler.getRequestMethod()); |
| assertEquals(URI.create("/xmlgroups"), handler.getRequestUri()); |
| assertEquals("multipart/form-data; boundary=<<", |
| handler.getRequestHeaders().getFirst("Content-Type")); |
| assertEquals(goldenResponse, |
| new String(handler.getRequestBytes(), charset)); |
| } |
| |
| @Test |
| public void testGroupsInvalidGroupSource() throws Exception { |
| thrown.expect(IllegalArgumentException.class); |
| sender.sendGroups("bad#source", "<payload/>", false); |
| } |
| |
| private static class MockHttpHandler implements HttpHandler { |
| private final int responseCode; |
| private final byte[] responseBytes; |
| private String requestMethod; |
| private URI requestUri; |
| private Headers requestHeaders; |
| private byte[] requestBytes; |
| |
| public MockHttpHandler(int responseCode, byte[] responseBytes) { |
| this.responseCode = responseCode; |
| this.responseBytes = responseBytes; |
| } |
| |
| @Override |
| public void handle(HttpExchange ex) throws IOException { |
| requestMethod = ex.getRequestMethod(); |
| requestUri = ex.getRequestURI(); |
| requestHeaders = new Headers(); |
| requestHeaders.putAll(ex.getRequestHeaders()); |
| requestBytes = IOHelper.readInputStreamToByteArray(ex.getRequestBody()); |
| ex.sendResponseHeaders(responseCode, responseBytes == null ? -1 : 0); |
| if (responseBytes != null) { |
| ex.getResponseBody().write(responseBytes); |
| ex.getResponseBody().flush(); |
| ex.getResponseBody().close(); |
| } |
| ex.close(); |
| } |
| |
| public String getRequestMethod() { |
| return requestMethod; |
| } |
| |
| public URI getRequestUri() { |
| return requestUri; |
| } |
| |
| public Headers getRequestHeaders() { |
| return requestHeaders; |
| } |
| |
| public byte[] getRequestBytes() { |
| return requestBytes; |
| } |
| } |
| } |