go.chromium.org/luci@v0.0.0-20240309015107-7cdc2e660f33/milo/internal/utils/utils_test.go (about)

     1  // Copyright 2019 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 utils
    16  
    17  import (
    18  	"context"
    19  	"testing"
    20  
    21  	"go.chromium.org/luci/auth/identity"
    22  	buildbucketpb "go.chromium.org/luci/buildbucket/proto"
    23  	"go.chromium.org/luci/common/errors"
    24  	"go.chromium.org/luci/gae/impl/memory"
    25  	"go.chromium.org/luci/grpc/grpcutil"
    26  	"go.chromium.org/luci/server/auth"
    27  	"go.chromium.org/luci/server/auth/authtest"
    28  	"google.golang.org/grpc/codes"
    29  	"google.golang.org/grpc/status"
    30  
    31  	. "github.com/smartystreets/goconvey/convey"
    32  )
    33  
    34  type TestStruct struct {
    35  	Prop string
    36  }
    37  
    38  func TestTagGRPC(t *testing.T) {
    39  	t.Parallel()
    40  
    41  	Convey("GRPC tagging works", t, func() {
    42  		c := memory.Use(context.Background())
    43  		cUser := auth.WithState(c, &authtest.FakeState{Identity: "user:user@example.com"})
    44  		cAnon := auth.WithState(c, &authtest.FakeState{Identity: identity.AnonymousIdentity})
    45  
    46  		Convey("For not found errors", func() {
    47  			errGRPCNotFound := status.Errorf(codes.NotFound, "not found")
    48  			So(grpcutil.Code(TagGRPC(cAnon, errGRPCNotFound)), ShouldEqual, codes.Unauthenticated)
    49  			So(grpcutil.Code(TagGRPC(cUser, errGRPCNotFound)), ShouldEqual, codes.NotFound)
    50  		})
    51  
    52  		Convey("For permission denied errors", func() {
    53  			errGRPCPermissionDenied := status.Errorf(codes.PermissionDenied, "permission denied")
    54  			So(grpcutil.Code(TagGRPC(cAnon, errGRPCPermissionDenied)), ShouldEqual, codes.Unauthenticated)
    55  			So(grpcutil.Code(TagGRPC(cUser, errGRPCPermissionDenied)), ShouldEqual, codes.NotFound)
    56  		})
    57  
    58  		Convey("For invalid argument errors", func() {
    59  			errGRPCInvalidArgument := status.Errorf(codes.InvalidArgument, "invalid argument")
    60  			So(grpcutil.Code(TagGRPC(cAnon, errGRPCInvalidArgument)), ShouldEqual, codes.InvalidArgument)
    61  			So(grpcutil.Code(TagGRPC(cUser, errGRPCInvalidArgument)), ShouldEqual, codes.InvalidArgument)
    62  		})
    63  
    64  		Convey("For invalid argument multi-errors", func() {
    65  			errGRPCInvalidArgument := status.Errorf(codes.InvalidArgument, "invalid argument")
    66  			errMulti := errors.NewMultiError(errGRPCInvalidArgument)
    67  			So(grpcutil.Code(TagGRPC(cAnon, errMulti)), ShouldEqual, codes.InvalidArgument)
    68  			So(grpcutil.Code(TagGRPC(cUser, errMulti)), ShouldEqual, codes.InvalidArgument)
    69  		})
    70  	})
    71  
    72  	Convey("ParseLegacyBuilderID", t, func() {
    73  		Convey("For valid ID", func() {
    74  			builderID, err := ParseLegacyBuilderID("buildbucket/luci.test project.test bucket/test builder")
    75  			So(err, ShouldBeNil)
    76  			So(builderID, ShouldResemble, &buildbucketpb.BuilderID{
    77  				Project: "test project",
    78  				Bucket:  "test bucket",
    79  				Builder: "test builder",
    80  			})
    81  		})
    82  
    83  		Convey("Allow '.' in builder ID", func() {
    84  			builderID, err := ParseLegacyBuilderID("buildbucket/luci.test project.test bucket/test.builder")
    85  			So(err, ShouldBeNil)
    86  			So(builderID, ShouldResemble, &buildbucketpb.BuilderID{
    87  				Project: "test project",
    88  				Bucket:  "test bucket",
    89  				Builder: "test.builder",
    90  			})
    91  		})
    92  
    93  		Convey("Allow '.' in bucket ID", func() {
    94  			builderID, err := ParseLegacyBuilderID("buildbucket/luci.test project.test.bucket/test builder")
    95  			So(err, ShouldBeNil)
    96  			So(builderID, ShouldResemble, &buildbucketpb.BuilderID{
    97  				Project: "test project",
    98  				Bucket:  "test.bucket",
    99  				Builder: "test builder",
   100  			})
   101  		})
   102  
   103  		Convey("For invalid ID", func() {
   104  			builderID, err := ParseLegacyBuilderID("buildbucket/123456")
   105  			So(err, ShouldEqual, ErrInvalidLegacyBuilderID)
   106  			So(builderID, ShouldBeNil)
   107  		})
   108  	})
   109  
   110  	Convey("ParseBuilderID", t, func() {
   111  		Convey("For valid ID", func() {
   112  			builderID, err := ParseBuilderID("test project/test bucket/test builder")
   113  			So(builderID, ShouldResemble, &buildbucketpb.BuilderID{
   114  				Project: "test project",
   115  				Bucket:  "test bucket",
   116  				Builder: "test builder",
   117  			})
   118  			So(err, ShouldBeNil)
   119  		})
   120  
   121  		Convey("For invalid ID", func() {
   122  			builderID, err := ParseBuilderID("test project/123456")
   123  			So(builderID, ShouldBeNil)
   124  			So(err, ShouldEqual, ErrInvalidBuilderID)
   125  		})
   126  	})
   127  
   128  	Convey("ParseBuildbucketBuildID", t, func() {
   129  		Convey("For valid build ID", func() {
   130  			bid, err := ParseBuildbucketBuildID("buildbucket/123456")
   131  			So(err, ShouldBeNil)
   132  			So(bid, ShouldEqual, 123456)
   133  		})
   134  
   135  		Convey("For invalid build ID", func() {
   136  			bid, err := ParseBuildbucketBuildID("notbuildbucket/123456")
   137  			So(err, ShouldEqual, ErrInvalidLegacyBuildID)
   138  			So(bid, ShouldEqual, 0)
   139  		})
   140  	})
   141  
   142  	Convey("ParseLegacyBuildbucketBuildID", t, func() {
   143  		Convey("For valid build ID", func() {
   144  			builderID, buildNum, err := ParseLegacyBuildbucketBuildID("buildbucket/luci.test project.test bucket/test builder/123456")
   145  			So(err, ShouldBeNil)
   146  			So(builderID, ShouldResemble, &buildbucketpb.BuilderID{
   147  				Project: "test project",
   148  				Bucket:  "test bucket",
   149  				Builder: "test builder",
   150  			})
   151  			So(buildNum, ShouldEqual, 123456)
   152  		})
   153  
   154  		Convey("Allow '.' in builder ID", func() {
   155  			builderID, buildNum, err := ParseLegacyBuildbucketBuildID("buildbucket/luci.test project.test bucket/test.builder/123456")
   156  			So(err, ShouldBeNil)
   157  			So(builderID, ShouldResemble, &buildbucketpb.BuilderID{
   158  				Project: "test project",
   159  				Bucket:  "test bucket",
   160  				Builder: "test.builder",
   161  			})
   162  			So(buildNum, ShouldEqual, 123456)
   163  		})
   164  
   165  		Convey("Allow '.' in bucket ID", func() {
   166  			builderID, buildNum, err := ParseLegacyBuildbucketBuildID("buildbucket/luci.test project.test.bucket/test builder/123456")
   167  			So(err, ShouldBeNil)
   168  			So(builderID, ShouldResemble, &buildbucketpb.BuilderID{
   169  				Project: "test project",
   170  				Bucket:  "test.bucket",
   171  				Builder: "test builder",
   172  			})
   173  			So(buildNum, ShouldEqual, 123456)
   174  		})
   175  
   176  		Convey("For invalid build ID", func() {
   177  			builderID, buildNum, err := ParseLegacyBuildbucketBuildID("buildbucket/123456")
   178  			So(err, ShouldEqual, ErrInvalidLegacyBuildID)
   179  			So(builderID, ShouldBeNil)
   180  			So(buildNum, ShouldEqual, 0)
   181  		})
   182  	})
   183  }