1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
|
package store
import "testing"
func TestExtractStructured(t *testing.T) {
boolPtr := func(b bool) *bool { return &b }
tests := []struct {
name string
query string
remaining string
statusSQL string
statusArgs []any
source string
flagged *bool
}{
{
name: "plain text only",
query: "admin login",
remaining: "admin login",
},
{
name: "flagged true",
query: "flagged:true",
remaining: "",
flagged: boolPtr(true),
},
{
name: "flagged false",
query: "flagged:no",
remaining: "",
flagged: boolPtr(false),
},
{
name: "not a real flagged token falls through as text",
query: "flagged:maybe",
remaining: "flagged:maybe",
},
{
name: "exact status",
query: "status:404",
remaining: "",
statusSQL: "status_code = ?",
statusArgs: []any{404},
},
{
name: "status with operator",
query: "status:>=400",
remaining: "",
statusSQL: "status_code >= ?",
statusArgs: []any{400},
},
{
name: "status not-equal",
query: "status:!=200",
remaining: "",
statusSQL: "status_code != ?",
statusArgs: []any{200},
},
{
name: "status range shorthand",
query: "status:4xx",
remaining: "",
statusSQL: "status_code >= ? AND status_code < ?",
statusArgs: []any{400, 500},
},
{
name: "source filter",
query: "source:repeater",
remaining: "",
source: "repeater",
},
{
name: "combined with free text",
query: "admin status:>=400 source:proxy",
remaining: "admin",
statusSQL: "status_code >= ?",
statusArgs: []any{400},
source: "proxy",
},
{
name: "not a real status token falls through as text",
query: "status:banana",
remaining: "status:banana",
},
{
name: "malformed 4-digit status falls through as text",
query: "status:4004",
remaining: "status:4004",
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
remaining, pred := extractStructured(tt.query)
if remaining != tt.remaining {
t.Errorf("remaining = %q, want %q", remaining, tt.remaining)
}
if pred.statusSQL != tt.statusSQL {
t.Errorf("statusSQL = %q, want %q", pred.statusSQL, tt.statusSQL)
}
if len(pred.statusArgs) != len(tt.statusArgs) {
t.Fatalf("statusArgs = %v, want %v", pred.statusArgs, tt.statusArgs)
}
for i := range pred.statusArgs {
if pred.statusArgs[i] != tt.statusArgs[i] {
t.Errorf("statusArgs[%d] = %v, want %v", i, pred.statusArgs[i], tt.statusArgs[i])
}
}
if pred.source != tt.source {
t.Errorf("source = %q, want %q", pred.source, tt.source)
}
switch {
case pred.flagged == nil && tt.flagged == nil:
case pred.flagged == nil || tt.flagged == nil:
t.Errorf("flagged = %v, want %v", pred.flagged, tt.flagged)
case *pred.flagged != *tt.flagged:
t.Errorf("flagged = %v, want %v", *pred.flagged, *tt.flagged)
}
})
}
}
|