Make the v2 API date query parameters consistent
Use a DateRange object to specify the old start_timestamp, end_timestamp, and search_offset parameters in a consistent way for all of the v2 API calls. This change addresses bug 1094337 and fixes problems with running the v2 API tests against the most current version of WSME, which expects all arguments to be listed on the controller methods explicitly. The changes to the test-requires files install the spidermonkey component, needed for some of the tests that were being skipped, causing this problem to go unnoticed for a while. Change-Id: I4d8677730f228701b0cb85e2ab4294958243e31e Signed-off-by: Doug Hellmann <doug.hellmann@dreamhost.com>
This commit is contained in:
parent
b5e3d5d4cb
commit
2660cd7d56
@ -95,50 +95,6 @@ from ceilometer import storage
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
||||
|
||||
def _get_query_timestamps(args={}):
|
||||
"""Return any optional timestamp information in the request.
|
||||
|
||||
Determine the desired range, if any, from the GET arguments. Set
|
||||
up the query range using the specified offset.
|
||||
|
||||
[query_start ... start_timestamp ... end_timestamp ... query_end]
|
||||
|
||||
Returns a dictionary containing:
|
||||
|
||||
query_start: First timestamp to use for query
|
||||
start_timestamp: start_timestamp parameter from request
|
||||
query_end: Final timestamp to use for query
|
||||
end_timestamp: end_timestamp parameter from request
|
||||
search_offset: search_offset parameter from request
|
||||
|
||||
"""
|
||||
search_offset = int(args.get('search_offset', 0))
|
||||
|
||||
start_timestamp = args.get('start_timestamp')
|
||||
if start_timestamp:
|
||||
start_timestamp = timeutils.parse_isotime(start_timestamp)
|
||||
start_timestamp = start_timestamp.replace(tzinfo=None)
|
||||
query_start = (start_timestamp -
|
||||
datetime.timedelta(minutes=search_offset))
|
||||
else:
|
||||
query_start = None
|
||||
|
||||
end_timestamp = args.get('end_timestamp')
|
||||
if end_timestamp:
|
||||
end_timestamp = timeutils.parse_isotime(end_timestamp)
|
||||
end_timestamp = end_timestamp.replace(tzinfo=None)
|
||||
query_end = end_timestamp + datetime.timedelta(minutes=search_offset)
|
||||
else:
|
||||
query_end = None
|
||||
|
||||
return {'query_start': query_start,
|
||||
'query_end': query_end,
|
||||
'start_timestamp': start_timestamp,
|
||||
'end_timestamp': end_timestamp,
|
||||
'search_offset': search_offset,
|
||||
}
|
||||
|
||||
|
||||
# FIXME(dhellmann): Change APIs that use this to return float?
|
||||
class MeterVolume(Base):
|
||||
volume = wsattr(float, mandatory=False)
|
||||
@ -149,13 +105,59 @@ class MeterVolume(Base):
|
||||
super(MeterVolume, self).__init__(volume=volume, **kw)
|
||||
|
||||
|
||||
class DateRange(Base):
|
||||
start = datetime.datetime
|
||||
end = datetime.datetime
|
||||
search_offset = int
|
||||
|
||||
def __init__(self, start=None, end=None, search_offset=0):
|
||||
if start is not None:
|
||||
start = start.replace(tzinfo=None)
|
||||
if end is not None:
|
||||
end = end.replace(tzinfo=None)
|
||||
super(DateRange, self).__init__(start=start,
|
||||
end=end,
|
||||
search_offset=search_offset,
|
||||
)
|
||||
|
||||
@property
|
||||
def query_start(self):
|
||||
"""The timestamp the query should use to start, including
|
||||
the search offset.
|
||||
"""
|
||||
if self.start is None:
|
||||
return None
|
||||
return (self.start -
|
||||
datetime.timedelta(minutes=self.search_offset))
|
||||
|
||||
@property
|
||||
def query_end(self):
|
||||
"""The timestamp the query should use to end, including
|
||||
the search offset.
|
||||
"""
|
||||
if self.end is None:
|
||||
return None
|
||||
return (self.end +
|
||||
datetime.timedelta(minutes=self.search_offset))
|
||||
|
||||
def to_dict(self):
|
||||
return {'query_start': self.query_start,
|
||||
'query_end': self.query_end,
|
||||
'start_timestamp': self.start,
|
||||
'end_timestamp': self.end,
|
||||
'search_offset': self.search_offset,
|
||||
}
|
||||
|
||||
|
||||
class MeterVolumeController(object):
|
||||
|
||||
@wsme.pecan.wsexpose(MeterVolume)
|
||||
def max(self):
|
||||
@wsme.pecan.wsexpose(MeterVolume, DateRange)
|
||||
def max(self, daterange=None):
|
||||
"""Find the maximum volume for the matching meter events.
|
||||
"""
|
||||
q_ts = _get_query_timestamps(request.params)
|
||||
if daterange is None:
|
||||
daterange = DateRange()
|
||||
q_ts = daterange.to_dict()
|
||||
|
||||
try:
|
||||
meter = request.context['meter_id']
|
||||
@ -193,11 +195,13 @@ class MeterVolumeController(object):
|
||||
|
||||
return MeterVolume(volume=value)
|
||||
|
||||
@wsme.pecan.wsexpose(MeterVolume)
|
||||
def sum(self):
|
||||
@wsme.pecan.wsexpose(MeterVolume, DateRange)
|
||||
def sum(self, daterange=None):
|
||||
"""Compute the total volume for the matching meter events.
|
||||
"""
|
||||
q_ts = _get_query_timestamps(request.params)
|
||||
if daterange is None:
|
||||
daterange = DateRange()
|
||||
q_ts = daterange.to_dict()
|
||||
|
||||
try:
|
||||
meter = request.context['meter_id']
|
||||
@ -285,16 +289,17 @@ class MeterController(RestController):
|
||||
request.context['meter_id'] = meter_id
|
||||
self._id = meter_id
|
||||
|
||||
@wsme.pecan.wsexpose([Event])
|
||||
def get_all(self):
|
||||
@wsme.pecan.wsexpose([Event], DateRange)
|
||||
def get_all(self, daterange=None):
|
||||
"""Return all events for the meter.
|
||||
"""
|
||||
q_ts = _get_query_timestamps(request.params)
|
||||
if daterange is None:
|
||||
daterange = DateRange()
|
||||
f = storage.EventFilter(
|
||||
user=request.context.get('user_id'),
|
||||
project=request.context.get('project_id'),
|
||||
start=q_ts['query_start'],
|
||||
end=q_ts['query_end'],
|
||||
start=daterange.query_start,
|
||||
end=daterange.query_end,
|
||||
resource=request.context.get('resource_id'),
|
||||
meter=self._id,
|
||||
source=request.context.get('source_id'),
|
||||
@ -303,24 +308,19 @@ class MeterController(RestController):
|
||||
for e in request.storage_conn.get_raw_events(f)
|
||||
]
|
||||
|
||||
# TODO(jd) replace str for timestamp by datetime?
|
||||
@wsme.pecan.wsexpose(Duration, str, str, int)
|
||||
def duration(self, start_timestamp=None, end_timestamp=None,
|
||||
search_offset=0):
|
||||
@wsme.pecan.wsexpose(Duration, DateRange)
|
||||
def duration(self, daterange=None):
|
||||
"""Computes the duration of the meter events in the time range given.
|
||||
"""
|
||||
q_ts = _get_query_timestamps(dict(start_timestamp=start_timestamp,
|
||||
end_timestamp=end_timestamp,
|
||||
search_offset=search_offset))
|
||||
start_timestamp = q_ts['start_timestamp']
|
||||
end_timestamp = q_ts['end_timestamp']
|
||||
if daterange is None:
|
||||
daterange = DateRange()
|
||||
|
||||
# Query the database for the interval of timestamps
|
||||
# within the desired range.
|
||||
f = storage.EventFilter(user=request.context.get('user_id'),
|
||||
project=request.context.get('project_id'),
|
||||
start=q_ts['query_start'],
|
||||
end=q_ts['query_end'],
|
||||
start=daterange.query_start,
|
||||
end=daterange.query_end,
|
||||
resource=request.context.get('resource_id'),
|
||||
meter=self._id,
|
||||
source=request.context.get('source_id'),
|
||||
@ -330,12 +330,12 @@ class MeterController(RestController):
|
||||
# "Clamp" the timestamps we return to the original time
|
||||
# range, excluding the offset.
|
||||
LOG.debug('start_timestamp %s, end_timestamp %s, min_ts %s, max_ts %s',
|
||||
start_timestamp, end_timestamp, min_ts, max_ts)
|
||||
if start_timestamp and min_ts and min_ts < start_timestamp:
|
||||
min_ts = start_timestamp
|
||||
daterange.start, daterange.end, min_ts, max_ts)
|
||||
if daterange.start and min_ts and min_ts < daterange.start:
|
||||
min_ts = daterange.start
|
||||
LOG.debug('clamping min timestamp to range')
|
||||
if end_timestamp and max_ts and max_ts > end_timestamp:
|
||||
max_ts = end_timestamp
|
||||
if daterange.end and max_ts and max_ts > daterange.end:
|
||||
max_ts = daterange.end
|
||||
LOG.debug('clamping max timestamp to range')
|
||||
|
||||
# If we got valid timestamps back, compute a duration in minutes.
|
||||
|
@ -108,6 +108,7 @@ class FunctionalTest(unittest.TestCase):
|
||||
'logging': {
|
||||
'loggers': {
|
||||
'root': {'level': 'INFO', 'handlers': ['console']},
|
||||
'wsme': {'level': 'INFO', 'handlers': ['console']},
|
||||
'ceilometer': {'level': 'DEBUG',
|
||||
'handlers': ['console'],
|
||||
},
|
||||
@ -154,11 +155,15 @@ class FunctionalTest(unittest.TestCase):
|
||||
self.mox.VerifyAll()
|
||||
set_config({}, overwrite=True)
|
||||
|
||||
def get_json(self, path, expect_errors=False, headers=None, **params):
|
||||
def get_json(self, path, expect_errors=False, headers=None,
|
||||
extra_params={}, **params):
|
||||
full_path = self.PATH_PREFIX + path
|
||||
print 'GET: %s %r' % (full_path, params)
|
||||
all_params = {}
|
||||
all_params.update(params)
|
||||
all_params.update(extra_params)
|
||||
print 'GET: %s %r' % (full_path, all_params)
|
||||
response = self.app.get(full_path,
|
||||
params=params,
|
||||
params=all_params,
|
||||
headers=headers,
|
||||
expect_errors=expect_errors)
|
||||
if not expect_errors:
|
||||
|
@ -44,7 +44,7 @@ class TestAPIACL(FunctionalTest):
|
||||
|
||||
def test_non_authenticated(self):
|
||||
response = self.get_json('/sources', expect_errors=True)
|
||||
self.assertEqual(response.status_code, 401)
|
||||
self.assertEqual(response.status_int, 401)
|
||||
|
||||
def test_authenticated_wrong_role(self):
|
||||
response = self.get_json('/sources',
|
||||
@ -54,7 +54,7 @@ class TestAPIACL(FunctionalTest):
|
||||
"X-Tenant-Name": "admin",
|
||||
"X-Tenant-Id": "bc23a9d531064583ace8f67dad60f6bb",
|
||||
})
|
||||
self.assertEqual(response.status_code, 401)
|
||||
self.assertEqual(response.status_int, 401)
|
||||
|
||||
# FIXME(dhellmann): This test is not properly looking at the tenant
|
||||
# info. We do not correctly detect the improper tenant. That's
|
||||
@ -69,7 +69,7 @@ class TestAPIACL(FunctionalTest):
|
||||
# "X-Tenant-Name": "achoo",
|
||||
# "X-Tenant-Id": "bc23a9d531064583ace8f67dad60f6bb",
|
||||
# })
|
||||
# self.assertEqual(response.status_code, 401)
|
||||
# self.assertEqual(response.status_int, 401)
|
||||
|
||||
def test_authenticated(self):
|
||||
response = self.get_json('/sources',
|
||||
@ -79,4 +79,4 @@ class TestAPIACL(FunctionalTest):
|
||||
"X-Tenant-Name": "admin",
|
||||
"X-Tenant-Id": "bc23a9d531064583ace8f67dad60f6bb",
|
||||
})
|
||||
self.assertEqual(response.status_code, 200)
|
||||
self.assertEqual(response.status_int, 200)
|
||||
|
@ -64,10 +64,12 @@ class TestComputeDurationByResource(FunctionalTest):
|
||||
def _invoke_api(self):
|
||||
return self.get_json(
|
||||
'/resources/resource-id/meters/instance:m1.tiny/duration',
|
||||
start_timestamp=self.start.isoformat(),
|
||||
end_timestamp=self.end.isoformat(),
|
||||
search_offset=10, # this value doesn't matter, db call is mocked
|
||||
)
|
||||
extra_params={
|
||||
'daterange.start': self.start.isoformat(),
|
||||
'daterange.end': self.end.isoformat(),
|
||||
# this value doesn't matter, db call is mocked
|
||||
'daterange.search_offset': 10,
|
||||
})
|
||||
|
||||
def test_before_range(self):
|
||||
self._set_interval(self.early1, self.early2)
|
||||
@ -124,9 +126,11 @@ class TestComputeDurationByResource(FunctionalTest):
|
||||
self._stub_interval_func(get_interval)
|
||||
data = self.get_json(
|
||||
'/resources/resource-id/meters/instance:m1.tiny/duration',
|
||||
start_timestamp=self.late1.isoformat(),
|
||||
search_offset=10, # this value doesn't matter, db call is mocked
|
||||
)
|
||||
extra_params={
|
||||
'daterange.start': self.late1.isoformat(),
|
||||
# this value doesn't matter, db call is mocked
|
||||
'daterange.search_offset': 10,
|
||||
})
|
||||
self._assert_times_match(data['start_timestamp'], self.late1)
|
||||
self._assert_times_match(data['end_timestamp'], self.late2)
|
||||
|
||||
@ -136,8 +140,10 @@ class TestComputeDurationByResource(FunctionalTest):
|
||||
self._stub_interval_func(get_interval)
|
||||
data = self.get_json(
|
||||
'/resources/resource-id/meters/instance:m1.tiny/duration',
|
||||
end_timestamp=self.early2.isoformat(),
|
||||
search_offset=10, # this value doesn't matter, db call is mocked
|
||||
)
|
||||
extra_params={
|
||||
'daterange.end': self.early2.isoformat(),
|
||||
# this value doesn't matter, db call is mocked
|
||||
'daterange.search_offset': 10,
|
||||
})
|
||||
self._assert_times_match(data['start_timestamp'], self.early1)
|
||||
self._assert_times_match(data['end_timestamp'], self.early2)
|
||||
|
@ -24,10 +24,10 @@ import datetime
|
||||
from ceilometer.api.controllers import v2 as api
|
||||
|
||||
|
||||
class TimestampTest(unittest.TestCase):
|
||||
class DateRangeTest(unittest.TestCase):
|
||||
|
||||
def test_get_query_timestamps_none_specified(self):
|
||||
result = api._get_query_timestamps()
|
||||
result = api.DateRange().to_dict()
|
||||
expected = {'start_timestamp': None,
|
||||
'end_timestamp': None,
|
||||
'query_start': None,
|
||||
@ -38,8 +38,8 @@ class TimestampTest(unittest.TestCase):
|
||||
assert result == expected
|
||||
|
||||
def test_get_query_timestamps_start(self):
|
||||
args = {'start_timestamp': '2012-09-20T12:13:14'}
|
||||
result = api._get_query_timestamps(args)
|
||||
d = datetime.datetime(2012, 9, 20, 12, 13, 14)
|
||||
result = api.DateRange(start=d).to_dict()
|
||||
expected = {
|
||||
'start_timestamp': datetime.datetime(2012, 9, 20, 12, 13, 14),
|
||||
'end_timestamp': None,
|
||||
@ -51,8 +51,8 @@ class TimestampTest(unittest.TestCase):
|
||||
assert result == expected
|
||||
|
||||
def test_get_query_timestamps_end(self):
|
||||
args = {'end_timestamp': '2012-09-20T12:13:14'}
|
||||
result = api._get_query_timestamps(args)
|
||||
d = datetime.datetime(2012, 9, 20, 12, 13, 14)
|
||||
result = api.DateRange(end=d).to_dict()
|
||||
expected = {
|
||||
'end_timestamp': datetime.datetime(2012, 9, 20, 12, 13, 14),
|
||||
'start_timestamp': None,
|
||||
@ -64,11 +64,11 @@ class TimestampTest(unittest.TestCase):
|
||||
assert result == expected
|
||||
|
||||
def test_get_query_timestamps_with_offset(self):
|
||||
args = {'start_timestamp': '2012-09-20T12:13:14',
|
||||
'end_timestamp': '2012-09-20T13:24:25',
|
||||
'search_offset': '20',
|
||||
}
|
||||
result = api._get_query_timestamps(args)
|
||||
result = api.DateRange(
|
||||
end=datetime.datetime(2012, 9, 20, 13, 24, 25),
|
||||
start=datetime.datetime(2012, 9, 20, 12, 13, 14),
|
||||
search_offset=20,
|
||||
).to_dict()
|
||||
expected = {
|
||||
'query_end': datetime.datetime(2012, 9, 20, 13, 44, 25),
|
||||
'query_start': datetime.datetime(2012, 9, 20, 11, 53, 14),
|
@ -95,7 +95,7 @@ class TestListEvents(FunctionalTest):
|
||||
def test_empty_source(self):
|
||||
data = self.get_json('/sources/no-such-source/meters/instance',
|
||||
expect_errors=True)
|
||||
self.assertEquals(data.status_code, 404)
|
||||
self.assertEquals(data.status_int, 404)
|
||||
|
||||
def test_by_source(self):
|
||||
data = self.get_json('/sources/test_source/meters/instance')
|
||||
|
@ -40,7 +40,7 @@ class TestListSource(FunctionalTest):
|
||||
'/sources/test_source_that_does_not_exist',
|
||||
expect_errors=True)
|
||||
print 'GOT:', ydata
|
||||
self.assertEqual(ydata.status_code, 404)
|
||||
self.assertEqual(ydata.status_int, 404)
|
||||
self.assert_(
|
||||
"No source test_source_that_does_not_exist" in
|
||||
ydata.json['error_message']
|
||||
|
@ -64,32 +64,37 @@ class TestMaxProjectVolume(FunctionalTest):
|
||||
self.assertEqual(data, expected)
|
||||
|
||||
def test_start_timestamp(self):
|
||||
data = self.get_json(self.PATH,
|
||||
start_timestamp='2012-09-25T11:30:00')
|
||||
data = self.get_json(
|
||||
self.PATH,
|
||||
extra_params={'daterange.start': '2012-09-25T11:30:00'})
|
||||
expected = {'volume': 7}
|
||||
self.assertEqual(data, expected)
|
||||
|
||||
def test_start_timestamp_after(self):
|
||||
data = self.get_json(self.PATH,
|
||||
start_timestamp='2012-09-25T12:34:00')
|
||||
data = self.get_json(
|
||||
self.PATH,
|
||||
extra_params={'daterange.start': '2012-09-25T12:34:00'})
|
||||
expected = {'volume': None}
|
||||
self.assertEqual(data, expected)
|
||||
|
||||
def test_end_timestamp(self):
|
||||
data = self.get_json(self.PATH,
|
||||
end_timestamp='2012-09-25T11:30:00')
|
||||
data = self.get_json(
|
||||
self.PATH,
|
||||
extra_params={'daterange.end': '2012-09-25T11:30:00'})
|
||||
expected = {'volume': 5}
|
||||
self.assertEqual(data, expected)
|
||||
|
||||
def test_end_timestamp_before(self):
|
||||
data = self.get_json(self.PATH,
|
||||
end_timestamp='2012-09-25T09:54:00')
|
||||
data = self.get_json(
|
||||
self.PATH,
|
||||
extra_params={'daterange.end': '2012-09-25T09:54:00'})
|
||||
expected = {'volume': None}
|
||||
self.assertEqual(data, expected)
|
||||
|
||||
def test_start_end_timestamp(self):
|
||||
data = self.get_json(self.PATH,
|
||||
start_timestamp='2012-09-25T11:30:00',
|
||||
end_timestamp='2012-09-25T11:32:00')
|
||||
data = self.get_json(
|
||||
self.PATH,
|
||||
extra_params={'daterange.start': '2012-09-25T11:30:00',
|
||||
'daterange.end': '2012-09-25T11:32:00'})
|
||||
expected = {'volume': 6}
|
||||
self.assertEqual(data, expected)
|
||||
|
@ -63,32 +63,37 @@ class TestMaxResourceVolume(FunctionalTest):
|
||||
assert data == expected
|
||||
|
||||
def test_start_timestamp(self):
|
||||
data = self.get_json(self.PATH,
|
||||
start_timestamp='2012-09-25T11:30:00')
|
||||
data = self.get_json(
|
||||
self.PATH,
|
||||
extra_params={'daterange.start': '2012-09-25T11:30:00'})
|
||||
expected = {'volume': 7}
|
||||
assert data == expected
|
||||
|
||||
def test_start_timestamp_after(self):
|
||||
data = self.get_json(self.PATH,
|
||||
start_timestamp='2012-09-25T12:34:00')
|
||||
data = self.get_json(
|
||||
self.PATH,
|
||||
extra_params={'daterange.start': '2012-09-25T12:34:00'})
|
||||
expected = {'volume': None}
|
||||
assert data == expected
|
||||
|
||||
def test_end_timestamp(self):
|
||||
data = self.get_json(self.PATH,
|
||||
end_timestamp='2012-09-25T11:30:00')
|
||||
data = self.get_json(
|
||||
self.PATH,
|
||||
extra_params={'daterange.end': '2012-09-25T11:30:00'})
|
||||
expected = {'volume': 5}
|
||||
assert data == expected
|
||||
|
||||
def test_end_timestamp_before(self):
|
||||
data = self.get_json(self.PATH,
|
||||
end_timestamp='2012-09-25T09:54:00')
|
||||
data = self.get_json(
|
||||
self.PATH,
|
||||
extra_params={'daterange.end': '2012-09-25T09:54:00'})
|
||||
expected = {'volume': None}
|
||||
assert data == expected
|
||||
|
||||
def test_start_end_timestamp(self):
|
||||
data = self.get_json(self.PATH,
|
||||
start_timestamp='2012-09-25T11:30:00',
|
||||
end_timestamp='2012-09-25T11:32:00')
|
||||
data = self.get_json(
|
||||
self.PATH,
|
||||
extra_params={'daterange.start': '2012-09-25T11:30:00',
|
||||
'daterange.end': '2012-09-25T11:32:00'})
|
||||
expected = {'volume': 6}
|
||||
assert data == expected
|
||||
|
@ -63,32 +63,37 @@ class TestSumProjectVolume(FunctionalTest):
|
||||
assert data == expected
|
||||
|
||||
def test_start_timestamp(self):
|
||||
data = self.get_json(self.PATH,
|
||||
start_timestamp='2012-09-25T11:30:00')
|
||||
data = self.get_json(
|
||||
self.PATH,
|
||||
extra_params={'daterange.start': '2012-09-25T11:30:00'})
|
||||
expected = {'volume': 6 + 7}
|
||||
assert data == expected
|
||||
|
||||
def test_start_timestamp_after(self):
|
||||
data = self.get_json(self.PATH,
|
||||
start_timestamp='2012-09-25T12:34:00')
|
||||
data = self.get_json(
|
||||
self.PATH,
|
||||
extra_params={'daterange.start': '2012-09-25T12:34:00'})
|
||||
expected = {'volume': None}
|
||||
assert data == expected
|
||||
|
||||
def test_end_timestamp(self):
|
||||
data = self.get_json(self.PATH,
|
||||
end_timestamp='2012-09-25T11:30:00')
|
||||
data = self.get_json(
|
||||
self.PATH,
|
||||
extra_params={'daterange.end': '2012-09-25T11:30:00'})
|
||||
expected = {'volume': 5}
|
||||
assert data == expected
|
||||
|
||||
def test_end_timestamp_before(self):
|
||||
data = self.get_json(self.PATH,
|
||||
end_timestamp='2012-09-25T09:54:00')
|
||||
data = self.get_json(
|
||||
self.PATH,
|
||||
extra_params={'daterange.end': '2012-09-25T09:54:00'})
|
||||
expected = {'volume': None}
|
||||
assert data == expected
|
||||
|
||||
def test_start_end_timestamp(self):
|
||||
data = self.get_json(self.PATH,
|
||||
start_timestamp='2012-09-25T11:30:00',
|
||||
end_timestamp='2012-09-25T11:32:00')
|
||||
data = self.get_json(
|
||||
self.PATH,
|
||||
extra_params={'daterange.start': '2012-09-25T11:30:00',
|
||||
'daterange.end': '2012-09-25T11:32:00'})
|
||||
expected = {'volume': 6}
|
||||
assert data == expected
|
||||
|
@ -63,32 +63,37 @@ class TestSumResourceVolume(FunctionalTest):
|
||||
assert data == expected
|
||||
|
||||
def test_start_timestamp(self):
|
||||
data = self.get_json(self.PATH,
|
||||
start_timestamp='2012-09-25T11:30:00')
|
||||
data = self.get_json(
|
||||
self.PATH,
|
||||
extra_params={'daterange.start': '2012-09-25T11:30:00'})
|
||||
expected = {'volume': 6 + 7}
|
||||
assert data == expected
|
||||
|
||||
def test_start_timestamp_after(self):
|
||||
data = self.get_json(self.PATH,
|
||||
start_timestamp='2012-09-25T12:34:00')
|
||||
data = self.get_json(
|
||||
self.PATH,
|
||||
extra_params={'daterange.start': '2012-09-25T12:34:00'})
|
||||
expected = {'volume': None}
|
||||
assert data == expected
|
||||
|
||||
def test_end_timestamp(self):
|
||||
data = self.get_json(self.PATH,
|
||||
end_timestamp='2012-09-25T11:30:00')
|
||||
data = self.get_json(
|
||||
self.PATH,
|
||||
extra_params={'daterange.end': '2012-09-25T11:30:00'})
|
||||
expected = {'volume': 5}
|
||||
assert data == expected
|
||||
|
||||
def test_end_timestamp_before(self):
|
||||
data = self.get_json(self.PATH,
|
||||
end_timestamp='2012-09-25T09:54:00')
|
||||
data = self.get_json(
|
||||
self.PATH,
|
||||
extra_params={'daterange.end': '2012-09-25T09:54:00'})
|
||||
expected = {'volume': None}
|
||||
assert data == expected
|
||||
|
||||
def test_start_end_timestamp(self):
|
||||
data = self.get_json(self.PATH,
|
||||
start_timestamp='2012-09-25T11:30:00',
|
||||
end_timestamp='2012-09-25T11:32:00')
|
||||
data = self.get_json(
|
||||
self.PATH,
|
||||
extra_params={'daterange.start': '2012-09-25T11:30:00',
|
||||
'daterange.end': '2012-09-25T11:32:00'})
|
||||
expected = {'volume': 6}
|
||||
assert data == expected
|
||||
|
@ -26,7 +26,7 @@ pecan
|
||||
swift
|
||||
# Swift dep that is not necessary if we depend on swift>1.7.5
|
||||
netifaces
|
||||
|
||||
# Docs Requirements
|
||||
sphinx
|
||||
docutils==0.9.1 # for bug 1091333, remove after sphinx >1.1.3 is released.
|
||||
python-spidermonkey
|
||||
|
@ -25,3 +25,4 @@ pecan
|
||||
http://tarballs.openstack.org/swift/swift-stable-folsom.tar.gz
|
||||
# Swift dep that is not necessary if we depend on swift>1.7.5
|
||||
netifaces
|
||||
python-spidermonkey
|
||||
|
Loading…
x
Reference in New Issue
Block a user