create lib/stringslice package (#7934)

This commit is contained in:
R.B. Boyer 2020-05-27 11:47:32 -05:00 committed by GitHub
parent 12f6d327f8
commit 77f2e54618
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
13 changed files with 70 additions and 70 deletions

View File

@ -17,7 +17,7 @@ import (
"github.com/hashicorp/consul/agent/structs" "github.com/hashicorp/consul/agent/structs"
tokenStore "github.com/hashicorp/consul/agent/token" tokenStore "github.com/hashicorp/consul/agent/token"
"github.com/hashicorp/consul/internal/go-sso/oidcauth/oidcauthtest" "github.com/hashicorp/consul/internal/go-sso/oidcauth/oidcauthtest"
"github.com/hashicorp/consul/lib" "github.com/hashicorp/consul/lib/stringslice"
"github.com/hashicorp/consul/sdk/freeport" "github.com/hashicorp/consul/sdk/freeport"
"github.com/hashicorp/consul/sdk/testutil" "github.com/hashicorp/consul/sdk/testutil"
"github.com/hashicorp/consul/sdk/testutil/retry" "github.com/hashicorp/consul/sdk/testutil/retry"
@ -564,7 +564,7 @@ func TestACLEndpoint_List(t *testing.T) {
if s.ID == anonymousToken || s.ID == "root" { if s.ID == anonymousToken || s.ID == "root" {
continue continue
} }
if !lib.StrContains(ids, s.ID) { if !stringslice.Contains(ids, s.ID) {
t.Fatalf("bad: %v", s) t.Fatalf("bad: %v", s)
} }
if s.Name != "User token" { if s.Name != "User token" {

View File

@ -12,6 +12,7 @@ import (
"github.com/hashicorp/consul/agent/structs" "github.com/hashicorp/consul/agent/structs"
"github.com/hashicorp/consul/api" "github.com/hashicorp/consul/api"
"github.com/hashicorp/consul/lib" "github.com/hashicorp/consul/lib"
"github.com/hashicorp/consul/lib/stringslice"
"github.com/hashicorp/consul/sdk/testutil/retry" "github.com/hashicorp/consul/sdk/testutil/retry"
"github.com/hashicorp/consul/testrpc" "github.com/hashicorp/consul/testrpc"
"github.com/hashicorp/consul/types" "github.com/hashicorp/consul/types"
@ -2440,7 +2441,7 @@ func TestCatalog_NodeServices(t *testing.T) {
t.Fatalf("bad: %v", out) t.Fatalf("bad: %v", out)
} }
services := out.NodeServices.Services services := out.NodeServices.Services
if !lib.StrContains(services["db"].Tags, "primary") || services["db"].Port != 5000 { if !stringslice.Contains(services["db"].Tags, "primary") || services["db"].Port != 5000 {
t.Fatalf("bad: %v", out) t.Fatalf("bad: %v", out)
} }
if len(services["web"].Tags) != 0 || services["web"].Port != 80 { if len(services["web"].Tags) != 0 || services["web"].Port != 80 {

View File

@ -12,7 +12,7 @@ import (
"github.com/hashicorp/consul/agent/consul/state" "github.com/hashicorp/consul/agent/consul/state"
"github.com/hashicorp/consul/agent/structs" "github.com/hashicorp/consul/agent/structs"
"github.com/hashicorp/consul/api" "github.com/hashicorp/consul/api"
"github.com/hashicorp/consul/lib" "github.com/hashicorp/consul/lib/stringslice"
"github.com/hashicorp/consul/sdk/testutil" "github.com/hashicorp/consul/sdk/testutil"
"github.com/hashicorp/go-raftchunking" "github.com/hashicorp/go-raftchunking"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
@ -456,7 +456,7 @@ func TestFSM_SnapshotRestore_OSS(t *testing.T) {
if len(fooSrv.Services) != 2 { if len(fooSrv.Services) != 2 {
t.Fatalf("Bad: %v", fooSrv) t.Fatalf("Bad: %v", fooSrv)
} }
if !lib.StrContains(fooSrv.Services["db"].Tags, "primary") { if !stringslice.Contains(fooSrv.Services["db"].Tags, "primary") {
t.Fatalf("Bad: %v", fooSrv) t.Fatalf("Bad: %v", fooSrv)
} }
if fooSrv.Services["db"].Port != 5000 { if fooSrv.Services["db"].Port != 5000 {

View File

@ -11,7 +11,7 @@ import (
"github.com/hashicorp/consul/agent/structs" "github.com/hashicorp/consul/agent/structs"
"github.com/hashicorp/consul/api" "github.com/hashicorp/consul/api"
"github.com/hashicorp/consul/ipaddr" "github.com/hashicorp/consul/ipaddr"
"github.com/hashicorp/consul/lib" "github.com/hashicorp/consul/lib/stringslice"
"github.com/hashicorp/consul/logging" "github.com/hashicorp/consul/logging"
"github.com/hashicorp/go-hclog" "github.com/hashicorp/go-hclog"
memdb "github.com/hashicorp/go-memdb" memdb "github.com/hashicorp/go-memdb"
@ -190,7 +190,7 @@ func (g *GatewayLocator) listGateways(primary bool) []string {
// *duplicates* (which shouldn't happen) it's not great but it // *duplicates* (which shouldn't happen) it's not great but it
// won't break anything other than biasing our eventual random // won't break anything other than biasing our eventual random
// choice a little bit. // choice a little bit.
addrs = lib.StringSliceMergeSorted(g.primaryGateways, g.PrimaryGatewayFallbackAddresses()) addrs = stringslice.MergeSorted(g.primaryGateways, g.PrimaryGatewayFallbackAddresses())
} }
} else { } else {
addrs = g.localGateways addrs = g.localGateways
@ -207,7 +207,7 @@ func (g *GatewayLocator) RefreshPrimaryGatewayFallbackAddresses(addrs []string)
g.primaryMeshGatewayDiscoveredAddressesLock.Lock() g.primaryMeshGatewayDiscoveredAddressesLock.Lock()
defer g.primaryMeshGatewayDiscoveredAddressesLock.Unlock() defer g.primaryMeshGatewayDiscoveredAddressesLock.Unlock()
if !lib.StringSliceEqual(addrs, g.primaryMeshGatewayDiscoveredAddresses) { if !stringslice.Equal(addrs, g.primaryMeshGatewayDiscoveredAddresses) {
g.primaryMeshGatewayDiscoveredAddresses = addrs g.primaryMeshGatewayDiscoveredAddresses = addrs
g.logger.Info("updated fallback list of primary mesh gateways", "mesh_gateways", addrs) g.logger.Info("updated fallback list of primary mesh gateways", "mesh_gateways", addrs)
} }
@ -363,12 +363,12 @@ func (g *GatewayLocator) updateFromState(results []*structs.FederationState) {
changed := false changed := false
primaryReady := false primaryReady := false
if !lib.StringSliceEqual(g.primaryGateways, primaryAddrs) { if !stringslice.Equal(g.primaryGateways, primaryAddrs) {
g.primaryGateways = primaryAddrs g.primaryGateways = primaryAddrs
primaryReady = len(g.primaryGateways) > 0 primaryReady = len(g.primaryGateways) > 0
changed = true changed = true
} }
if !lib.StringSliceEqual(g.localGateways, localAddrs) { if !stringslice.Equal(g.localGateways, localAddrs) {
g.localGateways = localAddrs g.localGateways = localAddrs
changed = true changed = true
} }

View File

@ -8,6 +8,7 @@ import (
"github.com/hashicorp/consul/agent/structs" "github.com/hashicorp/consul/agent/structs"
"github.com/hashicorp/consul/api" "github.com/hashicorp/consul/api"
"github.com/hashicorp/consul/lib" "github.com/hashicorp/consul/lib"
"github.com/hashicorp/consul/lib/stringslice"
"github.com/hashicorp/consul/sdk/testutil/retry" "github.com/hashicorp/consul/sdk/testutil/retry"
"github.com/hashicorp/consul/testrpc" "github.com/hashicorp/consul/testrpc"
"github.com/hashicorp/consul/types" "github.com/hashicorp/consul/types"
@ -591,10 +592,10 @@ func TestHealth_ServiceNodes(t *testing.T) {
if nodes[1].Node.Node != "foo" { if nodes[1].Node.Node != "foo" {
t.Fatalf("Bad: %v", nodes[1]) t.Fatalf("Bad: %v", nodes[1])
} }
if !lib.StrContains(nodes[0].Service.Tags, "slave") { if !stringslice.Contains(nodes[0].Service.Tags, "slave") {
t.Fatalf("Bad: %v", nodes[0]) t.Fatalf("Bad: %v", nodes[0])
} }
if !lib.StrContains(nodes[1].Service.Tags, "master") { if !stringslice.Contains(nodes[1].Service.Tags, "master") {
t.Fatalf("Bad: %v", nodes[1]) t.Fatalf("Bad: %v", nodes[1])
} }
if nodes[0].Checks[0].Status != api.HealthWarning { if nodes[0].Checks[0].Status != api.HealthWarning {
@ -629,10 +630,10 @@ func TestHealth_ServiceNodes(t *testing.T) {
if nodes[1].Node.Node != "foo" { if nodes[1].Node.Node != "foo" {
t.Fatalf("Bad: %v", nodes[1]) t.Fatalf("Bad: %v", nodes[1])
} }
if !lib.StrContains(nodes[0].Service.Tags, "slave") { if !stringslice.Contains(nodes[0].Service.Tags, "slave") {
t.Fatalf("Bad: %v", nodes[0]) t.Fatalf("Bad: %v", nodes[0])
} }
if !lib.StrContains(nodes[1].Service.Tags, "master") { if !stringslice.Contains(nodes[1].Service.Tags, "master") {
t.Fatalf("Bad: %v", nodes[1]) t.Fatalf("Bad: %v", nodes[1])
} }
if nodes[0].Checks[0].Status != api.HealthWarning { if nodes[0].Checks[0].Status != api.HealthWarning {

View File

@ -9,7 +9,7 @@ import (
"github.com/hashicorp/consul/acl" "github.com/hashicorp/consul/acl"
"github.com/hashicorp/consul/agent/structs" "github.com/hashicorp/consul/agent/structs"
"github.com/hashicorp/consul/api" "github.com/hashicorp/consul/api"
"github.com/hashicorp/consul/lib" "github.com/hashicorp/consul/lib/stringslice"
"github.com/hashicorp/consul/sdk/testutil/retry" "github.com/hashicorp/consul/sdk/testutil/retry"
"github.com/hashicorp/consul/testrpc" "github.com/hashicorp/consul/testrpc"
"github.com/hashicorp/consul/types" "github.com/hashicorp/consul/types"
@ -64,7 +64,7 @@ func TestInternal_NodeInfo(t *testing.T) {
if nodes[0].Node != "foo" { if nodes[0].Node != "foo" {
t.Fatalf("Bad: %v", nodes[0]) t.Fatalf("Bad: %v", nodes[0])
} }
if !lib.StrContains(nodes[0].Services[0].Tags, "master") { if !stringslice.Contains(nodes[0].Services[0].Tags, "master") {
t.Fatalf("Bad: %v", nodes[0]) t.Fatalf("Bad: %v", nodes[0])
} }
if nodes[0].Checks[0].Status != api.HealthPassing { if nodes[0].Checks[0].Status != api.HealthPassing {
@ -139,7 +139,7 @@ func TestInternal_NodeDump(t *testing.T) {
switch node.Node { switch node.Node {
case "foo": case "foo":
foundFoo = true foundFoo = true
if !lib.StrContains(node.Services[0].Tags, "master") { if !stringslice.Contains(node.Services[0].Tags, "master") {
t.Fatalf("Bad: %v", nodes[0]) t.Fatalf("Bad: %v", nodes[0])
} }
if node.Checks[0].Status != api.HealthPassing { if node.Checks[0].Status != api.HealthPassing {
@ -148,7 +148,7 @@ func TestInternal_NodeDump(t *testing.T) {
case "bar": case "bar":
foundBar = true foundBar = true
if !lib.StrContains(node.Services[0].Tags, "slave") { if !stringslice.Contains(node.Services[0].Tags, "slave") {
t.Fatalf("Bad: %v", nodes[1]) t.Fatalf("Bad: %v", nodes[1])
} }
if node.Checks[0].Status != api.HealthWarning { if node.Checks[0].Status != api.HealthWarning {

View File

@ -7,7 +7,7 @@ import (
"github.com/hashicorp/consul/acl" "github.com/hashicorp/consul/acl"
"github.com/hashicorp/consul/agent/structs" "github.com/hashicorp/consul/agent/structs"
"github.com/hashicorp/consul/lib" "github.com/hashicorp/consul/lib/stringslice"
"github.com/hashicorp/consul/testrpc" "github.com/hashicorp/consul/testrpc"
msgpackrpc "github.com/hashicorp/net-rpc-msgpackrpc" msgpackrpc "github.com/hashicorp/net-rpc-msgpackrpc"
) )
@ -370,7 +370,7 @@ func TestSession_List(t *testing.T) {
} }
for i := 0; i < len(sessions.Sessions); i++ { for i := 0; i < len(sessions.Sessions); i++ {
s := sessions.Sessions[i] s := sessions.Sessions[i]
if !lib.StrContains(ids, s.ID) { if !stringslice.Contains(ids, s.ID) {
t.Fatalf("bad: %v", s) t.Fatalf("bad: %v", s)
} }
if s.Node != "foo" { if s.Node != "foo" {
@ -649,7 +649,7 @@ func TestSession_Renew(t *testing.T) {
} }
for i := 0; i < len(sessions.Sessions); i++ { for i := 0; i < len(sessions.Sessions); i++ {
s := sessions.Sessions[i] s := sessions.Sessions[i]
if !lib.StrContains(ids, s.ID) { if !stringslice.Contains(ids, s.ID) {
t.Fatalf("bad: %v", s) t.Fatalf("bad: %v", s)
} }
if s.Node != "foo" { if s.Node != "foo" {
@ -683,7 +683,7 @@ func TestSession_Renew(t *testing.T) {
} }
s := session.Sessions[0] s := session.Sessions[0]
if !lib.StrContains(ids, s.ID) { if !stringslice.Contains(ids, s.ID) {
t.Fatalf("bad: %v", s) t.Fatalf("bad: %v", s)
} }
if s.Node != "foo" { if s.Node != "foo" {
@ -710,7 +710,7 @@ func TestSession_Renew(t *testing.T) {
for i := 0; i < len(sessionsL1.Sessions); i++ { for i := 0; i < len(sessionsL1.Sessions); i++ {
s := sessionsL1.Sessions[i] s := sessionsL1.Sessions[i]
if !lib.StrContains(ids, s.ID) { if !stringslice.Contains(ids, s.ID) {
t.Fatalf("bad: %v", s) t.Fatalf("bad: %v", s)
} }
if s.Node != "foo" { if s.Node != "foo" {
@ -742,7 +742,7 @@ func TestSession_Renew(t *testing.T) {
if len(sessionsL2.Sessions) != 0 { if len(sessionsL2.Sessions) != 0 {
for i := 0; i < len(sessionsL2.Sessions); i++ { for i := 0; i < len(sessionsL2.Sessions); i++ {
s := sessionsL2.Sessions[i] s := sessionsL2.Sessions[i]
if !lib.StrContains(ids, s.ID) { if !stringslice.Contains(ids, s.ID) {
t.Fatalf("bad: %v", s) t.Fatalf("bad: %v", s)
} }
if s.Node != "foo" { if s.Node != "foo" {
@ -947,7 +947,7 @@ func TestSession_NodeSessions(t *testing.T) {
} }
for i := 0; i < len(sessions.Sessions); i++ { for i := 0; i < len(sessions.Sessions); i++ {
s := sessions.Sessions[i] s := sessions.Sessions[i]
if !lib.StrContains(ids, s.ID) { if !stringslice.Contains(ids, s.ID) {
t.Fatalf("bad: %v", s) t.Fatalf("bad: %v", s)
} }
if s.Node != "foo" { if s.Node != "foo" {

View File

@ -9,7 +9,7 @@ import (
"github.com/hashicorp/consul/agent/structs" "github.com/hashicorp/consul/agent/structs"
"github.com/hashicorp/consul/api" "github.com/hashicorp/consul/api"
"github.com/hashicorp/consul/lib" "github.com/hashicorp/consul/lib/stringslice"
"github.com/hashicorp/consul/types" "github.com/hashicorp/consul/types"
"github.com/hashicorp/go-memdb" "github.com/hashicorp/go-memdb"
uuid "github.com/hashicorp/go-uuid" uuid "github.com/hashicorp/go-uuid"
@ -1814,7 +1814,7 @@ func TestStateStore_ServiceNodes(t *testing.T) {
if nodes[0].ServiceID != "db" { if nodes[0].ServiceID != "db" {
t.Fatalf("bad: %v", nodes) t.Fatalf("bad: %v", nodes)
} }
if !lib.StrContains(nodes[0].ServiceTags, "slave") { if !stringslice.Contains(nodes[0].ServiceTags, "slave") {
t.Fatalf("bad: %v", nodes) t.Fatalf("bad: %v", nodes)
} }
if nodes[0].ServicePort != 8000 { if nodes[0].ServicePort != 8000 {
@ -1829,7 +1829,7 @@ func TestStateStore_ServiceNodes(t *testing.T) {
if nodes[1].ServiceID != "db2" { if nodes[1].ServiceID != "db2" {
t.Fatalf("bad: %v", nodes) t.Fatalf("bad: %v", nodes)
} }
if !lib.StrContains(nodes[1].ServiceTags, "slave") { if !stringslice.Contains(nodes[1].ServiceTags, "slave") {
t.Fatalf("bad: %v", nodes) t.Fatalf("bad: %v", nodes)
} }
if nodes[1].ServicePort != 8001 { if nodes[1].ServicePort != 8001 {
@ -1844,7 +1844,7 @@ func TestStateStore_ServiceNodes(t *testing.T) {
if nodes[2].ServiceID != "db" { if nodes[2].ServiceID != "db" {
t.Fatalf("bad: %v", nodes) t.Fatalf("bad: %v", nodes)
} }
if !lib.StrContains(nodes[2].ServiceTags, "master") { if !stringslice.Contains(nodes[2].ServiceTags, "master") {
t.Fatalf("bad: %v", nodes) t.Fatalf("bad: %v", nodes)
} }
if nodes[2].ServicePort != 8000 { if nodes[2].ServicePort != 8000 {
@ -1947,7 +1947,7 @@ func TestStateStore_ServiceTagNodes(t *testing.T) {
if nodes[0].Address != "127.0.0.1" { if nodes[0].Address != "127.0.0.1" {
t.Fatalf("bad: %v", nodes) t.Fatalf("bad: %v", nodes)
} }
if !lib.StrContains(nodes[0].ServiceTags, "master") { if !stringslice.Contains(nodes[0].ServiceTags, "master") {
t.Fatalf("bad: %v", nodes) t.Fatalf("bad: %v", nodes)
} }
if nodes[0].ServicePort != 8000 { if nodes[0].ServicePort != 8000 {

View File

@ -5,7 +5,7 @@ import (
"strings" "strings"
"github.com/hashicorp/consul/acl" "github.com/hashicorp/consul/acl"
"github.com/hashicorp/consul/lib" "github.com/hashicorp/consul/lib/stringslice"
"github.com/miekg/dns" "github.com/miekg/dns"
) )
@ -377,7 +377,7 @@ func (g *GatewayService) IsSame(o *GatewayService) bool {
g.GatewayKind == o.GatewayKind && g.GatewayKind == o.GatewayKind &&
g.Port == o.Port && g.Port == o.Port &&
g.Protocol == o.Protocol && g.Protocol == o.Protocol &&
lib.StringSliceEqual(g.Hosts, o.Hosts) && stringslice.Equal(g.Hosts, o.Hosts) &&
g.CAFile == o.CAFile && g.CAFile == o.CAFile &&
g.CertFile == o.CertFile && g.CertFile == o.CertFile &&
g.KeyFile == o.KeyFile && g.KeyFile == o.KeyFile &&

View File

@ -1,11 +0,0 @@
package lib
// StrContains checks if a list contains a string
func StrContains(l []string, s string) bool {
for _, v := range l {
if v == s {
return true
}
}
return false
}

View File

@ -1,15 +0,0 @@
package lib
import (
"testing"
)
func TestStrContains(t *testing.T) {
l := []string{"a", "b", "c"}
if !StrContains(l, "b") {
t.Fatalf("should contain")
}
if StrContains(l, "d") {
t.Fatalf("should not contain")
}
}

View File

@ -1,9 +1,23 @@
package lib package stringslice
// StringSliceEqual compares two string slices for equality. Both the existence // StrContains => Contains
// StringSliceEqual => Equal
// StringSliceMergeSorted => MergeSorted
// Contains checks if a list contains a string
func Contains(l []string, s string) bool {
for _, v := range l {
if v == s {
return true
}
}
return false
}
// Equal compares two string slices for equality. Both the existence
// of the elements and the order of those elements matter for equality. Empty // of the elements and the order of those elements matter for equality. Empty
// slices are treated identically to nil slices. // slices are treated identically to nil slices.
func StringSliceEqual(a, b []string) bool { func Equal(a, b []string) bool {
if len(a) != len(b) { if len(a) != len(b) {
return false return false
} }
@ -16,11 +30,11 @@ func StringSliceEqual(a, b []string) bool {
return true return true
} }
// StringSliceMergeSorted takes two string slices that are assumed to be sorted // MergeSorted takes two string slices that are assumed to be sorted
// and does a zipper merge of the two sorted slices, removing any cross-slice // and does a zipper merge of the two sorted slices, removing any cross-slice
// duplicates. If any individual slice contained duplicates those will be // duplicates. If any individual slice contained duplicates those will be
// retained. // retained.
func StringSliceMergeSorted(a, b []string) []string { func MergeSorted(a, b []string) []string {
if len(a) == 0 && len(b) == 0 { if len(a) == 0 && len(b) == 0 {
return nil return nil
} else if len(a) == 0 { } else if len(a) == 0 {

View File

@ -1,4 +1,4 @@
package lib package stringslice
import ( import (
"fmt" "fmt"
@ -7,7 +7,17 @@ import (
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
) )
func TestStringSliceEqual(t *testing.T) { func TestContains(t *testing.T) {
l := []string{"a", "b", "c"}
if !Contains(l, "b") {
t.Fatalf("should contain")
}
if Contains(l, "d") {
t.Fatalf("should not contain")
}
}
func TestEqual(t *testing.T) {
for _, tc := range []struct { for _, tc := range []struct {
a, b []string a, b []string
equal bool equal bool
@ -23,13 +33,13 @@ func TestStringSliceEqual(t *testing.T) {
} { } {
name := fmt.Sprintf("%#v =?= %#v", tc.a, tc.b) name := fmt.Sprintf("%#v =?= %#v", tc.a, tc.b)
t.Run(name, func(t *testing.T) { t.Run(name, func(t *testing.T) {
require.Equal(t, tc.equal, StringSliceEqual(tc.a, tc.b)) require.Equal(t, tc.equal, Equal(tc.a, tc.b))
require.Equal(t, tc.equal, StringSliceEqual(tc.b, tc.a)) require.Equal(t, tc.equal, Equal(tc.b, tc.a))
}) })
} }
} }
func TestStringSliceMergeSorted(t *testing.T) { func TestMergeSorted(t *testing.T) {
for name, tc := range map[string]struct { for name, tc := range map[string]struct {
a, b []string a, b []string
expect []string expect []string
@ -45,8 +55,8 @@ func TestStringSliceMergeSorted(t *testing.T) {
} { } {
tc := tc tc := tc
t.Run(name, func(t *testing.T) { t.Run(name, func(t *testing.T) {
require.Equal(t, tc.expect, StringSliceMergeSorted(tc.a, tc.b)) require.Equal(t, tc.expect, MergeSorted(tc.a, tc.b))
require.Equal(t, tc.expect, StringSliceMergeSorted(tc.b, tc.a)) require.Equal(t, tc.expect, MergeSorted(tc.b, tc.a))
}) })
} }
} }