14
14
* limitations under the License.
15
15
*/
16
16
17
+ use std:: collections:: BTreeMap ;
18
+
17
19
use miette:: { miette, Result , WrapErr } ;
18
20
19
- use cedar_policy_core:: ast:: { PolicySet , Template } ;
21
+ use cedar_policy_core:: ast:: PolicySet ;
20
22
use cedar_policy_core:: parser:: parse_policyset;
21
23
use cedar_policy_core:: parser:: { err:: ParseErrors , text_to_cst:: parse_policies} ;
24
+ use smol_str:: ToSmolStr ;
22
25
23
26
use crate :: token:: get_comment;
24
27
@@ -42,15 +45,19 @@ fn tree_to_pretty<T: Doc>(t: &T, context: &mut config::Context<'_>) -> Result<St
42
45
fn soundness_check ( ps : & str , ast : & PolicySet ) -> Result < ( ) > {
43
46
let formatted_ast = parse_policyset ( ps) . wrap_err ( "formatter produces invalid policies" ) ?;
44
47
let ( formatted_policies, policies) = (
45
- formatted_ast. templates ( ) . collect :: < Vec < & Template > > ( ) ,
46
- ast. templates ( ) . collect :: < Vec < & Template > > ( ) ,
48
+ formatted_ast
49
+ . policies ( )
50
+ . map ( |p| ( p. id ( ) . to_smolstr ( ) , p) )
51
+ . collect :: < BTreeMap < _ , _ > > ( ) ,
52
+ ast. policies ( )
53
+ . map ( |p| ( p. id ( ) . to_smolstr ( ) , p) )
54
+ . collect :: < BTreeMap < _ , _ > > ( ) ,
47
55
) ;
48
56
49
57
if formatted_policies. len ( ) != policies. len ( ) {
50
58
return Err ( miette ! ( "missing formatted policies" ) ) ;
51
59
}
52
-
53
- for ( f_p, p) in formatted_policies. into_iter ( ) . zip ( policies. into_iter ( ) ) {
60
+ for ( ( f_p_id, f_p) , ( p_id, p) ) in formatted_policies. into_iter ( ) . zip ( policies. into_iter ( ) ) {
54
61
let ( f_anno, anno) = (
55
62
f_p. annotations ( )
56
63
. map ( |( k, v) | ( k, & v. val ) )
@@ -59,7 +66,8 @@ fn soundness_check(ps: &str, ast: &PolicySet) -> Result<()> {
59
66
. map ( |( k, v) | ( k, & v. val ) )
60
67
. collect :: < std:: collections:: BTreeMap < _ , _ > > ( ) ,
61
68
) ;
62
- if !( f_anno == anno
69
+ if !( f_p_id == p_id
70
+ && f_anno == anno
63
71
&& f_p. effect ( ) == p. effect ( )
64
72
&& f_p. principal_constraint ( ) == p. principal_constraint ( )
65
73
&& f_p. action_constraint ( ) == p. action_constraint ( )
@@ -69,7 +77,7 @@ fn soundness_check(ps: &str, ast: &PolicySet) -> Result<()> {
69
77
. eq_shape ( p. non_head_constraints ( ) ) )
70
78
{
71
79
return Err ( miette ! (
72
- "policies differ in meaning or annotations:\n original: {p}\n formatted: {f_p}"
80
+ "policies differ in policy ids or meaning or annotations:\n original: {p}\n formatted: {f_p}"
73
81
) ) ;
74
82
}
75
83
}
@@ -167,6 +175,49 @@ mod tests {
167
175
) ;
168
176
}
169
177
178
+ #[ test]
179
+ fn test_soundness_check ( ) {
180
+ let p1 = r#"permit (principal, action, resource)
181
+ when { "
182
+
183
+ a
184
+ " };"# ;
185
+ let p2 = r#"permit (principal, action, resource)
186
+ when { "
187
+ a
188
+ " };"# ;
189
+ assert ! ( soundness_check( p2, & parse_policyset( p1) . unwrap( ) ) . is_err( ) ) ;
190
+
191
+ let p1 = r#"
192
+ permit (principal, action, resource)
193
+ when { "a"};
194
+ permit (principal, action, resource)
195
+ when { "
196
+
197
+ a
198
+ " };"# ;
199
+ let p2 = r#"
200
+ permit (principal, action, resource)
201
+ when { "
202
+ a
203
+ " };
204
+ permit (principal, action, resource)
205
+ when { "a"};"# ;
206
+ assert ! ( soundness_check( p2, & parse_policyset( p1) . unwrap( ) ) . is_err( ) ) ;
207
+
208
+ let p1 = r#"
209
+ permit (principal, action, resource)
210
+ when { "a" };
211
+ permit (principal, action, resource)
212
+ when { "b" };"# ;
213
+ let p2 = r#"
214
+ permit (principal, action, resource)
215
+ when { "a" };
216
+ permit (principal, action, resource)
217
+ when { "b"};"# ;
218
+ assert ! ( soundness_check( p2, & parse_policyset( p1) . unwrap( ) ) . is_ok( ) ) ;
219
+ }
220
+
170
221
#[ test]
171
222
fn test_format_files ( ) {
172
223
use std:: fs:: read_to_string;
0 commit comments