diff --git a/CHANGELOG.md b/CHANGELOG.md index d81e0ceb..500d04b4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -17,6 +17,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Randomly failing `test_pending_events_limit` in `tests/instruments/picoquant/test_hydraharp_event_processing.py`: the test reused and `clear()`-ed a single `threading.Event` across three successive measurement phases while repatching the mocked `ReadFiFo` side effect. The background fetch thread could re-set that shared event from a stale, already-exhausted FIFO stream right after it was cleared but before the new measurement's data had been processed, causing an intermittent `AssertionError`. Each phase now uses its own dedicated event instead. - `RpcInterfaceDescriptor` in `qmi.core.rpc` could not unpickle descriptors sent by peer contexts running a QMI version older than 0.54.0, since those descriptors have 6 fields instead of the current 7 (missing `properties`). Such descriptors are now accepted and get an empty `properties` list. - `DataFolder.read_dataset()` raised `FileNotFoundError` for a raw dataset (data without axes, e.g. plain 2D data) written by `DataFolder.write_dataset()`, because such datasets are stored at the HDF5 file root instead of in a group named after the dataset. `read_dataset()` now falls back to reading the file root when a child group with the dataset's name is not found but the file's root attributes identify it as that raw dataset. Affects both the `h5py` and `h5netcdf` backends. +- Randomly failing `test_elf_upload_timeout` in `tests/instruments/zurich_instruments/test_hdawg.py`: the test relied on real wall-clock timing via `time.sleep()`, combined with a mocked upload progress sequence, to land on exactly two poll iterations before the upload timeout tripped. Under CI scheduling jitter, the real elapsed time could exceed the timeout one iteration earlier than intended, causing the reported progress to be `0.0%` instead of the expected `50.0%`. The test now mocks `time.monotonic()` (and `time.sleep()`) so the timeout trip point is deterministic. ## [0.54.0] - 2026-10-02 diff --git a/tests/instruments/zurich_instruments/test_hdawg.py b/tests/instruments/zurich_instruments/test_hdawg.py index 4dce16d4..0d8ba21e 100644 --- a/tests/instruments/zurich_instruments/test_hdawg.py +++ b/tests/instruments/zurich_instruments/test_hdawg.py @@ -4,7 +4,7 @@ import jsonschema import logging import unittest -from unittest.mock import call, Mock, ANY, PropertyMock +from unittest.mock import call, Mock, ANY, PropertyMock, patch import warnings import numpy as np @@ -1018,8 +1018,15 @@ def test_elf_upload_timeout(self): ] expected_calls_getdouble = [call("progress"), call("progress")] - with self.assertRaises(QMI_TimeoutException) as exc: - self.hdawg.compile_and_upload(source) + # Mock the monotonic clock so that the timeout trip point is deterministic. Relying on real + # elapsed wall-clock time together with a mocked `getDouble` progress sequence made this test + # flaky: under CI scheduling jitter, `time.sleep` calls could take longer than expected, causing + # the timeout to trip one poll iteration earlier than intended and report the wrong progress value. + monotonic_values = [0.0, 0.0, 0.0, 0.05, self.hdawg.UPLOAD_TIMEOUT + 0.01] + with patch("qmi.instruments.zurich_instruments.hdawg.time.sleep"), \ + patch("qmi.instruments.zurich_instruments.hdawg.time.monotonic", side_effect=monotonic_values): + with self.assertRaises(QMI_TimeoutException) as exc: + self.hdawg.compile_and_upload(source) self.assertEqual(expected_exception, str(exc.exception)) self._awg_module.awg.raw_module.set.assert_has_calls(expected_calls_set)