11import datetime
22from http import HTTPStatus
33import re
4- from typing import Optional
4+ from typing import Any , Optional
55
66import pytest
77import requests
1010from sqlalchemy .orm import aliased , Query
1111
1212from pbench .server import JSON , JSONARRAY , JSONOBJECT
13- from pbench .server .api .resources import APIAbort
13+ from pbench .server .api .resources import APIAbort , ApiParams
1414from pbench .server .api .resources .datasets_list import DatasetsList , urlencode_json
1515from pbench .server .database .database import Database
1616from pbench .server .database .models .datasets import Dataset , Metadata
@@ -129,17 +129,27 @@ def get_results(self, name_list: list[str], query: JSON, server_config) -> JSON:
129129 Returns:
130130 Paginated JSON object containing list of dataset values
131131 """
132+
133+ def convert (k : str , v : Any ) -> Any :
134+ if isinstance (v , str ) and k in ("filter" , "sort" , "metadata" ):
135+ return [v ]
136+ elif isinstance (v , int ):
137+ return str (v )
138+ else :
139+ return v
140+
132141 results : list [JSON ] = []
133- offset = query .get ("offset" , 0 )
142+ offset = int ( query .get ("offset" , "0" ) )
134143 limit = query .get ("limit" )
135144
136145 if limit :
137- next_offset = offset + limit
146+ next_offset = offset + int ( limit )
138147 paginated_name_list = name_list [offset :next_offset ]
139148 if next_offset >= len (name_list ):
149+ query ["offset" ] = str (len (name_list ))
140150 next_url = ""
141151 else :
142- query ["offset" ] = next_offset
152+ query ["offset" ] = str ( next_offset )
143153 next_url = (
144154 f"http://localhost{ server_config .rest_uri } /datasets?"
145155 + urlencode_json (query )
@@ -161,7 +171,15 @@ def get_results(self, name_list: list[str], query: JSON, server_config) -> JSON:
161171 },
162172 }
163173 )
164- return {"next_url" : next_url , "results" : results , "total" : len (name_list )}
174+ q1 = {k : convert (k , v ) for k , v in query .items ()}
175+ if "metadata" not in q1 :
176+ q1 ["metadata" ] = ["dataset.uploaded" ]
177+ return {
178+ "parameters" : q1 ,
179+ "next_url" : next_url ,
180+ "results" : results ,
181+ "total" : len (name_list ),
182+ }
165183
166184 def compare_results (
167185 self , result : JSONOBJECT , name_list : list [str ], query : JSON , server_config
@@ -190,8 +208,8 @@ def compare_results(
190208 (None , {}, ["fio_1" , "fio_2" ]),
191209 (None , {"access" : "public" }, ["fio_1" , "fio_2" ]),
192210 ("drb" , {"name" : "fio" }, ["fio_1" , "fio_2" ]),
193- ("drb" , {"name" : "fio" , "limit" : 1 }, ["fio_1" , "fio_2" ]),
194- ("drb" , {"name" : "fio" , "limit" : 1 , "offset" : 2 }, ["fio_1" , "fio_2" ]),
211+ ("drb" , {"name" : "fio" , "limit" : "1" }, ["fio_1" , "fio_2" ]),
212+ ("drb" , {"name" : "fio" , "limit" : 1 , "offset" : "2" }, ["fio_1" , "fio_2" ]),
195213 ("drb" , {"name" : "fio" , "offset" : 1 }, ["fio_1" , "fio_2" ]),
196214 ("drb" , {"name" : "fio" , "offset" : 2 }, ["fio_1" , "fio_2" ]),
197215 ("drb" , {"owner" : "drb" }, ["drb" , "fio_1" ]),
@@ -256,6 +274,17 @@ def compare_results(
256274 def test_dataset_list (self , server_config , query_as , login , query , results ):
257275 """Test `datasets/list` filters
258276
277+ NOTE: Several of these queries use the "limit" and/or "offset" options
278+ to test how the result set is segmented during pagination. These are
279+ represented in the parametrization above interchangeably as integers or
280+ strings. This is because (1) the actual input to the Pbench Server API
281+ is always in string form as a URI query parameter but (2) the requests
282+ package understands this and stringifies integer parameters while (3)
283+ the Pbench Server API framework recognizes these are integer values and
284+ presents them to the API code as integers. Mixing integer and string
285+ representation here must have no impact on the operation of the API so
286+ it's worth testing.
287+
259288 Args:
260289 server_config: The PbenchServerConfig object
261290 query_as: A fixture to provide a helper that executes the API call
@@ -311,7 +340,9 @@ def test_mine_novalue(self, server_config, client, more_datasets, get_token_func
311340 headers = headers ,
312341 )
313342 assert response .status_code == HTTPStatus .OK
314- self .compare_results (response .json , ["drb" , "fio_1" ], {}, server_config )
343+ self .compare_results (
344+ response .json , ["drb" , "fio_1" ], {"mine" : "" }, server_config
345+ )
315346
316347 @pytest .mark .parametrize (
317348 "login,query,results" ,
@@ -336,7 +367,7 @@ def test_dataset_paged_list(self, query_as, login, query, results, server_config
336367 results: A list of the dataset names we expect to be returned
337368 server_config: The PbenchServerConfig object
338369 """
339- query .update ({"metadata" : ["dataset.uploaded" ], "limit" : 5 })
370+ query .update ({"metadata" : ["dataset.uploaded" ], "limit" : "5" })
340371 result = query_as (query , login , HTTPStatus .OK )
341372 self .compare_results (result .json , results , query , server_config )
342373
@@ -384,6 +415,7 @@ def test_get_key_errors(self, query_as):
384415 )
385416 assert response .json == {
386417 "next_url" : "" ,
418+ "parameters" : {"metadata" : ["global.test.foo" ]},
387419 "results" : [
388420 {
389421 "metadata" : {"global.test.foo" : None },
@@ -444,6 +476,12 @@ def test_use_funk_metalog_keys(self, query_as):
444476 )
445477 assert response .json == {
446478 "next_url" : "" ,
479+ "parameters" : {
480+ "filter" : [
481+ "dataset.metalog.iterations/[email protected] _name:~10" 482+ ],
483+ "metadata" : ["dataset.metalog.iterations/fooBar=10-what_else@weird" ],
484+ },
447485 "results" : [
448486 {
449487 "metadata" : {
@@ -725,7 +763,7 @@ def test_mismatched_json_cast(self, query_as, server_config, query, results):
725763 "drb" ,
726764 HTTPStatus .OK ,
727765 )
728- self .compare_results (response .json , results , {}, server_config )
766+ self .compare_results (response .json , results , {"filter" : query }, server_config )
729767
730768 @pytest .mark .parametrize (
731769 "query,message" ,
@@ -769,7 +807,7 @@ def test_pagination_error(self, caplog, monkeypatch, query_as, exception, error)
769807 """
770808
771809 def do_error (
772- self , query : Query , json : JSONOBJECT , url : str
810+ self , query : Query , json : JSONOBJECT , raw_params : ApiParams , url : str
773811 ) -> tuple [JSONARRAY , JSONOBJECT ]:
774812 raise exception
775813
0 commit comments