Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(integration): add ability to search logs in integration test nodes + slot reservations test #976

Open
wants to merge 16 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 5 additions & 5 deletions codex/contracts/market.nim
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ proc approveFunds(market: OnChainMarket, amount: UInt256) {.async.} =
discard await token.increaseAllowance(market.contract.address(), amount).confirm(0)

method getZkeyHash*(market: OnChainMarket): Future[?string] {.async.} =
let config = await market.contract.config()
let config = await market.contract.configuration()
return some config.proofs.zkeyHash

method getSigner*(market: OnChainMarket): Future[Address] {.async.} =
Expand All @@ -65,18 +65,18 @@ method getSigner*(market: OnChainMarket): Future[Address] {.async.} =

method periodicity*(market: OnChainMarket): Future[Periodicity] {.async.} =
convertEthersError:
let config = await market.contract.config()
let config = await market.contract.configuration()
let period = config.proofs.period
return Periodicity(seconds: period)

method proofTimeout*(market: OnChainMarket): Future[UInt256] {.async.} =
convertEthersError:
let config = await market.contract.config()
let config = await market.contract.configuration()
return config.proofs.timeout

method proofDowntime*(market: OnChainMarket): Future[uint8] {.async.} =
convertEthersError:
let config = await market.contract.config()
let config = await market.contract.configuration()
return config.proofs.downtime

method getPointer*(market: OnChainMarket, slotId: SlotId): Future[uint8] {.async.} =
Expand Down Expand Up @@ -176,7 +176,7 @@ method fillSlot(market: OnChainMarket,

method freeSlot*(market: OnChainMarket, slotId: SlotId) {.async.} =
convertEthersError:
var freeSlot: Future[?TransactionResponse]
var freeSlot: Future[Confirmable]
if rewardRecipient =? market.rewardRecipient:
# If --reward-recipient specified, use it as the reward recipient, and use
# the SP's address as the collateral recipient
Expand Down
20 changes: 10 additions & 10 deletions codex/contracts/marketplace.nim
Original file line number Diff line number Diff line change
Expand Up @@ -17,18 +17,18 @@ export requests
type
Marketplace* = ref object of Contract

proc config*(marketplace: Marketplace): MarketplaceConfig {.contract, view.}
proc configuration*(marketplace: Marketplace): MarketplaceConfig {.contract, view.}
proc token*(marketplace: Marketplace): Address {.contract, view.}
proc slashMisses*(marketplace: Marketplace): UInt256 {.contract, view.}
proc slashPercentage*(marketplace: Marketplace): UInt256 {.contract, view.}
proc minCollateralThreshold*(marketplace: Marketplace): UInt256 {.contract, view.}

proc requestStorage*(marketplace: Marketplace, request: StorageRequest): ?TransactionResponse {.contract.}
proc fillSlot*(marketplace: Marketplace, requestId: RequestId, slotIndex: UInt256, proof: Groth16Proof): ?TransactionResponse {.contract.}
proc withdrawFunds*(marketplace: Marketplace, requestId: RequestId): ?TransactionResponse {.contract.}
proc withdrawFunds*(marketplace: Marketplace, requestId: RequestId, withdrawAddress: Address): ?TransactionResponse {.contract.}
proc freeSlot*(marketplace: Marketplace, id: SlotId): ?TransactionResponse {.contract.}
proc freeSlot*(marketplace: Marketplace, id: SlotId, rewardRecipient: Address, collateralRecipient: Address): ?TransactionResponse {.contract.}
proc requestStorage*(marketplace: Marketplace, request: StorageRequest): Confirmable {.contract.}
proc fillSlot*(marketplace: Marketplace, requestId: RequestId, slotIndex: UInt256, proof: Groth16Proof): Confirmable {.contract.}
proc withdrawFunds*(marketplace: Marketplace, requestId: RequestId): Confirmable {.contract.}
proc withdrawFunds*(marketplace: Marketplace, requestId: RequestId, withdrawAddress: Address): Confirmable {.contract.}
proc freeSlot*(marketplace: Marketplace, id: SlotId): Confirmable {.contract.}
proc freeSlot*(marketplace: Marketplace, id: SlotId, rewardRecipient: Address, collateralRecipient: Address): Confirmable {.contract.}
proc getRequest*(marketplace: Marketplace, id: RequestId): StorageRequest {.contract, view.}
proc getHost*(marketplace: Marketplace, id: SlotId): Address {.contract, view.}
proc getActiveSlot*(marketplace: Marketplace, id: SlotId): Slot {.contract, view.}
Expand All @@ -49,8 +49,8 @@ proc willProofBeRequired*(marketplace: Marketplace, id: SlotId): bool {.contract
proc getChallenge*(marketplace: Marketplace, id: SlotId): array[32, byte] {.contract, view.}
proc getPointer*(marketplace: Marketplace, id: SlotId): uint8 {.contract, view.}

proc submitProof*(marketplace: Marketplace, id: SlotId, proof: Groth16Proof): ?TransactionResponse {.contract.}
proc markProofAsMissing*(marketplace: Marketplace, id: SlotId, period: UInt256): ?TransactionResponse {.contract.}
proc submitProof*(marketplace: Marketplace, id: SlotId, proof: Groth16Proof): Confirmable {.contract.}
proc markProofAsMissing*(marketplace: Marketplace, id: SlotId, period: UInt256): Confirmable {.contract.}

proc reserveSlot*(marketplace: Marketplace, requestId: RequestId, slotIndex: UInt256): ?TransactionResponse {.contract.}
proc reserveSlot*(marketplace: Marketplace, requestId: RequestId, slotIndex: UInt256): Confirmable {.contract.}
proc canReserveSlot*(marketplace: Marketplace, requestId: RequestId, slotIndex: UInt256): bool {.contract, view.}
6 changes: 3 additions & 3 deletions codex/node.nim
Original file line number Diff line number Diff line change
Expand Up @@ -757,15 +757,15 @@ proc stop*(self: CodexNodeRef) {.async.} =
if not self.discovery.isNil:
await self.discovery.stop()

if not self.clock.isNil:
await self.clock.stop()

if clientContracts =? self.contracts.client:
await clientContracts.stop()

if hostContracts =? self.contracts.host:
await hostContracts.stop()

if not self.clock.isNil:
await self.clock.stop()

if validatorContracts =? self.contracts.validator:
await validatorContracts.stop()

Expand Down
54 changes: 26 additions & 28 deletions codex/utils/asyncstatemachine.nim
Original file line number Diff line number Diff line change
Expand Up @@ -59,31 +59,28 @@ proc onError(machine: Machine, error: ref CatchableError): Event =
state.onError(error)

proc run(machine: Machine, state: State) {.async.} =
try:
if next =? await state.run(machine):
machine.schedule(Event.transition(state, next))
except CancelledError:
discard
if next =? await state.run(machine):
machine.schedule(Event.transition(state, next))

proc scheduler(machine: Machine) {.async.} =
var running: Future[void]
try:
while machine.started:
let event = await machine.scheduled.get().track(machine)
if next =? event(machine.state):
if not running.isNil and not running.finished:
await running.cancelAndWait()
let fromState = if machine.state.isNil: "<none>" else: $machine.state
machine.state = next
debug "enter state", state = fromState & " => " & $machine.state
running = machine.run(machine.state)
running
.track(machine)
.catch((err: ref CatchableError) =>
machine.schedule(machine.onError(err))
)
except CancelledError:
discard
while machine.started:
let event = await machine.scheduled.get().track(machine)
if next =? event(machine.state):
if not running.isNil and not running.finished:
trace "cancelling current state", state = $machine.state
await running.cancelAndWait()
let fromState = if machine.state.isNil: "<none>" else: $machine.state
machine.state = next
debug "enter state", state = fromState & " => " & $machine.state
running = machine.run(machine.state)
running
.track(machine)
.cancelled(proc() = trace "state.run cancelled, swallowing", state = $machine.state)
.catch(proc(err: ref CatchableError) =
trace "error caught in state.run, calling state.onError", state = $machine.state
machine.schedule(machine.onError(err))
)

proc start*(machine: Machine, initialState: State) =
if machine.started:
Expand All @@ -93,12 +90,13 @@ proc start*(machine: Machine, initialState: State) =
machine.scheduled = newAsyncQueue[Event]()

machine.started = true
machine.scheduler()
.track(machine)
.catch((err: ref CatchableError) =>
error("Error in scheduler", error = err.msg)
)
machine.schedule(Event.transition(machine.state, initialState))
try:
discard machine.scheduler().track(machine)
machine.schedule(Event.transition(machine.state, initialState))
except CancelledError as e:
discard
except CatchableError as e:
error("Error in scheduler", error = e.msg)

proc stop*(machine: Machine) {.async.} =
if not machine.started:
Expand Down
2 changes: 1 addition & 1 deletion tests/contracts/testContracts.nim
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ ethersuite "Marketplace contracts":
let tokenAddress = await marketplace.token()
token = Erc20Token.new(tokenAddress, ethProvider.getSigner())

let config = await marketplace.config()
let config = await marketplace.configuration()
periodicity = Periodicity(seconds: config.proofs.period)

request = StorageRequest.example
Expand Down
2 changes: 1 addition & 1 deletion tests/contracts/testDeployment.nim
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import ../checktest
type MockProvider = ref object of Provider
chainId*: UInt256

method getChainId*(provider: MockProvider): Future[UInt256] {.async.} =
method getChainId*(provider: MockProvider): Future[UInt256] {.async: (raises:[ProviderError]).} =
return provider.chainId

proc configFactory(): CodexConf =
Expand Down
6 changes: 3 additions & 3 deletions tests/contracts/testMarket.nim
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ ethersuite "On-Chain Market":
setup:
let address = Marketplace.address(dummyVerifier = true)
marketplace = Marketplace.new(address, ethProvider.getSigner())
let config = await marketplace.config()
let config = await marketplace.configuration()
hostRewardRecipient = accounts[2]

market = OnChainMarket.new(marketplace)
Expand Down Expand Up @@ -76,13 +76,13 @@ ethersuite "On-Chain Market":

test "can retrieve proof periodicity":
let periodicity = await market.periodicity()
let config = await marketplace.config()
let config = await marketplace.configuration()
let periodLength = config.proofs.period
check periodicity.seconds == periodLength

test "can retrieve proof timeout":
let proofTimeout = await market.proofTimeout()
let config = await marketplace.config()
let config = await marketplace.configuration()
check proofTimeout == config.proofs.timeout

test "supports marketplace requests":
Expand Down
1 change: 1 addition & 0 deletions tests/contracts/time.nim
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import pkg/ethers
import pkg/serde/json

proc currentTime*(provider: Provider): Future[UInt256] {.async.} =
return (!await provider.getBlock(BlockTag.pending)).timestamp
Expand Down
17 changes: 16 additions & 1 deletion tests/integration/codexprocess.nim
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import pkg/chronicles
import pkg/chronos/asyncproc
import pkg/ethers
import pkg/libp2p
import pkg/stew/io2
import std/os
import std/strutils
import codex/conf
Expand Down Expand Up @@ -40,6 +41,20 @@ method outputLineEndings(node: CodexProcess): string =
method onOutputLineCaptured(node: CodexProcess, line: string) =
discard

method logFileContains*(node: CodexProcess, text: string): bool =
let config = CodexConf.load(cmdLine = node.arguments, quitOnFailure = false)
without logFile =? config.logFile.?string:
raiseAssert "codex node does have a --log-file option set (use .withLogFile())"

let resLogContents = logFile.readAllChars
if resLogContents.isErr:
# without logContents =? logFile.readAllChars:
raiseAssert "failed to open codex log file, aborting (log path: " & logFile & ")"

let logContents = resLogContents.value

return logContents.contains(text)

proc dataDir(node: CodexProcess): string =
let config = CodexConf.load(cmdLine = node.arguments, quitOnFailure = false)
return config.dataDir.string
Expand Down Expand Up @@ -73,4 +88,4 @@ method stop*(node: CodexProcess) {.async.} =
node.client = none CodexClient

method removeDataDir*(node: CodexProcess) =
removeDir(node.dataDir)
os.removeDir(node.dataDir)
19 changes: 19 additions & 0 deletions tests/integration/hardhatprocess.nim
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,25 @@ method processOptions(node: HardhatProcess): set[AsyncProcessOption] =
method outputLineEndings(node: HardhatProcess): string =
return "\n"

method logFileContains*(hardhat: HardhatProcess, text: string): bool =
without fileHandle =? hardhat.logFile:
raiseAssert "failed to open hardhat log file, aborting"

without fileSize =? fileHandle.getFileSize:
raiseAssert "failed to get current hardhat log file size, aborting"

if checkFileSize(fileSize).isErr:
raiseAssert "file size too big for nim indexing"

var data = ""
data.setLen(fileSize)

without bytesRead =? readFile(fileHandle,
data.toOpenArray(0, len(data) - 1)):
raiseAssert "unable to read hardhat log, aborting"

return data.contains(text)

proc openLogFile(node: HardhatProcess, logFilePath: string): IoHandle =
let logFileHandle = openFile(
logFilePath,
Expand Down
2 changes: 1 addition & 1 deletion tests/integration/marketplacesuite.nim
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ template marketplacesuite*(name: string, body: untyped) =
marketplace = Marketplace.new(Marketplace.address, ethProvider.getSigner())
let tokenAddress = await marketplace.token()
token = Erc20Token.new(tokenAddress, ethProvider.getSigner())
let config = await mp.config(marketplace)
let config = await marketplace.configuration()
period = config.proofs.period.truncate(uint64)
periodicity = Periodicity(seconds: period.u256)

Expand Down
20 changes: 20 additions & 0 deletions tests/integration/multinodes.nim
Original file line number Diff line number Diff line change
Expand Up @@ -222,6 +222,26 @@ template multinodesuite*(name: string, body: untyped) =

return await newCodexProcess(validatorIdx, config, Role.Validator)


proc searchLogs(role: Role, text: string): seq[bool] =
var hits: seq[bool] = @[]
if role == Role.Hardhat:
return @[hardhat().logFileContains(text)]
elif role == Role.Client:
for client in clients():
hits.add client.logFileContains(text)
else:
for provider in providers():
hits.add provider.logFileContains(text)

return hits

proc logsContain(role: Role, text: string): bool =
return searchLogs(role, text).allIt(it)

proc logsDoNotContain(role: Role, text: string): bool =
return searchLogs(role, text).allIt(not it)

proc teardownImpl() {.async.} =
for nodes in @[validators(), clients(), providers()]:
for node in nodes:
Expand Down
34 changes: 0 additions & 34 deletions tests/integration/nodeconfig.nim

This file was deleted.

3 changes: 3 additions & 0 deletions tests/integration/nodeprocess.nim
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,9 @@ method outputLineEndings(node: NodeProcess): string {.base.} =
method onOutputLineCaptured(node: NodeProcess, line: string) {.base.} =
raiseAssert "not implemented"

method logFileContains*(hardhat: NodeProcess): bool {.base.} =
raiseAssert "not implemented"

method start*(node: NodeProcess) {.base, async.} =
logScope:
nodeName = node.name
Expand Down
Loading
Loading