Commit 46c72cd5 authored by Vincent Bourgmayer's avatar Vincent Bourgmayer 🎼
Browse files

Merge branch 'instrumentation-test-oreo' into 'v1-oreo'

Instrumentation test oreo

See merge request e/apps/eDrive!44
parents f3b3935e 9503b6cf
Pipeline #124610 passed with stages
in 5 minutes and 18 seconds
image: "registry.gitlab.e.foundation:5000/e/apps/docker-android-apps-cicd:latest"
stages:
- test
- build
before_script:
......@@ -9,15 +10,32 @@ before_script:
- export GRADLE_USER_HOME=$(pwd)/.gradle
- chmod +x ./gradlew
cache:
key: ${CI_PROJECT_ID}
paths:
- .gradle/
test:
allow_failure: true
stage: test
script:
- ls /usr/lib/jvm/
- ./gradlew test -Dorg.gradle.java.home=/usr/lib/jvm/java-8-openjdk-amd64 -PtestAccountName="$testAccountName" -PtestAccountPwd="$testAccountPwd" -PtestServerUrl="$testServerUrl"
artifacts:
when: always
paths:
- app/build/test-results/*/TEST-*.xml
- app/build/reports/tests/*
reports:
junit: app/build/test-results/*/TEST-*.xml
build:
stage: build
script:
- ./gradlew build
- ./gradlew build -x test
artifacts:
paths:
- app/build/outputs/apk/
......
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectModuleManager">
<modules>
<module fileurl="file://$PROJECT_DIR$/Drive.iml" filepath="$PROJECT_DIR$/Drive.iml" />
<module fileurl="file://$PROJECT_DIR$/nextcloud-android-lib/NextcloudLib.iml" filepath="$PROJECT_DIR$/nextcloud-android-lib/NextcloudLib.iml" />
<module fileurl="file://$PROJECT_DIR$/app/app.iml" filepath="$PROJECT_DIR$/app/app.iml" />
<module fileurl="file://$PROJECT_DIR$/eDrive.iml" filepath="$PROJECT_DIR$/eDrive.iml" />
</modules>
</component>
</project>
\ No newline at end of file
......@@ -9,6 +9,18 @@ def buildTime() {
return df.format(new Date())
}
def getTestProp(String propName) {
def result = ""
if(project.hasProperty(propName)){
result =project.property(propName).toString()
}else if(project.rootProject.file('local.properties').exists()){
Properties properties = new Properties()
properties.load(project.rootProject.file('local.properties').newReader())
result = properties.getProperty(propName)
}
return result
}
android {
compileSdkVersion 26
......@@ -19,7 +31,9 @@ android {
//versionName "1.0"
versionName "beta-${versionMajor}-build-o-${buildTime()}"
setProperty("archivesBaseName", "$applicationId.$versionName")
buildConfigField "String", "testAccountName", "\""+getTestProp("testAccountName")+"\""
buildConfigField "String", "testAccountPWd", "\""+getTestProp("testAccountPwd")+"\""
buildConfigField "String", "testServerUrl", "\""+getTestProp("testServerUrl")+"\""
}
buildTypes {
release {
......@@ -34,19 +48,37 @@ android {
testOptions {
unitTests.returnDefaultValues = true
unitTests {
returnDefaultValues = true
//includeAndroidResources = true
}
}
}
dependencies {
implementation fileTree(include: ['*.jar'], dir: 'libs')
implementation 'com.android.support:appcompat-v7:26.1.0'
testImplementation 'junit:junit:4.12'
androidTestImplementation 'com.android.support.test:runner:1.0.2'
androidTestImplementation 'com.android.support.test:rules:1.0.2'
androidTestImplementation 'com.android.support:support-annotations:27.1.1'
androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.1'
api 'com.android.support:support-annotations:27.1.1'
api project(':NextcloudLib')
//start to add lib for test - 1/4/21
//@TODO: add junit runner as lib for testImplementation
testImplementation 'com.android.support.test:runner:1.0.2'
testImplementation 'com.android.support.test:rules:1.0.2'
testImplementation 'junit:junit:4.12'
//testImplementation 'org.robolectric:robolectric:4.4' //need AndroidX
testImplementation "org.robolectric:robolectric:3.8"
testImplementation('org.mockito:mockito-inline:3.4.0')
//testImplementation Libs.AndroidX.Test.archCoreTesting //TODO: replace by not android X version
//implementation 'androidx.localbroadcastmanager:localbroadcastmanager:1.0.0'
androidTestImplementation 'junit:junit:4.12'
}
/*
* Copyright © Vincent Bourgmayer (/e/ foundation).
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the GNU Public License v3.0
* which accompanies this distribution, and is available at
* http://www.gnu.org/licenses/gpl.html
*/
package foundation.e.drive;
import android.content.Context;
import android.support.test.InstrumentationRegistry;
import android.support.test.runner.AndroidJUnit4;
import org.junit.Test;
import org.junit.runner.RunWith;
import static org.junit.Assert.*;
/**
* Instrumented test, which will execute on an Android device.
*
* @see <a href="http://d.android.com/tools/testing">Testing documentation</a>
*/
@RunWith(AndroidJUnit4.class)
public class ExampleInstrumentedTest {
@Test
public void useAppContext() throws Exception {
// Context of the app under test.
Context appContext = InstrumentationRegistry.getTargetContext();
assertEquals("foundation.e.drive", appContext.getPackageName());
}
}
package foundation.e.drive.services;
import android.accounts.Account;
import android.accounts.AccountManager;
import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.os.Environment;
import android.support.test.InstrumentationRegistry;
import android.support.test.rule.ServiceTestRule;
import android.support.test.runner.AndroidJUnit4;
import org.junit.After;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.concurrent.TimeoutException;
import static android.support.test.InstrumentationRegistry.getContext;
import static org.junit.Assert.*;
/**
* Instrumented test, which will execute on an Android device.
*
* @see <a href="http://d.android.com/tools/testing">Testing documentation</a>
*/
@RunWith(AndroidJUnit4.class)
public class ObserverServiceInstrumentedTest {
private final static String NEW_SMALL_FILE_PATH = Environment.getExternalStorageDirectory() + File.separator + Environment.DIRECTORY_DOCUMENTS+File.separator+"test-small-file.txt";
private final static String ACCOUNT_NAME= "";
private final static String ACCOUNT_PASS="";
private final static String ACCOUNT_TYPE="";
@Rule
public final ServiceTestRule mServiceRule = new ServiceTestRule();
@Before
public void RegisterAccount() throws Exception {
final Account account = new Account(ACCOUNT_NAME, ACCOUNT_TYPE);
AccountManager.get(getContext()).addAccountExplicitly(account, ACCOUNT_PASS, null);
}
/**
* Souldn't it be more for a unit test ?
* @throws IOException
*/
@Before
public void createLocalSmallFile() throws IOException {
File file = new File(NEW_SMALL_FILE_PATH);
file.createNewFile();
String content = "this a very small content";
//write the bytes in file
if(file.exists())
{
OutputStream fo = new FileOutputStream(file);
fo.write(content.getBytes());
fo.close();
System.out.println("file created: "+file);
}
}
@After
public void deleteLocalSmallFile(){
File file = new File(NEW_SMALL_FILE_PATH);
//deleting the file
file.delete();
}
@Test
public void testWithStartedService() throws TimeoutException {
mServiceRule.startService(
new Intent(InstrumentationRegistry.getTargetContext(), ObserverService.class));
//do something
}
@Test
public void useAppContext() throws Exception {
// Context of the app under test.
Context appContext = InstrumentationRegistry.getTargetContext();
assertEquals("foundation.e.drive", appContext.getPackageName());
}
}
......@@ -11,6 +11,7 @@ package foundation.e.drive.operations;
import android.content.Context;
import android.os.Parcel;
import android.os.Parcelable;
import android.support.annotation.VisibleForTesting;
import android.util.Log;
import com.owncloud.android.lib.common.OwnCloudClient;
import com.owncloud.android.lib.common.UserInfo;
......@@ -217,7 +218,8 @@ public class UploadFileOperation extends RemoteOperation implements ComparableOp
* @param client OwnCloudClient
* @return RemoteOperationResult
*/
private RemoteOperationResult checkAvailableSpace(OwnCloudClient client, long fileSize){
@VisibleForTesting(otherwise = VisibleForTesting.PRIVATE)
public RemoteOperationResult checkAvailableSpace(OwnCloudClient client, long fileSize){
GetRemoteUserInfoOperation getRemoteUserInfoOperation = new GetRemoteUserInfoOperation();
RemoteOperationResult ocsResult = getRemoteUserInfoOperation.execute(client);
if(ocsResult.isSuccess() && ocsResult.getData() != null){
......
......@@ -17,6 +17,7 @@ import android.content.ContentResolver;
import android.content.Context;
import android.media.MediaScannerConnection;
import android.net.ConnectivityManager;
import android.net.Network;
import android.net.NetworkInfo;
import android.net.Uri;
import android.support.annotation.NonNull;
......@@ -54,7 +55,7 @@ public abstract class CommonUtils {
public static void setServiceUnCaughtExceptionHandler(Service service) {
Thread.UncaughtExceptionHandler defaultUEH = Thread.getDefaultUncaughtExceptionHandler();
if (defaultUEH.getClass().getSimpleName().equals(ServiceExceptionHandler.class.getSimpleName())) {
if (defaultUEH != null && ServiceExceptionHandler.class.getSimpleName().equals(defaultUEH.getClass().getSimpleName())) {
Log.d("ObserverService", "ServiceExceptionHandler already set!");
((ServiceExceptionHandler) defaultUEH).setService(service);
} else {
......@@ -206,10 +207,10 @@ public abstract class CommonUtils {
ConnectivityManager cm = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo[] netInfo = cm.getAllNetworkInfo();
for (NetworkInfo ni : netInfo) {
if (ni.getTypeName().equalsIgnoreCase("WIFI"))
if (ni.getType()== ConnectivityManager.TYPE_WIFI) // Replaced the ni.getTypeName by ni.getType to make the test from ObserverServiceTest to work. But looks a better solution in all case
if (ni.isConnected())
haveConnectedWifi = true;
if (ni.getTypeName().equalsIgnoreCase("MOBILE"))
if (ni.getType()== ConnectivityManager.TYPE_MOBILE)
if (ni.isConnected())
haveConnectedMobile = true;
}
......
/*
* Copyright © Vincent Bourgmayer (/e/ foundation).
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the GNU Public License v3.0
* which accompanies this distribution, and is available at
* http://www.gnu.org/licenses/gpl.html
*/
package foundation.e.drive.Test;
import android.accounts.Account;
import org.junit.Assert;
import org.junit.Test;
/**
* @author Vincent Bourgmayer
* raw mock will be replace ASAP to use mockito or other similar framework
*/
public class CommonUtilsUnitTest {
@Test
public void testIsThisSyncAllowed(){
boolean isMediaType = true; //sfs is media element
MockAccount account = new MockAccount("allowed", "allowed"); //Both type sync are allowed
Assert.assertNotNull("Assert account not null", account);
Assert.assertTrue(isThisSyncAllowed(account, isMediaType));
account = new MockAccount("allowed", "not allowed"); //Only Media sync is enabled
Assert.assertTrue(isThisSyncAllowed(account, isMediaType));
account = new MockAccount("not allowed", "allowed"); //Only settings sync is enabled
Assert.assertFalse(isThisSyncAllowed(account, isMediaType));
account = new MockAccount("not allowed", "not allowed"); //no sync is enabled
Assert.assertFalse(isThisSyncAllowed(account, isMediaType));
isMediaType = false;
Assert.assertFalse(isThisSyncAllowed(account, isMediaType));
account = new MockAccount("allowed", "not allowed"); //Only Media sync is enabled
Assert.assertFalse(isThisSyncAllowed(account, isMediaType));
account = new MockAccount("not allowed", "allowed"); //Only settings sync is enabled
Assert.assertTrue(isThisSyncAllowed(account, isMediaType));
account = new MockAccount("allowed", "allowed"); //no sync is enabled
Assert.assertTrue(isThisSyncAllowed(account, isMediaType));
}
static boolean isThisSyncAllowed(MockAccount account, boolean syncedFileStateIsMedia){
return ( syncedFileStateIsMedia && mockedIsMediaSyncEnabled(account) )
|| ( !syncedFileStateIsMedia && mockedIsSettingsSyncEnabled(account) ) ;
}
//@mock tmp
static boolean mockedIsMediaSyncEnabled(MockAccount account){
return account.mockName.equals("allowed");
}
//@mock tmp
static boolean mockedIsSettingsSyncEnabled(MockAccount account){
return account.mockType.equals("allowed");
}
/**
* Tmp mock class
*/
public class MockAccount extends Account{
String mockName;
String mockType;
MockAccount(String name, String type) {
super(name, type);
this.mockName = name;
this.mockType = type;
}
}
}
package foundation.e.drive.Test.FileFilterTest;
import org.junit.Assert;
import org.junit.Test;
public class CrashlogFileFilterTest {
private String mockFileName(String target, String prefix, String extension){
return prefix+target+extension;
}
private String extractTimestamp(String fileName, String prefix, String extension){
return fileName.substring(prefix.length(), (fileName.length() - extension.length()));
}
@Test
public void extractTimeStampFromFileNameTest(){
String prefix = "edrive-";
String extension = ".log";
String target = "";
//Case 1 Empty Target
String base = mockFileName(target, prefix, extension);
Assert.assertEquals("Base length is incorrect", prefix.length()+extension.length(), base.length());
String fileTimestamp = extractTimestamp(base, prefix, extension);
Assert.assertEquals("result is not empty String", "", fileTimestamp);
//Case 2: Prefix is empty
prefix = "";
target = "1234";
base = mockFileName(target, prefix, extension);
Assert.assertEquals("Base length is incorrect", prefix.length()+target.length()+extension.length(), base.length());
fileTimestamp = extractTimestamp(base, prefix, extension);
Assert.assertEquals("result is not empty String", target, fileTimestamp);
//Case 3: extension is empty
prefix = "edrive-";
extension = "";
base = mockFileName(target, prefix, extension);
Assert.assertEquals("Base length is incorrect", prefix.length()+target.length(), base.length());
fileTimestamp = extractTimestamp(base, prefix, extension);
Assert.assertEquals("result is not empty String", target, fileTimestamp);
}
}
\ No newline at end of file
/*
* Copyright © Vincent Bourgmayer (/e/ foundation).
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the GNU Public License v3.0
* which accompanies this distribution, and is available at
* http://www.gnu.org/licenses/gpl.html
*/
package foundation.e.drive.Test.FileFilterTest;
import junit.framework.Assert;
import org.junit.Test;
import foundation.e.drive.utils.AppConstants;
/**
* @author Vincent Bourgmayer
*/
public class FileFilterUnitTest {
@Test
public void SettingsFileFilterUnitTest(){
//Directory situation
Assert.assertFalse(mockSettingFileFilterAcceptMethod("", false));
Assert.assertFalse(mockSettingFileFilterAcceptMethod("", true));
Assert.assertFalse(mockSettingFileFilterAcceptMethod("settings_foo.xml", false));
Assert.assertFalse(mockSettingFileFilterAcceptMethod(AppConstants.APPLICATIONS_LIST_FILE_NAME, false));
Assert.assertFalse(mockSettingFileFilterAcceptMethod("settings_", true));
Assert.assertFalse(mockSettingFileFilterAcceptMethod(".xml", true));
Assert.assertFalse(mockSettingFileFilterAcceptMethod("settings_"+AppConstants.APPLICATIONS_LIST_FILE_NAME, true));
Assert.assertTrue(mockSettingFileFilterAcceptMethod("settings_.xml", true));
Assert.assertTrue(mockSettingFileFilterAcceptMethod("settings_foo.xml", true));
Assert.assertTrue(mockSettingFileFilterAcceptMethod(AppConstants.APPLICATIONS_LIST_FILE_NAME, true));
}
private boolean mockSettingFileFilterAcceptMethod(String name, boolean isFile){
return ( isFile &&
( ( name.startsWith("settings_") && name.endsWith(".xml") )
|| name.equals( AppConstants.APPLICATIONS_LIST_FILE_NAME ) ) );
}
}
package foundation.e.drive.Test;
/*
* Copyright (C) 2012 The CyanogenMod Project
*
* * Licensed under the GNU GPLv2 license
*
* The text of the license can be found in the LICENSE file
* or at https://www.gnu.org/licenses/gpl-2.0.txt
*/
import android.text.TextUtils;
import android.util.Log;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.math.BigInteger;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
public class MD5Test {
private static final String TAG = "MD5";
public static boolean checkMD5(String md5, File updateFile) {
if (TextUtils.isEmpty(md5) || updateFile == null) {
Log.e(TAG, "MD5 string empty or updateFile null");
return false;
}
String calculatedDigest = calculateMD5(updateFile);
if (calculatedDigest == null) {
Log.e(TAG, "calculatedDigest null");
return false;
}
Log.v(TAG, "Calculated digest: " + calculatedDigest);
Log.v(TAG, "Provided digest: " + md5);
return calculatedDigest.equalsIgnoreCase(md5);
}
public static String calculateMD5(File updateFile) {
MessageDigest digest;
try {
digest = MessageDigest.getInstance("MD5");
} catch (NoSuchAlgorithmException e) {
Log.e(TAG, "Exception while getting digest", e);
return null;
}
InputStream is;
try {
is = new FileInputStream(updateFile);
} catch (FileNotFoundException e) {
Log.e(TAG, "Exception while getting FileInputStream", e);
return null;
}
byte[] buffer = new byte[8192];
int read;
try {
while ((read = is.read(buffer)) > 0) {
digest.update(buffer, 0, read);
}
byte[] md5sum = digest.digest();
BigInteger bigInt = new BigInteger(1, md5sum);
String output = bigInt.toString(16);
// Fill to 32 chars
output = String.format("%32s", output).replace(' ', '0');
return output;
} catch (IOException e) {
throw new RuntimeException("Unable to process file for MD5", e);
} finally {
try {
is.close();
} catch (IOException e) {
Log.e(TAG, "Exception on closing MD5 input stream", e);
}
}
}
}
\ No newline at end of file
/*
* Copyright © Vincent Bourgmayer (/e/ foundation).
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the GNU Public License v3.0
* which accompanies this distribution, and is available at
* http://www.gnu.org/licenses/gpl.html
*/
package foundation.e.drive.Test;
import org.junit.Assert;