283 lines
8.4 KiB
JavaScript
283 lines
8.4 KiB
JavaScript
// Copyright 2008 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.net.ChannelRequestTest');
|
|
goog.setTestOnly('goog.net.ChannelRequestTest');
|
|
|
|
goog.require('goog.Uri');
|
|
goog.require('goog.functions');
|
|
goog.require('goog.net.BrowserChannel');
|
|
goog.require('goog.net.ChannelDebug');
|
|
goog.require('goog.net.ChannelRequest');
|
|
goog.require('goog.testing.MockClock');
|
|
goog.require('goog.testing.PropertyReplacer');
|
|
goog.require('goog.testing.jsunit');
|
|
goog.require('goog.testing.net.XhrIo');
|
|
goog.require('goog.testing.recordFunction');
|
|
|
|
var channelRequest;
|
|
var mockBrowserChannel;
|
|
var mockClock;
|
|
var stubs;
|
|
var xhrIo;
|
|
|
|
|
|
/**
|
|
* Time to wait for a network request to time out, before aborting.
|
|
*/
|
|
var WATCHDOG_TIME = 2000;
|
|
|
|
|
|
/**
|
|
* Time to throttle readystatechange events.
|
|
*/
|
|
var THROTTLE_TIME = 500;
|
|
|
|
|
|
/**
|
|
* A really long time - used to make sure no more timeouts will fire.
|
|
*/
|
|
var ALL_DAY_MS = 1000 * 60 * 60 * 24;
|
|
|
|
|
|
function setUp() {
|
|
mockClock = new goog.testing.MockClock();
|
|
mockClock.install();
|
|
stubs = new goog.testing.PropertyReplacer();
|
|
}
|
|
|
|
|
|
function tearDown() {
|
|
stubs.reset();
|
|
mockClock.uninstall();
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
* Constructs a duck-type BrowserChannel that tracks the completed requests.
|
|
* @constructor
|
|
*/
|
|
function MockBrowserChannel() {
|
|
this.reachabilityEvents = {};
|
|
this.isClosed = function() {
|
|
return false;
|
|
};
|
|
this.isActive = function() {
|
|
return true;
|
|
};
|
|
this.shouldUseSecondaryDomains = function() {
|
|
return false;
|
|
};
|
|
this.completedRequests = [];
|
|
this.notifyServerReachabilityEvent = function(reachabilityType) {
|
|
if (!this.reachabilityEvents[reachabilityType]) {
|
|
this.reachabilityEvents[reachabilityType] = 0;
|
|
}
|
|
this.reachabilityEvents[reachabilityType]++;
|
|
};
|
|
this.onRequestComplete = function(request) {
|
|
this.completedRequests.push(request);
|
|
};
|
|
this.onRequestData = function(request, data) {};
|
|
}
|
|
|
|
|
|
/**
|
|
* Creates a real ChannelRequest object, with some modifications for
|
|
* testability:
|
|
* <ul>
|
|
* <li>The BrowserChannel is a MockBrowserChannel.
|
|
* <li>The new watchdogTimeoutCallCount property tracks onWatchDogTimeout_()
|
|
* calls.
|
|
* <li>The timeout is set to WATCHDOG_TIME.
|
|
* </ul>
|
|
*/
|
|
function createChannelRequest() {
|
|
xhrIo = new goog.testing.net.XhrIo();
|
|
xhrIo.abort = xhrIo.abort || function() {
|
|
this.active_ = false;
|
|
};
|
|
|
|
// Install mock browser channel and no-op debug logger.
|
|
mockBrowserChannel = new MockBrowserChannel();
|
|
channelRequest = new goog.net.ChannelRequest(
|
|
mockBrowserChannel,
|
|
new goog.net.ChannelDebug());
|
|
|
|
// Install test XhrIo.
|
|
mockBrowserChannel.createXhrIo = function() {
|
|
return xhrIo;
|
|
};
|
|
|
|
// Install watchdogTimeoutCallCount.
|
|
channelRequest.watchdogTimeoutCallCount = 0;
|
|
channelRequest.originalOnWatchDogTimeout = channelRequest.onWatchDogTimeout_;
|
|
channelRequest.onWatchDogTimeout_ = function() {
|
|
this.watchdogTimeoutCallCount++;
|
|
return this.originalOnWatchDogTimeout();
|
|
};
|
|
|
|
channelRequest.setTimeout(WATCHDOG_TIME);
|
|
}
|
|
|
|
|
|
/**
|
|
* Run through the lifecycle of a long lived request, checking that the right
|
|
* network events are reported.
|
|
*/
|
|
function testNetworkEvents() {
|
|
createChannelRequest();
|
|
|
|
channelRequest.xmlHttpPost(new goog.Uri('some_uri'), 'some_postdata', true);
|
|
checkReachabilityEvents(1, 0, 0, 0);
|
|
if (goog.net.ChannelRequest.supportsXhrStreaming()) {
|
|
xhrIo.simulatePartialResponse('17\nI am a BC Message');
|
|
checkReachabilityEvents(1, 0, 0, 1);
|
|
xhrIo.simulatePartialResponse('23\nI am another BC Message');
|
|
checkReachabilityEvents(1, 0, 0, 2);
|
|
xhrIo.simulateResponse(200, '16\Final BC Message');
|
|
checkReachabilityEvents(1, 1, 0, 2);
|
|
} else {
|
|
xhrIo.simulateResponse(200, '16\Final BC Message');
|
|
checkReachabilityEvents(1, 1, 0, 0);
|
|
}
|
|
}
|
|
|
|
|
|
/**
|
|
* Test throttling of readystatechange events.
|
|
*/
|
|
function testNetworkEvents_throttleReadyStateChange() {
|
|
createChannelRequest();
|
|
channelRequest.setReadyStateChangeThrottle(THROTTLE_TIME);
|
|
|
|
var recordedHandler =
|
|
goog.testing.recordFunction(channelRequest.xmlHttpHandler_);
|
|
stubs.set(channelRequest, 'xmlHttpHandler_', recordedHandler);
|
|
|
|
channelRequest.xmlHttpPost(new goog.Uri('some_uri'), 'some_postdata', true);
|
|
assertEquals(1, recordedHandler.getCallCount());
|
|
|
|
checkReachabilityEvents(1, 0, 0, 0);
|
|
if (goog.net.ChannelRequest.supportsXhrStreaming()) {
|
|
xhrIo.simulatePartialResponse('17\nI am a BC Message');
|
|
checkReachabilityEvents(1, 0, 0, 1);
|
|
assertEquals(3, recordedHandler.getCallCount());
|
|
|
|
// Second event should be throttled
|
|
xhrIo.simulatePartialResponse('23\nI am another BC Message');
|
|
assertEquals(3, recordedHandler.getCallCount());
|
|
|
|
xhrIo.simulatePartialResponse('27\nI am yet another BC Message');
|
|
assertEquals(3, recordedHandler.getCallCount());
|
|
mockClock.tick(THROTTLE_TIME);
|
|
|
|
checkReachabilityEvents(1, 0, 0, 3);
|
|
// Only one more call because of throttling.
|
|
assertEquals(4, recordedHandler.getCallCount());
|
|
|
|
xhrIo.simulateResponse(200, '16\Final BC Message');
|
|
checkReachabilityEvents(1, 1, 0, 3);
|
|
assertEquals(5, recordedHandler.getCallCount());
|
|
} else {
|
|
xhrIo.simulateResponse(200, '16\Final BC Message');
|
|
checkReachabilityEvents(1, 1, 0, 0);
|
|
}
|
|
}
|
|
|
|
|
|
/**
|
|
* Make sure that the request "completes" with an error when the timeout
|
|
* expires.
|
|
*/
|
|
function testRequestTimeout() {
|
|
createChannelRequest();
|
|
|
|
channelRequest.xmlHttpPost(new goog.Uri('some_uri'), 'some_postdata', true);
|
|
assertEquals(0, channelRequest.watchdogTimeoutCallCount);
|
|
assertEquals(0, channelRequest.channel_.completedRequests.length);
|
|
|
|
// Watchdog timeout.
|
|
mockClock.tick(WATCHDOG_TIME);
|
|
assertEquals(1, channelRequest.watchdogTimeoutCallCount);
|
|
assertEquals(1, channelRequest.channel_.completedRequests.length);
|
|
assertFalse(channelRequest.getSuccess());
|
|
|
|
// Make sure no more timers are firing.
|
|
mockClock.tick(ALL_DAY_MS);
|
|
assertEquals(1, channelRequest.watchdogTimeoutCallCount);
|
|
assertEquals(1, channelRequest.channel_.completedRequests.length);
|
|
|
|
checkReachabilityEvents(1, 0, 1, 0);
|
|
}
|
|
|
|
|
|
function testRequestTimeoutWithUnexpectedException() {
|
|
createChannelRequest();
|
|
channelRequest.channel_.createXhrIo = goog.functions.error('Weird error');
|
|
|
|
try {
|
|
channelRequest.xmlHttpGet(new goog.Uri('some_uri'), true, null);
|
|
fail('Expected error');
|
|
} catch (e) {
|
|
assertEquals('Weird error', e.message);
|
|
}
|
|
|
|
|
|
assertEquals(0, channelRequest.watchdogTimeoutCallCount);
|
|
assertEquals(0, channelRequest.channel_.completedRequests.length);
|
|
|
|
// Watchdog timeout.
|
|
mockClock.tick(WATCHDOG_TIME);
|
|
assertEquals(1, channelRequest.watchdogTimeoutCallCount);
|
|
assertEquals(1, channelRequest.channel_.completedRequests.length);
|
|
assertFalse(channelRequest.getSuccess());
|
|
|
|
// Make sure no more timers are firing.
|
|
mockClock.tick(ALL_DAY_MS);
|
|
assertEquals(1, channelRequest.watchdogTimeoutCallCount);
|
|
assertEquals(1, channelRequest.channel_.completedRequests.length);
|
|
|
|
checkReachabilityEvents(0, 0, 1, 0);
|
|
}
|
|
|
|
function testActiveXBlocked() {
|
|
createChannelRequest();
|
|
stubs.set(goog.global, 'ActiveXObject',
|
|
goog.functions.error('Active X blocked'));
|
|
|
|
channelRequest.tridentGet(new goog.Uri('some_uri'), false);
|
|
assertFalse(channelRequest.getSuccess());
|
|
assertEquals(goog.net.ChannelRequest.Error.ACTIVE_X_BLOCKED,
|
|
channelRequest.getLastError());
|
|
|
|
checkReachabilityEvents(0, 0, 0, 0);
|
|
}
|
|
|
|
function checkReachabilityEvents(reqMade, reqSucceeded, reqFail, backChannel) {
|
|
var Reachability = goog.net.BrowserChannel.ServerReachability;
|
|
assertEquals(reqMade,
|
|
mockBrowserChannel.reachabilityEvents[Reachability.REQUEST_MADE] || 0);
|
|
assertEquals(reqSucceeded,
|
|
mockBrowserChannel.reachabilityEvents[Reachability.REQUEST_SUCCEEDED] ||
|
|
0);
|
|
assertEquals(reqFail,
|
|
mockBrowserChannel.reachabilityEvents[Reachability.REQUEST_FAILED] || 0);
|
|
assertEquals(backChannel,
|
|
mockBrowserChannel.reachabilityEvents[
|
|
Reachability.BACK_CHANNEL_ACTIVITY] ||
|
|
0);
|
|
}
|