123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932 |
- // 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.module.ModuleManagerTest');
- goog.setTestOnly('goog.module.ModuleManagerTest');
- goog.require('goog.array');
- goog.require('goog.functions');
- goog.require('goog.module.BaseModule');
- goog.require('goog.module.ModuleManager');
- goog.require('goog.testing');
- goog.require('goog.testing.MockClock');
- goog.require('goog.testing.jsunit');
- goog.require('goog.testing.recordFunction');
- var clock;
- var requestCount = 0;
- function tearDown() {
- clock.dispose();
- }
- function setUp() {
- clock = new goog.testing.MockClock(true);
- requestCount = 0;
- }
- function getModuleManager(infoMap) {
- var mm = new goog.module.ModuleManager();
- mm.setAllModuleInfo(infoMap);
- mm.isModuleLoaded = function(id) {
- return this.getModuleInfo(id).isLoaded();
- };
- return mm;
- }
- function createSuccessfulBatchLoader(moduleMgr) {
- return {
- loadModules: function(
- ids, moduleInfoMap, opt_successFn, opt_errFn, opt_timeoutFn) {
- requestCount++;
- setTimeout(goog.bind(this.onLoad, this, ids.concat(), 0), 5);
- },
- onLoad: function(ids, idxLoaded) {
- moduleMgr.beforeLoadModuleCode(ids[idxLoaded]);
- moduleMgr.setLoaded(ids[idxLoaded]);
- moduleMgr.afterLoadModuleCode(ids[idxLoaded]);
- var idx = idxLoaded + 1;
- if (idx < ids.length) {
- setTimeout(goog.bind(this.onLoad, this, ids, idx), 2);
- }
- }
- };
- }
- function createSuccessfulNonBatchLoader(moduleMgr) {
- return {
- loadModules: function(
- ids, moduleInfoMap, opt_successFn, opt_errFn, opt_timeoutFn) {
- requestCount++;
- setTimeout(function() {
- moduleMgr.beforeLoadModuleCode(ids[0]);
- moduleMgr.setLoaded(ids[0]);
- moduleMgr.afterLoadModuleCode(ids[0]);
- if (opt_successFn) {
- opt_successFn();
- }
- }, 5);
- }
- };
- }
- function createUnsuccessfulLoader(moduleMgr, status) {
- return {
- loadModules: function(
- ids, moduleInfoMap, opt_successFn, opt_errFn, opt_timeoutFn) {
- moduleMgr.beforeLoadModuleCode(ids[0]);
- setTimeout(function() { opt_errFn(status); }, 5);
- }
- };
- }
- function createUnsuccessfulBatchLoader(moduleMgr, status) {
- return {
- loadModules: function(
- ids, moduleInfoMap, opt_successFn, opt_errFn, opt_timeoutFn) {
- setTimeout(function() { opt_errFn(status); }, 5);
- }
- };
- }
- function createTimeoutLoader(moduleMgr, status) {
- return {
- loadModules: function(
- ids, moduleInfoMap, opt_successFn, opt_errFn, opt_timeoutFn) {
- setTimeout(function() { opt_timeoutFn(status); }, 5);
- }
- };
- }
- /**
- * Tests loading a module under different conditions i.e. unloaded
- * module, already loaded module, module loaded through user initiated
- * actions, synchronous callback for a module that has been already
- * loaded. Test both batch and non-batch loaders.
- */
- function testExecOnLoad() {
- var mm = getModuleManager({'a': [], 'b': [], 'c': []});
- mm.setLoader(createSuccessfulNonBatchLoader(mm));
- execOnLoad_(mm);
- mm = getModuleManager({'a': [], 'b': [], 'c': []});
- mm.setLoader(createSuccessfulBatchLoader(mm));
- mm.setBatchModeEnabled(true);
- execOnLoad_(mm);
- }
- /**
- * Tests execOnLoad with the specified module manager.
- * @param {goog.module.ModuleManager} mm The module manager.
- */
- function execOnLoad_(mm) {
- // When module is unloaded, execOnLoad is async.
- var execCalled1 = false;
- mm.execOnLoad('a', function() { execCalled1 = true; });
- assertFalse('module "a" should not be loaded', mm.isModuleLoaded('a'));
- assertTrue('module "a" should be loading', mm.isModuleLoading('a'));
- assertFalse('execCalled1 should not be set yet', execCalled1);
- assertTrue('ModuleManager should be active', mm.isActive());
- assertFalse('ModuleManager should not be user active', mm.isUserActive());
- clock.tick(5);
- assertTrue('module "a" should be loaded', mm.isModuleLoaded('a'));
- assertFalse('module "a" should not be loading', mm.isModuleLoading('a'));
- assertTrue('execCalled1 should be set', execCalled1);
- assertFalse('ModuleManager should not be active', mm.isActive());
- assertFalse('ModuleManager should not be user active', mm.isUserActive());
- // When module is already loaded, execOnLoad is still async unless
- // specified otherwise.
- var execCalled2 = false;
- mm.execOnLoad('a', function() { execCalled2 = true; });
- assertTrue('module "a" should be loaded', mm.isModuleLoaded('a'));
- assertFalse('module "a" should not be loading', mm.isModuleLoading('a'));
- assertFalse('execCalled2 should not be set yet', execCalled2);
- clock.tick(5);
- assertTrue('execCalled2 should be set', execCalled2);
- // When module is unloaded, execOnLoad is async (user active).
- var execCalled5 = false;
- mm.execOnLoad('c', function() { execCalled5 = true; }, null, null, true);
- assertFalse('module "c" should not be loaded', mm.isModuleLoaded('c'));
- assertTrue('module "c" should be loading', mm.isModuleLoading('c'));
- assertFalse('execCalled1 should not be set yet', execCalled5);
- assertTrue('ModuleManager should be active', mm.isActive());
- assertTrue('ModuleManager should be user active', mm.isUserActive());
- clock.tick(5);
- assertTrue('module "c" should be loaded', mm.isModuleLoaded('c'));
- assertFalse('module "c" should not be loading', mm.isModuleLoading('c'));
- assertTrue('execCalled1 should be set', execCalled5);
- assertFalse('ModuleManager should not be active', mm.isActive());
- assertFalse('ModuleManager should not be user active', mm.isUserActive());
- // When module is already loaded, execOnLoad is still synchronous when
- // so specified
- var execCalled6 = false;
- mm.execOnLoad('c', function() {
- execCalled6 = true;
- }, undefined, undefined, undefined, true);
- assertTrue('module "c" should be loaded', mm.isModuleLoaded('c'));
- assertFalse('module "c" should not be loading', mm.isModuleLoading('c'));
- assertTrue('execCalled6 should be set', execCalled6);
- clock.tick(5);
- assertTrue('execCalled6 should still be set', execCalled6);
- }
- /**
- * Test aborting the callback called on module load.
- */
- function testExecOnLoadAbort() {
- var mm = getModuleManager({'a': [], 'b': [], 'c': []});
- mm.setLoader(createSuccessfulNonBatchLoader(mm));
- // When module is unloaded and abort is called, module still gets
- // loaded, but callback is cancelled.
- var execCalled1 = false;
- var callback1 = mm.execOnLoad('b', function() { execCalled1 = true; });
- callback1.abort();
- clock.tick(5);
- assertTrue('module "b" should be loaded', mm.isModuleLoaded('b'));
- assertFalse('execCalled3 should not be set', execCalled1);
- // When module is already loaded, execOnLoad is still async, so calling
- // abort should still cancel the callback.
- var execCalled2 = false;
- var callback2 = mm.execOnLoad('a', function() { execCalled2 = true; });
- callback2.abort();
- clock.tick(5);
- assertFalse('execCalled2 should not be set', execCalled2);
- }
- /**
- * Test preloading modules and ensure that the before load, after load
- * and set load called are called only once per module.
- */
- function testExecOnLoadWhilePreloadingAndViceVersa() {
- var mm = getModuleManager({'c': [], 'd': []});
- mm.setLoader(createSuccessfulNonBatchLoader(mm));
- execOnLoadWhilePreloadingAndViceVersa_(mm);
- mm = getModuleManager({'c': [], 'd': []});
- mm.setLoader(createSuccessfulBatchLoader(mm));
- mm.setBatchModeEnabled(true);
- execOnLoadWhilePreloadingAndViceVersa_(mm);
- }
- /**
- * Perform tests with the specified module manager.
- * @param {goog.module.ModuleManager} mm The module manager.
- */
- function execOnLoadWhilePreloadingAndViceVersa_(mm) {
- var mm = getModuleManager({'c': [], 'd': []});
- mm.setLoader(createSuccessfulNonBatchLoader(mm));
- var origSetLoaded = mm.setLoaded;
- var calls = [0, 0, 0];
- mm.beforeLoadModuleCode = function(id) { calls[0]++; };
- mm.setLoaded = function(id) {
- calls[1]++;
- origSetLoaded.call(mm, id);
- };
- mm.afterLoadModuleCode = function(id) { calls[2]++; };
- mm.preloadModule('c', 2);
- assertFalse('module "c" should not be loading yet', mm.isModuleLoading('c'));
- clock.tick(2);
- assertTrue('module "c" should now be loading', mm.isModuleLoading('c'));
- mm.execOnLoad('c', function() {});
- assertTrue('module "c" should still be loading', mm.isModuleLoading('c'));
- clock.tick(5);
- assertFalse('module "c" should be done loading', mm.isModuleLoading('c'));
- assertEquals('beforeLoad should only be called once for "c"', 1, calls[0]);
- assertEquals('setLoaded should only be called once for "c"', 1, calls[1]);
- assertEquals('afterLoad should only be called once for "c"', 1, calls[2]);
- mm.execOnLoad('d', function() {});
- assertTrue('module "d" should now be loading', mm.isModuleLoading('d'));
- mm.preloadModule('d', 2);
- clock.tick(5);
- assertFalse('module "d" should be done loading', mm.isModuleLoading('d'));
- assertTrue('module "d" should now be loaded', mm.isModuleLoaded('d'));
- assertEquals('beforeLoad should only be called once for "d"', 2, calls[0]);
- assertEquals('setLoaded should only be called once for "d"', 2, calls[1]);
- assertEquals('afterLoad should only be called once for "d"', 2, calls[2]);
- }
- /**
- * Tests that multiple callbacks on the same module don't cause
- * confusion about the active state after the module is finally loaded.
- */
- function testUserInitiatedExecOnLoadEventuallyLeavesManagerIdle() {
- var mm = getModuleManager({'c': [], 'd': []});
- mm.setLoader(createSuccessfulNonBatchLoader(mm));
- var calledBack1 = false;
- var calledBack2 = false;
- mm.execOnLoad(
- 'c', function() { calledBack1 = true; }, undefined, undefined, true);
- mm.execOnLoad(
- 'c', function() { calledBack2 = true; }, undefined, undefined, true);
- mm.load('c');
- assertTrue(
- 'Manager should be active while waiting for load', mm.isUserActive());
- clock.tick(5);
- assertTrue('First callback should be called', calledBack1);
- assertTrue('Second callback should be called', calledBack2);
- assertFalse(
- 'Manager should be inactive after loading is complete',
- mm.isUserActive());
- }
- /**
- * Tests loading a module by requesting a Deferred object.
- */
- function testLoad() {
- var mm = getModuleManager({'a': [], 'b': [], 'c': []});
- mm.setLoader(createSuccessfulNonBatchLoader(mm));
- var calledBack = false;
- var error = null;
- var d = mm.load('a');
- d.addCallback(function(ctx) { calledBack = true; });
- d.addErrback(function(err) { error = err; });
- assertFalse(calledBack);
- assertNull(error);
- assertFalse(mm.isUserActive());
- clock.tick(5);
- assertTrue(calledBack);
- assertNull(error);
- }
- /**
- * Tests loading 2 modules asserting that the loads happen in parallel
- * in one unit of time.
- */
- function testLoad_concurrent() {
- var mm = getModuleManager({'a': [], 'b': [], 'c': []});
- mm.setConcurrentLoadingEnabled(true);
- mm.setLoader(createSuccessfulNonBatchLoader(mm));
- var calledBack = false;
- var error = null;
- mm.load('a');
- mm.load('b');
- assertEquals(2, requestCount);
- // Only time for one serialized download.
- clock.tick(5);
- assertTrue(mm.getModuleInfo('a').isLoaded());
- assertTrue(mm.getModuleInfo('b').isLoaded());
- }
- function testLoad_concurrentSecondIsDepOfFist() {
- var mm = getModuleManager({'a': [], 'b': [], 'c': []});
- mm.setBatchModeEnabled(true);
- mm.setConcurrentLoadingEnabled(true);
- mm.setLoader(createSuccessfulBatchLoader(mm));
- var calledBack = false;
- var error = null;
- mm.loadMultiple(['a', 'b']);
- mm.load('b');
- assertEquals('No 2nd request expected', 1, requestCount);
- // Only time for one serialized download.
- clock.tick(5);
- clock.tick(2); // Makes second module come in from batch requst.
- assertTrue(mm.getModuleInfo('a').isLoaded());
- assertTrue(mm.getModuleInfo('b').isLoaded());
- }
- function testLoad_nonConcurrent() {
- var mm = getModuleManager({'a': [], 'b': [], 'c': []});
- mm.setLoader(createSuccessfulNonBatchLoader(mm));
- var calledBack = false;
- var error = null;
- mm.load('a');
- mm.load('b');
- assertEquals(1, requestCount);
- // Only time for one serialized download.
- clock.tick(5);
- assertTrue(mm.getModuleInfo('a').isLoaded());
- assertFalse(mm.getModuleInfo('b').isLoaded());
- }
- function testLoadUnknown() {
- var mm = getModuleManager({'a': [], 'b': [], 'c': []});
- mm.setLoader(createSuccessfulNonBatchLoader(mm));
- var e = assertThrows(function() { mm.load('DoesNotExist'); });
- assertEquals('Unknown module: DoesNotExist', e.message);
- }
- /**
- * Tests loading multiple modules by requesting a Deferred object.
- */
- function testLoadMultiple() {
- var mm = getModuleManager({'a': [], 'b': [], 'c': []});
- mm.setBatchModeEnabled(true);
- mm.setLoader(createSuccessfulBatchLoader(mm));
- var calledBack = false;
- var error = null;
- var calledBack2 = false;
- var error2 = null;
- var dMap = mm.loadMultiple(['a', 'b']);
- dMap['a'].addCallback(function(ctx) { calledBack = true; });
- dMap['a'].addErrback(function(err) { error = err; });
- dMap['b'].addCallback(function(ctx) { calledBack2 = true; });
- dMap['b'].addErrback(function(err) { error2 = err; });
- assertFalse(calledBack);
- assertFalse(calledBack2);
- clock.tick(5);
- assertTrue(calledBack);
- assertFalse(calledBack2);
- assertTrue('module "a" should be loaded', mm.isModuleLoaded('a'));
- assertFalse('module "b" should not be loaded', mm.isModuleLoaded('b'));
- assertFalse('module "c" should not be loaded', mm.isModuleLoaded('c'));
- clock.tick(2);
- assertTrue(calledBack);
- assertTrue(calledBack2);
- assertTrue('module "a" should be loaded', mm.isModuleLoaded('a'));
- assertTrue('module "b" should be loaded', mm.isModuleLoaded('b'));
- assertFalse('module "c" should not be loaded', mm.isModuleLoaded('c'));
- assertNull(error);
- assertNull(error2);
- }
- /**
- * Tests loading multiple modules with deps by requesting a Deferred object.
- */
- function testLoadMultipleWithDeps() {
- var mm = getModuleManager({'a': [], 'b': ['c'], 'c': []});
- mm.setBatchModeEnabled(true);
- mm.setLoader(createSuccessfulBatchLoader(mm));
- var calledBack = false;
- var error = null;
- var calledBack2 = false;
- var error2 = null;
- var dMap = mm.loadMultiple(['a', 'b']);
- dMap['a'].addCallback(function(ctx) { calledBack = true; });
- dMap['a'].addErrback(function(err) { error = err; });
- dMap['b'].addCallback(function(ctx) { calledBack2 = true; });
- dMap['b'].addErrback(function(err) { error2 = err; });
- assertFalse(calledBack);
- assertFalse(calledBack2);
- clock.tick(5);
- assertTrue(calledBack);
- assertFalse(calledBack2);
- assertTrue('module "a" should be loaded', mm.isModuleLoaded('a'));
- assertFalse('module "b" should not be loaded', mm.isModuleLoaded('b'));
- assertFalse('module "c" should not be loaded', mm.isModuleLoaded('c'));
- clock.tick(2);
- assertFalse(calledBack2);
- assertTrue('module "a" should be loaded', mm.isModuleLoaded('a'));
- assertFalse('module "b" should not be loaded', mm.isModuleLoaded('b'));
- assertTrue('module "c" should be loaded', mm.isModuleLoaded('c'));
- clock.tick(2);
- assertTrue(calledBack2);
- assertTrue('module "a" should be loaded', mm.isModuleLoaded('a'));
- assertTrue('module "b" should be loaded', mm.isModuleLoaded('b'));
- assertTrue('module "c" should be loaded', mm.isModuleLoaded('c'));
- assertNull(error);
- assertNull(error2);
- }
- /**
- * Tests loading multiple modules by requesting a Deferred object when
- * a server error occurs.
- */
- function testLoadMultipleWithErrors() {
- var mm = getModuleManager({'a': [], 'b': [], 'c': []});
- mm.setBatchModeEnabled(true);
- mm.setLoader(createUnsuccessfulLoader(mm, 500));
- var calledBack = false;
- var error = null;
- var calledBack2 = false;
- var error2 = null;
- var calledBack3 = false;
- var error3 = null;
- var dMap = mm.loadMultiple(['a', 'b', 'c']);
- dMap['a'].addCallback(function(ctx) { calledBack = true; });
- dMap['a'].addErrback(function(err) { error = err; });
- dMap['b'].addCallback(function(ctx) { calledBack2 = true; });
- dMap['b'].addErrback(function(err) { error2 = err; });
- dMap['c'].addCallback(function(ctx) { calledBack3 = true; });
- dMap['c'].addErrback(function(err) { error3 = err; });
- assertFalse(calledBack);
- assertFalse(calledBack2);
- assertFalse(calledBack3);
- clock.tick(4);
- // A module request is now underway using the unsuccessful loader.
- // We substitute a successful loader for future module load requests.
- mm.setLoader(createSuccessfulBatchLoader(mm));
- clock.tick(1);
- assertFalse(calledBack);
- assertFalse(calledBack2);
- assertFalse(calledBack3);
- assertFalse('module "a" should not be loaded', mm.isModuleLoaded('a'));
- assertFalse('module "b" should not be loaded', mm.isModuleLoaded('b'));
- assertFalse('module "c" should not be loaded', mm.isModuleLoaded('c'));
- // Retry should happen after a backoff
- clock.tick(5 + mm.getBackOff_());
- assertTrue(calledBack);
- assertFalse(calledBack2);
- assertFalse(calledBack3);
- assertTrue('module "a" should be loaded', mm.isModuleLoaded('a'));
- assertFalse('module "b" should not be loaded', mm.isModuleLoaded('b'));
- assertFalse('module "c" should not be loaded', mm.isModuleLoaded('c'));
- clock.tick(2);
- assertTrue(calledBack2);
- assertFalse(calledBack3);
- assertTrue('module "b" should be loaded', mm.isModuleLoaded('b'));
- assertFalse('module "c" should not be loaded', mm.isModuleLoaded('c'));
- clock.tick(2);
- assertTrue(calledBack3);
- assertTrue('module "c" should be loaded', mm.isModuleLoaded('c'));
- assertNull(error);
- assertNull(error2);
- assertNull(error3);
- }
- /**
- * Tests loading multiple modules by requesting a Deferred object when
- * consecutive server error occur and the loader falls back to serial
- * loads.
- */
- function testLoadMultipleWithErrorsFallbackOnSerial() {
- var mm = getModuleManager({'a': [], 'b': [], 'c': []});
- mm.setBatchModeEnabled(true);
- mm.setLoader(createUnsuccessfulLoader(mm, 500));
- var calledBack = false;
- var error = null;
- var calledBack2 = false;
- var error2 = null;
- var calledBack3 = false;
- var error3 = null;
- var dMap = mm.loadMultiple(['a', 'b', 'c']);
- dMap['a'].addCallback(function(ctx) { calledBack = true; });
- dMap['a'].addErrback(function(err) { error = err; });
- dMap['b'].addCallback(function(ctx) { calledBack2 = true; });
- dMap['b'].addErrback(function(err) { error2 = err; });
- dMap['c'].addCallback(function(ctx) { calledBack3 = true; });
- dMap['c'].addErrback(function(err) { error3 = err; });
- assertFalse(calledBack);
- assertFalse(calledBack2);
- assertFalse(calledBack3);
- clock.tick(5);
- assertFalse(calledBack);
- assertFalse(calledBack2);
- assertFalse(calledBack3);
- assertFalse('module "a" should not be loaded', mm.isModuleLoaded('a'));
- assertFalse('module "b" should not be loaded', mm.isModuleLoaded('b'));
- assertFalse('module "c" should not be loaded', mm.isModuleLoaded('c'));
- // Retry should happen and fail after a backoff
- clock.tick(5 + mm.getBackOff_());
- assertFalse(calledBack);
- assertFalse(calledBack2);
- assertFalse(calledBack3);
- assertFalse('module "a" should not be loaded', mm.isModuleLoaded('a'));
- assertFalse('module "b" should not be loaded', mm.isModuleLoaded('b'));
- assertFalse('module "c" should not be loaded', mm.isModuleLoaded('c'));
- // A second retry should happen after a backoff
- clock.tick(4 + mm.getBackOff_());
- // The second retry is now underway using the unsuccessful loader.
- // We substitute a successful loader for future module load requests.
- mm.setLoader(createSuccessfulBatchLoader(mm));
- clock.tick(1);
- // A second retry should fail now
- assertFalse(calledBack);
- assertFalse(calledBack2);
- assertFalse(calledBack3);
- assertFalse('module "a" should not be loaded', mm.isModuleLoaded('a'));
- assertFalse('module "b" should not be loaded', mm.isModuleLoaded('b'));
- assertFalse('module "c" should not be loaded', mm.isModuleLoaded('c'));
- // Each module should be loaded individually now, each taking 5 ticks
- clock.tick(5);
- assertTrue(calledBack);
- assertFalse(calledBack2);
- assertFalse(calledBack3);
- assertTrue('module "a" should be loaded', mm.isModuleLoaded('a'));
- assertFalse('module "b" should not be loaded', mm.isModuleLoaded('b'));
- assertFalse('module "c" should not be loaded', mm.isModuleLoaded('c'));
- clock.tick(5);
- assertTrue(calledBack2);
- assertFalse(calledBack3);
- assertTrue('module "b" should be loaded', mm.isModuleLoaded('b'));
- assertFalse('module "c" should not be loaded', mm.isModuleLoaded('c'));
- clock.tick(5);
- assertTrue(calledBack3);
- assertTrue('module "c" should be loaded', mm.isModuleLoaded('c'));
- assertNull(error);
- assertNull(error2);
- assertNull(error3);
- }
- /**
- * Tests loading a module by user action by requesting a Deferred object.
- */
- function testLoadForUser() {
- var mm = getModuleManager({'a': [], 'b': [], 'c': []});
- mm.setLoader(createSuccessfulNonBatchLoader(mm));
- var calledBack = false;
- var error = null;
- var d = mm.load('a', true);
- d.addCallback(function(ctx) { calledBack = true; });
- d.addErrback(function(err) { error = err; });
- assertFalse(calledBack);
- assertNull(error);
- assertTrue(mm.isUserActive());
- clock.tick(5);
- assertTrue(calledBack);
- assertNull(error);
- }
- /**
- * Tests that preloading a module calls back the deferred object.
- */
- function testPreloadDeferredWhenNotLoaded() {
- var mm = getModuleManager({'a': []});
- mm.setLoader(createSuccessfulNonBatchLoader(mm));
- var calledBack = false;
- var d = mm.preloadModule('a');
- d.addCallback(function(ctx) { calledBack = true; });
- // First load should take five ticks.
- assertFalse('module "a" should not be loaded yet', calledBack);
- clock.tick(5);
- assertTrue('module "a" should be loaded', calledBack);
- }
- /**
- * Tests preloading an already loaded module.
- */
- function testPreloadDeferredWhenLoaded() {
- var mm = getModuleManager({'a': []});
- mm.setLoader(createSuccessfulNonBatchLoader(mm));
- var calledBack = false;
- mm.preloadModule('a');
- clock.tick(5);
- var d = mm.preloadModule('a');
- d.addCallback(function(ctx) { calledBack = true; });
- // Module is already loaded, should be called back after the setTimeout
- // in preloadModule.
- assertFalse('deferred for module "a" should not be called yet', calledBack);
- clock.tick(1);
- assertTrue('module "a" should be loaded', calledBack);
- }
- /**
- * Tests preloading a module that is currently loading.
- */
- function testPreloadDeferredWhenLoading() {
- var mm = getModuleManager({'a': []});
- mm.setLoader(createSuccessfulNonBatchLoader(mm));
- mm.preloadModule('a');
- clock.tick(1);
- // 'b' is in the middle of loading, should get called back when it's done.
- var calledBack = false;
- var d = mm.preloadModule('a');
- d.addCallback(function(ctx) { calledBack = true; });
- assertFalse('module "a" should not be loaded yet', calledBack);
- clock.tick(4);
- assertTrue('module "a" should be loaded', calledBack);
- }
- /**
- * Tests that load doesn't trigger another load if a module is already
- * preloading.
- */
- function testLoadWhenPreloading() {
- var mm = getModuleManager({'a': [], 'b': [], 'c': []});
- mm.setLoader(createSuccessfulNonBatchLoader(mm));
- var origSetLoaded = mm.setLoaded;
- var calls = [0, 0, 0];
- mm.beforeLoadModuleCode = function(id) { calls[0]++; };
- mm.setLoaded = function(id) {
- calls[1]++;
- origSetLoaded.call(mm, id);
- };
- mm.afterLoadModuleCode = function(id) { calls[2]++; };
- var calledBack = false;
- var error = null;
- mm.preloadModule('c', 2);
- assertFalse('module "c" should not be loading yet', mm.isModuleLoading('c'));
- clock.tick(2);
- assertTrue('module "c" should now be loading', mm.isModuleLoading('c'));
- var d = mm.load('c');
- d.addCallback(function(ctx) { calledBack = true; });
- d.addErrback(function(err) { error = err; });
- assertTrue('module "c" should still be loading', mm.isModuleLoading('c'));
- clock.tick(5);
- assertFalse('module "c" should be done loading', mm.isModuleLoading('c'));
- assertEquals('beforeLoad should only be called once for "c"', 1, calls[0]);
- assertEquals('setLoaded should only be called once for "c"', 1, calls[1]);
- assertEquals('afterLoad should only be called once for "c"', 1, calls[2]);
- assertTrue(calledBack);
- assertNull(error);
- }
- /**
- * Tests that load doesn't trigger another load if a module is already
- * preloading.
- */
- function testLoadMultipleWhenPreloading() {
- var mm = getModuleManager({'a': [], 'b': ['d'], 'c': [], 'd': []});
- mm.setLoader(createSuccessfulBatchLoader(mm));
- mm.setBatchModeEnabled(true);
- var origSetLoaded = mm.setLoaded;
- var calls = {'a': [0, 0, 0], 'b': [0, 0, 0], 'c': [0, 0, 0], 'd': [0, 0, 0]};
- mm.beforeLoadModuleCode = function(id) { calls[id][0]++; };
- mm.setLoaded = function(id) {
- calls[id][1]++;
- origSetLoaded.call(mm, id);
- };
- mm.afterLoadModuleCode = function(id) { calls[id][2]++; };
- var calledBack = false;
- var error = null;
- var calledBack2 = false;
- var error2 = null;
- var calledBack3 = false;
- var error3 = null;
- mm.preloadModule('c', 2);
- mm.preloadModule('d', 3);
- assertFalse('module "c" should not be loading yet', mm.isModuleLoading('c'));
- assertFalse('module "d" should not be loading yet', mm.isModuleLoading('d'));
- clock.tick(2);
- assertTrue('module "c" should now be loading', mm.isModuleLoading('c'));
- clock.tick(1);
- assertTrue('module "d" should now be loading', mm.isModuleLoading('d'));
- var dMap = mm.loadMultiple(['a', 'b', 'c']);
- dMap['a'].addCallback(function(ctx) { calledBack = true; });
- dMap['a'].addErrback(function(err) { error = err; });
- dMap['b'].addCallback(function(ctx) { calledBack2 = true; });
- dMap['b'].addErrback(function(err) { error2 = err; });
- dMap['c'].addCallback(function(ctx) { calledBack3 = true; });
- dMap['c'].addErrback(function(err) { error3 = err; });
- assertTrue('module "a" should be loading', mm.isModuleLoading('a'));
- assertTrue('module "b" should be loading', mm.isModuleLoading('b'));
- assertTrue('module "c" should still be loading', mm.isModuleLoading('c'));
- clock.tick(4);
- assertTrue(calledBack3);
- assertFalse('module "c" should be done loading', mm.isModuleLoading('c'));
- assertTrue('module "d" should still be loading', mm.isModuleLoading('d'));
- clock.tick(5);
- assertFalse('module "d" should be done loading', mm.isModuleLoading('d'));
- assertFalse(calledBack);
- assertFalse(calledBack2);
- assertTrue('module "a" should still be loading', mm.isModuleLoading('a'));
- assertTrue('module "b" should still be loading', mm.isModuleLoading('b'));
- clock.tick(7);
- assertTrue(calledBack);
- assertTrue(calledBack2);
- assertFalse('module "a" should be done loading', mm.isModuleLoading('a'));
- assertFalse('module "b" should be done loading', mm.isModuleLoading('b'));
- assertEquals(
- 'beforeLoad should only be called once for "a"', 1, calls['a'][0]);
- assertEquals(
- 'setLoaded should only be called once for "a"', 1, calls['a'][1]);
- assertEquals(
- 'afterLoad should only be called once for "a"', 1, calls['a'][2]);
- assertEquals(
- 'beforeLoad should only be called once for "b"', 1, calls['b'][0]);
- assertEquals(
- 'setLoaded should only be called once for "b"', 1, calls['b'][1]);
- assertEquals(
- 'afterLoad should only be called once for "b"', 1, calls['b'][2]);
- assertEquals(
- 'beforeLoad should only be called once for "c"', 1, calls['c'][0]);
- assertEquals(
- 'setLoaded should only be called once for "c"', 1, calls['c'][1]);
- assertEquals(
- 'afterLoad should only be called once for "c"', 1, calls['c'][2]);
- assertEquals(
- 'beforeLoad should only be called once for "d"', 1, calls['d'][0]);
- assertEquals(
- 'setLoaded should only be called once for "d"', 1, calls['d'][1]);
- assertEquals(
- 'afterLoad should only be called once for "d"', 1, calls['d'][2]);
- assertNull(error);
- assertNull(error2);
- assertNull(error3);
- }
- /**
- * Tests that the deferred is still called when loadMultiple loads modules
- * that are already preloading.
- */
- function testLoadMultipleWhenPreloadingSameModules() {
- var mm = getModuleManager({'a': [], 'b': ['d'], 'c': [], 'd': []});
- mm.setLoader(createSuccessfulBatchLoader(mm));
- mm.setBatchModeEnabled(true);
- var origSetLoaded = mm.setLoaded;
- var calls = {'c': [0, 0, 0], 'd': [0, 0, 0]};
- mm.beforeLoadModuleCode = function(id) { calls[id][0]++; };
- mm.setLoaded = function(id) {
- calls[id][1]++;
- origSetLoaded.call(mm, id);
- };
- mm.afterLoadModuleCode = function(id) { calls[id][2]++; };
- var calledBack = false;
- var error = null;
- var calledBack2 = false;
- var error2 = null;
- mm.preloadModule('c', 2);
- mm.preloadModule('d', 3);
- assertFalse('module "c" should not be loading yet', mm.isModuleLoading('c'));
- assertFalse('module "d" should not be loading yet', mm.isModuleLoading('d'));
- clock.tick(2);
- assertTrue('module "c" should now be loading', mm.isModuleLoading('c'));
- clock.tick(1);
- assertTrue('module "d" should now be loading', mm.isModuleLoading('d'));
- var dMap = mm.loadMultiple(['c', 'd']);
- dMap['c'].addCallback(function(ctx) { calledBack = true; });
- dMap['c'].addErrback(function(err) { error = err; });
- dMap['d'].addCallback(function(ctx) { calledBack2 = true; });
- dMap['d'].addErrback(function(err) { error2 = err; });
- assertTrue('module "c" should still be loading', mm.isModuleLoading('c'));
- clock.tick(4);
- assertFalse('module "c" should be done loading', mm.isModuleLoading('c'));
- assertTrue('module "d" should still be loading', mm.isModuleLoading('d'));
- clock.tick(5);
- assertFalse('module "d" should be done loading', mm.isModuleLoading('d'));
- assertTrue(calledBack);
- assertTrue(calledBack2);
- assertEquals(
- 'beforeLoad should only be called once for "c"', 1, calls['c'][0]);
- assertEquals(
- 'setLoaded should only be called once for "c"', 1, calls['c'][1]);
- assertEquals(
- 'afterLoad should only be called once for "c"', 1, calls['c'][2]);
- assertEquals(
- 'beforeLoad should only be called once for "d"', 1, calls['d'][0]);
- assertEquals(
- 'setLoaded should only be called once for "d"', 1, calls['d'][1]);
- assertEquals(
- 'afterLoad should only be called once for "d"', 1, calls['d'][2]);
- assertNull(error);
- assertNull(error2);
- }
- /**
- * Tests loading a module via load when the module is already
- * loaded. The deferred's callback should be called immediately.
- */
- function testLoadWhenLoaded() {
- var mm = getModuleManager({'a': [], 'b': [], 'c': []});
- mm.setLoader(createSuccessfulNonBatchLoader(mm));
- var calledBack = false;
- var error = null;
- mm.preloadModule('b', 2);
- clock.tick(10);
- assertFalse('module "b" should be done loading', mm.isModuleLoading('b'));
- var d = mm.load('b');
- d.addCallback(function(ctx) { calledBack = true; });
- d.addErrback(function(err) { error = err; });
- assertTrue(calledBack);
- assertNull(error);
- }
- /**
- * Tests that the deferred's errbacks are called if the module fails to load.
- */
- function testLoadWithFailingModule() {
- var mm = getModuleManager({'a': [], 'b': [], 'c': []});
- mm.setLoader(createUnsuccessfulLoader(mm, 401));
- mm.registerCallback(
- goog.module.ModuleManager.CallbackType.ERROR,
- function(callbackType, id, cause) {
- assertEquals(
- 'Failure cause was not as expected',
- goog.module.ModuleManager.FailureType.UNAUTHORIZED, cause);
- firedLoadFailed = true;
- });
- var calledBack = false;
- var error = null;
- var d = mm.load('a');
- d.addCallback(function(ctx) { calledBack = true; });
- d.addErrback(function(err) { error = err; });
- assertFalse(calledBack);
- assertNull(error);
- clock.tick(500);
- assertFalse(calledBack);
- // NOTE: Deferred always calls errbacks with an Error object. For now the
- // module manager just passes the FailureType which gets set as the Error
- // object's message.
- assertEquals(
- 'Failure cause was not as expected',
- goog.module.ModuleManager.FailureType.UNAUTHORIZED,
- Number(error.message));
- }
- /**
- * Tests that the deferred's errbacks are called if a module fails to load.
- */
- function testLoadMultipleWithFailingModule() {
- var mm = getModuleManager({'a': [], 'b': [], 'c': []});
- mm.setLoader(createUnsuccessfulLoader(mm, 401));
- mm.setBatchModeEnabled(true);
- mm.registerCallback(
- goog.module.ModuleManager.CallbackType.ERROR,
- function(callbackType, id, cause) {
- assertEquals(
- 'Failure cause was not as expected',
- goog.module.ModuleManager.FailureType.UNAUTHORIZED, cause);
- });
- var calledBack11 = false;
- var error11 = null;
- var calledBack12 = false;
- var error12 = null;
- var calledBack21 = false;
- var error21 = null;
- var calledBack22 = false;
- var error22 = null;
- var dMap = mm.loadMultiple(['a', 'b']);
- dMap['a'].addCallback(function(ctx) { calledBack11 = true; });
- dMap['a'].addErrback(function(err) { error11 = err; });
- dMap['b'].addCallback(function(ctx) { calledBack12 = true; });
- dMap['b'].addErrback(function(err) { error12 = err; });
- var dMap2 = mm.loadMultiple(['b', 'c']);
- dMap2['b'].addCallback(function(ctx) { calledBack21 = true; });
- dMap2['b'].addErrback(function(err) { error21 = err; });
- dMap2['c'].addCallback(function(ctx) { calledBack22 = true; });
- dMap2['c'].addErrback(function(err) { error22 = err; });
- assertFalse(calledBack11);
- assertFalse(calledBack12);
- assertFalse(calledBack21);
- assertFalse(calledBack22);
- assertNull(error11);
- assertNull(error12);
- assertNull(error21);
- assertNull(error22);
- clock.tick(5);
- assertFalse(calledBack11);
- assertFalse(calledBack12);
- assertFalse(calledBack21);
- assertFalse(calledBack22);
- // NOTE: Deferred always calls errbacks with an Error object. For now the
- // module manager just passes the FailureType which gets set as the Error
- // object's message.
- assertEquals(
- 'Failure cause was not as expected',
- goog.module.ModuleManager.FailureType.UNAUTHORIZED,
- Number(error11.message));
- assertEquals(
- 'Failure cause was not as expected',
- goog.module.ModuleManager.FailureType.UNAUTHORIZED,
- Number(error12.message));
- // The first deferred of the second load should be called since it asks for
- // one of the failed modules.
- assertEquals(
- 'Failure cause was not as expected',
- goog.module.ModuleManager.FailureType.UNAUTHORIZED,
- Number(error21.message));
- // The last deferred should be dropped so it is neither called back nor an
- // error.
- assertFalse(calledBack22);
- assertNull(error22);
- }
- /**
- * Tests that the right dependencies are cancelled on a loadMultiple failure.
- */
- function testLoadMultipleWithFailingModuleDependencies() {
- var mm =
- getModuleManager({'a': [], 'b': [], 'c': ['b'], 'd': ['c'], 'e': []});
- mm.setLoader(createUnsuccessfulLoader(mm, 401));
- mm.setBatchModeEnabled(true);
- var cancelledIds = [];
- mm.registerCallback(
- goog.module.ModuleManager.CallbackType.ERROR,
- function(callbackType, id, cause) {
- assertEquals(
- 'Failure cause was not as expected',
- goog.module.ModuleManager.FailureType.UNAUTHORIZED, cause);
- cancelledIds.push(id);
- });
- var calledBack11 = false;
- var error11 = null;
- var calledBack12 = false;
- var error12 = null;
- var calledBack21 = false;
- var error21 = null;
- var calledBack22 = false;
- var error22 = null;
- var calledBack23 = false;
- var error23 = null;
- var dMap = mm.loadMultiple(['a', 'b']);
- dMap['a'].addCallback(function(ctx) { calledBack11 = true; });
- dMap['a'].addErrback(function(err) { error11 = err; });
- dMap['b'].addCallback(function(ctx) { calledBack12 = true; });
- dMap['b'].addErrback(function(err) { error12 = err; });
- var dMap2 = mm.loadMultiple(['c', 'd', 'e']);
- dMap2['c'].addCallback(function(ctx) { calledBack21 = true; });
- dMap2['c'].addErrback(function(err) { error21 = err; });
- dMap2['d'].addCallback(function(ctx) { calledBack22 = true; });
- dMap2['d'].addErrback(function(err) { error22 = err; });
- dMap2['e'].addCallback(function(ctx) { calledBack23 = true; });
- dMap2['e'].addErrback(function(err) { error23 = err; });
- assertFalse(calledBack11);
- assertFalse(calledBack12);
- assertFalse(calledBack21);
- assertFalse(calledBack22);
- assertFalse(calledBack23);
- assertNull(error11);
- assertNull(error12);
- assertNull(error21);
- assertNull(error22);
- assertNull(error23);
- clock.tick(5);
- assertFalse(calledBack11);
- assertFalse(calledBack12);
- assertFalse(calledBack21);
- assertFalse(calledBack22);
- assertFalse(calledBack23);
- // NOTE: Deferred always calls errbacks with an Error object. For now the
- // module manager just passes the FailureType which gets set as the Error
- // object's message.
- assertEquals(
- 'Failure cause was not as expected',
- goog.module.ModuleManager.FailureType.UNAUTHORIZED,
- Number(error11.message));
- assertEquals(
- 'Failure cause was not as expected',
- goog.module.ModuleManager.FailureType.UNAUTHORIZED,
- Number(error12.message));
- // Check that among the failed modules, 'c' and 'd' are also cancelled
- // due to dependencies.
- assertTrue(goog.array.equals(['a', 'b', 'c', 'd'], cancelledIds.sort()));
- }
- /**
- * Tests that when loading multiple modules, the input array is not modified
- * when it has duplicates.
- */
- function testLoadMultipleWithDuplicates() {
- var mm = getModuleManager({'a': [], 'b': []});
- mm.setBatchModeEnabled(true);
- mm.setLoader(createSuccessfulBatchLoader(mm));
- var listWithDuplicates = ['a', 'a', 'b'];
- mm.loadMultiple(listWithDuplicates);
- assertArrayEquals(
- 'loadMultiple should not modify its input', ['a', 'a', 'b'],
- listWithDuplicates);
- }
- /**
- * Test loading dependencies transitively.
- */
- function testLoadingDepsInNonBatchMode1() {
- var mm =
- getModuleManager({'i': [], 'j': [], 'k': ['j'], 'l': ['i', 'j', 'k']});
- mm.setLoader(createSuccessfulNonBatchLoader(mm));
- mm.preloadModule('j');
- clock.tick(5);
- assertTrue('module "j" should be loaded', mm.isModuleLoaded('j'));
- assertFalse('module "i" should not be loaded (1)', mm.isModuleLoaded('i'));
- assertFalse('module "k" should not be loaded (1)', mm.isModuleLoaded('k'));
- assertFalse('module "l" should not be loaded (1)', mm.isModuleLoaded('l'));
- // When loading a module in non-batch mode, its dependencies should be
- // requested independently, and in dependency order.
- mm.preloadModule('l');
- clock.tick(5);
- assertTrue('module "i" should be loaded', mm.isModuleLoaded('i'));
- assertFalse('module "k" should not be loaded (2)', mm.isModuleLoaded('k'));
- assertFalse('module "l" should not be loaded (2)', mm.isModuleLoaded('l'));
- clock.tick(5);
- assertTrue('module "k" should be loaded', mm.isModuleLoaded('k'));
- assertFalse('module "l" should not be loaded (3)', mm.isModuleLoaded('l'));
- clock.tick(5);
- assertTrue('module "l" should be loaded', mm.isModuleLoaded('l'));
- }
- /**
- * Test loading dependencies transitively and in dependency order.
- */
- function testLoadingDepsInNonBatchMode2() {
- var mm = getModuleManager({
- 'h': [],
- 'i': ['h'],
- 'j': ['i'],
- 'k': ['j'],
- 'l': ['i', 'j', 'k'],
- 'm': ['l']
- });
- mm.setLoader(createSuccessfulNonBatchLoader(mm));
- // When loading a module in non-batch mode, its dependencies should be
- // requested independently, and in dependency order. The order in this
- // case should be h,i,j,k,l,m.
- mm.preloadModule('m');
- clock.tick(5);
- assertTrue('module "h" should be loaded', mm.isModuleLoaded('h'));
- assertFalse('module "i" should not be loaded (1)', mm.isModuleLoaded('i'));
- assertFalse('module "j" should not be loaded (1)', mm.isModuleLoaded('j'));
- assertFalse('module "k" should not be loaded (1)', mm.isModuleLoaded('k'));
- assertFalse('module "l" should not be loaded (1)', mm.isModuleLoaded('l'));
- assertFalse('module "m" should not be loaded (1)', mm.isModuleLoaded('m'));
- clock.tick(5);
- assertTrue('module "i" should be loaded', mm.isModuleLoaded('i'));
- assertFalse('module "j" should not be loaded (2)', mm.isModuleLoaded('j'));
- assertFalse('module "k" should not be loaded (2)', mm.isModuleLoaded('k'));
- assertFalse('module "l" should not be loaded (2)', mm.isModuleLoaded('l'));
- assertFalse('module "m" should not be loaded (2)', mm.isModuleLoaded('m'));
- clock.tick(5);
- assertTrue('module "j" should be loaded', mm.isModuleLoaded('j'));
- assertFalse('module "k" should not be loaded (3)', mm.isModuleLoaded('k'));
- assertFalse('module "l" should not be loaded (3)', mm.isModuleLoaded('l'));
- assertFalse('module "m" should not be loaded (3)', mm.isModuleLoaded('m'));
- clock.tick(5);
- assertTrue('module "k" should be loaded', mm.isModuleLoaded('k'));
- assertFalse('module "l" should not be loaded (4)', mm.isModuleLoaded('l'));
- assertFalse('module "m" should not be loaded (4)', mm.isModuleLoaded('m'));
- clock.tick(5);
- assertTrue('module "l" should be loaded', mm.isModuleLoaded('l'));
- assertFalse('module "m" should not be loaded (5)', mm.isModuleLoaded('m'));
- clock.tick(5);
- assertTrue('module "m" should be loaded', mm.isModuleLoaded('m'));
- }
- function testLoadingDepsInBatchMode() {
- var mm =
- getModuleManager({'e': [], 'f': [], 'g': ['f'], 'h': ['e', 'f', 'g']});
- mm.setLoader(createSuccessfulBatchLoader(mm));
- mm.setBatchModeEnabled(true);
- mm.preloadModule('f');
- clock.tick(5);
- assertTrue('module "f" should be loaded', mm.isModuleLoaded('f'));
- assertFalse('module "e" should not be loaded (1)', mm.isModuleLoaded('e'));
- assertFalse('module "g" should not be loaded (1)', mm.isModuleLoaded('g'));
- assertFalse('module "h" should not be loaded (1)', mm.isModuleLoaded('h'));
- // When loading a module in batch mode, its not-yet-loaded dependencies
- // should be requested at the same time, and in dependency order.
- mm.preloadModule('h');
- clock.tick(5);
- assertTrue('module "e" should be loaded', mm.isModuleLoaded('e'));
- assertFalse('module "g" should not be loaded (2)', mm.isModuleLoaded('g'));
- assertFalse('module "h" should not be loaded (2)', mm.isModuleLoaded('h'));
- clock.tick(2);
- assertTrue('module "g" should be loaded', mm.isModuleLoaded('g'));
- assertFalse('module "h" should not be loaded (3)', mm.isModuleLoaded('h'));
- clock.tick(2);
- assertTrue('module "h" should be loaded', mm.isModuleLoaded('h'));
- }
- /**
- * Test unauthorized errors while loading modules.
- */
- function testUnauthorizedLoading() {
- var mm = getModuleManager({'m': [], 'n': [], 'o': ['n']});
- mm.setLoader(createUnsuccessfulLoader(mm, 401));
- // Callback checks for an unauthorized error
- var firedLoadFailed = false;
- mm.registerCallback(
- goog.module.ModuleManager.CallbackType.ERROR,
- function(callbackType, id, cause) {
- assertEquals(
- 'Failure cause was not as expected',
- goog.module.ModuleManager.FailureType.UNAUTHORIZED, cause);
- firedLoadFailed = true;
- });
- mm.execOnLoad('o', function() {});
- assertTrue('module "o" should be loading', mm.isModuleLoading('o'));
- assertTrue('module "n" should be loading', mm.isModuleLoading('n'));
- clock.tick(5);
- assertTrue(
- 'should have called unauthorized module callback', firedLoadFailed);
- assertFalse('module "o" should not be loaded', mm.isModuleLoaded('o'));
- assertFalse('module "o" should not be loading', mm.isModuleLoading('o'));
- assertFalse('module "n" should not be loaded', mm.isModuleLoaded('n'));
- assertFalse('module "n" should not be loading', mm.isModuleLoading('n'));
- }
- /**
- * Test error loading modules which are retried.
- */
- function testErrorLoadingModule() {
- var mm = getModuleManager({'p': ['q'], 'q': [], 'r': ['q', 'p']});
- mm.setLoader(createUnsuccessfulLoader(mm, 500));
- mm.preloadModule('r');
- clock.tick(4);
- // A module request is now underway using the unsuccessful loader.
- // We substitute a successful loader for future module load requests.
- mm.setLoader(createSuccessfulNonBatchLoader(mm));
- clock.tick(1);
- assertFalse('module "q" should not be loaded (1)', mm.isModuleLoaded('q'));
- assertFalse('module "p" should not be loaded (1)', mm.isModuleLoaded('p'));
- assertFalse('module "r" should not be loaded (1)', mm.isModuleLoaded('r'));
- // Failed loads are automatically retried after a backOff.
- clock.tick(5 + mm.getBackOff_());
- assertTrue('module "q" should be loaded', mm.isModuleLoaded('q'));
- assertFalse('module "p" should not be loaded (2)', mm.isModuleLoaded('p'));
- assertFalse('module "r" should not be loaded (2)', mm.isModuleLoaded('r'));
- // A successful load decrements the backOff.
- clock.tick(5);
- assertTrue('module "p" should be loaded', mm.isModuleLoaded('p'));
- assertFalse('module "r" should not be loaded (3)', mm.isModuleLoaded('r'));
- clock.tick(5);
- assertTrue('module "r" should be loaded', mm.isModuleLoaded('r'));
- }
- /**
- * Tests error loading modules which are retried.
- */
- function testErrorLoadingModule_batchMode() {
- var mm = getModuleManager({'p': ['q'], 'q': [], 'r': ['q', 'p']});
- mm.setLoader(createUnsuccessfulBatchLoader(mm, 500));
- mm.setBatchModeEnabled(true);
- mm.preloadModule('r');
- clock.tick(4);
- // A module request is now underway using the unsuccessful loader.
- // We substitute a successful loader for future module load requests.
- mm.setLoader(createSuccessfulBatchLoader(mm));
- clock.tick(1);
- assertFalse('module "q" should not be loaded (1)', mm.isModuleLoaded('q'));
- assertFalse('module "p" should not be loaded (1)', mm.isModuleLoaded('p'));
- assertFalse('module "r" should not be loaded (1)', mm.isModuleLoaded('r'));
- // Failed loads are automatically retried after a backOff.
- clock.tick(5 + mm.getBackOff_());
- assertTrue('module "q" should be loaded', mm.isModuleLoaded('q'));
- clock.tick(2);
- assertTrue('module "p" should not be loaded (2)', mm.isModuleLoaded('p'));
- clock.tick(2);
- assertTrue('module "r" should not be loaded (2)', mm.isModuleLoaded('r'));
- }
- /**
- * Test consecutive errors in loading modules.
- */
- function testConsecutiveErrors() {
- var mm = getModuleManager({'s': []});
- mm.setLoader(createUnsuccessfulLoader(mm, 500));
- // Register an error callback for consecutive failures.
- var firedLoadFailed = false;
- mm.registerCallback(
- goog.module.ModuleManager.CallbackType.ERROR,
- function(callbackType, id, cause) {
- assertEquals(
- 'Failure cause was not as expected',
- goog.module.ModuleManager.FailureType.CONSECUTIVE_FAILURES, cause);
- firedLoadFailed = true;
- });
- mm.preloadModule('s');
- assertFalse('module "s" should not be loaded (0)', mm.isModuleLoaded('s'));
- // Fail twice.
- for (var i = 0; i < 2; i++) {
- clock.tick(5 + mm.getBackOff_());
- assertFalse('module "s" should not be loaded (1)', mm.isModuleLoaded('s'));
- assertFalse('should not fire failed callback (1)', firedLoadFailed);
- }
- // Fail a third time and check that the callback is fired.
- clock.tick(5 + mm.getBackOff_());
- assertFalse('module "s" should not be loaded (2)', mm.isModuleLoaded('s'));
- assertTrue('should have fired failed callback', firedLoadFailed);
- // Check that it doesn't attempt to load the module anymore after it has
- // failed.
- var triedLoad = false;
- mm.setLoader({
- loadModules: function(ids, moduleInfoMap, opt_successFn, opt_errFn) {
- triedLoad = true;
- }
- });
- // Also reset the failed callback flag and make sure it isn't called
- // again.
- firedLoadFailed = false;
- clock.tick(10 + mm.getBackOff_());
- assertFalse('module "s" should not be loaded (3)', mm.isModuleLoaded('s'));
- assertFalse('No more loads should have been tried', triedLoad);
- assertFalse(
- 'The load failed callback should be fired only once', firedLoadFailed);
- }
- /**
- * Test loading errors due to old code.
- */
- function testOldCodeGoneError() {
- var mm = getModuleManager({'s': []});
- mm.setLoader(createUnsuccessfulLoader(mm, 410));
- // Callback checks for an old code failure
- var firedLoadFailed = false;
- mm.registerCallback(
- goog.module.ModuleManager.CallbackType.ERROR,
- function(callbackType, id, cause) {
- assertEquals(
- 'Failure cause was not as expected',
- goog.module.ModuleManager.FailureType.OLD_CODE_GONE, cause);
- firedLoadFailed = true;
- });
- mm.preloadModule('s', 0);
- assertFalse('module "s" should not be loaded (0)', mm.isModuleLoaded('s'));
- clock.tick(5);
- assertFalse('module "s" should not be loaded (1)', mm.isModuleLoaded('s'));
- assertTrue('should have called old code gone callback', firedLoadFailed);
- }
- /**
- * Test timeout.
- */
- function testTimeout() {
- var mm = getModuleManager({'s': []});
- mm.setLoader(createTimeoutLoader(mm));
- // Callback checks for timeout
- var firedTimeout = false;
- mm.registerCallback(
- goog.module.ModuleManager.CallbackType.ERROR,
- function(callbackType, id, cause) {
- assertEquals(
- 'Failure cause was not as expected',
- goog.module.ModuleManager.FailureType.TIMEOUT, cause);
- firedTimeout = true;
- });
- mm.preloadModule('s', 0);
- assertFalse('module "s" should not be loaded (0)', mm.isModuleLoaded('s'));
- clock.tick(5);
- assertFalse('module "s" should not be loaded (1)', mm.isModuleLoaded('s'));
- assertTrue('should have called timeout callback', firedTimeout);
- }
- /**
- * Tests that an error during execOnLoad will trigger the error callback.
- */
- function testExecOnLoadError() {
- // Expect two callbacks, each of which will be called with callback type
- // ERROR, the right module id and failure type INIT_ERROR.
- var errorCallback1 = goog.testing.createFunctionMock('callback1');
- errorCallback1(
- goog.module.ModuleManager.CallbackType.ERROR, 'b',
- goog.module.ModuleManager.FailureType.INIT_ERROR);
- var errorCallback2 = goog.testing.createFunctionMock('callback2');
- errorCallback2(
- goog.module.ModuleManager.CallbackType.ERROR, 'b',
- goog.module.ModuleManager.FailureType.INIT_ERROR);
- errorCallback1.$replay();
- errorCallback2.$replay();
- var mm = new goog.module.ModuleManager();
- mm.setLoader(createSuccessfulNonBatchLoader(mm));
- // Register the first callback before setting the module info map.
- mm.registerCallback(
- goog.module.ModuleManager.CallbackType.ERROR, errorCallback1);
- mm.setAllModuleInfo({'a': [], 'b': [], 'c': []});
- // Register the second callback after setting the module info map.
- mm.registerCallback(
- goog.module.ModuleManager.CallbackType.ERROR, errorCallback2);
- var execOnLoadBCalled = false;
- mm.execOnLoad('b', function() {
- execOnLoadBCalled = true;
- throw new Error();
- });
- assertThrows(function() { clock.tick(5); });
- assertTrue(
- 'execOnLoad should have been called on module b.', execOnLoadBCalled);
- errorCallback1.$verify();
- errorCallback2.$verify();
- }
- /**
- * Tests that an error during execOnLoad will trigger the error callback.
- * Uses setAllModuleInfoString rather than setAllModuleInfo.
- */
- function testExecOnLoadErrorModuleInfoString() {
- // Expect a callback to be called with callback type ERROR, the right module
- // id and failure type INIT_ERROR.
- var errorCallback = goog.testing.createFunctionMock('callback');
- errorCallback(
- goog.module.ModuleManager.CallbackType.ERROR, 'b',
- goog.module.ModuleManager.FailureType.INIT_ERROR);
- errorCallback.$replay();
- var mm = new goog.module.ModuleManager();
- mm.setLoader(createSuccessfulNonBatchLoader(mm));
- // Register the first callback before setting the module info map.
- mm.registerCallback(
- goog.module.ModuleManager.CallbackType.ERROR, errorCallback);
- mm.setAllModuleInfoString('a/b/c');
- var execOnLoadBCalled = false;
- mm.execOnLoad('b', function() {
- execOnLoadBCalled = true;
- throw new Error();
- });
- assertThrows(function() { clock.tick(5); });
- assertTrue(
- 'execOnLoad should have been called on module b.', execOnLoadBCalled);
- errorCallback.$verify();
- }
- /**
- * Make sure ModuleInfo objects in moduleInfoMap_ get disposed.
- */
- function testDispose() {
- var mm = getModuleManager({'a': [], 'b': [], 'c': []});
- var moduleInfoA = mm.getModuleInfo('a');
- assertNotNull(moduleInfoA);
- var moduleInfoB = mm.getModuleInfo('b');
- assertNotNull(moduleInfoB);
- var moduleInfoC = mm.getModuleInfo('c');
- assertNotNull(moduleInfoC);
- mm.dispose();
- assertTrue(moduleInfoA.isDisposed());
- assertTrue(moduleInfoB.isDisposed());
- assertTrue(moduleInfoC.isDisposed());
- }
- function testDependencyOrderingWithSimpleDeps() {
- var mm = getModuleManager({
- 'a': ['b', 'c'],
- 'b': ['d'],
- 'c': ['e', 'f'],
- 'd': [],
- 'e': [],
- 'f': []
- });
- var ids = mm.getNotYetLoadedTransitiveDepIds_('a');
- assertDependencyOrder(ids, mm);
- assertArrayEquals(['d', 'e', 'f', 'b', 'c', 'a'], ids);
- }
- function testDependencyOrderingWithCommonDepsInDeps() {
- // Tests to make sure that if dependencies of the root are loaded before
- // their common dependencies.
- var mm = getModuleManager({'a': ['b', 'c'], 'b': ['d'], 'c': ['d'], 'd': []});
- var ids = mm.getNotYetLoadedTransitiveDepIds_('a');
- assertDependencyOrder(ids, mm);
- assertArrayEquals(['d', 'b', 'c', 'a'], ids);
- }
- function testDependencyOrderingWithCommonDepsInRoot1() {
- // Tests the case where a dependency of the root depends on another
- // dependency of the root. Regardless of ordering in the root's
- // deps.
- var mm = getModuleManager({'a': ['b', 'c'], 'b': ['c'], 'c': []});
- var ids = mm.getNotYetLoadedTransitiveDepIds_('a');
- assertDependencyOrder(ids, mm);
- assertArrayEquals(['c', 'b', 'a'], ids);
- }
- function testDependencyOrderingWithCommonDepsInRoot2() {
- // Tests the case where a dependency of the root depends on another
- // dependency of the root. Regardless of ordering in the root's
- // deps.
- var mm = getModuleManager({'a': ['b', 'c'], 'b': [], 'c': ['b']});
- var ids = mm.getNotYetLoadedTransitiveDepIds_('a');
- assertDependencyOrder(ids, mm);
- assertArrayEquals(['b', 'c', 'a'], ids);
- }
- function testDependencyOrderingWithGmailExample() {
- // Real dependency graph taken from gmail.
- var mm = getModuleManager({
- 's': ['dp', 'ml', 'md'],
- 'dp': ['a'],
- 'ml': ['ld', 'm'],
- 'ld': ['a'],
- 'm': ['ad', 'mh', 'n'],
- 'md': ['mh', 'ld'],
- 'a': [],
- 'mh': [],
- 'ad': [],
- 'n': []
- });
- mm.setLoaded('a');
- mm.setLoaded('m');
- mm.setLoaded('n');
- mm.setLoaded('ad');
- mm.setLoaded('mh');
- var ids = mm.getNotYetLoadedTransitiveDepIds_('s');
- assertDependencyOrder(ids, mm);
- assertArrayEquals(['ld', 'dp', 'ml', 'md', 's'], ids);
- }
- function assertDependencyOrder(list, mm) {
- var seen = {};
- for (var i = 0; i < list.length; i++) {
- var id = list[i];
- seen[id] = true;
- var deps = mm.getModuleInfo(id).getDependencies();
- for (var j = 0; j < deps.length; j++) {
- var dep = deps[j];
- assertTrue(
- 'Unresolved dependency [' + dep + '] for [' + id + '].',
- seen[dep] || mm.getModuleInfo(dep).isLoaded());
- }
- }
- }
- function testRegisterInitializationCallback() {
- var initCalled = 0;
- var mm = getModuleManager({'a': [], 'b': [], 'c': []});
- mm.setLoader(
- createSuccessfulNonBatchLoaderWithRegisterInitCallback(
- mm, function() { ++initCalled; }));
- execOnLoad_(mm);
- // execOnLoad_ loads modules a and c
- assertTrue(initCalled == 2);
- }
- function createSuccessfulNonBatchLoaderWithRegisterInitCallback(moduleMgr, fn) {
- return {
- loadModules: function(
- ids, moduleInfoMap, opt_successFn, opt_errFn, opt_timeoutFn) {
- moduleMgr.beforeLoadModuleCode(ids[0]);
- moduleMgr.registerInitializationCallback(fn);
- setTimeout(function() {
- moduleMgr.setLoaded(ids[0]);
- moduleMgr.afterLoadModuleCode(ids[0]);
- if (opt_successFn) {
- opt_successFn();
- }
- }, 5);
- }
- };
- }
- function testSetModuleConstructor() {
- var initCalled = 0;
- var mm = getModuleManager({'a': [], 'b': [], 'c': []});
- var info = {
- 'a': {ctor: AModule, count: 0},
- 'b': {ctor: BModule, count: 0},
- 'c': {ctor: CModule, count: 0}
- };
- function AModule() {
- ++info['a'].count;
- goog.module.BaseModule.call(this);
- }
- goog.inherits(AModule, goog.module.BaseModule);
- function BModule() {
- ++info['b'].count;
- goog.module.BaseModule.call(this);
- }
- goog.inherits(BModule, goog.module.BaseModule);
- function CModule() {
- ++info['c'].count;
- goog.module.BaseModule.call(this);
- }
- goog.inherits(CModule, goog.module.BaseModule);
- mm.setLoader(createSuccessfulNonBatchLoaderWithConstructor(mm, info));
- execOnLoad_(mm);
- assertTrue(info['a'].count == 1);
- assertTrue(info['b'].count == 0);
- assertTrue(info['c'].count == 1);
- assertTrue(mm.getModuleInfo('a').getModule() instanceof AModule);
- assertTrue(mm.getModuleInfo('c').getModule() instanceof CModule);
- }
- /**
- * Tests that a call to load the loading module during module initialization
- * doesn't trigger a second load.
- */
- function testLoadWhenInitializing() {
- var mm = getModuleManager({'a': []});
- mm.setLoader(createSuccessfulNonBatchLoader(mm));
- var info = {'a': {ctor: AModule, count: 0}};
- function AModule() {
- ++info['a'].count;
- goog.module.BaseModule.call(this);
- }
- goog.inherits(AModule, goog.module.BaseModule);
- AModule.prototype.initialize = function() { mm.load('a'); };
- mm.setLoader(createSuccessfulNonBatchLoaderWithConstructor(mm, info));
- mm.preloadModule('a');
- clock.tick(5);
- assertEquals(info['a'].count, 1);
- }
- function testErrorInEarlyCallback() {
- var errback = goog.testing.recordFunction();
- var callback = goog.testing.recordFunction();
- var mm = getModuleManager({'a': [], 'b': ['a']});
- mm.getModuleInfo('a').registerEarlyCallback(goog.functions.error('error'));
- mm.getModuleInfo('a').registerCallback(callback);
- mm.getModuleInfo('a').registerErrback(errback);
- mm.setLoader(
- createSuccessfulNonBatchLoaderWithConstructor(
- mm, createModulesFor('a', 'b')));
- mm.preloadModule('b');
- var e = assertThrows(function() { clock.tick(5); });
- assertEquals('error', e.message);
- assertEquals(0, callback.getCallCount());
- assertEquals(1, errback.getCallCount());
- assertEquals(
- goog.module.ModuleManager.FailureType.INIT_ERROR,
- errback.getLastCall().getArguments()[0]);
- assertTrue(mm.getModuleInfo('a').isLoaded());
- assertFalse(mm.getModuleInfo('b').isLoaded());
- clock.tick(5);
- assertTrue(mm.getModuleInfo('b').isLoaded());
- }
- function testErrorInNormalCallback() {
- var earlyCallback = goog.testing.recordFunction();
- var errback = goog.testing.recordFunction();
- var mm = getModuleManager({'a': [], 'b': ['a']});
- mm.getModuleInfo('a').registerEarlyCallback(earlyCallback);
- mm.getModuleInfo('a').registerEarlyCallback(goog.functions.error('error'));
- mm.getModuleInfo('a').registerErrback(errback);
- mm.setLoader(
- createSuccessfulNonBatchLoaderWithConstructor(
- mm, createModulesFor('a', 'b')));
- mm.preloadModule('b');
- var e = assertThrows(function() { clock.tick(10); });
- clock.tick(10);
- assertEquals('error', e.message);
- assertEquals(1, errback.getCallCount());
- assertEquals(
- goog.module.ModuleManager.FailureType.INIT_ERROR,
- errback.getLastCall().getArguments()[0]);
- assertTrue(mm.getModuleInfo('a').isLoaded());
- assertTrue(mm.getModuleInfo('b').isLoaded());
- }
- function testErrorInErrback() {
- var mm = getModuleManager({'a': [], 'b': ['a']});
- mm.getModuleInfo('a').registerCallback(goog.functions.error('error1'));
- mm.getModuleInfo('a').registerErrback(goog.functions.error('error2'));
- mm.setLoader(
- createSuccessfulNonBatchLoaderWithConstructor(
- mm, createModulesFor('a', 'b')));
- mm.preloadModule('a');
- var e = assertThrows(function() { clock.tick(10); });
- assertEquals('error1', e.message);
- var e = assertThrows(function() { clock.tick(10); });
- assertEquals('error2', e.message);
- assertTrue(mm.getModuleInfo('a').isLoaded());
- }
- function createModulesFor(var_args) {
- var result = {};
- for (var i = 0; i < arguments.length; i++) {
- var key = arguments[i];
- result[key] = {ctor: goog.module.BaseModule};
- }
- return result;
- }
- function createSuccessfulNonBatchLoaderWithConstructor(moduleMgr, info) {
- return {
- loadModules: function(
- ids, moduleInfoMap, opt_successFn, opt_errFn, opt_timeoutFn) {
- setTimeout(function() {
- moduleMgr.beforeLoadModuleCode(ids[0]);
- moduleMgr.setModuleConstructor(info[ids[0]].ctor);
- moduleMgr.setLoaded(ids[0]);
- moduleMgr.afterLoadModuleCode(ids[0]);
- if (opt_successFn) {
- opt_successFn();
- }
- }, 5);
- }
- };
- }
- function testInitCallbackInBaseModule() {
- var mm = new goog.module.ModuleManager();
- var called = false;
- var context;
- mm.registerInitializationCallback(function(mcontext) {
- called = true;
- context = mcontext;
- });
- mm.setAllModuleInfo({'a': [], 'b': ['a']});
- assertTrue('Base initialization not called', called);
- assertNull('Context should still be null', context);
- var mm = new goog.module.ModuleManager();
- called = false;
- mm.registerInitializationCallback(function(mcontext) {
- called = true;
- context = mcontext;
- });
- var appContext = {};
- mm.setModuleContext(appContext);
- assertTrue('Base initialization not called after setModuleContext', called);
- assertEquals('Did not receive module context', appContext, context);
- }
- function testSetAllModuleInfoString() {
- var info = 'base/one:0/two:0/three:0,1,2/four:0,3/five:';
- var mm = new goog.module.ModuleManager();
- mm.setAllModuleInfoString(info);
- assertNotNull('Base should exist', mm.getModuleInfo('base'));
- assertNotNull('One should exist', mm.getModuleInfo('one'));
- assertNotNull('Two should exist', mm.getModuleInfo('two'));
- assertNotNull('Three should exist', mm.getModuleInfo('three'));
- assertNotNull('Four should exist', mm.getModuleInfo('four'));
- assertNotNull('Five should exist', mm.getModuleInfo('five'));
- assertArrayEquals(
- ['base', 'one', 'two'], mm.getModuleInfo('three').getDependencies());
- assertArrayEquals(
- ['base', 'three'], mm.getModuleInfo('four').getDependencies());
- assertArrayEquals([], mm.getModuleInfo('five').getDependencies());
- }
- function testSetAllModuleInfoStringWithEmptyString() {
- var mm = new goog.module.ModuleManager();
- var called = false;
- var context;
- mm.registerInitializationCallback(function(mcontext) {
- called = true;
- context = mcontext;
- });
- mm.setAllModuleInfoString('');
- assertTrue('Initialization not called', called);
- }
- function testBackOffAmounts() {
- var mm = new goog.module.ModuleManager();
- assertEquals(0, mm.getBackOff_());
- mm.consecutiveFailures_++;
- assertEquals(5000, mm.getBackOff_());
- mm.consecutiveFailures_++;
- assertEquals(20000, mm.getBackOff_());
- }
- /**
- * Tests that the IDLE callbacks are executed for active->idle transitions
- * after setAllModuleInfoString with currently loading modules.
- */
- function testIdleCallbackWithInitialModules() {
- var callback = goog.testing.recordFunction();
- var mm = new goog.module.ModuleManager();
- mm.setAllModuleInfoString('a', ['a']);
- mm.registerCallback(goog.module.ModuleManager.CallbackType.IDLE, callback);
- assertTrue(mm.isActive());
- mm.beforeLoadModuleCode('a');
- assertEquals(0, callback.getCallCount());
- mm.setLoaded('a');
- mm.afterLoadModuleCode('a');
- assertFalse(mm.isActive());
- assertEquals(1, callback.getCallCount());
- }
|