27d8c3f7b4
Reviewed-by: smarks, rriggs, dfuchs
509 lines
19 KiB
Java
509 lines
19 KiB
Java
/*
|
|
* Copyright (c) 2018, 2019, 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 8224202
|
|
* @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 {
|
|
checkMalformedUnicodeEscape("b=\\u012\n");
|
|
checkMalformedUnicodeEscape("b=\\u01\n");
|
|
checkMalformedUnicodeEscape("b=\\u0\n");
|
|
checkMalformedUnicodeEscape("b=\\u\n");
|
|
checkMalformedUnicodeEscape("a=\\u0123\nb=\\u012\n");
|
|
checkMalformedUnicodeEscape("a=\\u0123\nb=\\u01\n");
|
|
checkMalformedUnicodeEscape("a=\\u0123\nb=\\u0\n");
|
|
checkMalformedUnicodeEscape("a=\\u0123\nb=\\u\n");
|
|
checkMalformedUnicodeEscape("b=\\u012xyz\n");
|
|
checkMalformedUnicodeEscape("b=x\\u012yz\n");
|
|
checkMalformedUnicodeEscape("b=xyz\\u012\n");
|
|
}
|
|
|
|
private static void checkMalformedUnicodeEscape(String propString) throws Exception {
|
|
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
|
OutputStreamWriter osw = new OutputStreamWriter(baos);
|
|
osw.write(propString);
|
|
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");
|
|
}
|
|
}
|