diff --git a/checker/check_result.go b/checker/check_result.go index ffccf8ee40e..485f3748a42 100644 --- a/checker/check_result.go +++ b/checker/check_result.go @@ -22,7 +22,7 @@ import ( sce "github.com/ossf/scorecard/v4/errors" "github.com/ossf/scorecard/v4/finding" - "github.com/ossf/scorecard/v4/rule" + "github.com/ossf/scorecard/v4/finding/probe" ) type ( @@ -86,13 +86,13 @@ type LogMessage struct { Finding *finding.Finding // Non-structured results. - Text string // A short string explaining why the detail was recorded/logged. - Path string // Fullpath to the file. - Type finding.FileType // Type of file. - Offset uint // Offset in the file of Path (line for source/text files). - EndOffset uint // End of offset in the file, e.g. if the command spans multiple lines. - Snippet string // Snippet of code - Remediation *rule.Remediation // Remediation information, if any. + Text string // A short string explaining why the detail was recorded/logged. + Path string // Fullpath to the file. + Type finding.FileType // Type of file. + Offset uint // Offset in the file of Path (line for source/text files). + EndOffset uint // End of offset in the file, e.g. if the command spans multiple lines. + Snippet string // Snippet of code + Remediation *probe.Remediation // Remediation information, if any. } // ProportionalScoreWeighted is a structure that contains diff --git a/checker/raw_result.go b/checker/raw_result.go index 011bd106cb5..88416761665 100644 --- a/checker/raw_result.go +++ b/checker/raw_result.go @@ -20,7 +20,7 @@ import ( "github.com/ossf/scorecard/v4/clients" "github.com/ossf/scorecard/v4/finding" - "github.com/ossf/scorecard/v4/rule" + "github.com/ossf/scorecard/v4/finding/probe" ) // RawResults contains results before a policy @@ -126,7 +126,7 @@ type Dependency struct { Location *File Msg *string // Only for debug messages. Pinned *bool - Remediation *rule.Remediation + Remediation *probe.Remediation Type DependencyUseType } diff --git a/checks/evaluation/pinned_dependencies.go b/checks/evaluation/pinned_dependencies.go index 39a2a978045..4d3a46acd3a 100644 --- a/checks/evaluation/pinned_dependencies.go +++ b/checks/evaluation/pinned_dependencies.go @@ -21,9 +21,7 @@ import ( "github.com/ossf/scorecard/v4/checks/fileparser" sce "github.com/ossf/scorecard/v4/errors" "github.com/ossf/scorecard/v4/finding" - "github.com/ossf/scorecard/v4/finding/probe" "github.com/ossf/scorecard/v4/probes/pinsDependencies" - "github.com/ossf/scorecard/v4/rule" ) type pinnedResult struct { @@ -52,15 +50,6 @@ const ( normalWeight int = gitHubOwnedActionWeight + thirdPartyActionWeight ) -func probeRemToRuleRem(rem *probe.Remediation) *rule.Remediation { - return &rule.Remediation{ - Patch: rem.Patch, - Text: rem.Text, - Markdown: rem.Markdown, - Effort: rule.RemediationEffort(rem.Effort), - } -} - // PinningDependencies applies the score policy for the Pinned-Dependencies check. func PinningDependencies(name string, findings []finding.Finding, @@ -101,7 +90,7 @@ func PinningDependencies(name string, } if f.Remediation != nil { - lm.Remediation = probeRemToRuleRem(f.Remediation) + lm.Remediation = f.Remediation } dl.Warn(lm) case finding.OutcomeError: diff --git a/checks/raw/pinned_dependencies_test.go b/checks/raw/pinned_dependencies_test.go index 305c075a600..fca8663b116 100644 --- a/checks/raw/pinned_dependencies_test.go +++ b/checks/raw/pinned_dependencies_test.go @@ -27,7 +27,7 @@ import ( "github.com/ossf/scorecard/v4/checker" mockrepo "github.com/ossf/scorecard/v4/clients/mockclients" - "github.com/ossf/scorecard/v4/rule" + "github.com/ossf/scorecard/v4/finding/probe" scut "github.com/ossf/scorecard/v4/utests" ) @@ -1874,7 +1874,7 @@ func TestCollectDockerfilePinning(t *testing.T) { }, Pinned: boolAsPointer(false), Type: "containerImage", - Remediation: &rule.Remediation{ + Remediation: &probe.Remediation{ Text: "pin your Docker image by updating python:3.7 to python:3.7" + "@sha256:eedf63967cdb57d8214db38ce21f105003ed4e4d0358f02bedc057341bcf92a0", Markdown: "pin your Docker image by updating python:3.7 to python:3.7" + diff --git a/pkg/common_test.go b/pkg/common_test.go index ad2ef2dba49..9c66c63c012 100644 --- a/pkg/common_test.go +++ b/pkg/common_test.go @@ -18,8 +18,8 @@ import ( "testing" "github.com/ossf/scorecard/v4/checker" + "github.com/ossf/scorecard/v4/finding/probe" "github.com/ossf/scorecard/v4/log" - rules "github.com/ossf/scorecard/v4/rule" ) func TestDetailString(t *testing.T) { @@ -122,7 +122,7 @@ func TestDetailString(t *testing.T) { Msg: checker.LogMessage{ Text: "some meaningful text", Path: "Dockerfile", - Remediation: &rules.Remediation{ + Remediation: &probe.Remediation{ Text: "fix x by doing y", }, }, diff --git a/pkg/sarif_test.go b/pkg/sarif_test.go index 6a8912721ef..adf896a3509 100644 --- a/pkg/sarif_test.go +++ b/pkg/sarif_test.go @@ -26,10 +26,10 @@ import ( "github.com/ossf/scorecard/v4/checker" "github.com/ossf/scorecard/v4/finding" + "github.com/ossf/scorecard/v4/finding/probe" "github.com/ossf/scorecard/v4/log" "github.com/ossf/scorecard/v4/options" spol "github.com/ossf/scorecard/v4/policy" - rules "github.com/ossf/scorecard/v4/rule" ) func sarifMockDocRead() *mockDoc { @@ -162,7 +162,7 @@ func TestSARIFOutput(t *testing.T) { Type: finding.FileTypeSource, Offset: 5, Snippet: "if (bad) {BUG();}", - Remediation: &rules.Remediation{ + Remediation: &probe.Remediation{ Markdown: "this is the custom markdown help", Text: "this is the custom text help", }, diff --git a/probes/pinsDependencies/impl.go b/probes/pinsDependencies/impl.go index 96d75f67448..df5d0f7d032 100644 --- a/probes/pinsDependencies/impl.go +++ b/probes/pinsDependencies/impl.go @@ -23,10 +23,8 @@ import ( "github.com/ossf/scorecard/v4/checks/fileparser" sce "github.com/ossf/scorecard/v4/errors" "github.com/ossf/scorecard/v4/finding" - "github.com/ossf/scorecard/v4/finding/probe" "github.com/ossf/scorecard/v4/internal/probes" "github.com/ossf/scorecard/v4/probes/internal/utils/uerror" - "github.com/ossf/scorecard/v4/rule" ) func init() { @@ -91,7 +89,7 @@ func Run(raw *checker.RawResults) ([]finding.Finding, string, error) { f = f.WithMessage(generateTextUnpinned(&rr)). WithOutcome(finding.OutcomeFalse) if rr.Remediation != nil { - f.Remediation = ruleRemToProbeRem(rr.Remediation) + f.Remediation = rr.Remediation } f = f.WithValues(map[string]string{ DepTypeKey: string(rr.Type), @@ -121,15 +119,6 @@ func generateTextIncompleteResults(e checker.ElementError) string { return fmt.Sprintf("Possibly incomplete results: %s", e.Err) } -func ruleRemToProbeRem(rem *rule.Remediation) *probe.Remediation { - return &probe.Remediation{ - Patch: rem.Patch, - Text: rem.Text, - Markdown: rem.Markdown, - Effort: probe.RemediationEffort(rem.Effort), - } -} - func generateTextUnpinned(rr *checker.Dependency) string { if rr.Type == checker.DependencyUseTypeGHAction { // Check if we are dealing with a GitHub action or a third-party one. diff --git a/remediation/remediations.go b/remediation/remediations.go index 3a737490099..7650b8b45d2 100644 --- a/remediation/remediations.go +++ b/remediation/remediations.go @@ -22,7 +22,7 @@ import ( "github.com/google/go-containerregistry/pkg/crane" "github.com/ossf/scorecard/v4/checker" - "github.com/ossf/scorecard/v4/rule" + "github.com/ossf/scorecard/v4/finding/probe" ) var errInvalidArg = errors.New("invalid argument") @@ -62,11 +62,11 @@ func New(c *checker.CheckRequest) (*RemediationMetadata, error) { } // CreateWorkflowPinningRemediation create remediation for pinning GH Actions. -func (r *RemediationMetadata) CreateWorkflowPinningRemediation(filepath string) *rule.Remediation { +func (r *RemediationMetadata) CreateWorkflowPinningRemediation(filepath string) *probe.Remediation { return r.createWorkflowRemediation(filepath, "pin") } -func (r *RemediationMetadata) createWorkflowRemediation(path, t string) *rule.Remediation { +func (r *RemediationMetadata) createWorkflowRemediation(path, t string) *probe.Remediation { p := strings.TrimPrefix(path, ".github/workflows/") if r.Branch == "" || r.Repo == "" { return nil @@ -75,7 +75,7 @@ func (r *RemediationMetadata) createWorkflowRemediation(path, t string) *rule.Re text := fmt.Sprintf(workflowText, r.Repo, p, r.Branch, t) markdown := fmt.Sprintf(workflowMarkdown, r.Repo, p, r.Branch, t) - return &rule.Remediation{ + return &probe.Remediation{ Text: text, Markdown: markdown, } @@ -101,7 +101,7 @@ func (c CraneDigester) Digest(name string) (string, error) { } // CreateDockerfilePinningRemediation create remediation for pinning Dockerfile images. -func CreateDockerfilePinningRemediation(dep *checker.Dependency, digester Digester) *rule.Remediation { +func CreateDockerfilePinningRemediation(dep *checker.Dependency, digester Digester) *probe.Remediation { name, ok := dockerImageName(dep) if !ok { return nil @@ -115,7 +115,7 @@ func CreateDockerfilePinningRemediation(dep *checker.Dependency, digester Digest text := fmt.Sprintf(dockerfilePinText, name, hash) markdown := text - return &rule.Remediation{ + return &probe.Remediation{ Text: text, Markdown: markdown, } diff --git a/remediation/remediations_test.go b/remediation/remediations_test.go index dd0ae914ce4..eb5d3e30fc9 100644 --- a/remediation/remediations_test.go +++ b/remediation/remediations_test.go @@ -23,7 +23,7 @@ import ( "github.com/ossf/scorecard/v4/checker" mockrepo "github.com/ossf/scorecard/v4/clients/mockclients" - "github.com/ossf/scorecard/v4/rule" + "github.com/ossf/scorecard/v4/finding/probe" ) func TestRepeatedSetup(t *testing.T) { @@ -75,7 +75,7 @@ func TestCreateDockerfilePinningRemediation(t *testing.T) { t.Parallel() tests := []struct { - expected *rule.Remediation + expected *probe.Remediation dep checker.Dependency name string }{ @@ -90,7 +90,7 @@ func TestCreateDockerfilePinningRemediation(t *testing.T) { Name: asPointer("foo"), Type: checker.DependencyUseTypeDockerfileContainerImage, }, - expected: &rule.Remediation{ + expected: &probe.Remediation{ Text: "pin your Docker image by updating foo to foo@sha256:2c26b46b68ffc68ff99b453c1d30413413422d706483bfa0f98a5e886266e7ae", Markdown: "pin your Docker image by updating foo to foo@sha256:2c26b46b68ffc68ff99b453c1d30413413422d706483bfa0f98a5e886266e7ae", }, @@ -103,7 +103,7 @@ func TestCreateDockerfilePinningRemediation(t *testing.T) { PinnedAt: asPointer("11"), Type: checker.DependencyUseTypeDockerfileContainerImage, }, - expected: &rule.Remediation{ + expected: &probe.Remediation{ Text: "pin your Docker image by updating amazoncorretto:11 to amazoncorretto:11@sha256:b1a711069b801a325a30885f08f5067b2b102232379750dda4d25a016afd9a88", Markdown: "pin your Docker image by updating amazoncorretto:11 to amazoncorretto:11@sha256:b1a711069b801a325a30885f08f5067b2b102232379750dda4d25a016afd9a88", }, @@ -143,7 +143,7 @@ func TestCreateWorkflowPinningRemediation(t *testing.T) { t.Parallel() tests := []struct { - expected *rule.Remediation + expected *probe.Remediation name string branch string repo string @@ -154,7 +154,7 @@ func TestCreateWorkflowPinningRemediation(t *testing.T) { branch: "main", repo: "ossf/scorecard", filepath: ".github/workflows/scorecard.yml", - expected: &rule.Remediation{ + expected: &probe.Remediation{ Text: fmt.Sprintf(workflowText, "ossf/scorecard", "scorecard.yml", "main", "pin"), Markdown: fmt.Sprintf(workflowMarkdown, "ossf/scorecard", "scorecard.yml", "main", "pin"), }, diff --git a/rule/rule.go b/rule/rule.go deleted file mode 100644 index e5aa7f6d43a..00000000000 --- a/rule/rule.go +++ /dev/null @@ -1,244 +0,0 @@ -// Copyright 2023 OpenSSF Scorecard Authors -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package rule - -import ( - "embed" - "errors" - "fmt" - "strings" - - "gopkg.in/yaml.v3" -) - -// RemediationEffort indicates the estimated effort necessary to remediate a finding. -type RemediationEffort int - -const ( - // RemediationEffortNone indicates a no remediation effort. - RemediationEffortNone RemediationEffort = iota - // RemediationEffortLow indicates a low remediation effort. - RemediationEffortLow - // RemediationEffortMedium indicates a medium remediation effort. - RemediationEffortMedium - // RemediationEffortHigh indicates a high remediation effort. - RemediationEffortHigh -) - -// Remediation represents the remediation for a finding. -type Remediation struct { - // Patch for machines. - Patch *string `json:"patch,omitempty"` - // Text for humans. - Text string `json:"text"` - // Text in markdown format for humans. - Markdown string `json:"markdown"` - // Effort to remediate. - Effort RemediationEffort `json:"effort"` -} - -type jsonRemediation struct { - Text []string `yaml:"text"` - Markdown []string `yaml:"markdown"` - Effort RemediationEffort `yaml:"effort"` -} - -type jsonRule struct { - Short string `yaml:"short"` - Desc string `yaml:"desc"` - Motivation string `yaml:"motivation"` - Implementation string `yaml:"implementation"` - Remediation jsonRemediation `yaml:"remediation"` - Risk Risk `yaml:"risk"` -} - -// Risk indicates a risk. -type Risk int - -const ( - // RiskNone is a no risk. - RiskNone Risk = iota - // RiskLow is a low risk. - RiskLow - // RiskMedium is a medium risk. - RiskMedium - // RiskHigh is a high risk. - RiskHigh - // RiskCritical is a critical risk. - RiskCritical -) - -type Rule struct { - Remediation *Remediation - Name string - Short string - Desc string - Motivation string - Risk Risk -} - -var errInvalid = errors.New("invalid") - -// New create a new rule. -func New(loc embed.FS, rule string) (*Rule, error) { - content, err := loc.ReadFile(fmt.Sprintf("%s.yml", rule)) - if err != nil { - return nil, fmt.Errorf("%w: %w", errInvalid, err) - } - - r, err := parseFromJSON(content) - if err != nil { - return nil, err - } - - if err := validate(r); err != nil { - return nil, err - } - - return &Rule{ - Name: rule, - Short: r.Short, - Desc: r.Desc, - Motivation: r.Motivation, - Risk: r.Risk, - Remediation: &Remediation{ - Text: strings.Join(r.Remediation.Text, "\n"), - Markdown: strings.Join(r.Remediation.Markdown, "\n"), - Effort: r.Remediation.Effort, - }, - }, nil -} - -func validate(r *jsonRule) error { - if err := validateRisk(r.Risk); err != nil { - return fmt.Errorf("%w: %w", errInvalid, err) - } - if err := validateRemediation(r.Remediation); err != nil { - return fmt.Errorf("%w: %w", errInvalid, err) - } - return nil -} - -func validateRemediation(r jsonRemediation) error { - switch r.Effort { - case RemediationEffortHigh, RemediationEffortMedium, RemediationEffortLow: - return nil - default: - return fmt.Errorf("%w: %v", errInvalid, fmt.Sprintf("remediation '%v'", r)) - } -} - -func validateRisk(r Risk) error { - switch r { - case RiskNone, RiskLow, RiskHigh, RiskMedium, RiskCritical: - return nil - default: - return fmt.Errorf("%w: %v", errInvalid, fmt.Sprintf("risk '%v'", r)) - } -} - -func parseFromJSON(content []byte) (*jsonRule, error) { - r := jsonRule{} - - err := yaml.Unmarshal(content, &r) - if err != nil { - return nil, fmt.Errorf("%w: %w", errInvalid, err) - } - return &r, nil -} - -// UnmarshalYAML is a custom unmarshalling function -// to transform the string into an enum. -func (r *RemediationEffort) UnmarshalYAML(n *yaml.Node) error { - var str string - if err := n.Decode(&str); err != nil { - return fmt.Errorf("%w: %w", errInvalid, err) - } - - //nolint:goconst - switch n.Value { - case "Low": - *r = RemediationEffortLow - case "Medium": - *r = RemediationEffortMedium - case "High": - *r = RemediationEffortHigh - default: - return fmt.Errorf("%w: %q", errInvalid, str) - } - return nil -} - -// UnmarshalYAML is a custom unmarshalling function -// to transform the string into an enum. -func (r *Risk) UnmarshalYAML(n *yaml.Node) error { - var str string - if err := n.Decode(&str); err != nil { - return fmt.Errorf("%w: %w", errInvalid, err) - } - - switch n.Value { - case "None": - *r = RiskNone - case "Low": - *r = RiskLow - case "High": - *r = RiskHigh - case "Medium": - *r = RiskMedium - case "Critical": - *r = RiskCritical - default: - return fmt.Errorf("%w: %q", errInvalid, str) - } - return nil -} - -// String stringifies the enum. -func (r *RemediationEffort) String() string { - switch *r { - case RemediationEffortLow: - return "Low" - case RemediationEffortMedium: - return "Medium" - case RemediationEffortHigh: - return "High" - default: - return "" - } -} - -// String stringifies the enum. -func (r *Risk) String() string { - switch *r { - case RiskNone: - return "None" - case RiskLow: - return "Low" - case RiskHigh: - return "High" - case RiskMedium: - return "Medium" - case RiskCritical: - return "Critical" - default: - return "" - } -} - -// GreaterThan compare risks. -func (r *Risk) GreaterThan(rr Risk) bool { - return *r > rr -} diff --git a/rule/rule_test.go b/rule/rule_test.go deleted file mode 100644 index 89f484f47c7..00000000000 --- a/rule/rule_test.go +++ /dev/null @@ -1,374 +0,0 @@ -// Copyright 2023 OpenSSF Scorecard Authors -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package rule - -import ( - "embed" - "errors" - "fmt" - "testing" - - "github.com/google/go-cmp/cmp" - "github.com/google/go-cmp/cmp/cmpopts" - "gopkg.in/yaml.v3" -) - -func errCmp(e1, e2 error) bool { - return errors.Is(e1, e2) || errors.Is(e2, e1) -} - -//go:embed testdata/* -var testfs embed.FS - -func Test_New(t *testing.T) { - t.Parallel() - tests := []struct { - err error - rule *Rule - name string - id string - }{ - { - name: "all fields set", - id: "testdata/all-fields", - rule: &Rule{ - Name: "testdata/all-fields", - Short: "short description", - Desc: "description", - Motivation: "line1 line2\n", - Risk: RiskHigh, - Remediation: &Remediation{ - Text: "step1\nstep2 https://www.google.com/something", - Markdown: "step1\nstep2 [google.com](https://www.google.com/something)", - Effort: RemediationEffortLow, - }, - }, - }, - { - name: "invalid risk", - id: "testdata/invalid-risk", - err: errInvalid, - }, - { - name: "invalid effort", - id: "testdata/invalid-effort", - err: errInvalid, - }, - } - for _, tt := range tests { - tt := tt // Re-initializing variable so it is not changed while executing the closure below - t.Run(tt.name, func(t *testing.T) { - t.Parallel() - - r, err := New(testfs, tt.id) - if err != nil || tt.err != nil { - if !errCmp(err, tt.err) { - t.Fatalf("unexpected error: %v", cmp.Diff(err, tt.err, cmpopts.EquateErrors())) - } - return - } - - if diff := cmp.Diff(*tt.rule, *r); diff != "" { - t.Errorf("mismatch (-want +got):\n%s", diff) - } - }) - } -} - -func TestRisk_GreaterThan(t *testing.T) { - t.Parallel() - - tests := []struct { - name string - r Risk - rr Risk - want bool - }{ - { - name: "greater than", - r: RiskHigh, - rr: RiskLow, - want: true, - }, - { - name: "less than", - r: RiskLow, - rr: RiskHigh, - want: false, - }, - { - name: "equal", - r: RiskMedium, - rr: RiskMedium, - want: false, - }, - } - - for _, tt := range tests { - tt := tt - t.Run(tt.name, func(t *testing.T) { - t.Parallel() - if got := tt.r.GreaterThan(tt.rr); got != tt.want { - t.Errorf("Risk.GreaterThan() = %v, want %v", got, tt.want) - } - }) - } -} - -func TestRisk_String(t *testing.T) { - t.Parallel() - - tests := []struct { - name string - want string - r Risk - }{ - { - name: "RiskNone", - r: RiskNone, - want: "None", - }, - { - name: "RiskLow", - r: RiskLow, - want: "Low", - }, - { - name: "RiskMedium", - r: RiskMedium, - want: "Medium", - }, - { - name: "RiskHigh", - r: RiskHigh, - want: "High", - }, - { - name: "RiskCritical", - r: RiskCritical, - want: "Critical", - }, - { - name: "invalid", - r: Risk(100), - want: "", - }, - } - - for _, tt := range tests { - tt := tt - t.Run(tt.name, func(t *testing.T) { - t.Parallel() - if got := tt.r.String(); got != tt.want { - t.Errorf("Risk.String() = %v, want %v", got, tt.want) - } - }) - } -} - -func TestRemediationEffort_String(t *testing.T) { - t.Parallel() - - tests := []struct { - name string - want string - effort RemediationEffort - }{ - { - name: "RemediationEffortNone", - effort: RemediationEffortNone, - want: "", - }, - { - name: "RemediationEffortLow", - effort: RemediationEffortLow, - want: "Low", - }, - { - name: "RemediationEffortMedium", - effort: RemediationEffortMedium, - want: "Medium", - }, - { - name: "RemediationEffortHigh", - effort: RemediationEffortHigh, - want: "High", - }, - { - name: "invalid", - effort: RemediationEffort(100), - want: "", - }, - } - - for _, tt := range tests { - tt := tt - t.Run(tt.name, func(t *testing.T) { - t.Parallel() - if got := tt.effort.String(); got != tt.want { - t.Errorf("RemediationEffort.String() = %v, want %v", got, tt.want) - } - }) - } -} - -func TestRisk_UnmarshalYAML(t *testing.T) { - t.Parallel() - - tests := []struct { - wantErr error - name string - input string - want Risk - }{ - { - name: "RiskNone", - input: "None", - want: RiskNone, - }, - { - name: "RiskLow", - input: "Low", - want: RiskLow, - }, - { - name: "RiskMedium", - input: "Medium", - want: RiskMedium, - }, - { - name: "RiskHigh", - input: "High", - want: RiskHigh, - }, - { - name: "RiskCritical", - input: "Critical", - want: RiskCritical, - }, - } - - for _, tt := range tests { - tt := tt - t.Run(tt.name, func(t *testing.T) { - t.Parallel() - var r Risk - err := yaml.Unmarshal([]byte(tt.input), &r) - if err != nil { - if tt.wantErr == nil || !errors.Is(err, tt.wantErr) { - t.Errorf("Risk.UnmarshalYAML() error = %v, wantErr %v", err, tt.wantErr) - } - return - } - if r != tt.want { - t.Errorf("Risk.UnmarshalYAML() got = %v, want %v", r, tt.want) - } - }) - } -} - -func TestRemediationEffort_UnmarshalYAML(t *testing.T) { - t.Parallel() - - tests := []struct { - wantErr error - name string - input string - want RemediationEffort - }{ - { - name: "RemediationEffortLow", - input: "Low", - want: RemediationEffortLow, - }, - { - name: "RemediationEffortMedium", - input: "Medium", - want: RemediationEffortMedium, - }, - { - name: "RemediationEffortHigh", - input: "High", - want: RemediationEffortHigh, - }, - } - - for _, tt := range tests { - tt := tt - t.Run(tt.name, func(t *testing.T) { - t.Parallel() - var r RemediationEffort - err := yaml.Unmarshal([]byte(tt.input), &r) - if err != nil { - if tt.wantErr == nil || !errors.Is(err, tt.wantErr) { - t.Errorf("RemediationEffort.UnmarshalYAML() error = %v, wantErr %v", err, tt.wantErr) - } - return - } - if r != tt.want { - t.Errorf("RemediationEffort.UnmarshalYAML() got = %v, want %v", r, tt.want) - } - }) - } -} - -func Test_validate(t *testing.T) { - t.Parallel() - - tests := []struct { - wantErr error - rule *jsonRule - name string - }{ - { - name: "valid", - rule: &jsonRule{ - Risk: RiskLow, - Remediation: jsonRemediation{ - Effort: RemediationEffortHigh, - }, - }, - wantErr: nil, - }, - { - name: "invalid risk", - rule: &jsonRule{ - Risk: Risk(100), - Remediation: jsonRemediation{ - Effort: RemediationEffortHigh, - }, - }, - wantErr: fmt.Errorf("%w: invalid: risk '100'", errInvalid), - }, - } - - for _, tt := range tests { - tt := tt - t.Run(tt.name, func(t *testing.T) { - t.Parallel() - err := validate(tt.rule) - if err != nil { - if tt.wantErr == nil || !cmp.Equal(tt.wantErr.Error(), err.Error()) { - t.Logf("got: %s", err.Error()) - t.Errorf("validate() error = %v, wantErr %v", err, cmp.Diff(tt.wantErr.Error(), err.Error())) - } - return - } - if tt.wantErr != nil { - t.Errorf("validate() error = %v, wantErr %v", err, cmp.Diff(tt.wantErr, err)) - } - }) - } -} diff --git a/rule/testdata/all-fields.yml b/rule/testdata/all-fields.yml deleted file mode 100644 index 8f4ac0c957b..00000000000 --- a/rule/testdata/all-fields.yml +++ /dev/null @@ -1,17 +0,0 @@ -short: short description -desc: description -motivation: > - line1 - line2 -implementation: > - line1 - line2 -risk: High -remediation: - effort: Low - text: - - step1 - - step2 https://www.google.com/something - markdown: - - step1 - - step2 [google.com](https://www.google.com/something) diff --git a/rule/testdata/invalid-effort.yml b/rule/testdata/invalid-effort.yml deleted file mode 100644 index 58ad228153b..00000000000 --- a/rule/testdata/invalid-effort.yml +++ /dev/null @@ -1,17 +0,0 @@ -short: short description -desc: description -motivation: > - line1 - line2 -implementation: > - line1 - line2 -risk: High -remediation: - effort: invalid - text: - - step1 - - step2 https://www.google.com/something - markdown: - - step1 - - step2 [google.com](https://www.google.com/something) diff --git a/rule/testdata/invalid-risk.yml b/rule/testdata/invalid-risk.yml deleted file mode 100644 index 0f8e601806b..00000000000 --- a/rule/testdata/invalid-risk.yml +++ /dev/null @@ -1,17 +0,0 @@ -short: short description -desc: description -motivation: > - line1 - line2 -implementation: > - line1 - line2 -risk: invalid -remediation: - effort: Low - text: - - step1 - - step2 https://www.google.com/something - markdown: - - step1 - - step2 [google.com](https://www.google.com/something)