internal/control/output_test.go

353f68a2e57ac692964b73ae1f9acd91fcdcae20
gitbay/internal/control/output_test.go history · blame · raw

59 lines · 2077 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{}, &DepsOut{}, &DepBehind{}, &ForkOut{}, &BookmarkOut{},
20		&SearchResult{}, &ReviewOut{}, &CheckOut{}, &CommitOut{},
21	}
22	for _, p := range payloads {
23		name := reflect.TypeOf(p).Elem().Name()
24		raw, err := json.Marshal(p)
25		if err != nil {
26			t.Errorf("%s does not marshal: %v", name, err)
27			continue
28		}
29		fresh := reflect.New(reflect.TypeOf(p).Elem()).Interface()
30		if err := json.Unmarshal(raw, fresh); err != nil {
31			t.Errorf("%s does not decode its own output: %v", name, err)
32		}
33	}
34}
35
36// TestPayloadFieldsAreTagged asserts every exported field on a payload
37// carries a json tag. Without one the key is the Go field name, which is
38// capitalised and drifts the moment the field is renamed.
39func TestPayloadFieldsAreTagged(t *testing.T) {
40	types := []any{
41		Created{}, MRCreated{}, BuildOut{}, JobOut{}, ProfileOut{}, ProfileRepo{},
42		ProfileMember{}, DashboardOut{}, DashboardItem{}, DashboardBuild{},
43		PinnedOut{}, FeedOut{}, ActivityDay{}, DepsOut{}, DepBehind{}, ForkOut{}, BookmarkOut{},
44		SearchResult{}, ReviewOut{},
45		CheckOut{}, CommitOut{}, ServerOut{},
46	}
47	for _, v := range types {
48		ty := reflect.TypeOf(v)
49		for i := 0; i < ty.NumField(); i++ {
50			f := ty.Field(i)
51			if !f.IsExported() || f.Anonymous {
52				continue
53			}
54			if _, ok := f.Tag.Lookup("json"); !ok {
55				t.Errorf("%s.%s has no json tag", ty.Name(), f.Name)
56			}
57		}
58	}
59}