private MockDownloadJob GetJob_FailedDownload_IOFailed(string songHash, string songDir) { Exception downloadException = new IOException(); DownloadResult downloadResult = new DownloadResult(@"C:\Test", DownloadResultStatus.IOFailed, 200, "IOFailed", downloadException); ZipExtractResult zipResult = null; var finalResult = new JobResult() { SongHash = songHash, DownloadResult = downloadResult, ZipResult = zipResult, SongDirectory = songDir }; var job = new MockDownloadJob(songHash, finalResult); return(job); }
private MockDownloadJob GetJob_FailedDownload_NetFailed(string songHash, string songDir) { Exception downloadException = new WebClientException("404: Not Found"); DownloadResult downloadResult = new DownloadResult(@"C:\Test", DownloadResultStatus.NetFailed, 404, "404: Not Found", downloadException); ZipExtractResult zipResult = null; var finalResult = new JobResult() { SongHash = songHash, DownloadResult = downloadResult, ZipResult = zipResult, SongDirectory = songDir }; var job = new MockDownloadJob(songHash, finalResult); return(job); }
public void ZipDestinationFailed() { var downloader = GetDefaultDownloader(); var testHash = "A7SDF6A86SDF9ASDF"; var song = new PlaylistSong(testHash, "Successful Song", "fff2", "Other"); var songPath = Path.Combine(TestSongsDir, "fff2 (Successful Song)"); downloader.HistoryManager.TryAdd(song, 0); var testDownloadResult = new DownloadResult(songPath, DownloadResultStatus.Success, 200); ZipExtractResult testZipResult = new ZipExtractResult() { CreatedOutputDirectory = true, Exception = null, OutputDirectory = songPath, ExtractedFiles = new string[] { "info.dat", "expert.dat", "song.egg" }, ResultStatus = ZipExtractResultStatus.DestinationFailed, SourceZip = "fff2.zip" }; var jobResult = new JobResult() { DownloadResult = testDownloadResult, ZipResult = testZipResult, SongHash = song.Hash, //Song = song, SongDirectory = null }; var testJob = new MockDownloadJob(testHash, jobResult, false); testJob.RunAsync().Wait(); var recentPlaylist = PlaylistManager.GetPlaylist(BuiltInPlaylist.BeatSyncRecent); recentPlaylist.TryAdd(song); var bSaberPlaylist = PlaylistManager.GetPlaylist(BuiltInPlaylist.BeastSaberCurator); bSaberPlaylist.TryAdd(song); // Verify setup Assert.IsTrue(recentPlaylist.Beatmaps.Any(s => song.Hash.Equals(s.Hash))); Assert.IsTrue(bSaberPlaylist.Beatmaps.Any(s => song.Hash.Equals(s.Hash))); Assert.IsTrue(downloader.HistoryManager.TryGetValue(song.Hash, out var entry)); Assert.AreEqual(HistoryFlag.None, entry.Flag); // Run tests downloader.ProcessJob(testJob); Assert.IsTrue(downloader.HistoryManager.TryGetValue(song.Hash, out entry)); Assert.AreEqual(HistoryFlag.Error, entry.Flag); Assert.IsTrue(recentPlaylist.Beatmaps.Any(s => song.Hash.Equals(s.Hash))); Assert.IsTrue(bSaberPlaylist.Beatmaps.Any(s => song.Hash.Equals(s.Hash))); }
private MockDownloadJob GetJob_Successful(string songHash, string songDir) { var downloadResult = new DownloadResult(@"C:\Test", DownloadResultStatus.Success, 200); var zipResult = new ZipExtractResult() { ResultStatus = ZipExtractResultStatus.Success }; var finalResult = new JobResult() { SongHash = songHash, DownloadResult = downloadResult, ZipResult = zipResult, SongDirectory = songDir }; var job = new MockDownloadJob(songHash, finalResult); return(job); }
private MockDownloadJob GetJob_FailedExtraction_Source(string songHash, string songDir) { var downloadResult = new DownloadResult(@"C:\Test", DownloadResultStatus.Success, 200); Exception zipException = new IOException(); var zipResult = new ZipExtractResult() { ResultStatus = ZipExtractResultStatus.SourceFailed, Exception = zipException }; var finalResult = new JobResult() { SongHash = songHash, DownloadResult = downloadResult, ZipResult = zipResult, SongDirectory = null }; var job = new MockDownloadJob(songHash, finalResult); return(job); }
public void BeatSaverNotFound() { //Assert.Fail("Need to fix after refactor"); var downloader = GetDefaultDownloader(); var testHash = "ASDFLKJACVOIAOSICJVLKXCVJ"; var song = new PlaylistSong(testHash, "Missing ExpectedDiff", "fff1", "Other"); downloader.HistoryManager.TryAdd(song, 0); var testDownloadResult = new DownloadResult(song.Hash, DownloadResultStatus.NetNotFound, 404); ZipExtractResult testZipResult = null; var jobResult = new JobResult() { DownloadResult = testDownloadResult, ZipResult = testZipResult, SongHash = song.Hash, //Song = song, SongDirectory = null }; var testJob = new MockDownloadJob(testHash, jobResult, false); testJob.RunAsync().Wait(); var recentPlaylist = PlaylistManager.GetPlaylist(BuiltInPlaylist.BeatSyncRecent); recentPlaylist.TryAdd(song); var bSaberPlaylist = PlaylistManager.GetPlaylist(BuiltInPlaylist.BeastSaberCurator); bSaberPlaylist.TryAdd(song); // Verify setup Assert.IsTrue(recentPlaylist.Beatmaps.Any(s => song.Hash.Equals(s.Hash))); Assert.IsTrue(bSaberPlaylist.Beatmaps.Any(s => song.Hash.Equals(s.Hash))); Assert.IsTrue(downloader.HistoryManager.TryGetValue(song.Hash, out var entry)); Assert.AreEqual(HistoryFlag.None, entry.Flag); // Run test downloader.ProcessJob(testJob); Assert.IsTrue(downloader.HistoryManager.TryGetValue(song.Hash, out entry)); Assert.AreEqual(HistoryFlag.BeatSaverNotFound, entry.Flag); Assert.IsFalse(recentPlaylist.Beatmaps.Any(s => song.Hash.Equals(s.Hash))); Assert.IsFalse(bSaberPlaylist.Beatmaps.Any(s => song.Hash.Equals(s.Hash))); }
public void ExtractZip_Normal_CantDeleteZip() { string zipName = "5d28-LongEntry.zip"; string zipPath = Path.Combine(SongZipsPath, zipName); string copiedZipPath = zipPath.Replace("Entry", "Entry-Copy"); File.Copy(zipPath, copiedZipPath, true); string[] entries; using (var fs = new FileStream(copiedZipPath, FileMode.Open, FileAccess.Read)) using (var zipArchive = new ZipArchive(fs, ZipArchiveMode.Read)) { entries = zipArchive.Entries.Select(e => e.Name).ToArray(); } string songsPath = @"Output"; string songDir = "5d28-CantDeleteZip"; string originalExtractPath = Path.GetFullPath(Path.Combine(songsPath, songDir)); ZipExtractResult zipResult = null; DirectoryInfo extractedFolder = null; using (var copiedZip = File.OpenRead(copiedZipPath)) { zipResult = FileIO.ExtractZip(copiedZipPath, originalExtractPath, true); extractedFolder = new DirectoryInfo(zipResult.OutputDirectory); } Assert.IsTrue(File.Exists(copiedZipPath)); var extractedFiles = extractedFolder.GetFiles().Select(f => f.Name); foreach (var entry in entries) { Assert.IsTrue(extractedFiles.Contains(entry)); } Directory.Delete(originalExtractPath, true); if (Directory.Exists(zipResult.OutputDirectory)) { Directory.Delete(zipResult.OutputDirectory, true); } }
public void DownloadFailed_IO() { var downloader = GetDefaultDownloader(); var testHash = "ASDFLKJACVOIAOSICJVLKXCVJ"; var song = new PlaylistSong(testHash, "Missing ExpectedDiff", "fff1", "Other"); downloader.HistoryManager.TryAdd(song, 0); var testDownloadResult = new DownloadResult(song.Hash, DownloadResultStatus.IOFailed, 200); ZipExtractResult testZipResult = null; var testJob = new JobResult() { DownloadResult = testDownloadResult, ZipResult = testZipResult, BeatSaverHash = song.Hash, Song = song, SongDirectory = null }; var recentPlaylist = PlaylistManager.GetPlaylist(BuiltInPlaylist.BeatSyncRecent); recentPlaylist.TryAdd(song); var bSaberPlaylist = PlaylistManager.GetPlaylist(BuiltInPlaylist.BeastSaberCurator); bSaberPlaylist.TryAdd(song); // Verify setup Assert.IsTrue(recentPlaylist.Songs.Any(s => song.Hash.Equals(s.Hash))); Assert.IsTrue(bSaberPlaylist.Songs.Any(s => song.Hash.Equals(s.Hash))); Assert.IsTrue(downloader.HistoryManager.TryGetValue(song.Hash, out var entry)); Assert.AreEqual(HistoryFlag.None, entry.Flag); // Run test downloader.ProcessJob(testJob); Assert.IsFalse(downloader.HistoryManager.TryGetValue(song.Hash, out entry)); Assert.IsTrue(recentPlaylist.Songs.Any(s => song.Hash.Equals(s.Hash))); Assert.IsTrue(bSaberPlaylist.Songs.Any(s => song.Hash.Equals(s.Hash))); }
public static async Task <ZipExtractResult> ExtractZip(Stream zipStream, string extractDirectory, bool overwriteTarget = true, string?sourcePath = null) { if (zipStream == null) { throw new ArgumentNullException(nameof(zipStream)); } if (string.IsNullOrEmpty(extractDirectory)) { throw new ArgumentNullException(nameof(extractDirectory)); } ZipExtractResult result = new ZipExtractResult { SourceZip = sourcePath ?? "Stream", ResultStatus = ZipExtractResultStatus.Unknown }; string? createdDirectory = null; List <string>?createdFiles = new List <string>(); try { //Plugin.Log?.Info($"ExtractDirectory is {extractDirectory}"); using (ZipArchive? zipArchive = new ZipArchive(zipStream, ZipArchiveMode.Read)) { //Plugin.Log?.Info("Zip opened"); //extractDirectory = GetValidPath(extractDirectory, zipArchive.Entries.Select(e => e.Name).ToArray(), shortDirName, overwriteTarget); int longestEntryName = zipArchive.Entries.Select(e => e.Name).Max(n => n.Length); try { extractDirectory = Path.GetFullPath(extractDirectory); // Could theoretically throw an exception: Argument/ArgumentNull/Security/NotSupported/PathTooLong extractDirectory = GetValidPath(extractDirectory, longestEntryName, 3); if (!overwriteTarget && Directory.Exists(extractDirectory)) { int pathNum = 2; string finalPath; do { string?append = $" ({pathNum})"; finalPath = GetValidPath(extractDirectory, longestEntryName, append.Length) + append; // padding ensures we aren't continuously cutting off the append value pathNum++; } while (Directory.Exists(finalPath)); extractDirectory = finalPath; } } catch (PathTooLongException ex) { result.Exception = ex; result.ResultStatus = ZipExtractResultStatus.DestinationFailed; return(result); } result.OutputDirectory = extractDirectory; bool extractDirectoryExists = Directory.Exists(extractDirectory); string?toBeCreated = extractDirectoryExists ? null : extractDirectory; // For cleanup try { Directory.CreateDirectory(extractDirectory); } catch (Exception ex) { result.Exception = ex; result.ResultStatus = ZipExtractResultStatus.DestinationFailed; return(result); } result.CreatedOutputDirectory = !extractDirectoryExists; createdDirectory = string.IsNullOrEmpty(toBeCreated) ? null : extractDirectory; // TODO: Ordering so largest files extracted first. If the extraction is interrupted, theoretically the song's hash won't match Beat Saver's. foreach (ZipArchiveEntry entry in zipArchive.Entries.OrderByDescending(e => e.Length)) { if (!entry.FullName.Equals(entry.Name)) // If false, the entry is a directory or file nested in one { continue; } string entryPath = Path.Combine(extractDirectory, entry.Name); bool fileExists = File.Exists(entryPath); if (overwriteTarget || !fileExists) { try { using (var fs = File.OpenWrite(entryPath)) { await entry.Open().CopyToAsync(fs); } createdFiles.Add(entryPath); } catch (InvalidDataException ex) // Entry is missing, corrupt, or compression method isn't supported { Plugin.Log?.Error($"Error extracting {extractDirectory}, archive appears to be damaged."); Plugin.Log?.Error(ex); result.Exception = ex; result.ResultStatus = ZipExtractResultStatus.SourceFailed; result.ExtractedFiles = createdFiles.ToArray(); } catch (Exception ex) { Plugin.Log?.Error($"Error extracting {extractDirectory}"); Plugin.Log?.Error(ex); result.Exception = ex; result.ResultStatus = ZipExtractResultStatus.DestinationFailed; result.ExtractedFiles = createdFiles.ToArray(); } if (result.Exception != null) { foreach (string?file in createdFiles) { TryDeleteAsync(file).Wait(); } return(result); } } } result.ExtractedFiles = createdFiles.ToArray(); } result.ResultStatus = ZipExtractResultStatus.Success; return(result); #pragma warning disable CA1031 // Do not catch general exception types } catch (InvalidDataException ex) // FileStream is not in the zip archive format. { result.ResultStatus = ZipExtractResultStatus.SourceFailed; result.Exception = ex; return(result); } catch (Exception ex) // If exception is thrown here, it probably happened when the FileStream was opened. #pragma warning restore CA1031 // Do not catch general exception types { Plugin.Log?.Error($"Error extracting zip from {sourcePath ?? "Stream"}"); Plugin.Log?.Error(ex); try { if (!string.IsNullOrEmpty(createdDirectory)) { Directory.Delete(createdDirectory, true); } else // TODO: What is this doing here... { foreach (string?file in createdFiles) { File.Delete(file); } } } catch (Exception cleanUpException) { // Failed at cleanup Plugin.Log?.Debug($"Failed to clean up zip file: {cleanUpException.Message}"); } result.Exception = ex; result.ResultStatus = ZipExtractResultStatus.SourceFailed; return(result); } }