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  }