Changeset

8626:20532f191f8d

util.stanza: Switch from asserts to if's, improve performance, errors and tests
author Matthew Wild <mwild1@gmail.com>
date Sun, 18 Mar 2018 11:32:00 +0000
parents 8625:08bf4df6fdb7
children 8627:24b59a62acce
files spec/util_stanza_spec.lua util/stanza.lua
diffstat 2 files changed, 69 insertions(+), 44 deletions(-) [+]
line wrap: on
line diff
--- a/spec/util_stanza_spec.lua	Sat Mar 17 22:03:08 2018 +0000
+++ b/spec/util_stanza_spec.lua	Sun Mar 18 11:32:00 2018 +0000
@@ -165,38 +165,49 @@
 		end);
 	end);
 
-	describe("#invalid", function ()
-		it("name should be rejected", function ()
-			assert.has_error(function ()
-				st.stanza(1234);
+	describe("should reject #invalid", function ()
+		local invalid_names = {
+			["empty string"] = "", ["characters"] = "<>";
+		}
+		local invalid_data = {
+			["number"] = 1234, ["table"] = {};
+			["utf8"] = string.char(0xF4, 0x90, 0x80, 0x80);
+		};
+
+		for value_type, value in pairs(invalid_names) do
+			it(value_type.." in tag names", function ()
+				assert.error_matches(function ()
+					st.stanza(value);
+				end, value_type);
 			end);
-			assert.has_error(function ()
-				st.stanza({});
-			end);
-			assert.has_error(function ()
-				st.stanza();
-			end);
-			assert.has_error(function ()
-				st.stanza("");
+			it(value_type.." in attribute names", function ()
+				assert.error_matches(function ()
+					st.stanza("valid", { [value] = "valid" });
+				end, value_type);
 			end);
-			assert.has_error(function ()
-				st.stanza(string.char(0xC0));
+		end
+		for value_type, value in pairs(invalid_data) do
+			it(value_type.." in tag names", function ()
+				assert.error_matches(function ()
+					st.stanza(value);
+				end, value_type);
 			end);
-			assert.has_error(function ()
-				st.stanza(string.char(0xF4, 0x90, 0x80, 0x80));
-			end);
-			assert.has_error(function ()
-				st.stanza("<>");
+			it(value_type.." in attribute names", function ()
+				assert.error_matches(function ()
+					st.stanza("valid", { [value] = "valid" });
+				end, value_type);
 			end);
-			assert.has_error(function ()
-				st.stanza("&");
+			it(value_type.." in attribute values", function ()
+				assert.error_matches(function ()
+					st.stanza("valid", { valid = value });
+				end, value_type);
 			end);
-		end);
-		it("UTF-8 should be rejected", function ()
-			assert.has_error(function ()
-				st.stanza("tag"):text("hello "..string.char(0xF4, 0x90, 0x80, 0x80).." world");
+			it(value_type.." in text node", function ()
+				assert.error_matches(function ()
+					st.stanza("valid"):text(value);
+				end, value_type);
 			end);
-		end);
+		end
 	end);
 
 	describe("#is_stanza", function ()
--- a/util/stanza.lua	Sat Mar 17 22:03:08 2018 +0000
+++ b/util/stanza.lua	Sun Mar 18 11:32:00 2018 +0000
@@ -7,7 +7,7 @@
 --
 
 
-local assert        =        assert;
+local error         =         error;
 local t_insert      =  table.insert;
 local t_remove      =  table.remove;
 local t_concat      =  table.concat;
@@ -45,31 +45,45 @@
 local stanza_mt = { __name = "stanza" };
 stanza_mt.__index = stanza_mt;
 
-local function check_name(name)
-	assert(type(name) == "string", "tag name is not a string, "..type(name));
-	assert(#name > 0, "tag name is empty");
-	assert(not s_find(name, "[<>& '\"]"), "tag name contains invalid characters");
-	assert(valid_utf8(name), "tag name is invalid utf8");
+local function check_name(name, name_type)
+	if type(name) ~= "string" then
+		error("invalid "..name_type.." name: expected string, got "..type(name));
+	elseif #name == 0 then
+		error("invalid "..name_type.." name: empty string");
+	elseif s_find(name, "[<>& '\"]") then
+		error("invalid "..name_type.." name: contains invalid characters");
+	elseif not valid_utf8(name) then
+		error("invalid "..name_type.." name: contains invalid utf8");
+	end
 end
+
+local function check_text(text, text_type)
+	if type(text) ~= "string" then
+		error("invalid "..text_type.." value: expected string, got "..type(text));
+	elseif not valid_utf8(text) then
+		error("invalid "..text_type.." value: contains invalid utf8");
+	end
+end
+
 local function check_attr(attr)
 	if attr ~= nil then
-		assert(type(attr) == "table", "attribute is not a table");
+		if type(attr) ~= "table" then
+			error("invalid attributes, expected table got "..type(attr));
+		end
 		for k, v in pairs(attr) do
-			assert(type(k) == "string", "non-string key in attributes");
-			assert(valid_utf8(k), "attribute name is not valid utf8");
-			assert(type(v) == "string", "non-string value in attributes");
-			assert(valid_utf8(v), "attribute value is not valid utf8");
+			check_name(k, "attribute");
+			check_text(v, "attribute");
+			if type(v) ~= "string" then
+				error("invalid attribute value for '"..k.."': expected string, got "..type(v));
+			elseif not valid_utf8(v) then
+				error("invalid attribute value for '"..k.."': contains invalid utf8");
+			end
 		end
 	end
 end
-local function check_text(text)
-	assert(type(text) == "string", "text is not a string");
-	assert(valid_utf8(text), "text is not valid utf8");
-end
 
 local function new_stanza(name, attr, namespaces)
-	assert(name)
-	check_name(name);
+	check_name(name, "tag");
 	check_attr(attr);
 	local stanza = { name = name, attr = attr or {}, namespaces = namespaces, tags = {} };
 	return setmetatable(stanza, stanza_mt);
@@ -97,7 +111,7 @@
 end
 
 function stanza_mt:text(text)
-	check_text(text);
+	check_text(text, "text");
 	local last_add = self.last_add;
 	(last_add and last_add[#last_add] or self):add_direct_child(text);
 	return self;