From 11d53aff3621c65b9fda63a26eb00e71888a91a8 Mon Sep 17 00:00:00 2001 From: tobiasKaminsky Date: Thu, 22 Mar 2018 09:04:51 +0100 Subject: [PATCH] - move to new src folder - add integration test for ExceptionParser - include integration tests --- .codecov.yml | 13 +++ .drone.yml | 41 ++++---- scripts/lint/lint-results.txt | 2 +- scripts/uploadReport.sh | 19 ++++ .../common/operations/ExceptionParser.java | 14 ++- test_client/build.gradle | 80 +++++++++++---- .../android/util/ExceptionParserIT.java | 91 ++++++++++++++++++ .../{ => src/main}/AndroidManifest.xml | 0 .../SelfSignedConfidentSslSocketFactory.java | 0 .../android/lib/testclient/TestActivity.java | 0 .../main}/res/drawable-hdpi/ic_launcher.png | Bin .../main}/res/drawable-mdpi/ic_launcher.png | Bin .../main}/res/drawable-xhdpi/ic_launcher.png | Bin .../main}/res/drawable-xxhdpi/ic_launcher.png | Bin .../main}/res/layout/activity_test.xml | 0 test_client/{ => src/main}/res/menu/test.xml | 0 .../main}/res/values-sw600dp/dimens.xml | 0 .../main}/res/values-sw720dp-land/dimens.xml | 0 .../{ => src/main}/res/values-v11/styles.xml | 0 .../{ => src/main}/res/values-v14/styles.xml | 0 .../{ => src/main}/res/values/dimens.xml | 0 .../{ => src/main}/res/values/setup.xml | 0 .../{ => src/main}/res/values/strings.xml | 0 .../{ => src/main}/res/values/styles.xml | 0 .../com/owncloud/android/utils/DummyTest.java | 37 +++++++ 25 files changed, 253 insertions(+), 44 deletions(-) create mode 100644 .codecov.yml create mode 100755 scripts/uploadReport.sh create mode 100644 test_client/src/androidTest/java/com/owncloud/android/util/ExceptionParserIT.java rename test_client/{ => src/main}/AndroidManifest.xml (100%) rename test_client/src/{ => main/java}/com/owncloud/android/lib/testclient/SelfSignedConfidentSslSocketFactory.java (100%) rename test_client/src/{ => main/java}/com/owncloud/android/lib/testclient/TestActivity.java (100%) rename test_client/{ => src/main}/res/drawable-hdpi/ic_launcher.png (100%) rename test_client/{ => src/main}/res/drawable-mdpi/ic_launcher.png (100%) rename test_client/{ => src/main}/res/drawable-xhdpi/ic_launcher.png (100%) rename test_client/{ => src/main}/res/drawable-xxhdpi/ic_launcher.png (100%) rename test_client/{ => src/main}/res/layout/activity_test.xml (100%) rename test_client/{ => src/main}/res/menu/test.xml (100%) rename test_client/{ => src/main}/res/values-sw600dp/dimens.xml (100%) rename test_client/{ => src/main}/res/values-sw720dp-land/dimens.xml (100%) rename test_client/{ => src/main}/res/values-v11/styles.xml (100%) rename test_client/{ => src/main}/res/values-v14/styles.xml (100%) rename test_client/{ => src/main}/res/values/dimens.xml (100%) rename test_client/{ => src/main}/res/values/setup.xml (100%) rename test_client/{ => src/main}/res/values/strings.xml (100%) rename test_client/{ => src/main}/res/values/styles.xml (100%) create mode 100644 test_client/src/test/java/com/owncloud/android/utils/DummyTest.java diff --git a/.codecov.yml b/.codecov.yml new file mode 100644 index 00000000..c3752593 --- /dev/null +++ b/.codecov.yml @@ -0,0 +1,13 @@ +codecov: + branch: master + ci: + - drone.nextcloud.com + +coverage: + precision: 2 + round: down + range: "70...100" + +comment: + layout: "header, diff, changes, uncovered, tree" + behavior: default \ No newline at end of file diff --git a/.drone.yml b/.drone.yml index e7d3f1cf..3328d708 100644 --- a/.drone.yml +++ b/.drone.yml @@ -1,24 +1,27 @@ pipeline: - test: - image: nextcloudci/android:android-30 + compile: + image: nextcloudci/android:android-33 commands: - # - echo no | android create avd --force -n test -t $ANDROID_TARGET --abi $ANDROID_ABI -c 20M - # - emulator -avd test -no-window & - # - ./wait_for_emulator.sh - - # build app - - ./gradlew clean build + # build app and assemble APK + - ./gradlew assemble - environment: - - ANDROID_TARGET=android-28 - - ANDROID_ABI=armeabi-v7a - - LD_LIBRARY_PATH=/usr/lib/x86_64-linux-gnu/:/opt/android-sdk-linux/tools/lib64/gles_mesa/ - - lint: - image: nextcloudci/android:android-30 + test: + image: nextcloudci/android:android-33 + privileged: true + commands: + - emulator -avd android-27 -no-window -no-audio & + - ./wait_for_emulator.sh + - ./gradlew jacocoTestDebugUnitTestReport || scripts/uploadReport.sh $LOG_USERNAME $LOG_PASSWORD $DRONE_BUILD_NUMBER "Unit" + - ./gradlew assembleDebug installDebugAndroidTest + - ./gradlew createDebugCoverageReport || scripts/uploadReport.sh $LOG_USERNAME $LOG_PASSWORD $DRONE_BUILD_NUMBER "IT" + - ./gradlew combinedTestReport + - curl -o codecov.sh https://codecov.io/bash + - bash ./codecov.sh -t 2eec98c3-ff20-4cad-9e08-463471a33431 + secrets: [ LOG_USERNAME, LOG_PASSWORD ] + + lint: + image: nextcloudci/android:android-33 commands: - # needs gplay - - sed -i '/com.google.*.gms/s/^.*\\/\\///g' build.gradle - export BRANCH=$(scripts/lint/getBranchName.sh $GIT_USERNAME $GIT_TOKEN $DRONE_PULL_REQUEST) - scripts/lint/lint-up-wrapper.sh $GIT_USERNAME $GIT_TOKEN $BRANCH $LOG_USERNAME $LOG_PASSWORD $DRONE_BUILD_NUMBER secrets: [ GIT_USERNAME, GIT_TOKEN, LOG_USERNAME, LOG_PASSWORD ] @@ -38,4 +41,8 @@ pipeline: status: failure branch: master +services: + server: + image: nextcloudci/server:server-1 + branches: master diff --git a/scripts/lint/lint-results.txt b/scripts/lint/lint-results.txt index 1a0d01dc..efe6871b 100644 --- a/scripts/lint/lint-results.txt +++ b/scripts/lint/lint-results.txt @@ -1,2 +1,2 @@ DO NOT TOUCH; GENERATED BY DRONE - Lint Report: 2 errors and 15 warnings + Lint Report: 2 errors and 19 warnings diff --git a/scripts/uploadReport.sh b/scripts/uploadReport.sh new file mode 100755 index 00000000..0f70fcd1 --- /dev/null +++ b/scripts/uploadReport.sh @@ -0,0 +1,19 @@ +#!/usr/bin/env bash + +URL=https://nextcloud.kaminsky.me/remote.php/webdav/integrationTests-library +ID=$3 +USER=$1 +PASS=$2 +TYPE=$4 + +if [ $TYPE = "IT" ]; then + cd test_client/build/reports/androidTests/connected/ +else + cd test_client/build/reports/tests/testDebugUnitTest +fi + +find . -type d -exec curl -u $USER:$PASS -X MKCOL $URL/$ID/$(echo {} | sed s#\./##) \; +find . -type f -exec curl -u $USER:$PASS -X PUT $URL/$ID/$(echo {} | sed s#\./##) --upload-file {} \; + +echo "Uploaded failing library tests to https://nextcloud.kaminsky.me/index.php/s/Pfc8NMxTStWtmMC -> $ID" +exit 1 diff --git a/src/com/owncloud/android/lib/common/operations/ExceptionParser.java b/src/com/owncloud/android/lib/common/operations/ExceptionParser.java index 1666194d..6ddceab8 100644 --- a/src/com/owncloud/android/lib/common/operations/ExceptionParser.java +++ b/src/com/owncloud/android/lib/common/operations/ExceptionParser.java @@ -26,6 +26,8 @@ package com.owncloud.android.lib.common.operations; import android.util.Xml; +import com.owncloud.android.lib.common.utils.Log_OC; + import org.xmlpull.v1.XmlPullParser; import org.xmlpull.v1.XmlPullParserException; import org.xmlpull.v1.XmlPullParserFactory; @@ -39,6 +41,7 @@ import java.io.InputStream; * @author masensio, tobiaskaminsky */ public class ExceptionParser { + private static final String TAG = ExceptionParser.class.getSimpleName(); private static final String INVALID_PATH_EXCEPTION_STRING = "OC\\Connector\\Sabre\\Exception\\InvalidPath"; private static final String INVALID_PATH_EXCEPTION_UPLOAD_STRING = "OCP\\Files\\InvalidPathException"; @@ -52,8 +55,8 @@ public class ExceptionParser { private static final String NODE_EXCEPTION = "s:exception"; private static final String NODE_MESSAGE = "s:message"; - private String exception; - private String message; + private String exception = ""; + private String message = ""; /** * Parse is as an Invalid Path Exception @@ -64,7 +67,6 @@ public class ExceptionParser { * @throws IOException */ public ExceptionParser(InputStream is) throws XmlPullParserException, IOException { - try { // XMLPullParser XmlPullParserFactory factory = XmlPullParserFactory.newInstance(); @@ -75,14 +77,16 @@ public class ExceptionParser { parser.setInput(is, null); parser.nextTag(); readError(parser); - + } catch (Exception e) { + Log_OC.e(TAG, "Error parsing exception: " + e.getMessage()); } finally { is.close(); } } public boolean isInvalidCharacterException() { - return exception.equalsIgnoreCase(INVALID_PATH_EXCEPTION_STRING) || exception.equalsIgnoreCase(INVALID_PATH_EXCEPTION_UPLOAD_STRING); + return exception.equalsIgnoreCase(INVALID_PATH_EXCEPTION_STRING) || + exception.equalsIgnoreCase(INVALID_PATH_EXCEPTION_UPLOAD_STRING); } public boolean isVirusException() { diff --git a/test_client/build.gradle b/test_client/build.gradle index 9d9e363f..cef555ab 100644 --- a/test_client/build.gradle +++ b/test_client/build.gradle @@ -1,39 +1,59 @@ apply plugin: 'com.android.application' +apply plugin: 'jacoco-android' repositories { jcenter() google() } +buildscript { + repositories { + jcenter() + maven { + url 'https://oss.sonatype.org/content/repositories/snapshots/' + } + google() + } + dependencies { + classpath 'com.dicedmelon.gradle:jacoco-android:0.1.2' + } +} + +ext { + jacocoVersion = "0.7.4.201502262128" +} + dependencies { implementation project(':') + + testImplementation 'junit:junit:4.12' + testImplementation 'org.mockito:mockito-core:1.10.19' + // dependencies for instrumented tests + // JUnit4 Rules + androidTestImplementation 'com.android.support.test:rules:1.0.1' + // Android JUnit Runner + androidTestImplementation 'com.android.support.test:runner:1.0.1' + + jacocoAnt "org.jacoco:org.jacoco.ant:${project.jacocoVersion}" + jacocoAgent "org.jacoco:org.jacoco.agent:${project.jacocoVersion}" + androidJacocoAgent "org.jacoco:org.jacoco.agent:${project.jacocoVersion}" + androidJacocoAnt "org.jacoco:org.jacoco.ant:${project.jacocoVersion}" + androidJacocoAnt "org.jacoco:org.jacoco.core:${project.jacocoVersion}" + androidJacocoAnt "org.jacoco:org.jacoco.report:${project.jacocoVersion}" + androidJacocoAnt "org.jacoco:org.jacoco.agent:${project.jacocoVersion}" } android { compileSdkVersion 26 - sourceSets { - main { - manifest.srcFile 'AndroidManifest.xml' - java.srcDirs = ['src'] - resources.srcDirs = ['src'] - aidl.srcDirs = ['src'] - renderscript.srcDirs = ['src'] - res.srcDirs = ['res'] - assets.srcDirs = ['assets'] + defaultConfig { + testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" + } + + buildTypes { + debug { + testCoverageEnabled true } - - // Move the tests to tests/java, tests/res, etc... - instrumentTest.setRoot('tests') - - // Move the build types to build-types/ - // For instance, build-types/debug/java, build-types/debug/AndroidManifest.xml, ... - // This moves them out of them default location under src//... which would - // conflict with src/ being used by the main source set. - // Adding new build types or product flavors should be accompanied - // by a similar customization. - debug.setRoot('build-types/debug') - release.setRoot('build-types/release') } lintOptions { @@ -44,3 +64,21 @@ android { exclude 'META-INF/LICENSE.txt' } } + +task combinedTestReport(type: JacocoReport) { + + reports { + xml.enabled = true + html.enabled = true + } + + def fileFilter = ['**/R.class', '**/R$*.class', '**/BuildConfig.*', '**/Manifest*.*', '**/*Test*.*', 'android/**/*.*'] + def debugTree = fileTree(dir: "$project.buildDir/intermediates/classes/debug", excludes: fileFilter) + def mainSrc = "$project.projectDir/src/main/java" + + sourceDirectories = files([mainSrc]) + classDirectories = files([debugTree]) + executionData = fileTree(dir: project.buildDir, includes: [ + 'jacoco/testDebugUnitTest.exec', 'outputs/code-coverage/connected/*coverage.ec' + ]) +} diff --git a/test_client/src/androidTest/java/com/owncloud/android/util/ExceptionParserIT.java b/test_client/src/androidTest/java/com/owncloud/android/util/ExceptionParserIT.java new file mode 100644 index 00000000..470d9c37 --- /dev/null +++ b/test_client/src/androidTest/java/com/owncloud/android/util/ExceptionParserIT.java @@ -0,0 +1,91 @@ +package com.owncloud.android.util; + +import android.support.test.runner.AndroidJUnit4; + +import com.owncloud.android.lib.common.operations.ExceptionParser; + +import org.junit.Assert; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.xmlpull.v1.XmlPullParserException; + +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.io.InputStream; + +/** + * Created by tobi on 3/21/18. + */ + +@RunWith(AndroidJUnit4.class) +public class ExceptionParserIT { + + @Test + public void testVirusException() throws IOException, XmlPullParserException { + String virusException = "\n" + + "\n" + + " OCA\\DAV\\Connector\\Sabre\\Exception\\UnsupportedMediaType" + + "\n" + + " Virus Eicar-Test-Signature is detected in the file. " + + "Upload cannot be completed.\n" + + ""; + + InputStream is = new ByteArrayInputStream(virusException.getBytes()); + ExceptionParser xmlParser = new ExceptionParser(is); + + Assert.assertTrue(xmlParser.isVirusException()); + Assert.assertFalse(xmlParser.isInvalidCharacterException()); + } + + @Test + public void testInvalidCharacterException() throws IOException, XmlPullParserException { + String virusException = "\n" + + "\n" + + " OC\\Connector\\Sabre\\Exception\\InvalidPath\n" + + " Wrong Path\n" + + ""; + + InputStream is = new ByteArrayInputStream(virusException.getBytes()); + ExceptionParser xmlParser = new ExceptionParser(is); + + Assert.assertTrue(xmlParser.isInvalidCharacterException()); + Assert.assertFalse(xmlParser.isVirusException()); + } + + @Test + public void testInvalidCharacterUploadException() throws IOException, XmlPullParserException { + String virusException = "\n" + + "\n" + + " OCP\\Files\\InvalidPathException\n" + + " Wrong Path\n" + + ""; + + InputStream is = new ByteArrayInputStream(virusException.getBytes()); + ExceptionParser xmlParser = new ExceptionParser(is); + + Assert.assertTrue(xmlParser.isInvalidCharacterException()); + Assert.assertFalse(xmlParser.isVirusException()); + } + + @Test + public void testEmptyString() throws IOException, XmlPullParserException { + String emptyString = ""; + + InputStream is = new ByteArrayInputStream(emptyString.getBytes()); + ExceptionParser xmlParser = new ExceptionParser(is); + + Assert.assertFalse(xmlParser.isVirusException()); + Assert.assertFalse(xmlParser.isInvalidCharacterException()); + } + + @Test + public void testString() throws IOException, XmlPullParserException { + String emptyString = ""; + + InputStream is = new ByteArrayInputStream(emptyString.getBytes()); + ExceptionParser xmlParser = new ExceptionParser(is); + + Assert.assertFalse(xmlParser.isVirusException()); + Assert.assertFalse(xmlParser.isInvalidCharacterException()); + } +} diff --git a/test_client/AndroidManifest.xml b/test_client/src/main/AndroidManifest.xml similarity index 100% rename from test_client/AndroidManifest.xml rename to test_client/src/main/AndroidManifest.xml diff --git a/test_client/src/com/owncloud/android/lib/testclient/SelfSignedConfidentSslSocketFactory.java b/test_client/src/main/java/com/owncloud/android/lib/testclient/SelfSignedConfidentSslSocketFactory.java similarity index 100% rename from test_client/src/com/owncloud/android/lib/testclient/SelfSignedConfidentSslSocketFactory.java rename to test_client/src/main/java/com/owncloud/android/lib/testclient/SelfSignedConfidentSslSocketFactory.java diff --git a/test_client/src/com/owncloud/android/lib/testclient/TestActivity.java b/test_client/src/main/java/com/owncloud/android/lib/testclient/TestActivity.java similarity index 100% rename from test_client/src/com/owncloud/android/lib/testclient/TestActivity.java rename to test_client/src/main/java/com/owncloud/android/lib/testclient/TestActivity.java diff --git a/test_client/res/drawable-hdpi/ic_launcher.png b/test_client/src/main/res/drawable-hdpi/ic_launcher.png similarity index 100% rename from test_client/res/drawable-hdpi/ic_launcher.png rename to test_client/src/main/res/drawable-hdpi/ic_launcher.png diff --git a/test_client/res/drawable-mdpi/ic_launcher.png b/test_client/src/main/res/drawable-mdpi/ic_launcher.png similarity index 100% rename from test_client/res/drawable-mdpi/ic_launcher.png rename to test_client/src/main/res/drawable-mdpi/ic_launcher.png diff --git a/test_client/res/drawable-xhdpi/ic_launcher.png b/test_client/src/main/res/drawable-xhdpi/ic_launcher.png similarity index 100% rename from test_client/res/drawable-xhdpi/ic_launcher.png rename to test_client/src/main/res/drawable-xhdpi/ic_launcher.png diff --git a/test_client/res/drawable-xxhdpi/ic_launcher.png b/test_client/src/main/res/drawable-xxhdpi/ic_launcher.png similarity index 100% rename from test_client/res/drawable-xxhdpi/ic_launcher.png rename to test_client/src/main/res/drawable-xxhdpi/ic_launcher.png diff --git a/test_client/res/layout/activity_test.xml b/test_client/src/main/res/layout/activity_test.xml similarity index 100% rename from test_client/res/layout/activity_test.xml rename to test_client/src/main/res/layout/activity_test.xml diff --git a/test_client/res/menu/test.xml b/test_client/src/main/res/menu/test.xml similarity index 100% rename from test_client/res/menu/test.xml rename to test_client/src/main/res/menu/test.xml diff --git a/test_client/res/values-sw600dp/dimens.xml b/test_client/src/main/res/values-sw600dp/dimens.xml similarity index 100% rename from test_client/res/values-sw600dp/dimens.xml rename to test_client/src/main/res/values-sw600dp/dimens.xml diff --git a/test_client/res/values-sw720dp-land/dimens.xml b/test_client/src/main/res/values-sw720dp-land/dimens.xml similarity index 100% rename from test_client/res/values-sw720dp-land/dimens.xml rename to test_client/src/main/res/values-sw720dp-land/dimens.xml diff --git a/test_client/res/values-v11/styles.xml b/test_client/src/main/res/values-v11/styles.xml similarity index 100% rename from test_client/res/values-v11/styles.xml rename to test_client/src/main/res/values-v11/styles.xml diff --git a/test_client/res/values-v14/styles.xml b/test_client/src/main/res/values-v14/styles.xml similarity index 100% rename from test_client/res/values-v14/styles.xml rename to test_client/src/main/res/values-v14/styles.xml diff --git a/test_client/res/values/dimens.xml b/test_client/src/main/res/values/dimens.xml similarity index 100% rename from test_client/res/values/dimens.xml rename to test_client/src/main/res/values/dimens.xml diff --git a/test_client/res/values/setup.xml b/test_client/src/main/res/values/setup.xml similarity index 100% rename from test_client/res/values/setup.xml rename to test_client/src/main/res/values/setup.xml diff --git a/test_client/res/values/strings.xml b/test_client/src/main/res/values/strings.xml similarity index 100% rename from test_client/res/values/strings.xml rename to test_client/src/main/res/values/strings.xml diff --git a/test_client/res/values/styles.xml b/test_client/src/main/res/values/styles.xml similarity index 100% rename from test_client/res/values/styles.xml rename to test_client/src/main/res/values/styles.xml diff --git a/test_client/src/test/java/com/owncloud/android/utils/DummyTest.java b/test_client/src/test/java/com/owncloud/android/utils/DummyTest.java new file mode 100644 index 00000000..1ed1d3ec --- /dev/null +++ b/test_client/src/test/java/com/owncloud/android/utils/DummyTest.java @@ -0,0 +1,37 @@ +package com.owncloud.android.utils; + +import org.junit.Test; + +import static junit.framework.Assert.assertFalse; +import static junit.framework.Assert.assertTrue; + +/* + * Nextcloud Android client application + * + * @author Tobias Kaminsky + * Copyright (C) 2018 Tobias Kaminsky + * Copyright (C) 2018 Nextcloud GmbH. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +public class DummyTest { + + @Test + public void dummy() { + // to replace with real tests + assertTrue(true); + assertFalse(false); + } +}