Skip to content

Commit

Permalink
wip
Browse files Browse the repository at this point in the history
  • Loading branch information
nitely committed Mar 23, 2024
1 parent 41b267a commit 3d32d52
Show file tree
Hide file tree
Showing 2 changed files with 92 additions and 111 deletions.
50 changes: 22 additions & 28 deletions src/hyperx/testutils.nim
Original file line number Diff line number Diff line change
Expand Up @@ -38,26 +38,27 @@ proc frame*(
for f in flags:
result.flags.incl f

# XXX
# client: ClientContext
# peer: PeerContext
# remove resps
type
TestClientContext* = ref object
c*: ClientContext
sid: int
resps*: seq[Response]
PeerContext = ref object
headersEnc*, headersDec*: DynHeaders
TestClientContext* = ref object
client*: ClientContext
peer*: PeerContext
sid*: int

func newTestClient*(hostname: string): TestClientContext =
result = TestClientContext(
c: newClient(hostname, Port 443),
sid: 1,
resps: newSeq[Response](),
func newPeerContext(): PeerContext =
PeerContext(
headersEnc: initDynHeaders(4096),
headersDec: initDynHeaders(4096)
)

func newTestClient*(hostname: string): TestClientContext =
TestClientContext(
client: newClient(hostname, Port 443),
peer: newPeerContext(),
sid: 1
)

proc frame*(
tc: TestClientContext,
typ: FrmTyp,
Expand All @@ -71,16 +72,9 @@ proc hencode*(tc: TestClientContext, hs: string): string =
if h.len == 0:
continue
let parts = h.split(": ", 1)
discard hencode(parts[0], parts[1], tc.headersEnc, resp)
discard hencode(parts[0], parts[1], tc.peer.headersEnc, resp)
result = resp.toString

template withConnection*(tc: TestClientContext, body: untyped): untyped =
withConnection tc.c:
body

proc get*(tc: TestClientContext, path: string) {.async.} =
tc.resps.add await tc.c.get(path)

proc reply*(
tc: TestClientContext,
headers: string,
Expand All @@ -90,34 +84,34 @@ proc reply*(
frmtHeaders, tc.sid.FrmSid, @[frmfEndHeaders]
)
frm1.add hencode(tc, headers).toBytes
await tc.c.putRecvTestData frm1.s
await tc.client.putRecvTestData frm1.s
var frm2 = frame(
frmtData, tc.sid.FrmSid, @[frmfEndStream]
)
frm2.add text.toBytes
await tc.c.putRecvTestData frm2.s
await tc.client.putRecvTestData frm2.s
tc.sid += 2

proc reply*(
tc: TestClientContext,
frm: Frame
) {.async.} =
await tc.c.putRecvTestData frm.s
await tc.client.putRecvTestData frm.s

proc sent*(tc: TestClientContext, size: int): Future[seq[byte]] {.async.} =
result = await tc.c.sentTestData(size)
result = await tc.client.sentTestData(size)

proc sent*(tc: TestClientContext): Future[Frame] {.async.} =
result = newEmptyFrame()
result.s = await tc.c.sentTestData(frmHeaderSize)
result.s = await tc.client.sentTestData(frmHeaderSize)
doAssert result.len == frmHeaderSize
var payload = newSeq[byte]()
if result.payloadLen.int > 0:
payload = await tc.c.sentTestData(result.payloadLen.int)
payload = await tc.client.sentTestData(result.payloadLen.int)
doAssert payload.len == result.payloadLen.int
if result.typ == frmtHeaders:
var ds = initDecodedStr()
hdecodeAll(payload, tc.headersDec, ds)
hdecodeAll(payload, tc.peer.headersDec, ds)
result.add toBytes($ds)
else:
result.add payload
Expand Down
153 changes: 70 additions & 83 deletions tests/testclient.nim
Original file line number Diff line number Diff line change
Expand Up @@ -43,63 +43,46 @@ proc checkTableSizeAck(tc: TestClientContext) {.async.} =
testAsync "simple response":
const headers = ":status: 200\r\nfoo: foo\r\n"
const text = "foobar body"
var resp1: Response
var tc = newTestClient("foo.bar")
withConnection tc:
withConnection tc.client:
await tc.checkHandshake()
await (
tc.get("/") and
tc.reply(headers, text)
)
doAssert tc.resps[0].headers == headers
doAssert tc.resps[0].text == text
let get1 = tc.client.get("/")
let rep1 = tc.reply(headers, text)
resp1 = await get1
await rep1
doAssert resp1.headers == headers
doAssert resp1.text == text

testAsync "multiple responses":
const
headers = ":status: 200\r\nfoo: foo\r\n"
text = "foo body"
headers2 = ":status: 200\r\nbar: bar\r\n"
text2 = "bar body"
var resp1, resp2: Response
var tc = newTestClient("foo.bar")
withConnection tc:
await tc.checkHandshake()
await (
tc.get("/") and
tc.reply(headers, text) and
tc.get("/") and
tc.reply(headers2, text2)
)
doAssert tc.resps[0].headers == headers
doAssert tc.resps[0].text == text
doAssert tc.resps[1].headers == headers2
doAssert tc.resps[1].text == text2

testAsync "multiple responses unordered":
const
headers = ":status: 200\r\nfoo: foo\r\n"
text = "foo body"
headers2 = ":status: 200\r\nbar: bar\r\n"
text2 = "bar body"
var tc = newTestClient("foo.bar")
withConnection tc:
withConnection tc.client:
await tc.checkHandshake()
await (
tc.get("/") and
tc.get("/") and
tc.reply(headers, text) and
tc.reply(headers2, text2)
)
doAssert tc.resps[0].headers == headers
doAssert tc.resps[0].text == text
doAssert tc.resps[1].headers == headers2
doAssert tc.resps[1].text == text2
let get1 = tc.client.get("/")
let get2 = tc.client.get("/")
let rep1 = tc.reply(headers, text)
let rep2 = tc.reply(headers2, text2)
resp1 = await get1
resp2 = await get2
await (rep1 and rep2)
doAssert resp1.headers == headers
doAssert resp1.text == text
doAssert resp2.headers == headers2
doAssert resp2.text == text2

testAsync "simple request":
var frm1: Frame
var tc = newTestClient("foo.bar")
withConnection tc:
withConnection tc.client:
await tc.checkHandshake()
await (
tc.get("/") and
tc.client.get("/") and
tc.reply(":status: 200\r\nfoo: foo\r\n", "bar")
)
frm1 = await tc.sent()
Expand All @@ -116,14 +99,14 @@ testAsync "simple request":
testAsync "multiple requests":
var frm1, frm2, frm3: Frame
var tc = newTestClient("foo.bar")
withConnection tc:
withConnection tc.client:
await tc.checkHandshake()
await (
tc.get("/1") and
tc.client.get("/1") and
tc.reply(":status: 200\r\nfoo: foo\r\n", "bar")
)
await (
tc.get("/2") and
tc.client.get("/2") and
tc.reply(":status: 200\r\nbar: bar\r\n", "bar")
)
frm1 = await tc.sent()
Expand Down Expand Up @@ -156,11 +139,11 @@ testAsync "response with bad header compression":
await tc.reply(frm1)
var errorMsg = ""
var tc = newTestClient("foo.bar")
withConnection tc:
withConnection tc.client:
await tc.checkHandshake()
try:
await (
tc.get("/") and
tc.client.get("/") and
tc.replyBadHeaders()
)
except HyperxConnectionError as err:
Expand All @@ -183,19 +166,21 @@ testAsync "response with headers prio":
text = "foo body"
headers2 = ":status: 200\r\nbar: bar\r\n"
text2 = "bar body"
var resp1, resp2: Response
var tc = newTestClient("foo.bar")
withConnection tc:
withConnection tc.client:
await tc.checkHandshake()
await (
tc.get("/") and
tc.replyPrio(headers, text) and
tc.get("/") and
tc.reply(headers2, text2)
)
doAssert tc.resps[0].headers == headers
doAssert tc.resps[0].text == text
doAssert tc.resps[1].headers == headers2
doAssert tc.resps[1].text == text2
let get1 = tc.client.get("/")
let get2 = tc.client.get("/")
let rep1 = tc.replyPrio(headers, text)
let rep2 = tc.reply(headers2, text2)
resp1 = await get1
resp2 = await get2
await (rep1 and rep2)
doAssert resp1.headers == headers
doAssert resp1.text == text
doAssert resp2.headers == headers2
doAssert resp2.text == text2

testAsync "response with bad prio length":
proc replyPrio(tc: TestClientContext) {.async.} =
Expand All @@ -206,11 +191,11 @@ testAsync "response with bad prio length":
await tc.reply(frm1)
var errorMsg = ""
var tc = newTestClient("foo.bar")
withConnection tc:
withConnection tc.client:
await tc.checkHandshake()
try:
await (
tc.get("/") and
tc.client.get("/") and
tc.replyPrio()
)
except HyperxConnectionError as err:
Expand All @@ -233,19 +218,21 @@ testAsync "response with headers padding":
text = "foo body"
headers2 = ":status: 200\r\nbar: bar\r\n"
text2 = "bar body"
var resp1, resp2: Response
var tc = newTestClient("foo.bar")
withConnection tc:
withConnection tc.client:
await tc.checkHandshake()
await (
tc.get("/") and
tc.replyPadding(headers, text) and
tc.get("/") and
tc.reply(headers2, text2)
)
doAssert tc.resps[0].headers == headers
doAssert tc.resps[0].text == text
doAssert tc.resps[1].headers == headers2
doAssert tc.resps[1].text == text2
let get1 = tc.client.get("/")
let get2 = tc.client.get("/")
let rep1 = tc.replyPadding(headers, text)
let rep2 = tc.reply(headers2, text2)
resp1 = await get1
resp2 = await get2
await (rep1 and rep2)
doAssert resp1.headers == headers
doAssert resp1.text == text
doAssert resp2.headers == headers2
doAssert resp2.text == text2

testAsync "response with bad over padding length":
proc replyPadding(tc: TestClientContext) {.async.} =
Expand All @@ -256,16 +243,17 @@ testAsync "response with bad over padding length":
await tc.reply(frm1)
var errorMsg = ""
var tc = newTestClient("foo.bar")
withConnection tc:
withConnection tc.client:
await tc.checkHandshake()
try:
await (
tc.get("/") and
tc.client.get("/") and
tc.replyPadding()
)
except HyperxConnectionError as err:
errorMsg = err.msg
doAssert "PROTOCOL_ERROR" in errorMsg

testAsync "response with bad missing padding length":
proc replyPadding(tc: TestClientContext) {.async.} =
let frm1 = tc.frame(
Expand All @@ -274,11 +262,11 @@ testAsync "response with bad missing padding length":
await tc.reply(frm1)
var errorMsg = ""
var tc = newTestClient("foo.bar")
withConnection tc:
withConnection tc.client:
await tc.checkHandshake()
try:
await (
tc.get("/") and
tc.client.get("/") and
tc.replyPadding()
)
except HyperxConnectionError as err:
Expand All @@ -288,15 +276,15 @@ testAsync "response with bad missing padding length":
testAsync "header table is populated":
var frm1: Frame
var tc = newTestClient("foo.bar")
withConnection tc:
withConnection tc.client:
await tc.checkHandshake()
await (
tc.get("/foo") and
tc.client.get("/foo") and
tc.reply(":status: 200\r\nfoo: foo\r\n", "bar")
)
frm1 = await tc.sent()
doAssert tc.headersDec.len == 4
doAssert $tc.headersDec ==
doAssert tc.peer.headersDec.len == 4
doAssert $tc.peer.headersDec ==
"accept: */*\r\L" &
"user-agent: " & userAgent & "\r\L" &
":authority: foo.bar\r\L" &
Expand All @@ -318,20 +306,20 @@ testAsync "header table size setting is applied":
await tc.reply(frm1)
var frm1: Frame
var tc = newTestClient("foo.bar")
withConnection tc:
withConnection tc.client:
await tc.checkHandshake()
await tc.recvTableSizeSetting(0)
await tc.checkTableSizeAck()
await (
tc.get("/foo") and
tc.client.get("/foo") and
tc.reply(":status: 200\r\nfoo: foo\r\n", "bar")
)
frm1 = await tc.sent()
# XXX window size update
#frm2 = await tc.sent()
# XXX ack window size update
#frm3 = await tc.sent()
doAssert tc.headersDec.len == 0
doAssert tc.peer.headersDec.len == 0
doAssert frm1.sid.int == 1
doAssert frm1.typ == frmtHeaders
doAssert frm1.payload.toString ==
Expand All @@ -347,14 +335,13 @@ testAsync "response stream":
const text = "foobar body"
let content = newStringRef()
var tc = newTestClient("foo.bar")
withConnection tc:
withConnection tc.client:
await tc.checkHandshake()
let strm = tc.c.newClientStream()
let strm = tc.client.newClientStream()
withStream strm:
await strm.sendHeaders(hmGet, "/")
await tc.reply(headers, text)
await strm.recvHeaders(content)
while not strm.ended:
await strm.recvBody(content)
doAssert content[] == headers & text

0 comments on commit 3d32d52

Please sign in to comment.