feat(graph-api): Add schema review notes for upcoming Graph API changes
Some checks failed
Docs CI / lint-and-preview (push) Has been cancelled
Some checks failed
Docs CI / lint-and-preview (push) Has been cancelled
feat(sbomservice): Add placeholder for SHA256SUMS in LNM v1 fixtures docs(devportal): Create README for SDK archives in public directory build(devportal): Implement offline bundle build script test(devportal): Add link checker script for validating links in documentation test(devportal): Create performance check script for dist folder size test(devportal): Implement accessibility check script using Playwright and Axe docs(devportal): Add SDK quickstart guide with examples for Node.js, Python, and cURL feat(excititor): Implement MongoDB storage for airgap import records test(findings): Add unit tests for export filters hash determinism feat(findings): Define attestation contracts for ledger web service feat(graph): Add MongoDB options and service collection extensions for graph indexing test(graph): Implement integration tests for MongoDB provider and service collection extensions feat(zastava): Define configuration options for Zastava surface secrets build(tests): Create script to run Concelier linkset tests with TRX output
This commit is contained in:
@@ -0,0 +1,125 @@
|
||||
using System.Collections.Immutable;
|
||||
using System.Text.Json.Nodes;
|
||||
using Mongo2Go;
|
||||
using MongoDB.Bson;
|
||||
using MongoDB.Driver;
|
||||
using StellaOps.Graph.Indexer.Analytics;
|
||||
using StellaOps.Graph.Indexer.Incremental;
|
||||
|
||||
namespace StellaOps.Graph.Indexer.Tests;
|
||||
|
||||
public sealed class MongoProviderIntegrationTests : IAsyncLifetime
|
||||
{
|
||||
private readonly MongoDbRunner _runner;
|
||||
private IMongoDatabase _database = default!;
|
||||
|
||||
public MongoProviderIntegrationTests()
|
||||
{
|
||||
_runner = MongoDbRunner.Start(singleNodeReplSet: true);
|
||||
}
|
||||
|
||||
public Task InitializeAsync()
|
||||
{
|
||||
var client = new MongoClient(_runner.ConnectionString);
|
||||
_database = client.GetDatabase("graph-indexer-tests");
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
public Task DisposeAsync()
|
||||
{
|
||||
_runner.Dispose();
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task SnapshotProvider_ReadsPendingSnapshots()
|
||||
{
|
||||
var snapshots = _database.GetCollection<BsonDocument>("graph_snapshots");
|
||||
var nodes = new BsonArray
|
||||
{
|
||||
new BsonDocument
|
||||
{
|
||||
{ "id", "gn:tenant-a:component:1" },
|
||||
{ "kind", "component" },
|
||||
{ "attributes", new BsonDocument { { "purl", "pkg:npm/a@1.0.0" } } }
|
||||
}
|
||||
};
|
||||
|
||||
var edges = new BsonArray();
|
||||
|
||||
await snapshots.InsertOneAsync(new BsonDocument
|
||||
{
|
||||
{ "tenant", "tenant-a" },
|
||||
{ "snapshot_id", "snap-1" },
|
||||
{ "generated_at", DateTime.UtcNow },
|
||||
{ "nodes", nodes },
|
||||
{ "edges", edges }
|
||||
});
|
||||
|
||||
var provider = new MongoGraphSnapshotProvider(_database);
|
||||
var pending = await provider.GetPendingSnapshotsAsync(CancellationToken.None);
|
||||
|
||||
Assert.Single(pending);
|
||||
Assert.Equal("snap-1", pending[0].SnapshotId);
|
||||
Assert.Single(pending[0].Nodes);
|
||||
|
||||
await provider.MarkProcessedAsync("tenant-a", "snap-1", CancellationToken.None);
|
||||
var none = await provider.GetPendingSnapshotsAsync(CancellationToken.None);
|
||||
Assert.Empty(none);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task ChangeEventSource_EnumeratesAndHonorsIdempotency()
|
||||
{
|
||||
var changes = _database.GetCollection<BsonDocument>("graph_change_events");
|
||||
await changes.InsertManyAsync(new[]
|
||||
{
|
||||
new BsonDocument
|
||||
{
|
||||
{ "tenant", "tenant-a" },
|
||||
{ "snapshot_id", "snap-1" },
|
||||
{ "sequence_token", "seq-1" },
|
||||
{ "is_backfill", false },
|
||||
{ "nodes", new BsonArray { new BsonDocument { { "id", "gn:1" }, { "kind", "component" } } } },
|
||||
{ "edges", new BsonArray() }
|
||||
},
|
||||
new BsonDocument
|
||||
{
|
||||
{ "tenant", "tenant-a" },
|
||||
{ "snapshot_id", "snap-1" },
|
||||
{ "sequence_token", "seq-2" },
|
||||
{ "is_backfill", false },
|
||||
{ "nodes", new BsonArray { new BsonDocument { { "id", "gn:2" }, { "kind", "component" } } } },
|
||||
{ "edges", new BsonArray() }
|
||||
}
|
||||
});
|
||||
|
||||
var source = new MongoGraphChangeEventSource(_database);
|
||||
var idempotency = new MongoIdempotencyStore(_database);
|
||||
|
||||
var events = new List<GraphChangeEvent>();
|
||||
await foreach (var change in source.ReadAsync(CancellationToken.None))
|
||||
{
|
||||
if (await idempotency.HasSeenAsync(change.SequenceToken, CancellationToken.None))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
events.Add(change);
|
||||
await idempotency.MarkSeenAsync(change.SequenceToken, CancellationToken.None);
|
||||
}
|
||||
|
||||
Assert.Equal(2, events.Count);
|
||||
|
||||
var secondPass = new List<GraphChangeEvent>();
|
||||
await foreach (var change in source.ReadAsync(CancellationToken.None))
|
||||
{
|
||||
if (!await idempotency.HasSeenAsync(change.SequenceToken, CancellationToken.None))
|
||||
{
|
||||
secondPass.Add(change);
|
||||
}
|
||||
}
|
||||
|
||||
Assert.Empty(secondPass);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using StellaOps.Graph.Indexer.Infrastructure;
|
||||
using Mongo2Go;
|
||||
using MongoDB.Driver;
|
||||
|
||||
namespace StellaOps.Graph.Indexer.Tests;
|
||||
|
||||
public sealed class MongoServiceCollectionExtensionsTests : IAsyncLifetime
|
||||
{
|
||||
private MongoDbRunner _runner = default!;
|
||||
|
||||
public Task InitializeAsync()
|
||||
{
|
||||
_runner = MongoDbRunner.Start(singleNodeReplSet: true);
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
public Task DisposeAsync()
|
||||
{
|
||||
_runner.Dispose();
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void AddGraphMongoDatabase_RegistersClientAndDatabase()
|
||||
{
|
||||
var services = new ServiceCollection();
|
||||
|
||||
services.AddGraphMongoDatabase(options =>
|
||||
{
|
||||
options.ConnectionString = _runner.ConnectionString;
|
||||
options.DatabaseName = "graph-indexer-ext-tests";
|
||||
});
|
||||
|
||||
var provider = services.BuildServiceProvider();
|
||||
|
||||
var client = provider.GetService<IMongoClient>();
|
||||
var database = provider.GetService<IMongoDatabase>();
|
||||
|
||||
Assert.NotNull(client);
|
||||
Assert.NotNull(database);
|
||||
Assert.Equal("graph-indexer-ext-tests", database!.DatabaseNamespace.DatabaseName);
|
||||
}
|
||||
}
|
||||
@@ -12,5 +12,6 @@
|
||||
<PackageReference Include="xunit" Version="2.9.2" />
|
||||
<PackageReference Include="xunit.runner.visualstudio" Version="2.8.2" />
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.11.1" />
|
||||
<PackageReference Include="Mongo2Go" Version="3.1.3" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
|
||||
Reference in New Issue
Block a user