github.com/Jeffail/benthos/v3@v3.65.0/public/bloblang/executor_test.go (about)

     1  package bloblang
     2  
     3  import (
     4  	"testing"
     5  
     6  	"github.com/stretchr/testify/assert"
     7  	"github.com/stretchr/testify/require"
     8  )
     9  
    10  func TestExecutorQuery(t *testing.T) {
    11  	tests := []struct {
    12  		name        string
    13  		mapping     string
    14  		input       interface{}
    15  		output      interface{}
    16  		errContains string
    17  	}{
    18  		{
    19  			name:        "no metadata get",
    20  			mapping:     `root = meta("foo")`,
    21  			errContains: "metadata value 'foo' not found",
    22  		},
    23  		{
    24  			name:        "no metadata set",
    25  			mapping:     `meta foo = "hello"`,
    26  			errContains: "unable to assign metadata in the current context",
    27  		},
    28  		{
    29  			name: "variable get and set",
    30  			mapping: `let foo = "foo value"
    31  root = $foo`,
    32  			output: "foo value",
    33  		},
    34  		{
    35  			name:    "not mapped",
    36  			mapping: `root = if false { "not this" }`,
    37  			input: map[string]interface{}{
    38  				"hello": "world",
    39  			},
    40  			output: map[string]interface{}{
    41  				"hello": "world",
    42  			},
    43  		},
    44  		{
    45  			name:        "delete root for some reason",
    46  			mapping:     `root = deleted()`,
    47  			errContains: "root was deleted",
    48  		},
    49  	}
    50  
    51  	for _, test := range tests {
    52  		t.Run(test.name, func(t *testing.T) {
    53  			m, err := NewEnvironment().Parse(test.mapping)
    54  			require.NoError(t, err)
    55  
    56  			res, err := m.Query(test.input)
    57  			if test.errContains == "" {
    58  				require.NoError(t, err)
    59  				assert.Equal(t, test.output, res)
    60  			} else {
    61  				assert.Contains(t, err.Error(), test.errContains)
    62  			}
    63  		})
    64  	}
    65  }
    66  
    67  func TestExecutorOverlay(t *testing.T) {
    68  	tests := []struct {
    69  		name        string
    70  		mapping     string
    71  		overlay     interface{}
    72  		input       interface{}
    73  		output      interface{}
    74  		errContains string
    75  	}{
    76  		{
    77  			name:        "no metadata get",
    78  			mapping:     `root = meta("foo")`,
    79  			errContains: "metadata value 'foo' not found",
    80  		},
    81  		{
    82  			name:        "no metadata set",
    83  			mapping:     `meta foo = "hello"`,
    84  			errContains: "unable to assign metadata in the current context",
    85  		},
    86  		{
    87  			name: "variable get and set",
    88  			mapping: `let foo = "foo value"
    89  root = $foo`,
    90  			output: "foo value",
    91  		},
    92  		{
    93  			name:    "set nested field from nil",
    94  			mapping: `root.foo.bar = "hello world"`,
    95  			output: map[string]interface{}{
    96  				"foo": map[string]interface{}{
    97  					"bar": "hello world",
    98  				},
    99  			},
   100  		},
   101  		{
   102  			name:        "set nested field from value",
   103  			mapping:     `root.foo.bar = "hello world"`,
   104  			overlay:     "value type",
   105  			errContains: "the root was a non-object type",
   106  		},
   107  		{
   108  			name:    "set nested field from object",
   109  			mapping: `root.foo.bar = "hello world"`,
   110  			overlay: map[string]interface{}{
   111  				"baz": "started with this",
   112  			},
   113  			output: map[string]interface{}{
   114  				"foo": map[string]interface{}{
   115  					"bar": "hello world",
   116  				},
   117  				"baz": "started with this",
   118  			},
   119  		},
   120  		{
   121  			name:    "not mapped",
   122  			mapping: `root = if false { "not this" }`,
   123  			overlay: map[string]interface{}{
   124  				"hello": "world",
   125  			},
   126  			output: map[string]interface{}{
   127  				"hello": "world",
   128  			},
   129  		},
   130  		{
   131  			name:        "delete root for some reason",
   132  			mapping:     `root = deleted()`,
   133  			errContains: "root was deleted",
   134  		},
   135  	}
   136  
   137  	for _, test := range tests {
   138  		t.Run(test.name, func(t *testing.T) {
   139  			m, err := NewEnvironment().Parse(test.mapping)
   140  			require.NoError(t, err)
   141  
   142  			res := test.overlay
   143  			err = m.Overlay(test.input, &res)
   144  			if test.errContains == "" {
   145  				require.NoError(t, err)
   146  				assert.Equal(t, test.output, res)
   147  			} else {
   148  				require.Error(t, err)
   149  				assert.Contains(t, err.Error(), test.errContains)
   150  			}
   151  		})
   152  	}
   153  }
   154  
   155  func TestExecutorQueryVarAllocation(t *testing.T) {
   156  	m, err := NewEnvironment().Parse(`
   157  root.foo = $meow | "not init"
   158  let meow = "meow meow"
   159  root.bar = $meow | "not init"
   160  root.baz = this.input
   161  	`)
   162  	require.NoError(t, err)
   163  
   164  	expected := map[string]interface{}{
   165  		"foo": "not init",
   166  		"bar": "meow meow",
   167  		"baz": "from input",
   168  	}
   169  
   170  	res, err := m.Query(map[string]interface{}{
   171  		"input": "from input",
   172  	})
   173  	require.NoError(t, err)
   174  	assert.Equal(t, expected, res)
   175  
   176  	// Run it again and make sure our variables were reset.
   177  	res, err = m.Query(map[string]interface{}{
   178  		"input": "from input 2",
   179  	})
   180  	expected["baz"] = "from input 2"
   181  	require.NoError(t, err)
   182  	assert.Equal(t, expected, res)
   183  }
   184  
   185  func TestExecutorOverlayVarAllocation(t *testing.T) {
   186  	m, err := NewEnvironment().Parse(`
   187  root.foo = $meow | "not init"
   188  let meow = "meow meow"
   189  root.bar = $meow | "not init"
   190  root.baz = this.input
   191  	`)
   192  	require.NoError(t, err)
   193  
   194  	expected := map[string]interface{}{
   195  		"started": "with this",
   196  		"foo":     "not init",
   197  		"bar":     "meow meow",
   198  		"baz":     "from input",
   199  	}
   200  
   201  	var onto interface{} = map[string]interface{}{
   202  		"started": "with this",
   203  	}
   204  
   205  	err = m.Overlay(map[string]interface{}{
   206  		"input": "from input",
   207  	}, &onto)
   208  	require.NoError(t, err)
   209  	assert.Equal(t, expected, onto)
   210  
   211  	// Run it again and make sure our variables were reset.
   212  	err = m.Overlay(map[string]interface{}{
   213  		"input": "from input 2",
   214  	}, &onto)
   215  	require.NoError(t, err)
   216  	expected["baz"] = "from input 2"
   217  	assert.Equal(t, expected, onto)
   218  }