Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2016 the V8 project authors. All rights reserved. | 1 // Copyright 2016 the V8 project authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 // Flags: --harmony-types | 5 // Flags: --harmony-types |
| 6 | 6 |
| 7 | 7 |
| 8 load("test/mjsunit/harmony/typesystem/testgen.js"); | |
| 9 | |
| 10 | |
| 8 // In all the following functions, the size parameter (positive integer) | 11 // In all the following functions, the size parameter (positive integer) |
| 9 // denotes how many test cases will be tried. The variable test_size | 12 // denotes how many test cases will be tried. The variable test_size |
| 10 // controls execution time of this test. It should not be too high. | 13 // controls execution time of this test. It should not be too high. |
| 11 let test_size = 1000; | 14 let test_size = 1000; |
| 12 | 15 |
| 13 function CheckValid(type) { | |
| 14 // print("V:", type); | |
| 15 assertDoesNotThrow("'use types'; var x: " + type + ";"); | |
| 16 } | |
| 17 | |
| 18 function CheckInvalid(type) { | |
| 19 // print("I:", type); | |
| 20 assertThrows("'use types'; var x: " + type + ";", SyntaxError); | |
| 21 } | |
| 22 | |
| 23 // Parameters: | |
| 24 // multiplicity: positive integer | |
| 25 // generator: (size: positive integer, ...params: any[]) => Iterator<SomeType> | |
| 26 // transformations: [false | ((t: SomeType) => OtherType)] | |
| 27 // params: any[] | |
| 28 // | |
| 29 // A "test generator" object will have its "generator" generate tests, | |
| 30 // will transform each generated test with all of its "transformations" | |
| 31 // and will yield the results. false transformations will be ignored. | |
| 32 class TestGen { | |
| 33 constructor(multiplicity, generator, transformations, ...params) { | |
| 34 // Determines how often this generator will run, compared to other ones. | |
| 35 this.multiplicity = multiplicity; | |
| 36 // The generator function. It will be called with (size, ...params), | |
| 37 // for an appropriate size provided externally to method initialize. | |
| 38 this.generator = generator; | |
| 39 // The list of transformation functions, excluding false ones. | |
| 40 this.transformations = transformations.filter(f => f !== false); | |
| 41 // The optional parameters to be passed to the generator function. | |
| 42 this.params = params; | |
| 43 } | |
| 44 // Returns how many tests this test generator is expected to yield | |
| 45 // in a row. | |
| 46 weight() { | |
| 47 return this.multiplicity * this.transformations.length; | |
| 48 } | |
| 49 // Initialize the generator function. | |
| 50 initialize(size) { | |
| 51 this.factory = this.generator(size, ...this.params); | |
| 52 } | |
| 53 // Is the test generator exhausted? | |
| 54 exhausted() { | |
| 55 return this.factory === null; | |
| 56 } | |
| 57 // Return a generator that will yield up to weight tests. | |
| 58 // It returns an Iterator<OtherType>. | |
| 59 * [Symbol.iterator]() { | |
| 60 for (let i = 0; i < this.multiplicity; i++) { | |
| 61 let element = this.factory.next(); | |
| 62 if (element.done) { | |
| 63 this.factory = null; | |
| 64 return; | |
| 65 } | |
| 66 for (let f of this.transformations) yield f(element.value); | |
| 67 } | |
| 68 } | |
| 69 } | |
| 70 | |
| 71 // Parameters: | |
| 72 // size: positive integer | |
| 73 // generators: [false | string | TestGen] | |
| 74 // | |
| 75 // This generator function will yield up to size tests. It will iterate | |
| 76 // cyclically through the list of test generators. A string in this list | |
| 77 // behaves as a simple generator yielding just one test; a false value | |
| 78 // behaves as a generator yielding nothing. For every test generator in | |
| 79 // the list, this function will generate as many tests as its weight | |
| 80 // before proceeding to the next test generator. Once a generator is | |
| 81 // exhausted, it is ignored in subsequent iterations. | |
| 82 function* Generate(size, generators) { | |
| 83 let fixed = 0, flexible = 0; | |
| 84 for (let gen of generators) { | |
| 85 if (gen === false) continue; | |
| 86 if (typeof gen === "string") fixed++; | |
| 87 else flexible += gen.weight(); | |
| 88 } | |
| 89 if (fixed + flexible == 0) throw "Empty list of test generators"; | |
| 90 let remaining = 0; | |
| 91 for (let gen of generators) { | |
| 92 if (gen === false) continue; | |
| 93 if (typeof gen !== "string") { | |
| 94 let weight = 1 + gen.weight(); | |
| 95 gen.initialize(Math.ceil(size * weight / flexible)); | |
| 96 remaining++; | |
| 97 } | |
| 98 } | |
| 99 for (let once = true; true; once = false) { | |
| 100 if (remaining == 0) return; | |
| 101 for (let gen of generators) { | |
| 102 if (gen === false) continue; | |
| 103 if (typeof gen === "string") { | |
| 104 if (once) { | |
| 105 if (size-- <= 0) return; else yield gen; | |
| 106 } | |
| 107 continue; | |
| 108 } | |
| 109 if (gen.exhausted()) continue; | |
| 110 for (let test of gen) { | |
| 111 if (size-- <= 0) return; else yield test; | |
| 112 } | |
| 113 if (gen.exhausted()) remaining--; | |
| 114 } | |
| 115 } | |
| 116 } | |
| 117 | |
| 118 // Parameters: | |
| 119 // size: positive integer | |
| 120 // generators: [string | TestGen] | |
| 121 // | |
| 122 // This function will generate all tests yielded by Generate and will | |
| 123 // discard the results. It will normally be called with test generators | |
| 124 // whose transformation functions test for validity (e.g. CheckValid or | |
| 125 // CheckInvalid) and do not return anything interesting. | |
| 126 function Test(size, generators) { | |
| 127 for (let attempt of Generate(size, generators)) continue; | |
| 128 } | |
| 129 | |
| 130 | 16 |
| 131 // In the rest, for each NonTerminal symbol in the parser grammar that we | 17 // In the rest, for each NonTerminal symbol in the parser grammar that we |
| 132 // care to test, there are two generator functions (ValidNonTerminal and | 18 // care to test, there are two generator functions (ValidNonTerminal and |
| 133 // InvalidNonTerminal) yielding valid and non valid terms for this symbol. | 19 // InvalidNonTerminal) yielding valid and non valid terms for this symbol. |
| 134 // These functions are of the form to be passed to Generate. | 20 // These functions are of the form to be passed to Generate. |
| 135 // There is also a test (using the TestNonTerminal function). | 21 // There is also a test (using the TestNonTerminal function). |
| 136 | 22 |
| 137 | 23 |
| 138 // Primary types. | 24 // Primary types. |
| 139 | 25 |
| 140 function ValidPrimaryTypes(size, proper=false) { | 26 function ValidPrimaryTypes(size, proper=false) { |
|
rossberg
2016/03/17 16:51:37
If I read the diffs correctly, then there is still
nickie
2016/03/18 11:12:01
You're right. Done.
| |
| 141 return Generate(size, [ | 27 return Generate(size, [ |
| 142 "any", | 28 "any", |
| 143 "void", | 29 "void", |
| 144 "this", | 30 "this", |
| 145 new TestGen(1, ValidTypes, [ | 31 new TestGen(1, ValidTypes, [ |
| 146 t => "(" + t + ")" | 32 t => "(" + t + ")" |
| 147 ]), | 33 ]), |
| 148 new TestGen(1, ValidPrimaryTypes, [ | 34 new TestGen(1, ValidPrimaryTypes, [ |
| 149 t => t + "[]", | 35 t => t + "[]", |
| 150 t => t + "[][]", | 36 t => t + "[][]", |
| (...skipping 23 matching lines...) Expand all Loading... | |
| 174 t => "(" + t + "[])", | 60 t => "(" + t + "[])", |
| 175 t => "(" + t + "[])[]", | 61 t => "(" + t + "[])[]", |
| 176 ]), | 62 ]), |
| 177 // Line terminator in arrays. | 63 // Line terminator in arrays. |
| 178 new TestGen(1, ValidTypes, [ | 64 new TestGen(1, ValidTypes, [ |
| 179 t => "(" + t + "\n[])" | 65 t => "(" + t + "\n[])" |
| 180 ]) | 66 ]) |
| 181 ]); | 67 ]); |
| 182 } | 68 } |
| 183 | 69 |
| 184 (function TestPrimaryTypes(size) { | |
| 185 Test(size, [ | |
| 186 new TestGen(4, ValidPrimaryTypes, [CheckValid], true), | |
| 187 new TestGen(1, InvalidPrimaryTypes, [CheckInvalid], true) | |
| 188 ]); | |
| 189 })(test_size); | |
| 190 | |
| 191 | 70 |
| 192 // Intersection types. | 71 // Intersection types. |
| 193 | 72 |
| 194 function ValidIntersectionTypes(size, proper=false) { | 73 function ValidIntersectionTypes(size, proper=false) { |
| 195 return Generate(size, [ | 74 return Generate(size, [ |
| 196 new TestGen(1, ValidPrimaryTypes, [ | 75 new TestGen(1, ValidPrimaryTypes, [ |
| 197 !proper && (t => t), | 76 !proper && (t => t), |
| 198 t => t + " & " + t, | 77 t => t + " & " + t, |
| 199 t => "(" + t + " & " + t + ") & " + t, | 78 t => "(" + t + " & " + t + ") & " + t, |
| 200 t => t + " & (" + t + " & " + t + ")", | 79 t => t + " & (" + t + " & " + t + ")", |
| (...skipping 11 matching lines...) Expand all Loading... | |
| 212 t => "(" + t + " & " + t + ") & " + t, | 91 t => "(" + t + " & " + t + ") & " + t, |
| 213 t => t + " & (" + t + " & " + t + ")", | 92 t => t + " & (" + t + " & " + t + ")", |
| 214 t => t + " & " + t + " & " + t | 93 t => t + " & " + t + " & " + t |
| 215 ]), | 94 ]), |
| 216 // Right hand side is a function or constructor type. | 95 // Right hand side is a function or constructor type. |
| 217 new TestGen(1, ValidFunctionTypes, [t => "any & " + t], false), | 96 new TestGen(1, ValidFunctionTypes, [t => "any & " + t], false), |
| 218 new TestGen(1, ValidFunctionTypes, [t => "any & " + t], true) | 97 new TestGen(1, ValidFunctionTypes, [t => "any & " + t], true) |
| 219 ]); | 98 ]); |
| 220 } | 99 } |
| 221 | 100 |
| 222 (function TestIntersectionTypes(size) { | |
| 223 Test(size, [ | |
| 224 new TestGen(4, ValidIntersectionTypes, [CheckValid], true), | |
| 225 new TestGen(1, InvalidIntersectionTypes, [CheckInvalid], true) | |
| 226 ]); | |
| 227 })(test_size); | |
| 228 | |
| 229 | 101 |
| 230 // Union types. | 102 // Union types. |
| 231 | 103 |
| 232 function ValidUnionTypes(size, proper=false) { | 104 function ValidUnionTypes(size, proper=false) { |
| 233 return Generate(size, [ | 105 return Generate(size, [ |
| 234 new TestGen(1, ValidIntersectionTypes, [ | 106 new TestGen(1, ValidIntersectionTypes, [ |
| 235 !proper && (t => t), | 107 !proper && (t => t), |
| 236 t => t + " | " + t, | 108 t => t + " | " + t, |
| 237 t => "(" + t + " | " + t + ") | " + t, | 109 t => "(" + t + " | " + t + ") | " + t, |
| 238 t => t + " | (" + t + " | " + t + ")", | 110 t => t + " | (" + t + " | " + t + ")", |
| (...skipping 11 matching lines...) Expand all Loading... | |
| 250 t => "(" + t + " | " + t + ") | " + t, | 122 t => "(" + t + " | " + t + ") | " + t, |
| 251 t => t + " | (" + t + " | " + t + ")", | 123 t => t + " | (" + t + " | " + t + ")", |
| 252 t => t + " | " + t + " | " + t | 124 t => t + " | " + t + " | " + t |
| 253 ]), | 125 ]), |
| 254 // Right hand side is a function or constructor type. | 126 // Right hand side is a function or constructor type. |
| 255 new TestGen(1, ValidFunctionTypes, [t => "any | " + t], false), | 127 new TestGen(1, ValidFunctionTypes, [t => "any | " + t], false), |
| 256 new TestGen(1, ValidFunctionTypes, [t => "any | " + t], true) | 128 new TestGen(1, ValidFunctionTypes, [t => "any | " + t], true) |
| 257 ]); | 129 ]); |
| 258 } | 130 } |
| 259 | 131 |
| 260 (function TestUnionTypes(size) { | |
| 261 Test(size, [ | |
| 262 new TestGen(4, ValidUnionTypes, [CheckValid], true), | |
| 263 new TestGen(1, InvalidUnionTypes, [CheckInvalid], true) | |
| 264 ]); | |
| 265 })(test_size); | |
| 266 | |
| 267 | 132 |
| 268 // Function and constructor types. | 133 // Function and constructor types. |
| 269 | 134 |
| 270 function ValidFunctionTypes(size, constr) { | 135 function ValidFunctionTypes(size, constr) { |
| 271 let c = constr ? "new " : ""; | 136 let c = constr ? "new " : ""; |
| 272 return Generate(size, [ | 137 return Generate(size, [ |
| 273 new TestGen(1, ValidTypes, [ | 138 new TestGen(1, ValidTypes, [ |
| 274 t => c + "() => " + t, | 139 t => c + "() => " + t, |
| 275 t => c + "(a: " + t + ") => " + t, | 140 t => c + "(a: " + t + ") => " + t, |
| 276 t => c + "(a:" + t + ", b?:" + t + ") => " + t, | 141 t => c + "(a:" + t + ", b?:" + t + ") => " + t, |
| (...skipping 16 matching lines...) Expand all Loading... | |
| 293 t => c + "(a:" + t + ", b?:" + t + ") => " + t, | 158 t => c + "(a:" + t + ", b?:" + t + ") => " + t, |
| 294 t => c + "(a:" + t + ", b?:" + t + ", c) => " + t, | 159 t => c + "(a:" + t + ", b?:" + t + ", c) => " + t, |
| 295 t => c + "(a:" + t + ", b?:" + t + ", c?) => " + t, | 160 t => c + "(a:" + t + ", b?:" + t + ", c?) => " + t, |
| 296 t => c + "(a:" + t + ", b:" + t + ", c, ...d) => " + t, | 161 t => c + "(a:" + t + ", b:" + t + ", c, ...d) => " + t, |
| 297 t => c + "(a:" + t + ", b:" + t + ", c, ...d) => " + t, | 162 t => c + "(a:" + t + ", b:" + t + ", c, ...d) => " + t, |
| 298 t => c + "(a:" + t + ", b:" + t + ", c, ...d: string[]) => " + t | 163 t => c + "(a:" + t + ", b:" + t + ", c, ...d: string[]) => " + t |
| 299 ]) | 164 ]) |
| 300 ]); | 165 ]); |
| 301 } | 166 } |
| 302 | 167 |
| 303 (function TestFunctionAndConstructorTypes(size) { | 168 |
| 169 // Tuple types. | |
| 170 | |
| 171 function ValidTupleTypes(size, proper=false) { | |
| 172 return Generate(size, [ | |
| 173 new TestGen(1, ValidTypes, [ | |
| 174 !proper && (t => t), | |
| 175 t => "[" + t + "]", | |
| 176 t => "[" + t + ", " + t + "]", | |
| 177 t => "[" + t + ", " + t + ", " + t + "]" | |
| 178 ]) | |
| 179 ]); | |
| 180 } | |
| 181 | |
| 182 function InvalidTupleTypes(size, proper=false) { | |
| 183 return Generate(size, [ | |
| 184 // Illegal types in legal places. | |
| 185 new TestGen(1, InvalidTypes, [ | |
| 186 !proper && (t => t), | |
| 187 t => "[" + t + "]", | |
| 188 t => "[" + t + ", " + t + "]", | |
| 189 t => "[" + t + ", " + t + ", " + t + "]" | |
| 190 ]), | |
| 191 // Valid binding patterns that are not tuple types. | |
| 192 "[]", | |
| 193 new TestGen(1, ValidTypes, [t => "[" + t + ",]"]), | |
| 194 new TestGen(1, ValidTypes, [t => "[" + t + ",,]"]), | |
| 195 new TestGen(1, ValidTypes, [t => "[," + t + "]"]), | |
| 196 new TestGen(1, ValidTypes, [t => "[,," + t + "]"]), | |
| 197 new TestGen(1, ValidTypes, [t => "[" + t + ",," + t + "]"]), | |
| 198 new TestGen(1, ValidTypes, [t => "[..." + t + "]"]), | |
| 199 new TestGen(1, ValidTypes, [t => "[" + t + ", ..." + t + "]"]), | |
| 200 ]); | |
| 201 } | |
| 202 | |
| 203 (function TestTupleTypes(size) { | |
| 304 Test(size, [ | 204 Test(size, [ |
| 305 new TestGen(4, ValidFunctionTypes, [CheckValid], false), | 205 new TestGen(4, ValidTupleTypes, [CheckValid], true), |
| 306 new TestGen(1, InvalidFunctionTypes, [CheckInvalid], false), | 206 new TestGen(1, InvalidTupleTypes, [CheckInvalid], true) |
| 307 new TestGen(4, ValidFunctionTypes, [CheckValid], true), | |
| 308 new TestGen(1, InvalidFunctionTypes, [CheckInvalid], true) | |
| 309 ]); | 207 ]); |
| 310 })(test_size); | 208 })(test_size); |
| 311 | 209 |
| 312 | 210 |
| 313 // All simple types. | 211 // All types. |
| 314 | 212 |
| 315 function ValidTypes(size) { | 213 function ValidTypes(size) { |
| 316 return Generate(size, [ | 214 return Generate(size, [ |
| 317 new TestGen(3, ValidUnionTypes, [t => t]), | 215 new TestGen(3, ValidUnionTypes, [t => t]), |
| 318 new TestGen(1, ValidFunctionTypes, [t => t], false), | 216 new TestGen(1, ValidFunctionTypes, [t => t], false), |
| 319 ]); | 217 ]); |
| 320 } | 218 } |
| 321 | 219 |
| 322 function InvalidTypes(size) { | 220 function InvalidTypes(size) { |
| 323 return Generate(size, [ | 221 return Generate(size, [ |
| 324 new TestGen(3, InvalidUnionTypes, [t => t]), | 222 new TestGen(3, InvalidUnionTypes, [t => t]), |
| 325 new TestGen(1, InvalidFunctionTypes, [t => t], false), | 223 new TestGen(1, InvalidFunctionTypes, [t => t], false), |
| 326 ]); | 224 ]); |
| 327 } | 225 } |
| OLD | NEW |