Commit 40f54e45 authored by Jamie A. Jennings's avatar Jamie A. Jennings

A tiny bit more refactoring done. Added engine:lookup() which returns rplx.

parent 86d15249
......@@ -618,6 +618,25 @@ local function shallow_copy(tbl)
return new
end
-- toboolean()
local function bool(value)
return not not value
end
local create_rplx
local function lookup_rplx(self, localname, pkgname, is_local)
local pkgenv = pkgname and self.env:lookup(pkgname)
if not pkgenv then return nil; end
local pat = pkgenv:lookup(localname)
if not pat then return nil; end
if bool(pat.exported) == not bool(is_local) then
return create_rplx(self, pat)
end
return nil
end -- look up
----------------------------------------------------------------------------------------
-- Engine and rplx structures
......@@ -680,7 +699,8 @@ engine =
block_dependencies = block_dependencies,
expression_dependencies = expression_dependencies,
macro_expand = macro_expand,
lookup = lookup_rplx,
set_encoder_parm = set_encoder_parm,
get_encoder_parms = function(self) return self.encoder_parms; end,
encoder_parms = false,
......@@ -697,7 +717,7 @@ engine =
-- FUTURE: Since rplx is already compiled, arrange for rplx.match to call a
-- streamlined version of engine_match that does not need to check to see if the
-- expression is a string and compile it.
local create_rplx = function(en, pattern)
create_rplx = function(en, pattern)
return rplx.factory{ engine=en,
pattern=pattern,
match=function(self, input, start, encoder, t0, t1)
......
......@@ -93,11 +93,58 @@ local function extract_test_string(p)
return teststr
end
-- Args:
-- rosie, the rosie module (for creating a new engine, and rplx objects for en)
-- en, the engine that has patterns for extracting test cases
-- args, the CLI args needed to set up the test engine
-- filename, the rpl file to load (compile) and which has the tests
local function write_compilation_error(exp, message)
unittest.write_test_result("ERROR: " .. message .. ": ",
tostring(exp))
end
local function test_exp(test_engine, pkgname, original_exp, q, should_accept, is_local)
-- returns status, result
-- where status is true if test passed, false if test failed, nil if error
local exp = original_exp
if pkgname then
exp = common.compose_id({pkgname, original_exp})
end
local ok, res, leftover
if not is_local then
-- The binding we want to test is not local, so it must be visible in
-- test_engine.
ok, res, leftover = test_engine:match(exp, q)
if (not ok) then
if test_engine:lookup(original_exp, pkgname, true) then
write_compilation_error(original_exp, "pattern is local; use 'test local' instead")
else
write_compilation_error(original_exp, "pattern did not compile (or is not defined)")
end
return nil
end
else
-- The binding we want to test is local to the package, so it is not
-- visible in the environment of test_engine. But we can extract it to
-- run the tests.
local compiled_pattern = test_engine:lookup(original_exp, pkgname, true)
if not compiled_pattern then
-- User wants to test a local, but it's either not there or is exported
if test_engine:lookup(original_exp, pkgname, false) then
write_compilation_error(original_exp, "pattern is exported; use 'test' not 'test local'")
else
write_compilation_error(original_exp, "pattern did not compile (or is not defined)")
end
return nil
end -- if not compiled_pattern
ok = true
res, leftover = compiled_pattern:match(q)
end -- if is_local
-- At this point, ok is true, and useful values are in: res, leftover
local accepted = res and (leftover == 0)
return (should_accept == accepted), res
end
-- Args to run():
-- rosie, the rosie module (for creating a new engine, and rplx objects for en)
-- en, the engine that has patterns for extracting test cases
-- args, the CLI args needed to set up the test engine
-- filename, the rpl file to load (compile) and which has the tests
-- Return values:
-- true if no execution errors, and if that is the case, then also:
-- number of test errors, failures, blocked, passed, and total
......@@ -127,69 +174,6 @@ function unittest.run(rosie, en, args, filename)
unittest.write_test_result("No tests found")
return true, 0, 0
end
local function find_local(en, pkgname, identifier)
-- returns an rplx if identifier found in pkgname, or
-- false if not found, or
-- nil if found but is exported, i.e. not a local
local pkgenv = pkgname and en.env:lookup(pkgname)
if pkgenv then
local pat = pkgenv:lookup(identifier)
if pat then
if pat.exported then
return nil
end
return rosie.rplx.new(en, pat)
end
end
return false
end
local function write_compilation_error(exp, message)
unittest.write_test_result("ERROR: " .. message .. ": ",
tostring(exp))
end
local function test_exp(original_exp, q, should_accept, is_local)
-- returns status, result
-- where status is true if test passed, false if test failed, nil if error
local exp = original_exp
if pkgname then
exp = common.compose_id({pkgname, original_exp})
end
local ok, res, leftover
if not is_local then
-- The binding we want to test is not local, so it must be visible in
-- test_engine.
ok, res, leftover = test_engine:match(exp, q)
if (not ok) then
local found_as_local = find_local(test_engine, pkgname, original_exp)
if found_as_local then
write_compilation_error(original_exp, "pattern is local; use 'test local' instead")
else
write_compilation_error(original_exp, "pattern did not compile (or is not defined)")
end
return nil
end
else
-- The binding we want to test is local to the package, so it is not
-- visible in the environment of test_engine. But we can extract it to
-- run the tests.
local compiled_pattern = find_local(test_engine, pkgname, original_exp)
if not compiled_pattern then
-- User wants to test a local, but it's either not there or is exported
if compiled_pattern == nil then
write_compilation_error(original_exp, "pattern is exported; use 'test' not 'test local'")
else
write_compilation_error(original_exp, "pattern did not compile (or is not defined)")
end
return nil
end -- if not compiled_pattern
assert(rosie.rplx.is(compiled_pattern))
ok = true
res, leftover = compiled_pattern:match(q)
end -- if is_local
-- At this point, ok is true, and useful values are in: res, leftover
local accepted = res and (leftover == 0)
return (should_accept == accepted), res
end
-- return values: true, false, nil (where nil means failure to match), or "error"
local function test_includes_ident(exp, q, id, is_local)
local function searchForID(tbl, id)
......@@ -208,7 +192,7 @@ function unittest.run(rosie, en, args, filename)
end
return found
end
local matched, res = test_exp(exp, q, true, is_local)
local matched, res = test_exp(test_engine, pkgname, exp, q, true, is_local)
if matched == nil then
return "error"
elseif matched == false then
......@@ -308,7 +292,7 @@ function unittest.run(rosie, en, args, filename)
errors = errors + 1
unittest.write_test_result("ERROR: ", msg)
else
local result = test_exp(testIdentifier, teststr, should_accept, is_local_identifier)
local result = test_exp(test_engine, pkgname, testIdentifier, teststr, should_accept, is_local_identifier)
if not result then
if result==nil then
errors = errors + 1
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment