github.com/expr-lang/expr@v1.16.9/patcher/with_context_test.go (about) 1 package patcher_test 2 3 import ( 4 "context" 5 "testing" 6 7 "github.com/expr-lang/expr/internal/testify/require" 8 9 "github.com/expr-lang/expr" 10 "github.com/expr-lang/expr/patcher" 11 ) 12 13 func TestWithContext(t *testing.T) { 14 env := map[string]any{ 15 "fn": func(ctx context.Context, a int) int { 16 return ctx.Value("value").(int) + a 17 }, 18 "ctx": context.TODO(), 19 } 20 21 withContext := patcher.WithContext{Name: "ctx"} 22 23 program, err := expr.Compile(`fn(40)`, expr.Env(env), expr.Patch(withContext)) 24 require.NoError(t, err) 25 26 ctx := context.WithValue(context.Background(), "value", 2) 27 env["ctx"] = ctx 28 29 output, err := expr.Run(program, env) 30 require.NoError(t, err) 31 require.Equal(t, 42, output) 32 } 33 34 func TestWithContext_with_env_Function(t *testing.T) { 35 env := map[string]any{ 36 "ctx": context.TODO(), 37 } 38 39 fn := expr.Function("fn", 40 func(params ...any) (any, error) { 41 ctx := params[0].(context.Context) 42 a := params[1].(int) 43 44 return ctx.Value("value").(int) + a, nil 45 }, 46 new(func(context.Context, int) int), 47 ) 48 49 program, err := expr.Compile( 50 `fn(40)`, 51 expr.Env(env), 52 expr.WithContext("ctx"), 53 fn, 54 ) 55 require.NoError(t, err) 56 57 ctx := context.WithValue(context.Background(), "value", 2) 58 env["ctx"] = ctx 59 60 output, err := expr.Run(program, env) 61 require.NoError(t, err) 62 require.Equal(t, 42, output) 63 } 64 65 type testEnvContext struct { 66 Context context.Context `expr:"ctx"` 67 } 68 69 func (testEnvContext) Fn(ctx context.Context, a int) int { 70 return ctx.Value("value").(int) + a 71 } 72 73 func TestWithContext_env_struct(t *testing.T) { 74 withContext := patcher.WithContext{Name: "ctx"} 75 76 program, err := expr.Compile(`Fn(40)`, expr.Env(testEnvContext{}), expr.Patch(withContext)) 77 require.NoError(t, err) 78 79 ctx := context.WithValue(context.Background(), "value", 2) 80 env := testEnvContext{ 81 Context: ctx, 82 } 83 84 output, err := expr.Run(program, env) 85 require.NoError(t, err) 86 require.Equal(t, 42, output) 87 } 88 89 type TestFoo struct { 90 contextValue int 91 } 92 93 func (f *TestFoo) GetValue(a int) int64 { 94 return int64(f.contextValue + a) 95 } 96 97 func TestWithContext_with_env_method_chain(t *testing.T) { 98 env := map[string]any{ 99 "ctx": context.TODO(), 100 } 101 102 fn := expr.Function("fn", 103 func(params ...any) (any, error) { 104 ctx := params[0].(context.Context) 105 106 contextValue := ctx.Value("value").(int) 107 108 return &TestFoo{ 109 contextValue: contextValue, 110 }, nil 111 }, 112 new(func(context.Context) *TestFoo), 113 ) 114 115 program, err := expr.Compile( 116 `fn().GetValue(40)`, 117 expr.Env(env), 118 expr.WithContext("ctx"), 119 fn, 120 expr.AsInt64(), 121 ) 122 require.NoError(t, err) 123 124 ctx := context.WithValue(context.Background(), "value", 2) 125 env["ctx"] = ctx 126 127 output, err := expr.Run(program, env) 128 require.NoError(t, err) 129 require.Equal(t, int64(42), output) 130 } 131 132 func TestWithContext_issue529(t *testing.T) { 133 env := map[string]any{ 134 "ctx": context.Background(), 135 "foo": func(ctx context.Context, n int) int { 136 if ctx == nil { 137 panic("wanted a context") 138 } 139 return n + 1 140 }, 141 } 142 options := []expr.Option{ 143 expr.Env(env), 144 expr.WithContext("ctx"), 145 } 146 147 code := "foo(0) | foo()" 148 program, err := expr.Compile(code, options...) 149 require.NoError(t, err) 150 151 out, err := expr.Run(program, env) 152 require.NoError(t, err) 153 require.Equal(t, 2, out) 154 }