package ezvcard.io.scribe; import static ezvcard.VCardDataType.URI; import static ezvcard.VCardDataType.URL; import static ezvcard.VCardVersion.V2_1; import static ezvcard.VCardVersion.V3_0; import static ezvcard.VCardVersion.V4_0; import static org.junit.Assert.assertArrayEquals; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNull; import org.junit.Test; import ezvcard.VCardVersion; import ezvcard.io.scribe.Sensei.Check; import ezvcard.parameter.Encoding; import ezvcard.parameter.ImageType; import ezvcard.property.BinaryProperty; import ezvcard.util.DataUri; import ezvcard.util.org.apache.commons.codec.binary.Base64; /* Copyright (c) 2012-2016, Michael Angstadt All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. The views and conclusions contained in the software and documentation are those of the authors and should not be interpreted as representing official policies, either expressed or implied, of the FreeBSD Project. */ /** * @author Michael Angstadt */ public class BinaryPropertyScribeTest { private final BinaryPropertyScribeImpl scribe = new BinaryPropertyScribeImpl(); private final Sensei<BinaryTypeImpl> sensei = new Sensei<BinaryTypeImpl>(scribe); private final String url = "http://example.com/image.jpg"; private final String urlUnknownExtension = "http://example.com/image.aaa"; private final String urlWithoutExtension = "http://example.com/image"; private final byte[] data = "data".getBytes(); private final String base64Data = Base64.encodeBase64String(data); private final String dataUri = new DataUri("image/jpeg", data).toString(); private final String dataUriNoContentType = new DataUri("application/octet-stream", data).toString(); private final BinaryTypeImpl withUrl = new BinaryTypeImpl(); { withUrl.setUrl(url, ImageType.JPEG); withUrl.getParameters().setEncoding(Encoding._8BIT); //ENCODING parameter (if one exists) should be removed when written } private final BinaryTypeImpl withDataNoContentType = new BinaryTypeImpl(); { withDataNoContentType.setData(data, null); } private final BinaryTypeImpl withData = new BinaryTypeImpl(); { withData.setData(data, ImageType.JPEG); withData.setType("work"); withData.getParameters().setEncoding(Encoding._8BIT); //ENCODING parameter (if one exists) should be removed/overwritten when written withData.getParameters().setMediaType("foo"); //MEDIATYPE parameter (if one exists) should be removed when written } private final BinaryTypeImpl empty = new BinaryTypeImpl(); @Test public void dataType() { sensei.assertDataType(withUrl).versions(V2_1).run(URL); sensei.assertDataType(withUrl).versions(V3_0, V4_0).run(URI); sensei.assertDataType(withData).versions(V2_1, V3_0).run(null); sensei.assertDataType(withData).versions(V4_0).run(URI); sensei.assertDataType(withDataNoContentType).versions(V2_1, V3_0).run(null); sensei.assertDataType(withDataNoContentType).versions(V4_0).run(URI); sensei.assertDataType(empty).versions(V2_1, V3_0).run(null); sensei.assertDataType(empty).versions(V4_0).run(URI); } @Test public void prepareParameters() { sensei.assertPrepareParams(withUrl).versions(V2_1, V3_0).expected("TYPE", "jpeg").run(); sensei.assertPrepareParams(withUrl).versions(V4_0).expected("MEDIATYPE", "image/jpeg").run(); sensei.assertPrepareParams(withData).versions(V2_1).expected("TYPE", "jpeg").expected("ENCODING", "BASE64").run(); sensei.assertPrepareParams(withData).versions(V3_0).expected("TYPE", "jpeg").expected("ENCODING", "b").run(); sensei.assertPrepareParams(withData).versions(V4_0).expected("TYPE", "work").run(); sensei.assertPrepareParams(withDataNoContentType).versions(V2_1).expected("ENCODING", "BASE64").run(); sensei.assertPrepareParams(withDataNoContentType).versions(V3_0).expected("ENCODING", "b").run(); sensei.assertPrepareParams(withDataNoContentType).versions(V4_0).run(); } @Test public void writeText() { sensei.assertWriteText(withUrl).run(url); sensei.assertWriteText(withData).versions(V2_1, V3_0).run(base64Data); sensei.assertWriteText(withData).versions(V4_0).run(dataUri); sensei.assertWriteText(withDataNoContentType).versions(V2_1, V3_0).run(base64Data); sensei.assertWriteText(withDataNoContentType).versions(V4_0).run(dataUriNoContentType); sensei.assertWriteText(empty).run(""); } @Test public void writeXml() { sensei.assertWriteXml(withUrl).run("<uri>" + url + "</uri>"); sensei.assertWriteXml(withData).run("<uri>" + dataUri + "</uri>"); sensei.assertWriteXml(withDataNoContentType).run("<uri>" + dataUriNoContentType + "</uri>"); sensei.assertWriteXml(empty).run("<uri/>"); } @Test public void writeJson() { sensei.assertWriteJson(withUrl).run(url); sensei.assertWriteJson(withData).run(dataUri); sensei.assertWriteJson(withDataNoContentType).run(dataUriNoContentType); sensei.assertWriteJson(empty).run(""); } @Test public void parseText_url() { { VCardVersion versions[] = { V2_1, V3_0 }; //without TYPE parameter sensei.assertParseText(url).dataType(URL).versions(versions).run(hasUrl(url, ImageType.JPEG)); sensei.assertParseText(url).versions(versions).run(hasUrl(url, ImageType.JPEG)); sensei.assertParseText(urlUnknownExtension).dataType(URL).versions(versions).run(hasUrl(urlUnknownExtension, null)); sensei.assertParseText(urlUnknownExtension).versions(versions).run(hasUrl(urlUnknownExtension, null)); sensei.assertParseText(urlWithoutExtension).dataType(URL).versions(versions).run(hasUrl(urlWithoutExtension, null)); sensei.assertParseText(urlWithoutExtension).versions(versions).run(hasUrl(urlWithoutExtension, null)); //with TYPE parameter sensei.assertParseText(url).dataType(URL).versions(versions).param("TYPE", "JPEG").run(hasUrl(url, ImageType.JPEG)); sensei.assertParseText(url).versions(versions).param("TYPE", "JPEG").run(hasUrl(url, ImageType.JPEG)); } { VCardVersion version = V4_0; //without MEDIATYPE parameter sensei.assertParseText(url).dataType(URI).versions(version).run(hasUrl(url, ImageType.JPEG)); sensei.assertParseText(url).versions(version).run(hasUrl(url, ImageType.JPEG)); sensei.assertParseText(urlUnknownExtension).dataType(URL).versions(version).run(hasUrl(urlUnknownExtension, null)); sensei.assertParseText(urlUnknownExtension).versions(version).run(hasUrl(urlUnknownExtension, null)); sensei.assertParseText(urlWithoutExtension).dataType(URI).versions(version).run(hasUrl(urlWithoutExtension, null)); sensei.assertParseText(urlWithoutExtension).versions(version).run(hasUrl(urlWithoutExtension, null)); //with MEDIATYPE parameter sensei.assertParseText(url).dataType(URI).versions(version).param("MEDIATYPE", "image/jpeg").run(hasUrl(url, ImageType.JPEG)); sensei.assertParseText(url).versions(version).param("MEDIATYPE", "image/jpeg").run(hasUrl(url, ImageType.JPEG)); } } @Test public void parseText_binary() { //2.1, 3.0 { VCardVersion versions[] = { V2_1, V3_0 }; //with TYPE { //B encoding sensei.assertParseText(base64Data).dataType(null).versions(versions).param("TYPE", "JPEG").param("ENCODING", "b").run(hasData(data, ImageType.JPEG)); //BASE64 encoding sensei.assertParseText(base64Data).dataType(null).versions(versions).param("TYPE", "JPEG").param("ENCODING", "base64").run(hasData(data, ImageType.JPEG)); //without encoding sensei.assertParseText(base64Data).dataType(null).versions(versions).param("TYPE", "JPEG").run(hasData(data, ImageType.JPEG)); } //without TYPE { //B encoding sensei.assertParseText(base64Data).dataType(null).versions(versions).param("ENCODING", "b").run(hasData(data, null)); //BASE64 encoding sensei.assertParseText(base64Data).dataType(null).versions(versions).param("ENCODING", "base64").run(hasData(data, null)); //without encoding sensei.assertParseText(base64Data).dataType(null).versions(versions).run(hasData(data, null)); } } //4.0 { VCardVersion version = V4_0; //without MEDIATYPE sensei.assertParseText(dataUri).versions(version).run(hasData(data, ImageType.JPEG)); //with MEDIATYPE (parameter should be ignored) sensei.assertParseText(dataUri).versions(version).param("MEDIATYPE", "image/png").run(hasData(data, ImageType.JPEG)); } } @Test public void parseXml_url() { //with MEDIATYPE sensei.assertParseXml("<uri>" + url + "</uri>").param("MEDIATYPE", "image/jpeg").run(hasUrl(url, ImageType.JPEG)); //without MEDIATYPE sensei.assertParseXml("<uri>" + url + "</uri>").run(hasUrl(url, ImageType.JPEG)); sensei.assertParseXml("<uri>" + urlUnknownExtension + "</uri>").run(hasUrl(urlUnknownExtension, null)); sensei.assertParseXml("<uri>" + urlWithoutExtension + "</uri>").run(hasUrl(urlWithoutExtension, null)); } @Test public void parseXml_binary() { //with MEDIATYPE (parameter should be ignored sensei.assertParseXml("<uri>" + dataUri + "</uri>").param("MEDIATYPE", "image/png").run(hasData(data, ImageType.JPEG)); //without MEDIATYPE sensei.assertParseXml("<uri>" + dataUri + "</uri>").run(hasData(data, ImageType.JPEG)); } @Test public void parseXml_empty() { sensei.assertParseXml("").cannotParse(); } @Test public void parseHtml_url() { //with type sensei.assertParseHtml("<object type=\"image/gif\" data=\"" + url + "\" />").run(hasUrl(url, ImageType.GIF)); //without type sensei.assertParseHtml("<object data=\"" + url + "\" />").run(hasUrl(url, ImageType.JPEG)); sensei.assertParseHtml("<object data=\"" + urlUnknownExtension + "\" />").run(hasUrl(urlUnknownExtension, null)); sensei.assertParseHtml("<object data=\"" + urlWithoutExtension + "\" />").run(hasUrl(urlWithoutExtension, null)); } @Test public void parseHtml_binary() { //with type (should be ignored) sensei.assertParseHtml("<object type=\"image/png\" data=\"" + dataUri + "\" />").run(hasData(data, ImageType.JPEG)); //without type sensei.assertParseHtml("<object data=\"" + dataUri + "\" />").run(hasData(data, ImageType.JPEG)); } @Test public void parseHtml_invalid() { sensei.assertParseHtml("<object type=\"image/gif\" />").cannotParse(); sensei.assertParseHtml("<div />").cannotParse(); } @Test public void parseJson_url() { //with MEDIATYPE sensei.assertParseJson(url).param("MEDIATYPE", "image/jpeg").run(hasUrl(url, ImageType.JPEG)); //without MEDIATYPE sensei.assertParseJson(url).run(hasUrl(url, ImageType.JPEG)); sensei.assertParseJson(urlUnknownExtension).run(hasUrl(urlUnknownExtension, null)); sensei.assertParseJson(urlWithoutExtension).run(hasUrl(urlWithoutExtension, null)); sensei.assertParseJson("").run(hasUrl("", null)); } @Test public void parseJson_binary() { //with MEDIATYPE (parameter should be ignored) sensei.assertParseJson(dataUri).param("MEDIATYPE", "image/png").run(hasData(data, ImageType.JPEG)); //without MEDIATYPE sensei.assertParseJson(dataUri).run(hasData(data, ImageType.JPEG)); } private static class BinaryPropertyScribeImpl extends BinaryPropertyScribe<BinaryTypeImpl, ImageType> { public BinaryPropertyScribeImpl() { super(BinaryTypeImpl.class, "BINARY"); } @Override protected ImageType _mediaTypeFromTypeParameter(String type) { return ImageType.get(type, null, null); } @Override protected ImageType _mediaTypeFromMediaTypeParameter(String mediaType) { return ImageType.get(null, mediaType, null); } @Override protected ImageType _mediaTypeFromFileExtension(String extension) { return ImageType.find(null, null, extension); } @Override protected BinaryTypeImpl _newInstance(String uri, ImageType contentType) { BinaryTypeImpl property = new BinaryTypeImpl(); property.setUrl(uri, contentType); return property; } @Override protected BinaryTypeImpl _newInstance(byte[] data, ImageType contentType) { BinaryTypeImpl property = new BinaryTypeImpl(); property.setData(data, contentType); return property; } } private static class BinaryTypeImpl extends BinaryProperty<ImageType> { public BinaryTypeImpl() { super((String) null, null); } } private Check<BinaryTypeImpl> hasUrl(final String url, final ImageType contentType) { return new Check<BinaryTypeImpl>() { public void check(BinaryTypeImpl actual) { assertEquals(url, actual.getUrl()); assertNull(actual.getData()); assertEquals(contentType, actual.getContentType()); } }; } private Check<BinaryTypeImpl> hasData(final byte[] data, final ImageType contentType) { return new Check<BinaryTypeImpl>() { public void check(BinaryTypeImpl actual) { assertNull(actual.getUrl()); assertArrayEquals(data, actual.getData()); assertEquals(contentType, actual.getContentType()); } }; } }