1
1
use std:: collections:: HashMap ;
2
2
3
+ use async_trait:: async_trait;
3
4
use spin_expressions:: { provider:: ProviderVariableKind , Key , Provider , ProviderResolver } ;
4
5
use spin_locked_app:: Variable ;
5
6
@@ -14,18 +15,12 @@ impl ResolverTester {
14
15
Self :: default ( )
15
16
}
16
17
17
- fn with_dynamic_provider ( mut self ) -> Self {
18
- self . providers . push ( Box :: new ( DynamicProvider ) ) ;
18
+ fn with_provider ( mut self , provider : impl Provider + ' static ) -> Self {
19
+ self . providers . push ( Box :: new ( provider ) ) ;
19
20
self
20
21
}
21
22
22
- fn with_static_provider ( mut self , key : & str , value : Option < & str > ) -> Self {
23
- self . providers
24
- . push ( Box :: new ( StaticProvider :: with_variable ( key, value) ) ) ;
25
- self
26
- }
27
-
28
- fn with_variable ( mut self , ( key, default) : ( & str , Option < & str > ) ) -> Self {
23
+ fn with_variable ( mut self , key : & str , default : Option < & str > ) -> Self {
29
24
self . variables . insert (
30
25
key. to_string ( ) ,
31
26
Variable {
@@ -41,32 +36,33 @@ impl ResolverTester {
41
36
let mut provider_resolver = ProviderResolver :: new ( self . variables ) ?;
42
37
43
38
for provider in self . providers {
44
- provider_resolver. add_provider ( provider as _ ) ;
39
+ provider_resolver. add_provider ( provider) ;
45
40
}
46
41
47
42
Ok ( provider_resolver)
48
43
}
49
44
}
50
45
51
46
#[ tokio:: test( flavor = "multi_thread" ) ]
52
- async fn single_static_provider_with_no_variable_provided_is_valid ( ) -> anyhow:: Result < ( ) > {
47
+ async fn if_single_static_provider_with_no_key_to_resolve_is_valid ( ) -> anyhow:: Result < ( ) > {
53
48
let resolver = ResolverTester :: new ( )
54
- . with_static_provider ( "foo" , Some ( "bar" ) )
49
+ . with_provider ( StaticProvider :: with_variable ( "foo" , Some ( "bar" ) ) )
55
50
. make_resolver ( ) ?;
56
51
57
- resolver. validate_variables ( ) . await ?;
52
+ resolver. ensure_required_variables_resolved ( ) . await ?;
58
53
59
54
Ok ( ( ) )
60
55
}
61
56
62
57
#[ tokio:: test( flavor = "multi_thread" ) ]
63
- async fn if_single_static_provider_has_variable_value_validation_succeeds ( ) -> anyhow:: Result < ( ) > {
58
+ async fn if_single_static_provider_has_data_for_variable_key_to_resolve_it_succeeds (
59
+ ) -> anyhow:: Result < ( ) > {
64
60
let resolver = ResolverTester :: new ( )
65
- . with_static_provider ( "foo" , Some ( "bar" ) )
66
- . with_variable ( ( "foo" , None ) )
61
+ . with_provider ( StaticProvider :: with_variable ( "foo" , Some ( "bar" ) ) )
62
+ . with_variable ( "foo" , None )
67
63
. make_resolver ( ) ?;
68
64
69
- resolver. validate_variables ( ) . await ?;
65
+ resolver. ensure_required_variables_resolved ( ) . await ?;
70
66
71
67
Ok ( ( ) )
72
68
}
@@ -75,38 +71,38 @@ async fn if_single_static_provider_has_variable_value_validation_succeeds() -> a
75
71
async fn if_there_is_a_single_static_provider_and_it_does_not_contain_a_required_variable_then_validation_fails (
76
72
) -> anyhow:: Result < ( ) > {
77
73
let resolver = ResolverTester :: new ( )
78
- . with_static_provider ( "foo" , Some ( "bar" ) )
79
- . with_variable ( ( "bar" , None ) )
74
+ . with_provider ( StaticProvider :: with_variable ( "foo" , Some ( "bar" ) ) )
75
+ . with_variable ( "bar" , None )
80
76
. make_resolver ( ) ?;
81
77
82
- assert ! ( resolver. validate_variables ( ) . await . is_err( ) ) ;
78
+ assert ! ( resolver. ensure_required_variables_resolved ( ) . await . is_err( ) ) ;
83
79
84
80
Ok ( ( ) )
85
81
}
86
82
87
83
#[ tokio:: test( flavor = "multi_thread" ) ]
88
- async fn if_there_is_a_dynamic_provider_then_validation_succeeds_even_if_a_static_provider_without_the_variable_is_in_play (
84
+ async fn if_there_is_a_dynamic_provider_then_validation_succeeds_even_without_default_value_in_play (
89
85
) -> anyhow:: Result < ( ) > {
90
86
let resolver = ResolverTester :: new ( )
91
- . with_dynamic_provider ( )
92
- . with_variable ( ( "bar" , None ) )
87
+ . with_provider ( DynamicProvider )
88
+ . with_variable ( "bar" , None )
93
89
. make_resolver ( ) ?;
94
90
95
- resolver. validate_variables ( ) . await ?;
91
+ resolver. ensure_required_variables_resolved ( ) . await ?;
96
92
97
93
Ok ( ( ) )
98
94
}
99
95
100
96
#[ tokio:: test( flavor = "multi_thread" ) ]
101
- async fn if_there_is_a_dynamic_provider_and_a_static_provider_then_validation_succeeds_even_if_a_static_provider_without_the_variable_is_in_play (
97
+ async fn if_there_is_a_dynamic_provider_and_static_provider_but_the_variable_to_be_resolved_is_not_in_play (
102
98
) -> anyhow:: Result < ( ) > {
103
99
let resolver = ResolverTester :: new ( )
104
- . with_dynamic_provider ( )
105
- . with_static_provider ( "foo" , Some ( "bar" ) )
106
- . with_variable ( ( "baz" , None ) )
100
+ . with_provider ( DynamicProvider )
101
+ . with_provider ( StaticProvider :: with_variable ( "foo" , Some ( "bar" ) ) )
102
+ . with_variable ( "baz" , None )
107
103
. make_resolver ( ) ?;
108
104
109
- resolver. validate_variables ( ) . await ?;
105
+ resolver. ensure_required_variables_resolved ( ) . await ?;
110
106
111
107
Ok ( ( ) )
112
108
}
@@ -115,52 +111,78 @@ async fn if_there_is_a_dynamic_provider_and_a_static_provider_then_validation_su
115
111
async fn if_there_is_a_dynamic_provider_and_a_static_provider_then_validation_succeeds_even_if_a_static_provider_with_the_variable_is_in_play (
116
112
) -> anyhow:: Result < ( ) > {
117
113
let resolver = ResolverTester :: new ( )
118
- . with_dynamic_provider ( )
119
- . with_static_provider ( "foo" , Some ( "bar" ) )
120
- . with_variable ( ( "baz" , Some ( "coo" ) ) )
114
+ . with_provider ( DynamicProvider )
115
+ . with_provider ( StaticProvider :: with_variable ( "foo" , Some ( "bar" ) ) )
116
+ . with_variable ( "baz" , Some ( "coo" ) )
121
117
. make_resolver ( ) ?;
122
118
123
- resolver. validate_variables ( ) . await ?;
119
+ resolver. ensure_required_variables_resolved ( ) . await ?;
124
120
125
121
Ok ( ( ) )
126
122
}
127
123
128
124
#[ tokio:: test( flavor = "multi_thread" ) ]
129
- async fn if_there_is_two_static_providers_where_one_has_data_is_valid ( ) -> anyhow:: Result < ( ) > {
125
+ async fn if_there_are_two_static_providers_where_one_has_data_is_valid ( ) -> anyhow:: Result < ( ) > {
130
126
let resolver = ResolverTester :: new ( )
131
- . with_static_provider ( "foo" , Some ( "bar" ) )
132
- . with_static_provider ( "baz" , Some ( "hay" ) )
133
- . with_variable ( ( "foo" , None ) )
127
+ . with_provider ( StaticProvider :: with_variable ( "foo" , Some ( "bar" ) ) )
128
+ . with_provider ( StaticProvider :: with_variable ( "baz" , Some ( "hay" ) ) )
129
+ . with_variable ( "foo" , None )
134
130
. make_resolver ( ) ?;
135
131
136
- resolver. validate_variables ( ) . await ?;
132
+ resolver. ensure_required_variables_resolved ( ) . await ?;
137
133
138
134
Ok ( ( ) )
139
135
}
140
-
136
+ // This is a bit of an edge case, but we want to ensure that if there are two or more static providers
137
+ // and the first one does not have data for the variable to be resolved, but the second or subsequent one does,
138
+ // then validation still succeeds.
141
139
#[ tokio:: test( flavor = "multi_thread" ) ]
142
- async fn if_there_is_two_static_providers_where_first_provider_does_not_have_data_while_second_provider_does (
140
+ async fn if_there_are_two_static_providers_where_first_provider_does_not_have_data_while_second_provider_does (
143
141
) -> anyhow:: Result < ( ) > {
144
142
let resolver = ResolverTester :: new ( )
145
- . with_static_provider ( "foo" , Some ( "bar" ) )
146
- . with_static_provider ( "baz" , Some ( "hay" ) )
147
- . with_variable ( ( "baz" , None ) )
143
+ . with_provider ( StaticProvider :: with_variable ( "foo" , Some ( "bar" ) ) )
144
+ . with_provider ( StaticProvider :: with_variable ( "baz" , Some ( "hay" ) ) )
145
+ . with_variable ( "baz" , None )
148
146
. make_resolver ( ) ?;
149
147
150
- resolver. validate_variables ( ) . await ?;
148
+ resolver. ensure_required_variables_resolved ( ) . await ?;
151
149
152
150
Ok ( ( ) )
153
151
}
154
152
155
153
#[ tokio:: test( flavor = "multi_thread" ) ]
156
154
async fn if_there_is_two_static_providers_neither_having_data_is_invalid ( ) -> anyhow:: Result < ( ) > {
157
155
let resolver = ResolverTester :: new ( )
158
- . with_static_provider ( "foo" , Some ( "bar" ) )
159
- . with_static_provider ( "baz" , Some ( "hay" ) )
160
- . with_variable ( ( "hello" , None ) )
156
+ . with_provider ( StaticProvider :: with_variable ( "foo" , Some ( "bar" ) ) )
157
+ . with_provider ( StaticProvider :: with_variable ( "baz" , Some ( "hay" ) ) )
158
+ . with_variable ( "hello" , None )
159
+ . make_resolver ( ) ?;
160
+
161
+ assert ! ( resolver. ensure_required_variables_resolved( ) . await . is_err( ) ) ;
162
+
163
+ Ok ( ( ) )
164
+ }
165
+
166
+ #[ tokio:: test( flavor = "multi_thread" ) ]
167
+ async fn no_provider_data_available_but_variable_default_value_needed_is_invalid (
168
+ ) -> anyhow:: Result < ( ) > {
169
+ let resolver = ResolverTester :: new ( )
170
+ . with_variable ( "hello" , None )
171
+ . make_resolver ( ) ?;
172
+
173
+ assert ! ( resolver. ensure_required_variables_resolved( ) . await . is_err( ) ) ;
174
+
175
+ Ok ( ( ) )
176
+ }
177
+
178
+ #[ tokio:: test( flavor = "multi_thread" ) ]
179
+ async fn no_provider_data_available_but_variable_has_default_value_needed_is_valid (
180
+ ) -> anyhow:: Result < ( ) > {
181
+ let resolver = ResolverTester :: new ( )
182
+ . with_variable ( "hello" , Some ( "World" ) )
161
183
. make_resolver ( ) ?;
162
184
163
- assert ! ( resolver. validate_variables ( ) . await . is_err ( ) ) ;
185
+ resolver. ensure_required_variables_resolved ( ) . await ? ;
164
186
165
187
Ok ( ( ) )
166
188
}
@@ -178,7 +200,7 @@ impl StaticProvider {
178
200
}
179
201
}
180
202
181
- #[ spin_world :: async_trait]
203
+ #[ async_trait]
182
204
impl Provider for StaticProvider {
183
205
async fn get ( & self , key : & Key ) -> anyhow:: Result < Option < String > > {
184
206
Ok ( self . variables . get ( key. as_str ( ) ) . cloned ( ) . flatten ( ) )
@@ -192,7 +214,7 @@ impl Provider for StaticProvider {
192
214
#[ derive( Debug ) ]
193
215
struct DynamicProvider ;
194
216
195
- #[ spin_world :: async_trait]
217
+ #[ async_trait]
196
218
impl Provider for DynamicProvider {
197
219
async fn get ( & self , _key : & Key ) -> anyhow:: Result < Option < String > > {
198
220
panic ! ( "validation should never call get for a dynamic provider" )
0 commit comments