123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531 |
- /*
- * Nextcloud - Android Client
- *
- * SPDX-FileCopyrightText: 2018 Tobias Kaminsky <tobias@kaminsky.me>
- * SPDX-License-Identifier: AGPL-3.0-or-later OR GPL-2.0-only
- */
- package com.owncloud.android;
- import android.accounts.Account;
- import android.accounts.AccountManager;
- import android.accounts.AuthenticatorException;
- import android.accounts.OperationCanceledException;
- import android.app.Activity;
- import android.content.ActivityNotFoundException;
- import android.content.Context;
- import android.content.res.Configuration;
- import android.content.res.Resources;
- import android.os.Build;
- import android.os.Bundle;
- import android.text.TextUtils;
- import android.view.View;
- import com.facebook.testing.screenshot.Screenshot;
- import com.facebook.testing.screenshot.internal.TestNameDetector;
- import com.nextcloud.client.account.User;
- import com.nextcloud.client.account.UserAccountManager;
- import com.nextcloud.client.account.UserAccountManagerImpl;
- import com.nextcloud.client.device.BatteryStatus;
- import com.nextcloud.client.device.PowerManagementService;
- import com.nextcloud.client.jobs.upload.FileUploadWorker;
- import com.nextcloud.client.network.Connectivity;
- import com.nextcloud.client.network.ConnectivityService;
- import com.nextcloud.client.preferences.AppPreferencesImpl;
- import com.nextcloud.client.preferences.DarkMode;
- import com.nextcloud.common.NextcloudClient;
- import com.nextcloud.test.GrantStoragePermissionRule;
- import com.nextcloud.test.RandomStringGenerator;
- import com.owncloud.android.datamodel.ArbitraryDataProvider;
- import com.owncloud.android.datamodel.ArbitraryDataProviderImpl;
- import com.owncloud.android.datamodel.FileDataStorageManager;
- import com.owncloud.android.datamodel.OCFile;
- import com.owncloud.android.datamodel.UploadsStorageManager;
- import com.owncloud.android.db.OCUpload;
- import com.owncloud.android.files.services.NameCollisionPolicy;
- import com.owncloud.android.lib.common.OwnCloudClient;
- import com.owncloud.android.lib.common.OwnCloudClientFactory;
- import com.owncloud.android.lib.common.accounts.AccountUtils;
- import com.owncloud.android.lib.common.operations.RemoteOperationResult;
- import com.owncloud.android.lib.resources.files.ExistenceCheckRemoteOperation;
- import com.owncloud.android.lib.resources.status.CapabilityBooleanType;
- import com.owncloud.android.lib.resources.status.GetCapabilitiesRemoteOperation;
- import com.owncloud.android.lib.resources.status.OCCapability;
- import com.owncloud.android.lib.resources.status.OwnCloudVersion;
- import com.owncloud.android.operations.CreateFolderOperation;
- import com.owncloud.android.operations.UploadFileOperation;
- import com.owncloud.android.utils.FileStorageUtils;
- import org.apache.commons.io.FileUtils;
- import org.junit.After;
- import org.junit.Before;
- import org.junit.BeforeClass;
- import org.junit.Rule;
- import org.junit.rules.TestRule;
- import java.io.File;
- import java.io.FileWriter;
- import java.io.IOException;
- import java.io.InputStream;
- import java.util.Collection;
- import java.util.Locale;
- import java.util.Objects;
- import java.util.Optional;
- import androidx.annotation.NonNull;
- import androidx.fragment.app.DialogFragment;
- import androidx.test.espresso.contrib.DrawerActions;
- import androidx.test.espresso.intent.rule.IntentsTestRule;
- import androidx.test.platform.app.InstrumentationRegistry;
- import androidx.test.runner.lifecycle.ActivityLifecycleMonitorRegistry;
- import androidx.test.runner.lifecycle.Stage;
- import static androidx.test.InstrumentationRegistry.getInstrumentation;
- import static androidx.test.espresso.Espresso.onView;
- import static androidx.test.espresso.matcher.ViewMatchers.withId;
- import static com.owncloud.android.lib.common.accounts.AccountUtils.Constants.KEY_USER_ID;
- import static org.junit.Assert.assertTrue;
- import static org.junit.Assume.assumeTrue;
- /**
- * Common base for all integration tests.
- */
- public abstract class AbstractIT {
- @Rule
- public final TestRule permissionRule = GrantStoragePermissionRule.grant();
- protected static OwnCloudClient client;
- protected static NextcloudClient nextcloudClient;
- protected static Account account;
- protected static User user;
- protected static Context targetContext;
- protected static String DARK_MODE = "";
- protected static String COLOR = "";
- protected Activity currentActivity;
- protected FileDataStorageManager fileDataStorageManager =
- new FileDataStorageManager(user, targetContext.getContentResolver());
- protected ArbitraryDataProvider arbitraryDataProvider = new ArbitraryDataProviderImpl(targetContext);
- @BeforeClass
- public static void beforeAll() {
- try {
- // clean up
- targetContext = InstrumentationRegistry.getInstrumentation().getTargetContext();
- AccountManager platformAccountManager = AccountManager.get(targetContext);
- for (Account account : platformAccountManager.getAccounts()) {
- if (account.type.equalsIgnoreCase("nextcloud")) {
- platformAccountManager.removeAccountExplicitly(account);
- }
- }
- account = createAccount("test@https://nextcloud.localhost");
- user = getUser(account);
- client = OwnCloudClientFactory.createOwnCloudClient(account, targetContext);
- nextcloudClient = OwnCloudClientFactory.createNextcloudClient(user, targetContext);
- } catch (OperationCanceledException |
- IOException |
- AccountUtils.AccountNotFoundException |
- AuthenticatorException e) {
- throw new RuntimeException("Error setting up clients", e);
- }
- Bundle arguments = androidx.test.platform.app.InstrumentationRegistry.getArguments();
- // color
- String colorParameter = arguments.getString("COLOR");
- if (!TextUtils.isEmpty(colorParameter)) {
- FileDataStorageManager fileDataStorageManager = new FileDataStorageManager(user,
- targetContext.getContentResolver());
- String colorHex = null;
- COLOR = colorParameter;
- switch (colorParameter) {
- case "red":
- colorHex = "#7c0000";
- break;
- case "green":
- colorHex = "#00ff00";
- break;
- case "white":
- colorHex = "#ffffff";
- break;
- case "black":
- colorHex = "#000000";
- break;
- case "lightgreen":
- colorHex = "#aaff00";
- break;
- default:
- break;
- }
- OCCapability capability = fileDataStorageManager.getCapability(account.name);
- capability.setGroupfolders(CapabilityBooleanType.TRUE);
- if (colorHex != null) {
- capability.setServerColor(colorHex);
- }
- fileDataStorageManager.saveCapabilities(capability);
- }
- // dark / light
- String darkModeParameter = arguments.getString("DARKMODE");
- if (darkModeParameter != null) {
- if (darkModeParameter.equalsIgnoreCase("dark")) {
- DARK_MODE = "dark";
- AppPreferencesImpl.fromContext(targetContext).setDarkThemeMode(DarkMode.DARK);
- MainApp.setAppTheme(DarkMode.DARK);
- } else {
- DARK_MODE = "light";
- }
- }
- if (DARK_MODE.equalsIgnoreCase("light") && COLOR.equalsIgnoreCase("blue")) {
- // use already existing names
- DARK_MODE = "";
- COLOR = "";
- }
- }
- protected void testOnlyOnServer(OwnCloudVersion version) throws AccountUtils.AccountNotFoundException {
- OCCapability ocCapability = getCapability();
- assumeTrue(ocCapability.getVersion().isNewerOrEqual(version));
- }
- protected OCCapability getCapability() throws AccountUtils.AccountNotFoundException {
- NextcloudClient client = OwnCloudClientFactory.createNextcloudClient(user, targetContext);
- OCCapability ocCapability = (OCCapability) new GetCapabilitiesRemoteOperation()
- .execute(client)
- .getSingleData();
- return ocCapability;
- }
- @Before
- public void enableAccessibilityChecks() {
- androidx.test.espresso.accessibility.AccessibilityChecks.enable().setRunChecksFromRootView(true);
- }
- @After
- public void after() {
- fileDataStorageManager.removeLocalFiles(user, fileDataStorageManager);
- fileDataStorageManager.deleteAllFiles();
- }
- protected FileDataStorageManager getStorageManager() {
- return fileDataStorageManager;
- }
- protected Account[] getAllAccounts() {
- return AccountManager.get(targetContext).getAccounts();
- }
- protected static void createDummyFiles() throws IOException {
- File tempPath = new File(FileStorageUtils.getTemporalPath(account.name));
- if (!tempPath.exists()) {
- assertTrue(tempPath.mkdirs());
- }
- assertTrue(tempPath.exists());
- createFile("empty.txt", 0);
- createFile("nonEmpty.txt", 100);
- createFile("chunkedFile.txt", 500000);
- }
- protected static File getDummyFile(String name) throws IOException {
- File file = new File(FileStorageUtils.getInternalTemporalPath(account.name, targetContext) + File.separator + name);
- if (file.exists()) {
- return file;
- } else if (name.endsWith("/")) {
- file.mkdirs();
- return file;
- } else {
- switch (name) {
- case "empty.txt":
- return createFile("empty.txt", 0);
- case "nonEmpty.txt":
- return createFile("nonEmpty.txt", 100);
- case "chunkedFile.txt":
- return createFile("chunkedFile.txt", 500000);
- default:
- return createFile(name, 0);
- }
- }
- }
- public static File createFile(String name, int iteration) throws IOException {
- File file = new File(FileStorageUtils.getTemporalPath(account.name) + File.separator + name);
- if (!file.getParentFile().exists()) {
- assertTrue(file.getParentFile().mkdirs());
- }
- file.createNewFile();
- FileWriter writer = new FileWriter(file);
- for (int i = 0; i < iteration; i++) {
- writer.write("123123123123123123123123123\n");
- }
- writer.flush();
- writer.close();
- return file;
- }
- protected File getFile(String filename) throws IOException {
- InputStream inputStream = getInstrumentation().getContext().getAssets().open(filename);
- File temp = File.createTempFile("file", "file");
- FileUtils.copyInputStreamToFile(inputStream, temp);
- return temp;
- }
- protected void waitForIdleSync() {
- InstrumentationRegistry.getInstrumentation().waitForIdleSync();
- }
- protected void openDrawer(IntentsTestRule activityRule) {
- Activity sut = activityRule.launchActivity(null);
- shortSleep();
- onView(withId(R.id.drawer_layout)).perform(DrawerActions.open());
- waitForIdleSync();
- screenshot(sut);
- }
- protected Activity getCurrentActivity() {
- InstrumentationRegistry.getInstrumentation().runOnMainSync(() -> {
- Collection<Activity> resumedActivities = ActivityLifecycleMonitorRegistry
- .getInstance()
- .getActivitiesInStage(Stage.RESUMED);
- if (resumedActivities.iterator().hasNext()) {
- currentActivity = resumedActivities.iterator().next();
- }
- });
- return currentActivity;
- }
- protected static void shortSleep() {
- try {
- Thread.sleep(2000);
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- }
- protected void longSleep() {
- try {
- Thread.sleep(20000);
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- }
- protected void sleep(int second) {
- try {
- Thread.sleep(1000L * second);
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- }
- public OCFile createFolder(String remotePath) {
- RemoteOperationResult check = new ExistenceCheckRemoteOperation(remotePath, false).execute(client);
- if (!check.isSuccess()) {
- assertTrue(new CreateFolderOperation(remotePath, user, targetContext, getStorageManager())
- .execute(client)
- .isSuccess());
- }
- return getStorageManager().getFileByDecryptedRemotePath(remotePath.endsWith("/") ? remotePath : remotePath + "/");
- }
- public void uploadFile(File file, String remotePath) {
- OCUpload ocUpload = new OCUpload(file.getAbsolutePath(), remotePath, account.name);
- uploadOCUpload(ocUpload);
- }
- public void uploadOCUpload(OCUpload ocUpload) {
- ConnectivityService connectivityServiceMock = new ConnectivityService() {
- @Override
- public boolean isConnected() {
- return false;
- }
- @Override
- public boolean isInternetWalled() {
- return false;
- }
- @Override
- public Connectivity getConnectivity() {
- return Connectivity.CONNECTED_WIFI;
- }
- };
- PowerManagementService powerManagementServiceMock = new PowerManagementService() {
- @NonNull
- @Override
- public BatteryStatus getBattery() {
- return new BatteryStatus();
- }
- @Override
- public boolean isPowerSavingEnabled() {
- return false;
- }
- @Override
- public boolean isPowerSavingExclusionAvailable() {
- return false;
- }
- };
- UserAccountManager accountManager = UserAccountManagerImpl.fromContext(targetContext);
- UploadsStorageManager uploadsStorageManager = new UploadsStorageManager(accountManager,
- targetContext.getContentResolver());
- UploadFileOperation newUpload = new UploadFileOperation(
- uploadsStorageManager,
- connectivityServiceMock,
- powerManagementServiceMock,
- user,
- null,
- ocUpload,
- NameCollisionPolicy.DEFAULT,
- FileUploadWorker.LOCAL_BEHAVIOUR_COPY,
- targetContext,
- false,
- false,
- getStorageManager()
- );
- newUpload.addRenameUploadListener(() -> {
- // dummy
- });
- newUpload.setRemoteFolderToBeCreated();
- RemoteOperationResult result = newUpload.execute(client);
- assertTrue(result.getLogMessage(), result.isSuccess());
- }
- protected void enableRTL() {
- Locale locale = new Locale("ar");
- Resources resources = InstrumentationRegistry.getInstrumentation().getTargetContext().getResources();
- Configuration config = resources.getConfiguration();
- config.setLocale(locale);
- resources.updateConfiguration(config, null);
- }
- protected void resetLocale() {
- Locale locale = new Locale("en");
- Resources resources = InstrumentationRegistry.getInstrumentation().getTargetContext().getResources();
- Configuration config = resources.getConfiguration();
- config.setLocale(locale);
- resources.updateConfiguration(config, null);
- }
- protected void screenshot(View view) {
- screenshot(view, "");
- }
- protected void screenshot(View view, String prefix) {
- if (Build.VERSION.SDK_INT < Build.VERSION_CODES.R) {
- Screenshot.snap(view).setName(createName(prefix)).record();
- }
- }
- protected void screenshot(Activity sut) {
- if (Build.VERSION.SDK_INT < Build.VERSION_CODES.R) {
- Screenshot.snapActivity(sut).setName(createName()).record();
- }
- }
- protected void screenshot(DialogFragment dialogFragment, String prefix) {
- screenshot(Objects.requireNonNull(dialogFragment.requireDialog().getWindow()).getDecorView(), prefix);
- }
- private String createName() {
- return createName("");
- }
- private String createName(String prefix) {
- String name = TestNameDetector.getTestClass() + "_" + TestNameDetector.getTestName();
- if (!TextUtils.isEmpty(prefix)) {
- name = name + "_" + prefix;
- }
- if (!DARK_MODE.isEmpty()) {
- name = name + "_" + DARK_MODE;
- }
- if (!COLOR.isEmpty()) {
- name = name + "_" + COLOR;
- }
- return name;
- }
- public static String getUserId(User user) {
- return AccountManager.get(targetContext).getUserData(user.toPlatformAccount(), KEY_USER_ID);
- }
- public String getRandomName() {
- return getRandomName(5);
- }
- public String getRandomName(int length) {
- return RandomStringGenerator.make(length);
- }
- protected static User getUser(Account account) {
- Optional<User> optionalUser = UserAccountManagerImpl.fromContext(targetContext).getUser(account.name);
- return optionalUser.orElseThrow(IllegalAccessError::new);
- }
- protected static Account createAccount(String name) {
- AccountManager platformAccountManager = AccountManager.get(targetContext);
- Account temp = new Account(name, MainApp.getAccountType(targetContext));
- int atPos = name.lastIndexOf('@');
- platformAccountManager.addAccountExplicitly(temp, "password", null);
- platformAccountManager.setUserData(temp, AccountUtils.Constants.KEY_OC_BASE_URL,
- name.substring(atPos + 1));
- platformAccountManager.setUserData(temp, KEY_USER_ID, name.substring(0, atPos));
- Account account = UserAccountManagerImpl.fromContext(targetContext).getAccountByName(name);
- if (account == null) {
- throw new ActivityNotFoundException();
- }
- return account;
- }
- protected static boolean removeAccount(Account account) {
- return AccountManager.get(targetContext).removeAccountExplicitly(account);
- }
- }
|