🌱 Add tests for probe output format (#3841)

* rename probe format file

Signed-off-by: Spencer Schrock <sschrock@google.com>

* add option parameter to probe result output function

the ability to pretty print will help write a test function

Signed-off-by: Spencer Schrock <sschrock@google.com>

* add test func

Signed-off-by: Spencer Schrock <sschrock@google.com>

* add docstring

Signed-off-by: Spencer Schrock <sschrock@google.com>

* clarify test. add another finding

Signed-off-by: Spencer Schrock <sschrock@google.com>

* force add the test file

Signed-off-by: Spencer Schrock <sschrock@google.com>

---------

Signed-off-by: Spencer Schrock <sschrock@google.com>
This commit is contained in:
Spencer Schrock 2024-02-06 12:19:17 -08:00 committed by GitHub
parent 5a0356b1a9
commit a762812285
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 130 additions and 2 deletions

View File

@ -31,7 +31,15 @@ type JSONScorecardProbeResult struct {
Findings []finding.Finding `json:"findings"`
}
func (r *ScorecardResult) AsPJSON(writer io.Writer) error {
// ProbeResultOption provides configuration options for the ScorecardResult probe output format.
type ProbeResultOption struct {
// Indent is used to control the JSON indentation. For example, if you want to pretty print.
Indent string
}
// AsPJSON writes results as JSON for flat findings without checks.
// It accepts an optional argument to configure the output.
func (r *ScorecardResult) AsPJSON(writer io.Writer, o *ProbeResultOption) error {
encoder := json.NewEncoder(writer)
out := JSONScorecardProbeResult{
Repo: jsonRepoV2{
@ -46,6 +54,10 @@ func (r *ScorecardResult) AsPJSON(writer io.Writer) error {
Findings: r.Findings,
}
if o != nil {
encoder.SetIndent("", o.Indent)
}
if err := encoder.Encode(out); err != nil {
return sce.WithMessage(sce.ErrScorecardInternal, fmt.Sprintf("encoder.Encode: %v", err))
}

88
pkg/probe_test.go Normal file
View File

@ -0,0 +1,88 @@
// Copyright 2024 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 pkg
import (
"bytes"
"os"
"testing"
"time"
"github.com/google/go-cmp/cmp"
"github.com/ossf/scorecard/v4/finding"
)
func Test_AsPJSON(t *testing.T) {
t.Parallel()
tests := []struct {
name string
expected string
result ScorecardResult
}{
{
name: "multiple findings displayed",
expected: "./testdata/probe1.json",
result: ScorecardResult{
Repo: RepoInfo{
Name: "foo",
CommitSHA: "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
},
Scorecard: ScorecardInfo{
Version: "1.2.3",
CommitSHA: "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb",
},
Date: time.Date(2024, time.February, 1, 13, 48, 0, 0, time.UTC),
Findings: []finding.Finding{
{
Probe: "check for X",
Outcome: finding.OutcomePositive,
Message: "found X",
Location: &finding.Location{
Path: "some/path/to/file",
Type: finding.FileTypeText,
},
},
{
Probe: "check for Y",
Outcome: finding.OutcomeNegative,
Message: "did not find Y",
},
},
},
},
}
// pretty print results so the test files are easier to read
opt := &ProbeResultOption{Indent: " "}
for _, tt := range tests {
tt := tt
t.Run(tt.name, func(t *testing.T) {
t.Parallel()
expected, err := os.ReadFile(tt.expected)
if err != nil {
t.Fatalf("cannot read expected results file: %v", err)
}
var result bytes.Buffer
if err = tt.result.AsPJSON(&result, opt); err != nil {
t.Fatalf("AsPJSON: %v", err)
}
if diff := cmp.Diff(expected, result.Bytes()); diff != "" {
t.Errorf("results differ: %s", diff)
}
})
}
}

View File

@ -138,7 +138,8 @@ func FormatResults(
case options.FormatFJSON:
err = results.AsFJSON(opts.ShowDetails, log.ParseLevel(opts.LogLevel), doc, output)
case options.FormatPJSON:
err = results.AsPJSON(output)
var opts *ProbeResultOption
err = results.AsPJSON(output, opts)
case options.FormatRaw:
err = results.AsRawJSON(output)
default:

27
pkg/testdata/probe1.json vendored Normal file
View File

@ -0,0 +1,27 @@
{
"date": "2024-02-01",
"repo": {
"name": "foo",
"commit": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
},
"scorecard": {
"version": "1.2.3",
"commit": "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb"
},
"findings": [
{
"location": {
"path": "some/path/to/file",
"type": 3
},
"probe": "check for X",
"message": "found X",
"outcome": 12
},
{
"probe": "check for Y",
"message": "did not find Y",
"outcome": 0
}
]
}