Chromium Code Reviews| OLD | NEW |
|---|---|
| (Empty) | |
| 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | |
| 2 // for details. All rights reserved. Use of this source code is governed by a | |
| 3 // BSD-style license that can be found in the LICENSE file. | |
| 4 | |
| 5 /** | |
| 6 * Tests for the toString methods on collections (including maps). | |
| 7 */ | |
| 8 | |
| 9 // todo(jjb): seed random number generator when API allows it | |
|
Ivan Posva
2012/02/15 09:54:10
Allcaps TODO. Here and maybe other places.
| |
| 10 | |
| 11 final int NUM_TESTS = 3000; | |
| 12 final int MAX_COLLECTION_SIZE = 6; | |
| 13 | |
| 14 main() { | |
| 15 exactTest(); | |
|
sra1
2012/02/15 03:11:10
The tests are large and require careful reading.
I
Ivan Posva
2012/02/15 09:54:10
Adding a couple of these before starting the more
| |
| 16 inexactTest(); | |
| 17 } | |
| 18 | |
| 19 /** | |
| 20 * Generate a bunch of random collections (including Maps), and test that | |
| 21 * there string form is as expected. The collections include collections | |
| 22 * as elements, keys, and values, and include recursive references. | |
| 23 * | |
| 24 * This test restricts itself to collections with well-defined iteration | |
| 25 * orders (i.e., no HashSet, HashMap). | |
| 26 */ | |
| 27 void exactTest() { | |
| 28 for (int i = 0; i < NUM_TESTS; i++) { | |
| 29 // Choose a size from 0 to MAX_COLLECTION_SIZE, favoring larger sizes | |
| 30 float sqrtSize = Math.sqrt(Math.random() * (MAX_COLLECTION_SIZE + 1)); | |
| 31 int size = (sqrtSize * sqrtSize).toInt(); | |
| 32 | |
| 33 StringBuffer stringRep = new StringBuffer(); | |
| 34 Object o = randomCollection(size, stringRep, exact:true); | |
| 35 Expect.equals(o.toString(), stringRep.toString()); | |
| 36 } | |
| 37 } | |
| 38 | |
| 39 /** | |
| 40 * Generate a bunch of random collections (including Maps), and test that | |
| 41 * there string form is as expected. The collections include collections | |
| 42 * as elements, keys, and values, and include recursive references. | |
| 43 * | |
| 44 * This test includes collections with ill-defined iteration orders (i.e., | |
| 45 * HashSet, HashMap). As a consequence, it can't use equality tests on the | |
| 46 * string form. Instead, it performs equality tests on their "alphagrams." | |
| 47 * This might allow false positives, but it does give a fair amount of | |
| 48 * confidence. | |
| 49 */ | |
| 50 void inexactTest() { | |
| 51 for (int i = 0; i < NUM_TESTS; i++) { | |
| 52 // Choose a size from 0 to MAX_COLLECTION_SIZE, favoring larger sizes | |
| 53 float sqrtSize = Math.sqrt(Math.random() * (MAX_COLLECTION_SIZE + 1)); | |
| 54 int size = (sqrtSize * sqrtSize).toInt(); | |
| 55 | |
| 56 StringBuffer stringRep = new StringBuffer(); | |
| 57 Object o = randomCollection(size, stringRep, exact:false); | |
| 58 Expect.equals(alphagram(o.toString()), alphagram(stringRep.toString())); | |
| 59 } | |
| 60 } | |
| 61 | |
| 62 /** | |
| 63 * Return a random collection (or Map) of the specified size, placing its | |
| 64 * string representation into the given string buffer. | |
| 65 * | |
| 66 * If exact is true, the returned collections will not be, and will not contain | |
| 67 * a collection with ill-defined iteration order (i.e., a HashSet or HashMap). | |
| 68 */ | |
| 69 Object randomCollection(int size, StringBuffer stringRep, [bool exact]) { | |
| 70 return randomCollectionHelper(size, exact, stringRep, []); | |
| 71 } | |
| 72 | |
| 73 /** | |
| 74 * Return a random collection (or map) of the specified size, placing its | |
| 75 * string representation into the given string buffer. The beingMade | |
| 76 * parameter is a list of collections currently under construction, i.e., | |
| 77 * candidates for recursive references. | |
| 78 * | |
| 79 * If exact is true, the returned collections will not be, and will not contain | |
| 80 * a collection with ill-defined iteration order (i.e., a HashSet or HashMap). | |
| 81 */ | |
| 82 Object randomCollectionHelper(int size, bool exact, StringBuffer stringRep, | |
| 83 List beingMade) { | |
| 84 double interfaceFrac = Math.random(); | |
| 85 | |
| 86 if (exact) { | |
| 87 if (interfaceFrac < 1/3) { | |
| 88 return randomList(size, exact, stringRep, beingMade); | |
| 89 } else if (interfaceFrac < 2/3) { | |
| 90 return randomQueue(size, exact, stringRep, beingMade); | |
| 91 } else { | |
| 92 return randomMap(size, exact, stringRep, beingMade); | |
| 93 } | |
| 94 } else { | |
| 95 if (interfaceFrac < 1/4) { | |
| 96 return randomList(size, exact, stringRep, beingMade); | |
| 97 } else if (interfaceFrac < 2/4) { | |
| 98 return randomQueue(size, exact, stringRep, beingMade); | |
| 99 } else if (interfaceFrac < 3/4) { | |
| 100 return randomSet(size, exact, stringRep, beingMade); | |
| 101 } else { | |
| 102 return randomMap(size, exact, stringRep, beingMade); | |
| 103 } | |
| 104 } | |
| 105 } | |
| 106 | |
| 107 /** | |
| 108 * Return a random List of the specified size, placing its string | |
| 109 * representation into the given string buffer. The beingMade | |
| 110 * parameter is a list of collections currently under construction, i.e., | |
| 111 * candidates for recursive references. | |
| 112 * | |
| 113 * If exact is true, the returned collections will not be, and will not contain | |
| 114 * a collection with ill-defined iteration order (i.e., a HashSet or HashMap). | |
| 115 */ | |
| 116 List randomList(int size, bool exact, StringBuffer stringRep, List beingMade) { | |
| 117 return populateRandomCollection(size, exact, stringRep, beingMade, []); | |
| 118 } | |
| 119 | |
| 120 /** | |
| 121 * Like randomList, but returns a queue. | |
| 122 */ | |
| 123 Queue randomQueue(int size, bool exact, StringBuffer stringRep, List beingMade){ | |
| 124 return populateRandomCollection(size, exact, stringRep, beingMade, new Queue() ); | |
| 125 } | |
| 126 | |
| 127 /** | |
| 128 * Like randomList, but returns a Set. | |
| 129 */ | |
| 130 Set randomSet(int size, bool exact, StringBuffer stringRep, List beingMade) { | |
| 131 // Until we have LinkedHashSet, method will only be called with exact==true | |
| 132 return populateRandomSet(size, exact, stringRep, beingMade, new Set()); | |
| 133 } | |
| 134 | |
| 135 /** | |
| 136 * Like randomList, but returns a map. | |
| 137 */ | |
| 138 Map randomMap(int size, bool exact, StringBuffer stringRep, List beingMade) { | |
| 139 if (exact) { | |
| 140 return populateRandomMap(size, exact, stringRep, beingMade, | |
| 141 new LinkedHashMap()); | |
| 142 } else { | |
| 143 return populateRandomMap(size, exact, stringRep, beingMade, | |
| 144 randomBool() ? new Map() : new LinkedHashMap()); | |
| 145 } | |
| 146 } | |
| 147 | |
| 148 /** | |
| 149 * Populates the given empty collection with elements, emitting the string | |
| 150 * representation of the collection to stringRep. The beingMade parameter is | |
| 151 * a list of collections currently under construction, i.e., candidates for | |
| 152 * recursive references. | |
| 153 * | |
| 154 * If exact is true, the elements of the returned collections will not be, | |
| 155 * and will not contain a collection with ill-defined iteration order | |
| 156 * (i.e., a HashSet or HashMap). | |
| 157 */ | |
| 158 Collection populateRandomCollection(int size, bool exact, | |
| 159 StringBuffer stringRep, List beingMade, Collection coll) { | |
| 160 beingMade.add(coll); | |
| 161 stringRep.add(coll is List ? '[' : '{'); | |
| 162 | |
| 163 for (int i = 0; i < size; i++) { | |
| 164 if (i != 0) stringRep.add(', '); | |
| 165 coll.add(randomElement(random(size), exact, stringRep, beingMade)); | |
| 166 } | |
| 167 | |
| 168 stringRep.add(coll is List ? ']' : '}'); | |
| 169 beingMade.removeLast(); | |
| 170 return coll; | |
| 171 } | |
| 172 | |
| 173 /** Like populateRandomCollection, but for sets (elements must be hashable) */ | |
| 174 Set populateRandomSet(int size, bool exact, StringBuffer stringRep, | |
| 175 List beingMade, Set set) { | |
| 176 stringRep.add('{'); | |
| 177 | |
| 178 for (int i = 0; i < size; i++) { | |
| 179 if (i != 0) stringRep.add(', '); | |
| 180 set.add(i); | |
| 181 stringRep.add(i); | |
| 182 } | |
| 183 | |
| 184 stringRep.add('}'); | |
| 185 return set; | |
| 186 } | |
| 187 | |
| 188 | |
| 189 /** Like populateRandomCollection, but for maps. */ | |
| 190 Map populateRandomMap(int size, bool exact, StringBuffer stringRep, | |
| 191 List beingMade, Map map) { | |
| 192 beingMade.add(map); | |
| 193 stringRep.add('{'); | |
| 194 | |
| 195 for (int i = 0; i < size; i++) { | |
| 196 if (i != 0) stringRep.add(', '); | |
| 197 | |
| 198 int key = i; // Ensures no duplicates | |
| 199 stringRep.add(key); | |
| 200 stringRep.add(': '); | |
| 201 Object val = randomElement(random(size), exact, stringRep, beingMade); | |
| 202 map[key] = val; | |
| 203 } | |
| 204 | |
| 205 stringRep.add('}'); | |
| 206 beingMade.removeLast(); | |
| 207 return map; | |
| 208 } | |
| 209 | |
| 210 /** | |
| 211 * Generates a random element which can be an int, a collection, or a map, | |
| 212 * and emits it to StringRep. The beingMade parameter is a list of collections | |
| 213 * currently under construction, i.e., candidates for recursive references. | |
| 214 * | |
| 215 * If exact is true, the returned element will not be, and will not contain | |
| 216 * a collection with ill-defined iteration order (i.e., a HashSet or HashMap). | |
| 217 */ | |
| 218 void randomElement(int size, bool exact, StringBuffer stringRep, | |
| 219 List beingMade) { | |
| 220 Object result; | |
| 221 double elementTypeFrac = Math.random(); | |
| 222 if (elementTypeFrac < 1/3) { | |
| 223 result = random(1000); | |
| 224 stringRep.add(result); | |
| 225 } else if (elementTypeFrac < 2/3) { | |
| 226 // Element Is a random (new) collection | |
| 227 result = randomCollectionHelper(size, exact, stringRep, beingMade); | |
| 228 } else { | |
| 229 // Element Is a random recursive ref | |
| 230 result = beingMade[random(beingMade.length)]; | |
| 231 if (result is List) | |
| 232 stringRep.add('[...]'); | |
| 233 else | |
| 234 stringRep.add('{...}'); | |
| 235 } | |
| 236 return result; | |
| 237 } | |
| 238 | |
| 239 /** Returns a random int on [0, max) */ | |
| 240 int random(int max) { | |
| 241 return (Math.random() * max).toInt(); | |
| 242 } | |
| 243 | |
| 244 /** Returns a random boolean value. */ | |
| 245 bool randomBool() { | |
| 246 return Math.random() < .5; | |
| 247 } | |
| 248 | |
| 249 /** Returns the alphabetized characters in a string. */ | |
| 250 String alphagram(String s) { | |
| 251 List<int> chars = s.charCodes(); | |
| 252 chars.sort((int a, int b) => a - b); | |
| 253 return new String.fromCharCodes(chars); | |
| 254 } | |
| OLD | NEW |