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

#c Copyright 2008-2019, the GAVO project
#c
#c This program is free software, covered by the GNU GPL.  See the
#c COPYING file in the source distribution.


import contextlib
import os
import warnings
from cStringIO import StringIO

from gavo.helpers import testhelpers

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


# The tests from fancyconfig itself
fcTest = fancyconfig._getTestSuite()


@contextlib.contextmanager
def tempConfig(*items):
	"""sets (sect, key, value) pairs in the config temporarily and re-sets
	the original values after the controlled block.
	"""
	origValues = []
	for sect, key, val in items:
		origValues.append((sect, key, config.get(sect, key)))
		config.set(sect, key, val)
	
	try:
		yield
	finally:
		for sect, key, val in origValues:
			config.set(sect, key, val)


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 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(base.getConfig("web", "sitename"),
				u'Universit\xe4t')


class UserConfigTest(testhelpers.VerboseTest):
	def testSimpleResolution(self):
		s = base.resolveCrossId("%#_test-script", None)
		self.assertEqual(s.name, "test instrumentation")
	
	def testOverriding(self):
		userConfigPath = os.path.join(
			base.getConfig("configDir"), "userconfig.rd")
		base.caches.clearForName(userConfigPath[:-3])
		with open(userConfigPath, "w") as f:
			f.write("""<resource schema="__system"><script id="_test-script"
				lang="SQL" name="test exstrumentation" type="preIndex"/>
				</resource>\n""")
		try:
			s = base.resolveCrossId("%#_test-script", None)
			self.assertEqual(s.name, "test exstrumentation")
		finally:
			os.unlink(userConfigPath)

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

	def _resetURLCaches(self):
		base.getHTTPBase._cache.clear()
		base.getHTTPSBase._cache.clear()

	def testBasesHTTP(self):
		self._resetURLCaches()
		with 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 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()


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