mirror of
https://github.com/logos-storage/logos-storage-nim-cs-dist-tests.git
synced 2026-01-03 22:13:10 +00:00
Merge branch 'master' into feature/multi-codex-folder-saver
This commit is contained in:
commit
bc01e97ff8
@ -22,7 +22,9 @@
|
||||
.Replace("\\", "-")
|
||||
.Replace("[", "-")
|
||||
.Replace("]", "-")
|
||||
.Replace(",", "-");
|
||||
.Replace(",", "-")
|
||||
.Replace("(", "-")
|
||||
.Replace(")", "-");
|
||||
|
||||
if (result.Length > maxLength) result = result.Substring(0, maxLength);
|
||||
result = result.Trim('-');
|
||||
|
||||
@ -40,7 +40,9 @@ namespace KubernetesWorkflow
|
||||
|
||||
protected override void ProcessLine(string line)
|
||||
{
|
||||
if (line.Contains("Received JSON-RPC response")) return;
|
||||
// This line is not useful and has no topic so we can't filter it with
|
||||
// normal log-level controls.
|
||||
if (line.Contains("Received JSON-RPC response") && !line.Contains("topics=")) return;
|
||||
if (line.Contains("object field not marked with serialize, skipping")) return;
|
||||
|
||||
LogFile.Write(line);
|
||||
|
||||
@ -11,7 +11,7 @@ namespace CodexClient
|
||||
private readonly ILog log;
|
||||
private readonly IHttpFactory httpFactory;
|
||||
private readonly IProcessControl processControl;
|
||||
private ICodexInstance instance;
|
||||
private readonly ICodexInstance instance;
|
||||
private readonly Mapper mapper = new Mapper();
|
||||
|
||||
public CodexAccess(ILog log, IHttpFactory httpFactory, IProcessControl processControl, ICodexInstance instance)
|
||||
@ -25,8 +25,6 @@ namespace CodexClient
|
||||
public void Stop(bool waitTillStopped)
|
||||
{
|
||||
processControl.Stop(waitTillStopped);
|
||||
// Prevents accidental use after stop:
|
||||
instance = null!;
|
||||
}
|
||||
|
||||
public IDownloadedLog DownloadLog(string additionalName = "")
|
||||
@ -143,7 +141,7 @@ namespace CodexClient
|
||||
return mapper.Map(OnCodex(api => api.ListDataAsync()));
|
||||
}
|
||||
|
||||
public StorageAvailability SalesAvailability(StorageAvailability request)
|
||||
public StorageAvailability SalesAvailability(CreateStorageAvailability request)
|
||||
{
|
||||
var body = mapper.Map(request);
|
||||
var read = OnCodex(api => api.OfferStorageAsync(body));
|
||||
|
||||
@ -36,7 +36,7 @@ namespace CodexClient
|
||||
};
|
||||
}
|
||||
|
||||
public CodexOpenApi.SalesAvailability Map(StorageAvailability availability)
|
||||
public CodexOpenApi.SalesAvailability Map(CreateStorageAvailability availability)
|
||||
{
|
||||
return new CodexOpenApi.SalesAvailability
|
||||
{
|
||||
@ -70,15 +70,13 @@ namespace CodexClient
|
||||
{
|
||||
return new StorageAvailability
|
||||
(
|
||||
availability.Id,
|
||||
ToByteSize(availability.TotalSize),
|
||||
ToTimespan(availability.Duration),
|
||||
new TestToken(ToBigInt(availability.MinPricePerBytePerSecond)),
|
||||
new TestToken(ToBigInt(availability.TotalCollateral))
|
||||
)
|
||||
{
|
||||
Id = availability.Id,
|
||||
FreeSpace = ToByteSize(availability.FreeSize),
|
||||
};
|
||||
new TestToken(ToBigInt(availability.TotalCollateral)),
|
||||
ToByteSize(availability.FreeSize)
|
||||
);
|
||||
}
|
||||
|
||||
public StoragePurchase Map(CodexOpenApi.Purchase purchase)
|
||||
|
||||
@ -6,7 +6,7 @@ namespace CodexClient
|
||||
{
|
||||
public interface IMarketplaceAccess
|
||||
{
|
||||
string MakeStorageAvailable(StorageAvailability availability);
|
||||
string MakeStorageAvailable(CreateStorageAvailability availability);
|
||||
StorageAvailability[] GetAvailabilities();
|
||||
IStoragePurchaseContract RequestStorage(StoragePurchaseRequest purchase);
|
||||
}
|
||||
@ -49,7 +49,7 @@ namespace CodexClient
|
||||
return new StoragePurchaseContract(log, codexAccess, response, purchase, hooks);
|
||||
}
|
||||
|
||||
public string MakeStorageAvailable(StorageAvailability availability)
|
||||
public string MakeStorageAvailable(CreateStorageAvailability availability)
|
||||
{
|
||||
availability.Log(log);
|
||||
|
||||
@ -77,7 +77,7 @@ namespace CodexClient
|
||||
|
||||
public class MarketplaceUnavailable : IMarketplaceAccess
|
||||
{
|
||||
public string MakeStorageAvailable(StorageAvailability availability)
|
||||
public string MakeStorageAvailable(CreateStorageAvailability availability)
|
||||
{
|
||||
Unavailable();
|
||||
throw new NotImplementedException();
|
||||
|
||||
@ -84,9 +84,9 @@ namespace CodexClient
|
||||
//public PoRParameters Por { get; set; }
|
||||
}
|
||||
|
||||
public class StorageAvailability
|
||||
public class CreateStorageAvailability
|
||||
{
|
||||
public StorageAvailability(ByteSize totalSpace, TimeSpan maxDuration, TestToken minPricePerBytePerSecond, TestToken totalCollateral)
|
||||
public CreateStorageAvailability(ByteSize totalSpace, TimeSpan maxDuration, TestToken minPricePerBytePerSecond, TestToken totalCollateral)
|
||||
{
|
||||
TotalSpace = totalSpace;
|
||||
MaxDuration = maxDuration;
|
||||
@ -94,20 +94,49 @@ namespace CodexClient
|
||||
TotalCollateral = totalCollateral;
|
||||
}
|
||||
|
||||
public string Id { get; set; } = string.Empty;
|
||||
public ByteSize TotalSpace { get; }
|
||||
public TimeSpan MaxDuration { get; }
|
||||
public TestToken MinPricePerBytePerSecond { get; }
|
||||
public TestToken TotalCollateral { get; }
|
||||
public ByteSize FreeSpace { get; set; } = ByteSize.Zero;
|
||||
public TestToken TotalCollateral { get; }
|
||||
|
||||
public void Log(ILog log)
|
||||
{
|
||||
log.Log($"Storage Availability: (" +
|
||||
log.Log($"Create storage Availability: (" +
|
||||
$"totalSize: {TotalSpace}, " +
|
||||
$"maxDuration: {Time.FormatDuration(MaxDuration)}, " +
|
||||
$"maxDuration: {Time.FormatDuration(MaxDuration)}, " +
|
||||
$"minPricePerBytePerSecond: {MinPricePerBytePerSecond}, " +
|
||||
$"totalCollateral: {TotalCollateral})");
|
||||
}
|
||||
}
|
||||
|
||||
public class StorageAvailability
|
||||
{
|
||||
public StorageAvailability(string id, ByteSize totalSpace, TimeSpan maxDuration, TestToken minPricePerBytePerSecond, TestToken totalCollateral, ByteSize freeSpace)
|
||||
{
|
||||
Id = id;
|
||||
TotalSpace = totalSpace;
|
||||
MaxDuration = maxDuration;
|
||||
MinPricePerBytePerSecond = minPricePerBytePerSecond;
|
||||
TotalCollateral = totalCollateral;
|
||||
FreeSpace = freeSpace;
|
||||
}
|
||||
|
||||
public string Id { get; }
|
||||
public ByteSize TotalSpace { get; }
|
||||
public TimeSpan MaxDuration { get; }
|
||||
public TestToken MinPricePerBytePerSecond { get; }
|
||||
public TestToken TotalCollateral { get; }
|
||||
public ByteSize FreeSpace { get; }
|
||||
|
||||
public void Log(ILog log)
|
||||
{
|
||||
log.Log($"Storage Availability: (" +
|
||||
$"id: {Id}, " +
|
||||
$"totalSize: {TotalSpace}, " +
|
||||
$"maxDuration: {Time.FormatDuration(MaxDuration)}, " +
|
||||
$"minPricePerBytePerSecond: {MinPricePerBytePerSecond}, " +
|
||||
$"totalCollateral: {TotalCollateral}, " +
|
||||
$"freeSpace: {FreeSpace})");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -14,7 +14,13 @@ namespace CodexClient
|
||||
void WaitForStorageContractSubmitted();
|
||||
void WaitForStorageContractStarted();
|
||||
void WaitForStorageContractFinished();
|
||||
void WaitForContractFailed();
|
||||
void WaitForContractFailed(IMarketplaceConfigInput config);
|
||||
}
|
||||
|
||||
public interface IMarketplaceConfigInput
|
||||
{
|
||||
int MaxNumberOfSlashes { get; }
|
||||
TimeSpan PeriodDuration { get; }
|
||||
}
|
||||
|
||||
public class StoragePurchaseContract : IStoragePurchaseContract
|
||||
@ -99,7 +105,7 @@ namespace CodexClient
|
||||
AssertDuration(SubmittedToFinished, timeout, nameof(SubmittedToFinished));
|
||||
}
|
||||
|
||||
public void WaitForContractFailed()
|
||||
public void WaitForContractFailed(IMarketplaceConfigInput config)
|
||||
{
|
||||
if (!contractStartedUtc.HasValue)
|
||||
{
|
||||
@ -107,7 +113,30 @@ namespace CodexClient
|
||||
}
|
||||
var currentContractTime = DateTime.UtcNow - contractSubmittedUtc!.Value;
|
||||
var timeout = (Purchase.Duration - currentContractTime) + gracePeriod;
|
||||
WaitForStorageContractState(timeout, StoragePurchaseState.Failed);
|
||||
var minTimeout = TimeNeededToFailEnoughProofsToFreeASlot(config);
|
||||
|
||||
if (timeout < minTimeout)
|
||||
{
|
||||
throw new ArgumentOutOfRangeException(
|
||||
$"Test is misconfigured. Assuming a proof is required every period, it will take {Time.FormatDuration(minTimeout)} " +
|
||||
$"to fail enough proofs for a slot to be freed. But, the storage contract will complete in {Time.FormatDuration(timeout)}. " +
|
||||
$"Increase the duration."
|
||||
);
|
||||
}
|
||||
|
||||
WaitForStorageContractState(timeout, StoragePurchaseState.Errored);
|
||||
}
|
||||
|
||||
private TimeSpan TimeNeededToFailEnoughProofsToFreeASlot(IMarketplaceConfigInput config)
|
||||
{
|
||||
var numMissedProofsRequiredForFree = config.MaxNumberOfSlashes;
|
||||
var timePerProof = config.PeriodDuration;
|
||||
var result = timePerProof * (numMissedProofsRequiredForFree + 1);
|
||||
|
||||
// Times 2!
|
||||
// Because of pointer-downtime it's possible that some periods even though there's a probability of 100%
|
||||
// will not require any proof. To be safe we take twice the required time.
|
||||
return result * 2;
|
||||
}
|
||||
|
||||
private void WaitForStorageContractState(TimeSpan timeout, StoragePurchaseState desiredState, int sleep = 1000)
|
||||
@ -128,7 +157,7 @@ namespace CodexClient
|
||||
hooks.OnStorageContractUpdated(purchaseStatus);
|
||||
}
|
||||
|
||||
if (lastState == StoragePurchaseState.Errored)
|
||||
if (desiredState != StoragePurchaseState.Errored && lastState == StoragePurchaseState.Errored)
|
||||
{
|
||||
FrameworkAssert.Fail("Contract errored: " + statusJson);
|
||||
}
|
||||
|
||||
@ -47,7 +47,7 @@ namespace CodexContractsPlugin.ChainMonitor
|
||||
handler = changeHandler;
|
||||
this.doProofPeriodMonitoring = doProofPeriodMonitoring;
|
||||
TotalSpan = new TimeRange(startUtc, startUtc);
|
||||
PeriodMonitor = new PeriodMonitor(contracts);
|
||||
PeriodMonitor = new PeriodMonitor(log, contracts);
|
||||
}
|
||||
|
||||
public TimeRange TotalSpan { get; private set; }
|
||||
|
||||
@ -1,15 +1,18 @@
|
||||
using Utils;
|
||||
using Logging;
|
||||
using Utils;
|
||||
|
||||
namespace CodexContractsPlugin.ChainMonitor
|
||||
{
|
||||
public class PeriodMonitor
|
||||
{
|
||||
private readonly ILog log;
|
||||
private readonly ICodexContracts contracts;
|
||||
private readonly List<PeriodReport> reports = new List<PeriodReport>();
|
||||
private ulong? currentPeriod = null;
|
||||
|
||||
public PeriodMonitor(ICodexContracts contracts)
|
||||
public PeriodMonitor(ILog log, ICodexContracts contracts)
|
||||
{
|
||||
this.log = log;
|
||||
this.contracts = contracts;
|
||||
}
|
||||
|
||||
@ -58,7 +61,9 @@ namespace CodexContractsPlugin.ChainMonitor
|
||||
}
|
||||
}
|
||||
}
|
||||
reports.Add(new PeriodReport(periodNumber, total, required, missed.ToArray()));
|
||||
var report = new PeriodReport(periodNumber, total, required, missed.ToArray());
|
||||
log.Log($"Period report: {report}");
|
||||
reports.Add(report);
|
||||
}
|
||||
}
|
||||
|
||||
@ -105,6 +110,16 @@ namespace CodexContractsPlugin.ChainMonitor
|
||||
public ulong TotalNumSlots { get; }
|
||||
public ulong TotalProofsRequired { get; }
|
||||
public PeriodProofMissed[] MissedProofs { get; }
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
var missed = "None";
|
||||
if (MissedProofs.Length > 0)
|
||||
{
|
||||
missed = string.Join("+", MissedProofs.Select(p => $"{p.FormatHost()} missed {p.Request.Request.Id} slot {p.SlotIndex}"));
|
||||
}
|
||||
return $"Period:{PeriodNumber}=[Slots:{TotalNumSlots},ProofsRequired:{TotalProofsRequired},ProofsMissed:{missed}]";
|
||||
}
|
||||
}
|
||||
|
||||
public class PeriodProofMissed
|
||||
@ -119,5 +134,11 @@ namespace CodexContractsPlugin.ChainMonitor
|
||||
public EthAddress? Host { get; }
|
||||
public IChainStateRequest Request { get; }
|
||||
public int SlotIndex { get; }
|
||||
|
||||
public string FormatHost()
|
||||
{
|
||||
if (Host == null) return "Unknown host";
|
||||
return Host.Address;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -146,7 +146,6 @@ namespace CodexContractsPlugin
|
||||
|
||||
public void WaitUntilNextPeriod()
|
||||
{
|
||||
log.Log("Waiting until next proof period...");
|
||||
var now = DateTimeOffset.UtcNow.ToUnixTimeSeconds();
|
||||
var periodSeconds = (int)Deployment.Config.Proofs.Period;
|
||||
var secondsLeft = now % periodSeconds;
|
||||
|
||||
@ -2,6 +2,7 @@
|
||||
using BlockchainUtils;
|
||||
using Nethereum.Hex.HexConvertors.Extensions;
|
||||
using Newtonsoft.Json;
|
||||
using CodexClient;
|
||||
using Utils;
|
||||
|
||||
namespace CodexContractsPlugin.Marketplace
|
||||
@ -92,5 +93,11 @@ namespace CodexContractsPlugin.Marketplace
|
||||
[JsonIgnore]
|
||||
public BlockTimeEntry Block { get; set; }
|
||||
}
|
||||
|
||||
public partial class MarketplaceConfig : IMarketplaceConfigInput
|
||||
{
|
||||
public int MaxNumberOfSlashes => this.Collateral.MaxNumberOfSlashes;
|
||||
public TimeSpan PeriodDuration => TimeSpan.FromSeconds(this.Proofs.Period);
|
||||
}
|
||||
}
|
||||
#pragma warning restore CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider declaring as nullable.
|
||||
|
||||
File diff suppressed because one or more lines are too long
@ -2,7 +2,7 @@
|
||||
{
|
||||
public class CodexDockerImage
|
||||
{
|
||||
private const string DefaultDockerImage = "codexstorage/nim-codex:0.2.3-dist-tests";
|
||||
private const string DefaultDockerImage = "codexstorage/nim-codex:sha-3e17207-dist-tests";
|
||||
|
||||
public static string Override { get; set; } = string.Empty;
|
||||
|
||||
|
||||
@ -7,15 +7,22 @@ using Utils;
|
||||
|
||||
namespace CodexReleaseTests.DataTests
|
||||
{
|
||||
[TestFixture]
|
||||
[TestFixture(2, 10)]
|
||||
[TestFixture(5, 20)]
|
||||
[TestFixture(10, 50)]
|
||||
public class SwarmTests : AutoBootstrapDistTest
|
||||
{
|
||||
private readonly int numberOfNodes;
|
||||
private readonly int filesizeMb;
|
||||
|
||||
public SwarmTests(int numberOfNodes, int filesizeMb)
|
||||
{
|
||||
this.numberOfNodes = numberOfNodes;
|
||||
this.filesizeMb = filesizeMb;
|
||||
}
|
||||
|
||||
[Test]
|
||||
[Combinatorial]
|
||||
public void SmallSwarm(
|
||||
[Values(2)] int numberOfNodes,
|
||||
[Values(10)] int filesizeMb
|
||||
)
|
||||
public void Swarm()
|
||||
{
|
||||
var filesize = filesizeMb.MB();
|
||||
var nodes = StartCodex(numberOfNodes);
|
||||
@ -28,11 +35,7 @@ namespace CodexReleaseTests.DataTests
|
||||
}
|
||||
|
||||
[Test]
|
||||
[Combinatorial]
|
||||
public void StreamlessSmallSwarm(
|
||||
[Values(2)] int numberOfNodes,
|
||||
[Values(10)] int filesizeMb
|
||||
)
|
||||
public void StreamlessSwarm()
|
||||
{
|
||||
var filesize = filesizeMb.MB();
|
||||
var nodes = StartCodex(numberOfNodes);
|
||||
|
||||
49
Tests/CodexReleaseTests/MarketTests/ChainMonitor.cs
Normal file
49
Tests/CodexReleaseTests/MarketTests/ChainMonitor.cs
Normal file
@ -0,0 +1,49 @@
|
||||
using CodexContractsPlugin;
|
||||
using CodexContractsPlugin.ChainMonitor;
|
||||
using Logging;
|
||||
|
||||
namespace CodexReleaseTests.MarketTests
|
||||
{
|
||||
public class ChainMonitor
|
||||
{
|
||||
private readonly ChainState chainMonitor;
|
||||
private readonly TimeSpan interval;
|
||||
private CancellationTokenSource cts = new CancellationTokenSource();
|
||||
private Task worker = null!;
|
||||
|
||||
public ChainMonitor(ILog log, ICodexContracts contracts, DateTime startUtc, TimeSpan interval)
|
||||
{
|
||||
chainMonitor = new ChainState(log, contracts, new DoNothingChainEventHandler(), startUtc, true);
|
||||
this.interval = interval;
|
||||
}
|
||||
|
||||
public void Start()
|
||||
{
|
||||
cts = new CancellationTokenSource();
|
||||
worker = Task.Run(Worker);
|
||||
}
|
||||
|
||||
public void Stop()
|
||||
{
|
||||
cts.Cancel();
|
||||
worker.Wait();
|
||||
|
||||
worker = null!;
|
||||
cts = null!;
|
||||
}
|
||||
|
||||
public PeriodMonitorResult GetPeriodReports()
|
||||
{
|
||||
return chainMonitor.PeriodMonitor.GetAndClearReports();
|
||||
}
|
||||
|
||||
private void Worker()
|
||||
{
|
||||
while (!cts.IsCancellationRequested)
|
||||
{
|
||||
Thread.Sleep(interval);
|
||||
chainMonitor.Update();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -8,11 +8,16 @@ namespace CodexReleaseTests.MarketTests
|
||||
public class FailTest : MarketplaceAutoBootstrapDistTest
|
||||
{
|
||||
protected override int NumberOfHosts => 4;
|
||||
private readonly int SlotTolerance;
|
||||
protected override int NumberOfClients => 1;
|
||||
protected override ByteSize HostAvailabilitySize => 1.GB();
|
||||
protected override TimeSpan HostAvailabilityMaxDuration => TimeSpan.FromDays(1.0);
|
||||
|
||||
[Ignore("Slots are never freed because proofs are never marked as missing. Issue: https://github.com/codex-storage/nim-codex/issues/1153")]
|
||||
public FailTest()
|
||||
{
|
||||
SlotTolerance = NumberOfHosts / 2;
|
||||
}
|
||||
|
||||
[Test]
|
||||
[Combinatorial]
|
||||
public void Fail(
|
||||
@ -35,7 +40,8 @@ namespace CodexReleaseTests.MarketTests
|
||||
|
||||
WaitForSlotFreedEvents();
|
||||
|
||||
request.WaitForContractFailed();
|
||||
var config = GetContracts().Deployment.Config;
|
||||
request.WaitForContractFailed(config);
|
||||
}
|
||||
|
||||
private void WaitForSlotFreedEvents()
|
||||
@ -49,7 +55,8 @@ namespace CodexReleaseTests.MarketTests
|
||||
{
|
||||
var events = GetContracts().GetEvents(GetTestRunTimeRange());
|
||||
var slotFreed = events.GetSlotFreedEvents();
|
||||
if (slotFreed.Length == NumberOfHosts)
|
||||
Log($"SlotFreed events: {slotFreed.Length} - Expected: {SlotTolerance}");
|
||||
if (slotFreed.Length > SlotTolerance)
|
||||
{
|
||||
Log($"{nameof(WaitForSlotFreedEvents)} took {Time.FormatDuration(DateTime.UtcNow - start)}");
|
||||
return;
|
||||
@ -67,7 +74,7 @@ namespace CodexReleaseTests.MarketTests
|
||||
Duration = HostAvailabilityMaxDuration / 2,
|
||||
Expiry = TimeSpan.FromMinutes(5.0),
|
||||
MinRequiredNumberOfNodes = (uint)NumberOfHosts,
|
||||
NodeFailureTolerance = (uint)(NumberOfHosts / 2),
|
||||
NodeFailureTolerance = (uint)SlotTolerance,
|
||||
PricePerBytePerSecond = 100.TstWei(),
|
||||
ProofProbability = 1, // Require a proof every period
|
||||
CollateralPerByte = 1.TstWei()
|
||||
|
||||
@ -6,7 +6,7 @@ using Utils;
|
||||
namespace CodexReleaseTests.MarketTests
|
||||
{
|
||||
[TestFixture(5, 3, 1)]
|
||||
[TestFixture(10, 20, 10)]
|
||||
[TestFixture(10, 8, 4)]
|
||||
public class FinishTest : MarketplaceAutoBootstrapDistTest
|
||||
{
|
||||
public FinishTest(int hosts, int slots, int tolerance)
|
||||
@ -32,6 +32,7 @@ namespace CodexReleaseTests.MarketTests
|
||||
{
|
||||
var hosts = StartHosts();
|
||||
var client = StartClients().Single();
|
||||
AssertHostAvailabilitiesAreEmpty(hosts);
|
||||
|
||||
var request = CreateStorageRequest(client);
|
||||
|
||||
@ -46,6 +47,7 @@ namespace CodexReleaseTests.MarketTests
|
||||
AssertClientHasPaidForContract(pricePerBytePerSecond, client, request, hosts);
|
||||
AssertHostsWerePaidForContract(pricePerBytePerSecond, request, hosts);
|
||||
AssertHostsCollateralsAreUnchanged(hosts);
|
||||
AssertHostAvailabilitiesAreEmpty(hosts);
|
||||
}
|
||||
|
||||
private IStoragePurchaseContract CreateStorageRequest(ICodexNode client)
|
||||
|
||||
@ -53,11 +53,15 @@ namespace CodexReleaseTests.Utils
|
||||
protected abstract ByteSize HostAvailabilitySize { get; }
|
||||
protected abstract TimeSpan HostAvailabilityMaxDuration { get; }
|
||||
protected virtual bool MonitorChainState { get; } = true;
|
||||
protected TimeSpan HostBlockTTL { get; } = TimeSpan.FromMinutes(1.0);
|
||||
|
||||
public ICodexNodeGroup StartHosts()
|
||||
{
|
||||
var hosts = StartCodex(NumberOfHosts, s => s
|
||||
.WithName("host")
|
||||
.WithBlockTTL(HostBlockTTL)
|
||||
.WithBlockMaintenanceNumber(1000)
|
||||
.WithBlockMaintenanceInterval(HostBlockTTL / 2)
|
||||
.EnableMarketplace(GetGeth(), GetContracts(), m => m
|
||||
.WithInitial(StartingBalanceEth.Eth(), StartingBalanceTST.Tst())
|
||||
.AsStorageNode()
|
||||
@ -70,7 +74,7 @@ namespace CodexReleaseTests.Utils
|
||||
AssertTstBalance(host, StartingBalanceTST.Tst(), nameof(StartHosts));
|
||||
AssertEthBalance(host, StartingBalanceEth.Eth(), nameof(StartHosts));
|
||||
|
||||
host.Marketplace.MakeStorageAvailable(new StorageAvailability(
|
||||
host.Marketplace.MakeStorageAvailable(new CreateStorageAvailability(
|
||||
totalSpace: HostAvailabilitySize,
|
||||
maxDuration: HostAvailabilityMaxDuration,
|
||||
minPricePerBytePerSecond: 1.TstWei(),
|
||||
@ -84,6 +88,9 @@ namespace CodexReleaseTests.Utils
|
||||
{
|
||||
var host = StartCodex(s => s
|
||||
.WithName("singlehost")
|
||||
.WithBlockTTL(HostBlockTTL)
|
||||
.WithBlockMaintenanceNumber(1000)
|
||||
.WithBlockMaintenanceInterval(HostBlockTTL / 2)
|
||||
.EnableMarketplace(GetGeth(), GetContracts(), m => m
|
||||
.WithInitial(StartingBalanceEth.Eth(), StartingBalanceTST.Tst())
|
||||
.AsStorageNode()
|
||||
@ -94,7 +101,7 @@ namespace CodexReleaseTests.Utils
|
||||
AssertTstBalance(host, StartingBalanceTST.Tst(), nameof(StartOneHost));
|
||||
AssertEthBalance(host, StartingBalanceEth.Eth(), nameof(StartOneHost));
|
||||
|
||||
host.Marketplace.MakeStorageAvailable(new StorageAvailability(
|
||||
host.Marketplace.MakeStorageAvailable(new CreateStorageAvailability(
|
||||
totalSpace: HostAvailabilitySize,
|
||||
maxDuration: HostAvailabilityMaxDuration,
|
||||
minPricePerBytePerSecond: 1.TstWei(),
|
||||
@ -103,6 +110,30 @@ namespace CodexReleaseTests.Utils
|
||||
return host;
|
||||
}
|
||||
|
||||
public void AssertHostAvailabilitiesAreEmpty(IEnumerable<ICodexNode> hosts)
|
||||
{
|
||||
var retry = GetAvailabilitySpaceAssertRetry();
|
||||
retry.Run(() =>
|
||||
{
|
||||
foreach (var host in hosts)
|
||||
{
|
||||
AssertHostAvailabilitiesAreEmpty(host);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void AssertHostAvailabilitiesAreEmpty(ICodexNode host)
|
||||
{
|
||||
var availabilities = host.Marketplace.GetAvailabilities();
|
||||
foreach (var a in availabilities)
|
||||
{
|
||||
if (a.FreeSpace.SizeInBytes != a.TotalSpace.SizeInBytes)
|
||||
{
|
||||
throw new Exception(nameof(AssertHostAvailabilitiesAreEmpty) + $" free: {a.FreeSpace} total: {a.TotalSpace}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void AssertTstBalance(ICodexNode node, TestToken expectedBalance, string message)
|
||||
{
|
||||
AssertTstBalance(node.EthAddress, expectedBalance, message);
|
||||
@ -160,6 +191,15 @@ namespace CodexReleaseTests.Utils
|
||||
failFast: false);
|
||||
}
|
||||
|
||||
private Retry GetAvailabilitySpaceAssertRetry()
|
||||
{
|
||||
return new Retry("AssertAvailabilitySpace",
|
||||
maxTimeout: HostBlockTTL * 3,
|
||||
sleepAfterFail: TimeSpan.FromSeconds(10.0),
|
||||
onFail: f => { },
|
||||
failFast: false);
|
||||
}
|
||||
|
||||
private TestToken GetTstBalance(ICodexNode node)
|
||||
{
|
||||
return GetContracts().GetTestTokenBalance(node);
|
||||
|
||||
@ -10,7 +10,6 @@ namespace DistTestCore.Helpers
|
||||
{
|
||||
try
|
||||
{
|
||||
|
||||
Time.WaitUntil(() => {
|
||||
var c = constraint.Resolve();
|
||||
return c.ApplyTo(actual()).IsSuccess;
|
||||
|
||||
@ -28,10 +28,11 @@ namespace DistTestCore
|
||||
public static string GetRawFixtureName()
|
||||
{
|
||||
var test = TestContext.CurrentContext.Test;
|
||||
if (test.ClassName!.Contains("AdhocContext")) return "none";
|
||||
var className = test.ClassName!.Substring(test.ClassName.LastIndexOf('.') + 1);
|
||||
className += FormatArguments(test);
|
||||
return className.Replace('.', '-');
|
||||
var fullName = test.FullName;
|
||||
if (fullName.Contains("AdhocContext")) return "none";
|
||||
var name = fullName.Substring(0, fullName.LastIndexOf('.'));
|
||||
name += FormatArguments(test);
|
||||
return name.Replace('.', '-').Replace(',', '-');
|
||||
}
|
||||
|
||||
public static string GetCategoryName()
|
||||
|
||||
@ -50,7 +50,7 @@ namespace ExperimentalTests.BasicTests
|
||||
{
|
||||
AssertBalance(contracts, host, Is.EqualTo(hostInitialBalance), "Host initial balance");
|
||||
|
||||
var availability = new StorageAvailability(
|
||||
var availability = new CreateStorageAvailability(
|
||||
totalSpace: 10.GB(),
|
||||
maxDuration: TimeSpan.FromMinutes(30),
|
||||
minPricePerBytePerSecond: 1.TstWei(),
|
||||
|
||||
@ -97,6 +97,7 @@ namespace CodexTests
|
||||
|
||||
public void AssertBalance(ICodexContracts contracts, ICodexNode codexNode, Constraint constraint, string msg)
|
||||
{
|
||||
Assert.Fail("Depricated, use MarketplaceAutobootstrapDistTest assertBalances instead.");
|
||||
AssertHelpers.RetryAssert(constraint, () => contracts.GetTestTokenBalance(codexNode), nameof(AssertBalance) + msg);
|
||||
}
|
||||
|
||||
|
||||
46
Tests/FrameworkTests/Utils/EthAddressEqualityTests.cs
Normal file
46
Tests/FrameworkTests/Utils/EthAddressEqualityTests.cs
Normal file
@ -0,0 +1,46 @@
|
||||
using GethPlugin;
|
||||
using NUnit.Framework;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using Utils;
|
||||
|
||||
namespace FrameworkTests.Utils
|
||||
{
|
||||
[TestFixture]
|
||||
public class EthAddressEqualityTests
|
||||
{
|
||||
[Test]
|
||||
[Combinatorial]
|
||||
public void Equal(
|
||||
[Values(1, 2, 3, 4, 5)] int runs
|
||||
)
|
||||
{
|
||||
var account = EthAccountGenerator.GenerateNew();
|
||||
|
||||
var str = account.EthAddress.Address;
|
||||
|
||||
var addr = new EthAddress(str);
|
||||
|
||||
Assert.That(addr, Is.EqualTo(account.EthAddress));
|
||||
Assert.That(addr == account.EthAddress);
|
||||
Assert.That(!(addr != account.EthAddress));
|
||||
}
|
||||
|
||||
[Test]
|
||||
[Combinatorial]
|
||||
public void NotEqual(
|
||||
[Values(1, 2, 3, 4, 5)] int runs
|
||||
)
|
||||
{
|
||||
var account1 = EthAccountGenerator.GenerateNew();
|
||||
var account2 = EthAccountGenerator.GenerateNew();
|
||||
|
||||
Assert.That(account1.EthAddress, Is.Not.EqualTo(account2.EthAddress));
|
||||
Assert.That(account1.EthAddress != account2.EthAddress);
|
||||
Assert.That(!(account1.EthAddress == account2.EthAddress));
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -17,6 +17,13 @@
|
||||
public string EncodedCid { get; set; } = string.Empty;
|
||||
public string PurchaseId { get; set; } = string.Empty;
|
||||
public DateTime PurchaseFinishedUtc { get; set; } = DateTime.MinValue;
|
||||
|
||||
public void ClearPurchase()
|
||||
{
|
||||
EncodedCid = string.Empty;
|
||||
PurchaseId = string.Empty;
|
||||
PurchaseFinishedUtc = DateTime.MinValue;
|
||||
}
|
||||
}
|
||||
|
||||
[Serializable]
|
||||
|
||||
@ -69,7 +69,7 @@ namespace CodexNetDeployer
|
||||
|
||||
if (config.ShouldMakeStorageAvailable)
|
||||
{
|
||||
var availability = new StorageAvailability(
|
||||
var availability = new CreateStorageAvailability(
|
||||
totalSpace: config.StorageSell!.Value.MB(),
|
||||
maxDuration: TimeSpan.FromSeconds(config.MaxDuration),
|
||||
minPricePerBytePerSecond: config.MinPricePerBytePerSecond.TstWei(),
|
||||
|
||||
@ -165,13 +165,7 @@ namespace TestNetRewarder
|
||||
|
||||
private void DescribeMissedProof(List<string> lines, PeriodProofMissed missedProof)
|
||||
{
|
||||
lines.Add($"[{FormatHost(missedProof.Host)}] missed proof for {FormatRequestId(missedProof.Request)} (slotIndex: {missedProof.SlotIndex})");
|
||||
}
|
||||
|
||||
private string FormatHost(EthAddress? host)
|
||||
{
|
||||
if (host == null) return "Unknown host";
|
||||
return host.Address;
|
||||
lines.Add($"[{missedProof.FormatHost()}] missed proof for {FormatRequestId(missedProof.Request)} (slotIndex: {missedProof.SlotIndex})");
|
||||
}
|
||||
|
||||
private void AddRequestBlock(RequestEvent requestEvent, string eventName, params string[] content)
|
||||
|
||||
@ -39,16 +39,16 @@
|
||||
|
||||
public Dictionary<string, string> LogReplacements = new()
|
||||
{
|
||||
{ "0xa1f988fBa23EFd5fA36F4c1a2D1E3c83e25bee4e", "codex 01" },
|
||||
{ "0xa26a91310F9f2987AA7e0b1ca70e5C474c88ed34", "codex 02" },
|
||||
{ "0x0CDC9d2D375300C46E13a679cD9eA5299A4FAc74", "codex 03" },
|
||||
{ "0x7AF1a49A4a52e4bCe3789Ce3d43ff8AD8c8F2118", "codex 04" },
|
||||
{ "0xfbbEB320c6c775f6565c7bcC732b2813Dd6E0cd3", "codex 05" },
|
||||
{ "0x4A904CA0998B643eb42d4ae190a5821A4ac51E68", "codex 06" },
|
||||
{ "0x2b8Ea47d0966B26DEec485c0fCcF0D1A8b52A0e8", "codex 07" },
|
||||
{ "0x78F90A61d9a2aA93B61A7503Cc2177fFEF379021", "codex 08" },
|
||||
{ "0xE7EEb996B3c817cEd03d10cd64A1325DA33D92e7", "codex 09" },
|
||||
{ "0xD25C7609e97F40b66E74c0FcEbeA06D09423CC7e", "codex 10" }
|
||||
{ "0x3620ec38d88e9f0cf7feceebf97864f27676aa3e", "codex-01" },
|
||||
{ "0xd80dc50af2a826f2cddc13840d05aed4ee6536c3", "codex-02" },
|
||||
{ "0x2d1cd0fa0c7e0d29e7b2482b9ff87d5e7b76b905", "codex-03" },
|
||||
{ "0xd47063bb6e56c9a6edb7612d33ad7d49eeb55ee0", "codex-04" },
|
||||
{ "0x069da63e29b12a3828984379fcbd7dd3ee3774aa", "codex-05" },
|
||||
{ "0x43fcceb2a9ce4761ccaa4c9f8d390c7581c190aa", "codex-06" },
|
||||
{ "0x1a30cef06dbbf8ec25062e4e8d22e8df292f5054", "codex-07" },
|
||||
{ "0xe169b5dcbae9a7392072323aaf5a677a33d67ecd", "codex-08" },
|
||||
{ "0x21f7428619ef9f53addc5dab6723c822a8a96b42", "codex-09" },
|
||||
{ "0xf9bd20512de2d5ca0dcfd8d3cd08a2821917797a", "codex-10" }
|
||||
};
|
||||
|
||||
public string GetElasticSearchUsername()
|
||||
|
||||
@ -28,21 +28,22 @@ namespace TraceContract
|
||||
|
||||
public Output(ILog log, Input input, Config config)
|
||||
{
|
||||
this.input = input;
|
||||
this.config = config;
|
||||
|
||||
folder = config.GetOuputFolder();
|
||||
Directory.CreateDirectory(folder);
|
||||
|
||||
var filename = Path.Combine(folder, $"contract_{input.PurchaseId}");
|
||||
var fileLog = new FileLog(filename);
|
||||
log.Log($"Logging to '{filename}'");
|
||||
|
||||
this.log = new LogSplitter(fileLog, log);
|
||||
foreach (var pair in config.LogReplacements)
|
||||
{
|
||||
fileLog.AddStringReplace(pair.Key, pair.Value);
|
||||
fileLog.AddStringReplace(pair.Key.ToLowerInvariant(), pair.Value);
|
||||
this.log.AddStringReplace(pair.Key, pair.Value);
|
||||
this.log.AddStringReplace(pair.Key.ToLowerInvariant(), pair.Value);
|
||||
}
|
||||
|
||||
log.Log($"Logging to '{filename}'");
|
||||
this.log = new LogSplitter(fileLog, log);
|
||||
this.input = input;
|
||||
this.config = config;
|
||||
}
|
||||
|
||||
public void LogRequestCreated(RequestEvent requestEvent)
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user