go.chromium.org/luci@v0.0.0-20240309015107-7cdc2e660f33/config_service/internal/rules/util_test.go (about)

     1  // Copyright 2023 The LUCI Authors.
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //      http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  package rules
    16  
    17  import (
    18  	"testing"
    19  
    20  	"go.chromium.org/luci/config/validation"
    21  
    22  	"go.chromium.org/luci/config_service/testutil"
    23  
    24  	. "github.com/smartystreets/goconvey/convey"
    25  	"go.chromium.org/luci/common/data/stringset"
    26  	. "go.chromium.org/luci/common/testing/assertions"
    27  )
    28  
    29  func TestValidateAccess(t *testing.T) {
    30  	t.Parallel()
    31  
    32  	Convey("Validate access", t, func() {
    33  		ctx := testutil.SetupContext()
    34  		vctx := &validation.Context{Context: ctx}
    35  
    36  		Convey("not specified", func() {
    37  			validateAccess(vctx, "")
    38  			So(vctx.Finalize(), ShouldErrLike, `not specified`)
    39  		})
    40  		Convey("invalid group", func() {
    41  			validateAccess(vctx, "group:foo^")
    42  			So(vctx.Finalize(), ShouldErrLike, `invalid auth group: "foo^"`)
    43  		})
    44  		Convey("unknown identity", func() {
    45  			validateAccess(vctx, "bad-kind:abc")
    46  			So(vctx.Finalize(), ShouldErrLike, `invalid identity "bad-kind:abc"; reason:`)
    47  		})
    48  		Convey("bad email", func() {
    49  			validateAccess(vctx, "not-a-valid-email")
    50  			So(vctx.Finalize(), ShouldErrLike, `invalid email address:`)
    51  		})
    52  	})
    53  }
    54  
    55  func TestValidateEmail(t *testing.T) {
    56  	t.Parallel()
    57  
    58  	Convey("Validate email", t, func() {
    59  		ctx := testutil.SetupContext()
    60  		vctx := &validation.Context{Context: ctx}
    61  
    62  		Convey("not specified", func() {
    63  			validateEmail(vctx, "")
    64  			So(vctx.Finalize(), ShouldErrLike, `email not specified`)
    65  		})
    66  		Convey("invalid email", func() {
    67  			validateEmail(vctx, "not-a-valid-email")
    68  			So(vctx.Finalize(), ShouldErrLike, `invalid email address:`)
    69  		})
    70  	})
    71  }
    72  
    73  func TestValidateSorted(t *testing.T) {
    74  	t.Parallel()
    75  
    76  	Convey("Validate sorted", t, func() {
    77  		ctx := testutil.SetupContext()
    78  		vctx := &validation.Context{Context: ctx}
    79  
    80  		type testItem struct {
    81  			id string
    82  		}
    83  		getIDFn := func(ti testItem) string { return ti.id }
    84  
    85  		Convey("handle empty", func() {
    86  			validateSorted[testItem](vctx, []testItem{}, "test_items", getIDFn)
    87  			So(vctx.Finalize(), ShouldBeNil)
    88  		})
    89  		Convey("sorted", func() {
    90  			validateSorted[testItem](vctx, []testItem{{"a"}, {"b"}, {"c"}}, "test_items", getIDFn)
    91  			So(vctx.Finalize(), ShouldBeNil)
    92  		})
    93  		Convey("ignore empty", func() {
    94  			validateSorted[testItem](vctx, []testItem{{"a"}, {""}, {"c"}}, "test_items", getIDFn)
    95  			So(vctx.Finalize(), ShouldBeNil)
    96  		})
    97  		Convey("not sorted", func() {
    98  			validateSorted[testItem](vctx, []testItem{{"a"}, {"c"}, {"b"}, {"d"}}, "test_items", getIDFn)
    99  			verr := vctx.Finalize().(*validation.Error)
   100  			So(verr.WithSeverity(validation.Warning), ShouldErrLike, `test_items are not sorted by id. First offending id: "b"`)
   101  		})
   102  	})
   103  }
   104  
   105  func TestValidateUniqueID(t *testing.T) {
   106  	t.Parallel()
   107  
   108  	Convey("Validate unique ID", t, func() {
   109  		ctx := testutil.SetupContext()
   110  		vctx := &validation.Context{Context: ctx}
   111  
   112  		Convey("empty", func() {
   113  			validateUniqueID(vctx, "", stringset.New(0), nil)
   114  			So(vctx.Finalize(), ShouldErrLike, `not specified`)
   115  		})
   116  
   117  		Convey("duplicate", func() {
   118  			seen := stringset.New(2)
   119  			validateUniqueID(vctx, "id", seen, nil)
   120  			So(vctx.Finalize(), ShouldBeNil)
   121  			validateUniqueID(vctx, "id", seen, nil)
   122  			So(vctx.Finalize(), ShouldErrLike, `duplicate: "id"`)
   123  		})
   124  
   125  		Convey("apply validateIDFn", func() {
   126  			validateUniqueID(vctx, "id", stringset.New(0), func(vctx *validation.Context, id string) {
   127  				vctx.Errorf("bad bad bad")
   128  			})
   129  			So(vctx.Finalize(), ShouldErrLike, `bad bad bad`)
   130  		})
   131  	})
   132  }
   133  
   134  func TestValidateURL(t *testing.T) {
   135  	t.Parallel()
   136  
   137  	Convey("Validate url", t, func() {
   138  		ctx := testutil.SetupContext()
   139  		vctx := &validation.Context{Context: ctx}
   140  
   141  		Convey("empty", func() {
   142  			validateURL(vctx, "")
   143  			So(vctx.Finalize(), ShouldErrLike, `not specified`)
   144  		})
   145  		Convey("invalid url", func() {
   146  			validateURL(vctx, "https://example.com\\foo")
   147  			So(vctx.Finalize(), ShouldErrLike, `invalid url:`)
   148  		})
   149  		Convey("missing host name", func() {
   150  			validateURL(vctx, "https://")
   151  			So(vctx.Finalize(), ShouldErrLike, `hostname must be specified`)
   152  		})
   153  		Convey("must use https", func() {
   154  			validateURL(vctx, "http://example.com")
   155  			So(vctx.Finalize(), ShouldErrLike, `scheme must be "https"`)
   156  		})
   157  	})
   158  }