github.com/google/osv-scalibr@v0.4.1/extractor/filesystem/language/java/gradlelockfile/gradlelockfile_test.go (about)

     1  // Copyright 2025 Google LLC
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //      http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  package gradlelockfile_test
    16  
    17  import (
    18  	"testing"
    19  
    20  	"github.com/google/go-cmp/cmp"
    21  	"github.com/google/go-cmp/cmp/cmpopts"
    22  	"github.com/google/osv-scalibr/extractor"
    23  	"github.com/google/osv-scalibr/extractor/filesystem/language/java/gradlelockfile"
    24  	"github.com/google/osv-scalibr/extractor/filesystem/language/java/javalockfile"
    25  	"github.com/google/osv-scalibr/extractor/filesystem/simplefileapi"
    26  	"github.com/google/osv-scalibr/inventory"
    27  	"github.com/google/osv-scalibr/purl"
    28  	"github.com/google/osv-scalibr/testing/extracttest"
    29  )
    30  
    31  func TestExtractor_FileRequired(t *testing.T) {
    32  	tests := []struct {
    33  		inputPath string
    34  		want      bool
    35  	}{
    36  		{
    37  			inputPath: "",
    38  			want:      false,
    39  		},
    40  		{
    41  			inputPath: "buildscript-gradle.lockfile",
    42  			want:      true,
    43  		},
    44  		{
    45  			inputPath: "path/to/my/buildscript-gradle.lockfile",
    46  			want:      true,
    47  		},
    48  		{
    49  			inputPath: "path/to/my/buildscript-gradle.lockfile/file",
    50  			want:      false,
    51  		},
    52  		{
    53  			inputPath: "path/to/my/buildscript-gradle.lockfile.file",
    54  			want:      false,
    55  		},
    56  		{
    57  			inputPath: "path.to.my.buildscript-gradle.lockfile",
    58  			want:      false,
    59  		},
    60  		{
    61  			inputPath: "gradle.lockfile",
    62  			want:      true,
    63  		},
    64  		{
    65  			inputPath: "path/to/my/gradle.lockfile",
    66  			want:      true,
    67  		},
    68  		{
    69  			inputPath: "path/to/my/gradle.lockfile/file",
    70  			want:      false,
    71  		},
    72  		{
    73  			inputPath: "path/to/my/gradle.lockfile.file",
    74  			want:      false,
    75  		},
    76  		{
    77  			inputPath: "path.to.my.gradle.lockfile",
    78  			want:      false,
    79  		},
    80  	}
    81  	for _, tt := range tests {
    82  		t.Run(tt.inputPath, func(t *testing.T) {
    83  			e := gradlelockfile.Extractor{}
    84  			got := e.FileRequired(simplefileapi.New(tt.inputPath, nil))
    85  			if got != tt.want {
    86  				t.Errorf("FileRequired(%s, FileInfo) got = %v, want %v", tt.inputPath, got, tt.want)
    87  			}
    88  		})
    89  	}
    90  }
    91  
    92  func TestExtractor_Extract(t *testing.T) {
    93  	tests := []extracttest.TestTableEntry{
    94  		{
    95  			Name: "only comments",
    96  			InputConfig: extracttest.ScanInputMockConfig{
    97  				Path: "testdata/only-comments",
    98  			},
    99  			WantPackages: []*extractor.Package{},
   100  		},
   101  		{
   102  			Name: "empty statement",
   103  			InputConfig: extracttest.ScanInputMockConfig{
   104  				Path: "testdata/only-empty",
   105  			},
   106  			WantPackages: []*extractor.Package{},
   107  		},
   108  		{
   109  			Name: "one package",
   110  			InputConfig: extracttest.ScanInputMockConfig{
   111  				Path: "testdata/one-pkg",
   112  			},
   113  			WantPackages: []*extractor.Package{
   114  				{
   115  					Name:      "org.springframework.security:spring-security-crypto",
   116  					Version:   "5.7.3",
   117  					PURLType:  purl.TypeMaven,
   118  					Locations: []string{"testdata/one-pkg"},
   119  					Metadata: &javalockfile.Metadata{
   120  						ArtifactID: "spring-security-crypto",
   121  						GroupID:    "org.springframework.security",
   122  					},
   123  				},
   124  			},
   125  		},
   126  		{
   127  			Name: "multiple package",
   128  			InputConfig: extracttest.ScanInputMockConfig{
   129  				Path: "testdata/5-pkg",
   130  			},
   131  			WantPackages: []*extractor.Package{
   132  				{
   133  					Name:      "org.springframework.boot:spring-boot-autoconfigure",
   134  					Version:   "2.7.4",
   135  					PURLType:  purl.TypeMaven,
   136  					Locations: []string{"testdata/5-pkg"},
   137  					Metadata: &javalockfile.Metadata{
   138  						ArtifactID: "spring-boot-autoconfigure",
   139  						GroupID:    "org.springframework.boot",
   140  					},
   141  				},
   142  				{
   143  					Name:      "org.springframework.boot:spring-boot-configuration-processor",
   144  					Version:   "2.7.5",
   145  					PURLType:  purl.TypeMaven,
   146  					Locations: []string{"testdata/5-pkg"},
   147  					Metadata: &javalockfile.Metadata{
   148  						ArtifactID: "spring-boot-configuration-processor",
   149  						GroupID:    "org.springframework.boot",
   150  					},
   151  				},
   152  				{
   153  					Name:      "org.springframework.boot:spring-boot-devtools",
   154  					Version:   "2.7.6",
   155  					PURLType:  purl.TypeMaven,
   156  					Locations: []string{"testdata/5-pkg"},
   157  					Metadata: &javalockfile.Metadata{
   158  						ArtifactID: "spring-boot-devtools",
   159  						GroupID:    "org.springframework.boot",
   160  					},
   161  				},
   162  				{
   163  					Name:      "org.springframework.boot:spring-boot-starter-aop",
   164  					Version:   "2.7.7",
   165  					PURLType:  purl.TypeMaven,
   166  					Locations: []string{"testdata/5-pkg"},
   167  					Metadata: &javalockfile.Metadata{
   168  						ArtifactID: "spring-boot-starter-aop",
   169  						GroupID:    "org.springframework.boot",
   170  					},
   171  				},
   172  				{
   173  					Name:      "org.springframework.boot:spring-boot-starter-data-jpa",
   174  					Version:   "2.7.8",
   175  					PURLType:  purl.TypeMaven,
   176  					Locations: []string{"testdata/5-pkg"},
   177  					Metadata: &javalockfile.Metadata{
   178  						ArtifactID: "spring-boot-starter-data-jpa",
   179  						GroupID:    "org.springframework.boot",
   180  					},
   181  				},
   182  			},
   183  		},
   184  		{
   185  			Name: "with invalid lines",
   186  			InputConfig: extracttest.ScanInputMockConfig{
   187  				Path: "testdata/with-bad-pkg",
   188  			},
   189  			WantPackages: []*extractor.Package{
   190  				{
   191  					Name:      "org.springframework.boot:spring-boot-autoconfigure",
   192  					Version:   "2.7.4",
   193  					PURLType:  purl.TypeMaven,
   194  					Locations: []string{"testdata/with-bad-pkg"},
   195  					Metadata: &javalockfile.Metadata{
   196  						ArtifactID: "spring-boot-autoconfigure",
   197  						GroupID:    "org.springframework.boot",
   198  					},
   199  				},
   200  				{
   201  					Name:      "org.springframework.boot:spring-boot-configuration-processor",
   202  					Version:   "2.7.5",
   203  					PURLType:  purl.TypeMaven,
   204  					Locations: []string{"testdata/with-bad-pkg"},
   205  					Metadata: &javalockfile.Metadata{
   206  						ArtifactID: "spring-boot-configuration-processor",
   207  						GroupID:    "org.springframework.boot",
   208  					},
   209  				},
   210  			},
   211  		},
   212  	}
   213  
   214  	for _, tt := range tests {
   215  		t.Run(tt.Name, func(t *testing.T) {
   216  			extr := gradlelockfile.Extractor{}
   217  
   218  			scanInput := extracttest.GenerateScanInputMock(t, tt.InputConfig)
   219  			defer extracttest.CloseTestScanInput(t, scanInput)
   220  
   221  			got, err := extr.Extract(t.Context(), &scanInput)
   222  
   223  			if diff := cmp.Diff(tt.WantErr, err, cmpopts.EquateErrors()); diff != "" {
   224  				t.Errorf("%s.Extract(%q) error diff (-want +got):\n%s", extr.Name(), tt.InputConfig.Path, diff)
   225  				return
   226  			}
   227  
   228  			wantInv := inventory.Inventory{Packages: tt.WantPackages}
   229  			if diff := cmp.Diff(wantInv, got, cmpopts.SortSlices(extracttest.PackageCmpLess)); diff != "" {
   230  				t.Errorf("%s.Extract(%q) diff (-want +got):\n%s", extr.Name(), tt.InputConfig.Path, diff)
   231  			}
   232  		})
   233  	}
   234  }