Chromium Code Reviews| 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 |