"""
Tests for the configuration infrastructure.
"""

#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.


import os
import warnings
from io import StringIO

from gavo.helpers import testhelpers

from gavo import api
from gavo import base
from gavo.base import config
from gavo.utils import fancyconfig


# The tests from fancyconfig itself
_, tests = fancyconfig._getTestSuite()
for _index, _t in enumerate(tests):
	globals()["FancyconfigTest%d"%_index] = _t


class RCParseTest(testhelpers.VerboseTest):
# NOTE: if these things actually change something in config, they
# must undo these changes (at least on success)

	def _parseFragment(self, fragment):
		config._config.addFromFp(StringIO(fragment), origin="testsuite")

	def testAuthorityRejected(self):
		self.assertRaisesWithMsg(fancyconfig.BadConfigValue,
			"[ivoa]authority must match [a-zA-Z0-9][a-zA-Z0-9._~-]{2,}$ ('more than three normal characters')",
			self._parseFragment,
			("[ivoa]\nauthority:ivo://x-invalid\n",))

	def testUnknownItemWarns(self):
		with warnings.catch_warnings(record=True) as ws:
			with testhelpers.testFile("testconfig.rc",
					"[web]\nextramad: invalid") as p:
				fancyconfig.readConfiguration(config._config, p, None)
		self.assertEqual([str(w.message) for w in ws],
			['Unknown configuration item [web] extramad ignored.'])

	def testUTF8(self):
		with testhelpers.tempConfig(("web", "sitename", "kaputt")):
			with testhelpers.testFile("testconfig.rc",
					b"[web]\nsitename: Universit\xc3\xa4t") as p:
				fancyconfig.readConfiguration(config._config, p, None)
			self.assertEqual(api.getConfig("web", "sitename"),
				'Universit\xe4t')


class UserConfigTest(testhelpers.VerboseTest):
	def testSimpleResolution(self):
		s = api.resolveCrossId("%#_test-rmk", None)
		self.assertEqual(s.maps[0].key, "foo")
	
	def testOverriding(self):
		userConfigPath = os.path.join(
			api.getConfig("configDir"), "userconfig.rd")
		base.caches.clearForName(str(userConfigPath)[:-3])
		with open(userConfigPath, "w") as f:
			f.write("""<resource schema="__system">
				<rowmaker id="_test-rmk"><map key="bar">@bar</map>
				</rowmaker></resource>\n""")
		try:
			s = api.resolveCrossId("%#_test-rmk", None)
			self.assertEqual(s.maps[0].key, "bar")
		finally:
			os.unlink(userConfigPath)
		base.caches.clearForName(str(userConfigPath)[:-3])

	def testNonexisting(self):
		self.assertRaisesWithMsg(api.NotFoundError,
			"Element with id 'dashiergibtsnicht' could not be located"
			" in etc/userconfig.rd",
			api.resolveCrossId,
			("%#dashiergibtsnicht", None))

	def _resetURLCaches(self):
		base.getHTTPBase.cache_clear()
		base.getHTTPSBase.cache_clear()

	def testBasesHTTP(self):
		self._resetURLCaches()
		with testhelpers.tempConfig(
				("web", "serverURL", "http://knall.org:4030/foo/bar")):
			self.assertEqual(base.getHTTPBase(),
				"http://knall.org:4030/foo/bar")
			self.assertEqual(base.getHTTPSBase(),
				"https://knall.org/foo/bar")
		self._resetURLCaches()

	def testBasesHTTPS(self):
		self._resetURLCaches()
		with testhelpers.tempConfig(
				("web", "serverURL", "https://knall.org/foo/bar")):
			self.assertEqual(base.getHTTPBase(),
				"http://knall.org/foo/bar")
			self.assertEqual(base.getHTTPSBase(),
				"https://knall.org/foo/bar")
		self._resetURLCaches()


def _modernise():
	if "test-modernise" in api.getConfig("future"):
		return "Modern"
	else:
		return "Old-Fashioned"


class FutureTest(testhelpers.VerboseTest):
	def testModern(self):
		with testhelpers.tempConfig(("general", "future", "test-modernise")):
			self.assertEqual(_modernise(), "Modern")

	def testOldFashioned(self):
		with testhelpers.tempConfig(("general", "future", "test-other")):
			self.assertEqual(_modernise(), "Old-Fashioned")

	def testNoFuture(self):
		self.assertEqual(_modernise(), "Old-Fashioned")


class LocalNSTest(testhelpers.VerboseTest):
	def testNoLocalDefined(self):
		self.assertRaisesWithMsg(api.ReportableError,
			api.EqualingRE("No file .*gavo_test/etc/local.py found"),
			lambda: api.local.whatever,
			())
	
	def testLocalReloading(self):
		with testhelpers.testFile("local.py",
				"MAGIC_LEVEL = 'moderate'\n",
				inDir=api.getConfig("configDir")):
			api.reloadLocal()

		self.assertEqual(api.local.MAGIC_LEVEL, 'moderate')
		
		api.reloadLocal()
		self.assertRaisesWithMsg(api.ReportableError,
			api.EqualingRE("No file .*gavo_test/etc/local.py found"),
			lambda: api.local.MAGIC_LEVEL,
			())


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