| /* |
| * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. |
| * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
| * |
| * This code is free software; you can redistribute it and/or modify it |
| * under the terms of the GNU General Public License version 2 only, as |
| * published by the Free Software Foundation. |
| * |
| * This code is distributed in the hope that it will be useful, but WITHOUT |
| * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
| * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
| * version 2 for more details (a copy is included in the LICENSE file that |
| * accompanied this code). |
| * |
| * You should have received a copy of the GNU General Public License version |
| * 2 along with this work; if not, write to the Free Software Foundation, |
| * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. |
| * |
| * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
| * or visit www.oracle.com if you need additional information or have any |
| * questions. |
| */ |
| |
| /* |
| * @test |
| * @summary tests the load and store methods of Properties class |
| * @author Xueming Shen |
| * @bug 4094886 |
| * @modules jdk.charsets |
| * @key randomness |
| */ |
| |
| import java.io.BufferedReader; |
| import java.io.ByteArrayInputStream; |
| import java.io.ByteArrayOutputStream; |
| import java.io.File; |
| import java.io.FileInputStream; |
| import java.io.FileOutputStream; |
| import java.io.IOException; |
| import java.io.InputStream; |
| import java.io.InputStreamReader; |
| import java.io.OutputStream; |
| import java.io.OutputStreamWriter; |
| import java.io.Reader; |
| import java.io.Writer; |
| import java.util.Properties; |
| import java.util.Random; |
| |
| public class PropertiesTest { |
| |
| private static boolean failure = false; |
| private static int failCount = 0; |
| |
| /** |
| * Main to interpret arguments and run several tests. |
| * |
| */ |
| public static void main(String[] args) throws Exception { |
| BlankLines(); |
| EscapeSpace(); |
| LoadParsing(); |
| SaveEncoding(); |
| SaveLoadBasher(); |
| SaveSeparator(); |
| SaveClose(); |
| SaveComments(); |
| UnicodeEscape(); |
| |
| if (failure) |
| throw new RuntimeException("Failure in Properties testing."); |
| else |
| System.err.println("OKAY: All tests passed."); |
| } |
| |
| private static void report(String testName) { |
| int spacesToAdd = 30 - testName.length(); |
| StringBuffer paddedNameBuffer = new StringBuffer(testName); |
| for (int i=0; i<spacesToAdd; i++) |
| paddedNameBuffer.append(" "); |
| String paddedName = paddedNameBuffer.toString(); |
| System.err.println(paddedName + ": " + |
| (failCount==0 ? "Passed":"Failed("+failCount+")")); |
| if (failCount > 0) |
| failure = true; |
| failCount = 0; |
| } |
| |
| private static void check(Properties prop1, Properties prop2) { |
| if (!prop1.equals(prop2)) |
| failCount++; |
| } |
| |
| private static Reader getReader(String src, String csn) |
| throws Exception { |
| return new InputStreamReader( |
| new ByteArrayInputStream(src.getBytes()), |
| csn); |
| } |
| |
| private static OutputStream getFOS(String name) |
| throws Exception |
| { |
| return new FileOutputStream(name); |
| } |
| |
| private static Writer getFOSW(String name, String csn) |
| throws Exception |
| { |
| return new OutputStreamWriter( |
| new FileOutputStream(name), |
| csn); |
| } |
| |
| private static Reader getReader(byte[] src, String csn) |
| throws Exception { |
| return new InputStreamReader(new ByteArrayInputStream(src), csn); |
| } |
| |
| private static InputStream getInputStream(String src) { |
| return new ByteArrayInputStream(src.getBytes()); |
| } |
| |
| private static InputStream getInputStream(byte[] src) { |
| return new ByteArrayInputStream(src); |
| } |
| |
| private static void BlankLines() throws Exception { |
| // write a single space to the output stream |
| ByteArrayOutputStream baos = new ByteArrayOutputStream(); |
| baos.write(' '); |
| // test empty properties |
| Properties prop1 = new Properties(); |
| |
| // now load the file we just created, into a properties object. |
| // the properties object should have no elements, but due to a |
| // bug, it has an empty key/value. key = "", value = "" |
| Properties prop2 = new Properties(); |
| prop2.load(getInputStream(baos.toByteArray())); |
| check(prop1, prop2); |
| |
| // test reader |
| prop2 = new Properties(); |
| prop2.load(getReader(baos.toByteArray(), "UTF-8")); |
| check(prop1, prop2); |
| |
| report("BlinkLine"); |
| } |
| |
| private static void EscapeSpace() throws Exception { |
| String propsCases = |
| "key1=\\ \\ Value\\u4e001, has leading and trailing spaces\\ \n" + |
| "key2=Value\\u4e002,\\ does not have\\ leading or trailing\\ spaces\n" + |
| "key3=Value\\u4e003,has,no,spaces\n" + |
| "key4=Value\\u4e004, does not have leading spaces\\ \n" + |
| "key5=\\t\\ \\ Value\\u4e005, has leading tab and no trailing spaces\n" + |
| "key6=\\ \\ Value\\u4e006,doesnothaveembeddedspaces\\ \\ \n" + |
| "\\ key1\\ test\\ =key1, has leading and trailing spaces \n" + |
| "key2\\ test=key2, does not have leading or trailing spaces\n" + |
| "key3test=key3,has,no,spaces\n" + |
| "key4\\ test\\ =key4, does not have leading spaces \n" + |
| "\\t\\ key5\\ test=key5, has leading tab and no trailing spaces\n" + |
| "\\ \\ key6\\ \\ =\\ key6,doesnothaveembeddedspaces "; |
| |
| // Put the same properties, but without the escape char for space in |
| // value part. |
| Properties props = new Properties(); |
| props.put("key1", " Value\u4e001, has leading and trailing spaces "); |
| props.put("key2", "Value\u4e002, does not have leading or trailing spaces"); |
| props.put("key3", "Value\u4e003,has,no,spaces"); |
| props.put("key4", "Value\u4e004, does not have leading spaces "); |
| props.put("key5", "\t Value\u4e005, has leading tab and no trailing spaces"); |
| props.put("key6", " Value\u4e006,doesnothaveembeddedspaces "); |
| props.put(" key1 test ", "key1, has leading and trailing spaces "); |
| props.put("key2 test", "key2, does not have leading or trailing spaces"); |
| props.put("key3test", "key3,has,no,spaces"); |
| props.put("key4 test ", "key4, does not have leading spaces "); |
| props.put("\t key5 test", "key5, has leading tab and no trailing spaces"); |
| props.put(" key6 ", " key6,doesnothaveembeddedspaces "); |
| |
| // Load properties with escape character '\' before space characters |
| Properties props1 = new Properties(); |
| props1.load(getInputStream(propsCases)); |
| check(props1, props); |
| |
| // Test Reader |
| props1 = new Properties(); |
| props1.load(getReader(propsCases, "UTF-8")); |
| check(props1, props); |
| |
| // Also store the new properties to a storage |
| ByteArrayOutputStream baos = new ByteArrayOutputStream(); |
| props.store(baos, "EscapeSpace Test"); |
| |
| props1 = new Properties(); |
| props1.load(getInputStream(baos.toByteArray())); |
| check(props1, props); |
| |
| // Reader should work as well |
| props1 = new Properties(); |
| props1.load(getReader(baos.toByteArray(), "UTF-8")); |
| check(props1, props); |
| |
| // Try Writer |
| baos = new ByteArrayOutputStream(); |
| props.store(new OutputStreamWriter(baos, "UTF-8"), |
| "EscapeSpace Test"); |
| |
| props1 = new Properties(); |
| props1.load(getReader(baos.toByteArray(), "UTF-8")); |
| check(props1, props); |
| |
| report("EscapeSpace"); |
| } |
| |
| private static void LoadParsing() throws Exception { |
| File f = new File(System.getProperty("test.src", "."), "input.txt"); |
| FileInputStream myIn = new FileInputStream(f); |
| Properties myProps = new Properties(); |
| int size = 0; |
| try { |
| myProps.load(myIn); |
| } finally { |
| myIn.close(); |
| } |
| |
| if (!myProps.getProperty("key1").equals("value1") || // comment |
| !myProps.getProperty("key2").equals("abc\\defg\\") || // slash |
| !myProps.getProperty("key3").equals("value3") || // spaces in key |
| !myProps.getProperty("key4").equals(":value4") || // separator |
| // Does not recognize comments with leading spaces |
| (myProps.getProperty("#") != null) || |
| // Wrong number of keys in Properties |
| ((size=myProps.size()) != 4)) |
| failCount++; |
| report("LoadParsing"); |
| } |
| |
| private static void SaveEncoding() throws Exception { |
| // Create a properties object to save |
| Properties props = new Properties(); |
| props.put("signal", "val\u0019"); |
| props.put("ABC 10", "value0"); |
| props.put("\uff10test", "value\u0020"); |
| props.put("key with spaces", "value with spaces"); |
| props.put("key with space and Chinese_\u4e00", "valueWithChinese_\u4e00"); |
| props.put(" special#=key ", "value3"); |
| |
| // Save the properties and check output |
| ByteArrayOutputStream baos = new ByteArrayOutputStream(); |
| props.store(baos,"A test"); |
| |
| // Read properties file and verify \u0019 |
| BufferedReader in = new BufferedReader( |
| new InputStreamReader( |
| new ByteArrayInputStream( |
| baos.toByteArray()))); |
| String firstLine = "foo"; |
| while (!firstLine.startsWith("signal")) |
| firstLine = in.readLine(); |
| if (firstLine.length() != 16) |
| failCount++; |
| |
| // Load the properties set |
| Properties newProps = new Properties(); |
| newProps.load(getInputStream(baos.toByteArray())); |
| check(newProps, props); |
| |
| // Store(Writer)/Load(Reader) |
| baos = new ByteArrayOutputStream(); |
| props.store(new OutputStreamWriter(baos, "EUC_JP"), "A test"); |
| newProps = new Properties(); |
| newProps.load(getReader(baos.toByteArray(), "EUC_JP")); |
| check(newProps, props); |
| |
| report("SaveEncoding"); |
| } |
| |
| /** |
| * This class tests to see if a properties object |
| * can successfully save and load properties |
| * using character encoding |
| */ |
| private static void SaveLoadBasher() throws Exception { |
| String keyValueSeparators = "=: \t\r\n\f#!\\"; |
| |
| Properties originalProps = new Properties(); |
| Properties loadedProps = new Properties(); |
| |
| // Generate a unicode key and value |
| Random generator = new Random(); |
| int achar=0; |
| StringBuffer aKeyBuffer = new StringBuffer(120); |
| StringBuffer aValueBuffer = new StringBuffer(120); |
| String aKey; |
| String aValue; |
| int maxKeyLen = 100; |
| int maxValueLen = 100; |
| int maxPropsNum = 300; |
| for (int x=0; x<maxPropsNum; x++) { |
| for(int y=0; y<maxKeyLen; y++) { |
| achar = generator.nextInt(); |
| char test; |
| if(achar < 99999) { |
| test = (char)(achar); |
| } |
| else { |
| int zz = achar % 10; |
| test = keyValueSeparators.charAt(zz); |
| } |
| if (Character.isHighSurrogate(test)) { |
| aKeyBuffer.append(test); |
| aKeyBuffer.append('\udc00'); |
| y++; |
| } else if (Character.isLowSurrogate(test)) { |
| aKeyBuffer.append('\ud800'); |
| aKeyBuffer.append(test); |
| y++; |
| } else |
| aKeyBuffer.append(test); |
| } |
| aKey = aKeyBuffer.toString(); |
| for(int y=0; y<maxValueLen; y++) { |
| achar = generator.nextInt(); |
| char test = (char)(achar); |
| if (Character.isHighSurrogate(test)) { |
| aKeyBuffer.append(test); |
| aKeyBuffer.append('\udc00'); |
| y++; |
| } else if (Character.isLowSurrogate(test)) { |
| aKeyBuffer.append('\ud800'); |
| aKeyBuffer.append(test); |
| y++; |
| } else { |
| aValueBuffer.append(test); |
| } |
| } |
| aValue = aValueBuffer.toString(); |
| |
| // Attempt to add to original |
| try { |
| originalProps.put(aKey, aValue); |
| } |
| catch (IllegalArgumentException e) { |
| System.err.println("disallowing..."); |
| } |
| aKeyBuffer.setLength(0); |
| aValueBuffer.setLength(0); |
| } |
| |
| // Store(OutputStream)/Load(InputStream) |
| ByteArrayOutputStream baos = new ByteArrayOutputStream(); |
| originalProps.store(baos, "test properties"); |
| loadedProps.load(getInputStream(baos.toByteArray())); |
| check(loadedProps, originalProps); |
| |
| // Store(Writer)/Load(Reader) |
| baos = new ByteArrayOutputStream(); |
| originalProps.store(new OutputStreamWriter(baos, "UTF-8"), |
| "test properties"); |
| loadedProps.load(getReader(baos.toByteArray(), "UTF-8")); |
| check(loadedProps, originalProps); |
| |
| report("SaveLoadBasher"); |
| } |
| |
| |
| /* Note: this regression test only detects incorrect line |
| * separator on platform running the test |
| */ |
| private static void SaveSeparator() throws Exception { |
| ByteArrayOutputStream baos = new ByteArrayOutputStream(); |
| Properties props = new Properties(); |
| props.store(baos, "A test"); |
| |
| // Examine the result to verify that line.separator was used |
| String theSeparator = System.getProperty("line.separator"); |
| String content = baos.toString(); |
| if (!content.endsWith(theSeparator)) |
| failCount++; |
| |
| // store(Writer) |
| baos = new ByteArrayOutputStream(); |
| props.store(new OutputStreamWriter(baos, "UTF-8"), "A test"); |
| content = baos.toString(); |
| if (!content.endsWith(theSeparator)) |
| failCount++; |
| |
| report("SaveSeparator"); |
| } |
| |
| // Ensure that the save method doesn't close its output stream |
| private static void SaveClose() throws Exception { |
| Properties p = new Properties(); |
| p.put("Foo", "Bar"); |
| class MyOS extends ByteArrayOutputStream { |
| boolean closed = false; |
| public void close() throws IOException { |
| this.closed = true; |
| } |
| } |
| MyOS myos = new MyOS(); |
| p.store(myos, "Test"); |
| if (myos.closed) |
| failCount++; |
| |
| p.store(new OutputStreamWriter(myos, "UTF-8"), "Test"); |
| if (myos.closed) |
| failCount++; |
| |
| report ("SaveClose"); |
| } |
| |
| private static void UnicodeEscape() throws Exception { |
| ByteArrayOutputStream baos = new ByteArrayOutputStream(); |
| OutputStreamWriter osw = new OutputStreamWriter(baos); |
| osw.write("a=b\nb=\\u0\n"); |
| osw.close(); |
| Properties props = new Properties(); |
| boolean failed = true; |
| try { |
| props.load(getInputStream(baos.toByteArray())); |
| } catch (IllegalArgumentException iae) { |
| failed = false; |
| } |
| if (failed) |
| failCount++; |
| |
| failed = true; |
| props = new Properties(); |
| try { |
| props.load(getReader(baos.toByteArray(), "UTF-8")); |
| } catch (IllegalArgumentException iae) { |
| failed = false; |
| } |
| if (failed) |
| failCount++; |
| report("UnicodeEscape"); |
| } |
| |
| private static void SaveComments() throws Exception { |
| String ls = System.getProperty("line.separator"); |
| String[] input = new String[] { |
| "Comments with \u4e2d\u6587\u6c49\u5b57 included", |
| "Comments with \n Second comments line", |
| "Comments with \n# Second comments line", |
| "Comments with \n! Second comments line", |
| "Comments with last character is \n", |
| "Comments with last character is \r\n", |
| "Comments with last two characters are \n\n", |
| "Comments with last four characters are \r\n\r\n", |
| "Comments with \nkey4=value4", |
| "Comments with \n#key4=value4"}; |
| |
| String[] output = new String[] { |
| "#Comments with \\u4E2D\\u6587\\u6C49\\u5B57 included" + ls, |
| "#Comments with " + ls + "# Second comments line" + ls, |
| "#Comments with " + ls + "# Second comments line" + ls, |
| "#Comments with " + ls + "! Second comments line" + ls, |
| "#Comments with last character is " + ls+"#"+ls, |
| "#Comments with last character is " + ls+"#"+ls, |
| "#Comments with last two characters are " + ls+"#"+ls+"#"+ls, |
| "#Comments with last four characters are " + ls+"#"+ls+"#"+ls}; |
| |
| Properties props = new Properties(); |
| ByteArrayOutputStream baos; |
| int i = 0; |
| for (i = 0; i < output.length; i++) { |
| baos = new ByteArrayOutputStream(); |
| props.store(baos, input[i]); |
| String result = baos.toString("iso8859-1"); |
| if (result.indexOf(output[i]) == -1) { |
| failCount++; |
| } |
| } |
| props.put("key1", "value1"); |
| props.put("key2", "value2"); |
| props.put("key3", "value3"); |
| for (; i < input.length; i++) { |
| baos = new ByteArrayOutputStream(); |
| props.store(baos, input[i]); |
| Properties propsNew = new Properties(); |
| propsNew.load(getInputStream(baos.toByteArray())); |
| check(propsNew, props); |
| |
| baos = new ByteArrayOutputStream(); |
| props.store(new OutputStreamWriter(baos, "UTF-8"), |
| input[i]); |
| propsNew = new Properties(); |
| propsNew.load(getReader(baos.toByteArray(), "UTF-8")); |
| check(propsNew, props); |
| } |
| report("SaveComments"); |
| } |
| } |