Documentation
¶
Overview ¶
Package vis draws a fuzzing run while it happens.
It attaches to the engine through fuzz.Observer, which hands out what happened and takes nothing back, so nothing here can change what the fuzzer explores. The determinism gate in internal/fuzz proves that for the seam and the gate in this package proves it for the whole display: one seed, drawn and undrawn, has to produce the same trace.
The design position is that the truth is the spectacle. Every mark maps to something the engine did: a tape cell is one action, a dot is one registered invariant, a funnel bar is one shrink candidate at its real length. There is no progress bar, because a fuzzer has no denominator; no coverage figure, because nothing measures coverage; and no idle animation, because motion on this screen means work happened.
Index ¶
- Constants
- func Fits(w, h int) bool
- func Render(s Snapshot, o Options) string
- type Attempt
- type Class
- type Display
- func (d *Display) Close()
- func (s Display) Done(r fuzz.Result)
- func (d *Display) Frame() string
- func (d *Display) Open()
- func (s Display) Rule(_ int, rule string, ok bool)
- func (s Display) Shrink(pass string, size int, accepted bool)
- func (s Display) Start(seed uint64, steps int)
- func (s Display) Step(i int, a fuzz.Action, vs []fuzz.Violation)
- type Options
- type Phase
- type Snapshot
Constants ¶
const ( DefaultFPS = 30 DefaultBatch = 12 // MinWidth and MinHeight are the smallest frame worth drawing. Below this // the rail alone does not fit and visual mode declines rather than showing // a mangled instrument. MinWidth = 60 MinHeight = 20 )
Cadence defaults. Thirty frames a second is what a terminal recording wants; over thousands of actions a second nothing on the tape is legible at that rate, which is what per-batch is for: it draws every N actions, so the tape advances a readable amount per frame and the recording is watchable.
Variables ¶
This section is empty.
Functions ¶
Types ¶
type Class ¶
type Class struct {
// Letter is the tape glyph. One cell, ASCII, so the tape survives both the
// ASCII pass and a small recording.
Letter string
Name string
Kinds []fuzz.Kind
}
Class is one row of the mix histogram and one glyph on the tape.
func DefaultClasses ¶
func DefaultClasses() []Class
DefaultClasses partitions the action alphabet. Order is the order the mix histogram lists them.
type Display ¶
type Display struct {
// contains filtered or unexported fields
}
Display is the observer and the renderer. It implements fuzz.Observer.
func (*Display) Close ¶
func (d *Display) Close()
Close stops the renderer, draws one last frame so the end card is what the recording ends on, and restores the terminal.
func (*Display) Frame ¶
Frame renders the current state. It is what the tests and the frame captures call, and it is the same function the renderer uses, so a capture is the frame a viewer sees rather than a reconstruction of one.
func (*Display) Open ¶
func (d *Display) Open()
Open begins drawing. Frames go out on whichever cadence Options set.
It is not called Start because Start is the observer's own lifecycle event, and a display whose renderer shadowed it would quietly stop being an Observer: the interface would still be satisfied by the embedded state, but the engine's Start would go to the wrong method.
type Options ¶
type Options struct {
// Rules is the target's invariant registry, in the order it checks them.
// The display never invents a name: with no registry it draws no matrix.
Rules []fuzz.RuleInfo
// Classes groups the action alphabet for the tape and the mix. Nil takes
// DefaultClasses.
Classes []Class
Out io.Writer
Width, Height int
// FPS draws on a wall-clock cadence. Batch draws every N actions instead,
// and wins when both are set.
FPS int
Batch int
ASCII bool
Mono bool
// Screen supplies the app under test's current frame for the viewport. It
// is pulled on the renderer's cadence rather than pushed, so a display that
// is not drawing costs the target nothing. Nil drops the viewport and the
// instruments take the whole frame, which is still the whole truth.
Screen func() string
// Command is the invocation the end card prints so a reader can reproduce
// the run. It is shown verbatim, so it has to be the real one.
Command string
}
Options configures a display. Every field has a working default, so the zero value plus a rule registry is a usable display.
type Phase ¶
type Phase int
Phase is what the engine is doing, derived from the events rather than reported: the first Shrink call means minimisation started, Done means it stopped. Nothing on screen claims a phase the engine did not enter.
type Snapshot ¶
type Snapshot struct {
Rules []fuzz.RuleInfo
Classes []Class
Seed uint64
Steps int
Elapsed time.Duration
Actions int
Checks int
Rate float64
Tape [tapeCap]uint8
Head int
ViolationCell int
Ledger [ledgerCap]fuzz.Action
LedgerN int
Mix []int
Broken []bool
Violated bool
FailedRule fuzz.RuleInfo
FailedStep int
Detail string
Phase Phase
InitialLen int
BestLen int
Runs []Attempt
RunsSeen int
Elided int
Done bool
Result fuzz.Result
}
Snapshot is a consistent copy of the state for one frame. It is a value so the renderer can work on it with no lock held, which is what keeps a slow terminal from ever showing up as engine latency.