"""
Various (sync) tests for DALI-type support code.
"""

#c Copyright 2008-2024, the GAVO project <gavo@ari.uni-heidelberg.de>
#c
#c This program is free software, covered by the GNU GPL.  See the
#c COPYING file in the source distribution.


from gavo.helpers import testhelpers, trialhelpers

from twisted.web import server

from gavo import svcs
from gavo.protocols import dali


def _renderErrInfo(errInfo, **kwargs):
	# we're going through DALIErrorResource rather than serveDALIError
	# because that way we're testing both in one go.
	request = trialhelpers.FakeRequest(kwargs.pop("reqPath", ""))
	res = dali.DALIErrorResource(errInfo, **kwargs)
	assert res.render(request)==server.NOT_DONE_YET
	return request


class DALIErrorTest(testhelpers.VerboseTest):
	def testErrorString(self):
		request = _renderErrInfo("Something is wrong", reqPath="/a/b/c")
		tree = testhelpers.getXMLTree(request.accumulator, debug=False)

		self.assertEqual(request.code, 500)
		self.assertEqual(tree[0].get("type"), "results")
		statusInfo = tree.xpath("//INFO[@name='QUERY_STATUS']")[0]
		self.assertEqual(statusInfo.text, "Something is wrong")
		self.assertEqual(statusInfo.get("value"), "ERROR")
		self.assertEqual(
			tree.xpath("//INFO[@name='request']")[0].get("value"),
			"a/b/c")

	def testErrorInfoMin(self):
		request = _renderErrInfo({"msg": "Something is wrong"}, reqPath="")
		tree = testhelpers.getXMLTree(request.accumulator, debug=False)
		self.assertEqual(request.code, 500)
		self.assertEqual(
			tree.xpath("//INFO[@name='QUERY_STATUS']")[0].text,
			"Something is wrong")

	def testErrorInfoCodeAndInt(self):
		request = _renderErrInfo({"msg": "Something is wrong",
			"hint": "This is just a test", "httpCode":  453}, reqPath="")
		tree = testhelpers.getXMLTree(request.accumulator, debug=False)
		self.assertEqual(request.code, 453)
		self.assertEqual(
			tree.xpath("//INFO[@name='QUERY_STATUS']")[0].text,
			"Something is wrong")
		self.assertEqual(
			tree.xpath("//INFO[@name='HINT']")[0].text,
			"This is just a test")

	def testQueryStatus(self):
		request = _renderErrInfo(
			"Something is wrong", queryStatus="CONFUSED", reqPath="")
		tree = testhelpers.getXMLTree(request.accumulator, debug=False)
		self.assertEqual(
			tree.xpath("//INFO[@name='QUERY_STATUS']/@value")[0],
			"CONFUSED")

	def testCodedException(self):
		request = _renderErrInfo(
			svcs.UnknownURI("You made it up"), reqPath="")
		tree = testhelpers.getXMLTree(request.accumulator, debug=False)
		self.assertEqual(request.code, 404)
		self.assertEqual(
			tree.xpath("//INFO[@name='QUERY_STATUS']")[0].text,
			"You made it up")

	def testOtherException(self):
		request = _renderErrInfo(
			SyntaxError("It's broken"), reqPath="")
		tree = testhelpers.getXMLTree(request.accumulator, debug=False)
		self.assertEqual(request.code, 500)
		self.assertEqual(
			tree.xpath("//INFO[@name='QUERY_STATUS']")[0].text,
			"It's broken")

	def testNoWrite(self):
		request = trialhelpers.FakeRequest("")
		request._disconnected = True
		res = dali.DALIErrorResource("Not shown")
		assert res.render(request)==server.NOT_DONE_YET
		self.assertEqual(request.accumulator, b"")

	def testBrokenError(self):
		class BrokenArrow(Exception):
			def __str__(self):
				raise KeyError("sense")
		request = _renderErrInfo(BrokenArrow(), reqPath="")
		self.assertEqual(request.accumulator,
			b"Ouch.  Can't even produce an error any more.\n")



if __name__=="__main__":
	testhelpers.main(DALIErrorTest)
