60 lines
		
	
	
		
			2.5 KiB
		
	
	
	
		
			C#
		
	
	
	
	
	
			
		
		
	
	
			60 lines
		
	
	
		
			2.5 KiB
		
	
	
	
		
			C#
		
	
	
	
	
	
using System.Collections.Immutable;
 | 
						|
using System.IO.Abstractions.TestingHelpers;
 | 
						|
using System.Linq;
 | 
						|
using System.Text.Json;
 | 
						|
using Microsoft.Extensions.Logging.Abstractions;
 | 
						|
using Microsoft.Extensions.Options;
 | 
						|
using StellaOps.Excititor.Core;
 | 
						|
using StellaOps.Excititor.Export;
 | 
						|
 | 
						|
namespace StellaOps.Excititor.Export.Tests;
 | 
						|
 | 
						|
public sealed class OfflineBundleArtifactStoreTests
 | 
						|
{
 | 
						|
    [Fact]
 | 
						|
    public async Task SaveAsync_WritesArtifactAndManifest()
 | 
						|
    {
 | 
						|
        var fs = new MockFileSystem();
 | 
						|
        var options = Options.Create(new OfflineBundleArtifactStoreOptions { RootPath = "/offline" });
 | 
						|
        var store = new OfflineBundleArtifactStore(options, NullLogger<OfflineBundleArtifactStore>.Instance, fs);
 | 
						|
 | 
						|
        var content = new byte[] { 1, 2, 3 };
 | 
						|
        var digest = "sha256:" + Convert.ToHexString(System.Security.Cryptography.SHA256.HashData(content)).ToLowerInvariant();
 | 
						|
        var artifact = new VexExportArtifact(
 | 
						|
            new VexContentAddress("sha256", digest.Split(':')[1]),
 | 
						|
            VexExportFormat.Json,
 | 
						|
            content,
 | 
						|
            ImmutableDictionary<string, string>.Empty);
 | 
						|
 | 
						|
        var stored = await store.SaveAsync(artifact, CancellationToken.None);
 | 
						|
 | 
						|
        var artifactPath = fs.Path.Combine(options.Value.RootPath, stored.Location);
 | 
						|
        Assert.True(fs.FileExists(artifactPath));
 | 
						|
 | 
						|
        var manifestPath = fs.Path.Combine(options.Value.RootPath, options.Value.ManifestFileName);
 | 
						|
        Assert.True(fs.FileExists(manifestPath));
 | 
						|
        await using var manifestStream = fs.File.OpenRead(manifestPath);
 | 
						|
        using var document = await JsonDocument.ParseAsync(manifestStream);
 | 
						|
        var artifacts = document.RootElement.GetProperty("artifacts");
 | 
						|
        Assert.True(artifacts.GetArrayLength() >= 1);
 | 
						|
        var first = artifacts.EnumerateArray().First();
 | 
						|
        Assert.Equal(digest, first.GetProperty("digest").GetString());
 | 
						|
    }
 | 
						|
 | 
						|
    [Fact]
 | 
						|
    public async Task SaveAsync_ThrowsOnDigestMismatch()
 | 
						|
    {
 | 
						|
        var fs = new MockFileSystem();
 | 
						|
        var options = Options.Create(new OfflineBundleArtifactStoreOptions { RootPath = "/offline" });
 | 
						|
        var store = new OfflineBundleArtifactStore(options, NullLogger<OfflineBundleArtifactStore>.Instance, fs);
 | 
						|
 | 
						|
        var artifact = new VexExportArtifact(
 | 
						|
            new VexContentAddress("sha256", "deadbeef"),
 | 
						|
            VexExportFormat.Json,
 | 
						|
            new byte[] { 0x01, 0x02 },
 | 
						|
            ImmutableDictionary<string, string>.Empty);
 | 
						|
 | 
						|
        await Assert.ThrowsAsync<InvalidOperationException>(() => store.SaveAsync(artifact, CancellationToken.None).AsTask());
 | 
						|
    }
 | 
						|
}
 |