@@ -143,3 +143,68 @@ def test_update_fipsstats_command(self, mock_cmd):
143143 pdstatsd .update_fipsstats_command ()
144144 assert pdstatsd .state_db .get ('STATE_DB' , 'FIPS_STATS|state' , 'enforced' ) == "False"
145145 assert pdstatsd .state_db .get ('STATE_DB' , 'FIPS_STATS|state' , 'enabled' ) == "True"
146+
147+ def test_datetime_utcnow_usage (self ):
148+ """Test that datetime.utcnow() is used instead of datetime.now() for consistent UTC timestamps"""
149+ pdstatsd = procdockerstatsd .ProcDockerStats (procdockerstatsd .SYSLOG_IDENTIFIER )
150+
151+ # Mock datetime.utcnow to return a fixed time for testing
152+ fixed_time = datetime (2025 , 7 , 1 , 12 , 34 , 56 )
153+
154+ with patch ('procdockerstatsd.datetime' ) as mock_datetime :
155+ mock_datetime .utcnow .return_value = fixed_time
156+
157+ # Test the update_fipsstats_command method which uses datetime.utcnow()
158+ pdstatsd .update_fipsstats_command ()
159+
160+ # Verify that utcnow() was called
161+ mock_datetime .utcnow .assert_called_once ()
162+
163+ # Verify that now() was NOT called (ensuring we're using UTC)
164+ mock_datetime .now .assert_not_called ()
165+
166+ # Test the main run loop datetime usage
167+ with patch .object (pdstatsd , 'update_dockerstats_command' ):
168+ with patch .object (pdstatsd , 'update_processstats_command' ):
169+ with patch .object (pdstatsd , 'update_fipsstats_command' ):
170+ with patch ('time.sleep' ): # Prevent actual sleep
171+ # Mock the first iteration of the run loop
172+ pdstatsd .update_dockerstats_command ()
173+ datetimeobj = mock_datetime .utcnow ()
174+ pdstatsd .update_state_db ('DOCKER_STATS|LastUpdateTime' , 'lastupdate' , str (datetimeobj ))
175+ pdstatsd .update_processstats_command ()
176+ pdstatsd .update_state_db ('PROCESS_STATS|LastUpdateTime' , 'lastupdate' , str (datetimeobj ))
177+ pdstatsd .update_fipsstats_command ()
178+ pdstatsd .update_state_db ('FIPS_STATS|LastUpdateTime' , 'lastupdate' , str (datetimeobj ))
179+
180+ # Verify utcnow() was called multiple times as expected
181+ assert mock_datetime .utcnow .call_count >= 2
182+
183+ def test_run_method_executes_with_utcnow (self ):
184+ """Test that run method executes and uses datetime.utcnow()"""
185+ pdstatsd = procdockerstatsd .ProcDockerStats (procdockerstatsd .SYSLOG_IDENTIFIER )
186+
187+ # Mock all dependencies but allow datetime.utcnow() to run normally
188+ with patch .object (pdstatsd , 'update_dockerstats_command' ):
189+ with patch .object (pdstatsd , 'update_processstats_command' ):
190+ with patch .object (pdstatsd , 'update_fipsstats_command' ):
191+ with patch ('time.sleep' , side_effect = Exception ("Stop after first iteration" )):
192+ with patch ('os.getuid' , return_value = 0 ): # Mock as root
193+ with patch .object (pdstatsd , 'log_info' ):
194+ with patch .object (pdstatsd , 'update_state_db' ) as mock_update_db :
195+ # This will actually call run() method
196+ try :
197+ pdstatsd .run ()
198+ except Exception as e :
199+ if "Stop after first iteration" in str (e ):
200+ # Verify that update_state_db was called
201+ assert mock_update_db .call_count >= 3
202+ # Verify that timestamps were passed
203+ for call in mock_update_db .call_args_list :
204+ args = call [0 ]
205+ if len (args ) >= 3 and 'lastupdate' in args [1 ]:
206+ timestamp_str = args [2 ]
207+ assert isinstance (timestamp_str , str )
208+ assert len (timestamp_str ) > 0
209+ else :
210+ raise
0 commit comments