go.mondoo.com/cnquery@v0.0.0-20231005093811-59568235f6ea/providers-sdk/v1/lr/lr_test.go (about) 1 // copyright: 2019, Dominik Richter and Christoph Hartmann 2 // author: Dominik Richter 3 // author: Christoph Hartmann 4 package lr 5 6 import ( 7 "os" 8 "testing" 9 10 "github.com/stretchr/testify/assert" 11 "github.com/stretchr/testify/require" 12 ) 13 14 func parse(t *testing.T, cmd string) *LR { 15 res, err := Parse(cmd) 16 require.Nil(t, err) 17 return res 18 } 19 20 func TestParse(t *testing.T) { 21 t.Run("empty", func(t *testing.T) { 22 res := parse(t, "") 23 assert.Equal(t, &LR{}, res) 24 }) 25 26 t.Run("empty resource", func(t *testing.T) { 27 res := parse(t, "name") 28 assert.Equal(t, []*Resource{{ID: "name"}}, res.Resources) 29 }) 30 31 t.Run("empty resources", func(t *testing.T) { 32 res := parse(t, "one tw2 thr33") 33 assert.Equal(t, []*Resource{ 34 {ID: "one"}, 35 {ID: "tw2"}, 36 {ID: "thr33"}, 37 }, res.Resources) 38 }) 39 40 t.Run("defaults", func(t *testing.T) { 41 res := parse(t, "name @defaults(\"id group=group.name\")") 42 assert.Equal(t, []*Resource{ 43 { 44 ID: "name", 45 Defaults: "id group=group.name", 46 }, 47 }, res.Resources) 48 }) 49 50 t.Run("resource with a static field", func(t *testing.T) { 51 res := parse(t, ` 52 // resource-docs 53 // with multiline 54 name { 55 // field docs... 56 field type 57 } 58 `) 59 assert.Equal(t, "name", res.Resources[0].ID) 60 // TODO: needs to be fixed 61 // assert.Equal(t, "resource-docs", res.Resources[0].title) 62 // assert.Equal(t, "with multiline", res.Resources[0].desc) 63 64 f := []*Field{ 65 { 66 BasicField: &BasicField{ 67 ID: "field", 68 Args: nil, 69 Type: Type{SimpleType: &SimpleType{"type"}}, 70 }, 71 Comments: []string{"// field docs..."}, 72 }, 73 } 74 assert.Equal(t, f, res.Resources[0].Body.Fields) 75 }) 76 77 t.Run("resource with a list type", func(t *testing.T) { 78 res := parse(t, "name {\nfield []type\n}") 79 f := []*Field{ 80 { 81 BasicField: &BasicField{ 82 ID: "field", 83 Args: nil, 84 Type: Type{ListType: &ListType{Type{SimpleType: &SimpleType{"type"}}}}, 85 }, 86 }, 87 } 88 assert.Equal(t, "name", res.Resources[0].ID) 89 assert.Equal(t, f, res.Resources[0].Body.Fields) 90 }) 91 92 t.Run("resource with a map type", func(t *testing.T) { 93 res := parse(t, "name {\nfield map[a]b\n}") 94 f := []*Field{ 95 { 96 BasicField: &BasicField{ID: "field", Args: nil, Type: Type{ 97 MapType: &MapType{SimpleType{"a"}, Type{SimpleType: &SimpleType{"b"}}}, 98 }}, 99 }, 100 } 101 assert.Equal(t, "name", res.Resources[0].ID) 102 assert.Equal(t, f, res.Resources[0].Body.Fields) 103 }) 104 105 t.Run("resource with a dependent field, no args", func(t *testing.T) { 106 res := parse(t, "name {\nfield() type\n}") 107 f := []*Field{ 108 {BasicField: &BasicField{ID: "field", Args: &FieldArgs{}, Type: Type{SimpleType: &SimpleType{"type"}}}}, 109 } 110 assert.Equal(t, "name", res.Resources[0].ID) 111 assert.Equal(t, f, res.Resources[0].Body.Fields) 112 }) 113 114 t.Run("resource with a dependent field, with args", func(t *testing.T) { 115 res := parse(t, "name {\nfield(one, two.three) type\n}") 116 f := []*Field{ 117 {BasicField: &BasicField{ID: "field", Type: Type{SimpleType: &SimpleType{"type"}}, Args: &FieldArgs{ 118 List: []SimpleType{{"one"}, {"two.three"}}, 119 }}}, 120 } 121 assert.Equal(t, "name", res.Resources[0].ID) 122 assert.Equal(t, f, res.Resources[0].Body.Fields) 123 }) 124 125 t.Run("resource with init, with args", func(t *testing.T) { 126 res := parse(t, "name {\ninit(one int, two? string)\n}") 127 f := []*Field{ 128 {Init: &Init{ 129 Args: []TypedArg{ 130 {ID: "one", Type: Type{SimpleType: &SimpleType{"int"}}}, 131 {ID: "two", Type: Type{SimpleType: &SimpleType{"string"}}, Optional: true}, 132 }, 133 }}, 134 } 135 assert.Equal(t, "name", res.Resources[0].ID) 136 assert.Equal(t, f, res.Resources[0].Body.Fields) 137 }) 138 139 t.Run("resource which is a list type", func(t *testing.T) { 140 res := parse(t, "name {\n[]base\n}") 141 lt := &SimplListType{Type: SimpleType{"base"}} 142 assert.Equal(t, "name", res.Resources[0].ID) 143 assert.Equal(t, lt, res.Resources[0].ListType) 144 }) 145 146 t.Run("resource which is a list type, with args", func(t *testing.T) { 147 res := parse(t, "name {\n[]base(content)\ncontent string\n}") 148 lt := &SimplListType{ 149 Type: SimpleType{"base"}, 150 Args: &FieldArgs{ 151 List: []SimpleType{{Type: "content"}}, 152 }, 153 } 154 assert.Equal(t, "name", res.Resources[0].ID) 155 assert.Equal(t, lt, res.Resources[0].ListType) 156 }) 157 158 t.Run("resource which is a list type based on resource chain", func(t *testing.T) { 159 res := parse(t, "name {\n[]base.type.name\n}") 160 lt := &SimplListType{Type: SimpleType{"base.type.name"}} 161 assert.Equal(t, "name", res.Resources[0].ID) 162 assert.Equal(t, lt, res.Resources[0].ListType) 163 }) 164 165 t.Run("embedded resource", func(t *testing.T) { 166 res := parse(t, ` 167 private name.no { 168 embed os.any 169 }`) 170 fields := []*Field{ 171 {BasicField: &BasicField{isEmbedded: true, ID: "os", Type: Type{SimpleType: &SimpleType{Type: "os.any"}}, Args: &FieldArgs{}}}, 172 } 173 174 assert.Equal(t, "name.no", res.Resources[0].ID) 175 assert.Equal(t, true, res.Resources[0].IsPrivate) 176 assert.Equal(t, fields, res.Resources[0].Body.Fields) 177 }) 178 179 t.Run("embedded resource with an alias", func(t *testing.T) { 180 res := parse(t, ` 181 private name.no { 182 embed os.any as testx 183 }`) 184 fields := []*Field{ 185 {BasicField: &BasicField{isEmbedded: true, ID: "testx", Type: Type{SimpleType: &SimpleType{Type: "os.any"}}, Args: &FieldArgs{}}}, 186 } 187 188 assert.Equal(t, "name.no", res.Resources[0].ID) 189 assert.Equal(t, true, res.Resources[0].IsPrivate) 190 assert.Equal(t, fields, res.Resources[0].Body.Fields) 191 }) 192 193 t.Run("complex resource", func(t *testing.T) { 194 res := parse(t, ` 195 private name.no { 196 init(i1 string, i2 map[int]int) 197 field map[string]int 198 call(resource.field) []int 199 embed os.any 200 }`) 201 fields := []*Field{ 202 {Init: &Init{Args: []TypedArg{ 203 {ID: "i1", Type: Type{SimpleType: &SimpleType{"string"}}}, 204 {ID: "i2", Type: Type{MapType: &MapType{SimpleType{"int"}, Type{SimpleType: &SimpleType{"int"}}}}}, 205 }}}, 206 {BasicField: &BasicField{ID: "field", Type: Type{MapType: &MapType{Key: SimpleType{"string"}, Value: Type{SimpleType: &SimpleType{"int"}}}}}}, 207 { 208 BasicField: &BasicField{ 209 ID: "call", 210 Type: Type{ListType: &ListType{Type: Type{SimpleType: &SimpleType{"int"}}}}, 211 Args: &FieldArgs{ 212 List: []SimpleType{{"resource.field"}}, 213 }, 214 }, 215 }, 216 {BasicField: &BasicField{isEmbedded: true, ID: "os", Type: Type{SimpleType: &SimpleType{Type: "os.any"}}, Args: &FieldArgs{}}}, 217 } 218 219 assert.Equal(t, "name.no", res.Resources[0].ID) 220 assert.Equal(t, true, res.Resources[0].IsPrivate) 221 assert.Equal(t, fields, res.Resources[0].Body.Fields) 222 }) 223 } 224 225 func TestParseLR(t *testing.T) { 226 files := []string{ 227 "core/resources/core.lr", 228 "os/resources/os.lr", 229 } 230 231 for i := range files { 232 lrPath := files[i] 233 absPath := "../../../providers/" + lrPath 234 235 t.Run(lrPath, func(t *testing.T) { 236 res, err := Resolve(absPath, func(path string) ([]byte, error) { 237 raw, err := os.ReadFile(path) 238 if err != nil { 239 t.Fatal("failed to load " + path + ":" + err.Error()) 240 } 241 return raw, err 242 }) 243 if err != nil { 244 t.Fatal("failed to compile " + lrPath + ":" + err.Error()) 245 } 246 247 collector := NewCollector(absPath) 248 godata, err := Go("resources", res, collector) 249 if err != nil { 250 t.Fatal("failed to go-convert " + lrPath + ":" + err.Error()) 251 } 252 assert.NotEmpty(t, godata) 253 254 schema, err := Schema(res) 255 if err != nil { 256 t.Fatal("failed to generate schema for " + lrPath + ":" + err.Error()) 257 } 258 assert.NotEmpty(t, schema) 259 }) 260 } 261 }