492 lines
14 KiB
Python
492 lines
14 KiB
Python
|
|
#!/usr/bin/env python3
|
||
|
|
#
|
||
|
|
# Copyright (c) 2016, The OpenThread Authors.
|
||
|
|
# All rights reserved.
|
||
|
|
#
|
||
|
|
# Redistribution and use in source and binary forms, with or without
|
||
|
|
# modification, are permitted provided that the following conditions are met:
|
||
|
|
# 1. Redistributions of source code must retain the above copyright
|
||
|
|
# notice, this list of conditions and the following disclaimer.
|
||
|
|
# 2. Redistributions in binary form must reproduce the above copyright
|
||
|
|
# notice, this list of conditions and the following disclaimer in the
|
||
|
|
# documentation and/or other materials provided with the distribution.
|
||
|
|
# 3. Neither the name of the copyright holder nor the
|
||
|
|
# names of its contributors may be used to endorse or promote products
|
||
|
|
# derived from this software without specific prior written permission.
|
||
|
|
#
|
||
|
|
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||
|
|
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||
|
|
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||
|
|
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||
|
|
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||
|
|
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||
|
|
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||
|
|
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||
|
|
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||
|
|
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||
|
|
# POSSIBILITY OF SUCH DAMAGE.
|
||
|
|
#
|
||
|
|
|
||
|
|
import io
|
||
|
|
import random
|
||
|
|
import struct
|
||
|
|
import unittest
|
||
|
|
|
||
|
|
import common
|
||
|
|
import network_layer
|
||
|
|
|
||
|
|
|
||
|
|
def any_eid():
|
||
|
|
return bytearray([random.getrandbits(8) for _ in range(16)])
|
||
|
|
|
||
|
|
|
||
|
|
def any_mac_extended_address():
|
||
|
|
return bytearray([random.getrandbits(8) for _ in range(8)])
|
||
|
|
|
||
|
|
|
||
|
|
def any_rloc16():
|
||
|
|
return random.getrandbits(16)
|
||
|
|
|
||
|
|
|
||
|
|
def any_ml_eid():
|
||
|
|
return bytearray([random.getrandbits(8) for _ in range(8)])
|
||
|
|
|
||
|
|
|
||
|
|
def any_status():
|
||
|
|
return random.getrandbits(1)
|
||
|
|
|
||
|
|
|
||
|
|
def any_seconds():
|
||
|
|
return random.getrandbits(32)
|
||
|
|
|
||
|
|
|
||
|
|
def any_id_sequence():
|
||
|
|
return random.getrandbits(8)
|
||
|
|
|
||
|
|
|
||
|
|
def any_router_id_mask():
|
||
|
|
return random.getrandbits(64)
|
||
|
|
|
||
|
|
|
||
|
|
def any_options(count=None):
|
||
|
|
count = count if count is not None else random.randint(0, 255)
|
||
|
|
return [random.getrandbits(8) for _ in range(count)]
|
||
|
|
|
||
|
|
|
||
|
|
def any_tlv_data(length=None):
|
||
|
|
_type = random.getrandbits(8)
|
||
|
|
length = length if length is not None else random.getrandbits(8)
|
||
|
|
value = bytearray([random.getrandbits(8) for _ in range(length)])
|
||
|
|
|
||
|
|
return bytearray([_type, length]) + value
|
||
|
|
|
||
|
|
|
||
|
|
def any_tlvs_data(count=None):
|
||
|
|
count = count if count is not None else random.randint(0, 16)
|
||
|
|
data = bytearray()
|
||
|
|
|
||
|
|
for _ in range(count):
|
||
|
|
data += any_tlv_data(random.randint(1, 15))
|
||
|
|
|
||
|
|
return data
|
||
|
|
|
||
|
|
|
||
|
|
class TestTargetEid(unittest.TestCase):
|
||
|
|
|
||
|
|
def test_should_return_eid_value_when_eid_property_is_called(self):
|
||
|
|
# GIVEN
|
||
|
|
eid = any_eid()
|
||
|
|
|
||
|
|
target_eid = network_layer.TargetEid(eid)
|
||
|
|
|
||
|
|
# WHEN
|
||
|
|
actual_eid = target_eid.eid
|
||
|
|
|
||
|
|
# THEN
|
||
|
|
self.assertEqual(eid, actual_eid)
|
||
|
|
|
||
|
|
def test_should_return_True_when_try_to_equal_two_the_same_type_objects_with_the_same_values(self):
|
||
|
|
# GIVEN
|
||
|
|
eid = any_eid()
|
||
|
|
|
||
|
|
target_eid = network_layer.TargetEid(eid)
|
||
|
|
|
||
|
|
# THEN
|
||
|
|
self.assertEqual(target_eid, network_layer.TargetEid(eid))
|
||
|
|
|
||
|
|
|
||
|
|
class TestTargetEidFactory(unittest.TestCase):
|
||
|
|
|
||
|
|
def test_should_create_TargetEid_from_bytearray_when_parse_method_is_called(self):
|
||
|
|
# GIVEN
|
||
|
|
eid = any_eid()
|
||
|
|
|
||
|
|
factory = network_layer.TargetEidFactory()
|
||
|
|
|
||
|
|
# WHEN
|
||
|
|
target_eid = factory.parse(io.BytesIO(eid), common.MessageInfo())
|
||
|
|
|
||
|
|
# THEN
|
||
|
|
self.assertTrue(isinstance(target_eid, network_layer.TargetEid))
|
||
|
|
self.assertEqual(eid, target_eid.eid)
|
||
|
|
|
||
|
|
|
||
|
|
class TestMacExtendedAddress(unittest.TestCase):
|
||
|
|
|
||
|
|
def test_should_return_mac_address_value_when_mac_address_property_is_called(self):
|
||
|
|
# GIVEN
|
||
|
|
mac_address = any_mac_extended_address()
|
||
|
|
|
||
|
|
mac_extended_address = network_layer.MacExtendedAddress(mac_address)
|
||
|
|
|
||
|
|
# WHEN
|
||
|
|
actual_mac_address = mac_extended_address.mac_address
|
||
|
|
|
||
|
|
# THEN
|
||
|
|
self.assertEqual(mac_address, actual_mac_address)
|
||
|
|
|
||
|
|
def test_should_return_True_when_try_to_equal_two_the_same_type_objects_with_the_same_values(self):
|
||
|
|
# GIVEN
|
||
|
|
mac_address = any_mac_extended_address()
|
||
|
|
|
||
|
|
mac_extended_address = network_layer.MacExtendedAddress(mac_address)
|
||
|
|
|
||
|
|
# THEN
|
||
|
|
self.assertEqual(mac_extended_address, network_layer.MacExtendedAddress(mac_address))
|
||
|
|
|
||
|
|
|
||
|
|
class TestMacExtendedAddressFactory(unittest.TestCase):
|
||
|
|
|
||
|
|
def test_should_create_MacExtendedAddress_from_bytearray_when_parse_method_is_called(self):
|
||
|
|
# GIVEN
|
||
|
|
mac_address = any_mac_extended_address()
|
||
|
|
|
||
|
|
factory = network_layer.MacExtendedAddressFactory()
|
||
|
|
|
||
|
|
# WHEN
|
||
|
|
mac_extended_address = factory.parse(io.BytesIO(mac_address), common.MessageInfo())
|
||
|
|
|
||
|
|
# THEN
|
||
|
|
self.assertTrue(isinstance(mac_extended_address, network_layer.MacExtendedAddress))
|
||
|
|
self.assertEqual(mac_address, mac_extended_address.mac_address)
|
||
|
|
|
||
|
|
|
||
|
|
class TestRloc16(unittest.TestCase):
|
||
|
|
|
||
|
|
def test_should_return_rloc16_value_when_rloc16_property_is_called(self):
|
||
|
|
# GIVEN
|
||
|
|
rloc16 = any_rloc16()
|
||
|
|
|
||
|
|
rloc16_obj = network_layer.Rloc16(rloc16)
|
||
|
|
|
||
|
|
# WHEN
|
||
|
|
actual_rloc16 = rloc16_obj.rloc16
|
||
|
|
|
||
|
|
# THEN
|
||
|
|
self.assertEqual(rloc16, actual_rloc16)
|
||
|
|
|
||
|
|
def test_should_return_True_when_try_to_equal_two_the_same_type_objects_with_the_same_values(self):
|
||
|
|
# GIVEN
|
||
|
|
rloc16 = any_rloc16()
|
||
|
|
|
||
|
|
rloc16_obj = network_layer.Rloc16(rloc16)
|
||
|
|
|
||
|
|
# THEN
|
||
|
|
self.assertEqual(rloc16_obj, network_layer.Rloc16(rloc16))
|
||
|
|
|
||
|
|
|
||
|
|
class TestRloc16Factory(unittest.TestCase):
|
||
|
|
|
||
|
|
def test_should_create_Rloc16_from_bytearray_when_parse_method_is_called(self):
|
||
|
|
# GIVEN
|
||
|
|
rloc16 = any_rloc16()
|
||
|
|
|
||
|
|
factory = network_layer.Rloc16Factory()
|
||
|
|
|
||
|
|
data = bytearray(struct.pack(">H", rloc16))
|
||
|
|
|
||
|
|
# WHEN
|
||
|
|
rloc16_obj = factory.parse(io.BytesIO(data), common.MessageInfo())
|
||
|
|
|
||
|
|
# THEN
|
||
|
|
self.assertTrue(isinstance(rloc16_obj, network_layer.Rloc16))
|
||
|
|
self.assertEqual(rloc16, rloc16_obj.rloc16)
|
||
|
|
|
||
|
|
|
||
|
|
class TestMlEid(unittest.TestCase):
|
||
|
|
|
||
|
|
def test_should_return_ml_eid_value_when_ml_eid_property_is_called(self):
|
||
|
|
# GIVEN
|
||
|
|
ml_eid = any_ml_eid()
|
||
|
|
|
||
|
|
ml_eid_obj = network_layer.MlEid(ml_eid)
|
||
|
|
|
||
|
|
# WHEN
|
||
|
|
actual_ml_eid = ml_eid_obj.ml_eid
|
||
|
|
|
||
|
|
# THEN
|
||
|
|
self.assertEqual(ml_eid, actual_ml_eid)
|
||
|
|
|
||
|
|
def test_should_return_True_when_try_to_equal_two_the_same_type_objects_with_the_same_values(self):
|
||
|
|
# GIVEN
|
||
|
|
ml_eid = any_ml_eid()
|
||
|
|
|
||
|
|
ml_eid_obj = network_layer.MlEid(ml_eid)
|
||
|
|
|
||
|
|
# THEN
|
||
|
|
self.assertEqual(ml_eid_obj, network_layer.MlEid(ml_eid))
|
||
|
|
|
||
|
|
|
||
|
|
class TestMlEidFactory(unittest.TestCase):
|
||
|
|
|
||
|
|
def test_should_create_MlEid_from_bytearray_when_parse_method_is_called(self):
|
||
|
|
# GIVEN
|
||
|
|
ml_eid = any_ml_eid()
|
||
|
|
|
||
|
|
factory = network_layer.MlEidFactory()
|
||
|
|
|
||
|
|
# WHEN
|
||
|
|
ml_eid_obj = factory.parse(io.BytesIO(ml_eid), common.MessageInfo())
|
||
|
|
|
||
|
|
# THEN
|
||
|
|
self.assertTrue(isinstance(ml_eid_obj, network_layer.MlEid))
|
||
|
|
self.assertEqual(ml_eid, ml_eid_obj.ml_eid)
|
||
|
|
|
||
|
|
|
||
|
|
class TestStatus(unittest.TestCase):
|
||
|
|
|
||
|
|
def test_should_return_status_value_when_status_property_is_called(self):
|
||
|
|
# GIVEN
|
||
|
|
status = any_status()
|
||
|
|
|
||
|
|
status_obj = network_layer.Status(status)
|
||
|
|
|
||
|
|
# WHEN
|
||
|
|
actual_status = status_obj.status
|
||
|
|
|
||
|
|
# THEN
|
||
|
|
self.assertEqual(status, actual_status)
|
||
|
|
|
||
|
|
def test_should_return_True_when_try_to_equal_two_the_same_type_objects_with_the_same_values(self):
|
||
|
|
# GIVEN
|
||
|
|
status = any_status()
|
||
|
|
|
||
|
|
status_obj = network_layer.Status(status)
|
||
|
|
|
||
|
|
# THEN
|
||
|
|
self.assertEqual(status_obj, network_layer.Status(status))
|
||
|
|
|
||
|
|
|
||
|
|
class TestStatusFactory(unittest.TestCase):
|
||
|
|
|
||
|
|
def test_should_create_Status_from_bytearray_when_parse_method_is_called(self):
|
||
|
|
# GIVEN
|
||
|
|
status = any_status()
|
||
|
|
|
||
|
|
factory = network_layer.StatusFactory()
|
||
|
|
|
||
|
|
data = bytearray([status])
|
||
|
|
|
||
|
|
# WHEN
|
||
|
|
status_obj = factory.parse(io.BytesIO(data), common.MessageInfo())
|
||
|
|
|
||
|
|
# THEN
|
||
|
|
self.assertTrue(isinstance(status_obj, network_layer.Status))
|
||
|
|
self.assertEqual(status, status_obj.status)
|
||
|
|
|
||
|
|
|
||
|
|
class TestTimeSinceLastTransaction(unittest.TestCase):
|
||
|
|
|
||
|
|
def test_should_return_seconds_value_when_seconds_property_is_called(self):
|
||
|
|
# GIVEN
|
||
|
|
seconds = any_seconds()
|
||
|
|
|
||
|
|
time_since_last_transaction = network_layer.TimeSinceLastTransaction(seconds)
|
||
|
|
|
||
|
|
# WHEN
|
||
|
|
actual_seconds = time_since_last_transaction.seconds
|
||
|
|
|
||
|
|
# THEN
|
||
|
|
self.assertEqual(seconds, actual_seconds)
|
||
|
|
|
||
|
|
def test_should_return_True_when_try_to_equal_two_the_same_type_objects_with_the_same_values(self):
|
||
|
|
# GIVEN
|
||
|
|
seconds = any_seconds()
|
||
|
|
|
||
|
|
time_since_last_transaction = network_layer.TimeSinceLastTransaction(seconds)
|
||
|
|
|
||
|
|
# THEN
|
||
|
|
self.assertEqual(
|
||
|
|
time_since_last_transaction,
|
||
|
|
network_layer.TimeSinceLastTransaction(seconds),
|
||
|
|
)
|
||
|
|
|
||
|
|
|
||
|
|
class TestTimeSinceLastTransactionFactory(unittest.TestCase):
|
||
|
|
|
||
|
|
def test_should_create_TimeSinceLastTransaction_from_bytearray_when_parse_method_is_called(self):
|
||
|
|
# GIVEN
|
||
|
|
seconds = any_seconds()
|
||
|
|
|
||
|
|
factory = network_layer.TimeSinceLastTransactionFactory()
|
||
|
|
|
||
|
|
data = bytearray(struct.pack(">L", seconds))
|
||
|
|
|
||
|
|
# WHEN
|
||
|
|
time_since_last_transaction = factory.parse(io.BytesIO(data), common.MessageInfo())
|
||
|
|
|
||
|
|
# THEN
|
||
|
|
self.assertTrue(isinstance(
|
||
|
|
time_since_last_transaction,
|
||
|
|
network_layer.TimeSinceLastTransaction,
|
||
|
|
))
|
||
|
|
self.assertEqual(seconds, time_since_last_transaction.seconds)
|
||
|
|
|
||
|
|
|
||
|
|
class TestRouterMask(unittest.TestCase):
|
||
|
|
|
||
|
|
def test_should_return_id_sequence_value_when_id_sequence_property_is_called(self):
|
||
|
|
# GIVEN
|
||
|
|
id_sequence = any_id_sequence()
|
||
|
|
|
||
|
|
router_mask = network_layer.RouterMask(id_sequence, any_router_id_mask())
|
||
|
|
|
||
|
|
# WHEN
|
||
|
|
actual_id_sequence = router_mask.id_sequence
|
||
|
|
|
||
|
|
# THEN
|
||
|
|
self.assertEqual(id_sequence, actual_id_sequence)
|
||
|
|
|
||
|
|
def test_should_return_router_id_mask_value_when_router_id_mask_property_is_called(self):
|
||
|
|
# GIVEN
|
||
|
|
router_id_mask = any_router_id_mask()
|
||
|
|
|
||
|
|
router_mask = network_layer.RouterMask(any_id_sequence(), router_id_mask)
|
||
|
|
|
||
|
|
# WHEN
|
||
|
|
actual_router_id_mask = router_mask.router_id_mask
|
||
|
|
|
||
|
|
# THEN
|
||
|
|
self.assertEqual(router_id_mask, actual_router_id_mask)
|
||
|
|
|
||
|
|
def test_should_return_True_when_try_to_equal_two_the_same_type_objects_with_the_same_values(self):
|
||
|
|
# GIVEN
|
||
|
|
id_sequence = any_id_sequence()
|
||
|
|
router_id_mask = any_router_id_mask()
|
||
|
|
|
||
|
|
router_mask = network_layer.RouterMask(id_sequence, router_id_mask)
|
||
|
|
|
||
|
|
# THEN
|
||
|
|
self.assertEqual(router_mask, network_layer.RouterMask(id_sequence, router_id_mask))
|
||
|
|
|
||
|
|
|
||
|
|
class TestRouterMaskFactory(unittest.TestCase):
|
||
|
|
|
||
|
|
def test_should_create_RouterMask_from_bytearray_when_parse_method_is_called(self):
|
||
|
|
# GIVEN
|
||
|
|
id_sequence = any_id_sequence()
|
||
|
|
router_id_mask = any_router_id_mask()
|
||
|
|
|
||
|
|
factory = network_layer.RouterMaskFactory()
|
||
|
|
|
||
|
|
data = bytearray([id_sequence]) + struct.pack(">Q", router_id_mask)
|
||
|
|
|
||
|
|
# WHEN
|
||
|
|
router_mask = factory.parse(io.BytesIO(data), common.MessageInfo())
|
||
|
|
|
||
|
|
# THEN
|
||
|
|
self.assertTrue(isinstance(router_mask, network_layer.RouterMask))
|
||
|
|
self.assertEqual(id_sequence, router_mask.id_sequence)
|
||
|
|
self.assertEqual(router_id_mask, router_mask.router_id_mask)
|
||
|
|
|
||
|
|
|
||
|
|
class TestNdOption(unittest.TestCase):
|
||
|
|
|
||
|
|
def test_should_return_options_value_when_options_property_is_called(self):
|
||
|
|
# GIVEN
|
||
|
|
options = any_options()
|
||
|
|
|
||
|
|
nd_option = network_layer.NdOption(options)
|
||
|
|
|
||
|
|
# WHEN
|
||
|
|
actual_options = nd_option.options
|
||
|
|
|
||
|
|
# THEN
|
||
|
|
self.assertEqual(options, actual_options)
|
||
|
|
|
||
|
|
def test_should_return_True_when_try_to_equal_two_the_same_type_objects_with_the_same_values(self):
|
||
|
|
# GIVEN
|
||
|
|
options = any_options()
|
||
|
|
|
||
|
|
nd_option = network_layer.NdOption(options)
|
||
|
|
|
||
|
|
# THEN
|
||
|
|
self.assertEqual(nd_option, network_layer.NdOption(options))
|
||
|
|
|
||
|
|
|
||
|
|
class TestNdOptionFactory(unittest.TestCase):
|
||
|
|
|
||
|
|
def test_should_create_NdOption_from_bytearray_when_parse_method_is_called(self):
|
||
|
|
# GIVEN
|
||
|
|
options = any_options()
|
||
|
|
|
||
|
|
factory = network_layer.NdOptionFactory()
|
||
|
|
|
||
|
|
data = bytearray(options)
|
||
|
|
|
||
|
|
# WHEN
|
||
|
|
nd_option = factory.parse(io.BytesIO(data), common.MessageInfo())
|
||
|
|
|
||
|
|
# THEN
|
||
|
|
self.assertTrue(isinstance(nd_option, network_layer.NdOption))
|
||
|
|
self.assertEqual(options, nd_option.options)
|
||
|
|
|
||
|
|
|
||
|
|
class TestThreadNetworkData(unittest.TestCase):
|
||
|
|
|
||
|
|
def test_should_return_options_value_when_options_property_is_called(self):
|
||
|
|
# GIVEN
|
||
|
|
tlvs = any_tlvs_data()
|
||
|
|
|
||
|
|
thread_network_data = network_layer.ThreadNetworkData(tlvs)
|
||
|
|
|
||
|
|
# WHEN
|
||
|
|
actual_tlvs = thread_network_data.tlvs
|
||
|
|
|
||
|
|
# THEN
|
||
|
|
self.assertEqual(tlvs, actual_tlvs)
|
||
|
|
|
||
|
|
def test_should_return_True_when_try_to_equal_two_the_same_type_objects_with_the_same_values(self):
|
||
|
|
# GIVEN
|
||
|
|
tlvs = any_tlvs_data()
|
||
|
|
|
||
|
|
thread_network_data = network_layer.ThreadNetworkData(tlvs)
|
||
|
|
|
||
|
|
# THEN
|
||
|
|
self.assertEqual(thread_network_data, network_layer.ThreadNetworkData(tlvs))
|
||
|
|
|
||
|
|
|
||
|
|
class TestThreadNetworkDataFactory(unittest.TestCase):
|
||
|
|
|
||
|
|
def test_should_create_ThreadNetworkData_from_bytearray_when_parse_method_is_called(self):
|
||
|
|
# GIVEN
|
||
|
|
tlvs = any_tlvs_data()
|
||
|
|
|
||
|
|
class DummyNetworkDataTlvsFactory:
|
||
|
|
|
||
|
|
def parse(self, data, message_info):
|
||
|
|
return bytearray(data.read())
|
||
|
|
|
||
|
|
factory = network_layer.ThreadNetworkDataFactory(DummyNetworkDataTlvsFactory())
|
||
|
|
|
||
|
|
# WHEN
|
||
|
|
thread_network_data = factory.parse(io.BytesIO(tlvs), common.MessageInfo())
|
||
|
|
|
||
|
|
# THEN
|
||
|
|
self.assertTrue(isinstance(thread_network_data, network_layer.ThreadNetworkData))
|
||
|
|
self.assertEqual(tlvs, thread_network_data.tlvs)
|
||
|
|
|
||
|
|
|
||
|
|
if __name__ == "__main__":
|
||
|
|
unittest.main()
|