scansion/console.lua

Thu, 23 Mar 2023 15:12:30 +0000

author
Matthew Wild <mwild1@gmail.com>
date
Thu, 23 Mar 2023 15:12:30 +0000
changeset 174
662bd8c5ae28
parent 148
e2c85e095a4c
child 181
3a9b9c98304a
permissions
-rw-r--r--

Serialize XML in a consistent order by default

This overrides all XML serialization to emit attributes in an ordered form, so
the XML will match across multiple runs. This can be useful for comparing
different runs, or even two stanzas printed in the same run (e.g. if there is
a mismatch).


local function lines(l, indent)
	return table.concat(l, "\n"..string.rep(" ", indent or 0));
end

local quiet_handlers = { "test-failed", "test-error" };

local function new(config)
	local pretty = require "scansion.pretty".new({
		sorted = config.ordered;
	});

	local handlers = {
		["script"] = function (data)
			return "TEST: "..(data.title or data.filename or "untitled");
		end;
		["test-passed"] = function ()
			return "PASS";
		end;
		["test-failed"] = function (data)
			local error_text;
			if data.reason and data.reason.type == "unexpected-stanza" then
				error_text = "Received unexpected stanza:\n\n"..pretty(data.reason.data.stanza, 4);
				if data.reason.data.expected then
					error_text = error_text.."\n\nExpected:\n\n"..pretty(data.reason.data.expected, 4);
				end
			else
				error_text = tostring(data.reason);
			end
			return lines({
				"FAILED: "..data.name;
				"";
				(error_text:gsub("\n", "\n    "));
				"";
			}, 4);
		end;
		["test-error"] = function (data)
			return lines({
				"ERROR: "..data.name;
				"";
				(tostring(data.reason):gsub("\n", "\n    "));
				"";
			}, 4);
		end;

		["action"] = function (data)
			local action = data.action;
			local obj_type = data.object_type;
			local l = {};
			if data.annotation then
				table.insert(l, action.annotation);
			end
			table.insert(l, data.object.." "..action);
			if data.extra and obj_type == "client" and (action == "sends" or action == "receives") then
				table.insert(l, "\n"..pretty(lines(data.extra), 4).."\n");
			end
			return lines(l);
		end;

		["end"] = function (data)
			local r = {};

			local all_results = {};
			for _, v in pairs(data.summary.all) do
				table.insert(all_results, v);
			end
			table.sort(all_results, function (a, b) return a.name < b.name end);

			print("");
			print("Summary");
			print("-------");

			for _, test_result in ipairs(all_results) do
				print("", test_result.status, test_result.name);
			end

			print("");

			for _, test_result in ipairs{ "ok", "fail", "error", "skipped", "total" } do
				local count = data.summary[test_result] and #data.summary[test_result] or 0;
				table.insert(r, tostring(count).." "..test_result);
			end
			return table.concat(r, " / ");
		end;
	};


	local h = {};
	if config.quiet then
		for _, handler_name in ipairs(quiet_handlers) do
			h[handler_name] = handlers[handler_name];
		end
		if config.summary then
			h["end"] = handlers["end"];
		end
	else
		h = handlers;
	end
	return h;
end

return {
	new = new;
}

mercurial