/** * (C) Copyright 2013 Jabylon (http://www.jabylon.org) and others. * * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html */ package org.jabylon.properties.util; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNull; import static org.mockito.Mockito.when; import java.io.BufferedInputStream; import java.io.BufferedReader; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileReader; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.StringReader; import java.io.StringWriter; import org.apache.tools.ant.filters.StringInputStream; import org.eclipse.emf.ecore.resource.ContentHandler.ByteOrderMark; import org.jabylon.properties.PropertiesFactory; import org.jabylon.properties.Property; import org.jabylon.properties.PropertyAnnotation; import org.jabylon.properties.types.impl.PropertiesHelper; import org.junit.Before; import org.junit.Test; import org.mockito.Mockito; public class PropertiesHelperTest { private PropertiesHelper fixture; private StringWriter writer; @Before public void setup() { fixture = new PropertiesHelper(); writer = new StringWriter(); } @Test public void testLoadReadPropertyWikiExample() throws IOException { BufferedReader reader = null; try { reader = loadFile("wiki_example.properties"); Property property = fixture.readProperty(reader); assertEquals("You are reading the \".properties\" entry.\nThe exclamation mark can also mark text as comments.", property.getComment()); assertEquals("website", property.getKey()); assertEquals("http://en.wikipedia.org/", property.getValue()); property = fixture.readProperty(reader); assertNull(property.getComment()); assertEquals("language", property.getKey()); assertEquals("English", property.getValue()); property = fixture.readProperty(reader); assertEquals("The backslash below tells the application to continue reading\nthe value onto the next line.", property.getComment()); assertEquals("message", property.getKey()); assertEquals("Welcome to Wikipedia!", property.getValue()); property = fixture.readProperty(reader); assertEquals("Add spaces to the key", property.getComment()); assertEquals("key with spaces", property.getKey()); assertEquals("This is the value that could be looked up with the key \"key with spaces\".", property.getValue()); property = fixture.readProperty(reader); assertEquals("Unicode", property.getComment()); assertEquals("tab", property.getKey()); assertEquals("\t", property.getValue()); } finally { if (reader != null) reader.close(); } } /** * @see https://github.com/jutzig/jabylon/issues/55 * @throws IOException */ @Test public void testLoadPropertyWithUnicodeAndBOM() throws IOException { BufferedReader reader = null; try { InputStream stream = new BufferedInputStream(loadFileAsStream("Buttons_en.seenls")); PropertiesHelper.checkForBom(stream); reader = new BufferedReader(new InputStreamReader(stream)); Property property = fixture.readProperty(reader); assertEquals("DTM.CASCADE_SESSION_FRAMES_TEXT", property.getKey()); assertEquals("Cascade", property.getValue()); assertEquals("test", fixture.getLicenseHeader()); } finally { if (reader != null) reader.close(); } } @Test public void testReadPropertySingleCharComment() throws IOException { BufferedReader reader = null; try { reader = loadFile("plugin.properties"); Property property = fixture.readProperty(reader); assertEquals("<copyright>\n</copyright>\n\n$Id$", property.getComment()); assertEquals("pluginName", property.getKey()); assertEquals("Properties Model", property.getValue()); property = fixture.readProperty(reader); assertNull(property.getComment()); assertEquals("providerName", property.getKey()); assertEquals("www.example.org", property.getValue()); assertNull(fixture.readProperty(reader)); } finally { if (reader != null) reader.close(); } } @Test public void testReadUnicodePropertyWithUnicodeEscapes() throws IOException { fixture = new PropertiesHelper(false); BufferedReader reader = new BufferedReader(new StringReader("äö\\u00DC = aaa")); try { Property property = fixture.readProperty(reader); assertEquals("even with escaping turned of, it must still parse the escaped strings", "äöÜ", property.getKey()); assertEquals("aaa", property.getValue()); } finally { if (reader != null) reader.close(); } } @Test public void testWriteProperty() throws IOException { Property property = PropertiesFactory.eINSTANCE.createProperty(); property.setComment("test"); property.setKey("key"); property.setValue("value"); fixture.writeProperty(writer, property); assertEquals("#test\nkey = value\n", writer.toString()); } @Test public void testWritePropertyUnicode() throws IOException { Property property = PropertiesFactory.eINSTANCE.createProperty(); property.setComment("test"); property.setKey("ä"); property.setValue("ü"); fixture.writeProperty(writer, property); assertEquals("#test\n\\u00e4 = \\u00fc\n", writer.toString()); } @Test public void testWritePropertyKeyWithSpaces() throws IOException { Property property = PropertiesFactory.eINSTANCE.createProperty(); property.setComment("test"); property.setKey("key with spaces"); property.setValue("test"); fixture.writeProperty(writer, property); assertEquals("#test\nkey\\ with\\ spaces = test\n", writer.toString()); } @Test public void testWritePropertyMultiline() throws IOException { Property property = PropertiesFactory.eINSTANCE.createProperty(); property.setKey("key"); property.setValue("test\ntest"); fixture.writeProperty(writer, property); assertEquals("key = test\\ntest\n", writer.toString()); } @Test public void testWritePropertyWindowsMultiline() throws IOException { Property property = PropertiesFactory.eINSTANCE.createProperty(); property.setKey("key"); property.setValue("test\r\ntest"); fixture.writeProperty(writer, property); assertEquals("key = test\\r\\ntest\n", writer.toString()); } @Test public void testWritePropertyKeyMultiline() throws IOException { Property property = PropertiesFactory.eINSTANCE.createProperty(); property.setKey("key\nkey"); property.setValue("test"); fixture.writeProperty(writer, property); assertEquals("key\\\nkey = test\n", writer.toString()); } @Test public void testReadPropertyWindowsMultiline() throws IOException { BufferedReader reader = asReader("key = test\\\r\ntest\n"); Property property = fixture.readProperty(reader); assertEquals("key", property.getKey()); assertEquals("With the leading \\ we need to read into the next line","testtest", property.getValue()); } @Test public void testReadPropertyMultilineLeadingSpaces() throws IOException { BufferedReader reader = asReader("key = test\\\n test\n"); Property property = fixture.readProperty(reader); assertEquals("key", property.getKey()); assertEquals("With the leading \\ we need to read into the next line and also ignore leading whitespace there","testtest", property.getValue()); } @Test public void testReadIgnoredProperties() throws IOException { BufferedReader reader = asReader("key = test\n#comment\n#@non-translatable\nkey1=value\n#new comment\nkey2=value"); Property property = fixture.readProperty(reader); assertEquals("key", property.getKey()); assertEquals("test", property.getValue()); property = fixture.readProperty(reader); assertEquals("key1 must be ignored","key2", property.getKey()); assertEquals("value", property.getValue()); assertEquals("new comment", property.getComment()); } @Test public void testWritePropertyMultilineComment() throws IOException { Property property = PropertiesFactory.eINSTANCE.createProperty(); property.setComment("test\ntest"); property.setKey("key"); property.setValue("test"); fixture.writeProperty(writer, property); assertEquals("#test\n#test\nkey = test\n", writer.toString()); } private BufferedReader loadFile(String name) throws FileNotFoundException { File file = new File("src/test/resources/project/master/org/jabylon/properties/util/" + name); return new BufferedReader(new FileReader(file)); } private InputStream loadFileAsStream(String name) throws FileNotFoundException { File file = new File("src/test/resources/project/master/org/jabylon/properties/util/" + name); return new FileInputStream(file); } @Test public void testCheckForBom() throws Exception { byte[] bytes = ByteOrderMark.UTF_16BE.bytes(); ByteArrayOutputStream out = new ByteArrayOutputStream(); out.write(bytes); out.write("test".getBytes()); ByteArrayInputStream stream = new ByteArrayInputStream(out.toByteArray()); ByteOrderMark bom = PropertiesHelper.checkForBom(stream); assertEquals(ByteOrderMark.UTF_16BE, bom); BufferedReader reader = new BufferedReader(new InputStreamReader(stream)); assertEquals("The reader must contain everything after the bom", "test", reader.readLine()); } @Test public void testCheckForBomNoBom() throws Exception { ByteArrayInputStream stream = new ByteArrayInputStream("test".getBytes()); ByteOrderMark bom = PropertiesHelper.checkForBom(stream); assertNull(bom); BufferedReader reader = new BufferedReader(new InputStreamReader(stream)); assertEquals("The reader must contain everything after the bom", "test", reader.readLine()); } @Test(expected=IllegalArgumentException.class) public void testCheckForBomWrongStream() throws Exception { InputStream in = Mockito.mock(InputStream.class); when(in.markSupported()).thenReturn(false); PropertiesHelper.checkForBom(in); } /** * tests that files that contain only a newline are handled correctly * http://github.com/jutzig/jabylon/issues/issue/104 * @throws IOException */ @Test public void testEmptyFile() throws IOException { StringInputStream in = new StringInputStream("\n\r"); Property property = fixture.readProperty(new BufferedReader(new InputStreamReader(in))); assertNull(property); } /** * tests that unicode non breakable space (\u00A0)is preserved * see https://github.com/jutzig/jabylon/issues/149 * @throws IOException */ @Test public void testPreserveNBSPWrite() throws IOException { Property property = PropertiesFactory.eINSTANCE.createProperty(); property.setKey("key"); property.setValue("test\u00A0"); fixture.writeProperty(writer, property); assertEquals("key = test\\u00a0\n", writer.toString()); } /** * tests that unicode non breakable space (\u00A0)is preserved * see https://github.com/jutzig/jabylon/issues/149 * @throws IOException */ @Test public void testPreserveNBSPWriteNoEscaping() throws IOException { fixture = new PropertiesHelper(false); Property property = PropertiesFactory.eINSTANCE.createProperty(); property.setKey("key"); property.setValue("test\u00A0"); fixture.writeProperty(writer, property); assertEquals("key = test\u00A0\n", writer.toString()); } /** * tests that unicode non breakable space (\u00A0)is preserved * see https://github.com/jutzig/jabylon/issues/149 * @throws IOException */ @Test public void testPreserveNBSPRead() throws IOException { BufferedReader reader = new BufferedReader(new StringReader("key = test\\u00a0\n")); try { Property property = fixture.readProperty(reader); assertEquals("the NBSP must survive", "test\u00a0", property.getValue()); } finally { if (reader != null) reader.close(); } } /** * tests that unicode non breakable space (\u00A0)is preserved * see https://github.com/jutzig/jabylon/issues/149 * @throws IOException */ @Test public void testPreserveNBSPReadNoEscaping() throws IOException { fixture = new PropertiesHelper(false); BufferedReader reader = new BufferedReader(new StringReader("key = test\u00a0\n")); try { Property property = fixture.readProperty(reader); assertEquals("the NBSP must survive", "test\u00a0", property.getValue()); } finally { if (reader != null) reader.close(); } } /** * tests that quotes in comments are handled properly * see https://github.com/jutzig/jabylon/issues/183 * @throws IOException */ @Test public void testQuotesInComments() throws IOException { fixture = new PropertiesHelper(false); BufferedReader reader = new BufferedReader(new StringReader("# Processes \"display\" button\r\n" +"PROC_INST_DISPLAY_IMG=dashb_display_12.gif")); try { Property property = fixture.readProperty(reader); assertEquals("dashb_display_12.gif", property.getValue()); assertEquals("PROC_INST_DISPLAY_IMG", property.getKey()); assertEquals("Processes \"display\" button", property.getComment()); } finally { if (reader != null) reader.close(); } } /** * tests that quotes in comments are handled properly * see https://github.com/jutzig/jabylon/issues/183 * @throws IOException */ @Test public void testQuotesInExclamationComments() throws IOException { fixture = new PropertiesHelper(false); BufferedReader reader = new BufferedReader(new StringReader("! Processes \"display\" button\r\n" +"PROC_INST_DISPLAY_IMG=dashb_display_12.gif")); try { Property property = fixture.readProperty(reader); assertEquals("dashb_display_12.gif", property.getValue()); assertEquals("PROC_INST_DISPLAY_IMG", property.getKey()); assertEquals("Processes \"display\" button", property.getComment()); } finally { if (reader != null) reader.close(); } } /** * tests that the parser resets a key when the newline is not escaped * see https://github.com/jutzig/jabylon/issues/183 * @throws IOException */ @Test public void testMultilineHandling() throws IOException { fixture = new PropertiesHelper(false); BufferedReader reader = new BufferedReader(new StringReader("// foo\n\r" +"PROC_INST_DISPLAY_IMG=dashb_display_12.gif")); try { Property property = fixture.readProperty(reader); assertEquals("dashb_display_12.gif", property.getValue()); assertEquals("PROC_INST_DISPLAY_IMG", property.getKey()); } finally { if (reader != null) reader.close(); } } /** * tests that leading spaces are properly escaped * see https://github.com/jutzig/jabylon/issues/186 * @throws IOException */ @Test public void testLeadingSpacesWrite() throws IOException { Property property = PropertiesFactory.eINSTANCE.createProperty(); property.setKey("key"); property.setValue(" test"); fixture.writeProperty(writer, property); assertEquals("key = \\ test\n", writer.toString()); } /** * tests that leading spaces are preserved during parsing * see https://github.com/jutzig/jabylon/issues/186 * @throws IOException */ @Test public void testLeadingSpacesRead() throws IOException { BufferedReader reader = new BufferedReader(new StringReader("key = \\ value")); Property property = fixture.readProperty(reader); assertEquals("key", property.getKey()); assertEquals(" value", property.getValue()); } /** * tests that newlines are converted to \n * see https://github.com/jutzig/jabylon/issues/185 * @throws IOException */ @Test public void testLFWrite() throws IOException { Property property = PropertiesFactory.eINSTANCE.createProperty(); property.setKey("key"); property.setValue("test\ntest"); fixture.writeProperty(writer, property); assertEquals("key = test\\ntest\n", writer.toString()); } /** * tests that CRLFs are converted to \r\n * see https://github.com/jutzig/jabylon/issues/185 * @throws IOException */ @Test public void testCRLFWrite() throws IOException { Property property = PropertiesFactory.eINSTANCE.createProperty(); property.setKey("key"); property.setValue("test\r\ntest"); fixture.writeProperty(writer, property); assertEquals("key = test\\r\\ntest\n", writer.toString()); } /** * tests that \n and \r are replaced with actual values during reading * see https://github.com/jutzig/jabylon/issues/186 * @throws IOException */ @Test public void testCRLFRead() throws IOException { BufferedReader reader = new BufferedReader(new StringReader("key = value\\r\\n")); Property property = fixture.readProperty(reader); assertEquals("key", property.getKey()); assertEquals("value\r\n", property.getValue()); } /** * tests that annotations are written correctly * @throws IOException */ @Test public void testWritePropertyWithAnnotation() throws IOException { Property property = PropertiesFactory.eINSTANCE.createProperty(); property.setComment("comment"); PropertyAnnotation ann1 = PropertiesFactory.eINSTANCE.createPropertyAnnotation(); ann1.setName("foo"); ann1.getValues().put("test", "value"); property.getAnnotations().add(ann1); PropertyAnnotation ann2 = PropertiesFactory.eINSTANCE.createPropertyAnnotation(); ann2.setName("bar"); property.getAnnotations().add(ann2); property.setKey("key"); property.setValue("test"); fixture.writeProperty(writer, property); assertEquals("#@foo(test=\"value\")@bar\n#comment\nkey = test\n", writer.toString()); } /** * tests that annotations are read correctly * @throws IOException */ @Test public void testReadPropertyWithAnnotation() throws IOException { BufferedReader reader = new BufferedReader(new StringReader("#@foo(test=\"value\")@bar\nkey = value")); Property property = fixture.readProperty(reader); assertEquals("key", property.getKey()); assertEquals("value", property.getValue()); assertEquals(2, property.getAnnotations().size()); assertEquals("foo", property.getAnnotations().get(0).getName()); } /** * tests that annotations are read correctly * @throws IOException */ @Test public void testColonInKey() throws IOException { BufferedReader reader = new BufferedReader(new StringReader("Name\\: = Name\\:")); Property property = fixture.readProperty(reader); assertEquals("Name:", property.getKey()); assertEquals("Name:", property.getValue()); } @Test public void testColonInKey2() throws IOException { BufferedReader reader = new BufferedReader(new StringReader("Name\\: = Name:")); Property property = fixture.readProperty(reader); assertEquals("Name:", property.getKey()); assertEquals("Name:", property.getValue()); } protected BufferedReader asReader(String string) { return new BufferedReader(new StringReader(string)); } }