1// Copyright 2013 The Chromium Authors. All rights reserved. 2// Use of this source code is governed by a BSD-style license that can be 3// found in the LICENSE file. 4 5define([ 6 "gin/test/expect", 7 "mojo/public/js/connection", 8 "mojo/public/js/core", 9 "mojo/public/interfaces/bindings/tests/sample_interfaces.mojom", 10 "mojo/public/interfaces/bindings/tests/sample_service.mojom", 11 "mojo/public/js/threading", 12 "gc", 13], function(expect, 14 connection, 15 core, 16 sample_interfaces, 17 sample_service, 18 threading, 19 gc) { 20 testClientServer() 21 .then(testWriteToClosedPipe) 22 .then(testRequestResponse) 23 .then(function() { 24 this.result = "PASS"; 25 gc.collectGarbage(); // should not crash 26 threading.quit(); 27 }.bind(this)).catch(function(e) { 28 this.result = "FAIL: " + (e.stack || e); 29 threading.quit(); 30 }.bind(this)); 31 32 function testClientServer() { 33 // ServiceImpl ------------------------------------------------------------ 34 35 function ServiceImpl() { 36 } 37 38 ServiceImpl.prototype = Object.create( 39 sample_service.Service.stubClass.prototype); 40 41 ServiceImpl.prototype.frobinate = function(foo, baz, port) { 42 expect(foo.name).toBe("Example name"); 43 expect(baz).toBe(sample_service.Service.BazOptions.REGULAR); 44 expect(core.close(port)).toBe(core.RESULT_OK); 45 46 return Promise.resolve({result: 42}); 47 }; 48 49 var pipe = core.createMessagePipe(); 50 var anotherPipe = core.createMessagePipe(); 51 var sourcePipe = core.createMessagePipe(); 52 53 var connection0 = new connection.Connection(pipe.handle0, ServiceImpl); 54 55 var connection1 = new connection.Connection( 56 pipe.handle1, undefined, sample_service.Service.proxyClass); 57 58 var foo = new sample_service.Foo(); 59 foo.bar = new sample_service.Bar(); 60 foo.name = "Example name"; 61 foo.source = sourcePipe.handle0; 62 var promise = connection1.remote.frobinate( 63 foo, sample_service.Service.BazOptions.REGULAR, anotherPipe.handle0) 64 .then(function(response) { 65 expect(response.result).toBe(42); 66 67 connection0.close(); 68 connection1.close(); 69 70 return Promise.resolve(); 71 }); 72 73 // sourcePipe.handle1 hasn't been closed yet. 74 expect(core.close(sourcePipe.handle1)).toBe(core.RESULT_OK); 75 76 // anotherPipe.handle1 hasn't been closed yet. 77 expect(core.close(anotherPipe.handle1)).toBe(core.RESULT_OK); 78 79 return promise; 80 } 81 82 function testWriteToClosedPipe() { 83 var pipe = core.createMessagePipe(); 84 var anotherPipe = core.createMessagePipe(); 85 86 var connection1 = new connection.Connection( 87 pipe.handle1, function() {}, sample_service.Service.proxyClass); 88 89 // Close the other end of the pipe. 90 core.close(pipe.handle0); 91 92 // Not observed yet because we haven't pumped events yet. 93 expect(connection1.encounteredError()).toBeFalsy(); 94 95 var promise = connection1.remote.frobinate( 96 null, sample_service.Service.BazOptions.REGULAR, anotherPipe.handle0) 97 .then(function(response) { 98 return Promise.reject("Unexpected response"); 99 }).catch(function(e) { 100 // We should observe the closed pipe. 101 expect(connection1.encounteredError()).toBeTruthy(); 102 return Promise.resolve(); 103 }); 104 105 // Write failures are not reported. 106 expect(connection1.encounteredError()).toBeFalsy(); 107 108 return promise; 109 } 110 111 function testRequestResponse() { 112 // ProviderImpl ------------------------------------------------------------ 113 114 function ProviderImpl() { 115 } 116 117 ProviderImpl.prototype = 118 Object.create(sample_interfaces.Provider.stubClass.prototype); 119 120 ProviderImpl.prototype.echoString = function(a) { 121 return Promise.resolve({a: a}); 122 }; 123 124 ProviderImpl.prototype.echoStrings = function(a, b) { 125 return Promise.resolve({a: a, b: b}); 126 }; 127 128 var pipe = core.createMessagePipe(); 129 130 var connection0 = new connection.Connection(pipe.handle0, ProviderImpl); 131 132 var connection1 = new connection.Connection( 133 pipe.handle1, undefined, sample_interfaces.Provider.proxyClass); 134 135 var promise = connection1.remote.echoString("hello") 136 .then(function(response) { 137 expect(response.a).toBe("hello"); 138 return connection1.remote.echoStrings("hello", "world"); 139 }).then(function(response) { 140 expect(response.a).toBe("hello"); 141 expect(response.b).toBe("world"); 142 // Mock a read failure, expect it to fail. 143 core.readMessage = function() { 144 return { result: core.RESULT_UNKNOWN }; 145 }; 146 return connection1.remote.echoString("goodbye"); 147 }).then(function() { 148 throw Error("Expected echoString to fail."); 149 }, function(error) { 150 expect(error.message).toBe("Connection error: " + core.RESULT_UNKNOWN); 151 152 return Promise.resolve(); 153 }); 154 155 return promise; 156 } 157}); 158