123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234 |
- #!/usr/bin/env python3
- #
- # Copyright (c) 2024, Arm Limited. All rights reserved.
- #
- # SPDX-License-Identifier: BSD-3-Clause
- #
- """Contains unit tests for the types TransferEntry and TransferList."""
- import math
- import pytest
- from tlc.te import TransferEntry
- from tlc.tl import TransferList
- large_data = 0xDEADBEEF.to_bytes(4, "big")
- small_data = 0x1234.to_bytes(3, "big")
- test_entries = [
- (0, b""),
- (1, small_data),
- (1, large_data),
- (0xFFFFFF, small_data),
- (0xFFFFFF, large_data),
- ]
- @pytest.mark.parametrize(
- "size,csum",
- [
- (-1, None),
- (0x18, 0x9E),
- (0x1000, 0xA6),
- (0x2000, 0x96),
- (0x4000, 0x76),
- ],
- )
- def test_make_transfer_list(size, csum):
- if size < 8:
- with pytest.raises(AssertionError):
- tl = TransferList(size)
- else:
- tl = TransferList(size)
- assert tl.signature == 0x4A0FB10B
- assert not tl.entries
- assert tl.sum_of_bytes() == 0
- assert tl.checksum == csum
- @pytest.mark.parametrize(("tag_id", "data"), test_entries)
- def test_add_transfer_entry(tag_id, data):
- tl = TransferList(0x1000)
- te = TransferEntry(tag_id, len(data), data)
- tl.add_transfer_entry(tag_id, data)
- assert te in tl.entries
- assert tl.size == TransferList.hdr_size + te.size
- @pytest.mark.parametrize(
- ("tag_id", "data"),
- [
- (-1, None), # tag out of range
- (1, None), # no data provided
- (1, bytes(8000)), # very large data > total size
- (0x100000, b"0dd0edfe"), # tag out of range
- ],
- )
- def test_add_out_of_range_transfer_entry(tag_id, data):
- tl = TransferList()
- with pytest.raises(Exception):
- tl.add_transfer_entry(tag_id, data)
- @pytest.mark.parametrize(("tag_id", "data"), test_entries)
- def test_calculate_te_sum_of_bytes(tag_id, data):
- te = TransferEntry(tag_id, len(data), data)
- csum = (
- sum(data)
- + sum(len(data).to_bytes(4, "big"))
- + te.hdr_size
- + sum(tag_id.to_bytes(4, "big"))
- ) % 256
- assert te.sum_of_bytes == csum
- @pytest.mark.parametrize(("tag_id", "data"), test_entries)
- def test_calculate_tl_checksum(tag_id, data):
- tl = TransferList(0x1000)
- tl.add_transfer_entry(tag_id, data)
- assert tl.sum_of_bytes() == 0
- def test_empty_transfer_list_blob(tmpdir):
- """Check that we can correctly create a transfer list header."""
- test_file = tmpdir.join("test_tl_blob.bin")
- tl = TransferList()
- tl.write_to_file(test_file)
- with open(test_file, "rb") as f:
- assert f.read(tl.hdr_size) == tl.header_to_bytes()
- @pytest.mark.parametrize(("tag_id", "data"), test_entries)
- def test_single_te_transfer_list(tag_id, data, tmpdir):
- """Check that we can create a complete TL with a single TE."""
- test_file = tmpdir.join("test_tl_blob.bin")
- tl = TransferList(0x1000)
- tl.add_transfer_entry(tag_id, data)
- tl.write_to_file(test_file)
- te = tl.entries[0]
- with open(test_file, "rb") as f:
- assert f.read(tl.hdr_size) == tl.header_to_bytes()
- assert int.from_bytes(f.read(3), "little") == te.id
- assert int.from_bytes(f.read(1), "little") == te.hdr_size
- assert int.from_bytes(f.read(4), "little") == te.data_size
- assert f.read(te.data_size) == te.data
- def test_multiple_te_transfer_list(tmpdir):
- """Check that we can create a TL with multiple TE's."""
- test_file = tmpdir.join("test_tl_blob.bin")
- tl = TransferList(0x1000)
- for tag_id, data in test_entries:
- tl.add_transfer_entry(tag_id, data)
- tl.write_to_file(test_file)
- with open(test_file, "rb") as f:
- assert f.read(tl.hdr_size) == tl.header_to_bytes()
- # Ensure that TE's have the correct alignment
- for tag_id, data in test_entries:
- f.seek(int(math.ceil(f.tell() / 2**tl.alignment) * 2**tl.alignment))
- print(f.tell())
- assert int.from_bytes(f.read(3), "little") == tag_id
- assert int.from_bytes(f.read(1), "little") == TransferEntry.hdr_size
- # Make sure the data in the TE matches the data in the original case
- data_size = int.from_bytes(f.read(4), "little")
- assert f.read(data_size) == data
- def test_read_empty_transfer_list_from_file(tmpdir):
- test_file = tmpdir.join("test_tl_blob.bin")
- original_tl = TransferList(0x1000)
- original_tl.write_to_file(test_file)
- # Read the contents of the file we just wrote
- tl = TransferList.fromfile(test_file)
- assert tl.header_to_bytes() == original_tl.header_to_bytes()
- assert tl.sum_of_bytes() == 0
- def test_read_single_transfer_list_from_file(tmpdir):
- test_file = tmpdir.join("test_tl_blob.bin")
- original_tl = TransferList(0x1000)
- original_tl.add_transfer_entry(test_entries[0][0], test_entries[0][1])
- original_tl.write_to_file(test_file)
- # Read the contents of the file we just wrote
- tl = TransferList.fromfile(test_file)
- assert tl.entries
- te = tl.entries[0]
- assert te.id == test_entries[0][0]
- assert te.data == test_entries[0][1]
- assert tl.sum_of_bytes() == 0
- def test_read_multiple_transfer_list_from_file(tmpdir):
- test_file = tmpdir.join("test_tl_blob.bin")
- original_tl = TransferList(0x1000)
- for tag_id, data in test_entries:
- original_tl.add_transfer_entry(tag_id, data)
- original_tl.write_to_file(test_file)
- # Read the contents of the file we just wrote
- tl = TransferList.fromfile(test_file)
- # The TE we derive from the file might have a an associated offset, compare
- # the TE's based on the header in bytes, which doesn't account for this.
- for te0, te1 in zip(tl.entries, original_tl.entries):
- assert te0.header_to_bytes() == te1.header_to_bytes()
- assert tl.sum_of_bytes() == 0
- @pytest.mark.parametrize("tag", [tag for tag, _ in test_entries])
- def test_remove_tag_from_file(tag):
- tl = TransferList(0x1000)
- for tag_id, data in test_entries:
- tl.add_transfer_entry(tag_id, data)
- removed_entries = list(filter(lambda te: te.id == tag, tl.entries))
- original_size = tl.size
- tl.remove_tag(tag)
- assert not any(tag == te.id for te in tl.entries)
- assert tl.size == original_size - sum(map(lambda te: te.size, removed_entries))
- def test_get_fdt_offset(tmpdir):
- tl = TransferList(0x1000)
- tl.add_transfer_entry(1, 0xEDFE0DD0.to_bytes(4, "big"))
- f = tmpdir.join("blob.bin")
- tl.write_to_file(f)
- blob_tl = TransferList.fromfile(f)
- assert blob_tl.hdr_size + TransferEntry.hdr_size == blob_tl.get_entry_data_offset(1)
- def test_get_missing_fdt_offset(tmpdir):
- tl = TransferList(0x1000)
- f = tmpdir.join("blob.bin")
- tl.write_to_file(f)
- blob_tl = TransferList.fromfile(f)
- with pytest.raises(ValueError):
- blob_tl.get_entry_data_offset(1)
|