From fe6efc27629cf08d3eeb705d5112685ea7540d76 Mon Sep 17 00:00:00 2001 From: Daniel Silverstone Date: Sun, 13 May 2012 21:12:21 +0100 Subject: Ensure default command works, via compiler assistance --- lib/lace/builtin.lua | 4 +++- lib/lace/compiler.lua | 28 +++++++++++++++++++++++ test/test-lace.compiler.lua | 55 ++++++++++++++++++++++++++++++++++++++++++--- 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() -- cgit v1.2.1