tstest

package
v0.0.0-...-113f59a Latest Latest
Warning

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

Go to latest
Published: Feb 16, 2024 License: BSD-3-Clause Imports: 22 Imported by: 0

Documentation

Overview

Package tstest provides utilities for use in unit tests.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func FixLogs

func FixLogs(t *testing.T)

func MinAllocsPerRun

func MinAllocsPerRun(t *testing.T, target uint64, f func()) error

MinAllocsPerRun asserts that f can run with no more than target allocations. It runs f up to 1000 times or 5s, whichever happens first. If f has executed more than target allocations on every run, it returns a non-nil error.

MinAllocsPerRun sets GOMAXPROCS to 1 during its measurement and restores it before returning.

func PanicOnLog

func PanicOnLog()

PanicOnLog modifies the standard library log package's default output to an io.Writer that panics, to root out code that's not plumbing their logging through explicit tailscale.com/logger.Logf paths.

func Parallel

func Parallel(t *testing.T)

Parallel calls t.Parallel, unless TS_SERIAL_TESTS is set true.

func Replace

func Replace[T any](t testing.TB, target *T, val T)

Replace replaces the value of target with val. The old value is restored when the test ends.

func ResourceCheck

func ResourceCheck(tb testing.TB)

ResourceCheck takes a snapshot of the current goroutines and registers a cleanup on tb to verify that after the rest, all goroutines created by the test go away. (well, at least that the count matches. Maybe in the future it can look at specific routines).

It panics if called from a parallel test.

func Shard

func Shard(t testing.TB)

Shard skips t if it's not running if the TS_TEST_SHARD test shard is set to "n/m" and this test execution number in the process mod m is not equal to n-1. That is, to run with 4 shards, set TS_TEST_SHARD=1/4, ..., TS_TEST_SHARD=4/4 for the four jobs.

func SkipOnUnshardedCI

func SkipOnUnshardedCI(t testing.TB)

SkipOnUnshardedCI skips t if we're in CI and the TS_TEST_SHARD environment variable isn't set.

func UnfixLogs

func UnfixLogs(t *testing.T)

func WaitFor

func WaitFor(maxWait time.Duration, try func() error) error

WaitFor retries try for up to maxWait. It returns nil once try returns nil the first time. If maxWait passes without success, it returns try's last error.

func WhileTestRunningLogger

func WhileTestRunningLogger(t testing.TB) logger.Logf

WhileTestRunningLogger returns a logger.Logf that logs to t.Logf until the test finishes, at which point it no longer logs anything.

Types

type Clock

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

Clock is a testing clock that advances every time its Now method is called, beginning at its start time. If no start time is specified using ClockBuilder, an arbitrary start time will be selected when the Clock is created and can be retrieved by calling Clock.Start().

func NewClock

func NewClock(co ClockOpts) *Clock

NewClock creates a Clock with the specified settings. To create a Clock with only the default settings, new(Clock) is equivalent, except that the start time will not be computed until one of the receivers is called.

func (*Clock) Advance

func (c *Clock) Advance(d time.Duration) time.Time

Advance moves simulated time forward or backwards by a relative amount. Any Timer or Ticker that is waiting will fire at the requested point in simulated time. Advance returns the new simulated time. If this Clock follows real time then the next call to Now will equal the return value of Advance + the elapsed time since calling Advance. Otherwise, the next call to Now will equal the return value of Advance, regardless of the current step.

func (*Clock) AdvanceTo

func (c *Clock) AdvanceTo(t time.Time)

AdvanceTo moves simulated time to a new absolute value. Any Timer or Ticker that is waiting will fire at the requested point in simulated time. If this Clock follows real time then the next call to Now will equal t + the elapsed time since calling Advance. Otherwise, the next call to Now will equal t, regardless of the configured step.

func (*Clock) AfterFunc

func (c *Clock) AfterFunc(d time.Duration, f func()) tstime.TimerController

AfterFunc returns a Timer that calls f when it fires, using this Clock for accessing the current time.

func (*Clock) GetStart

func (c *Clock) GetStart() time.Time

GetStart returns the initial simulated time when this Clock was created.

func (*Clock) GetStep

func (c *Clock) GetStep() time.Duration

GetStep returns the amount that simulated time advances on every call to Now.

func (*Clock) NewTicker

func (c *Clock) NewTicker(d time.Duration) (tstime.TickerController, <-chan time.Time)

NewTicker returns a Ticker that uses this Clock for accessing the current time.

func (*Clock) NewTimer

func (c *Clock) NewTimer(d time.Duration) (tstime.TimerController, <-chan time.Time)

NewTimer returns a Timer that uses this Clock for accessing the current time.

func (*Clock) Now

func (c *Clock) Now() time.Time

Now returns the virtual clock's current time, and advances it according to its step configuration.

func (*Clock) PeekNow

func (c *Clock) PeekNow() time.Time

PeekNow returns the last time reported by Now. If Now has never been called, PeekNow returns the same value as GetStart.

func (*Clock) SetStep

func (c *Clock) SetStep(d time.Duration)

SetStep updates the amount that simulated time advances on every call to Now.

func (*Clock) SetTimerChannelSize

func (c *Clock) SetTimerChannelSize(n int)

SetTimerChannelSize changes the channel size for any Timer or Ticker created in the future. It does not affect those that were already created.

func (*Clock) Since

func (c *Clock) Since(t time.Time) time.Duration

Since subtracts specified duration from Now().

type ClockOpts

type ClockOpts struct {
	// Start is the starting time for the Clock. When FollowRealTime is false,
	// Start is also the value that will be returned by the first call
	// to Clock.Now.
	Start time.Time
	// Step is the amount of time the Clock will advance whenever Clock.Now is
	// called. If set to zero, the Clock will only advance when Clock.Advance is
	// called and/or if FollowRealTime is true.
	//
	// FollowRealTime and Step cannot be enabled at the same time.
	Step time.Duration

	// TimerChannelSize configures the maximum buffered ticks that are
	// permitted in the channel of any Timer and Ticker created by this Clock.
	// The special value 0 means to use the default of 1. The buffer may need to
	// be increased if time is advanced by more than a single tick and proper
	// functioning of the test requires that the ticks are not lost.
	TimerChannelSize int

	// FollowRealTime makes the simulated time increment along with real time.
	// It is a compromise between determinism and the difficulty of explicitly
	// managing the simulated time via Step or Clock.Advance. When
	// FollowRealTime is set, calls to Now() and PeekNow() will add the
	// elapsed real-world time to the simulated time.
	//
	// FollowRealTime and Step cannot be enabled at the same time.
	FollowRealTime bool
}

ClockOpts is used to configure the initial settings for a Clock. Once the settings are configured as desired, call NewClock to get the resulting Clock.

type LogLineTracker

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

LogLineTracker is a logger that tracks which log format patterns it's seen and can report which expected ones were not seen later.

func NewLogLineTracker

func NewLogLineTracker(logf logger.Logf, expectedFormatStrings []string) *LogLineTracker

NewLogLineTracker produces a LogLineTracker wrapping a given logf that tracks whether expectedFormatStrings were seen.

func (*LogLineTracker) Check

func (lt *LogLineTracker) Check() []string

Check returns which format strings haven't been logged yet.

func (*LogLineTracker) Close

func (lt *LogLineTracker) Close()

Close closes lt. After calling Close, calls to Logf become no-ops.

func (*LogLineTracker) Logf

func (lt *LogLineTracker) Logf(format string, args ...any)

Logf logs to its underlying logger and also tracks that the given format pattern has been seen.

func (*LogLineTracker) Reset

func (lt *LogLineTracker) Reset()

Reset forgets everything that it's seen.

type MemLogger

type MemLogger struct {
	sync.Mutex
	bytes.Buffer
}

MemLogger is a bytes.Buffer with a Logf method for tests that want to log to a buffer.

func (*MemLogger) Logf

func (ml *MemLogger) Logf(format string, args ...any)

func (*MemLogger) String

func (ml *MemLogger) String() string

type Ticker

type Ticker struct {
	C <-chan time.Time // The channel on which ticks are delivered.
	// contains filtered or unexported fields
}

Ticker is a time.Ticker lookalike for use in tests that need to control when events fire. Ticker could be made standalone in future but for now is expected to be paired with a Clock and created by Clock.NewTicker.

func (*Ticker) Fire

func (t *Ticker) Fire(curTime time.Time) time.Time

Fire triggers the ticker. curTime is the timestamp to write to the channel. The next trigger time for the ticker is updated to the last computed trigger time + the ticker period (set at creation or using Reset). The next trigger time is computed this way to match standard time.Ticker behavior, which prevents accumulation of long term drift caused by delays in event execution.

func (*Ticker) Reset

func (t *Ticker) Reset(d time.Duration)

Reset adjusts the Ticker's period to d and reschedules the next fire time to the current simulated time + d.

func (*Ticker) ResetAbsolute

func (t *Ticker) ResetAbsolute(nextTrigger time.Time, d time.Duration)

ResetAbsolute adjusts the Ticker's period to d and reschedules the next fire time to nextTrigger.

func (*Ticker) Stop

func (t *Ticker) Stop()

Stop deactivates the Ticker.

type Timer

type Timer struct {
	C <-chan time.Time // The channel on which ticks are delivered.
	// contains filtered or unexported fields
}

Timer is a time.Timer lookalike for use in tests that need to control when events fire. Timer could be made standalone in future but for now must be paired with a Clock and created by Clock.NewTimer.

func (*Timer) Fire

func (t *Timer) Fire(curTime time.Time) time.Time

Fire triggers the ticker. curTime is the timestamp to write to the channel. The next trigger time for the ticker is updated to the last computed trigger time + the ticker period (set at creation or using Reset). The next trigger time is computed this way to match standard time.Ticker behavior, which prevents accumulation of long term drift caused by delays in event execution.

func (*Timer) Reset

func (t *Timer) Reset(d time.Duration) bool

Reset reschedules the next fire time to the current simulated time + d. Reset reports whether the timer was still active before the reset.

func (*Timer) ResetAbsolute

func (t *Timer) ResetAbsolute(nextTrigger time.Time) bool

ResetAbsolute reschedules the next fire time to nextTrigger. ResetAbsolute reports whether the timer was still active before the reset.

func (*Timer) Stop

func (t *Timer) Stop() bool

Stop deactivates the Timer. Stop reports whether the timer was active before stopping.

Directories

Path Synopsis
The deptest package contains a shared implementation of negative dependency tests for other packages, making sure we don't start depending on certain packages.
The deptest package contains a shared implementation of negative dependency tests for other packages, making sure we don't start depending on certain packages.
Package integration contains Tailscale integration tests.
Package integration contains Tailscale integration tests.
testcontrol
Package testcontrol contains a minimal control plane server for testing purposes.
Package testcontrol contains a minimal control plane server for testing purposes.
vms
Package vms does VM-based integration/functional tests by using qemu and a bank of pre-made VM images.
Package vms does VM-based integration/functional tests by using qemu and a bank of pre-made VM images.
Package iosdeps is a just a list of the packages we import on iOS, to let us test that our transitive closure of dependencies on iOS doesn't accidentally grow too large, as we've historically been memory constrained there.
Package iosdeps is a just a list of the packages we import on iOS, to let us test that our transitive closure of dependencies on iOS doesn't accidentally grow too large, as we've historically been memory constrained there.
Package jsdeps is a just a list of the packages we import in the JavaScript/WASM build, to let us test that our transitive closure of dependencies doesn't accidentally grow too large, since binary size is more of a concern.
Package jsdeps is a just a list of the packages we import in the JavaScript/WASM build, to let us test that our transitive closure of dependencies doesn't accidentally grow too large, since binary size is more of a concern.
Package natlab lets us simulate different types of networks all in-memory without running VMs or requiring root, etc.
Package natlab lets us simulate different types of networks all in-memory without running VMs or requiring root, etc.

Jump to

Keyboard shortcuts

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