Return-Path: Delivered-To: apmail-incubator-open-jpa-commits-archive@locus.apache.org Received: (qmail 69525 invoked from network); 1 Aug 2006 05:03:30 -0000 Received: from hermes.apache.org (HELO mail.apache.org) (209.237.227.199) by minotaur.apache.org with SMTP; 1 Aug 2006 05:03:30 -0000 Received: (qmail 37795 invoked by uid 500); 1 Aug 2006 05:03:30 -0000 Delivered-To: apmail-incubator-open-jpa-commits-archive@incubator.apache.org Received: (qmail 37773 invoked by uid 500); 1 Aug 2006 05:03:30 -0000 Mailing-List: contact open-jpa-commits-help@incubator.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: open-jpa-dev@incubator.apache.org Delivered-To: mailing list open-jpa-commits@incubator.apache.org Received: (qmail 37764 invoked by uid 99); 1 Aug 2006 05:03:30 -0000 Received: from asf.osuosl.org (HELO asf.osuosl.org) (140.211.166.49) by apache.org (qpsmtpd/0.29) with ESMTP; Mon, 31 Jul 2006 22:03:30 -0700 X-ASF-Spam-Status: No, hits=-9.4 required=10.0 tests=ALL_TRUSTED,NO_REAL_NAME X-Spam-Check-By: apache.org Received-SPF: pass (asf.osuosl.org: local policy) Received: from [140.211.166.113] (HELO eris.apache.org) (140.211.166.113) by apache.org (qpsmtpd/0.29) with ESMTP; Mon, 31 Jul 2006 22:03:29 -0700 Received: by eris.apache.org (Postfix, from userid 65534) id 08BEA1A981A; Mon, 31 Jul 2006 22:03:09 -0700 (PDT) Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: svn commit: r427444 - /incubator/openjpa/trunk/openjpa-lib/src/test/java/org/apache/openjpa/lib/util/TestPropertiesParser.java Date: Tue, 01 Aug 2006 05:03:08 -0000 To: open-jpa-commits@incubator.apache.org From: pcl@apache.org X-Mailer: svnmailer-1.0.8 Message-Id: <20060801050309.08BEA1A981A@eris.apache.org> X-Virus-Checked: Checked by ClamAV on apache.org X-Spam-Rating: minotaur.apache.org 1.6.2 0/1000/N Author: pcl Date: Mon Jul 31 22:03:08 2006 New Revision: 427444 URL: http://svn.apache.org/viewvc?rev=427444&view=rev Log: Brett Porter's patch to resolve OPENJPA-3 Modified: incubator/openjpa/trunk/openjpa-lib/src/test/java/org/apache/openjpa/lib/util/TestPropertiesParser.java Modified: incubator/openjpa/trunk/openjpa-lib/src/test/java/org/apache/openjpa/lib/util/TestPropertiesParser.java URL: http://svn.apache.org/viewvc/incubator/openjpa/trunk/openjpa-lib/src/test/java/org/apache/openjpa/lib/util/TestPropertiesParser.java?rev=427444&r1=427443&r2=427444&view=diff ============================================================================== --- incubator/openjpa/trunk/openjpa-lib/src/test/java/org/apache/openjpa/lib/util/TestPropertiesParser.java (original) +++ incubator/openjpa/trunk/openjpa-lib/src/test/java/org/apache/openjpa/lib/util/TestPropertiesParser.java Mon Jul 31 22:03:08 2006 @@ -1,378 +1,394 @@ -/* - * Copyright 2006 The Apache Software Foundation. - * 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.apache.openjpa.lib.util; - -import java.io.BufferedInputStream; -import java.io.BufferedReader; -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.InputStreamReader; -import java.io.ObjectInputStream; -import java.io.ObjectOutputStream; -import java.io.StringBufferInputStream; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; -import java.util.Properties; - -import junit.framework.TestCase; -import org.apache.openjpa.lib.util.FormatPreservingProperties.DuplicateKeyException; - -// things to test: -// - delimiters in keys -// - escape chars, including \:, \= in files(as generated by Properties) -// - unicode -// - non-String keys / vals -// - list() method behavior - -public class TestPropertiesParser extends TestCase { - - public void testSimpleProperties() throws IOException { - StringBuffer buf = new StringBuffer(); - buf.append("key: value\n"); - buf.append("key2: value2"); // no EOL -- this is intentional - Properties p = toProperties(buf.toString()); - assertProperties(new String[][]{ - { "key", "value" }, { "key2", "value2" } }, p); - } - - public void testComments() throws IOException { - StringBuffer buf = new StringBuffer(); - buf.append("# this is a comment\n"); - buf.append(" # another one, with leading whitespace \n"); - buf.append(" # and more with interesting whitespace \n"); - buf.append("! and with a ! delimiter\n"); - buf.append("! and with escape \t chars\n"); - buf.append("#and a comment with no whitespace\n"); - Properties p = toProperties(buf.toString()); - assertEquals(0, p.size()); - } - - public void testMixedContent() throws IOException { - StringBuffer buf = new StringBuffer(); - buf.append("# this is a comment\n"); - buf.append(" # another one, with leading whitespace \n"); - buf.append("foo: bar#baz\n"); - buf.append("! and with a ! delimiter\n"); - buf.append("! and with escape \t chars\n"); - Properties p = toProperties(buf.toString()); - assertProperties(new String[][]{ { "foo", "bar#baz" } }, p); - } - - public void testMultiLineInput() throws IOException { - String s = "foo: bar\\\n" + "more line goes here"; - Properties p = toProperties(s); - assertProperties( - new String[][]{ { "foo", "barmore line goes here" } }, p); - } - - public void testEmptyLines() throws IOException { - Properties p = toProperties("\nfoo: bar\n\nbaz: val"); - assertProperties(new String[][]{ { "foo", "bar" }, { "baz", "val" } }, - p); - } - - public void testAddProperties() throws IOException { - // intentionally left out the trailing end line - String s = "foo: bar\nbaz: val"; - Properties p = toProperties(s); - assertProperties(new String[][]{ { "foo", "bar" }, { "baz", "val" } }, - p); - - p.put("new-key", "val1"); - p.put("new-key-2", "val2"); - p.put("another-new-key", "val3"); - assertRoundTrip(s + "\nnew-key: val1\nnew-key-2: val2\n" + - "another-new-key: val3\n", p); - } - - public void testAddAndMutateProperties() throws IOException { - // intentionally left out the trailing end line - Properties p = toProperties("foo: bar\nbaz: val"); - assertProperties(new String[][]{ { "foo", "bar" }, { "baz", "val" } }, - p); - - p.put("new-key", "new value"); - p.put("foo", "barbar"); - assertRoundTrip("foo: barbar\nbaz: val\nnew-key: new value\n", p); - } - - public void testEscapedEquals() throws IOException { - Properties p = toProperties("foo=bar\\=WARN,baz\\=TRACE"); - assertProperties(new String[][]{ { "foo", "bar=WARN,baz=TRACE" } }, p); - } - - public void testLineTypes() throws IOException { - StringBuffer buf = new StringBuffer(); - buf.append(" !comment\n \t \nname = no\n " - + "#morec\tomm\\\nents\n\n dog=no\\cat \nburps " - + ":\ntest=\ndate today\n\n\nlong\\\n value=tryin \\\n " - + "gto\n4:vier\nvier :4"); - Properties p = toProperties(buf.toString()); - assertProperties(new String[][]{ - { "name", "no" }, { "ents", "" }, { "dog", "nocat " }, - { "burps", "" }, { "test", "" }, { "date", "today" }, - { "longvalue", "tryin gto" }, { "4", "vier" }, { "vier", "4" }, - }, p); - } - - public void testSpecialChars() throws Throwable { - testSpecialChars(false, true); - testSpecialChars(true, true); - testSpecialChars(false, false); - testSpecialChars(true, false); - } - - /** - * Test that special characters work. - * - * @param formattingProps if true, test against the - * FormatPreservingProperties, otherwise test - * against a normal Properties instance(for validation of the test case). - * @param value whether to test the key or the value - */ - public void testSpecialChars(boolean formattingProps, boolean value) - throws Throwable { - List valueList = new ArrayList(Arrays.asList(new String[]{ - "xxyy", "xx\\yy", "xx\nyy", "xx\\nyy", "xx\tyy", "xx\\tyy", - "xx\ryy", "xx\\ryy", "xx\fyy", "xx\\fyy", "xx\r\n\\\t\r\t\nyy", - "xx\\r\n\\\t\\r\t\\nyy", - "xx\r\n\\\\\\\\\\\\\\\\\\\\\\\\\\\t\r\t\nyy", - "C:\\Program Files\\Some Application\\OpenJPA\\My File.dat", })); - - // also store every individual character - for (char c = 'a'; c < 'Z'; c++) { - valueList.add(new String(new char[]{ c })); - valueList.add(new String(new char[]{ c, '\\', c })); - valueList.add(new String(new char[]{ '\\', c })); - } - - String[] values = (String[]) valueList.toArray(new String[0]); - - final String dummy = "XXX"; - - for (int i = 0; i < values.length; i++) { - // test special characters in either keys or values - String val = value ? values[i] : dummy; - String key = value ? dummy : values[i]; - - Properties p = formattingProps ? - new FormatPreservingProperties() : new Properties(); - if (p instanceof FormatPreservingProperties) { - // set these properties so we behave the same way as - // java.util.Properties - ((FormatPreservingProperties) p).setDefaultEntryDelimiter('='); - ((FormatPreservingProperties) p). - setAddWhitespaceAfterDelimiter(false); - } - - p.setProperty(key, val); - ByteArrayOutputStream out = new ByteArrayOutputStream(); - p.store(out, null); - - Properties copy = new Properties(); - copy.setProperty(key, val); - ByteArrayOutputStream copyOut = new ByteArrayOutputStream(); - copy.store(copyOut, null); - - p = formattingProps ? - new FormatPreservingProperties() : new Properties(); - - InputStream in = new BufferedInputStream - (new ByteArrayInputStream(out.toByteArray())); - - try { - // make sure that the 2 properties serialized are the same - String copyOutString = stripComments(copyOut.toByteArray()); - String outString = stripComments(out.toByteArray()); - assertEquals(copyOutString, outString); - - p.load(in); - - assertNotNull("Property \"" + key + "\" was null", - p.getProperty(key)); - assertEquals(val.trim(), p.getProperty(key).trim()); - } catch (Throwable ioe) { - if (!formattingProps) - throw ioe; - - // bug(1211, ioe, - // "Cannot store backslash in FormatPreservingProperties"); - throw ioe; - } - } - } - - static Character randomChar() { - char [] TEST_CHAR_ARRAY = new char []{ - 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', - 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', - 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '1', - '2', '3', '4', '5', '6', '7', '8', '9' }; - - return new Character(TEST_CHAR_ARRAY[ - (int) (Math.random() * TEST_CHAR_ARRAY.length)]); - } - - static String randomString(int len) { - StringBuffer buf = new StringBuffer(); - for (int i = 0; i < (int) (Math.random() * len) + 1; i++) - buf.append(randomChar()); - return buf.toString(); - } - - public void testEquivalentStore() throws IOException { - Properties p1 = new Properties(); - FormatPreservingProperties p2 = new FormatPreservingProperties(); - - ((FormatPreservingProperties) p2).setDefaultEntryDelimiter('='); - ((FormatPreservingProperties) p2).setAddWhitespaceAfterDelimiter(false); - - String[] values = new String[]{ - "x", "x\ny", "x\\ny", "x\ty", "x\\ty", "x\fy", "x\\fy", "x\ry", - "x\\ry", "C:\\Foo Bar\\Baz", randomString(5).replace('a', '\\'), - randomString(500).replace('a', '\\'), - randomString(5000).replace('a', '\\'), }; - - for (int i = 0; i < values.length; i++) { - p1.clear(); - p2.clear(); - - p1.setProperty("xxx", values[i]); - p2.setProperty("xxx", values[i]); - - ByteArrayOutputStream out1 = new ByteArrayOutputStream(); - ByteArrayOutputStream out2 = new ByteArrayOutputStream(); - - p1.store(out1, null); - p2.store(out2, null); - - String s1 = new String(out1.toByteArray()); - String s2 = new String(out2.toByteArray()); - - assertTrue("Expected <" + s1 + "> but was <" + s2 + ">", - s1.indexOf(s2) != -1); - } - } - - static String stripComments(byte[] bytes) throws IOException { - BufferedReader reader = new BufferedReader(new InputStreamReader - (new ByteArrayInputStream(bytes))); - StringBuffer sbuf = new StringBuffer(); - String line; - while ((line = reader.readLine()) != null) { - // skip comments - if (line.trim().startsWith("#")) - continue; - - sbuf.append(line); - sbuf.append('\n'); - } - - return sbuf.toString(); - } - - public void testDuplicateProperties() throws IOException { - FormatPreservingProperties p = new FormatPreservingProperties(); - try { - toProperties("foo=bar\nfoo=baz", p); - fail("expected duplicate keys to cause exception"); - } catch (DuplicateKeyException e) { - // expected - } - - // now test the expected behavior when duplicates are allowed. - p = new FormatPreservingProperties(); - p.setAllowDuplicates(true); - toProperties("foo=bar\nfoo=baz", p); - assertProperties(new String[][]{ { "foo", "baz" } }, p); - } - - public void testMultipleLoads() throws IOException { - String props = "foo=bar\nbaz=quux"; - String props2 = "a=b\nc=d"; - Properties vanilla = new Properties(); - vanilla.load(new BufferedInputStream - (new StringBufferInputStream(props))); - vanilla.load(new BufferedInputStream - (new StringBufferInputStream(props2))); - - Properties p = new FormatPreservingProperties(); - p.load(new BufferedInputStream(new StringBufferInputStream(props))); - p.load(new BufferedInputStream(new StringBufferInputStream(props2))); - assertPropertiesSame(vanilla, p); - } - - protected FormatPreservingProperties toProperties(String s) - throws IOException { - return toProperties(s, new FormatPreservingProperties()); - } - - protected FormatPreservingProperties toProperties(String s, - FormatPreservingProperties p) throws IOException { - Properties vanilla = new Properties(); - vanilla.load(new StringBufferInputStream(s)); - - p.load(new StringBufferInputStream(s)); - assertRoundTrip(s, p); - - assertPropertiesSame(vanilla, p); - - return p; - } - - private void assertRoundTrip(String s, Properties p) throws IOException { - ByteArrayOutputStream out = new ByteArrayOutputStream(); - p.store(out, null); - assertEquals(s, out.toString()); - - // also check serializable - ByteArrayOutputStream bout = new ByteArrayOutputStream(); - new ObjectOutputStream(bout).writeObject(p); - - try { - FormatPreservingProperties deserialized = - (FormatPreservingProperties) new ObjectInputStream - (new ByteArrayInputStream(bout.toByteArray())). - readObject(); - assertEquals(p, deserialized); - - out = new ByteArrayOutputStream(); - deserialized.store(out, null); - assertEquals(s, out.toString()); - } catch (ClassNotFoundException cnfe) { - fail(cnfe + ""); - } - } - - public static void assertEquals(String expected, String actual) { - if (expected == actual) - return; - - if (expected == null || !expected.equals(actual)) - fail("Expected <" + expected + "> but was <" + actual + ">"); - } - - private void assertPropertiesSame(Properties vanilla, Properties p) { - assertEquals(vanilla, p); - } - - protected void assertProperties(String[][] strings, Properties p) { - for (int i = 0; i < strings.length; i++) - assertEquals(strings[i][1], p.get(strings[i][0])); - - assertEquals(strings.length, p.size()); - } -} +/* + * Copyright 2006 The Apache Software Foundation. + * 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.apache.openjpa.lib.util; + +import java.io.BufferedInputStream; +import java.io.BufferedReader; +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.io.StringBufferInputStream; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.Properties; + +import junit.framework.TestCase; +import org.apache.openjpa.lib.util.FormatPreservingProperties.DuplicateKeyException; + +// things to test: +// - delimiters in keys +// - escape chars, including \:, \= in files(as generated by Properties) +// - unicode +// - non-String keys / vals +// - list() method behavior + +public class TestPropertiesParser extends TestCase { + + private static final String LS = System.getProperty( "line.separator" ); + + public void testSimpleProperties() throws IOException { + StringBuffer buf = new StringBuffer(); + buf.append("key: value" + LS); + buf.append("key2: value2"); // no EOL -- this is intentional + Properties p = toProperties(buf.toString()); + assertProperties(new String[][]{ + { "key", "value" }, { "key2", "value2" } }, p); + } + + public void testComments() throws IOException { + StringBuffer buf = new StringBuffer(); + buf.append("# this is a comment" + LS); + buf.append(" # another one, with leading whitespace " + LS); + buf.append(" # and more with interesting whitespace " + LS); + buf.append("! and with a ! delimiter" + LS); + buf.append("! and with escape \t chars" + LS); + buf.append("#and a comment with no whitespace" + LS); + Properties p = toProperties(buf.toString()); + assertEquals(0, p.size()); + } + + public void testMixedContent() throws IOException { + StringBuffer buf = new StringBuffer(); + buf.append("# this is a comment" + LS); + buf.append(" # another one, with leading whitespace " + LS); + buf.append("foo: bar#baz" + LS); + buf.append("! and with a ! delimiter" + LS); + buf.append("! and with escape \t chars" + LS); + Properties p = toProperties(buf.toString()); + assertProperties(new String[][]{ { "foo", "bar#baz" } }, p); + } + + public void testMultiLineInput() throws IOException { + String s = "foo: bar\\" + LS + "more line goes here"; + Properties p = toProperties(s); + assertProperties( + new String[][]{ { "foo", "barmore line goes here" } }, p); + } + + public void testEmptyLines() throws IOException { + Properties p = toProperties(LS + "foo: bar" + LS + LS + "baz: val"); + assertProperties(new String[][]{ { "foo", "bar" }, { "baz", "val" } }, + p); + } + + public void testAddProperties() throws IOException { + // intentionally left out the trailing end line + String s = "foo: bar" + LS + "baz: val"; + Properties p = toProperties(s); + assertProperties(new String[][]{ { "foo", "bar" }, { "baz", "val" } }, + p); + + p.put("new-key", "val1"); + p.put("new-key-2", "val2"); + p.put("another-new-key", "val3"); + assertRoundTrip(s + LS + "new-key: val1" + LS + "new-key-2: val2" + LS + + "another-new-key: val3" + LS, p); + } + + public void testAddAndMutateProperties() throws IOException { + // intentionally left out the trailing end line + Properties p = toProperties("foo: bar" + LS + "baz: val"); + assertProperties(new String[][]{ { "foo", "bar" }, { "baz", "val" } }, + p); + + p.put("new-key", "new value"); + p.put("foo", "barbar"); + assertRoundTrip("foo: barbar" + LS + "baz: val" + LS + + "new-key: new value" + LS, p); + } + + public void testEscapedEquals() throws IOException { + Properties p = toProperties("foo=bar\\=WARN,baz\\=TRACE"); + assertProperties(new String[][]{ { "foo", "bar=WARN,baz=TRACE" } }, p); + } + + public void testLineTypes() throws IOException { + StringBuffer buf = new StringBuffer(); + buf.append(" !comment" + LS + " \t " + LS + "name = no" + LS + " " + + "#morec\tomm\\" + LS + "ents" + LS + LS + " dog=no\\cat " + LS + + "burps :" + LS + "test=" + LS + "date today" + LS + LS + LS + + "long\\" + LS + " value=tryin \\" + LS + " " + + "gto" + LS + "4:vier" + LS + "vier :4"); + Properties p = toProperties(buf.toString()); + assertProperties(new String[][]{ + { "name", "no" }, { "ents", "" }, { "dog", "nocat " }, + { "burps", "" }, { "test", "" }, { "date", "today" }, + { "longvalue", "tryin gto" }, { "4", "vier" }, { "vier", "4" }, + }, p); + } + + public void testSpecialChars() throws Throwable { + testSpecialChars(false, true); + testSpecialChars(true, true); + testSpecialChars(false, false); + testSpecialChars(true, false); + } + + /** + * Test that special characters work. + * + * @param formattingProps if true, test against the + * FormatPreservingProperties, otherwise test + * against a normal Properties instance(for validation of the test case). + * @param value whether to test the key or the value + */ + public void testSpecialChars(boolean formattingProps, boolean value) + throws Throwable { + List valueList = new ArrayList(Arrays.asList(new String[]{ + "xxyy", "xx\\yy", "xx" + LS + "yy", "xx\\nyy", "xx\tyy", "xx\\tyy", + "xx\ryy", "xx\\ryy", "xx\fyy", "xx\\fyy", "xx\r" + LS + "\\\t\r\t" + + LS + "yy", + "xx\\r" + LS + "\\\t\\r\t\\nyy", + "xx\r" + LS + "\\\\\\\\\\\\\\\\\\\\\\\\\\\t\r\t" + LS + "yy", + "C:\\Program Files\\Some Application\\OpenJPA\\My File.dat", })); + + // also store every individual character + for (char c = 'a'; c < 'Z'; c++) { + valueList.add(new String(new char[]{ c })); + valueList.add(new String(new char[]{ c, '\\', c })); + valueList.add(new String(new char[]{ '\\', c })); + } + + String[] values = (String[]) valueList.toArray(new String[0]); + + final String dummy = "XXX"; + + for (int i = 0; i < values.length; i++) { + // test special characters in either keys or values + String val = value ? values[i] : dummy; + String key = value ? dummy : values[i]; + + Properties p = formattingProps ? + new FormatPreservingProperties() : new Properties(); + if (p instanceof FormatPreservingProperties) { + // set these properties so we behave the same way as + // java.util.Properties + ((FormatPreservingProperties) p).setDefaultEntryDelimiter('='); + ((FormatPreservingProperties) p). + setAddWhitespaceAfterDelimiter(false); + } + + p.setProperty(key, val); + ByteArrayOutputStream out = new ByteArrayOutputStream(); + p.store(out, null); + + Properties copy = new Properties(); + copy.setProperty(key, val); + ByteArrayOutputStream copyOut = new ByteArrayOutputStream(); + copy.store(copyOut, null); + + p = formattingProps ? + new FormatPreservingProperties() : new Properties(); + + InputStream in = new BufferedInputStream + (new ByteArrayInputStream(out.toByteArray())); + + try { + // make sure that the 2 properties serialized are the same + String copyOutString = stripComments(copyOut.toByteArray()); + String outString = stripComments(out.toByteArray()); + assertEquals(copyOutString, outString); + + p.load(in); + + assertNotNull("Property \"" + key + "\" was null", + p.getProperty(key)); + assertEquals(val.trim(), p.getProperty(key).trim()); + } catch (Throwable ioe) { + if (!formattingProps) + throw ioe; + + // bug(1211, ioe, + // "Cannot store backslash in FormatPreservingProperties"); + throw ioe; + } + } + } + + static Character randomChar() { + char [] TEST_CHAR_ARRAY = new char []{ + 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', + 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', + 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '1', + '2', '3', '4', '5', '6', '7', '8', '9' }; + + return new Character(TEST_CHAR_ARRAY[ + (int) (Math.random() * TEST_CHAR_ARRAY.length)]); + } + + static String randomString(int len) { + StringBuffer buf = new StringBuffer(); + for (int i = 0; i < (int) (Math.random() * len) + 1; i++) + buf.append(randomChar()); + return buf.toString(); + } + + public void testEquivalentStore() throws IOException { + Properties p1 = new Properties(); + FormatPreservingProperties p2 = new FormatPreservingProperties(); + + ((FormatPreservingProperties) p2).setDefaultEntryDelimiter('='); + ((FormatPreservingProperties) p2).setAddWhitespaceAfterDelimiter(false); + + String[] values = + new String[] { + "x", + "x" + LS + "y", + "x\\ny", + "x\ty", + "x\\ty", + "x\fy", + "x\\fy", + "x\ry", + "x\\ry", + "C:\\Foo Bar\\Baz", + randomString(5).replace('a', '\\'), + randomString(500).replace('a', '\\'), + randomString(5000).replace('a', '\\'), + }; + + for (int i = 0; i < values.length; i++) { + p1.clear(); + p2.clear(); + + p1.setProperty("xxx", values[i]); + p2.setProperty("xxx", values[i]); + + ByteArrayOutputStream out1 = new ByteArrayOutputStream(); + ByteArrayOutputStream out2 = new ByteArrayOutputStream(); + + p1.store(out1, null); + p2.store(out2, null); + + String s1 = new String(out1.toByteArray()); + String s2 = new String(out2.toByteArray()); + + assertTrue("Expected <" + s1 + "> but was <" + s2 + ">", + s1.indexOf(s2) != -1); + } + } + + static String stripComments(byte[] bytes) throws IOException { + BufferedReader reader = new BufferedReader(new InputStreamReader + (new ByteArrayInputStream(bytes))); + StringBuffer sbuf = new StringBuffer(); + String line; + while ((line = reader.readLine()) != null) { + // skip comments + if (line.trim().startsWith("#")) + continue; + + sbuf.append(line); + sbuf.append(LS); + } + + return sbuf.toString(); + } + + public void testDuplicateProperties() throws IOException { + FormatPreservingProperties p = new FormatPreservingProperties(); + try { + toProperties("foo=bar" + LS + "foo=baz", p); + fail("expected duplicate keys to cause exception"); + } catch (DuplicateKeyException e) { + // expected + } + + // now test the expected behavior when duplicates are allowed. + p = new FormatPreservingProperties(); + p.setAllowDuplicates(true); + toProperties("foo=bar" + LS + "foo=baz", p); + assertProperties(new String[][]{ { "foo", "baz" } }, p); + } + + public void testMultipleLoads() throws IOException { + String props = "foo=bar" + LS + "baz=quux"; + String props2 = "a=b" + LS + "c=d"; + Properties vanilla = new Properties(); + vanilla.load(new BufferedInputStream + (new StringBufferInputStream(props))); + vanilla.load(new BufferedInputStream + (new StringBufferInputStream(props2))); + + Properties p = new FormatPreservingProperties(); + p.load(new BufferedInputStream(new StringBufferInputStream(props))); + p.load(new BufferedInputStream(new StringBufferInputStream(props2))); + assertPropertiesSame(vanilla, p); + } + + protected FormatPreservingProperties toProperties(String s) + throws IOException { + return toProperties(s, new FormatPreservingProperties()); + } + + protected FormatPreservingProperties toProperties(String s, + FormatPreservingProperties p) throws IOException { + Properties vanilla = new Properties(); + vanilla.load(new StringBufferInputStream(s)); + + p.load(new StringBufferInputStream(s)); + assertRoundTrip(s, p); + + assertPropertiesSame(vanilla, p); + + return p; + } + + private void assertRoundTrip(String s, Properties p) throws IOException { + ByteArrayOutputStream out = new ByteArrayOutputStream(); + p.store(out, null); + assertEquals(s, out.toString()); + + // also check serializable + ByteArrayOutputStream bout = new ByteArrayOutputStream(); + new ObjectOutputStream(bout).writeObject(p); + + try { + FormatPreservingProperties deserialized = + (FormatPreservingProperties) new ObjectInputStream + (new ByteArrayInputStream(bout.toByteArray())). + readObject(); + assertEquals(p, deserialized); + + out = new ByteArrayOutputStream(); + deserialized.store(out, null); + assertEquals(s, out.toString()); + } catch (ClassNotFoundException cnfe) { + fail(cnfe + ""); + } + } + + public static void assertEquals(String expected, String actual) { + if (expected == actual) + return; + + if (expected == null || !expected.equals(actual)) + fail("Expected <" + expected + "> but was <" + actual + ">"); + } + + private void assertPropertiesSame(Properties vanilla, Properties p) { + assertEquals(vanilla, p); + } + + protected void assertProperties(String[][] strings, Properties p) { + for (int i = 0; i < strings.length; i++) + assertEquals(strings[i][1], p.get(strings[i][0])); + + assertEquals(strings.length, p.size()); + } +}