UploadIT.java 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517
  1. /*
  2. * Nextcloud - Android Client
  3. *
  4. * SPDX-FileCopyrightText: 2020 Tobias Kaminsky <tobias@kaminsky.me>
  5. * SPDX-FileCopyrightText: 2020 Chris Narkiewicz <hello@ezaquarii.com>
  6. * SPDX-FileCopyrightText: 2020 Nextcloud GmbH
  7. * SPDX-License-Identifier: AGPL-3.0-or-later OR GPL-2.0-only
  8. */
  9. package com.owncloud.android;
  10. import com.nextcloud.client.account.UserAccountManagerImpl;
  11. import com.nextcloud.client.device.BatteryStatus;
  12. import com.nextcloud.client.device.PowerManagementService;
  13. import com.nextcloud.client.jobs.upload.FileUploadWorker;
  14. import com.nextcloud.client.network.Connectivity;
  15. import com.nextcloud.client.network.ConnectivityService;
  16. import com.owncloud.android.datamodel.OCFile;
  17. import com.owncloud.android.datamodel.UploadsStorageManager;
  18. import com.owncloud.android.db.OCUpload;
  19. import com.owncloud.android.files.services.NameCollisionPolicy;
  20. import com.owncloud.android.lib.common.accounts.AccountUtils;
  21. import com.owncloud.android.lib.common.operations.RemoteOperationResult;
  22. import com.owncloud.android.lib.resources.files.model.GeoLocation;
  23. import com.owncloud.android.lib.resources.files.model.ImageDimension;
  24. import com.owncloud.android.lib.resources.status.NextcloudVersion;
  25. import com.owncloud.android.operations.RefreshFolderOperation;
  26. import com.owncloud.android.operations.RemoveFileOperation;
  27. import com.owncloud.android.operations.UploadFileOperation;
  28. import com.owncloud.android.utils.FileStorageUtils;
  29. import org.junit.Before;
  30. import org.junit.Test;
  31. import java.io.File;
  32. import java.io.IOException;
  33. import java.nio.file.Files;
  34. import java.nio.file.attribute.BasicFileAttributes;
  35. import java.util.List;
  36. import java.util.concurrent.TimeUnit;
  37. import androidx.annotation.NonNull;
  38. import static junit.framework.TestCase.assertEquals;
  39. import static junit.framework.TestCase.assertFalse;
  40. import static junit.framework.TestCase.assertNotNull;
  41. import static junit.framework.TestCase.assertTrue;
  42. /**
  43. * Tests related to file uploads.
  44. */
  45. public class UploadIT extends AbstractOnServerIT {
  46. private static final String FOLDER = "/testUpload/";
  47. private UploadsStorageManager uploadsStorageManager =
  48. new UploadsStorageManager(UserAccountManagerImpl.fromContext(targetContext),
  49. targetContext.getContentResolver());
  50. private ConnectivityService connectivityServiceMock = new ConnectivityService() {
  51. @Override
  52. public boolean isConnected() {
  53. return false;
  54. }
  55. @Override
  56. public boolean isInternetWalled() {
  57. return false;
  58. }
  59. @Override
  60. public Connectivity getConnectivity() {
  61. return Connectivity.CONNECTED_WIFI;
  62. }
  63. };
  64. private PowerManagementService powerManagementServiceMock = new PowerManagementService() {
  65. @Override
  66. public boolean isPowerSavingEnabled() {
  67. return false;
  68. }
  69. @Override
  70. public boolean isPowerSavingExclusionAvailable() {
  71. return false;
  72. }
  73. @NonNull
  74. @Override
  75. public BatteryStatus getBattery() {
  76. return new BatteryStatus(false, 0);
  77. }
  78. };
  79. @Before
  80. public void before() throws IOException {
  81. // make sure that every file is available, even after tests that remove source file
  82. createDummyFiles();
  83. }
  84. @Test
  85. public void testEmptyUpload() {
  86. OCUpload ocUpload = new OCUpload(FileStorageUtils.getTemporalPath(account.name) + "/empty.txt",
  87. FOLDER + "empty.txt",
  88. account.name);
  89. uploadOCUpload(ocUpload);
  90. }
  91. @Test
  92. public void testNonEmptyUpload() {
  93. OCUpload ocUpload = new OCUpload(FileStorageUtils.getTemporalPath(account.name) + "/nonEmpty.txt",
  94. FOLDER + "nonEmpty.txt",
  95. account.name);
  96. uploadOCUpload(ocUpload);
  97. }
  98. @Test
  99. public void testUploadWithCopy() {
  100. OCUpload ocUpload = new OCUpload(FileStorageUtils.getTemporalPath(account.name) + "/nonEmpty.txt",
  101. FOLDER + "nonEmpty.txt",
  102. account.name);
  103. uploadOCUpload(ocUpload, FileUploadWorker.LOCAL_BEHAVIOUR_COPY);
  104. File originalFile = new File(FileStorageUtils.getTemporalPath(account.name) + "/nonEmpty.txt");
  105. OCFile uploadedFile = fileDataStorageManager.getFileByDecryptedRemotePath(FOLDER + "nonEmpty.txt");
  106. assertTrue(originalFile.exists());
  107. assertTrue(new File(uploadedFile.getStoragePath()).exists());
  108. verifyStoragePath(uploadedFile);
  109. }
  110. @Test
  111. public void testUploadWithMove() {
  112. OCUpload ocUpload = new OCUpload(FileStorageUtils.getTemporalPath(account.name) + "/nonEmpty.txt",
  113. FOLDER + "nonEmpty.txt",
  114. account.name);
  115. uploadOCUpload(ocUpload, FileUploadWorker.LOCAL_BEHAVIOUR_MOVE);
  116. File originalFile = new File(FileStorageUtils.getTemporalPath(account.name) + "/nonEmpty.txt");
  117. OCFile uploadedFile = fileDataStorageManager.getFileByDecryptedRemotePath(FOLDER + "nonEmpty.txt");
  118. assertFalse(originalFile.exists());
  119. assertTrue(new File(uploadedFile.getStoragePath()).exists());
  120. verifyStoragePath(uploadedFile);
  121. }
  122. @Test
  123. public void testUploadWithForget() {
  124. OCUpload ocUpload = new OCUpload(FileStorageUtils.getTemporalPath(account.name) + "/nonEmpty.txt",
  125. FOLDER + "nonEmpty.txt",
  126. account.name);
  127. uploadOCUpload(ocUpload, FileUploadWorker.LOCAL_BEHAVIOUR_FORGET);
  128. File originalFile = new File(FileStorageUtils.getTemporalPath(account.name) + "/nonEmpty.txt");
  129. OCFile uploadedFile = fileDataStorageManager.getFileByDecryptedRemotePath(FOLDER + "nonEmpty.txt");
  130. assertTrue(originalFile.exists());
  131. assertFalse(new File(uploadedFile.getStoragePath()).exists());
  132. assertTrue(uploadedFile.getStoragePath().isEmpty());
  133. }
  134. @Test
  135. public void testUploadWithDelete() {
  136. OCUpload ocUpload = new OCUpload(FileStorageUtils.getTemporalPath(account.name) + "/nonEmpty.txt",
  137. FOLDER + "nonEmpty.txt",
  138. account.name);
  139. uploadOCUpload(ocUpload, FileUploadWorker.LOCAL_BEHAVIOUR_DELETE);
  140. File originalFile = new File(FileStorageUtils.getTemporalPath(account.name) + "/nonEmpty.txt");
  141. OCFile uploadedFile = fileDataStorageManager.getFileByDecryptedRemotePath(FOLDER + "nonEmpty.txt");
  142. assertFalse(originalFile.exists());
  143. assertFalse(new File(uploadedFile.getStoragePath()).exists());
  144. assertTrue(uploadedFile.getStoragePath().isEmpty());
  145. }
  146. @Test
  147. public void testChunkedUpload() {
  148. OCUpload ocUpload = new OCUpload(FileStorageUtils.getTemporalPath(account.name) + "/chunkedFile.txt",
  149. FOLDER + "chunkedFile.txt", account.name);
  150. uploadOCUpload(ocUpload);
  151. }
  152. @Test
  153. public void testUploadInNonExistingFolder() {
  154. OCUpload ocUpload = new OCUpload(FileStorageUtils.getTemporalPath(account.name) + "/empty.txt",
  155. FOLDER + "2/3/4/1.txt", account.name);
  156. uploadOCUpload(ocUpload);
  157. }
  158. @Test
  159. public void testUploadOnChargingOnlyButNotCharging() {
  160. OCUpload ocUpload = new OCUpload(FileStorageUtils.getTemporalPath(account.name) + "/empty.txt",
  161. FOLDER + "notCharging.txt", account.name);
  162. ocUpload.setWhileChargingOnly(true);
  163. UploadFileOperation newUpload = new UploadFileOperation(
  164. uploadsStorageManager,
  165. connectivityServiceMock,
  166. powerManagementServiceMock,
  167. user,
  168. null,
  169. ocUpload,
  170. NameCollisionPolicy.DEFAULT,
  171. FileUploadWorker.LOCAL_BEHAVIOUR_COPY,
  172. targetContext,
  173. false,
  174. true,
  175. getStorageManager()
  176. );
  177. newUpload.setRemoteFolderToBeCreated();
  178. newUpload.addRenameUploadListener(() -> {
  179. // dummy
  180. });
  181. RemoteOperationResult result = newUpload.execute(client);
  182. assertFalse(result.toString(), result.isSuccess());
  183. assertEquals(RemoteOperationResult.ResultCode.DELAYED_FOR_CHARGING, result.getCode());
  184. }
  185. @Test
  186. public void testUploadOnChargingOnlyAndCharging() {
  187. PowerManagementService powerManagementServiceMock = new PowerManagementService() {
  188. @Override
  189. public boolean isPowerSavingEnabled() {
  190. return false;
  191. }
  192. @Override
  193. public boolean isPowerSavingExclusionAvailable() {
  194. return false;
  195. }
  196. @NonNull
  197. @Override
  198. public BatteryStatus getBattery() {
  199. return new BatteryStatus(true, 100);
  200. }
  201. };
  202. OCUpload ocUpload = new OCUpload(FileStorageUtils.getTemporalPath(account.name) + "/empty.txt",
  203. FOLDER + "charging.txt", account.name);
  204. ocUpload.setWhileChargingOnly(true);
  205. UploadFileOperation newUpload = new UploadFileOperation(
  206. uploadsStorageManager,
  207. connectivityServiceMock,
  208. powerManagementServiceMock,
  209. user,
  210. null,
  211. ocUpload,
  212. NameCollisionPolicy.DEFAULT,
  213. FileUploadWorker.LOCAL_BEHAVIOUR_COPY,
  214. targetContext,
  215. false,
  216. true,
  217. getStorageManager()
  218. );
  219. newUpload.setRemoteFolderToBeCreated();
  220. newUpload.addRenameUploadListener(() -> {
  221. // dummy
  222. });
  223. RemoteOperationResult result = newUpload.execute(client);
  224. assertTrue(result.toString(), result.isSuccess());
  225. }
  226. @Test
  227. public void testUploadOnWifiOnlyButNoWifi() {
  228. ConnectivityService connectivityServiceMock = new ConnectivityService() {
  229. @Override
  230. public boolean isConnected() {
  231. return false;
  232. }
  233. @Override
  234. public boolean isInternetWalled() {
  235. return false;
  236. }
  237. @Override
  238. public Connectivity getConnectivity() {
  239. return new Connectivity(true, false, false, true);
  240. }
  241. };
  242. OCUpload ocUpload = new OCUpload(FileStorageUtils.getTemporalPath(account.name) + "/empty.txt",
  243. FOLDER + "noWifi.txt", account.name);
  244. ocUpload.setUseWifiOnly(true);
  245. UploadFileOperation newUpload = new UploadFileOperation(
  246. uploadsStorageManager,
  247. connectivityServiceMock,
  248. powerManagementServiceMock,
  249. user,
  250. null,
  251. ocUpload,
  252. NameCollisionPolicy.DEFAULT,
  253. FileUploadWorker.LOCAL_BEHAVIOUR_COPY,
  254. targetContext,
  255. true,
  256. false,
  257. getStorageManager()
  258. );
  259. newUpload.setRemoteFolderToBeCreated();
  260. newUpload.addRenameUploadListener(() -> {
  261. // dummy
  262. });
  263. RemoteOperationResult result = newUpload.execute(client);
  264. assertFalse(result.toString(), result.isSuccess());
  265. assertEquals(RemoteOperationResult.ResultCode.DELAYED_FOR_WIFI, result.getCode());
  266. }
  267. @Test
  268. public void testUploadOnWifiOnlyAndWifi() {
  269. OCUpload ocUpload = new OCUpload(FileStorageUtils.getTemporalPath(account.name) + "/empty.txt",
  270. FOLDER + "wifi.txt", account.name);
  271. ocUpload.setWhileChargingOnly(true);
  272. UploadFileOperation newUpload = new UploadFileOperation(
  273. uploadsStorageManager,
  274. connectivityServiceMock,
  275. powerManagementServiceMock,
  276. user,
  277. null,
  278. ocUpload,
  279. NameCollisionPolicy.DEFAULT,
  280. FileUploadWorker.LOCAL_BEHAVIOUR_COPY,
  281. targetContext,
  282. true,
  283. false,
  284. getStorageManager()
  285. );
  286. newUpload.setRemoteFolderToBeCreated();
  287. newUpload.addRenameUploadListener(() -> {
  288. // dummy
  289. });
  290. RemoteOperationResult result = newUpload.execute(client);
  291. assertTrue(result.toString(), result.isSuccess());
  292. // cleanup
  293. new RemoveFileOperation(getStorageManager().getFileByDecryptedRemotePath(FOLDER),
  294. false,
  295. user,
  296. false,
  297. targetContext,
  298. getStorageManager())
  299. .execute(client);
  300. }
  301. @Test
  302. public void testUploadOnWifiOnlyButMeteredWifi() {
  303. ConnectivityService connectivityServiceMock = new ConnectivityService() {
  304. @Override
  305. public boolean isConnected() {
  306. return false;
  307. }
  308. @Override
  309. public boolean isInternetWalled() {
  310. return false;
  311. }
  312. @Override
  313. public Connectivity getConnectivity() {
  314. return new Connectivity(true, true, true, true);
  315. }
  316. };
  317. OCUpload ocUpload = new OCUpload(FileStorageUtils.getTemporalPath(account.name) + "/empty.txt",
  318. FOLDER + "noWifi.txt",
  319. account.name);
  320. ocUpload.setUseWifiOnly(true);
  321. UploadFileOperation newUpload = new UploadFileOperation(
  322. uploadsStorageManager,
  323. connectivityServiceMock,
  324. powerManagementServiceMock,
  325. user,
  326. null,
  327. ocUpload,
  328. NameCollisionPolicy.DEFAULT,
  329. FileUploadWorker.LOCAL_BEHAVIOUR_COPY,
  330. targetContext,
  331. true,
  332. false,
  333. getStorageManager()
  334. );
  335. newUpload.setRemoteFolderToBeCreated();
  336. newUpload.addRenameUploadListener(() -> {
  337. // dummy
  338. });
  339. RemoteOperationResult result = newUpload.execute(client);
  340. assertFalse(result.toString(), result.isSuccess());
  341. assertEquals(RemoteOperationResult.ResultCode.DELAYED_FOR_WIFI, result.getCode());
  342. }
  343. @Test
  344. public void testCreationAndUploadTimestamp() throws IOException, AccountUtils.AccountNotFoundException {
  345. testOnlyOnServer(NextcloudVersion.nextcloud_27);
  346. File file = getDummyFile("empty.txt");
  347. String remotePath = "/testFile.txt";
  348. OCUpload ocUpload = new OCUpload(file.getAbsolutePath(), remotePath, account.name);
  349. assertTrue(
  350. new UploadFileOperation(
  351. uploadsStorageManager,
  352. connectivityServiceMock,
  353. powerManagementServiceMock,
  354. user,
  355. null,
  356. ocUpload,
  357. NameCollisionPolicy.DEFAULT,
  358. FileUploadWorker.LOCAL_BEHAVIOUR_COPY,
  359. targetContext,
  360. false,
  361. false,
  362. getStorageManager()
  363. )
  364. .setRemoteFolderToBeCreated()
  365. .execute(client)
  366. .isSuccess()
  367. );
  368. long creationTimestamp = Files.readAttributes(file.toPath(), BasicFileAttributes.class)
  369. .creationTime()
  370. .to(TimeUnit.SECONDS);
  371. long uploadTimestamp = System.currentTimeMillis() / 1000;
  372. // RefreshFolderOperation
  373. assertTrue(new RefreshFolderOperation(getStorageManager().getFileByDecryptedRemotePath("/"),
  374. System.currentTimeMillis() / 1000,
  375. false,
  376. false,
  377. getStorageManager(),
  378. user,
  379. targetContext).execute(client).isSuccess());
  380. List<OCFile> files = getStorageManager().getFolderContent(getStorageManager().getFileByDecryptedRemotePath("/"),
  381. false);
  382. OCFile ocFile = files.get(0);
  383. assertEquals(remotePath, ocFile.getRemotePath());
  384. assertEquals(creationTimestamp, ocFile.getCreationTimestamp());
  385. assertTrue(uploadTimestamp - 10 < ocFile.getUploadTimestamp() ||
  386. uploadTimestamp + 10 > ocFile.getUploadTimestamp());
  387. }
  388. @Test
  389. public void testMetadata() throws IOException, AccountUtils.AccountNotFoundException {
  390. testOnlyOnServer(NextcloudVersion.nextcloud_27);
  391. File file = getFile("gps.jpg");
  392. String remotePath = "/metadata.jpg";
  393. OCUpload ocUpload = new OCUpload(file.getAbsolutePath(), remotePath, account.name);
  394. assertTrue(
  395. new UploadFileOperation(
  396. uploadsStorageManager,
  397. connectivityServiceMock,
  398. powerManagementServiceMock,
  399. user,
  400. null,
  401. ocUpload,
  402. NameCollisionPolicy.DEFAULT,
  403. FileUploadWorker.LOCAL_BEHAVIOUR_COPY,
  404. targetContext,
  405. false,
  406. false,
  407. getStorageManager()
  408. )
  409. .setRemoteFolderToBeCreated()
  410. .execute(client)
  411. .isSuccess()
  412. );
  413. // RefreshFolderOperation
  414. assertTrue(new RefreshFolderOperation(getStorageManager().getFileByDecryptedRemotePath("/"),
  415. System.currentTimeMillis() / 1000,
  416. false,
  417. false,
  418. getStorageManager(),
  419. user,
  420. targetContext).execute(client).isSuccess());
  421. List<OCFile> files = getStorageManager().getFolderContent(getStorageManager().getFileByDecryptedRemotePath("/"),
  422. false);
  423. OCFile ocFile = null;
  424. for (OCFile f : files) {
  425. if (f.getFileName().equals("metadata.jpg")) {
  426. ocFile = f;
  427. break;
  428. }
  429. }
  430. assertNotNull(ocFile);
  431. assertEquals(remotePath, ocFile.getRemotePath());
  432. assertEquals(new GeoLocation(64, -46), ocFile.getGeoLocation());
  433. assertEquals(new ImageDimension(300f, 200f), ocFile.getImageDimension());
  434. }
  435. private void verifyStoragePath(OCFile file) {
  436. assertEquals(FileStorageUtils.getSavePath(account.name) + FOLDER + file.getDecryptedFileName(),
  437. file.getStoragePath());
  438. }
  439. }