Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(275)

Side by Side Diff: chrome/browser/resources/google_now/utility_unittest.gtestjs

Issue 23751004: Unit tests for attempt manager (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: skare@ comments Created 7 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « no previous file | chrome/test/data/webui/test_api.js » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2013 The Chromium Authors. All rights reserved. 1 // Copyright 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 /** 5 /**
6 * Test fixture for utility.js. 6 * Test fixture for utility.js.
7 * @constructor 7 * @constructor
8 * @extends {testing.Test} 8 * @extends {testing.Test}
9 */ 9 */
10 function GoogleNowUtilityUnitTest () { 10 function GoogleNowUtilityUnitTest () {
(...skipping 161 matching lines...) Expand 10 before | Expand all | Expand 10 after
172 this.mockGlobals.expects(once()). 172 this.mockGlobals.expects(once()).
173 buildErrorWithMessageForServer('Not in instrumented callback'). 173 buildErrorWithMessageForServer('Not in instrumented callback').
174 will(returnValue(testError)); 174 will(returnValue(testError));
175 this.mockGlobals.expects(once()). 175 this.mockGlobals.expects(once()).
176 reportError(eqJSON(testError)); 176 reportError(eqJSON(testError));
177 177
178 // Invocation. 178 // Invocation.
179 wrapper.checkInWrappedCallback(); 179 wrapper.checkInWrappedCallback();
180 180
181 // Step 4. Check that there won't be errors whe the page unloads. 181 // Step 4. Check that there won't be errors whe the page unloads.
182 assertTrue(onSuspendHandlerContainer.length == 1, 182 assertEquals(1, onSuspendHandlerContainer.length);
183 'onSuspendHandlerContainer.length must be 1');
184 onSuspendHandlerContainer[0](); 183 onSuspendHandlerContainer[0]();
185 }); 184 });
186 185
187 TEST_F('GoogleNowUtilityUnitTest', 'WrapperWrapCallbackPlugin', function() { 186 TEST_F('GoogleNowUtilityUnitTest', 'WrapperWrapCallbackPlugin', function() {
188 // Tests calling plugin's prologue and epilogue. 187 // Tests calling plugin's prologue and epilogue.
189 188
190 // Setup. 189 // Setup.
191 this.makeMockLocalFunctions([ 190 this.makeMockLocalFunctions([
192 'callback', 191 'callback',
193 'pluginFactory', 192 'pluginFactory',
(...skipping 180 matching lines...) Expand 10 before | Expand all | Expand 10 after
374 // Step 3. Fire runtime.onSuspend event. 373 // Step 3. Fire runtime.onSuspend event.
375 // Expectations. 374 // Expectations.
376 this.mockGlobals.expects(once()). 375 this.mockGlobals.expects(once()).
377 buildErrorWithMessageForServer(stringContains( 376 buildErrorWithMessageForServer(stringContains(
378 'ASSERT: Pending callbacks when unloading event page')). 377 'ASSERT: Pending callbacks when unloading event page')).
379 will(returnValue(testError)); 378 will(returnValue(testError));
380 this.mockGlobals.expects(once()). 379 this.mockGlobals.expects(once()).
381 reportError(eqJSON(testError)); 380 reportError(eqJSON(testError));
382 381
383 // Invocation. 382 // Invocation.
384 assertTrue(onSuspendHandlerContainer.length == 1, 383 assertEquals(1, onSuspendHandlerContainer.length);
385 'onSuspendHandlerContainer.length must be 1');
386 onSuspendHandlerContainer[0](); 384 onSuspendHandlerContainer[0]();
387 }); 385 });
388 386
389 TEST_F('GoogleNowUtilityUnitTest', 387 TEST_F('GoogleNowUtilityUnitTest',
390 'WrapperOnSuspendListenerSuccess', 388 'WrapperOnSuspendListenerSuccess',
391 function() { 389 function() {
392 // Tests that upon unloading event page, we don't get an error if there are no 390 // Tests that upon unloading event page, we don't get an error if there are no
393 // pending required callbacks. 391 // pending required callbacks.
394 392
395 // Setup. 393 // Setup.
(...skipping 21 matching lines...) Expand all
417 Mock4JS.verifyAllMocks(); 415 Mock4JS.verifyAllMocks();
418 416
419 // Step 3. Call wrapped callback. 417 // Step 3. Call wrapped callback.
420 // Expectations. 418 // Expectations.
421 this.mockLocalFunctions.expects(once()).callback(); 419 this.mockLocalFunctions.expects(once()).callback();
422 420
423 // Invocation. 421 // Invocation.
424 wrappedCallback(); 422 wrappedCallback();
425 423
426 // Step 4. Fire runtime.onSuspend event. 424 // Step 4. Fire runtime.onSuspend event.
427 assertTrue(onSuspendHandlerContainer.length == 1, 425 assertEquals(1, onSuspendHandlerContainer.length);
428 'onSuspendHandlerContainer.length must be 1');
429 onSuspendHandlerContainer[0](); 426 onSuspendHandlerContainer[0]();
430 }); 427 });
431 428
432 var taskNameA = 'TASK A'; 429 var taskNameA = 'TASK A';
433 var taskNameB = 'TASK B'; 430 var taskNameB = 'TASK B';
434 var taskNameC = 'TASK C'; 431 var taskNameC = 'TASK C';
435 432
436 function areTasksConflicting(newTaskName, scheduledTaskName) { 433 function areTasksConflicting(newTaskName, scheduledTaskName) {
437 // Task B is conflicting with Task A. This means that if Task B is added when 434 // Task B is conflicting with Task A. This means that if Task B is added when
438 // Task A is running, Task B will be ignored (but not vice versa). No other 435 // Task A is running, Task B will be ignored (but not vice versa). No other
439 // pair is conflicting. 436 // pair is conflicting.
440 return newTaskName == taskNameB && scheduledTaskName == taskNameA; 437 return newTaskName == taskNameB && scheduledTaskName == taskNameA;
441 } 438 }
442 439
443 function setUpTaskManagerTest(fixture) { 440 function setUpTaskManagerTest(fixture) {
444 // We want to mock wrapper using makeAndRegisterMockApis(), which requires
445 // the mocked functions to not exist as a precondition. Resetting 'wrapper' to
446 // 'undefined'.
447 wrapper = undefined;
448
449 fixture.makeAndRegisterMockApis([ 441 fixture.makeAndRegisterMockApis([
450 'wrapper.checkInWrappedCallback', 442 'wrapper.checkInWrappedCallback',
451 'wrapper.registerWrapperPluginFactory', 443 'wrapper.registerWrapperPluginFactory',
452 'wrapper.debugGetStateString' 444 'wrapper.debugGetStateString'
453 ]); 445 ]);
454 fixture.makeMockLocalFunctions(['task1', 'task2', 'task3']); 446 fixture.makeMockLocalFunctions(['task1', 'task2', 'task3']);
455 fixture.makeAndRegisterMockGlobals(['reportError']); 447 fixture.makeAndRegisterMockGlobals(['reportError']);
456 448
457 fixture.mockApis.stubs().wrapper_checkInWrappedCallback(); 449 fixture.mockApis.stubs().wrapper_checkInWrappedCallback();
458 fixture.mockApis.stubs().wrapper_debugGetStateString(). 450 fixture.mockApis.stubs().wrapper_debugGetStateString().
(...skipping 154 matching lines...) Expand 10 before | Expand all | Expand 10 after
613 will(callFunction(function() { 605 will(callFunction(function() {
614 test.pluginFactory(); 606 test.pluginFactory();
615 })); 607 }));
616 // Invocation. 608 // Invocation.
617 test.tasks.add(taskNameA, this.mockLocalFunctions.functions().task1); 609 test.tasks.add(taskNameA, this.mockLocalFunctions.functions().task1);
618 Mock4JS.verifyAllMocks(); 610 Mock4JS.verifyAllMocks();
619 611
620 // Step 2. Invoke onSuspend event of the task manager. 612 // Step 2. Invoke onSuspend event of the task manager.
621 // Setup and expectations. The 2 callbacks in onSuspendHandlerContainer are 613 // Setup and expectations. The 2 callbacks in onSuspendHandlerContainer are
622 // from the wrapper and the task manager. 614 // from the wrapper and the task manager.
623 assertTrue(onSuspendHandlerContainer.length == 2, 615 assertEquals(2, onSuspendHandlerContainer.length);
624 'onSuspendHandlerContainer.length must be 2');
625 this.mockGlobals.expects(once()).reportError(eqToString( 616 this.mockGlobals.expects(once()).reportError(eqToString(
626 'Error: ASSERT: Incomplete task when unloading event page,' + 617 'Error: ASSERT: Incomplete task when unloading event page,' +
627 ' queue = [{"name":"TASK A"}], testWrapperDebugState')); 618 ' queue = [{"name":"TASK A"}], testWrapperDebugState'));
628 // Invocation. 619 // Invocation.
629 onSuspendHandlerContainer[1](); 620 onSuspendHandlerContainer[1]();
630 }); 621 });
631 622
632 TEST_F('GoogleNowUtilityUnitTest', 'TaskManagerSuspendSuccess', function() { 623 TEST_F('GoogleNowUtilityUnitTest', 'TaskManagerSuspendSuccess', function() {
633 // Tests that task manager's onSuspend method does not report an error if all 624 // Tests that task manager's onSuspend method does not report an error if all
634 // tasks completed. 625 // tasks completed.
(...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after
719 // finished despite the pending non-task callback. 710 // finished despite the pending non-task callback.
720 task1PluginInstance.prologue(); 711 task1PluginInstance.prologue();
721 task1PluginInstance.epilogue(); 712 task1PluginInstance.epilogue();
722 Mock4JS.verifyAllMocks(); 713 Mock4JS.verifyAllMocks();
723 714
724 // Step 4. Check that task1 is finished by submitting task2, which should 715 // Step 4. Check that task1 is finished by submitting task2, which should
725 // be executed immediately. 716 // be executed immediately.
726 this.mockLocalFunctions.expects(once()).task2(ANYTHING); 717 this.mockLocalFunctions.expects(once()).task2(ANYTHING);
727 test.tasks.add(taskNameC, this.mockLocalFunctions.functions().task2); 718 test.tasks.add(taskNameC, this.mockLocalFunctions.functions().task2);
728 }); 719 });
720
721 var testAttemptAlarmName = 'attempt-scheduler-testAttempts';
722 var testAttemptStorageKey = 'current-delay-testAttempts';
723 var testInitialDelaySeconds = 239;
724 var testMaximumDelaySeconds = 2239;
725 // Value to be returned by mocked Math.random(). We want the value returned by
726 // Math.random() to be predictable to be able to check results against expected
727 // values. A fixed seed would be okay, but fixed seeding isn't possible in JS at
728 // the moment.
729 var testRandomValue = 0.31415926;
arv (Not doing code reviews) 2013/09/09 13:55:10 FYI, we have a bunch of these already: https://co
vadimt 2013/09/09 15:53:06 Thanks, that's nice to know! However, I don't see
730
731 function createTestAttempStorageEntry(delaySeconds) {
732 // Creates a test storage object that attempt manager uses to store current
733 // delay.
734 var storageObject = {};
735 storageObject[testAttemptStorageKey] = delaySeconds;
736 return storageObject;
737 }
738
739 function setupAttemptManagerTest(fixture) {
740 Math.random = function() { return testRandomValue; }
741
742 fixture.makeMockLocalFunctions([
743 'attempt',
744 'planForNextCallback',
745 'isRunningCallback'
746 ]);
747 fixture.makeAndRegisterMockApis([
748 'chrome.alarms.clear',
749 'chrome.alarms.create',
750 'chrome.storage.local.remove',
751 'chrome.storage.local.set',
752 'instrumented.alarms.get',
753 'instrumented.storage.local.get'
754 ]);
755
756 var testAttempts = buildAttemptManager(
757 'testAttempts',
758 fixture.mockLocalFunctions.functions().attempt,
759 testInitialDelaySeconds,
760 testMaximumDelaySeconds);
761 Mock4JS.verifyAllMocks();
762
763 return {
764 attempts: testAttempts
765 };
766 }
767
768 TEST_F('GoogleNowUtilityUnitTest', 'AttemptManagerStartStop', function() {
769 // Tests starting and stopping an attempt manager.
770
771 // Setup.
772 var test = setupAttemptManagerTest(this);
773
774 // Step 1. Check that attempt manager is not running.
775 // Expectations.
776 var alarmsGetSavedArgs = new SaveMockArguments();
777 this.mockApis.expects(once()).
778 instrumented_alarms_get(
779 alarmsGetSavedArgs.match(eq(testAttemptAlarmName)),
780 alarmsGetSavedArgs.match(ANYTHING)).
781 will(invokeCallback(alarmsGetSavedArgs, 1, undefined));
782 this.mockLocalFunctions.expects(once()).isRunningCallback(false);
783 // Invocation.
784 test.attempts.isRunning(
785 this.mockLocalFunctions.functions().isRunningCallback);
786 Mock4JS.verifyAllMocks();
787
788 // Step 2. Start attempt manager with no parameters.
789 // Expectations.
790 var expectedRetryDelaySeconds =
791 testInitialDelaySeconds * (1 + testRandomValue * 0.2);
792 this.mockApis.expects(once()).chrome_alarms_create(
793 testAttemptAlarmName,
794 eqJSON({
795 delayInMinutes: expectedRetryDelaySeconds / 60,
796 periodInMinutes: testMaximumDelaySeconds / 60
797 }));
798 this.mockApis.expects(once()).chrome_storage_local_set(
799 eqJSON(createTestAttempStorageEntry(expectedRetryDelaySeconds)));
800 // Invocation.
801 test.attempts.start();
802 Mock4JS.verifyAllMocks();
803
804 // Step 3. Check that attempt manager is running.
805 // Expectations.
806 alarmsGetSavedArgs = new SaveMockArguments();
807 this.mockApis.expects(once()).
808 instrumented_alarms_get(
809 alarmsGetSavedArgs.match(eq(testAttemptAlarmName)),
810 alarmsGetSavedArgs.match(ANYTHING)).
811 will(invokeCallback(alarmsGetSavedArgs, 1, {testField: 'TEST VALUE'}));
812 this.mockLocalFunctions.expects(once()).isRunningCallback(true);
813 // Invocation.
814 test.attempts.isRunning(
815 this.mockLocalFunctions.functions().isRunningCallback);
816 Mock4JS.verifyAllMocks();
817
818 // Step 4. Stop task manager.
819 // Expectations.
820 this.mockApis.expects(once()).chrome_alarms_clear(testAttemptAlarmName);
821 this.mockApis.expects(once()).chrome_storage_local_remove(
822 testAttemptStorageKey);
823 // Invocation.
824 test.attempts.stop();
825 });
826
827 TEST_F(
828 'GoogleNowUtilityUnitTest',
829 'AttemptManagerStartWithDelayParam',
830 function() {
831 // Tests starting an attempt manager with a delay parameter.
832
833 // Setup.
834 var test = setupAttemptManagerTest(this);
835 var testFirstDelaySeconds = 1039;
836
837 // Starting attempt manager with a parameter specifying first delay.
838 // Expectations.
839 this.mockApis.expects(once()).chrome_alarms_create(
840 testAttemptAlarmName,
841 eqJSON({
842 delayInMinutes: testFirstDelaySeconds / 60,
843 periodInMinutes: testMaximumDelaySeconds / 60
844 }));
845 this.mockApis.expects(once()).chrome_storage_local_remove(
846 testAttemptStorageKey);
847 // Invocation.
848 test.attempts.start(testFirstDelaySeconds);
849 });
850
851 TEST_F('GoogleNowUtilityUnitTest', 'AttemptManagerExponGrowth', function() {
852 // Tests that retry time grows exponentially. We don't need to check the case
853 // of growing more than once, since the object doesn't have state, and the
854 // test checks all its inputs and outputs of the tested code.
855
856 // Setup.
857 var test = setupAttemptManagerTest(this);
858 var testStoredRetryDelay = 433;
859
860 // Call planForNext, which prepares next attempt. Current retry time
861 // is less than 1/2 of the maximum delay.
862 // Expectations.
863 var expectedRetryDelaySeconds =
864 testStoredRetryDelay * 2 * (1 + testRandomValue * 0.2);
865 var storageGetSavedArgs = new SaveMockArguments();
866 this.mockApis.expects(once()).instrumented_storage_local_get(
867 storageGetSavedArgs.match(eq(testAttemptStorageKey)),
868 storageGetSavedArgs.match(ANYTHING)).
869 will(invokeCallback(
870 storageGetSavedArgs,
871 1,
872 createTestAttempStorageEntry(testStoredRetryDelay)));
873 this.mockApis.expects(once()).chrome_alarms_create(
874 testAttemptAlarmName,
875 eqJSON({
876 delayInMinutes: expectedRetryDelaySeconds / 60,
877 periodInMinutes: testMaximumDelaySeconds / 60}));
878 this.mockApis.expects(once()).chrome_storage_local_set(
879 eqJSON(createTestAttempStorageEntry(expectedRetryDelaySeconds)));
880 this.mockLocalFunctions.expects(once()).planForNextCallback();
881 // Invocation.
882 test.attempts.planForNext(
883 this.mockLocalFunctions.functions().planForNextCallback);
884 });
885
886 TEST_F('GoogleNowUtilityUnitTest', 'AttemptManagerGrowthLimit', function() {
887 // Tests that retry time stops growing at the maximum value.
888
889 // Setup.
890 var test = setupAttemptManagerTest(this);
891 var testStoredRetryDelay = 1500;
892
893 // Call planForNext, which prepares next attempt. Current retry time
894 // is greater than 1/2 of the maximum delay.
895 // Expectations.
896 var expectedRetryDelaySeconds = testMaximumDelaySeconds;
897 var storageGetSavedArgs = new SaveMockArguments();
898 this.mockApis.expects(once()).
899 instrumented_storage_local_get(
900 storageGetSavedArgs.match(eq(testAttemptStorageKey)),
901 storageGetSavedArgs.match(ANYTHING)).
902 will(invokeCallback(
903 storageGetSavedArgs,
904 1,
905 createTestAttempStorageEntry(testStoredRetryDelay)));
906 this.mockApis.expects(once()).chrome_alarms_create(
907 testAttemptAlarmName,
908 eqJSON({
909 delayInMinutes: expectedRetryDelaySeconds / 60,
910 periodInMinutes: testMaximumDelaySeconds / 60
911 }));
912 this.mockApis.expects(once()).chrome_storage_local_set(
913 eqJSON(createTestAttempStorageEntry(expectedRetryDelaySeconds)));
914 this.mockLocalFunctions.expects(once()).planForNextCallback();
915 // Invocation.
916 test.attempts.planForNext(
917 this.mockLocalFunctions.functions().planForNextCallback);
918 });
919
920 TEST_F('GoogleNowUtilityUnitTest', 'AttemptManagerAlarm', function() {
921 // Tests that firing the alarm invokes the attempt.
922
923 // Setup.
924 var test = setupAttemptManagerTest(this);
925 var onAlarmHandlerContainer = getMockHandlerContainer('alarms.onAlarm');
926 assertEquals(1, onAlarmHandlerContainer.length);
927
928 // Fire the alarm and check that this invokes the attempt callback.
929 // Expectations.
930 var alarmsGetSavedArgs = new SaveMockArguments();
931 this.mockApis.expects(once()).
932 instrumented_alarms_get(
933 alarmsGetSavedArgs.match(eq(testAttemptAlarmName)),
934 alarmsGetSavedArgs.match(ANYTHING)).
935 will(invokeCallback(alarmsGetSavedArgs, 1, {testField: 'TEST VALUE'}));
936 this.mockLocalFunctions.expects(once()).attempt();
937 // Invocation.
938 onAlarmHandlerContainer[0]({name: testAttemptAlarmName});
939 });
OLDNEW
« no previous file with comments | « no previous file | chrome/test/data/webui/test_api.js » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698