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

fix #14320 (tasyncawait.nim is recently very flaky) + avoid hardcoding service ports everywhere + flakyAssert #14327

Merged
merged 9 commits into from
May 13, 2020
Merged
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
4 changes: 4 additions & 0 deletions testament/lib/readme.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
This directory contains helper files used by several tests, to avoid
code duplication, akin to a std extension tailored for testament.

Some of these could later migrate to stdlib.
12 changes: 12 additions & 0 deletions testament/lib/stdtest/netutils.nim
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import std/[nativesockets, asyncdispatch, os]

proc bindAvailablePort*(handle: SocketHandle, port = Port(0)): Port =
block:
var name: Sockaddr_in
name.sin_family = typeof(name.sin_family)(toInt(AF_INET))
name.sin_port = htons(uint16(port))
name.sin_addr.s_addr = htonl(INADDR_ANY)
if bindAddr(handle, cast[ptr SockAddr](addr(name)),
sizeof(name).Socklen) < 0'i32:
raiseOSError(osLastError())
result = getLocalAddr(handle, AF_INET)[1]
25 changes: 25 additions & 0 deletions testament/lib/stdtest/testutils.nim
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import std/private/miscdollars

template flakyAssert*(cond: untyped, msg = "", notifySuccess = true) =
## API to deal with flaky or failing tests. This avoids disabling entire tests
## altogether so that at least the parts that are working are kept being
## tested. This also avoids making CI fail periodically for tests known to
## be flaky. Finally, for known failures, passing `notifySuccess = true` will
## log that the test succeeded, which may indicate that a bug was fixed
## "by accident" and should be looked into.
const info = instantiationInfo(-1, true)
const expr = astToStr(cond)
if cond and not notifySuccess:
discard # silent success
else:
var msg2 = ""
toLocation(msg2, info.filename, info.line, info.column)
if cond:
# a flaky test is failing, we still report it but we don't fail CI
msg2.add " FLAKY_SUCCESS "
else:
# a previously failing test is now passing, a pre-existing bug might've been
# fixed by accidend
msg2.add " FLAKY_FAILURE "
msg2.add $expr & " " & msg
echo msg2
21 changes: 7 additions & 14 deletions tests/arc/tasyncawait.nim
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@ discard """
cmd: "nim c --gc:orc $file"
"""

import asyncdispatch, asyncnet, nativesockets, net, strutils, os
import asyncdispatch, asyncnet, nativesockets, net, strutils
from stdtest/netutils import bindAvailablePort

var msgCount = 0

Expand Down Expand Up @@ -44,24 +45,16 @@ proc readMessages(client: AsyncFD) {.async.} =
else:
doAssert false

proc createServer(port: Port) {.async.} =
var server = createAsyncNativeSocket()
block:
var name: Sockaddr_in
name.sin_family = typeof(name.sin_family)(toInt(AF_INET))
name.sin_port = htons(uint16(port))
name.sin_addr.s_addr = htonl(INADDR_ANY)
if bindAddr(server.SocketHandle, cast[ptr SockAddr](addr(name)),
sizeof(name).Socklen) < 0'i32:
raiseOSError(osLastError())

proc createServer(server: AsyncFD) {.async.} =
discard server.SocketHandle.listen()
while true:
asyncCheck readMessages(await accept(server))

proc main =
asyncCheck createServer(Port(10335))
asyncCheck launchSwarm(Port(10335))
let server = createAsyncNativeSocket()
let port = bindAvailablePort(server.SocketHandle)
asyncCheck createServer(server)
asyncCheck launchSwarm(port)
while true:
poll()
if clientCount == swarmSize: break
Expand Down
27 changes: 8 additions & 19 deletions tests/async/tasyncawait.nim
Original file line number Diff line number Diff line change
@@ -1,8 +1,5 @@
discard """
output: "2000"
"""
import asyncdispatch, asyncnet, nativesockets, net, strutils, os

import asyncdispatch, asyncnet, nativesockets, net, strutils
from stdtest/netutils import bindAvailablePort
var msgCount = 0

const
Expand Down Expand Up @@ -42,26 +39,18 @@ proc readMessages(client: AsyncFD) {.async.} =
else:
doAssert false

proc createServer(port: Port) {.async.} =
var server = createAsyncNativeSocket()
block:
var name: Sockaddr_in
name.sin_family = typeof(name.sin_family)(toInt(AF_INET))
name.sin_port = htons(uint16(port))
name.sin_addr.s_addr = htonl(INADDR_ANY)
if bindAddr(server.SocketHandle, cast[ptr SockAddr](addr(name)),
sizeof(name).Socklen) < 0'i32:
raiseOSError(osLastError())

proc createServer(server: AsyncFD) {.async.} =
discard server.SocketHandle.listen()
while true:
asyncCheck readMessages(await accept(server))

asyncCheck createServer(Port(10335))
asyncCheck launchSwarm(Port(10335))
let server = createAsyncNativeSocket()
let port = bindAvailablePort(server.SocketHandle)
asyncCheck createServer(server)
asyncCheck launchSwarm(port)
while true:
poll()
if clientCount == swarmSize: break

assert msgCount == swarmSize * messagesToSend
echo msgCount
doAssert msgCount == 2000
21 changes: 7 additions & 14 deletions tests/async/tasyncawait_cyclebreaker.nim
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@ discard """
output: "20000"
cmd: "nim c -d:nimTypeNames -d:nimCycleBreaker $file"
"""
import asyncdispatch, asyncnet, nativesockets, net, strutils, os
import asyncdispatch, asyncnet, nativesockets, net, strutils
from stdtest/netutils import bindAvailablePort

var msgCount = 0

Expand Down Expand Up @@ -43,23 +44,15 @@ proc readMessages(client: AsyncFD) {.async.} =
else:
doAssert false

proc createServer(port: Port) {.async.} =
var server = createAsyncNativeSocket()
block:
var name: Sockaddr_in
name.sin_family = typeof(name.sin_family)(toInt(AF_INET))
name.sin_port = htons(uint16(port))
name.sin_addr.s_addr = htonl(INADDR_ANY)
if bindAddr(server.SocketHandle, cast[ptr SockAddr](addr(name)),
sizeof(name).Socklen) < 0'i32:
raiseOSError(osLastError())

proc createServer(server: AsyncFD) {.async.} =
discard server.SocketHandle.listen()
while true:
asyncCheck readMessages(await accept(server))

asyncCheck createServer(Port(10335))
asyncCheck launchSwarm(Port(10335))
let server = createAsyncNativeSocket()
let port = bindAvailablePort(server.SocketHandle)
asyncCheck createServer(server)
asyncCheck launchSwarm(port)
while true:
poll()
GC_collectZct()
Expand Down
20 changes: 10 additions & 10 deletions tests/async/tasyncsend4757.nim
Original file line number Diff line number Diff line change
@@ -1,24 +1,24 @@
discard """
output: "Finished"
"""

import asyncdispatch, asyncnet

proc createServer(port: Port) {.async.} =
var port: Port
proc createServer() {.async.} =
var server = newAsyncSocket()
server.setSockOpt(OptReuseAddr, true)
bindAddr(server, port)
bindAddr(server)
port = getLocalAddr(server)[1]
server.listen()
while true:
let client = await server.accept()
discard await client.recvLine()

asyncCheck createServer(10335.Port)
asyncCheck createServer()

var done = false
proc f(): Future[void] {.async.} =
let s = newAsyncNativeSocket()
await s.connect("localhost", 10335.Port)
let s = createAsyncNativeSocket()
await s.connect("localhost", port)
await s.send("123")
echo "Finished"
done = true

waitFor f()
doAssert done
30 changes: 17 additions & 13 deletions tests/async/tasyncssl.nim
Original file line number Diff line number Diff line change
@@ -1,16 +1,12 @@
discard """
cmd: "nim $target --hints:on --define:ssl $options $file"
output: "500"
disabled: "windows"
target: c
action: compile
"""

# XXX, deactivated

import asyncdispatch, asyncnet, net, strutils, os
import asyncdispatch, asyncnet, net, strutils
import stdtest/testutils

when defined(ssl):
var port0: Port
var msgCount = 0

const
Expand Down Expand Up @@ -45,25 +41,33 @@ when defined(ssl):
else:
doAssert false

proc createServer(port: Port) {.async.} =
proc createServer() {.async.} =
let serverContext = newContext(verifyMode = CVerifyNone,
certFile = "tests/testdata/mycert.pem",
keyFile = "tests/testdata/mycert.pem")
var server = newAsyncSocket()
serverContext.wrapSocket(server)
server.setSockOpt(OptReuseAddr, true)
bindAddr(server, port)
bindAddr(server)
port0 = getLocalAddr(server)[1]
server.listen()
while true:
let client = await accept(server)
serverContext.wrapConnectedSocket(client, handshakeAsServer)
asyncCheck readMessages(client)

asyncCheck createServer(Port(10335))
asyncCheck launchSwarm(Port(10335))
asyncCheck createServer()
asyncCheck launchSwarm(port0)
while true:
poll()
if clientCount == swarmSize: break

assert msgCount == swarmSize * messagesToSend
echo msgCount
template cond(): bool = msgCount == swarmSize * messagesToSend
when defined(windows):
# currently: msgCount == 0
flakyAssert cond()
elif defined(linux) and int.sizeof == 8:
# currently: msgCount == 10
flakyAssert cond()
assert msgCount > 0
else: assert cond(), $msgCount
29 changes: 8 additions & 21 deletions tests/async/twinasyncrw.nim
Original file line number Diff line number Diff line change
@@ -1,9 +1,6 @@
discard """
output: "5000"
"""
when defined(windows):
import asyncdispatch, nativesockets, net, strutils, os, winlean

from stdtest/netutils import bindAvailablePort
var msgCount = 0

const
Expand Down Expand Up @@ -228,29 +225,19 @@ when defined(windows):
else:
doAssert false

proc createServer(port: Port) {.async.} =
var server = createNativeSocket()
setBlocking(server, false)
block:
var name = Sockaddr_in()
name.sin_family = toInt(Domain.AF_INET).uint16
name.sin_port = htons(uint16(port))
name.sin_addr.s_addr = htonl(INADDR_ANY)
if bindAddr(server, cast[ptr SockAddr](addr(name)),
sizeof(name).Socklen) < 0'i32:
raiseOSError(osLastError())

proc createServer(server: SocketHandle) {.async.} =
discard server.listen()
while true:
asyncCheck readMessages(await winAccept(AsyncFD(server)))

asyncCheck createServer(Port(10335))
asyncCheck launchSwarm(Port(10335))
var server = createNativeSocket()
setBlocking(server, false)
let port = bindAvailablePort(server)
asyncCheck createServer(server)
asyncCheck launchSwarm(port)
while true:
poll()
if clientCount == swarmSize: break

assert msgCount == swarmSize * messagesToSend
echo msgCount
else:
echo(5000)
doAssert msgCount == 5000
5 changes: 4 additions & 1 deletion tests/config.nims
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
switch("path", "$nim/testament/lib") # so we can `import stdtest/foo` in this dir
switch("path", "$lib/../testament/lib")
# so we can `import stdtest/foo` inside tests
# Using $lib/../ instead of $nim/ so you can use a different nim to run tests
# during local testing, eg nim --lib:lib.

## prevent common user config settings to interfere with testament expectations
## Indifidual tests can override this if needed to test for these options.
Expand Down