Skip to content

Commit 4f77bb3

Browse files
committed
test(otp): Add unit tests for IsValidSequenceProgression method
1 parent 76e03fb commit 4f77bb3

File tree

2 files changed

+76
-2
lines changed

2 files changed

+76
-2
lines changed

Yubico.YubiKey/src/Yubico/YubiKey/Pipelines/OtpErrorTransform.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ public ResponseApdu Invoke(CommandApdu command, Type commandType, Type responseT
6060
var responseApdu = _nextTransform.Invoke(command, commandType, responseType);
6161
var readStatusResponse = new ReadStatusResponse(responseApdu);
6262
var otpStatus = readStatusResponse.GetData();
63-
byte nextSequence = otpStatus.SequenceNumber;
63+
int nextSequence = otpStatus.SequenceNumber;
6464

6565
// If we see the sequence number change, we can assume that the configuration was applied successfully. Otherwise
6666
// we just invent an error in the response.
@@ -82,7 +82,7 @@ public ResponseApdu Invoke(CommandApdu command, Type commandType, Type responseT
8282

8383
public void Cleanup() => _nextTransform.Cleanup();
8484

85-
private static bool IsValidSequenceProgression(int beforeSequence, int nextSequence, OtpStatus afterStatus)
85+
internal static bool IsValidSequenceProgression(int beforeSequence, int nextSequence, OtpStatus afterStatus)
8686
{
8787
const int configStatusMask = 0x1F;
8888

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
using Xunit;
2+
using Yubico.YubiKey.Otp;
3+
4+
namespace Yubico.YubiKey.Pipelines;
5+
6+
public class OtpErrorTransformTests
7+
{
8+
[Theory]
9+
[InlineData(0, 1)] // First increment
10+
[InlineData(5, 6)] // Normal increment
11+
[InlineData(254, 255)] // Near byte boundary
12+
[InlineData(257, 258)] // Near byte boundary
13+
14+
public void IsValidSequenceProgression_NormalIncrement_ReturnsTrue(int before, int after)
15+
{
16+
var status = CreateOtpStatus(touchLevel: 0xFF); // TouchLevel irrelevant
17+
18+
bool isValid = OtpErrorTransform.IsValidSequenceProgression(before, after, status);
19+
20+
Assert.True(isValid);
21+
}
22+
23+
[Theory]
24+
[InlineData(0, 2)] // Skip increment
25+
[InlineData(5, 7)] // Jump by 2
26+
[InlineData(10, 8)] // Backwards
27+
public void IsValidSequenceProgression_InvalidIncrement_ReturnsFalse(int before, int after)
28+
{
29+
var status = CreateOtpStatus(touchLevel: 0x00); // TouchLevel irrelevant
30+
31+
bool isValid = OtpErrorTransform.IsValidSequenceProgression(before, after, status);
32+
33+
Assert.False(isValid);
34+
}
35+
36+
[Theory]
37+
[InlineData(1, 0x00)] // Config bits clear
38+
[InlineData(5, 0x20)] // Upper bits set, config clear
39+
[InlineData(255, 0xE0)] // Multiple upper bits, config clear
40+
public void IsValidSequenceProgression_ValidReset_ReturnsTrue(int before, byte touchLevel)
41+
{
42+
var status = CreateOtpStatus(touchLevel);
43+
44+
bool isValid = OtpErrorTransform.IsValidSequenceProgression(before, 0, status);
45+
46+
Assert.True(isValid);
47+
}
48+
49+
[Theory]
50+
[InlineData(0, 0x00)] // Already zero (invalid before state)
51+
[InlineData(1, 0x01)] // Config bit set
52+
[InlineData(5, 0x1F)] // All config bits set
53+
[InlineData(5, 0x21)] // Config + upper bits set
54+
public void IsValidSequenceProgression_InvalidReset_ReturnsFalse(int before, byte touchLevel)
55+
{
56+
var status = CreateOtpStatus(touchLevel);
57+
58+
bool isValid = OtpErrorTransform.IsValidSequenceProgression(before, 0, status);
59+
60+
Assert.False(isValid);
61+
}
62+
63+
private static OtpStatus CreateOtpStatus(byte touchLevel) => new()
64+
{
65+
FirmwareVersion = new FirmwareVersion(),
66+
SequenceNumber = 0,
67+
TouchLevel = touchLevel,
68+
ShortPressConfigured = false,
69+
LongPressConfigured = false,
70+
ShortPressRequiresTouch = false,
71+
LongPressRequiresTouch = false,
72+
LedBehaviorInverted = false
73+
};
74+
}

0 commit comments

Comments
 (0)