diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 61c03de38..ea070f8da 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -12,6 +12,7 @@ stages: before_script: - export GRADLE_USER_HOME=$PWD/.gradle - export ANDROID_COMPILE_SDK=`sed -n 's,.*compileSdkVersion\s*\([0-9][0-9]*\).*,\1,p' app/build.gradle` + - alias sdkmanager="sdkmanager --no_https" - echo y | sdkmanager "platforms;android-${ANDROID_COMPILE_SDK}" > /dev/null .test-template: &test-template @@ -58,9 +59,17 @@ errorprone: # connectedCheck to test all the build flavors .connected-template: &connected-template script: - - ./gradlew assembleDebug - - echo y | sdkmanager "platforms;android-$AVD_SDK" > /dev/null + - ./gradlew assembleFullDebug + - export AVD_SDK=`echo $CI_JOB_NAME | awk '{print $2}'` + - export AVD_TAG=`echo $CI_JOB_NAME | awk '{print $3}'` + - export AVD_ARCH=`echo $CI_JOB_NAME | awk '{print $4}'` + - export AVD_PACKAGE="system-images;android-${AVD_SDK};${AVD_TAG};${AVD_ARCH}" + - echo $AVD_PACKAGE + - emulator -accel-check || true + - alias sdkmanager + - echo y | sdkmanager "emulator" "platforms;android-$AVD_SDK" > /dev/null - if ! avdmanager list avd | grep "Name. avd$AVD_SDK$"; then + set -x; rm -rf ~/.android/avd $ANDROID_HOME/system-images; echo y | sdkmanager "$AVD_PACKAGE" > /dev/null; echo no | avdmanager create avd --name avd$AVD_SDK --tag "$AVD_TAG" --package "$AVD_PACKAGE" --sdcard 64M --device "Nexus 5"; @@ -68,21 +77,90 @@ errorprone: sed -i '/^hw\.ramSize\s*=.*/d' ~/.android/avd/*.avd/config.ini; echo "hw.ramSize=$RAMSIZE" >> ~/.android/avd/*.avd/config.ini; avdmanager list avd; + set +x; fi - - emulator64-arm -avd avd$AVD_SDK -no-audio -no-window -no-snapstorage & + - adb start-server + - ls -l ~/.android + - emulator -avd avd$AVD_SDK + -no-audio + -no-jni + -no-snapstorage + -no-window + -skip-adb-auth + -verbose + -wipe-data + & - wait-for-emulator + - adb devices - adb shell input keyevent 82 & - - ./gradlew connectedFullDebugAndroidTest || (adb -e logcat -d > logcat.txt; exit 1) + - test $AVD_SDK -ge 25 || export FLAG=-Pandroid.testInstrumentationRunnerArguments.notAnnotation=android.test.suitebuilder.annotation.LargeTest + - ./gradlew connectedFullDebugAndroidTest $FLAG || (adb -e logcat -d > logcat.txt; exit 1) -connected24: +connected 22 default armeabi-v7a: retry: 1 + only: + - merge_requests <<: *test-template - variables: - AVD_SDK: "24" - AVD_TAG: "default" - AVD_PACKAGE: "system-images;android-${AVD_SDK};${AVD_TAG};armeabi-v7a" <<: *connected-template +.kvm-template: &kvm-template + tags: + - fdroid + - kvm + only: + - merge_requests + - branches@fdroid/fdroidclient + <<: *test-template + <<: *connected-template + +connected 17 default x86: + <<: *kvm-template + +connected 18 default x86: + <<: *kvm-template + only: + - master@fdroid/fdroidclient + +connected 19 default x86: + <<: *kvm-template + only: + - master@fdroid/fdroidclient + +connected 21 default x86: + <<: *kvm-template + only: + - master@fdroid/fdroidclient + +connected 22 default x86: + <<: *kvm-template + only: + - master@fdroid/fdroidclient + +connected 23 default x86: + <<: *kvm-template + +connected 24 google_apis x86: + <<: *kvm-template + only: + - master@fdroid/fdroidclient + +connected 25 default x86: + <<: *kvm-template + +connected 26 google_apis x86: + <<: *kvm-template + only: + - master@fdroid/fdroidclient + +connected 27 google_apis_playstore x86: + <<: *kvm-template + only: + - master@fdroid/fdroidclient + +connected 28 default x86_64: + <<: *kvm-template + + deploy_nightly: stage: deploy only: diff --git a/app/src/androidTest/java/org/fdroid/fdroid/MainActivityEspressoTest.java b/app/src/androidTest/java/org/fdroid/fdroid/MainActivityEspressoTest.java index 984e2869a..307297e8e 100644 --- a/app/src/androidTest/java/org/fdroid/fdroid/MainActivityEspressoTest.java +++ b/app/src/androidTest/java/org/fdroid/fdroid/MainActivityEspressoTest.java @@ -21,8 +21,8 @@ import org.fdroid.fdroid.views.main.MainActivity; import org.hamcrest.Matchers; import org.junit.After; import org.junit.AfterClass; +import org.junit.Before; import org.junit.BeforeClass; -import org.junit.Ignore; import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; @@ -45,30 +45,36 @@ import static android.support.test.espresso.matcher.ViewMatchers.withText; import static org.hamcrest.Matchers.allOf; import static org.hamcrest.Matchers.not; import static org.junit.Assert.assertTrue; +import static org.junit.Assume.assumeTrue; -@Ignore @RunWith(AndroidJUnit4.class) -@LargeTest public class MainActivityEspressoTest { public static final String TAG = "MainActivityEspressoTest"; /** + * Emulators older than {@code android-25} seem to fail at running Espresso tests. + *

* ARM emulators are too slow to run these tests in a useful way. The sad * thing is that it would probably work if Android didn't put up the ANR * "Process system isn't responding" on boot each time. There seems to be no * way to increase the ANR timeout. */ + private static boolean canRunEspresso() { + if (Build.VERSION.SDK_INT < 25 + || (Build.SUPPORTED_ABIS[0].startsWith("arm") && isEmulator())) { + Log.e(TAG, "SKIPPING TEST: ARM emulators are too slow to run these tests in a useful way"); + return false; + } + return true; + } + @BeforeClass public static void classSetUp() { - Log.i(TAG, "setUp " + isEmulator() + " " + Build.SUPPORTED_ABIS[0]); - if (Build.SUPPORTED_ABIS[0].startsWith("arm") && isEmulator()) { - Log.e(TAG, "SKIPPING TEST: ARM emulators are too slow to run these tests in a useful way"); - org.junit.Assume.assumeTrue(false); - return; - } - IdlingPolicies.setIdlingResourceTimeout(10, TimeUnit.MINUTES); IdlingPolicies.setMasterPolicyTimeout(10, TimeUnit.MINUTES); + if (!canRunEspresso()) { + return; + } Instrumentation instrumentation = InstrumentationRegistry.getInstrumentation(); try { UiDevice.getInstance(instrumentation) @@ -106,6 +112,11 @@ public class MainActivityEspressoTest { || "google_sdk".equals(Build.PRODUCT); } + @Before + public void setUp() { + assumeTrue(canRunEspresso()); + } + /** * Placate {@link android.os.StrictMode} * @@ -151,7 +162,7 @@ public class MainActivityEspressoTest { } } - @Test + @LargeTest public void showSettings() { ViewInteraction settingsBottonNavButton = onView( allOf(withText(R.string.menu_settings), isDisplayed())); @@ -168,14 +179,14 @@ public class MainActivityEspressoTest { onView(withText(R.string.installed_apps__activity_title)).check(matches(isDisplayed())); } - @Test + @LargeTest public void showUpdates() { ViewInteraction updatesBottonNavButton = onView(allOf(withText(R.string.main_menu__updates), isDisplayed())); updatesBottonNavButton.perform(click()); onView(withText(R.string.main_menu__updates)).check(matches(isDisplayed())); } - @Test + @LargeTest public void startSwap() { if (!BuildConfig.FLAVOR.startsWith("full")) { return; @@ -189,7 +200,7 @@ public class MainActivityEspressoTest { onView(withText(R.string.swap_send_fdroid)).check(matches(isDisplayed())); } - @Test + @LargeTest public void showCategories() { if (!BuildConfig.FLAVOR.startsWith("full")) { return; @@ -214,7 +225,7 @@ public class MainActivityEspressoTest { .perform(click()); } - @Test + @LargeTest public void showLatest() { if (!BuildConfig.FLAVOR.startsWith("full")) { return; @@ -236,7 +247,7 @@ public class MainActivityEspressoTest { .perform(click()); } - @Test + @LargeTest public void showSearch() { onView(allOf(withText(R.string.menu_settings), isDisplayed())).perform(click()); onView(withId(R.id.fab_search)).check(doesNotExist()); diff --git a/app/src/androidTest/java/org/fdroid/fdroid/net/HttpDownloaderTest.java b/app/src/androidTest/java/org/fdroid/fdroid/net/HttpDownloaderTest.java index 47400116c..57238613d 100644 --- a/app/src/androidTest/java/org/fdroid/fdroid/net/HttpDownloaderTest.java +++ b/app/src/androidTest/java/org/fdroid/fdroid/net/HttpDownloaderTest.java @@ -2,11 +2,15 @@ package org.fdroid.fdroid.net; import android.net.Uri; +import android.os.Build; +import android.util.Log; import org.fdroid.fdroid.ProgressListener; import org.junit.Test; import java.io.File; import java.io.IOException; +import java.util.ArrayList; +import java.util.Arrays; import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; @@ -15,22 +19,37 @@ import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; public class HttpDownloaderTest { + private static final String TAG = "HttpDownloaderTest"; - final String[] urls = { - "https://en.wikipedia.org/wiki/Index.html", - "https://mirrors.kernel.org/debian/dists/stable/Release", - "https://f-droid.org/repo/index.jar", - // sites that use SNI for HTTPS - "https://guardianproject.info/fdroid/repo/index.jar", - //"https://microg.org/fdroid/repo/index.jar", - //"https://grobox.de/fdroid/repo/index.jar", - }; + static final String[] URLS; + + // https://developer.android.com/reference/javax/net/ssl/SSLContext + static { + ArrayList tempUrls = new ArrayList<>(Arrays.asList( + "https://f-droid.org/repo/index-v1.jar", + // sites that use SNI for HTTPS + "https://mirrors.kernel.org/debian/dists/stable/Release", + "https://fdroid.tetaneutral.net/fdroid/repo/index-v1.jar", + "https://ftp.fau.de/fdroid/repo/index-v1.jar", + //"https://microg.org/fdroid/repo/index-v1.jar", + //"https://grobox.de/fdroid/repo/index.jar", + "https://guardianproject.info/fdroid/repo/index-v1.jar" + )); + if (Build.VERSION.SDK_INT >= 22) { + tempUrls.addAll(Arrays.asList( + "https://en.wikipedia.org/wiki/Index.html", // no SNI but weird ipv6 lookup issues + "https://mirror.cyberbits.eu/fdroid/repo/index-v1.jar" // TLSv1.2 only and SNI + )); + } + URLS = tempUrls.toArray(new String[tempUrls.size()]); + } private boolean receivedProgress; @Test public void downloadUninterruptedTest() throws IOException, InterruptedException { - for (String urlString : urls) { + for (String urlString : URLS) { + Log.i(TAG, "URL: " + urlString); Uri uri = Uri.parse(urlString); File destFile = File.createTempFile("dl-", ""); HttpDownloader httpDownloader = new HttpDownloader(uri, destFile); diff --git a/app/src/main/java/org/fdroid/fdroid/net/HttpDownloader.java b/app/src/main/java/org/fdroid/fdroid/net/HttpDownloader.java index eab3097f1..a6fe63dc2 100644 --- a/app/src/main/java/org/fdroid/fdroid/net/HttpDownloader.java +++ b/app/src/main/java/org/fdroid/fdroid/net/HttpDownloader.java @@ -177,6 +177,10 @@ public class HttpDownloader extends Downloader { connection.setRequestProperty("User-Agent", "F-Droid " + BuildConfig.VERSION_NAME); connection.setConnectTimeout(getTimeout()); + if (Build.VERSION.SDK_INT < 19) { // gzip encoding can be troublesome on old Androids + connection.setRequestProperty("Accept-Encoding", "identity"); + } + if (username != null && password != null) { // add authorization header from username / password if set String authString = username + ":" + password;