#!/usr/bin/env python
"""Test file for the physbiblio.errors module.

This file is part of the physbiblio package.
"""
import sys
import traceback

if sys.version_info[0] < 3:
	import unittest2 as unittest
	from mock import patch
	from StringIO import StringIO
else:
	import unittest
	from unittest.mock import patch
	from io import StringIO

try:
	from physbiblio.setuptests import *
	from physbiblio.errors import PBErrorManagerClass
	from physbiblio.config import pbConfig
except ImportError:
	print("Could not find physbiblio and its modules!")
	raise
except Exception:
	print(traceback.format_exc())


class TestErrors(unittest.TestCase):
	"""Test PBErrorManagerClass stuff"""
	@classmethod
	def setUpClass(self):
		"""settings"""
		with patch.dict(pbConfig.params,
				{"loggingLevel": 3, "logFileName": logFileName},
				clear=False):
			self.pBErrorManager = PBErrorManagerClass("testlogger")

	def reset(self, m):
		"""Clear a StringIO object"""
		m.seek(0)
		m.truncate(0)

	def resetLogFile(self):
		"""Reset the logfile content"""
		open(logFileName, 'w').close()

	def readLogFile(self):
		"""Read the logfile content"""
		with open(logFileName) as logFile:
			log_new = logFile.read()
		return log_new

	def test_critical(self):
		"""Test pBLogger.critical with and without exception"""
		self.resetLogFile()
		try:
			raise Exception("Fake error")
		except Exception as e:
			self.pBErrorManager.logger.critical(str(e))
		log_new = self.readLogFile()
		self.assertIn(datetime.datetime.now().strftime("%Y-%m-%d %H:%M"),
			log_new)
		self.assertIn("CRITICAL : [test_errors.test_critical] Fake error",
			log_new)
		self.assertNotIn("Traceback (most recent call last):", log_new)
		try:
			raise Exception("Fake error")
		except Exception as e:
			self.pBErrorManager.logger.critical(str(e), exc_info=True)
		log_new = self.readLogFile()
		self.assertIn("Traceback (most recent call last):", log_new)

	def test_exception(self):
		"""Test pBLogger.exception"""
		self.resetLogFile()
		try:
			raise Exception("Fake error")
		except Exception as e:
			self.pBErrorManager.logger.exception(str(e))
		try:
			raise Exception("New fake error")
		except Exception as e:
			self.pBErrorManager.logger.error(str(e))
		log_new = self.readLogFile()
		self.assertIn(datetime.datetime.now().strftime("%Y-%m-%d %H:%M"),
			log_new)
		self.assertIn("ERROR : [test_errors.test_exception] Fake error",
			log_new)
		self.assertIn("ERROR : [test_errors.test_exception] New fake error",
			log_new)
		self.assertIn("Traceback (most recent call last):", log_new)

	def test_warning(self):
		"""Test pBLogger.warning"""
		self.resetLogFile()
		try:
			raise Exception("Fake warning")
		except Exception as e:
			self.pBErrorManager.logger.warning(str(e))
		log_new = self.readLogFile()
		self.assertIn(datetime.datetime.now().strftime("%Y-%m-%d %H:%M"),
			log_new)
		self.assertIn("WARNING : [test_errors.test_warning] Fake warning",
			log_new)

	def test_info(self):
		"""Test pBLogger.info"""
		self.resetLogFile()
		self.pBErrorManager.logger.info("Some info")
		log_new = self.readLogFile()
		self.assertIn(datetime.datetime.now().strftime("%Y-%m-%d %H:%M"),
			log_new)
		self.assertIn("INFO : [test_errors.test_info] Some info", log_new)

	def test_tempHandler(self):
		"""Test stuff as the temporary handler"""
		self.assertEqual(self.pBErrorManager.tempsh, [])
		self.assertEqual(len(self.pBErrorManager.logger.handlers), 2)
		with patch('sys.stdout', new_callable=StringIO) as _mock:
			self.assertTrue(self.pBErrorManager.tempHandler(sys.stdout,
				format='%(message)s'))
			self.assertEqual(len(self.pBErrorManager.logger.handlers), 3)
			self.assertEqual(len(self.pBErrorManager.tempsh), 1)
			self.reset(_mock)
			self.pBErrorManager.logger.critical("Fake critical")
			self.assertEqual(_mock.getvalue(), "Fake critical\n")
			self.pBErrorManager.rmTempHandler()
			self.assertEqual(self.pBErrorManager.tempsh, [])
			self.assertEqual(len(self.pBErrorManager.logger.handlers), 2)
			self.assertEqual(len(self.pBErrorManager.tempsh), 0)
			self.reset(_mock)
			self.assertEqual(_mock.getvalue(), "")
			self.pBErrorManager.logger.critical("Fake critical")
			self.assertEqual(_mock.getvalue(), "")
			self.assertTrue(self.pBErrorManager.tempHandler(sys.stdout,
				format='%(message)s'))
			self.assertEqual(len(self.pBErrorManager.logger.handlers), 3)
			self.assertTrue(self.pBErrorManager.tempHandler(sys.stdout,
				format='%(message)s'))
			self.assertEqual(len(self.pBErrorManager.logger.handlers), 4)
			self.assertTrue(self.pBErrorManager.tempHandler(sys.stdout,
				format='%(message)s'))
			self.assertEqual(len(self.pBErrorManager.logger.handlers), 5)
			self.assertEqual(len(self.pBErrorManager.tempsh), 3)
			self.pBErrorManager.rmTempHandler()
			self.assertEqual(len(self.pBErrorManager.logger.handlers), 4)
			self.assertEqual(len(self.pBErrorManager.tempsh), 2)
			self.pBErrorManager.rmAllTempHandlers()
			self.assertEqual(len(self.pBErrorManager.logger.handlers), 2)
			self.assertEqual(len(self.pBErrorManager.tempsh), 0)


if __name__=='__main__':
	unittest.main()
