github.com/google/osv-scalibr@v0.4.1/clients/datasource/maven_registry_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 datasource_test
    16  
    17  import (
    18  	"bytes"
    19  	"os"
    20  	"path/filepath"
    21  	"reflect"
    22  	"testing"
    23  
    24  	"deps.dev/util/maven"
    25  	"github.com/google/osv-scalibr/clients/clienttest"
    26  	"github.com/google/osv-scalibr/clients/datasource"
    27  )
    28  
    29  func TestGetProject(t *testing.T) {
    30  	srv := clienttest.NewMockHTTPServer(t)
    31  	client, _ := datasource.NewDefaultMavenRegistryAPIClient(t.Context(), srv.URL)
    32  	srv.SetResponse(t, "org/example/x.y.z/1.0.0/x.y.z-1.0.0.pom", []byte(`
    33  	<project>
    34  	  <groupId>org.example</groupId>
    35  	  <artifactId>x.y.z</artifactId>
    36  	  <version>1.0.0</version>
    37  	</project>
    38  	`))
    39  
    40  	got, err := client.GetProject(t.Context(), "org.example", "x.y.z", "1.0.0")
    41  	if err != nil {
    42  		t.Fatalf("failed to get Maven project %s:%s verion %s: %v", "org.example", "x.y.z", "1.0.0", err)
    43  	}
    44  	want := maven.Project{
    45  		ProjectKey: maven.ProjectKey{
    46  			GroupID:    "org.example",
    47  			ArtifactID: "x.y.z",
    48  			Version:    "1.0.0",
    49  		},
    50  	}
    51  	if !reflect.DeepEqual(got, want) {
    52  		t.Errorf("GetProject(%s, %s, %s):\ngot %v\nwant %v\n", "org.example", "x.y.z", "1.0.0", got, want)
    53  	}
    54  }
    55  
    56  func TestGetProjectSnapshot(t *testing.T) {
    57  	srv := clienttest.NewMockHTTPServer(t)
    58  	client, _ := datasource.NewMavenRegistryAPIClient(t.Context(), datasource.MavenRegistry{URL: srv.URL, SnapshotsEnabled: true}, "", false)
    59  	srv.SetResponse(t, "org/example/x.y.z/3.3.1-SNAPSHOT/maven-metadata.xml", []byte(`
    60  	<metadata>
    61  	  <groupId>org.example</groupId>
    62  	  <artifactId>x.y.z</artifactId>
    63  	  <versioning>
    64  	  <snapshot>
    65  	    <timestamp>20230302.052731</timestamp>
    66  	    <buildNumber>9</buildNumber>
    67  	  </snapshot>
    68  	  <lastUpdated>20230302052731</lastUpdated>
    69  	  <snapshotVersions>
    70  	    <snapshotVersion>
    71  	      <extension>jar</extension>
    72  	      <value>3.3.1-20230302.052731-9</value>
    73  	      <updated>20230302052731</updated>
    74  	    </snapshotVersion>
    75  	    <snapshotVersion>
    76  	      <extension>pom</extension>
    77  	      <value>3.3.1-20230302.052731-9</value>
    78  	      <updated>20230302052731</updated>
    79  	    </snapshotVersion>
    80  	  </snapshotVersions>
    81  	  </versioning>
    82  	</metadata>
    83  	`))
    84  	srv.SetResponse(t, "org/example/x.y.z/3.3.1-SNAPSHOT/x.y.z-3.3.1-20230302.052731-9.pom", []byte(`
    85  	<project>
    86  	  <groupId>org.example</groupId>
    87  	  <artifactId>x.y.z</artifactId>
    88  	  <version>3.3.1-SNAPSHOT</version>
    89  	</project>
    90  	`))
    91  
    92  	got, err := client.GetProject(t.Context(), "org.example", "x.y.z", "3.3.1-SNAPSHOT")
    93  	if err != nil {
    94  		t.Fatalf("failed to get Maven project %s:%s verion %s: %v", "org.example", "x.y.z", "3.3.1-SNAPSHOT", err)
    95  	}
    96  	want := maven.Project{
    97  		ProjectKey: maven.ProjectKey{
    98  			GroupID:    "org.example",
    99  			ArtifactID: "x.y.z",
   100  			Version:    "3.3.1-SNAPSHOT",
   101  		},
   102  	}
   103  	if !reflect.DeepEqual(got, want) {
   104  		t.Errorf("GetProject(%s, %s, %s):\ngot %v\nwant %v\n", "org.example", "x.y.z", "3.3.1-SNAPSHOT", got, want)
   105  	}
   106  }
   107  
   108  func TestMultipleRegistry(t *testing.T) {
   109  	dft := clienttest.NewMockHTTPServer(t)
   110  	client, _ := datasource.NewDefaultMavenRegistryAPIClient(t.Context(), dft.URL)
   111  	dft.SetResponse(t, "org/example/x.y.z/maven-metadata.xml", []byte(`
   112  	<metadata>
   113  	  <groupId>org.example</groupId>
   114  	  <artifactId>x.y.z</artifactId>
   115  	  <versioning>
   116  	    <latest>3.0.0</latest>
   117  	    <release>3.0.0</release>
   118  	    <versions>
   119  	      <version>2.0.0</version>
   120  		    <version>3.0.0</version>
   121  	    </versions>
   122  	  </versioning>
   123  	</metadata>
   124  	`))
   125  	dft.SetResponse(t, "org/example/x.y.z/2.0.0/x.y.z-2.0.0.pom", []byte(`
   126  	<project>
   127  	  <groupId>org.example</groupId>
   128  	  <artifactId>x.y.z</artifactId>
   129  	  <version>2.0.0</version>
   130  	</project>
   131  	`))
   132  	dft.SetResponse(t, "org/example/x.y.z/3.0.0/x.y.z-3.0.0.pom", []byte(`
   133  	<project>
   134  	  <groupId>org.example</groupId>
   135  	  <artifactId>x.y.z</artifactId>
   136  	  <version>3.0.0</version>
   137  	</project>
   138  	`))
   139  
   140  	srv := clienttest.NewMockHTTPServer(t)
   141  	if err := client.AddRegistry(t.Context(), datasource.MavenRegistry{URL: srv.URL, ReleasesEnabled: true}); err != nil {
   142  		t.Fatalf("failed to add registry %s: %v", srv.URL, err)
   143  	}
   144  	srv.SetResponse(t, "org/example/x.y.z/maven-metadata.xml", []byte(`
   145  	<metadata>
   146  	  <groupId>org.example</groupId>
   147  	  <artifactId>x.y.z</artifactId>
   148  	  <versioning>
   149  	    <latest>2.0.0</latest>
   150  	    <release>2.0.0</release>
   151  	    <versions>
   152  	      <version>1.0.0</version>
   153  		    <version>2.0.0</version>
   154  	    </versions>
   155  	  </versioning>
   156  	</metadata>
   157  	`))
   158  	srv.SetResponse(t, "org/example/x.y.z/1.0.0/x.y.z-1.0.0.pom", []byte(`
   159  	<project>
   160  	  <groupId>org.example</groupId>
   161  	  <artifactId>x.y.z</artifactId>
   162  	  <version>1.0.0</version>
   163  	</project>
   164  	`))
   165  	srv.SetResponse(t, "org/example/x.y.z/2.0.0/x.y.z-2.0.0.pom", []byte(`
   166  	<project>
   167  	  <groupId>org.example</groupId>
   168  	  <artifactId>x.y.z</artifactId>
   169  	  <version>2.0.0</version>
   170  	</project>
   171  	`))
   172  
   173  	gotProj, err := client.GetProject(t.Context(), "org.example", "x.y.z", "1.0.0")
   174  	if err != nil {
   175  		t.Fatalf("failed to get Maven project %s:%s verion %s: %v", "org.example", "x.y.z", "1.0.0", err)
   176  	}
   177  	wantProj := maven.Project{
   178  		ProjectKey: maven.ProjectKey{
   179  			GroupID:    "org.example",
   180  			ArtifactID: "x.y.z",
   181  			Version:    "1.0.0",
   182  		},
   183  	}
   184  	if !reflect.DeepEqual(gotProj, wantProj) {
   185  		t.Errorf("GetProject(%s, %s, %s):\ngot %v\nwant %v\n", "org.example", "x.y.z", "1.0.0", gotProj, wantProj)
   186  	}
   187  
   188  	gotVersions, err := client.GetVersions(t.Context(), "org.example", "x.y.z")
   189  	if err != nil {
   190  		t.Fatalf("failed to get versions for Maven package %s:%s: %v", "org.example", "x.y.z", err)
   191  	}
   192  	wantVersions := []maven.String{"1.0.0", "2.0.0", "3.0.0"}
   193  	if !reflect.DeepEqual(gotVersions, wantVersions) {
   194  		t.Errorf("GetVersions(%s, %s):\ngot %v\nwant %v\n", "org.example", "x.y.z", gotVersions, wantVersions)
   195  	}
   196  }
   197  
   198  func TestUpdateDefaultRegistry(t *testing.T) {
   199  	dft := clienttest.NewMockHTTPServer(t)
   200  	client, _ := datasource.NewDefaultMavenRegistryAPIClient(t.Context(), dft.URL)
   201  	dft.SetResponse(t, "org/example/x.y.z/maven-metadata.xml", []byte(`
   202  	<metadata>
   203  	  <groupId>org.example</groupId>
   204  	  <artifactId>x.y.z</artifactId>
   205  	  <versioning>
   206  	    <latest>1.0.0</latest>
   207  	    <release>1.0.0</release>
   208  	    <versions>
   209  	      <version>1.0.0</version>
   210  	    </versions>
   211  	  </versioning>
   212  	</metadata>
   213  	`))
   214  
   215  	gotVersions, err := client.GetVersions(t.Context(), "org.example", "x.y.z")
   216  	if err != nil {
   217  		t.Fatalf("failed to get versions for Maven package %s:%s: %v", "org.example", "x.y.z", err)
   218  	}
   219  	wantVersions := []maven.String{"1.0.0"}
   220  	if !reflect.DeepEqual(gotVersions, wantVersions) {
   221  		t.Errorf("GetVersions(%s, %s):\ngot %v\nwant %v\n", "org.example", "x.y.z", gotVersions, wantVersions)
   222  	}
   223  
   224  	srv := clienttest.NewMockHTTPServer(t)
   225  	if err := client.AddRegistry(t.Context(), datasource.MavenRegistry{URL: srv.URL, ID: "default", ReleasesEnabled: true}); err != nil {
   226  		t.Fatalf("failed to add registry %s: %v", srv.URL, err)
   227  	}
   228  	srv.SetResponse(t, "org/example/x.y.z/maven-metadata.xml", []byte(`
   229  	<metadata>
   230  	  <groupId>org.example</groupId>
   231  	  <artifactId>x.y.z</artifactId>
   232  	  <versioning>
   233  	    <latest>2.0.0</latest>
   234  	    <release>2.0.0</release>
   235  	    <versions>
   236  	      <version>2.0.0</version>
   237  	    </versions>
   238  	  </versioning>
   239  	</metadata>
   240  	`))
   241  
   242  	gotVersions, err = client.GetVersions(t.Context(), "org.example", "x.y.z")
   243  	if err != nil {
   244  		t.Fatalf("failed to get versions for Maven package %s:%s: %v", "org.example", "x.y.z", err)
   245  	}
   246  	wantVersions = []maven.String{"2.0.0"}
   247  	if !reflect.DeepEqual(gotVersions, wantVersions) {
   248  		t.Errorf("GetVersions(%s, %s):\ngot %v\nwant %v\n", "org.example", "x.y.z", gotVersions, wantVersions)
   249  	}
   250  }
   251  
   252  func TestMavenLocalRegistry(t *testing.T) {
   253  	tempDir := t.TempDir()
   254  	srv := clienttest.NewMockHTTPServer(t)
   255  	client, _ := datasource.NewMavenRegistryAPIClient(t.Context(), datasource.MavenRegistry{URL: srv.URL, ReleasesEnabled: true}, tempDir, false)
   256  	path := "org/example/x.y.z/1.0.0/x.y.z-1.0.0.pom"
   257  	resp := []byte(`
   258  	<project>
   259  	  <groupId>org.example</groupId>
   260  	  <artifactId>x.y.z</artifactId>
   261  	  <version>1.0.0</version>
   262  	</project>`)
   263  	srv.SetResponse(t, path, resp)
   264  
   265  	_, err := client.GetProject(t.Context(), "org.example", "x.y.z", "1.0.0")
   266  	if err != nil {
   267  		t.Fatalf("failed to get Maven project %s:%s verion %s: %v", "org.example", "x.y.z", "1.0.0", err)
   268  	}
   269  
   270  	// Check that the pom file is stored locally.
   271  	filePath := filepath.Join(tempDir, "maven", path)
   272  	content, err := os.ReadFile(filePath)
   273  	if err != nil {
   274  		t.Fatalf("failed to read file: %v", err)
   275  	}
   276  	if !bytes.Equal(content, resp) {
   277  		t.Errorf("unexpected file content: got %s, want %s", string(content), string(resp))
   278  	}
   279  }