or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

core-assertions.mdgbytes.mdgcustom.mdgexec.mdghttp.mdgleak.mdgmeasure.mdgstruct.mdindex.mdmatchers.mdtypes.md
tile.json

gbytes.mddocs/

Byte Stream Testing (gbytes)

The gbytes package provides utilities for testing byte streams, buffers, and I/O operations. It includes a thread-safe Buffer type and matchers for testing streaming content.

Package Import

import "github.com/onsi/gomega/gbytes"

Buffer Type

Buffer

Thread-safe buffer for testing I/O operations. Implements io.Writer and io.Reader with additional test helpers.

type Buffer struct {
    // Contains filtered or unexported fields
}

The Buffer type provides a thread-safe wrapper around a byte buffer optimized for testing scenarios where you need to:

  • Capture output from commands or processes
  • Test streaming data
  • Verify content appears in output over time
  • Test readers and writers

Buffer Creation

NewBuffer

Creates a new empty buffer.

func NewBuffer() *Buffer

Returns: *Buffer - New empty buffer

Usage:

buffer := gbytes.NewBuffer()

BufferWithBytes

Creates a buffer pre-filled with content.

func BufferWithBytes(bytes []byte) *Buffer

Parameters:

  • bytes: Initial content

Returns: *Buffer - Buffer with initial content

Usage:

buffer := gbytes.BufferWithBytes([]byte("initial content\n"))

BufferReader

Creates a buffer that wraps an io.Reader.

func BufferReader(reader io.Reader) *Buffer

Parameters:

  • reader: io.Reader to wrap

Returns: *Buffer - Buffer that reads from the provided reader

Usage:

file, _ := os.Open("data.txt")
buffer := gbytes.BufferReader(file)

Buffer Methods

Write

Writes data to the buffer. Implements io.Writer.

func (buf *Buffer) Write(p []byte) (n int, err error)

Parameters:

  • p: Bytes to write

Returns:

  • n: Number of bytes written
  • err: Error (always nil for Buffer)

Usage:

buffer := gbytes.NewBuffer()
cmd.Stdout = buffer
cmd.Run()

Read

Reads data from the buffer. Implements io.Reader.

func (buf *Buffer) Read(p []byte) (n int, err error)

Parameters:

  • p: Byte slice to read into

Returns:

  • n: Number of bytes read
  • err: Error (io.EOF when empty)

Usage:

data := make([]byte, 1024)
n, err := buffer.Read(data)

Contents

Returns all content currently in the buffer.

func (buf *Buffer) Contents() []byte

Returns: []byte - Buffer contents

Usage:

buffer := gbytes.NewBuffer()
fmt.Fprintf(buffer, "test output")
content := buffer.Contents()
Expect(content).To(Equal([]byte("test output")))

Clear

Clears all content from the buffer.

func (buf *Buffer) Clear() error

Returns: error - Always returns nil

Usage:

err := buffer.Clear()
Expect(err).NotTo(HaveOccurred())
Expect(buffer.Contents()).To(BeEmpty())

Close

Closes the buffer. After closing, the buffer can no longer be written to.

func (buf *Buffer) Close() error

Returns: error - Always nil

Usage:

buffer.Close()

Closed

Returns whether the buffer has been closed.

func (buf *Buffer) Closed() bool

Returns: bool - True if buffer is closed

Usage:

if buffer.Closed() {
    t.Log("Buffer has been closed")
}

Detect

Creates a channel that receives true when the buffer contains data matching the specified pattern.

func (buf *Buffer) Detect(desired string, args ...any) chan bool

Parameters:

  • desired: Regular expression pattern (or format string with args)
  • args: Optional format arguments

Returns: chan bool - Channel that receives true when pattern is detected

Usage:

buffer := gbytes.NewBuffer()
detected := buffer.Detect("SUCCESS")

go func() {
    fmt.Fprintln(buffer, "Operation SUCCESS")
}()

Eventually(detected).Should(Receive(BeTrue()))

CancelDetects

Cancels all pending Detect operations and cleans up their goroutines.

func (buf *Buffer) CancelDetects()

Usage:

buffer := gbytes.NewBuffer()
_ = buffer.Detect("pattern1")
_ = buffer.Detect("pattern2")

// Cancel all pending detections
buffer.CancelDetects()

Buffer

Returns the buffer itself, implementing the BufferProvider interface.

func (buf *Buffer) Buffer() *Buffer

Returns: *Buffer - The buffer itself

Usage:

// Useful when Buffer implements BufferProvider interface
var provider gbytes.BufferProvider = buffer
buf := provider.Buffer()

Say

Method version of Say matcher for use with Eventually/Consistently.

func (buf *Buffer) Say(expected any, args ...any) types.GomegaMatcher

Parameters:

  • expected: String pattern or matcher
  • args: Format arguments if expected contains format specifiers

Returns: Matcher that succeeds when buffer contains expected content

Usage:

buffer := gbytes.NewBuffer()
cmd.Stdout = buffer

go cmd.Run()

Eventually(buffer).Should(gbytes.Say("expected output"))

SayWithTimeout

Like Say but with custom timeout for Eventually.

func (buf *Buffer) SayWithTimeout(expected any, timeout time.Duration, args ...any) types.GomegaMatcher

Parameters:

  • expected: String pattern or matcher
  • timeout: Custom timeout duration
  • args: Format arguments

Returns: Matcher with custom timeout

Usage:

Eventually(buffer).Should(buffer.SayWithTimeout("ready", 5*time.Second))

Matchers

Say

Matcher that succeeds when buffer contains expected content. Useful with Eventually for streaming output.

func Say(expected any, args ...any) types.GomegaMatcher

Parameters:

  • expected: Can be:
    • String: Matched as substring or regexp
    • String with format specifiers: Used with args
    • Matcher: Applied to buffer contents
  • args: Format arguments if expected contains format specifiers

Returns: types.GomegaMatcher that matches buffer contents

Usage:

// Wait for specific output
buffer := gbytes.NewBuffer()
cmd.Stdout = buffer
go cmd.Run()

Eventually(buffer).Should(gbytes.Say("Server started"))

// Match multiple patterns
Eventually(buffer).Should(gbytes.Say("Status: %s", "OK"))

// Use with Consistently to ensure output doesn't appear
Consistently(buffer).ShouldNot(gbytes.Say("ERROR"))

// Match with regex
Eventually(buffer).Should(gbytes.Say(`\d+ requests processed`))

Advanced Usage:

// Combine with other matchers
Eventually(buffer).Should(gbytes.Say(ContainSubstring("success")))

// Check ordered output
Eventually(buffer).Should(gbytes.Say("Phase 1"))
Eventually(buffer).Should(gbytes.Say("Phase 2"))
Eventually(buffer).Should(gbytes.Say("Phase 3"))

// Verify multiple independent outputs
buffer1 := gbytes.NewBuffer()
buffer2 := gbytes.NewBuffer()
cmd.Stdout = buffer1
cmd.Stderr = buffer2

Eventually(buffer1).Should(gbytes.Say("stdout message"))
Eventually(buffer2).Should(gbytes.Say("stderr message"))

Interfaces

BufferProvider

Interface for types that can provide a Buffer.

type BufferProvider interface {
    Buffer() *Buffer
}

Types implementing this interface can be used directly with the Say matcher. The Buffer type itself implements this interface.

Example:

var provider gbytes.BufferProvider = gbytes.NewBuffer()
buffer := provider.Buffer()

I/O Timeout Wrappers

TimeoutCloser

Wraps an io.Closer with timeout enforcement.

func TimeoutCloser(c io.Closer, timeout time.Duration) io.Closer

Parameters:

  • c: io.Closer to wrap
  • timeout: Maximum duration to wait for Close() to complete

Returns: io.Closer that enforces timeout

Example:

file, _ := os.Open("data.txt")
closer := gbytes.TimeoutCloser(file, 5*time.Second)

err := closer.Close()
if err == gbytes.ErrTimeout {
    log.Println("Close operation timed out")
}

TimeoutReader

Wraps an io.Reader with timeout enforcement.

func TimeoutReader(r io.Reader, timeout time.Duration) io.Reader

Parameters:

  • r: io.Reader to wrap
  • timeout: Maximum duration to wait for Read() to complete

Returns: io.Reader that enforces timeout

Example:

reader := gbytes.TimeoutReader(slowReader, 2*time.Second)

data := make([]byte, 1024)
n, err := reader.Read(data)
if err == gbytes.ErrTimeout {
    log.Println("Read operation timed out")
}

TimeoutWriter

Wraps an io.Writer with timeout enforcement.

func TimeoutWriter(w io.Writer, timeout time.Duration) io.Writer

Parameters:

  • w: io.Writer to wrap
  • timeout: Maximum duration to wait for Write() to complete

Returns: io.Writer that enforces timeout

Example:

writer := gbytes.TimeoutWriter(slowWriter, 3*time.Second)

n, err := writer.Write([]byte("data"))
if err == gbytes.ErrTimeout {
    log.Println("Write operation timed out")
}

ErrTimeout

Error returned when a timeout operation exceeds its duration.

var ErrTimeout error

Usage:

reader := gbytes.TimeoutReader(slowReader, 1*time.Second)
_, err := reader.Read(data)

if errors.Is(err, gbytes.ErrTimeout) {
    log.Println("Operation timed out")
}

Common Patterns

Testing Command Output

buffer := gbytes.NewBuffer()
cmd := exec.Command("myapp", "args")
cmd.Stdout = buffer
cmd.Stderr = buffer

err := cmd.Start()
Expect(err).ShouldNot(HaveOccurred())

// Wait for specific output
Eventually(buffer, 5*time.Second).Should(gbytes.Say("Application started"))

// Verify no errors appeared
Consistently(buffer, 2*time.Second).ShouldNot(gbytes.Say("ERROR|FATAL"))

cmd.Wait()

Testing Streaming APIs

buffer := gbytes.NewBuffer()

go func() {
    stream.WriteTo(buffer)
}()

// Verify data appears in order
Eventually(buffer).Should(gbytes.Say("Header"))
Eventually(buffer).Should(gbytes.Say("Data chunk 1"))
Eventually(buffer).Should(gbytes.Say("Data chunk 2"))
Eventually(buffer).Should(gbytes.Say("Footer"))

Testing Loggers

var logBuffer *gbytes.Buffer

BeforeEach(func() {
    logBuffer = gbytes.NewBuffer()
    logger.SetOutput(logBuffer)
})

It("logs important events", func() {
    service.DoSomething()

    Eventually(logBuffer).Should(gbytes.Say("INFO.*Operation started"))
    Eventually(logBuffer).Should(gbytes.Say("INFO.*Operation completed"))
})

It("doesn't log sensitive data", func() {
    service.ProcessData(sensitiveData)

    Consistently(logBuffer).ShouldNot(gbytes.Say("password|secret|token"))
})

Capturing and Verifying Multi-line Output

buffer := gbytes.NewBuffer()
cmd.Stdout = buffer

go cmd.Run()

// Match patterns across lines
Eventually(buffer).Should(gbytes.Say("Connection established"))
Eventually(buffer).Should(gbytes.Say("Authenticated"))
Eventually(buffer).Should(gbytes.Say("Ready"))

// Verify final state
Eventually(buffer).Should(gbytes.Say("Shutdown complete"))
Expect(buffer.Contents()).To(ContainSubstring("No errors"))

Testing with Both Stdout and Stderr

stdout := gbytes.NewBuffer()
stderr := gbytes.NewBuffer()

cmd.Stdout = stdout
cmd.Stderr = stderr

go cmd.Run()

// Verify normal output on stdout
Eventually(stdout).Should(gbytes.Say("Processing..."))
Eventually(stdout).Should(gbytes.Say("Done"))

// Verify warnings on stderr
Eventually(stderr).Should(gbytes.Say("Warning: deprecated API"))

// Ensure no errors
Consistently(stderr).ShouldNot(gbytes.Say("Error|Failed"))

Thread Safety

Buffer is thread-safe. Multiple goroutines can safely:

  • Write to the buffer concurrently
  • Read buffer contents concurrently
  • Use Say matcher while writes are happening

This makes it ideal for testing concurrent systems where output may be produced by multiple goroutines.

buffer := gbytes.NewBuffer()

// Safe: multiple writers
go func() { fmt.Fprintln(buffer, "Writer 1") }()
go func() { fmt.Fprintln(buffer, "Writer 2") }()
go func() { fmt.Fprintln(buffer, "Writer 3") }()

// Safe: concurrent reading
Eventually(buffer).Should(gbytes.Say("Writer 1"))
Eventually(buffer).Should(gbytes.Say("Writer 2"))
Eventually(buffer).Should(gbytes.Say("Writer 3"))