
Currently overall sync-state (/sync/sync-status/sync-state) represents degraded (HOLDOVER/FREERUN) when any state is degraded: os-clock-sync- state, ptp-status/lock-state, gnss-status/gnss-sync-status. This commit changes overall sync-state to represent whether the os-clock is synced or not to the timing source. Overall sync-state should only be degraded if the timing sources involved in providing the end-to-end timing is degraded or lost (i.e. it should represent the overall timing chain status). ptp4l instances that perform timing distribution only and are not part of the host timing chain must not impact the overall sync-state. os-clock-state should only represent the status of the OS clock sync state to the primary clock source in an HA configuration. Unit tests has been added and unit test's python interpreter has been changed to python3.9 to inline with base-image's python version (3.9.2). TEST PLAN: PASS: T-GM deployment with two ptp4l instances trigger different events (stop/start ptp4l/phc2sys/ts2phc instances, change clockClass, skew clocks, disable GNSS) overall sync-state is not affected by ptp-inst1 and ptp-inst2 states. PASS: T-BC deployment with two ptp4l instances trigger different events (stop/start ptp4l/phc2sys instances, change clockClass, skew clocks) overall sync-state is not affected by secondary ptp instance state. PASS: Hybrid (T-GM/T-BC) HA deployement: HA with GNSS and PTP source trigger different events overall sync-state is result of chained relation to chosen primary source Story: 2011370 Task: 51774 Change-Id: Ibfb7fa0f9f8ad09584a5f28b60b0e4649976932c Signed-off-by: Tara Nath Subedi <tara.subedi@windriver.com>
518 lines
18 KiB
Python
518 lines
18 KiB
Python
#
|
|
# Copyright (c) 2025 Wind River Systems, Inc.
|
|
#
|
|
# SPDX-License-Identifier: Apache-2.0
|
|
#
|
|
import mock
|
|
import unittest
|
|
import json
|
|
import time
|
|
|
|
from dataclasses import dataclass
|
|
from trackingfunctionsdk.common.helpers import constants
|
|
from trackingfunctionsdk.model.dto.osclockstate import OsClockState
|
|
from trackingfunctionsdk.model.dto.overallclockstate import OverallClockState
|
|
from trackingfunctionsdk.model.dto.ptpstate import PtpState
|
|
from trackingfunctionsdk.model.dto.gnssstate import GnssState
|
|
from trackingfunctionsdk.services.daemon import PtpWatcherDefault
|
|
|
|
context = {
|
|
"THIS_NAMESPACE": "notification",
|
|
"THIS_NODE_NAME": "controller-0",
|
|
"THIS_POD_IP": "172.16.192.71",
|
|
"REGISTRATION_TRANSPORT_ENDPOINT": "rabbit://admin:admin@registration.notification.svc.cluster.local:5672",
|
|
"NOTIFICATION_TRANSPORT_ENDPOINT": "rabbit://admin:admin@172.16.192.71:5672",
|
|
"GNSS_CONFIGS": [
|
|
"/ptp/linuxptp/ptpinstance/ts2phc-ts1.conf",
|
|
"/ptp/linuxptp/ptpinstance/ts2phc-ts2.conf",
|
|
],
|
|
"PHC2SYS_CONFIG": "/ptp/linuxptp/ptpinstance/phc2sys-phc-inst1.conf",
|
|
"PHC2SYS_SERVICE_NAME": "phc-inst1",
|
|
"PTP4L_CONFIGS": [
|
|
"/ptp/linuxptp/ptpinstance/ptp4l-ptp-inst2.conf",
|
|
"/ptp/linuxptp/ptpinstance/ptp4l-ptp-inst1.conf",
|
|
],
|
|
"GNSS_INSTANCES": ["ts1", "ts2"],
|
|
"PTP4L_INSTANCES": ["ptp-inst2", "ptp-inst1"],
|
|
"ptptracker_context": {"device_simulated": "false", "holdover_seconds": "15"},
|
|
"gnsstracker_context": {"holdover_seconds": 30},
|
|
"osclocktracker_context": {"holdover_seconds": "15"},
|
|
"overalltracker_context": {"holdover_seconds": "15"},
|
|
}
|
|
|
|
|
|
@dataclass
|
|
class OsClockData:
|
|
sync_state: str = OsClockState.Freerun
|
|
sync_source: str = "ptp0"
|
|
|
|
|
|
@dataclass
|
|
class PTP4lData:
|
|
ptp_devices: list[str]
|
|
sync_state: str = PtpState.Freerun
|
|
sync_source: str = constants.ClockSourceType.TypePTP
|
|
|
|
|
|
@dataclass
|
|
class ts2phcData:
|
|
ptp_devices: list[str]
|
|
sync_state: str = GnssState.Failure_Nofix
|
|
|
|
|
|
@dataclass
|
|
class TestData:
|
|
osclock: OsClockData
|
|
ptp4l: list[PTP4lData]
|
|
ts2phc: list[ts2phcData]
|
|
|
|
|
|
class DaemonTests(unittest.TestCase):
|
|
|
|
@mock.patch("trackingfunctionsdk.services.daemon.PtpMonitor")
|
|
@mock.patch("trackingfunctionsdk.services.daemon.OsClockMonitor")
|
|
@mock.patch("trackingfunctionsdk.services.daemon.GnssMonitor")
|
|
def _setup(self, gnssmonitor_mock, osclockmonitor_mock, ptpmonitor_mock):
|
|
event = None
|
|
|
|
sqlalchemy_conf = {
|
|
"url": "sqlite:///apiserver.db",
|
|
"echo": False,
|
|
"echo_pool": False,
|
|
"pool_recycle": 3600,
|
|
"encoding": "utf-8",
|
|
}
|
|
sqlalchemy_conf_json = json.dumps(sqlalchemy_conf)
|
|
daemon_context_json = json.dumps(context)
|
|
|
|
# distint mock class instances, to have distinct mock method on instance basis
|
|
gnssmonitor_mock.side_effect = [
|
|
mock.Mock(name=item) for item in context["GNSS_CONFIGS"]
|
|
]
|
|
ptpmonitor_mock.side_effect = [
|
|
mock.Mock(name=item) for item in context["PTP4L_CONFIGS"]
|
|
]
|
|
|
|
self.worker = PtpWatcherDefault(
|
|
event, sqlalchemy_conf_json, daemon_context_json
|
|
)
|
|
|
|
self.osclockmonitor_mock_instance = self.worker.os_clock_monitor
|
|
self.ptpmonitor_mock_instances = self.worker.ptp_monitor_list
|
|
self.gnssmonitor_mock_instances = self.worker.observer_list
|
|
|
|
self.assertEqual(
|
|
len(self.gnssmonitor_mock_instances), len(context["GNSS_CONFIGS"])
|
|
)
|
|
self.assertEqual(
|
|
len(self.ptpmonitor_mock_instances), len(context["PTP4L_CONFIGS"])
|
|
)
|
|
|
|
def _test__get_overall_sync_state(self, testdata, expected):
|
|
holdover_time = float(context["overalltracker_context"]["holdover_seconds"])
|
|
freq = 2
|
|
sync_state = OverallClockState.Freerun
|
|
last_event_time = time.time()
|
|
|
|
self.osclockmonitor_mock_instance.get_source_ptp_device.return_value = (
|
|
testdata.osclock.sync_source
|
|
)
|
|
self.osclockmonitor_mock_instance.get_os_clock_state.return_value = (
|
|
testdata.osclock.sync_state
|
|
)
|
|
# test mocking as expected or not.
|
|
self.assertEqual(
|
|
self.worker.os_clock_monitor.get_source_ptp_device(),
|
|
testdata.osclock.sync_source,
|
|
)
|
|
self.assertEqual(
|
|
self.worker.os_clock_monitor.get_os_clock_state(),
|
|
testdata.osclock.sync_state,
|
|
)
|
|
|
|
for i, gnssmonitor_mock_instance in enumerate(self.gnssmonitor_mock_instances):
|
|
gnssmonitor_mock_instance.get_ptp_devices.return_value = testdata.ts2phc[
|
|
i
|
|
].ptp_devices
|
|
gnssmonitor_mock_instance._state = testdata.ts2phc[i].sync_state
|
|
# test mocking as expected or not.
|
|
self.assertEqual(
|
|
self.gnssmonitor_mock_instances[0].get_ptp_devices(),
|
|
testdata.ts2phc[0].ptp_devices,
|
|
)
|
|
self.assertEqual(
|
|
self.gnssmonitor_mock_instances[0]._state, testdata.ts2phc[0].sync_state
|
|
)
|
|
self.assertEqual(
|
|
self.gnssmonitor_mock_instances[1].get_ptp_devices(),
|
|
testdata.ts2phc[1].ptp_devices,
|
|
)
|
|
self.assertEqual(
|
|
self.gnssmonitor_mock_instances[1]._state, testdata.ts2phc[1].sync_state
|
|
)
|
|
|
|
for i, ptpmonitor_mock_instance in enumerate(self.ptpmonitor_mock_instances):
|
|
ptpmonitor_mock_instance.get_ptp_devices.return_value = testdata.ptp4l[
|
|
i
|
|
].ptp_devices
|
|
ptpmonitor_mock_instance.get_ptp_sync_state.return_value = (
|
|
None,
|
|
testdata.ptp4l[i].sync_state,
|
|
None,
|
|
)
|
|
ptpmonitor_mock_instance.get_ptp_sync_source.return_value = testdata.ptp4l[
|
|
i
|
|
].sync_source
|
|
# test mocking as expected or not.
|
|
self.assertEqual(
|
|
self.ptpmonitor_mock_instances[0].get_ptp_devices(),
|
|
testdata.ptp4l[0].ptp_devices,
|
|
)
|
|
self.assertEqual(
|
|
self.ptpmonitor_mock_instances[0].get_ptp_sync_state(),
|
|
(None, testdata.ptp4l[0].sync_state, None),
|
|
)
|
|
self.assertEqual(
|
|
self.ptpmonitor_mock_instances[0].get_ptp_sync_source(),
|
|
testdata.ptp4l[0].sync_source,
|
|
)
|
|
self.assertEqual(
|
|
self.ptpmonitor_mock_instances[1].get_ptp_devices(),
|
|
testdata.ptp4l[1].ptp_devices,
|
|
)
|
|
self.assertEqual(
|
|
self.ptpmonitor_mock_instances[1].get_ptp_sync_state(),
|
|
(None, testdata.ptp4l[1].sync_state, None),
|
|
)
|
|
self.assertEqual(
|
|
self.ptpmonitor_mock_instances[1].get_ptp_sync_source(),
|
|
testdata.ptp4l[1].sync_source,
|
|
)
|
|
|
|
new_event, sync_state, new_event_time = (
|
|
self.worker._PtpWatcherDefault__get_overall_sync_state(
|
|
holdover_time, freq, sync_state, last_event_time
|
|
)
|
|
)
|
|
# overall sync state assertion
|
|
self.assertEqual(sync_state, expected)
|
|
|
|
def test__get_overall_sync_state__all_are_locked__overall_locked(self):
|
|
# when all are locked state -- overall state would be locked
|
|
self._setup()
|
|
osclockdata = OsClockData(sync_state=OsClockState.Locked, sync_source="ptp0")
|
|
|
|
ptp4ldata0 = PTP4lData(
|
|
ptp_devices=["ptp0"],
|
|
sync_state=PtpState.Locked,
|
|
sync_source=constants.ClockSourceType.TypePTP,
|
|
)
|
|
ptp4ldata1 = PTP4lData(
|
|
ptp_devices=["ptp1"],
|
|
sync_state=PtpState.Locked,
|
|
sync_source=constants.ClockSourceType.TypePTP,
|
|
)
|
|
|
|
ts2phcdata0 = ts2phcData(
|
|
ptp_devices=["ptp0"], sync_state=GnssState.Synchronized
|
|
)
|
|
ts2phcdata1 = ts2phcData(
|
|
ptp_devices=["ptp1"], sync_state=GnssState.Synchronized
|
|
)
|
|
|
|
testdata = TestData(
|
|
osclock=osclockdata,
|
|
ptp4l=[ptp4ldata0, ptp4ldata1],
|
|
ts2phc=[ts2phcdata0, ts2phcdata1],
|
|
)
|
|
expected = OverallClockState.Locked
|
|
self._test__get_overall_sync_state(testdata, expected)
|
|
|
|
def test__get_overall_sync_state__osclock_freerun__overall_freerun(self):
|
|
# when osclock is on freerun, and others are on locked state -- overall
|
|
# state would be freerun
|
|
self._setup()
|
|
osclockdata = OsClockData(sync_state=OsClockState.Freerun, sync_source="ptp0")
|
|
|
|
ptp4ldata0 = PTP4lData(
|
|
ptp_devices=["ptp0"],
|
|
sync_state=PtpState.Locked,
|
|
sync_source=constants.ClockSourceType.TypePTP,
|
|
)
|
|
ptp4ldata1 = PTP4lData(
|
|
ptp_devices=["ptp1"],
|
|
sync_state=PtpState.Locked,
|
|
sync_source=constants.ClockSourceType.TypePTP,
|
|
)
|
|
|
|
ts2phcdata0 = ts2phcData(
|
|
ptp_devices=["ptp0"], sync_state=GnssState.Synchronized
|
|
)
|
|
ts2phcdata1 = ts2phcData(
|
|
ptp_devices=["ptp1"], sync_state=GnssState.Synchronized
|
|
)
|
|
|
|
testdata = TestData(
|
|
osclock=osclockdata,
|
|
ptp4l=[ptp4ldata0, ptp4ldata1],
|
|
ts2phc=[ts2phcdata0, ts2phcdata1],
|
|
)
|
|
expected = OverallClockState.Freerun
|
|
self._test__get_overall_sync_state(testdata, expected)
|
|
|
|
def test__get_overall_sync_state__ptp4l_ptp0_freerun__overall_freerun(self):
|
|
# when chained ptp4l ptp0 sync_state is freerun -- overall state would be freerun
|
|
self._setup()
|
|
osclockdata = OsClockData(sync_state=OsClockState.Locked, sync_source="ptp0")
|
|
|
|
ptp4ldata0 = PTP4lData(
|
|
ptp_devices=["ptp0"],
|
|
sync_state=PtpState.Freerun,
|
|
sync_source=constants.ClockSourceType.TypePTP,
|
|
)
|
|
ptp4ldata1 = PTP4lData(
|
|
ptp_devices=["ptp1"],
|
|
sync_state=PtpState.Locked,
|
|
sync_source=constants.ClockSourceType.TypePTP,
|
|
)
|
|
|
|
ts2phcdata0 = ts2phcData(
|
|
ptp_devices=["ptp0"], sync_state=GnssState.Synchronized
|
|
)
|
|
ts2phcdata1 = ts2phcData(
|
|
ptp_devices=["ptp1"], sync_state=GnssState.Synchronized
|
|
)
|
|
|
|
testdata = TestData(
|
|
osclock=osclockdata,
|
|
ptp4l=[ptp4ldata0, ptp4ldata1],
|
|
ts2phc=[ts2phcdata0, ts2phcdata1],
|
|
)
|
|
expected = OverallClockState.Freerun
|
|
self._test__get_overall_sync_state(testdata, expected)
|
|
|
|
def test__get_overall_sync_state__ptp4l_ptp0_locked__overall_locked(self):
|
|
# when chained ptp4l ptp0 sync_state is locked -- overall state would be locked
|
|
self._setup()
|
|
osclockdata = OsClockData(sync_state=OsClockState.Locked, sync_source="ptp0")
|
|
|
|
ptp4ldata0 = PTP4lData(
|
|
ptp_devices=["ptp0"],
|
|
sync_state=PtpState.Locked,
|
|
sync_source=constants.ClockSourceType.TypePTP,
|
|
)
|
|
ptp4ldata1 = PTP4lData(
|
|
ptp_devices=["ptp1"],
|
|
sync_state=PtpState.Freerun,
|
|
sync_source=constants.ClockSourceType.TypePTP,
|
|
)
|
|
|
|
ts2phcdata0 = ts2phcData(
|
|
ptp_devices=["ptp0"], sync_state=GnssState.Failure_Nofix
|
|
)
|
|
ts2phcdata1 = ts2phcData(
|
|
ptp_devices=["ptp1"], sync_state=GnssState.Failure_Nofix
|
|
)
|
|
|
|
testdata = TestData(
|
|
osclock=osclockdata,
|
|
ptp4l=[ptp4ldata0, ptp4ldata1],
|
|
ts2phc=[ts2phcdata0, ts2phcdata1],
|
|
)
|
|
expected = OverallClockState.Locked
|
|
self._test__get_overall_sync_state(testdata, expected)
|
|
|
|
def test__get_overall_sync_state__ts2phc_ptp0_freerun__overall_freerun(self):
|
|
# when chained ts2phc ptp0 sync_state is freerun -- overall state would be freerun
|
|
self._setup()
|
|
osclockdata = OsClockData(sync_state=OsClockState.Locked, sync_source="ptp0")
|
|
|
|
ptp4ldata0 = PTP4lData(
|
|
ptp_devices=["ptp0"],
|
|
sync_state=PtpState.Locked,
|
|
sync_source=constants.ClockSourceType.TypeGNSS,
|
|
)
|
|
ptp4ldata1 = PTP4lData(
|
|
ptp_devices=["ptp1"],
|
|
sync_state=PtpState.Locked,
|
|
sync_source=constants.ClockSourceType.TypePTP,
|
|
)
|
|
|
|
ts2phcdata0 = ts2phcData(
|
|
ptp_devices=["ptp0"], sync_state=GnssState.Failure_Nofix
|
|
)
|
|
ts2phcdata1 = ts2phcData(
|
|
ptp_devices=["ptp1"], sync_state=GnssState.Synchronized
|
|
)
|
|
|
|
testdata = TestData(
|
|
osclock=osclockdata,
|
|
ptp4l=[ptp4ldata0, ptp4ldata1],
|
|
ts2phc=[ts2phcdata0, ts2phcdata1],
|
|
)
|
|
expected = OverallClockState.Freerun
|
|
self._test__get_overall_sync_state(testdata, expected)
|
|
|
|
def test__get_overall_sync_state__ts2phc_ptp0_locked__overall_locked(self):
|
|
# when chained ts2phc ptp0 sync_state is locked -- overall state would be locked
|
|
self._setup()
|
|
osclockdata = OsClockData(sync_state=OsClockState.Locked, sync_source="ptp0")
|
|
|
|
ptp4ldata0 = PTP4lData(
|
|
ptp_devices=["ptp0"],
|
|
sync_state=PtpState.Locked,
|
|
sync_source=constants.ClockSourceType.TypeGNSS,
|
|
)
|
|
ptp4ldata1 = PTP4lData(
|
|
ptp_devices=["ptp1"],
|
|
sync_state=PtpState.Freerun,
|
|
sync_source=constants.ClockSourceType.TypePTP,
|
|
)
|
|
|
|
ts2phcdata0 = ts2phcData(
|
|
ptp_devices=["ptp0"], sync_state=GnssState.Synchronized
|
|
)
|
|
ts2phcdata1 = ts2phcData(
|
|
ptp_devices=["ptp1"], sync_state=GnssState.Failure_Nofix
|
|
)
|
|
|
|
testdata = TestData(
|
|
osclock=osclockdata,
|
|
ptp4l=[ptp4ldata0, ptp4ldata1],
|
|
ts2phc=[ts2phcdata0, ts2phcdata1],
|
|
)
|
|
expected = OverallClockState.Locked
|
|
self._test__get_overall_sync_state(testdata, expected)
|
|
|
|
def test__get_overall_sync_state__ts2phc_ptp0_locked_no_ptp4l_for_ptp0__overall_locked(
|
|
self,
|
|
):
|
|
# when chained ts2phc ptp0 sync_state is locked -- overall state would be locked
|
|
# In this case there are no ptp4l instances with ptp0
|
|
self._setup()
|
|
osclockdata = OsClockData(sync_state=OsClockState.Locked, sync_source="ptp0")
|
|
|
|
ptp4ldata0 = PTP4lData(
|
|
ptp_devices=["ptpx"],
|
|
sync_state=PtpState.Freerun,
|
|
sync_source=constants.ClockSourceType.TypePTP,
|
|
)
|
|
ptp4ldata1 = PTP4lData(
|
|
ptp_devices=["ptp1"],
|
|
sync_state=PtpState.Freerun,
|
|
sync_source=constants.ClockSourceType.TypePTP,
|
|
)
|
|
|
|
ts2phcdata0 = ts2phcData(
|
|
ptp_devices=["ptp0"], sync_state=GnssState.Synchronized
|
|
)
|
|
ts2phcdata1 = ts2phcData(
|
|
ptp_devices=["ptp1"], sync_state=GnssState.Failure_Nofix
|
|
)
|
|
|
|
testdata = TestData(
|
|
osclock=osclockdata,
|
|
ptp4l=[ptp4ldata0, ptp4ldata1],
|
|
ts2phc=[ts2phcdata0, ts2phcdata1],
|
|
)
|
|
expected = OverallClockState.Locked
|
|
self._test__get_overall_sync_state(testdata, expected)
|
|
|
|
def test__get_overall_sync_state__no_source_for_ptp0__overall_freerun(self):
|
|
# when chained ptp4l ptp0 sync_source NA (neither gnss nor ptp) -- overall
|
|
# state would be freerun
|
|
# In this case there are no ts2phc instances with ptp0
|
|
self._setup()
|
|
osclockdata = OsClockData(sync_state=OsClockState.Locked, sync_source="ptp0")
|
|
|
|
# In this case, practically ptp0's ptp4l instance sync_state would be
|
|
# PtpState.Freerun, as there is no sync source. But still using locked state.
|
|
ptp4ldata0 = PTP4lData(
|
|
ptp_devices=["ptp0"],
|
|
sync_state=PtpState.Locked,
|
|
sync_source=constants.ClockSourceType.TypeNA,
|
|
)
|
|
ptp4ldata1 = PTP4lData(
|
|
ptp_devices=["ptp1"],
|
|
sync_state=PtpState.Locked,
|
|
sync_source=constants.ClockSourceType.TypePTP,
|
|
)
|
|
|
|
ts2phcdata0 = ts2phcData(
|
|
ptp_devices=["ptpx"], sync_state=GnssState.Synchronized
|
|
)
|
|
ts2phcdata1 = ts2phcData(
|
|
ptp_devices=["ptp1"], sync_state=GnssState.Synchronized
|
|
)
|
|
|
|
testdata = TestData(
|
|
osclock=osclockdata,
|
|
ptp4l=[ptp4ldata0, ptp4ldata1],
|
|
ts2phc=[ts2phcdata0, ts2phcdata1],
|
|
)
|
|
expected = OverallClockState.Freerun
|
|
self._test__get_overall_sync_state(testdata, expected)
|
|
|
|
def test__get_overall_sync_state__no_backtrack_for_ptp0__overall_freerun(self):
|
|
# when chained ptp0 is not included neither on ptp4l nor ts2phc -- overall
|
|
# state would be freerun
|
|
self._setup()
|
|
osclockdata = OsClockData(sync_state=OsClockState.Locked, sync_source="ptp0")
|
|
|
|
ptp4ldata0 = PTP4lData(
|
|
ptp_devices=["ptpx"],
|
|
sync_state=PtpState.Locked,
|
|
sync_source=constants.ClockSourceType.TypePTP,
|
|
)
|
|
ptp4ldata1 = PTP4lData(
|
|
ptp_devices=["ptp1"],
|
|
sync_state=PtpState.Locked,
|
|
sync_source=constants.ClockSourceType.TypePTP,
|
|
)
|
|
|
|
ts2phcdata0 = ts2phcData(
|
|
ptp_devices=["ptpx"], sync_state=GnssState.Synchronized
|
|
)
|
|
ts2phcdata1 = ts2phcData(
|
|
ptp_devices=["ptp1"], sync_state=GnssState.Synchronized
|
|
)
|
|
|
|
testdata = TestData(
|
|
osclock=osclockdata,
|
|
ptp4l=[ptp4ldata0, ptp4ldata1],
|
|
ts2phc=[ts2phcdata0, ts2phcdata1],
|
|
)
|
|
expected = OverallClockState.Freerun
|
|
self._test__get_overall_sync_state(testdata, expected)
|
|
|
|
def test__get_overall_sync_state__os_clock_no_ptp_device__overall_freerun(self):
|
|
# when there is no sync_source e.g. ptp0 for os_clock -- overall state would be freerun
|
|
self._setup()
|
|
osclockdata = OsClockData(sync_state=OsClockState.Locked, sync_source=None)
|
|
|
|
ptp4ldata0 = PTP4lData(
|
|
ptp_devices=["ptp0"],
|
|
sync_state=PtpState.Locked,
|
|
sync_source=constants.ClockSourceType.TypePTP,
|
|
)
|
|
ptp4ldata1 = PTP4lData(
|
|
ptp_devices=["ptp1"],
|
|
sync_state=PtpState.Locked,
|
|
sync_source=constants.ClockSourceType.TypePTP,
|
|
)
|
|
|
|
ts2phcdata0 = ts2phcData(
|
|
ptp_devices=["ptp0"], sync_state=GnssState.Synchronized
|
|
)
|
|
ts2phcdata1 = ts2phcData(
|
|
ptp_devices=["ptp1"], sync_state=GnssState.Synchronized
|
|
)
|
|
|
|
testdata = TestData(
|
|
osclock=osclockdata,
|
|
ptp4l=[ptp4ldata0, ptp4ldata1],
|
|
ts2phc=[ts2phcdata0, ts2phcdata1],
|
|
)
|
|
expected = OverallClockState.Freerun
|
|
self._test__get_overall_sync_state(testdata, expected)
|