summary refs log tree commit diff stats
path: root/tests/iter/t21306.nim
diff options
context:
space:
mode:
Diffstat (limited to 'tests/iter/t21306.nim')
-rw-r--r--tests/iter/t21306.nim118
1 files changed, 118 insertions, 0 deletions
diff --git a/tests/iter/t21306.nim b/tests/iter/t21306.nim
new file mode 100644
index 000000000..4d0396294
--- /dev/null
+++ b/tests/iter/t21306.nim
@@ -0,0 +1,118 @@
+discard """
+  targets: "c js"
+"""
+
+# bug #21306
+type
+  FutureState {.pure.} = enum
+    Pending, Finished, Cancelled, Failed
+
+  FutureBase = ref object of RootObj
+    state: FutureState
+    error: ref CatchableError
+    id: uint
+
+  Future[T] = ref object of FutureBase
+    closure: iterator(f: Future[T]): FutureBase {.raises: [Defect, CatchableError, Exception], gcsafe.}
+    value: T
+
+template setupFutureBase() =
+  new(result)
+  result.state = FutureState.Pending
+
+proc newFutureImpl[T](): Future[T] =
+  setupFutureBase()
+
+template newFuture[T](fromProc: static[string] = ""): Future[T] =
+  newFutureImpl[T]()
+
+proc internalRead[T](fut: Future[T]): T =
+  when T isnot void:
+    return fut.value
+
+template await[T](f: Future[T]): untyped =
+  when declared(chronosInternalRetFuture):
+    when not declaredInScope(chronosInternalTmpFuture):
+      var chronosInternalTmpFuture {.inject.}: FutureBase = f
+    else:
+      chronosInternalTmpFuture = f
+
+    yield chronosInternalTmpFuture
+
+    when T isnot void:
+      cast[type(f)](chronosInternalTmpFuture).internalRead()
+
+type
+  VerifierError {.pure.} = enum
+    Invalid
+    MissingParent
+    UnviableFork
+    Duplicate
+  ProcessingCallback = proc() {.gcsafe, raises: [Defect].}
+  BlockVerifier =
+    proc(signedBlock: int):
+      Future[VerifierError] {.gcsafe, raises: [Defect].}
+
+  SyncQueueKind {.pure.} = enum
+    Forward, Backward
+
+  SyncRequest[T] = object
+    kind: SyncQueueKind
+    index: uint64
+    slot: uint64
+    count: uint64
+    item: T
+
+  SyncResult[T] = object
+    request: SyncRequest[T]
+    data: seq[ref int]
+
+  SyncQueue[T] = ref object
+    kind: SyncQueueKind
+    readyQueue: seq[SyncResult[T]]
+    blockVerifier: BlockVerifier
+
+iterator blocks[T](sq: SyncQueue[T],
+                    sr: SyncResult[T]): ref int =
+  case sq.kind
+  of SyncQueueKind.Forward:
+    for i in countup(0, len(sr.data) - 1):
+      yield sr.data[i]
+  of SyncQueueKind.Backward:
+    for i in countdown(len(sr.data) - 1, 0):
+      yield sr.data[i]
+
+proc push[T](sq: SyncQueue[T]; sr: SyncRequest[T]; data: seq[ref int];
+             processingCb: ProcessingCallback = nil): Future[void] {.
+    stackTrace: off, gcsafe.} =
+  iterator push_436208182(chronosInternalRetFuture: Future[void]): FutureBase {.
+      closure, gcsafe, raises: [Defect, CatchableError, Exception].} =
+    block:
+      template result(): auto {.used.} =
+        {.fatal: "You should not reference the `result` variable inside" &
+            " a void async proc".}
+
+      let item = default(SyncResult[T])
+      for blk in sq.blocks(item):
+        let res = await sq.blockVerifier(blk[])
+
+  var resultFuture = newFuture[void]("push")
+  resultFuture.closure = push_436208182
+  return resultFuture
+
+type
+  SomeTPeer = ref object
+    score: int
+
+proc getSlice(): seq[ref int] =
+  discard
+
+template smokeTest(kkind: SyncQueueKind, start, finish: uint64,
+                   chunkSize: uint64) =
+  var queue: SyncQueue[SomeTPeer]
+  var request: SyncRequest[SomeTPeer]
+  discard queue.push(request, getSlice())
+
+for k in {SyncQueueKind.Forward}:
+  for item in [(uint64(1181), uint64(1399), 41'u64)]:
+    smokeTest(k, item[0], item[1], item[2])
\ No newline at end of file