UNPKG

sku-pg

Version:

Skulpt is a Javascript implementation of Python 2.x. Python that runs in your browser!

1,142 lines (906 loc) 32.1 kB
<!DOCTYPE html> <html> <!-- Copyright 2009 The Closure Library Authors. All Rights Reserved. Use of this source code is governed by an Apache 2.0 License. See the COPYING file for details. --> <!-- Author: mikaeld@google.com (Mikael Drugge) --> <head> <title>Closure Unit Tests - goog.net.BrowserChannel</title> <script type="text/javascript" src="../base.js"></script> <script type="text/javascript"> goog.require('goog.Timer'); goog.require('goog.dom'); goog.require('goog.json'); goog.require('goog.net.ChannelRequest'); goog.require('goog.net.BrowserChannel'); goog.require('goog.net.ChannelRequest'); goog.require('goog.net.tmpnetwork'); goog.require('goog.string.StringBuffer'); goog.require('goog.structs.Map'); goog.require('goog.testing.MockClock'); goog.require('goog.testing.asserts'); goog.require('goog.testing.jsunit'); </script> </head> <body> <!-- Define unit tests. --> <script type="text/javascript" > /** * Delay between a network failure and the next network request. */ var RETRY_TIME = 1000; /** * A really long time - used to make sure no more timeouts will fire. */ var ALL_DAY_MS = 1000 * 60 * 60 * 24; var browserChannel; var handler; var mockClock; var sb; var gotError; var numStatEvents; var lastStatEvent; var numTimingEvents; var lastPostSize; var lastPostRtt; var lastPostRetryCount; // Set to true to see the channel debug output in the browser window. var debug = false; function debugToWindow(message) { if (debug) { sb.append(message + '<br>'); goog.dom.getElement('debug').innerHTML = sb.toString(); } } /** * Mock ChannelRequest. */ function MockChannelRequest() {} MockChannelRequest = function(channel, channelDebug, opt_sessionId, opt_requestId, opt_retryId) { this.channel_ = channel; this.channelDebug_ = channelDebug; this.sessionId_ = opt_sessionId; this.requestId_ = opt_requestId; this.successful_ = true; this.lastError_ = null; this.lastStatusCode_ = 200; // For debugging, keep track of whether this is a back or forward channel. this.isBack = !!(opt_requestId == 'rpc'); this.isForward = !this.isBack; }; MockChannelRequest.prototype.postData_ = null; MockChannelRequest.prototype.requestStartTime_ = null; MockChannelRequest.prototype.setExtraHeaders = function(extraHeaders) {}; MockChannelRequest.prototype.setTimeout = function(timeout) {}; MockChannelRequest.prototype.xmlHttpPost = function(uri, postData, decodeChunks) { this.channelDebug_.debug('---> POST: ' + uri + ', ' + postData + ', ' + decodeChunks); this.postData_ = postData; this.requestStartTime_ = goog.now() }; MockChannelRequest.prototype.xmlHttpGet = function(uri, decodeChunks, opt_noClose) { this.channelDebug_.debug('<--- GET: ' + uri + ', ' + decodeChunks + ', ' + opt_noClose); this.requestStartTime_ = goog.now() }; MockChannelRequest.prototype.tridentGet = function(uri, usingSecondaryDomain) { this.channelDebug_.debug('<---GET (T): ' + uri); this.requestStartTime_ = goog.now() }; MockChannelRequest.prototype.sendUsingImgTag = function(uri) { this.requestStartTime_ = goog.now() }; MockChannelRequest.prototype.cancel = function() { this.successful_ = false; }; MockChannelRequest.prototype.getSuccess = function() { return this.successful_; }; MockChannelRequest.prototype.getLastError = function() { return this.lastError_; }; MockChannelRequest.prototype.getLastStatusCode = function() { return this.lastStatusCode_; }; MockChannelRequest.prototype.getSessionId = function() { return this.sessionId_; }; MockChannelRequest.prototype.getRequestId = function() { return this.requestId_; }; MockChannelRequest.prototype.getPostData = function() { return this.postData_; }; MockChannelRequest.prototype.getRequestStartTime = function() { return this.requestStartTime_; }; function setUpPage() { // Use our MockChannelRequests instead of the real ones. goog.net.BrowserChannel.createChannelRequest = function( channel, channelDebug, opt_sessionId, opt_requestId, opt_retryId) { return new MockChannelRequest( channel, channelDebug, opt_sessionId, opt_requestId, opt_retryId); }; sb = new goog.string.StringBuffer(); // Mock out the stat notification code. goog.net.BrowserChannel.notifyStatEvent = function(stat) { numStatEvents++; lastStatEvent = stat; }; goog.net.BrowserChannel.notifyTimingEvent = function(size, rtt, retries) { numTimingEvents++; lastPostSize = size; lastPostRtt = rtt; lastPostRetryCount = retries; }; } function setUp() { numTimingEvents = 0; lastPostSize = null; lastPostRtt = null; lastPostRetryCount = null; mockClock = new goog.testing.MockClock(true); browserChannel = new goog.net.BrowserChannel('1'); gotError = false; handler = new goog.net.BrowserChannel.Handler(); handler.channelOpened = function() {}; handler.channelError = function(channel, error) { gotError = true; }; handler.channelClosed = function( channel, opt_pendingMaps, opt_undeliveredMaps) { // Mock out the handler, and let it set a formatted user readable string // of the undelivered maps which we can use when verifying our assertions. if (opt_pendingMaps) { this.pendingMapsString = formatArrayOfMaps(opt_pendingMaps); } if (opt_undeliveredMaps) { this.undeliveredMapsString = formatArrayOfMaps(opt_undeliveredMaps); } }; handler.channelHandleMultipleArrays = function() {}; handler.channelHandleArray = function() {}; browserChannel.setHandler(handler); // Provide a predictable retry time for testing. browserChannel.getRetryTime_ = function(retryCount) { return RETRY_TIME; }; var channelDebug = new goog.net.ChannelDebug(); channelDebug.debug = function(message) { debugToWindow(message); }; browserChannel.setChannelDebug(channelDebug); numStatEvents = 0; lastStatEvent = null; } function tearDown() { mockClock.dispose(); debugToWindow('<hr>'); } /** * Helper function to return a formatted string representing an array of maps. */ function formatArrayOfMaps(arrayOfMaps) { var result = []; for (var i = 0; i < arrayOfMaps.length; i++) { var map = arrayOfMaps[i]; var keys = map.map.getKeys(); for (var j = 0; j < keys.length; j++) { result.push(keys[j] + ':' + map.map.get(keys[j])); } } return result.join(', '); } function testFormatArrayOfMaps() { // This function is used in a non-trivial test, so let's verify that it works. var map1 = new goog.structs.Map(); map1.set('k1', 'v1'); map1.set('k2', 'v2'); var map2 = new goog.structs.Map(); map2.set('k3', 'v3'); var map3 = new goog.structs.Map(); map3.set('k4', 'v4'); map3.set('k5', 'v5'); map3.set('k6', 'v6'); // One map. var a = []; a.push(new goog.net.BrowserChannel.QueuedMap(0, map1)); assertEquals('k1:v1, k2:v2', formatArrayOfMaps(a)); // Many maps. var b = []; b.push(new goog.net.BrowserChannel.QueuedMap(0, map1)); b.push(new goog.net.BrowserChannel.QueuedMap(0, map2)); b.push(new goog.net.BrowserChannel.QueuedMap(0, map3)); assertEquals('k1:v1, k2:v2, k3:v3, k4:v4, k5:v5, k6:v6', formatArrayOfMaps(b)); } function connect(opt_serverVersion) { browserChannel.connect('/test', '/bind', null); mockClock.tick(0); completeTestConnection(); completeForwardChannel(opt_serverVersion); completeBackChannel(); } function disconnect() { browserChannel.disconnect(); mockClock.tick(0); } function completeTestConnection() { completeForwardTestConnection(); completeBackTestConnection(); assertEquals(goog.net.BrowserChannel.State.OPENING, browserChannel.getState()); } function completeForwardTestConnection() { browserChannel.connectionTest_.onRequestData( browserChannel.connectionTest_, '["b"]'); browserChannel.connectionTest_.onRequestComplete( browserChannel.connectionTest_); mockClock.tick(0); } function completeBackTestConnection() { browserChannel.connectionTest_.onRequestData( browserChannel.connectionTest_, '11111'); mockClock.tick(201); browserChannel.connectionTest_.onRequestData( browserChannel.connectionTest_, '2'); browserChannel.connectionTest_.onRequestComplete( browserChannel.connectionTest_); mockClock.tick(0); } function completeForwardChannel(opt_serverVersion) { var responseData = '[[0,["c","1234567890ABCDEF",null]]]' if (opt_serverVersion) { responseData = '[[0,["c","1234567890ABCDEF",null,' + opt_serverVersion + ']]]'; } browserChannel.onRequestData( browserChannel.forwardChannelRequest_, responseData); browserChannel.onRequestComplete( browserChannel.forwardChannelRequest_); mockClock.tick(0); } function completeBackChannel() { browserChannel.onRequestData( browserChannel.backChannelRequest_, '[[1,["foo"]]]'); browserChannel.onRequestComplete( browserChannel.backChannelRequest_); mockClock.tick(0); } function responseVersion7() { browserChannel.onRequestData( browserChannel.forwardChannelRequest_, goog.net.BrowserChannel.MAGIC_RESPONSE_COOKIE); browserChannel.onRequestComplete( browserChannel.forwardChannelRequest_); mockClock.tick(0); } function responseNoBackchannel(lastArrayIdSentFromServer, outstandingDataSize) { responseData = goog.json.serialize( [0, lastArrayIdSentFromServer, outstandingDataSize]); browserChannel.onRequestData( browserChannel.forwardChannelRequest_, responseData); browserChannel.onRequestComplete( browserChannel.forwardChannelRequest_); mockClock.tick(0); } function response(lastArrayIdSentFromServer, outstandingDataSize) { responseData = goog.json.serialize( [1, lastArrayIdSentFromServer, outstandingDataSize]); browserChannel.onRequestData( browserChannel.forwardChannelRequest_, responseData ); browserChannel.onRequestComplete( browserChannel.forwardChannelRequest_); mockClock.tick(0); } function receive(data) { browserChannel.onRequestData( browserChannel.backChannelRequest_, '[[1,' + data + ']]'); browserChannel.onRequestComplete( browserChannel.backChannelRequest_); mockClock.tick(0); } function responseTimeout() { browserChannel.forwardChannelRequest_lastError_ = goog.net.ChannelRequest.Error.TIMEOUT; browserChannel.forwardChannelRequest_.successful_ = false; browserChannel.onRequestComplete( browserChannel.forwardChannelRequest_); mockClock.tick(0); } function responseRequestFailed(opt_statusCode) { browserChannel.forwardChannelRequest_.lastError_ = goog.net.ChannelRequest.Error.STATUS; browserChannel.forwardChannelRequest_.lastStatusCode_ = opt_statusCode || 503; browserChannel.forwardChannelRequest_.successful_ = false; browserChannel.onRequestComplete( browserChannel.forwardChannelRequest_); mockClock.tick(0); } function responseUnknownSessionId() { browserChannel.forwardChannelRequest_.lastError_ = goog.net.ChannelRequest.Error.UNKNOWN_SESSION_ID; browserChannel.forwardChannelRequest_.successful_ = false; browserChannel.onRequestComplete( browserChannel.forwardChannelRequest_); mockClock.tick(0); } function sendMap(key, value) { var map = new goog.structs.Map(); map.set(key, value); browserChannel.sendMap(map); mockClock.tick(0); } function hasForwardChannel() { return !!browserChannel.forwardChannelRequest_; } function hasBackChannel() { return !!browserChannel.backChannelRequest_; } function hasDeadBackChannelTimer() { return goog.isDefAndNotNull(browserChannel.deadBackChannelTimerId_); }; function assertHasForwardChannel() { assertTrue('Forward channel missing.', hasForwardChannel()); } function assertHasBackChannel() { assertTrue('Back channel missing.', hasBackChannel()); } function testConnect() { connect(); assertEquals(goog.net.BrowserChannel.State.OPENED, browserChannel.getState()); // If the server specifies no version, the client assumes 6 assertEquals(6, browserChannel.channelVersion_); assertFalse(browserChannel.isBuffered()); } function testConnect_backChannelEstablished() { connect(); assertHasBackChannel(); } function testConnect_withServerVersion() { connect(8); assertEquals(8, browserChannel.channelVersion_); } function testSendMap() { connect(); assertEquals(1, numTimingEvents); sendMap('foo', 'bar'); responseVersion7(); assertEquals(2, numTimingEvents); } function testSendMap_twice() { connect(); sendMap('foo1', 'bar1'); responseVersion7(); sendMap('foo2', 'bar2'); responseVersion7(); } function testSendMap_andReceive() { connect(); sendMap('foo', 'bar'); responseVersion7(); receive('["the server reply"]'); } function testReceive() { connect(); receive('["message from server"]'); assertHasBackChannel(); } function testReceive_twice() { connect(); receive('["message one from server"]'); receive('["message two from server"]'); assertHasBackChannel(); } function testReceive_andSendMap() { connect(); receive('["the server reply"]'); sendMap('foo', 'bar'); responseVersion7(); assertHasBackChannel(); } function testBackChannelRemainsEstablished_afterSingleSendMap() { connect(); sendMap('foo', 'bar'); responseVersion7(); receive('["ack"]'); assertHasBackChannel(); } function testBackChannelRemainsEstablished_afterDoubleSendMap() { connect(); sendMap('foo1', 'bar1'); sendMap('foo2', 'bar2'); responseVersion7(); receive('["ack"]'); // This assertion would fail prior to CL 13302660. assertHasBackChannel(); } function testTimingEvent(){ connect(); assertEquals(1, numTimingEvents); sendMap('', ''); assertEquals(1, numTimingEvents); mockClock.tick(20); var expSize = browserChannel.forwardChannelRequest_.getPostData().length; responseVersion7(); assertEquals(2, numTimingEvents); assertEquals(expSize, lastPostSize); assertEquals(20, lastPostRtt); assertEquals(0, lastPostRetryCount); sendMap('abcdefg', '123456'); expSize = browserChannel.forwardChannelRequest_.getPostData().length; responseTimeout(); assertEquals(2, numTimingEvents); mockClock.tick(RETRY_TIME + 1); responseVersion7(); assertEquals(3, numTimingEvents); assertEquals(expSize, lastPostSize); assertEquals(1, lastPostRetryCount); assertEquals(1, lastPostRtt); } /** * Make sure that dropping the forward channel retry limit below the retry count * reports an error, and prevents another request from firing. */ function testSetFailFastWhileWaitingForRetry() { connect(); assertEquals(1, numTimingEvents); sendMap('foo', 'bar'); assertNull(browserChannel.forwardChannelTimerId_); assertNotNull(browserChannel.forwardChannelRequest_); assertEquals(0, browserChannel.forwardChannelRetryCount_); // Watchdog timeout. responseTimeout(); assertNotNull(browserChannel.forwardChannelTimerId_); assertNull(browserChannel.forwardChannelRequest_); assertEquals(1, browserChannel.forwardChannelRetryCount_); // Almost finish the between-retry timeout. mockClock.tick(RETRY_TIME - 1); assertNotNull(browserChannel.forwardChannelTimerId_); assertNull(browserChannel.forwardChannelRequest_); assertEquals(1, browserChannel.forwardChannelRetryCount_); // Setting max retries to 0 should cancel the timer and raise an error. browserChannel.setFailFast(true); assertNull(browserChannel.forwardChannelTimerId_); assertNull(browserChannel.forwardChannelRequest_); assertEquals(1, browserChannel.forwardChannelRetryCount_); assertTrue(gotError); // We get the error immediately before starting to ping google.com. // Simulate that timing out. We should get a network error in addition to the // initial failure. gotError = false; mockClock.tick(goog.net.GOOGLECOM_TIMEOUT); assertTrue(gotError); // Make sure no more retry timers are firing. mockClock.tick(ALL_DAY_MS); assertNull(browserChannel.forwardChannelTimerId_); assertNull(browserChannel.forwardChannelRequest_); assertEquals(1, browserChannel.forwardChannelRetryCount_); assertEquals(1, numTimingEvents); } /** * Make sure that dropping the forward channel retry limit below the retry count * reports an error, and prevents another request from firing. */ function testSetFailFastWhileRetryXhrIsInFlight() { connect(); assertEquals(1, numTimingEvents); sendMap('foo', 'bar'); assertNull(browserChannel.forwardChannelTimerId_); assertNotNull(browserChannel.forwardChannelRequest_); assertEquals(0, browserChannel.forwardChannelRetryCount_); // Watchdog timeout. responseTimeout(); assertNotNull(browserChannel.forwardChannelTimerId_); assertNull(browserChannel.forwardChannelRequest_); assertEquals(1, browserChannel.forwardChannelRetryCount_); // Wait for the between-retry timeout. mockClock.tick(RETRY_TIME); assertNull(browserChannel.forwardChannelTimerId_); assertNotNull(browserChannel.forwardChannelRequest_); assertEquals(1, browserChannel.forwardChannelRetryCount_); // Simulate a second watchdog timeout. responseTimeout(); assertNotNull(browserChannel.forwardChannelTimerId_); assertNull(browserChannel.forwardChannelRequest_); assertEquals(2, browserChannel.forwardChannelRetryCount_); // Wait for another between-retry timeout. mockClock.tick(RETRY_TIME); // Now the third req is in flight. assertNull(browserChannel.forwardChannelTimerId_); assertNotNull(browserChannel.forwardChannelRequest_); assertEquals(2, browserChannel.forwardChannelRetryCount_); // Set fail fast, killing the request browserChannel.setFailFast(true); assertNull(browserChannel.forwardChannelTimerId_); assertNull(browserChannel.forwardChannelRequest_); assertEquals(2, browserChannel.forwardChannelRetryCount_); assertTrue(gotError); // We get the error immediately before starting to ping google.com. // Simulate that timing out. We should get a network error in addition to the gotError = false; mockClock.tick(goog.net.GOOGLECOM_TIMEOUT); assertTrue(gotError); // Make sure no more retry timers are firing. mockClock.tick(ALL_DAY_MS); assertNull(browserChannel.forwardChannelTimerId_); assertNull(browserChannel.forwardChannelRequest_); assertEquals(2, browserChannel.forwardChannelRetryCount_); assertEquals(1, numTimingEvents); } /** * Makes sure that setting fail fast while not retrying doesn't cause a failure. */ function testSetFailFastAtRetryCount() { connect(); assertEquals(1, numTimingEvents); sendMap('foo', 'bar'); assertNull(browserChannel.forwardChannelTimerId_); assertNotNull(browserChannel.forwardChannelRequest_); assertEquals(0, browserChannel.forwardChannelRetryCount_); // Set fail fast. browserChannel.setFailFast(true); // Request should still be alive. assertNull(browserChannel.forwardChannelTimerId_); assertNotNull(browserChannel.forwardChannelRequest_); assertEquals(0, browserChannel.forwardChannelRetryCount_); // Watchdog timeout. Now we should get an error. responseTimeout(); assertNull(browserChannel.forwardChannelTimerId_); assertNull(browserChannel.forwardChannelRequest_); assertEquals(0, browserChannel.forwardChannelRetryCount_); assertTrue(gotError); // We get the error immediately before starting to ping google.com. // Simulate that timing out. We should get a network error in addition to the // initial failure. gotError = false; mockClock.tick(goog.net.GOOGLECOM_TIMEOUT); assertTrue(gotError); // Make sure no more retry timers are firing. mockClock.tick(ALL_DAY_MS); assertNull(browserChannel.forwardChannelTimerId_); assertNull(browserChannel.forwardChannelRequest_); assertEquals(0, browserChannel.forwardChannelRetryCount_); assertEquals(1, numTimingEvents); } function testRequestFailedClosesChannel() { connect(); assertEquals(1, numTimingEvents); sendMap('foo', 'bar'); responseRequestFailed(); assertEquals('Should be closed immediately after request failed.', goog.net.BrowserChannel.State.CLOSED, browserChannel.getState()); mockClock.tick(goog.net.GOOGLECOM_TIMEOUT); assertEquals('Should remain closed after the ping timeout.', goog.net.BrowserChannel.State.CLOSED, browserChannel.getState()); assertEquals(1, numTimingEvents); } function testStatEventReportedOnlyOnce() { connect(); sendMap('foo', 'bar'); numStatEvents = 0; lastStatEvent = null; responseUnknownSessionId(); assertEquals(1, numStatEvents); assertEquals(goog.net.BrowserChannel.Stat.ERROR_OTHER, lastStatEvent); numStatEvents = 0; mockClock.tick(goog.net.GOOGLECOM_TIMEOUT); assertEquals('No new stat events should be reported.', 0, numStatEvents); } function testStatEventReportedOnlyOnce_onNetworkUp() { connect(); sendMap('foo', 'bar'); numStatEvents = 0; lastStatEvent = null; responseRequestFailed(); assertEquals('No stat event should be reported before we know the reason.', 0, numStatEvents); // Let the ping time out. mockClock.tick(goog.net.GOOGLECOM_TIMEOUT); // Assert we report the correct stat event. assertEquals(1, numStatEvents); assertEquals(goog.net.BrowserChannel.Stat.ERROR_NETWORK, lastStatEvent); } function testStatEventReportedOnlyOnce_onNetworkDown() { connect(); sendMap('foo', 'bar'); numStatEvents = 0; lastStatEvent = null; responseRequestFailed(); assertEquals('No stat event should be reported before we know the reason.', 0, numStatEvents); // Wait half the ping timeout period, and then fake the network being up. mockClock.tick(goog.net.GOOGLECOM_TIMEOUT / 2); browserChannel.testGoogleComCallback_(true); // Assert we report the correct stat event. assertEquals(1, numStatEvents); assertEquals(goog.net.BrowserChannel.Stat.ERROR_OTHER, lastStatEvent); } function testOutgoingMapsAwaitsResponse() { connect(); assertEquals(0, browserChannel.outgoingMaps_.length); sendMap('foo1', 'bar'); assertEquals(0, browserChannel.outgoingMaps_.length); sendMap('foo2', 'bar'); assertEquals(1, browserChannel.outgoingMaps_.length); sendMap('foo3', 'bar'); assertEquals(2, browserChannel.outgoingMaps_.length); sendMap('foo4', 'bar'); assertEquals(3, browserChannel.outgoingMaps_.length); responseVersion7(); // Now the forward channel request is completed and a new started, so all maps // are dequeued from the array of outgoing maps into this new forward request. assertEquals(0, browserChannel.outgoingMaps_.length); } function testUndeliveredMaps_doesNotNotifyWhenSuccessful() { handler.channelClosed = function( channel, opt_pendingMaps, opt_undeliveredMaps) { if (opt_pendingMaps || opt_undeliveredMaps) { fail('No pending or undelivered maps should be reported.'); } }; connect(); sendMap('foo1', 'bar1'); responseVersion7(); sendMap('foo2', 'bar2'); responseVersion7(); disconnect(); } function testUndeliveredMaps_doesNotNotifyIfNothingWasSent() { handler.channelClosed = function( channel, opt_pendingMaps, opt_undeliveredMaps) { if (opt_pendingMaps || opt_undeliveredMaps) { fail('No pending or undelivered maps should be reported.'); } }; connect(); mockClock.tick(ALL_DAY_MS); disconnect(); } function testUndeliveredMaps_clearsPendingMapsAfterNotifying() { connect(); sendMap('foo1', 'bar1'); sendMap('foo2', 'bar2'); sendMap('foo3', 'bar3'); assertEquals(1, browserChannel.pendingMaps_.length); assertEquals(2, browserChannel.outgoingMaps_.length); disconnect(); assertEquals(0, browserChannel.pendingMaps_.length); assertEquals(0, browserChannel.outgoingMaps_.length); } function testUndeliveredMaps_notifiesWhenNoResponseReceived() { connect(); // First send two messages that succeed. sendMap('foo1', 'bar1'); responseVersion7(); sendMap('foo2', 'bar2'); responseVersion7(); // Pretend the server hangs and no longer responds. sendMap('foo3', 'bar3'); sendMap('foo4', 'bar4'); sendMap('foo5', 'bar5'); // Give up. disconnect(); // Assert that we are informed of any undelivered messages; both about // #3 that was sent but which we don't know if the server received, and // #4 and #5 which remain in the outgoing maps and have not yet been sent. assertEquals('foo3:bar3', handler.pendingMapsString); assertEquals('foo4:bar4, foo5:bar5', handler.undeliveredMapsString); } function testUndeliveredMaps_serviceUnavailable() { // Send a few maps, and let one fail. connect(); sendMap('foo1', 'bar1'); responseVersion7(); sendMap('foo2', 'bar2'); responseRequestFailed(); // After a failure, the channel should be closed. disconnect(); assertEquals('foo2:bar2', handler.pendingMapsString); assertEquals('', handler.undeliveredMapsString); } function testUndeliveredMaps_onPingTimeout() { connect(); // Send a message. sendMap('foo1', 'bar1'); // Fake REQUEST_FAILED, triggering a ping to check the network. responseRequestFailed(); // Let the ping time out, unsuccessfully. mockClock.tick(goog.net.GOOGLECOM_TIMEOUT); // Assert channel is closed. assertEquals(goog.net.BrowserChannel.State.CLOSED, browserChannel.getState()); // Assert that the handler is notified about the undelivered messages. assertEquals('foo1:bar1', handler.pendingMapsString); assertEquals('', handler.undeliveredMapsString); } function testResponseNoBackchannelPostNotBeforeBackchannel() { connect(8); sendMap('foo1', 'bar1'); mockClock.tick(10); assertFalse(browserChannel.backChannelRequest_.getRequestStartTime() < browserChannel.forwardChannelRequest_.getRequestStartTime()); responseNoBackchannel(); assertNotEquals(goog.net.BrowserChannel.Stat.BACKCHANNEL_MISSING, lastStatEvent); } function testResponseNoBackchannel() { connect(8); sendMap('foo1', 'bar1'); response(-1, 0); mockClock.tick(goog.net.BrowserChannel.RTT_ESTIMATE + 1); sendMap('foo2', 'bar2'); assertTrue(browserChannel.backChannelRequest_.getRequestStartTime() + goog.net.BrowserChannel.RTT_ESTIMATE < browserChannel.forwardChannelRequest_.getRequestStartTime()); responseNoBackchannel(); assertEquals(goog.net.BrowserChannel.Stat.BACKCHANNEL_MISSING, lastStatEvent); } function testResponseNoBackchannelWithNoBackchannel() { connect(8); sendMap('foo1', 'bar1'); assertNull(browserChannel.backChannelTimerId_); browserChannel.backChannelRequest_.cancel(); browserChannel.backChannelRequest_ = null; responseNoBackchannel(); assertEquals(goog.net.BrowserChannel.Stat.BACKCHANNEL_MISSING, lastStatEvent); } function testResponseNoBackchannelWithStartTimer() { connect(8); sendMap('foo1', 'bar1'); browserChannel.backChannelRequest_.cancel(); browserChannel.backChannelRequest_ = null; browserChannel.backChannelTimerId_ = 123; responseNoBackchannel(); assertNotEquals(goog.net.BrowserChannel.Stat.BACKCHANNEL_MISSING, lastStatEvent); } function testResponseWithNoArraySent() { connect(8); sendMap('foo1', 'bar1'); // Send a response as if the server hasn't sent down an array. response(-1, 0); // POST response with an array ID lower than our last received is OK. assertEquals(1, browserChannel.lastArrayId_); assertEquals(-1, browserChannel.lastPostResponseArrayId_); } function testResponseWithArraysMissing() { connect(8); sendMap('foo1', 'bar1'); assertEquals(-1, browserChannel.lastPostResponseArrayId_); // Send a response as if the server has sent down seven arrays. response(7, 111); assertEquals(1, browserChannel.lastArrayId_); assertEquals(7, browserChannel.lastPostResponseArrayId_); mockClock.tick(goog.net.BrowserChannel.RTT_ESTIMATE * 2); assertEquals(goog.net.BrowserChannel.Stat.BACKCHANNEL_DEAD, lastStatEvent); } function testMultipleResponsesWithArraysMissing() { connect(8); sendMap('foo1', 'bar1'); assertEquals(-1, browserChannel.lastPostResponseArrayId_); // Send a response as if the server has sent down seven arrays. response(7, 111); assertEquals(1, browserChannel.lastArrayId_); assertEquals(7, browserChannel.lastPostResponseArrayId_); sendMap('foo2', 'bar2'); mockClock.tick(goog.net.BrowserChannel.RTT_ESTIMATE); response(8, 119); mockClock.tick(goog.net.BrowserChannel.RTT_ESTIMATE); // The original timer should still fire. assertEquals(goog.net.BrowserChannel.Stat.BACKCHANNEL_DEAD, lastStatEvent); } function testOnlyRetryOnceBasedOnResponse() { connect(8); sendMap('foo1', 'bar1'); assertEquals(-1, browserChannel.lastPostResponseArrayId_); // Send a response as if the server has sent down seven arrays. response(7, 111); assertEquals(1, browserChannel.lastArrayId_); assertEquals(7, browserChannel.lastPostResponseArrayId_); assertTrue(hasDeadBackChannelTimer()); mockClock.tick(goog.net.BrowserChannel.RTT_ESTIMATE * 2); assertEquals(goog.net.BrowserChannel.Stat.BACKCHANNEL_DEAD, lastStatEvent); assertEquals(1, browserChannel.backChannelRetryCount_); mockClock.tick(goog.net.BrowserChannel.RTT_ESTIMATE); sendMap('foo2', 'bar2'); assertFalse(hasDeadBackChannelTimer()); response(8, 119); assertFalse(hasDeadBackChannelTimer()); } function testResponseWithArraysMissingAndLiveChannel() { connect(8); sendMap('foo1', 'bar1'); assertEquals(-1, browserChannel.lastPostResponseArrayId_); // Send a response as if the server has sent down seven arrays. response(7, 111); assertEquals(1, browserChannel.lastArrayId_); assertEquals(7, browserChannel.lastPostResponseArrayId_); mockClock.tick(goog.net.BrowserChannel.RTT_ESTIMATE); assertTrue(hasDeadBackChannelTimer()); receive('["ack"]'); assertFalse(hasDeadBackChannelTimer()); mockClock.tick(goog.net.BrowserChannel.RTT_ESTIMATE); assertNotEquals(goog.net.BrowserChannel.Stat.BACKCHANNEL_DEAD, lastStatEvent); } function testResponseWithBigOutstandingData() { connect(8); sendMap('foo1', 'bar1'); assertEquals(-1, browserChannel.lastPostResponseArrayId_); // Send a response as if the server has sent down seven arrays and 50kbytes. response(7, 50000); assertEquals(1, browserChannel.lastArrayId_); assertEquals(7, browserChannel.lastPostResponseArrayId_); assertFalse(hasDeadBackChannelTimer()); mockClock.tick(goog.net.BrowserChannel.RTT_ESTIMATE * 2); assertNotEquals(goog.net.BrowserChannel.Stat.BACKCHANNEL_DEAD, lastStatEvent); } function testResponseInBufferedMode() { connect(8); browserChannel.useChunked_ = false; sendMap('foo1', 'bar1'); assertEquals(-1, browserChannel.lastPostResponseArrayId_); response(7, 111); assertEquals(1, browserChannel.lastArrayId_); assertEquals(7, browserChannel.lastPostResponseArrayId_); assertFalse(hasDeadBackChannelTimer()); mockClock.tick(goog.net.BrowserChannel.RTT_ESTIMATE * 2); assertNotEquals(goog.net.BrowserChannel.Stat.BACKCHANNEL_DEAD, lastStatEvent); } function testResponseWithGarbage() { connect(8); sendMap('foo1', 'bar1'); browserChannel.onRequestData( browserChannel.forwardChannelRequest_, 'garbage' ); assertEquals(goog.net.BrowserChannel.State.CLOSED, browserChannel.getState()); } function testResponseWithGarbageInArray() { connect(8); sendMap('foo1', 'bar1'); browserChannel.onRequestData( browserChannel.forwardChannelRequest_, '["garbage"]' ); assertEquals(goog.net.BrowserChannel.State.CLOSED, browserChannel.getState()); } function testResponseWithEvilData() { connect(8); sendMap('foo1', 'bar1'); browserChannel.onRequestData( browserChannel.forwardChannelRequest_, goog.net.BrowserChannel.LAST_ARRAY_ID_RESPONSE_PREFIX + '=<script>evil()\<\/script>&' + goog.net.BrowserChannel.OUTSTANDING_DATA_RESPONSE_PREFIX + '=<script>moreEvil()\<\/script>'); assertEquals(goog.net.BrowserChannel.State.CLOSED, browserChannel.getState()); } </script> <div id="debug" style="font-size: small"></div> </body> </html>