package commontest import ( "regexp" "testing" "github.com/stretchr/testify/require" ) // 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 } // Run runs the test suite. func (s WriterTestSuite) Run(t *testing.T) { tf := testFactory{ valueTestFactory: s.ValueTestFactory, encodingBehavior: encodingBehavior{ encodeAsHex: s.EncodeAsHex, }, } tds := tf.MakeAllValueTests() for _, td := range tds { t.Run(td.name, func(t *testing.T) { c := s.ContextFactory() t.Cleanup(func() { if t.Failed() { t.Logf("JSON output: `%s`", string(c.JSONData())) } }) require.NoError(t, td.action(c)) output := string(c.JSONData()) require.Regexp(t, makeOutputRegex(td.encoding), output) }) } } // Make a regex that will allow any amount of whitespace between the matched substrings. func makeOutputRegex(outputParts []string) *regexp.Regexp { regex := "\\w*" for _, outputPart := range outputParts { regex += regexp.QuoteMeta(outputPart) regex += "\\w*" } return regexp.MustCompile(regex) }