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

Unified 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, 7 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 side-by-side diff with in-line comments
Download patch
Index: chrome/test/base/js2gtest.js
diff --git a/chrome/test/base/js2gtest.js b/chrome/test/base/js2gtest.js
index a13ad87c719744257b25ee3ff8c19bddb64e8888..a066d549bfd6378ad942c037bedf6f7ba35ee5d4 100644
--- a/chrome/test/base/js2gtest.js
+++ b/chrome/test/base/js2gtest.js
@@ -15,9 +15,10 @@
// Arguments from rules in chrome_tests.gypi are passed in through
// python script gypv8sh.py.
-if (arguments.length < 4) {
+if (arguments.length != 6) {
print('usage: ' +
- arguments[0] + ' path-to-testfile.js testfile.js output.cc test-type');
+ arguments[0] +
+ ' path-to-testfile.js testfile.js path_to_deps.js output.cc test-type');
quit(-1);
}
@@ -35,16 +36,22 @@ var jsFile = arguments[1];
var jsFileBase = arguments[2];
/**
+ * Path to Closure library style deps.js file.
+ * @type {string?}
+ */
+var depsFile = arguments[3];
+
+/**
* Path to C++ file generation is outputting to.
* @type {string}
*/
-var outputFile = arguments[3];
+var outputFile = arguments[4];
/**
* Type of this test.
* @type {string} ('unit'| 'webui')
*/
-var testType = arguments[4];
+var testType = arguments[5];
/**
* C++ gtest macro to use for TEST_F depending on |testType|.
@@ -114,6 +121,100 @@ function includeFileToPaths(includeFile) {
};
}
+
+/**
+ * Maps namespace/object names to the path to the file that provides them.
+ * Populated from the |depsFile| if any.
+ * @type {Object.<string, string>}
+ */
+var dependencyProvidesToPaths = {};
+
+/**
+ * For each path included in the |depsFile|, if any, contains
+ * the list of object/namespace names required by the file.
+ * @type {Object.<string, Array.<string>>}
+ */
+var dependencyPathsToRequires = {};
+
+if (depsFile) {
+ var goog = goog || {};
+ /**
+ * Called by the javascript in the deps file to add modules and their
+ * dependencies.
+ * @param {string} path Relative path to the file.
+ * @param Array.<string> provides Objects provided by this file.
+ * @param Array.<string> requires Objects required by this file.
+ */
+ goog.addDependency = function(path, provides, requires) {
+ provides.forEach(function(provide) {
+ dependencyProvidesToPaths[provide] = path;
+ });
+ dependencyPathsToRequires[path] = requires;
+ };
+
+ // Read and eval the deps file. It should only contain goog.addDependency
+ // calls.
+ eval(read(depsFile));
+}
+
+/**
+ * Resolves a list of libraries to an ordered list of paths to load by the
+ * generated C++. The input can contain paths relative to the test script and,
+ * if a deps file was provided, namespace/object names provided by the
+ * deps file. For the latter case, dependencies will be resolved and
+ * included in the correct order, meaning that the returned array may contain
+ * more entries than the input.
+ * @param {Array.<string>} libraries List of libraries, either paths or
+ * namespace/object names if a deps file was provided.
+ * @return {Array.<string>} List of paths to load.
+ */
+function resolveLibraries(libraries) {
+ var resultPaths = [];
+ var addedPaths = {};
+
+ function addPath(path) {
+ addedPaths[path] = true;
+ resultPaths.push(path);
+ }
+
+ function resolveAndAppend(path) {
+ if (addedPaths[path]) {
+ return;
+ }
+ // Set before recursing to catch cycles.
+ addedPaths[path] = true;
+ dependencyPathsToRequires[path].forEach(function(require) {
+ var providingPath = dependencyProvidesToPaths[require];
+ if (!providingPath) {
+ print('Unknown object', require, 'required by', path);
+ quit(-1);
+ }
+ resolveAndAppend(providingPath);
+ });
+ resultPaths.push(path);
+ }
+
+ // Always add closure libaries base.js if provided by deps.
David Tseng 2014/05/30 17:08:46 libraries
+ var basePath = dependencyProvidesToPaths['goog'];
+ if (basePath) {
+ addPath(basePath);
+ }
+
+ libraries.forEach(function(library) {
+ var providingPath = dependencyProvidesToPaths[library];
+ if (providingPath) {
+ resolveAndAppend(providingPath);
+ } else {
+ var basePath = includeFileToPaths(library).base;
+ if (!addedPaths[basePath]) {
+ addPath(basePath);
+ }
+ }
+ });
+
+ return resultPaths;
+}
+
/**
* Output |code| verbatim.
* @param {string} code The code to output.
@@ -155,10 +256,7 @@ function TEST_F(testFixture, testFunction, testBody) {
var testShouldFail = this[testFixture].prototype.testShouldFail;
var testPredicate = testShouldFail ? 'ASSERT_FALSE' : 'ASSERT_TRUE';
var extraLibraries = genIncludes.concat(
- this[testFixture].prototype.extraLibraries.map(
- function(includeFile) {
- return includeFileToPaths(includeFile).base;
- }));
+ resolveLibraries(this[testFixture].prototype.extraLibraries));
David Tseng 2014/05/30 17:08:46 Nice.
if (typedefCppFixture && !(testFixture in typedeffedCppFixtures)) {
print('typedef ' + typedefCppFixture + ' ' + testFixture + ';');

Powered by Google App Engine
This is Rietveld 408576698