Add tests for SBOM generation determinism across multiple formats
- Created `StellaOps.TestKit.Tests` project for unit tests related to determinism. - Implemented `DeterminismManifestTests` to validate deterministic output for canonical bytes and strings, file read/write operations, and error handling for invalid schema versions. - Added `SbomDeterminismTests` to ensure identical inputs produce consistent SBOMs across SPDX 3.0.1 and CycloneDX 1.6/1.7 formats, including parallel execution tests. - Updated project references in `StellaOps.Integration.Determinism` to include the new determinism testing library.
This commit is contained in:
@@ -0,0 +1,111 @@
|
||||
using System.Net.Http.Headers;
|
||||
using System.Text;
|
||||
|
||||
namespace StellaOps.TestKit.Extensions;
|
||||
|
||||
/// <summary>
|
||||
/// Extension methods for HttpClient to support test scenarios.
|
||||
/// </summary>
|
||||
public static class HttpClientTestExtensions
|
||||
{
|
||||
/// <summary>
|
||||
/// Sends a request without any authentication headers.
|
||||
/// </summary>
|
||||
public static async Task<HttpResponseMessage> SendWithoutAuthAsync(
|
||||
this HttpClient client,
|
||||
HttpMethod method,
|
||||
string endpoint,
|
||||
CancellationToken ct = default)
|
||||
{
|
||||
var request = new HttpRequestMessage(method, endpoint);
|
||||
request.Headers.Authorization = null; // Ensure no auth header
|
||||
return await client.SendAsync(request, ct);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sends a request with an expired bearer token.
|
||||
/// </summary>
|
||||
public static async Task<HttpResponseMessage> SendWithExpiredTokenAsync(
|
||||
this HttpClient client,
|
||||
string endpoint,
|
||||
string expiredToken,
|
||||
CancellationToken ct = default)
|
||||
{
|
||||
var request = new HttpRequestMessage(HttpMethod.Get, endpoint);
|
||||
request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", expiredToken);
|
||||
return await client.SendAsync(request, ct);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sends a request with a malformed content type (text/plain instead of application/json).
|
||||
/// </summary>
|
||||
public static async Task<HttpResponseMessage> SendWithMalformedContentTypeAsync(
|
||||
this HttpClient client,
|
||||
HttpMethod method,
|
||||
string endpoint,
|
||||
string body,
|
||||
CancellationToken ct = default)
|
||||
{
|
||||
var request = new HttpRequestMessage(method, endpoint)
|
||||
{
|
||||
Content = new StringContent(body, Encoding.UTF8, "text/plain")
|
||||
};
|
||||
return await client.SendAsync(request, ct);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sends a request with an oversized payload.
|
||||
/// </summary>
|
||||
public static async Task<HttpResponseMessage> SendOversizedPayloadAsync(
|
||||
this HttpClient client,
|
||||
string endpoint,
|
||||
int sizeBytes,
|
||||
CancellationToken ct = default)
|
||||
{
|
||||
var payload = new string('x', sizeBytes);
|
||||
var request = new HttpRequestMessage(HttpMethod.Post, endpoint)
|
||||
{
|
||||
Content = new StringContent(payload, Encoding.UTF8, "application/json")
|
||||
};
|
||||
return await client.SendAsync(request, ct);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sends a request with the wrong HTTP method (opposite of expected).
|
||||
/// </summary>
|
||||
public static async Task<HttpResponseMessage> SendWithWrongMethodAsync(
|
||||
this HttpClient client,
|
||||
string endpoint,
|
||||
HttpMethod expectedMethod,
|
||||
CancellationToken ct = default)
|
||||
{
|
||||
// If endpoint expects POST, send GET; if expects GET, send DELETE
|
||||
var wrongMethod = expectedMethod == HttpMethod.Post ? HttpMethod.Get :
|
||||
expectedMethod == HttpMethod.Get ? HttpMethod.Delete :
|
||||
expectedMethod == HttpMethod.Put ? HttpMethod.Patch :
|
||||
expectedMethod == HttpMethod.Delete ? HttpMethod.Post :
|
||||
HttpMethod.Options;
|
||||
|
||||
var request = new HttpRequestMessage(wrongMethod, endpoint);
|
||||
return await client.SendAsync(request, ct);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sends a request with a bearer token for a specific tenant.
|
||||
/// </summary>
|
||||
public static async Task<HttpResponseMessage> SendWithTokenAsync(
|
||||
this HttpClient client,
|
||||
HttpMethod method,
|
||||
string endpoint,
|
||||
string token,
|
||||
HttpContent? content = null,
|
||||
CancellationToken ct = default)
|
||||
{
|
||||
var request = new HttpRequestMessage(method, endpoint)
|
||||
{
|
||||
Content = content
|
||||
};
|
||||
request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", token);
|
||||
return await client.SendAsync(request, ct);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user