示例#1
0
        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);
        }
示例#2
0
        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);
        }
示例#3
0
        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)));
        }
示例#4
0
        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);
        }
示例#5
0
        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);
        }
示例#6
0
        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);
            }
        }
示例#8
0
        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);
            }
        }