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  }