diff --git a/Automation/UnitTestCategories.cs b/Automation/UnitTestCategories.cs
index fffa1a2d..b673a060 100644
--- a/Automation/UnitTestCategories.cs
+++ b/Automation/UnitTestCategories.cs
@@ -5,6 +5,7 @@ public static class UnitTestCategories {
public const string ManualOnly = "ManualOnly";
public const string HouseholdsWithTransportation = "HouseholdsWithTransportation";
public const string HouseholdTest = "HouseholdTest";
+ public const string HouseholdTemplateTest = "HouseholdTemplateTest";
public const string HousetypeTests = "HousetypeTests";
public const string CalcOptionTests = "CalcOptionTests";
public const string LongTest5 = "LongTest5";
diff --git a/Common/Logger.cs b/Common/Logger.cs
index 2d5d4133..4b1aebf7 100644
--- a/Common/Logger.cs
+++ b/Common/Logger.cs
@@ -367,7 +367,7 @@ private void ReportString([JetBrains.Annotations.NotNull] string message, Severi
}
if (severity <= Threshold)
{
- if (OutputHelper!= null) {
+ if (OutputHelper != null && !Config.OutputToConsole) {
OutputHelper.WriteLine(message);
}
else {
diff --git a/Common/WorkingDir.cs b/Common/WorkingDir.cs
index 0f5daa4f..cc0e955b 100644
--- a/Common/WorkingDir.cs
+++ b/Common/WorkingDir.cs
@@ -148,6 +148,7 @@ public void CleanUp(int numberOfFilesToTolerate = 0, bool throwAllErrors = true)
[JetBrains.Annotations.NotNull]
private static string InitializeWorkingDirectory([JetBrains.Annotations.NotNull] string testname, bool useRamdisk) {
var baseWorkingDir = DetermineBaseWorkingDir(useRamdisk);
+ testname = ReplaceInvalidChars(testname);
var resultdir = Path.Combine(baseWorkingDir, testname);
try {
if (Directory.Exists(resultdir)) {
@@ -173,6 +174,25 @@ private static string InitializeWorkingDirectory([JetBrains.Annotations.NotNull]
return resultdir;
}
+ ///
+ /// Replaces all characters that are not allowed in file names with a fixed replacement character.
+ ///
+ /// The file name to adjust
+ /// The character to use instead of illegal characters
+ /// The adjusted file name without any illegal characters
+ public static string ReplaceInvalidChars(string filename, char replacementChar = '_')
+ {
+ foreach (char c in Path.GetInvalidFileNameChars())
+ {
+ if (c == replacementChar)
+ {
+ throw new LPGException("Used an illegal character as replacementChar: '" + replacementChar + "'");
+ }
+ filename = filename.Replace(c, replacementChar);
+ }
+ return filename;
+ }
+
///
/// Determines the base directory for any working directories used for tests.
///
diff --git a/Directory.Build.props b/Directory.Build.props
index 9d14262a..d8cf5895 100644
--- a/Directory.Build.props
+++ b/Directory.Build.props
@@ -1,6 +1,6 @@
- 10.7.0.6
- 10.7.0.6
+ 10.8.0.1
+ 10.8.0.1
-
\ No newline at end of file
+
diff --git a/SimulationEngine.Tests/CalculationTests.cs b/SimulationEngine.Tests/CalculationTests.cs
index ccca7a26..6832981d 100644
--- a/SimulationEngine.Tests/CalculationTests.cs
+++ b/SimulationEngine.Tests/CalculationTests.cs
@@ -34,6 +34,7 @@
namespace SimulationEngine.Tests {
public enum TestDuration {
+ ThreeDays,
OneMonth,
ThreeMonths,
TwelveMonths
@@ -52,6 +53,7 @@ public static HouseCreationAndCalculationJob PrepareExistingHouseForTesting([Jet
public static HouseCreationAndCalculationJob PrepareNewHouseForHouseholdTesting(Simulator sim, string guid, TestDuration duration)
{
+
var hj = new HouseCreationAndCalculationJob
{
CalcSpec = JsonCalcSpecification.MakeDefaultsForTesting()
@@ -86,17 +88,22 @@ private static void SetEndDate(TestDuration duration, HouseCreationAndCalculatio
if (hj.CalcSpec == null) {
throw new LPGException("was null");
}
- if (duration == TestDuration.OneMonth) {
- hj.CalcSpec.EndDate = new DateTime(2020, 2, 1);
- }
- else if (duration == TestDuration.ThreeMonths) {
- hj.CalcSpec.EndDate = new DateTime(2020, 4, 1);
- }
- else if (duration == TestDuration.TwelveMonths) {
- hj.CalcSpec.EndDate = new DateTime(2020, 12, 31);
- }
- else {
- throw new LPGException("Unkown duration");
+ switch (duration)
+ {
+ case TestDuration.ThreeDays:
+ hj.CalcSpec.EndDate = new DateTime(2020, 1, 4);
+ break;
+ case TestDuration.OneMonth:
+ hj.CalcSpec.EndDate = new DateTime(2020, 2, 1);
+ break;
+ case TestDuration.ThreeMonths:
+ hj.CalcSpec.EndDate = new DateTime(2020, 4, 1);
+ break;
+ case TestDuration.TwelveMonths:
+ hj.CalcSpec.EndDate = new DateTime(2020, 12, 31);
+ break;
+ default:
+ throw new LPGException("Unkown duration");
}
}
@@ -215,7 +222,7 @@ public static void CheckForResultfile(string wd, CalcOption option)
{
var peakWorkingSet = Process.GetCurrentProcess().PeakWorkingSet64;
- const long memoryCap = 1024l * 1024l * 2000l * 2l;
+ const long memoryCap = 1024L * 1024L * 2000L * 2L;
peakWorkingSet.Should().BeLessThan(memoryCap);
GC.Collect();
GC.WaitForPendingFinalizers();
@@ -370,7 +377,7 @@ public static void CheckForResultfile(string wd, CalcOption option)
//}
}
- public static void RunSingleHouse(Func makeHj, Action checkResults,
+ public static void RunSingleHouse(Func makeHj, Action checkResults,
bool skipcleaning = false)
{
Logger.Get().StartCollectingAllMessages();
@@ -384,14 +391,64 @@ public static void RunSingleHouse(Func
+ /// Generates one household from a household template and simulates them.
+ ///
+ /// A unique name of the calling test for setting up a working directory
+ /// The Guid of the household template to use
+ /// Duration for which the household should be simulated
+ public static void GenerateAndSimulateHHFromTemplate(string testID, StrGuid hhTemplateGuid, TestDuration duration)
+ {
+ Logger.Get().StartCollectingAllMessages();
+ // set up a working directory
+ using var wd = new WorkingDir(testID);
+ wd.SkipCleaning = false;
+ // get a database connection
+ using var db = new DatabaseSetup(testID);
+ Directory.SetCurrentDirectory(wd.WorkingDirectory);
+ Simulator sim;
+ try
+ {
+ sim = new Simulator(db.ConnectionString);
+ }
+ catch (FormatException)
+ {
+ // during tests infrequent problems occur when loading and parsing dates from the database
+ // --> save the database in another folder
+ string backupPath = Path.Combine(WorkingDir.DetermineBaseWorkingDir(true), "InvalidDatetime_DB_Backup");
+ string dbFilename = Path.GetFileName(db.FileName);
+ string destinationFile = Path.Combine(backupPath, dbFilename);
+ Directory.CreateDirectory(backupPath);
+ File.Copy(db.FileName, destinationFile);
+ throw;
+ }
+ // find the household template to use
+ var hhTemplate = sim.HouseholdTemplates.FindByGuid(hhTemplateGuid);
+ hhTemplate.Should().NotBeNull();
+ Logger.Info("Testing generation and simulation of a household using household template \"" + hhTemplate.Name + "\"");
+ // generate one household
+ hhTemplate.Count = 1;
+ var households = hhTemplate.GenerateHouseholds(sim, false, new List(), new List());
+ households.Should().HaveCount(1);
+ var household = households[0];
+ // prepare and execute the house job
+ var hj = HouseJobCalcPreparer.PrepareNewHouseForHouseholdTesting(sim, household.Guid.StrVal, duration);
+ if (hj.CalcSpec?.CalcOptions == null) { throw new LPGException("No CalcOptions were set"); }
+ hj.CalcSpec.EnableIdlemode = true;
+ hj.CalcSpec.DefaultForOutputFiles = OutputFileDefault.OnlySums;
+ var houseGenerator = new HouseGenerator();
+ houseGenerator.ProcessSingleHouseJob(hj, sim);
+ }
}
@@ -813,6 +870,85 @@ public void GenerateSystematicHouseholdTestsWithTransport()
sw.Close();
}
+ ///
+ /// Tests generation of households using a household template. Generates 100 households for each
+ /// template, and simulates each household for 3 days.
+ ///
+ /// Guid of the template to test
+ /// Name of the template to test
+ /// Repetition of this test for the same template
+ /// Each call of this method only handles a single household
+ [Theory]
+ [MemberData(nameof(GetEachHHTemplate100Times))]
+ [Trait(UnitTestCategories.Category, UnitTestCategories.HouseholdTemplateTest)]
+ public void SystematicHouseholdTemplateTestShort(StrGuid hhTemplateGuid, string hhTemplateName, int repetition)
+ {
+ string testID = "CalculationTests.SystematicHouseholdTemplateTestShort." + hhTemplateName + "." + repetition;
+ HouseJobTestHelper.GenerateAndSimulateHHFromTemplate(testID, hhTemplateGuid, TestDuration.ThreeDays);
+ }
+
+ ///
+ /// Tests generation of households using a household template. Generates 3 households for each
+ /// template, and simulates each household for one year.
+ ///
+ /// Guid of the template to test
+ /// Name of the template to test
+ /// Repetition of this test for the same template
+ /// Each call of this method only handles a single household
+ [Theory]
+ [MemberData(nameof(GetEachHHTemplate3Times))]
+ [Trait(UnitTestCategories.Category, UnitTestCategories.HouseholdTemplateTest)]
+ public void SystematicHouseholdTemplateTestLong(StrGuid hhTemplateGuid, string hhTemplateName, int repetition)
+ {
+ string testID = "CalculationTests.SystematicHouseholdTemplateTestLong." + hhTemplateName + "." + repetition;
+ HouseJobTestHelper.GenerateAndSimulateHHFromTemplate(testID, hhTemplateGuid, TestDuration.TwelveMonths);
+ }
+
+ ///
+ /// Creates an enumerable of all household template guids and names, repeating each template 100 times.
+ ///
+ /// An of household template guids and names
+ public static IEnumerable