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

     1  package scanner
     2  
     3  import (
     4  	"context"
     5  	"errors"
     6  	"testing"
     7  	"time"
     8  
     9  	"github.com/stretchr/testify/assert"
    10  	"github.com/stretchr/testify/require"
    11  
    12  	"github.com/devseccon/trivy/pkg/clock"
    13  	"github.com/devseccon/trivy/pkg/fanal/artifact"
    14  	ftypes "github.com/devseccon/trivy/pkg/fanal/types"
    15  	"github.com/devseccon/trivy/pkg/types"
    16  )
    17  
    18  func TestScanner_ScanArtifact(t *testing.T) {
    19  	type args struct {
    20  		options types.ScanOptions
    21  	}
    22  	clock.SetFakeTime(t, time.Date(2021, 8, 25, 12, 20, 30, 5, time.UTC))
    23  	tests := []struct {
    24  		name               string
    25  		args               args
    26  		inspectExpectation artifact.ArtifactInspectExpectation
    27  		scanExpectation    DriverScanExpectation
    28  		want               types.Report
    29  		wantErr            string
    30  	}{
    31  		{
    32  			name: "happy path",
    33  			args: args{
    34  				options: types.ScanOptions{VulnType: []string{"os"}},
    35  			},
    36  			inspectExpectation: artifact.ArtifactInspectExpectation{
    37  				Args: artifact.ArtifactInspectArgs{
    38  					CtxAnything: true,
    39  				},
    40  				Returns: artifact.ArtifactInspectReturns{
    41  					Reference: ftypes.ArtifactReference{
    42  						Name:    "alpine:3.11",
    43  						Type:    ftypes.ArtifactContainerImage,
    44  						ID:      "sha256:e7d92cdc71feacf90708cb59182d0df1b911f8ae022d29e8e95d75ca6a99776a",
    45  						BlobIDs: []string{"sha256:5216338b40a7b96416b8b9858974bbe4acc3096ee60acbc4dfb1ee02aecceb10"},
    46  						ImageMetadata: ftypes.ImageMetadata{
    47  							ID:          "sha256:e389ae58922402a7ded319e79f06ac428d05698d8e61ecbe88d2cf850e42651d",
    48  							DiffIDs:     []string{"sha256:9a5d14f9f5503e55088666beef7e85a8d9625d4fa7418e2fe269e9c54bcb853c"},
    49  							RepoTags:    []string{"alpine:3.11"},
    50  							RepoDigests: []string{"alpine@sha256:0bd0e9e03a022c3b0226667621da84fc9bf562a9056130424b5bfbd8bcb0397f"},
    51  						},
    52  					},
    53  				},
    54  			},
    55  			scanExpectation: DriverScanExpectation{
    56  				Args: DriverScanArgs{
    57  					CtxAnything: true,
    58  					Target:      "alpine:3.11",
    59  					ImageID:     "sha256:e7d92cdc71feacf90708cb59182d0df1b911f8ae022d29e8e95d75ca6a99776a",
    60  					LayerIDs:    []string{"sha256:5216338b40a7b96416b8b9858974bbe4acc3096ee60acbc4dfb1ee02aecceb10"},
    61  					Options:     types.ScanOptions{VulnType: []string{"os"}},
    62  				},
    63  				Returns: DriverScanReturns{
    64  					Results: types.Results{
    65  						{
    66  							Target: "alpine:3.11",
    67  							Vulnerabilities: []types.DetectedVulnerability{
    68  								{
    69  									VulnerabilityID:  "CVE-2019-9999",
    70  									PkgName:          "vim",
    71  									InstalledVersion: "1.2.3",
    72  									FixedVersion:     "1.2.4",
    73  									Layer: ftypes.Layer{
    74  										Digest: "sha256:5216338b40a7b96416b8b9858974bbe4acc3096ee60acbc4dfb1ee02aecceb10",
    75  										DiffID: "sha256:b2a1a2d80bf0c747a4f6b0ca6af5eef23f043fcdb1ed4f3a3e750aef2dc68079",
    76  									},
    77  								},
    78  							},
    79  						},
    80  						{
    81  							Target: "node-app/package-lock.json",
    82  							Vulnerabilities: []types.DetectedVulnerability{
    83  								{
    84  									VulnerabilityID:  "CVE-2019-11358",
    85  									PkgName:          "jquery",
    86  									InstalledVersion: "3.3.9",
    87  									FixedVersion:     ">=3.4.0",
    88  								},
    89  							},
    90  							Type: "npm",
    91  						},
    92  					},
    93  					OsFound: ftypes.OS{
    94  						Family: "alpine",
    95  						Name:   "3.10",
    96  						Eosl:   true,
    97  					},
    98  				},
    99  			},
   100  			want: types.Report{
   101  				SchemaVersion: 2,
   102  				CreatedAt:     time.Date(2021, 8, 25, 12, 20, 30, 5, time.UTC),
   103  				ArtifactName:  "alpine:3.11",
   104  				ArtifactType:  ftypes.ArtifactContainerImage,
   105  				Metadata: types.Metadata{
   106  					OS: &ftypes.OS{
   107  						Family: "alpine",
   108  						Name:   "3.10",
   109  						Eosl:   true,
   110  					},
   111  					ImageID:     "sha256:e389ae58922402a7ded319e79f06ac428d05698d8e61ecbe88d2cf850e42651d",
   112  					DiffIDs:     []string{"sha256:9a5d14f9f5503e55088666beef7e85a8d9625d4fa7418e2fe269e9c54bcb853c"},
   113  					RepoTags:    []string{"alpine:3.11"},
   114  					RepoDigests: []string{"alpine@sha256:0bd0e9e03a022c3b0226667621da84fc9bf562a9056130424b5bfbd8bcb0397f"},
   115  				},
   116  				Results: types.Results{
   117  					{
   118  						Target: "alpine:3.11",
   119  						Vulnerabilities: []types.DetectedVulnerability{
   120  							{
   121  								VulnerabilityID:  "CVE-2019-9999",
   122  								PkgName:          "vim",
   123  								InstalledVersion: "1.2.3",
   124  								FixedVersion:     "1.2.4",
   125  								Layer: ftypes.Layer{
   126  									Digest: "sha256:5216338b40a7b96416b8b9858974bbe4acc3096ee60acbc4dfb1ee02aecceb10",
   127  									DiffID: "sha256:b2a1a2d80bf0c747a4f6b0ca6af5eef23f043fcdb1ed4f3a3e750aef2dc68079",
   128  								},
   129  							},
   130  						},
   131  					},
   132  					{
   133  						Target: "node-app/package-lock.json",
   134  						Vulnerabilities: []types.DetectedVulnerability{
   135  							{
   136  								VulnerabilityID:  "CVE-2019-11358",
   137  								PkgName:          "jquery",
   138  								InstalledVersion: "3.3.9",
   139  								FixedVersion:     ">=3.4.0",
   140  							},
   141  						},
   142  						Type: "npm",
   143  					},
   144  				},
   145  			},
   146  		},
   147  		{
   148  			name: "sad path: AnalyzerAnalyze returns an error",
   149  			args: args{
   150  				options: types.ScanOptions{VulnType: []string{"os"}},
   151  			},
   152  			inspectExpectation: artifact.ArtifactInspectExpectation{
   153  				Args: artifact.ArtifactInspectArgs{
   154  					CtxAnything: true,
   155  				},
   156  				Returns: artifact.ArtifactInspectReturns{
   157  					Err: errors.New("error"),
   158  				},
   159  			},
   160  			wantErr: "failed analysis",
   161  		},
   162  		{
   163  			name: "sad path: Scan returns an error",
   164  			args: args{
   165  				options: types.ScanOptions{VulnType: []string{"os"}},
   166  			},
   167  			inspectExpectation: artifact.ArtifactInspectExpectation{
   168  				Args: artifact.ArtifactInspectArgs{
   169  					CtxAnything: true,
   170  				},
   171  				Returns: artifact.ArtifactInspectReturns{
   172  					Reference: ftypes.ArtifactReference{
   173  						Name:    "alpine:3.11",
   174  						ID:      "sha256:e7d92cdc71feacf90708cb59182d0df1b911f8ae022d29e8e95d75ca6a99776a",
   175  						BlobIDs: []string{"sha256:5216338b40a7b96416b8b9858974bbe4acc3096ee60acbc4dfb1ee02aecceb10"},
   176  					},
   177  				},
   178  			},
   179  			scanExpectation: DriverScanExpectation{
   180  				Args: DriverScanArgs{
   181  					CtxAnything: true,
   182  					Target:      "alpine:3.11",
   183  					ImageID:     "sha256:e7d92cdc71feacf90708cb59182d0df1b911f8ae022d29e8e95d75ca6a99776a",
   184  					LayerIDs:    []string{"sha256:5216338b40a7b96416b8b9858974bbe4acc3096ee60acbc4dfb1ee02aecceb10"},
   185  					Options:     types.ScanOptions{VulnType: []string{"os"}},
   186  				},
   187  				Returns: DriverScanReturns{
   188  					Err: errors.New("error"),
   189  				},
   190  			},
   191  			wantErr: "scan failed",
   192  		},
   193  	}
   194  	for _, tt := range tests {
   195  		t.Run(tt.name, func(t *testing.T) {
   196  			d := new(MockDriver)
   197  			d.ApplyScanExpectation(tt.scanExpectation)
   198  
   199  			mockArtifact := new(artifact.MockArtifact)
   200  			mockArtifact.ApplyInspectExpectation(tt.inspectExpectation)
   201  
   202  			s := NewScanner(d, mockArtifact)
   203  			got, err := s.ScanArtifact(context.Background(), tt.args.options)
   204  			if tt.wantErr != "" {
   205  				require.NotNil(t, err, tt.name)
   206  				require.Contains(t, err.Error(), tt.wantErr, tt.name)
   207  				return
   208  			} else {
   209  				require.NoError(t, err, tt.name)
   210  			}
   211  
   212  			assert.Equal(t, tt.want, got, tt.name)
   213  		})
   214  	}
   215  }