diff --git a/.tests/parse/file/testfiles/header_invalid.json b/.tests/parse/file/testfiles/header_invalid.json new file mode 100644 index 0000000..24ff005 --- /dev/null +++ b/.tests/parse/file/testfiles/header_invalid.json @@ -0,0 +1,14 @@ +{ + "name": "A castle", + "size": { + "x": 50, + "y": 25, + "z": 75 + }, + "offset": { + "x": 3, + "y": 0, + "z": 5 + }, + "type": "full", + "generator": "WorldEditAdditions v1.14" diff --git a/.tests/parse/file/testfiles/header_invalid_generator.json b/.tests/parse/file/testfiles/header_invalid_generator.json new file mode 100644 index 0000000..8ef428e --- /dev/null +++ b/.tests/parse/file/testfiles/header_invalid_generator.json @@ -0,0 +1,15 @@ +{ + "name": "A castle", + "size": { + "x": 50, + "y": 25, + "z": 75 + }, + "offset": { + "x": 3, + "y": 0, + "z": 5 + }, + "type": "full", + "generator": 552323 +} \ No newline at end of file diff --git a/.tests/parse/file/testfiles/header_invalid_no_generator.json b/.tests/parse/file/testfiles/header_invalid_no_generator.json new file mode 100644 index 0000000..f62e207 --- /dev/null +++ b/.tests/parse/file/testfiles/header_invalid_no_generator.json @@ -0,0 +1,14 @@ +{ + "name": "A castle", + "size": { + "x": 50, + "y": 25, + "z": 75 + }, + "offset": { + "x": 3, + "y": 0, + "z": 5 + }, + "type": "full" +} \ No newline at end of file diff --git a/.tests/parse/file/testfiles/header_invalid_no_type.json b/.tests/parse/file/testfiles/header_invalid_no_type.json new file mode 100644 index 0000000..f65849b --- /dev/null +++ b/.tests/parse/file/testfiles/header_invalid_no_type.json @@ -0,0 +1,14 @@ +{ + "name": "A castle", + "size": { + "x": 50, + "y": 25, + "z": 75 + }, + "offset": { + "x": 3, + "y": 0, + "z": 5 + }, + "generator": "WorldEditAdditions v1.14" +} \ No newline at end of file diff --git a/.tests/parse/file/testfiles/header_invalid_type.json b/.tests/parse/file/testfiles/header_invalid_type.json new file mode 100644 index 0000000..41dd19a --- /dev/null +++ b/.tests/parse/file/testfiles/header_invalid_type.json @@ -0,0 +1,15 @@ +{ + "name": "A castle", + "size": { + "x": 50, + "y": 25, + "z": 75 + }, + "offset": { + "x": 3, + "y": 0, + "z": 5 + }, + "type": 55, + "generator": "WorldEditAdditions v1.14" +} \ No newline at end of file diff --git a/.tests/parse/file/testfiles/header_invalid_type_typo.json b/.tests/parse/file/testfiles/header_invalid_type_typo.json new file mode 100644 index 0000000..ae8d25d --- /dev/null +++ b/.tests/parse/file/testfiles/header_invalid_type_typo.json @@ -0,0 +1,15 @@ +{ + "name": "A castle", + "size": { + "x": 50, + "y": 25, + "z": 75 + }, + "offset": { + "x": 3, + "y": 0, + "z": 5 + }, + "type": "deltaa", + "generator": "WorldEditAdditions v1.14" +} \ No newline at end of file diff --git a/.tests/parse/file/weaschem_header.test.lua b/.tests/parse/file/weaschem_header.test.lua index 42a2c50..b450228 100644 --- a/.tests/parse/file/weaschem_header.test.lua +++ b/.tests/parse/file/weaschem_header.test.lua @@ -23,6 +23,14 @@ describe("parse.file.weaschem.parse_header", function() assert.are.same("SUCCESS", code) assert.are.same(parse_json(content), result) end) + it("should not parse a header with a syntax error", function() + local content = get_json_string("invalid") + assert.are_not.same(nil, content) + local success, code, result = weaschem.parse_header(content) + assert.are.same(false, success) + assert.are.same("HEADER_INVALID_JSON", code) + assert.are.same("string", type(result)) + end) it("should parse a valid header with a description", function() local content = get_json_string("valid2") assert.are_not.same(nil, content) @@ -87,6 +95,46 @@ describe("parse.file.weaschem.parse_header", function() assert.are.same("HEADER_NO_SIZE", code) assert.are.same("string", type(result)) end) + it("should complain for an invalid header with no type", function() + local content = get_json_string("invalid_no_type") + assert.are_not.same(nil, content) + local success, code, result = weaschem.parse_header(content) + assert.are.same(false, success) + assert.are.same("HEADER_NO_TYPE", code) + assert.are.same("string", type(result)) + end) + it("should complain for an invalid header with wrong typed type", function() + local content = get_json_string("invalid_type") + assert.are_not.same(nil, content) + local success, code, result = weaschem.parse_header(content) + assert.are.same(false, success) + assert.are.same("HEADER_TYPE_INVALID", code) + assert.are.same("string", type(result)) + end) + it("should complain for an invalid header with typo in type", function() + local content = get_json_string("invalid_type_typo") + assert.are_not.same(nil, content) + local success, code, result = weaschem.parse_header(content) + assert.are.same(false, success) + assert.are.same("HEADER_TYPE_INVALID", code) + assert.are.same("string", type(result)) + end) + it("should complain for invalid header with no generator", function() + local content = get_json_string("invalid_no_generator") + assert.are_not.same(nil, content) + local success, code, result = weaschem.parse_header(content) + assert.are.same(false, success) + assert.are.same("HEADER_NO_GENERATOR", code) + assert.are.same("string", type(result)) + end) + it("should complain for invalid header with generator of wrong type", function() + local content = get_json_string("invalid_generator") + assert.are_not.same(nil, content) + local success, code, result = weaschem.parse_header(content) + assert.are.same(false, success) + assert.are.same("HEADER_GENERATOR_INVALID", code) + assert.are.same("string", type(result)) + end) -- TODO: Test invalid sizes/offsets, but this is mainly handled by the above end) diff --git a/worldeditadditions_core/utils/parse/file/weaschem.lua b/worldeditadditions_core/utils/parse/file/weaschem.lua index ae2510a..a012a25 100644 --- a/worldeditadditions_core/utils/parse/file/weaschem.lua +++ b/worldeditadditions_core/utils/parse/file/weaschem.lua @@ -45,7 +45,7 @@ end function weaschem.parse_header(source) local raw_obj = parse_json(source) - if raw_obj == nil then return false, "HEADER_INVALID", "The header is invalid JSON." end + if raw_obj == nil then return false, "HEADER_INVALID_JSON", "The header is invalid JSON." end local header = {} @@ -88,7 +88,7 @@ function weaschem.parse_header(source) header["type"] = raw_obj["type"] if type(header["type"]) ~= "string" then return false, "HEADER_TYPE_INVALID", - "Invalid type in header: expected string, but found value of type '" .. type(raw_obj["type"]) "'." + "Invalid type in header: expected string, but found value of type '" .. type(raw_obj["type"]).."'." end if header["type"] ~= "full" and header["type"] ~= "delta" then return false, "HEADER_TYPE_INVALID", diff --git a/worldeditadditions_core/utils/parse/json.lua b/worldeditadditions_core/utils/parse/json.lua index 50021d6..b314a82 100644 --- a/worldeditadditions_core/utils/parse/json.lua +++ b/worldeditadditions_core/utils/parse/json.lua @@ -3,10 +3,29 @@ if minetest == nil then json = require("json") end +-- Set to true to log JSON parsing errors to stderr when NOT running in Minetest's environment. +local log_errors_ext = false + +local function do_log_error(msg) + if log_errors_ext then + io.stderr:write(msg) + end +end + +local function do_parse_module(source) + local success, result = pcall(function() return json.decode(source) end) + -- minetest.parse_json doesn't return error messages, so there's no point in return it here either since we can't use this in Minetest's lua environment due to no require(). + if not success then + do_log_error("Error parsing JSON: "..result) + return nil + end + return result +end + return function(source) if minetest ~= nil then return minetest.parse_json(source) else - return json.decode(source) + return do_parse_module(source) end end \ No newline at end of file