From 0ceff0fd5f433209593fa7b4056fa0bdeb2146ce Mon Sep 17 00:00:00 2001 From: Alistair Coles Date: Wed, 26 Nov 2025 14:34:19 +0000 Subject: [PATCH] test_base.py: tighten up use of Timestamp Change-Id: I9c3bd921b42dfab7d6238ea267fbc7031239a6d8 Signed-off-by: Alistair Coles --- swift/proxy/controllers/base.py | 4 +- test/unit/proxy/controllers/test_base.py | 52 +++++++++++++++++------- 2 files changed, 40 insertions(+), 16 deletions(-) diff --git a/swift/proxy/controllers/base.py b/swift/proxy/controllers/base.py index 3a8d554e1f..259a69a968 100644 --- a/swift/proxy/controllers/base.py +++ b/swift/proxy/controllers/base.py @@ -1168,8 +1168,8 @@ class GetterSource(object): @property def timestamp(self): """ - Provide the timestamp of the swift http response as a floating - point value. Used as a sort key. + Provide the timestamp of the swift http response as a Timestamp + instance. Used as a sort key. :return: an instance of ``utils.Timestamp`` """ diff --git a/test/unit/proxy/controllers/test_base.py b/test/unit/proxy/controllers/test_base.py index 1b54fd7f70..c8fca31132 100644 --- a/test/unit/proxy/controllers/test_base.py +++ b/test/unit/proxy/controllers/test_base.py @@ -14,6 +14,7 @@ # limitations under the License. import operator import os +import random from argparse import Namespace import itertools import json @@ -40,7 +41,7 @@ from swift.common.storage_policy import StoragePolicy, StoragePolicyCollection from test.debug_logger import debug_logger from test.unit import ( fake_http_connect, FakeRing, FakeMemcache, PatchPolicies, patch_policies, - FakeSource, StubResponse, CaptureIteratorFactory) + FakeSource, StubResponse, CaptureIteratorFactory, make_timestamp_iter) from swift.common.request_helpers import ( get_sys_meta_prefix, get_object_transient_sysmeta ) @@ -1603,6 +1604,7 @@ class TestGetterSource(unittest.TestCase): self.node = {'ip': '1.2.3.4', 'port': '999'} self.headers = {'X-Timestamp': '1234567.12345'} self.resp = StubResponse(200, headers=self.headers) + self.ts_iter = make_timestamp_iter() def test_init(self): src = GetterSource(self.app, self.resp, self.node) @@ -1615,38 +1617,60 @@ class TestGetterSource(unittest.TestCase): headers = {} src = self._make_source(headers, self.node) self.assertIsInstance(src.timestamp, Timestamp) - self.assertEqual(Timestamp(0), src.timestamp) + self.assertEqual(Timestamp.zero(), src.timestamp) # now x-timestamp headers = dict(self.headers) src = self._make_source(headers, self.node) self.assertIsInstance(src.timestamp, Timestamp) - self.assertEqual(Timestamp(1234567.12345), src.timestamp) + self.assertEqual(Timestamp(headers['X-Timestamp']), src.timestamp) headers['x-put-timestamp'] = '1234567.11111' src = self._make_source(headers, self.node) self.assertIsInstance(src.timestamp, Timestamp) - self.assertEqual(Timestamp(1234567.11111), src.timestamp) + self.assertEqual(Timestamp('1234567.11111'), src.timestamp) headers['x-backend-timestamp'] = '1234567.22222' src = self._make_source(headers, self.node) self.assertIsInstance(src.timestamp, Timestamp) - self.assertEqual(Timestamp(1234567.22222), src.timestamp) + self.assertEqual(Timestamp('1234567.22222'), src.timestamp) headers['x-backend-data-timestamp'] = '1234567.33333' src = self._make_source(headers, self.node) self.assertIsInstance(src.timestamp, Timestamp) - self.assertEqual(Timestamp(1234567.33333), src.timestamp) + self.assertEqual(Timestamp('1234567.33333'), src.timestamp) + ts_data = Timestamp.now(offset=123) + headers['x-backend-data-timestamp'] = ts_data.internal + src = self._make_source(headers, self.node) + self.assertIsInstance(src.timestamp, Timestamp) + self.assertEqual(ts_data, src.timestamp) - def test_sort(self): + def test_sort_by_x_timestamp(self): # verify sorting by timestamp srcs = [ - self._make_source({'X-Timestamp': '12345.12345'}, + self._make_source( + {'X-Timestamp': next(self.ts_iter).normal, + 'X-Put-Timestamp': next(self.ts_iter).normal}, + {'ip': '1.2.3.9', 'port': '7'}), + self._make_source({'X-Timestamp': next(self.ts_iter).normal}, {'ip': '1.2.3.7', 'port': '9'}), - self._make_source({'X-Timestamp': '12345.12346'}, + self._make_source({'X-Timestamp': next(self.ts_iter).normal}, {'ip': '1.2.3.8', 'port': '8'}), - self._make_source({'X-Timestamp': '12345.12343', - 'X-Put-Timestamp': '12345.12344'}, - {'ip': '1.2.3.9', 'port': '7'}), ] - actual = sorted(srcs, key=operator.attrgetter('timestamp')) - self.assertEqual([srcs[2], srcs[0], srcs[1]], actual) + actual = sorted(random.sample(srcs, k=len(srcs)), + key=operator.attrgetter('timestamp')) + self.assertEqual(srcs, actual) + + def test_sort_by_x_backend_timestamp(self): + # verify x-backend-timestamp is preferred over x-timestamp + src_headers = [{'X-Backend-Timestamp': next(self.ts_iter).internal} + for _ in range(3)] + for headers in reversed(src_headers): + headers['X-Timestamp'] = next(self.ts_iter).normal + srcs = [ + self._make_source(headers, + {'ip': '1.2.3.%d' % i, 'port': '%d' % i}) + for i, headers in enumerate(src_headers) + ] + actual = sorted(random.sample(srcs, k=len(srcs)), + key=operator.attrgetter('timestamp')) + self.assertEqual(srcs, actual) def test_close(self): # verify close is robust...