go.mondoo.com/cnquery@v0.0.0-20231005093811-59568235f6ea/mql/mql_test.go (about) 1 // Copyright (c) Mondoo, Inc. 2 // SPDX-License-Identifier: BUSL-1.1 3 4 package mql_test 5 6 import ( 7 "fmt" 8 "os" 9 "strings" 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/mql" 17 "go.mondoo.com/cnquery/providers-sdk/v1/testutils" 18 "go.mondoo.com/cnquery/types" 19 ) 20 21 var features cnquery.Features 22 23 func init() { 24 features = getEnvFeatures() 25 } 26 27 func runtime() llx.Runtime { 28 return testutils.LinuxMock() 29 } 30 31 func getEnvFeatures() cnquery.Features { 32 env := os.Getenv("FEATURES") 33 if env == "" { 34 return cnquery.Features{} 35 } 36 37 arr := strings.Split(env, ",") 38 var fts cnquery.Features 39 for i := range arr { 40 v, ok := cnquery.FeaturesValue[arr[i]] 41 if ok { 42 fmt.Println("--> activate feature: " + arr[i]) 43 fts = append(features, byte(v)) 44 } else { 45 panic("cannot find requested feature: " + arr[i]) 46 } 47 } 48 return fts 49 } 50 51 func TestMqlSimple(t *testing.T) { 52 tests := []struct { 53 query string 54 assertion interface{} 55 }{ 56 {"asset.platform", "arch"}, 57 {"asset { platform version }", map[string]interface{}{ 58 "platform": "arch", 59 "version": "rolling", 60 }}, 61 {"users { name uid }", []interface{}{ 62 map[string]interface{}{"name": "root", "uid": int64(0)}, 63 map[string]interface{}{"name": "bin", "uid": int64(1)}, 64 map[string]interface{}{"name": "chris", "uid": int64(1000)}, 65 map[string]interface{}{"name": "christopher", "uid": int64(1001)}, 66 }}, 67 } 68 69 for i := range tests { 70 one := tests[i] 71 t.Run(one.query, func(t *testing.T) { 72 res, err := mql.Exec(one.query, runtime(), features, nil) 73 assert.NoError(t, err) 74 assert.NoError(t, res.Error) 75 assert.Equal(t, one.assertion, res.Value) 76 }) 77 } 78 } 79 80 func TestCustomData(t *testing.T) { 81 query := "{ \"a\": \"valuea\", \"b\": \"valueb\"}" 82 83 value, err := mql.Exec(query, runtime(), features, nil) 84 require.NoError(t, err) 85 assert.Equal(t, map[string]interface{}{"a": "valuea", "b": "valueb"}, value.Value) 86 } 87 88 func TestMqlProps(t *testing.T) { 89 query := "props.a + props.b" 90 props := map[string]*llx.Primitive{ 91 "a": llx.IntPrimitive(2), 92 "b": llx.IntPrimitive(2), 93 } 94 95 value, err := mql.Exec(query, runtime(), features, props) 96 require.NoError(t, err) 97 assert.Equal(t, int64(4), value.Value) 98 } 99 100 func TestMqlIfElseProps(t *testing.T) { 101 me := mql.New(runtime(), cnquery.DefaultFeatures) 102 query := "if (props.a > 2) { return {\"a\": \"valuea\"} } return {\"a\": \"valueb\"}" 103 104 props := map[string]*llx.Primitive{ 105 "a": llx.IntPrimitive(3), 106 } 107 value, err := me.Exec(query, props) 108 require.NoError(t, err) 109 assert.Equal(t, map[string]interface{}{"a": "valuea"}, value.Value) 110 111 props = map[string]*llx.Primitive{ 112 "a": llx.IntPrimitive(2), 113 } 114 value, err = me.Exec(query, props) 115 require.NoError(t, err) 116 assert.Equal(t, map[string]interface{}{"a": "valueb"}, value.Value) 117 } 118 119 func TestMqlIfAndProps(t *testing.T) { 120 me := mql.New(runtime(), cnquery.DefaultFeatures) 121 query := "if (props.a > 2) { return {\"a\": \"valuea\"} }" 122 123 props := map[string]*llx.Primitive{ 124 "a": llx.IntPrimitive(3), 125 } 126 value, err := me.Exec(query, props) 127 require.NoError(t, err) 128 assert.Equal(t, map[string]interface{}{"a": "valuea"}, value.Value) 129 130 props = map[string]*llx.Primitive{ 131 "a": llx.IntPrimitive(2), 132 } 133 value, err = me.Exec(query, props) 134 require.NoError(t, err) 135 assert.Equal(t, nil, value.Value) 136 } 137 138 func TestResourceAliases(t *testing.T) { 139 x := testutils.InitTester(testutils.LinuxMock()) 140 x.TestSimple(t, []testutils.SimpleTest{ 141 { 142 Code: "os.unix.sshd.config.file.path", 143 ResultIndex: 0, 144 Expectation: "/etc/ssh/sshd_config", 145 }, 146 { 147 Code: "os.unix.sshd { config.file.path }", 148 ResultIndex: 0, 149 Expectation: map[string]interface{}{ 150 "_": llx.ResourceData(&llx.MockResource{Name: "sshd"}, "os.unix.sshd"), 151 "__s": llx.NilData, 152 "__t": llx.BoolData(true), 153 "k6rlXoYpV48Qd19gKeNl+/IiPnkI5VNQBiqZBca3gDKsIRiLcpXQUlDv52x9sscIWiqOMpC7+x/aBpY0IUq0ww==": llx.StringData("/etc/ssh/sshd_config"), 154 }, 155 }, 156 }) 157 } 158 159 func TestNullResources(t *testing.T) { 160 x := testutils.InitTester(testutils.LinuxMock()) 161 x.TestSimple(t, []testutils.SimpleTest{ 162 { 163 Code: "muser.group", 164 ResultIndex: 0, 165 Expectation: &llx.MockResource{Name: "mgroup", ID: "group one"}, 166 }, 167 { 168 Code: "muser.nullgroup", 169 ResultIndex: 0, 170 Expectation: nil, 171 }, 172 { 173 Code: "muser.nullgroup == null", 174 ResultIndex: 1, 175 Expectation: true, 176 }, 177 { 178 Code: "muser.nullgroup == empty", 179 ResultIndex: 2, 180 Expectation: true, 181 }, 182 { 183 Code: "muser.groups.where(null) == empty", 184 ResultIndex: 2, 185 Expectation: false, 186 }, 187 { 188 Code: "muser.groups.where(name == '') == empty", 189 ResultIndex: 2, 190 Expectation: true, 191 }, 192 { 193 Code: "muser.groups", 194 ResultIndex: 0, 195 Expectation: []interface{}{ 196 &llx.MockResource{Name: "mgroup", ID: "group one"}, 197 nil, 198 }, 199 }, 200 { 201 Code: "muser { nullgroup }", 202 ResultIndex: 0, 203 Expectation: map[string]interface{}{ 204 "_": &llx.RawData{Type: types.Resource("muser"), Value: &llx.MockResource{Name: "muser"}}, 205 "__s": llx.NilData, 206 "__t": llx.BoolTrue, 207 "A8qiFMpyfjKsr3OzVu+L+43W0BvYXoCPiwM7zu8AFQkBYEBMvZfR73ZsdfIqswmN1n9Qs/Soc1D7qxJipXv/ZA==": llx.ResourceData(nil, "mgroup"), 208 }, 209 }, 210 }) 211 }