-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathjtoh_fuzz_test.go
171 lines (149 loc) · 3.27 KB
/
jtoh_fuzz_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
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
//go:build go1.18
// +build go1.18
package jtoh_test
import (
"bytes"
"encoding/json"
"strings"
"testing"
"github.com/madlambda/jtoh"
)
func FuzzJTOH(f *testing.F) {
type seed struct {
selector string
input []byte
}
seedCorpus := []seed{
{
selector: ":a",
input: []byte("string"),
},
{
selector: "/s",
input: []byte(" "),
},
{
selector: "aa",
input: []byte("{}"),
},
{
selector: ".field4",
input: []byte("[]"),
},
{
selector: "%1",
input: []byte(`{ "name": "value"}`),
},
{
selector: "<field",
input: []byte(`{ "name": 666}`),
},
{
selector: "?xS",
input: []byte(`{ "name": true}`),
},
{
selector: "|da",
input: []byte(`[{ "name": "value"}]`),
},
{
selector: "^field^field2",
input: []byte(`[{ "name": 666}]`),
},
{
selector: "#a#name",
input: []byte(`[{ "name": true}]`),
},
{
selector: ":a:B:c",
input: []byte(`[{ "name": "value"}, {"name":666}]`),
},
{
selector: ":name",
input: []byte(`{ "name": "value"}
{"name":666}`),
},
{
selector: "@a@b",
input: []byte("\nmsg\nmsg2\nmsg2\n"),
},
}
for _, seed := range seedCorpus {
f.Add(seed.selector, seed.input)
}
f.Fuzz(func(t *testing.T, selector string, orig []byte) {
input := bytes.NewReader(orig)
output := &bytes.Buffer{}
j, err := jtoh.New(selector)
if err != nil {
// It is expected that invalid selector will be generated
return
}
j.Do(input, output)
})
}
func FuzzJTOHValid(f *testing.F) {
type seed struct {
key string
val string
}
seedCorpus := []seed{
{
key: "str",
val: "str",
},
}
for _, seed := range seedCorpus {
f.Add(seed.key, seed.val)
}
f.Fuzz(func(t *testing.T, key string, val string) {
// Since field selectors have spaces trimmed for now we also
// trim the key, or else we would not be able to select the key.
key = strings.TrimSpace(key)
if key == "" {
return
}
if strings.ContainsAny(key, ".:") {
// We don't handle nesting/keys with dot on name for now.
return
}
input, err := json.Marshal(map[string]string{key: val})
if err != nil {
return
}
// key/value may change on marshalling, so we get the actual
// final key/value from the json encoding/decoding process.
parsedInput := map[string]string{}
if err = json.Unmarshal(input, &parsedInput); err != nil {
t.Fatal(err)
}
var selectKey, wantValue string
for k, v := range parsedInput {
selectKey = k
wantValue = v
}
selector := ":" + selectKey
j, err := jtoh.New(selector)
if err != nil {
t.Fatal(err)
}
// Newlines on values are escaped to avoid breaking the
// line oriented nature of the output.
wantValue = strings.Replace(wantValue, "\n", "\\n", -1)
want := wantValue + "\n"
testSelection := func(input []byte) {
output := &bytes.Buffer{}
j.Do(bytes.NewReader(input), output)
got := output.String()
if got != want {
t.Errorf("input: %q", string(input))
t.Errorf("str : got %q != want %q", got, want)
t.Errorf("bytes: got %v != want %v", []byte(got), []byte(want))
}
}
// Selecting on single document/stream must behave identically to
// selecting from a list of documents.
testSelection(input)
testSelection([]byte("[" + string(input) + "]"))
})
}