1#!/usr/bin/env python3 2# Copyright 2022 The Pigweed Authors 3# 4# Licensed under the Apache License, Version 2.0 (the "License"); you may not 5# use this file except in compliance with the License. You may obtain a copy of 6# the License at 7# 8# https://www.apache.org/licenses/LICENSE-2.0 9# 10# Unless required by applicable law or agreed to in writing, software 11# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13# License for the specific language governing permissions and limitations under 14# the License. 15"""Tests for the timestamp analyzer.""" 16 17import unittest 18from pw_chrono.timestamp_analyzer import process_snapshot 19from pw_chrono_protos import chrono_pb2 20from pw_tokenizer import detokenize, tokens 21 22 23class TimestampTest(unittest.TestCase): 24 """Test for the timestamp analyzer.""" 25 26 def test_no_timepoint(self): 27 snapshot = chrono_pb2.SnapshotTimestamps() 28 self.assertEqual( 29 '', str(process_snapshot(snapshot.SerializeToString())) 30 ) 31 32 def test_timestamp_unknown_epoch_type(self): 33 snapshot = chrono_pb2.SnapshotTimestamps() 34 35 time_point = chrono_pb2.TimePoint( 36 timestamp=0, 37 clock_parameters=chrono_pb2.ClockParameters( 38 tick_period_seconds_numerator=1, 39 tick_period_seconds_denominator=1, 40 epoch_type=chrono_pb2.EpochType.Enum.UNKNOWN, 41 ), 42 ) 43 snapshot.timestamps.append(time_point) 44 45 expected = '\n'.join( 46 ( 47 'Snapshot capture timestamp', 48 ' Timestamp (epoch UNKNOWN): 0 s', 49 '', 50 ) 51 ) 52 53 self.assertEqual( 54 expected, str(process_snapshot(snapshot.SerializeToString())) 55 ) 56 57 def test_timestamp_with_time_since_boot(self): 58 snapshot = chrono_pb2.SnapshotTimestamps() 59 60 time_point = chrono_pb2.TimePoint( 61 timestamp=8640015, 62 clock_parameters=chrono_pb2.ClockParameters( 63 tick_period_seconds_numerator=1, 64 tick_period_seconds_denominator=1000, 65 epoch_type=chrono_pb2.EpochType.Enum.TIME_SINCE_BOOT, 66 ), 67 ) 68 snapshot.timestamps.append(time_point) 69 70 expected = '\n'.join( 71 ( 72 'Snapshot capture timestamp', 73 ' Time since boot: 2:24:00.015000 (8640015 ms)', 74 '', 75 ) 76 ) 77 78 self.assertEqual( 79 expected, str(process_snapshot(snapshot.SerializeToString())) 80 ) 81 82 def test_timestamp_with_utc_wall_clock(self): 83 snapshot = chrono_pb2.SnapshotTimestamps() 84 85 time_point = chrono_pb2.TimePoint( 86 timestamp=8640015, 87 clock_parameters=chrono_pb2.ClockParameters( 88 tick_period_seconds_numerator=1, 89 tick_period_seconds_denominator=1000, 90 epoch_type=chrono_pb2.EpochType.Enum.UTC_WALL_CLOCK, 91 ), 92 ) 93 snapshot.timestamps.append(time_point) 94 95 expected = '\n'.join( 96 ( 97 'Snapshot capture timestamp', 98 ' UTC time: 1970-01-01 02:24:00.015000+00:00 (8640015 ms)', 99 '', 100 ) 101 ) 102 103 self.assertEqual( 104 expected, str(process_snapshot(snapshot.SerializeToString())) 105 ) 106 107 def test_timestamp_with_name(self): 108 snapshot = chrono_pb2.SnapshotTimestamps() 109 110 time_point = chrono_pb2.TimePoint( 111 timestamp=51140716, 112 clock_parameters=chrono_pb2.ClockParameters( 113 tick_period_seconds_numerator=1, 114 tick_period_seconds_denominator=1000000, 115 epoch_type=chrono_pb2.EpochType.Enum.UNKNOWN, 116 name='High resolution clock'.encode('utf-8'), 117 ), 118 ) 119 snapshot.timestamps.append(time_point) 120 121 expected = '\n'.join( 122 ( 123 'Snapshot capture timestamp', 124 ' High resolution clock (epoch UNKNOWN): 51140716 us', 125 '', 126 ) 127 ) 128 129 self.assertEqual( 130 expected, str(process_snapshot(snapshot.SerializeToString())) 131 ) 132 133 def test_timestamp_with_tokenized_name(self): 134 token_db = tokens.Database( 135 [ 136 tokens.TokenizedStringEntry(1, 'Peer device clock'), 137 ] 138 ) 139 detokenizer = detokenize.Detokenizer(token_db) 140 141 snapshot = chrono_pb2.SnapshotTimestamps() 142 143 time_point = chrono_pb2.TimePoint( 144 timestamp=51140716, 145 clock_parameters=chrono_pb2.ClockParameters( 146 tick_period_seconds_numerator=1, 147 tick_period_seconds_denominator=1000000, 148 epoch_type=chrono_pb2.EpochType.Enum.UNKNOWN, 149 name=b'\x01\x00\x00\x00', 150 ), 151 ) 152 snapshot.timestamps.append(time_point) 153 154 expected = '\n'.join( 155 ( 156 'Snapshot capture timestamp', 157 ' Peer device clock (epoch UNKNOWN): 51140716 us', 158 '', 159 ) 160 ) 161 162 self.assertEqual( 163 expected, 164 str(process_snapshot(snapshot.SerializeToString(), detokenizer)), 165 ) 166 167 def test_timestamp_with_tai_clock(self): 168 snapshot = chrono_pb2.SnapshotTimestamps() 169 170 time_point = chrono_pb2.TimePoint( 171 timestamp=1733882018, 172 clock_parameters=chrono_pb2.ClockParameters( 173 tick_period_seconds_numerator=1, 174 tick_period_seconds_denominator=1000, 175 epoch_type=chrono_pb2.EpochType.Enum.TAI_WALL_CLOCK, 176 ), 177 ) 178 snapshot.timestamps.append(time_point) 179 180 expected = '\n'.join( 181 ( 182 'Snapshot capture timestamp', 183 ' Timestamp (epoch TAI_WALL_CLOCK): 1733882018 ms', 184 '', 185 ) 186 ) 187 188 self.assertEqual( 189 expected, str(process_snapshot(snapshot.SerializeToString())) 190 ) 191 192 def test_timestamp_with_unrecognized_epoch(self): 193 snapshot = chrono_pb2.SnapshotTimestamps() 194 195 time_point = chrono_pb2.TimePoint( 196 timestamp=3424, 197 clock_parameters=chrono_pb2.ClockParameters( 198 tick_period_seconds_numerator=1, 199 tick_period_seconds_denominator=1, 200 epoch_type=chrono_pb2.EpochType.Enum.ValueType(15), 201 ), 202 ) 203 snapshot.timestamps.append(time_point) 204 205 expected = '\n'.join( 206 ( 207 'Snapshot capture timestamp', 208 ' Timestamp (epoch 15): 3424 s', 209 '', 210 ) 211 ) 212 213 self.assertEqual( 214 expected, str(process_snapshot(snapshot.SerializeToString())) 215 ) 216 217 def test_invalid_timestamp(self): 218 snapshot = chrono_pb2.SnapshotTimestamps() 219 220 time_point = chrono_pb2.TimePoint( 221 timestamp=1, 222 clock_parameters=chrono_pb2.ClockParameters( 223 tick_period_seconds_numerator=1, 224 tick_period_seconds_denominator=0, 225 ), 226 ) 227 snapshot.timestamps.append(time_point) 228 229 expected = '' 230 231 self.assertEqual( 232 expected, str(process_snapshot(snapshot.SerializeToString())) 233 ) 234 235 def test_no_timestamp(self): 236 snapshot = chrono_pb2.SnapshotTimestamps() 237 238 expected = '' 239 240 self.assertEqual( 241 expected, str(process_snapshot(snapshot.SerializeToString())) 242 ) 243 244 def test_timestamp_with_time_since_boot_and_utc_wall_clock(self): 245 """Test multiple timestamps.""" 246 snapshot = chrono_pb2.SnapshotTimestamps() 247 248 time_point = chrono_pb2.TimePoint( 249 timestamp=8640000, 250 clock_parameters=chrono_pb2.ClockParameters( 251 tick_period_seconds_numerator=1, 252 tick_period_seconds_denominator=1000, 253 epoch_type=chrono_pb2.EpochType.Enum.TIME_SINCE_BOOT, 254 ), 255 ) 256 snapshot.timestamps.append(time_point) 257 258 time_point = chrono_pb2.TimePoint( 259 timestamp=8640000, 260 clock_parameters=chrono_pb2.ClockParameters( 261 tick_period_seconds_numerator=1, 262 tick_period_seconds_denominator=1000, 263 epoch_type=chrono_pb2.EpochType.Enum.UTC_WALL_CLOCK, 264 ), 265 ) 266 snapshot.timestamps.append(time_point) 267 268 expected = '\n'.join( 269 ( 270 'Snapshot capture timestamps', 271 ' Time since boot: 2:24:00 (8640000 ms)', 272 ' UTC time: 1970-01-01 02:24:00+00:00 (8640000 ms)', 273 '', 274 ) 275 ) 276 277 self.assertEqual( 278 expected, str(process_snapshot(snapshot.SerializeToString())) 279 ) 280 281 282if __name__ == '__main__': 283 unittest.main() 284