FileUtilsTest.cs 9.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255
  1. namespace MeloongCore.Tests;
  2. public class FileUtilsTest : TestWithFolder {
  3. #region 压缩包
  4. [Theory]
  5. [InlineData("GB Encoding.zip")]
  6. [InlineData("UTF8 Encoding.zip")]
  7. public void Compression_ReadZip(string testFile) {
  8. double progress = 0;
  9. string output = Path.Combine(tempFolder, "Extracted");
  10. FileUtils.ExtractToDirectory(GetTestFile(testFile), output, p => progress = p);
  11. Assert.Equal(1, progress);
  12. Assert.True(DirectoryUtils.Exists(Path.Combine(output, "文件夹")));
  13. Assert.False(DirectoryUtils.Exists(Path.Combine(output, "空文件夹")));
  14. Assert.Contains("FabricLoader", File.ReadAllText(PathUtils.WithLongPath(Path.Combine(output, "fabricloader.log"))));
  15. Assert.Contains("测试内容", File.ReadAllText(PathUtils.WithLongPath(Path.Combine(output, "文件夹", "中文文件.txt"))));
  16. }
  17. [Theory]
  18. [InlineData("GZ.gz", "LTCat")]
  19. public void Compression_ReadGz(string testFile, string containsText) {
  20. double progress = 0;
  21. string output = Path.Combine(tempFolder, "Extracted");
  22. FileUtils.ExtractToDirectory(GetTestFile(testFile), output, p => progress = p);
  23. Assert.Equal(1, progress);
  24. Assert.Contains(containsText, File.ReadAllText(PathUtils.WithLongPath(Path.Combine(output, Path.GetFileNameWithoutExtension(testFile)))));
  25. }
  26. [Theory]
  27. [InlineData("Corrupted.zip")]
  28. [InlineData("Not zip.zip")]
  29. public void Compression_ReadBad(string testFile) {
  30. Assert.Throws<InvalidDataException>(() => FileUtils.ExtractToDirectory(GetTestFile(testFile), tempFolder));
  31. }
  32. #endregion
  33. /*
  34. *
  35. #region CreateZipFromDirectory 测试
  36. public void CreateZipFromDirectory_SingleFile_ZipContainsFile() {
  37. string srcDir = CreateSourceDirectory(("hello.txt", "hello world"));
  38. string outZip = Path.Combine(_tempDir, "from_dir.zip");
  39. FileUtils.CreateZipFromDirectory(outZip, srcDir);
  40. Assert.True(File.Exists(outZip));
  41. using var archive = ZipFile.OpenRead(outZip);
  42. Assert.Single(archive.Entries);
  43. Assert.Equal("hello.txt", archive.Entries[0].Name);
  44. }
  45. public void CreateZipFromDirectory_MultipleFiles_AllFilesIncluded() {
  46. string srcDir = CreateSourceDirectory(
  47. ("a.txt", "aaa"),
  48. ("b.txt", "bbb"),
  49. ("c.txt", "ccc"));
  50. string outZip = Path.Combine(_tempDir, "from_dir_multi.zip");
  51. FileUtils.CreateZipFromDirectory(outZip, srcDir);
  52. using var archive = ZipFile.OpenRead(outZip);
  53. Assert.Equal(3, archive.Entries.Count);
  54. }
  55. public void CreateZipFromDirectory_SubdirectoryFiles_StructurePreserved() {
  56. string srcDir = CreateSourceDirectory(
  57. ("sub/file.txt", "nested"),
  58. ("root.txt", "root"));
  59. string outZip = Path.Combine(_tempDir, "from_dir_sub.zip");
  60. FileUtils.CreateZipFromDirectory(outZip, srcDir);
  61. using var archive = ZipFile.OpenRead(outZip);
  62. var names = archive.Entries.Select(e => e.FullName.Replace('\\', '/')).ToList();
  63. Assert.Contains(names, n => n.Contains("sub/file.txt"));
  64. Assert.Contains(names, n => n.Contains("root.txt"));
  65. }
  66. public void CreateZipFromDirectory_OverwritesExistingZip() {
  67. string srcDir = CreateSourceDirectory(("new.txt", "new content"));
  68. string outZip = Path.Combine(_tempDir, "overwrite_dir.zip");
  69. // 先创建一个旧 zip
  70. string oldSrcDir = CreateSourceDirectory(("old.txt", "old content"));
  71. FileUtils.CreateZipFromDirectory(outZip, oldSrcDir);
  72. // 再用新目录覆盖
  73. FileUtils.CreateZipFromDirectory(outZip, srcDir);
  74. using var archive = ZipFile.OpenRead(outZip);
  75. Assert.Single(archive.Entries);
  76. Assert.Equal("new.txt", archive.Entries[0].Name);
  77. }
  78. public void CreateZipFromDirectory_OutputDirectoryAutoCreated() {
  79. string srcDir = CreateSourceDirectory(("f.txt", "x"));
  80. string outZip = Path.Combine(_tempDir, "newdir", "nested.zip");
  81. FileUtils.CreateZipFromDirectory(outZip, srcDir);
  82. Assert.True(File.Exists(outZip));
  83. }
  84. #endregion
  85. #region CreateZipFromFiles(params 版)测试
  86. public void CreateZipFromFiles_Params_SingleFile_ZipContainsFile() {
  87. string srcFile = Path.Combine(_tempDir, "single.txt");
  88. File.WriteAllText(srcFile, "content");
  89. string outZip = Path.Combine(_tempDir, "from_files_single.zip");
  90. FileUtils.CreateZipFromFiles(outZip, srcFile);
  91. using var archive = ZipFile.OpenRead(outZip);
  92. Assert.Single(archive.Entries);
  93. Assert.Equal("single.txt", archive.Entries[0].Name);
  94. }
  95. public void CreateZipFromFiles_Params_MultipleFiles_AllIncluded() {
  96. string file1 = Path.Combine(_tempDir, "f1.txt");
  97. string file2 = Path.Combine(_tempDir, "f2.txt");
  98. File.WriteAllText(file1, "1");
  99. File.WriteAllText(file2, "2");
  100. string outZip = Path.Combine(_tempDir, "from_files_multi.zip");
  101. FileUtils.CreateZipFromFiles(outZip, file1, file2);
  102. using var archive = ZipFile.OpenRead(outZip);
  103. Assert.Equal(2, archive.Entries.Count);
  104. var names = archive.Entries.Select(e => e.Name).ToHashSet();
  105. Assert.Contains("f1.txt", names);
  106. Assert.Contains("f2.txt", names);
  107. }
  108. public void CreateZipFromFiles_Params_DuplicateFileNames_ThrowsArgumentException() {
  109. string file1 = Path.Combine(_tempDir, "dup", "a", "same.txt");
  110. string file2 = Path.Combine(_tempDir, "dup", "b", "same.txt");
  111. Directory.CreateDirectory(Path.GetDirectoryName(file1)!);
  112. Directory.CreateDirectory(Path.GetDirectoryName(file2)!);
  113. File.WriteAllText(file1, "1");
  114. File.WriteAllText(file2, "2");
  115. string outZip = Path.Combine(_tempDir, "dup_names.zip");
  116. Assert.Throws<ArgumentException>(() => FileUtils.CreateZipFromFiles(outZip, file1, file2));
  117. }
  118. public void CreateZipFromFiles_Params_OverwritesExistingZip() {
  119. string oldFile = Path.Combine(_tempDir, "old.txt");
  120. string newFile = Path.Combine(_tempDir, "new.txt");
  121. File.WriteAllText(oldFile, "old");
  122. File.WriteAllText(newFile, "new");
  123. string outZip = Path.Combine(_tempDir, "overwrite_files.zip");
  124. FileUtils.CreateZipFromFiles(outZip, oldFile);
  125. FileUtils.CreateZipFromFiles(outZip, newFile);
  126. using var archive = ZipFile.OpenRead(outZip);
  127. Assert.Single(archive.Entries);
  128. Assert.Equal("new.txt", archive.Entries[0].Name);
  129. }
  130. #endregion
  131. #region CreateZipFromFiles(IDictionary 版)测试
  132. public void CreateZipFromFiles_Dict_CustomEntryPath_EntryNameMatchesDictKey() {
  133. string srcFile = Path.Combine(_tempDir, "source.txt");
  134. File.WriteAllText(srcFile, "data");
  135. string outZip = Path.Combine(_tempDir, "from_dict.zip");
  136. var sources = new Dictionary<string, string> {
  137. ["custom/path/file.txt"] = srcFile
  138. };
  139. FileUtils.CreateZipFromFiles(outZip, sources);
  140. using var archive = ZipFile.OpenRead(outZip);
  141. Assert.Single(archive.Entries);
  142. Assert.Equal("custom/path/file.txt", archive.Entries[0].FullName);
  143. }
  144. public void CreateZipFromFiles_Dict_MultipleEntries_AllIncluded() {
  145. string f1 = Path.Combine(_tempDir, "d1.txt");
  146. string f2 = Path.Combine(_tempDir, "d2.txt");
  147. File.WriteAllText(f1, "1");
  148. File.WriteAllText(f2, "2");
  149. string outZip = Path.Combine(_tempDir, "from_dict_multi.zip");
  150. var sources = new Dictionary<string, string> {
  151. ["a/one.txt"] = f1,
  152. ["b/two.txt"] = f2
  153. };
  154. FileUtils.CreateZipFromFiles(outZip, sources);
  155. using var archive = ZipFile.OpenRead(outZip);
  156. Assert.Equal(2, archive.Entries.Count);
  157. var fullNames = archive.Entries.Select(e => e.FullName).ToHashSet();
  158. Assert.Contains("a/one.txt", fullNames);
  159. Assert.Contains("b/two.txt", fullNames);
  160. }
  161. public void CreateZipFromFiles_Dict_FileContentPreserved() {
  162. const string expectedContent = "preserved content";
  163. string srcFile = Path.Combine(_tempDir, "preserve.txt");
  164. File.WriteAllText(srcFile, expectedContent, Encoding.UTF8);
  165. string outZip = Path.Combine(_tempDir, "from_dict_content.zip");
  166. var sources = new Dictionary<string, string> { ["entry.txt"] = srcFile };
  167. FileUtils.CreateZipFromFiles(outZip, sources);
  168. string outDir = Path.Combine(_tempDir, "dict_content_out");
  169. Directory.CreateDirectory(outDir);
  170. using var archive = ZipFile.OpenRead(outZip);
  171. using var entryStream = archive.Entries[0].Open();
  172. using var reader = new StreamReader(entryStream, Encoding.UTF8);
  173. Assert.Equal(expectedContent, reader.ReadToEnd());
  174. }
  175. public void CreateZipFromFiles_Dict_BackslashInKey_NormalizedToForwardSlash() {
  176. string srcFile = Path.Combine(_tempDir, "bs.txt");
  177. File.WriteAllText(srcFile, "x");
  178. string outZip = Path.Combine(_tempDir, "backslash.zip");
  179. var sources = new Dictionary<string, string> {
  180. [@"dir\sub\file.txt"] = srcFile
  181. };
  182. FileUtils.CreateZipFromFiles(outZip, sources);
  183. using var archive = ZipFile.OpenRead(outZip);
  184. // 条目路径中的反斜杠应被规范化为正斜杠
  185. Assert.Equal("dir/sub/file.txt", archive.Entries[0].FullName);
  186. }
  187. #endregion
  188. */
  189. }