master
go 175 lines 4.6 KB
Raw
1 // SPDX-License-Identifier: GPL-3.0-or-later
2
3 package logs
4
5 import (
6 "strings"
7 "testing"
8
9 "github.com/stretchr/testify/assert"
10 "github.com/stretchr/testify/require"
11 )
12
13 var testCSVConfig = CSVConfig{
14 Delimiter: " ",
15 Format: "$A %B",
16 }
17
18 func TestNewCSVParser(t *testing.T) {
19 tests := []struct {
20 name string
21 format string
22 wantErr bool
23 }{
24 {name: "valid format", format: "$A $B"},
25 {name: "empty format", wantErr: true},
26 {name: "bad format: csv read error", format: "$A $B \"$C", wantErr: true},
27 {name: "bad format: duplicate fields", format: "$A $A", wantErr: true},
28 {name: "bad format: zero fields", format: "!A !B", wantErr: true},
29 }
30
31 for _, tt := range tests {
32 t.Run(tt.name, func(t *testing.T) {
33 c := testCSVConfig
34 c.Format = tt.format
35 p, err := NewCSVParser(c, nil)
36 if tt.wantErr {
37 assert.Error(t, err)
38 assert.Nil(t, p)
39 } else {
40 assert.NoError(t, err)
41 assert.NotNil(t, p)
42 }
43 })
44 }
45 }
46
47 func TestNewCSVFormat(t *testing.T) {
48 tests := []struct {
49 format string
50 wantFormat csvFormat
51 wantErr bool
52 }{
53 {format: "$A $B", wantFormat: csvFormat{maxIndex: 1, fields: []csvField{{"$A", 0}, {"$B", 1}}}},
54 {format: "$A $B !C $E", wantFormat: csvFormat{maxIndex: 3, fields: []csvField{{"$A", 0}, {"$B", 1}, {"$E", 3}}}},
55 {format: "!A !B !C $E", wantFormat: csvFormat{maxIndex: 3, fields: []csvField{{"$E", 3}}}},
56 {format: "$A $OFFSET $B", wantFormat: csvFormat{maxIndex: 3, fields: []csvField{{"$A", 0}, {"$B", 3}}}},
57 {format: "$A $OFFSET $B $OFFSET !A", wantFormat: csvFormat{maxIndex: 3, fields: []csvField{{"$A", 0}, {"$B", 3}}}},
58 {format: "$A $OFFSET $OFFSET $B", wantFormat: csvFormat{maxIndex: 5, fields: []csvField{{"$A", 0}, {"$B", 5}}}},
59 {format: "$OFFSET $A $OFFSET $B", wantFormat: csvFormat{maxIndex: 5, fields: []csvField{{"$A", 2}, {"$B", 5}}}},
60 {format: "$A \"$A", wantErr: true},
61 {format: "$A $A", wantErr: true},
62 {format: "!A !A", wantErr: true},
63 {format: "", wantErr: true},
64 }
65
66 for _, tt := range tests {
67 t.Run(tt.format, func(t *testing.T) {
68 c := testCSVConfig
69 c.Format = tt.format
70 c.CheckField = testCheckCSVFormatField
71 tt.wantFormat.raw = tt.format
72
73 f, err := newCSVFormat(c)
74
75 if tt.wantErr {
76 assert.Error(t, err)
77 assert.Nil(t, f)
78 } else {
79 assert.NoError(t, err)
80 assert.Equal(t, tt.wantFormat, *f)
81 }
82 })
83 }
84 }
85
86 func TestCSVParser_ReadLine(t *testing.T) {
87 tests := []struct {
88 name string
89 row string
90 format string
91 wantErr bool
92 wantParseErr bool
93 }{
94 {name: "match and no error", row: "1 2 3", format: `$A $B $C`},
95 {name: "match but error on assigning", row: "1 2 3", format: `$A $B $ERR`, wantErr: true, wantParseErr: true},
96 {name: "not match", row: "1 2 3", format: `$A $B $C $d`, wantErr: true, wantParseErr: true},
97 {name: "error on reading csv.Err", row: "1 2\"3", format: `$A $B $C`, wantErr: true, wantParseErr: true},
98 {name: "error on reading EOF", row: "", format: `$A $B $C`, wantErr: true},
99 }
100
101 for _, tt := range tests {
102 t.Run(tt.name, func(t *testing.T) {
103 var line logLine
104 r := strings.NewReader(tt.row)
105 c := testCSVConfig
106 c.Format = tt.format
107 p, err := NewCSVParser(c, r)
108 require.NoError(t, err)
109
110 err = p.ReadLine(&line)
111
112 if tt.wantErr {
113 require.Error(t, err)
114 if tt.wantParseErr {
115 assert.True(t, IsParseError(err))
116 } else {
117 assert.False(t, IsParseError(err))
118 }
119 } else {
120 assert.NoError(t, err)
121 }
122 })
123 }
124 }
125
126 func TestCSVParser_Parse(t *testing.T) {
127 tests := []struct {
128 name string
129 row string
130 format string
131 wantErr bool
132 }{
133 {name: "match and no error", row: "1 2 3", format: `$A $B $C`},
134 {name: "match but error on assigning", row: "1 2 3", format: `$A $B $ERR`, wantErr: true},
135 {name: "not match", row: "1 2 3", format: `$A $B $C $d`, wantErr: true},
136 {name: "error on reading csv.Err", row: "1 2\"3", format: `$A $B $C`, wantErr: true},
137 }
138
139 for _, tt := range tests {
140 t.Run(tt.name, func(t *testing.T) {
141 var line logLine
142 r := strings.NewReader(tt.row)
143 c := testCSVConfig
144 c.Format = tt.format
145 p, err := NewCSVParser(c, r)
146 require.NoError(t, err)
147
148 err = p.ReadLine(&line)
149
150 if tt.wantErr {
151 require.Error(t, err)
152 assert.True(t, IsParseError(err))
153 } else {
154 assert.NoError(t, err)
155 }
156 })
157 }
158
159 }
160
161 func TestCSVParser_Info(t *testing.T) {
162 p, err := NewCSVParser(testCSVConfig, nil)
163 require.NoError(t, err)
164 assert.NotZero(t, p.Info())
165 }
166
167 func testCheckCSVFormatField(name string) (newName string, offset int, valid bool) {
168 if len(name) < 2 || !strings.HasPrefix(name, "$") {
169 return "", 0, false
170 }
171 if name == "$OFFSET" {
172 return "", 1, false
173 }
174 return name, 0, true
175 }