github.com/honeycombio/honeytail@v1.9.0/parsers/syslog/syslog_test.go (about) 1 package syslog 2 3 import ( 4 "reflect" 5 "regexp" 6 "testing" 7 "time" 8 9 "github.com/stretchr/testify/assert" 10 11 "github.com/honeycombio/honeytail/event" 12 "github.com/honeycombio/honeytail/parsers" 13 ) 14 15 const ( 16 commonLogFormatTimeLayout = "02/Jan/2006:15:04:05 -0700" 17 iso8601TimeLayout = "2006-01-02T15:04:05-07:00" 18 ) 19 20 // Test Init(...) success/fail 21 22 type testInitMap struct { 23 options *Options 24 expectedPass bool 25 } 26 27 var testInitCases = []testInitMap{ 28 { 29 expectedPass: true, 30 options: &Options{ 31 Mode: "rfc3164", 32 NumParsers: 5, 33 }, 34 }, 35 { 36 expectedPass: false, 37 options: &Options{ 38 Mode: "foo", // unsupported syslog mode should cause a failure 39 }, 40 }, 41 } 42 43 func TestInit(t *testing.T) { 44 for _, testCase := range testInitCases { 45 p := &Parser{} 46 err := p.Init(testCase.options) 47 if (err == nil) != testCase.expectedPass { 48 if err == nil { 49 t.Error("Parser Init(...) passed; expected it to fail.") 50 } else { 51 t.Error("Parser Init(...) failed; expected it to pass. Error:", err) 52 } 53 } else { 54 t.Logf("Init pass status is %t as expected", (err == nil)) 55 } 56 } 57 } 58 59 type testLineMap struct { 60 mode string 61 processList string 62 input string 63 expected map[string]interface{} 64 err bool 65 } 66 67 var tlms = []testLineMap{ 68 // these test cases taken from https://github.com/jeromer/syslogparser/ 69 { 70 input: "<34>Oct 11 22:14:15 mymachine su: 'su root' failed for lonvick on /dev/pts/8", 71 mode: "rfc3164", 72 expected: map[string]interface{}{ 73 "timestamp": time.Date(time.Now().Year(), 10, 11, 22, 14, 15, 0, time.UTC), 74 "hostname": "mymachine", 75 "process": "su", 76 "content": "'su root' failed for lonvick on /dev/pts/8", 77 "priority": 34, 78 "facility": 4, 79 "severity": 2, 80 }, 81 }, 82 { 83 input: "<34>Oct 11 22:14:15 mymachine su: 'su root' failed for lonvick on /dev/pts/8", 84 mode: "rfc3164", 85 // should parse, because su is in the list of processes 86 processList: "su,sshd", 87 expected: map[string]interface{}{ 88 "timestamp": time.Date(time.Now().Year(), 10, 11, 22, 14, 15, 0, time.UTC), 89 "hostname": "mymachine", 90 "process": "su", 91 "content": "'su root' failed for lonvick on /dev/pts/8", 92 "priority": 34, 93 "facility": 4, 94 "severity": 2, 95 }, 96 }, 97 { 98 input: "<34>Oct 11 22:14:15 mymachine su: 'su root' failed for lonvick on /dev/pts/8", 99 mode: "rfc3164", 100 // should not parse (but not return an error) since su is not in the list of processes 101 processList: "sshd", 102 expected: nil, 103 }, 104 { 105 input: `<165>1 2003-10-11T22:14:15.003Z mymachine.example.com evntslog - ID47 [exampleSDID@32473 iut="3" eventSource="Application" eventID="1011"] An application event log entry...`, 106 mode: "rfc5424", 107 expected: map[string]interface{}{ 108 "version": 1, 109 "timestamp": time.Date(2003, 10, 11, 22, 14, 15, int(time.Millisecond*3), time.UTC), 110 "structured_data": `[exampleSDID@32473 iut="3" eventSource="Application" eventID="1011"]`, 111 "proc_id": "-", 112 "hostname": "mymachine.example.com", 113 "severity": 5, 114 "facility": 20, 115 "priority": 165, 116 "message": "An application event log entry...", 117 "msg_id": "ID47", 118 "process": "evntslog", 119 }, 120 }, 121 } 122 123 func TestParseLine(t *testing.T) { 124 for _, tlm := range tlms { 125 p := &Parser{} 126 err := p.Init(&Options{ 127 Mode: tlm.mode, 128 ProcessList: tlm.processList, 129 }) 130 assert.NoError(t, err, "could not instantiate parser with mode: %s", tlm.mode) 131 resp, err := p.lineParser.ParseLine(tlm.input) 132 t.Logf("%+v", resp) 133 if tlm.err { 134 assert.Error(t, err, "p.ParseLine did not return error as expected") 135 } else { 136 assert.NoError(t, err, "p.ParseLine unexpectedly returned error %v", err) 137 } 138 if !reflect.DeepEqual(resp, tlm.expected) { 139 t.Errorf("response %+v didn't match expected %+v", resp, tlm.expected) 140 } 141 } 142 } 143 144 type testLineMaps struct { 145 line string 146 trimmedLine string 147 resp map[string]interface{} 148 typedResp map[string]interface{} 149 ev event.Event 150 } 151 152 // Test event emitted from ProcessLines 153 func TestProcessLines(t *testing.T) { 154 preReg := &parsers.ExtRegexp{regexp.MustCompile("^(?P<pre_hostname>[a-zA-Z-.]+): ")} 155 tlm := []testLineMaps{ 156 { 157 line: "somehost: <34>Oct 11 22:14:15 mymachine su: 'su root' failed for lonvick on /dev/pts/8", 158 ev: event.Event{ 159 Timestamp: time.Date(time.Now().Year(), 10, 11, 22, 14, 15, 0, time.UTC), 160 Data: map[string]interface{}{ 161 "pre_hostname": "somehost", 162 "timestamp": time.Date(time.Now().Year(), 10, 11, 22, 14, 15, 0, time.UTC), 163 "hostname": "mymachine", 164 "process": "su", 165 "content": "'su root' failed for lonvick on /dev/pts/8", 166 "priority": 34, 167 "facility": 4, 168 "severity": 2, 169 }, 170 }, 171 }, 172 } 173 p := &Parser{} 174 err := p.Init(&Options{ 175 Mode: "rfc3164", 176 NumParsers: 5, 177 }) 178 assert.NoError(t, err, "Couldn't instantiate Parser") 179 180 lines := make(chan string) 181 send := make(chan event.Event) 182 go func() { 183 for _, pair := range tlm { 184 lines <- pair.line 185 } 186 close(lines) 187 }() 188 go p.ProcessLines(lines, send, preReg) 189 for _, pair := range tlm { 190 resp := <-send 191 if !reflect.DeepEqual(resp, pair.ev) { 192 t.Fatalf("line resp didn't match up for %s. Expected: %+v, actual: %+v", 193 pair.line, pair.ev, resp) 194 } 195 } 196 }