1 # Copyright (C) The Arvados Authors. All rights reserved.
3 # SPDX-License-Identifier: Apache-2.0
11 from unittest import mock
16 class KeysetTestHelper:
17 def __init__(self, expect, expect_num_retries=0):
20 self.expect_num_retries = expect_num_retries
22 def fn(self, **kwargs):
23 assert kwargs == self.expect[self.n][0]
26 def execute(self, num_retries):
27 assert num_retries == self.expect_num_retries
29 return self.expect[self.n-1][1]
32 'uuid': 'zzzzz-zyyyz-zzzzzyyyyywwwww',
33 'name': 'KeysetListAllTestCase.test_select mock',
34 'created_at': '2023-08-28T12:34:56.123456Z',
37 _FAKE_COMPUTED_PERMISSIONS_ITEM = {
38 'user_uuid': 'zzzzz-zyyyz-zzzzzyyyyywwwww',
39 'target_uuid': 'zzzzz-ttttt-xxxxxyyyyyzzzzz',
40 'perm_level': 'can_write',
43 class KeysetListAllTestCase(unittest.TestCase):
45 ks = KeysetTestHelper([[
46 {"limit": 1000, "count": "none", "order": ["created_at asc", "uuid asc"], "filters": []},
50 ls = list(arvados.util.keyset_list_all(ks.fn))
51 self.assertEqual(ls, [])
53 def test_oneitem(self):
54 ks = KeysetTestHelper([[
55 {"limit": 1000, "count": "none", "order": ["created_at asc", "uuid asc"], "filters": []},
56 {"items": [{"created_at": "1", "uuid": "1"}]}
58 {"limit": 1000, "count": "none", "order": ["created_at asc", "uuid asc"], "filters": [["created_at", "=", "1"], ["uuid", ">", "1"]]},
61 {"limit": 1000, "count": "none", "order": ["created_at asc", "uuid asc"], "filters": [["created_at", ">", "1"]]},
65 ls = list(arvados.util.keyset_list_all(ks.fn))
66 self.assertEqual(ls, [{"created_at": "1", "uuid": "1"}])
68 def test_onepage2(self):
69 ks = KeysetTestHelper([[
70 {"limit": 1000, "count": "none", "order": ["created_at asc", "uuid asc"], "filters": []},
71 {"items": [{"created_at": "1", "uuid": "1"}, {"created_at": "2", "uuid": "2"}]}
73 {"limit": 1000, "count": "none", "order": ["created_at asc", "uuid asc"], "filters": [["created_at", ">=", "2"], ["uuid", "!=", "2"]]},
77 ls = list(arvados.util.keyset_list_all(ks.fn))
78 self.assertEqual(ls, [{"created_at": "1", "uuid": "1"}, {"created_at": "2", "uuid": "2"}])
80 def test_onepage3(self):
81 ks = KeysetTestHelper([[
82 {"limit": 1000, "count": "none", "order": ["created_at asc", "uuid asc"], "filters": []},
83 {"items": [{"created_at": "1", "uuid": "1"}, {"created_at": "2", "uuid": "2"}, {"created_at": "3", "uuid": "3"}]}
85 {"limit": 1000, "count": "none", "order": ["created_at asc", "uuid asc"], "filters": [["created_at", ">=", "3"], ["uuid", "!=", "3"]]},
89 ls = list(arvados.util.keyset_list_all(ks.fn))
90 self.assertEqual(ls, [{"created_at": "1", "uuid": "1"}, {"created_at": "2", "uuid": "2"}, {"created_at": "3", "uuid": "3"}])
93 def test_twopage(self):
94 ks = KeysetTestHelper([[
95 {"limit": 1000, "count": "none", "order": ["created_at asc", "uuid asc"], "filters": []},
96 {"items": [{"created_at": "1", "uuid": "1"}, {"created_at": "2", "uuid": "2"}]}
98 {"limit": 1000, "count": "none", "order": ["created_at asc", "uuid asc"], "filters": [["created_at", ">=", "2"], ["uuid", "!=", "2"]]},
99 {"items": [{"created_at": "3", "uuid": "3"}, {"created_at": "4", "uuid": "4"}]}
101 {"limit": 1000, "count": "none", "order": ["created_at asc", "uuid asc"], "filters": [["created_at", ">=", "4"], ["uuid", "!=", "4"]]},
105 ls = list(arvados.util.keyset_list_all(ks.fn))
106 self.assertEqual(ls, [{"created_at": "1", "uuid": "1"},
107 {"created_at": "2", "uuid": "2"},
108 {"created_at": "3", "uuid": "3"},
109 {"created_at": "4", "uuid": "4"}
112 def test_repeated_key(self):
113 ks = KeysetTestHelper([[
114 {"limit": 1000, "count": "none", "order": ["created_at asc", "uuid asc"], "filters": []},
115 {"items": [{"created_at": "1", "uuid": "1"}, {"created_at": "2", "uuid": "2"}, {"created_at": "2", "uuid": "3"}]}
117 {"limit": 1000, "count": "none", "order": ["created_at asc", "uuid asc"], "filters": [["created_at", ">=", "2"], ["uuid", "!=", "3"]]},
118 {"items": [{"created_at": "2", "uuid": "2"}, {"created_at": "2", "uuid": "4"}]}
120 {"limit": 1000, "count": "none", "order": ["created_at asc", "uuid asc"], "filters": [["created_at", "=", "2"], ["uuid", ">", "4"]]},
123 {"limit": 1000, "count": "none", "order": ["created_at asc", "uuid asc"], "filters": [["created_at", ">", "2"]]},
124 {"items": [{"created_at": "3", "uuid": "5"}, {"created_at": "4", "uuid": "6"}]}
126 {"limit": 1000, "count": "none", "order": ["created_at asc", "uuid asc"], "filters": [["created_at", ">=", "4"], ["uuid", "!=", "6"]]},
131 ls = list(arvados.util.keyset_list_all(ks.fn))
132 self.assertEqual(ls, [{"created_at": "1", "uuid": "1"},
133 {"created_at": "2", "uuid": "2"},
134 {"created_at": "2", "uuid": "3"},
135 {"created_at": "2", "uuid": "4"},
136 {"created_at": "3", "uuid": "5"},
137 {"created_at": "4", "uuid": "6"}
140 def test_onepage_withfilter(self):
141 ks = KeysetTestHelper([[
142 {"limit": 1000, "count": "none", "order": ["created_at asc", "uuid asc"], "filters": [["foo", ">", "bar"]]},
143 {"items": [{"created_at": "1", "uuid": "1"}, {"created_at": "2", "uuid": "2"}]}
145 {"limit": 1000, "count": "none", "order": ["created_at asc", "uuid asc"], "filters": [["created_at", ">=", "2"], ["uuid", "!=", "2"], ["foo", ">", "bar"]]},
149 ls = list(arvados.util.keyset_list_all(ks.fn, filters=[["foo", ">", "bar"]]))
150 self.assertEqual(ls, [{"created_at": "1", "uuid": "1"}, {"created_at": "2", "uuid": "2"}])
152 def test_onepage_desc(self):
153 ks = KeysetTestHelper([[
154 {"limit": 1000, "count": "none", "order": ["created_at desc", "uuid desc"], "filters": []},
155 {"items": [{"created_at": "2", "uuid": "2"}, {"created_at": "1", "uuid": "1"}]}
157 {"limit": 1000, "count": "none", "order": ["created_at desc", "uuid desc"], "filters": [["created_at", "<=", "1"], ["uuid", "!=", "1"]]},
161 ls = list(arvados.util.keyset_list_all(ks.fn, ascending=False))
162 self.assertEqual(ls, [{"created_at": "2", "uuid": "2"}, {"created_at": "1", "uuid": "1"}])
164 @parameterized.parameterized.expand(
165 (fake_item, key_fields, order_key, select)
166 for (fake_item, key_fields) in [
167 (_SELECT_FAKE_ITEM, ('uuid',)),
168 (_FAKE_COMPUTED_PERMISSIONS_ITEM, ('user_uuid', 'target_uuid')),
170 for order_key in fake_item
171 if order_key != 'perm_level'
172 for count in range(len(fake_item) + 1)
173 for select in itertools.combinations(fake_item, count)
175 def test_select(self, fake_item, key_fields, order_key, select):
176 # keyset_list_all must have both uuid and order_key to function.
177 # Test that it selects those fields along with user-specified ones.
178 expect_select = {*key_fields, order_key, *select}
181 for key, value in fake_item.items()
182 if key in expect_select
184 list_func = mock.Mock()
185 list_func().execute = mock.Mock(
192 list_func.reset_mock()
193 actual = list(arvados.util.keyset_list_all(list_func, order_key, select=list(select), key_fields=key_fields))
194 self.assertEqual(actual, [item])
195 calls = list_func.call_args_list
196 self.assertTrue(len(calls) >= 2, "list_func() not called enough to exhaust items")
197 for args, kwargs in calls:
198 self.assertEqual(set(kwargs.get('select', ())), expect_select)