You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
consul/proto/private/pbservice/convert_test.go

130 lines
3.6 KiB

// Copyright (c) HashiCorp, Inc.
[COMPLIANCE] License changes (#18443) * Adding explicit MPL license for sub-package This directory and its subdirectories (packages) contain files licensed with the MPLv2 `LICENSE` file in this directory and are intentionally licensed separately from the BSL `LICENSE` file at the root of this repository. * Adding explicit MPL license for sub-package This directory and its subdirectories (packages) contain files licensed with the MPLv2 `LICENSE` file in this directory and are intentionally licensed separately from the BSL `LICENSE` file at the root of this repository. * Updating the license from MPL to Business Source License Going forward, this project will be licensed under the Business Source License v1.1. Please see our blog post for more details at <Blog URL>, FAQ at www.hashicorp.com/licensing-faq, and details of the license at www.hashicorp.com/bsl. * add missing license headers * Update copyright file headers to BUSL-1.1 * Update copyright file headers to BUSL-1.1 * Update copyright file headers to BUSL-1.1 * Update copyright file headers to BUSL-1.1 * Update copyright file headers to BUSL-1.1 * Update copyright file headers to BUSL-1.1 * Update copyright file headers to BUSL-1.1 * Update copyright file headers to BUSL-1.1 * Update copyright file headers to BUSL-1.1 * Update copyright file headers to BUSL-1.1 * Update copyright file headers to BUSL-1.1 * Update copyright file headers to BUSL-1.1 * Update copyright file headers to BUSL-1.1 * Update copyright file headers to BUSL-1.1 * Update copyright file headers to BUSL-1.1 --------- Co-authored-by: hashicorp-copywrite[bot] <110428419+hashicorp-copywrite[bot]@users.noreply.github.com>
1 year ago
// SPDX-License-Identifier: BUSL-1.1
package pbservice
import (
"os"
"reflect"
"strconv"
"testing"
"time"
"github.com/google/go-cmp/cmp"
"github.com/google/go-cmp/cmp/cmpopts"
fuzz "github.com/google/gofuzz"
"github.com/hashicorp/consul/agent/structs"
)
func TestNewCheckServiceNodeFromStructs_RoundTrip(t *testing.T) {
repeat(t, func(t *testing.T, fuzzer *fuzz.Fuzzer) {
fuzzer.Funcs(randInt32, randUint32, randInterface, randStructsUpstream, randEnterpriseMeta, randStructsConnectProxyConfig)
var target structs.CheckServiceNode
fuzzer.Fuzz(&target)
result, err := CheckServiceNodeToStructs(NewCheckServiceNodeFromStructs(&target))
if err != nil {
t.Fatalf("unexpected error: %s", err.Error())
}
assertEqual(t, &target, result)
})
}
func repeat(t *testing.T, fn func(t *testing.T, fuzzer *fuzz.Fuzzer)) {
reps := getEnvIntWithDefault(t, "TEST_REPEAT_COUNT", 5)
seed := getEnvIntWithDefault(t, "TEST_RANDOM_SEED", time.Now().UnixNano())
t.Logf("using seed %d for %d repetitions", seed, reps)
fuzzer := fuzz.NewWithSeed(seed)
for i := 0; i < int(reps); i++ {
t.Run(strconv.Itoa(i), func(t *testing.T) {
fn(t, fuzzer)
})
}
}
func getEnvIntWithDefault(t *testing.T, key string, d int64) int64 {
t.Helper()
raw, ok := os.LookupEnv(key)
if !ok {
return d
}
v, err := strconv.Atoi(raw)
if err != nil {
t.Fatalf("invald value for %v: %v", key, err.Error())
}
return int64(v)
}
func assertEqual(t *testing.T, x, y interface{}) {
t.Helper()
if diff := cmp.Diff(x, y, cmpopts.EquateEmpty()); diff != "" {
t.Fatalf("assertion failed: values are not equal\n--- original\n+++ result\n\n%v", diff)
}
}
// randUint32 is a custom fuzzer function which limits all uints to 32 bits.
// This is necessary because the structs types use un-sized uints, however in
// practice they are constrained to 32 bits, and the protobuf types use (u)int32.
// The structs types use (u)int64 for any fields that require 64 bits.
func randUint32(i *uint, c fuzz.Continue) {
*i = uint(c.Rand.Uint32())
}
// see randUint32
func randInt32(i *int, c fuzz.Continue) {
*i = int(c.Rand.Int31())
}
// randStructsConnectProxyConfig is a custom fuzzer function which skips
// generating values for fields enumerated in the ignore-fields annotation.
func randStructsConnectProxyConfig(p *structs.ConnectProxyConfig, c fuzz.Continue) {
v := reflect.ValueOf(p).Elem()
for i := 0; i < v.NumField(); i++ {
switch v.Type().Field(i).Name {
case "MutualTLSMode":
continue
}
c.Fuzz(v.Field(i).Addr().Interface())
}
}
// randStructsUpstream is a custom fuzzer function which skips generating values
// for fields enumerated in the ignore-fields annotation.
func randStructsUpstream(u *structs.Upstream, c fuzz.Continue) {
v := reflect.ValueOf(u).Elem()
for i := 0; i < v.NumField(); i++ {
switch v.Type().Field(i).Name {
case "IngressHosts":
continue
}
c.Fuzz(v.Field(i).Addr().Interface())
}
}
// randInterface is a custom fuzzer function which generates random data for
// interface{} (most likely used in a map[string]interface{}).
// The random data does not contain any ints (or float32) because protobuf
// converts them to float64, which will cause the test to fail.
func randInterface(m *interface{}, c fuzz.Continue) {
switch c.Rand.Intn(6) {
case 0:
*m = nil
case 1:
*m = c.RandBool()
case 2:
*m = c.Rand.Float64()
case 3:
*m = c.RandString()
case 4:
*m = []interface{}{c.RandString(), c.RandBool(), nil, c.Rand.Float64()}
case 5:
*m = map[string]interface{}{
c.RandString(): c.RandString(),
c.RandString(): c.Rand.Float64(),
c.RandString(): nil,
}
}
}