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_scope_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
}
@@ -135,6 +143,49 @@ mod tests {
135
143
136
144
use super :: * ;
137
145
146
+ #[ test]
147
+ fn test_soundness_check ( ) {
148
+ let p1 = r#"permit (principal, action, resource)
149
+ when { "
150
+
151
+ a
152
+ " };"# ;
153
+ let p2 = r#"permit (principal, action, resource)
154
+ when { "
155
+ a
156
+ " };"# ;
157
+ assert ! ( soundness_check( p2, & parse_policyset( p1) . unwrap( ) ) . is_err( ) ) ;
158
+
159
+ let p1 = r#"
160
+ permit (principal, action, resource)
161
+ when { "a"};
162
+ permit (principal, action, resource)
163
+ when { "
164
+
165
+ a
166
+ " };"# ;
167
+ let p2 = r#"
168
+ permit (principal, action, resource)
169
+ when { "
170
+ a
171
+ " };
172
+ permit (principal, action, resource)
173
+ when { "a"};"# ;
174
+ assert ! ( soundness_check( p2, & parse_policyset( p1) . unwrap( ) ) . is_err( ) ) ;
175
+
176
+ let p1 = r#"
177
+ permit (principal, action, resource)
178
+ when { "a" };
179
+ permit (principal, action, resource)
180
+ when { "b" };"# ;
181
+ let p2 = r#"
182
+ permit (principal, action, resource)
183
+ when { "a" };
184
+ permit (principal, action, resource)
185
+ when { "b"};"# ;
186
+ assert ! ( soundness_check( p2, & parse_policyset( p1) . unwrap( ) ) . is_ok( ) ) ;
187
+ }
188
+
138
189
#[ test]
139
190
fn test_format_files ( ) {
140
191
let config = Config {
0 commit comments