1717import static com .google .common .truth .Truth .assertThat ;
1818import static org .junit .Assert .assertThrows ;
1919
20+ import com .google .common .collect .ImmutableList ;
21+ import com .google .common .collect .ImmutableMap ;
22+ import com .google .errorprone .annotations .Immutable ;
23+ import dev .cel .bundle .Cel ;
24+ import dev .cel .bundle .CelFactory ;
25+ import dev .cel .common .CelAbstractSyntaxTree ;
26+ import dev .cel .common .types .CelType ;
27+ import dev .cel .common .types .CelTypeProvider ;
2028import dev .cel .common .types .OpaqueType ;
29+ import java .util .Map ;
30+ import java .util .Optional ;
2131import org .junit .Test ;
2232import org .junit .runner .RunWith ;
2333import org .junit .runners .JUnit4 ;
@@ -37,4 +47,177 @@ public void opaqueValue_construct() {
3747 public void create_nullValue_throws () {
3848 assertThrows (NullPointerException .class , () -> OpaqueValue .create ("opaque_type_name" , null ));
3949 }
50+
51+ private static final OpaqueType CUSTOM_OPAQUE_TYPE = OpaqueType .create ("custom_opaque_type" );
52+
53+ private static final CelTypeProvider CUSTOM_OPAQUE_TYPE_PROVIDER =
54+ new CelTypeProvider () {
55+ @ Override
56+ public ImmutableList <CelType > types () {
57+ return ImmutableList .of (CUSTOM_OPAQUE_TYPE );
58+ }
59+
60+ @ Override
61+ public Optional <CelType > findType (String typeName ) {
62+ return typeName .equals (CUSTOM_OPAQUE_TYPE .name ())
63+ ? Optional .of (CUSTOM_OPAQUE_TYPE )
64+ : Optional .empty ();
65+ }
66+ };
67+
68+ private static final CelValueProvider CUSTOM_OPAQUE_VALUE_PROVIDER =
69+ new CelValueProvider () {
70+ @ Override
71+ public Optional <Object > newValue (String structType , Map <String , Object > fields ) {
72+ return Optional .empty ();
73+ }
74+
75+ @ Override
76+ public CelValueConverter celValueConverter () {
77+ return new CelValueConverter () {
78+ @ Override
79+ public Object toRuntimeValue (Object value ) {
80+ if (value instanceof CustomOpaqueObject ) {
81+ CustomOpaqueObject customOpaqueObject = (CustomOpaqueObject ) value ;
82+ return new CelCustomOpaqueValue (customOpaqueObject );
83+ }
84+ return super .toRuntimeValue (value );
85+ }
86+ };
87+ }
88+ };
89+
90+ private static final CelValueProvider WRAPPED_CUSTOM_OPAQUE_VALUE_PROVIDER =
91+ new CelValueProvider () {
92+ @ Override
93+ public Optional <Object > newValue (String structType , Map <String , Object > fields ) {
94+ return Optional .empty ();
95+ }
96+
97+ @ Override
98+ public CelValueConverter celValueConverter () {
99+ return new CelValueConverter () {
100+ @ Override
101+ public Object toRuntimeValue (Object value ) {
102+ if (value instanceof CustomOpaqueObject ) {
103+ CustomOpaqueObject customOpaqueObject = (CustomOpaqueObject ) value ;
104+ return OpaqueValue .create (CUSTOM_OPAQUE_TYPE .name (), customOpaqueObject );
105+ }
106+ return super .toRuntimeValue (value );
107+ }
108+ };
109+ }
110+ };
111+
112+ @ Immutable
113+ private static class CustomOpaqueObject {
114+ private final String value ;
115+
116+ CustomOpaqueObject (String value ) {
117+ this .value = value ;
118+ }
119+
120+ String getValue () {
121+ return value ;
122+ }
123+ }
124+
125+ @ Immutable
126+ private static class CelCustomOpaqueValue extends OpaqueValue {
127+ private final CustomOpaqueObject obj ;
128+
129+ CelCustomOpaqueValue (CustomOpaqueObject obj ) {
130+ this .obj = obj ;
131+ }
132+
133+ @ Override
134+ public CustomOpaqueObject value () {
135+ return obj ;
136+ }
137+
138+ @ Override
139+ public OpaqueType celType () {
140+ return CUSTOM_OPAQUE_TYPE ;
141+ }
142+ }
143+
144+ @ Test
145+ public void evaluate_customOpaqueValue_asVariable () throws Exception {
146+ Cel cel =
147+ CelFactory .plannerCelBuilder ()
148+ .addVar ("opaque_var" , CUSTOM_OPAQUE_TYPE )
149+ .setTypeProvider (CUSTOM_OPAQUE_TYPE_PROVIDER )
150+ .setValueProvider (CUSTOM_OPAQUE_VALUE_PROVIDER )
151+ .build ();
152+ CelAbstractSyntaxTree ast = cel .compile ("opaque_var" ).getAst ();
153+
154+ CustomOpaqueObject rawValue = new CustomOpaqueObject ("hello" );
155+ Object result = cel .createProgram (ast ).eval (ImmutableMap .of ("opaque_var" , rawValue ));
156+
157+ assertThat (result ).isInstanceOf (CustomOpaqueObject .class );
158+ assertThat (((CustomOpaqueObject ) result ).getValue ()).isEqualTo ("hello" );
159+ }
160+
161+ @ Test
162+ public void evaluate_typeOfCustomOpaqueValue () throws Exception {
163+ Cel cel =
164+ CelFactory .plannerCelBuilder ()
165+ .addVar ("opaque_var" , CUSTOM_OPAQUE_TYPE )
166+ .setTypeProvider (CUSTOM_OPAQUE_TYPE_PROVIDER )
167+ .setValueProvider (CUSTOM_OPAQUE_VALUE_PROVIDER )
168+ .build ();
169+ CelAbstractSyntaxTree ast = cel .compile ("type(opaque_var) == custom_opaque_type" ).getAst ();
170+
171+ CustomOpaqueObject rawValue = new CustomOpaqueObject ("hello" );
172+ Object result = cel .createProgram (ast ).eval (ImmutableMap .of ("opaque_var" , rawValue ));
173+
174+ assertThat (result ).isEqualTo (true );
175+ }
176+
177+ @ Test
178+ public void evaluate_typeOfCustomOpaqueValue_wrapped () throws Exception {
179+ Cel cel =
180+ CelFactory .plannerCelBuilder ()
181+ .addVar ("opaque_var" , CUSTOM_OPAQUE_TYPE )
182+ .setTypeProvider (CUSTOM_OPAQUE_TYPE_PROVIDER )
183+ .setValueProvider (WRAPPED_CUSTOM_OPAQUE_VALUE_PROVIDER )
184+ .build ();
185+ CelAbstractSyntaxTree ast = cel .compile ("type(opaque_var) == custom_opaque_type" ).getAst ();
186+
187+ CustomOpaqueObject rawValue = new CustomOpaqueObject ("hello" );
188+ Object result = cel .createProgram (ast ).eval (ImmutableMap .of ("opaque_var" , rawValue ));
189+
190+ assertThat (result ).isEqualTo (true );
191+ }
192+
193+ @ Immutable
194+ private static class SelfReturningOpaqueObject extends OpaqueValue {
195+ SelfReturningOpaqueObject () {}
196+
197+ @ Override
198+ public Object value () {
199+ return this ;
200+ }
201+
202+ @ Override
203+ public OpaqueType celType () {
204+ return CUSTOM_OPAQUE_TYPE ;
205+ }
206+ }
207+
208+ @ Test
209+ public void evaluate_selfReturningOpaqueValue_noConverter () throws Exception {
210+ Cel cel =
211+ CelFactory .plannerCelBuilder ()
212+ .addVar ("opaque_var" , CUSTOM_OPAQUE_TYPE )
213+ .setTypeProvider (CUSTOM_OPAQUE_TYPE_PROVIDER )
214+ .build ();
215+ CelAbstractSyntaxTree ast = cel .compile ("type(opaque_var) == custom_opaque_type" ).getAst ();
216+
217+ SelfReturningOpaqueObject rawValue = new SelfReturningOpaqueObject ();
218+ Object result = cel .createProgram (ast ).eval (ImmutableMap .of ("opaque_var" , rawValue ));
219+
220+ assertThat (result ).isEqualTo (true );
221+ }
40222}
223+
0 commit comments