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,175 @@ 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 customOpaqueObject ) {
81+ return new CelCustomOpaqueValue (customOpaqueObject );
82+ }
83+ return super .toRuntimeValue (value );
84+ }
85+ };
86+ }
87+ };
88+
89+ private static final CelValueProvider WRAPPED_CUSTOM_OPAQUE_VALUE_PROVIDER =
90+ new CelValueProvider () {
91+ @ Override
92+ public Optional <Object > newValue (String structType , Map <String , Object > fields ) {
93+ return Optional .empty ();
94+ }
95+
96+ @ Override
97+ public CelValueConverter celValueConverter () {
98+ return new CelValueConverter () {
99+ @ Override
100+ public Object toRuntimeValue (Object value ) {
101+ if (value instanceof CustomOpaqueObject customOpaqueObject ) {
102+ return OpaqueValue .create (CUSTOM_OPAQUE_TYPE .name (), customOpaqueObject );
103+ }
104+ return super .toRuntimeValue (value );
105+ }
106+ };
107+ }
108+ };
109+
110+ @ Immutable
111+ private static class CustomOpaqueObject {
112+ private final String value ;
113+
114+ CustomOpaqueObject (String value ) {
115+ this .value = value ;
116+ }
117+
118+ String getValue () {
119+ return value ;
120+ }
121+ }
122+
123+ @ Immutable
124+ private static class CelCustomOpaqueValue extends OpaqueValue {
125+ private final CustomOpaqueObject obj ;
126+
127+ CelCustomOpaqueValue (CustomOpaqueObject obj ) {
128+ this .obj = obj ;
129+ }
130+
131+ @ Override
132+ public CustomOpaqueObject value () {
133+ return obj ;
134+ }
135+
136+ @ Override
137+ public OpaqueType celType () {
138+ return CUSTOM_OPAQUE_TYPE ;
139+ }
140+ }
141+
142+ @ Test
143+ public void evaluate_customOpaqueValue_asVariable () throws Exception {
144+ Cel cel =
145+ CelFactory .plannerCelBuilder ()
146+ .addVar ("opaque_var" , CUSTOM_OPAQUE_TYPE )
147+ .setTypeProvider (CUSTOM_OPAQUE_TYPE_PROVIDER )
148+ .setValueProvider (CUSTOM_OPAQUE_VALUE_PROVIDER )
149+ .build ();
150+ CelAbstractSyntaxTree ast = cel .compile ("opaque_var" ).getAst ();
151+
152+ CustomOpaqueObject rawValue = new CustomOpaqueObject ("hello" );
153+ Object result = cel .createProgram (ast ).eval (ImmutableMap .of ("opaque_var" , rawValue ));
154+
155+ assertThat (result ).isInstanceOf (CustomOpaqueObject .class );
156+ assertThat (((CustomOpaqueObject ) result ).getValue ()).isEqualTo ("hello" );
157+ }
158+
159+ @ Test
160+ public void evaluate_typeOfCustomOpaqueValue () throws Exception {
161+ Cel cel =
162+ CelFactory .plannerCelBuilder ()
163+ .addVar ("opaque_var" , CUSTOM_OPAQUE_TYPE )
164+ .setTypeProvider (CUSTOM_OPAQUE_TYPE_PROVIDER )
165+ .setValueProvider (CUSTOM_OPAQUE_VALUE_PROVIDER )
166+ .build ();
167+ CelAbstractSyntaxTree ast = cel .compile ("type(opaque_var) == custom_opaque_type" ).getAst ();
168+
169+ CustomOpaqueObject rawValue = new CustomOpaqueObject ("hello" );
170+ Object result = cel .createProgram (ast ).eval (ImmutableMap .of ("opaque_var" , rawValue ));
171+
172+ assertThat (result ).isEqualTo (true );
173+ }
174+
175+ @ Test
176+ public void evaluate_typeOfCustomOpaqueValue_wrapped () throws Exception {
177+ Cel cel =
178+ CelFactory .plannerCelBuilder ()
179+ .addVar ("opaque_var" , CUSTOM_OPAQUE_TYPE )
180+ .setTypeProvider (CUSTOM_OPAQUE_TYPE_PROVIDER )
181+ .setValueProvider (WRAPPED_CUSTOM_OPAQUE_VALUE_PROVIDER )
182+ .build ();
183+ CelAbstractSyntaxTree ast = cel .compile ("type(opaque_var) == custom_opaque_type" ).getAst ();
184+
185+ CustomOpaqueObject rawValue = new CustomOpaqueObject ("hello" );
186+ Object result = cel .createProgram (ast ).eval (ImmutableMap .of ("opaque_var" , rawValue ));
187+
188+ assertThat (result ).isEqualTo (true );
189+ }
190+
191+ @ Immutable
192+ private static class SelfReturningOpaqueObject extends OpaqueValue {
193+ SelfReturningOpaqueObject () {}
194+
195+ @ Override
196+ public Object value () {
197+ return this ;
198+ }
199+
200+ @ Override
201+ public OpaqueType celType () {
202+ return CUSTOM_OPAQUE_TYPE ;
203+ }
204+ }
205+
206+ @ Test
207+ public void evaluate_selfReturningOpaqueValue_noConverter () throws Exception {
208+ Cel cel =
209+ CelFactory .plannerCelBuilder ()
210+ .addVar ("opaque_var" , CUSTOM_OPAQUE_TYPE )
211+ .setTypeProvider (CUSTOM_OPAQUE_TYPE_PROVIDER )
212+ .build ();
213+ CelAbstractSyntaxTree ast = cel .compile ("type(opaque_var) == custom_opaque_type" ).getAst ();
214+
215+ SelfReturningOpaqueObject rawValue = new SelfReturningOpaqueObject ();
216+ Object result = cel .createProgram (ast ).eval (ImmutableMap .of ("opaque_var" , rawValue ));
217+
218+ assertThat (result ).isEqualTo (true );
219+ }
40220}
221+
0 commit comments