OLD | NEW |
---|---|
(Empty) | |
1 // Copyright (c) 2015, 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 library dart2js.constants.expressions.evaluate_test; | |
6 | |
7 import 'dart:async'; | |
8 import 'package:async_helper/async_helper.dart'; | |
9 import 'package:expect/expect.dart'; | |
10 import 'package:compiler/src/constants/expressions.dart'; | |
11 import 'package:compiler/src/constants/values.dart'; | |
12 import 'package:compiler/src/constant_system_dart.dart'; | |
13 import 'package:compiler/src/core_types.dart'; | |
14 import 'package:compiler/src/dart2jslib.dart'; | |
15 import 'package:compiler/src/elements/elements.dart'; | |
16 import 'memory_compiler.dart'; | |
17 | |
18 class TestData { | |
19 /// Declarations needed for the [constants]. | |
20 final String declarations; | |
21 /// Tested constants. | |
22 final List constants; | |
23 | |
24 const TestData(this.declarations, this.constants); | |
25 } | |
26 | |
27 class ConstantData { | |
28 /// Source code for the constant expression. | |
29 final String code; | |
30 /// Map from environment to expected constant value as structured text. | |
31 final Map<Map<String, String>, String> expectedValues; | |
32 | |
33 const ConstantData(this.code, | |
34 this.expectedValues); | |
35 } | |
36 | |
37 class MemoryEnvironment implements Environment { | |
38 final Compiler compiler; | |
39 final Map<String, String> env; | |
40 | |
41 MemoryEnvironment(this.compiler, [this.env = const <String, String>{}]); | |
42 | |
43 @override | |
44 String readFromEnvironment(String name) => env[name]; | |
45 } | |
46 | |
47 const List<TestData> DATA = const [ | |
48 const TestData('', const [ | |
49 const ConstantData('null', const { const {} : 'NullConstant' }), | |
50 const ConstantData('false', const { const {} : 'BoolConstant(false)' }), | |
51 const ConstantData('true', const { const {} : 'BoolConstant(true)' }), | |
52 const ConstantData('0', const { const {} : 'IntConstant(0)' }), | |
53 const ConstantData('0.0', const { const {} : 'DoubleConstant(0.0)' }), | |
54 const ConstantData('"foo"', const { const {} : 'StringConstant("foo")' }), | |
55 const ConstantData('1 + 2', const { const {} : 'IntConstant(3)' }), | |
56 const ConstantData('-(1)', const { const {} : 'IntConstant(-1)' }), | |
57 const ConstantData('identical(0, 1)', | |
58 const { const {} : 'BoolConstant(false)' }), | |
59 const ConstantData('"a" "b"', const { const {} : 'StringConstant("ab")' }), | |
60 const ConstantData('identical', | |
61 const { const {} : 'FunctionConstant(identical)' }), | |
62 const ConstantData('true ? 0 : 1', const { const {} : 'IntConstant(0)' }), | |
63 const ConstantData('proxy', | |
64 const { const {} : 'ConstructedConstant(_Proxy())' }), | |
65 const ConstantData('Object', const { const {} : 'TypeConstant(Object)' }), | |
66 const ConstantData('const [0, 1]', | |
67 const { const {} : 'ListConstant([IntConstant(0),IntConstant(1)])' }), | |
karlklose
2015/05/11 12:48:08
I would prefer more white-space in the string valu
Johnni Winther
2015/05/11 13:59:46
Done.
| |
68 const ConstantData('const <int>[0, 1]', const { | |
69 const {} : 'ListConstant(<int>[IntConstant(0),IntConstant(1)])' }), | |
70 const ConstantData('const {0: 1, 2: 3}', | |
71 const { const {} : | |
72 'MapConstant({IntConstant(0):IntConstant(1),' | |
73 'IntConstant(2):IntConstant(3)})' }), | |
74 const ConstantData('const <int, int>{0: 1, 2: 3}', | |
75 const { const {} : | |
76 'MapConstant(<int, int>{IntConstant(0):IntConstant(1),' | |
77 'IntConstant(2):IntConstant(3)})' }), | |
78 const ConstantData( | |
79 'const bool.fromEnvironment("foo", defaultValue: false)', | |
80 const { const {} : 'BoolConstant(false)', | |
81 const {'foo': 'true'} : 'BoolConstant(true)'}), | |
82 const ConstantData( | |
83 'const int.fromEnvironment("foo", defaultValue: 42)', | |
84 const { const {} : 'IntConstant(42)', | |
85 const {'foo': '87'} : 'IntConstant(87)'}), | |
86 const ConstantData( | |
87 'const String.fromEnvironment("foo", defaultValue: "bar")', | |
88 const { const {} : 'StringConstant("bar")', | |
89 const {'foo': 'foo'} : 'StringConstant("foo")'}), | |
90 ]), | |
91 const TestData(''' | |
92 const a = const bool.fromEnvironment("foo", defaultValue: true); | |
93 const b = const int.fromEnvironment("bar", defaultValue: 42); | |
94 | |
95 class A { | |
96 const A(); | |
97 } | |
98 class B { | |
99 final field1; | |
100 const B(this.field1); | |
101 } | |
102 class C extends B { | |
103 final field2; | |
104 const C({field1: 42, this.field2: false}) : super(field1); | |
105 const C.named([field = false]) : this(field1: field, field2: field); | |
106 } | |
107 ''', const [ | |
108 const ConstantData('const Object()', | |
109 const { const {} : 'ConstructedConstant(Object())' }), | |
110 const ConstantData('const A()', | |
111 const { const {} : 'ConstructedConstant(A())' }), | |
112 const ConstantData('const B(0)', | |
113 const { const {} : 'ConstructedConstant(B(field1=IntConstant(0)))' }), | |
114 const ConstantData('const B(const A())', | |
115 const { const {} : | |
116 'ConstructedConstant(B(field1=ConstructedConstant(A())))' }), | |
117 const ConstantData('const C()', const { const {} : | |
118 'ConstructedConstant(C(field1=IntConstant(42),' | |
119 'field2=BoolConstant(false)))' }), | |
120 const ConstantData('const C(field1: 87)', const { const {} : | |
121 'ConstructedConstant(C(field1=IntConstant(87),' | |
122 'field2=BoolConstant(false)))' }), | |
123 const ConstantData('const C(field2: true)', const { const {} : | |
124 'ConstructedConstant(C(field1=IntConstant(42),' | |
125 'field2=BoolConstant(true)))' }), | |
126 const ConstantData('const C.named()', const { const {} : | |
127 'ConstructedConstant(C(field1=BoolConstant(false),' | |
128 'field2=BoolConstant(false)))' }), | |
129 const ConstantData('const C.named(87)', const { const {} : | |
130 'ConstructedConstant(C(field1=IntConstant(87),' | |
131 'field2=IntConstant(87)))' }), | |
132 const ConstantData('const C(field1: a, field2: b)', const { | |
133 const {} : | |
134 'ConstructedConstant(C(field1=BoolConstant(true),' | |
135 'field2=IntConstant(42)))', | |
136 const {'foo': 'false', 'bar': '87'} : | |
137 'ConstructedConstant(C(field1=BoolConstant(false),' | |
138 'field2=IntConstant(87)))', }), | |
139 ]), | |
140 const TestData(''' | |
141 class A<T> implements B { | |
142 final field1; | |
143 const A({this.field1:42}); | |
144 } | |
145 class B<S> implements C { | |
146 const factory B({field1}) = A<B<S>>; | |
147 // TODO(johnniwinther): Enable this when the constructor evaluator doesn't | |
148 // crash: | |
149 /*const factory B.named() = A<S>;*/ | |
150 } | |
151 class C<U> { | |
152 const factory C({field1}) = A<B<double>>; | |
153 } | |
154 ''', const [ | |
155 const ConstantData('const A()', | |
156 const { const {} : | |
157 'ConstructedConstant(A<dynamic>(field1=IntConstant(42)))' }), | |
158 const ConstantData('const A<int>(field1: 87)', | |
159 const { const {} : | |
160 'ConstructedConstant(A<int>(field1=IntConstant(87)))' }), | |
161 const ConstantData('const B()', | |
162 const { const {} : | |
163 'ConstructedConstant(A<B<dynamic>>(field1=IntConstant(42)))' }), | |
164 const ConstantData('const B<int>()', | |
165 const { const {} : | |
166 'ConstructedConstant(A<B<int>>(field1=IntConstant(42)))' }), | |
167 const ConstantData('const B<int>(field1: 87)', | |
168 const { const {} : | |
169 'ConstructedConstant(A<B<int>>(field1=IntConstant(87)))' }), | |
170 const ConstantData('const C<int>(field1: 87)', | |
171 const { const {} : | |
172 'ConstructedConstant(A<B<double>>(field1=IntConstant(87)))' }), | |
173 // TODO(johnniwinther): Enable this when the constructor evaluator doesn't | |
174 // crash: | |
175 /*const ConstantData('const B<int>.named()', | |
176 const { const {} : | |
177 'ConstructedConstant(A<int>(field1=IntConstant(42)))' }),*/ | |
178 ]), | |
179 const TestData(''' | |
180 const c = const int.fromEnvironment("foo", defaultValue: 5); | |
181 const d = const int.fromEnvironment("bar", defaultValue: 10); | |
182 | |
183 class A { | |
184 final field; | |
185 const A(a, b) : field = a + b; | |
186 } | |
187 | |
188 class B extends A { | |
189 const B(a) : super(a, a * 2); | |
190 } | |
191 ''', const [ | |
192 const ConstantData('const A(c, d)', const { | |
193 const {} : | |
194 'ConstructedConstant(A(field=IntConstant(15)))', | |
195 const {'foo': '7', 'bar': '11'} : | |
196 'ConstructedConstant(A(field=IntConstant(18)))', }), | |
197 const ConstantData('const B(d)', const { | |
198 const {} : | |
199 'ConstructedConstant(B(field=IntConstant(30)))', | |
200 const {'bar': '42'} : | |
201 'ConstructedConstant(B(field=IntConstant(126)))', }), | |
202 ]), | |
203 ]; | |
204 | |
205 main() { | |
206 asyncTest(() => Future.forEach(DATA, testData)); | |
207 } | |
208 | |
209 Future testData(TestData data) { | |
210 StringBuffer sb = new StringBuffer(); | |
211 sb.write('${data.declarations}\n'); | |
212 Map constants = {}; | |
213 data.constants.forEach((ConstantData constantData) { | |
214 String name = 'c${constants.length}'; | |
215 sb.write('const $name = ${constantData.code};\n'); | |
216 constants[name] = constantData; | |
217 }); | |
218 sb.write('main() {}\n'); | |
219 String source = sb.toString(); | |
220 Compiler compiler = compilerFor( | |
221 {'main.dart': source}, options: ['--analyze-all']); | |
222 return compiler.runCompiler(Uri.parse('memory:main.dart')).then((_) { | |
223 var library = compiler.mainApp; | |
224 constants.forEach((String name, ConstantData data) { | |
225 FieldElement field = library.localLookup(name); | |
226 ConstantExpression constant = field.constant; | |
227 data.expectedValues.forEach( | |
228 (Map<String, String> env, String expectedText) { | |
229 Environment environment = new MemoryEnvironment(compiler, env); | |
230 ConstantValue value = | |
231 constant.evaluate(environment, DART_CONSTANT_SYSTEM); | |
232 String valueText = value.toStructuredString(); | |
233 Expect.equals(expectedText, valueText, | |
234 "Unexpected value '${valueText}' for contant " | |
235 "`${constant.getText()}`, expected '${expectedText}'."); | |
236 }); | |
237 }); | |
238 }); | |
239 } | |
OLD | NEW |