mirror of
https://github.com/logos-storage/logos-storage-nim.git
synced 2026-01-05 23:13:09 +00:00
chore(marketplace) - fix the http error codes when validating the availability requests (#1104)
* Use 422 http code when there is a validation error * Update the open api description * Fix typo * Add more tests for total size * Catch CancelledError because TrackedFuture raise no error * Split rest api validation test to a new file * Change the way of testing negative numbers * Rename client variable and fix test status code * Try to reduce the number of requests in CI when asserting in tests * Fix rebase and remove safeEventually
This commit is contained in:
parent
709a8648fd
commit
a0d6fbaf02
@ -475,7 +475,7 @@ proc initSalesApi(node: CodexNodeRef, router: var RestRouter) =
|
||||
|
||||
if restAv.totalSize == 0:
|
||||
return RestApiResponse.error(
|
||||
Http400, "Total size must be larger then zero", headers = headers
|
||||
Http422, "Total size must be larger then zero", headers = headers
|
||||
)
|
||||
|
||||
if not reservations.hasAvailable(restAv.totalSize):
|
||||
@ -548,17 +548,23 @@ proc initSalesApi(node: CodexNodeRef, router: var RestRouter) =
|
||||
return RestApiResponse.error(Http500, error.msg)
|
||||
|
||||
if isSome restAv.freeSize:
|
||||
return RestApiResponse.error(Http400, "Updating freeSize is not allowed")
|
||||
return RestApiResponse.error(Http422, "Updating freeSize is not allowed")
|
||||
|
||||
if size =? restAv.totalSize:
|
||||
if size == 0:
|
||||
return RestApiResponse.error(Http422, "Total size must be larger then zero")
|
||||
|
||||
# we don't allow lowering the totalSize bellow currently utilized size
|
||||
if size < (availability.totalSize - availability.freeSize):
|
||||
return RestApiResponse.error(
|
||||
Http400,
|
||||
Http422,
|
||||
"New totalSize must be larger then current totalSize - freeSize, which is currently: " &
|
||||
$(availability.totalSize - availability.freeSize),
|
||||
)
|
||||
|
||||
if not reservations.hasAvailable(size):
|
||||
return RestApiResponse.error(Http422, "Not enough storage quota")
|
||||
|
||||
availability.freeSize += size - availability.totalSize
|
||||
availability.totalSize = size
|
||||
|
||||
|
||||
@ -374,13 +374,13 @@ proc onSlotFreed(sales: Sales, requestId: RequestId, slotIndex: uint64) =
|
||||
|
||||
if err =? queue.push(slotQueueItem).errorOption:
|
||||
if err of SlotQueueItemExistsError:
|
||||
error "Failed to push item to queue becaue it already exists",
|
||||
error "Failed to push item to queue because it already exists",
|
||||
error = err.msgDetail
|
||||
elif err of QueueNotRunningError:
|
||||
warn "Failed to push item to queue becaue queue is not running",
|
||||
warn "Failed to push item to queue because queue is not running",
|
||||
error = err.msgDetail
|
||||
except CatchableError as e:
|
||||
warn "Failed to add slot to queue", error = e.msg
|
||||
except CancelledError as e:
|
||||
trace "sales.addSlotToQueue was cancelled"
|
||||
|
||||
# We could get rid of this by adding the storage ask in the SlotFreed event,
|
||||
# so we would not need to call getRequest to get the collateralPerSlot.
|
||||
|
||||
@ -704,7 +704,7 @@ paths:
|
||||
"400":
|
||||
description: Invalid data input
|
||||
"422":
|
||||
description: Not enough node's storage quota available
|
||||
description: The provided parameters did not pass validation
|
||||
"500":
|
||||
description: Error reserving availability
|
||||
"503":
|
||||
@ -737,7 +737,7 @@ paths:
|
||||
"404":
|
||||
description: Availability not found
|
||||
"422":
|
||||
description: Not enough node's storage quota available
|
||||
description: The provided parameters did not pass validation
|
||||
"500":
|
||||
description: Error reserving availability
|
||||
"503":
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
import helpers/multisetup
|
||||
import helpers/trackers
|
||||
import helpers/templeveldb
|
||||
|
||||
import std/times
|
||||
import std/sequtils, chronos
|
||||
|
||||
export multisetup, trackers, templeveldb
|
||||
|
||||
@ -45,7 +45,7 @@ proc request(
|
||||
).get
|
||||
.send()
|
||||
|
||||
proc post(
|
||||
proc post*(
|
||||
self: CodexClient,
|
||||
url: string,
|
||||
body: string = "",
|
||||
@ -69,7 +69,7 @@ proc delete(
|
||||
.} =
|
||||
return self.request(MethodDelete, url, headers = headers)
|
||||
|
||||
proc patch(
|
||||
proc patch*(
|
||||
self: CodexClient,
|
||||
url: string,
|
||||
body: string = "",
|
||||
@ -290,11 +290,11 @@ proc getSalesAgent*(
|
||||
except CatchableError as e:
|
||||
return failure e.msg
|
||||
|
||||
proc postAvailability*(
|
||||
proc postAvailabilityRaw*(
|
||||
client: CodexClient,
|
||||
totalSize, duration: uint64,
|
||||
minPricePerBytePerSecond, totalCollateral: UInt256,
|
||||
): Future[?!Availability] {.async: (raises: [CancelledError, HttpError]).} =
|
||||
): Future[HttpClientResponseRef] {.async: (raises: [CancelledError, HttpError]).} =
|
||||
## Post sales availability endpoint
|
||||
##
|
||||
let url = client.baseurl & "/sales/availability"
|
||||
@ -305,7 +305,17 @@ proc postAvailability*(
|
||||
"minPricePerBytePerSecond": minPricePerBytePerSecond,
|
||||
"totalCollateral": totalCollateral,
|
||||
}
|
||||
let response = await client.post(url, $json)
|
||||
|
||||
return await client.post(url, $json)
|
||||
|
||||
proc postAvailability*(
|
||||
client: CodexClient,
|
||||
totalSize, duration: uint64,
|
||||
minPricePerBytePerSecond, totalCollateral: UInt256,
|
||||
): Future[?!Availability] {.async: (raises: [CancelledError, HttpError]).} =
|
||||
let response = await client.postAvailabilityRaw(
|
||||
totalSize, duration, minPricePerBytePerSecond, totalCollateral
|
||||
)
|
||||
let body = await response.body
|
||||
|
||||
doAssert response.status == 201,
|
||||
@ -389,3 +399,6 @@ proc requestId*(
|
||||
client: CodexClient, id: PurchaseId
|
||||
): Future[?RequestId] {.async: (raises: [CancelledError, HttpError]).} =
|
||||
return (await client.getPurchase(id)).option .? requestId
|
||||
|
||||
proc buildUrl*(client: CodexClient, path: string): string =
|
||||
return client.baseurl & path
|
||||
|
||||
@ -37,10 +37,12 @@ type
|
||||
|
||||
MultiNodeSuiteError = object of CatchableError
|
||||
|
||||
const jsonRpcProviderUrl* = "http://127.0.0.1:8545"
|
||||
|
||||
proc raiseMultiNodeSuiteError(msg: string) =
|
||||
raise newException(MultiNodeSuiteError, msg)
|
||||
|
||||
proc nextFreePort(startPort: int): Future[int] {.async.} =
|
||||
proc nextFreePort*(startPort: int): Future[int] {.async.} =
|
||||
proc client(server: StreamServer, transp: StreamTransport) {.async.} =
|
||||
await transp.closeWait()
|
||||
|
||||
@ -60,6 +62,15 @@ proc nextFreePort(startPort: int): Future[int] {.async.} =
|
||||
trace "port is not free", port
|
||||
inc port
|
||||
|
||||
proc sanitize(pathSegment: string): string =
|
||||
var sanitized = pathSegment
|
||||
for invalid in invalidFilenameChars.items:
|
||||
sanitized = sanitized.replace(invalid, '_').replace(' ', '_')
|
||||
sanitized
|
||||
|
||||
proc getTempDirName*(starttime: string, role: Role, roleIdx: int): string =
|
||||
getTempDir() / "Codex" / sanitize($starttime) / sanitize($role & "_" & $roleIdx)
|
||||
|
||||
template multinodesuite*(name: string, body: untyped) =
|
||||
asyncchecksuite name:
|
||||
# Following the problem described here:
|
||||
@ -82,7 +93,6 @@ template multinodesuite*(name: string, body: untyped) =
|
||||
# .withEthProvider("ws://localhost:8545")
|
||||
# .some,
|
||||
# ...
|
||||
let jsonRpcProviderUrl = "http://127.0.0.1:8545"
|
||||
var running {.inject, used.}: seq[RunningNode]
|
||||
var bootstrapNodes: seq[string]
|
||||
let starttime = now().format("yyyy-MM-dd'_'HH:mm:ss")
|
||||
@ -148,8 +158,7 @@ template multinodesuite*(name: string, body: untyped) =
|
||||
raiseMultiNodeSuiteError "Cannot start node at nodeIdx " & $nodeIdx &
|
||||
", not enough eth accounts."
|
||||
|
||||
let datadir =
|
||||
getTempDir() / "Codex" / sanitize($starttime) / sanitize($role & "_" & $roleIdx)
|
||||
let datadir = getTempDirName(starttime, role, roleIdx)
|
||||
|
||||
try:
|
||||
if config.logFile.isSome:
|
||||
|
||||
@ -55,25 +55,6 @@ twonodessuite "REST API":
|
||||
check:
|
||||
[cid1, cid2].allIt(it in list.content.mapIt(it.cid))
|
||||
|
||||
test "request storage fails for datasets that are too small", twoNodesConfig:
|
||||
let cid = (await client1.upload("some file contents")).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 == 422
|
||||
(await response.body) ==
|
||||
"Dataset too small for erasure parameters, need at least " &
|
||||
$(2 * DefaultBlockSize.int) & " bytes"
|
||||
|
||||
test "request storage succeeds for sufficiently sized datasets", twoNodesConfig:
|
||||
let data = await RandomChunker.example(blocks = 2)
|
||||
let cid = (await client1.upload(data)).get
|
||||
@ -91,176 +72,6 @@ twonodessuite "REST API":
|
||||
check:
|
||||
response.status == 200
|
||||
|
||||
test "request storage fails if tolerance is zero", twoNodesConfig:
|
||||
let data = await RandomChunker.example(blocks = 2)
|
||||
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
|
||||
let nodes = 3
|
||||
let tolerance = 0
|
||||
|
||||
var responseBefore = (
|
||||
await client1.requestStorageRaw(
|
||||
cid, duration, pricePerBytePerSecond, proofProbability, collateralPerByte,
|
||||
expiry, nodes.uint, tolerance.uint,
|
||||
)
|
||||
)
|
||||
|
||||
check responseBefore.status == 422
|
||||
check (await responseBefore.body) == "Tolerance needs to be bigger then zero"
|
||||
|
||||
test "request storage fails if duration exceeds limit", twoNodesConfig:
|
||||
let data = await RandomChunker.example(blocks = 2)
|
||||
let cid = (await client1.upload(data)).get
|
||||
let duration = (31 * 24 * 60 * 60).uint64
|
||||
# 31 days TODO: this should not be hardcoded, but waits for https://github.com/codex-storage/nim-codex/issues/1056
|
||||
let proofProbability = 3.u256
|
||||
let expiry = 30.uint
|
||||
let collateralPerByte = 1.u256
|
||||
let nodes = 3
|
||||
let tolerance = 2
|
||||
let pricePerBytePerSecond = 1.u256
|
||||
|
||||
var responseBefore = (
|
||||
await client1.requestStorageRaw(
|
||||
cid, duration, pricePerBytePerSecond, proofProbability, collateralPerByte,
|
||||
expiry, nodes.uint, tolerance.uint,
|
||||
)
|
||||
)
|
||||
|
||||
check responseBefore.status == 422
|
||||
check "Duration exceeds limit of" in (await responseBefore.body)
|
||||
|
||||
test "request storage fails if nodes and tolerance aren't correct", twoNodesConfig:
|
||||
let data = await RandomChunker.example(blocks = 2)
|
||||
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
|
||||
let ecParams = @[(1, 1), (2, 1), (3, 2), (3, 3)]
|
||||
|
||||
for ecParam in ecParams:
|
||||
let (nodes, tolerance) = ecParam
|
||||
|
||||
var responseBefore = (
|
||||
await client1.requestStorageRaw(
|
||||
cid, duration, pricePerBytePerSecond, proofProbability, collateralPerByte,
|
||||
expiry, nodes.uint, tolerance.uint,
|
||||
)
|
||||
)
|
||||
|
||||
check responseBefore.status == 422
|
||||
check (await responseBefore.body) ==
|
||||
"Invalid parameters: parameters must satify `1 < (nodes - tolerance) ≥ tolerance`"
|
||||
|
||||
test "request storage fails if tolerance > nodes (underflow protection)",
|
||||
twoNodesConfig:
|
||||
let data = await RandomChunker.example(blocks = 2)
|
||||
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
|
||||
let ecParams = @[(0, 1), (1, 2), (2, 3)]
|
||||
|
||||
for ecParam in ecParams:
|
||||
let (nodes, tolerance) = ecParam
|
||||
|
||||
var responseBefore = (
|
||||
await client1.requestStorageRaw(
|
||||
cid, duration, pricePerBytePerSecond, proofProbability, collateralPerByte,
|
||||
expiry, nodes.uint, tolerance.uint,
|
||||
)
|
||||
)
|
||||
|
||||
check responseBefore.status == 422
|
||||
check (await responseBefore.body) ==
|
||||
"Invalid parameters: `tolerance` cannot be greater than `nodes`"
|
||||
|
||||
test "request storage fails if expiry is zero", twoNodesConfig:
|
||||
let data = await RandomChunker.example(blocks = 2)
|
||||
let cid = (await client1.upload(data)).get
|
||||
let duration = 100.uint64
|
||||
let pricePerBytePerSecond = 1.u256
|
||||
let proofProbability = 3.u256
|
||||
let expiry = 0.uint64
|
||||
let collateralPerByte = 1.u256
|
||||
let nodes = 3
|
||||
let tolerance = 1
|
||||
|
||||
var responseBefore = await client1.requestStorageRaw(
|
||||
cid, duration, pricePerBytePerSecond, proofProbability, collateralPerByte, expiry,
|
||||
nodes.uint, tolerance.uint,
|
||||
)
|
||||
|
||||
check responseBefore.status == 422
|
||||
check (await responseBefore.body) ==
|
||||
"Expiry must be greater than zero and less than the request's duration"
|
||||
|
||||
test "request storage fails if proof probability is zero", twoNodesConfig:
|
||||
let data = await RandomChunker.example(blocks = 2)
|
||||
let cid = (await client1.upload(data)).get
|
||||
let duration = 100.uint64
|
||||
let pricePerBytePerSecond = 1.u256
|
||||
let proofProbability = 0.u256
|
||||
let expiry = 30.uint64
|
||||
let collateralPerByte = 1.u256
|
||||
let nodes = 3
|
||||
let tolerance = 1
|
||||
|
||||
var responseBefore = await client1.requestStorageRaw(
|
||||
cid, duration, pricePerBytePerSecond, proofProbability, collateralPerByte, expiry,
|
||||
nodes.uint, tolerance.uint,
|
||||
)
|
||||
|
||||
check responseBefore.status == 422
|
||||
check (await responseBefore.body) == "Proof probability must be greater than zero"
|
||||
|
||||
test "request storage fails if collareral per byte is zero", twoNodesConfig:
|
||||
let data = await RandomChunker.example(blocks = 2)
|
||||
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 = 0.u256
|
||||
let nodes = 3
|
||||
let tolerance = 1
|
||||
|
||||
var responseBefore = await client1.requestStorageRaw(
|
||||
cid, duration, pricePerBytePerSecond, proofProbability, collateralPerByte, expiry,
|
||||
nodes.uint, tolerance.uint,
|
||||
)
|
||||
|
||||
check responseBefore.status == 422
|
||||
check (await responseBefore.body) == "Collateral per byte must be greater than zero"
|
||||
|
||||
test "request storage fails if price per byte per second is zero", twoNodesConfig:
|
||||
let data = await RandomChunker.example(blocks = 2)
|
||||
let cid = (await client1.upload(data)).get
|
||||
let duration = 100.uint64
|
||||
let pricePerBytePerSecond = 0.u256
|
||||
let proofProbability = 3.u256
|
||||
let expiry = 30.uint64
|
||||
let collateralPerByte = 1.u256
|
||||
let nodes = 3
|
||||
let tolerance = 1
|
||||
|
||||
var responseBefore = await client1.requestStorageRaw(
|
||||
cid, duration, pricePerBytePerSecond, proofProbability, collateralPerByte, expiry,
|
||||
nodes.uint, tolerance.uint,
|
||||
)
|
||||
|
||||
check responseBefore.status == 422
|
||||
check (await responseBefore.body) ==
|
||||
"Price per byte per second must be greater than zero"
|
||||
|
||||
for ecParams in @[
|
||||
(minBlocks: 2, nodes: 3, tolerance: 1), (minBlocks: 3, nodes: 5, tolerance: 2)
|
||||
]:
|
||||
@ -306,20 +117,6 @@ twonodessuite "REST API":
|
||||
check response.status == 200
|
||||
check (await response.body) != ""
|
||||
|
||||
test "upload fails if content disposition contains bad filename", twoNodesConfig:
|
||||
let headers = @[("Content-Disposition", "attachment; filename=\"exam*ple.txt\"")]
|
||||
let response = await client1.uploadRaw("some file contents", headers)
|
||||
|
||||
check response.status == 422
|
||||
check (await response.body) == "The filename is not valid."
|
||||
|
||||
test "upload fails if content type is invalid", twoNodesConfig:
|
||||
let headers = @[("Content-Type", "hello/world")]
|
||||
let response = await client1.uploadRaw("some file contents", headers)
|
||||
|
||||
check response.status == 422
|
||||
check (await response.body) == "The MIME type 'hello/world' is not valid."
|
||||
|
||||
test "node retrieve the metadata", twoNodesConfig:
|
||||
let headers =
|
||||
@[
|
||||
|
||||
368
tests/integration/testrestapivalidation.nim
Normal file
368
tests/integration/testrestapivalidation.nim
Normal file
@ -0,0 +1,368 @@
|
||||
import std/httpclient
|
||||
import std/times
|
||||
import pkg/ethers
|
||||
import pkg/codex/manifest
|
||||
import pkg/codex/conf
|
||||
import pkg/codex/contracts
|
||||
from pkg/codex/stores/repostore/types import DefaultQuotaBytes
|
||||
import ../asynctest
|
||||
import ../checktest
|
||||
import ../examples
|
||||
import ../codex/examples
|
||||
import ./codexconfig
|
||||
import ./codexprocess
|
||||
|
||||
from ./multinodes import Role, getTempDirName, jsonRpcProviderUrl, nextFreePort
|
||||
|
||||
# This suite allows to run fast the basic rest api validation.
|
||||
# It starts only one node for all the checks in order to speed up
|
||||
# the execution.
|
||||
asyncchecksuite "Rest API validation":
|
||||
var node: CodexProcess
|
||||
var config = CodexConfigs.init(nodes = 1).configs[0]
|
||||
let starttime = now().format("yyyy-MM-dd'_'HH:mm:ss")
|
||||
let nodexIdx = 0
|
||||
let datadir = getTempDirName(starttime, Role.Client, nodexIdx)
|
||||
|
||||
config.addCliOption("--api-port", $(waitFor nextFreePort(8081)))
|
||||
config.addCliOption("--data-dir", datadir)
|
||||
config.addCliOption("--nat", "none")
|
||||
config.addCliOption("--listen-addrs", "/ip4/127.0.0.1/tcp/0")
|
||||
config.addCliOption("--disc-port", $(waitFor nextFreePort(8081)))
|
||||
config.addCliOption(StartUpCmd.persistence, "--eth-provider", jsonRpcProviderUrl)
|
||||
config.addCliOption(StartUpCmd.persistence, "--eth-account", $EthAddress.example)
|
||||
|
||||
node =
|
||||
waitFor CodexProcess.startNode(config.cliArgs, config.debugEnabled, $Role.Client)
|
||||
|
||||
waitFor node.waitUntilStarted()
|
||||
|
||||
let client = node.client()
|
||||
|
||||
test "should return 422 when attempting delete of non-existing dataset":
|
||||
let data = await RandomChunker.example(blocks = 2)
|
||||
let cid = (await client.upload(data)).get
|
||||
let duration = 100.uint64
|
||||
let pricePerBytePerSecond = 1.u256
|
||||
let proofProbability = 3.u256
|
||||
let expiry = 30.uint64
|
||||
let collateralPerByte = 1.u256
|
||||
let nodes = 3
|
||||
let tolerance = 0
|
||||
|
||||
var responseBefore = await client.requestStorageRaw(
|
||||
cid, duration, pricePerBytePerSecond, proofProbability, collateralPerByte, expiry,
|
||||
nodes.uint, tolerance.uint,
|
||||
)
|
||||
|
||||
check responseBefore.status == 422
|
||||
check (await responseBefore.body) == "Tolerance needs to be bigger then zero"
|
||||
|
||||
test "request storage fails for datasets that are too small":
|
||||
let cid = (await client.upload("some file contents")).get
|
||||
let response = (
|
||||
await client.requestStorageRaw(
|
||||
cid,
|
||||
duration = 10.uint64,
|
||||
pricePerBytePerSecond = 1.u256,
|
||||
proofProbability = 3.u256,
|
||||
collateralPerByte = 1.u256,
|
||||
expiry = 9.uint64,
|
||||
)
|
||||
)
|
||||
|
||||
check:
|
||||
response.status == 422
|
||||
(await response.body) ==
|
||||
"Dataset too small for erasure parameters, need at least " &
|
||||
$(2 * DefaultBlockSize.int) & " bytes"
|
||||
|
||||
test "request storage fails if nodes and tolerance aren't correct":
|
||||
let data = await RandomChunker.example(blocks = 2)
|
||||
let cid = (await client.upload(data)).get
|
||||
let duration = 100.uint64
|
||||
let pricePerBytePerSecond = 1.u256
|
||||
let proofProbability = 3.u256
|
||||
let expiry = 30.uint64
|
||||
let collateralPerByte = 1.u256
|
||||
let ecParams = @[(1, 1), (2, 1), (3, 2), (3, 3)]
|
||||
|
||||
for ecParam in ecParams:
|
||||
let (nodes, tolerance) = ecParam
|
||||
|
||||
var responseBefore = (
|
||||
await client.requestStorageRaw(
|
||||
cid, duration, pricePerBytePerSecond, proofProbability, collateralPerByte,
|
||||
expiry, nodes.uint, tolerance.uint,
|
||||
)
|
||||
)
|
||||
|
||||
check responseBefore.status == 422
|
||||
check (await responseBefore.body) ==
|
||||
"Invalid parameters: parameters must satify `1 < (nodes - tolerance) ≥ tolerance`"
|
||||
|
||||
test "request storage fails if tolerance > nodes (underflow protection)":
|
||||
let data = await RandomChunker.example(blocks = 2)
|
||||
let cid = (await client.upload(data)).get
|
||||
let duration = 100.uint64
|
||||
let pricePerBytePerSecond = 1.u256
|
||||
let proofProbability = 3.u256
|
||||
let expiry = 30.uint64
|
||||
let collateralPerByte = 1.u256
|
||||
let nodes = 3
|
||||
let tolerance = 0
|
||||
|
||||
var responseBefore = (
|
||||
await client.requestStorageRaw(
|
||||
cid, duration, pricePerBytePerSecond, proofProbability, collateralPerByte,
|
||||
expiry, nodes.uint, tolerance.uint,
|
||||
)
|
||||
)
|
||||
|
||||
check responseBefore.status == 422
|
||||
check (await responseBefore.body) == "Tolerance needs to be bigger then zero"
|
||||
|
||||
test "upload fails if content disposition contains bad filename":
|
||||
let headers = @[("Content-Disposition", "attachment; filename=\"exam*ple.txt\"")]
|
||||
let response = await client.uploadRaw("some file contents", headers)
|
||||
|
||||
check response.status == 422
|
||||
check (await response.body) == "The filename is not valid."
|
||||
|
||||
test "upload fails if content type is invalid":
|
||||
let headers = @[("Content-Type", "hello/world")]
|
||||
let response = await client.uploadRaw("some file contents", headers)
|
||||
|
||||
check response.status == 422
|
||||
check (await response.body) == "The MIME type 'hello/world' is not valid."
|
||||
|
||||
test "updating non-existing availability":
|
||||
let nonExistingResponse = await client.patchAvailabilityRaw(
|
||||
AvailabilityId.example,
|
||||
duration = 100.uint64.some,
|
||||
minPricePerBytePerSecond = 2.u256.some,
|
||||
totalCollateral = 200.u256.some,
|
||||
)
|
||||
check nonExistingResponse.status == 404
|
||||
|
||||
test "updating availability - freeSize is not allowed to be changed":
|
||||
let availability = (
|
||||
await client.postAvailability(
|
||||
totalSize = 140000.uint64,
|
||||
duration = 200.uint64,
|
||||
minPricePerBytePerSecond = 3.u256,
|
||||
totalCollateral = 300.u256,
|
||||
)
|
||||
).get
|
||||
let freeSizeResponse =
|
||||
await client.patchAvailabilityRaw(availability.id, freeSize = 110000.uint64.some)
|
||||
check freeSizeResponse.status == 422
|
||||
check "not allowed" in (await freeSizeResponse.body)
|
||||
|
||||
test "creating availability above the node quota returns 422":
|
||||
let response = await client.postAvailabilityRaw(
|
||||
totalSize = 24000000000.uint64,
|
||||
duration = 200.uint64,
|
||||
minPricePerBytePerSecond = 3.u256,
|
||||
totalCollateral = 300.u256,
|
||||
)
|
||||
|
||||
check response.status == 422
|
||||
check (await response.body) == "Not enough storage quota"
|
||||
|
||||
test "updating availability above the node quota returns 422":
|
||||
let availability = (
|
||||
await client.postAvailability(
|
||||
totalSize = 140000.uint64,
|
||||
duration = 200.uint64,
|
||||
minPricePerBytePerSecond = 3.u256,
|
||||
totalCollateral = 300.u256,
|
||||
)
|
||||
).get
|
||||
let response = await client.patchAvailabilityRaw(
|
||||
availability.id, totalSize = 24000000000.uint64.some
|
||||
)
|
||||
|
||||
check response.status == 422
|
||||
check (await response.body) == "Not enough storage quota"
|
||||
|
||||
test "creating availability when total size is zero returns 422":
|
||||
let response = await client.postAvailabilityRaw(
|
||||
totalSize = 0.uint64,
|
||||
duration = 200.uint64,
|
||||
minPricePerBytePerSecond = 3.u256,
|
||||
totalCollateral = 300.u256,
|
||||
)
|
||||
|
||||
check response.status == 422
|
||||
check (await response.body) == "Total size must be larger then zero"
|
||||
|
||||
test "updating availability when total size is zero returns 422":
|
||||
let availability = (
|
||||
await client.postAvailability(
|
||||
totalSize = 140000.uint64,
|
||||
duration = 200.uint64,
|
||||
minPricePerBytePerSecond = 3.u256,
|
||||
totalCollateral = 300.u256,
|
||||
)
|
||||
).get
|
||||
let response =
|
||||
await client.patchAvailabilityRaw(availability.id, totalSize = 0.uint64.some)
|
||||
|
||||
check response.status == 422
|
||||
check (await response.body) == "Total size must be larger then zero"
|
||||
|
||||
test "creating availability when total size is negative returns 422":
|
||||
let json =
|
||||
%*{
|
||||
"totalSize": "-1",
|
||||
"duration": "200",
|
||||
"minPricePerBytePerSecond": "3",
|
||||
"totalCollateral": "300",
|
||||
}
|
||||
let response = await client.post(client.buildUrl("/sales/availability"), $json)
|
||||
|
||||
check response.status == 400
|
||||
check (await response.body) == "Parsed integer outside of valid range"
|
||||
|
||||
test "updating availability when total size is negative returns 422":
|
||||
let availability = (
|
||||
await client.postAvailability(
|
||||
totalSize = 140000.uint64,
|
||||
duration = 200.uint64,
|
||||
minPricePerBytePerSecond = 3.u256,
|
||||
totalCollateral = 300.u256,
|
||||
)
|
||||
).get
|
||||
|
||||
let json = %*{"totalSize": "-1"}
|
||||
let response = await client.patch(
|
||||
client.buildUrl("/sales/availability/") & $availability.id, $json
|
||||
)
|
||||
|
||||
check response.status == 400
|
||||
check (await response.body) == "Parsed integer outside of valid range"
|
||||
|
||||
test "request storage fails if tolerance is zero":
|
||||
let data = await RandomChunker.example(blocks = 2)
|
||||
let cid = (await client.upload(data)).get
|
||||
let duration = 100.uint64
|
||||
let pricePerBytePerSecond = 1.u256
|
||||
let proofProbability = 3.u256
|
||||
let expiry = 30.uint64
|
||||
let collateralPerByte = 1.u256
|
||||
let nodes = 3
|
||||
let tolerance = 0
|
||||
|
||||
var responseBefore = (
|
||||
await client.requestStorageRaw(
|
||||
cid, duration, pricePerBytePerSecond, proofProbability, collateralPerByte,
|
||||
expiry, nodes.uint, tolerance.uint,
|
||||
)
|
||||
)
|
||||
|
||||
check responseBefore.status == 422
|
||||
check (await responseBefore.body) == "Tolerance needs to be bigger then zero"
|
||||
|
||||
test "request storage fails if duration exceeds limit":
|
||||
let data = await RandomChunker.example(blocks = 2)
|
||||
let cid = (await client.upload(data)).get
|
||||
let duration = (31 * 24 * 60 * 60).uint64
|
||||
# 31 days TODO: this should not be hardcoded, but waits for https://github.com/codex-storage/nim-codex/issues/1056
|
||||
let proofProbability = 3.u256
|
||||
let expiry = 30.uint
|
||||
let collateralPerByte = 1.u256
|
||||
let nodes = 3
|
||||
let tolerance = 2
|
||||
let pricePerBytePerSecond = 1.u256
|
||||
|
||||
var responseBefore = (
|
||||
await client.requestStorageRaw(
|
||||
cid, duration, pricePerBytePerSecond, proofProbability, collateralPerByte,
|
||||
expiry, nodes.uint, tolerance.uint,
|
||||
)
|
||||
)
|
||||
|
||||
check responseBefore.status == 422
|
||||
check "Duration exceeds limit of" in (await responseBefore.body)
|
||||
|
||||
test "request storage fails if expiry is zero":
|
||||
let data = await RandomChunker.example(blocks = 2)
|
||||
let cid = (await client.upload(data)).get
|
||||
let duration = 100.uint64
|
||||
let pricePerBytePerSecond = 1.u256
|
||||
let proofProbability = 3.u256
|
||||
let expiry = 0.uint64
|
||||
let collateralPerByte = 1.u256
|
||||
let nodes = 3
|
||||
let tolerance = 1
|
||||
|
||||
var responseBefore = await client.requestStorageRaw(
|
||||
cid, duration, pricePerBytePerSecond, proofProbability, collateralPerByte, expiry,
|
||||
nodes.uint, tolerance.uint,
|
||||
)
|
||||
|
||||
check responseBefore.status == 422
|
||||
check (await responseBefore.body) ==
|
||||
"Expiry must be greater than zero and less than the request's duration"
|
||||
|
||||
test "request storage fails if proof probability is zero":
|
||||
let data = await RandomChunker.example(blocks = 2)
|
||||
let cid = (await client.upload(data)).get
|
||||
let duration = 100.uint64
|
||||
let pricePerBytePerSecond = 1.u256
|
||||
let proofProbability = 0.u256
|
||||
let expiry = 30.uint64
|
||||
let collateralPerByte = 1.u256
|
||||
let nodes = 3
|
||||
let tolerance = 1
|
||||
|
||||
var responseBefore = await client.requestStorageRaw(
|
||||
cid, duration, pricePerBytePerSecond, proofProbability, collateralPerByte, expiry,
|
||||
nodes.uint, tolerance.uint,
|
||||
)
|
||||
|
||||
check responseBefore.status == 422
|
||||
check (await responseBefore.body) == "Proof probability must be greater than zero"
|
||||
|
||||
test "request storage fails if price per byte per second is zero":
|
||||
let data = await RandomChunker.example(blocks = 2)
|
||||
let cid = (await client.upload(data)).get
|
||||
let duration = 100.uint64
|
||||
let pricePerBytePerSecond = 0.u256
|
||||
let proofProbability = 3.u256
|
||||
let expiry = 30.uint64
|
||||
let collateralPerByte = 1.u256
|
||||
let nodes = 3
|
||||
let tolerance = 1
|
||||
|
||||
var responseBefore = await client.requestStorageRaw(
|
||||
cid, duration, pricePerBytePerSecond, proofProbability, collateralPerByte, expiry,
|
||||
nodes.uint, tolerance.uint,
|
||||
)
|
||||
|
||||
check responseBefore.status == 422
|
||||
check (await responseBefore.body) ==
|
||||
"Price per byte per second must be greater than zero"
|
||||
|
||||
test "request storage fails if collareral per byte is zero":
|
||||
let data = await RandomChunker.example(blocks = 2)
|
||||
let cid = (await client.upload(data)).get
|
||||
let duration = 100.uint64
|
||||
let pricePerBytePerSecond = 1.u256
|
||||
let proofProbability = 3.u256
|
||||
let expiry = 30.uint64
|
||||
let collateralPerByte = 0.u256
|
||||
let nodes = 3
|
||||
let tolerance = 1
|
||||
|
||||
var responseBefore = await client.requestStorageRaw(
|
||||
cid, duration, pricePerBytePerSecond, proofProbability, collateralPerByte, expiry,
|
||||
nodes.uint, tolerance.uint,
|
||||
)
|
||||
|
||||
check responseBefore.status == 422
|
||||
check (await responseBefore.body) == "Collateral per byte must be greater than zero"
|
||||
|
||||
waitFor node.stop()
|
||||
node.removeDataDir()
|
||||
@ -1,5 +1,6 @@
|
||||
import std/httpclient
|
||||
import pkg/codex/contracts
|
||||
from pkg/codex/stores/repostore/types import DefaultQuotaBytes
|
||||
import ./twonodes
|
||||
import ../codex/examples
|
||||
import ../contracts/time
|
||||
@ -69,15 +70,6 @@ multinodesuite "Sales":
|
||||
).get
|
||||
check availability in (await host.getAvailabilities()).get
|
||||
|
||||
test "updating non-existing availability", salesConfig:
|
||||
let nonExistingResponse = await host.patchAvailabilityRaw(
|
||||
AvailabilityId.example,
|
||||
duration = 100.uint64.some,
|
||||
minPricePerBytePerSecond = 2.u256.some,
|
||||
totalCollateral = 200.u256.some,
|
||||
)
|
||||
check nonExistingResponse.status == 404
|
||||
|
||||
test "updating availability", salesConfig:
|
||||
let availability = (
|
||||
await host.postAvailability(
|
||||
@ -103,20 +95,6 @@ multinodesuite "Sales":
|
||||
check updatedAvailability.totalSize == 140000.uint64
|
||||
check updatedAvailability.freeSize == 140000.uint64
|
||||
|
||||
test "updating availability - freeSize is not allowed to be changed", salesConfig:
|
||||
let availability = (
|
||||
await host.postAvailability(
|
||||
totalSize = 140000.uint64,
|
||||
duration = 200.uint64,
|
||||
minPricePerBytePerSecond = 3.u256,
|
||||
totalCollateral = 300.u256,
|
||||
)
|
||||
).get
|
||||
let freeSizeResponse =
|
||||
await host.patchAvailabilityRaw(availability.id, freeSize = 110000.uint64.some)
|
||||
check freeSizeResponse.status == 400
|
||||
check "not allowed" in (await freeSizeResponse.body)
|
||||
|
||||
test "updating availability - updating totalSize", salesConfig:
|
||||
let availability = (
|
||||
await host.postAvailability(
|
||||
@ -176,7 +154,7 @@ multinodesuite "Sales":
|
||||
availability.id, totalSize = (utilizedSize - 1).some
|
||||
)
|
||||
)
|
||||
check totalSizeResponse.status == 400
|
||||
check totalSizeResponse.status == 422
|
||||
check "totalSize must be larger then current totalSize" in
|
||||
(await totalSizeResponse.body)
|
||||
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
import ./integration/testcli
|
||||
import ./integration/testrestapi
|
||||
import ./integration/testrestapivalidation
|
||||
import ./integration/testupdownload
|
||||
import ./integration/testsales
|
||||
import ./integration/testpurchasing
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user