integration

package
v0.12.0 Latest Latest
Warning

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

Go to latest
Published: Oct 10, 2024 License: Apache-2.0 Imports: 25 Imported by: 2

README

Go Integration Tests

Integration tests in go are standalone binaries that can be run. The convention is that binaries should end in _integration. We do this by putting the main of integration test in a package named *_integration. After building the integration test binaries end up in ./bin

All integration tests assume the topology is running (scion.sh run).

Implementation of your own integration test

  • An integration test should be a standalone binary, i.e. should have a main method.
  • The binary should be named *_integration.
  • It should exit (os.Exit()) with 0 on success and with a non-zero value on error.
  • The Integration interface and the methods in integration should be used to implement the test.

Documentation

Overview

Package integration simplifies the creation of integration tests.

Index

Constants

View Source
const (
	// Daemon is a placeholder for the Daemon server in the arguments.
	Daemon = "<SCIOND>"
	// ServerPortReplace is a placeholder for the server port in the arguments.
	ServerPortReplace = "<ServerPort>"
	// SrcIAReplace is a placeholder for the source IA in the arguments.
	SrcIAReplace = "<SRCIA>"
	// SrcHostReplace is a placeholder for the source host in the arguments.
	SrcHostReplace = "<SRCHost>"
	// SrcAddrPattern is a placeholder for the source address in the arguments.
	SrcAddrPattern = SrcIAReplace + "," + SrcHostReplace
	// DstIAReplace is a placeholder for the destination IA in the arguments.
	DstIAReplace = "<DSTIA>"
	// DstHostReplace is a placeholder for the destination host in the arguments.
	DstHostReplace = "<DSTHost>"
	// DstAddrPattern is a placeholder for the destination address in the arguments.
	DstAddrPattern = DstIAReplace + "," + DstHostReplace
	// ReadySignal should be written to Stdout by the server once it is read to accept clients.
	// The message should always be `Listening ia=<IA>`
	// where <IA> is the IA the server is listening on.
	ReadySignal = "Listening ia="
	// GoIntegrationEnv is an environment variable that is set for the binary under test.
	// It can be used to guard certain statements, like printing the ReadySignal,
	// in a program under test.
	GoIntegrationEnv = "SCION_GO_INTEGRATION"

	// WrapperCmd is the command used to run non-test binaries
	WrapperCmd = "./tools/integration/bin_wrapper.sh"
)
View Source
const (
	// StartServerTimeout is the timeout for starting a server.
	StartServerTimeout = 40 * time.Second
	// DefaultRunTimeout is the timeout when running a server or a client.
	DefaultRunTimeout = 20 * time.Second
	// CtxTimeout is the timeout a context waits before being killed
	CtxTimeout = 2 * time.Second
	// RetryTimeout is the timeout between different attempts
	RetryTimeout = time.Second / 2
	// DaemonAddressesFile is the default file for SCIOND addresses in a topology created
	// with the topology generator.
	DaemonAddressesFile = "sciond_addresses.json"
)

Variables

View Source
var (
	// Docker indicates if the tests should be executed in a Docker container
	Docker = flag.Bool("d", false, "Run tests in a docker container")
)

Functions

func ExecuteTimed

func ExecuteTimed(name string, f func() error) error

ExecuteTimed executes f and prints how long f took to StdOut. Returns the error of f.

func ExtractUniqueDsts

func ExtractUniqueDsts(pairs []IAPair) []*snet.UDPAddr

ExtractUniqueDsts returns all unique destinations in pairs.

func GenFile

func GenFile(file string) string

GenFile returns the path for the given file in the gen folder.

func GetSCIONDAddress

func GetSCIONDAddress(networksFile string, ia addr.IA) (string, error)

func GetSCIONDAddresses

func GetSCIONDAddresses(networksFile string) (map[string]string, error)

func GroupBySource

func GroupBySource(pairs []IAPair) map[*snet.UDPAddr][]*snet.UDPAddr

GroupBySource groups the ISD-AS pairs by source.

func Init

func Init() error

Init initializes the integration test, it adds and validates the command line flags, and initializes logging.

func ListenDone

func ListenDone(dir string, onDone func(src, dst addr.IA)) (string, func(), error)

ListenDone opens a RPC server to listen for done signals.

func LoadNetworkAllocs

func LoadNetworkAllocs() (map[addr.IA]*snet.UDPAddr, error)

func LogDir

func LogDir() string

LogDir returns the path for logs.

func Run

func Run(ctx context.Context, cfg RunConfig) error

Run runs the commands of the run config. The caller must ensure that all commands are executable when run in a tester container. E.g., for end-to-end tests this means the source address is the same for all.

func RunClient

func RunClient(in Integration, pair IAPair, timeout time.Duration,
	checkOutput func([]byte) error) error

RunClient runs a client on the given IAPair. If the client does not finish until timeout it is killed.

func RunUnaryTests

func RunUnaryTests(in Integration, pairs []IAPair,
	timeout time.Duration, checkOutput func([]byte) error) error

RunUnaryTests runs the client for each IAPair. In case of an error the function is terminated immediately.

func StartServer

func StartServer(in Integration, dst *snet.UDPAddr) (io.Closer, error)

StartServer runs a server. The server can be stopped by calling Close() on the returned Closer. To start a server with a custom context use in.StartServer directly.

func TesterID

func TesterID(a *snet.UDPAddr) string

TesterID returns the ID of the tester container.

func WithTimestamp

func WithTimestamp(s string) string

WithTimestamp returns s with the now timestamp prefixed. This is helpful for logging staments to stdout/stderr or in a file where the logger isn't used.

Types

type ASList

type ASList struct {
	Core    []addr.IA `yaml:"Core"`
	NonCore []addr.IA `yaml:"Non-core"`
}

ASList is a list of ISD-AS identifiers grouped by core and non-core.

var (
	// LoadedASList exposes the ASList loaded during Init
	LoadedASList *ASList
)

func LoadASList added in v0.9.0

func LoadASList(fileName string) (*ASList, error)

LoadASList parses the yaml file fileName and returns a structure with non-core and core ASes.

func (*ASList) AllASes added in v0.9.0

func (al *ASList) AllASes() []addr.IA

AllASes returns all ASes in the ASList as a slice.

type BinaryWaiter

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

BinaryWaiter can be used to wait on completion of the process.

func (*BinaryWaiter) Output

func (bw *BinaryWaiter) Output() []byte

Output is the output of the process, only available after Wait is returnred.

func (*BinaryWaiter) Wait

func (bw *BinaryWaiter) Wait() error

Wait waits for completion of the process.

type Cmd

type Cmd struct {
	// Binary is the path to the application binary.
	Binary string
	Args   []string
}

Cmd represents a single command.

func (Cmd) String

func (c Cmd) String() string

func (Cmd) Template

func (c Cmd) Template(src, dst *snet.UDPAddr) (Cmd, error)

Template returns a command with the place holder arguments filled in.

type HostAddr

type HostAddr func(ia addr.IA) *snet.UDPAddr
var CSAddr HostAddr = func(ia addr.IA) *snet.UDPAddr {
	if a := loadAddr(ia); a != nil {
		return a
	}
	if raw, err := os.ReadFile(GenFile("networks.conf")); err == nil {
		pattern := fmt.Sprintf("tester_%s = (.*)", addr.FormatIA(ia, addr.WithFileSeparator()))
		matches := regexp.MustCompile(pattern).FindSubmatch(raw)
		if len(matches) == 2 {
			return &snet.UDPAddr{IA: ia, Host: &net.UDPAddr{IP: net.ParseIP(string(matches[1]))}}
		}
	}
	path := GenFile(
		filepath.Join(
			addr.FormatAS(ia.AS(), addr.WithDefaultPrefix(), addr.WithFileSeparator()),
			"topology.json",
		),
	)
	topo, err := topology.RWTopologyFromJSONFile(path)
	if err != nil {
		log.Error("Error loading topology", "err", err)
		os.Exit(1)
	}
	cs := topo.CS["cs"+addr.FormatIA(ia, addr.WithFileSeparator())+"-1"]
	return &snet.UDPAddr{IA: ia, Host: cs.SCIONAddress}
}

CSAddr reads the tester host Addr from the topology for the specified IA. If the address cannot be found, the CS address is returned.

type IAPair

type IAPair struct {
	Src, Dst *snet.UDPAddr
}

IAPair is a source, destination pair. The client (Src) will dial the server (Dst).

func IAPairs

func IAPairs(hostAddr HostAddr) []IAPair

IAPairs returns all IAPairs that should be tested.

func UniqueIAPairs

func UniqueIAPairs(hostAddr HostAddr) []IAPair

UniqueIAPairs returns all distinct IAPairs that should be tested.

type Integration

type Integration interface {
	// Name returns the name of the test
	Name() string
	// StartServer should start the server listening on the address dst.
	// StartServer should return after it is ready to accept clients.
	// The context should be used to make the server cancellable.
	StartServer(ctx context.Context, dst *snet.UDPAddr) (Waiter, error)
	// StartClient should start the client on the src address connecting to the dst address.
	// StartClient should return immediately.
	// The context should be used to make the client cancellable.
	StartClient(ctx context.Context, src, dst *snet.UDPAddr) (*BinaryWaiter, error)
}

Integration can be used to run integration tests.

func NewBinaryIntegration

func NewBinaryIntegration(name string, cmd string, clientArgs, serverArgs []string) Integration

NewBinaryIntegration returns an implementation of the Integration interface. Start* will run the binary programm with name and use the given arguments for the client/server. Use SrcIAReplace and DstIAReplace in arguments as placeholder for the source and destination IAs. When starting a client/server the placeholders will be replaced with the actual values. The server should output the ReadySignal to Stdout once it is ready to accept clients.

type RunConfig

type RunConfig struct {
	Commands []Cmd
	LogFile  string
	// Tester is the tester container to run the commands in. If it is empty,
	// the commands are run directly, instead of in a tester container.
	Tester string
}

RunConfig is used to configure the run.

type Waiter

type Waiter interface {
	// Wait should block until the underlying program is terminated.
	Wait() error
}

Waiter is a descriptor of a process running in the integration test. It should be used to wait on completion of the process.

Directories

Path Synopsis

Jump to

Keyboard shortcuts

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