204 lines
6.2 KiB
C#
204 lines
6.2 KiB
C#
// <copyright file="FixtureValidationTests.cs" company="Stella Operations">
|
|
// Copyright (c) Stella Operations. Licensed under BUSL-1.1.
|
|
// </copyright>
|
|
|
|
using System.Text.Json;
|
|
using StellaOps.Testing.FixtureHarvester.Models;
|
|
using YamlDotNet.Serialization;
|
|
using YamlDotNet.Serialization.NamingConventions;
|
|
using Xunit;
|
|
|
|
namespace StellaOps.Testing.FixtureHarvester.Tests;
|
|
|
|
/// <summary>
|
|
/// Validation tests for fixture infrastructure.
|
|
/// These tests verify fixture files when they exist, otherwise they pass with a warning.
|
|
/// </summary>
|
|
public sealed class FixtureValidationTests
|
|
{
|
|
private static readonly string FixturesBasePath = GetFixturesPath();
|
|
private readonly string _manifestPath = Path.Combine(FixturesBasePath, "fixtures.manifest.yml");
|
|
|
|
private static string GetFixturesPath()
|
|
{
|
|
// Try multiple locations for fixtures
|
|
var candidates = new[]
|
|
{
|
|
"../../../fixtures",
|
|
"fixtures",
|
|
Path.Combine(AppContext.BaseDirectory, "..", "..", "..", "fixtures"),
|
|
Path.Combine(AppContext.BaseDirectory, "fixtures")
|
|
};
|
|
|
|
foreach (var path in candidates)
|
|
{
|
|
if (Directory.Exists(path) || File.Exists(Path.Combine(path, "fixtures.manifest.yml")))
|
|
{
|
|
return path;
|
|
}
|
|
}
|
|
|
|
return candidates[0]; // Default to first if none exist
|
|
}
|
|
|
|
[Fact]
|
|
public void ManifestFile_WhenExists_IsValid()
|
|
{
|
|
// Arrange & Act
|
|
var exists = File.Exists(_manifestPath);
|
|
|
|
if (!exists)
|
|
{
|
|
// Pass with informational message - fixtures not yet populated
|
|
Assert.True(true, "Fixtures manifest not yet created - test passes vacuously");
|
|
return;
|
|
}
|
|
|
|
// Assert - file exists and is readable
|
|
var content = File.ReadAllText(_manifestPath);
|
|
Assert.NotEmpty(content);
|
|
}
|
|
|
|
[Fact]
|
|
public async Task ManifestFile_WhenExists_CanBeParsed()
|
|
{
|
|
// Arrange
|
|
if (!File.Exists(_manifestPath))
|
|
{
|
|
// Skip if manifest doesn't exist yet - pass vacuously
|
|
Assert.True(true, "Fixtures manifest not yet created");
|
|
return;
|
|
}
|
|
|
|
var yamlContent = await File.ReadAllTextAsync(_manifestPath);
|
|
var deserializer = new DeserializerBuilder()
|
|
.WithNamingConvention(CamelCaseNamingConvention.Instance)
|
|
.Build();
|
|
|
|
// Act
|
|
var manifest = deserializer.Deserialize<FixtureManifest>(yamlContent);
|
|
|
|
// Assert
|
|
Assert.NotNull(manifest);
|
|
Assert.Equal("1.0", manifest.SchemaVersion);
|
|
Assert.NotNull(manifest.Fixtures);
|
|
}
|
|
|
|
[Fact]
|
|
public async Task AllFixtures_WhenPopulated_HaveValidMetadata()
|
|
{
|
|
// Arrange
|
|
if (!File.Exists(_manifestPath))
|
|
{
|
|
Assert.True(true, "Fixtures manifest not yet created");
|
|
return;
|
|
}
|
|
|
|
var yamlContent = await File.ReadAllTextAsync(_manifestPath);
|
|
var deserializer = new DeserializerBuilder()
|
|
.WithNamingConvention(CamelCaseNamingConvention.Instance)
|
|
.Build();
|
|
var manifest = deserializer.Deserialize<FixtureManifest>(yamlContent);
|
|
|
|
var allFixtures = new List<(string Type, string Id)>();
|
|
foreach (var sbom in manifest.Fixtures.Sbom)
|
|
{
|
|
allFixtures.Add(("sbom", sbom.Id));
|
|
}
|
|
|
|
foreach (var feed in manifest.Fixtures.Feeds)
|
|
{
|
|
allFixtures.Add(("feeds", feed.Id));
|
|
}
|
|
|
|
foreach (var vex in manifest.Fixtures.Vex)
|
|
{
|
|
allFixtures.Add(("vex", vex.Id));
|
|
}
|
|
|
|
// Act & Assert
|
|
foreach (var (type, id) in allFixtures)
|
|
{
|
|
var fixtureDir = Path.Combine(FixturesBasePath, type, id);
|
|
var metaPath = Path.Combine(fixtureDir, "meta.json");
|
|
|
|
if (!File.Exists(metaPath))
|
|
{
|
|
// Fixture not yet created - skip
|
|
continue;
|
|
}
|
|
|
|
var metaJson = await File.ReadAllTextAsync(metaPath);
|
|
var meta = JsonSerializer.Deserialize<FixtureMeta>(metaJson);
|
|
|
|
Assert.NotNull(meta);
|
|
Assert.Equal(id, meta.Id);
|
|
Assert.NotEmpty(meta.Source);
|
|
Assert.NotEmpty(meta.License);
|
|
Assert.NotEmpty(meta.Sha256);
|
|
Assert.StartsWith("sha256:", meta.Sha256);
|
|
Assert.NotEmpty(meta.RefreshPolicy);
|
|
}
|
|
}
|
|
|
|
[Fact]
|
|
public async Task AllFixtures_WhenPopulated_HaveRawDirectory()
|
|
{
|
|
// Arrange
|
|
if (!File.Exists(_manifestPath))
|
|
{
|
|
Assert.True(true, "Fixtures manifest not yet created");
|
|
return;
|
|
}
|
|
|
|
var yamlContent = await File.ReadAllTextAsync(_manifestPath);
|
|
var deserializer = new DeserializerBuilder()
|
|
.WithNamingConvention(CamelCaseNamingConvention.Instance)
|
|
.Build();
|
|
var manifest = deserializer.Deserialize<FixtureManifest>(yamlContent);
|
|
|
|
var allFixtures = new List<(string Type, string Id)>();
|
|
foreach (var sbom in manifest.Fixtures.Sbom)
|
|
{
|
|
allFixtures.Add(("sbom", sbom.Id));
|
|
}
|
|
|
|
foreach (var feed in manifest.Fixtures.Feeds)
|
|
{
|
|
allFixtures.Add(("feeds", feed.Id));
|
|
}
|
|
|
|
foreach (var vex in manifest.Fixtures.Vex)
|
|
{
|
|
allFixtures.Add(("vex", vex.Id));
|
|
}
|
|
|
|
// Act & Assert
|
|
foreach (var (type, id) in allFixtures)
|
|
{
|
|
var fixtureDir = Path.Combine(FixturesBasePath, type, id);
|
|
var rawDir = Path.Combine(fixtureDir, "raw");
|
|
|
|
if (!Directory.Exists(fixtureDir))
|
|
{
|
|
// Fixture not yet created - skip
|
|
continue;
|
|
}
|
|
|
|
Assert.True(Directory.Exists(rawDir), $"Fixture {id} should have raw/ directory");
|
|
}
|
|
}
|
|
|
|
[Theory]
|
|
[InlineData("T0")]
|
|
[InlineData("T1")]
|
|
[InlineData("T2")]
|
|
[InlineData("T3")]
|
|
public void FixtureTiers_AreDocumented(string tier)
|
|
{
|
|
// This is a documentation test to ensure all tiers are defined
|
|
var validTiers = new[] { "T0", "T1", "T2", "T3" };
|
|
Assert.Contains(tier, validTiers);
|
|
}
|
|
}
|