# -*- coding: utf-8 -*-
# :-
# SPDX-FileCopyrightText: © 2025 Franz Glasner
# SPDX-License-Identifier: BSD-3-Clause
# :-
r"""Unit tests for the vendored crcmod2 package.

"""

from __future__ import absolute_import, print_function

import struct
import sys
import unittest
import zlib

import _test_setup           # noqa: F401 imported but unused

import cutils.util.crc32


class TestCRC32(unittest.TestCase):

    def test_empty(self):
        c1 = cutils.util.crc32.crc32()
        c2 = zlib.crc32(b"")
        self.assertEqual(c1._crc, c2)
        self.assertEqual("00000000", c1.hexdigest())
        self.assertEqual(b"\x00\x00\x00\x00", c1.digest())

    def test_uint32(self):
        c1 = cutils.util.crc32.crc32()
        c1._crc = 0xffffffff
        self.assertEqual("FFFFFFFF", c1.hexdigest())
        self.assertEqual(b"\xff\xff\xff\xff", c1.digest())

    @unittest.skipIf(sys.version_info[0] >= 3, "Only for Python 2")
    def test_negative_minus_one(self):
        # Python2 yields negative numbers in zlib.crc32()
        c1 = cutils.util.crc32.crc32()
        c1._crc = -1
        self.assertEqual("FFFFFFFF", c1.hexdigest())
        self.assertEqual(b"\xff\xff\xff\xff", c1.digest())

    def test_postitive_asd(self):
        c1 = cutils.util.crc32.crc32(b"asd\n")
        c2 = zlib.crc32(b"")
        c2 = zlib.crc32(b"asd\n", c2)
        self.assertEqual(c1._crc, c2)
        self.assertEqual(355327694, c1._crc)
        self.assertEqual("152DDECE", c1.hexdigest())
        self.assertEqual(b"\x15\x2d\xde\xce", c1.digest())

    def test_negative_123456789(self):
        c1 = cutils.util.crc32.crc32()
        c1.update(b"123456789")
        c2 = zlib.crc32(b"123456789")
        self.assertEqual(c1._crc, c2)
        self.assertEqual("CBF43926", c1.hexdigest())
        self.assertEqual(b"\xcb\xf4\x39\x26", c1.digest())

    def test_copy(self):
        c1 = cutils.util.crc32.crc32(b"123456789")
        c2 = c1.copy()
        self.assertEqual(c1._crc, c2._crc)
        self.assertEqual("CBF43926", c2.hexdigest())

    def test_copy_parts(self):
        c1 = cutils.util.crc32.crc32(b"12345")
        c2 = c1.copy()
        c2.update(b"6789")
        self.assertEqual("CBF43926", c2.hexdigest())

    def test_equality(self):
        c1 = cutils.util.crc32.crc32(b"123")
        c2 = c1.copy()
        c3 = zlib.crc32(b"123")
        self.assertEqual(c2, c1)
        self.assertEqual(c1, c2._crc)
        self.assertEqual(c1, c3)
        self.assertNotEqual(c1, None)

    def test_equality_2(self):
        c1 = cutils.util.crc32.crc32(b"123456789")
        c2 = c1.copy()
        c3 = zlib.crc32(b"123456789")
        self.assertEqual(c2, c1)
        self.assertEqual(c1, c2._crc)
        self.assertEqual(c1, c3)
        self.assertNotEqual(c1, None)

    def test_inequality(self):
        c1 = cutils.util.crc32.crc32(b"123")
        c2 = c1.copy()
        c1.update(b"4")
        c3 = zlib.crc32(b"12345")
        self.assertNotEqual(c2, c1)
        self.assertNotEqual(c1, c2._crc)
        self.assertNotEqual(c1, c3)
        self.assertNotEqual(c1, None)

    def test_inequality_2(self):
        c1 = cutils.util.crc32.crc32(b"12345678")
        c2 = c1.copy()
        c2.update(b"9")
        c3 = zlib.crc32(b"1234567")
        self.assertNotEqual(c2, c1)
        self.assertNotEqual(c1, c2._crc)
        self.assertNotEqual(c1, c3)
        self.assertNotEqual(c1, None)

    def test_equality_negative_number(self):
        c1 = cutils.util.crc32.crc32(b"123456789")
        # Py2 yields signed ints
        self.assertEqual(c1, -873187034)
        # Py3 yields unsigned ints
        self.assertEqual(c1, 3421780262)

    def test_as_uint32(self):
        self.assertEqual(3421780262,
                         cutils.util.crc32.crc32.as_uint32(-873187034))

    def test_struct_pack(self):
        self.assertEqual(
            struct.pack(">I", 3421780262),
            struct.pack(">i", -873187034))
        self.assertEqual(
            struct.pack(">i", -2147483648),
            struct.pack(">I", 0x80000000))


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