-
Notifications
You must be signed in to change notification settings - Fork 1
/
filter_proto_test.go
138 lines (120 loc) · 3.19 KB
/
filter_proto_test.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
package dapper_test
import (
"regexp"
"strings"
"testing"
"time"
"github.com/dogmatiq/dapper"
"github.com/dogmatiq/dapper/internal/fixtures"
)
func TestPrinter_ProtoFilter(t *testing.T) {
t.Run(
"it formats as expected", func(t *testing.T) {
m := &fixtures.Message{
Str: "hello",
Enum: fixtures.Enum_FOO,
Nested: &fixtures.Nested{
NestedA: "foo",
NestedB: []byte("<bytes>"),
},
Stringer: &fixtures.Stringer{
Value: "<stringer>",
},
}
// Trigger population of internal state to make sure it does not
// render.
_ = m.String()
actual := dapper.Format(m)
expected := strings.Join([]string{
`*github.com/dogmatiq/dapper/internal/fixtures.Message{`,
` Str: "hello"`,
` Enum: 1`,
` Nested: {`,
` NestedA: "foo"`,
` NestedB: {`,
` 00000000 3c 62 79 74 65 73 3e |<bytes>|`,
` }`,
` }`,
` Stringer: [<stringer>]`,
`}`,
}, "\n")
if !matchProtoFormat(actual, expected) {
t.Errorf("Expected\n%s\nbut got\n%s", expected, actual)
}
},
)
t.Run(
"it renders the zero-marker when the message is empty", func(t *testing.T) {
m := &fixtures.Message{}
expected := `*github.com/dogmatiq/dapper/internal/fixtures.Message{<zero>}`
actual := dapper.Format(m)
if actual != expected {
t.Errorf("Expected\n%s\nbut got\n%s", expected, actual)
}
},
)
t.Run(
"it renders a protocol buffers message properly when nested within a regular struct", func(t *testing.T) {
m := &fixtures.Message{
Str: "hello",
Stringer: &fixtures.Stringer{
Value: "<stringer>",
},
}
outerStruct := struct {
foo string
bar *fixtures.Message
}{"hi", m}
actual := dapper.Format(outerStruct)
expected := strings.Join([]string{
`{`,
` foo: "hi"`,
` bar: *github.com/dogmatiq/dapper/internal/fixtures.Message{`,
` Str: "hello"`,
` Enum: 0`,
` Nested: nil`,
` Stringer: [<stringer>]`,
` }`,
`}`,
}, "\n")
if !matchProtoFormat(actual, expected) {
t.Errorf("Expected\n%s\nbut got\n%s", expected, actual)
}
},
)
t.Run(
"it performs adequately with internal state set", func(t *testing.T) {
m := &fixtures.Message{
Str: "hello",
Enum: fixtures.Enum_FOO,
}
// Trigger population of internal state.
_ = m.String()
result := make(chan string)
go func() {
result <- dapper.Format(m)
}()
select {
case <-result:
case <-time.After(time.Millisecond * 10):
t.Errorf("Formatting took too long")
}
},
)
}
// matchProtoFormat works around non-deterministic behaviour introduced by the
// protobuf package.
//
// The protobuf maintainers want to enforce nobody relies on the output being
// stable. It's not unreasonable but Dapper is all about the output, so we
// really want to know when it changes.
//
// See https://github.com/golang/protobuf/issues/1121.
func matchProtoFormat(actual, expected string) bool {
pattern := strings.ReplaceAll(regexp.QuoteMeta(expected), ": ", ": ?")
ok, err := regexp.MatchString(pattern, actual)
if err != nil {
panic(err)
}
return ok
}