from chrysacase import ChrysalideTestCase
from pychrysalide.analysis.contents import MemoryContent
from pychrysalide.format import KnownFormat


class TestKnownFormat(ChrysalideTestCase):
    """TestCase for format.KnownFormat."""


    def testCustomInstance(self):
        """Validate a full custom KnownFormat implementation."""

        data  = b'\x01\x02\x03'
        cnt = MemoryContent(data)


        class CustomFormat(KnownFormat):

            def _get_key(self):
                return 'tiny'

            def _get_description(self):
                return 'Small description'

        cf = CustomFormat(cnt)

        self.assertEqual(cf.key, 'tiny')
        self.assertEqual(cf.description, 'Small description')


        class EmptyCustomFormat(KnownFormat):
            pass

        cf = EmptyCustomFormat(cnt)

        # NotImplementedError: method implementation is missing for '_get_key'
        with self.assertRaisesRegex(NotImplementedError, "method implementation is missing for '_get_key'"):
            k = cf.key

        # NotImplementedError: method implementation is missing for '_get_description'
        with self.assertRaisesRegex(NotImplementedError, "method implementation is missing for '_get_description'"):
            k = cf.description


        class BadCustomFormat(KnownFormat):

            def _get_key(self):
                return 123

            def _get_description(self):
                return 456

        cf = BadCustomFormat(cnt)

        # ValueError: unexpected value type for known format key
        with self.assertRaisesRegex(ValueError, 'unexpected value type for known format key'):
            k = cf.key

        # ValueError: unexpected value type for known format description
        with self.assertRaisesRegex(ValueError, 'unexpected value type for known format description'):
            k = cf.description


    def testKnownFormatConstructor(self):
        """Load a simple content for a known format."""

        with self.assertRaisesRegex(RuntimeError, 'pychrysalide.format.KnownFormat is an abstract class'):
            fmt = KnownFormat()

        class MyKnownFormat(KnownFormat):
            pass

        with self.assertRaisesRegex(TypeError, 'function takes exactly 1 argument .0 given.'):
            fmt = MyKnownFormat()

        class MyKnownFormat2(KnownFormat):
            pass

        with self.assertRaisesRegex(TypeError, 'unable to convert the provided argument to binary content'):
            fmt = MyKnownFormat2(123)