github.com/devseccon/trivy@v0.47.1-0.20231123133102-bd902a0bd996/pkg/flag/report_flags_test.go (about)

     1  package flag_test
     2  
     3  import (
     4  	"testing"
     5  
     6  	"github.com/spf13/viper"
     7  	"github.com/stretchr/testify/assert"
     8  	"go.uber.org/zap"
     9  	"go.uber.org/zap/zaptest/observer"
    10  
    11  	defsecTypes "github.com/aquasecurity/defsec/pkg/types"
    12  	dbTypes "github.com/aquasecurity/trivy-db/pkg/types"
    13  	"github.com/devseccon/trivy/pkg/compliance/spec"
    14  	"github.com/devseccon/trivy/pkg/flag"
    15  	"github.com/devseccon/trivy/pkg/log"
    16  	"github.com/devseccon/trivy/pkg/types"
    17  )
    18  
    19  func TestReportFlagGroup_ToOptions(t *testing.T) {
    20  	type fields struct {
    21  		format         types.Format
    22  		template       string
    23  		dependencyTree bool
    24  		listAllPkgs    bool
    25  		ignoreUnfixed  bool
    26  		ignoreFile     string
    27  		exitCode       int
    28  		exitOnEOSL     bool
    29  		ignorePolicy   string
    30  		output         string
    31  		severities     string
    32  		compliane      string
    33  
    34  		debug bool
    35  	}
    36  	tests := []struct {
    37  		name     string
    38  		fields   fields
    39  		want     flag.ReportOptions
    40  		wantLogs []string
    41  	}{
    42  		{
    43  			name:   "happy default (without flags)",
    44  			fields: fields{},
    45  			want:   flag.ReportOptions{},
    46  		},
    47  		{
    48  			name: "happy path with an cyclonedx",
    49  			fields: fields{
    50  				severities:  "CRITICAL",
    51  				format:      "cyclonedx",
    52  				listAllPkgs: true,
    53  			},
    54  			want: flag.ReportOptions{
    55  				Severities:  []dbTypes.Severity{dbTypes.SeverityCritical},
    56  				Format:      types.FormatCycloneDX,
    57  				ListAllPkgs: true,
    58  			},
    59  		},
    60  		{
    61  			name: "happy path with an cyclonedx option list-all-pkgs is false",
    62  			fields: fields{
    63  				severities:  "CRITICAL",
    64  				format:      "cyclonedx",
    65  				listAllPkgs: false,
    66  
    67  				debug: true,
    68  			},
    69  			wantLogs: []string{
    70  				`["cyclonedx" "spdx" "spdx-json" "github"] automatically enables '--list-all-pkgs'.`,
    71  				`Severities: ["CRITICAL"]`,
    72  			},
    73  			want: flag.ReportOptions{
    74  				Severities: []dbTypes.Severity{
    75  					dbTypes.SeverityCritical,
    76  				},
    77  				Format:      types.FormatCycloneDX,
    78  				ListAllPkgs: true,
    79  			},
    80  		},
    81  		{
    82  			name: "invalid option combination: --template enabled without --format",
    83  			fields: fields{
    84  				template:   "@contrib/gitlab.tpl",
    85  				severities: "LOW",
    86  			},
    87  			wantLogs: []string{
    88  				"'--template' is ignored because '--format template' is not specified. Use '--template' option with '--format template' option.",
    89  			},
    90  			want: flag.ReportOptions{
    91  				Severities: []dbTypes.Severity{dbTypes.SeverityLow},
    92  				Template:   "@contrib/gitlab.tpl",
    93  			},
    94  		},
    95  		{
    96  			name: "invalid option combination: --template and --format json",
    97  			fields: fields{
    98  				format:     "json",
    99  				template:   "@contrib/gitlab.tpl",
   100  				severities: "LOW",
   101  			},
   102  			wantLogs: []string{
   103  				"'--template' is ignored because '--format json' is specified. Use '--template' option with '--format template' option.",
   104  			},
   105  			want: flag.ReportOptions{
   106  				Format:     "json",
   107  				Severities: []dbTypes.Severity{dbTypes.SeverityLow},
   108  				Template:   "@contrib/gitlab.tpl",
   109  			},
   110  		},
   111  		{
   112  			name: "invalid option combination: --format template without --template",
   113  			fields: fields{
   114  				format:     "template",
   115  				severities: "LOW",
   116  			},
   117  			wantLogs: []string{
   118  				"'--format template' is ignored because '--template' is not specified. Specify '--template' option when you use '--format template'.",
   119  			},
   120  			want: flag.ReportOptions{
   121  				Format:     "template",
   122  				Severities: []dbTypes.Severity{dbTypes.SeverityLow},
   123  			},
   124  		},
   125  		{
   126  			name: "invalid option combination: --list-all-pkgs with --format table",
   127  			fields: fields{
   128  				format:      "table",
   129  				severities:  "LOW",
   130  				listAllPkgs: true,
   131  			},
   132  			wantLogs: []string{
   133  				`"--list-all-pkgs" cannot be used with "--format table". Try "--format json" or other formats.`,
   134  			},
   135  			want: flag.ReportOptions{
   136  				Format:      "table",
   137  				Severities:  []dbTypes.Severity{dbTypes.SeverityLow},
   138  				ListAllPkgs: true,
   139  			},
   140  		},
   141  		{
   142  			name: "happy path with compliance",
   143  			fields: fields{
   144  				compliane:  "@testdata/example-spec.yaml",
   145  				severities: dbTypes.SeverityLow.String(),
   146  			},
   147  			want: flag.ReportOptions{
   148  				Compliance: spec.ComplianceSpec{
   149  					Spec: defsecTypes.Spec{
   150  						ID:          "0001",
   151  						Title:       "my-custom-spec",
   152  						Description: "My fancy spec",
   153  						Version:     "1.2",
   154  						Controls: []defsecTypes.Control{
   155  							{
   156  								ID:          "1.1",
   157  								Name:        "Unencrypted S3 bucket",
   158  								Description: "S3 Buckets should be encrypted to protect the data that is stored within them if access is compromised.",
   159  								Checks: []defsecTypes.SpecCheck{
   160  									{ID: "AVD-AWS-0088"},
   161  								},
   162  								Severity: "HIGH",
   163  							},
   164  						},
   165  					},
   166  				},
   167  				Severities: []dbTypes.Severity{dbTypes.SeverityLow},
   168  			},
   169  		},
   170  	}
   171  	for _, tt := range tests {
   172  		t.Run(tt.name, func(t *testing.T) {
   173  			level := zap.WarnLevel
   174  			if tt.fields.debug {
   175  				level = zap.DebugLevel
   176  			}
   177  			core, obs := observer.New(level)
   178  			log.Logger = zap.New(core).Sugar()
   179  
   180  			viper.Set(flag.FormatFlag.ConfigName, string(tt.fields.format))
   181  			viper.Set(flag.TemplateFlag.ConfigName, tt.fields.template)
   182  			viper.Set(flag.DependencyTreeFlag.ConfigName, tt.fields.dependencyTree)
   183  			viper.Set(flag.ListAllPkgsFlag.ConfigName, tt.fields.listAllPkgs)
   184  			viper.Set(flag.IgnoreFileFlag.ConfigName, tt.fields.ignoreFile)
   185  			viper.Set(flag.IgnoreUnfixedFlag.ConfigName, tt.fields.ignoreUnfixed)
   186  			viper.Set(flag.IgnorePolicyFlag.ConfigName, tt.fields.ignorePolicy)
   187  			viper.Set(flag.ExitCodeFlag.ConfigName, tt.fields.exitCode)
   188  			viper.Set(flag.ExitOnEOLFlag.ConfigName, tt.fields.exitOnEOSL)
   189  			viper.Set(flag.OutputFlag.ConfigName, tt.fields.output)
   190  			viper.Set(flag.SeverityFlag.ConfigName, tt.fields.severities)
   191  			viper.Set(flag.ComplianceFlag.ConfigName, tt.fields.compliane)
   192  
   193  			// Assert options
   194  			f := &flag.ReportFlagGroup{
   195  				Format:         &flag.FormatFlag,
   196  				Template:       &flag.TemplateFlag,
   197  				DependencyTree: &flag.DependencyTreeFlag,
   198  				ListAllPkgs:    &flag.ListAllPkgsFlag,
   199  				IgnoreFile:     &flag.IgnoreFileFlag,
   200  				IgnorePolicy:   &flag.IgnorePolicyFlag,
   201  				ExitCode:       &flag.ExitCodeFlag,
   202  				ExitOnEOL:      &flag.ExitOnEOLFlag,
   203  				Output:         &flag.OutputFlag,
   204  				Severity:       &flag.SeverityFlag,
   205  				Compliance:     &flag.ComplianceFlag,
   206  			}
   207  
   208  			got, err := f.ToOptions()
   209  			assert.NoError(t, err)
   210  			assert.Equalf(t, tt.want, got, "ToOptions()")
   211  
   212  			// Assert log messages
   213  			var gotMessages []string
   214  			for _, entry := range obs.AllUntimed() {
   215  				gotMessages = append(gotMessages, entry.Message)
   216  			}
   217  			assert.Equal(t, tt.wantLogs, gotMessages, tt.name)
   218  		})
   219  	}
   220  }