using AvParser.Core.Proxies;
namespace AvParser.Core.Tests.Proxies;
/// A clock the tests move by hand, so quarantine expiry is deterministic.
internal sealed class FakeTimeProvider(DateTimeOffset start) : TimeProvider
{
private DateTimeOffset _now = start;
public FakeTimeProvider()
: this(new DateTimeOffset(2026, 1, 1, 0, 0, 0, TimeSpan.Zero)) { }
public override DateTimeOffset GetUtcNow() => _now;
public void Advance(TimeSpan delta) => _now += delta;
}
/// A source that returns whatever the test handed it.
internal sealed class FakeProxySource(ProxySourceKind kind = ProxySourceKind.Feed, params ProxyEndpoint[] endpoints)
: IProxySource
{
public string Id { get; init; } = "fake";
public string DisplayName => "Fake source";
public ProxySourceKind Kind { get; } = kind;
public List Endpoints { get; } = [.. endpoints];
public int GetCallCount { get; private set; }
public Task> GetProxiesAsync(CancellationToken cancellationToken = default)
{
GetCallCount++;
return Task.FromResult>(Endpoints.ToArray());
}
}
/// A probe whose verdict the test decides, per address.
internal sealed class FakeProxyProbe : IProxyProbe
{
private readonly Dictionary _verdicts = new(StringComparer.Ordinal);
/// Verdict for addresses with no explicit entry.
public bool DefaultAlive { get; set; }
/// How many probes were requested.
public int ProbeCount { get; private set; }
/// Addresses probed, in order.
public List Probed { get; } = [];
public FakeProxyProbe Set(ProxyEndpoint endpoint, bool alive)
{
_verdicts[endpoint.Key] = alive;
return this;
}
public Task ProbeAsync(
ProxyEndpoint endpoint,
ProxyOptions options,
CancellationToken cancellationToken = default
)
{
ProbeCount++;
Probed.Add(endpoint.Key);
var alive = _verdicts.TryGetValue(endpoint.Key, out var verdict) ? verdict : DefaultAlive;
return Task.FromResult(
alive ? ProxyProbeResult.Success(TimeSpan.FromMilliseconds(42)) : ProxyProbeResult.Failure("dead")
);
}
}
/// Shorthand builders for the proxy tests.
internal static class ProxyFactory
{
public static ProxyEndpoint Endpoint(
string host,
int port = 8080,
ProxyProtocol protocol = ProxyProtocol.Http,
int score = 0
) => new(protocol, host, port) { Score = score };
public static ProxyEntry Entry(
string host,
int port = 8080,
ProxyProtocol protocol = ProxyProtocol.Http,
int score = 0,
ProxySourceKind source = ProxySourceKind.Feed
) => new(Endpoint(host, port, protocol, score), source);
}