Add new features and tests for AirGap and Time modules
Some checks failed
Docs CI / lint-and-preview (push) Has been cancelled
Some checks failed
Docs CI / lint-and-preview (push) Has been cancelled
- Introduced `SbomService` tasks documentation. - Updated `StellaOps.sln` to include new projects: `StellaOps.AirGap.Time` and `StellaOps.AirGap.Importer`. - Added unit tests for `BundleImportPlanner`, `DsseVerifier`, `ImportValidator`, and other components in the `StellaOps.AirGap.Importer.Tests` namespace. - Implemented `InMemoryBundleRepositories` for testing bundle catalog and item repositories. - Created `MerkleRootCalculator`, `RootRotationPolicy`, and `TufMetadataValidator` tests. - Developed `StalenessCalculator` and `TimeAnchorLoader` tests in the `StellaOps.AirGap.Time.Tests` namespace. - Added `fetch-sbomservice-deps.sh` script for offline dependency fetching.
This commit is contained in:
@@ -0,0 +1,9 @@
|
||||
using StellaOps.AirGap.Importer.Models;
|
||||
|
||||
namespace StellaOps.AirGap.Importer.Repositories;
|
||||
|
||||
public interface IBundleCatalogRepository
|
||||
{
|
||||
Task UpsertAsync(BundleCatalogEntry entry, CancellationToken cancellationToken);
|
||||
Task<IReadOnlyList<BundleCatalogEntry>> ListAsync(string tenantId, CancellationToken cancellationToken);
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
using StellaOps.AirGap.Importer.Models;
|
||||
|
||||
namespace StellaOps.AirGap.Importer.Repositories;
|
||||
|
||||
public interface IBundleItemRepository
|
||||
{
|
||||
Task UpsertManyAsync(IEnumerable<BundleItem> items, CancellationToken cancellationToken);
|
||||
Task<IReadOnlyList<BundleItem>> ListByBundleAsync(string tenantId, string bundleId, CancellationToken cancellationToken);
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
using StellaOps.AirGap.Importer.Models;
|
||||
|
||||
namespace StellaOps.AirGap.Importer.Repositories;
|
||||
|
||||
/// <summary>
|
||||
/// Deterministic in-memory implementations suitable for offline tests and as a template for Mongo-backed repos.
|
||||
/// Enforces tenant isolation and stable ordering (by BundleId then Path).
|
||||
/// </summary>
|
||||
public sealed class InMemoryBundleCatalogRepository : IBundleCatalogRepository
|
||||
{
|
||||
private readonly Dictionary<string, List<BundleCatalogEntry>> _catalog = new(StringComparer.Ordinal);
|
||||
|
||||
public Task UpsertAsync(BundleCatalogEntry entry, CancellationToken cancellationToken)
|
||||
{
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
var bucket = _catalog.GetValueOrDefault(entry.TenantId) ?? new List<BundleCatalogEntry>();
|
||||
bucket.RemoveAll(e => e.BundleId == entry.BundleId);
|
||||
bucket.Add(entry);
|
||||
_catalog[entry.TenantId] = bucket;
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
public Task<IReadOnlyList<BundleCatalogEntry>> ListAsync(string tenantId, CancellationToken cancellationToken)
|
||||
{
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
var items = _catalog.GetValueOrDefault(tenantId) ?? new List<BundleCatalogEntry>();
|
||||
return Task.FromResult<IReadOnlyList<BundleCatalogEntry>>(items
|
||||
.OrderBy(e => e.BundleId, StringComparer.Ordinal)
|
||||
.ToList());
|
||||
}
|
||||
}
|
||||
|
||||
public sealed class InMemoryBundleItemRepository : IBundleItemRepository
|
||||
{
|
||||
private readonly Dictionary<(string TenantId, string BundleId), List<BundleItem>> _items = new();
|
||||
|
||||
public Task UpsertManyAsync(IEnumerable<BundleItem> items, CancellationToken cancellationToken)
|
||||
{
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
foreach (var item in items)
|
||||
{
|
||||
var key = (item.TenantId, item.BundleId);
|
||||
if (!_items.TryGetValue(key, out var list))
|
||||
{
|
||||
list = new List<BundleItem>();
|
||||
_items[key] = list;
|
||||
}
|
||||
list.RemoveAll(i => i.Path == item.Path);
|
||||
list.Add(item);
|
||||
}
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
public Task<IReadOnlyList<BundleItem>> ListByBundleAsync(string tenantId, string bundleId, CancellationToken cancellationToken)
|
||||
{
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
var key = (tenantId, bundleId);
|
||||
var list = _items.GetValueOrDefault(key) ?? new List<BundleItem>();
|
||||
return Task.FromResult<IReadOnlyList<BundleItem>>(list
|
||||
.OrderBy(i => i.Path, StringComparer.Ordinal)
|
||||
.ToList());
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user