2019-09-24 04:20:24 +00:00
|
|
|
|
using System;
|
|
|
|
|
using System.Collections.Generic;
|
|
|
|
|
using System.Collections.Specialized;
|
|
|
|
|
using System.IO;
|
|
|
|
|
using System.IO.Compression;
|
|
|
|
|
using System.Linq;
|
|
|
|
|
using System.Security.Cryptography;
|
|
|
|
|
using System.Text;
|
|
|
|
|
using System.Threading.Tasks;
|
2019-10-29 21:30:27 +00:00
|
|
|
|
using Alphaleonis.Win32.Filesystem;
|
2019-09-24 04:20:24 +00:00
|
|
|
|
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
|
|
|
|
using Wabbajack.Common;
|
|
|
|
|
using Directory = Alphaleonis.Win32.Filesystem.Directory;
|
|
|
|
|
using File = Alphaleonis.Win32.Filesystem.File;
|
2019-10-29 21:30:27 +00:00
|
|
|
|
using FileInfo = Alphaleonis.Win32.Filesystem.FileInfo;
|
2019-09-24 04:20:24 +00:00
|
|
|
|
using Path = Alphaleonis.Win32.Filesystem.Path;
|
|
|
|
|
|
|
|
|
|
namespace Wabbajack.Test
|
|
|
|
|
{
|
|
|
|
|
public class TestUtils : IDisposable
|
|
|
|
|
{
|
|
|
|
|
public TestUtils()
|
|
|
|
|
{
|
|
|
|
|
RNG = new Random();
|
|
|
|
|
ID = RandomName();
|
|
|
|
|
WorkingDirectory = Path.Combine(Directory.GetCurrentDirectory(), "tmp_data");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public string WorkingDirectory { get;}
|
|
|
|
|
public string ID { get; }
|
|
|
|
|
public Random RNG { get; }
|
|
|
|
|
|
2019-11-16 22:02:36 +00:00
|
|
|
|
public Game Game { get; set; }
|
2019-09-24 04:20:24 +00:00
|
|
|
|
|
|
|
|
|
public string TestFolder => Path.Combine(WorkingDirectory, ID);
|
|
|
|
|
public string GameFolder => Path.Combine(WorkingDirectory, ID, "game_folder");
|
|
|
|
|
|
|
|
|
|
public string MO2Folder => Path.Combine(WorkingDirectory, ID, "mo2_folder");
|
|
|
|
|
public string ModsFolder => Path.Combine(MO2Folder, "mods");
|
|
|
|
|
public string DownloadsFolder => Path.Combine(MO2Folder, "downloads");
|
|
|
|
|
|
|
|
|
|
public string InstallFolder => Path.Combine(TestFolder, "installed");
|
|
|
|
|
|
2019-11-16 21:29:05 +00:00
|
|
|
|
public HashSet<string> Profiles = new HashSet<string>();
|
|
|
|
|
|
|
|
|
|
public List<string> Mods = new List<string>();
|
2019-09-24 04:20:24 +00:00
|
|
|
|
|
|
|
|
|
public void Configure()
|
|
|
|
|
{
|
|
|
|
|
File.WriteAllLines(Path.Combine(MO2Folder, "ModOrganizer.ini"), new []
|
|
|
|
|
{
|
|
|
|
|
"[General]",
|
2019-11-16 22:02:36 +00:00
|
|
|
|
$"gameName={GameRegistry.Games[this.Game].MO2Name}",
|
2019-09-24 04:20:24 +00:00
|
|
|
|
$"gamePath={GameFolder.Replace("\\", "\\\\")}",
|
2019-11-04 04:36:25 +00:00
|
|
|
|
$"download_directory={DownloadsFolder}"
|
2019-09-24 04:20:24 +00:00
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
Directory.CreateDirectory(DownloadsFolder);
|
2019-11-02 21:08:37 +00:00
|
|
|
|
Directory.CreateDirectory(Path.Combine(GameFolder, "Data"));
|
2019-09-24 04:20:24 +00:00
|
|
|
|
|
|
|
|
|
Profiles.Do(profile =>
|
|
|
|
|
{
|
|
|
|
|
File.WriteAllLines(Path.Combine(MO2Folder, "profiles", profile, "modlist.txt"),
|
|
|
|
|
Mods.Select(s => $"+{s}").ToArray());
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
2019-10-28 03:15:48 +00:00
|
|
|
|
public string AddProfile(string name = null)
|
2019-09-24 04:20:24 +00:00
|
|
|
|
{
|
2019-10-28 03:15:48 +00:00
|
|
|
|
string profile_name = name ?? RandomName();
|
2019-09-24 04:20:24 +00:00
|
|
|
|
Directory.CreateDirectory(Path.Combine(MO2Folder, "profiles", profile_name));
|
|
|
|
|
Profiles.Add(profile_name);
|
|
|
|
|
return profile_name;
|
|
|
|
|
}
|
|
|
|
|
|
2019-10-28 03:15:48 +00:00
|
|
|
|
public string AddMod(string name = null)
|
2019-09-24 04:20:24 +00:00
|
|
|
|
{
|
2019-10-28 03:15:48 +00:00
|
|
|
|
string mod_name = name ?? RandomName();
|
2019-10-31 02:24:42 +00:00
|
|
|
|
var mod_folder = Path.Combine(MO2Folder, "mods", mod_name);
|
|
|
|
|
Directory.CreateDirectory(mod_folder);
|
|
|
|
|
File.WriteAllText(Path.Combine(mod_folder, "meta.ini"), "[General]");
|
2019-09-24 04:20:24 +00:00
|
|
|
|
Mods.Add(mod_name);
|
|
|
|
|
return mod_name;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Adds a file to the given mod with a given path in the mod. Fills it with random data unless
|
|
|
|
|
/// random_fill == 0;
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="mod_name"></param>
|
|
|
|
|
/// <param name="path"></param>
|
|
|
|
|
/// <param name="random_fill"></param>
|
|
|
|
|
/// <returns></returns>
|
|
|
|
|
public string AddModFile(string mod_name, string path, int random_fill=128)
|
2019-11-02 21:08:37 +00:00
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
var full_path = Path.Combine(ModsFolder, mod_name, path);
|
|
|
|
|
Directory.CreateDirectory(Path.GetDirectoryName(full_path));
|
|
|
|
|
|
|
|
|
|
GenerateRandomFileData(full_path, random_fill);
|
|
|
|
|
return full_path;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public void GenerateRandomFileData(string full_path, int random_fill)
|
2019-09-24 04:20:24 +00:00
|
|
|
|
{
|
|
|
|
|
byte[] bytes = new byte[0];
|
|
|
|
|
if (random_fill != 0)
|
|
|
|
|
{
|
|
|
|
|
bytes = new byte[random_fill];
|
|
|
|
|
RNG.NextBytes(bytes);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
File.WriteAllBytes(full_path, bytes);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public void Dispose()
|
|
|
|
|
{
|
|
|
|
|
var exts = new [] {".md", ".exe"};
|
|
|
|
|
Directory.Delete(Path.Combine(WorkingDirectory, ID), true);
|
|
|
|
|
Profiles.Do(p =>
|
|
|
|
|
{
|
|
|
|
|
foreach (var ext in exts) {
|
|
|
|
|
var path = Path.Combine(Directory.GetCurrentDirectory(), p + ext);
|
|
|
|
|
if (File.Exists(path))
|
|
|
|
|
File.Delete(path);
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Returns a random string name (with spaces)
|
|
|
|
|
/// </summary>
|
|
|
|
|
public string RandomName()
|
|
|
|
|
{
|
|
|
|
|
return Guid.NewGuid().ToString();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public string AddManualDownload(Dictionary<string, byte[]> contents)
|
|
|
|
|
{
|
|
|
|
|
var name = RandomName() + ".zip";
|
|
|
|
|
|
|
|
|
|
using(FileStream fs = new FileStream(Path.Combine(DownloadsFolder, name), FileMode.Create))
|
|
|
|
|
using (ZipArchive archive = new ZipArchive(fs, ZipArchiveMode.Create))
|
|
|
|
|
{
|
|
|
|
|
contents.Do(kv =>
|
|
|
|
|
{
|
|
|
|
|
var entry = archive.CreateEntry(kv.Key);
|
|
|
|
|
using (var os = entry.Open())
|
|
|
|
|
os.Write(kv.Value, 0, kv.Value.Length);
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
File.WriteAllLines(Path.Combine(DownloadsFolder, name+".meta"),
|
|
|
|
|
|
|
|
|
|
new string[]
|
|
|
|
|
{
|
|
|
|
|
"[General]",
|
|
|
|
|
"manualURL=<TESTING>"
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
return name;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public void VerifyInstalledFile(string mod, string file)
|
|
|
|
|
{
|
|
|
|
|
var src = Path.Combine(MO2Folder, "mods", mod, file);
|
|
|
|
|
Assert.IsTrue(File.Exists(src), src);
|
|
|
|
|
|
|
|
|
|
var dest = Path.Combine(InstallFolder, "mods", mod, file);
|
|
|
|
|
Assert.IsTrue(File.Exists(dest), dest);
|
|
|
|
|
|
|
|
|
|
var src_data = File.ReadAllBytes(src);
|
|
|
|
|
var dest_data = File.ReadAllBytes(dest);
|
|
|
|
|
|
|
|
|
|
Assert.AreEqual(src_data.Length, dest_data.Length);
|
|
|
|
|
|
|
|
|
|
for(int x = 0; x < src_data.Length; x++)
|
|
|
|
|
{
|
|
|
|
|
if (src_data[x] != dest_data[x])
|
|
|
|
|
Assert.Fail($"Index {x} of {mod}\\{file} are not the same");
|
|
|
|
|
}
|
|
|
|
|
}
|
2019-10-29 21:30:27 +00:00
|
|
|
|
|
|
|
|
|
public void VerifyAllFiles()
|
|
|
|
|
{
|
|
|
|
|
foreach (var dest_file in Directory.EnumerateFiles(InstallFolder, "*", DirectoryEnumerationOptions.Recursive))
|
|
|
|
|
{
|
|
|
|
|
var rel_file = dest_file.RelativeTo(InstallFolder);
|
|
|
|
|
if (rel_file.StartsWith(Consts.LOOTFolderFilesDir) || rel_file.StartsWith(Consts.GameFolderFilesDir))
|
|
|
|
|
continue;
|
|
|
|
|
Assert.IsTrue(File.Exists(Path.Combine(MO2Folder, rel_file)), $"Only in Destination: {rel_file}");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var skip_extensions = new HashSet<string> {".txt", ".ini"};
|
|
|
|
|
|
|
|
|
|
foreach (var src_file in Directory.EnumerateFiles(MO2Folder, "*", DirectoryEnumerationOptions.Recursive))
|
|
|
|
|
{
|
|
|
|
|
var rel_file = src_file.RelativeTo(MO2Folder);
|
|
|
|
|
|
|
|
|
|
if (rel_file.StartsWith("downloads\\"))
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
var dest_file = Path.Combine(InstallFolder, rel_file);
|
|
|
|
|
Assert.IsTrue(File.Exists(dest_file), $"Only in Source: {rel_file}");
|
|
|
|
|
|
|
|
|
|
var fi_src = new FileInfo(src_file);
|
|
|
|
|
var fi_dest = new FileInfo(dest_file);
|
|
|
|
|
|
|
|
|
|
if (!skip_extensions.Contains(Path.GetExtension(src_file)))
|
|
|
|
|
{
|
|
|
|
|
Assert.AreEqual(fi_src.Length, fi_dest.Length, $"Differing sizes {rel_file}");
|
2019-10-31 03:40:33 +00:00
|
|
|
|
Assert.AreEqual(src_file.FileHash(), dest_file.FileHash(), $"Differing content hash {rel_file}");
|
2019-10-29 21:30:27 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2019-09-24 04:20:24 +00:00
|
|
|
|
}
|
|
|
|
|
}
|