269 lines
10 KiB
JavaScript
269 lines
10 KiB
JavaScript
// Copyright 2010 The Closure Library Authors. 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.
|
|
|
|
goog.provide('goog.messaging.BufferedChannelTest');
|
|
goog.setTestOnly('goog.messaging.BufferedChannelTest');
|
|
|
|
goog.require('goog.debug.Console');
|
|
goog.require('goog.dom');
|
|
goog.require('goog.log');
|
|
goog.require('goog.log.Level');
|
|
goog.require('goog.messaging.BufferedChannel');
|
|
goog.require('goog.testing.MockClock');
|
|
goog.require('goog.testing.MockControl');
|
|
goog.require('goog.testing.async.MockControl');
|
|
goog.require('goog.testing.jsunit');
|
|
goog.require('goog.testing.messaging.MockMessageChannel');
|
|
|
|
var clock;
|
|
var messages = [
|
|
{serviceName: 'firstService', payload: 'firstPayload'},
|
|
{serviceName: 'secondService', payload: 'secondPayload'}
|
|
];
|
|
var mockControl;
|
|
var asyncMockControl;
|
|
|
|
function setUpPage() {
|
|
if (goog.global.console) {
|
|
new goog.debug.Console().setCapturing(true);
|
|
}
|
|
var logger = goog.log.getLogger('goog.messaging');
|
|
logger.setLevel(goog.log.Level.ALL);
|
|
goog.log.addHandler(logger, function(logRecord) {
|
|
var msg = goog.dom.createDom('div');
|
|
msg.innerHTML = logRecord.getMessage();
|
|
goog.dom.appendChild(goog.dom.getElement('debug-div'), msg);
|
|
});
|
|
clock = new goog.testing.MockClock();
|
|
mockControl = new goog.testing.MockControl();
|
|
asyncMockControl = new goog.testing.async.MockControl(mockControl);
|
|
}
|
|
|
|
|
|
function setUp() {
|
|
clock.install();
|
|
}
|
|
|
|
|
|
function tearDown() {
|
|
clock.uninstall();
|
|
mockControl.$tearDown();
|
|
}
|
|
|
|
|
|
function assertMessageArraysEqual(ma1, ma2) {
|
|
assertEquals('message array lengths differ', ma1.length, ma2.length);
|
|
for (var i = 0; i < ma1.length; i++) {
|
|
assertEquals(
|
|
'message array serviceNames differ',
|
|
ma1[i].serviceName, ma2[i].serviceName);
|
|
assertEquals(
|
|
'message array payloads differ',
|
|
ma1[i].payload, ma2[i].payload);
|
|
}
|
|
}
|
|
|
|
|
|
function testDelegationToWrappedChannel() {
|
|
var mockChannel = new goog.testing.messaging.MockMessageChannel(mockControl);
|
|
var channel = new goog.messaging.BufferedChannel(mockChannel);
|
|
|
|
channel.registerDefaultService(
|
|
asyncMockControl.asyncAssertEquals(
|
|
'default service should be delegated',
|
|
'defaultServiceName', 'default service payload'));
|
|
channel.registerService(
|
|
'normalServiceName',
|
|
asyncMockControl.asyncAssertEquals(
|
|
'normal service should be delegated',
|
|
'normal service payload'));
|
|
mockChannel.send(
|
|
goog.messaging.BufferedChannel.USER_CHANNEL_NAME_ + ':message',
|
|
'payload');
|
|
|
|
mockControl.$replayAll();
|
|
channel.peerReady_ = true; // Prevent buffering so we delegate send calls.
|
|
mockChannel.receive(
|
|
goog.messaging.BufferedChannel.USER_CHANNEL_NAME_ + ':defaultServiceName',
|
|
'default service payload');
|
|
mockChannel.receive(
|
|
goog.messaging.BufferedChannel.USER_CHANNEL_NAME_ + ':normalServiceName',
|
|
'normal service payload');
|
|
channel.send('message', 'payload');
|
|
mockControl.$verifyAll();
|
|
}
|
|
|
|
|
|
function testOptionalConnectCallbackExecutes() {
|
|
var mockChannel = new goog.testing.messaging.MockMessageChannel(mockControl);
|
|
var channel = new goog.messaging.BufferedChannel(mockChannel);
|
|
var mockConnectCb = mockControl.createFunctionMock('mockConnectCb');
|
|
mockConnectCb();
|
|
|
|
mockControl.$replayAll();
|
|
channel.connect(mockConnectCb);
|
|
mockControl.$verifyAll();
|
|
}
|
|
|
|
|
|
function testSendExceptionsInSendReadyPingStopsTimerAndReraises() {
|
|
var mockChannel = new goog.testing.messaging.MockMessageChannel(mockControl);
|
|
var channel = new goog.messaging.BufferedChannel(mockChannel);
|
|
|
|
var errorMessage = 'errorMessage';
|
|
mockChannel.send(
|
|
goog.messaging.BufferedChannel.CONTROL_CHANNEL_NAME_ + ':' +
|
|
goog.messaging.BufferedChannel.PEER_READY_SERVICE_NAME_,
|
|
/* payload */ '').$throws(Error(errorMessage));
|
|
channel.timer_.enabled = true;
|
|
|
|
mockControl.$replayAll();
|
|
var exception = assertThrows(function() {
|
|
channel.sendReadyPing_();
|
|
});
|
|
assertContains(errorMessage, exception.message);
|
|
assertFalse(channel.timer_.enabled);
|
|
mockControl.$verifyAll();
|
|
}
|
|
|
|
|
|
function testPollingIntervalDefaultAndOverride() {
|
|
var mockChannel = new goog.testing.messaging.MockMessageChannel(mockControl);
|
|
var channel = new goog.messaging.BufferedChannel(mockChannel);
|
|
|
|
assertEquals(
|
|
goog.messaging.BufferedChannel.DEFAULT_INTERVAL_MILLIS_,
|
|
channel.timer_.getInterval());
|
|
var interval = 100;
|
|
var longIntervalChannel = new goog.messaging.BufferedChannel(
|
|
new goog.testing.messaging.MockMessageChannel(mockControl), interval);
|
|
assertEquals(interval, longIntervalChannel.timer_.getInterval());
|
|
}
|
|
|
|
|
|
function testBidirectionalCommunicationBuffersUntilReadyPingsSucceed() {
|
|
var mockChannel1 = new goog.testing.messaging.MockMessageChannel(mockControl);
|
|
var mockChannel2 = new goog.testing.messaging.MockMessageChannel(mockControl);
|
|
var bufferedChannel1 = new goog.messaging.BufferedChannel(mockChannel1);
|
|
var bufferedChannel2 = new goog.messaging.BufferedChannel(mockChannel2);
|
|
mockChannel1.send(
|
|
goog.messaging.BufferedChannel.CONTROL_CHANNEL_NAME_ + ':setPeerReady_',
|
|
'').$does(function() {
|
|
bufferedChannel2.setPeerReady_('');
|
|
});
|
|
mockChannel2.send(
|
|
goog.messaging.BufferedChannel.CONTROL_CHANNEL_NAME_ + ':setPeerReady_',
|
|
'1').$does(function() {
|
|
bufferedChannel1.setPeerReady_('1');
|
|
});
|
|
mockChannel1.send(
|
|
goog.messaging.BufferedChannel.CONTROL_CHANNEL_NAME_ + ':setPeerReady_',
|
|
'1').$does(function() {
|
|
bufferedChannel2.setPeerReady_('1');
|
|
});
|
|
mockChannel1.send(goog.messaging.BufferedChannel.USER_CHANNEL_NAME_ + ':' +
|
|
messages[0].serviceName,
|
|
messages[0].payload);
|
|
mockChannel2.send(goog.messaging.BufferedChannel.USER_CHANNEL_NAME_ + ':' +
|
|
messages[1].serviceName,
|
|
messages[1].payload);
|
|
|
|
mockControl.$replayAll();
|
|
bufferedChannel1.send(messages[0].serviceName, messages[0].payload);
|
|
bufferedChannel2.send(messages[1].serviceName, messages[1].payload);
|
|
assertMessageArraysEqual([messages[0]], bufferedChannel1.buffer_);
|
|
assertMessageArraysEqual([messages[1]], bufferedChannel2.buffer_);
|
|
// First tick causes setPeerReady_ to fire, which in turn flushes the buffers.
|
|
clock.tick(goog.messaging.BufferedChannel.DEFAULT_INTERVAL_MILLIS_);
|
|
assertEquals(bufferedChannel1.buffer_, null);
|
|
assertEquals(bufferedChannel2.buffer_, null);
|
|
// Now that peers are ready, a second tick causes no more sends.
|
|
clock.tick(goog.messaging.BufferedChannel.DEFAULT_INTERVAL_MILLIS_);
|
|
mockControl.$verifyAll();
|
|
}
|
|
|
|
|
|
function testBidirectionalCommunicationReconnectsAfterOneSideRestarts() {
|
|
var mockChannel1 = new goog.testing.messaging.MockMessageChannel(mockControl);
|
|
var mockChannel2 = new goog.testing.messaging.MockMessageChannel(mockControl);
|
|
var mockChannel3 = new goog.testing.messaging.MockMessageChannel(mockControl);
|
|
var bufferedChannel1 = new goog.messaging.BufferedChannel(mockChannel1);
|
|
var bufferedChannel2 = new goog.messaging.BufferedChannel(mockChannel2);
|
|
var bufferedChannel3 = new goog.messaging.BufferedChannel(mockChannel3);
|
|
|
|
// First tick
|
|
mockChannel1.send(
|
|
goog.messaging.BufferedChannel.CONTROL_CHANNEL_NAME_ + ':setPeerReady_',
|
|
'').$does(function() {
|
|
bufferedChannel2.setPeerReady_('');
|
|
});
|
|
mockChannel2.send(
|
|
goog.messaging.BufferedChannel.CONTROL_CHANNEL_NAME_ + ':setPeerReady_',
|
|
'1').$does(function() {
|
|
bufferedChannel1.setPeerReady_('1');
|
|
});
|
|
mockChannel1.send(
|
|
goog.messaging.BufferedChannel.CONTROL_CHANNEL_NAME_ + ':setPeerReady_',
|
|
'1').$does(function() {
|
|
bufferedChannel2.setPeerReady_('1');
|
|
});
|
|
mockChannel3.send(
|
|
goog.messaging.BufferedChannel.CONTROL_CHANNEL_NAME_ + ':setPeerReady_',
|
|
''); // pretend it's not ready to connect yet
|
|
|
|
// Second tick
|
|
mockChannel3.send(
|
|
goog.messaging.BufferedChannel.CONTROL_CHANNEL_NAME_ + ':setPeerReady_',
|
|
'').$does(function() {
|
|
bufferedChannel1.setPeerReady_('');
|
|
});
|
|
|
|
// Third tick
|
|
mockChannel1.send(
|
|
goog.messaging.BufferedChannel.CONTROL_CHANNEL_NAME_ + ':setPeerReady_',
|
|
'1').$does(function() {
|
|
bufferedChannel3.setPeerReady_('1');
|
|
});
|
|
mockChannel3.send(
|
|
goog.messaging.BufferedChannel.CONTROL_CHANNEL_NAME_ + ':setPeerReady_',
|
|
'1').$does(function() {
|
|
bufferedChannel1.setPeerReady_('1');
|
|
});
|
|
|
|
mockChannel1.send(goog.messaging.BufferedChannel.USER_CHANNEL_NAME_ + ':' +
|
|
messages[0].serviceName,
|
|
messages[0].payload);
|
|
mockChannel3.send(goog.messaging.BufferedChannel.USER_CHANNEL_NAME_ + ':' +
|
|
messages[1].serviceName,
|
|
messages[1].payload);
|
|
|
|
mockControl.$replayAll();
|
|
// First tick causes setPeerReady_ to fire, which sets up the connection
|
|
// between channels 1 and 2.
|
|
clock.tick(goog.messaging.BufferedChannel.DEFAULT_INTERVAL_MILLIS_);
|
|
assertTrue(bufferedChannel1.peerReady_);
|
|
assertTrue(bufferedChannel2.peerReady_);
|
|
// Now pretend that channel 2 went down and was replaced by channel 3, which
|
|
// is trying to connect with channel 1.
|
|
clock.tick(goog.messaging.BufferedChannel.DEFAULT_INTERVAL_MILLIS_);
|
|
assertTrue(bufferedChannel1.peerReady_);
|
|
clock.tick(goog.messaging.BufferedChannel.DEFAULT_INTERVAL_MILLIS_);
|
|
assertTrue(bufferedChannel3.peerReady_);
|
|
bufferedChannel1.send(messages[0].serviceName, messages[0].payload);
|
|
bufferedChannel3.send(messages[1].serviceName, messages[1].payload);
|
|
// All timers stopped, nothing happens on the fourth tick.
|
|
clock.tick(goog.messaging.BufferedChannel.DEFAULT_INTERVAL_MILLIS_);
|
|
mockControl.$verifyAll();
|
|
}
|