diff --git a/script/test.py b/script/test.py index 023e9534..dcd83756 100755 --- a/script/test.py +++ b/script/test.py @@ -19,7 +19,7 @@ EXPECT_ERROR_PATTERN = re.compile(r'// expect error(?! line)') EXPECT_ERROR_LINE_PATTERN = re.compile(r'// expect error line (\d+)') EXPECT_RUNTIME_ERROR_PATTERN = re.compile(r'// expect runtime error: (.+)') ERROR_PATTERN = re.compile(r'\[.* line (\d+)\] Error') -STACK_TRACE_PATTERN = re.compile(r'\[.* line (\d+)\] in') +STACK_TRACE_PATTERN = re.compile(r'\[main line (\d+)\] in') STDIN_PATTERN = re.compile(r'// stdin: (.*)') SKIP_PATTERN = re.compile(r'// skip: (.*)') NONTEST_PATTERN = re.compile(r'// nontest') @@ -159,11 +159,17 @@ class Test: self.runtime_error_message) self.fail(error_lines[0]) - # Make sure the stack trace has the right line. - match = STACK_TRACE_PATTERN.search(error_lines[1]) + # Make sure the stack trace has the right line. Skip over any lines that + # come from builtin libraries. + stack_lines = error_lines[1:] + for stack_line in stack_lines: + match = STACK_TRACE_PATTERN.search(stack_line) + if match: break + if not match: self.fail('Expected stack trace and got:') - self.fail(error_lines[1]) + for stack_line in stack_lines: + self.fail(stack_line) else: stack_line = int(match.group(1)) if stack_line != self.runtime_error_line: diff --git a/src/module/timer.c b/src/module/timer.c index 62c3eb48..9cfba26f 100644 --- a/src/module/timer.c +++ b/src/module/timer.c @@ -11,6 +11,8 @@ static const char* timerLibSource = "class Timer {\n" " static sleep(milliseconds) {\n" +" if (!(milliseconds is Num)) Fiber.abort(\"Milliseconds must be a number.\")\n" +" if (milliseconds < 0) Fiber.abort(\"Milliseconds cannot be negative.\")\n" " startTimer_(milliseconds, Fiber.current)\n" " Fiber.yield()\n" " }\n" diff --git a/src/module/timer.h b/src/module/timer.h index 0f8f311d..8c3384b9 100644 --- a/src/module/timer.h +++ b/src/module/timer.h @@ -3,7 +3,6 @@ #include "wren.h" -// TODO: Coherent naming scheme. char* timerGetSource(); WrenForeignMethodFn timerBindForeign( diff --git a/src/module/timer.wren b/src/module/timer.wren index 18f54eaf..a6ea328d 100644 --- a/src/module/timer.wren +++ b/src/module/timer.wren @@ -1,5 +1,7 @@ class Timer { static sleep(milliseconds) { + if (!(milliseconds is Num)) Fiber.abort("Milliseconds must be a number.") + if (milliseconds < 0) Fiber.abort("Milliseconds cannot be negative.") startTimer_(milliseconds, Fiber.current) Fiber.yield() } diff --git a/test/timer/sleep_fibers.wren b/test/timer/sleep_fibers.wren new file mode 100644 index 00000000..88e308c9 --- /dev/null +++ b/test/timer/sleep_fibers.wren @@ -0,0 +1,19 @@ +import "timer" for Timer + +Fiber.new { + Timer.sleep(2) + IO.print("a") +}.call() + +Fiber.new { + Timer.sleep(1) + IO.print("b") +}.call() + +IO.print("main") +Timer.sleep(3) +IO.print("done") +// expect: main +// expect: b +// expect: a +// expect: done diff --git a/test/timer/sleep_float.wren b/test/timer/sleep_float.wren new file mode 100644 index 00000000..f04b6111 --- /dev/null +++ b/test/timer/sleep_float.wren @@ -0,0 +1,20 @@ +import "timer" for Timer + +// These are both rounded to 1, so "a" should complete first. +Fiber.new { + Timer.sleep(1.5) + IO.print("a") +}.call() + +Fiber.new { + Timer.sleep(1.3) + IO.print("b") +}.call() + +IO.print("main") +Timer.sleep(3) +IO.print("done") +// expect: main +// expect: a +// expect: b +// expect: done diff --git a/test/timer/sleep_main_fiber.wren b/test/timer/sleep_main_fiber.wren new file mode 100644 index 00000000..3e3e43fb --- /dev/null +++ b/test/timer/sleep_main_fiber.wren @@ -0,0 +1,9 @@ +import "timer" for Timer + +IO.print("1") // expect: 1 +Timer.sleep(3) +IO.print("2") // expect: 2 +Timer.sleep(3) +IO.print("3") // expect: 3 +Timer.sleep(3) +IO.print("4") // expect: 4 diff --git a/test/timer/sleep_negative.wren b/test/timer/sleep_negative.wren new file mode 100644 index 00000000..15afb714 --- /dev/null +++ b/test/timer/sleep_negative.wren @@ -0,0 +1,3 @@ +import "timer" for Timer + +Timer.sleep(-1) // expect runtime error: Milliseconds cannot be negative. diff --git a/test/timer/sleep_not_num.wren b/test/timer/sleep_not_num.wren new file mode 100644 index 00000000..cbd3d1ed --- /dev/null +++ b/test/timer/sleep_not_num.wren @@ -0,0 +1,3 @@ +import "timer" for Timer + +Timer.sleep("wat") // expect runtime error: Milliseconds must be a number. diff --git a/test/timer/sleep_zero.wren b/test/timer/sleep_zero.wren new file mode 100644 index 00000000..569ffe13 --- /dev/null +++ b/test/timer/sleep_zero.wren @@ -0,0 +1,27 @@ +import "timer" for Timer + +Fiber.new { + Timer.sleep(0) + IO.print("a") +}.call() + +Fiber.new { + Timer.sleep(0) + IO.print("b") +}.call() + +Fiber.new { + Timer.sleep(0) + IO.print("c") +}.call() + +IO.print("main") +Timer.sleep(0) // This is enough to let the other fiber run. +IO.print("done") + +// expect: main +// Run in the order they were enqueued. +// expect: a +// expect: b +// expect: c +// expect: done