browserchannel_test.js 38 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326
  1. // Copyright 2009 The Closure Library Authors. All Rights Reserved.
  2. //
  3. // Licensed under the Apache License, Version 2.0 (the "License");
  4. // you may not use this file except in compliance with the License.
  5. // You may obtain a copy of the License at
  6. //
  7. // http://www.apache.org/licenses/LICENSE-2.0
  8. //
  9. // Unless required by applicable law or agreed to in writing, software
  10. // distributed under the License is distributed on an "AS-IS" BASIS,
  11. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. // See the License for the specific language governing permissions and
  13. // limitations under the License.
  14. goog.provide('goog.net.BrowserChannelTest');
  15. goog.setTestOnly('goog.net.BrowserChannelTest');
  16. goog.require('goog.Timer');
  17. goog.require('goog.array');
  18. goog.require('goog.dom');
  19. goog.require('goog.functions');
  20. goog.require('goog.json');
  21. goog.require('goog.net.BrowserChannel');
  22. goog.require('goog.net.ChannelDebug');
  23. goog.require('goog.net.ChannelRequest');
  24. goog.require('goog.net.tmpnetwork');
  25. goog.require('goog.structs.Map');
  26. goog.require('goog.testing.MockClock');
  27. goog.require('goog.testing.PropertyReplacer');
  28. goog.require('goog.testing.asserts');
  29. goog.require('goog.testing.jsunit');
  30. goog.require('goog.testing.recordFunction');
  31. /**
  32. * Delay between a network failure and the next network request.
  33. */
  34. var RETRY_TIME = 1000;
  35. /**
  36. * A really long time - used to make sure no more timeouts will fire.
  37. */
  38. var ALL_DAY_MS = 1000 * 60 * 60 * 24;
  39. var stubs = new goog.testing.PropertyReplacer();
  40. var browserChannel;
  41. var deliveredMaps;
  42. var handler;
  43. var mockClock;
  44. var gotError;
  45. var numStatEvents;
  46. var lastStatEvent;
  47. var numTimingEvents;
  48. var lastPostSize;
  49. var lastPostRtt;
  50. var lastPostRetryCount;
  51. // Set to true to see the channel debug output in the browser window.
  52. var debug = false;
  53. // Debug message to print out when debug is true.
  54. var debugMessage = '';
  55. function debugToWindow(message) {
  56. if (debug) {
  57. debugMessage += message + '<br>';
  58. goog.dom.getElement('debug').innerHTML = debugMessage;
  59. }
  60. }
  61. /**
  62. * Stubs goog.net.tmpnetwork to always time out. It maintains the
  63. * contract given by goog.net.tmpnetwork.testGoogleCom, but always
  64. * times out (calling callback(false)).
  65. *
  66. * stubTmpnetwork should be called in tests that require it before
  67. * a call to testGoogleCom happens. It is reset at tearDown.
  68. */
  69. function stubTmpnetwork() {
  70. stubs.set(
  71. goog.net.tmpnetwork, 'testLoadImage', function(url, timeout, callback) {
  72. goog.Timer.callOnce(goog.partial(callback, false), timeout);
  73. });
  74. }
  75. /**
  76. * Mock ChannelRequest.
  77. * @constructor
  78. */
  79. var MockChannelRequest = function(
  80. channel, channelDebug, opt_sessionId, opt_requestId, opt_retryId) {
  81. this.channel_ = channel;
  82. this.channelDebug_ = channelDebug;
  83. this.sessionId_ = opt_sessionId;
  84. this.requestId_ = opt_requestId;
  85. this.successful_ = true;
  86. this.lastError_ = null;
  87. this.lastStatusCode_ = 200;
  88. // For debugging, keep track of whether this is a back or forward channel.
  89. this.isBack = !!(opt_requestId == 'rpc');
  90. this.isForward = !this.isBack;
  91. };
  92. MockChannelRequest.prototype.postData_ = null;
  93. MockChannelRequest.prototype.requestStartTime_ = null;
  94. MockChannelRequest.prototype.requestUri_ = null;
  95. MockChannelRequest.prototype.setExtraHeaders = function(extraHeaders) {};
  96. MockChannelRequest.prototype.setTimeout = function(timeout) {};
  97. MockChannelRequest.prototype.setReadyStateChangeThrottle = function(throttle) {
  98. };
  99. MockChannelRequest.prototype.xmlHttpPost = function(
  100. uri, postData, decodeChunks) {
  101. this.channelDebug_.debug(
  102. '---> POST: ' + uri + ', ' + postData + ', ' + decodeChunks);
  103. this.postData_ = postData;
  104. this.requestStartTime_ = goog.now();
  105. };
  106. MockChannelRequest.prototype.xmlHttpGet = function(
  107. uri, decodeChunks, opt_noClose) {
  108. this.channelDebug_.debug(
  109. '<--- GET: ' + uri + ', ' + decodeChunks + ', ' + opt_noClose);
  110. this.requestUri_ = uri;
  111. this.requestStartTime_ = goog.now();
  112. };
  113. MockChannelRequest.prototype.tridentGet = function(uri, usingSecondaryDomain) {
  114. this.channelDebug_.debug('<---GET (T): ' + uri);
  115. this.requestUri_ = uri;
  116. this.requestStartTime_ = goog.now();
  117. };
  118. MockChannelRequest.prototype.sendUsingImgTag = function(uri) {
  119. this.requestStartTime_ = goog.now();
  120. };
  121. MockChannelRequest.prototype.cancel = function() {
  122. this.successful_ = false;
  123. };
  124. MockChannelRequest.prototype.getSuccess = function() {
  125. return this.successful_;
  126. };
  127. MockChannelRequest.prototype.getLastError = function() {
  128. return this.lastError_;
  129. };
  130. MockChannelRequest.prototype.getLastStatusCode = function() {
  131. return this.lastStatusCode_;
  132. };
  133. MockChannelRequest.prototype.getSessionId = function() {
  134. return this.sessionId_;
  135. };
  136. MockChannelRequest.prototype.getRequestId = function() {
  137. return this.requestId_;
  138. };
  139. MockChannelRequest.prototype.getPostData = function() {
  140. return this.postData_;
  141. };
  142. MockChannelRequest.prototype.getRequestStartTime = function() {
  143. return this.requestStartTime_;
  144. };
  145. function setUpPage() {
  146. // Use our MockChannelRequests instead of the real ones.
  147. goog.net.BrowserChannel.createChannelRequest = function(
  148. channel, channelDebug, opt_sessionId, opt_requestId, opt_retryId) {
  149. return new MockChannelRequest(
  150. channel, channelDebug, opt_sessionId, opt_requestId, opt_retryId);
  151. };
  152. // Mock out the stat notification code.
  153. goog.net.BrowserChannel.notifyStatEvent = function(stat) {
  154. numStatEvents++;
  155. lastStatEvent = stat;
  156. };
  157. goog.net.BrowserChannel.notifyTimingEvent = function(size, rtt, retries) {
  158. numTimingEvents++;
  159. lastPostSize = size;
  160. lastPostRtt = rtt;
  161. lastPostRetryCount = retries;
  162. };
  163. }
  164. function setUp() {
  165. numTimingEvents = 0;
  166. lastPostSize = null;
  167. lastPostRtt = null;
  168. lastPostRetryCount = null;
  169. mockClock = new goog.testing.MockClock(true);
  170. browserChannel = new goog.net.BrowserChannel('1');
  171. gotError = false;
  172. handler = new goog.net.BrowserChannel.Handler();
  173. handler.channelOpened = function() {};
  174. handler.channelError = function(channel, error) { gotError = true; };
  175. handler.channelSuccess = function(channel, maps) {
  176. deliveredMaps = goog.array.clone(maps);
  177. };
  178. handler.channelClosed = function(
  179. channel, opt_pendingMaps, opt_undeliveredMaps) {
  180. // Mock out the handler, and let it set a formatted user readable string
  181. // of the undelivered maps which we can use when verifying our assertions.
  182. if (opt_pendingMaps) {
  183. this.pendingMapsString = formatArrayOfMaps(opt_pendingMaps);
  184. }
  185. if (opt_undeliveredMaps) {
  186. this.undeliveredMapsString = formatArrayOfMaps(opt_undeliveredMaps);
  187. }
  188. };
  189. handler.channelHandleMultipleArrays = function() {};
  190. handler.channelHandleArray = function() {};
  191. browserChannel.setHandler(handler);
  192. // Provide a predictable retry time for testing.
  193. browserChannel.getRetryTime_ = function(retryCount) { return RETRY_TIME; };
  194. var channelDebug = new goog.net.ChannelDebug();
  195. channelDebug.debug = function(message) { debugToWindow(message); };
  196. browserChannel.setChannelDebug(channelDebug);
  197. numStatEvents = 0;
  198. lastStatEvent = null;
  199. }
  200. function tearDown() {
  201. mockClock.dispose();
  202. stubs.reset();
  203. debugToWindow('<hr>');
  204. }
  205. /**
  206. * Helper function to return a formatted string representing an array of maps.
  207. */
  208. function formatArrayOfMaps(arrayOfMaps) {
  209. var result = [];
  210. for (var i = 0; i < arrayOfMaps.length; i++) {
  211. var map = arrayOfMaps[i];
  212. var keys = map.map.getKeys();
  213. for (var j = 0; j < keys.length; j++) {
  214. var tmp = keys[j] + ':' + map.map.get(keys[j]) +
  215. (map.context ? ':' + map.context : '');
  216. result.push(tmp);
  217. }
  218. }
  219. return result.join(', ');
  220. }
  221. function testFormatArrayOfMaps() {
  222. // This function is used in a non-trivial test, so let's verify that it works.
  223. var map1 = new goog.structs.Map();
  224. map1.set('k1', 'v1');
  225. map1.set('k2', 'v2');
  226. var map2 = new goog.structs.Map();
  227. map2.set('k3', 'v3');
  228. var map3 = new goog.structs.Map();
  229. map3.set('k4', 'v4');
  230. map3.set('k5', 'v5');
  231. map3.set('k6', 'v6');
  232. // One map.
  233. var a = [];
  234. a.push(new goog.net.BrowserChannel.QueuedMap(0, map1));
  235. assertEquals('k1:v1, k2:v2', formatArrayOfMaps(a));
  236. // Many maps.
  237. var b = [];
  238. b.push(new goog.net.BrowserChannel.QueuedMap(0, map1));
  239. b.push(new goog.net.BrowserChannel.QueuedMap(0, map2));
  240. b.push(new goog.net.BrowserChannel.QueuedMap(0, map3));
  241. assertEquals(
  242. 'k1:v1, k2:v2, k3:v3, k4:v4, k5:v5, k6:v6', formatArrayOfMaps(b));
  243. // One map with a context.
  244. var c = [];
  245. c.push(new goog.net.BrowserChannel.QueuedMap(0, map1, 'c1'));
  246. assertEquals('k1:v1:c1, k2:v2:c1', formatArrayOfMaps(c));
  247. }
  248. function connectForwardChannel(
  249. opt_serverVersion, opt_hostPrefix, opt_uriPrefix) {
  250. var uriPrefix = opt_uriPrefix || '';
  251. browserChannel.connect(uriPrefix + '/test', uriPrefix + '/bind', null);
  252. mockClock.tick(0);
  253. completeTestConnection();
  254. completeForwardChannel(opt_serverVersion, opt_hostPrefix);
  255. }
  256. function connect(opt_serverVersion, opt_hostPrefix, opt_uriPrefix) {
  257. connectForwardChannel(opt_serverVersion, opt_hostPrefix, opt_uriPrefix);
  258. completeBackChannel();
  259. }
  260. function disconnect() {
  261. browserChannel.disconnect();
  262. mockClock.tick(0);
  263. }
  264. function completeTestConnection() {
  265. completeForwardTestConnection();
  266. completeBackTestConnection();
  267. assertEquals(
  268. goog.net.BrowserChannel.State.OPENING, browserChannel.getState());
  269. }
  270. function completeForwardTestConnection() {
  271. browserChannel.connectionTest_.onRequestData(
  272. browserChannel.connectionTest_, '["b"]');
  273. browserChannel.connectionTest_.onRequestComplete(
  274. browserChannel.connectionTest_);
  275. mockClock.tick(0);
  276. }
  277. function completeBackTestConnection() {
  278. browserChannel.connectionTest_.onRequestData(
  279. browserChannel.connectionTest_, '11111');
  280. mockClock.tick(0);
  281. }
  282. function completeForwardChannel(opt_serverVersion, opt_hostPrefix) {
  283. var responseData = '[[0,["c","1234567890ABCDEF",' +
  284. (opt_hostPrefix ? '"' + opt_hostPrefix + '"' : 'null') +
  285. (opt_serverVersion ? ',' + opt_serverVersion : '') + ']]]';
  286. browserChannel.onRequestData(
  287. browserChannel.forwardChannelRequest_, responseData);
  288. browserChannel.onRequestComplete(browserChannel.forwardChannelRequest_);
  289. mockClock.tick(0);
  290. }
  291. function completeBackChannel() {
  292. browserChannel.onRequestData(
  293. browserChannel.backChannelRequest_, '[[1,["foo"]]]');
  294. browserChannel.onRequestComplete(browserChannel.backChannelRequest_);
  295. mockClock.tick(0);
  296. }
  297. function responseVersion7() {
  298. browserChannel.onRequestData(
  299. browserChannel.forwardChannelRequest_,
  300. goog.net.ChannelDebug.MAGIC_RESPONSE_COOKIE);
  301. browserChannel.onRequestComplete(browserChannel.forwardChannelRequest_);
  302. mockClock.tick(0);
  303. }
  304. function responseNoBackchannel(lastArrayIdSentFromServer, outstandingDataSize) {
  305. responseData =
  306. goog.json.serialize([0, lastArrayIdSentFromServer, outstandingDataSize]);
  307. browserChannel.onRequestData(
  308. browserChannel.forwardChannelRequest_, responseData);
  309. browserChannel.onRequestComplete(browserChannel.forwardChannelRequest_);
  310. mockClock.tick(0);
  311. }
  312. function response(lastArrayIdSentFromServer, outstandingDataSize) {
  313. responseData =
  314. goog.json.serialize([1, lastArrayIdSentFromServer, outstandingDataSize]);
  315. browserChannel.onRequestData(
  316. browserChannel.forwardChannelRequest_, responseData);
  317. browserChannel.onRequestComplete(browserChannel.forwardChannelRequest_);
  318. mockClock.tick(0);
  319. }
  320. function receive(data) {
  321. browserChannel.onRequestData(
  322. browserChannel.backChannelRequest_, '[[1,' + data + ']]');
  323. browserChannel.onRequestComplete(browserChannel.backChannelRequest_);
  324. mockClock.tick(0);
  325. }
  326. function responseTimeout() {
  327. browserChannel.forwardChannelRequest_lastError_ =
  328. goog.net.ChannelRequest.Error.TIMEOUT;
  329. browserChannel.forwardChannelRequest_.successful_ = false;
  330. browserChannel.onRequestComplete(browserChannel.forwardChannelRequest_);
  331. mockClock.tick(0);
  332. }
  333. function responseRequestFailed(opt_statusCode) {
  334. browserChannel.forwardChannelRequest_.lastError_ =
  335. goog.net.ChannelRequest.Error.STATUS;
  336. browserChannel.forwardChannelRequest_.lastStatusCode_ = opt_statusCode || 503;
  337. browserChannel.forwardChannelRequest_.successful_ = false;
  338. browserChannel.onRequestComplete(browserChannel.forwardChannelRequest_);
  339. mockClock.tick(0);
  340. }
  341. function responseUnknownSessionId() {
  342. browserChannel.forwardChannelRequest_.lastError_ =
  343. goog.net.ChannelRequest.Error.UNKNOWN_SESSION_ID;
  344. browserChannel.forwardChannelRequest_.successful_ = false;
  345. browserChannel.onRequestComplete(browserChannel.forwardChannelRequest_);
  346. mockClock.tick(0);
  347. }
  348. function responseActiveXBlocked() {
  349. browserChannel.backChannelRequest_.lastError_ =
  350. goog.net.ChannelRequest.Error.ACTIVE_X_BLOCKED;
  351. browserChannel.backChannelRequest_.successful_ = false;
  352. browserChannel.onRequestComplete(browserChannel.backChannelRequest_);
  353. mockClock.tick(0);
  354. }
  355. function sendMap(key, value, opt_context) {
  356. var map = new goog.structs.Map();
  357. map.set(key, value);
  358. browserChannel.sendMap(map, opt_context);
  359. mockClock.tick(0);
  360. }
  361. function hasForwardChannel() {
  362. return !!browserChannel.forwardChannelRequest_;
  363. }
  364. function hasBackChannel() {
  365. return !!browserChannel.backChannelRequest_;
  366. }
  367. function hasDeadBackChannelTimer() {
  368. return goog.isDefAndNotNull(browserChannel.deadBackChannelTimerId_);
  369. }
  370. function assertHasForwardChannel() {
  371. assertTrue('Forward channel missing.', hasForwardChannel());
  372. }
  373. function assertHasBackChannel() {
  374. assertTrue('Back channel missing.', hasBackChannel());
  375. }
  376. function testConnect() {
  377. connect();
  378. assertEquals(goog.net.BrowserChannel.State.OPENED, browserChannel.getState());
  379. // If the server specifies no version, the client assumes 6
  380. assertEquals(6, browserChannel.channelVersion_);
  381. assertFalse(browserChannel.isBuffered());
  382. }
  383. function testConnect_backChannelEstablished() {
  384. connect();
  385. assertHasBackChannel();
  386. }
  387. function testConnect_withServerHostPrefix() {
  388. connect(undefined, 'serverHostPrefix');
  389. assertEquals('serverHostPrefix', browserChannel.hostPrefix_);
  390. }
  391. function testConnect_withClientHostPrefix() {
  392. handler.correctHostPrefix = function(hostPrefix) {
  393. return 'clientHostPrefix';
  394. };
  395. connect();
  396. assertEquals('clientHostPrefix', browserChannel.hostPrefix_);
  397. }
  398. function testConnect_overrideServerHostPrefix() {
  399. handler.correctHostPrefix = function(hostPrefix) {
  400. return 'clientHostPrefix';
  401. };
  402. connect(undefined, 'serverHostPrefix');
  403. assertEquals('clientHostPrefix', browserChannel.hostPrefix_);
  404. }
  405. function testConnect_withServerVersion() {
  406. connect(8);
  407. assertEquals(8, browserChannel.channelVersion_);
  408. }
  409. function testConnect_notOkToMakeRequestForTest() {
  410. handler.okToMakeRequest =
  411. goog.functions.constant(goog.net.BrowserChannel.Error.NETWORK);
  412. browserChannel.connect('/test', '/bind', null);
  413. mockClock.tick(0);
  414. assertEquals(goog.net.BrowserChannel.State.CLOSED, browserChannel.getState());
  415. }
  416. function testConnect_notOkToMakeRequestForBind() {
  417. browserChannel.connect('/test', '/bind', null);
  418. mockClock.tick(0);
  419. completeTestConnection();
  420. handler.okToMakeRequest =
  421. goog.functions.constant(goog.net.BrowserChannel.Error.NETWORK);
  422. completeForwardChannel();
  423. assertEquals(goog.net.BrowserChannel.State.CLOSED, browserChannel.getState());
  424. }
  425. function testSendMap() {
  426. connect();
  427. assertEquals(1, numTimingEvents);
  428. sendMap('foo', 'bar');
  429. responseVersion7();
  430. assertEquals(2, numTimingEvents);
  431. assertEquals('foo:bar', formatArrayOfMaps(deliveredMaps));
  432. }
  433. function testSendMap_twice() {
  434. connect();
  435. sendMap('foo1', 'bar1');
  436. responseVersion7();
  437. assertEquals('foo1:bar1', formatArrayOfMaps(deliveredMaps));
  438. sendMap('foo2', 'bar2');
  439. responseVersion7();
  440. assertEquals('foo2:bar2', formatArrayOfMaps(deliveredMaps));
  441. }
  442. function testSendMap_andReceive() {
  443. connect();
  444. sendMap('foo', 'bar');
  445. responseVersion7();
  446. receive('["the server reply"]');
  447. }
  448. function testReceive() {
  449. connect();
  450. receive('["message from server"]');
  451. assertHasBackChannel();
  452. }
  453. function testReceive_twice() {
  454. connect();
  455. receive('["message one from server"]');
  456. receive('["message two from server"]');
  457. assertHasBackChannel();
  458. }
  459. function testReceive_andSendMap() {
  460. connect();
  461. receive('["the server reply"]');
  462. sendMap('foo', 'bar');
  463. responseVersion7();
  464. assertHasBackChannel();
  465. }
  466. function testBackChannelRemainsEstablished_afterSingleSendMap() {
  467. connect();
  468. sendMap('foo', 'bar');
  469. responseVersion7();
  470. receive('["ack"]');
  471. assertHasBackChannel();
  472. }
  473. function testBackChannelRemainsEstablished_afterDoubleSendMap() {
  474. connect();
  475. sendMap('foo1', 'bar1');
  476. sendMap('foo2', 'bar2');
  477. responseVersion7();
  478. receive('["ack"]');
  479. // This assertion would fail prior to CL 13302660.
  480. assertHasBackChannel();
  481. }
  482. function testTimingEvent() {
  483. connect();
  484. assertEquals(1, numTimingEvents);
  485. sendMap('', '');
  486. assertEquals(1, numTimingEvents);
  487. mockClock.tick(20);
  488. var expSize = browserChannel.forwardChannelRequest_.getPostData().length;
  489. responseVersion7();
  490. assertEquals(2, numTimingEvents);
  491. assertEquals(expSize, lastPostSize);
  492. assertEquals(20, lastPostRtt);
  493. assertEquals(0, lastPostRetryCount);
  494. sendMap('abcdefg', '123456');
  495. expSize = browserChannel.forwardChannelRequest_.getPostData().length;
  496. responseTimeout();
  497. assertEquals(2, numTimingEvents);
  498. mockClock.tick(RETRY_TIME + 1);
  499. responseVersion7();
  500. assertEquals(3, numTimingEvents);
  501. assertEquals(expSize, lastPostSize);
  502. assertEquals(1, lastPostRetryCount);
  503. assertEquals(1, lastPostRtt);
  504. }
  505. /**
  506. * Make sure that dropping the forward channel retry limit below the retry count
  507. * reports an error, and prevents another request from firing.
  508. */
  509. function testSetFailFastWhileWaitingForRetry() {
  510. stubTmpnetwork();
  511. connect();
  512. assertEquals(1, numTimingEvents);
  513. sendMap('foo', 'bar');
  514. assertNull(browserChannel.forwardChannelTimerId_);
  515. assertNotNull(browserChannel.forwardChannelRequest_);
  516. assertEquals(0, browserChannel.forwardChannelRetryCount_);
  517. // Watchdog timeout.
  518. responseTimeout();
  519. assertNotNull(browserChannel.forwardChannelTimerId_);
  520. assertNull(browserChannel.forwardChannelRequest_);
  521. assertEquals(1, browserChannel.forwardChannelRetryCount_);
  522. // Almost finish the between-retry timeout.
  523. mockClock.tick(RETRY_TIME - 1);
  524. assertNotNull(browserChannel.forwardChannelTimerId_);
  525. assertNull(browserChannel.forwardChannelRequest_);
  526. assertEquals(1, browserChannel.forwardChannelRetryCount_);
  527. // Setting max retries to 0 should cancel the timer and raise an error.
  528. browserChannel.setFailFast(true);
  529. assertNull(browserChannel.forwardChannelTimerId_);
  530. assertNull(browserChannel.forwardChannelRequest_);
  531. assertEquals(1, browserChannel.forwardChannelRetryCount_);
  532. assertTrue(gotError);
  533. assertEquals(0, deliveredMaps.length);
  534. // We get the error immediately before starting to ping google.com.
  535. // Simulate that timing out. We should get a network error in addition to the
  536. // initial failure.
  537. gotError = false;
  538. mockClock.tick(goog.net.tmpnetwork.GOOGLECOM_TIMEOUT);
  539. assertTrue('No error after tmpnetwork ping timed out.', gotError);
  540. // Make sure no more retry timers are firing.
  541. mockClock.tick(ALL_DAY_MS);
  542. assertNull(browserChannel.forwardChannelTimerId_);
  543. assertNull(browserChannel.forwardChannelRequest_);
  544. assertEquals(1, browserChannel.forwardChannelRetryCount_);
  545. assertEquals(1, numTimingEvents);
  546. }
  547. /**
  548. * Make sure that dropping the forward channel retry limit below the retry count
  549. * reports an error, and prevents another request from firing.
  550. */
  551. function testSetFailFastWhileRetryXhrIsInFlight() {
  552. stubTmpnetwork();
  553. connect();
  554. assertEquals(1, numTimingEvents);
  555. sendMap('foo', 'bar');
  556. assertNull(browserChannel.forwardChannelTimerId_);
  557. assertNotNull(browserChannel.forwardChannelRequest_);
  558. assertEquals(0, browserChannel.forwardChannelRetryCount_);
  559. // Watchdog timeout.
  560. responseTimeout();
  561. assertNotNull(browserChannel.forwardChannelTimerId_);
  562. assertNull(browserChannel.forwardChannelRequest_);
  563. assertEquals(1, browserChannel.forwardChannelRetryCount_);
  564. // Wait for the between-retry timeout.
  565. mockClock.tick(RETRY_TIME);
  566. assertNull(browserChannel.forwardChannelTimerId_);
  567. assertNotNull(browserChannel.forwardChannelRequest_);
  568. assertEquals(1, browserChannel.forwardChannelRetryCount_);
  569. // Simulate a second watchdog timeout.
  570. responseTimeout();
  571. assertNotNull(browserChannel.forwardChannelTimerId_);
  572. assertNull(browserChannel.forwardChannelRequest_);
  573. assertEquals(2, browserChannel.forwardChannelRetryCount_);
  574. // Wait for another between-retry timeout.
  575. mockClock.tick(RETRY_TIME);
  576. // Now the third req is in flight.
  577. assertNull(browserChannel.forwardChannelTimerId_);
  578. assertNotNull(browserChannel.forwardChannelRequest_);
  579. assertEquals(2, browserChannel.forwardChannelRetryCount_);
  580. // Set fail fast, killing the request
  581. browserChannel.setFailFast(true);
  582. assertNull(browserChannel.forwardChannelTimerId_);
  583. assertNull(browserChannel.forwardChannelRequest_);
  584. assertEquals(2, browserChannel.forwardChannelRetryCount_);
  585. assertTrue(gotError);
  586. // We get the error immediately before starting to ping google.com.
  587. // Simulate that timing out. We should get a network error in addition to the
  588. gotError = false;
  589. mockClock.tick(goog.net.tmpnetwork.GOOGLECOM_TIMEOUT);
  590. assertTrue('No error after tmpnetwork ping timed out.', gotError);
  591. // Make sure no more retry timers are firing.
  592. mockClock.tick(ALL_DAY_MS);
  593. assertNull(browserChannel.forwardChannelTimerId_);
  594. assertNull(browserChannel.forwardChannelRequest_);
  595. assertEquals(2, browserChannel.forwardChannelRetryCount_);
  596. assertEquals(1, numTimingEvents);
  597. }
  598. /**
  599. * Makes sure that setting fail fast while not retrying doesn't cause a failure.
  600. */
  601. function testSetFailFastAtRetryCount() {
  602. stubTmpnetwork();
  603. connect();
  604. assertEquals(1, numTimingEvents);
  605. sendMap('foo', 'bar');
  606. assertNull(browserChannel.forwardChannelTimerId_);
  607. assertNotNull(browserChannel.forwardChannelRequest_);
  608. assertEquals(0, browserChannel.forwardChannelRetryCount_);
  609. // Set fail fast.
  610. browserChannel.setFailFast(true);
  611. // Request should still be alive.
  612. assertNull(browserChannel.forwardChannelTimerId_);
  613. assertNotNull(browserChannel.forwardChannelRequest_);
  614. assertEquals(0, browserChannel.forwardChannelRetryCount_);
  615. // Watchdog timeout. Now we should get an error.
  616. responseTimeout();
  617. assertNull(browserChannel.forwardChannelTimerId_);
  618. assertNull(browserChannel.forwardChannelRequest_);
  619. assertEquals(0, browserChannel.forwardChannelRetryCount_);
  620. assertTrue(gotError);
  621. // We get the error immediately before starting to ping google.com.
  622. // Simulate that timing out. We should get a network error in addition to the
  623. // initial failure.
  624. gotError = false;
  625. mockClock.tick(goog.net.tmpnetwork.GOOGLECOM_TIMEOUT);
  626. assertTrue('No error after tmpnetwork ping timed out.', gotError);
  627. // Make sure no more retry timers are firing.
  628. mockClock.tick(ALL_DAY_MS);
  629. assertNull(browserChannel.forwardChannelTimerId_);
  630. assertNull(browserChannel.forwardChannelRequest_);
  631. assertEquals(0, browserChannel.forwardChannelRetryCount_);
  632. assertEquals(1, numTimingEvents);
  633. }
  634. function testRequestFailedClosesChannel() {
  635. stubTmpnetwork();
  636. connect();
  637. assertEquals(1, numTimingEvents);
  638. sendMap('foo', 'bar');
  639. responseRequestFailed();
  640. assertEquals(
  641. 'Should be closed immediately after request failed.',
  642. goog.net.BrowserChannel.State.CLOSED, browserChannel.getState());
  643. mockClock.tick(goog.net.tmpnetwork.GOOGLECOM_TIMEOUT);
  644. assertEquals(
  645. 'Should remain closed after the ping timeout.',
  646. goog.net.BrowserChannel.State.CLOSED, browserChannel.getState());
  647. assertEquals(1, numTimingEvents);
  648. }
  649. function testStatEventReportedOnlyOnce() {
  650. stubTmpnetwork();
  651. connect();
  652. sendMap('foo', 'bar');
  653. numStatEvents = 0;
  654. lastStatEvent = null;
  655. responseUnknownSessionId();
  656. assertEquals(1, numStatEvents);
  657. assertEquals(goog.net.BrowserChannel.Stat.ERROR_OTHER, lastStatEvent);
  658. numStatEvents = 0;
  659. mockClock.tick(goog.net.tmpnetwork.GOOGLECOM_TIMEOUT);
  660. assertEquals('No new stat events should be reported.', 0, numStatEvents);
  661. }
  662. function testActiveXBlockedEventReportedOnlyOnce() {
  663. stubTmpnetwork();
  664. connectForwardChannel();
  665. numStatEvents = 0;
  666. lastStatEvent = null;
  667. responseActiveXBlocked();
  668. assertEquals(1, numStatEvents);
  669. assertEquals(goog.net.BrowserChannel.Stat.ERROR_OTHER, lastStatEvent);
  670. mockClock.tick(goog.net.tmpnetwork.GOOGLECOM_TIMEOUT);
  671. assertEquals('No new stat events should be reported.', 1, numStatEvents);
  672. }
  673. function testStatEventReportedOnlyOnce_onNetworkUp() {
  674. stubTmpnetwork();
  675. connect();
  676. sendMap('foo', 'bar');
  677. numStatEvents = 0;
  678. lastStatEvent = null;
  679. responseRequestFailed();
  680. assertEquals(
  681. 'No stat event should be reported before we know the reason.', 0,
  682. numStatEvents);
  683. // Let the ping time out.
  684. mockClock.tick(goog.net.tmpnetwork.GOOGLECOM_TIMEOUT);
  685. // Assert we report the correct stat event.
  686. assertEquals(1, numStatEvents);
  687. assertEquals(goog.net.BrowserChannel.Stat.ERROR_NETWORK, lastStatEvent);
  688. }
  689. function testStatEventReportedOnlyOnce_onNetworkDown() {
  690. stubTmpnetwork();
  691. connect();
  692. sendMap('foo', 'bar');
  693. numStatEvents = 0;
  694. lastStatEvent = null;
  695. responseRequestFailed();
  696. assertEquals(
  697. 'No stat event should be reported before we know the reason.', 0,
  698. numStatEvents);
  699. // Wait half the ping timeout period, and then fake the network being up.
  700. mockClock.tick(goog.net.tmpnetwork.GOOGLECOM_TIMEOUT / 2);
  701. browserChannel.testGoogleComCallback_(true);
  702. // Assert we report the correct stat event.
  703. assertEquals(1, numStatEvents);
  704. assertEquals(goog.net.BrowserChannel.Stat.ERROR_OTHER, lastStatEvent);
  705. }
  706. function testOutgoingMapsAwaitsResponse() {
  707. connect();
  708. assertEquals(0, browserChannel.outgoingMaps_.length);
  709. sendMap('foo1', 'bar');
  710. assertEquals(0, browserChannel.outgoingMaps_.length);
  711. sendMap('foo2', 'bar');
  712. assertEquals(1, browserChannel.outgoingMaps_.length);
  713. sendMap('foo3', 'bar');
  714. assertEquals(2, browserChannel.outgoingMaps_.length);
  715. sendMap('foo4', 'bar');
  716. assertEquals(3, browserChannel.outgoingMaps_.length);
  717. responseVersion7();
  718. // Now the forward channel request is completed and a new started, so all maps
  719. // are dequeued from the array of outgoing maps into this new forward request.
  720. assertEquals(0, browserChannel.outgoingMaps_.length);
  721. }
  722. function testUndeliveredMaps_doesNotNotifyWhenSuccessful() {
  723. handler.channelClosed = function(
  724. channel, opt_pendingMaps, opt_undeliveredMaps) {
  725. if (opt_pendingMaps || opt_undeliveredMaps) {
  726. fail('No pending or undelivered maps should be reported.');
  727. }
  728. };
  729. connect();
  730. sendMap('foo1', 'bar1');
  731. responseVersion7();
  732. sendMap('foo2', 'bar2');
  733. responseVersion7();
  734. disconnect();
  735. }
  736. function testUndeliveredMaps_doesNotNotifyIfNothingWasSent() {
  737. handler.channelClosed = function(
  738. channel, opt_pendingMaps, opt_undeliveredMaps) {
  739. if (opt_pendingMaps || opt_undeliveredMaps) {
  740. fail('No pending or undelivered maps should be reported.');
  741. }
  742. };
  743. connect();
  744. mockClock.tick(ALL_DAY_MS);
  745. disconnect();
  746. }
  747. function testUndeliveredMaps_clearsPendingMapsAfterNotifying() {
  748. connect();
  749. sendMap('foo1', 'bar1');
  750. sendMap('foo2', 'bar2');
  751. sendMap('foo3', 'bar3');
  752. assertEquals(1, browserChannel.pendingMaps_.length);
  753. assertEquals(2, browserChannel.outgoingMaps_.length);
  754. disconnect();
  755. assertEquals(0, browserChannel.pendingMaps_.length);
  756. assertEquals(0, browserChannel.outgoingMaps_.length);
  757. }
  758. function testUndeliveredMaps_notifiesWithContext() {
  759. connect();
  760. // First send two messages that succeed.
  761. sendMap('foo1', 'bar1', 'context1');
  762. responseVersion7();
  763. sendMap('foo2', 'bar2', 'context2');
  764. responseVersion7();
  765. // Pretend the server hangs and no longer responds.
  766. sendMap('foo3', 'bar3', 'context3');
  767. sendMap('foo4', 'bar4', 'context4');
  768. sendMap('foo5', 'bar5', 'context5');
  769. // Give up.
  770. disconnect();
  771. // Assert that we are informed of any undelivered messages; both about
  772. // #3 that was sent but which we don't know if the server received, and
  773. // #4 and #5 which remain in the outgoing maps and have not yet been sent.
  774. assertEquals('foo3:bar3:context3', handler.pendingMapsString);
  775. assertEquals(
  776. 'foo4:bar4:context4, foo5:bar5:context5', handler.undeliveredMapsString);
  777. }
  778. function testUndeliveredMaps_serviceUnavailable() {
  779. // Send a few maps, and let one fail.
  780. connect();
  781. sendMap('foo1', 'bar1');
  782. responseVersion7();
  783. sendMap('foo2', 'bar2');
  784. responseRequestFailed();
  785. // After a failure, the channel should be closed.
  786. disconnect();
  787. assertEquals('foo2:bar2', handler.pendingMapsString);
  788. assertEquals('', handler.undeliveredMapsString);
  789. }
  790. function testUndeliveredMaps_onPingTimeout() {
  791. stubTmpnetwork();
  792. connect();
  793. // Send a message.
  794. sendMap('foo1', 'bar1');
  795. // Fake REQUEST_FAILED, triggering a ping to check the network.
  796. responseRequestFailed();
  797. // Let the ping time out, unsuccessfully.
  798. mockClock.tick(goog.net.tmpnetwork.GOOGLECOM_TIMEOUT);
  799. // Assert channel is closed.
  800. assertEquals(goog.net.BrowserChannel.State.CLOSED, browserChannel.getState());
  801. // Assert that the handler is notified about the undelivered messages.
  802. assertEquals('foo1:bar1', handler.pendingMapsString);
  803. assertEquals('', handler.undeliveredMapsString);
  804. }
  805. function testResponseNoBackchannelPostNotBeforeBackchannel() {
  806. connect(8);
  807. sendMap('foo1', 'bar1');
  808. mockClock.tick(10);
  809. assertFalse(
  810. browserChannel.backChannelRequest_.getRequestStartTime() <
  811. browserChannel.forwardChannelRequest_.getRequestStartTime());
  812. responseNoBackchannel();
  813. assertNotEquals(
  814. goog.net.BrowserChannel.Stat.BACKCHANNEL_MISSING, lastStatEvent);
  815. }
  816. function testResponseNoBackchannel() {
  817. connect(8);
  818. sendMap('foo1', 'bar1');
  819. response(-1, 0);
  820. mockClock.tick(goog.net.BrowserChannel.RTT_ESTIMATE + 1);
  821. sendMap('foo2', 'bar2');
  822. assertTrue(
  823. browserChannel.backChannelRequest_.getRequestStartTime() +
  824. goog.net.BrowserChannel.RTT_ESTIMATE <
  825. browserChannel.forwardChannelRequest_.getRequestStartTime());
  826. responseNoBackchannel();
  827. assertEquals(goog.net.BrowserChannel.Stat.BACKCHANNEL_MISSING, lastStatEvent);
  828. }
  829. function testResponseNoBackchannelWithNoBackchannel() {
  830. connect(8);
  831. sendMap('foo1', 'bar1');
  832. assertNull(browserChannel.backChannelTimerId_);
  833. browserChannel.backChannelRequest_.cancel();
  834. browserChannel.backChannelRequest_ = null;
  835. responseNoBackchannel();
  836. assertEquals(goog.net.BrowserChannel.Stat.BACKCHANNEL_MISSING, lastStatEvent);
  837. }
  838. function testResponseNoBackchannelWithStartTimer() {
  839. connect(8);
  840. sendMap('foo1', 'bar1');
  841. browserChannel.backChannelRequest_.cancel();
  842. browserChannel.backChannelRequest_ = null;
  843. browserChannel.backChannelTimerId_ = 123;
  844. responseNoBackchannel();
  845. assertNotEquals(
  846. goog.net.BrowserChannel.Stat.BACKCHANNEL_MISSING, lastStatEvent);
  847. }
  848. function testResponseWithNoArraySent() {
  849. connect(8);
  850. sendMap('foo1', 'bar1');
  851. // Send a response as if the server hasn't sent down an array.
  852. response(-1, 0);
  853. // POST response with an array ID lower than our last received is OK.
  854. assertEquals(1, browserChannel.lastArrayId_);
  855. assertEquals(-1, browserChannel.lastPostResponseArrayId_);
  856. }
  857. function testResponseWithArraysMissing() {
  858. connect(8);
  859. sendMap('foo1', 'bar1');
  860. assertEquals(-1, browserChannel.lastPostResponseArrayId_);
  861. // Send a response as if the server has sent down seven arrays.
  862. response(7, 111);
  863. assertEquals(1, browserChannel.lastArrayId_);
  864. assertEquals(7, browserChannel.lastPostResponseArrayId_);
  865. mockClock.tick(goog.net.BrowserChannel.RTT_ESTIMATE * 2);
  866. assertEquals(goog.net.BrowserChannel.Stat.BACKCHANNEL_DEAD, lastStatEvent);
  867. }
  868. function testMultipleResponsesWithArraysMissing() {
  869. connect(8);
  870. sendMap('foo1', 'bar1');
  871. assertEquals(-1, browserChannel.lastPostResponseArrayId_);
  872. // Send a response as if the server has sent down seven arrays.
  873. response(7, 111);
  874. assertEquals(1, browserChannel.lastArrayId_);
  875. assertEquals(7, browserChannel.lastPostResponseArrayId_);
  876. sendMap('foo2', 'bar2');
  877. mockClock.tick(goog.net.BrowserChannel.RTT_ESTIMATE);
  878. response(8, 119);
  879. mockClock.tick(goog.net.BrowserChannel.RTT_ESTIMATE);
  880. // The original timer should still fire.
  881. assertEquals(goog.net.BrowserChannel.Stat.BACKCHANNEL_DEAD, lastStatEvent);
  882. }
  883. function testOnlyRetryOnceBasedOnResponse() {
  884. connect(8);
  885. sendMap('foo1', 'bar1');
  886. assertEquals(-1, browserChannel.lastPostResponseArrayId_);
  887. // Send a response as if the server has sent down seven arrays.
  888. response(7, 111);
  889. assertEquals(1, browserChannel.lastArrayId_);
  890. assertEquals(7, browserChannel.lastPostResponseArrayId_);
  891. assertTrue(hasDeadBackChannelTimer());
  892. mockClock.tick(goog.net.BrowserChannel.RTT_ESTIMATE * 2);
  893. assertEquals(goog.net.BrowserChannel.Stat.BACKCHANNEL_DEAD, lastStatEvent);
  894. assertEquals(1, browserChannel.backChannelRetryCount_);
  895. mockClock.tick(goog.net.BrowserChannel.RTT_ESTIMATE);
  896. sendMap('foo2', 'bar2');
  897. assertFalse(hasDeadBackChannelTimer());
  898. response(8, 119);
  899. assertFalse(hasDeadBackChannelTimer());
  900. }
  901. function testResponseWithArraysMissingAndLiveChannel() {
  902. connect(8);
  903. sendMap('foo1', 'bar1');
  904. assertEquals(-1, browserChannel.lastPostResponseArrayId_);
  905. // Send a response as if the server has sent down seven arrays.
  906. response(7, 111);
  907. assertEquals(1, browserChannel.lastArrayId_);
  908. assertEquals(7, browserChannel.lastPostResponseArrayId_);
  909. mockClock.tick(goog.net.BrowserChannel.RTT_ESTIMATE);
  910. assertTrue(hasDeadBackChannelTimer());
  911. receive('["ack"]');
  912. assertFalse(hasDeadBackChannelTimer());
  913. mockClock.tick(goog.net.BrowserChannel.RTT_ESTIMATE);
  914. assertNotEquals(goog.net.BrowserChannel.Stat.BACKCHANNEL_DEAD, lastStatEvent);
  915. }
  916. function testResponseWithBigOutstandingData() {
  917. connect(8);
  918. sendMap('foo1', 'bar1');
  919. assertEquals(-1, browserChannel.lastPostResponseArrayId_);
  920. // Send a response as if the server has sent down seven arrays and 50kbytes.
  921. response(7, 50000);
  922. assertEquals(1, browserChannel.lastArrayId_);
  923. assertEquals(7, browserChannel.lastPostResponseArrayId_);
  924. assertFalse(hasDeadBackChannelTimer());
  925. mockClock.tick(goog.net.BrowserChannel.RTT_ESTIMATE * 2);
  926. assertNotEquals(goog.net.BrowserChannel.Stat.BACKCHANNEL_DEAD, lastStatEvent);
  927. }
  928. function testResponseInBufferedMode() {
  929. connect(8);
  930. browserChannel.useChunked_ = false;
  931. sendMap('foo1', 'bar1');
  932. assertEquals(-1, browserChannel.lastPostResponseArrayId_);
  933. response(7, 111);
  934. assertEquals(1, browserChannel.lastArrayId_);
  935. assertEquals(7, browserChannel.lastPostResponseArrayId_);
  936. assertFalse(hasDeadBackChannelTimer());
  937. mockClock.tick(goog.net.BrowserChannel.RTT_ESTIMATE * 2);
  938. assertNotEquals(goog.net.BrowserChannel.Stat.BACKCHANNEL_DEAD, lastStatEvent);
  939. }
  940. function testResponseWithGarbage() {
  941. connect(8);
  942. sendMap('foo1', 'bar1');
  943. browserChannel.onRequestData(
  944. browserChannel.forwardChannelRequest_, 'garbage');
  945. assertEquals(goog.net.BrowserChannel.State.CLOSED, browserChannel.getState());
  946. }
  947. function testResponseWithGarbageInArray() {
  948. connect(8);
  949. sendMap('foo1', 'bar1');
  950. browserChannel.onRequestData(
  951. browserChannel.forwardChannelRequest_, '["garbage"]');
  952. assertEquals(goog.net.BrowserChannel.State.CLOSED, browserChannel.getState());
  953. }
  954. function testResponseWithEvilData() {
  955. connect(8);
  956. sendMap('foo1', 'bar1');
  957. browserChannel.onRequestData(
  958. browserChannel.forwardChannelRequest_,
  959. goog.net.BrowserChannel.LAST_ARRAY_ID_RESPONSE_PREFIX +
  960. '=<script>evil()\<\/script>&' +
  961. goog.net.BrowserChannel.OUTSTANDING_DATA_RESPONSE_PREFIX +
  962. '=<script>moreEvil()\<\/script>');
  963. assertEquals(goog.net.BrowserChannel.State.CLOSED, browserChannel.getState());
  964. }
  965. function testPathAbsolute() {
  966. connect(8, undefined, '/talkgadget');
  967. assertEquals(
  968. browserChannel.backChannelUri_.getDomain(), window.location.hostname);
  969. assertEquals(
  970. browserChannel.forwardChannelUri_.getDomain(), window.location.hostname);
  971. }
  972. function testPathRelative() {
  973. connect(8, undefined, 'talkgadget');
  974. assertEquals(
  975. browserChannel.backChannelUri_.getDomain(), window.location.hostname);
  976. assertEquals(
  977. browserChannel.forwardChannelUri_.getDomain(), window.location.hostname);
  978. }
  979. function testPathWithHost() {
  980. connect(8, undefined, 'https://example.com');
  981. assertEquals(browserChannel.backChannelUri_.getScheme(), 'https');
  982. assertEquals(browserChannel.backChannelUri_.getDomain(), 'example.com');
  983. assertEquals(browserChannel.forwardChannelUri_.getScheme(), 'https');
  984. assertEquals(browserChannel.forwardChannelUri_.getDomain(), 'example.com');
  985. }
  986. function testCreateXhrIo() {
  987. var xhr = browserChannel.createXhrIo(null);
  988. assertFalse(xhr.getWithCredentials());
  989. assertThrows(
  990. 'Error connection to different host without CORS',
  991. goog.bind(browserChannel.createXhrIo, browserChannel, 'some_host'));
  992. browserChannel.setSupportsCrossDomainXhrs(true);
  993. xhr = browserChannel.createXhrIo(null);
  994. assertTrue(xhr.getWithCredentials());
  995. xhr = browserChannel.createXhrIo('some_host');
  996. assertTrue(xhr.getWithCredentials());
  997. }
  998. function testSetParser() {
  999. var recordUnsafeParse = goog.testing.recordFunction(goog.json.unsafeParse);
  1000. var parser = {};
  1001. parser.parse = recordUnsafeParse;
  1002. browserChannel.setParser(parser);
  1003. connect();
  1004. assertEquals(3, recordUnsafeParse.getCallCount());
  1005. var call3 = recordUnsafeParse.popLastCall();
  1006. var call2 = recordUnsafeParse.popLastCall();
  1007. var call1 = recordUnsafeParse.popLastCall();
  1008. assertEquals(1, call1.getArguments().length);
  1009. assertEquals('["b"]', call1.getArgument(0));
  1010. assertEquals(1, call2.getArguments().length);
  1011. assertEquals('[[0,["c","1234567890ABCDEF",null]]]', call2.getArgument(0));
  1012. assertEquals(1, call3.getArguments().length);
  1013. assertEquals('[[1,["foo"]]]', call3.getArgument(0));
  1014. }
  1015. function testAsyncTest() {
  1016. browserChannel.asyncTest_ = true;
  1017. browserChannel.connect('/test', '/bind');
  1018. mockClock.tick(0);
  1019. // We first establish the channel, assuming it is buffered.
  1020. assertNotNull(browserChannel.forwardChannelRequest_);
  1021. assertNull(browserChannel.connectionTest_);
  1022. assertTrue(browserChannel.isBuffered());
  1023. // Since we're assuming the channel is buferred, the "Close Immediately" flag
  1024. // should be set.
  1025. completeForwardChannel();
  1026. assertEquals(
  1027. '1', browserChannel.backChannelRequest_.requestUri_.queryData_.get('CI'));
  1028. mockClock.tick(100);
  1029. // Now, we perform the test which reveals the channel is not buffered.
  1030. assertNotNull(browserChannel.connectionTest_);
  1031. completeForwardTestConnection();
  1032. completeBackTestConnection();
  1033. assertFalse(browserChannel.isBuffered());
  1034. // From now on, the "Close Immediately" flag should not be set.
  1035. completeBackChannel();
  1036. assertEquals(
  1037. '0', browserChannel.backChannelRequest_.requestUri_.queryData_.get('CI'));
  1038. }