OSDN Git Service

Merge pull request #41 from Bytom/dev
[bytom/vapor.git] / vendor / github.com / go-logfmt / logfmt / fuzz.go
1 // +build gofuzz
2
3 package logfmt
4
5 import (
6         "bufio"
7         "bytes"
8         "fmt"
9         "io"
10         "reflect"
11
12         kr "github.com/kr/logfmt"
13 )
14
15 // Fuzz checks reserialized data matches
16 func Fuzz(data []byte) int {
17         parsed, err := parse(data)
18         if err != nil {
19                 return 0
20         }
21         var w1 bytes.Buffer
22         if err = write(parsed, &w1); err != nil {
23                 panic(err)
24         }
25         parsed, err = parse(w1.Bytes())
26         if err != nil {
27                 panic(err)
28         }
29         var w2 bytes.Buffer
30         if err = write(parsed, &w2); err != nil {
31                 panic(err)
32         }
33         if !bytes.Equal(w1.Bytes(), w2.Bytes()) {
34                 panic(fmt.Sprintf("reserialized data does not match:\n%q\n%q\n", w1.Bytes(), w2.Bytes()))
35         }
36         return 1
37 }
38
39 // FuzzVsKR checks go-logfmt/logfmt against kr/logfmt
40 func FuzzVsKR(data []byte) int {
41         parsed, err := parse(data)
42         parsedKR, errKR := parseKR(data)
43
44         // github.com/go-logfmt/logfmt is a stricter parser. It returns errors for
45         // more inputs than github.com/kr/logfmt. Ignore any inputs that have a
46         // stict error.
47         if err != nil {
48                 return 0
49         }
50
51         // Fail if the more forgiving parser finds an error not found by the
52         // stricter parser.
53         if errKR != nil {
54                 panic(fmt.Sprintf("unmatched error: %v", errKR))
55         }
56
57         if !reflect.DeepEqual(parsed, parsedKR) {
58                 panic(fmt.Sprintf("parsers disagree:\n%+v\n%+v\n", parsed, parsedKR))
59         }
60         return 1
61 }
62
63 type kv struct {
64         k, v []byte
65 }
66
67 func parse(data []byte) ([][]kv, error) {
68         var got [][]kv
69         dec := NewDecoder(bytes.NewReader(data))
70         for dec.ScanRecord() {
71                 var kvs []kv
72                 for dec.ScanKeyval() {
73                         kvs = append(kvs, kv{dec.Key(), dec.Value()})
74                 }
75                 got = append(got, kvs)
76         }
77         return got, dec.Err()
78 }
79
80 func parseKR(data []byte) ([][]kv, error) {
81         var (
82                 s   = bufio.NewScanner(bytes.NewReader(data))
83                 err error
84                 h   saveHandler
85                 got [][]kv
86         )
87         for err == nil && s.Scan() {
88                 h.kvs = nil
89                 err = kr.Unmarshal(s.Bytes(), &h)
90                 got = append(got, h.kvs)
91         }
92         if err == nil {
93                 err = s.Err()
94         }
95         return got, err
96 }
97
98 type saveHandler struct {
99         kvs []kv
100 }
101
102 func (h *saveHandler) HandleLogfmt(key, val []byte) error {
103         if len(key) == 0 {
104                 key = nil
105         }
106         if len(val) == 0 {
107                 val = nil
108         }
109         h.kvs = append(h.kvs, kv{key, val})
110         return nil
111 }
112
113 func write(recs [][]kv, w io.Writer) error {
114         enc := NewEncoder(w)
115         for _, rec := range recs {
116                 for _, f := range rec {
117                         if err := enc.EncodeKeyval(f.k, f.v); err != nil {
118                                 return err
119                         }
120                 }
121                 if err := enc.EndRecord(); err != nil {
122                         return err
123                 }
124         }
125         return nil
126 }