diff options
author | abarth@chromium.org <abarth@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-11-19 04:33:15 +0000 |
---|---|---|
committer | abarth@chromium.org <abarth@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-11-19 04:33:15 +0000 |
commit | be12cc446c38f5d149318e8282dd32b726c02640 (patch) | |
tree | c14985510a4a8e5aad43f6a9c4e77e0c8455a9d7 /mojo/public | |
parent | 1e70007669ac9740a0b80ba9b337be657c518328 (diff) | |
download | chromium_src-be12cc446c38f5d149318e8282dd32b726c02640.zip chromium_src-be12cc446c38f5d149318e8282dd32b726c02640.tar.gz chromium_src-be12cc446c38f5d149318e8282dd32b726c02640.tar.bz2 |
Port Mojo's sample_service.cc to JavaScript
This CL completes the manual implementation of sample_service.js and tests it
using sample_test.js, which exactly mirrors the testing of sample_service.cc by
sample_service.cc.
(I've also moved sample_service.js into mojo/public/bindings/sample/mojom to
better mirror the C++ implementation.)
BUG=317398
Review URL: https://codereview.chromium.org/68323004
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@235917 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'mojo/public')
-rw-r--r-- | mojo/public/bindings/js/codec.js | 8 | ||||
-rw-r--r-- | mojo/public/bindings/js/codec_unittests.js | 33 | ||||
-rw-r--r-- | mojo/public/bindings/js/core.cc | 3 | ||||
-rw-r--r-- | mojo/public/bindings/js/test/run_js_tests.cc | 12 | ||||
-rw-r--r-- | mojo/public/bindings/js/test/sample_service.js | 99 | ||||
-rw-r--r-- | mojo/public/bindings/sample/mojom/sample_service.js | 229 | ||||
-rw-r--r-- | mojo/public/bindings/sample/sample_test.js | 123 |
7 files changed, 406 insertions, 101 deletions
diff --git a/mojo/public/bindings/js/codec.js b/mojo/public/bindings/js/codec.js index b7dcbee..2df9c46 100644 --- a/mojo/public/bindings/js/codec.js +++ b/mojo/public/bindings/js/codec.js @@ -50,6 +50,12 @@ define(function() { return low + high * 0x10000; } + var kAlignment = 8; + + function align(size) { + return size + (kAlignment - (size % kAlignment)) % kAlignment; + } + // Buffer ------------------------------------------------------------------- function Buffer(size) { @@ -391,7 +397,7 @@ define(function() { }; var exports = {}; - exports.load32 = load32; + exports.align = align; exports.MessageBuilder = MessageBuilder; exports.MessageReader = MessageReader; exports.kArrayHeaderSize = kArrayHeaderSize; diff --git a/mojo/public/bindings/js/codec_unittests.js b/mojo/public/bindings/js/codec_unittests.js index 7fd23f6..f22791d 100644 --- a/mojo/public/bindings/js/codec_unittests.js +++ b/mojo/public/bindings/js/codec_unittests.js @@ -5,10 +5,11 @@ define([ "gtest", "mojo/public/bindings/js/codec", - "mojo/public/bindings/js/test/sample_service" + "mojo/public/bindings/sample/mojom/sample_service" ], function(gtest, codec, sample) { testBar(); testFoo(); + testAlign(); this.result = "PASS"; function barMatches(bar, expected) { @@ -161,4 +162,34 @@ define([ equalsArray(foo2.files, foo.files, "foo2.files"); } + + function testAlign() { + var aligned = [ + 0, // 0 + 8, // 1 + 8, // 2 + 8, // 3 + 8, // 4 + 8, // 5 + 8, // 6 + 8, // 7 + 8, // 8 + 16, // 9 + 16, // 10 + 16, // 11 + 16, // 12 + 16, // 13 + 16, // 14 + 16, // 15 + 16, // 16 + 24, // 17 + 24, // 18 + 24, // 19 + 24, // 20 + ]; + for (var i = 0; i < aligned.length; ++i) { + gtest.expectEqual(codec.align(i), aligned[i], + "codec.align(" + i + ") is " + codec.align(i)); + } + } }); diff --git a/mojo/public/bindings/js/core.cc b/mojo/public/bindings/js/core.cc index 9760ca0..6a048cf 100644 --- a/mojo/public/bindings/js/core.cc +++ b/mojo/public/bindings/js/core.cc @@ -156,6 +156,9 @@ v8::Local<v8::ObjectTemplate> Core::GetTemplate(v8::Isolate* isolate) { templ->Set(gin::StringToSymbol(isolate, "readMessage"), v8::FunctionTemplate::New(ReadMessage)); + templ->Set(gin::StringToSymbol(isolate, "kInvalidHandle"), + gin::ConvertToV8(isolate, mojo::kInvalidHandle)); + templ->Set(gin::StringToSymbol(isolate, "RESULT_OK"), gin::ConvertToV8(isolate, MOJO_RESULT_OK)); templ->Set(gin::StringToSymbol(isolate, "RESULT_CANCELLED"), diff --git a/mojo/public/bindings/js/test/run_js_tests.cc b/mojo/public/bindings/js/test/run_js_tests.cc index 00f7574..c558547 100644 --- a/mojo/public/bindings/js/test/run_js_tests.cc +++ b/mojo/public/bindings/js/test/run_js_tests.cc @@ -45,6 +45,18 @@ TEST(JSTest, codec) { RunTest("codec_unittests.js"); } +TEST(JSTest, sample_test) { + base::FilePath path; + PathService::Get(base::DIR_SOURCE_ROOT, &path); + path = path.AppendASCII("mojo") + .AppendASCII("public") + .AppendASCII("bindings") + .AppendASCII("sample") + .AppendASCII("sample_test.js"); + TestRunnerDelegate delegate; + gin::RunTestFromFile(path, &delegate); +} + } // namespace } // namespace js } // namespace mojo diff --git a/mojo/public/bindings/js/test/sample_service.js b/mojo/public/bindings/js/test/sample_service.js deleted file mode 100644 index 1885f7a..0000000 --- a/mojo/public/bindings/js/test/sample_service.js +++ /dev/null @@ -1,99 +0,0 @@ -// Copyright 2013 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// "Generated" code for sample_service.mojom -define([ - "mojo/public/bindings/js/codec", - ], function(codec) { - - // Bar ---------------------------------------------------------------------- - - function Bar() { - this.alpha = 0; - this.beta = 0; - this.gamma = 0; - } - - Bar.encodedSize = codec.kStructHeaderSize + 8; - - Bar.decode = function(decoder) { - var val = new Bar(); - var numberOfBytes = decoder.read32(); - var numberOfFields = decoder.read32(); - // TODO(abarth): We need to support optional fields. - val.alpha = decoder.read8(); - val.beta = decoder.read8(); - val.gamma = decoder.read8(); - decoder.skip(5); - return val; - }; - - Bar.encode = function(encoder, val) { - encoder.write32(Bar.encodedSize); - encoder.write32(3); - encoder.write8(val.alpha); - encoder.write8(val.beta); - encoder.write8(val.gamma); - encoder.skip(5); - }; - - // Foo ---------------------------------------------------------------------- - - function Foo() { - this.x = 0; - this.y = 0; - this.a = 0; - this.b = 0; - this.c = 0; - this.bar = null; - this.data = []; - this.extra_bars = []; - this.name = ""; - this.files = []; - } - - Foo.encodedSize = codec.kStructHeaderSize + 64; - - Foo.decode = function(decoder) { - var val = new Foo(); - var numberOfBytes = decoder.read32(); - var numberofFields = decoder.read32(); - // TODO(abarth): We need to support optional fields. - val.x = decoder.read32(); - val.y = decoder.read32(); - var packed = decoder.read8(); - val.a = (packed >> 0) & 1; - val.b = (packed >> 1) & 1; - val.c = (packed >> 2) & 1; - decoder.skip(7); - val.bar = decoder.decodeStructPointer(Bar); - val.data = decoder.decodeArrayPointer(codec.Uint8); - val.extra_bars = decoder.decodeArrayPointer(new codec.PointerTo(Bar)); - val.name = decoder.decodeStringPointer(); - val.files = decoder.decodeArrayPointer(codec.Handle); - return val; - } - - Foo.encode = function(encoder, val) { - encoder.write32(Foo.encodedSize); - encoder.write32(10); - encoder.write32(val.x); - encoder.write32(val.y); - var packed = (val.a & 1) << 0 | - (val.b & 1) << 1 | - (val.c & 1) << 2; - encoder.write8(packed); - encoder.skip(7); - encoder.encodeStructPointer(Bar, val.bar); - encoder.encodeArrayPointer(codec.Uint8, val.data); - encoder.encodeArrayPointer(new codec.PointerTo(Bar), val.extra_bars); - encoder.encodeStringPointer(val.name); - encoder.encodeArrayPointer(codec.Handle, val.files); - }; - - var exports = {}; - exports.Bar = Bar; - exports.Foo = Foo; - return exports; -}); diff --git a/mojo/public/bindings/sample/mojom/sample_service.js b/mojo/public/bindings/sample/mojom/sample_service.js new file mode 100644 index 0000000..081ed99 --- /dev/null +++ b/mojo/public/bindings/sample/mojom/sample_service.js @@ -0,0 +1,229 @@ +// Copyright 2013 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// "Generated" code for sample_service.mojom +define([ + "mojo/public/bindings/js/core", + "mojo/public/bindings/js/codec", + ], function(core, codec) { + + // Bar ---------------------------------------------------------------------- + + function Bar() { + this.alpha = 0; + this.beta = 0; + this.gamma = 0; + } + + Bar.encodedSize = codec.kStructHeaderSize + 8; + + Bar.decode = function(decoder) { + var val = new Bar(); + var numberOfBytes = decoder.read32(); + var numberOfFields = decoder.read32(); + // TODO(abarth): We need to support optional fields. + val.alpha = decoder.read8(); + val.beta = decoder.read8(); + val.gamma = decoder.read8(); + decoder.skip(5); + return val; + }; + + Bar.encode = function(encoder, val) { + encoder.write32(Bar.encodedSize); + encoder.write32(3); + encoder.write8(val.alpha); + encoder.write8(val.beta); + encoder.write8(val.gamma); + encoder.skip(5); + }; + + // Foo ---------------------------------------------------------------------- + + function Foo() { + this.x = 0; + this.y = 0; + this.a = 0; + this.b = 0; + this.c = 0; + this.bar = null; + this.data = []; + this.extra_bars = []; + this.name = ""; + this.files = []; + } + + Foo.encodedSize = codec.kStructHeaderSize + 64; + + Foo.decode = function(decoder) { + var val = new Foo(); + var numberOfBytes = decoder.read32(); + var numberOfFields = decoder.read32(); + // TODO(abarth): We need to support optional fields. + val.x = decoder.read32(); + val.y = decoder.read32(); + var packed = decoder.read8(); + val.a = (packed >> 0) & 1; + val.b = (packed >> 1) & 1; + val.c = (packed >> 2) & 1; + decoder.skip(7); + val.bar = decoder.decodeStructPointer(Bar); + val.data = decoder.decodeArrayPointer(codec.Uint8); + val.extra_bars = decoder.decodeArrayPointer(new codec.PointerTo(Bar)); + val.name = decoder.decodeStringPointer(); + val.files = decoder.decodeArrayPointer(codec.Handle); + return val; + }; + + Foo.encode = function(encoder, val) { + encoder.write32(Foo.encodedSize); + encoder.write32(10); + encoder.write32(val.x); + encoder.write32(val.y); + var packed = (val.a & 1) << 0 | + (val.b & 1) << 1 | + (val.c & 1) << 2; + encoder.write8(packed); + encoder.skip(7); + encoder.encodeStructPointer(Bar, val.bar); + encoder.encodeArrayPointer(codec.Uint8, val.data); + encoder.encodeArrayPointer(new codec.PointerTo(Bar), val.extra_bars); + encoder.encodeStringPointer(val.name); + encoder.encodeArrayPointer(codec.Handle, val.files); + }; + + // Service ------------------------------------------------------------------ + + var kService_Frobinate_Name = 1; + + function Service_Frobinate_Params() { + this.foo = null; + this.baz = false; + this.port = core.kInvalidHandle; + } + + Service_Frobinate_Params.encodedSize = codec.kStructHeaderSize + 16; + + Service_Frobinate_Params.decode = function(decoder) { + var val = new Service_Frobinate_Params(); + var numberOfBytes = decoder.read32(); + var numberOfFields = decoder.read32(); + val.foo = decoder.decodeStructPointer(Foo); + val.baz = decoder.read8() & 1; + decoder.skip(3); + val.port = decoder.decodeHandle(); + return val; + }; + + Service_Frobinate_Params.encode = function(encoder, val) { + encoder.write32(Service_Frobinate_Params.encodedSize); + encoder.write32(3); + encoder.encodeStructPointer(Foo, val.foo); + encoder.write8(val.baz & 1); + encoder.skip(3); + encoder.encodeHandle(val.port); + }; + + function ServiceProxy(receiver) { + this.receiver_ = receiver; + } + + ServiceProxy.prototype.frobinate = function(foo, baz, port) { + var params = new Service_Frobinate_Params(); + params.foo = foo; + params.baz = baz; + params.port = port; + + var payloadSize = codec.align(Service_Frobinate_Params.encodedSize); + var builder = new codec.MessageBuilder(kService_Frobinate_Name, + payloadSize); + builder.encodeStruct(Service_Frobinate_Params, params); + var message = builder.finish(); + this.receiver_.accept(message); + }; + + function ServiceStub() { + } + + ServiceStub.prototype.accept = function(message) { + var reader = new codec.MessageReader(message); + switch (reader.messageName) { + case kService_Frobinate_Name: + var params = reader.decodeStruct(Service_Frobinate_Params); + this.frobinate(params.foo, params.baz, params.port); + return true; + default: + return false; + } + }; + + // ServiceClient ------------------------------------------------------------ + + var kServiceClient_DidFrobinate_Name = 0; + + function ServiceClient_DidFrobinate_Params() { + this.result = 0; + } + + ServiceClient_DidFrobinate_Params.encodedSize = codec.kStructHeaderSize + 8; + + ServiceClient_DidFrobinate_Params.decode = function(decoder) { + var val = new ServiceClient_DidFrobinate_Params(); + var numberOfBytes = decoder.read32(); + var numberOfFields = decoder.read32(); + val.result = decoder.read32(); + decoder.skip(4); + return val; + }; + + ServiceClient_DidFrobinate_Params.encode = function(encoder, val) { + encoder.write32(ServiceClient_DidFrobinate_Params.encodedSize); + encoder.write32(1); + encoder.write32(val.result); + encoder.skip(4); + }; + + function ServiceClientProxy(receiver) { + this.receiver_ = receiver; + } + + ServiceClientProxy.prototype.didFrobinate = function(result) { + var params = new ServiceClient_DidFrobinate_Params(); + params.result = result; + + var payloadSize = codec.align( + ServiceClient_DidFrobinate_Params.encodedSize); + var builder = new codec.MessageBuilder(kServiceClient_DidFrobinate_Name, + payloadSize); + builder.encodeStruct(ServiceClient_DidFrobinate_Params, params); + var message = builder.finish(); + this.receiver_.accept(message); + }; + + function ServiceClientStub() { + } + + ServiceClientStub.prototype.accept = function(message) { + var reader = new codec.MessageReader(message); + switch (reader.messageName) { + case kServiceClient_DidFrobinate_Name: + var params = reader.decodeStruct(kServiceClient_DidFrobinate_Name); + this.didFrobinate(params.result); + return true; + default: + return false; + } + }; + + // Exports ------------------------------------------------------------------ + + var exports = {}; + exports.Bar = Bar; + exports.Foo = Foo; + exports.ServiceProxy = ServiceProxy; + exports.ServiceStub = ServiceStub; + exports.ServiceClientProxy = ServiceClientProxy; + exports.ServiceClientStub = ServiceClientStub; + return exports; +}); diff --git a/mojo/public/bindings/sample/sample_test.js b/mojo/public/bindings/sample/sample_test.js new file mode 100644 index 0000000..230f4df --- /dev/null +++ b/mojo/public/bindings/sample/sample_test.js @@ -0,0 +1,123 @@ +// Copyright 2013 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +define([ + "gtest", + // TODO(abarth): We shouldn't need to depend on codec, but there seems to + // be a bug in the module loading system whereby this test doesn't run if + // we don't import codec here. + "mojo/public/bindings/js/codec", + "mojo/public/bindings/sample/mojom/sample_service" + ], function(gtest, codec, sample) { + + var global = this; + + function makeFoo() { + var bar = new sample.Bar(); + bar.alpha = 20; + bar.beta = 40; + bar.gamma = 60; + + var extra_bars = new Array(3); + for (var i = 0; i < extra_bars.length; ++i) { + var base = i * 100; + extra_bars[i] = new sample.Bar(); + extra_bars[i].alpha = base; + extra_bars[i].beta = base + 20; + extra_bars[i].gamma = base + 40; + } + + var data = new Array(10); + for (var i = 0; i < data.length; ++i) { + data[i] = data.length - i; + } + + var files = new Array(4); + for (var i = 0; i < files.length; ++i) { + files[i] = 0xFFFF - i; + } + + var foo = new sample.Foo(); + foo.name = "foopy"; + foo.x = 1; + foo.y = 2; + foo.a = false; + foo.b = true; + foo.c = false; + foo.bar = bar; + foo.extra_bars = extra_bars; + foo.data = data; + foo.files = files; + return foo; + } + + // Check that the given |Foo| is identical to the one made by |MakeFoo()|. + function checkFoo(foo) { + gtest.expectEqual(foo.name, "foopy", "foo.name is " + foo.name); + gtest.expectEqual(foo.x, 1, "foo.x is " + foo.x); + gtest.expectEqual(foo.y, 2, "foo.y is " + foo.y); + gtest.expectFalse(foo.a, "foo.a is " + foo.a); + gtest.expectTrue(foo.b, "foo.b is " + foo.b); + gtest.expectFalse(foo.c, "foo.c is " + foo.c); + gtest.expectEqual(foo.bar.alpha, 20, "foo.bar.alpha is " + foo.bar.alpha); + gtest.expectEqual(foo.bar.beta, 40, "foo.bar.beta is " + foo.bar.beta); + gtest.expectEqual(foo.bar.gamma, 60, "foo.bar.gamma is " + foo.bar.gamma); + + gtest.expectEqual(foo.extra_bars.length, 3, + "foo.extra_bars.length is " + foo.extra_bars.length); + for (var i = 0; i < foo.extra_bars.length; ++i) { + var base = i * 100; + gtest.expectEqual(foo.extra_bars[i].alpha, base, + "foo.extra_bars[" + i + "].alpha is " + foo.extra_bars[i].alpha); + gtest.expectEqual(foo.extra_bars[i].beta, base + 20, + "foo.extra_bars[" + i + "].beta is " + foo.extra_bars[i].beta); + gtest.expectEqual(foo.extra_bars[i].gamma, base + 40, + "foo.extra_bars[" + i + "].gamma is " + foo.extra_bars[i].gamma); + } + + gtest.expectEqual(foo.data.length, 10, + "foo.data.length is " + foo.data.length); + for (var i = 0; i < foo.data.length; ++i) { + gtest.expectEqual(foo.data[i], foo.data.length - i, + "foo.data[" + i + "] is " + foo.data[i]); + } + + gtest.expectEqual(foo.files.length, 4, + "foo.files.length " + foo.files.length); + for (var i = 0; i < foo.files.length; ++i) { + gtest.expectEqual(foo.files[i], 0xFFFF - i, + "foo.files[" + i + "] is " + foo.files[i]); + } + } + + function ServiceImpl() { + } + + ServiceImpl.prototype = Object.create(sample.ServiceStub.prototype); + + ServiceImpl.prototype.frobinate = function(foo, baz, port) { + checkFoo(foo); + gtest.expectTrue(baz, "baz is " + baz); + gtest.expectEqual(port, 10, "port is " + port); + global.result = "PASS"; + }; + + function SimpleMessageReceiver() { + } + + SimpleMessageReceiver.prototype.accept = function(message) { + // Imagine some IPC happened here. + var serviceImpl = new ServiceImpl(); + serviceImpl.accept(message); + }; + + var receiver = new SimpleMessageReceiver(); + var serviceProxy = new sample.ServiceProxy(receiver); + + var foo = makeFoo(); + checkFoo(foo); + + var port = 10; + serviceProxy.frobinate(foo, true, port); +}); |