diff options
Diffstat (limited to 'src/test/java/com')
6 files changed, 435 insertions, 0 deletions
diff --git a/src/test/java/com/keuin/kbackupfabric/operation/backup/method/ConfiguredIncrementalBackupMethodTest.java b/src/test/java/com/keuin/kbackupfabric/operation/backup/method/ConfiguredIncrementalBackupMethodTest.java new file mode 100644 index 0000000..30f2d44 --- /dev/null +++ b/src/test/java/com/keuin/kbackupfabric/operation/backup/method/ConfiguredIncrementalBackupMethodTest.java @@ -0,0 +1,213 @@ +package com.keuin.kbackupfabric.operation.backup.method; + +import org.apache.commons.codec.digest.DigestUtils; +import org.junit.Test; + +import java.io.*; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.*; +import java.util.function.Function; + +import static org.apache.commons.io.FileUtils.forceDelete; +import static org.junit.Assert.*; + +public class ConfiguredIncrementalBackupMethodTest { + + private final String testTempPath = (new File("R:\\").isDirectory()) ? "R:\\" : ".\\testfile\\ConfiguredIncrementalBackupMethodTest"; + private final String sourceDirectoryName = "source"; + private final String destDirectoryName = "destination"; + private final String indexFileName = "index"; + + private final double directoryFactor = 0.02; + private final double fileFactor = 0.05; + private final int maxRandomFileSizeBytes = 1024 * 1024 * 16; + private final Function<Integer, Integer> scaleDecayFunc = (x) -> x - 1; + + @Test + public void iterationTest() throws IOException { + int a = 12; + for (int i = 0; i < a; ++i) { + performTest(Math.min(i + 1, 10)); + System.out.println("Round " + i + " passed."); + } + } + + private void performTest(int scale) throws IOException { + + // init source and destination + final Path sourcePath = Paths.get(testTempPath, sourceDirectoryName); + final Path destPath = Paths.get(testTempPath, destDirectoryName); + if (new File(sourcePath.toString()).exists()) { + forceDelete(new File(sourcePath.toString())); + if (!new File(sourcePath.toString()).mkdirs()) + fail(); + } + if (new File(destPath.toString()).exists()) { + forceDelete(new File(destPath.toString())); + if (!new File(destPath.toString()).mkdirs()) + fail(); + } + if (new File(testTempPath, indexFileName).exists()) { + if (!new File(testTempPath, indexFileName).delete()) + fail(); + } + + // initialize src + createRandomDirectoryTree(sourcePath.toString(), scale); + + String hash1 = calcMD5HashForDir(sourcePath.toFile(), true); + + // copy src to dest + ConfiguredIncrementalBackupMethod method = new ConfiguredIncrementalBackupMethod( + indexFileName, + sourcePath.toString(), + testTempPath, + destPath.toString() + ); + method.backup(); + + // delete src + forceDelete(sourcePath.toFile()); + assertFalse(sourcePath.toFile().isDirectory()); + + // restore src + if (!method.restore()) + fail(); + + boolean fake = scale % 2 != 0; + + int[] success = new int[1]; + if (fake) { + Files.walk(sourcePath).filter(path -> path.toFile().isFile()).limit(3).forEach(path -> { + if (!path.toFile().delete()) + fail(); + success[0]++; + }); + if (success[0] == 0) + fake = false; + } + + if (fake) + System.out.println("Fake: deleted " + success[0] + " file(s)."); + + String hash2 = calcMD5HashForDir(sourcePath.toFile(), true); + + if (!fake) + assertEquals(hash1, hash2); + else + assertNotEquals(hash1, hash2); + } + + private void createRandomDirectoryTree(String path, int scale) throws IOException { + if (scale <= 0) { + if (Math.random() < 0.5) + if (!new File(path).mkdirs() && !new File(path).exists()) + throw new IOException("Failed to create directory " + path); + return; + } + if (!new File(path).isDirectory() && !new File(path).mkdirs()) + throw new IOException("Failed to create directory " + path); + + int subFileCount = (int) Math.round(Math.random() * 10 * scale * fileFactor); + for (int i = 0; i < subFileCount; i++) { + String subFile = null; + while (subFile == null || new File(path, subFile).exists()) + subFile = getRandomString((int) (Math.random() * 16 + 5)); + createRandomFile(new File(path, subFile), maxRandomFileSizeBytes); + } + + + int subDirCount = (int) Math.round(Math.random() * 10 * scale * directoryFactor); + for (int i = 0; i < subDirCount; i++) { + String subDir = null; + while (subDir == null || new File(path, subDir).exists()) + subDir = getRandomString((int) (Math.random() * 16 + 5)); + createRandomDirectoryTree(new File(path, subDir).getAbsolutePath(), scaleDecayFunc.apply(scale)); + } + } + + private static void createRandomFile(File file, int maxSizeBytes) throws IOException { + if (!file.createNewFile()) + throw new IOException("Failed to create file " + file.getAbsolutePath()); + try (FileOutputStream fileOutputStream = new FileOutputStream(file)) { + int fileBytes = (int) (maxSizeBytes * Math.random() + 1); + Random random = new Random(); + final int chunkSize = 1024 * 4; + byte[] randomChunk = new byte[chunkSize]; + for (int i = 0; i < fileBytes / chunkSize; i++) { + random.nextBytes(randomChunk); + fileOutputStream.write(randomChunk); + } + if (fileBytes % chunkSize != 0) { + randomChunk = new byte[fileBytes % chunkSize]; + random.nextBytes(randomChunk); + fileOutputStream.write(randomChunk); + } + } + } + + private static String getRandomString(int length) { + String str = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"; + Random random = new Random(); + StringBuilder sb = new StringBuilder(); + for (int i = 0; i < length; i++) { + int number = random.nextInt(62); + sb.append(str.charAt(number)); + } + return sb.toString(); + } + + public String calcMD5HashForDir(File dirToHash, boolean includeHiddenFiles) { + + assert (dirToHash.isDirectory()); + Vector<FileInputStream> fileStreams = new Vector<>(); + + System.out.println("Found files for hashing:"); + collectInputStreams(dirToHash, fileStreams, includeHiddenFiles); + + SequenceInputStream seqStream = + new SequenceInputStream(fileStreams.elements()); + + try { + String md5Hash = DigestUtils.md5Hex(seqStream); + seqStream.close(); + return md5Hash; + } catch (IOException e) { + throw new RuntimeException("Error reading files to hash in " + + dirToHash.getAbsolutePath(), e); + } + + } + + private void collectInputStreams(File dir, + List<FileInputStream> foundStreams, + boolean includeHiddenFiles) { + + File[] fileList = dir.listFiles(); + Arrays.sort(fileList, // Need in reproducible order + new Comparator<File>() { + public int compare(File f1, File f2) { + return f1.getName().compareTo(f2.getName()); + } + }); + + for (File f : fileList) { + if (!includeHiddenFiles && f.getName().startsWith(".")) { + // Skip it + } else if (f.isDirectory()) { + collectInputStreams(f, foundStreams, includeHiddenFiles); + } else { + try { + System.out.println("\t" + f.getAbsolutePath()); + foundStreams.add(new FileInputStream(f)); + } catch (FileNotFoundException e) { + throw new AssertionError(e.getMessage() + + ": file should never not be found!"); + } + } + } + + } +}
\ No newline at end of file diff --git a/src/test/java/com/keuin/kbackupfabric/util/backup/incremental/ObjectCollectionFactoryTest.java b/src/test/java/com/keuin/kbackupfabric/util/backup/incremental/ObjectCollectionFactoryTest.java new file mode 100644 index 0000000..3f722a4 --- /dev/null +++ b/src/test/java/com/keuin/kbackupfabric/util/backup/incremental/ObjectCollectionFactoryTest.java @@ -0,0 +1,80 @@ +package com.keuin.kbackupfabric.util.backup.incremental; + +import com.keuin.kbackupfabric.util.backup.incremental.identifier.Sha256Identifier; +import org.junit.Test; + +import java.io.File; +import java.io.IOException; +import java.util.*; + +import static org.junit.Assert.*; + +public class ObjectCollectionFactoryTest { + + private void validate(ObjectCollection collection, List<String> subCollections, Map<String, String> subElements) { + assertEquals(subCollections.size(), collection.getSubCollectionMap().size()); + assertEquals(subElements.size(), collection.getElementSet().size()); + for (Map.Entry<String, ObjectCollection> c : collection.getSubCollectionMap().entrySet()) { + assertEquals(c.getKey(), c.getValue().getName()); + assertTrue(subCollections.contains(c.getKey())); + } + for (Map.Entry<String, ObjectElement> entry : collection.getElementMap().entrySet()) { +// assertTrue(subElements.contains(e.getIdentification())); + assertEquals(subElements.get(entry.getKey()).toUpperCase(), entry.getValue().getIdentifier().getIdentification().toUpperCase()); + } + } + + @Test + public void fromDirectory() { + try { + ObjectCollectionFactory<Sha256Identifier> factory = + new ObjectCollectionFactory<>(Sha256Identifier.getFactory()); + ObjectCollection collection = + factory.fromDirectory(new File("./testfile/ObjectCollectionFactoryTest")); + + assertEquals("ObjectCollectionFactoryTest", collection.getName()); + assertEquals(3, collection.getSubCollectionMap().size()); + assertEquals(2, collection.getElementSet().size()); + + final Map<String, String> elements = new HashMap<>(); + + // check root dir + elements.put("a", "S2-261CA0D59FEE8FD169802BB8030A07CF23E5C1593FA81A16C6D0A8CF27DAA2ED"); + elements.put("b", "S2-B3FED75012C4969DC63A50EBC4E745FF77E4A06E0B04720EF71EF033032EBAF7"); + validate(collection, Arrays.asList("1", "2", "3"), elements); + elements.clear(); + + // check `1` + elements.put("a", "S2-E8620F35A5DB33B1257CC51245DDACDA8AF3E0D431A8A38473575E468BCBD0BD"); + elements.put("b", "S2-19EE41585A674274891DE5A4B365DBAB9C49C576AB6F86CD515B683724D2DBBD"); + validate(collection.getSubCollectionMap().get("1"), Arrays.asList("11", "12"), elements); + elements.clear(); + + // check `2` + validate(collection.getSubCollectionMap().get("2"), Collections.emptyList(), Collections.emptyMap()); + + // check `3` + validate(collection.getSubCollectionMap().get("3"), Collections.emptyList(), Collections.emptyMap()); + + // check `11` + validate(collection.getSubCollectionMap().get("1").getSubCollectionMap().get("11"), Collections.singletonList("111"), Collections.emptyMap()); + + // check `111` + elements.put("a", "S2-1EDBE882A757E1FAFCA77A9D3BE3FF5D2BB3E2037B238C865F1F957C431F43B4"); + elements.put("b", "S2-30BA7CD8B4AD93A8B3826CD8D1518790924EEBB930EC04DF7DFB03A50B17D7BC"); + validate( + collection.getSubCollectionMap().get("1").getSubCollectionMap().get("11").getSubCollectionMap().get("111"), + Collections.emptyList(), + elements + ); + elements.clear(); + + // check `12` + validate(collection.getSubCollectionMap().get("1").getSubCollectionMap().get("12"), Collections.emptyList(), Collections.emptyMap()); + + } catch (IOException e) { + e.printStackTrace(); + fail(); + } + } +}
\ No newline at end of file diff --git a/src/test/java/com/keuin/kbackupfabric/util/backup/incremental/ObjectCollectionSerializerTest.java b/src/test/java/com/keuin/kbackupfabric/util/backup/incremental/ObjectCollectionSerializerTest.java new file mode 100644 index 0000000..0edfe01 --- /dev/null +++ b/src/test/java/com/keuin/kbackupfabric/util/backup/incremental/ObjectCollectionSerializerTest.java @@ -0,0 +1,29 @@ +package com.keuin.kbackupfabric.util.backup.incremental; + +import com.keuin.kbackupfabric.util.backup.incremental.identifier.Sha256Identifier; +import org.junit.Test; + +import java.io.File; +import java.io.IOException; +import java.nio.file.Files; + +import static org.junit.Assert.assertEquals; + +public class ObjectCollectionSerializerTest { + @Test + public void testSerializationConsistency() throws IOException { + ObjectCollectionFactory<Sha256Identifier> factory = + new ObjectCollectionFactory<>(Sha256Identifier.getFactory()); + ObjectCollection collection = + factory.fromDirectory(new File("./testfile/ObjectCollectionFactoryTest")); + File file = new File("./testfile/serialized"); + if (file.exists()) { + Files.delete(file.toPath()); + } + ObjectCollectionSerializer.toFile(collection, file); + ObjectCollection collection2 = ObjectCollectionSerializer.fromFile(file); + Files.delete(file.toPath()); + assertEquals(collection, collection2); + } + +}
\ No newline at end of file diff --git a/src/test/java/com/keuin/kbackupfabric/util/backup/incremental/identifier/Sha256IdentifierTest.java b/src/test/java/com/keuin/kbackupfabric/util/backup/incremental/identifier/Sha256IdentifierTest.java new file mode 100644 index 0000000..f799a95 --- /dev/null +++ b/src/test/java/com/keuin/kbackupfabric/util/backup/incremental/identifier/Sha256IdentifierTest.java @@ -0,0 +1,25 @@ +package com.keuin.kbackupfabric.util.backup.incremental.identifier; + +import org.junit.Test; + +import java.io.File; +import java.io.IOException; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.fail; + +public class Sha256IdentifierTest { + + @Test + public void fromFile() { + try { + Sha256Identifier sha256 = Sha256Identifier.fromFile(new File("./testfile/Sha256IdentifierTest")); + String str = sha256.getIdentification().toUpperCase(); + assertEquals("S2-315F5BDB76D078C43B8AC0064E4A0164612B1FCE77C869345BFC94C75894EDD3", str); + } catch (IOException e) { + e.printStackTrace(); + fail(); + } + } + +}
\ No newline at end of file diff --git a/src/test/java/com/keuin/kbackupfabric/util/backup/name/IncrementalBackupFileNameEncoderTest.java b/src/test/java/com/keuin/kbackupfabric/util/backup/name/IncrementalBackupFileNameEncoderTest.java new file mode 100644 index 0000000..e5fedd7 --- /dev/null +++ b/src/test/java/com/keuin/kbackupfabric/util/backup/name/IncrementalBackupFileNameEncoderTest.java @@ -0,0 +1,38 @@ +package com.keuin.kbackupfabric.util.backup.name; + +import org.junit.Test; + +import java.time.LocalDateTime; + +import static org.junit.Assert.*; + +public class IncrementalBackupFileNameEncoderTest { + @Test + public void testEncode() { + LocalDateTime time = LocalDateTime.of(1, 1, 1, 1, 1, 1); + String customName = "name"; + IncrementalBackupFileNameEncoder encoder = new IncrementalBackupFileNameEncoder(); + assertEquals("incremental-0001-01-01_01-01-01_name.kbi", encoder.encode(customName, time)); + } + + @Test + public void testDecode() { + LocalDateTime time = LocalDateTime.of(1, 1, 1, 1, 1, 1); + String customName = "name"; + IncrementalBackupFileNameEncoder encoder = new IncrementalBackupFileNameEncoder(); + BackupFileNameEncoder.BackupBasicInformation information = encoder.decode("incremental-0001-01-01_01-01-01_name.kbi"); + assertEquals(time, information.time); + assertEquals(customName, information.customName); + } + + @Test + public void isValid() { + IncrementalBackupFileNameEncoder encoder = new IncrementalBackupFileNameEncoder(); + assertTrue(encoder.isValidFileName("incremental-0001-01-01_01-01-01_name.kbi")); + assertTrue(encoder.isValidFileName("incremental-0001-01-01_01-01-01_0001-01-01_01-01-01_name.kbi")); + assertFalse(encoder.isValidFileName("incremental-0001-01-01_01-01-01incremental-0001-01-01_01-01-01_name.kbi")); + assertFalse(encoder.isValidFileName("incremental-0001-01-01_01-01-01_name")); + assertFalse(encoder.isValidFileName("incremental-0001-01-01_01-01-01_name.zip")); + assertFalse(encoder.isValidFileName("somefile")); + } +}
\ No newline at end of file diff --git a/src/test/java/com/keuin/kbackupfabric/util/backup/name/PrimitiveBackupFileNameEncoderTest.java b/src/test/java/com/keuin/kbackupfabric/util/backup/name/PrimitiveBackupFileNameEncoderTest.java new file mode 100644 index 0000000..abc19d5 --- /dev/null +++ b/src/test/java/com/keuin/kbackupfabric/util/backup/name/PrimitiveBackupFileNameEncoderTest.java @@ -0,0 +1,50 @@ +package com.keuin.kbackupfabric.util.backup.name; + +import org.junit.Test; + +import java.time.LocalDateTime; +import java.time.ZoneOffset; + +import static org.junit.Assert.*; + +public class PrimitiveBackupFileNameEncoderTest { + + @Test + public void testConsistency() { + LocalDateTime time = LocalDateTime.ofEpochSecond(System.currentTimeMillis() / 1000, 0, ZoneOffset.UTC); + String name = "Test Na_me"; + PrimitiveBackupFileNameEncoder encoder = new PrimitiveBackupFileNameEncoder(); + BackupFileNameEncoder.BackupBasicInformation information = encoder.decode(encoder.encode(name, time)); + assertEquals(time, information.time); + assertEquals(name, information.customName); + } + + @Test + public void testEncode() { + LocalDateTime time = LocalDateTime.of(1, 1, 1, 1, 1, 1); + String customName = "name"; + PrimitiveBackupFileNameEncoder encoder = new PrimitiveBackupFileNameEncoder(); + assertEquals("kbackup-0001-01-01_01-01-01_name.zip", encoder.encode(customName, time)); + } + + @Test + public void testDecode() { + LocalDateTime time = LocalDateTime.of(1, 1, 1, 1, 1, 1); + String customName = "name"; + PrimitiveBackupFileNameEncoder encoder = new PrimitiveBackupFileNameEncoder(); + BackupFileNameEncoder.BackupBasicInformation information = encoder.decode("kbackup-0001-01-01_01-01-01_name.zip"); + assertEquals(time, information.time); + assertEquals(customName, information.customName); + } + + @Test + public void isValid() { + PrimitiveBackupFileNameEncoder encoder = new PrimitiveBackupFileNameEncoder(); + assertTrue(encoder.isValidFileName("kbackup-0001-01-01_01-01-01_name.zip")); + assertTrue(encoder.isValidFileName("kbackup-0001-01-01_01-01-01_0001-01-01_01-01-01_name.zip")); + assertFalse(encoder.isValidFileName("kbackup-0001-01-01_01-01-01kbackup-0001-01-01_01-01-01_name.zip")); + assertFalse(encoder.isValidFileName("kbackup-0001-01-01_01-01-01_name")); + assertFalse(encoder.isValidFileName("kbackup-0001-01-01_01-01-01_name.kbi")); + assertFalse(encoder.isValidFileName("somefile")); + } +}
\ No newline at end of file |