1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138
|
"""Unit test for SetUTC module."""
import unittest
from unittest.mock import MagicMock, patch
from pyvlx.api import SetUTC
from pyvlx.api.frames import FrameSetUTCConfirmation, FrameSetUTCRequest
class TestSetUTC(unittest.IsolatedAsyncioTestCase):
"""Test class for SetUTC."""
def setUp(self) -> None:
"""Set up TestSetUTC."""
self.pyvlx = MagicMock()
def test_explicit_timestamp(self) -> None:
"""Test that an explicit timestamp is stored correctly."""
set_utc = SetUTC(pyvlx=self.pyvlx, timestamp=1234567890.0)
self.assertEqual(set_utc.timestamp, 1234567890.0)
def test_explicit_timestamp_float(self) -> None:
"""Test that a float timestamp is preserved."""
set_utc = SetUTC(pyvlx=self.pyvlx, timestamp=1234567890.123)
self.assertEqual(set_utc.timestamp, 1234567890.123)
@patch("pyvlx.api.set_utc.time.time", return_value=1700000000.0)
def test_default_timestamp_uses_current_time(self, mock_time: MagicMock) -> None:
"""Test that omitting timestamp uses time.time()."""
set_utc = SetUTC(pyvlx=self.pyvlx)
self.assertEqual(set_utc.timestamp, 1700000000.0)
mock_time.assert_called_once()
@patch("pyvlx.api.set_utc.time.time", return_value=1700000000.0)
def test_default_timestamp_none_uses_current_time(self, mock_time: MagicMock) -> None:
"""Test that passing timestamp=None explicitly uses time.time()."""
set_utc = SetUTC(pyvlx=self.pyvlx, timestamp=None)
self.assertEqual(set_utc.timestamp, 1700000000.0)
mock_time.assert_called_once()
@patch("pyvlx.api.set_utc.time.time")
def test_multiple_calls_get_different_timestamps(self, mock_time: MagicMock) -> None:
"""Test that multiple SetUTC instances each capture their own timestamp."""
mock_time.side_effect = [1700000000.0, 1700000005.0, 1700000010.0]
set_utc_1 = SetUTC(pyvlx=self.pyvlx)
set_utc_2 = SetUTC(pyvlx=self.pyvlx)
set_utc_3 = SetUTC(pyvlx=self.pyvlx)
self.assertEqual(set_utc_1.timestamp, 1700000000.0)
self.assertEqual(set_utc_2.timestamp, 1700000005.0)
self.assertEqual(set_utc_3.timestamp, 1700000010.0)
self.assertEqual(mock_time.call_count, 3)
@patch("pyvlx.api.set_utc.time.time")
def test_multiple_calls_timestamp_captured_at_init(self, mock_time: MagicMock) -> None:
"""Test that timestamp is captured at __init__, not at request_frame time."""
mock_time.return_value = 1700000000.0
set_utc = SetUTC(pyvlx=self.pyvlx)
# Advance mock time — should NOT affect the already-created instance
mock_time.return_value = 1700099999.0
frame = set_utc.request_frame()
self.assertEqual(frame.timestamp, 1700000000)
@patch("pyvlx.api.set_utc.time.time")
def test_multiple_instances_independent_request_frames(self, mock_time: MagicMock) -> None:
"""Test that request_frame of each instance uses its own captured timestamp."""
mock_time.side_effect = [1700000000.0, 1700000060.0]
set_utc_1 = SetUTC(pyvlx=self.pyvlx)
set_utc_2 = SetUTC(pyvlx=self.pyvlx)
frame_1 = set_utc_1.request_frame()
frame_2 = set_utc_2.request_frame()
self.assertEqual(frame_1.timestamp, 1700000000)
self.assertEqual(frame_2.timestamp, 1700000060)
self.assertNotEqual(frame_1.timestamp, frame_2.timestamp)
def test_initial_success_is_false(self) -> None:
"""Test that success is initially False."""
set_utc = SetUTC(pyvlx=self.pyvlx, timestamp=1000.0)
self.assertFalse(set_utc.success)
async def test_handle_frame_confirmation(self) -> None:
"""Test handle_frame with a valid FrameSetUTCConfirmation."""
set_utc = SetUTC(pyvlx=self.pyvlx, timestamp=1000.0)
frame = FrameSetUTCConfirmation()
result = await set_utc.handle_frame(frame)
self.assertTrue(result)
self.assertTrue(set_utc.success)
async def test_handle_frame_wrong_frame_type(self) -> None:
"""Test handle_frame with an unrelated frame type returns False."""
set_utc = SetUTC(pyvlx=self.pyvlx, timestamp=1000.0)
frame = MagicMock()
result = await set_utc.handle_frame(frame)
self.assertFalse(result)
self.assertFalse(set_utc.success)
async def test_handle_frame_does_not_change_timestamp(self) -> None:
"""Test that handle_frame does not alter the stored timestamp."""
set_utc = SetUTC(pyvlx=self.pyvlx, timestamp=1234567890.0)
frame = FrameSetUTCConfirmation()
await set_utc.handle_frame(frame)
self.assertEqual(set_utc.timestamp, 1234567890.0)
def test_request_frame_returns_correct_type(self) -> None:
"""Test that request_frame returns a FrameSetUTCRequest."""
set_utc = SetUTC(pyvlx=self.pyvlx, timestamp=1700000000.5)
frame = set_utc.request_frame()
self.assertIsInstance(frame, FrameSetUTCRequest)
def test_request_frame_truncates_to_int(self) -> None:
"""Test that request_frame truncates float timestamp to int."""
set_utc = SetUTC(pyvlx=self.pyvlx, timestamp=1700000000.999)
frame = set_utc.request_frame()
self.assertEqual(frame.timestamp, 1700000000)
@patch("pyvlx.api.set_utc.time.time")
def test_multiple_calls_request_frame_called_twice_same_instance(self, mock_time: MagicMock) -> None:
"""Test that calling request_frame multiple times on the same instance returns the same timestamp."""
mock_time.return_value = 1700000000.0
set_utc = SetUTC(pyvlx=self.pyvlx)
frame_1 = set_utc.request_frame()
frame_2 = set_utc.request_frame()
self.assertEqual(frame_1.timestamp, frame_2.timestamp)
# time.time() should only have been called once — at __init__
mock_time.assert_called_once()
@patch("pyvlx.api.set_utc.time.time")
def test_explicit_timestamp_does_not_call_time(self, mock_time: MagicMock) -> None:
"""Test that passing an explicit timestamp does not call time.time()."""
SetUTC(pyvlx=self.pyvlx, timestamp=1234567890.0)
mock_time.assert_not_called()
|