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

This commit is contained in:
Araq 2017-11-21 01:42:58 +01:00
commit 1bbab827c4
115 changed files with 1279 additions and 1542 deletions

View file

@ -40,8 +40,7 @@ proc testVarargs(x, y, z: int): seq[int] =
result = waitFor all(a, b, c)
suite "tasyncall":
test "testFuturesWithValue":
block:
let
startTime = cpuTime()
results = testFuturesWithValue(42)
@ -51,14 +50,14 @@ suite "tasyncall":
doAssert execTime * 1000 < taskCount * sleepDuration
doAssert results == expected
test "testFuturesWithoutValues":
block:
let startTime = cpuTime()
testFuturesWithoutValues()
let execTime = cpuTime() - startTime
doAssert execTime * 1000 < taskCount * sleepDuration
test "testVarargs":
block:
let
startTime = cpuTime()
results = testVarargs(1, 2, 3)
@ -68,7 +67,7 @@ suite "tasyncall":
doAssert execTime * 100 < taskCount * sleepDuration
doAssert results == expected
test "all on seq[Future]":
block:
let
noIntFuturesFut = all(newSeq[Future[int]]())
noVoidFuturesFut = all(newSeq[Future[void]]())

View file

@ -3,11 +3,22 @@ discard """
output: "Finished"
"""
import asyncdispatch
import asyncdispatch, asyncnet
proc createServer(port: Port) {.async.} =
var server = newAsyncSocket()
server.setSockOpt(OptReuseAddr, true)
bindAddr(server, port)
server.listen()
while true:
let client = await server.accept()
discard await client.recvLine()
asyncCheck createServer(10335.Port)
proc f(): Future[void] {.async.} =
let s = newAsyncNativeSocket()
await s.connect("example.com", 80.Port)
await s.connect("localhost", 10335.Port)
await s.send("123")
echo "Finished"

View file

@ -86,7 +86,7 @@ proc readMessages(server: AsyncFD) {.async.} =
size = 0
var grammString = $cstring(addr buffer)
if grammString.startswith("Message ") and
saddr.sin_addr.s_addr == 0x100007F:
saddr.sin_addr.s_addr == nativesockets.ntohl(INADDR_LOOPBACK.uint32):
await sendTo(server, addr grammString[0], len(grammString),
cast[ptr SockAddr](addr saddr), slen)
inc(msgCount)

View file

@ -0,0 +1,33 @@
discard """
output: '''@[0, 4, 9, 1, 3, 2]
@[0, 1, 2, 3, 9]'''
"""
# bug #6724
import algorithm
type
Bar = object
bar: ref seq[int]
Foo = ref Bar
proc test(x: ref Foo) =
x.bar[].del(1)
x.bar[].sort(cmp)
proc main() =
var foo: ref Foo
new(foo)
var s = @[0, 4, 9, 1, 3, 2]
var sr: ref seq[int]
new(sr)
sr[] = s
foo[] = Foo(bar: sr)
echo($foo.bar[])
test(foo)
echo($foo.bar[])
main()

View file

@ -1,5 +1,5 @@
discard """
cmd: "nim cpp $file"
targets: "cpp"
output: "hello"
"""

10
tests/cpp/tcasts.nim Normal file
View file

@ -0,0 +1,10 @@
discard """
cmd: "nim cpp $file"
output: ""
"""
block: #5979
var a = 'a'
var p: pointer = cast[pointer](a)
var c = cast[char](p)
doAssert(c == 'a')

View file

@ -1,5 +1,5 @@
discard """
cmd: "nim cpp $file"
targets: "cpp"
output: '''
cat
cat

View file

@ -1,5 +1,5 @@
discard """
cmd: "nim cpp $file"
targets: "cpp"
output: '''foo
bar
Need odd and >= 3 digits##

View file

@ -1,5 +1,5 @@
discard """
cmd: "nim cpp $file"
targets: "cpp"
output: ''''''
disabled: true
"""

View file

@ -1,4 +1,5 @@
discard """
targets: "cpp"
cmd: "nim cpp --threads:on $file"
"""

View file

@ -1,5 +1,5 @@
discard """
cmd: "nim cpp $file"
targets: "cpp"
output: '''6.0'''
"""

View file

@ -1,5 +1,5 @@
discard """
cmd: "nim cpp $file"
targets: "cpp"
output: '''int
float'''
"""

View file

@ -1,5 +1,5 @@
discard """
cmd: "nim cpp $file"
targets: "cpp"
output: '''Hello world'''
"""

View file

@ -1,5 +1,5 @@
discard """
cmd: "nim cpp $file"
targets: "cpp"
"""
{.emit: """

View file

@ -1,5 +1,5 @@
discard """
cmd: "nim cpp $file"
targets: "cpp"
"""
import nativesockets

View file

@ -1,3 +1,6 @@
discard """
targets: "cpp"
"""
# bug #2259
type Mat4f* = array[0..15, float]

View file

@ -1,5 +1,5 @@
discard """
cmd: "nim cpp $file"
targets: "cpp"
"""
import tables, lists

View file

@ -1,5 +1,5 @@
discard """
cmd: "nim cpp $file"
targets: "cpp"
output: "42"
"""

View file

@ -1,3 +1,7 @@
discard """
targets: "cpp"
"""
type
Map {.importcpp: "std::map", header: "<map>".} [T,U] = object

View file

@ -1,4 +1,5 @@
discard """
targets: "cpp"
cmd: "nim cpp --hints:on --threads:on $options $file"
"""

View file

@ -1,6 +1,6 @@
discard """
targets: "cpp"
output: '''100'''
cmd: "nim cpp $file"
"""
import typeinfo

View file

@ -1,5 +1,5 @@
discard """
cmd: "nim cpp $file"
targets: "cpp"
"""
# bug #2841
import typeinfo

View file

@ -1,5 +1,5 @@
discard """
cmd: "nim cpp $file"
targets: "cpp"
"""
{.emit: """

View file

@ -1,7 +1,7 @@
discard """
targets: "cpp"
output: '''(x: 1.0)
(x: 0.0)'''
cmd: "nim cpp $file"
disabled: "true"
"""

View file

@ -0,0 +1,23 @@
discard """
errormsg: '''got (tuple of (type NimEdAppWindow, int))'''
line: 22
nimout: '''got (tuple of (type NimEdAppWindow, int))
but expected one of:
template xxx(tn: typedesc; i: int)'''
"""
type
NimEdAppWindow = ptr NimEdAppWindowObj
NimEdAppWindowObj = object
i: int
template gDefineTypeExtended*(tn: typeDesc) =
discard
gDefineTypeExtended (NimEdAppWindow)
template xxx*(tn: typeDesc, i: int) =
discard
xxx (NimEdAppWindow, 0)
# bug #6776

View file

@ -5,7 +5,8 @@ discard """
6
abcdefghijklmnopqrstuvwxyz
145 23
3'''
3
2'''
"""
import strutils
@ -122,3 +123,21 @@ var testTry =
PFooBase(field: 5)
echo(testTry.field)
# bug #6166
proc quo(op: proc (x: int): bool): int =
result =
if op(3):
2
else:
0
echo(
if true:
quo do (a: int) -> bool:
a mod 2 != 0
else:
quo do (a: int) -> bool:
a mod 3 != 0
)

View file

@ -1,5 +1,6 @@
discard """
exitcode: 0
disabled: '''true'''
"""
import moverloading_typedesc
import tables

View file

@ -1,71 +0,0 @@
discard """
file: "tromans.nim"
output: "success"
"""
import
strutils
## Convert an integer to a Roman numeral
# See http://en.wikipedia.org/wiki/Roman_numerals for reference
proc raiseInvalidValue(msg: string) {.noreturn.} =
# Yes, we really need a shorthand for this code...
var e: ref EInvalidValue
new(e)
e.msg = msg
raise e
# I should use a class, perhaps.
# --> No. Why introduce additional state into such a simple and nice
# interface? State is evil. :D
proc RomanToDecimal(romanVal: string): int =
result = 0
var prevVal = 0
for i in countdown(romanVal.len - 1, 0):
var val = 0
case romanVal[i]
of 'I', 'i': val = 1
of 'V', 'v': val = 5
of 'X', 'x': val = 10
of 'L', 'l': val = 50
of 'C', 'c': val = 100
of 'D', 'd': val = 500
of 'M', 'm': val = 1000
else: raiseInvalidValue("Incorrect character in roman numeral! (" &
$romanVal[i] & ")")
if val >= prevVal:
inc(result, val)
else:
dec(result, val)
prevVal = val
proc DecimalToRoman(decValParam: int): string =
# Apparently numbers cannot be above 4000
# Well, they can be (using overbar or parenthesis notation)
# but I see little interest (beside coding challenge) in coding them as
# we rarely use huge Roman numeral.
const romanComposites = [
("M", 1000), ("CM", 900),
("D", 500), ("CD", 400), ("C", 100),
("XC", 90), ("L", 50), ("XL", 40), ("X", 10), ("IX", 9),
("V", 5), ("IV", 4), ("I", 1)]
if decValParam < 1 or decValParam > 3999:
raiseInvalidValue("number not representable")
result = ""
var decVal = decValParam
for key, val in items(romanComposites):
while decVal >= val:
dec(decVal, val)
result.add(key)
for i in 1..100:
if RomanToDecimal(DecimalToRoman(i)) != i: quit "BUG"
for i in items([1238, 1777, 3830, 2401, 379, 33, 940, 3973]):
if RomanToDecimal(DecimalToRoman(i)) != i: quit "BUG"
echo "success" #OUT success

View file

@ -0,0 +1,47 @@
discard """
output: '''
9.0'''
"""
### bug #6773
{.emit: """ /*INCLUDESECTION*/
typedef double cimported;
cimported set1_imported(double x) {
return x;
}
"""}
type vfloat{.importc: "cimported".} = object
proc set1(a: float): vfloat {.importc: "set1_imported".}
converter scalar_to_vector(x: float): vfloat =
set1(x)
proc sqrt(x: vfloat): vfloat =
x
proc pow(x, y: vfloat): vfloat =
y
proc `^`(x: vfloat, exp: static[int]): vfloat =
when exp == 0:
1.0
else:
x
proc `^`(x: vfloat, exp: static[float]): vfloat =
when exp == 0.5:
sqrt(x)
else:
pow(x, exp)
proc `$`(x: vfloat): string =
let y = cast[ptr float](unsafeAddr x)
echo y[]
let x = set1(9.0)
echo x^0.5

View file

@ -1,82 +1,82 @@
discard """
nimout: '''
StmtList
Ident !"foo010"
Ident ident"foo010"
Call
Ident !"foo020"
Ident ident"foo020"
Call
Ident !"foo030"
Ident !"x"
Ident ident"foo030"
Ident ident"x"
Command
Ident !"foo040"
Ident !"x"
Ident ident"foo040"
Ident ident"x"
Call
Ident !"foo050"
Ident ident"foo050"
StmtList
DiscardStmt
Empty
Call
Ident !"foo060"
Ident ident"foo060"
StmtList
DiscardStmt
Empty
Call
Ident !"foo070"
Ident ident"foo070"
StrLit test
StmtList
DiscardStmt
Empty
Call
Ident !"foo080"
Ident ident"foo080"
StrLit test
StmtList
DiscardStmt
Empty
Command
Ident !"foo090"
Ident ident"foo090"
StrLit test
StmtList
DiscardStmt
Empty
Command
Ident !"foo100"
Ident ident"foo100"
Call
StrLit test
StmtList
DiscardStmt
Empty
Command
Ident !"foo101"
Ident ident"foo101"
Call
IntLit 10
StmtList
DiscardStmt
Empty
Command
Ident !"foo110"
Ident ident"foo110"
IntLit 1
Par
Infix
Ident !"+"
Ident ident"+"
IntLit 2
IntLit 3
StmtList
DiscardStmt
Empty
Command
Ident !"foo120"
Ident ident"foo120"
IntLit 1
Call
Par
Infix
Ident !"+"
Ident ident"+"
IntLit 2
IntLit 3
StmtList
DiscardStmt
Empty
Call
Ident !"foo130"
Ident ident"foo130"
Do
Empty
Empty
@ -84,7 +84,7 @@ StmtList
FormalParams
Empty
IdentDefs
Ident !"x"
Ident ident"x"
Empty
Empty
Empty
@ -93,7 +93,7 @@ StmtList
DiscardStmt
Empty
Call
Ident !"foo140"
Ident ident"foo140"
Do
Empty
Empty
@ -101,8 +101,8 @@ StmtList
FormalParams
Empty
IdentDefs
Ident !"x"
Ident !"int"
Ident ident"x"
Ident ident"int"
Empty
Empty
Empty
@ -110,16 +110,16 @@ StmtList
DiscardStmt
Empty
Call
Ident !"foo150"
Ident ident"foo150"
Do
Empty
Empty
Empty
FormalParams
Ident !"int"
Ident ident"int"
IdentDefs
Ident !"x"
Ident !"int"
Ident ident"x"
Ident ident"int"
Empty
Empty
Empty
@ -127,9 +127,9 @@ StmtList
DiscardStmt
Empty
Command
Ident !"foo160"
Ident ident"foo160"
Call
Ident !"x"
Ident ident"x"
Do
Empty
Empty
@ -137,7 +137,7 @@ StmtList
FormalParams
Empty
IdentDefs
Ident !"y"
Ident ident"y"
Empty
Empty
Empty
@ -146,7 +146,7 @@ StmtList
DiscardStmt
Empty
Call
Ident !"foo170"
Ident ident"foo170"
StmtList
DiscardStmt
Empty
@ -155,7 +155,7 @@ StmtList
DiscardStmt
Empty
Call
Ident !"foo180"
Ident ident"foo180"
StmtList
DiscardStmt
Empty
@ -167,9 +167,9 @@ StmtList
DiscardStmt
Empty
Command
Ident !"foo190"
Ident ident"foo190"
Call
Ident !"x"
Ident ident"x"
Do
Empty
Empty
@ -177,7 +177,7 @@ StmtList
FormalParams
Empty
IdentDefs
Ident !"y"
Ident ident"y"
Empty
Empty
Empty
@ -190,9 +190,9 @@ StmtList
Empty
Empty
FormalParams
Ident !"int"
Ident ident"int"
IdentDefs
Ident !"z"
Ident ident"z"
Empty
Empty
Empty
@ -205,10 +205,10 @@ StmtList
Empty
Empty
FormalParams
Ident !"int"
Ident ident"int"
IdentDefs
Ident !"w"
Ident !"int"
Ident ident"w"
Ident ident"int"
Empty
Empty
Empty
@ -223,10 +223,10 @@ StmtList
DiscardStmt
Empty
Call
Ident !"foo200"
Ident !"x"
Ident ident"foo200"
Ident ident"x"
Call
Ident !"bar"
Ident ident"bar"
StmtList
DiscardStmt
Empty
@ -236,53 +236,53 @@ StmtList
Empty
VarSection
IdentDefs
Ident !"a"
Ident ident"a"
Empty
Ident !"foo210"
Ident ident"foo210"
VarSection
IdentDefs
Ident !"a"
Ident ident"a"
Empty
Call
Ident !"foo220"
Ident ident"foo220"
VarSection
IdentDefs
Ident !"a"
Ident ident"a"
Empty
Call
Ident !"foo230"
Ident !"x"
Ident ident"foo230"
Ident ident"x"
VarSection
IdentDefs
Ident !"a"
Ident ident"a"
Empty
Command
Ident !"foo240"
Ident !"x"
Ident ident"foo240"
Ident ident"x"
VarSection
IdentDefs
Ident !"a"
Ident ident"a"
Empty
Call
Ident !"foo250"
Ident ident"foo250"
StmtList
DiscardStmt
Empty
VarSection
IdentDefs
Ident !"a"
Ident ident"a"
Empty
Call
Ident !"foo260"
Ident ident"foo260"
StmtList
DiscardStmt
Empty
VarSection
IdentDefs
Ident !"a"
Ident ident"a"
Empty
Call
Ident !"foo270"
Ident ident"foo270"
StmtList
DiscardStmt
Empty
@ -292,12 +292,12 @@ StmtList
Empty
VarSection
IdentDefs
Ident !"a"
Ident ident"a"
Empty
Command
Ident !"foo280"
Ident ident"foo280"
Call
Ident !"x"
Ident ident"x"
Do
Empty
Empty
@ -305,7 +305,7 @@ StmtList
FormalParams
Empty
IdentDefs
Ident !"y"
Ident ident"y"
Empty
Empty
Empty
@ -318,40 +318,40 @@ StmtList
DiscardStmt
Empty
Asgn
Ident !"a"
Ident !"foo290"
Ident ident"a"
Ident ident"foo290"
Asgn
Ident !"a"
Ident ident"a"
Call
Ident !"foo300"
Ident ident"foo300"
Asgn
Ident !"a"
Ident ident"a"
Call
Ident !"foo310"
Ident !"x"
Ident ident"foo310"
Ident ident"x"
Asgn
Ident !"a"
Ident ident"a"
Command
Ident !"foo320"
Ident !"x"
Ident ident"foo320"
Ident ident"x"
Asgn
Ident !"a"
Ident ident"a"
Call
Ident !"foo330"
Ident ident"foo330"
StmtList
DiscardStmt
Empty
Asgn
Ident !"a"
Ident ident"a"
Call
Ident !"foo340"
Ident ident"foo340"
StmtList
DiscardStmt
Empty
Asgn
Ident !"a"
Ident ident"a"
Call
Ident !"foo350"
Ident ident"foo350"
StmtList
DiscardStmt
Empty
@ -360,13 +360,13 @@ StmtList
DiscardStmt
Empty
Asgn
Ident !"a"
Ident ident"a"
Command
Ident !"foo360"
Ident ident"foo360"
Call
DotExpr
Ident !"x"
Ident !"bar"
Ident ident"x"
Ident ident"bar"
Do
Empty
Empty
@ -374,7 +374,7 @@ StmtList
FormalParams
Empty
IdentDefs
Ident !"y"
Ident ident"y"
Empty
Empty
Empty
@ -388,20 +388,20 @@ StmtList
Empty
Command
DotExpr
Ident !"foo370"
Ident !"add"
Ident ident"foo370"
Ident ident"add"
Call
Ident !"quote"
Ident ident"quote"
StmtList
DiscardStmt
Empty
Call
DotExpr
Ident !"foo380"
Ident !"add"
Ident ident"foo380"
Ident ident"add"
BracketExpr
Call
Ident !"quote"
Ident ident"quote"
StmtList
DiscardStmt
Empty

View file

@ -1,10 +1,14 @@
discard """
file: "trat_init.nim"
exitcode: "1"
output: '''true'''
"""
import rationals
var
z = Rational[int](num: 0, den: 1)
o = initRational(num=1, den=1)
a = initRational(1, 2)
r = initRational(1, 0) # this fails - no zero denominator
try:
var
r = initRational(1, 0) # this fails - no zero denominator
except AssertionError:
echo "true"

View file

@ -3,6 +3,7 @@ discard """
exitcode: 0
output: "OK"
disabled: "travis"
disabled: "appveyor"
"""
import strutils

View file

@ -21,5 +21,6 @@ import subexes
import tables
import unicode
import uri
import macros
echo "Nimscript imports are successful."

View file

@ -219,9 +219,9 @@ proc debuggerTests(r: var TResults, cat: Category, options: string) =
proc jsTests(r: var TResults, cat: Category, options: string) =
template test(filename: untyped) =
testSpec r, makeTest(filename, options & " -d:nodejs", cat,
actionRun, targetJS)
actionRun), targetJS
testSpec r, makeTest(filename, options & " -d:nodejs -d:release", cat,
actionRun, targetJS)
actionRun), targetJS
for t in os.walkFiles("tests/js/t*.nim"):
test(t)
@ -245,10 +245,10 @@ proc testNimInAction(r: var TResults, cat: Category, options: string) =
testSpec r, makeTest(filename, options, cat, action)
template testJS(filename: untyped) =
testSpec r, makeTest(filename, options, cat, actionCompile, targetJS)
testSpec r, makeTest(filename, options, cat, actionCompile), targetJS
template testCPP(filename: untyped) =
testSpec r, makeTest(filename, options, cat, actionCompile, targetCPP)
testSpec r, makeTest(filename, options, cat, actionCompile), targetCPP
let tests = [
"niminaction/Chapter3/ChatApp/src/server",
@ -387,7 +387,7 @@ proc testNimblePackages(r: var TResults, cat: Category, filter: PackageFilter) =
installStatus = waitForExitEx(installProcess)
installProcess.close
if installStatus != QuitSuccess:
r.addResult(test, "", "", reInstallFailed)
r.addResult(test, targetC, "", "", reInstallFailed)
continue
let
@ -396,12 +396,12 @@ proc testNimblePackages(r: var TResults, cat: Category, filter: PackageFilter) =
buildStatus = waitForExitEx(buildProcess)
buildProcess.close
if buildStatus != QuitSuccess:
r.addResult(test, "", "", reBuildFailed)
r.addResult(test, "", "", reSuccess)
r.addResult(packageFileTest, "", "", reSuccess)
r.addResult(test, targetC, "", "", reBuildFailed)
r.addResult(test, targetC, "", "", reSuccess)
r.addResult(packageFileTest, targetC, "", "", reSuccess)
except JsonParsingError:
echo("[Warning] - Cannot run nimble tests: Invalid package file.")
r.addResult(packageFileTest, "", "", reBuildFailed)
r.addResult(packageFileTest, targetC, "", "", reBuildFailed)
# ----------------------------------------------------------------------------
@ -420,7 +420,7 @@ proc processSingleTest(r: var TResults, cat: Category, options, test: string) =
let test = "tests" & DirSep &.? cat.string / test
let target = if cat.string.normalize == "js": targetJS else: targetC
if existsFile(test): testSpec r, makeTest(test, options, cat, target = target)
if existsFile(test): testSpec r, makeTest(test, options, cat), target
else: echo "[Warning] - ", test, " test does not exist"
proc processCategory(r: var TResults, cat: Category, options: string) =

View file

@ -13,6 +13,7 @@ import parseutils, strutils, os, osproc, streams, parsecfg
var compilerPrefix* = "compiler" / "nim "
let isTravis = existsEnv("TRAVIS")
let isAppVeyor = existsEnv("APPVEYOR")
proc cmdTemplate*(): string =
compilerPrefix & "$target --lib:lib --hints:on -d:testing $options $file"
@ -151,6 +152,7 @@ proc parseSpec*(filename: string): TSpec =
result.sortoutput = parseCfgBool(e.value)
of "exitcode":
discard parseInt(e.value, result.exitCode)
result.action = actionRun
of "msg":
result.msg = e.value
if result.action != actionRun:
@ -178,6 +180,8 @@ proc parseSpec*(filename: string): TSpec =
when defined(posix): result.err = reIgnored
of "travis":
if isTravis: result.err = reIgnored
of "appveyor":
if isAppVeyor: result.err = reIgnored
else:
raise newException(ValueError, "cannot interpret as a bool: " & e.value)
of "cmd":

View file

@ -44,7 +44,6 @@ type
name: string
cat: Category
options: string
target: TTarget
action: TTestAction
startTime: float
@ -155,13 +154,13 @@ proc `$`(x: TResults): string =
"Tests skipped: $2 / $3 <br />\n") %
[$x.passed, $x.skipped, $x.total]
proc addResult(r: var TResults, test: TTest,
proc addResult(r: var TResults, test: TTest, target: TTarget,
expected, given: string, success: TResultEnum) =
let name = test.name.extractFilename & test.options
let name = test.name.extractFilename & " " & $target & test.options
let duration = epochTime() - test.startTime
backend.writeTestResult(name = name,
category = test.cat.string,
target = $test.target,
target = $target,
action = $test.action,
result = $success,
expected = expected,
@ -197,29 +196,29 @@ proc addResult(r: var TResults, test: TTest,
discard waitForExit(p)
close(p)
proc cmpMsgs(r: var TResults, expected, given: TSpec, test: TTest) =
proc cmpMsgs(r: var TResults, expected, given: TSpec, test: TTest, target: TTarget) =
if strip(expected.msg) notin strip(given.msg):
r.addResult(test, expected.msg, given.msg, reMsgsDiffer)
r.addResult(test, target, expected.msg, given.msg, reMsgsDiffer)
elif expected.nimout.len > 0 and expected.nimout.normalizeMsg notin given.nimout.normalizeMsg:
r.addResult(test, expected.nimout, given.nimout, reMsgsDiffer)
r.addResult(test, target, expected.nimout, given.nimout, reMsgsDiffer)
elif expected.tfile == "" and extractFilename(expected.file) != extractFilename(given.file) and
"internal error:" notin expected.msg:
r.addResult(test, expected.file, given.file, reFilesDiffer)
r.addResult(test, target, expected.file, given.file, reFilesDiffer)
elif expected.line != given.line and expected.line != 0 or
expected.column != given.column and expected.column != 0:
r.addResult(test, $expected.line & ':' & $expected.column,
r.addResult(test, target, $expected.line & ':' & $expected.column,
$given.line & ':' & $given.column,
reLinesDiffer)
elif expected.tfile != "" and extractFilename(expected.tfile) != extractFilename(given.tfile) and
"internal error:" notin expected.msg:
r.addResult(test, expected.tfile, given.tfile, reFilesDiffer)
r.addResult(test, target, expected.tfile, given.tfile, reFilesDiffer)
elif expected.tline != given.tline and expected.tline != 0 or
expected.tcolumn != given.tcolumn and expected.tcolumn != 0:
r.addResult(test, $expected.tline & ':' & $expected.tcolumn,
r.addResult(test, target, $expected.tline & ':' & $expected.tcolumn,
$given.tline & ':' & $given.tcolumn,
reLinesDiffer)
else:
r.addResult(test, expected.msg, given.msg, reSuccess)
r.addResult(test, target, expected.msg, given.msg, reSuccess)
inc(r.passed)
proc generatedFile(path, name: string, target: TTarget): string =
@ -231,11 +230,11 @@ proc generatedFile(path, name: string, target: TTarget): string =
proc needsCodegenCheck(spec: TSpec): bool =
result = spec.maxCodeSize > 0 or spec.ccodeCheck.len > 0
proc codegenCheck(test: TTest, spec: TSpec, expectedMsg: var string,
proc codegenCheck(test: TTest, target: TTarget, spec: TSpec, expectedMsg: var string,
given: var TSpec) =
try:
let (path, name, _) = test.name.splitFile
let genFile = generatedFile(path, name, test.target)
let genFile = generatedFile(path, name, target)
let contents = readFile(genFile).string
let check = spec.ccodeCheck
if check.len > 0:
@ -267,13 +266,13 @@ proc makeDeterministic(s: string): string =
sort(x, system.cmp)
result = join(x, "\n")
proc compilerOutputTests(test: TTest, given: var TSpec, expected: TSpec;
r: var TResults) =
proc compilerOutputTests(test: TTest, target: TTarget, given: var TSpec,
expected: TSpec; r: var TResults) =
var expectedmsg: string = ""
var givenmsg: string = ""
if given.err == reSuccess:
if expected.needsCodegenCheck:
codegenCheck(test, expected, expectedmsg, given)
codegenCheck(test, target, expected, expectedmsg, given)
givenmsg = given.msg
if expected.nimout.len > 0:
expectedmsg = expected.nimout
@ -282,7 +281,7 @@ proc compilerOutputTests(test: TTest, given: var TSpec, expected: TSpec;
else:
givenmsg = given.nimout.strip
if given.err == reSuccess: inc(r.passed)
r.addResult(test, expectedmsg, givenmsg, given.err)
r.addResult(test, target, expectedmsg, givenmsg, given.err)
proc analyzeAndConsolidateOutput(s: string): string =
result = ""
@ -298,13 +297,7 @@ proc analyzeAndConsolidateOutput(s: string): string =
result = substr(rows[i], pos)
return
proc testSpec(r: var TResults, test: TTest) =
# major entry point for a single test
if test.target notin targets:
r.addResult(test, "", "", reIgnored)
inc(r.skipped)
return
proc testSpec(r: var TResults, test: TTest, target = targetC) =
let tname = test.name.addFileExt(".nim")
#echo "TESTING ", tname
inc(r.total)
@ -316,83 +309,92 @@ proc testSpec(r: var TResults, test: TTest) =
expected.action = actionRunNoSpec
if expected.err == reIgnored:
r.addResult(test, "", "", reIgnored)
r.addResult(test, target, "", "", reIgnored)
inc(r.skipped)
return
case expected.action
of actionCompile:
var given = callCompiler(expected.cmd, test.name,
test.options & " --stdout --hint[Path]:off --hint[Processing]:off",
test.target)
compilerOutputTests(test, given, expected, r)
of actionRun, actionRunNoSpec:
# In this branch of code "early return" pattern is clearer than deep
# nested conditionals - the empty rows in between to clarify the "danger"
var given = callCompiler(expected.cmd, test.name, test.options,
test.target)
if expected.targets == {}:
expected.targets.incl(target)
if given.err != reSuccess:
r.addResult(test, "", given.msg, given.err)
return
for target in expected.targets:
if target notin targets:
r.addResult(test, target, "", "", reIgnored)
inc(r.skipped)
continue
let isJsTarget = test.target == targetJS
var exeFile: string
if isJsTarget:
let (dir, file, _) = splitFile(tname)
exeFile = dir / "nimcache" / file & ".js" # *TODO* hardcoded "nimcache"
else:
exeFile = changeFileExt(tname, ExeExt)
case expected.action
of actionCompile:
var given = callCompiler(expected.cmd, test.name,
test.options & " --stdout --hint[Path]:off --hint[Processing]:off",
target)
compilerOutputTests(test, target, given, expected, r)
of actionRun, actionRunNoSpec:
# In this branch of code "early return" pattern is clearer than deep
# nested conditionals - the empty rows in between to clarify the "danger"
var given = callCompiler(expected.cmd, test.name, test.options,
target)
if not existsFile(exeFile):
r.addResult(test, expected.outp, "executable not found", reExeNotFound)
return
if given.err != reSuccess:
r.addResult(test, target, "", given.msg, given.err)
continue
let nodejs = if isJsTarget: findNodeJs() else: ""
if isJsTarget and nodejs == "":
r.addResult(test, expected.outp, "nodejs binary not in PATH",
reExeNotFound)
return
let isJsTarget = target == targetJS
var exeFile: string
if isJsTarget:
let (dir, file, _) = splitFile(tname)
exeFile = dir / "nimcache" / file & ".js" # *TODO* hardcoded "nimcache"
else:
exeFile = changeFileExt(tname, ExeExt)
let exeCmd = (if isJsTarget: nodejs & " " else: "") & exeFile
var (buf, exitCode) = execCmdEx(exeCmd, options = {poStdErrToStdOut})
if not existsFile(exeFile):
r.addResult(test, target, expected.outp, "executable not found", reExeNotFound)
continue
# Treat all failure codes from nodejs as 1. Older versions of nodejs used
# to return other codes, but for us it is sufficient to know that it's not 0.
if exitCode != 0: exitCode = 1
let nodejs = if isJsTarget: findNodeJs() else: ""
if isJsTarget and nodejs == "":
r.addResult(test, target, expected.outp, "nodejs binary not in PATH",
reExeNotFound)
continue
let bufB = if expected.sortoutput: makeDeterministic(strip(buf.string))
else: strip(buf.string)
let expectedOut = strip(expected.outp)
let exeCmd = (if isJsTarget: nodejs & " " else: "") & exeFile
var (buf, exitCode) = execCmdEx(exeCmd, options = {poStdErrToStdOut})
if exitCode != expected.exitCode:
r.addResult(test, "exitcode: " & $expected.exitCode,
"exitcode: " & $exitCode & "\n\nOutput:\n" &
analyzeAndConsolidateOutput(bufB),
reExitCodesDiffer)
return
# Treat all failure codes from nodejs as 1. Older versions of nodejs used
# to return other codes, but for us it is sufficient to know that it's not 0.
if exitCode != 0: exitCode = 1
if bufB != expectedOut and expected.action != actionRunNoSpec:
if not (expected.substr and expectedOut in bufB):
given.err = reOutputsDiffer
r.addResult(test, expected.outp, bufB, reOutputsDiffer)
return
let bufB = if expected.sortoutput: makeDeterministic(strip(buf.string))
else: strip(buf.string)
let expectedOut = strip(expected.outp)
compilerOutputTests(test, given, expected, r)
return
if exitCode != expected.exitCode:
r.addResult(test, target, "exitcode: " & $expected.exitCode,
"exitcode: " & $exitCode & "\n\nOutput:\n" &
analyzeAndConsolidateOutput(bufB),
reExitCodesDiffer)
continue
of actionReject:
var given = callCompiler(expected.cmd, test.name, test.options,
test.target)
cmpMsgs(r, expected, given, test)
return
if bufB != expectedOut and expected.action != actionRunNoSpec:
if not (expected.substr and expectedOut in bufB):
given.err = reOutputsDiffer
r.addResult(test, target, expected.outp, bufB, reOutputsDiffer)
continue
proc testNoSpec(r: var TResults, test: TTest) =
compilerOutputTests(test, target, given, expected, r)
continue
of actionReject:
var given = callCompiler(expected.cmd, test.name, test.options,
target)
cmpMsgs(r, expected, given, test, target)
continue
proc testNoSpec(r: var TResults, test: TTest, target = targetC) =
# does not extract the spec because the file is not supposed to have any
#let tname = test.name.addFileExt(".nim")
inc(r.total)
let given = callCompiler(cmdTemplate(), test.name, test.options, test.target)
r.addResult(test, "", given.msg, given.err)
let given = callCompiler(cmdTemplate(), test.name, test.options, target)
r.addResult(test, target, "", given.msg, given.err)
if given.err == reSuccess: inc(r.passed)
proc testC(r: var TResults, test: TTest) =
@ -400,9 +402,9 @@ proc testC(r: var TResults, test: TTest) =
let tname = test.name.addFileExt(".c")
inc(r.total)
styledEcho "Processing ", fgCyan, extractFilename(tname)
var given = callCCompiler(cmdTemplate(), test.name & ".c", test.options, test.target)
var given = callCCompiler(cmdTemplate(), test.name & ".c", test.options, targetC)
if given.err != reSuccess:
r.addResult(test, "", given.msg, given.err)
r.addResult(test, targetC, "", given.msg, given.err)
elif test.action == actionRun:
let exeFile = changeFileExt(test.name, ExeExt)
var (_, exitCode) = execCmdEx(exeFile, options = {poStdErrToStdOut, poUsePath})
@ -410,10 +412,10 @@ proc testC(r: var TResults, test: TTest) =
if given.err == reSuccess: inc(r.passed)
proc makeTest(test, options: string, cat: Category, action = actionCompile,
target = targetC, env: string = ""): TTest =
env: string = ""): TTest =
# start with 'actionCompile', will be overwritten in the spec:
result = TTest(cat: cat, name: test, options: options,
target: target, action: action, startTime: epochTime())
action: action, startTime: epochTime())
when defined(windows):
const
@ -463,7 +465,10 @@ proc main() =
let testsDir = "tests" & DirSep
var myself = quoteShell(findExe("tests" / "testament" / "tester"))
if targetsStr.len > 0:
myself &= " '--targets:" & targetsStr & "'"
myself &= " " & quoteShell("--targets:" & targetsStr)
myself &= " " & quoteShell("--nim:" & compilerPrefix)
var cmds: seq[string] = @[]
let rest = if p.cmdLineRest.string.len > 0: " " & p.cmdLineRest.string else: ""
for kind, dir in walkDir(testsDir):

View file

@ -1,5 +1,7 @@
discard """
output: "23"
output: '''23
1.5
'''
"""
# bug #554, #179
@ -25,3 +27,24 @@ type
var
it: TKeysIterator[int, string] = nil
#bug #5521
type
Texture = enum
Smooth
Coarse
FruitBase = object of RootObj
color: int
case kind: Texture
of Smooth:
skin: float64
of Coarse:
grain: int
Apple = object of FruitBase
width: int
taste: float64
var x = Apple(kind: Smooth, skin: 1.5)
var u = x.skin
echo u

View file

@ -0,0 +1,13 @@
import system
type Bar[T] = ref object
value: T
type types = int32|int64 # if I change this to just int32 or int64 it works (compiles)
# if I replace Bar everywhere with seq it also compiles fine
proc Foo[T: Bar[types]](): T =
when T is Bar: nil
discard Foo[Bar[int32]]()
#bug #6073

View file

@ -26,12 +26,12 @@ proc checkNode(arg: NimNode; name: string): void {. compileTime .} =
seqAppend.add(arg) # bit this creates a copy
arg.add newCall(ident"echo", newLit("Hello World"))
assertEq arg.lispRepr , """StmtList(DiscardStmt(Empty()), Call(Ident(!"echo"), StrLit(Hello World)))"""
assertEq node.lispRepr , """StmtList(DiscardStmt(Empty()), Call(Ident(!"echo"), StrLit(Hello World)))"""
assertEq nodeArray[0].lispRepr , """StmtList(DiscardStmt(Empty()), Call(Ident(!"echo"), StrLit(Hello World)))"""
assertEq nodeSeq[0].lispRepr , """StmtList(DiscardStmt(Empty()), Call(Ident(!"echo"), StrLit(Hello World)))"""
assertEq seqAppend[0].lispRepr , """StmtList(DiscardStmt(Empty()), Call(Ident(!"echo"), StrLit(Hello World)))"""
assertEq seqAppend[1].lispRepr , """StmtList(DiscardStmt(Empty()), Call(Ident(!"echo"), StrLit(Hello World)))"""
assertEq arg.lispRepr , """StmtList(DiscardStmt(Empty()), Call(Ident(ident"echo"), StrLit(Hello World)))"""
assertEq node.lispRepr , """StmtList(DiscardStmt(Empty()), Call(Ident(ident"echo"), StrLit(Hello World)))"""
assertEq nodeArray[0].lispRepr , """StmtList(DiscardStmt(Empty()), Call(Ident(ident"echo"), StrLit(Hello World)))"""
assertEq nodeSeq[0].lispRepr , """StmtList(DiscardStmt(Empty()), Call(Ident(ident"echo"), StrLit(Hello World)))"""
assertEq seqAppend[0].lispRepr , """StmtList(DiscardStmt(Empty()), Call(Ident(ident"echo"), StrLit(Hello World)))"""
assertEq seqAppend[1].lispRepr , """StmtList(DiscardStmt(Empty()), Call(Ident(ident"echo"), StrLit(Hello World)))"""
echo "OK"