| OLD | NEW |
| 1 // Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a | 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. | 3 // BSD-style license that can be found in the LICENSE file. |
| 4 |
| 4 import 'package:kernel/ast.dart'; | 5 import 'package:kernel/ast.dart'; |
| 5 import 'package:kernel/text/ast_to_text.dart'; | 6 import 'package:kernel/text/ast_to_text.dart'; |
| 6 import 'package:kernel/verifier.dart'; | 7 import 'package:kernel/verifier.dart'; |
| 7 import 'package:test/test.dart'; | 8 import 'package:test/test.dart'; |
| 8 | 9 |
| 10 const String varRegexp = "#t[0-9]+"; |
| 11 |
| 12 const String tvarRegexp = "#T[0-9]+"; |
| 13 |
| 9 /// Checks that the verifier correctly find errors in invalid programs. | 14 /// Checks that the verifier correctly find errors in invalid programs. |
| 10 /// | 15 /// |
| 11 /// The frontend should never generate invalid programs, so we have to test | 16 /// The frontend should never generate invalid programs, so we have to test |
| 12 /// these by manually constructing invalid ASTs. | 17 /// these by manually constructing invalid ASTs. |
| 13 /// | 18 /// |
| 14 /// We mostly test negative cases here, as we get plenty of positive cases by | 19 /// We mostly test negative cases here, as we get plenty of positive cases by |
| 15 /// compiling the Dart test suite with the verifier enabled. | 20 /// compiling the Dart test suite with the verifier enabled. |
| 16 main() { | 21 main() { |
| 17 positiveTest('Test harness has no errors', (TestHarness test) { | 22 positiveTest('Test harness has no errors', (TestHarness test) { |
| 18 return new NullLiteral(); | 23 return new NullLiteral(); |
| 19 }); | 24 }); |
| 20 negativeTest('VariableGet out of scope', (TestHarness test) { | 25 negativeTest('VariableGet out of scope', |
| 26 matches("Variable '$varRegexp' used out of scope\\."), |
| 27 (TestHarness test) { |
| 21 return new VariableGet(test.makeVariable()); | 28 return new VariableGet(test.makeVariable()); |
| 22 }); | 29 }); |
| 23 negativeTest('VariableSet out of scope', (TestHarness test) { | 30 negativeTest('VariableSet out of scope', |
| 31 matches("Variable '$varRegexp' used out of scope\\."), |
| 32 (TestHarness test) { |
| 24 return new VariableSet(test.makeVariable(), new NullLiteral()); | 33 return new VariableSet(test.makeVariable(), new NullLiteral()); |
| 25 }); | 34 }); |
| 26 negativeTest('Variable block scope', (TestHarness test) { | 35 negativeTest('Variable block scope', |
| 36 matches("Variable '$varRegexp' used out of scope\\."), |
| 37 (TestHarness test) { |
| 27 VariableDeclaration variable = test.makeVariable(); | 38 VariableDeclaration variable = test.makeVariable(); |
| 28 return new Block([ | 39 return new Block([ |
| 29 new Block([variable]), | 40 new Block([variable]), |
| 30 new ReturnStatement(new VariableGet(variable)) | 41 new ReturnStatement(new VariableGet(variable)) |
| 31 ]); | 42 ]); |
| 32 }); | 43 }); |
| 33 negativeTest('Variable let scope', (TestHarness test) { | 44 negativeTest('Variable let scope', |
| 45 matches("Variable '$varRegexp' used out of scope\\."), |
| 46 (TestHarness test) { |
| 34 VariableDeclaration variable = test.makeVariable(); | 47 VariableDeclaration variable = test.makeVariable(); |
| 35 return new LogicalExpression(new Let(variable, new VariableGet(variable)), | 48 return new LogicalExpression(new Let(variable, new VariableGet(variable)), |
| 36 '&&', new VariableGet(variable)); | 49 '&&', new VariableGet(variable)); |
| 37 }); | 50 }); |
| 38 negativeTest('Variable redeclared', (TestHarness test) { | 51 negativeTest('Variable redeclared', |
| 52 matches("Variable '$varRegexp' declared more than once\\."), |
| 53 (TestHarness test) { |
| 39 VariableDeclaration variable = test.makeVariable(); | 54 VariableDeclaration variable = test.makeVariable(); |
| 40 return new Block([variable, variable]); | 55 return new Block([variable, variable]); |
| 41 }); | 56 }); |
| 42 negativeTest('Member redeclared', (TestHarness test) { | 57 negativeTest('Member redeclared', |
| 58 "Member 'test_lib::Test::field' has been declared more than once.", |
| 59 (TestHarness test) { |
| 43 Field field = new Field(new Name('field'), initializer: new NullLiteral()); | 60 Field field = new Field(new Name('field'), initializer: new NullLiteral()); |
| 44 return new Class( | 61 return new Class( |
| 45 name: 'Test', | 62 name: 'Test', |
| 46 supertype: test.objectClass.asRawSupertype, | 63 supertype: test.objectClass.asRawSupertype, |
| 47 fields: [field, field]); | 64 fields: [field, field]); |
| 48 }); | 65 }); |
| 49 negativeTest('Class redeclared', (TestHarness test) { | 66 negativeTest('Class redeclared', |
| 67 "Class 'test_lib::OtherClass' declared more than once.", |
| 68 (TestHarness test) { |
| 50 return test.otherClass; // Test harness also adds otherClass to program. | 69 return test.otherClass; // Test harness also adds otherClass to program. |
| 51 }); | 70 }); |
| 52 negativeTest('Class type parameter redeclared', (TestHarness test) { | 71 negativeTest('Class type parameter redeclared', |
| 72 matches("Type parameter 'test_lib::Test::$tvarRegexp' redeclared\\."), |
| 73 (TestHarness test) { |
| 53 var parameter = test.makeTypeParameter(); | 74 var parameter = test.makeTypeParameter(); |
| 54 return new Class( | 75 return new Class( |
| 55 name: 'Test', | 76 name: 'Test', |
| 56 supertype: test.objectClass.asRawSupertype, | 77 supertype: test.objectClass.asRawSupertype, |
| 57 typeParameters: [parameter, parameter]); | 78 typeParameters: [parameter, parameter]); |
| 58 }); | 79 }); |
| 59 negativeTest('Member type parameter redeclared', (TestHarness test) { | 80 negativeTest('Member type parameter redeclared', |
| 81 matches("Type parameter '$tvarRegexp' redeclared\\."), |
| 82 (TestHarness test) { |
| 60 var parameter = test.makeTypeParameter(); | 83 var parameter = test.makeTypeParameter(); |
| 61 return new Procedure( | 84 return new Procedure( |
| 62 new Name('bar'), | 85 new Name('bar'), |
| 63 ProcedureKind.Method, | 86 ProcedureKind.Method, |
| 64 new FunctionNode(new ReturnStatement(new NullLiteral()), | 87 new FunctionNode(new ReturnStatement(new NullLiteral()), |
| 65 typeParameters: [parameter, parameter])); | 88 typeParameters: [parameter, parameter])); |
| 66 }); | 89 }); |
| 67 negativeTest('Type parameter out of scope', (TestHarness test) { | 90 negativeTest( |
| 91 'Type parameter out of scope', |
| 92 matches("Type parameter '$tvarRegexp' referenced out of scope," |
| 93 " parent is: 'null'\\."), (TestHarness test) { |
| 68 var parameter = test.makeTypeParameter(); | 94 var parameter = test.makeTypeParameter(); |
| 69 return new ListLiteral([], typeArgument: new TypeParameterType(parameter)); | 95 return new ListLiteral([], typeArgument: new TypeParameterType(parameter)); |
| 70 }); | 96 }); |
| 71 negativeTest('Class type parameter from another class', (TestHarness test) { | 97 negativeTest( |
| 98 'Class type parameter from another class', |
| 99 "Type parameter 'test_lib::OtherClass::OtherT' referenced out of scope," |
| 100 " parent is: 'test_lib::OtherClass'.", (TestHarness test) { |
| 72 return new TypeLiteral( | 101 return new TypeLiteral( |
| 73 new TypeParameterType(test.otherClass.typeParameters[0])); | 102 new TypeParameterType(test.otherClass.typeParameters[0])); |
| 74 }); | 103 }); |
| 75 negativeTest('Class type parameter in static method', (TestHarness test) { | 104 negativeTest( |
| 105 'Class type parameter in static method', |
| 106 "Type parameter 'test_lib::TestClass::T' referenced from static context," |
| 107 " parent is 'test_lib::TestClass'.", (TestHarness test) { |
| 76 return new Procedure( | 108 return new Procedure( |
| 77 new Name('bar'), | 109 new Name('bar'), |
| 78 ProcedureKind.Method, | 110 ProcedureKind.Method, |
| 79 new FunctionNode(new ReturnStatement( | 111 new FunctionNode(new ReturnStatement( |
| 80 new TypeLiteral(new TypeParameterType(test.classTypeParameter)))), | 112 new TypeLiteral(new TypeParameterType(test.classTypeParameter)))), |
| 81 isStatic: true); | 113 isStatic: true); |
| 82 }); | 114 }); |
| 83 negativeTest('Class type parameter in static field', (TestHarness test) { | 115 negativeTest( |
| 116 'Class type parameter in static field', |
| 117 "Type parameter 'test_lib::TestClass::T' referenced from static context," |
| 118 " parent is 'test_lib::TestClass'.", (TestHarness test) { |
| 84 return new Field(new Name('field'), | 119 return new Field(new Name('field'), |
| 85 initializer: | 120 initializer: |
| 86 new TypeLiteral(new TypeParameterType(test.classTypeParameter)), | 121 new TypeLiteral(new TypeParameterType(test.classTypeParameter)), |
| 87 isStatic: true); | 122 isStatic: true); |
| 88 }); | 123 }); |
| 89 negativeTest('Method type parameter out of scope', (TestHarness test) { | 124 negativeTest( |
| 125 'Method type parameter out of scope', |
| 126 matches("Type parameter '$tvarRegexp' referenced out of scope," |
| 127 " parent is: '<FunctionNode>'\\."), (TestHarness test) { |
| 90 var parameter = test.makeTypeParameter(); | 128 var parameter = test.makeTypeParameter(); |
| 91 return new Class( | 129 return new Class( |
| 92 name: 'Test', | 130 name: 'Test', |
| 93 supertype: test.objectClass.asRawSupertype, | 131 supertype: test.objectClass.asRawSupertype, |
| 94 procedures: [ | 132 procedures: [ |
| 95 new Procedure( | 133 new Procedure( |
| 96 new Name('generic'), | 134 new Name('generic'), |
| 97 ProcedureKind.Method, | 135 ProcedureKind.Method, |
| 98 new FunctionNode(new EmptyStatement(), | 136 new FunctionNode(new EmptyStatement(), |
| 99 typeParameters: [parameter])), | 137 typeParameters: [parameter])), |
| 100 new Procedure( | 138 new Procedure( |
| 101 new Name('use'), | 139 new Name('use'), |
| 102 ProcedureKind.Method, | 140 ProcedureKind.Method, |
| 103 new FunctionNode(new ReturnStatement( | 141 new FunctionNode(new ReturnStatement( |
| 104 new TypeLiteral(new TypeParameterType(parameter))))) | 142 new TypeLiteral(new TypeParameterType(parameter))))) |
| 105 ]); | 143 ]); |
| 106 }); | 144 }); |
| 107 negativeTest('Interface type arity too low', (TestHarness test) { | 145 negativeTest( |
| 146 'Interface type arity too low', |
| 147 "Type test_lib::OtherClass provides 0 type arguments" |
| 148 " but the class declares 1 parameters.", (TestHarness test) { |
| 108 return new TypeLiteral(new InterfaceType(test.otherClass, [])); | 149 return new TypeLiteral(new InterfaceType(test.otherClass, [])); |
| 109 }); | 150 }); |
| 110 negativeTest('Interface type arity too high', (TestHarness test) { | 151 negativeTest( |
| 152 'Interface type arity too high', |
| 153 "Type test_lib::OtherClass<dynamic, dynamic> provides 2 type arguments" |
| 154 " but the class declares 1 parameters.", (TestHarness test) { |
| 111 return new TypeLiteral(new InterfaceType( | 155 return new TypeLiteral(new InterfaceType( |
| 112 test.otherClass, [new DynamicType(), new DynamicType()])); | 156 test.otherClass, [new DynamicType(), new DynamicType()])); |
| 113 }); | 157 }); |
| 114 negativeTest('Dangling interface type', (TestHarness test) { | 158 negativeTest( |
| 159 'Dangling interface type', |
| 160 matches("Dangling reference to 'null::#class[0-9]+'," |
| 161 " parent is: 'null'\\."), (TestHarness test) { |
| 115 var orphan = new Class(); | 162 var orphan = new Class(); |
| 116 return new TypeLiteral(new InterfaceType(orphan)); | 163 return new TypeLiteral(new InterfaceType(orphan)); |
| 117 }); | 164 }); |
| 118 negativeTest('Dangling field get', (TestHarness test) { | 165 negativeTest('Dangling field get', |
| 166 "Dangling reference to 'null::foo', parent is: 'null'.", |
| 167 (TestHarness test) { |
| 119 var orphan = new Field(new Name('foo')); | 168 var orphan = new Field(new Name('foo')); |
| 120 return new DirectPropertyGet(new NullLiteral(), orphan); | 169 return new DirectPropertyGet(new NullLiteral(), orphan); |
| 121 }); | 170 }); |
| 122 negativeTest('Missing block parent pointer', (TestHarness test) { | 171 negativeTest( |
| 172 'Missing block parent pointer', |
| 173 "Incorrect parent pointer on ReturnStatement:" |
| 174 " expected 'Block', but found: 'Null'.", (TestHarness test) { |
| 123 var block = new Block([]); | 175 var block = new Block([]); |
| 124 block.statements.add(new ReturnStatement()); | 176 block.statements.add(new ReturnStatement()); |
| 125 return block; | 177 return block; |
| 126 }); | 178 }); |
| 127 negativeTest('Missing function parent pointer', (TestHarness test) { | 179 negativeTest( |
| 180 'Missing function parent pointer', |
| 181 "Incorrect parent pointer on FunctionNode:" |
| 182 " expected 'Procedure', but found: 'Null'.", (TestHarness test) { |
| 128 var procedure = new Procedure(new Name('bar'), ProcedureKind.Method, null); | 183 var procedure = new Procedure(new Name('bar'), ProcedureKind.Method, null); |
| 129 procedure.function = new FunctionNode(new EmptyStatement()); | 184 procedure.function = new FunctionNode(new EmptyStatement()); |
| 130 return procedure; | 185 return procedure; |
| 131 }); | 186 }); |
| 132 negativeTest('StaticGet without target', (TestHarness test) { | 187 negativeTest('StaticGet without target', "StaticGet without target.", |
| 188 (TestHarness test) { |
| 133 return new StaticGet(null); | 189 return new StaticGet(null); |
| 134 }); | 190 }); |
| 135 negativeTest('StaticSet without target', (TestHarness test) { | 191 negativeTest('StaticSet without target', "StaticSet without target.", |
| 192 (TestHarness test) { |
| 136 return new StaticSet(null, new NullLiteral()); | 193 return new StaticSet(null, new NullLiteral()); |
| 137 }); | 194 }); |
| 138 negativeTest('StaticInvocation without target', (TestHarness test) { | 195 negativeTest( |
| 196 'StaticInvocation without target', "StaticInvocation without target.", |
| 197 (TestHarness test) { |
| 139 return new StaticInvocation(null, new Arguments.empty()); | 198 return new StaticInvocation(null, new Arguments.empty()); |
| 140 }); | 199 }); |
| 141 positiveTest('Correct StaticInvocation', (TestHarness test) { | 200 positiveTest('Correct StaticInvocation', (TestHarness test) { |
| 142 var method = new Procedure( | 201 var method = new Procedure( |
| 143 new Name('foo'), | 202 new Name('foo'), |
| 144 ProcedureKind.Method, | 203 ProcedureKind.Method, |
| 145 new FunctionNode(new EmptyStatement(), | 204 new FunctionNode(new EmptyStatement(), |
| 146 positionalParameters: [new VariableDeclaration('p')]), | 205 positionalParameters: [new VariableDeclaration('p')]), |
| 147 isStatic: true); | 206 isStatic: true); |
| 148 test.enclosingClass.addMember(method); | 207 test.enclosingClass.addMember(method); |
| 149 return new StaticInvocation(method, new Arguments([new NullLiteral()])); | 208 return new StaticInvocation(method, new Arguments([new NullLiteral()])); |
| 150 }); | 209 }); |
| 151 negativeTest('StaticInvocation with too many parameters', (TestHarness test) { | 210 negativeTest( |
| 211 'StaticInvocation with too many parameters', |
| 212 "StaticInvocation with incompatible arguments for" |
| 213 " 'test_lib::TestClass::bar'.", (TestHarness test) { |
| 152 var method = new Procedure(new Name('bar'), ProcedureKind.Method, | 214 var method = new Procedure(new Name('bar'), ProcedureKind.Method, |
| 153 new FunctionNode(new EmptyStatement()), | 215 new FunctionNode(new EmptyStatement()), |
| 154 isStatic: true); | 216 isStatic: true); |
| 155 test.enclosingClass.addMember(method); | 217 test.enclosingClass.addMember(method); |
| 156 return new StaticInvocation(method, new Arguments([new NullLiteral()])); | 218 return new StaticInvocation(method, new Arguments([new NullLiteral()])); |
| 157 }); | 219 }); |
| 158 negativeTest('StaticInvocation with too few parameters', (TestHarness test) { | 220 negativeTest( |
| 221 'StaticInvocation with too few parameters', |
| 222 "StaticInvocation with incompatible arguments for" |
| 223 " 'test_lib::TestClass::bar'.", (TestHarness test) { |
| 159 var method = new Procedure( | 224 var method = new Procedure( |
| 160 new Name('bar'), | 225 new Name('bar'), |
| 161 ProcedureKind.Method, | 226 ProcedureKind.Method, |
| 162 new FunctionNode(new EmptyStatement(), | 227 new FunctionNode(new EmptyStatement(), |
| 163 positionalParameters: [new VariableDeclaration('p')]), | 228 positionalParameters: [new VariableDeclaration('p')]), |
| 164 isStatic: true); | 229 isStatic: true); |
| 165 test.enclosingClass.addMember(method); | 230 test.enclosingClass.addMember(method); |
| 166 return new StaticInvocation(method, new Arguments.empty()); | 231 return new StaticInvocation(method, new Arguments.empty()); |
| 167 }); | 232 }); |
| 168 negativeTest('StaticInvocation with unmatched named parameter', | 233 negativeTest( |
| 169 (TestHarness test) { | 234 'StaticInvocation with unmatched named parameter', |
| 235 "StaticInvocation with incompatible arguments for" |
| 236 " 'test_lib::TestClass::bar'.", (TestHarness test) { |
| 170 var method = new Procedure(new Name('bar'), ProcedureKind.Method, | 237 var method = new Procedure(new Name('bar'), ProcedureKind.Method, |
| 171 new FunctionNode(new EmptyStatement()), | 238 new FunctionNode(new EmptyStatement()), |
| 172 isStatic: true); | 239 isStatic: true); |
| 173 test.enclosingClass.addMember(method); | 240 test.enclosingClass.addMember(method); |
| 174 return new StaticInvocation( | 241 return new StaticInvocation( |
| 175 method, | 242 method, |
| 176 new Arguments([], | 243 new Arguments([], |
| 177 named: [new NamedExpression('p', new NullLiteral())])); | 244 named: [new NamedExpression('p', new NullLiteral())])); |
| 178 }); | 245 }); |
| 179 negativeTest('StaticInvocation with missing type argument', | 246 negativeTest( |
| 180 (TestHarness test) { | 247 'StaticInvocation with missing type argument', |
| 248 "StaticInvocation with wrong number of type arguments for" |
| 249 " 'test_lib::TestClass::bar'.", (TestHarness test) { |
| 181 var method = new Procedure( | 250 var method = new Procedure( |
| 182 new Name('bar'), | 251 new Name('bar'), |
| 183 ProcedureKind.Method, | 252 ProcedureKind.Method, |
| 184 new FunctionNode(new EmptyStatement(), | 253 new FunctionNode(new EmptyStatement(), |
| 185 typeParameters: [test.makeTypeParameter()]), | 254 typeParameters: [test.makeTypeParameter()]), |
| 186 isStatic: true); | 255 isStatic: true); |
| 187 test.enclosingClass.addMember(method); | 256 test.enclosingClass.addMember(method); |
| 188 return new StaticInvocation(method, new Arguments.empty()); | 257 return new StaticInvocation(method, new Arguments.empty()); |
| 189 }); | 258 }); |
| 190 negativeTest('ConstructorInvocation with missing type argument', | 259 negativeTest( |
| 191 (TestHarness test) { | 260 'ConstructorInvocation with missing type argument', |
| 261 "ConstructorInvocation with wrong number of type arguments for" |
| 262 " 'test_lib::TestClass::foo'.", (TestHarness test) { |
| 192 var class_ = new Class( | 263 var class_ = new Class( |
| 193 name: 'Test', | 264 name: 'Test', |
| 194 typeParameters: [test.makeTypeParameter()], | 265 typeParameters: [test.makeTypeParameter()], |
| 195 supertype: test.objectClass.asRawSupertype); | 266 supertype: test.objectClass.asRawSupertype); |
| 196 test.enclosingLibrary.addClass(class_); | 267 test.enclosingLibrary.addClass(class_); |
| 197 var constructor = new Constructor(new FunctionNode(new EmptyStatement()), | 268 var constructor = new Constructor(new FunctionNode(new EmptyStatement()), |
| 198 name: new Name('foo')); | 269 name: new Name('foo')); |
| 199 test.enclosingClass.addMember(constructor); | 270 test.enclosingClass.addMember(constructor); |
| 200 return new ConstructorInvocation(constructor, new Arguments.empty()); | 271 return new ConstructorInvocation(constructor, new Arguments.empty()); |
| 201 }); | 272 }); |
| (...skipping 19 matching lines...) Expand all Loading... |
| 221 var foo = new Typedef('Foo', null); | 292 var foo = new Typedef('Foo', null); |
| 222 var bar = new Typedef('Bar', null); | 293 var bar = new Typedef('Bar', null); |
| 223 foo.type = new InterfaceType(test.otherClass, [new TypedefType(bar)]); | 294 foo.type = new InterfaceType(test.otherClass, [new TypedefType(bar)]); |
| 224 bar.type = test.otherClass.rawType; | 295 bar.type = test.otherClass.rawType; |
| 225 test.enclosingLibrary.addTypedef(foo); | 296 test.enclosingLibrary.addTypedef(foo); |
| 226 test.enclosingLibrary.addTypedef(bar); | 297 test.enclosingLibrary.addTypedef(bar); |
| 227 }); | 298 }); |
| 228 positiveTest('Valid typedef type in field', (TestHarness test) { | 299 positiveTest('Valid typedef type in field', (TestHarness test) { |
| 229 var typedef_ = new Typedef( | 300 var typedef_ = new Typedef( |
| 230 'Foo', new FunctionType([test.otherClass.rawType], const VoidType())); | 301 'Foo', new FunctionType([test.otherClass.rawType], const VoidType())); |
| 231 var field = new Field(new Name('field'), type: new TypedefType(typedef_)); | 302 var field = new Field(new Name('field'), |
| 303 type: new TypedefType(typedef_), isStatic: true); |
| 232 test.enclosingLibrary.addTypedef(typedef_); | 304 test.enclosingLibrary.addTypedef(typedef_); |
| 233 test.enclosingLibrary.addMember(field); | 305 test.enclosingLibrary.addMember(field); |
| 234 }); | 306 }); |
| 235 negativeTest('Invalid typedef Foo = Foo', (TestHarness test) { | 307 negativeTest( |
| 308 'Invalid typedef Foo = Foo', |
| 309 "The typedef 'typedef Foo = test_lib::Foo;\n'" |
| 310 " refers to itself", (TestHarness test) { |
| 236 var typedef_ = new Typedef('Foo', null); | 311 var typedef_ = new Typedef('Foo', null); |
| 237 typedef_.type = new TypedefType(typedef_); | 312 typedef_.type = new TypedefType(typedef_); |
| 238 test.enclosingLibrary.addTypedef(typedef_); | 313 test.enclosingLibrary.addTypedef(typedef_); |
| 239 }); | 314 }); |
| 240 negativeTest('Invalid typedef Foo = `(Foo) => void`', (TestHarness test) { | 315 negativeTest( |
| 316 'Invalid typedef Foo = `(Foo) => void`', |
| 317 "The typedef 'typedef Foo = (test_lib::Foo) → void;\n'" |
| 318 " refers to itself", (TestHarness test) { |
| 241 var typedef_ = new Typedef('Foo', null); | 319 var typedef_ = new Typedef('Foo', null); |
| 242 typedef_.type = | 320 typedef_.type = |
| 243 new FunctionType([new TypedefType(typedef_)], const VoidType()); | 321 new FunctionType([new TypedefType(typedef_)], const VoidType()); |
| 244 test.enclosingLibrary.addTypedef(typedef_); | 322 test.enclosingLibrary.addTypedef(typedef_); |
| 245 }); | 323 }); |
| 246 negativeTest('Invalid typedef Foo = `() => Foo`', (TestHarness test) { | 324 negativeTest( |
| 325 'Invalid typedef Foo = `() => Foo`', |
| 326 "The typedef 'typedef Foo = () → test_lib::Foo;\n'" |
| 327 " refers to itself", (TestHarness test) { |
| 247 var typedef_ = new Typedef('Foo', null); | 328 var typedef_ = new Typedef('Foo', null); |
| 248 typedef_.type = new FunctionType([], new TypedefType(typedef_)); | 329 typedef_.type = new FunctionType([], new TypedefType(typedef_)); |
| 249 test.enclosingLibrary.addTypedef(typedef_); | 330 test.enclosingLibrary.addTypedef(typedef_); |
| 250 }); | 331 }); |
| 251 negativeTest('Invalid typedef Foo = C<Foo>', (TestHarness test) { | 332 negativeTest( |
| 333 'Invalid typedef Foo = C<Foo>', |
| 334 "The typedef 'typedef Foo = test_lib::OtherClass<test_lib::Foo>;\n'" |
| 335 " refers to itself", (TestHarness test) { |
| 252 var typedef_ = new Typedef('Foo', null); | 336 var typedef_ = new Typedef('Foo', null); |
| 253 typedef_.type = | 337 typedef_.type = |
| 254 new InterfaceType(test.otherClass, [new TypedefType(typedef_)]); | 338 new InterfaceType(test.otherClass, [new TypedefType(typedef_)]); |
| 255 test.enclosingLibrary.addTypedef(typedef_); | 339 test.enclosingLibrary.addTypedef(typedef_); |
| 256 }); | 340 }); |
| 257 negativeTest('Invalid typedefs Foo = Bar, Bar = Foo', (TestHarness test) { | 341 negativeTest( |
| 342 'Invalid typedefs Foo = Bar, Bar = Foo', |
| 343 "The typedef 'typedef Foo = test_lib::Bar;\n'" |
| 344 " refers to itself", (TestHarness test) { |
| 258 var foo = new Typedef('Foo', null); | 345 var foo = new Typedef('Foo', null); |
| 259 var bar = new Typedef('Bar', null); | 346 var bar = new Typedef('Bar', null); |
| 260 foo.type = new TypedefType(bar); | 347 foo.type = new TypedefType(bar); |
| 261 bar.type = new TypedefType(foo); | 348 bar.type = new TypedefType(foo); |
| 262 test.enclosingLibrary.addTypedef(foo); | 349 test.enclosingLibrary.addTypedef(foo); |
| 263 test.enclosingLibrary.addTypedef(bar); | 350 test.enclosingLibrary.addTypedef(bar); |
| 264 }); | 351 }); |
| 265 negativeTest('Invalid typedefs Foo = Bar, Bar = C<Foo>', (TestHarness test) { | 352 negativeTest( |
| 353 'Invalid typedefs Foo = Bar, Bar = C<Foo>', |
| 354 "The typedef 'typedef Foo = test_lib::Bar;\n'" |
| 355 " refers to itself", (TestHarness test) { |
| 266 var foo = new Typedef('Foo', null); | 356 var foo = new Typedef('Foo', null); |
| 267 var bar = new Typedef('Bar', null); | 357 var bar = new Typedef('Bar', null); |
| 268 foo.type = new TypedefType(bar); | 358 foo.type = new TypedefType(bar); |
| 269 bar.type = new InterfaceType(test.otherClass, [new TypedefType(foo)]); | 359 bar.type = new InterfaceType(test.otherClass, [new TypedefType(foo)]); |
| 270 test.enclosingLibrary.addTypedef(foo); | 360 test.enclosingLibrary.addTypedef(foo); |
| 271 test.enclosingLibrary.addTypedef(bar); | 361 test.enclosingLibrary.addTypedef(bar); |
| 272 }); | 362 }); |
| 273 negativeTest('Invalid typedefs Foo = C<Bar>, Bar = C<Foo>', | 363 negativeTest( |
| 274 (TestHarness test) { | 364 'Invalid typedefs Foo = C<Bar>, Bar = C<Foo>', |
| 365 "The typedef 'typedef Foo = test_lib::OtherClass<test_lib::Bar>;\n'" |
| 366 " refers to itself", (TestHarness test) { |
| 275 var foo = new Typedef('Foo', null); | 367 var foo = new Typedef('Foo', null); |
| 276 var bar = new Typedef('Bar', null); | 368 var bar = new Typedef('Bar', null); |
| 277 foo.type = new InterfaceType(test.otherClass, [new TypedefType(bar)]); | 369 foo.type = new InterfaceType(test.otherClass, [new TypedefType(bar)]); |
| 278 bar.type = new InterfaceType(test.otherClass, [new TypedefType(foo)]); | 370 bar.type = new InterfaceType(test.otherClass, [new TypedefType(foo)]); |
| 279 test.enclosingLibrary.addTypedef(foo); | 371 test.enclosingLibrary.addTypedef(foo); |
| 280 test.enclosingLibrary.addTypedef(bar); | 372 test.enclosingLibrary.addTypedef(bar); |
| 281 }); | 373 }); |
| 282 positiveTest('Valid long typedefs C20 = C19 = ... = C1 = C0 = dynamic', | 374 positiveTest('Valid long typedefs C20 = C19 = ... = C1 = C0 = dynamic', |
| 283 (TestHarness test) { | 375 (TestHarness test) { |
| 284 var typedef_ = new Typedef('C0', const DynamicType()); | 376 var typedef_ = new Typedef('C0', const DynamicType()); |
| 285 test.enclosingLibrary.addTypedef(typedef_); | 377 test.enclosingLibrary.addTypedef(typedef_); |
| 286 for (int i = 1; i < 20; ++i) { | 378 for (int i = 1; i < 20; ++i) { |
| 287 typedef_ = new Typedef('C$i', new TypedefType(typedef_)); | 379 typedef_ = new Typedef('C$i', new TypedefType(typedef_)); |
| 288 test.enclosingLibrary.addTypedef(typedef_); | 380 test.enclosingLibrary.addTypedef(typedef_); |
| 289 } | 381 } |
| 290 }); | 382 }); |
| 291 negativeTest('Invalid long typedefs C20 = C19 = ... = C1 = C0 = C20', | 383 negativeTest( |
| 292 (TestHarness test) { | 384 'Invalid long typedefs C20 = C19 = ... = C1 = C0 = C20', |
| 385 "The typedef 'typedef C0 = test_lib::C19;\n'" |
| 386 " refers to itself", (TestHarness test) { |
| 293 var typedef_ = new Typedef('C0', null); | 387 var typedef_ = new Typedef('C0', null); |
| 294 test.enclosingLibrary.addTypedef(typedef_); | 388 test.enclosingLibrary.addTypedef(typedef_); |
| 295 var first = typedef_; | 389 var first = typedef_; |
| 296 for (int i = 1; i < 20; ++i) { | 390 for (int i = 1; i < 20; ++i) { |
| 297 typedef_ = new Typedef('C$i', new TypedefType(typedef_)); | 391 typedef_ = new Typedef('C$i', new TypedefType(typedef_)); |
| 298 test.enclosingLibrary.addTypedef(typedef_); | 392 test.enclosingLibrary.addTypedef(typedef_); |
| 299 } | 393 } |
| 300 first.type = new TypedefType(typedef_); | 394 first.type = new TypedefType(typedef_); |
| 301 }); | 395 }); |
| 302 positiveTest('Valid typedef Foo<T extends C> = C<T>', (TestHarness test) { | 396 positiveTest('Valid typedef Foo<T extends C> = C<T>', (TestHarness test) { |
| (...skipping 18 matching lines...) Expand all Loading... |
| 321 var foo = | 415 var foo = |
| 322 new Typedef('Foo', const DynamicType(), typeParameters: [fooParam]); | 416 new Typedef('Foo', const DynamicType(), typeParameters: [fooParam]); |
| 323 var barParam = new TypeParameter('T', null); | 417 var barParam = new TypeParameter('T', null); |
| 324 barParam.bound = new TypedefType(foo, [new TypeParameterType(barParam)]); | 418 barParam.bound = new TypedefType(foo, [new TypeParameterType(barParam)]); |
| 325 var bar = new Typedef('Bar', | 419 var bar = new Typedef('Bar', |
| 326 new InterfaceType(test.otherClass, [new TypeParameterType(barParam)]), | 420 new InterfaceType(test.otherClass, [new TypeParameterType(barParam)]), |
| 327 typeParameters: [barParam]); | 421 typeParameters: [barParam]); |
| 328 test.enclosingLibrary.addTypedef(foo); | 422 test.enclosingLibrary.addTypedef(foo); |
| 329 test.enclosingLibrary.addTypedef(bar); | 423 test.enclosingLibrary.addTypedef(bar); |
| 330 }); | 424 }); |
| 331 negativeTest('Invalid typedefs Foo<T extends Bar<T>>, Bar<T extends Foo<T>>', | 425 negativeTest( |
| 332 (TestHarness test) { | 426 'Invalid typedefs Foo<T extends Bar<T>>, Bar<T extends Foo<T>>', |
| 427 "The typedef 'typedef Foo<T extends test_lib::Bar<T>> = dynamic;\n'" |
| 428 " refers to itself", (TestHarness test) { |
| 333 var fooParam = test.makeTypeParameter('T'); | 429 var fooParam = test.makeTypeParameter('T'); |
| 334 var foo = | 430 var foo = |
| 335 new Typedef('Foo', const DynamicType(), typeParameters: [fooParam]); | 431 new Typedef('Foo', const DynamicType(), typeParameters: [fooParam]); |
| 336 var barParam = new TypeParameter('T', null); | 432 var barParam = new TypeParameter('T', null); |
| 337 barParam.bound = new TypedefType(foo, [new TypeParameterType(barParam)]); | 433 barParam.bound = new TypedefType(foo, [new TypeParameterType(barParam)]); |
| 338 var bar = new Typedef('Bar', | 434 var bar = new Typedef('Bar', |
| 339 new InterfaceType(test.otherClass, [new TypeParameterType(barParam)]), | 435 new InterfaceType(test.otherClass, [new TypeParameterType(barParam)]), |
| 340 typeParameters: [barParam]); | 436 typeParameters: [barParam]); |
| 341 fooParam.bound = new TypedefType(bar, [new TypeParameterType(fooParam)]); | 437 fooParam.bound = new TypedefType(bar, [new TypeParameterType(fooParam)]); |
| 342 test.enclosingLibrary.addTypedef(foo); | 438 test.enclosingLibrary.addTypedef(foo); |
| 343 test.enclosingLibrary.addTypedef(bar); | 439 test.enclosingLibrary.addTypedef(bar); |
| 344 }); | 440 }); |
| 345 negativeTest('Invalid typedef Foo<T extends Foo<dynamic> = C<T>', | 441 negativeTest( |
| 346 (TestHarness test) { | 442 'Invalid typedef Foo<T extends Foo<dynamic> = C<T>', |
| 443 "The typedef 'typedef Foo<T extends test_lib::Foo<dynamic>> = " |
| 444 "test_lib::OtherClass<T>;\n'" |
| 445 " refers to itself", (TestHarness test) { |
| 347 var param = new TypeParameter('T', null); | 446 var param = new TypeParameter('T', null); |
| 348 var foo = new Typedef('Foo', | 447 var foo = new Typedef('Foo', |
| 349 new InterfaceType(test.otherClass, [new TypeParameterType(param)]), | 448 new InterfaceType(test.otherClass, [new TypeParameterType(param)]), |
| 350 typeParameters: [param]); | 449 typeParameters: [param]); |
| 351 param.bound = new TypedefType(foo, [const DynamicType()]); | 450 param.bound = new TypedefType(foo, [const DynamicType()]); |
| 352 test.enclosingLibrary.addTypedef(foo); | 451 test.enclosingLibrary.addTypedef(foo); |
| 353 }); | 452 }); |
| 354 negativeTest('Typedef arity error', (TestHarness test) { | 453 negativeTest( |
| 454 'Typedef arity error', |
| 455 "The typedef type test_lib::Foo provides 0 type arguments" |
| 456 " but the typedef declares 1 parameters.", (TestHarness test) { |
| 355 var param = test.makeTypeParameter('T'); | 457 var param = test.makeTypeParameter('T'); |
| 356 var foo = | 458 var foo = |
| 357 new Typedef('Foo', test.otherClass.rawType, typeParameters: [param]); | 459 new Typedef('Foo', test.otherClass.rawType, typeParameters: [param]); |
| 358 var field = new Field(new Name('field'), type: new TypedefType(foo, [])); | 460 var field = new Field(new Name('field'), |
| 461 type: new TypedefType(foo, []), isStatic: true); |
| 359 test.enclosingLibrary.addTypedef(foo); | 462 test.enclosingLibrary.addTypedef(foo); |
| 360 test.enclosingLibrary.addMember(field); | 463 test.enclosingLibrary.addMember(field); |
| 361 }); | 464 }); |
| 362 negativeTest('Dangling typedef reference', (TestHarness test) { | 465 negativeTest( |
| 466 'Dangling typedef reference', |
| 467 "Dangling reference to 'typedef Foo = test_lib::OtherClass<dynamic>;\n'" |
| 468 ", parent is: 'null'", (TestHarness test) { |
| 363 var foo = new Typedef('Foo', test.otherClass.rawType, typeParameters: []); | 469 var foo = new Typedef('Foo', test.otherClass.rawType, typeParameters: []); |
| 364 var field = new Field(new Name('field'), type: new TypedefType(foo, [])); | 470 var field = new Field(new Name('field'), |
| 471 type: new TypedefType(foo, []), isStatic: true); |
| 472 test.enclosingLibrary.addMember(field); |
| 473 }); |
| 474 negativeTest('Non-static top-level field', |
| 475 "The top-level field 'field' should be static", (TestHarness test) { |
| 476 var field = new Field(new Name('field')); |
| 365 test.enclosingLibrary.addMember(field); | 477 test.enclosingLibrary.addMember(field); |
| 366 }); | 478 }); |
| 367 } | 479 } |
| 368 | 480 |
| 369 checkHasError(Program program) { | 481 checkHasError(Program program, Matcher matcher) { |
| 370 bool passed = false; | |
| 371 try { | 482 try { |
| 372 verifyProgram(program); | 483 verifyProgram(program); |
| 373 passed = true; | 484 } on VerificationError catch (e) { |
| 374 } catch (e) {} | 485 expect(e.details, matcher); |
| 375 if (passed) { | 486 return; |
| 376 fail('Failed to reject invalid program:\n${programToString(program)}'); | |
| 377 } | 487 } |
| 488 fail('Failed to reject invalid program:\n${programToString(program)}'); |
| 378 } | 489 } |
| 379 | 490 |
| 380 class TestHarness { | 491 class TestHarness { |
| 381 Program program; | 492 Program program; |
| 382 Class objectClass; | 493 Class objectClass; |
| 383 Library stubLibrary; | 494 Library stubLibrary; |
| 384 | 495 |
| 385 TypeParameter classTypeParameter; | 496 TypeParameter classTypeParameter; |
| 386 | 497 |
| 387 Library enclosingLibrary; | 498 Library enclosingLibrary; |
| (...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 453 new FunctionNode(new EmptyStatement())); | 564 new FunctionNode(new EmptyStatement())); |
| 454 enclosingClass.addMember(enclosingMember); | 565 enclosingClass.addMember(enclosingMember); |
| 455 otherClass = new Class( | 566 otherClass = new Class( |
| 456 name: 'OtherClass', | 567 name: 'OtherClass', |
| 457 typeParameters: [makeTypeParameter('OtherT')], | 568 typeParameters: [makeTypeParameter('OtherT')], |
| 458 supertype: objectClass.asRawSupertype); | 569 supertype: objectClass.asRawSupertype); |
| 459 enclosingLibrary.addClass(otherClass); | 570 enclosingLibrary.addClass(otherClass); |
| 460 } | 571 } |
| 461 } | 572 } |
| 462 | 573 |
| 463 negativeTest(String name, TreeNode makeTestCase(TestHarness test)) { | 574 negativeTest(String name, matcher, TreeNode makeTestCase(TestHarness test)) { |
| 575 if (matcher is String) { |
| 576 matcher = equals(matcher); |
| 577 } |
| 464 test(name, () { | 578 test(name, () { |
| 465 var test = new TestHarness(); | 579 var test = new TestHarness(); |
| 466 test.addNode(makeTestCase(test)); | 580 test.addNode(makeTestCase(test)); |
| 467 checkHasError(test.program); | 581 checkHasError(test.program, matcher); |
| 468 }); | 582 }); |
| 469 } | 583 } |
| 470 | 584 |
| 471 positiveTest(String name, TreeNode makeTestCase(TestHarness test)) { | 585 positiveTest(String name, TreeNode makeTestCase(TestHarness test)) { |
| 472 test(name, () { | 586 test(name, () { |
| 473 var test = new TestHarness(); | 587 var test = new TestHarness(); |
| 474 test.addNode(makeTestCase(test)); | 588 test.addNode(makeTestCase(test)); |
| 475 verifyProgram(test.program); | 589 verifyProgram(test.program); |
| 476 }); | 590 }); |
| 477 } | 591 } |
| OLD | NEW |