diff --git a/.travis.yml b/.travis.yml index 821766c12..eae20668e 100644 --- a/.travis.yml +++ b/.travis.yml @@ -4,9 +4,16 @@ jdk: oraclejdk8 sudo: required +env: + global: + - ANDROID_TARGET=android-22 + - ANDROID_ABI=arm64-v8a + + install: - pip install --user 'requests[security]' - - wget -r -nH -nd -np -R index.html* robots.txt* http://download.kiwix.org/dev/android/api/licenses/ -e robots=off -P $ANDROID_HOME/licenses || true + - wget -r -nH -nd -np -R index.html* robots.txt* http://download.kiwix.org/dev/android/api/licenses/ + -e robots=off -P $ANDROID_HOME/licenses || true before_cache: - rm -f $HOME/.gradle/caches/modules-2/modules-2.lock @@ -14,9 +21,9 @@ before_cache: cache: directories: - - $HOME/.gradle/caches/ - - $HOME/.gradle/wrapper/ - - $HOME/.android/build-cache + - "$HOME/.gradle/caches/" + - "$HOME/.gradle/wrapper/" + - "$HOME/.android/build-cache" android: components: @@ -25,8 +32,23 @@ android: - tools - build-tools-27.0.3 - android-27 + - extra-android-m2repository + - $ANDROID_TARGET + - sys-img-${ANDROID_ABI}-${ANDROID_TARGET} licenses: - - '.+' + - ".+" -script: ./gradlew assembleKiwixRelease testdroidUploadKiwix && ./testdroid.py +script: + - ./gradlew assembleKiwixDebug jacocoTestKiwixDebugUnitTestReport + - echo no | android create avd --force -n test -t $ANDROID_TARGET --abi $ANDROID_ABI + - emulator -avd test -no-skin -no-audio -no-window & + - android-wait-for-emulator + - adb shell setprop dalvik.vm.dexopt-flags v=n,o=v + - ./gradlew createKiwixDebugCoverageReport + - if [ "$TRAVIS_BRANCH" == "release" ]; + then ./gradlew publishKiwixRelease; fi + +after_success: + - bash <(curl -s https://codecov.io/bash) + - ./gradlew testdroidUploadKiwixDebug diff --git a/app/build.gradle b/app/build.gradle index f7fbf6b5f..60456806f 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -1,3 +1,4 @@ +import com.android.build.OutputFile import groovy.json.JsonSlurper buildscript { @@ -13,13 +14,18 @@ buildscript { } } -apply plugin: 'com.android.application' -apply plugin: 'kotlin-android' -apply plugin: 'kotlin-android-extensions' -apply plugin: 'kotlin-kapt' -apply plugin: 'checkstyle' +plugins { + id 'com.android.application' + id 'kotlin-android' + id 'kotlin-android-extensions' + id 'kotlin-kapt' + id 'checkstyle' + id 'io.objectbox' + id 'com.github.triplet.play' version '2.2.1' +} + apply plugin: 'testdroid' -apply plugin: 'io.objectbox' +apply plugin: 'jacoco-android' repositories { mavenCentral() @@ -30,7 +36,7 @@ repositories { google() } -String[] archs = ['arm64-v8a', 'armeabi', 'mips', 'mips64', 'x86', 'x86_64'] +String[] archs = ['arm64-v8a', 'armeabi-v7a', 'x86', 'x86_64'] dependencies { // Get kiwixlib online if it is not populated locally @@ -67,7 +73,7 @@ dependencies { exclude group: 'com.android.support', module: 'recyclerview-v7' } - androidTestCompile('com.schibsted.spain:barista:2.4.0') { + androidTestImplementation('com.schibsted.spain:barista:2.4.0') { exclude group: 'com.android.support' } @@ -118,19 +124,10 @@ dependencies { androidTestImplementation "org.mockito:mockito-android:2.24.5" // Leak canary - implementation 'com.squareup.leakcanary:leakcanary-android-no-op:1.6.3' - // Only enable leak canary in debug builds - configurations.all { config -> - if (config.name.contains('debug') || config.name.contains("Debug")) { - config.resolutionStrategy.eachDependency { details -> - if (details.requested.group == 'com.squareup.leakcanary' && - details.requested.name == 'leakcanary-android-no-op') { - details.useTarget(group: details.requested.group, name: 'leakcanary-android', - version: details.requested.version) - } - } - } - } + debugImplementation 'com.squareup.leakcanary:leakcanary-android:1.6.3' + androidTestImplementation 'com.squareup.leakcanary:leakcanary-android-no-op:1.6.3' + releaseImplementation 'com.squareup.leakcanary:leakcanary-android-no-op:1.6.3' + implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" implementation 'com.android.support.constraint:constraint-layout:1.1.3' implementation "android.arch.lifecycle:extensions:1.1.1" @@ -146,17 +143,28 @@ if (project.hasProperty('customDir')) { } // Set up flavours for each custom app in the directory -if(custom.listFiles()) { +if (custom.listFiles()) { custom.eachFile() { file -> def fileName = file.getName() - if (fileName.startsWith(".") || fileName.contains("test") || fileName == "main" || fileName.contains("Test")) { + if (fileName.startsWith(".") || + fileName.contains("test") || + fileName == "main" || + fileName.contains("Test")) { return } map.put(fileName, file.getAbsolutePath()) } } +jacoco { + toolVersion = "0.8.3" +} + +tasks.withType(Test) { + jacoco.includeNoLocationClasses = true +} + android { compileSdkVersion 27 @@ -197,8 +205,7 @@ android { debug { buildConfigField "String", "KIWIX_DOWNLOAD_URL", "\"http://download.kiwix.org/\"" buildConfigField "boolean", "KIWIX_ERROR_ACTIVITY", "false" - // True breaks local variables being shown in breakpoints - testCoverageEnabled false + testCoverageEnabled true } mock_network { @@ -213,19 +220,11 @@ android { matchingFallbacks = ['debug', 'release'] } - // Used to assess code coverage - coverage { - initWith debug - testCoverageEnabled true - matchingFallbacks = ['debug', 'release'] - } - // Release Type release { buildConfigField "String", "KIWIX_DOWNLOAD_URL", "\"http://download.kiwix.org/\"" buildConfigField "boolean", "KIWIX_ERROR_ACTIVITY", "false" } - } productFlavors { @@ -253,6 +252,7 @@ android { versionName "2.5" } } + // Custom apps built from a json file, zim file and icon set map.each { name, directory -> "$name" { @@ -274,15 +274,15 @@ android { sourceFile = file(directory + "/" + parsedJson.zim_file) } if (parsedJson.embed_zim) { - // Place content in each lib directory for embeded zims + // Place content in each lib directory for embeded zims for (String archName : archs) { - copy { - from sourceFile - into file(directory + "/jniLibs/" + archName) - rename { String filename -> "libcontent.so" } - } - } - parsedJson.zim_file = "libcontent.so" + copy { + from sourceFile + into file(directory + "/jniLibs/" + archName) + rename { String filename -> "libcontent.so" } + } + } + parsedJson.zim_file = "libcontent.so" } // Set custom config from json applicationId "$parsedJson.package" @@ -318,7 +318,7 @@ android { buildConfigField "int", "CONTENT_VERSION_CODE", "$content_version_code" } else if (parsedJson.content_version_code != null) { buildConfigField "int", "CONTENT_VERSION_CODE", "$parsedJson.content_version_code" - } else if (project.hasProperty('version_code')) { + } else if (project.hasProperty('version_code')) { def version_code = project.property('version_code') buildConfigField "int", "CONTENT_VERSION_CODE", "$version_code" } else if (parsedJson.version_code != null) { diff --git a/app/src/androidTestKiwix/java/org/kiwix/kiwixmobile/di/components/TestComponent.java b/app/src/androidTestKiwix/java/org/kiwix/kiwixmobile/di/components/TestComponent.java index 811df2c78..6bf428e30 100644 --- a/app/src/androidTestKiwix/java/org/kiwix/kiwixmobile/di/components/TestComponent.java +++ b/app/src/androidTestKiwix/java/org/kiwix/kiwixmobile/di/components/TestComponent.java @@ -17,18 +17,17 @@ */ package org.kiwix.kiwixmobile.di.components; +import android.content.Context; +import dagger.BindsInstance; +import dagger.Component; +import javax.inject.Singleton; import org.kiwix.kiwixmobile.di.modules.ApplicationModule; import org.kiwix.kiwixmobile.di.modules.JNIModule; -import org.kiwix.kiwixmobile.di.modules.TestJNIModule; import org.kiwix.kiwixmobile.di.modules.TestNetworkModule; import org.kiwix.kiwixmobile.tests.NetworkTest; import org.kiwix.kiwixmobile.tests.ZimTest; import org.kiwix.kiwixmobile.utils.TestNetworkInterceptor; -import javax.inject.Singleton; - -import dagger.Component; - /** * Created by mhutti1 on 13/04/17. */ @@ -41,6 +40,14 @@ import dagger.Component; }) public interface TestComponent extends ApplicationComponent { + @Component.Builder + interface Builder { + + @BindsInstance TestComponent.Builder context(Context context); + + TestComponent build(); + } + void inject(ZimTest zimTest); void inject(NetworkTest networkTest); diff --git a/app/src/androidTestKiwix/java/org/kiwix/kiwixmobile/di/modules/TestJNIModule.java b/app/src/androidTestKiwix/java/org/kiwix/kiwixmobile/di/modules/TestJNIModule.java index 23c425e5b..f47d9cbf4 100644 --- a/app/src/androidTestKiwix/java/org/kiwix/kiwixmobile/di/modules/TestJNIModule.java +++ b/app/src/androidTestKiwix/java/org/kiwix/kiwixmobile/di/modules/TestJNIModule.java @@ -17,7 +17,6 @@ */ package org.kiwix.kiwixmobile.di.modules; -import org.apache.commons.io.IOUtils; import org.kiwix.kiwixlib.JNIKiwix; import org.kiwix.kiwixlib.JNIKiwixString; import org.mockito.Mockito; diff --git a/app/src/androidTestKiwix/java/org/kiwix/kiwixmobile/tests/DownloadTest.java b/app/src/androidTestKiwix/java/org/kiwix/kiwixmobile/tests/DownloadTest.java index ed135d659..317557090 100644 --- a/app/src/androidTestKiwix/java/org/kiwix/kiwixmobile/tests/DownloadTest.java +++ b/app/src/androidTestKiwix/java/org/kiwix/kiwixmobile/tests/DownloadTest.java @@ -18,48 +18,44 @@ package org.kiwix.kiwixmobile.tests; + import android.Manifest; + import android.support.test.espresso.Espresso; + import android.support.test.espresso.IdlingPolicies; + import android.support.test.espresso.ViewInteraction; + import android.support.test.rule.ActivityTestRule; + import android.support.test.rule.GrantPermissionRule; + import android.support.test.runner.AndroidJUnit4; + import android.test.suitebuilder.annotation.LargeTest; + import android.util.Log; + import com.schibsted.spain.barista.interaction.BaristaSleepInteractions; + import java.util.concurrent.TimeUnit; + import org.junit.After; + 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; + import org.kiwix.kiwixmobile.R; + import org.kiwix.kiwixmobile.utils.KiwixIdlingResource; + import org.kiwix.kiwixmobile.utils.SplashActivity; -import android.Manifest; -import android.support.test.espresso.Espresso; -import android.support.test.espresso.IdlingPolicies; -import android.support.test.espresso.ViewInteraction; -import android.support.test.rule.ActivityTestRule; -import android.support.test.runner.AndroidJUnit4; -import android.support.test.rule.GrantPermissionRule; -import android.test.suitebuilder.annotation.LargeTest; -import android.util.Log; - -import com.schibsted.spain.barista.interaction.BaristaSleepInteractions; - -import org.junit.After; -import org.junit.Before; -import org.junit.BeforeClass; -import org.junit.Rule; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.kiwix.kiwixmobile.R; -import org.kiwix.kiwixmobile.utils.KiwixIdlingResource; -import org.kiwix.kiwixmobile.utils.SplashActivity; - -import java.util.concurrent.TimeUnit; - -import static android.support.test.espresso.Espresso.onData; -import static android.support.test.espresso.Espresso.onView; -import static android.support.test.espresso.action.ViewActions.click; -import static android.support.test.espresso.matcher.ViewMatchers.isDisplayed; -import static android.support.test.espresso.matcher.ViewMatchers.withId; -import static android.support.test.espresso.matcher.ViewMatchers.withParent; -import static com.schibsted.spain.barista.assertion.BaristaVisibilityAssertions.assertDisplayed; -import static com.schibsted.spain.barista.interaction.BaristaClickInteractions.clickOn; -import static com.schibsted.spain.barista.interaction.BaristaSwipeRefreshInteractions.refresh; -import static junit.framework.Assert.fail; -import static org.hamcrest.Matchers.allOf; -import static org.kiwix.kiwixmobile.testutils.TestUtils.TEST_PAUSE_MS; -import static org.kiwix.kiwixmobile.testutils.TestUtils.allowPermissionsIfNeeded; -import static org.kiwix.kiwixmobile.testutils.TestUtils.captureAndSaveScreenshot; -import static org.kiwix.kiwixmobile.testutils.TestUtils.withContent; -import static org.kiwix.kiwixmobile.utils.StandardActions.deleteZimIfExists; -import static org.kiwix.kiwixmobile.utils.StandardActions.enterHelp; + import static android.support.test.espresso.Espresso.onData; + import static android.support.test.espresso.Espresso.onView; + import static android.support.test.espresso.matcher.ViewMatchers.isDisplayed; + import static android.support.test.espresso.matcher.ViewMatchers.withId; + import static android.support.test.espresso.matcher.ViewMatchers.withParent; + import static com.schibsted.spain.barista.assertion.BaristaVisibilityAssertions.assertDisplayed; + import static com.schibsted.spain.barista.interaction.BaristaClickInteractions.clickOn; + import static com.schibsted.spain.barista.interaction.BaristaSwipeRefreshInteractions.refresh; + import static junit.framework.Assert.fail; + import static org.hamcrest.Matchers.allOf; + import static org.kiwix.kiwixmobile.testutils.TestUtils.TEST_PAUSE_MS; + import static org.kiwix.kiwixmobile.testutils.TestUtils.allowPermissionsIfNeeded; + import static org.kiwix.kiwixmobile.testutils.TestUtils.captureAndSaveScreenshot; + import static org.kiwix.kiwixmobile.testutils.TestUtils.withContent; + import static org.kiwix.kiwixmobile.utils.StandardActions.deleteZimIfExists; + import static org.kiwix.kiwixmobile.utils.StandardActions.enterHelp; @LargeTest @RunWith(AndroidJUnit4.class) @@ -85,6 +81,7 @@ public class DownloadTest { } @Test + @Ignore("Broken in 2.5")//TODO: Fix in 3.0 public void downloadTest() { enterHelp(); clickOn(R.string.menu_zim_manager); @@ -97,12 +94,6 @@ public class DownloadTest { clickOn(R.string.remote_zims); - try { - clickOn(R.id.network_permission_button); - } catch (RuntimeException e) { - Log.d(KIWIX_DOWNLOAD_TEST, "Failed to click Network Permission Button", e); - } - captureAndSaveScreenshot("Before-checking-for-ZimManager-Main-Activity"); ViewInteraction viewPager2 = onView( allOf(withId(R.id.manageViewPager), diff --git a/app/src/androidTestKiwix/java/org/kiwix/kiwixmobile/tests/NetworkTest.java b/app/src/androidTestKiwix/java/org/kiwix/kiwixmobile/tests/NetworkTest.java index 1ea4f276a..12d85052a 100644 --- a/app/src/androidTestKiwix/java/org/kiwix/kiwixmobile/tests/NetworkTest.java +++ b/app/src/androidTestKiwix/java/org/kiwix/kiwixmobile/tests/NetworkTest.java @@ -24,11 +24,19 @@ import android.support.test.espresso.IdlingPolicies; import android.support.test.rule.ActivityTestRule; import android.support.test.rule.GrantPermissionRule; import android.util.Log; - -import org.apache.commons.io.IOUtils; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.util.concurrent.TimeUnit; +import javax.inject.Inject; +import okhttp3.mockwebserver.MockResponse; +import okhttp3.mockwebserver.MockWebServer; +import okio.Buffer; import org.junit.After; import org.junit.Before; import org.junit.BeforeClass; +import org.junit.Ignore; import org.junit.Rule; import org.junit.Test; import org.kiwix.kiwixmobile.KiwixApplication; @@ -37,20 +45,10 @@ import org.kiwix.kiwixmobile.R; import org.kiwix.kiwixmobile.ZimContentProvider; import org.kiwix.kiwixmobile.di.components.DaggerTestComponent; import org.kiwix.kiwixmobile.di.components.TestComponent; -import org.kiwix.kiwixmobile.di.modules.ApplicationModule; import org.kiwix.kiwixmobile.testutils.TestUtils; +import org.kiwix.kiwixmobile.utils.IOUtils; import org.kiwix.kiwixmobile.utils.KiwixIdlingResource; -import java.io.IOException; -import java.io.InputStream; -import java.util.concurrent.TimeUnit; - -import javax.inject.Inject; - -import okhttp3.mockwebserver.MockResponse; -import okhttp3.mockwebserver.MockWebServer; -import okio.Buffer; - import static android.support.test.InstrumentationRegistry.getInstrumentation; import static android.support.test.espresso.Espresso.onData; import static android.support.test.espresso.Espresso.onView; @@ -93,9 +91,8 @@ public class NetworkTest { @Before public void setUp() { - TestComponent component = DaggerTestComponent.builder().applicationModule - (new ApplicationModule( - (KiwixApplication) getInstrumentation().getTargetContext().getApplicationContext())).build(); + TestComponent component = DaggerTestComponent.builder().context( + getInstrumentation().getTargetContext().getApplicationContext()).build(); ((KiwixApplication) getInstrumentation().getTargetContext().getApplicationContext()).setApplicationComponent(component); @@ -121,6 +118,7 @@ public class NetworkTest { @Test + @Ignore("Broken in 2.5")//TODO: Fix in 3.0 public void networkTest() { mActivityTestRule.launchActivity(null); @@ -130,13 +128,6 @@ public class NetworkTest { TestUtils.allowPermissionsIfNeeded(); - try { - onView(withId(R.id.network_permission_button)).perform(click()); - } catch (RuntimeException e) { - Log.i(NETWORK_TEST_TAG, - "Permission dialog was not shown, we probably already have required permissions"); - } - onData(withContent("wikipedia_ab_all_2017-03")).inAdapterView(withId(R.id.libraryList)).perform(click()); try { diff --git a/app/src/androidTestKiwix/java/org/kiwix/kiwixmobile/utils/IOUtils.java b/app/src/androidTestKiwix/java/org/kiwix/kiwixmobile/utils/IOUtils.java new file mode 100644 index 000000000..847c95535 --- /dev/null +++ b/app/src/androidTestKiwix/java/org/kiwix/kiwixmobile/utils/IOUtils.java @@ -0,0 +1,57 @@ +package org.kiwix.kiwixmobile.utils; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; + +/* + * Kiwix Android + * Copyright (C) 2018 Kiwix + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +public class IOUtils { + private IOUtils() { + //utility class + } + + private static final int DEFAULT_BUFFER_SIZE = 1024 * 4; + private static final int EOF = -1; + + public static byte[] toByteArray(final InputStream input) throws IOException { + try (final ByteArrayOutputStream output = new ByteArrayOutputStream()) { + copy(input, output); + return output.toByteArray(); + } + } + private static int copy(final InputStream input, final OutputStream output) throws IOException { + final long count = copyLarge(input, output); + if (count > Integer.MAX_VALUE) { + return -1; + } + return (int) count; + + } + private static long copyLarge(final InputStream input, final OutputStream output) throws IOException { + final byte[] buffer = new byte[DEFAULT_BUFFER_SIZE]; + long count = 0; + int n; + while (EOF != (n = input.read(buffer))) { + output.write(buffer, 0, n); + count += n; + } + return count; + } +} diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 558d1d161..dd50e65ad 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -176,8 +176,6 @@ - - diff --git a/app/src/main/java/org/kiwix/kiwixmobile/di/components/ApplicationComponent.java b/app/src/main/java/org/kiwix/kiwixmobile/di/components/ApplicationComponent.java index 081b6cd3a..646ee28c6 100644 --- a/app/src/main/java/org/kiwix/kiwixmobile/di/components/ApplicationComponent.java +++ b/app/src/main/java/org/kiwix/kiwixmobile/di/components/ApplicationComponent.java @@ -26,7 +26,6 @@ import org.kiwix.kiwixmobile.ZimContentProvider; import org.kiwix.kiwixmobile.di.modules.ApplicationModule; import org.kiwix.kiwixmobile.di.modules.JNIModule; import org.kiwix.kiwixmobile.di.modules.NetworkModule; -import org.kiwix.kiwixmobile.downloader.DownloadService; import org.kiwix.kiwixmobile.settings.KiwixSettingsActivity; import org.kiwix.kiwixmobile.views.AutoCompleteAdapter; import org.kiwix.kiwixmobile.views.web.KiwixWebView; @@ -52,8 +51,6 @@ public interface ApplicationComponent { void inject(KiwixApplication application); - void inject(DownloadService service); - void inject(ZimContentProvider zimContentProvider); void inject(KiwixWebView kiwixWebView); diff --git a/build.gradle b/build.gradle index a7e867e97..a1f756bcb 100644 --- a/build.gradle +++ b/build.gradle @@ -9,6 +9,7 @@ buildscript { classpath 'com.android.tools.build:gradle:3.4.1' classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" classpath "io.objectbox:objectbox-gradle-plugin:$objectboxVersion" + classpath 'com.dicedmelon.gradle:jacoco-android:0.1.4' // NOTE: Do not place your application dependencies here; they belong // in the individual module build.gradle files