Files
git.stella-ops.org/src/Signals/__Tests/StellaOps.Signals.Tests/UnknownsIngestionServiceTests.cs
StellaOps Bot 1c782897f7
Some checks failed
Docs CI / lint-and-preview (push) Has been cancelled
Mirror Thin Bundle Sign & Verify / mirror-sign (push) Has been cancelled
Signals CI & Image / signals-ci (push) Has been cancelled
up
2025-11-26 07:47:08 +02:00

83 lines
2.8 KiB
C#

using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Extensions.Logging.Abstractions;
using StellaOps.Signals.Models;
using StellaOps.Signals.Persistence;
using StellaOps.Signals.Services;
using Xunit;
namespace StellaOps.Signals.Tests;
public class UnknownsIngestionServiceTests
{
[Fact]
public async Task IngestAsync_StoresNormalizedUnknowns()
{
var repo = new InMemoryUnknownsRepository();
var service = new UnknownsIngestionService(repo, TimeProvider.System, NullLogger<UnknownsIngestionService>.Instance);
var request = new UnknownsIngestRequest
{
Subject = new ReachabilitySubject { Component = "demo", Version = "1.0.0" },
CallgraphId = "cg-1",
Unknowns = new List<UnknownSymbolEntry>
{
new()
{
SymbolId = "symA",
Purl = "pkg:pypi/foo",
Reason = "missing-edge"
},
new() // empty entry should be ignored
}
};
var response = await service.IngestAsync(request, CancellationToken.None);
Assert.Equal("demo|1.0.0", response.SubjectKey);
Assert.Equal(1, response.UnknownsCount);
Assert.Single(repo.Stored);
Assert.Equal("symA", repo.Stored[0].SymbolId);
Assert.Equal("pkg:pypi/foo", repo.Stored[0].Purl);
}
[Fact]
public async Task IngestAsync_ThrowsWhenEmpty()
{
var repo = new InMemoryUnknownsRepository();
var service = new UnknownsIngestionService(repo, TimeProvider.System, NullLogger<UnknownsIngestionService>.Instance);
var request = new UnknownsIngestRequest
{
Subject = new ReachabilitySubject { Component = "demo", Version = "1.0.0" },
CallgraphId = "cg-1",
Unknowns = new List<UnknownSymbolEntry>()
};
await Assert.ThrowsAsync<UnknownsValidationException>(() => service.IngestAsync(request, CancellationToken.None));
}
private sealed class InMemoryUnknownsRepository : IUnknownsRepository
{
public List<UnknownSymbolDocument> Stored { get; } = new();
public Task UpsertAsync(string subjectKey, IEnumerable<UnknownSymbolDocument> items, CancellationToken cancellationToken)
{
Stored.Clear();
Stored.AddRange(items);
return Task.CompletedTask;
}
public Task<IReadOnlyList<UnknownSymbolDocument>> GetBySubjectAsync(string subjectKey, CancellationToken cancellationToken)
{
return Task.FromResult((IReadOnlyList<UnknownSymbolDocument>)Stored);
}
public Task<int> CountBySubjectAsync(string subjectKey, CancellationToken cancellationToken)
{
return Task.FromResult(Stored.Count);
}
}
}