blob: 75986c04201ac159ea5c63054fb555f5e3c87c8e [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You 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 org.apache.solr.response;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.StringWriter;
import java.nio.charset.StandardCharsets;
import org.apache.lucene.util.TestUtil;
import org.apache.solr.SolrTestCaseJ4;
import org.apache.solr.client.solrj.impl.BinaryResponseParser;
import org.apache.solr.common.util.ContentStreamBase.ByteArrayStream;
import org.apache.solr.common.util.ContentStreamBase.StringStream;
import org.apache.solr.common.util.NamedList;
import org.junit.BeforeClass;
import org.junit.AfterClass;
/**
* Tests the {@link RawResponseWriter} behavior, in particular when dealing with "base" writer
*/
public class TestRawResponseWriter extends SolrTestCaseJ4 {
private static RawResponseWriter writerXmlBase;
private static RawResponseWriter writerJsonBase;
private static RawResponseWriter writerBinBase;
private static RawResponseWriter writerNoBase;
private static RawResponseWriter[] allWriters;
@BeforeClass
public static void setupCoreAndWriters() throws Exception {
// we don't directly use this core or its config, we use
// QueryResponseWriters' constructed programmatically,
// but we do use this core for managing the life cycle of the requests
// we spin up.
initCore("solrconfig.xml","schema.xml");
writerNoBase = newRawResponseWriter(null); /* defaults to standard writer as base */
writerXmlBase = newRawResponseWriter("xml");
writerJsonBase = newRawResponseWriter("json");
writerBinBase = newRawResponseWriter("javabin");
allWriters = new RawResponseWriter[] {
writerXmlBase, writerJsonBase, writerBinBase, writerNoBase
};
}
@AfterClass
public static void cleanupWriters() throws Exception {
writerXmlBase = null;
writerJsonBase = null;
writerBinBase = null;
writerNoBase = null;
allWriters = null;
}
/**
* Regardless of base writer, the bytes in should be the same as the bytes out
* when response is a raw ContentStream written to an OutputStream
*/
public void testRawBinaryContentStream() throws IOException {
SolrQueryResponse rsp = new SolrQueryResponse();
byte[] data = new byte[TestUtil.nextInt(random(), 10, 2048)];
random().nextBytes(data);
ByteArrayStream stream = new ByteArrayStream(data, TestUtil.randomUnicodeString(random()));
stream.setContentType(TestUtil.randomSimpleString(random()));
rsp.add(RawResponseWriter.CONTENT, stream);
for (RawResponseWriter writer : allWriters) {
assertEquals(stream.getContentType(), writer.getContentType(req(), rsp));
ByteArrayOutputStream out = new ByteArrayOutputStream();
writer.write(out, req(), rsp);
assertArrayEquals(data, out.toByteArray());
}
}
/**
* Regardless of base writer, the String in should be the same as the String out
* when response is a raw ContentStream written to a Writer (or OutputStream)
*/
public void testRawStringContentStream() throws IOException {
SolrQueryResponse rsp = new SolrQueryResponse();
String data = TestUtil.randomUnicodeString(random());
StringStream stream = new StringStream(data);
stream.setContentType(TestUtil.randomSimpleString(random()));
rsp.add(RawResponseWriter.CONTENT, stream);
for (RawResponseWriter writer : allWriters) {
assertEquals(stream.getContentType(), writer.getContentType(req(), rsp));
// we should have the same string if we use a Writer
StringWriter sout = new StringWriter();
writer.write(sout, req(), rsp);
assertEquals(data, sout.toString());
// we should have UTF-8 Bytes if we use an OutputStream
ByteArrayOutputStream bout = new ByteArrayOutputStream();
writer.write(bout, req(), rsp);
assertEquals(data, bout.toString(StandardCharsets.UTF_8.toString()));
}
}
/**
* When no real ContentStream is specified, each base writer should be used for formatting
*/
public void testStructuredDataViaBaseWriters() throws IOException {
SolrQueryResponse rsp = new SolrQueryResponse();
// Don't send a ContentStream back, this will fall back to the configured base writer.
// But abuse the CONTENT key to ensure writer is also checking type
rsp.add(RawResponseWriter.CONTENT, "test");
rsp.add("foo", "bar");
// check Content-Type against each writer
assertEquals("application/xml; charset=UTF-8", writerNoBase.getContentType(req(), rsp));
assertEquals("application/xml; charset=UTF-8", writerXmlBase.getContentType(req(), rsp));
assertEquals("application/json; charset=UTF-8", writerJsonBase.getContentType(req(), rsp));
assertEquals("application/octet-stream", writerBinBase.getContentType(req(), rsp));
// check response against each writer
// xml & none (default behavior same as XML)
String xml = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" +
"<response>\n" +
"\n" +
"<str name=\"content\">test</str>\n" +
"<str name=\"foo\">bar</str>\n" +
"</response>\n";
StringWriter xmlSout = new StringWriter();
writerXmlBase.write(xmlSout, req(), rsp);
assertEquals(xml, xmlSout.toString());
ByteArrayOutputStream xmlBout = new ByteArrayOutputStream();
writerXmlBase.write(xmlBout, req(), rsp);
assertEquals(xml, xmlBout.toString(StandardCharsets.UTF_8.toString()));
//
StringWriter noneSout = new StringWriter();
writerNoBase.write(noneSout, req(), rsp);
assertEquals(xml, noneSout.toString());
ByteArrayOutputStream noneBout = new ByteArrayOutputStream();
writerNoBase.write(noneBout, req(), rsp);
assertEquals(xml, noneBout.toString(StandardCharsets.UTF_8.toString()));
// json
String json = "{\n" +
" \"content\":\"test\",\n" +
" \"foo\":\"bar\"}\n";
StringWriter jsonSout = new StringWriter();
writerJsonBase.write(jsonSout, req(), rsp);
assertEquals(json, jsonSout.toString());
ByteArrayOutputStream jsonBout = new ByteArrayOutputStream();
writerJsonBase.write(jsonBout, req(), rsp);
assertEquals(json, jsonBout.toString(StandardCharsets.UTF_8.toString()));
// javabin
ByteArrayOutputStream bytes = new ByteArrayOutputStream();
writerBinBase.write(bytes, req(), rsp);
BinaryResponseParser parser = new BinaryResponseParser();
NamedList<Object> out = parser.processResponse
(new ByteArrayInputStream(bytes.toByteArray()), /* encoding irrelevant */ null);
assertEquals(RawResponseWriter.CONTENT, out.getName(0));
assertEquals("test", out.getVal(0));
assertEquals("foo", out.getName(1));
assertEquals("bar", out.getVal(1));
}
/**
* Generates a new {@link RawResponseWriter} wrapping the specified baseWriter name
* (which much either be an implicitly defined response writer, or one explicitly
* configured in solrconfig.xml)
*
* @param baseWriter null or the name of a valid base writer
*/
@SuppressWarnings({"unchecked"})
private static RawResponseWriter newRawResponseWriter(String baseWriter) {
RawResponseWriter writer = new RawResponseWriter();
@SuppressWarnings({"rawtypes"})
NamedList initArgs = new NamedList<Object>();
if (null != baseWriter) {
initArgs.add("base", baseWriter);
}
writer.init(initArgs);
return writer;
}
}