Skip to content

Commit 8e74c23

Browse files
[Improve] coverage
1 parent 3dbdc68 commit 8e74c23

12 files changed

Lines changed: 935 additions & 146 deletions

File tree

Lines changed: 216 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,216 @@
1+
// -------------------------------------------------------------------------------------------------
2+
// <copyright file="ChecksumKindProviderTestFixture.cs" company="Starion Group S.A.">
3+
//
4+
// Copyright 2022-2026 Starion Group S.A.
5+
//
6+
// Licensed under the Apache License, Version 2.0 (the "License");
7+
// you may not use this file except in compliance with the License.
8+
// You may obtain a copy of the License at
9+
//
10+
// http://www.apache.org/licenses/LICENSE-2.0
11+
//
12+
// Unless required by applicable law or agreed to in writing, software
13+
// distributed under the License is distributed on an "AS IS" BASIS,
14+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15+
// See the License for the specific language governing permissions and
16+
// limitations under the License.
17+
//
18+
// </copyright>
19+
// ------------------------------------------------------------------------------------------------
20+
21+
namespace SysML2.NET.Extensions.Tests.Core.ModelInterchange
22+
{
23+
using System;
24+
using System.Buffers;
25+
using System.Linq;
26+
using System.Text;
27+
28+
using NUnit.Framework;
29+
30+
using SysML2.NET.ModelInterchange;
31+
32+
[TestFixture]
33+
public class ChecksumKindProviderTestFixture
34+
{
35+
[TestCase(ChecksumKind.SHA1, "SHA1")]
36+
[TestCase(ChecksumKind.SHA224, "SHA224")]
37+
[TestCase(ChecksumKind.SHA256, "SHA256")]
38+
[TestCase(ChecksumKind.SHA384, "SHA-384")]
39+
[TestCase(ChecksumKind.SHA3256, "SHA3-256")]
40+
[TestCase(ChecksumKind.SHA3384, "SHA3-384")]
41+
[TestCase(ChecksumKind.SHA3512, "SHA3-512")]
42+
[TestCase(ChecksumKind.BLAKE2b256, "BLAKE2b-256")]
43+
[TestCase(ChecksumKind.BLAKE2b384, "BLAKE2b-384")]
44+
[TestCase(ChecksumKind.BLAKE2b512, "BLAKE2b-512")]
45+
[TestCase(ChecksumKind.BLAKE3, "BLAKE3")]
46+
[TestCase(ChecksumKind.MD2, "MD2")]
47+
[TestCase(ChecksumKind.MD4, "MD4")]
48+
[TestCase(ChecksumKind.MD5, "MD5")]
49+
[TestCase(ChecksumKind.MD6, "MD6")]
50+
[TestCase(ChecksumKind.ADLER32, "ADLER32")]
51+
public void Verify_that_Parse_charSpan_parses_known_values_case_insensitively(ChecksumKind expected, string token)
52+
{
53+
// Upper
54+
Assert.That(ChecksumKindProvider.Parse(token.AsSpan()), Is.EqualTo(expected));
55+
56+
// Lower
57+
Assert.That(ChecksumKindProvider.Parse(token.ToLowerInvariant().AsSpan()), Is.EqualTo(expected));
58+
59+
// Mixed (simple mixed variant)
60+
var mixed = token.Length > 1
61+
? char.ToLowerInvariant(token[0]) + token.Substring(1).ToUpperInvariant()
62+
: token;
63+
Assert.That(ChecksumKindProvider.Parse(mixed.AsSpan()), Is.EqualTo(expected));
64+
}
65+
66+
[TestCase(ChecksumKind.SHA1, "SHA1")]
67+
[TestCase(ChecksumKind.SHA224, "SHA224")]
68+
[TestCase(ChecksumKind.SHA256, "SHA256")]
69+
[TestCase(ChecksumKind.SHA384, "SHA-384")]
70+
[TestCase(ChecksumKind.SHA3256, "SHA3-256")]
71+
[TestCase(ChecksumKind.SHA3384, "SHA3-384")]
72+
[TestCase(ChecksumKind.SHA3512, "SHA3-512")]
73+
[TestCase(ChecksumKind.BLAKE2b256, "BLAKE2b-256")]
74+
[TestCase(ChecksumKind.BLAKE2b384, "BLAKE2b-384")]
75+
[TestCase(ChecksumKind.BLAKE2b512, "BLAKE2b-512")]
76+
[TestCase(ChecksumKind.BLAKE3, "BLAKE3")]
77+
[TestCase(ChecksumKind.MD2, "MD2")]
78+
[TestCase(ChecksumKind.MD4, "MD4")]
79+
[TestCase(ChecksumKind.MD5, "MD5")]
80+
[TestCase(ChecksumKind.MD6, "MD6")]
81+
[TestCase(ChecksumKind.ADLER32, "ADLER32")]
82+
public void Verify_that_Parse_utf8Span_parses_known_values_case_sensitively(ChecksumKind expected, string token)
83+
{
84+
// Note: this overload uses SequenceEqual against uppercase literals.
85+
var utf8 = Encoding.UTF8.GetBytes(token);
86+
Assert.That(ChecksumKindProvider.Parse(utf8.AsSpan()), Is.EqualTo(expected));
87+
}
88+
89+
[TestCase(ChecksumKind.SHA1, "SHA1")]
90+
[TestCase(ChecksumKind.SHA224, "SHA224")]
91+
[TestCase(ChecksumKind.SHA256, "SHA256")]
92+
[TestCase(ChecksumKind.SHA384, "SHA-384")]
93+
[TestCase(ChecksumKind.SHA3256, "SHA3-256")]
94+
[TestCase(ChecksumKind.SHA3384, "SHA3-384")]
95+
[TestCase(ChecksumKind.SHA3512, "SHA3-512")]
96+
[TestCase(ChecksumKind.BLAKE2b256, "BLAKE2b-256")]
97+
[TestCase(ChecksumKind.BLAKE2b384, "BLAKE2b-384")]
98+
[TestCase(ChecksumKind.BLAKE2b512, "BLAKE2b-512")]
99+
[TestCase(ChecksumKind.BLAKE3, "BLAKE3")]
100+
[TestCase(ChecksumKind.MD2, "MD2")]
101+
[TestCase(ChecksumKind.MD4, "MD4")]
102+
[TestCase(ChecksumKind.MD5, "MD5")]
103+
[TestCase(ChecksumKind.MD6, "MD6")]
104+
[TestCase(ChecksumKind.ADLER32, "ADLER32")]
105+
public void Verify_that_Parse_readonlySequence_parses_single_segment(ChecksumKind expected, string token)
106+
{
107+
var bytes = Encoding.UTF8.GetBytes(token);
108+
var sequence = new ReadOnlySequence<byte>(bytes);
109+
Assert.That(ChecksumKindProvider.Parse(sequence), Is.EqualTo(expected));
110+
}
111+
112+
[Test]
113+
public void Verify_that_Parse_readonlySequence_parses_multi_segment_using_stackalloc_copy()
114+
{
115+
// Multi-segment "SHA256" -> "SHA" + "256"
116+
var seg1 = Encoding.UTF8.GetBytes("SHA");
117+
var seg2 = Encoding.UTF8.GetBytes("256");
118+
119+
var first = new BufferSegment(seg1);
120+
var last = first.Append(seg2);
121+
122+
var sequence = new ReadOnlySequence<byte>(first, 0, last, last.Memory.Length);
123+
124+
Assert.That(sequence.IsSingleSegment, Is.False);
125+
Assert.That(ChecksumKindProvider.Parse(sequence), Is.EqualTo(ChecksumKind.SHA256));
126+
}
127+
128+
[Test]
129+
public void Verify_that_Parse_readonlySequence_throws_when_length_exceeds_16()
130+
{
131+
var bytes = Enumerable.Repeat((byte)'A', 17).ToArray();
132+
var sequence = new ReadOnlySequence<byte>(bytes);
133+
134+
var ex = Assert.Throws<ArgumentException>(() => ChecksumKindProvider.Parse(sequence));
135+
Assert.That(ex!.ParamName, Is.EqualTo("value"));
136+
Assert.That(ex.Message, Does.Contain("'AAAAAAAAAAAAAAAAA' is not a valid ChecksumKind (Parameter 'value')"));
137+
}
138+
139+
[Test]
140+
public void Verify_that_Parse_charSpan_throws_for_unknown_value()
141+
{
142+
var ex = Assert.Throws<ArgumentException>(() => ChecksumKindProvider.Parse("NOPE".AsSpan()));
143+
Assert.That(ex!.ParamName, Is.EqualTo("value"));
144+
Assert.That(ex.Message, Does.Contain("is not a valid ChecksumKind"));
145+
}
146+
147+
[Test]
148+
public void Verify_that_Parse_utf8Span_throws_for_unknown_value_and_message_contains_decoded_value()
149+
{
150+
var bytes = Encoding.UTF8.GetBytes("NOPE");
151+
var ex = Assert.Throws<ArgumentException>(() => ChecksumKindProvider.Parse(bytes.AsSpan()));
152+
Assert.That(ex!.ParamName, Is.EqualTo("value"));
153+
Assert.That(ex.Message, Does.Contain("NOPE"));
154+
Assert.That(ex.Message, Does.Contain("is not a valid ChecksumKind"));
155+
}
156+
157+
[TestCase(ChecksumKind.SHA1, "SHA1")]
158+
[TestCase(ChecksumKind.SHA224, "SHA224")]
159+
[TestCase(ChecksumKind.SHA256, "SHA256")]
160+
[TestCase(ChecksumKind.SHA384, "SHA-384")]
161+
[TestCase(ChecksumKind.SHA3256, "SHA3-256")]
162+
[TestCase(ChecksumKind.SHA3384, "SHA3-384")]
163+
[TestCase(ChecksumKind.SHA3512, "SHA3-512")]
164+
[TestCase(ChecksumKind.BLAKE2b256, "BLAKE2b-256")]
165+
[TestCase(ChecksumKind.BLAKE2b384, "BLAKE2b-384")]
166+
[TestCase(ChecksumKind.BLAKE2b512, "BLAKE2b-512")]
167+
[TestCase(ChecksumKind.BLAKE3, "BLAKE3")]
168+
[TestCase(ChecksumKind.MD2, "MD2")]
169+
[TestCase(ChecksumKind.MD4, "MD4")]
170+
[TestCase(ChecksumKind.MD5, "MD5")]
171+
[TestCase(ChecksumKind.MD6, "MD6")]
172+
[TestCase(ChecksumKind.ADLER32, "ADLER32")]
173+
public void Verify_that_ToUtf8LowerBytes_returns_expected_token_and_roundtrips_via_Parse_utf8Span(
174+
ChecksumKind kind,
175+
string expectedToken)
176+
{
177+
var bytes = ChecksumKindProvider.ToUtf8LowerBytes(kind);
178+
179+
// Verify exact bytes content
180+
Assert.That(Encoding.UTF8.GetString(bytes), Is.EqualTo(expectedToken));
181+
182+
// Round-trip via Parse(ReadOnlySpan<byte>)
183+
Assert.That(ChecksumKindProvider.Parse(bytes), Is.EqualTo(kind));
184+
}
185+
186+
[Test]
187+
public void Verify_that_ToUtf8LowerBytes_throws_for_undefined_enum_value()
188+
{
189+
// Pick a clearly undefined value
190+
var invalid = (ChecksumKind)123456;
191+
Assert.Throws<ArgumentOutOfRangeException>(() => ChecksumKindProvider.ToUtf8LowerBytes(invalid));
192+
}
193+
194+
/// <summary>
195+
/// Minimal ReadOnlySequence segment helper to build multi-segment sequences.
196+
/// </summary>
197+
private sealed class BufferSegment : ReadOnlySequenceSegment<byte>
198+
{
199+
public BufferSegment(ReadOnlyMemory<byte> memory)
200+
{
201+
Memory = memory;
202+
}
203+
204+
public BufferSegment Append(ReadOnlyMemory<byte> memory)
205+
{
206+
var segment = new BufferSegment(memory)
207+
{
208+
RunningIndex = RunningIndex + Memory.Length
209+
};
210+
211+
Next = segment;
212+
return segment;
213+
}
214+
}
215+
}
216+
}

SysML2.NET.Extensions/ModelInterchange/ChecksumKindProvider.cs

Lines changed: 48 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -18,10 +18,6 @@
1818
// </copyright>
1919
// ------------------------------------------------------------------------------------------------
2020

21-
// ------------------------------------------------------------------------------------------------
22-
// --------THIS IS AN AUTOMATICALLY GENERATED FILE. ANY MANUAL CHANGES WILL BE OVERWRITTEN!--------
23-
// ------------------------------------------------------------------------------------------------
24-
2521
namespace SysML2.NET.ModelInterchange
2622
{
2723
using System;
@@ -74,34 +70,40 @@ public static class ChecksumKindProvider
7470
/// </remarks>
7571
public static ChecksumKind Parse(ReadOnlySpan<char> value)
7672
{
73+
if (value == null)
74+
{
75+
throw new ArgumentNullException(nameof(value));
76+
}
77+
7778
switch (value.Length)
7879
{
79-
case 4:
80+
case 3:
8081
if (value.Equals("MD2".AsSpan(), StringComparison.OrdinalIgnoreCase)) return ChecksumKind.MD2;
8182
if (value.Equals("MD4".AsSpan(), StringComparison.OrdinalIgnoreCase)) return ChecksumKind.MD4;
8283
if (value.Equals("MD5".AsSpan(), StringComparison.OrdinalIgnoreCase)) return ChecksumKind.MD5;
8384
if (value.Equals("MD6".AsSpan(), StringComparison.OrdinalIgnoreCase)) return ChecksumKind.MD6;
85+
break;
86+
case 4:
8487
if (value.Equals("SHA1".AsSpan(), StringComparison.OrdinalIgnoreCase)) return ChecksumKind.SHA1;
8588
break;
86-
8789
case 6:
8890
if (value.Equals("SHA224".AsSpan(), StringComparison.OrdinalIgnoreCase)) return ChecksumKind.SHA224;
8991
if (value.Equals("SHA256".AsSpan(), StringComparison.OrdinalIgnoreCase)) return ChecksumKind.SHA256;
90-
if (value.Equals("SHA384".AsSpan(), StringComparison.OrdinalIgnoreCase)) return ChecksumKind.SHA384;
91-
if (value.Equals("ADLER32".AsSpan(), StringComparison.OrdinalIgnoreCase)) return ChecksumKind.ADLER32;
9292
if (value.Equals("BLAKE3".AsSpan(), StringComparison.OrdinalIgnoreCase)) return ChecksumKind.BLAKE3;
9393
break;
94-
9594
case 7:
96-
if (value.Equals("SHA3256".AsSpan(), StringComparison.OrdinalIgnoreCase)) return ChecksumKind.SHA3256;
97-
if (value.Equals("SHA3384".AsSpan(), StringComparison.OrdinalIgnoreCase)) return ChecksumKind.SHA3384;
98-
if (value.Equals("SHA3512".AsSpan(), StringComparison.OrdinalIgnoreCase)) return ChecksumKind.SHA3512;
95+
if (value.Equals("ADLER32".AsSpan(), StringComparison.OrdinalIgnoreCase)) return ChecksumKind.ADLER32;
96+
if (value.Equals("SHA-384".AsSpan(), StringComparison.OrdinalIgnoreCase)) return ChecksumKind.SHA384;
9997
break;
100-
101-
case 9:
102-
if (value.Equals("BLAKE2b256".AsSpan(), StringComparison.OrdinalIgnoreCase)) return ChecksumKind.BLAKE2b256;
103-
if (value.Equals("BLAKE2b384".AsSpan(), StringComparison.OrdinalIgnoreCase)) return ChecksumKind.BLAKE2b384;
104-
if (value.Equals("BLAKE2b512".AsSpan(), StringComparison.OrdinalIgnoreCase)) return ChecksumKind.BLAKE2b512;
98+
case 8:
99+
if (value.Equals("SHA3-256".AsSpan(), StringComparison.OrdinalIgnoreCase)) return ChecksumKind.SHA3256;
100+
if (value.Equals("SHA3-384".AsSpan(), StringComparison.OrdinalIgnoreCase)) return ChecksumKind.SHA3384;
101+
if (value.Equals("SHA3-512".AsSpan(), StringComparison.OrdinalIgnoreCase)) return ChecksumKind.SHA3512;
102+
break;
103+
case 11:
104+
if (value.Equals("BLAKE2b-256".AsSpan(), StringComparison.OrdinalIgnoreCase)) return ChecksumKind.BLAKE2b256;
105+
if (value.Equals("BLAKE2b-384".AsSpan(), StringComparison.OrdinalIgnoreCase)) return ChecksumKind.BLAKE2b384;
106+
if (value.Equals("BLAKE2b-512".AsSpan(), StringComparison.OrdinalIgnoreCase)) return ChecksumKind.BLAKE2b512;
105107
break;
106108
}
107109

@@ -122,51 +124,46 @@ public static ChecksumKind Parse(ReadOnlySpan<char> value)
122124
/// Thrown when <paramref name="value"/> does not represent
123125
/// a valid checksum algorithm.
124126
/// </exception>
125-
/// <remarks>
126-
/// <para>
127-
/// This overload is optimized for streaming deserialization.
128-
/// It avoids heap allocations and performs direct span comparison.
129-
/// </para>
130-
/// <para>
131-
/// Matching is performed using <see cref="ReadOnlySpan{Byte}.SequenceEqual(ReadOnlySpan{Byte})"/>.
132-
/// </para>
133-
/// </remarks>
134127
public static ChecksumKind Parse(ReadOnlySpan<byte> value)
135128
{
129+
if (value == null)
130+
{
131+
throw new ArgumentNullException(nameof(value));
132+
}
133+
136134
switch (value.Length)
137135
{
138-
case 4:
136+
case 3:
139137
if (value.SequenceEqual("MD2"u8)) return ChecksumKind.MD2;
140138
if (value.SequenceEqual("MD4"u8)) return ChecksumKind.MD4;
141139
if (value.SequenceEqual("MD5"u8)) return ChecksumKind.MD5;
142-
if (value.SequenceEqual("MD6"u8)) return ChecksumKind.MD6;
143-
if (value.SequenceEqual("SHA1"u8)) return ChecksumKind.SHA1;
140+
if (value.SequenceEqual("MD6"u8)) return ChecksumKind.MD6;
141+
break;
142+
case 4:
143+
if (value.SequenceEqual("SHA1"u8)) return ChecksumKind.SHA1;
144144
break;
145-
146145
case 6:
147146
if (value.SequenceEqual("SHA224"u8)) return ChecksumKind.SHA224;
148147
if (value.SequenceEqual("SHA256"u8)) return ChecksumKind.SHA256;
149-
if (value.SequenceEqual("SHA384"u8)) return ChecksumKind.SHA384;
150-
if (value.SequenceEqual("ADLER32"u8)) return ChecksumKind.ADLER32;
151148
if (value.SequenceEqual("BLAKE3"u8)) return ChecksumKind.BLAKE3;
152149
break;
153-
154150
case 7:
155-
if (value.SequenceEqual("SHA3256"u8)) return ChecksumKind.SHA3256;
156-
if (value.SequenceEqual("SHA3384"u8)) return ChecksumKind.SHA3384;
157-
if (value.SequenceEqual("SHA3512"u8)) return ChecksumKind.SHA3512;
151+
if (value.SequenceEqual("SHA-384"u8)) return ChecksumKind.SHA384;
152+
if (value.SequenceEqual("ADLER32"u8)) return ChecksumKind.ADLER32;
158153
break;
159-
160-
case 9:
161-
if (value.SequenceEqual("BLAKE2b256"u8)) return ChecksumKind.BLAKE2b256;
162-
if (value.SequenceEqual("BLAKE2b384"u8)) return ChecksumKind.BLAKE2b384;
163-
if (value.SequenceEqual("BLAKE2b512"u8)) return ChecksumKind.BLAKE2b512;
154+
case 8:
155+
if (value.SequenceEqual("SHA3-256"u8)) return ChecksumKind.SHA3256;
156+
if (value.SequenceEqual("SHA3-384"u8)) return ChecksumKind.SHA3384;
157+
if (value.SequenceEqual("SHA3-512"u8)) return ChecksumKind.SHA3512;
158+
break;
159+
case 11:
160+
if (value.SequenceEqual("BLAKE2b-256"u8)) return ChecksumKind.BLAKE2b256;
161+
if (value.SequenceEqual("BLAKE2b-384"u8)) return ChecksumKind.BLAKE2b384;
162+
if (value.SequenceEqual("BLAKE2b-512"u8)) return ChecksumKind.BLAKE2b512;
164163
break;
165164
}
166165

167-
throw new ArgumentException(
168-
$"'{System.Text.Encoding.UTF8.GetString(value)}' is not a valid ChecksumKind",
169-
nameof(value));
166+
throw new ArgumentException($"'{System.Text.Encoding.UTF8.GetString(value)}' is not a valid ChecksumKind", nameof(value));
170167
}
171168

172169
/// <summary>
@@ -247,13 +244,13 @@ public static ReadOnlySpan<byte> ToUtf8LowerBytes(ChecksumKind value)
247244
ChecksumKind.SHA1 => "SHA1"u8,
248245
ChecksumKind.SHA224 => "SHA224"u8,
249246
ChecksumKind.SHA256 => "SHA256"u8,
250-
ChecksumKind.SHA384 => "SHA384"u8,
251-
ChecksumKind.SHA3256 => "SHA3256"u8,
252-
ChecksumKind.SHA3384 => "SHA3384"u8,
253-
ChecksumKind.SHA3512 => "SHA3512"u8,
254-
ChecksumKind.BLAKE2b256 => "BLAKE2b256"u8,
255-
ChecksumKind.BLAKE2b384 => "BLAKE2b384"u8,
256-
ChecksumKind.BLAKE2b512 => "BLAKE2b512"u8,
247+
ChecksumKind.SHA384 => "SHA-384"u8,
248+
ChecksumKind.SHA3256 => "SHA3-256"u8,
249+
ChecksumKind.SHA3384 => "SHA3-384"u8,
250+
ChecksumKind.SHA3512 => "SHA3-512"u8,
251+
ChecksumKind.BLAKE2b256 => "BLAKE2b-256"u8,
252+
ChecksumKind.BLAKE2b384 => "BLAKE2b-384"u8,
253+
ChecksumKind.BLAKE2b512 => "BLAKE2b-512"u8,
257254
ChecksumKind.BLAKE3 => "BLAKE3"u8,
258255
ChecksumKind.MD2 => "MD2"u8,
259256
ChecksumKind.MD4 => "MD4"u8,
@@ -265,7 +262,3 @@ public static ReadOnlySpan<byte> ToUtf8LowerBytes(ChecksumKind value)
265262
}
266263
}
267264
}
268-
269-
// ------------------------------------------------------------------------------------------------
270-
// --------THIS IS AN AUTOMATICALLY GENERATED FILE. ANY MANUAL CHANGES WILL BE OVERWRITTEN!--------
271-
// ------------------------------------------------------------------------------------------------

0 commit comments

Comments
 (0)