Merge branch 'devel' of github.com:nim-lang/Nim into devel

This commit is contained in:
Araq 2018-01-11 18:05:26 +01:00
commit 425f221440
19 changed files with 302 additions and 113 deletions

View file

@ -1202,18 +1202,30 @@ proc genObjConstr(p: BProc, e: PNode, d: var TLoc) =
# we skip this step here: # we skip this step here:
if not p.module.compileToCpp: if not p.module.compileToCpp:
if handleConstExpr(p, e, d): return if handleConstExpr(p, e, d): return
var tmp: TLoc
var t = e.typ.skipTypes(abstractInst) var t = e.typ.skipTypes(abstractInst)
getTemp(p, t, tmp)
let isRef = t.kind == tyRef let isRef = t.kind == tyRef
var r = rdLoc(tmp)
if isRef: # check if we need to construct the object in a temporary
rawGenNew(p, tmp, nil) var useTemp =
t = t.lastSon.skipTypes(abstractInst) isRef or
r = "(*$1)" % [r] (d.k notin {locTemp,locLocalVar,locGlobalVar,locParam,locField}) or
gcUsage(e) (isPartOf(d.lode, e) != arNo)
var tmp: TLoc
var r: Rope
if useTemp:
getTemp(p, t, tmp)
r = rdLoc(tmp)
if isRef:
rawGenNew(p, tmp, nil)
t = t.lastSon.skipTypes(abstractInst)
r = "(*$1)" % [r]
gcUsage(e)
else:
constructLoc(p, tmp)
else: else:
constructLoc(p, tmp) resetLoc(p, d)
r = rdLoc(d)
discard getTypeDesc(p.module, t) discard getTypeDesc(p.module, t)
let ty = getUniqueType(t) let ty = getUniqueType(t)
for i in 1 ..< e.len: for i in 1 ..< e.len:
@ -1227,15 +1239,19 @@ proc genObjConstr(p: BProc, e: PNode, d: var TLoc) =
genFieldCheck(p, it.sons[2], r, field) genFieldCheck(p, it.sons[2], r, field)
add(tmp2.r, ".") add(tmp2.r, ".")
add(tmp2.r, field.loc.r) add(tmp2.r, field.loc.r)
tmp2.k = locTemp if useTemp:
tmp2.k = locTemp
tmp2.storage = if isRef: OnHeap else: OnStack
else:
tmp2.k = d.k
tmp2.storage = if isRef: OnHeap else: d.storage
tmp2.lode = it.sons[1] tmp2.lode = it.sons[1]
tmp2.storage = if isRef: OnHeap else: OnStack
expr(p, it.sons[1], tmp2) expr(p, it.sons[1], tmp2)
if useTemp:
if d.k == locNone: if d.k == locNone:
d = tmp d = tmp
else: else:
genAssignment(p, d, tmp, {}) genAssignment(p, d, tmp, {})
proc lhsDoesAlias(a, b: PNode): bool = proc lhsDoesAlias(a, b: PNode): bool =
for y in b: for y in b:

View file

@ -70,7 +70,7 @@ __clang__
#if defined(_MSC_VER) #if defined(_MSC_VER)
# pragma warning(disable: 4005 4100 4101 4189 4191 4200 4244 4293 4296 4309) # pragma warning(disable: 4005 4100 4101 4189 4191 4200 4244 4293 4296 4309)
# pragma warning(disable: 4310 4365 4456 4477 4514 4574 4611 4668 4702 4706) # pragma warning(disable: 4310 4365 4456 4477 4514 4574 4611 4668 4702 4706)
# pragma warning(disable: 4710 4711 4774 4800 4820 4996 4090 4297) # pragma warning(disable: 4710 4711 4774 4800 4809 4820 4996 4090 4297)
#endif #endif
/* ------------------------------------------------------------------------- */ /* ------------------------------------------------------------------------- */

View file

@ -324,12 +324,12 @@ proc mget*[T](future: FutureVar[T]): var T =
## Future has not been finished. ## Future has not been finished.
result = Future[T](future).value result = Future[T](future).value
proc finished*[T](future: Future[T] | FutureVar[T]): bool = proc finished*(future: FutureBase | FutureVar): bool =
## Determines whether ``future`` has completed. ## Determines whether ``future`` has completed.
## ##
## ``True`` may indicate an error or a value. Use ``failed`` to distinguish. ## ``True`` may indicate an error or a value. Use ``failed`` to distinguish.
when future is FutureVar[T]: when future is FutureVar:
result = (Future[T](future)).finished result = (FutureBase(future)).finished
else: else:
result = future.finished result = future.finished

View file

@ -32,6 +32,12 @@ template createCb(retFutureSym, iteratorNameSym,
try: try:
if not nameIterVar.finished: if not nameIterVar.finished:
var next = nameIterVar() var next = nameIterVar()
# Continue while the yielded future is already finished.
while (not next.isNil) and next.finished:
next = nameIterVar()
if nameIterVar.finished:
break
if next == nil: if next == nil:
if not retFutureSym.finished: if not retFutureSym.finished:
let msg = "Async procedure ($1) yielded `nil`, are you await'ing a " & let msg = "Async procedure ($1) yielded `nil`, are you await'ing a " &

View file

@ -413,7 +413,7 @@ proc isIpAddress*(address_str: string): bool {.tags: [].} =
when defineSsl: when defineSsl:
CRYPTO_malloc_init() CRYPTO_malloc_init()
SslLibraryInit() doAssert SslLibraryInit() == 1
SslLoadErrorStrings() SslLoadErrorStrings()
ErrLoadBioStrings() ErrLoadBioStrings()
OpenSSL_add_all_algorithms() OpenSSL_add_all_algorithms()

View file

@ -672,7 +672,10 @@ template walkCommon(pattern: string, filter) =
if dotPos < 0 or idx >= ff.len or ff[idx] == '.' or if dotPos < 0 or idx >= ff.len or ff[idx] == '.' or
pattern[dotPos+1] == '*': pattern[dotPos+1] == '*':
yield splitFile(pattern).dir / extractFilename(ff) yield splitFile(pattern).dir / extractFilename(ff)
if findNextFile(res, f) == 0'i32: break if findNextFile(res, f) == 0'i32:
let errCode = getLastError()
if errCode == ERROR_NO_MORE_FILES: break
else: raiseOSError(errCode.OSErrorCode)
else: # here we use glob else: # here we use glob
var var
f: Glob f: Glob
@ -782,7 +785,10 @@ iterator walkDir*(dir: string; relative=false): tuple[kind: PathComponent, path:
let xx = if relative: extractFilename(getFilename(f)) let xx = if relative: extractFilename(getFilename(f))
else: dir / extractFilename(getFilename(f)) else: dir / extractFilename(getFilename(f))
yield (k, xx) yield (k, xx)
if findNextFile(h, f) == 0'i32: break if findNextFile(h, f) == 0'i32:
let errCode = getLastError()
if errCode == ERROR_NO_MORE_FILES: break
else: raiseOSError(errCode.OSErrorCode)
else: else:
var d = opendir(dir) var d = opendir(dir)
if d != nil: if d != nil:

View file

@ -129,8 +129,8 @@ type
## The ``times`` module only supplies implementations for the systems local time and UTC. ## The ``times`` module only supplies implementations for the systems local time and UTC.
## The members ``zoneInfoFromUtc`` and ``zoneInfoFromTz`` should not be accessed directly ## The members ``zoneInfoFromUtc`` and ``zoneInfoFromTz`` should not be accessed directly
## and are only exported so that ``Timezone`` can be implemented by other modules. ## and are only exported so that ``Timezone`` can be implemented by other modules.
zoneInfoFromUtc*: proc (time: Time): ZonedTime {.nimcall, tags: [], raises: [], benign .} zoneInfoFromUtc*: proc (time: Time): ZonedTime {.tags: [], raises: [], benign.}
zoneInfoFromTz*: proc (adjTime: Time): ZonedTime {.nimcall, tags: [], raises: [], benign .} zoneInfoFromTz*: proc (adjTime: Time): ZonedTime {.tags: [], raises: [], benign.}
name*: string ## The name of the timezone, f.ex 'Europe/Stockholm' or 'Etc/UTC'. Used for checking equality. name*: string ## The name of the timezone, f.ex 'Europe/Stockholm' or 'Etc/UTC'. Used for checking equality.
## Se also: https://en.wikipedia.org/wiki/List_of_tz_database_time_zones ## Se also: https://en.wikipedia.org/wiki/List_of_tz_database_time_zones
ZonedTime* = object ## Represents a zooned instant in time that is not associated with any calendar. ZonedTime* = object ## Represents a zooned instant in time that is not associated with any calendar.

View file

@ -406,7 +406,8 @@ proc setStdIoUnbuffered() =
when declared(stdout): when declared(stdout):
proc echoBinSafe(args: openArray[string]) {.compilerProc.} = proc echoBinSafe(args: openArray[string]) {.compilerProc.} =
when not defined(windows): # flockfile deadlocks some versions of Android 5.x.x
when not defined(windows) and not defined(android):
proc flockfile(f: File) {.importc, noDecl.} proc flockfile(f: File) {.importc, noDecl.}
proc funlockfile(f: File) {.importc, noDecl.} proc funlockfile(f: File) {.importc, noDecl.}
flockfile(stdout) flockfile(stdout)
@ -415,7 +416,7 @@ when declared(stdout):
const linefeed = "\n" # can be 1 or more chars const linefeed = "\n" # can be 1 or more chars
discard c_fwrite(linefeed.cstring, linefeed.len, 1, stdout) discard c_fwrite(linefeed.cstring, linefeed.len, 1, stdout)
discard c_fflush(stdout) discard c_fflush(stdout)
when not defined(windows): when not defined(windows) and not defined(android):
funlockfile(stdout) funlockfile(stdout)
{.pop.} {.pop.}

View file

@ -386,8 +386,7 @@ proc nimParseBiggestFloat(s: string, number: var BiggestFloat,
kdigits, fdigits = 0 kdigits, fdigits = 0
exponent: int exponent: int
integer: uint64 integer: uint64
fraction: uint64 frac_exponent = 0
frac_exponent= 0
exp_sign = 1 exp_sign = 1
first_digit = -1 first_digit = -1
has_sign = false has_sign = false
@ -480,7 +479,8 @@ proc nimParseBiggestFloat(s: string, number: var BiggestFloat,
# if integer is representable in 53 bits: fast path # if integer is representable in 53 bits: fast path
# max fast path integer is 1<<53 - 1 or 8999999999999999 (16 digits) # max fast path integer is 1<<53 - 1 or 8999999999999999 (16 digits)
if kdigits + fdigits <= 16 and first_digit <= 8: let digits = kdigits + fdigits
if digits <= 15 or (digits <= 16 and first_digit <= 8):
# max float power of ten with set bits above the 53th bit is 10^22 # max float power of ten with set bits above the 53th bit is 10^22
if abs_exponent <= 22: if abs_exponent <= 22:
if exp_negative: if exp_negative:
@ -504,6 +504,7 @@ proc nimParseBiggestFloat(s: string, number: var BiggestFloat,
result = i - start result = i - start
i = start i = start
# re-parse without error checking, any error should be handled by the code above. # re-parse without error checking, any error should be handled by the code above.
if s[i] == '.': i.inc
while s[i] in {'0'..'9','+','-'}: while s[i] in {'0'..'9','+','-'}:
if ti < maxlen: if ti < maxlen:
t[ti] = s[i]; inc(ti) t[ti] = s[i]; inc(ti)

View file

@ -686,6 +686,7 @@ const
ERROR_FILE_NOT_FOUND* = 2 ERROR_FILE_NOT_FOUND* = 2
ERROR_PATH_NOT_FOUND* = 3 ERROR_PATH_NOT_FOUND* = 3
ERROR_ACCESS_DENIED* = 5 ERROR_ACCESS_DENIED* = 5
ERROR_NO_MORE_FILES* = 18
ERROR_HANDLE_EOF* = 38 ERROR_HANDLE_EOF* = 38
ERROR_BAD_ARGUMENTS* = 165 ERROR_BAD_ARGUMENTS* = 165

View file

@ -8,6 +8,17 @@
# #
## OpenSSL support ## OpenSSL support
##
## When OpenSSL is dynamically linked, the wrapper provides partial forward and backward
## compatibility for OpenSSL versions above and below 1.1.0
##
## OpenSSL can be also statically linked using dynlibOverride:ssl for OpenSSL >= 1.1.0
##
## Build and test examples:
##
## .. code-block::
## ./bin/nim c -d:ssl -p:. -r tests/untestable/tssl.nim
## ./bin/nim c -d:ssl -p:. --dynlibOverride:ssl --passL:-lcrypto --passL:-lssl -r tests/untestable/tssl.nim
{.deadCodeElim: on.} {.deadCodeElim: on.}
@ -25,8 +36,8 @@ when useWinVersion:
from winlean import SocketHandle from winlean import SocketHandle
else: else:
const const versions = "(.1.1|.38|.39|.41|.43|.10|.1.0.2|.1.0.1|.1.0.0|.0.9.9|.0.9.8|)"
versions = "(|.38|.39|.41|.43|.10|.1.0.2|.1.0.1|.1.0.0|.0.9.9|.0.9.8)"
when defined(macosx): when defined(macosx):
const const
DLLSSLName = "libssl" & versions & ".dylib" DLLSSLName = "libssl" & versions & ".dylib"
@ -140,6 +151,7 @@ const
SSL_OP_NO_SSLv2* = 0x01000000 SSL_OP_NO_SSLv2* = 0x01000000
SSL_OP_NO_SSLv3* = 0x02000000 SSL_OP_NO_SSLv3* = 0x02000000
SSL_OP_NO_TLSv1* = 0x04000000 SSL_OP_NO_TLSv1* = 0x04000000
SSL_OP_NO_TLSv1_1* = 0x08000000
SSL_OP_ALL* = 0x000FFFFF SSL_OP_ALL* = 0x000FFFFF
SSL_VERIFY_NONE* = 0x00000000 SSL_VERIFY_NONE* = 0x00000000
SSL_VERIFY_PEER* = 0x00000001 SSL_VERIFY_PEER* = 0x00000001
@ -191,16 +203,39 @@ const
proc TLSv1_method*(): PSSL_METHOD{.cdecl, dynlib: DLLSSLName, importc.} proc TLSv1_method*(): PSSL_METHOD{.cdecl, dynlib: DLLSSLName, importc.}
when compileOption("dynlibOverride", "ssl"): # TLS_method(), TLS_server_method(), TLS_client_method() are introduced in 1.1.0
proc SSL_library_init*(): cint {.cdecl, dynlib: DLLSSLName, importc, discardable.} # and support SSLv3, TLSv1, TLSv1.1 and TLSv1.2
proc SSL_load_error_strings*() {.cdecl, dynlib: DLLSSLName, importc.} # SSLv23_method(), SSLv23_server_method(), SSLv23_client_method() are removed in 1.1.0
proc SSLv23_client_method*(): PSSL_METHOD {.cdecl, dynlib: DLLSSLName, importc.}
proc SSLv23_method*(): PSSL_METHOD {.cdecl, dynlib: DLLSSLName, importc.} when compileOption("dynlibOverride", "ssl"):
# Static linking
proc OPENSSL_init_ssl*(opts: uint64, settings: uint8): cint {.cdecl, dynlib: DLLSSLName, importc, discardable.}
proc SSL_library_init*(): cint {.discardable.} =
## Initialize SSL using OPENSSL_init_ssl for OpenSSL >= 1.1.0
return OPENSSL_init_ssl(0.uint64, 0.uint8)
proc TLS_method*(): PSSL_METHOD {.cdecl, dynlib: DLLSSLName, importc.}
proc SSLv23_method*(): PSSL_METHOD =
TLS_method()
proc SSLv23_client_method*(): PSSL_METHOD {.cdecl, dynlib: DLLSSLName, importc.}
proc SSLv2_method*(): PSSL_METHOD {.cdecl, dynlib: DLLSSLName, importc.} proc SSLv2_method*(): PSSL_METHOD {.cdecl, dynlib: DLLSSLName, importc.}
proc SSLv3_method*(): PSSL_METHOD {.cdecl, dynlib: DLLSSLName, importc.} proc SSLv3_method*(): PSSL_METHOD {.cdecl, dynlib: DLLSSLName, importc.}
template OpenSSL_add_all_algorithms*() = discard template OpenSSL_add_all_algorithms*() = discard
proc OpenSSL_version_num(): culong {.cdecl, dynlib: DLLSSLName, importc.}
proc getOpenSSLVersion*(): culong =
## Return OpenSSL version as unsigned long
OpenSSL_version_num()
proc SSL_load_error_strings*() =
## Removed from OpenSSL 1.1.0
# This proc prevents breaking existing code calling SslLoadErrorStrings
# Static linking against OpenSSL < 1.1.0 is not supported
discard
else: else:
# Here we're trying to stay compatible with openssl 1.0.* and 1.1.*. Some # Here we're trying to stay compatible with openssl 1.0.* and 1.1.*. Some
# symbols are loaded dynamically and we don't use them if not found. # symbols are loaded dynamically and we don't use them if not found.
@ -223,38 +258,58 @@ else:
if not dl.isNil: if not dl.isNil:
result = symAddr(dl, name) result = symAddr(dl, name)
proc loadPSSLMethod(method1, method2: string): PSSL_METHOD =
## Load <method1> from OpenSSL if available, otherwise <method2>
let m1 = cast[proc(): PSSL_METHOD {.cdecl, gcsafe.}](sslSym(method1))
if not m1.isNil:
return m1()
cast[proc(): PSSL_METHOD {.cdecl, gcsafe.}](sslSym(method2))()
proc SSL_library_init*(): cint {.discardable.} = proc SSL_library_init*(): cint {.discardable.} =
let theProc = cast[proc(): cint {.cdecl.}](sslSym("SSL_library_init")) ## Initialize SSL using OPENSSL_init_ssl for OpenSSL >= 1.1.0 otherwise
if not theProc.isNil: result = theProc() ## SSL_library_init
let theProc = cast[proc(opts: uint64, settings: uint8): cint {.cdecl.}](sslSym("OPENSSL_init_ssl"))
if not theProc.isNil:
return theProc(0, 0)
let olderProc = cast[proc(): cint {.cdecl.}](sslSym("SSL_library_init"))
if not olderProc.isNil: result = olderProc()
proc SSL_load_error_strings*() = proc SSL_load_error_strings*() =
let theProc = cast[proc() {.cdecl.}](sslSym("SSL_load_error_strings")) let theProc = cast[proc() {.cdecl.}](sslSym("SSL_load_error_strings"))
if not theProc.isNil: theProc() if not theProc.isNil: theProc()
proc SSLv23_client_method*(): PSSL_METHOD = proc SSLv23_client_method*(): PSSL_METHOD =
let theProc = cast[proc(): PSSL_METHOD {.cdecl, gcsafe.}](sslSym("SSLv23_client_method")) loadPSSLMethod("SSLv23_client_method", "TLS_client_method")
if not theProc.isNil: result = theProc()
else: result = TLSv1_method()
proc SSLv23_method*(): PSSL_METHOD = proc SSLv23_method*(): PSSL_METHOD =
let theProc = cast[proc(): PSSL_METHOD {.cdecl, gcsafe.}](sslSym("SSLv23_method")) loadPSSLMethod("SSLv23_method", "TLS_method")
if not theProc.isNil: result = theProc()
else: result = TLSv1_method()
proc SSLv2_method*(): PSSL_METHOD = proc SSLv2_method*(): PSSL_METHOD =
let theProc = cast[proc(): PSSL_METHOD {.cdecl, gcsafe.}](sslSym("SSLv2_method")) loadPSSLMethod("SSLv2_method", "TLS_method")
if not theProc.isNil: result = theProc()
else: result = TLSv1_method()
proc SSLv3_method*(): PSSL_METHOD = proc SSLv3_method*(): PSSL_METHOD =
let theProc = cast[proc(): PSSL_METHOD {.cdecl, gcsafe.}](sslSym("SSLv3_method")) loadPSSLMethod("SSLv3_method", "TLS_method")
if not theProc.isNil: result = theProc()
else: result = TLSv1_method() proc TLS_method*(): PSSL_METHOD =
loadPSSLMethod("TLS_method", "SSLv23_method")
proc TLS_client_method*(): PSSL_METHOD =
loadPSSLMethod("TLS_client_method", "SSLv23_client_method")
proc TLS_server_method*(): PSSL_METHOD =
loadPSSLMethod("TLS_server_method", "SSLv23_server_method")
proc OpenSSL_add_all_algorithms*() = proc OpenSSL_add_all_algorithms*() =
let theProc = cast[proc() {.cdecl.}](sslSym("OPENSSL_add_all_algorithms_conf")) let theProc = cast[proc() {.cdecl.}](sslSym("OPENSSL_add_all_algorithms_conf"))
if not theProc.isNil: theProc() if not theProc.isNil: theProc()
proc getOpenSSLVersion*(): culong =
## Return OpenSSL version as unsigned long or 0 if not available
let theProc = cast[proc(): culong {.cdecl.}](sslSym("OpenSSL_version_num"))
result =
if theProc.isNil: 0.culong
else: theProc()
proc ERR_load_BIO_strings*(){.cdecl, dynlib: DLLUtilName, importc.} proc ERR_load_BIO_strings*(){.cdecl, dynlib: DLLUtilName, importc.}
proc SSL_new*(context: SslCtx): SslPtr{.cdecl, dynlib: DLLSSLName, importc.} proc SSL_new*(context: SslCtx): SslPtr{.cdecl, dynlib: DLLSSLName, importc.}

15
tests/async/t6100.nim Normal file
View file

@ -0,0 +1,15 @@
discard """
file: "t6100.nim"
exitcode: 0
output: "10000000"
"""
import asyncdispatch
let done = newFuture[int]()
done.complete(1)
proc asyncSum: Future[int] {.async.} =
for _ in 1..10_000_000:
result += await done
echo waitFor asyncSum()

View file

@ -1,61 +1,7 @@
discard """ discard """
exitcode: 0 exitcode: 0
disabled: "windows" disabled: "windows"
output: ''' output: "Matched"
b failure
Async traceback:
tasync_traceback.nim(97) tasync_traceback
asyncmacro.nim(395) a
asyncmacro.nim(34) a_continue
## Resumes an async procedure
tasync_traceback.nim(95) aIter
asyncmacro.nim(395) b
asyncmacro.nim(34) b_continue
## Resumes an async procedure
tasync_traceback.nim(92) bIter
#[
tasync_traceback.nim(97) tasync_traceback
asyncmacro.nim(395) a
asyncmacro.nim(43) a_continue
## Resumes an async procedure
asyncfutures.nim(211) callback=
asyncfutures.nim(190) addCallback
asyncfutures.nim(53) callSoon
asyncmacro.nim(34) a_continue
## Resumes an async procedure
asyncmacro.nim(0) aIter
asyncfutures.nim(304) read
]#
Exception message: b failure
Exception type:
bar failure
Async traceback:
tasync_traceback.nim(113) tasync_traceback
asyncdispatch.nim(1492) waitFor
asyncdispatch.nim(1496) poll
## Processes asynchronous completion events
asyncdispatch.nim(1262) runOnce
asyncdispatch.nim(183) processPendingCallbacks
## Executes pending callbacks
asyncmacro.nim(34) bar_continue
## Resumes an async procedure
tasync_traceback.nim(108) barIter
#[
tasync_traceback.nim(113) tasync_traceback
asyncdispatch.nim(1492) waitFor
asyncdispatch.nim(1496) poll
## Processes asynchronous completion events
asyncdispatch.nim(1262) runOnce
asyncdispatch.nim(183) processPendingCallbacks
## Executes pending callbacks
asyncmacro.nim(34) foo_continue
## Resumes an async procedure
asyncmacro.nim(0) fooIter
asyncfutures.nim(304) read
]#
Exception message: bar failure
Exception type:'''
""" """
import asyncdispatch import asyncdispatch
@ -87,6 +33,8 @@ import asyncdispatch
# tasync_traceback.nim(21) a # tasync_traceback.nim(21) a
# tasync_traceback.nim(18) b # tasync_traceback.nim(18) b
var result = ""
proc b(): Future[int] {.async.} = proc b(): Future[int] {.async.} =
if true: if true:
raise newException(OSError, "b failure") raise newException(OSError, "b failure")
@ -98,8 +46,8 @@ let aFut = a()
try: try:
discard waitFor aFut discard waitFor aFut
except Exception as exc: except Exception as exc:
echo exc.msg result.add(exc.msg & "\n")
echo() result.add("\n")
# From #6803 # From #6803
proc bar(): Future[string] {.async.} = proc bar(): Future[string] {.async.} =
@ -110,7 +58,69 @@ proc bar(): Future[string] {.async.} =
proc foo(): Future[string] {.async.} = return await bar() proc foo(): Future[string] {.async.} = return await bar()
try: try:
echo waitFor(foo()) result.add(waitFor(foo()) & "\n")
except Exception as exc: except Exception as exc:
echo exc.msg result.add(exc.msg & "\n")
echo() result.add("\n")
# Use re to parse the result
import re
const expected = """
b failure
Async traceback:
tasync_traceback\.nim\(\d+?\)\s+?tasync_traceback
asyncmacro\.nim\(\d+?\)\s+?a
asyncmacro\.nim\(\d+?\)\s+?a_continue
## Resumes an async procedure
tasync_traceback\.nim\(\d+?\)\s+?aIter
asyncmacro\.nim\(\d+?\)\s+?b
asyncmacro\.nim\(\d+?\)\s+?b_continue
## Resumes an async procedure
tasync_traceback\.nim\(\d+?\)\s+?bIter
#\[
tasync_traceback\.nim\(\d+?\)\s+?tasync_traceback
asyncmacro\.nim\(\d+?\)\s+?a
asyncmacro\.nim\(\d+?\)\s+?a_continue
## Resumes an async procedure
asyncmacro\.nim\(\d+?\)\s+?aIter
asyncfutures\.nim\(\d+?\)\s+?read
\]#
Exception message: b failure
Exception type:
bar failure
Async traceback:
tasync_traceback\.nim\(\d+?\)\s+?tasync_traceback
asyncdispatch\.nim\(\d+?\)\s+?waitFor
asyncdispatch\.nim\(\d+?\)\s+?poll
## Processes asynchronous completion events
asyncdispatch\.nim\(\d+?\)\s+?runOnce
asyncdispatch\.nim\(\d+?\)\s+?processPendingCallbacks
## Executes pending callbacks
asyncmacro\.nim\(\d+?\)\s+?bar_continue
## Resumes an async procedure
tasync_traceback\.nim\(\d+?\)\s+?barIter
#\[
tasync_traceback\.nim\(\d+?\)\s+?tasync_traceback
asyncdispatch\.nim\(\d+?\)\s+?waitFor
asyncdispatch\.nim\(\d+?\)\s+?poll
## Processes asynchronous completion events
asyncdispatch\.nim\(\d+?\)\s+?runOnce
asyncdispatch\.nim\(\d+?\)\s+?processPendingCallbacks
## Executes pending callbacks
asyncmacro\.nim\(\d+?\)\s+?foo_continue
## Resumes an async procedure
asyncmacro\.nim\(\d+?\)\s+?fooIter
asyncfutures\.nim\(\d+?\)\s+?read
\]#
Exception message: bar failure
Exception type:
"""
if result.match(re(expected)):
echo("Matched")
else:
echo("Not matched!")
echo()
echo(result)
quit(QuitFailure)

View file

@ -18,8 +18,8 @@ var fs = newFutureStream[int]()
proc alpha() {.async.} = proc alpha() {.async.} =
for i in 0 .. 5: for i in 0 .. 5:
await sleepAsync(1000)
await fs.write(i) await fs.write(i)
await sleepAsync(1000)
echo("Done") echo("Done")
fs.complete() fs.complete()

View file

@ -48,5 +48,11 @@ doAssert "2.71828182845904523536028747".parseFloat ==
2.71828182845904523536028747 2.71828182845904523536028747
doAssert 0.00097656250000000021684043449710088680149056017398834228515625 == doAssert 0.00097656250000000021684043449710088680149056017398834228515625 ==
"0.00097656250000000021684043449710088680149056017398834228515625".parseFloat "0.00097656250000000021684043449710088680149056017398834228515625".parseFloat
doAssert 0.00998333 == ".00998333".parseFloat
doAssert 0.00128333 == ".00128333".parseFloat
doAssert 999999999999999.0 == "999999999999999.0".parseFloat
doAssert 9999999999999999.0 == "9999999999999999.0".parseFloat
doAssert 0.999999999999999 == ".999999999999999".parseFloat
doAssert 0.9999999999999999 == ".9999999999999999".parseFloat
echo("passed all tests.") echo("passed all tests.")

View file

@ -15,7 +15,8 @@ discard """
(y: 678, x: 123) (y: 678, x: 123)
(y: 678, x: 123) (y: 678, x: 123)
(y: 0, x: 123) (y: 0, x: 123)
(y: 678, x: 123)''' (y: 678, x: 123)
(y: 123, x: 678)'''
""" """
type type
@ -75,3 +76,7 @@ when true:
echo b # (y: 0, x: 123) echo b # (y: 0, x: 123)
b=B(y: 678, x: 123) b=B(y: 678, x: 123)
echo b # (y: 678, x: 123) echo b # (y: 678, x: 123)
b=B(y: b.x, x: b.y)
echo b # (y: 123, x: 678)
GC_fullCollect()

View file

@ -1,3 +1,8 @@
discard """
output: '''42
Foo'''
"""
type TFoo{.exportc.} = object type TFoo{.exportc.} = object
x:int x:int
@ -48,3 +53,5 @@ type NamedGraphic = object of Graphic2
var ngr = NamedGraphic(kind: Koo, radius: 6.9, name: "Foo") var ngr = NamedGraphic(kind: Koo, radius: 6.9, name: "Foo")
echo ngr.name echo ngr.name
GC_fullCollect()

View file

@ -281,6 +281,30 @@ suite "ttimes":
test "parseTest": test "parseTest":
runTimezoneTests() runTimezoneTests()
test "dynamic timezone":
proc staticOffset(offset: int): Timezone =
proc zoneInfoFromTz(adjTime: Time): ZonedTime =
result.isDst = false
result.utcOffset = offset
result.adjTime = adjTime
proc zoneInfoFromUtc(time: Time): ZonedTime =
result.isDst = false
result.utcOffset = offset
result.adjTime = fromUnix(time.toUnix - offset)
result.name = ""
result.zoneInfoFromTz = zoneInfoFromTz
result.zoneInfoFromUtc = zoneInfoFromUtc
let tz = staticOffset(-9000)
let dt = initDateTime(1, mJan, 2000, 12, 00, 00, tz)
check dt.utcOffset == -9000
check dt.isDst == false
check $dt == "2000-01-01T12:00:00+02:30"
check $dt.utc == "2000-01-01T09:30:00+00:00"
check $dt.utc.inZone(tz) == $dt
test "isLeapYear": test "isLeapYear":
check isLeapYear(2016) check isLeapYear(2016)
check (not isLeapYear(2015)) check (not isLeapYear(2015))

36
tests/untestable/tssl.nim Normal file
View file

@ -0,0 +1,36 @@
#
# Nim - SSL integration tests
# (c) Copyright 2017 Nim contributors
#
# See the file "copying.txt", included in this
# distribution, for details about the copyright.
#
## Warning: this test performs external networking.
##
## Test with:
## ./bin/nim c -d:ssl -p:. -r tests/untestable/tssl.nim
## ./bin/nim c -d:ssl -p:. --dynlibOverride:ssl --passL:-lcrypto --passL:-lssl -r tests/untestable/tssl.nim
## The compilation is expected to succeed with any new/old version of OpenSSL,
## both with dynamic and static linking.
## The "howsmyssl" test is known to fail with OpenSSL < 1.1 due to insecure
## cypher suites being used.
import httpclient, os
from strutils import contains, toHex
from openssl import getOpenSSLVersion
when isMainModule:
echo "version: 0x" & $getOpenSSLVersion().toHex()
let client = newHttpClient()
# hacky SSL check
const url = "https://www.howsmyssl.com"
let report = client.getContent(url)
if not report.contains(">Probably Okay</span>"):
let fn = getTempDir() / "sslreport.html"
echo "SSL CHECK ERROR, see " & fn
writeFile(fn, report)
quit(1)
echo "done"