rpcreplay

package
v0.9.0 Latest Latest
Warning

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

Go to latest
Published: Jun 21, 2017 License: Apache-2.0 Imports: 15 Imported by: 0

Documentation

Overview

Package rpcreplay supports the capture and replay of gRPC calls. Its main goal is to improve testing. Once one captures the calls of a test that runs against a real service, one has an "automatic mock" that can be replayed against the same test, yielding a unit test that is fast and flake-free.

Recording

To record a sequence of gRPC calls to a file, create a Recorder and pass its DialOptions to grpc.Dial:

rec, err := rpcreplay.NewRecorder("service.replay", nil)
if err != nil { ... }
defer func() {
    if err := rec.Close(); err != nil { ... }
}()
conn, err := grpc.Dial(serverAddress, rec.DialOptions()...)

It's essential to close the Recorder when the interaction is finished.

There is also a NewRecorderWriter function for capturing to an arbitrary io.Writer.

Replaying

Replaying a captured file looks almost identical: create a Replayer and use its DialOptions. (Since we're reading the file and not writing it, we don't have to be as careful about the error returned from Close).

rep, err := rpcreplay.NewReplayer("service.replay")
if err != nil { ... }
defer rep.Close()
conn, err := grpc.Dial(serverAddress, rep.DialOptions()...)

Initial State

A test might use random or time-sensitive values, for instance to create unique resources for isolation from other tests. The test therefore has initial values -- the current time, a random seed -- that differ from run to run. You must record this initial state and re-establish it on replay.

To record the initial state, serialize it into a []byte and pass it as the second argument to NewRecorder:

timeNow := time.Now()
b, err := timeNow.MarshalBinary()
if err != nil { ... }
rec, err := rpcreplay.NewRecorder("service.replay", b)

On replay, get the bytes from Replayer.Initial:

rep, err := rpcreplay.NewReplayer("service.replay")
if err != nil { ... }
defer rep.Close()
err = timeNow.UnmarshalBinary(rep.Initial())
if err != nil { ... }

Nondeterminism

A nondeterministic program may invoke RPCs in a different order each time it is run. The order in which RPCs are called during recording may differ from the order during replay.

The replayer matches incoming to recorded requests by method name and request contents, so nondeterminism is only a concern for identical requests that result in different responses. A nondeterministic program whose behavior differs depending on the order of such RPCs probably has a race condition: since both the recorded sequence of RPCs and the sequence during replay are valid orderings, the program should behave the same under both.

Other Replayer Differences

Besides the differences in replay mentioned above, other differences may cause issues for some programs. We list them here.

The Replayer delivers a response to an RPC immediately, without waiting for other incoming RPCs. This can violate causality. For example, in a Pub/Sub program where one goroutine publishes and another subscribes, during replay the Subscribe call may finish before the Publish call begins.

For streaming RPCs, the Replayer delivers the result of Send and Recv calls in the order they were recorded. No attempt is made to match message contents.

At present, this package does not record or replay stream headers and trailers, or the result of the CloseSend method.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func Fprint

func Fprint(w io.Writer, filename string) error

Fprint reads the entries from filename and writes them to w in human-readable form. It is intended for debugging.

func FprintReader

func FprintReader(w io.Writer, r io.Reader) error

FprintReader reads the entries from r and writes them to w in human-readable form. It is intended for debugging.

Types

type Recorder

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

A Recorder records RPCs for later playback.

func NewRecorder

func NewRecorder(filename string, initial []byte) (*Recorder, error)

NewRecorder creates a recorder that writes to filename. The file will also store the initial bytes for retrieval during replay.

You must call Close on the Recorder to ensure that all data is written.

func NewRecorderWriter

func NewRecorderWriter(w io.Writer, initial []byte) (*Recorder, error)

NewRecorderWriter creates a recorder that writes to w. The initial bytes will also be written to w for retrieval during replay.

You must call Close on the Recorder to ensure that all data is written.

func (*Recorder) Close

func (r *Recorder) Close() error

Close saves any unwritten information.

func (*Recorder) DialOptions

func (r *Recorder) DialOptions() []grpc.DialOption

DialOptions returns the options that must be passed to grpc.Dial to enable recording.

type Replayer

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

A Replayer replays a set of RPCs saved by a Recorder.

func NewReplayer

func NewReplayer(filename string) (*Replayer, error)

NewReplayer creates a Replayer that reads from filename.

func NewReplayerReader

func NewReplayerReader(r io.Reader) (*Replayer, error)

NewReplayerReader creates a Replayer that reads from r.

func (*Replayer) Close

func (r *Replayer) Close() error

Close closes the Replayer.

func (*Replayer) DialOptions

func (r *Replayer) DialOptions() []grpc.DialOption

DialOptions returns the options that must be passed to grpc.Dial to enable replaying.

func (*Replayer) Initial

func (r *Replayer) Initial() []byte

Initial returns the initial state saved by the Recorder.

func (*Replayer) SetLogFunc

func (r *Replayer) SetLogFunc(f func(format string, v ...interface{}))

SetLogFunc sets a function to be used for debug logging. The function should be safe to be called from multiple goroutines.

Directories

Path Synopsis
proto
intstore
Package intstore is a generated protocol buffer package.
Package intstore is a generated protocol buffer package.
rpcreplay
Package rpcreplay is a generated protocol buffer package.
Package rpcreplay is a generated protocol buffer package.

Jump to

Keyboard shortcuts

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