File: 1007_tests_support_skip_closure-compiler.patch

package info (click to toggle)
emscripten 3.1.69%2Bdfsg-3
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 121,860 kB
  • sloc: ansic: 636,110; cpp: 425,974; javascript: 78,401; python: 58,404; sh: 49,154; pascal: 5,237; makefile: 3,366; asm: 2,415; lisp: 1,869
file content (407 lines) | stat: -rw-r--r-- 19,543 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
--- a/test/common.py
+++ b/test/common.py
@@ -60,6 +60,7 @@
 EMTEST_SKIP_SLOW = None
 EMTEST_SKIP_FLAKY = None
 EMTEST_RETRY_FLAKY = None
+EMTEST_LACKS_CLOSURE_COMPILER = None
 EMTEST_LACKS_NATIVE_CLANG = None
 EMTEST_VERBOSE = None
 EMTEST_REBASELINE = None
@@ -232,6 +233,17 @@
   return lambda f: f
 
 
+def requires_closure_compiler(func):
+  assert callable(func)
+
+  def decorated(self, *args, **kwargs):
+    if EMTEST_LACKS_CLOSURE_COMPILER:
+      return self.skipTest('closure compiler tests are disabled')
+    return func(self, *args, **kwargs)
+
+  return decorated
+
+
 def requires_native_clang(func):
   assert callable(func)
 
--- a/test/runner.py
+++ b/test/runner.py
@@ -401,6 +401,7 @@
   common.EMTEST_DETECT_TEMPFILE_LEAKS = int(os.getenv('EMTEST_DETECT_TEMPFILE_LEAKS', '0'))
   common.EMTEST_ALL_ENGINES = int(os.getenv('EMTEST_ALL_ENGINES', '0'))
   common.EMTEST_SKIP_SLOW = int(os.getenv('EMTEST_SKIP_SLOW', '0'))
+  common.EMTEST_LACKS_CLOSURE_COMPILER = int(os.getenv('EMTEST_LACKS_CLOSURE_COMPILER', '0'))
   common.EMTEST_SKIP_FLAKY = int(os.getenv('EMTEST_SKIP_FLAKY', '0'))
   common.EMTEST_RETRY_FLAKY = int(os.getenv('EMTEST_RETRY_FLAKY', '0'))
   common.EMTEST_LACKS_NATIVE_CLANG = int(os.getenv('EMTEST_LACKS_NATIVE_CLANG', '0'))
--- a/test/test_core.py
+++ b/test/test_core.py
@@ -22,14 +22,14 @@
 from tools.utils import WINDOWS, MACOS, write_file, delete_file
 from tools import shared, building, config, utils, webassembly
 import common
-from common import RunnerCore, path_from_root, requires_native_clang, test_file, create_file
+from common import RunnerCore, path_from_root, requires_closure_compiler, requires_native_clang, test_file, create_file
 from common import skip_if, no_windows, no_mac, is_slow_test, parameterized, parameterize
 from common import env_modify, with_env_modify, disabled, flaky, node_pthreads, also_with_wasm_bigint
 from common import read_file, read_binary, requires_v8, requires_node, requires_wasm2js, requires_node_canary
 from common import compiler_for, crossplatform, no_4gb, no_2gb, also_with_minimal_runtime
 from common import also_with_noderawfs, also_with_wasmfs
 from common import with_all_eh_sjlj, with_all_sjlj, also_with_standalone_wasm, can_do_standalone, no_wasm64, requires_wasm_exnref
-from common import NON_ZERO, WEBIDL_BINDER, EMBUILDER, PYTHON
+from common import NON_ZERO, EMTEST_LACKS_CLOSURE_COMPILER, WEBIDL_BINDER, EMBUILDER, PYTHON
 import clang_native
 
 # decorators for limiting which modes a test can run in
@@ -328,7 +328,7 @@
 
   # Use closure in some tests for some additional coverage
   def maybe_closure(self):
-    if '--closure=1' not in self.emcc_args and self.should_use_closure():
+    if '--closure=1' not in self.emcc_args and self.should_use_closure() and not EMTEST_LACKS_CLOSURE_COMPILER:
       self.emcc_args += ['--closure=1']
       logger.debug('using closure compiler..')
       return True
@@ -5398,7 +5398,7 @@
 
   def test_files(self):
     # Use closure here, to test we don't break FS stuff
-    if '-O3' in self.emcc_args and self.is_wasm2js():
+    if '-O3' in self.emcc_args and self.is_wasm2js() and not EMTEST_LACKS_CLOSURE_COMPILER:
       print('closure 2')
       self.emcc_args += ['--closure', '2'] # Use closure 2 here for some additional coverage
       # Sadly --closure=2 is not yet free of closure warnings
@@ -7948,6 +7948,7 @@
       self.assertLessEqual(start_wat_addr, dwarf_addr)
       self.assertLessEqual(dwarf_addr, end_wat_addr)
 
+  @requires_closure_compiler
   def test_modularize_closure_pre(self):
     # test that the combination of modularize + closure + pre-js works. in that mode,
     # closure should not minify the Module object in a way that the pre-js cannot use it.
@@ -9029,6 +9030,7 @@
   @no_wasm2js('TODO: ASAN in wasm2js')
   @no_wasm64('TODO: ASAN in memory64')
   @no_2gb('asan doesnt support GLOBAL_BASE')
+  @requires_closure_compiler
   def test_asan_modularized_with_closure(self):
     # the bug is that createModule() returns undefined, instead of the
     # proper Promise object.
--- a/test/test_other.py
+++ b/test/test_other.py
@@ -32,8 +32,8 @@
 from tools.shared import EMCC, EMXX, EMAR, EMRANLIB, FILE_PACKAGER, LLVM_NM
 from tools.shared import CLANG_CC, CLANG_CXX, LLVM_AR, LLVM_DWARFDUMP, LLVM_DWP, EMCMAKE, EMCONFIGURE, WASM_LD
 from common import RunnerCore, path_from_root, is_slow_test, ensure_dir, disabled, make_executable
-from common import env_modify, no_mac, no_windows, only_windows, requires_native_clang, with_env_modify
-from common import create_file, parameterized, NON_ZERO, node_pthreads, TEST_ROOT, test_file
+from common import env_modify, no_mac, no_windows, only_windows, requires_closure_compiler, requires_native_clang, with_env_modify
+from common import create_file, parameterized, NON_ZERO, EMTEST_LACKS_CLOSURE_COMPILER, node_pthreads, TEST_ROOT, test_file
 from common import compiler_for, EMBUILDER, requires_v8, requires_node, requires_wasm64, requires_node_canary
 from common import requires_wasm_exnref, crossplatform, with_all_eh_sjlj, with_all_sjlj
 from common import also_with_standalone_wasm, also_with_wasm2js, also_with_noderawfs, also_with_wasmfs
@@ -381,6 +381,7 @@
     self.assertContained("new Worker(new URL('hello_world.mjs', import.meta.url), workerOptions)", src)
     self.assertContained('hello, world!', self.run_js('hello_world.mjs'))
 
+  @requires_closure_compiler
   def test_emcc_output_mjs_closure(self):
     self.run_process([EMCC, '-o', 'hello_world.mjs',
                       '--extern-post-js', test_file('modularize_post_js.js'),
@@ -2785,6 +2786,7 @@
     self.do_runf(test_file('hello_world.c'), 'prepre\npre-run\nhello, world!\n',
                  emcc_args=['--pre-js', 'pre.js', '--pre-js', 'pre2.js'])
 
+  @requires_closure_compiler
   def test_extern_prepost(self):
     create_file('extern-pre.js', '// I am an external pre.\n')
     create_file('extern-post.js', '// I am an external post.\n')
@@ -3182,6 +3184,7 @@
     ''')
     self.do_runf('main.cpp', '42', emcc_args=['-lembind', '--post-js', 'post.js'])
 
+  @requires_closure_compiler
   def test_embind_closure_no_dynamic_execution(self):
     create_file('post.js', '''
       Module['onRuntimeInitialized'] = () => {
@@ -3841,6 +3844,7 @@
     self.assertLess(output.count('Cannot enlarge memory arrays'),  6)
 
   @requires_node
+  @requires_closure_compiler
   def test_module_exports_with_closure(self):
     # This test checks that module.export is retained when JavaScript
     # is minified by compiling with --closure 1
@@ -4791,6 +4795,7 @@
     output = self.run_js('a.out.js')
     self.assertContained('|5|', output)
 
+  @requires_closure_compiler
   def test_LEGACY_VM_SUPPORT(self):
     # when modern features are lacking, we can polyfill them or at least warn
     create_file('pre.js', 'Math.imul = undefined;')
@@ -6476,12 +6481,13 @@
     test(['-sASSERTIONS=0'], 120000) # we don't care about code size with assertions
     test(['-O1'], 91000)
     test(['-O2'], 46000)
-    test(['-O3', '--closure=1'], 17000)
-    # js too
-    # -Wclosure is needed due to
-    # https://github.com/google/closure-compiler/issues/4108
-    test(['-O3', '--closure=1', '-Wno-closure', '-sWASM=0'], 36000)
-    test(['-O3', '--closure=2', '-Wno-closure', '-sWASM=0'], 33000) # might change now and then
+    if not EMTEST_LACKS_CLOSURE_COMPILER:
+      test(['-O3', '--closure=1'], 17000)
+      # js too
+      # -Wclosure is needed due to
+      # https://github.com/google/closure-compiler/issues/4108
+      test(['-O3', '--closure=1', '-Wno-closure', '-sWASM=0'], 36000)
+      test(['-O3', '--closure=2', '-Wno-closure', '-sWASM=0'], 33000) # might change now and then
 
   def test_no_main_loop(self):
     MAINLOOP = 'var MainLoop'
@@ -7880,7 +7886,7 @@
                       '-sDEFAULT_LIBRARY_FUNCS_TO_INCLUDE=$dynCall',
                       '-sEXPORTED_RUNTIME_METHODS=getTempRet0',
                       '-sEXPORTED_FUNCTIONS=_test_return64', '-o', 'test.js', '-O2',
-                      '--closure=1', '-g1', '-sWASM_ASYNC_COMPILATION=0'] + args)
+                      '--closure=0' if EMTEST_LACKS_CLOSURE_COMPILER else '--closure=1', '-g1', '-sWASM_ASYNC_COMPILATION=0'] + args)
 
     # Simple test program to load the test.js binding library and call the binding to the
     # C function returning the 64 bit long.
@@ -9312,6 +9318,7 @@
           for std in ([], ['-std=c89']):
             self.run_process([EMCC] + std + ['-Werror', '-Wall', '-pedantic', 'a.c', 'b.c'])
 
+  @requires_closure_compiler
   @is_slow_test
   @parameterized({
     '': (True,),
@@ -9324,6 +9331,8 @@
       # skip unhelpful option combinations
       if closure_enabled and debug_enabled:
         continue
+      if closure_enabled and not EMTEST_LACKS_CLOSURE_COMPILER:
+        continue
 
       cmd = [EMCC, test_file('hello_world.c')] + self.get_emcc_args()
 
@@ -9454,6 +9463,7 @@
     assert_aliases_match('MAXIMUM_MEMORY', 'WASM_MEM_MAX', '16777216', ['-sALLOW_MEMORY_GROWTH'])
     assert_aliases_match('MAXIMUM_MEMORY', 'BINARYEN_MEM_MAX', '16777216', ['-sALLOW_MEMORY_GROWTH'])
 
+  @requires_closure_compiler
   def test_IGNORE_CLOSURE_COMPILER_ERRORS(self):
     create_file('pre.js', r'''
       // make closure compiler very very angry
@@ -9504,6 +9514,7 @@
     self.do_other_test('test_full_js_library_except.cpp')
 
   @crossplatform
+  @requires_closure_compiler
   @parameterized({
     '': [[]],
     # bigint support is interesting to test here because it changes which
@@ -9569,6 +9580,7 @@
       self.assertContained('.' + sym, js)
 
   @also_with_wasm64
+  @requires_closure_compiler
   def test_closure_webgpu(self):
     # This test can be removed if USE_WEBGPU is later included in INCLUDE_FULL_LIBRARY.
     self.build(test_file('hello_world.c'), emcc_args=[
@@ -9580,6 +9592,7 @@
 
   # Tests --closure-args command line flag
   @crossplatform
+  @requires_closure_compiler
   def test_closure_externs(self):
     # Test with relocate path to the externs file to ensure that incoming relative paths
     # are translated correctly (Since closure runs with a different CWD)
@@ -9596,6 +9609,7 @@
                        args)
 
   # Tests that it is possible to enable the Closure compiler via --closure=1 even if any of the input files reside in a path with unicode characters.
+  @requires_closure_compiler
   def test_closure_cmdline_utf8_chars(self):
     test = "☃ äö Ć € ' 🦠.c"
     shutil.copy(test_file('hello_world.c'), test)
@@ -9603,6 +9617,7 @@
     create_file(externs, '')
     self.run_process([EMCC, test, '--closure=1', '--closure-args', '--externs "' + externs + '"'])
 
+  @requires_closure_compiler
   def test_closure_type_annotations(self):
     # Verify that certain type annotations exist to allow closure to avoid
     # ambiguity and maximize optimization opportunities in user code.
@@ -9868,11 +9883,12 @@
     self.assertContained('GROWABLE_HEAP_I8().set([ 1, 2, 3 ], $0 >>> 0)',
                          read_file('a.out.js'))
 
+  # FIXME: skip tests when closure is lacking instead of doing same tests twice
   @parameterized({
     '': ([],), # noqa
     'O3': (['-O3'],), # noqa
-    'closure': (['--closure=1'],), # noqa
-    'closure_O3': (['--closure=1', '-O3'],), # noqa
+    'closure': (['--closure=0' if EMTEST_LACKS_CLOSURE_COMPILER else '--closure=1'],), # noqa
+    'closure_O3': (['--closure=0' if EMTEST_LACKS_CLOSURE_COMPILER else '--closure=1', '-O3'],), # noqa
   })
   def test_EM_ASM_ES6(self, args):
     create_file('src.c', r'''
@@ -10838,7 +10854,10 @@
     for wasm in ([], ['-sWASM=0']):
       # Currently we rely on Closure for full minification of every appearance of JS function names.
       # TODO: Add minification also for non-Closure users and add [] to this list to test minification without Closure.
-      for closure in [['--closure=1']]:
+      closure_cases = [[]]
+      if not EMTEST_LACKS_CLOSURE_COMPILER:
+        closure_cases.append(['--closure=1'])
+      for closure in closure_cases:
         args = [EMCC, '-O3', '--js-library', 'library_long.js', 'main_long.c', '-o', 'a.html'] + wasm + closure
         print(' '.join(args))
         self.run_process(args)
@@ -10868,15 +10887,16 @@
       self.assertNotContained('invoke_ii', output)
       self.assertNotContained('invoke_v', output)
 
+  # FIXME: skip tests when closure is lacking instead of doing same tests twice
   @parameterized({
     'O0': (False, ['-O0']), # noqa
     'O0_emit': (True, ['-O0', '-sEMIT_EMSCRIPTEN_LICENSE']), # noqa
     'O2': (False, ['-O2']), # noqa
     'O2_emit': (True, ['-O2', '-sEMIT_EMSCRIPTEN_LICENSE']), # noqa
     'O2_js_emit': (True, ['-O2', '-sEMIT_EMSCRIPTEN_LICENSE', '-sWASM=0']), # noqa
-    'O2_closure': (False, ['-O2', '--closure=1']), # noqa
-    'O2_closure_emit': (True, ['-O2', '-sEMIT_EMSCRIPTEN_LICENSE', '--closure=1']), # noqa
-    'O2_closure_js_emit': (True, ['-O2', '-sEMIT_EMSCRIPTEN_LICENSE', '--closure=1', '-sWASM=0']), # noqa
+    'O2_closure': (False, ['-O2', '--closure=0' if EMTEST_LACKS_CLOSURE_COMPILER else '--closure=1']), # noqa
+    'O2_closure_emit': (True, ['-O2', '-sEMIT_EMSCRIPTEN_LICENSE', '--closure=0' if EMTEST_LACKS_CLOSURE_COMPILER else '--closure=1']), # noqa
+    'O2_closure_js_emit': (True, ['-O2', '-sEMIT_EMSCRIPTEN_LICENSE', '--closure=0' if EMTEST_LACKS_CLOSURE_COMPILER else '--closure=1', '-sWASM=0']), # noqa
   })
   def test_emscripten_license(self, expect_license, args):
     # fastcomp does not support the new license flag
@@ -10956,7 +10976,7 @@
                                '-sSTRICT',
                                '--output_eol', 'linux',
                                '-Oz',
-                               '--closure=1',
+                               '--closure=0' if EMTEST_LACKS_CLOSURE_COMPILER else '--closure=1',
                                '-DNDEBUG',
                                '-ffast-math']
 
@@ -11503,6 +11523,7 @@
     # otherwise in such a trivial program).
     self.assertLess(no, 0.95 * yes)
 
+  @requires_closure_compiler
   def test_INCOMING_MODULE_JS_API(self):
     def test(args):
       self.run_process([EMCC, test_file('hello_world.c'), '-O3', '--closure=1', '-sENVIRONMENT=node,shell', '--output_eol=linux'] + args)
@@ -11645,6 +11666,7 @@
       self.assertContainedIf('exception catching is disabled, this exception cannot be caught', result, expect_caught)
     self.assertContainedIf('CAUGHT', result, expect_caught)
 
+  @requires_closure_compiler
   def test_exceptions_with_closure_and_without_catching(self):
     # using invokes will require setThrew(), and closure will error if it is not
     # defined. this test checks that we define it even without catching any
@@ -11982,11 +12004,14 @@
 
   def test_warning_flags(self):
     self.run_process([EMCC, '-c', '-o', 'hello.o', test_file('hello_world.c')])
-    cmd = [EMCC, 'hello.o', '-o', 'a.js', '-g', '--closure=1']
+    cmd = [EMCC, 'hello.o', '-o', 'a.js', '-g']
+    if not EMTEST_LACKS_CLOSURE_COMPILER:
+      cmd.append(['--closure=1'])
 
     # warning that is enabled by default
-    stderr = self.run_process(cmd, stderr=PIPE).stderr
-    self.assertContained('emcc: warning: disabling closure because debug info was requested [-Wemcc]', stderr)
+    if not EMTEST_LACKS_CLOSURE_COMPILER:
+      stderr = self.run_process(cmd, stderr=PIPE).stderr
+      self.assertContained('emcc: warning: disabling closure because debug info was requested [-Wemcc]', stderr)
 
     # -w to suppress warnings
     stderr = self.run_process(cmd + ['-w'], stderr=PIPE).stderr
@@ -11997,12 +12022,14 @@
     self.assertNotContained('warning', stderr)
 
     # with -Werror should fail
-    stderr = self.expect_fail(cmd + ['-Werror'])
-    self.assertContained('error: disabling closure because debug info was requested [-Wemcc] [-Werror]', stderr)
+    if not EMTEST_LACKS_CLOSURE_COMPILER:
+      stderr = self.expect_fail(cmd + ['-Werror'])
+      self.assertContained('error: disabling closure because debug info was requested [-Wemcc] [-Werror]', stderr)
 
     # with -Werror + -Wno-error=<type> should only warn
-    stderr = self.run_process(cmd + ['-Werror', '-Wno-error=emcc'], stderr=PIPE).stderr
-    self.assertContained('emcc: warning: disabling closure because debug info was requested [-Wemcc]', stderr)
+    if not EMTEST_LACKS_CLOSURE_COMPILER:
+      stderr = self.run_process(cmd + ['-Werror', '-Wno-error=emcc'], stderr=PIPE).stderr
+      self.assertContained('emcc: warning: disabling closure because debug info was requested [-Wemcc]', stderr)
 
     # check that `-Werror=foo` also enales foo
     stderr = self.expect_fail(cmd + ['-Werror=legacy-settings', '-sTOTAL_MEMORY'])
@@ -12187,6 +12214,7 @@
     for engine in config.WASM_ENGINES:
       self.assertContained(expected, self.run_js('test.wasm', engine))
 
+  @requires_closure_compiler
   @parameterized({
     'wasm2js': (['-sWASM=0'],),
     'modularize': (['-sMODULARIZE', '--extern-post-js', test_file('modularize_post_js.js')],),
@@ -12232,6 +12260,7 @@
     self.assertContained('function signature mismatch: foo', stderr)
 
   # Verifies that warning messages that Closure outputs are recorded to console
+  @requires_closure_compiler
   def test_closure_warnings(self):
     # Default should be no warnings
     proc = self.run_process([EMCC, test_file('test_closure_warning.c'), '-O3', '--closure=1'], stderr=PIPE)
@@ -12729,6 +12758,7 @@
     self.assertContained('hello, world!', self.run_js('a.out.js'))
 
   # Test that Closure prints out clear readable error messages when there are errors.
+  @requires_closure_compiler
   def test_closure_errors(self):
     err = self.expect_fail([EMCC, test_file('closure_error.c'), '-O2', '--closure=1'])
     lines = err.split('\n')
@@ -12747,16 +12777,19 @@
     self.assertNotEqual(idx1, idx2)
 
   # Make sure that --cpuprofiler compiles with --closure 1
+  @requires_closure_compiler
   def test_cpuprofiler_closure(self):
     # TODO: Enable '-Werror=closure' in the following, but that has currently regressed.
     self.run_process([EMCC, test_file('hello_world.c'), '-O2', '--closure=1', '--cpuprofiler'])
 
   # Make sure that --memoryprofiler compiles with --closure 1
+  @requires_closure_compiler
   def test_memoryprofiler_closure(self):
     # TODO: Enable '-Werror=closure' in the following, but that has currently regressed.
     self.run_process([EMCC, test_file('hello_world.c'), '-O2', '--closure=1', '--memoryprofiler'])
 
   # Make sure that --threadprofiler compiles with --closure 1
+  @requires_closure_compiler
   def test_threadprofiler_closure(self):
     # TODO: Enable '-Werror=closure' in the following, but that has currently regressed.
     self.run_process([EMCC, test_file('hello_world.c'), '-O2', '-pthread', '--closure=1', '--threadprofiler', '-sASSERTIONS'])
@@ -13326,6 +13359,7 @@
     err = self.run_js('test_pthread_js_exception.js', assert_returncode=NON_ZERO)
     self.assertContained('missing is not defined', err)
 
+  @requires_closure_compiler
   def test_config_closure_compiler(self):
     self.run_process([EMCC, test_file('hello_world.c'), '--closure=1'])
     with env_modify({'EM_CLOSURE_COMPILER': sys.executable}):
@@ -13607,6 +13641,7 @@
     # as `examples/`?)
     self.run_process([EMCC, test_file('hello_function.cpp'), '-o', 'function.html', '-sEXPORTED_FUNCTIONS=_int_sqrt', '-sEXPORTED_RUNTIME_METHODS=ccall,cwrap'])
 
+  @requires_closure_compiler
   @parameterized({
     '': ([],),
     'O3': (['-O3'],),