/*
* Copyright 2002-2013 the original author or authors.
*
* 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 org.springframework.web.socket.adapter.standard;
import java.nio.ByteBuffer;
import javax.websocket.DecodeException;
import javax.websocket.Decoder;
import javax.websocket.EncodeException;
import javax.websocket.Encoder;
import org.junit.After;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.convert.ConversionService;
import org.springframework.core.convert.ConverterNotFoundException;
import org.springframework.core.convert.converter.Converter;
import org.springframework.core.convert.support.DefaultConversionService;
import org.springframework.core.convert.support.GenericConversionService;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.context.support.AnnotationConfigWebApplicationContext;
import org.springframework.web.socket.ContextLoaderTestUtils;
import static org.hamcrest.Matchers.*;
import static org.junit.Assert.*;
/**
* Test for {@link org.springframework.web.socket.adapter.standard.ConvertingEncoderDecoderSupport}.
*
* @author Phillip Webb
*/
public class ConvertingEncoderDecoderSupportTests {
private static final String CONVERTED_TEXT = "_test";
private static final ByteBuffer CONVERTED_BYTES = ByteBuffer.wrap("~test".getBytes());
@Rule
public ExpectedException thown = ExpectedException.none();
private WebApplicationContext applicationContext;
private MyType myType = new MyType("test");
@Before
public void setup() {
setup(Config.class);
}
@After
public void teardown() {
ContextLoaderTestUtils.setCurrentWebApplicationContext(null);
}
private void setup(Class<?> configurationClass) {
AnnotationConfigWebApplicationContext applicationContext = new AnnotationConfigWebApplicationContext();
applicationContext.register(configurationClass);
applicationContext.refresh();
this.applicationContext = applicationContext;
ContextLoaderTestUtils.setCurrentWebApplicationContext(this.applicationContext);
}
@Test
public void encodeToText() throws Exception {
assertThat(new MyTextEncoder().encode(myType), equalTo(CONVERTED_TEXT));
}
@Test
public void encodeToTextCannotConvert() throws Exception {
setup(NoConvertersConfig.class);
thown.expect(EncodeException.class);
thown.expectCause(isA(ConverterNotFoundException.class));
new MyTextEncoder().encode(myType);
}
@Test
public void encodeToBinary() throws Exception {
assertThat(new MyBinaryEncoder().encode(myType).array(),
equalTo(CONVERTED_BYTES.array()));
}
@Test
public void encodeToBinaryCannotConvert() throws Exception {
setup(NoConvertersConfig.class);
thown.expect(EncodeException.class);
thown.expectCause(isA(ConverterNotFoundException.class));
new MyBinaryEncoder().encode(myType);
}
@Test
public void decodeFromText() throws Exception {
Decoder.Text<MyType> decoder = new MyTextDecoder();
assertThat(decoder.willDecode(CONVERTED_TEXT), is(true));
assertThat(decoder.decode(CONVERTED_TEXT), equalTo(myType));
}
@Test
public void decodeFromTextCannotConvert() throws Exception {
setup(NoConvertersConfig.class);
Decoder.Text<MyType> decoder = new MyTextDecoder();
assertThat(decoder.willDecode(CONVERTED_TEXT), is(false));
thown.expect(DecodeException.class);
thown.expectCause(isA(ConverterNotFoundException.class));
decoder.decode(CONVERTED_TEXT);
}
@Test
public void decodeFromBinary() throws Exception {
Decoder.Binary<MyType> decoder = new MyBinaryDecoder();
assertThat(decoder.willDecode(CONVERTED_BYTES), is(true));
assertThat(decoder.decode(CONVERTED_BYTES), equalTo(myType));
}
@Test
public void decodeFromBinaryCannotConvert() throws Exception {
setup(NoConvertersConfig.class);
Decoder.Binary<MyType> decoder = new MyBinaryDecoder();
assertThat(decoder.willDecode(CONVERTED_BYTES), is(false));
thown.expect(DecodeException.class);
thown.expectCause(isA(ConverterNotFoundException.class));
decoder.decode(CONVERTED_BYTES);
}
@Test
public void encodeAndDecodeText() throws Exception {
MyTextEncoderDecoder encoderDecoder = new MyTextEncoderDecoder();
String encoded = encoderDecoder.encode(myType);
assertThat(encoderDecoder.decode(encoded), equalTo(myType));
}
@Test
public void encodeAndDecodeBytes() throws Exception {
MyBinaryEncoderDecoder encoderDecoder = new MyBinaryEncoderDecoder();
ByteBuffer encoded = encoderDecoder.encode(myType);
assertThat(encoderDecoder.decode(encoded), equalTo(myType));
}
@Test
public void autowiresIntoEncoder() throws Exception {
WithAutowire withAutowire = new WithAutowire();
withAutowire.init(null);
assertThat(withAutowire.config, equalTo(applicationContext.getBean(Config.class)));
}
@Test
public void cannotFindApplicationContext() throws Exception {
ContextLoaderTestUtils.setCurrentWebApplicationContext(null);
WithAutowire encoder = new WithAutowire();
encoder.init(null);
thown.expect(IllegalStateException.class);
thown.expectMessage("Unable to locate the Spring ApplicationContext");
encoder.encode(myType);
}
@Test
public void cannotFindConversionService() throws Exception {
setup(NoConfig.class);
MyBinaryEncoder encoder = new MyBinaryEncoder();
encoder.init(null);
thown.expect(IllegalStateException.class);
thown.expectMessage("Unable to find ConversionService");
encoder.encode(myType);
}
@Configuration
public static class Config {
@Bean
public ConversionService webSocketConversionService() {
GenericConversionService conversionService = new DefaultConversionService();
conversionService.addConverter(new MyTypeToStringConverter());
conversionService.addConverter(new MyTypeToBytesConverter());
conversionService.addConverter(new StringToMyTypeConverter());
conversionService.addConverter(new BytesToMyTypeConverter());
return conversionService;
}
}
@Configuration
public static class NoConvertersConfig {
@Bean
public ConversionService webSocketConversionService() {
return new GenericConversionService();
}
}
@Configuration
public static class NoConfig {
}
public static class MyType {
private String value;
public MyType(String value) {
this.value = value;
}
@Override
public String toString() {
return this.value;
}
@Override
public int hashCode() {
return value.hashCode();
}
@Override
public boolean equals(Object obj) {
if (obj instanceof MyType) {
return ((MyType)obj).value.equals(value);
}
return false;
}
}
private static class MyTypeToStringConverter implements Converter<MyType, String> {
@Override
public String convert(MyType source) {
return "_" + source.toString();
}
}
private static class MyTypeToBytesConverter implements Converter<MyType, byte[]> {
@Override
public byte[] convert(MyType source) {
return ("~" + source.toString()).getBytes();
}
}
private static class StringToMyTypeConverter implements Converter<String, MyType> {
@Override
public MyType convert(String source) {
return new MyType(source.substring(1));
}
}
private static class BytesToMyTypeConverter implements Converter<byte[], MyType> {
@Override
public MyType convert(byte[] source) {
return new MyType(new String(source).substring(1));
}
}
public static class MyTextEncoder extends
ConvertingEncoderDecoderSupport.TextEncoder<MyType> {
}
public static class MyBinaryEncoder extends
ConvertingEncoderDecoderSupport.BinaryEncoder<MyType> {
}
public static class MyTextDecoder extends
ConvertingEncoderDecoderSupport.TextDecoder<MyType> {
}
public static class MyBinaryDecoder extends
ConvertingEncoderDecoderSupport.BinaryDecoder<MyType> {
}
public static class MyTextEncoderDecoder extends
ConvertingEncoderDecoderSupport<MyType, String> implements Encoder.Text<MyType>,
Decoder.Text<MyType> {
}
public static class MyBinaryEncoderDecoder extends
ConvertingEncoderDecoderSupport<MyType, ByteBuffer> implements Encoder.Binary<MyType>,
Decoder.Binary<MyType> {
}
public static class WithAutowire extends ConvertingEncoderDecoderSupport.TextDecoder<MyType> {
@Autowired
private Config config;
}
}