Permalink
Cannot retrieve contributors at this time
Name already in use
A tag already exists with the provided branch name. Many Git commands accept both tag and branch names, so creating this branch may cause unexpected behavior. Are you sure you want to create this branch?
lua-nucleo/test/cases/0050-coro.lua
Go to fileThis commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
333 lines (247 sloc)
9.86 KB
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| -------------------------------------------------------------------------------- | |
| -- 0050-coro.lua: tests for coroutine module extensions | |
| -- This file is a part of lua-nucleo library | |
| -- Copyright (c) lua-nucleo authors (see file `COPYRIGHT` for the license) | |
| -------------------------------------------------------------------------------- | |
| local make_suite = assert(loadfile('test/test-lib/init/strict.lua'))(...) | |
| local select, assert, type, tostring = select, assert, type, tostring | |
| local table_concat = table.concat | |
| local coroutine_create, coroutine_yield, coroutine_status, coroutine_resume = | |
| coroutine.create, coroutine.yield, coroutine.status, coroutine.resume | |
| local ensure, | |
| ensure_equals, | |
| ensure_tequals | |
| = import 'lua-nucleo/ensure.lua' | |
| { | |
| 'ensure', | |
| 'ensure_equals', | |
| 'ensure_tequals' | |
| } | |
| local make_concatter = import 'lua-nucleo/string.lua' { 'make_concatter' } | |
| local eat_true = import 'lua-nucleo/args.lua' { 'eat_true' } | |
| local coro = import 'lua-nucleo/coro.lua' () | |
| -------------------------------------------------------------------------------- | |
| local eat_tag = function(v, ...) | |
| if not coro.is_outer_yield_tag(v) then | |
| error("can't eat outer yield tag, it is: "..tostring(v), 2) | |
| end | |
| return ... | |
| end | |
| local eat_true_tag = function(...) | |
| return eat_tag(eat_true(...)) | |
| end | |
| -------------------------------------------------------------------------------- | |
| local test = make_suite("coro", coro) | |
| -------------------------------------------------------------------------------- | |
| -- NOTE: Tests below check all these functions in conjunction, | |
| -- so we're simply declaring them here as tested. | |
| -- When adding function to this list, make sure it has tests first. | |
| test:tests_for 'resume_inner' | |
| -------------------------------------------------------------------------------- | |
| test "yield_inner" (function() | |
| local co = coroutine_create(function(A) | |
| ensure_equals("A", A, "A") | |
| ensure_equals("C", coroutine_yield("B"), "C") | |
| return "D" | |
| end) | |
| ensure_equals("B", eat_true(coro.resume_inner(co, "A")), "B") | |
| ensure_equals("D", eat_true(coro.resume_inner(co, "C")), "D") | |
| ensure_equals("coroutine dead", coroutine_status(co), "dead") | |
| end) | |
| -------------------------------------------------------------------------------- | |
| test:test_for "yield_outer" (function() | |
| local co = coroutine_create(function(A) | |
| ensure_equals("A", A, "A") | |
| ensure_equals("C", coro.yield_outer("B"), "C") | |
| return "D" | |
| end) | |
| ensure_equals("B", eat_true_tag(coroutine_resume(co, "A")), "B") | |
| ensure_equals("D", eat_true(coro.resume_inner(co, "C")), "D") | |
| ensure_equals("coroutine dead", coroutine_status(co), "dead") | |
| end) | |
| -------------------------------------------------------------------------------- | |
| test "inner-inner-yield_inner" (function() | |
| local inner1 = coroutine_create(function(A) | |
| assert(A == "A") | |
| local inner2 = coroutine_create(function(B) | |
| assert(B == "B") | |
| assert(coroutine_yield("C") == "D") | |
| return "E" | |
| end) | |
| assert(eat_true(coro.resume_inner(inner2, "B")) == "C") | |
| assert(eat_true(coro.resume_inner(inner2, "D")) == "E") | |
| assert(coroutine_status(inner2) == "dead") | |
| return "F" | |
| end) | |
| assert(eat_true(coro.resume_inner(inner1, "A")) == "F") | |
| assert(coroutine_status(inner1) == "dead") | |
| end) | |
| -------------------------------------------------------------------------------- | |
| test "outer-inner-inner-yield_outer" (function() | |
| local outer = coroutine_create(function(A) | |
| ensure_equals("A", A, "A") | |
| local inner1 = coroutine_create(function(B) | |
| ensure_equals("B", B, "B") | |
| local inner2 = coroutine_create(function(C) | |
| ensure_equals("C", C, "C") | |
| ensure_equals("E", coro.yield_outer("D"), "E") | |
| return "F" | |
| end) | |
| ensure_equals("F", eat_true(coro.resume_inner(inner2, "C")), "F") | |
| ensure_equals("inner2 dead", coroutine_status(inner2), "dead") | |
| return "G" | |
| end) | |
| ensure_equals("G", eat_true(coro.resume_inner(inner1, "B")), "G") | |
| ensure_equals("inner1 dead", coroutine_status(inner1), "dead") | |
| return "H" | |
| end) | |
| ensure_equals("D", eat_true_tag(coroutine_resume(outer, "A")),"D") | |
| ensure_equals("H", eat_true(coroutine_resume(outer, "E")), "H") | |
| ensure_equals("outer dead", coroutine_status(outer), "dead") | |
| end) | |
| -------------------------------------------------------------------------------- | |
| test "outer-inner-inner-yield_outer-twice" (function() | |
| local outer = coroutine_create(function(A) | |
| ensure_equals("A", A, "A") | |
| local inner1 = coroutine_create(function(B) | |
| ensure_equals("B", B, "B") | |
| local inner2 = coroutine_create(function(C) | |
| ensure_equals("C", C, "C") | |
| ensure_equals("E", coro.yield_outer("D"), "E") | |
| ensure_equals("G", coro.yield_outer("F"), "G") | |
| return "H" | |
| end) | |
| ensure_equals("H", eat_true(coro.resume_inner(inner2, "C")), "H") | |
| ensure_equals("inner2 dead", coroutine_status(inner2), "dead") | |
| return "I" | |
| end) | |
| ensure_equals("F", eat_true(coro.resume_inner(inner1, "B")), "I") | |
| ensure_equals("inner1 dead", coroutine_status(inner1), "dead") | |
| return "J" | |
| end) | |
| ensure_equals("D", eat_true_tag(coroutine_resume(outer, "A")), "D") | |
| ensure_equals("J", eat_true_tag(coroutine_resume(outer, "E")), "F") | |
| ensure_equals("J", eat_true(coroutine_resume(outer, "G")), "J") | |
| ensure_equals("outer dead", coroutine_status(outer), "dead") | |
| end) | |
| -------------------------------------------------------------------------------- | |
| --[[ | |
| Mesage passing scheme for basic test: | |
| main outer inner1 inner2 | |
| | . . . | |
| A--------c->* . . | |
| | | . . | |
| *<=g========B . . | |
| | | . . | |
| C========g=>* . . | |
| | | . . | |
| *<-l--------D . . | |
| | | . . | |
| E--------l->* . . | |
| | | . . | |
| | F--------c->* . | |
| | | | . | |
| *<=g========o===========G . | |
| | | | . | |
| H===========o========g=>* . | |
| | | | . | |
| | <-l---------I . | |
| | | | . | |
| | J--------l->* . | |
| | | | . | |
| | | K----------c->* | |
| | | | | | |
| *<=g========o===========o=============L | |
| | | | | | |
| M===========o===========o==========g=>* | |
| | | | | | |
| | | *<-l----------N | |
| | | | | | |
| | | O----------l->* | |
| | | | | | |
| | | *<-r----------P | |
| | | | . | |
| | *<-r--------Q . | |
| | | . . | |
| *<-r--------R . . | |
| | . . . | |
| --]] | |
| test "basic" (function() | |
| local cat, concat = make_concatter() | |
| do | |
| local outer = coroutine_create(function(A) | |
| cat(A) --> A | |
| cat(coro.yield_outer("B")) --> C | |
| -- Outer coroutines may do inner yields | |
| -- (in case they're held by inner corouines). | |
| cat(coroutine_yield("D")) --> E | |
| local inner1 = coroutine_create(function(F) | |
| cat(F) --> F | |
| cat(coro.yield_outer("G")) --> H | |
| cat(coroutine_yield("I")) --> J | |
| local inner2 = coroutine_create(function(K) | |
| cat(K) | |
| cat(coro.yield_outer("L")) --> M | |
| cat(coroutine_yield("N")) --> O | |
| return "P" | |
| end) | |
| cat(eat_true(coro.resume_inner(inner2, "K"))) --> N | |
| cat(eat_true(coro.resume_inner(inner2, "O"))) --> P | |
| assert(coroutine_status(inner2) == "dead") | |
| return "Q" | |
| end) | |
| cat(eat_true(coro.resume_inner(inner1, "F"))) --> I | |
| cat(eat_true(coro.resume_inner(inner1, "J"))) --> Q | |
| assert(coroutine_status(inner1) == "dead") | |
| return "R" | |
| end) | |
| cat(eat_true_tag(coroutine_resume(outer, "A"))) --> B | |
| cat(eat_true(coroutine_resume(outer, "C"))) --> D | |
| cat(eat_true_tag(coroutine_resume(outer, "E"))) --> G | |
| cat(eat_true_tag(coroutine_resume(outer, "H"))) --> L | |
| cat(eat_true(coroutine_resume(outer, "M"))) --> R | |
| assert(coroutine_status(outer) == "dead") | |
| end | |
| assert(concat() == "ABCDEFGHIJKLMNOPQR") | |
| end) | |
| -------------------------------------------------------------------------------- | |
| -- NOTE: Tests below check all these functions in conjunction, | |
| -- so we're simply declaring them here as tested. | |
| -- When adding function to this list, make sure it has tests first. | |
| test:tests_for 'eat_tag' | |
| 'is_outer_yield_tag' | |
| -------------------------------------------------------------------------------- | |
| test:test "eat_tag-is_outer_yield_tag-not-tag" (function() | |
| ensure_equals("that is not the tag", coro.is_outer_yield_tag(42), false) | |
| ensure_tequals( | |
| "do not eat non-tag true", | |
| { coro.eat_tag(true, 42) }, | |
| { true, 42 } | |
| ) | |
| ensure_tequals( | |
| "do not eat non-tag false", | |
| { coro.eat_tag(false, 42) }, | |
| { false, 42 } | |
| ) | |
| end) | |
| test:test "eat_tag-is_outer_yield_tag-actual-tag" (function() | |
| local tag | |
| do | |
| local co = coroutine_create(function() | |
| coro.yield_outer() | |
| end) | |
| local _ | |
| _, tag = assert(coroutine.resume(co)) | |
| end | |
| ensure_equals("that is the tag", coro.is_outer_yield_tag(tag), true) | |
| ensure_tequals( | |
| "eat tag true", | |
| { coro.eat_tag(true, tag, 42) }, | |
| { true, 42 } | |
| ) | |
| ensure_tequals( | |
| "eat tag false", | |
| { coro.eat_tag(false, tag, 42) }, | |
| { false, 42 } | |
| ) | |
| end) |