internal/control/output_test.go
57 lines · 1969 bytes
1package control
2
3import (
4 "encoding/json"
5 "reflect"
6 "testing"
7)
8
9// TestNamedPayloadsRoundTrip asserts that every named payload survives a
10// marshal/unmarshal cycle with no field lost. A field added to the struct
11// but given no JSON tag, or given one that collides with another, drops
12// silently: the command still emits, the client still decodes, and the
13// value is simply missing. This is the failure #126 is about.
14func TestNamedPayloadsRoundTrip(t *testing.T) {
15 payloads := []any{
16 &Created{}, &MRCreated{}, &IssueShow{}, &MRShow{},
17 &BuildOut{}, &JobOut{}, &ProfileOut{}, &ProfileRepo{}, &ProfileMember{},
18 &DashboardOut{}, &DashboardItem{}, &DashboardBuild{}, &PinnedOut{},
19 &FeedOut{}, &ActivityDay{}, &SearchResult{}, &ReviewOut{}, &CheckOut{}, &CommitOut{},
20 }
21 for _, p := range payloads {
22 name := reflect.TypeOf(p).Elem().Name()
23 raw, err := json.Marshal(p)
24 if err != nil {
25 t.Errorf("%s does not marshal: %v", name, err)
26 continue
27 }
28 fresh := reflect.New(reflect.TypeOf(p).Elem()).Interface()
29 if err := json.Unmarshal(raw, fresh); err != nil {
30 t.Errorf("%s does not decode its own output: %v", name, err)
31 }
32 }
33}
34
35// TestPayloadFieldsAreTagged asserts every exported field on a payload
36// carries a json tag. Without one the key is the Go field name, which is
37// capitalised and drifts the moment the field is renamed.
38func TestPayloadFieldsAreTagged(t *testing.T) {
39 types := []any{
40 Created{}, MRCreated{}, BuildOut{}, JobOut{}, ProfileOut{}, ProfileRepo{},
41 ProfileMember{}, DashboardOut{}, DashboardItem{}, DashboardBuild{},
42 PinnedOut{}, FeedOut{}, ActivityDay{}, SearchResult{}, ReviewOut{},
43 CheckOut{}, CommitOut{}, ServerOut{},
44 }
45 for _, v := range types {
46 ty := reflect.TypeOf(v)
47 for i := 0; i < ty.NumField(); i++ {
48 f := ty.Field(i)
49 if !f.IsExported() || f.Anonymous {
50 continue
51 }
52 if _, ok := f.Tag.Lookup("json"); !ok {
53 t.Errorf("%s.%s has no json tag", ty.Name(), f.Name)
54 }
55 }
56 }
57}