public void CheckRequiredMods_WhenRequiredVersionInvalid_GetExpectedRequiredMod() { const string requiredMod = "SMLHelper"; const string invalidVersionString = "1.X.0.Y"; var versionDependentMod = new QMod { // Mod with a bad version string in its version dependencies. VersionDependencies = new Dictionary <string, string> { { requiredMod, invalidVersionString } } }; var validator = new ManifestValidator(); validator.CheckRequiredMods(versionDependentMod); // The entry is added to RequiredMods but without a minimum version. Assert.AreEqual(1, versionDependentMod.RequiredMods.Count()); RequiredQMod expected = new RequiredQMod(requiredMod); RequiredQMod actual = versionDependentMod.RequiredMods.First(); Assert.AreEqual(requiredMod, actual.Id); Assert.AreEqual(expected.RequiresMinimumVersion, actual.RequiresMinimumVersion); Assert.AreEqual(expected.MinimumVersion, actual.MinimumVersion); }
public void CheckRequiredMods_WhenRequirementsRedundant_GetExpectedRequiredMod() { const string requiredMod = "SMLHelper"; const string requiredVersionString = "8.6.7"; var versionDependentMod = new QMod { // Mod that redundantly includes the same mod both ID and minimum version. // Unnecessary, but should not cause errors. Dependencies = new[] { requiredMod }, VersionDependencies = new Dictionary <string, string> { { requiredMod, requiredVersionString } } }; var validator = new ManifestValidator(); validator.CheckRequiredMods(versionDependentMod); // Only a single entry is added to RequiredMods. Assert.AreEqual(1, versionDependentMod.RequiredMods.Count()); RequiredQMod expected = new RequiredQMod(requiredMod, requiredVersionString); RequiredQMod actual = versionDependentMod.RequiredMods.First(); Assert.AreEqual(requiredMod, actual.Id); Assert.AreEqual(expected.RequiresMinimumVersion, actual.RequiresMinimumVersion); Assert.AreEqual(expected.MinimumVersion, actual.MinimumVersion); }
public void TestDependencies_SML_CC2_ConfirmCorrectOrder() { var validator = new ManifestValidator(); var tree = new SortedCollection <string, QMod>(); var cc2 = new QMod { Id = "CustomCraft2SML", Dependencies = new[] { "SMLHelper" } }; var sml = new QMod { Id = "SMLHelper" }; validator.CheckRequiredMods(cc2); validator.CheckRequiredMods(sml); tree.AddSorted(cc2); tree.AddSorted(sml); List <QMod> list = tree.GetSortedList(); Console.WriteLine(ListToString(list)); Assert.AreEqual(2, list.Count); Assert.AreEqual("CustomCraft2SML", list[0].Id); Assert.AreEqual("SMLHelper", list[1].Id); }
public void TestDependencies_SSS_SE_ConfirmCorrectOrder() { var validator = new ManifestValidator(); var tree = new SortedCollection <string, QMod>(); var sss = new QMod { Id = "SeamothStorageSlots", LoadBefore = new[] { "SlotExtender" } }; var se = new QMod { Id = "SlotExtender" }; validator.CheckRequiredMods(sss); validator.CheckRequiredMods(se); tree.AddSorted(sss); tree.AddSorted(se); List <QMod> list = tree.GetSortedList(); Console.WriteLine(ListToString(list)); Assert.AreEqual(2, list.Count); Assert.AreEqual("SeamothStorageSlots", list[0].Id); Assert.AreEqual("SlotExtender", list[1].Id); }
public void CheckRequiredMods_WhenRequiresVersion_GetExpectedRequiredMod() { const string requiredMod = "SMLHelper"; const string requiredVersionString = "8.6.7"; var versionDependentMod = new QMod { // Mod that requires a minimum version of another mod. VersionDependencies = new Dictionary <string, string> { { requiredMod, requiredVersionString } } }; var validator = new ManifestValidator(); validator.CheckRequiredMods(versionDependentMod); Assert.AreEqual(1, versionDependentMod.RequiredMods.Count()); RequiredQMod expected = new RequiredQMod(requiredMod, requiredVersionString); RequiredQMod actual = versionDependentMod.RequiredMods.First(); Assert.AreEqual(requiredMod, actual.Id); Assert.AreEqual(expected.RequiresMinimumVersion, actual.RequiresMinimumVersion); Assert.AreEqual(expected.MinimumVersion, actual.MinimumVersion); }
public void TestList_MixedDependenciesAndPreferences_OrderInCycle_PreferenceIgnored_AllModsLinked() { var tree = new SortedCollection <string, QMod>(); var coreMod = new QMod { Id = "Core", LoadBefore = new[] { "NonCore" } }; var nonCoreMod = new QMod { Id = "NonCore", Dependencies = new[] { "Core" } }; tree.AddSorted(coreMod); tree.AddSorted(nonCoreMod); List <QMod> list = tree.GetSortedList(); Console.WriteLine(ListToString(list)); Assert.AreEqual(2, list.Count); Assert.AreEqual("NonCore", list[0].Id); Assert.AreEqual("Core", list[1].Id); }
public void SetUpTestMod() { qmod = new QMod { Id = nameof(QMMTests), SupportedGame = QModGame.Subnautica, LoadedAssembly = Assembly.GetExecutingAssembly() }; }
/// <summary> /// Validates the that modder has read the documentation. /// </summary> /// <param name="method">The method.</param> /// <param name="mod">The mod.</param> /// <exception cref="FatalPatchingException">This modder has not read the documentation and should not be using prepatch/postpatch functions.</exception> internal void ValidateSecretPassword(MethodInfo method, QMod mod) { switch (this.PatchOrder) { case PatchingOrder.PreInitialize: case PatchingOrder.NormalInitialize: case PatchingOrder.PostInitialize: return; } /* * What is all this for? * This is to make sure that modders don't start using elevated PrePatching and PostPatching in place of normal Pre/Post Patching without a second thought. * Elevated Pre/Post patching should be reserved for mods that absolutely require it; Primarily, mods that interact with all other mods. * Mods that only interact with one or two mods can likely do just fine with basic load order. * * Now, if you are convinced that your mod should be using these features, then this is what you do. */ using (var md5 = MD5.Create()) { string c1 = method.Name; // Step 1: Start with the name of your pre or post patching method. string c2 = mod.Id; // Step 2: Get the ID of your mod string c; // Step 3: Check if you are doing a PrePatch or PostPatch if (this.PatchOrder < 0) { // Step 3 Option A: For a PrePatch, create a string by placing the prepatch method name before the assembly name. c = c1 + c2; } else { // Step 3 Option B: For a PostPatch, create a string by placing the postpatch method name after the assembly name. c = c2 + c1; } // Step 4: Compute the MD5 Hash of that string // You don't need to write code for this. You can do it online: http://onlinemd5.com/ byte[] inputBytes = Encoding.ASCII.GetBytes(c); byte[] hashBytes = md5.ComputeHash(inputBytes); // Step 5: Use the resulting string as the parameter for [QModPrePatch()] or [QModPostPatch()] depending on which one you built. var sb = new StringBuilder(); for (int i = 0; i < hashBytes.Length; i++) { sb.Append(hashBytes[i].ToString("X2")); } if (sb.ToString() != _secretPasword) { throw new FatalPatchingException("This modder has not read the documentation and should not be using prepatch/postpatch functions."); } } }
public void CheckRequiredMods_WhenRequiresNothing_GetEmptyRequiredMods() { // Mod that requires no other mods. var standaloneMod = new QMod(); var validator = new ManifestValidator(); validator.CheckRequiredMods(standaloneMod); Assert.AreEqual(0, standaloneMod.RequiredMods.Count()); }
public void TwoModTest_BothOrdersDefined_GetExpectedOrder() { Patcher.loadedMods.Clear(); Patcher.foundMods.Clear(); Patcher.sortedMods.Clear(); Patcher.erroredMods.Clear(); QMod mod1 = new QMod { Id = "Mod1", LoadBefore = new string[1] { "Mod2" } }; QMod mod2 = new QMod { Id = "Mod2", LoadAfter = new string[1] { "Mod1" } }; Patcher.foundMods = new List <QMod> { mod2, mod1 // Simulate being picked up in the wrong order }; Patcher.sortedMods = new List <QMod>(Patcher.foundMods); foreach (QMod mod in Patcher.foundMods) { Console.WriteLine("Now Loading: " + mod.Id); Patcher.modSortingChain.Clear(); Assert.IsTrue(Patcher.SortMod(mod)); } foreach (QMod mod in Patcher.sortedMods) { Console.WriteLine(mod.Id); } int indexOfMod1 = Patcher.sortedMods.IndexOf(mod1); int indexOfMod2 = Patcher.sortedMods.IndexOf(mod2); Assert.IsTrue(indexOfMod1 < indexOfMod2); Assert.IsTrue(indexOfMod2 > indexOfMod1); }
public void TestDependencies_Multiple_Mod_Dependencies_ConfirmCorrectOrder() { var validator = new ManifestValidator(); var tree = new SortedCollection <string, QMod>(); var st = new QMod { Id = "SpecialtyManifold", Dependencies = new[] { "NitrogenMod", "ScubaManifold" } }; var no2 = new QMod { Id = "NitrogenMod", Dependencies = new[] { "SMLHelper" } }; var sm = new QMod { Id = "ScubaManifold", Dependencies = new[] { "SMLHelper" } }; var sml = new QMod { Id = "SMLHelper" }; validator.CheckRequiredMods(st); validator.CheckRequiredMods(no2); validator.CheckRequiredMods(sm); validator.CheckRequiredMods(sml); tree.AddSorted(st); tree.AddSorted(no2); tree.AddSorted(sm); tree.AddSorted(sml); List <QMod> list = tree.GetSortedList(); Console.WriteLine(ListToString(list)); Assert.AreEqual(4, list.Count); Assert.AreEqual("SpecialtyManifold", list[0].Id); Assert.AreEqual("ScubaManifold", list[1].Id); Assert.AreEqual("NitrogenMod", list[2].Id); Assert.AreEqual("SMLHelper", list[3].Id); }
public void CreateModStatusList_WhenMissingVersionDependencies_StatusUpdates(string missingOrOutdatedMod, ModStatus expectedStatus) { // Arange var factory = new QModFactory(new DummyPluginCollection(), new DummyValidator()) { }; var noModsRequired = new RequiredQMod[0]; var earlyErrors = new List <QMod> { new QMod { Id = "5", Status = ModStatus.MissingPatchMethod, RequiredMods = noModsRequired }, }; var modToInspect = new QMod { Id = "8", Status = ModStatus.Success, RequiredMods = new List <RequiredQMod> { new RequiredQMod(missingOrOutdatedMod, "1.0.2") } }; var modsToLoad = new List <QMod> { new QMod { Id = "6", Status = ModStatus.Success, RequiredMods = noModsRequired }, new QMod { Id = "7", Status = ModStatus.Success, ParsedVersion = new Version(1, 0, 1), LoadedAssembly = Assembly.GetExecutingAssembly(), RequiredMods = noModsRequired }, modToInspect }; // Act List <QMod> combinedList = factory.CreateModStatusList(earlyErrors, modsToLoad); // Assert Assert.AreEqual(expectedStatus, modToInspect.Status); }
public void TwoModTest_CircularDependency_SortModReturnsFalse() { Patcher.loadedMods.Clear(); Patcher.foundMods.Clear(); Patcher.sortedMods.Clear(); Patcher.erroredMods.Clear(); QMod mod1 = new QMod { Id = "Mod1", LoadBefore = new string[1] { "Mod2" } }; QMod mod2 = new QMod { Id = "Mod2", LoadBefore = new string[1] { "Mod1" } }; Patcher.foundMods = new List <QMod> { mod2, mod1 // Simulate being picked up in the wrong order }; Patcher.sortedMods = new List <QMod>(Patcher.foundMods); // Mod 1 Console.WriteLine("Now Loading: " + Patcher.foundMods[0].Id); Patcher.modSortingChain.Clear(); Assert.IsTrue(Patcher.SortMod(Patcher.foundMods[0])); // Mod 2 - Circular dependency encountered Console.WriteLine("Now Loading: " + Patcher.foundMods[1].Id); Patcher.modSortingChain.Clear(); Assert.IsFalse(Patcher.SortMod(Patcher.foundMods[1])); }
public void CreateModStatusList_WhenMissingVersionDependencies_StatusUpdates(string missingOrOutdatedMod, ModStatus expectedStatus) { // Arange var earlyErrors = new List <QMod> { new QMod { Id = "5", Status = ModStatus.MissingPatchMethod }, }; var modToInspect = new QMod { Id = "8", Status = ModStatus.Success, RequiredMods = new List <RequiredQMod> { new RequiredQMod(missingOrOutdatedMod, new Version(1, 0, 2)) } }; var modsToLoad = new List <QMod> { new QMod { Id = "6", Status = ModStatus.Success }, new QMod { Id = "7", Status = ModStatus.Success, ParsedVersion = new Version(1, 0, 1) }, modToInspect }; // Act List <QMod> combinedList = QModFactory.CreateModStatusList(earlyErrors, modsToLoad); // Assert Assert.AreEqual(expectedStatus, modToInspect.Status); }
public void CheckRequiredMods_WhenRequiresIdOnly_GetExpectedRequiredMod() { const string requiredMod = "SMLHelper"; var simpleDependentMod = new QMod { // Mod that requires one other mod, only by ID. Dependencies = new[] { requiredMod } }; var validator = new ManifestValidator(); validator.CheckRequiredMods(simpleDependentMod); Assert.AreEqual(1, simpleDependentMod.RequiredMods.Count()); RequiredQMod expected = new RequiredQMod(requiredMod); RequiredQMod actual = simpleDependentMod.RequiredMods.First(); Assert.AreEqual(requiredMod, actual.Id); Assert.AreEqual(expected.RequiresMinimumVersion, actual.RequiresMinimumVersion); Assert.AreEqual(expected.MinimumVersion, actual.MinimumVersion); }
public void CheckRequiredMods_WhenRequirementsMixed_GetExpectedRequiredMods() { const string requiredModA = "SMLHelper"; const string requiredModB = "MoreCyclopsUpgrades"; const string requiredVersionBString = "8.6.7"; var versionDependentMod = new QMod { // Mod that requires one mod by id only and another at a minimum verison. Dependencies = new[] { requiredModA }, VersionDependencies = new Dictionary <string, string> { { requiredModB, requiredVersionBString } } }; var validator = new ManifestValidator(); validator.CheckRequiredMods(versionDependentMod); Assert.AreEqual(2, versionDependentMod.RequiredMods.Count()); RequiredQMod expectedA = new RequiredQMod(requiredModA); RequiredQMod actualA = versionDependentMod.RequiredMods.ElementAt(0); Assert.AreEqual(requiredModA, actualA.Id); Assert.AreEqual(expectedA.RequiresMinimumVersion, actualA.RequiresMinimumVersion); Assert.AreEqual(expectedA.MinimumVersion, actualA.MinimumVersion); RequiredQMod expectedB = new RequiredQMod(requiredModB, requiredVersionBString); RequiredQMod actualB = versionDependentMod.RequiredMods.ElementAt(1); Assert.AreEqual(requiredModB, actualB.Id); Assert.AreEqual(expectedB.RequiresMinimumVersion, actualB.RequiresMinimumVersion); Assert.AreEqual(expectedB.MinimumVersion, actualB.MinimumVersion); }
public void ValidateManifest(QMod mod) { }
public void CheckRequiredMods(QMod mod) { }
public void ValidateBasicManifest(QMod mod) { }
public void LoadAssembly(QMod mod) { }
public void FindPatchMethods(QMod qMod) { }
public void FourModTest() { Patcher.loadedMods.Clear(); Patcher.foundMods.Clear(); Patcher.sortedMods.Clear(); Patcher.erroredMods.Clear(); QMod mod1 = new QMod { Id = "Mod1", LoadBefore = new string[2] { "Mod2", "Mod3" }, LoadAfter = new string[1] { "Mod4" } }; QMod mod2 = new QMod { Id = "Mod2", LoadAfter = new string[2] { "Mod1", "Mod3" } }; QMod mod3 = new QMod { Id = "Mod3" }; QMod mod4 = new QMod { Id = "Mod4" }; Patcher.foundMods = new List <QMod> { mod1, mod2, mod3, mod4 }; Patcher.sortedMods = new List <QMod>(Patcher.foundMods); foreach (QMod mod in Patcher.foundMods) { Console.WriteLine("Now Loading: " + mod.Id); Patcher.modSortingChain.Clear(); Assert.IsTrue(Patcher.SortMod(mod)); } foreach (QMod mod in Patcher.sortedMods) { Console.WriteLine(mod.Id); } int indexOfMod1 = Patcher.sortedMods.IndexOf(mod1); int indexOfMod2 = Patcher.sortedMods.IndexOf(mod2); int indexOfMod3 = Patcher.sortedMods.IndexOf(mod3); int indexOfMod4 = Patcher.sortedMods.IndexOf(mod4); Assert.IsTrue(indexOfMod1 < indexOfMod2); Assert.IsTrue(indexOfMod1 < indexOfMod3); Assert.IsTrue(indexOfMod2 > indexOfMod1); Assert.IsTrue(indexOfMod2 > indexOfMod3); }