Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(50)

Side by Side Diff: pkg/kernel/test/verify_test.dart

Issue 2665723002: Implement canonical name scheme in kernel. (Closed)
Patch Set: Address comments Created 3 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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 import 'package:kernel/ast.dart'; 4 import 'package:kernel/ast.dart';
5 import 'package:kernel/text/ast_to_text.dart'; 5 import 'package:kernel/text/ast_to_text.dart';
6 import 'package:kernel/verifier.dart'; 6 import 'package:kernel/verifier.dart';
7 import 'package:test/test.dart'; 7 import 'package:test/test.dart';
8 8
9 /// Checks that the verifier correctly find errors in invalid programs. 9 /// Checks that the verifier correctly find errors in invalid programs.
10 /// 10 ///
11 /// The frontend should never generate invalid programs, so we have to test 11 /// The frontend should never generate invalid programs, so we have to test
12 /// these by manually constructing invalid ASTs. 12 /// these by manually constructing invalid ASTs.
13 /// 13 ///
14 /// We mostly test negative cases here, as we get plenty of positive cases by 14 /// We mostly test negative cases here, as we get plenty of positive cases by
15 /// compiling the Dart test suite with the verifier enabled. 15 /// compiling the Dart test suite with the verifier enabled.
16 main() { 16 main() {
17 positiveTest('Test harness has no errors', () { 17 positiveTest('Test harness has no errors', (TestHarness test) {
18 return new NullLiteral(); 18 return new NullLiteral();
19 }); 19 });
20 negativeTest('VariableGet out of scope', () { 20 negativeTest('VariableGet out of scope', (TestHarness test) {
21 return new VariableGet(makeVariable()); 21 return new VariableGet(test.makeVariable());
22 }); 22 });
23 negativeTest('VariableSet out of scope', () { 23 negativeTest('VariableSet out of scope', (TestHarness test) {
24 return new VariableSet(makeVariable(), new NullLiteral()); 24 return new VariableSet(test.makeVariable(), new NullLiteral());
25 }); 25 });
26 negativeTest('Variable block scope', () { 26 negativeTest('Variable block scope', (TestHarness test) {
27 VariableDeclaration variable = makeVariable(); 27 VariableDeclaration variable = test.makeVariable();
28 return new Block([ 28 return new Block([
29 new Block([variable]), 29 new Block([variable]),
30 new ReturnStatement(new VariableGet(variable)) 30 new ReturnStatement(new VariableGet(variable))
31 ]); 31 ]);
32 }); 32 });
33 negativeTest('Variable let scope', () { 33 negativeTest('Variable let scope', (TestHarness test) {
34 VariableDeclaration variable = makeVariable(); 34 VariableDeclaration variable = test.makeVariable();
35 return new LogicalExpression(new Let(variable, new VariableGet(variable)), 35 return new LogicalExpression(new Let(variable, new VariableGet(variable)),
36 '&&', new VariableGet(variable)); 36 '&&', new VariableGet(variable));
37 }); 37 });
38 negativeTest('Variable redeclared', () { 38 negativeTest('Variable redeclared', (TestHarness test) {
39 VariableDeclaration variable = makeVariable(); 39 VariableDeclaration variable = test.makeVariable();
40 return new Block([variable, variable]); 40 return new Block([variable, variable]);
41 }); 41 });
42 negativeTest('Member redeclared', () { 42 negativeTest('Member redeclared', (TestHarness test) {
43 Field field = new Field(new Name('field'), initializer: new NullLiteral()); 43 Field field = new Field(new Name('field'), initializer: new NullLiteral());
44 return new Class( 44 return new Class(
45 name: 'Test', 45 name: 'Test',
46 supertype: objectClass.asRawSupertype, 46 supertype: test.objectClass.asRawSupertype,
47 fields: [field, field]); 47 fields: [field, field]);
48 }); 48 });
49 negativeTest('Class redeclared', () { 49 negativeTest('Class redeclared', (TestHarness test) {
50 return otherClass; // Test harness also adds otherClass to program. 50 return test.otherClass; // Test harness also adds otherClass to program.
51 }); 51 });
52 negativeTest('Class type parameter redeclared', () { 52 negativeTest('Class type parameter redeclared', (TestHarness test) {
53 var parameter = makeTypeParameter(); 53 var parameter = test.makeTypeParameter();
54 return new Class( 54 return new Class(
55 name: 'Test', 55 name: 'Test',
56 supertype: objectClass.asRawSupertype, 56 supertype: test.objectClass.asRawSupertype,
57 typeParameters: [parameter, parameter]); 57 typeParameters: [parameter, parameter]);
58 }); 58 });
59 negativeTest('Member type parameter redeclared', () { 59 negativeTest('Member type parameter redeclared', (TestHarness test) {
60 var parameter = makeTypeParameter(); 60 var parameter = test.makeTypeParameter();
61 return new Procedure( 61 return new Procedure(
62 new Name('test'), 62 new Name('bar'),
63 ProcedureKind.Method, 63 ProcedureKind.Method,
64 new FunctionNode(new ReturnStatement(new NullLiteral()), 64 new FunctionNode(new ReturnStatement(new NullLiteral()),
65 typeParameters: [parameter, parameter])); 65 typeParameters: [parameter, parameter]));
66 }); 66 });
67 negativeTest('Type parameter out of scope', () { 67 negativeTest('Type parameter out of scope', (TestHarness test) {
68 var parameter = makeTypeParameter(); 68 var parameter = test.makeTypeParameter();
69 return new ListLiteral([], typeArgument: new TypeParameterType(parameter)); 69 return new ListLiteral([], typeArgument: new TypeParameterType(parameter));
70 }); 70 });
71 negativeTest('Class type parameter from another class', () { 71 negativeTest('Class type parameter from another class', (TestHarness test) {
72 return new TypeLiteral(new TypeParameterType(otherClass.typeParameters[0])); 72 return new TypeLiteral(
73 new TypeParameterType(test.otherClass.typeParameters[0]));
73 }); 74 });
74 negativeTest('Class type parameter in static method', () { 75 negativeTest('Class type parameter in static method', (TestHarness test) {
75 return new Procedure( 76 return new Procedure(
76 new Name('test'), 77 new Name('bar'),
77 ProcedureKind.Method, 78 ProcedureKind.Method,
78 new FunctionNode(new ReturnStatement( 79 new FunctionNode(new ReturnStatement(
79 new TypeLiteral(new TypeParameterType(classTypeParameter)))), 80 new TypeLiteral(new TypeParameterType(test.classTypeParameter)))),
80 isStatic: true); 81 isStatic: true);
81 }); 82 });
82 negativeTest('Class type parameter in static field', () { 83 negativeTest('Class type parameter in static field', (TestHarness test) {
83 return new Field(new Name('field'), 84 return new Field(new Name('field'),
84 initializer: new TypeLiteral(new TypeParameterType(classTypeParameter)), 85 initializer:
86 new TypeLiteral(new TypeParameterType(test.classTypeParameter)),
85 isStatic: true); 87 isStatic: true);
86 }); 88 });
87 negativeTest('Method type parameter out of scope', () { 89 negativeTest('Method type parameter out of scope', (TestHarness test) {
88 var parameter = makeTypeParameter(); 90 var parameter = test.makeTypeParameter();
89 return new Class( 91 return new Class(
90 name: 'Test', 92 name: 'Test',
91 supertype: objectClass.asRawSupertype, 93 supertype: test.objectClass.asRawSupertype,
92 procedures: [ 94 procedures: [
93 new Procedure( 95 new Procedure(
94 new Name('generic'), 96 new Name('generic'),
95 ProcedureKind.Method, 97 ProcedureKind.Method,
96 new FunctionNode(new EmptyStatement(), 98 new FunctionNode(new EmptyStatement(),
97 typeParameters: [parameter])), 99 typeParameters: [parameter])),
98 new Procedure( 100 new Procedure(
99 new Name('use'), 101 new Name('use'),
100 ProcedureKind.Method, 102 ProcedureKind.Method,
101 new FunctionNode(new ReturnStatement( 103 new FunctionNode(new ReturnStatement(
102 new TypeLiteral(new TypeParameterType(parameter))))) 104 new TypeLiteral(new TypeParameterType(parameter)))))
103 ]); 105 ]);
104 }); 106 });
105 negativeTest('Interface type arity too low', () { 107 negativeTest('Interface type arity too low', (TestHarness test) {
106 return new TypeLiteral(new InterfaceType(otherClass, [])); 108 return new TypeLiteral(new InterfaceType(test.otherClass, []));
107 }); 109 });
108 negativeTest('Interface type arity too high', () { 110 negativeTest('Interface type arity too high', (TestHarness test) {
109 return new TypeLiteral( 111 return new TypeLiteral(new InterfaceType(
110 new InterfaceType(otherClass, [new DynamicType(), new DynamicType()])); 112 test.otherClass, [new DynamicType(), new DynamicType()]));
111 }); 113 });
112 negativeTest('Dangling interface type', () { 114 negativeTest('Dangling interface type', (TestHarness test) {
113 return new TypeLiteral(new InterfaceType(new Class())); 115 var orphan = new Class();
116 test.enclosingLibrary.canonicalName.getChild('foo').bindTo(orphan);
117 return new TypeLiteral(new InterfaceType(orphan));
114 }); 118 });
115 negativeTest('Dangling field get', () { 119 negativeTest('Dangling field get', (TestHarness test) {
116 return new DirectPropertyGet(new NullLiteral(), new Field(new Name('foo'))); 120 var orphan = new Field(new Name('foo'));
121 test.enclosingLibrary.canonicalName.getChild('foo').bindTo(orphan);
122 return new DirectPropertyGet(new NullLiteral(), orphan);
117 }); 123 });
118 negativeTest('Missing block parent pointer', () { 124 negativeTest('Missing block parent pointer', (TestHarness test) {
119 var block = new Block([]); 125 var block = new Block([]);
120 block.statements.add(new ReturnStatement()); 126 block.statements.add(new ReturnStatement());
121 return block; 127 return block;
122 }); 128 });
123 negativeTest('Missing function parent pointer', () { 129 negativeTest('Missing function parent pointer', (TestHarness test) {
124 var procedure = new Procedure(new Name('test'), ProcedureKind.Method, null); 130 var procedure = new Procedure(new Name('bar'), ProcedureKind.Method, null);
125 procedure.function = new FunctionNode(new EmptyStatement()); 131 procedure.function = new FunctionNode(new EmptyStatement());
126 return procedure; 132 return procedure;
127 }); 133 });
128 negativeTest('StaticGet without target', () { 134 negativeTest('StaticGet without target', (TestHarness test) {
129 return new StaticGet(null); 135 return new StaticGet(null);
130 }); 136 });
131 negativeTest('StaticSet without target', () { 137 negativeTest('StaticSet without target', (TestHarness test) {
132 return new StaticSet(null, new NullLiteral()); 138 return new StaticSet(null, new NullLiteral());
133 }); 139 });
134 negativeTest('StaticInvocation without target', () { 140 negativeTest('StaticInvocation without target', (TestHarness test) {
135 return new StaticInvocation(null, new Arguments.empty()); 141 return new StaticInvocation(null, new Arguments.empty());
136 }); 142 });
137 positiveTest('Correct StaticInvocation', () { 143 positiveTest('Correct StaticInvocation', (TestHarness test) {
138 var method = new Procedure(new Name('test'), ProcedureKind.Method, null, 144 var method = new Procedure(
145 new Name('foo'),
146 ProcedureKind.Method,
147 new FunctionNode(new EmptyStatement(),
148 positionalParameters: [new VariableDeclaration('p')]),
139 isStatic: true); 149 isStatic: true);
140 method.function = new FunctionNode( 150 test.enclosingClass.addMember(method);
141 new ReturnStatement( 151 return new StaticInvocation(method, new Arguments([new NullLiteral()]));
142 new StaticInvocation(method, new Arguments([new NullLiteral()]))),
143 positionalParameters: [new VariableDeclaration('p')])..parent = method;
144 return new Class(
145 name: 'Test',
146 supertype: objectClass.asRawSupertype,
147 procedures: [method]);
148 }); 152 });
149 negativeTest('StaticInvocation with too many parameters', () { 153 negativeTest('StaticInvocation with too many parameters', (TestHarness test) {
150 var method = new Procedure(new Name('test'), ProcedureKind.Method, null, 154 var method = new Procedure(new Name('bar'), ProcedureKind.Method,
155 new FunctionNode(new EmptyStatement()),
151 isStatic: true); 156 isStatic: true);
152 method.function = new FunctionNode(new ReturnStatement( 157 test.enclosingClass.addMember(method);
153 new StaticInvocation(method, new Arguments([new NullLiteral()])))) 158 return new StaticInvocation(method, new Arguments([new NullLiteral()]));
154 ..parent = method;
155 return new Class(
156 name: 'Test',
157 supertype: objectClass.asRawSupertype,
158 procedures: [method]);
159 }); 159 });
160 negativeTest('StaticInvocation with too few parameters', () { 160 negativeTest('StaticInvocation with too few parameters', (TestHarness test) {
161 var method = new Procedure(new Name('test'), ProcedureKind.Method, null, 161 var method = new Procedure(
162 new Name('bar'),
163 ProcedureKind.Method,
164 new FunctionNode(new EmptyStatement(),
165 positionalParameters: [new VariableDeclaration('p')]),
162 isStatic: true); 166 isStatic: true);
163 method.function = new FunctionNode( 167 test.enclosingClass.addMember(method);
164 new ReturnStatement( 168 return new StaticInvocation(method, new Arguments.empty());
165 new StaticInvocation(method, new Arguments.empty())),
166 positionalParameters: [new VariableDeclaration('p')])..parent = method;
167 return new Class(
168 name: 'Test',
169 supertype: objectClass.asRawSupertype,
170 procedures: [method]);
171 }); 169 });
172 negativeTest('StaticInvocation with unmatched named parameter', () { 170 negativeTest('StaticInvocation with unmatched named parameter',
173 var method = new Procedure(new Name('test'), ProcedureKind.Method, null, 171 (TestHarness test) {
172 var method = new Procedure(new Name('bar'), ProcedureKind.Method,
173 new FunctionNode(new EmptyStatement()),
174 isStatic: true); 174 isStatic: true);
175 method.function = new FunctionNode(new ReturnStatement(new StaticInvocation( 175 test.enclosingClass.addMember(method);
176 return new StaticInvocation(
176 method, 177 method,
177 new Arguments([], 178 new Arguments([],
178 named: [new NamedExpression('p', new NullLiteral())])))) 179 named: [new NamedExpression('p', new NullLiteral())]));
179 ..parent = method; 180 });
180 return new Class( 181 negativeTest('StaticInvocation with missing type argument',
182 (TestHarness test) {
183 var method = new Procedure(
184 new Name('bar'),
185 ProcedureKind.Method,
186 new FunctionNode(new EmptyStatement(),
187 typeParameters: [test.makeTypeParameter()]),
188 isStatic: true);
189 test.enclosingClass.addMember(method);
190 return new StaticInvocation(method, new Arguments.empty());
191 });
192 negativeTest('ConstructorInvocation with missing type argument',
193 (TestHarness test) {
194 var class_ = new Class(
181 name: 'Test', 195 name: 'Test',
182 supertype: objectClass.asRawSupertype, 196 typeParameters: [test.makeTypeParameter()],
183 procedures: [method]); 197 supertype: test.objectClass.asRawSupertype);
184 }); 198 test.enclosingLibrary.addClass(class_);
185 negativeTest('StaticInvocation with missing type argument', () { 199 var constructor = new Constructor(new FunctionNode(new EmptyStatement()),
186 var method = new Procedure(new Name('test'), ProcedureKind.Method, null, 200 name: new Name('foo'));
187 isStatic: true); 201 test.enclosingClass.addMember(constructor);
188 method.function = new FunctionNode( 202 return new ConstructorInvocation(constructor, new Arguments.empty());
189 new ReturnStatement(
190 new StaticInvocation(method, new Arguments.empty())),
191 typeParameters: [makeTypeParameter()])..parent = method;
192 return new Class(
193 name: 'Test',
194 supertype: objectClass.asRawSupertype,
195 procedures: [method]);
196 });
197 negativeTest('ConstructorInvocation with missing type argument', () {
198 var constructor = new Constructor(null);
199 constructor.function = new FunctionNode(new ReturnStatement(
200 new ConstructorInvocation(constructor, new Arguments.empty())))
201 ..parent = constructor;
202 return new Class(
203 name: 'Test',
204 typeParameters: [makeTypeParameter()],
205 supertype: objectClass.asRawSupertype,
206 constructors: [constructor]);
207 }); 203 });
208 } 204 }
209 205
210 checkHasError(Program program) { 206 checkHasError(Program program) {
211 bool passed = false; 207 bool passed = false;
212 try { 208 try {
213 verifyProgram(program); 209 verifyProgram(program);
214 passed = true; 210 passed = true;
215 } catch (e) {} 211 } catch (e) {}
216 if (passed) { 212 if (passed) {
217 fail('Failed to reject invalid program:\n${programToString(program)}'); 213 fail('Failed to reject invalid program:\n${programToString(program)}');
218 } 214 }
219 } 215 }
220 216
221 Class objectClass = new Class(name: 'Object'); 217 class TestHarness {
218 void addNode(TreeNode node) {
219 if (node is Expression) {
220 addExpression(node);
221 } else if (node is Statement) {
222 addStatement(node);
223 } else if (node is Member) {
224 addClassMember(node);
225 } else if (node is Class) {
226 addClass(node);
227 }
228 }
222 229
223 Library stubLibrary = new Library(Uri.parse('dart:core')) 230 void addExpression(Expression node) {
224 ..addClass(objectClass); 231 addStatement(new ReturnStatement(node));
232 }
225 233
226 TypeParameter classTypeParameter = makeTypeParameter('T'); 234 void addStatement(Statement node) {
235 var function = enclosingMember.function;
236 function.body = node..parent = function;
237 }
227 238
228 Class otherClass = new Class( 239 void addClassMember(Member node) {
229 name: 'OtherClass', 240 enclosingClass.addMember(node);
230 typeParameters: [makeTypeParameter('OtherT')], 241 }
231 supertype: objectClass.asRawSupertype);
232 242
233 Program makeProgram(TreeNode makeBody()) { 243 void addTopLevelMember(Member node) {
234 var node = makeBody(); 244 enclosingLibrary.addMember(node);
235 if (node is Expression) {
236 node = new ReturnStatement(node);
237 } 245 }
238 if (node is Statement) { 246
239 node = new FunctionNode(node); 247 void addClass(Class node) {
248 enclosingLibrary.addClass(node);
240 } 249 }
241 if (node is FunctionNode) { 250
242 node = new Procedure(new Name('test'), ProcedureKind.Method, node); 251 VariableDeclaration makeVariable() => new VariableDeclaration(null);
252
253 TypeParameter makeTypeParameter([String name]) {
254 return new TypeParameter(name, new InterfaceType(objectClass));
243 } 255 }
244 if (node is Member) { 256
245 node = new Class( 257 Program program;
ahe 2017/02/02 16:24:01 It always confuses me when fields aren't first in
asgerf 2017/02/03 10:31:16 Fixed.
246 name: 'Test', 258 Class objectClass;
259 Library stubLibrary;
260
261 TypeParameter classTypeParameter;
262
263 Library enclosingLibrary;
264 Class enclosingClass;
265 Procedure enclosingMember;
266
267 Class otherClass;
268
269 TestHarness() {
270 setupProgram();
271 }
272
273 void setupProgram() {
274 program = new Program();
275 stubLibrary = program.getLibraryReference(Uri.parse('dart:core'));
276 stubLibrary.name = 'dart.core';
277 objectClass = new Class(name: 'Object');
278 stubLibrary.addClass(objectClass);
279 enclosingLibrary =
280 program.getLibraryReference(Uri.parse('file://test.dart'));
281 enclosingLibrary.name = 'test_lib';
282 classTypeParameter = makeTypeParameter('T');
283 enclosingClass = new Class(
284 name: 'TestClass',
247 typeParameters: [classTypeParameter], 285 typeParameters: [classTypeParameter],
248 supertype: objectClass.asRawSupertype)..addMember(node); 286 supertype: objectClass.asRawSupertype);
287 enclosingLibrary.addClass(enclosingClass);
288 enclosingMember = new Procedure(new Name('test'), ProcedureKind.Method,
289 new FunctionNode(new EmptyStatement()));
290 enclosingClass.addMember(enclosingMember);
291 otherClass = new Class(
292 name: 'OtherClass',
293 typeParameters: [makeTypeParameter('OtherT')],
294 supertype: objectClass.asRawSupertype);
295 enclosingLibrary.addClass(otherClass);
249 } 296 }
250 if (node is Class) {
251 node =
252 new Library(Uri.parse('test.dart'), classes: <Class>[node, otherClass]);
253 }
254 if (node is Library) {
255 node = new Program(<Library>[node, stubLibrary]);
256 }
257 assert(node is Program);
258 return node;
259 } 297 }
260 298
261 negativeTest(String name, TreeNode makeBody()) { 299 negativeTest(String name, TreeNode makeTestCase(TestHarness test)) {
262 test(name, () { 300 test(name, () {
263 checkHasError(makeProgram(makeBody)); 301 var test = new TestHarness();
302 test.addNode(makeTestCase(test));
303 checkHasError(test.program);
264 }); 304 });
265 } 305 }
266 306
267 positiveTest(String name, TreeNode makeBody()) { 307 positiveTest(String name, TreeNode makeTestCase(TestHarness test)) {
268 test(name, () { 308 test(name, () {
269 verifyProgram(makeProgram(makeBody)); 309 var test = new TestHarness();
310 test.addNode(makeTestCase(test));
311 verifyProgram(test.program);
270 }); 312 });
271 } 313 }
272
273 VariableDeclaration makeVariable() => new VariableDeclaration(null);
274
275 TypeParameter makeTypeParameter([String name]) {
276 return new TypeParameter(name, new InterfaceType(objectClass));
277 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698