Skip to content

Commit c59bbd6

Browse files
authored
Merge pull request #11 from chainreactors/feat/parsers-framework-is-rejected
feat(parsers): Framework 新增 Judge 判定结论字段
2 parents 7f27166 + fd113e9 commit c59bbd6

2 files changed

Lines changed: 77 additions & 0 deletions

File tree

‎parsers/framework.go‎

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,10 +110,29 @@ type Framework struct {
110110
Froms map[From]bool `json:"froms,omitempty"`
111111
Tags []string `json:"tags,omitempty"`
112112
IsFocus bool `json:"is_focus,omitempty"`
113+
Judge *Judgement `json:"judge,omitempty"` // 判定层(fingers/judge)的结论, nil 表示未经判定
113114
MatchDetail *MatchDetail `json:"matcher,omitempty"`
114115
*Attributes `json:"attributes,omitempty"`
115116
}
116117

118+
// Judgement is a judgement layer's ruling on the claim that a framework
119+
// produced the response (see github.com/chainreactors/fingers/judge).
120+
// Rejected and duplicate entries are kept so callers can explain them;
121+
// Frameworks.Accepted drops them.
122+
type Judgement struct {
123+
// Option is the claim option the ruling picked, such as "declared"
124+
// (the response names the product in a header or cookie, decided without
125+
// a model), "running", "mentioned" or "unrelated".
126+
Option string `json:"option,omitempty"`
127+
// Outcome is what Option means for the claim: "holds", "refuted" or
128+
// "insufficient" (the evidence decides neither way).
129+
Outcome string `json:"outcome,omitempty"`
130+
Confidence float64 `json:"confidence,omitempty"` // the provider's confidence in Option; 1 for code's rulings
131+
Evidence []string `json:"evidence,omitempty"` // the response excerpts the claim was ruled on
132+
Rejected bool `json:"rejected,omitempty"` // the action taken: not reported (refuted, or insufficient where so configured)
133+
Duplicate bool `json:"duplicate,omitempty"` // another engine's spelling of a product kept under another name
134+
}
135+
117136
// MatchDetail describes which rule and matcher produced a hit.
118137
type MatchDetail struct {
119138
RuleIndex int `json:"rule_index,omitempty"`
@@ -227,6 +246,9 @@ func (fs Frameworks) Add(other *Framework) bool {
227246
}
228247
frame.Tags = iutils.StringsUnique(append(frame.Tags, other.Tags...))
229248
frame.UpdateAttributes(other.Attributes)
249+
if frame.Judge == nil {
250+
frame.Judge = other.Judge
251+
}
230252
return false
231253
} else {
232254
fs[other.Name] = other
@@ -337,3 +359,15 @@ func (fs Frameworks) HasFrom(from string) bool {
337359
}
338360
return false
339361
}
362+
363+
// Accepted returns the frameworks without judged false positives and
364+
// duplicate spellings. Frameworks that were not judged are kept.
365+
func (fs Frameworks) Accepted() Frameworks {
366+
out := make(Frameworks, len(fs))
367+
for k, f := range fs {
368+
if f != nil && (f.Judge == nil || !f.Judge.Rejected && !f.Judge.Duplicate) {
369+
out[k] = f
370+
}
371+
}
372+
return out
373+
}

‎parsers/framework_test.go‎

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
package parsers
2+
3+
import (
4+
"encoding/json"
5+
"testing"
6+
)
7+
8+
func TestFrameworksJudgement(t *testing.T) {
9+
fs := Frameworks{}
10+
fs.Add(&Framework{Name: "nginx", Judge: &Judgement{Option: "running", Outcome: "holds", Evidence: []string{"Server: nginx"}, Confidence: 0.9}})
11+
fs.Add(&Framework{Name: "jenkins", Judge: &Judgement{Option: "insufficient", Outcome: "insufficient"}})
12+
fs.Add(&Framework{Name: "tomcat", Judge: &Judgement{Rejected: true}})
13+
fs.Add(&Framework{Name: "apache-tomcat", Judge: &Judgement{Duplicate: true}})
14+
fs.Add(&Framework{Name: "unjudged"})
15+
16+
accepted := fs.Accepted()
17+
if len(accepted) != 3 || accepted["tomcat"] != nil || accepted["apache-tomcat"] != nil || accepted["unjudged"] == nil {
18+
t.Fatalf("accepted %v", accepted.GetNames())
19+
}
20+
21+
data, err := json.Marshal(fs["nginx"])
22+
if err != nil {
23+
t.Fatal(err)
24+
}
25+
var back Framework
26+
if err := json.Unmarshal(data, &back); err != nil || back.Judge == nil || back.Judge.Outcome != "holds" || back.Judge.Option != "running" || len(back.Judge.Evidence) != 1 || back.Judge.Confidence != 0.9 {
27+
t.Fatalf("round trip %s -> %+v", data, back.Judge)
28+
}
29+
if data, _ := json.Marshal(fs["unjudged"]); string(data) != `{"name":"unjudged"}` {
30+
t.Fatalf("unjudged serializes as %s", data)
31+
}
32+
}
33+
34+
func TestFrameworksAddKeepsJudgement(t *testing.T) {
35+
fs := Frameworks{}
36+
fs.Add(NewFramework("nginx", FrameFromDefault))
37+
judged := NewFramework("nginx", FrameFromDefault)
38+
judged.Judge = &Judgement{Option: "running", Outcome: "holds"}
39+
fs.Add(judged)
40+
if fs["nginx"].Judge == nil {
41+
t.Fatal("judgement lost on merge")
42+
}
43+
}

0 commit comments

Comments
 (0)