@@ -141,6 +141,73 @@ def next(self):
141141 raw = True ,
142142 )
143143
144+ @staticmethod
145+ @pytest .mark .usefixtures ("in_context" )
146+ @mock .patch ("google.cloud.ndb._datastore_query._datastore_run_query" )
147+ def test_count_by_skipping_w_a_result (run_query ):
148+ # These results should technically be impossible, but better safe than sorry.
149+ run_query .side_effect = utils .future_results (
150+ mock .Mock (
151+ batch = mock .Mock (
152+ more_results = _datastore_query .NOT_FINISHED ,
153+ skipped_results = 1000 ,
154+ entity_results = [],
155+ end_cursor = b"dontlookatme" ,
156+ skipped_cursor = b"himom" ,
157+ spec = (
158+ "more_results" ,
159+ "skipped_results" ,
160+ "entity_results" ,
161+ "end_cursor" ,
162+ ),
163+ ),
164+ spec = ("batch" ,),
165+ ),
166+ mock .Mock (
167+ batch = mock .Mock (
168+ more_results = _datastore_query .NO_MORE_RESULTS ,
169+ skipped_results = 99 ,
170+ entity_results = [object ()],
171+ end_cursor = b"ohhaithere" ,
172+ skipped_cursor = b"hellodad" ,
173+ spec = (
174+ "more_results" ,
175+ "skipped_results" ,
176+ "entity_results" ,
177+ "end_cursor" ,
178+ "skipped_cursor" ,
179+ ),
180+ ),
181+ spec = ("batch" ,),
182+ ),
183+ )
184+
185+ query = query_module .QueryOptions ()
186+ future = _datastore_query .count (query )
187+ assert future .result () == 1100
188+
189+ expected = [
190+ mock .call (
191+ query_module .QueryOptions (
192+ limit = 1 ,
193+ offset = 10000 ,
194+ projection = ["__key__" ],
195+ )
196+ ),
197+ (
198+ (
199+ query_module .QueryOptions (
200+ limit = 1 ,
201+ offset = 10000 ,
202+ projection = ["__key__" ],
203+ start_cursor = _datastore_query .Cursor (b"himom" ),
204+ ),
205+ ),
206+ {},
207+ ),
208+ ]
209+ assert run_query .call_args_list == expected
210+
144211 @staticmethod
145212 @pytest .mark .usefixtures ("in_context" )
146213 @mock .patch ("google.cloud.ndb._datastore_query._datastore_run_query" )
@@ -151,7 +218,8 @@ def test_count_by_skipping(run_query):
151218 more_results = _datastore_query .NOT_FINISHED ,
152219 skipped_results = 1000 ,
153220 entity_results = [],
154- end_cursor = b"himom" ,
221+ end_cursor = b"dontlookatme" ,
222+ skipped_cursor = b"himom" ,
155223 spec = (
156224 "more_results" ,
157225 "skipped_results" ,
@@ -166,12 +234,14 @@ def test_count_by_skipping(run_query):
166234 more_results = _datastore_query .NO_MORE_RESULTS ,
167235 skipped_results = 100 ,
168236 entity_results = [],
169- end_cursor = b"hellodad" ,
237+ end_cursor = b"nopenuhuh" ,
238+ skipped_cursor = b"hellodad" ,
170239 spec = (
171240 "more_results" ,
172241 "skipped_results" ,
173242 "entity_results" ,
174243 "end_cursor" ,
244+ "skipped_cursor" ,
175245 ),
176246 ),
177247 spec = ("batch" ,),
@@ -204,6 +274,106 @@ def test_count_by_skipping(run_query):
204274 ]
205275 assert run_query .call_args_list == expected
206276
277+ @staticmethod
278+ @pytest .mark .usefixtures ("in_context" )
279+ @mock .patch ("google.cloud.ndb._datastore_query._datastore_run_query" )
280+ def test_count_by_skipping_emulator (run_query ):
281+ """Regression test for #525
282+
283+ Test differences between emulator and the real Datastore.
284+
285+ https://github.com/googleapis/python-ndb/issues/525
286+ """
287+ run_query .side_effect = utils .future_results (
288+ mock .Mock (
289+ batch = mock .Mock (
290+ more_results = _datastore_query .MORE_RESULTS_AFTER_LIMIT ,
291+ skipped_results = 1000 ,
292+ entity_results = [],
293+ end_cursor = b"dontlookatme" ,
294+ skipped_cursor = b"himom" ,
295+ spec = (
296+ "more_results" ,
297+ "skipped_results" ,
298+ "entity_results" ,
299+ "end_cursor" ,
300+ ),
301+ ),
302+ spec = ("batch" ,),
303+ ),
304+ mock .Mock (
305+ batch = mock .Mock (
306+ more_results = _datastore_query .MORE_RESULTS_AFTER_LIMIT ,
307+ skipped_results = 100 ,
308+ entity_results = [],
309+ end_cursor = b"nopenuhuh" ,
310+ skipped_cursor = b"hellodad" ,
311+ spec = (
312+ "more_results" ,
313+ "skipped_results" ,
314+ "entity_results" ,
315+ "end_cursor" ,
316+ "skipped_cursor" ,
317+ ),
318+ ),
319+ spec = ("batch" ,),
320+ ),
321+ mock .Mock (
322+ batch = mock .Mock (
323+ more_results = _datastore_query .MORE_RESULTS_AFTER_LIMIT ,
324+ skipped_results = 0 ,
325+ entity_results = [],
326+ end_cursor = b"nopenuhuh" ,
327+ skipped_cursor = b"hellodad" ,
328+ spec = (
329+ "more_results" ,
330+ "skipped_results" ,
331+ "entity_results" ,
332+ "end_cursor" ,
333+ "skipped_cursor" ,
334+ ),
335+ ),
336+ spec = ("batch" ,),
337+ ),
338+ )
339+
340+ query = query_module .QueryOptions ()
341+ future = _datastore_query .count (query )
342+ assert future .result () == 1100
343+
344+ expected = [
345+ mock .call (
346+ query_module .QueryOptions (
347+ limit = 1 ,
348+ offset = 10000 ,
349+ projection = ["__key__" ],
350+ )
351+ ),
352+ (
353+ (
354+ query_module .QueryOptions (
355+ limit = 1 ,
356+ offset = 10000 ,
357+ projection = ["__key__" ],
358+ start_cursor = _datastore_query .Cursor (b"himom" ),
359+ ),
360+ ),
361+ {},
362+ ),
363+ (
364+ (
365+ query_module .QueryOptions (
366+ limit = 1 ,
367+ offset = 10000 ,
368+ projection = ["__key__" ],
369+ start_cursor = _datastore_query .Cursor (b"hellodad" ),
370+ ),
371+ ),
372+ {},
373+ ),
374+ ]
375+ assert run_query .call_args_list == expected
376+
207377 @staticmethod
208378 @pytest .mark .usefixtures ("in_context" )
209379 @mock .patch ("google.cloud.ndb._datastore_query._datastore_run_query" )
0 commit comments