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

Side by Side Diff: pkg/barback/test/asset_graph/transform_test.dart

Issue 5695057915019264: Make barback more package-aware. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Additional tests. Created 7 years, 5 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 | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2013, 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
5 library barback.test.asset_graph.transform_test; 5 library barback.test.asset_graph.transform_test;
6 6
7 import 'dart:async'; 7 import 'dart:async';
8 8
9 import 'package:barback/barback.dart'; 9 import 'package:barback/barback.dart';
10 import 'package:barback/src/asset_graph.dart'; 10 import 'package:barback/src/asset_graph.dart';
11 import 'package:scheduled_test/scheduled_test.dart'; 11 import 'package:scheduled_test/scheduled_test.dart';
12 12
13 import '../utils.dart'; 13 import '../utils.dart';
14 14
15 main() { 15 main() {
16 initConfig(); 16 initConfig();
17 test("gets a transformed asset with a different path", () { 17 test("gets a transformed asset with a different path", () {
18 initGraph(["app|foo.blub"], [ 18 initGraph(["app|foo.blub"], {"app": [
19 [new RewriteTransformer("blub", "blab")] 19 [new RewriteTransformer("blub", "blab")]
20 ]); 20 ]});
21 updateSources(["app|foo.blub"]); 21 updateSources(["app|foo.blub"]);
22 expectAsset("app|foo.blab", "foo.blab"); 22 expectAsset("app|foo.blab", "foo.blab");
23 }); 23 });
24 24
25 test("gets a transformed asset with the same path", () { 25 test("gets a transformed asset with the same path", () {
26 initGraph(["app|foo.blub"], [ 26 initGraph(["app|foo.blub"], {"app": [
27 [new RewriteTransformer("blub", "blub")] 27 [new RewriteTransformer("blub", "blub")]
28 ]); 28 ]});
29 updateSources(["app|foo.blub"]); 29 updateSources(["app|foo.blub"]);
30 expectAsset("app|foo.blub", "foo.blub"); 30 expectAsset("app|foo.blub", "foo.blub");
31 }); 31 });
32 32
33 test("doesn't find an output from a later phase", () { 33 test("doesn't find an output from a later phase", () {
34 initGraph(["app|foo.a"], [ 34 initGraph(["app|foo.a"], {"app": [
35 [new RewriteTransformer("b", "c")], 35 [new RewriteTransformer("b", "c")],
36 [new RewriteTransformer("a", "b")] 36 [new RewriteTransformer("a", "b")]
37 ]); 37 ]});
38 updateSources(["app|foo.a"]); 38 updateSources(["app|foo.a"]);
39 expectNoAsset("app|foo.c"); 39 expectNoAsset("app|foo.c");
40 }); 40 });
41 41
42 test("doesn't find an output from the same phase", () { 42 test("doesn't find an output from the same phase", () {
43 initGraph(["app|foo.a"], [ 43 initGraph(["app|foo.a"], {"app": [
44 [ 44 [
45 new RewriteTransformer("a", "b"), 45 new RewriteTransformer("a", "b"),
46 new RewriteTransformer("b", "c") 46 new RewriteTransformer("b", "c")
47 ] 47 ]
48 ]); 48 ]});
49 updateSources(["app|foo.a"]); 49 updateSources(["app|foo.a"]);
50 expectAsset("app|foo.b", "foo.b"); 50 expectAsset("app|foo.b", "foo.b");
51 expectNoAsset("app|foo.c"); 51 expectNoAsset("app|foo.c");
52 }); 52 });
53 53
54 test("finds the latest output before the transformer's phase", () { 54 test("finds the latest output before the transformer's phase", () {
55 initGraph(["app|foo.blub"], [ 55 initGraph(["app|foo.blub"], {"app": [
56 [new RewriteTransformer("blub", "blub")], 56 [new RewriteTransformer("blub", "blub")],
57 [ 57 [
58 new RewriteTransformer("blub", "blub"), 58 new RewriteTransformer("blub", "blub"),
59 new RewriteTransformer("blub", "done") 59 new RewriteTransformer("blub", "done")
60 ], 60 ],
61 [new RewriteTransformer("blub", "blub")] 61 [new RewriteTransformer("blub", "blub")]
62 ]); 62 ]});
63 updateSources(["app|foo.blub"]); 63 updateSources(["app|foo.blub"]);
64 expectAsset("app|foo.done", "foo.blub.done"); 64 expectAsset("app|foo.done", "foo.blub.done");
65 }); 65 });
66 66
67 test("applies multiple transformations to an asset", () { 67 test("applies multiple transformations to an asset", () {
68 initGraph(["app|foo.a"], [ 68 initGraph(["app|foo.a"], {"app": [
69 [new RewriteTransformer("a", "b")], 69 [new RewriteTransformer("a", "b")],
70 [new RewriteTransformer("b", "c")], 70 [new RewriteTransformer("b", "c")],
71 [new RewriteTransformer("c", "d")], 71 [new RewriteTransformer("c", "d")],
72 [new RewriteTransformer("d", "e")], 72 [new RewriteTransformer("d", "e")],
73 [new RewriteTransformer("e", "f")], 73 [new RewriteTransformer("e", "f")],
74 [new RewriteTransformer("f", "g")], 74 [new RewriteTransformer("f", "g")],
75 [new RewriteTransformer("g", "h")], 75 [new RewriteTransformer("g", "h")],
76 [new RewriteTransformer("h", "i")], 76 [new RewriteTransformer("h", "i")],
77 [new RewriteTransformer("i", "j")], 77 [new RewriteTransformer("i", "j")],
78 [new RewriteTransformer("j", "k")], 78 [new RewriteTransformer("j", "k")],
79 ]); 79 ]});
80 updateSources(["app|foo.a"]); 80 updateSources(["app|foo.a"]);
81 expectAsset("app|foo.k", "foo.b.c.d.e.f.g.h.i.j.k"); 81 expectAsset("app|foo.k", "foo.b.c.d.e.f.g.h.i.j.k");
82 }); 82 });
83 83
84 test("only runs a transform once for all of its outputs", () { 84 test("only runs a transform once for all of its outputs", () {
85 var transformer = new RewriteTransformer("blub", "a b c"); 85 var transformer = new RewriteTransformer("blub", "a b c");
86 initGraph(["app|foo.blub"], [[transformer]]); 86 initGraph(["app|foo.blub"], {"app": [[transformer]]});
87 updateSources(["app|foo.blub"]); 87 updateSources(["app|foo.blub"]);
88 expectAsset("app|foo.a", "foo.a"); 88 expectAsset("app|foo.a", "foo.a");
89 expectAsset("app|foo.b", "foo.b"); 89 expectAsset("app|foo.b", "foo.b");
90 expectAsset("app|foo.c", "foo.c"); 90 expectAsset("app|foo.c", "foo.c");
91 schedule(() { 91 schedule(() {
92 expect(transformer.numRuns, equals(1)); 92 expect(transformer.numRuns, equals(1));
93 }); 93 });
94 }); 94 });
95 95
96 test("runs transforms in the same phase in parallel", () { 96 test("runs transforms in the same phase in parallel", () {
97 var transformerA = new RewriteTransformer("txt", "a"); 97 var transformerA = new RewriteTransformer("txt", "a");
98 var transformerB = new RewriteTransformer("txt", "b"); 98 var transformerB = new RewriteTransformer("txt", "b");
99 initGraph(["app|foo.txt"], [[transformerA, transformerB]]); 99 initGraph(["app|foo.txt"], {"app": [[transformerA, transformerB]]});
100 100
101 transformerA.wait(); 101 transformerA.wait();
102 transformerB.wait(); 102 transformerB.wait();
103 103
104 schedule(() { 104 schedule(() {
105 updateSources(["app|foo.txt"]); 105 updateSources(["app|foo.txt"]);
106 106
107 // Wait for them both to start. 107 // Wait for them both to start.
108 return Future.wait([transformerA.started, transformerB.started]); 108 return Future.wait([transformerA.started, transformerB.started]);
109 }); 109 });
110 110
111 schedule(() { 111 schedule(() {
112 // They should both still be running. 112 // They should both still be running.
113 expect(transformerA.isRunning, isTrue); 113 expect(transformerA.isRunning, isTrue);
114 expect(transformerB.isRunning, isTrue); 114 expect(transformerB.isRunning, isTrue);
115 115
116 transformerA.complete(); 116 transformerA.complete();
117 transformerB.complete(); 117 transformerB.complete();
118 }); 118 });
119 119
120 expectAsset("app|foo.a", "foo.a"); 120 expectAsset("app|foo.a", "foo.a");
121 expectAsset("app|foo.b", "foo.b"); 121 expectAsset("app|foo.b", "foo.b");
122 }); 122 });
123 123
124 test("does not reapply transform when inputs are not modified", () { 124 test("does not reapply transform when inputs are not modified", () {
125 var transformer = new RewriteTransformer("blub", "blab"); 125 var transformer = new RewriteTransformer("blub", "blab");
126 initGraph(["app|foo.blub"], [[transformer]]); 126 initGraph(["app|foo.blub"], {"app": [[transformer]]});
127 updateSources(["app|foo.blub"]); 127 updateSources(["app|foo.blub"]);
128 expectAsset("app|foo.blab", "foo.blab"); 128 expectAsset("app|foo.blab", "foo.blab");
129 expectAsset("app|foo.blab", "foo.blab"); 129 expectAsset("app|foo.blab", "foo.blab");
130 expectAsset("app|foo.blab", "foo.blab"); 130 expectAsset("app|foo.blab", "foo.blab");
131 131
132 schedule(() { 132 schedule(() {
133 expect(transformer.numRuns, equals(1)); 133 expect(transformer.numRuns, equals(1));
134 }); 134 });
135 }); 135 });
136 136
137 test("reapplies a transform when its input is modified", () { 137 test("reapplies a transform when its input is modified", () {
138 var transformer = new RewriteTransformer("blub", "blab"); 138 var transformer = new RewriteTransformer("blub", "blab");
139 initGraph(["app|foo.blub"], [[transformer]]); 139 initGraph(["app|foo.blub"], {"app": [[transformer]]});
140 140
141 schedule(() { 141 schedule(() {
142 updateSources(["app|foo.blub"]); 142 updateSources(["app|foo.blub"]);
143 }); 143 });
144 144
145 expectAsset("app|foo.blab", "foo.blab"); 145 expectAsset("app|foo.blab", "foo.blab");
146 146
147 schedule(() { 147 schedule(() {
148 updateSources(["app|foo.blub"]); 148 updateSources(["app|foo.blub"]);
149 }); 149 });
(...skipping 10 matching lines...) Expand all
160 expect(transformer.numRuns, equals(3)); 160 expect(transformer.numRuns, equals(3));
161 }); 161 });
162 }); 162 });
163 163
164 test("does not reapply transform when a removed input is modified", () { 164 test("does not reapply transform when a removed input is modified", () {
165 var transformer = new ManyToOneTransformer("txt"); 165 var transformer = new ManyToOneTransformer("txt");
166 initGraph({ 166 initGraph({
167 "app|a.txt": "a.inc,b.inc", 167 "app|a.txt": "a.inc,b.inc",
168 "app|a.inc": "a", 168 "app|a.inc": "a",
169 "app|b.inc": "b" 169 "app|b.inc": "b"
170 }, [[transformer]]); 170 }, {"app": [[transformer]]});
171 171
172 updateSources(["app|a.txt", "app|a.inc", "app|b.inc"]); 172 updateSources(["app|a.txt", "app|a.inc", "app|b.inc"]);
173 173
174 expectAsset("app|a.out", "ab"); 174 expectAsset("app|a.out", "ab");
175 175
176 // Remove the dependency on the non-primary input. 176 // Remove the dependency on the non-primary input.
177 schedule(() { 177 schedule(() {
178 modifyAsset("app|a.txt", "a.inc"); 178 modifyAsset("app|a.txt", "a.inc");
179 updateSources(["app|a.txt"]); 179 updateSources(["app|a.txt"]);
180 }); 180 });
181 181
182 // Process it again. 182 // Process it again.
183 expectAsset("app|a.out", "a"); 183 expectAsset("app|a.out", "a");
184 184
185 // Now touch the removed input. It should not trigger another build. 185 // Now touch the removed input. It should not trigger another build.
186 schedule(() { 186 schedule(() {
187 updateSources(["app|b.inc"]); 187 updateSources(["app|b.inc"]);
188 }); 188 });
189 189
190 expectAsset("app|a.out", "a"); 190 expectAsset("app|a.out", "a");
191 191
192 schedule(() { 192 schedule(() {
193 expect(transformer.numRuns, equals(2)); 193 expect(transformer.numRuns, equals(2));
194 }); 194 });
195 }); 195 });
196 196
197 test("allows a transform to generate multiple outputs", () { 197 test("allows a transform to generate multiple outputs", () {
198 initGraph({"app|foo.txt": "a.out,b.out"}, [ 198 initGraph({"app|foo.txt": "a.out,b.out"}, {"app": [
199 [new OneToManyTransformer("txt")] 199 [new OneToManyTransformer("txt")]
200 ]); 200 ]});
201 201
202 updateSources(["app|foo.txt"]); 202 updateSources(["app|foo.txt"]);
203 203
204 expectAsset("app|a.out", "spread txt"); 204 expectAsset("app|a.out", "spread txt");
205 expectAsset("app|b.out", "spread txt"); 205 expectAsset("app|b.out", "spread txt");
206 }); 206 });
207 207
208 test("does not rebuild transforms that don't use modified source", () { 208 test("does not rebuild transforms that don't use modified source", () {
209 var a = new RewriteTransformer("a", "aa"); 209 var a = new RewriteTransformer("a", "aa");
210 var aa = new RewriteTransformer("aa", "aaa"); 210 var aa = new RewriteTransformer("aa", "aaa");
211 var b = new RewriteTransformer("b", "bb"); 211 var b = new RewriteTransformer("b", "bb");
212 var bb = new RewriteTransformer("bb", "bbb"); 212 var bb = new RewriteTransformer("bb", "bbb");
213 initGraph(["app|foo.a", "app|foo.b"], [ 213 initGraph(["app|foo.a", "app|foo.b"], {"app": [
214 [a, b], 214 [a, b],
215 [aa, bb], 215 [aa, bb],
216 ]); 216 ]});
217 217
218 updateSources(["app|foo.a"]); 218 updateSources(["app|foo.a"]);
219 updateSources(["app|foo.b"]); 219 updateSources(["app|foo.b"]);
220 220
221 expectAsset("app|foo.aaa", "foo.aa.aaa"); 221 expectAsset("app|foo.aaa", "foo.aa.aaa");
222 expectAsset("app|foo.bbb", "foo.bb.bbb"); 222 expectAsset("app|foo.bbb", "foo.bb.bbb");
223 223
224 schedule(() { 224 schedule(() {
225 updateSources(["app|foo.a"]); 225 updateSources(["app|foo.a"]);
226 }); 226 });
227 227
228 expectAsset("app|foo.aaa", "foo.aa.aaa"); 228 expectAsset("app|foo.aaa", "foo.aa.aaa");
229 expectAsset("app|foo.bbb", "foo.bb.bbb"); 229 expectAsset("app|foo.bbb", "foo.bb.bbb");
230 230
231 schedule(() { 231 schedule(() {
232 expect(aa.numRuns, equals(2)); 232 expect(aa.numRuns, equals(2));
233 expect(bb.numRuns, equals(1)); 233 expect(bb.numRuns, equals(1));
234 }); 234 });
235 }); 235 });
236 236
237 test("doesn't get an output from a transform whose primary input is removed", 237 test("doesn't get an output from a transform whose primary input is removed",
238 () { 238 () {
239 initGraph(["app|foo.txt"], [ 239 initGraph(["app|foo.txt"], {"app": [
240 [new RewriteTransformer("txt", "out")] 240 [new RewriteTransformer("txt", "out")]
241 ]); 241 ]});
242 242
243 updateSources(["app|foo.txt"]); 243 updateSources(["app|foo.txt"]);
244 expectAsset("app|foo.out", "foo.out"); 244 expectAsset("app|foo.out", "foo.out");
245 245
246 schedule(() { 246 schedule(() {
247 removeSources(["app|foo.txt"]); 247 removeSources(["app|foo.txt"]);
248 }); 248 });
249 249
250 expectNoAsset("app|foo.out"); 250 expectNoAsset("app|foo.out");
251 }); 251 });
252 252
253 test("reapplies a transform when a non-primary input changes", () { 253 test("reapplies a transform when a non-primary input changes", () {
254 initGraph({ 254 initGraph({
255 "app|a.txt": "a.inc", 255 "app|a.txt": "a.inc",
256 "app|a.inc": "a" 256 "app|a.inc": "a"
257 }, [[new ManyToOneTransformer("txt")]]); 257 }, {"app": [[new ManyToOneTransformer("txt")]]});
258 258
259 updateSources(["app|a.txt", "app|a.inc"]); 259 updateSources(["app|a.txt", "app|a.inc"]);
260 expectAsset("app|a.out", "a"); 260 expectAsset("app|a.out", "a");
261 261
262 schedule(() { 262 schedule(() {
263 modifyAsset("app|a.inc", "after"); 263 modifyAsset("app|a.inc", "after");
264 updateSources(["app|a.inc"]); 264 updateSources(["app|a.inc"]);
265 }); 265 });
266 266
267 expectAsset("app|a.out", "after"); 267 expectAsset("app|a.out", "after");
268 }); 268 });
269 269
270 test("restarts processing if a change occurs during processing", () { 270 test("restarts processing if a change occurs during processing", () {
271 var transformer = new RewriteTransformer("txt", "out"); 271 var transformer = new RewriteTransformer("txt", "out");
272 initGraph(["app|foo.txt"], [[transformer]]); 272 initGraph(["app|foo.txt"], {"app": [[transformer]]});
273 273
274 transformer.wait(); 274 transformer.wait();
275 275
276 schedule(() { 276 schedule(() {
277 updateSources(["app|foo.txt"]); 277 updateSources(["app|foo.txt"]);
278 278
279 // Wait for the transform to start. 279 // Wait for the transform to start.
280 return transformer.started; 280 return transformer.started;
281 }); 281 });
282 282
(...skipping 11 matching lines...) Expand all
294 schedule(() { 294 schedule(() {
295 expect(transformer.numRuns, equals(2)); 295 expect(transformer.numRuns, equals(2));
296 }); 296 });
297 }); 297 });
298 298
299 test("handles an output moving from one transformer to another", () { 299 test("handles an output moving from one transformer to another", () {
300 // In the first run, "shared.out" is created by the "a.a" transformer. 300 // In the first run, "shared.out" is created by the "a.a" transformer.
301 initGraph({ 301 initGraph({
302 "app|a.a": "a.out,shared.out", 302 "app|a.a": "a.out,shared.out",
303 "app|b.b": "b.out" 303 "app|b.b": "b.out"
304 }, [ 304 }, {"app": [
305 [new OneToManyTransformer("a"), new OneToManyTransformer("b")] 305 [new OneToManyTransformer("a"), new OneToManyTransformer("b")]
306 ]); 306 ]});
307 307
308 updateSources(["app|a.a", "app|b.b"]); 308 updateSources(["app|a.a", "app|b.b"]);
309 309
310 expectAsset("app|a.out", "spread a"); 310 expectAsset("app|a.out", "spread a");
311 expectAsset("app|b.out", "spread b"); 311 expectAsset("app|b.out", "spread b");
312 expectAsset("app|shared.out", "spread a"); 312 expectAsset("app|shared.out", "spread a");
313 313
314 // Now switch their contents so that "shared.out" will be output by "b.b"'s 314 // Now switch their contents so that "shared.out" will be output by "b.b"'s
315 // transformer. 315 // transformer.
316 schedule(() { 316 schedule(() {
317 modifyAsset("app|a.a", "a.out"); 317 modifyAsset("app|a.a", "a.out");
318 modifyAsset("app|b.b", "b.out,shared.out"); 318 modifyAsset("app|b.b", "b.out,shared.out");
319 updateSources(["app|a.a", "app|b.b"]); 319 updateSources(["app|a.a", "app|b.b"]);
320 }); 320 });
321 321
322 expectAsset("app|a.out", "spread a"); 322 expectAsset("app|a.out", "spread a");
323 expectAsset("app|b.out", "spread b"); 323 expectAsset("app|b.out", "spread b");
324 expectAsset("app|shared.out", "spread b"); 324 expectAsset("app|shared.out", "spread b");
325 }); 325 });
326 326
327 test("restarts before finishing later phases when a change occurs", () { 327 test("restarts before finishing later phases when a change occurs", () {
328 var txtToInt = new RewriteTransformer("txt", "int"); 328 var txtToInt = new RewriteTransformer("txt", "int");
329 var intToOut = new RewriteTransformer("int", "out"); 329 var intToOut = new RewriteTransformer("int", "out");
330 initGraph(["app|foo.txt", "app|bar.txt"], [[txtToInt], [intToOut]]); 330 initGraph(["app|foo.txt", "app|bar.txt"],
331 {"app": [[txtToInt], [intToOut]]});
331 332
332 txtToInt.wait(); 333 txtToInt.wait();
333 334
334 schedule(() { 335 schedule(() {
335 updateSources(["app|foo.txt"]); 336 updateSources(["app|foo.txt"]);
336 337
337 // Wait for the first transform to start. 338 // Wait for the first transform to start.
338 return txtToInt.started; 339 return txtToInt.started;
339 }); 340 });
340 341
341 schedule(() { 342 schedule(() {
342 // Now update the graph during it. 343 // Now update the graph during it.
343 updateSources(["app|bar.txt"]); 344 updateSources(["app|bar.txt"]);
344 }); 345 });
345 346
346 schedule(() { 347 schedule(() {
347 txtToInt.complete(); 348 txtToInt.complete();
348 }); 349 });
349 350
350 expectAsset("app|foo.out", "foo.int.out"); 351 expectAsset("app|foo.out", "foo.int.out");
351 expectAsset("app|bar.out", "bar.int.out"); 352 expectAsset("app|bar.out", "bar.int.out");
352 353
353 schedule(() { 354 schedule(() {
354 // Should only have run each transform once for each primary. 355 // Should only have run each transform once for each primary.
355 expect(txtToInt.numRuns, equals(2)); 356 expect(txtToInt.numRuns, equals(2));
356 expect(intToOut.numRuns, equals(2)); 357 expect(intToOut.numRuns, equals(2));
357 }); 358 });
358 }); 359 });
360
361 test("applies transforms to the correct packages", () {
362 var rewrite1 = new RewriteTransformer("txt", "out1");
363 var rewrite2 = new RewriteTransformer("txt", "out2");
364 initGraph([
365 "pkg1|foo.txt",
366 "pkg2|foo.txt"
367 ], {"pkg1": [[rewrite1]], "pkg2": [[rewrite2]]});
368
369 updateSources(["pkg1|foo.txt", "pkg2|foo.txt"]);
370 expectAsset("pkg1|foo.out1", "foo.out1");
371 expectAsset("pkg2|foo.out2", "foo.out2");
372 buildShouldSucceed();
373 });
374
375 test("doesn't emit a result until all builds are finished", () {
376 var rewrite = new RewriteTransformer("txt", "out");
377 initGraph([
378 "pkg1|foo.txt",
379 "pkg2|foo.txt"
380 ], {"pkg1": [[rewrite]], "pkg2": [[rewrite]]});
381
382 // First, run both packages' transformers so both packages are successful.
383 updateSources(["pkg1|foo.txt", "pkg2|foo.txt"]);
384 expectAsset("pkg1|foo.out", "foo.out");
385 expectAsset("pkg2|foo.out", "foo.out");
386 buildShouldSucceed();
387
388 // pkg1 is still successful, but pkg2 is waiting on the provider, so the
389 // overall build shouldn't finish.
390 pauseProvider();
391 schedule(() => updateSources(["pkg2|foo.txt"]));
392 expectAsset("pkg1|foo.out", "foo.out");
393 buildShouldNotBeDone();
394
395 // Now that the provider is unpaused, pkg2's transforms finish and the
396 // overall build succeeds.
397 resumeProvider();
398 buildShouldSucceed();
399 });
359 } 400 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698