• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

orion-ecs / keen-eye / 20386896415

20 Dec 2025 01:18AM UTC coverage: 62.508% (-24.5%) from 87.015%
20386896415

push

github

tyevco
Add KeenEyes.Testing Phase 2: Graphics, Platform, Logging, Encryption, Network mocks

Implements comprehensive testing infrastructure for headless game testing:

Graphics mocks:
- MockWindow: Headless window with lifecycle events and device creation
- MockGraphicsDevice: Low-level GPU state tracking (buffers, textures, shaders)
- MockGraphicsContext: High-level GPU operations with resource management
- Mock2DRenderer: 2D rendering command recording with batching
- MockTextRenderer: Text rendering with effects (outline, shadow)
- MockFontManager: Font metrics and text measurement
- GraphicsAssertions: Fluent verification helpers

Platform mocks:
- MockLoopProvider: Step-through game loop for deterministic testing
- LoopAssertions: Loop behavior verification

Logging mocks:
- MockLogProvider: Log capture with level filtering
- LogAssertions: Log verification (errors, warnings, content matching)

Encryption mocks:
- MockEncryptionProvider: PassThrough, Reversible, and Tracking modes
- EncryptionAssertions: Encryption operation verification

Network mocks:
- INetworkContext: Network abstraction interface
- MockNetworkContext: Connection simulation, message queuing, latency/packet loss
- NetworkConnectionState: Connection state enumeration

Also includes:
- Input mocks from Phase 1 (MockInputContext, MockKeyboard, MockMouse, MockGamepad)
- Event recording and assertions
- Plugin testing infrastructure
- TestWorld and TestWorldBuilder integration

Tests: 460 passing

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

2695 of 3764 branches covered (71.6%)

Branch coverage included in aggregate %.

1238 of 2566 new or added lines in 29 files covered. (48.25%)

172 existing lines in 6 files now uncovered.

15461 of 25282 relevant lines covered (61.15%)

0.85 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

96.97
/src/KeenEyes.Testing/Encryption/MockEncryptionProvider.cs
1
using KeenEyes.Persistence.Encryption;
2

3
namespace KeenEyes.Testing.Encryption;
4

5
/// <summary>
6
/// Modes for the mock encryption provider.
7
/// </summary>
8
public enum MockEncryptionMode
9
{
10
    /// <summary>
11
    /// Data passes through unchanged. IsEncrypted returns false.
12
    /// </summary>
13
    PassThrough,
14

15
    /// <summary>
16
    /// Data is XOR'd with a key for reversible transformation. IsEncrypted returns true.
17
    /// </summary>
18
    Reversible,
19

20
    /// <summary>
21
    /// Data is stored but returned unchanged. Useful for tracking operations.
22
    /// </summary>
23
    Tracking
24
}
25

26
/// <summary>
27
/// A mock implementation of <see cref="IEncryptionProvider"/> for testing encryption
28
/// and decryption operations without real cryptographic operations.
29
/// </summary>
30
/// <remarks>
31
/// <para>
32
/// MockEncryptionProvider supports multiple modes for different testing scenarios:
33
/// <list type="bullet">
34
///   <item><description><see cref="MockEncryptionMode.PassThrough"/>: Data unchanged</description></item>
35
///   <item><description><see cref="MockEncryptionMode.Reversible"/>: XOR-based transformation</description></item>
36
///   <item><description><see cref="MockEncryptionMode.Tracking"/>: Stores operations for verification</description></item>
37
/// </list>
38
/// </para>
39
/// <para>
40
/// Use the <see cref="Operations"/> list to verify encryption/decryption was called.
41
/// </para>
42
/// </remarks>
43
/// <example>
44
/// <code>
45
/// var crypto = new MockEncryptionProvider();
46
/// crypto.Mode = MockEncryptionMode.Reversible;
47
///
48
/// var data = Encoding.UTF8.GetBytes("secret");
49
/// var encrypted = crypto.Encrypt(data);
50
/// var decrypted = crypto.Decrypt(encrypted);
51
///
52
/// decrypted.Should().BeEquivalentTo(data);
53
/// crypto.EncryptCount.Should().Be(1);
54
/// </code>
55
/// </example>
56
public sealed class MockEncryptionProvider : IEncryptionProvider
57
{
58
    private readonly byte[] xorKey = [0x42, 0x13, 0x37, 0xAB, 0xCD, 0xEF, 0x12, 0x34];
1✔
59

60
    /// <summary>
61
    /// Gets or sets the mock encryption mode.
62
    /// </summary>
63
    public MockEncryptionMode Mode { get; set; } = MockEncryptionMode.PassThrough;
1✔
64

65
    /// <summary>
66
    /// Gets the list of all recorded operations.
67
    /// </summary>
68
    public List<EncryptionOperation> Operations { get; } = [];
1✔
69

70
    /// <summary>
71
    /// Gets the number of times Encrypt was called.
72
    /// </summary>
73
    public int EncryptCount { get; private set; }
1✔
74

75
    /// <summary>
76
    /// Gets the number of times Decrypt was called.
77
    /// </summary>
78
    public int DecryptCount { get; private set; }
1✔
79

80
    /// <summary>
81
    /// Gets or sets whether encryption should fail with an exception.
82
    /// </summary>
83
    public bool ShouldFailEncrypt { get; set; }
1✔
84

85
    /// <summary>
86
    /// Gets or sets whether decryption should fail with an exception.
87
    /// </summary>
88
    public bool ShouldFailDecrypt { get; set; }
1✔
89

90
    /// <summary>
91
    /// Gets or sets a custom encryption function.
92
    /// </summary>
93
    public Func<byte[], byte[]>? CustomEncrypt { get; set; }
1✔
94

95
    /// <summary>
96
    /// Gets or sets a custom decryption function.
97
    /// </summary>
98
    public Func<byte[], byte[]>? CustomDecrypt { get; set; }
1✔
99

100
    #region IEncryptionProvider Implementation
101

102
    /// <inheritdoc />
103
    public string Name => "MockEncryptionProvider";
1✔
104

105
    /// <inheritdoc />
106
    public bool IsEncrypted => Mode != MockEncryptionMode.PassThrough;
1✔
107

108
    /// <inheritdoc />
109
    public byte[] Encrypt(byte[] data)
110
    {
111
        EncryptCount++;
1✔
112
        Operations.Add(new EncryptionOperation(OperationType.Encrypt, data.Length, DateTime.UtcNow));
1✔
113

114
        if (ShouldFailEncrypt)
1✔
115
        {
116
            throw new InvalidOperationException("Mock encryption failed (ShouldFailEncrypt = true)");
1✔
117
        }
118

119
        if (CustomEncrypt != null)
1✔
120
        {
121
            return CustomEncrypt(data);
1✔
122
        }
123

124
        return Mode switch
1✔
125
        {
1✔
126
            MockEncryptionMode.PassThrough => data,
1✔
127
            MockEncryptionMode.Reversible => XorTransform(data),
1✔
128
            MockEncryptionMode.Tracking => data,
1✔
NEW
129
            _ => data
×
130
        };
1✔
131
    }
132

133
    /// <inheritdoc />
134
    public byte[] Decrypt(byte[] encryptedData)
135
    {
136
        DecryptCount++;
1✔
137
        Operations.Add(new EncryptionOperation(OperationType.Decrypt, encryptedData.Length, DateTime.UtcNow));
1✔
138

139
        if (ShouldFailDecrypt)
1✔
140
        {
141
            throw new System.Security.Cryptography.CryptographicException("Mock decryption failed (ShouldFailDecrypt = true)");
1✔
142
        }
143

144
        if (CustomDecrypt != null)
1✔
145
        {
146
            return CustomDecrypt(encryptedData);
1✔
147
        }
148

149
        return Mode switch
1✔
150
        {
1✔
151
            MockEncryptionMode.PassThrough => encryptedData,
1✔
152
            MockEncryptionMode.Reversible => XorTransform(encryptedData),
1✔
153
            MockEncryptionMode.Tracking => encryptedData,
1✔
NEW
154
            _ => encryptedData
×
155
        };
1✔
156
    }
157

158
    /// <inheritdoc />
159
    public Task<byte[]> EncryptAsync(byte[] data, CancellationToken cancellationToken = default)
160
    {
161
        cancellationToken.ThrowIfCancellationRequested();
1✔
162
        return Task.FromResult(Encrypt(data));
1✔
163
    }
164

165
    /// <inheritdoc />
166
    public Task<byte[]> DecryptAsync(byte[] encryptedData, CancellationToken cancellationToken = default)
167
    {
168
        cancellationToken.ThrowIfCancellationRequested();
1✔
169
        return Task.FromResult(Decrypt(encryptedData));
1✔
170
    }
171

172
    #endregion
173

174
    #region Test Control
175

176
    /// <summary>
177
    /// Resets all tracking state.
178
    /// </summary>
179
    public void Reset()
180
    {
181
        Operations.Clear();
1✔
182
        EncryptCount = 0;
1✔
183
        DecryptCount = 0;
1✔
184
        ShouldFailEncrypt = false;
1✔
185
        ShouldFailDecrypt = false;
1✔
186
        CustomEncrypt = null;
1✔
187
        CustomDecrypt = null;
1✔
188
        Mode = MockEncryptionMode.PassThrough;
1✔
189
    }
1✔
190

191
    /// <summary>
192
    /// Clears only the operations list.
193
    /// </summary>
194
    public void ClearOperations()
195
    {
196
        Operations.Clear();
1✔
197
        EncryptCount = 0;
1✔
198
        DecryptCount = 0;
1✔
199
    }
1✔
200

201
    private byte[] XorTransform(byte[] data)
202
    {
203
        var result = new byte[data.Length];
1✔
204
        for (int i = 0; i < data.Length; i++)
1✔
205
        {
206
            result[i] = (byte)(data[i] ^ xorKey[i % xorKey.Length]);
1✔
207
        }
208
        return result;
1✔
209
    }
210

211
    #endregion
212
}
213

214
/// <summary>
215
/// Type of encryption operation.
216
/// </summary>
217
public enum OperationType
218
{
219
    /// <summary>Encryption operation.</summary>
220
    Encrypt,
221

222
    /// <summary>Decryption operation.</summary>
223
    Decrypt
224
}
225

226
/// <summary>
227
/// A recorded encryption operation.
228
/// </summary>
229
/// <param name="Type">The operation type.</param>
230
/// <param name="DataSize">The size of the data in bytes.</param>
231
/// <param name="Timestamp">When the operation occurred.</param>
232
public sealed record EncryptionOperation(OperationType Type, int DataSize, DateTime Timestamp);
1✔
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc