errdare

package module
v0.1.0 Latest Latest
Warning

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

Go to latest
Published: May 31, 2018 License: BSD-3-Clause Imports: 4 Imported by: 0

README

errdare GoDoc Report card

Package errdare exemplifies some of the challenges of Go error handling by daring anyone to fix them.

go get github.com/mpvl/errdare

The easiest way to get going is to open dares_test.go, set dareOn to true, and fix the tests until they pass. See the errdare.go file or the godoc documentation for a description of each dare.

Documentation

Overview

Package errdare exemplifies some of the challenges of Go error handling by daring anyone to fix them.

go get github.com/mpvl/errdare

To fastest way to get started is to open dares_test.go, set dareOn to true, and fix the tests until they pass. See the errdare.go file or the godoc documentation for a description of each dare.

Index

Constants

This section is empty.

Variables

View Source
var PanicError = errtest.NewPanicError("user")

PanicError is an error that users may return if the IgnorePanicOrder option is set and a panic is detected.

Functions

func RunCloudStorage

func RunCloudStorage(t *testing.T, cfg *errtest.Config, f func(t *CloudStorage) error)

RunCloudStorage runs the CloudStorage dare as a test.

func RunPipeConvert

func RunPipeConvert(t *testing.T, cfg *errtest.Config, f func(t *PipeConvert, r Reader) error)

RunPipeConvert runs the PipeConvert dare as a test.

func RunTrickyCatch

func RunTrickyCatch(t *testing.T, cfg *errtest.Config, f func(t *TrickyCatch) error)

Types

type Aborter

type Aborter interface {
	Value
	io.Closer
	Abort(err error)
}

An Aborter is a Value with a Close and Abort method.

type Client

type Client interface {
	Value
	io.Closer
}

Client is a Value with a Close method.

type CloudStorage

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

The CloudStorage challenge: open the client, reader, and writer and copy the contents of the reader to the writer. Any error while copying the contents should result in a non-nil error being passed to the Writer's CloseWithError method.

A simplistic, but incorrect, implementation is:

func TestCloudStorage(t *testing.T) {
	errdare.RunCloudStorage(t, nil, func(tc *CloudStorage) error {
		c, err := tc.NewClient()
		if err != nil {
			return err
		}
		defer c.Close()

		r, err := tc.NewReader()
		if err != nil {
			return err
		}
		defer r.Close()

		w := tc.NewWriter(c)
		defer func() { w.CloseWithError(err) }()

		_, err = tc.Copy(w, r)
		return err
	})
}

func (*CloudStorage) Copy

func (c *CloudStorage) Copy(w Writer, r Reader) (n int, err error)

Copy takes a Reader and Writer and reports any error.

func (*CloudStorage) NewClient

func (c *CloudStorage) NewClient() (Client, error)

NewClient returns a client that must be closed. The error of the close may be ignored.

func (*CloudStorage) NewReader

func (c *CloudStorage) NewReader() (Reader, error)

NewReader returns a reader. The caller must call Close on the reader.

func (*CloudStorage) NewWriter

func (c *CloudStorage) NewWriter(client Client) Writer

NewWriter returns a writer. The caller must call CloseWithError with a non-nil value if there was any error.

type PipeConvert

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

The PipeConvert challenge: given a reader, wrap the reader in a scanner and copy the result of repeated scans into a newly created pipe. Return the reader passing it to Wait().

Source: https://github.com/cmars/represent/blob/e19ef73980e42e849cd026150516a5cdb9f827bc/pkg/represent/eol.go

An almost correct implementation is:

func TestPipeConvert(t *testing.T) {
	RunPipeConvert(t, skip, func(t *PipeConvert, r Reader) error {
		pipeReader, pipeWriter := t.Pipe()
		go func() {
			var err error
			defer func() { pipeWriter.CloseWithError(err) }()
			scanner := t.NewScanner(r)
			for t.Scan(scanner) {
				err = t.WriteScanned(pipeWriter, scanner)
				if err != nil {
					return
				}
			}
			err = t.ScanErr(scanner)
		}()
		return t.Wait(pipeReader)
	})
}

func (*PipeConvert) NewScanner

func (p *PipeConvert) NewScanner(r Reader) Value

NewScanner returns a new Scanner that readers from the Reader passed to the test.

func (*PipeConvert) Pipe

func (p *PipeConvert) Pipe() (Reader, Writer)

Pipe returns a Reader and Writer. The Writer must be closed upon completion. It must be closed with CloseWithError and a non-nil error if any error occurs. The Reader must be passed to Wait to await completion.

func (*PipeConvert) Scan

func (p *PipeConvert) Scan(scanner Value) bool

Scan must be called with the Scanner created from NewScanner until it returs false.

func (*PipeConvert) ScanErr

func (p *PipeConvert) ScanErr(scan Value) error

ScanErr must be called after the last call to Scan.

func (*PipeConvert) Wait

func (p *PipeConvert) Wait(r Reader) error

Wait must be called on the Reader returned from Pipe.

func (*PipeConvert) WriteScanned

func (p *PipeConvert) WriteScanned(w Writer, scanner Value) error

WriteScanned must be called after each successful call to Scan.

type Reader

type Reader interface {
	Value
	io.Closer
}

A Reader is a Value with a Close method.

type TrickyCatch

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

The TrickyCatch challenge: create a writer, wrap it, and write something to it. If any error occurs during writing or wrapping, the original writer should be called with CloseWithError. Any error encountered should be returned.

A simple, but incorrect implementation is:

func TestTrickyCatch(t *testing.T) {
	RunTrickyCatch(t, skip, func(t *TrickyCatch) (err error) {
		w, err := t.NewWriter()
		if err != nil {
			return err
		}
		defer func() { w.CloseWithError(err) }() // Close may return error, even if err is not

		ww, err := t.NewWrapper(w)
		if err != nil {
			return err
		}
		defer ww.Close() // must catch error, but may also panic.

		err = t.WriteSomething(ww)
		return err
	})
}

func (*TrickyCatch) NewWrapper

func (t *TrickyCatch) NewWrapper(w Writer) (Writer, error)

NewWrapper returns a Writer, given the Writer returned by NewWriter. It must be Closed and the error returned by the close must be observed.

func (*TrickyCatch) NewWriter

func (t *TrickyCatch) NewWriter() (Writer, error)

NewWriter returns a Writer. It must be closed with CloseWithError and a non-nil error if any error occurred.

func (*TrickyCatch) WriteSomething

func (t *TrickyCatch) WriteSomething(w Writer) error

WriteSomething writes something to the Writer returned by NewWrapper. It may return an error.

type Value

type Value interface {
	// contains filtered or unexported methods
}

Value is any value returned by a call.

type Writer

type Writer interface {
	Value
	io.Closer
	CloseWithError(err error) error
}

A Writer is a Value with a Close and CloseWithError method.

Directories

Path Synopsis

Jump to

Keyboard shortcuts

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