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  }