Skip to content

Add --verbose flag #94

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Dec 10, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 5 additions & 2 deletions check/check.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import (

"github.com/arduino/arduino-check/check/checkconfigurations"
"github.com/arduino/arduino-check/check/checkdata"
"github.com/arduino/arduino-check/check/checkresult"
"github.com/arduino/arduino-check/configuration"
"github.com/arduino/arduino-check/configuration/checkmode"
"github.com/arduino/arduino-check/project"
Expand Down Expand Up @@ -49,11 +50,13 @@ func RunChecks(project project.Type) {
}

// Output will be printed after all checks are finished when configured for "json" output format.
feedback.Printf("Running check %s: ", checkConfiguration.ID)
feedback.VerbosePrintf("Running check %s...\n", checkConfiguration.ID)

checkResult, checkOutput := checkConfiguration.CheckFunction()
reportText := result.Results.Record(project, checkConfiguration, checkResult, checkOutput)
feedback.Print(reportText)
if (checkResult == checkresult.Fail) || configuration.Verbose() {
feedback.Print(reportText)
}
}

// Checks are finished for this project, so summarize its check results in the report.
Expand Down
1 change: 1 addition & 0 deletions cli/cli.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ func Root() *cobra.Command {
rootCommand.PersistentFlags().String("project-type", "all", "Only check projects of the specified type and their subprojects. Can be {sketch|library|all}.")
rootCommand.PersistentFlags().Bool("recursive", true, "Search path recursively for Arduino projects to check. Can be {true|false}.")
rootCommand.PersistentFlags().String("report-file", "", "Save a report on the checks to this file.")
rootCommand.PersistentFlags().BoolP("verbose", "v", false, "Show more information while running checks.")
rootCommand.PersistentFlags().Bool("version", false, "Print version and timestamp of the build.")

return rootCommand
Expand Down
10 changes: 10 additions & 0 deletions configuration/configuration.go
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,8 @@ func Initialize(flags *pflag.FlagSet, projectPaths []string) error {
reportFilePathString, _ := flags.GetString("report-file")
reportFilePath = paths.New(reportFilePathString)

verbose, _ = flags.GetBool("verbose")

versionMode, _ = flags.GetBool("version")

targetPaths = nil
Expand Down Expand Up @@ -125,6 +127,7 @@ func Initialize(flags *pflag.FlagSet, projectPaths []string) error {
"superproject type filter": SuperprojectTypeFilter(),
"recursive": Recursive(),
"report file": ReportFilePath(),
"verbose": Verbose(),
"projects path": TargetPaths(),
}).Debug("Configuration initialized")

Expand Down Expand Up @@ -178,6 +181,13 @@ func ReportFilePath() *paths.Path {
return reportFilePath
}

var verbose bool

// Verbose returns the verbosity setting.
func Verbose() bool {
return verbose
}

var versionMode bool

func VersionMode() bool {
Expand Down
12 changes: 12 additions & 0 deletions configuration/configuration_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -194,6 +194,18 @@ func TestInitializeVersion(t *testing.T) {
assert.False(t, VersionMode())
}

func TestInitializeVerbose(t *testing.T) {
flags := test.ConfigurationFlags()

flags.Set("verbose", "true")
assert.Nil(t, Initialize(flags, projectPaths))
assert.True(t, Verbose())

flags.Set("verbose", "false")
assert.Nil(t, Initialize(flags, projectPaths))
assert.False(t, Verbose())
}

func TestInitializeProjectPath(t *testing.T) {
assert.Nil(t, Initialize(test.ConfigurationFlags(), []string{}))
workingDirectoryPath, err := os.Getwd()
Expand Down
12 changes: 12 additions & 0 deletions result/feedback/feedback.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,18 @@ import (
"github.com/sirupsen/logrus"
)

// VerbosePrintf behaves like Printf but only prints when verbosity is enabled.
func VerbosePrintf(format string, v ...interface{}) {
VerbosePrint(fmt.Sprintf(format, v...))
}

// VerbosePrint behaves like Print but only prints when verbosity is enabled.
func VerbosePrint(message string) {
if configuration.Verbose() && (configuration.OutputFormat() == outputformat.Text) {
Printf(message)
}
}

// Printf behaves like fmt.Printf but only prints when output format is set to `text`.
func Printf(format string, v ...interface{}) {
Print(fmt.Sprintf(format, v...))
Expand Down
33 changes: 17 additions & 16 deletions result/result.go
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@ type summaryReportType struct {

// Initialize adds the tool configuration data to the results data.
func (results *Type) Initialize() {
*results = *new(Type)
results.Configuration = toolConfigurationReportType{
Paths: configuration.TargetPaths(),
ProjectType: configuration.SuperprojectTypeFilter().String(),
Expand All @@ -98,7 +99,7 @@ func (results *Type) Record(checkedProject project.Type, checkConfiguration chec
os.Exit(1)
}

summaryText := fmt.Sprintf("%s\n", checkResult)
summaryText := fmt.Sprintf("Check %s result: %s\n", checkConfiguration.ID, checkResult)

checkMessage := ""
if checkLevel == checklevel.Error {
Expand All @@ -114,17 +115,6 @@ func (results *Type) Record(checkedProject project.Type, checkConfiguration chec
summaryText += fmt.Sprintf("%s: %s\n", checkLevel, checkMessage)
}

checkReport := checkReportType{
Category: checkConfiguration.Category,
Subcategory: checkConfiguration.Subcategory,
ID: checkConfiguration.ID,
Brief: checkConfiguration.Brief,
Description: checkConfiguration.Description,
Result: checkResult.String(),
Level: checkLevel.String(),
Message: checkMessage,
}

reportExists, projectReportIndex := results.getProjectReportIndex(checkedProject.Path)
if !reportExists {
// There is no existing report for this project.
Expand All @@ -139,11 +129,22 @@ func (results *Type) Record(checkedProject project.Type, checkConfiguration chec
LibraryManagerUpdate: configuration.CheckModes(checkedProject.ProjectType)[checkmode.LibraryManagerIndexed],
Official: configuration.CheckModes(checkedProject.ProjectType)[checkmode.Official],
},
Checks: []checkReportType{checkReport},
Checks: []checkReportType{},
},
)
} else {
// There's already a report for this project; just add the checks report to it.
}

if (checkResult == checkresult.Fail) || configuration.Verbose() {
checkReport := checkReportType{
Category: checkConfiguration.Category,
Subcategory: checkConfiguration.Subcategory,
ID: checkConfiguration.ID,
Brief: checkConfiguration.Brief,
Description: checkConfiguration.Description,
Result: checkResult.String(),
Level: checkLevel.String(),
Message: checkMessage,
}
results.Projects[projectReportIndex].Checks = append(results.Projects[projectReportIndex].Checks, checkReport)
}

Expand Down Expand Up @@ -265,7 +266,7 @@ func (results Type) getProjectReportIndex(projectPath *paths.Path) (bool, int) {
}

// There is no element in the report for this project.
return false, index + 1
return false, len(results.Projects)
}

// message fills the message template provided by the check configuration with the check output.
Expand Down
72 changes: 57 additions & 15 deletions result/result_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,16 @@ import (
"github.com/stretchr/testify/require"
)

var projectPaths []string

func init() {
projectPath, err := os.Getwd() // Path to an arbitrary folder that is guaranteed to exist.
if err != nil {
panic(err)
}
projectPaths = []string{projectPath}
}

func TestInitialize(t *testing.T) {
flags := test.ConfigurationFlags()
flags.Set("project-type", "sketch")
Expand All @@ -52,25 +62,30 @@ func TestInitialize(t *testing.T) {
}

func TestRecord(t *testing.T) {
flags := test.ConfigurationFlags()
require.Nil(t, configuration.Initialize(flags, projectPaths))

checkedProject := project.Type{
Path: paths.New("/foo/bar"),
ProjectType: projecttype.Sketch,
SuperprojectType: projecttype.Library,
}

var results Type
results.Initialize()
checkConfiguration := checkconfigurations.Configurations()[0]
checkOutput := "foo"
summaryText := results.Record(checkedProject, checkConfiguration, checkresult.Fail, checkOutput)
assert.Equal(t, fmt.Sprintf("%s\n%s: %s\n", checkresult.Fail, checklevel.Error, message(checkConfiguration.MessageTemplate, checkOutput)), summaryText)
assert.Equal(t, fmt.Sprintf("Check %s result: %s\n%s: %s\n", checkConfiguration.ID, checkresult.Fail, checklevel.Error, message(checkConfiguration.MessageTemplate, checkOutput)), summaryText)
summaryText = results.Record(checkedProject, checkConfiguration, checkresult.NotRun, checkOutput)
assert.Equal(t, fmt.Sprintf("%s\n%s: %s\n", checkresult.NotRun, checklevel.Notice, checkOutput), summaryText, "Non-fail result should not use message")
assert.Equal(t, fmt.Sprintf("Check %s result: %s\n%s: %s\n", checkConfiguration.ID, checkresult.NotRun, checklevel.Notice, checkOutput), summaryText, "Non-fail result should not use message")
summaryText = results.Record(checkedProject, checkConfiguration, checkresult.Pass, "")
assert.Equal(t, "", "", summaryText, "Non-failure result with no check function output should result in an empty summary")

flags.Set("verbose", "true")
require.Nil(t, configuration.Initialize(flags, projectPaths))
checkResult := checkresult.Pass
results = Type{}

results.Initialize()
results.Record(checkedProject, checkConfiguration, checkResult, checkOutput)
projectReport := results.Projects[0]
assert.Equal(t, checkedProject.Path, projectReport.Path)
Expand All @@ -80,7 +95,7 @@ func TestRecord(t *testing.T) {
assert.Equal(t, configuration.CheckModes(checkedProject.ProjectType)[checkmode.LibraryManagerSubmission], projectConfigurationReport.LibraryManagerSubmit)
assert.Equal(t, configuration.CheckModes(checkedProject.ProjectType)[checkmode.LibraryManagerIndexed], projectConfigurationReport.LibraryManagerUpdate)
assert.Equal(t, configuration.CheckModes(checkedProject.ProjectType)[checkmode.Official], projectConfigurationReport.Official)

assert.Equal(t, 1, len(results.Projects[0].Checks), "Passing check reports should be written to report in verbose mode")
checkReport := projectReport.Checks[0]
assert.Equal(t, checkConfiguration.Category, checkReport.Category)
assert.Equal(t, checkConfiguration.Subcategory, checkReport.Subcategory)
Expand All @@ -92,15 +107,25 @@ func TestRecord(t *testing.T) {
assert.Equal(t, checkLevel.String(), checkReport.Level)
assert.Equal(t, checkOutput, checkReport.Message)

flags.Set("verbose", "false")
require.Nil(t, configuration.Initialize(flags, projectPaths))
results.Initialize()
results.Record(checkedProject, checkConfiguration, checkresult.Pass, checkOutput)
assert.Equal(t, 0, len(results.Projects[0].Checks), "Passing check reports should not be written to report in non-verbose mode")

results.Initialize()
results.Record(checkedProject, checkConfiguration, checkresult.Fail, checkOutput)
require.Equal(t, 1, len(projectReport.Checks), "Failing check reports should be written to report in non-verbose mode")

assert.Len(t, results.Projects, 1)
previousProjectPath := checkedProject.Path
checkedProject.Path = paths.New("/foo/baz")
results.Record(checkedProject, checkConfiguration, checkResult, checkOutput)
results.Record(checkedProject, checkConfiguration, checkresult.Fail, checkOutput)
assert.Len(t, results.Projects, 2)

assert.Len(t, results.Projects[0].Checks, 1)
checkedProject.Path = previousProjectPath
results.Record(checkedProject, checkconfigurations.Configurations()[1], checkResult, checkOutput)
results.Record(checkedProject, checkconfigurations.Configurations()[1], checkresult.Fail, checkOutput)
assert.Len(t, results.Projects[0].Checks, 2)
}

Expand All @@ -114,40 +139,61 @@ func TestAddProjectSummary(t *testing.T) {
testTables := []struct {
results []checkresult.Type
levels []checklevel.Type
verbose string
expectedPass bool
expectedWarningCount int
expectedErrorCount int
}{
{
[]checkresult.Type{checkresult.Pass, checkresult.Pass},
[]checklevel.Type{checklevel.Info, checklevel.Info},
"true",
true,
0,
0,
},
{
[]checkresult.Type{checkresult.Pass, checkresult.Pass},
[]checklevel.Type{checklevel.Info, checklevel.Info},
"false",
true,
0,
0,
},
{
[]checkresult.Type{checkresult.Pass, checkresult.Fail},
[]checklevel.Type{checklevel.Info, checklevel.Warning},
"false",
true,
1,
0,
},
{
[]checkresult.Type{checkresult.Fail, checkresult.Fail},
[]checklevel.Type{checklevel.Error, checklevel.Warning},
"false",
false,
1,
1,
},
}

for _, testTable := range testTables {
flags := test.ConfigurationFlags()
flags.Set("verbose", testTable.verbose)
require.Nil(t, configuration.Initialize(flags, projectPaths))

var results Type
for _, result := range testTable.results {
results.Initialize()

checkIndex := 0
for testDataIndex, result := range testTable.results {
results.Record(checkedProject, checkconfigurations.Configurations()[0], result, "")
}
for checkIndex, level := range testTable.levels {
results.Projects[0].Checks[checkIndex].Level = level.String()
if (result == checkresult.Fail) || configuration.Verbose() {
level := testTable.levels[testDataIndex].String()
results.Projects[0].Checks[checkIndex].Level = level
checkIndex += 1
}
}
results.AddProjectSummary(checkedProject)
assert.Equal(t, testTable.expectedPass, results.Projects[0].Summary.Pass)
Expand Down Expand Up @@ -243,10 +289,6 @@ func TestAddSummary(t *testing.T) {
func TestWriteReport(t *testing.T) {
flags := test.ConfigurationFlags()

projectPath, err := os.Getwd() // Path to an arbitrary folder that is guaranteed to exist.
require.Nil(t, err)
projectPaths := []string{projectPath}

reportFolderPathString, err := ioutil.TempDir("", "arduino-check-result-TestWriteReport")
require.Nil(t, err)
defer os.RemoveAll(reportFolderPathString) // clean up
Expand Down
1 change: 1 addition & 0 deletions util/test/test.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ func ConfigurationFlags() *pflag.FlagSet {
flags.String("project-type", "all", "")
flags.Bool("recursive", true, "")
flags.String("report-file", "", "")
flags.Bool("verbose", false, "")
flags.Bool("version", false, "")

return flags
Expand Down