diff options
author | Zahary Karadjov <zahary@gmail.com> | 2012-03-31 18:51:11 +0300 |
---|---|---|
committer | Zahary Karadjov <zahary@gmail.com> | 2012-03-31 18:51:11 +0300 |
commit | 8d698b2bdd63cb7390a418d9ebb3ee7fdc7ea3b5 (patch) | |
tree | 3fb011eb742df74754abc2479d211bbdbef16b02 /tests | |
parent | 22dc76a361c70af93403dfbf2610c8d49111637c (diff) | |
parent | c7fc519fa39ded59744bc677261faa04b6947cee (diff) | |
download | Nim-8d698b2bdd63cb7390a418d9ebb3ee7fdc7ea3b5.tar.gz |
Merge branch 'master' of github.com:Araq/Nimrod into upstream
Diffstat (limited to 'tests')
-rw-r--r-- | tests/benchmark.nim | 47 | ||||
-rw-r--r-- | tests/benchmarks/fannkuch.nim | 69 | ||||
-rw-r--r-- | tests/benchmarks/quicksort.nim | 54 | ||||
-rw-r--r-- | tests/compile/tglobalforvar.nim | 7 | ||||
-rw-r--r-- | tests/compile/tircbot.nim | 447 | ||||
-rwxr-xr-x | tests/reject/t99bott.nim | 2 | ||||
-rw-r--r-- | tests/reject/tenumitems.nim | 2 |
7 files changed, 626 insertions, 2 deletions
diff --git a/tests/benchmark.nim b/tests/benchmark.nim new file mode 100644 index 000000000..8dd9cc2e2 --- /dev/null +++ b/tests/benchmark.nim @@ -0,0 +1,47 @@ +# +# +# Nimrod Benchmark tool +# (c) Copyright 2012 Dominik Picheta +# +# See the file "copying.txt", included in this +# distribution, for details about the copyright. +# + +## This program runs benchmarks +import osproc, os, times, json + +type + TBenchResult = tuple[file: string, success: bool, time: float] + +proc compileBench(file: string) = + ## Compiles ``file``. + doAssert(execCmdEx("nimrod c -d:release " & file).exitCode == QuitSuccess) + +proc runBench(file: string): TBenchResult = + ## Runs ``file`` and returns info on how long it took to run. + var start = epochTime() + if execCmdEx(file.addFileExt(ExeExt)).exitCode == QuitSuccess: + var t = epochTime() - start + result = (file, true, t) + else: result = (file, false, -1.0) + +proc genOutput(benches: seq[TBenchResult]): PJsonNode = + result = newJObject() + for i in benches: + if i.success: + result[i.file.extractFilename] = newJFloat(i.time) + else: + result[i.file.extractFilename] = newJNull() + +proc doBench(): seq[TBenchResult] = + result = @[] + for i in walkFiles("tests/benchmarks/*.nim"): + echo(i.extractFilename) + compileBench(i) + result.add(runBench(i)) + +when isMainModule: + var b = doBench() + var output = genOutput(b) + writeFile("benchmarkResults.json", pretty(output)) + \ No newline at end of file diff --git a/tests/benchmarks/fannkuch.nim b/tests/benchmarks/fannkuch.nim new file mode 100644 index 000000000..15f78f50c --- /dev/null +++ b/tests/benchmarks/fannkuch.nim @@ -0,0 +1,69 @@ +import os +import strutils + +proc fannkuch (n: int): int = + var + count: seq[int] + maxFlips = 0 + m = n-1 + r = n + check = 0 + perm1: seq[int] + perm: seq[int] + + newSeq (count, n+1) + newSeq (perm1, n) + newSeq (perm, n) + for i in 0 .. n-1: + count[i] = i+1 + perm1[i] = i + perm[i] = i + count[n] = n+1 + + while True: + if check < 30: + for i in items (perm1): + write (stdout, $(i+1)) + echo ("") + inc (check) + + while r != 1: + count[r-1] = r + dec (r) + + if perm1[0] != 0 and perm1[m] != m: + # perm = perm1 + # The above line is between 3 and 4 times slower than the loop below! + for i in 0 .. n-1: + perm[i] = perm1[i] + var flipsCount = 0 + var k = perm[0] + while k != 0: + for i in 0 .. (k div 2): + swap (perm[i], perm[k-i]) + inc (flipsCount) + k = perm[0] + + if flipsCount > maxFlips: + maxFlips = flipsCount + + block makePerm: + while r != n: + var tmp = perm1[0] + # # perm1.delete (0) + # # perm1.insert (tmp, r) + # # The above is about twice as slow as the following: + # moveMem (addr (perm1[0]), addr (perm1[1]), r * sizeof (int)) + # The call to moveMem is about 50% slower than the loop below! + for i in 0 .. r-1: + perm1[i] = perm1[i+1] + perm1[r] = tmp + + dec (count[r]) + if count[r] > 0: + break makePerm + inc (r) + return maxFlips + +var n = 10 +echo ("Pfannkuchen(" & $n & ") = " & $fannkuch (n)) \ No newline at end of file diff --git a/tests/benchmarks/quicksort.nim b/tests/benchmarks/quicksort.nim new file mode 100644 index 000000000..599e3674c --- /dev/null +++ b/tests/benchmarks/quicksort.nim @@ -0,0 +1,54 @@ +import os +import strutils + +# Generate some pseudo-random data +var seed: tuple[s1, s2, s3: int32] = (2'i32, 8'i32, 16'i32) + +proc random(): int32 = + seed = (((((((seed[0] and 0x0007_FFFF'i32) shl 13'i32) xor seed[0]) shr + 19'i32) and 0x0000_1FFF'i32) xor + ((seed[0] and 0x000F_FFFE'i32) shl 12'i32)), + + ((((((seed[1] and 0x3FFF_FFFF'i32) shl 2'i32) xor seed[1]) shr + 25'i32) and 0x0000_007F'i32) xor + ((seed[1] and 0x0FFF_FFF8'i32) shl 4'i32)), + + ((((((seed[2] and 0x1FFF_FFFF'i32) shl 3'i32) xor seed[2]) shr + 11'i32) and 0x001F_FFFF'i32) xor + ((seed[2] and 0x0000_7FF0'i32) shl 17'i32))) + return seed[0] xor seed[1] xor seed[2] + +var n = 9999999 + +var data: seq[int32] +newSeq (data, n) +for i in 0 .. data.high(): + data[i] = random() + + +proc `$` (d: seq[int32]): string = + result = "[ " + for i in items (d): + result.addSep (", ", 2) + result.add ($(i and 0xFFFF_FFFF'i64)) + result.add (" ]") + +# Sort the data +proc sort (start, stop: int) = + if stop <= start+1: + return + + var j = start + for i in start..stop-2: + if data[i] <% data[stop-1]: + swap (data[i], data[j]) + inc (j) + swap (data[j], data[stop-1]) + + sort (start, j) + sort (j+1, stop) + +sort (0, data.len) +echo (data[n div 2 - 1] and 0xFFFF_FFFF'i64, ", ", + data[n div 2] and 0xFFFF_FFFF'i64, ", ", + data[n div 2 + 1] and 0xFFFF_FFFF'i64) \ No newline at end of file diff --git a/tests/compile/tglobalforvar.nim b/tests/compile/tglobalforvar.nim new file mode 100644 index 000000000..9f61ebcab --- /dev/null +++ b/tests/compile/tglobalforvar.nim @@ -0,0 +1,7 @@ + +var funcs: seq[proc (): int] = @[] +for i in 0..10: + funcs.add((proc (): int = return i * i)) + +echo(funcs[3]()) + diff --git a/tests/compile/tircbot.nim b/tests/compile/tircbot.nim new file mode 100644 index 000000000..91be18092 --- /dev/null +++ b/tests/compile/tircbot.nim @@ -0,0 +1,447 @@ +import irc, sockets, asyncio, json, os, strutils, times, redis + +type + TDb* = object + r*: TRedis + lastPing: float + + TBuildResult* = enum + bUnknown, bFail, bSuccess + + TTestResult* = enum + tUnknown, tFail, tSuccess + + TEntry* = tuple[c: TCommit, p: seq[TPlatform]] + + TCommit* = object + commitMsg*, username*, hash*: string + date*: TTime + + TPlatform* = object + buildResult*: TBuildResult + testResult*: TTestResult + failReason*, platform*: string + total*, passed*, skipped*, failed*: biggestInt + csources*: bool + +const + listName = "commits" + failOnExisting = False + +proc open*(host = "localhost", port: TPort): TDb = + result.r = redis.open(host, port) + result.lastPing = epochTime() + +proc customHSet(database: TDb, name, field, value: string) = + if database.r.hSet(name, field, value).int == 0: + if failOnExisting: + assert(false) + else: + echo("[Warning:REDIS] ", field, " already exists in ", name) + +proc updateProperty*(database: TDb, commitHash, platform, property, + value: string) = + var name = platform & ":" & commitHash + if database.r.hSet(name, property, value).int == 0: + echo("[INFO:REDIS] '$1' field updated in hash" % [property]) + else: + echo("[INFO:REDIS] '$1' new field added to hash" % [property]) + +proc globalProperty*(database: TDb, commitHash, property, value: string) = + if database.r.hSet(commitHash, property, value).int == 0: + echo("[INFO:REDIS] '$1' field updated in hash" % [property]) + else: + echo("[INFO:REDIS] '$1' new field added to hash" % [property]) + +proc addCommit*(database: TDb, commitHash, commitMsg, user: string) = + # Add the commit hash to the `commits` list. + discard database.r.lPush(listName, commitHash) + # Add the commit message, current date and username as a property + globalProperty(database, commitHash, "commitMsg", commitMsg) + globalProperty(database, commitHash, "date", $int(getTime())) + globalProperty(database, commitHash, "username", user) + +proc keepAlive*(database: var TDb) = + ## Keep the connection alive. Ping redis in this case. This functions does + ## not guarantee that redis will be pinged. + var t = epochTime() + if t - database.lastPing >= 60.0: + echo("PING -> redis") + assert(database.r.ping() == "PONG") + database.lastPing = t + +proc getCommits*(database: TDb, + plStr: var seq[string]): seq[TEntry] = + result = @[] + var commitsRaw = database.r.lrange("commits", 0, -1) + for c in items(commitsRaw): + var commit: TCommit + commit.hash = c + for key, value in database.r.hPairs(c): + case normalize(key) + of "commitmsg": commit.commitMsg = value + of "date": commit.date = TTime(parseInt(value)) + of "username": commit.username = value + else: + echo(key) + assert(false) + + var platformsRaw = database.r.lrange(c & ":platforms", 0, -1) + var platforms: seq[TPlatform] = @[] + for p in items(platformsRaw): + var platform: TPlatform + for key, value in database.r.hPairs(p & ":" & c): + case normalize(key) + of "buildresult": + platform.buildResult = parseInt(value).TBuildResult + of "testresult": + platform.testResult = parseInt(value).TTestResult + of "failreason": + platform.failReason = value + of "total": + platform.total = parseBiggestInt(value) + of "passed": + platform.passed = parseBiggestInt(value) + of "skipped": + platform.skipped = parseBiggestInt(value) + of "failed": + platform.failed = parseBiggestInt(value) + of "csources": + platform.csources = if value == "t": true else: false + else: + echo(normalize(key)) + assert(false) + + platform.platform = p + + platforms.add(platform) + if p notin plStr: + plStr.add(p) + result.add((commit, platforms)) + +proc commitExists*(database: TDb, commit: string, starts = false): bool = + # TODO: Consider making the 'commits' list a set. + for c in items(database.r.lrange("commits", 0, -1)): + if starts: + if c.startsWith(commit): return true + else: + if c == commit: return true + return false + +proc platformExists*(database: TDb, commit: string, platform: string): bool = + for p in items(database.r.lrange(commit & ":" & "platforms", 0, -1)): + if p == platform: return true + +proc expandHash*(database: TDb, commit: string): string = + for c in items(database.r.lrange("commits", 0, -1)): + if c.startsWith(commit): return c + assert false + +proc isNewest*(database: TDb, commit: string): bool = + return database.r.lIndex("commits", 0) == commit + +proc getNewest*(database: TDb): string = + return database.r.lIndex("commits", 0) + +proc addPlatform*(database: TDb, commit: string, platform: string) = + assert database.commitExists(commit) + assert (not database.platformExists(commit, platform)) + var name = platform & ":" & commit + if database.r.exists(name): + if failOnExisting: quit("[FAIL] " & name & " already exists!", 1) + else: echo("[Warning] " & name & " already exists!") + + discard database.r.lPush(commit & ":" & "platforms", platform) + +proc `[]`*(p: seq[TPlatform], name: string): TPlatform = + for platform in items(p): + if platform.platform == name: + return platform + raise newException(EInvalidValue, name & " platforms not found in commits.") + +proc contains*(p: seq[TPlatform], s: string): bool = + for i in items(p): + if i.platform == s: + return True + + +type + PState = ref TState + TState = object of TObject + dispatcher: PDispatcher + sock: PAsyncSocket + ircClient: PAsyncIRC + hubPort: TPort + database: TDb + dbConnected: bool + + TSeenType = enum + PSeenJoin, PSeenPart, PSeenMsg, PSeenNick, PSeenQuit + + TSeen = object + nick: string + channel: string + timestamp: TTime + case kind*: TSeenType + of PSeenJoin: nil + of PSeenPart, PSeenQuit, PSeenMsg: + msg: string + of PSeenNick: + newNick: string + +const + ircServer = "irc.freenode.net" + joinChans = @["#nimrod"] + botNickname = "NimBot" + +proc setSeen(d: TDb, s: TSeen) = + discard d.r.del("seen:" & s.nick) + + var hashToSet = @[("type", $s.kind.int), ("channel", s.channel), + ("timestamp", $s.timestamp.int)] + case s.kind + of PSeenJoin: nil + of PSeenPart, PSeenMsg, PSeenQuit: + hashToSet.add(("msg", s.msg)) + of PSeenNick: + hashToSet.add(("newnick", s.newNick)) + + d.r.hMSet("seen:" & s.nick, hashToSet) + +proc getSeen(d: TDb, nick: string, s: var TSeen): bool = + if d.r.exists("seen:" & nick): + result = true + s.nick = nick + # Get the type first + s.kind = d.r.hGet("seen:" & nick, "type").parseInt.TSeenType + + for key, value in d.r.hPairs("seen:" & nick): + case normalize(key) + of "type": + #s.kind = value.parseInt.TSeenType + of "channel": + s.channel = value + of "timestamp": + s.timestamp = TTime(value.parseInt) + of "msg": + s.msg = value + of "newnick": + s.newNick = value + +template createSeen(typ: TSeenType, n, c: string): stmt = + var seenNick: TSeen + seenNick.kind = typ + seenNick.nick = n + seenNick.channel = c + seenNick.timestamp = getTime() + +proc parseReply(line: string, expect: string): Bool = + var jsonDoc = parseJson(line) + return jsonDoc["reply"].str == expect + +proc limitCommitMsg(m: string): string = + ## Limits the message to 300 chars and adds ellipsis. + var m1 = m + if NewLines in m1: + m1 = m1.splitLines()[0] + + if m1.len >= 300: + m1 = m1[0..300] + + if m1.len >= 300 or NewLines in m: m1.add("... ") + + if NewLines in m: m1.add($m.splitLines().len & " more lines") + + return m1 + +proc handleWebMessage(state: PState, line: string) = + echo("Got message from hub: " & line) + var json = parseJson(line) + if json.existsKey("payload"): + for i in 0..min(4, json["payload"]["commits"].len-1): + var commit = json["payload"]["commits"][i] + # Create the message + var message = "" + message.add(json["payload"]["repository"]["owner"]["name"].str & "/" & + json["payload"]["repository"]["name"].str & " ") + message.add(commit["id"].str[0..6] & " ") + message.add(commit["author"]["name"].str & " ") + message.add("[+" & $commit["added"].len & " ") + message.add("±" & $commit["modified"].len & " ") + message.add("-" & $commit["removed"].len & "]: ") + message.add(limitCommitMsg(commit["message"].str)) + + # Send message to #nimrod. + state.ircClient[].privmsg(joinChans[0], message) + elif json.existsKey("redisinfo"): + assert json["redisinfo"].existsKey("port") + let redisPort = json["redisinfo"]["port"].num + state.dbConnected = true + +proc hubConnect(state: PState) +proc handleConnect(s: PAsyncSocket, userArg: PObject) = + let state = PState(userArg) + try: + # Send greeting + var obj = newJObject() + obj["name"] = newJString("irc") + obj["platform"] = newJString("?") + state.sock.send($obj & "\c\L") + + # Wait for reply. + var line = "" + sleep(1500) + if state.sock.recvLine(line): + assert(line != "") + doAssert parseReply(line, "OK") + echo("The hub accepted me!") + else: + raise newException(EInvalidValue, + "Hub didn't accept me. Waited 1.5 seconds.") + + # ask for the redis info + var riobj = newJObject() + riobj["do"] = newJString("redisinfo") + state.sock.send($riobj & "\c\L") + + except EOS: + echo(getCurrentExceptionMsg()) + s.close() + echo("Waiting 5 seconds...") + sleep(5000) + state.hubConnect() + +proc handleRead(s: PAsyncSocket, userArg: PObject) = + let state = PState(userArg) + var line = "" + if state.sock.recvLine(line): + if line != "": + # Handle the message + state.handleWebMessage(line) + else: + echo("Disconnected from hub: ", OSErrorMsg()) + s.close() + echo("Reconnecting...") + state.hubConnect() + else: + echo(OSErrorMsg()) + +proc hubConnect(state: PState) = + state.sock = AsyncSocket() + state.sock.connect("127.0.0.1", state.hubPort) + state.sock.userArg = state + state.sock.handleConnect = handleConnect + state.sock.handleRead = handleRead + + state.dispatcher.register(state.sock) + +proc handleIrc(irc: var TAsyncIRC, event: TIRCEvent, userArg: PObject) = + let state = PState(userArg) + case event.typ + of EvDisconnected: + while not state.ircClient[].isConnected: + try: + state.ircClient.connect() + except: + echo("Error reconnecting: ", getCurrentExceptionMsg()) + + echo("Waiting 5 seconds...") + sleep(5000) + echo("Reconnected successfully!") + of EvMsg: + echo("< ", event.raw) + case event.cmd + of MPrivMsg: + let msg = event.params[event.params.len-1] + let words = msg.split(' ') + template pm(msg: string): stmt = + state.ircClient[].privmsg(event.origin, msg) + case words[0] + of "!ping": pm("pong") + of "!lag": + if state.ircClient[].getLag != -1.0: + var lag = state.ircClient[].getLag + lag = lag * 1000.0 + pm($int(lag) & "ms between me and the server.") + else: + pm("Unknown.") + of "!seen": + if words.len > 1: + let nick = words[1] + if nick == botNickname: + pm("Yes, I see myself.") + echo(nick) + var seenInfo: TSeen + if state.database.getSeen(nick, seenInfo): + var mSend = "" + case seenInfo.kind + of PSeenMsg: + pm("$1 was last seen on $2 in $3 saying: $4" % + [seenInfo.nick, $seenInfo.timestamp, + seenInfo.channel, seenInfo.msg]) + of PSeenJoin: + pm("$1 was last seen on $2 joining $3" % + [seenInfo.nick, $seenInfo.timestamp, seenInfo.channel]) + of PSeenPart: + pm("$1 was last seen on $2 leaving $3 with message: $4" % + [seenInfo.nick, $seenInfo.timestamp, seenInfo.channel, + seenInfo.msg]) + of PSeenQuit: + pm("$1 was last seen on $2 quitting with message: $3" % + [seenInfo.nick, $seenInfo.timestamp, seenInfo.msg]) + of PSeenNick: + pm("$1 was last seen on $2 changing nick to $3" % + [seenInfo.nick, $seenInfo.timestamp, seenInfo.newNick]) + + else: + pm("I have not seen " & nick) + else: + pm("Syntax: !seen <nick>") + + # TODO: ... commands + + # -- Seen + # Log this as activity. + createSeen(PSeenMsg, event.nick, event.origin) + seenNick.msg = msg + state.database.setSeen(seenNick) + of MJoin: + createSeen(PSeenJoin, event.nick, event.origin) + state.database.setSeen(seenNick) + of MPart: + createSeen(PSeenPart, event.nick, event.origin) + let msg = event.params[event.params.high] + seenNick.msg = msg + state.database.setSeen(seenNick) + of MQuit: + createSeen(PSeenQuit, event.nick, event.origin) + let msg = event.params[event.params.high] + seenNick.msg = msg + state.database.setSeen(seenNick) + of MNick: + createSeen(PSeenNick, event.nick, "#nimrod") + seenNick.newNick = event.params[0] + state.database.setSeen(seenNick) + else: + nil # TODO: ? + +proc open(port: TPort = TPort(5123)): PState = + new(result) + result.dispatcher = newDispatcher() + + result.hubPort = port + result.hubConnect() + + # Connect to the irc server. + result.ircClient = AsyncIrc(ircServer, nick = botNickname, user = botNickname, + joinChans = joinChans, ircEvent = handleIrc, userArg = result) + result.ircClient.connect() + result.dispatcher.register(result.ircClient) + + result.dbConnected = false + +var state = tircbot.open() # Connect to the website and the IRC server. + +while state.dispatcher.poll(): + if state.dbConnected: + state.database.keepAlive() diff --git a/tests/reject/t99bott.nim b/tests/reject/t99bott.nim index 7d11ba4b0..7ebfd61e9 100755 --- a/tests/reject/t99bott.nim +++ b/tests/reject/t99bott.nim @@ -1,7 +1,7 @@ discard """ file: "t99bott.nim" line: 26 - errormsg: "cannot evaluate 'GetBottleNumber(bn)'" + errormsg: "constant expression expected" disabled: false """ ## 99 Bottles of Beer diff --git a/tests/reject/tenumitems.nim b/tests/reject/tenumitems.nim index a0497fd59..b6eee5ba8 100644 --- a/tests/reject/tenumitems.nim +++ b/tests/reject/tenumitems.nim @@ -1,6 +1,6 @@ discard """ line: 7 - errormsg: "a type has no value" + errormsg: "type mismatch" """ type a = enum b,c,d |