UploadIT.java 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482
  1. /*
  2. * Nextcloud Android client application
  3. *
  4. * @author Tobias Kaminsky
  5. * Copyright (C) 2020 Tobias Kaminsky
  6. * Copyright (C) 2020 Nextcloud GmbH
  7. * Copyright (C) 2020 Chris Narkiewicz <hello@ezaquarii.com>
  8. *
  9. * This program is free software: you can redistribute it and/or modify
  10. * it under the terms of the GNU Affero General Public License as published by
  11. * the Free Software Foundation, either version 3 of the License, or
  12. * (at your option) any later version.
  13. *
  14. * This program is distributed in the hope that it will be useful,
  15. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  16. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  17. * GNU Affero General Public License for more details.
  18. *
  19. * You should have received a copy of the GNU Affero General Public License
  20. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  21. */
  22. package com.owncloud.android;
  23. import com.nextcloud.client.account.UserAccountManagerImpl;
  24. import com.nextcloud.client.device.BatteryStatus;
  25. import com.nextcloud.client.device.PowerManagementService;
  26. import com.nextcloud.client.network.Connectivity;
  27. import com.nextcloud.client.network.ConnectivityService;
  28. import com.owncloud.android.datamodel.OCFile;
  29. import com.owncloud.android.datamodel.UploadsStorageManager;
  30. import com.owncloud.android.db.OCUpload;
  31. import com.owncloud.android.files.services.FileUploader;
  32. import com.owncloud.android.files.services.NameCollisionPolicy;
  33. import com.owncloud.android.lib.common.operations.RemoteOperationResult;
  34. import com.owncloud.android.operations.RefreshFolderOperation;
  35. import com.owncloud.android.operations.RemoveFileOperation;
  36. import com.owncloud.android.operations.UploadFileOperation;
  37. import com.owncloud.android.utils.FileStorageUtils;
  38. import org.junit.After;
  39. import org.junit.Before;
  40. import org.junit.Test;
  41. import java.io.File;
  42. import java.io.IOException;
  43. import java.nio.file.Files;
  44. import java.nio.file.attribute.BasicFileAttributes;
  45. import java.util.List;
  46. import java.util.concurrent.TimeUnit;
  47. import androidx.annotation.NonNull;
  48. import static junit.framework.TestCase.assertEquals;
  49. import static junit.framework.TestCase.assertFalse;
  50. import static junit.framework.TestCase.assertTrue;
  51. /**
  52. * Tests related to file uploads
  53. */
  54. public class UploadIT extends AbstractOnServerIT {
  55. private static final String FOLDER = "/testUpload/";
  56. private UploadsStorageManager uploadsStorageManager =
  57. new UploadsStorageManager(UserAccountManagerImpl.fromContext(targetContext),
  58. targetContext.getContentResolver());
  59. private ConnectivityService connectivityServiceMock = new ConnectivityService() {
  60. @Override
  61. public boolean isInternetWalled() {
  62. return false;
  63. }
  64. @Override
  65. public Connectivity getConnectivity() {
  66. return Connectivity.CONNECTED_WIFI;
  67. }
  68. };
  69. private PowerManagementService powerManagementServiceMock = new PowerManagementService() {
  70. @Override
  71. public boolean isPowerSavingEnabled() {
  72. return false;
  73. }
  74. @Override
  75. public boolean isPowerSavingExclusionAvailable() {
  76. return false;
  77. }
  78. @NonNull
  79. @Override
  80. public BatteryStatus getBattery() {
  81. return new BatteryStatus(false, 0);
  82. }
  83. };
  84. @Before
  85. public void before() throws IOException {
  86. // make sure that every file is available, even after tests that remove source file
  87. createDummyFiles();
  88. }
  89. @After
  90. public void after() {
  91. RemoteOperationResult result = new RefreshFolderOperation(getStorageManager().getFileByPath("/"),
  92. System.currentTimeMillis() / 1000L,
  93. false,
  94. true,
  95. getStorageManager(),
  96. user,
  97. targetContext)
  98. .execute(client);
  99. // cleanup only if folder exists
  100. if (result.isSuccess() && getStorageManager().getFileByDecryptedRemotePath(FOLDER) != null) {
  101. new RemoveFileOperation(getStorageManager().getFileByDecryptedRemotePath(FOLDER),
  102. false,
  103. account,
  104. false,
  105. targetContext,
  106. getStorageManager())
  107. .execute(client);
  108. }
  109. }
  110. @Test
  111. public void testEmptyUpload() {
  112. OCUpload ocUpload = new OCUpload(FileStorageUtils.getTemporalPath(account.name) + "/empty.txt",
  113. FOLDER + "empty.txt",
  114. account.name);
  115. uploadOCUpload(ocUpload);
  116. }
  117. @Test
  118. public void testNonEmptyUpload() {
  119. OCUpload ocUpload = new OCUpload(FileStorageUtils.getTemporalPath(account.name) + "/nonEmpty.txt",
  120. FOLDER + "nonEmpty.txt",
  121. account.name);
  122. uploadOCUpload(ocUpload);
  123. }
  124. @Test
  125. public void testUploadWithCopy() {
  126. OCUpload ocUpload = new OCUpload(FileStorageUtils.getTemporalPath(account.name) + "/nonEmpty.txt",
  127. FOLDER + "nonEmpty.txt",
  128. account.name);
  129. uploadOCUpload(ocUpload, FileUploader.LOCAL_BEHAVIOUR_COPY);
  130. File originalFile = new File(FileStorageUtils.getTemporalPath(account.name) + "/nonEmpty.txt");
  131. OCFile uploadedFile = fileDataStorageManager.getFileByDecryptedRemotePath(FOLDER + "nonEmpty.txt");
  132. assertTrue(originalFile.exists());
  133. assertTrue(new File(uploadedFile.getStoragePath()).exists());
  134. verifyStoragePath(uploadedFile);
  135. }
  136. @Test
  137. public void testUploadWithMove() {
  138. OCUpload ocUpload = new OCUpload(FileStorageUtils.getTemporalPath(account.name) + "/nonEmpty.txt",
  139. FOLDER + "nonEmpty.txt",
  140. account.name);
  141. uploadOCUpload(ocUpload, FileUploader.LOCAL_BEHAVIOUR_MOVE);
  142. File originalFile = new File(FileStorageUtils.getTemporalPath(account.name) + "/nonEmpty.txt");
  143. OCFile uploadedFile = fileDataStorageManager.getFileByDecryptedRemotePath(FOLDER + "nonEmpty.txt");
  144. assertFalse(originalFile.exists());
  145. assertTrue(new File(uploadedFile.getStoragePath()).exists());
  146. verifyStoragePath(uploadedFile);
  147. }
  148. @Test
  149. public void testUploadWithForget() {
  150. OCUpload ocUpload = new OCUpload(FileStorageUtils.getTemporalPath(account.name) + "/nonEmpty.txt",
  151. FOLDER + "nonEmpty.txt",
  152. account.name);
  153. uploadOCUpload(ocUpload, FileUploader.LOCAL_BEHAVIOUR_FORGET);
  154. File originalFile = new File(FileStorageUtils.getTemporalPath(account.name) + "/nonEmpty.txt");
  155. OCFile uploadedFile = fileDataStorageManager.getFileByDecryptedRemotePath(FOLDER + "nonEmpty.txt");
  156. assertTrue(originalFile.exists());
  157. assertFalse(new File(uploadedFile.getStoragePath()).exists());
  158. assertTrue(uploadedFile.getStoragePath().isEmpty());
  159. }
  160. @Test
  161. public void testUploadWithDelete() {
  162. OCUpload ocUpload = new OCUpload(FileStorageUtils.getTemporalPath(account.name) + "/nonEmpty.txt",
  163. FOLDER + "nonEmpty.txt",
  164. account.name);
  165. uploadOCUpload(ocUpload, FileUploader.LOCAL_BEHAVIOUR_DELETE);
  166. File originalFile = new File(FileStorageUtils.getTemporalPath(account.name) + "/nonEmpty.txt");
  167. OCFile uploadedFile = fileDataStorageManager.getFileByDecryptedRemotePath(FOLDER + "nonEmpty.txt");
  168. assertFalse(originalFile.exists());
  169. assertFalse(new File(uploadedFile.getStoragePath()).exists());
  170. assertTrue(uploadedFile.getStoragePath().isEmpty());
  171. }
  172. @Test
  173. public void testChunkedUpload() {
  174. OCUpload ocUpload = new OCUpload(FileStorageUtils.getTemporalPath(account.name) + "/chunkedFile.txt",
  175. FOLDER + "chunkedFile.txt", account.name);
  176. uploadOCUpload(ocUpload);
  177. }
  178. @Test
  179. public void testUploadInNonExistingFolder() {
  180. OCUpload ocUpload = new OCUpload(FileStorageUtils.getTemporalPath(account.name) + "/empty.txt",
  181. FOLDER + "2/3/4/1.txt", account.name);
  182. uploadOCUpload(ocUpload);
  183. }
  184. @Test
  185. public void testUploadOnChargingOnlyButNotCharging() {
  186. OCUpload ocUpload = new OCUpload(FileStorageUtils.getTemporalPath(account.name) + "/empty.txt",
  187. FOLDER + "notCharging.txt", account.name);
  188. ocUpload.setWhileChargingOnly(true);
  189. UploadFileOperation newUpload = new UploadFileOperation(
  190. uploadsStorageManager,
  191. connectivityServiceMock,
  192. powerManagementServiceMock,
  193. user,
  194. null,
  195. ocUpload,
  196. NameCollisionPolicy.DEFAULT,
  197. FileUploader.LOCAL_BEHAVIOUR_COPY,
  198. targetContext,
  199. false,
  200. true,
  201. getStorageManager()
  202. );
  203. newUpload.setRemoteFolderToBeCreated();
  204. newUpload.addRenameUploadListener(() -> {
  205. // dummy
  206. });
  207. RemoteOperationResult result = newUpload.execute(client);
  208. assertFalse(result.toString(), result.isSuccess());
  209. assertEquals(RemoteOperationResult.ResultCode.DELAYED_FOR_CHARGING, result.getCode());
  210. }
  211. @Test
  212. public void testUploadOnChargingOnlyAndCharging() {
  213. PowerManagementService powerManagementServiceMock = new PowerManagementService() {
  214. @Override
  215. public boolean isPowerSavingEnabled() {
  216. return false;
  217. }
  218. @Override
  219. public boolean isPowerSavingExclusionAvailable() {
  220. return false;
  221. }
  222. @NonNull
  223. @Override
  224. public BatteryStatus getBattery() {
  225. return new BatteryStatus(true, 100);
  226. }
  227. };
  228. OCUpload ocUpload = new OCUpload(FileStorageUtils.getTemporalPath(account.name) + "/empty.txt",
  229. FOLDER + "charging.txt", account.name);
  230. ocUpload.setWhileChargingOnly(true);
  231. UploadFileOperation newUpload = new UploadFileOperation(
  232. uploadsStorageManager,
  233. connectivityServiceMock,
  234. powerManagementServiceMock,
  235. user,
  236. null,
  237. ocUpload,
  238. NameCollisionPolicy.DEFAULT,
  239. FileUploader.LOCAL_BEHAVIOUR_COPY,
  240. targetContext,
  241. false,
  242. true,
  243. getStorageManager()
  244. );
  245. newUpload.setRemoteFolderToBeCreated();
  246. newUpload.addRenameUploadListener(() -> {
  247. // dummy
  248. });
  249. RemoteOperationResult result = newUpload.execute(client);
  250. assertTrue(result.toString(), result.isSuccess());
  251. }
  252. @Test
  253. public void testUploadOnWifiOnlyButNoWifi() {
  254. ConnectivityService connectivityServiceMock = new ConnectivityService() {
  255. @Override
  256. public boolean isInternetWalled() {
  257. return false;
  258. }
  259. @Override
  260. public Connectivity getConnectivity() {
  261. return new Connectivity(true, false, false, true);
  262. }
  263. };
  264. OCUpload ocUpload = new OCUpload(FileStorageUtils.getTemporalPath(account.name) + "/empty.txt",
  265. FOLDER + "noWifi.txt", account.name);
  266. ocUpload.setUseWifiOnly(true);
  267. UploadFileOperation newUpload = new UploadFileOperation(
  268. uploadsStorageManager,
  269. connectivityServiceMock,
  270. powerManagementServiceMock,
  271. user,
  272. null,
  273. ocUpload,
  274. NameCollisionPolicy.DEFAULT,
  275. FileUploader.LOCAL_BEHAVIOUR_COPY,
  276. targetContext,
  277. true,
  278. false,
  279. getStorageManager()
  280. );
  281. newUpload.setRemoteFolderToBeCreated();
  282. newUpload.addRenameUploadListener(() -> {
  283. // dummy
  284. });
  285. RemoteOperationResult result = newUpload.execute(client);
  286. assertFalse(result.toString(), result.isSuccess());
  287. assertEquals(RemoteOperationResult.ResultCode.DELAYED_FOR_WIFI, result.getCode());
  288. }
  289. @Test
  290. public void testUploadOnWifiOnlyAndWifi() {
  291. OCUpload ocUpload = new OCUpload(FileStorageUtils.getTemporalPath(account.name) + "/empty.txt",
  292. FOLDER + "wifi.txt", account.name);
  293. ocUpload.setWhileChargingOnly(true);
  294. UploadFileOperation newUpload = new UploadFileOperation(
  295. uploadsStorageManager,
  296. connectivityServiceMock,
  297. powerManagementServiceMock,
  298. user,
  299. null,
  300. ocUpload,
  301. NameCollisionPolicy.DEFAULT,
  302. FileUploader.LOCAL_BEHAVIOUR_COPY,
  303. targetContext,
  304. true,
  305. false,
  306. getStorageManager()
  307. );
  308. newUpload.setRemoteFolderToBeCreated();
  309. newUpload.addRenameUploadListener(() -> {
  310. // dummy
  311. });
  312. RemoteOperationResult result = newUpload.execute(client);
  313. assertTrue(result.toString(), result.isSuccess());
  314. // cleanup
  315. new RemoveFileOperation(getStorageManager().getFileByDecryptedRemotePath(FOLDER),
  316. false,
  317. account,
  318. false,
  319. targetContext,
  320. getStorageManager())
  321. .execute(client);
  322. }
  323. @Test
  324. public void testUploadOnWifiOnlyButMeteredWifi() {
  325. ConnectivityService connectivityServiceMock = new ConnectivityService() {
  326. @Override
  327. public boolean isInternetWalled() {
  328. return false;
  329. }
  330. @Override
  331. public Connectivity getConnectivity() {
  332. return new Connectivity(true, true, true, true);
  333. }
  334. };
  335. OCUpload ocUpload = new OCUpload(FileStorageUtils.getTemporalPath(account.name) + "/empty.txt",
  336. FOLDER + "noWifi.txt",
  337. account.name);
  338. ocUpload.setUseWifiOnly(true);
  339. UploadFileOperation newUpload = new UploadFileOperation(
  340. uploadsStorageManager,
  341. connectivityServiceMock,
  342. powerManagementServiceMock,
  343. user,
  344. null,
  345. ocUpload,
  346. NameCollisionPolicy.DEFAULT,
  347. FileUploader.LOCAL_BEHAVIOUR_COPY,
  348. targetContext,
  349. true,
  350. false,
  351. getStorageManager()
  352. );
  353. newUpload.setRemoteFolderToBeCreated();
  354. newUpload.addRenameUploadListener(() -> {
  355. // dummy
  356. });
  357. RemoteOperationResult result = newUpload.execute(client);
  358. assertFalse(result.toString(), result.isSuccess());
  359. assertEquals(RemoteOperationResult.ResultCode.DELAYED_FOR_WIFI, result.getCode());
  360. }
  361. @Test
  362. public void testCreationAndUploadTimestamp() throws IOException {
  363. File file = getDummyFile("/empty.txt");
  364. String remotePath = "/testFile.txt";
  365. OCUpload ocUpload = new OCUpload(file.getAbsolutePath(), remotePath, account.name);
  366. long creationTimestamp = Files.readAttributes(file.toPath(), BasicFileAttributes.class)
  367. .creationTime()
  368. .to(TimeUnit.SECONDS);
  369. // wait a bit to simulate a later upload, so we can verify if creation date is set correct
  370. shortSleep();
  371. assertTrue(
  372. new UploadFileOperation(
  373. uploadsStorageManager,
  374. connectivityServiceMock,
  375. powerManagementServiceMock,
  376. user,
  377. null,
  378. ocUpload,
  379. NameCollisionPolicy.DEFAULT,
  380. FileUploader.LOCAL_BEHAVIOUR_COPY,
  381. targetContext,
  382. false,
  383. false,
  384. getStorageManager()
  385. )
  386. .setRemoteFolderToBeCreated()
  387. .execute(client)
  388. .isSuccess()
  389. );
  390. long uploadTimestamp = System.currentTimeMillis() / 1000;
  391. // RefreshFolderOperation
  392. assertTrue(new RefreshFolderOperation(getStorageManager().getFileByDecryptedRemotePath("/"),
  393. System.currentTimeMillis() / 1000,
  394. false,
  395. false,
  396. getStorageManager(),
  397. user,
  398. targetContext).execute(client).isSuccess());
  399. List<OCFile> files = getStorageManager().getFolderContent(getStorageManager().getFileByDecryptedRemotePath("/"),
  400. false);
  401. OCFile ocFile = files.get(0);
  402. assertEquals(remotePath, ocFile.getRemotePath());
  403. assertEquals(creationTimestamp, ocFile.getCreationTimestamp());
  404. assertTrue(uploadTimestamp - 10 < ocFile.getUploadTimestamp() ||
  405. uploadTimestamp + 10 > ocFile.getUploadTimestamp());
  406. }
  407. private void verifyStoragePath(OCFile file) {
  408. assertEquals(FileStorageUtils.getSavePath(account.name) + FOLDER + file.getDecryptedFileName(),
  409. file.getStoragePath());
  410. }
  411. }