commit and up
This commit is contained in:
		| @@ -0,0 +1,113 @@ | ||||
| using System; | ||||
| using System.Collections.Generic; | ||||
| using System.IO; | ||||
| using System.Linq; | ||||
| using System.Text; | ||||
| using System.Text.Json; | ||||
| using System.Security.Cryptography; | ||||
| using StellaOps.Feedser.Exporter.TrivyDb; | ||||
|  | ||||
| namespace StellaOps.Feedser.Exporter.TrivyDb.Tests; | ||||
|  | ||||
| public sealed class TrivyDbOciWriterTests : IDisposable | ||||
| { | ||||
|     private readonly string _root; | ||||
|  | ||||
|     public TrivyDbOciWriterTests() | ||||
|     { | ||||
|         _root = Directory.CreateTempSubdirectory("feedser-trivy-oci-tests").FullName; | ||||
|     } | ||||
|  | ||||
|     [Fact] | ||||
|     public async Task WritesOciLayoutWithManifestIndex() | ||||
|     { | ||||
|         var metadata = Encoding.UTF8.GetBytes("{\"generatedAt\":\"2024-08-01T00:00:00Z\",\"schema\":1}"); | ||||
|         var archive = Enumerable.Range(0, 128).Select(static b => (byte)b).ToArray(); | ||||
|         var generatedAt = DateTimeOffset.Parse("2024-08-01T00:00:00Z"); | ||||
|         var archivePath = Path.Combine(_root, "db.bin"); | ||||
|         File.WriteAllBytes(archivePath, archive); | ||||
|         var archiveDigest = ComputeDigest(archive); | ||||
|         var request = new TrivyDbPackageRequest(metadata, archivePath, archiveDigest, archive.LongLength, generatedAt, "2024.08.01"); | ||||
|  | ||||
|         var builder = new TrivyDbPackageBuilder(); | ||||
|         var package = builder.BuildPackage(request); | ||||
|  | ||||
|         var writer = new TrivyDbOciWriter(); | ||||
|         var result = await writer.WriteAsync(package, Path.Combine(_root, "oci"), "feedser:v2024.08.01", CancellationToken.None); | ||||
|  | ||||
|         Assert.Equal(package.Manifest.Layers[0].Digest, package.Config.DatabaseDigest); | ||||
|         Assert.NotEmpty(result.BlobDigests); | ||||
|         Assert.Contains(result.ManifestDigest, result.BlobDigests); | ||||
|  | ||||
|         var layoutPath = Path.Combine(result.RootDirectory, "oci-layout"); | ||||
|         Assert.True(File.Exists(layoutPath)); | ||||
|         var layoutJson = await File.ReadAllTextAsync(layoutPath, CancellationToken.None); | ||||
|         Assert.Contains("\"imageLayoutVersion\":\"1.0.0\"", layoutJson, StringComparison.Ordinal); | ||||
|  | ||||
|         var metadataPath = Path.Combine(result.RootDirectory, "metadata.json"); | ||||
|         Assert.True(File.Exists(metadataPath)); | ||||
|         var roundTripMetadata = await File.ReadAllBytesAsync(metadataPath, CancellationToken.None); | ||||
|         Assert.Equal(metadata, roundTripMetadata); | ||||
|  | ||||
|         var indexPath = Path.Combine(result.RootDirectory, "index.json"); | ||||
|         Assert.True(File.Exists(indexPath)); | ||||
|         using var indexDocument = JsonDocument.Parse(await File.ReadAllBytesAsync(indexPath, CancellationToken.None)); | ||||
|         var manifestElement = indexDocument.RootElement.GetProperty("manifests")[0]; | ||||
|         Assert.Equal(result.ManifestDigest, manifestElement.GetProperty("digest").GetString()); | ||||
|         Assert.Equal(TrivyDbMediaTypes.OciManifest, manifestElement.GetProperty("mediaType").GetString()); | ||||
|         Assert.Equal("feedser:v2024.08.01", manifestElement.GetProperty("annotations").GetProperty("org.opencontainers.image.ref.name").GetString()); | ||||
|  | ||||
|         var manifestPath = Path.Combine(result.RootDirectory, "blobs", "sha256", result.ManifestDigest.Split(':')[1]); | ||||
|         var manifestBytes = await File.ReadAllBytesAsync(manifestPath, CancellationToken.None); | ||||
|         using var manifestDocument = JsonDocument.Parse(manifestBytes); | ||||
|         var configDescriptor = manifestDocument.RootElement.GetProperty("config"); | ||||
|         Assert.Equal(package.Manifest.Config.Digest, configDescriptor.GetProperty("digest").GetString()); | ||||
|         Assert.Equal(package.Manifest.Config.MediaType, configDescriptor.GetProperty("mediaType").GetString()); | ||||
|         var layer = manifestDocument.RootElement.GetProperty("layers")[0]; | ||||
|         Assert.Equal(package.Manifest.Layers[0].Digest, layer.GetProperty("digest").GetString()); | ||||
|         Assert.Equal(package.Manifest.Layers[0].MediaType, layer.GetProperty("mediaType").GetString()); | ||||
|  | ||||
|         foreach (var digest in package.Blobs.Keys) | ||||
|         { | ||||
|             var blobPath = Path.Combine(result.RootDirectory, "blobs", "sha256", digest.Split(':')[1]); | ||||
|             Assert.True(File.Exists(blobPath)); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     [Fact] | ||||
|     public async Task ThrowsOnUnsupportedDigest() | ||||
|     { | ||||
|         var package = new TrivyDbPackage( | ||||
|             new OciManifest(2, TrivyDbMediaTypes.OciManifest, new OciDescriptor(TrivyDbMediaTypes.TrivyConfig, "sha256:abcd", 4), Array.Empty<OciDescriptor>()), | ||||
|             new TrivyConfigDocument(TrivyDbMediaTypes.TrivyConfig, DateTimeOffset.UtcNow, "1", "sha256:abcd", 4), | ||||
|             new Dictionary<string, TrivyDbBlob> | ||||
|             { | ||||
|                 ["md5:deadbeef"] = TrivyDbBlob.FromBytes(new byte[] { 1, 2, 3, 4 }), | ||||
|             }, | ||||
|             new byte[] { 123 }); | ||||
|  | ||||
|         var writer = new TrivyDbOciWriter(); | ||||
|         await Assert.ThrowsAsync<InvalidOperationException>(() => writer.WriteAsync(package, Path.Combine(_root, "invalid"), "feedser:bad", CancellationToken.None)); | ||||
|     } | ||||
|  | ||||
|     public void Dispose() | ||||
|     { | ||||
|         try | ||||
|         { | ||||
|             if (Directory.Exists(_root)) | ||||
|             { | ||||
|                 Directory.Delete(_root, recursive: true); | ||||
|             } | ||||
|         } | ||||
|         catch | ||||
|         { | ||||
|             // ignore cleanup issues | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     private static string ComputeDigest(byte[] payload) | ||||
|     { | ||||
|         var hash = SHA256.HashData(payload); | ||||
|         return "sha256:" + Convert.ToHexString(hash).ToLowerInvariant(); | ||||
|     } | ||||
| } | ||||
		Reference in New Issue
	
	Block a user