1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207
|
# test_object_format.py -- tests for object_format.py
# Copyright (C) 2025 Jelmer Vernooij <jelmer@jelmer.uk>
#
# SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
# Dulwich is dual-licensed under the Apache License, Version 2.0 and the GNU
# General Public License as published by the Free Software Foundation; version 2.0
# or (at your option) any later version. You can redistribute it and/or
# modify it under the terms of either of these two licenses.
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
# You should have received a copy of the licenses; if not, see
# <http://www.gnu.org/licenses/> for a copy of the GNU General Public License
# and <http://www.apache.org/licenses/LICENSE-2.0> for a copy of the Apache
# License, Version 2.0.
#
"""Tests for object_format module."""
from dulwich.object_format import (
DEFAULT_OBJECT_FORMAT,
OBJECT_FORMAT_TYPE_NUMS,
OBJECT_FORMATS,
SHA1,
SHA256,
get_object_format,
verify_same_object_format,
)
from . import TestCase
class ObjectFormatTests(TestCase):
"""Tests for ObjectFormat class."""
def test_sha1_attributes(self) -> None:
"""Test SHA1 object format attributes."""
self.assertEqual("sha1", SHA1.name)
self.assertEqual(1, SHA1.type_num)
self.assertEqual(20, SHA1.oid_length)
self.assertEqual(40, SHA1.hex_length)
def test_sha256_attributes(self) -> None:
"""Test SHA256 object format attributes."""
self.assertEqual("sha256", SHA256.name)
self.assertEqual(20, SHA256.type_num)
self.assertEqual(32, SHA256.oid_length)
self.assertEqual(64, SHA256.hex_length)
def test_str_representation(self) -> None:
"""Test __str__ method returns format name."""
self.assertEqual("sha1", str(SHA1))
self.assertEqual("sha256", str(SHA256))
def test_repr_representation(self) -> None:
"""Test __repr__ method."""
self.assertEqual("ObjectFormat('sha1')", repr(SHA1))
self.assertEqual("ObjectFormat('sha256')", repr(SHA256))
def test_new_hash(self) -> None:
"""Test new_hash creates a hash object."""
sha1_hash = SHA1.new_hash()
self.assertEqual("sha1", sha1_hash.name)
sha256_hash = SHA256.new_hash()
self.assertEqual("sha256", sha256_hash.name)
def test_hash_object(self) -> None:
"""Test hash_object returns binary digest."""
data = b"test data"
# Test SHA1
sha1_digest = SHA1.hash_object(data)
self.assertIsInstance(sha1_digest, bytes)
self.assertEqual(20, len(sha1_digest))
# Verify it matches expected hash
import hashlib
expected_sha1 = hashlib.sha1(data).digest()
self.assertEqual(expected_sha1, sha1_digest)
# Test SHA256
sha256_digest = SHA256.hash_object(data)
self.assertIsInstance(sha256_digest, bytes)
self.assertEqual(32, len(sha256_digest))
expected_sha256 = hashlib.sha256(data).digest()
self.assertEqual(expected_sha256, sha256_digest)
def test_hash_object_hex(self) -> None:
"""Test hash_object_hex returns hexadecimal digest."""
data = b"test data"
# Test SHA1
sha1_hex = SHA1.hash_object_hex(data)
self.assertIsInstance(sha1_hex, bytes)
self.assertEqual(40, len(sha1_hex))
# Verify it matches expected hash
import hashlib
expected_sha1_hex = hashlib.sha1(data).hexdigest().encode("ascii")
self.assertEqual(expected_sha1_hex, sha1_hex)
# Test SHA256
sha256_hex = SHA256.hash_object_hex(data)
self.assertIsInstance(sha256_hex, bytes)
self.assertEqual(64, len(sha256_hex))
expected_sha256_hex = hashlib.sha256(data).hexdigest().encode("ascii")
self.assertEqual(expected_sha256_hex, sha256_hex)
class ObjectFormatMappingTests(TestCase):
"""Tests for object format mappings."""
def test_object_formats_dict(self) -> None:
"""Test OBJECT_FORMATS dictionary."""
self.assertEqual(SHA1, OBJECT_FORMATS["sha1"])
self.assertEqual(SHA256, OBJECT_FORMATS["sha256"])
def test_object_format_type_nums_dict(self) -> None:
"""Test OBJECT_FORMAT_TYPE_NUMS dictionary."""
self.assertEqual(SHA1, OBJECT_FORMAT_TYPE_NUMS[1])
self.assertEqual(SHA256, OBJECT_FORMAT_TYPE_NUMS[2])
def test_default_object_format(self) -> None:
"""Test DEFAULT_OBJECT_FORMAT is SHA1."""
self.assertEqual(SHA1, DEFAULT_OBJECT_FORMAT)
class GetObjectFormatTests(TestCase):
"""Tests for get_object_format function."""
def test_get_object_format_none(self) -> None:
"""Test get_object_format with None returns default."""
result = get_object_format(None)
self.assertEqual(DEFAULT_OBJECT_FORMAT, result)
def test_get_object_format_sha1(self) -> None:
"""Test get_object_format with 'sha1'."""
result = get_object_format("sha1")
self.assertEqual(SHA1, result)
def test_get_object_format_sha256(self) -> None:
"""Test get_object_format with 'sha256'."""
result = get_object_format("sha256")
self.assertEqual(SHA256, result)
def test_get_object_format_case_insensitive(self) -> None:
"""Test get_object_format is case insensitive."""
self.assertEqual(SHA1, get_object_format("SHA1"))
self.assertEqual(SHA1, get_object_format("Sha1"))
self.assertEqual(SHA256, get_object_format("SHA256"))
self.assertEqual(SHA256, get_object_format("Sha256"))
def test_get_object_format_invalid(self) -> None:
"""Test get_object_format with invalid name raises ValueError."""
with self.assertRaises(ValueError) as cm:
get_object_format("md5")
self.assertEqual("Unsupported object format: md5", str(cm.exception))
class VerifySameObjectFormatTests(TestCase):
"""Tests for verify_same_object_format function."""
def test_verify_single_format(self) -> None:
"""Test verify_same_object_format with single format."""
result = verify_same_object_format(SHA1)
self.assertEqual(SHA1, result)
def test_verify_multiple_same_formats(self) -> None:
"""Test verify_same_object_format with multiple same formats."""
result = verify_same_object_format(SHA1, SHA1, SHA1)
self.assertEqual(SHA1, result)
result = verify_same_object_format(SHA256, SHA256)
self.assertEqual(SHA256, result)
def test_verify_no_formats(self) -> None:
"""Test verify_same_object_format with no formats raises ValueError."""
with self.assertRaises(ValueError) as cm:
verify_same_object_format()
self.assertEqual(
"At least one object format must be provided", str(cm.exception)
)
def test_verify_different_formats(self) -> None:
"""Test verify_same_object_format with different formats raises ValueError."""
with self.assertRaises(ValueError) as cm:
verify_same_object_format(SHA1, SHA256)
self.assertEqual("Object format mismatch: sha1 != sha256", str(cm.exception))
def test_verify_multiple_different_formats(self) -> None:
"""Test verify_same_object_format fails on first mismatch."""
with self.assertRaises(ValueError) as cm:
verify_same_object_format(SHA1, SHA1, SHA256, SHA1)
self.assertEqual("Object format mismatch: sha1 != sha256", str(cm.exception))
|