local function F(G,h)if typeof(G)~=typeof(h)then local F=("\123\049\125 \105\115 \111\102 \116\121\112\101 \037\115\044 \098\117\116 \123\050\125 \105\115 \111\102 \116\121\112\101 \037\115"):format(typeof(G),typeof(h))return false,F end if typeof(G)=="\116\097\098\108\101"then local l={}for G,d in pairs(G)do l[G]=true local o,O=F(d,h[G])if not o then local F=(O:gsub("\123\049\125",("\123\049\125\091\037\115\093"):format(tostring(G)))):gsub("\123\050\125",("\123\050\125\091\037\115\093"):format(tostring(G)))return false,F end end for h,d in pairs(h)do if not l[h]then local l,o=F(d,G[h])if not l then local F=(o:gsub("\123\049\125",("\123\049\125\091\037\115\093"):format(tostring(h)))):gsub("\123\050\125",("\123\050\125\091\037\115\093"):format(tostring(h)))return false,F end end end return true end if G==h then return true end local l="\123\049\125 ~\061 \123\050\125"return false,l end local function G(G,h)local l,d=F(G,h)if not l then local F=(d:gsub("\123\049\125","\102\105\114\115\116")):gsub("\123\050\125","\115\101\099\111\110\100")local G=("\086\097\108\117\101\115 \119\101\114\101 \110\111\116 \100\101\101\112-\101\113\117\097\108\046\n\037\115"):format(F)error(G,2)end end return G
--[[
	A utility used to assert that two objects are value-equal recursively. It
	outputs fairly nicely formatted messages to help diagnose why two objects
	would be different.

	This should only be used in tests.
]]

local function deepEqual(a, b)
	if typeof(a) ~= typeof(b) then
		local message = ("{1} is of type %s, but {2} is of type %s"):format(
			typeof(a),
			typeof(b)
		)
		return false, message
	end

	if typeof(a) == "table" then
		local visitedKeys = {}

		for key, value in pairs(a) do
			visitedKeys[key] = true

			local success, innerMessage = deepEqual(value, b[key])
			if not success then
				local message = innerMessage
					:gsub("{1}", ("{1}[%s]"):format(tostring(key)))
					:gsub("{2}", ("{2}[%s]"):format(tostring(key)))

				return false, message
			end
		end

		for key, value in pairs(b) do
			if not visitedKeys[key] then
				local success, innerMessage = deepEqual(value, a[key])

				if not success then
					local message = innerMessage
						:gsub("{1}", ("{1}[%s]"):format(tostring(key)))
						:gsub("{2}", ("{2}[%s]"):format(tostring(key)))

					return false, message
				end
			end
		end

		return true
	end

	if a == b then
		return true
	end

	local message = "{1} ~= {2}"
	return false, message
end

local function assertDeepEqual(a, b)
	local success, innerMessageTemplate = deepEqual(a, b)

	if not success then
		local innerMessage = innerMessageTemplate
			:gsub("{1}", "first")
			:gsub("{2}", "second")

		local message = ("Values were not deep-equal.\n%s"):format(innerMessage)

		error(message, 2)
	end
end

return assertDeepEqual