From 8771d551a4e6fa2d645e519d504a377e34cbd730 Mon Sep 17 00:00:00 2001 From: Dmitry Isaenko Date: Tue, 27 Oct 2020 00:22:26 +0300 Subject: [PATCH] Fix split-files validation. Add JUnit5 dependency on testing stage. --- Jenkinsfile | 7 +- pom.xml | 19 ++ .../COM/NET/NetworkSetupValidator.java | 11 +- .../nsusbloader/COM/USB/TransferModule.java | 58 +++-- src/main/java/nsusbloader/FilesHelper.java | 8 +- src/main/java/nsusbloader/RainbowHexDump.java | 12 +- .../COM/USB/TransferModuleTest.java | 227 ++++++++++++++++++ 7 files changed, 305 insertions(+), 37 deletions(-) create mode 100644 src/test/java/nsusbloader/COM/USB/TransferModuleTest.java diff --git a/Jenkinsfile b/Jenkinsfile index e85efc8..bf047ac 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -7,9 +7,14 @@ pipeline { } stages { + stage('Test') { + steps { + sh 'mvn test' + } + } stage('Build') { steps { - sh 'mvn -B -DskipTests clean package' + sh 'mvn clean package' } } } diff --git a/pom.xml b/pom.xml index a0b0b52..2b96fe1 100644 --- a/pom.xml +++ b/pom.xml @@ -150,6 +150,25 @@ 1.3.0 compile + + + org.junit.jupiter + junit-jupiter-engine + 5.5.2 + test + + + org.junit.jupiter + junit-jupiter-api + 5.5.2 + test + + + org.junit.jupiter + junit-jupiter-params + 5.5.2 + test + diff --git a/src/main/java/nsusbloader/COM/NET/NetworkSetupValidator.java b/src/main/java/nsusbloader/COM/NET/NetworkSetupValidator.java index b46b418..009cd74 100644 --- a/src/main/java/nsusbloader/COM/NET/NetworkSetupValidator.java +++ b/src/main/java/nsusbloader/COM/NET/NetworkSetupValidator.java @@ -77,12 +77,21 @@ public class NetworkSetupValidator { Arrays.sort(subFiles, Comparator.comparingInt(file -> Integer.parseInt(file.getName()))); for (int i = subFiles.length - 2; i > 0 ; i--){ - if (subFiles[i].length() < subFiles[i-1].length()) { + if (subFiles[i].length() != subFiles[i-1].length()) { logPrinter.print("NET: Exclude split file: "+f.getName()+ "\n Chunk sizes of the split file are not the same, but has to be.", EMsgType.WARNING); return true; } } + + long firstFileLength = subFiles[0].length(); + long lastFileLength = subFiles[subFiles.length-1].length(); + + if (lastFileLength > firstFileLength){ + logPrinter.print("NET: Exclude split file: "+f.getName()+ + "\n Chunk sizes of the split file are not the same, but has to be.", EMsgType.WARNING); + return true; + } return false; }); } diff --git a/src/main/java/nsusbloader/COM/USB/TransferModule.java b/src/main/java/nsusbloader/COM/USB/TransferModule.java index f7a734b..02dd059 100644 --- a/src/main/java/nsusbloader/COM/USB/TransferModule.java +++ b/src/main/java/nsusbloader/COM/USB/TransferModule.java @@ -41,32 +41,40 @@ public abstract class TransferModule { this.task = task; this.logPrinter = printer; - // Validate split files to be sure that there is no crap - //logPrinter.print("TransferModule: Validating split files ...", EMsgType.INFO); // NOTE: Used for debug - Iterator> iterator = nspMap.entrySet().iterator(); - while (iterator.hasNext()){ - File f = iterator.next().getValue(); - if (f.isDirectory()){ - File[] subFiles = f.listFiles((file, name) -> name.matches("[0-9]{2}")); - if (subFiles == null || subFiles.length == 0) { - logPrinter.print("TransferModule: Removing empty folder: " + f.getName(), EMsgType.WARNING); - iterator.remove(); - } - else { - Arrays.sort(subFiles, Comparator.comparingInt(file -> Integer.parseInt(file.getName()))); - - for (int i = subFiles.length - 2; i > 0 ; i--){ - if (subFiles[i].length() < subFiles[i-1].length()) { - logPrinter.print("TransferModule: Removing strange split file: "+f.getName()+ - "\n (Chunk sizes of the split file are not the same, but has to be.)", EMsgType.WARNING); - iterator.remove(); - } // what - } // a - } // nice - } // stairway - } // here =) - //logPrinter.print("TransferModule: Validation complete.", EMsgType.INFO); // NOTE: Used for debug + filterFiles(); } + void filterFiles(){ + nspMap.values().removeIf(f -> { + if (f.isFile()) + return false; + File[] subFiles = f.listFiles((file, name) -> name.matches("[0-9]{2}")); + + if (subFiles == null || subFiles.length == 0) { + logPrinter.print("TransferModule: Exclude folder: " + f.getName(), EMsgType.WARNING); + return true; + } + + Arrays.sort(subFiles, Comparator.comparingInt(file -> Integer.parseInt(file.getName()))); + + for (int i = subFiles.length - 2; i > 0 ; i--){ + if (subFiles[i].length() != subFiles[i-1].length()) { + logPrinter.print("TransferModule: Exclude split file: "+f.getName()+ + "\n Chunk sizes of the split file are not the same, but has to be.", EMsgType.WARNING); + return true; + } + } + + long firstFileLength = subFiles[0].length(); + long lastFileLength = subFiles[subFiles.length-1].length(); + + if (lastFileLength > firstFileLength){ + logPrinter.print("TransferModule: Exclude split file: "+f.getName()+ + "\n Chunk sizes of the split file are not the same, but has to be.", EMsgType.WARNING); + return true; + } + return false; + }); + } public EFileStatus getStatus(){ return status; } } diff --git a/src/main/java/nsusbloader/FilesHelper.java b/src/main/java/nsusbloader/FilesHelper.java index 5267ada..7988a06 100644 --- a/src/main/java/nsusbloader/FilesHelper.java +++ b/src/main/java/nsusbloader/FilesHelper.java @@ -23,10 +23,10 @@ import java.nio.file.Path; import java.nio.file.Paths; public class FilesHelper { - public static String getRealFolder(String path){ - Path splitMergePath = Paths.get(path); - if (Files.notExists(splitMergePath) || Files.isRegularFile(splitMergePath)) + public static String getRealFolder(String location){ + Path locationAsPath = Paths.get(location); + if (Files.notExists(locationAsPath) || Files.isRegularFile(locationAsPath)) return System.getProperty("user.home"); - return path; + return location; } } diff --git a/src/main/java/nsusbloader/RainbowHexDump.java b/src/main/java/nsusbloader/RainbowHexDump.java index ebdd277..109957d 100644 --- a/src/main/java/nsusbloader/RainbowHexDump.java +++ b/src/main/java/nsusbloader/RainbowHexDump.java @@ -37,10 +37,10 @@ public class RainbowHexDump { public static void hexDumpUTF8(byte[] byteArray){ System.out.print(ANSI_BLUE); for (int i=0; i < byteArray.length; i++) - System.out.print(String.format("%02d-", i%100)); + System.out.printf("%02d-", i%100); System.out.println(">"+ANSI_RED+byteArray.length+ANSI_RESET); for (byte b: byteArray) - System.out.print(String.format("%02x ", b)); + System.out.printf("%02x ", b); System.out.println(); System.out.print("\t\t\t" + new String(byteArray, StandardCharsets.UTF_8) @@ -49,10 +49,10 @@ public class RainbowHexDump { public static void hexDumpUTF8ForWin(byte[] byteArray){ for (int i=0; i < byteArray.length; i++) - System.out.print(String.format("%02d-", i%100)); + System.out.printf("%02d-", i%100); System.out.println(">"+byteArray.length); for (byte b: byteArray) - System.out.print(String.format("%02x ", b)); + System.out.printf("%02x ", b); System.out.println(); System.out.print(new String(byteArray, StandardCharsets.UTF_8) + "\n"); @@ -61,10 +61,10 @@ public class RainbowHexDump { public static void hexDumpUTF16LE(byte[] byteArray){ System.out.print(ANSI_BLUE); for (int i=0; i < byteArray.length; i++) - System.out.print(String.format("%02d-", i%100)); + System.out.printf("%02d-", i%100); System.out.println(">"+ANSI_RED+byteArray.length+ANSI_RESET); for (byte b: byteArray) - System.out.print(String.format("%02x ", b)); + System.out.printf("%02x ", b); System.out.print(new String(byteArray, StandardCharsets.UTF_16LE) + "\n"); } diff --git a/src/test/java/nsusbloader/COM/USB/TransferModuleTest.java b/src/test/java/nsusbloader/COM/USB/TransferModuleTest.java new file mode 100644 index 0000000..12acb65 --- /dev/null +++ b/src/test/java/nsusbloader/COM/USB/TransferModuleTest.java @@ -0,0 +1,227 @@ +package nsusbloader.COM.USB; + +import nsusbloader.ModelControllers.CancellableRunnable; +import nsusbloader.ModelControllers.ILogPrinter; +import nsusbloader.ModelControllers.LogPrinterCli; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.io.TempDir; +import org.usb4java.DeviceHandle; + +import java.io.File; +import java.io.FileWriter; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.LinkedHashMap; + +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertTrue; + +class TransferModuleTest{ + + @TempDir + File testFilesLocation; + + final String regularFileName1 = "file1.nsp"; + final String regularFileName2 = "file2.nsz"; + final String regularFileName3 = "file3.xci"; + final String regularFileName4 = "file4.xcz"; + final String splitFileName1 = "splitFile1.nsp"; + final String splitFileName2 = "splitFile2.nsp"; + final String splitFileName3 = "splitFile3.nsp"; + final String splitFileName4 = "splitFile4.nsp"; + final String splitFileName5 = "splitFile5.nsp"; + final String splitFileName6 = "splitFile6.nsp"; + final String splitFileName7 = "splitFile7.nsp"; + final String splitFileName8 = "splitFile8.nsp"; + final String splitFileName9 = "splitFile9.nsp"; + final String splitFileName10 = "splitFile10.nsp"; + final String splitFileName11 = "splitFile11.nsp"; + + TransferModuleImplementation transferModule; + + @BeforeEach + void createFiles() throws Exception{ + String parentTempDirectory = testFilesLocation.getAbsolutePath(); + + File regularFile1 = createFile(parentTempDirectory, regularFileName1); + File regularFile2 = createFile(parentTempDirectory, regularFileName2); + File regularFile3 = createFile(parentTempDirectory, regularFileName3); + File regularFile4 = createFile(parentTempDirectory, regularFileName4); + File splitFile1 = createSplitInvalidEmpty(parentTempDirectory, splitFileName1); + File splitFile2 = createSplitInvalidEmpty(parentTempDirectory, splitFileName2); + File splitFile3 = createSplitValid(parentTempDirectory, splitFileName3); + File splitFile4 = createSplitValid(parentTempDirectory, splitFileName4); + File splitFile5 = createSplitValidWithExtras(parentTempDirectory, splitFileName5); + File splitFile6 = createSplitInvalidVariant1(parentTempDirectory, splitFileName6); + File splitFile7 = createSplitInvalidVariant2(parentTempDirectory, splitFileName7); + File splitFile8 = createSplitInvalidVariant3(parentTempDirectory, splitFileName8); + File splitFile9 = createSplitInvalidVariant4(parentTempDirectory, splitFileName9); + File splitFile10 = createSplitInvalidVariant5(parentTempDirectory, splitFileName10); + File splitFile11 = createSplitValidSingleChunk(parentTempDirectory, splitFileName11); + + + LinkedHashMap filesMap = new LinkedHashMap<>(); + + filesMap.put(regularFileName1, regularFile1); + filesMap.put(regularFileName2, regularFile2); + filesMap.put(regularFileName3, regularFile3); + filesMap.put(regularFileName4, regularFile4); + filesMap.put(splitFileName1, splitFile1); + filesMap.put(splitFileName2, splitFile2); + filesMap.put(splitFileName3, splitFile3); + filesMap.put(splitFileName4, splitFile4); + filesMap.put(splitFileName5, splitFile5); + filesMap.put(splitFileName6, splitFile6); + filesMap.put(splitFileName7, splitFile7); + filesMap.put(splitFileName8, splitFile8); + filesMap.put(splitFileName9, splitFile9); + filesMap.put(splitFileName10, splitFile10); + filesMap.put(splitFileName11, splitFile11); + + ILogPrinter printer = new LogPrinterCli(); + this.transferModule = new TransferModuleImplementation((DeviceHandle)null, filesMap, (CancellableRunnable)null, printer); + } + + File createFile(String parent, String name) throws Exception{ + Path file = Paths.get(parent, name); + Files.createFile(file); + return new File(parent, name); + } + + File createSplitInvalidEmpty(String parent, String name) throws Exception{ + Path file = Paths.get(parent, name); + Files.createDirectory(file); + return new File(parent, name); + } + + File createSplitValid(String parent, String name) throws Exception{ + Path path = Paths.get(parent, name); + Files.createDirectory(path); + makeSplitFileEntryBigger(path, 0); + makeSplitFileEntryBigger(path, 1); + makeSplitFileEntryBigger(path, 2); + makeSplitFileEntryBigger(path, 3); + makeSplitFileEntrySmaller(path, 4); + return new File(parent, name); + } + + File createSplitValidWithExtras(String parent, String name) throws Exception{ + Path path = Paths.get(parent, name); + Files.createDirectory(path); + makeSplitFileEntrySmaller(path, 0); + makeSplitFileEntrySmaller(path, 1); + makeSplitFileEntrySmaller(path, 2); + makeSplitFileEntryWeired(path); + return new File(parent, name); + } + + File createSplitInvalidVariant1(String parent, String name) throws Exception{ + Path path = Paths.get(parent, name); + Files.createDirectory(path); + makeSplitFileEntrySmaller(path, 0); + makeSplitFileEntrySmaller(path, 1); + makeSplitFileEntryBigger(path, 2); //incorrect + makeSplitFileEntrySmaller(path, 3); + return new File(parent, name); + } + File createSplitInvalidVariant2(String parent, String name) throws Exception{ + Path path = Paths.get(parent, name); + Files.createDirectory(path); + makeSplitFileEntryBigger(path, 0); //incorrect + makeSplitFileEntrySmaller(path, 1); + makeSplitFileEntrySmaller(path, 2); + makeSplitFileEntrySmaller(path, 3); + return new File(parent, name); + } + File createSplitInvalidVariant3(String parent, String name) throws Exception{ + Path path = Paths.get(parent, name); + Files.createDirectory(path); + makeSplitFileEntrySmaller(path, 0); + makeSplitFileEntryBigger(path, 1); //incorrect + makeSplitFileEntrySmaller(path, 2); + makeSplitFileEntrySmaller(path, 3); + return new File(parent, name); + } + File createSplitInvalidVariant4(String parent, String name) throws Exception{ + Path path = Paths.get(parent, name); + Files.createDirectory(path); + makeSplitFileEntrySmaller(path, 0); //incorrect + makeSplitFileEntryBigger(path, 1); + makeSplitFileEntryBigger(path, 2); + makeSplitFileEntryBigger(path, 3); + return new File(parent, name); + } + File createSplitInvalidVariant5(String parent, String name) throws Exception{ + Path path = Paths.get(parent, name); + Files.createDirectory(path); + makeSplitFileEntrySmaller(path, 0); + makeSplitFileEntrySmaller(path, 1); + makeSplitFileEntrySmaller(path, 2); + makeSplitFileEntryBigger(path, 3); //incorrect: Could be only smaller + return new File(parent, name); + } + + File createSplitValidSingleChunk(String parent, String name) throws Exception{ + Path path = Paths.get(parent, name); + Files.createDirectory(path); + makeSplitFileEntryBigger(path, 0); + return new File(parent, name); + } + + void makeSplitFileEntrySmaller(Path path, int entryNum) throws Exception{ + try (FileWriter writer = new FileWriter(String.format("%s%s%02x", path.toString(), File.separator, entryNum))){ + writer.write("test"); + writer.flush(); + } + } + void makeSplitFileEntryBigger(Path path, int entryNum) throws Exception{ + try (FileWriter writer = new FileWriter(String.format("%s%s%02x", path.toString(), File.separator, entryNum))){ + writer.write("test_"); + writer.flush(); + } + } + void makeSplitFileEntryWeired(Path path) throws Exception{ + try (FileWriter writer = new FileWriter(String.format("%s%sNOT_A_VALID_FILE.nsp", path.toString(), File.separator))){ + writer.write("literally anything"); + writer.flush(); + } + } + + private static class TransferModuleImplementation extends TransferModule{ + TransferModuleImplementation(DeviceHandle handler, + LinkedHashMap nspMap, + CancellableRunnable task, + ILogPrinter printer) + { + super(handler, nspMap, task, printer); + } + + LinkedHashMap getFiles(){ return nspMap; } + } + + @DisplayName("Test 'split-files' filter-validator") + @Test + void validateTransferModule() { + LinkedHashMap files = transferModule.getFiles(); + + assertTrue(files.containsKey(regularFileName1)); + assertTrue(files.containsKey(regularFileName2)); + assertTrue(files.containsKey(regularFileName3)); + assertTrue(files.containsKey(regularFileName4)); + assertFalse(files.containsKey(splitFileName1)); + assertFalse(files.containsKey(splitFileName1)); + assertFalse(files.containsKey(splitFileName2)); + assertTrue(files.containsKey(splitFileName3)); + assertTrue(files.containsKey(splitFileName4)); + assertTrue(files.containsKey(splitFileName5)); + assertFalse(files.containsKey(splitFileName6)); + assertFalse(files.containsKey(splitFileName7)); + assertFalse(files.containsKey(splitFileName8)); + assertFalse(files.containsKey(splitFileName9)); + assertFalse(files.containsKey(splitFileName10)); + assertTrue(files.containsKey(splitFileName11)); + } +} \ No newline at end of file