cuelang.org/go@v0.10.1/internal/buildattr/buildattr_test.go (about)

     1  package buildattr
     2  
     3  import (
     4  	"testing"
     5  
     6  	"cuelang.org/go/cue/errors"
     7  	"cuelang.org/go/cue/format"
     8  	"cuelang.org/go/cue/parser"
     9  
    10  	"github.com/go-quicktest/qt"
    11  )
    12  
    13  var shouldBuildFileTests = []struct {
    14  	testName     string
    15  	syntax       string
    16  	tags         map[string]bool
    17  	wantOK       bool
    18  	wantAttr     string
    19  	wantError    string
    20  	wantTagCalls map[string]bool
    21  }{{
    22  	testName: "EmptyFile",
    23  	syntax:   "",
    24  	wantOK:   true,
    25  }, {
    26  	testName: "PackageWithIf",
    27  	syntax: `
    28  @if(foo)
    29  
    30  package something
    31  `,
    32  	wantOK:       false,
    33  	wantTagCalls: map[string]bool{"foo": true},
    34  	wantAttr:     "@if(foo)",
    35  }, {
    36  	testName: "PackageWithComments",
    37  	syntax: `
    38  
    39  // Some comment
    40  
    41  @if(foo)
    42  
    43  // Other comment
    44  
    45  package something
    46  `,
    47  	wantOK:       false,
    48  	wantTagCalls: map[string]bool{"foo": true},
    49  	wantAttr:     "@if(foo)",
    50  }, {
    51  	testName: "PackageWithIfSuccess",
    52  	syntax: `
    53  @if(foo)
    54  
    55  package something
    56  `,
    57  	tags:         map[string]bool{"foo": true},
    58  	wantOK:       true,
    59  	wantTagCalls: map[string]bool{"foo": true},
    60  	wantAttr:     "@if(foo)",
    61  }, {
    62  	testName: "PackageWithIfAfterPackageClause",
    63  	syntax: `
    64  package something
    65  
    66  @if(foo)
    67  `,
    68  	wantOK: true,
    69  }, {
    70  	testName: "InvalidExpr",
    71  	syntax: `
    72  @if(foo + bar)
    73  
    74  package something
    75  `,
    76  	wantOK:   false,
    77  	wantAttr: "@if(foo + bar)",
    78  	wantError: `invalid operator \+ in build attribute
    79  `,
    80  }, {
    81  	testName: "MultipleIfAttributes",
    82  	syntax: `
    83  
    84  @if(foo)
    85  @if(bar)
    86  
    87  package something
    88  `,
    89  	wantOK:   false,
    90  	wantAttr: "@if(foo)",
    91  	wantError: `previous declaration here:
    92      testfile.cue:3:1
    93  multiple @if attributes:
    94      testfile.cue:4:1
    95  `,
    96  }, {
    97  	testName: "MultipleIfAttributesWithOneAfterPackage",
    98  	syntax: `
    99  
   100  @if(foo)
   101  
   102  package something
   103  
   104  @if(bar)
   105  `,
   106  	wantOK:       false,
   107  	wantAttr:     "@if(foo)",
   108  	wantTagCalls: map[string]bool{"foo": true},
   109  }, {
   110  	testName: "And#0",
   111  	syntax: `
   112  @if(foo && bar)
   113  
   114  package something
   115  `,
   116  	wantOK:   false,
   117  	wantAttr: "@if(foo && bar)",
   118  	wantTagCalls: map[string]bool{
   119  		"foo": true,
   120  		"bar": true,
   121  	},
   122  }, {
   123  	testName: "And#1",
   124  	syntax: `
   125  @if(foo && bar)
   126  
   127  package something
   128  `,
   129  	tags:     map[string]bool{"foo": true},
   130  	wantOK:   false,
   131  	wantAttr: "@if(foo && bar)",
   132  	wantTagCalls: map[string]bool{
   133  		"foo": true,
   134  		"bar": true,
   135  	},
   136  }, {
   137  	testName: "And#2",
   138  	syntax: `
   139  @if(foo && bar)
   140  
   141  package something
   142  `,
   143  	tags:     map[string]bool{"bar": true},
   144  	wantOK:   false,
   145  	wantAttr: "@if(foo && bar)",
   146  	wantTagCalls: map[string]bool{
   147  		"foo": true,
   148  		"bar": true,
   149  	},
   150  }, {
   151  	testName: "And#3",
   152  	syntax: `
   153  @if(foo && bar)
   154  
   155  package something
   156  `,
   157  	tags:     map[string]bool{"foo": true, "bar": true},
   158  	wantOK:   true,
   159  	wantAttr: "@if(foo && bar)",
   160  	wantTagCalls: map[string]bool{
   161  		"foo": true,
   162  		"bar": true,
   163  	},
   164  }, {
   165  	testName: "Or#0",
   166  	syntax: `
   167  @if(foo || bar)
   168  
   169  package something
   170  `,
   171  	wantOK:   false,
   172  	wantAttr: "@if(foo || bar)",
   173  	wantTagCalls: map[string]bool{
   174  		"foo": true,
   175  		"bar": true,
   176  	},
   177  }, {
   178  	testName: "Or#1",
   179  	syntax: `
   180  @if(foo || bar)
   181  
   182  package something
   183  `,
   184  	tags:     map[string]bool{"foo": true},
   185  	wantOK:   true,
   186  	wantAttr: "@if(foo || bar)",
   187  	wantTagCalls: map[string]bool{
   188  		"foo": true,
   189  		"bar": true,
   190  	},
   191  }, {
   192  	testName: "Or#2",
   193  	syntax: `
   194  @if(foo || bar)
   195  
   196  package something
   197  `,
   198  	tags:     map[string]bool{"bar": true},
   199  	wantOK:   true,
   200  	wantAttr: "@if(foo || bar)",
   201  	wantTagCalls: map[string]bool{
   202  		"foo": true,
   203  		"bar": true,
   204  	},
   205  }, {
   206  	testName: "Or#3",
   207  	syntax: `
   208  @if(foo || bar)
   209  
   210  package something
   211  `,
   212  	tags:     map[string]bool{"foo": true, "bar": true},
   213  	wantOK:   true,
   214  	wantAttr: "@if(foo || bar)",
   215  	wantTagCalls: map[string]bool{
   216  		"foo": true,
   217  		"bar": true,
   218  	},
   219  }, {
   220  	testName: "Not#0",
   221  	syntax: `
   222  @if(!foo)
   223  
   224  package something
   225  `,
   226  	wantOK:   true,
   227  	wantAttr: "@if(!foo)",
   228  	wantTagCalls: map[string]bool{
   229  		"foo": true,
   230  	},
   231  }, {
   232  	testName: "Not#1",
   233  	syntax: `
   234  @if(!foo)
   235  
   236  package something
   237  `,
   238  	tags:     map[string]bool{"foo": true},
   239  	wantOK:   false,
   240  	wantAttr: "@if(!foo)",
   241  	wantTagCalls: map[string]bool{
   242  		"foo": true,
   243  	},
   244  }, {
   245  	testName: "ComplexExpr",
   246  	syntax: `
   247  @if(foo || (!bar && baz))
   248  
   249  package something
   250  `,
   251  	tags: map[string]bool{
   252  		"baz": true,
   253  	},
   254  	wantOK: true,
   255  	wantTagCalls: map[string]bool{
   256  		"foo": true,
   257  		"bar": true,
   258  		"baz": true,
   259  	},
   260  	wantAttr: "@if(foo || (!bar && baz))",
   261  }, {
   262  	testName: "IgnoreOnly",
   263  	syntax: `
   264  @ignore()
   265  
   266  package something
   267  `,
   268  	wantOK:   false,
   269  	wantAttr: "@ignore()",
   270  }, {
   271  	testName: "IgnoreWithBuildAttrs",
   272  	syntax: `
   273  @ignore()
   274  @if(blah)
   275  
   276  package something
   277  `,
   278  	wantOK:   false,
   279  	wantAttr: "@ignore()",
   280  }, {
   281  	// It's arguable whether multiple @if attributes
   282  	// should be an error when there's an @ignore
   283  	// attribute, but it's easily worked around by
   284  	// putting the @ignore attribute first, which should
   285  	// be fairly intuitive.
   286  	testName: "IgnoreWithMultipleEarlierIfs",
   287  	syntax: `
   288  @if(foo)
   289  @if(bar)
   290  @ignore()
   291  
   292  package something
   293  `,
   294  	wantOK: false,
   295  	wantError: `previous declaration here:
   296      testfile.cue:2:1
   297  multiple @if attributes:
   298      testfile.cue:3:1
   299  `,
   300  	wantAttr: "@if(foo)",
   301  }, {
   302  	testName: "IgnoreWithMultipleLaterIfs",
   303  	syntax: `
   304  @ignore()
   305  @if(foo)
   306  @if(bar)
   307  
   308  package something
   309  `,
   310  	wantOK:   false,
   311  	wantAttr: "@ignore()",
   312  }, {
   313  	testName: "IgnoreWithoutPackageClause",
   314  	syntax: `
   315  @ignore()
   316  a: 5
   317  `,
   318  	wantOK:   false,
   319  	wantAttr: "@ignore()",
   320  }, {
   321  	testName: "IfAfterDeclaration",
   322  	syntax: `
   323  a: 1
   324  @if(foo)
   325  `,
   326  	wantOK: true,
   327  }}
   328  
   329  func TestShouldBuildFile(t *testing.T) {
   330  	for _, test := range shouldBuildFileTests {
   331  		t.Run(test.testName, func(t *testing.T) {
   332  			f, err := parser.ParseFile("testfile.cue", test.syntax)
   333  			qt.Assert(t, qt.IsNil(err))
   334  			tagsUsed := make(map[string]bool)
   335  			ok, attr, err := ShouldBuildFile(f, func(tag string) bool {
   336  				tagsUsed[tag] = true
   337  				return test.tags[tag]
   338  			})
   339  			qt.Check(t, qt.Equals(ok, test.wantOK))
   340  			if test.wantAttr == "" {
   341  				qt.Assert(t, qt.IsNil(attr))
   342  			} else {
   343  				qt.Assert(t, qt.Not(qt.IsNil(attr)))
   344  				attrStr, err := format.Node(attr)
   345  				qt.Assert(t, qt.IsNil(err))
   346  				qt.Assert(t, qt.Equals(string(attrStr), test.wantAttr))
   347  			}
   348  			if test.wantError != "" {
   349  				qt.Assert(t, qt.Not(qt.IsNil(err)))
   350  				qt.Assert(t, qt.Matches(errors.Details(err, nil), test.wantError))
   351  				qt.Assert(t, qt.Equals(ok, false))
   352  				return
   353  			}
   354  			qt.Assert(t, qt.IsNil(err))
   355  			if len(tagsUsed) == 0 {
   356  				tagsUsed = nil
   357  			}
   358  			qt.Check(t, qt.DeepEquals(tagsUsed, test.wantTagCalls))
   359  		})
   360  	}
   361  }