15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/**
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @fileoverview Generator script for creating gtest-style JavaScript
7f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) *     tests for extensions, WebUI and unit tests. Generates C++ gtest wrappers
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *     which will invoke the appropriate JavaScript for each test.
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @author scr@chromium.org (Sheridan Rawlins)
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @see WebUI testing: http://goo.gl/ZWFXF
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @see gtest documentation: http://goo.gl/Ujj3H
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @see chrome/chrome_tests.gypi
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @see tools/gypv8sh.py
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Arguments from rules in chrome_tests.gypi are passed in through
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// python script gypv8sh.py.
1846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)if (arguments.length != 6) {
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  print('usage: ' +
2046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)        arguments[0] +
2146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)        ' path-to-testfile.js testfile.js path_to_deps.js output.cc test-type');
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  quit(-1);
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/**
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Full path to the test input file.
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @type {string}
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)var jsFile = arguments[1];
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/**
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Relative path to the test input file appropriate for use in the
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * C++ TestFixture's addLibrary method.
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @type {string}
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)var jsFileBase = arguments[2];
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/**
39116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch * The cwd, as determined by the paths of |jsFile| and |jsFileBase|.
40116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch * This is usually relative to the root source directory and points to the
41116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch * directory where the GYP rule processing the js file lives.
42116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch */
43116680a4aac90f2aa7413d9095a592090648e557Ben Murdochvar jsDirBase = jsFileBase.replace(jsFile, '');
44116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
45116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch/**
4646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) * Path to Closure library style deps.js file.
4746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) * @type {string?}
4846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) */
4946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)var depsFile = arguments[3];
5046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
5146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)/**
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Path to C++ file generation is outputting to.
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @type {string}
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
5546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)var outputFile = arguments[4];
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/**
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Type of this test.
59f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) * @type {string} ('extension' | 'unit' | 'webui')
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
6146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)var testType = arguments[5];
62f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)if (testType != 'extension' &&
63f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    testType != 'unit' &&
64f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    testType != 'webui') {
65f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  print('Invalid test type: ' + testType);
66f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  quit(-1);
67f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)}
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/**
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * C++ gtest macro to use for TEST_F depending on |testType|.
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @type {string} ('TEST_F'|'IN_PROC_BROWSER_TEST_F')
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)var testF;
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/**
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Keeps track of whether a typedef has been generated for each test
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * fixture.
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @type {Object.<string, string>}
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)var typedeffedCppFixtures = {};
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/**
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Maintains a list of relative file paths to add to each gtest body
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * for inclusion at runtime before running each JavaScript test.
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @type {Array.<string>}
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)var genIncludes = [];
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/**
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * When true, add calls to set_preload_test_(fixture|name). This is needed when
91f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) * |testType| === 'webui' to send an injection message before the page loads,
92f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) * but is not required or supported by any other test type.
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @type {boolean}
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)var addSetPreloadInfo;
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
97f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)/**
98f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) * Whether cc headers need to be generated.
99f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) * @type {boolean}
100f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) */
101f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)var needGenHeader = true;
102f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
103f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)/**
104f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) * Helpful hint pointing back to the source js.
105f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) * @type {string}
106f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) */
107f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)var argHint = '// ' + this['arguments'].join(' ');
108f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
109f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
110f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)/**
111f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) * Generates the header of the cc file to stdout.
112f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) * @param {string?} testFixture Name of test fixture.
113f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) */
114f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)function maybeGenHeader(testFixture) {
115f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  if (!needGenHeader)
116f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    return;
117f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  needGenHeader = false;
118f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  print('// GENERATED FILE');
119f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  print(argHint);
120f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  print('// PLEASE DO NOT HAND EDIT!');
121f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  print();
122f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
123f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  // Output some C++ headers based upon the |testType|.
124f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  //
125f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  // Currently supports:
126f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  // 'extension' - browser_tests harness, js2extension rule,
127f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  //               ExtensionJSBrowserTest superclass.
128f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  // 'unit' - unit_tests harness, js2unit rule, V8UnitTest superclass.
129f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  // 'webui' - browser_tests harness, js2webui rule, WebUIBrowserTest
130f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  // superclass.
131f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  if (testType === 'extension') {
132f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    print('#include "chrome/test/base/extension_js_browser_test.h"');
133f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    testing.Test.prototype.typedefCppFixture = 'ExtensionJSBrowserTest';
134f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    addSetPreloadInfo = false;
135f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    testF = 'IN_PROC_BROWSER_TEST_F';
136f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  } else if (testType === 'unit') {
137f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    print('#include "chrome/test/base/v8_unit_test.h"');
138f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    testing.Test.prototype.typedefCppFixture = 'V8UnitTest';
139f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    testF = 'TEST_F';
140f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    addSetPreloadInfo = false;
141f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  } else {
142f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    print('#include "chrome/test/base/web_ui_browser_test.h"');
143f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    testing.Test.prototype.typedefCppFixture = 'WebUIBrowserTest';
144f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    testF = 'IN_PROC_BROWSER_TEST_F';
145f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    addSetPreloadInfo = true;
146f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  }
147f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  print('#include "url/gurl.h"');
148f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  print('#include "testing/gtest/include/gtest/gtest.h"');
149f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  if (testFixture && this[testFixture].prototype.testGenCppIncludes)
150f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    this[testFixture].prototype.testGenCppIncludes();
151f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  print();
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
153f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/**
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Convert the |includeFile| to paths appropriate for immediate
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * inclusion (path) and runtime inclusion (base).
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param {string} includeFile The file to include.
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @return {{path: string, base: string}} Object describing the paths
160116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch *     for |includeFile|. |path| is relative to cwd; |base| is relative to
161116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch * source root.
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)function includeFileToPaths(includeFile) {
164116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  if (includeFile.indexOf(jsDirBase) == 0) {
165116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    // The caller supplied a path relative to root source.
166116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    var relPath = includeFile.replace(jsDirBase, '');
167116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    return {
168116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      path: relPath,
169116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      base: jsDirBase + relPath
170116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    };
171116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  }
172116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
173116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  // The caller supplied a path relative to the input js file's directory (cwd).
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return {
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    path: jsFile.replace(/[^\/\\]+$/, includeFile),
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    base: jsFileBase.replace(/[^\/\\]+$/, includeFile),
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
18046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
18146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)/**
18246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) * Maps object names to the path to the file that provides them.
18346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) * Populated from the |depsFile| if any.
18446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) * @type {Object.<string, string>}
18546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) */
18646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)var dependencyProvidesToPaths = {};
18746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
18846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)/**
18946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) * Maps dependency path names to object names required by the file.
19046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) * Populated from the |depsFile| if any.
19146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) * @type {Object.<string, Array.<string>>}
19246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) */
19346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)var dependencyPathsToRequires = {};
19446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
19546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)if (depsFile) {
19646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  var goog = goog || {};
19746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  /**
19846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)   * Called by the javascript in the deps file to add modules and their
19946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)   * dependencies.
20046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)   * @param {string} path Relative path to the file.
20146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)   * @param Array.<string> provides Objects provided by this file.
20246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)   * @param Array.<string> requires Objects required by this file.
20346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)   */
20446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  goog.addDependency = function(path, provides, requires) {
20546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    provides.forEach(function(provide) {
20646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      dependencyProvidesToPaths[provide] = path;
20746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    });
20846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    dependencyPathsToRequires[path] = requires;
20946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  };
21046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
21146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  // Read and eval the deps file.  It should only contain goog.addDependency
21246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  // calls.
21346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  eval(read(depsFile));
21446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)}
21546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
21646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)/**
21746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) * Resolves a list of libraries to an ordered list of paths to load by the
21846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) * generated C++.  The input should contain object names provided
21946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) * by the deps file.  Dependencies will be resolved and included in the
22046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) * correct order, meaning that the returned array may contain more entries
22146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) * than the input.
22246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) * @param {Array.<string>} deps List of dependencies.
22346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) * @return {Array.<string>} List of paths to load.
22446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) */
22546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)function resolveClosureModuleDeps(deps) {
22646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  if (!depsFile && deps.length > 0) {
22746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    print('Can\'t have closure dependencies without a deps file.');
22846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    quit(-1);
22946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  }
23046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  var resultPaths = [];
23146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  var addedPaths = {};
23246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
23346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  function addPath(path) {
23446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    addedPaths[path] = true;
23546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    resultPaths.push(path);
23646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  }
23746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
23846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  function resolveAndAppend(path) {
23946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    if (addedPaths[path]) {
24046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      return;
24146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    }
24246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    // Set before recursing to catch cycles.
24346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    addedPaths[path] = true;
24446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    dependencyPathsToRequires[path].forEach(function(require) {
24546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      var providingPath = dependencyProvidesToPaths[require];
24646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      if (!providingPath) {
24746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)        print('Unknown object', require, 'required by', path);
24846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)        quit(-1);
24946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      }
25046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      resolveAndAppend(providingPath);
25146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    });
25246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    resultPaths.push(path);
25346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  }
25446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
25546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  // Always add closure library's base.js if provided by deps.
25646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  var basePath = dependencyProvidesToPaths['goog'];
25746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  if (basePath) {
25846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    addPath(basePath);
25946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  }
26046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
26146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  deps.forEach(function(dep) {
26246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    var providingPath = dependencyProvidesToPaths[dep];
26346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    if (providingPath) {
26446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      resolveAndAppend(providingPath);
26546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    } else {
26646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      print('Unknown dependency:', dep);
26746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      quit(-1);
26846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    }
26946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  });
27046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
27146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  return resultPaths;
27246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)}
27346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/**
2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Output |code| verbatim.
2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param {string} code The code to output.
2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)function GEN(code) {
279f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  maybeGenHeader(null);
2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  print(code);
2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/**
284f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) * Outputs |commentEncodedCode|, converting comment to enclosed C++ code.
285f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) * @param {function} commentEncodedCode A function in the following format (note
286f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) * the space in '/ *' and '* /' should be removed to form a comment delimiter):
287f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) *    function() {/ *! my_cpp_code.DoSomething(); * /
288f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) *    Code between / *! and * / will be extracted and written to stdout.
289f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) */
290f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)function GEN_BLOCK(commentEncodedCode) {
291f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  var code = commentEncodedCode.toString().
292f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      replace(/^[^\/]+\/\*!?/, '').
293f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      replace(/\*\/[^\/]+$/, '').
294f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      replace(/^\n|\n$/, '').
295f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      replace(/\s+$/, '');
296f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  GEN(code);
297f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)}
298f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
299f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)/**
3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Generate includes for the current |jsFile| by including them
3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * immediately and at runtime.
302116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch * The paths are allowed to be:
303116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch *   1. relative to the root src directory (i.e. similar to #include's).
304116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch *   2. relative to the directory specified in the GYP rule for the file.
3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param {Array.<string>} includes Paths to JavaScript files to
3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *     include immediately and at runtime.
3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)function GEN_INCLUDE(includes) {
3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (var i = 0; i < includes.length; i++) {
3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    var includePaths = includeFileToPaths(includes[i]);
3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    var js = read(includePaths.path);
3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ('global', eval)(js);
3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    genIncludes.push(includePaths.base);
3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/**
3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Generate gtest-style TEST_F definitions for C++ with a body that
3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * will invoke the |testBody| for |testFixture|.|testFunction|.
3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param {string} testFixture The name of this test's fixture.
3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param {string} testFunction The name of this test's function.
3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param {Function} testBody The function body to execute for this test.
3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)function TEST_F(testFixture, testFunction, testBody) {
325f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  maybeGenHeader(testFixture);
3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  var browsePreload = this[testFixture].prototype.browsePreload;
3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  var browsePrintPreload = this[testFixture].prototype.browsePrintPreload;
3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  var testGenPreamble = this[testFixture].prototype.testGenPreamble;
3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  var testGenPostamble = this[testFixture].prototype.testGenPostamble;
3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  var typedefCppFixture = this[testFixture].prototype.typedefCppFixture;
3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  var isAsyncParam = testType === 'unit' ? '' :
3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      this[testFixture].prototype.isAsync + ', ';
3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  var testShouldFail = this[testFixture].prototype.testShouldFail;
3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  var testPredicate = testShouldFail ? 'ASSERT_FALSE' : 'ASSERT_TRUE';
3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  var extraLibraries = genIncludes.concat(
3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      this[testFixture].prototype.extraLibraries.map(
3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          function(includeFile) {
3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            return includeFileToPaths(includeFile).base;
33946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)          }),
34046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      resolveClosureModuleDeps(this[testFixture].prototype.closureModuleDeps));
3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (typedefCppFixture && !(testFixture in typedeffedCppFixtures)) {
3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    print('typedef ' + typedefCppFixture + ' ' + testFixture + ';');
3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    typedeffedCppFixtures[testFixture] = typedefCppFixture;
3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  print(testF + '(' + testFixture + ', ' + testFunction + ') {');
3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (var i = 0; i < extraLibraries.length; i++) {
3492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    print('  AddLibrary(base::FilePath(FILE_PATH_LITERAL("' +
3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        extraLibraries[i].replace(/\\/g, '/') + '")));');
3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  print('  AddLibrary(base::FilePath(FILE_PATH_LITERAL("' +
3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      jsFileBase.replace(/\\/g, '/') + '")));');
3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (addSetPreloadInfo) {
3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    print('  set_preload_test_fixture("' + testFixture + '");');
3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    print('  set_preload_test_name("' + testFunction + '");');
3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (testGenPreamble)
3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    testGenPreamble(testFixture, testFunction);
3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (browsePreload)
3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    print('  BrowsePreload(GURL("' + browsePreload + '"));');
3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (browsePrintPreload) {
3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    print('  BrowsePrintPreload(GURL(WebUITestDataPathToURL(\n' +
3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          '      FILE_PATH_LITERAL("' + browsePrintPreload + '"))));');
3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  print('  ' + testPredicate + '(RunJavascriptTestF(' + isAsyncParam +
3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        '"' + testFixture + '", ' +
3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        '"' + testFunction + '"));');
3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (testGenPostamble)
3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    testGenPostamble(testFixture, testFunction);
3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  print('}');
3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  print();
3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Now that generation functions are defined, load in |jsFile|.
3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)var js = read(jsFile);
3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)eval(js);
378