From abe80cc31d5a40ebed743085011fbcda0c1a9a10 Mon Sep 17 00:00:00 2001 From: "Matt A. Tobin" Date: Tue, 23 Apr 2019 15:32:23 -0400 Subject: Issue #1053 - Drop support Android and remove Fennec - Part 1a: Remove mobile/android --- .../robocop/src/org/mozilla/gecko/Actions.java | 126 -- .../robocop/src/org/mozilla/gecko/Assert.java | 25 - .../robocop/src/org/mozilla/gecko/Driver.java | 44 - .../robocop/src/org/mozilla/gecko/Element.java | 27 - .../gecko/FennecInstrumentationTestRunner.java | 79 - .../org/mozilla/gecko/FennecMochitestAssert.java | 254 --- .../src/org/mozilla/gecko/FennecNativeActions.java | 482 ----- .../src/org/mozilla/gecko/FennecNativeDriver.java | 392 ---- .../src/org/mozilla/gecko/FennecNativeElement.java | 116 -- .../src/org/mozilla/gecko/FennecTalosAssert.java | 74 - .../LaunchFennecWithConfigurationActivity.java | 40 - .../src/org/mozilla/gecko/PaintedSurface.java | 105 -- .../src/org/mozilla/gecko/RoboCopException.java | 24 - .../src/org/mozilla/gecko/RobocopShare1.java | 17 - .../src/org/mozilla/gecko/RobocopShare2.java | 17 - .../src/org/mozilla/gecko/RobocopUtils.java | 58 - .../src/org/mozilla/gecko/StructuredLogger.java | 188 -- .../src/org/mozilla/gecko/tests/AboutHomeTest.java | 252 --- .../org/mozilla/gecko/tests/BaseRobocopTest.java | 288 --- .../src/org/mozilla/gecko/tests/BaseTest.java | 976 ---------- .../gecko/tests/ContentContextMenuTest.java | 135 -- .../mozilla/gecko/tests/ContentProviderTest.java | 255 --- .../org/mozilla/gecko/tests/DatabaseHelper.java | 170 -- .../mozilla/gecko/tests/JavascriptBridgeTest.java | 107 -- .../org/mozilla/gecko/tests/JavascriptTest.java | 87 - .../org/mozilla/gecko/tests/MotionEventHelper.java | 210 --- .../mozilla/gecko/tests/MotionEventReplayer.java | 224 --- .../src/org/mozilla/gecko/tests/PixelTest.java | 117 -- .../mozilla/gecko/tests/SelectionHandlerTest.java | 56 - .../src/org/mozilla/gecko/tests/SessionTest.java | 407 ----- .../src/org/mozilla/gecko/tests/StringHelper.java | 401 ---- .../src/org/mozilla/gecko/tests/UITest.java | 203 --- .../src/org/mozilla/gecko/tests/UITestContext.java | 51 - .../gecko/tests/components/AboutHomeComponent.java | 193 -- .../gecko/tests/components/AppMenuComponent.java | 295 --- .../gecko/tests/components/BaseComponent.java | 36 - .../gecko/tests/components/GeckoViewComponent.java | 343 ---- .../gecko/tests/components/TabStripComponent.java | 56 - .../gecko/tests/components/ToolbarComponent.java | 326 ---- .../gecko/tests/helpers/AssertionHelper.java | 112 -- .../mozilla/gecko/tests/helpers/DeviceHelper.java | 108 -- .../gecko/tests/helpers/FrameworkHelper.java | 94 - .../gecko/tests/helpers/GeckoClickHelper.java | 50 - .../mozilla/gecko/tests/helpers/GeckoHelper.java | 49 - .../gecko/tests/helpers/HelperInitializer.java | 30 - .../gecko/tests/helpers/JavascriptBridge.java | 394 ---- .../tests/helpers/JavascriptMessageParser.java | 100 - .../gecko/tests/helpers/NavigationHelper.java | 104 -- .../gecko/tests/helpers/RobotiumHelper.java | 43 - .../mozilla/gecko/tests/helpers/WaitHelper.java | 215 --- .../org/mozilla/gecko/tests/testANRReporter.java | 240 --- .../gecko/tests/testAboutHomePageNavigation.java | 107 -- .../gecko/tests/testAboutHomeVisibility.java | 57 - .../src/org/mozilla/gecko/tests/testAboutPage.java | 47 - .../mozilla/gecko/tests/testAccessibleCarets.java | 76 - .../gecko/tests/testActivityStreamContextMenu.java | 94 - .../mozilla/gecko/tests/testAddSearchEngine.java | 172 -- .../org/mozilla/gecko/tests/testAddonManager.java | 79 - .../org/mozilla/gecko/tests/testAdobeFlash.java | 39 - .../mozilla/gecko/tests/testAppMenuPathways.java | 77 - .../org/mozilla/gecko/tests/testAxisLocking.java | 58 - .../gecko/tests/testBackButtonInEditMode.java | 47 - .../src/org/mozilla/gecko/tests/testBookmark.java | 72 - .../mozilla/gecko/tests/testBookmarkFolders.java | 169 -- .../mozilla/gecko/tests/testBookmarkKeyword.java | 28 - .../org/mozilla/gecko/tests/testBookmarklets.java | 46 - .../mozilla/gecko/tests/testBookmarksPanel.java | 174 -- .../tests/testBrowserDatabaseHelperUpgrades.java | 150 -- .../mozilla/gecko/tests/testBrowserDiscovery.java | 13 - .../mozilla/gecko/tests/testBrowserProvider.java | 1921 -------------------- .../gecko/tests/testBrowserSearchVisibility.java | 69 - .../org/mozilla/gecko/tests/testBug1217581.java | 31 - .../src/org/mozilla/gecko/tests/testCheck2.java | 61 - .../src/org/mozilla/gecko/tests/testCheck3.java | 61 - .../src/org/mozilla/gecko/tests/testDBUtils.java | 70 - .../org/mozilla/gecko/tests/testDistribution.java | 556 ------ .../org/mozilla/gecko/tests/testDoorHanger.java | 205 --- .../mozilla/gecko/tests/testEventDispatcher.java | 450 ----- .../org/mozilla/gecko/tests/testFilePicker.java | 52 - .../org/mozilla/gecko/tests/testFilterOpenTab.java | 133 -- .../org/mozilla/gecko/tests/testFindInPage.java | 107 -- .../mozilla/gecko/tests/testFlingCorrectness.java | 52 - .../org/mozilla/gecko/tests/testFormHistory.java | 104 -- .../org/mozilla/gecko/tests/testGeckoProfile.java | 295 --- .../org/mozilla/gecko/tests/testGeckoRequest.java | 121 -- .../org/mozilla/gecko/tests/testGetUserMedia.java | 159 -- .../src/org/mozilla/gecko/tests/testHistory.java | 74 - .../mozilla/gecko/tests/testHistoryService.java | 12 - .../org/mozilla/gecko/tests/testHomeBanner.java | 94 - .../mozilla/gecko/tests/testHomeListsProvider.java | 118 -- .../org/mozilla/gecko/tests/testICODecoder.java | 238 --- .../mozilla/gecko/tests/testInputConnection.java | 349 ---- .../org/mozilla/gecko/tests/testInputUrlBar.java | 136 -- .../src/org/mozilla/gecko/tests/testJarReader.java | 70 - .../mozilla/gecko/tests/testJavascriptBridge.java | 69 - .../mozilla/gecko/tests/testLinkContextMenu.java | 37 - .../src/org/mozilla/gecko/tests/testLoad.java | 23 - .../mozilla/gecko/tests/testLoginsProvider.java | 387 ---- .../mozilla/gecko/tests/testMailToContextMenu.java | 26 - .../org/mozilla/gecko/tests/testNativeCrypto.java | 288 --- .../src/org/mozilla/gecko/tests/testNewTab.java | 65 - .../src/org/mozilla/gecko/tests/testOSLocale.java | 137 -- .../mozilla/gecko/tests/testPanCorrectness.java | 49 - .../mozilla/gecko/tests/testPasswordEncrypt.java | 125 -- .../mozilla/gecko/tests/testPasswordProvider.java | 104 -- .../org/mozilla/gecko/tests/testPermissions.java | 72 - .../gecko/tests/testPictureLinkContextMenu.java | 52 - .../org/mozilla/gecko/tests/testPrefsObserver.java | 81 - .../mozilla/gecko/tests/testPrivateBrowsing.java | 89 - .../mozilla/gecko/tests/testPromptGridInput.java | 47 - .../gecko/tests/testReaderCacheMigration.java | 62 - .../mozilla/gecko/tests/testReaderModeTitle.java | 19 - .../mozilla/gecko/tests/testReadingListCache.java | 12 - .../tests/testReadingListToBookmarksMigration.java | 217 --- .../org/mozilla/gecko/tests/testRestrictions.java | 39 - .../gecko/tests/testRuntimePermissionsAPI.java | 48 - .../gecko/tests/testSearchHistoryProvider.java | 379 ---- .../mozilla/gecko/tests/testSearchSuggestions.java | 115 -- .../mozilla/gecko/tests/testSessionHistory.java | 37 - .../mozilla/gecko/tests/testSessionOOMRestore.java | 54 - .../mozilla/gecko/tests/testSessionOOMSave.java | 87 - .../src/org/mozilla/gecko/tests/testShareLink.java | 265 --- .../org/mozilla/gecko/tests/testSnackbarAPI.java | 52 - .../mozilla/gecko/tests/testStateWhileLoading.java | 40 - .../mozilla/gecko/tests/testStumblerSetting.java | 90 - .../org/mozilla/gecko/tests/testThumbnails.java | 116 -- .../gecko/tests/testTrackingProtection.java | 65 - .../org/mozilla/gecko/tests/testUITelemetry.java | 56 - .../gecko/tests/testUnifiedTelemetryClientId.java | 265 --- .../org/mozilla/gecko/tests/testVideoControls.java | 9 - .../org/mozilla/gecko/tests/testVkbOverlap.java | 105 -- 131 files changed, 19621 deletions(-) delete mode 100644 mobile/android/tests/browser/robocop/src/org/mozilla/gecko/Actions.java delete mode 100644 mobile/android/tests/browser/robocop/src/org/mozilla/gecko/Assert.java delete mode 100644 mobile/android/tests/browser/robocop/src/org/mozilla/gecko/Driver.java delete mode 100644 mobile/android/tests/browser/robocop/src/org/mozilla/gecko/Element.java delete mode 100644 mobile/android/tests/browser/robocop/src/org/mozilla/gecko/FennecInstrumentationTestRunner.java delete mode 100644 mobile/android/tests/browser/robocop/src/org/mozilla/gecko/FennecMochitestAssert.java delete mode 100644 mobile/android/tests/browser/robocop/src/org/mozilla/gecko/FennecNativeActions.java delete mode 100644 mobile/android/tests/browser/robocop/src/org/mozilla/gecko/FennecNativeDriver.java delete mode 100644 mobile/android/tests/browser/robocop/src/org/mozilla/gecko/FennecNativeElement.java delete mode 100644 mobile/android/tests/browser/robocop/src/org/mozilla/gecko/FennecTalosAssert.java delete mode 100644 mobile/android/tests/browser/robocop/src/org/mozilla/gecko/LaunchFennecWithConfigurationActivity.java delete mode 100644 mobile/android/tests/browser/robocop/src/org/mozilla/gecko/PaintedSurface.java delete mode 100644 mobile/android/tests/browser/robocop/src/org/mozilla/gecko/RoboCopException.java delete mode 100644 mobile/android/tests/browser/robocop/src/org/mozilla/gecko/RobocopShare1.java delete mode 100644 mobile/android/tests/browser/robocop/src/org/mozilla/gecko/RobocopShare2.java delete mode 100644 mobile/android/tests/browser/robocop/src/org/mozilla/gecko/RobocopUtils.java delete mode 100644 mobile/android/tests/browser/robocop/src/org/mozilla/gecko/StructuredLogger.java delete mode 100644 mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/AboutHomeTest.java delete mode 100644 mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/BaseRobocopTest.java delete mode 100644 mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/BaseTest.java delete mode 100644 mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/ContentContextMenuTest.java delete mode 100644 mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/ContentProviderTest.java delete mode 100644 mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/DatabaseHelper.java delete mode 100644 mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/JavascriptBridgeTest.java delete mode 100644 mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/JavascriptTest.java delete mode 100644 mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/MotionEventHelper.java delete mode 100644 mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/MotionEventReplayer.java delete mode 100644 mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/PixelTest.java delete mode 100644 mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/SelectionHandlerTest.java delete mode 100644 mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/SessionTest.java delete mode 100644 mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/StringHelper.java delete mode 100644 mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/UITest.java delete mode 100644 mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/UITestContext.java delete mode 100644 mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/components/AboutHomeComponent.java delete mode 100644 mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/components/AppMenuComponent.java delete mode 100644 mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/components/BaseComponent.java delete mode 100644 mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/components/GeckoViewComponent.java delete mode 100644 mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/components/TabStripComponent.java delete mode 100644 mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/components/ToolbarComponent.java delete mode 100644 mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/helpers/AssertionHelper.java delete mode 100644 mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/helpers/DeviceHelper.java delete mode 100644 mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/helpers/FrameworkHelper.java delete mode 100644 mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/helpers/GeckoClickHelper.java delete mode 100644 mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/helpers/GeckoHelper.java delete mode 100644 mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/helpers/HelperInitializer.java delete mode 100644 mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/helpers/JavascriptBridge.java delete mode 100644 mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/helpers/JavascriptMessageParser.java delete mode 100644 mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/helpers/NavigationHelper.java delete mode 100644 mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/helpers/RobotiumHelper.java delete mode 100644 mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/helpers/WaitHelper.java delete mode 100644 mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/testANRReporter.java delete mode 100644 mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/testAboutHomePageNavigation.java delete mode 100644 mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/testAboutHomeVisibility.java delete mode 100644 mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/testAboutPage.java delete mode 100644 mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/testAccessibleCarets.java delete mode 100644 mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/testActivityStreamContextMenu.java delete mode 100644 mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/testAddSearchEngine.java delete mode 100644 mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/testAddonManager.java delete mode 100644 mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/testAdobeFlash.java delete mode 100644 mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/testAppMenuPathways.java delete mode 100644 mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/testAxisLocking.java delete mode 100644 mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/testBackButtonInEditMode.java delete mode 100644 mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/testBookmark.java delete mode 100644 mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/testBookmarkFolders.java delete mode 100644 mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/testBookmarkKeyword.java delete mode 100644 mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/testBookmarklets.java delete mode 100644 mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/testBookmarksPanel.java delete mode 100644 mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/testBrowserDatabaseHelperUpgrades.java delete mode 100644 mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/testBrowserDiscovery.java delete mode 100644 mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/testBrowserProvider.java delete mode 100644 mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/testBrowserSearchVisibility.java delete mode 100644 mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/testBug1217581.java delete mode 100644 mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/testCheck2.java delete mode 100644 mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/testCheck3.java delete mode 100644 mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/testDBUtils.java delete mode 100644 mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/testDistribution.java delete mode 100644 mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/testDoorHanger.java delete mode 100644 mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/testEventDispatcher.java delete mode 100644 mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/testFilePicker.java delete mode 100644 mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/testFilterOpenTab.java delete mode 100644 mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/testFindInPage.java delete mode 100644 mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/testFlingCorrectness.java delete mode 100644 mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/testFormHistory.java delete mode 100644 mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/testGeckoProfile.java delete mode 100644 mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/testGeckoRequest.java delete mode 100644 mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/testGetUserMedia.java delete mode 100644 mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/testHistory.java delete mode 100644 mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/testHistoryService.java delete mode 100644 mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/testHomeBanner.java delete mode 100644 mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/testHomeListsProvider.java delete mode 100644 mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/testICODecoder.java delete mode 100644 mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/testInputConnection.java delete mode 100644 mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/testInputUrlBar.java delete mode 100644 mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/testJarReader.java delete mode 100644 mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/testJavascriptBridge.java delete mode 100644 mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/testLinkContextMenu.java delete mode 100644 mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/testLoad.java delete mode 100644 mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/testLoginsProvider.java delete mode 100644 mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/testMailToContextMenu.java delete mode 100644 mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/testNativeCrypto.java delete mode 100644 mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/testNewTab.java delete mode 100644 mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/testOSLocale.java delete mode 100644 mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/testPanCorrectness.java delete mode 100644 mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/testPasswordEncrypt.java delete mode 100644 mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/testPasswordProvider.java delete mode 100644 mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/testPermissions.java delete mode 100644 mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/testPictureLinkContextMenu.java delete mode 100644 mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/testPrefsObserver.java delete mode 100644 mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/testPrivateBrowsing.java delete mode 100644 mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/testPromptGridInput.java delete mode 100644 mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/testReaderCacheMigration.java delete mode 100644 mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/testReaderModeTitle.java delete mode 100644 mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/testReadingListCache.java delete mode 100644 mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/testReadingListToBookmarksMigration.java delete mode 100644 mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/testRestrictions.java delete mode 100644 mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/testRuntimePermissionsAPI.java delete mode 100644 mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/testSearchHistoryProvider.java delete mode 100644 mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/testSearchSuggestions.java delete mode 100644 mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/testSessionHistory.java delete mode 100644 mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/testSessionOOMRestore.java delete mode 100644 mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/testSessionOOMSave.java delete mode 100644 mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/testShareLink.java delete mode 100644 mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/testSnackbarAPI.java delete mode 100644 mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/testStateWhileLoading.java delete mode 100644 mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/testStumblerSetting.java delete mode 100644 mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/testThumbnails.java delete mode 100644 mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/testTrackingProtection.java delete mode 100644 mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/testUITelemetry.java delete mode 100644 mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/testUnifiedTelemetryClientId.java delete mode 100644 mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/testVideoControls.java delete mode 100644 mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/testVkbOverlap.java (limited to 'mobile/android/tests/browser/robocop/src/org') diff --git a/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/Actions.java b/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/Actions.java deleted file mode 100644 index 05e6bfa52..000000000 --- a/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/Actions.java +++ /dev/null @@ -1,126 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -package org.mozilla.gecko; -import android.database.Cursor; - -public interface Actions { - - /** Special keys supported by sendSpecialKey() */ - public enum SpecialKey { - DOWN, - UP, - LEFT, - RIGHT, - ENTER, - MENU, - DELETE, - } - - public interface EventExpecter { - /** Blocks until the event has been received. Subsequent calls will return immediately. */ - public void blockForEvent(); - public void blockForEvent(long millis, boolean failOnTimeout); - - /** Blocks until the event has been received and returns data associated with the event. */ - public String blockForEventData(); - - /** - * Blocks until the event has been received, or until the timeout has been exceeded. - * Returns the data associated with the event, if applicable. - */ - public String blockForEventDataWithTimeout(long millis); - - /** Polls to see if the event has been received. Once this returns true, subsequent calls will also return true. */ - public boolean eventReceived(); - - /** Stop listening for events. */ - public void unregisterListener(); - } - - public interface RepeatedEventExpecter extends EventExpecter { - /** Blocks until at least one event has been received, and no events have been received in the last millis milliseconds. */ - public void blockUntilClear(long millis); - } - - /** - * Sends an event to Gecko. - * - * @param geckoEvent The geckoEvent JSONObject's type - */ - void sendGeckoEvent(String geckoEvent, String data); - - public interface PrefWaiter { - boolean isFinished(); - void waitForFinish(); - void waitForFinish(long timeoutMillis, boolean failOnTimeout); - } - - public abstract static class PrefHandlerBase implements PrefsHelper.PrefHandler { - /* package */ Assert asserter; - - @Override // PrefsHelper.PrefHandler - public void prefValue(String pref, boolean value) { - asserter.ok(false, "Unexpected pref callback", ""); - } - - @Override // PrefsHelper.PrefHandler - public void prefValue(String pref, int value) { - asserter.ok(false, "Unexpected pref callback", ""); - } - - @Override // PrefsHelper.PrefHandler - public void prefValue(String pref, String value) { - asserter.ok(false, "Unexpected pref callback", ""); - } - - @Override // PrefsHelper.PrefHandler - public void finish() { - } - } - - PrefWaiter getPrefs(String[] prefNames, PrefHandlerBase handler); - void setPref(String pref, Object value, boolean flush); - PrefWaiter addPrefsObserver(String[] prefNames, PrefHandlerBase handler); - void removePrefsObserver(PrefWaiter handler); - - /** - * Listens for a gecko event to be sent from the Gecko instance. - * The returned object can be used to test if the event has been - * received. Note that only one event is listened for. - * - * @param geckoEvent The geckoEvent JSONObject's type - */ - RepeatedEventExpecter expectGeckoEvent(String geckoEvent); - - /** - * Listens for a paint event. Note that calling expectPaint() will - * invalidate the event expecters returned from any previous calls - * to expectPaint(); calling any methods on those invalidated objects - * will result in undefined behaviour. - */ - RepeatedEventExpecter expectPaint(); - - /** - * Send a string to the application - * - * @param keysToSend The string to send - */ - void sendKeys(String keysToSend); - - /** - * Send a special keycode to the element - * - * @param key The special key to send - */ - void sendSpecialKey(SpecialKey key); - void sendKeyCode(int keyCode); - - void drag(int startingX, int endingX, int startingY, int endingY); - - /** - * Run a sql query on the specified database - */ - public Cursor querySql(String dbPath, String sql); -} diff --git a/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/Assert.java b/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/Assert.java deleted file mode 100644 index aa76dcf2b..000000000 --- a/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/Assert.java +++ /dev/null @@ -1,25 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -package org.mozilla.gecko; - -public interface Assert { - void dumpLog(String message); - void dumpLog(String message, Throwable t); - void setLogFile(String filename); - void setTestName(String testName); - void endTest(); - - void ok(boolean condition, String name, String diag); - void is(Object actual, Object expected, String name); - void isnot(Object actual, Object notExpected, String name); - void todo(boolean condition, String name, String diag); - void todo_is(Object actual, Object expected, String name); - void todo_isnot(Object actual, Object notExpected, String name); - void info(String name, String message); - - // robocop-specific asserts - void ispixel(int actual, int r, int g, int b, String name); - void isnotpixel(int actual, int r, int g, int b, String name); -} diff --git a/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/Driver.java b/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/Driver.java deleted file mode 100644 index 4c8373c5b..000000000 --- a/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/Driver.java +++ /dev/null @@ -1,44 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -package org.mozilla.gecko; - -import android.app.Activity; - -public interface Driver { - /** - * Find the first Element using the given method. - * - * @param activity The activity the element belongs to - * @param id The resource id of the element - * @return The first matching element on the current context, or null if not found. - */ - Element findElement(Activity activity, int id); - - /** - * Sets up scroll handling so that data is received from the extension. - */ - void setupScrollHandling(); - - int getPageHeight(); - int getScrollHeight(); - int getHeight(); - int getGeckoTop(); - int getGeckoLeft(); - int getGeckoWidth(); - int getGeckoHeight(); - - void startFrameRecording(); - int stopFrameRecording(); - - void startCheckerboardRecording(); - float stopCheckerboardRecording(); - - /** - * Get a copy of the painted content region. - * @return A 2-D array of pixels (indexed by y, then x). The pixels - * are in ARGB-8888 format. - */ - PaintedSurface getPaintedSurface(); -} diff --git a/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/Element.java b/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/Element.java deleted file mode 100644 index 97610ff32..000000000 --- a/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/Element.java +++ /dev/null @@ -1,27 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -package org.mozilla.gecko; - -/** - * Element provides access to a specific UI view (android.view.View). - * See also Driver.findElement(). - */ -public interface Element { - - /** Click on the element's view. Returns true on success. */ - boolean click(); - - /** Returns true if the element is currently displayed */ - boolean isDisplayed(); - - /** - * Returns the text currently displayed on the element, or null - * if the text cannot be retrieved. - */ - String getText(); - - /** Returns the view ID */ - Integer getId(); -} diff --git a/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/FennecInstrumentationTestRunner.java b/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/FennecInstrumentationTestRunner.java deleted file mode 100644 index 6bcb4e102..000000000 --- a/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/FennecInstrumentationTestRunner.java +++ /dev/null @@ -1,79 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -package org.mozilla.gecko; - -import android.app.KeyguardManager; -import android.content.Context; -import android.os.Bundle; -import android.os.PowerManager; -import android.test.InstrumentationTestRunner; -import android.util.Log; - -import static android.os.PowerManager.ACQUIRE_CAUSES_WAKEUP; -import static android.os.PowerManager.FULL_WAKE_LOCK; -import static android.os.PowerManager.ON_AFTER_RELEASE; - -public class FennecInstrumentationTestRunner extends InstrumentationTestRunner { - private static Bundle sArguments; - private PowerManager.WakeLock wakeLock; - private KeyguardManager.KeyguardLock keyguardLock; - - @Override - public void onCreate(Bundle arguments) { - sArguments = arguments; - if (sArguments == null) { - Log.e("Robocop", "FennecInstrumentationTestRunner.onCreate got null bundle"); - } - super.onCreate(arguments); - } - - // unfortunately we have to make this static because test classes that don't extend - // from ActivityInstrumentationTestCase2 can't get a reference to this class. - public static Bundle getFennecArguments() { - if (sArguments == null) { - Log.e("Robocop", "FennecInstrumentationTestCase.getFennecArguments returns null bundle"); - } - return sArguments; - } - - @Override - public void onStart() { - final Context context = getContext(); // The Robocop package itself has DISABLE_KEYGUARD and WAKE_LOCK. - if (context != null) { - try { - String name = FennecInstrumentationTestRunner.class.getSimpleName(); - // Unlock the device so that the tests can input keystrokes. - final KeyguardManager keyguard = (KeyguardManager) context.getSystemService(Context.KEYGUARD_SERVICE); - // Deprecated in favour of window flags, which aren't appropriate here. - keyguardLock = keyguard.newKeyguardLock(name); - keyguardLock.disableKeyguard(); - - // Wake up the screen. - final PowerManager power = (PowerManager) context.getSystemService(Context.POWER_SERVICE); - wakeLock = power.newWakeLock(FULL_WAKE_LOCK | ACQUIRE_CAUSES_WAKEUP | ON_AFTER_RELEASE, name); - wakeLock.acquire(); - } catch (SecurityException e) { - Log.w("GeckoInstTestRunner", "Got SecurityException: not disabling keyguard and not taking wakelock."); - } - } else { - Log.w("GeckoInstTestRunner", "Application target context is null: not disabling keyguard and not taking wakelock."); - } - - super.onStart(); - } - - @Override - public void onDestroy() { - super.onDestroy(); - - if (wakeLock != null) { - wakeLock.release(); - } - if (keyguardLock != null) { - // Deprecated in favour of window flags, which aren't appropriate here. - keyguardLock.reenableKeyguard(); - } - } -} diff --git a/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/FennecMochitestAssert.java b/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/FennecMochitestAssert.java deleted file mode 100644 index cb7c3c464..000000000 --- a/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/FennecMochitestAssert.java +++ /dev/null @@ -1,254 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -package org.mozilla.gecko; - -import java.io.PrintWriter; -import java.io.StringWriter; -import java.io.Writer; - -import android.os.SystemClock; - -public class FennecMochitestAssert implements Assert { - // Internal state variables to make logging match up with existing mochitests - private int mPassed = 0; - private int mFailed = 0; - private int mTodo = 0; - - // Used to write the first line of the test file - private boolean mLogStarted = false; - - // Used to write the test-start/test-end log lines - private String mLogTestName = ""; - - // Measure the time it takes to run test case - private long mStartTime = 0; - - // Structured logger - private StructuredLogger mLogger; - - /** Write information to a logfile and logcat */ - public void dumpLog(String message) { - mLogger.info(message); - } - - public void dumpLog(String message, Throwable t) { - Writer sw = new StringWriter(); - PrintWriter pw = new PrintWriter(sw); - t.printStackTrace(pw); - mLogger.error(message + " - " + sw.toString()); - } - - /** Write information to a logfile and logcat */ - static class DumpLogCallback implements StructuredLogger.LoggerCallback { - public void call(String output) { - FennecNativeDriver.log(FennecNativeDriver.LogLevel.INFO, output); - } - } - - - public FennecMochitestAssert() { - mLogger = new StructuredLogger("robocop", new DumpLogCallback()); - } - - /** Set the filename used for dumpLog. */ - public void setLogFile(String filename) { - FennecNativeDriver.setLogFile(filename); - - String message; - if (!mLogStarted) { - mLogger.info("SimpleTest START"); - mLogStarted = true; - } - - if (mLogTestName != "") { - long diff = SystemClock.uptimeMillis() - mStartTime; - mLogger.testEnd(mLogTestName, "OK", "finished in " + diff + "ms"); - } - } - - public void setTestName(String testName) { - String[] nameParts = testName.split("\\."); - mLogTestName = nameParts[nameParts.length - 1]; - mStartTime = SystemClock.uptimeMillis(); - - mLogger.testStart(mLogTestName); - } - - class testInfo { - public boolean mResult; - public String mName; - public String mDiag; - public boolean mTodo; - public boolean mInfo; - public testInfo(boolean r, String n, String d, boolean t, boolean i) { - mResult = r; - mName = n; - mDiag = d; - mTodo = t; - mInfo = i; - } - - } - - /** Used to log a subtest's result. - * test represents the subtest (an assertion). - * passStatus and passExpected are the actual status and the expected status if the assertion is true. - * failStatus and failExpected are the actual status and the expected status otherwise. - */ - private void _logMochitestResult(testInfo test, String passStatus, String passExpected, String failStatus, String failExpected) { - boolean isError = true; - if (test.mResult || test.mTodo) { - isError = false; - } - if (test.mResult) - { - mLogger.testStatus(mLogTestName, test.mName, passStatus, passExpected, test.mDiag); - } else { - mLogger.testStatus(mLogTestName, test.mName, failStatus, failExpected, test.mDiag); - } - - if (test.mInfo) { - // do not count TEST-INFO messages - } else if (test.mTodo) { - mTodo++; - } else if (isError) { - mFailed++; - } else { - mPassed++; - } - if (isError) { - String message = "TEST-UNEXPECTED-" + failStatus + " | " + mLogTestName + " | " - + test.mName + " - " + test.mDiag; - junit.framework.Assert.fail(message); - } - } - - public void endTest() { - String message; - - if (mLogTestName != "") { - long diff = SystemClock.uptimeMillis() - mStartTime; - mLogger.testEnd(mLogTestName, "OK", "finished in " + diff + "ms"); - } - - mLogger.info("TEST-START | Shutdown"); - mLogger.info("Passed: " + Integer.toString(mPassed)); - mLogger.info("Failed: " + Integer.toString(mFailed)); - mLogger.info("Todo: " + Integer.toString(mTodo)); - mLogger.info("SimpleTest FINISHED"); - } - - public void ok(boolean condition, String name, String diag) { - testInfo test = new testInfo(condition, name, diag, false, false); - _logMochitestResult(test, "PASS", "PASS", "FAIL", "PASS"); - } - - public void is(Object actual, Object expected, String name) { - boolean pass = checkObjectsEqual(actual, expected); - ok(pass, name, getEqualString(actual, expected, pass)); - } - - public void isnot(Object actual, Object notExpected, String name) { - boolean pass = checkObjectsNotEqual(actual, notExpected); - ok(pass, name, getNotEqualString(actual, notExpected, pass)); - } - - public void ispixel(int actual, int r, int g, int b, String name) { - int aAlpha = ((actual >> 24) & 0xFF); - int aR = ((actual >> 16) & 0xFF); - int aG = ((actual >> 8) & 0xFF); - int aB = (actual & 0xFF); - boolean pass = checkPixel(actual, r, g, b); - ok(pass, name, "Color rgba(" + aR + "," + aG + "," + aB + "," + aAlpha + ")" + (pass ? " " : " not") + " close enough to expected rgb(" + r + "," + g + "," + b + ")"); - } - - public void isnotpixel(int actual, int r, int g, int b, String name) { - int aAlpha = ((actual >> 24) & 0xFF); - int aR = ((actual >> 16) & 0xFF); - int aG = ((actual >> 8) & 0xFF); - int aB = (actual & 0xFF); - boolean pass = checkPixel(actual, r, g, b); - ok(!pass, name, "Color rgba(" + aR + "," + aG + "," + aB + "," + aAlpha + ")" + (!pass ? " is" : " is not") + " different enough from rgb(" + r + "," + g + "," + b + ")"); - } - - private boolean checkPixel(int actual, int r, int g, int b) { - // When we read GL pixels the GPU has already processed them and they - // are usually off by a little bit. For example a CSS-color pixel of color #64FFF5 - // was turned into #63FFF7 when it came out of glReadPixels. So in order to compare - // against the expected value, we use a little fuzz factor. For the alpha we just - // make sure it is always 0xFF. There is also bug 691354 which crops up every so - // often just to make our lives difficult. However the individual color components - // should never be off by more than 8. - int aAlpha = ((actual >> 24) & 0xFF); - int aR = ((actual >> 16) & 0xFF); - int aG = ((actual >> 8) & 0xFF); - int aB = (actual & 0xFF); - boolean pass = (aAlpha == 0xFF) /* alpha */ - && (Math.abs(aR - r) <= 8) /* red */ - && (Math.abs(aG - g) <= 8) /* green */ - && (Math.abs(aB - b) <= 8); /* blue */ - if (pass) { - return true; - } else { - return false; - } - } - - public void todo(boolean condition, String name, String diag) { - testInfo test = new testInfo(condition, name, diag, true, false); - _logMochitestResult(test, "PASS", "FAIL", "FAIL", "FAIL"); - } - - public void todo_is(Object actual, Object expected, String name) { - boolean pass = checkObjectsEqual(actual, expected); - todo(pass, name, getEqualString(actual, expected, pass)); - } - - public void todo_isnot(Object actual, Object notExpected, String name) { - boolean pass = checkObjectsNotEqual(actual, notExpected); - todo(pass, name, getNotEqualString(actual, notExpected, pass)); - } - - private boolean checkObjectsEqual(Object a, Object b) { - if (a == null || b == null) { - if (a == null && b == null) { - return true; - } - return false; - } else { - return a.equals(b); - } - } - - private String getEqualString(Object a, Object b, boolean pass) { - if (pass) { - return a + " should equal " + b; - } - return "got " + a + ", expected " + b; - } - - private boolean checkObjectsNotEqual(Object a, Object b) { - if (a == null || b == null) { - if ((a == null && b != null) || (a != null && b == null)) { - return true; - } else { - return false; - } - } else { - return !a.equals(b); - } - } - - private String getNotEqualString(Object a, Object b, boolean pass) { - if(pass) { - return a + " should not equal " + b; - } - return "didn't expect " + a + ", but got it"; - } - - public void info(String name, String message) { - mLogger.info(name + " | " + message); - } -} diff --git a/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/FennecNativeActions.java b/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/FennecNativeActions.java deleted file mode 100644 index 7faccdf43..000000000 --- a/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/FennecNativeActions.java +++ /dev/null @@ -1,482 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -package org.mozilla.gecko; - -import java.util.ArrayList; -import java.util.concurrent.BlockingQueue; -import java.util.concurrent.LinkedBlockingQueue; -import java.util.concurrent.TimeUnit; - -import org.json.JSONObject; -import org.mozilla.gecko.FennecNativeDriver.LogLevel; -import org.mozilla.gecko.gfx.LayerView; -import org.mozilla.gecko.gfx.LayerView.DrawListener; -import org.mozilla.gecko.mozglue.GeckoLoader; -import org.mozilla.gecko.sqlite.SQLiteBridge; -import org.mozilla.gecko.util.GeckoEventListener; - -import android.app.Activity; -import android.app.Instrumentation; -import android.database.Cursor; -import android.os.SystemClock; -import android.text.TextUtils; -import android.view.KeyEvent; - -import com.robotium.solo.Solo; - -public class FennecNativeActions implements Actions { - private static final String LOGTAG = "FennecNativeActions"; - - private Solo mSolo; - private Instrumentation mInstr; - private Assert mAsserter; - - public FennecNativeActions(Activity activity, Solo robocop, Instrumentation instrumentation, Assert asserter) { - mSolo = robocop; - mInstr = instrumentation; - mAsserter = asserter; - - GeckoLoader.loadSQLiteLibs(activity, activity.getApplication().getPackageResourcePath()); - } - - class GeckoEventExpecter implements RepeatedEventExpecter { - private static final int MAX_WAIT_MS = 180000; - - private volatile boolean mIsRegistered; - - private final String mGeckoEvent; - private final GeckoEventListener mListener; - - private volatile boolean mEventEverReceived; - private String mEventData; - private BlockingQueue mEventDataQueue; - - GeckoEventExpecter(final String geckoEvent) { - if (TextUtils.isEmpty(geckoEvent)) { - throw new IllegalArgumentException("geckoEvent must not be empty"); - } - - mGeckoEvent = geckoEvent; - mEventDataQueue = new LinkedBlockingQueue(); - - final GeckoEventExpecter expecter = this; - mListener = new GeckoEventListener() { - @Override - public void handleMessage(final String event, final JSONObject message) { - FennecNativeDriver.log(FennecNativeDriver.LogLevel.DEBUG, - "handleMessage called for: " + event + "; expecting: " + mGeckoEvent); - mAsserter.is(event, mGeckoEvent, "Given message occurred for registered event: " + message); - - expecter.notifyOfEvent(message); - } - }; - - EventDispatcher.getInstance().registerGeckoThreadListener(mListener, mGeckoEvent); - mIsRegistered = true; - } - - public void blockForEvent() { - blockForEvent(MAX_WAIT_MS, true); - } - - public void blockForEvent(long millis, boolean failOnTimeout) { - if (!mIsRegistered) { - throw new IllegalStateException("listener not registered"); - } - - try { - mEventData = mEventDataQueue.poll(millis, TimeUnit.MILLISECONDS); - } catch (InterruptedException ie) { - FennecNativeDriver.log(LogLevel.ERROR, ie); - } - if (mEventData == null) { - if (failOnTimeout) { - FennecNativeDriver.logAllStackTraces(FennecNativeDriver.LogLevel.ERROR); - mAsserter.ok(false, "GeckoEventExpecter", - "blockForEvent timeout: "+mGeckoEvent); - } else { - FennecNativeDriver.log(FennecNativeDriver.LogLevel.DEBUG, - "blockForEvent timeout: "+mGeckoEvent); - } - } else { - FennecNativeDriver.log(FennecNativeDriver.LogLevel.DEBUG, - "unblocked on expecter for " + mGeckoEvent); - } - } - - public void blockUntilClear(long millis) { - if (!mIsRegistered) { - throw new IllegalStateException("listener not registered"); - } - if (millis <= 0) { - throw new IllegalArgumentException("millis must be > 0"); - } - - // wait for at least one event - try { - mEventData = mEventDataQueue.poll(MAX_WAIT_MS, TimeUnit.MILLISECONDS); - } catch (InterruptedException ie) { - FennecNativeDriver.log(LogLevel.ERROR, ie); - } - if (mEventData == null) { - FennecNativeDriver.logAllStackTraces(FennecNativeDriver.LogLevel.ERROR); - mAsserter.ok(false, "GeckoEventExpecter", "blockUntilClear timeout"); - return; - } - // now wait for a period of millis where we don't get an event - while (true) { - try { - mEventData = mEventDataQueue.poll(millis, TimeUnit.MILLISECONDS); - } catch (InterruptedException ie) { - FennecNativeDriver.log(LogLevel.INFO, ie); - } - if (mEventData == null) { - // success - break; - } - } - FennecNativeDriver.log(FennecNativeDriver.LogLevel.DEBUG, - "unblocked on expecter for " + mGeckoEvent); - } - - public String blockForEventData() { - blockForEvent(); - return mEventData; - } - - public String blockForEventDataWithTimeout(long millis) { - blockForEvent(millis, false); - return mEventData; - } - - public void unregisterListener() { - if (!mIsRegistered) { - throw new IllegalStateException("listener not registered"); - } - - FennecNativeDriver.log(LogLevel.INFO, - "EventExpecter: no longer listening for " + mGeckoEvent); - - EventDispatcher.getInstance().unregisterGeckoThreadListener(mListener, mGeckoEvent); - mIsRegistered = false; - } - - public boolean eventReceived() { - return mEventEverReceived; - } - - void notifyOfEvent(final JSONObject message) { - FennecNativeDriver.log(FennecNativeDriver.LogLevel.DEBUG, - "received event " + mGeckoEvent); - - mEventEverReceived = true; - - try { - mEventDataQueue.put(message.toString()); - } catch (InterruptedException e) { - FennecNativeDriver.log(LogLevel.ERROR, - "EventExpecter dropped event: " + message.toString(), e); - } - } - } - - public RepeatedEventExpecter expectGeckoEvent(final String geckoEvent) { - FennecNativeDriver.log(FennecNativeDriver.LogLevel.DEBUG, "waiting for " + geckoEvent); - return new GeckoEventExpecter(geckoEvent); - } - - public void sendGeckoEvent(final String geckoEvent, final String data) { - GeckoAppShell.notifyObservers(geckoEvent, data); - } - - public static final class PrefProxy implements PrefsHelper.PrefHandler, PrefWaiter { - public static final int MAX_WAIT_MS = 180000; - - /* package */ final PrefHandlerBase target; - private final String[] expectedPrefs; - private final ArrayList seenPrefs = new ArrayList<>(); - private boolean finished = false; - - /* package */ PrefProxy(PrefHandlerBase target, String[] expectedPrefs, Assert asserter) { - this.target = target; - this.expectedPrefs = expectedPrefs; - target.asserter = asserter; - } - - @Override // PrefsHelper.PrefHandler - public void prefValue(String pref, boolean value) { - target.prefValue(pref, value); - seenPrefs.add(pref); - } - - @Override // PrefsHelper.PrefHandler - public void prefValue(String pref, int value) { - target.prefValue(pref, value); - seenPrefs.add(pref); - } - - @Override // PrefsHelper.PrefHandler - public void prefValue(String pref, String value) { - target.prefValue(pref, value); - seenPrefs.add(pref); - } - - @Override // PrefsHelper.PrefHandler - public synchronized void finish() { - target.finish(); - - for (String pref : expectedPrefs) { - target.asserter.ok(seenPrefs.remove(pref), "Checking pref was seen", pref); - } - target.asserter.ok(seenPrefs.isEmpty(), "Checking unexpected prefs", - TextUtils.join(", ", seenPrefs)); - - finished = true; - this.notifyAll(); - } - - @Override // PrefWaiter - public synchronized boolean isFinished() { - return finished; - } - - @Override // PrefWaiter - public void waitForFinish() { - waitForFinish(MAX_WAIT_MS, /* failOnTimeout */ true); - } - - @Override // PrefWaiter - public synchronized void waitForFinish(long timeoutMillis, boolean failOnTimeout) { - final long startTime = System.nanoTime(); - while (!finished) { - if (System.nanoTime() - startTime - >= timeoutMillis * 1e6 /* ns per ms */) { - final String prefsLog = "expected " + - TextUtils.join(", ", expectedPrefs) + "; got " + - TextUtils.join(", ", seenPrefs.toArray()) + "."; - if (failOnTimeout) { - FennecNativeDriver.logAllStackTraces(FennecNativeDriver.LogLevel.ERROR); - target.asserter.ok(false, "Timeout waiting for pref", prefsLog); - } else { - FennecNativeDriver.log(FennecNativeDriver.LogLevel.DEBUG, - "Pref timeout (" + prefsLog + ")"); - } - break; - } - try { - this.wait(1000); // Wait for 1 second at a time. - } catch (final InterruptedException e) { - // Attempt waiting again. - } - } - finished = false; - } - } - - @Override // Actions - public PrefWaiter getPrefs(String[] prefNames, PrefHandlerBase handler) { - final PrefProxy proxy = new PrefProxy(handler, prefNames, mAsserter); - PrefsHelper.getPrefs(prefNames, proxy); - return proxy; - } - - @Override // Actions - public void setPref(String pref, Object value, boolean flush) { - PrefsHelper.setPref(pref, value, flush); - } - - @Override // Actions - public PrefWaiter addPrefsObserver(String[] prefNames, PrefHandlerBase handler) { - final PrefProxy proxy = new PrefProxy(handler, prefNames, mAsserter); - PrefsHelper.addObserver(prefNames, proxy); - return proxy; - } - - @Override // Actions - public void removePrefsObserver(PrefWaiter proxy) { - PrefsHelper.removeObserver((PrefProxy) proxy); - } - - class PaintExpecter implements RepeatedEventExpecter { - private static final int MAX_WAIT_MS = 90000; - - private boolean mPaintDone; - private boolean mListening; - - private final LayerView mLayerView; - private final DrawListener mDrawListener; - - PaintExpecter() { - final PaintExpecter expecter = this; - mLayerView = GeckoAppShell.getLayerView(); - mDrawListener = new DrawListener() { - @Override - public void drawFinished() { - FennecNativeDriver.log(FennecNativeDriver.LogLevel.DEBUG, - "Received drawFinished notification"); - expecter.notifyOfEvent(); - } - }; - mLayerView.addDrawListener(mDrawListener); - mListening = true; - } - - private synchronized void notifyOfEvent() { - mPaintDone = true; - this.notifyAll(); - } - - public synchronized void blockForEvent(long millis, boolean failOnTimeout) { - if (!mListening) { - throw new IllegalStateException("draw listener not registered"); - } - long startTime = SystemClock.uptimeMillis(); - long endTime = 0; - while (!mPaintDone) { - try { - this.wait(millis); - } catch (InterruptedException ie) { - FennecNativeDriver.log(LogLevel.ERROR, ie); - break; - } - endTime = SystemClock.uptimeMillis(); - if (!mPaintDone && (endTime - startTime >= millis)) { - if (failOnTimeout) { - FennecNativeDriver.logAllStackTraces(FennecNativeDriver.LogLevel.ERROR); - mAsserter.ok(false, "PaintExpecter", "blockForEvent timeout"); - } - return; - } - } - } - - public synchronized void blockForEvent() { - blockForEvent(MAX_WAIT_MS, true); - } - - public synchronized String blockForEventData() { - blockForEvent(); - return null; - } - - public synchronized String blockForEventDataWithTimeout(long millis) { - blockForEvent(millis, false); - return null; - } - - public synchronized boolean eventReceived() { - return mPaintDone; - } - - public synchronized void blockUntilClear(long millis) { - if (!mListening) { - throw new IllegalStateException("draw listener not registered"); - } - if (millis <= 0) { - throw new IllegalArgumentException("millis must be > 0"); - } - // wait for at least one event - long startTime = SystemClock.uptimeMillis(); - long endTime = 0; - while (!mPaintDone) { - try { - this.wait(MAX_WAIT_MS); - } catch (InterruptedException ie) { - FennecNativeDriver.log(LogLevel.ERROR, ie); - break; - } - endTime = SystemClock.uptimeMillis(); - if (!mPaintDone && (endTime - startTime >= MAX_WAIT_MS)) { - FennecNativeDriver.logAllStackTraces(FennecNativeDriver.LogLevel.ERROR); - mAsserter.ok(false, "PaintExpecter", "blockUtilClear timeout"); - return; - } - } - // now wait for a period of millis where we don't get an event - startTime = SystemClock.uptimeMillis(); - while (true) { - try { - this.wait(millis); - } catch (InterruptedException ie) { - FennecNativeDriver.log(LogLevel.ERROR, ie); - break; - } - endTime = SystemClock.uptimeMillis(); - if (endTime - startTime >= millis) { - // success - break; - } - - // we got a notify() before we could wait long enough, so we need to start over - // Note, moving the goal post might have us race against a "drawFinished" flood - startTime = endTime; - } - } - - public synchronized void unregisterListener() { - if (!mListening) { - throw new IllegalStateException("listener not registered"); - } - - FennecNativeDriver.log(LogLevel.INFO, - "PaintExpecter: no longer listening for events"); - mLayerView.removeDrawListener(mDrawListener); - mListening = false; - } - } - - public RepeatedEventExpecter expectPaint() { - return new PaintExpecter(); - } - - public void sendSpecialKey(SpecialKey button) { - switch(button) { - case DOWN: - sendKeyCode(Solo.DOWN); - break; - case UP: - sendKeyCode(Solo.UP); - break; - case LEFT: - sendKeyCode(Solo.LEFT); - break; - case RIGHT: - sendKeyCode(Solo.RIGHT); - break; - case ENTER: - sendKeyCode(Solo.ENTER); - break; - case MENU: - sendKeyCode(Solo.MENU); - break; - case DELETE: - sendKeyCode(Solo.DELETE); - break; - default: - mAsserter.ok(false, "sendSpecialKey", "Unknown SpecialKey " + button); - break; - } - } - - public void sendKeyCode(int keyCode) { - if (keyCode <= 0 || keyCode > KeyEvent.getMaxKeyCode()) { - mAsserter.ok(false, "sendKeyCode", "Unknown keyCode " + keyCode); - } - mSolo.sendKey(keyCode); - } - - @Override - public void sendKeys(String input) { - mInstr.sendStringSync(input); - } - - public void drag(int startingX, int endingX, int startingY, int endingY) { - mSolo.drag(startingX, endingX, startingY, endingY, 10); - } - - public Cursor querySql(final String dbPath, final String sql) { - return new SQLiteBridge(dbPath).rawQuery(sql, null); - } -} diff --git a/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/FennecNativeDriver.java b/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/FennecNativeDriver.java deleted file mode 100644 index 3931b7e20..000000000 --- a/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/FennecNativeDriver.java +++ /dev/null @@ -1,392 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -package org.mozilla.gecko; - -import java.io.BufferedOutputStream; -import java.io.BufferedReader; -import java.io.DataOutputStream; -import java.io.File; -import java.io.FileOutputStream; -import java.io.FileReader; -import java.io.FileWriter; -import java.io.IOException; -import java.io.PrintWriter; -import java.nio.IntBuffer; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import org.json.JSONException; -import org.json.JSONObject; -import org.mozilla.gecko.gfx.LayerView; -import org.mozilla.gecko.gfx.PanningPerfAPI; -import org.mozilla.gecko.util.GeckoEventListener; - -import android.app.Activity; -import android.util.Log; -import android.view.View; - -import com.robotium.solo.Solo; - -public class FennecNativeDriver implements Driver { - private static final int FRAME_TIME_THRESHOLD = 25; // allow 25ms per frame (40fps) - - private final Activity mActivity; - private final Solo mSolo; - private final String mRootPath; - - private static String mLogFile; - private static LogLevel mLogLevel = LogLevel.INFO; - - public enum LogLevel { - DEBUG(1), - INFO(2), - WARN(3), - ERROR(4); - - private final int mValue; - LogLevel(int value) { - mValue = value; - } - public boolean isEnabled(LogLevel configuredLevel) { - return mValue >= configuredLevel.getValue(); - } - private int getValue() { - return mValue; - } - } - - public FennecNativeDriver(Activity activity, Solo robocop, String rootPath) { - mActivity = activity; - mSolo = robocop; - mRootPath = rootPath; - } - - //Information on the location of the Gecko Frame. - private boolean mGeckoInfo = false; - private int mGeckoTop = 100; - private int mGeckoLeft = 0; - private int mGeckoHeight= 700; - private int mGeckoWidth = 1024; - - private void getGeckoInfo() { - View geckoLayout = mActivity.findViewById(R.id.gecko_layout); - if (geckoLayout != null) { - int[] pos = new int[2]; - geckoLayout.getLocationOnScreen(pos); - mGeckoTop = pos[1]; - mGeckoLeft = pos[0]; - mGeckoWidth = geckoLayout.getWidth(); - mGeckoHeight = geckoLayout.getHeight(); - mGeckoInfo = true; - } else { - throw new RoboCopException("Unable to find view gecko_layout"); - } - } - - @Override - public int getGeckoTop() { - if (!mGeckoInfo) { - getGeckoInfo(); - } - return mGeckoTop; - } - - @Override - public int getGeckoLeft() { - if (!mGeckoInfo) { - getGeckoInfo(); - } - return mGeckoLeft; - } - - @Override - public int getGeckoHeight() { - if (!mGeckoInfo) { - getGeckoInfo(); - } - return mGeckoHeight; - } - - @Override - public int getGeckoWidth() { - if (!mGeckoInfo) { - getGeckoInfo(); - } - return mGeckoWidth; - } - - /** Find the element with given id. - * - * @return An Element representing the view, or null if the view is not found. - */ - @Override - public Element findElement(Activity activity, int id) { - return new FennecNativeElement(id, activity); - } - - @Override - public void startFrameRecording() { - PanningPerfAPI.startFrameTimeRecording(); - } - - @Override - public int stopFrameRecording() { - final List frames = PanningPerfAPI.stopFrameTimeRecording(); - int badness = 0; - for (int i = 1; i < frames.size(); i++) { - long frameTime = frames.get(i) - frames.get(i - 1); - int delay = (int)(frameTime - FRAME_TIME_THRESHOLD); - // for each frame we miss, add the square of the delay. This - // makes large delays much worse than small delays. - if (delay > 0) { - badness += delay * delay; - } - } - - // Don't do any averaging of the numbers because really we want to - // know how bad the jank was at its worst - return badness; - } - - @Override - public void startCheckerboardRecording() { - PanningPerfAPI.startCheckerboardRecording(); - } - - @Override - public float stopCheckerboardRecording() { - final List checkerboard = PanningPerfAPI.stopCheckerboardRecording(); - float total = 0; - for (float val : checkerboard) { - total += val; - } - return total * 100.0f; - } - - private LayerView getSurfaceView() { - final LayerView layerView = mSolo.getView(LayerView.class, 0); - - if (layerView == null) { - log(LogLevel.WARN, "getSurfaceView could not find LayerView"); - for (final View v : mSolo.getViews()) { - log(LogLevel.WARN, " View: " + v); - } - } - return layerView; - } - - @Override - public PaintedSurface getPaintedSurface() { - final LayerView view = getSurfaceView(); - if (view == null) { - return null; - } - - final IntBuffer pixelBuffer = view.getPixels(); - - // now we need to (1) flip the image, because GL likes to do things up-side-down, - // and (2) rearrange the bits from AGBR-8888 to ARGB-8888. - int w = view.getWidth(); - int h = view.getHeight(); - pixelBuffer.position(0); - String mapFile = mRootPath + "/pixels.map"; - - FileOutputStream fos = null; - BufferedOutputStream bos = null; - DataOutputStream dos = null; - try { - fos = new FileOutputStream(mapFile); - bos = new BufferedOutputStream(fos); - dos = new DataOutputStream(bos); - - for (int y = h - 1; y >= 0; y--) { - for (int x = 0; x < w; x++) { - int agbr = pixelBuffer.get(); - dos.writeInt((agbr & 0xFF00FF00) | ((agbr >> 16) & 0x000000FF) | ((agbr << 16) & 0x00FF0000)); - } - } - } catch (IOException e) { - throw new RoboCopException("exception with pixel writer on file: " + mapFile); - } finally { - try { - if (dos != null) { - dos.flush(); - dos.close(); - } - // closing dos automatically closes bos - if (fos != null) { - fos.flush(); - fos.close(); - } - } catch (IOException e) { - log(LogLevel.ERROR, e); - throw new RoboCopException("exception closing pixel writer on file: " + mapFile); - } - } - return new PaintedSurface(mapFile, w, h); - } - - public int mHeight=0; - public int mScrollHeight=0; - public int mPageHeight=10; - - @Override - public int getScrollHeight() { - return mScrollHeight; - } - @Override - public int getPageHeight() { - return mPageHeight; - } - @Override - public int getHeight() { - return mHeight; - } - - @Override - public void setupScrollHandling() { - GeckoApp.getEventDispatcher().registerGeckoThreadListener(new GeckoEventListener() { - @Override - public void handleMessage(final String event, final JSONObject message) { - try { - mScrollHeight = message.getInt("y"); - mHeight = message.getInt("cheight"); - // We don't want a height of 0. That means it's a bad response. - if (mHeight > 0) { - mPageHeight = message.getInt("height"); - } - } catch (JSONException e) { - FennecNativeDriver.log(FennecNativeDriver.LogLevel.WARN, - "WARNING: ScrollReceived, but message does not contain " + - "expected fields: " + e); - } - } - }, "robocop:scroll"); - } - - /** - * Takes a filename, loads the file, and returns a string version of the entire file. - */ - public static String getFile(String filename) - { - StringBuilder text = new StringBuilder(); - - BufferedReader br = null; - try { - br = new BufferedReader(new FileReader(filename)); - String line; - - while ((line = br.readLine()) != null) { - text.append(line); - text.append('\n'); - } - } catch (IOException e) { - log(LogLevel.ERROR, e); - } finally { - try { - if (br != null) { - br.close(); - } - } catch (IOException e) { - } - } - return text.toString(); - } - - /** - * Takes a string of "key=value" pairs split by \n and creates a hash table. - */ - public static Map convertTextToTable(String data) - { - HashMap retVal = new HashMap(); - - String[] lines = data.split("\n"); - for (int i = 0; i < lines.length; i++) { - String[] parts = lines[i].split("=", 2); - retVal.put(parts[0].trim(), parts[1].trim()); - } - return retVal; - } - - public static void logAllStackTraces(LogLevel level) { - StringBuffer sb = new StringBuffer(); - sb.append("Dumping ALL the threads!\n"); - Map allStacks = Thread.getAllStackTraces(); - for (Thread t : allStacks.keySet()) { - sb.append(t.toString()).append('\n'); - for (StackTraceElement ste : allStacks.get(t)) { - sb.append(ste.toString()).append('\n'); - } - sb.append('\n'); - } - log(level, sb.toString()); - } - - /** - * Set the filename used for logging. If the file already exists, delete it - * as a safe-guard against accidentally appending to an old log file. - */ - public static void setLogFile(String filename) { - mLogFile = filename; - File file = new File(mLogFile); - if (file.exists()) { - file.delete(); - } - } - - public static void setLogLevel(LogLevel level) { - mLogLevel = level; - } - - public static void log(LogLevel level, String message) { - log(level, message, null); - } - - public static void log(LogLevel level, Throwable t) { - log(level, null, t); - } - - public static void log(LogLevel level, String message, Throwable t) { - if (mLogFile == null) { - throw new RuntimeException("No log file specified!"); - } - - if (level.isEnabled(mLogLevel)) { - PrintWriter pw = null; - try { - pw = new PrintWriter(new FileWriter(mLogFile, true)); - if (message != null) { - pw.println(message); - } - if (t != null) { - t.printStackTrace(pw); - } - } catch (IOException ioe) { - Log.e("Robocop", "exception with file writer on: " + mLogFile); - } finally { - if (pw != null) { - pw.close(); - } - } - - // PrintWriter doesn't throw IOE but sets an error flag instead, - // so check for that - if (pw != null && pw.checkError()) { - Log.e("Robocop", "exception with file writer on: " + mLogFile); - } - } - - if (level == LogLevel.INFO) { - Log.i("Robocop", message, t); - } else if (level == LogLevel.DEBUG) { - Log.d("Robocop", message, t); - } else if (level == LogLevel.WARN) { - Log.w("Robocop", message, t); - } else if (level == LogLevel.ERROR) { - Log.e("Robocop", message, t); - } - } -} diff --git a/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/FennecNativeElement.java b/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/FennecNativeElement.java deleted file mode 100644 index 2a24344fd..000000000 --- a/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/FennecNativeElement.java +++ /dev/null @@ -1,116 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -package org.mozilla.gecko; - -import android.app.Activity; -import android.view.View; -import android.view.ViewGroup; -import android.widget.EditText; -import android.widget.TextSwitcher; -import android.widget.TextView; - -public class FennecNativeElement implements Element { - private final Activity mActivity; - private final Integer mId; - private final String mName; - - public FennecNativeElement(Integer id, Activity activity) { - mId = id; - mActivity = activity; - mName = activity.getResources().getResourceName(id); - } - - @Override - public Integer getId() { - return mId; - } - - private boolean mClickSuccess; - - @Override - public boolean click() { - mClickSuccess = false; - RobocopUtils.runOnUiThreadSync(mActivity, - new Runnable() { - @Override - public void run() { - View view = mActivity.findViewById(mId); - if (view != null) { - if (view.performClick()) { - mClickSuccess = true; - } else { - FennecNativeDriver.log(FennecNativeDriver.LogLevel.WARN, - "Robocop called click on an element with no listener " + mId + " " + mName); - } - } else { - FennecNativeDriver.log(FennecNativeDriver.LogLevel.ERROR, - "click: unable to find view " + mId + " " + mName); - } - } - }); - return mClickSuccess; - } - - private Object mText; - - @Override - public String getText() { - mText = null; - RobocopUtils.runOnUiThreadSync(mActivity, - new Runnable() { - @Override - public void run() { - View v = mActivity.findViewById(mId); - if (v instanceof EditText) { - EditText et = (EditText)v; - mText = et.getEditableText(); - } else if (v instanceof TextSwitcher) { - TextSwitcher ts = (TextSwitcher)v; - mText = ((TextView)ts.getCurrentView()).getText(); - } else if (v instanceof ViewGroup) { - ViewGroup vg = (ViewGroup)v; - for (int i = 0; i < vg.getChildCount(); i++) { - if (vg.getChildAt(i) instanceof TextView) { - mText = ((TextView)vg.getChildAt(i)).getText(); - } - } - } else if (v instanceof TextView) { - mText = ((TextView)v).getText(); - } else if (v == null) { - FennecNativeDriver.log(FennecNativeDriver.LogLevel.ERROR, - "getText: unable to find view " + mId + " " + mName); - } else { - FennecNativeDriver.log(FennecNativeDriver.LogLevel.ERROR, - "getText: unhandled type for view " + mId + " " + mName); - } - } // end of run() method definition - } // end of anonymous Runnable object instantiation - ); - if (mText == null) { - FennecNativeDriver.log(FennecNativeDriver.LogLevel.WARN, - "getText: Text is null for view " + mId + " " + mName); - return null; - } - return mText.toString(); - } - - private boolean mDisplayed; - - @Override - public boolean isDisplayed() { - mDisplayed = false; - RobocopUtils.runOnUiThreadSync(mActivity, - new Runnable() { - @Override - public void run() { - View view = mActivity.findViewById(mId); - if (view != null) { - mDisplayed = true; - } - } - }); - return mDisplayed; - } -} diff --git a/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/FennecTalosAssert.java b/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/FennecTalosAssert.java deleted file mode 100644 index 862f66777..000000000 --- a/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/FennecTalosAssert.java +++ /dev/null @@ -1,74 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -package org.mozilla.gecko; - - -public class FennecTalosAssert implements Assert { - - public FennecTalosAssert() { } - - /** - * Write information to a logfile and logcat - */ - public void dumpLog(String message) { - FennecNativeDriver.log(FennecNativeDriver.LogLevel.INFO, message); - } - - /** Write information to a logfile and logcat */ - public void dumpLog(String message, Throwable t) { - FennecNativeDriver.log(FennecNativeDriver.LogLevel.INFO, message, t); - } - - /** - * Set the filename used for dumpLog. - */ - public void setLogFile(String filename) { - FennecNativeDriver.setLogFile(filename); - } - - public void setTestName(String testName) { } - - public void endTest() { } - - public void ok(boolean condition, String name, String diag) { - if (!condition) { - dumpLog("__FAIL" + name + ": " + diag + "__FAIL"); - } - } - - public void is(Object actual, Object expected, String name) { - boolean pass = (actual == null ? expected == null : actual.equals(expected)); - ok(pass, name, "got " + actual + ", expected " + expected); - } - - public void isnot(Object actual, Object notExpected, String name) { - boolean fail = (actual == null ? notExpected == null : actual.equals(notExpected)); - ok(!fail, name, "got " + actual + ", expected not " + notExpected); - } - - public void ispixel(int actual, int r, int g, int b, String name) { - throw new UnsupportedOperationException(); - } - - public void isnotpixel(int actual, int r, int g, int b, String name) { - throw new UnsupportedOperationException(); - } - - public void todo(boolean condition, String name, String diag) { - throw new UnsupportedOperationException(); - } - - public void todo_is(Object actual, Object expected, String name) { - throw new UnsupportedOperationException(); - } - - public void todo_isnot(Object actual, Object notExpected, String name) { - throw new UnsupportedOperationException(); - } - - public void info(String name, String message) { - dumpLog(name + ": " + message); - } -} diff --git a/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/LaunchFennecWithConfigurationActivity.java b/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/LaunchFennecWithConfigurationActivity.java deleted file mode 100644 index 208b2c7bd..000000000 --- a/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/LaunchFennecWithConfigurationActivity.java +++ /dev/null @@ -1,40 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -package org.mozilla.gecko; - -import java.util.Map; - -import org.mozilla.gecko.tests.BaseRobocopTest; - -import android.app.Activity; -import android.content.Intent; -import android.os.Bundle; - -/** - * An Activity that extracts Robocop settings from robotium.config, launches - * Fennec with the Robocop testing parameters, and finishes itself. - *

- * This is intended to be used by local testers using |mach robocop --serve|. - */ -public class LaunchFennecWithConfigurationActivity extends Activity { - @Override - public void onCreate(Bundle arguments) { - super.onCreate(arguments); - } - - @Override - public void onResume() { - super.onResume(); - - final String configFile = FennecNativeDriver.getFile(BaseRobocopTest.DEFAULT_ROOT_PATH + "/robotium.config"); - final Map config = FennecNativeDriver.convertTextToTable(configFile); - final Intent intent = BaseRobocopTest.createActivityIntent(config); - - intent.setClassName(AppConstants.ANDROID_PACKAGE_NAME, AppConstants.MOZ_ANDROID_BROWSER_INTENT_CLASS); - - this.finish(); - this.startActivity(intent); - } -} diff --git a/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/PaintedSurface.java b/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/PaintedSurface.java deleted file mode 100644 index 17d77b758..000000000 --- a/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/PaintedSurface.java +++ /dev/null @@ -1,105 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this file, - * You can obtain one at http://mozilla.org/MPL/2.0/. */ - -package org.mozilla.gecko; - -import java.io.ByteArrayOutputStream; -import java.io.File; -import java.io.FileInputStream; -import java.nio.MappedByteBuffer; -import java.nio.channels.FileChannel; - -import android.graphics.Bitmap; -import android.util.Base64; -import android.util.Base64OutputStream; - -public class PaintedSurface { - private String mFileName; - private int mWidth; - private int mHeight; - private FileInputStream mPixelFile; - private MappedByteBuffer mPixelBuffer; - - public PaintedSurface(String filename, int width, int height) { - mFileName = filename; - mWidth = width; - mHeight = height; - - try { - File f = new File(filename); - int pixelSize = (int)f.length(); - - mPixelFile = new FileInputStream(filename); - mPixelBuffer = mPixelFile.getChannel().map(FileChannel.MapMode.READ_ONLY, 0, pixelSize); - } catch (java.io.FileNotFoundException e) { - FennecNativeDriver.log(FennecNativeDriver.LogLevel.ERROR, e); - } catch (java.io.IOException e) { - FennecNativeDriver.log(FennecNativeDriver.LogLevel.ERROR, e); - } - } - - public final int getWidth() { - return mWidth; - } - - public final int getHeight() { - return mHeight; - } - - private int pixelAtIndex(int index) { - int b1 = mPixelBuffer.get(index) & 0xFF; - int b2 = mPixelBuffer.get(index + 1) & 0xFF; - int b3 = mPixelBuffer.get(index + 2) & 0xFF; - int b4 = mPixelBuffer.get(index + 3) & 0xFF; - int value = (b1 << 24) + (b2 << 16) + (b3 << 8) + (b4 << 0); - return value; - } - - public final int getPixelAt(int x, int y) { - if (mPixelBuffer == null) { - throw new RoboCopException("Trying to access PaintedSurface with no active PixelBuffer"); - } - - if (x >= mWidth || x < 0) { - throw new RoboCopException("Trying to access PaintedSurface with invalid x value"); - } - - if (y >= mHeight || y < 0) { - throw new RoboCopException("Trying to access PaintedSurface with invalid y value"); - } - - // The rows are reversed so row 0 is at the end and we start with the last row. - // This is why we do mHeight-y; - int index = (x + ((mHeight - y - 1) * mWidth)) * 4; - return pixelAtIndex(index); - } - - public final String asDataUri() { - try { - Bitmap bm = Bitmap.createBitmap(mWidth, mHeight, Bitmap.Config.ARGB_8888); - for (int y = 0; y < mHeight; y++) { - for (int x = 0; x < mWidth; x++) { - int index = (x + ((mHeight - y - 1) * mWidth)) * 4; - bm.setPixel(x, y, pixelAtIndex(index)); - } - } - ByteArrayOutputStream out = new ByteArrayOutputStream(); - out.write("data:image/png;base64,".getBytes()); - Base64OutputStream b64 = new Base64OutputStream(out, Base64.NO_WRAP); - bm.compress(Bitmap.CompressFormat.PNG, 100, b64); - return new String(out.toByteArray()); - } catch (Exception e) { - FennecNativeDriver.log(FennecNativeDriver.LogLevel.ERROR, e); - throw new RoboCopException("Unable to convert surface to a PNG data:uri"); - } - } - - public void close() { - try { - mPixelFile.close(); - } catch (Exception e) { - FennecNativeDriver.log(FennecNativeDriver.LogLevel.DEBUG, e); - } - } -} diff --git a/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/RoboCopException.java b/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/RoboCopException.java deleted file mode 100644 index 420df818d..000000000 --- a/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/RoboCopException.java +++ /dev/null @@ -1,24 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -package org.mozilla.gecko; - -public class RoboCopException extends RuntimeException { - - public RoboCopException() { - super(); - } - - public RoboCopException(String message) { - super(message); - } - - public RoboCopException(Throwable cause) { - super(cause); - } - - public RoboCopException(String message, Throwable cause) { - super(message, cause); - } -} diff --git a/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/RobocopShare1.java b/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/RobocopShare1.java deleted file mode 100644 index 80ab3396c..000000000 --- a/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/RobocopShare1.java +++ /dev/null @@ -1,17 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -package org.mozilla.gecko; - -import android.os.Bundle; -import android.support.v4.app.FragmentActivity; - -public class RobocopShare1 extends FragmentActivity { - private static Bundle sArguments; - - @Override - public void onCreate(Bundle arguments) { - super.onCreate(arguments); - } -} diff --git a/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/RobocopShare2.java b/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/RobocopShare2.java deleted file mode 100644 index 4874dffb7..000000000 --- a/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/RobocopShare2.java +++ /dev/null @@ -1,17 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -package org.mozilla.gecko; - -import android.os.Bundle; -import android.support.v4.app.FragmentActivity; - -public class RobocopShare2 extends FragmentActivity { - private static Bundle sArguments; - - @Override - public void onCreate(Bundle arguments) { - super.onCreate(arguments); - } -} diff --git a/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/RobocopUtils.java b/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/RobocopUtils.java deleted file mode 100644 index 7a33abfa6..000000000 --- a/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/RobocopUtils.java +++ /dev/null @@ -1,58 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -package org.mozilla.gecko; - -import java.util.concurrent.atomic.AtomicBoolean; - -import android.app.Activity; - -public final class RobocopUtils { - private static final int MAX_WAIT_MS = 20000; - - private RobocopUtils() {} - - public static void runOnUiThreadSync(Activity activity, final Runnable runnable) { - final AtomicBoolean sentinel = new AtomicBoolean(false); - - // On the UI thread, run the Runnable, then set sentinel to true and wake this thread. - activity.runOnUiThread( - new Runnable() { - @Override - public void run() { - runnable.run(); - - synchronized (sentinel) { - sentinel.set(true); - sentinel.notifyAll(); - } - } - } - ); - - - // Suspend this thread, until the other thread completes its work or until a timeout is - // reached. - long startTimestamp = System.currentTimeMillis(); - - synchronized (sentinel) { - while (!sentinel.get()) { - try { - sentinel.wait(MAX_WAIT_MS); - } catch (InterruptedException e) { - FennecNativeDriver.log(FennecNativeDriver.LogLevel.ERROR, e); - } - - // Abort if we woke up due to timeout (instead of spuriously). - if (System.currentTimeMillis() - startTimestamp >= MAX_WAIT_MS) { - FennecNativeDriver.log(FennecNativeDriver.LogLevel.ERROR, - "time-out waiting for UI thread"); - FennecNativeDriver.logAllStackTraces(FennecNativeDriver.LogLevel.ERROR); - - return; - } - } - } - } -} diff --git a/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/StructuredLogger.java b/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/StructuredLogger.java deleted file mode 100644 index 87d5a3c25..000000000 --- a/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/StructuredLogger.java +++ /dev/null @@ -1,188 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -package org.mozilla.gecko; - -import java.util.HashSet; -import java.util.Arrays; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import org.json.JSONObject; - -// This implements the structured logging API described here: http://mozbase.readthedocs.org/en/latest/mozlog_structured.html -public class StructuredLogger { - private final static HashSet validTestStatus = new HashSet(Arrays.asList("PASS", "FAIL", "TIMEOUT", "NOTRUN", "ASSERT")); - private final static HashSet validTestEnd = new HashSet(Arrays.asList("PASS", "FAIL", "OK", "ERROR", "TIMEOUT", - "CRASH", "ASSERT", "SKIP")); - - private String mName; - private String mComponent; - private LoggerCallback mCallback; - - static public interface LoggerCallback { - public void call(String output); - } - - /* A default logger callback that prints the JSON output to stdout. - * This is not to be used in robocop as we write to a log file. */ - static class StandardLoggerCallback implements LoggerCallback { - public void call(String output) { - System.out.println(output); - } - } - - public StructuredLogger(String name, String component, LoggerCallback callback) { - mName = name; - mComponent = component; - mCallback = callback; - } - - public StructuredLogger(String name, String component) { - this(name, component, new StandardLoggerCallback()); - } - - public StructuredLogger(String name, LoggerCallback callback) { - this(name, null, callback); - } - - public StructuredLogger(String name) { - this(name, null, new StandardLoggerCallback()); - } - - public void suiteStart(List tests, Map runInfo) { - HashMap data = new HashMap(); - data.put("tests", tests); - if (runInfo != null) { - data.put("run_info", runInfo); - } - this.logData("suite_start", data); - } - - public void suiteStart(List tests) { - this.suiteStart(tests, null); - } - - public void suiteEnd() { - this.logData("suite_end"); - } - - public void testStart(String test) { - HashMap data = new HashMap(); - data.put("test", test); - this.logData("test_start", data); - } - - public void testStatus(String test, String subtest, String status, String expected, String message) { - status = status.toUpperCase(); - if (!StructuredLogger.validTestStatus.contains(status)) { - throw new IllegalArgumentException("Unrecognized status: " + status); - } - - HashMap data = new HashMap(); - data.put("test", test); - data.put("subtest", subtest); - data.put("status", status); - - if (message != null) { - data.put("message", message); - } - if (!expected.equals(status)) { - data.put("expected", expected); - } - - this.logData("test_status", data); - } - - public void testStatus(String test, String subtest, String status, String message) { - this.testStatus(test, subtest, status, "PASS", message); - } - - public void testEnd(String test, String status, String expected, String message, Map extra) { - status = status.toUpperCase(); - if (!StructuredLogger.validTestEnd.contains(status)) { - throw new IllegalArgumentException("Unrecognized status: " + status); - } - - HashMap data = new HashMap(); - data.put("test", test); - data.put("status", status); - - if (message != null) { - data.put("message", message); - } - if (extra != null) { - data.put("extra", extra); - } - if (!expected.equals(status) && !status.equals("SKIP")) { - data.put("expected", expected); - } - - this.logData("test_end", data); - } - - public void testEnd(String test, String status, String expected, String message) { - this.testEnd(test, status, expected, message, null); - } - - public void testEnd(String test, String status, String message) { - this.testEnd(test, status, "OK", message, null); - } - - - public void debug(String message) { - this.log("debug", message); - } - - public void info(String message) { - this.log("info", message); - } - - public void warning(String message) { - this.log("warning", message); - } - - public void error(String message) { - this.log("error", message); - } - - public void critical(String message) { - this.log("critical", message); - } - - private void log(String level, String message) { - HashMap data = new HashMap(); - data.put("message", message); - data.put("level", level); - this.logData("log", data); - } - - private HashMap makeLogData(String action, Map data) { - HashMap allData = new HashMap(); - allData.put("action", action); - allData.put("time", System.currentTimeMillis()); - allData.put("thread", JSONObject.NULL); - allData.put("pid", JSONObject.NULL); - allData.put("source", mName); - if (mComponent != null) { - allData.put("component", mComponent); - } - - allData.putAll(data); - - return allData; - } - - private void logData(String action, Map data) { - HashMap logData = this.makeLogData(action, data); - JSONObject jsonObject = new JSONObject(logData); - mCallback.call(jsonObject.toString()); - } - - private void logData(String action) { - this.logData(action, new HashMap()); - } - -} diff --git a/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/AboutHomeTest.java b/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/AboutHomeTest.java deleted file mode 100644 index cadb5df93..000000000 --- a/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/AboutHomeTest.java +++ /dev/null @@ -1,252 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -package org.mozilla.gecko.tests; - -import java.util.ArrayList; - -import org.mozilla.gecko.Actions; -import org.mozilla.gecko.home.HomePager; - -import android.support.v4.view.ViewPager; -import android.support.v7.widget.RecyclerView; -import android.text.TextUtils; -import android.view.View; -import android.view.ViewGroup; -import android.widget.ListAdapter; -import android.widget.ListView; -import android.widget.TabWidget; -import android.widget.TextView; - -import com.robotium.solo.Condition; - -/** - * This class is an extension of BaseTest that helps with interaction with about:home - * This class contains methods that access the different tabs from about:home, methods that get information like history and bookmarks from the database, edit and remove bookmarks and history items - * The purpose of this class is to collect all the logically connected methods that deal with about:home - * To use any of these methods in your test make sure it extends AboutHomeTest instead of BaseTest - */ -abstract class AboutHomeTest extends PixelTest { - protected enum AboutHomeTabs { - RECENT_TABS, - HISTORY, - TOP_SITES, - BOOKMARKS, - }; - - private final ArrayList aboutHomeTabs = new ArrayList() {{ - add("TOP_SITES"); - add("BOOKMARKS"); - }}; - - - @Override - public void setUp() throws Exception { - super.setUp(); - - if (aboutHomeTabs.size() < 4) { - // Update it for tablets vs. phones. - if (mDevice.type.equals("phone")) { - aboutHomeTabs.add(0, AboutHomeTabs.HISTORY.toString()); - aboutHomeTabs.add(0, AboutHomeTabs.RECENT_TABS.toString()); - } else { - aboutHomeTabs.add(AboutHomeTabs.HISTORY.toString()); - aboutHomeTabs.add(AboutHomeTabs.RECENT_TABS.toString()); - } - } - } - - /** - * FIXME: Write new versions of these methods and update their consumers to use the new about:home pages. - */ - protected ListView getHistoryList(String waitText, int expectedChildCount) { - return null; - } - protected ListView getHistoryList(String waitText) { - return null; - } - - // Returns true if the bookmark is displayed in the bookmarks tab, false otherwise - does not check in folders - protected void isBookmarkDisplayed(final String url) { - boolean isCorrect = waitForCondition(new Condition() { - @Override - public boolean isSatisfied() { - View bookmark = getDisplayedBookmark(url); - return bookmark != null; - } - }, MAX_WAIT_MS); - - mAsserter.ok(isCorrect, "Checking that " + url + " displayed as a bookmark", url + " displayed"); - } - - // Loads a bookmark by tapping on the bookmark view in the Bookmarks tab - protected void loadBookmark(String url) { - View bookmark = getDisplayedBookmark(url); - if (bookmark != null) { - Actions.EventExpecter contentEventExpecter = mActions.expectGeckoEvent("DOMContentLoaded"); - mSolo.clickOnView(bookmark); - contentEventExpecter.blockForEvent(); - contentEventExpecter.unregisterListener(); - } else { - mAsserter.ok(false, url + " is not one of the displayed bookmarks", "Please make sure the url provided is bookmarked"); - } - } - - // Opens the bookmark context menu by long-tapping on it - protected void openBookmarkContextMenu(String url) { - View bookmark = getDisplayedBookmark(url); - if (bookmark != null) { - mSolo.waitForView(bookmark); - mSolo.clickLongOnView(bookmark, LONG_PRESS_TIME); - mSolo.waitForDialogToOpen(); - } else { - mAsserter.ok(false, url + " is not one of the displayed bookmarks", "Please make sure the url provided is bookmarked"); - } - } - - // @return the View associated with bookmark for the provided url or null if the link is not bookmarked - protected View getDisplayedBookmark(String url) { - openAboutHomeTab(AboutHomeTabs.BOOKMARKS); - mSolo.hideSoftKeyboard(); - getInstrumentation().waitForIdleSync(); - ListView bookmarksTabList = findListViewWithTag(HomePager.LIST_TAG_BOOKMARKS); - waitForNonEmptyListToLoad(bookmarksTabList); - ListAdapter adapter = bookmarksTabList.getAdapter(); - if (adapter != null) { - for (int i = 0; i < adapter.getCount(); i++ ) { - // I am unable to click the view taken with getView for some reason so getting the child at i - bookmarksTabList.smoothScrollToPosition(i); - View bookmarkView = bookmarksTabList.getChildAt(i); - if (bookmarkView instanceof android.widget.LinearLayout) { - ViewGroup bookmarkItemView = (ViewGroup) bookmarkView; - for (int j = 0 ; j < bookmarkItemView.getChildCount(); j++) { - View bookmarkContent = bookmarkItemView.getChildAt(j); - if (bookmarkContent instanceof android.widget.LinearLayout) { - ViewGroup bookmarkItemLayout = (ViewGroup) bookmarkContent; - for (int k = 0 ; k < bookmarkItemLayout.getChildCount(); k++) { - // Both the title and url are represented as text views so we can cast the view without any issues - TextView bookmarkTextContent = (TextView)bookmarkItemLayout.getChildAt(k); - if (url.equals(bookmarkTextContent.getText().toString())) { - return bookmarkView; - } - } - } - } - } - } - } - return null; - } - - /** - * Waits for the given ListView to have a non-empty adapter and be populated - * with a minimum number of items. - * - * This method will return false if the given ListView or its adapter is null, - * or if the ListView does not have the minimum number of items. - */ - protected boolean waitForListToLoad(final ListView listView, final int minSize) { - Condition listWaitCondition = new Condition() { - @Override - public boolean isSatisfied() { - if (listView == null) { - return false; - } - - final ListAdapter adapter = listView.getAdapter(); - if (adapter == null) { - return false; - } - - return (listView.getCount() - listView.getHeaderViewsCount() >= minSize); - } - }; - return waitForCondition(listWaitCondition, MAX_WAIT_MS); - } - - protected boolean waitForNonEmptyListToLoad(final ListView listView) { - return waitForListToLoad(listView, 1); - } - - /** - * Get an active ListView with the specified tag . - * - * This method uses the predefined tags in HomePager. - */ - protected final ListView findListViewWithTag(String tag) { - for (ListView listView : mSolo.getCurrentViews(ListView.class)) { - final String listTag = (String) listView.getTag(); - if (TextUtils.isEmpty(listTag)) { - continue; - } - - if (TextUtils.equals(listTag, tag)) { - return listView; - } - } - - return null; - } - - // A wait in order for the about:home tab to be rendered after drag/tab selection - private void waitForAboutHomeTab(final int tabIndex) { - boolean correctTab = waitForCondition(new Condition() { - @Override - public boolean isSatisfied() { - ViewPager pager = mSolo.getView(ViewPager.class, 0); - return (pager.getCurrentItem() == tabIndex); - } - }, MAX_WAIT_MS); - mAsserter.ok(correctTab, "Checking that the correct tab is displayed", "The " + aboutHomeTabs.get(tabIndex) + " tab is displayed"); - } - - private void clickAboutHomeTab(AboutHomeTabs tab) { - mSolo.clickOnText(tab.toString().replace("_", " ")); - } - - /** - * Swipes to an about:home tab. - * @param swipeVector swipeVector Value and direction to swipe (go left for negative, right for positive). - */ - private void swipeAboutHome(int swipeVector) { - // Increase swipe width, which will especially impact tablets. - int swipeWidth = mDriver.getGeckoWidth() - 1; - int swipeHeight = mDriver.getGeckoHeight() / 2; - - if (swipeVector >= 0) { - // Emulate swipe motion from right to left. - for (int i = 0; i < swipeVector; i++) { - mActions.drag(swipeWidth, 0, swipeHeight, swipeHeight); - mSolo.sleep(100); - } - } else { - // Emulate swipe motion from left to right. - for (int i = 0; i > swipeVector; i--) { - mActions.drag(0, swipeWidth, swipeHeight, swipeHeight); - mSolo.sleep(100); - } - } - } - - /** - * This method can be used to open the different tabs of about:home. - */ - protected void openAboutHomeTab(AboutHomeTabs tab) { - focusUrlBar(); - ViewPager pager = mSolo.getView(ViewPager.class, 0); - final int currentTabIndex = pager.getCurrentItem(); - int tabOffset; - - // Handle tablets by just clicking the visible tab title. - if (mDevice.type.equals("tablet")) { - clickAboutHomeTab(tab); - return; - } - - // Handle phones (non-tablets). - tabOffset = aboutHomeTabs.indexOf(tab.toString()) - currentTabIndex; - swipeAboutHome(tabOffset); - waitForAboutHomeTab(aboutHomeTabs.indexOf(tab.toString())); - } -} diff --git a/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/BaseRobocopTest.java b/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/BaseRobocopTest.java deleted file mode 100644 index 3033524e8..000000000 --- a/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/BaseRobocopTest.java +++ /dev/null @@ -1,288 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -package org.mozilla.gecko.tests; - -import android.app.Activity; -import android.content.Context; -import android.content.Intent; -import android.os.PowerManager; -import android.test.ActivityInstrumentationTestCase2; -import android.text.TextUtils; -import android.util.Log; - -import com.robotium.solo.Solo; - -import org.mozilla.gecko.Actions; -import org.mozilla.gecko.AppConstants; -import org.mozilla.gecko.Assert; -import org.mozilla.gecko.BrowserApp; -import org.mozilla.gecko.Driver; -import org.mozilla.gecko.FennecInstrumentationTestRunner; -import org.mozilla.gecko.FennecMochitestAssert; -import org.mozilla.gecko.FennecNativeActions; -import org.mozilla.gecko.FennecNativeDriver; -import org.mozilla.gecko.FennecTalosAssert; -import org.mozilla.gecko.GeckoAppShell; -import org.mozilla.gecko.GeckoProfile; -import org.mozilla.gecko.updater.UpdateServiceHelper; - -import java.net.HttpURLConnection; -import java.net.URL; -import java.util.Map; - -@SuppressWarnings("unchecked") -public abstract class BaseRobocopTest extends ActivityInstrumentationTestCase2 { - public static final String LOGTAG = "BaseTest"; - - public enum Type { - MOCHITEST, - TALOS - } - - public static final String DEFAULT_ROOT_PATH = "/mnt/sdcard/tests"; - - // How long to wait for a Robocop:Quit message to actually kill Fennec. - private static final int ROBOCOP_QUIT_WAIT_MS = 180000; - - /** - * The Java Class instance that launches the browser. - *

- * This should always agree with {@link AppConstants#MOZ_ANDROID_BROWSER_INTENT_CLASS}. - */ - public static final Class BROWSER_INTENT_CLASS; - - // Use reflection here so we don't have to preprocess this file. - static { - Class cl; - try { - cl = (Class) Class.forName(AppConstants.MOZ_ANDROID_BROWSER_INTENT_CLASS); - } catch (ClassNotFoundException e) { - // Oh well. - cl = Activity.class; - } - BROWSER_INTENT_CLASS = cl; - } - - protected Assert mAsserter; - protected String mLogFile; - - protected String mBaseHostnameUrl; - protected String mBaseIpUrl; - - protected Map mConfig; - protected String mRootPath; - - protected Solo mSolo; - protected Driver mDriver; - protected Actions mActions; - - protected String mProfile; - - protected StringHelper mStringHelper; - - /** - * The browser is started at the beginning of this test. A single test is a - * class inheriting from BaseRobocopTest that contains test - * methods. - *

- * If a test should not start the browser at the beginning of a test, - * specify a different activity class to the one-argument constructor. To do - * as little as possible, specify Activity.class. - */ - public BaseRobocopTest() { - this((Class) BROWSER_INTENT_CLASS); - } - - /** - * Start the given activity class at the beginning of this test. - *

- * You should use the no-argument constructor in almost all cases. - * - * @param activityClass to start before this test. - */ - protected BaseRobocopTest(Class activityClass) { - super(activityClass); - } - - /** - * Returns the test type: mochitest or talos. - *

- * By default tests are mochitests, but a test can override this method in - * order to change its type. Most Robocop tests are mochitests. - */ - protected Type getTestType() { - return Type.MOCHITEST; - } - - // Member function to allow specialization. - protected Intent createActivityIntent() { - return BaseRobocopTest.createActivityIntent(mConfig); - } - - // Static function to allow re-use. - public static Intent createActivityIntent(Map config) { - final Intent intent = new Intent(Intent.ACTION_MAIN); - intent.putExtra("args", "-no-remote -profile " + config.get("profile")); - // Don't show the first run experience. - intent.putExtra(BrowserApp.EXTRA_SKIP_STARTPANE, true); - - final String envString = config.get("envvars"); - if (!TextUtils.isEmpty(envString)) { - final String[] envStrings = envString.split(","); - - for (int iter = 0; iter < envStrings.length; iter++) { - intent.putExtra("env" + iter, envStrings[iter]); - } - } - - return intent; - } - - @Override - protected void setUp() throws Exception { - // Disable the updater. - UpdateServiceHelper.setEnabled(false); - - // Load config file from root path (set up by Python script). - mRootPath = FennecInstrumentationTestRunner.getFennecArguments().getString("deviceroot"); - if (mRootPath == null) { - Log.w("Robocop", "Did not find deviceroot in arguments; falling back to: " + DEFAULT_ROOT_PATH); - mRootPath = DEFAULT_ROOT_PATH; - } - String configFile = FennecNativeDriver.getFile(mRootPath + "/robotium.config"); - mConfig = FennecNativeDriver.convertTextToTable(configFile); - mLogFile = mConfig.get("logfile"); - mProfile = mConfig.get("profile"); - mBaseHostnameUrl = mConfig.get("host").replaceAll("(/$)", ""); - mBaseIpUrl = mConfig.get("rawhost").replaceAll("(/$)", ""); - - // Initialize the asserter. - if (getTestType() == Type.TALOS) { - mAsserter = new FennecTalosAssert(); - } else { - mAsserter = new FennecMochitestAssert(); - } - mAsserter.setLogFile(mLogFile); - mAsserter.setTestName(getClass().getName()); - - // Start the activity. - final Intent intent = createActivityIntent(); - setActivityIntent(intent); - - // Set up Robotium.solo and Driver objects - Activity tempActivity = getActivity(); - - StringHelper.initialize(tempActivity.getResources()); - mStringHelper = StringHelper.get(); - - mSolo = new Solo(getInstrumentation(), tempActivity); - mDriver = new FennecNativeDriver(tempActivity, mSolo, mRootPath); - mActions = new FennecNativeActions(tempActivity, mSolo, getInstrumentation(), mAsserter); - } - - @Override - protected void runTest() throws Throwable { - try { - super.runTest(); - } catch (Throwable t) { - // save screenshot -- written to /mnt/sdcard/Robotium-Screenshots - // as .jpg - mSolo.takeScreenshot("robocop-screenshot-"+getClass().getName()); - if (mAsserter != null) { - mAsserter.dumpLog("Exception caught during test!", t); - mAsserter.ok(false, "Exception caught", t.toString()); - } - // re-throw to continue bail-out - throw t; - } - } - - @Override - public void tearDown() throws Exception { - try { - mAsserter.endTest(); - - // By default, we don't quit Fennec on finish, and we don't finish - // all opened activities. Not quiting Fennec entirely is intended to - // make life better for local testers, who might want to alter a - // test that is under development rather than Fennec itself. Not - // finishing activities is intended to allow local testers to - // manually inspect an activity's state after a test - // run. runtestsremote.py sets this to "1". Testers running via an - // IDE will not have this set at all. - final String quitAndFinish = FennecInstrumentationTestRunner.getFennecArguments() - .getString("quit_and_finish"); // null means not specified. - if ("1".equals(quitAndFinish)) { - // Request the browser force quit and wait for it to take effect. - Log.i(LOGTAG, "Requesting force quit."); - mActions.sendGeckoEvent("Robocop:Quit", null); - mSolo.sleep(ROBOCOP_QUIT_WAIT_MS); - - // If still running, finish activities as recommended by Robotium. - Log.i(LOGTAG, "Finishing all opened activities."); - mSolo.finishOpenedActivities(); - } else { - // This has the effect of keeping the activity-under-test - // around; if we don't set it to null, it is killed, either by - // finishOpenedActivities above or super.tearDown below. - Log.i(LOGTAG, "Not requesting force quit and trying to keep started activity alive."); - setActivity(null); - } - } catch (Throwable e) { - e.printStackTrace(); - } - super.tearDown(); - } - - /** - * Function to early abort if we can't reach the given HTTP server. Provides local testers - * with diagnostic information. Not currently available for TALOS tests, which are rarely run - * locally in any case. - */ - public void throwIfHttpGetFails() { - if (getTestType() == Type.TALOS) { - return; - } - - // rawURL to test fetching from. This should be a raw (IP) URL, not an alias - // (like mochi.test). We can't (easily) test fetching from the aliases, since - // those are managed by Fennec's proxy settings. - final String rawUrl = ((String) mConfig.get("rawhost")).replaceAll("(/$)", ""); - - HttpURLConnection urlConnection = null; - - try { - urlConnection = (HttpURLConnection) new URL(rawUrl).openConnection(); - - final int statusCode = urlConnection.getResponseCode(); - if (200 != statusCode) { - throw new IllegalStateException("Status code: " + statusCode); - } - } catch (Exception e) { - mAsserter.ok(false, "Robocop tests on your device need network/wifi access to reach: [" + rawUrl + "].", e.toString()); - } finally { - if (urlConnection != null) { - urlConnection.disconnect(); - } - } - } - - /** - * Ensure that the screen on the test device is powered on during tests. - */ - public void throwIfScreenNotOn() { - final PowerManager pm = (PowerManager) getActivity().getSystemService(Context.POWER_SERVICE); - mAsserter.ok(pm.isScreenOn(), - "Robocop tests need the test device screen to be powered on.", ""); - } - - protected GeckoProfile getTestProfile() { - if (mProfile.startsWith("/")) { - return GeckoProfile.get(getActivity(), /* profileName */ null, mProfile); - } - - return GeckoProfile.get(getActivity(), mProfile); - } -} diff --git a/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/BaseTest.java b/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/BaseTest.java deleted file mode 100644 index a8dfedc4e..000000000 --- a/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/BaseTest.java +++ /dev/null @@ -1,976 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -package org.mozilla.gecko.tests; - -import java.io.File; -import java.io.IOException; -import java.io.InputStream; -import java.io.PrintWriter; -import java.io.StringWriter; -import java.util.ArrayList; -import java.util.HashSet; - -import org.json.JSONException; -import org.json.JSONObject; - -import org.mozilla.gecko.Actions; -import org.mozilla.gecko.Element; -import org.mozilla.gecko.GeckoAppShell; -import org.mozilla.gecko.GeckoProfile; -import org.mozilla.gecko.GeckoThread; -import org.mozilla.gecko.R; -import org.mozilla.gecko.RobocopUtils; -import org.mozilla.gecko.Tab; -import org.mozilla.gecko.Tabs; - -import android.content.ContentValues; -import android.content.res.AssetManager; -import android.database.Cursor; -import android.os.Build; -import android.support.v4.app.Fragment; -import android.support.v4.app.FragmentActivity; -import android.support.v4.app.FragmentManager; -import android.support.v7.widget.RecyclerView; -import android.text.TextUtils; -import android.util.DisplayMetrics; -import android.view.View; -import android.widget.AdapterView; -import android.widget.Button; -import android.widget.EditText; -import android.widget.ListAdapter; -import android.widget.TextView; - -import com.robotium.solo.Condition; -import com.robotium.solo.Timeout; - -/** - * A convenient base class suitable for most Robocop tests. - */ -@SuppressWarnings("unchecked") -abstract class BaseTest extends BaseRobocopTest { - private static final int VERIFY_URL_TIMEOUT = 2000; - private static final int MAX_WAIT_ENABLED_TEXT_MS = 15000; - private static final int MAX_WAIT_HOME_PAGER_HIDDEN_MS = 15000; - private static final int MAX_WAIT_VERIFY_PAGE_TITLE_MS = 15000; - public static final int MAX_WAIT_MS = 4500; - public static final int LONG_PRESS_TIME = 6000; - private static final int GECKO_READY_WAIT_MS = 180000; - - protected static final String URL_HTTP_PREFIX = "http://"; - - public Device mDevice; - protected DatabaseHelper mDatabaseHelper; - protected int mScreenMidWidth; - protected int mScreenMidHeight; - private final HashSet mKnownTabIDs = new HashSet(); - - protected void blockForDelayedStartup() { - try { - Actions.EventExpecter delayedStartupExpector = mActions.expectGeckoEvent("Gecko:DelayedStartup"); - delayedStartupExpector.blockForEvent(GECKO_READY_WAIT_MS, true); - delayedStartupExpector.unregisterListener(); - } catch (Exception e) { - mAsserter.dumpLog("Exception in blockForDelayedStartup", e); - } - } - - protected void blockForGeckoReady() { - try { - Actions.EventExpecter geckoReadyExpector = mActions.expectGeckoEvent("Gecko:Ready"); - if (!GeckoThread.isRunning()) { - geckoReadyExpector.blockForEvent(GECKO_READY_WAIT_MS, true); - } - geckoReadyExpector.unregisterListener(); - } catch (Exception e) { - mAsserter.dumpLog("Exception in blockForGeckoReady", e); - } - } - - @Override - public void setUp() throws Exception { - super.setUp(); - - mDevice = new Device(); - mDatabaseHelper = new DatabaseHelper(getActivity(), mAsserter); - - // Ensure Robocop tests have access to network, and are run with Display powered on. - throwIfHttpGetFails(); - throwIfScreenNotOn(); - } - - protected void initializeProfile() { - final GeckoProfile profile = getTestProfile(); - - // In Robocop tests, we typically don't get initialized correctly, because - // GeckoProfile doesn't create the profile directory. - profile.enqueueInitialization(profile.getDir()); - } - - /** - * Click on the URL bar to focus it and enter editing mode. - */ - protected final void focusUrlBar() { - // Click on the browser toolbar to enter editing mode - mSolo.waitForView(R.id.browser_toolbar); - final View toolbarView = mSolo.getView(R.id.browser_toolbar); - mSolo.clickOnView(toolbarView); - - // Wait for highlighed text to gain focus - boolean success = waitForCondition(new Condition() { - @Override - public boolean isSatisfied() { - mSolo.waitForView(R.id.url_edit_text); - EditText urlEditText = (EditText) mSolo.getView(R.id.url_edit_text); - if (urlEditText.isInputMethodTarget()) { - return true; - } - return false; - } - }, MAX_WAIT_ENABLED_TEXT_MS); - - mAsserter.ok(success, "waiting for urlbar text to gain focus", "urlbar text gained focus"); - } - - protected final void enterUrl(String url) { - focusUrlBar(); - - final EditText urlEditView = (EditText) mSolo.getView(R.id.url_edit_text); - - // Send the keys for the URL we want to enter - mSolo.clearEditText(urlEditView); - mSolo.typeText(urlEditView, url); - - // Get the URL text from the URL bar EditText view - final String urlBarText = urlEditView.getText().toString(); - mAsserter.is(url, urlBarText, "URL typed properly"); - } - - protected final Fragment getBrowserSearch() { - final FragmentManager fm = ((FragmentActivity) getActivity()).getSupportFragmentManager(); - return fm.findFragmentByTag("browser_search"); - } - - protected final void hitEnterAndWait() { - Actions.EventExpecter contentEventExpecter = mActions.expectGeckoEvent("DOMContentLoaded"); - mActions.sendSpecialKey(Actions.SpecialKey.ENTER); - // wait for screen to load - contentEventExpecter.blockForEvent(); - contentEventExpecter.unregisterListener(); - } - - /** - * Load url by sending key strokes to the URL bar UI. - * - * This method waits synchronously for the DOMContentLoaded - * message from Gecko before returning. - * - * Unless you need to test text entry in the url bar, consider using loadUrl - * instead -- it loads pages more directly and quickly. - */ - protected final void inputAndLoadUrl(String url) { - enterUrl(url); - hitEnterAndWait(); - } - - /** - * Load url using the internal - * org.mozilla.gecko.Tabs API. - * - * This method does not wait for any confirmation from Gecko before - * returning -- consider using verifyUrlBarTitle or a similar approach - * to wait for the page to load, or at least use loadUrlAndWait. - */ - protected final void loadUrl(final String url) { - try { - Tabs.getInstance().loadUrl(url); - } catch (Exception e) { - mAsserter.dumpLog("Exception in loadUrl", e); - throw new RuntimeException(e); - } - } - - /** - * Load url using the internal - * org.mozilla.gecko.Tabs API and wait for DOMContentLoaded. - */ - protected final void loadUrlAndWait(final String url) { - Actions.EventExpecter contentEventExpecter = mActions.expectGeckoEvent("DOMContentLoaded"); - loadUrl(url); - contentEventExpecter.blockForEvent(); - contentEventExpecter.unregisterListener(); - } - - protected final void closeTab(int tabId) { - Tabs tabs = Tabs.getInstance(); - Tab tab = tabs.getTab(tabId); - tabs.closeTab(tab); - } - - public final void verifyUrl(String url) { - final EditText urlEditText = (EditText) mSolo.getView(R.id.url_edit_text); - String urlBarText = null; - if (urlEditText != null) { - // wait for a short time for the expected text, in case there is a delay - // in updating the view - waitForCondition(new VerifyTextViewText(urlEditText, url), VERIFY_URL_TIMEOUT); - urlBarText = urlEditText.getText().toString(); - - } - mAsserter.is(urlBarText, url, "Browser toolbar URL stayed the same"); - } - - class VerifyTextViewText implements Condition { - private final TextView mTextView; - private final String mExpected; - public VerifyTextViewText(TextView textView, String expected) { - mTextView = textView; - mExpected = expected; - } - - @Override - public boolean isSatisfied() { - String textValue = mTextView.getText().toString(); - return mExpected.equals(textValue); - } - } - - class VerifyContentDescription implements Condition { - private final View view; - private final String expected; - - public VerifyContentDescription(View view, String expected) { - this.view = view; - this.expected = expected; - } - - @Override - public boolean isSatisfied() { - final CharSequence actual = view.getContentDescription(); - return TextUtils.equals(actual, expected); - } - } - - protected final String getAbsoluteUrl(String url) { - return mBaseHostnameUrl + "/" + url.replaceAll("(^/)", ""); - } - - protected final String getAbsoluteRawUrl(String url) { - return mBaseIpUrl + "/" + url.replaceAll("(^/)", ""); - } - - /* - * Wrapper method for mSolo.waitForCondition with additional logging. - */ - protected final boolean waitForCondition(Condition condition, int timeout) { - boolean result = mSolo.waitForCondition(condition, timeout); - if (!result) { - // Log timeout failure for diagnostic purposes only; a failed wait may - // be normal and does not necessarily warrant a test assertion/failure. - mAsserter.dumpLog("waitForCondition timeout after " + timeout + " ms."); - } - return result; - } - - public void SqliteCompare(String dbName, String sqlCommand, ContentValues[] cvs) { - File profile = new File(mProfile); - String dbPath = new File(profile, dbName).getPath(); - - Cursor c = mActions.querySql(dbPath, sqlCommand); - SqliteCompare(c, cvs); - } - - public void SqliteCompare(Cursor c, ContentValues[] cvs) { - mAsserter.is(c.getCount(), cvs.length, "List is correct length"); - if (c.moveToFirst()) { - do { - boolean found = false; - for (int i = 0; !found && i < cvs.length; i++) { - if (CursorMatches(c, cvs[i])) { - found = true; - } - } - mAsserter.is(found, true, "Password was found"); - } while (c.moveToNext()); - } - } - - public boolean CursorMatches(Cursor c, ContentValues cv) { - for (int i = 0; i < c.getColumnCount(); i++) { - String column = c.getColumnName(i); - if (cv.containsKey(column)) { - mAsserter.info("Comparing", "Column values for: " + column); - Object value = cv.get(column); - if (value == null) { - if (!c.isNull(i)) { - return false; - } - } else { - if (c.isNull(i) || !value.toString().equals(c.getString(i))) { - return false; - } - } - } - } - return true; - } - - public InputStream getAsset(String filename) throws IOException { - AssetManager assets = getInstrumentation().getContext().getAssets(); - return assets.open(filename); - } - - public boolean waitForText(final String text) { - // false is the default value for finding only - // visible views in `Solo.waitForText(String)`. - return waitForText(text, false); - } - - public boolean waitForText(final String text, final boolean onlyVisibleViews) { - // We use the default robotium values from - // `Waiter.waitForText(String)` for unspecified arguments. - final boolean rc = - mSolo.waitForText(text, 0, Timeout.getLargeTimeout(), true, onlyVisibleViews); - if (!rc) { - // log out failed wait for diagnostic purposes only; - // waitForText failures are sometimes expected/normal - mAsserter.dumpLog("waitForText timeout on "+text); - } - return rc; - } - - // waitForText usually scrolls down in a view when text is not visible. - // For PreferenceScreens and dialogs, Solo.waitForText scrolling does not - // work, so we use this hack to do the same thing. - protected boolean waitForPreferencesText(String txt) { - boolean foundText = waitForText(txt); - if (!foundText) { - if ((mScreenMidWidth == 0) || (mScreenMidHeight == 0)) { - mScreenMidWidth = mDriver.getGeckoWidth()/2; - mScreenMidHeight = mDriver.getGeckoHeight()/2; - } - - // If we don't see the item, scroll down once in case it's off-screen. - // Hacky way to scroll down. solo.scroll* does not work in dialogs. - MotionEventHelper meh = new MotionEventHelper(getInstrumentation(), mDriver.getGeckoLeft(), mDriver.getGeckoTop()); - meh.dragSync(mScreenMidWidth, mScreenMidHeight+100, mScreenMidWidth, mScreenMidHeight-100); - - foundText = mSolo.waitForText(txt); - } - return foundText; - } - - /** - * Wait for to be visible and also be enabled/clickable. - */ - public boolean waitForEnabledText(String text) { - final String testText = text; - boolean rc = waitForCondition(new Condition() { - @Override - public boolean isSatisfied() { - // Solo.getText() could be used here, except that it sometimes - // hits an assertion when the requested text is not found. - ArrayList views = mSolo.getCurrentViews(); - for (View view : views) { - if (view instanceof TextView) { - TextView tv = (TextView)view; - String viewText = tv.getText().toString(); - if (tv.isEnabled() && viewText != null && viewText.matches(testText)) { - return true; - } - } - } - return false; - } - }, MAX_WAIT_ENABLED_TEXT_MS); - if (!rc) { - // log out failed wait for diagnostic purposes only; - // failures are sometimes expected/normal - mAsserter.dumpLog("waitForEnabledText timeout on "+text); - } - return rc; - } - - - /** - * Select from Menu > "Settings" >

. - */ - public void selectSettingsItem(String section, String item) { - String[] itemPath = { "Settings", section, item }; - selectMenuItemByPath(itemPath); - } - - /** - * Traverses the items in listItems in order in the menu. - */ - public void selectMenuItemByPath(String[] listItems) { - int listLength = listItems.length; - if (listLength > 0) { - selectMenuItem(listItems[0]); - } - if (listLength > 1) { - for (int i = 1; i < listLength; i++) { - String itemName = "^" + listItems[i] + "$"; - mAsserter.ok(waitForPreferencesText(itemName), "Waiting for and scrolling once to find item " + itemName, itemName + " found"); - mAsserter.ok(waitForEnabledText(itemName), "Waiting for enabled text " + itemName, itemName + " option is present and enabled"); - mSolo.clickOnText(itemName); - } - } - } - - public final void selectMenuItem(String menuItemName) { - // build the item name ready to be used - String itemName = "^" + menuItemName + "$"; - final View menuView = mSolo.getView(R.id.menu); - mAsserter.isnot(menuView, null, "Menu view is not null"); - mSolo.clickOnView(menuView, true); - mAsserter.ok(waitForEnabledText(itemName), "Waiting for menu item " + itemName, itemName + " is present and enabled"); - mSolo.clickOnText(itemName); - } - - public final void verifyHomePagerHidden() { - final View homePagerContainer = mSolo.getView(R.id.home_screen_container); - - boolean rc = waitForCondition(new Condition() { - @Override - public boolean isSatisfied() { - return homePagerContainer.getVisibility() != View.VISIBLE; - } - }, MAX_WAIT_HOME_PAGER_HIDDEN_MS); - - if (!rc) { - mAsserter.ok(rc, "Verify HomePager is hidden", "HomePager is hidden"); - } - } - - public final void verifyUrlBarTitle(String url) { - mAsserter.isnot(url, null, "The url argument is not null"); - - final String expected; - if (mStringHelper.ABOUT_HOME_URL.equals(url)) { - expected = mStringHelper.ABOUT_HOME_TITLE; - } else if (url.startsWith(URL_HTTP_PREFIX)) { - expected = url.substring(URL_HTTP_PREFIX.length()); - } else { - expected = url; - } - - final TextView urlBarTitle = (TextView) mSolo.getView(R.id.url_bar_title); - String pageTitle = null; - if (urlBarTitle != null) { - // Wait for the title to make sure it has been displayed in case the view - // does not update fast enough - waitForCondition(new VerifyTextViewText(urlBarTitle, expected), MAX_WAIT_VERIFY_PAGE_TITLE_MS); - pageTitle = urlBarTitle.getText().toString(); - } - mAsserter.is(pageTitle, expected, "Page title is correct"); - } - - public final void verifyUrlInContentDescription(String url) { - mAsserter.isnot(url, null, "The url argument is not null"); - - final String expected; - if (mStringHelper.ABOUT_HOME_URL.equals(url)) { - expected = mStringHelper.ABOUT_HOME_TITLE; - } else if (url.startsWith(URL_HTTP_PREFIX)) { - expected = url.substring(URL_HTTP_PREFIX.length()); - } else { - expected = url; - } - - final View urlDisplayLayout = mSolo.getView(R.id.display_layout); - assertNotNull("ToolbarDisplayLayout is not null", urlDisplayLayout); - - String actualUrl = null; - - // Wait for the title to make sure it has been displayed in case the view - // does not update fast enough - waitForCondition(new VerifyContentDescription(urlDisplayLayout, expected), MAX_WAIT_VERIFY_PAGE_TITLE_MS); - if (urlDisplayLayout.getContentDescription() != null) { - actualUrl = urlDisplayLayout.getContentDescription().toString(); - } - - mAsserter.is(actualUrl, expected, "Url is correct"); - } - - public final void verifyTabCount(int expectedTabCount) { - Element tabCount = mDriver.findElement(getActivity(), R.id.tabs_counter); - String tabCountText = tabCount.getText(); - int tabCountInt = Integer.parseInt(tabCountText); - mAsserter.is(tabCountInt, expectedTabCount, "The correct number of tabs are opened"); - } - - public void verifyPinned(final boolean isPinned, final String gridItemTitle) { - boolean viewFound = waitForText(gridItemTitle); - mAsserter.ok(viewFound, "Found top site title: " + gridItemTitle, null); - - boolean success = waitForCondition(new Condition() { - @Override - public boolean isSatisfied() { - // We set the left compound drawable (index 0) to the pin icon. - final TextView gridItemTextView = mSolo.getText(gridItemTitle); - return isPinned == (gridItemTextView.getCompoundDrawables()[0] != null); - } - }, MAX_WAIT_MS); - mAsserter.ok(success, "Top site item was pinned: " + isPinned, null); - } - - public void pinTopSite(String gridItemTitle) { - verifyPinned(false, gridItemTitle); - mSolo.clickLongOnText(gridItemTitle); - boolean dialogOpened = mSolo.waitForDialogToOpen(); - mAsserter.ok(dialogOpened, "Pin site dialog opened: " + gridItemTitle, null); - boolean pinSiteFound = waitForText(mStringHelper.CONTEXT_MENU_PIN_SITE); - mAsserter.ok(pinSiteFound, "Found pin site menu item", null); - mSolo.clickOnText(mStringHelper.CONTEXT_MENU_PIN_SITE); - verifyPinned(true, gridItemTitle); - } - - public void unpinTopSite(String gridItemTitle) { - verifyPinned(true, gridItemTitle); - mSolo.clickLongOnText(gridItemTitle); - boolean dialogOpened = mSolo.waitForDialogToOpen(); - mAsserter.ok(dialogOpened, "Pin site dialog opened: " + gridItemTitle, null); - boolean unpinSiteFound = waitForText(mStringHelper.CONTEXT_MENU_UNPIN_SITE); - mAsserter.ok(unpinSiteFound, "Found unpin site menu item", null); - mSolo.clickOnText(mStringHelper.CONTEXT_MENU_UNPIN_SITE); - verifyPinned(false, gridItemTitle); - } - - // Used to perform clicks on pop-up buttons without having to close the virtual keyboard - public void clickOnButton(String label) { - final Button button = mSolo.getButton(label); - try { - runTestOnUiThread(new Runnable() { - @Override - public void run() { - button.performClick(); - } - }); - } catch (Throwable throwable) { - mAsserter.ok(false, "Unable to click the button","Was unable to click button "); - } - } - - private void waitForAnimationsToFinish() { - // Ideally we'd actually wait for animations to finish but since we have - // no good way of doing that, we just wait an arbitrary unit of time. - mSolo.sleep(3500); - } - - public void addTab() { - mSolo.clickOnView(mSolo.getView(R.id.tabs)); - waitForAnimationsToFinish(); - - // wait for addTab to appear (this is usually immediate) - boolean success = waitForCondition(new Condition() { - @Override - public boolean isSatisfied() { - View addTabView = mSolo.getView(R.id.add_tab); - if (addTabView == null) { - return false; - } - return true; - } - }, MAX_WAIT_MS); - mAsserter.ok(success, "waiting for add tab view", "add tab view available"); - final Actions.RepeatedEventExpecter pageShowExpecter = mActions.expectGeckoEvent("Content:PageShow"); - mSolo.clickOnView(mSolo.getView(R.id.add_tab)); - waitForAnimationsToFinish(); - - // Wait until we get a PageShow event for a new tab ID - for(;;) { - try { - JSONObject data = new JSONObject(pageShowExpecter.blockForEventData()); - int tabID = data.getInt("tabID"); - if (tabID == 0) { - mAsserter.dumpLog("addTab ignoring PageShow for tab 0"); - continue; - } - if (!mKnownTabIDs.contains(tabID)) { - mKnownTabIDs.add(tabID); - break; - } - } catch(JSONException e) { - mAsserter.ok(false, "Exception in addTab", getStackTraceString(e)); - } - } - pageShowExpecter.unregisterListener(); - } - - public void addTab(String url) { - addTab(); - - // Adding a new tab opens about:home, so now we just need to load the url in it. - loadUrlAndWait(url); - } - - public void closeAddedTabs() { - for(int tabID : mKnownTabIDs) { - closeTab(tabID); - } - } - - // A temporary tabs list/grid holder while the list and grid views are being transitioned to - // RecyclerViews (bug 1116415 and bug 1310081). - private static class TabsView { - private AdapterView gridView; - private RecyclerView listView; - - public TabsView(View view) { - if (view instanceof RecyclerView) { - listView = (RecyclerView) view; - } else { - gridView = (AdapterView) view; - } - } - - public void bringPositionIntoView(int index) { - if (gridView != null) { - gridView.setSelection(index); - } else { - listView.scrollToPosition(index); - } - } - - public View getViewAtIndex(int index) { - if (gridView != null) { - return gridView.getChildAt(index - gridView.getFirstVisiblePosition()); - } else { - final RecyclerView.ViewHolder itemViewHolder = listView.findViewHolderForLayoutPosition(index); - return itemViewHolder == null ? null : itemViewHolder.itemView; - } - } - - public void post(Runnable runnable) { - if (gridView != null) { - gridView.post(runnable); - } else { - listView.post(runnable); - } - } - } - /** - * Gets the AdapterView of the tabs list. - * - * @return List view in the tabs panel - */ - private final TabsView getTabsLayout() { - Element tabs = mDriver.findElement(getActivity(), R.id.tabs); - tabs.click(); - return new TabsView(getActivity().findViewById(R.id.normal_tabs)); - } - - /** - * Gets the view in the tabs panel at the specified index. - * - * @return View at index - */ - private View getTabViewAt(final int index) { - final View[] childView = { null }; - - final TabsView view = getTabsLayout(); - - runOnUiThreadSync(new Runnable() { - @Override - public void run() { - view.bringPositionIntoView(index); - - // The selection isn't updated synchronously; posting a - // runnable to the view's queue guarantees we'll run after the - // layout pass. - view.post(new Runnable() { - @Override - public void run() { - // Index is relative to all views in the list. - childView[0] = view.getViewAtIndex(index); - } - }); - } - }); - - boolean result = waitForCondition(new Condition() { - @Override - public boolean isSatisfied() { - return childView[0] != null; - } - }, MAX_WAIT_MS); - - mAsserter.ok(result, "list item at index " + index + " exists", null); - - return childView[0]; - } - - /** - * Selects the tab at the specified index. - * - * @param index Index of tab to select - */ - public void selectTabAt(final int index) { - mSolo.clickOnView(getTabViewAt(index)); - } - - public final void runOnUiThreadSync(Runnable runnable) { - RobocopUtils.runOnUiThreadSync(getActivity(), runnable); - } - - /* Tap the "star" (bookmark) button to bookmark or un-bookmark the current page */ - public void toggleBookmark() { - mActions.sendSpecialKey(Actions.SpecialKey.MENU); - waitForText("Settings"); - - // On ICS+ phones, there is no button labeled "Bookmarks" - // instead we have to just dig through every button on the screen - ArrayList images = mSolo.getCurrentViews(); - for (int i = 0; i < images.size(); i++) { - final View view = images.get(i); - boolean found = false; - found = "Bookmark".equals(view.getContentDescription()); - - // on older android versions, try looking at the button's text - if (!found) { - if (view instanceof TextView) { - found = "Bookmark".equals(((TextView)view).getText()); - } - } - - if (found) { - int[] xy = new int[2]; - view.getLocationOnScreen(xy); - - final int viewWidth = view.getWidth(); - final int viewHeight = view.getHeight(); - final float x = xy[0] + (viewWidth / 2.0f); - float y = xy[1] + (viewHeight / 2.0f); - - mSolo.clickOnScreen(x, y); - } - } - } - - class Device { - public final String version; // 2.x or 3.x or 4.x - public String type; // "tablet" or "phone" - public final int width; - public final int height; - public final float density; - - public Device() { - // Determine device version - int sdk = Build.VERSION.SDK_INT; - if (sdk < Build.VERSION_CODES.HONEYCOMB) { - version = "2.x"; - } else { - if (sdk > Build.VERSION_CODES.HONEYCOMB_MR2) { - version = "4.x"; - } else { - version = "3.x"; - } - } - // Determine with and height - DisplayMetrics dm = new DisplayMetrics(); - getActivity().getWindowManager().getDefaultDisplay().getMetrics(dm); - height = dm.heightPixels; - width = dm.widthPixels; - density = dm.density; - // Determine device type - type = "phone"; - try { - if (GeckoAppShell.isTablet()) { - type = "tablet"; - } - } catch (Exception e) { - mAsserter.dumpLog("Exception in detectDevice", e); - } - } - } - - class Navigation { - private final String devType; - private final String osVersion; - - public Navigation(Device mDevice) { - devType = mDevice.type; - osVersion = mDevice.version; - } - - public void back() { - Actions.EventExpecter pageShowExpecter = mActions.expectGeckoEvent("Content:PageShow"); - - if (devType.equals("tablet")) { - Element backBtn = mDriver.findElement(getActivity(), R.id.back); - backBtn.click(); - } else { - mSolo.goBack(); - } - - pageShowExpecter.blockForEvent(); - pageShowExpecter.unregisterListener(); - } - - public void forward() { - Actions.EventExpecter pageShowExpecter = mActions.expectGeckoEvent("Content:PageShow"); - - if (devType.equals("tablet")) { - mSolo.waitForView(R.id.forward); - mSolo.clickOnView(mSolo.getView(R.id.forward)); - } else { - mActions.sendSpecialKey(Actions.SpecialKey.MENU); - waitForText("^New Tab$"); - if (!osVersion.equals("2.x")) { - mSolo.waitForView(R.id.forward); - mSolo.clickOnView(mSolo.getView(R.id.forward)); - } else { - mSolo.clickOnText("^Forward$"); - } - ensureMenuClosed(); - } - - pageShowExpecter.blockForEvent(); - pageShowExpecter.unregisterListener(); - } - - // DEPRECATED! - // Use BaseTest.toggleBookmark() in new code. - public void bookmark() { - mActions.sendSpecialKey(Actions.SpecialKey.MENU); - waitForText("^New Tab$"); - if (mSolo.searchText("^Bookmark$")) { - // This is the Android 2.x so the button has text - mSolo.clickOnText("^Bookmark$"); - } else { - Element bookmarkBtn = mDriver.findElement(getActivity(), R.id.bookmark); - if (bookmarkBtn != null) { - // We are on Android 4.x so the button is an image button - bookmarkBtn.click(); - } - } - ensureMenuClosed(); - } - - // On some devices, the menu may not be dismissed after clicking on an - // item. Close it here. - private void ensureMenuClosed() { - if (mSolo.searchText("^New Tab$")) { - mSolo.goBack(); - } - } - } - - /** - * Gets the string representation of a stack trace. - * - * @param t Throwable to get stack trace for - * @return Stack trace as a string - */ - public static String getStackTraceString(Throwable t) { - StringWriter sw = new StringWriter(); - t.printStackTrace(new PrintWriter(sw)); - return sw.toString(); - } - - /** - * Condition class that waits for a view, and allows callers access it when done. - */ - private class DescriptionCondition implements Condition { - public T mView; - private final String mDescr; - private final Class mCls; - - public DescriptionCondition(Class cls, String descr) { - mDescr = descr; - mCls = cls; - } - - @Override - public boolean isSatisfied() { - mView = findViewWithContentDescription(mCls, mDescr); - return (mView != null); - } - } - - /** - * Wait for a view with the specified description . - */ - public T waitForViewWithDescription(Class cls, String description) { - DescriptionCondition c = new DescriptionCondition(cls, description); - waitForCondition(c, MAX_WAIT_ENABLED_TEXT_MS); - return c.mView; - } - - /** - * Get an active view with the specified description . - */ - public T findViewWithContentDescription(Class cls, String description) { - for (T view : mSolo.getCurrentViews(cls)) { - final String descr = (String) view.getContentDescription(); - if (TextUtils.isEmpty(descr)) { - continue; - } - - if (TextUtils.equals(description, descr)) { - return view; - } - } - - return null; - } - - /** - * Abstract class for running small test cases within a BaseTest. - */ - abstract class TestCase implements Runnable { - /** - * Implement tests here. setUp and tearDown for the test case - * should be handled by the parent test. This is so we can avoid the - * overhead of starting Gecko and creating profiles. - */ - protected abstract void test() throws Exception; - - @Override - public void run() { - try { - test(); - } catch (Exception e) { - mAsserter.ok(false, - "Test " + this.getClass().getName() + " threw exception: " + e, - ""); - } - } - } - - /** - * Set the preference and wait for it to change before proceeding with the test. - */ - public void setPreferenceAndWaitForChange(final String name, final Object value) { - blockForGeckoReady(); - mActions.setPref(name, value, /* flush */ false); - - // Wait for confirmation of the pref change before proceeding with the test. - mActions.getPrefs(new String[] { name }, new Actions.PrefHandlerBase() { - - @Override // Actions.PrefHandlerBase - public void prefValue(String pref, boolean changedValue) { - mAsserter.is(pref, name, "Expecting correct pref name"); - mAsserter.ok(value instanceof Boolean, "Expecting boolean pref", ""); - mAsserter.is(changedValue, value, "Expecting matching pref value"); - } - - @Override // Actions.PrefHandlerBase - public void prefValue(String pref, int changedValue) { - mAsserter.is(pref, name, "Expecting correct pref name"); - mAsserter.ok(value instanceof Integer, "Expecting int pref", ""); - mAsserter.is(changedValue, value, "Expecting matching pref value"); - } - - @Override // Actions.PrefHandlerBase - public void prefValue(String pref, String changedValue) { - mAsserter.is(pref, name, "Expecting correct pref name"); - mAsserter.ok(value instanceof CharSequence, "Expecting string pref", ""); - mAsserter.is(changedValue, value, "Expecting matching pref value"); - } - - }).waitForFinish(); - } -} diff --git a/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/ContentContextMenuTest.java b/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/ContentContextMenuTest.java deleted file mode 100644 index 5a1d09f8c..000000000 --- a/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/ContentContextMenuTest.java +++ /dev/null @@ -1,135 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -package org.mozilla.gecko.tests; - -import org.mozilla.gecko.Actions; -import org.mozilla.gecko.util.Clipboard; -import org.mozilla.gecko.Element; -import org.mozilla.gecko.R; - -import android.util.DisplayMetrics; - -import com.robotium.solo.Condition; - -/** - * This class covers interactions with the context menu opened from web content - */ -abstract class ContentContextMenuTest extends PixelTest { - private static final int MAX_TEST_TIMEOUT = 30000; // 30 seconds (worst case) - - // This method opens the context menu of any web content. It assumes that the page is already loaded - protected void openWebContentContextMenu(String waitText) { - DisplayMetrics dm = new DisplayMetrics(); - getActivity().getWindowManager().getDefaultDisplay().getMetrics(dm); - - // The web content we are trying to open the context menu for should be positioned at the top of the page, at least 60px high and aligned to the middle - float top = mDriver.getGeckoTop() + 30 * dm.density; - float left = mDriver.getGeckoLeft() + mDriver.getGeckoWidth() / 2; - - mAsserter.dumpLog("long-clicking at "+left+", "+top); - mSolo.clickLongOnScreen(left, top); - waitForText(waitText); - } - - protected void verifyContextMenuItems(String[] items) { - // Test that the menu items are displayed - if (!mSolo.searchText(items[0])) { - openWebContentContextMenu(items[0]); // Open the context menu if it is not already - } - - for (String option:items) { - mAsserter.ok(mSolo.searchText(option), "Checking that the option: " + option + " is available", "The option is available"); - } - } - - protected void openTabFromContextMenu(String contextMenuOption, int expectedTabCount) { - if (!mSolo.searchText(contextMenuOption)) { - openWebContentContextMenu(contextMenuOption); // Open the context menu if it is not already - } - Actions.EventExpecter tabEventExpecter = mActions.expectGeckoEvent("Tab:Added"); - mSolo.clickOnText(contextMenuOption); - tabEventExpecter.blockForEvent(); - tabEventExpecter.unregisterListener(); - verifyTabCount(expectedTabCount); - } - - protected void verifyTabs(String[] items) { - if (!mSolo.searchText(items[0])) { - openWebContentContextMenu(items[0]); - } - - for (String option:items) { - mAsserter.ok(mSolo.searchText(option), "Checking that the option: " + option + " is available", "The option is available"); - } - } - - protected void switchTabs(String tab) { - if (!mSolo.searchText(tab)) { - openWebContentContextMenu(tab); - } - mSolo.clickOnText(tab); - } - - - protected void verifyCopyOption(String copyOption, final String copiedText) { - if (!mSolo.searchText(copyOption)) { - openWebContentContextMenu(copyOption); // Open the context menu if it is not already - } - mSolo.clickOnText(copyOption); - boolean correctText = waitForCondition(new Condition() { - @Override - public boolean isSatisfied() { - final String clipboardText = Clipboard.getText(); - mAsserter.dumpLog("Clipboard text = " + clipboardText + " , expected text = " + copiedText); - return clipboardText.contains(copiedText); - } - }, MAX_TEST_TIMEOUT); - mAsserter.ok(correctText, "Checking if the text is correctly copied", "The text was correctly copied"); - } - - - - protected void verifyShareOption(String shareOption, String pageTitle) { - waitForText(pageTitle); // Even if this fails, it won't assert - if (!mSolo.searchText(shareOption)) { - openWebContentContextMenu(shareOption); // Open the context menu if it is not already - } - mSolo.clickOnText(shareOption); - mAsserter.ok(waitForText(shareOption), "Checking that the share pop-up is displayed", "The pop-up has been displayed"); - - // Close the Share Link option menu and wait for the page to be focused again - mSolo.goBack(); - waitForText(pageTitle); - } - - protected void verifyViewImageOption(String viewImageOption, final String imageUrl, String pageTitle) { - if (!mSolo.searchText(viewImageOption)) { - openWebContentContextMenu(viewImageOption); - } - mSolo.clickOnText(viewImageOption); - - boolean viewedImage = waitForCondition(new Condition() { - @Override - public boolean isSatisfied() { - final Element urlBarElement = mDriver.findElement(getActivity(), R.id.url_edit_text); - final String loadedUrl = urlBarElement.getText(); - return loadedUrl.contentEquals(imageUrl); - } - }, MAX_TEST_TIMEOUT); - mAsserter.ok(viewedImage, "Checking if the image is correctly viewed", "The image was correctly viewed"); - - mSolo.goBack(); - waitForText(pageTitle); - } - - protected void verifyBookmarkLinkOption(String bookmarkOption, String link) { - if (!mSolo.searchText(bookmarkOption)) { - openWebContentContextMenu(bookmarkOption); // Open the context menu if it is not already - } - mSolo.clickOnText(bookmarkOption); - mAsserter.ok(waitForText("Bookmark added"), "Waiting for the Bookmark added toaster notification", "The notification has been displayed"); - mAsserter.ok(mDatabaseHelper.isBookmark(link), "Checking if the link has been added as a bookmark", "The link has been bookmarked"); - } -} diff --git a/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/ContentProviderTest.java b/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/ContentProviderTest.java deleted file mode 100644 index 5496c97d2..000000000 --- a/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/ContentProviderTest.java +++ /dev/null @@ -1,255 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -package org.mozilla.gecko.tests; - -import java.io.File; -import java.util.ArrayList; -import java.util.LinkedList; -import java.util.concurrent.Callable; - -import org.mozilla.gecko.db.BrowserContract; -import org.mozilla.gecko.db.BrowserProvider; - -import android.content.ContentProvider; -import android.content.ContentProviderOperation; -import android.content.ContentProviderResult; -import android.content.ContentValues; -import android.content.Context; -import android.content.OperationApplicationException; -import android.content.SharedPreferences; -import android.content.pm.ApplicationInfo; -import android.content.res.AssetManager; -import android.content.res.Resources; -import android.database.ContentObserver; -import android.database.Cursor; -import android.net.Uri; -import android.os.Build; -import android.test.IsolatedContext; -import android.test.RenamingDelegatingContext; -import android.test.mock.MockContentResolver; -import android.test.mock.MockContext; - -/* - * ContentProviderTest provides the infrastructure to run content provider - * tests in an controlled/isolated environment, guaranteeing that your tests - * will not affect or be affected by any UI-related code. This is basically - * a heavily adapted port of Android's ProviderTestCase2 to work on Mozilla's - * infrastructure. - * - * For some tests, we need to have access to UI parts, or at least launch - * the activity so the assets with test data become available, which requires - * that we derive this test from BaseTest and consequently pull in some more - * UI code than we'd ideally want. Furthermore, we need to pass the - * Activity and not the instrumentation Context for the UI part to find some - * of its required resources. - * Similarly, we need to pass the Activity instead of the Instrumentation - * Context down to some of our users (still wrapped in the Delegating Provider) - * because they will stop working correctly if we do not. A typical problem - * is that databases used in the ContentProvider will be attempted to be - * opened twice. - */ -abstract class ContentProviderTest extends BaseTest { - protected ContentProvider mProvider; - protected ChangeRecordingMockContentResolver mResolver; - protected ArrayList mTests; - protected String mDatabaseName; - protected String mProviderAuthority; - protected IsolatedContext mProviderContext; - - private class ContentProviderMockContext extends MockContext { - @Override - public Resources getResources() { - // We will fail to find some resources if we don't point - // at the original activity. - return ((Context)getActivity()).getResources(); - } - - @Override - public String getPackageName() { - return getInstrumentation().getContext().getPackageName(); - } - - @Override - public String getPackageResourcePath() { - return getInstrumentation().getContext().getPackageResourcePath(); - } - - @Override - public File getDir(String name, int mode) { - return getInstrumentation().getContext().getDir(this.getClass().getSimpleName() + "_" + name, mode); - } - - @Override - public Context getApplicationContext() { - return this; - } - - @Override - public SharedPreferences getSharedPreferences(String name, int mode) { - return getInstrumentation().getContext().getSharedPreferences(name, mode); - } - - @Override - public ApplicationInfo getApplicationInfo() { - return getInstrumentation().getContext().getApplicationInfo(); - } - } - - protected class DelegatingTestContentProvider extends ContentProvider { - ContentProvider mTargetProvider; - - public DelegatingTestContentProvider(ContentProvider targetProvider) { - super(); - mTargetProvider = targetProvider; - } - - private Uri appendTestParam(Uri uri) { - try { - return appendUriParam(uri, BrowserContract.PARAM_IS_TEST, "1"); - } catch (Exception e) {} - - return null; - } - - @Override - public boolean onCreate() { - return mTargetProvider.onCreate(); - } - - @Override - public String getType(Uri uri) { - return mTargetProvider.getType(uri); - } - - @Override - public int delete(Uri uri, String selection, String[] selectionArgs) { - return mTargetProvider.delete(appendTestParam(uri), selection, selectionArgs); - } - - @Override - public Uri insert(Uri uri, ContentValues values) { - return mTargetProvider.insert(appendTestParam(uri), values); - } - - @Override - public int update(Uri uri, ContentValues values, String selection, - String[] selectionArgs) { - return mTargetProvider.update(appendTestParam(uri), values, - selection, selectionArgs); - } - - @Override - public Cursor query(Uri uri, String[] projection, String selection, - String[] selectionArgs, String sortOrder) { - return mTargetProvider.query(appendTestParam(uri), projection, selection, - selectionArgs, sortOrder); - } - - @Override - public ContentProviderResult[] applyBatch (ArrayList operations) - throws OperationApplicationException { - return mTargetProvider.applyBatch(operations); - } - - @Override - public int bulkInsert(Uri uri, ContentValues[] values) { - return mTargetProvider.bulkInsert(appendTestParam(uri), values); - } - - public ContentProvider getTargetProvider() { - return mTargetProvider; - } - } - - /* - * A MockContentResolver that records each URI that is supplied to - * notifyChange. Warning: the list of changed URIs is not - * synchronized. - */ - protected class ChangeRecordingMockContentResolver extends MockContentResolver { - public final LinkedList notifyChangeList = new LinkedList(); - - @Override - public void notifyChange(Uri uri, ContentObserver observer, boolean syncToNetwork) { - notifyChangeList.addLast(uri); - - super.notifyChange(uri, observer, syncToNetwork); - } - } - - /** - * Factory function that makes new ContentProvider instances. - *

- * We want a fresh provider each test, so this should be invoked in - * setUp before each individual test. - */ - protected static Callable sBrowserProviderCallable = new Callable() { - @Override - public ContentProvider call() { - return new BrowserProvider(); - } - }; - - private void setUpContentProvider(ContentProvider targetProvider) throws Exception { - mResolver = new ChangeRecordingMockContentResolver(); - - final String filenamePrefix = this.getClass().getSimpleName() + "."; - RenamingDelegatingContext targetContextWrapper = - new RenamingDelegatingContext( - new ContentProviderMockContext(), - (Context)getActivity(), - filenamePrefix); - - mProviderContext = new IsolatedContext(mResolver, targetContextWrapper); - - targetProvider.attachInfo(mProviderContext, null); - - mProvider = new DelegatingTestContentProvider(targetProvider); - mProvider.attachInfo(mProviderContext, null); - - mResolver.addProvider(mProviderAuthority, mProvider); - } - - public static Uri appendUriParam(Uri uri, String param, String value) { - return uri.buildUpon().appendQueryParameter(param, value).build(); - } - - public void setTestName(String testName) { - mAsserter.setTestName(this.getClass().getName() + " - " + testName); - } - - @Override - public void setUp() throws Exception { - throw new UnsupportedOperationException("You should call setUp(authority, databaseName) instead"); - } - - public void setUp(Callable contentProviderFactory, String authority, String databaseName) throws Exception { - super.setUp(); - - mTests = new ArrayList(); - mDatabaseName = databaseName; - - mProviderAuthority = authority; - - setUpContentProvider(contentProviderFactory.call()); - } - - @Override - public void tearDown() throws Exception { - if (Build.VERSION.SDK_INT >= 11) { - mProvider.shutdown(); - } - - if (mDatabaseName != null) { - mProviderContext.deleteDatabase(mDatabaseName); - } - - super.tearDown(); - } - - public AssetManager getAssetManager() { - return getInstrumentation().getContext().getAssets(); - } -} diff --git a/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/DatabaseHelper.java b/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/DatabaseHelper.java deleted file mode 100644 index c87dc2432..000000000 --- a/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/DatabaseHelper.java +++ /dev/null @@ -1,170 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -package org.mozilla.gecko.tests; - -import java.util.ArrayList; - -import org.mozilla.gecko.AppConstants; -import org.mozilla.gecko.Assert; -import org.mozilla.gecko.GeckoProfile; -import org.mozilla.gecko.db.BrowserDB; - -import android.app.Activity; -import android.content.ContentResolver; -import android.database.Cursor; -import android.net.Uri; - -class DatabaseHelper { - protected enum BrowserDataType {BOOKMARKS, HISTORY}; - private final Activity mActivity; - private final Assert mAsserter; - - public DatabaseHelper(Activity activity, Assert asserter) { - mActivity = activity; - mAsserter = asserter; - } - /** - * This method can be used to check if an URL is present in the bookmarks database - */ - protected boolean isBookmark(String url) { - final ContentResolver resolver = mActivity.getContentResolver(); - return getProfileDB().isBookmark(resolver, url); - } - - protected Uri buildUri(BrowserDataType dataType) { - Uri uri = null; - if (dataType == BrowserDataType.BOOKMARKS || dataType == BrowserDataType.HISTORY) { - uri = Uri.parse("content://" + AppConstants.ANDROID_PACKAGE_NAME + ".db.browser/" + dataType.toString().toLowerCase()); - } else { - mAsserter.ok(false, "The wrong data type has been provided = " + dataType.toString(), "Please provide the correct data type"); - } - uri = uri.buildUpon().appendQueryParameter("profile", GeckoProfile.DEFAULT_PROFILE) - .appendQueryParameter("sync", "true").build(); - return uri; - } - - /** - * Adds a bookmark. - */ - protected void addMobileBookmark(String title, String url) { - final ContentResolver resolver = mActivity.getContentResolver(); - getProfileDB().addBookmark(resolver, title, url); - mAsserter.ok(true, "Inserting a new bookmark", "Inserting the bookmark with the title = " + title + " and the url = " + url); - } - - /** - * Updates the title and keyword of a bookmark with the given URL. - * - * Warning: This method assumes that there's only one bookmark with the given URL. - */ - protected void updateBookmark(String url, String title, String keyword) { - final ContentResolver resolver = mActivity.getContentResolver(); - // Get the id for the bookmark with the given URL. - Cursor c = null; - try { - c = getProfileDB().getBookmarkForUrl(resolver, url); - if (!c.moveToFirst()) { - mAsserter.ok(false, "Getting bookmark with url", "Couldn't find bookmark with url = " + url); - return; - } - - int id = c.getInt(c.getColumnIndexOrThrow("_id")); - getProfileDB().updateBookmark(resolver, id, url, title, keyword); - - mAsserter.ok(true, "Updating bookmark", "Updating bookmark with url = " + url); - } finally { - if (c != null) { - c.close(); - } - } - } - - protected void deleteBookmark(String url) { - final ContentResolver resolver = mActivity.getContentResolver(); - getProfileDB().removeBookmarksWithURL(resolver, url); - } - - protected void deleteHistoryItem(String url) { - final ContentResolver resolver = mActivity.getContentResolver(); - getProfileDB().removeHistoryEntry(resolver, url); - } - - // About the same implementation as getFolderIdFromGuid from LocalBrowserDB because it is declared private and we can't use reflections to access it - protected long getFolderIdFromGuid(String guid) { - final ContentResolver resolver = mActivity.getContentResolver(); - long folderId = -1L; - final Uri bookmarksUri = buildUri(BrowserDataType.BOOKMARKS); - - Cursor c = null; - try { - c = resolver.query(bookmarksUri, - new String[] { "_id" }, - "guid = ?", - new String[] { guid }, - null); - if (c.moveToFirst()) { - folderId = c.getLong(c.getColumnIndexOrThrow("_id")); - } - - if (folderId == -1) { - mAsserter.ok(false, "Trying to get the folder id" ,"We did not get the correct folder id"); - } - } finally { - if (c != null) { - c.close(); - } - } - return folderId; - } - - /** - * Returns all of the bookmarks or history entries in a database. - * - * @return an ArrayList of the urls in the Firefox for Android Bookmarks or History databases. - */ - protected ArrayList getBrowserDBUrls(BrowserDataType dataType) { - final ArrayList browserData = new ArrayList(); - final ContentResolver resolver = mActivity.getContentResolver(); - - Cursor cursor = null; - final BrowserDB db = getProfileDB(); - if (dataType == BrowserDataType.HISTORY) { - cursor = db.getAllVisitedHistory(resolver); - } else if (dataType == BrowserDataType.BOOKMARKS) { - cursor = db.getBookmarksInFolder(resolver, getFolderIdFromGuid("mobile")); - } - - if (cursor == null) { - mAsserter.ok(false, "We could not retrieve any data from the database", "The cursor was null"); - return browserData; - } - - try { - if (!cursor.moveToFirst()) { - // Nothing here, but that's OK -- maybe there are zero results. The calling test will fail. - return browserData; - } - - do { - // The URL field may be null for folders in the structure of the Bookmarks table for Firefox. Eliminate those. - if (cursor.getString(cursor.getColumnIndex("url")) != null) { - browserData.add(cursor.getString(cursor.getColumnIndex("url"))); - } - } while (cursor.moveToNext()); - - return browserData; - } finally { - cursor.close(); - } - } - - protected BrowserDB getProfileDB() { - return BrowserDB.from(mActivity); - } -} diff --git a/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/JavascriptBridgeTest.java b/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/JavascriptBridgeTest.java deleted file mode 100644 index a71f8fd49..000000000 --- a/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/JavascriptBridgeTest.java +++ /dev/null @@ -1,107 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -package org.mozilla.gecko.tests; - -import static org.mozilla.gecko.tests.helpers.AssertionHelper.*; - -import org.mozilla.gecko.tests.helpers.GeckoHelper; -import org.mozilla.gecko.tests.helpers.JavascriptBridge; -import org.mozilla.gecko.tests.helpers.NavigationHelper; - -/** - * Extended to write tests using JavascriptBridge, which allows Java and JS to communicate back-and-forth. - * If you don't need back-and-forth communication, consider {@link JavascriptTest}. - * - * To write a test: - * * Extend this class - * * Add your javascript file to the base robocop directory (see where `testJavascriptBridge.js` is located) - * * In the main test method, call {@link #blockForReadyAndLoadJS(String)} with your javascript file name - * (don't include the path) or if you're loading a non-harness url, be sure to call {@link GeckoHelper#blockForReady()} - * * You can access js calls via the {@link #getJS()} method - * - Read {@link JavascriptBridge} javadoc for more information about using the API. - */ -public class JavascriptBridgeTest extends UITest { - - private static final long WAIT_GET_FROM_JS_MILLIS = 20000; - - private JavascriptBridge js; - - // Feel free to implement additional return types. - private boolean isAsyncValueSet; - private String asyncValueStr; - - @Override - public void setUp() throws Exception { - super.setUp(); - js = new JavascriptBridge(this); - } - - @Override - public void tearDown() throws Exception { - js.disconnect(); - super.tearDown(); - } - - public JavascriptBridge getJS() { - return js; - } - - protected void blockForReadyAndLoadJS(final String jsFilename) { - NavigationHelper.enterAndLoadUrl(mStringHelper.getHarnessUrlForJavascript(jsFilename)); - } - - /** - * Used to retrieve values from js when it's required to call async methods (e.g. promises). - * This method will block until the value is retrieved else timeout. - * - * This method is not thread-safe. - * - * Ideally, we could just have Javascript call Java when the callback completes but Java won't - * listen for messages unless we call into JS again (bug 1253467). - * - * To use this method: - * * Call this method with a name argument, henceforth known as `varName`. Note that it will be capitalized - * in all function names. - * * Create a js function, `"getAsync" + varName` (e.g. if `varName == "clientId`, the function is - * `getAsyncClientId`) of no args. This function should call the async get method and assign a global variable to - * the return value. - * * Create a js function, `"pollGetAsync" + varName` (e.g. `pollGetAsyncClientId`) of no args. It should call - * `java.asyncCall('blockingFromJsResponseString', ...` with two args: a boolean if the async value has been set yet - * and a String with the global return value (`null` or `undefined` are acceptable if the value has not been set). - */ - public String getBlockingFromJsString(final String varName) { - isAsyncValueSet = false; - final String fnSuffix = capitalize(varName); - getJS().syncCall("getAsync" + fnSuffix); // Initiate async callback - - final long timeoutMillis = System.currentTimeMillis() + WAIT_GET_FROM_JS_MILLIS; - do { - // Avoid sleeping! The async callback may have already completed so - // we test for completion here, rather than in the loop predicate. - getJS().syncCall("pollGetAsync" + fnSuffix); - if (isAsyncValueSet) { - break; - } - - if (System.currentTimeMillis() > timeoutMillis) { - fFail("Retrieving " + varName + " from JS has timed out"); - } - try { - Thread.sleep(500, 0); // Give time for JS to complete its operation. (emulator one core?) - } catch (final InterruptedException e) { } - } while (true); - - return asyncValueStr; - } - - public void blockingFromJsResponseString(final boolean isValueSet, final String value) { - this.isAsyncValueSet = isValueSet; - this.asyncValueStr = value; - } - - private String capitalize(final String str) { - return str.substring(0, 1).toUpperCase() + str.substring(1); - } -} diff --git a/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/JavascriptTest.java b/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/JavascriptTest.java deleted file mode 100644 index 52893510d..000000000 --- a/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/JavascriptTest.java +++ /dev/null @@ -1,87 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -package org.mozilla.gecko.tests; - -import org.json.JSONObject; -import org.mozilla.gecko.Actions; -import org.mozilla.gecko.tests.helpers.JavascriptBridge; -import org.mozilla.gecko.tests.helpers.JavascriptMessageParser; - -import android.util.Log; - -/** - * Extended to test stand-alone Javascript in automation. If you're looking to test JS interactions - * with Java, see {@link JavascriptBridgeTest}. - * - * There are also other tests that run stand-alone javascript but are more difficult for the mobile - * team to run (e.g. xpcshell). - */ -public class JavascriptTest extends BaseTest { - private static final String LOGTAG = "JavascriptTest"; - private static final String EVENT_TYPE = JavascriptBridge.EVENT_TYPE; - - // Calculate these once, at initialization. isLoggable is too expensive to - // have in-line in each log call. - private static final boolean logDebug = Log.isLoggable(LOGTAG, Log.DEBUG); - private static final boolean logVerbose = Log.isLoggable(LOGTAG, Log.VERBOSE); - - private final String javascriptUrl; - - public JavascriptTest(String javascriptUrl) { - super(); - this.javascriptUrl = javascriptUrl; - } - - public void testJavascript() throws Exception { - blockForGeckoReady(); - - doTestJavascript(); - } - - protected void doTestJavascript() throws Exception { - // We want to be waiting for Robocop messages before the page is loaded - // because the test harness runs each test in the suite (and possibly - // completes testing) before the page load event is fired. - final Actions.EventExpecter expecter = mActions.expectGeckoEvent(EVENT_TYPE); - mAsserter.dumpLog("Registered listener for " + EVENT_TYPE); - - final String url = getAbsoluteUrl(mStringHelper.getHarnessUrlForJavascript(javascriptUrl)); - mAsserter.dumpLog("Loading JavaScript test from " + url); - loadUrl(url); - - final JavascriptMessageParser testMessageParser = - new JavascriptMessageParser(mAsserter, false); - try { - while (!testMessageParser.isTestFinished()) { - if (logVerbose) { - Log.v(LOGTAG, "Waiting for " + EVENT_TYPE); - } - String data = expecter.blockForEventData(); - if (logVerbose) { - Log.v(LOGTAG, "Got event with data '" + data + "'"); - } - - JSONObject o = new JSONObject(data); - String innerType = o.getString("innerType"); - if (!"progress".equals(innerType)) { - throw new Exception("Unexpected event innerType " + innerType); - } - - String message = o.getString("message"); - if (message == null) { - throw new Exception("Progress message must not be null"); - } - testMessageParser.logMessage(message); - } - - if (logDebug) { - Log.d(LOGTAG, "Got test finished message"); - } - } finally { - expecter.unregisterListener(); - mAsserter.dumpLog("Unregistered listener for " + EVENT_TYPE); - } - } -} diff --git a/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/MotionEventHelper.java b/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/MotionEventHelper.java deleted file mode 100644 index 5b8254e99..000000000 --- a/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/MotionEventHelper.java +++ /dev/null @@ -1,210 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -package org.mozilla.gecko.tests; - -import org.mozilla.gecko.GeckoAppShell; -import org.mozilla.gecko.gfx.LayerView; -import org.mozilla.gecko.PrefsHelper; - -import android.app.Instrumentation; -import android.os.SystemClock; -import android.util.Log; -import android.view.MotionEvent; - -class MotionEventHelper { - private static final String LOGTAG = "RobocopMotionEventHelper"; - - private static final long DRAG_EVENTS_PER_SECOND = 20; // 20 move events per second when doing a drag - - private final Instrumentation mInstrumentation; - private final int mSurfaceOffsetX; - private final int mSurfaceOffsetY; - private final LayerView layerView; - private boolean mApzEnabled; - private float mTouchStartTolerance; - private final int mDpi; - - public MotionEventHelper(Instrumentation inst, int surfaceOffsetX, int surfaceOffsetY) { - mInstrumentation = inst; - mSurfaceOffsetX = surfaceOffsetX; - mSurfaceOffsetY = surfaceOffsetY; - layerView = GeckoAppShell.getLayerView(); - mApzEnabled = false; - mTouchStartTolerance = 0.0f; - mDpi = GeckoAppShell.getDpi(); - Log.i(LOGTAG, "Initialized using offset (" + mSurfaceOffsetX + "," + mSurfaceOffsetY + ")"); - PrefsHelper.getPref("layers.async-pan-zoom.enabled", new PrefsHelper.PrefHandlerBase() { - @Override public void prefValue(String pref, boolean value) { - mApzEnabled = value; - } - }); - PrefsHelper.getPref("apz.touch_start_tolerance", new PrefsHelper.PrefHandlerBase() { - @Override public void prefValue(String pref, String value) { - mTouchStartTolerance = Float.parseFloat(value); - } - }); - } - - public long down(float x, float y) { - Log.d(LOGTAG, "Triggering down at (" + x + "," + y + ")"); - long downTime = SystemClock.uptimeMillis(); - MotionEvent event = MotionEvent.obtain(downTime, downTime, MotionEvent.ACTION_DOWN, mSurfaceOffsetX + x, mSurfaceOffsetY + y, 0); - try { - mInstrumentation.sendPointerSync(event); - } finally { - event.recycle(); - event = null; - } - return downTime; - } - - public long move(long downTime, float x, float y) { - return move(downTime, SystemClock.uptimeMillis(), x, y); - } - - public long move(long downTime, long moveTime, float x, float y) { - Log.d(LOGTAG, "Triggering move to (" + x + "," + y + ")"); - MotionEvent event = MotionEvent.obtain(downTime, moveTime, MotionEvent.ACTION_MOVE, mSurfaceOffsetX + x, mSurfaceOffsetY + y, 0); - try { - mInstrumentation.sendPointerSync(event); - } finally { - event.recycle(); - event = null; - } - return downTime; - } - - public long up(long downTime, float x, float y) { - return up(downTime, SystemClock.uptimeMillis(), x, y); - } - - public long up(long downTime, long upTime, float x, float y) { - Log.d(LOGTAG, "Triggering up at (" + x + "," + y + ")"); - MotionEvent event = MotionEvent.obtain(downTime, upTime, MotionEvent.ACTION_UP, mSurfaceOffsetX + x, mSurfaceOffsetY + y, 0); - try { - mInstrumentation.sendPointerSync(event); - } finally { - event.recycle(); - event = null; - } - return -1L; - } - - private long movePastTouchStartTolerance(float startX, float startY, float endX, float endY) { - long downTime = 0; - float eventDx = (endX - startX); - float eventDy = (endY - startY); - if (mApzEnabled && (mTouchStartTolerance > 0.0f) && (eventDx != 0 || eventDy !=0)) { - final float dragLength = (float)Math.sqrt((eventDx * eventDx) + (eventDy * eventDy)); - final float extraDragLength = (float)Math.ceil(mTouchStartTolerance * mDpi); - final float extraDx = (eventDx / dragLength) * extraDragLength * (eventDx > 0.0f ? -1.0f : 1.0f); - final float extraDy = (eventDy / dragLength) * extraDragLength * (eventDy > 0.0f ? -1.0f : 1.0f); - downTime = down(startX + extraDx, startY + extraDy); - downTime = move(downTime, startX + extraDx, startY + extraDy); - try { - Thread.sleep(1000L / DRAG_EVENTS_PER_SECOND); - } catch (InterruptedException ie) { - ie.printStackTrace(); - } - } else { - downTime = down(startX, startY); - } - return downTime; - } - - public Thread dragAsync(final float startX, final float startY, final float endX, final float endY, final long durationMillis) { - Thread t = new Thread() { - @Override - public void run() { - layerView.setIsLongpressEnabled(false); - - int numEvents = (int)(durationMillis * DRAG_EVENTS_PER_SECOND / 1000); - float eventDx = (endX - startX) / numEvents; - float eventDy = (endY - startY) / numEvents; - long downTime = movePastTouchStartTolerance(startX, startY, endX, endY); - for (int i = 0; i < numEvents - 1; i++) { - downTime = move(downTime, startX + (eventDx * i), startY + (eventDy * i)); - try { - Thread.sleep(1000L / DRAG_EVENTS_PER_SECOND); - } catch (InterruptedException ie) { - ie.printStackTrace(); - } - } - // sleep a bit before sending the last move so that the calculated - // fling velocity is low and we don't end up doing a fling afterwards. - try { - Thread.sleep(1000L); - } catch (InterruptedException ie) { - ie.printStackTrace(); - } - // do the last one using endX/endY directly to avoid rounding errors - downTime = move(downTime, endX, endY); - downTime = up(downTime, endX, endY); - - layerView.setIsLongpressEnabled(true); - } - }; - t.start(); - return t; - } - - public void dragSync(float startX, float startY, float endX, float endY, long durationMillis) { - try { - dragAsync(startX, startY, endX, endY, durationMillis).join(); - mInstrumentation.waitForIdleSync(); - } catch (InterruptedException ie) { - ie.printStackTrace(); - } - } - - public void dragSync(float startX, float startY, float endX, float endY) { - dragSync(startX, startY, endX, endY, 1000); - } - - public Thread flingAsync(final float startX, final float startY, final float endX, final float endY, final float velocity) { - // note that the first move after the touch-down is used to get over the panning threshold, and - // is basically cancelled out. this means we need to generate (at least) two move events, with - // the last move event hitting the target velocity. to do this we just slice the total distance - // in half, assuming the first half will get us over the panning threshold and the second half - // will trigger the fling. - final float dx = (endX - startX) / 2; - final float dy = (endY - startY) / 2; - float distance = (float) Math.sqrt((dx * dx) + (dy * dy)); - final long time = (long)(distance / velocity); - if (time <= 0) { - throw new IllegalArgumentException( "Fling parameters require too small a time period" ); - } - Thread t = new Thread() { - @Override - public void run() { - long downTime = down(startX, startY); - downTime = move(downTime, downTime + time, startX + dx, startY + dy); - downTime = move(downTime, downTime + time + time, endX, endY); - downTime = up(downTime, downTime + time + time + time, endX, endY); - } - }; - t.start(); - return t; - } - - public void flingSync(float startX, float startY, float endX, float endY, float velocity) { - try { - flingAsync(startX, startY, endX, endY, velocity).join(); - mInstrumentation.waitForIdleSync(); - } catch (InterruptedException ie) { - ie.printStackTrace(); - } - } - - public void tap(float x, float y) { - long downTime = down(x, y); - downTime = up(downTime, x, y); - } - - public void doubleTap(float x, float y) { - tap(x, y); - tap(x, y); - } -} diff --git a/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/MotionEventReplayer.java b/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/MotionEventReplayer.java deleted file mode 100644 index 508c6b197..000000000 --- a/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/MotionEventReplayer.java +++ /dev/null @@ -1,224 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -package org.mozilla.gecko.tests; - -import java.io.BufferedReader; -import java.io.IOException; -import java.io.InputStream; -import java.io.InputStreamReader; -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; -import java.util.HashMap; -import java.util.Map; -import java.util.StringTokenizer; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -import android.app.Instrumentation; -import android.os.Build; -import android.os.SystemClock; -import android.util.Log; -import android.view.MotionEvent; - -class MotionEventReplayer { - private static final String LOGTAG = "RobocopMotionEventReplayer"; - - // the inner dimensions of the window on which the motion event capture was taken from - private static final int CAPTURE_WINDOW_WIDTH = 720; - private static final int CAPTURE_WINDOW_HEIGHT = 1038; - - private final Instrumentation mInstrumentation; - private final int mSurfaceOffsetX; - private final int mSurfaceOffsetY; - private final int mSurfaceWidth; - private final int mSurfaceHeight; - private final Map mActionTypes; - private Method mObtainNanoMethod; - - public MotionEventReplayer(Instrumentation inst, int surfaceOffsetX, int surfaceOffsetY, int surfaceWidth, int surfaceHeight) { - mInstrumentation = inst; - mSurfaceOffsetX = surfaceOffsetX; - mSurfaceOffsetY = surfaceOffsetY; - mSurfaceWidth = surfaceWidth; - mSurfaceHeight = surfaceHeight; - Log.i(LOGTAG, "Initialized using offset (" + mSurfaceOffsetX + "," + mSurfaceOffsetY + ")"); - - mActionTypes = new HashMap(); - mActionTypes.put("ACTION_CANCEL", MotionEvent.ACTION_CANCEL); - mActionTypes.put("ACTION_DOWN", MotionEvent.ACTION_DOWN); - mActionTypes.put("ACTION_MOVE", MotionEvent.ACTION_MOVE); - mActionTypes.put("ACTION_POINTER_DOWN", MotionEvent.ACTION_POINTER_DOWN); - mActionTypes.put("ACTION_POINTER_UP", MotionEvent.ACTION_POINTER_UP); - mActionTypes.put("ACTION_UP", MotionEvent.ACTION_UP); - } - - private int parseAction(String action) { - int index = 0; - - // ACTION_POINTER_DOWN and ACTION_POINTER_UP might be followed by - // pointer index in parentheses, like ACTION_POINTER_UP(1) - int beginParen = action.indexOf("("); - if (beginParen >= 0) { - int endParen = action.indexOf(")", beginParen + 1); - index = Integer.parseInt(action.substring(beginParen + 1, endParen)); - action = action.substring(0, beginParen); - } - - return mActionTypes.get(action) | (index << MotionEvent.ACTION_POINTER_INDEX_SHIFT); - } - - private int parseInt(String value) { - if (value == null) { - return 0; - } - if (value.startsWith("0x")) { - return Integer.parseInt(value.substring(2), 16); - } - return Integer.parseInt(value); - } - - private float scaleX(float value) { - return value * mSurfaceWidth / CAPTURE_WINDOW_WIDTH; - } - - private float scaleY(float value) { - return value * mSurfaceHeight / CAPTURE_WINDOW_HEIGHT; - } - - public void replayEvents(InputStream eventDescriptions) - throws IOException, IllegalAccessException, InvocationTargetException, NoSuchMethodException - { - // As an example, a line in the input stream might look like: - // - // MotionEvent { action=ACTION_DOWN, id[0]=0, x[0]=424.41055, y[0]=825.2412, - // toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, - // edgeFlags=0x0, pointerCount=1, historySize=0, eventTime=21972329, - // downTime=21972329, deviceId=6, source=0x1002 } - // - // These can be generated by printing out event.toString() in LayerView's - // onTouchEvent function on a phone running Ice Cream Sandwich. Different - // Android versions have different serializations of the motion event, and this - // code could probably be modified to parse other serializations if needed. - Pattern p = Pattern.compile("MotionEvent \\{ (.*?) \\}"); - Map eventProperties = new HashMap(); - - boolean firstEvent = true; - long timeDelta = 0L; - long lastEventTime = 0L; - - BufferedReader br = new BufferedReader(new InputStreamReader(eventDescriptions)); - try { - for (String eventStr = br.readLine(); eventStr != null; eventStr = br.readLine()) { - Matcher m = p.matcher(eventStr); - if (! m.find()) { - // this line doesn't have any MotionEvent data, skip it - continue; - } - - // extract the key-value pairs from the description and store them - // in the eventProperties table - StringTokenizer keyValues = new StringTokenizer(m.group(1), ","); - while (keyValues.hasMoreTokens()) { - String keyValue = keyValues.nextToken(); - String key = keyValue.substring(0, keyValue.indexOf('=')).trim(); - String value = keyValue.substring(keyValue.indexOf('=') + 1).trim(); - eventProperties.put(key, value); - } - - // set up the values we need to build the MotionEvent - long downTime = Long.parseLong(eventProperties.get("downTime")); - long eventTime = Long.parseLong(eventProperties.get("eventTime")); - int action = parseAction(eventProperties.get("action")); - float pressure = 1.0f; - float size = 1.0f; - int metaState = parseInt(eventProperties.get("metaState")); - float xPrecision = 1.0f; - float yPrecision = 1.0f; - int deviceId = 0; - int edgeFlags = parseInt(eventProperties.get("edgeFlags")); - int source = parseInt(eventProperties.get("source")); - int flags = parseInt(eventProperties.get("flags")); - - int pointerCount = parseInt(eventProperties.get("pointerCount")); - int[] pointerIds = new int[pointerCount]; - Object pointerData; - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.GINGERBREAD) { - MotionEvent.PointerCoords[] pointerCoords = new MotionEvent.PointerCoords[pointerCount]; - for (int i = 0; i < pointerCount; i++) { - pointerIds[i] = Integer.parseInt(eventProperties.get("id[" + i + "]")); - pointerCoords[i] = new MotionEvent.PointerCoords(); - pointerCoords[i].x = mSurfaceOffsetX + scaleX(Float.parseFloat(eventProperties.get("x[" + i + "]"))); - pointerCoords[i].y = mSurfaceOffsetY + scaleY(Float.parseFloat(eventProperties.get("y[" + i + "]"))); - } - pointerData = pointerCoords; - } else { - // pre-gingerbread we have to use a hidden API to create the motion event, and we have - // to create a flattened list of floats rather than an array of PointerCoords - final int NUM_SAMPLE_DATA = 4; // MotionEvent.NUM_SAMPLE_DATA - final int SAMPLE_X = 0; // MotionEvent.SAMPLE_X - final int SAMPLE_Y = 1; // MotionEvent.SAMPLE_Y - float[] sampleData = new float[pointerCount * NUM_SAMPLE_DATA]; - for (int i = 0; i < pointerCount; i++) { - pointerIds[i] = Integer.parseInt(eventProperties.get("id[" + i + "]")); - sampleData[(i * NUM_SAMPLE_DATA) + SAMPLE_X] = - mSurfaceOffsetX + scaleX(Float.parseFloat(eventProperties.get("x[" + i + "]"))); - sampleData[(i * NUM_SAMPLE_DATA) + SAMPLE_Y] = - mSurfaceOffsetY + scaleY(Float.parseFloat(eventProperties.get("y[" + i + "]"))); - } - pointerData = sampleData; - } - - // we want to adjust the timestamps on all the generated events so that they line up with - // the time that this function is executing on-device. - long now = SystemClock.uptimeMillis(); - if (firstEvent) { - timeDelta = now - eventTime; - firstEvent = false; - } - downTime += timeDelta; - eventTime += timeDelta; - - // we also generate the events in "real-time" (i.e. have delays between events that - // correspond to the delays in the event timestamps). - if (now < eventTime) { - try { - Thread.sleep(eventTime - now); - } catch (InterruptedException ie) { - } - } - - // and finally we dispatch the event - MotionEvent event; - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.GINGERBREAD) { - event = MotionEvent.obtain(downTime, eventTime, action, pointerCount, - pointerIds, (MotionEvent.PointerCoords[])pointerData, metaState, - xPrecision, yPrecision, deviceId, edgeFlags, source, flags); - } else { - // pre-gingerbread we have to use a hidden API to accomplish this - if (mObtainNanoMethod == null) { - mObtainNanoMethod = MotionEvent.class.getMethod("obtainNano", long.class, - long.class, long.class, int.class, int.class, pointerIds.getClass(), - pointerData.getClass(), int.class, float.class, float.class, - int.class, int.class); - } - event = (MotionEvent)mObtainNanoMethod.invoke(null, downTime, eventTime, - eventTime * 1000000, action, pointerCount, pointerIds, (float[])pointerData, - metaState, xPrecision, yPrecision, deviceId, edgeFlags); - } - try { - Log.v(LOGTAG, "Injecting " + event.toString()); - mInstrumentation.sendPointerSync(event); - } finally { - event.recycle(); - event = null; - } - - eventProperties.clear(); - } - } finally { - br.close(); - } - } -} diff --git a/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/PixelTest.java b/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/PixelTest.java deleted file mode 100644 index a33ecf241..000000000 --- a/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/PixelTest.java +++ /dev/null @@ -1,117 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -package org.mozilla.gecko.tests; - -import org.mozilla.gecko.Actions; -import org.mozilla.gecko.PaintedSurface; - -abstract class PixelTest extends BaseTest { - private static final long PAINT_CLEAR_DELAY = 10000; // milliseconds - - protected final PaintedSurface loadAndGetPainted(String url) { - Actions.RepeatedEventExpecter paintExpecter = mActions.expectPaint(); - loadUrlAndWait(url); - verifyHomePagerHidden(); - paintExpecter.blockUntilClear(PAINT_CLEAR_DELAY); - paintExpecter.unregisterListener(); - PaintedSurface p = mDriver.getPaintedSurface(); - if (p == null) { - mAsserter.ok(p != null, "checking that painted surface loaded", - "painted surface loaded"); - } - return p; - } - - protected final void loadAndPaint(String url) { - PaintedSurface painted = loadAndGetPainted(url); - painted.close(); - } - - protected final PaintedSurface reloadAndGetPainted() { - Actions.RepeatedEventExpecter paintExpecter = mActions.expectPaint(); - - mActions.sendSpecialKey(Actions.SpecialKey.MENU); - waitForText(mStringHelper.RELOAD_LABEL); - mSolo.clickOnText(mStringHelper.RELOAD_LABEL); - - paintExpecter.blockUntilClear(PAINT_CLEAR_DELAY); - paintExpecter.unregisterListener(); - PaintedSurface p = mDriver.getPaintedSurface(); - if (p == null) { - mAsserter.ok(p != null, "checking that painted surface loaded", - "painted surface loaded"); - } - return p; - } - - protected final void reloadAndPaint() { - PaintedSurface painted = reloadAndGetPainted(); - painted.close(); - } - - protected final PaintedSurface waitForPaint(Actions.RepeatedEventExpecter expecter) { - expecter.blockUntilClear(PAINT_CLEAR_DELAY); - PaintedSurface p = mDriver.getPaintedSurface(); - if (p == null) { - mAsserter.ok(p != null, "checking that painted surface loaded", - "painted surface loaded"); - } - return p; - } - - protected final PaintedSurface waitWithNoPaint(Actions.RepeatedEventExpecter expecter) { - try { - Thread.sleep(PAINT_CLEAR_DELAY); - } catch (InterruptedException ie) { - ie.printStackTrace(); - } - mAsserter.is(expecter.eventReceived(), false, "Checking gecko didn't draw unnecessarily"); - PaintedSurface p = mDriver.getPaintedSurface(); - if (p == null) { - mAsserter.ok(p != null, "checking that painted surface loaded", - "painted surface loaded"); - } - return p; - } - - // this matches the algorithm in robocop_boxes.html - protected final int[] getBoxColorAt(int x, int y) { - int r = ((int)Math.floor(x / 3) % 256); - r = r & 0xF8; - int g = (x + y) % 256; - g = g & 0xFC; - int b = ((int)Math.floor(y / 3) % 256); - b = b & 0xF8; - return new int[] { r, g, b }; - } - - /** - * Checks the top-left corner of the visible area of the page is at (x,y) of robocop_boxes.html. - */ - protected final void checkScrollWithBoxes(PaintedSurface painted, int x, int y) { - int[] color = getBoxColorAt(x, y); - mAsserter.ispixel(painted.getPixelAt(0, 0), color[0], color[1], color[2], "Pixel at 0, 0"); - color = getBoxColorAt(x + 100, y); - mAsserter.ispixel(painted.getPixelAt(100, 0), color[0], color[1], color[2], "Pixel at 100, 0"); - color = getBoxColorAt(x, y + 100); - mAsserter.ispixel(painted.getPixelAt(0, 100), color[0], color[1], color[2], "Pixel at 0, 100"); - color = getBoxColorAt(x + 100, y + 100); - mAsserter.ispixel(painted.getPixelAt(100, 100), color[0], color[1], color[2], "Pixel at 100, 100"); - } - - /** - * Loads the robocop_boxes.html file and verifies that we are positioned at (0,0) on it. - * @param url URL of the robocop_boxes.html file. - * @return The painted surface after rendering the file. - */ - protected final void loadAndVerifyBoxes(String url) { - PaintedSurface painted = loadAndGetPainted(url); - try { - checkScrollWithBoxes(painted, 0, 0); - } finally { - painted.close(); - } - } -} diff --git a/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/SelectionHandlerTest.java b/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/SelectionHandlerTest.java deleted file mode 100644 index eb808b542..000000000 --- a/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/SelectionHandlerTest.java +++ /dev/null @@ -1,56 +0,0 @@ -package org.mozilla.gecko.tests; - -import org.mozilla.gecko.Actions; -import org.mozilla.gecko.EventDispatcher; -import org.mozilla.gecko.tests.helpers.GeckoHelper; -import org.mozilla.gecko.tests.helpers.NavigationHelper; - -import android.util.Log; - -import org.json.JSONObject; - -/** - * A base test class for selection handler tests. - */ -abstract class SelectionHandlerTest extends UITest { - private static final String geckoEventString = "Robocop:testSelectionHandler"; - private final String url; - - public SelectionHandlerTest(String url) { - this.url = url; - } - - public void testSelection() { - GeckoHelper.blockForReady(); - - Actions.EventExpecter robocopTestExpecter = getActions().expectGeckoEvent(geckoEventString); - NavigationHelper.enterAndLoadUrl(url); - mToolbar.assertTitle(url); - - while (!test(robocopTestExpecter)) { - // do nothing - } - - robocopTestExpecter.unregisterListener(); - } - - protected boolean test(Actions.EventExpecter expecter) { - final JSONObject eventData; - try { - eventData = new JSONObject(expecter.blockForEventData()); - } catch(Exception ex) { - // Log and ignore - getAsserter().ok(false, "JS Test", "Error decoding data " + ex); - return false; - } - - if (eventData.has("result")) { - getAsserter().ok(eventData.optBoolean("result"), "JS Test", eventData.optString("msg")); - } else if (eventData.has("todo")) { - getAsserter().todo(eventData.optBoolean("todo"), "JS TODO", eventData.optString("msg")); - } - - EventDispatcher.sendResponse(eventData, new JSONObject()); - return eventData.optBoolean("done", false); - } -} diff --git a/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/SessionTest.java b/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/SessionTest.java deleted file mode 100644 index e07a9750c..000000000 --- a/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/SessionTest.java +++ /dev/null @@ -1,407 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -package org.mozilla.gecko.tests; - -import java.io.File; -import java.io.FileReader; -import java.io.FileWriter; -import java.io.IOException; - -import org.json.JSONArray; -import org.json.JSONException; -import org.json.JSONObject; -import org.mozilla.gecko.Actions; -import org.mozilla.gecko.Assert; -import org.mozilla.gecko.FennecMochitestAssert; - -public abstract class SessionTest extends BaseTest { - protected Navigation mNavigation; - - @Override - public void setUp() throws Exception { - super.setUp(); - - mNavigation = new Navigation(mDevice); - } - - /** - * A generic session object representing a collection of items that has a - * selected index. - */ - protected abstract class SessionObject { - private final int mIndex; - private final T[] mItems; - - public SessionObject(int index, T... items) { - mIndex = index; - mItems = items; - } - - public int getIndex() { - return mIndex; - } - - public T[] getItems() { - return mItems; - } - } - - protected class PageInfo { - private final String url; - private final String title; - - public PageInfo(String key) { - if (key.startsWith("about:")) { - url = key; - } else { - url = getPage(key); - } - title = key; - } - } - - protected class SessionTab extends SessionObject { - public SessionTab(int index, PageInfo... items) { - super(index, items); - } - } - - protected class Session extends SessionObject { - public Session(int index, SessionTab... items) { - super(index, items); - } - } - - /** - * Walker for visiting items in a browser-like navigation order. - */ - protected abstract class NavigationWalker { - private final T[] mItems; - private final int mIndex; - - public NavigationWalker(SessionObject obj) { - mItems = obj.getItems(); - mIndex = obj.getIndex(); - } - - /** - * Walks over the list of items, calling the onItem() callback for each. - * - * The selected item is the first item visited. Each item after the - * selected item is then visited in ascending index order. Finally, the - * list is iterated in reverse, and each item before the selected item - * is visited in descending index order. - */ - public void walk() { - onItem(mItems[mIndex], mIndex); - for (int i = mIndex + 1; i < mItems.length; i++) { - goForward(); - onItem(mItems[i], i); - } - if (mIndex > 0) { - for (int i = mItems.length - 2; i >= 0; i--) { - goBack(); - if (i < mIndex) { - onItem(mItems[i], i); - } - } - } - } - - /** - * Callback when an item is visited during a walk. - * - * Only one callback is executed per item. - */ - public abstract void onItem(T item, int currentIndex); - - /** - * Callback executed for each back step of the walk. - */ - public void goBack() {} - - /** - * Callback executed for each forward step of the walk. - */ - public void goForward() {} - } - - /** - * Loads a set of tabs in the browser specified by the given session. - * - * @param session Session to load - */ - protected void loadSessionTabs(Session session) { - // Verify initial about:home tab - verifyTabCount(1); - verifyUrl(mStringHelper.ABOUT_HOME_URL); - - SessionTab[] tabs = session.getItems(); - for (int i = 0; i < tabs.length; i++) { - final SessionTab tab = tabs[i]; - final PageInfo[] pages = tab.getItems(); - - // New tabs always start with about:home, so make sure about:home - // is always the first entry. - mAsserter.is(pages[0].url, mStringHelper.ABOUT_HOME_URL, "first page in tab is " + - mStringHelper.ABOUT_HOME_URL); - - // If this is the first tab, the tab already exists, so no need to - // create a new one. Otherwise, create a new tab if we're loading - // the first the first page in the set. - if (i > 0) { - addTab(); - } - - for (int j = 1; j < pages.length; j++) { - Actions.EventExpecter pageShowExpecter = mActions.expectGeckoEvent("Content:PageShow"); - - loadUrl(pages[j].url); - - pageShowExpecter.blockForEvent(); - pageShowExpecter.unregisterListener(); - } - - final int index = tab.getIndex(); - for (int j = pages.length - 1; j > index; j--) { - mNavigation.back(); - } - } - - selectTabAt(session.getIndex()); - } - - /** - * Verifies that the set of open tabs matches the given session. - * - * @param session Session to verify - */ - protected void verifySessionTabs(Session session) { - verifyTabCount(session.getItems().length); - - (new NavigationWalker(session) { - boolean mFirstTabVisited; - - @Override - public void onItem(SessionTab tab, int currentIndex) { - // The first tab to check should already be selected at startup - if (mFirstTabVisited) { - selectTabAt(currentIndex); - } else { - mFirstTabVisited = true; - } - - (new NavigationWalker(tab) { - @Override - public void onItem(PageInfo page, int currentIndex) { - final String text; - if (mStringHelper.ABOUT_HOME_URL.equals(page.url)) { - text = mStringHelper.TITLE_PLACE_HOLDER; - } else if (page.url.startsWith(URL_HTTP_PREFIX)) { - text = page.url.substring(URL_HTTP_PREFIX.length()); - } else { - text = page.url; - } - waitForText(text); - - verifyUrlBarTitle(page.url); - } - - @Override - public void goBack() { - mNavigation.back(); - } - - @Override - public void goForward() { - mNavigation.forward(); - } - }).walk(); - } - }).walk(); - } - - /** - * Gets session restore JSON corresponding to the open session. - * - * The JSON format follows the format used in Gecko for session restore and - * should be interchangeable with the Gecko's generated sessionstore.js. - * - * @param session Session to serialize - * @return JSON string of session - */ - protected String buildSessionJSON(Session session) { - final SessionTab[] sessionTabs = session.getItems(); - String sessionString = null; - - try { - final JSONArray tabs = new JSONArray(); - - for (int i = 0; i < sessionTabs.length; i++) { - final JSONObject tab = new JSONObject(); - final JSONArray entries = new JSONArray(); - final SessionTab sessionTab = sessionTabs[i]; - final PageInfo[] pages = sessionTab.getItems(); - - for (int j = 0; j < pages.length; j++) { - final PageInfo page = pages[j]; - final JSONObject entry = new JSONObject(); - entry.put("url", page.url); - entry.put("title", page.title); - entries.put(entry); - } - - tab.put("entries", entries); - tab.put("index", sessionTab.getIndex() + 1); - tabs.put(tab); - } - - JSONObject window = new JSONObject(); - window.put("tabs", tabs); - window.put("selected", session.getIndex() + 1); - sessionString = new JSONObject().put("windows", new JSONArray().put(window)).toString(); - } catch (JSONException e) { - mAsserter.ok(false, "JSON exception", getStackTraceString(e)); - } - - return sessionString; - } - - /** - * @see SessionTest#verifySessionJSON(Session, String, Assert) - */ - protected void verifySessionJSON(Session session, String sessionString) { - verifySessionJSON(session, sessionString, mAsserter); - } - - /** - * Verifies a session JSON string against the given session. - * - * @param session Session to verify against - * @param sessionString JSON string to verify - * @param asserter Assert class to use during verification - */ - protected void verifySessionJSON(Session session, String sessionString, Assert asserter) { - final SessionTab[] sessionTabs = session.getItems(); - - try { - final JSONObject window = new JSONObject(sessionString).getJSONArray("windows").getJSONObject(0); - final JSONArray tabs = window.getJSONArray("tabs"); - final int optSelected = window.optInt("selected", -1); - - asserter.is(optSelected, session.getIndex() + 1, "selected tab matches"); - - for (int i = 0; i < tabs.length(); i++) { - final JSONObject tab = tabs.getJSONObject(i); - final int index = tab.getInt("index"); - final JSONArray entries = tab.getJSONArray("entries"); - final SessionTab sessionTab = sessionTabs[i]; - final PageInfo[] pages = sessionTab.getItems(); - - asserter.is(index, sessionTab.getIndex() + 1, "selected page index matches"); - - for (int j = 0; j < entries.length(); j++) { - final JSONObject entry = entries.getJSONObject(j); - final String url = entry.getString("url"); - final String title = entry.optString("title"); - final PageInfo page = pages[j]; - - asserter.is(url, page.url, "URL in JSON matches session URL"); - if (!page.url.startsWith("about:")) { - asserter.is(title, page.title, "title in JSON matches session title"); - } - } - } - } catch (JSONException e) { - asserter.ok(false, "JSON exception", getStackTraceString(e)); - } - } - - /** - * Exception thrown by NonFatalAsserter for assertion failures. - */ - public static class AssertException extends RuntimeException { - public AssertException(String msg) { - super(msg); - } - } - - /** - * Asserter that throws an AssertException on failure instead of aborting - * the test. - * - * This can be used in methods called via waitForCondition() where an assertion - * might not immediately succeed. - */ - public class NonFatalAsserter extends FennecMochitestAssert { - @Override - public void ok(boolean condition, String name, String diag) { - if (!condition) { - String details = (diag == null ? "" : " | " + diag); - throw new AssertException("Assertion failed: " + name + details); - } - mAsserter.ok(condition, name, diag); - } - } - - /** - * Gets a URL for a dynamically-generated page. - * - * The page will have a URL unique to the given ID, and the page's title - * will match the given ID. - * - * @param id ID used to generate page URL - * @return URL of the page - */ - protected String getPage(String id) { - return getAbsoluteUrl("/robocop/robocop_dynamic.sjs?id=" + id); - } - - protected String readProfileFile(String filename) { - try { - return readFile(new File(mProfile, filename)); - } catch (IOException e) { - mAsserter.ok(false, "Error reading" + filename, getStackTraceString(e)); - } - return null; - } - - protected void writeProfileFile(String filename, String data) { - try { - writeFile(new File(mProfile, filename), data); - } catch (IOException e) { - mAsserter.ok(false, "Error writing to " + filename, getStackTraceString(e)); - } - } - - private String readFile(File target) throws IOException { - if (!target.exists()) { - return null; - } - - FileReader fr = new FileReader(target); - try { - StringBuffer sb = new StringBuffer(); - char[] buf = new char[8192]; - int read = fr.read(buf); - while (read >= 0) { - sb.append(buf, 0, read); - read = fr.read(buf); - } - return sb.toString(); - } finally { - fr.close(); - } - } - - private void writeFile(File target, String data) throws IOException { - FileWriter writer = new FileWriter(target); - try { - writer.write(data); - } finally { - writer.close(); - } - } -} diff --git a/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/StringHelper.java b/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/StringHelper.java deleted file mode 100644 index 6f5db560d..000000000 --- a/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/StringHelper.java +++ /dev/null @@ -1,401 +0,0 @@ -/* -*- Mode: Java; c-basic-offset: 4; tab-width: 4; indent-tabs-mode: nil; -*- - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -package org.mozilla.gecko.tests; - -import android.content.res.Resources; - -import org.mozilla.gecko.R; - -public class StringHelper { - private static StringHelper instance; - - // This needs to be accessed statically, before an instance of StringHelper can be created. - public static String STATIC_ABOUT_HOME_URL = "about:home"; - - public final String OK; - public final String CANCEL; - public final String CLEAR; - - // Note: DEFAULT_BOOKMARKS_TITLES.length == DEFAULT_BOOKMARKS_URLS.length - public final String[] DEFAULT_BOOKMARKS_TITLES; - public final String[] DEFAULT_BOOKMARKS_URLS; - public final int DEFAULT_BOOKMARKS_COUNT; - - // About pages - public final String ABOUT_BLANK_URL = "about:blank"; - public final String ABOUT_FIREFOX_URL; - public final String ABOUT_HOME_URL = "about:home"; - public final String ABOUT_ADDONS_URL = "about:addons"; - public final String ABOUT_SCHEME = "about:"; - - // About pages' titles - public final String ABOUT_HOME_TITLE = ""; - - // Context Menu item strings - public final String CONTEXT_MENU_BOOKMARK_LINK = "Bookmark Link"; - public final String CONTEXT_MENU_OPEN_LINK_IN_NEW_TAB = "Open Link in New Tab"; - public final String CONTEXT_MENU_OPEN_IN_NEW_TAB; - public final String CONTEXT_MENU_OPEN_LINK_IN_PRIVATE_TAB = "Open Link in Private Tab"; - public final String CONTEXT_MENU_OPEN_IN_PRIVATE_TAB; - public final String CONTEXT_MENU_COPY_LINK = "Copy Link"; - public final String CONTEXT_MENU_SHARE_LINK = "Share Link"; - public final String CONTEXT_MENU_EDIT; - public final String CONTEXT_MENU_SHARE; - public final String CONTEXT_MENU_REMOVE; - public final String CONTEXT_MENU_COPY_ADDRESS; - public final String CONTEXT_MENU_EDIT_SITE_SETTINGS; - public final String CONTEXT_MENU_SITE_SETTINGS_SAVE_PASSWORD = "Save Password"; - public final String CONTEXT_MENU_ADD_TO_HOME_SCREEN; - public final String CONTEXT_MENU_PIN_SITE; - public final String CONTEXT_MENU_UNPIN_SITE; - - // Context Menu menu items - public final String[] CONTEXT_MENU_ITEMS_IN_PRIVATE_TAB; - - public final String[] CONTEXT_MENU_ITEMS_IN_NORMAL_TAB; - - public final String[] BOOKMARK_CONTEXT_MENU_ITEMS; - - public final String[] CONTEXT_MENU_ITEMS_IN_URL_BAR; - - public final String TITLE_PLACE_HOLDER; - - // Robocop page urls - // Note: please use getAbsoluteUrl(String url) on each robocop url to get the correct url - public final String ROBOCOP_BIG_LINK_URL = "/robocop/robocop_big_link.html"; - public final String ROBOCOP_BIG_MAILTO_URL = "/robocop/robocop_big_mailto.html"; - public final String ROBOCOP_BLANK_PAGE_01_URL = "/robocop/robocop_blank_01.html"; - public final String ROBOCOP_BLANK_PAGE_02_URL = "/robocop/robocop_blank_02.html"; - public final String ROBOCOP_BLANK_PAGE_03_URL = "/robocop/robocop_blank_03.html"; - public final String ROBOCOP_BLANK_PAGE_04_URL = "/robocop/robocop_blank_04.html"; - public final String ROBOCOP_BLANK_PAGE_05_URL = "/robocop/robocop_blank_05.html"; - public final String ROBOCOP_BOXES_URL = "/robocop/robocop_boxes.html"; - public final String ROBOCOP_GEOLOCATION_URL = "/robocop/robocop_geolocation.html"; - public final String ROBOCOP_LOGIN_01_URL= "/robocop/robocop_login_01.html"; - public final String ROBOCOP_LOGIN_02_URL= "/robocop/robocop_login_02.html"; - public final String ROBOCOP_POPUP_URL = "/robocop/robocop_popup.html"; - public final String ROBOCOP_OFFLINE_STORAGE_URL = "/robocop/robocop_offline_storage.html"; - public final String ROBOCOP_PICTURE_LINK_URL = "/robocop/robocop_picture_link.html"; - public final String ROBOCOP_SEARCH_URL = "/robocop/robocop_search.html"; - public final String ROBOCOP_TEXT_PAGE_URL = "/robocop/robocop_text_page.html"; - public final String ROBOCOP_ADOBE_FLASH_URL = "/robocop/robocop_adobe_flash.html"; - public final String ROBOCOP_INPUT_URL = "/robocop/robocop_input.html"; - public final String ROBOCOP_READER_MODE_BASIC_ARTICLE = "/robocop/reader_mode_pages/basic_article.html"; - public final String ROBOCOP_LINK_TO_SLOW_LOADING = "/robocop/robocop_link_to_slow_loading.html"; - - private final String ROBOCOP_JS_HARNESS_URL = "/robocop/robocop_javascript.html"; - - // Robocop page images - public final String ROBOCOP_PICTURE_URL = "/robocop/Firefox.jpg"; - - // Robocop page titles - public final String ROBOCOP_BIG_LINK_TITLE = "Big Link"; - public final String ROBOCOP_BIG_MAILTO_TITLE = "Big Mailto"; - public final String ROBOCOP_BLANK_PAGE_01_TITLE = "Browser Blank Page 01"; - public final String ROBOCOP_BLANK_PAGE_02_TITLE = "Browser Blank Page 02"; - public final String ROBOCOP_GEOLOCATION_TITLE = "Geolocation Test Page"; - public final String ROBOCOP_PICTURE_LINK_TITLE = "Picture Link"; - public final String ROBOCOP_SEARCH_TITLE = "Robocop Search Engine"; - - // Distribution tile labels - public final String DISTRIBUTION1_LABEL = "Distribution 1"; - public final String DISTRIBUTION2_LABEL = "Distribution 2"; - - // Settings menu strings - public final String PRIVACY_SECTION_LABEL; - public final String MOZILLA_SECTION_LABEL; - - // Mozilla - public final String BRAND_NAME = "(Fennec|Nightly|Firefox Aurora|Firefox Beta|Firefox)"; - public final String ABOUT_LABEL = "About " + BRAND_NAME ; - public final String LOCATION_SERVICES_LABEL = "Mozilla Location Service"; - - // Labels for the about:home tabs - public final String HISTORY_LABEL; - public final String TOP_SITES_LABEL; - public final String BOOKMARKS_LABEL; - public final String TODAY_LABEL; - - // Desktop default bookmarks folders - public final String BOOKMARKS_UP_TO; - public final String BOOKMARKS_ROOT_LABEL; - public final String DESKTOP_FOLDER_LABEL; - public final String TOOLBAR_FOLDER_LABEL; - public final String BOOKMARKS_MENU_FOLDER_LABEL; - public final String UNSORTED_FOLDER_LABEL; - - // Menu items - some of the items are found only on android 2.3 and lower and some only on android 3.0+ - public final String NEW_TAB_LABEL; - public final String NEW_PRIVATE_TAB_LABEL; - public final String SHARE_LABEL; - public final String FIND_IN_PAGE_LABEL; - public final String DESKTOP_SITE_LABEL; - public final String PDF_LABEL; - public final String DOWNLOADS_LABEL; - public final String ADDONS_LABEL; - public final String LOGINS_LABEL; - public final String SETTINGS_LABEL; - public final String GUEST_MODE_LABEL; - public final String TAB_QUEUE_LABEL; - public final String TAB_QUEUE_SUMMARY; - - // Android 3.0+ - public final String TOOLS_LABEL; - public final String PAGE_LABEL; - - // Android 2.3 and lower only - public final String MORE_LABEL = "More"; - public final String RELOAD_LABEL; - public final String FORWARD_LABEL; - public final String BOOKMARK_LABEL; - - // Bookmark Toast Notification - public final String BOOKMARK_ADDED_LABEL; - public final String BOOKMARK_REMOVED_LABEL; - public final String BOOKMARK_UPDATED_LABEL; - public final String BOOKMARK_OPTIONS_LABEL; - - // Edit Bookmark screen - public final String EDIT_BOOKMARK; - - // Strings used in doorhanger messages and buttons - public final String GEO_MESSAGE = "Share your location with"; - public final String GEO_ALLOW; - public final String GEO_DENY = "Don't share"; - - public final String OFFLINE_MESSAGE = "to store data on your device for offline use"; - public final String OFFLINE_ALLOW = "Allow"; - public final String OFFLINE_DENY = "Don't allow"; - - public final String LOGIN_MESSAGE = "Would you like " + BRAND_NAME + " to remember this login?"; - public final String LOGIN_ALLOW = "Remember"; - public final String LOGIN_DENY = "Never"; - - public final String POPUP_MESSAGE = "prevented this site from opening"; - public final String POPUP_ALLOW; - public final String POPUP_DENY = "Don't show"; - - // Strings used as content description, e.g. for ImageButtons - public final String CONTENT_DESCRIPTION_READER_MODE_BUTTON = "Enter Reader View"; - - // Home Panel Settings - public final String CUSTOMIZE_HOME; - public final String ENABLED; - public final String HISTORY; - public final String PANELS; - - // Search Settings - public final String SEARCH_TITLE; - public final String SEARCH_SUGGESTIONS; - public final String SEARCH_INSTALLED; - - // Advanced Settings - public final String ADVANCED; - public final String DONT_SHOW_MENU; - public final String SHOW_MENU; - public final String DISABLED; - public final String TAP_TO_PLAY; - public final String HIDE_TITLE_BAR; - - // Update Settings - public final String AUTOMATIC_UPDATES; - public final String OVER_WIFI_OPTION; - public final String DOWNLOAD_UPDATES_AUTO; - public final String ALWAYS; - public final String NEVER; - - // Restore Tabs Settings - public final String DONT_RESTORE_TABS; - public final String ALWAYS_RESTORE_TABS; - public final String DONT_RESTORE_QUIT; - - private StringHelper(final Resources res) { - - OK = res.getString(R.string.button_ok); - CANCEL = res.getString(R.string.button_cancel); - CLEAR = res.getString(R.string.button_clear); - - // Note: DEFAULT_BOOKMARKS_TITLES.length == DEFAULT_BOOKMARKS_URLS.length - DEFAULT_BOOKMARKS_TITLES = new String[] { - res.getString(R.string.bookmarkdefaults_title_aboutfirefox), - res.getString(R.string.bookmarkdefaults_title_support), - res.getString(R.string.bookmarkdefaults_title_addons) - }; - DEFAULT_BOOKMARKS_URLS = new String[] { - res.getString(R.string.bookmarkdefaults_url_aboutfirefox), - res.getString(R.string.bookmarkdefaults_url_support), - res.getString(R.string.bookmarkdefaults_url_addons) - }; - DEFAULT_BOOKMARKS_COUNT = DEFAULT_BOOKMARKS_TITLES.length; - - // About pages - ABOUT_FIREFOX_URL = res.getString(R.string.bookmarkdefaults_url_aboutfirefox); - - // Context Menu item strings - CONTEXT_MENU_OPEN_IN_NEW_TAB = res.getString(R.string.contextmenu_open_new_tab); - CONTEXT_MENU_OPEN_IN_PRIVATE_TAB = res.getString(R.string.contextmenu_open_private_tab); - CONTEXT_MENU_EDIT = res.getString(R.string.contextmenu_top_sites_edit); - CONTEXT_MENU_SHARE = res.getString(R.string.contextmenu_share); - CONTEXT_MENU_REMOVE = res.getString(R.string.contextmenu_remove); - CONTEXT_MENU_COPY_ADDRESS = res.getString(R.string.contextmenu_copyurl); - CONTEXT_MENU_EDIT_SITE_SETTINGS = res.getString(R.string.contextmenu_site_settings); - CONTEXT_MENU_ADD_TO_HOME_SCREEN = res.getString(R.string.contextmenu_add_to_launcher); - CONTEXT_MENU_PIN_SITE = res.getString(R.string.contextmenu_top_sites_pin); - CONTEXT_MENU_UNPIN_SITE = res.getString(R.string.contextmenu_top_sites_unpin); - - // Context Menu menu items - CONTEXT_MENU_ITEMS_IN_PRIVATE_TAB = new String[] { - CONTEXT_MENU_OPEN_LINK_IN_PRIVATE_TAB, - CONTEXT_MENU_COPY_LINK, - CONTEXT_MENU_SHARE_LINK, - CONTEXT_MENU_BOOKMARK_LINK - }; - - CONTEXT_MENU_ITEMS_IN_NORMAL_TAB = new String[] { - CONTEXT_MENU_OPEN_LINK_IN_NEW_TAB, - CONTEXT_MENU_OPEN_LINK_IN_PRIVATE_TAB, - CONTEXT_MENU_COPY_LINK, - CONTEXT_MENU_SHARE_LINK, - CONTEXT_MENU_BOOKMARK_LINK - }; - - BOOKMARK_CONTEXT_MENU_ITEMS = new String[] { - CONTEXT_MENU_OPEN_IN_NEW_TAB, - CONTEXT_MENU_OPEN_IN_PRIVATE_TAB, - CONTEXT_MENU_COPY_ADDRESS, - CONTEXT_MENU_SHARE, - CONTEXT_MENU_EDIT, - CONTEXT_MENU_REMOVE, - CONTEXT_MENU_ADD_TO_HOME_SCREEN - }; - - CONTEXT_MENU_ITEMS_IN_URL_BAR = new String[] { - CONTEXT_MENU_SHARE, - CONTEXT_MENU_COPY_ADDRESS, - CONTEXT_MENU_EDIT_SITE_SETTINGS, - CONTEXT_MENU_ADD_TO_HOME_SCREEN - }; - - TITLE_PLACE_HOLDER = res.getString(R.string.url_bar_default_text); - - // Settings menu strings - PRIVACY_SECTION_LABEL = res.getString(R.string.pref_category_privacy_short); - MOZILLA_SECTION_LABEL = res.getString(R.string.pref_category_vendor); - - // Labels for the about:home tabs - HISTORY_LABEL = res.getString(R.string.home_history_title); - TOP_SITES_LABEL = res.getString(R.string.home_top_sites_title); - BOOKMARKS_LABEL = res.getString(R.string.bookmarks_title); - TODAY_LABEL = res.getString(R.string.history_today_section); - - BOOKMARKS_UP_TO = res.getString(R.string.home_move_back_to_filter); - BOOKMARKS_ROOT_LABEL = res.getString(R.string.bookmarks_title); - DESKTOP_FOLDER_LABEL = res.getString(R.string.bookmarks_folder_desktop); - TOOLBAR_FOLDER_LABEL = res.getString(R.string.bookmarks_folder_toolbar); - BOOKMARKS_MENU_FOLDER_LABEL = res.getString(R.string.bookmarks_folder_menu); - UNSORTED_FOLDER_LABEL = res.getString(R.string.bookmarks_folder_unfiled); - - // Menu items - some of the items are found only on android 2.3 and lower and some only on android 3.0+ - NEW_TAB_LABEL = res.getString(R.string.new_tab); - NEW_PRIVATE_TAB_LABEL = res.getString(R.string.new_private_tab); - SHARE_LABEL = res.getString(R.string.share); - FIND_IN_PAGE_LABEL = res.getString(R.string.find_in_page); - DESKTOP_SITE_LABEL = res.getString(R.string.desktop_mode); - PDF_LABEL = res.getString(R.string.save_as_pdf); - DOWNLOADS_LABEL = res.getString(R.string.downloads); - ADDONS_LABEL = res.getString(R.string.addons); - LOGINS_LABEL = res.getString(R.string.logins); - SETTINGS_LABEL = res.getString(R.string.settings); - GUEST_MODE_LABEL = res.getString(R.string.new_guest_session); - TAB_QUEUE_LABEL = res.getString(R.string.pref_tab_queue_title); - TAB_QUEUE_SUMMARY = res.getString(R.string.pref_tab_queue_summary); - - // Android 3.0+ - TOOLS_LABEL = res.getString(R.string.tools); - PAGE_LABEL = res.getString(R.string.page); - - // Android 2.3 and lower only - RELOAD_LABEL = res.getString(R.string.reload); - FORWARD_LABEL = res.getString(R.string.forward); - BOOKMARK_LABEL = res.getString(R.string.bookmark); - - // Bookmark Toast Notification - BOOKMARK_ADDED_LABEL = res.getString(R.string.bookmark_added); - BOOKMARK_REMOVED_LABEL = res.getString(R.string.bookmark_removed); - BOOKMARK_UPDATED_LABEL = res.getString(R.string.bookmark_updated); - BOOKMARK_OPTIONS_LABEL = res.getString(R.string.bookmark_options); - - // Edit Bookmark screen - EDIT_BOOKMARK = res.getString(R.string.bookmark_edit_title); - - // Strings used in doorhanger messages and buttons - GEO_ALLOW = res.getString(R.string.share); - - POPUP_ALLOW = res.getString(R.string.pref_panels_show); - - // Home Settings - PANELS = res.getString(R.string.pref_category_home_panels); - CUSTOMIZE_HOME = res.getString(R.string.pref_category_home); - ENABLED = res.getString(R.string.pref_home_updates_enabled); - HISTORY = res.getString(R.string.home_history_title); - - // Search Settings - SEARCH_TITLE = res.getString(R.string.search); - SEARCH_SUGGESTIONS = res.getString(R.string.pref_search_suggestions); - SEARCH_INSTALLED = res.getString(R.string.pref_category_installed_search_engines); - - // Advanced Settings - ADVANCED = res.getString(R.string.pref_category_advanced); - DONT_SHOW_MENU = res.getString(R.string.pref_char_encoding_off); - SHOW_MENU = res.getString(R.string.pref_char_encoding_on); - DISABLED = res.getString(R.string.pref_plugins_disabled ); - TAP_TO_PLAY = res.getString(R.string.pref_plugins_tap_to_play); - HIDE_TITLE_BAR = res.getString(R.string.pref_scroll_title_bar_summary ); - - // Update Settings - AUTOMATIC_UPDATES = res.getString(R.string.pref_home_updates); - OVER_WIFI_OPTION = res.getString(R.string.pref_update_autodownload_wifi); - DOWNLOAD_UPDATES_AUTO = res.getString(R.string.pref_update_autodownload); - ALWAYS = res.getString(R.string.pref_update_autodownload_enabled); - NEVER = res.getString(R.string.pref_update_autodownload_disabled); - - // Restore Tabs Settings - DONT_RESTORE_TABS = res.getString(R.string.pref_restore_quit); - ALWAYS_RESTORE_TABS = res.getString(R.string.pref_restore_always); - DONT_RESTORE_QUIT = res.getString(R.string.pref_restore_quit); - } - - public static void initialize(Resources res) { - if (instance != null) { - throw new IllegalStateException(StringHelper.class.getSimpleName() + " already Initialized"); - } - instance = new StringHelper(res); - } - - public static StringHelper get() { - if (instance == null) { - throw new IllegalStateException(StringHelper.class.getSimpleName() + " instance is not yet initialized. Use StringHelper.initialize(Resources) first."); - } - return instance; - } - - /** - * Build a URL for loading a Javascript file in the Robocop Javascript - * harness. - *

- * We append a random slug to avoid caching: see - * https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/Using_XMLHttpRequest#Bypassing_the_cache. - * - * @param javascriptUrl to load. - * @return URL with harness wrapper. - */ - public String getHarnessUrlForJavascript(String javascriptUrl) { - // We include a slug to make sure we never cache the harness. - return ROBOCOP_JS_HARNESS_URL + - "?slug=" + System.currentTimeMillis() + - "&path=" + javascriptUrl; - } -} diff --git a/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/UITest.java b/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/UITest.java deleted file mode 100644 index da952b5cb..000000000 --- a/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/UITest.java +++ /dev/null @@ -1,203 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -package org.mozilla.gecko.tests; - -import org.mozilla.gecko.Actions; -import org.mozilla.gecko.Assert; -import org.mozilla.gecko.Driver; -import org.mozilla.gecko.tests.components.AboutHomeComponent; -import org.mozilla.gecko.tests.components.AppMenuComponent; -import org.mozilla.gecko.tests.components.BaseComponent; -import org.mozilla.gecko.tests.components.GeckoViewComponent; -import org.mozilla.gecko.tests.components.TabStripComponent; -import org.mozilla.gecko.tests.components.ToolbarComponent; -import org.mozilla.gecko.tests.helpers.HelperInitializer; - -import com.robotium.solo.Solo; - -/** - * A base test class for Robocop (UI-centric) tests. This and the related classes attempt to - * provide a framework to improve upon the issues discovered with the previous BaseTest - * implementation by providing simple test authorship and framework extension, consistency, - * and reliability. - * - * For documentation on writing tests and extending the framework, see - * https://wiki.mozilla.org/Mobile/Fennec/Android/UITest - */ -abstract class UITest extends BaseRobocopTest - implements UITestContext { - - private static final String JUNIT_FAILURE_MSG = "A JUnit method was called. Make sure " + - "you are using AssertionHelper to make assertions. Try `fAssert*(...);`"; - - protected AboutHomeComponent mAboutHome; - protected AppMenuComponent mAppMenu; - protected GeckoViewComponent mGeckoView; - protected TabStripComponent mTabStrip; - protected ToolbarComponent mToolbar; - - @Override - protected void setUp() throws Exception { - super.setUp(); - - // Helpers depend on components so initialize them first. - initComponents(); - initHelpers(); - - // Ensure Robocop tests have access to network, and are run with Display powered on. - throwIfHttpGetFails(); - throwIfScreenNotOn(); - } - - private void initComponents() { - mAboutHome = new AboutHomeComponent(this); - mAppMenu = new AppMenuComponent(this); - mGeckoView = new GeckoViewComponent(this); - mTabStrip = new TabStripComponent(this); - mToolbar = new ToolbarComponent(this); - } - - private void initHelpers() { - HelperInitializer.init(this); - } - - @Override - public Solo getSolo() { - return mSolo; - } - - @Override - public Assert getAsserter() { - return mAsserter; - } - - @Override - public Driver getDriver() { - return mDriver; - } - - @Override - public Actions getActions() { - return mActions; - } - - @Override - public StringHelper getStringHelper() { - return mStringHelper; - } - - @Override - public void dumpLog(final String logtag, final String message) { - mAsserter.dumpLog(logtag + ": " + message); - } - - @Override - public void dumpLog(final String logtag, final String message, final Throwable t) { - mAsserter.dumpLog(logtag + ": " + message, t); - } - - @Override - public BaseComponent getComponent(final ComponentType type) { - switch (type) { - case ABOUTHOME: - return mAboutHome; - - case APPMENU: - return mAppMenu; - - case GECKOVIEW: - return mGeckoView; - - case TOOLBAR: - return mToolbar; - - default: - fail("Unknown component type, " + type + "."); - return null; // Should not reach this statement but required by javac. - } - } - - /** - * Returns the test type. By default this returns MOCHITEST, but tests can override this - * method in order to change the type of the test. - */ - @Override - protected Type getTestType() { - return Type.MOCHITEST; - } - - @Override - public String getAbsoluteHostnameUrl(final String url) { - return getAbsoluteUrl(mBaseHostnameUrl, url); - } - - @Override - public String getAbsoluteIpUrl(final String url) { - return getAbsoluteUrl(mBaseIpUrl, url); - } - - private String getAbsoluteUrl(final String baseUrl, final String url) { - return baseUrl + "/" + url.replaceAll("(^/)", ""); - } - - /** - * Throws an Exception. Called from overridden JUnit methods to ensure JUnit assertions - * are not accidentally used over AssertionHelper assertions (the latter of which contains - * additional logging facilities for use in our test harnesses). - */ - private static void junit() { - throw new UnsupportedOperationException(JUNIT_FAILURE_MSG); - } - - // Note: inexplicably, javac does not think we're overriding these methods, - // so we can't use the @Override annotation. - public static void assertEquals(short e, short a) { junit(); } - public static void assertEquals(String m, int e, int a) { junit(); } - public static void assertEquals(String m, short e, short a) { junit(); } - public static void assertEquals(char e, char a) { junit(); } - public static void assertEquals(String m, String e, String a) { junit(); } - public static void assertEquals(int e, int a) { junit(); } - public static void assertEquals(String m, double e, double a, double delta) { junit(); } - public static void assertEquals(String m, long e, long a) { junit(); } - public static void assertEquals(byte e, byte a) { junit(); } - public static void assertEquals(Object e, Object a) { junit(); } - public static void assertEquals(boolean e, boolean a) { junit(); } - public static void assertEquals(String m, float e, float a, float delta) { junit(); } - public static void assertEquals(String m, boolean e, boolean a) { junit(); } - public static void assertEquals(String e, String a) { junit(); } - public static void assertEquals(float e, float a, float delta) { junit(); } - public static void assertEquals(String m, byte e, byte a) { junit(); } - public static void assertEquals(double e, double a, double delta) { junit(); } - public static void assertEquals(String m, char e, char a) { junit(); } - public static void assertEquals(String m, Object e, Object a) { junit(); } - public static void assertEquals(long e, long a) { junit(); } - - public static void assertFalse(String m, boolean c) { junit(); } - public static void assertFalse(boolean c) { junit(); } - - public static void assertNotNull(String m, Object o) { junit(); } - public static void assertNotNull(Object o) { junit(); } - - public static void assertNotSame(Object e, Object a) { junit(); } - public static void assertNotSame(String m, Object e, Object a) { junit(); } - - public static void assertNull(Object o) { junit(); } - public static void assertNull(String m, Object o) { junit(); } - - public static void assertSame(Object e, Object a) { junit(); } - public static void assertSame(String m, Object e, Object a) { junit(); } - - public static void assertTrue(String m, boolean c) { junit(); } - public static void assertTrue(boolean c) { junit(); } - - public static void fail(String m) { junit(); } - public static void fail() { junit(); } - - public static void failNotEquals(String m, Object e, Object a) { junit(); } - public static void failNotSame(String m, Object e, Object a) { junit(); } - public static void failSame(String m) { junit(); } - - public static String format(String m, Object e, Object a) { junit(); return null; } -} diff --git a/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/UITestContext.java b/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/UITestContext.java deleted file mode 100644 index c825a20a4..000000000 --- a/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/UITestContext.java +++ /dev/null @@ -1,51 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -package org.mozilla.gecko.tests; - -import org.mozilla.gecko.Actions; -import org.mozilla.gecko.Assert; -import org.mozilla.gecko.Driver; -import org.mozilla.gecko.tests.components.BaseComponent; - -import android.app.Activity; -import android.app.Instrumentation; - -import com.robotium.solo.Solo; - -/** - * Interface to the global information about a UITest environment. - */ -public interface UITestContext { - - public static enum ComponentType { - ABOUTHOME, - APPMENU, - GECKOVIEW, - TOOLBAR - } - - public Activity getActivity(); - public Solo getSolo(); - public Assert getAsserter(); - public Driver getDriver(); - public Actions getActions(); - public Instrumentation getInstrumentation(); - public StringHelper getStringHelper(); - - public void dumpLog(final String logtag, final String message); - public void dumpLog(final String logtag, final String message, final Throwable t); - - /** - * Returns the absolute version of the given URL using the host's hostname. - */ - public String getAbsoluteHostnameUrl(final String url); - - /** - * Returns the absolute version of the given URL using the host's IP address. - */ - public String getAbsoluteIpUrl(final String url); - - public BaseComponent getComponent(final ComponentType type); -} diff --git a/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/components/AboutHomeComponent.java b/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/components/AboutHomeComponent.java deleted file mode 100644 index b12e0d23e..000000000 --- a/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/components/AboutHomeComponent.java +++ /dev/null @@ -1,193 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -package org.mozilla.gecko.tests.components; - -import static org.mozilla.gecko.tests.helpers.AssertionHelper.fAssertEquals; -import static org.mozilla.gecko.tests.helpers.AssertionHelper.fAssertTrue; - -import java.util.Arrays; -import java.util.List; - -import org.mozilla.gecko.AboutPages; -import org.mozilla.gecko.R; -import org.mozilla.gecko.Tabs; -import org.mozilla.gecko.home.HomeConfig.PanelType; -import org.mozilla.gecko.tests.UITestContext; -import org.mozilla.gecko.tests.helpers.WaitHelper; - -import android.os.Build; -import android.support.v4.view.ViewPager; -import android.view.View; -import android.widget.TextView; - -import com.robotium.solo.Condition; -import com.robotium.solo.Solo; - -/** - * A class representing any interactions that take place on the Awesomescreen. - */ -public class AboutHomeComponent extends BaseComponent { - private static final String LOGTAG = AboutHomeComponent.class.getSimpleName(); - - private static final List PANEL_ORDERING = Arrays.asList( - PanelType.TOP_SITES, - PanelType.BOOKMARKS, - PanelType.COMBINED_HISTORY - ); - - // The percentage of the panel to swipe between 0 and 1. This value was set through - // testing: 0.55f was tested on try and fails on armv6 devices. - private static final float SWIPE_PERCENTAGE = 0.70f; - - public AboutHomeComponent(final UITestContext testContext) { - super(testContext); - } - - private View getHomePagerContainer() { - return mSolo.getView(R.id.home_screen_container); - } - - private ViewPager getHomePagerView() { - return (ViewPager) mSolo.getView(R.id.home_pager); - } - - private View getHomeBannerView() { - if (mSolo.waitForView(R.id.home_banner)) { - return mSolo.getView(R.id.home_banner); - } - return null; - } - - public AboutHomeComponent assertCurrentPanel(final PanelType expectedPanel) { - assertVisible(); - - final int expectedPanelIndex = PANEL_ORDERING.indexOf(expectedPanel); - fAssertEquals("The current HomePager panel is " + expectedPanel, - expectedPanelIndex, getHomePagerView().getCurrentItem()); - return this; - } - - public AboutHomeComponent assertNotVisible() { - fAssertTrue("The HomePager is not visible", - getHomePagerContainer().getVisibility() != View.VISIBLE || - getHomePagerView().getVisibility() != View.VISIBLE); - return this; - } - - public AboutHomeComponent assertVisible() { - fAssertTrue("The HomePager is visible", - getHomePagerContainer().getVisibility() == View.VISIBLE && - getHomePagerView().getVisibility() == View.VISIBLE); - return this; - } - - public AboutHomeComponent assertBannerNotVisible() { - View banner = getHomeBannerView(); - if (Build.VERSION.SDK_INT >= 11) { - fAssertTrue("The HomeBanner is not visible", - getHomePagerContainer().getVisibility() != View.VISIBLE || - banner == null || - banner.getVisibility() != View.VISIBLE || - banner.getTranslationY() == banner.getHeight()); - } else { - // getTranslationY is not available before api 11. - // This check is a little less specific. - fAssertTrue("The HomeBanner is not visible", - getHomePagerContainer().getVisibility() != View.VISIBLE || - banner == null || - banner.isShown() == false); - } - return this; - } - - public AboutHomeComponent assertBannerVisible() { - fAssertTrue("The HomeBanner is visible", - getHomePagerContainer().getVisibility() == View.VISIBLE && - getHomeBannerView().getVisibility() == View.VISIBLE); - return this; - } - - public AboutHomeComponent assertBannerText(String text) { - assertBannerVisible(); - - final TextView textView = (TextView) getHomeBannerView().findViewById(R.id.text); - fAssertEquals("The correct HomeBanner text is shown", - text, textView.getText().toString()); - return this; - } - - public AboutHomeComponent clickOnBanner() { - assertBannerVisible(); - - mTestContext.dumpLog(LOGTAG, "Clicking on HomeBanner."); - mSolo.clickOnView(getHomeBannerView()); - return this; - } - - public AboutHomeComponent dismissBanner() { - assertBannerVisible(); - - mTestContext.dumpLog(LOGTAG, "Clicking on HomeBanner close button."); - mSolo.clickOnView(getHomeBannerView().findViewById(R.id.close)); - return this; - } - - public AboutHomeComponent swipeToPanelOnRight() { - mTestContext.dumpLog(LOGTAG, "Swiping to the panel on the right."); - swipeToPanel(Solo.RIGHT); - return this; - } - - public AboutHomeComponent swipeToPanelOnLeft() { - mTestContext.dumpLog(LOGTAG, "Swiping to the panel on the left."); - swipeToPanel(Solo.LEFT); - return this; - } - - private void swipeToPanel(final int panelDirection) { - fAssertTrue("Swiping in a valid direction", - panelDirection == Solo.LEFT || panelDirection == Solo.RIGHT); - assertVisible(); - - final int panelIndex = getHomePagerView().getCurrentItem(); - - mSolo.scrollViewToSide(getHomePagerView(), panelDirection, SWIPE_PERCENTAGE); - - // The panel on the left is a lower index and vice versa. - final int unboundedPanelIndex = panelIndex + (panelDirection == Solo.LEFT ? -1 : 1); - final int maxPanelIndex = PANEL_ORDERING.size() - 1; - final int expectedPanelIndex = Math.min(Math.max(0, unboundedPanelIndex), maxPanelIndex); - - waitForPanelIndex(expectedPanelIndex); - } - - private void waitForPanelIndex(final int expectedIndex) { - final String panelName = PANEL_ORDERING.get(expectedIndex).name(); - - WaitHelper.waitFor("HomePager " + panelName + " panel", new Condition() { - @Override - public boolean isSatisfied() { - return (getHomePagerView().getCurrentItem() == expectedIndex); - } - }); - } - - /** - * Navigate directly to a built-in panel by its panel type. - *

- * If the panel type is not part of the active Home Panel configuration, the - * default about:home panel is displayed. If the panel type is not a - * built-in panel, an IllegalArgumentException is thrown. - * - * @param panelType to navigate to. - * @return self, for chaining. - */ - public AboutHomeComponent navigateToBuiltinPanelType(PanelType panelType) throws IllegalArgumentException { - Tabs.getInstance().loadUrl(AboutPages.getURLForBuiltinPanelType(panelType)); - final int expectedPanelIndex = PANEL_ORDERING.indexOf(panelType); - waitForPanelIndex(expectedPanelIndex); - return this; - } -} diff --git a/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/components/AppMenuComponent.java b/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/components/AppMenuComponent.java deleted file mode 100644 index 278cc7564..000000000 --- a/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/components/AppMenuComponent.java +++ /dev/null @@ -1,295 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -package org.mozilla.gecko.tests.components; - -import static org.mozilla.gecko.tests.helpers.AssertionHelper.fAssertEquals; -import static org.mozilla.gecko.tests.helpers.AssertionHelper.fAssertFalse; -import static org.mozilla.gecko.tests.helpers.AssertionHelper.fAssertNotNull; -import static org.mozilla.gecko.tests.helpers.AssertionHelper.fAssertTrue; - -import java.util.List; -import java.util.concurrent.Callable; - -import org.mozilla.gecko.AppConstants; -import org.mozilla.gecko.R; -import org.mozilla.gecko.menu.MenuItemActionBar; -import org.mozilla.gecko.menu.MenuItemDefault; -import org.mozilla.gecko.tests.UITestContext; -import org.mozilla.gecko.tests.helpers.DeviceHelper; -import org.mozilla.gecko.tests.helpers.RobotiumHelper; -import org.mozilla.gecko.tests.helpers.WaitHelper; - -import android.text.TextUtils; -import android.view.View; -import android.widget.TextView; -import android.widget.RelativeLayout; - -import com.robotium.solo.Condition; -import com.robotium.solo.RobotiumUtils; -import com.robotium.solo.Solo; - -/** - * A class representing any interactions that take place on the app menu. - */ -public class AppMenuComponent extends BaseComponent { - private static final int MAX_WAITTIME_FOR_MENU_UPDATE_IN_MS = 7500; - - public enum MenuItem { - FORWARD(R.string.forward), - NEW_TAB(R.string.new_tab), - PAGE(R.string.page), - RELOAD(R.string.reload); - - private final int resourceID; - private String stringResource; - - MenuItem(final int resourceID) { - this.resourceID = resourceID; - } - - public String getString(final Solo solo) { - if (stringResource == null) { - stringResource = solo.getString(resourceID); - } - - return stringResource; - } - }; - - public enum PageMenuItem { - SAVE_AS_PDF(R.string.save_as_pdf); - - private static final MenuItem PARENT_MENU = MenuItem.PAGE; - - private final int resourceID; - private String stringResource; - - PageMenuItem(final int resourceID) { - this.resourceID = resourceID; - } - - public String getString(final Solo solo) { - if (stringResource == null) { - stringResource = solo.getString(resourceID); - } - - return stringResource; - } - }; - - public AppMenuComponent(final UITestContext testContext) { - super(testContext); - } - - public void assertMenuIsOpen() { - fAssertTrue("Menu is open", isMenuOpen()); - } - - public void assertMenuIsNotOpen() { - fAssertFalse("Menu is not open", isMenuOpen()); - } - - public void assertMenuItemIsDisabledAndVisible(PageMenuItem pageMenuItem) { - openAppMenu(); - - // Non-legacy devices have hierarchical menu, check for parent menu item "page". - final View parentMenuItemView = findAppMenuItemView(MenuItem.PAGE.getString(mSolo)); - if (parentMenuItemView.isEnabled()) { - fAssertTrue("The parent 'page' menu item is enabled", parentMenuItemView.isEnabled()); - fAssertEquals("The parent 'page' menu item is visible", View.VISIBLE, - parentMenuItemView.getVisibility()); - - // Parent menu "page" is enabled, open page menu and check for menu item represented by pageMenuItem. - pressMenuItem(MenuItem.PAGE.getString(mSolo)); - - final View pageMenuItemView = findAppMenuItemView(pageMenuItem.getString(mSolo)); - fAssertNotNull("The page menu item is not null", pageMenuItemView); - fAssertFalse("The page menu item is not enabled", pageMenuItemView.isEnabled()); - fAssertEquals("The page menu item is visible", View.VISIBLE, pageMenuItemView.getVisibility()); - } else { - fAssertFalse("The parent 'page' menu item is not enabled", parentMenuItemView.isEnabled()); - fAssertEquals("The parent 'page' menu item is visible", View.VISIBLE, parentMenuItemView.getVisibility()); - } - // Close the App Menu. - mSolo.goBack(); - } - - private View getOverflowMenuButtonView() { - return mSolo.getView(R.id.menu); - } - - /** - * Try to find a MenuItemActionBar/MenuItemDefault with the given text set as contentDescription / text. - * - * When using legacy menus, make sure the menu has been opened to the appropriate level - * (i.e. base menu or "More" menu) to ensure the appropriate menu views are in memory. - * TODO: ^ Maybe we just need to have opened the "More" menu and the current one doesn't matter. - * - * This method is dependent on not having two views with equivalent contentDescription / text. - */ - private View findAppMenuItemView(final String text) { - return WaitHelper.waitFor(String.format("menu item view '%s'", text), new Callable() { - @Override - public View call() throws Exception { - final List views = mSolo.getViews(); - - final List menuItemActionBarList = RobotiumUtils.filterViews(MenuItemActionBar.class, views); - for (MenuItemActionBar menuItem : menuItemActionBarList) { - if (TextUtils.equals(menuItem.getContentDescription(), text)) { - return menuItem; - } - } - - final List menuItemDefaultList = RobotiumUtils.filterViews(MenuItemDefault.class, views); - for (MenuItemDefault menuItem : menuItemDefaultList) { - if (TextUtils.equals(menuItem.getText(), text)) { - return menuItem; - } - } - - // On Android 2.3, menu items may be instances of - // com.android.internal.view.menu.ListMenuItemView, each with a child - // android.widget.RelativeLayout which in turn has a child - // TextView with the appropriate text. - final List textViewList = RobotiumUtils.filterViews(TextView.class, views); - for (TextView textView : textViewList) { - if (TextUtils.equals(textView.getText(), text)) { - View relativeLayout = (View) textView.getParent(); - if (relativeLayout instanceof RelativeLayout) { - View listMenuItemView = (View)relativeLayout.getParent(); - return listMenuItemView; - } - } - } - return null; - } - }, MAX_WAITTIME_FOR_MENU_UPDATE_IN_MS); - } - - /** - * Helper function to let Robotium locate and click menu item from legacy Android menu (devices with Android 2.x). - * - * Robotium will also try to open the menu if there are no open dialog. - * - * @param menuItemTitle, The title of menu item to open. - */ - private void pressLegacyMenuItem(final String menuItemTitle) { - mSolo.clickOnMenuItem(menuItemTitle, true); - } - - private void pressMenuItem(final String menuItemTitle) { - // Wait for the menu item view to be enabled. This improves reliability on Android 2.3. - WaitHelper.waitFor(String.format("menu item %s to be enabled", menuItemTitle), new Condition() { - @Override - public boolean isSatisfied() { - View v = findAppMenuItemView(menuItemTitle); - return (v != null) && v.isEnabled(); - } - }); - - final View menuItemView = findAppMenuItemView(menuItemTitle); - fAssertTrue("Menu is open", isMenuOpen(menuItemView)); - - fAssertTrue(String.format("The menu item %s is enabled", menuItemTitle), menuItemView.isEnabled()); - fAssertEquals(String.format("The menu item %s is visible", menuItemTitle), View.VISIBLE, - menuItemView.getVisibility()); - - mSolo.clickOnView(menuItemView); - } - - private void pressSubMenuItem(final String parentMenuItemTitle, final String childMenuItemTitle) { - openAppMenu(); - - pressMenuItem(parentMenuItemTitle); - - // Child menu item is not pressed yet, Click on it. - pressMenuItem(childMenuItemTitle); - } - - public void pressMenuItem(MenuItem menuItem) { - openAppMenu(); - pressMenuItem(menuItem.getString(mSolo)); - } - - public void pressMenuItem(final PageMenuItem pageMenuItem) { - pressSubMenuItem(PageMenuItem.PARENT_MENU.getString(mSolo), pageMenuItem.getString(mSolo)); - } - - private void openAppMenu() { - assertMenuIsNotOpen(); - - // This is a hack needed for tablets where the OverflowMenuButton is always in the GONE state, - // so we press the menu key instead. - if (DeviceHelper.isTablet()) { - mSolo.sendKey(Solo.MENU); - } else { - pressOverflowMenuButton(); - } - - waitForMenuOpen(); - } - - private void pressOverflowMenuButton() { - final View overflowMenuButton = getOverflowMenuButtonView(); - - fAssertTrue("The overflow menu button is enabled", overflowMenuButton.isEnabled()); - fAssertEquals("The overflow menu button is visible", View.VISIBLE, overflowMenuButton.getVisibility()); - - mSolo.clickOnView(overflowMenuButton, true); - } - - /** - * Determines whether the app menu is open by searching for items in the menu. - * - * @return true if app menu is open. - */ - private boolean isMenuOpen() { - // We choose these options because New Tab is near the top of the menu and Page is near the middle/bottom. - // Intermittently, the menu doesn't scroll to top so we can't just use the first item in the list. - return isMenuOpen(MenuItem.NEW_TAB.getString(mSolo)) || isMenuOpen(MenuItem.PAGE.getString(mSolo)); - } - - /** - * Determines whether the app menu is open by searching for the text in menuItemTitle. - * - * @param menuItemTitle, The contentDescription of menu item to search. - * - * @return true if app menu is open. - */ - private boolean isMenuOpen(String menuItemTitle) { - final View menuItemView = findAppMenuItemView(menuItemTitle); - return isMenuOpen(menuItemView) ? true : RobotiumHelper.searchExactText(menuItemTitle, true); - } - - /** - * If a ListMenuItemView with menuItemTitle is visible then the app menu is open . - * - * @param menuItemView, must be a ListMenuItemView with menuItemTitle. - * You must use findAppMenuItemView(menuItemTitle) to obtain it. - * - * @return true if app menu is open. - */ - private boolean isMenuOpen(View menuItemView) { - return (menuItemView != null) && (menuItemView.getVisibility() == View.VISIBLE); - } - - public void waitForMenuOpen() { - WaitHelper.waitFor("menu to open", new Condition() { - @Override - public boolean isSatisfied() { - return isMenuOpen(); - } - }); - } - - public void waitForMenuClose() { - WaitHelper.waitFor("menu to close", new Condition() { - @Override - public boolean isSatisfied() { - return !isMenuOpen(); - } - }); - } -} diff --git a/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/components/BaseComponent.java b/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/components/BaseComponent.java deleted file mode 100644 index eadaaa173..000000000 --- a/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/components/BaseComponent.java +++ /dev/null @@ -1,36 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -package org.mozilla.gecko.tests.components; - -import org.mozilla.gecko.Actions; -import org.mozilla.gecko.tests.StringHelper; -import org.mozilla.gecko.tests.UITestContext; - -import android.app.Activity; - -import com.robotium.solo.Solo; - -/** - * A base class for constructing components - an abstraction over small bits of Firefox - * functionality. For example, the Toolbar or the about:home screen could be considered a - * component. Components should not need to know about each others existences and should be - * combined via helpers. Helpers can also handle a series of actions taken on one component - * (e.g. clicking the toolbar, entering a url, and waiting for page load). - */ -public abstract class BaseComponent { - protected final UITestContext mTestContext; - protected final Activity mActivity; - protected final Solo mSolo; - protected final Actions mActions; - protected final StringHelper mStringHelper; - - public BaseComponent(final UITestContext testContext) { - mTestContext = testContext; - mActivity = mTestContext.getActivity(); - mSolo = mTestContext.getSolo(); - mActions = mTestContext.getActions(); - mStringHelper = mTestContext.getStringHelper(); - } -} diff --git a/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/components/GeckoViewComponent.java b/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/components/GeckoViewComponent.java deleted file mode 100644 index 3beab3169..000000000 --- a/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/components/GeckoViewComponent.java +++ /dev/null @@ -1,343 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -package org.mozilla.gecko.tests.components; - -import static org.mozilla.gecko.tests.helpers.AssertionHelper.fAssertEquals; -import static org.mozilla.gecko.tests.helpers.AssertionHelper.fAssertNotNull; -import static org.mozilla.gecko.tests.helpers.AssertionHelper.fAssertNotSame; -import static org.mozilla.gecko.tests.helpers.AssertionHelper.fAssertSame; -import static org.mozilla.gecko.tests.helpers.AssertionHelper.fAssertTrue; - -import org.mozilla.gecko.GeckoThread; -import org.mozilla.gecko.R; -import org.mozilla.gecko.tests.UITestContext; -import org.mozilla.gecko.tests.helpers.FrameworkHelper; -import org.mozilla.gecko.tests.helpers.WaitHelper; - -import android.content.Context; -import android.content.ContextWrapper; -import android.os.Handler; -import android.os.Looper; -import android.os.Message; -import android.os.MessageQueue; -import android.view.View; -import android.view.inputmethod.EditorInfo; -import android.view.inputmethod.ExtractedText; -import android.view.inputmethod.ExtractedTextRequest; -import android.view.inputmethod.InputConnection; -import android.view.inputmethod.InputMethodManager; - -import com.robotium.solo.Condition; - -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; - -/** - * A class representing any interactions that take place on GeckoView. - */ -public class GeckoViewComponent extends BaseComponent { - - public final TextInput mTextInput; - - public GeckoViewComponent(final UITestContext testContext) { - super(testContext); - mTextInput = new TextInput(); - } - - /** - * Returns the GeckoView. - */ - private View getView() { - // Solo.getView asserts returning a valid View - return mSolo.getView(R.id.layer_view); - } - - private void setContext(final Context newContext) { - final View geckoView = getView(); - // Switch to a no-InputMethodManager context to avoid interference - mTestContext.getInstrumentation().runOnMainSync(new Runnable() { - @Override - public void run() { - FrameworkHelper.setViewContext(geckoView, newContext); - } - }); - } - - public static abstract class InputConnectionTest { - protected Handler inputConnectionHandler; - - /** - * Processes pending events on the input connection thread before returning. - * Must be called on the input connection thread during a test. - */ - protected void processInputConnectionEvents() { - fAssertSame("Should be called on input connection thread", - Looper.myLooper(), inputConnectionHandler.getLooper()); - - // Adapted from GeckoThread.pumpMessageLoop. - MessageQueue queue = Looper.myQueue(); - queue.addIdleHandler(new MessageQueue.IdleHandler() { - @Override - public boolean queueIdle() { - final Message msg = Message.obtain(inputConnectionHandler); - msg.obj = inputConnectionHandler; - inputConnectionHandler.sendMessageAtFrontOfQueue(msg); - return false; // Remove this idle handler. - } - }); - - final Method getNextMessage; - try { - getNextMessage = queue.getClass().getDeclaredMethod("next"); - } catch (final NoSuchMethodException e) { - throw new UnsupportedOperationException(e); - } - getNextMessage.setAccessible(true); - - while (true) { - final Message msg; - try { - msg = (Message) getNextMessage.invoke(queue); - } catch (final IllegalAccessException | InvocationTargetException e) { - throw new UnsupportedOperationException(e); - } - if (msg.obj == inputConnectionHandler && - msg.getTarget() == inputConnectionHandler) { - // Our idle signal - break; - } else if (msg.getTarget() == null) { - Looper.myLooper().quit(); - break; - } - msg.getTarget().dispatchMessage(msg); - } - } - - /** - * Processes pending events on the Gecko thread before returning. - * Must be called on the input connection thread during a test. - */ - protected void processGeckoEvents() { - fAssertSame("Should be called on input connection thread", - Looper.myLooper(), inputConnectionHandler.getLooper()); - - GeckoThread.waitOnGecko(); - } - - private static ExtractedText getExtractedText(final InputConnection ic) { - final ExtractedTextRequest req = new ExtractedTextRequest(); - return ic.getExtractedText(req, 0); - } - - protected String getText(final InputConnection ic) { - return getExtractedText(ic).text.toString(); - } - - private static void assertText(final String message, - final String expected, - final String actual) { - // In an HTML editor, Gecko may insert an additional element that show up as a - // return character at the end. Deal with that here. - int end = actual.length(); - if (end > 0 && actual.charAt(end - 1) == '\n') { - end--; - } - fAssertEquals(message, expected, actual.substring(0, end)); - } - - protected void assertText(final String message, - final InputConnection ic, - final String text) { - processGeckoEvents(); - processInputConnectionEvents(); - - assertText(message, text, getText(ic)); - } - - protected void assertSelection(final String message, - final InputConnection ic, - final int start, - final int end) { - processGeckoEvents(); - processInputConnectionEvents(); - - final ExtractedText extract = getExtractedText(ic); - fAssertEquals(message, start, extract.selectionStart); - fAssertEquals(message, end, extract.selectionEnd); - } - - protected void assertSelectionAt(final String message, - final InputConnection ic, - final int value) { - assertSelection(message, ic, value, value); - } - - protected void assertTextAndSelection(final String message, - final InputConnection ic, - final String text, - final int start, - final int end) { - processGeckoEvents(); - processInputConnectionEvents(); - - final ExtractedText extract = getExtractedText(ic); - assertText(message, text, extract.text.toString()); - fAssertEquals(message, start, extract.selectionStart); - fAssertEquals(message, end, extract.selectionEnd); - } - - protected void assertTextAndSelectionAt(final String message, - final InputConnection ic, - final String text, - final int selection) { - assertTextAndSelection(message, ic, text, selection, selection); - } - - public abstract void test(InputConnection ic, EditorInfo info); - } - - public class TextInput { - private TextInput() { - } - - private InputMethodManager getInputMethodManager() { - final InputMethodManager imm = (InputMethodManager) - mActivity.getSystemService(Context.INPUT_METHOD_SERVICE); - fAssertNotNull("Must have an InputMethodManager", imm); - return imm; - } - - /** - * Returns whether text input is being directed to the GeckoView. - */ - private boolean isActive() { - return getInputMethodManager().isActive(getView()); - } - - public TextInput assertActive() { - fAssertTrue("Current view should be the active input view", isActive()); - return this; - } - - public TextInput waitForActive() { - WaitHelper.waitFor("current view to become the active input view", new Condition() { - @Override - public boolean isSatisfied() { - return isActive(); - } - }); - return this; - } - - /** - * Returns whether an InputConnection is available. - * An InputConnection is available when text input is being directed to the - * GeckoView, and a text field (input, textarea, contentEditable, etc.) is - * currently focused inside the GeckoView. - */ - private boolean hasInputConnection() { - final InputMethodManager imm = getInputMethodManager(); - return imm.isActive(getView()) && imm.isAcceptingText(); - } - - public TextInput assertInputConnection() { - fAssertTrue("Current view should have an active InputConnection", hasInputConnection()); - return this; - } - - public TextInput waitForInputConnection() { - WaitHelper.waitFor("current view to have an active InputConnection", new Condition() { - @Override - public boolean isSatisfied() { - return hasInputConnection(); - } - }); - return this; - } - - /** - * Starts an InputConnectionTest. An InputConnectionTest must run on the - * InputConnection thread which may or may not be the main UI thread. Also, - * during an InputConnectionTest, the system InputMethodManager service must - * be temporarily disabled to prevent the system IME from interfering with our - * tests. We disable the service by override the GeckoView's context with one - * that returns a null InputMethodManager service. - * - * @param test Test to run - */ - public TextInput testInputConnection(final InputConnectionTest test) { - - fAssertNotNull("Test must not be null", test); - assertInputConnection(); - - // GeckoInputConnection can run on another thread than the main thread, - // so we need to be testing it on that same thread it's running on - final View geckoView = getView(); - final Handler inputConnectionHandler = geckoView.getHandler(); - final Context oldGeckoViewContext = FrameworkHelper.getViewContext(geckoView); - - setContext(new ContextWrapper(oldGeckoViewContext) { - @Override - public Object getSystemService(String name) { - if (Context.INPUT_METHOD_SERVICE.equals(name)) { - return null; - } - return super.getSystemService(name); - } - }); - - (new InputConnectionTestRunner(test, inputConnectionHandler)).launch(); - - setContext(oldGeckoViewContext); - return this; - } - - private class InputConnectionTestRunner implements Runnable { - private final InputConnectionTest mTest; - private boolean mDone; - - public InputConnectionTestRunner(final InputConnectionTest test, - final Handler handler) { - test.inputConnectionHandler = handler; - mTest = test; - } - - public synchronized void launch() { - // Below, we are blocking the instrumentation thread to wait on the - // InputConnection thread. Therefore, the InputConnection thread must not be - // the same as the instrumentation thread to avoid a deadlock. This should - // always be the case and we perform a sanity check to make sure. - fAssertNotSame("InputConnection should not be running on instrumentation thread", - Looper.myLooper(), mTest.inputConnectionHandler.getLooper()); - - mDone = false; - mTest.inputConnectionHandler.post(this); - do { - try { - wait(); - } catch (InterruptedException e) { - // Ignore interrupts - } - } while (!mDone); - } - - @Override - public void run() { - final EditorInfo info = new EditorInfo(); - final InputConnection ic = getView().onCreateInputConnection(info); - fAssertNotNull("Must have an InputConnection", ic); - // Restore the IC to a clean state - ic.clearMetaKeyStates(-1); - ic.finishComposingText(); - mTest.test(ic, info); - synchronized (this) { - // Test finished; return from launch(). - mDone = true; - notify(); - } - } - } - } -} diff --git a/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/components/TabStripComponent.java b/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/components/TabStripComponent.java deleted file mode 100644 index e8a90b351..000000000 --- a/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/components/TabStripComponent.java +++ /dev/null @@ -1,56 +0,0 @@ -package org.mozilla.gecko.tests.components; - -import android.view.View; - -import com.robotium.solo.Condition; - -import org.mozilla.gecko.tests.UITestContext; -import org.mozilla.gecko.tests.helpers.DeviceHelper; -import org.mozilla.gecko.tests.helpers.WaitHelper; -import org.mozilla.gecko.widget.TwoWayView; - -import static org.mozilla.gecko.tests.helpers.AssertionHelper.*; - -/** - * A class representing any interactions that take place on the tablet tab strip. - */ -public class TabStripComponent extends BaseComponent { - // Using a text id because the layout and therefore the id might be stripped from the (non-tablet) build - private static final String TAB_STRIP_ID = "tab_strip"; - - public TabStripComponent(final UITestContext testContext) { - super(testContext); - } - - public void switchToTab(int index) { - // The tab strip is only available on tablets - DeviceHelper.assertIsTablet(); - - View tabView = waitForTabView(index); - fAssertNotNull(String.format("Tab at index %d is not null", index), tabView); - - mSolo.clickOnView(tabView); - } - - private View waitForTabView(final int index) { - final TwoWayView tabStrip = getTabStripView(); - final View[] tabView = new View[1]; - - WaitHelper.waitFor(String.format("Tab at index %d to be visible", index), new Condition() { - @Override - public boolean isSatisfied() { - return (tabView[0] = tabStrip.getChildAt(index)) != null; - } - }); - - return tabView[0]; - } - - private TwoWayView getTabStripView() { - TwoWayView tabStrip = (TwoWayView) mSolo.getView("tab_strip"); - - fAssertNotNull("Tab strip is not null", tabStrip); - - return tabStrip; - } -} diff --git a/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/components/ToolbarComponent.java b/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/components/ToolbarComponent.java deleted file mode 100644 index 25101a395..000000000 --- a/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/components/ToolbarComponent.java +++ /dev/null @@ -1,326 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -package org.mozilla.gecko.tests.components; - -import static org.mozilla.gecko.tests.helpers.AssertionHelper.fAssertEquals; -import static org.mozilla.gecko.tests.helpers.AssertionHelper.fAssertFalse; -import static org.mozilla.gecko.tests.helpers.AssertionHelper.fAssertNotNull; -import static org.mozilla.gecko.tests.helpers.AssertionHelper.fAssertTrue; - -import org.mozilla.gecko.R; -import org.mozilla.gecko.tests.UITestContext; -import org.mozilla.gecko.tests.helpers.DeviceHelper; -import org.mozilla.gecko.tests.helpers.NavigationHelper; -import org.mozilla.gecko.tests.helpers.WaitHelper; -import org.mozilla.gecko.toolbar.PageActionLayout; - -import android.view.View; -import android.widget.EditText; -import android.widget.ImageButton; -import android.widget.TextView; - -import com.robotium.solo.Condition; -import com.robotium.solo.Solo; - -/** - * A class representing any interactions that take place on the Toolbar. - */ -public class ToolbarComponent extends BaseComponent { - - private static final String URL_HTTP_PREFIX = "http://"; - - // We are waiting up to 30 seconds instead of the default waiting time because reader mode - // parsing can take quite some time on slower devices (Bug 1142699) - private static final int READER_MODE_WAIT_MS = 30000; - - public ToolbarComponent(final UITestContext testContext) { - super(testContext); - } - - public ToolbarComponent assertIsEditing() { - fAssertTrue("The toolbar is in the editing state", isEditing()); - return this; - } - - public ToolbarComponent assertIsNotEditing() { - fAssertFalse("The toolbar is not in the editing state", isEditing()); - return this; - } - - public ToolbarComponent assertTitle(final String url) { - fAssertNotNull("The url argument is not null", url); - - final String expected; - final String absoluteURL = NavigationHelper.adjustUrl(url); - - if (mStringHelper.ABOUT_HOME_URL.equals(absoluteURL)) { - expected = mStringHelper.ABOUT_HOME_TITLE; - } else if (absoluteURL.startsWith(URL_HTTP_PREFIX)) { - expected = absoluteURL.substring(URL_HTTP_PREFIX.length()); - } else { - expected = absoluteURL; - } - - // Since we only display a shortened "base domain" (See bug 1236431) we use the content - // description to obtain the full URL. - fAssertEquals("The Toolbar title is " + expected, expected, getUrlFromContentDescription()); - return this; - } - - public ToolbarComponent assertUrl(final String expected) { - assertIsEditing(); - fAssertEquals("The Toolbar url is " + expected, expected, getUrlEditText().getText()); - return this; - } - - public ToolbarComponent assertIsUrlEditTextSelected() { - fAssertTrue("The edit text is selected", isUrlEditTextSelected()); - return this; - } - - public ToolbarComponent assertIsUrlEditTextNotSelected() { - fAssertFalse("The edit text is not selected", isUrlEditTextSelected()); - return this; - } - - public ToolbarComponent assertBackButtonIsNotEnabled() { - fAssertFalse("The back button is not enabled", isBackButtonEnabled()); - return this; - } - - /** - * Returns the root View for the browser toolbar. - */ - private View getToolbarView() { - mSolo.waitForView(R.id.browser_toolbar); - return mSolo.getView(R.id.browser_toolbar); - } - - private EditText getUrlEditText() { - return (EditText) getToolbarView().findViewById(R.id.url_edit_text); - } - - private View getUrlDisplayLayout() { - return getToolbarView().findViewById(R.id.display_layout); - } - - private TextView getUrlTitleText() { - return (TextView) getToolbarView().findViewById(R.id.url_bar_title); - } - - private ImageButton getBackButton() { - DeviceHelper.assertIsTablet(); - return (ImageButton) getToolbarView().findViewById(R.id.back); - } - - private ImageButton getForwardButton() { - DeviceHelper.assertIsTablet(); - return (ImageButton) getToolbarView().findViewById(R.id.forward); - } - - private ImageButton getReloadButton() { - DeviceHelper.assertIsTablet(); - return (ImageButton) getToolbarView().findViewById(R.id.reload); - } - - private PageActionLayout getPageActionLayout() { - return (PageActionLayout) getToolbarView().findViewById(R.id.page_action_layout); - } - - private ImageButton getReaderModeButton() { - final PageActionLayout pageActionLayout = getPageActionLayout(); - final int count = pageActionLayout.getChildCount(); - - for (int i = 0; i < count; i++) { - final View view = pageActionLayout.getChildAt(i); - if (mStringHelper.CONTENT_DESCRIPTION_READER_MODE_BUTTON.equals(view.getContentDescription())) { - return (ImageButton) view; - } - } - - return null; - } - - /** - * Returns the View for the edit cancel button in the browser toolbar. - */ - private View getEditCancelButton() { - return getToolbarView().findViewById(R.id.edit_cancel); - } - - private String getUrlFromContentDescription() { - assertIsNotEditing(); - - final CharSequence contentDescription = getUrlDisplayLayout().getContentDescription(); - if (contentDescription == null) { - return ""; - } else { - return contentDescription.toString(); - } - } - - /** - * Returns the title of the page. Note that this makes no assertions to Toolbar state and - * may return a value that may never be visible to the user. Callers likely want to use - * {@link assertTitle} instead. - */ - public String getPotentiallyInconsistentTitle() { - return getTitleHelper(false); - } - - private String getTitleHelper(final boolean shouldAssertNotEditing) { - if (shouldAssertNotEditing) { - assertIsNotEditing(); - } - - return getUrlTitleText().getText().toString(); - } - - private boolean isEditing() { - return getUrlDisplayLayout().getVisibility() != View.VISIBLE && - getUrlEditText().getVisibility() == View.VISIBLE; - } - - public ToolbarComponent enterEditingMode() { - assertIsNotEditing(); - - mSolo.clickOnView(getUrlTitleText(), true); - - waitForEditing(); - WaitHelper.waitFor("UrlEditText to be input method target", new Condition() { - @Override - public boolean isSatisfied() { - return getUrlEditText().isInputMethodTarget(); - } - }); - - return this; - } - - public ToolbarComponent commitEditingMode() { - assertIsEditing(); - - WaitHelper.waitForPageLoad(new Runnable() { - @Override - public void run() { - mSolo.sendKey(Solo.ENTER); - } - }); - waitForNotEditing(); - - return this; - } - - public ToolbarComponent dismissEditingMode() { - assertIsEditing(); - - if (DeviceHelper.isTablet()) { - final EditText urlEditText = getUrlEditText(); - if (urlEditText.isFocused()) { - mSolo.goBack(); - } - mSolo.goBack(); - } else { - mSolo.clickOnView(getEditCancelButton()); - } - - waitForNotEditing(); - - return this; - } - - public ToolbarComponent enterUrl(final String url) { - fAssertNotNull("url is not null", url); - - assertIsEditing(); - - final EditText urlEditText = getUrlEditText(); - fAssertTrue("The UrlEditText is the input method target", - urlEditText.isInputMethodTarget()); - - mSolo.clearEditText(urlEditText); - mSolo.typeText(urlEditText, url); - - return this; - } - - public ToolbarComponent pressBackButton() { - final ImageButton backButton = getBackButton(); - return pressButton(backButton, "back"); - } - - public ToolbarComponent pressForwardButton() { - final ImageButton forwardButton = getForwardButton(); - return pressButton(forwardButton, "forward"); - } - - public ToolbarComponent pressReloadButton() { - final ImageButton reloadButton = getReloadButton(); - return pressButton(reloadButton, "reload"); - } - - public ToolbarComponent pressReaderModeButton() { - final ImageButton readerModeButton = waitForReaderModeButton(); - pressButton(readerModeButton, "reader mode"); - - return this; - } - - private ToolbarComponent pressButton(final View view, final String buttonName) { - fAssertNotNull("The " + buttonName + " button View is not null", view); - fAssertTrue("The " + buttonName + " button is enabled", view.isEnabled()); - fAssertEquals("The " + buttonName + " button is visible", - View.VISIBLE, view.getVisibility()); - assertIsNotEditing(); - - WaitHelper.waitForPageLoad(new Runnable() { - @Override - public void run() { - mSolo.clickOnView(view); - } - }); - - return this; - } - - private void waitForEditing() { - WaitHelper.waitFor("Toolbar to enter editing mode", new Condition() { - @Override - public boolean isSatisfied() { - return isEditing(); - } - }); - } - - private void waitForNotEditing() { - WaitHelper.waitFor("Toolbar to exit editing mode", new Condition() { - @Override - public boolean isSatisfied() { - return !isEditing(); - } - }); - } - - private ImageButton waitForReaderModeButton() { - final ImageButton[] readerModeButton = new ImageButton[1]; - - WaitHelper.waitFor("the Reader mode button to be visible", new Condition() { - @Override - public boolean isSatisfied() { - return (readerModeButton[0] = getReaderModeButton()) != null; - } - }, READER_MODE_WAIT_MS); - - return readerModeButton[0]; - } - - private boolean isUrlEditTextSelected() { - return getUrlEditText().isSelected(); - } - - private boolean isBackButtonEnabled() { - return getBackButton().isEnabled(); - } -} diff --git a/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/helpers/AssertionHelper.java b/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/helpers/AssertionHelper.java deleted file mode 100644 index 894d134d1..000000000 --- a/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/helpers/AssertionHelper.java +++ /dev/null @@ -1,112 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -package org.mozilla.gecko.tests.helpers; - -import java.util.Arrays; - -import org.mozilla.gecko.Assert; -import org.mozilla.gecko.tests.UITestContext; - -/** - * Provides assertions in a JUnit-like API that wraps the robocop Assert interface. - */ -public final class AssertionHelper { - // Assert.ok has a "diag" ("diagnostic") parameter that has no useful purpose. - private static final String DIAG_STRING = ""; - - private static Assert sAsserter; - - private AssertionHelper() { /* To disallow instantiation. */ } - - protected static void init(final UITestContext context) { - sAsserter = context.getAsserter(); - } - - public static void fAssertArrayEquals(final String message, final byte[] expecteds, final byte[] actuals) { - sAsserter.ok(Arrays.equals(expecteds, actuals), message, DIAG_STRING); - } - - public static void fAssertArrayEquals(final String message, final char[] expecteds, final char[] actuals) { - sAsserter.ok(Arrays.equals(expecteds, actuals), message, DIAG_STRING); - } - - public static void fAssertArrayEquals(final String message, final short[] expecteds, final short[] actuals) { - sAsserter.ok(Arrays.equals(expecteds, actuals), message, DIAG_STRING); - } - - public static void fAssertArrayEquals(final String message, final int[] expecteds, final int[] actuals) { - sAsserter.ok(Arrays.equals(expecteds, actuals), message, DIAG_STRING); - } - - public static void fAssertArrayEquals(final String message, final long[] expecteds, final long[] actuals) { - sAsserter.ok(Arrays.equals(expecteds, actuals), message, DIAG_STRING); - } - - public static void fAssertArrayEquals(final String message, final Object[] expecteds, final Object[] actuals) { - sAsserter.ok(Arrays.equals(expecteds, actuals), message, DIAG_STRING); - } - - public static void fAssertEquals(final String message, final double expected, final double actual, final double delta) { - if (Double.compare(expected, actual) != 0) { - sAsserter.ok(Math.abs(expected - actual) <= delta, message, DIAG_STRING); - } - } - - public static void fAssertEquals(final String message, final long expected, final long actual) { - sAsserter.is(actual, expected, message); - } - - public static void fAssertEquals(final String message, final Object expected, final Object actual) { - sAsserter.is(actual, expected, message); - } - - public static void fAssertNotEquals(final String message, final double unexpected, final double actual, final double delta) { - sAsserter.ok(Math.abs(unexpected - actual) > delta, message, DIAG_STRING); - } - - public static void fAssertNotEquals(final String message, final long unexpected, final long actual) { - sAsserter.isnot(actual, unexpected, message); - } - - public static void fAssertNotEquals(final String message, final Object unexpected, final Object actual) { - sAsserter.isnot(actual, unexpected, message); - } - - public static void fAssertFalse(final String message, final boolean actual) { - sAsserter.ok(!actual, message, DIAG_STRING); - } - - public static void fAssertNotNull(final String message, final Object actual) { - sAsserter.isnot(actual, null, message); - } - - public static void fAssertNotSame(final String message, final Object unexpected, final Object actual) { - sAsserter.ok(unexpected != actual, message, DIAG_STRING); - } - - public static void fAssertNull(final String message, final Object actual) { - sAsserter.is(actual, null, message); - } - - public static void fAssertSame(final String message, final Object expected, final Object actual) { - sAsserter.ok(expected == actual, message, DIAG_STRING); - } - - public static void fAssertTrue(final String message, final boolean actual) { - sAsserter.ok(actual, message, DIAG_STRING); - } - - public static void fAssertIsPixel(final String message, final int actual, final int r, final int g, final int b) { - sAsserter.ispixel(actual, r, g, b, message); - } - - public static void fAssertIsNotPixel(final String message, final int actual, final int r, final int g, final int b) { - sAsserter.isnotpixel(actual, r, g, b, message); - } - - public static void fFail(final String message) { - sAsserter.ok(false, message, DIAG_STRING); - } -} diff --git a/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/helpers/DeviceHelper.java b/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/helpers/DeviceHelper.java deleted file mode 100644 index 476bd34dd..000000000 --- a/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/helpers/DeviceHelper.java +++ /dev/null @@ -1,108 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -package org.mozilla.gecko.tests.helpers; - -import static org.mozilla.gecko.tests.helpers.AssertionHelper.fAssertTrue; - -import org.mozilla.gecko.GeckoAppShell; -import org.mozilla.gecko.tests.UITestContext; - -import android.app.Activity; -import android.os.Build; -import android.util.DisplayMetrics; - -import com.robotium.solo.Solo; - -/** - * Provides general hardware (ex: configuration) and software (ex: version) information - * about the current test device and allows changing its configuration. - */ -public final class DeviceHelper { - public enum Type { - PHONE, - TABLET - } - - public enum AndroidVersion { - v2x, - v3x, - v4x - } - - private static Activity sActivity; - private static Solo sSolo; - - private static Type sDeviceType; - private static AndroidVersion sAndroidVersion; - - private static int sScreenHeight; - private static int sScreenWidth; - - private DeviceHelper() { /* To disallow instantiation. */ } - - public static void assertIsTablet() { - fAssertTrue("The device is a tablet", isTablet()); - } - - protected static void init(final UITestContext context) { - sActivity = context.getActivity(); - sSolo = context.getSolo(); - - setAndroidVersion(); - setScreenDimensions(); - setDeviceType(); - } - - private static void setAndroidVersion() { - int sdk = Build.VERSION.SDK_INT; - if (sdk < Build.VERSION_CODES.HONEYCOMB) { - sAndroidVersion = AndroidVersion.v2x; - } else if (sdk > Build.VERSION_CODES.HONEYCOMB_MR2) { - sAndroidVersion = AndroidVersion.v4x; - } else { - sAndroidVersion = AndroidVersion.v3x; - } - } - - private static void setScreenDimensions() { - final DisplayMetrics dm = new DisplayMetrics(); - sActivity.getWindowManager().getDefaultDisplay().getMetrics(dm); - - sScreenHeight = dm.heightPixels; - sScreenWidth = dm.widthPixels; - } - - private static void setDeviceType() { - sDeviceType = (GeckoAppShell.isTablet() ? Type.TABLET : Type.PHONE); - } - - public static int getScreenHeight() { - return sScreenHeight; - } - - public static int getScreenWidth() { - return sScreenWidth; - } - - public static AndroidVersion getAndroidVersion() { - return sAndroidVersion; - } - - public static boolean isPhone() { - return (sDeviceType == Type.PHONE); - } - - public static boolean isTablet() { - return (sDeviceType == Type.TABLET); - } - - public static void setLandscapeRotation() { - sSolo.setActivityOrientation(Solo.LANDSCAPE); - } - - public static void setPortraitOrientation() { - sSolo.setActivityOrientation(Solo.LANDSCAPE); - } -} diff --git a/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/helpers/FrameworkHelper.java b/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/helpers/FrameworkHelper.java deleted file mode 100644 index d3c4d6390..000000000 --- a/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/helpers/FrameworkHelper.java +++ /dev/null @@ -1,94 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -package org.mozilla.gecko.tests.helpers; - -import static org.mozilla.gecko.tests.helpers.AssertionHelper.fFail; - -import java.lang.reflect.Field; - -import android.content.Context; -import android.view.View; - -/** - * Provides helper functions for accessing Android framework features - * - * This class uses reflection to access framework functionalities that are - * unavailable through the regular Android API. Using reflection in this - * case is okay because it does not touch Gecko classes that go through - * ProGuard. - */ -public final class FrameworkHelper { - - private FrameworkHelper() { /* To disallow instantiation. */ } - - private static Field getClassField(final Class clazz, final String fieldName) - throws NoSuchFieldException { - Class cls = clazz; - do { - try { - return cls.getDeclaredField(fieldName); - } catch (final Exception e) { - // NoSuchFieldException is a documented exception of getDeclaredField - // and is frequently observed here. No other exceptions are documented - // for getDeclaredField. However, on Android 2.3, NoSuchMethodException - // is also observed, when called on some classes. This appears to be - // an Android bug reportedly fixed in Honeycomb. Since NoSuchMethodException - // is not declared, it cannot be caught, so we catch all Exceptions. - cls = cls.getSuperclass(); - } - } while (cls != null); - // We tried getDeclaredField before; now try getField instead. - // getField behaves differently in that getField traverses the inheritance - // list, but it only works on public fields. While getField won't get us - // anything new, it makes code cleaner by throwing an exception for us. - return clazz.getField(fieldName); - } - - private static Object getField(final Object obj, final String fieldName) { - try { - final Field field = getClassField(obj.getClass(), fieldName); - final boolean accessible = field.isAccessible(); - field.setAccessible(true); - final Object ret = field.get(obj); - field.setAccessible(accessible); - return ret; - } catch (final NoSuchFieldException e) { - // We expect a valid field name; if it's not valid, - // the caller is doing something wrong and should be fixed. - fFail("Argument field should be a valid field name: " + e.toString()); - } catch (final IllegalAccessException e) { - // This should not happen. If it does, setAccessible above is not working. - fFail("Field should be accessible: " + e.toString()); - } - throw new IllegalStateException("Should not continue from previous failures"); - } - - private static void setField(final Object obj, final String fieldName, final Object value) { - try { - final Field field = getClassField(obj.getClass(), fieldName); - final boolean accessible = field.isAccessible(); - field.setAccessible(true); - field.set(obj, value); - field.setAccessible(accessible); - return; - } catch (final NoSuchFieldException e) { - // We expect a valid field name; if it's not valid, - // the caller is doing something wrong and should be fixed. - fFail("Argument field should be a valid field name: " + e.toString()); - } catch (final IllegalAccessException e) { - // This should not happen. If it does, setAccessible above is not working. - fFail("Field should be accessible: " + e.toString()); - } - throw new IllegalStateException("Cannot continue from previous failures"); - } - - public static Context getViewContext(final View v) { - return (Context) getField(v, "mContext"); - } - - public static void setViewContext(final View v, final Context c) { - setField(v, "mContext", c); - } -} diff --git a/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/helpers/GeckoClickHelper.java b/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/helpers/GeckoClickHelper.java deleted file mode 100644 index b8d1ef0ce..000000000 --- a/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/helpers/GeckoClickHelper.java +++ /dev/null @@ -1,50 +0,0 @@ -package org.mozilla.gecko.tests.helpers; - -import android.app.Activity; -import android.util.DisplayMetrics; - -import com.robotium.solo.Solo; - -import org.mozilla.gecko.Driver; -import org.mozilla.gecko.tests.StringHelper; -import org.mozilla.gecko.tests.UITestContext; - -/** - * Provides helper functions for clicking elements rendered by the Gecko engine. - */ -public class GeckoClickHelper { - private static Solo sSolo; - private static Activity sActivity; - private static Driver sDriver; - - protected static void init(final UITestContext context) { - sSolo = context.getSolo(); - sActivity = context.getActivity(); - sDriver = context.getDriver(); - } - - private GeckoClickHelper() { /* To disallow instantiation. */ } - - /** - * Long press the link and select "Open Link in New Tab" from the context menu. - * - * The link should be positioned at the top of the page, at least 60px high and - * aligned to the middle. - */ - public static void openCentralizedLinkInNewTab() { - openLinkContextMenu(); - - // Click on "Open Link in New Tab" - sSolo.clickOnText(StringHelper.get().CONTEXT_MENU_ITEMS_IN_NORMAL_TAB[0]); - } - - private static void openLinkContextMenu() { - DisplayMetrics dm = new DisplayMetrics(); - sActivity.getWindowManager().getDefaultDisplay().getMetrics(dm); - - sSolo.clickLongOnScreen( - sDriver.getGeckoLeft() + sDriver.getGeckoWidth() / 2, - sDriver.getGeckoTop() + 30 * dm.density - ); - } -} diff --git a/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/helpers/GeckoHelper.java b/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/helpers/GeckoHelper.java deleted file mode 100644 index cd75b7255..000000000 --- a/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/helpers/GeckoHelper.java +++ /dev/null @@ -1,49 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -package org.mozilla.gecko.tests.helpers; - -import org.mozilla.gecko.Actions; -import org.mozilla.gecko.Actions.EventExpecter; -import org.mozilla.gecko.GeckoThread; -import org.mozilla.gecko.tests.UITestContext; - -import android.app.Activity; - -/** - * Provides helper functions for accessing the underlying Gecko engine. - */ -public final class GeckoHelper { - private static Activity sActivity; - private static Actions sActions; - - private GeckoHelper() { /* To disallow instantiation. */ } - - protected static void init(final UITestContext context) { - sActivity = context.getActivity(); - sActions = context.getActions(); - } - - public static void blockForReady() { - blockForEvent("Gecko:Ready"); - } - - /** - * Blocks for the "Gecko:DelayedStartup" event, which occurs after "Gecko:Ready" and the - * first page load. - */ - public static void blockForDelayedStartup() { - blockForEvent("Gecko:DelayedStartup"); - } - - private static void blockForEvent(final String eventName) { - final EventExpecter eventExpecter = sActions.expectGeckoEvent(eventName); - - if (!GeckoThread.isRunning()) { - eventExpecter.blockForEvent(); - } - - eventExpecter.unregisterListener(); - } -} diff --git a/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/helpers/HelperInitializer.java b/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/helpers/HelperInitializer.java deleted file mode 100644 index 229dc1062..000000000 --- a/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/helpers/HelperInitializer.java +++ /dev/null @@ -1,30 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -package org.mozilla.gecko.tests.helpers; - -import org.mozilla.gecko.tests.UITestContext; - -/** - * AssertionHelper is statically imported in many places. Thus we want to hide - * its init method outside of this package. We initialize the remaining helper - * classes from here so that all the init methods are package protected. - */ -public final class HelperInitializer { - - private HelperInitializer() { /* To disallow instantiation. */ } - - public static void init(final UITestContext context) { - // Other helpers make assertions so init AssertionHelper first. - AssertionHelper.init(context); - - DeviceHelper.init(context); - GeckoClickHelper.init(context); - GeckoHelper.init(context); - JavascriptBridge.init(context); - NavigationHelper.init(context); - RobotiumHelper.init(context); - WaitHelper.init(context); - } -} diff --git a/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/helpers/JavascriptBridge.java b/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/helpers/JavascriptBridge.java deleted file mode 100644 index 1b0ece1cd..000000000 --- a/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/helpers/JavascriptBridge.java +++ /dev/null @@ -1,394 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -package org.mozilla.gecko.tests.helpers; - -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; - -import junit.framework.AssertionFailedError; - -import org.json.JSONArray; -import org.json.JSONException; -import org.json.JSONObject; - -import org.mozilla.gecko.Actions; -import org.mozilla.gecko.Actions.EventExpecter; -import org.mozilla.gecko.Assert; -import org.mozilla.gecko.tests.UITestContext; - -/** - * Javascript bridge allows calls to and from JavaScript. - * - * To establish communication, create an instance of JavascriptBridge in Java and pass in - * an object that will receive calls from JavaScript. For example: - * - * {@code final JavascriptBridge js = new JavascriptBridge(javaObj);} - * - * Next, create an instance of JavaBridge in JavaScript and pass in another object - * that will receive calls from Java. For example: - * - * {@code let java = new JavaBridge(jsObj);} - * - * Once a link is established, calls can be made using the methods syncCall and asyncCall. - * syncCall waits for the call to finish before returning. For example: - * - * {@code js.syncCall("abc", 1, 2, 3);} will synchronously call the JavaScript method - * jsObj.abc and pass in arguments 1, 2, and 3. - * - * {@code java.asyncCall("def", 4, 5, 6);} will asynchronously call the Java method - * javaObj.def and pass in arguments 4, 5, and 6. - * - * Supported argument types include int, double, boolean, String, and JSONObject. Note - * that only implicit conversion is done, meaning if a floating point argument is passed - * from JavaScript to Java, the call will fail if the Java method has an int argument. - * - * Because JavascriptBridge and JavaBridge use one underlying communication channel, - * creating multiple instances of them will not create independent links. - * - * Note also that because Robocop tests finish as soon as the Java test method returns, - * the last call to JavaScript from Java must be a synchronous call. Otherwise, the test - * will finish before the JavaScript method is run. Calls to Java from JavaScript do not - * have this requirement. Because of these considerations, calls from Java to JavaScript - * are usually synchronous and calls from JavaScript to Java are usually asynchronous. - * See testJavascriptBridge.java for examples. - */ -public final class JavascriptBridge { - - private static enum MessageStatus { - QUEUE_EMPTY, // Did not process a message; queue was empty. - PROCESSED, // A message other than sync was processed. - REPLIED, // A sync message was processed. - SAVED, // An async message was saved; see processMessage(). - }; - - @SuppressWarnings("serial") - public static class CallException extends RuntimeException { - public CallException() { - super(); - } - - public CallException(final String msg) { - super(msg); - } - - public CallException(final String msg, final Throwable e) { - super(msg, e); - } - - public CallException(final Throwable e) { - super(e); - } - } - - public static final String EVENT_TYPE = "Robocop:JS"; - - private static Actions sActions; - private static Assert sAsserter; - - // Target of JS-to-Java calls - private final Object mTarget; - // List of public methods in subclass - private final Method[] mMethods; - // Parser for handling xpcshell assertions - private final JavascriptMessageParser mLogParser; - // Expecter of our internal Robocop event - private final EventExpecter mExpecter; - // Saved async message; see processMessage() for its purpose. - private JSONObject mSavedAsyncMessage; - // Number of levels in the synchronous call stack - private int mCallStackDepth; - // If JavaBridge has been loaded - private boolean mJavaBridgeLoaded; - - /* package */ static void init(final UITestContext context) { - sActions = context.getActions(); - sAsserter = context.getAsserter(); - } - - public JavascriptBridge(final Object target) { - mTarget = target; - mMethods = target.getClass().getMethods(); - mExpecter = sActions.expectGeckoEvent(EVENT_TYPE); - // The JS here is unrelated to a test harness, so we - // have our message parser end on assertion failure. - mLogParser = new JavascriptMessageParser(sAsserter, true); - } - - /** - * Synchronously calls a method in Javascript. - * - * @param method Name of the method to call - * @param args Arguments to pass to the Javascript method; must be a list of - * values allowed by JSONObject. - */ - public void syncCall(final String method, final Object... args) { - mCallStackDepth++; - - sendMessage("sync-call", method, args); - try { - while (processPendingMessage() != MessageStatus.REPLIED) { - } - } catch (final AssertionFailedError e) { - // Most likely an event expecter time out - throw new CallException("Cannot call " + method, e); - } - - // If syncCall was called reentrantly from processPendingMessage(), mCallStackDepth - // will be greater than 1 here. In that case we don't have to wait for pending calls - // because the outermost syncCall will do it for us. - if (mCallStackDepth == 1) { - // We want to wait for all asynchronous calls to finish, - // because the test may end immediately after this method returns. - finishPendingCalls(); - } - mCallStackDepth--; - } - - /** - * Asynchronously calls a method in Javascript. - * - * @param method Name of the method to call - * @param args Arguments to pass to the Javascript method; must be a list of - * values allowed by JSONObject. - */ - public void asyncCall(final String method, final Object... args) { - sendMessage("async-call", method, args); - } - - /** - * Disconnect the bridge. - */ - public void disconnect() { - mExpecter.unregisterListener(); - } - - /** - * Process a new message; wait for new message if necessary. - * - * @return MessageStatus value to indicate result of processing the message - */ - private MessageStatus processPendingMessage() { - // We're on the test thread. - // We clear mSavedAsyncMessage in maybeProcessPendingMessage() but not here, - // because we always have a new message for processing here, so we never - // get a chance to clear mSavedAsyncMessage. - try { - final String message = mExpecter.blockForEventData(); - return processMessage(new JSONObject(message)); - } catch (final JSONException e) { - throw new IllegalStateException("Invalid message", e); - } - } - - /** - * Process a message if a new or saved message is available. - * - * @return MessageStatus value to indicate result of processing the message - */ - private MessageStatus maybeProcessPendingMessage() { - // We're on the test thread. - final String message = mExpecter.blockForEventDataWithTimeout(0); - if (message != null) { - try { - return processMessage(new JSONObject(message)); - } catch (final JSONException e) { - throw new IllegalStateException("Invalid message", e); - } - } - if (mSavedAsyncMessage != null) { - // processMessage clears mSavedAsyncMessage. - return processMessage(mSavedAsyncMessage); - } - return MessageStatus.QUEUE_EMPTY; - } - - /** - * Wait for all asynchronous messages from Javascript to be processed. - */ - private void finishPendingCalls() { - MessageStatus result; - do { - result = maybeProcessPendingMessage(); - if (result == MessageStatus.REPLIED) { - throw new IllegalStateException("Sync reply was unexpected"); - } - } while (result != MessageStatus.QUEUE_EMPTY); - } - - private void ensureJavaBridgeLoaded() { - while (!mJavaBridgeLoaded) { - processPendingMessage(); - } - } - - private void sendMessage(final String innerType, final String method, final Object[] args) { - ensureJavaBridgeLoaded(); - - // Call from Java to Javascript - final JSONObject message = new JSONObject(); - final JSONArray jsonArgs = new JSONArray(); - try { - if (args != null) { - for (final Object arg : args) { - jsonArgs.put(convertToJSONValue(arg)); - } - } - message.put("type", EVENT_TYPE) - .put("innerType", innerType) - .put("method", method) - .put("args", jsonArgs); - } catch (final JSONException e) { - throw new IllegalStateException("Unable to create JSON message", e); - } - sActions.sendGeckoEvent(EVENT_TYPE, message.toString()); - } - - private MessageStatus processMessage(JSONObject message) { - final String type; - final String methodName; - final JSONArray argsArray; - final Object[] args; - try { - if (!EVENT_TYPE.equals(message.getString("type"))) { - throw new IllegalStateException("Message type is not " + EVENT_TYPE); - } - type = message.getString("innerType"); - - switch (type) { - case "progress": - // Javascript harness message - mLogParser.logMessage(message.getString("message")); - return MessageStatus.PROCESSED; - - case "notify-loaded": - mJavaBridgeLoaded = true; - return MessageStatus.PROCESSED; - - case "sync-reply": - // Reply to Java-to-Javascript sync call - return MessageStatus.REPLIED; - - case "sync-call": - case "async-call": - - if ("async-call".equals(type)) { - // Save this async message until another async message arrives, then we - // process the saved message and save the new one. This is done as a - // form of tail call optimization, by making sync-replies come before - // async-calls. On the other hand, if (message == mSavedAsyncMessage), - // it means we're currently processing the saved message and should clear - // mSavedAsyncMessage. - final JSONObject newSavedMessage = - (message != mSavedAsyncMessage ? message : null); - message = mSavedAsyncMessage; - mSavedAsyncMessage = newSavedMessage; - if (message == null) { - // Saved current message and there wasn't an already saved one. - return MessageStatus.SAVED; - } - } - - methodName = message.getString("method"); - argsArray = message.getJSONArray("args"); - args = new Object[argsArray.length()]; - for (int i = 0; i < args.length; i++) { - args[i] = convertFromJSONValue(argsArray.get(i)); - } - invokeMethod(methodName, args); - - if ("sync-call".equals(type)) { - // Reply for sync messages - sendMessage("sync-reply", methodName, null); - } - return MessageStatus.PROCESSED; - } - - throw new IllegalStateException("Message type is unexpected"); - - } catch (final JSONException e) { - throw new IllegalStateException("Unable to retrieve JSON message", e); - } - } - - /** - * Given a method name and a list of arguments, - * call the most suitable method in the subclass. - */ - private Object invokeMethod(final String methodName, final Object[] args) { - final Class[] argTypes = new Class[args.length]; - for (int i = 0; i < argTypes.length; i++) { - if (args[i] == null) { - argTypes[i] = Object.class; - } else { - argTypes[i] = args[i].getClass(); - } - } - - // Try using argument types directly without casting. - try { - return invokeMethod(mTarget.getClass().getMethod(methodName, argTypes), args); - } catch (final NoSuchMethodException e) { - // getMethod() failed; try fallback below. - } - - // One scenario for getMethod() to fail above is that we don't have the exact - // argument types in argTypes (e.g. JS gave us an int but we're using a double, - // or JS gave us a null and we don't know its intended type), or the number of - // arguments is incorrect. Now we find all the methods with the given name and - // try calling them one-by-one. If one call fails, we move to the next call. - // Java will try to convert our arguments to the right types. - Throwable lastException = null; - for (final Method method : mMethods) { - if (!method.getName().equals(methodName)) { - continue; - } - try { - return invokeMethod(method, args); - } catch (final IllegalArgumentException e) { - lastException = e; - // Try the next method - } catch (final UnsupportedOperationException e) { - // "Cannot access method" exception below, see if there are other public methods - lastException = e; - // Try the next method - } - } - // Now we're out of options - throw new UnsupportedOperationException( - "Cannot call method " + methodName + " (not public? wrong argument types?)", - lastException); - } - - private Object invokeMethod(final Method method, final Object[] args) { - try { - return method.invoke(mTarget, args); - } catch (final IllegalAccessException e) { - throw new UnsupportedOperationException( - "Cannot access method " + method.getName(), e); - } catch (final InvocationTargetException e) { - final Throwable cause = e.getCause(); - if (cause instanceof CallException) { - // Don't wrap CallExceptions; this can happen if a call is nested on top - // of existing sync calls, and the nested call throws a CallException - throw (CallException) cause; - } - throw new CallException("Failed to invoke " + method.getName(), cause); - } - } - - private Object convertFromJSONValue(final Object value) { - if (value == JSONObject.NULL) { - return null; - } - return value; - } - - private Object convertToJSONValue(final Object value) { - if (value == null) { - return JSONObject.NULL; - } - return value; - } -} diff --git a/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/helpers/JavascriptMessageParser.java b/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/helpers/JavascriptMessageParser.java deleted file mode 100644 index 6237f1adc..000000000 --- a/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/helpers/JavascriptMessageParser.java +++ /dev/null @@ -1,100 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -package org.mozilla.gecko.tests.helpers; - -import org.mozilla.gecko.Assert; - -import junit.framework.AssertionFailedError; - -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -/** - * Route messages from Javascript's head.js test framework into Java's - * Mochitest framework. - */ -public final class JavascriptMessageParser { - - /** - * The Javascript test harness sends test events to Java. - * Each such test event is wrapped in a Robocop:JS event. - */ - public static final String EVENT_TYPE = "Robocop:JS"; - - // Messages matching this pattern are handled specially. Messages not - // matching this pattern are still printed. This pattern should be able - // to handle having multiple lines in a message. - private static final Pattern testMessagePattern = - Pattern.compile("TEST-([A-Z\\-]+) \\| (.*?) \\| (.*)", Pattern.DOTALL); - - private final Assert asserter; - // Used to help print stack traces neatly. - private String lastTestName = ""; - // Have we seen a message saying the test is finished? - private boolean testFinishedMessageSeen = false; - private final boolean endOnAssertionFailure; - - /** - * Constructs a message parser for test result messages sent from JavaScript. When seeing an - * assertion failure, the message parser can use the given {@link org.mozilla.gecko.Assert} - * instance to immediately end the test (typically if the underlying JS framework is not able - * to end the test itself) or to swallow the Errors - this functionality is determined by the - * endOnAssertionFailure parameter. - * - * @param asserter The Assert instance to which test results should be passed. - * @param endOnAssertionFailure - * true if the test should end if we see a JS assertion failure, false otherwise. - */ - public JavascriptMessageParser(final Assert asserter, final boolean endOnAssertionFailure) { - this.asserter = asserter; - this.endOnAssertionFailure = endOnAssertionFailure; - } - - public boolean isTestFinished() { - return testFinishedMessageSeen; - } - - public void logMessage(final String str) { - final Matcher m = testMessagePattern.matcher(str.trim()); - - if (m.matches()) { - final String type = m.group(1); - final String name = m.group(2); - final String message = m.group(3); - - if ("INFO".equals(type)) { - asserter.info(name, message); - testFinishedMessageSeen = testFinishedMessageSeen || - "exiting test".equals(message); - } else if ("PASS".equals(type)) { - asserter.ok(true, name, message); - } else if ("UNEXPECTED-FAIL".equals(type)) { - try { - asserter.ok(false, name, message); - } catch (AssertionFailedError e) { - // Above, we call the assert, allowing it to log. - // Now we can end the test, if applicable. - if (this.endOnAssertionFailure) { - throw e; - } - // Otherwise, swallow the Error. The JS framework we're - // logging messages from is likely capable of ending tests - // when it needs to, and we want to see all of its failures, - // not just the first one! - } - } else if ("KNOWN-FAIL".equals(type)) { - asserter.todo(false, name, message); - } else if ("UNEXPECTED-PASS".equals(type)) { - asserter.todo(true, name, message); - } - - lastTestName = name; - } else { - // Generally, these extra lines are stack traces from failures, - // so we print them with the name of the last test seen. - asserter.info(lastTestName, str.trim()); - } - } -} diff --git a/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/helpers/NavigationHelper.java b/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/helpers/NavigationHelper.java deleted file mode 100644 index e3ccc8236..000000000 --- a/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/helpers/NavigationHelper.java +++ /dev/null @@ -1,104 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -package org.mozilla.gecko.tests.helpers; - -import static org.mozilla.gecko.tests.helpers.AssertionHelper.fAssertNotNull; - -import org.mozilla.gecko.tests.UITestContext; -import org.mozilla.gecko.tests.UITestContext.ComponentType; -import org.mozilla.gecko.tests.components.AppMenuComponent; -import org.mozilla.gecko.tests.components.ToolbarComponent; - -import com.robotium.solo.Solo; - -/** - * Provides helper functionality for navigating around the Firefox UI. These functions will often - * combine actions taken on multiple components to perform larger interactions. - */ -final public class NavigationHelper { - private static UITestContext sContext; - private static Solo sSolo; - - private static AppMenuComponent sAppMenu; - private static ToolbarComponent sToolbar; - - protected static void init(final UITestContext context) { - sContext = context; - sSolo = context.getSolo(); - - sAppMenu = (AppMenuComponent) context.getComponent(ComponentType.APPMENU); - sToolbar = (ToolbarComponent) context.getComponent(ComponentType.TOOLBAR); - } - - public static void enterAndLoadUrl(String url) { - fAssertNotNull("url is not null", url); - - url = adjustUrl(url); - sToolbar.enterEditingMode() - .enterUrl(url) - .commitEditingMode(); - } - - /** - * Returns a new URL with the docshell HTTP server host prefix. - */ - public static String adjustUrl(final String url) { - fAssertNotNull("url is not null", url); - - if (url.startsWith("about:") || url.startsWith("chrome:")) { - return url; - } - - return sContext.getAbsoluteHostnameUrl(url); - } - - public static void goBack() { - if (DeviceHelper.isTablet()) { - sToolbar.pressBackButton(); // Waits for page load & asserts isNotEditing. - return; - } - - sToolbar.assertIsNotEditing(); - WaitHelper.waitForPageLoad(new Runnable() { - @Override - public void run() { - // TODO: Lower soft keyboard first if applicable. Note that - // Solo.hideSoftKeyboard() does not clear focus (which might be fine since - // Gecko would be the element focused). - sSolo.goBack(); - } - }); - } - - public static void goForward() { - if (DeviceHelper.isTablet()) { - sToolbar.pressForwardButton(); // Waits for page load & asserts isNotEditing. - return; - } - - sToolbar.assertIsNotEditing(); - WaitHelper.waitForPageLoad(new Runnable() { - @Override - public void run() { - sAppMenu.pressMenuItem(AppMenuComponent.MenuItem.FORWARD); - } - }); - } - - public static void reload() { - if (DeviceHelper.isTablet()) { - sToolbar.pressReloadButton(); // Waits for page load & asserts isNotEditing. - return; - } - - sToolbar.assertIsNotEditing(); - WaitHelper.waitForPageLoad(new Runnable() { - @Override - public void run() { - sAppMenu.pressMenuItem(AppMenuComponent.MenuItem.RELOAD); - } - }); - } -} diff --git a/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/helpers/RobotiumHelper.java b/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/helpers/RobotiumHelper.java deleted file mode 100644 index 2536eb9db..000000000 --- a/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/helpers/RobotiumHelper.java +++ /dev/null @@ -1,43 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -package org.mozilla.gecko.tests.helpers; - -import com.robotium.solo.Solo; - -import org.mozilla.gecko.tests.UITestContext; - -import java.util.regex.Pattern; - -/** - * Provides helper functions for using Robotium. - */ -public final class RobotiumHelper { - private static Solo sSolo; - - private RobotiumHelper() { /* To disallow instantiation. */ } - - protected static void init(final UITestContext context) { - sSolo = context.getSolo(); - } - - /** - * Same as Solo.waitForText(), but matching against full text, without regular expressions. - */ - public static boolean waitForExactText(final String text, - final int minimumNumberOfMatches, - final long timeout) { - String matchText = "^" + Pattern.quote(text) + "$"; - return sSolo.waitForText(matchText, minimumNumberOfMatches, timeout); - } - - /** - * Same as Solo.searchText(), but matching against full text, without regular expressions. - */ - public static boolean searchExactText(final String text, - final boolean onlyVisible) { - String matchText = "^" + Pattern.quote(text) + "$"; - return sSolo.searchText(matchText, onlyVisible); - } -} diff --git a/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/helpers/WaitHelper.java b/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/helpers/WaitHelper.java deleted file mode 100644 index f6e616652..000000000 --- a/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/helpers/WaitHelper.java +++ /dev/null @@ -1,215 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -package org.mozilla.gecko.tests.helpers; - -import static org.mozilla.gecko.tests.helpers.AssertionHelper.fAssertNotNull; -import static org.mozilla.gecko.tests.helpers.AssertionHelper.fAssertTrue; - -import android.os.SystemClock; - -import java.util.concurrent.Callable; -import java.util.regex.Pattern; - -import org.mozilla.gecko.Actions; -import org.mozilla.gecko.Actions.EventExpecter; -import org.mozilla.gecko.tests.UITestContext; -import org.mozilla.gecko.tests.UITestContext.ComponentType; -import org.mozilla.gecko.tests.components.ToolbarComponent; - -import com.robotium.solo.Condition; -import com.robotium.solo.Solo; - -/** - * Provides functionality related to waiting on certain events to happen. - */ -public final class WaitHelper { - // TODO: Make public for when Solo.waitForCondition is used directly (i.e. do not want - // assertion from waitFor)? - // DEFAULT_MAX_WAIT_MS of 5000 was intermittently insufficient during - // initialization on Android 2.3 emulator -- bug 1114655 - private static final int DEFAULT_MAX_WAIT_MS = 15000; - private static final int PAGE_LOAD_WAIT_MS = 10000; - private static final int CHANGE_WAIT_MS = 15000; - - // TODO: via lucasr - Add ThrobberVisibilityChangeVerifier? - private static final ChangeVerifier[] PAGE_LOAD_VERIFIERS = new ChangeVerifier[] { - new ToolbarTitleTextChangeVerifier() - }; - - private static UITestContext sContext; - private static Solo sSolo; - private static Actions sActions; - - private static ToolbarComponent sToolbar; - - private WaitHelper() { /* To disallow instantiation. */ } - - protected static void init(final UITestContext context) { - sContext = context; - sSolo = context.getSolo(); - sActions = context.getActions(); - - sToolbar = (ToolbarComponent) context.getComponent(ComponentType.TOOLBAR); - } - - /** - * Waits for the given {@link solo.Condition} using the default wait duration; will throw an - * AssertionError if the duration is elapsed and the condition is not satisfied. - */ - public static void waitFor(String message, final Condition condition) { - message = "Waiting for " + message + "."; - fAssertTrue(message, sSolo.waitForCondition(condition, DEFAULT_MAX_WAIT_MS)); - } - - /** - * Waits for the given {@link solo.Condition} using the given wait duration; will throw an - * AssertionError if the duration is elapsed and the condition is not satisfied. - */ - public static void waitFor(String message, final Condition condition, final int waitMillis) { - message = "Waiting for " + message + " with timeout " + waitMillis + "."; - fAssertTrue(message, sSolo.waitForCondition(condition, waitMillis)); - } - - /** - * Waits for the given Callable to return something that is not null, using the given wait - * duration; will throw an AssertionError if the duration is elapsed and the callable has not - * returned a non-null object. - * - * @return the value returned by the Callable. Or null if the duration has elapsed. - */ - public static V waitFor(String message, final Callable callable, int waitMillis) { - sContext.dumpLog("WaitHelper", "Waiting for " + message + " with timeout " + waitMillis + "."); - - final Object[] value = new Object[1]; - - Condition condition = new Condition() { - @Override - public boolean isSatisfied() { - try { - V result = callable.call(); - value[0] = result; - return result != null; - } catch (Exception e) { - return false; - } - } - }; - - sSolo.waitForCondition(condition, waitMillis); - - return (V) value[0]; - } - - /** - * Waits for the Gecko event declaring the page has loaded. Takes in and runs a Runnable - * that will perform the action that will cause the page to load. - */ - public static void waitForPageLoad(final Runnable initiatingAction) { - fAssertNotNull("initiatingAction is not null", initiatingAction); - - // Some changes to the UI occur in response to the same event we listen to for when - // the page has finished loading (e.g. a page title update). As such, we ensure this - // UI state has changed before returning from this method; here we store the initial - // state. - final ChangeVerifier[] pageLoadVerifiers = PAGE_LOAD_VERIFIERS; - for (final ChangeVerifier verifier : pageLoadVerifiers) { - verifier.storeState(); - } - - // Wait for the page load and title changed event. - final EventExpecter[] eventExpecters = new EventExpecter[] { - sActions.expectGeckoEvent("DOMContentLoaded"), - sActions.expectGeckoEvent("DOMTitleChanged") - }; - - initiatingAction.run(); - - // PAGE_LOAD_WAIT_MS is the total time we wait for all events to finish. - final long expecterStartMillis = SystemClock.uptimeMillis(); - for (final EventExpecter expecter : eventExpecters) { - final int eventWaitTimeMillis = PAGE_LOAD_WAIT_MS - (int)(SystemClock.uptimeMillis() - expecterStartMillis); - expecter.blockForEventDataWithTimeout(eventWaitTimeMillis); - expecter.unregisterListener(); - } - - // The timeout wait time should be the aggregate time for all ChangeVerifiers. - final long verifierStartMillis = SystemClock.uptimeMillis(); - - // Verify remaining state has changed. - for (final ChangeVerifier verifier : pageLoadVerifiers) { - // If we timeout, either the state is set to the same value (which is fine), or - // the state has not yet changed. Since we can't be sure it will ever change, move - // on and let the assertions fail if applicable. - final int verifierWaitMillis = CHANGE_WAIT_MS - (int)(SystemClock.uptimeMillis() - verifierStartMillis); - final boolean hasTimedOut = !sSolo.waitForCondition(new Condition() { - @Override - public boolean isSatisfied() { - return verifier.hasStateChanged(); - } - }, verifierWaitMillis); - - sContext.dumpLog(verifier.getLogTag(), - (hasTimedOut ? "timed out." : "was satisfied.")); - } - } - - /** - * Implementations of this interface verify that the state of the test has changed from - * the invocation of storeState to the invocation of hasStateChanged. A boolean will be - * returned from hasStateChanged, indicating this change of status. - */ - private interface ChangeVerifier { - String getLogTag(); - - /** - * Stores the initial state of the system. This system state is used to diff against - * the end state to determine if the system has changed. Since this is just a diff - * (with a timeout), this method could potentially store state inconsistent with - * what is visible to the user. - */ - void storeState(); - boolean hasStateChanged(); - } - - private static class ToolbarTitleTextChangeVerifier implements ChangeVerifier { - private static final String LOGTAG = ToolbarTitleTextChangeVerifier.class.getSimpleName(); - - // A regex that matches the page title that shows up while the page is loading. - private static final Pattern LOADING_PREFIX = Pattern.compile("[A-Za-z]{3,9}://"); - - private CharSequence mOldTitleText; - - @Override - public String getLogTag() { - return LOGTAG; - } - - @Override - public void storeState() { - mOldTitleText = sToolbar.getPotentiallyInconsistentTitle(); - sContext.dumpLog(LOGTAG, "stored title, \"" + mOldTitleText + "\"."); - } - - @Override - public boolean hasStateChanged() { - // TODO: Additionally, consider Solo.waitForText. - // TODO: Robocop sleeps .5 sec between calls. Cache title view? - final CharSequence title = sToolbar.getPotentiallyInconsistentTitle(); - - // TODO: Handle the case where the URL is shown instead of page title by preference. - // HACK: We want to wait until the title changes to the state a tester may assert - // (e.g. the page title). However, the title is set to the URL before the title is - // loaded from the server and set as the final page title; we ignore the - // intermediate URL loading state here. - final boolean isLoading = LOADING_PREFIX.matcher(title).lookingAt(); - final boolean hasStateChanged = !isLoading && !mOldTitleText.equals(title); - - if (hasStateChanged) { - sContext.dumpLog(LOGTAG, "state changed to title, \"" + title + "\"."); - } - return hasStateChanged; - } - } -} diff --git a/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/testANRReporter.java b/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/testANRReporter.java deleted file mode 100644 index e3afeb8d9..000000000 --- a/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/testANRReporter.java +++ /dev/null @@ -1,240 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -package org.mozilla.gecko.tests; - -import org.mozilla.gecko.AppConstants; - -import android.content.Context; -import android.content.Intent; - -import com.robotium.solo.Condition; - -import java.io.File; -import java.io.FileReader; -import java.io.FileWriter; - -import org.json.JSONObject; - -/** - * Tests the proper operation of the ANR reporter. - */ -public class testANRReporter extends BaseTest { - - private static final String ANR_ACTION = "android.intent.action.ANR"; - private static final String PING_DIR = "saved-telemetry-pings"; - private static final int WAIT_FOR_PING_TIMEOUT = 60000; - private static final String ANR_PATH = "/data/anr/traces.txt"; - private static final String SAMPLE_ANR - = "----- pid 1 at 2014-01-15 18:55:51 -----\n" - + "Cmd line: " + AppConstants.ANDROID_PACKAGE_NAME + "\n" - + "\n" - + "JNI: CheckJNI is off; workarounds are off; pins=0; globals=397\n" - + "\n" - + "DALVIK THREADS:\n" - + "(mutexes: tll=0 tsl=0 tscl=0 ghl=0)\n" - + "\n" - + "\"main\" prio=5 tid=1 WAIT\n" - + " | group=\"main\" sCount=1 dsCount=0 obj=0x41d6bc90 self=0x41d5a3c8\n" - + " | sysTid=3485 nice=0 sched=0/0 cgrp=apps handle=1074852180\n" - + " | state=S schedstat=( 0 0 0 ) utm=1065 stm=152 core=0\n" - + " at java.lang.Object.wait(Native Method)\n" - + " - waiting on <0x427ab340> (a org.mozilla.gecko.GeckoEditable$5)\n" - + " at java.lang.Object.wait(Object.java:364)\n" - + " at org.mozilla.gecko.GeckoEditable$5.run(GeckoEditable.java:746)\n" - + " at android.os.Handler.handleCallback(Handler.java:733)\n" - + " at android.os.Handler.dispatchMessage(Handler.java:95)\n" - + " at android.os.Looper.loop(Looper.java:137)\n" - + " at android.app.ActivityThread.main(ActivityThread.java:4998)\n" - + " at java.lang.reflect.Method.invokeNative(Native Method)\n" - + " at java.lang.reflect.Method.invoke(Method.java:515)\n" - + " at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:777)\n" - + " at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:593)\n" - + " at dalvik.system.NativeStart.main(Native Method)\n" - + "\n" - + "\"Gecko\" prio=5 tid=16 SUSPENDED\n" - + " | group=\"main\" sCount=1 dsCount=0 obj=0x426e2b28 self=0x76ae92e8\n" - + " | sysTid=3541 nice=0 sched=0/0 cgrp=apps handle=1991153472\n" - + " | state=S schedstat=( 0 0 0 ) utm=1118 stm=145 core=0\n" - + " #00 pc 00000904 /system/lib/libc.so (__futex_syscall3+4294832136)\n" - + " #01 pc 0000eec4 /system/lib/libc.so (__pthread_cond_timedwait_relative+48)\n" - + " #02 pc 0000ef24 /system/lib/libc.so (__pthread_cond_timedwait+64)\n" - + " #03 pc 000536b7 /system/lib/libdvm.so\n" - + " #04 pc 00053c79 /system/lib/libdvm.so (dvmChangeStatus(Thread*, ThreadStatus)+34)\n" - + " #05 pc 00049507 /system/lib/libdvm.so\n" - + " #06 pc 0004d84b /system/lib/libdvm.so\n" - + " #07 pc 0003f1df /dev/ashmem/libxul.so (deleted)\n" - + " at org.mozilla.gecko.mozglue.GeckoLoader.nativeRun(Native Method)\n" - + " at org.mozilla.gecko.GeckoAppShell.runGecko(GeckoAppShell.java:384)\n" - + " at org.mozilla.gecko.GeckoThread.run(GeckoThread.java:177)\n" - + "\n" - + "----- end 1 -----\n" - + "\n" - + "\n" - + "----- pid 2 at 2013-01-25 13:27:01 -----\n" - + "Cmd line: system_server\n" - + "\n" - + "----- end 2 -----\n"; - - private boolean mDone; - - private JSONObject readPingFile(final File pingFile) throws Exception { - final long fileSize = pingFile.length(); - if (fileSize == 0 || fileSize > Integer.MAX_VALUE) { - throw new Exception("Invalid ping file size"); - } - final char[] buffer = new char[(int) fileSize]; - final FileReader reader = new FileReader(pingFile); - try { - final int readSize = reader.read(buffer); - if (readSize == 0 || readSize > buffer.length) { - throw new Exception("Invalid number of bytes read"); - } - } finally { - reader.close(); - } - return new JSONObject(new String(buffer)); - } - - public void testANRReporter() throws Exception { - blockForGeckoReady(); - - // Cannot test ANR reporter if it's disabled. - if (!AppConstants.MOZ_ANDROID_ANR_REPORTER) { - mAsserter.ok(true, "ANR reporter is disabled", null); - return; - } - - // For the ANR reporter to work, we need to provide sample ANR traces to it. - // Therefore, we need the ANR file to exist and writable. If not, we don't - // have the right permissions to create the file, so we just bail. - final File anrFile = new File(ANR_PATH); - if (!anrFile.exists()) { - mAsserter.ok(true, "ANR file does not exist", null); - return; - } - if (!anrFile.canWrite()) { - mAsserter.ok(true, "ANR file is not writable", null); - return; - } - - final FileWriter anrWriter = new FileWriter(anrFile); - try { - anrWriter.write(SAMPLE_ANR); - } finally { - anrWriter.close(); - } - - // Block the UI thread to simulate an ANR - final Runnable uiBlocker = new Runnable() { - @Override - public synchronized void run() { - while (!mDone) { - try { - wait(); - } catch (final InterruptedException e) { - } - } - } - }; - getActivity().runOnUiThread(uiBlocker); - - // Make sure our initial ping directory is empty. - final File pingDir = new File(mProfile, PING_DIR); - final String[] initialFiles = pingDir.list(); - mAsserter.ok(initialFiles == null || initialFiles.length == 0, - "Ping directory is empty", null); - - final Intent anrIntent = new Intent(ANR_ACTION); - anrIntent.setPackage(AppConstants.ANDROID_PACKAGE_NAME); - mAsserter.is(anrIntent.getPackage(), AppConstants.ANDROID_PACKAGE_NAME, - "Successfully set package name"); - - final Context testContext = getInstrumentation().getContext(); - mAsserter.isnot(testContext, null, "testContext should not be null"); - - // Trigger the ANR. - mAsserter.info("Triggering ANR", null); - testContext.sendBroadcast(anrIntent); - - // ANR reporter is supposed to ignore duplicate ANRs. - // This will be checked later when we look for ping files. - mAsserter.info("Triggering second ANR", null); - testContext.sendBroadcast(new Intent(anrIntent)); - - waitForCondition(new Condition() { - @Override - public boolean isSatisfied() { - mAsserter.info("Waiting for ping", null); - - try { - // Sleep to allow the ANR reporter thread time to process the ANR. - Thread.sleep(1000); - } catch (final InterruptedException e) { - } - - final File[] newFiles = pingDir.listFiles(); - if (newFiles == null || newFiles.length == 0) { - // Keep waiting. - return false; - } - // Make sure we have a complete file. We skip assertions and catch all - // exceptions here because the condition may not be satisfied now but may - // be satisfied later. After the wait is over, we will repeat the same - // steps with assertions and exceptions. - try { - return readPingFile(newFiles[0]).has("slug"); - } catch (final Exception e) { - return false; - } - } - }, WAIT_FOR_PING_TIMEOUT); - - mAsserter.ok(pingDir.exists(), "Ping directory exists", null); - mAsserter.ok(pingDir.isDirectory(), "Ping directory is a directory", null); - - final File[] newFiles = pingDir.listFiles(); - mAsserter.isnot(newFiles, null, "Ping directory is not empty"); - mAsserter.is(newFiles.length, 1, "ANR reporter wrote one ping"); - mAsserter.ok(newFiles[0].exists(), "Ping exists", null); - mAsserter.ok(newFiles[0].isFile(), "Ping is a file", null); - mAsserter.ok(newFiles[0].canRead(), "Ping is readable", null); - mAsserter.info("Found ping file", newFiles[0].getPath()); - - // Check standard properties required by Telemetry server. - final JSONObject pingObject = readPingFile(newFiles[0]); - mAsserter.ok(pingObject.has("slug"), "Ping has slug property", null); - mAsserter.ok(pingObject.has("reason"), "Ping has reason property", null); - mAsserter.ok(pingObject.has("payload"), "Ping has payload property", null); - - final JSONObject pingPayload = pingObject.getJSONObject("payload"); - mAsserter.ok(pingPayload.has("ver"), "Payload has ver property", null); - mAsserter.ok(pingPayload.has("info"), "Payload has info property", null); - mAsserter.ok(pingPayload.has("androidANR"), "Payload has androidANR property", null); - - final JSONObject pingInfo = pingPayload.getJSONObject("info"); - mAsserter.ok(pingInfo.has("reason"), "Info has reason property", null); - mAsserter.ok(pingInfo.has("appName"), "Info has appName property", null); - mAsserter.ok(pingInfo.has("appUpdateChannel"), "Info has appUpdateChannel property", null); - mAsserter.ok(pingInfo.has("appVersion"), "Info has appVersion property", null); - mAsserter.ok(pingInfo.has("appBuildID"), "Info has appBuildID property", null); - - // Do some profile clean up. This is not absolutely necessary because the profile - // is blown away after test runs anyways, so we don't check return values here. - for (final File ping : newFiles) { - ping.delete(); - } - pingDir.delete(); - - // Unblock UI thread - synchronized (uiBlocker) { - mDone = true; - uiBlocker.notify(); - } - - // Clear the sample ANR - final FileWriter anrClearer = new FileWriter(anrFile); - anrClearer.close(); - } -} diff --git a/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/testAboutHomePageNavigation.java b/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/testAboutHomePageNavigation.java deleted file mode 100644 index 68f3a38db..000000000 --- a/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/testAboutHomePageNavigation.java +++ /dev/null @@ -1,107 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -package org.mozilla.gecko.tests; - -import org.mozilla.gecko.home.HomeConfig.PanelType; -import org.mozilla.gecko.tests.helpers.DeviceHelper; -import org.mozilla.gecko.tests.helpers.GeckoHelper; - -/** - * Tests functionality related to navigating between the various about:home panels. - */ -public class testAboutHomePageNavigation extends UITest { - // TODO: Define this test dynamically by creating dynamic representations of the Page - // enum for both phone and tablet, then swiping through the panels. This will also - // benefit having a HomePager with custom panels. - public void testAboutHomePageNavigation() { - GeckoHelper.blockForDelayedStartup(); - - mAboutHome.assertVisible() - .assertCurrentPanel(PanelType.TOP_SITES); - - mAboutHome.swipeToPanelOnRight(); - mAboutHome.assertCurrentPanel(PanelType.BOOKMARKS); - - // Ideally these helpers would just be their own tests. However, by keeping this within - // one method, we're saving test setUp and tearDown resources. - if (DeviceHelper.isTablet()) { - helperTestTablet(); - } else { - helperTestPhone(); - } - } - - private void helperTestTablet() { - mAboutHome.swipeToPanelOnRight(); - mAboutHome.assertCurrentPanel(PanelType.COMBINED_HISTORY); - - // Edge case. - mAboutHome.swipeToPanelOnRight(); - mAboutHome.assertCurrentPanel(PanelType.COMBINED_HISTORY); - - mAboutHome.swipeToPanelOnLeft(); - mAboutHome.assertCurrentPanel(PanelType.BOOKMARKS); - - mAboutHome.swipeToPanelOnLeft(); - mAboutHome.assertCurrentPanel(PanelType.TOP_SITES); - - // Edge case. - mAboutHome.swipeToPanelOnLeft(); - mAboutHome.assertCurrentPanel(PanelType.TOP_SITES); - } - - private void helperTestPhone() { - // Edge case. - mAboutHome.swipeToPanelOnLeft(); - mAboutHome.assertCurrentPanel(PanelType.BOOKMARKS); - - mAboutHome.swipeToPanelOnLeft(); - mAboutHome.assertCurrentPanel(PanelType.TOP_SITES); - - mAboutHome.swipeToPanelOnLeft(); - mAboutHome.assertCurrentPanel(PanelType.COMBINED_HISTORY); - - // Edge case. - mAboutHome.swipeToPanelOnLeft(); - mAboutHome.assertCurrentPanel(PanelType.COMBINED_HISTORY); - - mAboutHome.swipeToPanelOnRight(); - mAboutHome.assertCurrentPanel(PanelType.TOP_SITES); - } - - // TODO: bug 943706 - reimplement this old test code. - /* - // Removed by Bug 896576 - [fig] Remove [getAllPagesList] from BaseTest - // ListView list = getAllPagesList("about:firefox"); - - // Test normal sliding of the list left and right - ViewPager pager = (ViewPager)mSolo.getView(ViewPager.class, 0); - mAsserter.is(pager.getCurrentItem(), 0, "All pages is selected"); - - int width = mDriver.getGeckoWidth() / 2; - int y = mDriver.getGeckoHeight() / 2; - mActions.drag(width, 0, y, y); - mAsserter.is(pager.getCurrentItem(), 1, "Bookmarks page is selected"); - - mActions.drag(0, width, y, y); - mAsserter.is(pager.getCurrentItem(), 0, "All pages is selected"); - - // Test tapping on the tab strip changes tabs - TabWidget tabwidget = (TabWidget)mSolo.getView(TabWidget.class, 0); - mSolo.clickOnView(tabwidget.getChildAt(1)); - mAsserter.is(pager.getCurrentItem(), 1, "Clicking on tab selected bookmarks page"); - - // Test typing in the awesomebar changes tabs and prevents panning - mSolo.typeText(0, "woot"); - mAsserter.is(pager.getCurrentItem(), 0, "Searching switched to all pages tab"); - mSolo.scrollToSide(Solo.LEFT); - mAsserter.is(pager.getCurrentItem(), 0, "Dragging left is not allowed when searching"); - - mSolo.scrollToSide(Solo.RIGHT); - mAsserter.is(pager.getCurrentItem(), 0, "Dragging right is not allowed when searching"); - - mSolo.goBack(); - */ -} diff --git a/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/testAboutHomeVisibility.java b/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/testAboutHomeVisibility.java deleted file mode 100644 index 3be6ed53f..000000000 --- a/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/testAboutHomeVisibility.java +++ /dev/null @@ -1,57 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -package org.mozilla.gecko.tests; - -import org.mozilla.gecko.home.HomeConfig; -import org.mozilla.gecko.home.HomeConfig.PanelType; -import org.mozilla.gecko.tests.helpers.GeckoHelper; -import org.mozilla.gecko.tests.helpers.NavigationHelper; - -/** - * Tests the visibility of about:home after various interactions with the browser. - */ -public class testAboutHomeVisibility extends UITest { - public void testAboutHomeVisibility() { - GeckoHelper.blockForReady(); - - // Check initial state on about:home. - mToolbar.assertTitle(mStringHelper.ABOUT_HOME_URL); - mAboutHome.assertVisible() - .assertCurrentPanel(PanelType.TOP_SITES); - - // Go to blank 01. - NavigationHelper.enterAndLoadUrl(mStringHelper.ROBOCOP_BLANK_PAGE_01_URL); - mToolbar.assertTitle(mStringHelper.ROBOCOP_BLANK_PAGE_01_URL); - mAboutHome.assertNotVisible(); - - // Go to blank 02. - NavigationHelper.enterAndLoadUrl(mStringHelper.ROBOCOP_BLANK_PAGE_02_URL); - mToolbar.assertTitle(mStringHelper.ROBOCOP_BLANK_PAGE_02_URL); - mAboutHome.assertNotVisible(); - - // Enter editing mode, where the about:home UI should be visible. - mToolbar.enterEditingMode(); - mAboutHome.assertVisible() - .assertCurrentPanel(PanelType.TOP_SITES); - - // Dismiss editing mode, where the about:home UI should be gone. - mToolbar.dismissEditingMode(); - mAboutHome.assertNotVisible(); - - // Loading about:home should show about:home again. - NavigationHelper.enterAndLoadUrl(mStringHelper.ABOUT_HOME_URL); - mToolbar.assertTitle(mStringHelper.ABOUT_HOME_URL); - mAboutHome.assertVisible() - .assertCurrentPanel(PanelType.TOP_SITES); - - // We can navigate to about:home panels by panel UUID. - mAboutHome.navigateToBuiltinPanelType(PanelType.BOOKMARKS) - .assertVisible() - .assertCurrentPanel(PanelType.BOOKMARKS); - mAboutHome.navigateToBuiltinPanelType(PanelType.COMBINED_HISTORY) - .assertVisible() - .assertCurrentPanel(PanelType.COMBINED_HISTORY); - } -} diff --git a/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/testAboutPage.java b/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/testAboutPage.java deleted file mode 100644 index 6a00acd96..000000000 --- a/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/testAboutPage.java +++ /dev/null @@ -1,47 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -package org.mozilla.gecko.tests; - -import org.mozilla.gecko.Actions; - -/* Tests related to the about: page: - * - check that about: loads from the URL bar - * - check that about: loads from Settings/About... - */ -public class testAboutPage extends PixelTest { - - public void testAboutPage() { - blockForGeckoReady(); - - // Load the about: page and verify its title. - String url = mStringHelper.ABOUT_SCHEME; - loadAndPaint(url); - - verifyUrlInContentDescription(url); - - // Open a new page to remove the about: page from the current tab. - url = getAbsoluteUrl(mStringHelper.ROBOCOP_BLANK_PAGE_01_URL); - loadUrlAndWait(url); - - // At this point the page title should have been set. - verifyUrlInContentDescription(url); - - // Set up listeners to catch the page load we're about to do. - Actions.EventExpecter tabEventExpecter = mActions.expectGeckoEvent("Tab:Added"); - Actions.EventExpecter contentEventExpecter = mActions.expectGeckoEvent("DOMContentLoaded"); - - selectSettingsItem(mStringHelper.MOZILLA_SECTION_LABEL, mStringHelper.ABOUT_LABEL); - - // Wait for the new tab and page to load - tabEventExpecter.blockForEvent(); - contentEventExpecter.blockForEvent(); - - tabEventExpecter.unregisterListener(); - contentEventExpecter.unregisterListener(); - - // Make sure the about: page was loaded. - verifyUrlInContentDescription(mStringHelper.ABOUT_SCHEME); - } -} diff --git a/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/testAccessibleCarets.java b/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/testAccessibleCarets.java deleted file mode 100644 index d064eb1dd..000000000 --- a/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/testAccessibleCarets.java +++ /dev/null @@ -1,76 +0,0 @@ -/** - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this file, - * You can obtain one at http://mozilla.org/MPL/2.0/. - */ -package org.mozilla.gecko.tests; - -import org.mozilla.gecko.AppConstants; -import org.mozilla.gecko.Tab; -import org.mozilla.gecko.Tabs; - -import android.util.Log; - -import org.json.JSONException; -import org.json.JSONObject; - - -public class testAccessibleCarets extends JavascriptTest { - private static final String LOGTAG = "testAccessibleCarets"; - private static final String TAB_CHANGE_EVENT = "testAccessibleCarets:TabChange"; - - private final TabsListener tabsListener; - - - public testAccessibleCarets() { - super("testAccessibleCarets.js"); - - tabsListener = new TabsListener(); - } - - @Override - public void setUp() throws Exception { - super.setUp(); - - Tabs.registerOnTabsChangedListener(tabsListener); - } - - @Override - public void tearDown() throws Exception { - Tabs.unregisterOnTabsChangedListener(tabsListener); - - super.tearDown(); - } - - @Override - public void testJavascript() throws Exception { - // This feature is currently only available in Nightly. - if (!AppConstants.NIGHTLY_BUILD) { - mAsserter.dumpLog(LOGTAG + " is disabled on non-Nightly builds: returning"); - return; - } - super.testJavascript(); - } - - /** - * Observes tab change events to broadcast to the test script. - */ - private class TabsListener implements Tabs.OnTabsChangedListener { - @Override - public void onTabChanged(Tab tab, Tabs.TabEvents msg, String data) { - switch (msg) { - case STOP: - final JSONObject args = new JSONObject(); - try { - args.put("tabId", tab.getId()); - args.put("event", msg.toString()); - } catch (JSONException e) { - Log.e(LOGTAG, "Error building JSON arguments for " + TAB_CHANGE_EVENT, e); - return; - } - mActions.sendGeckoEvent(TAB_CHANGE_EVENT, args.toString()); - break; - } - } - } -} diff --git a/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/testActivityStreamContextMenu.java b/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/testActivityStreamContextMenu.java deleted file mode 100644 index b4b06a236..000000000 --- a/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/testActivityStreamContextMenu.java +++ /dev/null @@ -1,94 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -package org.mozilla.gecko.tests; - -import android.support.design.widget.NavigationView; -import android.support.v4.app.Fragment; -import android.view.KeyEvent; -import android.view.MenuItem; -import android.view.View; - -import com.robotium.solo.Condition; - -import org.mozilla.gecko.R; -import org.mozilla.gecko.db.BrowserDB; -import org.mozilla.gecko.home.activitystream.ActivityStream; -import org.mozilla.gecko.home.activitystream.menu.ActivityStreamContextMenu; - -/** - * This test is unfortunately closely coupled to the current implementation, however it is still - * useful in that it tests the bookmark/history state specific menu items for correctness. - */ -public class testActivityStreamContextMenu extends BaseTest { - public void testActivityStreamContextMenu() { - blockForGeckoReady(); - - final String testURL = "http://mozilla.org"; - - BrowserDB db = BrowserDB.from(getActivity()); - db.removeHistoryEntry(getActivity().getContentResolver(), testURL); - db.removeBookmarksWithURL(getActivity().getContentResolver(), testURL); - - testMenuForUrl(testURL, false, false); - - db.addBookmark(getActivity().getContentResolver(), "foobar", testURL); - testMenuForUrl(testURL, true, false); - - db.updateVisitedHistory(getActivity().getContentResolver(), testURL); - testMenuForUrl(testURL, true, true); - - db.removeBookmarksWithURL(getActivity().getContentResolver(), testURL); - testMenuForUrl(testURL, false, true); - } - - /** - * Test that the menu shows the expected menu items for a given URL, and that these items have - * the correct state. - */ - private void testMenuForUrl(final String url, final boolean isBookmarked, final boolean isVisited) { - final View anchor = new View(getActivity()); - - final ActivityStreamContextMenu menu = ActivityStreamContextMenu.show(getActivity(), anchor, ActivityStreamContextMenu.MenuMode.HIGHLIGHT, "foobar", url, null, null, 100, 100); - - final int expectedBookmarkString; - if (isBookmarked) { - expectedBookmarkString = R.string.bookmark_remove; - } else { - expectedBookmarkString = R.string.bookmark; - } - - final MenuItem bookmarkItem = menu.getItemByID(R.id.bookmark); - assertMenuItemHasString(bookmarkItem, expectedBookmarkString); - - final MenuItem deleteItem = menu.getItemByID(R.id.delete); - assertMenuItemIsVisible(deleteItem, isVisited); - - menu.dismiss(); - } - - private void assertMenuItemIsVisible(final MenuItem item, final boolean shouldBeVisible) { - waitForCondition(new Condition() { - @Override - public boolean isSatisfied() { - return (item.isVisible() == shouldBeVisible); - } - }, 5000); - - mAsserter.is(item.isVisible(), shouldBeVisible, "menu item \"" + item.getTitle() + "\" should be visible"); - } - - private void assertMenuItemHasString(final MenuItem item, final int stringID) { - waitForCondition(new Condition() { - @Override - public boolean isSatisfied() { - return item.isEnabled(); - } - }, 5000); - - final String expectedTitle = getActivity().getResources().getString(stringID); - mAsserter.is(item.getTitle(), expectedTitle, "Title does not match expected title"); - } -} - diff --git a/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/testAddSearchEngine.java b/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/testAddSearchEngine.java deleted file mode 100644 index 44bd1f903..000000000 --- a/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/testAddSearchEngine.java +++ /dev/null @@ -1,172 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -package org.mozilla.gecko.tests; - -import java.io.File; -import java.util.ArrayList; - -import org.json.JSONArray; -import org.json.JSONException; -import org.json.JSONObject; -import org.mozilla.gecko.Actions; -import org.mozilla.gecko.GeckoProfile; -import org.mozilla.gecko.home.HomePager; -import org.mozilla.gecko.home.SearchEngineBar; -import org.mozilla.gecko.R; - -import android.widget.ImageView; -import android.widget.ListView; - -import com.robotium.solo.Condition; - -/** - * Test adding a search engine from an input field context menu. - * 1. Get the number of existing search engines from the SearchEngine:Data event and as displayed in about:home. - * 2. Load a page with a text field, open the context menu and add a search engine from the page. - * 3. Get the number of search engines after adding the new one and verify it has increased by 1. - */ -public class testAddSearchEngine extends AboutHomeTest { - private final int MAX_WAIT_TEST_MS = 5000; - private final String SEARCH_TEXT = "Firefox for Android"; - private final String ADD_SEARCHENGINE_OPTION_TEXT = "Add as Search Engine"; - - public void testAddSearchEngine() { - String blankPageURL = getAbsoluteUrl(mStringHelper.ROBOCOP_BLANK_PAGE_01_URL); - String searchEngineURL = getAbsoluteUrl(mStringHelper.ROBOCOP_SEARCH_URL); - - blockForGeckoReady(); - int height = mDriver.getGeckoTop() + 150; - int width = mDriver.getGeckoLeft() + 150; - - inputAndLoadUrl(blankPageURL); - waitForText(mStringHelper.ROBOCOP_BLANK_PAGE_01_TITLE); - - // Get the searchengine data by clicking the awesomebar - this causes Gecko to send Java the list - // of search engines. - Actions.EventExpecter searchEngineDataEventExpector = mActions.expectGeckoEvent("SearchEngines:Data"); - focusUrlBar(); - mActions.sendKeys(SEARCH_TEXT); - String eventData = searchEngineDataEventExpector.blockForEventData(); - searchEngineDataEventExpector.unregisterListener(); - - ArrayList searchEngines; - try { - // Parse the data to get the number of searchengines. - searchEngines = getSearchEnginesNames(eventData); - } catch (JSONException e) { - mAsserter.ok(false, "Fatal exception in testAddSearchEngine while decoding JSON search engine string from Gecko prior to addition of new engine.", e.toString()); - return; - } - final int initialNumSearchEngines = searchEngines.size(); - mAsserter.dumpLog("Search Engines list = " + searchEngines.toString()); - - // Verify that the number of displayed search engines is the same as the one received through the SearchEngines:Data event. - verifyDisplayedSearchEnginesCount(initialNumSearchEngines); - - // Load the page for the search engine to add. - inputAndLoadUrl(searchEngineURL); - verifyUrlBarTitle(searchEngineURL); - - // Used to long-tap on the search input box for the search engine to add. - getInstrumentation().waitForIdleSync(); - mAsserter.dumpLog("Long Clicking at width = " + String.valueOf(width) + " and height = " + String.valueOf(height)); - mSolo.clickLongOnScreen(width,height); - - ImageView view = waitForViewWithDescription(ImageView.class, ADD_SEARCHENGINE_OPTION_TEXT); - mAsserter.isnot(view, null, "The action mode was opened"); - - // Add the search engine - mSolo.clickOnView(view); - waitForText("Cancel"); - clickOnButton("OK"); - mAsserter.ok(!mSolo.searchText(ADD_SEARCHENGINE_OPTION_TEXT), "Adding the Search Engine", "The add Search Engine pop-up has been closed"); - waitForText(mStringHelper.ROBOCOP_SEARCH_TITLE); // Make sure the pop-up is closed and we are back at the searchengine page - - // Load Robocop Blank 1 again to give the time for the searchengine to be added - // TODO: This is a potential source of intermittent oranges - it's a race condition! - loadUrl(blankPageURL); - waitForText(mStringHelper.ROBOCOP_BLANK_PAGE_01_TITLE); - - // Load search engines again and check that the quantity of engines has increased by 1. - searchEngineDataEventExpector = mActions.expectGeckoEvent("SearchEngines:Data"); - focusUrlBar(); - mActions.sendKeys(SEARCH_TEXT); - eventData = searchEngineDataEventExpector.blockForEventData(); - - try { - // Parse the data to get the number of searchengines - searchEngines = getSearchEnginesNames(eventData); - } catch (JSONException e) { - mAsserter.ok(false, "Fatal exception in testAddSearchEngine while decoding JSON search engine string from Gecko after adding of new engine.", e.toString()); - return; - } - - mAsserter.dumpLog("Search Engines list = " + searchEngines.toString()); - mAsserter.is(searchEngines.size(), initialNumSearchEngines + 1, "Checking the number of Search Engines has increased"); - - // Verify that the number of displayed searchengines is the same as the one received through the SearchEngines:Data event. - verifyDisplayedSearchEnginesCount(initialNumSearchEngines + 1); - searchEngineDataEventExpector.unregisterListener(); - - // Verify that the search plugin XML file for the new engine ended up where we expected it to. - // This file name is created in nsSearchService.js based on the name of the new engine. - final File f = GeckoProfile.get(getActivity()).getFile("searchplugins/robocop-search-engine.xml"); - mAsserter.ok(f.exists(), "Checking that new search plugin file exists", ""); - } - - /** - * Helper method to decode a list of search engine names from the provided search engine information - * JSON string sent from Gecko. - * @param searchEngineData The JSON string representing the search engine array to process - * @return An ArrayList containing the names of all the search engines represented in - * the provided JSON message. - * @throws JSONException In the event that the JSON provided cannot be decoded. - */ - public ArrayList getSearchEnginesNames(String searchEngineData) throws JSONException { - JSONObject data = new JSONObject(searchEngineData); - JSONArray engines = data.getJSONArray("searchEngines"); - - ArrayList searchEngineNames = new ArrayList(); - for (int i = 0; i < engines.length(); i++) { - JSONObject engineJSON = engines.getJSONObject(i); - searchEngineNames.add(engineJSON.getString("name")); - } - return searchEngineNames; - } - - /** - * Method to verify that the displayed number of search engines matches the expected number. - * @param expectedCount The expected number of search engines. - */ - public void verifyDisplayedSearchEnginesCount(final int expectedCount) { - mSolo.clearEditText(0); - mActions.sendKeys(SEARCH_TEXT); - boolean correctNumSearchEnginesDisplayed = waitForCondition(new Condition() { - @Override - public boolean isSatisfied() { - ListView searchResultList = findListViewWithTag(HomePager.LIST_TAG_BROWSER_SEARCH); - if (searchResultList == null || searchResultList.getAdapter() == null) { - return false; - } - - SearchEngineBar searchEngineBar = (SearchEngineBar) mSolo.getView(R.id.search_engine_bar); - if (searchEngineBar == null || searchEngineBar.getAdapter() == null) { - return false; - } - - final int actualCount = searchResultList.getAdapter().getCount() - + searchEngineBar.getAdapter().getItemCount() - - 1; // Subtract one for the search engine bar label (Bug 1172071) - - return (actualCount == expectedCount); - } - }, MAX_WAIT_TEST_MS); - - // Exit about:home - mSolo.goBack(); - waitForText(mStringHelper.ROBOCOP_BLANK_PAGE_01_TITLE); - mAsserter.ok(correctNumSearchEnginesDisplayed, expectedCount + " Search Engines should be displayed" , "The correct number of Search Engines has been displayed"); - } -} diff --git a/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/testAddonManager.java b/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/testAddonManager.java deleted file mode 100644 index 4256d93c4..000000000 --- a/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/testAddonManager.java +++ /dev/null @@ -1,79 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -package org.mozilla.gecko.tests; - -import org.json.JSONObject; -import org.mozilla.gecko.Actions; - -import android.util.DisplayMetrics; - -/** - * This test performs the following steps to check the behavior of the Add-on Manager: - * - * 1) Open the Add-on Manager from the Add-ons menu item, and then close it. - * 2) Open the Add-on Manager by visiting about:addons in the URL bar. - * 3) Open a new tab, select the Add-ons menu item, then verify that the existing - * Add-on Manager tab was selected, instead of opening a new tab. - */ -public class testAddonManager extends PixelTest { - public void testAddonManager() { - Actions.EventExpecter tabEventExpecter; - Actions.EventExpecter contentEventExpecter; - final String aboutAddonsURL = mStringHelper.ABOUT_ADDONS_URL; - - blockForGeckoReady(); - - // Use the menu to open the Addon Manger - selectMenuItem(mStringHelper.ADDONS_LABEL); - - // Set up listeners to catch the page load we're about to do - tabEventExpecter = mActions.expectGeckoEvent("Tab:Added"); - contentEventExpecter = mActions.expectGeckoEvent("DOMContentLoaded"); - - // Wait for the new tab and page to load - tabEventExpecter.blockForEvent(); - contentEventExpecter.blockForEvent(); - - tabEventExpecter.unregisterListener(); - contentEventExpecter.unregisterListener(); - - // Verify the url - verifyUrlBarTitle(aboutAddonsURL); - - // Close the Add-on Manager - mSolo.goBack(); - - // Load the about:addons page and verify it was loaded - loadAndPaint(aboutAddonsURL); - verifyUrlBarTitle(aboutAddonsURL); - - // Setup wait for tab to spawn and load - tabEventExpecter = mActions.expectGeckoEvent("Tab:Added"); - contentEventExpecter = mActions.expectGeckoEvent("DOMContentLoaded"); - - // Open a new tab - final String blankURL = getAbsoluteUrl(mStringHelper.ROBOCOP_BLANK_PAGE_01_URL); - addTab(blankURL); - - // Wait for the new tab and page to load - tabEventExpecter.blockForEvent(); - contentEventExpecter.blockForEvent(); - - tabEventExpecter.unregisterListener(); - contentEventExpecter.unregisterListener(); - - // Verify tab count has increased - verifyTabCount(2); - - // Verify the page was opened - verifyUrlBarTitle(blankURL); - - // Addons Manager is not opened 2 separate times when opened from the menu - selectMenuItem(mStringHelper.ADDONS_LABEL); - - // Verify tab count not increased - verifyTabCount(2); - } -} diff --git a/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/testAdobeFlash.java b/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/testAdobeFlash.java deleted file mode 100644 index 13f7f817a..000000000 --- a/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/testAdobeFlash.java +++ /dev/null @@ -1,39 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -package org.mozilla.gecko.tests; - -import org.json.JSONObject; -import org.mozilla.gecko.PaintedSurface; - -import android.os.Build; - -/** - * Tests that Flash is working - * - loads a page containing a Flash plugin - * - verifies it rendered properly - */ -public class testAdobeFlash extends PixelTest { - public void testLoad() { - // This test only works on ICS and higher - if (Build.VERSION.SDK_INT < 15) { - blockForGeckoReady(); - return; - } - - // Enable plugins - setPreferenceAndWaitForChange("plugin.enable", "1"); - - blockForGeckoReady(); - - String url = getAbsoluteUrl(mStringHelper.ROBOCOP_ADOBE_FLASH_URL); - PaintedSurface painted = loadAndGetPainted(url); - - mAsserter.ispixel(painted.getPixelAt(0, 0), 0, 0xff, 0, "Pixel at 0, 0"); - mAsserter.ispixel(painted.getPixelAt(50, 50), 0, 0xff, 0, "Pixel at 50, 50"); - mAsserter.ispixel(painted.getPixelAt(101, 0), 0xff, 0xff, 0xff, "Pixel at 101, 0"); - mAsserter.ispixel(painted.getPixelAt(0, 101), 0xff, 0xff, 0xff, "Pixel at 0, 101"); - - } -} diff --git a/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/testAppMenuPathways.java b/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/testAppMenuPathways.java deleted file mode 100644 index 69efb4dec..000000000 --- a/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/testAppMenuPathways.java +++ /dev/null @@ -1,77 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -package org.mozilla.gecko.tests; - -import org.json.JSONObject; -import org.mozilla.gecko.Tabs; -import org.mozilla.gecko.tests.components.AppMenuComponent; -import org.mozilla.gecko.tests.helpers.GeckoHelper; -import org.mozilla.gecko.tests.helpers.NavigationHelper; - -import com.robotium.solo.Solo; - -/** - * Set of tests to test UI App menu and submenus the user interact with. - */ -public class testAppMenuPathways extends UITest { - - /** - * Robocop supports only a single test function per test class. Therefore, we - * have a single top-level test function that dispatches to sub-tests. - */ - public void testAppMenuPathways() { - GeckoHelper.blockForReady(); - - _testHardwareMenuKeyOpenClose(); - _testSaveAsPDFPathway(); - } - - public void _testHardwareMenuKeyOpenClose() { - mAppMenu.assertMenuIsNotOpen(); - - mSolo.sendKey(Solo.MENU); - mAppMenu.waitForMenuOpen(); - mAppMenu.assertMenuIsOpen(); - - mSolo.sendKey(Solo.MENU); - mAppMenu.waitForMenuClose(); - mAppMenu.assertMenuIsNotOpen(); - } - - public void _testSaveAsPDFPathway() { - // Page menu should be disabled in about:home. - mAppMenu.assertMenuItemIsDisabledAndVisible(AppMenuComponent.PageMenuItem.SAVE_AS_PDF); - - // Generate a mock Content:LocationChange message with video mime-type for the current tab (tabId = 0). - final JSONObject message = new JSONObject(); - try { - message.put("contentType", "video/webm"); - message.put("baseDomain", "webmfiles.org"); - message.put("type", "Content:LocationChange"); - message.put("sameDocument", false); - message.put("userRequested", ""); - message.put("uri", getAbsoluteIpUrl("/big-buck-bunny_trailer.webm")); - message.put("tabID", 0); - } catch (Exception ex) { - mAsserter.ok(false, "exception in testSaveAsPDFPathway", ex.toString()); - } - - // Mock video playback with the generated message and Content:LocationChange event. - Tabs.getInstance().handleMessage("Content:LocationChange", message); - - // Save as pdf menu is disabled while playing video. - mAppMenu.assertMenuItemIsDisabledAndVisible(AppMenuComponent.PageMenuItem.SAVE_AS_PDF); - - // The above mock video playback test changes Java state, but not the associated JS state. - // Navigate to a new page so that the Java state is cleared. - NavigationHelper.enterAndLoadUrl(mStringHelper.ROBOCOP_BLANK_PAGE_01_URL); - mToolbar.assertTitle(mStringHelper.ROBOCOP_BLANK_PAGE_01_URL); - - // Test save as pdf functionality. - // The following call doesn't wait for the resulting pdf but checks that no exception are thrown. - // NOTE: save as pdf functionality must be done at the end as it is slow and cause other test operations to fail. - mAppMenu.pressMenuItem(AppMenuComponent.PageMenuItem.SAVE_AS_PDF); - } -} diff --git a/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/testAxisLocking.java b/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/testAxisLocking.java deleted file mode 100644 index 72bf62e04..000000000 --- a/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/testAxisLocking.java +++ /dev/null @@ -1,58 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -package org.mozilla.gecko.tests; - -import org.mozilla.gecko.Actions; -import org.mozilla.gecko.PaintedSurface; - -/** - * Basic test for axis locking behaviour. - * - Load page and verify it draws - * - Drag page upwards 100 pixels at a 5-degree angle off the vertical axis - * - Verify that the 5-degree angle was thrown out and it dragged vertically - * - Drag page upwards at a 45-degree angle - * - Verify that the 45-degree angle was not thrown out and it dragged diagonally - */ -public class testAxisLocking extends PixelTest { - public void testAxisLocking() { - String url = getAbsoluteUrl(mStringHelper.ROBOCOP_BOXES_URL); - - MotionEventHelper meh = new MotionEventHelper(getInstrumentation(), mDriver.getGeckoLeft(), mDriver.getGeckoTop()); - - blockForGeckoReady(); - - // load page and check we're at 0,0 - loadAndVerifyBoxes(url); - - // drag page upwards by 100 pixels with a slight angle. verify that - // axis locking prevents any horizontal scrolling - Actions.RepeatedEventExpecter paintExpecter = mActions.expectPaint(); - meh.dragSync(20, 150, 10, 50); - PaintedSurface painted = waitForPaint(paintExpecter); - paintExpecter.unregisterListener(); - try { - checkScrollWithBoxes(painted, 0, 100); - // since checkScrollWithBoxes only checks 4 points, it may not pick up a - // sub-100 pixel horizontal shift. so we check another point manually to make sure. - int[] color = getBoxColorAt(0, 100); - mAsserter.ispixel(painted.getPixelAt(99, 0), color[0], color[1], color[2], "Pixel at 99, 0 indicates no horizontal scroll"); - - // now drag at a 45-degree angle to ensure we break the axis lock, and - // verify that we have both horizontal and vertical scrolling - paintExpecter = mActions.expectPaint(); - meh.dragSync(150, 150, 50, 50); - } finally { - painted.close(); - } - - painted = waitForPaint(paintExpecter); - paintExpecter.unregisterListener(); - try { - checkScrollWithBoxes(painted, 100, 200); - } finally { - painted.close(); - } - } -} diff --git a/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/testBackButtonInEditMode.java b/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/testBackButtonInEditMode.java deleted file mode 100644 index b391f7920..000000000 --- a/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/testBackButtonInEditMode.java +++ /dev/null @@ -1,47 +0,0 @@ -package org.mozilla.gecko.tests; - -import org.mozilla.gecko.tests.helpers.GeckoHelper; - -import android.view.View; - -/** - * Tests that verify the behavior of back button in edit mode. - */ -public class testBackButtonInEditMode extends UITest { - public void testBackButtonInEditMode() { - GeckoHelper.blockForReady(); - - // Verify back button behavior for edit mode. - mToolbar.enterEditingMode() - .assertIsUrlEditTextSelected(); - checkBackPressInEditMode(); - checkExitUsingBackButton(); - - // Verify back button behavior in edit mode after input. - mToolbar.enterEditingMode() - .enterUrl("dummy") - .assertIsUrlEditTextSelected(); - checkBackPressInEditMode(); - checkExitUsingBackButton(); - - // Verify the swipe behavior in edit mode. - mToolbar.enterEditingMode() - .assertIsUrlEditTextSelected(); - mAboutHome.swipeToPanelOnLeft(); - mToolbar.assertIsUrlEditTextNotSelected() - .assertIsEditing(); - checkExitUsingBackButton(); - } - - private void checkBackPressInEditMode() { - // Press back button and verify URLEditText is not selected. - getSolo().goBack(); - mToolbar.assertIsUrlEditTextNotSelected() - .assertIsEditing(); - } - - private void checkExitUsingBackButton() { - getSolo().goBack(); - mToolbar.assertIsNotEditing(); - } -} diff --git a/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/testBookmark.java b/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/testBookmark.java deleted file mode 100644 index 041b76e2f..000000000 --- a/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/testBookmark.java +++ /dev/null @@ -1,72 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -package org.mozilla.gecko.tests; - -import com.robotium.solo.Condition; - -public class testBookmark extends AboutHomeTest { - private static String BOOKMARK_URL; - private static final int WAIT_FOR_BOOKMARKED_TIMEOUT = 10000; - - public void testBookmark() { - BOOKMARK_URL = getAbsoluteUrl(mStringHelper.ROBOCOP_BLANK_PAGE_01_URL); - runAboutHomeTest(); - runMenuTest(); - } - - public void runMenuTest() { - mAsserter.is(mDatabaseHelper.isBookmark(BOOKMARK_URL), false, "Page is not bookmarked initially"); - setUpBookmark(); // loads the page, taps the star button, and waits for the "Bookmark Added" message - waitForBookmarked(true); - - cleanUpBookmark(); // loads the page, taps the star button, and waits for the "Bookmark Removed" message - waitForBookmarked(false); - } - - public void runAboutHomeTest() { - blockForGeckoReady(); - for (String url : mStringHelper.DEFAULT_BOOKMARKS_URLS) { - mAsserter.ok(mDatabaseHelper.isBookmark(url), "Checking that " + url + " is bookmarked by default", url + " is bookmarked"); - } - - mDatabaseHelper.addMobileBookmark(mStringHelper.ROBOCOP_BLANK_PAGE_01_TITLE, BOOKMARK_URL); - waitForBookmarked(true); - - isBookmarkDisplayed(BOOKMARK_URL); - loadBookmark(BOOKMARK_URL); - verifyUrlBarTitle(mStringHelper.ROBOCOP_BLANK_PAGE_01_URL); - - mDatabaseHelper.deleteBookmark(BOOKMARK_URL); - waitForBookmarked(false); - } - - private void waitForBookmarked(final boolean isBookmarked) { - boolean bookmarked = waitForCondition(new Condition() { - @Override - public boolean isSatisfied() { - return (isBookmarked) ? - mDatabaseHelper.isBookmark(BOOKMARK_URL) : - !mDatabaseHelper.isBookmark(BOOKMARK_URL); - } - }, WAIT_FOR_BOOKMARKED_TIMEOUT); - mAsserter.is(bookmarked, true, BOOKMARK_URL + " was " + (isBookmarked ? "added as a bookmark" : "removed from bookmarks")); - } - - private void setUpBookmark() { - // Bookmark a page for the test - loadUrl(BOOKMARK_URL); - waitForText(mStringHelper.ROBOCOP_BLANK_PAGE_01_TITLE); - toggleBookmark(); - mAsserter.is(waitForText(mStringHelper.BOOKMARK_ADDED_LABEL), true, "bookmark added successfully"); - } - - private void cleanUpBookmark() { - // Go back to the page we bookmarked - loadUrl(BOOKMARK_URL); - waitForText(mStringHelper.ROBOCOP_BLANK_PAGE_01_TITLE); - toggleBookmark(); - mAsserter.is(waitForText(mStringHelper.BOOKMARK_REMOVED_LABEL), true, "bookmark removed successfully"); - } -} diff --git a/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/testBookmarkFolders.java b/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/testBookmarkFolders.java deleted file mode 100644 index 6205337ea..000000000 --- a/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/testBookmarkFolders.java +++ /dev/null @@ -1,169 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -package org.mozilla.gecko.tests; - -import org.mozilla.gecko.home.HomePager; -import org.mozilla.gecko.sync.Utils; - -import android.content.ContentResolver; -import android.content.ContentValues; -import android.net.Uri; -import android.view.View; -import android.widget.ListAdapter; -import android.widget.ListView; -import android.widget.TextView; - -import com.robotium.solo.Condition; - -public class testBookmarkFolders extends AboutHomeTest { - private static String DESKTOP_BOOKMARK_URL; - - public void testBookmarkFolders() { - DESKTOP_BOOKMARK_URL = getAbsoluteUrl(mStringHelper.ROBOCOP_BLANK_PAGE_02_URL); - - setUpDesktopBookmarks(); - checkBookmarkList(); - } - - private void checkBookmarkList() { - openAboutHomeTab(AboutHomeTabs.BOOKMARKS); - waitForText(mStringHelper.DESKTOP_FOLDER_LABEL); - clickOnBookmarkFolder(mStringHelper.DESKTOP_FOLDER_LABEL); - waitForText(mStringHelper.TOOLBAR_FOLDER_LABEL); - - // Verify the number of folders displayed in the Desktop Bookmarks folder is correct - ListView desktopFolderContent = findListViewWithTag(HomePager.LIST_TAG_BOOKMARKS); - ListAdapter adapter = desktopFolderContent.getAdapter(); - - // Three folders and "Up to Bookmarks". - mAsserter.is(adapter.getCount(), 4, "Checking that the correct number of folders is displayed in the Desktop Bookmarks folder"); - - clickOnBookmarkFolder(mStringHelper.TOOLBAR_FOLDER_LABEL); - - // Go up in the bookmark folder hierarchy - clickOnBookmarkFolder(String.format(mStringHelper.BOOKMARKS_UP_TO, mStringHelper.DESKTOP_FOLDER_LABEL)); - mAsserter.ok(waitForText(mStringHelper.BOOKMARKS_MENU_FOLDER_LABEL), "Going up in the folder hierarchy", "We are back in the Desktop Bookmarks folder"); - - clickOnBookmarkFolder(String.format(mStringHelper.BOOKMARKS_UP_TO, mStringHelper.BOOKMARKS_ROOT_LABEL)); - mAsserter.ok(waitForText(mStringHelper.DESKTOP_FOLDER_LABEL), "Going up in the folder hierarchy", "We are back in the main Bookmarks List View"); - - clickOnBookmarkFolder(mStringHelper.DESKTOP_FOLDER_LABEL); - clickOnBookmarkFolder(mStringHelper.TOOLBAR_FOLDER_LABEL); - isBookmarkDisplayed(DESKTOP_BOOKMARK_URL); - - // Open the bookmark from a bookmark folder hierarchy - loadBookmark(DESKTOP_BOOKMARK_URL); - verifyUrlBarTitle(DESKTOP_BOOKMARK_URL); - openAboutHomeTab(AboutHomeTabs.BOOKMARKS); - - // Check that folders don't have a context menu - boolean success = waitForCondition(new Condition() { - @Override - public boolean isSatisfied() { - View desktopFolder = getBookmarkFolderView(mStringHelper.DESKTOP_FOLDER_LABEL); - if (desktopFolder == null) { - return false; - } - mSolo.clickLongOnView(desktopFolder); - return true; } - }, MAX_WAIT_MS); - - mAsserter.ok(success, "Trying to long click on the Desktop Bookmarks","Desktop Bookmarks folder could not be long clicked"); - - final String contextMenuString = mStringHelper.BOOKMARK_CONTEXT_MENU_ITEMS[0]; - mAsserter.ok(!waitForText(contextMenuString), "Folders do not have context menus", "The context menu was not opened"); - - // Even if no context menu is opened long clicking a folder still opens it. We need to close it. - clickOnBookmarkFolder(String.format(mStringHelper.BOOKMARKS_UP_TO, mStringHelper.BOOKMARKS_ROOT_LABEL)); - } - - private void clickOnBookmarkFolder(final String folderName) { - boolean success = waitForCondition(new Condition() { - @Override - public boolean isSatisfied() { - View bookmarksFolder = getBookmarkFolderView(folderName); - if (bookmarksFolder == null) { - return false; - } - mSolo.waitForView(bookmarksFolder); - mSolo.clickOnView(bookmarksFolder); - return true; - } - }, MAX_WAIT_MS); - mAsserter.ok(success, "Trying to click on the " + folderName + " folder","The " + folderName + " folder was clicked"); - } - - private View getBookmarkFolderView(String folderName) { - openAboutHomeTab(AboutHomeTabs.BOOKMARKS); - mSolo.hideSoftKeyboard(); - getInstrumentation().waitForIdleSync(); - - ListView bookmarksTabList = findListViewWithTag(HomePager.LIST_TAG_BOOKMARKS); - if (!waitForNonEmptyListToLoad(bookmarksTabList)) { - return null; - } - - ListAdapter adapter = bookmarksTabList.getAdapter(); - if (adapter == null) { - return null; - } - - for (int i = 0; i < adapter.getCount(); i++ ) { - View bookmarkView = bookmarksTabList.getChildAt(i); - if (bookmarkView instanceof TextView) { - TextView folderTextView = (TextView) bookmarkView; - if (folderTextView.getText().equals(folderName)) { - return bookmarkView; - } - } - } - - return null; - } - - // Add a bookmark in the Desktop folder so we can check the folder navigation in the bookmarks page - private void setUpDesktopBookmarks() { - blockForGeckoReady(); - - // Get the folder id of the mStringHelper.DESKTOP_FOLDER_LABEL folder - Long desktopFolderId = mDatabaseHelper.getFolderIdFromGuid("toolbar"); - - // Generate a Guid for the bookmark - final String generatedGuid = Utils.generateGuid(); - mAsserter.ok((generatedGuid != null), "Generating a random Guid for the bookmark", "We could not generate a Guid for the bookmark"); - - // Insert the bookmark - ContentResolver resolver = getActivity().getContentResolver(); - Uri bookmarksUri = mDatabaseHelper.buildUri(DatabaseHelper.BrowserDataType.BOOKMARKS); - - long now = System.currentTimeMillis(); - ContentValues values = new ContentValues(); - values.put("title", mStringHelper.ROBOCOP_BLANK_PAGE_02_TITLE); - values.put("url", DESKTOP_BOOKMARK_URL); - values.put("parent", desktopFolderId); - values.put("modified", now); - values.put("type", 1); - values.put("guid", generatedGuid); - values.put("position", 10); - values.put("created", now); - - int updated = resolver.update(bookmarksUri, - values, - "url = ?", - new String[] { DESKTOP_BOOKMARK_URL }); - if (updated == 0) { - Uri uri = resolver.insert(bookmarksUri, values); - mAsserter.ok(true, "Inserted at: ", uri.toString()); - } else { - mAsserter.ok(false, "Failed to insert the Desktop bookmark", "Something went wrong"); - } - } - - @Override - public void tearDown() throws Exception { - mDatabaseHelper.deleteBookmark(DESKTOP_BOOKMARK_URL); - super.tearDown(); - } -} diff --git a/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/testBookmarkKeyword.java b/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/testBookmarkKeyword.java deleted file mode 100644 index 363954bfa..000000000 --- a/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/testBookmarkKeyword.java +++ /dev/null @@ -1,28 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -package org.mozilla.gecko.tests; - - -public class testBookmarkKeyword extends AboutHomeTest { - public void testBookmarkKeyword() { - blockForGeckoReady(); - - final String url = getAbsoluteUrl(mStringHelper.ROBOCOP_BLANK_PAGE_01_URL); - final String keyword = "testkeyword"; - - // Add a bookmark, and update it to have a keyword. - mDatabaseHelper.addMobileBookmark(mStringHelper.ROBOCOP_BLANK_PAGE_01_TITLE, url); - mDatabaseHelper.updateBookmark(url, mStringHelper.ROBOCOP_BLANK_PAGE_01_TITLE, keyword); - - // Enter the keyword in the urlbar. - inputAndLoadUrl(keyword); - - // Make sure the title of the page appeared. - verifyUrlBarTitle(mStringHelper.ROBOCOP_BLANK_PAGE_01_URL); - - // Delete the bookmark to clean up. - mDatabaseHelper.deleteBookmark(url); - } -} diff --git a/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/testBookmarklets.java b/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/testBookmarklets.java deleted file mode 100644 index 4ae57104c..000000000 --- a/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/testBookmarklets.java +++ /dev/null @@ -1,46 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -package org.mozilla.gecko.tests; - -import org.mozilla.gecko.Actions; - -import com.robotium.solo.Condition; - - -public class testBookmarklets extends BaseTest { - public void testBookmarklets() { - final String url = getAbsoluteUrl(mStringHelper.ROBOCOP_BLANK_PAGE_01_URL); - final String title = "alertBookmarklet"; - final String js = "javascript:alert(12 + 10)"; - final String expected = "22"; - boolean alerted; - - blockForGeckoReady(); - - // Load a standard page so bookmarklets work - loadUrlAndWait(url); - - // Verify that user-entered bookmarklets do *not* work - enterUrl(js); - mActions.sendSpecialKey(Actions.SpecialKey.ENTER); - alerted = waitForCondition(new Condition() { - @Override - public boolean isSatisfied() { - return mSolo.searchButton("OK", true) || mSolo.searchText(expected, true); - } - }, 3000); - mAsserter.is(alerted, false, "Alert was not shown for user-entered bookmarklet"); - - // Verify that non-user-entered bookmarklets do work - loadUrl(js); - alerted = waitForCondition(new Condition() { - @Override - public boolean isSatisfied() { - return mSolo.searchButton("OK", true) && mSolo.searchText(expected, true); - } - }, 10000); - mAsserter.is(alerted, true, "Alert was shown for bookmarklet"); - } -} diff --git a/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/testBookmarksPanel.java b/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/testBookmarksPanel.java deleted file mode 100644 index a7e9505da..000000000 --- a/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/testBookmarksPanel.java +++ /dev/null @@ -1,174 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -package org.mozilla.gecko.tests; - -import org.json.JSONException; -import org.json.JSONObject; -import org.mozilla.gecko.Actions; -import org.mozilla.gecko.Element; -import org.mozilla.gecko.R; -import org.mozilla.gecko.util.StringUtils; - -public class testBookmarksPanel extends AboutHomeTest { - public void testBookmarksPanel() { - final String BOOKMARK_URL = getAbsoluteUrl(mStringHelper.ROBOCOP_BLANK_PAGE_01_URL); - JSONObject data = null; - - // Make sure our default bookmarks are loaded. - // Technically this will race with the check below. - initializeProfile(); - - // Add a mobile bookmark. - mDatabaseHelper.addMobileBookmark(mStringHelper.ROBOCOP_BLANK_PAGE_01_TITLE, BOOKMARK_URL); - - openAboutHomeTab(AboutHomeTabs.BOOKMARKS); - - // Check that the default bookmarks are displayed. - // We need to wait for the distribution to have been processed - // before this will succeed. - for (String url : mStringHelper.DEFAULT_BOOKMARKS_URLS) { - isBookmarkDisplayed(url); - } - - assertAllContextMenuOptionsArePresent(mStringHelper.DEFAULT_BOOKMARKS_URLS[1], - mStringHelper.DEFAULT_BOOKMARKS_URLS[0]); - - openBookmarkContextMenu(mStringHelper.DEFAULT_BOOKMARKS_URLS[0]); - - // Test that "Open in New Tab" works - final Element tabCount = mDriver.findElement(getActivity(), R.id.tabs_counter); - final int tabCountInt = Integer.parseInt(tabCount.getText()); - Actions.EventExpecter tabEventExpecter = mActions.expectGeckoEvent("Tab:Added"); - mSolo.clickOnText(mStringHelper.BOOKMARK_CONTEXT_MENU_ITEMS[0]); - try { - data = new JSONObject(tabEventExpecter.blockForEventData()); - } catch (JSONException e) { - mAsserter.ok(false, "exception getting event data", e.toString()); - } - tabEventExpecter.unregisterListener(); - mAsserter.ok(mSolo.searchText(mStringHelper.TITLE_PLACE_HOLDER), "Checking that the tab is not changed", "The tab was not changed"); - // extra check here on the Tab:Added message to be sure the right tab opened - int tabID = 0; - try { - mAsserter.is(mStringHelper.ABOUT_FIREFOX_URL, data.getString("uri"), "Checking tab uri"); - tabID = data.getInt("tabID"); - } catch (JSONException e) { - mAsserter.ok(false, "exception accessing event data", e.toString()); - } - // close tab so about:firefox can be selected again - closeTab(tabID); - - // Test that "Open in Private Tab" works - openBookmarkContextMenu(mStringHelper.DEFAULT_BOOKMARKS_URLS[0]); - tabEventExpecter = mActions.expectGeckoEvent("Tab:Added"); - mSolo.clickOnText(mStringHelper.BOOKMARK_CONTEXT_MENU_ITEMS[1]); - try { - data = new JSONObject(tabEventExpecter.blockForEventData()); - } catch (JSONException e) { - mAsserter.ok(false, "exception getting event data", e.toString()); - } - tabEventExpecter.unregisterListener(); - mAsserter.ok(mSolo.searchText(mStringHelper.TITLE_PLACE_HOLDER), "Checking that the tab is not changed", "The tab was not changed"); - // extra check here on the Tab:Added message to be sure the right tab opened, again - try { - mAsserter.is(mStringHelper.ABOUT_FIREFOX_URL, data.getString("uri"), "Checking tab uri"); - } catch (JSONException e) { - mAsserter.ok(false, "exception accessing event data", e.toString()); - } - - // Test that "Edit" works - String[] editedBookmarkValues = new String[] { "New bookmark title", "www.NewBookmark.url", "newBookmarkKeyword" }; - editBookmark(BOOKMARK_URL, editedBookmarkValues); - checkBookmarkEdit(editedBookmarkValues[1], editedBookmarkValues); - - // Test that "Remove" works - openBookmarkContextMenu(editedBookmarkValues[1]); - mSolo.clickOnText(mStringHelper.BOOKMARK_CONTEXT_MENU_ITEMS[5]); - waitForText(mStringHelper.BOOKMARK_REMOVED_LABEL); - mAsserter.ok(!mDatabaseHelper.isBookmark(editedBookmarkValues[1]), "Checking that the bookmark was removed", "The bookmark was removed"); - } - - /** - * Asserts that all context menu items are present on the given links. For one link, - * the context menu is expected to not have the "Share" context menu item. - * - * @param shareableURL A URL that is expected to have the "Share" context menu item - * @param nonShareableURL A URL that is expected not to have the "Share" context menu item. - */ - private void assertAllContextMenuOptionsArePresent(final String shareableURL, - final String nonShareableURL) { - mAsserter.ok(StringUtils.isShareableUrl(shareableURL), "Ensuring url is shareable", ""); - mAsserter.ok(!StringUtils.isShareableUrl(nonShareableURL), "Ensuring url is not shareable", ""); - - openBookmarkContextMenu(shareableURL); - for (String contextMenuOption : mStringHelper.BOOKMARK_CONTEXT_MENU_ITEMS) { - mAsserter.ok(mSolo.searchText(contextMenuOption), - "Checking that the context menu option is present", - contextMenuOption + " is present"); - } - - // Close the menu. - mSolo.goBack(); - - openBookmarkContextMenu(nonShareableURL); - for (String contextMenuOption : mStringHelper.BOOKMARK_CONTEXT_MENU_ITEMS) { - // This link is not shareable: skip the "Share" option. - if ("Share".equals(contextMenuOption)) { - continue; - } - - mAsserter.ok(mSolo.searchText(contextMenuOption), - "Checking that the context menu option is present", - contextMenuOption + " is present"); - } - - // The use of Solo.searchText is potentially fragile as It will only - // scroll the most recently drawn view. Works fine for now though. - mAsserter.ok(!mSolo.searchText("Share"), - "Checking that the Share option is not present", - "Share option is not present"); - - // Close the menu. - mSolo.goBack(); - } - - /** - * @param bookmarkUrl URL of the bookmark to edit - * @param values String array with the new values for all fields - */ - private void editBookmark(String bookmarkUrl, String[] values) { - openBookmarkContextMenu(bookmarkUrl); - mSolo.clickOnText(mStringHelper.CONTEXT_MENU_EDIT); - waitForText(mStringHelper.EDIT_BOOKMARK); - - // Update the fields with the new values - for (int i = 0; i < values.length; i++) { - mSolo.clearEditText(i); - mSolo.clickOnEditText(i); - mActions.sendKeys(values[i]); - } - - mSolo.clickOnButton(mStringHelper.OK); - waitForText(mStringHelper.BOOKMARK_UPDATED_LABEL); - } - - /** - * @param bookmarkUrl String with the original url - * @param values String array with the new values for all fields - */ - private void checkBookmarkEdit(String bookmarkUrl, String[] values) { - openBookmarkContextMenu(bookmarkUrl); - mSolo.clickOnText(mStringHelper.CONTEXT_MENU_EDIT); - waitForText(mStringHelper.EDIT_BOOKMARK); - - // Check the values of the fields - for (String value : values) { - mAsserter.ok(mSolo.searchText(value), "Checking that the value is correct", "The value = " + value + " is correct"); - } - - mSolo.clickOnButton("Cancel"); - waitForText(mStringHelper.BOOKMARKS_LABEL); - } -} diff --git a/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/testBrowserDatabaseHelperUpgrades.java b/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/testBrowserDatabaseHelperUpgrades.java deleted file mode 100644 index eec5c4b33..000000000 --- a/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/testBrowserDatabaseHelperUpgrades.java +++ /dev/null @@ -1,150 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this file, - * You can obtain one at http://mozilla.org/MPL/2.0/. */ - -package org.mozilla.gecko.tests; - -import static org.mozilla.gecko.tests.helpers.AssertionHelper.*; - -import android.database.sqlite.SQLiteDatabase; -import android.util.Log; - -import org.mozilla.gecko.db.BrowserDatabaseHelper; - -import java.io.BufferedInputStream; -import java.io.BufferedOutputStream; -import java.io.File; -import java.io.FileNotFoundException; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.util.ArrayList; - -// TODO: Move to junit 3 tests, once those run in automation. There is no ui testing to do so it's a better fit. -/** - * This test runs upgrades for the databases in (robocop-assets)/browser_db_upgrade. Currently, - * (robocop-assets)=mobile/android/tests/browser/robocop/assets/. - * - * It copies the old database from the robocop assets directory into a temporary file and opens a SQLiteHelper - * on the database to verify it gets upgraded to the correct version. If there is an issue with the upgrade, - * generally a SQLiteException will be thrown and the test will fail. For example: - * android.database.sqlite.SQLiteException: duplicate column name: calculated_pages_times_rating (code 1): , while compiling: ALTER TABLE book_information ADD COLUMN calculated_pages_times_rating INTEGER; - * - * Alternative upgrade tests: - * * Robolectric 2.3+ uses a real SQLite database implementation so we could run our upgrades there. However, the - * SQLite implementation may not be the same as we run on Android. Benefits: speed & we don't need the application to - * run (and thus a valid DB of the latest version) to run these tests. - * * We could copy the current database creation code into a new test, create the database, and then try to upgrade - * it. However, the tables are empty and thus not a realistic migration plan (e.g. foreign key constraints). - * - * TO EDIT THIS TEST: - * * Copy the current version of the database into (robocop-assets)/browser_db_upgrade/v##.db database. You can do - * this via Margaret's copy profile addon - take browser.db from the profile directory. This db copy should contain a - * used profile - e.g. history items, bookmarks. A good way to get a used profile is to sign into sync. - * * MAKE SURE YOU COPY YOUR DB FIRST. Then make your changes to the DB schema code. - * * Test! - * * Note: when the application starts for testing, it may need to upgrade the database from your existing version. If - * this fails, the application will crash and the test may fail to start. - * - * IMPORTANT: - * Test DBs must be created on the oldest version of Android that is currently supported. SQLite - * is not forwards compatible. E.g. uploading a DB created on a 6.0 device will cause failures - * when robocop tests running on 4.3 are unable to load it. - * - * Implementation inspired by: - * http://riggaroo.co.za/automated-testing-sqlite-database-upgrades-android/ - */ -public class testBrowserDatabaseHelperUpgrades extends UITest { - private static final int TEST_FROM_VERSION = 27; // We only started testing on this version. - - private ArrayList temporaryDbFiles; - - @Override - public void setUp() throws Exception { - super.setUp(); - // TODO: We already install & remove the profile directory each run so it'd be safer for clean-up to store - // this there. That being said, temporary files are still stored in the application directory so these temporary - // files will get cleaned up when the application is uninstalled or when data is cleared. - temporaryDbFiles = new ArrayList<>(); - } - - @Override - public void tearDown() throws Exception { - super.tearDown(); - for (final File dbFile : temporaryDbFiles) { - dbFile.delete(); - } - } - - /** - * @throws IOException if the database cannot be copied. - */ - public void test() throws IOException { - for (int i = TEST_FROM_VERSION; i < BrowserDatabaseHelper.DATABASE_VERSION; ++i) { - Log.d(LOGTAG, "Testing upgrade from version: " + i); - final String tempDbPath = copyDatabase(i); - - final SQLiteDatabase db = SQLiteDatabase.openDatabase(tempDbPath, null, 0); - try { - fAssertEquals("Input DB isn't the expected version", - i, db.getVersion()); - } finally { - db.close(); - } - - final BrowserDatabaseHelper dbHelperToUpgrade = new BrowserDatabaseHelper(getActivity(), tempDbPath); - // Ideally, we'd test upgrading version i to version i + 1 but this method does not permit that. Alas! - final SQLiteDatabase upgradedDb = dbHelperToUpgrade.getWritableDatabase(); - try { - fAssertEquals("DB helper should upgrade to latest version", - BrowserDatabaseHelper.DATABASE_VERSION, upgradedDb.getVersion()); - } finally { - upgradedDb.close(); - } - } - } - - /** - * Copies the database from the assets directory to a temporary test file. - * - * @param version version of the database to copy. - * @return the String path to the new copy of the database - * @throws IOException if reading the existing database or writing the temporary database fails - */ - private String copyDatabase(final int version) throws IOException { - final InputStream inputStream = openDbFromAssets(version); - try { - final File dbDestination = File.createTempFile("temporaryDB-v" + version + "_", "db"); - temporaryDbFiles.add(dbDestination); - Log.d(LOGTAG, "Moving DB from assets to " + dbDestination.getPath()); - - final OutputStream outputStream = new BufferedOutputStream(new FileOutputStream(dbDestination)); - try { - final byte[] buffer = new byte[1024]; - int len; - while ((len = inputStream.read(buffer)) > 0) { - outputStream.write(buffer, 0, len); - } - outputStream.flush(); - } finally { - outputStream.close(); - } - - return dbDestination.getPath(); - } finally { - inputStream.close(); - } - } - - private InputStream openDbFromAssets(final int version) throws IOException { - final String dbAssetPath = String.format("browser_db_upgrade" + File.separator + String.format("v%d.db", version)); - Log.d(LOGTAG, "Opening DB from assets: " + dbAssetPath); - try { - return new BufferedInputStream(getInstrumentation().getContext().getAssets().open(dbAssetPath)); - } catch (final FileNotFoundException e) { - throw new IllegalStateException("If you're upgrading the browser.db version, " + - "you need to provide an old version of the database for this test! See the javadoc.", e); - } - } -} diff --git a/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/testBrowserDiscovery.java b/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/testBrowserDiscovery.java deleted file mode 100644 index 2dab2996c..000000000 --- a/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/testBrowserDiscovery.java +++ /dev/null @@ -1,13 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -package org.mozilla.gecko.tests; - - - -public class testBrowserDiscovery extends JavascriptTest { - public testBrowserDiscovery() { - super("testBrowserDiscovery.js"); - } -} diff --git a/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/testBrowserProvider.java b/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/testBrowserProvider.java deleted file mode 100644 index e0ebb5c8e..000000000 --- a/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/testBrowserProvider.java +++ /dev/null @@ -1,1921 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -package org.mozilla.gecko.tests; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Random; - -import org.mozilla.gecko.db.BrowserContract; -import org.mozilla.gecko.db.BrowserContract.UrlAnnotations.SyncStatus; -import org.mozilla.gecko.db.BrowserDB; -import org.mozilla.gecko.db.URLMetadata; -import org.mozilla.gecko.db.URLMetadataTable; - -import android.content.ContentProviderOperation; -import android.content.ContentProviderResult; -import android.content.ContentUris; -import android.content.ContentValues; -import android.content.OperationApplicationException; -import android.database.Cursor; -import android.net.Uri; -import android.os.Build; -import android.util.Log; - -/* - * This test is meant to exercise all operations exposed by Fennec's - * history and bookmarks content provider. It does so in an isolated - * environment (see ContentProviderTest) without affecting any UI-related - * code. - */ -public class testBrowserProvider extends ContentProviderTest { - private long mMobileFolderId; - - private void loadMobileFolderId() throws Exception { - Cursor c = null; - try { - c = getBookmarkByGuid(BrowserContract.Bookmarks.MOBILE_FOLDER_GUID); - mAsserter.is(c.moveToFirst(), true, "Mobile bookmarks folder is present"); - - mMobileFolderId = c.getLong(c.getColumnIndex(BrowserContract.Bookmarks._ID)); - } finally { - if (c != null) { - c.close(); - } - } - } - - private void ensureEmptyDatabase() throws Exception { - Cursor c; - - String guid = BrowserContract.Bookmarks.GUID; - - mProvider.delete(appendUriParam(BrowserContract.Bookmarks.CONTENT_URI, BrowserContract.PARAM_IS_SYNC, "1"), - guid + " != ? AND " + - guid + " != ? AND " + - guid + " != ? AND " + - guid + " != ? AND " + - guid + " != ? AND " + - guid + " != ?", - new String[] { BrowserContract.Bookmarks.PLACES_FOLDER_GUID, - BrowserContract.Bookmarks.MOBILE_FOLDER_GUID, - BrowserContract.Bookmarks.MENU_FOLDER_GUID, - BrowserContract.Bookmarks.TAGS_FOLDER_GUID, - BrowserContract.Bookmarks.TOOLBAR_FOLDER_GUID, - BrowserContract.Bookmarks.UNFILED_FOLDER_GUID }); - - c = mProvider.query(appendUriParam(BrowserContract.Bookmarks.CONTENT_URI, BrowserContract.PARAM_SHOW_DELETED, "1"), null, null, null, null); - assertCountIsAndClose(c, 6, "All non-special bookmarks and folders were deleted"); - - mProvider.delete(appendUriParam(BrowserContract.History.CONTENT_URI, BrowserContract.PARAM_IS_SYNC, "1"), null, null); - c = mProvider.query(appendUriParam(BrowserContract.History.CONTENT_URI, BrowserContract.PARAM_SHOW_DELETED, "1"), null, null, null, null); - assertCountIsAndClose(c, 0, "All history entries were deleted"); - - /** - * There's no reason why the following two parts should fail. - * But sometimes they do, and I'm not going to spend the time - * to figure out why in an unrelated bug. - */ - - mProvider.delete(appendUriParam(BrowserContract.Favicons.CONTENT_URI, BrowserContract.PARAM_IS_SYNC, "1"), null, null); - c = mProvider.query(appendUriParam(BrowserContract.Favicons.CONTENT_URI, - BrowserContract.PARAM_SHOW_DELETED, "1"), - null, null, null, null); - - if (c.getCount() > 0) { - mAsserter.dumpLog("Unexpected favicons in ensureEmptyDatabase."); - } - c.close(); - - mAsserter.dumpLog("ensureEmptyDatabase: Favicon deletion completed."); // Bug 968951 debug. - // assertCountIsAndClose(c, 0, "All favicons were deleted"); - - mProvider.delete(appendUriParam(BrowserContract.Thumbnails.CONTENT_URI, BrowserContract.PARAM_IS_SYNC, "1"), null, null); - c = mProvider.query(appendUriParam(BrowserContract.Thumbnails.CONTENT_URI, - BrowserContract.PARAM_SHOW_DELETED, "1"), - null, null, null, null); - - if (c.getCount() > 0) { - mAsserter.dumpLog("Unexpected thumbnails in ensureEmptyDatabase."); - } - c.close(); - - mAsserter.dumpLog("ensureEmptyDatabase: Thumbnail deletion completed."); // Bug 968951 debug. - // assertCountIsAndClose(c, 0, "All thumbnails were deleted"); - } - - private ContentValues createBookmark(String title, String url, long parentId, - int type, int position, String tags, String description, String keyword) throws Exception { - ContentValues bookmark = new ContentValues(); - - bookmark.put(BrowserContract.Bookmarks.TITLE, title); - bookmark.put(BrowserContract.Bookmarks.URL, url); - bookmark.put(BrowserContract.Bookmarks.PARENT, parentId); - bookmark.put(BrowserContract.Bookmarks.TYPE, type); - bookmark.put(BrowserContract.Bookmarks.POSITION, position); - bookmark.put(BrowserContract.Bookmarks.TAGS, tags); - bookmark.put(BrowserContract.Bookmarks.DESCRIPTION, description); - bookmark.put(BrowserContract.Bookmarks.KEYWORD, keyword); - - return bookmark; - } - - private ContentValues createOneBookmark() throws Exception { - return createBookmark("Example", "http://example.com", mMobileFolderId, - BrowserContract.Bookmarks.TYPE_BOOKMARK, 0, "tags", "description", "keyword"); - } - - private Cursor getBookmarksByParent(long parent) throws Exception { - // Order by position. - return mProvider.query(BrowserContract.Bookmarks.CONTENT_URI, null, - BrowserContract.Bookmarks.PARENT + " = ?", - new String[] { String.valueOf(parent) }, - BrowserContract.Bookmarks.POSITION); - } - - private Cursor getBookmarkByGuid(String guid) throws Exception { - return mProvider.query(BrowserContract.Bookmarks.CONTENT_URI, null, - BrowserContract.Bookmarks.GUID + " = ?", - new String[] { guid }, - null); - } - - private Cursor getBookmarkById(long id) throws Exception { - return getBookmarkById(BrowserContract.Bookmarks.CONTENT_URI, id, null); - } - - private Cursor getBookmarkById(long id, String[] projection) throws Exception { - return getBookmarkById(BrowserContract.Bookmarks.CONTENT_URI, id, projection); - } - - private Cursor getBookmarkById(Uri bookmarksUri, long id) throws Exception { - return getBookmarkById(bookmarksUri, id, null); - } - - private Cursor getBookmarkById(Uri bookmarksUri, long id, String[] projection) throws Exception { - return mProvider.query(bookmarksUri, projection, - BrowserContract.Bookmarks._ID + " = ?", - new String[] { String.valueOf(id) }, - null); - } - - private ContentValues createHistoryEntry(String title, String url, int visits, long lastVisited) throws Exception { - ContentValues historyEntry = new ContentValues(); - - historyEntry.put(BrowserContract.History.TITLE, title); - historyEntry.put(BrowserContract.History.URL, url); - historyEntry.put(BrowserContract.History.VISITS, visits); - historyEntry.put(BrowserContract.History.DATE_LAST_VISITED, lastVisited); - - return historyEntry; - } - - private ContentValues createFaviconEntry(String pageUrl, String data) throws Exception { - ContentValues faviconEntry = new ContentValues(); - - faviconEntry.put(BrowserContract.Favicons.PAGE_URL, pageUrl); - faviconEntry.put(BrowserContract.Favicons.URL, pageUrl + "/favicon.ico"); - faviconEntry.put(BrowserContract.Favicons.DATA, data.getBytes("UTF8")); - - return faviconEntry; - } - - private ContentValues createThumbnailEntry(String pageUrl, String data) throws Exception { - ContentValues thumbnailEntry = new ContentValues(); - - thumbnailEntry.put(BrowserContract.Thumbnails.URL, pageUrl); - thumbnailEntry.put(BrowserContract.Thumbnails.DATA, data.getBytes("UTF8")); - - return thumbnailEntry; - } - - private ContentValues createUrlMetadataEntry(final String url, final String tileImage, final String tileColor, - final String touchIcon) { - final ContentValues values = new ContentValues(); - values.put(URLMetadataTable.URL_COLUMN, url); - values.put(URLMetadataTable.TILE_IMAGE_URL_COLUMN, tileImage); - values.put(URLMetadataTable.TILE_COLOR_COLUMN, tileColor); - values.put(URLMetadataTable.TOUCH_ICON_COLUMN, touchIcon); - return values; - } - - private ContentValues createUrlAnnotationEntry(final String url, final String key, final String value, - final long dateCreated) { - final ContentValues values = new ContentValues(); - values.put(BrowserContract.UrlAnnotations.URL, url); - values.put(BrowserContract.UrlAnnotations.KEY, key); - values.put(BrowserContract.UrlAnnotations.VALUE, value); - values.put(BrowserContract.UrlAnnotations.DATE_CREATED, dateCreated); - values.put(BrowserContract.UrlAnnotations.DATE_MODIFIED, dateCreated); - return values; - } - - private ContentValues createOneHistoryEntry() throws Exception { - return createHistoryEntry("Example", "http://example.com", 10, System.currentTimeMillis()); - } - - private Cursor getHistoryEntryById(long id) throws Exception { - return getHistoryEntryById(BrowserContract.History.CONTENT_URI, id, null); - } - - private Cursor getHistoryEntryById(long id, String[] projection) throws Exception { - return getHistoryEntryById(BrowserContract.History.CONTENT_URI, id, projection); - } - - private Cursor getHistoryEntryById(Uri historyUri, long id) throws Exception { - return getHistoryEntryById(historyUri, id, null); - } - - private Cursor getHistoryEntryById(Uri historyUri, long id, String[] projection) throws Exception { - return mProvider.query(historyUri, projection, - BrowserContract.History._ID + " = ?", - new String[] { String.valueOf(id) }, - null); - } - - private Cursor getFaviconsByUrl(String url) throws Exception { - return mProvider.query(BrowserContract.Combined.CONTENT_URI, null, - BrowserContract.Combined.URL + " = ?", - new String[] { url }, - null); - } - - private Cursor getThumbnailByUrl(String url) throws Exception { - return mProvider.query(BrowserContract.Thumbnails.CONTENT_URI, null, - BrowserContract.Thumbnails.URL + " = ?", - new String[] { url }, - null); - } - - private Cursor getUrlAnnotationByUrl(final String url) throws Exception { - return mProvider.query(BrowserContract.UrlAnnotations.CONTENT_URI, null, - BrowserContract.UrlAnnotations.URL + " = ?", - new String[] { url }, - null); - } - - private Cursor getUrlMetadataByUrl(final String url) throws Exception { - return mProvider.query(URLMetadataTable.CONTENT_URI, null, - URLMetadataTable.URL_COLUMN + " = ?", - new String[] { url }, - null); - } - - @Override - public void setUp() throws Exception { - super.setUp(sBrowserProviderCallable, BrowserContract.AUTHORITY, "browser.db"); - - mTests.add(new TestSpecialFolders()); - - mTests.add(new TestInsertBookmarks()); - mTests.add(new TestInsertBookmarksFavicons()); - mTests.add(new TestDeleteBookmarks()); - mTests.add(new TestDeleteBookmarksFavicons()); - mTests.add(new TestUpdateBookmarks()); - mTests.add(new TestUpdateBookmarksFavicons()); - mTests.add(new TestPositionBookmarks()); - - mTests.add(new TestInsertHistory()); - mTests.add(new TestInsertHistoryFavicons()); - mTests.add(new TestDeleteHistory()); - mTests.add(new TestDeleteHistoryFavicons()); - mTests.add(new TestUpdateHistory()); - mTests.add(new TestUpdateHistoryFavicons()); - mTests.add(new TestUpdateOrInsertHistory()); - mTests.add(new TestInsertHistoryThumbnails()); - mTests.add(new TestUpdateHistoryThumbnails()); - mTests.add(new TestDeleteHistoryThumbnails()); - - mTests.add(new TestInsertUrlAnnotations()); - mTests.add(new TestInsertUrlMetadata()); - - mTests.add(new TestBatchOperations()); - - mTests.add(new TestCombinedView()); - mTests.add(new TestCombinedViewDisplay()); - mTests.add(new TestCombinedViewWithDeletedBookmark()); - - mTests.add(new TestBrowserProviderNotifications()); - } - - public void testBrowserProvider() throws Exception { - loadMobileFolderId(); - - for (int i = 0; i < mTests.size(); i++) { - Runnable test = mTests.get(i); - - final String testName = test.getClass().getSimpleName(); - setTestName(testName); - ensureEmptyDatabase(); - mAsserter.dumpLog("testBrowserProvider: Database empty - Starting " + testName + "."); - test.run(); - } - } - - private class TestBatchOperations extends TestCase { - static final int TESTCOUNT = 100; - - public void testApplyBatch() throws Exception { - ArrayList mOperations - = new ArrayList(); - - // Test a bunch of inserts with applyBatch - ContentValues values = new ContentValues(); - ContentProviderOperation.Builder builder = null; - - for (int i = 0; i < TESTCOUNT; i++) { - values.clear(); - values.put(BrowserContract.History.VISITS, i); - values.put(BrowserContract.History.TITLE, "Test" + i); - values.put(BrowserContract.History.URL, "http://www.test.org/" + i); - - // Insert - builder = ContentProviderOperation.newInsert(BrowserContract.History.CONTENT_URI); - builder.withValues(values); - // Queue the operation - mOperations.add(builder.build()); - } - - ContentProviderResult[] applyResult = - mProvider.applyBatch(mOperations); - - boolean allFound = true; - for (int i = 0; i < TESTCOUNT; i++) { - Cursor cursor = mProvider.query(BrowserContract.History.CONTENT_URI, - null, - BrowserContract.History.URL + " = ?", - new String[] { "http://www.test.org/" + i }, - null); - - if (!cursor.moveToFirst()) - allFound = false; - cursor.close(); - } - mAsserter.is(allFound, true, "Found all batchApply entries"); - mOperations.clear(); - - // Update all visits to 1 - values.clear(); - values.put(BrowserContract.History.VISITS, 1); - for (int i = 0; i < TESTCOUNT; i++) { - builder = ContentProviderOperation.newUpdate(BrowserContract.History.CONTENT_URI); - builder.withSelection(BrowserContract.History.URL + " = ?", - new String[] {"http://www.test.org/" + i}); - builder.withValues(values); - builder.withExpectedCount(1); - // Queue the operation - mOperations.add(builder.build()); - } - - boolean seenException = false; - try { - applyResult = mProvider.applyBatch(mOperations); - } catch (OperationApplicationException ex) { - seenException = true; - } - mAsserter.is(seenException, false, "Batch updating succeeded"); - mOperations.clear(); - - // Delete all visits - for (int i = 0; i < TESTCOUNT; i++) { - builder = ContentProviderOperation.newDelete(BrowserContract.History.CONTENT_URI); - builder.withSelection(BrowserContract.History.URL + " = ?", - new String[] {"http://www.test.org/" + i}); - builder.withExpectedCount(1); - // Queue the operation - mOperations.add(builder.build()); - } - try { - applyResult = mProvider.applyBatch(mOperations); - } catch (OperationApplicationException ex) { - seenException = true; - } - mAsserter.is(seenException, false, "Batch deletion succeeded"); - } - - // Force a Constraint error, see if later operations still apply correctly - public void testApplyBatchErrors() throws Exception { - ArrayList mOperations - = new ArrayList(); - - // Test a bunch of inserts with applyBatch - ContentProviderOperation.Builder builder = null; - ContentValues values = createFaviconEntry("http://www.test.org", "FAVICON"); - builder = ContentProviderOperation.newInsert(BrowserContract.Favicons.CONTENT_URI); - builder.withValues(values); - mOperations.add(builder.build()); - - // Make a duplicate, this will fail because of a UNIQUE constraint - builder = ContentProviderOperation.newInsert(BrowserContract.Favicons.CONTENT_URI); - builder.withValues(values); - mOperations.add(builder.build()); - - // This is valid and should be in the table afterwards - values.put(BrowserContract.Favicons.URL, "http://www.test.org/valid.ico"); - builder = ContentProviderOperation.newInsert(BrowserContract.Favicons.CONTENT_URI); - builder.withValues(values); - mOperations.add(builder.build()); - - boolean seenException = false; - - try { - ContentProviderResult[] applyResult = - mProvider.applyBatch(mOperations); - } catch (OperationApplicationException ex) { - seenException = true; - } - - // This test may need to go away if Bug 717428 is fixed. - mAsserter.is(seenException, true, "Expected failure in favicons table"); - - boolean allFound = true; - Cursor cursor = mProvider.query(BrowserContract.Favicons.CONTENT_URI, - null, - BrowserContract.Favicons.URL + " = ?", - new String[] { "http://www.test.org/valid.ico" }, - null); - - if (!cursor.moveToFirst()) - allFound = false; - cursor.close(); - - mAsserter.is(allFound, true, "Found all applyBatch (with error) entries"); - } - - public void testBulkInsert() throws Exception { - // Test a bunch of inserts with bulkInsert - ContentValues allVals[] = new ContentValues[TESTCOUNT]; - for (int i = 0; i < TESTCOUNT; i++) { - allVals[i] = new ContentValues(); - allVals[i].put(BrowserContract.History.URL, i); - allVals[i].put(BrowserContract.History.TITLE, "Test" + i); - allVals[i].put(BrowserContract.History.URL, "http://www.test.org/" + i); - } - - int inserts = mProvider.bulkInsert(BrowserContract.History.CONTENT_URI, allVals); - mAsserter.is(inserts, TESTCOUNT, "Excepted number of inserts matches"); - - boolean allFound = true; - for (int i = 0; i < TESTCOUNT; i++) { - Cursor cursor = mProvider.query(BrowserContract.History.CONTENT_URI, - null, - BrowserContract.History.URL + " = ?", - new String[] { "http://www.test.org/" + i }, - null); - - if (!cursor.moveToFirst()) - allFound = false; - cursor.close(); - } - mAsserter.is(allFound, true, "Found all bulkInsert entries"); - } - - @Override - public void test() throws Exception { - testApplyBatch(); - // Clean up - ensureEmptyDatabase(); - - testBulkInsert(); - ensureEmptyDatabase(); - - testApplyBatchErrors(); - } - } - - private class TestSpecialFolders extends TestCase { - @Override - public void test() throws Exception { - Cursor c = mProvider.query(BrowserContract.Bookmarks.CONTENT_URI, - new String[] { BrowserContract.Bookmarks._ID, - BrowserContract.Bookmarks.GUID, - BrowserContract.Bookmarks.PARENT }, - BrowserContract.Bookmarks.GUID + " = ? OR " + - BrowserContract.Bookmarks.GUID + " = ? OR " + - BrowserContract.Bookmarks.GUID + " = ? OR " + - BrowserContract.Bookmarks.GUID + " = ? OR " + - BrowserContract.Bookmarks.GUID + " = ? OR " + - BrowserContract.Bookmarks.GUID + " = ?", - new String[] { BrowserContract.Bookmarks.PLACES_FOLDER_GUID, - BrowserContract.Bookmarks.MOBILE_FOLDER_GUID, - BrowserContract.Bookmarks.MENU_FOLDER_GUID, - BrowserContract.Bookmarks.TAGS_FOLDER_GUID, - BrowserContract.Bookmarks.TOOLBAR_FOLDER_GUID, - BrowserContract.Bookmarks.UNFILED_FOLDER_GUID}, - null); - - mAsserter.is(c.getCount(), 6, "Right number of special folders"); - - int rootId = BrowserContract.Bookmarks.FIXED_ROOT_ID; - - while (c.moveToNext()) { - int id = c.getInt(c.getColumnIndex(BrowserContract.Bookmarks._ID)); - String guid = c.getString(c.getColumnIndex(BrowserContract.Bookmarks.GUID)); - int parentId = c.getInt(c.getColumnIndex(BrowserContract.Bookmarks.PARENT)); - - if (guid.equals(BrowserContract.Bookmarks.PLACES_FOLDER_GUID)) { - mAsserter.is(id, rootId, "The id of places folder is correct"); - } - - mAsserter.is(parentId, rootId, - "The PARENT of the " + guid + " special folder is correct"); - } - - c.close(); - } - } - - private class TestInsertBookmarks extends TestCase { - private long insertWithNullCol(String colName) throws Exception { - ContentValues b = createOneBookmark(); - b.putNull(colName); - long id = -1; - - try { - id = ContentUris.parseId(mProvider.insert(BrowserContract.Bookmarks.CONTENT_URI, b)); - } catch (Exception e) {} - - return id; - } - - @Override - public void test() throws Exception { - ContentValues b = createOneBookmark(); - long id = ContentUris.parseId(mProvider.insert(BrowserContract.Bookmarks.CONTENT_URI, b)); - - final Cursor c = getBookmarkById(id); - try { - mAsserter.is(c.moveToFirst(), true, "Inserted bookmark found"); - - mAsserter.is(c.getString(c.getColumnIndex(BrowserContract.Bookmarks.TITLE)), b.getAsString(BrowserContract.Bookmarks.TITLE), - "Inserted bookmark has correct title"); - mAsserter.is(c.getString(c.getColumnIndex(BrowserContract.Bookmarks.URL)), b.getAsString(BrowserContract.Bookmarks.URL), - "Inserted bookmark has correct URL"); - mAsserter.is(c.getString(c.getColumnIndex(BrowserContract.Bookmarks.TAGS)), b.getAsString(BrowserContract.Bookmarks.TAGS), - "Inserted bookmark has correct tags"); - mAsserter.is(c.getString(c.getColumnIndex(BrowserContract.Bookmarks.KEYWORD)), b.getAsString(BrowserContract.Bookmarks.KEYWORD), - "Inserted bookmark has correct keyword"); - mAsserter.is(c.getString(c.getColumnIndex(BrowserContract.Bookmarks.DESCRIPTION)), b.getAsString(BrowserContract.Bookmarks.DESCRIPTION), - "Inserted bookmark has correct description"); - mAsserter.is(c.getString(c.getColumnIndex(BrowserContract.Bookmarks.POSITION)), b.getAsString(BrowserContract.Bookmarks.POSITION), - "Inserted bookmark has correct position"); - mAsserter.is(c.getString(c.getColumnIndex(BrowserContract.Bookmarks.TYPE)), b.getAsString(BrowserContract.Bookmarks.TYPE), - "Inserted bookmark has correct type"); - mAsserter.is(c.getString(c.getColumnIndex(BrowserContract.Bookmarks.PARENT)), b.getAsString(BrowserContract.Bookmarks.PARENT), - "Inserted bookmark has correct parent ID"); - mAsserter.is(c.getString(c.getColumnIndex(BrowserContract.Bookmarks.IS_DELETED)), String.valueOf(0), - "Inserted bookmark has correct is-deleted state"); - - id = insertWithNullCol(BrowserContract.Bookmarks.POSITION); - mAsserter.is(id, -1L, - "Should not be able to insert bookmark with null position"); - - id = insertWithNullCol(BrowserContract.Bookmarks.TYPE); - mAsserter.is(id, -1L, - "Should not be able to insert bookmark with null type"); - - if (Build.VERSION.SDK_INT >= 8 && - Build.VERSION.SDK_INT < 16) { - b = createOneBookmark(); - b.put(BrowserContract.Bookmarks.PARENT, -1); - id = -1; - - try { - id = ContentUris.parseId(mProvider.insert(BrowserContract.Bookmarks.CONTENT_URI, b)); - } catch (Exception e) {} - - mAsserter.is(id, -1L, - "Should not be able to insert bookmark with invalid parent"); - } - - b = createOneBookmark(); - b.remove(BrowserContract.Bookmarks.TYPE); - id = ContentUris.parseId(mProvider.insert(BrowserContract.Bookmarks.CONTENT_URI, b)); - final Cursor c2 = getBookmarkById(id); - try { - mAsserter.is(c2.moveToFirst(), true, "Inserted bookmark found"); - mAsserter.is(c2.getString(c2.getColumnIndex(BrowserContract.Bookmarks.TYPE)), String.valueOf(BrowserContract.Bookmarks.TYPE_BOOKMARK), - "Inserted bookmark has correct default type"); - } finally { - c2.close(); - } - } finally { - c.close(); - } - } - } - - private class TestInsertBookmarksFavicons extends TestCase { - @Override - public void test() throws Exception { - ContentValues b = createOneBookmark(); - - final String favicon = "FAVICON"; - final String pageUrl = b.getAsString(BrowserContract.Bookmarks.URL); - - long id = ContentUris.parseId(mProvider.insert(BrowserContract.Bookmarks.CONTENT_URI, b)); - - // Insert the favicon into the favicons table - mProvider.insert(BrowserContract.Favicons.CONTENT_URI, createFaviconEntry(pageUrl, favicon)); - - Cursor c = getBookmarkById(id, new String[] { BrowserContract.Bookmarks.FAVICON }); - - mAsserter.is(c.moveToFirst(), true, "Inserted bookmark found"); - - mAsserter.is(new String(c.getBlob(c.getColumnIndex(BrowserContract.Bookmarks.FAVICON)), "UTF8"), - favicon, "Inserted bookmark has corresponding favicon image"); - c.close(); - - c = getFaviconsByUrl(pageUrl); - mAsserter.is(c.moveToFirst(), true, "Inserted favicon found"); - - mAsserter.is(new String(c.getBlob(c.getColumnIndex(BrowserContract.Combined.FAVICON)), "UTF8"), - favicon, "Inserted favicon has corresponding favicon image"); - c.close(); - } - } - - private class TestDeleteBookmarks extends TestCase { - private long insertOneBookmark() throws Exception { - ContentValues b = createOneBookmark(); - long id = ContentUris.parseId(mProvider.insert(BrowserContract.Bookmarks.CONTENT_URI, b)); - - Cursor c = getBookmarkById(id); - mAsserter.is(c.moveToFirst(), true, "Inserted bookmark found"); - c.close(); - - return id; - } - - @Override - public void test() throws Exception { - long id = insertOneBookmark(); - - int deleted = mProvider.delete(BrowserContract.Bookmarks.CONTENT_URI, - BrowserContract.Bookmarks._ID + " = ?", - new String[] { String.valueOf(id) }); - - mAsserter.is((deleted == 1), true, "Inserted bookmark was deleted"); - - Cursor c = getBookmarkById(appendUriParam(BrowserContract.Bookmarks.CONTENT_URI, BrowserContract.PARAM_SHOW_DELETED, "1"), id); - mAsserter.is(c.moveToFirst(), true, "Deleted bookmark was only marked as deleted"); - mAsserter.is(c.getString(c.getColumnIndex(BrowserContract.Bookmarks.TITLE)), null, - "Deleted bookmark title is null"); - mAsserter.is(c.getString(c.getColumnIndex(BrowserContract.Bookmarks.URL)), null, - "Deleted bookmark URL is null"); - mAsserter.is(c.getString(c.getColumnIndex(BrowserContract.Bookmarks.TAGS)), null, - "Deleted bookmark tags is null"); - mAsserter.is(c.getString(c.getColumnIndex(BrowserContract.Bookmarks.KEYWORD)), null, - "Deleted bookmark keyword is null"); - mAsserter.is(c.getString(c.getColumnIndex(BrowserContract.Bookmarks.DESCRIPTION)), null, - "Deleted bookmark description is null"); - mAsserter.is(c.getString(c.getColumnIndex(BrowserContract.Bookmarks.POSITION)), String.valueOf(0), - "Deleted bookmark has correct position"); - mAsserter.is(c.getString(c.getColumnIndex(BrowserContract.Bookmarks.PARENT)), null, - "Deleted bookmark parent ID is null"); - mAsserter.is(c.getString(c.getColumnIndex(BrowserContract.Bookmarks.IS_DELETED)), String.valueOf(1), - "Deleted bookmark has correct is-deleted state"); - mAsserter.is(c.getString(c.getColumnIndex(BrowserContract.Bookmarks.FAVICON_ID)), null, - "Deleted bookmark Favicon ID is null"); - mAsserter.isnot(c.getString(c.getColumnIndex(BrowserContract.Bookmarks.GUID)), null, - "Deleted bookmark GUID is not null"); - c.close(); - - deleted = mProvider.delete(appendUriParam(BrowserContract.Bookmarks.CONTENT_URI, BrowserContract.PARAM_IS_SYNC, "1"), - BrowserContract.Bookmarks._ID + " = ?", - new String[] { String.valueOf(id) }); - - mAsserter.is((deleted == 1), true, "Inserted bookmark was deleted"); - - c = getBookmarkById(appendUriParam(BrowserContract.Bookmarks.CONTENT_URI, BrowserContract.PARAM_SHOW_DELETED, "1"), id); - mAsserter.is(c.moveToFirst(), false, "Inserted bookmark is now actually deleted"); - c.close(); - - id = insertOneBookmark(); - - deleted = mProvider.delete(ContentUris.withAppendedId(BrowserContract.Bookmarks.CONTENT_URI, id), null, null); - mAsserter.is((deleted == 1), true, - "Inserted bookmark was deleted using URI with id"); - - c = getBookmarkById(id); - mAsserter.is(c.moveToFirst(), false, - "Inserted bookmark can't be found after deletion using URI with ID"); - c.close(); - - if (Build.VERSION.SDK_INT >= 8 && - Build.VERSION.SDK_INT < 16) { - ContentValues b = createBookmark("Folder", null, mMobileFolderId, - BrowserContract.Bookmarks.TYPE_FOLDER, 0, "folderTags", "folderDescription", "folderKeyword"); - - long parentId = ContentUris.parseId(mProvider.insert(BrowserContract.Bookmarks.CONTENT_URI, b)); - c = getBookmarkById(parentId); - mAsserter.is(c.moveToFirst(), true, "Inserted bookmarks folder found"); - c.close(); - - b = createBookmark("Example", "http://example.com", parentId, - BrowserContract.Bookmarks.TYPE_BOOKMARK, 0, "tags", "description", "keyword"); - - id = ContentUris.parseId(mProvider.insert(BrowserContract.Bookmarks.CONTENT_URI, b)); - c = getBookmarkById(id); - mAsserter.is(c.moveToFirst(), true, "Inserted bookmark found"); - c.close(); - - deleted = 0; - try { - Uri uri = ContentUris.withAppendedId(BrowserContract.Bookmarks.CONTENT_URI, parentId); - deleted = mProvider.delete(appendUriParam(uri, BrowserContract.PARAM_IS_SYNC, "1"), null, null); - } catch(Exception e) {} - - mAsserter.is((deleted == 0), true, - "Should not be able to delete folder that causes orphan bookmarks"); - } - } - } - - private class TestDeleteBookmarksFavicons extends TestCase { - @Override - public void test() throws Exception { - ContentValues b = createOneBookmark(); - - final String pageUrl = b.getAsString(BrowserContract.Bookmarks.URL); - long id = ContentUris.parseId(mProvider.insert(BrowserContract.Bookmarks.CONTENT_URI, b)); - - // Insert the favicon into the favicons table - mProvider.insert(BrowserContract.Favicons.CONTENT_URI, createFaviconEntry(pageUrl, "FAVICON")); - - Cursor c = getFaviconsByUrl(pageUrl); - mAsserter.is(c.moveToFirst(), true, "Inserted favicon found"); - c.close(); - - mProvider.delete(ContentUris.withAppendedId(BrowserContract.Bookmarks.CONTENT_URI, id), null, null); - - c = getFaviconsByUrl(pageUrl); - mAsserter.is(c.moveToFirst(), false, "Favicon is deleted with last reference to it"); - c.close(); - } - } - - private class TestUpdateBookmarks extends TestCase { - private int updateWithNullCol(long id, String colName) throws Exception { - ContentValues u = new ContentValues(); - u.putNull(colName); - - int updated = 0; - - try { - updated = mProvider.update(BrowserContract.Bookmarks.CONTENT_URI, u, - BrowserContract.Bookmarks._ID + " = ?", - new String[] { String.valueOf(id) }); - } catch (Exception e) {} - - return updated; - } - - @Override - public void test() throws Exception { - ContentValues b = createOneBookmark(); - long id = ContentUris.parseId(mProvider.insert(BrowserContract.Bookmarks.CONTENT_URI, b)); - - Cursor c = getBookmarkById(id); - mAsserter.is(c.moveToFirst(), true, "Inserted bookmark found"); - - long dateCreated = c.getLong(c.getColumnIndex(BrowserContract.Bookmarks.DATE_CREATED)); - long dateModified = c.getLong(c.getColumnIndex(BrowserContract.Bookmarks.DATE_MODIFIED)); - - ContentValues u = new ContentValues(); - u.put(BrowserContract.Bookmarks.TITLE, b.getAsString(BrowserContract.Bookmarks.TITLE) + "CHANGED"); - u.put(BrowserContract.Bookmarks.URL, b.getAsString(BrowserContract.Bookmarks.URL) + "/more/stuff"); - u.put(BrowserContract.Bookmarks.TAGS, b.getAsString(BrowserContract.Bookmarks.TAGS) + "CHANGED"); - u.put(BrowserContract.Bookmarks.DESCRIPTION, b.getAsString(BrowserContract.Bookmarks.DESCRIPTION) + "CHANGED"); - u.put(BrowserContract.Bookmarks.KEYWORD, b.getAsString(BrowserContract.Bookmarks.KEYWORD) + "CHANGED"); - u.put(BrowserContract.Bookmarks.TYPE, BrowserContract.Bookmarks.TYPE_FOLDER); - u.put(BrowserContract.Bookmarks.POSITION, 10); - - int updated = mProvider.update(BrowserContract.Bookmarks.CONTENT_URI, u, - BrowserContract.Bookmarks._ID + " = ?", - new String[] { String.valueOf(id) }); - - mAsserter.is((updated == 1), true, "Inserted bookmark was updated"); - c.close(); - - c = getBookmarkById(id); - mAsserter.is(c.moveToFirst(), true, "Updated bookmark found"); - - mAsserter.is(c.getString(c.getColumnIndex(BrowserContract.Bookmarks.TITLE)), u.getAsString(BrowserContract.Bookmarks.TITLE), - "Inserted bookmark has correct title"); - mAsserter.is(c.getString(c.getColumnIndex(BrowserContract.Bookmarks.URL)), u.getAsString(BrowserContract.Bookmarks.URL), - "Inserted bookmark has correct URL"); - mAsserter.is(c.getString(c.getColumnIndex(BrowserContract.Bookmarks.TAGS)), u.getAsString(BrowserContract.Bookmarks.TAGS), - "Inserted bookmark has correct tags"); - mAsserter.is(c.getString(c.getColumnIndex(BrowserContract.Bookmarks.KEYWORD)), u.getAsString(BrowserContract.Bookmarks.KEYWORD), - "Inserted bookmark has correct keyword"); - mAsserter.is(c.getString(c.getColumnIndex(BrowserContract.Bookmarks.DESCRIPTION)), u.getAsString(BrowserContract.Bookmarks.DESCRIPTION), - "Inserted bookmark has correct description"); - mAsserter.is(c.getString(c.getColumnIndex(BrowserContract.Bookmarks.POSITION)), u.getAsString(BrowserContract.Bookmarks.POSITION), - "Inserted bookmark has correct position"); - mAsserter.is(c.getString(c.getColumnIndex(BrowserContract.Bookmarks.TYPE)), u.getAsString(BrowserContract.Bookmarks.TYPE), - "Inserted bookmark has correct type"); - - mAsserter.is(c.getLong(c.getColumnIndex(BrowserContract.Bookmarks.DATE_CREATED)), - dateCreated, - "Updated bookmark has same creation date"); - - mAsserter.isnot(c.getLong(c.getColumnIndex(BrowserContract.Bookmarks.DATE_MODIFIED)), - dateModified, - "Updated bookmark has new modification date"); - - updated = updateWithNullCol(id, BrowserContract.Bookmarks.POSITION); - mAsserter.is((updated > 0), false, - "Should not be able to update bookmark with null position"); - - updated = updateWithNullCol(id, BrowserContract.Bookmarks.TYPE); - mAsserter.is((updated > 0), false, - "Should not be able to update bookmark with null type"); - - u = new ContentValues(); - u.put(BrowserContract.Bookmarks.URL, "http://examples2.com"); - - updated = mProvider.update(ContentUris.withAppendedId(BrowserContract.Bookmarks.CONTENT_URI, id), u, null, null); - c.close(); - - c = getBookmarkById(id); - mAsserter.is(c.moveToFirst(), true, "Updated bookmark found"); - - mAsserter.is(c.getString(c.getColumnIndex(BrowserContract.Bookmarks.URL)), u.getAsString(BrowserContract.Bookmarks.URL), - "Updated bookmark has correct URL using URI with id"); - c.close(); - } - } - - private class TestUpdateBookmarksFavicons extends TestCase { - @Override - public void test() throws Exception { - ContentValues b = createOneBookmark(); - - final String favicon = "FAVICON"; - final String newFavicon = "NEW_FAVICON"; - final String pageUrl = b.getAsString(BrowserContract.Bookmarks.URL); - - mProvider.insert(BrowserContract.Bookmarks.CONTENT_URI, b); - - // Insert the favicon into the favicons table - ContentValues f = createFaviconEntry(pageUrl, favicon); - long faviconId = ContentUris.parseId(mProvider.insert(BrowserContract.Favicons.CONTENT_URI, f)); - - Cursor c = getFaviconsByUrl(pageUrl); - mAsserter.is(c.moveToFirst(), true, "Inserted favicon found"); - - mAsserter.is(new String(c.getBlob(c.getColumnIndex(BrowserContract.Combined.FAVICON)), "UTF8"), - favicon, "Inserted favicon has corresponding favicon image"); - - ContentValues u = createFaviconEntry(pageUrl, newFavicon); - mProvider.update(BrowserContract.Favicons.CONTENT_URI, u, null, null); - c.close(); - - c = getFaviconsByUrl(pageUrl); - mAsserter.is(c.moveToFirst(), true, "Updated favicon found"); - - mAsserter.is(new String(c.getBlob(c.getColumnIndex(BrowserContract.Combined.FAVICON)), "UTF8"), - newFavicon, "Updated favicon has corresponding favicon image"); - c.close(); - } - } - - /** - * Create a folder of one thousand and one bookmarks, then impose an order - * on them. - * - * Verify that the reordering worked by querying. - */ - private class TestPositionBookmarks extends TestCase { - - public String makeGUID(final long in) { - String part = String.valueOf(in); - return "aaaaaaaaaaaa".substring(0, (12 - part.length())) + part; - } - - public void compareCursorToItems(final Cursor c, final String[] items, final int count) { - mAsserter.is(c.moveToFirst(), true, "Folder has children."); - - int posColumn = c.getColumnIndex(BrowserContract.Bookmarks.POSITION); - int guidColumn = c.getColumnIndex(BrowserContract.Bookmarks.GUID); - int i = 0; - - while (!c.isAfterLast()) { - String guid = c.getString(guidColumn); - long pos = c.getLong(posColumn); - if ((pos != i) || (guid == null) || (!guid.equals(items[i]))) { - mAsserter.is(pos, (long) i, "Position matches sequence."); - mAsserter.is(guid, items[i], "GUID matches sequence."); - } - ++i; - c.moveToNext(); - } - - mAsserter.is(i, count, "Folder has the right number of children."); - c.close(); - } - - public static final int NUMBER_OF_CHILDREN = 1001; - @Override - public void test() throws Exception { - // Create the containing folder. - ContentValues folder = createBookmark("FolderFolder", "", mMobileFolderId, - BrowserContract.Bookmarks.TYPE_FOLDER, 0, "", - "description", "keyword"); - folder.put(BrowserContract.Bookmarks.GUID, "folderfolder"); - long folderId = ContentUris.parseId(mProvider.insert(BrowserContract.Bookmarks.CONTENT_URI, folder)); - - mAsserter.dumpLog("TestPositionBookmarks: Folder inserted"); // Bug 968951 debug. - - // Create the children. - String[] items = new String[NUMBER_OF_CHILDREN]; - - // Reuse the same ContentValues. - ContentValues item = createBookmark("Test Bookmark", "http://example.com", folderId, - BrowserContract.Bookmarks.TYPE_FOLDER, 0, "", - "description", "keyword"); - - for (int i = 0; i < NUMBER_OF_CHILDREN; ++i) { - String guid = makeGUID(i); - items[i] = guid; - item.put(BrowserContract.Bookmarks.GUID, guid); - item.put(BrowserContract.Bookmarks.POSITION, i); - item.put(BrowserContract.Bookmarks.URL, "http://example.com/" + guid); - item.put(BrowserContract.Bookmarks.TITLE, "Test Bookmark " + guid); - mProvider.insert(BrowserContract.Bookmarks.CONTENT_URI, item); - } - - mAsserter.dumpLog("TestPositionBookmarks: Bookmarks inserted"); // Bug 968951 debug. - - Cursor c; - - // Verify insertion. - c = getBookmarksByParent(folderId); - mAsserter.dumpLog("TestPositionBookmarks: Got bookmarks by parent"); // Bug 968951 debug. - compareCursorToItems(c, items, NUMBER_OF_CHILDREN); - c.close(); - - // Now permute the items array. - Random rand = new Random(); - for (int i = 0; i < NUMBER_OF_CHILDREN; ++i) { - final int newPosition = rand.nextInt(NUMBER_OF_CHILDREN); - final String switched = items[newPosition]; - items[newPosition] = items[i]; - items[i] = switched; - } - - // Impose the positions. - long updated = mProvider.update(BrowserContract.Bookmarks.POSITIONS_CONTENT_URI, null, null, items); - mAsserter.is(updated, (long) NUMBER_OF_CHILDREN, "Updated " + NUMBER_OF_CHILDREN + " positions."); - - // Verify that the database was updated. - c = getBookmarksByParent(folderId); - compareCursorToItems(c, items, NUMBER_OF_CHILDREN); - c.close(); - } - } - - private class TestInsertHistory extends TestCase { - private long insertWithNullCol(String colName) throws Exception { - ContentValues h = createOneHistoryEntry(); - h.putNull(colName); - long id = -1; - - try { - id = ContentUris.parseId(mProvider.insert(BrowserContract.History.CONTENT_URI, h)); - } catch (Exception e) {} - - return id; - } - - @Override - public void test() throws Exception { - ContentValues h = createOneHistoryEntry(); - long id = ContentUris.parseId(mProvider.insert(BrowserContract.History.CONTENT_URI, h)); - Cursor c = getHistoryEntryById(id); - - mAsserter.is(c.moveToFirst(), true, "Inserted history entry found"); - - mAsserter.is(c.getString(c.getColumnIndex(BrowserContract.History.TITLE)), h.getAsString(BrowserContract.History.TITLE), - "Inserted history entry has correct title"); - mAsserter.is(c.getString(c.getColumnIndex(BrowserContract.History.URL)), h.getAsString(BrowserContract.History.URL), - "Inserted history entry has correct URL"); - mAsserter.is(c.getString(c.getColumnIndex(BrowserContract.History.VISITS)), h.getAsString(BrowserContract.History.VISITS), - "Inserted history entry has correct number of visits"); - mAsserter.is(c.getString(c.getColumnIndex(BrowserContract.History.DATE_LAST_VISITED)), h.getAsString(BrowserContract.History.DATE_LAST_VISITED), - "Inserted history entry has correct last visited date"); - mAsserter.is(c.getString(c.getColumnIndex(BrowserContract.History.IS_DELETED)), String.valueOf(0), - "Inserted history entry has correct is-deleted state"); - - id = insertWithNullCol(BrowserContract.History.URL); - mAsserter.is(id, -1L, - "Should not be able to insert history with null URL"); - - id = insertWithNullCol(BrowserContract.History.VISITS); - mAsserter.is(id, -1L, - "Should not be able to insert history with null number of visits"); - c.close(); - } - } - - private class TestInsertHistoryFavicons extends TestCase { - @Override - public void test() throws Exception { - ContentValues h = createOneHistoryEntry(); - - final String favicon = "FAVICON"; - final String pageUrl = h.getAsString(BrowserContract.History.URL); - - long id = ContentUris.parseId(mProvider.insert(BrowserContract.History.CONTENT_URI, h)); - - // Insert the favicon into the favicons table - mProvider.insert(BrowserContract.Favicons.CONTENT_URI, createFaviconEntry(pageUrl, favicon)); - - Cursor c = getHistoryEntryById(id, new String[] { BrowserContract.History.FAVICON }); - - mAsserter.is(c.moveToFirst(), true, "Inserted history entry found"); - - mAsserter.is(new String(c.getBlob(c.getColumnIndex(BrowserContract.History.FAVICON)), "UTF8"), - favicon, "Inserted history entry has corresponding favicon image"); - c.close(); - - c = getFaviconsByUrl(pageUrl); - mAsserter.is(c.moveToFirst(), true, "Inserted favicon found"); - - mAsserter.is(new String(c.getBlob(c.getColumnIndex(BrowserContract.Combined.FAVICON)), "UTF8"), - favicon, "Inserted favicon has corresponding favicon image"); - c.close(); - } - } - - private class TestDeleteHistory extends TestCase { - private long insertOneHistoryEntry() throws Exception { - ContentValues h = createOneHistoryEntry(); - long id = ContentUris.parseId(mProvider.insert(BrowserContract.History.CONTENT_URI, h)); - - Cursor c = getHistoryEntryById(id); - mAsserter.is(c.moveToFirst(), true, "Inserted history entry found"); - c.close(); - - return id; - } - - @Override - public void test() throws Exception { - long id = insertOneHistoryEntry(); - - int deleted = mProvider.delete(BrowserContract.History.CONTENT_URI, - BrowserContract.History._ID + " = ?", - new String[] { String.valueOf(id) }); - - mAsserter.is((deleted == 1), true, "Inserted history entry was deleted"); - - Cursor c = getHistoryEntryById(appendUriParam(BrowserContract.History.CONTENT_URI, BrowserContract.PARAM_SHOW_DELETED, "1"), id); - mAsserter.is(c.moveToFirst(), true, "Deleted history entry was only marked as deleted"); - - deleted = mProvider.delete(appendUriParam(BrowserContract.History.CONTENT_URI, BrowserContract.PARAM_IS_SYNC, "1"), - BrowserContract.History._ID + " = ?", - new String[] { String.valueOf(id) }); - - mAsserter.is((deleted == 1), true, "Inserted history entry was deleted"); - c.close(); - - c = getHistoryEntryById(appendUriParam(BrowserContract.History.CONTENT_URI, BrowserContract.PARAM_SHOW_DELETED, "1"), id); - mAsserter.is(c.moveToFirst(), false, "Inserted history is now actually deleted"); - - id = insertOneHistoryEntry(); - - deleted = mProvider.delete(ContentUris.withAppendedId(BrowserContract.History.CONTENT_URI, id), null, null); - mAsserter.is((deleted == 1), true, - "Inserted history entry was deleted using URI with id"); - c.close(); - - c = getHistoryEntryById(id); - mAsserter.is(c.moveToFirst(), false, - "Inserted history entry can't be found after deletion using URI with ID"); - c.close(); - } - } - - private class TestDeleteHistoryFavicons extends TestCase { - @Override - public void test() throws Exception { - ContentValues h = createOneHistoryEntry(); - - long id = ContentUris.parseId(mProvider.insert(BrowserContract.History.CONTENT_URI, h)); - final String pageUrl = h.getAsString(BrowserContract.History.URL); - - // Insert the favicon into the favicons table - mProvider.insert(BrowserContract.Favicons.CONTENT_URI, createFaviconEntry(pageUrl, "FAVICON")); - - Cursor c = getFaviconsByUrl(pageUrl); - mAsserter.is(c.moveToFirst(), true, "Inserted favicon found"); - - mProvider.delete(ContentUris.withAppendedId(BrowserContract.History.CONTENT_URI, id), null, null); - c.close(); - - c = getFaviconsByUrl(pageUrl); - mAsserter.is(c.moveToFirst(), false, "Favicon is deleted with last reference to it"); - c.close(); - } - } - - private class TestUpdateHistory extends TestCase { - private int updateWithNullCol(long id, String colName) throws Exception { - ContentValues u = new ContentValues(); - u.putNull(colName); - - int updated = 0; - - try { - updated = mProvider.update(BrowserContract.History.CONTENT_URI, u, - BrowserContract.History._ID + " = ?", - new String[] { String.valueOf(id) }); - } catch (Exception e) {} - - return updated; - } - - @Override - public void test() throws Exception { - ContentValues h = createOneHistoryEntry(); - long id = ContentUris.parseId(mProvider.insert(BrowserContract.History.CONTENT_URI, h)); - - Cursor c = getHistoryEntryById(id); - mAsserter.is(c.moveToFirst(), true, "Inserted history entry found"); - - long dateCreated = c.getLong(c.getColumnIndex(BrowserContract.History.DATE_CREATED)); - long dateModified = c.getLong(c.getColumnIndex(BrowserContract.History.DATE_MODIFIED)); - - ContentValues u = new ContentValues(); - u.put(BrowserContract.History.VISITS, h.getAsInteger(BrowserContract.History.VISITS) + 1); - u.put(BrowserContract.History.DATE_LAST_VISITED, System.currentTimeMillis()); - u.put(BrowserContract.History.TITLE, h.getAsString(BrowserContract.History.TITLE) + "CHANGED"); - u.put(BrowserContract.History.URL, h.getAsString(BrowserContract.History.URL) + "/more/stuff"); - - int updated = mProvider.update(BrowserContract.History.CONTENT_URI, u, - BrowserContract.History._ID + " = ?", - new String[] { String.valueOf(id) }); - - mAsserter.is((updated == 1), true, "Inserted history entry was updated"); - c.close(); - - c = getHistoryEntryById(id); - mAsserter.is(c.moveToFirst(), true, "Updated history entry found"); - - mAsserter.is(c.getString(c.getColumnIndex(BrowserContract.History.TITLE)), u.getAsString(BrowserContract.History.TITLE), - "Updated history entry has correct title"); - mAsserter.is(c.getString(c.getColumnIndex(BrowserContract.History.URL)), u.getAsString(BrowserContract.History.URL), - "Updated history entry has correct URL"); - mAsserter.is(c.getString(c.getColumnIndex(BrowserContract.History.VISITS)), u.getAsString(BrowserContract.History.VISITS), - "Updated history entry has correct number of visits"); - mAsserter.is(c.getString(c.getColumnIndex(BrowserContract.History.DATE_LAST_VISITED)), u.getAsString(BrowserContract.History.DATE_LAST_VISITED), - "Updated history entry has correct last visited date"); - - mAsserter.is(c.getLong(c.getColumnIndex(BrowserContract.History.DATE_CREATED)), - dateCreated, - "Updated history entry has same creation date"); - - mAsserter.isnot(c.getLong(c.getColumnIndex(BrowserContract.History.DATE_MODIFIED)), - dateModified, - "Updated history entry has new modification date"); - - updated = updateWithNullCol(id, BrowserContract.History.URL); - mAsserter.is((updated > 0), false, - "Should not be able to update history with null URL"); - - updated = updateWithNullCol(id, BrowserContract.History.VISITS); - mAsserter.is((updated > 0), false, - "Should not be able to update history with null number of visits"); - - u = new ContentValues(); - u.put(BrowserContract.History.URL, "http://examples2.com"); - - updated = mProvider.update(ContentUris.withAppendedId(BrowserContract.History.CONTENT_URI, id), u, null, null); - c.close(); - - c = getHistoryEntryById(id); - mAsserter.is(c.moveToFirst(), true, "Updated history entry found"); - - mAsserter.is(c.getString(c.getColumnIndex(BrowserContract.History.URL)), u.getAsString(BrowserContract.History.URL), - "Updated history entry has correct URL using URI with id"); - c.close(); - } - } - - private class TestUpdateHistoryFavicons extends TestCase { - @Override - public void test() throws Exception { - ContentValues h = createOneHistoryEntry(); - - final String favicon = "FAVICON"; - final String newFavicon = "NEW_FAVICON"; - final String pageUrl = h.getAsString(BrowserContract.History.URL); - - mProvider.insert(BrowserContract.History.CONTENT_URI, h); - - // Insert the favicon into the favicons table - mProvider.insert(BrowserContract.Favicons.CONTENT_URI, createFaviconEntry(pageUrl, favicon)); - - Cursor c = getFaviconsByUrl(pageUrl); - mAsserter.is(c.moveToFirst(), true, "Inserted favicon found"); - - mAsserter.is(new String(c.getBlob(c.getColumnIndex(BrowserContract.Combined.FAVICON)), "UTF8"), - favicon, "Inserted favicon has corresponding favicon image"); - - ContentValues u = createFaviconEntry(pageUrl, newFavicon); - - mProvider.update(BrowserContract.Favicons.CONTENT_URI, u, null, null); - c.close(); - - c = getFaviconsByUrl(pageUrl); - mAsserter.is(c.moveToFirst(), true, "Updated favicon found"); - - mAsserter.is(new String(c.getBlob(c.getColumnIndex(BrowserContract.Combined.FAVICON)), "UTF8"), - newFavicon, "Updated favicon has corresponding favicon image"); - c.close(); - } - } - - private class TestUpdateOrInsertHistory extends TestCase { - private final String TEST_URL_1 = "http://example.com"; - private final String TEST_URL_2 = "http://example.org"; - private final String TEST_TITLE = "Example"; - - private long getHistoryEntryIdByUrl(String url) { - Cursor c = mProvider.query(BrowserContract.History.CONTENT_URI, - new String[] { BrowserContract.History._ID }, - BrowserContract.History.URL + " = ?", - new String[] { url }, - null); - c.moveToFirst(); - long id = c.getLong(0); - c.close(); - - return id; - } - - @Override - public void test() throws Exception { - Uri updateHistoryUri = BrowserContract.History.CONTENT_URI.buildUpon(). - appendQueryParameter("increment_visits", "true").build(); - Uri updateOrInsertHistoryUri = BrowserContract.History.CONTENT_URI.buildUpon(). - appendQueryParameter("insert_if_needed", "true"). - appendQueryParameter("increment_visits", "true").build(); - - // Update a non-existent history entry, without specifying visits or title - ContentValues values = new ContentValues(); - values.put(BrowserContract.History.URL, TEST_URL_1); - - int updated = mProvider.update(updateHistoryUri, values, - BrowserContract.History.URL + " = ?", - new String[] { TEST_URL_1 }); - mAsserter.is((updated == 0), true, "History entry was not updated"); - Cursor c = mProvider.query(BrowserContract.History.CONTENT_URI, null, null, null, null); - mAsserter.is(c.moveToFirst(), false, "History entry was not inserted"); - c.close(); - - // Now let's try with update-or-insert. - updated = mProvider.update(updateOrInsertHistoryUri, values, - BrowserContract.History.URL + " = ?", - new String[] { TEST_URL_1 }); - mAsserter.is((updated == 1), true, "History entry was inserted"); - - long id = getHistoryEntryIdByUrl(TEST_URL_1); - c = getHistoryEntryById(id); - mAsserter.is(c.moveToFirst(), true, "History entry was inserted"); - - long dateCreated = c.getLong(c.getColumnIndex(BrowserContract.History.DATE_CREATED)); - long dateModified = c.getLong(c.getColumnIndex(BrowserContract.History.DATE_MODIFIED)); - - mAsserter.is(c.getLong(c.getColumnIndex(BrowserContract.History.VISITS)), 1L, - "Inserted history entry has correct default number of visits"); - mAsserter.is(c.getString(c.getColumnIndex(BrowserContract.History.TITLE)), TEST_URL_1, - "Inserted history entry has correct default title"); - - // Update the history entry, without specifying an additional visit count - values = new ContentValues(); - values.put(BrowserContract.History.DATE_LAST_VISITED, System.currentTimeMillis()); - values.put(BrowserContract.History.TITLE, TEST_TITLE); - - updated = mProvider.update(updateOrInsertHistoryUri, values, - BrowserContract.History._ID + " = ?", - new String[] { String.valueOf(id) }); - mAsserter.is((updated == 1), true, "Inserted history entry was updated"); - c.close(); - - c = getHistoryEntryById(id); - mAsserter.is(c.moveToFirst(), true, "Updated history entry found"); - - mAsserter.is(c.getString(c.getColumnIndex(BrowserContract.History.TITLE)), TEST_TITLE, - "Updated history entry has correct title"); - mAsserter.is(c.getLong(c.getColumnIndex(BrowserContract.History.VISITS)), 2L, - "Updated history entry has correct number of visits"); - mAsserter.is(c.getLong(c.getColumnIndex(BrowserContract.History.DATE_CREATED)), dateCreated, - "Updated history entry has same creation date"); - mAsserter.isnot(c.getLong(c.getColumnIndex(BrowserContract.History.DATE_MODIFIED)), dateModified, - "Updated history entry has new modification date"); - - // Create a new history entry, specifying visits and history - values = new ContentValues(); - values.put(BrowserContract.History.URL, TEST_URL_2); - values.put(BrowserContract.History.TITLE, TEST_TITLE); - values.put(BrowserContract.History.VISITS, 10); - - updated = mProvider.update(updateOrInsertHistoryUri, values, - BrowserContract.History.URL + " = ?", - new String[] { values.getAsString(BrowserContract.History.URL) }); - mAsserter.is((updated == 1), true, "History entry was inserted"); - - id = getHistoryEntryIdByUrl(TEST_URL_2); - c.close(); - - c = getHistoryEntryById(id); - mAsserter.is(c.moveToFirst(), true, "History entry was inserted"); - - dateCreated = c.getLong(c.getColumnIndex(BrowserContract.History.DATE_CREATED)); - dateModified = c.getLong(c.getColumnIndex(BrowserContract.History.DATE_MODIFIED)); - - mAsserter.is(c.getLong(c.getColumnIndex(BrowserContract.History.VISITS)), 10L, - "Inserted history entry has correct specified number of visits"); - mAsserter.is(c.getString(c.getColumnIndex(BrowserContract.History.TITLE)), TEST_TITLE, - "Inserted history entry has correct specified title"); - - // Update the history entry, specifying additional visit count. - // The expectation is that the value is ignored, and count is bumped by 1 only. - // At the same time, a visit is inserted into the visits table. - // See junit4 tests in BrowserProviderHistoryVisitsTest. - values = new ContentValues(); - values.put(BrowserContract.History.VISITS, 10); - - updated = mProvider.update(updateOrInsertHistoryUri, values, - BrowserContract.History._ID + " = ?", - new String[] { String.valueOf(id) }); - mAsserter.is((updated == 1), true, "Inserted history entry was updated"); - c.close(); - - c = getHistoryEntryById(id); - mAsserter.is(c.moveToFirst(), true, "Updated history entry found"); - - mAsserter.is(c.getString(c.getColumnIndex(BrowserContract.History.TITLE)), TEST_TITLE, - "Updated history entry has correct unchanged title"); - mAsserter.is(c.getString(c.getColumnIndex(BrowserContract.History.URL)), TEST_URL_2, - "Updated history entry has correct unchanged URL"); - mAsserter.is(c.getLong(c.getColumnIndex(BrowserContract.History.VISITS)), 11L, - "Updated history entry has correct number of visits"); - mAsserter.is(c.getLong(c.getColumnIndex(BrowserContract.History.DATE_CREATED)), dateCreated, - "Updated history entry has same creation date"); - mAsserter.isnot(c.getLong(c.getColumnIndex(BrowserContract.History.DATE_MODIFIED)), dateModified, - "Updated history entry has new modification date"); - c.close(); - - } - } - - private class TestInsertHistoryThumbnails extends TestCase { - @Override - public void test() throws Exception { - ContentValues h = createOneHistoryEntry(); - - final String thumbnail = "THUMBNAIL"; - final String pageUrl = h.getAsString(BrowserContract.History.URL); - - long id = ContentUris.parseId(mProvider.insert(BrowserContract.History.CONTENT_URI, h)); - - // Insert the thumbnail into the thumbnails table - mProvider.insert(BrowserContract.Thumbnails.CONTENT_URI, createThumbnailEntry(pageUrl, thumbnail)); - - Cursor c = getThumbnailByUrl(pageUrl); - mAsserter.is(c.moveToFirst(), true, "Inserted thumbnail found"); - - mAsserter.is(new String(c.getBlob(c.getColumnIndex(BrowserContract.Thumbnails.DATA)), "UTF8"), - thumbnail, "Inserted thumbnail has corresponding thumbnail image"); - c.close(); - } - } - - private class TestUpdateHistoryThumbnails extends TestCase { - @Override - public void test() throws Exception { - ContentValues h = createOneHistoryEntry(); - - final String thumbnail = "THUMBNAIL"; - final String newThumbnail = "NEW_THUMBNAIL"; - final String pageUrl = h.getAsString(BrowserContract.History.URL); - - mProvider.insert(BrowserContract.History.CONTENT_URI, h); - - // Insert the thumbnail into the thumbnails table - mProvider.insert(BrowserContract.Thumbnails.CONTENT_URI, createThumbnailEntry(pageUrl, thumbnail)); - - Cursor c = getThumbnailByUrl(pageUrl); - mAsserter.is(c.moveToFirst(), true, "Inserted thumbnail found"); - - mAsserter.is(new String(c.getBlob(c.getColumnIndex(BrowserContract.Thumbnails.DATA)), "UTF8"), - thumbnail, "Inserted thumbnail has corresponding thumbnail image"); - - ContentValues u = createThumbnailEntry(pageUrl, newThumbnail); - - mProvider.update(BrowserContract.Thumbnails.CONTENT_URI, u, null, null); - c.close(); - - c = getThumbnailByUrl(pageUrl); - mAsserter.is(c.moveToFirst(), true, "Updated thumbnail found"); - - mAsserter.is(new String(c.getBlob(c.getColumnIndex(BrowserContract.Thumbnails.DATA)), "UTF8"), - newThumbnail, "Updated thumbnail has corresponding thumbnail image"); - c.close(); - } - } - - private class TestDeleteHistoryThumbnails extends TestCase { - @Override - public void test() throws Exception { - ContentValues h = createOneHistoryEntry(); - - long id = ContentUris.parseId(mProvider.insert(BrowserContract.History.CONTENT_URI, h)); - final String pageUrl = h.getAsString(BrowserContract.History.URL); - - // Insert the thumbnail into the thumbnails table - mProvider.insert(BrowserContract.Thumbnails.CONTENT_URI, createThumbnailEntry(pageUrl, "THUMBNAIL")); - - Cursor c = getThumbnailByUrl(pageUrl); - mAsserter.is(c.moveToFirst(), true, "Inserted thumbnail found"); - - mProvider.delete(ContentUris.withAppendedId(BrowserContract.History.CONTENT_URI, id), null, null); - c.close(); - - c = getThumbnailByUrl(pageUrl); - mAsserter.is(c.moveToFirst(), false, "Thumbnail is deleted with last reference to it"); - c.close(); - } - } - - private class TestInsertUrlAnnotations extends TestCase { - @Override - public void test() throws Exception { - testInsertionViaContentProvider(); - testInsertionViaUrlAnnotations(); - } - - private void testInsertionViaContentProvider() throws Exception { - final String url = "http://mozilla.org"; - final String key = "todo"; - final String value = "v"; - final long dateCreated = System.currentTimeMillis(); - - mProvider.insert(BrowserContract.UrlAnnotations.CONTENT_URI, createUrlAnnotationEntry(url, key, value, dateCreated)); - - final Cursor c = getUrlAnnotationByUrl(url); - try { - mAsserter.is(c.moveToFirst(), true, "Inserted url annotation found"); - assertKeyValueSync(c, key, value); - mAsserter.is(c.getLong(c.getColumnIndex(BrowserContract.UrlAnnotations.DATE_CREATED)), dateCreated, - "Inserted url annotation has correct date created"); - mAsserter.is(c.getLong(c.getColumnIndex(BrowserContract.UrlAnnotations.DATE_MODIFIED)), dateCreated, - "Inserted url annotation has correct date modified"); - } finally { - c.close(); - } - } - - private void testInsertionViaUrlAnnotations() throws Exception { - final String url = "http://hello.org"; - final String key = "toTheUniverse"; - final String value = "42a"; - final long timeBeforeCreation = System.currentTimeMillis(); - - BrowserDB.from(getTestProfile()).getUrlAnnotations().insertAnnotation(mResolver, url, key, value); - - final Cursor c = getUrlAnnotationByUrl(url); - try { - mAsserter.is(c.moveToFirst(), true, "Inserted url annotation found"); - assertKeyValueSync(c, key, value); - mAsserter.is(true, c.getLong(c.getColumnIndex(BrowserContract.UrlAnnotations.DATE_CREATED)) >= timeBeforeCreation, - "Inserted url annotation has date created greater than or equal to time saved before insertion"); - mAsserter.is(true, c.getLong(c.getColumnIndex(BrowserContract.UrlAnnotations.DATE_MODIFIED)) >= timeBeforeCreation, - "Inserted url annotation has correct date modified greater than or equal to time saved before insertion"); - } finally { - c.close(); - } - } - - private void assertKeyValueSync(final Cursor c, final String key, final String value) { - mAsserter.is(c.getString(c.getColumnIndex(BrowserContract.UrlAnnotations.KEY)), key, - "Inserted url annotation has correct key"); - mAsserter.is(c.getString(c.getColumnIndex(BrowserContract.UrlAnnotations.VALUE)), value, - "Inserted url annotation has correct value"); - mAsserter.is(c.getInt(c.getColumnIndex(BrowserContract.UrlAnnotations.SYNC_STATUS)), SyncStatus.NEW.getDBValue(), - "Inserted url annotation has default sync status"); - } - } - - private class TestInsertUrlMetadata extends TestCase { - @Override - public void test() throws Exception { - testInsertionViaContentProvider(); - testInsertionViaUrlMetadata(); - // testRetrievalViaUrlMetadata depends on data added in the previous two tests - testRetrievalViaUrlMetadata(); - } - - final String url1 = "http://mozilla.org"; - final String url2 = "http://hello.org"; - - private void testInsertionViaContentProvider() throws Exception { - final String tileImage = "http://mozilla.org/tileImage.png"; - final String tileColor = "#FF0000"; - final String touchIcon = "http://mozilla.org/touchIcon.png"; - - // We can only use update since the redirection machinery doesn't exist for insert - mProvider.update(URLMetadataTable.CONTENT_URI.buildUpon().appendQueryParameter(BrowserContract.PARAM_INSERT_IF_NEEDED, "true").build(), - createUrlMetadataEntry(url1, tileImage, tileColor, touchIcon), - URLMetadataTable.URL_COLUMN + "=?", - new String[] {url1} - ); - - final Cursor c = getUrlMetadataByUrl(url1); - try { - mAsserter.is(c.getCount(), 1, "URL metadata inserted via Content Provider not found"); - } finally { - c.close(); - } - } - - private void testInsertionViaUrlMetadata() throws Exception { - final String tileImage = "http://hello.org/tileImage.png"; - final String tileColor = "#FF0000"; - final String touchIcon = "http://hello.org/touchIcon.png"; - - final Map data = new HashMap<>(); - data.put(URLMetadataTable.URL_COLUMN, url2); - data.put(URLMetadataTable.TILE_IMAGE_URL_COLUMN, tileImage); - data.put(URLMetadataTable.TILE_COLOR_COLUMN, tileColor); - data.put(URLMetadataTable.TOUCH_ICON_COLUMN, touchIcon); - - BrowserDB.from(getTestProfile()).getURLMetadata().save(mResolver, data); - - final Cursor c = getUrlMetadataByUrl(url2); - try { - mAsserter.is(c.moveToFirst(), true, "URL metadata inserted via UrlMetadata not found"); - } finally { - c.close(); - } - } - - private void testRetrievalViaUrlMetadata() { - // LocalURLMetadata has some caching of results: we need to test that this caching - // doesn't prevent us from accessing data that might not have been loaded into the cache. - // We do this by first doing queries with a subset of data, then later querying additional - // data for a given URL. E.g. even if the first query results in only the requested - // column being cached, the subsequent query should still retrieve all requested columns. - // (In this case the URL may be cached but without all data, we need to make sure that - // this state is correctly handled.) - URLMetadata metadata = BrowserDB.from(getTestProfile()).getURLMetadata(); - - Map> results; - Map urlData; - - // 1: retrieve just touch Icons for URL 1 - results = metadata.getForURLs(mResolver, - Collections.singletonList(url1), - Collections.singletonList(URLMetadataTable.TOUCH_ICON_COLUMN)); - - mAsserter.is(results.containsKey(url1), true, "URL 1 not found in results"); - - urlData = results.get(url1); - mAsserter.is(urlData.containsKey(URLMetadataTable.TOUCH_ICON_COLUMN), true, "touchIcon column missing in UrlMetadata results"); - - // 2: retrieve just tile color for URL 2 - results = metadata.getForURLs(mResolver, - Collections.singletonList(url2), - Collections.singletonList(URLMetadataTable.TILE_COLOR_COLUMN)); - - mAsserter.is(results.containsKey(url2), true, "URL 2 not found in results"); - - urlData = results.get(url2); - mAsserter.is(urlData.containsKey(URLMetadataTable.TILE_COLOR_COLUMN), true, "touchIcon column missing in UrlMetadata results"); - - - // 3: retrieve all columns for both URLs - final List urls = Arrays.asList(url1, url2); - - results = metadata.getForURLs(mResolver, - urls, - Arrays.asList(URLMetadataTable.TILE_IMAGE_URL_COLUMN, - URLMetadataTable.TILE_COLOR_COLUMN, - URLMetadataTable.TOUCH_ICON_COLUMN - )); - - mAsserter.is(results.containsKey(url1), true, "URL 1 not found in results"); - mAsserter.is(results.containsKey(url2), true, "URL 2 not found in results"); - - - for (final String url : urls) { - urlData = results.get(url); - mAsserter.is(urlData.containsKey(URLMetadataTable.TILE_IMAGE_URL_COLUMN), true, "touchIcon column missing in UrlMetadata results"); - mAsserter.is(urlData.containsKey(URLMetadataTable.TILE_COLOR_COLUMN), true, "touchIcon column missing in UrlMetadata results"); - mAsserter.is(urlData.containsKey(URLMetadataTable.TOUCH_ICON_COLUMN), true, "touchIcon column missing in UrlMetadata results"); - } - } - } - - private class TestCombinedView extends TestCase { - @Override - public void test() throws Exception { - final String TITLE_1 = "Test Page 1"; - final String TITLE_2 = "Test Page 2"; - final String TITLE_3_HISTORY = "Test Page 3 (History Entry)"; - final String TITLE_3_BOOKMARK = "Test Page 3 (Bookmark Entry)"; - final String TITLE_3_BOOKMARK2 = "Test Page 3 (Bookmark Entry 2)"; - - final String URL_1 = "http://example1.com"; - final String URL_2 = "http://example2.com"; - final String URL_3 = "http://example3.com"; - - final int VISITS = 10; - final long LAST_VISITED = System.currentTimeMillis(); - - // Create a basic history entry - ContentValues basicHistory = createHistoryEntry(TITLE_1, URL_1, VISITS, LAST_VISITED); - long basicHistoryId = ContentUris.parseId(mProvider.insert(BrowserContract.History.CONTENT_URI, basicHistory)); - - // Create a basic bookmark entry - ContentValues basicBookmark = createBookmark(TITLE_2, URL_2, mMobileFolderId, - BrowserContract.Bookmarks.TYPE_BOOKMARK, 0, "tags", "description", "keyword"); - long basicBookmarkId = ContentUris.parseId(mProvider.insert(BrowserContract.Bookmarks.CONTENT_URI, basicBookmark)); - - // Create a history entry and bookmark entry with the same URL to - // represent a visited bookmark - ContentValues combinedHistory = createHistoryEntry(TITLE_3_HISTORY, URL_3, VISITS, LAST_VISITED); - long combinedHistoryId = ContentUris.parseId(mProvider.insert(BrowserContract.History.CONTENT_URI, combinedHistory)); - - - ContentValues combinedBookmark = createBookmark(TITLE_3_BOOKMARK, URL_3, mMobileFolderId, - BrowserContract.Bookmarks.TYPE_BOOKMARK, 0, "tags", "description", "keyword"); - long combinedBookmarkId = ContentUris.parseId(mProvider.insert(BrowserContract.Bookmarks.CONTENT_URI, combinedBookmark)); - - ContentValues combinedBookmark2 = createBookmark(TITLE_3_BOOKMARK2, URL_3, mMobileFolderId, - BrowserContract.Bookmarks.TYPE_BOOKMARK, 0, "tags", "description", "keyword"); - long combinedBookmarkId2 = ContentUris.parseId(mProvider.insert(BrowserContract.Bookmarks.CONTENT_URI, combinedBookmark2)); - - // Create a bookmark folder to make sure it _doesn't_ show up in the results - ContentValues folderBookmark = createBookmark("", "", mMobileFolderId, - BrowserContract.Bookmarks.TYPE_FOLDER, 0, "tags", "description", "keyword"); - mProvider.insert(BrowserContract.Bookmarks.CONTENT_URI, folderBookmark); - - // Sort entries by url so we can check them individually - final Cursor c = mProvider.query(BrowserContract.Combined.CONTENT_URI, null, "", null, BrowserContract.Combined.URL); - - try { - mAsserter.is(c.getCount(), 3, "3 combined entries found"); - - // First combined entry is basic history entry - mAsserter.is(c.moveToFirst(), true, "Found basic history entry"); - mAsserter.is(c.getLong(c.getColumnIndex(BrowserContract.Combined._ID)), 0L, - "Combined _id column should always be 0"); - // TODO: Should we change BrowserProvider to make this return -1, not 0? - mAsserter.is(c.getLong(c.getColumnIndex(BrowserContract.Combined.BOOKMARK_ID)), 0L, - "Bookmark id should be 0 for basic history entry"); - mAsserter.is(c.getLong(c.getColumnIndex(BrowserContract.Combined.HISTORY_ID)), basicHistoryId, - "Basic history entry has correct history id"); - mAsserter.is(c.getString(c.getColumnIndex(BrowserContract.Combined.TITLE)), TITLE_1, - "Basic history entry has correct title"); - mAsserter.is(c.getString(c.getColumnIndex(BrowserContract.Combined.URL)), URL_1, - "Basic history entry has correct url"); - mAsserter.is(c.getInt(c.getColumnIndex(BrowserContract.Combined.VISITS)), VISITS, - "Basic history entry has correct number of visits"); - mAsserter.is(c.getLong(c.getColumnIndex(BrowserContract.Combined.DATE_LAST_VISITED)), LAST_VISITED, - "Basic history entry has correct last visit time"); - - // Second combined entry is basic bookmark entry - mAsserter.is(c.moveToNext(), true, "Found basic bookmark entry"); - mAsserter.is(c.getLong(c.getColumnIndex(BrowserContract.Combined._ID)), 0L, - "Combined _id column should always be 0"); - mAsserter.is(c.getLong(c.getColumnIndex(BrowserContract.Combined.BOOKMARK_ID)), basicBookmarkId, - "Basic bookmark entry has correct bookmark id"); - mAsserter.is(c.getLong(c.getColumnIndex(BrowserContract.Combined.HISTORY_ID)), -1L, - "History id should be -1 for basic bookmark entry"); - mAsserter.is(c.getString(c.getColumnIndex(BrowserContract.Combined.TITLE)), TITLE_2, - "Basic bookmark entry has correct title"); - mAsserter.is(c.getString(c.getColumnIndex(BrowserContract.Combined.URL)), URL_2, - "Basic bookmark entry has correct url"); - mAsserter.is(c.getInt(c.getColumnIndex(BrowserContract.Combined.VISITS)), -1, - "Visits should be -1 for basic bookmark entry"); - mAsserter.is(c.getLong(c.getColumnIndex(BrowserContract.Combined.DATE_LAST_VISITED)), -1L, - "Basic entry has correct last visit time"); - - // Third combined entry is a combined history/bookmark entry - mAsserter.is(c.moveToNext(), true, "Found third combined entry"); - mAsserter.is(c.getLong(c.getColumnIndex(BrowserContract.Combined._ID)), 0L, - "Combined _id column should always be 0"); - // The bookmark data (bookmark_id and title) associated with the combined entry is non-deterministic, - // it might end up with data coming from any of the matching bookmark entries. - mAsserter.is(c.getLong(c.getColumnIndex(BrowserContract.Combined.BOOKMARK_ID)) == combinedBookmarkId || - c.getLong(c.getColumnIndex(BrowserContract.Combined.BOOKMARK_ID)) == combinedBookmarkId2, true, - "Combined entry has correct bookmark id"); - mAsserter.is(c.getString(c.getColumnIndex(BrowserContract.Combined.TITLE)).equals(TITLE_3_BOOKMARK) || - c.getString(c.getColumnIndex(BrowserContract.Combined.TITLE)).equals(TITLE_3_BOOKMARK2), true, - "Combined entry has title corresponding to bookmark entry"); - mAsserter.is(c.getLong(c.getColumnIndex(BrowserContract.Combined.HISTORY_ID)), combinedHistoryId, - "Combined entry has correct history id"); - mAsserter.is(c.getString(c.getColumnIndex(BrowserContract.Combined.URL)), URL_3, - "Combined entry has correct url"); - mAsserter.is(c.getInt(c.getColumnIndex(BrowserContract.Combined.VISITS)), VISITS, - "Combined entry has correct number of visits"); - mAsserter.is(c.getLong(c.getColumnIndex(BrowserContract.Combined.DATE_LAST_VISITED)), LAST_VISITED, - "Combined entry has correct last visit time"); - } finally { - c.close(); - } - } - } - - private class TestCombinedViewDisplay extends TestCase { - @Override - public void test() throws Exception { - final String TITLE_1 = "Test Page 1"; - final String TITLE_2 = "Test Page 2"; - final String TITLE_3_HISTORY = "Test Page 3 (History Entry)"; - final String TITLE_3_BOOKMARK = "Test Page 3 (Bookmark Entry)"; - - final String URL_1 = "http://example.com"; - final String URL_2 = "http://example.org"; - final String URL_3 = "http://examples2.com"; - - final int VISITS = 10; - final long LAST_VISITED = System.currentTimeMillis(); - - // Create a basic history entry - ContentValues basicHistory = createHistoryEntry(TITLE_1, URL_1, VISITS, LAST_VISITED); - ContentUris.parseId(mProvider.insert(BrowserContract.History.CONTENT_URI, basicHistory)); - - // Create a basic bookmark entry - ContentValues basicBookmark = createBookmark(TITLE_2, URL_2, mMobileFolderId, - BrowserContract.Bookmarks.TYPE_BOOKMARK, 0, "tags", "description", "keyword"); - mProvider.insert(BrowserContract.Bookmarks.CONTENT_URI, basicBookmark); - - // Create a history entry and bookmark entry with the same URL to - // represent a visited bookmark - ContentValues combinedHistory = createHistoryEntry(TITLE_3_HISTORY, URL_3, VISITS, LAST_VISITED); - mProvider.insert(BrowserContract.History.CONTENT_URI, combinedHistory); - - ContentValues combinedBookmark = createBookmark(TITLE_3_BOOKMARK, URL_3, mMobileFolderId, - BrowserContract.Bookmarks.TYPE_BOOKMARK, 0, "tags", "description", "keyword"); - mProvider.insert(BrowserContract.Bookmarks.CONTENT_URI, combinedBookmark); - - final Cursor c = mProvider.query(BrowserContract.Combined.CONTENT_URI, null, "", null, null); - try { - mAsserter.is(c.getCount(), 3, "3 combined entries found"); - } finally { - c.close(); - } - } - } - - private class TestCombinedViewWithDeletedBookmark extends TestCase { - @Override - public void test() throws Exception { - final String TITLE = "Test Page 1"; - final String URL = "http://example.com"; - final int VISITS = 10; - final long LAST_VISITED = System.currentTimeMillis(); - - // Create a combined history entry - ContentValues combinedHistory = createHistoryEntry(TITLE, URL, VISITS, LAST_VISITED); - mProvider.insert(BrowserContract.History.CONTENT_URI, combinedHistory); - - // Create a combined bookmark entry - ContentValues combinedBookmark = createBookmark(TITLE, URL, mMobileFolderId, - BrowserContract.Bookmarks.TYPE_BOOKMARK, 0, "tags", "description", "keyword"); - long combinedBookmarkId = ContentUris.parseId(mProvider.insert(BrowserContract.Bookmarks.CONTENT_URI, combinedBookmark)); - - Cursor c = mProvider.query(BrowserContract.Combined.CONTENT_URI, null, "", null, null); - mAsserter.is(c.getCount(), 1, "1 combined entry found"); - - mAsserter.is(c.moveToFirst(), true, "Found combined entry with bookmark id"); - mAsserter.is(c.getLong(c.getColumnIndex(BrowserContract.Combined.BOOKMARK_ID)), combinedBookmarkId, - "Bookmark id should be set correctly on combined entry"); - - int deleted = mProvider.delete(BrowserContract.Bookmarks.CONTENT_URI, - BrowserContract.Bookmarks._ID + " = ?", - new String[] { String.valueOf(combinedBookmarkId) }); - - mAsserter.is((deleted == 1), true, "Inserted combined bookmark was deleted"); - c.close(); - - c = mProvider.query(BrowserContract.Combined.CONTENT_URI, null, "", null, null); - mAsserter.is(c.getCount(), 1, "1 combined entry found"); - - mAsserter.is(c.moveToFirst(), true, "Found combined entry without bookmark id"); - mAsserter.is(c.getLong(c.getColumnIndex(BrowserContract.Combined.BOOKMARK_ID)), 0L, - "Bookmark id should not be set to removed bookmark id"); - c.close(); - } - } - - /* - * Verify that insert, update, delete, and bulkInsert operations - * notify the ambient content resolver. Each operation calls the - * content resolver notifyChange method synchronously, so it is - * okay to test sequentially. - */ - private class TestBrowserProviderNotifications extends TestCase { - public static final String LOGTAG = "TestBPNotifications"; - - protected void ensureOnlyChangeNotifiedStartsWith(Uri expectedUri, String operation) { - if (expectedUri == null) { - throw new IllegalArgumentException("expectedUri must not be null"); - } - - if (mResolver.notifyChangeList.size() != 1) { - // Log to help post-mortem debugging - Log.w(LOGTAG, "after operation, notifyChangeList = " + mResolver.notifyChangeList); - } - - mAsserter.is((long) mResolver.notifyChangeList.size(), - 1L, - "Content observer was notified exactly once by " + operation); - - Uri uri = mResolver.notifyChangeList.poll(); - - mAsserter.isnot(uri, - null, - "Notification from " + operation + " was valid"); - - mAsserter.ok(uri.toString().startsWith(expectedUri.toString()), - "Content observer was notified exactly once by " + operation, - uri.toString() + " starts with expected prefix " + expectedUri); - } - - @Override - public void test() throws Exception { - // Insert - final ContentValues h = createOneHistoryEntry(); - - mResolver.notifyChangeList.clear(); - long id = ContentUris.parseId(mProvider.insert(BrowserContract.History.CONTENT_URI, h)); - - mAsserter.isnot(id, - -1L, - "Inserted item has valid id"); - - ensureOnlyChangeNotifiedStartsWith(BrowserContract.History.CONTENT_URI, "insert"); - - // Update - mResolver.notifyChangeList.clear(); - h.put(BrowserContract.History.TITLE, "http://newexample.com"); - - long numUpdated = mProvider.update(BrowserContract.History.CONTENT_URI, h, - BrowserContract.History._ID + " = ?", - new String[] { String.valueOf(id) }); - - mAsserter.is(numUpdated, - 1L, - "Correct number of items are updated"); - - ensureOnlyChangeNotifiedStartsWith(BrowserContract.History.CONTENT_URI, "update"); - - // Delete - mResolver.notifyChangeList.clear(); - long numDeleted = mProvider.delete(BrowserContract.History.CONTENT_URI, null, null); - - mAsserter.is(numDeleted, - 1L, - "Correct number of items are deleted"); - - ensureOnlyChangeNotifiedStartsWith(BrowserContract.History.CONTENT_URI, "delete"); - - // Bulk insert - final ContentValues[] hs = new ContentValues[] { createOneHistoryEntry() }; - - mResolver.notifyChangeList.clear(); - long numBulkInserted = mProvider.bulkInsert(BrowserContract.History.CONTENT_URI, hs); - - mAsserter.is(numBulkInserted, - 1L, - "Correct number of items are bulkInserted"); - - ensureOnlyChangeNotifiedStartsWith(BrowserContract.History.CONTENT_URI, "bulkInsert"); - } - } - - /** - * Assert that the provided cursor has the expected number of rows, - * closing the cursor afterwards. - */ - private void assertCountIsAndClose(Cursor c, int expectedCount, String message) { - try { - mAsserter.is(c.getCount(), expectedCount, message); - } finally { - c.close(); - } - } -} diff --git a/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/testBrowserSearchVisibility.java b/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/testBrowserSearchVisibility.java deleted file mode 100644 index d8fc793fc..000000000 --- a/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/testBrowserSearchVisibility.java +++ /dev/null @@ -1,69 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -package org.mozilla.gecko.tests; - -import android.support.v4.app.Fragment; -import android.view.KeyEvent; -import android.view.View; - -import com.robotium.solo.Condition; - -/** - * Test for browser search visibility. - * Sends queries from url bar input and verifies that browser search - * visibility is correct. - */ -public class testBrowserSearchVisibility extends BaseTest { - public void testSearchSuggestions() { - blockForGeckoReady(); - - focusUrlBar(); - - // search should not be visible when editing mode starts - assertBrowserSearchVisibility(false); - - mActions.sendKeys("a"); - - // search should be visible when entry is not empty - assertBrowserSearchVisibility(true); - - mActions.sendKeys("b"); - - // search continues to be visible when more text is added - assertBrowserSearchVisibility(true); - - mActions.sendKeyCode(KeyEvent.KEYCODE_DEL); - - // search continues to be visible when not all text is deleted - assertBrowserSearchVisibility(true); - - mActions.sendKeyCode(KeyEvent.KEYCODE_DEL); - - // search should not be visible, entry is empty now - assertBrowserSearchVisibility(false); - } - - private void assertBrowserSearchVisibility(final boolean isVisible) { - waitForCondition(new Condition() { - @Override - public boolean isSatisfied() { - final Fragment browserSearch = getBrowserSearch(); - - // The fragment should not be present at all. Testing if the - // fragment is present but has no defined view is not a valid - // state. - if (browserSearch == null) - return !isVisible; - - final View v = browserSearch.getView(); - if (isVisible && v != null && v.getVisibility() == View.VISIBLE) - return true; - - return false; - } - }, 5000); - } -} - diff --git a/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/testBug1217581.java b/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/testBug1217581.java deleted file mode 100644 index fe3c047a3..000000000 --- a/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/testBug1217581.java +++ /dev/null @@ -1,31 +0,0 @@ -/* -*- Mode: Java; c-basic-offset: 4; tab-width: 4; indent-tabs-mode: nil; -*- - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -package org.mozilla.gecko.tests; - - -import org.mozilla.gecko.Telemetry; - -public class testBug1217581 extends BaseTest { - // Take arbitrary histogram names used by Fennec. - private static final String TEST_HISTOGRAM_NAME = "FENNEC_SYNC_NUMBER_OF_SYNCS_COMPLETED"; - private static final String TEST_KEYED_HISTOGRAM_NAME = "FX_MIGRATION_ERRORS"; - private static final String TEST_KEY_NAME = "testBug1217581"; - - - public void testBug1217581() { - blockForGeckoReady(); - - mAsserter.ok(true, "Checking that adding to a keyed histogram then adding to a normal histogram does not cause a crash.", ""); - Telemetry.addToKeyedHistogram(TEST_KEYED_HISTOGRAM_NAME, TEST_KEY_NAME, 1); - Telemetry.addToHistogram(TEST_HISTOGRAM_NAME, 1); - mAsserter.ok(true, "Adding to a keyed histogram then to a normal histogram was a success!", ""); - - mAsserter.ok(true, "Checking that adding to a normal histogram then adding to a keyed histogram does not cause a crash.", ""); - Telemetry.addToHistogram(TEST_HISTOGRAM_NAME, 1); - Telemetry.addToKeyedHistogram(TEST_KEYED_HISTOGRAM_NAME, TEST_KEY_NAME, 1); - mAsserter.ok(true, "Adding to a normal histogram then to a keyed histogram was a success!", ""); - } -} diff --git a/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/testCheck2.java b/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/testCheck2.java deleted file mode 100644 index fc538b5bf..000000000 --- a/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/testCheck2.java +++ /dev/null @@ -1,61 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -package org.mozilla.gecko.tests; - -import org.json.JSONObject; - -public class testCheck2 extends PixelTest { - @Override - protected Type getTestType() { - return Type.TALOS; - } - - public void testCheck2() { - String url = getAbsoluteUrl("/startup_test/fennecmark/cnn/cnn.com/index.html"); - - // Enable double-tap zooming - setPreferenceAndWaitForChange("browser.ui.zoom.force-user-scalable", true); - - blockForGeckoReady(); - loadAndPaint(url); - - mDriver.setupScrollHandling(); - - /* - * for this test, we load the timecube page, and replay a recorded sequence of events - * that is a user panning/zooming around the page. specific things in the sequence - * include: - * - scroll on one axis followed by scroll on another axis - * - pinch zoom (in and out) - * - double-tap zoom (in and out) - * - multi-fling panning with different velocities on each fling - * - * this checkerboarding metric is going to be more of a "functional" style test than - * a "unit" style test; i.e. it covers a little bit of a lot of things to measure - * overall performance, but doesn't really allow identifying which part is slow. - */ - - MotionEventReplayer mer = new MotionEventReplayer(getInstrumentation(), mDriver.getGeckoLeft(), mDriver.getGeckoTop(), - mDriver.getGeckoWidth(), mDriver.getGeckoHeight()); - - float completeness = 0.0f; - mDriver.startCheckerboardRecording(); - // replay the events - try { - mer.replayEvents(getAsset("testcheck2-motionevents")); - // give it some time to draw any final frames - Thread.sleep(1000); - completeness = mDriver.stopCheckerboardRecording(); - } catch (Exception e) { - e.printStackTrace(); - mAsserter.ok(false, "Exception while replaying events", e.toString()); - } - - mAsserter.dumpLog("__start_report" + completeness + "__end_report"); - System.out.println("Completeness score: " + completeness); - long msecs = System.currentTimeMillis(); - mAsserter.dumpLog("__startTimestamp" + msecs + "__endTimestamp"); - } -} diff --git a/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/testCheck3.java b/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/testCheck3.java deleted file mode 100644 index 28915bdbc..000000000 --- a/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/testCheck3.java +++ /dev/null @@ -1,61 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -package org.mozilla.gecko.tests; - -import org.json.JSONObject; - -public class testCheck3 extends PixelTest { - @Override - protected Type getTestType() { - return Type.TALOS; - } - - public void testCheck3() { - String url = getAbsoluteUrl("/facebook.com/www.facebook.com/barackobama.html"); - - // Enable double-tap zooming - setPreferenceAndWaitForChange("browser.ui.zoom.force-user-scalable", true); - - blockForGeckoReady(); - loadAndPaint(url); - - mDriver.setupScrollHandling(); - - /* - * for this test, we load the timecube page, and replay a recorded sequence of events - * that is a user panning/zooming around the page. specific things in the sequence - * include: - * - scroll on one axis followed by scroll on another axis - * - pinch zoom (in and out) - * - double-tap zoom (in and out) - * - multi-fling panning with different velocities on each fling - * - * this checkerboarding metric is going to be more of a "functional" style test than - * a "unit" style test; i.e. it covers a little bit of a lot of things to measure - * overall performance, but doesn't really allow identifying which part is slow. - */ - - MotionEventReplayer mer = new MotionEventReplayer(getInstrumentation(), mDriver.getGeckoLeft(), mDriver.getGeckoTop(), - mDriver.getGeckoWidth(), mDriver.getGeckoHeight()); - - float completeness = 0.0f; - mDriver.startCheckerboardRecording(); - // replay the events - try { - mer.replayEvents(getAsset("testcheck2-motionevents")); - // give it some time to draw any final frames - Thread.sleep(1000); - completeness = mDriver.stopCheckerboardRecording(); - } catch (Exception e) { - e.printStackTrace(); - mAsserter.ok(false, "Exception while replaying events", e.toString()); - } - - mAsserter.dumpLog("__start_report" + completeness + "__end_report"); - System.out.println("Completeness score: " + completeness); - long msecs = System.currentTimeMillis(); - mAsserter.dumpLog("__startTimestamp" + msecs + "__endTimestamp"); - } -} diff --git a/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/testDBUtils.java b/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/testDBUtils.java deleted file mode 100644 index 700c1c255..000000000 --- a/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/testDBUtils.java +++ /dev/null @@ -1,70 +0,0 @@ -/* -*- Mode: Java; c-basic-offset: 4; tab-width: 20; indent-tabs-mode: nil; -*- - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -package org.mozilla.gecko.tests; - -import android.content.ContentValues; -import android.database.Cursor; -import android.database.sqlite.SQLiteDatabase; -import org.mozilla.gecko.db.DBUtils; - -import java.io.File; -import java.io.IOException; - -public class testDBUtils extends BaseTest { - public void testDBUtils() throws IOException { - final File cacheDir = getInstrumentation().getContext().getCacheDir(); - final File dbFile = File.createTempFile("testDBUtils", ".db", cacheDir); - final SQLiteDatabase db = SQLiteDatabase.openOrCreateDatabase(dbFile, null); - try { - mAsserter.ok(db != null, "Created DB.", null); - db.execSQL("CREATE TABLE foo (x INTEGER NOT NULL DEFAULT 0, y TEXT)"); - final ContentValues v = new ContentValues(); - v.put("x", 5); - v.put("y", "a"); - db.insert("foo", null, v); - v.put("x", 2); - v.putNull("y"); - db.insert("foo", null, v); - v.put("x", 3); - v.put("y", "z"); - db.insert("foo", null, v); - - DBUtils.UpdateOperation[] ops = {DBUtils.UpdateOperation.BITWISE_OR, DBUtils.UpdateOperation.ASSIGN}; - ContentValues[] values = {new ContentValues(), new ContentValues()}; - values[0].put("x", 0xff); - values[1].put("y", "hello"); - - final int updated = DBUtils.updateArrays(db, "foo", values, ops, "x >= 3", null); - - mAsserter.ok(updated == 2, "Updated two rows.", null); - final Cursor out = db.query("foo", new String[]{"x", "y"}, null, null, null, null, "x"); - try { - mAsserter.ok(out.moveToNext(), "Has first result.", null); - mAsserter.ok(2 == out.getInt(0), "1: First column was untouched.", null); - mAsserter.ok(out.isNull(1), "1: Second column was untouched.", null); - - mAsserter.ok(out.moveToNext(), "Has second result.", null); - mAsserter.ok((0xff | 3) == out.getInt(0), "2: First column was ORed correctly.", null); - mAsserter.ok("hello".equals(out.getString(1)), "2: Second column was assigned correctly.", null); - - mAsserter.ok(out.moveToNext(), "Has third result.", null); - mAsserter.ok((0xff | 5) == out.getInt(0), "3: First column was ORed correctly.", null); - mAsserter.ok("hello".equals(out.getString(1)), "3: Second column was assigned correctly.", null); - - mAsserter.ok(!out.moveToNext(), "No more results.", null); - } finally { - out.close(); - } - - } finally { - try { - db.close(); - } catch (Exception e) { - } - dbFile.delete(); - } - } -} diff --git a/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/testDistribution.java b/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/testDistribution.java deleted file mode 100644 index 4cc08cc5c..000000000 --- a/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/testDistribution.java +++ /dev/null @@ -1,556 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -package org.mozilla.gecko.tests; - -import java.io.File; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.net.HttpURLConnection; -import java.net.URI; -import java.util.Locale; -import java.util.jar.JarInputStream; -import java.util.NoSuchElementException; - -import org.json.JSONArray; -import org.json.JSONException; -import org.json.JSONObject; - -import org.mozilla.gecko.Actions; -import org.mozilla.gecko.AppConstants; -import org.mozilla.gecko.BrowserLocaleManager; -import org.mozilla.gecko.GeckoProfile; -import org.mozilla.gecko.GeckoSharedPrefs; -import org.mozilla.gecko.db.BrowserContract; -import org.mozilla.gecko.distribution.Distribution; -import org.mozilla.gecko.distribution.ReferrerDescriptor; -import org.mozilla.gecko.distribution.ReferrerReceiver; -import org.mozilla.gecko.preferences.DistroSharedPrefsImport; -import org.mozilla.gecko.preferences.GeckoPreferences; -import org.mozilla.gecko.util.ThreadUtils; - -import android.app.Activity; -import android.content.BroadcastReceiver; -import android.content.Context; -import android.content.Intent; -import android.content.IntentFilter; -import android.content.SharedPreferences; -import android.support.v4.content.LocalBroadcastManager; -import android.util.Log; - -/** - * Tests distribution customization. - * mock-package.zip should contain the following directory structure: - * - * distribution/ - * preferences.json - * bookmarks.json - * searchplugins/ - * common/ - * engine.xml - * suggestedsites/ - * locales/ - * en-US/ - * suggestedsites.json - * extensions/ - * distribution.test@mozilla.org.xpi - */ -public class testDistribution extends ContentProviderTest { - private static final String CLASS_REFERRER_RECEIVER = "org.mozilla.gecko.distribution.ReferrerReceiver"; - private static final String ACTION_INSTALL_REFERRER = "com.android.vending.INSTALL_REFERRER"; - private static final int WAIT_TIMEOUT_MSEC = 10000; - public static final String LOGTAG = "GeckoTestDistribution"; - - public static class TestableDistribution extends Distribution { - @Override - protected JarInputStream fetchDistribution(URI uri, - HttpURLConnection connection) throws IOException { - Log.i(LOGTAG, "Not downloading: this is a test."); - return null; - } - - public TestableDistribution(Context context) { - super(context); - } - - public void go() { - doInit(); - } - - public static void clearReferrerDescriptorForTesting() { - referrer = null; - } - - public static ReferrerDescriptor getReferrerDescriptorForTesting() { - return referrer; - } - } - - private static final String MOCK_PACKAGE = "mock-package.zip"; - private static final int PREF_REQUEST_ID = 0x7357; - - private Activity mActivity; - - /** - * This is a hack. - * - * Startup results in us writing prefs -- we fetch the Distribution, which - * caches its state. Our tests try to wipe those prefs, but apparently - * sometimes race with startup, which leads to us not getting one of our - * expected messages. The test fails. - * - * This hack waits for any existing background tasks -- such as the one that - * writes prefs -- to finish before we begin the test. - */ - private void waitForBackgroundHappiness() { - final Object signal = new Object(); - final Runnable done = new Runnable() { - @Override - public void run() { - synchronized (signal) { - signal.notify(); - } - } - }; - synchronized (signal) { - ThreadUtils.postToBackgroundThread(done); - try { - signal.wait(); - } catch (InterruptedException e) { - mAsserter.ok(false, "InterruptedException waiting on background thread.", e.toString()); - } - } - mAsserter.dumpLog("Background task completed. Proceeding."); - } - - public void testDistribution() throws Exception { - mActivity = getActivity(); - - String mockPackagePath = getMockPackagePath(); - - // Wait for any startup-related background distribution shenanigans to - // finish. This reduces the chance of us racing with startup pref writes. - waitForBackgroundHappiness(); - - // Pre-clear distribution pref, run basic preferences and en-US localized preferences Tests - clearDistributionPref(); - clearDistributionFromDataData(); - - setTestLocale("en-US"); - try { - initDistribution(mockPackagePath); - } catch(NoSuchElementException e) { - // TODO: determine why this exception is intermittently thrown - Log.w(LOGTAG, "NoSuchElementException on first initDistribution -- will retry"); - mSolo.sleep(4000); - initDistribution(mockPackagePath); - } - checkPreferences(); - checkAndroidPreferences(); - checkLocalizedPreferences("en-US"); - checkSearchPlugin(); - checkAddon(); - - // Pre-clear distribution pref, and run es-MX localized preferences Test - clearDistributionPref(); - clearDistributionFromDataData(); - setTestLocale("es-MX"); - initDistribution(mockPackagePath); - checkLocalizedPreferences("es-MX"); - - // Test the (stubbed) download interaction. - setTestLocale("en-US"); - clearDistributionPref(); - clearDistributionFromDataData(); - doTestValidReferrerIntent(); - - clearDistributionPref(); - clearDistributionFromDataData(); - doTestInvalidReferrerIntent(); - } - - private void setOSLocale(Locale locale) { - Locale.setDefault(locale); - BrowserLocaleManager.storeAndNotifyOSLocale(GeckoSharedPrefs.forProfile(mActivity), locale); - } - - private abstract class ExpectNoDistributionCallback implements Distribution.ReadyCallback { - @Override - public void distributionFound(final Distribution distribution) { - mAsserter.ok(false, "No distributionFound.", "Wasn't expecting a distribution!"); - synchronized (distribution) { - distribution.notifyAll(); - } - } - - @Override - public void distributionArrivedLate(final Distribution distribution) { - mAsserter.ok(false, "No distributionArrivedLate.", "Wasn't expecting a late distribution!"); - } - } - - private void doReferrerTest(String ref, final TestableDistribution distribution, final Distribution.ReadyCallback distributionReady) throws InterruptedException { - final Intent intent = new Intent(ACTION_INSTALL_REFERRER); - intent.setClassName(AppConstants.ANDROID_PACKAGE_NAME, CLASS_REFERRER_RECEIVER); - intent.putExtra("referrer", ref); - - final BroadcastReceiver receiver = new BroadcastReceiver() { - @Override - public void onReceive(Context context, Intent intent) { - Log.i(LOGTAG, "Test received " + intent.getAction()); - - ThreadUtils.postToBackgroundThread(new Runnable() { - @Override - public void run() { - distribution.addOnDistributionReadyCallback(distributionReady); - distribution.go(); - } - }); - } - }; - - IntentFilter intentFilter = new IntentFilter(ReferrerReceiver.ACTION_REFERRER_RECEIVED); - final LocalBroadcastManager localBroadcastManager = LocalBroadcastManager.getInstance(mActivity); - localBroadcastManager.registerReceiver(receiver, intentFilter); - - Log.i(LOGTAG, "Broadcasting referrer intent."); - try { - mActivity.sendBroadcast(intent, null); - synchronized (distribution) { - distribution.wait(WAIT_TIMEOUT_MSEC); - } - } finally { - localBroadcastManager.unregisterReceiver(receiver); - } - } - - public void doTestValidReferrerIntent() throws Exception { - // Equivalent to - // am broadcast -a com.android.vending.INSTALL_REFERRER \ - // -n org.mozilla.fennec/org.mozilla.gecko.distribution.ReferrerReceiver \ - // --es "referrer" "utm_source=mozilla&utm_medium=testmedium&utm_term=testterm&utm_content=testcontent&utm_campaign=distribution" - final String ref = "utm_source=mozilla&utm_medium=testmedium&utm_term=testterm&utm_content=testcontent&utm_campaign=distribution"; - final TestableDistribution distribution = new TestableDistribution(mActivity); - final Distribution.ReadyCallback distributionReady = new ExpectNoDistributionCallback() { - @Override - public void distributionNotFound() { - Log.i(LOGTAG, "Test told distribution processing is done."); - mAsserter.ok(!distribution.exists(), "Not processed.", "No download because we're offline."); - ReferrerDescriptor referrerValue = TestableDistribution.getReferrerDescriptorForTesting(); - mAsserter.dumpLog("Referrer was " + referrerValue); - mAsserter.is(referrerValue.content, "testcontent", "Referrer content"); - mAsserter.is(referrerValue.medium, "testmedium", "Referrer medium"); - mAsserter.is(referrerValue.campaign, "distribution", "Referrer campaign"); - synchronized (distribution) { - distribution.notifyAll(); - } - } - }; - - doReferrerTest(ref, distribution, distributionReady); - } - - /** - * Test processing if the campaign isn't "distribution". The intent shouldn't - * result in a download, and won't be saved as the temporary referrer, - * even if we *do* include it in a Campaign:Set message. - */ - public void doTestInvalidReferrerIntent() throws Exception { - // Equivalent to - // am broadcast -a com.android.vending.INSTALL_REFERRER \ - // -n org.mozilla.fennec/org.mozilla.gecko.distribution.ReferrerReceiver \ - // --es "referrer" "utm_source=mozilla&utm_medium=testmedium&utm_term=testterm&utm_content=testcontent&utm_campaign=testname" - final String ref = "utm_source=mozilla&utm_medium=testmedium&utm_term=testterm&utm_content=testcontent&utm_campaign=testname"; - final TestableDistribution distribution = new TestableDistribution(mActivity); - final Distribution.ReadyCallback distributionReady = new ExpectNoDistributionCallback() { - @Override - public void distributionNotFound() { - mAsserter.ok(!distribution.exists(), "Not processed.", "No download because campaign was wrong."); - ReferrerDescriptor referrerValue = TestableDistribution.getReferrerDescriptorForTesting(); - mAsserter.is(referrerValue, null, "No referrer."); - synchronized (distribution) { - distribution.notifyAll(); - } - } - }; - - doReferrerTest(ref, distribution, distributionReady); - } - - // Initialize the distribution from the mock package. - private Distribution initDistribution(String aPackagePath) { - // Call Distribution.init with the mock package. - Actions.EventExpecter distributionSetExpecter = mActions.expectGeckoEvent("Distribution:Set:OK"); - Distribution dist = Distribution.init(mActivity, aPackagePath, "prefs-" + System.currentTimeMillis()); - distributionSetExpecter.blockForEvent(); - distributionSetExpecter.unregisterListener(); - DistroSharedPrefsImport.importPreferences(mActivity, dist); - return dist; - } - - // Test distribution and preferences values stored in preferences.json - private void checkPreferences() { - String prefID = "distribution.id"; - String prefAbout = "distribution.about"; - String prefVersion = "distribution.version"; - String prefTestBoolean = "distribution.test.boolean"; - String prefTestString = "distribution.test.string"; - String prefTestInt = "distribution.test.int"; - - try { - final String[] prefNames = { prefID, - prefAbout, - prefVersion, - prefTestBoolean, - prefTestString, - prefTestInt }; - - final JSONArray preferences = getPrefs(prefNames); - for (int i = 0; i < preferences.length(); i++) { - JSONObject pref = (JSONObject) preferences.get(i); - String name = pref.getString("name"); - - if (name.equals(prefID)) { - mAsserter.is(pref.getString("value"), "test-partner", "check " + prefID); - } else if (name.equals(prefAbout)) { - mAsserter.is(pref.getString("value"), "Test Partner", "check " + prefAbout); - } else if (name.equals(prefVersion)) { - mAsserter.is(pref.getInt("value"), 1, "check " + prefVersion); - } else if (name.equals(prefTestBoolean)) { - mAsserter.is(pref.getBoolean("value"), true, "check " + prefTestBoolean); - } else if (name.equals(prefTestString)) { - mAsserter.is(pref.getString("value"), "test", "check " + prefTestString); - } else if (name.equals(prefTestInt)) { - mAsserter.is(pref.getInt("value"), 5, "check " + prefTestInt); - } - } - - } catch (JSONException e) { - mAsserter.ok(false, "exception getting preferences", e.toString()); - } - } - - private void checkAndroidPreferences() { - final SharedPreferences sharedPreferences = GeckoSharedPrefs.forProfile(getActivity()); - String prefTestBoolean = "android.distribution.test.boolean"; - String prefTestString = "android.distribution.test.string"; - String prefTestInt = "android.distribution.test.int"; - String prefTestLong = "android.distribution.test.long"; - - final String[] prefNames = { prefTestBoolean, - prefTestString, - prefTestInt, - prefTestLong }; - - try { - for (String name : prefNames) { - if (name.equals(prefTestBoolean)) { - mAsserter.is(sharedPreferences.getBoolean(GeckoPreferences.NON_PREF_PREFIX + name, false), true, "check " + prefTestBoolean); - } else if (name.equals(prefTestString)) { - mAsserter.is(sharedPreferences.getString(GeckoPreferences.NON_PREF_PREFIX + name, ""), "test", "check " + prefTestString); - } else if (name.equals(prefTestInt)) { - mAsserter.is(sharedPreferences.getInt(GeckoPreferences.NON_PREF_PREFIX + name, 0), 1, "check " + prefTestInt); - } else if (name.equals(prefTestLong)) { - mAsserter.is(sharedPreferences.getLong(GeckoPreferences.NON_PREF_PREFIX + name, 0), 2147483648l, "check " + prefTestLong); - } - } - } catch (ClassCastException e) { - mAsserter.ok(false, "exception getting preferences", e.toString()); - } - } - - private void checkSearchPlugin() { - Actions.RepeatedEventExpecter eventExpecter = mActions.expectGeckoEvent("SearchEngines:Data"); - mActions.sendGeckoEvent("SearchEngines:GetVisible", null); - - try { - JSONObject data = new JSONObject(eventExpecter.blockForEventData()); - eventExpecter.unregisterListener(); - JSONArray searchEngines = data.getJSONArray("searchEngines"); - boolean foundEngine = false; - for (int i = 0; i < searchEngines.length(); i++) { - JSONObject engine = (JSONObject) searchEngines.get(i); - String name = engine.getString("name"); - if (name.equals("Test search engine")) { - foundEngine = true; - break; - } - } - mAsserter.ok(foundEngine, "check search plugin", "found test search plugin"); - } catch (JSONException e) { - mAsserter.ok(false, "exception getting search plugins", e.toString()); - } - } - - private void checkAddon() { - try { - final String[] prefNames = { "distribution.test.addonEnabled" }; - final JSONArray preferences = getPrefs(prefNames); - final JSONObject pref = (JSONObject) preferences.get(0); - mAsserter.is(pref.getBoolean("value"), true, "check distribution add-on is enabled"); - } catch (JSONException e) { - mAsserter.ok(false, "exception getting preferences", e.toString()); - } - } - - private JSONArray getPrefs(String[] prefNames) throws JSONException { - final JSONArray result = new JSONArray(); - - mActions.getPrefs(prefNames, new Actions.PrefHandlerBase() { - private void addItem(String pref, Object value) { - try { - final JSONObject item = new JSONObject(); - item.put("name", pref).put("value", value); - result.put(item); - } catch (final JSONException e) { - mAsserter.ok(false, "exception getting prefs", e.toString()); - } - } - - @Override // Actions.PrefHandlerBase - public void prefValue(String pref, boolean value) { - addItem(pref, value); - } - - @Override // Actions.PrefHandlerBase - public void prefValue(String pref, int value) { - addItem(pref, value); - } - - @Override // Actions.PrefHandlerBase - public void prefValue(String pref, String value) { - addItem(pref, value); - } - }).waitForFinish(); - - return result; - } - - // Sets the distribution locale preference for the test. - private void setTestLocale(String locale) { - BrowserLocaleManager.getInstance().setSelectedLocale(mActivity, locale); - } - - // Test localized distribution and preferences values stored in preferences.json - private void checkLocalizedPreferences(final String aLocale) { - final String prefAbout = "distribution.about"; - final String prefLocalizeable = "distribution.test.localizeable"; - final String prefLocalizeableOverride = "distribution.test.localizeable-override"; - final String[] prefNames = { prefAbout, prefLocalizeable, prefLocalizeableOverride }; - - mActions.getPrefs(prefNames, new Actions.PrefHandlerBase() { - @Override // Actions.PrefHandlerBase - public void prefValue(String name, String value) { - if (name.equals(prefAbout)) { - if (aLocale.equals("en-US")) { - mAsserter.is(value, "Test Partner", "check " + prefAbout); - } else if (aLocale.equals("es-MX")) { - mAsserter.is(value, "Afiliado de Prueba", "check " + prefAbout); - } - } else if (name.equals(prefLocalizeable)) { - if (aLocale.equals("en-US")) { - mAsserter.is(value, "http://test.org/en-US/en-US/", "check " + prefLocalizeable); - } else if (aLocale.equals("es-MX")) { - mAsserter.is(value, "http://test.org/es-MX/es-MX/", "check " + prefLocalizeable); - } - } else if (name.equals(prefLocalizeableOverride)) { - if (aLocale.equals("en-US")) { - mAsserter.is(value, "http://cheese.com", "check " + prefLocalizeableOverride); - } else if (aLocale.equals("es-MX")) { - mAsserter.is(value, "http://test.org/es-MX/", "check " + prefLocalizeableOverride); - } - } else { - // Raise exception. - super.prefValue(name, value); - } - } - }).waitForFinish(); - } - - // Copies the mock package to the data directory and returns the file path to it. - private String getMockPackagePath() { - String mockPackagePath = ""; - - try { - InputStream inStream = getAsset(MOCK_PACKAGE); - File dataDir = new File(mActivity.getApplicationInfo().dataDir); - File outFile = new File(dataDir, MOCK_PACKAGE); - - OutputStream outStream = new FileOutputStream(outFile); - int b; - while ((b = inStream.read()) != -1) { - outStream.write(b); - } - inStream.close(); - outStream.close(); - - mockPackagePath = outFile.getPath(); - - } catch (Exception e) { - mAsserter.ok(false, "exception copying mock distribution package to data directory", e.toString()); - } - - return mockPackagePath; - } - - /** - * Clears the distribution pref to return distribution state to STATE_UNKNOWN, - * and wipes the in-memory referrer pigeonhole. - */ - private void clearDistributionPref() { - mAsserter.dumpLog("Clearing distribution pref."); - SharedPreferences settings = mActivity.getSharedPreferences("GeckoApp", Activity.MODE_PRIVATE); - String keyName = mActivity.getPackageName() + ".distribution_state"; - settings.edit().remove(keyName).commit(); - TestableDistribution.clearReferrerDescriptorForTesting(); - } - - /** - * Clears any distribution found in /data/data. - */ - private void clearDistributionFromDataData() throws Exception { - File dataDir = new File(mActivity.getApplicationInfo().dataDir); - - // Recursively delete distribution files that Distribution.init copied to data directory. - File distDir = new File(dataDir, "distribution"); - if (distDir.exists()) { - mAsserter.dumpLog("Clearing distribution from " + distDir.getAbsolutePath()); - delete(distDir); - } else { - mAsserter.dumpLog("No distribution to clear from " + distDir.getAbsolutePath()); - } - } - - @Override - public void setUp() throws Exception { - // TODO: Set up the content provider after setting the distribution. - super.setUp(sBrowserProviderCallable, BrowserContract.AUTHORITY, "browser.db"); - } - - private void delete(File file) throws Exception { - if (file.isDirectory()) { - File[] files = file.listFiles(); - for (File f : files) { - delete(f); - } - } - mAsserter.ok(file.delete(), "clean up distribution files", "deleted " + file.getPath()); - } - - @Override - public void tearDown() throws Exception { - File dataDir = new File(mActivity.getApplicationInfo().dataDir); - - // Delete mock package from data directory. - File mockPackage = new File(dataDir, MOCK_PACKAGE); - mAsserter.ok(mockPackage.delete(), "clean up mock package", "deleted " + mockPackage.getPath()); - - clearDistributionFromDataData(); - clearDistributionPref(); - - super.tearDown(); - } -} diff --git a/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/testDoorHanger.java b/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/testDoorHanger.java deleted file mode 100644 index 2c3feb3a8..000000000 --- a/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/testDoorHanger.java +++ /dev/null @@ -1,205 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -package org.mozilla.gecko.tests; - -import android.widget.CheckBox; -import android.view.View; -import com.robotium.solo.Condition; -import org.json.JSONArray; -import org.json.JSONException; -import org.json.JSONObject; -import org.mozilla.gecko.Actions; - -/* This test will test if doorhangers are displayed and dismissed - The test will test: - * geolocation doorhangers - sharing and not sharing the location dismisses the doorhanger - * opening a new tab hides the doorhanger - * offline storage permission doorhangers - allowing and not allowing offline storage dismisses the doorhanger - * Password Manager doorhangers - Remember and Not Now options dismiss the doorhanger -*/ -public class testDoorHanger extends BaseTest { - private boolean offlineAllowedByDefault = true; - - public void testDoorHanger() { - String GEO_URL = getAbsoluteUrl(mStringHelper.ROBOCOP_GEOLOCATION_URL); - String BLANK_URL = getAbsoluteUrl(mStringHelper.ROBOCOP_BLANK_PAGE_01_URL); - String OFFLINE_STORAGE_URL = getAbsoluteUrl(mStringHelper.ROBOCOP_OFFLINE_STORAGE_URL); - - blockForGeckoReady(); - - // Test geolocation notification - loadUrlAndWait(GEO_URL); - waitForText(mStringHelper.GEO_MESSAGE); - mAsserter.is(mSolo.searchText(mStringHelper.GEO_MESSAGE), true, "Geolocation doorhanger has been displayed"); - - // Test "Share" button hides the notification - waitForCheckBox(); - mSolo.clickOnCheckBox(0); - mSolo.clickOnButton(mStringHelper.GEO_ALLOW); - waitForTextDismissed(mStringHelper.GEO_MESSAGE); - mAsserter.is(mSolo.searchText(mStringHelper.GEO_MESSAGE), false, "Geolocation doorhanger has been hidden when allowing share"); - - // Re-trigger geolocation notification - loadUrlAndWait(GEO_URL); - waitForText(mStringHelper.GEO_MESSAGE); - - // Test "Don't share" button hides the notification - waitForCheckBox(); - mSolo.clickOnCheckBox(0); - mSolo.clickOnButton(mStringHelper.GEO_DENY); - waitForTextDismissed(mStringHelper.GEO_MESSAGE); - mAsserter.is(mSolo.searchText(mStringHelper.GEO_MESSAGE), false, "Geolocation doorhanger has been hidden when denying share"); - - /* FIXME: disabled on fig - bug 880060 (for some reason this fails because of some raciness) - // Re-trigger geolocation notification - loadUrlAndWait(GEO_URL); - waitForText(GEO_MESSAGE); - - // Add a new tab - addTab(BLANK_URL); - - // Make sure doorhanger is hidden - mAsserter.is(mSolo.searchText(GEO_MESSAGE), false, "Geolocation doorhanger notification is hidden when opening a new tab"); - */ - - // Save offline-allow-by-default preferences first - mActions.getPrefs(new String[] { "offline-apps.allow_by_default" }, - new Actions.PrefHandlerBase() { - @Override // Actions.PrefHandlerBase - public void prefValue(String pref, boolean value) { - mAsserter.is(pref, "offline-apps.allow_by_default", "Expecting correct pref name"); - offlineAllowedByDefault = value; - } - }).waitForFinish(); - - setPreferenceAndWaitForChange("offline-apps.allow_by_default", false); - - // Load offline storage page - loadUrlAndWait(OFFLINE_STORAGE_URL); - waitForText(mStringHelper.OFFLINE_MESSAGE); - - // Test doorhanger dismissed when tapping "Don't share" - waitForCheckBox(); - mSolo.clickOnCheckBox(0); - mSolo.clickOnButton(mStringHelper.OFFLINE_DENY); - waitForTextDismissed(mStringHelper.OFFLINE_MESSAGE); - mAsserter.is(mSolo.searchText(mStringHelper.OFFLINE_MESSAGE), false, "Offline storage doorhanger notification is hidden when denying storage"); - - // Load offline storage page - loadUrlAndWait(OFFLINE_STORAGE_URL); - waitForText(mStringHelper.OFFLINE_MESSAGE); - - // Test doorhanger dismissed when tapping "Allow" and is not displayed again - mSolo.clickOnButton(mStringHelper.OFFLINE_ALLOW); - waitForTextDismissed(mStringHelper.OFFLINE_MESSAGE); - mAsserter.is(mSolo.searchText(mStringHelper.OFFLINE_MESSAGE), false, "Offline storage doorhanger notification is hidden when allowing storage"); - loadUrlAndWait(OFFLINE_STORAGE_URL); - mAsserter.is(mSolo.searchText(mStringHelper.OFFLINE_MESSAGE), false, "Offline storage doorhanger is no longer triggered"); - - // Revert offline setting - setPreferenceAndWaitForChange("offline-apps.allow_by_default", offlineAllowedByDefault); - - // Load new login page - loadUrlAndWait(getAbsoluteUrl(mStringHelper.ROBOCOP_LOGIN_01_URL)); - waitForText(mStringHelper.LOGIN_MESSAGE); - - // Test doorhanger is dismissed when tapping "Remember". - mSolo.clickOnButton(mStringHelper.LOGIN_ALLOW); - waitForTextDismissed(mStringHelper.LOGIN_MESSAGE); - mAsserter.is(mSolo.searchText(mStringHelper.LOGIN_MESSAGE), false, "Login doorhanger notification is hidden when allowing saving password"); - - // Load login page - loadUrlAndWait(getAbsoluteUrl(mStringHelper.ROBOCOP_LOGIN_02_URL)); - waitForText(mStringHelper.LOGIN_MESSAGE); - - // Test doorhanger is dismissed when tapping "Never". - mSolo.clickOnButton(mStringHelper.LOGIN_DENY); - waitForTextDismissed(mStringHelper.LOGIN_MESSAGE); - mAsserter.is(mSolo.searchText(mStringHelper.LOGIN_MESSAGE), false, "Login doorhanger notification is hidden when denying saving password"); - - testPopupBlocking(); - } - - private void testPopupBlocking() { - String POPUP_URL = getAbsoluteUrl(mStringHelper.ROBOCOP_POPUP_URL); - - setPreferenceAndWaitForChange("dom.disable_open_during_load", true); - - // Load page with popup - loadUrlAndWait(POPUP_URL); - waitForText(mStringHelper.POPUP_MESSAGE); - mAsserter.is(mSolo.searchText(mStringHelper.POPUP_MESSAGE), true, "Popup blocker is displayed"); - - // Wait for the popup to be shown. - Actions.EventExpecter tabEventExpecter = mActions.expectGeckoEvent("Tab:Added"); - - waitForCheckBox(); - mSolo.clickOnCheckBox(0); - mSolo.clickOnButton(mStringHelper.POPUP_ALLOW); - waitForTextDismissed(mStringHelper.POPUP_MESSAGE); - mAsserter.is(mSolo.searchText(mStringHelper.POPUP_MESSAGE), false, "Popup blocker is hidden when popup allowed"); - - try { - final JSONObject data = new JSONObject(tabEventExpecter.blockForEventData()); - - // Check to make sure the popup window was opened. - mAsserter.is("data:text/plain;charset=utf-8,a", data.getString("uri"), "Checking popup URL"); - - // Close the popup window. - closeTab(data.getInt("tabID")); - - } catch (JSONException e) { - mAsserter.ok(false, "exception getting event data", e.toString()); - } - tabEventExpecter.unregisterListener(); - - // Load page with popup - loadUrlAndWait(POPUP_URL); - waitForText(mStringHelper.POPUP_MESSAGE); - mAsserter.is(mSolo.searchText(mStringHelper.POPUP_MESSAGE), true, "Popup blocker is displayed"); - - waitForCheckBox(); - mSolo.clickOnCheckBox(0); - mSolo.clickOnButton(mStringHelper.POPUP_DENY); - waitForTextDismissed(mStringHelper.POPUP_MESSAGE); - mAsserter.is(mSolo.searchText(mStringHelper.POPUP_MESSAGE), false, "Popup blocker is hidden when popup denied"); - - // Check that we're on the same page to verify that the popup was not shown. - verifyUrl(POPUP_URL); - - setPreferenceAndWaitForChange("dom.disable_open_during_load", false); - } - - // wait for a CheckBox view that is clickable - private void waitForCheckBox() { - waitForCondition(new Condition() { - @Override - public boolean isSatisfied() { - for (CheckBox view : mSolo.getCurrentViews(CheckBox.class)) { - // checking isClickable alone is not sufficient -- - // intermittent "cannot click" errors persist unless - // additional checks are used - if (view.isClickable() && - view.getVisibility() == View.VISIBLE && - view.getWidth() > 0 && - view.getHeight() > 0) { - return true; - } - } - return false; - } - }, MAX_WAIT_MS); - } - - // wait until the specified text is *not* displayed - private void waitForTextDismissed(final String text) { - waitForCondition(new Condition() { - @Override - public boolean isSatisfied() { - return !mSolo.searchText(text); - } - }, MAX_WAIT_MS); - } -} diff --git a/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/testEventDispatcher.java b/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/testEventDispatcher.java deleted file mode 100644 index ad40459d5..000000000 --- a/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/testEventDispatcher.java +++ /dev/null @@ -1,450 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -package org.mozilla.gecko.tests; - -import static org.mozilla.gecko.tests.helpers.AssertionHelper.*; - -import org.mozilla.gecko.EventDispatcher; -import org.mozilla.gecko.util.BundleEventListener; -import org.mozilla.gecko.util.EventCallback; -import org.mozilla.gecko.util.GeckoEventListener; -import org.mozilla.gecko.util.NativeEventListener; -import org.mozilla.gecko.util.NativeJSObject; -import org.mozilla.gecko.util.ThreadUtils; - -import android.os.Bundle; - -import org.json.JSONArray; -import org.json.JSONException; -import org.json.JSONObject; - -/** - * Tests the proper operation of EventDispatcher, - * including associated NativeJSObject objects. - */ -public class testEventDispatcher extends JavascriptBridgeTest - implements BundleEventListener, GeckoEventListener, NativeEventListener { - - private static final String TEST_JS = "testEventDispatcher.js"; - private static final String GECKO_EVENT = "Robocop:TestGeckoEvent"; - private static final String GECKO_RESPONSE_EVENT = "Robocop:TestGeckoResponse"; - private static final String NATIVE_EVENT = "Robocop:TestNativeEvent"; - private static final String NATIVE_RESPONSE_EVENT = "Robocop:TestNativeResponse"; - private static final String NATIVE_EXCEPTION_EVENT = "Robocop:TestNativeException"; - private static final String UI_EVENT = "Robocop:TestUIEvent"; - private static final String UI_RESPONSE_EVENT = "Robocop:TestUIResponse"; - private static final String BACKGROUND_EVENT = "Robocop:TestBackgroundEvent"; - private static final String BACKGROUND_RESPONSE_EVENT = "Robocop:TestBackgrondResponse"; - - private static final long WAIT_FOR_BUNDLE_EVENT_TIMEOUT_MILLIS = 20000; // 20 seconds - - private NativeJSObject savedMessage; - - private boolean handledGeckoEvent; - private boolean handledNativeEvent; - private boolean handledAsyncEvent; - - @Override - public void setUp() throws Exception { - super.setUp(); - - EventDispatcher.getInstance().registerGeckoThreadListener( - (GeckoEventListener) this, GECKO_EVENT, GECKO_RESPONSE_EVENT); - EventDispatcher.getInstance().registerGeckoThreadListener( - (NativeEventListener) this, - NATIVE_EVENT, NATIVE_RESPONSE_EVENT, NATIVE_EXCEPTION_EVENT); - EventDispatcher.getInstance().registerUiThreadListener( - this, UI_EVENT, UI_RESPONSE_EVENT); - EventDispatcher.getInstance().registerBackgroundThreadListener( - this, BACKGROUND_EVENT, BACKGROUND_RESPONSE_EVENT); - } - - @Override - public void tearDown() throws Exception { - EventDispatcher.getInstance().unregisterGeckoThreadListener( - (GeckoEventListener) this, GECKO_EVENT, GECKO_RESPONSE_EVENT); - EventDispatcher.getInstance().unregisterGeckoThreadListener( - (NativeEventListener) this, - NATIVE_EVENT, NATIVE_RESPONSE_EVENT, NATIVE_EXCEPTION_EVENT); - EventDispatcher.getInstance().unregisterUiThreadListener( - this, UI_EVENT, UI_RESPONSE_EVENT); - EventDispatcher.getInstance().unregisterBackgroundThreadListener( - this, BACKGROUND_EVENT, BACKGROUND_RESPONSE_EVENT); - - super.tearDown(); - } - - private synchronized void waitForAsyncEvent() { - final long startTime = System.nanoTime(); - while (!handledAsyncEvent) { - if (System.nanoTime() - startTime - >= WAIT_FOR_BUNDLE_EVENT_TIMEOUT_MILLIS * 1e6 /* ns per ms */) { - fFail("Should have completed event before timeout"); - } - try { - wait(1000); // Wait for 1 second at a time. - } catch (final InterruptedException e) { - // Attempt waiting again. - } - } - handledAsyncEvent = false; - } - - private synchronized void notifyAsyncEvent() { - handledAsyncEvent = true; - notifyAll(); - } - - public void testEventDispatcher() { - blockForReadyAndLoadJS(TEST_JS); - - getJS().syncCall("send_test_message", GECKO_EVENT); - fAssertTrue("Should have handled Gecko event synchronously", handledGeckoEvent); - - getJS().syncCall("send_message_for_response", GECKO_RESPONSE_EVENT, "success"); - getJS().syncCall("send_message_for_response", GECKO_RESPONSE_EVENT, "error"); - - getJS().syncCall("send_test_message", NATIVE_EVENT); - fAssertTrue("Should have handled native event synchronously", handledNativeEvent); - - getJS().syncCall("send_message_for_response", NATIVE_RESPONSE_EVENT, "success"); - getJS().syncCall("send_message_for_response", NATIVE_RESPONSE_EVENT, "error"); - - getJS().syncCall("send_test_message", NATIVE_EXCEPTION_EVENT); - - getJS().syncCall("send_test_message", UI_EVENT); - waitForAsyncEvent(); - - getJS().syncCall("send_message_for_response", UI_RESPONSE_EVENT, "success"); - waitForAsyncEvent(); - - getJS().syncCall("send_message_for_response", UI_RESPONSE_EVENT, "error"); - waitForAsyncEvent(); - - getJS().syncCall("send_test_message", BACKGROUND_EVENT); - waitForAsyncEvent(); - - getJS().syncCall("send_message_for_response", BACKGROUND_RESPONSE_EVENT, "success"); - waitForAsyncEvent(); - - getJS().syncCall("send_message_for_response", BACKGROUND_RESPONSE_EVENT, "error"); - waitForAsyncEvent(); - - getJS().syncCall("finish_test"); - } - - @Override - public void handleMessage(final String event, final Bundle message, - final EventCallback callback) { - - if (UI_EVENT.equals(event) || UI_RESPONSE_EVENT.equals(event)) { - fAssertTrue("UI event should be on UI thread", ThreadUtils.isOnUiThread()); - - } else if (BACKGROUND_EVENT.equals(event) || BACKGROUND_RESPONSE_EVENT.equals(event)) { - fAssertTrue("Background event should be on background thread", - ThreadUtils.isOnBackgroundThread()); - - } else { - fFail("Event type should be valid: " + event); - } - - if (UI_EVENT.equals(event) || BACKGROUND_EVENT.equals(event)) { - checkBundle(message); - checkBundle(message.getBundle("object")); - - } else if (UI_RESPONSE_EVENT.equals(event) || BACKGROUND_RESPONSE_EVENT.equals(event)) { - final String response = message.getString("response"); - if ("success".equals(response)) { - callback.sendSuccess(response); - } else if ("error".equals(response)) { - callback.sendError(response); - } else { - fFail("Response type should be valid: " + response); - } - - } else { - fFail("Event type should be valid: " + event); - } - - notifyAsyncEvent(); - } - - @Override - public void handleMessage(final String event, final JSONObject message) { - ThreadUtils.assertOnGeckoThread(); - - try { - if (GECKO_EVENT.equals(event)) { - checkJSONObject(message); - checkJSONObject(message.getJSONObject("object")); - handledGeckoEvent = true; - - } else if (GECKO_RESPONSE_EVENT.equals(event)) { - final String response = message.getString("response"); - if ("success".equals(response)) { - EventDispatcher.sendResponse(message, response); - } else if ("error".equals(response)) { - EventDispatcher.sendError(message, response); - } else { - fFail("Response type should be valid: " + response); - } - - } else { - fFail("Event type should be valid: " + event); - } - } catch (final JSONException e) { - fFail(e.toString()); - } - } - - @Override - public void handleMessage(final String event, final NativeJSObject message, - final EventCallback callback) { - ThreadUtils.assertOnGeckoThread(); - - if (NATIVE_EVENT.equals(event)) { - checkNativeJSObject(message); - checkNativeJSObject(message.getObject("object")); - fAssertNotSame("optObject returns existent value", - null, message.optObject("object", null)); - fAssertSame("optObject returns fallback value if nonexistent", - null, message.optObject("nonexistent_object", null)); - - final NativeJSObject[] objectArray = message.getObjectArray("objectArray"); - fAssertNotNull("Native object array should exist", objectArray); - fAssertEquals("Native object array has correct length", 2, objectArray.length); - fAssertSame("Native object array index 0 has correct value", null, objectArray[0]); - fAssertNotSame("Native object array index 1 has correct value", null, objectArray[1]); - checkNativeJSObject(objectArray[1]); - fAssertNotSame("optObjectArray returns existent value", - null, message.optObjectArray("objectArray", null)); - fAssertSame("optObjectArray returns fallback value if nonexistent", - null, message.optObjectArray("nonexistent_objectArray", null)); - - final Bundle bundle = message.toBundle(); - checkBundle(bundle); - checkBundle(bundle.getBundle("object")); - fAssertNotSame("optBundle returns property value if it exists", - null, message.optBundle("object", null)); - fAssertSame("optBundle returns fallback value if property does not exist", - null, message.optBundle("nonexistent_object", null)); - - final Bundle[] bundleArray = message.getBundleArray("objectArray"); - fAssertNotNull("Native bundle array should exist", bundleArray); - fAssertEquals("Native bundle array has correct length", 2, bundleArray.length); - fAssertSame("Native bundle array index 0 has correct value", null, bundleArray[0]); - fAssertNotSame("Native bundle array index 1 has correct value", null, bundleArray[1]); - checkBundle(bundleArray[1]); - fAssertNotSame("optBundleArray returns existent value", - null, message.optBundleArray("objectArray", null)); - fAssertSame("optBundleArray returns fallback value if nonexistent", - null, message.optBundleArray("nonexistent_objectArray", null)); - - handledNativeEvent = true; - - } else if (NATIVE_RESPONSE_EVENT.equals(event)) { - final String response = message.getString("response"); - if ("success".equals(response)) { - callback.sendSuccess(response); - } else if ("error".equals(response)) { - callback.sendError(response); - } else { - fFail("Response type should be valid: " + response); - } - - // Save this message for post-disposal check. - savedMessage = message; - - } else if (NATIVE_EXCEPTION_EVENT.equals(event)) { - // Make sure we throw the right exceptions. - try { - message.getString(null); - fFail("null property name should throw IllegalArgumentException"); - } catch (final IllegalArgumentException e) { - } - - try { - message.getString("nonexistent_string"); - fFail("Nonexistent property name should throw InvalidPropertyException"); - } catch (final NativeJSObject.InvalidPropertyException e) { - } - - try { - message.getString("int"); - fFail("Wrong property type should throw InvalidPropertyException"); - } catch (final NativeJSObject.InvalidPropertyException e) { - } - - fAssertNotSame("Should have saved a message", null, savedMessage); - try { - savedMessage.toString(); - fFail("Using NativeJSContainer should throw after disposal"); - } catch (final NullPointerException e) { - } - - // Save this test for last; make sure EventDispatcher catches InvalidPropertyException. - message.getString("nonexistent_string"); - fFail("EventDispatcher should catch InvalidPropertyException"); - - } else { - fFail("Event type should be valid: " + event); - } - } - - private void checkBundle(final Bundle bundle) { - fAssertEquals("Bundle boolean has correct value", true, bundle.getBoolean("boolean")); - fAssertEquals("Bundle int has correct value", 1, bundle.getInt("int")); - fAssertEquals("Bundle double has correct value", 0.5, bundle.getDouble("double")); - fAssertEquals("Bundle string has correct value", "foo", bundle.getString("string")); - - final boolean[] booleanArray = bundle.getBooleanArray("booleanArray"); - fAssertNotNull("Bundle boolean array should exist", booleanArray); - fAssertEquals("Bundle boolean array has correct length", 2, booleanArray.length); - fAssertEquals("Bundle boolean array index 0 has correct value", false, booleanArray[0]); - fAssertEquals("Bundle boolean array index 1 has correct value", true, booleanArray[1]); - - final int[] intArray = bundle.getIntArray("intArray"); - fAssertNotNull("Bundle int array should exist", intArray); - fAssertEquals("Bundle int array has correct length", 2, intArray.length); - fAssertEquals("Bundle int array index 0 has correct value", 2, intArray[0]); - fAssertEquals("Bundle int array index 1 has correct value", 3, intArray[1]); - - final double[] doubleArray = bundle.getDoubleArray("doubleArray"); - fAssertNotNull("Bundle double array should exist", doubleArray); - fAssertEquals("Bundle double array has correct length", 2, doubleArray.length); - fAssertEquals("Bundle double array index 0 has correct value", 1.5, doubleArray[0]); - fAssertEquals("Bundle double array index 1 has correct value", 2.5, doubleArray[1]); - - final String[] stringArray = bundle.getStringArray("stringArray"); - fAssertNotNull("Bundle string array should exist", stringArray); - fAssertEquals("Bundle string array has correct length", 2, stringArray.length); - fAssertEquals("Bundle string array index 0 has correct value", "bar", stringArray[0]); - fAssertEquals("Bundle string array index 1 has correct value", "baz", stringArray[1]); - } - - private void checkJSONObject(final JSONObject object) throws JSONException { - fAssertEquals("JSON boolean has correct value", true, object.getBoolean("boolean")); - fAssertEquals("JSON int has correct value", 1, object.getInt("int")); - fAssertEquals("JSON double has correct value", 0.5, object.getDouble("double")); - fAssertEquals("JSON string has correct value", "foo", object.getString("string")); - - final JSONArray booleanArray = object.getJSONArray("booleanArray"); - fAssertNotNull("JSON boolean array should exist", booleanArray); - fAssertEquals("JSON boolean array has correct length", 2, booleanArray.length()); - fAssertEquals("JSON boolean array index 0 has correct value", - false, booleanArray.getBoolean(0)); - fAssertEquals("JSON boolean array index 1 has correct value", - true, booleanArray.getBoolean(1)); - - final JSONArray intArray = object.getJSONArray("intArray"); - fAssertNotNull("JSON int array should exist", intArray); - fAssertEquals("JSON int array has correct length", 2, intArray.length()); - fAssertEquals("JSON int array index 0 has correct value", - 2, intArray.getInt(0)); - fAssertEquals("JSON int array index 1 has correct value", - 3, intArray.getInt(1)); - - final JSONArray doubleArray = object.getJSONArray("doubleArray"); - fAssertNotNull("JSON double array should exist", doubleArray); - fAssertEquals("JSON double array has correct length", 2, doubleArray.length()); - fAssertEquals("JSON double array index 0 has correct value", - 1.5, doubleArray.getDouble(0)); - fAssertEquals("JSON double array index 1 has correct value", - 2.5, doubleArray.getDouble(1)); - - final JSONArray stringArray = object.getJSONArray("stringArray"); - fAssertNotNull("JSON string array should exist", stringArray); - fAssertEquals("JSON string array has correct length", 2, stringArray.length()); - fAssertEquals("JSON string array index 0 has correct value", - "bar", stringArray.getString(0)); - fAssertEquals("JSON string array index 1 has correct value", - "baz", stringArray.getString(1)); - } - - private void checkNativeJSObject(final NativeJSObject object) { - fAssertEquals("Native boolean has correct value", - true, object.getBoolean("boolean")); - fAssertEquals("optBoolean returns existent value", - true, object.optBoolean("boolean", false)); - fAssertEquals("optBoolean returns fallback value if nonexistent", - false, object.optBoolean("nonexistent_boolean", false)); - - fAssertEquals("Native int has correct value", - 1, object.getInt("int")); - fAssertEquals("optInt returns existent value", - 1, object.optInt("int", 0)); - fAssertEquals("optInt returns fallback value if nonexistent", - 0, object.optInt("nonexistent_int", 0)); - - fAssertEquals("Native double has correct value", - 0.5, object.getDouble("double")); - fAssertEquals("optDouble returns existent value", - 0.5, object.optDouble("double", -0.5)); - fAssertEquals("optDouble returns fallback value if nonexistent", - -0.5, object.optDouble("nonexistent_double", -0.5)); - - fAssertEquals("Native string has correct value", - "foo", object.getString("string")); - fAssertEquals("optDouble returns existent value", - "foo", object.optString("string", "bar")); - fAssertEquals("optDouble returns fallback value if nonexistent", - "bar", object.optString("nonexistent_string", "bar")); - - final boolean[] booleanArray = object.getBooleanArray("booleanArray"); - fAssertNotNull("Native boolean array should exist", booleanArray); - fAssertEquals("Native boolean array has correct length", 2, booleanArray.length); - fAssertEquals("Native boolean array index 0 has correct value", false, booleanArray[0]); - fAssertEquals("Native boolean array index 1 has correct value", true, booleanArray[1]); - fAssertNotSame("optBooleanArray returns existent value", - null, object.optBooleanArray("booleanArray", null)); - fAssertSame("optBooleanArray returns fallback value if nonexistent", - null, object.optBooleanArray("nonexistent_booleanArray", null)); - - final int[] intArray = object.getIntArray("intArray"); - fAssertNotNull("Native int array should exist", intArray); - fAssertEquals("Native int array has correct length", 2, intArray.length); - fAssertEquals("Native int array index 0 has correct value", 2, intArray[0]); - fAssertEquals("Native int array index 1 has correct value", 3, intArray[1]); - fAssertNotSame("optIntArray returns existent value", - null, object.optIntArray("intArray", null)); - fAssertSame("optIntArray returns fallback value if nonexistent", - null, object.optIntArray("nonexistent_intArray", null)); - - final double[] doubleArray = object.getDoubleArray("doubleArray"); - fAssertNotNull("Native double array should exist", doubleArray); - fAssertEquals("Native double array has correct length", 2, doubleArray.length); - fAssertEquals("Native double array index 0 has correct value", 1.5, doubleArray[0]); - fAssertEquals("Native double array index 1 has correct value", 2.5, doubleArray[1]); - fAssertNotSame("optDoubleArray returns existent value", - null, object.optDoubleArray("doubleArray", null)); - fAssertSame("optDoubleArray returns fallback value if nonexistent", - null, object.optDoubleArray("nonexistent_doubleArray", null)); - - final String[] stringArray = object.getStringArray("stringArray"); - fAssertNotNull("Native string array should exist", stringArray); - fAssertEquals("Native string array has correct length", 2, stringArray.length); - fAssertEquals("Native string array index 0 has correct value", "bar", stringArray[0]); - fAssertEquals("Native string array index 1 has correct value", "baz", stringArray[1]); - fAssertNotSame("optStringArray returns existent value", - null, object.optStringArray("stringArray", null)); - fAssertSame("optStringArray returns fallback value if nonexistent", - null, object.optStringArray("nonexistent_stringArray", null)); - - fAssertEquals("Native has(null) is false", false, object.has("null")); - fAssertEquals("Native has(emptyString) is true", true, object.has("emptyString")); - - fAssertEquals("Native optBoolean returns fallback value if null", - true, object.optBoolean("null", true)); - fAssertEquals("Native optInt returns fallback value if null", - 42, object.optInt("null", 42)); - fAssertEquals("Native optDouble returns fallback value if null", - -3.1415926535, object.optDouble("null", -3.1415926535)); - fAssertEquals("Native optString returns fallback value if null", - "baz", object.optString("null", "baz")); - - fAssertNotEquals("Native optString does not return fallback value if emptyString", - "baz", object.optString("emptyString", "baz")); - } -} diff --git a/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/testFilePicker.java b/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/testFilePicker.java deleted file mode 100644 index c613eca8f..000000000 --- a/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/testFilePicker.java +++ /dev/null @@ -1,52 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this file, - * You can obtain one at http://mozilla.org/MPL/2.0/. */ - -package org.mozilla.gecko.tests; - -import static org.mozilla.gecko.tests.helpers.AssertionHelper.fFail; - -import org.mozilla.gecko.EventDispatcher; -import org.mozilla.gecko.GeckoApp; -import org.mozilla.gecko.GeckoAppShell; -import org.mozilla.gecko.util.GeckoEventListener; - -import org.json.JSONException; -import org.json.JSONObject; - -public class testFilePicker extends JavascriptTest implements GeckoEventListener { - private static final String TEST_FILENAME = "/mnt/sdcard/my-favorite-martian.png"; - - public testFilePicker() { - super("testFilePicker.js"); - } - - @Override - public void handleMessage(String event, final JSONObject message) { - // We handle the FilePicker message here so we can send back hard coded file information. We - // don't want to try to emulate "picking" a file using the Android intent chooser. - if (event.equals("FilePicker:Show")) { - try { - message.put("file", TEST_FILENAME); - } catch (JSONException ex) { - fFail("Can't add filename to message " + TEST_FILENAME); - } - - mActions.sendGeckoEvent("FilePicker:Result", message.toString()); - } - } - - @Override - public void setUp() throws Exception { - super.setUp(); - - GeckoApp.getEventDispatcher().registerGeckoThreadListener(this, "FilePicker:Show"); - } - - @Override - public void tearDown() throws Exception { - super.tearDown(); - - GeckoApp.getEventDispatcher().unregisterGeckoThreadListener(this, "FilePicker:Show"); - } -} diff --git a/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/testFilterOpenTab.java b/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/testFilterOpenTab.java deleted file mode 100644 index 3c57b864a..000000000 --- a/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/testFilterOpenTab.java +++ /dev/null @@ -1,133 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -package org.mozilla.gecko.tests; - -import java.util.ArrayList; -import java.util.List; -import java.util.concurrent.Callable; - -import org.mozilla.gecko.GeckoProfile; -import org.mozilla.gecko.PrivateTab; -import org.mozilla.gecko.Tab; -import org.mozilla.gecko.db.BrowserContract; -import org.mozilla.gecko.db.TabsProvider; - -import android.content.ContentProvider; -import android.content.Context; -import android.database.Cursor; - -/** - * Tests that local tabs are filtered prior to upload. - * - create a set of tabs and persists them through TabsAccessor. - * - verifies that tabs are filtered by querying. - */ -public class testFilterOpenTab extends ContentProviderTest { - private static final String[] TABS_PROJECTION_COLUMNS = new String[] { - BrowserContract.Tabs.TITLE, - BrowserContract.Tabs.URL, - BrowserContract.Clients.GUID, - BrowserContract.Clients.NAME - }; - - private static final String LOCAL_TABS_SELECTION = BrowserContract.Tabs.CLIENT_GUID + " IS NULL"; - - /** - * Factory function that makes new ContentProvider instances. - *

- * We want a fresh provider each test, so this should be invoked in - * setUp before each individual test. - */ - protected static Callable sTabProviderCallable = new Callable() { - @Override - public ContentProvider call() { - return new TabsProvider(); - } - }; - - private Cursor getTabsFromLocalClient() throws Exception { - return mProvider.query(BrowserContract.Tabs.CONTENT_URI, - TABS_PROJECTION_COLUMNS, - LOCAL_TABS_SELECTION, - null, - null); - } - - private Tab createTab(int id, String url, boolean external, int parentId, String title) { - return new Tab((Context) getActivity(), id, url, external, parentId, title); - } - - private Tab createPrivateTab(int id, String url, boolean external, int parentId, String title) { - return new PrivateTab((Context) getActivity(), id, url, external, parentId, title); - } - - @Override - public void setUp() throws Exception { - super.setUp(sTabProviderCallable, BrowserContract.TABS_AUTHORITY, "tabs.db"); - mTests.add(new TestInsertLocalTabs()); - } - - public void testFilterOpenTab() throws Exception { - blockForGeckoReady(); - - for (int i = 0; i < mTests.size(); i++) { - Runnable test = mTests.get(i); - - setTestName(test.getClass().getSimpleName()); - test.run(); - } - } - - private class TestInsertLocalTabs extends TestCase { - @Override - public void test() throws Exception { - final String TITLE1 = "Google"; - final String URL1 = "http://www.google.com/"; - final String TITLE2 = "Mozilla Start Page"; - final String URL2 = "about:home"; - final String TITLE3 = "Chrome Weave URL"; - final String URL3 = "chrome://weave/"; - final String TITLE4 = "What You Cache Is What You Get"; - final String URL4 = "wyciwyg://1/test.com"; - final String TITLE5 = "Root Folder"; - final String URL5 = "file:///"; - - // Create a list of local tabs. - List tabs = new ArrayList(6); - Tab tab1 = createTab(1, URL1, false, 0, TITLE1); - Tab tab2 = createTab(2, URL2, false, 0, TITLE2); - Tab tab3 = createTab(3, URL3, false, 0, TITLE3); - Tab tab4 = createTab(4, URL4, false, 0, TITLE4); - Tab tab5 = createTab(5, URL5, false, 0, TITLE5); - Tab tab6 = createPrivateTab(6, URL1, false, 0, TITLE1); - tabs.add(tab1); - tabs.add(tab2); - tabs.add(tab3); - tabs.add(tab4); - tabs.add(tab5); - tabs.add(tab6); - - // Persist the created tabs. Normally, you should be careful that you get a profile on the - // original thread, and do the work in a background one, but for testing we don't. - final DatabaseHelper helper = new DatabaseHelper(getActivity(), mAsserter); - helper.getProfileDB().getTabsAccessor().persistLocalTabs(mResolver, tabs); - - // Get the persisted tab and check if urls are filtered. - Cursor c = getTabsFromLocalClient(); - assertCountIsAndClose(c, 1, 1 + " tabs entries found"); - } - } - - /** - * Assert that the provided cursor has the expected number of rows, - * closing the cursor afterwards. - */ - private void assertCountIsAndClose(Cursor c, int expectedCount, String message) { - try { - mAsserter.is(c.getCount(), expectedCount, message); - } finally { - c.close(); - } - } -} diff --git a/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/testFindInPage.java b/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/testFindInPage.java deleted file mode 100644 index 2797fdf5b..000000000 --- a/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/testFindInPage.java +++ /dev/null @@ -1,107 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -package org.mozilla.gecko.tests; - -import static org.mozilla.gecko.tests.helpers.AssertionHelper.fFail; - -import org.mozilla.gecko.Actions; -import org.mozilla.gecko.Element; -import org.mozilla.gecko.R; - -import org.mozilla.gecko.EventDispatcher; -import org.mozilla.gecko.util.GeckoEventListener; - -import org.json.JSONObject; - -import com.robotium.solo.Condition; - -public class testFindInPage extends JavascriptTest implements GeckoEventListener { - private static final int WAIT_FOR_CONDITION_MS = 3000; - - protected Element next, close; - - public testFindInPage() { - super("testFindInPage.js"); - } - - @Override - public void handleMessage(String event, final JSONObject message) { - if (event.equals("Test:FindInPage")) { - try { - final String text = message.getString("text"); - final int nrOfMatches = Integer.parseInt(message.getString("nrOfMatches")); - findText(text, nrOfMatches); - } catch (Exception e) { - fFail("Can't extract find query from JSON"); - } - } - - if (event.equals("Test:CloseFindInPage")) { - try { - close.click(); - } catch (Exception e) { - fFail("FindInPage prompt not opened"); - } - } - } - - @Override - public void setUp() throws Exception { - super.setUp(); - - EventDispatcher.getInstance().registerGeckoThreadListener(this, - "Test:FindInPage", - "Test:CloseFindInPage"); - } - - @Override - public void tearDown() throws Exception { - super.tearDown(); - - EventDispatcher.getInstance().unregisterGeckoThreadListener(this, - "Test:FindInPage", - "Test:CloseFindInPage"); - } - - public void findText(String text, int nrOfMatches){ - selectMenuItem(mStringHelper.FIND_IN_PAGE_LABEL); - close = mDriver.findElement(getActivity(), R.id.find_close); - boolean success = waitForCondition ( new Condition() { - @Override - public boolean isSatisfied() { - next = mDriver.findElement(getActivity(), R.id.find_next); - if (next != null) { - return true; - } else { - return false; - } - } - }, WAIT_FOR_CONDITION_MS); - mAsserter.ok(success, "Looking for the next search match button in the Find in Page UI", "Found the next match button"); - - // TODO: Find a better way to wait and then enter the text - // Without the sleep this seems to work but the actions are not updated in the UI - mSolo.sleep(500); - - mActions.sendKeys(text); - mActions.sendSpecialKey(Actions.SpecialKey.ENTER); - - // Advance a few matches to scroll the page - for (int i=1;i < nrOfMatches;i++) { - success = waitForCondition ( new Condition() { - @Override - public boolean isSatisfied() { - if (next.click()) { - return true; - } else { - return false; - } - } - }, WAIT_FOR_CONDITION_MS); - mSolo.sleep(500); // TODO: Find a better way to wait here because waitForCondition is not enough - mAsserter.ok(success, "Checking if the next button was clicked", "button was clicked"); - } - } -} diff --git a/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/testFlingCorrectness.java b/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/testFlingCorrectness.java deleted file mode 100644 index e173a8c16..000000000 --- a/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/testFlingCorrectness.java +++ /dev/null @@ -1,52 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -package org.mozilla.gecko.tests; - -import org.mozilla.gecko.Actions; -import org.mozilla.gecko.PaintedSurface; - -/** - * Basic fling correctness test. - * - Loads a page and verifies it draws - * - Drags page upwards by 200 pixels to get ready for a fling - * - Fling the page downwards so we get back to the top and verify. - */ -public class testFlingCorrectness extends PixelTest { - public void testFlingCorrectness() { - String url = getAbsoluteUrl(mStringHelper.ROBOCOP_BOXES_URL); - - MotionEventHelper meh = new MotionEventHelper(getInstrumentation(), mDriver.getGeckoLeft(), mDriver.getGeckoTop()); - - blockForGeckoReady(); - - // load page and check we're at 0,0 - loadAndVerifyBoxes(url); - - // drag page upwards by 200 pixels (use two drags instead of one in case - // the screen size is small) - Actions.RepeatedEventExpecter paintExpecter = mActions.expectPaint(); - meh.dragSync(10, 150, 10, 50); - meh.dragSync(10, 150, 10, 50); - PaintedSurface painted = waitForPaint(paintExpecter); - paintExpecter.unregisterListener(); - try { - checkScrollWithBoxes(painted, 0, 200); - } finally { - painted.close(); - } - - // now fling page downwards using a 100-pixel drag but a velocity of 15px/sec, so that - // we scroll the full 200 pixels back to the top of the page - paintExpecter = mActions.expectPaint(); - meh.flingSync(10, 50, 10, 150, 15); - painted = waitForPaint(paintExpecter); - paintExpecter.unregisterListener(); - try { - checkScrollWithBoxes(painted, 0, 0); - } finally { - painted.close(); - } - } -} diff --git a/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/testFormHistory.java b/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/testFormHistory.java deleted file mode 100644 index 40968b9be..000000000 --- a/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/testFormHistory.java +++ /dev/null @@ -1,104 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -package org.mozilla.gecko.tests; - -import java.io.File; - -import org.mozilla.gecko.db.BrowserContract.FormHistory; - -import android.content.ContentResolver; -import android.content.ContentValues; -import android.content.Context; -import android.net.Uri; - -/** - * A basic form history contentprovider test. - * - inserts an element in form history when it is not yet set up - * - inserts an element in form history - * - updates an element in form history - * - deletes an element in form history - */ -public class testFormHistory extends BaseTest { - private static final String DB_NAME = "formhistory.sqlite"; - - public void testFormHistory() { - Context context = (Context)getActivity(); - ContentResolver cr = context.getContentResolver(); - ContentValues[] cvs = new ContentValues[1]; - cvs[0] = new ContentValues(); - - blockForGeckoReady(); - - Uri formHistoryUri; - Uri insertUri; - Uri expectedUri; - int numUpdated; - int numDeleted; - - cvs[0].put("fieldname", "fieldname"); - cvs[0].put("value", "value"); - cvs[0].put("timesUsed", "0"); - cvs[0].put("guid", "guid"); - - // Attempt to insert into the db - formHistoryUri = FormHistory.CONTENT_URI; - Uri.Builder builder = formHistoryUri.buildUpon(); - formHistoryUri = builder.appendQueryParameter("profilePath", mProfile).build(); - - insertUri = cr.insert(formHistoryUri, cvs[0]); - expectedUri = formHistoryUri.buildUpon().appendPath("1").build(); - mAsserter.is(expectedUri.toString(), insertUri.toString(), "Insert returned correct uri"); - SqliteCompare(DB_NAME, "SELECT * FROM moz_formhistory", cvs); - - cvs[0].put("fieldname", "fieldname2"); - cvs[0].putNull("guid"); - - numUpdated = cr.update(formHistoryUri, cvs[0], null, null); - mAsserter.is(1, numUpdated, "Correct number updated"); - SqliteCompare(DB_NAME, "SELECT * FROM moz_formhistory", cvs); - - numDeleted = cr.delete(formHistoryUri, null, null); - mAsserter.is(1, numDeleted, "Correct number deleted"); - cvs = new ContentValues[0]; - SqliteCompare(DB_NAME, "SELECT * FROM moz_formhistory", cvs); - - cvs = new ContentValues[1]; - cvs[0] = new ContentValues(); - cvs[0].put("fieldname", "fieldname"); - cvs[0].put("value", "value"); - cvs[0].put("timesUsed", "0"); - cvs[0].putNull("guid"); - - insertUri = cr.insert(formHistoryUri, cvs[0]); - expectedUri = formHistoryUri.buildUpon().appendPath("1").build(); - mAsserter.is(expectedUri.toString(), insertUri.toString(), "Insert returned correct uri"); - SqliteCompare(DB_NAME, "SELECT * FROM moz_formhistory", cvs); - - cvs[0].put("guid", "guid"); - - numUpdated = cr.update(formHistoryUri, cvs[0], null, null); - mAsserter.is(1, numUpdated, "Correct number updated"); - SqliteCompare(DB_NAME, "SELECT * FROM moz_formhistory", cvs); - - numDeleted = cr.delete(formHistoryUri, null, null); - mAsserter.is(1, numDeleted, "Correct number deleted"); - cvs = new ContentValues[0]; - SqliteCompare(DB_NAME, "SELECT * FROM moz_formhistory", cvs); - } - - @Override - public void tearDown() throws Exception { - // remove the entire signons.sqlite file - File profile = new File(mProfile); - File db = new File(profile, "formhistory.sqlite"); - if (db.delete()) { - mAsserter.dumpLog("tearDown deleted "+db.toString()); - } else { - mAsserter.dumpLog("tearDown did not delete "+db.toString()); - } - - super.tearDown(); - } -} diff --git a/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/testGeckoProfile.java b/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/testGeckoProfile.java deleted file mode 100644 index eb9a705be..000000000 --- a/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/testGeckoProfile.java +++ /dev/null @@ -1,295 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -package org.mozilla.gecko.tests; - -import java.io.File; -import java.util.Enumeration; -import java.util.Hashtable; - -import org.mozilla.gecko.GeckoApp; -import org.mozilla.gecko.GeckoProfile; -import org.mozilla.gecko.GeckoProfileDirectories; -import org.mozilla.gecko.GeckoSharedPrefs; -import org.mozilla.gecko.util.INIParser; -import org.mozilla.gecko.util.INISection; - -import android.content.Context; -import android.text.TextUtils; - -/** - * This patch tests GeckoProfile. It has unit tests for basic getting and removing of profiles, as well as - * some guest mode tests. It does not test locking and unlocking profiles yet. It does not test the file management in GeckoProfile. - */ - -public class testGeckoProfile extends PixelTest { - private final String TEST_PROFILE_NAME = "testProfile"; - private File mozDir; - public void testGeckoProfile() { - blockForGeckoReady(); - - try { - mozDir = GeckoProfileDirectories.getMozillaDirectory(getActivity()); - } catch(Exception ex) { - // If we can't get the moz dir, something is wrong. Just fail quickly. - mAsserter.ok(false, "Couldn't get moz dir", ex.toString()); - return; - } - - checkProfileCreationDeletion(); - checkGuestProfile(); - } - - // This getter just passes an activity. Passing null should throw. - private void checkDefaultGetter() { - // "Default" is a custom profile set up by the test harness. - mAsserter.info("Test using the test profile", GeckoProfile.CUSTOM_PROFILE); - GeckoProfile profile = GeckoProfile.get(getActivity()); - verifyProfile(profile, GeckoProfile.CUSTOM_PROFILE, ((GeckoApp) getActivity()).getProfile().getDir(), true); - - try { - profile = GeckoProfile.get(null); - mAsserter.ok(false, "Passing a null context should throw", profile.toString()); - } catch(Exception ex) { - mAsserter.ok(true, "Passing a null context should throw", ex.toString()); - } - } - - // Test get(Context, String) methods - private void checkNamedGetter(String name) { - mAsserter.info("Test using a named profile", name); - GeckoProfile profile = GeckoProfile.get(getActivity(), name); - if (name != null) { - verifyProfile(profile, name, findDir(name), false); - removeProfile(profile, true); - } else { - // Passing in null for a profile name, should get you the default - File defaultProfile = ((GeckoApp) getActivity()).getProfile().getDir(); - verifyProfile(profile, GeckoProfile.CUSTOM_PROFILE, defaultProfile, true); - } - } - - // Test get(Context, String, String) methods - private void checkNameAndPathGetter(String name, boolean createBefore) { - if (name == null) { - checkNameAndPathGetter(name, null, createBefore); - } else { - checkNameAndPathGetter(name, name + "_FORCED_DIR", createBefore); - } - } - - // Test get(Context, String, String) methods - private void checkNameAndPathGetter(String name, String path, boolean createBefore) { - mAsserter.info("Test using a named profile and path", name + ", " + path); - checkNameAndDirGetter(name, /* useFile */ false, path, /* file */ null, createBefore); - } - - private void checkNameAndFileGetter(String name, boolean createBefore) { - if (name == null) { - checkNameAndFileGetter(name, null, createBefore); - } else { - checkNameAndFileGetter(name, new File(mozDir, name + "_FORCED_DIR"), createBefore); - } - } - - private void checkNameAndFileGetter(String name, File f, boolean createBefore) { - mAsserter.info("Test using a named profile and File", name + ", " + f); - checkNameAndDirGetter(name, /* useFile */ true, /* path */ null, f, createBefore); - } - - private void checkNameAndDirGetter(final String name, final boolean useFile, - String path, final File file, - final boolean createBefore) { - final File f; - if (useFile) { - f = file; - } else if (!TextUtils.isEmpty(path)) { - f = new File(mozDir, path); - path = f.getAbsolutePath(); - } else { - f = null; - } - - if (f != null && createBefore) { - // For some tests we create explicitly beforehand - f.mkdir(); - } - - final File testProfileDir = ((GeckoApp) getActivity()).getProfile().getDir(); - final String expectedName = name != null ? name : GeckoProfile.CUSTOM_PROFILE; - - final GeckoProfile profile; - if (useFile) { - profile = GeckoProfile.get(getActivity(), name, file); - } else { - profile = GeckoProfile.get(getActivity(), name, path); - } - - if (name != null || f != null) { - // GeckoProfile will create a directory and add an ini section if f is null - // here. Therefore, when f is null, shouldHaveFound is false for the - // verifyProfile call, and inProfileIni is true for the removeProfile call. - verifyProfile(profile, expectedName, f, f != null); - removeProfile(profile, f == null); - if (name == null) { - // A side effect of calling GeckoProfile.get with null name is it changes - // the test profile's directory to the new directory. Restore it back. - GeckoProfile.get(getActivity(), null, testProfileDir); - mAsserter.is(GeckoProfile.get(getActivity()).getDir(), testProfileDir, - "Test profile should be restored"); - } - } else { - // Passing in null for a profile name and path, should get you the default - verifyProfile(profile, expectedName, testProfileDir, true); - } - } - - private void checkProfileCreationDeletion() { - // Test - checkDefaultGetter(); - - int index = 0; - checkNamedGetter(TEST_PROFILE_NAME + (index++)); // 0 - checkNamedGetter(null); - - // name and path - checkNameAndPathGetter(TEST_PROFILE_NAME + (index++), true); - checkNameAndPathGetter(TEST_PROFILE_NAME + (index++), false); - checkNameAndPathGetter(null, false); - // null name and path - checkNameAndPathGetter(null, TEST_PROFILE_NAME + (index++) + "_FORCED_DIR", true); - checkNameAndPathGetter(null, TEST_PROFILE_NAME + (index++) + "_FORCED_DIR", false); - // name and null path - checkNameAndPathGetter(TEST_PROFILE_NAME + (index++), null, false); - checkNameAndPathGetter(TEST_PROFILE_NAME + (index++), "", false); - // null name and null path - checkNameAndPathGetter(null, null, false); - checkNameAndPathGetter(null, "", false); - - // name and path - checkNameAndFileGetter(TEST_PROFILE_NAME + (index++), true); - checkNameAndFileGetter(TEST_PROFILE_NAME + (index++), false); - checkNameAndFileGetter(null, false); - // null name and path - checkNameAndFileGetter(null, new File(mozDir, TEST_PROFILE_NAME + (index++) + "_FORCED_DIR"), true); - checkNameAndFileGetter(null, new File(mozDir, TEST_PROFILE_NAME + (index++) + "_FORCED_DIR"), false); - // name and null path - checkNameAndFileGetter(TEST_PROFILE_NAME + (index++), null, false); - // null name and null path - checkNameAndFileGetter(null, null, false); - } - - // Tests of Guest profile methods - private void checkGuestProfile() { - final File testProfileDir = ((GeckoApp) getActivity()).getProfile().getDir(); - - mAsserter.info("Test getting a guest profile", ""); - GeckoProfile profile = GeckoProfile.getGuestProfile(getActivity()); - verifyProfile(profile, GeckoProfile.CUSTOM_PROFILE, getActivity().getFileStreamPath("guest"), true); - mAsserter.ok(profile.inGuestMode(), "Profile is in guest mode", profile.getName()); - - final File dir = profile.getDir(); - mAsserter.info("Test deleting a guest profile", ""); - mAsserter.ok(GeckoProfile.removeProfile(getActivity(), profile), "Cleaned up unlocked guest profile", profile.getName()); - mAsserter.ok(!dir.exists(), "Guest dir was deleted", dir.toString()); - - // Restore test profile directory, which was changed in the last GeckoProfile.get call. - GeckoProfile.get(getActivity(), null, testProfileDir); - mAsserter.is(GeckoProfile.get(getActivity()).getDir(), testProfileDir, - "Test profile should be restored"); - } - - // Runs generic tests on a profile to make sure it looks correct - private void verifyProfile(GeckoProfile profile, String name, File requestedDir, boolean shouldHaveFound) { - mAsserter.is(profile.getName(), name, "Profile name is correct"); - - File dir = null; - if (!shouldHaveFound) { - mAsserter.is(findDir(name), null, "Dir with name doesn't exist yet"); - - dir = profile.getDir(); - mAsserter.isnot(requestedDir, dir, "Profile should not have used expectedDir"); - - // The used dir should be based on the name passed in. - requestedDir = findDir(name); - } else { - dir = profile.getDir(); - } - - mAsserter.is(dir, requestedDir, "Profile dir is correct"); - mAsserter.ok(dir.exists(), "Profile dir exists after getting it", dir.toString()); - } - - // Tries to find a profile in profiles.ini. Makes sure its name and path match what is expected - private void findInProfilesIni(final String name, final File dir, final boolean shouldFind) { - final File mozDir; - try { - mozDir = GeckoProfileDirectories.getMozillaDirectory(getActivity()); - } catch(Exception ex) { - mAsserter.ok(false, "Couldn't get moz dir", ex.toString()); - return; - } - - final INIParser parser = GeckoProfileDirectories.getProfilesINI(mozDir); - final Hashtable sections = parser.getSections(); - - boolean found = false; - for (Enumeration e = sections.elements(); e.hasMoreElements();) { - final INISection section = e.nextElement(); - String iniName = section.getStringProperty("Name"); - if (iniName == null || !iniName.equals(name)) { - continue; - } - - found = true; - - String iniPath = section.getStringProperty("Path"); - mAsserter.is(name, iniName, "Section with name found"); - mAsserter.is(dir.getName(), iniPath, "Section has correct path"); - } - - mAsserter.is(found, shouldFind, "Found profile where expected"); - } - - // Tries to remove a profile from Gecko profile. Verifies that it's removed from profiles.ini and its directory is deleted. - // TODO: Reconsider profile removal. Firefox would not normally remove a - // profile. Outstanding tasks may still try to access files in the profile. - private void removeProfile(GeckoProfile profile, boolean inProfilesIni) { - final String name = profile.getName(); - final File dir = profile.getDir(); - findInProfilesIni(name, dir, inProfilesIni); - mAsserter.ok(dir.exists(), "Profile dir exists before removing", dir.toString()); - mAsserter.ok(GeckoProfile.removeProfile(getActivity(), profile), "Remove was successful", name); - mAsserter.ok(!dir.exists(), "Profile dir was deleted when it was removed", dir.toString()); - findInProfilesIni(name, dir, false); - } - - // Looks for a dir whose name ends with the passed-in string. - private File findDir(String name) { - final File root; - try { - root = GeckoProfileDirectories.getMozillaDirectory(getActivity()); - } catch(Exception ex) { - return null; - } - - File[] dirs = root.listFiles(); - for (File dir : dirs) { - if (dir.getName().endsWith(name)) { - return dir; - } - } - - return null; - } - - @Override - public void tearDown() throws Exception { - // Clear SharedPreferences. - final Context context = getInstrumentation().getContext(); - GeckoSharedPrefs.forProfile(context).edit().clear().apply(); - - super.tearDown(); - } -} diff --git a/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/testGeckoRequest.java b/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/testGeckoRequest.java deleted file mode 100644 index ac4a9862c..000000000 --- a/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/testGeckoRequest.java +++ /dev/null @@ -1,121 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -package org.mozilla.gecko.tests; - -import java.util.concurrent.atomic.AtomicBoolean; - -import com.robotium.solo.Condition; - -import org.mozilla.gecko.GeckoAppShell; -import org.mozilla.gecko.tests.helpers.AssertionHelper; -import org.mozilla.gecko.tests.helpers.WaitHelper; -import org.mozilla.gecko.util.GeckoRequest; -import org.mozilla.gecko.util.NativeJSObject; - -/** - * Tests sending and receiving Gecko requests using the GeckoRequest API. - */ -public class testGeckoRequest extends JavascriptBridgeTest { - private static final String TEST_JS = "testGeckoRequest.js"; - private static final String REQUEST_EVENT = "Robocop:GeckoRequest"; - private static final String REQUEST_EXCEPTION_EVENT = "Robocop:GeckoRequestException"; - private static final int MAX_WAIT_MS = 5000; - - public void testGeckoRequest() { - blockForReadyAndLoadJS(TEST_JS); - - // Register a listener for this request. - getJS().syncCall("add_request_listener", REQUEST_EVENT); - - // Make sure we receive the expected response. - checkFooRequest(); - - // Try registering a second listener for this request, which should fail. - getJS().syncCall("add_second_request_listener", REQUEST_EVENT); - - // Unregister the listener for this request. - getJS().syncCall("remove_request_listener", REQUEST_EVENT); - - // Make sure we don't receive a response after removing the listener. - checkUnregisteredRequest(); - - // Check that we still receive a response for listeners that throw. - getJS().syncCall("add_exception_listener", REQUEST_EXCEPTION_EVENT); - checkExceptionRequest(); - getJS().syncCall("remove_request_listener", REQUEST_EXCEPTION_EVENT); - - getJS().syncCall("finish_test"); - } - - private void checkFooRequest() { - final AtomicBoolean responseReceived = new AtomicBoolean(false); - final String data = "foo"; - - GeckoAppShell.sendRequestToGecko(new GeckoRequest(REQUEST_EVENT, data) { - @Override - public void onResponse(NativeJSObject nativeJSObject) { - // Ensure we receive the expected response from Gecko. - final String result = nativeJSObject.getString("result"); - AssertionHelper.fAssertEquals("Sent and received request data", data + "bar", result); - responseReceived.set(true); - } - }); - - WaitHelper.waitFor("Received response for registered listener", new Condition() { - @Override - public boolean isSatisfied() { - return responseReceived.get(); - } - }, MAX_WAIT_MS); - } - - private void checkExceptionRequest() { - final AtomicBoolean responseReceived = new AtomicBoolean(false); - final AtomicBoolean errorReceived = new AtomicBoolean(false); - - GeckoAppShell.sendRequestToGecko(new GeckoRequest(REQUEST_EXCEPTION_EVENT, null) { - @Override - public void onResponse(NativeJSObject nativeJSObject) { - responseReceived.set(true); - } - - @Override - public void onError(NativeJSObject error) { - errorReceived.set(true); - } - }); - - WaitHelper.waitFor("Received error for listener with exception", new Condition() { - @Override - public boolean isSatisfied() { - return errorReceived.get(); - } - }, MAX_WAIT_MS); - - AssertionHelper.fAssertTrue("onResponse not called for listener with exception", !responseReceived.get()); - } - - private void checkUnregisteredRequest() { - final AtomicBoolean responseReceived = new AtomicBoolean(false); - - GeckoAppShell.sendRequestToGecko(new GeckoRequest(REQUEST_EVENT, null) { - @Override - public void onResponse(NativeJSObject nativeJSObject) { - responseReceived.set(true); - } - }); - - // This check makes sure that we do *not* receive a response for an unregistered listener, - // meaning waitForCondition() should always time out. - getSolo().waitForCondition(new Condition() { - @Override - public boolean isSatisfied() { - return responseReceived.get(); - } - }, MAX_WAIT_MS); - - AssertionHelper.fAssertTrue("Did not receive response for unregistered listener", !responseReceived.get()); - } -} diff --git a/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/testGetUserMedia.java b/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/testGetUserMedia.java deleted file mode 100644 index 405ddef7a..000000000 --- a/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/testGetUserMedia.java +++ /dev/null @@ -1,159 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -package org.mozilla.gecko.tests; - -import org.mozilla.gecko.AppConstants; - -import android.widget.Spinner; -import android.view.View; - -import com.robotium.solo.Condition; - -import android.hardware.Camera; -import android.os.Build; - -public class testGetUserMedia extends BaseTest { - private static final String LOGTAG = testGetUserMedia.class.getSimpleName(); - - private static final String GUM_MESSAGE = "Would you like to share your camera and microphone with"; - private static final String GUM_ALLOW = "^Share$"; - private static final String GUM_DENY = "^Don't Share$"; - - private static final String GUM_BACK_CAMERA = "Back facing camera"; - private static final String GUM_SELECT_TAB = "Choose a tab to stream"; - - private static final String GUM_PAGE_TITLE = "gUM Test Page"; - private static final String GUM_PAGE_FAILED = "failed gumtest"; - private static final String GUM_PAGE_AUDIO = "audio gumtest"; - private static final String GUM_PAGE_VIDEO = "video gumtest"; - private static final String GUM_PAGE_AUDIOVIDEO = "audiovideo gumtest"; - - public void testGetUserMedia() { - // TabShare.js is disabled on release builds. - if (AppConstants.RELEASE_OR_BETA) { - mAsserter.dumpLog(LOGTAG + " is disabled on release builds: returning"); - return; - } - - // Only try GUM test if the device has a camera (emulation). - if (Camera.getNumberOfCameras() <= 0) { - return; - } - - blockForGeckoReady(); - - final String GUM_CAMERA_URL = getAbsoluteUrl("/robocop/robocop_getusermedia2.html"); - final String GUM_TAB_URL = getAbsoluteUrl("/robocop/robocop_getusermedia.html"); - // Browser constraint needs HTTPS - final String GUM_TAB_HTTPS_URL = GUM_TAB_URL.replace("http://mochi.test:8888", "https://example.com"); - - // Tests on Camera page will test camera enumeration code, but - // the actual cameras don't seem to work on the emulators, so - // the enumeration is all that gets tested. - - // Test GUM notification showing - loadUrlAndWait(GUM_CAMERA_URL); - waitForText(GUM_MESSAGE); - mAsserter.is(mSolo.searchText(GUM_MESSAGE), true, "getUserMedia doorhanger has been displayed"); - waitForSpinner(); - // At least one camera detected - mAsserter.is(mSolo.searchText(GUM_BACK_CAMERA), true, "getUserMedia found a camera"); - mSolo.clickOnButton(GUM_DENY); - waitForTextDismissed(GUM_MESSAGE); - mAsserter.is(mSolo.searchText(GUM_MESSAGE), false, "getUserMedia doorhanger hidden after dismissal"); - verifyUrlBarTitle(GUM_CAMERA_URL); - - // Cameras don't work on the testing hardware, so stream a tab - loadUrlAndWait(GUM_TAB_HTTPS_URL); - waitForText(GUM_MESSAGE); - mAsserter.is(mSolo.searchText(GUM_MESSAGE), true, "getUserMedia doorhanger has been displayed"); - waitForSpinner(); - mAsserter.is(mSolo.searchText(GUM_SELECT_TAB), true, "Video source selection available"); - mAsserter.is(mSolo.searchText("MICROPHONE TO USE"), true, "Microphone selection available"); - mAsserter.is(mSolo.searchText("Microphone 1"), true, "Microphone 1 available"); - mSolo.clickOnText("Microphone 1"); - waitForText("No Audio"); - mAsserter.is(mSolo.searchText("No Audio"), true, "No 'No Audio' selection available"); - mSolo.clickOnText("No Audio"); - waitForTextDismissed("Microphone 1"); - mAsserter.is(mSolo.searchText("Microphone 1"), false, "Audio selection hidden after dismissal"); - mAsserter.is(mSolo.searchText(GUM_ALLOW), true, "Share button available after selection"); - mSolo.clickOnButton(GUM_ALLOW); - waitForTextDismissed(GUM_MESSAGE); - mAsserter.is(mSolo.searchText(GUM_MESSAGE), false, "getUserMedia doorhanger hidden after dismissal"); - waitForText(GUM_SELECT_TAB); - mAsserter.is(mSolo.searchText(GUM_SELECT_TAB), true, "Tab selection dialog displayed"); - mSolo.clickOnText(GUM_PAGE_TITLE); - waitForTextDismissed(GUM_SELECT_TAB); - mAsserter.is(mSolo.searchText(GUM_SELECT_TAB), false, "Tab selection dialog hidden"); - verifyUrlBarTitle(GUM_TAB_HTTPS_URL); - - // Android 2.3 testers fail because of audio issues: - // E/AudioRecord( 650): Unsupported configuration: sampleRate 44100, format 1, channelCount 1 - // E/libOpenSLES( 650): android_audioRecorder_realize(0x26d7d8) error creating AudioRecord object - if (Build.VERSION.SDK_INT < Build.VERSION_CODES.ICE_CREAM_SANDWICH) { - return; - } - - loadUrlAndWait(GUM_TAB_HTTPS_URL); - waitForText(GUM_MESSAGE); - mAsserter.is(mSolo.searchText(GUM_MESSAGE), true, "getUserMedia doorhanger has been displayed"); - - waitForSpinner(); - mAsserter.is(mSolo.searchText(GUM_SELECT_TAB), true, "Video source selection available"); - mSolo.clickOnButton(GUM_ALLOW); - waitForTextDismissed(GUM_MESSAGE); - waitForText(GUM_SELECT_TAB); - mAsserter.is(mSolo.searchText(GUM_SELECT_TAB), true, "Tab selection dialog displayed"); - mSolo.clickOnText(GUM_PAGE_TITLE); - waitForTextDismissed(GUM_SELECT_TAB); - mAsserter.is(mSolo.searchText(GUM_SELECT_TAB), false, "Tab selection dialog hidden"); - verifyUrlBarTitle(GUM_TAB_HTTPS_URL); - - loadUrlAndWait(GUM_TAB_HTTPS_URL); - waitForText(GUM_MESSAGE); - mAsserter.is(mSolo.searchText(GUM_MESSAGE), true, "getUserMedia doorhanger has been displayed"); - - waitForSpinner(); - mAsserter.is(mSolo.searchText(GUM_SELECT_TAB), true, "Video source selection available"); - mSolo.clickOnText(GUM_SELECT_TAB); - waitForText("No Video"); - mAsserter.is(mSolo.searchText("No Video"), true, "'No video' source selection available"); - mSolo.clickOnText("No Video"); - waitForTextDismissed(GUM_SELECT_TAB); - mSolo.clickOnButton(GUM_ALLOW); - waitForTextDismissed(GUM_MESSAGE); - mAsserter.is(mSolo.searchText(GUM_MESSAGE), false, "getUserMedia doorhanger hidden after dismissal"); - verifyUrlBarTitle(GUM_TAB_HTTPS_URL); - } - - // wait for a Spinner view that is clickable - private void waitForSpinner() { - waitForCondition(new Condition() { - @Override - public boolean isSatisfied() { - for (Spinner view : mSolo.getCurrentViews(Spinner.class)) { - if (view.isClickable() && - view.getVisibility() == View.VISIBLE && - view.getWidth() > 0 && - view.getHeight() > 0) { - return true; - } - } - return false; - } - }, MAX_WAIT_MS); - } - - // wait until the specified text is *not* displayed - private void waitForTextDismissed(final String text) { - waitForCondition(new Condition() { - @Override - public boolean isSatisfied() { - return !mSolo.searchText(text); - } - }, MAX_WAIT_MS); - } -} diff --git a/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/testHistory.java b/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/testHistory.java deleted file mode 100644 index 1f2fbbd38..000000000 --- a/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/testHistory.java +++ /dev/null @@ -1,74 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -package org.mozilla.gecko.tests; - -import android.view.View; -import android.view.ViewGroup; -import android.widget.ListView; - -import org.mozilla.gecko.home.HomePager; - -import com.robotium.solo.Condition; - -public class testHistory extends AboutHomeTest { - private View mFirstChild; - - public void testHistory() { - blockForGeckoReady(); - - String url = getAbsoluteUrl(mStringHelper.ROBOCOP_BLANK_PAGE_01_URL); - String url2 = getAbsoluteUrl(mStringHelper.ROBOCOP_BLANK_PAGE_02_URL); - String url3 = getAbsoluteUrl(mStringHelper.ROBOCOP_BLANK_PAGE_03_URL); - - inputAndLoadUrl(url); - verifyUrlBarTitle(url); - inputAndLoadUrl(url2); - verifyUrlBarTitle(url2); - inputAndLoadUrl(url3); - verifyUrlBarTitle(url3); - - openAboutHomeTab(AboutHomeTabs.HISTORY); - - final ListView hList = findListViewWithTag(HomePager.LIST_TAG_HISTORY); - mAsserter.is(waitForNonEmptyListToLoad(hList), true, "list is properly loaded"); - - // Click on the history item and wait for the page to load - // wait for the history list to be populated - mFirstChild = null; - boolean success = waitForCondition(new Condition() { - @Override - public boolean isSatisfied() { - mFirstChild = hList.getChildAt(1); - if (mFirstChild == null) { - return false; - } - if (mFirstChild instanceof android.view.ViewGroup) { - ViewGroup group = (ViewGroup)mFirstChild; - if (group.getChildCount() < 1) { - return false; - } - for (int i = 0; i < group.getChildCount(); i++) { - View grandChild = group.getChildAt(i); - if (grandChild instanceof android.widget.TextView) { - mAsserter.ok(true, "found TextView:", ((android.widget.TextView)grandChild).getText().toString()); - } - } - } else { - mAsserter.dumpLog("first child not a ViewGroup: "+mFirstChild); - return false; - } - return true; - } - }, MAX_WAIT_MS); - - mAsserter.isnot(mFirstChild, null, "Got history item"); - mSolo.clickOnView(mFirstChild); - - // The first item here (since it was just visited) should be a "Switch to tab" item - // i.e. don't expect a DOMContentLoaded event - verifyUrlBarTitle(mStringHelper.ROBOCOP_BLANK_PAGE_03_URL); - verifyUrl(url3); - } -} diff --git a/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/testHistoryService.java b/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/testHistoryService.java deleted file mode 100644 index 4c605f6c3..000000000 --- a/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/testHistoryService.java +++ /dev/null @@ -1,12 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this file, - * You can obtain one at http://mozilla.org/MPL/2.0/. */ - -package org.mozilla.gecko.tests; - -public class testHistoryService extends JavascriptTest { - - public testHistoryService() { - super("testHistoryService.js"); - } -} diff --git a/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/testHomeBanner.java b/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/testHomeBanner.java deleted file mode 100644 index be36ae5a0..000000000 --- a/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/testHomeBanner.java +++ /dev/null @@ -1,94 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -package org.mozilla.gecko.tests; - -import org.mozilla.gecko.Actions; -import org.mozilla.gecko.tests.helpers.GeckoHelper; -import org.mozilla.gecko.tests.helpers.NavigationHelper; - -public class testHomeBanner extends UITest { - - private static final String TEST_URL = "chrome://roboextender/content/robocop_home_banner.html"; - private static final String TEXT = "The quick brown fox jumps over the lazy dog."; - - public void testHomeBanner() { - GeckoHelper.blockForReady(); - - // Make sure the banner is not visible to start. - mAboutHome.assertVisible() - .assertBannerNotVisible(); - - // These test methods depend on being run in this order. - addBannerTest(); - - // Make sure the banner hides when the user starts interacting with the url bar. - hideOnToolbarFocusTest(); - - // Make sure to test dismissing the banner after everything else, since dismissing - // the banner will prevent it from showing up again. - dismissBannerTest(); - } - - /** - * Adds a banner message, verifies that it appears when it should, and verifies that - * onshown/onclick handlers are called in JS. - * - * Note: This test does not remove the message after it is done. - */ - private void addBannerTest() { - // Load about:home and make sure the onshown handler is called. - Actions.EventExpecter eventExpecter = getActions().expectGeckoEvent("TestHomeBanner:MessageShown"); - addBannerMessage(); - NavigationHelper.enterAndLoadUrl(mStringHelper.ABOUT_HOME_URL); - eventExpecter.blockForEvent(); - - // Verify that the banner is visible with the correct text. - mAboutHome.assertBannerText(TEXT); - - // Verify that the banner isn't visible after navigating away from about:home. - NavigationHelper.enterAndLoadUrl(mStringHelper.ABOUT_FIREFOX_URL); - mAboutHome.assertBannerNotVisible(); - } - - - private void hideOnToolbarFocusTest() { - NavigationHelper.enterAndLoadUrl(mStringHelper.ABOUT_HOME_URL); - mAboutHome.assertVisible() - .assertBannerVisible(); - - mToolbar.enterEditingMode(); - mAboutHome.assertBannerNotVisible(); - - mToolbar.dismissEditingMode(); - mAboutHome.assertBannerVisible(); - } - - /** - * Adds a banner message, verifies that its ondismiss handler is called in JS, - * and verifies that the banner is no longer shown after it is dismissed. - * - * Note: This test does not remove the message after it is done. - */ - private void dismissBannerTest() { - NavigationHelper.enterAndLoadUrl(mStringHelper.ABOUT_HOME_URL); - mAboutHome.assertVisible(); - - // Test to make sure the ondismiss handler is called when the close button is clicked. - final Actions.EventExpecter eventExpecter = getActions().expectGeckoEvent("TestHomeBanner:MessageDismissed"); - mAboutHome.dismissBanner(); - eventExpecter.blockForEvent(); - - mAboutHome.assertBannerNotVisible(); - } - - /** - * Loads the roboextender page to add a message to the banner. - */ - private void addBannerMessage() { - final Actions.EventExpecter eventExpecter = getActions().expectGeckoEvent("TestHomeBanner:MessageAdded"); - NavigationHelper.enterAndLoadUrl(TEST_URL + "#addMessage"); - eventExpecter.blockForEvent(); - } -} diff --git a/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/testHomeListsProvider.java b/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/testHomeListsProvider.java deleted file mode 100644 index fbe2df82f..000000000 --- a/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/testHomeListsProvider.java +++ /dev/null @@ -1,118 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -package org.mozilla.gecko.tests; - -import android.content.ContentUris; -import android.content.ContentValues; -import android.database.Cursor; -import android.net.Uri; - -public class testHomeListsProvider extends ContentProviderTest { - // This test does not run, so it just needs to compile. The test was - // disabled at the time the real Contract was removed; to leave a skeleton - // for a future re-implementor, we include this dummy Contract class. - private static class Contract { - public static final Uri CONTENT_URI = null; - public static final Uri CONTENT_FAKE_URI = null; - - public static final String _ID = null; - public static final String PROVIDER_ID = null; - public static final String TITLE = null; - public static final String URL = null; - } - - @SuppressWarnings("unused") - private void ensureEmptyDatabase() throws Exception { - // Delete all the list entries. - mProvider.delete(Contract.CONTENT_URI, null, null); - - final Cursor c = mProvider.query(Contract.CONTENT_URI, null, null, null, null); - mAsserter.is(c.getCount(), 0, "All list entries were deleted"); - c.close(); - } - - @Override - public void setUp() throws Exception { - // This test is disabled, so this just needs to compile. - super.setUp(null, null, "homelists.db"); - - mTests.add(new TestFakeItems()); - - // Disabled until database support lands - //mTests.add(new TestInsertItem()); - } - - public void testListsProvider() throws Exception { - for (int i = 0; i < mTests.size(); i++) { - Runnable test = mTests.get(i); - - setTestName(test.getClass().getSimpleName()); - // Disabled until database support lands - //ensureEmptyDatabase(); - test.run(); - } - } - - abstract class Test implements Runnable { - @Override - public void run() { - try { - test(); - } catch (Exception e) { - mAsserter.is(true, false, "Test " + this.getClass().getName() + - " threw exception: " + e); - } - } - - public abstract void test() throws Exception; - } - - class TestFakeItems extends Test { - @Override - public void test() throws Exception { - final long id = 1; - final String providerId = "fake-provider"; - final String title = "Example"; - final String url = "http://example.com"; - - final Cursor c = mProvider.query(Contract.CONTENT_FAKE_URI, null, null, null, null); - mAsserter.is(c.moveToFirst(), true, "Fake list item found"); - - mAsserter.is(c.getLong(c.getColumnIndex(Contract._ID)), id, "Fake list item has correct ID"); - mAsserter.is(c.getString(c.getColumnIndex(Contract.PROVIDER_ID)), providerId, "Fake list item has correct provider ID"); - mAsserter.is(c.getString(c.getColumnIndex(Contract.TITLE)), title, "Fake list item has correct title"); - mAsserter.is(c.getString(c.getColumnIndex(Contract.URL)), url, "Fake list item has correct URL"); - - c.close(); - } - } - - class TestInsertItem extends Test { - @Override - public void test() throws Exception { - final String providerId = "{c77da387-4c80-0c45-9f22-70276c29b3ed}"; - final String title = "Mozilla"; - final String url = "https://mozilla.org"; - - // Insert a new list item with test values. - final ContentValues cv = new ContentValues(); - cv.put(Contract.PROVIDER_ID, providerId); - cv.put(Contract.TITLE, title); - cv.put(Contract.URL, url); - - final long id = ContentUris.parseId(mProvider.insert(Contract.CONTENT_URI, cv)); - - // Check that the item was inserted correctly. - final Cursor c = mProvider.query(Contract.CONTENT_URI, null, Contract._ID + " = ?", new String[] { String.valueOf(id) }, null); - mAsserter.is(c.moveToFirst(), true, "Inserted list item found"); - - mAsserter.is(c.getString(c.getColumnIndex(Contract.PROVIDER_ID)), providerId, "Inserted list item has correct provider ID"); - mAsserter.is(c.getString(c.getColumnIndex(Contract.TITLE)), title, "Inserted list item has correct title"); - mAsserter.is(c.getString(c.getColumnIndex(Contract.URL)), url, "Inserted list item has correct URL"); - - c.close(); - } - } -} diff --git a/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/testICODecoder.java b/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/testICODecoder.java deleted file mode 100644 index 5cbbd1be9..000000000 --- a/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/testICODecoder.java +++ /dev/null @@ -1,238 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -package org.mozilla.gecko.tests; - -import android.graphics.Bitmap; - -import org.mozilla.gecko.icons.decoders.ICODecoder; -import org.mozilla.gecko.icons.decoders.IconDirectoryEntry; -import org.mozilla.gecko.icons.decoders.LoadFaviconResult; - -import java.io.ByteArrayOutputStream; -import java.io.File; -import java.io.IOException; -import java.io.InputStream; - -import static org.mozilla.gecko.tests.helpers.AssertionHelper.fAssertEquals; -import static org.mozilla.gecko.tests.helpers.AssertionHelper.fAssertNull; -import static org.mozilla.gecko.tests.helpers.AssertionHelper.fAssertNotNull; -import static org.mozilla.gecko.tests.helpers.AssertionHelper.fAssertTrue; - -public class testICODecoder extends UITest { - - private int mGolemNumIconDirEntries; - - public void testICODecoder() throws IOException { - testMicrosoftFavicon(); - testNvidiaFavicon(); - testGolemFavicon(); - testMissingHeader(); - testCorruptIconDirectory(); - } - - /** - * Decode and verify a Microsoft favicon with six different sizes: - * 128x128, 72x72, 48x48, 32x32, 24x24, 16x16 - * Each of the six BMPs supposedly has zero colour depth. - */ - private void testMicrosoftFavicon() throws IOException { - byte[] icoBytes = readICO("microsoft_favicon.ico"); - fAssertEquals("Expecting Microsoft favicon to be 17174 bytes.", 17174, icoBytes.length); - - ICODecoder decoder = new ICODecoder(getInstrumentation().getTargetContext(), icoBytes, 0, - icoBytes.length); - LoadFaviconResult result = decoder.decode(); - fAssertNotNull("Expecting Microsoft favicon to not fail decoding.", result); - - int largestBitmap = Integer.MAX_VALUE; - - int[] possibleSizes = {16, 24, 32, 48, 72, 128}; - for (int i = 0; i < possibleSizes.length; i++) { - if (possibleSizes[i] > decoder.getLargestFaviconSize()) { - largestBitmap = possibleSizes[i]; - - // Verify that all bitmaps but the smallest larger than Favicons.largestFaviconSize - // have been discarded. - for (int j = i + 1; j < possibleSizes.length; j++) { - Bitmap selectedBitmap = result.getBestBitmap(possibleSizes[j]); - fAssertNotNull("Expecting a best bitmap to be found for " + - possibleSizes[j] + "x" + possibleSizes[j], selectedBitmap); - - fAssertEquals("Expecting best bitmap to have width " + possibleSizes[i], - possibleSizes[i], selectedBitmap.getWidth()); - fAssertEquals("Expecting best bitmap to have height " + possibleSizes[i], - possibleSizes[i], selectedBitmap.getHeight()); - - // Reset the result's bitmap iterator. - result = decoder.decode(); - } - - break; - } - } - - int[] expectedSizes = { - // If we request a 33x33 we should get a 48x48. - 33, 48, - // If we request a 24x24 we should get a 24x24. - 24, 24, - // If we request a 8x8 we should get a 16x16. - 8, 16, - }; - - for (int i = 0; i < expectedSizes.length - 1; i += 2) { - if (expectedSizes[i + 1] > largestBitmap) { - // This bitmap has been discarded. - continue; - } - - Bitmap selectedBitmap = result.getBestBitmap(expectedSizes[i]); - fAssertNotNull("Expecting a best bitmap to have been found for " + - expectedSizes[i] + "x" + expectedSizes[i], selectedBitmap); - - fAssertEquals("Expecting best bitmap to have width " + expectedSizes[i + 1], - expectedSizes[i + 1], selectedBitmap.getWidth()); - fAssertEquals("Expecting best bitmap to have height " + expectedSizes[i + 1], - expectedSizes[i + 1], selectedBitmap.getHeight()); - - // Reset the result's bitmap iterator. - result = decoder.decode(); - } - } - - /** - * Decode and verify a NVIDIA favicon with three different colour depths, - * and three different sizes for each colour depth. All payloads are BMP. - */ - private void testNvidiaFavicon() throws IOException { - byte[] icoBytes = readICO("nvidia_favicon.ico"); - fAssertEquals("Expecting NVIDIA favicon to be 25214 bytes.", 25214, icoBytes.length); - - ICODecoder decoder = new ICODecoder(getInstrumentation().getTargetContext(), icoBytes, 0, - icoBytes.length); - fAssertNotNull("Expecting NVIDIA favicon to not fail decoding.", decoder.decode()); - - // Verify the best entry is correctly chosen for each width. - // We expect 32 bpp in all cases even if 32 bpp exceeds IconDirectoryEntry.maxBPP. - // This is okay because IconDirectoryEntry.maxBPP is a "desired bpp" not the absolute max. - // This was chosen because we think it gives better results to select a higher bpp and let - // Android downscale the bpp, rather than showing a bitmap of potentially significantly - // lower color depth. - IconDirectoryEntry[] expectedEntries = { - new IconDirectoryEntry(16, 16, 0, 32, 1128, 24086, false), - new IconDirectoryEntry(32, 32, 0, 32, 4264, 19822, false), - new IconDirectoryEntry(48, 48, 0, 32, 9640, 10182, false) - }; - - IconDirectoryEntry[] directory = decoder.getIconDirectory(); - fAssertTrue("NVIDIA icon directory must contain at least one entry.", directory.length > 0); - for (int i = 0; i < directory.length; i++) { - if (expectedEntries[i].getWidth() > directory[directory.length - 1].getWidth()) { - // This test-case has been discarded due to being over-sized. Next. - // All subsequent cases will be too. - fAssertTrue("At least one test-case should not have been discarded.", i > 0); - break; - } - - // Verify the actual Icon Directory entry was as expected. - fAssertEquals(directory[i] + " is expected to be equal to " + expectedEntries[i], - 0, directory[i].compareTo(expectedEntries[i])); - } - } - - /** - * Decode and verify a Golem.de favicon with five bitmaps: 256x256, 48x48, 32x32, 24x24, 16x16 - * Only the 256x256 is a PNG payload. All others are BMP. - */ - private void testGolemFavicon() throws IOException { - byte[] icoBytes = readICO("golem_favicon.ico"); - fAssertEquals("Expecting Golem favicon to be 40648 bytes.", 40648, icoBytes.length); - - ICODecoder decoder = new ICODecoder(getInstrumentation().getTargetContext(), icoBytes, 0, - icoBytes.length); - fAssertNotNull("Expecting Golem favicon to not fail decoding.", decoder.decode()); - - // Verify the five entries were correctly identified. - IconDirectoryEntry[] expectedEntries = { - new IconDirectoryEntry(16, 16, 0, 32, 1128, 39250, false), - new IconDirectoryEntry(24, 24, 0, 32, 2488, 37032, false), - new IconDirectoryEntry(32, 32, 0, 32, 4392, 32640, false), - new IconDirectoryEntry(48, 48, 0, 32, 9832, 22808, false), - new IconDirectoryEntry(256, 256, 0, 32, 22722, 86, true) - }; - - IconDirectoryEntry[] directory = decoder.getIconDirectory(); - fAssertTrue("Golem icon directory must contain at least one entry.", directory.length > 0); - for (int i = 0; i < directory.length; i++) { - if (expectedEntries[i].getWidth() > directory[directory.length - 1].getWidth()) { - // This test-case has been discarded due to being over-sized. - // All subsequent cases will be too. - fAssertTrue("At least one test-case should not have been discarded.", i > 0); - break; - } - - // Verify the actual Icon Directory entry was as expected. - fAssertEquals(directory[i] + " is expected to be equal to " + expectedEntries[i], - 0, directory[i].compareTo(expectedEntries[i])); - } - - // How many icon directory entries in the non-maimed favicon? - mGolemNumIconDirEntries = directory.length; - } - - /** - * Verify that deleting the header will make decoding fail. - */ - private void testMissingHeader() throws IOException { - byte[] icoBytes = readICO("microsoft_favicon.ico"); - fAssertEquals("Expecting Microsoft favicon to be 17174 bytes.", 17174, icoBytes.length); - - int offsetNoHeader = ICODecoder.ICO_HEADER_LENGTH_BYTES; - int lenNoHeader = icoBytes.length - ICODecoder.ICO_HEADER_LENGTH_BYTES; - ICODecoder decoder = new ICODecoder(getInstrumentation().getTargetContext(), icoBytes, - offsetNoHeader, lenNoHeader); - fAssertNull("Expecting Microsoft favicon to fail decoding.", decoder.decode()); - } - - /** - * Verify that decoding does not fail if the number of icon directory entries is smaller than - * the number given in the header. - */ - private void testCorruptIconDirectory() throws IOException { - byte[] icoBytes = readICO("golem_favicon.ico"); - fAssertEquals("Expecting Golem favicon to be 40648 bytes.", 40648, icoBytes.length); - - byte[] icoMaimed = new byte[icoBytes.length - ICODecoder.ICO_ICONDIRENTRY_LENGTH_BYTES]; - // Copy the header and first four icon directory entries into icoMaimed. - System.arraycopy(icoBytes, 0, icoMaimed, 0, - ICODecoder.ICO_HEADER_LENGTH_BYTES + 4 * ICODecoder.ICO_ICONDIRENTRY_LENGTH_BYTES); - // Skip the last icon directory entry. - System.arraycopy(icoBytes, - ICODecoder.ICO_HEADER_LENGTH_BYTES + 5 * ICODecoder.ICO_ICONDIRENTRY_LENGTH_BYTES, - icoMaimed, - ICODecoder.ICO_HEADER_LENGTH_BYTES + 4 * ICODecoder.ICO_ICONDIRENTRY_LENGTH_BYTES, - icoBytes.length - ICODecoder.ICO_HEADER_LENGTH_BYTES - 5 * ICODecoder.ICO_ICONDIRENTRY_LENGTH_BYTES); - - ICODecoder decoder = new ICODecoder(getInstrumentation().getTargetContext(), icoMaimed, 0, - icoMaimed.length); - fAssertNotNull("Expecting Golem favicon to not fail decoding.", decoder.decode()); - fAssertEquals("Expecting Golem favicon icon directory to contain one less bitmap.", - mGolemNumIconDirEntries - 1, decoder.getIconDirectory().length); - } - - private byte[] readICO(String fileName) throws IOException { - String filePath = "ico_decoder_favicons" + File.separator + fileName; - InputStream icoStream = getInstrumentation().getContext().getAssets().open(filePath); - ByteArrayOutputStream byteStream = new ByteArrayOutputStream(icoStream.available()); - - int readByte; - while ((readByte = icoStream.read()) != -1) { - byteStream.write(readByte); - } - - return byteStream.toByteArray(); - } -} - diff --git a/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/testInputConnection.java b/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/testInputConnection.java deleted file mode 100644 index f9a6bcef7..000000000 --- a/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/testInputConnection.java +++ /dev/null @@ -1,349 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -package org.mozilla.gecko.tests; - -import static org.mozilla.gecko.tests.helpers.AssertionHelper.fAssertEquals; -import static org.mozilla.gecko.tests.helpers.WaitHelper.waitFor; - -import org.mozilla.gecko.tests.components.GeckoViewComponent.InputConnectionTest; -import org.mozilla.gecko.tests.helpers.GeckoHelper; -import org.mozilla.gecko.tests.helpers.NavigationHelper; - -import com.robotium.solo.Condition; - -import android.view.KeyEvent; -import android.view.inputmethod.EditorInfo; -import android.view.inputmethod.InputConnection; - -/** - * Tests the proper operation of GeckoInputConnection - */ -public class testInputConnection extends JavascriptBridgeTest { - - private static final String INITIAL_TEXT = "foo"; - - public void testInputConnection() throws InterruptedException { - GeckoHelper.blockForReady(); - - final String url = mStringHelper.ROBOCOP_INPUT_URL; - NavigationHelper.enterAndLoadUrl(url); - mToolbar.assertTitle(url); - - // First run tests inside the normal input field. - getJS().syncCall("focus_input", INITIAL_TEXT); - mGeckoView.mTextInput - .waitForInputConnection() - .testInputConnection(new BasicInputConnectionTest()); - - // Then switch focus to the text area and rerun tests. - getJS().syncCall("focus_text_area", INITIAL_TEXT); - mGeckoView.mTextInput - .waitForInputConnection() - .testInputConnection(new BasicInputConnectionTest()); - - // Then switch focus to the content editable and rerun tests. - getJS().syncCall("focus_content_editable", INITIAL_TEXT); - mGeckoView.mTextInput - .waitForInputConnection() - .testInputConnection(new BasicInputConnectionTest()); - - // Then switch focus to the design mode document and rerun tests. - getJS().syncCall("focus_design_mode", INITIAL_TEXT); - mGeckoView.mTextInput - .waitForInputConnection() - .testInputConnection(new BasicInputConnectionTest()); - - // Then switch focus to the resetting input field, and run tests there. - getJS().syncCall("focus_resetting_input", ""); - mGeckoView.mTextInput - .waitForInputConnection() - .testInputConnection(new ResettingInputConnectionTest()); - - // Then switch focus to the hiding input field, and run tests there. - getJS().syncCall("focus_hiding_input", ""); - mGeckoView.mTextInput - .waitForInputConnection() - .testInputConnection(new HidingInputConnectionTest()); - - getJS().syncCall("finish_test"); - } - - private class BasicInputConnectionTest extends InputConnectionTest { - @Override - public void test(final InputConnection ic, EditorInfo info) { - waitFor("focus change", new Condition() { - @Override - public boolean isSatisfied() { - return INITIAL_TEXT.equals(getText(ic)); - } - }); - - // Test setSelection - ic.setSelection(0, 3); - assertSelection("Can set selection to range", ic, 0, 3); - ic.setSelection(-3, 6); - // Test both forms of assert - assertTextAndSelection("Can handle invalid range", ic, INITIAL_TEXT, 0, 3); - ic.setSelection(3, 3); - assertSelectionAt("Can collapse selection", ic, 3); - ic.setSelection(4, 4); - assertTextAndSelectionAt("Can handle invalid cursor", ic, INITIAL_TEXT, 3); - - // Test commitText - ic.commitText("", 10); // Selection past end of new text - assertTextAndSelectionAt("Can commit empty text", ic, "foo", 3); - ic.commitText("bar", 1); // Selection at end of new text - assertTextAndSelectionAt("Can commit text (select after)", ic, "foobar", 6); - ic.commitText("foo", -1); // Selection at start of new text - assertTextAndSelectionAt("Can commit text (select before)", ic, "foobarfoo", 5); - - // Test deleteSurroundingText - ic.deleteSurroundingText(1, 0); - assertTextAndSelectionAt("Can delete text before", ic, "foobrfoo", 4); - ic.deleteSurroundingText(1, 1); - assertTextAndSelectionAt("Can delete text before/after", ic, "foofoo", 3); - ic.deleteSurroundingText(0, 10); - assertTextAndSelectionAt("Can delete text after", ic, "foo", 3); - ic.deleteSurroundingText(0, 0); - assertTextAndSelectionAt("Can delete empty text", ic, "foo", 3); - - // Test setComposingText - ic.setComposingText("foo", 1); - assertTextAndSelectionAt("Can start composition", ic, "foofoo", 6); - ic.setComposingText("", 1); - assertTextAndSelectionAt("Can set empty composition", ic, "foo", 3); - ic.setComposingText("bar", 1); - assertTextAndSelectionAt("Can update composition", ic, "foobar", 6); - - // Test finishComposingText - ic.finishComposingText(); - assertTextAndSelectionAt("Can finish composition", ic, "foobar", 6); - - // Test setComposingRegion - ic.setComposingRegion(0, 3); - assertTextAndSelectionAt("Can set composing region", ic, "foobar", 6); - - ic.setComposingText("far", 1); - assertTextAndSelectionAt("Can set composing region text", ic, "farbar", 3); - - ic.setComposingRegion(1, 4); - assertTextAndSelectionAt("Can set existing composing region", ic, "farbar", 3); - - ic.setComposingText("rab", 3); - assertTextAndSelectionAt("Can set new composing region text", ic, "frabar", 6); - - // Test getTextBeforeCursor - fAssertEquals("Can retrieve text before cursor", "bar", ic.getTextBeforeCursor(3, 0)); - - // Test getTextAfterCursor - fAssertEquals("Can retrieve text after cursor", "", ic.getTextAfterCursor(3, 0)); - - ic.finishComposingText(); - assertTextAndSelectionAt("Can finish composition", ic, "frabar", 6); - - // Test sendKeyEvent - final KeyEvent shiftKey = new KeyEvent(KeyEvent.ACTION_DOWN, - KeyEvent.KEYCODE_SHIFT_LEFT); - final KeyEvent leftKey = new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_DPAD_LEFT); - final KeyEvent tKey = new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_T); - - ic.sendKeyEvent(shiftKey); - ic.sendKeyEvent(leftKey); - ic.sendKeyEvent(KeyEvent.changeAction(leftKey, KeyEvent.ACTION_UP)); - ic.sendKeyEvent(KeyEvent.changeAction(shiftKey, KeyEvent.ACTION_UP)); - assertTextAndSelection("Can select using key event", ic, "frabar", 6, 5); - - ic.sendKeyEvent(tKey); - ic.sendKeyEvent(KeyEvent.changeAction(tKey, KeyEvent.ACTION_UP)); - assertTextAndSelectionAt("Can type using event", ic, "frabat", 6); - - ic.deleteSurroundingText(6, 0); - assertTextAndSelectionAt("Can clear text", ic, "", 0); - - // Bug 1133802, duplication when setting the same composing text more than once. - ic.setComposingText("foo", 1); - assertTextAndSelectionAt("Can set the composing text", ic, "foo", 3); - ic.setComposingText("foo", 1); - assertTextAndSelectionAt("Can set the same composing text", ic, "foo", 3); - ic.setComposingText("bar", 1); - assertTextAndSelectionAt("Can set different composing text", ic, "bar", 3); - ic.setComposingText("bar", 1); - assertTextAndSelectionAt("Can set the same composing text", ic, "bar", 3); - ic.setComposingText("bar", 1); - assertTextAndSelectionAt("Can set the same composing text again", ic, "bar", 3); - ic.finishComposingText(); - assertTextAndSelectionAt("Can finish composing text", ic, "bar", 3); - - ic.deleteSurroundingText(3, 0); - assertTextAndSelectionAt("Can clear text", ic, "", 0); - - // Bug 1209465, cannot enter ideographic space character by itself (U+3000). - ic.commitText("\u3000", 1); - assertTextAndSelectionAt("Can commit ideographic space", ic, "\u3000", 1); - - ic.deleteSurroundingText(1, 0); - assertTextAndSelectionAt("Can clear text", ic, "", 0); - - // Bug 1051556, exception due to committing text changes during flushing. - ic.setComposingText("bad", 1); - assertTextAndSelectionAt("Can set the composing text", ic, "bad", 3); - getJS().asyncCall("test_reflush_changes"); - // Wait for text change notifications to come in. - processGeckoEvents(); - assertTextAndSelectionAt("Can re-flush text changes", ic, "good", 4); - ic.setComposingText("done", 1); - assertTextAndSelectionAt("Can update composition after re-flushing", ic, "gooddone", 8); - ic.finishComposingText(); - assertTextAndSelectionAt("Can finish composing text", ic, "gooddone", 8); - - ic.deleteSurroundingText(8, 0); - assertTextAndSelectionAt("Can clear text", ic, "", 0); - - // Bug 1241558 - wrong selection due to ignoring selection notification. - ic.setComposingText("foobar", 1); - assertTextAndSelectionAt("Can set the composing text", ic, "foobar", 6); - getJS().asyncCall("test_set_selection"); - // Wait for text change notifications to come in. - processGeckoEvents(); - assertTextAndSelectionAt("Can select after committing", ic, "foobar", 3); - ic.setComposingText("barfoo", 1); - assertTextAndSelectionAt("Can compose after selecting", ic, "barfoo", 6); - ic.beginBatchEdit(); - ic.setSelection(3, 3); - ic.finishComposingText(); - ic.deleteSurroundingText(1, 1); - ic.endBatchEdit(); - assertTextAndSelectionAt("Can delete after committing", ic, "baoo", 2); - - ic.deleteSurroundingText(2, 2); - assertTextAndSelectionAt("Can clear text", ic, "", 0); - - // Bug 1275371 - shift+backspace should not forward delete on Android. - final KeyEvent delKey = new KeyEvent(KeyEvent.ACTION_DOWN, - KeyEvent.KEYCODE_DEL); - - ic.beginBatchEdit(); - ic.commitText("foo", 1); - ic.setSelection(1, 1); - ic.endBatchEdit(); - assertTextAndSelectionAt("Can commit text", ic, "foo", 1); - - ic.sendKeyEvent(shiftKey); - ic.sendKeyEvent(delKey); - ic.sendKeyEvent(KeyEvent.changeAction(delKey, KeyEvent.ACTION_UP)); - assertTextAndSelectionAt("Can backspace with shift+backspace", ic, "oo", 0); - - ic.sendKeyEvent(delKey); - ic.sendKeyEvent(KeyEvent.changeAction(delKey, KeyEvent.ACTION_UP)); - ic.sendKeyEvent(KeyEvent.changeAction(shiftKey, KeyEvent.ACTION_UP)); - assertTextAndSelectionAt("Cannot forward delete with shift+backspace", ic, "oo", 0); - - ic.deleteSurroundingText(0, 2); - assertTextAndSelectionAt("Can clear text", ic, "", 0); - - // Bug 1123514 - exception due to incorrect text replacement offsets. - getJS().syncCall("test_bug1123514"); - // Gecko will change text to 'abc' when we input 'b', potentially causing - // incorrect calculation of text replacement offsets. - ic.commitText("b", 1); - // We don't assert text here because this test only works for input/textarea, - // so an assertion would fail for contentEditable/designMode. - processGeckoEvents(); - processInputConnectionEvents(); - - ic.deleteSurroundingText(2, 1); - assertTextAndSelectionAt("Can clear text", ic, "", 0); - - // Make sure we don't leave behind stale events for the following test. - processGeckoEvents(); - processInputConnectionEvents(); - } - } - - /** - * ResettingInputConnectionTest performs tests on the resetting input in - * robocop_input.html. Any test that uses the normal input should be put in - * BasicInputConnectionTest. - */ - private class ResettingInputConnectionTest extends InputConnectionTest { - @Override - public void test(final InputConnection ic, EditorInfo info) { - waitFor("focus change", new Condition() { - @Override - public boolean isSatisfied() { - return "".equals(getText(ic)); - } - }); - - // Bug 1199658, duplication when page has JS that resets input field value. - - ic.commitText("foo", 1); - assertTextAndSelectionAt("Can commit text (resetting)", ic, "foo", 3); - - ic.setComposingRegion(0, 3); - // The bug appears after composition update events are processed. We only - // issue these events after some back-and-forth calls between the Gecko thread - // and the input connection thread. Therefore, to ensure these events are - // issued and to ensure the bug appears, we have to process all Gecko events, - // then all input connection events, and finally all Gecko events again. - processGeckoEvents(); - processInputConnectionEvents(); - processGeckoEvents(); - assertTextAndSelectionAt("Can set composing region (resetting)", ic, "foo", 3); - - ic.setComposingText("foobar", 1); - processGeckoEvents(); - processInputConnectionEvents(); - processGeckoEvents(); - assertTextAndSelectionAt("Can change composing text (resetting)", ic, "foobar", 6); - - ic.setComposingText("baz", 1); - processGeckoEvents(); - processInputConnectionEvents(); - processGeckoEvents(); - assertTextAndSelectionAt("Can reset composing text (resetting)", ic, "baz", 3); - - ic.finishComposingText(); - assertTextAndSelectionAt("Can finish composing text (resetting)", ic, "baz", 3); - - ic.deleteSurroundingText(3, 0); - assertTextAndSelectionAt("Can clear text", ic, "", 0); - - // Make sure we don't leave behind stale events for the following test. - processGeckoEvents(); - processInputConnectionEvents(); - } - } - - /** - * HidingInputConnectionTest performs tests on the hiding input in - * robocop_input.html. Any test that uses the normal input should be put in - * BasicInputConnectionTest. - */ - private class HidingInputConnectionTest extends InputConnectionTest { - @Override - public void test(final InputConnection ic, EditorInfo info) { - waitFor("focus change", new Condition() { - @Override - public boolean isSatisfied() { - return "".equals(getText(ic)); - } - }); - - // Bug 1254629, crash when hiding input during input. - ic.commitText("foo", 1); - assertTextAndSelectionAt("Can commit text (hiding)", ic, "foo", 3); - - ic.commitText("!", 1); - // The '!' key causes the input to hide in robocop_input.html, - // and there won't be a text/selection update as a result. - assertTextAndSelectionAt("Can handle hiding input", ic, "foo", 3); - - // Make sure we don't leave behind stale events for the following test. - processGeckoEvents(); - processInputConnectionEvents(); - } - } -} diff --git a/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/testInputUrlBar.java b/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/testInputUrlBar.java deleted file mode 100644 index c12ccef98..000000000 --- a/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/testInputUrlBar.java +++ /dev/null @@ -1,136 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -package org.mozilla.gecko.tests; - -import org.mozilla.gecko.Actions; -import org.mozilla.gecko.Element; -import org.mozilla.gecko.R; - -import android.widget.EditText; - -/** - * Basic test of text editing within the editing mode. - * - Enter some text, move the cursor around, and modifying some text. - * - Check that all edit entry text is selected after switching about:home tabs. - */ -public final class testInputUrlBar extends BaseTest { - private Element mUrlBarEditElement; - private EditText mUrlBarEditView; - - public void testInputUrlBar() { - blockForGeckoReady(); - - startEditingMode(); - assertUrlBarText(""); - - // Avoid any auto domain completion by using a prefix that matches - // nothing, including about: pages - mActions.sendKeys("zy"); - assertUrlBarText("zy"); - - mActions.sendKeys("cd"); - assertUrlBarText("zycd"); - - mActions.sendSpecialKey(Actions.SpecialKey.LEFT); - mActions.sendSpecialKey(Actions.SpecialKey.LEFT); - - // Inserting "" should not do anything. - mActions.sendKeys(""); - assertUrlBarText("zycd"); - - mActions.sendKeys("ef"); - assertUrlBarText("zyefcd"); - - mActions.sendSpecialKey(Actions.SpecialKey.RIGHT); - mActions.sendKeys("gh"); - assertUrlBarText("zyefcghd"); - - final EditText editText = mUrlBarEditView; - runOnUiThreadSync(new Runnable() { - @Override - public void run() { - // Select "ef" - editText.setSelection(2); - } - }); - mActions.sendKeys("op"); - assertUrlBarText("zyopefcghd"); - - runOnUiThreadSync(new Runnable() { - @Override - public void run() { - // Select "cg" - editText.setSelection(6, 8); - } - }); - mActions.sendKeys("qr"); - assertUrlBarText("zyopefqrhd"); - - runOnUiThreadSync(new Runnable() { - @Override - public void run() { - // Select "op" - editText.setSelection(4,2); - } - }); - mActions.sendKeys("st"); - assertUrlBarText("zystefqrhd"); - - runOnUiThreadSync(new Runnable() { - @Override - public void run() { - editText.selectAll(); - } - }); - mActions.sendKeys("uv"); - assertUrlBarText("uv"); - - // Dismiss the VKB - mSolo.goBack(); - - // Dismiss editing mode - mSolo.goBack(); - - waitForText(mStringHelper.TITLE_PLACE_HOLDER); - - // URL bar should have forgotten about "uv" text. - startEditingMode(); - assertUrlBarText(""); - - int width = mDriver.getGeckoWidth() / 2; - int y = mDriver.getGeckoHeight() / 2; - - // Slide to the right, force URL bar entry to lose input focus - mActions.drag(width, 0, y, y); - - // Select text and replace the content - mSolo.clickOnView(mUrlBarEditView); - mActions.sendKeys("yz"); - - String yz = getUrlBarText(); - mAsserter.ok("yz".equals(yz), "Is the URL bar text \"yz\"?", yz); - } - - private void startEditingMode() { - focusUrlBar(); - - mUrlBarEditElement = mDriver.findElement(getActivity(), R.id.url_edit_text); - final int id = mUrlBarEditElement.getId(); - mUrlBarEditView = (EditText) getActivity().findViewById(id); - } - - private String getUrlBarText() { - final String elementText = mUrlBarEditElement.getText(); - final String editText = mUrlBarEditView.getText().toString(); - mAsserter.is(editText, elementText, "Does URL bar editText == elementText?"); - - return editText; - } - - private void assertUrlBarText(String expectedText) { - String actualText = getUrlBarText(); - mAsserter.is(actualText, expectedText, "Does URL bar actualText == expectedText?"); - } -} diff --git a/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/testJarReader.java b/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/testJarReader.java deleted file mode 100644 index 9310599d3..000000000 --- a/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/testJarReader.java +++ /dev/null @@ -1,70 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -package org.mozilla.gecko.tests; - -import java.io.InputStream; - -import org.mozilla.gecko.AppConstants; -import org.mozilla.gecko.util.GeckoJarReader; - -import android.content.Context; - -/** - * A basic jar reader test. Tests reading a png from fennec's apk, as well - * as loading some invalid jar urls. - */ -public class testJarReader extends BaseTest { - public void testJarReader() { - // Invalid characters are escaped. - final String s = GeckoJarReader.computeJarURI("some[1].apk", "something/else"); - mAsserter.ok(!s.contains("["), "Illegal characters are escaped away.", null); - mAsserter.ok(!s.toLowerCase().contains("%2f"), "Path characters aren't escaped.", null); - - final Context context = getInstrumentation().getTargetContext().getApplicationContext(); - String appPath = getActivity().getApplication().getPackageResourcePath(); - mAsserter.isnot(appPath, null, "getPackageResourcePath is non-null"); - - // Test reading a file from a jar url that looks correct. - String url = "jar:file://" + appPath + "!/" + AppConstants.OMNIJAR_NAME; - InputStream stream = GeckoJarReader.getStream(context, "jar:" + url + "!/chrome/chrome/content/branding/favicon32.png"); - mAsserter.isnot(stream, null, "JarReader returned non-null for valid file in valid jar"); - - // Test looking for an non-existent file in a jar. - url = "jar:file://" + appPath + "!/" + AppConstants.OMNIJAR_NAME; - stream = GeckoJarReader.getStream(context, "jar:" + url + "!/chrome/chrome/content/branding/nonexistent_file.png"); - mAsserter.is(stream, null, "JarReader returned null for non-existent file in valid jar"); - - // Test looking for a file that doesn't exist in the APK. - url = "jar:file://" + appPath + "!/" + "BAD" + AppConstants.OMNIJAR_NAME; - stream = GeckoJarReader.getStream(context, "jar:" + url + "!/chrome/chrome/content/branding/favicon32.png"); - mAsserter.is(stream, null, "JarReader returned null for valid file in invalid jar file"); - - // Test looking for a file that doesn't exist in the APK. - // Bug 1174922, prefixed string / length error. - url = "jar:file://" + appPath + "!/" + AppConstants.OMNIJAR_NAME + "BAD"; - stream = GeckoJarReader.getStream(context, "jar:" + url + "!/chrome/chrome/content/branding/favicon32.png"); - mAsserter.is(stream, null, "JarReader returned null for valid file in other invalid jar file"); - - // Test looking for an jar with an invalid url. - url = "jar:file://" + appPath + "!" + "!/" + AppConstants.OMNIJAR_NAME; - stream = GeckoJarReader.getStream(context, "jar:" + url + "!/chrome/chrome/content/branding/nonexistent_file.png"); - mAsserter.is(stream, null, "JarReader returned null for bad jar url"); - - // Test looking for a file that doesn't exist on disk. - url = "jar:file://" + appPath + "BAD" + "!/" + AppConstants.OMNIJAR_NAME; - stream = GeckoJarReader.getStream(context, "jar:" + url + "!/chrome/chrome/content/branding/favicon32.png"); - mAsserter.is(stream, null, "JarReader returned null for a non-existent APK"); - - // This test completes very quickly. If it completes too soon, the - // minidumps directory may not be created before the process is - // taken down, causing bug 722166. - blockForGeckoReady(); - } - - private String getData(InputStream stream) { - return new java.util.Scanner(stream).useDelimiter("\\A").next(); - } - -} diff --git a/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/testJavascriptBridge.java b/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/testJavascriptBridge.java deleted file mode 100644 index 724b6b4ab..000000000 --- a/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/testJavascriptBridge.java +++ /dev/null @@ -1,69 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -package org.mozilla.gecko.tests; - -import static org.mozilla.gecko.tests.helpers.AssertionHelper.*; - -import org.json.JSONException; -import org.json.JSONObject; - -/** - * Tests the proper operation of JavascriptBridge and JavaBridge, - * which are used by tests for communication between Java and JS. - */ -public class testJavascriptBridge extends JavascriptBridgeTest { - - private static final String TEST_JS = "testJavascriptBridge.js"; - - private boolean syncCallReceived; - - public void testJavascriptBridge() { - blockForReadyAndLoadJS(TEST_JS); - getJS().syncCall("check_js_int_arg", 1); - } - - public void checkJavaIntArg(final int int2) { - // Async call from JS - fAssertEquals("Integer argument matches", 2, int2); - getJS().syncCall("check_js_double_arg", 3.0D); - } - - public void checkJavaDoubleArg(final double double4) { - // Async call from JS - fAssertEquals("Double argument matches", 4.0, double4); - getJS().syncCall("check_js_boolean_arg", false); - } - - public void checkJavaBooleanArg(final boolean booltrue) { - // Async call from JS - fAssertEquals("Boolean argument matches", true, booltrue); - getJS().syncCall("check_js_string_arg", "foo"); - } - - public void checkJavaStringArg(final String stringbar) throws JSONException { - // Async call from JS - fAssertEquals("String argument matches", "bar", stringbar); - final JSONObject obj = new JSONObject(); - obj.put("caller", "java"); - getJS().syncCall("check_js_object_arg", (JSONObject) obj); - } - - public void checkJavaObjectArg(final JSONObject obj) throws JSONException { - // Async call from JS - fAssertEquals("Object argument matches", "js", obj.getString("caller")); - getJS().syncCall("check_js_sync_call"); - } - - public void doJSSyncCall() { - // Sync call from JS - syncCallReceived = true; - getJS().asyncCall("respond_to_js_sync_call"); - } - - public void checkJSSyncCallReceived() { - fAssertTrue("Received sync call before end of test", syncCallReceived); - // End of test - } -} diff --git a/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/testLinkContextMenu.java b/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/testLinkContextMenu.java deleted file mode 100644 index 556ed0e07..000000000 --- a/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/testLinkContextMenu.java +++ /dev/null @@ -1,37 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -package org.mozilla.gecko.tests; - -public class testLinkContextMenu extends ContentContextMenuTest { - - // Test website strings - private static String LINK_PAGE_URL; - private static String BLANK_PAGE_URL; - private static final String LINK_PAGE_TITLE = "Big Link"; - - public void testLinkContextMenu() { - final String linkMenuItems [] = mStringHelper.CONTEXT_MENU_ITEMS_IN_NORMAL_TAB; - - blockForGeckoReady(); - - LINK_PAGE_URL=getAbsoluteUrl(mStringHelper.ROBOCOP_BIG_LINK_URL); - BLANK_PAGE_URL=getAbsoluteUrl(mStringHelper.ROBOCOP_BLANK_PAGE_01_URL); - loadUrlAndWait(LINK_PAGE_URL); - waitForText(LINK_PAGE_TITLE); - - verifyContextMenuItems(linkMenuItems); // Verify context menu items are correct - openTabFromContextMenu(linkMenuItems[0],2); // Test the "Open in New Tab" option - expecting 2 tabs: the original and the new one - openTabFromContextMenu(linkMenuItems[1],2); // Test the "Open in Private Tab" option - expecting only 2 tabs in normal mode - verifyCopyOption(linkMenuItems[2], BLANK_PAGE_URL); // Test the "Copy Link" option - verifyShareOption(linkMenuItems[3], LINK_PAGE_TITLE); // Test the "Share Link" option - verifyBookmarkLinkOption(linkMenuItems[4], BLANK_PAGE_URL); // Test the "Bookmark Link" option - } - - @Override - public void tearDown() throws Exception { - mDatabaseHelper.deleteBookmark(BLANK_PAGE_URL); - super.tearDown(); - } -} diff --git a/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/testLoad.java b/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/testLoad.java deleted file mode 100644 index e62bd7899..000000000 --- a/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/testLoad.java +++ /dev/null @@ -1,23 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -package org.mozilla.gecko.tests; - -/** - * A basic page load test. - * - loads a page - * - verifies it rendered properly - * - verifies the displayed url is correct - */ -public class testLoad extends PixelTest { - public void testLoad() { - String url = getAbsoluteUrl(mStringHelper.ROBOCOP_BOXES_URL); - - blockForGeckoReady(); - - loadAndVerifyBoxes(url); - - verifyUrl(url); - } -} diff --git a/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/testLoginsProvider.java b/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/testLoginsProvider.java deleted file mode 100644 index 10dde28cd..000000000 --- a/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/testLoginsProvider.java +++ /dev/null @@ -1,387 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -package org.mozilla.gecko.tests; - -import android.content.ContentProvider; -import android.content.ContentUris; -import android.content.ContentValues; -import android.database.Cursor; -import android.database.sqlite.SQLiteDatabase; -import android.net.Uri; - -import org.mozilla.gecko.db.BrowserContract; -import org.mozilla.gecko.db.BrowserContract.DeletedLogins; -import org.mozilla.gecko.db.BrowserContract.Logins; -import org.mozilla.gecko.db.BrowserContract.LoginsDisabledHosts; -import org.mozilla.gecko.db.LoginsProvider; - -import java.util.concurrent.Callable; - -import static org.mozilla.gecko.db.BrowserContract.CommonColumns._ID; -import static org.mozilla.gecko.db.BrowserContract.DeletedLogins.TABLE_DELETED_LOGINS; -import static org.mozilla.gecko.db.BrowserContract.Logins.TABLE_LOGINS; -import static org.mozilla.gecko.db.BrowserContract.LoginsDisabledHosts.TABLE_DISABLED_HOSTS; - -public class testLoginsProvider extends ContentProviderTest { - - private static final String DB_NAME = "browser.db"; - - private final TestCase[] TESTS_TO_RUN = { - new InsertLoginsTest(), - new UpdateLoginsTest(), - new DeleteLoginsTest(), - new InsertDeletedLoginsTest(), - new InsertDeletedLoginsFailureTest(), - new DisabledHostsInsertTest(), - new DisabledHostsInsertFailureTest(), - new InsertLoginsWithDefaultValuesTest(), - new InsertLoginsWithDuplicateGuidFailureTest(), - new DeleteLoginsByNonExistentGuidTest(), - }; - - /** - * Factory function that makes new LoginsProvider instances. - *

- * We want a fresh provider each test, so this should be invoked in - * setUp before each individual test. - */ - private static final Callable sProviderFactory = new Callable() { - @Override - public ContentProvider call() { - return new LoginsProvider(); - } - }; - - @Override - public void setUp() throws Exception { - super.setUp(sProviderFactory, BrowserContract.LOGINS_AUTHORITY, DB_NAME); - for (TestCase test: TESTS_TO_RUN) { - mTests.add(test); - } - } - - public void testLoginProviderTests() throws Exception { - for (Runnable test : mTests) { - final String testName = test.getClass().getSimpleName(); - setTestName(testName); - ensureEmptyDatabase(); - mAsserter.dumpLog("testLoginsProvider: Database empty - Starting " + testName + "."); - test.run(); - } - } - - /** - * Wipe DB. - */ - private void ensureEmptyDatabase() { - getWritableDatabase(Logins.CONTENT_URI).delete(TABLE_LOGINS, null, null); - getWritableDatabase(DeletedLogins.CONTENT_URI).delete(TABLE_DELETED_LOGINS, null, null); - getWritableDatabase(LoginsDisabledHosts.CONTENT_URI).delete(TABLE_DISABLED_HOSTS, null, null); - } - - private SQLiteDatabase getWritableDatabase(Uri uri) { - Uri testUri = appendUriParam(uri, BrowserContract.PARAM_IS_TEST, "1"); - DelegatingTestContentProvider delegateProvider = (DelegatingTestContentProvider) mProvider; - LoginsProvider loginsProvider = (LoginsProvider) delegateProvider.getTargetProvider(); - return loginsProvider.getWritableDatabaseForTesting(testUri); - } - - /** - * LoginsProvider insert logins test. - */ - private class InsertLoginsTest extends TestCase { - @Override - public void test() throws Exception { - ContentValues contentValues = createLogin("http://www.example.com", "http://www.example.com", - "http://www.example.com", "username1", "password1", "username1", "password1", "guid1"); - long id = ContentUris.parseId(mProvider.insert(BrowserContract.Logins.CONTENT_URI, contentValues)); - verifyLoginExists(contentValues, id); - Cursor cursor = mProvider.query(Logins.CONTENT_URI, null, Logins.GUID + " = ?", new String[] { "guid1" }, null); - verifyRowMatches(contentValues, cursor, "logins found"); - - // Empty ("") encrypted username and password are valid. - contentValues = createLogin("http://www.example.com", "http://www.example.com", - "http://www.example.com", "username1", "password1", "", "", "guid2"); - id = ContentUris.parseId(mProvider.insert(BrowserContract.Logins.CONTENT_URI, contentValues)); - verifyLoginExists(contentValues, id); - cursor = mProvider.query(Logins.CONTENT_URI, null, Logins.GUID + " = ?", new String[] { "guid2" }, null); - verifyRowMatches(contentValues, cursor, "logins found"); - } - } - - /** - * LoginsProvider updates logins test. - */ - private class UpdateLoginsTest extends TestCase { - @Override - public void test() throws Exception { - final String guid1 = "guid1"; - ContentValues contentValues = createLogin("http://www.example.com", "http://www.example.com", - "http://www.example.com", "username1", "password1", "username1", "password1", guid1); - long timeBeforeCreated = System.currentTimeMillis(); - long id = ContentUris.parseId(mProvider.insert(BrowserContract.Logins.CONTENT_URI, contentValues)); - long timeAfterCreated = System.currentTimeMillis(); - verifyLoginExists(contentValues, id); - - Cursor cursor = getLoginById(id); - try { - mAsserter.ok(cursor.moveToFirst(), "cursor is not empty", ""); - verifyBounded(timeBeforeCreated, cursor.getLong(cursor.getColumnIndexOrThrow(Logins.TIME_CREATED)), timeAfterCreated); - } finally { - cursor.close(); - } - - contentValues.put(BrowserContract.Logins.ENCRYPTED_USERNAME, "username2"); - contentValues.put(Logins.ENCRYPTED_PASSWORD, "password2"); - - Uri updateUri = Logins.CONTENT_URI.buildUpon().appendPath(String.valueOf(id)).build(); - int numUpdated = mProvider.update(updateUri, contentValues, null, null); - mAsserter.is(1, numUpdated, "Correct number updated"); - verifyLoginExists(contentValues, id); - - contentValues.put(BrowserContract.Logins.ENCRYPTED_USERNAME, "username1"); - contentValues.put(Logins.ENCRYPTED_PASSWORD, "password1"); - - updateUri = Logins.CONTENT_URI; - numUpdated = mProvider.update(updateUri, contentValues, Logins.GUID + " = ?", new String[]{guid1}); - mAsserter.is(1, numUpdated, "Correct number updated"); - verifyLoginExists(contentValues, id); - } - } - - /** - * LoginsProvider deletion logins test. - * - inserts a new logins - * - deletes the logins and verify deleted-logins table has entry for deleted guid. - */ - private class DeleteLoginsTest extends TestCase { - @Override - public void test() throws Exception { - final String guid1 = "guid1"; - ContentValues contentValues = createLogin("http://www.example.com", "http://www.example.com", - "http://www.example.com", "username1", "password1", "username1", "password1", guid1); - long id = ContentUris.parseId(mProvider.insert(Logins.CONTENT_URI, contentValues)); - verifyLoginExists(contentValues, id); - - Uri deletedUri = Logins.CONTENT_URI.buildUpon().appendPath(String.valueOf(id)).build(); - int numDeleted = mProvider.delete(deletedUri, null, null); - mAsserter.is(1, numDeleted, "Correct number deleted"); - verifyNoRowExists(Logins.CONTENT_URI, "No login entry found"); - - contentValues = new ContentValues(); - contentValues.put(DeletedLogins.GUID, guid1); - Cursor cursor = mProvider.query(DeletedLogins.CONTENT_URI, null, null, null, null); - verifyRowMatches(contentValues, cursor, "deleted-login found"); - cursor = mProvider.query(DeletedLogins.CONTENT_URI, null, DeletedLogins.GUID + " = ?", new String[] { guid1 }, null); - verifyRowMatches(contentValues, cursor, "deleted-login found"); - } - } - - /** - * LoginsProvider re-insert logins test. - * - inserts a row into deleted-logins - * - insert the same login (matching guid) and verify deleted-logins table is empty. - */ - private class InsertDeletedLoginsTest extends TestCase { - @Override - public void test() throws Exception { - ContentValues contentValues = new ContentValues(); - contentValues.put(DeletedLogins.GUID, "guid1"); - long id = ContentUris.parseId(mProvider.insert(DeletedLogins.CONTENT_URI, contentValues)); - final Uri insertedUri = DeletedLogins.CONTENT_URI.buildUpon().appendPath(String.valueOf(id)).build(); - Cursor cursor = mProvider.query(insertedUri, null, null, null, null); - verifyRowMatches(contentValues, cursor, "deleted-login found"); - verifyNoRowExists(BrowserContract.Logins.CONTENT_URI, "No login entry found"); - - contentValues = createLogin("http://www.example.com", "http://www.example.com", - "http://www.example.com", "username1", "password1", "username1", "password1", "guid1"); - id = ContentUris.parseId(mProvider.insert(Logins.CONTENT_URI, contentValues)); - verifyLoginExists(contentValues, id); - verifyNoRowExists(DeletedLogins.CONTENT_URI, "No deleted-login entry found"); - } - } - - /** - * LoginsProvider insert Deleted logins test. - * - inserts a row into deleted-login without GUID. - */ - private class InsertDeletedLoginsFailureTest extends TestCase { - @Override - public void test() throws Exception { - ContentValues contentValues = new ContentValues(); - try { - mProvider.insert(DeletedLogins.CONTENT_URI, contentValues); - fail("Failed to throw IllegalArgumentException while missing GUID"); - } catch (Exception e) { - mAsserter.is(e.getClass(), IllegalArgumentException.class, "IllegalArgumentException thrown for invalid GUID"); - } - } - } - - /** - * LoginsProvider disabled host test. - * - inserts a disabled-host - * - delete the inserted disabled-host and verify disabled-hosts table is empty. - */ - private class DisabledHostsInsertTest extends TestCase { - @Override - public void test() throws Exception { - final String hostname = "localhost"; - final ContentValues contentValues = new ContentValues(); - contentValues.put(LoginsDisabledHosts.HOSTNAME, hostname); - mProvider.insert(LoginsDisabledHosts.CONTENT_URI, contentValues); - final Uri insertedUri = LoginsDisabledHosts.CONTENT_URI.buildUpon().appendPath("hostname").appendPath(hostname).build(); - final Cursor cursor = mProvider.query(insertedUri, null, null, null, null); - verifyRowMatches(contentValues, cursor, "disabled-hosts found"); - - final Uri deletedUri = LoginsDisabledHosts.CONTENT_URI.buildUpon().appendPath("hostname").appendPath(hostname).build(); - final int numDeleted = mProvider.delete(deletedUri, null, null); - mAsserter.is(1, numDeleted, "Correct number deleted"); - verifyNoRowExists(LoginsDisabledHosts.CONTENT_URI, "No disabled-hosts entry found"); - } - } - - /** - * LoginsProvider disabled host insert failure testcase. - * - inserts a disabled-host without providing hostname - */ - private class DisabledHostsInsertFailureTest extends TestCase { - @Override - public void test() throws Exception { - final String hostname = "localhost"; - final ContentValues contentValues = new ContentValues(); - try { - mProvider.insert(LoginsDisabledHosts.CONTENT_URI, contentValues); - fail("Failed to throw IllegalArgumentException while missing hostname"); - } catch (Exception e) { - mAsserter.is(e.getClass(), IllegalArgumentException.class, "IllegalArgumentException thrown for invalid hostname"); - } - } - } - - /** - * LoginsProvider login insertion with default values test. - * - insert a login missing GUID, FORM_SUBMIT_URL, HTTP_REALM and verify default values are set. - */ - private class InsertLoginsWithDefaultValuesTest extends TestCase { - @Override - protected void test() throws Exception { - ContentValues contentValues = createLogin("http://www.example.com", "http://www.example.com", - "http://www.example.com", "username1", "password1", "username1", "password1", null); - // Remove GUID, HTTP_REALM, FORM_SUBMIT_URL from content values - contentValues.remove(Logins.GUID); - contentValues.remove(Logins.FORM_SUBMIT_URL); - contentValues.remove(Logins.HTTP_REALM); - - long id = ContentUris.parseId(mProvider.insert(BrowserContract.Logins.CONTENT_URI, contentValues)); - Cursor cursor = getLoginById(id); - assertNotNull(cursor); - cursor.moveToFirst(); - - mAsserter.isnot(cursor.getString(cursor.getColumnIndex(Logins.GUID)), null, "GUID is not null"); - mAsserter.is(cursor.getString(cursor.getColumnIndex(Logins.HTTP_REALM)), null, "HTTP_REALM is not null"); - mAsserter.is(cursor.getString(cursor.getColumnIndex(Logins.FORM_SUBMIT_URL)), null, "FORM_SUBMIT_URL is not null"); - mAsserter.isnot(cursor.getString(cursor.getColumnIndex(Logins.TIME_LAST_USED)), null, "TIME_LAST_USED is not null"); - mAsserter.isnot(cursor.getString(cursor.getColumnIndex(Logins.TIME_CREATED)), null, "TIME_CREATED is not null"); - mAsserter.isnot(cursor.getString(cursor.getColumnIndex(Logins.TIME_PASSWORD_CHANGED)), null, "TIME_PASSWORD_CHANGED is not null"); - mAsserter.is(cursor.getString(cursor.getColumnIndex(Logins.ENC_TYPE)), "0", "ENC_TYPE is 0"); - mAsserter.is(cursor.getString(cursor.getColumnIndex(Logins.TIMES_USED)), "0", "TIMES_USED is 0"); - - // Verify other values. - verifyRowMatches(contentValues, cursor, "Updated login found"); - } - } - - /** - * LoginsProvider login insertion with duplicate GUID test. - * - insert two different logins with same GUID and verify that only one login exists. - */ - private class InsertLoginsWithDuplicateGuidFailureTest extends TestCase { - @Override - protected void test() throws Exception { - final String guid = "guid1"; - ContentValues contentValues = createLogin("http://www.example.com", "http://www.example.com", - "http://www.example.com", "username1", "password1", "username1", "password1", guid); - long id1 = ContentUris.parseId(mProvider.insert(BrowserContract.Logins.CONTENT_URI, contentValues)); - verifyLoginExists(contentValues, id1); - - // Insert another login with duplicate GUID. - contentValues = createLogin("http://www.example2.com", "http://www.example2.com", - "http://www.example2.com", "username2", "password2", "username2", "password2", guid); - Uri insertUri = mProvider.insert(Logins.CONTENT_URI, contentValues); - mAsserter.is(insertUri, null, "Duplicate Guid insertion id1"); - - // Verify login with id1 still exists. - verifyLoginExists(contentValues, id1); - } - } - - /** - * LoginsProvider deletion by non-existent GUID test. - * - delete a login with random GUID and verify that no entry was deleted. - */ - private class DeleteLoginsByNonExistentGuidTest extends TestCase { - @Override - protected void test() throws Exception { - Uri deletedUri = Logins.CONTENT_URI; - int numDeleted = mProvider.delete(deletedUri, Logins.GUID + "= ?", new String[] { "guid1" }); - mAsserter.is(0, numDeleted, "Correct number deleted"); - } - } - - private void verifyBounded(long left, long middle, long right) { - mAsserter.ok(left <= middle, "Left <= middle", left + " <= " + middle); - mAsserter.ok(middle <= right, "Middle <= right", middle + " <= " + right); - } - - private Cursor getById(Uri uri, long id, String[] projection) { - return mProvider.query(uri, projection, - _ID + " = ?", - new String[] { String.valueOf(id) }, - null); - } - - private Cursor getLoginById(long id) { - return getById(Logins.CONTENT_URI, id, null); - } - - private void verifyLoginExists(ContentValues contentValues, long id) { - Cursor cursor = getLoginById(id); - verifyRowMatches(contentValues, cursor, "Updated login found"); - } - - private void verifyRowMatches(ContentValues contentValues, Cursor cursor, String name) { - try { - mAsserter.ok(cursor.moveToFirst(), name, "cursor is not empty"); - CursorMatches(cursor, contentValues); - } finally { - cursor.close(); - } - } - - private void verifyNoRowExists(Uri contentUri, String name) { - Cursor cursor = mProvider.query(contentUri, null, null, null, null); - try { - mAsserter.is(0, cursor.getCount(), name); - } finally { - cursor.close(); - } - } - - private ContentValues createLogin(String hostname, String httpRealm, String formSubmitUrl, - String usernameField, String passwordField, String encryptedUsername, - String encryptedPassword, String guid) { - final ContentValues values = new ContentValues(); - values.put(Logins.HOSTNAME, hostname); - values.put(Logins.HTTP_REALM, httpRealm); - values.put(Logins.FORM_SUBMIT_URL, formSubmitUrl); - values.put(Logins.USERNAME_FIELD, usernameField); - values.put(Logins.PASSWORD_FIELD, passwordField); - values.put(Logins.ENCRYPTED_USERNAME, encryptedUsername); - values.put(Logins.ENCRYPTED_PASSWORD, encryptedPassword); - values.put(Logins.GUID, guid); - return values; - } -} diff --git a/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/testMailToContextMenu.java b/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/testMailToContextMenu.java deleted file mode 100644 index af674f441..000000000 --- a/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/testMailToContextMenu.java +++ /dev/null @@ -1,26 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -package org.mozilla.gecko.tests; - -public class testMailToContextMenu extends ContentContextMenuTest { - - // Test website strings - private static String MAILTO_PAGE_URL; - private static final String mailtoMenuItems [] = {"Copy Email Address", "Share Email Address"}; - - public void testMailToContextMenu() { - final String MAILTO_PAGE_TITLE = mStringHelper.ROBOCOP_BIG_MAILTO_TITLE; - - blockForGeckoReady(); - - MAILTO_PAGE_URL=getAbsoluteUrl(mStringHelper.ROBOCOP_BIG_MAILTO_URL); - loadUrlAndWait(MAILTO_PAGE_URL); - waitForText(MAILTO_PAGE_TITLE); - - verifyContextMenuItems(mailtoMenuItems); - verifyCopyOption(mailtoMenuItems[0], "foo.bar@example.com"); // Test the "Copy Email Address" option - verifyShareOption(mailtoMenuItems[1], MAILTO_PAGE_TITLE); // Test the "Share Email Address" option - } -} diff --git a/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/testNativeCrypto.java b/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/testNativeCrypto.java deleted file mode 100644 index 2ae2bb532..000000000 --- a/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/testNativeCrypto.java +++ /dev/null @@ -1,288 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -package org.mozilla.gecko.tests; - -import static org.mozilla.gecko.tests.helpers.AssertionHelper.fAssertArrayEquals; -import static org.mozilla.gecko.tests.helpers.AssertionHelper.fAssertEquals; -import static org.mozilla.gecko.tests.helpers.AssertionHelper.fAssertNotNull; -import static org.mozilla.gecko.tests.helpers.AssertionHelper.fFail; - -import java.io.ByteArrayInputStream; -import java.io.IOException; -import java.io.UnsupportedEncodingException; -import java.security.GeneralSecurityException; -import java.security.MessageDigest; -import java.security.NoSuchAlgorithmException; - -import org.mozilla.gecko.background.nativecode.NativeCrypto; -import org.mozilla.gecko.sync.Utils; -import org.mozilla.gecko.tests.helpers.GeckoHelper; - -import android.os.SystemClock; - -/** - * Tests the Java wrapper over native implementations of crypto code. Test vectors from: - * * PBKDF2SHA256: - * - - - - * SHA-1: - - - */ -public class testNativeCrypto extends UITest { - private final static String LOGTAG = "testNativeCrypto"; - - /** - * Robocop supports only a single test function per test class. Therefore, we - * have a single top-level test function that dispatches to sub-tests, - * accepting that we might fail part way through the cycle. Proper JUnit 3 - * testing can't land soon enough! - * - * @throws Exception - */ - public void test() throws Exception { - // This test could complete very quickly. If it completes too soon, the - // minidumps directory may not be created before the process is - // taken down, causing bug 722166. But we can't run the test and then block - // for Gecko:Ready, since it may have arrived before we block. So we wait. - // Again, JUnit 3 can't land soon enough! - GeckoHelper.blockForReady(); - - _testPBKDF2SHA256A(); - _testPBKDF2SHA256B(); - _testPBKDF2SHA256C(); - _testPBKDF2SHA256scryptA(); - _testPBKDF2SHA256scryptB(); - _testPBKDF2SHA256InvalidLenArg(); - - _testSHA1(); - _testSHA1AgainstMessageDigest(); - - _testSHA256(); - _testSHA256MultiPart(); - _testSHA256AgainstMessageDigest(); - _testSHA256WithMultipleUpdatesFromStream(); - } - - public void _testPBKDF2SHA256A() throws UnsupportedEncodingException, GeneralSecurityException { - final String p = "password"; - final String s = "salt"; - final int dkLen = 32; - - checkPBKDF2SHA256(p, s, 1, dkLen, "120fb6cffcf8b32c43e7225256c4f837a86548c92ccc35480805987cb70be17b"); - checkPBKDF2SHA256(p, s, 4096, dkLen, "c5e478d59288c841aa530db6845c4c8d962893a001ce4e11a4963873aa98134a"); - } - - public void _testPBKDF2SHA256B() throws UnsupportedEncodingException, GeneralSecurityException { - final String p = "passwordPASSWORDpassword"; - final String s = "saltSALTsaltSALTsaltSALTsaltSALTsalt"; - final int dkLen = 40; - - checkPBKDF2SHA256(p, s, 4096, dkLen, "348c89dbcbd32b2f32d814b8116e84cf2b17347ebc1800181c4e2a1fb8dd53e1c635518c7dac47e9"); - } - - public void _testPBKDF2SHA256scryptA() throws UnsupportedEncodingException, GeneralSecurityException { - final String p = "passwd"; - final String s = "salt"; - final int dkLen = 64; - - checkPBKDF2SHA256(p, s, 1, dkLen, "55ac046e56e3089fec1691c22544b605f94185216dde0465e68b9d57c20dacbc49ca9cccf179b645991664b39d77ef317c71b845b1e30bd509112041d3a19783"); - } - - public void _testPBKDF2SHA256scryptB() throws UnsupportedEncodingException, GeneralSecurityException { - final String p = "Password"; - final String s = "NaCl"; - final int dkLen = 64; - - checkPBKDF2SHA256(p, s, 80000, dkLen, "4ddcd8f60b98be21830cee5ef22701f9641a4418d04c0414aeff08876b34ab56a1d425a1225833549adb841b51c9b3176a272bdebba1d078478f62b397f33c8d"); - } - - public void _testPBKDF2SHA256C() throws UnsupportedEncodingException, GeneralSecurityException { - final String p = "pass\0word"; - final String s = "sa\0lt"; - final int dkLen = 16; - - checkPBKDF2SHA256(p, s, 4096, dkLen, "89b69d0516f829893c696226650a8687"); - } - - public void _testPBKDF2SHA256InvalidLenArg() throws UnsupportedEncodingException, GeneralSecurityException { - final String p = "password"; - final String s = "salt"; - final int c = 1; - final int dkLen = -1; // Should always be positive. - - try { - final byte[] key = NativeCrypto.pbkdf2SHA256(p.getBytes("US-ASCII"), s.getBytes("US-ASCII"), c, dkLen); - fFail("Expected sha256 to throw with negative dkLen argument."); - } catch (IllegalArgumentException e) { } // Expected. - } - - private void _testSHA1() throws UnsupportedEncodingException { - final String[] inputs = new String[] { - "abc", - "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq", - "" // To be filled in below. - }; - final String baseStr = "01234567"; - final int repetitions = 80; - final StringBuilder builder = new StringBuilder(baseStr.length() * repetitions); - for (int i = 0; i < 80; ++i) { - builder.append(baseStr); - } - inputs[2] = builder.toString(); - - final String[] expecteds = new String[] { - "a9993e364706816aba3e25717850c26c9cd0d89d", - "84983e441c3bd26ebaae4aa1f95129e5e54670f1", - "dea356a2cddd90c7a7ecedc5ebb563934f460452" - }; - - for (int i = 0; i < inputs.length; ++i) { - final byte[] input = inputs[i].getBytes("US-ASCII"); - final String expected = expecteds[i]; - - final byte[] actual = NativeCrypto.sha1(input); - fAssertNotNull("Hashed value is non-null", actual); - assertExpectedBytes(expected, actual); - } - } - - /** - * Test to ensure the output of our SHA1 algo is the same as MessageDigest's. This is important - * because we intend to replace MessageDigest in FHR with this SHA-1 algo (bug 959652). - */ - private void _testSHA1AgainstMessageDigest() throws UnsupportedEncodingException, - NoSuchAlgorithmException { - final String[] inputs = { - "password", - "saranghae", - "aoeusnthaoeusnthaoeusnth \0 12345098765432109876_!" - }; - - final MessageDigest digest = MessageDigest.getInstance("SHA-1"); - for (final String input : inputs) { - final byte[] inputBytes = input.getBytes("US-ASCII"); - - final byte[] mdBytes = digest.digest(inputBytes); - final byte[] ourBytes = NativeCrypto.sha1(inputBytes); - fAssertArrayEquals("MessageDigest hash is the same as NativeCrypto SHA-1 hash", mdBytes, ourBytes); - } - } - - private void _testSHA256() throws UnsupportedEncodingException { - final String[] inputs = new String[] { - "abc", - "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq", - "" // To be filled in below. - }; - final String baseStr = "01234567"; - final int repetitions = 80; - final StringBuilder builder = new StringBuilder(baseStr.length() * repetitions); - for (int i = 0; i < repetitions; ++i) { - builder.append(baseStr); - } - inputs[2] = builder.toString(); - - final String[] expecteds = new String[] { - "ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad", - "248d6a61d20638b8e5c026930c3e6039a33ce45964ff2167f6ecedd419db06c1", - "594847328451bdfa85056225462cc1d867d877fb388df0ce35f25ab5562bfbb5" - }; - - for (int i = 0; i < inputs.length; ++i) { - final byte[] input = inputs[i].getBytes("US-ASCII"); - final String expected = expecteds[i]; - - final byte[] ctx = NativeCrypto.sha256init(); - NativeCrypto.sha256update(ctx, input, input.length); - final byte[] actual = NativeCrypto.sha256finalize(ctx); - fAssertNotNull("Hashed value is non-null", actual); - assertExpectedBytes(expected, actual); - } - } - - private void _testSHA256MultiPart() throws UnsupportedEncodingException { - final String input = "01234567"; - final int repetitions = 80; - final String expected = "594847328451bdfa85056225462cc1d867d877fb388df0ce35f25ab5562bfbb5"; - - final byte[] inputBytes = input.getBytes("US-ASCII"); - final byte[] ctx = NativeCrypto.sha256init(); - for (int i = 0; i < repetitions; ++i) { - NativeCrypto.sha256update(ctx, inputBytes, inputBytes.length); - } - final byte[] actual = NativeCrypto.sha256finalize(ctx); - fAssertNotNull("Hashed value is non-null", actual); - assertExpectedBytes(expected, actual); - } - - private void _testSHA256AgainstMessageDigest() throws UnsupportedEncodingException, - NoSuchAlgorithmException { - final String[] inputs = { - "password", - "saranghae", - "aoeusnthaoeusnthaoeusnth \0 12345098765432109876_!" - }; - - final MessageDigest digest = MessageDigest.getInstance("SHA-256"); - for (final String input : inputs) { - final byte[] inputBytes = input.getBytes("US-ASCII"); - - final byte[] mdBytes = digest.digest(inputBytes); - - final byte[] ctx = NativeCrypto.sha256init(); - NativeCrypto.sha256update(ctx, inputBytes, inputBytes.length); - final byte[] ourBytes = NativeCrypto.sha256finalize(ctx); - fAssertArrayEquals("MessageDigest hash is the same as NativeCrypto SHA-256 hash", mdBytes, ourBytes); - } - } - - private void _testSHA256WithMultipleUpdatesFromStream() throws UnsupportedEncodingException { - final String input = "HelloWorldThisIsASuperLongStringThatIsReadAsAStreamOfBytes"; - final ByteArrayInputStream stream = new ByteArrayInputStream(input.getBytes("UTF-8")); - final String expected = "8b5cb76b80f7eb6fb83ee138bfd31e2922e71dd245daa21a8d9876e8dee9eef5"; - - byte[] buffer = new byte[10]; - final byte[] ctx = NativeCrypto.sha256init(); - int c; - - try { - while ((c = stream.read(buffer)) != -1) { - NativeCrypto.sha256update(ctx, buffer, c); - } - final byte[] actual = NativeCrypto.sha256finalize(ctx); - fAssertNotNull("Hashed value is non-null", actual); - assertExpectedBytes(expected, actual); - } catch (IOException e) { - fFail("IOException while reading stream"); - } - } - - private void checkPBKDF2SHA256(String p, String s, int c, int dkLen, final String expectedStr) - throws GeneralSecurityException, UnsupportedEncodingException { - final long start = SystemClock.elapsedRealtime(); - - final byte[] key = NativeCrypto.pbkdf2SHA256(p.getBytes("US-ASCII"), s.getBytes("US-ASCII"), c, dkLen); - fAssertNotNull("Hash result is non-null", key); - - final long end = SystemClock.elapsedRealtime(); - dumpLog(LOGTAG, "SHA-256 " + c + " took " + (end - start) + "ms"); - - if (expectedStr == null) { - return; - } - - fAssertEquals("Hash result is the appropriate length", dkLen, - Utils.hex2Byte(expectedStr).length); - assertExpectedBytes(expectedStr, key); - } - - private void assertExpectedBytes(final String expectedStr, byte[] key) { - fAssertEquals("Expected string matches hash result", expectedStr, Utils.byte2Hex(key)); - final byte[] expected = Utils.hex2Byte(expectedStr); - - fAssertEquals("Expected byte array length matches key length", expected.length, key.length); - fAssertArrayEquals("Expected byte array matches key byte array", expected, key); - } -} diff --git a/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/testNewTab.java b/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/testNewTab.java deleted file mode 100644 index d9b014c1a..000000000 --- a/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/testNewTab.java +++ /dev/null @@ -1,65 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -package org.mozilla.gecko.tests; - -import org.mozilla.gecko.Element; -import org.mozilla.gecko.R; - -import android.app.Activity; -import android.view.View; - -import com.robotium.solo.Condition; - -/* A simple test that creates 2 new tabs and checks that the tab count increases. */ -public class testNewTab extends BaseTest { - private Element tabCount = null; - private Element tabs = null; - private final Element closeTab = null; - private int tabCountInt = 0; - - public void testNewTab() { - String url = getAbsoluteUrl(mStringHelper.ROBOCOP_BLANK_PAGE_01_URL); - String url2 = getAbsoluteUrl(mStringHelper.ROBOCOP_BLANK_PAGE_02_URL); - - blockForGeckoReady(); - - Activity activity = getActivity(); - tabCount = mDriver.findElement(activity, R.id.tabs_counter); - tabs = mDriver.findElement(activity, R.id.tabs); - mAsserter.ok(tabCount != null && tabs != null, - "Checking elements", "all elements present"); - - int expectedTabCount = 1; - getTabCount(expectedTabCount); - mAsserter.is(tabCountInt, expectedTabCount, "Initial number of tabs correct"); - - addTab(url); - expectedTabCount++; - getTabCount(expectedTabCount); - mAsserter.is(tabCountInt, expectedTabCount, "Number of tabs increased"); - - addTab(url2); - expectedTabCount++; - getTabCount(expectedTabCount); - mAsserter.is(tabCountInt, expectedTabCount, "Number of tabs increased"); - - // cleanup: close all opened tabs - closeAddedTabs(); - } - - private void getTabCount(final int expected) { - waitForCondition(new Condition() { - @Override - public boolean isSatisfied() { - String newTabCountText = tabCount.getText(); - tabCountInt = Integer.parseInt(newTabCountText); - if (tabCountInt == expected) { - return true; - } - return false; - } - }, MAX_WAIT_MS); - } -} diff --git a/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/testOSLocale.java b/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/testOSLocale.java deleted file mode 100644 index 434594fee..000000000 --- a/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/testOSLocale.java +++ /dev/null @@ -1,137 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -package org.mozilla.gecko.tests; - -import java.util.Locale; - -import org.mozilla.gecko.BrowserLocaleManager; -import org.mozilla.gecko.GeckoSharedPrefs; -import org.mozilla.gecko.GeckoThread; -import org.mozilla.gecko.Locales; -import org.mozilla.gecko.PrefsHelper; - -import android.content.SharedPreferences; - - -public class testOSLocale extends BaseTest { - @Override - public void setUp() throws Exception { - super.setUp(); - - // Clear per-profile SharedPreferences as a workaround for Bug 1069687. - // We're trying to exercise logic that only applies on first onCreate! - // We can't rely on this occurring prior to the first broadcast, though, - // so see the main test method for more logic. - final String profileName = getTestProfile().getName(); - mAsserter.info("Setup", "Clearing pref in " + profileName + "."); - GeckoSharedPrefs.forProfileName(getActivity(), profileName) - .edit() - .remove("osLocale") - .apply(); - } - - public static class PrefState extends PrefsHelper.PrefHandlerBase { - private static final String PREF_LOCALE_OS = "intl.locale.os"; - private static final String PREF_ACCEPT_LANG = "intl.accept_languages"; - - private static final String[] TO_FETCH = {PREF_LOCALE_OS, PREF_ACCEPT_LANG}; - - public volatile String osLocale; - public volatile String acceptLanguages; - - private final Object waiter = new Object(); - - public void fetch() throws InterruptedException { - // Wait for any pending changes to have taken. Bug 1092580. - GeckoThread.waitOnGecko(); - synchronized (waiter) { - PrefsHelper.getPrefs(TO_FETCH, this); - waiter.wait(MAX_WAIT_MS); - } - } - - @Override - public void prefValue(String pref, String value) { - switch (pref) { - case PREF_LOCALE_OS: - osLocale = value; - return; - case PREF_ACCEPT_LANG: - acceptLanguages = value; - return; - } - } - - @Override - public void finish() { - synchronized (waiter) { - waiter.notify(); - } - } - } - - public void testOSLocale() throws Exception { - blockForDelayedStartup(); - - final SharedPreferences prefs = GeckoSharedPrefs.forProfile(getActivity()); - final PrefState state = new PrefState(); - - state.fetch(); - - // We don't know at this point whether we were run against a dirty profile or not. - // - // If we cleared the pref above prior to BrowserApp's delayed init, or our Gecko - // profile has been used before, then we're already going to be set up for en-US. - // - // If we cleared the pref after the initial broadcast, and our Android-side profile - // has been used before but the Gecko profile is clean, then the Gecko prefs won't - // have been set. - // - // Instead, we always send a new locale code, and see what we get. - final Locale fr = Locales.parseLocaleCode("fr"); - BrowserLocaleManager.storeAndNotifyOSLocale(prefs, fr); - - state.fetch(); - - mAsserter.is(state.osLocale, "fr", "We're in fr."); - - // Now we can see what the expected Accept-Languages header should be. - // The OS locale is 'fr', so we have our app locale (en-US), - // the OS locale (fr), then any remaining fallbacks from intl.properties. - mAsserter.is(state.acceptLanguages, "en-us,fr,en", "We have the default en-US+fr Accept-Languages."); - - // Now set the app locale to be es-ES. - BrowserLocaleManager.getInstance().setSelectedLocale(getActivity(), "es-ES"); - - state.fetch(); - - mAsserter.is(state.osLocale, "fr", "We're still in fr."); - - // The correct set here depends on whether the - // browser was built with multiple locales or not. - // This is exasperating, but hey. - final boolean isMultiLocaleBuild = false; - - // This never changes. - final String SELECTED_LOCALES = "es-es,fr,"; - - // Expected, from es-ES's intl.properties: - final String EXPECTED = SELECTED_LOCALES + - (isMultiLocaleBuild ? "es,en-us,en" : // Expected, from es-ES's intl.properties. - "en-us,en"); // Expected, from en-US (the default). - - mAsserter.is(state.acceptLanguages, EXPECTED, "We have the right es-ES+fr Accept-Languages for this build."); - - // And back to en-US. - final Locale en_US = Locales.parseLocaleCode("en-US"); - BrowserLocaleManager.storeAndNotifyOSLocale(prefs, en_US); - BrowserLocaleManager.getInstance().resetToSystemLocale(getActivity()); - - state.fetch(); - - mAsserter.is(state.osLocale, "en-US", "We're in en-US."); - mAsserter.is(state.acceptLanguages, "en-us,en", "We have the default processed en-US Accept-Languages."); - } -} \ No newline at end of file diff --git a/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/testPanCorrectness.java b/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/testPanCorrectness.java deleted file mode 100644 index e7d402607..000000000 --- a/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/testPanCorrectness.java +++ /dev/null @@ -1,49 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -package org.mozilla.gecko.tests; - -import org.mozilla.gecko.Actions; -import org.mozilla.gecko.PaintedSurface; - -/** - * A basic panning correctness test. - * - Loads a page and verifies it draws - * - drags page upwards by 100 pixels and verifies it draws - * - drags page leftwards by 100 pixels and verifies it draws - */ -public class testPanCorrectness extends PixelTest { - public void testPanCorrectness() { - String url = getAbsoluteUrl(mStringHelper.ROBOCOP_BOXES_URL); - - MotionEventHelper meh = new MotionEventHelper(getInstrumentation(), mDriver.getGeckoLeft(), mDriver.getGeckoTop()); - - blockForGeckoReady(); - - // load page and check we're at 0,0 - loadAndVerifyBoxes(url); - - // drag page upwards by 100 pixels - Actions.RepeatedEventExpecter paintExpecter = mActions.expectPaint(); - meh.dragSync(10, 150, 10, 50); - PaintedSurface painted = waitForPaint(paintExpecter); - paintExpecter.unregisterListener(); - try { - checkScrollWithBoxes(painted, 0, 100); - } finally { - painted.close(); - } - - // drag page leftwards by 100 pixels - paintExpecter = mActions.expectPaint(); - meh.dragSync(150, 10, 50, 10); - painted = waitForPaint(paintExpecter); - paintExpecter.unregisterListener(); - try { - checkScrollWithBoxes(painted, 100, 100); - } finally { - painted.close(); - } - } -} diff --git a/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/testPasswordEncrypt.java b/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/testPasswordEncrypt.java deleted file mode 100644 index 65a4eaba6..000000000 --- a/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/testPasswordEncrypt.java +++ /dev/null @@ -1,125 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -package org.mozilla.gecko.tests; - -import java.io.File; - -import org.json.JSONObject; -import org.mozilla.gecko.NSSBridge; -import org.mozilla.gecko.db.BrowserContract; - -import android.content.ContentResolver; -import android.content.ContentValues; -import android.content.Context; -import android.database.Cursor; -import android.net.Uri; - -public class testPasswordEncrypt extends BaseTest { - public void testPasswordEncrypt() { - Context context = (Context)getActivity(); - ContentResolver cr = context.getContentResolver(); - mAsserter.isnot(cr, null, "Found a content resolver"); - ContentValues cvs = new ContentValues(); - - blockForGeckoReady(); - - File db = new File(mProfile, "signons.sqlite"); - String dbPath = db.getPath(); - - Uri passwordUri; - cvs.put("hostname", "http://www.example.com"); - cvs.put("encryptedUsername", "username"); - cvs.put("encryptedPassword", "password"); - - // Attempt to insert into the db - passwordUri = BrowserContract.Passwords.CONTENT_URI; - Uri.Builder builder = passwordUri.buildUpon(); - passwordUri = builder.appendQueryParameter("profilePath", mProfile).build(); - - Uri uri = cr.insert(passwordUri, cvs); - Uri expectedUri = passwordUri.buildUpon().appendPath("1").build(); - mAsserter.is(uri.toString(), expectedUri.toString(), "Insert returned correct uri"); - - Cursor list = mActions.querySql(dbPath, "SELECT encryptedUsername FROM moz_logins"); - list.moveToFirst(); - String decryptedU = null; - try { - decryptedU = NSSBridge.decrypt(context, mProfile, list.getString(0)); - } catch (Exception e) { - mAsserter.ok(false, "NSSBridge.decrypt through Exception " + e, ""); // TODO: What is diag? - } - mAsserter.is(decryptedU, "username", "Username was encrypted correctly when inserting"); - - list = mActions.querySql(dbPath, "SELECT encryptedPassword, encType FROM moz_logins"); - list.moveToFirst(); - String decryptedP = null; - try { - decryptedP = NSSBridge.decrypt(context, mProfile, list.getString(0)); - } catch (Exception e) { - mAsserter.ok(false, "NSSBridge.decrypt through Exception " + e, ""); // TODO: What is diag? - } - mAsserter.is(decryptedP, "password", "Password was encrypted correctly when inserting"); - mAsserter.is(list.getInt(1), 1, "Password has correct encryption type"); - - cvs.put("encryptedUsername", "username2"); - cvs.put("encryptedPassword", "password2"); - cr.update(passwordUri, cvs, null, null); - - list = mActions.querySql(dbPath, "SELECT encryptedUsername FROM moz_logins"); - list.moveToFirst(); - try { - decryptedU = NSSBridge.decrypt(context, mProfile, list.getString(0)); - } catch (Exception e) { - mAsserter.ok(false, "NSSBridge.decrypt through Exception " + e, ""); // TODO: What is diag? - } - mAsserter.is(decryptedU, "username2", "Username was encrypted when updating"); - - list = mActions.querySql(dbPath, "SELECT encryptedPassword FROM moz_logins"); - list.moveToFirst(); - try { - decryptedP = NSSBridge.decrypt(context, mProfile, list.getString(0)); - } catch (Exception e) { - mAsserter.ok(false, "NSSBridge.decrypt through Exception " + e, ""); // TODO: What is diag? - } - mAsserter.is(decryptedP, "password2", "Password was encrypted when updating"); - - // Trying to store a password while master password is enabled should throw, - // but because Android can't send Exceptions across processes - // it just results in a null uri/cursor being returned. - toggleMasterPassword("password"); - try { - uri = cr.insert(passwordUri, cvs); - // TODO: restore this assertion -- see bug 764901 - // mAsserter.is(uri, null, "Storing a password while MP was set should fail"); - - Cursor c = cr.query(passwordUri, null, null, null, null); - // TODO: restore this assertion -- see bug 764901 - // mAsserter.is(c, null, "Querying passwords while MP was set should fail"); - } catch (Exception ex) { - // Password provider currently can not throw across process - // so we should not catch this exception here - mAsserter.ok(false, "Caught exception", ex.toString()); - } - toggleMasterPassword("password"); - } - - private void toggleMasterPassword(String passwd) { - setPreferenceAndWaitForChange("privacy.masterpassword.enabled", passwd); - } - - @Override - public void tearDown() throws Exception { - // remove the entire signons.sqlite file - File profile = new File(mProfile); - File db = new File(profile, "signons.sqlite"); - if (db.delete()) { - mAsserter.dumpLog("tearDown deleted "+db.toString()); - } else { - mAsserter.dumpLog("tearDown did not delete "+db.toString()); - } - - super.tearDown(); - } -} diff --git a/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/testPasswordProvider.java b/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/testPasswordProvider.java deleted file mode 100644 index 8a2cc357e..000000000 --- a/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/testPasswordProvider.java +++ /dev/null @@ -1,104 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -package org.mozilla.gecko.tests; - -import java.io.File; - -import org.mozilla.gecko.db.BrowserContract; -import org.mozilla.gecko.db.BrowserContract.GeckoDisabledHosts; -import org.mozilla.gecko.db.BrowserContract.Passwords; - -import android.content.ContentResolver; -import android.content.ContentValues; -import android.content.Context; -import android.database.Cursor; -import android.net.Uri; - -/** - * A basic password contentprovider test. - * - inserts a password when the database is not yet set up - * - inserts a password - * - updates a password - * - deletes a password - * - inserts a disabled host - * - queries for disabled host - */ -public class testPasswordProvider extends BaseTest { - private static final String DB_NAME = "signons.sqlite"; - - public void testPasswordProvider() { - Context context = (Context)getActivity(); - ContentResolver cr = context.getContentResolver(); - ContentValues[] cvs = new ContentValues[1]; - cvs[0] = new ContentValues(); - - blockForGeckoReady(); - - cvs[0].put("hostname", "http://www.example.com"); - cvs[0].put("httpRealm", "http://www.example.com"); - cvs[0].put("formSubmitURL", "http://www.example.com"); - cvs[0].put("usernameField", "usernameField"); - cvs[0].put("passwordField", "passwordField"); - cvs[0].put("encryptedUsername", "username"); - cvs[0].put("encryptedPassword", "password"); - cvs[0].put("encType", "1"); - - // Attempt to insert into the db - Uri passwordUri = Passwords.CONTENT_URI; - Uri.Builder builder = passwordUri.buildUpon(); - passwordUri = builder.appendQueryParameter("profilePath", mProfile).build(); - - Uri uri = cr.insert(passwordUri, cvs[0]); - Uri expectedUri = passwordUri.buildUpon().appendPath("1").build(); - mAsserter.is(uri.toString(), expectedUri.toString(), "Insert returned correct uri"); - Cursor c = cr.query(passwordUri, null, null, null, null); - SqliteCompare(c, cvs); - - cvs[0].put("usernameField", "usernameField2"); - cvs[0].put("passwordField", "passwordField2"); - - int numUpdated = cr.update(passwordUri, cvs[0], null, null); - mAsserter.is(1, numUpdated, "Correct number updated"); - c = cr.query(passwordUri, null, null, null, null); - SqliteCompare(c, cvs); - - int numDeleted = cr.delete(passwordUri, null, null); - mAsserter.is(1, numDeleted, "Correct number deleted"); - cvs = new ContentValues[0]; - c = cr.query(passwordUri, null, null, null, null); - SqliteCompare(c, cvs); - - ContentValues values = new ContentValues(); - values.put("hostname", "http://www.example.com"); - - // Attempt to insert into the db. - Uri disabledHostUri = GeckoDisabledHosts.CONTENT_URI; - builder = disabledHostUri.buildUpon(); - disabledHostUri = builder.appendQueryParameter("profilePath", mProfile).build(); - - uri = cr.insert(disabledHostUri, values); - expectedUri = disabledHostUri.buildUpon().appendPath("1").build(); - mAsserter.is(uri.toString(), expectedUri.toString(), "Insert returned correct uri"); - Cursor cursor = cr.query(disabledHostUri, null, null, null, null); - assertNotNull(cursor); - assertEquals(1, cursor.getCount()); - cursor.moveToFirst(); - CursorMatches(cursor, values); - } - - @Override - public void tearDown() throws Exception { - // remove the entire signons.sqlite file - File profile = new File(mProfile); - File db = new File(profile, "signons.sqlite"); - if (db.delete()) { - mAsserter.dumpLog("tearDown deleted "+db.toString()); - } else { - mAsserter.dumpLog("tearDown did not delete "+db.toString()); - } - - super.tearDown(); - } -} diff --git a/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/testPermissions.java b/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/testPermissions.java deleted file mode 100644 index e4d997895..000000000 --- a/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/testPermissions.java +++ /dev/null @@ -1,72 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -package org.mozilla.gecko.tests; - -import java.util.ArrayList; - -import org.mozilla.gecko.Actions; -import org.mozilla.gecko.PaintedSurface; - -import android.widget.CheckBox; - -public class testPermissions extends PixelTest { - public void testPermissions() { - blockForGeckoReady(); - - geolocationTest(); - } - - private void geolocationTest() { - Actions.RepeatedEventExpecter paintExpecter; - - // Test geolocation notification - loadAndPaint(getAbsoluteUrl(mStringHelper.ROBOCOP_GEOLOCATION_URL)); - waitForText("wants your location"); - - // Uncheck the "Don't ask again for this site" checkbox - ArrayList checkBoxes = mSolo.getCurrentViews(CheckBox.class); - mAsserter.ok(checkBoxes.size() == 1, "checkbox count", "only one checkbox visible"); - mAsserter.ok(mSolo.isCheckBoxChecked(0), "checkbox checked", "checkbox is checked"); - mSolo.clickOnCheckBox(0); - mAsserter.ok(!mSolo.isCheckBoxChecked(0), "checkbox not checked", "checkbox is not checked"); - - // Test "Share" button functionality with unchecked checkbox - paintExpecter = mActions.expectPaint(); - mSolo.clickOnText("Share"); - PaintedSurface painted = waitForPaint(paintExpecter); - paintExpecter.unregisterListener(); - try { - mAsserter.ispixel(painted.getPixelAt(10, 10), 0, 0x80, 0, "checking page background is green"); - } finally { - painted.close(); - } - - // Re-trigger geolocation notification - reloadAndPaint(); - waitForText("wants your location"); - - // Make sure the checkbox is checked this time - mAsserter.ok(mSolo.isCheckBoxChecked(0), "checkbox checked", "checkbox is checked"); - - // Test "Share" button functionality with checked checkbox - paintExpecter = mActions.expectPaint(); - mSolo.clickOnText("Share"); - painted = waitForPaint(paintExpecter); - paintExpecter.unregisterListener(); - try { - mAsserter.ispixel(painted.getPixelAt(10, 10), 0, 0x80, 0, "checking page background is green"); - } finally { - painted.close(); - } - - // When we reload the page, location should be automatically shared - painted = reloadAndGetPainted(); - try { - mAsserter.ispixel(painted.getPixelAt(10, 10), 0, 0x80, 0, "checking page background is green"); - } finally { - painted.close(); - } - } -} diff --git a/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/testPictureLinkContextMenu.java b/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/testPictureLinkContextMenu.java deleted file mode 100644 index 1461fd9be..000000000 --- a/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/testPictureLinkContextMenu.java +++ /dev/null @@ -1,52 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -package org.mozilla.gecko.tests; - -public class testPictureLinkContextMenu extends ContentContextMenuTest { - - // Test website strings - private static String PICTURE_PAGE_URL; - private static String BLANK_PAGE_URL; - private static String PICTURE_URL; - private static final String tabs [] = { "Image", "Link" }; - private static final String photoMenuItems [] = { "Copy Image Location", "Share Image", "View Image", "Set Image As", "Save Image" }; - private static final String imageTitle = "^Image$"; - - public void testPictureLinkContextMenu() { - final String PICTURE_PAGE_TITLE = mStringHelper.ROBOCOP_PICTURE_LINK_TITLE; - final String linkMenuItems [] = mStringHelper.CONTEXT_MENU_ITEMS_IN_NORMAL_TAB; - - blockForGeckoReady(); - - PICTURE_PAGE_URL=getAbsoluteUrl(mStringHelper.ROBOCOP_PICTURE_LINK_URL); - BLANK_PAGE_URL=getAbsoluteUrl(mStringHelper.ROBOCOP_BLANK_PAGE_02_URL); - PICTURE_URL=getAbsoluteUrl(mStringHelper.ROBOCOP_PICTURE_URL); - loadAndPaint(PICTURE_PAGE_URL); - verifyUrlInContentDescription(PICTURE_PAGE_URL); - - switchTabs(imageTitle); - verifyContextMenuItems(photoMenuItems); - verifyTabs(tabs); - switchTabs(imageTitle); - verifyCopyOption(photoMenuItems[0], "Firefox.jpg"); // Test the "Copy Image Location" option - switchTabs(imageTitle); - verifyShareOption(photoMenuItems[1], PICTURE_PAGE_TITLE); // Test the "Share Image" option - switchTabs(imageTitle); - verifyViewImageOption(photoMenuItems[2], PICTURE_URL, PICTURE_PAGE_TITLE); // Test the "View Image" option - - verifyContextMenuItems(linkMenuItems); - openTabFromContextMenu(linkMenuItems[0],2); // Test the "Open in New Tab" option - expecting 2 tabs: the original and the new one - openTabFromContextMenu(linkMenuItems[1],2); // Test the "Open in Private Tab" option - expecting only 2 tabs in normal mode - verifyCopyOption(linkMenuItems[2], BLANK_PAGE_URL); // Test the "Copy Link" option - verifyShareOption(linkMenuItems[3], PICTURE_PAGE_TITLE); // Test the "Share Link" option - verifyBookmarkLinkOption(linkMenuItems[4],BLANK_PAGE_URL); // Test the "Bookmark Link" option - } - - @Override - public void tearDown() throws Exception { - mDatabaseHelper.deleteBookmark(BLANK_PAGE_URL); - super.tearDown(); - } -} diff --git a/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/testPrefsObserver.java b/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/testPrefsObserver.java deleted file mode 100644 index f63358d57..000000000 --- a/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/testPrefsObserver.java +++ /dev/null @@ -1,81 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -package org.mozilla.gecko.tests; - -import org.mozilla.gecko.Actions; - -/** - * Basic test to check bounce-back from overscroll. - * - Load the page and verify it draws - * - Drag page downwards by 100 pixels into overscroll, verify it snaps back. - * - Drag page rightwards by 100 pixels into overscroll, verify it snaps back. - */ -public class testPrefsObserver extends BaseTest { - private static final String PREF_TEST_PREF = "robocop.tests.dummy"; - - private Actions.PrefWaiter prefWaiter; - private boolean prefValue; - - public void setPref(boolean value) { - mAsserter.dumpLog("Setting pref"); - mActions.setPref(PREF_TEST_PREF, value, /* flush */ false); - } - - public void waitAndCheckPref(boolean value) { - mAsserter.dumpLog("Waiting to check pref"); - - mAsserter.isnot(prefWaiter, null, "Check pref waiter is not null"); - prefWaiter.waitForFinish(); - - mAsserter.is(prefValue, value, "Check correct pref value"); - } - - public void verifyDisconnect() { - mAsserter.dumpLog("Checking pref observer is removed"); - - final boolean newValue = !prefValue; - setPreferenceAndWaitForChange(PREF_TEST_PREF, newValue); - mAsserter.isnot(prefValue, newValue, "Check pref value did not change"); - } - - public void observePref() { - mAsserter.dumpLog("Setting up pref observer"); - - // Setup the pref observer - mAsserter.is(prefWaiter, null, "Check pref waiter is null"); - prefWaiter = mActions.addPrefsObserver( - new String[] { PREF_TEST_PREF }, new Actions.PrefHandlerBase() { - @Override // Actions.PrefHandlerBase - public void prefValue(String pref, boolean value) { - mAsserter.is(pref, PREF_TEST_PREF, "Check correct pref name"); - prefValue = value; - } - }); - } - - public void removePrefObserver() { - mAsserter.dumpLog("Removing pref observer"); - - mActions.removePrefsObserver(prefWaiter); - } - - public void testPrefsObserver() { - blockForGeckoReady(); - - setPref(false); - observePref(); - waitAndCheckPref(false); - - setPref(true); - waitAndCheckPref(true); - - removePrefObserver(); - verifyDisconnect(); - - // Removing again should be a no-op. - removePrefObserver(); - } -} - diff --git a/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/testPrivateBrowsing.java b/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/testPrivateBrowsing.java deleted file mode 100644 index 461e95aa7..000000000 --- a/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/testPrivateBrowsing.java +++ /dev/null @@ -1,89 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -package org.mozilla.gecko.tests; - -import java.util.ArrayList; - -import org.json.JSONException; -import org.json.JSONObject; -import org.mozilla.gecko.Actions; -import org.mozilla.gecko.Tabs; - -/** - * The test loads a new private tab and loads a page with a big link on it - * Opens the link in a new private tab and checks that it is private - * Adds a new normal tab and loads a 3rd URL - * Checks that the bigLinkUrl loaded in the normal tab is present in the browsing history but the 2 urls opened in private tabs are not - */ -public class testPrivateBrowsing extends ContentContextMenuTest { - - public void testPrivateBrowsing() { - String bigLinkUrl = getAbsoluteUrl(mStringHelper.ROBOCOP_BIG_LINK_URL); - String blank1Url = getAbsoluteUrl(mStringHelper.ROBOCOP_BLANK_PAGE_01_URL); - String blank2Url = getAbsoluteUrl(mStringHelper.ROBOCOP_BLANK_PAGE_02_URL); - Tabs tabs = Tabs.getInstance(); - - blockForGeckoReady(); - - Actions.EventExpecter tabExpecter = mActions.expectGeckoEvent("Tab:Added"); - Actions.EventExpecter contentExpecter = mActions.expectGeckoEvent("Content:PageShow"); - tabs.loadUrl(bigLinkUrl, Tabs.LOADURL_NEW_TAB | Tabs.LOADURL_PRIVATE); - tabExpecter.blockForEvent(); - tabExpecter.unregisterListener(); - contentExpecter.blockForEvent(); - contentExpecter.unregisterListener(); - verifyTabCount(1); - - // May intermittently get context menu for normal tab without additional wait - mSolo.sleep(5000); - - // Open the link context menu and verify the options - verifyContextMenuItems(mStringHelper.CONTEXT_MENU_ITEMS_IN_PRIVATE_TAB); - - // Check that "Open Link in New Tab" is not in the menu - mAsserter.ok(!mSolo.searchText(mStringHelper.CONTEXT_MENU_ITEMS_IN_NORMAL_TAB[0]), "Checking that 'Open Link in New Tab' is not displayed in the context menu", "'Open Link in New Tab' is not displayed in the context menu"); - - // Open the link in a new private tab and check that it is private - tabExpecter = mActions.expectGeckoEvent("Tab:Added"); - contentExpecter = mActions.expectGeckoEvent("Content:PageShow"); - mSolo.clickOnText(mStringHelper.CONTEXT_MENU_ITEMS_IN_PRIVATE_TAB[0]); - String eventData = tabExpecter.blockForEventData(); - tabExpecter.unregisterListener(); - contentExpecter.blockForEvent(); - contentExpecter.unregisterListener(); - mAsserter.ok(isTabPrivate(eventData), "Checking if the new tab opened from the context menu was a private tab", "The tab was a private tab"); - verifyTabCount(2); - - // Open a normal tab to check later that it was registered in the Firefox Browser History - tabExpecter = mActions.expectGeckoEvent("Tab:Added"); - contentExpecter = mActions.expectGeckoEvent("Content:PageShow"); - tabs.loadUrl(blank2Url, Tabs.LOADURL_NEW_TAB); - tabExpecter.blockForEvent(); - tabExpecter.unregisterListener(); - contentExpecter.blockForEvent(); - contentExpecter.unregisterListener(); - verifyTabCount(2); - - // wait for history updates to complete - mSolo.sleep(3000); - - // Get the history list and check that the links open in private browsing are not saved - final ArrayList firefoxHistory = mDatabaseHelper.getBrowserDBUrls(DatabaseHelper.BrowserDataType.HISTORY); - - mAsserter.ok(!firefoxHistory.contains(bigLinkUrl), "Check that the link opened in the first private tab was not saved", bigLinkUrl + " was not added to history"); - mAsserter.ok(!firefoxHistory.contains(blank1Url), "Check that the link opened in the private tab from the context menu was not saved", blank1Url + " was not added to history"); - mAsserter.ok(firefoxHistory.contains(blank2Url), "Check that the link opened in the normal tab was saved", blank2Url + " was added to history"); - } - - private boolean isTabPrivate(String eventData) { - try { - JSONObject data = new JSONObject(eventData); - return data.getBoolean("isPrivate"); - } catch (JSONException e) { - mAsserter.ok(false, "Error parsing the event data", e.toString()); - return false; - } - } -} diff --git a/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/testPromptGridInput.java b/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/testPromptGridInput.java deleted file mode 100644 index f645fe3be..000000000 --- a/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/testPromptGridInput.java +++ /dev/null @@ -1,47 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -package org.mozilla.gecko.tests; - -public class testPromptGridInput extends BaseTest { - protected int index = 1; - public void testPromptGridInput() { - blockForGeckoReady(); - - test(1); - - testGridItem("Icon 1"); - testGridItem("Icon 2"); - testGridItem("Icon 3"); - testGridItem("Icon 4"); - testGridItem("Icon 5"); - testGridItem("Icon 6"); - testGridItem("Icon 7"); - testGridItem("Icon 8"); - testGridItem("Icon 9"); - testGridItem("Icon 10"); - testGridItem("Icon 11"); - - mSolo.clickOnText("Icon 11"); - mSolo.clickOnText("OK"); - - mAsserter.ok(waitForText("PASS"), "test passed", "PASS"); - mSolo.goBack(); - } - - public void testGridItem(String title) { - // Force the list to scroll if necessary - mSolo.waitForText(title, 1, 500, true); - mAsserter.ok(waitForText(title), "Found grid item", title); - } - - public void test(final int num) { - // Load about:blank between each test to ensure we reset state - loadUrl(mStringHelper.ABOUT_BLANK_URL); - mAsserter.ok(waitForText(mStringHelper.ABOUT_BLANK_URL), "Loaded blank page", - mStringHelper.ABOUT_BLANK_URL); - - loadUrl("chrome://roboextender/content/robocop_prompt_gridinput.html#test" + num); - } -} diff --git a/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/testReaderCacheMigration.java b/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/testReaderCacheMigration.java deleted file mode 100644 index 6dbc70de5..000000000 --- a/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/testReaderCacheMigration.java +++ /dev/null @@ -1,62 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -package org.mozilla.gecko.tests; - -import org.mozilla.gecko.GeckoProfile; -import org.mozilla.gecko.db.BrowserDatabaseHelper; - -import java.io.File; -import java.io.IOException; - -import static org.mozilla.gecko.tests.helpers.AssertionHelper.fAssertTrue; - -/** - * Tests that our readercache-migration works correctly. - * - * Our main concern is ensuring that the hashed path for a given url is the same in Java - * as it was in JS, or else our (Java-based) migration will lose track of valid cached items. - */ -public class testReaderCacheMigration extends JavascriptBridgeTest { - - private final String[] TEST_DOMAINS = new String[] { - "", - "http://mozilla.org", - "https://bugzilla.mozilla.org/show_bug.cgi?id=1234315#c41", - "http://www.llanfairpwllgwyngyllgogerychwyrndrobwllllantysiliogogogoch.com/" - }; - - private static final String TEST_JS = "testReaderCacheMigration.js"; - - /** - * We compute the path-name in Java, and pass this through to JS, which conducts the actual - * equality check. Our JavascriptBridge doesn't seem to support return values, so we need - * to instead pass the computed path-name in at least one direction. - */ - private void checkPathMatches(final String pageURL, final File cacheDir) { - final String hashedName = BrowserDatabaseHelper.getReaderCacheFileNameForURL(pageURL); - - final File cacheFile = new File(cacheDir, hashedName); - - try { - // We have to use the canonical path to match what the JS side will use. We could - // instead just match on the file name, and not the path, but this helps - // ensure that we've not broken any of the path finding either. - getJS().syncCall("check_hashed_path_matches", pageURL, cacheFile.getCanonicalPath()); - } catch (IOException e) { - fAssertTrue("Unable to getCanonicalPath(), this should never happen", false); - } - - } - - public void testReaderCacheMigration() { - blockForReadyAndLoadJS(TEST_JS); - - final File cacheDir = new File(GeckoProfile.get(getActivity()).getDir(), "readercache"); - - for (final String URL : TEST_DOMAINS) { - checkPathMatches(URL, cacheDir); - } - } -} diff --git a/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/testReaderModeTitle.java b/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/testReaderModeTitle.java deleted file mode 100644 index 31e012070..000000000 --- a/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/testReaderModeTitle.java +++ /dev/null @@ -1,19 +0,0 @@ -package org.mozilla.gecko.tests; - -import org.mozilla.gecko.tests.helpers.GeckoHelper; -import org.mozilla.gecko.tests.helpers.NavigationHelper; - -/** - * This tests ensures that the toolbar in reader mode displays the original page url. - */ -public class testReaderModeTitle extends UITest { - public void testReaderModeTitle() { - GeckoHelper.blockForReady(); - - NavigationHelper.enterAndLoadUrl(mStringHelper.ROBOCOP_READER_MODE_BASIC_ARTICLE); - - mToolbar.pressReaderModeButton(); - - mToolbar.assertTitle(mStringHelper.ROBOCOP_READER_MODE_BASIC_ARTICLE); - } -} diff --git a/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/testReadingListCache.java b/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/testReadingListCache.java deleted file mode 100644 index 2006bbbfc..000000000 --- a/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/testReadingListCache.java +++ /dev/null @@ -1,12 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -package org.mozilla.gecko.tests; - - -public class testReadingListCache extends JavascriptTest { - public testReadingListCache() { - super("testReadingListCache.js"); - } -} diff --git a/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/testReadingListToBookmarksMigration.java b/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/testReadingListToBookmarksMigration.java deleted file mode 100644 index dc181defc..000000000 --- a/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/testReadingListToBookmarksMigration.java +++ /dev/null @@ -1,217 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this file, - * You can obtain one at http://mozilla.org/MPL/2.0/. */ - -package org.mozilla.gecko.tests; - -import android.database.Cursor; -import android.database.sqlite.SQLiteDatabase; -import android.net.Uri; -import android.util.Log; - -import org.mozilla.gecko.GeckoProfile; -import org.mozilla.gecko.GeckoProfileDirectories; -import org.mozilla.gecko.db.*; -import org.mozilla.gecko.reader.SavedReaderViewHelper; - -import java.io.BufferedInputStream; -import java.io.BufferedOutputStream; -import java.io.File; -import java.io.FileNotFoundException; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.util.ArrayList; -import java.util.HashSet; -import java.util.Set; - -import static org.mozilla.gecko.db.BrowserContract.*; -import static org.mozilla.gecko.tests.helpers.AssertionHelper.fAssertEquals; -import static org.mozilla.gecko.tests.helpers.AssertionHelper.fAssertNotNull; -import static org.mozilla.gecko.tests.helpers.AssertionHelper.fAssertTrue; - -// TODO: Move to junit 3 tests, once those run in automation. There is no ui testing to do so it's a better fit. - -/** - * This test runs the 30 to 31 database upgrade, which moves reading-list INPUT_FILES from a separate - * reading-list folder into mobile bookmarks. - * - * It is based on testBrowserDatabaseHelperUpgrades. We load a v30 db containing two reading list - * INPUT_FILES, and test that these have successfully been converted into bookmarks. - */ -public class testReadingListToBookmarksMigration extends UITest { - private ArrayList tempFiles; - - // These names are generated by hashing the URLs, see INPUT_URLS below, and - // BrowserDatabaseHelper.getReaderCacheFileNameForURL() - private static final ArrayList INPUT_FILES = new ArrayList() {{ - add("DWUP3U4ERC6TKJVSYXKJLHHEFY.json"); - add("KWNV7PXD3JFOJBQJVFXI3CQKNE.json"); - }}; - - // same ordering as in INPUT_FILES, although we don't rely on ordering in this test - private static final ArrayList INPUT_URLS = new ArrayList() {{ - add("http://www.bbc.com/news/election-us-2016-35962179"); - add("http://www.bbc.com/news/world-europe-35962670"); - }}; - - @Override - public void setUp() throws Exception { - super.setUp(); - // TODO: We already install & remove the profile directory each run so it'd be safer for clean-up to store - // this there. That being said, temporary files are still stored in the application directory so these temporary - // files will get cleaned up when the application is uninstalled or when data is cleared. - tempFiles = new ArrayList<>(); - } - - @Override - public void tearDown() throws Exception { - super.tearDown(); - for (final File file : tempFiles) { - file.delete(); - } - } - - private void walkRLPreMigration(SQLiteDatabase db) { - Set urls = new HashSet<>(INPUT_URLS); - - final Cursor c = db.rawQuery("SELECT * FROM " + ReadingListItems.TABLE_NAME, null); - - fAssertNotNull("Cursor cannot be null", c); - try { - final boolean movedToFirst = c.moveToFirst(); - fAssertTrue("Cursor must have data", movedToFirst); - - int urlIndex = c.getColumnIndexOrThrow(ReadingListItems.URL); - do { - final String url = c.getString(urlIndex); - - boolean removed = urls.remove(url); - fAssertTrue("Unexpected reading-list URL in database", removed); - } while (c.moveToNext()); - } finally { - c.close(); - } - - fAssertTrue("All urls should have been removed from set", urls.isEmpty()); - } - - private void walkRLPostMigration(SQLiteDatabase db) { - Set urls = new HashSet<>(INPUT_URLS); - - final Cursor c = db.rawQuery("SELECT * FROM " + - Bookmarks.VIEW_WITH_ANNOTATIONS - + " WHERE " + BrowserContract.UrlAnnotations.KEY + " = ?", - new String[] { - BrowserContract.UrlAnnotations.Key.READER_VIEW.getDbValue() - }); - - fAssertNotNull("Cursor cannot be null", c); - try { - final boolean movedToFirst = c.moveToFirst(); - fAssertTrue("Cursor must have data", movedToFirst); - - int urlIndex = c.getColumnIndexOrThrow(Bookmarks.URL); - do { - final String url = c.getString(urlIndex); - - boolean removed = urls.remove(url); - fAssertTrue("Unexpected reading-list URL in database", removed); - } while (c.moveToNext()); - } finally { - c.close(); - } - - fAssertTrue("All urls should have been removed from set", urls.isEmpty()); - } - - /** - * @throws IOException if the database or input files cannot be copied. - */ - public void testReadingListToBookmarksMigration() throws IOException { - final String tempDbPath = copyAssets(); - final SQLiteDatabase db = SQLiteDatabase.openDatabase(tempDbPath, null, 0); - - try { - // This initialises the helper, but does not open the DB. - BrowserDatabaseHelper dbHelper = new BrowserDatabaseHelper(getActivity(), tempDbPath); - - walkRLPreMigration(db); - - // Run just one upgrade - we don't know what future upgrades might do, whereas with one - // upgrade we can guarantee a given DB state. - dbHelper.onUpgrade(db, 30, 31); - - // SavedReaderViewHelper writes annotations directly to the GeckoProfile DB (as opposed - // to our local DB copy). We aren't able to read this here (and the data isn't written - // to our own db), hence we can't test the DB content yet. -// walkRLPostMigration(db); - - SavedReaderViewHelper rvh = SavedReaderViewHelper.getSavedReaderViewHelper(getActivity()); - - fAssertEquals("All input files should have been migrated", INPUT_FILES.size(), rvh.size()); - for (String url : INPUT_URLS) { - boolean isCached = rvh.isURLCached(url); - fAssertTrue("URL no longer in cache after migration", isCached); - } - } finally { - db.close(); - } - } - - private void copyAssetToFile(String inputPath, File destination) throws IOException { - final InputStream inputStream = openFileFromAssets(inputPath); - final OutputStream os = new BufferedOutputStream(new FileOutputStream(destination)); - try { - final byte[] buffer = new byte[1024]; - int len; - while ((len = inputStream.read(buffer)) > 0) { - os.write(buffer, 0, len); - } - os.flush(); - } finally { - os.close(); - inputStream.close(); - } - } - - /** - * Copies assets into the desired locations. We need to copy our DB into a temporary file, - * and readercache items into the profile directory. - * - * @throws IOException if reading the existing files or writing the temporary files fails - */ - private String copyAssets() throws IOException { - final File profileDir = GeckoProfile.get(getActivity()).getDir(); - final File cacheDir = new File(profileDir, "readercache"); - cacheDir.mkdir(); - - for (String name : INPUT_FILES) { - final String path = "readercache" + File.separator + name; - final File destination = new File(cacheDir, name); - tempFiles.add(destination); - - Log.d(LOGTAG, "Moving readerview cache file to " + destination.getPath()); - copyAssetToFile(path, destination); - } - - final File dbDestination = File.createTempFile("temporaryDB_", "db"); - tempFiles.add(dbDestination); - - Log.d(LOGTAG, "Moving DB from assets to " + dbDestination.getPath()); - copyAssetToFile("browser.db", dbDestination); - - return dbDestination.getPath(); - } - - private InputStream openFileFromAssets(final String name) throws IOException { - final String assetPath = String.format("reading_list_bookmarks_migration" + File.separator + name); - Log.d(LOGTAG, "Opening file from assets: " + assetPath); - try { - return new BufferedInputStream(getInstrumentation().getContext().getAssets().open(assetPath)); - } catch (final FileNotFoundException e) { - throw new IllegalStateException("Declared input files must be provided", e); - } - } -} diff --git a/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/testRestrictions.java b/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/testRestrictions.java deleted file mode 100644 index 8977aa177..000000000 --- a/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/testRestrictions.java +++ /dev/null @@ -1,39 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -package org.mozilla.gecko.tests; - -import static org.mozilla.gecko.tests.helpers.AssertionHelper.fAssertFalse; -import static org.mozilla.gecko.tests.helpers.AssertionHelper.fAssertTrue; - -import org.mozilla.gecko.restrictions.Restrictable; -import org.mozilla.gecko.restrictions.Restrictions; -import org.mozilla.gecko.tests.helpers.GeckoHelper; - -public class testRestrictions extends UITest { - public void testRestrictions() { - GeckoHelper.blockForReady(); - - // No restrictions should be enforced when using a normal profile - for (Restrictable restrictable : Restrictable.values()) { - if (restrictable == Restrictable.BLOCK_LIST) { - assertFeatureDisabled(restrictable); - } else { - assertFeatureEnabled(restrictable); - } - } - } - - private void assertFeatureEnabled(Restrictable restrictable) { - fAssertTrue(String.format("Restrictable feature %s is enabled", restrictable.name), - Restrictions.isAllowed(getActivity(), restrictable) - ); - } - - private void assertFeatureDisabled(Restrictable restrictable) { - fAssertFalse(String.format("Restrictable feature %s is disabled", restrictable.name), - Restrictions.isAllowed(getActivity(), restrictable) - ); - } -} diff --git a/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/testRuntimePermissionsAPI.java b/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/testRuntimePermissionsAPI.java deleted file mode 100644 index df192fc43..000000000 --- a/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/testRuntimePermissionsAPI.java +++ /dev/null @@ -1,48 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this file, - * You can obtain one at http://mozilla.org/MPL/2.0/. */ - -package org.mozilla.gecko.tests; - -import org.mozilla.gecko.EventDispatcher; -import org.mozilla.gecko.util.EventCallback; -import org.mozilla.gecko.util.NativeEventListener; -import org.mozilla.gecko.util.NativeJSObject; - -import static org.mozilla.gecko.tests.helpers.AssertionHelper.fFail; - -public class testRuntimePermissionsAPI extends JavascriptTest implements NativeEventListener { - public testRuntimePermissionsAPI() { - super("testRuntimePermissionsAPI.js"); - } - - @Override - public void setUp() throws Exception { - super.setUp(); - - EventDispatcher.getInstance().registerGeckoThreadListener(this, "RuntimePermissions:Prompt"); - } - - @Override - public void tearDown() throws Exception { - super.tearDown(); - - EventDispatcher.getInstance().unregisterGeckoThreadListener(this, "RuntimePermissions:Prompt"); - } - - @Override - public void handleMessage(String event, NativeJSObject message, EventCallback callback) { - mAsserter.is(event, "RuntimePermissions:Prompt", "Received RuntimePermissions:Prompt event"); - - try { - String[] permissions = message.getStringArray("permissions"); - mAsserter.is(3, permissions.length, "Received three permissions"); - - mAsserter.is("android.permission.CAMERA", permissions[0], "Received CAMERA permission"); - mAsserter.is("android.permission.WRITE_EXTERNAL_STORAGE", permissions[1], "Received WRITE_EXTERNAL_STORAGE permission"); - mAsserter.is("android.permission.RECORD_AUDIO", permissions[2], "Received RECORD_AUDIO permission"); - } catch (Exception e) { - fFail("Event does not contain expected data: " + e.getMessage()); - } - } -} diff --git a/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/testSearchHistoryProvider.java b/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/testSearchHistoryProvider.java deleted file mode 100644 index 3c22703bc..000000000 --- a/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/testSearchHistoryProvider.java +++ /dev/null @@ -1,379 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -package org.mozilla.gecko.tests; - -import java.util.concurrent.Callable; - -import org.mozilla.gecko.db.BrowserContract; -import org.mozilla.gecko.db.BrowserContract.SearchHistory; -import org.mozilla.gecko.db.SearchHistoryProvider; - -import android.content.ContentProvider; -import android.content.ContentValues; -import android.database.Cursor; -import android.net.Uri; - -public class testSearchHistoryProvider extends ContentProviderTest { - - // Translations of "United Kingdom" in several different languages - private static final String[] testStrings = { - "An Ríocht Aontaithe", // Irish - "Angli", // Albanian - "Britanniarum Regnum", // Latin - "Britio", // Esperanto - "Büyük Britanya", // Turkish - "Egyesült Királyság", // Hungarian - "Erresuma Batua", // Basque - "Inggris Raya", // Indonesian - "Ir-Renju Unit", // Maltese - "Iso-Britannia", // Finnish - "Jungtinė Karalystė", // Lithuanian - "Lielbritānija", // Latvian - "Regatul Unit", // Romanian - "Regne Unit", // Catalan, Valencian - "Regno Unito", // Italian - "Royaume-Uni", // French - "Spojené království", // Czech - "Spojené kráľovstvo", // Slovak - "Storbritannia", // Norwegian - "Storbritannien", // Danish - "Suurbritannia", // Estonian - "Ujedinjeno Kraljevstvo", // Bosnian - "United Alaeze", // Igbo - "United Kingdom", // English - "Vereinigtes Königreich", // German - "Verenigd Koninkrijk", // Dutch - "Verenigde Koninkryk", // Afrikaans - "Vương quốc Anh", // Vietnamese - "Wayòm Ini", // Haitian, Haitian Creole - "Y Deyrnas Unedig", // Welsh - "Združeno kraljestvo", // Slovene - "Zjednoczone Królestwo", // Polish - "Ηνωμένο Βασίλειο", // Greek (modern) - "Великобритания", // Russian - "Нэгдсэн Вант Улс", // Mongolian - "Обединетото Кралство", // Macedonian - "Уједињено Краљевство", // Serbian - "Միացյալ Թագավորություն", // Armenian - "בריטניה", // Hebrew (modern) - "פֿאַראייניקטע מלכות", // Yiddish - "المملكة المتحدة", // Arabic - "برطانیہ", // Urdu - "پادشاهی متحده", // Persian (Farsi) - "यूनाइटेड किंगडम", // Hindi - "संयुक्त राज्य", // Nepali - "যুক্তরাজ্য", // Bengali, Bangla - "યુનાઇટેડ કિંગડમ", // Gujarati - "ஐக்கிய ராஜ்யம்", // Tamil - "สหราชอาณาจักร", // Thai - "ສະ​ຫະ​ປະ​ຊາ​ຊະ​ອາ​ນາ​ຈັກ", // Lao - "გაერთიანებული სამეფო", // Georgian - "イギリス", // Japanese - "联合王国" // Chinese - }; - - - private static final String DB_NAME = "searchhistory.db"; - - /** - * Boilerplate alert. - *

- * Make sure this method is present and that it returns a new - * instance of your class. - */ - private static final Callable sProviderFactory = - new Callable() { - @Override - public ContentProvider call() { - return new SearchHistoryProvider(); - } - }; - - @Override - public void setUp() throws Exception { - super.setUp(sProviderFactory, BrowserContract.SEARCH_HISTORY_AUTHORITY, DB_NAME); - mTests.add(new TestInsert()); - mTests.add(new TestUnicodeQuery()); - mTests.add(new TestTimestamp()); - mTests.add(new TestLimit()); - mTests.add(new TestDelete()); - mTests.add(new TestIncrement()); - } - - public void testSearchHistory() throws Exception { - for (Runnable test : mTests) { - String testName = test.getClass().getSimpleName(); - setTestName(testName); - mAsserter.dumpLog( - "testBrowserProvider: Database empty - Starting " + testName + "."); - // Clear the db - mProvider.delete(SearchHistory.CONTENT_URI, null, null); - test.run(); - } - } - - /** - * Verify that we can pass a LIMIT clause using a query parameter. - */ - private class TestLimit extends TestCase { - @Override - public void test() throws Exception { - ContentValues cv; - for (int i = 0; i < testStrings.length; i++) { - cv = new ContentValues(); - cv.put(SearchHistory.QUERY, testStrings[i]); - mProvider.insert(SearchHistory.CONTENT_URI, cv); - } - - final int limit = 5; - - // Test 1: Handle proper input. - - Uri uri = SearchHistory.CONTENT_URI - .buildUpon() - .appendQueryParameter(BrowserContract.PARAM_LIMIT, String.valueOf(limit)) - .build(); - - Cursor c = mProvider.query(uri, null, null, null, null); - try { - mAsserter.is(c.getCount(), limit, - String.format("Should have %d results", limit)); - } finally { - c.close(); - } - - // Test 2: Empty input yields all results. - - uri = SearchHistory.CONTENT_URI - .buildUpon() - .appendQueryParameter(BrowserContract.PARAM_LIMIT, "") - .build(); - - c = mProvider.query(uri, null, null, null, null); - try { - mAsserter.is(c.getCount(), testStrings.length, "Should have all results"); - } finally { - c.close(); - } - - // Test 3: Illegal params. - - String[] illegalParams = new String[] {"a", "-1"}; - boolean success = true; - - for (String param : illegalParams) { - success = true; - - uri = SearchHistory.CONTENT_URI - .buildUpon() - .appendQueryParameter(BrowserContract.PARAM_LIMIT, param) - .build(); - - try { - c = mProvider.query(uri, null, null, null, null); - success = false; - } catch(IllegalArgumentException e) { - // noop. - } finally { - if (c != null) { - c.close(); - } - } - - mAsserter.ok(success, "LIMIT", param + " should have been an invalid argument"); - } - - } - } - - /** - * Verify that we can insert values into the DB, including unicode. - */ - private class TestInsert extends TestCase { - @Override - public void test() throws Exception { - ContentValues cv; - for (int i = 0; i < testStrings.length; i++) { - cv = new ContentValues(); - cv.put(SearchHistory.QUERY, testStrings[i]); - mProvider.insert(SearchHistory.CONTENT_URI, cv); - } - - final Cursor c = mProvider.query(SearchHistory.CONTENT_URI, null, null, null, null); - try { - mAsserter.is(c.getCount(), testStrings.length, - "Should have one row for each insert"); - } finally { - c.close(); - } - } - } - - /** - * Verify that we can insert values into the DB, including unicode. - */ - private class TestUnicodeQuery extends TestCase { - @Override - public void test() throws Exception { - final String selection = SearchHistory.QUERY + " = ?"; - - for (int i = 0; i < testStrings.length; i++) { - final ContentValues cv = new ContentValues(); - cv.put(SearchHistory.QUERY, testStrings[i]); - mProvider.insert(SearchHistory.CONTENT_URI, cv); - - final Cursor c = mProvider.query(SearchHistory.CONTENT_URI, null, selection, - new String[]{ testStrings[i] }, null); - try { - mAsserter.is(c.getCount(), 1, - "Should have one row for insert of " + testStrings[i]); - } finally { - c.close(); - } - } - } - } - - /** - * Verify that timestamps are updated on insert. - */ - private class TestTimestamp extends TestCase { - @Override - public void test() throws Exception { - String insertedTerm = "Courtside Seats"; - long insertStart; - long insertFinish; - long t1Db; - long t2Db; - - ContentValues cv = new ContentValues(); - cv.put(SearchHistory.QUERY, insertedTerm); - - // First check that the DB has a value that is close to the - // system time. - insertStart = System.currentTimeMillis(); - mProvider.insert(SearchHistory.CONTENT_URI, cv); - insertFinish = System.currentTimeMillis(); - - final Cursor c1 = mProvider.query(SearchHistory.CONTENT_URI, null, null, null, null); - try { - c1.moveToFirst(); - t1Db = c1.getLong(c1.getColumnIndex(SearchHistory.DATE_LAST_VISITED)); - } finally { - c1.close(); - } - - mAsserter.dumpLog("First insert:"); - mAsserter.dumpLog(" insertStart " + insertStart); - mAsserter.dumpLog(" insertFinish " + insertFinish); - mAsserter.dumpLog(" t1Db " + t1Db); - mAsserter.ok(t1Db >= insertStart, "DATE_LAST_VISITED", - "Date last visited should be set on insert."); - mAsserter.ok(t1Db <= insertFinish, "DATE_LAST_VISITED", - "Date last visited should be set on insert."); - - cv = new ContentValues(); - cv.put(SearchHistory.QUERY, insertedTerm); - - insertStart = System.currentTimeMillis(); - mProvider.insert(SearchHistory.CONTENT_URI, cv); - insertFinish = System.currentTimeMillis(); - - final Cursor c2 = mProvider.query(SearchHistory.CONTENT_URI, null, null, null, null); - try { - c2.moveToFirst(); - t2Db = c2.getLong(c2.getColumnIndex(SearchHistory.DATE_LAST_VISITED)); - } finally { - c2.close(); - } - - mAsserter.dumpLog("Second insert:"); - mAsserter.dumpLog(" insertStart " + insertStart); - mAsserter.dumpLog(" insertFinish " + insertFinish); - mAsserter.dumpLog(" t2Db " + t2Db); - - mAsserter.ok(t2Db >= insertStart, "DATE_LAST_VISITED", - "Date last visited should be set on insert."); - mAsserter.ok(t2Db <= insertFinish, "DATE_LAST_VISITED", - "Date last visited should be set on insert."); - mAsserter.ok(t2Db >= t1Db, "DATE_LAST_VISITED", - "Date last visited should be updated on key increment."); - } - } - - /** - * Verify that sending a delete command empties the database. - */ - private class TestDelete extends TestCase { - @Override - public void test() throws Exception { - String insertedTerm = "Courtside Seats"; - - ContentValues cv = new ContentValues(); - cv.put(SearchHistory.QUERY, insertedTerm); - mProvider.insert(SearchHistory.CONTENT_URI, cv); - - final Cursor c1 = mProvider.query(SearchHistory.CONTENT_URI, null, null, null, null); - try { - mAsserter.is(c1.getCount(), 1, "Should have one value"); - mProvider.delete(SearchHistory.CONTENT_URI, null, null); - } finally { - c1.close(); - } - - final Cursor c2 = mProvider.query(SearchHistory.CONTENT_URI, null, null, null, null); - try { - mAsserter.is(c2.getCount(), 0, "Should be empty"); - mProvider.insert(SearchHistory.CONTENT_URI, cv); - } finally { - c2.close(); - } - - final Cursor c3 = mProvider.query(SearchHistory.CONTENT_URI, null, null, null, null); - try { - mAsserter.is(c3.getCount(), 1, "Should have one value"); - } finally { - c3.close(); - } - } - } - - - /** - * Ensure that we only increment when the case matches. - */ - private class TestIncrement extends TestCase { - @Override - public void test() throws Exception { - ContentValues cv = new ContentValues(); - cv.put(SearchHistory.QUERY, "omaha"); - mProvider.insert(SearchHistory.CONTENT_URI, cv); - - cv = new ContentValues(); - cv.put(SearchHistory.QUERY, "omaha"); - mProvider.insert(SearchHistory.CONTENT_URI, cv); - - Cursor c = mProvider.query(SearchHistory.CONTENT_URI, null, null, null, null); - try { - c.moveToFirst(); - mAsserter.is(c.getCount(), 1, "Should have one result"); - mAsserter.is(c.getInt(c.getColumnIndex(SearchHistory.VISITS)), 2, - "Counter should be 2"); - } finally { - c.close(); - } - - cv = new ContentValues(); - cv.put(SearchHistory.QUERY, "Omaha"); - mProvider.insert(SearchHistory.CONTENT_URI, cv); - c = mProvider.query(SearchHistory.CONTENT_URI, null, null, null, null); - try { - mAsserter.is(c.getCount(), 2, "Should have two results"); - } finally { - c.close(); - } - } - } -} diff --git a/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/testSearchSuggestions.java b/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/testSearchSuggestions.java deleted file mode 100644 index 6f82e5c51..000000000 --- a/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/testSearchSuggestions.java +++ /dev/null @@ -1,115 +0,0 @@ -package org.mozilla.gecko.tests; - -import java.util.ArrayList; -import java.util.HashMap; - -import org.mozilla.gecko.R; -import org.mozilla.gecko.SuggestClient; -import org.mozilla.gecko.home.BrowserSearch; - -import android.content.Context; -import android.view.View; -import android.view.ViewGroup; -import android.widget.TextView; - -import com.robotium.solo.Condition; - -/** - * Test for search suggestions. - * Sends queries from AwesomeBar input and verifies that suggestions match - * expected values. - */ -public class testSearchSuggestions extends BaseTest { - private static final int SUGGESTION_MAX = 3; - private static final int SUGGESTION_TIMEOUT = 15000; - - private static final String TEST_QUERY = "foo barz"; - private static final String SUGGESTION_TEMPLATE = "/robocop/robocop_suggestions.sjs?query=__searchTerms__"; - - public void testSearchSuggestions() { - // Mock the search system. - // The BrowserSearch UI only shows up once a non-empty - // search term is entered, but we swizzle in a new factory beforehand. - mockSuggestClientFactory(); - - blockForGeckoReady(); - - // Map of expected values. See robocop_suggestions.sjs. - final HashMap> suggestMap = new HashMap>(); - buildSuggestMap(suggestMap); - - focusUrlBar(); - - // At this point we rely on our swizzling having worked -- which relies - // on us not having previously run a search. - // The test will fail later if there's already a BrowserSearch object with a - // suggest client set, so fail here. - BrowserSearch browserSearch = (BrowserSearch) getBrowserSearch(); - mAsserter.ok(browserSearch == null || - browserSearch.mSuggestClient == null, - "There is no existing search client.", ""); - - // Now test the incremental suggestions. - for (int i = 0; i < TEST_QUERY.length(); i++) { - mActions.sendKeys(TEST_QUERY.substring(i, i+1)); - - final String query = TEST_QUERY.substring(0, i+1); - mSolo.waitForView(R.id.suggestion_text); - boolean success = waitForCondition(new Condition() { - @Override - public boolean isSatisfied() { - // Get the first suggestion row. - ViewGroup suggestionGroup = (ViewGroup) getActivity().findViewById(R.id.suggestion_layout); - if (suggestionGroup == null) { - mAsserter.dumpLog("Fail: suggestionGroup is null."); - return false; - } - - final ArrayList expected = suggestMap.get(query); - for (int i = 0; i < expected.size(); i++) { - View queryChild = suggestionGroup.getChildAt(i); - if (queryChild == null || queryChild.getVisibility() == View.GONE) { - mAsserter.dumpLog("Fail: queryChild is null or GONE."); - return false; - } - - String suggestion = ((TextView) queryChild.findViewById(R.id.suggestion_text)).getText().toString(); - if (!suggestion.equals(expected.get(i))) { - mAsserter.dumpLog("Suggestion '" + suggestion + "' not equal to expected '" + expected.get(i) + "'."); - return false; - } - } - - return true; - } - }, SUGGESTION_TIMEOUT); - - mAsserter.is(success, true, "Results for query '" + query + "' matched expected suggestions"); - } - } - - private void buildSuggestMap(HashMap> suggestMap) { - // these values assume SUGGESTION_MAX = 3 - suggestMap.put("f", new ArrayList() {{ add("f"); add("facebook"); add("fandango"); add("frys"); }}); - suggestMap.put("fo", new ArrayList() {{ add("fo"); add("forever 21"); add("food network"); add("fox news"); }}); - suggestMap.put("foo", new ArrayList() {{ add("foo"); add("food network"); add("foothill college"); add("foot locker"); }}); - suggestMap.put("foo ", new ArrayList() {{ add("foo "); add("foo fighters"); add("foo bar"); add("foo bat"); }}); - suggestMap.put("foo b", new ArrayList() {{ add("foo b"); add("foo bar"); add("foo bat"); add("foo bay"); }}); - suggestMap.put("foo ba", new ArrayList() {{ add("foo ba"); add("foo bar"); add("foo bat"); add("foo bay"); }}); - suggestMap.put("foo bar", new ArrayList() {{ add("foo bar"); }}); - suggestMap.put("foo barz", new ArrayList() {{ add("foo barz"); }}); - } - - private void mockSuggestClientFactory() { - BrowserSearch.sSuggestClientFactory = new BrowserSearch.SuggestClientFactory() { - @Override - public SuggestClient getSuggestClient(Context context, String template, int timeout, int max) { - final String suggestTemplate = getAbsoluteRawUrl(SUGGESTION_TEMPLATE); - - // This one uses our template, and also doesn't check for network accessibility. - return new SuggestClient(context, suggestTemplate, SUGGESTION_TIMEOUT, Integer.MAX_VALUE, false); - } - }; - } -} - diff --git a/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/testSessionHistory.java b/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/testSessionHistory.java deleted file mode 100644 index 50d173461..000000000 --- a/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/testSessionHistory.java +++ /dev/null @@ -1,37 +0,0 @@ -package org.mozilla.gecko.tests; - -import org.mozilla.gecko.tests.helpers.GeckoHelper; -import org.mozilla.gecko.tests.helpers.NavigationHelper; - -/** - * Tests that navigating through session history (ex: forward, back) sets the correct UI state. - */ -public class testSessionHistory extends UITest { - public void testSessionHistory() { - GeckoHelper.blockForReady(); - - String url = mStringHelper.ROBOCOP_BLANK_PAGE_01_URL; - NavigationHelper.enterAndLoadUrl(url); - mToolbar.assertTitle(url); - - url = mStringHelper.ROBOCOP_BLANK_PAGE_02_URL; - NavigationHelper.enterAndLoadUrl(url); - mToolbar.assertTitle(url); - - url = mStringHelper.ROBOCOP_BLANK_PAGE_03_URL; - NavigationHelper.enterAndLoadUrl(url); - mToolbar.assertTitle(url); - - NavigationHelper.goBack(); - mToolbar.assertTitle(mStringHelper.ROBOCOP_BLANK_PAGE_02_URL); - - NavigationHelper.goBack(); - mToolbar.assertTitle(mStringHelper.ROBOCOP_BLANK_PAGE_01_URL); - - NavigationHelper.goForward(); - mToolbar.assertTitle(mStringHelper.ROBOCOP_BLANK_PAGE_02_URL); - - NavigationHelper.reload(); - mToolbar.assertTitle(mStringHelper.ROBOCOP_BLANK_PAGE_02_URL); - } -} diff --git a/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/testSessionOOMRestore.java b/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/testSessionOOMRestore.java deleted file mode 100644 index 5646311b1..000000000 --- a/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/testSessionOOMRestore.java +++ /dev/null @@ -1,54 +0,0 @@ -package org.mozilla.gecko.tests; - -import android.content.Context; -import android.content.Intent; -import android.content.SharedPreferences; -import android.os.Bundle; - -/** - * Tests session OOM restore behavior. - * - * Loads a session and tests that it is restored correctly. - */ -public class testSessionOOMRestore extends SessionTest { - private Session mSession; - private static final String PREFS_NAME = "GeckoApp"; - private static final String PREFS_ALLOW_STATE_BUNDLE = "allowStateBundle"; - - @Override - public void setActivityIntent(Intent intent) { - PageInfo home = new PageInfo(StringHelper.STATIC_ABOUT_HOME_URL); - PageInfo page1 = new PageInfo("page1"); - PageInfo page2 = new PageInfo("page2"); - PageInfo page3 = new PageInfo("page3"); - PageInfo page4 = new PageInfo("page4"); - PageInfo page5 = new PageInfo("page5"); - PageInfo page6 = new PageInfo("page6"); - - SessionTab tab1 = new SessionTab(0, home, page1, page2); - SessionTab tab2 = new SessionTab(1, home, page3, page4); - SessionTab tab3 = new SessionTab(2, home, page5, page6); - - mSession = new Session(1, tab1, tab2, tab3); - - String sessionString = buildSessionJSON(mSession); - writeProfileFile("sessionstore.js", sessionString); - - // This feature is pref-protected to prevent other apps from injecting - // a state bundle, so enable it here. - SharedPreferences prefs = getInstrumentation().getTargetContext() - .getSharedPreferences(PREFS_NAME, Context.MODE_PRIVATE); - prefs.edit().putBoolean(PREFS_ALLOW_STATE_BUNDLE, true).commit(); - - Bundle bundle = new Bundle(); - bundle.putString("privateSession", null); - intent.putExtra("stateBundle", bundle); - - super.setActivityIntent(intent); - } - - public void testSessionOOMRestore() throws Exception { - blockForGeckoReady(); - verifySessionTabs(mSession); - } -} diff --git a/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/testSessionOOMSave.java b/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/testSessionOOMSave.java deleted file mode 100644 index f5e5ee099..000000000 --- a/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/testSessionOOMSave.java +++ /dev/null @@ -1,87 +0,0 @@ -package org.mozilla.gecko.tests; - -import org.mozilla.gecko.Actions; - -import com.robotium.solo.Condition; - -/** - * Tests session OOM save behavior. - * - * Builds a session and tests that the saved state is correct. - */ -public class testSessionOOMSave extends SessionTest { - private final static int SESSION_TIMEOUT = 25000; - - public void testSessionOOMSave() { - Actions.EventExpecter pageShowExpecter = mActions.expectGeckoEvent("Content:PageShow"); - pageShowExpecter.blockForEvent(); - pageShowExpecter.unregisterListener(); - - PageInfo home = new PageInfo(mStringHelper.ABOUT_HOME_URL); - PageInfo page1 = new PageInfo("page1"); - PageInfo page2 = new PageInfo("page2"); - PageInfo page3 = new PageInfo("page3"); - PageInfo page4 = new PageInfo("page4"); - PageInfo page5 = new PageInfo("page5"); - PageInfo page6 = new PageInfo("page6"); - - SessionTab tab1 = new SessionTab(0, home, page1, page2); - SessionTab tab2 = new SessionTab(1, home, page3, page4); - SessionTab tab3 = new SessionTab(2, home, page5, page6); - - final Session session = new Session(1, tab1, tab2, tab3); - - // Load the tabs into the browser - loadSessionTabs(session); - - // Verify sessionstore.js written by Gecko. The session write is - // delayed for certain interactions (such as changing the selected - // tab), so the file is repeatedly read until it matches the expected - // output. Because of the delay, this part of the test takes ~9 seconds - // to pass. - VerifyJSONCondition verifyJSONCondition = new VerifyJSONCondition(session); - boolean success = waitForCondition(verifyJSONCondition, SESSION_TIMEOUT); - if (success) { - mAsserter.ok(true, "verified session JSON", null); - } else { - mAsserter.ok(false, "failed to verify session JSON", - getStackTraceString(verifyJSONCondition.getLastException())); - } - } - - private class VerifyJSONCondition implements Condition { - private AssertException mLastException; - private final NonFatalAsserter mAsserter = new NonFatalAsserter(); - private final Session mSession; - - public VerifyJSONCondition(Session session) { - mSession = session; - } - - @Override - public boolean isSatisfied() { - try { - String sessionString = readProfileFile("sessionstore.js"); - if (sessionString == null) { - mLastException = new AssertException("Could not read sessionstore.js"); - return false; - } - - verifySessionJSON(mSession, sessionString, mAsserter); - } catch (AssertException e) { - mLastException = e; - return false; - } - return true; - } - - /** - * Gets the last AssertException thrown by verifySessionJSON(). - * - * This is useful to get the stack trace if the test fails. - */ - public AssertException getLastException() { - return mLastException; - } - } -} diff --git a/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/testShareLink.java b/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/testShareLink.java deleted file mode 100644 index 0df786136..000000000 --- a/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/testShareLink.java +++ /dev/null @@ -1,265 +0,0 @@ -package org.mozilla.gecko.tests; - -import java.util.ArrayList; -import java.util.List; - -import org.mozilla.gecko.Actions; -import org.mozilla.gecko.home.HomePager; - -import android.app.Activity; -import android.content.Intent; -import android.content.pm.PackageManager; -import android.content.pm.ResolveInfo; -import android.os.Build; -import android.view.View; -import android.view.ViewGroup; -import android.widget.AbsListView; -import android.widget.GridView; -import android.widget.ListView; -import android.widget.TextView; - -import com.robotium.solo.Condition; - -/** - * This test covers the opening and content of the Share Link pop-up list - * The test opens the Share menu from the app menu, the URL bar, a link context menu and the Awesomescreen tabs - */ -public class testShareLink extends AboutHomeTest { - String url; - String urlTitle = mStringHelper.ROBOCOP_BIG_LINK_TITLE; - - public void testShareLink() { - url = getAbsoluteUrl(mStringHelper.ROBOCOP_BIG_LINK_URL); - ArrayList shareOptions; - blockForGeckoReady(); - - // FIXME: This is a temporary hack workaround for a permissions problem. - openAboutHomeTab(AboutHomeTabs.HISTORY); - - inputAndLoadUrl(url); - verifyUrlBarTitle(url); // Waiting for page title to ensure the page is loaded - - selectMenuItem(mStringHelper.SHARE_LABEL); - if (Build.VERSION.SDK_INT >= 14) { - // Check for our own sync in the submenu. - waitForText("Sync$"); - } else { - waitForText("Share via"); - } - - // Get list of current available share activities and verify them - shareOptions = getShareOptions(); - ArrayList displayedOptions = getShareOptionsList(); - for (String option:shareOptions) { - // Verify if the option is present in the list of displayed share options - mAsserter.ok(optionDisplayed(option, displayedOptions), "Share option found", option); - } - - // Test share from the urlbar context menu - mSolo.goBack(); // Close the share menu - mSolo.clickLongOnText(urlTitle); - verifySharePopup(shareOptions,"urlbar"); - - // The link has a 60px height, so let's try to hit the middle - float top = mDriver.getGeckoTop() + 30 * mDevice.density; - float left = mDriver.getGeckoLeft() + mDriver.getGeckoWidth() / 2; - mSolo.clickLongOnScreen(left, top); - verifySharePopup("Share Link",shareOptions,"Link"); - - // Test the share popup in the Bookmarks page - openAboutHomeTab(AboutHomeTabs.BOOKMARKS); - - final ListView bookmarksList = findListViewWithTag(HomePager.LIST_TAG_BOOKMARKS); - mAsserter.is(waitForNonEmptyListToLoad(bookmarksList), true, "list is properly loaded"); - - int headerViewsCount = bookmarksList.getHeaderViewsCount(); - View bookmarksItem = bookmarksList.getChildAt(headerViewsCount); - if (bookmarksItem == null) { - mAsserter.dumpLog("no child at index " + headerViewsCount + "; waiting for one..."); - Condition listWaitCondition = new Condition() { - @Override - public boolean isSatisfied() { - if (bookmarksList.getChildAt(bookmarksList.getHeaderViewsCount()) == null) - return false; - return true; - } - }; - waitForCondition(listWaitCondition, MAX_WAIT_MS); - headerViewsCount = bookmarksList.getHeaderViewsCount(); - bookmarksItem = bookmarksList.getChildAt(headerViewsCount); - } - - mSolo.clickLongOnView(bookmarksItem); - verifySharePopup(shareOptions,"bookmarks"); - - // Prepopulate top sites with history items to overflow tiles. - // We are trying to move away from using reflection and doing more black-box testing. - inputAndLoadUrl(getAbsoluteUrl(mStringHelper.ROBOCOP_BLANK_PAGE_01_URL)); - inputAndLoadUrl(getAbsoluteUrl(mStringHelper.ROBOCOP_BLANK_PAGE_02_URL)); - inputAndLoadUrl(getAbsoluteUrl(mStringHelper.ROBOCOP_BLANK_PAGE_03_URL)); - inputAndLoadUrl(getAbsoluteUrl(mStringHelper.ROBOCOP_BLANK_PAGE_04_URL)); - if (mDevice.type.equals("tablet")) { - // Tablets have more tile spaces to fill. - inputAndLoadUrl(getAbsoluteUrl(mStringHelper.ROBOCOP_BLANK_PAGE_05_URL)); - inputAndLoadUrl(getAbsoluteUrl(mStringHelper.ROBOCOP_BOXES_URL)); - inputAndLoadUrl(getAbsoluteUrl(mStringHelper.ROBOCOP_SEARCH_URL)); - inputAndLoadUrl(getAbsoluteUrl(mStringHelper.ROBOCOP_TEXT_PAGE_URL)); - } - - // Test the share popup in Top Sites. - openAboutHomeTab(AboutHomeTabs.TOP_SITES); - - // Scroll down a bit so that the top sites list has more items on screen. - int width = mDriver.getGeckoWidth(); - int height = mDriver.getGeckoHeight(); - mActions.drag(width / 2, width / 2, height - 10, height / 2); - - ListView topSitesList = findListViewWithTag(HomePager.LIST_TAG_TOP_SITES); - mAsserter.is(waitForNonEmptyListToLoad(topSitesList), true, "list is properly loaded"); - View mostVisitedItem = topSitesList.getChildAt(topSitesList.getHeaderViewsCount()); - mSolo.clickLongOnView(mostVisitedItem); - verifySharePopup(shareOptions,"top_sites"); - - // Test the share popup in the history tab - openAboutHomeTab(AboutHomeTabs.HISTORY); - - ListView mostRecentList = findListViewWithTag(HomePager.LIST_TAG_HISTORY); - mAsserter.is(waitForNonEmptyListToLoad(mostRecentList), true, "list is properly loaded"); - - // Getting second child after header views because the first is the "Today" label - View mostRecentItem = mostRecentList.getChildAt(mostRecentList.getHeaderViewsCount() + 1); - mSolo.clickLongOnView(mostRecentItem); - verifySharePopup(shareOptions,"most recent"); - } - - public void verifySharePopup(ArrayList shareOptions, String openedFrom) { - verifySharePopup("Share", shareOptions, openedFrom); - } - - public void verifySharePopup(String shareItemText, ArrayList shareOptions, String openedFrom) { - waitForText(shareItemText); - mSolo.clickOnText(shareItemText); - waitForText("Share via"); - ArrayList displayedOptions = getSharePopupOption(); - for (String option:shareOptions) { - // Verify if the option is present in the list of displayed share options - mAsserter.ok(optionDisplayed(option, displayedOptions), "Share option for " + openedFrom + (openedFrom.equals("urlbar") ? "" : " item") + " found", option); - } - mSolo.goBack(); - /** - * Adding a wait for the page title to make sure the Awesomebar will be dismissed - * Because of Bug 712370 the Awesomescreen will be dismissed when the Share Menu is closed - * so there is no need for handling this different depending on where the share menu was invoked from - * TODO: Look more into why the delay is needed here now and it was working before - */ - waitForText(urlTitle); - } - - // Create a SEND intent and get the possible activities offered - public ArrayList getShareOptions() { - ArrayList shareOptions = new ArrayList<>(); - Activity currentActivity = getActivity(); - final Intent shareIntent = new Intent(Intent.ACTION_SEND); - shareIntent.putExtra(Intent.EXTRA_TEXT, url); - shareIntent.putExtra(Intent.EXTRA_SUBJECT, "Robocop Blank 01"); - shareIntent.setType("text/plain"); - PackageManager pm = currentActivity.getPackageManager(); - List activities = pm.queryIntentActivities(shareIntent, 0); - for (ResolveInfo activity : activities) { - shareOptions.add(activity.loadLabel(pm).toString()); - } - return shareOptions; - } - - // Traverse the group of views, adding strings from TextViews to the list. - private void getGroupTextViews(ViewGroup group, ArrayList list) { - for (int i = 0; i < group.getChildCount(); i++) { - View child = group.getChildAt(i); - if (child instanceof AbsListView) { - getGroupTextViews((AbsListView)child, list); - } else if (child instanceof ViewGroup) { - getGroupTextViews((ViewGroup)child, list); - } else if (child instanceof TextView) { - String viewText = ((TextView)child).getText().toString(); - if (viewText != null && viewText.length() > 0) { - list.add(viewText); - } - } - } - } - - // Traverse the group of views, adding strings from TextViews to the list. - // This override is for AbsListView, which has adapters. If adapters are - // available, it is better to use them so that child views that are not - // yet displayed can be examined. - private void getGroupTextViews(AbsListView group, ArrayList list) { - for (int i = 0; i < group.getAdapter().getCount(); i++) { - View child = group.getAdapter().getView(i, null, group); - if (child instanceof AbsListView) { - getGroupTextViews((AbsListView)child, list); - } else if (child instanceof ViewGroup) { - getGroupTextViews((ViewGroup)child, list); - } else if (child instanceof TextView) { - String viewText = ((TextView)child).getText().toString(); - if (viewText != null && viewText.length() > 0) { - list.add(viewText); - } - } - } - } - - public ArrayList getSharePopupOption() { - ArrayList displayedOptions = new ArrayList<>(); - AbsListView shareMenu = getDisplayedShareList(); - getGroupTextViews(shareMenu, displayedOptions); - return displayedOptions; - } - - public ArrayList getShareSubMenuOption() { - ArrayList displayedOptions = new ArrayList<>(); - AbsListView shareMenu = getDisplayedShareList(); - getGroupTextViews(shareMenu, displayedOptions); - return displayedOptions; - } - - public ArrayList getShareOptionsList() { - if (Build.VERSION.SDK_INT >= 14) { - return getShareSubMenuOption(); - } else { - return getSharePopupOption(); - } - } - - private boolean optionDisplayed(String shareOption, ArrayList displayedOptions) { - for (String displayedOption: displayedOptions) { - if (shareOption.equals(displayedOption)) { - return true; - } - } - return false; - } - - private AbsListView mViewGroup; - - private AbsListView getDisplayedShareList() { - mViewGroup = null; - boolean success = waitForCondition(new Condition() { - @Override - public boolean isSatisfied() { - ArrayList views = mSolo.getCurrentViews(); - for (View view : views) { - // List may be displayed in different view formats. - // On JB, GridView is common; on ICS-, ListView is common. - if (view instanceof ListView || - view instanceof GridView) { - mViewGroup = (AbsListView)view; - return true; - } - } - return false; - } - }, MAX_WAIT_MS); - mAsserter.ok(success,"Got the displayed share options?", "Got the share options view"); - return mViewGroup; - } -} diff --git a/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/testSnackbarAPI.java b/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/testSnackbarAPI.java deleted file mode 100644 index 893f98a51..000000000 --- a/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/testSnackbarAPI.java +++ /dev/null @@ -1,52 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this file, - * You can obtain one at http://mozilla.org/MPL/2.0/. */ - -package org.mozilla.gecko.tests; - -import static org.mozilla.gecko.tests.helpers.AssertionHelper.fFail; - -import org.mozilla.gecko.EventDispatcher; -import org.mozilla.gecko.util.EventCallback; -import org.mozilla.gecko.util.NativeEventListener; -import org.mozilla.gecko.util.NativeJSObject; - -public class testSnackbarAPI extends JavascriptTest implements NativeEventListener { - // Snackbar.LENGTH_INDEFINITE: To avoid tests depending on the android design support library - private static final int SNACKBAR_LENGTH_INDEFINITE = -2; - - public testSnackbarAPI() { - super("testSnackbarAPI.js"); - } - - @Override - public void handleMessage(String event, NativeJSObject message, EventCallback callback) { - mAsserter.is(event, "Snackbar:Show", "Received Snackbar:Show event"); - - try { - mAsserter.is(message.getString("message"), "This is a Snackbar", "Snackbar message"); - mAsserter.is(message.getInt("duration"), SNACKBAR_LENGTH_INDEFINITE, "Snackbar duration"); - - NativeJSObject action = message.getObject("action"); - - mAsserter.is(action.getString("label"), "Click me", "Snackbar action label"); - - } catch (Exception e) { - fFail("Event does not contain expected data: " + e.getMessage()); - } - } - - @Override - public void setUp() throws Exception { - super.setUp(); - - EventDispatcher.getInstance().registerGeckoThreadListener(this, "Snackbar:Show"); - } - - @Override - public void tearDown() throws Exception { - super.tearDown(); - - EventDispatcher.getInstance().unregisterGeckoThreadListener(this, "Snackbar:Show"); - } -} diff --git a/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/testStateWhileLoading.java b/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/testStateWhileLoading.java deleted file mode 100644 index 7f7b47450..000000000 --- a/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/testStateWhileLoading.java +++ /dev/null @@ -1,40 +0,0 @@ -package org.mozilla.gecko.tests; - -import org.mozilla.gecko.tests.helpers.DeviceHelper; -import org.mozilla.gecko.tests.helpers.GeckoClickHelper; -import org.mozilla.gecko.tests.helpers.GeckoHelper; -import org.mozilla.gecko.tests.helpers.NavigationHelper; -import org.mozilla.gecko.tests.helpers.WaitHelper; - -/** - * This test ensures the back/forward state is correct when switching to loading pages - * to prevent regressions like Bug 1124190. - */ -public class testStateWhileLoading extends UITest { - public void testStateWhileLoading() { - if (!DeviceHelper.isTablet()) { - // This test case only covers tablets currently. - return; - } - - GeckoHelper.blockForReady(); - - NavigationHelper.enterAndLoadUrl(mStringHelper.ROBOCOP_LINK_TO_SLOW_LOADING); - - GeckoClickHelper.openCentralizedLinkInNewTab(); - - WaitHelper.waitForPageLoad(new Runnable() { - @Override - public void run() { - mTabStrip.switchToTab(1); - - // Assert that the state of the back button is correct - // after switching to the new (still loading) tab. - mToolbar.assertBackButtonIsNotEnabled(); - } - }); - - // Assert that the state of the back button is still correct after the page has loaded. - mToolbar.assertBackButtonIsNotEnabled(); - } -} diff --git a/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/testStumblerSetting.java b/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/testStumblerSetting.java deleted file mode 100644 index ac551b97f..000000000 --- a/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/testStumblerSetting.java +++ /dev/null @@ -1,90 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * * License, v. 2.0. If a copy of the MPL was not distributed with this - * * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -package org.mozilla.gecko.tests; - -import org.mozilla.gecko.AppConstants; -import org.mozilla.gecko.preferences.GeckoPreferences; -import org.mozilla.mozstumbler.service.AppGlobals; -import android.content.BroadcastReceiver; -import android.content.Context; -import android.content.Intent; -import android.content.IntentFilter; - -import com.robotium.solo.Condition; - -/* - * This test enables (checkbox checked) the Fennec setting to contribute to MLS, then waits for - * a response Intent from the stumbler service to confirm it has started. Then, it disables the - * service in the setting, and waits for confirmation that the servie has stopped. - */ -public class testStumblerSetting extends BaseTest { - boolean mIsEnabled; - - public void testStumblerSetting() { - if (!AppConstants.MOZ_STUMBLER_BUILD_TIME_ENABLED) { - mAsserter.info("Checking stumbler build config.", "Skipping test as Stumbler is not enabled in this build."); - return; - } - - blockForGeckoReady(); - - selectMenuItem(mStringHelper.SETTINGS_LABEL); - mAsserter.ok(mSolo.waitForText(mStringHelper.SETTINGS_LABEL), - "The Settings menu did not load", mStringHelper.SETTINGS_LABEL); - - String section = "^" + mStringHelper.MOZILLA_SECTION_LABEL + "$"; - waitForEnabledText(section); - mSolo.clickOnText(section); - - String itemTitle = "^" + mStringHelper.LOCATION_SERVICES_LABEL + "$"; - boolean foundText = waitForPreferencesText(itemTitle); - mAsserter.ok(foundText, "Waiting for settings item " + itemTitle + " in section " + section, - "The " + itemTitle + " option is present in section " + section); - - BroadcastReceiver enabledDisabledReceiver = new BroadcastReceiver() { - @Override - public void onReceive(Context context, Intent intent) { - if (intent.getAction().equals(AppGlobals.ACTION_TEST_SETTING_ENABLED)) { - mIsEnabled = true; - } else { - mIsEnabled = false; - } - } - }; - - Context context = getInstrumentation().getTargetContext(); - IntentFilter intentFilter = new IntentFilter(AppGlobals.ACTION_TEST_SETTING_ENABLED); - intentFilter.addAction(AppGlobals.ACTION_TEST_SETTING_DISABLED); - context.registerReceiver(enabledDisabledReceiver, intentFilter); - - boolean checked = mSolo.isCheckBoxChecked(itemTitle); - try { - mAsserter.ok(!checked, "Checking stumbler setting is unchecked.", "Unchecked as expected."); - - waitForEnabledText(itemTitle); - mSolo.clickOnText(itemTitle); - - mSolo.waitForCondition(new Condition() { - @Override - public boolean isSatisfied() { - return mIsEnabled; - } - }, 15000); - - mAsserter.ok(mIsEnabled, "Checking if stumbler became enabled.", "Stumbler is enabled."); - mSolo.clickOnText(itemTitle); - - mSolo.waitForCondition(new Condition() { - @Override - public boolean isSatisfied() { - return !mIsEnabled; - } - }, 15000); - - mAsserter.ok(!mIsEnabled, "Checking if stumbler became disabled.", "Stumbler is disabled."); - } finally { - context.unregisterReceiver(enabledDisabledReceiver); - } - } -} diff --git a/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/testThumbnails.java b/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/testThumbnails.java deleted file mode 100644 index 6cb42f37c..000000000 --- a/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/testThumbnails.java +++ /dev/null @@ -1,116 +0,0 @@ -package org.mozilla.gecko.tests; - -import org.mozilla.gecko.db.BrowserDB; - -import android.content.ContentResolver; -import android.graphics.Color; - -import com.robotium.solo.Condition; - -/** - * Test for thumbnail updates. - * - loads 2 pages, each of which yield an HTTP 200 - * - verifies thumbnails are updated for both pages - * - loads pages again; first page yields HTTP 200, second yields HTTP 404 - * - verifies thumbnail is updated for HTTP 200, but not HTTP 404 - * - finally, test that BrowserDB.removeThumbnails drops the thumbnails - */ -public class testThumbnails extends BaseTest { - public void testThumbnails() { - final String site1Url = getAbsoluteUrl("/robocop/robocop_404.sjs?type=changeColor"); - final String site2Url = getAbsoluteUrl("/robocop/robocop_404.sjs?type=do404"); - final String site1Title = "changeColor"; - final String site2Title = "do404"; - - // the session snapshot runnable is run 500ms after document stop. a - // 3000ms delay gives us 2.5 seconds to take the screenshot, which - // should be plenty of time, even on slow devices - final int thumbnailDelay = 3000; - - blockForGeckoReady(); - - // load sites; both will return HTTP 200 with a green background - inputAndLoadUrl(site1Url); - mSolo.sleep(thumbnailDelay); - inputAndLoadUrl(site2Url); - mSolo.sleep(thumbnailDelay); - inputAndLoadUrl(mStringHelper.ABOUT_HOME_URL); - waitForCondition(new ThumbnailTest(site1Title, Color.GREEN), 5000); - mAsserter.is(getTopSiteThumbnailColor(site1Title), Color.GREEN, "Top site thumbnail updated for HTTP 200"); - waitForCondition(new ThumbnailTest(site2Title, Color.GREEN), 5000); - mAsserter.is(getTopSiteThumbnailColor(site2Title), Color.GREEN, "Top site thumbnail updated for HTTP 200"); - - // load sites again; both will have red background, and do404 will return HTTP 404 - inputAndLoadUrl(site1Url); - mSolo.sleep(thumbnailDelay); - inputAndLoadUrl(site2Url); - mSolo.sleep(thumbnailDelay); - inputAndLoadUrl(mStringHelper.ABOUT_HOME_URL); - waitForCondition(new ThumbnailTest(site1Title, Color.RED), 5000); - mAsserter.is(getTopSiteThumbnailColor(site1Title), Color.RED, "Top site thumbnail updated for HTTP 200"); - waitForCondition(new ThumbnailTest(site2Title, Color.GREEN), 5000); - mAsserter.is(getTopSiteThumbnailColor(site2Title), Color.GREEN, "Top site thumbnail not updated for HTTP 404"); - - // test dropping thumbnails - final ContentResolver resolver = getActivity().getContentResolver(); - final DatabaseHelper helper = new DatabaseHelper(getActivity(), mAsserter); - final BrowserDB db = helper.getProfileDB(); - - // check that the thumbnail is non-null - byte[] thumbnailData = db.getThumbnailForUrl(resolver, site1Url); - mAsserter.ok(thumbnailData != null && thumbnailData.length > 0, "Checking for thumbnail data", "No thumbnail data found"); - // drop thumbnails - db.removeThumbnails(resolver); - // check that the thumbnail is now null - thumbnailData = db.getThumbnailForUrl(resolver, site1Url); - mAsserter.ok(thumbnailData == null || thumbnailData.length == 0, "Checking for thumbnail data", "Thumbnail data found"); - } - - private class ThumbnailTest implements Condition { - private final String mTitle; - private final int mColor; - - public ThumbnailTest(String title, int color) { - mTitle = title; - mColor = color; - } - - @Override - public boolean isSatisfied() { - return getTopSiteThumbnailColor(mTitle) == mColor; - } - } - - private int getTopSiteThumbnailColor(String title) { - // This test is not currently run, so this just needs to compile. - return -1; -// ViewGroup topSites = (ViewGroup) getActivity().findViewById(mTopSitesId); -// if (topSites != null) { -// final int childCount = topSites.getChildCount(); -// for (int i = 0; i < childCount; i++) { -// View child = topSites.getChildAt(i); -// if (child != null) { -// TextView titleView = (TextView) child.findViewById(R.id.title); -// if (titleView != null) { -// if (titleView.getText().equals(title)) { -// ImageView thumbnailView = (ImageView) child.findViewById(R.id.thumbnail); -// if (thumbnailView != null) { -// Bitmap thumbnail = ((BitmapDrawable) thumbnailView.getDrawable()).getBitmap(); -// return thumbnail.getPixel(0, 0); -// } else { -// mAsserter.dumpLog("getTopSiteThumbnailColor: unable to find mThumbnailId: "+R.id.thumbnail); -// } -// } -// } else { -// mAsserter.dumpLog("getTopSiteThumbnailColor: unable to find R.id.title: "+R.id.title); -// } -// } else { -// mAsserter.dumpLog("getTopSiteThumbnailColor: skipped null child at index "+i); -// } -// } -// } else { -// mAsserter.dumpLog("getTopSiteThumbnailColor: unable to find mTopSitesId: " + mTopSitesId); -// } -// return -1; - } -} diff --git a/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/testTrackingProtection.java b/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/testTrackingProtection.java deleted file mode 100644 index c27ff0094..000000000 --- a/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/testTrackingProtection.java +++ /dev/null @@ -1,65 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this file, - * You can obtain one at http://mozilla.org/MPL/2.0/. */ - -package org.mozilla.gecko.tests; - -import static org.mozilla.gecko.tests.helpers.AssertionHelper.fFail; - -import org.mozilla.gecko.EventDispatcher; -import org.mozilla.gecko.GeckoApp; -import org.mozilla.gecko.GeckoAppShell; -import org.mozilla.gecko.util.GeckoEventListener; - -import org.json.JSONException; -import org.json.JSONObject; - -public class testTrackingProtection extends JavascriptTest implements GeckoEventListener { - private String mLastTracking; - - public testTrackingProtection() { - super("testTrackingProtection.js"); - } - - @Override - public void handleMessage(String event, final JSONObject message) { - if (event.equals("Content:SecurityChange")) { - try { - JSONObject identity = message.getJSONObject("identity"); - JSONObject mode = identity.getJSONObject("mode"); - mLastTracking = mode.getString("tracking"); - mAsserter.dumpLog("Security change (tracking): " + mLastTracking); - } catch (Exception e) { - fFail("Can't extract tracking state from JSON"); - } - } - - if (event.equals("Test:Expected")) { - try { - String expected = message.getString("expected"); - mAsserter.is(mLastTracking, expected, "Tracking matched expectation"); - mAsserter.dumpLog("Testing (tracking): " + mLastTracking + " = " + expected); - } catch (Exception e) { - fFail("Can't extract expected state from JSON"); - } - } - } - - @Override - public void setUp() throws Exception { - super.setUp(); - - EventDispatcher.getInstance().registerGeckoThreadListener(this, - "Content:SecurityChange", - "Test:Expected"); - } - - @Override - public void tearDown() throws Exception { - super.tearDown(); - - EventDispatcher.getInstance().unregisterGeckoThreadListener(this, - "Content:SecurityChange", - "Test:Expected"); - } -} diff --git a/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/testUITelemetry.java b/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/testUITelemetry.java deleted file mode 100644 index 30d7c169c..000000000 --- a/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/testUITelemetry.java +++ /dev/null @@ -1,56 +0,0 @@ -package org.mozilla.gecko.tests; - -import org.mozilla.gecko.AppConstants; -import org.mozilla.gecko.PrefsHelper; -import org.mozilla.gecko.Telemetry; -import org.mozilla.gecko.TelemetryContract.Event; -import org.mozilla.gecko.TelemetryContract.Method; -import org.mozilla.gecko.TelemetryContract.Reason; -import org.mozilla.gecko.TelemetryContract.Session; - -import android.util.Log; - -public class testUITelemetry extends JavascriptTest { - public testUITelemetry() { - super("testUITelemetry.js"); - } - - @Override - public void testJavascript() throws Exception { - blockForGeckoReady(); - - // We can't run these tests unless telemetry is turned on -- - // the events will be dropped on the floor. - Log.i("GeckoTest", "Enabling telemetry."); - PrefsHelper.setPref(AppConstants.TELEMETRY_PREF_NAME, true); - - Log.i("GeckoTest", "Adding telemetry events."); - try { - Telemetry.sendUIEvent(Event._TEST1, Method._TEST1); - Telemetry.startUISession(Session._TEST_STARTED_TWICE); - Telemetry.sendUIEvent(Event._TEST2, Method._TEST1); - - // We can only start one session per name, so this call should be ignored. - Telemetry.startUISession(Session._TEST_STARTED_TWICE); - - Telemetry.sendUIEvent(Event._TEST2, Method._TEST2); - Telemetry.startUISession(Session._TEST_STOPPED_TWICE); - Telemetry.sendUIEvent(Event._TEST3, Method._TEST1, "foobarextras"); - Telemetry.stopUISession(Session._TEST_STARTED_TWICE, Reason._TEST1); - Telemetry.sendUIEvent(Event._TEST4, Method._TEST1, "barextras"); - Telemetry.stopUISession(Session._TEST_STOPPED_TWICE, Reason._TEST2); - - // This session is already stopped, so this call should be ignored. - Telemetry.stopUISession(Session._TEST_STOPPED_TWICE, Reason._TEST_IGNORED); - - // Method defaults to Method.NONE - Telemetry.sendUIEvent(Event._TEST1); - } catch (Exception e) { - Log.e("GeckoTest", "Oops.", e); - } - - Log.i("GeckoTest", "Running remaining JS test code."); - super.testJavascript(); - } -} - diff --git a/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/testUnifiedTelemetryClientId.java b/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/testUnifiedTelemetryClientId.java deleted file mode 100644 index aaaded4c8..000000000 --- a/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/testUnifiedTelemetryClientId.java +++ /dev/null @@ -1,265 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -package org.mozilla.gecko.tests; - -import static org.mozilla.gecko.tests.helpers.AssertionHelper.*; - -import android.util.Log; -import org.json.JSONException; -import org.json.JSONObject; -import org.mozilla.gecko.GeckoProfile; - -import java.io.File; -import java.io.IOException; -import java.util.UUID; - -public class testUnifiedTelemetryClientId extends JavascriptBridgeTest { - private static final String TEST_JS = "testUnifiedTelemetryClientId.js"; - - private static final String CLIENT_ID_PATH = "datareporting/state.json"; - private static final String FHR_DIR_PATH = "healthreport/"; - private static final String FHR_CLIENT_ID_PATH = FHR_DIR_PATH + "state.json"; - - private GeckoProfile profile; - private File profileDir; - private File[] filesToDeleteOnReset; - - public void setUp() throws Exception { - super.setUp(); - profile = getTestProfile(); - profileDir = profile.getDir(); // Assumes getDir is tested. - filesToDeleteOnReset = new File[] { - getClientIdFile(), - getFHRClientIdFile(), - getFHRClientIdParentDir(), - }; - } - - public void tearDown() throws Exception { - // Don't clear cache because who knows what state Gecko is in. - deleteClientIDFiles(); - super.tearDown(); - } - - private void deleteClientIDFiles() { - Log.d(LOGTAG, "deleteClientIDFiles: begin"); - - for (final File file : filesToDeleteOnReset) { - file.delete(); // can't check return value because the file may not exist before deletion. - fAssertFalse("Deleted file in reset does not exist", file.exists()); // sanity check. - } - - Log.d(LOGTAG, "deleteClientIDFiles: end"); - } - - public void testUnifiedTelemetryClientId() throws Exception { - blockForReadyAndLoadJS(TEST_JS); - fAssertTrue("Profile directory exists", profileDir.exists()); - - // Important note: we cannot stop Gecko from running while we run this test and - // Gecko is capable of creating client ID files while we run this test. However, - // ClientID.jsm will not touch modify the client ID files on disk if its client - // ID cache is filled. As such, we prevent it from touching the disk by intentionally - // priming the cache & deleting the files it added now, and resetting the cache at the - // latest possible moment before we attempt to test the client ID file. - // - // This is fragile because it relies on the ClientID cache's implementation, however, - // some alternatives (e.g. changing file system permissions, file locking) are worse - // because they can fire error handling code, which is not currently under test. - // - // First, we delete the test files - we don't want the cache prime to fail which could happen if - // these files are around & corrupted from a previous test/install. Then we prime the cache, - // and delete the files the cache priming added, so the tests are ready to add their own version - // of these files. - deleteClientIDFiles(); - primeJsClientIdCache(); - deleteClientIDFiles(); - - // TODO: If these tests weren't so expensive to run in automation, - // this should be two separate tests to avoid storing state between tests. - testJavaCreatesClientId(); // leaves cache filled. - deleteClientIDFiles(); - testJsCreatesClientId(); // leaves cache filled. - deleteClientIDFiles(); - testJavaMigratesFromHealthReport(); // leaves cache filled. - deleteClientIDFiles(); - testJsMigratesFromHealthReport(); // leaves cache filled. - - getJS().syncCall("endTest"); - } - - /** - * Scenario: Java creates client ID: - * * Fennec starts on fresh profile - * * Java code creates the client ID in datareporting/state.json - * * Js accesses client ID from the same file - * * Assert the client IDs are the same - */ - private void testJavaCreatesClientId() throws Exception { - Log.d(LOGTAG, "testJavaCreatesClientId: start"); - - fAssertFalse("Client id file does not exist yet", getClientIdFile().exists()); - - final String clientIdFromJava = getClientIdFromJava(); - resetJSCache(); - final String clientIdFromJS = getClientIdFromJS(); - // allow for the case where gecko updates the client ID after the first get - final String clientIdFromJavaAgain = getClientIdFromJava(); - fAssertTrue("Client ID from Java equals ID from JS", - clientIdFromJava.equals(clientIdFromJS) || - clientIdFromJavaAgain.equals(clientIdFromJS)); - - final String clientIdFromJSCache = getClientIdFromJS(); - resetJSCache(); - final String clientIdFromJSFileAgain = getClientIdFromJS(); - fAssertEquals("Same client ID retrieved from JS cache", clientIdFromJavaAgain, clientIdFromJSCache); - fAssertEquals("Same client ID retrieved from JS file", clientIdFromJavaAgain, clientIdFromJSFileAgain); - } - - /** - * Scenario: JS creates client ID - * * Fennec starts on a fresh profile - * * Js creates the client ID in datareporting/state.json - * * Java access the client ID from the same file - * * Assert the client IDs are the same - */ - private void testJsCreatesClientId() throws Exception { - Log.d(LOGTAG, "testJsCreatesClientId: start"); - - fAssertFalse("Client id file does not exist yet", getClientIdFile().exists()); - - resetJSCache(); - final String clientIdFromJS = getClientIdFromJS(); - final String clientIdFromJava = getClientIdFromJava(); - fAssertEquals("Client ID from JS equals ID from Java", clientIdFromJS, clientIdFromJava); - - final String clientIdFromJSCache = getClientIdFromJS(); - final String clientIdFromJavaAgain = getClientIdFromJava(); - resetJSCache(); - final String clientIdFromJSFileAgain = getClientIdFromJS(); - fAssertEquals("Same client ID retrieved from JS cache", clientIdFromJS, clientIdFromJSCache); - fAssertEquals("Same client ID retrieved from JS file", clientIdFromJS, clientIdFromJSFileAgain); - fAssertEquals("Same client ID retrieved from Java", clientIdFromJS, clientIdFromJavaAgain); - } - - /** - * Scenario: Java migrates client ID from FHR client ID file. - * * FHR file already exists. - * * Fennec starts on fresh profile - * * Java code merges client ID to datareporting/state.json from healthreport/state.json - * * Js accesses client ID from the same file - * * Assert the client IDs are the same - */ - private void testJavaMigratesFromHealthReport() throws Exception { - Log.d(LOGTAG, "testJavaMigratesFromHealthReport: start"); - - fAssertFalse("Client id file does not exist yet", getClientIdFile().exists()); - fAssertFalse("Health report file does not exist yet", getFHRClientIdFile().exists()); - - final String expectedClientId = UUID.randomUUID().toString(); - createFHRClientIdFile(expectedClientId); - - final String clientIdFromJava = getClientIdFromJava(); - fAssertEquals("Health report client ID merged by Java", expectedClientId, clientIdFromJava); - resetJSCache(); - final String clientIdFromJS = getClientIdFromJS(); - fAssertEquals("Merged client ID read by JS", expectedClientId, clientIdFromJS); - - final String clientIdFromJavaAgain = getClientIdFromJava(); - final String clientIdFromJSCache = getClientIdFromJS(); - resetJSCache(); - final String clientIdFromJSFileAgain = getClientIdFromJS(); - fAssertEquals("Same client ID retrieved from Java", expectedClientId, clientIdFromJavaAgain); - fAssertEquals("Same client ID retrieved from JS cache", expectedClientId, clientIdFromJSCache); - fAssertEquals("Same client ID retrieved from JS file", expectedClientId, clientIdFromJSFileAgain); - } - - /** - * Scenario: JS merges client ID from FHR client ID file. - * * FHR file already exists. - * * Fennec starts on a fresh profile - * * Js merges the client ID to datareporting/state.json from healthreport/state.json - * * Java access the client ID from the same file - * * Assert the client IDs are the same - */ - private void testJsMigratesFromHealthReport() throws Exception { - Log.d(LOGTAG, "testJsMigratesFromHealthReport: start"); - - fAssertFalse("Client id file does not exist yet", getClientIdFile().exists()); - fAssertFalse("Health report file does not exist yet", getFHRClientIdFile().exists()); - - final String expectedClientId = UUID.randomUUID().toString(); - createFHRClientIdFile(expectedClientId); - - resetJSCache(); - final String clientIdFromJS = getClientIdFromJS(); - fAssertEquals("Health report client ID merged by JS", expectedClientId, clientIdFromJS); - final String clientIdFromJava = getClientIdFromJava(); - fAssertEquals("Merged client ID read by Java", expectedClientId, clientIdFromJava); - - final String clientIdFromJavaAgain = getClientIdFromJava(); - final String clientIdFromJSCache = getClientIdFromJS(); - resetJSCache(); - final String clientIdFromJSFileAgain = getClientIdFromJS(); - fAssertEquals("Same client ID retrieved from Java", expectedClientId, clientIdFromJavaAgain); - fAssertEquals("Same client ID retrieved from JS cache", expectedClientId, clientIdFromJSCache); - fAssertEquals("Same client ID retrieved from JS file", expectedClientId, clientIdFromJSFileAgain); - } - - private String getClientIdFromJava() throws IOException { - // This assumes implementation details: it assumes the client ID - // file is created when Java attempts to retrieve it if it does not exist. - final String clientId = profile.getClientId(); - fAssertNotNull("Returned client ID is not null", clientId); - fAssertTrue("Client ID file exists after getClientId call", getClientIdFile().exists()); - return clientId; - } - - private String getClientIdFromJS() { - return getBlockingFromJsString("clientId"); - } - - /** - * Must be called after Gecko is loaded. - */ - private void primeJsClientIdCache() { - // Not the cleanest way, but it works. - getClientIdFromJS(); - } - - /** - * Resets the client ID cache in ClientID.jsm. This method *must* be called after - * Gecko is loaded or else this method will hang. - * - * Note: we do this for very specific reasons - see the comment in the test method - * ({@link #testUnifiedTelemetryClientId()}) for more. - */ - private void resetJSCache() { - // HACK: the backing JS method is a promise with no return value. Rather than writing a method - // to handle this (for time reasons), I call the get String method and don't access the return value. - getBlockingFromJsString("reset"); - } - - private File getClientIdFile() { - return new File(profileDir, CLIENT_ID_PATH); - } - - private File getFHRClientIdParentDir() { - return new File(profileDir, FHR_DIR_PATH); - } - - private File getFHRClientIdFile() { - return new File(profileDir, FHR_CLIENT_ID_PATH); - } - - private void createFHRClientIdFile(final String clientId) throws JSONException { - fAssertTrue("FHR directory created", getFHRClientIdParentDir().mkdirs()); - - final JSONObject obj = new JSONObject(); - obj.put("clientID", clientId); - profile.writeFile(FHR_CLIENT_ID_PATH, obj.toString()); - fAssertTrue("FHR client ID file exists after writing", getFHRClientIdFile().exists()); - } -} diff --git a/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/testVideoControls.java b/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/testVideoControls.java deleted file mode 100644 index 5164815c4..000000000 --- a/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/testVideoControls.java +++ /dev/null @@ -1,9 +0,0 @@ -package org.mozilla.gecko.tests; - - - -public class testVideoControls extends JavascriptTest { - public testVideoControls() { - super("testVideoControls.js"); - } -} diff --git a/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/testVkbOverlap.java b/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/testVkbOverlap.java deleted file mode 100644 index f5a54a0e9..000000000 --- a/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/testVkbOverlap.java +++ /dev/null @@ -1,105 +0,0 @@ -package org.mozilla.gecko.tests; - -import org.mozilla.gecko.Actions; -import org.mozilla.gecko.PaintedSurface; - -import android.net.Uri; - -/** - * A test to ensure that when an input field is focused, it is not obscured by the VKB. - * - Loads a page with an input field past the bottom of the visible area. - * - scrolls down to make the input field visible at the bottom of the screen. - * - taps on the input field to bring up the VKB - * - verifies that the input field is still visible. - */ -public class testVkbOverlap extends PixelTest { - private static final int CURSOR_BLINK_PERIOD = 500; - private static final int LESS_THAN_CURSOR_BLINK_PERIOD = CURSOR_BLINK_PERIOD - 50; - private static final int PAGE_SETTLE_TIME = 5000; - - public void testVkbOverlap() { - blockForGeckoReady(); - testSetup("initial-scale=1.0, user-scalable=no", false); - testSetup("initial-scale=1.0", false); - testSetup("", "phone".equals(mDevice.type)); - } - - private void testSetup(String viewport, boolean shouldZoom) { - loadAndPaint(getAbsoluteUrl("/robocop/test_viewport.sjs?metadata=" + Uri.encode(viewport))); - - // scroll to the bottom of the page and let it settle - Actions.RepeatedEventExpecter paintExpecter = mActions.expectPaint(); - MotionEventHelper meh = new MotionEventHelper(getInstrumentation(), mDriver.getGeckoLeft(), mDriver.getGeckoTop()); - meh.dragSync(10, 150, 10, 50); - - // the input field has a green background, so let's count the number of green pixels - int greenPixelCount = 0; - - PaintedSurface painted = waitForPaint(paintExpecter); - paintExpecter.unregisterListener(); - try { - greenPixelCount = countGreenPixels(painted); - } finally { - painted.close(); - } - - mAsserter.ok(greenPixelCount > 0, "testInputVisible", "Found " + greenPixelCount + " green pixels after scrolling"); - - paintExpecter = mActions.expectPaint(); - // the input field should be in the bottom-left corner, so tap thereabouts - meh.tap(5, mDriver.getGeckoHeight() - 5); - - // After tapping in the input field, the page needs some time to do stuff, like draw and undraw the focus highlight - // on the input field, trigger the VKB, process any resulting events generated by the system, and scroll the page. So - // we give it a few seconds to do all that. We are sufficiently generous with our definition of "few seconds" to - // prevent intermittent test failures. - try { - Thread.sleep(PAGE_SETTLE_TIME); - } catch (InterruptedException ie) { - ie.printStackTrace(); - } - - // now that the focus is in the text field we will repaint every 500ms as the cursor blinks, so we need to use a smaller - // "no paints" threshold to consider the page painted - paintExpecter.blockUntilClear(LESS_THAN_CURSOR_BLINK_PERIOD); - paintExpecter.unregisterListener(); - painted = mDriver.getPaintedSurface(); - try { - // if the vkb scrolled into view as expected, then the number of green pixels now visible should be about the - // same as it was before, since the green pixels indicate the text input is in view. use a fudge factor of 0.9 to - // account for borders and such of the text input which might still be out of view. - int newCount = countGreenPixels(painted); - - // if zooming is allowed, the number of green pixels visible should have increased substantially - if (shouldZoom) { - mAsserter.ok(newCount > greenPixelCount * 1.5, "testVkbOverlap", "Found " + newCount + " green pixels after tapping; expected " + greenPixelCount); - } else { - mAsserter.ok((Math.abs(greenPixelCount - newCount) / greenPixelCount < 0.1), "testVkbOverlap", "Found " + newCount + " green pixels after tapping; expected " + greenPixelCount); - } - } finally { - painted.close(); - } - } - - private int countGreenPixels(PaintedSurface painted) { - int count = 0; - for (int y = painted.getHeight() - 1; y >= 0; y--) { - for (int x = painted.getWidth() - 1; x >= 0; x--) { - int pixel = painted.getPixelAt(x, y); - int r = (pixel >> 16) & 0xFF; - int g = (pixel >> 8) & 0xFF; - int b = (pixel & 0xFF); - if (g > (r + 0x30) && g > (b + 0x30)) { - // there's more green in this pixel than red or blue, so count it. - // the reason this is so hacky-looking is because even though green is supposed to - // be (r,g,b) = (0x00, 0x80, 0x00), the GL readback ends up coming back quite - // different. - count++; - } - // uncomment for debugging: - // if (pixel != -1) mAsserter.dumpLog("Pixel at " + x + ", " + y + ": " + Integer.toString(pixel, 16)); - } - } - return count; - } -} -- cgit v1.2.3