coverage

package
v0.0.0-...-1dd1f65 Latest Latest
Warning

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

Go to latest
Published: Feb 26, 2023 License: MIT Imports: 25 Imported by: 0

Documentation

Overview

Package coverage contains helpers for building compiler coverage reports.

Index

Examples

Constants

View Source
const (
	// DefaultCount is the default value for the Count quantity.
	DefaultCount = 1000
	// DefaultNWorkers is the default value for the NWorkers quantity.
	DefaultNWorkers = 10
)

Variables

View Source
var (

	// ErrNoArch occurs when we try to run a lifted fuzzer for coverage and haven't a target architecture.
	ErrNoArch = errors.New("this runner needs an architecture set, but got none")
	// ErrNoFuzzer occurs when we try to run a lifted fuzzer for coverage but the fuzzer is nil.
	ErrNoFuzzer = errors.New("this runner needs a fuzzer, but got none")
	// ErrNoLifter occurs when we try to run a lifted fuzzer for coverage but the lifter is nil.
	ErrNoLifter = errors.New("this runner needs a lifter, but got none")
	// ErrNoStatDumper occurs when we try to run a lifted fuzzer for coverage but the statistic dumper is nil.
	ErrNoStatDumper = errors.New("this runner needs a lifter, but got none")
	// ErrNoInput occurs when we try to run a mutating fuzzer for coverage and haven't any input to feed it.
	ErrNoInput = errors.New("this runner needs input testcases, but got none")
)
View Source
var (
	// ErrNeedBackend occurs when we try to instantiate a runner for a known-fuzzer profile without a backend.
	ErrNeedBackend = errors.New("need backend information for this profile")

	// ErrNeedRunInfo occurs when we try to instantiate a runner for a standalone profile without run information.
	ErrNeedRunInfo = errors.New("need run information for this profile")

	// ErrUnsupportedProfileKind occurs when we try to instantiate a runner for an unsupported profile type.
	ErrUnsupportedProfileKind = errors.New("this profile kind can't be run yet")
)
View Source
var ErrConfigNil = errors.New("supplied config is nil")

ErrConfigNil is produced when we supply a null pointer to OptionsFromConfig.

View Source
var ErrUnknownProfileKind = errors.New("unknown profile kind")

ErrUnknownProfileKind is an error that occurs if we try to unmarshal an unknown profile kind.

Functions

func OnCoverageRun

func OnCoverageRun(rm RunMessage, o ...Observer)

OnCoverageRun broadcasts run message rm to all observers o.

Types

type Bucket

type Bucket struct {
	// Name is the name of the bucket, in the form "[0-9]+(,[0-9]+)*".
	Name string
	// Size is the size of the bucket.
	Size int
}

Bucket is the type of coverage buckets.

func (Bucket) String

func (b Bucket) String() string

String gets a string representation of this bucket.

type Config

type Config struct {
	// Paths contains the input and output pathsets for the coverage generator.
	Paths config.Pathset `toml:"paths"`

	// Quantities contains quantities for the coverage generator.
	Quantities QuantitySet `toml:"quantities"`

	// Profiles contains the list of coverage profiles to use.
	Profiles map[string]Profile `toml:"profiles"`
}

Config gathers the configuration present in coverage generator config files.

func LoadConfigFromFile

func LoadConfigFromFile(path string) (*Config, error)

LoadConfigFromFile loads a coverage configuration from the filepath path.

func (*Config) MakeMaker

func (cfg *Config) MakeMaker(o ...Option) (*Maker, error)

MakeMaker makes a maker using the configuration in cfg.

type FuzzRunner

type FuzzRunner struct {
	// TODO(@MattWindsor91): this overlaps with Env in director.
	// Fuzzer is the fuzzer this fuzz runner uses.
	Fuzzer fuzzer.SingleFuzzer
	// Lifter is the lifter this fuzz runner uses.
	Lifter backend.SingleLifter
	// StatDumper is the statistics dumper this fuzz runner uses between fuzzing and lifting.
	StatDumper litmus.StatDumper
	// Config is the configuration to pass to the fuzz runner.
	Config *fuzzer2.Config

	// Arch is the architecture that the lifting process should target.
	Arch id.ID
	// Runner should be the service runner to use when invoking the lifter.
	Runner service.Runner
}

FuzzRunner is a coverage runner that uses the c4f fuzzer.

func (*FuzzRunner) Run

func (f *FuzzRunner) Run(ctx context.Context, rc RunContext) error

type Maker

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

Maker contains state used by the coverage testbed maker.

func NewMaker

func NewMaker(outDir string, profiles map[string]Profile, opts ...Option) (*Maker, error)

NewMaker constructs a new coverage testbed maker.

func (*Maker) Run

func (m *Maker) Run(ctx context.Context) error

type Observer

type Observer interface {
	// OnCoverageRun announces that a coverage run is starting, stopping, or progressing.
	OnCoverageRun(rm RunMessage)
}

Observer is the interface of types that can observe the progress of a coverage testbed generator.

type Option

type Option func(*Maker) error

Option is the type of options to supply to the coverage testbed maker's constructor.

func AddInputs

func AddInputs(paths ...string) Option

AddInputs adds paths to the input list.

func ObserveWith

func ObserveWith(o ...Observer) Option

ObserveWith adds each observer o into the observer list.

func Options

func Options(opts ...Option) Option

Options applies each option in opts successively.

func OptionsFromConfig

func OptionsFromConfig(cfg *Config) Option

func OverrideQuantities

func OverrideQuantities(qs QuantitySet) Option

OverrideQuantities overrides the maker's quantity set with qs.

func SendStderrTo

func SendStderrTo(w io.Writer) Option

SendStderrTo redirects stderr from commands to w.

func UseBackendResolver

func UseBackendResolver(r backend.Resolver) Option

UseBackendResolver adds support for r as the source of backends.

func UseFuzzer

func UseFuzzer(f fuzzer.SingleFuzzer) Option

UseFuzzer adds support for f as a 'known' fuzzer.

func UseStatDumper

func UseStatDumper(d litmus.StatDumper) Option

UseStatDumper adds support for d as the statistics dumper.

type Profile

type Profile struct {
	// Kind specifies the type of fuzzer profile this is.
	Kind ProfileKind `toml:"kind"`

	// Arch is the target architecture for the profile, if it uses one.
	Arch id.ID `toml:"arch"`

	// Backend directly feeds in the target backend for the profile, if it uses one.
	Backend *backend.Spec `toml:"backend"`

	// Run specifies, if this is a standalone profile, how to run the generator.
	Run *service.RunInfo `toml:"run"`

	// Fuzz specifies a fuzzer configuration to use if this is an known-fuzzer profile.
	Fuzz *fuzzer2.Config `toml:"fuzz"`

	// Runner specifies an overridden runner for the profile; this is basically useful only for testing.
	Runner Runner
}

Profile tells the coverage generator how to set up a particular coverage profile.

type ProfileKind

type ProfileKind uint8

ProfileKind is the enumeration of kinds of coverage profile.

const (
	// Known is a profile kind that tells the coverage generator to run a mutating fuzzer known to it.
	// At time of writing, there is only one such fuzzer (c4f-fuzz).
	Known ProfileKind = iota
	// Standalone is a profile kind that tells the coverage generator to run an external, stand-alone fuzzer.
	Standalone
	// LastProfileKind represents the last profile kind.
	LastProfileKind = Standalone
)

func (ProfileKind) MarshalText

func (i ProfileKind) MarshalText() (text []byte, err error)

MarshalText marshals a profile kind to text by using its string representation.

func (ProfileKind) String

func (i ProfileKind) String() string

func (*ProfileKind) UnmarshalText

func (i *ProfileKind) UnmarshalText(text []byte) error

UnmarshalText tries to unmarshal a profile kind from text.

type QuantitySet

type QuantitySet struct {
	// Count is the number of subjects to fuzz for each profile.
	Count int `toml:"count"`

	// Divisions specifies how to divide Count subjects into buckets.
	// Divisions behave recursively: each subsequent level of division gets applied to the first bucket in the
	// previous level.
	Divisions []int `toml:"divisions"`

	// NWorkers is the number of workers to spawn in the worker pool.
	NWorkers int
}

QuantitySet contains the quantities tracked by the coverage generator.

func (*QuantitySet) Buckets

func (q *QuantitySet) Buckets() []Bucket

Buckets calculates the set of buckets that should be constructed for the coverage setup. Buckets are allocated recursively according to the divisions set in the quantity set; each division carves the first bucket from the previous division into that many sub-buckets. Buckets always appear in reverse order, from highest outer bucket to lowest inner bucket.

Example

ExampleQuantitySet_Buckets is a runnable example for QuantitySet.Buckets.

package main

import (
	"fmt"

	"github.com/c4-project/c4t/internal/coverage"
)

func main() {
	qs := coverage.QuantitySet{Count: 1000, Divisions: []int{4, 5}}
	for _, b := range qs.Buckets() {
		fmt.Println(b)
	}

}
Output:

4[250]
3[250]
2[250]
1_5[50]
1_4[50]
1_3[50]
1_2[50]
1_1[50]
Example (NoDivision)

ExampleQuantitySet_Buckets is a runnable example for QuantitySet.Buckets where there is no division.

package main

import (
	"fmt"

	"github.com/c4-project/c4t/internal/coverage"
)

func main() {
	qs := coverage.QuantitySet{Count: 1000, Divisions: []int{}}
	for _, b := range qs.Buckets() {
		fmt.Println(b)
	}

}
Output:

1[1000]
Example (Uneven)

ExampleQuantitySet_Buckets_uneven is a runnable example for QuantitySet.Buckets when there is uneven division.

package main

import (
	"fmt"

	"github.com/c4-project/c4t/internal/coverage"
)

func main() {
	qs := coverage.QuantitySet{Count: 1000, Divisions: []int{3, 3}}
	for _, b := range qs.Buckets() {
		fmt.Println(b)
	}

}
Output:

3[333]
2[333]
1_3[111]
1_2[111]
1_1[112]

func (*QuantitySet) Override

func (q *QuantitySet) Override(other QuantitySet)

Override overrides this quantity set with the non-zero fields of other.

type RunContext

type RunContext struct {
	// Seed is the seed to use to drive any random parts of the coverage runner.
	Seed int32
	// BucketDir is the filepath to the bucket directory into which the coverage runner should output its recipe.
	BucketDir string
	// NumInBucket is the index of this single instance in its bucket.
	NumInBucket int
	// Input points to an input subject for the coverage runner, if any are available.
	Input *subject.Subject
}

RunContext is the type of state provided to a coverage runner.

func (RunContext) ExpandArgs

func (r RunContext) ExpandArgs(arg ...string) []string

ExpandArgs expands various special identifiers in args to parts of the runner context.

Example

ExampleRunContext_ExpandArgs is a runnable example for RunContext.ExpandArgs.

package main

import (
	"fmt"
	"path/filepath"

	"github.com/c4-project/c4t/internal/coverage"
	"github.com/c4-project/c4t/internal/model/litmus"
	"github.com/c4-project/c4t/internal/subject"
)

func main() {
	rc := coverage.RunContext{
		Seed:        8675309,
		BucketDir:   "bucket1,1",
		NumInBucket: 42,
		Input:       subject.NewOrPanic(litmus.NewOrPanic("foo/bar.litmus")),
	}
	args := rc.ExpandArgs("-seed", "${seed}", "-o", "${outputDir}/${i}.c", "${input}")
	for _, arg := range args {
		fmt.Println(filepath.ToSlash(arg))
	}

}
Output:

-seed
8675309
-o
bucket1,1/42.c
foo/bar.litmus

func (RunContext) LiftOutDir

func (r RunContext) LiftOutDir() string

LiftOutDir is a suggested output directory for backend lifts in this runner context.

func (RunContext) OutLitmus

func (r RunContext) OutLitmus() string

OutLitmus is a suggested filename for Litmus outputs of this runner context.

type RunMessage

type RunMessage struct {
	observing.Batch

	// ProfileName contains the runner profile name on start and stop messages.
	ProfileName string

	// Profile contains the runner profile on start messages.
	Profile *Profile

	// Context contains the runner context on step messages.
	Context *RunContext
}

RunMessage is the type of messages announcing coverage run progress.

func RunEnd

func RunEnd(pname string) RunMessage

RunEnd announces that a coverage run is ending for the profile named pname.

func RunStart

func RunStart(pname string, p Profile, nruns int) RunMessage

RunStart constructs a message stating that a coverage run of size nruns is starting using profile p (named pname).

func RunStep

func RunStep(pname string, i int, rc RunContext) RunMessage

RunStep announces that a coverage run instance, number i, in profile pname and with runner context rc, is starting.

type Runner

type Runner interface {
	// Run runs the Runner with context ctx and runner context rc.
	Run(ctx context.Context, rc RunContext) error
}

Runner is the interface of things that can be run to generate coverage testbeds.

type StandaloneRunner

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

StandaloneRunner is a coverage runner that runs a standalone binary.

func (*StandaloneRunner) Run

Run runs the standalone runner.

Directories

Path Synopsis

Jump to

Keyboard shortcuts

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