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  }