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
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
|
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
tag string
}{
{
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: "tag filter",
query: "tag:jwt",
remaining: "",
tag: "jwt",
},
{
name: "tag filter preserves case",
query: "tag:JWT",
remaining: "",
tag: "JWT",
},
{
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)
}
if pred.tag != tt.tag {
t.Errorf("tag = %q, want %q", pred.tag, tt.tag)
}
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)
}
})
}
}
|