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

Side by Side Diff: chrome/test/base/js2gtest.js

Issue 304793002: Support automatically resolving dependencies in javascript tests. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@lkgr
Patch Set: rebase on top of Dominic's submitted test. Created 6 years, 6 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
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 /** 5 /**
6 * @fileoverview Generator script for creating gtest-style JavaScript 6 * @fileoverview Generator script for creating gtest-style JavaScript
7 * tests for WebUI and unit tests. Generates C++ gtest wrappers 7 * tests for WebUI and unit tests. Generates C++ gtest wrappers
8 * which will invoke the appropriate JavaScript for each test. 8 * which will invoke the appropriate JavaScript for each test.
9 * @author scr@chromium.org (Sheridan Rawlins) 9 * @author scr@chromium.org (Sheridan Rawlins)
10 * @see WebUI testing: http://goo.gl/ZWFXF 10 * @see WebUI testing: http://goo.gl/ZWFXF
11 * @see gtest documentation: http://goo.gl/Ujj3H 11 * @see gtest documentation: http://goo.gl/Ujj3H
12 * @see chrome/chrome_tests.gypi 12 * @see chrome/chrome_tests.gypi
13 * @see tools/gypv8sh.py 13 * @see tools/gypv8sh.py
14 */ 14 */
15 15
16 // Arguments from rules in chrome_tests.gypi are passed in through 16 // Arguments from rules in chrome_tests.gypi are passed in through
17 // python script gypv8sh.py. 17 // python script gypv8sh.py.
18 if (arguments.length < 4) { 18 if (arguments.length != 6) {
19 print('usage: ' + 19 print('usage: ' +
20 arguments[0] + ' path-to-testfile.js testfile.js output.cc test-type'); 20 arguments[0] +
21 ' path-to-testfile.js testfile.js path_to_deps.js output.cc test-type');
21 quit(-1); 22 quit(-1);
22 } 23 }
23 24
24 /** 25 /**
25 * Full path to the test input file. 26 * Full path to the test input file.
26 * @type {string} 27 * @type {string}
27 */ 28 */
28 var jsFile = arguments[1]; 29 var jsFile = arguments[1];
29 30
30 /** 31 /**
31 * Relative path to the test input file appropriate for use in the 32 * Relative path to the test input file appropriate for use in the
32 * C++ TestFixture's addLibrary method. 33 * C++ TestFixture's addLibrary method.
33 * @type {string} 34 * @type {string}
34 */ 35 */
35 var jsFileBase = arguments[2]; 36 var jsFileBase = arguments[2];
36 37
37 /** 38 /**
39 * Path to Closure library style deps.js file.
40 * @type {string?}
41 */
42 var depsFile = arguments[3];
43
44 /**
38 * Path to C++ file generation is outputting to. 45 * Path to C++ file generation is outputting to.
39 * @type {string} 46 * @type {string}
40 */ 47 */
41 var outputFile = arguments[3]; 48 var outputFile = arguments[4];
42 49
43 /** 50 /**
44 * Type of this test. 51 * Type of this test.
45 * @type {string} ('unit'| 'webui') 52 * @type {string} ('unit'| 'webui')
46 */ 53 */
47 var testType = arguments[4]; 54 var testType = arguments[5];
48 55
49 /** 56 /**
50 * C++ gtest macro to use for TEST_F depending on |testType|. 57 * C++ gtest macro to use for TEST_F depending on |testType|.
51 * @type {string} ('TEST_F'|'IN_PROC_BROWSER_TEST_F') 58 * @type {string} ('TEST_F'|'IN_PROC_BROWSER_TEST_F')
52 */ 59 */
53 var testF; 60 var testF;
54 61
55 /** 62 /**
56 * Keeps track of whether a typedef has been generated for each test 63 * Keeps track of whether a typedef has been generated for each test
57 * fixture. 64 * fixture.
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after
107 * @return {{path: string, base: string}} Object describing the paths 114 * @return {{path: string, base: string}} Object describing the paths
108 * for |includeFile|. 115 * for |includeFile|.
109 */ 116 */
110 function includeFileToPaths(includeFile) { 117 function includeFileToPaths(includeFile) {
111 return { 118 return {
112 path: jsFile.replace(/[^\/\\]+$/, includeFile), 119 path: jsFile.replace(/[^\/\\]+$/, includeFile),
113 base: jsFileBase.replace(/[^\/\\]+$/, includeFile), 120 base: jsFileBase.replace(/[^\/\\]+$/, includeFile),
114 }; 121 };
115 } 122 }
116 123
124
125 /**
126 * Maps namespace/object names to the path to the file that provides them.
127 * Populated from the |depsFile| if any.
128 * @type {Object.<string, string>}
129 */
130 var dependencyProvidesToPaths = {};
131
132 /**
133 * For each path included in the |depsFile|, if any, contains
134 * the list of object/namespace names required by the file.
135 * @type {Object.<string, Array.<string>>}
136 */
137 var dependencyPathsToRequires = {};
138
139 if (depsFile) {
140 var goog = goog || {};
141 /**
142 * Called by the javascript in the deps file to add modules and their
143 * dependencies.
144 * @param {string} path Relative path to the file.
145 * @param Array.<string> provides Objects provided by this file.
146 * @param Array.<string> requires Objects required by this file.
147 */
148 goog.addDependency = function(path, provides, requires) {
149 provides.forEach(function(provide) {
150 dependencyProvidesToPaths[provide] = path;
151 });
152 dependencyPathsToRequires[path] = requires;
153 };
154
155 // Read and eval the deps file. It should only contain goog.addDependency
156 // calls.
157 eval(read(depsFile));
158 }
159
160 /**
161 * Resolves a list of libraries to an ordered list of paths to load by the
162 * generated C++. The input can contain paths relative to the test script and,
163 * if a deps file was provided, namespace/object names provided by the
164 * deps file. For the latter case, dependencies will be resolved and
165 * included in the correct order, meaning that the returned array may contain
166 * more entries than the input.
167 * @param {Array.<string>} libraries List of libraries, either paths or
168 * namespace/object names if a deps file was provided.
169 * @return {Array.<string>} List of paths to load.
170 */
171 function resolveLibraries(libraries) {
172 var resultPaths = [];
173 var addedPaths = {};
174
175 function addPath(path) {
176 addedPaths[path] = true;
177 resultPaths.push(path);
178 }
179
180 function resolveAndAppend(path) {
181 if (addedPaths[path]) {
182 return;
183 }
184 // Set before recursing to catch cycles.
185 addedPaths[path] = true;
186 dependencyPathsToRequires[path].forEach(function(require) {
187 var providingPath = dependencyProvidesToPaths[require];
188 if (!providingPath) {
189 print('Unknown object', require, 'required by', path);
190 quit(-1);
191 }
192 resolveAndAppend(providingPath);
193 });
194 resultPaths.push(path);
195 }
196
197 // Always add closure libaries base.js if provided by deps.
David Tseng 2014/05/30 17:08:46 libraries
198 var basePath = dependencyProvidesToPaths['goog'];
199 if (basePath) {
200 addPath(basePath);
201 }
202
203 libraries.forEach(function(library) {
204 var providingPath = dependencyProvidesToPaths[library];
205 if (providingPath) {
206 resolveAndAppend(providingPath);
207 } else {
208 var basePath = includeFileToPaths(library).base;
209 if (!addedPaths[basePath]) {
210 addPath(basePath);
211 }
212 }
213 });
214
215 return resultPaths;
216 }
217
117 /** 218 /**
118 * Output |code| verbatim. 219 * Output |code| verbatim.
119 * @param {string} code The code to output. 220 * @param {string} code The code to output.
120 */ 221 */
121 function GEN(code) { 222 function GEN(code) {
122 print(code); 223 print(code);
123 } 224 }
124 225
125 /** 226 /**
126 * Generate includes for the current |jsFile| by including them 227 * Generate includes for the current |jsFile| by including them
(...skipping 21 matching lines...) Expand all
148 var browsePreload = this[testFixture].prototype.browsePreload; 249 var browsePreload = this[testFixture].prototype.browsePreload;
149 var browsePrintPreload = this[testFixture].prototype.browsePrintPreload; 250 var browsePrintPreload = this[testFixture].prototype.browsePrintPreload;
150 var testGenPreamble = this[testFixture].prototype.testGenPreamble; 251 var testGenPreamble = this[testFixture].prototype.testGenPreamble;
151 var testGenPostamble = this[testFixture].prototype.testGenPostamble; 252 var testGenPostamble = this[testFixture].prototype.testGenPostamble;
152 var typedefCppFixture = this[testFixture].prototype.typedefCppFixture; 253 var typedefCppFixture = this[testFixture].prototype.typedefCppFixture;
153 var isAsyncParam = testType === 'unit' ? '' : 254 var isAsyncParam = testType === 'unit' ? '' :
154 this[testFixture].prototype.isAsync + ', '; 255 this[testFixture].prototype.isAsync + ', ';
155 var testShouldFail = this[testFixture].prototype.testShouldFail; 256 var testShouldFail = this[testFixture].prototype.testShouldFail;
156 var testPredicate = testShouldFail ? 'ASSERT_FALSE' : 'ASSERT_TRUE'; 257 var testPredicate = testShouldFail ? 'ASSERT_FALSE' : 'ASSERT_TRUE';
157 var extraLibraries = genIncludes.concat( 258 var extraLibraries = genIncludes.concat(
158 this[testFixture].prototype.extraLibraries.map( 259 resolveLibraries(this[testFixture].prototype.extraLibraries));
David Tseng 2014/05/30 17:08:46 Nice.
159 function(includeFile) {
160 return includeFileToPaths(includeFile).base;
161 }));
162 260
163 if (typedefCppFixture && !(testFixture in typedeffedCppFixtures)) { 261 if (typedefCppFixture && !(testFixture in typedeffedCppFixtures)) {
164 print('typedef ' + typedefCppFixture + ' ' + testFixture + ';'); 262 print('typedef ' + typedefCppFixture + ' ' + testFixture + ';');
165 typedeffedCppFixtures[testFixture] = typedefCppFixture; 263 typedeffedCppFixtures[testFixture] = typedefCppFixture;
166 } 264 }
167 265
168 print(testF + '(' + testFixture + ', ' + testFunction + ') {'); 266 print(testF + '(' + testFixture + ', ' + testFunction + ') {');
169 for (var i = 0; i < extraLibraries.length; i++) { 267 for (var i = 0; i < extraLibraries.length; i++) {
170 print(' AddLibrary(base::FilePath(FILE_PATH_LITERAL("' + 268 print(' AddLibrary(base::FilePath(FILE_PATH_LITERAL("' +
171 extraLibraries[i].replace(/\\/g, '/') + '")));'); 269 extraLibraries[i].replace(/\\/g, '/') + '")));');
(...skipping 17 matching lines...) Expand all
189 '"' + testFunction + '"));'); 287 '"' + testFunction + '"));');
190 if (testGenPostamble) 288 if (testGenPostamble)
191 testGenPostamble(testFixture, testFunction); 289 testGenPostamble(testFixture, testFunction);
192 print('}'); 290 print('}');
193 print(); 291 print();
194 } 292 }
195 293
196 // Now that generation functions are defined, load in |jsFile|. 294 // Now that generation functions are defined, load in |jsFile|.
197 var js = read(jsFile); 295 var js = read(jsFile);
198 eval(js); 296 eval(js);
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698