Documentation
¶
Index ¶
- Variables
- func DiscardLogger() *slog.Logger
- func Eventually(t testing.TB, timeout, interval time.Duration, cond func() bool, what string)
- func Go(fn func() error) func() error
- func GoN(n int, fn func(i int) error) func() error
- func Logger(w io.Writer, level slog.Level) *slog.Logger
- func Must[T any](v T, err error) T
- func Must2[A, B any](a A, b B, err error) (A, B)
- func Poll(timeout, interval time.Duration, cond func() bool, what string) error
- func RandBytes(t testing.TB, n int) []byte
- func Run(t *testing.T, body func() error)
- func RunTable[C any](t *testing.T, cases []C, name func(C) string, body func(*testing.T, C) error)
- func StdoutLogger(level slog.Level) *slog.Logger
- func Within(d time.Duration, what string, body func() error) error
- func WithinCtx(ctx context.Context, what string, body func() error) error
- type NamedSize
- type Stream
- func (s *Stream[Req, Resp]) Context() context.Context
- func (s *Stream[Req, Resp]) Recv() (Req, error)
- func (s *Stream[Req, Resp]) RecvMsg(any) error
- func (s *Stream[Req, Resp]) Send(resp Resp) error
- func (s *Stream[Req, Resp]) SendHeader(metadata.MD) error
- func (s *Stream[Req, Resp]) SendMsg(any) error
- func (s *Stream[Req, Resp]) SetHeader(metadata.MD) error
- func (s *Stream[Req, Resp]) SetTrailer(metadata.MD)
Constants ¶
This section is empty.
Variables ¶
var StdSizes = []NamedSize{
{"1MB", 1 * 1024 * 1024},
{"10MB", 10 * 1024 * 1024},
{"100MB", 100 * 1024 * 1024},
{"1GB", 1024 * 1024 * 1024},
}
StdSizes is the size ladder repeated by 6 of the 10 size tables in tests/benchmark_test.go. Match a table by its ladder, not by line number.
The other four are deliberately NOT covered. They measure different things and keep their own ladders:
- 10MB, 100MB, 600MB netem profiles
- 1KB to 1GB, seven steps chunk-size sweep
- 1KB, 10KB, 100KB, 1MB mount latency
- a {name, count, size} triple multi-file write
Names must stay exactly as written. Subtest names depend on them.
Do not mutate it. A caller that writes `sizes := testkit.StdSizes` shares the backing array with every other test in the binary. Copy it first if a test needs its own ladder.
Functions ¶
func DiscardLogger ¶
DiscardLogger drops all output. It replaces the inline slog.New(slog.NewTextHandler(io.Discard, nil)) construction. slog defaults to LevelInfo when the options are nil, so this is unchanged behaviour for those sites.
func Eventually ¶
Eventually fails the test if cond does not become true inside timeout.
func Go ¶
Go starts fn and returns a join function. Call the join function to wait for fn and get its error. The join function has the shape func() error, so it composes into fp.All with no wrapper.
func GoN ¶
GoN runs fn for i in [0,n) and returns a join function. The join function drains every result before it returns, so no goroutine leaks when one of them fails early. It reports the first error by index.
func Logger ¶
Logger returns a text logger that writes to w at the given level. It is the general form. Use it when a test must keep its output, for example an integration test that logs warnings to stdout for a human to read after a failure. Replacing such a logger with DiscardLogger loses that output.
func Must ¶
Must returns v, or aborts the enclosing Run with err.
ln := testkit.Must(quic.ListenAddr("127.0.0.1:0", cfg, nil))
Must takes no *testing.T on purpose. The Go spec allows a multi-value call to fill an argument list only when that call is the sole argument, so Must(t, f()) is not valid Go. Dropping t makes Must(f()) legal and lets T infer, including the two-value form.
Call Must only inside a Run body. Run turns the abort into an ordinary test failure. Outside Run the panic escapes and ends the test binary.
func Poll ¶
Poll waits for cond, or reports a timeout. It returns error, so it composes with fp.All and is safe off the test goroutine, where t.Fatal is a Go bug.
func Run ¶
Run joins the error-returning code to testify. This is the only point that observes a test failure. Put the whole test body inside it, so Must is safe everywhere in the test.
func RunTable ¶
RunTable runs one subtest per case. name supplies the subtest name, so a conversion keeps the original names. body returns an error, so a case composes with fp.All.
func StdoutLogger ¶
StdoutLogger writes to stdout at the given level. The integration tests use this to keep warnings and errors visible.
func Within ¶
Within runs body and reports an error if body does not return inside d. It replaces the hand-rolled shape that starts a goroutine, reports through a bool channel and races a time.After.
A panic in body becomes an error, so Must is safe inside body. A bare goroutine cannot do this: only the goroutine that panics can recover it, so a Must in a plain go func ends the test binary instead of failing the test.
After a timeout body keeps running. Do not call t.Error or t.Fatal in body. A late call panics after the test ends. Return an error instead.
func WithinCtx ¶
WithinCtx runs body and reports an error if body does not return before ctx ends. Use it where the deadline is held by a context and is shared by more than one wait. Within starts a new duration at each call, so it gives each wait its own budget, which is a different test.
A panic in body becomes an error, the same as Within. The same rule applies after a timeout: body keeps running, so return an error from it, never t.Error.
Types ¶
type Stream ¶
type Stream[Req any, Resp any] struct { // Requests are returned by Recv in order, then io.EOF. Requests []Req // Sent records every message passed to Send. Sent []Resp // SendErr, when set, is returned by Send instead of recording. SendErr error // RecvErr, when set, is returned by Recv instead of the next request. RecvErr error // Ctx overrides the stream context. Nil means context.Background. Ctx context.Context // contains filtered or unexported fields }
Stream is a generic server stream stub. Req is the received message type, Resp the sent one. Both are concrete at every instantiation, so no cast is needed at a call site.
The existing hand-written stubs do not embed grpc.ServerStream. They implement the six methods directly, which avoids a nil-interface panic when the code under test calls one. This type does the same.
For a send-only RPC, instantiate Req as struct{}. The extra Recv method is harmless.
func (*Stream[Req, Resp]) SetHeader ¶
The remaining methods satisfy grpc.ServerStream. SendMsg and RecvMsg take any because the gRPC interface requires it. This is the one place the no-any-as-a-value-type rule does not apply.