termux-app
396 строк · 18.4 Кб
1package com.termux.shared.file.tests;
2
3import android.content.Context;
4
5import androidx.annotation.NonNull;
6
7import com.termux.shared.errors.Errno;
8import com.termux.shared.file.FileUtils;
9import com.termux.shared.file.FileUtilsErrno;
10import com.termux.shared.logger.Logger;
11import com.termux.shared.errors.Error;
12
13import java.io.File;
14import java.nio.charset.Charset;
15import java.util.Arrays;
16import java.util.List;
17
18public class FileUtilsTests {
19
20private static final String LOG_TAG = "FileUtilsTests";
21
22/**
23* Run basic tests for {@link FileUtils} class.
24*
25* Move tests need to be written, specially for failures.
26*
27* The log level must be set to verbose.
28*
29* Run at app startup like in an activity
30* FileUtilsTests.runTests(this, TermuxConstants.TERMUX_HOME_DIR_PATH + "/FileUtilsTests");
31*
32* @param context The {@link Context} for operations.
33*/
34public static void runTests(@NonNull final Context context, @NonNull final String testRootDirectoryPath) {
35try {
36Logger.logInfo(LOG_TAG, "Running tests");
37Logger.logInfo(LOG_TAG, "testRootDirectoryPath: \"" + testRootDirectoryPath + "\"");
38
39String fileUtilsTestsDirectoryCanonicalPath = FileUtils.getCanonicalPath(testRootDirectoryPath, null);
40assertEqual("FileUtilsTests directory path is not a canonical path", testRootDirectoryPath, fileUtilsTestsDirectoryCanonicalPath);
41
42runTestsInner(testRootDirectoryPath);
43Logger.logInfo(LOG_TAG, "All tests successful");
44} catch (Exception e) {
45Logger.logErrorExtended(LOG_TAG, e.getMessage());
46Logger.showToast(context, e.getMessage() != null ? e.getMessage().replaceAll("(?s)\nFull Error:\n.*", "") : null, true);
47}
48}
49
50private static void runTestsInner(@NonNull final String testRootDirectoryPath) throws Exception {
51Error error;
52String label;
53String path;
54
55/*
56* - dir1
57* - sub_dir1
58* - sub_reg1
59* - sub_sym1 (absolute symlink to dir2)
60* - sub_sym2 (copy of sub_sym1 for symlink to dir2)
61* - sub_sym3 (relative symlink to dir4)
62* - dir2
63* - sub_reg1
64* - sub_reg2 (copy of dir2/sub_reg1)
65* - dir3 (copy of dir1)
66* - dir4 (moved from dir3)
67*/
68
69String dir1_label = "dir1";
70String dir1_path = testRootDirectoryPath + "/dir1";
71
72String dir1__sub_dir1_label = "dir1/sub_dir1";
73String dir1__sub_dir1_path = dir1_path + "/sub_dir1";
74
75String dir1__sub_dir2_label = "dir1/sub_dir2";
76String dir1__sub_dir2_path = dir1_path + "/sub_dir2";
77
78String dir1__sub_dir3_label = "dir1/sub_dir3";
79String dir1__sub_dir3_path = dir1_path + "/sub_dir3";
80
81String dir1__sub_dir3__sub_reg1_label = "dir1/sub_dir3/sub_reg1";
82String dir1__sub_dir3__sub_reg1_path = dir1__sub_dir3_path + "/sub_reg1";
83
84String dir1__sub_reg1_label = "dir1/sub_reg1";
85String dir1__sub_reg1_path = dir1_path + "/sub_reg1";
86
87String dir1__sub_sym1_label = "dir1/sub_sym1";
88String dir1__sub_sym1_path = dir1_path + "/sub_sym1";
89
90String dir1__sub_sym2_label = "dir1/sub_sym2";
91String dir1__sub_sym2_path = dir1_path + "/sub_sym2";
92
93String dir1__sub_sym3_label = "dir1/sub_sym3";
94String dir1__sub_sym3_path = dir1_path + "/sub_sym3";
95
96
97String dir2_label = "dir2";
98String dir2_path = testRootDirectoryPath + "/dir2";
99
100String dir2__sub_reg1_label = "dir2/sub_reg1";
101String dir2__sub_reg1_path = dir2_path + "/sub_reg1";
102
103String dir2__sub_reg2_label = "dir2/sub_reg2";
104String dir2__sub_reg2_path = dir2_path + "/sub_reg2";
105
106
107String dir3_label = "dir3";
108String dir3_path = testRootDirectoryPath + "/dir3";
109
110String dir4_label = "dir4";
111String dir4_path = testRootDirectoryPath + "/dir4";
112
113
114
115
116
117// Create or clear test root directory file
118label = "testRootDirectoryPath";
119error = FileUtils.clearDirectory(label, testRootDirectoryPath);
120assertEqual("Failed to create " + label + " directory file", null, error);
121
122if (!FileUtils.directoryFileExists(testRootDirectoryPath, false))
123throwException("The " + label + " directory file does not exist as expected after creation");
124
125
126// Create dir1 directory file
127error = FileUtils.createDirectoryFile(dir1_label, dir1_path);
128assertEqual("Failed to create " + dir1_label + " directory file", null, error);
129
130// Create dir2 directory file
131error = FileUtils.createDirectoryFile(dir2_label, dir2_path);
132assertEqual("Failed to create " + dir2_label + " directory file", null, error);
133
134
135
136
137
138// Create dir1/sub_dir1 directory file
139label = dir1__sub_dir1_label; path = dir1__sub_dir1_path;
140error = FileUtils.createDirectoryFile(label, path);
141assertEqual("Failed to create " + label + " directory file", null, error);
142if (!FileUtils.directoryFileExists(path, false))
143throwException("The " + label + " directory file does not exist as expected after creation");
144
145// Create dir1/sub_reg1 regular file
146label = dir1__sub_reg1_label; path = dir1__sub_reg1_path;
147error = FileUtils.createRegularFile(label, path);
148assertEqual("Failed to create " + label + " regular file", null, error);
149if (!FileUtils.regularFileExists(path, false))
150throwException("The " + label + " regular file does not exist as expected after creation");
151
152// Create dir1/sub_sym1 -> dir2 absolute symlink file
153label = dir1__sub_sym1_label; path = dir1__sub_sym1_path;
154error = FileUtils.createSymlinkFile(label, dir2_path, path);
155assertEqual("Failed to create " + label + " symlink file", null, error);
156if (!FileUtils.symlinkFileExists(path))
157throwException("The " + label + " symlink file does not exist as expected after creation");
158
159// Copy dir1/sub_sym1 symlink file to dir1/sub_sym2
160label = dir1__sub_sym2_label; path = dir1__sub_sym2_path;
161error = FileUtils.copySymlinkFile(label, dir1__sub_sym1_path, path, false);
162assertEqual("Failed to copy " + dir1__sub_sym1_label + " symlink file to " + label, null, error);
163if (!FileUtils.symlinkFileExists(path))
164throwException("The " + label + " symlink file does not exist as expected after copying it from " + dir1__sub_sym1_label);
165if (!new File(path).getCanonicalPath().equals(dir2_path))
166throwException("The " + label + " symlink file does not point to " + dir2_label);
167
168
169
170
171
172// Write "line1" to dir2/sub_reg1 regular file
173label = dir2__sub_reg1_label; path = dir2__sub_reg1_path;
174error = FileUtils.writeTextToFile(label, path, Charset.defaultCharset(), "line1", false);
175assertEqual("Failed to write string to " + label + " file with append mode false", null, error);
176if (!FileUtils.regularFileExists(path, false))
177throwException("The " + label + " file does not exist as expected after writing to it with append mode false");
178
179// Write "line2" to dir2/sub_reg1 regular file
180error = FileUtils.writeTextToFile(label, path, Charset.defaultCharset(), "\nline2", true);
181assertEqual("Failed to write string to " + label + " file with append mode true", null, error);
182
183// Read dir2/sub_reg1 regular file
184StringBuilder dataStringBuilder = new StringBuilder();
185error = FileUtils.readTextFromFile(label, path, Charset.defaultCharset(), dataStringBuilder, false);
186assertEqual("Failed to read from " + label + " file", null, error);
187assertEqual("The data read from " + label + " file in not as expected", "line1\nline2", dataStringBuilder.toString());
188
189// Copy dir2/sub_reg1 regular file to dir2/sub_reg2 file
190label = dir2__sub_reg2_label; path = dir2__sub_reg2_path;
191error = FileUtils.copyRegularFile(label, dir2__sub_reg1_path, path, false);
192assertEqual("Failed to copy " + dir2__sub_reg1_label + " regular file to " + label, null, error);
193if (!FileUtils.regularFileExists(path, false))
194throwException("The " + label + " regular file does not exist as expected after copying it from " + dir2__sub_reg1_label);
195
196
197
198
199
200// Copy dir1 directory file to dir3
201label = dir3_label; path = dir3_path;
202error = FileUtils.copyDirectoryFile(label, dir2_path, path, false);
203assertEqual("Failed to copy " + dir2_label + " directory file to " + label, null, error);
204if (!FileUtils.directoryFileExists(path, false))
205throwException("The " + label + " directory file does not exist as expected after copying it from " + dir2_label);
206
207// Copy dir1 directory file to dir3 again to test overwrite
208label = dir3_label; path = dir3_path;
209error = FileUtils.copyDirectoryFile(label, dir2_path, path, false);
210assertEqual("Failed to copy " + dir2_label + " directory file to " + label, null, error);
211if (!FileUtils.directoryFileExists(path, false))
212throwException("The " + label + " directory file does not exist as expected after copying it from " + dir2_label);
213
214// Move dir3 directory file to dir4
215label = dir4_label; path = dir4_path;
216error = FileUtils.moveDirectoryFile(label, dir3_path, path, false);
217assertEqual("Failed to move " + dir3_label + " directory file to " + label, null, error);
218if (!FileUtils.directoryFileExists(path, false))
219throwException("The " + label + " directory file does not exist as expected after copying it from " + dir3_label);
220
221
222
223
224
225// Create dir1/sub_sym3 -> dir4 relative symlink file
226label = dir1__sub_sym3_label; path = dir1__sub_sym3_path;
227error = FileUtils.createSymlinkFile(label, "../dir4", path);
228assertEqual("Failed to create " + label + " symlink file", null, error);
229if (!FileUtils.symlinkFileExists(path))
230throwException("The " + label + " symlink file does not exist as expected after creation");
231
232// Create dir1/sub_sym3 -> dirX relative dangling symlink file
233// This is to ensure that symlinkFileExists returns true if a symlink file exists but is dangling
234label = dir1__sub_sym3_label; path = dir1__sub_sym3_path;
235error = FileUtils.createSymlinkFile(label, "../dirX", path);
236assertEqual("Failed to create " + label + " symlink file", null, error);
237if (!FileUtils.symlinkFileExists(path))
238throwException("The " + label + " dangling symlink file does not exist as expected after creation");
239
240
241
242
243
244// Delete dir1/sub_sym2 symlink file
245label = dir1__sub_sym2_label; path = dir1__sub_sym2_path;
246error = FileUtils.deleteSymlinkFile(label, path, false);
247assertEqual("Failed to delete " + label + " symlink file", null, error);
248if (FileUtils.fileExists(path, false))
249throwException("The " + label + " symlink file still exist after deletion");
250
251// Check if dir2 directory file still exists after deletion of dir1/sub_sym2 since it was a symlink to dir2
252// When deleting a symlink file, its target must not be deleted
253label = dir2_label; path = dir2_path;
254if (!FileUtils.directoryFileExists(path, false))
255throwException("The " + label + " directory file has unexpectedly been deleted after deletion of " + dir1__sub_sym2_label);
256
257
258
259
260
261// Delete dir1 directory file
262label = dir1_label; path = dir1_path;
263error = FileUtils.deleteDirectoryFile(label, path, false);
264assertEqual("Failed to delete " + label + " directory file", null, error);
265if (FileUtils.fileExists(path, false))
266throwException("The " + label + " directory file still exist after deletion");
267
268
269// Check if dir2 directory file and dir2/sub_reg1 regular file still exist after deletion of
270// dir1 since there was a dir1/sub_sym1 symlink to dir2 in it
271// When deleting a directory, any targets of symlinks must not be deleted when deleting symlink files
272label = dir2_label; path = dir2_path;
273if (!FileUtils.directoryFileExists(path, false))
274throwException("The " + label + " directory file has unexpectedly been deleted after deletion of " + dir1_label);
275label = dir2__sub_reg1_label; path = dir2__sub_reg1_path;
276if (!FileUtils.fileExists(path, false))
277throwException("The " + label + " regular file has unexpectedly been deleted after deletion of " + dir1_label);
278
279
280
281
282
283// Delete dir2/sub_reg1 regular file
284label = dir2__sub_reg1_label; path = dir2__sub_reg1_path;
285error = FileUtils.deleteRegularFile(label, path, false);
286assertEqual("Failed to delete " + label + " regular file", null, error);
287if (FileUtils.fileExists(path, false))
288throwException("The " + label + " regular file still exist after deletion");
289
290
291List<String> ignoredSubFilePaths = Arrays.asList(dir1__sub_dir2_path, dir1__sub_dir3__sub_reg1_path);
292
293// Create dir1 directory file
294error = FileUtils.createDirectoryFile(dir1_label, dir1_path);
295assertEqual("Failed to create " + dir1_label + " directory file", null, error);
296
297// Test empty dir
298error = FileUtils.validateDirectoryFileEmptyOrOnlyContainsSpecificFiles(dir1_label, dir1_path, ignoredSubFilePaths, false);
299assertEqual("Failed to validate if " + dir1_label + " directory file is empty", null, error);
300
301
302// Create dir1/sub_dir3 directory file
303label = dir1__sub_dir3_label; path = dir1__sub_dir3_path;
304error = FileUtils.createDirectoryFile(label, path);
305assertEqual("Failed to create " + label + " directory file", null, error);
306if (!FileUtils.directoryFileExists(path, false))
307throwException("The " + label + " directory file does not exist as expected after creation");
308
309// Test parent dir existing of non existing ignored regular file
310error = FileUtils.validateDirectoryFileEmptyOrOnlyContainsSpecificFiles(dir1_label, dir1_path, ignoredSubFilePaths, false);
311assertErrnoEqual("Failed to validate if " + dir1_label + " directory file is empty with parent dir existing of non existing ignored regular file", FileUtilsErrno.ERRNO_NON_EMPTY_DIRECTORY_FILE, error);
312
313
314// Write "line1" to dir1/sub_dir3/sub_reg1 regular file
315label = dir1__sub_dir3__sub_reg1_label; path = dir1__sub_dir3__sub_reg1_path;
316error = FileUtils.writeTextToFile(label, path, Charset.defaultCharset(), "line1", false);
317assertEqual("Failed to write string to " + label + " file with append mode false", null, error);
318if (!FileUtils.regularFileExists(path, false))
319throwException("The " + label + " file does not exist as expected after writing to it with append mode false");
320
321// Test ignored regular file existing
322error = FileUtils.validateDirectoryFileEmptyOrOnlyContainsSpecificFiles(dir1_label, dir1_path, ignoredSubFilePaths, false);
323assertEqual("Failed to validate if " + dir1_label + " directory file is empty with ignored regular file existing", null, error);
324
325
326// Create dir1/sub_dir2 directory file
327label = dir1__sub_dir2_label; path = dir1__sub_dir2_path;
328error = FileUtils.createDirectoryFile(label, path);
329assertEqual("Failed to create " + label + " directory file", null, error);
330if (!FileUtils.directoryFileExists(path, false))
331throwException("The " + label + " directory file does not exist as expected after creation");
332
333// Test ignored dir file existing
334error = FileUtils.validateDirectoryFileEmptyOrOnlyContainsSpecificFiles(dir1_label, dir1_path, ignoredSubFilePaths, false);
335assertEqual("Failed to validate if " + dir1_label + " directory file is empty with ignored dir file existing", null, error);
336
337
338// Create dir1/sub_dir1 directory file
339label = dir1__sub_dir1_label; path = dir1__sub_dir1_path;
340error = FileUtils.createDirectoryFile(label, path);
341assertEqual("Failed to create " + label + " directory file", null, error);
342if (!FileUtils.directoryFileExists(path, false))
343throwException("The " + label + " directory file does not exist as expected after creation");
344
345// Test non ignored dir file existing
346error = FileUtils.validateDirectoryFileEmptyOrOnlyContainsSpecificFiles(dir1_label, dir1_path, ignoredSubFilePaths, false);
347assertErrnoEqual("Failed to validate if " + dir1_label + " directory file is empty with non ignored dir file existing", FileUtilsErrno.ERRNO_NON_EMPTY_DIRECTORY_FILE, error);
348
349
350// Delete dir1 directory file
351label = dir1_label; path = dir1_path;
352error = FileUtils.deleteDirectoryFile(label, path, false);
353assertEqual("Failed to delete " + label + " directory file", null, error);
354
355
356FileUtils.getFileType("/dev/ptmx", false);
357FileUtils.getFileType("/dev/null", false);
358}
359
360
361
362public static void assertEqual(@NonNull final String message, final String expected, final Error actual) throws Exception {
363String actualString = actual != null ? actual.getMessage() : null;
364if (!equalsRegardingNull(expected, actualString))
365throwException(message + "\nexpected: \"" + expected + "\"\nactual: \"" + actualString + "\"\nFull Error:\n" + (actual != null ? actual.toString() : ""));
366}
367
368public static void assertEqual(@NonNull final String message, final String expected, final String actual) throws Exception {
369if (!equalsRegardingNull(expected, actual))
370throwException(message + "\nexpected: \"" + expected + "\"\nactual: \"" + actual + "\"");
371}
372
373private static boolean equalsRegardingNull(final String expected, final String actual) {
374if (expected == null) {
375return actual == null;
376}
377
378return isEquals(expected, actual);
379}
380
381public static void assertErrnoEqual(@NonNull final String message, final Errno expected, final Error actual) throws Exception {
382if ((expected == null && actual != null) || (expected != null && !expected.equalsErrorTypeAndCode(actual)))
383throwException(message + "\nexpected: \"" + expected + "\"\nactual: \"" + actual + "\"\nFull Error:\n" + (actual != null ? actual.toString() : ""));
384}
385
386
387
388private static boolean isEquals(String expected, String actual) {
389return expected.equals(actual);
390}
391
392public static void throwException(@NonNull final String message) throws Exception {
393throw new Exception(message);
394}
395
396}
397