1 /*
  2  * Copyright (c) 2018, 2022, 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 This exercises String#repeat patterns and limits.
 27  * @run main/othervm StringRepeat
 28  */
 29 
 30 /*
 31  * @test
 32  * @summary This exercises String#repeat patterns with 16 * 1024 * 1024 repeats.
 33  * @requires os.maxMemory >= 2G
 34  * @requires vm.bits == "64"
 35  * @run main/othervm -Xmx2g StringRepeat 16777216
 36  */
 37 
 38 import java.nio.CharBuffer;
 39 
 40 public class StringRepeat {
 41     public static void main(String... args) {
 42         if (args.length > 0) {
 43             REPEATS = new int[args.length];
 44             for (int i = 0; i < args.length; ++i) {
 45                 REPEATS[i] = Integer.parseInt(args[i]);
 46             }
 47         }
 48         test1();
 49         test2();
 50     }
 51 
 52     /*
 53      * Default varitions of repeat count.
 54      */
 55     static int[] REPEATS = {
 56         0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16,
 57         32, 64, 128, 256, 512, 1024, 64 * 1024, 1024 * 1024
 58     };
 59 
 60     /*
 61      * Varitions of Strings.
 62      */
 63     static String[] STRINGS = new String[] {
 64             "", "\0",  " ", "a", "$", "\u2022",
 65             "ab", "abc", "abcd", "abcde",
 66             "The quick brown fox jumps over the lazy dog."
 67     };
 68 
 69     /*
 70      * Repeat String function tests.
 71      */
 72     static void test1() {
 73         for (int repeat : REPEATS) {
 74             for (String string : STRINGS) {
 75                 long limit = (long)string.length() * (long)repeat;
 76 
 77                 if ((long)(Integer.MAX_VALUE >> 1) <= limit) {
 78                     break;
 79                 }
 80 
 81                 verify(string.repeat(repeat), string, repeat);
 82             }
 83         }
 84     }
 85 
 86     /*
 87      * Repeat String exception tests.
 88      */
 89     static void test2() {
 90         try {
 91             "abc".repeat(-1);
 92             throw new RuntimeException("No exception for negative repeat count");
 93         } catch (IllegalArgumentException ex) {
 94             // Correct
 95         }
 96 
 97         try {
 98             "abc".repeat(Integer.MAX_VALUE - 1);
 99             throw new RuntimeException("No exception for large repeat count");
100         } catch (OutOfMemoryError ex) {
101             // Correct
102         }
103     }
104 
105     static String truncate(String string) {
106         if (string.length() < 80) {
107             return string;
108         }
109         return string.substring(0, 80) + "...";
110     }
111 
112     /*
113      * Verify string repeat patterns.
114      */
115     static void verify(String result, String string, int repeat) {
116         if (string.isEmpty() || repeat == 0) {
117             if (!result.isEmpty()) {
118                 System.err.format("\"%s\".repeat(%d)%n", truncate(string), repeat);
119                 System.err.format("Result \"%s\"%n", truncate(result));
120                 System.err.format("Result expected to be empty, found string of length %d%n", result.length());
121                 throw new RuntimeException();
122             }
123         } else {
124             int expected = 0;
125             int count = 0;
126             for (int offset = result.indexOf(string, expected);
127                  0 <= offset;
128                  offset = result.indexOf(string, expected)) {
129                 count++;
130                 if (offset != expected) {
131                     System.err.format("\"%s\".repeat(%d)%n", truncate(string), repeat);
132                     System.err.format("Result \"%s\"%n", truncate(result));
133                     System.err.format("Repeat expected at %d, found at = %d%n", expected, offset);
134                     throw new RuntimeException();
135                 }
136                 expected += string.length();
137             }
138             if (count != repeat) {
139                 System.err.format("\"%s\".repeat(%d)%n", truncate(string), repeat);
140                 System.err.format("Result \"%s\"%n", truncate(result));
141                 System.err.format("Repeat count expected to be %d, found %d%n", repeat, count);
142                 throw new RuntimeException();
143             }
144         }
145     }
146 }