diff options
Diffstat (limited to 'builtin/common')
-rw-r--r-- | builtin/common/information_formspecs.lua | 4 | ||||
-rw-r--r-- | builtin/common/misc_helpers.lua | 109 | ||||
-rw-r--r-- | builtin/common/serialize.lua | 34 | ||||
-rw-r--r-- | builtin/common/tests/misc_helpers_spec.lua | 73 | ||||
-rw-r--r-- | builtin/common/tests/serialize_spec.lua | 44 | ||||
-rw-r--r-- | builtin/common/tests/vector_spec.lua | 46 |
6 files changed, 203 insertions, 107 deletions
diff --git a/builtin/common/information_formspecs.lua b/builtin/common/information_formspecs.lua index b977e2656..8afa5bc87 100644 --- a/builtin/common/information_formspecs.lua +++ b/builtin/common/information_formspecs.lua @@ -136,14 +136,14 @@ help_command.func = function(name, param) core.show_formspec(name, "__builtin:help_privs", build_privs_formspec(name)) if name ~= admin then - return + return true end end if param == "" or param == "all" then core.show_formspec(name, "__builtin:help_cmds", build_chatcommands_formspec(name)) if name ~= admin then - return + return true end end diff --git a/builtin/common/misc_helpers.lua b/builtin/common/misc_helpers.lua index d6673a691..715f89bc4 100644 --- a/builtin/common/misc_helpers.lua +++ b/builtin/common/misc_helpers.lua @@ -5,7 +5,7 @@ local string_sub, string_find = string.sub, string.find -------------------------------------------------------------------------------- -function basic_dump(o) +local function basic_dump(o) local tp = type(o) if tp == "number" then return tostring(o) @@ -200,28 +200,11 @@ function table.indexof(list, val) return -1 end -assert(table.indexof({"foo", "bar"}, "foo") == 1) -assert(table.indexof({"foo", "bar"}, "baz") == -1) - --------------------------------------------------------------------------------- -if INIT ~= "client" then - function file_exists(filename) - local f = io.open(filename, "r") - if f == nil then - return false - else - f:close() - return true - end - end -end -------------------------------------------------------------------------------- function string:trim() return (self:gsub("^%s*(.-)%s*$", "%1")) end -assert(string.trim("\n \t\tfoo bar\t ") == "foo bar") - -------------------------------------------------------------------------------- function math.hypot(x, y) local t @@ -259,64 +242,6 @@ function math.factorial(x) return v end --------------------------------------------------------------------------------- -function get_last_folder(text,count) - local parts = text:split(DIR_DELIM) - - if count == nil then - return parts[#parts] - end - - local retval = "" - for i=1,count,1 do - retval = retval .. parts[#parts - (count-i)] .. DIR_DELIM - end - - return retval -end - --------------------------------------------------------------------------------- -function cleanup_path(temppath) - - local parts = temppath:split("-") - temppath = "" - for i=1,#parts,1 do - if temppath ~= "" then - temppath = temppath .. "_" - end - temppath = temppath .. parts[i] - end - - parts = temppath:split(".") - temppath = "" - for i=1,#parts,1 do - if temppath ~= "" then - temppath = temppath .. "_" - end - temppath = temppath .. parts[i] - end - - parts = temppath:split("'") - temppath = "" - for i=1,#parts,1 do - if temppath ~= "" then - temppath = temppath .. "" - end - temppath = temppath .. parts[i] - end - - parts = temppath:split(" ") - temppath = "" - for i=1,#parts,1 do - if temppath ~= "" then - temppath = temppath - end - temppath = temppath .. parts[i] - end - - return temppath -end - function core.formspec_escape(text) if text ~= nil then text = string.gsub(text,"\\","\\\\") @@ -428,10 +353,9 @@ if INIT == "game" then core.rotate_node = function(itemstack, placer, pointed_thing) local name = placer and placer:get_player_name() or "" local invert_wall = placer and placer:get_player_control().sneak or false - core.rotate_and_place(itemstack, placer, pointed_thing, + return core.rotate_and_place(itemstack, placer, pointed_thing, is_creative(name), {invert_wall = invert_wall}, true) - return itemstack end end @@ -521,9 +445,6 @@ function core.string_to_pos(value) return nil end -assert(core.string_to_pos("10.0, 5, -2").x == 10) -assert(core.string_to_pos("( 10.0, 5, -2)").z == -2) -assert(core.string_to_pos("asd, 5, -2)") == nil) -------------------------------------------------------------------------------- function core.string_to_area(value) @@ -576,6 +497,29 @@ function table.insert_all(t, other) end +function table.key_value_swap(t) + local ti = {} + for k,v in pairs(t) do + ti[v] = k + end + return ti +end + + +function table.shuffle(t, from, to, random) + from = from or 1 + to = to or #t + random = random or math.random + local n = to - from + 1 + while n > 1 do + local r = from + n-1 + local l = from + random(0, n-1) + t[l], t[r] = t[r], t[l] + n = n-1 + end +end + + -------------------------------------------------------------------------------- -- mainmenu only functions -------------------------------------------------------------------------------- @@ -756,6 +700,3 @@ function core.privs_to_string(privs, delim) end return table.concat(list, delim) end - -assert(core.string_to_privs("a,b").b == true) -assert(core.privs_to_string({a=true,b=true}) == "a,b") diff --git a/builtin/common/serialize.lua b/builtin/common/serialize.lua index c91d2d5ce..163aa67ad 100644 --- a/builtin/common/serialize.lua +++ b/builtin/common/serialize.lua @@ -177,13 +177,16 @@ end -- Deserialization -local env = { - loadstring = loadstring, -} +local function safe_loadstring(...) + local func, err = loadstring(...) + if func then + setfenv(func, {}) + return func + end + return nil, err +end -local safe_env = { - loadstring = function() end, -} +local function dummy_func() end function core.deserialize(str, safe) if type(str) ~= "string" then @@ -195,7 +198,10 @@ function core.deserialize(str, safe) end local f, err = loadstring(str) if not f then return nil, err end - setfenv(f, safe and safe_env or env) + + -- The environment is recreated every time so deseralized code cannot + -- pollute it with permanent references. + setfenv(f, {loadstring = safe and dummy_func or safe_loadstring}) local good, data = pcall(f) if good then @@ -204,17 +210,3 @@ function core.deserialize(str, safe) return nil, data end end - - --- Unit tests -local test_in = {cat={sound="nyan", speed=400}, dog={sound="woof"}} -local test_out = core.deserialize(core.serialize(test_in)) - -assert(test_in.cat.sound == test_out.cat.sound) -assert(test_in.cat.speed == test_out.cat.speed) -assert(test_in.dog.sound == test_out.dog.sound) - -test_in = {escape_chars="\n\r\t\v\\\"\'", non_european="θשׁ٩∂"} -test_out = core.deserialize(core.serialize(test_in)) -assert(test_in.escape_chars == test_out.escape_chars) -assert(test_in.non_european == test_out.non_european) diff --git a/builtin/common/tests/misc_helpers_spec.lua b/builtin/common/tests/misc_helpers_spec.lua new file mode 100644 index 000000000..bb9d13e7f --- /dev/null +++ b/builtin/common/tests/misc_helpers_spec.lua @@ -0,0 +1,73 @@ +_G.core = {} +dofile("builtin/common/misc_helpers.lua") + +describe("string", function() + it("trim()", function() + assert.equal("foo bar", string.trim("\n \t\tfoo bar\t ")) + end) + + describe("split()", function() + it("removes empty", function() + assert.same({ "hello" }, string.split("hello")) + assert.same({ "hello", "world" }, string.split("hello,world")) + assert.same({ "hello", "world" }, string.split("hello,world,,,")) + assert.same({ "hello", "world" }, string.split(",,,hello,world")) + assert.same({ "hello", "world", "2" }, string.split("hello,,,world,2")) + assert.same({ "hello ", " world" }, string.split("hello :| world", ":|")) + end) + + it("keeps empty", function() + assert.same({ "hello" }, string.split("hello", ",", true)) + assert.same({ "hello", "world" }, string.split("hello,world", ",", true)) + assert.same({ "hello", "world", "" }, string.split("hello,world,", ",", true)) + assert.same({ "hello", "", "", "world", "2" }, string.split("hello,,,world,2", ",", true)) + assert.same({ "", "", "hello", "world", "2" }, string.split(",,hello,world,2", ",", true)) + assert.same({ "hello ", " world | :" }, string.split("hello :| world | :", ":|")) + end) + + it("max_splits", function() + assert.same({ "one" }, string.split("one", ",", true, 2)) + assert.same({ "one,two,three,four" }, string.split("one,two,three,four", ",", true, 0)) + assert.same({ "one", "two", "three,four" }, string.split("one,two,three,four", ",", true, 2)) + assert.same({ "one", "", "two,three,four" }, string.split("one,,two,three,four", ",", true, 2)) + assert.same({ "one", "two", "three,four" }, string.split("one,,,,,,two,three,four", ",", false, 2)) + end) + + it("pattern", function() + assert.same({ "one", "two" }, string.split("one,two", ",", false, -1, true)) + assert.same({ "one", "two", "three" }, string.split("one2two3three", "%d", false, -1, true)) + end) + end) +end) + +describe("privs", function() + it("from string", function() + assert.same({ a = true, b = true }, core.string_to_privs("a,b")) + end) + + it("to string", function() + assert.equal("one", core.privs_to_string({ one=true })) + + local ret = core.privs_to_string({ a=true, b=true }) + assert(ret == "a,b" or ret == "b,a") + end) +end) + +describe("pos", function() + it("from string", function() + assert.same({ x = 10, y = 5.1, z = -2}, core.string_to_pos("10.0, 5.1, -2")) + assert.same({ x = 10, y = 5.1, z = -2}, core.string_to_pos("( 10.0, 5.1, -2)")) + assert.is_nil(core.string_to_pos("asd, 5, -2)")) + end) + + it("to string", function() + assert.equal("(10.1,5.2,-2.3)", core.pos_to_string({ x = 10.1, y = 5.2, z = -2.3})) + end) +end) + +describe("table", function() + it("indexof()", function() + assert.equal(1, table.indexof({"foo", "bar"}, "foo")) + assert.equal(-1, table.indexof({"foo", "bar"}, "baz")) + end) +end) diff --git a/builtin/common/tests/serialize_spec.lua b/builtin/common/tests/serialize_spec.lua new file mode 100644 index 000000000..c41b0a372 --- /dev/null +++ b/builtin/common/tests/serialize_spec.lua @@ -0,0 +1,44 @@ +_G.core = {} + +_G.setfenv = require 'busted.compatibility'.setfenv + +dofile("builtin/common/serialize.lua") + +describe("serialize", function() + it("works", function() + local test_in = {cat={sound="nyan", speed=400}, dog={sound="woof"}} + local test_out = core.deserialize(core.serialize(test_in)) + + assert.same(test_in, test_out) + end) + + it("handles characters", function() + local test_in = {escape_chars="\n\r\t\v\\\"\'", non_european="θשׁ٩∂"} + local test_out = core.deserialize(core.serialize(test_in)) + assert.same(test_in, test_out) + end) + + it("handles recursive structures", function() + local test_in = { hello = "world" } + test_in.foo = test_in + + local test_out = core.deserialize(core.serialize(test_in)) + assert.same(test_in, test_out) + end) + + it("strips functions in safe mode", function() + local test_in = { + func = function(a, b) + error("test") + end, + foo = "bar" + } + + local str = core.serialize(test_in) + assert.not_nil(str:find("loadstring")) + + local test_out = core.deserialize(str, true) + assert.is_nil(test_out.func) + assert.equals(test_out.foo, "bar") + end) +end) diff --git a/builtin/common/tests/vector_spec.lua b/builtin/common/tests/vector_spec.lua new file mode 100644 index 000000000..79f032f28 --- /dev/null +++ b/builtin/common/tests/vector_spec.lua @@ -0,0 +1,46 @@ +_G.vector = {} +dofile("builtin/common/vector.lua") + +describe("vector", function() + describe("new()", function() + it("constructs", function() + assert.same({ x = 0, y = 0, z = 0 }, vector.new()) + assert.same({ x = 1, y = 2, z = 3 }, vector.new(1, 2, 3)) + assert.same({ x = 3, y = 2, z = 1 }, vector.new({ x = 3, y = 2, z = 1 })) + + local input = vector.new({ x = 3, y = 2, z = 1 }) + local output = vector.new(input) + assert.same(input, output) + assert.are_not.equal(input, output) + end) + + it("throws on invalid input", function() + assert.has.errors(function() + vector.new({ x = 3 }) + end) + + assert.has.errors(function() + vector.new({ d = 3 }) + end) + end) + end) + + it("equal()", function() + local function assertE(a, b) + assert.is_true(vector.equals(a, b)) + end + local function assertNE(a, b) + assert.is_false(vector.equals(a, b)) + end + + assertE({x = 0, y = 0, z = 0}, {x = 0, y = 0, z = 0}) + assertE({x = -1, y = 0, z = 1}, {x = -1, y = 0, z = 1}) + local a = { x = 2, y = 4, z = -10 } + assertE(a, a) + assertNE({x = -1, y = 0, z = 1}, a) + end) + + it("add()", function() + assert.same({ x = 2, y = 4, z = 6 }, vector.add(vector.new(1, 2, 3), { x = 1, y = 2, z = 3 })) + end) +end) |