go.chromium.org/luci@v0.0.0-20240309015107-7cdc2e660f33/logdog/appengine/coordinator/endpoints/services/loadStream_test.go (about)

     1  // Copyright 2015 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 services
    16  
    17  import (
    18  	"errors"
    19  	"testing"
    20  	"time"
    21  
    22  	"google.golang.org/protobuf/proto"
    23  	"google.golang.org/protobuf/types/known/durationpb"
    24  
    25  	"go.chromium.org/luci/gae/filter/featureBreaker"
    26  	logdog "go.chromium.org/luci/logdog/api/endpoints/coordinator/services/v1"
    27  	"go.chromium.org/luci/logdog/appengine/coordinator"
    28  	ct "go.chromium.org/luci/logdog/appengine/coordinator/coordinatorTest"
    29  
    30  	. "github.com/smartystreets/goconvey/convey"
    31  
    32  	. "go.chromium.org/luci/common/testing/assertions"
    33  )
    34  
    35  func TestLoadStream(t *testing.T) {
    36  	t.Parallel()
    37  
    38  	Convey(`With a testing configuration`, t, func() {
    39  		c, env := ct.Install()
    40  
    41  		svr := New(ServerSettings{NumQueues: 2})
    42  
    43  		// Register a test stream.
    44  		env.AddProject(c, "proj-foo")
    45  		tls := ct.MakeStream(c, "proj-foo", "some-realm", "testing/+/foo/bar")
    46  		if err := tls.Put(c); err != nil {
    47  			panic(err)
    48  		}
    49  
    50  		// Prepare a request to load the test stream.
    51  		req := &logdog.LoadStreamRequest{
    52  			Project: string(tls.Project),
    53  			Id:      string(tls.Stream.ID),
    54  		}
    55  
    56  		Convey(`Returns Forbidden error if not a service.`, func() {
    57  			_, err := svr.LoadStream(c, &logdog.LoadStreamRequest{})
    58  			So(err, ShouldBeRPCPermissionDenied)
    59  		})
    60  
    61  		Convey(`When logged in as a service`, func() {
    62  			env.ActAsService()
    63  
    64  			Convey(`Will succeed.`, func() {
    65  				resp, err := svr.LoadStream(c, req)
    66  				So(err, ShouldBeNil)
    67  				So(resp, ShouldResembleProto, &logdog.LoadStreamResponse{
    68  					State: &logdog.InternalLogStreamState{
    69  						ProtoVersion:  "1",
    70  						TerminalIndex: -1,
    71  						Secret:        tls.State.Secret,
    72  					},
    73  					Age: durationpb.New(0),
    74  				})
    75  			})
    76  
    77  			Convey(`Will return archival properties.`, func() {
    78  				// Add an hour to the clock. Created is +0, Updated is +1hr.
    79  				env.Clock.Add(1 * time.Hour)
    80  				tls.State.ArchivalKey = []byte("archival key")
    81  				tls.Reload(c)
    82  				if err := tls.Put(c); err != nil {
    83  					panic(err)
    84  				}
    85  
    86  				// Set time to +2hr, age should now be 1hr.
    87  				env.Clock.Add(1 * time.Hour)
    88  				resp, err := svr.LoadStream(c, req)
    89  				So(err, ShouldBeNil)
    90  				So(resp, ShouldResembleProto, &logdog.LoadStreamResponse{
    91  					State: &logdog.InternalLogStreamState{
    92  						ProtoVersion:  "1",
    93  						TerminalIndex: -1,
    94  						Secret:        tls.State.Secret,
    95  					},
    96  					ArchivalKey: []byte("archival key"),
    97  					Age:         durationpb.New(1 * time.Hour),
    98  				})
    99  			})
   100  
   101  			Convey(`Will succeed, and return the descriptor when requested.`, func() {
   102  				req.Desc = true
   103  
   104  				d, err := proto.Marshal(tls.Desc)
   105  				if err != nil {
   106  					panic(err)
   107  				}
   108  
   109  				resp, err := svr.LoadStream(c, req)
   110  				So(err, ShouldBeNil)
   111  				So(resp, ShouldResembleProto, &logdog.LoadStreamResponse{
   112  					State: &logdog.InternalLogStreamState{
   113  						ProtoVersion:  "1",
   114  						TerminalIndex: -1,
   115  						Secret:        tls.State.Secret,
   116  					},
   117  					Desc: d,
   118  					Age:  durationpb.New(0),
   119  				})
   120  			})
   121  
   122  			Convey(`Will return InvalidArgument if the stream hash is not valid.`, func() {
   123  				req.Id = string("!!! not a hash !!!")
   124  
   125  				_, err := svr.LoadStream(c, req)
   126  				So(err, ShouldBeRPCInvalidArgument, "Invalid ID")
   127  			})
   128  
   129  			Convey(`Will return NotFound for non-existent streams.`, func() {
   130  				req.Id = string(coordinator.LogStreamID("this/stream/+/does/not/exist"))
   131  
   132  				_, err := svr.LoadStream(c, req)
   133  				So(err, ShouldBeRPCNotFound)
   134  			})
   135  
   136  			Convey(`Will return Internal for random datastore failures.`, func() {
   137  				c, fb := featureBreaker.FilterRDS(c, nil)
   138  				fb.BreakFeatures(errors.New("test error"), "GetMulti")
   139  
   140  				_, err := svr.LoadStream(c, req)
   141  				So(err, ShouldBeRPCInternal)
   142  			})
   143  		})
   144  	})
   145  }