1515package cel
1616
1717import (
18+ "context"
1819 "fmt"
1920 "io/ioutil"
2021 "log"
2122 "sync"
2223 "testing"
24+ "time"
2325
2426 "github.com/golang/protobuf/proto"
2527 "github.com/google/cel-go/checker/decls"
@@ -32,6 +34,7 @@ import (
3234 "github.com/google/cel-go/interpreter"
3335 "github.com/google/cel-go/interpreter/functions"
3436 "github.com/google/cel-go/parser"
37+ "github.com/google/cel-go/test"
3538
3639 descpb "github.com/golang/protobuf/protoc-gen-go/descriptor"
3740 proto2pb "github.com/google/cel-go/test/proto2pb"
@@ -876,3 +879,98 @@ func Test_CustomInterpreterDecorator(t *testing.T) {
876879 t .Errorf ("got %v as the last observed constant, wanted 1" , lastConst )
877880 }
878881}
882+
883+ func Test_AsyncExtension (t * testing.T ) {
884+ env , err := NewEnv (
885+ Declarations (
886+ decls .NewVar ("x" , decls .String ),
887+ decls .NewFunction ("asyncEcho" ,
888+ decls .NewOverload (
889+ "async_echo_string" ,
890+ []* exprpb.Type {decls .String },
891+ decls .String )),
892+ ),
893+ )
894+ if err != nil {
895+ t .Fatal (err )
896+ }
897+ funcs := Functions (
898+ & functions.Overload {
899+ Operator : "asyncEcho" ,
900+ Async : test .FakeRPC (25 * time .Millisecond ),
901+ },
902+ & functions.Overload {
903+ Operator : "async_echo_string" ,
904+ Async : test .FakeRPC (25 * time .Millisecond ),
905+ },
906+ )
907+
908+ tests := []struct {
909+ expr string
910+ parseOnly bool
911+ evalOpts EvalOption
912+ out ref.Val
913+ }{
914+ {
915+ expr : `asyncEcho(x)` ,
916+ out : types .String ("async echo success!" ),
917+ },
918+ {
919+ expr : `asyncEcho(x)` ,
920+ parseOnly : true ,
921+ out : types .String ("async echo success!" ),
922+ },
923+ {
924+ expr : `asyncEcho(x)` ,
925+ evalOpts : OptOptimize ,
926+ out : types .String ("async echo success!" ),
927+ },
928+ {
929+ expr : `asyncEcho(x) == 'async echo success!'` ,
930+ evalOpts : OptOptimize | OptTrackState ,
931+ out : types .True ,
932+ },
933+ {
934+ expr : `asyncEcho(x) == 'async echo success!' || true` ,
935+ evalOpts : OptOptimize | OptTrackState ,
936+ out : types .True ,
937+ },
938+ }
939+ for i , tst := range tests {
940+ tc := tst
941+ t .Run (fmt .Sprintf ("%d" , i ), func (tt * testing.T ) {
942+ var ast * Ast
943+ var iss * Issues
944+ if tc .parseOnly {
945+ ast , iss = env .Parse (tc .expr )
946+ } else {
947+ ast , iss = env .Compile (tc .expr )
948+ }
949+ if iss .Err () != nil {
950+ tt .Fatal (iss .Err ())
951+ }
952+ opts := []ProgramOption {funcs }
953+ if tc .evalOpts != 0 {
954+ opts = append (opts , EvalOptions (tc .evalOpts ))
955+ }
956+ prg , err := env .AsyncProgram (ast , opts ... )
957+ if err != nil {
958+ tt .Fatal (err )
959+ }
960+ ctx := context .TODO ()
961+ out , det , err := prg .AsyncEval (ctx , map [string ]interface {}{
962+ "x" : "async echo" ,
963+ })
964+ if err != nil {
965+ tt .Fatal (err )
966+ }
967+ if out .Equal (tc .out ) != types .True {
968+ tt .Errorf ("got %v, wanted %v" , out , tc .out )
969+ }
970+ if tc .evalOpts & OptTrackState == OptTrackState && det == nil {
971+ tt .Error ("details was nil, expected non-nil" )
972+ }
973+ })
974+ }
975+
976+ }
0 commit comments