Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 10 additions & 11 deletions pcapkit/protocols/misc/pcap/header.py
Original file line number Diff line number Diff line change
Expand Up @@ -197,8 +197,8 @@ def make(self,

Args:
byteorder: header byte order
lilendian: little-endian flag
bigendian: big-endian flag
lilendian: little-endian flag; overrides ``byteorder`` if given
bigendian: big-endian flag; overrides ``byteorder`` if given
nanosecond: nanosecond-resolution file flag
version: version information
version_major: major version number
Expand Down Expand Up @@ -336,21 +336,20 @@ def _make_magic(self, byteorder: 'Literal["big", "little"]' = sys.byteorder,

Args:
byteorder: header byte order
lilendian: little-endian flag
bigendian: big-endian flag
lilendian: little-endian flag; overrides ``byteorder`` if given
bigendian: big-endian flag; overrides ``byteorder`` if given
nanosecond: nanosecond-resolution file flag

Returns:
Magic number and little-endian flag.

"""
if lilendian is not None and bigendian is not None:
if lilendian == bigendian:
raise EndianError('unresolved byte order')
if bigendian:
return _MAGIC_NUM[('big', nanosecond)], False
if lilendian:
return _MAGIC_NUM[('little', nanosecond)], True
if lilendian is not None and bigendian is not None and lilendian == bigendian:
raise EndianError('unresolved byte order')
if bigendian is not None:
byteorder = 'big' if bigendian else 'little'
elif lilendian is not None:
byteorder = 'little' if lilendian else 'big'

if byteorder not in ('little', 'big'):
raise EndianError(f"unknown byte order: {byteorder!r}")
Expand Down
4 changes: 2 additions & 2 deletions tests/protocols/misc/pcap/test_header_frame_unit.py
Original file line number Diff line number Diff line change
Expand Up @@ -146,8 +146,8 @@ class NamedBytesIO(io.BytesIO):
(b'\xa1\xb2\xc3\xd4', False))
self.assertEqual(header._make_magic(lilendian=True, bigendian=False),
(b'\xd4\xc3\xb2\xa1', True))
self.assertEqual(header._make_magic(byteorder='big', lilendian='', bigendian=False), # type: ignore[arg-type]
(b'\xa1\xb2\xc3\xd4', False))
self.assertEqual(header._make_magic(byteorder='big', bigendian=False),
(b'\xd4\xc3\xb2\xa1', True))
with self.assertRaises(EndianError):
header._make_magic(lilendian=True, bigendian=True)
with self.assertRaises(EndianError):
Expand Down
50 changes: 50 additions & 0 deletions tests/protocols/misc/pcap/test_header_lone_endian_flag_unit.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
from __future__ import annotations

import importlib.util
import unittest

from tests._support import reimport_once_per_class

RUNTIME_DEPS = ('tbtrim', 'aenum', 'chardet', 'dictdumper')
HAS_RUNTIME = all(importlib.util.find_spec(name) is not None for name in RUNTIME_DEPS)

BIG = b'\xa1\xb2\xc3\xd4'
LITTLE = b'\xd4\xc3\xb2\xa1'


@unittest.skipUnless(HAS_RUNTIME, 'runtime dependencies not installed')
class PCAPHeaderLoneEndianFlagUnitTests(unittest.TestCase):
"""A single ``lilendian``/``bigendian`` flag selects the byte order (GH-1144)."""

def setUp(self) -> None:
reimport_once_per_class(self)

def test_lone_flag_overrides_byteorder(self) -> None:
from pcapkit.protocols.misc.pcap.header import Header

# ``byteorder`` is set to the opposite order, so a flag that is ignored
# shows up regardless of the host's own byte order
cases = (
({'bigendian': True, 'byteorder': 'little'}, BIG, 'big'),
({'bigendian': False, 'byteorder': 'big'}, LITTLE, 'little'),
({'lilendian': True, 'byteorder': 'big'}, LITTLE, 'little'),
({'lilendian': False, 'byteorder': 'little'}, BIG, 'big'),
)
for kwargs, magic, byteorder in cases:
with self.subTest(**kwargs):
header = Header(**kwargs)
self.assertEqual(header.data[:4], magic)
self.assertEqual(header.info.magic_number.byteorder, byteorder)

def test_conflicting_flags_are_rejected(self) -> None:
from pcapkit.protocols.misc.pcap.header import Header
from pcapkit.utilities.exceptions import EndianError

for flag in (True, False):
with self.subTest(flag=flag):
with self.assertRaises(EndianError):
Header(lilendian=flag, bigendian=flag)


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