001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: */
017: package org.apache.commons.lang;
018:
019: import java.lang.reflect.Constructor;
020: import java.lang.reflect.Modifier;
021: import java.util.Random;
022:
023: import junit.framework.Test;
024: import junit.framework.TestSuite;
025: import junit.textui.TestRunner;
026:
027: /**
028: * Unit tests {@link org.apache.commons.lang.RandomStringUtils}.
029: *
030: * @author <a href="mailto:steven@caswell.name">Steven Caswell</a>
031: * @author <a href="mailto:ridesmet@users.sourceforge.net">Ringo De Smet</a>
032: * @author Phil Steitz
033: * @version $Id: RandomStringUtilsTest.java 437554 2006-08-28 06:21:41Z bayard $
034: */
035: public class RandomStringUtilsTest extends junit.framework.TestCase {
036: /**
037: * Construct a new instance of RandomStringUtilsTest with the specified name
038: */
039: public RandomStringUtilsTest(String name) {
040: super (name);
041: }
042:
043: public static Test suite() {
044: TestSuite suite = new TestSuite(RandomStringUtilsTest.class);
045: suite.setName("RandomStringUtils Tests");
046: return suite;
047: }
048:
049: /**
050: * Set up instance variables required by this test case.
051: */
052: public void setUp() {
053: }
054:
055: /**
056: * Tear down instance variables required by this test case.
057: */
058: public void tearDown() {
059: }
060:
061: //-----------------------------------------------------------------------
062: public void testConstructor() {
063: assertNotNull(new RandomStringUtils());
064: Constructor[] cons = RandomStringUtils.class
065: .getDeclaredConstructors();
066: assertEquals(1, cons.length);
067: assertEquals(true, Modifier.isPublic(cons[0].getModifiers()));
068: assertEquals(true, Modifier.isPublic(RandomStringUtils.class
069: .getModifiers()));
070: assertEquals(false, Modifier.isFinal(RandomStringUtils.class
071: .getModifiers()));
072: }
073:
074: //-----------------------------------------------------------------------
075: /**
076: * Test the implementation
077: */
078: public void testRandomStringUtils() {
079: String r1 = RandomStringUtils.random(50);
080: assertEquals("random(50) length", 50, r1.length());
081: String r2 = RandomStringUtils.random(50);
082: assertEquals("random(50) length", 50, r2.length());
083: assertTrue("!r1.equals(r2)", !r1.equals(r2));
084:
085: r1 = RandomStringUtils.randomAscii(50);
086: assertEquals("randomAscii(50) length", 50, r1.length());
087: for (int i = 0; i < r1.length(); i++) {
088: assertTrue("char between 32 and 127", r1.charAt(i) >= 32
089: && r1.charAt(i) <= 127);
090: }
091: r2 = RandomStringUtils.randomAscii(50);
092: assertTrue("!r1.equals(r2)", !r1.equals(r2));
093:
094: r1 = RandomStringUtils.randomAlphabetic(50);
095: assertEquals("randomAlphabetic(50)", 50, r1.length());
096: for (int i = 0; i < r1.length(); i++) {
097: assertEquals("r1 contains alphabetic", true, Character
098: .isLetter(r1.charAt(i))
099: && !Character.isDigit(r1.charAt(i)));
100: }
101: r2 = RandomStringUtils.randomAlphabetic(50);
102: assertTrue("!r1.equals(r2)", !r1.equals(r2));
103:
104: r1 = RandomStringUtils.randomAlphanumeric(50);
105: assertEquals("randomAlphanumeric(50)", 50, r1.length());
106: for (int i = 0; i < r1.length(); i++) {
107: assertEquals("r1 contains alphanumeric", true, Character
108: .isLetterOrDigit(r1.charAt(i)));
109: }
110: r2 = RandomStringUtils.randomAlphabetic(50);
111: assertTrue("!r1.equals(r2)", !r1.equals(r2));
112:
113: r1 = RandomStringUtils.randomNumeric(50);
114: assertEquals("randomNumeric(50)", 50, r1.length());
115: for (int i = 0; i < r1.length(); i++) {
116: assertEquals("r1 contains numeric", true, Character
117: .isDigit(r1.charAt(i))
118: && !Character.isLetter(r1.charAt(i)));
119: }
120: r2 = RandomStringUtils.randomNumeric(50);
121: assertTrue("!r1.equals(r2)", !r1.equals(r2));
122:
123: String set = "abcdefg";
124: r1 = RandomStringUtils.random(50, set);
125: assertEquals("random(50, \"abcdefg\")", 50, r1.length());
126: for (int i = 0; i < r1.length(); i++) {
127: assertTrue("random char in set",
128: set.indexOf(r1.charAt(i)) > -1);
129: }
130: r2 = RandomStringUtils.random(50, set);
131: assertTrue("!r1.equals(r2)", !r1.equals(r2));
132:
133: r1 = RandomStringUtils.random(50, (String) null);
134: assertEquals("random(50) length", 50, r1.length());
135: r2 = RandomStringUtils.random(50, (String) null);
136: assertEquals("random(50) length", 50, r2.length());
137: assertTrue("!r1.equals(r2)", !r1.equals(r2));
138:
139: set = "stuvwxyz";
140: r1 = RandomStringUtils.random(50, set.toCharArray());
141: assertEquals("random(50, \"stuvwxyz\")", 50, r1.length());
142: for (int i = 0; i < r1.length(); i++) {
143: assertTrue("random char in set",
144: set.indexOf(r1.charAt(i)) > -1);
145: }
146: r2 = RandomStringUtils.random(50, set);
147: assertTrue("!r1.equals(r2)", !r1.equals(r2));
148:
149: r1 = RandomStringUtils.random(50, (char[]) null);
150: assertEquals("random(50) length", 50, r1.length());
151: r2 = RandomStringUtils.random(50, (char[]) null);
152: assertEquals("random(50) length", 50, r2.length());
153: assertTrue("!r1.equals(r2)", !r1.equals(r2));
154:
155: long seed = System.currentTimeMillis();
156: r1 = RandomStringUtils.random(50, 0, 0, true, true, null,
157: new Random(seed));
158: r2 = RandomStringUtils.random(50, 0, 0, true, true, null,
159: new Random(seed));
160: assertEquals("r1.equals(r2)", r1, r2);
161:
162: r1 = RandomStringUtils.random(0);
163: assertEquals("random(0).equals(\"\")", "", r1);
164:
165: }
166:
167: public void testExceptions() {
168: try {
169: RandomStringUtils.random(-1);
170: fail();
171: } catch (IllegalArgumentException ex) {
172: }
173: try {
174: RandomStringUtils.random(-1, true, true);
175: fail();
176: } catch (IllegalArgumentException ex) {
177: }
178: try {
179: RandomStringUtils.random(-1, new char[0]);
180: fail();
181: } catch (IllegalArgumentException ex) {
182: }
183: try {
184: RandomStringUtils.random(-1, "");
185: fail();
186: } catch (IllegalArgumentException ex) {
187: }
188: try {
189: RandomStringUtils.random(-1, 'a', 'z', false, false);
190: fail();
191: } catch (IllegalArgumentException ex) {
192: }
193: try {
194: RandomStringUtils.random(-1, 'a', 'z', false, false,
195: new char[0]);
196: fail();
197: } catch (IllegalArgumentException ex) {
198: }
199: try {
200: RandomStringUtils.random(-1, 'a', 'z', false, false,
201: new char[0], new Random());
202: fail();
203: } catch (IllegalArgumentException ex) {
204: }
205: }
206:
207: /**
208: * Make sure boundary alphanumeric characters are generated by randomAlphaNumeric
209: * This test will fail randomly with probability = 6 * (61/62)**1000 ~ 5.2E-7
210: */
211: public void testRandomAlphaNumeric() {
212: char[] testChars = { 'a', 'z', 'A', 'Z', '0', '9' };
213: boolean[] found = { false, false, false, false, false, false };
214: for (int i = 0; i < 100; i++) {
215: String randString = RandomStringUtils
216: .randomAlphanumeric(10);
217: for (int j = 0; j < testChars.length; j++) {
218: if (randString.indexOf(testChars[j]) > 0) {
219: found[j] = true;
220: }
221: }
222: }
223: for (int i = 0; i < testChars.length; i++) {
224: if (!found[i]) {
225: fail("alphanumeric character not generated in 1000 attempts: "
226: + testChars[i]
227: + " -- repeated failures indicate a problem ");
228: }
229: }
230: }
231:
232: /**
233: * Make sure '0' and '9' are generated by randomNumeric
234: * This test will fail randomly with probability = 2 * (9/10)**1000 ~ 3.5E-46
235: */
236: public void testRandomNumeric() {
237: char[] testChars = { '0', '9' };
238: boolean[] found = { false, false };
239: for (int i = 0; i < 100; i++) {
240: String randString = RandomStringUtils.randomNumeric(10);
241: for (int j = 0; j < testChars.length; j++) {
242: if (randString.indexOf(testChars[j]) > 0) {
243: found[j] = true;
244: }
245: }
246: }
247: for (int i = 0; i < testChars.length; i++) {
248: if (!found[i]) {
249: fail("digit not generated in 1000 attempts: "
250: + testChars[i]
251: + " -- repeated failures indicate a problem ");
252: }
253: }
254: }
255:
256: /**
257: * Make sure boundary alpha characters are generated by randomAlphabetic
258: * This test will fail randomly with probability = 4 * (51/52)**1000 ~ 1.58E-8
259: */
260: public void testRandomAlphabetic() {
261: char[] testChars = { 'a', 'z', 'A', 'Z' };
262: boolean[] found = { false, false, false, false };
263: for (int i = 0; i < 100; i++) {
264: String randString = RandomStringUtils.randomAlphabetic(10);
265: for (int j = 0; j < testChars.length; j++) {
266: if (randString.indexOf(testChars[j]) > 0) {
267: found[j] = true;
268: }
269: }
270: }
271: for (int i = 0; i < testChars.length; i++) {
272: if (!found[i]) {
273: fail("alphanumeric character not generated in 1000 attempts: "
274: + testChars[i]
275: + " -- repeated failures indicate a problem ");
276: }
277: }
278: }
279:
280: /**
281: * Make sure 32 and 127 are generated by randomNumeric
282: * This test will fail randomly with probability = 2*(95/96)**1000 ~ 5.7E-5
283: */
284: public void testRandomAscii() {
285: char[] testChars = { (char) 32, (char) 126 };
286: boolean[] found = { false, false };
287: for (int i = 0; i < 100; i++) {
288: String randString = RandomStringUtils.randomAscii(10);
289: for (int j = 0; j < testChars.length; j++) {
290: if (randString.indexOf(testChars[j]) > 0) {
291: found[j] = true;
292: }
293: }
294: }
295: for (int i = 0; i < testChars.length; i++) {
296: if (!found[i]) {
297: fail("ascii character not generated in 1000 attempts: "
298: + (int) testChars[i]
299: + " -- repeated failures indicate a problem");
300: }
301: }
302: }
303:
304: /**
305: * Test homogeneity of random strings generated --
306: * i.e., test that characters show up with expected frequencies
307: * in generated strings. Will fail randomly about 1 in 1000 times.
308: * Repeated failures indicate a problem.
309: */
310: public void testRandomStringUtilsHomog() {
311: String set = "abc";
312: char[] chars = set.toCharArray();
313: String gen = "";
314: int[] counts = { 0, 0, 0 };
315: int[] expected = { 200, 200, 200 };
316: for (int i = 0; i < 100; i++) {
317: gen = RandomStringUtils.random(6, chars);
318: for (int j = 0; j < 6; j++) {
319: switch (gen.charAt(j)) {
320: case 'a': {
321: counts[0]++;
322: break;
323: }
324: case 'b': {
325: counts[1]++;
326: break;
327: }
328: case 'c': {
329: counts[2]++;
330: break;
331: }
332: default: {
333: fail("generated character not in set");
334: }
335: }
336: }
337: }
338: // Perform chi-square test with df = 3-1 = 2, testing at .001 level
339: assertTrue(
340: "test homogeneity -- will fail about 1 in 1000 times",
341: chiSquare(expected, counts) < 13.82);
342: }
343:
344: /**
345: * Computes Chi-Square statistic given observed and expected counts
346: * @param observed array of observed frequency counts
347: * @param expected array of expected frequency counts
348: */
349: private double chiSquare(int[] expected, int[] observed) {
350: double sumSq = 0.0d;
351: double dev = 0.0d;
352: for (int i = 0; i < observed.length; i++) {
353: dev = (double) (observed[i] - expected[i]);
354: sumSq += dev * dev / (double) expected[i];
355: }
356: return sumSq;
357: }
358:
359: /**
360: * Checks if the string got by {@link RandomStringUtils#random(int)}
361: * can be converted to UTF-8 and back without loss.
362: *
363: * @author stefanhoehne@fastmail.fm
364: * @throws Exception
365: */
366: public void testLang100() throws Exception {
367: int size = 5000;
368: String encoding = "UTF-8";
369: String orig = RandomStringUtils.random(size);
370: byte[] bytes = orig.getBytes(encoding);
371: String copy = new String(bytes, encoding);
372:
373: // for a verbose compare:
374: for (int i = 0; i < orig.length() && i < copy.length(); i++) {
375: char o = orig.charAt(i);
376: char c = copy.charAt(i);
377: assertEquals("differs at "
378: + i
379: + "("
380: + Integer
381: .toHexString((new Character(o)).hashCode())
382: + ","
383: + Integer
384: .toHexString((new Character(c)).hashCode())
385: + ")", o, c);
386: }
387: // compare length also
388: assertEquals(orig.length(), copy.length());
389: // just to be complete
390: assertEquals(orig, copy);
391: }
392:
393: public static void main(String args[]) {
394: TestRunner.run(suite());
395: }
396: }
|