2023-03-28 18:39:22 +00:00
|
|
|
// Copyright (c) HashiCorp, Inc.
|
|
|
|
// SPDX-License-Identifier: MPL-2.0
|
|
|
|
|
2021-10-28 21:11:26 +00:00
|
|
|
package consul
|
|
|
|
|
|
|
|
import (
|
|
|
|
"reflect"
|
|
|
|
"testing"
|
|
|
|
"time"
|
|
|
|
|
|
|
|
fuzz "github.com/google/gofuzz"
|
|
|
|
"github.com/stretchr/testify/require"
|
|
|
|
)
|
|
|
|
|
|
|
|
func TestCloneSerfLANConfig(t *testing.T) {
|
|
|
|
config := DefaultConfig().SerfLANConfig
|
|
|
|
|
|
|
|
// NOTE: ALL fields on serf.Config and memberlist.Config MUST BE
|
|
|
|
// represented either here or in the CloneSerfLANConfig function body.
|
|
|
|
// Failure to add it to the clone or ignore sections will fail the test.
|
|
|
|
memberlistIgnoreFieldNames := []string{
|
|
|
|
"Alive",
|
|
|
|
"AwarenessMaxMultiplier",
|
|
|
|
"Conflict",
|
|
|
|
"Delegate",
|
|
|
|
"DelegateProtocolMax",
|
|
|
|
"DelegateProtocolMin",
|
|
|
|
"DelegateProtocolVersion",
|
|
|
|
"DisableTcpPings",
|
|
|
|
"DisableTcpPingsForNode",
|
2021-11-15 15:51:14 +00:00
|
|
|
"DNSConfigPath",
|
2021-10-28 21:11:26 +00:00
|
|
|
"EnableCompression",
|
|
|
|
"Events",
|
|
|
|
"GossipToTheDeadTime",
|
|
|
|
"HandoffQueueDepth",
|
|
|
|
"IndirectChecks",
|
2021-11-15 15:51:14 +00:00
|
|
|
"Label",
|
2021-10-28 21:11:26 +00:00
|
|
|
"Logger",
|
2021-11-15 15:51:14 +00:00
|
|
|
"LogOutput",
|
2021-10-28 21:11:26 +00:00
|
|
|
"Merge",
|
|
|
|
"Name",
|
|
|
|
"Ping",
|
|
|
|
"ProtocolVersion",
|
|
|
|
"PushPullInterval",
|
2022-10-04 23:51:37 +00:00
|
|
|
"QueueCheckInterval",
|
2021-10-28 21:11:26 +00:00
|
|
|
"RequireNodeNames",
|
2021-11-15 15:51:14 +00:00
|
|
|
"SkipInboundLabelCheck",
|
2021-10-28 21:11:26 +00:00
|
|
|
"SuspicionMaxTimeoutMult",
|
|
|
|
"TCPTimeout",
|
|
|
|
"Transport",
|
|
|
|
"UDPBufferSize",
|
|
|
|
}
|
|
|
|
serfIgnoreFieldNames := []string{
|
|
|
|
"BroadcastTimeout",
|
|
|
|
"CoalescePeriod",
|
|
|
|
"DisableCoordinates",
|
|
|
|
"EnableNameConflictResolution",
|
|
|
|
"EventBuffer",
|
|
|
|
"EventCh",
|
|
|
|
"FlapTimeout",
|
|
|
|
"LeavePropagateDelay",
|
|
|
|
"LogOutput",
|
|
|
|
"Logger",
|
|
|
|
"MaxQueueDepth",
|
|
|
|
"MemberlistConfig",
|
|
|
|
"Merge",
|
|
|
|
"MinQueueDepth",
|
|
|
|
"NodeName",
|
|
|
|
"ProtocolVersion",
|
|
|
|
"QueryBuffer",
|
|
|
|
"QueryResponseSizeLimit",
|
|
|
|
"QuerySizeLimit",
|
|
|
|
"QueryTimeoutMult",
|
|
|
|
"QueueCheckInterval",
|
|
|
|
"QueueDepthWarning",
|
|
|
|
"QuiescentPeriod",
|
|
|
|
"RecentIntentTimeout",
|
|
|
|
"ReconnectInterval",
|
|
|
|
"ReconnectTimeoutOverride",
|
|
|
|
"RejoinAfterLeave",
|
|
|
|
"SnapshotPath",
|
|
|
|
"Tags",
|
|
|
|
"UserCoalescePeriod",
|
|
|
|
"UserEventSizeLimit",
|
|
|
|
"UserQuiescentPeriod",
|
|
|
|
"ValidateNodeNames",
|
|
|
|
}
|
|
|
|
|
|
|
|
serfFuzzed := fuzzNonIgnoredFields(config, serfIgnoreFieldNames)
|
|
|
|
t.Logf("Fuzzing serf.Config fields: %v", serfFuzzed)
|
|
|
|
|
|
|
|
memberlistFuzzed := fuzzNonIgnoredFields(config.MemberlistConfig, memberlistIgnoreFieldNames)
|
|
|
|
t.Logf("Fuzzing memberlist.Config fields: %v", memberlistFuzzed)
|
|
|
|
|
|
|
|
clone := CloneSerfLANConfig(config)
|
|
|
|
require.Equal(t, config, clone)
|
|
|
|
}
|
|
|
|
|
|
|
|
func fuzzNonIgnoredFields(value interface{}, ignoredFields []string) []string {
|
|
|
|
ignored := make(map[string]struct{})
|
|
|
|
for _, field := range ignoredFields {
|
|
|
|
ignored[field] = struct{}{}
|
|
|
|
}
|
|
|
|
|
|
|
|
var fuzzed []string
|
|
|
|
|
|
|
|
// Walk the fields of our object to fuzz and selectively only fuzz the
|
|
|
|
// fields that were not ignored.
|
|
|
|
fuzzer := fuzz.NewWithSeed(time.Now().UnixNano())
|
|
|
|
|
|
|
|
v := reflect.ValueOf(value).Elem()
|
|
|
|
for i := 0; i < v.NumField(); i++ {
|
|
|
|
field := v.Field(i)
|
|
|
|
if !field.CanInterface() {
|
|
|
|
continue // skip unexported fields
|
|
|
|
}
|
|
|
|
|
|
|
|
fieldName := v.Type().Field(i).Name
|
|
|
|
if _, ok := ignored[fieldName]; ok {
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
|
|
|
|
fuzzed = append(fuzzed, fieldName)
|
|
|
|
|
|
|
|
// copy the data somewhere mutable
|
|
|
|
tmp := reflect.New(field.Type())
|
|
|
|
tmp.Elem().Set(field)
|
|
|
|
// fuzz the copy
|
|
|
|
fuzzer.Fuzz(tmp.Interface())
|
|
|
|
// and set the fuzzed copy back to the original location
|
|
|
|
field.Set(reflect.Indirect(tmp))
|
|
|
|
}
|
|
|
|
|
|
|
|
return fuzzed
|
|
|
|
}
|