|
|
using System.IO.Compression;
|
|
|
using GlennLib;
|
|
|
using SixLabors.ImageSharp;
|
|
|
using SixLabors.ImageSharp.Processing;
|
|
|
using UndertaleModLib;
|
|
|
using Xunit;
|
|
|
using Xunit.Abstractions;
|
|
|
|
|
|
namespace GlennLibTests;
|
|
|
|
|
|
public class RawModsTests : IDisposable
|
|
|
{
|
|
|
private readonly string testTempDir;
|
|
|
private readonly string libTempDir = Path.GetTempPath() + "/GlennPortHelper/";
|
|
|
private readonly ITestOutputHelper output;
|
|
|
|
|
|
public RawModsTests(ITestOutputHelper output)
|
|
|
{
|
|
|
Directory.CreateDirectory(libTempDir);
|
|
|
testTempDir = Path.GetTempPath() + Guid.NewGuid() + "/";
|
|
|
Directory.CreateDirectory(testTempDir);
|
|
|
this.output = output;
|
|
|
}
|
|
|
|
|
|
public void Dispose()
|
|
|
{
|
|
|
// Get rid of our test directory to not leave a huge mess
|
|
|
Directory.Delete(testTempDir, true);
|
|
|
}
|
|
|
|
|
|
#region GetModOSOfRawZipTests
|
|
|
|
|
|
[Theory]
|
|
|
[InlineData("./GameWin.zip", Core.ModOS.Windows)]
|
|
|
[InlineData("./GameLin.zip", Core.ModOS.Linux)]
|
|
|
[InlineData("./GameMac.zip", Core.ModOS.Mac)]
|
|
|
public void OSZipWithGoodRunnerShouldSucceed(string input, Core.ModOS os)
|
|
|
{
|
|
|
var result = RawMods.GetModOSOfRawZip(input);
|
|
|
Assert.True(result == os);
|
|
|
}
|
|
|
|
|
|
[Theory]
|
|
|
[InlineData("./GameLin.zip", "/runner")]
|
|
|
[InlineData("./GameMac.zip", "/AM2R.app/Contents/MacOS/Mac_Runner")]
|
|
|
public void UnixWithWrongRunnerShouldThrow(string input, string runnerSuffix)
|
|
|
{
|
|
|
var destinationZip = Path.GetTempPath() + Guid.NewGuid();
|
|
|
ZipFile.ExtractToDirectory(input, testTempDir);
|
|
|
File.Move(testTempDir + runnerSuffix, testTempDir + runnerSuffix + "_");
|
|
|
ZipFile.CreateFromDirectory(testTempDir, destinationZip);
|
|
|
Assert.Throws<NotSupportedException>(() => RawMods.GetModOSOfRawZip(destinationZip));
|
|
|
File.Delete(destinationZip);
|
|
|
}
|
|
|
|
|
|
[Fact]
|
|
|
public void WindowsZipWithDifferentRunnerShouldSucceed()
|
|
|
{
|
|
|
var destinationZip = Path.GetTempPath() + Guid.NewGuid() + ".zip";
|
|
|
ZipFile.ExtractToDirectory("./GameWin.zip", testTempDir);
|
|
|
File.Move(testTempDir + "/AM2R.exe", testTempDir + "/Game.exe");
|
|
|
ZipFile.CreateFromDirectory(testTempDir, destinationZip);
|
|
|
var result = RawMods.GetModOSOfRawZip(destinationZip);
|
|
|
Assert.True(result == Core.ModOS.Windows);
|
|
|
File.Delete(destinationZip);
|
|
|
}
|
|
|
|
|
|
[Fact]
|
|
|
public void WindowsZipWithTwoRunnersShouldThrow()
|
|
|
{
|
|
|
var destinationZip = Path.GetTempPath() + Guid.NewGuid();
|
|
|
ZipFile.ExtractToDirectory("./GameWin.zip", testTempDir);
|
|
|
File.Copy(testTempDir + "/AM2R.exe", testTempDir + "/Game.exe");
|
|
|
ZipFile.CreateFromDirectory(testTempDir, destinationZip);
|
|
|
Assert.Throws<NotSupportedException>(() => RawMods.GetModOSOfRawZip(destinationZip));
|
|
|
File.Delete(destinationZip);
|
|
|
}
|
|
|
|
|
|
[Theory]
|
|
|
[InlineData("./GameWin.zip", "/data.win")]
|
|
|
[InlineData("./GameLin.zip", "/assets/game.unx")]
|
|
|
[InlineData("./GameMac.zip", "/AM2R.app/Contents/Resources/game.ios")]
|
|
|
public void OSZipWithInvalidDataFileShouldThrow(string input, string dataSuffix)
|
|
|
{
|
|
|
var destinationZip = Path.GetTempPath() + Guid.NewGuid() + ".zip";
|
|
|
ZipFile.ExtractToDirectory(input, testTempDir);
|
|
|
File.Move(testTempDir + dataSuffix, testTempDir + dataSuffix + "_");
|
|
|
ZipFile.CreateFromDirectory(testTempDir, destinationZip);
|
|
|
Assert.Throws<NotSupportedException>(() => RawMods.GetModOSOfRawZip(destinationZip));
|
|
|
File.Delete(destinationZip);
|
|
|
}
|
|
|
|
|
|
#endregion
|
|
|
|
|
|
#region GetProperPathToBuiltinIcons
|
|
|
|
|
|
[Fact]
|
|
|
public void ExistingPathShouldReturnPath()
|
|
|
{
|
|
|
const string relative = "./GameLin.zip";
|
|
|
string absolute = new FileInfo(relative).FullName;
|
|
|
string result = RawMods.GetProperPathToBuiltinIcons(nameof(Resources.icon), relative);
|
|
|
Assert.True(result == relative);
|
|
|
result = RawMods.GetProperPathToBuiltinIcons(nameof(Resources.icon), absolute);
|
|
|
Assert.True(result == absolute);
|
|
|
}
|
|
|
|
|
|
[Fact]
|
|
|
public void NonExistantPathShouldReturnPathToResource()
|
|
|
{
|
|
|
string iconPath = libTempDir + "/" + nameof(Resources.icon) + ".png";
|
|
|
string result = RawMods.GetProperPathToBuiltinIcons(nameof(Resources.icon), null);
|
|
|
Assert.True(result == iconPath);
|
|
|
result = RawMods.GetProperPathToBuiltinIcons(nameof(Resources.icon), "/foo");
|
|
|
Assert.True(result == iconPath);
|
|
|
}
|
|
|
|
|
|
[Fact]
|
|
|
public void NonExistantResourceShouldThrow()
|
|
|
{
|
|
|
Assert.Throws<InvalidDataException>(() => RawMods.GetProperPathToBuiltinIcons("foo", null));
|
|
|
}
|
|
|
|
|
|
#endregion
|
|
|
|
|
|
#region PortToWindows
|
|
|
|
|
|
[Theory]
|
|
|
[InlineData("./GameWin.zip", false, false)]
|
|
|
[InlineData("./GameLin.zip", false, false)]
|
|
|
[InlineData("./GameMac.zip", false, false)]
|
|
|
[InlineData("./GameWin.zip", true, true)]
|
|
|
[InlineData("./GameLin.zip", true, true)]
|
|
|
[InlineData("./GameMac.zip", true, true)]
|
|
|
public void PortZipToWindows(string inputZip, bool useSubdirectories, bool createWorkingDirectoryBeforeHand)
|
|
|
{
|
|
|
var origMod = RawMods.GetModOSOfRawZip(inputZip);
|
|
|
var outputZip = testTempDir + Guid.NewGuid();
|
|
|
var origExtract = testTempDir + Guid.NewGuid();
|
|
|
var newExtract = testTempDir + Guid.NewGuid() + "/";
|
|
|
var deepSuffix = "Foobar/Foobar/Foo/Blag/";
|
|
|
var origInput = inputZip;
|
|
|
|
|
|
if (useSubdirectories)
|
|
|
{
|
|
|
string archiveDeepSuffix = deepSuffix;
|
|
|
if (origMod == Core.ModOS.Linux)
|
|
|
archiveDeepSuffix = "assets/" + deepSuffix;
|
|
|
else if (origMod == Core.ModOS.Mac)
|
|
|
archiveDeepSuffix = "AM2R.app/Contents/Resources/" + deepSuffix;
|
|
|
|
|
|
File.Copy(inputZip, testTempDir + inputZip + "_modified");
|
|
|
inputZip = testTempDir + inputZip + "_modified";
|
|
|
using ZipArchive archive = ZipFile.Open(inputZip, ZipArchiveMode.Update);
|
|
|
archive.CreateEntry(archiveDeepSuffix + origInput);
|
|
|
}
|
|
|
|
|
|
if (createWorkingDirectoryBeforeHand)
|
|
|
Directory.CreateDirectory(libTempDir + Path.GetFileNameWithoutExtension(inputZip));
|
|
|
|
|
|
RawMods.PortToWindows(inputZip, outputZip);
|
|
|
// Our function should see that its a windows zip
|
|
|
Assert.True(RawMods.GetModOSOfRawZip(outputZip) == Core.ModOS.Windows);
|
|
|
|
|
|
ZipFile.ExtractToDirectory(inputZip, origExtract);
|
|
|
ZipFile.ExtractToDirectory(outputZip, newExtract);
|
|
|
switch (origMod)
|
|
|
{
|
|
|
case Core.ModOS.Windows:
|
|
|
{
|
|
|
// File contents should be same between the zips
|
|
|
var origFiles = new DirectoryInfo(origExtract).GetFiles().Select(f => f.Name).ToList();
|
|
|
origFiles.Sort();
|
|
|
var newFiles = new DirectoryInfo(newExtract).GetFiles().Select(f => f.Name).ToList();
|
|
|
newFiles.Sort();
|
|
|
Assert.True(origFiles.SequenceEqual(newFiles));
|
|
|
break;
|
|
|
}
|
|
|
case Core.ModOS.Linux:
|
|
|
{
|
|
|
// File contents should be same between the zips except for runner+d3d.dll missing in original and data file being different
|
|
|
var origFiles = new DirectoryInfo(origExtract + "/assets").GetFiles().Select(f => f.Name).ToList();
|
|
|
origFiles.Remove("game.unx");
|
|
|
origFiles.Add("data.win");
|
|
|
origFiles.Add("AM2R.exe");
|
|
|
origFiles.Add("D3DX9_43.dll");
|
|
|
origFiles.Sort();
|
|
|
var newFiles = new DirectoryInfo(newExtract).GetFiles().Select(f => f.Name).ToList();
|
|
|
newFiles.Sort();
|
|
|
Assert.True(origFiles.SequenceEqual(newFiles));
|
|
|
break;
|
|
|
}
|
|
|
case Core.ModOS.Mac:
|
|
|
{
|
|
|
// File contents should be the same between the zips except for runner+d3d.dll missing in original, data file being different and extra mac files
|
|
|
var origFiles = new DirectoryInfo(origExtract + "/AM2R.app/Contents/Resources").GetFiles().Select(f => f.Name).ToList();
|
|
|
origFiles.Remove("game.ios");
|
|
|
origFiles.Add("data.win");
|
|
|
origFiles.Add("AM2R.exe");
|
|
|
origFiles.Add("D3DX9_43.dll");
|
|
|
origFiles.Remove("gamecontrollerdb.txt");
|
|
|
origFiles.Remove("yoyorunner.config");
|
|
|
origFiles.Sort();
|
|
|
var newFiles = new DirectoryInfo(newExtract).GetFiles().Select(f => f.Name).ToList();
|
|
|
newFiles.Sort();
|
|
|
Assert.True(origFiles.SequenceEqual(newFiles));
|
|
|
break;
|
|
|
}
|
|
|
default: throw new Exception("unwritten test case for new os?");
|
|
|
}
|
|
|
|
|
|
// If we didn't specify any, there should be no subdirectories at the end
|
|
|
if (!useSubdirectories)
|
|
|
{
|
|
|
Assert.Empty(new DirectoryInfo(newExtract).GetDirectories());
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
//Otherwise there should be our stuff
|
|
|
Assert.True(File.Exists(newExtract + deepSuffix + origInput));
|
|
|
}
|
|
|
#endregion
|
|
|
|
|
|
#region PortToLinux
|
|
|
|
|
|
[Theory]
|
|
|
[InlineData("./GameWin.zip", false, false)]
|
|
|
[InlineData("./GameLin.zip", false, false)]
|
|
|
[InlineData("./GameMac.zip", false, false)]
|
|
|
[InlineData("./GameWin.zip", true, true)]
|
|
|
[InlineData("./GameLin.zip", true, true)]
|
|
|
[InlineData("./GameMac.zip", true, true)]
|
|
|
public void PortZipToLinux(string inputZip, bool useSubdirectories, bool createWorkingDirectoryBeforeHand)
|
|
|
{
|
|
|
var origMod = RawMods.GetModOSOfRawZip(inputZip);
|
|
|
var outputZip = testTempDir + Guid.NewGuid();
|
|
|
var origExtract = testTempDir + Guid.NewGuid();
|
|
|
var newExtract = testTempDir + Guid.NewGuid() + "/";
|
|
|
var deepSuffix = "Foobar/Foobar/Foo/Blag/";
|
|
|
var origInput = inputZip;
|
|
|
|
|
|
if (useSubdirectories)
|
|
|
{
|
|
|
string archiveDeepSuffix = deepSuffix;
|
|
|
if (origMod == Core.ModOS.Linux)
|
|
|
archiveDeepSuffix = "assets/" + deepSuffix.ToLower();
|
|
|
else if (origMod == Core.ModOS.Mac)
|
|
|
archiveDeepSuffix = "AM2R.app/Contents/Resources/" + deepSuffix;
|
|
|
|
|
|
File.Copy(inputZip, testTempDir + inputZip.ToLower() + "_modified");
|
|
|
inputZip = testTempDir + inputZip.ToLower() + "_modified";
|
|
|
using ZipArchive archive = ZipFile.Open(inputZip, ZipArchiveMode.Update);
|
|
|
archive.CreateEntry(archiveDeepSuffix + origInput.ToLower());
|
|
|
}
|
|
|
|
|
|
if (createWorkingDirectoryBeforeHand)
|
|
|
Directory.CreateDirectory(libTempDir + Path.GetFileNameWithoutExtension(inputZip));
|
|
|
|
|
|
RawMods.PortToLinux(inputZip, outputZip);
|
|
|
// Our function should see that its a linux zip
|
|
|
Assert.True(RawMods.GetModOSOfRawZip(outputZip) == Core.ModOS.Linux);
|
|
|
|
|
|
ZipFile.ExtractToDirectory(inputZip, origExtract);
|
|
|
ZipFile.ExtractToDirectory(outputZip, newExtract);
|
|
|
switch (origMod)
|
|
|
{
|
|
|
case Core.ModOS.Windows:
|
|
|
{
|
|
|
// File contents should be same between the zips except for old runner+d3d.dll, new splash+icon,
|
|
|
// files being lowered and data file being different
|
|
|
var origFiles = new DirectoryInfo(origExtract).GetFiles().Select(f => f.Name.ToLower()).ToList();
|
|
|
origFiles.Remove("am2r.exe");
|
|
|
origFiles.Remove("d3dx9_43.dll");
|
|
|
origFiles.Add("splash.png");
|
|
|
origFiles.Add("icon.png");
|
|
|
origFiles.Remove("data.win");
|
|
|
origFiles.Add("game.unx");
|
|
|
origFiles.Sort();
|
|
|
var newFiles = new DirectoryInfo(newExtract + "/assets").GetFiles().Select(f => f.Name).ToList();
|
|
|
newFiles.Sort();
|
|
|
Assert.True(origFiles.SequenceEqual(newFiles));
|
|
|
break;
|
|
|
}
|
|
|
case Core.ModOS.Linux:
|
|
|
{
|
|
|
// File contents should be same between the zips
|
|
|
var origFiles = new DirectoryInfo(origExtract + "/assets").GetFiles().Select(f => f.Name).ToList();
|
|
|
origFiles.Sort();
|
|
|
var newFiles = new DirectoryInfo(newExtract + "/assets").GetFiles().Select(f => f.Name).ToList();
|
|
|
newFiles.Sort();
|
|
|
Assert.True(origFiles.SequenceEqual(newFiles));
|
|
|
break;
|
|
|
}
|
|
|
case Core.ModOS.Mac:
|
|
|
{
|
|
|
// File contents should be the same between the zips except for data file being different and extra mac files
|
|
|
var origFiles = new DirectoryInfo(origExtract + "/AM2R.app/Contents/Resources").GetFiles().Select(f => f.Name).ToList();
|
|
|
origFiles.Remove("game.ios");
|
|
|
origFiles.Add("game.unx");
|
|
|
origFiles.Remove("gamecontrollerdb.txt");
|
|
|
origFiles.Remove("yoyorunner.config");
|
|
|
origFiles.Sort();
|
|
|
var newFiles = new DirectoryInfo(newExtract + "/assets").GetFiles().Select(f => f.Name).ToList();
|
|
|
newFiles.Sort();
|
|
|
Assert.True(origFiles.SequenceEqual(newFiles));
|
|
|
break;
|
|
|
}
|
|
|
default: throw new Exception("unwritten test case for new os?");
|
|
|
}
|
|
|
|
|
|
// There should be exactly one subdir here
|
|
|
Assert.Single(new DirectoryInfo(newExtract).GetDirectories());
|
|
|
|
|
|
// If we didn't specify any, there should no more subdirs after that at the end
|
|
|
if (!useSubdirectories)
|
|
|
{
|
|
|
Assert.Empty(new DirectoryInfo(newExtract + "/assets").GetDirectories());
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
//Otherwise there should be our stuff
|
|
|
Assert.True(File.Exists(newExtract + "/assets/" + deepSuffix.ToLower() + origInput.ToLower()));
|
|
|
}
|
|
|
|
|
|
#endregion
|
|
|
|
|
|
#region PortToMac
|
|
|
|
|
|
[Theory]
|
|
|
[InlineData("./GameWin.zip", false, false, false)]
|
|
|
[InlineData("./GameLin.zip", false, false, false)]
|
|
|
[InlineData("./GameMac.zip", false, false, false)]
|
|
|
[InlineData("./GameWin.zip", true, true, true)]
|
|
|
[InlineData("./GameLin.zip", true, true, true)]
|
|
|
[InlineData("./GameMac.zip", true, true, true)]
|
|
|
public void PortZipToMac(string inputZip, bool useSubdirectories, bool createWorkingDirectoryBeforeHand, bool testFontsFolder)
|
|
|
{
|
|
|
var origMod = RawMods.GetModOSOfRawZip(inputZip);
|
|
|
var outputZip = testTempDir + Guid.NewGuid();
|
|
|
var origExtract = testTempDir + Guid.NewGuid();
|
|
|
var newExtract = testTempDir + Guid.NewGuid() + "/";
|
|
|
var deepSuffix = "Foobar/Foobar/Foo/Blag/";
|
|
|
var origInput = inputZip;
|
|
|
|
|
|
if (testFontsFolder && origMod != Core.ModOS.Mac)
|
|
|
{
|
|
|
string assetsDir = "";
|
|
|
if (origMod == Core.ModOS.Linux)
|
|
|
assetsDir = "assets/";
|
|
|
|
|
|
File.Copy(inputZip, testTempDir + inputZip.ToLower().Replace(testTempDir, "") + "_modified");
|
|
|
inputZip = testTempDir + inputZip.ToLower().Replace(testTempDir, "") + "_modified";
|
|
|
using ZipArchive archive = ZipFile.Open(inputZip, ZipArchiveMode.Update);
|
|
|
archive.CreateEntry(assetsDir + "lang/fonts/");
|
|
|
}
|
|
|
|
|
|
if (useSubdirectories)
|
|
|
{
|
|
|
string archiveDeepSuffix = deepSuffix;
|
|
|
if (origMod == Core.ModOS.Linux)
|
|
|
archiveDeepSuffix = "assets/" + deepSuffix;
|
|
|
else if (origMod == Core.ModOS.Mac)
|
|
|
archiveDeepSuffix = "AM2R.app/Contents/Resources/" + deepSuffix.ToLower();
|
|
|
|
|
|
File.Copy(inputZip, testTempDir + inputZip.Replace(testTempDir, "") + "_modified");
|
|
|
inputZip = testTempDir + inputZip.Replace(testTempDir, "") + "_modified";
|
|
|
using ZipArchive archive = ZipFile.Open(inputZip, ZipArchiveMode.Update);
|
|
|
archive.CreateEntry(archiveDeepSuffix + origInput.ToLower());
|
|
|
}
|
|
|
|
|
|
if (createWorkingDirectoryBeforeHand)
|
|
|
Directory.CreateDirectory(libTempDir + Path.GetFileNameWithoutExtension(inputZip));
|
|
|
|
|
|
RawMods.PortToMac(inputZip, outputZip);
|
|
|
|
|
|
// Our function should see that its a mac zip
|
|
|
Assert.True(RawMods.GetModOSOfRawZip(outputZip) == Core.ModOS.Mac);
|
|
|
|
|
|
ZipFile.ExtractToDirectory(inputZip, origExtract);
|
|
|
ZipFile.ExtractToDirectory(outputZip, newExtract);
|
|
|
var appDir = new DirectoryInfo(newExtract).GetDirectories().First(n => n.Name.EndsWith(".app"));
|
|
|
|
|
|
// Confirm via UTMT that it is indeed BC16
|
|
|
using (FileStream fs = new FileInfo(appDir.FullName + "/Contents/Resources/game.ios").OpenRead())
|
|
|
{
|
|
|
UndertaleData gmData = UndertaleIO.Read(fs);
|
|
|
Assert.Equal(16, gmData.GeneralInfo.BytecodeVersion);
|
|
|
}
|
|
|
|
|
|
switch (origMod)
|
|
|
{
|
|
|
case Core.ModOS.Windows:
|
|
|
{
|
|
|
// File contents should be same between the zips except for old runner+d3d.dll, new splash+icon,
|
|
|
// files being lowercase, data file being different a new gamecontrollerdb and a new yoyorunner.config
|
|
|
var origFiles = new DirectoryInfo(origExtract).GetFiles().Select(f => f.Name.ToLower()).ToList();
|
|
|
origFiles.Remove("am2r.exe");
|
|
|
origFiles.Remove("d3dx9_43.dll");
|
|
|
origFiles.Add("splash.png");
|
|
|
origFiles.Add("icon.png");
|
|
|
origFiles.Remove("data.win");
|
|
|
origFiles.Add("game.ios");
|
|
|
origFiles.Add("gamecontrollerdb.txt");
|
|
|
origFiles.Add("yoyorunner.config");
|
|
|
origFiles.Sort();
|
|
|
var newFiles = new DirectoryInfo(appDir.FullName + "/Contents/Resources").GetFiles().Select(f => f.Name).ToList();
|
|
|
newFiles.Sort();
|
|
|
Assert.True(origFiles.SequenceEqual(newFiles));
|
|
|
break;
|
|
|
}
|
|
|
case Core.ModOS.Linux:
|
|
|
{
|
|
|
// File contents should be same between the zips except for all files being lowercase, data file being different and mac specific files
|
|
|
var origFiles = new DirectoryInfo(origExtract + "/assets").GetFiles().Select(f => f.Name.ToLower()).ToList();
|
|
|
origFiles.Remove("game.unx");
|
|
|
origFiles.Add("game.ios");
|
|
|
origFiles.Add("gamecontrollerdb.txt");
|
|
|
origFiles.Add("yoyorunner.config");
|
|
|
origFiles.Sort();
|
|
|
var newFiles = new DirectoryInfo(newExtract + "/" + appDir.Name + "/Contents/Resources").GetFiles().Select(f => f.Name).ToList();
|
|
|
newFiles.Sort();
|
|
|
Assert.True(origFiles.SequenceEqual(newFiles));
|
|
|
break;
|
|
|
}
|
|
|
case Core.ModOS.Mac:
|
|
|
{
|
|
|
// File contents should be same between the zips
|
|
|
var origFiles = new DirectoryInfo(origExtract + "/" + appDir.Name + "/Contents/Resources").GetFiles().Select(f => f.Name).ToList();
|
|
|
origFiles.Sort();
|
|
|
var newFiles = new DirectoryInfo(newExtract + "/" + appDir.Name + "/Contents/Resources").GetFiles().Select(f => f.Name).ToList();
|
|
|
newFiles.Sort();
|
|
|
Assert.True(origFiles.SequenceEqual(newFiles));
|
|
|
break;
|
|
|
}
|
|
|
default: throw new Exception("unwritten test case for new os?");
|
|
|
}
|
|
|
|
|
|
// There should be exactly one subdir here and it should end with .app
|
|
|
Assert.Single(new DirectoryInfo(newExtract).GetDirectories());
|
|
|
Assert.EndsWith(".app", new DirectoryInfo(newExtract).GetDirectories().First().Name);
|
|
|
Assert.Equal("English.lproj", new DirectoryInfo(newExtract + "/" + appDir.Name + "/Contents/Resources").GetDirectories().First(d => d.Name == "English.lproj").Name);
|
|
|
|
|
|
// If we didn't specify any, there should two more subdirs after that at the end (the English.lproj, lang)
|
|
|
// fonts directory in lang should not exist anymore!
|
|
|
|
|
|
Assert.True(new DirectoryInfo(newExtract + "/" + appDir.Name + "/Contents/Resources/English.lproj").Exists);
|
|
|
Assert.False(new DirectoryInfo(newExtract + "/" + appDir.Name + "/Contents/Resources/lang/fonts").Exists);
|
|
|
|
|
|
if (!useSubdirectories)
|
|
|
return;
|
|
|
|
|
|
// Otherwise there should be also our stuff
|
|
|
Assert.True(File.Exists(newExtract + "/" + appDir.Name + "/Contents/Resources/" + deepSuffix.ToLower() + origInput.ToLower()));
|
|
|
}
|
|
|
|
|
|
#endregion
|
|
|
|
|
|
#region PortInvalidZips
|
|
|
|
|
|
[Theory]
|
|
|
[InlineData(Core.ModOS.Windows)]
|
|
|
[InlineData(Core.ModOS.Linux)]
|
|
|
[InlineData(Core.ModOS.Mac)]
|
|
|
[InlineData(Core.ModOS.Android)]
|
|
|
public void PortInvalidZipsToOS(Core.ModOS os)
|
|
|
{
|
|
|
Action<string?, string?> function = os switch
|
|
|
{
|
|
|
Core.ModOS.Windows => (input, outputFile) => RawMods.PortToWindows(input, outputFile),
|
|
|
Core.ModOS.Linux => (input, outputFile) => RawMods.PortToLinux(input, outputFile),
|
|
|
Core.ModOS.Mac => (input, outputFile) => RawMods.PortToMac(input, outputFile),
|
|
|
Core.ModOS.Android => (input, outputFile) => RawMods.PortToAndroid(input, outputFile),
|
|
|
_ => throw new Exception("This should not have happened! new unhandled data!")
|
|
|
};
|
|
|
|
|
|
Assert.Throws<ArgumentNullException>(() => function.Invoke(null, "/foo"));
|
|
|
Assert.Throws<FileNotFoundException>(() => function.Invoke("/foo", "/foo"));
|
|
|
Assert.Throws<ArgumentOutOfRangeException>(() => function.Invoke("./GameLin.zip", null));
|
|
|
|
|
|
}
|
|
|
|
|
|
#endregion
|
|
|
|
|
|
#region PortToAndroid
|
|
|
|
|
|
[Theory]
|
|
|
[InlineData("./GameWin.zip", false, false, false, false)]
|
|
|
[InlineData("./GameLin.zip", false, false, false, false)]
|
|
|
[InlineData("./GameMac.zip", false, false, false, false)]
|
|
|
[InlineData("./GameWin.zip", true, true, true, true)]
|
|
|
[InlineData("./GameLin.zip", true, true, true, true)]
|
|
|
[InlineData("./GameMac.zip", true, true, true, true)]
|
|
|
public void PortZipToAndroid(string inputZip, bool useSubdirectories, bool createWorkingDirectoryBeforeHand, bool useCustomSave, bool useInternet)
|
|
|
{
|
|
|
var origMod = RawMods.GetModOSOfRawZip(inputZip);
|
|
|
var outputZip = testTempDir + Guid.NewGuid();
|
|
|
var origExtract = testTempDir + Guid.NewGuid();
|
|
|
var newExtract = testTempDir + Guid.NewGuid() + "/";
|
|
|
var deepSuffix = "Foobar/Foobar/Foo/Blag/";
|
|
|
var origInput = inputZip;
|
|
|
|
|
|
if (useSubdirectories)
|
|
|
{
|
|
|
string archiveDeepSuffix = deepSuffix;
|
|
|
if (origMod == Core.ModOS.Linux)
|
|
|
archiveDeepSuffix = "assets/" + deepSuffix;
|
|
|
else if (origMod == Core.ModOS.Mac)
|
|
|
archiveDeepSuffix = "AM2R.app/Contents/Resources/" + deepSuffix;
|
|
|
|
|
|
File.Copy(inputZip, testTempDir + inputZip + "_modified");
|
|
|
inputZip = testTempDir + inputZip + "_modified";
|
|
|
using ZipArchive archive = ZipFile.Open(inputZip, ZipArchiveMode.Update);
|
|
|
archive.CreateEntry(archiveDeepSuffix + origInput);
|
|
|
}
|
|
|
|
|
|
if (createWorkingDirectoryBeforeHand)
|
|
|
Directory.CreateDirectory(libTempDir + Path.GetFileNameWithoutExtension(inputZip));
|
|
|
|
|
|
RawMods.PortToAndroid(inputZip, outputZip, null, null, useCustomSave, useInternet);
|
|
|
|
|
|
// HACK: STORE'd files aren't compressed, thus the compressed size is the same as the normal
|
|
|
using (var archive = ZipFile.OpenRead(outputZip))
|
|
|
{
|
|
|
var entry = archive.GetEntry("assets/coolsong.ogg");
|
|
|
Assert.Equal(entry.Length, entry.CompressedLength);
|
|
|
}
|
|
|
|
|
|
ZipFile.ExtractToDirectory(inputZip, origExtract);
|
|
|
ZipFile.ExtractToDirectory(outputZip, newExtract);
|
|
|
switch (origMod)
|
|
|
{
|
|
|
case Core.ModOS.Windows:
|
|
|
{
|
|
|
// File contents should be same between the zips except for all files being lowered now, data file being different, runner+dll not existing now, and splash being new
|
|
|
var origFiles = new DirectoryInfo(origExtract).GetFiles().Select(f => f.Name.ToLower()).ToList();
|
|
|
origFiles.Remove("am2r.exe");
|
|
|
origFiles.Remove("d3dx9_43.dll");
|
|
|
origFiles.Remove("data.win");
|
|
|
origFiles.Add("game.droid");
|
|
|
origFiles.Remove("am2r.exe");
|
|
|
origFiles.Add("splash.png");
|
|
|
origFiles.Sort();
|
|
|
var newFiles = new DirectoryInfo(newExtract + "/assets").GetFiles().Select(f => f.Name).ToList();
|
|
|
newFiles.Sort();
|
|
|
Assert.True(origFiles.SequenceEqual(newFiles));
|
|
|
break;
|
|
|
}
|
|
|
case Core.ModOS.Linux:
|
|
|
{
|
|
|
// File contents should be same between the zips except for data file being different
|
|
|
var origFiles = new DirectoryInfo(origExtract + "/assets").GetFiles().Select(f => f.Name).ToList();
|
|
|
origFiles.Remove("game.unx");
|
|
|
origFiles.Add("game.droid");
|
|
|
origFiles.Sort();
|
|
|
var newFiles = new DirectoryInfo(newExtract + "/assets").GetFiles().Select(f => f.Name).ToList();
|
|
|
newFiles.Sort();
|
|
|
Assert.True(origFiles.SequenceEqual(newFiles));
|
|
|
break;
|
|
|
}
|
|
|
case Core.ModOS.Mac:
|
|
|
{
|
|
|
// File contents should be the same between the zips except for data file being different and extra mac files
|
|
|
var origFiles = new DirectoryInfo(origExtract + "/AM2R.app/Contents/Resources").GetFiles().Select(f => f.Name).ToList();
|
|
|
origFiles.Remove("game.ios");
|
|
|
origFiles.Add("game.droid");
|
|
|
origFiles.Remove("gamecontrollerdb.txt");
|
|
|
origFiles.Remove("yoyorunner.config");
|
|
|
origFiles.Sort();
|
|
|
var newFiles = new DirectoryInfo(newExtract + "/assets").GetFiles().Select(f => f.Name).ToList();
|
|
|
newFiles.Sort();
|
|
|
Assert.True(origFiles.SequenceEqual(newFiles));
|
|
|
break;
|
|
|
}
|
|
|
default: throw new Exception("unwritten test case for new os?");
|
|
|
}
|
|
|
|
|
|
// TODO: check save folder - probably needs to be done by decompiling again. If one does this, then the "useInternet" check below should also get redone
|
|
|
if (useCustomSave)
|
|
|
{
|
|
|
}
|
|
|
|
|
|
// HACK: ugly af, but works
|
|
|
if (useInternet)
|
|
|
{
|
|
|
// TODO: reimplement this properly
|
|
|
/*Assert.Contains(" |