test/jdk/java/util/Properties/PropertiesTest.java
changeset 48664 ed014587f0e2
child 55221 27d3b8e5c58b
equal deleted inserted replaced
48663:b742e0f9ce80 48664:ed014587f0e2
       
     1 /*
       
     2  * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
       
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
       
     4  *
       
     5  * This code is free software; you can redistribute it and/or modify it
       
     6  * under the terms of the GNU General Public License version 2 only, as
       
     7  * published by the Free Software Foundation.
       
     8  *
       
     9  * This code is distributed in the hope that it will be useful, but WITHOUT
       
    10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
       
    11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
       
    12  * version 2 for more details (a copy is included in the LICENSE file that
       
    13  * accompanied this code).
       
    14  *
       
    15  * You should have received a copy of the GNU General Public License version
       
    16  * 2 along with this work; if not, write to the Free Software Foundation,
       
    17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
       
    18  *
       
    19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
       
    20  * or visit www.oracle.com if you need additional information or have any
       
    21  * questions.
       
    22  */
       
    23 
       
    24 /*
       
    25  * @test
       
    26  * @summary tests the load and store methods of Properties class
       
    27  * @author Xueming Shen
       
    28  * @bug 4094886
       
    29  * @modules jdk.charsets
       
    30  * @key randomness
       
    31  */
       
    32 
       
    33 import java.io.BufferedReader;
       
    34 import java.io.ByteArrayInputStream;
       
    35 import java.io.ByteArrayOutputStream;
       
    36 import java.io.File;
       
    37 import java.io.FileInputStream;
       
    38 import java.io.FileOutputStream;
       
    39 import java.io.IOException;
       
    40 import java.io.InputStream;
       
    41 import java.io.InputStreamReader;
       
    42 import java.io.OutputStream;
       
    43 import java.io.OutputStreamWriter;
       
    44 import java.io.Reader;
       
    45 import java.io.Writer;
       
    46 import java.util.Properties;
       
    47 import java.util.Random;
       
    48 
       
    49 public class PropertiesTest {
       
    50 
       
    51     private static boolean failure = false;
       
    52     private static int failCount = 0;
       
    53 
       
    54     /**
       
    55      * Main to interpret arguments and run several tests.
       
    56      *
       
    57      */
       
    58     public static void main(String[] args) throws Exception {
       
    59         BlankLines();
       
    60         EscapeSpace();
       
    61         LoadParsing();
       
    62         SaveEncoding();
       
    63         SaveLoadBasher();
       
    64         SaveSeparator();
       
    65         SaveClose();
       
    66         SaveComments();
       
    67         UnicodeEscape();
       
    68 
       
    69         if (failure)
       
    70             throw new RuntimeException("Failure in Properties testing.");
       
    71         else
       
    72             System.err.println("OKAY: All tests passed.");
       
    73     }
       
    74 
       
    75     private static void report(String testName) {
       
    76         int spacesToAdd = 30 - testName.length();
       
    77         StringBuffer paddedNameBuffer = new StringBuffer(testName);
       
    78         for (int i=0; i<spacesToAdd; i++)
       
    79             paddedNameBuffer.append(" ");
       
    80         String paddedName = paddedNameBuffer.toString();
       
    81         System.err.println(paddedName + ": " +
       
    82                            (failCount==0 ? "Passed":"Failed("+failCount+")"));
       
    83         if (failCount > 0)
       
    84             failure = true;
       
    85         failCount = 0;
       
    86     }
       
    87 
       
    88     private static void check(Properties prop1, Properties prop2) {
       
    89         if (!prop1.equals(prop2))
       
    90             failCount++;
       
    91     }
       
    92 
       
    93     private static Reader getReader(String src, String csn)
       
    94         throws Exception {
       
    95         return new InputStreamReader(
       
    96                    new ByteArrayInputStream(src.getBytes()),
       
    97                    csn);
       
    98     }
       
    99 
       
   100     private static OutputStream getFOS(String name)
       
   101         throws Exception
       
   102     {
       
   103         return new FileOutputStream(name);
       
   104     }
       
   105 
       
   106     private static Writer getFOSW(String name, String csn)
       
   107         throws Exception
       
   108     {
       
   109         return new OutputStreamWriter(
       
   110                    new FileOutputStream(name),
       
   111                    csn);
       
   112     }
       
   113 
       
   114     private static Reader getReader(byte[] src, String csn)
       
   115         throws Exception {
       
   116         return new InputStreamReader(new ByteArrayInputStream(src), csn);
       
   117     }
       
   118 
       
   119     private static InputStream getInputStream(String src) {
       
   120         return new ByteArrayInputStream(src.getBytes());
       
   121     }
       
   122 
       
   123     private static InputStream getInputStream(byte[] src) {
       
   124         return new ByteArrayInputStream(src);
       
   125     }
       
   126 
       
   127     private static void BlankLines() throws Exception {
       
   128         // write a single space to the output stream
       
   129         ByteArrayOutputStream baos = new ByteArrayOutputStream();
       
   130         baos.write(' ');
       
   131         // test empty properties
       
   132         Properties prop1 = new Properties();
       
   133 
       
   134         // now load the file we just created, into a properties object.
       
   135         // the properties object should have no elements, but due to a
       
   136         // bug, it has an empty key/value. key = "", value = ""
       
   137         Properties prop2 = new Properties();
       
   138         prop2.load(getInputStream(baos.toByteArray()));
       
   139         check(prop1, prop2);
       
   140 
       
   141         // test reader
       
   142         prop2 = new Properties();
       
   143         prop2.load(getReader(baos.toByteArray(), "UTF-8"));
       
   144         check(prop1, prop2);
       
   145 
       
   146         report("BlinkLine");
       
   147     }
       
   148 
       
   149     private static void EscapeSpace() throws Exception {
       
   150         String propsCases =
       
   151             "key1=\\ \\ Value\\u4e001, has leading and trailing spaces\\  \n" +
       
   152             "key2=Value\\u4e002,\\ does not have\\ leading or trailing\\ spaces\n" +
       
   153             "key3=Value\\u4e003,has,no,spaces\n" +
       
   154             "key4=Value\\u4e004, does not have leading spaces\\  \n" +
       
   155             "key5=\\t\\ \\ Value\\u4e005, has leading tab and no trailing spaces\n" +
       
   156             "key6=\\ \\ Value\\u4e006,doesnothaveembeddedspaces\\ \\ \n" +
       
   157             "\\ key1\\ test\\ =key1, has leading and trailing spaces  \n" +
       
   158             "key2\\ test=key2, does not have leading or trailing spaces\n" +
       
   159             "key3test=key3,has,no,spaces\n" +
       
   160             "key4\\ test\\ =key4, does not have leading spaces  \n" +
       
   161             "\\t\\ key5\\ test=key5, has leading tab and no trailing spaces\n" +
       
   162             "\\ \\ key6\\ \\ =\\  key6,doesnothaveembeddedspaces  ";
       
   163 
       
   164         // Put the same properties, but without the escape char for space in
       
   165         // value part.
       
   166         Properties props = new Properties();
       
   167         props.put("key1", "  Value\u4e001, has leading and trailing spaces  ");
       
   168         props.put("key2", "Value\u4e002, does not have leading or trailing spaces");
       
   169         props.put("key3", "Value\u4e003,has,no,spaces");
       
   170         props.put("key4", "Value\u4e004, does not have leading spaces  ");
       
   171         props.put("key5", "\t  Value\u4e005, has leading tab and no trailing spaces");
       
   172         props.put("key6", "  Value\u4e006,doesnothaveembeddedspaces  ");
       
   173         props.put(" key1 test ", "key1, has leading and trailing spaces  ");
       
   174         props.put("key2 test", "key2, does not have leading or trailing spaces");
       
   175         props.put("key3test", "key3,has,no,spaces");
       
   176         props.put("key4 test ", "key4, does not have leading spaces  ");
       
   177         props.put("\t key5 test", "key5, has leading tab and no trailing spaces");
       
   178         props.put("  key6  ", "  key6,doesnothaveembeddedspaces  ");
       
   179 
       
   180         // Load properties with escape character '\' before space characters
       
   181         Properties props1 = new Properties();
       
   182         props1.load(getInputStream(propsCases));
       
   183         check(props1, props);
       
   184 
       
   185         // Test Reader
       
   186         props1 = new Properties();
       
   187         props1.load(getReader(propsCases, "UTF-8"));
       
   188         check(props1, props);
       
   189 
       
   190         // Also store the new properties to a storage
       
   191         ByteArrayOutputStream baos = new ByteArrayOutputStream();
       
   192         props.store(baos, "EscapeSpace Test");
       
   193 
       
   194         props1 = new Properties();
       
   195         props1.load(getInputStream(baos.toByteArray()));
       
   196         check(props1, props);
       
   197 
       
   198         // Reader should work as well
       
   199         props1 = new Properties();
       
   200         props1.load(getReader(baos.toByteArray(), "UTF-8"));
       
   201         check(props1, props);
       
   202 
       
   203         // Try Writer
       
   204         baos = new ByteArrayOutputStream();
       
   205         props.store(new OutputStreamWriter(baos, "UTF-8"),
       
   206                      "EscapeSpace Test");
       
   207 
       
   208         props1 = new Properties();
       
   209         props1.load(getReader(baos.toByteArray(), "UTF-8"));
       
   210         check(props1, props);
       
   211 
       
   212         report("EscapeSpace");
       
   213     }
       
   214 
       
   215     private static void LoadParsing() throws Exception {
       
   216         File f = new File(System.getProperty("test.src", "."), "input.txt");
       
   217         FileInputStream myIn = new FileInputStream(f);
       
   218         Properties myProps = new Properties();
       
   219         int size = 0;
       
   220         try {
       
   221             myProps.load(myIn);
       
   222         } finally {
       
   223             myIn.close();
       
   224         }
       
   225 
       
   226         if (!myProps.getProperty("key1").equals("value1")      || // comment
       
   227             !myProps.getProperty("key2").equals("abc\\defg\\") || // slash
       
   228             !myProps.getProperty("key3").equals("value3")      || // spaces in key
       
   229             !myProps.getProperty("key4").equals(":value4")     || // separator
       
   230             // Does not recognize comments with leading spaces
       
   231             (myProps.getProperty("#") != null)                 ||
       
   232             // Wrong number of keys in Properties
       
   233             ((size=myProps.size()) != 4))
       
   234             failCount++;
       
   235         report("LoadParsing");
       
   236     }
       
   237 
       
   238     private static void SaveEncoding() throws Exception {
       
   239         // Create a properties object to save
       
   240         Properties props = new Properties();
       
   241         props.put("signal", "val\u0019");
       
   242         props.put("ABC 10", "value0");
       
   243         props.put("\uff10test", "value\u0020");
       
   244         props.put("key with spaces", "value with spaces");
       
   245         props.put("key with space and Chinese_\u4e00", "valueWithChinese_\u4e00");
       
   246         props.put(" special#=key ", "value3");
       
   247 
       
   248         // Save the properties and check output
       
   249         ByteArrayOutputStream baos = new ByteArrayOutputStream();
       
   250         props.store(baos,"A test");
       
   251 
       
   252         // Read properties file and verify \u0019
       
   253         BufferedReader in = new BufferedReader(
       
   254                                 new InputStreamReader(
       
   255                                     new ByteArrayInputStream(
       
   256                                         baos.toByteArray())));
       
   257         String firstLine = "foo";
       
   258         while (!firstLine.startsWith("signal"))
       
   259             firstLine = in.readLine();
       
   260         if (firstLine.length() != 16)
       
   261             failCount++;
       
   262 
       
   263         // Load the properties set
       
   264         Properties newProps = new Properties();
       
   265         newProps.load(getInputStream(baos.toByteArray()));
       
   266         check(newProps, props);
       
   267 
       
   268         // Store(Writer)/Load(Reader)
       
   269         baos = new ByteArrayOutputStream();
       
   270         props.store(new OutputStreamWriter(baos, "EUC_JP"), "A test");
       
   271         newProps = new Properties();
       
   272         newProps.load(getReader(baos.toByteArray(), "EUC_JP"));
       
   273         check(newProps, props);
       
   274 
       
   275         report("SaveEncoding");
       
   276     }
       
   277 
       
   278    /**
       
   279     * This class tests to see if a properties object
       
   280     * can successfully save and load properties
       
   281     * using character encoding
       
   282     */
       
   283     private static void SaveLoadBasher() throws Exception {
       
   284         String keyValueSeparators = "=: \t\r\n\f#!\\";
       
   285 
       
   286         Properties originalProps = new Properties();
       
   287         Properties loadedProps = new Properties();
       
   288 
       
   289         // Generate a unicode key and value
       
   290         Random generator = new Random();
       
   291         int achar=0;
       
   292         StringBuffer aKeyBuffer = new StringBuffer(120);
       
   293         StringBuffer aValueBuffer = new StringBuffer(120);
       
   294         String aKey;
       
   295         String aValue;
       
   296         int maxKeyLen = 100;
       
   297         int maxValueLen = 100;
       
   298         int maxPropsNum = 300;
       
   299         for (int x=0; x<maxPropsNum; x++) {
       
   300             for(int y=0; y<maxKeyLen; y++) {
       
   301                 achar = generator.nextInt();
       
   302                 char test;
       
   303                 if(achar < 99999) {
       
   304                     test = (char)(achar);
       
   305                 }
       
   306                 else {
       
   307                     int zz = achar % 10;
       
   308                     test = keyValueSeparators.charAt(zz);
       
   309                 }
       
   310                 if (Character.isHighSurrogate(test)) {
       
   311                     aKeyBuffer.append(test);
       
   312                     aKeyBuffer.append('\udc00');
       
   313                     y++;
       
   314                 } else if (Character.isLowSurrogate(test)) {
       
   315                     aKeyBuffer.append('\ud800');
       
   316                     aKeyBuffer.append(test);
       
   317                     y++;
       
   318                 } else
       
   319                     aKeyBuffer.append(test);
       
   320             }
       
   321             aKey = aKeyBuffer.toString();
       
   322             for(int y=0; y<maxValueLen; y++) {
       
   323                 achar = generator.nextInt();
       
   324                 char test = (char)(achar);
       
   325                 if (Character.isHighSurrogate(test)) {
       
   326                     aKeyBuffer.append(test);
       
   327                     aKeyBuffer.append('\udc00');
       
   328                     y++;
       
   329                 } else if (Character.isLowSurrogate(test)) {
       
   330                     aKeyBuffer.append('\ud800');
       
   331                     aKeyBuffer.append(test);
       
   332                     y++;
       
   333                 } else {
       
   334                     aValueBuffer.append(test);
       
   335                 }
       
   336             }
       
   337             aValue = aValueBuffer.toString();
       
   338 
       
   339             // Attempt to add to original
       
   340             try {
       
   341                 originalProps.put(aKey, aValue);
       
   342             }
       
   343             catch (IllegalArgumentException e) {
       
   344                 System.err.println("disallowing...");
       
   345             }
       
   346             aKeyBuffer.setLength(0);
       
   347             aValueBuffer.setLength(0);
       
   348         }
       
   349 
       
   350         // Store(OutputStream)/Load(InputStream)
       
   351         ByteArrayOutputStream baos = new ByteArrayOutputStream();
       
   352         originalProps.store(baos, "test properties");
       
   353         loadedProps.load(getInputStream(baos.toByteArray()));
       
   354         check(loadedProps, originalProps);
       
   355 
       
   356         // Store(Writer)/Load(Reader)
       
   357         baos = new ByteArrayOutputStream();
       
   358         originalProps.store(new OutputStreamWriter(baos, "UTF-8"),
       
   359                             "test properties");
       
   360         loadedProps.load(getReader(baos.toByteArray(), "UTF-8"));
       
   361         check(loadedProps, originalProps);
       
   362 
       
   363         report("SaveLoadBasher");
       
   364     }
       
   365 
       
   366 
       
   367     /* Note: this regression test only detects incorrect line
       
   368      * separator on platform running the test
       
   369      */
       
   370     private static void SaveSeparator() throws Exception {
       
   371         ByteArrayOutputStream baos = new ByteArrayOutputStream();
       
   372         Properties props = new Properties();
       
   373         props.store(baos, "A test");
       
   374 
       
   375         // Examine the result to verify that line.separator was used
       
   376         String theSeparator = System.getProperty("line.separator");
       
   377         String content = baos.toString();
       
   378         if (!content.endsWith(theSeparator))
       
   379             failCount++;
       
   380 
       
   381         // store(Writer)
       
   382         baos = new ByteArrayOutputStream();
       
   383         props.store(new OutputStreamWriter(baos, "UTF-8"), "A test");
       
   384         content = baos.toString();
       
   385         if (!content.endsWith(theSeparator))
       
   386             failCount++;
       
   387 
       
   388         report("SaveSeparator");
       
   389     }
       
   390 
       
   391     // Ensure that the save method doesn't close its output stream
       
   392     private static void SaveClose() throws Exception {
       
   393         Properties p = new Properties();
       
   394         p.put("Foo", "Bar");
       
   395         class MyOS extends ByteArrayOutputStream {
       
   396             boolean closed = false;
       
   397             public void close() throws IOException {
       
   398                 this.closed = true;
       
   399             }
       
   400         }
       
   401         MyOS myos = new MyOS();
       
   402         p.store(myos, "Test");
       
   403         if (myos.closed)
       
   404             failCount++;
       
   405 
       
   406         p.store(new OutputStreamWriter(myos, "UTF-8"), "Test");
       
   407         if (myos.closed)
       
   408             failCount++;
       
   409 
       
   410         report ("SaveClose");
       
   411     }
       
   412 
       
   413     private static void UnicodeEscape() throws Exception {
       
   414         ByteArrayOutputStream baos = new ByteArrayOutputStream();
       
   415         OutputStreamWriter osw = new OutputStreamWriter(baos);
       
   416         osw.write("a=b\nb=\\u0\n");
       
   417         osw.close();
       
   418         Properties props = new Properties();
       
   419         boolean failed = true;
       
   420         try {
       
   421             props.load(getInputStream(baos.toByteArray()));
       
   422         } catch (IllegalArgumentException iae) {
       
   423             failed = false;
       
   424         }
       
   425         if (failed)
       
   426             failCount++;
       
   427 
       
   428         failed = true;
       
   429         props = new Properties();
       
   430         try {
       
   431             props.load(getReader(baos.toByteArray(), "UTF-8"));
       
   432         } catch (IllegalArgumentException iae) {
       
   433             failed = false;
       
   434         }
       
   435         if (failed)
       
   436             failCount++;
       
   437         report("UnicodeEscape");
       
   438     }
       
   439 
       
   440     private static void SaveComments() throws Exception {
       
   441         String ls = System.getProperty("line.separator");
       
   442         String[] input = new String[] {
       
   443           "Comments with \u4e2d\u6587\u6c49\u5b57 included",
       
   444           "Comments with \n Second comments line",
       
   445           "Comments with \n# Second comments line",
       
   446           "Comments with \n! Second comments line",
       
   447           "Comments with last character is \n",
       
   448           "Comments with last character is \r\n",
       
   449           "Comments with last two characters are \n\n",
       
   450           "Comments with last four characters are \r\n\r\n",
       
   451           "Comments with \nkey4=value4",
       
   452           "Comments with \n#key4=value4"};
       
   453 
       
   454         String[] output = new String[] {
       
   455           "#Comments with \\u4E2D\\u6587\\u6C49\\u5B57 included" + ls,
       
   456           "#Comments with " + ls + "# Second comments line" + ls,
       
   457           "#Comments with " + ls + "# Second comments line" + ls,
       
   458           "#Comments with " + ls + "! Second comments line" + ls,
       
   459           "#Comments with last character is " + ls+"#"+ls,
       
   460           "#Comments with last character is " + ls+"#"+ls,
       
   461           "#Comments with last two characters are " + ls+"#"+ls+"#"+ls,
       
   462           "#Comments with last four characters are " + ls+"#"+ls+"#"+ls};
       
   463 
       
   464         Properties props = new Properties();
       
   465         ByteArrayOutputStream baos;
       
   466         int i = 0;
       
   467         for (i = 0; i < output.length; i++) {
       
   468             baos = new ByteArrayOutputStream();
       
   469             props.store(baos, input[i]);
       
   470             String result = baos.toString("iso8859-1");
       
   471             if (result.indexOf(output[i]) == -1) {
       
   472                 failCount++;
       
   473             }
       
   474         }
       
   475         props.put("key1", "value1");
       
   476         props.put("key2", "value2");
       
   477         props.put("key3", "value3");
       
   478         for (; i < input.length; i++) {
       
   479             baos = new ByteArrayOutputStream();
       
   480             props.store(baos, input[i]);
       
   481             Properties propsNew = new Properties();
       
   482             propsNew.load(getInputStream(baos.toByteArray()));
       
   483             check(propsNew, props);
       
   484 
       
   485             baos = new ByteArrayOutputStream();
       
   486             props.store(new OutputStreamWriter(baos, "UTF-8"),
       
   487                         input[i]);
       
   488             propsNew = new Properties();
       
   489             propsNew.load(getReader(baos.toByteArray(), "UTF-8"));
       
   490             check(propsNew, props);
       
   491         }
       
   492         report("SaveComments");
       
   493     }
       
   494 }