go.mondoo.com/cnquery@v0.0.0-20231005093811-59568235f6ea/mqlc/mqlc_test.go (about)

     1  // Copyright (c) Mondoo, Inc.
     2  // SPDX-License-Identifier: BUSL-1.1
     3  
     4  package mqlc_test
     5  
     6  import (
     7  	"errors"
     8  	"fmt"
     9  	"sort"
    10  	"testing"
    11  
    12  	"github.com/stretchr/testify/assert"
    13  	"github.com/stretchr/testify/require"
    14  	"go.mondoo.com/cnquery"
    15  	"go.mondoo.com/cnquery/llx"
    16  	"go.mondoo.com/cnquery/logger"
    17  	"go.mondoo.com/cnquery/mqlc"
    18  	"go.mondoo.com/cnquery/types"
    19  
    20  	"go.mondoo.com/cnquery/providers-sdk/v1/testutils"
    21  )
    22  
    23  var (
    24  	features    = cnquery.Features{}
    25  	core_schema = testutils.MustLoadSchema(testutils.SchemaProvider{Provider: "core"})
    26  	os_schema   = testutils.MustLoadSchema(testutils.SchemaProvider{Provider: "os"})
    27  	conf        = mqlc.NewConfig(
    28  		core_schema.Add(os_schema),
    29  		features,
    30  	)
    31  )
    32  
    33  func init() {
    34  	logger.InitTestEnv()
    35  }
    36  
    37  func compileProps(t *testing.T, s string, props map[string]*llx.Primitive, f func(res *llx.CodeBundle)) {
    38  	res, err := mqlc.Compile(s, props, conf)
    39  	require.Nil(t, err)
    40  	require.NotNil(t, res)
    41  	require.NotNil(t, res.CodeV2)
    42  	assert.NoError(t, mqlc.Invariants.Check(res))
    43  
    44  	assert.Nil(t, res.Suggestions)
    45  	require.NotEmpty(t, res.CodeV2.Blocks)
    46  	f(res)
    47  }
    48  
    49  func compileT(t *testing.T, s string, f func(res *llx.CodeBundle)) {
    50  	compileProps(t, s, nil, f)
    51  }
    52  
    53  func compileCtx(t *testing.T, s string, f func(res *llx.CodeBundle)) {
    54  	nuConf := conf
    55  	nuConf.UseAssetContext = true
    56  	res, err := mqlc.Compile(s, nil, nuConf)
    57  	assert.Nil(t, err)
    58  	assert.NotNil(t, res)
    59  	assert.NoError(t, mqlc.Invariants.Check(res))
    60  	if res != nil && res.CodeV2 != nil {
    61  		assert.Nil(t, res.Suggestions)
    62  		if assert.NotEmpty(t, res.CodeV2.Blocks) {
    63  			f(res)
    64  		}
    65  	}
    66  }
    67  
    68  func compileEmpty(t *testing.T, s string, f func(res *llx.CodeBundle)) {
    69  	res, err := mqlc.Compile(s, nil, conf)
    70  	require.NoError(t, err)
    71  	require.NotNil(t, res)
    72  	require.Nil(t, res.Suggestions)
    73  
    74  	f(res)
    75  }
    76  
    77  func compileErroneous(t *testing.T, s string, expectedError error, f func(res *llx.CodeBundle)) {
    78  	res, err := mqlc.Compile(s, nil, conf)
    79  
    80  	if err != nil && expectedError != nil {
    81  		assert.Equal(t, expectedError.Error(), err.Error())
    82  	} else {
    83  		assert.Equal(t, expectedError, err)
    84  	}
    85  
    86  	if f != nil {
    87  		f(res)
    88  	}
    89  }
    90  
    91  func assertPrimitive(t *testing.T, p *llx.Primitive, chunk *llx.Chunk) {
    92  	assert.Equal(t, llx.Chunk_PRIMITIVE, chunk.Call)
    93  	assert.Nil(t, chunk.Function)
    94  	assert.Equal(t, p, chunk.Primitive)
    95  }
    96  
    97  func assertFunction(t *testing.T, id string, f *llx.Function, chunk *llx.Chunk) {
    98  	assert.Equal(t, llx.Chunk_FUNCTION, chunk.Call)
    99  	assert.Equal(t, id, chunk.Id, "chunk.Id")
   100  	assert.Nil(t, chunk.Primitive, "it is not a primitive")
   101  	assert.Equal(t, f, chunk.Function, "chunk.Function")
   102  }
   103  
   104  func assertProperty(t *testing.T, name string, typ types.Type, chunk *llx.Chunk) {
   105  	assert.Equal(t, llx.Chunk_PROPERTY, chunk.Call)
   106  	assert.Equal(t, name, chunk.Id, "property name is set")
   107  	assert.Equal(t, &llx.Primitive{Type: string(typ)}, chunk.Primitive, "property type is set")
   108  }
   109  
   110  //    ===========================
   111  //   👋   VALUES + OPERATIONS   🍹
   112  //    ===========================
   113  
   114  func TestCompiler_Basics(t *testing.T) {
   115  	data := []struct {
   116  		code string
   117  	}{
   118  		{""},
   119  		{"// some comment"},
   120  		{"// some comment\n"},
   121  	}
   122  	for _, v := range data {
   123  		t.Run(v.code, func(t *testing.T) {
   124  			compileEmpty(t, v.code, func(res *llx.CodeBundle) {
   125  				assert.Empty(t, res.CodeV2.Blocks[0].Chunks)
   126  			})
   127  		})
   128  	}
   129  }
   130  
   131  func TestCompiler_Buggy(t *testing.T) {
   132  	data := []struct {
   133  		code string
   134  		res  []*llx.Chunk
   135  		err  error
   136  	}{
   137  		{`parse parse`, []*llx.Chunk{
   138  			{Id: "parse", Call: llx.Chunk_FUNCTION},
   139  			{Id: "parse", Call: llx.Chunk_FUNCTION},
   140  		}, nil},
   141  		{`parse # mondoo`, []*llx.Chunk{
   142  			{Id: "parse", Call: llx.Chunk_FUNCTION},
   143  		}, nil},
   144  		{`parse }`, []*llx.Chunk{
   145  			{Id: "parse", Call: llx.Chunk_FUNCTION},
   146  		}, errors.New("mismatched symbol '}' at the end of expression")},
   147  		{`parse ]`, []*llx.Chunk{
   148  			{Id: "parse", Call: llx.Chunk_FUNCTION},
   149  		}, errors.New("mismatched symbol ']' at the end of expression")},
   150  		{`parse )`, []*llx.Chunk{
   151  			{Id: "parse", Call: llx.Chunk_FUNCTION},
   152  		}, errors.New("mismatched symbol ')' at the end of expression")},
   153  		{`mondoo { version }`, []*llx.Chunk{
   154  			{Id: "mondoo", Call: llx.Chunk_FUNCTION},
   155  			{Id: "{}", Call: llx.Chunk_FUNCTION, Function: &llx.Function{
   156  				Type:    string(types.Block),
   157  				Binding: (1 << 32) | 1,
   158  				Args:    []*llx.Primitive{llx.FunctionPrimitive(2 << 32)},
   159  			}},
   160  		}, nil},
   161  		{"# ..\nmondoo { \n# ..\nversion\n# ..\n}\n# ..", []*llx.Chunk{
   162  			{Call: llx.Chunk_FUNCTION, Id: "mondoo"},
   163  			{Call: llx.Chunk_FUNCTION, Id: "{}", Function: &llx.Function{
   164  				Type:    string(types.Block),
   165  				Binding: (1 << 32) | 1,
   166  				Args:    []*llx.Primitive{llx.FunctionPrimitive(2 << 32)},
   167  			}},
   168  		}, nil},
   169  		{`users.list[]`, nil, errors.New("missing value inside of `[]` at <source>:1:12")},
   170  		{`file(not-there)`, nil, errors.New("addResourceCall error: cannot find resource for identifier 'not'")},
   171  		{`if(true) {`, []*llx.Chunk{
   172  			{Call: llx.Chunk_FUNCTION, Id: "if", Function: &llx.Function{
   173  				Type: string(types.Block),
   174  				Args: []*llx.Primitive{
   175  					llx.BoolPrimitive(true),
   176  					llx.FunctionPrimitive(2 << 32),
   177  					llx.ArrayPrimitive([]*llx.Primitive{}, types.Ref),
   178  				},
   179  			}},
   180  		}, errors.New("incomplete query, missing closing '}' at <source>:1:11")},
   181  		{`if(true) { return 1 } else { return 2 } return 3`, []*llx.Chunk{
   182  			{Call: llx.Chunk_FUNCTION, Id: "if", Function: &llx.Function{
   183  				Type: string(types.Int),
   184  				Args: []*llx.Primitive{
   185  					llx.BoolPrimitive(true),
   186  					llx.FunctionPrimitive(2 << 32),
   187  					llx.ArrayPrimitive([]*llx.Primitive{}, types.Ref),
   188  					llx.FunctionPrimitive(3 << 32),
   189  					llx.ArrayPrimitive([]*llx.Primitive{}, types.Ref),
   190  				},
   191  			}},
   192  		}, errors.New("single valued block followed by expressions")},
   193  		{`parse.date`, []*llx.Chunk{
   194  			{Id: "parse", Call: llx.Chunk_FUNCTION},
   195  		}, errors.New("missing arguments to parse date")},
   196  		{`parse.date()`, []*llx.Chunk{
   197  			{Id: "parse", Call: llx.Chunk_FUNCTION},
   198  		}, errors.New("missing arguments to parse date")},
   199  		{`switch(mondoo) { case`, nil, errors.New("missing expression after `case` statement")},
   200  	}
   201  
   202  	for _, v := range data {
   203  		t.Run(v.code, func(t *testing.T) {
   204  			compileErroneous(t, v.code, v.err, func(res *llx.CodeBundle) {
   205  				if res.CodeV2 != nil {
   206  					assert.Equal(t, v.res, res.CodeV2.Blocks[0].Chunks)
   207  				} else {
   208  					assert.Nil(t, v.res)
   209  				}
   210  			})
   211  		})
   212  	}
   213  }
   214  
   215  func TestCompiler_Semicolon(t *testing.T) {
   216  	compileT(t, "mondoo.version;mondoo.build", func(res *llx.CodeBundle) {
   217  		require.Len(t, res.CodeV2.Blocks, 1)
   218  		require.Len(t, res.CodeV2.Blocks[0].Chunks, 4)
   219  		assertFunction(t, "version",
   220  			&llx.Function{Binding: (1 << 32) | 1, Type: string(types.String)},
   221  			res.CodeV2.Blocks[0].Chunks[1])
   222  		assertFunction(t, "build",
   223  			&llx.Function{Binding: (1 << 32) | 3, Type: string(types.String)},
   224  			res.CodeV2.Blocks[0].Chunks[3])
   225  	})
   226  
   227  	compileT(t, "mondoo{version;build}", func(res *llx.CodeBundle) {
   228  		require.Len(t, res.CodeV2.Blocks, 2)
   229  		require.Len(t, res.CodeV2.Blocks[1].Chunks, 3)
   230  		assertFunction(t, "version",
   231  			&llx.Function{Binding: (2 << 32) | 1, Type: string(types.String)},
   232  			res.CodeV2.Blocks[1].Chunks[1])
   233  		assertFunction(t, "build",
   234  			&llx.Function{Binding: (2 << 32) | 1, Type: string(types.String)},
   235  			res.CodeV2.Blocks[1].Chunks[2])
   236  	})
   237  }
   238  
   239  func TestCompiler_DeterministicChecksum(t *testing.T) {
   240  	// this is a query that in the past used to produce different checksum every now and then
   241  	// this test ensures that the checksum is always deterministic now
   242  	mql := `azure.subscription.sql.servers.all(databases.one (transparentDataEncryption["state"] == "Enabled") && encryptionProtector["serverKeyType"] == "AzureKeyVault" )`
   243  	azure_schema := testutils.MustLoadSchema(testutils.SchemaProvider{Provider: "azure"})
   244  
   245  	for i := 0; i < 10_000; i++ {
   246  		azureConf := mqlc.NewConfig(azure_schema, features)
   247  		res, err := mqlc.Compile(mql, map[string]*llx.Primitive{}, azureConf)
   248  		require.Nil(t, err)
   249  		require.Equal(t, res.CodeV2.Id, "LkB8PP3xB2Q=")
   250  	}
   251  }
   252  
   253  func TestCompiler_Simple(t *testing.T) {
   254  	data := []struct {
   255  		code string
   256  		res  *llx.Primitive
   257  	}{
   258  		{"null", llx.NilPrimitive},
   259  		{"false", llx.BoolPrimitive(false)},
   260  		{"true", llx.BoolPrimitive(true)},
   261  		{"123", llx.IntPrimitive(123)},
   262  		{"010", llx.IntPrimitive(8)},
   263  		{"12.3", llx.FloatPrimitive(12.3)},
   264  		{"\"hi\"", llx.StringPrimitive("hi")},
   265  		{"/hi/", llx.RegexPrimitive("hi")},
   266  		{"[true, false]", &llx.Primitive{
   267  			Type: string(types.Array(types.Bool)),
   268  			Array: []*llx.Primitive{
   269  				llx.BoolPrimitive(true),
   270  				llx.BoolPrimitive(false),
   271  			},
   272  		}},
   273  		{"[1, 2]", &llx.Primitive{
   274  			Type: string(types.Array(types.Int)),
   275  			Array: []*llx.Primitive{
   276  				llx.IntPrimitive(1),
   277  				llx.IntPrimitive(2),
   278  			},
   279  		}},
   280  		{"[1.2,3.4]", &llx.Primitive{
   281  			Type: string(types.Array(types.Float)),
   282  			Array: []*llx.Primitive{
   283  				llx.FloatPrimitive(1.2),
   284  				llx.FloatPrimitive(3.4),
   285  			},
   286  		}},
   287  		{"[\"a\",\"b\"]", &llx.Primitive{
   288  			Type: string(types.Array(types.String)),
   289  			Array: []*llx.Primitive{
   290  				llx.StringPrimitive("a"),
   291  				llx.StringPrimitive("b"),
   292  			},
   293  		}},
   294  		{"[1.2,1]", &llx.Primitive{
   295  			Type: string(types.Array(types.Any)),
   296  			Array: []*llx.Primitive{
   297  				llx.FloatPrimitive(1.2),
   298  				llx.IntPrimitive(1),
   299  			},
   300  		}},
   301  		{"[\n  1.2,\n  1\n]", &llx.Primitive{
   302  			Type: string(types.Array(types.Any)),
   303  			Array: []*llx.Primitive{
   304  				llx.FloatPrimitive(1.2),
   305  				llx.IntPrimitive(1),
   306  			},
   307  		}},
   308  		{"{a: 123}", &llx.Primitive{
   309  			Type: string(types.Map(types.String, types.Int)),
   310  			Map: map[string]*llx.Primitive{
   311  				"a": llx.IntPrimitive(123),
   312  			},
   313  		}},
   314  	}
   315  	for _, v := range data {
   316  		t.Run(v.code, func(t *testing.T) {
   317  			compileT(t, v.code, func(res *llx.CodeBundle) {
   318  				o := res.CodeV2.Blocks[0].Chunks[0]
   319  				assert.Equal(t, llx.Chunk_PRIMITIVE, o.Call)
   320  				assert.Equal(t, v.res, o.Primitive)
   321  			})
   322  		})
   323  	}
   324  }
   325  
   326  // FIXME: this is weirdly failing
   327  // func TestCompiler_SimpleArrayResource(t *testing.T) {
   328  // 	res := compileT(t, "[mochi, mochi]").Code.Code[2]
   329  // 	assert.Equal(t, llx.Chunk_PRIMITIVE, res.Call)
   330  // 	assert.Equal(t, []types.Type{types.Type_ARRAY, types.Type_ANY}, res.Primitive.Type)
   331  // 	assert.Equal(t, []*llx.Primitive{
   332  // 		llx.RefPrimitive(1),
   333  // 		llx.RefPrimitive(2),
   334  // 	}, res.Primitive.Array)
   335  // 	assert.Nil(t, res.Primitive.Value)
   336  // }
   337  
   338  func TestCompiler_Comparisons(t *testing.T) {
   339  	ops := []string{"==", "!=", ">", "<", ">=", "<="}
   340  	vals := map[string]*llx.Primitive{
   341  		"1":       llx.IntPrimitive(1),
   342  		"1.2":     llx.FloatPrimitive(1.2),
   343  		"true":    llx.BoolPrimitive(true),
   344  		"\"str\"": llx.StringPrimitive("str"),
   345  		"/str/":   llx.RegexPrimitive("str"),
   346  	}
   347  	for _, op := range ops {
   348  		for val, valres := range vals {
   349  			if types.Type(valres.Type) != types.Int && types.Type(valres.Type) != types.Float && types.Type(valres.Type) != types.String {
   350  				continue
   351  			}
   352  			code := val + " " + op + " " + val
   353  			t.Run(code, func(t *testing.T) {
   354  				compileT(t, code, func(res *llx.CodeBundle) {
   355  					o := res.CodeV2.Blocks[0].Chunks[0]
   356  					assert.Equal(t, valres, o.Primitive)
   357  					o = res.CodeV2.Blocks[0].Chunks[1]
   358  					assert.Equal(t, llx.Chunk_FUNCTION, o.Call)
   359  					assert.Equal(t, op+string(valres.Type), o.Id)
   360  					assert.Equal(t, uint64((1<<32)|1), o.Function.Binding)
   361  					assert.Equal(t, types.Bool, types.Type(o.Function.Type))
   362  					assert.Equal(t, valres, o.Function.Args[0])
   363  				})
   364  			})
   365  		}
   366  	}
   367  }
   368  
   369  func TestCompiler_LogicalOps(t *testing.T) {
   370  	ops := []string{"&&", "||"}
   371  	vals := map[string]*llx.Primitive{
   372  		"1":       llx.IntPrimitive(1),
   373  		"1.2":     llx.FloatPrimitive(1.2),
   374  		"true":    llx.BoolPrimitive(true),
   375  		"\"str\"": llx.StringPrimitive("str"),
   376  		"/str/":   llx.RegexPrimitive("str"),
   377  		"[]":      llx.ArrayPrimitive([]*llx.Primitive{}, types.Unset),
   378  		"{}":      llx.MapPrimitive(map[string]*llx.Primitive{}, types.Unset),
   379  	}
   380  	for _, op := range ops {
   381  		for val1, valres1 := range vals {
   382  			for val2, valres2 := range vals {
   383  				code := val1 + " " + op + " " + val2
   384  				t.Run(code, func(t *testing.T) {
   385  					compileT(t, code, func(res *llx.CodeBundle) {
   386  						l := res.CodeV2.Blocks[0].Chunks[0]
   387  						assert.Equal(t, valres1, l.Primitive)
   388  
   389  						r := res.CodeV2.Blocks[0].Chunks[1]
   390  						assert.Equal(t, llx.Chunk_FUNCTION, r.Call)
   391  						assert.Equal(t, uint64((1<<32)|1), r.Function.Binding)
   392  						assert.Equal(t, types.Bool, types.Type(r.Function.Type))
   393  						assert.Equal(t, valres2, r.Function.Args[0])
   394  
   395  						f, err := llx.BuiltinFunctionV2(l.Type(), r.Id)
   396  						assert.NoError(t, err, "was able to find builtin function for llx execution")
   397  						assert.NotNil(t, f, "was able to get non-nil builtin function")
   398  					})
   399  				})
   400  			}
   401  		}
   402  	}
   403  }
   404  
   405  func TestCompiler_Arithmetics(t *testing.T) {
   406  	t.Run("concat arrays", func(t *testing.T) {
   407  		compileT(t, "[1,2] + [3]", func(res *llx.CodeBundle) {
   408  			require.NotEmpty(t, res.CodeV2)
   409  			require.NotEmpty(t, res.CodeV2.Blocks)
   410  			chunks := res.CodeV2.Blocks[0].Chunks
   411  			require.NotEmpty(t, chunks)
   412  
   413  			assert.Equal(t, llx.Chunk_PRIMITIVE, chunks[0].Call)
   414  			assert.Equal(t, llx.Chunk_FUNCTION, chunks[1].Call)
   415  			assert.Equal(t, "+", chunks[1].Id)
   416  			assert.Equal(t, 1, len(chunks[1].Function.Args))
   417  		})
   418  	})
   419  }
   420  
   421  func TestCompiler_OperatorPrecedence(t *testing.T) {
   422  	data := []struct {
   423  		code   string
   424  		idx    int
   425  		first  string
   426  		second string
   427  	}{
   428  		{"1 || 2 && 3", 2, string("&&" + types.Int), string("||" + types.Bool)},
   429  		{"1 && 2 || 3", 1, string("&&" + types.Int), string("||" + types.Int)},
   430  	}
   431  
   432  	for _, d := range data {
   433  		t.Run(d.code, func(t *testing.T) {
   434  			compileT(t, d.code, func(res *llx.CodeBundle) {
   435  				fmt.Printf("compiled: %#v\n", res)
   436  
   437  				o := res.CodeV2.Blocks[0].Chunks[d.idx]
   438  				assert.Equal(t, d.first, o.Id)
   439  
   440  				o = res.CodeV2.Blocks[0].Chunks[d.idx+1]
   441  				assert.Equal(t, d.second, o.Id)
   442  			})
   443  		})
   444  	}
   445  }
   446  
   447  func TestCompiler_Assignment(t *testing.T) {
   448  	compileT(t, "a = 123", func(res *llx.CodeBundle) {
   449  		assertPrimitive(t, llx.IntPrimitive(123), res.CodeV2.Blocks[0].Chunks[0])
   450  		assert.Empty(t, res.CodeV2.Entrypoints())
   451  	})
   452  	compileT(t, "a = 123\na", func(res *llx.CodeBundle) {
   453  		assertPrimitive(t, llx.RefPrimitiveV2((1<<32)|1), res.CodeV2.Blocks[0].Chunks[1])
   454  		assert.Equal(t, []uint64{(1 << 32) | 2}, res.CodeV2.Entrypoints())
   455  	})
   456  }
   457  
   458  func TestCompiler_Props(t *testing.T) {
   459  	compileProps(t, "props.name", map[string]*llx.Primitive{
   460  		"name": {Type: string(types.String)},
   461  	}, func(res *llx.CodeBundle) {
   462  		assertProperty(t, "name", types.String, res.CodeV2.Blocks[0].Chunks[0])
   463  		assert.Equal(t, []uint64{(1 << 32) | 1}, res.CodeV2.Entrypoints())
   464  		assert.Equal(t, map[string]string{"name": string(types.String)}, res.Props)
   465  	})
   466  
   467  	// prop <op> value
   468  	compileProps(t, "props.name == 'bob'", map[string]*llx.Primitive{
   469  		"name": {Type: string(types.String)},
   470  	}, func(res *llx.CodeBundle) {
   471  		assertProperty(t, "name", types.String, res.CodeV2.Blocks[0].Chunks[0])
   472  		assertFunction(t, "=="+string(types.String), &llx.Function{
   473  			Type:    string(types.Bool),
   474  			Binding: (1 << 32) | 1,
   475  			Args:    []*llx.Primitive{llx.StringPrimitive("bob")},
   476  		}, res.CodeV2.Blocks[0].Chunks[1])
   477  		assert.Equal(t, []uint64{(1 << 32) | 2}, res.CodeV2.Entrypoints())
   478  		assert.Equal(t, map[string]string{"name": string(types.String)}, res.Props)
   479  	})
   480  
   481  	// different compile stages yielding the same checksums
   482  	compileProps(t, "props.name == 'bob'", map[string]*llx.Primitive{
   483  		"name": {Type: string(types.String)},
   484  	}, func(res1 *llx.CodeBundle) {
   485  		compileProps(t, "props.name == 'bob'", map[string]*llx.Primitive{
   486  			"name": {Type: string(types.String), Value: []byte("yoman")},
   487  		}, func(res2 *llx.CodeBundle) {
   488  			assert.Equal(t, res2.CodeV2.Id, res1.CodeV2.Id)
   489  		})
   490  	})
   491  
   492  	compileProps(t, "props.name == props.name", map[string]*llx.Primitive{
   493  		"name": {Type: string(types.String)},
   494  	}, func(res *llx.CodeBundle) {
   495  		assertProperty(t, "name", types.String, res.CodeV2.Blocks[0].Chunks[0])
   496  		assertProperty(t, "name", types.String, res.CodeV2.Blocks[0].Chunks[1])
   497  		assertFunction(t, "=="+string(types.String), &llx.Function{
   498  			Type:    string(types.Bool),
   499  			Binding: (1 << 32) | 1,
   500  			Args:    []*llx.Primitive{llx.RefPrimitiveV2((1 << 32) | 2)},
   501  		}, res.CodeV2.Blocks[0].Chunks[2])
   502  		assert.Equal(t, []uint64{(1 << 32) | 3}, res.CodeV2.Entrypoints())
   503  		assert.Equal(t, map[string]string{"name": string(types.String)}, res.Props)
   504  	})
   505  }
   506  
   507  func TestCompiler_Dict(t *testing.T) {
   508  	compileProps(t, "props.d.A.B", map[string]*llx.Primitive{
   509  		"d": {Type: string(types.Dict)},
   510  	}, func(res *llx.CodeBundle) {
   511  		assertProperty(t, "d", types.Dict, res.CodeV2.Blocks[0].Chunks[0])
   512  		assert.Equal(t, []uint64{(1 << 32) | 3}, res.CodeV2.Entrypoints())
   513  		assertFunction(t, "[]", &llx.Function{
   514  			Type:    string(types.Dict),
   515  			Binding: (1 << 32) | 1,
   516  			Args:    []*llx.Primitive{llx.StringPrimitive("A")},
   517  		}, res.CodeV2.Blocks[0].Chunks[1])
   518  		assertFunction(t, "[]", &llx.Function{
   519  			Type:    string(types.Dict),
   520  			Binding: (1 << 32) | 2,
   521  			Args:    []*llx.Primitive{llx.StringPrimitive("B")},
   522  		}, res.CodeV2.Blocks[0].Chunks[2])
   523  		assert.Equal(t, map[string]string{"d": string(types.Dict)}, res.Props)
   524  	})
   525  
   526  	compileProps(t, "props.d.A-1", map[string]*llx.Primitive{
   527  		"d": {Type: string(types.Dict)},
   528  	}, func(res *llx.CodeBundle) {
   529  		assertProperty(t, "d", types.Dict, res.CodeV2.Blocks[0].Chunks[0])
   530  		assert.Equal(t, []uint64{(1 << 32) | 2, (1 << 32) | 3}, res.CodeV2.Entrypoints())
   531  		assertFunction(t, "[]", &llx.Function{
   532  			Type:    string(types.Dict),
   533  			Binding: (1 << 32) | 1,
   534  			Args:    []*llx.Primitive{llx.StringPrimitive("A")},
   535  		}, res.CodeV2.Blocks[0].Chunks[1])
   536  		assertPrimitive(t, llx.IntPrimitive(-1), res.CodeV2.Blocks[0].Chunks[2])
   537  		assert.Equal(t, map[string]string{"d": string(types.Dict)}, res.Props)
   538  	})
   539  }
   540  
   541  func TestCompiler_If(t *testing.T) {
   542  	compileT(t, "if ( true ) { return 1 } else if ( false ) { return 2 } else { return 3 }", func(res *llx.CodeBundle) {
   543  		assertFunction(t, "if", &llx.Function{
   544  			Type:    string(types.Int),
   545  			Binding: 0,
   546  			Args: []*llx.Primitive{
   547  				llx.BoolPrimitive(true),
   548  				llx.FunctionPrimitive(2 << 32),
   549  				llx.ArrayPrimitive([]*llx.Primitive{}, types.Ref),
   550  				llx.BoolPrimitive(false),
   551  				llx.FunctionPrimitive(3 << 32),
   552  				llx.ArrayPrimitive([]*llx.Primitive{}, types.Ref),
   553  				llx.FunctionPrimitive(4 << 32),
   554  				llx.ArrayPrimitive([]*llx.Primitive{}, types.Ref),
   555  			},
   556  		}, res.CodeV2.Blocks[0].Chunks[0])
   557  		assert.Equal(t, []uint64{(1 << 32) | 1}, res.CodeV2.Entrypoints())
   558  		assert.Equal(t, []uint64(nil), res.CodeV2.Datapoints())
   559  
   560  		assertPrimitive(t, llx.IntPrimitive(1), res.CodeV2.Blocks[1].Chunks[0])
   561  		assertFunction(t, "return", &llx.Function{
   562  			Type:    string(types.Int),
   563  			Binding: 0,
   564  			Args: []*llx.Primitive{
   565  				llx.RefPrimitiveV2((2 << 32) | 1),
   566  			},
   567  		}, res.CodeV2.Blocks[1].Chunks[1])
   568  		assert.Equal(t, []uint64{(2 << 32) | 2}, res.CodeV2.Blocks[1].Entrypoints)
   569  
   570  		assertPrimitive(t, llx.IntPrimitive(2), res.CodeV2.Blocks[2].Chunks[0])
   571  		assertFunction(t, "return", &llx.Function{
   572  			Type:    string(types.Int),
   573  			Binding: 0,
   574  			Args: []*llx.Primitive{
   575  				llx.RefPrimitiveV2((3 << 32) | 1),
   576  			},
   577  		}, res.CodeV2.Blocks[2].Chunks[1])
   578  		assert.Equal(t, []uint64{(3 << 32) | 2}, res.CodeV2.Blocks[2].Entrypoints)
   579  
   580  		assertPrimitive(t, llx.IntPrimitive(3), res.CodeV2.Blocks[3].Chunks[0])
   581  		assertFunction(t, "return", &llx.Function{
   582  			Type:    string(types.Int),
   583  			Binding: 0,
   584  			Args: []*llx.Primitive{
   585  				llx.RefPrimitiveV2((4 << 32) | 1),
   586  			},
   587  		}, res.CodeV2.Blocks[3].Chunks[1])
   588  		assert.Equal(t, []uint64{(4 << 32) | 2}, res.CodeV2.Blocks[3].Entrypoints)
   589  	})
   590  
   591  	compileT(t, "if ( mondoo ) { return 123 } if ( true ) { return 456 } 789", func(res *llx.CodeBundle) {
   592  		assertFunction(t, "mondoo", nil, res.CodeV2.Blocks[0].Chunks[0])
   593  
   594  		assertFunction(t, "if", &llx.Function{
   595  			Type:    string(types.Int),
   596  			Binding: 0,
   597  			Args: []*llx.Primitive{
   598  				llx.RefPrimitiveV2((1 << 32) | 1),
   599  				llx.FunctionPrimitive(2 << 32),
   600  				llx.ArrayPrimitive([]*llx.Primitive{}, types.Ref),
   601  				llx.FunctionPrimitive(3 << 32),
   602  				llx.ArrayPrimitive([]*llx.Primitive{}, types.Ref),
   603  			},
   604  		}, res.CodeV2.Blocks[0].Chunks[1])
   605  		assert.Equal(t, []uint64{(1 << 32) | 2}, res.CodeV2.Entrypoints())
   606  		assert.Equal(t, []uint64(nil), res.CodeV2.Datapoints())
   607  
   608  		assertPrimitive(t, llx.IntPrimitive(123), res.CodeV2.Blocks[1].Chunks[0])
   609  		assertFunction(t, "return", &llx.Function{
   610  			Type:    string(types.Int),
   611  			Binding: 0,
   612  			Args: []*llx.Primitive{
   613  				llx.RefPrimitiveV2((2 << 32) | 1),
   614  			},
   615  		}, res.CodeV2.Blocks[1].Chunks[1])
   616  		assert.Equal(t, []uint64{(2 << 32) | 2}, res.CodeV2.Blocks[1].Entrypoints)
   617  
   618  		assertFunction(t, "if", &llx.Function{
   619  			Type:    string(types.Int),
   620  			Binding: 0,
   621  			Args: []*llx.Primitive{
   622  				llx.BoolPrimitive(true),
   623  				llx.FunctionPrimitive(4 << 32),
   624  				llx.ArrayPrimitive([]*llx.Primitive{}, types.Ref),
   625  				llx.FunctionPrimitive(5 << 32),
   626  				llx.ArrayPrimitive([]*llx.Primitive{}, types.Ref),
   627  			},
   628  		}, res.CodeV2.Blocks[2].Chunks[0])
   629  		assert.Equal(t, []uint64{(3 << 32) | 1}, res.CodeV2.Blocks[2].Entrypoints)
   630  
   631  		assertPrimitive(t, llx.IntPrimitive(456), res.CodeV2.Blocks[3].Chunks[0])
   632  		assertFunction(t, "return", &llx.Function{
   633  			Type:    string(types.Int),
   634  			Binding: 0,
   635  			Args: []*llx.Primitive{
   636  				llx.RefPrimitiveV2((4 << 32) | 1),
   637  			},
   638  		}, res.CodeV2.Blocks[3].Chunks[1])
   639  		assert.Equal(t, []uint64{(4 << 32) | 2}, res.CodeV2.Blocks[3].Entrypoints)
   640  
   641  		assertPrimitive(t, llx.IntPrimitive(789), res.CodeV2.Blocks[4].Chunks[0])
   642  		assert.Equal(t, []uint64{(5 << 32) | 1}, res.CodeV2.Blocks[4].Entrypoints)
   643  	})
   644  
   645  	compileT(t, "if ( mondoo ) { return 123 } 456", func(res *llx.CodeBundle) {
   646  		assertFunction(t, "mondoo", nil, res.CodeV2.Blocks[0].Chunks[0])
   647  
   648  		assertFunction(t, "if", &llx.Function{
   649  			Type:    string(types.Int),
   650  			Binding: 0,
   651  			Args: []*llx.Primitive{
   652  				llx.RefPrimitiveV2((1 << 32) | 1),
   653  				llx.FunctionPrimitive(2 << 32),
   654  				llx.ArrayPrimitive([]*llx.Primitive{}, types.Ref),
   655  				llx.FunctionPrimitive(3 << 32),
   656  				llx.ArrayPrimitive([]*llx.Primitive{}, types.Ref),
   657  			},
   658  		}, res.CodeV2.Blocks[0].Chunks[1])
   659  		assert.Equal(t, []uint64{(1 << 32) | 2}, res.CodeV2.Entrypoints())
   660  		assert.Equal(t, []uint64(nil), res.CodeV2.Datapoints())
   661  
   662  		assertPrimitive(t, llx.IntPrimitive(123), res.CodeV2.Blocks[1].Chunks[0])
   663  		assertFunction(t, "return", &llx.Function{
   664  			Type:    string(types.Int),
   665  			Binding: 0,
   666  			Args: []*llx.Primitive{
   667  				llx.RefPrimitiveV2((2 << 32) | 1),
   668  			},
   669  		}, res.CodeV2.Blocks[1].Chunks[1])
   670  		assert.Equal(t, []uint64{(2 << 32) | 2}, res.CodeV2.Blocks[1].Entrypoints)
   671  
   672  		assertPrimitive(t, llx.IntPrimitive(456), res.CodeV2.Blocks[2].Chunks[0])
   673  		assert.Equal(t, []uint64{(3 << 32) | 1}, res.CodeV2.Blocks[2].Entrypoints)
   674  	})
   675  
   676  	// Test empty array with filled array and type-consolidation in the compiler
   677  	compileT(t, "if ( mondoo ) { return [] } return [1,2,3]", func(res *llx.CodeBundle) {
   678  		assertFunction(t, "mondoo", nil, res.CodeV2.Blocks[0].Chunks[0])
   679  
   680  		assertFunction(t, "if", &llx.Function{
   681  			Type:    string(types.Array(types.Int)),
   682  			Binding: 0,
   683  			Args: []*llx.Primitive{
   684  				llx.RefPrimitiveV2((1 << 32) | 1),
   685  				llx.FunctionPrimitive(2 << 32),
   686  				llx.ArrayPrimitive([]*llx.Primitive{}, types.Ref),
   687  				llx.FunctionPrimitive(3 << 32),
   688  				llx.ArrayPrimitive([]*llx.Primitive{}, types.Ref),
   689  			},
   690  		}, res.CodeV2.Blocks[0].Chunks[1])
   691  		assert.Equal(t, []uint64{(1 << 32) | 2}, res.CodeV2.Entrypoints())
   692  		assert.Equal(t, []uint64(nil), res.CodeV2.Datapoints())
   693  
   694  		assertPrimitive(t, llx.ArrayPrimitive([]*llx.Primitive{}, types.Unset),
   695  			res.CodeV2.Blocks[1].Chunks[0])
   696  		assertFunction(t, "return", &llx.Function{
   697  			Type:    string(types.Array(types.Unset)),
   698  			Binding: 0,
   699  			Args: []*llx.Primitive{
   700  				llx.RefPrimitiveV2((2 << 32) | 1),
   701  			},
   702  		}, res.CodeV2.Blocks[1].Chunks[1])
   703  		assert.Equal(t, []uint64{(2 << 32) | 2}, res.CodeV2.Blocks[1].Entrypoints)
   704  	})
   705  
   706  	compileT(t, "if ( mondoo.version != null ) { 123 }", func(res *llx.CodeBundle) {
   707  		assertFunction(t, "mondoo", nil, res.CodeV2.Blocks[0].Chunks[0])
   708  		assertFunction(t, "version", &llx.Function{
   709  			Type:    string(types.String),
   710  			Binding: (1 << 32) | 1,
   711  		}, res.CodeV2.Blocks[0].Chunks[1])
   712  		assertFunction(t, "!=\x02", &llx.Function{
   713  			Type:    string(types.Bool),
   714  			Binding: (1 << 32) | 2,
   715  			Args:    []*llx.Primitive{llx.NilPrimitive},
   716  		}, res.CodeV2.Blocks[0].Chunks[2])
   717  
   718  		assertFunction(t, "if", &llx.Function{
   719  			Type:    string(types.Block),
   720  			Binding: 0,
   721  			Args: []*llx.Primitive{
   722  				llx.RefPrimitiveV2((1 << 32) | 3),
   723  				llx.FunctionPrimitive(2 << 32),
   724  				llx.ArrayPrimitive([]*llx.Primitive{}, types.Ref),
   725  			},
   726  		}, res.CodeV2.Blocks[0].Chunks[3])
   727  		assert.Equal(t, []uint64{(1 << 32) | 4}, res.CodeV2.Entrypoints())
   728  		assert.Equal(t, []uint64{(1 << 32) | 2}, res.CodeV2.Datapoints())
   729  
   730  		assertPrimitive(t, llx.IntPrimitive(123), res.CodeV2.Blocks[1].Chunks[0])
   731  		assert.Equal(t, []uint64{(2 << 32) | 1}, res.CodeV2.Blocks[1].Entrypoints)
   732  	})
   733  
   734  	compileT(t, "if ( mondoo ) { 123 } else { 456 }", func(res *llx.CodeBundle) {
   735  		assertFunction(t, "mondoo", nil, res.CodeV2.Blocks[0].Chunks[0])
   736  
   737  		assertFunction(t, "if", &llx.Function{
   738  			Type:    string(types.Block),
   739  			Binding: 0,
   740  			Args: []*llx.Primitive{
   741  				llx.RefPrimitiveV2((1 << 32) | 1),
   742  				llx.FunctionPrimitive(2 << 32),
   743  				llx.ArrayPrimitive([]*llx.Primitive{}, types.Ref),
   744  				llx.FunctionPrimitive(3 << 32),
   745  				llx.ArrayPrimitive([]*llx.Primitive{}, types.Ref),
   746  			},
   747  		}, res.CodeV2.Blocks[0].Chunks[1])
   748  		assert.Equal(t, []uint64{(1 << 32) | 2}, res.CodeV2.Entrypoints())
   749  		assert.Equal(t, []uint64(nil), res.CodeV2.Datapoints())
   750  
   751  		assertPrimitive(t, llx.IntPrimitive(123), res.CodeV2.Blocks[1].Chunks[0])
   752  		assert.Equal(t, []uint64{(2 << 32) | 1}, res.CodeV2.Blocks[1].Entrypoints)
   753  
   754  		assertPrimitive(t, llx.IntPrimitive(456), res.CodeV2.Blocks[2].Chunks[0])
   755  		assert.Equal(t, []uint64{(3 << 32) | 1}, res.CodeV2.Blocks[2].Entrypoints)
   756  	})
   757  
   758  	compileT(t, "if ( mondoo ) { 123 } else if ( true ) { 456 } else { 789 }", func(res *llx.CodeBundle) {
   759  		assertFunction(t, "mondoo", nil, res.CodeV2.Blocks[0].Chunks[0])
   760  
   761  		assertFunction(t, "if", &llx.Function{
   762  			Type:    string(types.Block),
   763  			Binding: 0,
   764  			Args: []*llx.Primitive{
   765  				llx.RefPrimitiveV2((1 << 32) | 1),
   766  				llx.FunctionPrimitive(2 << 32),
   767  				llx.ArrayPrimitive([]*llx.Primitive{}, types.Ref),
   768  				llx.BoolPrimitive(true),
   769  				llx.FunctionPrimitive(3 << 32),
   770  				llx.ArrayPrimitive([]*llx.Primitive{}, types.Ref),
   771  				llx.FunctionPrimitive(4 << 32),
   772  				llx.ArrayPrimitive([]*llx.Primitive{}, types.Ref),
   773  			},
   774  		}, res.CodeV2.Blocks[0].Chunks[1])
   775  		assert.Equal(t, []uint64{(1 << 32) | 2}, res.CodeV2.Entrypoints())
   776  		assert.Equal(t, []uint64(nil), res.CodeV2.Datapoints())
   777  
   778  		assertPrimitive(t, llx.IntPrimitive(123), res.CodeV2.Blocks[1].Chunks[0])
   779  		assert.Equal(t, []uint64{(2 << 32) | 1}, res.CodeV2.Blocks[1].Entrypoints)
   780  
   781  		assertPrimitive(t, llx.IntPrimitive(456), res.CodeV2.Blocks[2].Chunks[0])
   782  		assert.Equal(t, []uint64{(3 << 32) | 1}, res.CodeV2.Blocks[2].Entrypoints)
   783  
   784  		assertPrimitive(t, llx.IntPrimitive(789), res.CodeV2.Blocks[3].Chunks[0])
   785  		assert.Equal(t, []uint64{(4 << 32) | 1}, res.CodeV2.Blocks[3].Entrypoints)
   786  	})
   787  }
   788  
   789  func TestCompiler_Switch(t *testing.T) {
   790  	compileT(t, "switch ( 1 ) { case _ > 0: true; default: false }", func(res *llx.CodeBundle) {
   791  		assertFunction(t, "switch", &llx.Function{
   792  			Type:    string(types.Bool),
   793  			Binding: 0,
   794  			Args: []*llx.Primitive{
   795  				llx.IntPrimitive(1),
   796  				llx.RefPrimitiveV2((1 << 32) | 2),
   797  				llx.FunctionPrimitive(2 << 32),
   798  				llx.ArrayPrimitive([]*llx.Primitive{
   799  					// TODO(jaym): this shouldn't be needed. Its already
   800  					// a dependency of the switch, and thus implicitly
   801  					// will already be available for any blocks
   802  					llx.RefPrimitiveV2((1 << 32) | 1),
   803  				}, types.Ref),
   804  				llx.BoolPrimitive(true),
   805  				llx.FunctionPrimitive(3 << 32),
   806  				llx.ArrayPrimitive([]*llx.Primitive{
   807  					// TODO: this shouldn't be needed
   808  					llx.RefPrimitiveV2((1 << 32) | 1),
   809  				}, types.Ref),
   810  			},
   811  		}, res.CodeV2.Blocks[0].Chunks[2])
   812  		assert.Equal(t, []uint64{(1 << 32) | 3}, res.CodeV2.Entrypoints())
   813  		assert.Empty(t, res.CodeV2.Datapoints())
   814  	})
   815  
   816  	compileT(t, "switch { case 3 > 2: 123; default: 321 }", func(res *llx.CodeBundle) {
   817  		assert.Equal(t, []uint64{(1 << 32) | 3}, res.CodeV2.Entrypoints())
   818  	})
   819  
   820  	t.Run("test types fall back to any", func(t *testing.T) {
   821  		compileT(t, "switch ( 1 ) { case _ > 0: true; case _ < 0: 'test'; default: false }", func(res *llx.CodeBundle) {
   822  			assert.Equal(t, types.Any, res.CodeV2.Blocks[0].Chunks[3].Type())
   823  		})
   824  		compileT(t, "switch ( 1 ) { case _ > 0: true; default: 'test' }", func(res *llx.CodeBundle) {
   825  			assert.Equal(t, types.Any, res.CodeV2.Blocks[0].Chunks[2].Type())
   826  		})
   827  	})
   828  }
   829  
   830  // //    =======================
   831  // //   👋   ARRAYS and MAPS   🍹
   832  // //    =======================
   833  
   834  func TestCompiler_ArrayEmptyWhere(t *testing.T) {
   835  	compileT(t, "[1,2,3].where()", func(res *llx.CodeBundle) {
   836  		assertPrimitive(t, &llx.Primitive{
   837  			Type: string(types.Array(types.Int)),
   838  			Array: []*llx.Primitive{
   839  				llx.IntPrimitive(1),
   840  				llx.IntPrimitive(2),
   841  				llx.IntPrimitive(3),
   842  			},
   843  		}, res.CodeV2.Blocks[0].Chunks[0])
   844  		assert.Equal(t, 1, len(res.CodeV2.Blocks[0].Chunks))
   845  	})
   846  }
   847  
   848  func TestCompiler_ArrayWhereStatic(t *testing.T) {
   849  	compileErroneous(t, "[1,2,3].where(sshd)", errors.New("called 'where' with wrong type; either provide a type int value or write it as an expression (e.g. \"_ == 123\")"), func(res *llx.CodeBundle) {
   850  		assertPrimitive(t, &llx.Primitive{
   851  			Type: string(types.Array(types.Int)),
   852  			Array: []*llx.Primitive{
   853  				llx.IntPrimitive(1),
   854  				llx.IntPrimitive(2),
   855  				llx.IntPrimitive(3),
   856  			},
   857  		}, res.CodeV2.Blocks[0].Chunks[0])
   858  	})
   859  
   860  	compileT(t, "[1,2,3].where(2)", func(res *llx.CodeBundle) {
   861  		assertPrimitive(t, &llx.Primitive{
   862  			Type: string(types.Array(types.Int)),
   863  			Array: []*llx.Primitive{
   864  				llx.IntPrimitive(1),
   865  				llx.IntPrimitive(2),
   866  				llx.IntPrimitive(3),
   867  			},
   868  		}, res.CodeV2.Blocks[0].Chunks[0])
   869  
   870  		assertFunction(t, "where", &llx.Function{
   871  			Type:    string(types.Array(types.Int)),
   872  			Binding: (1 << 32) | 1,
   873  			Args: []*llx.Primitive{
   874  				llx.RefPrimitiveV2((1 << 32) | 1),
   875  				llx.FunctionPrimitive(2 << 32),
   876  			},
   877  		}, res.CodeV2.Blocks[0].Chunks[1])
   878  
   879  		assert.Equal(t, 2, len(res.CodeV2.Blocks[0].Chunks))
   880  	})
   881  }
   882  
   883  func TestCompiler_ArrayContains(t *testing.T) {
   884  	compileT(t, "[1,2,3].contains(_ == 2)", func(res *llx.CodeBundle) {
   885  		assertPrimitive(t, &llx.Primitive{
   886  			Type: string(types.Array(types.Int)),
   887  			Array: []*llx.Primitive{
   888  				llx.IntPrimitive(1),
   889  				llx.IntPrimitive(2),
   890  				llx.IntPrimitive(3),
   891  			},
   892  		}, res.CodeV2.Blocks[0].Chunks[0])
   893  
   894  		assertFunction(t, "where", &llx.Function{
   895  			Type:    string(types.Array(types.Int)),
   896  			Binding: (1 << 32) | 1,
   897  			Args: []*llx.Primitive{
   898  				llx.RefPrimitiveV2((1 << 32) | 1),
   899  				llx.FunctionPrimitive(2 << 32),
   900  			},
   901  		}, res.CodeV2.Blocks[0].Chunks[1])
   902  
   903  		assertFunction(t, "length", &llx.Function{
   904  			Type:    string(types.Int),
   905  			Binding: (1 << 32) | 2,
   906  		}, res.CodeV2.Blocks[0].Chunks[2])
   907  		assertFunction(t, string(">"+types.Int), &llx.Function{
   908  			Type:    string(types.Bool),
   909  			Binding: (1 << 32) | 3,
   910  			Args:    []*llx.Primitive{llx.IntPrimitive(0)},
   911  		}, res.CodeV2.Blocks[0].Chunks[3])
   912  
   913  		assert.Equal(t, 4, len(res.CodeV2.Blocks[0].Chunks))
   914  	})
   915  }
   916  
   917  func TestCompiler_ArrayOne(t *testing.T) {
   918  	compileT(t, "[1,2,3].one(_ == 2)", func(res *llx.CodeBundle) {
   919  		assertPrimitive(t, &llx.Primitive{
   920  			Type: string(types.Array(types.Int)),
   921  			Array: []*llx.Primitive{
   922  				llx.IntPrimitive(1),
   923  				llx.IntPrimitive(2),
   924  				llx.IntPrimitive(3),
   925  			},
   926  		}, res.CodeV2.Blocks[0].Chunks[0])
   927  
   928  		assertFunction(t, "where", &llx.Function{
   929  			Type:    string(types.Array(types.Int)),
   930  			Binding: (1 << 32) | 1,
   931  			Args: []*llx.Primitive{
   932  				llx.RefPrimitiveV2((1 << 32) | 1),
   933  				llx.FunctionPrimitive(2 << 32),
   934  			},
   935  		}, res.CodeV2.Blocks[0].Chunks[1])
   936  
   937  		assertFunction(t, "$one", &llx.Function{
   938  			Type:    string(types.Bool),
   939  			Binding: (1 << 32) | 2,
   940  		}, res.CodeV2.Blocks[0].Chunks[2])
   941  		assert.Equal(t, 3, len(res.CodeV2.Blocks[0].Chunks))
   942  	})
   943  }
   944  
   945  func TestCompiler_ArrayAll(t *testing.T) {
   946  	compileT(t, "[1,2,3].all(_ < 9)", func(res *llx.CodeBundle) {
   947  		assertPrimitive(t, &llx.Primitive{
   948  			Type: string(types.Array(types.Int)),
   949  			Array: []*llx.Primitive{
   950  				llx.IntPrimitive(1),
   951  				llx.IntPrimitive(2),
   952  				llx.IntPrimitive(3),
   953  			},
   954  		}, res.CodeV2.Blocks[0].Chunks[0])
   955  
   956  		assertFunction(t, "$whereNot", &llx.Function{
   957  			Type:    string(types.Array(types.Int)),
   958  			Binding: (1 << 32) | 1,
   959  			Args: []*llx.Primitive{
   960  				llx.RefPrimitiveV2((1 << 32) | 1),
   961  				llx.FunctionPrimitive(2 << 32),
   962  			},
   963  		}, res.CodeV2.Blocks[0].Chunks[1])
   964  
   965  		assertFunction(t, "$all", &llx.Function{
   966  			Type:    string(types.Bool),
   967  			Binding: (1 << 32) | 2,
   968  		}, res.CodeV2.Blocks[0].Chunks[2])
   969  
   970  		assert.Equal(t, 3, len(res.CodeV2.Blocks[0].Chunks))
   971  	})
   972  }
   973  
   974  func TestCompiler_All_Issue1316(t *testing.T) {
   975  	// https://github.com/mondoohq/cnquery/issues/1316
   976  	compileT(t, `files.find(from: ".", type: "file").all( permissions.other_readable == false )`, func(res *llx.CodeBundle) {
   977  		require.Equal(t, 3, len(res.CodeV2.Blocks))
   978  		require.Equal(t, 6, len(res.CodeV2.Blocks[2].Chunks))
   979  		assertPrimitive(t, &llx.Primitive{
   980  			Type: string(types.Resource("file")),
   981  		}, res.CodeV2.Blocks[2].Chunks[0])
   982  		assertFunction(t, "path", &llx.Function{
   983  			Type:    string(types.String),
   984  			Binding: (3 << 32) | 1,
   985  		}, res.CodeV2.Blocks[2].Chunks[1])
   986  		assertFunction(t, "size", &llx.Function{
   987  			Type:    string(types.Int),
   988  			Binding: (3 << 32) | 1,
   989  		}, res.CodeV2.Blocks[2].Chunks[2])
   990  		assertFunction(t, "permissions", &llx.Function{
   991  			Type:    string(types.Resource("file.permissions")),
   992  			Binding: (3 << 32) | 1,
   993  		}, res.CodeV2.Blocks[2].Chunks[3])
   994  		assertFunction(t, "string", &llx.Function{
   995  			Type:    string(types.String),
   996  			Binding: (3 << 32) | 4,
   997  		}, res.CodeV2.Blocks[2].Chunks[4])
   998  		assertFunction(t, "other_readable", &llx.Function{
   999  			Type:    string(types.Bool),
  1000  			Binding: (3 << 32) | 4,
  1001  		}, res.CodeV2.Blocks[2].Chunks[5])
  1002  	})
  1003  }
  1004  
  1005  //    =================
  1006  //   👋   RESOURCES   🍹
  1007  //    =================
  1008  
  1009  func TestCompiler_Resource(t *testing.T) {
  1010  	compileT(t, "sshd", func(res *llx.CodeBundle) {
  1011  		assertFunction(t, "sshd", nil, res.CodeV2.Blocks[0].Chunks[0])
  1012  	})
  1013  }
  1014  
  1015  func TestCompiler_Resource_versioning(t *testing.T) {
  1016  	compileT(t, "sshd", func(res *llx.CodeBundle) {
  1017  		assert.Equal(t, "5.15.0", res.MinMondooVersion)
  1018  	})
  1019  }
  1020  
  1021  func TestCompiler_Resource_versioning2(t *testing.T) {
  1022  	compileT(t, "file.empty", func(res *llx.CodeBundle) {
  1023  		assert.Equal(t, "5.18.0", res.MinMondooVersion)
  1024  	})
  1025  }
  1026  
  1027  func TestCompiler_ResourceWithCall(t *testing.T) {
  1028  	compileT(t, "sshd()", func(res *llx.CodeBundle) {
  1029  		assertFunction(t, "sshd", nil, res.CodeV2.Blocks[0].Chunks[0])
  1030  	})
  1031  }
  1032  
  1033  func TestCompiler_LongResource(t *testing.T) {
  1034  	compileT(t, "sshd.config", func(res *llx.CodeBundle) {
  1035  		assertFunction(t, "sshd.config", nil, res.CodeV2.Blocks[0].Chunks[0])
  1036  	})
  1037  }
  1038  
  1039  func TestCompiler_ResourceMap(t *testing.T) {
  1040  	compileT(t, "sshd.config.params", func(res *llx.CodeBundle) {
  1041  		assertFunction(t, "sshd.config", nil, res.CodeV2.Blocks[0].Chunks[0])
  1042  		assert.Equal(t, "5.15.0", res.MinMondooVersion)
  1043  		assertFunction(t, "params", &llx.Function{
  1044  			Type:    string(types.Map(types.String, types.String)),
  1045  			Binding: (1 << 32) | 1,
  1046  		}, res.CodeV2.Blocks[0].Chunks[1])
  1047  	})
  1048  }
  1049  
  1050  func TestCompiler_ResourceMapLength(t *testing.T) {
  1051  	compileT(t, "sshd.config.params.length", func(res *llx.CodeBundle) {
  1052  		assertFunction(t, "length", &llx.Function{
  1053  			Type:    string(types.Int),
  1054  			Binding: (1 << 32) | 2,
  1055  		}, res.CodeV2.Blocks[0].Chunks[2])
  1056  	})
  1057  }
  1058  
  1059  func TestCompiler_ResourceExpansion(t *testing.T) {
  1060  	var cmd string
  1061  
  1062  	cmd = "mondoo"
  1063  	t.Run(cmd, func(t *testing.T) {
  1064  		compileT(t, cmd, func(res *llx.CodeBundle) {
  1065  			assertFunction(t, "mondoo", nil, res.CodeV2.Blocks[0].Chunks[0])
  1066  			assertFunction(t, "{}", &llx.Function{
  1067  				Binding: (1 << 32) | 1,
  1068  				Type:    string(types.Block),
  1069  				Args:    []*llx.Primitive{llx.FunctionPrimitive(2 << 32)},
  1070  			}, res.CodeV2.Blocks[0].Chunks[1])
  1071  
  1072  			assertFunction(t, "version", &llx.Function{
  1073  				Binding: (2 << 32) | 1,
  1074  				Type:    string(types.String),
  1075  			}, res.CodeV2.Blocks[1].Chunks[1])
  1076  
  1077  			assert.Equal(t, map[string]uint64{res.CodeV2.Checksums[1<<32|2]: 2 << 32}, res.AutoExpand)
  1078  			assert.Equal(t, []uint64{1<<32 | 2}, res.CodeV2.Blocks[0].Entrypoints)
  1079  		})
  1080  	})
  1081  
  1082  	cmd = "users"
  1083  	t.Run(cmd, func(t *testing.T) {
  1084  		compileT(t, cmd, func(res *llx.CodeBundle) {
  1085  			assertFunction(t, "users", nil, res.CodeV2.Blocks[0].Chunks[0])
  1086  			assertFunction(t, "list", &llx.Function{
  1087  				Binding: (1 << 32) | 1,
  1088  				Args:    nil,
  1089  				Type:    string(types.Array(types.Resource("user"))),
  1090  			}, res.CodeV2.Blocks[0].Chunks[1])
  1091  			assertFunction(t, "{}", &llx.Function{
  1092  				Binding: (1 << 32) | 2,
  1093  				Type:    string(types.Array(types.Block)),
  1094  				Args:    []*llx.Primitive{llx.FunctionPrimitive(2 << 32)},
  1095  			}, res.CodeV2.Blocks[0].Chunks[2])
  1096  
  1097  			assertFunction(t, "name", &llx.Function{
  1098  				Binding: (2 << 32) | 1,
  1099  				Type:    string(types.String),
  1100  			}, res.CodeV2.Blocks[1].Chunks[1])
  1101  			assertFunction(t, "uid", &llx.Function{
  1102  				Binding: (2 << 32) | 1,
  1103  				Type:    string(types.Int),
  1104  			}, res.CodeV2.Blocks[1].Chunks[2])
  1105  			assertFunction(t, "gid", &llx.Function{
  1106  				Binding: (2 << 32) | 1,
  1107  				Type:    string(types.Int),
  1108  			}, res.CodeV2.Blocks[1].Chunks[3])
  1109  
  1110  			assert.Equal(t, map[string]uint64{res.CodeV2.Checksums[1<<32|3]: 2 << 32}, res.AutoExpand)
  1111  			assert.Equal(t, []uint64{1<<32 | 3}, res.CodeV2.Blocks[0].Entrypoints)
  1112  			assert.Equal(t, []uint64{2<<32 | 2, 2<<32 | 3, 2<<32 | 4}, res.CodeV2.Blocks[1].Entrypoints)
  1113  		})
  1114  	})
  1115  
  1116  	cmd = "users { group }"
  1117  	t.Run(cmd, func(t *testing.T) {
  1118  		compileT(t, cmd, func(res *llx.CodeBundle) {
  1119  			require.Len(t, res.CodeV2.Blocks, 3)
  1120  
  1121  			assertFunction(t, "{}", &llx.Function{
  1122  				Binding: (1 << 32) | 2,
  1123  				Type:    string(types.Array(types.Block)),
  1124  				Args:    []*llx.Primitive{llx.FunctionPrimitive(2 << 32)},
  1125  			}, res.CodeV2.Blocks[0].Chunks[2])
  1126  
  1127  			assertFunction(t, "group", &llx.Function{
  1128  				Binding: (2 << 32) | 1,
  1129  				Type:    string(types.Resource("group")),
  1130  			}, res.CodeV2.Blocks[1].Chunks[1])
  1131  			assertFunction(t, "{}", &llx.Function{
  1132  				Binding: (2 << 32) | 2,
  1133  				Type:    string(types.Block),
  1134  				Args:    []*llx.Primitive{llx.FunctionPrimitive(3 << 32)},
  1135  			}, res.CodeV2.Blocks[1].Chunks[2])
  1136  
  1137  			assertFunction(t, "name", &llx.Function{
  1138  				Binding: (3 << 32) | 1,
  1139  				Type:    string(types.String),
  1140  			}, res.CodeV2.Blocks[2].Chunks[1])
  1141  			assertFunction(t, "gid", &llx.Function{
  1142  				Binding: (3 << 32) | 1,
  1143  				Type:    string(types.Int),
  1144  			}, res.CodeV2.Blocks[2].Chunks[2])
  1145  
  1146  			assert.Equal(t, map[string]uint64{res.CodeV2.Checksums[2<<32|3]: 3 << 32}, res.AutoExpand)
  1147  			assert.Equal(t, []uint64{1<<32 | 3}, res.CodeV2.Blocks[0].Entrypoints)
  1148  			assert.Equal(t, []uint64{2<<32 | 3}, res.CodeV2.Blocks[1].Entrypoints)
  1149  			assert.Equal(t, []uint64{3<<32 | 2, 3<<32 | 3}, res.CodeV2.Blocks[2].Entrypoints)
  1150  		})
  1151  	})
  1152  
  1153  	cmd = "pam.conf.entries['.']"
  1154  	t.Run(cmd, func(t *testing.T) {
  1155  		compileT(t, cmd, func(res *llx.CodeBundle) {
  1156  			assertFunction(t, "[]", &llx.Function{
  1157  				Binding: (1 << 32) | 2,
  1158  				Args: []*llx.Primitive{{
  1159  					Type:  string(types.String),
  1160  					Value: []byte("."),
  1161  				}},
  1162  				Type: string(types.Array(types.Resource("pam.conf.serviceEntry"))),
  1163  			}, res.CodeV2.Blocks[0].Chunks[2])
  1164  			assertFunction(t, "{}", &llx.Function{
  1165  				Binding: (1 << 32) | 3,
  1166  				Type:    string(types.Array(types.Block)),
  1167  				Args:    []*llx.Primitive{llx.FunctionPrimitive(2 << 32)},
  1168  			}, res.CodeV2.Blocks[0].Chunks[3])
  1169  
  1170  			assertFunction(t, "service", &llx.Function{
  1171  				Binding: (2 << 32) | 1,
  1172  				Type:    string(types.String),
  1173  			}, res.CodeV2.Blocks[1].Chunks[1])
  1174  		})
  1175  	})
  1176  }
  1177  
  1178  func TestCompiler_ArrayResource(t *testing.T) {
  1179  	var cmd string
  1180  
  1181  	cmd = "packages[123]"
  1182  	t.Run(cmd, func(t *testing.T) {
  1183  		compileT(t, cmd, func(res *llx.CodeBundle) {
  1184  			assertFunction(t, "list", &llx.Function{
  1185  				Binding: (1 << 32) | 1,
  1186  				Args:    nil,
  1187  				Type:    string(types.Array(types.Resource("package"))),
  1188  			}, res.CodeV2.Blocks[0].Chunks[1])
  1189  			assertFunction(t, "[]", &llx.Function{
  1190  				Binding: (1 << 32) | 2,
  1191  				Args:    []*llx.Primitive{llx.IntPrimitive(123)},
  1192  				Type:    string(types.Resource("package")),
  1193  			}, res.CodeV2.Blocks[0].Chunks[2])
  1194  		})
  1195  	})
  1196  
  1197  	cmd = "packages.length"
  1198  	t.Run(cmd, func(t *testing.T) {
  1199  		compileT(t, cmd, func(res *llx.CodeBundle) {
  1200  			assertFunction(t, "list", &llx.Function{
  1201  				Binding: (1 << 32) | 1,
  1202  				Args:    nil,
  1203  				Type:    string(types.Array(types.Resource("package"))),
  1204  			}, res.CodeV2.Blocks[0].Chunks[1])
  1205  			assertFunction(t, "length", &llx.Function{
  1206  				Binding: (1 << 32) | 1,
  1207  				Args:    []*llx.Primitive{llx.RefPrimitiveV2((1 << 32) | 2)},
  1208  				Type:    string(types.Int),
  1209  			}, res.CodeV2.Blocks[0].Chunks[2])
  1210  		})
  1211  	})
  1212  
  1213  	// FIXME: DEPRECATED, remove in v8.0 vv
  1214  	compileT(t, "packages.list[123]", func(res *llx.CodeBundle) {
  1215  		assertFunction(t, "[]", &llx.Function{
  1216  			Binding: (1 << 32) | 2,
  1217  			Args:    []*llx.Primitive{llx.IntPrimitive(123)},
  1218  			Type:    string(types.Resource("package")),
  1219  		}, res.CodeV2.Blocks[0].Chunks[2])
  1220  	})
  1221  
  1222  	compileT(t, "packages.list.length", func(res *llx.CodeBundle) {
  1223  		assertFunction(t, "list", &llx.Function{
  1224  			Binding: (1 << 32) | 1,
  1225  			Type:    string(types.Array(types.Resource("package"))),
  1226  		}, res.CodeV2.Blocks[0].Chunks[1])
  1227  		assertFunction(t, "length", &llx.Function{
  1228  			Binding: (1 << 32) | 2,
  1229  			Type:    string(types.Int),
  1230  		}, res.CodeV2.Blocks[0].Chunks[2])
  1231  	})
  1232  	// ^^
  1233  }
  1234  
  1235  func TestCompiler_ResourceFieldGlob(t *testing.T) {
  1236  	compileT(t, "mondoo{*}", func(res *llx.CodeBundle) {
  1237  		assertFunction(t, "mondoo", nil, res.CodeV2.Blocks[0].Chunks[0])
  1238  		assertFunction(t, "arch", &llx.Function{
  1239  			Type:    string(types.String),
  1240  			Binding: (2 << 32) | 1,
  1241  		}, res.CodeV2.Blocks[1].Chunks[1])
  1242  	})
  1243  
  1244  	compileT(t, "pam.conf { * }", func(res *llx.CodeBundle) {
  1245  		assertFunction(t, "pam.conf", nil, res.CodeV2.Blocks[0].Chunks[0])
  1246  		assertFunction(t, "{}", &llx.Function{
  1247  			Type:    string(types.Block),
  1248  			Binding: (1 << 32) | 1,
  1249  			Args:    []*llx.Primitive{llx.FunctionPrimitive(2 << 32)},
  1250  		}, res.CodeV2.Blocks[0].Chunks[1])
  1251  		assert.Equal(t, []uint64{(1 << 32) | 2}, res.CodeV2.Entrypoints())
  1252  
  1253  		assertPrimitive(t, &llx.Primitive{
  1254  			Type: string(types.Resource("pam.conf")),
  1255  		}, res.CodeV2.Blocks[1].Chunks[0])
  1256  		assertFunction(t, "content", &llx.Function{
  1257  			Type:    string(types.String),
  1258  			Binding: (2 << 32) | 1,
  1259  		}, res.CodeV2.Blocks[1].Chunks[1])
  1260  		assertFunction(t, "entries", &llx.Function{
  1261  			Type:    string(types.Map(types.String, types.Array(types.Resource("pam.conf.serviceEntry")))),
  1262  			Binding: (2 << 32) | 1,
  1263  		}, res.CodeV2.Blocks[1].Chunks[2])
  1264  		assertFunction(t, "files", &llx.Function{
  1265  			Type:    string(types.Array(types.Resource("file"))),
  1266  			Binding: (2 << 32) | 1,
  1267  		}, res.CodeV2.Blocks[1].Chunks[3])
  1268  		assertFunction(t, "services", &llx.Function{
  1269  			Type:    string(types.Map(types.String, types.Array(types.String))),
  1270  			Binding: (2 << 32) | 1,
  1271  		}, res.CodeV2.Blocks[1].Chunks[4])
  1272  		assertFunction(t, "{}", &llx.Function{
  1273  			Type:    string(types.Array(types.Block)),
  1274  			Binding: (2 << 32) | 4,
  1275  			Args:    []*llx.Primitive{llx.FunctionPrimitive(3 << 32)},
  1276  		}, res.CodeV2.Blocks[1].Chunks[5])
  1277  		assert.Equal(t, []uint64{(2 << 32) | 2, (2 << 32) | 3, (2 << 32) | 6, (2 << 32) | 5},
  1278  			res.CodeV2.Blocks[1].Entrypoints)
  1279  	})
  1280  }
  1281  
  1282  func TestCompiler_ArrayResourceFieldGlob(t *testing.T) {
  1283  	compileT(t, "groups { * }", func(res *llx.CodeBundle) {
  1284  		assertFunction(t, "groups", nil, res.CodeV2.Blocks[0].Chunks[0])
  1285  		assertFunction(t, "list", &llx.Function{
  1286  			Binding: (1 << 32) | 1,
  1287  			Type:    string(types.Array(types.Resource("group"))),
  1288  		}, res.CodeV2.Blocks[0].Chunks[1])
  1289  		assertFunction(t, "{}", &llx.Function{
  1290  			Type:    string(types.Array(types.Block)),
  1291  			Binding: (1 << 32) | 2,
  1292  			Args:    []*llx.Primitive{llx.FunctionPrimitive(2 << 32)},
  1293  		}, res.CodeV2.Blocks[0].Chunks[2])
  1294  		assert.Equal(t, []uint64{(1 << 32) | 3}, res.CodeV2.Entrypoints())
  1295  
  1296  		assertPrimitive(t, &llx.Primitive{
  1297  			Type: string(types.Resource("group")),
  1298  		}, res.CodeV2.Blocks[1].Chunks[0])
  1299  		assertFunction(t, "gid", &llx.Function{
  1300  			Type:    string(types.Int),
  1301  			Binding: (2 << 32) | 1,
  1302  		}, res.CodeV2.Blocks[1].Chunks[1])
  1303  		assertFunction(t, "members", &llx.Function{
  1304  			Type:    string(types.Array(types.Resource("user"))),
  1305  			Binding: (2 << 32) | 1,
  1306  		}, res.CodeV2.Blocks[1].Chunks[2])
  1307  		assertFunction(t, "name", &llx.Function{
  1308  			Type:    string(types.String),
  1309  			Binding: (2 << 32) | 1,
  1310  		}, res.CodeV2.Blocks[1].Chunks[3])
  1311  		assertFunction(t, "sid", &llx.Function{
  1312  			Type:    string(types.String),
  1313  			Binding: (2 << 32) | 1,
  1314  		}, res.CodeV2.Blocks[1].Chunks[4])
  1315  		assertFunction(t, "{}", &llx.Function{
  1316  			Type:    string(types.Array(types.Block)),
  1317  			Binding: (2 << 32) | 3,
  1318  			Args:    []*llx.Primitive{llx.FunctionPrimitive(3 << 32)},
  1319  		}, res.CodeV2.Blocks[1].Chunks[5])
  1320  		assert.Equal(t, []uint64{(2 << 32) | 2, (2 << 32) | 6, (2 << 32) | 4, (2 << 32) | 5},
  1321  			res.CodeV2.Blocks[1].Entrypoints)
  1322  	})
  1323  }
  1324  
  1325  func TestCompiler_ResourceFieldArrayAccessor(t *testing.T) {
  1326  	compileT(t, "sshd.config.params[\"Protocol\"]", func(res *llx.CodeBundle) {
  1327  		assertFunction(t, "[]", &llx.Function{
  1328  			Type:    string(types.String),
  1329  			Binding: (1 << 32) | 2,
  1330  			Args: []*llx.Primitive{
  1331  				llx.StringPrimitive("Protocol"),
  1332  			},
  1333  		}, res.CodeV2.Blocks[0].Chunks[2])
  1334  	})
  1335  }
  1336  
  1337  func TestCompiler_ResourceWithUnnamedArgs(t *testing.T) {
  1338  	compileT(t, "file(\"/path\")", func(res *llx.CodeBundle) {
  1339  		assertFunction(t, "file", &llx.Function{
  1340  			Type:    string(types.Resource("file")),
  1341  			Binding: 0,
  1342  			Args: []*llx.Primitive{
  1343  				llx.StringPrimitive("path"),
  1344  				llx.StringPrimitive("/path"),
  1345  			},
  1346  		}, res.CodeV2.Blocks[0].Chunks[0])
  1347  	})
  1348  }
  1349  
  1350  func TestCompiler_ResourceWithNamedArgs(t *testing.T) {
  1351  	compileT(t, "file(path: \"/path\")", func(res *llx.CodeBundle) {
  1352  		assertFunction(t, "file", &llx.Function{
  1353  			Type:    string(types.Resource("file")),
  1354  			Binding: 0,
  1355  			Args: []*llx.Primitive{
  1356  				llx.StringPrimitive("path"),
  1357  				llx.StringPrimitive("/path"),
  1358  			},
  1359  		}, res.CodeV2.Blocks[0].Chunks[0])
  1360  	})
  1361  }
  1362  
  1363  func TestCompiler_LongResourceWithUnnamedArgs(t *testing.T) {
  1364  	compileT(t, "sshd.config(\"/path\")", func(res *llx.CodeBundle) {
  1365  		assertFunction(t, "sshd.config", &llx.Function{
  1366  			Type:    string(types.Resource("sshd.config")),
  1367  			Binding: 0,
  1368  			Args: []*llx.Primitive{
  1369  				llx.StringPrimitive("path"),
  1370  				llx.StringPrimitive("/path"),
  1371  			},
  1372  		}, res.CodeV2.Blocks[0].Chunks[0])
  1373  	})
  1374  }
  1375  
  1376  // FIXME: reactivate
  1377  func testCompiler_EmbeddedResource(t *testing.T) {
  1378  	compileCtx(t, "docker.containers[0].os", func(res *llx.CodeBundle) {
  1379  		assertFunction(t, "os", &llx.Function{
  1380  			Type:    string(types.Resource("os.linux")),
  1381  			Binding: 1<<32 | 3,
  1382  		}, res.CodeV2.Blocks[0].Chunks[3])
  1383  	})
  1384  }
  1385  
  1386  func testCompiler_EmbeddedResource_Lookup(t *testing.T) {
  1387  	compileCtx(t, "docker.containers[0].hostname", func(res *llx.CodeBundle) {
  1388  		assertFunction(t, "os", &llx.Function{
  1389  			Type:    string(types.Resource("os.linux")),
  1390  			Binding: 1<<32 | 3,
  1391  		}, res.CodeV2.Blocks[0].Chunks[3])
  1392  
  1393  		assertFunction(t, "unix", &llx.Function{
  1394  			Type:    string(types.Resource("os.unix")),
  1395  			Binding: 1<<32 | 4,
  1396  		}, res.CodeV2.Blocks[0].Chunks[4])
  1397  
  1398  		assertFunction(t, "base", &llx.Function{
  1399  			Type:    string(types.Resource("os.base")),
  1400  			Binding: 1<<32 | 5,
  1401  		}, res.CodeV2.Blocks[0].Chunks[5])
  1402  
  1403  		assertFunction(t, "hostname", &llx.Function{
  1404  			Type:    string(types.String),
  1405  			Binding: 1<<32 | 6,
  1406  		}, res.CodeV2.Blocks[0].Chunks[6])
  1407  	})
  1408  }
  1409  
  1410  func testCompiler_EmbeddedResource_ImplicitResource(t *testing.T) {
  1411  	compileCtx(t, "docker.containers[0].user(uid: 999).name", func(res *llx.CodeBundle) {
  1412  		assertFunction(t, "createResource", &llx.Function{
  1413  			Type: string(types.Resource("os.base.user")),
  1414  			Args: []*llx.Primitive{
  1415  				llx.RefPrimitiveV2(1<<32 | 3),
  1416  				llx.StringPrimitive("uid"),
  1417  				llx.IntPrimitive(999),
  1418  			},
  1419  			Binding: 0,
  1420  		}, res.CodeV2.Blocks[0].Chunks[3])
  1421  
  1422  		assert.Equal(t, "user", res.Labels.Labels[res.CodeV2.Checksums[1<<32|4]])
  1423  
  1424  		assertFunction(t, "name", &llx.Function{
  1425  			Type:    string(types.String),
  1426  			Binding: 1<<32 | 4,
  1427  		}, res.CodeV2.Blocks[0].Chunks[4])
  1428  	})
  1429  }
  1430  
  1431  func testCompiler_EmbeddedResource_ImplicitResource_Block(t *testing.T) {
  1432  	compileCtx(t, "docker.containers[0].user(uid: 999) { name }", func(res *llx.CodeBundle) {
  1433  		assertFunction(t, "createResource", &llx.Function{
  1434  			Type:    string(types.Resource("os.base.user")),
  1435  			Binding: 0,
  1436  			Args: []*llx.Primitive{
  1437  				llx.RefPrimitiveV2(1<<32 | 3),
  1438  				llx.StringPrimitive("uid"),
  1439  				llx.IntPrimitive(999),
  1440  			},
  1441  		}, res.CodeV2.Blocks[0].Chunks[3])
  1442  
  1443  		assertFunction(t, "{}", &llx.Function{
  1444  			Type:    string(types.Block),
  1445  			Binding: 1<<32 | 4,
  1446  			Args: []*llx.Primitive{
  1447  				llx.FunctionPrimitive(2 << 32),
  1448  			},
  1449  		}, res.CodeV2.Blocks[0].Chunks[4])
  1450  	})
  1451  }
  1452  
  1453  func testCompiler_EmbeddedResource_ImplicitResource_List(t *testing.T) {
  1454  	compileCtx(t, "docker.containers[0].packages", func(res *llx.CodeBundle) {
  1455  		assertFunction(t, "createResource", &llx.Function{
  1456  			Type:    string(types.Resource("os.base.packages")),
  1457  			Binding: 0,
  1458  			Args: []*llx.Primitive{
  1459  				llx.RefPrimitiveV2(1<<32 | 3),
  1460  			},
  1461  		}, res.CodeV2.Blocks[0].Chunks[3])
  1462  	})
  1463  }
  1464  
  1465  func TestCompiler_ExpectSimplest(t *testing.T) {
  1466  	compileT(t, "expect(true)", func(res *llx.CodeBundle) {
  1467  		f := res.CodeV2.Blocks[0].Chunks[0]
  1468  		assert.Equal(t, llx.Chunk_FUNCTION, f.Call)
  1469  		assert.Equal(t, "expect", f.Id)
  1470  		assert.Equal(t, []uint64{(1 << 32) | 1}, res.CodeV2.Entrypoints())
  1471  		assert.Equal(t, &llx.Function{
  1472  			Type:    string(types.Bool),
  1473  			Binding: 0,
  1474  			Args:    []*llx.Primitive{llx.BoolPrimitive(true)},
  1475  		}, f.Function)
  1476  	})
  1477  }
  1478  
  1479  func TestCompiler_ExpectEq(t *testing.T) {
  1480  	compileT(t, "expect(1 == \"1\")", func(res *llx.CodeBundle) {
  1481  		cmp := res.CodeV2.Blocks[0].Chunks[1]
  1482  		assert.Equal(t, llx.Chunk_FUNCTION, cmp.Call)
  1483  		assert.Equal(t, []uint64{(1 << 32) | 3}, res.CodeV2.Entrypoints())
  1484  		assert.Equal(t, string("=="+types.String), cmp.Id)
  1485  		assert.Equal(t, &llx.Function{
  1486  			Type:    string(types.Bool),
  1487  			Binding: (1 << 32) | 1,
  1488  			Args: []*llx.Primitive{
  1489  				llx.StringPrimitive("1"),
  1490  			},
  1491  		}, cmp.Function)
  1492  
  1493  		f := res.CodeV2.Blocks[0].Chunks[2]
  1494  		assert.Equal(t, llx.Chunk_FUNCTION, f.Call)
  1495  		assert.Equal(t, "expect", f.Id)
  1496  		assert.Equal(t, &llx.Function{
  1497  			Type:    string(types.Bool),
  1498  			Binding: 0,
  1499  			Args:    []*llx.Primitive{llx.RefPrimitiveV2((1 << 32) | 2)},
  1500  		}, f.Function)
  1501  	})
  1502  }
  1503  
  1504  func TestCompiler_EmptyBlock(t *testing.T) {
  1505  	compileT(t, "parse { }", func(res *llx.CodeBundle) {
  1506  		assertFunction(t, "parse", nil, res.CodeV2.Blocks[0].Chunks[0])
  1507  		assert.Equal(t, 1, len(res.CodeV2.Blocks[0].Chunks))
  1508  		assert.Len(t, res.CodeV2.Blocks, 1)
  1509  	})
  1510  }
  1511  
  1512  func TestCompiler_Block(t *testing.T) {
  1513  	compileT(t, "mondoo { version build }", func(res *llx.CodeBundle) {
  1514  		assertFunction(t, "mondoo", nil, res.CodeV2.Blocks[0].Chunks[0])
  1515  		assertFunction(t, "{}", &llx.Function{
  1516  			Type:    string(types.Block),
  1517  			Binding: (1 << 32) | 1,
  1518  			Args:    []*llx.Primitive{llx.FunctionPrimitive(2 << 32)},
  1519  		}, res.CodeV2.Blocks[0].Chunks[1])
  1520  		assert.Equal(t, []uint64{(1 << 32) | 2}, res.CodeV2.Entrypoints())
  1521  
  1522  		assertPrimitive(t, &llx.Primitive{
  1523  			Type: string(types.Resource("mondoo")),
  1524  		}, res.CodeV2.Blocks[1].Chunks[0])
  1525  		assertFunction(t, "version", &llx.Function{
  1526  			Type:    string(types.String),
  1527  			Binding: (2 << 32) | 1,
  1528  		}, res.CodeV2.Blocks[1].Chunks[1])
  1529  		assertFunction(t, "build", &llx.Function{
  1530  			Type:    string(types.String),
  1531  			Binding: (2 << 32) | 1,
  1532  		}, res.CodeV2.Blocks[1].Chunks[2])
  1533  		assert.Equal(t, []uint64{(2 << 32) | 2, (2 << 32) | 3}, res.CodeV2.Blocks[1].Entrypoints)
  1534  	})
  1535  }
  1536  
  1537  func TestCompiler_BlockWithSelf(t *testing.T) {
  1538  	compileT(t, "mondoo { _.version }", func(res *llx.CodeBundle) {
  1539  		assertFunction(t, "mondoo", nil, res.CodeV2.Blocks[0].Chunks[0])
  1540  		assertFunction(t, "{}", &llx.Function{
  1541  			Type:    string(types.Block),
  1542  			Binding: (1 << 32) | 1,
  1543  			Args:    []*llx.Primitive{llx.FunctionPrimitive(2 << 32)},
  1544  		}, res.CodeV2.Blocks[0].Chunks[1])
  1545  		assert.Equal(t, []uint64{(1 << 32) | 2}, res.CodeV2.Entrypoints())
  1546  
  1547  		assertPrimitive(t, &llx.Primitive{
  1548  			Type: string(types.Resource("mondoo")),
  1549  		}, res.CodeV2.Blocks[1].Chunks[0])
  1550  		assertFunction(t, "version", &llx.Function{
  1551  			Type:    string(types.String),
  1552  			Binding: (2 << 32) | 1,
  1553  		}, res.CodeV2.Blocks[1].Chunks[1])
  1554  		assert.Equal(t, []uint64{(2 << 32) | 2}, res.CodeV2.Blocks[1].Entrypoints)
  1555  	})
  1556  
  1557  	compileT(t, "sshd.config.params { _['A'] != _['B'] }", func(res *llx.CodeBundle) {
  1558  		assertFunction(t, "sshd.config", nil, res.CodeV2.Blocks[0].Chunks[0])
  1559  		assertFunction(t, "params", &llx.Function{
  1560  			Type:    string(types.Map(types.String, types.String)),
  1561  			Binding: (1 << 32) | 1,
  1562  		}, res.CodeV2.Blocks[0].Chunks[1])
  1563  		assertFunction(t, "{}", &llx.Function{
  1564  			Type:    string(types.Block),
  1565  			Binding: (1 << 32) | 2,
  1566  			Args:    []*llx.Primitive{llx.FunctionPrimitive(2 << 32)},
  1567  		}, res.CodeV2.Blocks[0].Chunks[2])
  1568  		assert.Equal(t, []uint64{(1 << 32) | 3}, res.CodeV2.Entrypoints())
  1569  
  1570  		assertPrimitive(t, &llx.Primitive{
  1571  			Type: string(types.Map(types.String, types.String)),
  1572  		}, res.CodeV2.Blocks[1].Chunks[0])
  1573  		assertFunction(t, "[]", &llx.Function{
  1574  			Type:    string(types.String),
  1575  			Binding: (2 << 32) | 1,
  1576  			Args:    []*llx.Primitive{llx.StringPrimitive("A")},
  1577  		}, res.CodeV2.Blocks[1].Chunks[1])
  1578  		assertFunction(t, "[]", &llx.Function{
  1579  			Type:    string(types.String),
  1580  			Binding: (2 << 32) | 1,
  1581  			Args:    []*llx.Primitive{llx.StringPrimitive("B")},
  1582  		}, res.CodeV2.Blocks[1].Chunks[2])
  1583  		assertFunction(t, string("!="+types.String), &llx.Function{
  1584  			Type:    string(types.Bool),
  1585  			Binding: (2 << 32) | 2,
  1586  			Args:    []*llx.Primitive{llx.RefPrimitiveV2((2 << 32) | 3)},
  1587  		}, res.CodeV2.Blocks[1].Chunks[3])
  1588  		assert.Equal(t, []uint64{(2 << 32) | 4}, res.CodeV2.Blocks[1].Entrypoints)
  1589  	})
  1590  
  1591  	compileT(t, "\"alice\\nbob\".lines { _ != \"alice\" && _ != \"bob\" }", func(res *llx.CodeBundle) {
  1592  		assertPrimitive(t, llx.StringPrimitive("alice\nbob"), res.CodeV2.Blocks[0].Chunks[0])
  1593  		assertFunction(t, "lines", &llx.Function{
  1594  			Type:    string(types.Array(types.String)),
  1595  			Binding: (1 << 32) | 1,
  1596  		}, res.CodeV2.Blocks[0].Chunks[1])
  1597  		assertFunction(t, "{}", &llx.Function{
  1598  			Type:    string(types.Array(types.Block)),
  1599  			Binding: (1 << 32) | 2,
  1600  			Args:    []*llx.Primitive{llx.FunctionPrimitive(2 << 32)},
  1601  		}, res.CodeV2.Blocks[0].Chunks[2])
  1602  		assert.Equal(t, []uint64{(1 << 32) | 3}, res.CodeV2.Entrypoints())
  1603  
  1604  		assertPrimitive(t, &llx.Primitive{
  1605  			Type: string(types.String),
  1606  		}, res.CodeV2.Blocks[1].Chunks[0])
  1607  		assertFunction(t, string("!="+types.String), &llx.Function{
  1608  			Type:    string(types.Bool),
  1609  			Binding: (2 << 32) | 1,
  1610  			Args:    []*llx.Primitive{llx.StringPrimitive("alice")},
  1611  		}, res.CodeV2.Blocks[1].Chunks[1])
  1612  		assertFunction(t, string("!="+types.String), &llx.Function{
  1613  			Type:    string(types.Bool),
  1614  			Binding: (2 << 32) | 1,
  1615  			Args:    []*llx.Primitive{llx.StringPrimitive("bob")},
  1616  		}, res.CodeV2.Blocks[1].Chunks[2])
  1617  		assertFunction(t, string("&&"+types.Bool), &llx.Function{
  1618  			Type:    string(types.Bool),
  1619  			Binding: (2 << 32) | 2,
  1620  			Args:    []*llx.Primitive{llx.RefPrimitiveV2((2 << 32) | 3)},
  1621  		}, res.CodeV2.Blocks[1].Chunks[3])
  1622  		assert.Equal(t, []uint64{(2 << 32) | 4}, res.CodeV2.Blocks[1].Entrypoints)
  1623  	})
  1624  }
  1625  
  1626  func TestCompiler_ContainsWithResource(t *testing.T) {
  1627  	compileT(t, "'hello'.contains(asset.family)", func(res *llx.CodeBundle) {
  1628  		assertPrimitive(t, llx.StringPrimitive("hello"), res.CodeV2.Blocks[0].Chunks[0])
  1629  		assertFunction(t, "asset", nil, res.CodeV2.Blocks[0].Chunks[1])
  1630  		assertFunction(t, "family", &llx.Function{
  1631  			Type:    string(types.Array(types.String)),
  1632  			Binding: (1 << 32) | 2,
  1633  		}, res.CodeV2.Blocks[0].Chunks[2])
  1634  		assertFunction(t, "contains"+string(types.Array(types.String)), &llx.Function{
  1635  			Type:    string(types.Bool),
  1636  			Binding: (1 << 32) | 1,
  1637  			Args:    []*llx.Primitive{llx.RefPrimitiveV2((1 << 32) | 3)},
  1638  		}, res.CodeV2.Blocks[0].Chunks[3])
  1639  
  1640  		assert.Equal(t, []uint64{(1 << 32) | 4}, res.CodeV2.Entrypoints())
  1641  	})
  1642  }
  1643  
  1644  func TestCompiler_StringContainsWithInt(t *testing.T) {
  1645  	compileT(t, "'hello123'.contains(23)", func(res *llx.CodeBundle) {
  1646  		assertPrimitive(t, llx.StringPrimitive("hello123"), res.CodeV2.Blocks[0].Chunks[0])
  1647  		assertFunction(t, "contains"+string(types.Int), &llx.Function{
  1648  			Type:    string(types.Bool),
  1649  			Binding: (1 << 32) | 1,
  1650  			Args:    []*llx.Primitive{llx.IntPrimitive(23)},
  1651  		}, res.CodeV2.Blocks[0].Chunks[1])
  1652  
  1653  		assert.Equal(t, []uint64{(1 << 32) | 2}, res.CodeV2.Entrypoints())
  1654  	})
  1655  }
  1656  
  1657  func TestCompiler_CallWithResource(t *testing.T) {
  1658  	compileT(t, "users { file(home) }", func(res *llx.CodeBundle) {
  1659  		assertFunction(t, "users", nil, res.CodeV2.Blocks[0].Chunks[0])
  1660  		assertFunction(t, "list", &llx.Function{
  1661  			Binding: (1 << 32) | 1,
  1662  			Type:    string(types.Array(types.Resource("user"))),
  1663  		}, res.CodeV2.Blocks[0].Chunks[1])
  1664  		assertFunction(t, "{}", &llx.Function{
  1665  			Type:    string(types.Array(types.Block)),
  1666  			Binding: (1 << 32) | 2,
  1667  			Args:    []*llx.Primitive{llx.FunctionPrimitive(2 << 32)},
  1668  		}, res.CodeV2.Blocks[0].Chunks[2])
  1669  		assert.Equal(t, 3, len(res.CodeV2.Blocks[0].Chunks))
  1670  
  1671  		assertPrimitive(t, &llx.Primitive{
  1672  			Type: string(types.Resource("user")),
  1673  		}, res.CodeV2.Blocks[1].Chunks[0])
  1674  		assertFunction(t, "home", &llx.Function{
  1675  			Type:    string(types.String),
  1676  			Binding: (2 << 32) | 1,
  1677  		}, res.CodeV2.Blocks[1].Chunks[1])
  1678  		assertFunction(t, "file", &llx.Function{
  1679  			Type:    string(types.Resource("file")),
  1680  			Binding: 0,
  1681  			Args: []*llx.Primitive{
  1682  				llx.StringPrimitive("path"),
  1683  				llx.RefPrimitiveV2((2 << 32) | 2),
  1684  			},
  1685  		}, res.CodeV2.Blocks[1].Chunks[2])
  1686  		assert.EqualValues(t, 1, res.CodeV2.Blocks[1].Parameters)
  1687  	})
  1688  }
  1689  
  1690  func TestCompiler_List(t *testing.T) {
  1691  	compileT(t, "packages { name }", func(res *llx.CodeBundle) {
  1692  		assertFunction(t, "packages", nil, res.CodeV2.Blocks[0].Chunks[0])
  1693  		assertFunction(t, "list", &llx.Function{
  1694  			Binding: (1 << 32) | 1,
  1695  			Type:    string(types.Array(types.Resource("package"))),
  1696  		}, res.CodeV2.Blocks[0].Chunks[1])
  1697  		assertFunction(t, "{}", &llx.Function{
  1698  			Type:    string(types.Array(types.Block)),
  1699  			Binding: (1 << 32) | 2,
  1700  			Args:    []*llx.Primitive{llx.FunctionPrimitive(2 << 32)},
  1701  		}, res.CodeV2.Blocks[0].Chunks[2])
  1702  		assert.Equal(t, 3, len(res.CodeV2.Blocks[0].Chunks))
  1703  
  1704  		assertPrimitive(t, &llx.Primitive{
  1705  			Type: string(types.Resource("package")),
  1706  		}, res.CodeV2.Blocks[1].Chunks[0])
  1707  		assertFunction(t, "name", &llx.Function{
  1708  			Type:    string(types.String),
  1709  			Binding: (2 << 32) | 1,
  1710  		}, res.CodeV2.Blocks[1].Chunks[1])
  1711  		assert.Equal(t, []uint64{(2 << 32) | 2}, res.CodeV2.Blocks[1].Entrypoints)
  1712  	})
  1713  }
  1714  
  1715  func TestCompiler_ResourceEmptyWhere(t *testing.T) {
  1716  	compileT(t, "packages.where()", func(res *llx.CodeBundle) {
  1717  		assertFunction(t, "packages", nil, res.CodeV2.Blocks[0].Chunks[0])
  1718  		assert.Len(t, res.CodeV2.Blocks[0].Chunks, 3)
  1719  		assertFunction(t, "packages", nil, res.CodeV2.Blocks[0].Chunks[0])
  1720  		assertFunction(t, "list", &llx.Function{
  1721  			Binding: (1 << 32) | 1,
  1722  			Type:    string(types.Array(types.Resource("package"))),
  1723  		}, res.CodeV2.Blocks[0].Chunks[1])
  1724  	})
  1725  }
  1726  
  1727  func TestCompiler_ResourceWhere(t *testing.T) {
  1728  	compileT(t, "packages.where(outdated)", func(res *llx.CodeBundle) {
  1729  		assertFunction(t, "packages", nil, res.CodeV2.Blocks[0].Chunks[0])
  1730  		assertFunction(t, "list", &llx.Function{
  1731  			Type:    string(types.Array(types.Resource("package"))),
  1732  			Binding: (1 << 32) | 1,
  1733  		}, res.CodeV2.Blocks[0].Chunks[1])
  1734  		assertFunction(t, "where", &llx.Function{
  1735  			Type:    string(types.Resource("packages")),
  1736  			Binding: (1 << 32) | 1,
  1737  			Args: []*llx.Primitive{
  1738  				llx.RefPrimitiveV2((1 << 32) | 2),
  1739  				llx.FunctionPrimitive(2 << 32),
  1740  			},
  1741  		}, res.CodeV2.Blocks[0].Chunks[2])
  1742  
  1743  		assertPrimitive(t, &llx.Primitive{
  1744  			Type: string(types.Resource("package")),
  1745  		}, res.CodeV2.Blocks[1].Chunks[0])
  1746  		assertFunction(t, "outdated", &llx.Function{
  1747  			Type:    string(types.Bool),
  1748  			Binding: (2 << 32) | 1,
  1749  		}, res.CodeV2.Blocks[1].Chunks[1])
  1750  		assert.Equal(t, []uint64{(2 << 32) | 2}, res.CodeV2.Blocks[1].Entrypoints)
  1751  	})
  1752  }
  1753  
  1754  func TestCompiler_ResourceContains(t *testing.T) {
  1755  	compileT(t, "packages.contains(outdated)", func(res *llx.CodeBundle) {
  1756  		assertFunction(t, "packages", nil, res.CodeV2.Blocks[0].Chunks[0])
  1757  		assertFunction(t, "list", &llx.Function{
  1758  			Type:    string(types.Array(types.Resource("package"))),
  1759  			Binding: (1 << 32) | 1,
  1760  		}, res.CodeV2.Blocks[0].Chunks[1])
  1761  		assertFunction(t, "where", &llx.Function{
  1762  			Type:    string(types.Resource("packages")),
  1763  			Binding: (1 << 32) | 1,
  1764  			Args: []*llx.Primitive{
  1765  				llx.RefPrimitiveV2((1 << 32) | 2),
  1766  				llx.FunctionPrimitive(2 << 32),
  1767  			},
  1768  		}, res.CodeV2.Blocks[0].Chunks[2])
  1769  		assertFunction(t, "list", &llx.Function{
  1770  			Type:    string(types.Array(types.Resource("package"))),
  1771  			Binding: (1 << 32) | 3,
  1772  		}, res.CodeV2.Blocks[0].Chunks[3])
  1773  		assertFunction(t, "length", &llx.Function{
  1774  			Type:    string(types.Int),
  1775  			Binding: (1 << 32) | 4,
  1776  		}, res.CodeV2.Blocks[0].Chunks[4])
  1777  		assertFunction(t, string(">"+types.Int), &llx.Function{
  1778  			Type:    string(types.Bool),
  1779  			Binding: (1 << 32) | 5,
  1780  			Args:    []*llx.Primitive{llx.IntPrimitive(0)},
  1781  		}, res.CodeV2.Blocks[0].Chunks[5])
  1782  
  1783  		assertPrimitive(t, &llx.Primitive{
  1784  			Type: string(types.Resource("package")),
  1785  		}, res.CodeV2.Blocks[1].Chunks[0])
  1786  		assertFunction(t, "outdated", &llx.Function{
  1787  			Type:    string(types.Bool),
  1788  			Binding: (2 << 32) | 1,
  1789  		}, res.CodeV2.Blocks[1].Chunks[1])
  1790  		assert.Equal(t, []uint64{(2 << 32) | 2}, res.CodeV2.Blocks[1].Entrypoints)
  1791  	})
  1792  }
  1793  
  1794  //    ================
  1795  //   👋   INTERNAL   🍹
  1796  //    ================
  1797  
  1798  func TestChecksums(t *testing.T) {
  1799  	t.Run("no duplicate code IDs", func(t *testing.T) {
  1800  		dupes := []struct {
  1801  			qa string
  1802  			qb string
  1803  		}{
  1804  			{
  1805  				"users.list { uid == 1 }",
  1806  				"users.list { uid == 2 }",
  1807  			},
  1808  			{
  1809  				"asset.platform\nasset.version",
  1810  				"asset.platform",
  1811  			},
  1812  			{
  1813  				"asset.platform\nasset.version",
  1814  				"asset.version",
  1815  			},
  1816  			{
  1817  				"if (true) { 2 }",
  1818  				"if (true) { 3 }",
  1819  			},
  1820  			{
  1821  				"mondoo { version == 'a'}",
  1822  				"mondoo { version == 'b' version == 'a'}",
  1823  			},
  1824  		}
  1825  
  1826  		for i := range dupes {
  1827  			t.Run(dupes[i].qa+" != "+dupes[i].qb, func(t *testing.T) {
  1828  				a, err := mqlc.Compile(dupes[i].qa, nil, conf)
  1829  				assert.NoError(t, err)
  1830  				b, err := mqlc.Compile(dupes[i].qb, nil, conf)
  1831  				assert.NoError(t, err)
  1832  				assert.NotEqual(t, a.CodeV2.Id, b.CodeV2.Id)
  1833  			})
  1834  		}
  1835  	})
  1836  }
  1837  
  1838  func TestChecksums_block(t *testing.T) {
  1839  	a, err := mqlc.Compile("mondoo { version == 'a'}", nil, conf)
  1840  	assert.NoError(t, err)
  1841  	b, err := mqlc.Compile("mondoo { version == 'b' version == 'a'}", nil, conf)
  1842  	assert.NoError(t, err)
  1843  	// make sure the checksum for the block calls are different
  1844  	assert.NotEqual(t, a.CodeV2.Checksums[4294967298], b.CodeV2.Checksums[4294967298])
  1845  }
  1846  
  1847  func TestSuggestions(t *testing.T) {
  1848  	tests := []struct {
  1849  		code             string
  1850  		suggestions      []string
  1851  		err              error
  1852  		requiredFeatures cnquery.Features
  1853  	}{
  1854  		{
  1855  			"does_not_get_suggestions",
  1856  			[]string{},
  1857  			errors.New("cannot find resource for identifier 'does_not_get_suggestions'"),
  1858  			nil,
  1859  		},
  1860  		{
  1861  			// resource suggestions
  1862  			"ssh",
  1863  			[]string{"os.unix.sshd", "sshd", "sshd.config", "windows.security.health"},
  1864  			errors.New("cannot find resource for identifier 'ssh'"),
  1865  			nil,
  1866  		},
  1867  		{
  1868  			// resource with empty field call
  1869  			"sshd.",
  1870  			[]string{"config"},
  1871  			errors.New("incomplete query, missing identifier after '.' at <source>:1:6"),
  1872  			nil,
  1873  		},
  1874  		{
  1875  			// list resource with empty field call
  1876  			"users.",
  1877  			[]string{"all", "any", "contains", "length", "list", "map", "none", "one", "where"},
  1878  			errors.New("incomplete query, missing identifier after '.' at <source>:1:7"),
  1879  			nil,
  1880  		},
  1881  		{
  1882  			// resource with partial field call
  1883  			"sshd.config.para",
  1884  			[]string{"params"},
  1885  			errors.New("cannot find field 'para' in sshd.config"),
  1886  			nil,
  1887  		},
  1888  		{
  1889  			// resource with partial field call in block
  1890  			"sshd.config { para }",
  1891  			[]string{"params"},
  1892  			errors.New("cannot find field or resource 'para' in block for type 'sshd.config'"),
  1893  			nil,
  1894  		},
  1895  		{
  1896  			// native type function call
  1897  			"sshd.config.params.leng",
  1898  			[]string{"length"},
  1899  			errors.New("cannot find field 'leng' in map[string]string"),
  1900  			nil,
  1901  		},
  1902  		{
  1903  			// builtin calls
  1904  			"parse.d",
  1905  			[]string{"date"},
  1906  			errors.New("cannot find field 'd' in parse"),
  1907  			nil,
  1908  		},
  1909  		{
  1910  			// embedded with asset context on
  1911  			"docker.containers[0].hostnam",
  1912  			[]string{"hostname"},
  1913  			errors.New("cannot find field 'hostnam' in docker.container"),
  1914  			cnquery.Features{byte(cnquery.MQLAssetContext)},
  1915  		},
  1916  		{
  1917  			// embedded with asset context off
  1918  			"docker.containers[0].hostnam",
  1919  			[]string{},
  1920  			errors.New("cannot find field 'hostnam' in docker.container"),
  1921  			nil,
  1922  		},
  1923  	}
  1924  
  1925  	for i := range tests {
  1926  		cur := tests[i]
  1927  		t.Run(cur.code, func(t *testing.T) {
  1928  			nuConf := mqlc.NewConfig(conf.Schema,
  1929  				append(features, cur.requiredFeatures...))
  1930  			res, err := mqlc.Compile(cur.code, nil, nuConf)
  1931  			assert.Empty(t, res.CodeV2.Entrypoints())
  1932  			assert.Equal(t, cur.err.Error(), err.Error())
  1933  
  1934  			suggestions := make([]string, len(res.Suggestions))
  1935  			for i := range res.Suggestions {
  1936  				suggestions[i] = res.Suggestions[i].Field
  1937  			}
  1938  			sort.Strings(suggestions)
  1939  			assert.Equal(t, cur.suggestions, suggestions)
  1940  		})
  1941  	}
  1942  }
  1943  
  1944  func TestImplicitSuggestion(t *testing.T) {
  1945  	res, _ := mqlc.Compile("sshd.", nil, conf)
  1946  	require.NotEmpty(t, res.Suggestions)
  1947  
  1948  	assert.Equal(t, "SSH server configuration", res.Suggestions[0].Title)
  1949  }
  1950  
  1951  func TestCompiler_Error(t *testing.T) {
  1952  	t.Run("unknown term", func(t *testing.T) {
  1953  		_, err := mqlc.Compile("sshd.config.params == enabled", nil, conf)
  1954  		// assert.Nil(t, res)
  1955  		assert.EqualError(t, err, "failed to compile: cannot find resource for identifier 'enabled'")
  1956  	})
  1957  }
  1958  
  1959  func TestCompiler_Multiline(t *testing.T) {
  1960  	compileT(t, "1 < 2\n2 != 3", func(res *llx.CodeBundle) {
  1961  		assert.Equal(t, 4, len(res.CodeV2.Blocks[0].Chunks))
  1962  	})
  1963  }
  1964  
  1965  func TestCompiler_Entrypoints(t *testing.T) {
  1966  	tests := []struct {
  1967  		code        string
  1968  		datapoints  []uint64
  1969  		entrypoints []uint64
  1970  	}{
  1971  		{
  1972  			"1",
  1973  			[]uint64(nil),
  1974  			[]uint64{(1 << 32) | 1},
  1975  		},
  1976  		{
  1977  			"mondoo.version == 1",
  1978  			[]uint64{(1 << 32) | 2},
  1979  			[]uint64{(1 << 32) | 3},
  1980  		},
  1981  		{
  1982  			"mondoo.version == mondoo.build",
  1983  			[]uint64{(1 << 32) | 2, (1 << 32) | 4},
  1984  			[]uint64{(1 << 32) | 5},
  1985  		},
  1986  		{
  1987  			`
  1988  				a = "a"
  1989  				b = "b"
  1990  				a == "a"
  1991  				b == "b"
  1992  				c = "c"
  1993  				c == "c"
  1994  			`,
  1995  			[]uint64{(1 << 32) | 3, (1 << 32) | 5, (1 << 32) | 8},
  1996  			[]uint64{(1 << 32) | 4, (1 << 32) | 6, (1 << 32) | 9},
  1997  		},
  1998  		{
  1999  			`
  2000  				a = "a"
  2001  				b = "b"
  2002  				a == "a"
  2003  				b == "b"
  2004  				c = a == b
  2005  				c == false
  2006  			`,
  2007  			[]uint64{(1 << 32) | 3, (1 << 32) | 5, (1 << 32) | 10},
  2008  			[]uint64{(1 << 32) | 4, (1 << 32) | 6, (1 << 32) | 11},
  2009  		},
  2010  	}
  2011  
  2012  	for i := range tests {
  2013  		test := tests[i]
  2014  		t.Run(test.code, func(t *testing.T) {
  2015  			compileT(t, test.code, func(res *llx.CodeBundle) {
  2016  				assert.ElementsMatch(t, test.entrypoints, res.CodeV2.Entrypoints())
  2017  				assert.Equal(t, test.datapoints, res.CodeV2.Datapoints())
  2018  			})
  2019  		})
  2020  	}
  2021  }
  2022  
  2023  func TestCompiler_NestedEntrypoints(t *testing.T) {
  2024  	tests := []struct {
  2025  		code        string
  2026  		datapoints  []uint64
  2027  		entrypoints []uint64
  2028  	}{
  2029  		{
  2030  			`
  2031  				if(true) {
  2032  					a = "a"
  2033  					b = "b"
  2034  					a == b
  2035  				}
  2036  			`,
  2037  			[]uint64{},
  2038  			[]uint64{(1 << 32) | 1, (2 << 32) | 5},
  2039  		},
  2040  		{
  2041  			`
  2042  				if(true) {
  2043  					a = "a"
  2044  					b = "b"
  2045  					a == b
  2046  				} else {
  2047  					x = "x"
  2048  					y = "y"
  2049  					x == y
  2050  				}
  2051  			`,
  2052  			[]uint64{},
  2053  			[]uint64{(1 << 32) | 1, (2 << 32) | 5, (3 << 32) | 5},
  2054  		},
  2055  		{
  2056  			`
  2057  			  z = "z"
  2058  				if(z == "z") {
  2059  					a = "a"
  2060  					b = "b"
  2061  					a == b
  2062  				} else if (z == "a") {
  2063  					x = "x"
  2064  					y = "y"
  2065  					x == y
  2066  				} else {
  2067  					j = "j"
  2068  					k = "k"
  2069  					j == k
  2070  				}
  2071  			`,
  2072  			[]uint64{(1 << 32) | 2},
  2073  			[]uint64{(1 << 32) | 6, (2 << 32) | 5, (3 << 32) | 5, (4 << 32) | 5},
  2074  		},
  2075  		{
  2076  			`
  2077  				switch {
  2078  				case "a" == "a":
  2079  					a = "a"
  2080  					b = "b"
  2081  					a == b;
  2082  				case "b" == "b":
  2083  					x = "x"
  2084  					y = "y"
  2085  					x == y
  2086  				}
  2087  			`,
  2088  			[]uint64{},
  2089  			[]uint64{(1 << 32) | 5, (2 << 32) | 5, (3 << 32) | 5},
  2090  		},
  2091  		{
  2092  			`
  2093  				mondoo {
  2094  					a = "a"
  2095  					b = "b"
  2096  					a == b
  2097  				}
  2098  			`,
  2099  			[]uint64{},
  2100  			[]uint64{(1 << 32) | 2, (2 << 32) | 6},
  2101  		},
  2102  		{
  2103  			`
  2104  				{a: "a"} {
  2105  					x = "x"
  2106  					y = "y"
  2107  					x == y
  2108  				}
  2109  			`,
  2110  			[]uint64{},
  2111  			[]uint64{(1 << 32) | 2, (2 << 32) | 6},
  2112  		},
  2113  		{
  2114  			`
  2115  				[1,2,3] {
  2116  					x = "x"
  2117  					y = "y"
  2118  					x == y
  2119  				}
  2120  			`,
  2121  			[]uint64{},
  2122  			[]uint64{(1 << 32) | 2, (2 << 32) | 6},
  2123  		},
  2124  		{
  2125  			`
  2126  				mondoo {
  2127  					_
  2128  				}
  2129  			`,
  2130  			[]uint64{},
  2131  			[]uint64{(1 << 32) | 2, (2 << 32) | 1},
  2132  		},
  2133  		{
  2134  			`
  2135  				mondoo {
  2136  					a = true
  2137  					a
  2138  				}
  2139  			`,
  2140  			[]uint64{},
  2141  			[]uint64{(1 << 32) | 2, (2 << 32) | 3},
  2142  		},
  2143  		{
  2144  			`
  2145  				if(true) {
  2146  					a = true
  2147  					a
  2148  				}
  2149  			`,
  2150  			[]uint64{},
  2151  			[]uint64{(1 << 32) | 1, (2 << 32) | 2},
  2152  		},
  2153  	}
  2154  
  2155  	for i := range tests {
  2156  		test := tests[i]
  2157  		t.Run(test.code, func(t *testing.T) {
  2158  			compileT(t, test.code, func(res *llx.CodeBundle) {
  2159  				entrypoints, datapoints := allCodepoints(res.CodeV2)
  2160  				assert.ElementsMatch(t, test.entrypoints, entrypoints)
  2161  				assert.ElementsMatch(t, test.datapoints, datapoints)
  2162  			})
  2163  		})
  2164  	}
  2165  }
  2166  
  2167  func allCodepoints(code *llx.CodeV2) ([]uint64, []uint64) {
  2168  	entrypoints := []uint64{}
  2169  	datapoints := []uint64{}
  2170  
  2171  	for _, b := range code.Blocks {
  2172  		entrypoints = append(entrypoints, b.Entrypoints...)
  2173  		datapoints = append(datapoints, b.Datapoints...)
  2174  	}
  2175  	return entrypoints, datapoints
  2176  }