def test_etag_set_etag_in_response(self, app, schemas, paginate): etag_schema = schemas.DocEtagSchema item = {'item_id': 1, 'db_field': 0} extra_data = ('Dummy pagination header', ) if paginate else tuple() etag = _generate_etag(item, extra_data=extra_data) etag_with_schema = _generate_etag(item, etag_schema, extra_data=extra_data) with app.test_request_context('/'): resp = Response() if extra_data: resp.headers['X-Pagination'] = 'Dummy pagination header' if is_etag_enabled(app): set_etag_in_response(resp, item, None) assert resp.get_etag() == (etag, False) set_etag_in_response(resp, item, etag_schema) assert resp.get_etag() == (etag_with_schema, False) else: set_etag_in_response(resp, item, None) assert resp.get_etag() == (None, None) set_etag_in_response(resp, item, etag_schema) assert resp.get_etag() == (None, None) disable_etag_for_request() resp = Response() set_etag_in_response(resp, item, None) assert resp.get_etag() == (None, None) set_etag_in_response(resp, item, etag_schema) assert resp.get_etag() == (None, None)
def test_etag_check_etag(self, app, schemas): etag_schema = schemas.DocEtagSchema old_item = {'item_id': 1, 'db_field': 0} new_item = {'item_id': 1, 'db_field': 1} old_etag = _generate_etag(old_item) old_etag_with_schema = _generate_etag(old_item, etag_schema) with app.test_request_context('/', headers={'If-Match': old_etag}): check_etag(old_item) if is_etag_enabled(app): with pytest.raises(PreconditionFailed): check_etag(new_item) else: check_etag(new_item) disable_etag_for_request() check_etag(old_item) check_etag(new_item) with app.test_request_context( '/', headers={'If-Match': old_etag_with_schema}): check_etag(old_item, etag_schema) if is_etag_enabled(app): with pytest.raises(PreconditionFailed): check_etag(new_item, etag_schema) else: check_etag(new_item) disable_etag_for_request() check_etag(old_item) check_etag(new_item)
def test_etag_set_etag(self, app, schemas): etag_schema = schemas.DocEtagSchema item = {'item_id': 1, 'db_field': 0} etag = _generate_etag(item) etag_with_schema = _generate_etag(item, etag_schema) with app.test_request_context('/'): set_etag(item) if is_etag_enabled(app): assert _get_etag_ctx()['etag'] == etag del _get_etag_ctx()['etag'] else: assert 'etag' not in _get_etag_ctx() disable_etag_for_request() set_etag(item) assert 'etag' not in _get_etag_ctx() with app.test_request_context('/', headers={'If-None-Match': etag}): if is_etag_enabled(app): with pytest.raises(NotModified): set_etag(item) else: set_etag(item) assert 'etag' not in _get_etag_ctx() disable_etag_for_request() set_etag(item) assert 'etag' not in _get_etag_ctx() with app.test_request_context( '/', headers={'If-None-Match': etag_with_schema}): if is_etag_enabled(app): with pytest.raises(NotModified): set_etag(item, etag_schema) else: set_etag(item, etag_schema) assert 'etag' not in _get_etag_ctx() disable_etag_for_request() set_etag(item, etag_schema) assert 'etag' not in _get_etag_ctx() with app.test_request_context('/', headers={'If-None-Match': 'dummy'}): if is_etag_enabled(app): set_etag(item) assert _get_etag_ctx()['etag'] == etag del _get_etag_ctx()['etag'] set_etag(item, etag_schema) assert _get_etag_ctx()['etag'] == etag_with_schema del _get_etag_ctx()['etag'] else: set_etag(item) assert 'etag' not in _get_etag_ctx() set_etag(item, etag_schema) assert 'etag' not in _get_etag_ctx() disable_etag_for_request() set_etag(item) assert 'etag' not in _get_etag_ctx() set_etag(item, etag_schema) assert 'etag' not in _get_etag_ctx()
def test_etag_verify_check_etag_warning(self, app, method): old_item = {'item_id': 1, 'db_field': 0} old_etag = _generate_etag(old_item) with mock.patch.object(app.logger, 'warning') as mock_warning: with app.test_request_context('/', method=method, headers={'If-Match': old_etag}): verify_check_etag() if (is_etag_enabled(app) and method in ['PUT', 'PATCH', 'DELETE']): assert mock_warning.called mock_warning.reset_mock() else: assert not mock_warning.called check_etag(old_item) verify_check_etag() assert not mock_warning.called disable_etag_for_request() verify_check_etag() assert not mock_warning.called check_etag(old_item) verify_check_etag() assert not mock_warning.called
def test_etag_generate_etag(self, schemas, extra_data): etag_schema = schemas.DocEtagSchema item = {'item_id': 1, 'db_field': 0} item_schema_dump = etag_schema().dump(item)[0] if extra_data is None or extra_data == {}: data = item data_dump = item_schema_dump else: data = (item, extra_data) data_dump = (item_schema_dump, extra_data) etag = _generate_etag(item, extra_data=extra_data) assert etag == hashlib.sha1( bytes(json.dumps(data, sort_keys=True), 'utf-8')).hexdigest() etag = _generate_etag(item, etag_schema, extra_data=extra_data) assert etag == hashlib.sha1( bytes(json.dumps(data_dump, sort_keys=True), 'utf-8')).hexdigest() etag = _generate_etag(item, etag_schema(), extra_data=extra_data) assert etag == hashlib.sha1( bytes(json.dumps(data_dump, sort_keys=True), 'utf-8')).hexdigest()
def test_etag_is_deterministic(self): """Check etag computation is deterministic _generate_etag should return the same value everytime the same dictionary is passed. This is not obvious since dictionaries are unordered by design. We check this by feeding it different OrderedDict instances that are equivalent to the same dictionary. """ data = OrderedDict([('a', 1), ('b', 2), ('c', OrderedDict([('a', 1), ('b', 2)]))]) etag = _generate_etag(data) data_copies = [ OrderedDict([ ('b', 2), ('a', 1), ('c', OrderedDict([('a', 1), ('b', 2)])), ]), OrderedDict([ ('a', 1), ('b', 2), ('c', OrderedDict([('b', 2), ('a', 1)])), ]), OrderedDict([ ('a', 1), ('c', OrderedDict([('a', 1), ('b', 2)])), ('b', 2), ]), OrderedDict([ ('c', OrderedDict([('a', 1), ('b', 2)])), ('b', 2), ('a', 1), ]), ] data_copies_etag = [_generate_etag(d) for d in data_copies] assert all(e == etag for e in data_copies_etag)