import unittest

from . import helper
from htic.error import HumbleError


class ParserError(unittest.TestCase):

	# uint

	def testInvalidUnsignedIntLow(self):
		with self.assertRaises(HumbleError):
			helper.getData("maxp{ -1 maxStackElements \n}")

	def testInvalidUnsignedIntHeigh(self):
		with self.assertRaises(HumbleError):
			helper.getData("maxp{ 65536 maxStackElements \n}")

	def testInvalidUnsignedIntToken(self):
		with self.assertRaises(HumbleError):
			helper.getData("maxp{ maxStackElements 1 \n}")

	# num

	def testInvalidNumBinToken(self):
		with self.assertRaises(HumbleError):
			helper.toBytes("push 0b2")

	def testInvalidNumHexToken(self):
		with self.assertRaises(HumbleError):
			helper.toBytes("push 0xG")

	def testInvalidNumHexHigh(self):
		with self.assertRaises(HumbleError):
			helper.toBytes("push 0x10000")

	def testInvalidNumF26d6Token(self):
		with self.assertRaises(HumbleError):
			helper.toBytes("push 0.A")

	def testInvalidNumF2d14Token(self):
		with self.assertRaises(HumbleError):
			helper.toBytes("push 0:A")

	def testInvalidNumIntLow(self):
		with self.assertRaises(HumbleError):
			helper.toBytes("push -32769")

	def testInvalidNumIntHigh(self):
		with self.assertRaises(HumbleError):
			helper.toBytes("push 32768")

	def testInvalidNumIntToken(self):
		with self.assertRaises(HumbleError):
			helper.toBytes("push foo")

	# delta

	def testInvalidDeltaModifierPpemLow(self):
		with self.assertRaises(HumbleError):
			helper.toBytes("DELTAP 8 -1-8")

	def testInvalidDeltaModifierPpemHigh(self):
		with self.assertRaises(HumbleError):
			helper.toBytes("DELTAP 8 32768-8")

	def testInvalidDeltaModifierPpemToken(self):
		with self.assertRaises(HumbleError):
			helper.toBytes("DELTAP 8 foo-8")

	def testInvalidDeltaModifierSign(self):
		with self.assertRaises(HumbleError):
			helper.toBytes("DELTAP 8 12u8")

	def testInvalidDeltaModifierStepZero(self):
		with self.assertRaises(HumbleError):
			helper.toBytes("DELTAP 8 12-0")

	def testInvalidDeltaModifierStepLow(self):
		with self.assertRaises(HumbleError):
			helper.toBytes("DELTAP 8 12-9")

	def testInvalidDeltaModifierStepHeigh(self):
		with self.assertRaises(HumbleError):
			helper.toBytes("DELTAP 8 12+9")

	def testInvalidDeltaModifierStepToken(self):
		with self.assertRaises(HumbleError):
			helper.toBytes("DELTAP 8 12+foo")

	# other

	def testInvalidBitValue(self):
		with self.assertRaises(HumbleError):
			helper.getData("flags{ foo 2 \n}")

	def testInvalidId(self):
		with self.assertRaises(HumbleError):
			helper.getData("cvt{ 0 a-b \n}")

	def testMissingToken(self):
		with self.assertRaises(HumbleError):
			helper.getData("cvt  0 foo \n}")


class TableError(unittest.TestCase):

	def testDuplicateInstructionFlagName(self):
		with self.assertRaises(HumbleError):
			helper.getData("flags{ x 1 \n x 11110 \n}")

	def testUnknownInstructionFlagName(self):
		with self.assertRaises(HumbleError):
			helper.toBytes("IUP[foo]")

	def testDuplicateHeadBlock(self):
		with self.assertRaises(HumbleError):
			helper.getData("head{ 8 lowestRecPPEM \n} \n head{ 9 lowestRecPPEM \n}")

	def testDuplicateHeadIdentifier(self):
		with self.assertRaises(HumbleError):
			helper.getData("head{ 8 lowestRecPPEM \n 9 lowestRecPPEM \n}")

	def testUnknownHeadIdentifier(self):
		with self.assertRaises(HumbleError):
			helper.getData("head{ 8 foo \n}")

	def testInvalidHeadFlagValue(self):
		with self.assertRaises(HumbleError):
			helper.getData("head{ 2 flags.fontOptimizedForClearType \n}")

	def testUnknownHeadFlag(self):
		with self.assertRaises(HumbleError):
			helper.getData("head{ 0 flags.foo \n}")

	def testDuplicateMaxpBlock(self):
		with self.assertRaises(HumbleError):
			helper.getData("maxp{ 1 maxZones \n} \n maxp{ 2 maxZones \n}")

	def testDuplicateMaxpIdentifier(self):
		with self.assertRaises(HumbleError):
			helper.getData("maxp{ 1 maxZones \n 2 maxZones \n}")

	def testUnknownMaxpIdentifier(self):
		with self.assertRaises(HumbleError):
			helper.getData("maxp{ 16 foo \n}")

	def testDuplicateGaspBlock(self):
		with self.assertRaises(HumbleError):
			helper.getData("gasp{ 1 \n } \n gasp{ 2 \n}")

	def testUnorderedGaspItems(self):
		with self.assertRaises(HumbleError):
			helper.getData("gasp{ 2 \n 1 \n}")

	def testUnknownGaspFlag(self):
		with self.assertRaises(HumbleError):
			helper.getData("gasp{ 2 foo \n}")

	def testDuplicateCvtBlock(self):
		with self.assertRaises(HumbleError):
			helper.getData("cvt{ 0 foo \n} \n cvt{ 1 bar \n}")

	def testDuplicateCvtIdentifier(self):
		with self.assertRaises(HumbleError):
			helper.getData("cvt{ 0 foo \n 1 foo \n}")

	def testUndeclaredCvt(self):
		with self.assertRaises(HumbleError):
			helper.toBytes("MIAP 8 foo")

	def testDuplicateFpgmBlock(self):
		with self.assertRaises(HumbleError):
			helper.getData("fpgm{ \n} \n fpgm{ \n}")

	def testDuplicatePrepBlock(self):
		with self.assertRaises(HumbleError):
			helper.getData("prep{ \n} \n prep{ \n}")

	def testDuplicateGlyphBlock(self):
		with self.assertRaises(HumbleError):
			helper.getData("a{ \n} \n a{ \n}")

	def testDuplicateFunctionIndex(self):
		with self.assertRaises(HumbleError):
			helper.getData("fpgm{ FDEF 0 foo \n POP \n ENDF \n FDEF 0 bar \n POP \n ENDF \n}")

	def testDuplicateFunctionName(self):
		with self.assertRaises(HumbleError):
			helper.getData("fpgm{ FDEF 0 foo \n POP \n ENDF \n FDEF 1 foo \n POP \n ENDF \n}")

	def testUndeclaredFunction(self):
		with self.assertRaises(HumbleError):
			helper.toBytes("CALL foo")

	def testUndeclaredStorage(self):
		with self.assertRaises(HumbleError):
			helper.toBytes("RS foo")


class InstructionError(unittest.TestCase):

	def testUnsupportedInstruction(self):
		with self.assertRaises(HumbleError):
			helper.toBytes("FOO 0")

	def testInvalidOperatorSymbol(self):
		with self.assertRaises(HumbleError):
			helper.toBytes("IF (2 % 3) \n EIF")

	def testInvalidInstructionFlag(self):
		with self.assertRaises(HumbleError):
			helper.toBytes("IUP+10")

