UploadIT.java 19 KB

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