Import code from internal repository to git

This commit is contained in:
Justine Tunney 2016-03-01 17:18:14 -05:00
commit 0ef0c933d2
2490 changed files with 281594 additions and 0 deletions

26
third_party/closure/testing/BUILD vendored Normal file
View file

@ -0,0 +1,26 @@
package(default_visibility = ["//visibility:public"])
licenses(["notice"]) # Apache License 2.0
load("//third_party/closure/compiler:closure_js_check_test.bzl", "closure_js_check_test")
exports_files([
"phantomjs_jsunit_runner.js",
"phantomjs_runner.js",
])
closure_js_check_test(
name = "phantomjs_jsunit_runner_check",
srcs = ["phantomjs_jsunit_runner.js"],
pedantic = 1,
visibility = ["//visibility:private"],
deps = ["//third_party/closure/library"],
)
closure_js_check_test(
name = "phantomjs_runner_check",
srcs = ["phantomjs_runner.js"],
externs_list = ["externs/phantom.js"],
pedantic = 1,
visibility = ["//visibility:private"],
)

View file

@ -0,0 +1,116 @@
# -*- mode: python; -*-
#
# Copyright 2016 Google Inc. All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""Build rule for running Closure Library JsUnit tests in PhantomJS.
"""
# XXX: It would be significantly faster and produce better stacktraces if we
# could avoid compilation by running in raw sources mode. This is not
# possible due to a resource loading bug in PhantomJS.
# https://github.com/ariya/phantomjs/issues/14028
load("//third_party/closure/compiler/private:defs.bzl",
"JS_HIDE_WARNING_ARGS",
"JS_LANGUAGE_DEFAULT",
"JS_LIBRARY_ATTRS",
"JS_PEDANTIC_ARGS",
"collect_js_srcs",
"determine_js_language")
def _impl(ctx):
srcs, externs = collect_js_srcs(ctx)
srcs += [ctx.file._phantomjs_jsunit_runner]
args = [
"--js_output_file=%s" % ctx.outputs.js.path,
"--language_in=%s" % determine_js_language(ctx),
"--language_out=ECMASCRIPT5_STRICT",
"--compilation_level=WHITESPACE_ONLY",
"--warning_level=VERBOSE",
"--dependency_mode=LOOSE",
"--formatting=PRETTY_PRINT",
"--new_type_inf",
"--debug",
]
if ctx.attr.pedantic:
args += JS_PEDANTIC_ARGS
args += JS_HIDE_WARNING_ARGS
args += ["--externs=%s" % extern.path for extern in externs]
args += ["--js=%s" % src.path for src in srcs]
ctx.action(
inputs=list(srcs) + list(externs),
outputs=[ctx.outputs.js],
executable=ctx.executable._compiler,
arguments=args,
mnemonic="JSCompile",
progress_message="Compiling %d JavaScript files to %s" % (
len(srcs) + len(externs), ctx.outputs.js.short_path))
ctx.file_action(
executable=True,
output=ctx.outputs.executable,
content="\n".join([
"#!/bin/sh",
"exec %s \\\n %s \\\n %s\n" % (
ctx.file._phantomjs.short_path,
ctx.file._phantomjs_runner.short_path,
ctx.outputs.js.short_path),
]))
return struct(
files=set([ctx.outputs.executable,
ctx.outputs.js]),
runfiles=ctx.runfiles(files=[ctx.file._phantomjs,
ctx.file._phantomjs_runner,
ctx.outputs.js],
collect_data=True))
_closure_js_test = rule(
test=True,
implementation=_impl,
attrs=JS_LIBRARY_ATTRS + {
"language": attr.string(default=JS_LANGUAGE_DEFAULT),
"pedantic": attr.bool(default=False),
"_compiler": attr.label(
default=Label("//third_party/closure/compiler"),
executable=True),
"_phantomjs": attr.label(
default=Label("//third_party/phantomjs"),
allow_files=True,
single_file=True),
"_phantomjs_runner": attr.label(
default=Label("//third_party/closure/testing:phantomjs_runner.js"),
allow_files=True,
single_file=True),
"_phantomjs_jsunit_runner": attr.label(
default=Label(
"//third_party/closure/testing:phantomjs_jsunit_runner.js"),
allow_files=True,
single_file=True),
},
outputs={"js": "%{name}_dbg.js"})
# XXX: In compiled mode, we're forced to compile each test file individually,
# because tests might have overlapping global symbols. We compile in
# WHITESPACE_ONLY mode because other modes would be unreasonably slow.
def closure_js_test(name, srcs, **kwargs):
if len(srcs) == 1:
_closure_js_test(name = name, srcs = srcs, **kwargs)
else:
tests = []
for src in srcs:
test = name + '_' + src.replace('_test.js', '').replace('-', '_')
tests += [test]
_closure_js_test(name = test, srcs = [src], **kwargs)
native.test_suite(name = name, tests = tests)

View file

@ -0,0 +1,282 @@
// Copyright 2016 Google Inc. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
/**
* @fileoverview PhantomJS API definitions. We're only defining the parts of
* the API we plan on using. This file is necessary in order to have 100%
* strict type safety in {@code testrunner.js}.
* @externs
* @see http://phantomjs.org/api/
*/
/**
* Fake namespace for PhantomJS types.
*/
var phantomjs = {};
/**
* @constructor
* @final
* @see https://github.com/ariya/phantomjs/blob/master/examples/stdin-stdout-stderr.js
*/
phantomjs.File = function() {};
/**
* @param {string} text
* @const
*/
phantomjs.File.prototype.write = function(text) {};
/**
* @param {string} text
* @const
*/
phantomjs.File.prototype.writeLine = function(text) {};
/**
* @constructor
* @final
* @see http://phantomjs.org/api/system/
*/
phantomjs.System = function() {};
/**
* @type {!Array<string>}
* @const
*/
phantomjs.System.prototype.args;
/**
* @type {!phantomjs.File}
* @const
*/
phantomjs.System.prototype.stdout;
/**
* @type {!phantomjs.File}
* @const
*/
phantomjs.System.prototype.stderr;
/**
* @constructor
* @final
* @see http://phantomjs.org/api/fs/
*/
phantomjs.FileSystem = function() {};
/**
* @param {string} path
* @return {boolean}
*/
phantomjs.FileSystem.prototype.exists = function(path) {};
/**
* @param {string} path
* @return {string}
*/
phantomjs.FileSystem.prototype.read = function(path) {};
/**
* @constructor
* @final
*/
phantomjs.WebPage = function() {};
/**
* @return {!phantomjs.Page}
*/
phantomjs.WebPage.prototype.create = function() {};
/**
* @constructor
* @final
*/
phantomjs.PageSettings = function() {};
/**
* @type {number}
*/
phantomjs.PageSettings.prototype.resourceTimeout;
/**
* @constructor
* @final
*/
phantomjs.Page = function() {};
/**
* @param {string} url
* @param {function(string)=} opt_callback
*/
phantomjs.Page.prototype.open = function(url, opt_callback) {};
phantomjs.Page.prototype.close = function() {};
/**
* @param {function(): T} callback
* @return {T}
* @template T
*/
phantomjs.Page.prototype.evaluate = function(callback) {};
/**
* @type {!phantomjs.PageSettings}
* @const
*/
phantomjs.Page.prototype.settings;
/**
* @constructor
* @final
* @see http://phantomjs.org/api/webserver/
*/
phantomjs.Server = function() {};
/**
* @type {number}
*/
phantomjs.Server.prototype.port;
/**
* @param {number} port
* @param {function(!phantomjs.Server.Request,
* !phantomjs.Server.Response)} callback
*/
phantomjs.Server.prototype.listen = function(port, callback) {};
/**
* @constructor
* @final
* @see http://phantomjs.org/api/webserver/method/listen.html
*/
phantomjs.Server.Request = function() {};
/**
* @type {string}
* @const
*/
phantomjs.Server.Request.prototype.url;
/**
* @constructor
* @final
* @see http://phantomjs.org/api/webserver/method/listen.html
*/
phantomjs.Server.Response = function() {};
/**
* @param {string} encoding
*/
phantomjs.Server.Response.prototype.setEncoding = function(encoding) {};
/**
* @param {number} statusCode
* @param {!Object<string, string>=} opt_headers
*/
phantomjs.Server.Response.prototype.writeHead =
function(statusCode, opt_headers) {};
/**
* @param {string} data
*/
phantomjs.Server.Response.prototype.write = function(data) {};
phantomjs.Server.Response.prototype.close = function() {};
phantomjs.Server.Response.prototype.closeGracefully = function() {};
/**
* @constructor
* @final
* @see http://phantomjs.org/api/webserver/
*/
phantomjs.WebServer = function() {};
/**
* @return {!phantomjs.Server}
*/
phantomjs.WebServer.prototype.create = function() {};
/**
* @constructor
* @final
* @see http://phantomjs.org/api/phantom/
*/
phantomjs.Phantom = function() {};
/**
* @param {number=} opt_status
*/
phantomjs.Phantom.prototype.exit = function(opt_status) {};
/**
* @type {!phantomjs.Phantom}
* @const
*/
var phantom;
/**
* @param {string} name
* @return {?}
*/
function require(name) {}

View file

@ -0,0 +1,30 @@
// Copyright 2016 Google Inc. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
/**
* @fileoverview PhantomJS test runner in-browser code. This file loads Closure
* testing libraries and then polls for test completion and then sends a
* message to PhantomJS letting it know it can exit.
*/
goog.require('goog.testing.jsunit');
(function() {
window.setInterval(function() {
if (window['G_testRunner'].isFinished()) {
window['callPhantom'](window['G_testRunner'].isSuccess());
}
}, 200);
})();

View file

@ -0,0 +1,285 @@
// Copyright 2016 Google Inc. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
/**
* @fileoverview PhantomJS headless browser container for Closure unit tests.
* This program runs inside PhantomJS but not inside the browser itself. It
* starts an HTTP server that serves runfiles. It loads the generated test
* runner HTML file inside an ethereal browser. Once the page is loaded,
* this program communicates with the page to collect log data and monitor
* whether or not the tests succeeded.
*/
'use strict';
var /** !phantomjs.WebPage */ webpage = require('webpage');
var /** !phantomjs.FileSystem */ fs = require('fs');
var /** !phantomjs.WebServer */ webserver = require('webserver');
var /** !phantomjs.System */ system = require('system');
/**
* Location of virtual test page.
* @type {string}
* @const
*/
var VIRTUAL_PAGE = '/index.html';
/**
* Path under which runfiles are served.
* @type {string}
* @const
*/
var RUNFILES_PREFIX = '/filez/';
/**
* Full URL of virtual page.
* @type {string}
*/
var url;
/**
* HTML for virtual test page, hosted under {@code index.html}.
* @type {string}
*/
var virtualPageHtml;
/**
* Path of JS file to load.
* @type {string}
*/
var js;
/**
* PhantomJS page object.
* @type {!phantomjs.Page}
*/
var page = webpage.create();
/**
* Guesses Content-Type header for {@code path}
* @param {string} path
* @return {string}
*/
function guessContentType(path) {
switch (path.substr(path.lastIndexOf('.') + 1)) {
case 'js':
return 'application/javascript;charset=utf-8';
case 'html':
return 'text/html;charset=utf-8';
case 'css':
return 'text/css;charset=utf-8';
case 'txt':
return 'text/plain;charset=utf-8';
case 'xml':
return 'application/xml;charset=utf-8';
case 'gif':
return 'image/gif';
case 'png':
return 'image/png';
case 'jpg':
case 'jpeg':
return 'image/jpeg';
default:
return 'application/octet-stream';
}
}
/**
* Handles request from web browser.
* @param {!phantomjs.Server.Request} request
* @param {!phantomjs.Server.Response} response
*/
function onRequest(request, response) {
var path = request.url;
system.stderr.writeLine('Serving ' + path);
if (path == VIRTUAL_PAGE) {
response.writeHead(200, {
'Cache': 'no-cache',
'Content-Type': 'text/html;charset=utf-8'
});
response.write(virtualPageHtml);
response.closeGracefully();
} else if (path.indexOf(RUNFILES_PREFIX) == 0) {
path = path.substr(RUNFILES_PREFIX.length);
if (!fs.exists(path)) {
send404(request, response);
return;
}
var contentType = guessContentType(path);
if (contentType.indexOf('charset') != -1) {
response.setEncoding('binary');
}
response.writeHead(200, {
'Cache': 'no-cache',
'Content-Type': contentType
});
response.write(fs.read(path));
response.closeGracefully();
} else {
send404(request, response);
}
}
/**
* Sends a 404 Not Found response.
* @param {!phantomjs.Server.Request} request
* @param {!phantomjs.Server.Response} response
*/
function send404(request, response) {
system.stderr.writeLine('NOT FOUND ' + request.url);
response.writeHead(404, {
'Cache': 'no-cache',
'Content-Type': 'text/plain;charset=utf-8'
});
response.write('Not Found');
response.closeGracefully();
}
/**
* Extracts text from inside page.
* @return {string}
*/
function extractText() {
var element = document.getElementById('blah');
if (element != null) {
return element.innerText;
} else {
return '';
}
}
/**
* Callback when log entries are emitted inside the browser.
* @param {string} message
* @param {?string} line
* @param {?string} source
*/
function onConsoleMessage(message, line, source) {
message = message.replace(/\r?\n/, '\n-> ');
if (line && source) {
system.stderr.writeLine('-> ' + source + ':' + line + '] ' + message);
} else {
system.stderr.writeLine('-> ' + message);
}
}
/**
* Callback when headless web page is loaded.
* @param {string} status
*/
function onLoadFinished(status) {
if (status != 'success') {
system.stderr.writeLine('Load Failed');
phantom.exit(1);
return;
}
}
/**
* Callback when webpage shows an alert dialog.
* @param {string} message
*/
function onAlert(message) {
system.stderr.writeLine('Alert: ' + message);
}
/**
* Callback when headless web page throws an error.
* @param {string} message
* @param {!Array<{file: string,
* line: number,
* function: string}>} trace
*/
function onError(message, trace) {
system.stderr.writeLine(message);
trace.forEach(function(t) {
var msg = '> ';
if (t.function != '') {
msg += t.function + ' at ';
}
msg += t.file + ':' + t.line;
system.stderr.writeLine(msg);
});
page.close();
phantom.exit(1);
}
/**
* Callback when JavaScript inside page sends us a message.
* @param {boolean} succeeded
*/
function onCallback(succeeded) {
page.close();
if (succeeded) {
phantom.exit();
} else {
phantom.exit(1);
}
}
/**
* Runs a single pending test.
*/
function run() {
virtualPageHtml =
'<!doctype html>\n' +
'<meta charset="utf-8">' +
'<body>\n' +
'</body>\n' +
// These definitions are only necessary because we're compiling in
// WHITESPACE_ONLY mode.
'<script>\n' +
' var CLOSURE_NO_DEPS = true;\n' +
' var CLOSURE_UNCOMPILED_DEFINES = {\n' +
' "goog.ENABLE_DEBUG_LOADER": false\n' +
' };\n' +
'</script>\n' +
'<script src="' + RUNFILES_PREFIX + js + '"></script>\n';
page.onAlert = onAlert;
page.onCallback = onCallback;
page.onConsoleMessage = onConsoleMessage;
page.onError = onError;
page.onLoadFinished = onLoadFinished;
// XXX: If PhantomJS croaks, fail sooner rather than later.
// https://github.com/ariya/phantomjs/issues/10652
page.settings.resourceTimeout = 2000;
page.open(url);
}
(function() {
js = system.args[1];
var port = Math.floor(Math.random() * (60000 - 32768)) + 32768;
var server = webserver.create();
server.listen(port, onRequest);
url = 'http://localhost:' + port + VIRTUAL_PAGE;
system.stderr.writeLine('Listening ' + url);
run();
})();