Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions Directory.Packages.props
Original file line number Diff line number Diff line change
Expand Up @@ -12,5 +12,7 @@ SPDX-License-Identifier: MIT
<!-- UnitTests -->
<PackageVersion Include="JunitXml.TestLogger" Version="8.0.0" />
<PackageVersion Include="Moq" Version="4.21.0" />
<!-- fuzzing tests -->
<PackageVersion Include="FsCheck" Version="3.3.4" />
</ItemGroup>
</Project>
23 changes: 23 additions & 0 deletions FuzzingTests/FuzzingTests.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
SPDX-FileCopyrightText: 2026 Frans van Dorsselaer

SPDX-License-Identifier: MIT
-->
<Project Sdk="MSTest.Sdk">

<PropertyGroup>
<TargetFramework>$(MainTargetFramework)</TargetFramework>
<SignAssembly>True</SignAssembly>
</PropertyGroup>

<ItemGroup>
<ProjectReference Include="..\GitVersion.MsBuild\GitVersion.MsBuild.csproj" />
</ItemGroup>

<ItemGroup>
<PackageReference Include="FsCheck" />
<PackageReference Include="JunitXml.TestLogger" />
</ItemGroup>

</Project>
23 changes: 23 additions & 0 deletions FuzzingTests/GitVersionVariables_Tests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
// SPDX-FileCopyrightText: 2026 Frans van Dorsselaer
//
// SPDX-License-Identifier: MIT

using System.Text.Json.Nodes;

namespace FuzzingTests;

[TestClass]
sealed class GitVersionVariables_Tests
{
[TestMethod]
public void JsonIsParsedCorrectly()
{
var jsonGenerator = JsonGenerator.GenerateExactlyTwoPairs();

Prop.ForAll(Arb.From(jsonGenerator), (JsonObject json) =>
{
var result = GitVersionVariables.FromJson(json.ToJsonString());
return result.Count == 2 && json.All(pair => result.TryGetValue(pair.Key, out var value) && value == pair.Value!.ToString());
Comment thread
dorssel marked this conversation as resolved.
Resolved
}).QuickCheckThrowOnFailure();
}
}
7 changes: 7 additions & 0 deletions FuzzingTests/GlobalSuppressions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
// SPDX-FileCopyrightText: 2026 Frans van Dorsselaer
//
// SPDX-License-Identifier: MIT

using System.Diagnostics.CodeAnalysis;

[assembly: SuppressMessage("Performance", "CA1812:Internal class is never instantiated", Justification = "We use internal test classes")]
48 changes: 48 additions & 0 deletions FuzzingTests/JsonGenerator.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
// SPDX-FileCopyrightText: 2026 Frans van Dorsselaer
//
// SPDX-License-Identifier: MIT

using System.Text.Json.Nodes;

namespace FuzzingTests;

static class JsonGenerator
{
static readonly char[] AllowedKeyChars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz".ToCharArray();

public static Gen<JsonObject> GenerateExactlyTwoPairs()
{
// GitVersion keys are always strings of length 1 to 20, consisting of uppercase and lowercase letters.
var keyGen = Gen.Choose(1, 20).SelectMany(
length => Gen.ArrayOf(Gen.Elements(AllowedKeyChars), length).Select(chars => new string(chars)));

// GitVersion values can be either strings or integers, so we create a generator that can produce both types.
var valueGen = Gen.OneOf(
ArbMap.Default.GeneratorFor<string>().Where(s => s is not null).Select(s => JsonValue.Create(s)),
Gen.Choose(0, int.MaxValue).Select(i => JsonValue.Create(i)));

var firstPairGen = Gen.Zip(keyGen, valueGen);

// Chain the generation to enforce uniqueness on the second key
return firstPairGen.SelectMany(firstPair =>
{
var key1 = firstPair.Item1;
var val1 = firstPair.Item2;

// CRITICAL: Key 2 must be different from Key 1 to avoid a duplicate key error
var uniqueSecondKeyGen = keyGen.Where(key2 => key2 != key1);

return Gen.Zip(uniqueSecondKeyGen, valueGen).Select(secondPair =>
{
var key2 = secondPair.Item1;
var val2 = secondPair.Item2;

return new JsonObject
{
{ key1, val1 },
{ key2, val2 }
};
});
});
}
}
6 changes: 6 additions & 0 deletions FuzzingTests/MSTestSettings.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
// SPDX-FileCopyrightText: 2026 Frans van Dorsselaer
//
// SPDX-License-Identifier: MIT

[assembly: Parallelize(Scope = ExecutionScope.MethodLevel)]
[assembly: DiscoverInternals]
8 changes: 8 additions & 0 deletions FuzzingTests/Usings.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
// SPDX-FileCopyrightText: 2026 Frans van Dorsselaer
//
// SPDX-License-Identifier: MIT

global using Dorssel.GitVersion.MsBuild;

global using FsCheck;
global using FsCheck.Fluent;
146 changes: 146 additions & 0 deletions FuzzingTests/packages.lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 3 additions & 0 deletions FuzzingTests/packages.lock.json.license
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
SPDX-FileCopyrightText: 2026 Frans van Dorsselaer

SPDX-License-Identifier: MIT
19 changes: 19 additions & 0 deletions GitVersion.MsBuild/AssemblySettings.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
// SPDX-FileCopyrightText: 2026 Frans van Dorsselaer
//
// SPDX-License-Identifier: MIT

using System.Runtime.CompilerServices;

[assembly: InternalsVisibleTo("FuzzingTests, PublicKey = "
+ "002400000480000094010000060200000024000052534131000c000001000100f1c9097124f926" // DevSkim: ignore DS173237
+ "60242335d835f2f0bc70ff592f63bd0fb41d3a753441884f35c53253a0eb123a01d960dfba3903" // DevSkim: ignore DS173237
+ "7470b7272d51ade1af6fca95d260075ec71cae6559cd9e20558a6f281f53ec76108cbc4a55c5dd" // DevSkim: ignore DS173237
+ "05ceac08699305fdbdb3a7bce263b9b920a1ea077d3ad05736a47ade8a2489c33b62a37115dc64" // DevSkim: ignore DS173237
+ "6758f0f5d804e01d9729514e8ac719b9b861bf6ae820c34cd60b3bb71f4042f637829ac42eb105" // DevSkim: ignore DS173237
+ "f3d55cbb10dae14ff7c84198b8a74328eca4c5815cac4734d3c2581496cbbe253cff89bdb33f8f" // DevSkim: ignore DS173237
+ "44e447f33ef3e227eb6a4e2c9e197c2dd90fc24c054be4f90e38dc95a47878854556debd0b8540" // DevSkim: ignore DS173237
+ "221cd2f782e7281191af6a5463ce34c1caf03a40d1b2c26ddf717db931b74633b9102b855699db" // DevSkim: ignore DS173237
+ "299b2c8e4c1710eee22a79d360fc953e872d5722dd3851a5cccd5697c102e455491890c0ff1e40" // DevSkim: ignore DS173237
+ "0d050a4d6efafb8e62e59df7239fda4b06856e3abb17d8b32530c43f2afffc626a94046c6d58ea" // DevSkim: ignore DS173237
+ "6af4915f06baca85b66d157ea2655dde145054dac3a5543dd7e5" // DevSkim: ignore DS173237
)]
2 changes: 1 addition & 1 deletion GitVersion.MsBuild/GetVersion.cs
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ public class GetVersion : GitVersionTaskBase

public override bool Execute()
{
foreach (var keyValue in GitVersionVariables.FromFile(VersionFile!))
foreach (var keyValue in GitVersionVariables.FromJson(File.ReadAllText(VersionFile)))
{
GetType().GetProperty(keyValue.Key).SetValue(this, keyValue.Value);
}
Expand Down
23 changes: 10 additions & 13 deletions GitVersion.MsBuild/GitVersionVariables.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,26 +3,23 @@
// SPDX-License-Identifier: MIT

using System.Collections.ObjectModel;
using System.Runtime.Serialization.Json;
using System.Text;

namespace Dorssel.GitVersion.MsBuild;

static class GitVersionVariables
{
public static ReadOnlyDictionary<string, string> FromFile(string versionFile)
public static ReadOnlyDictionary<string, string> FromJson(string json)
{
var dictionary = new Dictionary<string, string>();

foreach (var line in File.ReadAllLines(versionFile))
{
var keyValue = line.Split(':');
if (keyValue.Length != 2)
var serializer = new DataContractJsonSerializer(typeof(Dictionary<string, string>),
new DataContractJsonSerializerSettings()
{
// opening or closing brace
continue;
}
dictionary.Add(keyValue[0].Trim(' ', '"'), keyValue[1].Trim(' ', '"', ','));
}
UseSimpleDictionaryFormat = true
Comment thread
dorssel marked this conversation as resolved.
Resolved
});

return new(dictionary);
using var stream = new MemoryStream(Encoding.UTF8.GetBytes(json));
var result = (Dictionary<string, string>)serializer.ReadObject(stream);
return new(result);
}
}
1 change: 1 addition & 0 deletions gitversion-msbuild.slnx
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ SPDX-License-Identifier: MIT
<Platform Project="x64" />
<Build Project="false" />
</Project>
<Project Path="FuzzingTests/FuzzingTests.csproj" />
<Project Path="GitVersion.MsBuild/GitVersion.MsBuild.csproj" />
<Project Path="UnitTests/UnitTests.csproj" />
</Solution>
Loading