/* * Copyright 2002-2014 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.http.converter.xml; import java.io.IOException; import java.nio.charset.Charset; import junit.framework.TestCase; import org.simpleframework.xml.Attribute; import org.simpleframework.xml.Element; import org.simpleframework.xml.ElementArray; import org.simpleframework.xml.Root; import org.springframework.android.test.Assert; import org.springframework.http.MediaType; import org.springframework.http.MockHttpInputMessage; import org.springframework.http.MockHttpOutputMessage; import org.springframework.http.converter.HttpMessageNotReadableException; import android.test.suitebuilder.annotation.SmallTest; /** * @author Roy Clarkson */ public class SimpleXmlHttpMessageConverterTests extends TestCase { private static final Charset UTF_8 = Charset.forName("UTF-8"); private static final Charset ISO_8859_1 = Charset.forName("ISO-8859-1"); private SimpleXmlHttpMessageConverter converter; @Override public void setUp() throws Exception { super.setUp(); this.converter = new SimpleXmlHttpMessageConverter(); } @Override public void tearDown() { converter = null; } @SmallTest public void testCanRead() { assertTrue("Converter does not support reading @Root", converter.canRead(SimpleObject.class, new MediaType("application", "xml"))); assertTrue("Converter does not support reading @Root", converter.canRead(SimpleObject.class, new MediaType("text", "xml"))); assertTrue("Converter does not support reading @Root", converter.canRead(SimpleObject.class, new MediaType("application", "*+xml"))); } @SmallTest public void testCanWrite() { assertTrue("Converter does not support writing @Root", converter.canWrite(SimpleObject.class, new MediaType("application", "xml"))); assertTrue("Converter does not support writing @Root", converter.canWrite(SimpleObject.class, new MediaType("text", "xml"))); assertTrue("Converter does not support writing @Root", converter.canWrite(SimpleObject.class, new MediaType("application", "*+xml"))); } @SmallTest public void testCanReadNoRootAnnotation() { // @Root annotation not required for reading assertTrue("Converter does not support reading @Root", converter.canRead(SimpleNoRootAnnotationObject.class, new MediaType("application", "xml"))); } @SmallTest public void testCanWriteNoRootAnnotation() { // @Root annotation is required for writing assertFalse("Converter does not support reading @Root", converter.canWrite(SimpleNoRootAnnotationObject.class, new MediaType("application", "xml"))); } @SmallTest public void testReadSimple() throws IOException { String body = "<root number=\"123\"><string>Example message</string></root>"; MockHttpInputMessage inputMessage = new MockHttpInputMessage(body.getBytes(UTF_8.displayName())); SimpleObject result = (SimpleObject) converter.read(SimpleObject.class, inputMessage); assertEquals("Invalid result", 123, result.getNumber()); assertEquals("Invalid result", "Example message", result.getString()); } @SmallTest public void testReadComplex() throws IOException { String body = "<root number=\"123\"><string>Example message</string><fraction>42.0</fraction><array length=\"2\"><string>Foo</string><string>Bar</string></array><bool>true</bool></root>"; MockHttpInputMessage inputMessage = new MockHttpInputMessage(body.getBytes(UTF_8.displayName())); ComplexObject result = (ComplexObject) converter.read(ComplexObject.class, inputMessage); assertEquals("Invalid result", 123, result.getNumber()); assertEquals("Invalid result", "Example message", result.getString()); assertEquals("Invalid result", 42.0f, result.getFraction()); Assert.assertArrayEquals("Invalid result", new String[]{"Foo", "Bar"}, result.getArray()); assertTrue(result.isBool()); assertNull(result.getNullstring()); } @SmallTest public void testReadSimpleNonAnnotated() throws IOException { String body = "<root><string>Example message</string><number>123</number></root>"; MockHttpInputMessage inputMessage = new MockHttpInputMessage(body.getBytes(UTF_8.displayName())); SimpleNonAnnotatedObject result = (SimpleNonAnnotatedObject) converter.read(SimpleNonAnnotatedObject.class, inputMessage); assertEquals("Invalid result", "Example message", result.getString()); assertEquals("Invalid result", 123, result.getNumber()); } @SmallTest public void testReadSimpleNoRootAnnotation() throws IOException { String body = "<root><string>Example message</string><number>123</number></root>"; MockHttpInputMessage inputMessage = new MockHttpInputMessage(body.getBytes(UTF_8.displayName())); SimpleNoRootAnnotationObject result = (SimpleNoRootAnnotationObject) converter.read(SimpleNoRootAnnotationObject.class, inputMessage); assertEquals("Invalid result", "Example message", result.getString()); assertEquals("Invalid result", 123, result.getNumber()); } @SmallTest public void testReadSimple_ISO_8859_1() throws IOException { String body = "<root number=\"123\"><string> ¡¢£¤¥</string></root>"; MockHttpInputMessage inputMessage = new MockHttpInputMessage(body.getBytes(ISO_8859_1.displayName())); SimpleObject result = (SimpleObject) converter.read(SimpleObject.class, inputMessage); assertEquals("Invalid result", 123, result.getNumber()); byte[] bytes = new byte[] {(byte)0xA0, (byte)0xA1, (byte)0xA2, (byte)0xA3, (byte)0xA4, (byte)0xA5}; Assert.assertArrayEquals("Invalid result", bytes, result.getString().getBytes(ISO_8859_1.displayName())); assertEquals("Invalid result", new String(bytes, ISO_8859_1.displayName()), result.getString()); } @SmallTest public void testWriteSimple() throws IOException { SimpleObject body = new SimpleObject(); body.setString("Example message"); body.setNumber(123); MockHttpOutputMessage outputMessage = new MockHttpOutputMessage(); converter.write(body, null, outputMessage); String result = outputMessage.getBodyAsString(UTF_8); assertTrue(result.contains("<string>Example message</string>")); assertTrue(result.contains("number=\"123\"")); assertEquals("Invalid content-type", new MediaType("application", "xml"), outputMessage.getHeaders().getContentType()); } @SmallTest public void testWriteComplex() throws IOException { ComplexObject body = new ComplexObject(); body.setString("Example message"); body.setNumber(123); body.setFraction(42.0f); body.setArray(new String[] {"Foo", "Bar" }); body.setBool(true); body.setNullstring(null); MockHttpOutputMessage outputMessage = new MockHttpOutputMessage(); converter.write(body, null, outputMessage); String result = outputMessage.getBodyAsString(UTF_8); assertTrue(result.contains("<string>Example message</string>")); assertTrue(result.contains("number=\"123\"")); assertTrue(result.contains("<fraction>42.0</fraction>")); assertTrue(result.contains("<array length=\"2\">") && result.contains("<string>Foo</string>") && result.contains("<string>Bar</string>") && result.contains("</array>")); assertFalse(result.contains("<nullstring>")); assertEquals("Invalid content-type", new MediaType("application", "xml"), outputMessage.getHeaders().getContentType()); } @SmallTest public void testWrite_ISO_8859_1() throws IOException { MediaType contentType = new MediaType("text", "xml", ISO_8859_1); MockHttpOutputMessage outputMessage = new MockHttpOutputMessage(); byte[] bytes = new byte[] {(byte)0xA0, (byte)0xA1, (byte)0xA2, (byte)0xA3, (byte)0xA4, (byte)0xA5}; String body = new String(bytes, ISO_8859_1.displayName()); converter.write(body, contentType, outputMessage); assertEquals("Invalid result", "<string>" + body + "</string>", outputMessage.getBodyAsString(ISO_8859_1)); assertEquals("Invalid content-type", contentType, outputMessage.getHeaders().getContentType()); } // helpers @Root private static class SimpleObject { @Element private String string; @Attribute private int number; public void setString(String string) { this.string = string; } public String getString() { return string; } public void setNumber(int number) { this.number = number; } public int getNumber() { return number; } } @SuppressWarnings("unused") private static class SimpleNonAnnotatedObject { private String string; private int number; public void setString(String string) { this.string = string; } public String getString() { return string; } public void setNumber(int number) { this.number = number; } public int getNumber() { return number; } } @SuppressWarnings("unused") private static class SimpleNoRootAnnotationObject { @Element private String string; @Element private int number; public void setString(String string) { this.string = string; } public String getString() { return string; } public void setNumber(int number) { this.number = number; } public int getNumber() { return number; } } @Root private static class ComplexObject { @Element private String string; @Attribute private int number; @Element private float fraction; @ElementArray private String[] array; @Element private boolean bool; @Element(required = false) private String nullstring; public boolean isBool() { return bool; } public void setBool(boolean bool) { this.bool = bool; } public String getString() { return string; } public void setString(String string) { this.string = string; } public int getNumber() { return number; } public void setNumber(int number) { this.number = number; } public float getFraction() { return fraction; } public void setFraction(float fraction) { this.fraction = fraction; } public String[] getArray() { return array; } public void setArray(String[] array) { this.array = array; } public void setNullstring(String nullstring) { this.nullstring = nullstring; } public String getNullstring() { return nullstring; } } }