github.com/philpearl/plenc@v0.0.15/plenccodec/descriptor_test.go (about)

     1  package plenccodec_test
     2  
     3  import (
     4  	_ "embed"
     5  	"encoding/json"
     6  	"reflect"
     7  	"testing"
     8  	"time"
     9  
    10  	"github.com/google/go-cmp/cmp"
    11  	"github.com/philpearl/plenc"
    12  	"github.com/philpearl/plenc/plenccodec"
    13  )
    14  
    15  //go:embed descriptor_test.json
    16  var expTestDescriptor string
    17  
    18  func TestDescriptor(t *testing.T) {
    19  	type sub struct {
    20  		A int8   `plenc:"1"`
    21  		B string `plenc:"2"`
    22  	}
    23  
    24  	// maps are rendered as a list of keys and values because maps like this
    25  	// don't have a valid JSON representation
    26  	type mykey struct {
    27  		A int `plenc:"1"`
    28  		B int `plenc:"2"`
    29  	}
    30  	type mymap map[mykey]string
    31  
    32  	type my struct {
    33  		A int                 `plenc:"1"`
    34  		B float32             `plenc:"2"`
    35  		C string              `plenc:"3"`
    36  		D uint                `plenc:"4"`
    37  		E []float64           `plenc:"5"`
    38  		F []sub               `plenc:"6"`
    39  		G [][]uint32          `plenc:"7"`
    40  		H [][]float32         `plenc:"8"`
    41  		I *uint               `plenc:"9"`
    42  		J mymap               `plenc:"10"`
    43  		K []byte              `plenc:"11"`
    44  		L map[float32]float32 `plenc:"12"`
    45  		M *int                `plenc:"13"`
    46  		N time.Time           `plenc:"14"`
    47  		O bool                `plenc:"15" json:"elephant"`
    48  		P map[string]any      `plenc:"16"`
    49  		Q int32               `plenc:"17,flat"`
    50  		R time.Time           `plenc:"18,flattime"`
    51  		S map[string]int      `plenc:"19"`
    52  	}
    53  
    54  	plenc.RegisterCodec(reflect.TypeOf(map[string]any{}), plenccodec.JSONMapCodec{})
    55  	plenc.RegisterCodec(reflect.TypeOf([]any{}), plenccodec.JSONArrayCodec{})
    56  	plenc.RegisterCodecWithTag(reflect.TypeOf(time.Time{}), "flattime", plenccodec.BQTimestampCodec{})
    57  
    58  	c, err := plenc.CodecForType(reflect.TypeOf(my{}))
    59  	if err != nil {
    60  		t.Fatal(err)
    61  	}
    62  	d := c.Descriptor()
    63  
    64  	// Check we can encode and decode a Descriptor!
    65  	descData, err := plenc.Marshal(nil, &d)
    66  	if err != nil {
    67  		t.Fatal(err)
    68  	}
    69  	var dd plenccodec.Descriptor
    70  	if err := plenc.Unmarshal(descData, &dd); err != nil {
    71  		t.Fatal(err)
    72  	}
    73  	if diff := cmp.Diff(d, dd); diff != "" {
    74  		t.Fatal(diff)
    75  	}
    76  
    77  	// Now test we can use the descriptor
    78  	var seven uint = 7
    79  	in := my{
    80  		A: 1,
    81  		B: 3.7,
    82  		C: "this is my hat",
    83  		D: 9898,
    84  		E: []float64{1, 2.3, 3.7},
    85  		F: []sub{
    86  			{A: 1, B: "one"},
    87  			{A: 2, B: "two"},
    88  			{A: 3},
    89  		},
    90  		G: [][]uint32{
    91  			{1, 2},
    92  			{3, 4},
    93  		},
    94  		H: [][]float32{
    95  			{1, 2},
    96  			{3, 4},
    97  		},
    98  		I: &seven,
    99  		J: mymap{
   100  			mykey{A: 9, B: 4}: "nine",
   101  		},
   102  		K: []byte{0, 1, 2, 3},
   103  		// Map order is random, so we'll just have one entry in the map. I have
   104  		// tested with two!
   105  		L: map[float32]float32{
   106  			3.14: 13.37,
   107  		},
   108  		N: time.Date(1970, 3, 15, 0, 0, 0, 1337e5, time.UTC),
   109  		O: true,
   110  		P: map[string]any{
   111  			"array": []any{1, 1.3, "cheese", json.Number("1337")},
   112  		},
   113  		Q: 123,
   114  		R: time.Date(1970, 3, 15, 0, 0, 0, 1337e5, time.UTC),
   115  		S: map[string]int{
   116  			"one": 1,
   117  			"two": 2,
   118  		},
   119  	}
   120  
   121  	data, err := plenc.Marshal(nil, in)
   122  	if err != nil {
   123  		t.Fatal(err)
   124  	}
   125  
   126  	{
   127  		// Check we can decode that plenc
   128  		var out my
   129  		if err := plenc.Unmarshal(data, &out); err != nil {
   130  			t.Fatal(err)
   131  		}
   132  		if diff := cmp.Diff(in, out); diff != "" {
   133  			t.Fatal(diff)
   134  		}
   135  	}
   136  
   137  	var j plenccodec.JSONOutput
   138  
   139  	if err := d.Read(&j, data); err != nil {
   140  		t.Fatal(err, string(j.Done()))
   141  	}
   142  	out := string(j.Done())
   143  
   144  	if diff := cmp.Diff(expTestDescriptor, out); diff != "" {
   145  		t.Log(out)
   146  		t.Fatal(diff)
   147  	}
   148  }