mirror of
https://github.com/logos-storage/logos-storage-nim.git
synced 2026-01-02 13:33:10 +00:00
* Add availability enabled parameter * Return bytes to availability when finished * Add until parameter * Remove debug message * Clean up and fix tests * Update documentations and cleanup * Avoid swallowing CancelledError * Move until validation to reservations module * Call onAvailabilityAdded callabck when the availability is enabled in sales * Remove until validation in restapi when creating an availability * Add openapi documentation * Use results instead of stew/results (#1112) * feat: request duration limit (#1057) * feat: request duration limit * Fix tests and duration type * Add custom error * Remove merge issue * Update codex contracts eth * Update market config and fix test * Fix SlotReservationsConfig syntax * Update dependencies * test: remove doubled test * chore: update contracts repo --------- Co-authored-by: Arnaud <arnaud@status.im> * fix(statemachine): do not raise from state.run (#1115) * fix(statemachine): do not raise from state.run * fix rebase * fix exception handling in SaleProvingSimulated.prove - re-raise CancelledError - don't return State on CatchableError - expect the Proofs_InvalidProof custom error instead of checking a string * asyncSpawn salesagent.onCancelled This was swallowing a KeyError in one of the tests (fixed in the previous commit) * remove error handling states in asyncstatemachine * revert unneeded changes * formatting * PR feedback, logging updates * chore(integration): simplify block expiration integration test (#1100) * chore(integration): simplify block expiration integration test * clean up * fix after rebase * perf: contract storage optimizations (#1094) * perf: contract storage optimizations * Apply optimization changes * Apply optimizing parameters sizing * Update codex-contracts-eth * bump latest changes in contracts branch * Change requestDurationLimit to uint64 * fix tests * fix tests --------- Co-authored-by: Arnaud <arnaud@status.im> Co-authored-by: Eric <5089238+emizzle@users.noreply.github.com> * bump contracts to master (#1122) * Add availability enabled parameter * Return bytes to availability when finished * Add until parameter * Clean up and fix tests * Move until validation to reservations module * Apply suggestion changes: return the reservation module error * Apply suggestion changes for until dates * Apply suggestion changes: reorganize tests * Fix indent * Remove test related to timing issue * Add raises errors to async pragram and remove useless try except * Update open api documentation * Fix wording * Remove the httpClient restart statements * Use market.getRequestEnd to set validUntil * Remove returnBytes * Use clock.now in testing * Move the api validation file to the right file --------- Co-authored-by: Adam Uhlíř <adam@uhlir.dev> Co-authored-by: Eric <5089238+emizzle@users.noreply.github.com>
223 lines
7.8 KiB
Nim
223 lines
7.8 KiB
Nim
import std/importutils
|
|
import std/net
|
|
import std/sequtils
|
|
import std/strformat
|
|
from pkg/libp2p import `==`, `$`, Cid
|
|
import pkg/codex/units
|
|
import pkg/codex/manifest
|
|
import ./twonodes
|
|
import ../examples
|
|
import ../codex/examples
|
|
import ../codex/slots/helpers
|
|
import json
|
|
|
|
twonodessuite "REST API":
|
|
test "nodes can print their peer information", twoNodesConfig:
|
|
check !(await client1.info()) != !(await client2.info())
|
|
|
|
test "nodes can set chronicles log level", twoNodesConfig:
|
|
await client1.setLogLevel("DEBUG;TRACE:codex")
|
|
|
|
test "node accepts file uploads", twoNodesConfig:
|
|
let cid1 = (await client1.upload("some file contents")).get
|
|
let cid2 = (await client1.upload("some other contents")).get
|
|
|
|
check cid1 != cid2
|
|
|
|
test "node shows used and available space", twoNodesConfig:
|
|
discard (await client1.upload("some file contents")).get
|
|
let totalSize = 12.uint64
|
|
let minPricePerBytePerSecond = 1.u256
|
|
let totalCollateral = totalSize.u256 * minPricePerBytePerSecond
|
|
discard (
|
|
await client1.postAvailability(
|
|
totalSize = totalSize,
|
|
duration = 2.uint64,
|
|
minPricePerBytePerSecond = minPricePerBytePerSecond,
|
|
totalCollateral = totalCollateral,
|
|
enabled = true.some,
|
|
)
|
|
).get
|
|
let space = (await client1.space()).tryGet()
|
|
check:
|
|
space.totalBlocks == 2
|
|
space.quotaMaxBytes == 21474836480.NBytes
|
|
space.quotaUsedBytes == 65592.NBytes
|
|
space.quotaReservedBytes == 12.NBytes
|
|
|
|
test "node lists local files", twoNodesConfig:
|
|
let content1 = "some file contents"
|
|
let content2 = "some other contents"
|
|
|
|
let cid1 = (await client1.upload(content1)).get
|
|
let cid2 = (await client1.upload(content2)).get
|
|
let list = (await client1.list()).get
|
|
|
|
check:
|
|
[cid1, cid2].allIt(it in list.content.mapIt(it.cid))
|
|
|
|
test "request storage succeeds for sufficiently sized datasets", twoNodesConfig:
|
|
let data = await RandomChunker.example(blocks = 2)
|
|
let cid = (await client1.upload(data)).get
|
|
let response = (
|
|
await client1.requestStorageRaw(
|
|
cid,
|
|
duration = 10.uint64,
|
|
pricePerBytePerSecond = 1.u256,
|
|
proofProbability = 3.u256,
|
|
collateralPerByte = 1.u256,
|
|
expiry = 9.uint64,
|
|
)
|
|
)
|
|
|
|
check:
|
|
response.status == 200
|
|
|
|
for ecParams in @[
|
|
(minBlocks: 2, nodes: 3, tolerance: 1), (minBlocks: 3, nodes: 5, tolerance: 2)
|
|
]:
|
|
let (minBlocks, nodes, tolerance) = ecParams
|
|
test "request storage succeeds if nodes and tolerance within range " &
|
|
fmt"({minBlocks=}, {nodes=}, {tolerance=})", twoNodesConfig:
|
|
let data = await RandomChunker.example(blocks = minBlocks)
|
|
let cid = (await client1.upload(data)).get
|
|
let duration = 100.uint64
|
|
let pricePerBytePerSecond = 1.u256
|
|
let proofProbability = 3.u256
|
|
let expiry = 30.uint64
|
|
let collateralPerByte = 1.u256
|
|
|
|
var responseBefore = (
|
|
await client1.requestStorageRaw(
|
|
cid, duration, pricePerBytePerSecond, proofProbability, collateralPerByte,
|
|
expiry, nodes.uint, tolerance.uint,
|
|
)
|
|
)
|
|
|
|
check responseBefore.status == 200
|
|
|
|
test "node accepts file uploads with content type", twoNodesConfig:
|
|
let headers = @[("Content-Type", "text/plain")]
|
|
let response = await client1.uploadRaw("some file contents", headers)
|
|
|
|
check response.status == 200
|
|
check (await response.body) != ""
|
|
|
|
test "node accepts file uploads with content disposition", twoNodesConfig:
|
|
let headers = @[("Content-Disposition", "attachment; filename=\"example.txt\"")]
|
|
let response = await client1.uploadRaw("some file contents", headers)
|
|
|
|
check response.status == 200
|
|
check (await response.body) != ""
|
|
|
|
test "node accepts file uploads with content disposition without filename",
|
|
twoNodesConfig:
|
|
let headers = @[("Content-Disposition", "attachment")]
|
|
let response = await client1.uploadRaw("some file contents", headers)
|
|
|
|
check response.status == 200
|
|
check (await response.body) != ""
|
|
|
|
test "node retrieve the metadata", twoNodesConfig:
|
|
let headers =
|
|
@[
|
|
("Content-Type", "text/plain"),
|
|
("Content-Disposition", "attachment; filename=\"example.txt\""),
|
|
]
|
|
let uploadResponse = await client1.uploadRaw("some file contents", headers)
|
|
let cid = await uploadResponse.body
|
|
let listResponse = await client1.listRaw()
|
|
|
|
let jsonData = parseJson(await listResponse.body)
|
|
|
|
check jsonData.hasKey("content") == true
|
|
|
|
let content = jsonData["content"][0]
|
|
|
|
check content.hasKey("manifest") == true
|
|
|
|
let manifest = content["manifest"]
|
|
|
|
check manifest.hasKey("filename") == true
|
|
check manifest["filename"].getStr() == "example.txt"
|
|
check manifest.hasKey("mimetype") == true
|
|
check manifest["mimetype"].getStr() == "text/plain"
|
|
|
|
test "node set the headers when for download", twoNodesConfig:
|
|
let headers =
|
|
@[
|
|
("Content-Disposition", "attachment; filename=\"example.txt\""),
|
|
("Content-Type", "text/plain"),
|
|
]
|
|
|
|
let uploadResponse = await client1.uploadRaw("some file contents", headers)
|
|
let cid = await uploadResponse.body
|
|
|
|
check uploadResponse.status == 200
|
|
|
|
let response = await client1.downloadRaw(cid)
|
|
|
|
check response.status == 200
|
|
check "Content-Type" in response.headers
|
|
check response.headers.getString("Content-Type") == "text/plain"
|
|
check "Content-Disposition" in response.headers
|
|
check response.headers.getString("Content-Disposition") ==
|
|
"attachment; filename=\"example.txt\""
|
|
|
|
let local = true
|
|
let localResponse = await client1.downloadRaw(cid, local)
|
|
|
|
check localResponse.status == 200
|
|
check "Content-Type" in localResponse.headers
|
|
check localResponse.headers.getString("Content-Type") == "text/plain"
|
|
check "Content-Disposition" in localResponse.headers
|
|
check localResponse.headers.getString("Content-Disposition") ==
|
|
"attachment; filename=\"example.txt\""
|
|
|
|
test "should delete a dataset when requested", twoNodesConfig:
|
|
let cid = (await client1.upload("some file contents")).get
|
|
|
|
var response = await client1.downloadRaw($cid, local = true)
|
|
check (await response.body) == "some file contents"
|
|
|
|
(await client1.delete(cid)).get
|
|
|
|
response = await client1.downloadRaw($cid, local = true)
|
|
check response.status == 404
|
|
|
|
test "should return 200 when attempting delete of non-existing block", twoNodesConfig:
|
|
let response = await client1.deleteRaw($(Cid.example()))
|
|
check response.status == 204
|
|
|
|
test "should return 200 when attempting delete of non-existing dataset",
|
|
twoNodesConfig:
|
|
let cid = Manifest.example().makeManifestBlock().get.cid
|
|
let response = await client1.deleteRaw($cid)
|
|
check response.status == 204
|
|
|
|
test "should not crash if the download stream is closed before download completes",
|
|
twoNodesConfig:
|
|
# FIXME this is not a good test. For some reason, to get this to fail, I have to
|
|
# store content that is several times the default stream buffer size, otherwise
|
|
# the test will succeed even when the bug is present. Since this is probably some
|
|
# setting that is internal to chronos, it might change in future versions,
|
|
# invalidating this test. Works on Chronos 4.0.3.
|
|
|
|
let
|
|
contents = repeat("b", DefaultStreamBufferSize * 10)
|
|
cid = (await client1.upload(contents)).get
|
|
response = await client1.downloadRaw($cid)
|
|
|
|
let reader = response.getBodyReader()
|
|
|
|
# Read 4 bytes from the stream just to make sure we actually
|
|
# receive some data.
|
|
check (bytesToString await reader.read(4)) == "bbbb"
|
|
|
|
# Abruptly closes the stream (we have to dig all the way to the transport
|
|
# or Chronos will close things "nicely").
|
|
response.connection.reader.tsource.close()
|
|
|
|
let response2 = await client1.downloadRaw($cid)
|
|
check (await response2.body) == contents
|