github.com/honeycombio/honeytail@v1.9.0/parsers/keyval/keyval_test.go (about) 1 package keyval 2 3 import ( 4 "reflect" 5 "sync" 6 "testing" 7 8 "github.com/honeycombio/honeytail/event" 9 ) 10 11 type testLineMap struct { 12 input string 13 expected map[string]interface{} 14 } 15 16 var tlms = []testLineMap{ 17 { // strings, floats, and ints 18 input: `mystr="myval" myint=3 myfloat=4.234 mybool=true`, 19 expected: map[string]interface{}{ 20 "mystr": "myval", 21 "myint": 3, 22 "myfloat": 4.234, 23 "mybool": true, 24 }, 25 }, 26 { // missing keyval pairs 27 input: `foo bar 123 baz`, 28 expected: map[string]interface{}{ 29 "foo": "", 30 "bar": "", 31 "123": "", 32 "baz": "", 33 }, 34 }, 35 { // time 36 input: `time="2014-03-10 19:57:38.123456789 -0800 PST" myint=3 myfloat=4.234`, 37 expected: map[string]interface{}{ 38 "time": "2014-03-10 19:57:38.123456789 -0800 PST", 39 "myint": 3, 40 "myfloat": 4.234, 41 }, 42 }, 43 } 44 45 func TestParseLine(t *testing.T) { 46 jlp := KeyValLineParser{} 47 for _, tlm := range tlms { 48 resp, err := jlp.ParseLine(tlm.input) 49 if err != nil { 50 t.Error("jlp.ParseLine unexpectedly returned error ", err) 51 } 52 if !reflect.DeepEqual(resp, tlm.expected) { 53 t.Errorf("response %+v didn't match expected %+v", resp, tlm.expected) 54 } 55 } 56 } 57 58 func TestBrokenFilterRegex(t *testing.T) { 59 // test filter that doesn't compile 60 broken := &Parser{} 61 err := broken.Init(&Options{ 62 FilterRegex: "regex [ won't compile", 63 }) 64 if err == nil { 65 t.Error("Parser Init with broken regex should err, instead got nil") 66 } 67 } 68 69 func TestFilterRegex(t *testing.T) { 70 tsts := []struct { 71 filterString string 72 invertFilter bool 73 lines []string 74 expectedEvents int 75 }{ 76 { 77 "aaaa", 78 false, 79 []string{ 80 "key=val", 81 "key=val", 82 "key=val", 83 }, 84 0, // no lines have 'aaaa' 85 }, 86 { 87 "aaaa", 88 true, 89 []string{ 90 "key=val", 91 "key=val", 92 "key=val", 93 }, 94 3, // all lines don't have 'aaaa' 95 }, 96 { 97 "aoeu", 98 false, 99 []string{ 100 "key=val", 101 "key=val aoeu", 102 "key=val", 103 }, 104 1, // only line two has 'aoeu' 105 }, 106 { 107 "aoeu", 108 true, 109 []string{ 110 "key=val", 111 "key=val aoeu", 112 "key=val", 113 }, 114 2, // lines one and three don't have 'aoeu' 115 }, 116 } 117 for _, tst := range tsts { 118 p := &Parser{} 119 p.Init(&Options{ 120 NumParsers: 5, 121 FilterRegex: tst.filterString, 122 InvertFilter: tst.invertFilter, 123 }) 124 lines := make(chan string) 125 send := make(chan event.Event) 126 // send input into lines in a goroutine then close the lines channel 127 go func() { 128 for _, line := range tst.lines { 129 lines <- line 130 } 131 close(lines) 132 }() 133 // read from the send channel and see if we got back what we expected 134 wg := sync.WaitGroup{} 135 wg.Add(1) 136 go func() { 137 var counter int 138 for range send { 139 counter++ 140 } 141 if counter != tst.expectedEvents { 142 t.Errorf("expected %d messages out the send channel, got %d\n", tst.expectedEvents, counter) 143 } 144 wg.Done() 145 }() 146 p.ProcessLines(lines, send, nil) 147 close(send) 148 wg.Wait() 149 } 150 } 151 152 func TestDontReturnEmptyEvents(t *testing.T) { 153 p := &Parser{} 154 p.Init(&Options{}) 155 lines := make(chan string) 156 send := make(chan event.Event) 157 // send input into lines in a goroutine then close the lines channel 158 go func() { 159 for _, line := range []string{"one", "two", "three"} { 160 lines <- line 161 } 162 close(lines) 163 }() 164 // read from the send channel and see if we got back what we expected 165 wg := sync.WaitGroup{} 166 wg.Add(1) 167 go func() { 168 var counter int 169 for range send { 170 counter++ 171 } 172 if counter != 0 { 173 t.Errorf("expected no messages out the send channel, got %d\n", counter) 174 } 175 wg.Done() 176 }() 177 p.ProcessLines(lines, send, nil) 178 close(send) 179 wg.Wait() 180 } 181 182 // TestDontReturnUselessEvents a useless event is one with all keys and no 183 // values 184 func TestDontReturnUselessEvents(t *testing.T) { 185 p := &Parser{} 186 p.Init(&Options{}) 187 lines := make(chan string) 188 send := make(chan event.Event) 189 // send input into lines in a goroutine then close the lines channel 190 go func() { 191 for _, line := range []string{"key=", "key2=", "key= key2="} { 192 lines <- line 193 } 194 close(lines) 195 }() 196 // read from the send channel and see if we got back what we expected 197 wg := sync.WaitGroup{} 198 wg.Add(1) 199 go func() { 200 var counter int 201 for range send { 202 counter++ 203 } 204 if counter != 0 { 205 t.Errorf("expected no messages out the send channel, got %d\n", counter) 206 } 207 wg.Done() 208 }() 209 p.ProcessLines(lines, send, nil) 210 close(send) 211 wg.Wait() 212 } 213 214 func TestAllEmpty(t *testing.T) { 215 tsts := []struct { 216 incoming map[string]interface{} 217 empty bool 218 }{ 219 { 220 map[string]interface{}{ 221 "k1": "v1", 222 }, 223 false, 224 }, 225 { 226 map[string]interface{}{ 227 "k1": 3, 228 }, 229 false, 230 }, 231 { 232 map[string]interface{}{ 233 "k1": []string{"foo", "bar"}, 234 }, 235 false, 236 }, 237 { 238 map[string]interface{}{}, 239 true, 240 }, 241 { 242 map[string]interface{}{ 243 "k1": "", 244 }, 245 true, 246 }, 247 { 248 map[string]interface{}{ 249 "k1": "", 250 "k2": "", 251 "k3": "", 252 }, 253 true, 254 }, 255 } 256 for _, tst := range tsts { 257 res := allEmpty(tst.incoming) 258 if res != tst.empty { 259 t.Errorf("expected %v's empty val would be %v, got %v", 260 tst.incoming, tst.empty, res) 261 } 262 } 263 }