github.com/netdata/go.d.plugin@v0.58.1/pkg/logs/regexp_test.go (about) 1 // SPDX-License-Identifier: GPL-3.0-or-later 2 3 package logs 4 5 import ( 6 "errors" 7 "strings" 8 "testing" 9 10 "github.com/stretchr/testify/assert" 11 "github.com/stretchr/testify/require" 12 ) 13 14 func TestNewRegExpParser(t *testing.T) { 15 tests := []struct { 16 name string 17 pattern string 18 wantErr bool 19 }{ 20 {name: "valid pattern", pattern: `(?P<A>\d+) (?P<B>\d+)`}, 21 {name: "no names subgroups in pattern", pattern: `(?:\d+) (?:\d+)`, wantErr: true}, 22 {name: "invalid pattern", pattern: `(((?P<A>\d+) (?P<B>\d+)`, wantErr: true}, 23 {name: "empty pattern", wantErr: true}, 24 } 25 26 for _, tt := range tests { 27 t.Run(tt.name, func(t *testing.T) { 28 p, err := NewRegExpParser(RegExpConfig{Pattern: tt.pattern}, nil) 29 if tt.wantErr { 30 assert.Error(t, err) 31 assert.Nil(t, p) 32 } else { 33 assert.NoError(t, err) 34 assert.NotNil(t, p) 35 } 36 }) 37 } 38 } 39 40 func TestRegExpParser_ReadLine(t *testing.T) { 41 tests := []struct { 42 name string 43 row string 44 pattern string 45 wantErr bool 46 wantParseErr bool 47 }{ 48 {name: "match and no error", row: "1 2", pattern: `(?P<A>\d+) (?P<B>\d+)`}, 49 {name: "match but error on assigning", row: "1 2", pattern: `(?P<A>\d+) (?P<ERR>\d+)`, wantErr: true, wantParseErr: true}, 50 {name: "not match", row: "A B", pattern: `(?P<A>\d+) (?P<B>\d+)`, wantErr: true, wantParseErr: true}, 51 {name: "not match multiline", row: "a b\n3 4", pattern: `(?P<A>\d+) (?P<B>\d+)`, wantErr: true, wantParseErr: true}, 52 {name: "error on reading EOF", row: "", pattern: `(?P<A>\d+) (?P<B>\d+)`, wantErr: true}, 53 } 54 55 for _, tt := range tests { 56 t.Run(tt.name, func(t *testing.T) { 57 var line logLine 58 r := strings.NewReader(tt.row) 59 p, err := NewRegExpParser(RegExpConfig{Pattern: tt.pattern}, r) 60 require.NoError(t, err) 61 62 err = p.ReadLine(&line) 63 if tt.wantErr { 64 require.Error(t, err) 65 if tt.wantParseErr { 66 assert.True(t, IsParseError(err)) 67 } else { 68 assert.False(t, IsParseError(err)) 69 } 70 } else { 71 assert.NoError(t, err) 72 } 73 }) 74 } 75 } 76 77 func TestRegExpParser_Parse(t *testing.T) { 78 tests := []struct { 79 name string 80 row string 81 pattern string 82 wantErr bool 83 }{ 84 {name: "match and no error", row: "1 2", pattern: `(?P<A>\d+) (?P<B>\d+)`}, 85 {name: "match but error on assigning", row: "1 2", pattern: `(?P<A>\d+) (?P<ERR>\d+)`, wantErr: true}, 86 {name: "not match", row: "A B", pattern: `(?P<A>\d+) (?P<B>\d+)`, wantErr: true}, 87 } 88 89 for _, tt := range tests { 90 t.Run(tt.name, func(t *testing.T) { 91 var line logLine 92 p, err := NewRegExpParser(RegExpConfig{Pattern: tt.pattern}, nil) 93 require.NoError(t, err) 94 95 err = p.Parse([]byte(tt.row), &line) 96 if tt.wantErr { 97 require.Error(t, err) 98 assert.True(t, IsParseError(err)) 99 } else { 100 assert.NoError(t, err) 101 } 102 }) 103 } 104 } 105 106 func TestRegExpParser_Info(t *testing.T) { 107 p, err := NewRegExpParser(RegExpConfig{Pattern: `(?P<A>\d+) (?P<B>\d+)`}, nil) 108 require.NoError(t, err) 109 assert.NotZero(t, p.Info()) 110 } 111 112 type logLine struct { 113 assigned map[string]string 114 } 115 116 func newLogLine() *logLine { 117 return &logLine{ 118 assigned: make(map[string]string), 119 } 120 } 121 122 func (l *logLine) Assign(name, val string) error { 123 switch name { 124 case "$ERR", "ERR": 125 return errors.New("assign error") 126 } 127 if l.assigned != nil { 128 l.assigned[name] = val 129 } 130 return nil 131 }