local function i(W,K)if typeof(W)~=typeof(K)then local i=("\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(W),typeof(K))return false,i end if typeof(W)=="\116\097\098\108\101"then local D={}for W,u in pairs(W)do D[W]=true local J,G=i(u,K[W])if not J then local i=(G:gsub("\123\049\125",("\123\049\125\091\037\115\093"):format(tostring(W)))):gsub("\123\050\125",("\123\050\125\091\037\115\093"):format(tostring(W)))return false,i end end for K,u in pairs(K)do if not D[K]then local D,J=i(u,W[K])if not D then local i=(J:gsub("\123\049\125",("\123\049\125\091\037\115\093"):format(tostring(K)))):gsub("\123\050\125",("\123\050\125\091\037\115\093"):format(tostring(K)))return false,i end end end return true end if W==K then return true end local D="\123\049\125 ~\061 \123\050\125"return false,D end local function W(W,K)local D,u=i(W,K)if not D then local i=(u:gsub("\123\049\125","\102\105\114\115\116")):gsub("\123\050\125","\115\101\099\111\110\100")local W=("\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(i)error(W,2)end end return W
--[[
	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