Commit d593dea8 authored by hansmuller's avatar hansmuller Committed by Commit bot

Mojo JS validation unit test should check Connection et al

Replaced the test for validation of requests and responses
with one that relies on the Connection et al classes to set
up the validators and deliver messages.

BUG=413303

Review URL: https://codereview.chromium.org/551293004

Cr-Commit-Position: refs/heads/master@{#294924}
parent e92897b3
...@@ -218,9 +218,11 @@ ...@@ -218,9 +218,11 @@
'dependencies': [ 'dependencies': [
'../gin/gin.gyp:gin_test', '../gin/gin.gyp:gin_test',
'mojo_common_test_support', 'mojo_common_test_support',
'mojo_environment_standalone',
'mojo_js_bindings_lib', 'mojo_js_bindings_lib',
'mojo_public_test_interfaces', 'mojo_public_test_interfaces',
'mojo_run_all_unittests', 'mojo_run_all_unittests',
'mojo_utility',
], ],
'sources': [ 'sources': [
'public/js/bindings/tests/run_js_tests.cc', 'public/js/bindings/tests/run_js_tests.cc',
......
...@@ -3,11 +3,15 @@ ...@@ -3,11 +3,15 @@
// found in the LICENSE file. // found in the LICENSE file.
define("mojo/public/js/bindings/connection", [ define("mojo/public/js/bindings/connection", [
"mojo/public/js/bindings/connector",
"mojo/public/js/bindings/router", "mojo/public/js/bindings/router",
], function(router) { ], function(connector, router) {
function Connection(handle, localFactory, remoteFactory) { function Connection(
this.router_ = new router.Router(handle); handle, localFactory, remoteFactory, routerFactory, connectorFactory) {
if (routerFactory === undefined)
routerFactory = router.Router;
this.router_ = new routerFactory(handle, connectorFactory);
this.remote = new remoteFactory(this.router_); this.remote = new remoteFactory(this.router_);
this.local = new localFactory(this.remote); this.local = new localFactory(this.remote);
this.router_.setIncomingReceiver(this.local); this.router_.setIncomingReceiver(this.local);
...@@ -33,7 +37,21 @@ define("mojo/public/js/bindings/connection", [ ...@@ -33,7 +37,21 @@ define("mojo/public/js/bindings/connection", [
return this.router_.encounteredError(); return this.router_.encounteredError();
}; };
// The TestConnection subclass is only intended to be used in unit tests.
function TestConnection(handle, localFactory, remoteFactory) {
Connection.call(this,
handle,
localFactory,
remoteFactory,
router.TestRouter,
connector.TestConnector);
}
TestConnection.prototype = Object.create(Connection.prototype);
var exports = {}; var exports = {};
exports.Connection = Connection; exports.Connection = Connection;
exports.TestConnection = TestConnection;
return exports; return exports;
}); });
...@@ -104,7 +104,24 @@ define("mojo/public/js/bindings/connector", [ ...@@ -104,7 +104,24 @@ define("mojo/public/js/bindings/connector", [
} }
}; };
// The TestConnector subclass is only intended to be used in unit tests. It
// enables delivering a message to the pipe's handle without an async wait.
function TestConnector(handle) {
Connector.call(this, handle);
}
TestConnector.prototype = Object.create(Connector.prototype);
TestConnector.prototype.waitToReadMore_ = function() {
};
TestConnector.prototype.deliverMessage = function() {
this.readMore_(core.RESULT_OK);
}
var exports = {}; var exports = {};
exports.Connector = Connector; exports.Connector = Connector;
exports.TestConnector = TestConnector;
return exports; return exports;
}); });
...@@ -8,8 +8,10 @@ define("mojo/public/js/bindings/router", [ ...@@ -8,8 +8,10 @@ define("mojo/public/js/bindings/router", [
"mojo/public/js/bindings/validator", "mojo/public/js/bindings/validator",
], function(codec, connector, validator) { ], function(codec, connector, validator) {
function Router(handle) { function Router(handle, connectorFactory) {
this.connector_ = new connector.Connector(handle); if (connectorFactory === undefined)
connectorFactory = connector.Connector;
this.connector_ = new connectorFactory(handle);
this.incomingReceiver_ = null; this.incomingReceiver_ = null;
this.nextRequestID_ = 0; this.nextRequestID_ = 0;
this.responders_ = {}; this.responders_ = {};
...@@ -71,9 +73,14 @@ define("mojo/public/js/bindings/router", [ ...@@ -71,9 +73,14 @@ define("mojo/public/js/bindings/router", [
var err = messageValidator.validateMessageHeader(); var err = messageValidator.validateMessageHeader();
for (var i = 0; err === noError && i < this.payloadValidators_.length; ++i) for (var i = 0; err === noError && i < this.payloadValidators_.length; ++i)
err = this.payloadValidators_[i](messageValidator); err = this.payloadValidators_[i](messageValidator);
if (err !== noError)
this.close();
if (err == noError)
this.handleValidIncomingMessage_(message);
else
this.handleInvalidIncomingMessage_(message, err);
};
Router.prototype.handleValidIncomingMessage_ = function(message) {
if (message.expectsResponse()) { if (message.expectsResponse()) {
if (this.incomingReceiver_) { if (this.incomingReceiver_) {
this.incomingReceiver_.acceptWithResponder(message, this); this.incomingReceiver_.acceptWithResponder(message, this);
...@@ -92,7 +99,11 @@ define("mojo/public/js/bindings/router", [ ...@@ -92,7 +99,11 @@ define("mojo/public/js/bindings/router", [
if (this.incomingReceiver_) if (this.incomingReceiver_)
this.incomingReceiver_.accept(message); this.incomingReceiver_.accept(message);
} }
}; }
Router.prototype.handleInvalidIncomingMessage_ = function(message, error) {
this.close();
}
Router.prototype.handleConnectionError_ = function(result) { Router.prototype.handleConnectionError_ = function(result) {
for (var each in this.responders_) for (var each in this.responders_)
...@@ -100,7 +111,25 @@ define("mojo/public/js/bindings/router", [ ...@@ -100,7 +111,25 @@ define("mojo/public/js/bindings/router", [
this.close(); this.close();
}; };
// The TestRouter subclass is only intended to be used in unit tests.
// It defeats valid message handling and delgates invalid message handling.
function TestRouter(handle, connectorFactory) {
Router.call(this, handle, connectorFactory);
}
TestRouter.prototype = Object.create(Router.prototype);
TestRouter.prototype.handleValidIncomingMessage_ = function() {
};
TestRouter.prototype.handleInvalidIncomingMessage_ =
function(message, error) {
this.validationErrorHandler(error);
};
var exports = {}; var exports = {};
exports.Router = Router; exports.Router = Router;
exports.TestRouter = TestRouter;
return exports; return exports;
}); });
...@@ -6,11 +6,12 @@ ...@@ -6,11 +6,12 @@
test("mojo_js_unittests") { test("mojo_js_unittests") {
deps = [ deps = [
"//gin:gin_test", "//gin:gin_test",
"//mojo/common/test:run_all_unittests",
"//mojo/common/test:test_support", "//mojo/common/test:test_support",
"//mojo/environment:chromium", "//mojo/public/cpp/environment:standalone",
"//mojo/public/interfaces/bindings/tests:test_interfaces",
"//mojo/bindings/js", "//mojo/bindings/js",
"//mojo/public/interfaces/bindings/tests:test_interfaces",
"//mojo/common/test:run_all_unittests",
"//mojo/public/cpp/utility",
] ]
sources = [ "run_js_tests.cc" ] sources = [ "run_js_tests.cc" ]
......
...@@ -3,4 +3,5 @@ include_rules = [ ...@@ -3,4 +3,5 @@ include_rules = [
"+gin", "+gin",
"+v8", "+v8",
"+mojo/bindings/js/core.h", "+mojo/bindings/js/core.h",
"+mojo/bindings/js/support.h",
] ]
...@@ -10,6 +10,8 @@ ...@@ -10,6 +10,8 @@
#include "gin/test/file_runner.h" #include "gin/test/file_runner.h"
#include "gin/test/gtest.h" #include "gin/test/gtest.h"
#include "mojo/bindings/js/core.h" #include "mojo/bindings/js/core.h"
#include "mojo/bindings/js/support.h"
#include "mojo/public/cpp/environment/environment.h"
#include "testing/gtest/include/gtest/gtest.h" #include "testing/gtest/include/gtest/gtest.h"
namespace mojo { namespace mojo {
...@@ -21,6 +23,7 @@ class TestRunnerDelegate : public gin::FileRunnerDelegate { ...@@ -21,6 +23,7 @@ class TestRunnerDelegate : public gin::FileRunnerDelegate {
TestRunnerDelegate() { TestRunnerDelegate() {
AddBuiltinModule(gin::Console::kModuleName, gin::Console::GetModule); AddBuiltinModule(gin::Console::kModuleName, gin::Console::GetModule);
AddBuiltinModule(Core::kModuleName, Core::GetModule); AddBuiltinModule(Core::kModuleName, Core::GetModule);
AddBuiltinModule(Support::kModuleName, Support::GetModule);
} }
private: private:
...@@ -28,6 +31,7 @@ class TestRunnerDelegate : public gin::FileRunnerDelegate { ...@@ -28,6 +31,7 @@ class TestRunnerDelegate : public gin::FileRunnerDelegate {
}; };
void RunTest(std::string test, bool run_until_idle) { void RunTest(std::string test, bool run_until_idle) {
Environment env;
base::FilePath path; base::FilePath path;
PathService::Get(base::DIR_SOURCE_ROOT, &path); PathService::Get(base::DIR_SOURCE_ROOT, &path);
path = path.AppendASCII("mojo") path = path.AppendASCII("mojo")
......
...@@ -9,10 +9,26 @@ define([ ...@@ -9,10 +9,26 @@ define([
"mojo/public/interfaces/bindings/tests/validation_test_interfaces.mojom", "mojo/public/interfaces/bindings/tests/validation_test_interfaces.mojom",
"mojo/public/js/bindings/buffer", "mojo/public/js/bindings/buffer",
"mojo/public/js/bindings/codec", "mojo/public/js/bindings/codec",
"mojo/public/js/bindings/connection",
"mojo/public/js/bindings/connector",
"mojo/public/js/bindings/core",
"mojo/public/js/bindings/tests/validation_test_input_parser", "mojo/public/js/bindings/tests/validation_test_input_parser",
"mojo/public/js/bindings/router",
"mojo/public/js/bindings/validator", "mojo/public/js/bindings/validator",
], function( ], function(console,
console, file, expect, testInterface, buffer, codec, parser, validator) { file,
expect,
testInterface,
buffer,
codec,
connection,
connector,
core,
parser,
router,
validator) {
var noError = validator.validationError.NONE;
function checkTestMessageParser() { function checkTestMessageParser() {
function TestMessageParserFailure(message, input) { function TestMessageParserFailure(message, input) {
...@@ -196,11 +212,18 @@ define([ ...@@ -196,11 +212,18 @@ define([
return contents.trim(); return contents.trim();
} }
function checkValidationResult(testFile, err) {
var actualResult = (err === noError) ? "PASS" : err;
var expectedResult = readTestExpected(testFile);
if (actualResult != expectedResult)
console.log("[Test message validation failed: " + testFile + " ]");
expect(actualResult).toEqual(expectedResult);
}
function testMessageValidation(key, filters) { function testMessageValidation(key, filters) {
var testFiles = getMessageTestFiles(key); var testFiles = getMessageTestFiles(key);
expect(testFiles.length).toBeGreaterThan(0); expect(testFiles.length).toBeGreaterThan(0);
var noError = validator.validationError.NONE;
for (var i = 0; i < testFiles.length; i++) { for (var i = 0; i < testFiles.length; i++) {
// TODO(hansmuller): Temporarily skipping array pointer overflow tests. // TODO(hansmuller): Temporarily skipping array pointer overflow tests.
if (testFiles[i].indexOf("overflow") != -1) { if (testFiles[i].indexOf("overflow") != -1) {
...@@ -217,11 +240,7 @@ define([ ...@@ -217,11 +240,7 @@ define([
for (var j = 0; err === noError && j < filters.length; ++j) for (var j = 0; err === noError && j < filters.length; ++j)
err = filters[j](messageValidator); err = filters[j](messageValidator);
var actualResult = (err === noError) ? "PASS" : err; checkValidationResult(testFiles[i], err);
var expectedResult = readTestExpected(testFiles[i]);
if (actualResult != expectedResult)
console.log("[Test message validation failed: " + testFiles[i] + " ]");
expect(actualResult).toEqual(expectedResult);
} }
} }
...@@ -235,14 +254,49 @@ define([ ...@@ -235,14 +254,49 @@ define([
testInterface.ConformanceTestInterfaceStub.prototype.validator]); testInterface.ConformanceTestInterfaceStub.prototype.validator]);
} }
function testIntegrationMessageValidation() { function testIntegratedMessageValidation() {
testMessageValidation("integration_", [ var testFiles = getMessageTestFiles("integration_");
testInterface.IntegrationTestInterface1Stub.prototype.validator, expect(testFiles.length).toBeGreaterThan(0);
testInterface.IntegrationTestInterface2Proxy.prototype.validator]);
for (var i = 0; i < testFiles.length; i++) {
// TODO(hansmuller): Temporarily skipping array pointer overflow tests.
if (testFiles[i].indexOf("overflow") != -1) {
console.log("[Skipping " + testFiles[i] + "]");
continue;
}
var testMessage = readTestMessage(testFiles[i]);
var handles = new Array(testMessage.handleCount);
var testMessagePipe = new core.createMessagePipe();
expect(testMessagePipe.result).toBe(core.RESULT_OK);
var writeMessageValue = core.writeMessage(
testMessagePipe.handle0,
new Uint8Array(testMessage.buffer.arrayBuffer),
new Array(testMessage.handleCount),
core.WRITE_MESSAGE_FLAG_NONE);
expect(writeMessageValue).toBe(core.RESULT_OK);
var testConnection = new connection.TestConnection(
testMessagePipe.handle1,
testInterface.IntegrationTestInterface1Stub,
testInterface.IntegrationTestInterface2Proxy);
var validationError = noError;
testConnection.router_.validationErrorHandler = function(err) {
validationError = err;
}
testConnection.router_.connector_.deliverMessage();
checkValidationResult(testFiles[i], validationError);
testConnection.close();
expect(core.close(testMessagePipe.handle0)).toBe(core.RESULT_OK);
}
} }
expect(checkTestMessageParser()).toBeNull(); expect(checkTestMessageParser()).toBeNull();
testConformanceMessageValidation(); testConformanceMessageValidation();
testIntegrationMessageValidation(); testIntegratedMessageValidation();
this.result = "PASS"; this.result = "PASS";
}); });
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment