...

Source file src/github.com/launchdarkly/go-jsonstream/v3/jwriter/token_writer_test.go

Documentation: github.com/launchdarkly/go-jsonstream/v3/jwriter

     1  package jwriter
     2  
     3  import (
     4  	"encoding/json"
     5  	"fmt"
     6  	"strconv"
     7  	"testing"
     8  
     9  	"github.com/launchdarkly/go-jsonstream/v3/internal/commontest"
    10  )
    11  
    12  // This uses the framework defined in WriterTestSuite to exercise any TokenWriter implementation
    13  // with a large number of JSON output permutations.
    14  
    15  type tokenWriterTestContext struct {
    16  	tw        *tokenWriter
    17  	getOutput func() []byte
    18  }
    19  
    20  type tokenWriterValueTestFactory struct{}
    21  
    22  const (
    23  	writeNumberAsInt commontest.ValueVariant = "int:"
    24  )
    25  
    26  var (
    27  	variantsForScalarValues   = []commontest.ValueVariant{"", commontest.UntypedVariant}
    28  	variantsForWritingNumbers = []commontest.ValueVariant{"", writeNumberAsInt, commontest.UntypedVariant}
    29  )
    30  
    31  type tokenWriterTestSuite struct {
    32  	Factory     func() (*tokenWriter, func() []byte)
    33  	EncodeAsHex func(rune) bool
    34  }
    35  
    36  func TestTokenWriter(t *testing.T) {
    37  	s := tokenWriterTestSuite{
    38  		Factory: func() (*tokenWriter, func() []byte) {
    39  			tw := newTokenWriter()
    40  			return &tw, tw.Bytes
    41  		},
    42  	}
    43  	s.Run(t)
    44  }
    45  
    46  func (s tokenWriterTestSuite) Run(t *testing.T) {
    47  	ws := commontest.WriterTestSuite{
    48  		ContextFactory: func() commontest.TestContext {
    49  			tw, getOutput := s.Factory()
    50  			return &tokenWriterTestContext{
    51  				tw:        tw,
    52  				getOutput: getOutput,
    53  			}
    54  		},
    55  		ValueTestFactory: tokenWriterValueTestFactory{},
    56  		EncodeAsHex:      tokenWriterWillEncodeAsHex,
    57  	}
    58  	ws.Run(t)
    59  }
    60  
    61  func (c tokenWriterTestContext) JSONData() []byte { return c.getOutput() }
    62  
    63  func (f tokenWriterValueTestFactory) EOF() commontest.Action {
    64  	return func(c commontest.TestContext) error { return nil }
    65  }
    66  
    67  func (f tokenWriterValueTestFactory) Variants(value commontest.AnyValue) []commontest.ValueVariant {
    68  	// Integer values can be written using either Int() or Float64().
    69  	if value.Kind == commontest.NumberValue && float64(int(value.Number)) == value.Number {
    70  		return variantsForWritingNumbers
    71  	}
    72  	if value.Kind != commontest.ArrayValue && value.Kind != commontest.ObjectValue {
    73  		return variantsForScalarValues
    74  	}
    75  	return nil
    76  }
    77  
    78  func (f tokenWriterValueTestFactory) Value(value commontest.AnyValue, variant commontest.ValueVariant) commontest.Action {
    79  	return func(c commontest.TestContext) error {
    80  		ctx := c.(*tokenWriterTestContext)
    81  		tw := ctx.tw
    82  
    83  		switch value.Kind {
    84  		case commontest.NullValue:
    85  			if variant == commontest.UntypedVariant {
    86  				return tw.Raw(json.RawMessage(`null`))
    87  			}
    88  			return tw.Null()
    89  
    90  		case commontest.BoolValue:
    91  			if variant == commontest.UntypedVariant {
    92  				return tw.Raw(json.RawMessage(fmt.Sprintf("%t", value.Bool)))
    93  			}
    94  			return tw.Bool(value.Bool)
    95  
    96  		case commontest.NumberValue:
    97  			if variant == commontest.UntypedVariant {
    98  				return tw.Raw(json.RawMessage(strconv.FormatFloat(value.Number, 'f', -1, 64)))
    99  			}
   100  			if variant == writeNumberAsInt {
   101  				return tw.Int(int(value.Number))
   102  			} else {
   103  				return tw.Float64(value.Number)
   104  			}
   105  
   106  		case commontest.StringValue:
   107  			if variant == commontest.UntypedVariant {
   108  				// Use our own encoder to encode the string, but then write it with Raw()
   109  				tw1 := newTokenWriter()
   110  				_ = tw1.String(value.String)
   111  				return tw.Raw(json.RawMessage(tw1.Bytes()))
   112  			}
   113  			return tw.String(value.String)
   114  
   115  		case commontest.ArrayValue:
   116  			if err := tw.Delimiter('['); err != nil {
   117  				return err
   118  			}
   119  			first := true
   120  			for _, e := range value.Array {
   121  				if !first {
   122  					if err := tw.Delimiter(','); err != nil {
   123  						return err
   124  					}
   125  				}
   126  				first = false
   127  				if err := e(c); err != nil {
   128  					return err
   129  				}
   130  			}
   131  			return tw.Delimiter(']')
   132  
   133  		case commontest.ObjectValue:
   134  			if err := tw.Delimiter('{'); err != nil {
   135  				return err
   136  			}
   137  			first := true
   138  			for _, p := range value.Object {
   139  				if !first {
   140  					if err := tw.Delimiter(','); err != nil {
   141  						return err
   142  					}
   143  				}
   144  				first = false
   145  				if err := tw.String(p.Name); err != nil {
   146  					return err
   147  				}
   148  				if err := tw.Delimiter(':'); err != nil {
   149  					return err
   150  				}
   151  				if err := p.Action(c); err != nil {
   152  					return err
   153  				}
   154  			}
   155  			return tw.Delimiter('}')
   156  		}
   157  		return nil
   158  	}
   159  }
   160  

View as plain text