mirror of
https://github.com/nim-lang/Nim.git
synced 2026-01-02 03:02:31 +00:00
Merge branch 'devel' of github.com:nim-lang/Nim into devel
This commit is contained in:
@@ -48,3 +48,5 @@ script:
|
||||
- ./koch csource
|
||||
- ./koch nimsuggest
|
||||
# - nim c -r nimsuggest/tester
|
||||
- ( ! grep -F '.. code-block' -l -r --include '*.html' --exclude contributing.html --exclude docgen.html --exclude tut2.html )
|
||||
- ( ! grep -F '..code-block' -l -r --include '*.html' --exclude contributing.html --exclude docgen.html --exclude tut2.html )
|
||||
|
||||
27
changelog.md
27
changelog.md
@@ -102,10 +102,12 @@ This now needs to be written as:
|
||||
- Nim's ``rst2html`` command now supports the testing of code snippets via an RST
|
||||
extension that we called ``:test:``::
|
||||
|
||||
```rst
|
||||
.. code-block:: nim
|
||||
:test:
|
||||
# shows how the 'if' statement works
|
||||
if true: echo "yes"
|
||||
```
|
||||
- The ``[]`` proc for strings now raises an ``IndexError`` exception when
|
||||
the specified slice is out of bounds. See issue
|
||||
[#6223](https://github.com/nim-lang/Nim/issues/6223) for more details.
|
||||
@@ -130,7 +132,8 @@ This now needs to be written as:
|
||||
- The ``random`` procs in ``random.nim`` have all been deprecated. Instead use
|
||||
the new ``rand`` procs. The module now exports the state of the random
|
||||
number generator as type ``Rand`` so multiple threads can easily use their
|
||||
own random number generators that do not require locking.
|
||||
own random number generators that do not require locking. For more information
|
||||
about this rename see issue [#6934](https://github.com/nim-lang/Nim/issues/6934)
|
||||
- The compiler is now more consistent in its treatment of ambiguous symbols:
|
||||
Types that shadow procs and vice versa are marked as ambiguous (bug #6693).
|
||||
- ``yield`` (or ``await`` which is mapped to ``yield``) never worked reliably
|
||||
@@ -141,3 +144,25 @@ This now needs to be written as:
|
||||
- codegenDecl pragma now works for the JavaScript backend. It returns an empty string for
|
||||
function return type placeholders.
|
||||
- Asynchronous programming for the JavaScript backend using the `asyncjs` module.
|
||||
- Extra semantic checks for procs with noreturn pragma: return type is not allowed,
|
||||
statements after call to noreturn procs are no longer allowed.
|
||||
- Noreturn proc calls and raising exceptions branches are now skipped during common type
|
||||
deduction in if and case expressions. The following code snippets now compile:
|
||||
```nim
|
||||
import strutils
|
||||
let str = "Y"
|
||||
let a = case str:
|
||||
of "Y": true
|
||||
of "N": false
|
||||
else: raise newException(ValueError, "Invalid boolean")
|
||||
let b = case str:
|
||||
of nil, "": raise newException(ValueError, "Invalid boolean")
|
||||
elif str.startsWith("Y"): true
|
||||
elif str.startsWith("N"): false
|
||||
else: false
|
||||
let c = if str == "Y": true
|
||||
elif str == "N": false
|
||||
else:
|
||||
echo "invalid bool"
|
||||
quit("this is the end")
|
||||
```
|
||||
|
||||
@@ -26,7 +26,8 @@ type
|
||||
errAtPopWithoutPush, errEmptyAsm, errInvalidIndentation,
|
||||
errExceptionExpected, errExceptionAlreadyHandled,
|
||||
errYieldNotAllowedHere, errYieldNotAllowedInTryStmt,
|
||||
errInvalidNumberOfYieldExpr, errCannotReturnExpr, errAttemptToRedefine,
|
||||
errInvalidNumberOfYieldExpr, errCannotReturnExpr,
|
||||
errNoReturnWithReturnTypeNotAllowed, errAttemptToRedefine,
|
||||
errStmtInvalidAfterReturn, errStmtExpected, errInvalidLabel,
|
||||
errInvalidCmdLineOption, errCmdLineArgExpected, errCmdLineNoArgExpected,
|
||||
errInvalidVarSubstitution, errUnknownVar, errUnknownCcompiler,
|
||||
@@ -179,8 +180,9 @@ const
|
||||
errYieldNotAllowedInTryStmt: "'yield' cannot be used within 'try' in a non-inlined iterator",
|
||||
errInvalidNumberOfYieldExpr: "invalid number of \'yield\' expressions",
|
||||
errCannotReturnExpr: "current routine cannot return an expression",
|
||||
errNoReturnWithReturnTypeNotAllowed: "routines with NoReturn pragma are not allowed to have return type",
|
||||
errAttemptToRedefine: "redefinition of \'$1\'",
|
||||
errStmtInvalidAfterReturn: "statement not allowed after \'return\', \'break\', \'raise\' or \'continue'",
|
||||
errStmtInvalidAfterReturn: "statement not allowed after \'return\', \'break\', \'raise\', \'continue\' or proc call with noreturn pragma",
|
||||
errStmtExpected: "statement expected",
|
||||
errInvalidLabel: "\'$1\' is no label",
|
||||
errInvalidCmdLineOption: "invalid command line option: \'$1\'",
|
||||
|
||||
@@ -771,6 +771,8 @@ proc singlePragma(c: PContext, sym: PSym, n: PNode, i: int,
|
||||
of wNoreturn:
|
||||
noVal(it)
|
||||
incl(sym.flags, sfNoReturn)
|
||||
if sym.typ[0] != nil:
|
||||
localError(sym.ast[paramsPos][0].info, errNoReturnWithReturnTypeNotAllowed)
|
||||
of wDynlib:
|
||||
processDynLib(c, it, sym)
|
||||
of wCompilerProc, wCore:
|
||||
|
||||
@@ -165,6 +165,19 @@ proc commonType*(x, y: PType): PType =
|
||||
result = newType(k, r.owner)
|
||||
result.addSonSkipIntLit(r)
|
||||
|
||||
proc endsInNoReturn(n: PNode): bool =
|
||||
# check if expr ends in raise exception or call of noreturn proc
|
||||
var it = n
|
||||
while it.kind in {nkStmtList, nkStmtListExpr} and it.len > 0:
|
||||
it = it.lastSon
|
||||
result = it.kind == nkRaiseStmt or
|
||||
it.kind in nkCallKinds and it[0].kind == nkSym and sfNoReturn in it[0].sym.flags
|
||||
|
||||
proc commonType*(x: PType, y: PNode): PType =
|
||||
# ignore exception raising branches in case/if expressions
|
||||
if endsInNoReturn(y): return x
|
||||
commonType(x, y.typ)
|
||||
|
||||
proc newSymS(kind: TSymKind, n: PNode, c: PContext): PSym =
|
||||
result = newSym(kind, considerQuotedIdent(n), getCurrOwner(c), n.info)
|
||||
when defined(nimsuggest):
|
||||
|
||||
@@ -165,14 +165,14 @@ proc semIf(c: PContext, n: PNode): PNode =
|
||||
it.sons[0] = forceBool(c, semExprWithType(c, it.sons[0]))
|
||||
when not newScopeForIf: openScope(c)
|
||||
it.sons[1] = semExprBranch(c, it.sons[1])
|
||||
typ = commonType(typ, it.sons[1].typ)
|
||||
typ = commonType(typ, it.sons[1])
|
||||
closeScope(c)
|
||||
elif it.len == 1:
|
||||
hasElse = true
|
||||
it.sons[0] = semExprBranchScope(c, it.sons[0])
|
||||
typ = commonType(typ, it.sons[0].typ)
|
||||
typ = commonType(typ, it.sons[0])
|
||||
else: illFormedAst(it)
|
||||
if isEmptyType(typ) or typ.kind == tyNil or not hasElse:
|
||||
if isEmptyType(typ) or typ.kind in {tyNil, tyExpr} or not hasElse:
|
||||
for it in n: discardCheck(c, it.lastSon)
|
||||
result.kind = nkIfStmt
|
||||
# propagate any enforced VoidContext:
|
||||
@@ -180,7 +180,8 @@ proc semIf(c: PContext, n: PNode): PNode =
|
||||
else:
|
||||
for it in n:
|
||||
let j = it.len-1
|
||||
it.sons[j] = fitNode(c, typ, it.sons[j], it.sons[j].info)
|
||||
if not endsInNoReturn(it.sons[j]):
|
||||
it.sons[j] = fitNode(c, typ, it.sons[j], it.sons[j].info)
|
||||
result.kind = nkIfExpr
|
||||
result.typ = typ
|
||||
|
||||
@@ -213,7 +214,7 @@ proc semCase(c: PContext, n: PNode): PNode =
|
||||
semCaseBranch(c, n, x, i, covered)
|
||||
var last = sonsLen(x)-1
|
||||
x.sons[last] = semExprBranchScope(c, x.sons[last])
|
||||
typ = commonType(typ, x.sons[last].typ)
|
||||
typ = commonType(typ, x.sons[last])
|
||||
of nkElifBranch:
|
||||
chckCovered = false
|
||||
checkSonsLen(x, 2)
|
||||
@@ -221,13 +222,13 @@ proc semCase(c: PContext, n: PNode): PNode =
|
||||
x.sons[0] = forceBool(c, semExprWithType(c, x.sons[0]))
|
||||
when not newScopeForIf: openScope(c)
|
||||
x.sons[1] = semExprBranch(c, x.sons[1])
|
||||
typ = commonType(typ, x.sons[1].typ)
|
||||
typ = commonType(typ, x.sons[1])
|
||||
closeScope(c)
|
||||
of nkElse:
|
||||
chckCovered = false
|
||||
checkSonsLen(x, 1)
|
||||
x.sons[0] = semExprBranchScope(c, x.sons[0])
|
||||
typ = commonType(typ, x.sons[0].typ)
|
||||
typ = commonType(typ, x.sons[0])
|
||||
hasElse = true
|
||||
else:
|
||||
illFormedAst(x)
|
||||
@@ -237,7 +238,7 @@ proc semCase(c: PContext, n: PNode): PNode =
|
||||
else:
|
||||
localError(n.info, errNotAllCasesCovered)
|
||||
closeScope(c)
|
||||
if isEmptyType(typ) or typ.kind == tyNil or not hasElse:
|
||||
if isEmptyType(typ) or typ.kind in {tyNil, tyExpr} or not hasElse:
|
||||
for i in 1..n.len-1: discardCheck(c, n.sons[i].lastSon)
|
||||
# propagate any enforced VoidContext:
|
||||
if typ == enforceVoidContext:
|
||||
@@ -246,7 +247,8 @@ proc semCase(c: PContext, n: PNode): PNode =
|
||||
for i in 1..n.len-1:
|
||||
var it = n.sons[i]
|
||||
let j = it.len-1
|
||||
it.sons[j] = fitNode(c, typ, it.sons[j], it.sons[j].info)
|
||||
if not endsInNoReturn(it.sons[j]):
|
||||
it.sons[j] = fitNode(c, typ, it.sons[j], it.sons[j].info)
|
||||
result.typ = typ
|
||||
|
||||
proc semTry(c: PContext, n: PNode): PNode =
|
||||
@@ -1851,8 +1853,8 @@ proc semStmtList(c: PContext, n: PNode, flags: TExprFlags): PNode =
|
||||
else:
|
||||
n.typ = n.sons[i].typ
|
||||
if not isEmptyType(n.typ): n.kind = nkStmtListExpr
|
||||
case n.sons[i].kind
|
||||
of LastBlockStmts:
|
||||
if n.sons[i].kind in LastBlockStmts or
|
||||
n.sons[i].kind in nkCallKinds and n.sons[i][0].kind == nkSym and sfNoReturn in n.sons[i][0].sym.flags:
|
||||
for j in countup(i + 1, length - 1):
|
||||
case n.sons[j].kind
|
||||
of nkPragma, nkCommentStmt, nkNilLit, nkEmpty, nkBlockExpr,
|
||||
|
||||
@@ -41,7 +41,8 @@ These integer types are pre-defined:
|
||||
``int``
|
||||
the generic signed integer type; its size is platform dependent and has the
|
||||
same size as a pointer. This type should be used in general. An integer
|
||||
literal that has no type suffix is of this type.
|
||||
literal that has no type suffix is of this type if it is in the range
|
||||
``low(int32)..high(int32)`` otherwise the literal's type is ``int64``.
|
||||
|
||||
intXX
|
||||
additional signed integer types of XX bits use this naming scheme
|
||||
|
||||
@@ -1234,7 +1234,7 @@ else:
|
||||
processBasicCallbacks(fd, writeList)
|
||||
result = true
|
||||
|
||||
if Event.User in events or events == {Event.Error}:
|
||||
if Event.User in events:
|
||||
processBasicCallbacks(fd, readList)
|
||||
custom = true
|
||||
if rLength == 0:
|
||||
|
||||
@@ -21,13 +21,41 @@
|
||||
## ``nim c -r <testfile.nim>`` exits with 0 or 1
|
||||
##
|
||||
## Running a single test
|
||||
## ---------------------
|
||||
## =====================
|
||||
##
|
||||
## Simply specify the test name as a command line argument.
|
||||
## Specify the test name as a command line argument.
|
||||
##
|
||||
## .. code::
|
||||
##
|
||||
## nim c -r test "my super awesome test name"
|
||||
## nim c -r test "my test name" "another test"
|
||||
##
|
||||
## Multiple arguments can be used.
|
||||
##
|
||||
## Running a single test suite
|
||||
## ===========================
|
||||
##
|
||||
## Specify the suite name delimited by ``"::"``.
|
||||
##
|
||||
## .. code::
|
||||
##
|
||||
## nim c -r test "my test name::"
|
||||
##
|
||||
## Selecting tests by pattern
|
||||
## ==========================
|
||||
##
|
||||
## A single ``"*"`` can be used for globbing.
|
||||
##
|
||||
## Delimit the end of a suite name with ``"::"``.
|
||||
##
|
||||
## Tests matching **any** of the arguments are executed.
|
||||
##
|
||||
## .. code::
|
||||
##
|
||||
## nim c -r test fast_suite::mytest1 fast_suite::mytest2
|
||||
## nim c -r test "fast_suite::mytest*"
|
||||
## nim c -r test "auth*::" "crypto::hashing*"
|
||||
## # Run suites starting with 'bug #' and standalone tests starting with '#'
|
||||
## nim c -r test 'bug #*::' '::#*'
|
||||
##
|
||||
## Example
|
||||
## -------
|
||||
@@ -121,7 +149,7 @@ var
|
||||
|
||||
checkpoints {.threadvar.}: seq[string]
|
||||
formatters {.threadvar.}: seq[OutputFormatter]
|
||||
testsToRun {.threadvar.}: HashSet[string]
|
||||
testsFilters {.threadvar.}: HashSet[string]
|
||||
|
||||
when declared(stdout):
|
||||
abortOnError = existsEnv("NIMTEST_ABORT_ON_ERROR")
|
||||
@@ -300,22 +328,63 @@ method testEnded*(formatter: JUnitOutputFormatter, testResult: TestResult) =
|
||||
method suiteEnded*(formatter: JUnitOutputFormatter) =
|
||||
formatter.stream.writeLine("\t</testsuite>")
|
||||
|
||||
proc shouldRun(testName: string): bool =
|
||||
if testsToRun.len == 0:
|
||||
proc glob(matcher, filter: string): bool =
|
||||
## Globbing using a single `*`. Empty `filter` matches everything.
|
||||
if filter.len == 0:
|
||||
return true
|
||||
|
||||
result = testName in testsToRun
|
||||
if not filter.contains('*'):
|
||||
return matcher == filter
|
||||
|
||||
let beforeAndAfter = filter.split('*', maxsplit=1)
|
||||
if beforeAndAfter.len == 1:
|
||||
# "foo*"
|
||||
return matcher.startswith(beforeAndAfter[0])
|
||||
|
||||
if matcher.len < filter.len - 1:
|
||||
return false # "12345" should not match "123*345"
|
||||
|
||||
return matcher.startsWith(beforeAndAfter[0]) and matcher.endsWith(beforeAndAfter[1])
|
||||
|
||||
proc matchFilter(suiteName, testName, filter: string): bool =
|
||||
if filter == "":
|
||||
return true
|
||||
if testName == filter:
|
||||
# corner case for tests containing "::" in their name
|
||||
return true
|
||||
let suiteAndTestFilters = filter.split("::", maxsplit=1)
|
||||
|
||||
if suiteAndTestFilters.len == 1:
|
||||
# no suite specified
|
||||
let test_f = suiteAndTestFilters[0]
|
||||
return glob(testName, test_f)
|
||||
|
||||
return glob(suiteName, suiteAndTestFilters[0]) and glob(testName, suiteAndTestFilters[1])
|
||||
|
||||
when defined(testing): export matchFilter
|
||||
|
||||
proc shouldRun(currentSuiteName, testName: string): bool =
|
||||
## Check if a test should be run by matching suiteName and testName against
|
||||
## test filters.
|
||||
if testsFilters.len == 0:
|
||||
return true
|
||||
|
||||
for f in testsFilters:
|
||||
if matchFilter(currentSuiteName, testName, f):
|
||||
return true
|
||||
|
||||
return false
|
||||
|
||||
proc ensureInitialized() =
|
||||
if formatters == nil:
|
||||
formatters = @[OutputFormatter(defaultConsoleFormatter())]
|
||||
|
||||
if not testsToRun.isValid:
|
||||
testsToRun.init()
|
||||
if not testsFilters.isValid:
|
||||
testsFilters.init()
|
||||
when declared(paramCount):
|
||||
# Read tests to run from the command line.
|
||||
for i in 1 .. paramCount():
|
||||
testsToRun.incl(paramStr(i))
|
||||
testsFilters.incl(paramStr(i))
|
||||
|
||||
# These two procs are added as workarounds for
|
||||
# https://github.com/nim-lang/Nim/issues/5549
|
||||
@@ -395,7 +464,7 @@ template test*(name, body) {.dirty.} =
|
||||
|
||||
ensureInitialized()
|
||||
|
||||
if shouldRun(name):
|
||||
if shouldRun(when declared(testSuiteName): testSuiteName else: "", name):
|
||||
checkpoints = @[]
|
||||
var testStatusIMPL {.inject.} = OK
|
||||
|
||||
|
||||
@@ -2916,7 +2916,10 @@ when not defined(JS): #and not defined(nimscript):
|
||||
elif x > y: result = 1
|
||||
else: result = 0
|
||||
else:
|
||||
result = int(c_strcmp(x, y))
|
||||
let minlen = min(x.len, y.len)
|
||||
result = int(c_memcmp(x.cstring, y.cstring, minlen.csize))
|
||||
if result == 0:
|
||||
result = x.len - y.len
|
||||
|
||||
when defined(nimscript):
|
||||
proc readFile*(filename: string): string {.tags: [ReadIOEffect], benign.}
|
||||
|
||||
@@ -63,7 +63,6 @@ proc chckObj(obj, subclass: PNimType) {.compilerproc.} =
|
||||
while x != subclass:
|
||||
if x == nil:
|
||||
sysFatal(ObjectConversionError, "invalid object conversion")
|
||||
break
|
||||
x = x.base
|
||||
|
||||
proc chckObjAsgn(a, b: PNimType) {.compilerproc, inline.} =
|
||||
|
||||
@@ -24,10 +24,10 @@ proc cmpStrings(a, b: NimString): int {.inline, compilerProc.} =
|
||||
if a == b: return 0
|
||||
if a == nil: return -1
|
||||
if b == nil: return 1
|
||||
when defined(nimNoArrayToCstringConversion):
|
||||
return c_strcmp(addr a.data, addr b.data)
|
||||
else:
|
||||
return c_strcmp(a.data, b.data)
|
||||
let minlen = min(a.len, b.len)
|
||||
result = c_memcmp(addr a.data, addr b.data, minlen.csize)
|
||||
if result == 0:
|
||||
result = a.len - b.len
|
||||
|
||||
proc eqStrings(a, b: NimString): bool {.inline, compilerProc.} =
|
||||
if a == b: return true
|
||||
|
||||
@@ -36,5 +36,64 @@ var z = case i
|
||||
echo z
|
||||
#OUT ayyy
|
||||
|
||||
let str1 = "Y"
|
||||
let str2 = "NN"
|
||||
let a = case str1:
|
||||
of "Y": true
|
||||
of "N": false
|
||||
else:
|
||||
echo "no good"
|
||||
quit("quiting")
|
||||
|
||||
let b = case str2:
|
||||
of nil, "": raise newException(ValueError, "Invalid boolean")
|
||||
elif str2[0] == 'Y': true
|
||||
elif str2[0] == 'N': false
|
||||
else: "error".quit(2)
|
||||
|
||||
doAssert(a == true)
|
||||
doAssert(b == false)
|
||||
|
||||
var bb: bool
|
||||
doassert(not compiles(
|
||||
bb = case str2:
|
||||
of nil, "": raise newException(ValueError, "Invalid boolean")
|
||||
elif str.startsWith("Y"): true
|
||||
elif str.startsWith("N"): false
|
||||
))
|
||||
|
||||
doassert(not compiles(
|
||||
bb = case str2:
|
||||
of "Y": true
|
||||
of "N": false
|
||||
))
|
||||
|
||||
doassert(not compiles(
|
||||
bb = case str2:
|
||||
of "Y": true
|
||||
of "N": raise newException(ValueError, "N not allowed")
|
||||
))
|
||||
|
||||
doassert(not compiles(
|
||||
bb = case str2:
|
||||
of "Y": raise newException(ValueError, "Invalid Y")
|
||||
else: raise newException(ValueError, "Invalid N")
|
||||
))
|
||||
|
||||
|
||||
doassert(not compiles(
|
||||
bb = case str2:
|
||||
of "Y":
|
||||
raise newException(ValueError, "Invalid Y")
|
||||
true
|
||||
else: raise newException(ValueError, "Invalid")
|
||||
))
|
||||
|
||||
|
||||
doassert(not compiles(
|
||||
bb = case str2:
|
||||
of "Y":
|
||||
"invalid Y".quit(3)
|
||||
true
|
||||
else: raise newException(ValueError, "Invalid")
|
||||
))
|
||||
22
tests/pragmas/tnoreturn.nim
Normal file
22
tests/pragmas/tnoreturn.nim
Normal file
@@ -0,0 +1,22 @@
|
||||
discard """
|
||||
ccodeCheck: "\\i @'__attribute__((noreturn))' .*"
|
||||
"""
|
||||
|
||||
proc noret1*(i: int) {.noreturn.} =
|
||||
echo i
|
||||
|
||||
|
||||
proc noret2*(i: int): void {.noreturn.} =
|
||||
echo i
|
||||
|
||||
var p {.used.}: proc(i: int): int
|
||||
doAssert(not compiles(
|
||||
p = proc(i: int): int {.noreturn.} = i # noreturn lambda returns int
|
||||
))
|
||||
|
||||
|
||||
doAssert(not compiles(
|
||||
block:
|
||||
noret1(5)
|
||||
echo 1 # statement after noreturn
|
||||
))
|
||||
@@ -56,4 +56,24 @@ proc test_string_slice() =
|
||||
|
||||
echo("OK")
|
||||
|
||||
proc test_string_cmp() =
|
||||
let world = "hello\0world"
|
||||
let earth = "hello\0earth"
|
||||
let short = "hello\0"
|
||||
let hello = "hello"
|
||||
let goodbye = "goodbye"
|
||||
|
||||
doAssert world == world
|
||||
doAssert world != earth
|
||||
doAssert world != short
|
||||
doAssert world != hello
|
||||
doAssert world != goodbye
|
||||
|
||||
doAssert cmp(world, world) == 0
|
||||
doAssert cmp(world, earth) > 0
|
||||
doAssert cmp(world, short) > 0
|
||||
doAssert cmp(world, hello) > 0
|
||||
doAssert cmp(world, goodbye) > 0
|
||||
|
||||
test_string_slice()
|
||||
test_string_cmp()
|
||||
|
||||
@@ -13,6 +13,8 @@ discard """
|
||||
|
||||
[Suite] bug #5784
|
||||
|
||||
[Suite] test name filtering
|
||||
|
||||
'''
|
||||
"""
|
||||
|
||||
@@ -120,3 +122,39 @@ suite "bug #5784":
|
||||
field: int
|
||||
var obj: Obj
|
||||
check obj.isNil or obj.field == 0
|
||||
|
||||
when defined(testing):
|
||||
suite "test name filtering":
|
||||
test "test name":
|
||||
check matchFilter("suite1", "foo", "")
|
||||
check matchFilter("suite1", "foo", "foo")
|
||||
check matchFilter("suite1", "foo", "::")
|
||||
check matchFilter("suite1", "foo", "*")
|
||||
check matchFilter("suite1", "foo", "::foo")
|
||||
check matchFilter("suite1", "::foo", "::foo")
|
||||
|
||||
test "test name - glob":
|
||||
check matchFilter("suite1", "foo", "f*")
|
||||
check matchFilter("suite1", "foo", "*oo")
|
||||
check matchFilter("suite1", "12345", "12*345")
|
||||
check matchFilter("suite1", "q*wefoo", "q*wefoo")
|
||||
check false == matchFilter("suite1", "foo", "::x")
|
||||
check false == matchFilter("suite1", "foo", "::x*")
|
||||
check false == matchFilter("suite1", "foo", "::*x")
|
||||
# overlap
|
||||
check false == matchFilter("suite1", "12345", "123*345")
|
||||
check matchFilter("suite1", "ab*c::d*e::f", "ab*c::d*e::f")
|
||||
|
||||
test "suite name":
|
||||
check matchFilter("suite1", "foo", "suite1::")
|
||||
check false == matchFilter("suite1", "foo", "suite2::")
|
||||
check matchFilter("suite1", "qwe::foo", "qwe::foo")
|
||||
check matchFilter("suite1", "qwe::foo", "suite1::qwe::foo")
|
||||
|
||||
test "suite name - glob":
|
||||
check matchFilter("suite1", "foo", "::*")
|
||||
check matchFilter("suite1", "foo", "*::*")
|
||||
check matchFilter("suite1", "foo", "*::foo")
|
||||
check false == matchFilter("suite1", "foo", "*ite2::")
|
||||
check matchFilter("suite1", "q**we::foo", "q**we::foo")
|
||||
check matchFilter("suite1", "a::b*c::d*e", "a::b*c::d*e")
|
||||
|
||||
4
todo.txt
4
todo.txt
@@ -1,8 +1,6 @@
|
||||
version 1.0 battle plan
|
||||
=======================
|
||||
|
||||
- introduce ``nkStmtListExpr`` for template/macro invokations to produce
|
||||
better stack traces
|
||||
- let 'doAssert' analyse the expressions and produce more helpful output
|
||||
- fix "high priority" bugs
|
||||
- try to fix as many compiler crashes as reasonable
|
||||
@@ -11,6 +9,8 @@ version 1.0 battle plan
|
||||
Not critical for 1.0
|
||||
====================
|
||||
|
||||
- introduce ``nkStmtListExpr`` for template/macro invokations to produce
|
||||
better stack traces
|
||||
- make 'break' not leave named blocks
|
||||
- make FlowVar compatible to Futures
|
||||
- make 'not nil' the default (produce warnings instead of errors for
|
||||
|
||||
Reference in New Issue
Block a user