Skip to content

Commit ea022aa

Browse files
Add combination matrix test (#22)
Add a matrix test to validate we don't lose data in any of the
1 parent 845779a commit ea022aa

File tree

3 files changed

+114
-11
lines changed

3 files changed

+114
-11
lines changed

src/UnitTests/TaskTestBase.cs

Lines changed: 112 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
using AggregateConfigBuildTask.Contracts;
1+
using AggregateConfigBuildTask.Contracts;
22
using Microsoft.Build.Framework;
33
using Moq;
44
using Newtonsoft.Json;
@@ -477,6 +477,117 @@ public void StressTest_ShouldAddSourcePropertyManyFiles()
477477
}
478478
}
479479

480+
[TestMethod]
481+
[DataRow("arm", new[] { "json", "yml", "arm" }, DisplayName = "ARM -> JSON -> YAML -> ARM")]
482+
[DataRow("arm", new[] { "yml", "json", "arm" }, DisplayName = "ARM -> YAML -> JSON -> ARM")]
483+
[DataRow("json", new[] { "arm", "yml", "json" }, DisplayName = "JSON -> ARM -> YAML -> JSON")]
484+
[DataRow("json", new[] { "yml", "arm", "json" }, DisplayName = "JSON -> YAML -> ARM -> JSON")]
485+
[DataRow("yml", new[] { "arm", "json", "yml" }, DisplayName = "YAML -> ARM -> JSON -> YAML")]
486+
[DataRow("yml", new[] { "json", "arm", "yml" }, DisplayName = "YAML -> JSON -> ARM -> YAML")]
487+
[Description("Test that files are correctly translated between ARM, JSON, and YAML.")]
488+
public void ShouldTranslateBetweenFormatsAndValidateNoDataLoss(string inputType, string[] steps)
489+
{
490+
Assert.IsTrue(steps?.Length > 0);
491+
492+
// Arrange: Prepare paths and sample data based on the input type.
493+
var inputDir = $"{testPath}\\input";
494+
virtualFileSystem.CreateDirectory(inputDir);
495+
496+
// Write the initial input file
497+
var inputFilePath = $"{inputDir}\\input.{(inputType == "arm" ? "json" : inputType)}";
498+
virtualFileSystem.WriteAllText(inputFilePath, GetSampleDataForType(inputType));
499+
500+
string previousInputPath = inputFilePath;
501+
string previousOutputType = inputType;
502+
503+
// Execute the translation steps dynamically
504+
for (int i = 0; i < steps.Length; i++)
505+
{
506+
var outputType = steps[i];
507+
var stepDir = $"{testPath}\\step{i + 1}";
508+
var stepOutputPath = $"{stepDir}\\output.{(outputType == "arm" ? "json" : outputType)}";
509+
510+
virtualFileSystem.CreateDirectory(stepDir);
511+
512+
// Execute translation for this step
513+
ExecuteTranslationTask(previousOutputType, outputType, previousInputPath, stepOutputPath);
514+
515+
// Update paths for the next iteration
516+
previousInputPath = stepOutputPath;
517+
previousOutputType = outputType;
518+
}
519+
520+
// Final step: Convert the final output back to the original input type
521+
var finalDir = $"{testPath}\\final";
522+
var finalOutputPath = $"{finalDir}\\final_output.{(inputType == "arm" ? "json" : inputType)}";
523+
virtualFileSystem.CreateDirectory(finalDir);
524+
525+
ExecuteTranslationTask(previousOutputType, inputType, previousInputPath, finalOutputPath);
526+
527+
// Assert: Compare final output with original input to check no data loss
528+
AssertNoDataLoss(inputFilePath, finalOutputPath, inputType);
529+
}
530+
531+
private void ExecuteTranslationTask(string inputType, string outputType, string inputFilePath, string outputFilePath)
532+
{
533+
var task = new AggregateConfig(virtualFileSystem, mockLogger.Object)
534+
{
535+
InputDirectory = inputFilePath,
536+
InputType = inputType,
537+
OutputFile = outputFilePath,
538+
OutputType = outputType,
539+
BuildEngine = Mock.Of<IBuildEngine>()
540+
};
541+
bool result = task.Execute();
542+
Assert.IsTrue(result, $"Failed translation: {inputType} -> {outputType}");
543+
}
544+
545+
private void AssertNoDataLoss(string originalFilePath, string finalFilePath, string inputType)
546+
{
547+
string originalInput = virtualFileSystem.ReadAllText(originalFilePath);
548+
string finalOutput = virtualFileSystem.ReadAllText(finalFilePath);
549+
Assert.AreEqual(originalInput, finalOutput, $"Data mismatch after full conversion cycle for {inputType}");
550+
}
551+
552+
private static string GetSampleDataForType(string type)
553+
{
554+
return type switch
555+
{
556+
"json" => @"{
557+
""options"": [
558+
{
559+
""name"": ""Option 1"",
560+
""description"": ""First option"",
561+
""isTrue"": true,
562+
""number"": 100
563+
}
564+
]
565+
}",
566+
"arm" => @"{
567+
""$schema"": ""https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#"",
568+
""contentVersion"": ""1.0.0.0"",
569+
""parameters"": {
570+
""options"": {
571+
""type"": ""object"",
572+
""value"": {
573+
""name"": ""Option 1"",
574+
""description"": ""First option"",
575+
""isTrue"": true,
576+
""number"": 100
577+
}
578+
}
579+
}
580+
}",
581+
"yml" => @"options:
582+
- name: Option 1
583+
description: First option
584+
isTrue: true
585+
number: 100
586+
",
587+
_ => throw new InvalidOperationException("Unknown type")
588+
};
589+
}
590+
480591
/// <summary>
481592
/// Check if an option exists with a given name and source
482593
/// </summary>

src/UnitTests/UnitTests.csproj

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
<Nullable>disable</Nullable>
88
<IsPackable>false</IsPackable>
99
<IsTestProject>true</IsTestProject>
10-
<NoWarn>CS1591,CA1707,CA5394,CA1305</NoWarn>
10+
<NoWarn>CS1591,CA1707,CA5394,CA1305,CA1861</NoWarn>
1111
</PropertyGroup>
1212

1313
<ItemGroup>

src/UnitTests/VirtualFileSystem.cs

Lines changed: 1 addition & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ namespace AggregateConfigBuildTask.Tests.Unit
1010
internal sealed class VirtualFileSystem(bool isWindowsMode = true) : IFileSystem
1111
{
1212
private readonly bool isWindowsMode = isWindowsMode;
13-
private ConcurrentDictionary<string, string> fileSystem = new(
13+
private readonly ConcurrentDictionary<string, string> fileSystem = new(
1414
isWindowsMode ? StringComparer.OrdinalIgnoreCase : StringComparer.Ordinal);
1515

1616
private RegexOptions RegexOptions => isWindowsMode ? RegexOptions.IgnoreCase : RegexOptions.None;
@@ -132,14 +132,6 @@ public Stream OpenRead(string inputPath)
132132
return new MemoryStream(byteArray);
133133
}
134134

135-
/// <summary>
136-
/// Delete all files on the virtual file system.
137-
/// </summary>
138-
public void FormatSystem()
139-
{
140-
fileSystem = new ConcurrentDictionary<string, string>();
141-
}
142-
143135
/// <summary>
144136
/// Ensures that the provided directory path ends with a directory separator character.
145137
/// </summary>

0 commit comments

Comments
 (0)