2023-06-26 13:37:16 +00:00
|
|
|
|
using DistTestCore;
|
|
|
|
|
using DistTestCore.Codex;
|
2023-06-27 13:28:00 +00:00
|
|
|
|
using Newtonsoft.Json;
|
2023-06-26 13:37:16 +00:00
|
|
|
|
using NUnit.Framework;
|
2023-06-28 13:11:20 +00:00
|
|
|
|
using Utils;
|
2023-06-23 09:38:30 +00:00
|
|
|
|
|
|
|
|
|
namespace ContinuousTests.Tests
|
|
|
|
|
{
|
2023-06-26 13:37:16 +00:00
|
|
|
|
public class MarketplaceTest : ContinuousTest
|
|
|
|
|
{
|
|
|
|
|
public override int RequiredNumberOfNodes => 1;
|
2023-06-28 08:41:04 +00:00
|
|
|
|
public override TimeSpan RunTestEvery => TimeSpan.FromMinutes(15);
|
2023-06-26 14:00:16 +00:00
|
|
|
|
public override TestFailMode TestFailMode => TestFailMode.StopAfterFirstFailure;
|
2023-06-28 09:01:10 +00:00
|
|
|
|
public override int EthereumAccountIndex => 200;
|
|
|
|
|
public override string CustomK8sNamespace => "codex-continuous-marketplace";
|
2023-06-26 13:37:16 +00:00
|
|
|
|
|
2023-06-27 13:28:00 +00:00
|
|
|
|
private readonly uint numberOfSlots = 3;
|
|
|
|
|
private readonly ByteSize fileSize = 10.MB();
|
|
|
|
|
private readonly TestToken pricePerSlotPerSecond = 10.TestTokens();
|
2023-06-26 13:37:16 +00:00
|
|
|
|
|
|
|
|
|
private TestFile file = null!;
|
|
|
|
|
private ContentId? cid;
|
|
|
|
|
private string purchaseId = string.Empty;
|
|
|
|
|
|
|
|
|
|
[TestMoment(t: Zero)]
|
|
|
|
|
public void NodePostsStorageRequest()
|
|
|
|
|
{
|
2023-06-28 08:41:04 +00:00
|
|
|
|
var contractDuration = TimeSpan.FromMinutes(11); //TimeSpan.FromDays(3) + TimeSpan.FromHours(1);
|
2023-06-26 13:37:16 +00:00
|
|
|
|
decimal totalDurationSeconds = Convert.ToDecimal(contractDuration.TotalSeconds);
|
2023-06-28 08:41:04 +00:00
|
|
|
|
var expectedTotalCost = numberOfSlots * pricePerSlotPerSecond.Amount * (totalDurationSeconds + 1) * 1000000;
|
2023-06-26 13:37:16 +00:00
|
|
|
|
|
|
|
|
|
file = FileManager.GenerateTestFile(fileSize);
|
|
|
|
|
|
2023-06-28 09:48:05 +00:00
|
|
|
|
NodeRunner.RunNode((codexAccess, marketplaceAccess) =>
|
2023-06-26 13:37:16 +00:00
|
|
|
|
{
|
|
|
|
|
cid = UploadFile(codexAccess.Node, file);
|
|
|
|
|
Assert.That(cid, Is.Not.Null);
|
|
|
|
|
|
2023-06-28 09:48:05 +00:00
|
|
|
|
purchaseId = marketplaceAccess.RequestStorage(
|
2023-06-26 13:37:16 +00:00
|
|
|
|
contentId: cid!,
|
2023-06-27 13:28:00 +00:00
|
|
|
|
pricePerSlotPerSecond: pricePerSlotPerSecond,
|
2023-06-26 13:37:16 +00:00
|
|
|
|
requiredCollateral: 100.TestTokens(),
|
2023-06-27 13:28:00 +00:00
|
|
|
|
minRequiredNumberOfNodes: numberOfSlots,
|
2023-06-26 13:37:16 +00:00
|
|
|
|
proofProbability: 10,
|
|
|
|
|
duration: contractDuration);
|
|
|
|
|
|
|
|
|
|
Assert.That(!string.IsNullOrEmpty(purchaseId));
|
2023-06-28 08:41:04 +00:00
|
|
|
|
|
2023-06-28 09:48:05 +00:00
|
|
|
|
WaitForContractToStart(codexAccess, purchaseId);
|
|
|
|
|
});
|
2023-06-26 13:37:16 +00:00
|
|
|
|
}
|
|
|
|
|
|
2023-06-28 08:41:04 +00:00
|
|
|
|
[TestMoment(t: MinuteFive * 2)]
|
2023-06-26 13:37:16 +00:00
|
|
|
|
public void StoredDataIsAvailableAfterThreeDays()
|
|
|
|
|
{
|
2023-06-28 09:48:05 +00:00
|
|
|
|
NodeRunner.RunNode((codexAccess, marketplaceAccess) =>
|
2023-06-26 13:37:16 +00:00
|
|
|
|
{
|
2023-06-28 13:11:20 +00:00
|
|
|
|
var result = DownloadFile(codexAccess.Node, cid!);
|
2023-06-26 13:37:16 +00:00
|
|
|
|
|
|
|
|
|
file.AssertIsEqual(result);
|
2023-06-28 09:48:05 +00:00
|
|
|
|
});
|
2023-06-26 13:37:16 +00:00
|
|
|
|
}
|
|
|
|
|
|
2023-06-28 09:48:05 +00:00
|
|
|
|
private void WaitForContractToStart(CodexAccess codexAccess, string purchaseId)
|
2023-06-26 13:37:16 +00:00
|
|
|
|
{
|
2023-06-28 09:48:05 +00:00
|
|
|
|
var lastState = "";
|
|
|
|
|
var waitStart = DateTime.UtcNow;
|
2023-06-29 08:23:04 +00:00
|
|
|
|
var filesizeInMb = fileSize.SizeInBytes / (1024 * 1024);
|
2023-06-28 09:48:05 +00:00
|
|
|
|
var maxWaitTime = TimeSpan.FromSeconds(filesizeInMb * 10.0);
|
2023-06-27 13:28:00 +00:00
|
|
|
|
|
2023-06-29 08:23:04 +00:00
|
|
|
|
Log.Log($"{nameof(WaitForContractToStart)} for {Time.FormatDuration(maxWaitTime)}");
|
2023-06-28 09:48:05 +00:00
|
|
|
|
while (lastState != "started")
|
|
|
|
|
{
|
2023-06-29 08:23:04 +00:00
|
|
|
|
CancelToken.ThrowIfCancellationRequested();
|
|
|
|
|
|
2023-06-28 09:48:05 +00:00
|
|
|
|
var purchaseStatus = codexAccess.Node.GetPurchaseStatus(purchaseId);
|
2023-06-29 08:23:04 +00:00
|
|
|
|
var statusJson = JsonConvert.SerializeObject(purchaseStatus);
|
2023-06-28 09:48:05 +00:00
|
|
|
|
if (purchaseStatus != null && purchaseStatus.state != lastState)
|
|
|
|
|
{
|
|
|
|
|
lastState = purchaseStatus.state;
|
2023-06-29 08:23:04 +00:00
|
|
|
|
Log.Log("Purchase status: " + statusJson);
|
2023-06-28 09:48:05 +00:00
|
|
|
|
}
|
2023-06-28 08:41:04 +00:00
|
|
|
|
|
2023-06-28 09:48:05 +00:00
|
|
|
|
Thread.Sleep(2000);
|
|
|
|
|
|
|
|
|
|
if (lastState == "errored")
|
|
|
|
|
{
|
2023-06-29 08:23:04 +00:00
|
|
|
|
Assert.Fail("Contract start failed: " + statusJson);
|
2023-06-28 09:48:05 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (DateTime.UtcNow - waitStart > maxWaitTime)
|
|
|
|
|
{
|
2023-06-29 08:23:04 +00:00
|
|
|
|
Assert.Fail($"Contract was not picked up within {maxWaitTime.TotalSeconds} seconds timeout: {statusJson}");
|
2023-06-28 09:48:05 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
2023-06-28 13:11:20 +00:00
|
|
|
|
Log.Log("Contract started.");
|
2023-06-28 08:41:04 +00:00
|
|
|
|
}
|
2023-06-26 13:37:16 +00:00
|
|
|
|
}
|
2023-06-23 09:38:30 +00:00
|
|
|
|
}
|