Skip to content

Commit c9b9003

Browse files
authored
Unit tests for several classes (#3037)
1 parent d714ae5 commit c9b9003

9 files changed

Lines changed: 522 additions & 0 deletions

File tree

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
using commonItems;
2+
using commonItems.Mods;
3+
using ImperatorToCK3.CK3.Characters;
4+
using System;
5+
using System.IO;
6+
using System.Linq;
7+
using Xunit;
8+
9+
namespace ImperatorToCK3.UnitTests.CK3.Characters;
10+
11+
[Collection("Sequential")]
12+
[CollectionDefinition("Sequential", DisableParallelization = true)]
13+
public class CharactersLoaderTests {
14+
[Fact]
15+
public void LoadCK3Characters_ProcessesCharactersAndFiltersInvalid() {
16+
var tempRoot = Path.Combine(Path.GetTempPath(), "CharactersLoaderTests", Guid.NewGuid().ToString());
17+
try {
18+
var charDir = Path.Combine(tempRoot, "history", "characters");
19+
Directory.CreateDirectory(charDir);
20+
21+
File.WriteAllText(Path.Combine(charDir, "chars.txt"),
22+
"char_mother = { female = yes 900.1.1 = { birth = yes } }\n" +
23+
"char_father = { female = no 900.1.1 = { birth = yes } }\n" +
24+
"char_child = { name = \"Child\" female = yes mother = char_mother father = char_father 920.1.1 = { birth = yes death = { death_reason = death_murder_known killer = 1 } } }\n" +
25+
"animation_test_1 = { 1.1.1 = { birth = yes } }\n" +
26+
"no_birth = { female = yes }\n"
27+
);
28+
29+
var modFS = new ModFilesystem(tempRoot, Array.Empty<Mod>());
30+
var characters = new CharacterCollection();
31+
characters.LoadCK3Characters(modFS, new Date(1000, 1, 1));
32+
33+
// Characters without birth date should be ignored
34+
Assert.False(characters.ContainsKey("no_birth"));
35+
36+
// Characters should exist
37+
var child = characters["char_child"];
38+
Assert.NotNull(child);
39+
40+
// Mother/father should remain because sexes are correct
41+
var motherEntry = child.History.Fields["mother"].InitialEntries.Select(kvp => kvp.Value).Single();
42+
var fatherEntry = child.History.Fields["father"].InitialEntries.Select(kvp => kvp.Value).Single();
43+
Assert.Equal("char_mother", motherEntry.ToString());
44+
Assert.Equal("char_father", fatherEntry.ToString());
45+
46+
// Birth entry should have been simplified (value becomes boolean true)
47+
var birthEntryValue = child.History.Fields["birth"].GetValue(new Date(920, 1, 1));
48+
Assert.True(birthEntryValue is bool v && v);
49+
50+
// Animation test character should be killed on 2.1.1
51+
var animationChar = characters["animation_test_1"];
52+
Assert.Equal(new Date(2, 1, 1), animationChar.DeathDate);
53+
} finally {
54+
try { Directory.Delete(tempRoot, recursive: true); } catch {
55+
// Failure to delete the temp directory can be ignored.
56+
}
57+
}
58+
}
59+
}
Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
using commonItems;
2+
using ImperatorToCK3.CK3.Diplomacy;
3+
using ImperatorToCK3.CK3.Titles;
4+
using ImperatorToCK3.Imperator.Countries;
5+
using System;
6+
using System.Collections.Generic;
7+
using System.IO;
8+
using System.Linq;
9+
using Xunit;
10+
11+
namespace ImperatorToCK3.UnitTests.CK3.Diplomacy;
12+
13+
[Collection("Sequential")]
14+
[CollectionDefinition("Sequential", DisableParallelization = true)]
15+
public class DiplomacyDBTests {
16+
[Fact]
17+
public void ImportImperatorLeagues_SkipsMissingCountriesAndLogsWarning() {
18+
var db = new DiplomacyDB();
19+
var countries = new CountryCollection();
20+
21+
// Only one country exists; league contains an unknown member
22+
var leagues = new List<List<ulong>> {
23+
new() { 1, 2 }
24+
};
25+
26+
var output = new StringWriter();
27+
Console.SetOut(output);
28+
29+
db.ImportImperatorLeagues(leagues, countries);
30+
31+
Assert.Empty(db.Leagues);
32+
Assert.Contains("Member 2 of defensive league not found in countries!", output.ToString());
33+
}
34+
35+
[Fact]
36+
public void ImportImperatorLeagues_SkipsLeaguesWithLessThanTwoAvailableMembers() {
37+
var db = new DiplomacyDB();
38+
var countries = new CountryCollection();
39+
var titles = new Title.LandedTitles();
40+
41+
var title = titles.Add("k_test");
42+
countries.Add(new Country(1) { CK3Title = title });
43+
44+
var leagues = new List<List<ulong>> {
45+
new() { 1 },
46+
new() { 1, 2 }
47+
};
48+
49+
var output = new StringWriter();
50+
Console.SetOut(output);
51+
52+
db.ImportImperatorLeagues(leagues, countries);
53+
54+
// Only the first league had at least 2 members, but one member was missing, so none should be imported.
55+
Assert.Empty(db.Leagues);
56+
Assert.Contains("Not enough members in league to import it", output.ToString());
57+
}
58+
59+
[Fact]
60+
public void ImportImperatorLeagues_AddsLeagueWithTwoValidMembers() {
61+
var db = new DiplomacyDB();
62+
var countries = new CountryCollection();
63+
var titles = new Title.LandedTitles();
64+
65+
var titleA = titles.Add("k_a");
66+
var titleB = titles.Add("k_b");
67+
countries.Add(new Country(1) { CK3Title = titleA });
68+
countries.Add(new Country(2) { CK3Title = titleB });
69+
70+
var leagues = new List<List<ulong>> {
71+
new() { 1, 2 }
72+
};
73+
74+
db.ImportImperatorLeagues(leagues, countries);
75+
76+
Assert.Single(db.Leagues);
77+
Assert.Equal(new[] { "k_a", "k_b" }, db.Leagues[0].Select(t => t.Id));
78+
}
79+
}
Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
using commonItems.Mods;
2+
using ImperatorToCK3.CK3.Legends;
3+
using System;
4+
using System.IO;
5+
using System.Linq;
6+
using Xunit;
7+
8+
namespace ImperatorToCK3.UnitTests.CK3.Legends;
9+
10+
[Collection("Sequential")]
11+
[CollectionDefinition("Sequential", DisableParallelization = true)]
12+
public class LegendSeedCollectionTests {
13+
[Fact]
14+
public void LoadSeeds_ParsesLegendSeedFiles() {
15+
var testRoot = Path.Combine(Path.GetTempPath(), "LegendSeedCollectionTests", Guid.NewGuid().ToString());
16+
try {
17+
var seedsDir = Path.Combine(testRoot, "common", "legends", "legend_seeds");
18+
Directory.CreateDirectory(seedsDir);
19+
File.WriteAllText(Path.Combine(seedsDir, "seeds.txt"), "seed_a = { foo = bar }\nseed_b = { baz = qux }");
20+
21+
var modFs = new ModFilesystem(testRoot, Array.Empty<Mod>());
22+
var collection = new LegendSeedCollection();
23+
collection.LoadSeeds(modFs);
24+
25+
var serialized = collection.Serialize(string.Empty, withBraces: true);
26+
var seedIds = serialized.Split(['\n', '\r'], StringSplitOptions.RemoveEmptyEntries)
27+
.Select(line => line.Split('=', 2)[0].Trim());
28+
29+
Assert.Contains("seed_a", seedIds);
30+
Assert.Contains("seed_b", seedIds);
31+
Assert.Contains("seed_a={ foo = bar }", serialized);
32+
Assert.Contains("seed_b={ baz = qux }", serialized);
33+
} finally {
34+
try {
35+
Directory.Delete(testRoot, recursive: true);
36+
} catch {
37+
// Failure to delete the temp directory can be ignored.
38+
}
39+
}
40+
}
41+
42+
[Fact]
43+
public void RemoveAnachronisticSeeds_RemovesListedSeeds() {
44+
var testRoot = Path.Combine(Path.GetTempPath(), "LegendSeedCollectionTests", Guid.NewGuid().ToString());
45+
try {
46+
var seedsDir = Path.Combine(testRoot, "common", "legends", "legend_seeds");
47+
Directory.CreateDirectory(seedsDir);
48+
File.WriteAllText(Path.Combine(seedsDir, "seeds.txt"), "seed_a = { foo = bar }\nseed_b = { baz = qux }");
49+
50+
var removalFile = Path.Combine(testRoot, "remove_seeds.txt");
51+
File.WriteAllText(removalFile, "seed_a\n");
52+
53+
var modFs = new ModFilesystem(testRoot, Array.Empty<Mod>());
54+
var collection = new LegendSeedCollection();
55+
collection.LoadSeeds(modFs);
56+
collection.RemoveAnachronisticSeeds(removalFile);
57+
58+
var serialized = collection.Serialize(string.Empty, withBraces: true);
59+
Assert.DoesNotContain("seed_a=", serialized);
60+
Assert.Contains("seed_b=", serialized);
61+
} finally {
62+
try {
63+
Directory.Delete(testRoot, recursive: true);
64+
} catch {
65+
// Failure to delete the temp directory can be ignored.
66+
}
67+
}
68+
}
69+
}
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
using commonItems;
2+
using ImperatorToCK3.CK3.Legends;
3+
using Xunit;
4+
5+
namespace ImperatorToCK3.UnitTests.CK3.Legends;
6+
7+
public class LegendSeedTests {
8+
[Fact]
9+
public void IdIsStored() {
10+
var seed = new LegendSeed("legend_1", new BufferedReader("{}"));
11+
Assert.Equal("legend_1", seed.Id);
12+
}
13+
14+
[Fact]
15+
public void Serialize_ReturnsBodyString() {
16+
// The body is parsed as a StringOfItem; it should round-trip via Serialize.
17+
var seed = new LegendSeed("legend_2", new BufferedReader("{ foo = bar }"));
18+
Assert.Equal("{ foo = bar }", seed.Serialize(string.Empty, withBraces: true));
19+
}
20+
}
Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
using commonItems;
2+
using ImperatorToCK3.CK3.Provinces;
3+
using ImperatorToCK3.CK3.Titles;
4+
using CK3War = ImperatorToCK3.CK3.Wars.War;
5+
using ImperatorWar = ImperatorToCK3.Imperator.Diplomacy.War;
6+
using ImperatorToCK3.Imperator.Countries;
7+
using ImperatorToCK3.Imperator.States;
8+
using ImperatorToCK3.Mappers.Province;
9+
using ImperatorToCK3.Mappers.War;
10+
using System.IO;
11+
using System.Reflection;
12+
using commonItems.Exceptions;
13+
using Xunit;
14+
15+
namespace ImperatorToCK3.UnitTests.CK3.Wars;
16+
17+
[Collection("Sequential")]
18+
[CollectionDefinition("Sequential", DisableParallelization = true)]
19+
public class WarTests {
20+
[Fact]
21+
public void Constructor_ThrowsWhenNoValidAttackers() {
22+
var war = ImperatorWar.Parse(new BufferedReader("start_date = 100.1.1\nattacker = 1\nindependence = { type = independence }"));
23+
var mapperFile = "TestFiles/configurables/temp_wargoal_map_wartest.txt";
24+
File.WriteAllText(mapperFile, "link = { ck3 = cb ir = independence }");
25+
var warMapper = new WarMapper(mapperFile);
26+
27+
var countries = new CountryCollection {
28+
new Country(1)
29+
};
30+
31+
var provinceMapper = new ProvinceMapper();
32+
var states = new StateCollection();
33+
var provinces = new ProvinceCollection();
34+
var titles = new Title.LandedTitles();
35+
36+
var bookmarkDate = new Date(1100, 1, 1);
37+
38+
var ex = Assert.Throws<ConverterException>(() => new CK3War(war, warMapper, provinceMapper, countries, states, provinces, titles, bookmarkDate));
39+
Assert.Contains("War has no valid attackers", ex.Message);
40+
}
41+
42+
[Fact]
43+
public void Constructor_PopulatesAttackersClaimantAndCasusBelli() {
44+
var war = ImperatorWar.Parse(new BufferedReader("start_date = 100.1.1\nattacker = 1\ndefender = 2\nindependence = { type = independence }"));
45+
var mapperFile = "TestFiles/configurables/temp_wargoal_map_wartest.txt";
46+
File.WriteAllText(mapperFile, "link = { ck3 = cb_independence ir = independence }");
47+
var warMapper = new WarMapper(mapperFile);
48+
49+
var countries = new CountryCollection();
50+
var titles = new Title.LandedTitles();
51+
52+
var attackerTitle = titles.Add("k_attacker");
53+
SetTitleHolder(attackerTitle, "holder1", new Date(1000, 1, 1));
54+
var attackerCountry = new Country(1) { CK3Title = attackerTitle };
55+
countries.Add(attackerCountry);
56+
57+
var defenderTitle = titles.Add("k_defender");
58+
SetTitleHolder(defenderTitle, "holder2", new Date(1000, 1, 1));
59+
var defenderCountry = new Country(2) { CK3Title = defenderTitle };
60+
countries.Add(defenderCountry);
61+
62+
var provinceMapper = new ProvinceMapper();
63+
var states = new StateCollection();
64+
var provinces = new ProvinceCollection();
65+
66+
var bookmarkDate = new Date(1100, 1, 1);
67+
var createdWar = new CK3War(war, warMapper, provinceMapper, countries, states, provinces, titles, bookmarkDate);
68+
69+
Assert.Equal("holder1", Assert.Single(createdWar.Attackers));
70+
Assert.Equal("holder1", createdWar.Claimant);
71+
Assert.Equal("cb_independence", createdWar.CasusBelli);
72+
Assert.Equal(bookmarkDate.ChangeByDays(1), createdWar.EndDate);
73+
}
74+
75+
private static void SetTitleHolder(Title title, string holderId, Date date) {
76+
// Title stores its history in a private field/property created by the source generator.
77+
var historyProperty = typeof(Title).GetProperty("History", BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance);
78+
var history = historyProperty?.GetValue(title);
79+
var addMethod = history?.GetType().GetMethod("AddFieldValue", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
80+
addMethod?.Invoke(history, [date, "holder", "holder", holderId]);
81+
}
82+
}
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.IO;
4+
using commonItems.Collections;
5+
using ImperatorToCK3.CommonUtils;
6+
using Xunit;
7+
8+
namespace ImperatorToCK3.UnitTests.CommonUtils;
9+
10+
public class FieldValueTests {
11+
[Fact]
12+
public void Add_AddsToOrderedSet() {
13+
var set = new OrderedSet<string>();
14+
var field = new FieldValue(set, "setter");
15+
16+
field.Add("value");
17+
18+
Assert.Contains("value", (IEnumerable<string>)set);
19+
}
20+
21+
[Fact]
22+
public void Remove_RemovesFromOrderedSet() {
23+
var set = new OrderedSet<string> { "value" };
24+
var field = new FieldValue(set, "setter");
25+
26+
field.Remove("value");
27+
28+
Assert.DoesNotContain("value", (IEnumerable<string>)set);
29+
}
30+
31+
[Fact]
32+
public void Add_LogsWarning_OnNonAdditiveValue() {
33+
var originalOut = Console.Out;
34+
try {
35+
var output = new StringWriter();
36+
Console.SetOut(output);
37+
38+
var field = new FieldValue("not a set", "setter");
39+
field.Add("value");
40+
41+
Assert.Contains("Cannot additively add value", output.ToString());
42+
} finally {
43+
Console.SetOut(originalOut);
44+
}
45+
}
46+
47+
[Fact]
48+
public void Remove_LogsWarning_OnNonAdditiveValue() {
49+
var originalOut = Console.Out;
50+
try {
51+
var output = new StringWriter();
52+
Console.SetOut(output);
53+
54+
var field = new FieldValue("not a set", "setter");
55+
field.Remove("value");
56+
57+
Assert.Contains("Cannot additively remove value", output.ToString());
58+
} finally {
59+
Console.SetOut(originalOut);
60+
}
61+
}
62+
}

0 commit comments

Comments
 (0)