OLD | NEW |
---|---|
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 }); | |
OLD | NEW |