summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDaniel Silverstone <dsilvers@digital-scurf.org>2012-05-13 21:12:21 +0100
committerDaniel Silverstone <dsilvers@digital-scurf.org>2012-05-13 21:12:21 +0100
commitfe6efc27629cf08d3eeb705d5112685ea7540d76 (patch)
treef70770a4140b5beb01bc4e42c413bf7984757599
parent5b497fab972a8f22963b9c76b36b7d2ed6689711 (diff)
downloadlace-fe6efc27629cf08d3eeb705d5112685ea7540d76.tar.gz
Ensure default command works, via compiler assistance
-rw-r--r--lib/lace/builtin.lua4
-rw-r--r--lib/lace/compiler.lua28
-rw-r--r--test/test-lace.compiler.lua55
3 files changed, 83 insertions, 4 deletions
diff --git a/lib/lace/builtin.lua b/lib/lace/builtin.lua
index ff1cfd2..928724b 100644
--- a/lib/lace/builtin.lua
+++ b/lib/lace/builtin.lua
@@ -80,8 +80,10 @@ function builtin.default(compcontext, def, result, reason, unwanted)
if compcontext[".lace"].default then
return compiler().error("Cannot change the default")
end
-
+
+ local uncond, last = unconditional_result, last_result
compcontext[".lace"].default = _return(compcontext, result, reason)
+ unconditional_result, last_result = uncond, last
return {
fn = function() return true end,
diff --git a/lib/lace/compiler.lua b/lib/lace/compiler.lua
index bd57671..538c27b 100644
--- a/lib/lace/compiler.lua
+++ b/lib/lace/compiler.lua
@@ -92,6 +92,9 @@ local function internal_compile_ruleset(compcontext, sourcename, content)
rules = {},
}
+ local prev_uncond_result = builtin.get_set_last_unconditional_result()
+ local prev_result = builtin.get_set_last_result()
+
for i = 1, #lexed_content.lines do
local line = lexed_content.lines[i]
if line.type == "rule" then
@@ -106,6 +109,31 @@ local function internal_compile_ruleset(compcontext, sourcename, content)
end
end
+ -- And restore the builtin result (in case we were chained/included)
+ local uncond = builtin.get_set_last_unconditional_result(prev_uncond_result)
+ local result = builtin.get_set_last_result(prev_result)
+ -- Finally consider the default behaviour
+ -- Cases to consider are:
+ -- There's an unconditional result, in which case no problem
+ -- There's no result whatsoever, conditional or otherwise, error out
+ -- There's no unconditional result but there's a default
+ -- in which case use the default
+ -- There's no unconditional result and no default, fake up a default and
+ -- then use it.
+ if not uncond and not result then
+ return false, "No result set whatsoever"
+ end
+
+ if not uncond then
+ if not compcontext[".lace"].default then
+ -- No default, fake one up
+ builtin.commands.default(compcontext, "default",
+ result == "allow" and "deny" or "allow")
+ end
+ -- Now, inject the default command at the end of the ruleset.
+ ruleset.rules[#ruleset.rules+1] = compcontext[".lace"].default
+ end
+
_setposition(compcontext)
return ruleset
end
diff --git a/test/test-lace.compiler.lua b/test/test-lace.compiler.lua
index 5c5c843..dabc54e 100644
--- a/test/test-lace.compiler.lua
+++ b/test/test-lace.compiler.lua
@@ -55,7 +55,8 @@ end
function suite.empty_content_no_loader()
local result, msg = compiler.compile({[".lace"] = {}}, "", "")
- assert(type(result) == "table", "No ruleset returned?")
+ assert(result == false, "Internal errors should return false")
+ assert(msg:match("whatsoever"), "Supposed to whinge about no allow/deny at all")
end
function suite.no_content_no_loader()
@@ -64,6 +65,54 @@ function suite.no_content_no_loader()
assert(msg:match("Ruleset not found:"), "Supposed to whinge about ruleset not being found")
end
+function suite.no_unconditional_action()
+ local result, msg = compiler.compile({[".lace"] = {}}, "", "deny stuff cond")
+ assert(type(result) == "table", "Loading a ruleset should result in a table")
+ assert(#result.rules == 2, "There should be two rules present")
+ local rule = result.rules[1]
+ assert(type(rule) == "table", "Rules should be tables")
+ assert(type(rule.fn) == "function", "Rules should have functions")
+ assert(type(rule.args) == "table", "Rules should have arguments")
+ -- rule 2 should be an unconditional allow with 'Default behaviour' as the reason,
+ -- let's check
+ local r2a = result.rules[2].args
+ assert(r2a[1] == "allow", "Rule 2 should be an allow")
+ assert(r2a[2] == "Default behaviour", "Rule 2's reason should be 'Default behaviour'")
+ assert(#r2a[3] == 0, "Rule 2 should have no conditions")
+end
+
+function suite.no_unconditional_action_default_deny()
+ local result, msg = compiler.compile({[".lace"] = {}}, "", "default deny\ndeny stuff cond")
+ assert(type(result) == "table", "Loading a ruleset should result in a table")
+ assert(#result.rules == 3, "There should be three rules present")
+ local rule = result.rules[1]
+ assert(type(rule) == "table", "Rules should be tables")
+ assert(type(rule.fn) == "function", "Rules should have functions")
+ assert(type(rule.args) == "table", "Rules should have arguments")
+ -- rule 3 should be an unconditional deny with 'Default behaviour' as the reason,
+ -- let's check
+ local r3a = result.rules[3].args
+ assert(r3a[1] == "deny", "Rule 3 should be a deny, despite last rule behind a deny")
+ assert(r3a[2] == "Default behaviour", "Rule 3's reason should be 'Default behaviour'")
+ assert(#r3a[3] == 0, "Rule 2 should have no conditions")
+end
+
+function suite.is_unconditional_action_default_deny()
+ local result, msg = compiler.compile({[".lace"] = {}}, "", "default deny\nallow stuff")
+ assert(type(result) == "table", "Loading a ruleset should result in a table")
+ assert(#result.rules == 2, "There should be two rules present")
+ local rule = result.rules[1]
+ assert(type(rule) == "table", "Rules should be tables")
+ assert(type(rule.fn) == "function", "Rules should have functions")
+ assert(type(rule.args) == "table", "Rules should have arguments")
+ -- rule 2 should be an unconditional allow with 'stuff' as the reason
+ -- let's check
+ local r2a = result.rules[2].args
+ assert(r2a[1] == "allow", "Rule 2 should be an allow, despite default being deny")
+ assert(r2a[2] == "stuff", "Rule 2's reason should be 'stuff'")
+ assert(#r2a[3] == 0, "Rule 2 should have no conditions")
+end
+
-- Now we set up a more useful context and use that going forward:
local comp_context = {
@@ -100,8 +149,8 @@ end
function suite.load_file_with_no_rules()
local result, msg = compiler.compile(comp_context, "nothing")
- assert(type(result) == "table", "Loading a ruleset should result in a table")
- assert(#result.rules == 0, "There should be no rules present")
+ assert(result == false, "Internal errors should return false")
+ assert(msg:match("whatsoever"), "Error returned didn't match expected whinge about no allow/deny")
end
function suite.load_file_with_bad_command()