private static async Task CreateArchiveAsync(string sourcePath, string headerFilePath, string dataFilePath) { if (!Directory.Exists(sourcePath)) { throw new Exception($"Directory doesn't exist \"{sourcePath}\"."); } var filePaths = GetFilesRelative(sourcePath); MS2File[] files = new MS2File[filePaths.Length]; var tasks = new Task[filePaths.Length]; for (uint i = 0; i < filePaths.Length; i++) { uint ic = i; tasks[i] = Task.Run(() => { var(filePath, relativePath) = filePaths[ic]; files[ic] = MS2File.Create(ic + 1u, relativePath, CompressionType.Zlib, CryptoMode, filePath); }); } await Task.WhenAll(tasks).ConfigureAwait(false); await MS2Archive.Save(CryptoMode, files, headerFilePath, dataFilePath, RunMode.Async2).ConfigureAwait(false); }
private static void UpdateRandomFilesFromArchive(MS2Archive archive) { const int minFilesForRandom = 10; const string folderForAddingName = "FilesForAddingToArchive"; string folderToArchive = Path.Combine(@"..\TestData", folderForAddingName); string folderToArchiveFullPath = Path.GetFullPath(folderToArchive) + @"\"; string[] filesToArchive = Directory.GetFiles(folderToArchive, "*.*", SearchOption.AllDirectories).Select(p => Path.GetFullPath(p)).ToArray(); Assert.IsTrue(filesToArchive.Length > minFilesForRandom, $"you need at least {minFilesForRandom} files in the adding archive folder for this test"); uint count = (uint)Random.Next(minFilesForRandom, filesToArchive.Length); HashSet <string> distinctFiles = new HashSet <string>(); uint i = 0; while (i < count) { if (distinctFiles.Add(filesToArchive[Random.Next(0, filesToArchive.Length)])) { i++; } } string[] files = distinctFiles.ToArray(); Assert.AreEqual(files.Length, (int)count); for (i = 0; i < count; i++) { string file = files[i]; int index = Random.Next(0, archive.Files.Count); MS2File previousFile = archive.Files[index]; archive.Files[index] = MS2File.CreateUpdate(previousFile, file); } }
public void Dispose_EncapsulatedMemoryMappedFile_DoesNotThrowObjectDisposedException() { var expectedBytes = new byte[] { 0x30, 0x60 }; var archiveMock = new Mock <IMS2Archive>(MockBehavior.Strict); var mappedFile = MemoryMappedFile.CreateNew(nameof(Dispose_EncapsulatedMemoryMappedFile_DoesNotThrowObjectDisposedException), expectedBytes.Length, MemoryMappedFileAccess.ReadWrite, MemoryMappedFileOptions.None, HandleInheritability.None); var info = new MS2FileInfo("1", "testfile"); var header = new MS2FileHeader(expectedBytes.Length, 1, 0); var file = new MS2File(archiveMock.Object, mappedFile, info, header, false); file.Dispose(); mappedFile.CreateViewAccessor(); }
public void Dispose_EncapsulatedStream_ThrowsObjectDisposedException() { var expectedBytes = new byte[] { 0x30, 0x60 }; var archiveMock = new Mock <IMS2Archive>(MockBehavior.Strict); var stream = new MemoryStream(expectedBytes); var info = new MS2FileInfo("1", "testfile"); var header = new MS2FileHeader(expectedBytes.Length, 1, 0); var file = new MS2File(archiveMock.Object, stream, info, header, false); file.Dispose(); stream.ReadByte(); }
public async Task Dispose_GetStreamForArchivingAsync_ThrowsObjectDisposedException() { var expectedBytes = new byte[] { 0x30, 0x60 }; var archiveMock = new Mock <IMS2Archive>(MockBehavior.Strict); var stream = new MemoryStream(expectedBytes); var info = new MS2FileInfo("1", "testfile"); var header = new MS2FileHeader(expectedBytes.Length, 1, 0); var file = new MS2File(archiveMock.Object, stream, info, header, false); file.Dispose(); await file.GetStreamForArchivingAsync(); }
private static async Task ExtractArchiveSync(string headerFile, string dataFile, string destinationPath) { using (MS2Archive archive = await MS2Archive.Load(headerFile, dataFile).ConfigureAwait(false)) { List <MS2File> files = archive.Files; for (int i = 0; i < files.Count; i++) { MS2File file = files[i]; Logger.Info($"Extracting file \"{file.Name}\", \"{FileEx.FormatStorage(file.Header.Size)}\". ({file.Header.Id}/{files.Count})"); await ExtractFileAsync(destinationPath, file).ConfigureAwait(false); } } }
private static async Task ExportArchiveAsync(string headerFile, string dataFile, string destinationFilePath) { using (var swExport = new StreamWriter(destinationFilePath)) using (MS2Archive archive = await MS2Archive.Load(headerFile, dataFile).ConfigureAwait(false)) { List <MS2File> files = archive.Files; for (int i = 0; i < files.Count; i++) { MS2File file = files[i]; Logger.Info($"Exporting file \"{file.Name}\". ({file.Header.Id}/{files.Count})"); await ExportFileAsync(swExport, file).ConfigureAwait(false); } } }
public async Task GetStreamAsync_StreamEncryptedFalseAndCompressionZlib_EqualsInput() { string input = "testdatainputcompressed"; string expected = input; using MemoryStream inputStream = StringToStream(input); var archiveMock = CreateArchiveMock(); var infoMock = CreateFileInfoMock("1", "testfile"); var sizeMock = CreateSizeMock(input.Length, input.Length, input.Length); var headerMock = CreateFileHeaderMock(sizeMock, 1, 0, CompressionType.Zlib); var file = new MS2File(archiveMock.Object, inputStream, infoMock.Object, headerMock.Object, false); var actualStream = await file.GetStreamAsync(); string actual = await StreamToString(actualStream); Assert.AreEqual(expected, actual); }
public async Task GetStreamAsync_StreamEncryptedTrueAndCompressionZlib_EqualsExpected() { string input = "testdatainputencryptedcompressed"; string expected = "testdataexpected"; MS2CryptoMode cryptoMode = (MS2CryptoMode)12345; var sizeMock = CreateSizeMock(10, 20, 30); IMS2ArchiveCryptoRepository repo = new FakeCryptoRepository(cryptoMode, EncodingTest, expected, input, sizeMock.Object); using MemoryStream inputStream = StringToStream(input); var archiveMock = CreateArchiveMock(repo); var infoMock = CreateFileInfoMock("1", "testfile"); var headerMock = CreateFileHeaderMock(sizeMock, 1, 0, CompressionType.Zlib); var file = new MS2File(archiveMock.Object, inputStream, infoMock.Object, headerMock.Object, true); var actualStream = await file.GetStreamAsync(); string actual = await StreamToString(actualStream); Assert.AreEqual(expected, actual); }
private static Task ExportFileAsync(StreamWriter swExport, MS2File file) { string fileName = file.Name; if (String.IsNullOrWhiteSpace(fileName)) { Logger.Warning($"File number \"{file.Id}\" has no name and will be ignored."); return(Task.CompletedTask); } uint id = file.Header.Id; CompressionType typeId = file.CompressionType; FileTypes.AddOrUpdate(Path.GetExtension(fileName), new HashSet <string>() { typeId.ToString() }, (_, v) => { v.Add(typeId.ToString()); return(v); }); string rootDirectory = PathEx.GetRootDirectory(fileName); if (!String.IsNullOrEmpty(rootDirectory)) { if (String.IsNullOrEmpty(file.InfoHeader.RootFolderId)) { Logger.Warning($"Root folder id is empty but it has a root folder ({rootDirectory})!"); } RootFolderIds.AddOrUpdate(rootDirectory, new HashSet <string>() { file.InfoHeader.RootFolderId }, (_, v) => { v.Add(file.InfoHeader.RootFolderId); return(v); }); } int propCount = file.InfoHeader.Properties.Count; string info = String.Join(",", file.InfoHeader.Properties); return(swExport.WriteLineAsync($"{id:d6} - Type:{typeId}; Properties:{propCount}; Info={info}")); }
public async Task GetStreamForArchivingAsync_StreamEncryptedTrueAndCompressionNone_EqualsInput() { string input = "testdatainput"; string expected = input; MS2CryptoMode cryptoMode = (MS2CryptoMode)12345; var sizeMock = CreateSizeMock(10, 10, 10); var expectedSize = sizeMock.Object; IMS2ArchiveCryptoRepository repo = new FakeCryptoRepository(cryptoMode, EncodingTest, input, expected, sizeMock.Object); using MemoryStream inputStream = StringToStream(input); var archiveMock = CreateArchiveMock(repo); var infoMock = CreateFileInfoMock("1", "testfile"); var headerMock = CreateFileHeaderMock(sizeMock, 1, 0, CompressionType.None); var file = new MS2File(archiveMock.Object, inputStream, infoMock.Object, headerMock.Object, true); var(actualStream, actualSize) = await file.GetStreamForArchivingAsync(); string actual = await StreamToString(actualStream); Assert.AreEqual(expected, actual); Assert.AreEqual(expectedSize.EncodedSize, actualSize.EncodedSize); Assert.AreEqual(expectedSize.CompressedSize, actualSize.CompressedSize); Assert.AreEqual(expectedSize.Size, actualSize.Size); }
private static async Task ExtractFileAsync(string destinationPath, MS2File file) { if (String.IsNullOrWhiteSpace(file.Name)) { Logger.Warning($"File number \"{file.Id}\", \"{FileEx.FormatStorage(file.Header.Size)}\" has no name and will be ignored."); return; } string fileDestinationPath = Path.Combine(destinationPath, file.Name); (Stream stream, bool shouldDispose) = await file.GetDecryptedStreamAsync().ConfigureAwait(false); try { await stream.CopyToAsync(fileDestinationPath).ConfigureAwait(false); } finally { if (shouldDispose) { stream.Dispose(); } } }
public async Task TestCreateConsistencyMS2F() { const string archiveName = "PrecomputedTerrain"; const string folderToArchive = @"C:\Users\Miyu\Desktop\ReleaseOutput\Resource\" + archiveName; string folderToArchiveFullPath = Path.GetFullPath(folderToArchive) + @"\"; string[] filesToArchive = Directory.GetFiles(folderToArchive, "*.*", SearchOption.AllDirectories).Select(p => Path.GetFullPath(p)).ToArray(); const string headerFilePath = @"..\TestData\PrecomputedTerrain.m2h"; const string dataFilePath = @"..\TestData\PrecomputedTerrain.m2d"; MS2CryptoMode archiveCryptoMode = MS2CryptoMode.MS2F; MS2File[] files = new MS2File[filesToArchive.Length]; for (int i = 0; i < filesToArchive.Length; i++) { string file = filesToArchive[i]; files[i] = MS2File.Create((uint)i + 1u, file.Remove(folderToArchiveFullPath), CompressionType.Zlib, archiveCryptoMode, file); } const string testArchiveName = "FromExtractedMS2F"; const string headerTestFileName = testArchiveName + ".m2h"; const string dataTestFileName = testArchiveName + ".m2d"; try { await MS2Archive.Save(archiveCryptoMode, files, headerTestFileName, dataTestFileName, RunMode.Async2).ConfigureAwait(false); Assert.IsTrue(File.Exists(headerTestFileName)); Assert.IsTrue(File.Exists(dataTestFileName)); using (MS2Archive archive = await MS2Archive.Load(headerFilePath, dataFilePath).ConfigureAwait(false)) { Dictionary <uint, MS2File> mappedFiles = archive.Files.Zip(files, (o, s) => (o, s)) .ToDictionary(f => f.o.Id, f => files.Where(sf => sf.Name == f.o.Name).First()); Assert.AreEqual(archive.CryptoMode, archiveCryptoMode); Assert.AreEqual(archive.Files.Count, filesToArchive.Length); //Assert.AreEqual(archive.Name, ArchiveName); Task[] tasks = new Task[filesToArchive.Length]; for (int i = 0; i < filesToArchive.Length; i++) { int ic = i; tasks[ic] = Task.Run(async() => { MS2File file = archive.Files[ic]; MS2File savedFile = mappedFiles[file.Id]; var(savedStream, savedShouldDispose) = await savedFile.GetDecryptedStreamAsync().ConfigureAwait(false); try { Assert.AreEqual(file.Id, (uint)ic + 1); Assert.AreEqual(file.CompressionType, CompressionType.Zlib); Assert.IsTrue(file.IsZlibCompressed); Assert.AreEqual(file.Name, savedFile.Name); Assert.AreEqual(file.Header.CompressionType, file.CompressionType); Assert.AreEqual(file.Header.Size, (uint)savedStream.Length); (Stream stream, bool shouldDispose) = await file.GetDecryptedStreamAsync().ConfigureAwait(false); try { byte[] savedBytes = new byte[savedStream.Length]; byte[] originalBytes = new byte[stream.Length]; int savedReadBytes = await savedStream.ReadAsync(savedBytes, 0, savedBytes.Length).ConfigureAwait(false); int originalReadBytes = await stream.ReadAsync(originalBytes, 0, originalBytes.Length).ConfigureAwait(false); Assert.AreEqual(originalReadBytes, savedReadBytes); CollectionAssert.AreEqual(originalBytes, savedBytes); } finally { if (shouldDispose) { stream.Dispose(); } } } finally { if (savedShouldDispose) { savedStream.Dispose(); } } }); } await Task.WhenAll(tasks).ConfigureAwait(false); } } finally { File.Delete(headerTestFileName); File.Delete(dataTestFileName); } }
public async Task TestCreateCompletelyNewNS2F() { const string folderForArchiving = "TestFolderForArchiving"; string folderToArchive = Path.Combine(@"..\TestData", folderForArchiving); string folderToArchiveFullPath = Path.GetFullPath(folderToArchive) + @"\"; string[] filesToArchive = Directory.GetFiles(folderToArchive, "*.*", SearchOption.AllDirectories).Select(p => Path.GetFullPath(p)).ToArray(); MS2CryptoMode cryptoMode = MS2CryptoMode.NS2F; MS2File[] files = new MS2File[filesToArchive.Length]; for (int i = 0; i < filesToArchive.Length; i++) { string file = filesToArchive[i]; files[i] = MS2File.Create((uint)i + 1u, file.Remove(folderToArchiveFullPath), CompressionType.Zlib, cryptoMode, file); } const string testArchiveName = "TestArchiveNS2F"; const string headerTestFileName = testArchiveName + ".m2h"; const string dataTestFileName = testArchiveName + ".m2d"; try { await MS2Archive.Save(cryptoMode, files, headerTestFileName, dataTestFileName, RunMode.Async2).ConfigureAwait(false); Assert.IsTrue(File.Exists(headerTestFileName)); Assert.IsTrue(File.Exists(dataTestFileName)); using (MS2Archive archive = await MS2Archive.Load(headerTestFileName, dataTestFileName).ConfigureAwait(false)) { Assert.AreEqual(archive.CryptoMode, cryptoMode); Assert.AreEqual(archive.Files.Count, filesToArchive.Length); //Assert.AreEqual(archive.Name, ArchiveFolder); for (int i = 0; i < filesToArchive.Length; i++) { FileStream fsFile = File.OpenRead(filesToArchive[i]); MS2File file = archive.Files[i]; Assert.AreEqual(file.Id, (uint)i + 1); Assert.AreEqual(file.CompressionType, CompressionType.Zlib); Assert.IsTrue(file.IsZlibCompressed); Assert.AreEqual(file.Name, filesToArchive[i].Remove(folderToArchiveFullPath)); Assert.AreEqual(file.Header.CompressionType, file.CompressionType); Assert.AreEqual(file.Header.Size, (uint)fsFile.Length); (Stream stream, bool shouldDispose) = await file.GetDecryptedStreamAsync().ConfigureAwait(false); try { byte[] originalBytes = new byte[fsFile.Length]; byte[] savedBytes = new byte[stream.Length]; int originalReadBytes = await fsFile.ReadAsync(originalBytes, 0, originalBytes.Length).ConfigureAwait(false); int savedReadBytes = await stream.ReadAsync(savedBytes, 0, savedBytes.Length).ConfigureAwait(false); Assert.AreEqual(originalReadBytes, savedReadBytes); CollectionAssert.AreEqual(originalBytes, savedBytes); } finally { if (shouldDispose) { stream.Dispose(); } } } } } finally { File.Delete(headerTestFileName); File.Delete(dataTestFileName); } }