diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index b450830..9e75d60 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -18,7 +18,7 @@ jobs: - name: Setup Sage uses: einride/sage/actions/setup@master with: - go-version: '1.23' + go-version-file: .sage/go.mod check-latest: true - name: Setup Node @@ -49,7 +49,7 @@ jobs: - name: Setup Sage uses: einride/sage/actions/setup@master with: - go-version: '1.23' + go-version-file: .sage/go.mod check-latest: true - name: Make diff --git a/.github/workflows/review.yml b/.github/workflows/review.yml index 78b42ac..1506c82 100644 --- a/.github/workflows/review.yml +++ b/.github/workflows/review.yml @@ -11,7 +11,7 @@ jobs: - name: Setup Sage uses: einride/sage/actions/setup@master with: - go-version: '1.23' + go-version-file: .sage/go.mod check-latest: true - name: Make diff --git a/.sage/go.mod b/.sage/go.mod index cf25aab..eccbf31 100644 --- a/.sage/go.mod +++ b/.sage/go.mod @@ -1,5 +1,5 @@ module sage -go 1.23 +go 1.25.7 -require go.einride.tech/sage v0.347.0 +require go.einride.tech/sage v0.405.1 diff --git a/.sage/go.sum b/.sage/go.sum index b999689..20c9d0d 100644 --- a/.sage/go.sum +++ b/.sage/go.sum @@ -1,2 +1,2 @@ -go.einride.tech/sage v0.347.0 h1:mbbRgq/HWXps5hWgGDT2HH3tuPQfViEKPkGLHqe5w8I= -go.einride.tech/sage v0.347.0/go.mod h1:EzV5uciFX7/2ho8EKB5K9JghOfXIxlzs694b+Tkl5GQ= +go.einride.tech/sage v0.405.1 h1:4vABEmRGSFp+TyE1noBuLIMXhuL8iQaJMqa4uYum7Vs= +go.einride.tech/sage v0.405.1/go.mod h1:k/GWZv8EP64DxdCSZt9GIYMgOCxntdfE6FTRTIzQVdE= diff --git a/Makefile b/Makefile index 593799f..a549b1d 100644 --- a/Makefile +++ b/Makefile @@ -10,7 +10,7 @@ sagefile := $(abspath $(cwd)/.sage/bin/sagefile) go := $(shell command -v go 2>/dev/null) export GOWORK ?= off ifndef go -SAGE_GO_VERSION ?= 1.23.4 +SAGE_GO_VERSION ?= 1.25.7 export GOROOT := $(abspath $(cwd)/.sage/tools/go/$(SAGE_GO_VERSION)/go) export PATH := $(PATH):$(GOROOT)/bin go := $(GOROOT)/bin/go @@ -37,7 +37,7 @@ sage: .PHONY: update-sage update-sage: $(go) - @cd .sage && $(go) get -d go.einride.tech/sage@latest && $(go) mod tidy && $(go) run . + @cd .sage && $(go) get go.einride.tech/sage@latest && $(go) mod tidy && $(go) run . .PHONY: clean-sage clean-sage: diff --git a/proto/Makefile b/proto/Makefile index ed532dc..0a7a028 100644 --- a/proto/Makefile +++ b/proto/Makefile @@ -10,7 +10,7 @@ sagefile := $(abspath $(cwd)/../.sage/bin/sagefile) go := $(shell command -v go 2>/dev/null) export GOWORK ?= off ifndef go -SAGE_GO_VERSION ?= 1.23.4 +SAGE_GO_VERSION ?= 1.25.7 export GOROOT := $(abspath $(cwd)/../.sage/tools/go/$(SAGE_GO_VERSION)/go) export PATH := $(PATH):$(GOROOT)/bin go := $(GOROOT)/bin/go @@ -37,7 +37,7 @@ sage: .PHONY: update-sage update-sage: $(go) - @cd ../.sage && $(go) get -d go.einride.tech/sage@latest && $(go) mod tidy && $(go) run . + @cd ../.sage && $(go) get go.einride.tech/sage@latest && $(go) mod tidy && $(go) run . .PHONY: clean-sage clean-sage: diff --git a/proto/gen/go/einride/saga/extend/book/v1beta1/booking_service_aiptest.pb.go b/proto/gen/go/einride/saga/extend/book/v1beta1/booking_service_aiptest.pb.go index d3351fb..67468c9 100644 --- a/proto/gen/go/einride/saga/extend/book/v1beta1/booking_service_aiptest.pb.go +++ b/proto/gen/go/einride/saga/extend/book/v1beta1/booking_service_aiptest.pb.go @@ -365,115 +365,117 @@ func (fx *BookingServiceTourTestSuiteConfig) testUpdate(t *testing.T) { assert.DeepEqual(t, originalCreateTime, updated.CreateTime, protocmp.Transform()) }) - parent := fx.nextParent(t, false) - created := fx.create(t, parent) - // Method should fail with NotFound if the resource does not exist. - t.Run("not found", func(t *testing.T) { - fx.maybeSkip(t) - msg := fx.Update(parent) - msg.Name = created.Name + "notfound" - _, err := fx.Service().UpdateTour(fx.Context(), &UpdateTourRequest{ - Tour: msg, - }) - assert.Equal(t, codes.NotFound, status.Code(err), err) - }) - - // The method should fail with InvalidArgument if the update_mask is invalid. - t.Run("invalid update mask", func(t *testing.T) { - fx.maybeSkip(t) - _, err := fx.Service().UpdateTour(fx.Context(), &UpdateTourRequest{ - Tour: created, - UpdateMask: &fieldmaskpb.FieldMask{ - Paths: []string{ - "invalid_field_xyz", - }, - }, - }) - assert.Equal(t, codes.InvalidArgument, status.Code(err), err) - }) - - // Method should fail with InvalidArgument if any required field is missing - // when called with '*' update_mask. - t.Run("required fields", func(t *testing.T) { - fx.maybeSkip(t) - t.Run(".sender", func(t *testing.T) { + { + parent := fx.nextParent(t, false) + created := fx.create(t, parent) + // Method should fail with NotFound if the resource does not exist. + t.Run("not found", func(t *testing.T) { fx.maybeSkip(t) - msg := proto.Clone(created).(*Tour) - container := msg - if container == nil { - t.Skip("not reachable") - } - fd := container.ProtoReflect().Descriptor().Fields().ByName("sender") - container.ProtoReflect().Clear(fd) + msg := fx.Update(parent) + msg.Name = created.Name + "notfound" _, err := fx.Service().UpdateTour(fx.Context(), &UpdateTourRequest{ Tour: msg, - UpdateMask: &fieldmaskpb.FieldMask{ - Paths: []string{ - "*", - }, - }, }) - assert.Equal(t, codes.InvalidArgument, status.Code(err), err) + assert.Equal(t, codes.NotFound, status.Code(err), err) }) - t.Run(".service_type", func(t *testing.T) { + + // The method should fail with InvalidArgument if the update_mask is invalid. + t.Run("invalid update mask", func(t *testing.T) { fx.maybeSkip(t) - msg := proto.Clone(created).(*Tour) - container := msg - if container == nil { - t.Skip("not reachable") - } - fd := container.ProtoReflect().Descriptor().Fields().ByName("service_type") - container.ProtoReflect().Clear(fd) _, err := fx.Service().UpdateTour(fx.Context(), &UpdateTourRequest{ - Tour: msg, + Tour: created, UpdateMask: &fieldmaskpb.FieldMask{ Paths: []string{ - "*", + "invalid_field_xyz", }, }, }) assert.Equal(t, codes.InvalidArgument, status.Code(err), err) }) - t.Run(".preliminary_shipments", func(t *testing.T) { + + // Method should fail with InvalidArgument if any required field is missing + // when called with '*' update_mask. + t.Run("required fields", func(t *testing.T) { fx.maybeSkip(t) - msg := proto.Clone(created).(*Tour) - container := msg - if container == nil { - t.Skip("not reachable") - } - fd := container.ProtoReflect().Descriptor().Fields().ByName("preliminary_shipments") - container.ProtoReflect().Clear(fd) - _, err := fx.Service().UpdateTour(fx.Context(), &UpdateTourRequest{ - Tour: msg, - UpdateMask: &fieldmaskpb.FieldMask{ - Paths: []string{ - "*", + t.Run(".sender", func(t *testing.T) { + fx.maybeSkip(t) + msg := proto.Clone(created).(*Tour) + container := msg + if container == nil { + t.Skip("not reachable") + } + fd := container.ProtoReflect().Descriptor().Fields().ByName("sender") + container.ProtoReflect().Clear(fd) + _, err := fx.Service().UpdateTour(fx.Context(), &UpdateTourRequest{ + Tour: msg, + UpdateMask: &fieldmaskpb.FieldMask{ + Paths: []string{ + "*", + }, }, - }, + }) + assert.Equal(t, codes.InvalidArgument, status.Code(err), err) }) - assert.Equal(t, codes.InvalidArgument, status.Code(err), err) - }) - t.Run(".stops", func(t *testing.T) { - fx.maybeSkip(t) - msg := proto.Clone(created).(*Tour) - container := msg - if container == nil { - t.Skip("not reachable") - } - fd := container.ProtoReflect().Descriptor().Fields().ByName("stops") - container.ProtoReflect().Clear(fd) - _, err := fx.Service().UpdateTour(fx.Context(), &UpdateTourRequest{ - Tour: msg, - UpdateMask: &fieldmaskpb.FieldMask{ - Paths: []string{ - "*", + t.Run(".service_type", func(t *testing.T) { + fx.maybeSkip(t) + msg := proto.Clone(created).(*Tour) + container := msg + if container == nil { + t.Skip("not reachable") + } + fd := container.ProtoReflect().Descriptor().Fields().ByName("service_type") + container.ProtoReflect().Clear(fd) + _, err := fx.Service().UpdateTour(fx.Context(), &UpdateTourRequest{ + Tour: msg, + UpdateMask: &fieldmaskpb.FieldMask{ + Paths: []string{ + "*", + }, }, - }, + }) + assert.Equal(t, codes.InvalidArgument, status.Code(err), err) + }) + t.Run(".preliminary_shipments", func(t *testing.T) { + fx.maybeSkip(t) + msg := proto.Clone(created).(*Tour) + container := msg + if container == nil { + t.Skip("not reachable") + } + fd := container.ProtoReflect().Descriptor().Fields().ByName("preliminary_shipments") + container.ProtoReflect().Clear(fd) + _, err := fx.Service().UpdateTour(fx.Context(), &UpdateTourRequest{ + Tour: msg, + UpdateMask: &fieldmaskpb.FieldMask{ + Paths: []string{ + "*", + }, + }, + }) + assert.Equal(t, codes.InvalidArgument, status.Code(err), err) + }) + t.Run(".stops", func(t *testing.T) { + fx.maybeSkip(t) + msg := proto.Clone(created).(*Tour) + container := msg + if container == nil { + t.Skip("not reachable") + } + fd := container.ProtoReflect().Descriptor().Fields().ByName("stops") + container.ProtoReflect().Clear(fd) + _, err := fx.Service().UpdateTour(fx.Context(), &UpdateTourRequest{ + Tour: msg, + UpdateMask: &fieldmaskpb.FieldMask{ + Paths: []string{ + "*", + }, + }, + }) + assert.Equal(t, codes.InvalidArgument, status.Code(err), err) }) - assert.Equal(t, codes.InvalidArgument, status.Code(err), err) }) - }) + } } func (fx *BookingServiceTourTestSuiteConfig) testList(t *testing.T) { @@ -509,85 +511,125 @@ func (fx *BookingServiceTourTestSuiteConfig) testList(t *testing.T) { assert.Equal(t, codes.InvalidArgument, status.Code(err), err) }) - const resourcesCount = 15 - parent := fx.nextParent(t, true) - parentMsgs := make([]*Tour, resourcesCount) - for i := 0; i < resourcesCount; i++ { - parentMsgs[i] = fx.create(t, parent) - } - - // If parent is provided the method must only return resources - // under that parent. - t.Run("isolation", func(t *testing.T) { - fx.maybeSkip(t) - response, err := fx.Service().ListTours(fx.Context(), &ListToursRequest{ - Parent: parent, - PageSize: 999, - }) - assert.NilError(t, err) - assert.DeepEqual( - t, - parentMsgs, - response.Tours, - cmpopts.SortSlices(func(a, b *Tour) bool { - return a.Name < b.Name - }), - protocmp.Transform(), - ) - }) - - // If there are no more resources, next_page_token should not be set. - t.Run("last page", func(t *testing.T) { - fx.maybeSkip(t) - response, err := fx.Service().ListTours(fx.Context(), &ListToursRequest{ - Parent: parent, - PageSize: resourcesCount, - }) - assert.NilError(t, err) - assert.Equal(t, "", response.NextPageToken) - }) + { + const resourcesCount = 15 + parent := fx.nextParent(t, true) + parentMsgs := make([]*Tour, resourcesCount) + for i := 0; i < resourcesCount; i++ { + parentMsgs[i] = fx.create(t, parent) + } - // If there are more resources, next_page_token should be set. - t.Run("more pages", func(t *testing.T) { - fx.maybeSkip(t) - response, err := fx.Service().ListTours(fx.Context(), &ListToursRequest{ - Parent: parent, - PageSize: resourcesCount - 1, + // If parent is provided the method must only return resources + // under that parent. + t.Run("isolation", func(t *testing.T) { + fx.maybeSkip(t) + response, err := fx.Service().ListTours(fx.Context(), &ListToursRequest{ + Parent: parent, + PageSize: 999, + }) + assert.NilError(t, err) + assert.DeepEqual( + t, + parentMsgs, + response.Tours, + cmpopts.SortSlices(func(a, b *Tour) bool { + return a.Name < b.Name + }), + protocmp.Transform(), + ) + }) + + // If there are no more resources, next_page_token should not be set. + t.Run("last page", func(t *testing.T) { + fx.maybeSkip(t) + response, err := fx.Service().ListTours(fx.Context(), &ListToursRequest{ + Parent: parent, + PageSize: resourcesCount, + }) + assert.NilError(t, err) + assert.Equal(t, "", response.NextPageToken) }) - assert.NilError(t, err) - assert.Check(t, response.NextPageToken != "") - }) - // Listing resource one by one should eventually return all resources. - t.Run("one by one", func(t *testing.T) { - fx.maybeSkip(t) - msgs := make([]*Tour, 0, resourcesCount) - var nextPageToken string - for { + // If there are more resources, next_page_token should be set. + t.Run("more pages", func(t *testing.T) { + fx.maybeSkip(t) response, err := fx.Service().ListTours(fx.Context(), &ListToursRequest{ - Parent: parent, - PageSize: 1, - PageToken: nextPageToken, + Parent: parent, + PageSize: resourcesCount - 1, }) assert.NilError(t, err) - assert.Equal(t, 1, len(response.Tours)) - msgs = append(msgs, response.Tours...) - nextPageToken = response.NextPageToken - if nextPageToken == "" { - break + assert.Check(t, response.NextPageToken != "") + }) + + // Listing resource one by one should eventually return all resources. + t.Run("one by one", func(t *testing.T) { + fx.maybeSkip(t) + msgs := make([]*Tour, 0, resourcesCount) + var nextPageToken string + for { + response, err := fx.Service().ListTours(fx.Context(), &ListToursRequest{ + Parent: parent, + PageSize: 1, + PageToken: nextPageToken, + }) + assert.NilError(t, err) + assert.Equal(t, 1, len(response.Tours)) + msgs = append(msgs, response.Tours...) + nextPageToken = response.NextPageToken + if nextPageToken == "" { + break + } } + assert.DeepEqual( + t, + parentMsgs, + msgs, + cmpopts.SortSlices(func(a, b *Tour) bool { + return a.Name < b.Name + }), + protocmp.Transform(), + ) + }) + + } + { + const resourcesCount = 101 + parent := fx.nextParent(t, true) + parentMsgs := make([]*Tour, resourcesCount) + for i := 0; i < resourcesCount; i++ { + parentMsgs[i] = fx.create(t, parent) } - assert.DeepEqual( - t, - parentMsgs, - msgs, - cmpopts.SortSlices(func(a, b *Tour) bool { - return a.Name < b.Name - }), - protocmp.Transform(), - ) - }) + // Listing resource with page size zero should eventually return all resources. + t.Run("page size zero", func(t *testing.T) { + fx.maybeSkip(t) + msgs := make([]*Tour, 0, resourcesCount) + var nextPageToken string + for { + page, err := fx.Service().ListTours(fx.Context(), &ListToursRequest{ + Parent: parent, + PageSize: 0, + PageToken: nextPageToken, + }) + assert.NilError(t, err) + msgs = append(msgs, page.Tours...) + nextPageToken = page.NextPageToken + if nextPageToken == "" { + break + } + } + assert.DeepEqual( + t, + parentMsgs, + msgs, + cmpopts.SortSlices(func(a, b *Tour) bool { + return a.Name < b.Name + }), + protocmp.Transform(), + ) + }) + + } } func (fx *BookingServiceTourTestSuiteConfig) testSearch(t *testing.T) { @@ -623,85 +665,87 @@ func (fx *BookingServiceTourTestSuiteConfig) testSearch(t *testing.T) { assert.Equal(t, codes.InvalidArgument, status.Code(err), err) }) - const resourcesCount = 15 - parent := fx.nextParent(t, true) - parentMsgs := make([]*Tour, resourcesCount) - for i := 0; i < resourcesCount; i++ { - parentMsgs[i] = fx.create(t, parent) - } - - // If parent is provided the method must only return resources - // under that parent. - t.Run("isolation", func(t *testing.T) { - fx.maybeSkip(t) - response, err := fx.Service().SearchTours(fx.Context(), &SearchToursRequest{ - Parent: parent, - PageSize: 999, - }) - assert.NilError(t, err) - assert.DeepEqual( - t, - parentMsgs, - response.Tours, - cmpopts.SortSlices(func(a, b *Tour) bool { - return a.Name < b.Name - }), - protocmp.Transform(), - ) - }) - - // If there are no more resources, next_page_token should not be set. - t.Run("last page", func(t *testing.T) { - fx.maybeSkip(t) - response, err := fx.Service().SearchTours(fx.Context(), &SearchToursRequest{ - Parent: parent, - PageSize: resourcesCount, - }) - assert.NilError(t, err) - assert.Equal(t, "", response.NextPageToken) - }) + { + const resourcesCount = 15 + parent := fx.nextParent(t, true) + parentMsgs := make([]*Tour, resourcesCount) + for i := 0; i < resourcesCount; i++ { + parentMsgs[i] = fx.create(t, parent) + } - // If there are more resources, next_page_token should be set. - t.Run("more pages", func(t *testing.T) { - fx.maybeSkip(t) - response, err := fx.Service().SearchTours(fx.Context(), &SearchToursRequest{ - Parent: parent, - PageSize: resourcesCount - 1, + // If parent is provided the method must only return resources + // under that parent. + t.Run("isolation", func(t *testing.T) { + fx.maybeSkip(t) + response, err := fx.Service().SearchTours(fx.Context(), &SearchToursRequest{ + Parent: parent, + PageSize: 999, + }) + assert.NilError(t, err) + assert.DeepEqual( + t, + parentMsgs, + response.Tours, + cmpopts.SortSlices(func(a, b *Tour) bool { + return a.Name < b.Name + }), + protocmp.Transform(), + ) + }) + + // If there are no more resources, next_page_token should not be set. + t.Run("last page", func(t *testing.T) { + fx.maybeSkip(t) + response, err := fx.Service().SearchTours(fx.Context(), &SearchToursRequest{ + Parent: parent, + PageSize: resourcesCount, + }) + assert.NilError(t, err) + assert.Equal(t, "", response.NextPageToken) }) - assert.NilError(t, err) - assert.Check(t, response.NextPageToken != "") - }) - // Searching resource one by one should eventually return all resources. - t.Run("one by one", func(t *testing.T) { - fx.maybeSkip(t) - msgs := make([]*Tour, 0, resourcesCount) - var nextPageToken string - for { + // If there are more resources, next_page_token should be set. + t.Run("more pages", func(t *testing.T) { + fx.maybeSkip(t) response, err := fx.Service().SearchTours(fx.Context(), &SearchToursRequest{ - Parent: parent, - PageSize: 1, - PageToken: nextPageToken, + Parent: parent, + PageSize: resourcesCount - 1, }) assert.NilError(t, err) - assert.Equal(t, 1, len(response.Tours)) - msgs = append(msgs, response.Tours...) - nextPageToken = response.NextPageToken - if nextPageToken == "" { - break + assert.Check(t, response.NextPageToken != "") + }) + + // Searching resource one by one should eventually return all resources. + t.Run("one by one", func(t *testing.T) { + fx.maybeSkip(t) + msgs := make([]*Tour, 0, resourcesCount) + var nextPageToken string + for { + response, err := fx.Service().SearchTours(fx.Context(), &SearchToursRequest{ + Parent: parent, + PageSize: 1, + PageToken: nextPageToken, + }) + assert.NilError(t, err) + assert.Equal(t, 1, len(response.Tours)) + msgs = append(msgs, response.Tours...) + nextPageToken = response.NextPageToken + if nextPageToken == "" { + break + } } - } - assert.DeepEqual( - t, - parentMsgs, - msgs, - cmpopts.SortSlices(func(a, b *Tour) bool { - return a.Name < b.Name - }), - protocmp.Transform(), - ) - }) + assert.DeepEqual( + t, + parentMsgs, + msgs, + cmpopts.SortSlices(func(a, b *Tour) bool { + return a.Name < b.Name + }), + protocmp.Transform(), + ) + }) + } } func (fx *BookingServiceTourTestSuiteConfig) nextParent(t *testing.T, pristine bool) string { diff --git a/proto/gen/go/einride/saga/extend/book/v1beta1/shipment_service_aiptest.pb.go b/proto/gen/go/einride/saga/extend/book/v1beta1/shipment_service_aiptest.pb.go index a807b07..cd618ea 100644 --- a/proto/gen/go/einride/saga/extend/book/v1beta1/shipment_service_aiptest.pb.go +++ b/proto/gen/go/einride/saga/extend/book/v1beta1/shipment_service_aiptest.pb.go @@ -459,210 +459,212 @@ func (fx *ShipmentServiceShipmentTestSuiteConfig) testUpdate(t *testing.T) { assert.DeepEqual(t, originalCreateTime, updated.CreateTime, protocmp.Transform()) }) - parent := fx.nextParent(t, false) - created := fx.create(t, parent) - // Method should fail with NotFound if the resource does not exist. - t.Run("not found", func(t *testing.T) { - fx.maybeSkip(t) - msg := fx.Update(parent) - msg.Name = created.Name + "notfound" - _, err := fx.Service().UpdateShipment(fx.Context(), &UpdateShipmentRequest{ - Shipment: msg, - }) - assert.Equal(t, codes.NotFound, status.Code(err), err) - }) - - // The method should fail with InvalidArgument if the update_mask is invalid. - t.Run("invalid update mask", func(t *testing.T) { - fx.maybeSkip(t) - _, err := fx.Service().UpdateShipment(fx.Context(), &UpdateShipmentRequest{ - Shipment: created, - UpdateMask: &fieldmaskpb.FieldMask{ - Paths: []string{ - "invalid_field_xyz", - }, - }, - }) - assert.Equal(t, codes.InvalidArgument, status.Code(err), err) - }) - - // Method should fail with InvalidArgument if any required field is missing - // when called with '*' update_mask. - t.Run("required fields", func(t *testing.T) { - fx.maybeSkip(t) - t.Run(".sender", func(t *testing.T) { + { + parent := fx.nextParent(t, false) + created := fx.create(t, parent) + // Method should fail with NotFound if the resource does not exist. + t.Run("not found", func(t *testing.T) { fx.maybeSkip(t) - msg := proto.Clone(created).(*Shipment) - container := msg - if container == nil { - t.Skip("not reachable") - } - fd := container.ProtoReflect().Descriptor().Fields().ByName("sender") - container.ProtoReflect().Clear(fd) + msg := fx.Update(parent) + msg.Name = created.Name + "notfound" _, err := fx.Service().UpdateShipment(fx.Context(), &UpdateShipmentRequest{ Shipment: msg, - UpdateMask: &fieldmaskpb.FieldMask{ - Paths: []string{ - "*", - }, - }, }) - assert.Equal(t, codes.InvalidArgument, status.Code(err), err) + assert.Equal(t, codes.NotFound, status.Code(err), err) }) - t.Run(".pickup_address.recipient", func(t *testing.T) { + + // The method should fail with InvalidArgument if the update_mask is invalid. + t.Run("invalid update mask", func(t *testing.T) { fx.maybeSkip(t) - msg := proto.Clone(created).(*Shipment) - container := msg.GetPickupAddress() - if container == nil { - t.Skip("not reachable") - } - fd := container.ProtoReflect().Descriptor().Fields().ByName("recipient") - container.ProtoReflect().Clear(fd) _, err := fx.Service().UpdateShipment(fx.Context(), &UpdateShipmentRequest{ - Shipment: msg, + Shipment: created, UpdateMask: &fieldmaskpb.FieldMask{ Paths: []string{ - "*", + "invalid_field_xyz", }, }, }) assert.Equal(t, codes.InvalidArgument, status.Code(err), err) }) - t.Run(".pickup_address.line1", func(t *testing.T) { + + // Method should fail with InvalidArgument if any required field is missing + // when called with '*' update_mask. + t.Run("required fields", func(t *testing.T) { fx.maybeSkip(t) - msg := proto.Clone(created).(*Shipment) - container := msg.GetPickupAddress() - if container == nil { - t.Skip("not reachable") - } - fd := container.ProtoReflect().Descriptor().Fields().ByName("line1") - container.ProtoReflect().Clear(fd) - _, err := fx.Service().UpdateShipment(fx.Context(), &UpdateShipmentRequest{ - Shipment: msg, - UpdateMask: &fieldmaskpb.FieldMask{ - Paths: []string{ - "*", + t.Run(".sender", func(t *testing.T) { + fx.maybeSkip(t) + msg := proto.Clone(created).(*Shipment) + container := msg + if container == nil { + t.Skip("not reachable") + } + fd := container.ProtoReflect().Descriptor().Fields().ByName("sender") + container.ProtoReflect().Clear(fd) + _, err := fx.Service().UpdateShipment(fx.Context(), &UpdateShipmentRequest{ + Shipment: msg, + UpdateMask: &fieldmaskpb.FieldMask{ + Paths: []string{ + "*", + }, }, - }, + }) + assert.Equal(t, codes.InvalidArgument, status.Code(err), err) }) - assert.Equal(t, codes.InvalidArgument, status.Code(err), err) - }) - t.Run(".pickup_address.postal_code", func(t *testing.T) { - fx.maybeSkip(t) - msg := proto.Clone(created).(*Shipment) - container := msg.GetPickupAddress() - if container == nil { - t.Skip("not reachable") - } - fd := container.ProtoReflect().Descriptor().Fields().ByName("postal_code") - container.ProtoReflect().Clear(fd) - _, err := fx.Service().UpdateShipment(fx.Context(), &UpdateShipmentRequest{ - Shipment: msg, - UpdateMask: &fieldmaskpb.FieldMask{ - Paths: []string{ - "*", + t.Run(".pickup_address.recipient", func(t *testing.T) { + fx.maybeSkip(t) + msg := proto.Clone(created).(*Shipment) + container := msg.GetPickupAddress() + if container == nil { + t.Skip("not reachable") + } + fd := container.ProtoReflect().Descriptor().Fields().ByName("recipient") + container.ProtoReflect().Clear(fd) + _, err := fx.Service().UpdateShipment(fx.Context(), &UpdateShipmentRequest{ + Shipment: msg, + UpdateMask: &fieldmaskpb.FieldMask{ + Paths: []string{ + "*", + }, }, - }, + }) + assert.Equal(t, codes.InvalidArgument, status.Code(err), err) }) - assert.Equal(t, codes.InvalidArgument, status.Code(err), err) - }) - t.Run(".pickup_address.city", func(t *testing.T) { - fx.maybeSkip(t) - msg := proto.Clone(created).(*Shipment) - container := msg.GetPickupAddress() - if container == nil { - t.Skip("not reachable") - } - fd := container.ProtoReflect().Descriptor().Fields().ByName("city") - container.ProtoReflect().Clear(fd) - _, err := fx.Service().UpdateShipment(fx.Context(), &UpdateShipmentRequest{ - Shipment: msg, - UpdateMask: &fieldmaskpb.FieldMask{ - Paths: []string{ - "*", + t.Run(".pickup_address.line1", func(t *testing.T) { + fx.maybeSkip(t) + msg := proto.Clone(created).(*Shipment) + container := msg.GetPickupAddress() + if container == nil { + t.Skip("not reachable") + } + fd := container.ProtoReflect().Descriptor().Fields().ByName("line1") + container.ProtoReflect().Clear(fd) + _, err := fx.Service().UpdateShipment(fx.Context(), &UpdateShipmentRequest{ + Shipment: msg, + UpdateMask: &fieldmaskpb.FieldMask{ + Paths: []string{ + "*", + }, }, - }, + }) + assert.Equal(t, codes.InvalidArgument, status.Code(err), err) }) - assert.Equal(t, codes.InvalidArgument, status.Code(err), err) - }) - t.Run(".pickup_address.region_code", func(t *testing.T) { - fx.maybeSkip(t) - msg := proto.Clone(created).(*Shipment) - container := msg.GetPickupAddress() - if container == nil { - t.Skip("not reachable") - } - fd := container.ProtoReflect().Descriptor().Fields().ByName("region_code") - container.ProtoReflect().Clear(fd) - _, err := fx.Service().UpdateShipment(fx.Context(), &UpdateShipmentRequest{ - Shipment: msg, - UpdateMask: &fieldmaskpb.FieldMask{ - Paths: []string{ - "*", + t.Run(".pickup_address.postal_code", func(t *testing.T) { + fx.maybeSkip(t) + msg := proto.Clone(created).(*Shipment) + container := msg.GetPickupAddress() + if container == nil { + t.Skip("not reachable") + } + fd := container.ProtoReflect().Descriptor().Fields().ByName("postal_code") + container.ProtoReflect().Clear(fd) + _, err := fx.Service().UpdateShipment(fx.Context(), &UpdateShipmentRequest{ + Shipment: msg, + UpdateMask: &fieldmaskpb.FieldMask{ + Paths: []string{ + "*", + }, }, - }, + }) + assert.Equal(t, codes.InvalidArgument, status.Code(err), err) }) - assert.Equal(t, codes.InvalidArgument, status.Code(err), err) - }) - t.Run(".delivery_address", func(t *testing.T) { - fx.maybeSkip(t) - msg := proto.Clone(created).(*Shipment) - container := msg - if container == nil { - t.Skip("not reachable") - } - fd := container.ProtoReflect().Descriptor().Fields().ByName("delivery_address") - container.ProtoReflect().Clear(fd) - _, err := fx.Service().UpdateShipment(fx.Context(), &UpdateShipmentRequest{ - Shipment: msg, - UpdateMask: &fieldmaskpb.FieldMask{ - Paths: []string{ - "*", + t.Run(".pickup_address.city", func(t *testing.T) { + fx.maybeSkip(t) + msg := proto.Clone(created).(*Shipment) + container := msg.GetPickupAddress() + if container == nil { + t.Skip("not reachable") + } + fd := container.ProtoReflect().Descriptor().Fields().ByName("city") + container.ProtoReflect().Clear(fd) + _, err := fx.Service().UpdateShipment(fx.Context(), &UpdateShipmentRequest{ + Shipment: msg, + UpdateMask: &fieldmaskpb.FieldMask{ + Paths: []string{ + "*", + }, }, - }, + }) + assert.Equal(t, codes.InvalidArgument, status.Code(err), err) }) - assert.Equal(t, codes.InvalidArgument, status.Code(err), err) - }) - t.Run(".units", func(t *testing.T) { - fx.maybeSkip(t) - msg := proto.Clone(created).(*Shipment) - container := msg - if container == nil { - t.Skip("not reachable") - } - fd := container.ProtoReflect().Descriptor().Fields().ByName("units") - container.ProtoReflect().Clear(fd) - _, err := fx.Service().UpdateShipment(fx.Context(), &UpdateShipmentRequest{ - Shipment: msg, - UpdateMask: &fieldmaskpb.FieldMask{ - Paths: []string{ - "*", + t.Run(".pickup_address.region_code", func(t *testing.T) { + fx.maybeSkip(t) + msg := proto.Clone(created).(*Shipment) + container := msg.GetPickupAddress() + if container == nil { + t.Skip("not reachable") + } + fd := container.ProtoReflect().Descriptor().Fields().ByName("region_code") + container.ProtoReflect().Clear(fd) + _, err := fx.Service().UpdateShipment(fx.Context(), &UpdateShipmentRequest{ + Shipment: msg, + UpdateMask: &fieldmaskpb.FieldMask{ + Paths: []string{ + "*", + }, }, - }, + }) + assert.Equal(t, codes.InvalidArgument, status.Code(err), err) }) - assert.Equal(t, codes.InvalidArgument, status.Code(err), err) - }) - t.Run(".vehicle.reference_id", func(t *testing.T) { - fx.maybeSkip(t) - msg := proto.Clone(created).(*Shipment) - container := msg.GetVehicle() - if container == nil { - t.Skip("not reachable") - } - fd := container.ProtoReflect().Descriptor().Fields().ByName("reference_id") - container.ProtoReflect().Clear(fd) - _, err := fx.Service().UpdateShipment(fx.Context(), &UpdateShipmentRequest{ - Shipment: msg, - UpdateMask: &fieldmaskpb.FieldMask{ - Paths: []string{ - "*", + t.Run(".delivery_address", func(t *testing.T) { + fx.maybeSkip(t) + msg := proto.Clone(created).(*Shipment) + container := msg + if container == nil { + t.Skip("not reachable") + } + fd := container.ProtoReflect().Descriptor().Fields().ByName("delivery_address") + container.ProtoReflect().Clear(fd) + _, err := fx.Service().UpdateShipment(fx.Context(), &UpdateShipmentRequest{ + Shipment: msg, + UpdateMask: &fieldmaskpb.FieldMask{ + Paths: []string{ + "*", + }, }, - }, + }) + assert.Equal(t, codes.InvalidArgument, status.Code(err), err) + }) + t.Run(".units", func(t *testing.T) { + fx.maybeSkip(t) + msg := proto.Clone(created).(*Shipment) + container := msg + if container == nil { + t.Skip("not reachable") + } + fd := container.ProtoReflect().Descriptor().Fields().ByName("units") + container.ProtoReflect().Clear(fd) + _, err := fx.Service().UpdateShipment(fx.Context(), &UpdateShipmentRequest{ + Shipment: msg, + UpdateMask: &fieldmaskpb.FieldMask{ + Paths: []string{ + "*", + }, + }, + }) + assert.Equal(t, codes.InvalidArgument, status.Code(err), err) + }) + t.Run(".vehicle.reference_id", func(t *testing.T) { + fx.maybeSkip(t) + msg := proto.Clone(created).(*Shipment) + container := msg.GetVehicle() + if container == nil { + t.Skip("not reachable") + } + fd := container.ProtoReflect().Descriptor().Fields().ByName("reference_id") + container.ProtoReflect().Clear(fd) + _, err := fx.Service().UpdateShipment(fx.Context(), &UpdateShipmentRequest{ + Shipment: msg, + UpdateMask: &fieldmaskpb.FieldMask{ + Paths: []string{ + "*", + }, + }, + }) + assert.Equal(t, codes.InvalidArgument, status.Code(err), err) }) - assert.Equal(t, codes.InvalidArgument, status.Code(err), err) }) - }) + } } func (fx *ShipmentServiceShipmentTestSuiteConfig) testList(t *testing.T) { @@ -698,85 +700,125 @@ func (fx *ShipmentServiceShipmentTestSuiteConfig) testList(t *testing.T) { assert.Equal(t, codes.InvalidArgument, status.Code(err), err) }) - const resourcesCount = 15 - parent := fx.nextParent(t, true) - parentMsgs := make([]*Shipment, resourcesCount) - for i := 0; i < resourcesCount; i++ { - parentMsgs[i] = fx.create(t, parent) - } - - // If parent is provided the method must only return resources - // under that parent. - t.Run("isolation", func(t *testing.T) { - fx.maybeSkip(t) - response, err := fx.Service().ListShipments(fx.Context(), &ListShipmentsRequest{ - Parent: parent, - PageSize: 999, - }) - assert.NilError(t, err) - assert.DeepEqual( - t, - parentMsgs, - response.Shipments, - cmpopts.SortSlices(func(a, b *Shipment) bool { - return a.Name < b.Name - }), - protocmp.Transform(), - ) - }) - - // If there are no more resources, next_page_token should not be set. - t.Run("last page", func(t *testing.T) { - fx.maybeSkip(t) - response, err := fx.Service().ListShipments(fx.Context(), &ListShipmentsRequest{ - Parent: parent, - PageSize: resourcesCount, - }) - assert.NilError(t, err) - assert.Equal(t, "", response.NextPageToken) - }) + { + const resourcesCount = 15 + parent := fx.nextParent(t, true) + parentMsgs := make([]*Shipment, resourcesCount) + for i := 0; i < resourcesCount; i++ { + parentMsgs[i] = fx.create(t, parent) + } - // If there are more resources, next_page_token should be set. - t.Run("more pages", func(t *testing.T) { - fx.maybeSkip(t) - response, err := fx.Service().ListShipments(fx.Context(), &ListShipmentsRequest{ - Parent: parent, - PageSize: resourcesCount - 1, + // If parent is provided the method must only return resources + // under that parent. + t.Run("isolation", func(t *testing.T) { + fx.maybeSkip(t) + response, err := fx.Service().ListShipments(fx.Context(), &ListShipmentsRequest{ + Parent: parent, + PageSize: 999, + }) + assert.NilError(t, err) + assert.DeepEqual( + t, + parentMsgs, + response.Shipments, + cmpopts.SortSlices(func(a, b *Shipment) bool { + return a.Name < b.Name + }), + protocmp.Transform(), + ) + }) + + // If there are no more resources, next_page_token should not be set. + t.Run("last page", func(t *testing.T) { + fx.maybeSkip(t) + response, err := fx.Service().ListShipments(fx.Context(), &ListShipmentsRequest{ + Parent: parent, + PageSize: resourcesCount, + }) + assert.NilError(t, err) + assert.Equal(t, "", response.NextPageToken) }) - assert.NilError(t, err) - assert.Check(t, response.NextPageToken != "") - }) - // Listing resource one by one should eventually return all resources. - t.Run("one by one", func(t *testing.T) { - fx.maybeSkip(t) - msgs := make([]*Shipment, 0, resourcesCount) - var nextPageToken string - for { + // If there are more resources, next_page_token should be set. + t.Run("more pages", func(t *testing.T) { + fx.maybeSkip(t) response, err := fx.Service().ListShipments(fx.Context(), &ListShipmentsRequest{ - Parent: parent, - PageSize: 1, - PageToken: nextPageToken, + Parent: parent, + PageSize: resourcesCount - 1, }) assert.NilError(t, err) - assert.Equal(t, 1, len(response.Shipments)) - msgs = append(msgs, response.Shipments...) - nextPageToken = response.NextPageToken - if nextPageToken == "" { - break + assert.Check(t, response.NextPageToken != "") + }) + + // Listing resource one by one should eventually return all resources. + t.Run("one by one", func(t *testing.T) { + fx.maybeSkip(t) + msgs := make([]*Shipment, 0, resourcesCount) + var nextPageToken string + for { + response, err := fx.Service().ListShipments(fx.Context(), &ListShipmentsRequest{ + Parent: parent, + PageSize: 1, + PageToken: nextPageToken, + }) + assert.NilError(t, err) + assert.Equal(t, 1, len(response.Shipments)) + msgs = append(msgs, response.Shipments...) + nextPageToken = response.NextPageToken + if nextPageToken == "" { + break + } } + assert.DeepEqual( + t, + parentMsgs, + msgs, + cmpopts.SortSlices(func(a, b *Shipment) bool { + return a.Name < b.Name + }), + protocmp.Transform(), + ) + }) + + } + { + const resourcesCount = 101 + parent := fx.nextParent(t, true) + parentMsgs := make([]*Shipment, resourcesCount) + for i := 0; i < resourcesCount; i++ { + parentMsgs[i] = fx.create(t, parent) } - assert.DeepEqual( - t, - parentMsgs, - msgs, - cmpopts.SortSlices(func(a, b *Shipment) bool { - return a.Name < b.Name - }), - protocmp.Transform(), - ) - }) + // Listing resource with page size zero should eventually return all resources. + t.Run("page size zero", func(t *testing.T) { + fx.maybeSkip(t) + msgs := make([]*Shipment, 0, resourcesCount) + var nextPageToken string + for { + page, err := fx.Service().ListShipments(fx.Context(), &ListShipmentsRequest{ + Parent: parent, + PageSize: 0, + PageToken: nextPageToken, + }) + assert.NilError(t, err) + msgs = append(msgs, page.Shipments...) + nextPageToken = page.NextPageToken + if nextPageToken == "" { + break + } + } + assert.DeepEqual( + t, + parentMsgs, + msgs, + cmpopts.SortSlices(func(a, b *Shipment) bool { + return a.Name < b.Name + }), + protocmp.Transform(), + ) + }) + + } } func (fx *ShipmentServiceShipmentTestSuiteConfig) nextParent(t *testing.T, pristine bool) string {