...

Package commontest

import "github.com/launchdarkly/go-jsonstream/v3/internal/commontest"
Overview
Index

Overview ▾

Package commontest provides test logic for JSON reading and writing.

To ensure that the go-jsonstream types perform correctly with a wide range of inputs and outputs, we generate many permutations (single scalar values of various types; numbers in different formats; strings with or without escape characters at different positions; arrays and objects with different numbers of elements/properties) which are tested for both readers and writers. For readers, we also test various permutations of invalid input.

Reader and writer tests are run against the high-level APIs (Reader, Writer) and the default implementations of the low-level APIs (tokenReader, tokenWriter).

Constants

const (
    ExampleStructStringFieldName             = "string"
    ExampleStructIntFieldName                = "int"
    ExampleStructOptBoolAsInterfaceFieldName = "optBool"
)

Variables

var (
    ExampleStructData               = []byte(`{"string":"s","int":3,"optBool":true}`)
    ExampleStructValue              = ExampleStruct{StringField: "s", IntField: 3, OptBoolAsInterfaceField: true}
    ExampleStructRequiredFieldNames = []string{ExampleStructStringFieldName, ExampleStructIntFieldName}
)

func AssertEqual

func AssertEqual(expected, actual interface{}) error

func AssertNoErrors

func AssertNoErrors(errs ...error) error

func AssertTrue

func AssertTrue(value bool, failureMessage string) error

func MakeBools

func MakeBools() []bool

func MakeBoolsJSON

func MakeBoolsJSON(bools []bool) []byte

func MakeStrings

func MakeStrings() []string

func MakeStringsJSON

func MakeStringsJSON(strings []string) []byte

func MakeStructsJSON

func MakeStructsJSON(structs []ExampleStruct) []byte

func MakeWhitespaceOptions

func MakeWhitespaceOptions() map[string]string

type Action

Action is an arbitrary action that can be executed during a test. For readers, this normally consists of trying to read some type of value from the input, and asserting that no error occurred and that the expected value was found. For writers, it consists of trying to write something to the output.

All test assertions should return early on any non-nil error.

type Action func(c TestContext) error

type AnyValue

type AnyValue struct {
    Kind   ValueKind
    Bool   bool
    Number float64
    String string
    Array  []Action
    Object []PropertyAction
}

type ExampleStruct

type ExampleStruct struct {
    StringField             string      `json:"string"`
    IntField                int         `json:"int"`
    OptBoolAsInterfaceField interface{} `json:"optBool"`
}

func MakeStructs

func MakeStructs() []ExampleStruct

type PropertyAction

PropertyAction is used in the context of a JSON object value, describing a property name and the Action for reading or writing the property value.

type PropertyAction struct {
    Name   string
    Action Action
}

type ReadErrorTestFactory

ReadErrorTestFactory is an interface for use with ReaderTestSuite to generate expectations about how errors are reported.

type ReadErrorTestFactory interface {
    ExpectEOFError(err error) error
    ExpectWrongTypeError(err error, expectedType ValueKind, variant ValueVariant, gotType ValueKind) error
    ExpectSyntaxError(err error) error
}

type ReaderTestSuite

ReaderTestSuite runs a standard set of tests against some implementation of JSON reading. This allows us to test both jreader.Reader and the low-level tokenizer jreader.tokenReader with many permutations of valid and invalid input.

type ReaderTestSuite struct {
    // ContextFactory must be provided by the caller to create an implementation of TestContext for
    // running a parsing test on the specified JSON input. This should include whatever parser
    // object will be used by the Actions that the ValueTestFactory creates.
    ContextFactory func(input []byte) TestContext

    // ValueTestFactory must be provided by the caller to create implementations of Action for
    // various JSON value types.
    ValueTestFactory ValueTestFactory

    // ReadErrorTestFactory must be provided by the caller to define expectations about error
    // reporting for invalid input.
    ReadErrorTestFactory ReadErrorTestFactory
}

func (ReaderTestSuite) Run

func (s ReaderTestSuite) Run(t *testing.T)

Run runs the test suite.

type TestContext

TestContext is an abstraction used by ReaderTestSuite and WriterTestSuite.

type TestContext interface {
    // JSONData returns either (for readers) the input data that was passed in when the TestContext
    // was created, or (for writers) all of the output that has been produced so far.
    JSONData() []byte
}

type ValueKind

type ValueKind int
const (
    NullValue   ValueKind = iota
    BoolValue   ValueKind = iota
    NumberValue ValueKind = iota
    StringValue ValueKind = iota
    ArrayValue  ValueKind = iota
    ObjectValue ValueKind = iota
)

type ValueTestFactory

ValueTestFactory is an interface for producing specific reader/writer test actions. To test any reader or writer with ReaderTestSuite or WriterTestSuite, provide an implementation of this interface that performs the specified actions.

type ValueTestFactory interface {
    EOF() Action
    Value(value AnyValue, variant ValueVariant) Action
    Variants(value AnyValue) []ValueVariant
}

type ValueVariant

ValueVariant is an optional identifier that ValueTestFactory can use to make the tests produce multiple variations of value tests. See ValueTestFactory.Variants.

type ValueVariant string
const (
    // This variant means that the reader will try to consume a JSON value without regard to its type,
    // or the writer will write it as raw JSON data.
    UntypedVariant ValueVariant = "any:"

    // This variant means that the reader will try to recursively skip past a JSON value of any type.
    SkipValueVariant ValueVariant = "skip:"
)

type WriterTestSuite

WriterTestSuite runs a standard set of tests against some implementation of JSON writing. This allows us to test both jwriter.Writer and the low-level JSON formatter jwriter.tokenWriter with many permutations of output data.

type WriterTestSuite struct {
    // ContextFactory must be provided by the caller to create an implementation of TestContext for
    // running a writing test on some set of JSON data. This should include whatever writer object
    // will be used by the Actions that the ValueTestFactory creates.
    ContextFactory func() TestContext

    // ValueTestFactory must be provided by the caller to create implementations of Action for
    // various JSON value types.
    ValueTestFactory ValueTestFactory

    // EncodeAsHex must be provided by the caller to define expectations about whether this writer
    // will use a \uNNNN escape sequence for the specified Unicode character. There is no single
    // correct answer for all implementations, since JSON allows characters to be escaped in
    // several ways and also allows unescaped multi-byte characters.
    EncodeAsHex func(rune) bool
}

func (WriterTestSuite) Run

func (s WriterTestSuite) Run(t *testing.T)

Run runs the test suite.