2424public class EventContextFormatterTest extends BaseTest {
2525 private final LDContext context ;
2626 private final boolean allAttributesPrivate ;
27+ private final boolean redactAnonymous ;
2728 private final AttributeRef [] globalPrivateAttributes ;
2829 private final String expectedJson ;
2930
3031 public EventContextFormatterTest (
3132 String name ,
3233 LDContext context ,
3334 boolean allAttributesPrivate ,
35+ boolean redactAnonymous ,
3436 AttributeRef [] globalPrivateAttributes ,
3537 String expectedJson
3638 ) {
3739 this .context = context ;
3840 this .allAttributesPrivate = allAttributesPrivate ;
41+ this .redactAnonymous = redactAnonymous ;
3942 this .globalPrivateAttributes = globalPrivateAttributes ;
4043 this .expectedJson = expectedJson ;
4144 }
@@ -53,6 +56,7 @@ public static Iterable<Object[]> data() {
5356 .set ("attr1" , "value1" )
5457 .build (),
5558 false ,
59+ false ,
5660 new AttributeRef [0 ],
5761 "{\" kind\" : \" org\" , \" key\" : \" my-key\" , \" name\" : \" my-name\" , \" attr1\" : \" value1\" }"
5862 },
@@ -68,6 +72,7 @@ public static Iterable<Object[]> data() {
6872 .build ()
6973 ),
7074 false ,
75+ false ,
7176 new AttributeRef [0 ],
7277 "{" +
7378 "\" kind\" : \" multi\" ," +
@@ -79,6 +84,7 @@ public static Iterable<Object[]> data() {
7984 "anonymous" ,
8085 LDContext .builder ("my-key" ).kind ("org" ).anonymous (true ).build (),
8186 false ,
87+ false ,
8288 new AttributeRef [0 ],
8389 "{\" kind\" : \" org\" , \" key\" : \" my-key\" , \" anonymous\" : true}"
8490 },
@@ -89,6 +95,7 @@ public static Iterable<Object[]> data() {
8995 .set ("attr1" , "value1" )
9096 .build (),
9197 true ,
98+ false ,
9299 new AttributeRef [0 ],
93100 "{" +
94101 "\" kind\" : \" org\" ," +
@@ -107,6 +114,7 @@ public static Iterable<Object[]> data() {
107114 .privateAttributes ("attr2" )
108115 .build (),
109116 false ,
117+ false ,
110118 new AttributeRef [] { AttributeRef .fromLiteral ("name" ) },
111119 "{" +
112120 "\" kind\" : \" org\" ," +
@@ -125,6 +133,7 @@ public static Iterable<Object[]> data() {
125133 .privateAttributes ("/complex/a/b/d" , "/complex/a/b/nonexistent-prop" , "/complex/f" , "/complex/g/g-is-not-an-object" )
126134 .build (),
127135 false ,
136+ false ,
128137 new AttributeRef [] { AttributeRef .fromPath ("/address/street" ) },
129138 "{" +
130139 "\" kind\" : \" user\" ," +
@@ -135,6 +144,82 @@ public static Iterable<Object[]> data() {
135144 "\" redactedAttributes\" : [\" /address/street\" , \" /complex/a/b/d\" , \" /complex/f\" ]" +
136145 "}" +
137146 "}"
147+ },
148+ // A name that starts with a slash is reported as an escaped reference. Any other name
149+ // is already a valid reference and is reported unchanged.
150+ new Object [] {
151+ "all attributes private globally - names needing escaping" ,
152+ LDContext .builder ("my-key" ).kind ("org" )
153+ .set ("/ssn" , "123-45-6789" )
154+ .set ("/a~b" , "secret" )
155+ .set ("c/d~e" , "value" )
156+ .build (),
157+ true ,
158+ false ,
159+ new AttributeRef [0 ],
160+ "{" +
161+ "\" kind\" : \" org\" ," +
162+ "\" key\" : \" my-key\" ," +
163+ "\" _meta\" : {" +
164+ "\" redactedAttributes\" : [\" /~1a~0b\" , \" /~1ssn\" , \" c/d~e\" ]" +
165+ "}" +
166+ "}"
167+ },
168+ new Object [] {
169+ "redacting anonymous context - names needing escaping" ,
170+ LDContext .builder ("my-key" ).kind ("org" )
171+ .anonymous (true )
172+ .name ("my-name" )
173+ .set ("/ssn" , "123-45-6789" )
174+ .build (),
175+ false ,
176+ true ,
177+ new AttributeRef [0 ],
178+ "{" +
179+ "\" kind\" : \" org\" ," +
180+ "\" key\" : \" my-key\" ," +
181+ "\" anonymous\" : true," +
182+ "\" _meta\" : {" +
183+ "\" redactedAttributes\" : [\" /~1ssn\" , \" name\" ]" +
184+ "}" +
185+ "}"
186+ },
187+ new Object [] {
188+ "slash-prefixed attribute name configured as private" ,
189+ LDContext .builder ("my-key" ).kind ("org" )
190+ .name ("my-name" )
191+ .set ("/ssn" , "123-45-6789" )
192+ .build (),
193+ false ,
194+ false ,
195+ new AttributeRef [] { AttributeRef .fromLiteral ("/ssn" ) },
196+ "{" +
197+ "\" kind\" : \" org\" ," +
198+ "\" key\" : \" my-key\" ," +
199+ "\" name\" : \" my-name\" ," +
200+ "\" _meta\" : {" +
201+ "\" redactedAttributes\" : [\" /~1ssn\" ]" +
202+ "}" +
203+ "}"
204+ },
205+ new Object [] {
206+ "slash-prefixed attribute name private for this context" ,
207+ LDContext .builder ("my-key" ).kind ("org" )
208+ .name ("my-name" )
209+ .set ("/ssn" , "123-45-6789" )
210+ .privateAttributes ("/~1ssn" )
211+ .build (),
212+ false ,
213+ false ,
214+ new AttributeRef [0 ],
215+ "{" +
216+ "\" kind\" : \" org\" ," +
217+ "\" key\" : \" my-key\" ," +
218+ "\" name\" : \" my-name\" ," +
219+ "\" _meta\" : {" +
220+ "\" redactedAttributes\" : [\" /~1ssn\" ]" +
221+ "}" +
222+ "}"
138223 }
139224 );
140225 }
@@ -145,7 +230,7 @@ public void testOutput() throws Exception {
145230 StringWriter sw = new StringWriter ();
146231 JsonWriter jw = new JsonWriter (sw );
147232
148- f .write (context , jw , false );
233+ f .write (context , jw , redactAnonymous );
149234 jw .flush ();
150235
151236 String canonicalizedOutput = canonicalizeOutputJson (sw .toString ());
0 commit comments