Allow Timestamp comparisons against out-of-range values

Prior to the related change, clients may have written down X-Delete-At headers
that are outside of the Timestamp range, for example.

Change-Id: Ib8ae7ebcbdb32e0aa58446bd1ef949e5e2f63e74
Related-Change: I23666ec8a067d829eaf9bfe54bd086c320b3429e
Related-Bug: 1821204
Partial-Bug: 1860149
This commit is contained in:
Tim Burke
2020-01-16 10:07:33 -08:00
parent 0901464513
commit 57ca3570e9
2 changed files with 47 additions and 12 deletions

View File

@@ -1231,7 +1231,7 @@ class Timestamp(object):
compatible for normalized timestamps which do not include an offset.
"""
def __init__(self, timestamp, offset=0, delta=0):
def __init__(self, timestamp, offset=0, delta=0, check_bounds=True):
"""
Create a new Timestamp.
@@ -1275,10 +1275,11 @@ class Timestamp(object):
raise ValueError(
'delta must be greater than %d' % (-1 * self.raw))
self.timestamp = float(self.raw * PRECISION)
if self.timestamp < 0:
raise ValueError('timestamp cannot be negative')
if self.timestamp >= 10000000000:
raise ValueError('timestamp too large')
if check_bounds:
if self.timestamp < 0:
raise ValueError('timestamp cannot be negative')
if self.timestamp >= 10000000000:
raise ValueError('timestamp too large')
@classmethod
def now(cls, offset=0, delta=0):
@@ -1352,21 +1353,24 @@ class Timestamp(object):
if other is None:
return False
if not isinstance(other, Timestamp):
other = Timestamp(other)
try:
other = Timestamp(other, check_bounds=False)
except ValueError:
return False
return self.internal == other.internal
def __ne__(self, other):
if other is None:
return True
if not isinstance(other, Timestamp):
other = Timestamp(other)
return self.internal != other.internal
return not (self == other)
def __lt__(self, other):
if other is None:
return False
if not isinstance(other, Timestamp):
other = Timestamp(other)
other = Timestamp(other, check_bounds=False)
if other.timestamp < 0:
return False
if other.timestamp >= 10000000000:
return True
return self.internal < other.internal
def __hash__(self):

View File

@@ -858,6 +858,37 @@ class TestTimestamp(unittest.TestCase):
self.assertIn(ts_0, d) # sanity
self.assertIn(ts_0_also, d)
def test_out_of_range_comparisons(self):
now = utils.Timestamp.now()
def check_is_later(val):
self.assertTrue(now != val)
self.assertFalse(now == val)
self.assertTrue(now <= val)
self.assertTrue(now < val)
self.assertTrue(val > now)
self.assertTrue(val >= now)
check_is_later(1e30)
check_is_later(1579753284000) # someone gave us ms instead of s!
check_is_later('1579753284000')
check_is_later(b'1e15')
check_is_later(u'1.e+10_f')
def check_is_earlier(val):
self.assertTrue(now != val)
self.assertFalse(now == val)
self.assertTrue(now >= val)
self.assertTrue(now > val)
self.assertTrue(val < now)
self.assertTrue(val <= now)
check_is_earlier(-1)
check_is_earlier(-0.1)
check_is_earlier('-9999999')
check_is_earlier(b'-9999.999')
check_is_earlier(u'-1234_5678')
class TestTimestampEncoding(unittest.TestCase):