Chromium Code Reviews| Index: tests/compiler/dart2js/cpa_inference_test.dart |
| diff --git a/tests/compiler/dart2js/cpa_inference_test.dart b/tests/compiler/dart2js/cpa_inference_test.dart |
| index a8db3d513305e96e2cd3c225c143ef7157e2eaf3..c49c1557b40be1cbb8894ab58c1f75dbdb8030db 100644 |
| --- a/tests/compiler/dart2js/cpa_inference_test.dart |
| +++ b/tests/compiler/dart2js/cpa_inference_test.dart |
| @@ -111,6 +111,14 @@ class AnalysisResult { |
| } |
| /** |
| + * Checks that the inferred type of the node corresponding to the last |
| + * occurence of [: variable; :] in the program is the unknown concrete type. |
| + */ |
| + void checkNodeHasUnknownType(String variable) { |
| + return Expect.isTrue(inferrer.inferredTypes[findNode(variable)].isUnkown()); |
| + } |
| + |
| + /** |
| * Checks that [: className#fieldName :]'s inferred type is the concrete type |
| * made of [baseTypes]. |
| */ |
| @@ -120,11 +128,26 @@ class AnalysisResult { |
| concreteFrom(baseTypes), |
| inferrer.inferredFieldTypes[findField(className, fieldName)]); |
| } |
| + |
| + /** |
| + * Checks that [: className#fieldName :]'s inferred type is the unknown |
| + * concrete type. |
| + */ |
| + void checkFieldHasUknownType(String className, String fieldName) { |
| + return Expect.isTrue( |
| + inferrer.inferredFieldTypes[findField(className, fieldName)] |
| + .isUnkown()); |
| + } |
| } |
| const String CORELIB = r''' |
| print(var obj) {} |
| - abstract class num { operator +(x); operator *(x); operator -(x); } |
| + abstract class num { |
| + operator +(x); |
| + operator *(x); |
| + operator -(x); |
| + operator ==(x); |
| + } |
| abstract class int extends num { } |
| abstract class double extends num { } |
| class bool {} |
| @@ -148,6 +171,17 @@ AnalysisResult analyze(String code) { |
| return new AnalysisResult(compiler); |
| } |
| +testDynamicBackDoor() { |
| + final String source = r""" |
| + main () { |
| + var x = "__dynamic_for_test"; |
| + x; |
| + } |
| + """; |
| + AnalysisResult result = analyze(source); |
| + result.checkNodeHasUnknownType('x'); |
| +} |
| + |
| testLiterals() { |
| final String source = r""" |
| main() { |
| @@ -267,6 +301,15 @@ testFor2() { |
| result.checkNodeHasType('bar', [result.int]); |
| } |
| +testToplevelVariable() { |
| + final String source = r""" |
| + final top = 'abc'; |
| + main() { var foo = top; foo; } |
| + """; |
| + AnalysisResult result = analyze(source); |
| + result.checkNodeHasType('foo', [result.string]); |
| +} |
| + |
| testNonRecusiveFunction() { |
| final String source = r""" |
| f(x, y) => true ? x : y; |
| @@ -298,6 +341,49 @@ testMutuallyRecusiveFunction() { |
| result.checkNodeHasType('foo', [result.int, result.string]); |
| } |
| +testSimpleSend() { |
| + final String source = r""" |
| + class A { |
| + f(x) => x; |
| + } |
| + class B { |
| + f(x) => 'abc'; |
| + } |
| + class C { |
| + f(x) => 3.14; |
| + } |
| + class D { |
| + var f; // we check that this field is ignored in calls to dynamic.f() |
| + D(this.f); |
| + } |
| + main() { |
| + new B(); new D(42); // we instantiate B and D but not C |
| + var foo = new A().f(42); |
| + var bar = "__dynamic_for_test".f(42); |
| + foo; bar; |
| + } |
| + """; |
| + AnalysisResult result = analyze(source); |
| + result.checkNodeHasType('foo', [result.int]); |
| + result.checkNodeHasType('bar', [result.int, result.string]); |
| +} |
| + |
| +testSendToClosureField() { |
| + final String source = r""" |
| + f(x) => x; |
| + class A { |
| + var g; |
| + A(this.g); |
| + } |
| + main() { |
| + var foo = new A(f).g(42); |
| + foo; |
| + } |
| + """; |
| + AnalysisResult result = analyze(source); |
| + result.checkNodeHasType('foo', [result.int]); |
| +} |
| + |
| testSendToThis1() { |
| final String source = r""" |
| class A { |
| @@ -356,18 +442,25 @@ testGetters() { |
| get y => x; |
| get z => y; |
| } |
| + class B { |
| + var x; |
| + B(this.x); |
| + } |
| main() { |
| var a = new A(42); |
| + var b = new B('abc'); |
| var foo = a.x; |
| var bar = a.y; |
| var baz = a.z; |
| - foo; bar; baz; |
| + var qux = "__dynamic_for_test".x; |
| + foo; bar; baz; qux; |
| } |
| """; |
| AnalysisResult result = analyze(source); |
| result.checkNodeHasType('foo', [result.int]); |
| result.checkNodeHasType('bar', [result.int]); |
| result.checkNodeHasType('baz', [result.int]); |
| + result.checkNodeHasType('qux', [result.int, result.string]); |
| } |
| testSetters() { |
| @@ -379,15 +472,33 @@ testSetters() { |
| set y(a) { x = a; z = a; } |
| set z(a) { w = a; } |
| } |
| + class B { |
| + var x; |
| + B(this.x); |
| + } |
| main() { |
| var a = new A(42, 42); |
| + var b = new B(42); |
| a.x = 'abc'; |
| a.y = true; |
| + "__dynamic_for_test".x = null; |
| + "__dynamic_for_test".y = 3.14; |
| } |
| """; |
| AnalysisResult result = analyze(source); |
| - result.checkFieldHasType('A', 'x', [result.int, result.string, result.bool]); |
| - result.checkFieldHasType('A', 'w', [result.int, result.bool]); |
| + result.checkFieldHasType('B', 'x', |
| + [result.int, // new B(42) |
| + result.nullType]); // dynamic.x = null |
| + result.checkFieldHasType('A', 'x', |
| + [result.int, // new A(42, ...) |
| + result.string, // a.x = 'abc' |
| + result.bool, // a.y = true |
| + result.nullType, // dynamic.x = null |
| + result.double]); // dynamic.y = 3.14 |
| + result.checkFieldHasType('A', 'w', |
| + [result.int, // new A(..., 42) |
| + result.bool, // a.y = true |
| + result.double]); // dynamic.y = double |
| } |
| testNamedParameters() { |
| @@ -527,6 +638,26 @@ testOperators() { |
| result.checkNodeHasType('y', [result.string]); |
| } |
| +testSetIndexOperator() { |
| + final String source = r""" |
| + class A { |
| + var witness1; |
| + var witness2; |
| + operator []=(i, x) { witness1 = i; witness2 = x; } |
| + } |
| + main() { |
| + var x = new A()[42] = "abc"; |
| + x; |
| + } |
| + """; |
| + AnalysisResult result = analyze(source); |
| + result.checkNodeHasType('x', [result.string]); |
| + // TODO(polux): the two following results should be {null, string}, see |
| + // fieldInitialization(). |
|
karlklose
2012/11/28 08:24:07
fieldInitialization() -> testFieldInitialization?
polux
2012/11/29 14:18:39
Done.
|
| + result.checkFieldHasType('A', 'witness1', [result.int]); |
| + result.checkFieldHasType('A', 'witness2', [result.string]); |
| +} |
| + |
| testCompoundOperators1() { |
| final String source = r""" |
| class A { |
| @@ -535,17 +666,21 @@ testCompoundOperators1() { |
| main() { |
| var x1 = 1; x1++; |
| var x2 = 1; ++x2; |
| - var x3 = new A(); x3++; |
| - var x4 = new A(); ++x4; |
| + var x3 = 1; x3 += 42; |
|
karlklose
2012/11/28 08:24:07
Perhaps these statements should all have their own
polux
2012/11/29 14:18:39
Done.
|
| + var x4 = new A(); x4++; |
| + var x5 = new A(); ++x5; |
| + var x6 = new A(); x6 += true; |
| - x1; x2; x3; x4; |
| + x1; x2; x3; x4; x5; x6; |
| } |
| """; |
| AnalysisResult result = analyze(source); |
| result.checkNodeHasType('x1', [result.int]); |
| result.checkNodeHasType('x2', [result.int]); |
| - result.checkNodeHasType('x3', [result.string]); |
| + result.checkNodeHasType('x3', [result.int]); |
| result.checkNodeHasType('x4', [result.string]); |
| + result.checkNodeHasType('x5', [result.string]); |
| + result.checkNodeHasType('x6', [result.string]); |
| } |
| @@ -553,24 +688,58 @@ testCompoundOperators2() { |
| final String source = r""" |
| class A { |
| var xx; |
| + var yy; |
| var witness1; |
| var witness2; |
| + var witness3; |
| + var witness4; |
| - A(this.xx); |
| + A(this.xx, this.yy); |
| get x { witness1 = "foo"; return xx; } |
| - set x(y) { witness2 = "foo"; xx = y; } |
| + set x(a) { witness2 = "foo"; xx = a; } |
| + get y { witness3 = "foo"; return yy; } |
| + set y(a) { witness4 = "foo"; yy = a; } |
| } |
| main () { |
| - var a = new A(1); |
| + var a = new A(1, 1); |
| a.x++; |
| + a.y++; |
| } |
| """; |
| AnalysisResult result = analyze(source); |
| result.checkFieldHasType('A', 'xx', [result.int]); |
| - // TODO(polux): the two following results should be {null, string}, see |
| + result.checkFieldHasType('A', 'yy', [result.int]); |
| + // TODO(polux): the four following results should be {null, string}, see |
| // fieldInitialization(). |
| result.checkFieldHasType('A', 'witness1', [result.string]); |
| result.checkFieldHasType('A', 'witness2', [result.string]); |
| + result.checkFieldHasType('A', 'witness3', [result.string]); |
| + result.checkFieldHasType('A', 'witness4', [result.string]); |
| +} |
| + |
| +testDisequality() { |
|
karlklose
2012/11/28 08:24:07
'Disequality' -> 'Inequality'.
polux
2012/11/29 14:18:39
In automated theorem proving, disequalities are in
|
| + final String source = r""" |
| + class A { |
| + var witness; |
| + operator ==(x) { witness = "foo"; return "abc"; } |
| + } |
| + class B { |
| + operator ==(x) { throw "error"; } |
| + } |
| + main() { |
| + var foo = 1 != 2; |
| + var bar = new A() != 2; |
| + var baz = new B() != 2; |
| + foo; bar; baz; |
| + } |
| + """; |
| + AnalysisResult result = analyze(source); |
| + result.checkNodeHasType('foo', [result.bool]); |
| + result.checkNodeHasType('bar', [result.bool]); |
| + result.checkNodeHasType('baz', []); |
| + // TODO(polux): the following result should be {null, string}, see |
|
karlklose
2012/11/28 08:24:07
{null, string} -> [:[null, string]:]
polux
2012/11/29 14:18:39
Done. Is [: :] used in non dartdoc comments too?
|
| + // fieldInitialization(). |
| + result.checkFieldHasType('A', 'witness', [result.string]); |
| } |
| testFieldInitialization() { |
| @@ -588,7 +757,24 @@ testFieldInitialization() { |
| result.checkFieldHasType('A', 'y', [result.int]); |
| } |
| +testDynamicIsAbsorbing() { |
| + final String source = r""" |
| + main () { |
| + var x = 1; |
| + if (true) { |
| + x = "__dynamic_for_test"; |
| + } else { |
| + x = 42; |
| + } |
| + x; |
| + } |
| + """; |
| + AnalysisResult result = analyze(source); |
| + result.checkNodeHasUnknownType('x'); |
| +} |
| + |
| void main() { |
| + testDynamicBackDoor(); |
| testLiterals(); |
| testRedefinition(); |
| testIfThenElse(); |
| @@ -596,9 +782,12 @@ void main() { |
| testWhile(); |
| testFor1(); |
| testFor2(); |
| + // testToplevelVariable(); // toplevel variables are not yet supported |
| testNonRecusiveFunction(); |
| testRecusiveFunction(); |
| testMutuallyRecusiveFunction(); |
| + testSimpleSend(); |
| + // testSendToClosureField(); // closures are not yet supported |
| testSendToThis1(); |
| testSendToThis2(); |
| testConstructor(); |
| @@ -613,5 +802,8 @@ void main() { |
| testOperators(); |
| testCompoundOperators1(); |
| testCompoundOperators2(); |
| + testSetIndexOperator(); |
| + testDisequality(); |
| // testFieldInitialization(); // TODO(polux) |
| + testDynamicIsAbsorbing(); |
| } |