package com.google.sitebricks.headless;
import static org.easymock.EasyMock.createNiceMock;
import static org.easymock.EasyMock.expect;
import static org.easymock.EasyMock.replay;
import static org.easymock.EasyMock.verify;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.Collections;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import org.testng.annotations.Test;
import com.google.common.collect.ImmutableMap;
import com.google.inject.AbstractModule;
import com.google.inject.Guice;
import com.google.inject.Injector;
import com.google.sitebricks.client.transport.Json;
import com.google.sitebricks.client.transport.Text;
import com.google.sitebricks.client.transport.Xml;
import com.google.sitebricks.conversion.Converter;
import com.google.sitebricks.conversion.ConverterRegistry;
import com.google.sitebricks.conversion.StandardTypeConverter;
/**
* A unit test for the reply builder/response populate pipeline.
*/
public class HeadlessReplyTest {
private static final String HELLO_THERE = "Hello there!";
private static final String INK_SPOTS = "Ink Spots";
private static final String MAYBE = "Maybe";
private static final int SONG_LENGTH_MAYBE = 3456;
private static final String X_MY_HEADER = "X-My-Header";
private static final String X_MY_HEADER_VAL = "X-My-Haisdjfoiajsd";
private static final String X_YOUR_HEADER = "X-Your-Header";
private static final String X_YOUR_HEADER_VAL = "2838L";
private static class FakeServletOutputStream extends ServletOutputStream {
private final ByteArrayOutputStream bout = new ByteArrayOutputStream();
@Override
public void write(int b) throws IOException {
bout.write(b);
}
@Override
public String toString() {
return bout.toString();
}
}
@Test
public void textReply() throws IOException {
Injector injector = Guice.createInjector();
HeadlessRenderer renderer = injector.getInstance(HeadlessRenderer.class);
HttpServletResponse response = createNiceMock(HttpServletResponse.class);
ServletOutputStream outputStream = fakeServletOutputStream();
// The script to expect for our mock.
response.setStatus(HttpServletResponse.SC_OK);
expect(response.getOutputStream())
.andReturn(outputStream);
response.setContentType(injector.getInstance(Text.class).contentType());
replay(response);
renderer.render(response, Reply.with(HELLO_THERE));
verify(response);
assert HELLO_THERE.equals(outputStream.toString());
}
@Test
public void jsonReply() throws IOException {
Injector injector = Guice.createInjector(new AbstractModule() {
@SuppressWarnings("rawtypes")
@Override
protected void configure() {
bind(ConverterRegistry.class).toInstance(new StandardTypeConverter(Collections.<Converter>emptySet()));
}
});
HeadlessRenderer renderer = injector.getInstance(HeadlessRenderer.class);
HttpServletResponse response = createNiceMock(HttpServletResponse.class);
ServletOutputStream outputStream = fakeServletOutputStream();
// The script to expect for our mock.
response.setStatus(HttpServletResponse.SC_OK);
expect(response.getOutputStream())
.andReturn(outputStream);
response.setContentType(injector.getInstance(Json.class).contentType());
replay(response);
Song maybeByTheInkspots = new Song(MAYBE, INK_SPOTS, SONG_LENGTH_MAYBE);
renderer.render(response, Reply.with(maybeByTheInkspots).as(Json.class));
verify(response);
String output = outputStream.toString();
assert output.contains(MAYBE);
assert output.contains(INK_SPOTS);
assert output.contains("" + SONG_LENGTH_MAYBE);
// Now the real test, unmarshall it back into Java.
Song song = injector.getInstance(Json.class)
.in(new ByteArrayInputStream(output.getBytes()), Song.class);
assert maybeByTheInkspots.hashCode() == song.hashCode();
assert maybeByTheInkspots.equals(song);
}
@Test
public void xmlReplyWithHeaders() throws IOException {
Injector injector = Guice.createInjector();
HeadlessRenderer renderer = injector.getInstance(HeadlessRenderer.class);
HttpServletResponse response = createNiceMock(HttpServletResponse.class);
ServletOutputStream outputStream = fakeServletOutputStream();
ImmutableMap<String, String> headerMap = ImmutableMap.of(
X_MY_HEADER, X_MY_HEADER_VAL,
X_YOUR_HEADER, X_YOUR_HEADER_VAL
);
// The script to expect for our mock.
response.setStatus(HttpServletResponse.SC_OK);
expect(response.getOutputStream())
.andReturn(outputStream);
response.setContentType(injector.getInstance(Xml.class).contentType());
response.setHeader(X_MY_HEADER, X_MY_HEADER_VAL);
response.setHeader(X_YOUR_HEADER, X_YOUR_HEADER_VAL);
replay(response);
Song maybeByTheInkspots = new Song(MAYBE, INK_SPOTS, SONG_LENGTH_MAYBE);
renderer.render(response, Reply.with(maybeByTheInkspots)
.as(Xml.class)
.headers(headerMap)
);
verify(response);
String output = outputStream.toString();
assert output.contains(MAYBE);
assert output.contains(INK_SPOTS);
assert output.contains("" + SONG_LENGTH_MAYBE);
// Now the real test, unmarshall it back into Java.
Song song = injector.getInstance(Xml.class)
.in(new ByteArrayInputStream(output.getBytes()), Song.class);
assert maybeByTheInkspots.hashCode() == song.hashCode();
assert maybeByTheInkspots.equals(song);
}
public static class Song {
private String name;
private String artist;
private int length;
// Needed for Jackson (crappy)
public Song() {
}
public Song(String name, String artist, int length) {
this.name = name;
this.artist = artist;
this.length = length;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getArtist() {
return artist;
}
public void setArtist(String artist) {
this.artist = artist;
}
public int getLength() {
return length;
}
public void setLength(int length) {
this.length = length;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Song song = (Song) o;
if (length != song.length) return false;
if (artist != null ? !artist.equals(song.artist) : song.artist != null) return false;
if (name != null ? !name.equals(song.name) : song.name != null) return false;
return true;
}
@Override
public int hashCode() {
int result = name != null ? name.hashCode() : 0;
result = 31 * result + (artist != null ? artist.hashCode() : 0);
result = 31 * result + length;
return result;
}
}
private static ServletOutputStream fakeServletOutputStream() {
return new FakeServletOutputStream();
}
}