testutil

package
v0.16.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Feb 28, 2024 License: MPL-2.0 Imports: 27 Imported by: 22

README

Consul Testing Utilities

This package provides some generic helpers to facilitate testing in Consul.

TestServer

TestServer is a harness for managing Consul agents and initializing them with test data. Using it, you can form test clusters, create services, add health checks, manipulate the K/V store, etc. This test harness is completely decoupled from Consul's core and API client, meaning it can be easily imported and used in external unit tests for various applications. It works by invoking the Consul CLI, which means it is a requirement to have Consul installed in the $PATH.

Following is an example usage:

package my_program

import (
	"testing"

	"github.com/hashicorp/consul/consul/structs"
	"github.com/hashicorp/consul/sdk/testutil"
)

func TestFoo_bar(t *testing.T) {
	// Create a test Consul server
	srv1, err := testutil.NewTestServerConfigT(t, nil)
	if err != nil {
		t.Fatal(err)
	}
	defer srv1.Stop()

	// Create a secondary server, passing in configuration
	// to avoid bootstrapping as we are forming a cluster.
	srv2, err := testutil.NewTestServerConfigT(t, func(c *testutil.TestServerConfig) {
		c.Bootstrap = false
	})
	if err != nil {
		t.Fatal(err)
	}
	defer srv2.Stop()

	// Join the servers together
	srv1.JoinLAN(t, srv2.LANAddr)

	// Create a test key/value pair
	srv1.SetKV(t, "foo", []byte("bar"))

	// Create lots of test key/value pairs
	srv1.PopulateKV(t, map[string][]byte{
		"bar": []byte("123"),
		"baz": []byte("456"),
	})

	// Create a service
	srv1.AddService(t, "redis", structs.HealthPassing, []string{"primary"})

	// Create a service that will be accessed in target source code
	srv1.AddAccessibleService("redis", structs.HealthPassing, "127.0.0.1", 6379, []string{"primary"})

	// Create a service check
	srv1.AddCheck(t, "service:redis", "redis", structs.HealthPassing)

	// Create a node check
	srv1.AddCheck(t, "mem", "", structs.HealthCritical)

	// The HTTPAddr field contains the address of the Consul
	// API on the new test server instance.
	println(srv1.HTTPAddr)

	// All functions also have a wrapper method to limit the passing of "t"
	wrap := srv1.Wrap(t)
	wrap.SetKV("foo", []byte("bar"))
}

Documentation

Index

Constants

View Source
const (
	HealthAny      = "any"
	HealthPassing  = "passing"
	HealthWarning  = "warning"
	HealthCritical = "critical"
	HealthMaint    = "maintenance"
)

copied from testutil to break circular dependency

Variables

View Source
var TestLogLevel = TestLogLevelWithDefault(hclog.Warn)

TestLogLevel is set from the TEST_LOG_LEVEL environment variable. It can be used by tests to set the log level of a hclog.Logger. Defaults to hclog.Warn if the environment variable is unset, or if the value of the environment variable can not be matched to a log level.

Functions

func Logger added in v0.4.0

func Logger(t TestingTB) hclog.InterceptLogger

func LoggerWithOutput added in v0.4.0

func LoggerWithOutput(t TestingTB, output io.Writer) hclog.InterceptLogger

func NewLogBuffer added in v0.6.0

func NewLogBuffer(t TestingTB) io.Writer

NewLogBuffer returns an io.Writer which buffers all writes. When the test ends, t.Failed is checked. If the test has failed or has been run in verbose mode all log output is printed to stdout.

Set the env var NOLOGBUFFER=1 to disable buffering, resulting in all log output being written immediately to stdout.

Typically log output is written either for failed tests or when go test is running with the verbose flag (-v) set. Setting TEST_LOGGING_ONLY_FAILED=1 will prevent logs being output when the verbose flag is set if the test case is successful.

func RequireErrorContains added in v0.5.0

func RequireErrorContains(t testing.TB, err error, expectedErrorMessage string)

RequireErrorContains is a test helper for asserting that an error occurred and the error message returned contains the expected error message as a substring.

func RunStep added in v0.11.0

func RunStep(t *testing.T, name string, fn func(t *testing.T))

RunStep is a test helper to help you stop a series of subtests from executing after the first one that fails.

func TempDir

func TempDir(t TestingTB, name string) string

TempDir creates a temporary directory within tmpdir with the name 'testname-name'. If the directory cannot be created t.Fatal is called. The directory will be removed when the test ends. Set TEST_NOCLEANUP env var to prevent the directory from being removed.

func TempFile

func TempFile(t testing.TB, name string) *os.File

TempFile creates a temporary file within tmpdir with the name 'testname-name'. If the file cannot be created t.Fatal is called. If a temporary directory has been created before consider storing the file inside this directory to avoid double cleanup. The file will be removed when the test ends. Set TEST_NOCLEANUP env var to prevent the file from being removed.

func TestContext added in v0.8.0

func TestContext(t CleanerT) context.Context

func TestLogLevelWithDefault added in v0.15.0

func TestLogLevelWithDefault(l hclog.Level) hclog.Level

Types

type CleanerT added in v0.15.0

type CleanerT interface {
	Helper()
	Cleanup(func())
}

type Locality added in v0.14.0

type Locality struct {
	Region string `json:"region"`
	Zone   string `json:"zone"`
}

Locality is used as the TestServerConfig's Locality.

type ServerConfigCallback

type ServerConfigCallback func(c *TestServerConfig)

ServerConfigCallback is a function interface which can be passed to NewTestServerConfig to modify the server config.

type TestACLs

type TestACLs struct {
	Enabled             bool       `json:"enabled,omitempty"`
	TokenReplication    bool       `json:"enable_token_replication,omitempty"`
	PolicyTTL           string     `json:"policy_ttl,omitempty"`
	TokenTTL            string     `json:"token_ttl,omitempty"`
	DownPolicy          string     `json:"down_policy,omitempty"`
	DefaultPolicy       string     `json:"default_policy,omitempty"`
	EnableKeyListPolicy bool       `json:"enable_key_list_policy,omitempty"`
	Tokens              TestTokens `json:"tokens,omitempty"`
	DisabledTTL         string     `json:"disabled_ttl,omitempty"`
}

type TestAddressConfig

type TestAddressConfig struct {
	HTTP string `json:"http,omitempty"`
}

TestAddressConfig contains the bind addresses for various components of the Consul server.

type TestAuditConfig added in v0.14.0

type TestAuditConfig struct {
	Enabled bool `json:"enabled,omitempty"`
}

TestAudigConfig contains the configuration for Audit

type TestAutopilotConfig added in v0.15.0

type TestAutopilotConfig struct {
	ServerStabilizationTime string `json:"server_stabilization_time,omitempty"`
}

TestAutopilotConfig contains the configuration for autopilot.

type TestCheck

type TestCheck struct {
	ID        string `json:",omitempty"`
	Name      string `json:",omitempty"`
	ServiceID string `json:",omitempty"`
	TTL       string `json:",omitempty"`
}

TestCheck is used to serialize a check definition.

type TestKVResponse

type TestKVResponse struct {
	Value string
}

TestKVResponse is what we use to decode KV data.

type TestNetworkSegment

type TestNetworkSegment struct {
	Name      string `json:"name"`
	Bind      string `json:"bind"`
	Port      int    `json:"port"`
	Advertise string `json:"advertise"`
}

TestNetworkSegment contains the configuration for a network segment.

type TestPeeringConfig added in v0.11.0

type TestPeeringConfig struct {
	Enabled bool `json:"enabled,omitempty"`
}

type TestPerformanceConfig

type TestPerformanceConfig struct {
	RaftMultiplier uint `json:"raft_multiplier,omitempty"`
}

TestPerformanceConfig configures the performance parameters.

type TestPortConfig

type TestPortConfig struct {
	DNS          int `json:"dns,omitempty"`
	HTTP         int `json:"http,omitempty"`
	HTTPS        int `json:"https,omitempty"`
	SerfLan      int `json:"serf_lan,omitempty"`
	SerfWan      int `json:"serf_wan,omitempty"`
	Server       int `json:"server,omitempty"`
	GRPC         int `json:"grpc,omitempty"`
	GRPCTLS      int `json:"grpc_tls,omitempty"`
	ProxyMinPort int `json:"proxy_min_port,omitempty"`
	ProxyMaxPort int `json:"proxy_max_port,omitempty"`
}

TestPortConfig configures the various ports used for services provided by the Consul server.

type TestServer

type TestServer struct {
	Config *TestServerConfig

	HTTPAddr    string
	HTTPSAddr   string
	LANAddr     string
	WANAddr     string
	ServerAddr  string
	GRPCAddr    string
	GRPCTLSAddr string

	HTTPClient *http.Client
	// contains filtered or unexported fields
}

TestServer is the main server wrapper struct.

func NewTestServerConfigT

func NewTestServerConfigT(t TestingTB, cb ServerConfigCallback) (*TestServer, error)

NewTestServerConfigT creates a new TestServer, and makes a call to an optional callback function to modify the configuration. If there is an error configuring or starting the server, the server will NOT be running when the function returns (thus you do not need to stop it). This function will call the `consul` binary in GOPATH.

func (*TestServer) AddAddressableService

func (s *TestServer) AddAddressableService(t testing.TB, name, status, address string, port int, tags []string)

AddAddressableService adds a new service to the Consul instance by passing "address" and "port". It is helpful when you need to prepare a fakeService that maybe accessed with in target source code. It also automatically adds a health check with the given status, which can be one of "passing", "warning", or "critical", just like `AddService` does.

func (*TestServer) AddCheck

func (s *TestServer) AddCheck(t testing.TB, name, serviceID, status string)

AddCheck adds a check to the Consul instance. If the serviceID is left empty (""), then the check will be associated with the node. The check status may be "passing", "warning", or "critical".

func (*TestServer) AddService

func (s *TestServer) AddService(t testing.TB, name, status string, tags []string)

AddService adds a new service to the Consul instance. It also automatically adds a health check with the given status, which can be one of "passing", "warning", or "critical".

func (*TestServer) GetKV

func (s *TestServer) GetKV(t testing.TB, key string) []byte

GetKV retrieves a single key and returns its value

func (*TestServer) GetKVString

func (s *TestServer) GetKVString(t testing.TB, key string) string

GetKVString retrieves a value from the store, but returns as a string instead of []byte.

func (*TestServer) JoinLAN

func (s *TestServer) JoinLAN(t testing.TB, addr string)

JoinLAN is used to join local datacenters together.

func (*TestServer) JoinWAN

func (s *TestServer) JoinWAN(t testing.TB, addr string)

JoinWAN is used to join remote datacenters together.

func (*TestServer) ListKV

func (s *TestServer) ListKV(t testing.TB, prefix string) []string

ListKV returns a list of keys present in the KV store. This will list all keys under the given prefix recursively and return them as a slice.

func (*TestServer) PopulateKV

func (s *TestServer) PopulateKV(t testing.TB, data map[string][]byte)

PopulateKV fills the Consul KV with data from a generic map.

func (*TestServer) SetKV

func (s *TestServer) SetKV(t testing.TB, key string, val []byte)

SetKV sets an individual key in the K/V store.

func (*TestServer) SetKVString

func (s *TestServer) SetKVString(t testing.TB, key string, val string)

SetKVString sets an individual key in the K/V store, but accepts a string instead of []byte.

func (*TestServer) Stop

func (s *TestServer) Stop() error

Stop stops the test Consul server, and removes the Consul data directory once we are done.

func (*TestServer) WaitForActiveCARoot added in v0.4.0

func (s *TestServer) WaitForActiveCARoot(t testing.TB)

WaitForActiveCARoot waits until the server can return a Connect CA meaning connect has completed bootstrapping and is ready to use.

func (*TestServer) WaitForLeader added in v0.2.0

func (s *TestServer) WaitForLeader(t testing.TB)

WaitForLeader waits for the Consul server's HTTP API to become available, and then waits for a known leader to be observed to confirm leader election is done.

func (*TestServer) WaitForSerfCheck

func (s *TestServer) WaitForSerfCheck(t testing.TB)

WaitForSerfCheck ensures we have a node with serfHealth check registered Behavior mirrors testrpc.WaitForTestAgent but avoids the dependency cycle in api pkg

func (*TestServer) WaitForServiceIntentions added in v0.7.0

func (s *TestServer) WaitForServiceIntentions(t testing.TB)

WaitForServiceIntentions waits until the server can accept config entry kinds of service-intentions meaning any migration bootstrapping from pre-1.9 intentions has completed.

func (*TestServer) WaitForVoting added in v0.15.0

func (s *TestServer) WaitForVoting(t testing.TB)

WaitForVoting waits for the Consul server to become a voter in the current raft configuration. You probably want to adjust the ServerStablizationTime autopilot configuration otherwise this could take 10 seconds.

func (*TestServer) Wrap

func (s *TestServer) Wrap(t testing.TB) *WrappedServer

Wrap wraps the test server in a `testing.t` for convenience.

For example, the following code snippets are equivalent.

server.JoinLAN(t, "1.2.3.4")
server.Wrap(t).JoinLAN("1.2.3.4")

This is useful when you are calling multiple functions and save the wrapped value as another variable to reduce the inclusion of "t".

type TestServerConfig

type TestServerConfig struct {
	NodeName            string                 `json:"node_name"`
	NodeID              string                 `json:"node_id"`
	NodeMeta            map[string]string      `json:"node_meta,omitempty"`
	NodeLocality        *Locality              `json:"locality,omitempty"`
	Performance         *TestPerformanceConfig `json:"performance,omitempty"`
	Bootstrap           bool                   `json:"bootstrap,omitempty"`
	Server              bool                   `json:"server,omitempty"`
	Partition           string                 `json:"partition,omitempty"`
	RetryJoin           []string               `json:"retry_join,omitempty"`
	DataDir             string                 `json:"data_dir,omitempty"`
	Datacenter          string                 `json:"datacenter,omitempty"`
	Segments            []TestNetworkSegment   `json:"segments"`
	DisableCheckpoint   bool                   `json:"disable_update_check"`
	LogLevel            string                 `json:"log_level,omitempty"`
	Bind                string                 `json:"bind_addr,omitempty"`
	Addresses           *TestAddressConfig     `json:"addresses,omitempty"`
	Ports               *TestPortConfig        `json:"ports,omitempty"`
	RaftProtocol        int                    `json:"raft_protocol,omitempty"`
	ACLDatacenter       string                 `json:"acl_datacenter,omitempty"`
	PrimaryDatacenter   string                 `json:"primary_datacenter,omitempty"`
	ACLDefaultPolicy    string                 `json:"acl_default_policy,omitempty"`
	ACL                 TestACLs               `json:"acl,omitempty"`
	Encrypt             string                 `json:"encrypt,omitempty"`
	CAFile              string                 `json:"ca_file,omitempty"`
	CertFile            string                 `json:"cert_file,omitempty"`
	KeyFile             string                 `json:"key_file,omitempty"`
	VerifyIncoming      bool                   `json:"verify_incoming,omitempty"`
	VerifyIncomingRPC   bool                   `json:"verify_incoming_rpc,omitempty"`
	VerifyIncomingHTTPS bool                   `json:"verify_incoming_https,omitempty"`
	VerifyOutgoing      bool                   `json:"verify_outgoing,omitempty"`
	EnableScriptChecks  bool                   `json:"enable_script_checks,omitempty"`
	Connect             map[string]interface{} `json:"connect,omitempty"`
	EnableDebug         bool                   `json:"enable_debug,omitempty"`
	SkipLeaveOnInt      bool                   `json:"skip_leave_on_interrupt"`
	Peering             *TestPeeringConfig     `json:"peering,omitempty"`
	Autopilot           *TestAutopilotConfig   `json:"autopilot,omitempty"`
	ReadyTimeout        time.Duration          `json:"-"`
	StopTimeout         time.Duration          `json:"-"`
	Stdout              io.Writer              `json:"-"`
	Stderr              io.Writer              `json:"-"`
	Args                []string               `json:"-"`
	ReturnPorts         func()                 `json:"-"`
	Audit               *TestAuditConfig       `json:"audit,omitempty"`
	Version             string                 `json:"version,omitempty"`
	Experiments         []string               `json:"experiments,omitempty"`
}

TestServerConfig is the main server configuration struct.

type TestService

type TestService struct {
	ID      string   `json:",omitempty"`
	Name    string   `json:",omitempty"`
	Tags    []string `json:",omitempty"`
	Address string   `json:",omitempty"`
	Port    int      `json:",omitempty"`
}

TestService is used to serialize a service definition.

type TestTokens

type TestTokens struct {
	Replication string `json:"replication,omitempty"`
	Default     string `json:"default,omitempty"`
	Agent       string `json:"agent,omitempty"`

	// Note: this field is marshaled as master for compatibility with
	// versions of Consul prior to 1.11.
	InitialManagement string `json:"master,omitempty"`

	// Note: this field is marshaled as agent_master for compatibility with
	// versions of Consul prior to 1.11.
	AgentRecovery string `json:"agent_master,omitempty"`
}

type TestingTB added in v0.7.0

type TestingTB interface {
	Cleanup(func())
	Error(args ...any)
	Errorf(format string, args ...any)
	Fail()
	FailNow()
	Failed() bool
	Fatal(args ...any)
	Fatalf(format string, args ...any)
	Helper()
	Log(args ...any)
	Logf(format string, args ...any)
	Name() string
	Setenv(key, value string)
	TempDir() string
}

TestingTB is an interface that describes the implementation of the testing object. Using an interface that describes testing.TB instead of the actual implementation makes testutil usable in a wider variety of contexts (e.g. use with ginkgo : https://godoc.org/github.com/onsi/ginkgo#GinkgoT)

type WrappedServer

type WrappedServer struct {
	// contains filtered or unexported fields
}

func (*WrappedServer) AddAddressableService

func (w *WrappedServer) AddAddressableService(name, status, address string, port int, tags []string)

func (*WrappedServer) AddCheck

func (w *WrappedServer) AddCheck(name, serviceID, status string)

func (*WrappedServer) AddService

func (w *WrappedServer) AddService(name, status string, tags []string)

func (*WrappedServer) GetKV

func (w *WrappedServer) GetKV(key string) []byte

func (*WrappedServer) GetKVString

func (w *WrappedServer) GetKVString(key string) string

func (*WrappedServer) JoinLAN

func (w *WrappedServer) JoinLAN(addr string)

func (*WrappedServer) JoinWAN

func (w *WrappedServer) JoinWAN(addr string)

func (*WrappedServer) ListKV

func (w *WrappedServer) ListKV(prefix string) []string

func (*WrappedServer) PopulateKV

func (w *WrappedServer) PopulateKV(data map[string][]byte)

func (*WrappedServer) SetKV

func (w *WrappedServer) SetKV(key string, val []byte)

func (*WrappedServer) SetKVString

func (w *WrappedServer) SetKVString(key string, val string)

Directories

Path Synopsis
Package retry provides support for repeating operations in tests.
Package retry provides support for repeating operations in tests.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL