Implement Errno system

This commit adds onto 679e0de0

If an exception is thrown, the exception message might not contain the full errors. Individual failures may get added to suppressed throwables. FileUtils functions previously just returned the exception message as errmsg which did not contain full error info.

Now `Error` class has been implemented which will used to return errors, including suppressed throwables. Each `Error` object will have an error type, code, message and a list of throwables in case multiple throwables need to returned, in addition to the suppressed throwables list in each throwable.

A supportive `Errno` base class has been implemented as well which other errno classes can inherit of which some have been added. Each `Errno` object will have an error type, code and message and can be converted to an `Error` object if needed.

Requirement for `Context` object has been removed from FileUtils so that they can be called from anywhere in code instead of having to pass around `Context` objects. Previously, `string.xml` was used to store error messages in case multi language support had to be added in future since error messages are displayed to users and not just for dev usage. However, now this will have to handled in java code if needed, based on locale.

The termux related file utils have also been moved from FileUtils to TermuxFileUtils
This commit is contained in:
agnostic-apollo
2021-06-26 07:23:34 +05:00
parent 679e0de044
commit 4494bc66e4
13 changed files with 905 additions and 434 deletions

View File

@@ -6,6 +6,7 @@ import androidx.annotation.NonNull;
import com.termux.shared.file.FileUtils;
import com.termux.shared.logger.Logger;
import com.termux.shared.models.errors.Error;
import java.io.File;
import java.nio.charset.Charset;
@@ -31,18 +32,19 @@ public class FileUtilsTests {
Logger.logInfo(LOG_TAG, "Running tests");
Logger.logInfo(LOG_TAG, "testRootDirectoryPath: \"" + testRootDirectoryPath + "\"");
String fileUtilsTestsDirectoryCanonicalPath = FileUtils.getCanonicalPath(testRootDirectoryPath, null, false);
String fileUtilsTestsDirectoryCanonicalPath = FileUtils.getCanonicalPath(testRootDirectoryPath, null);
assertEqual("FileUtilsTests directory path is not a canonical path", testRootDirectoryPath, fileUtilsTestsDirectoryCanonicalPath);
runTestsInner(context, testRootDirectoryPath);
runTestsInner(testRootDirectoryPath);
Logger.logInfo(LOG_TAG, "All tests successful");
} catch (Exception e) {
Logger.logErrorAndShowToast(context, LOG_TAG, e.getMessage());
Logger.logErrorExtended(LOG_TAG, e.getMessage());
Logger.showToast(context, e.getMessage() != null ? e.getMessage().replaceAll("(?s)\nFull Error:\n.*", "") : null, true);
}
}
private static void runTestsInner(@NonNull final Context context, @NonNull final String testRootDirectoryPath) throws Exception {
String errmsg;
private static void runTestsInner(@NonNull final String testRootDirectoryPath) throws Exception {
Error error;
String label;
String path;
@@ -101,20 +103,20 @@ public class FileUtilsTests {
// Create or clear test root directory file
label = "testRootDirectoryPath";
errmsg = FileUtils.clearDirectory(context, label, testRootDirectoryPath);
assertEqual("Failed to create " + label + " directory file", null, errmsg);
error = FileUtils.clearDirectory(label, testRootDirectoryPath);
assertEqual("Failed to create " + label + " directory file", null, error);
if (!FileUtils.directoryFileExists(testRootDirectoryPath, false))
throwException("The " + label + " directory file does not exist as expected after creation");
// Create dir1 directory file
errmsg = FileUtils.createDirectoryFile(context, dir1_label, dir1_path);
assertEqual("Failed to create " + dir1_label + " directory file", null, errmsg);
error = FileUtils.createDirectoryFile(dir1_label, dir1_path);
assertEqual("Failed to create " + dir1_label + " directory file", null, error);
// Create dir2 directory file
errmsg = FileUtils.createDirectoryFile(context, dir2_label, dir2_path);
assertEqual("Failed to create " + dir2_label + " directory file", null, errmsg);
error = FileUtils.createDirectoryFile(dir2_label, dir2_path);
assertEqual("Failed to create " + dir2_label + " directory file", null, error);
@@ -122,29 +124,29 @@ public class FileUtilsTests {
// Create dir1/sub_dir1 directory file
label = dir1__sub_dir1_label; path = dir1__sub_dir1_path;
errmsg = FileUtils.createDirectoryFile(context, label, path);
assertEqual("Failed to create " + label + " directory file", null, errmsg);
error = FileUtils.createDirectoryFile(label, path);
assertEqual("Failed to create " + label + " directory file", null, error);
if (!FileUtils.directoryFileExists(path, false))
throwException("The " + label + " directory file does not exist as expected after creation");
// Create dir1/sub_reg1 regular file
label = dir1__sub_reg1_label; path = dir1__sub_reg1_path;
errmsg = FileUtils.createRegularFile(context, label, path);
assertEqual("Failed to create " + label + " regular file", null, errmsg);
error = FileUtils.createRegularFile(label, path);
assertEqual("Failed to create " + label + " regular file", null, error);
if (!FileUtils.regularFileExists(path, false))
throwException("The " + label + " regular file does not exist as expected after creation");
// Create dir1/sub_sym1 -> dir2 absolute symlink file
label = dir1__sub_sym1_label; path = dir1__sub_sym1_path;
errmsg = FileUtils.createSymlinkFile(context, label, dir2_path, path);
assertEqual("Failed to create " + label + " symlink file", null, errmsg);
error = FileUtils.createSymlinkFile(label, dir2_path, path);
assertEqual("Failed to create " + label + " symlink file", null, error);
if (!FileUtils.symlinkFileExists(path))
throwException("The " + label + " symlink file does not exist as expected after creation");
// Copy dir1/sub_sym1 symlink file to dir1/sub_sym2
label = dir1__sub_sym2_label; path = dir1__sub_sym2_path;
errmsg = FileUtils.copySymlinkFile(context, label, dir1__sub_sym1_path, path, false);
assertEqual("Failed to copy " + dir1__sub_sym1_label + " symlink file to " + label, null, errmsg);
error = FileUtils.copySymlinkFile(label, dir1__sub_sym1_path, path, false);
assertEqual("Failed to copy " + dir1__sub_sym1_label + " symlink file to " + label, null, error);
if (!FileUtils.symlinkFileExists(path))
throwException("The " + label + " symlink file does not exist as expected after copying it from " + dir1__sub_sym1_label);
if (!new File(path).getCanonicalPath().equals(dir2_path))
@@ -156,25 +158,25 @@ public class FileUtilsTests {
// Write "line1" to dir2/sub_reg1 regular file
label = dir2__sub_reg1_label; path = dir2__sub_reg1_path;
errmsg = FileUtils.writeStringToFile(context, label, path, Charset.defaultCharset(), "line1", false);
assertEqual("Failed to write string to " + label + " file with append mode false", null, errmsg);
error = FileUtils.writeStringToFile(label, path, Charset.defaultCharset(), "line1", false);
assertEqual("Failed to write string to " + label + " file with append mode false", null, error);
if (!FileUtils.regularFileExists(path, false))
throwException("The " + label + " file does not exist as expected after writing to it with append mode false");
// Write "line2" to dir2/sub_reg1 regular file
errmsg = FileUtils.writeStringToFile(context, label, path, Charset.defaultCharset(), "\nline2", true);
assertEqual("Failed to write string to " + label + " file with append mode true", null, errmsg);
error = FileUtils.writeStringToFile(label, path, Charset.defaultCharset(), "\nline2", true);
assertEqual("Failed to write string to " + label + " file with append mode true", null, error);
// Read dir2/sub_reg1 regular file
StringBuilder dataStringBuilder = new StringBuilder();
errmsg = FileUtils.readStringFromFile(context, label, path, Charset.defaultCharset(), dataStringBuilder, false);
assertEqual("Failed to read from " + label + " file", null, errmsg);
error = FileUtils.readStringFromFile(label, path, Charset.defaultCharset(), dataStringBuilder, false);
assertEqual("Failed to read from " + label + " file", null, error);
assertEqual("The data read from " + label + " file in not as expected", "line1\nline2", dataStringBuilder.toString());
// Copy dir2/sub_reg1 regular file to dir2/sub_reg2 file
label = dir2__sub_reg2_label; path = dir2__sub_reg2_path;
errmsg = FileUtils.copyRegularFile(context, label, dir2__sub_reg1_path, path, false);
assertEqual("Failed to copy " + dir2__sub_reg1_label + " regular file to " + label, null, errmsg);
error = FileUtils.copyRegularFile(label, dir2__sub_reg1_path, path, false);
assertEqual("Failed to copy " + dir2__sub_reg1_label + " regular file to " + label, null, error);
if (!FileUtils.regularFileExists(path, false))
throwException("The " + label + " regular file does not exist as expected after copying it from " + dir2__sub_reg1_label);
@@ -184,22 +186,22 @@ public class FileUtilsTests {
// Copy dir1 directory file to dir3
label = dir3_label; path = dir3_path;
errmsg = FileUtils.copyDirectoryFile(context, label, dir2_path, path, false);
assertEqual("Failed to copy " + dir2_label + " directory file to " + label, null, errmsg);
error = FileUtils.copyDirectoryFile(label, dir2_path, path, false);
assertEqual("Failed to copy " + dir2_label + " directory file to " + label, null, error);
if (!FileUtils.directoryFileExists(path, false))
throwException("The " + label + " directory file does not exist as expected after copying it from " + dir2_label);
// Copy dir1 directory file to dir3 again to test overwrite
label = dir3_label; path = dir3_path;
errmsg = FileUtils.copyDirectoryFile(context, label, dir2_path, path, false);
assertEqual("Failed to copy " + dir2_label + " directory file to " + label, null, errmsg);
error = FileUtils.copyDirectoryFile(label, dir2_path, path, false);
assertEqual("Failed to copy " + dir2_label + " directory file to " + label, null, error);
if (!FileUtils.directoryFileExists(path, false))
throwException("The " + label + " directory file does not exist as expected after copying it from " + dir2_label);
// Move dir3 directory file to dir4
label = dir4_label; path = dir4_path;
errmsg = FileUtils.moveDirectoryFile(context, label, dir3_path, path, false);
assertEqual("Failed to move " + dir3_label + " directory file to " + label, null, errmsg);
error = FileUtils.moveDirectoryFile(label, dir3_path, path, false);
assertEqual("Failed to move " + dir3_label + " directory file to " + label, null, error);
if (!FileUtils.directoryFileExists(path, false))
throwException("The " + label + " directory file does not exist as expected after copying it from " + dir3_label);
@@ -209,16 +211,16 @@ public class FileUtilsTests {
// Create dir1/sub_sym3 -> dir4 relative symlink file
label = dir1__sub_sym3_label; path = dir1__sub_sym3_path;
errmsg = FileUtils.createSymlinkFile(context, label, "../dir4", path);
assertEqual("Failed to create " + label + " symlink file", null, errmsg);
error = FileUtils.createSymlinkFile(label, "../dir4", path);
assertEqual("Failed to create " + label + " symlink file", null, error);
if (!FileUtils.symlinkFileExists(path))
throwException("The " + label + " symlink file does not exist as expected after creation");
// Create dir1/sub_sym3 -> dirX relative dangling symlink file
// This is to ensure that symlinkFileExists returns true if a symlink file exists but is dangling
label = dir1__sub_sym3_label; path = dir1__sub_sym3_path;
errmsg = FileUtils.createSymlinkFile(context, label, "../dirX", path);
assertEqual("Failed to create " + label + " symlink file", null, errmsg);
error = FileUtils.createSymlinkFile(label, "../dirX", path);
assertEqual("Failed to create " + label + " symlink file", null, error);
if (!FileUtils.symlinkFileExists(path))
throwException("The " + label + " dangling symlink file does not exist as expected after creation");
@@ -228,8 +230,8 @@ public class FileUtilsTests {
// Delete dir1/sub_sym2 symlink file
label = dir1__sub_sym2_label; path = dir1__sub_sym2_path;
errmsg = FileUtils.deleteSymlinkFile(context, label, path, false);
assertEqual("Failed to delete " + label + " symlink file", null, errmsg);
error = FileUtils.deleteSymlinkFile(label, path, false);
assertEqual("Failed to delete " + label + " symlink file", null, error);
if (FileUtils.fileExists(path, false))
throwException("The " + label + " symlink file still exist after deletion");
@@ -245,8 +247,8 @@ public class FileUtilsTests {
// Delete dir1 directory file
label = dir1_label; path = dir1_path;
errmsg = FileUtils.deleteDirectoryFile(context, label, path, false);
assertEqual("Failed to delete " + label + " directory file", null, errmsg);
error = FileUtils.deleteDirectoryFile(label, path, false);
assertEqual("Failed to delete " + label + " directory file", null, error);
if (FileUtils.fileExists(path, false))
throwException("The " + label + " directory file still exist after deletion");
@@ -267,8 +269,8 @@ public class FileUtilsTests {
// Delete dir2/sub_reg1 regular file
label = dir2__sub_reg1_label; path = dir2__sub_reg1_path;
errmsg = FileUtils.deleteRegularFile(context, label, path, false);
assertEqual("Failed to delete " + label + " regular file", null, errmsg);
error = FileUtils.deleteRegularFile(label, path, false);
assertEqual("Failed to delete " + label + " regular file", null, error);
if (FileUtils.fileExists(path, false))
throwException("The " + label + " regular file still exist after deletion");
@@ -276,6 +278,14 @@ public class FileUtilsTests {
FileUtils.getFileType("/dev/null", false);
}
public static void assertEqual(@NonNull final String message, final String expected, final Error actual) throws Exception {
String actualString = actual != null ? actual.getMessage() : null;
if (!equalsRegardingNull(expected, actualString))
throwException(message + "\nexpected: \"" + expected + "\"\nactual: \"" + actualString + "\"\nFull Error:\n" + (actual != null ? actual.toString() : ""));
}
public static void assertEqual(@NonNull final String message, final String expected, final String actual) throws Exception {
if (!equalsRegardingNull(expected, actual))
throwException(message + "\nexpected: \"" + expected + "\"\nactual: \"" + actual + "\"");