"""Test NetworkElementUpdate framework"""
from datetime import datetime, timezone
import unittest
from hashlib import sha256
from uuid import uuid4

from preseem_protobuf.network_poller import network_poller_pb2
from preseem import network_element_update


class TestNetworkElementUpdate(unittest.TestCase):

    def setUp(self):
        pass

    def tearDown(self):
        pass

    def test_01(self):
        """Try setting and getting the fields."""
        neu = network_element_update.NetworkElementUpdate()

        ts = 1612927766
        neu.time = ts
        self.assertEqual(ts, neu.time)

        company_uuid = uuid4().bytes
        neu.company_uuid = company_uuid
        self.assertEqual(company_uuid, neu.company_uuid)

        element_uuid = uuid4().bytes
        neu.element_uuid = element_uuid
        self.assertEqual(element_uuid, neu.element_uuid)

        instance = 'MyInstance'
        neu.instance = instance
        self.assertEqual(instance, neu.instance)

        neu.active = True
        self.assertEqual(neu.active, True)

        neu.pingable = True
        self.assertEqual(neu.pingable, True)

        neu.errctx = network_element_update.ErrorContext()
        self.assertEqual(neu.ping_time, None)
        neu.ping_time = 120
        self.assertEqual(neu.ping_time, 120)
        neu.ping_time = pow(2, 31)
        self.assertEqual(neu.ping_time, 120)
        neu.ping_time = -1
        self.assertEqual(neu.ping_time, 120)
        neu.ping_time = None
        self.assertEqual(neu.ping_time, None)
        self.assertEqual(len(neu.errctx.errors), 2)
        neu.errctx = None

        neu.snmp_version = network_poller_pb2.SnmpVersion.V2C
        self.assertEqual(neu.snmp_version, network_poller_pb2.SnmpVersion.V2C)

        sysobjid = '1.3.6.1.4.1.43356.1.1.3'
        self.assertEqual(neu.sysobjid, None)
        neu.sysobjid = sysobjid
        self.assertEqual(neu.sysobjid, sysobjid)
        neu.sysobjid = None
        self.assertEqual(neu.sysobjid, None)

        neu.errctx = network_element_update.ErrorContext()
        self.assertEqual(neu.poll_time, None)
        neu.poll_time = 60
        self.assertEqual(neu.poll_time, 60)
        neu.poll_time = pow(2, 31)
        self.assertEqual(neu.poll_time, 60)
        neu.poll_time = -1
        self.assertEqual(neu.poll_time, 60)
        neu.poll_time = None
        self.assertEqual(neu.poll_time, None)
        self.assertEqual(len(neu.errctx.errors), 2)
        neu.errctx = None

        self.assertEqual(neu.is_topology_stale, None)
        neu.is_topology_stale = True
        self.assertTrue(neu.is_topology_stale)
        neu.is_topology_stale = False
        self.assertFalse(neu.is_topology_stale)
        neu.is_topology_stale = None
        self.assertEqual(neu.is_topology_stale, None)

        poller_version = '11.22.33'
        neu.poller_version = poller_version
        self.assertEqual(poller_version, neu.poller_version)

        # Check functionality of a simple repeated type
        self.assertEqual(list(neu.errors), [])
        neu.errors.append(network_poller_pb2.PollError.ERROR_SNMP_OFFLINE)
        neu.errors.append(network_poller_pb2.PollError.ERROR_SNMP_BAD_MIB)
        self.assertEqual(len(neu.errors), 2)
        self.assertEqual(neu.errors[0], network_poller_pb2.PollError.ERROR_SNMP_OFFLINE)
        self.assertEqual(neu.errors[1], network_poller_pb2.PollError.ERROR_SNMP_BAD_MIB)
        del neu.errors[0]
        self.assertEqual(len(neu.errors), 1)
        self.assertEqual(neu.errors[0], network_poller_pb2.PollError.ERROR_SNMP_BAD_MIB)

        # Check functionality of a message repeated type
        self.assertEqual(list(neu.peers), [])
        peer = neu.peers.add()
        self.assertEqual(len(neu.peers), 1)
        del neu.peers[0]
        self.assertEqual(len(neu.peers), 0)

        # Test IpMac
        self.assertEqual(list(neu.ip_macs), [])
        ip_mac = neu.ip_macs.add()
        self.assertEqual(len(neu.ip_macs), 1)

        ip_mac.ip_address = "1.2.3.4"
        self.assertEqual(ip_mac.ip_address, "1.2.3.4")

        ip_mac.mac_address = "0a:00:00:01:02:01"
        self.assertEqual(ip_mac.mac_address, "0a:00:00:01:02:01")

        ip_mac.errctx = network_element_update.ErrorContext()
        self.assertEqual(ip_mac.port, None)
        ip_mac.port = 12
        self.assertEqual(ip_mac.port, 12)
        ip_mac.port = -1
        self.assertEqual(ip_mac.port, 12)
        ip_mac.port = pow(2, 31) + 1
        self.assertEqual(ip_mac.port, 12)
        ip_mac.port = None
        self.assertEqual(len(ip_mac.errctx.errors), 2)
        ip_mac.errctx = None

        del neu.ip_macs[0]
        self.assertEqual(len(neu.ip_macs), 0)

        # Test Route
        self.assertEqual(list(neu.routes), [])
        route = neu.routes.add()
        self.assertEqual(len(neu.routes), 1)

        self.assertEqual(route.net, "")
        route.net = "0b:00:00:01:02:01"
        self.assertEqual(route.net, "0b:00:00:01:02:01")

        route.errctx = network_element_update.ErrorContext()
        self.assertEqual(route.if_index, None)
        route.if_index = 11
        self.assertEqual(route.if_index, 11)
        route.if_index = -1
        self.assertEqual(route.if_index, 11)
        route.if_index = pow(2, 31) + 1
        self.assertEqual(route.if_index, 11)
        route.if_index = None
        self.assertEqual(len(route.errctx.errors), 2)
        route.errctx = None

        next_hop = '0b:00:00:01:02:03'
        self.assertEqual(route.next_hop, None)
        route.next_hop = next_hop
        self.assertEqual(route.next_hop, next_hop)
        route.next_hop = None
        self.assertEqual(route.next_hop, None)

        mac_address = '0b:00:00:01:02:04'
        self.assertEqual(route.mac_address, None)
        route.mac_address = mac_address
        self.assertEqual(route.mac_address, mac_address)
        route.mac_address = None
        self.assertEqual(route.mac_address, None)

        del neu.routes[0]
        self.assertEqual(len(neu.routes), 0)

        # Test DhcpLease
        self.assertEqual(list(neu.dhcp_leases), [])
        dhcp_lease = neu.dhcp_leases.add()
        self.assertEqual(len(neu.dhcp_leases), 1)

        dhcp_lease.ip_address = "1.2.3.4"
        self.assertEqual(dhcp_lease.ip_address, "1.2.3.4")

        dhcp_lease.mac_address = "0a:00:00:01:02:01"
        self.assertEqual(dhcp_lease.mac_address, "0a:00:00:01:02:01")

        circuit_id = '0b:00:00:01:02:07'
        self.assertEqual(dhcp_lease.circuit_id, None)
        dhcp_lease.circuit_id = circuit_id
        self.assertEqual(dhcp_lease.circuit_id, circuit_id)
        dhcp_lease.circuit_id = None
        self.assertEqual(dhcp_lease.circuit_id, None)

        remote_id = '0b:00:00:01:02:08'
        self.assertEqual(dhcp_lease.remote_id, None)
        dhcp_lease.remote_id = remote_id
        self.assertEqual(dhcp_lease.remote_id, remote_id)
        dhcp_lease.remote_id = None
        self.assertEqual(dhcp_lease.remote_id, None)

        hostname = 'testhost1'
        self.assertEqual(dhcp_lease.hostname, None)
        dhcp_lease.hostname = hostname
        self.assertEqual(dhcp_lease.hostname, hostname)
        dhcp_lease.hostname = None
        self.assertEqual(dhcp_lease.hostname, None)

        del neu.dhcp_leases[0]
        self.assertEqual(len(neu.dhcp_leases), 0)

        # Test PppoeClient
        self.assertEqual(list(neu.pppoe_clients), [])
        pppoe_client = neu.pppoe_clients.add()
        self.assertEqual(len(neu.pppoe_clients), 1)

        pppoe_client.errctx = network_element_update.ErrorContext()

        pppoe_client.username = "user1"
        self.assertEqual(pppoe_client.username, "user1")

        mac_address = '0b:00:00:01:02:04'
        self.assertEqual(pppoe_client.mac_address, None)
        pppoe_client.mac_address = mac_address
        self.assertEqual(pppoe_client.mac_address, mac_address)
        pppoe_client.mac_address = None
        self.assertEqual(pppoe_client.mac_address, None)

        del neu.pppoe_clients[0]
        self.assertEqual(len(neu.pppoe_clients), 0)

        self.assertEqual(list(pppoe_client.network_prefixes), [])
        pppoe_client.network_prefixes.append('192.0.2.100')
        self.assertEqual(len(pppoe_client.network_prefixes), 1)
        self.assertEqual(pppoe_client.network_prefixes[0], '192.0.2.100')
        pppoe_client.network_prefixes.append('192.0.3.100/29')
        self.assertEqual(len(pppoe_client.network_prefixes), 2)
        self.assertEqual(pppoe_client.network_prefixes[1], '192.0.3.100/29')
        del pppoe_client.network_prefixes[1]
        self.assertEqual(len(pppoe_client.network_prefixes), 1)
        del pppoe_client.network_prefixes[0]
        self.assertEqual(len(pppoe_client.network_prefixes), 0)

        # Check copy behavior of sub-message assignment
        ne = network_element_update.NetworkElement()
        self.assertEqual(ne.management_ip, None)
        ne.management_ip = '192.0.2.2'
        neu.data = ne  # this is a copy, not a ref
        self.assertEqual(neu.data.management_ip, '192.0.2.2')
        ne.management_ip = None
        self.assertEqual(ne.management_ip, None)
        self.assertEqual(neu.data.management_ip, '192.0.2.2')

        self.assertEqual(ne.name, None)
        ne.name = 'my-name'
        self.assertEqual(ne.name, 'my-name')
        ne.name = None
        self.assertEqual(ne.name, None)

        self.assertEqual(ne.manufacturer, None)
        ne.manufacturer = 'my-mfg'
        self.assertEqual(ne.manufacturer, 'my-mfg')
        ne.manufacturer = None
        self.assertEqual(ne.manufacturer, None)

        self.assertEqual(ne.model, None)
        ne.model = 'my-mod'
        self.assertEqual(ne.model, 'my-mod')
        ne.model = None
        self.assertEqual(ne.model, None)

        self.assertEqual(ne.serial_number, None)
        ne.serial_number = 'my-ser'
        self.assertEqual(ne.serial_number, 'my-ser')
        ne.serial_number = None
        self.assertEqual(ne.serial_number, None)

        self.assertEqual(ne.system_mac_address, None)
        ne.system_mac_address = '0a:00:00:01:02:03'
        self.assertEqual(ne.system_mac_address, '0a:00:00:01:02:03')
        with self.assertRaises(ValueError):
            ne.system_mac_address = 'asdf'
        with self.assertRaises(ValueError):
            ne.system_mac_address = '11:22:33:44:55:66:77'

        ne.system_mac_address = None
        self.assertEqual(ne.system_mac_address, None)

        self.assertEqual(ne.sw_version, None)
        ne.sw_version = '1.2.3'
        self.assertEqual(ne.sw_version, '1.2.3')
        ne.sw_version = None
        self.assertEqual(ne.sw_version, None)

        ne.errctx = network_element_update.ErrorContext()
        self.assertEqual(ne.uptime, None)
        ne.uptime = 12345
        self.assertEqual(ne.uptime, 12345)
        ne.uptime = -1
        self.assertEqual(ne.uptime, 12345)
        ne.uptime = pow(2, 63) + 1
        self.assertEqual(ne.uptime, 12345)
        ne.uptime = None
        self.assertEqual(len(ne.errctx.errors), 2)
        ne.errctx = None

        ne.errctx = network_element_update.ErrorContext()
        self.assertEqual(ne.cpu, None)
        ne.cpu = 5.5
        self.assertEqual(round(ne.cpu, 4), 5.5)
        ne.cpu = -1
        self.assertEqual(round(ne.cpu, 4), 5.5)
        ne.cpu = 100.1
        self.assertEqual(round(ne.cpu, 4), 5.5)
        ne.cpu = None
        self.assertEqual(ne.cpu, None)
        self.assertEqual(len(ne.errctx.errors), 2)
        ne.errctx = None

        ne.errctx = network_element_update.ErrorContext()
        self.assertEqual(ne.mem, None)
        ne.mem = 5.6
        self.assertEqual(round(ne.mem, 4), 5.6)
        ne.mem = -1
        self.assertEqual(round(ne.mem, 4), 5.6)
        ne.mem = 100.1
        self.assertEqual(round(ne.mem, 4), 5.6)
        ne.mem = None
        self.assertEqual(ne.mem, None)
        self.assertEqual(len(ne.errctx.errors), 2)
        ne.errctx = None

        self.assertEqual(ne.temperature, None)
        ne.temperature = 31.02
        self.assertEqual(round(ne.temperature, 4), 31.02)
        ne.temperature = -10
        self.assertEqual(round(ne.temperature, 4), -10)
        ne.temperature = None
        self.assertEqual(ne.temperature, None)

        poller_hash = sha256().digest()
        ne.poller_hash = poller_hash
        self.assertEqual(poller_hash, ne.poller_hash)

        ne.errctx = network_element_update.ErrorContext()
        self.assertEqual(ne.gps_sats_tracked, None)
        ne.gps_sats_tracked = 12
        self.assertEqual(ne.gps_sats_tracked, 12)
        ne.gps_sats_tracked = -1
        self.assertEqual(ne.gps_sats_tracked, 12)
        ne.gps_sats_tracked = pow(2, 31) + 1
        self.assertEqual(ne.gps_sats_tracked, 12)
        ne.gps_sats_tracked = None
        self.assertEqual(len(ne.errctx.errors), 2)
        ne.errctx = None

        self.assertEqual(ne.latitude, None)
        ne.latitude = 43.4772382
        self.assertEqual(ne.latitude, 43.4772382)
        ne.latitude = None
        self.assertEqual(ne.latitude, None)

        self.assertEqual(ne.longitude, None)
        ne.longitude = -80.5516853
        self.assertEqual(ne.longitude, -80.5516853)
        ne.longitude = None
        self.assertEqual(ne.longitude, None)

        self.assertEqual(ne.elevation, None)
        ne.elevation = 45.67
        self.assertEqual(round(ne.elevation, 4), 45.67)
        ne.elevation = None
        self.assertEqual(ne.elevation, None)

        self.assertEqual(ne.height, None)
        ne.height = 78.90
        self.assertEqual(round(ne.height, 4), 78.90)
        ne.height = None
        self.assertEqual(ne.height, None)

        self.assertEqual(ne.imsi, None)
        ne.imsi = '123456789012345'
        self.assertEqual(ne.imsi, '123456789012345')
        ne.imsi = None
        self.assertEqual(ne.imsi, None)

        self.assertEqual(ne.admin_disabled, None)
        ne.admin_disabled = True
        self.assertEqual(ne.admin_disabled, True)
        ne.admin_disabled = None
        self.assertEqual(ne.admin_disabled, None)

        self.assertEqual(ne.extra, None)
        ne.extra = '{"key": "value"}'
        self.assertEqual(ne.extra, '{"key": "value"}')
        ne.extra = None
        self.assertEqual(ne.extra, None)

        self.assertEqual(ne.counter_source, None)
        ne.counter_source = "http"
        self.assertEqual(ne.counter_source, "http")
        ne.counter_source = None
        self.assertEqual(ne.counter_source, None)
        ne.counter_source = "snmp"
        self.assertEqual(ne.counter_source, "snmp")

        self.assertEqual(ne.offline_reason, None)
        ne.offline_reason = network_poller_pb2.OfflineReason.OFFLINE_REASON_POWER_OFF
        self.assertEqual(ne.offline_reason, network_poller_pb2.OfflineReason.OFFLINE_REASON_POWER_OFF)
        ne.offline_reason = None
        self.assertEqual(ne.offline_reason, None)
        ne.offline_reason = network_poller_pb2.OfflineReason.OFFLINE_REASON_OTHER
        self.assertEqual(ne.offline_reason, network_poller_pb2.OfflineReason.OFFLINE_REASON_OTHER)

        self.assertEqual(ne.offline_reason_detail, None)
        ne.offline_reason_detail = "dying gasp"
        self.assertEqual(ne.offline_reason_detail, "dying gasp")
        ne.offline_reason_detail = None
        self.assertEqual(ne.offline_reason_detail, None)
        ne.offline_reason_detail = "unknown"
        self.assertEqual(ne.offline_reason_detail, "unknown")

        ut_time = datetime(2025, 7, 14, 12, 34, 56, tzinfo=timezone.utc)
        self.assertEqual(ne.offline_time, None)
        ne.offline_time = ut_time
        self.assertEqual(ne.offline_time, ut_time)
        ne.offline_time = None
        self.assertEqual(ne.offline_time, None)
        ne.offline_time = ut_time
        self.assertEqual(ne.offline_time, ut_time)

        # Interface
        intf = ne.interfaces.add()
        intf.id = '1'
        self.assertEqual(intf.id, '1')

        self.assertEqual(intf.name, None)
        intf.name = 'interface 1'
        self.assertEqual(intf.name, 'interface 1')
        intf.name = None
        self.assertEqual(intf.name, None)

        intf.errctx = network_element_update.ErrorContext()
        self.assertEqual(intf.type, None)
        intf.type = 6
        self.assertEqual(intf.type, 6)
        intf.type = -1
        self.assertEqual(intf.type, 6)
        intf.type = pow(2, 31) + 1
        self.assertEqual(intf.type, 6)
        intf.type = None
        self.assertEqual(intf.type, None)
        self.assertEqual(len(intf.errctx.errors), 2)
        intf.errctx = None

        intf.errctx = network_element_update.ErrorContext()
        self.assertEqual(intf.mtu, None)
        intf.mtu = 1500
        self.assertEqual(intf.mtu, 1500)
        intf.mtu = -1
        self.assertEqual(intf.mtu, 1500)
        intf.mtu = pow(2, 31) + 1
        self.assertEqual(intf.mtu, 1500)
        intf.mtu = None
        self.assertEqual(intf.mtu, None)
        self.assertEqual(len(intf.errctx.errors), 2)
        intf.errctx = None

        intf.errctx = network_element_update.ErrorContext()
        self.assertEqual(intf.speed, None)
        intf.speed = 10000000000
        self.assertEqual(intf.speed, 10000000000)
        intf.speed = -1
        self.assertEqual(intf.speed, 10000000000)
        intf.speed = pow(2, 63) + 1
        self.assertEqual(intf.speed, 10000000000)
        intf.speed = None
        self.assertEqual(intf.speed, None)
        self.assertEqual(len(intf.errctx.errors), 2)
        intf.errctx = None

        self.assertEqual(intf.mac_address, None)
        intf.mac_address = '0a:00:00:01:02:03'
        self.assertEqual(intf.mac_address, '0a:00:00:01:02:03')
        intf.mac_address = None
        self.assertEqual(intf.mac_address, None)

        self.assertEqual(intf.admin_up, None)
        intf.admin_up = True
        self.assertEqual(intf.admin_up, True)
        intf.admin_up = None
        self.assertEqual(intf.admin_up, None)

        self.assertEqual(intf.oper_up, None)
        intf.oper_up = False
        self.assertEqual(intf.oper_up, False)
        intf.oper_up = None
        self.assertEqual(intf.oper_up, None)

        intf.errctx = network_element_update.ErrorContext()
        self.assertEqual(intf.in_octets, None)
        intf.in_octets = pow(2, 31) + 1
        self.assertEqual(intf.in_octets, pow(2, 31) + 1)
        intf.in_octets = -1
        self.assertEqual(intf.in_octets, pow(2, 31) + 1)
        intf.in_octets = pow(2, 63) + 1
        self.assertEqual(intf.in_octets, pow(2, 31) + 1)
        intf.in_octets = None
        self.assertEqual(intf.in_octets, None)
        self.assertEqual(len(intf.errctx.errors), 2)
        intf.errctx = None

        intf.errctx = network_element_update.ErrorContext()
        self.assertEqual(intf.in_ucast_pkts, None)
        intf.in_ucast_pkts = pow(2, 32) + 1
        self.assertEqual(intf.in_ucast_pkts, pow(2, 32) + 1)
        intf.in_ucast_pkts = -1
        self.assertEqual(intf.in_ucast_pkts, pow(2, 32) + 1)
        intf.in_ucast_pkts = pow(2, 63) + 1
        self.assertEqual(intf.in_ucast_pkts, pow(2, 32) + 1)
        intf.in_ucast_pkts = None
        self.assertEqual(intf.in_ucast_pkts, None)
        self.assertEqual(len(intf.errctx.errors), 2)
        intf.errctx = None

        intf.errctx = network_element_update.ErrorContext()
        self.assertEqual(intf.in_nucast_pkts, None)
        intf.in_nucast_pkts = pow(2, 33) + 1
        self.assertEqual(intf.in_nucast_pkts, pow(2, 33) + 1)
        intf.in_nucast_pkts = -1
        self.assertEqual(intf.in_nucast_pkts, pow(2, 33) + 1)
        intf.in_nucast_pkts = pow(2, 63) + 1
        self.assertEqual(intf.in_nucast_pkts, pow(2, 33) + 1)
        intf.in_nucast_pkts = None
        self.assertEqual(intf.in_nucast_pkts, None)
        self.assertEqual(len(intf.errctx.errors), 2)
        intf.errctx = None

        intf.errctx = network_element_update.ErrorContext()
        self.assertEqual(intf.in_discards, None)
        intf.in_discards = pow(2, 34) + 1
        self.assertEqual(intf.in_discards, pow(2, 34) + 1)
        intf.in_discards = -1
        self.assertEqual(intf.in_discards, pow(2, 34) + 1)
        intf.in_discards = pow(2, 63) + 1
        self.assertEqual(intf.in_discards, pow(2, 34) + 1)
        intf.in_discards = None
        self.assertEqual(intf.in_discards, None)
        self.assertEqual(len(intf.errctx.errors), 2)
        intf.errctx = None

        intf.errctx = network_element_update.ErrorContext()
        self.assertEqual(intf.in_errors, None)
        intf.in_errors = pow(2, 35) + 1
        self.assertEqual(intf.in_errors, pow(2, 35) + 1)
        intf.in_errors = -1
        self.assertEqual(intf.in_errors, pow(2, 35) + 1)
        intf.in_errors = pow(2, 63) + 1
        self.assertEqual(intf.in_errors, pow(2, 35) + 1)
        intf.in_errors = None
        self.assertEqual(intf.in_errors, None)
        self.assertEqual(len(intf.errctx.errors), 2)
        intf.errctx = None

        intf.errctx = network_element_update.ErrorContext()
        self.assertEqual(intf.in_unknown_protos, None)
        intf.in_unknown_protos = pow(2, 36) + 1
        self.assertEqual(intf.in_unknown_protos, pow(2, 36) + 1)
        intf.in_unknown_protos = -1
        self.assertEqual(intf.in_unknown_protos, pow(2, 36) + 1)
        intf.in_unknown_protos = pow(2, 63) + 1
        self.assertEqual(intf.in_unknown_protos, pow(2, 36) + 1)
        intf.in_unknown_protos = None
        self.assertEqual(intf.in_unknown_protos, None)
        self.assertEqual(len(intf.errctx.errors), 2)
        intf.errctx = None

        intf.errctx = network_element_update.ErrorContext()
        self.assertEqual(intf.out_octets, None)
        intf.out_octets = pow(2, 37) + 1
        self.assertEqual(intf.out_octets, pow(2, 37) + 1)
        intf.out_octets = -1
        self.assertEqual(intf.out_octets, pow(2, 37) + 1)
        intf.out_octets = pow(2, 63) + 1
        self.assertEqual(intf.out_octets, pow(2, 37) + 1)
        intf.out_octets = None
        self.assertEqual(intf.out_octets, None)
        self.assertEqual(len(intf.errctx.errors), 2)
        intf.errctx = None

        intf.errctx = network_element_update.ErrorContext()
        self.assertEqual(intf.out_ucast_pkts, None)
        intf.out_ucast_pkts = pow(2, 38) + 1
        self.assertEqual(intf.out_ucast_pkts, pow(2, 38) + 1)
        intf.out_ucast_pkts = -1
        self.assertEqual(intf.out_ucast_pkts, pow(2, 38) + 1)
        intf.out_ucast_pkts = pow(2, 63) + 1
        self.assertEqual(intf.out_ucast_pkts, pow(2, 38) + 1)
        intf.out_ucast_pkts = None
        self.assertEqual(intf.out_octets, None)
        self.assertEqual(len(intf.errctx.errors), 2)
        intf.errctx = None

        intf.errctx = network_element_update.ErrorContext()
        self.assertEqual(intf.out_nucast_pkts, None)
        intf.out_nucast_pkts = pow(2, 39) + 1
        self.assertEqual(intf.out_nucast_pkts, pow(2, 39) + 1)
        intf.out_nucast_pkts = -1
        self.assertEqual(intf.out_nucast_pkts, pow(2, 39) + 1)
        intf.out_nucast_pkts = pow(2, 63) + 1
        self.assertEqual(intf.out_nucast_pkts, pow(2, 39) + 1)
        intf.out_nucast_pkts = None
        self.assertEqual(intf.out_octets, None)
        self.assertEqual(len(intf.errctx.errors), 2)
        intf.errctx = None

        intf.errctx = network_element_update.ErrorContext()
        self.assertEqual(intf.out_discards, None)
        intf.out_discards = pow(2, 40) + 1
        self.assertEqual(intf.out_discards, pow(2, 40) + 1)
        intf.out_discards = -1
        self.assertEqual(intf.out_discards, pow(2, 40) + 1)
        intf.out_discards = pow(2, 63) + 1
        self.assertEqual(intf.out_discards, pow(2, 40) + 1)
        intf.out_discards = None
        self.assertEqual(intf.out_discards, None)
        self.assertEqual(len(intf.errctx.errors), 2)
        intf.errctx = None

        intf.errctx = network_element_update.ErrorContext()
        self.assertEqual(intf.out_errors, None)
        intf.out_errors = pow(2, 41) + 1
        self.assertEqual(intf.out_errors, pow(2, 41) + 1)
        intf.out_errors = -1
        self.assertEqual(intf.out_errors, pow(2, 41) + 1)
        intf.out_errors = pow(2, 63) + 1
        self.assertEqual(intf.out_errors, pow(2, 41) + 1)
        intf.out_errors = None
        self.assertEqual(intf.out_discards, None)
        self.assertEqual(len(intf.errctx.errors), 2)
        intf.errctx = None

        self.assertEqual(list(intf.ip_addresses), [])
        intf.ip_addresses.append('192.0.2.2')
        self.assertEqual(len(intf.ip_addresses), 1)
        self.assertEqual(intf.ip_addresses[0], '192.0.2.2')
        del intf.ip_addresses[0]
        self.assertEqual(len(intf.ip_addresses), 0)

        self.assertEqual(list(intf.bridged_mac_addresses), [])
        intf.bridged_mac_addresses.append('0a:00:00:0a:0b:0c')
        self.assertEqual(len(intf.bridged_mac_addresses), 1)
        self.assertEqual(intf.bridged_mac_addresses[0], '0a:00:00:0a:0b:0c')
        self.assertEqual([x for x in intf.bridged_mac_addresses], ['0a:00:00:0a:0b:0c'])
        del intf.bridged_mac_addresses[0]
        self.assertEqual(len(intf.bridged_mac_addresses), 0)

        self.assertEqual(intf.poller_hash, None)
        poller_hash = sha256().digest()
        intf.poller_hash = poller_hash
        self.assertEqual(poller_hash, intf.poller_hash)
        intf.poller_hash = None
        self.assertEqual(intf.poller_hash, None)

        self.assertEqual(intf.manufacturer, None)
        intf.manufacturer = 'intf-mfg'
        self.assertEqual(intf.manufacturer, 'intf-mfg')
        intf.manufacturer = None
        self.assertEqual(intf.manufacturer, None)

        self.assertEqual(intf.model, None)
        intf.model = 'intf-mod'
        self.assertEqual(intf.model, 'intf-mod')
        intf.model = None
        self.assertEqual(intf.model, None)

        # Link
        link = intf.links.add()
        link.mac_address = '0a:00:00:0d:0e:0f'
        self.assertEqual(link.mac_address, '0a:00:00:0d:0e:0f')

        self.assertEqual(link.oper_up, None)
        link.oper_up = False
        self.assertEqual(link.oper_up, False)
        link.oper_up = None
        self.assertEqual(link.oper_up, None)

        link.errctx = network_element_update.ErrorContext()
        self.assertEqual(link.in_octets, None)
        link.in_octets = pow(2, 31) + 1
        self.assertEqual(link.in_octets, pow(2, 31) + 1)
        link.in_octets = -1
        self.assertEqual(link.in_octets, pow(2, 31) + 1)
        link.in_octets = pow(2, 63) + 1
        self.assertEqual(link.in_octets, pow(2, 31) + 1)
        link.in_octets = None
        self.assertEqual(link.in_octets, None)
        self.assertEqual(len(link.errctx.errors), 2)
        link.errctx = None

        link.errctx = network_element_update.ErrorContext()
        self.assertEqual(link.in_ucast_pkts, None)
        link.in_ucast_pkts = pow(2, 32) + 1
        self.assertEqual(link.in_ucast_pkts, pow(2, 32) + 1)
        link.in_ucast_pkts = -1
        self.assertEqual(link.in_ucast_pkts, pow(2, 32) + 1)
        link.in_ucast_pkts = pow(2, 63) + 1
        self.assertEqual(link.in_ucast_pkts, pow(2, 32) + 1)
        link.in_ucast_pkts = None
        self.assertEqual(link.in_ucast_pkts, None)
        self.assertEqual(len(link.errctx.errors), 2)
        link.errctx = None

        link.errctx = network_element_update.ErrorContext()
        self.assertEqual(link.in_nucast_pkts, None)
        link.in_nucast_pkts = pow(2, 33) + 1
        self.assertEqual(link.in_nucast_pkts, pow(2, 33) + 1)
        link.in_nucast_pkts = -1
        self.assertEqual(link.in_nucast_pkts, pow(2, 33) + 1)
        link.in_nucast_pkts = pow(2, 63) + 1
        self.assertEqual(link.in_nucast_pkts, pow(2, 33) + 1)
        link.in_nucast_pkts = None
        self.assertEqual(link.in_nucast_pkts, None)
        self.assertEqual(len(link.errctx.errors), 2)
        link.errctx = None

        link.errctx = network_element_update.ErrorContext()
        self.assertEqual(link.in_discards, None)
        link.in_discards = pow(2, 34) + 1
        self.assertEqual(link.in_discards, pow(2, 34) + 1)
        link.in_discards = -1
        self.assertEqual(link.in_discards, pow(2, 34) + 1)
        link.in_discards = pow(2, 63) + 1
        self.assertEqual(link.in_discards, pow(2, 34) + 1)
        link.in_discards = None
        self.assertEqual(link.in_discards, None)
        self.assertEqual(len(link.errctx.errors), 2)
        link.errctx = None

        link.errctx = network_element_update.ErrorContext()
        self.assertEqual(link.in_errors, None)
        link.in_errors = pow(2, 35) + 1
        self.assertEqual(link.in_errors, pow(2, 35) + 1)
        link.in_errors = -1
        self.assertEqual(link.in_errors, pow(2, 35) + 1)
        link.in_errors = pow(2, 63) + 1
        self.assertEqual(link.in_errors, pow(2, 35) + 1)
        link.in_errors = None
        self.assertEqual(link.in_errors, None)
        self.assertEqual(len(link.errctx.errors), 2)
        link.errctx = None

        link.errctx = network_element_update.ErrorContext()
        self.assertEqual(link.in_unknown_protos, None)
        link.in_unknown_protos = pow(2, 36) + 1
        self.assertEqual(link.in_unknown_protos, pow(2, 36) + 1)
        link.in_unknown_protos = -1
        self.assertEqual(link.in_unknown_protos, pow(2, 36) + 1)
        link.in_unknown_protos = pow(2, 63) + 1
        self.assertEqual(link.in_unknown_protos, pow(2, 36) + 1)
        link.in_unknown_protos = None
        self.assertEqual(link.in_unknown_protos, None)
        self.assertEqual(len(link.errctx.errors), 2)
        link.errctx = None

        link.errctx = network_element_update.ErrorContext()
        self.assertEqual(link.out_octets, None)
        link.out_octets = pow(2, 37) + 1
        self.assertEqual(link.out_octets, pow(2, 37) + 1)
        link.out_octets = -1
        self.assertEqual(link.out_octets, pow(2, 37) + 1)
        link.out_octets = pow(2, 63) + 1
        self.assertEqual(link.out_octets, pow(2, 37) + 1)
        link.out_octets = None
        self.assertEqual(link.out_octets, None)
        self.assertEqual(len(link.errctx.errors), 2)
        link.errctx = None

        link.errctx = network_element_update.ErrorContext()
        self.assertEqual(link.out_ucast_pkts, None)
        link.out_ucast_pkts = pow(2, 38) + 1
        self.assertEqual(link.out_ucast_pkts, pow(2, 38) + 1)
        link.out_ucast_pkts = -1
        self.assertEqual(link.out_ucast_pkts, pow(2, 38) + 1)
        link.out_ucast_pkts = pow(2, 63) + 1
        self.assertEqual(link.out_ucast_pkts, pow(2, 38) + 1)
        link.out_ucast_pkts = None
        self.assertEqual(link.out_octets, None)
        self.assertEqual(len(link.errctx.errors), 2)
        link.errctx = None

        link.errctx = network_element_update.ErrorContext()
        self.assertEqual(link.out_nucast_pkts, None)
        link.out_nucast_pkts = pow(2, 39) + 1
        self.assertEqual(link.out_nucast_pkts, pow(2, 39) + 1)
        link.out_nucast_pkts = -1
        self.assertEqual(link.out_nucast_pkts, pow(2, 39) + 1)
        link.out_nucast_pkts = pow(2, 63) + 1
        self.assertEqual(link.out_nucast_pkts, pow(2, 39) + 1)
        link.out_nucast_pkts = None
        self.assertEqual(link.out_octets, None)
        self.assertEqual(len(link.errctx.errors), 2)
        link.errctx = None

        link.errctx = network_element_update.ErrorContext()
        self.assertEqual(link.out_discards, None)
        link.out_discards = pow(2, 40) + 1
        self.assertEqual(link.out_discards, pow(2, 40) + 1)
        link.out_discards = -1
        self.assertEqual(link.out_discards, pow(2, 40) + 1)
        link.out_discards = pow(2, 63) + 1
        self.assertEqual(link.out_discards, pow(2, 40) + 1)
        link.out_discards = None
        self.assertEqual(link.out_discards, None)
        self.assertEqual(len(link.errctx.errors), 2)
        link.errctx = None

        link.errctx = network_element_update.ErrorContext()
        self.assertEqual(link.out_errors, None)
        link.out_errors = pow(2, 41) + 1
        self.assertEqual(link.out_errors, pow(2, 41) + 1)
        link.out_errors = -1
        self.assertEqual(link.out_errors, pow(2, 41) + 1)
        link.out_errors = pow(2, 63) + 1
        self.assertEqual(link.out_errors, pow(2, 41) + 1)
        link.out_errors = None
        self.assertEqual(link.out_discards, None)
        self.assertEqual(len(link.errctx.errors), 2)
        link.errctx = None

        link.errctx = network_element_update.ErrorContext()
        self.assertEqual(link.out_retransmits, None)
        link.out_retransmits = pow(2, 42) + 1
        self.assertEqual(link.out_retransmits, pow(2, 42) + 1)
        link.out_retransmits = -1
        self.assertEqual(link.out_retransmits, pow(2, 42) + 1)
        link.out_retransmits = pow(2, 63) + 1
        self.assertEqual(link.out_retransmits, pow(2, 42) + 1)
        link.out_retransmits = None
        self.assertEqual(link.out_discards, None)
        self.assertEqual(len(link.errctx.errors), 2)
        link.errctx = None

        self.assertEqual(list(link.bridged_mac_addresses), [])
        link.bridged_mac_addresses.append('1a:00:00:0a:0b:0c')
        self.assertEqual(len(link.bridged_mac_addresses), 1)
        self.assertEqual(link.bridged_mac_addresses[0], '1a:00:00:0a:0b:0c')
        self.assertEqual([x for x in link.bridged_mac_addresses], ['1a:00:00:0a:0b:0c'])
        del link.bridged_mac_addresses[0]
        self.assertEqual(len(link.bridged_mac_addresses), 0)

        poller_hash = sha256().digest()
        link.poller_hash = poller_hash
        self.assertEqual(poller_hash, link.poller_hash)

        # Radio
        radio = intf.radios.add()
        radio.id = 'radio1'
        self.assertEqual(radio.id, 'radio1')

        radio.errctx = network_element_update.ErrorContext()
        self.assertEqual(radio.frequency, None)
        radio.frequency = 5540
        self.assertEqual(radio.frequency, 5540)
        radio.frequency = -1
        self.assertEqual(radio.frequency, 5540)
        radio.frequency = pow(2, 31) + 1
        self.assertEqual(radio.frequency, 5540)
        radio.frequency = None
        self.assertEqual(radio.frequency, None)
        self.assertEqual(len(radio.errctx.errors), 2)
        radio.errctx = None

        radio.errctx = network_element_update.ErrorContext()
        self.assertEqual(radio.chan_width, None)
        radio.chan_width = 40
        self.assertEqual(radio.chan_width, 40)
        radio.chan_width = -1
        self.assertEqual(radio.chan_width, 40)
        radio.chan_width = pow(2, 31) + 1
        self.assertEqual(radio.chan_width, 40)
        radio.chan_width = None
        self.assertEqual(radio.chan_width, None)
        self.assertEqual(len(radio.errctx.errors), 2)
        radio.errctx = None

        radio.errctx = network_element_update.ErrorContext()
        self.assertEqual(radio.tx_power, None)
        radio.tx_power = 15
        self.assertEqual(radio.tx_power, 15)
        radio.tx_power = -3
        self.assertEqual(radio.tx_power, -3)
        radio.tx_power = pow(2, 31) + 1
        self.assertEqual(radio.tx_power, -3)
        radio.tx_power = None
        self.assertEqual(radio.tx_power, None)
        self.assertEqual(len(radio.errctx.errors), 1)
        radio.errctx = None

        radio.errctx = network_element_update.ErrorContext()
        self.assertEqual(radio.dl_percent, None)
        radio.dl_percent = 75
        self.assertEqual(radio.dl_percent, 75)
        radio.dl_percent = -1
        self.assertEqual(radio.dl_percent, 75)
        radio.dl_percent = pow(2, 31) + 1
        self.assertEqual(radio.dl_percent, 75)
        radio.dl_percent = None
        self.assertEqual(radio.dl_percent, None)
        self.assertEqual(len(radio.errctx.errors), 2)
        radio.errctx = None

        radio.framing = network_poller_pb2.FramingMode.FIXED
        self.assertEqual(radio.framing, network_poller_pb2.FramingMode.FIXED)

        radio.errctx = network_element_update.ErrorContext()
        self.assertEqual(radio.rx_airtime, None)
        radio.rx_airtime = 19.2
        self.assertEqual(round(radio.rx_airtime, 4), 19.2)
        radio.rx_airtime = -1
        self.assertEqual(round(radio.rx_airtime, 4), 19.2)
        radio.rx_airtime = 100.1
        self.assertEqual(round(radio.rx_airtime, 4), 100.1)
        radio.rx_airtime = None
        self.assertEqual(radio.rx_airtime, None)
        self.assertEqual(len(radio.errctx.errors), 1)
        radio.errctx = None

        radio.errctx = network_element_update.ErrorContext()
        self.assertEqual(radio.tx_airtime, None)
        radio.tx_airtime = 6.8
        self.assertEqual(round(radio.tx_airtime, 4), 6.8)
        radio.tx_airtime = -1
        self.assertEqual(round(radio.tx_airtime, 4), 6.8)
        radio.tx_airtime = 100.1
        self.assertEqual(round(radio.tx_airtime, 4), 100.1)
        radio.tx_airtime = None
        self.assertEqual(radio.tx_airtime, None)
        self.assertEqual(len(radio.errctx.errors), 1)
        radio.errctx = None

        self.assertEqual(radio.gps_sync, None)
        radio.gps_sync = True
        self.assertEqual(radio.gps_sync, True)
        radio.gps_sync = None
        self.assertEqual(radio.gps_sync, None)

        self.assertEqual(radio.chain_balance, None)
        radio.chain_balance = 0.56
        self.assertEqual(round(radio.chain_balance, 4), 0.56)
        radio.chain_balance = None
        self.assertEqual(radio.chain_balance, None)

        radio.errctx = network_element_update.ErrorContext()
        self.assertEqual(radio.rx_link_rate, None)
        radio.rx_link_rate = 7449000000
        self.assertEqual(radio.rx_link_rate, 7449000000)
        radio.rx_link_rate = -1
        self.assertEqual(radio.rx_link_rate, 7449000000)
        radio.rx_link_rate = pow(2, 63) + 1
        self.assertEqual(radio.rx_link_rate, 7449000000)
        radio.rx_link_rate = None
        self.assertEqual(radio.rx_link_rate, None)
        self.assertEqual(len(radio.errctx.errors), 2)
        radio.errctx = None

        radio.errctx = network_element_update.ErrorContext()
        self.assertEqual(radio.tx_link_rate, None)
        radio.tx_link_rate = 17449000000
        self.assertEqual(radio.tx_link_rate, 17449000000)
        radio.tx_link_rate = -1
        self.assertEqual(radio.tx_link_rate, 17449000000)
        radio.tx_link_rate = pow(2, 63) + 1
        self.assertEqual(radio.tx_link_rate, 17449000000)
        radio.tx_link_rate = None
        self.assertEqual(radio.tx_link_rate, None)
        self.assertEqual(len(radio.errctx.errors), 2)
        radio.errctx = None

        radio.errctx = network_element_update.ErrorContext()
        self.assertEqual(radio.frame_duration, None)
        radio.frame_duration = 5000
        self.assertEqual(radio.frame_duration, 5000)
        radio.frame_duration = -1
        self.assertEqual(radio.frame_duration, 5000)
        radio.frame_duration = pow(2, 63) + 1
        self.assertEqual(radio.frame_duration, 5000)
        radio.frame_duration = None
        self.assertEqual(radio.frame_duration, None)
        self.assertEqual(len(radio.errctx.errors), 2)
        radio.errctx = None

        radio.errctx = network_element_update.ErrorContext()
        self.assertEqual(radio.rx_multiplexing_gain, None)
        radio.rx_multiplexing_gain = 1.1
        self.assertEqual(round(radio.rx_multiplexing_gain, 4), 1.1)
        radio.rx_multiplexing_gain = None
        self.assertEqual(radio.rx_multiplexing_gain, None)

        radio.errctx = network_element_update.ErrorContext()
        self.assertEqual(radio.tx_multiplexing_gain, None)
        radio.tx_multiplexing_gain = 1.1
        self.assertEqual(round(radio.tx_multiplexing_gain, 4), 1.1)
        radio.tx_multiplexing_gain = None
        self.assertEqual(radio.tx_multiplexing_gain, None)

        radio.errctx = network_element_update.ErrorContext()
        self.assertEqual(radio.rx_average_group_size, None)
        radio.rx_average_group_size = 2.1
        self.assertEqual(round(radio.rx_average_group_size, 4), 2.1)
        radio.rx_average_group_size = None
        self.assertEqual(radio.rx_average_group_size, None)

        radio.errctx = network_element_update.ErrorContext()
        self.assertEqual(radio.tx_average_group_size, None)
        radio.tx_average_group_size = 2.1
        self.assertEqual(round(radio.tx_average_group_size, 4), 2.1)
        radio.tx_average_group_size = None
        self.assertEqual(radio.tx_average_group_size, None)

        radio.errctx = network_element_update.ErrorContext()
        self.assertEqual(radio.wifi_mode, None)
        radio.wifi_mode = network_poller_pb2.WifiStandard.WIFI_STANDARD_80211B
        self.assertEqual(radio.wifi_mode,
                         network_poller_pb2.WifiStandard.WIFI_STANDARD_80211B)
        radio.wifi_mode = network_poller_pb2.WifiStandard.WIFI_STANDARD_INVALID
        self.assertEqual(len(radio.errctx.errors), 1)
        self.assertEqual(radio.wifi_mode, None)
        radio.wifi_mode = network_poller_pb2.WifiStandard.WIFI_STANDARD_80211AY
        self.assertEqual(radio.wifi_mode,
                         network_poller_pb2.WifiStandard.WIFI_STANDARD_80211AY)
        radio.wifi_mode = None
        self.assertEqual(radio.wifi_mode, None)

        radio.errctx = network_element_update.ErrorContext()
        self.assertEqual(radio.max_cpe_radios, None)
        radio.max_cpe_radios = 10
        self.assertEqual(radio.max_cpe_radios, 10)
        radio.max_cpe_radios = -1
        self.assertEqual(radio.max_cpe_radios, 10)
        radio.max_cpe_radios = pow(2, 31)
        self.assertEqual(radio.max_cpe_radios, 10)
        radio.max_cpe_radios = None
        self.assertEqual(radio.max_cpe_radios, None)
        self.assertEqual(len(radio.errctx.errors), 2)
        radio.errctx = None

        radio.errctx = network_element_update.ErrorContext()
        self.assertEqual(radio.max_distance, None)
        radio.max_distance = 8000
        self.assertEqual(radio.max_distance, 8000)
        radio.max_distance = -1
        self.assertEqual(radio.max_distance, 8000)
        radio.max_distance = pow(2, 31)
        self.assertEqual(radio.max_distance, 8000)
        radio.max_distance = None
        self.assertEqual(radio.max_distance, None)
        self.assertEqual(len(radio.errctx.errors), 2)
        radio.errctx = None

        radio.errctx = network_element_update.ErrorContext()
        self.assertEqual(radio.rx_path_loss, None)
        radio.rx_path_loss = -20.59
        self.assertEqual(round(radio.rx_path_loss, 4), -20.59)
        radio.rx_path_loss = 190.59
        self.assertEqual(round(radio.rx_path_loss, 4), -20.59)
        radio.rx_path_loss = None
        self.assertEqual(radio.rx_path_loss, None)
        self.assertEqual(len(radio.errctx.errors), 1)
        radio.errctx = None

        radio.errctx = network_element_update.ErrorContext()
        self.assertEqual(radio.rx_max_interference_noise_ratio, None)
        radio.rx_max_interference_noise_ratio = -20.59
        self.assertEqual(round(radio.rx_max_interference_noise_ratio, 4), -20.59)
        radio.rx_max_interference_noise_ratio = 190.59
        self.assertEqual(round(radio.rx_max_interference_noise_ratio, 4), -20.59)
        radio.rx_max_interference_noise_ratio = None
        self.assertEqual(radio.rx_max_interference_noise_ratio, None)
        self.assertEqual(len(radio.errctx.errors), 1)
        radio.errctx = None

        radio.errctx = network_element_update.ErrorContext()
        self.assertEqual(radio.rx_max_sensitivity_loss, None)
        radio.rx_max_sensitivity_loss = -20.59
        self.assertEqual(round(radio.rx_max_sensitivity_loss, 4), -20.59)
        radio.rx_max_sensitivity_loss = 190.59
        self.assertEqual(round(radio.rx_max_sensitivity_loss, 4), -20.59)
        radio.rx_max_sensitivity_loss = None
        self.assertEqual(radio.rx_max_sensitivity_loss, None)
        self.assertEqual(len(radio.errctx.errors), 1)
        radio.errctx = None

        radio.errctx = network_element_update.ErrorContext()
        self.assertEqual(radio.azimuth, None)
        radio.azimuth = 0
        self.assertEqual(round(radio.azimuth, 4), 0)
        radio.azimuth = 180.5
        self.assertEqual(round(radio.azimuth, 4), 180.5)
        radio.max_distance = -1
        self.assertEqual(round(radio.azimuth, 4), 180.5)
        radio.azimuth = 360
        self.assertEqual(round(radio.azimuth, 4), 360)
        radio.azimuth = 361
        self.assertEqual(round(radio.azimuth, 4), 360)
        radio.azimuth = None
        self.assertEqual(radio.azimuth, None)
        self.assertEqual(len(radio.errctx.errors), 2)
        radio.errctx = None

        self.assertEqual(radio.admin_up, None)
        radio.admin_up = True
        self.assertEqual(radio.admin_up, True)
        radio.admin_up = None
        self.assertEqual(radio.admin_up, None)

        self.assertEqual(radio.oper_up, None)
        radio.oper_up = True
        self.assertEqual(radio.oper_up, True)
        radio.oper_up = None
        self.assertEqual(radio.oper_up, None)

        # RadioStream
        stream = radio.streams.add()
        stream.id = '1'
        self.assertEqual(stream.id, '1')

        self.assertEqual(stream.polarization, None)
        stream.polarization = 'HORIZONTAL'
        self.assertEqual(stream.polarization, 'HORIZONTAL')
        stream.polarization = None
        self.assertEqual(stream.polarization, None)

        self.assertEqual(stream.noise_floor, None)
        stream.noise_floor = -79
        self.assertEqual(round(stream.noise_floor, 4), -79)
        stream.noise_floor = None
        self.assertEqual(stream.noise_floor, None)

        # WirelessLink
        wlink = stream.links.add()
        wlink.mac_address = '0a:00:00:0d:0e:0f'
        self.assertEqual(wlink.mac_address, '0a:00:00:0d:0e:0f')

        wlink.errctx = network_element_update.ErrorContext()
        self.assertEqual(wlink.distance, None)
        wlink.distance = 600
        self.assertEqual(wlink.distance, 600)
        wlink.distance = -1
        self.assertEqual(wlink.distance, 600)
        wlink.distance = pow(2, 31) + 1
        self.assertEqual(wlink.distance, 600)
        wlink.distance = None
        self.assertEqual(wlink.distance, None)
        self.assertEqual(len(wlink.errctx.errors), 2)
        wlink.errctx = None

        wlink.errctx = network_element_update.ErrorContext()
        self.assertEqual(wlink.connected_time, None)
        wlink.connected_time = pow(2, 31) + 100
        self.assertEqual(wlink.connected_time, pow(2, 31) + 100)
        wlink.connected_time = -1
        self.assertEqual(wlink.connected_time, pow(2, 31) + 100)
        wlink.connected_time = pow(2, 63) + 1
        self.assertEqual(wlink.connected_time, pow(2, 31) + 100)
        wlink.connected_time = None
        self.assertEqual(wlink.connected_time, None)
        self.assertEqual(len(wlink.errctx.errors), 2)
        wlink.errctx = None

        self.assertEqual(wlink.noise_floor, None)
        wlink.noise_floor = -89
        self.assertEqual(round(wlink.noise_floor, 4), -89)
        wlink.noise_floor = None
        self.assertEqual(wlink.noise_floor, None)

        self.assertEqual(wlink.rssi, None)
        wlink.rssi = -51
        self.assertEqual(round(wlink.rssi, 4), -51)
        wlink.rssi = None
        self.assertEqual(wlink.rssi, None)

        self.assertEqual(wlink.snr, None)
        wlink.snr = 44
        self.assertEqual(round(wlink.snr, 4), 44)
        wlink.snr = None
        self.assertEqual(wlink.snr, None)

        wlink.errctx = network_element_update.ErrorContext()
        self.assertEqual(wlink.rx_link_rate, None)
        wlink.rx_link_rate = 17449000000
        self.assertEqual(wlink.rx_link_rate, 17449000000)
        wlink.rx_link_rate = -1
        self.assertEqual(wlink.rx_link_rate, 17449000000)
        wlink.rx_link_rate = pow(2, 63) + 1
        self.assertEqual(wlink.rx_link_rate, 17449000000)
        wlink.rx_link_rate = None
        self.assertEqual(wlink.rx_link_rate, None)
        self.assertEqual(len(wlink.errctx.errors), 2)
        wlink.errctx = None

        wlink.errctx = network_element_update.ErrorContext()
        self.assertEqual(wlink.tx_link_rate, None)
        wlink.tx_link_rate = 6410000000
        self.assertEqual(wlink.tx_link_rate, 6410000000)
        wlink.tx_link_rate = -1
        self.assertEqual(wlink.tx_link_rate, 6410000000)
        wlink.tx_link_rate = pow(2, 63) + 1
        self.assertEqual(wlink.tx_link_rate, 6410000000)
        wlink.tx_link_rate = None
        self.assertEqual(wlink.tx_link_rate, None)
        self.assertEqual(len(wlink.errctx.errors), 2)
        wlink.errctx = None

        wlink.errctx = network_element_update.ErrorContext()
        self.assertEqual(wlink.rx_mcs, None)
        wlink.rx_mcs = 4
        self.assertEqual(wlink.rx_mcs, 4)
        wlink.rx_mcs = -1
        self.assertEqual(wlink.rx_mcs, 4)
        wlink.rx_mcs = pow(2, 31) + 1
        self.assertEqual(wlink.rx_mcs, 4)
        wlink.rx_mcs = None
        self.assertEqual(wlink.rx_mcs, None)
        self.assertEqual(len(wlink.errctx.errors), 2)
        wlink.errctx = None

        wlink.errctx = network_element_update.ErrorContext()
        self.assertEqual(wlink.tx_mcs, None)
        wlink.tx_mcs = 4
        self.assertEqual(wlink.tx_mcs, 4)
        wlink.tx_mcs = -1
        self.assertEqual(wlink.tx_mcs, 4)
        wlink.tx_mcs = pow(2, 31) + 1
        self.assertEqual(wlink.tx_mcs, 4)
        wlink.tx_mcs = None
        self.assertEqual(wlink.tx_mcs, None)
        self.assertEqual(len(wlink.errctx.errors), 2)
        wlink.errctx = None

        self.assertEqual(wlink.rx_modulation_rate, None)
        wlink.rx_modulation_rate = 10.8
        self.assertEqual(round(wlink.rx_modulation_rate, 4), 10.8)
        wlink.rx_modulation_rate = None
        self.assertEqual(wlink.rx_modulation_rate, None)

        self.assertEqual(wlink.tx_modulation_rate, None)
        wlink.tx_modulation_rate = 7.7
        self.assertEqual(round(wlink.tx_modulation_rate, 4), 7.7)
        wlink.tx_modulation_rate = None
        self.assertEqual(wlink.tx_modulation_rate, None)

        wlink.errctx = network_element_update.ErrorContext()
        self.assertEqual(wlink.rx_airtime, None)
        wlink.rx_airtime = 60.4
        self.assertEqual(round(wlink.rx_airtime, 4), 60.4)
        wlink.rx_airtime = -1
        self.assertEqual(round(wlink.rx_airtime, 4), 60.4)
        wlink.rx_airtime = 100.1
        self.assertEqual(round(wlink.rx_airtime, 4), 100.1)
        wlink.rx_airtime = None
        self.assertEqual(wlink.rx_airtime, None)
        self.assertEqual(len(wlink.errctx.errors), 1)
        wlink.errctx = None

        wlink.errctx = network_element_update.ErrorContext()
        self.assertEqual(wlink.tx_airtime, None)
        wlink.tx_airtime = 4.5
        self.assertEqual(round(wlink.tx_airtime, 4), 4.5)
        wlink.tx_airtime = -1
        self.assertEqual(round(wlink.tx_airtime, 4), 4.5)
        wlink.tx_airtime = 100.1
        self.assertEqual(round(wlink.tx_airtime, 4), 100.1)
        wlink.tx_airtime = None
        self.assertEqual(wlink.tx_airtime, None)
        self.assertEqual(len(wlink.errctx.errors), 1)
        wlink.errctx = None

        wlink.errctx = network_element_update.ErrorContext()
        self.assertEqual(wlink.amc, None)
        wlink.amc = 4.5
        self.assertEqual(round(wlink.amc, 4), 4.5)
        wlink.amc = -1
        self.assertEqual(round(wlink.amc, 4), 4.5)
        wlink.amc = 100.1
        self.assertEqual(round(wlink.amc, 4), 4.5)
        wlink.amc = None
        self.assertEqual(wlink.amc, None)
        self.assertEqual(len(wlink.errctx.errors), 2)
        wlink.errctx = None

        wlink.errctx = network_element_update.ErrorContext()
        self.assertEqual(wlink.amq, None)
        wlink.amq = 4.5
        self.assertEqual(round(wlink.amq, 4), 4.5)
        wlink.amq = -1
        self.assertEqual(round(wlink.amq, 4), 4.5)
        wlink.amq = 100.1
        self.assertEqual(round(wlink.amq, 4), 4.5)
        wlink.amq = None
        self.assertEqual(wlink.amq, None)
        self.assertEqual(len(wlink.errctx.errors), 2)
        wlink.errctx = None

        wlink.errctx = network_element_update.ErrorContext()
        self.assertEqual(wlink.ccq, None)
        wlink.ccq = 4.5
        self.assertEqual(round(wlink.ccq, 4), 4.5)
        wlink.ccq = -1
        self.assertEqual(round(wlink.ccq, 4), 4.5)
        wlink.ccq = 100.1
        self.assertEqual(round(wlink.ccq, 4), 4.5)
        wlink.ccq = None
        self.assertEqual(wlink.ccq, None)
        self.assertEqual(len(wlink.errctx.errors), 2)
        wlink.errctx = None

        poller_hash = sha256().digest()
        wlink.poller_hash = poller_hash
        self.assertEqual(poller_hash, wlink.poller_hash)

        # RfAggregationGroup
        rf_aggr_gr = intf.rf_aggregation_groups.add()
        rf_aggr_gr.name = 'RadioGr1'
        self.assertEqual(rf_aggr_gr.name, 'RadioGr1')

        rf_aggr_gr.errctx = network_element_update.ErrorContext()
        self.assertEqual(rf_aggr_gr.airtime, None)
        rf_aggr_gr.airtime = 19.2
        self.assertEqual(round(rf_aggr_gr.airtime, 4), 19.2)
        rf_aggr_gr.airtime = -1
        self.assertEqual(round(rf_aggr_gr.airtime, 4), 19.2)
        rf_aggr_gr.airtime = 100.1
        self.assertEqual(round(rf_aggr_gr.airtime, 4), 100.1)
        rf_aggr_gr.airtime = None
        self.assertEqual(rf_aggr_gr.airtime, None)
        self.assertEqual(len(rf_aggr_gr.errctx.errors), 1)
        rf_aggr_gr.errctx = None

        rf_aggr_gr.errctx = network_element_update.ErrorContext()
        self.assertEqual(rf_aggr_gr.tx_packet_error_rate, None)
        rf_aggr_gr.tx_packet_error_rate = 19.2
        self.assertEqual(round(rf_aggr_gr.tx_packet_error_rate, 4), 19.2)
        rf_aggr_gr.tx_packet_error_rate = -1
        self.assertEqual(round(rf_aggr_gr.tx_packet_error_rate, 4), 19.2)
        rf_aggr_gr.tx_packet_error_rate = 100.1
        self.assertEqual(round(rf_aggr_gr.tx_packet_error_rate, 4), 100.1)
        rf_aggr_gr.tx_packet_error_rate = None
        self.assertEqual(rf_aggr_gr.tx_packet_error_rate, None)
        self.assertEqual(len(rf_aggr_gr.errctx.errors), 1)
        rf_aggr_gr.errctx = None

        rf_aggr_gr.errctx = network_element_update.ErrorContext()
        self.assertEqual(rf_aggr_gr.rx_packet_error_rate, None)
        rf_aggr_gr.rx_packet_error_rate = 19.2
        self.assertEqual(round(rf_aggr_gr.rx_packet_error_rate, 4), 19.2)
        rf_aggr_gr.rx_packet_error_rate = -1
        self.assertEqual(round(rf_aggr_gr.rx_packet_error_rate, 4), 19.2)
        rf_aggr_gr.rx_packet_error_rate = 100.1
        self.assertEqual(round(rf_aggr_gr.rx_packet_error_rate, 4), 100.1)
        rf_aggr_gr.rx_packet_error_rate = None
        self.assertEqual(rf_aggr_gr.rx_packet_error_rate, None)
        self.assertEqual(len(rf_aggr_gr.errctx.errors), 1)
        rf_aggr_gr.errctx = None

        rf_aggr_gr.errctx = network_element_update.ErrorContext()
        self.assertEqual(rf_aggr_gr.tx_interference_signal_ratio, None)
        rf_aggr_gr.tx_interference_signal_ratio = -20.59
        self.assertEqual(round(rf_aggr_gr.tx_interference_signal_ratio, 4), -20.59)
        rf_aggr_gr.tx_interference_signal_ratio = 190.59
        self.assertEqual(round(rf_aggr_gr.tx_interference_signal_ratio, 4), 190.59)
        rf_aggr_gr.tx_interference_signal_ratio = None
        self.assertEqual(rf_aggr_gr.tx_interference_signal_ratio, None)
        self.assertEqual(len(rf_aggr_gr.errctx.errors), 0)
        rf_aggr_gr.errctx = None

        rf_aggr_gr.errctx = network_element_update.ErrorContext()
        self.assertEqual(rf_aggr_gr.rx_interference_signal_ratio, None)
        rf_aggr_gr.rx_interference_signal_ratio = -20.59
        self.assertEqual(round(rf_aggr_gr.rx_interference_signal_ratio, 4), -20.59)
        rf_aggr_gr.rx_interference_signal_ratio = 190.59
        self.assertEqual(round(rf_aggr_gr.rx_interference_signal_ratio, 4), 190.59)
        rf_aggr_gr.rx_interference_signal_ratio = None
        self.assertEqual(rf_aggr_gr.rx_interference_signal_ratio, None)
        self.assertEqual(len(rf_aggr_gr.errctx.errors), 0)
        rf_aggr_gr.errctx = None

        # Sector
        sector = intf.sectors.add()

        sector.ssid = 'MySSID'
        self.assertEqual(sector.ssid, 'MySSID')

        sector.mode = network_poller_pb2.SectorMode.AP
        self.assertEqual(sector.mode, network_poller_pb2.SectorMode.AP)

        # Module
        module = ne.modules.add()
        module.id = 'module1'
        self.assertEqual(module.id, 'module1')

        poller_hash = sha256().digest()
        module.poller_hash = poller_hash
        self.assertEqual(poller_hash, module.poller_hash)

        self.assertEqual(module.name, None)
        module.name = 'module-name'
        self.assertEqual(module.name, 'module-name')
        module.name = None
        self.assertEqual(module.name, None)

        self.assertEqual(module.manufacturer, None)
        module.manufacturer = 'module-mfg'
        self.assertEqual(module.manufacturer, 'module-mfg')
        module.manufacturer = None
        self.assertEqual(module.manufacturer, None)

        self.assertEqual(module.model, None)
        module.model = 'module-mod'
        self.assertEqual(module.model, 'module-mod')
        module.model = None
        self.assertEqual(module.model, None)

        self.assertEqual(module.serial_number, None)
        module.serial_number = 'module-ser'
        self.assertEqual(module.serial_number, 'module-ser')
        module.serial_number = None
        self.assertEqual(module.serial_number, None)

        self.assertEqual(module.sw_version, None)
        module.sw_version = '1.2.3'
        self.assertEqual(module.sw_version, '1.2.3')
        module.sw_version = None
        self.assertEqual(module.sw_version, None)

        module.errctx = network_element_update.ErrorContext()
        self.assertEqual(module.uptime, None)
        module.uptime = 12345
        self.assertEqual(module.uptime, 12345)
        module.uptime = -1
        self.assertEqual(module.uptime, 12345)
        module.uptime = pow(2, 63) + 1
        self.assertEqual(module.uptime, 12345)
        module.uptime = None
        self.assertEqual(len(module.errctx.errors), 2)
        module.errctx = None

        module.errctx = network_element_update.ErrorContext()
        self.assertEqual(module.cpu, None)
        module.cpu = 5.5
        self.assertEqual(round(module.cpu, 4), 5.5)
        module.cpu = -1
        self.assertEqual(round(module.cpu, 4), 5.5)
        module.cpu = 100.1
        self.assertEqual(round(module.cpu, 4), 5.5)
        module.cpu = None
        self.assertEqual(module.cpu, None)
        self.assertEqual(len(module.errctx.errors), 2)
        module.errctx = None

        module.errctx = network_element_update.ErrorContext()
        self.assertEqual(module.mem, None)
        module.mem = 5.6
        self.assertEqual(round(module.mem, 4), 5.6)
        module.mem = -1
        self.assertEqual(round(module.mem, 4), 5.6)
        module.mem = 100.1
        self.assertEqual(round(module.mem, 4), 5.6)
        module.mem = None
        self.assertEqual(module.mem, None)
        self.assertEqual(len(module.errctx.errors), 2)
        module.errctx = None

        self.assertEqual(module.temperature, None)
        module.temperature = 31.02
        self.assertEqual(round(module.temperature, 4), 31.02)
        module.temperature = -10
        self.assertEqual(round(module.temperature, 4), -10)
        module.temperature = None
        self.assertEqual(module.temperature, None)

        intf2 = module.interfaces.add()

        # Pon
        pon = intf2.pons.add()
        pon.id = 'pon1'
        self.assertEqual(pon.id, 'pon1')

        poller_hash = sha256().digest()
        pon.poller_hash = poller_hash
        self.assertEqual(poller_hash, pon.poller_hash)

        pon.pon_technology = network_poller_pb2.PonTechnology.APON
        self.assertEqual(pon.pon_technology, network_poller_pb2.PonTechnology.APON)
        pon.pon_technology = None
        self.assertEqual(pon.pon_technology, None)

        pon.errctx = network_element_update.ErrorContext()
        self.assertEqual(pon.split_ratio, None)
        pon.split_ratio = 5
        self.assertEqual(pon.split_ratio, 5)
        pon.split_ratio = -1
        self.assertEqual(pon.split_ratio, 5)
        pon.split_ratio = pow(2, 31) + 1
        self.assertEqual(pon.split_ratio, 5)
        pon.split_ratio = None
        self.assertEqual(pon.split_ratio, None)
        self.assertEqual(len(pon.errctx.errors), 2)
        pon.errctx = None

        pon.errctx = network_element_update.ErrorContext()
        self.assertEqual(pon.max_distance, None)
        pon.max_distance = 600
        self.assertEqual(pon.max_distance, 600)
        pon.max_distance = -1
        self.assertEqual(pon.max_distance, 600)
        pon.max_distance = pow(2, 31) + 1
        self.assertEqual(pon.max_distance, 600)
        pon.max_distance = None
        self.assertEqual(pon.max_distance, None)
        self.assertEqual(len(pon.errctx.errors), 2)
        pon.errctx = None

        self.assertEqual(pon.minimum_loss, None)
        pon.minimum_loss = 5.02
        self.assertEqual(round(pon.minimum_loss, 4), 5.02)
        pon.minimum_loss = None
        self.assertEqual(pon.minimum_loss, None)

        self.assertEqual(pon.maximum_loss, None)
        pon.maximum_loss = 6.02
        self.assertEqual(round(pon.maximum_loss, 4), 6.02)
        pon.maximum_loss = None
        self.assertEqual(pon.maximum_loss, None)

        pon.errctx = network_element_update.ErrorContext()
        self.assertEqual(pon.rx_link_rate, None)
        pon.rx_link_rate = 7449000000
        self.assertEqual(pon.rx_link_rate, 7449000000)
        pon.rx_link_rate = -1
        self.assertEqual(pon.rx_link_rate, 7449000000)
        pon.rx_link_rate = pow(2, 63) + 1
        self.assertEqual(pon.rx_link_rate, 7449000000)
        pon.rx_link_rate = None
        self.assertEqual(pon.rx_link_rate, None)
        self.assertEqual(len(pon.errctx.errors), 2)
        pon.errctx = None

        pon.errctx = network_element_update.ErrorContext()
        self.assertEqual(pon.tx_link_rate, None)
        pon.tx_link_rate = 17449000000
        self.assertEqual(pon.tx_link_rate, 17449000000)
        pon.tx_link_rate = -1
        self.assertEqual(pon.tx_link_rate, 17449000000)
        pon.tx_link_rate = pow(2, 63) + 1
        self.assertEqual(pon.tx_link_rate, 17449000000)
        pon.tx_link_rate = None
        self.assertEqual(pon.tx_link_rate, None)
        self.assertEqual(len(pon.errctx.errors), 2)
        pon.errctx = None

        self.assertEqual(pon.name, None)
        pon.name = 'pon-name'
        self.assertEqual(pon.name, 'pon-name')
        pon.name = None
        self.assertEqual(pon.name, None)

        self.assertEqual(pon.description, None)
        pon.description = 'pon-description'
        self.assertEqual(pon.description, 'pon-description')
        pon.description = None
        self.assertEqual(pon.description, None)

        # PonLink
        ponlink = pon.links.add()
        poller_hash = sha256().digest()
        ponlink.poller_hash = poller_hash
        self.assertEqual(poller_hash, ponlink.poller_hash)

        ponlink.errctx = network_element_update.ErrorContext()
        self.assertEqual(ponlink.rx_power, None)
        ponlink.rx_power = -20.59
        self.assertEqual(round(ponlink.rx_power, 4), -20.59)
        ponlink.rx_power = 190.59
        self.assertEqual(round(ponlink.rx_power, 4), -20.59)
        ponlink.rx_power = None
        self.assertEqual(ponlink.rx_power, None)
        self.assertEqual(len(ponlink.errctx.errors), 1)
        ponlink.errctx = None

        ponlink.errctx = network_element_update.ErrorContext()
        self.assertEqual(ponlink.tx_power, None)
        ponlink.tx_power = -20.59
        self.assertEqual(round(ponlink.tx_power, 4), -20.59)
        ponlink.tx_power = 190.59
        self.assertEqual(round(ponlink.tx_power, 4), -20.59)
        ponlink.tx_power = None
        self.assertEqual(ponlink.tx_power, None)
        self.assertEqual(len(ponlink.errctx.errors), 1)
        ponlink.errctx = None

        ponlink.errctx = network_element_update.ErrorContext()
        self.assertEqual(ponlink.fiber_length, None)
        ponlink.fiber_length = 200
        self.assertEqual(ponlink.fiber_length, 200)
        ponlink.fiber_length = -1
        self.assertEqual(ponlink.fiber_length, 200)
        ponlink.fiber_length = pow(2, 31) + 1
        self.assertEqual(ponlink.fiber_length, 200)
        ponlink.fiber_length = None
        self.assertEqual(ponlink.fiber_length, None)
        self.assertEqual(len(ponlink.errctx.errors), 2)
        ponlink.errctx = None

        ponlink.errctx = network_element_update.ErrorContext()
        self.assertEqual(ponlink.connected_time, None)
        ponlink.connected_time = 123456
        self.assertEqual(ponlink.connected_time, 123456)
        ponlink.connected_time = -1
        self.assertEqual(ponlink.connected_time, 123456)
        ponlink.connected_time = pow(2, 63) + 1
        self.assertEqual(ponlink.connected_time, 123456)
        ponlink.connected_time = None
        self.assertEqual(ponlink.connected_time, None)
        self.assertEqual(len(ponlink.errctx.errors), 2)
        ponlink.errctx = None

        ponlink.errctx = network_element_update.ErrorContext()
        self.assertEqual(ponlink.rx_link_rate, None)
        ponlink.rx_link_rate = 7449000000
        self.assertEqual(ponlink.rx_link_rate, 7449000000)
        ponlink.rx_link_rate = -1
        self.assertEqual(ponlink.rx_link_rate, 7449000000)
        ponlink.rx_link_rate = pow(2, 63) + 1
        self.assertEqual(ponlink.rx_link_rate, 7449000000)
        ponlink.rx_link_rate = None
        self.assertEqual(ponlink.rx_link_rate, None)
        self.assertEqual(len(ponlink.errctx.errors), 2)
        ponlink.errctx = None

        ponlink.errctx = network_element_update.ErrorContext()
        self.assertEqual(ponlink.tx_link_rate, None)
        ponlink.tx_link_rate = 17449000000
        self.assertEqual(ponlink.tx_link_rate, 17449000000)
        ponlink.tx_link_rate = -1
        self.assertEqual(ponlink.tx_link_rate, 17449000000)
        ponlink.tx_link_rate = pow(2, 63) + 1
        self.assertEqual(ponlink.tx_link_rate, 17449000000)
        ponlink.tx_link_rate = None
        self.assertEqual(ponlink.tx_link_rate, None)
        self.assertEqual(len(ponlink.errctx.errors), 2)
        ponlink.errctx = None

    def test_add_bridged_mac(self):
        """PPA-1321 test MAC filtering when adding bridged macs via a helper method."""
        neu = network_element_update.NetworkElementUpdate()
        intf = neu.data.interfaces.add()
        link = intf.links.add()

        intf.add_bridged_mac('00:01:02:03:04:05')
        intf.add_bridged_mac('33:33:ff:00:00:00')  # should be filtered
        intf.add_bridged_mac('00:00:00:00:00:00')  # should be filtered
        intf.add_bridged_mac('00:01:02:03:04:06')
        link.add_bridged_mac('00:01:02:03:04:05')
        link.add_bridged_mac('33:33:ff:00:00:00')  # should be filtered
        link.add_bridged_mac('00:00:00:00:00:00')  # should be filtered
        link.add_bridged_mac('00:01:02:03:04:06')

        self.assertEqual(len(intf.bridged_mac_addresses), 2)
        self.assertEqual(intf.bridged_mac_addresses[0], '00:01:02:03:04:05')
        self.assertEqual(intf.bridged_mac_addresses[1], '00:01:02:03:04:06')

        self.assertEqual(len(link.bridged_mac_addresses), 2)
        self.assertEqual(link.bridged_mac_addresses[0], '00:01:02:03:04:05')
        self.assertEqual(link.bridged_mac_addresses[1], '00:01:02:03:04:06')
