1717from scim2_models import Resource
1818from scim2_models import ResourceType
1919from scim2_models import URIReference
20+ from scim2_models .utils import UNION_TYPES
2021
2122from scim2_tester .utils import CheckConfig
2223from scim2_tester .utils import CheckResult
@@ -34,8 +35,46 @@ def model_from_resource_type(
3435 return None
3536
3637
37- def fill_with_random_values (obj : Resource ) -> Resource :
38- for field_name , field in obj .model_fields .items ():
38+ def create_minimal_object (
39+ conf : CheckConfig , model : type [Resource ]
40+ ) -> tuple [Resource , list [Resource ]]:
41+ """Create an object filling with the minimum required field set."""
42+ field_names = [
43+ field_name
44+ for field_name in model .model_fields .keys ()
45+ if model .get_field_annotation (field_name , Required ) == Required .true
46+ ]
47+ obj , garbages = fill_with_random_values (conf , model (), field_names )
48+ obj = conf .client .create (obj )
49+ return obj , garbages
50+
51+
52+ def model_from_ref_type (
53+ conf : CheckConfig , ref_type : type , different_than : Resource
54+ ) -> type [Resource ]:
55+ def model_from_ref_type_ (ref_type ):
56+ if get_origin (ref_type ) in UNION_TYPES :
57+ return [
58+ model_from_ref_type_ (sub_ref_type )
59+ for sub_ref_type in get_args (ref_type )
60+ ]
61+
62+ model_name = get_args (ref_type )[0 ]
63+ model = conf .client .get_resource_model (model_name )
64+ return model
65+
66+ models = model_from_ref_type_ (ref_type )
67+ models = models if isinstance (models , list ) else [models ]
68+ acceptable_models = [model for model in models if model != different_than ]
69+ return acceptable_models [0 ]
70+
71+
72+ def fill_with_random_values (
73+ conf : CheckConfig , obj : Resource , field_names : list [str ] | None = None
74+ ) -> Resource :
75+ garbages = []
76+ for field_name in field_names or obj .model_fields .keys ():
77+ field = obj .model_fields [field_name ]
3978 if field .default :
4079 continue
4180
@@ -61,27 +100,28 @@ def fill_with_random_values(obj: Resource) -> Resource:
61100 value = base64 .b64encode (str (uuid .uuid4 ()).encode ("utf-8" ))
62101
63102 elif get_origin (field_type ) is Reference :
64- if get_args (field_type )[0 ] not in (
65- ExternalReference ,
66- URIReference ,
67- ):
68- if (
69- obj .__class__ .get_field_annotation (field_name , Required )
70- == Required .true
71- ):
72- return None
73- continue
74-
75- value = f"https://{ str (uuid .uuid4 ())} .test"
103+ ref_type = get_args (field_type )[0 ]
104+ if ref_type not in (ExternalReference , URIReference ):
105+ model = model_from_ref_type (
106+ conf , ref_type , different_than = obj .__class__
107+ )
108+ ref_obj , sub_garbages = create_minimal_object (conf , model )
109+ value = ref_obj .meta .location
110+ garbages += sub_garbages
111+
112+ else :
113+ value = f"https://{ str (uuid .uuid4 ())} .test"
76114
77115 elif isclass (field_type ) and issubclass (field_type , Enum ):
78116 value = random .choice (list (field_type ))
79117
80118 elif isclass (field_type ) and issubclass (field_type , ComplexAttribute ):
81- value = fill_with_random_values (field_type ())
119+ value , sub_garbages = fill_with_random_values (conf , field_type ())
120+ garbages += sub_garbages
82121
83122 elif isclass (field_type ) and issubclass (field_type , Extension ):
84- value = fill_with_random_values (field_type ())
123+ value , sub_garbages = fill_with_random_values (conf , field_type ())
124+ garbages += sub_garbages
85125
86126 else :
87127 # Put emails so this will be accepted by EmailStr too
@@ -93,7 +133,7 @@ def fill_with_random_values(obj: Resource) -> Resource:
93133 else :
94134 setattr (obj , field_name , value )
95135
96- return obj
136+ return obj , garbages
97137
98138
99139@checker
@@ -217,7 +257,9 @@ def check_resource_type(
217257 ]
218258
219259 results = []
220- obj = fill_with_random_values (model ())
260+ garbages = []
261+ obj , obj_garbages = fill_with_random_values (conf , model ())
262+ garbages += obj_garbages
221263
222264 result = check_object_creation (conf , obj )
223265 results .append (result )
@@ -231,11 +273,15 @@ def check_resource_type(
231273 result = check_object_query_without_id (conf , created_obj )
232274 results .append (result )
233275
234- fill_with_random_values (queried_obj )
276+ _ , obj_garbages = fill_with_random_values (conf , queried_obj )
277+ garbages += obj_garbages
235278 result = check_object_replacement (conf , created_obj )
236279 results .append (result )
237280
238281 result = check_object_deletion (conf , created_obj )
239282 results .append (result )
240283
284+ for garbage in reversed (garbages ):
285+ conf .client .delete (garbage )
286+
241287 return results
0 commit comments