go.charczuk.com@v0.0.0-20240327042549-bc490516bd1a/projects/nodes/pkg/funcs/expression_test.go (about) 1 /* 2 3 Copyright (c) 2023 - Present. Will Charczuk. All rights reserved. 4 Use of this source code is governed by a MIT license that can be found in the LICENSE file at the root of the repository. 5 6 */ 7 8 package funcs 9 10 import ( 11 "context" 12 "testing" 13 "time" 14 15 "github.com/wcharczuk/go-incr" 16 "go.charczuk.com/projects/nodes/pkg/incrutil" 17 "go.charczuk.com/sdk/assert" 18 ) 19 20 type mockNodeWithLabelIncr[A any] struct { 21 node *incr.Node 22 value A 23 } 24 25 func (m *mockNodeWithLabelIncr[A]) Node() *incr.Node { 26 return m.node 27 } 28 29 func (m *mockNodeWithLabelIncr[A]) Value() A { 30 return m.value 31 } 32 33 func mockNodeWithLabel[A any](label string, value A) incr.Incr[A] { 34 n := incr.NewNode("mock-node") 35 n.SetLabel(label) 36 return &mockNodeWithLabelIncr[A]{ 37 node: n, 38 value: value, 39 } 40 } 41 42 func Test_Expression_basic(t *testing.T) { 43 ctx := context.Background() 44 45 evalFn := Expression[string, string]("output = input(0) + input(1)") 46 47 inputs := incrutil.NewInputs[string](mockNodeWithLabel("input-0", "foo"), mockNodeWithLabel("input-1", "bar")) 48 res, err := evalFn(ctx, inputs) 49 assert.ItsNil(t, err) 50 assert.ItsEqual(t, "foobar", res) 51 } 52 53 func Test_Expression_basic_byLabel(t *testing.T) { 54 ctx := context.Background() 55 56 evalFn := Expression[string, string]("output = input('input-0') + input('input-1')") 57 58 inputs := incrutil.NewInputs(mockNodeWithLabel("input-0", "foo"), mockNodeWithLabel("input-1", "bar")) 59 res, err := evalFn(ctx, inputs) 60 assert.ItsNil(t, err) 61 assert.ItsEqual(t, "foobar", res) 62 } 63 64 func Test_Expression_newlines(t *testing.T) { 65 ctx := context.Background() 66 67 evalFn := Expression[[]float64, float64](`i = input(0) 68 output = i[0] 69 `) 70 71 inputs := incrutil.NewInputs(mockNodeWithLabel("input-0", []float64{1, 2, 3, 4})) 72 73 res, err := evalFn(ctx, inputs) 74 assert.ItsNil(t, err) 75 assert.ItsEqual(t, 1, res) 76 } 77 78 func Test_Expression_math(t *testing.T) { 79 ctx := context.Background() 80 evalFn := Expression[int64, int64]("output = input(0) + input(1)") 81 82 inputs := incrutil.NewInputs(mockNodeWithLabel("input-0", int64(123)), mockNodeWithLabel("input-1", int64(456))) 83 res, err := evalFn(ctx, inputs) 84 assert.ItsNil(t, err) 85 assert.ItsEqual(t, 123+456, res) 86 } 87 88 func Test_Expression_lists(t *testing.T) { 89 ctx := context.Background() 90 const expr = ` 91 i = input(0) 92 output = [] 93 for v in i: 94 output.append(v + 10) 95 ` 96 evalFn := Expression[[]int64, []int64](expr) 97 98 inputs := incrutil.NewInputs( 99 mockNodeWithLabel("input-0", []int64{1, 2, 3, 4, 5}), 100 ) 101 res, err := evalFn(ctx, inputs) 102 assert.ItsNil(t, err) 103 assert.ItsEqual(t, []int64{11, 12, 13, 14, 15}, res) 104 } 105 106 func Test_Expression_parse_timestamp(t *testing.T) { 107 ctx := context.Background() 108 now := time.Date(2023, 10, 27, 8, 42, 12, 11, time.UTC) 109 110 inputs := incrutil.NewInputs[any]( 111 mockNodeWithLabel[any]("input-0", now.UnixMilli()), 112 mockNodeWithLabel[any]("input-1", now.Add(-time.Hour).Format(incrutil.TimeFormatYearTime)), 113 ) 114 115 evalFn := Expression[any, bool]("output = parse_timestamp(input(0)) == parse_timestamp(input(1))") 116 res, err := evalFn(ctx, inputs) 117 assert.ItsNil(t, err) 118 assert.ItsEqual(t, false, res) 119 120 evalFnStr := Expression[any, string]("output = str(parse_timestamp(input(0)))") 121 resStr, err := evalFnStr(ctx, inputs) 122 assert.ItsNil(t, err) 123 assert.ItsEqual(t, "1698396132000", resStr) 124 125 evalFnStr = Expression[any, string]("output = str(parse_timestamp(input(1)))") 126 resStr, err = evalFnStr(ctx, inputs) 127 assert.ItsNil(t, err) 128 assert.ItsEqual(t, "1698392520000", resStr) 129 }