From 4fc552164383e63dbe20d576b42e230ac9c78c61 Mon Sep 17 00:00:00 2001 From: tmdiep Date: Wed, 4 Nov 2020 03:43:37 -0500 Subject: [PATCH] Move ValidateZone|Region to internal/wire --- pubsublite/admin.go | 2 +- .../internal/wire/message_router_test.go | 13 +--- pubsublite/internal/wire/resources.go | 27 +++++++ pubsublite/internal/wire/resources_test.go | 78 +++++++++++++++++++ pubsublite/types.go | 44 +++-------- pubsublite/types_test.go | 62 --------------- 6 files changed, 122 insertions(+), 104 deletions(-) create mode 100644 pubsublite/internal/wire/resources_test.go diff --git a/pubsublite/admin.go b/pubsublite/admin.go index 921d719b96f..0b7fd836445 100644 --- a/pubsublite/admin.go +++ b/pubsublite/admin.go @@ -35,7 +35,7 @@ type AdminClient struct { // See https://cloud.google.com/pubsub/lite/docs/locations for the list of // regions and zones where Cloud Pub/Sub Lite is available. func NewAdminClient(ctx context.Context, region string, opts ...option.ClientOption) (*AdminClient, error) { - if err := validateRegion(region); err != nil { + if err := wire.ValidateRegion(region); err != nil { return nil, err } admin, err := wire.NewAdminClient(ctx, region, opts...) diff --git a/pubsublite/internal/wire/message_router_test.go b/pubsublite/internal/wire/message_router_test.go index a72ce4a5f19..0f847074afa 100644 --- a/pubsublite/internal/wire/message_router_test.go +++ b/pubsublite/internal/wire/message_router_test.go @@ -17,14 +17,9 @@ import ( "fmt" "math/rand" "testing" -) - -type fakeSource struct { - ret int64 -} -func (f *fakeSource) Int63() int64 { return f.ret } -func (f *fakeSource) Seed(seed int64) {} + "cloud.google.com/go/pubsublite/internal/test" +) type fakeMsgRouter struct { multiplier int @@ -42,7 +37,7 @@ func (f *fakeMsgRouter) Route(orderingKey []byte) int { func TestRoundRobinMsgRouter(t *testing.T) { // Using the same msgRouter for each test run ensures that it reinitializes // when the partition count changes. - source := &fakeSource{} + source := &test.FakeSource{} msgRouter := &roundRobinMsgRouter{rng: rand.New(source)} for _, tc := range []struct { @@ -62,7 +57,7 @@ func TestRoundRobinMsgRouter(t *testing.T) { }, } { t.Run(fmt.Sprintf("partitionCount=%d", tc.partitionCount), func(t *testing.T) { - source.ret = tc.source + source.Ret = tc.source msgRouter.SetPartitionCount(tc.partitionCount) for i, want := range tc.want { got := msgRouter.Route([]byte("IGNORED")) diff --git a/pubsublite/internal/wire/resources.go b/pubsublite/internal/wire/resources.go index d8cab3048b1..b31b4dd0ff6 100644 --- a/pubsublite/internal/wire/resources.go +++ b/pubsublite/internal/wire/resources.go @@ -13,6 +13,33 @@ package wire +import ( + "fmt" + "strings" +) + +// ValidateZone verifies that the `input` string has the format of a valid +// Google Cloud zone. An example zone is "europe-west1-b". +// See https://cloud.google.com/compute/docs/regions-zones for more information. +func ValidateZone(input string) error { + parts := strings.Split(input, "-") + if len(parts) != 3 { + return fmt.Errorf("pubsublite: invalid zone %q", input) + } + return nil +} + +// ValidateRegion verifies that the `input` string has the format of a valid +// Google Cloud region. An example region is "europe-west1". +// See https://cloud.google.com/compute/docs/regions-zones for more information. +func ValidateRegion(input string) error { + parts := strings.Split(input, "-") + if len(parts) != 2 { + return fmt.Errorf("pubsublite: invalid region %q", input) + } + return nil +} + type topicPartition struct { Path string Partition int diff --git a/pubsublite/internal/wire/resources_test.go b/pubsublite/internal/wire/resources_test.go new file mode 100644 index 00000000000..8191234a191 --- /dev/null +++ b/pubsublite/internal/wire/resources_test.go @@ -0,0 +1,78 @@ +// Copyright 2020 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and + +package wire + +import "testing" + +func TestValidateZone(t *testing.T) { + for _, tc := range []struct { + desc string + input string + wantErr bool + }{ + { + desc: "valid", + input: "us-central1-a", + wantErr: false, + }, + { + desc: "invalid: insufficient dashes", + input: "us-central1", + wantErr: true, + }, + { + desc: "invalid: excess dashes", + input: "us-central1-a-b", + wantErr: true, + }, + } { + t.Run(tc.desc, func(t *testing.T) { + err := ValidateZone(tc.input) + if (err != nil) != tc.wantErr { + t.Errorf("ValidateZone(%q) = %v, want err=%v", tc.input, err, tc.wantErr) + } + }) + } +} + +func TestValidateRegion(t *testing.T) { + for _, tc := range []struct { + desc string + input string + wantErr bool + }{ + { + desc: "valid", + input: "europe-west1", + wantErr: false, + }, + { + desc: "invalid: insufficient dashes", + input: "europewest1", + wantErr: true, + }, + { + desc: "invalid: excess dashes", + input: "europe-west1-b", + wantErr: true, + }, + } { + t.Run(tc.desc, func(t *testing.T) { + err := ValidateRegion(tc.input) + if (err != nil) != tc.wantErr { + t.Errorf("ValidateRegion(%q) = %v, want err=%v", tc.input, err, tc.wantErr) + } + }) + } +} diff --git a/pubsublite/types.go b/pubsublite/types.go index 40104d2d3c7..dfb2b56438d 100644 --- a/pubsublite/types.go +++ b/pubsublite/types.go @@ -17,6 +17,8 @@ import ( "fmt" "regexp" "strings" + + "cloud.google.com/go/pubsublite/internal/wire" ) // LocationPath stores a path consisting of a project and zone. @@ -27,7 +29,7 @@ type LocationPath struct { // A Google Cloud zone, for example "us-central1-a". // See https://cloud.google.com/pubsub/lite/docs/locations for the list of - // zones where Google Pub/Sub Lite is available. + // zones where Cloud Pub/Sub Lite is available. Zone string } @@ -35,7 +37,7 @@ func (l LocationPath) String() string { return fmt.Sprintf("projects/%s/locations/%s", l.Project, l.Zone) } -// TopicPath stores the full path of a Google Pub/Sub Lite topic. +// TopicPath stores the full path of a Cloud Pub/Sub Lite topic. // See https://cloud.google.com/pubsub/lite/docs/topics for more information. type TopicPath struct { // A Google Cloud project. The project ID (e.g. "my-project") or the project @@ -44,10 +46,10 @@ type TopicPath struct { // A Google Cloud zone, for example "us-central1-a". // See https://cloud.google.com/pubsub/lite/docs/locations for the list of - // zones where Google Pub/Sub Lite is available. + // zones where Cloud Pub/Sub Lite is available. Zone string - // The ID of the Google Pub/Sub Lite topic, for example "my-topic-name". + // The ID of the Cloud Pub/Sub Lite topic, for example "my-topic-name". // See https://cloud.google.com/pubsub/docs/admin#resource_names for more // information. TopicID string @@ -63,7 +65,7 @@ func (t TopicPath) location() LocationPath { var topicPathRE = regexp.MustCompile(`^projects/([^/]+)/locations/([^/]+)/topics/([^/]+)$`) -// parseTopicPath parses the full path of a Google Pub/Sub Lite topic, which +// parseTopicPath parses the full path of a Cloud Pub/Sub Lite topic, which // should have the format: `projects/{project}/locations/{zone}/topics/{id}`. func parseTopicPath(input string) (TopicPath, error) { parts := topicPathRE.FindStringSubmatch(input) @@ -73,7 +75,7 @@ func parseTopicPath(input string) (TopicPath, error) { return TopicPath{Project: parts[1], Zone: parts[2], TopicID: parts[3]}, nil } -// SubscriptionPath stores the full path of a Google Pub/Sub Lite subscription. +// SubscriptionPath stores the full path of a Cloud Pub/Sub Lite subscription. // See https://cloud.google.com/pubsub/lite/docs/subscriptions for more // information. type SubscriptionPath struct { @@ -83,10 +85,10 @@ type SubscriptionPath struct { // A Google Cloud zone. An example zone is "us-central1-a". // See https://cloud.google.com/pubsub/lite/docs/locations for the list of - // zones where Google Pub/Sub Lite is available. + // zones where Cloud Pub/Sub Lite is available. Zone string - // The ID of the Google Pub/Sub Lite subscription, for example + // The ID of the Cloud Pub/Sub Lite subscription, for example // "my-subscription-name". // See https://cloud.google.com/pubsub/docs/admin#resource_names for more // information. @@ -103,7 +105,7 @@ func (s SubscriptionPath) location() LocationPath { var subsPathRE = regexp.MustCompile(`^projects/([^/]+)/locations/([^/]+)/subscriptions/([^/]+)$`) -// parseSubscriptionPath parses the full path of a Google Pub/Sub Lite +// parseSubscriptionPath parses the full path of a Cloud Pub/Sub Lite // subscription, which should have the format: // `projects/{project}/locations/{zone}/subscriptions/{id}`. func parseSubscriptionPath(input string) (SubscriptionPath, error) { @@ -114,31 +116,9 @@ func parseSubscriptionPath(input string) (SubscriptionPath, error) { return SubscriptionPath{Project: parts[1], Zone: parts[2], SubscriptionID: parts[3]}, nil } -// validateZone verifies that the `input` string has the format of a valid -// Google Cloud zone. An example zone is "europe-west1-b". -// See https://cloud.google.com/compute/docs/regions-zones for more information. -func validateZone(input string) error { - parts := strings.Split(input, "-") - if len(parts) != 3 { - return fmt.Errorf("pubsublite: invalid zone %q", input) - } - return nil -} - -// validateRegion verifies that the `input` string has the format of a valid -// Google Cloud region. An example region is "europe-west1". -// See https://cloud.google.com/compute/docs/regions-zones for more information. -func validateRegion(input string) error { - parts := strings.Split(input, "-") - if len(parts) != 2 { - return fmt.Errorf("pubsublite: invalid region %q", input) - } - return nil -} - // ZoneToRegion returns the region that the given zone is in. func ZoneToRegion(zone string) (string, error) { - if err := validateZone(zone); err != nil { + if err := wire.ValidateZone(zone); err != nil { return "", err } return zone[0:strings.LastIndex(zone, "-")], nil diff --git a/pubsublite/types_test.go b/pubsublite/types_test.go index 18f02b96ac6..fcd89af79c4 100644 --- a/pubsublite/types_test.go +++ b/pubsublite/types_test.go @@ -129,68 +129,6 @@ func TestParseSubscriptionPath(t *testing.T) { } } -func TestValidateZone(t *testing.T) { - for _, tc := range []struct { - desc string - input string - wantErr bool - }{ - { - desc: "valid", - input: "us-central1-a", - wantErr: false, - }, - { - desc: "invalid: insufficient dashes", - input: "us-central1", - wantErr: true, - }, - { - desc: "invalid: excess dashes", - input: "us-central1-a-b", - wantErr: true, - }, - } { - t.Run(tc.desc, func(t *testing.T) { - err := validateZone(tc.input) - if (err != nil) != tc.wantErr { - t.Errorf("validateZone(%q) = %v, want err=%v", tc.input, err, tc.wantErr) - } - }) - } -} - -func TestValidateRegion(t *testing.T) { - for _, tc := range []struct { - desc string - input string - wantErr bool - }{ - { - desc: "valid", - input: "europe-west1", - wantErr: false, - }, - { - desc: "invalid: insufficient dashes", - input: "europewest1", - wantErr: true, - }, - { - desc: "invalid: excess dashes", - input: "europe-west1-b", - wantErr: true, - }, - } { - t.Run(tc.desc, func(t *testing.T) { - err := validateRegion(tc.input) - if (err != nil) != tc.wantErr { - t.Errorf("validateRegion(%q) = %v, want err=%v", tc.input, err, tc.wantErr) - } - }) - } -} - func TestZoneToRegion(t *testing.T) { for _, tc := range []struct { desc string