github.com/google/osv-scalibr@v0.4.1/guidedremediation/internal/strategy/relax/relaxer/npm_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 relaxer_test
    16  
    17  import (
    18  	"testing"
    19  
    20  	"deps.dev/util/resolve"
    21  	"github.com/google/osv-scalibr/guidedremediation/internal/strategy/relax/relaxer"
    22  	"github.com/google/osv-scalibr/guidedremediation/upgrade"
    23  )
    24  
    25  func TestRelaxNpm(t *testing.T) {
    26  	type result struct {
    27  		version string
    28  		ok      bool
    29  	}
    30  	tests := []struct {
    31  		name          string
    32  		versions      []string
    33  		from          string
    34  		upgradeConfig upgrade.Config
    35  		want          result
    36  	}{
    37  		{
    38  			name:          "pinned-to-patch",
    39  			versions:      []string{"1.2.3", "1.2.4", "1.2.5", "1.3.0", "2.0.0"},
    40  			from:          "1.2.3",
    41  			upgradeConfig: upgrade.Config{"": upgrade.Minor},
    42  			want: result{
    43  				version: "~1.2.5",
    44  				ok:      true,
    45  			},
    46  		},
    47  		{
    48  			name:          "patch-to-minor",
    49  			versions:      []string{"1.2.3", "1.2.4", "1.3.0", "1.3.1", "2.0.0"},
    50  			from:          "~1.2.3",
    51  			upgradeConfig: upgrade.Config{"": upgrade.Minor},
    52  			want: result{
    53  				version: "^1.3.1",
    54  				ok:      true,
    55  			},
    56  		},
    57  		{
    58  			name:          "minor-to-next-major",
    59  			versions:      []string{"1.2.3", "1.3.4", "2.3.4", "2.4.5", "3.0.0"},
    60  			from:          "^1.2.3",
    61  			upgradeConfig: upgrade.Config{"": upgrade.Major},
    62  			want: result{
    63  				version: "^2.4.5",
    64  				ok:      true,
    65  			},
    66  		},
    67  		{
    68  			name:          "skip-missing-major",
    69  			versions:      []string{"1.0.0", "3.0.0", "4.0.0"},
    70  			from:          "^1.0.0",
    71  			upgradeConfig: upgrade.Config{"": upgrade.Major},
    72  			want: result{
    73  				version: "^3.0.0",
    74  				ok:      true,
    75  			},
    76  		},
    77  		{
    78  			name:          "no-more-versions",
    79  			versions:      []string{"1.2.3", "1.3.4", "1.4.5"},
    80  			from:          "^1.2.3",
    81  			upgradeConfig: upgrade.Config{"": upgrade.Major},
    82  			want: result{
    83  				version: "^1.2.3",
    84  				ok:      false,
    85  			},
    86  		},
    87  		{
    88  			name:          "avoid-prerelease-patch",
    89  			versions:      []string{"1.2.3", "1.2.4", "1.2.5-alpha"},
    90  			from:          "1.2.3",
    91  			upgradeConfig: upgrade.Config{"": upgrade.Minor},
    92  			want: result{
    93  				version: "~1.2.4",
    94  				ok:      true,
    95  			},
    96  		},
    97  		{
    98  			name:          "avoid-prerelease-minor",
    99  			versions:      []string{"1.2.3", "1.3.4", "1.4.5-alpha"},
   100  			from:          "~1.2.3",
   101  			upgradeConfig: upgrade.Config{"": upgrade.Major},
   102  			want: result{
   103  				version: "^1.3.4",
   104  				ok:      true,
   105  			},
   106  		},
   107  		{
   108  			name:          "skip-prerelease",
   109  			versions:      []string{"1.2.3", "2.0.0-alpha", "2.0.0", "3.0.0"},
   110  			from:          "^1.0.0",
   111  			upgradeConfig: upgrade.Config{"": upgrade.Major},
   112  			want: result{
   113  				version: "^2.0.0",
   114  				ok:      true,
   115  			},
   116  		},
   117  		{
   118  			name:          "choose-final-prerelease",
   119  			versions:      []string{"1.2.3", "2.0.0-alpha.0", "2.0.0-alpha.1", "2.0.0-beta"},
   120  			from:          "^1.0.0",
   121  			upgradeConfig: upgrade.Config{"": upgrade.Major},
   122  			want: result{
   123  				version: "^2.0.0-beta",
   124  				ok:      true,
   125  			},
   126  		},
   127  		{
   128  			name:          "from-prerelease",
   129  			versions:      []string{"1.0.0-pre", "1.2.3", "2.0.0-pre", "2.3.4"},
   130  			from:          "^1.0.0-pre",
   131  			upgradeConfig: upgrade.Config{"": upgrade.Major},
   132  			want: result{
   133  				version: "^2.3.4",
   134  				ok:      true,
   135  			},
   136  		},
   137  		{
   138  			name:          "disallow-major",
   139  			versions:      []string{"1.2.3", "1.3.4", "2.3.4", "2.4.5", "3.0.0"},
   140  			from:          "^1.2.3",
   141  			upgradeConfig: upgrade.Config{"": upgrade.Minor},
   142  			want: result{
   143  				version: "^1.2.3",
   144  				ok:      false,
   145  			},
   146  		},
   147  		{
   148  			name:          "disallow-major-pkg-only",
   149  			versions:      []string{"1.2.3", "1.3.4", "2.3.4", "2.4.5", "3.0.0"},
   150  			from:          "^1.2.3",
   151  			upgradeConfig: upgrade.Config{"disallow-major-pkg-only": upgrade.Minor, "": upgrade.None},
   152  			want: result{
   153  				version: "^1.2.3",
   154  				ok:      false,
   155  			},
   156  		},
   157  		{
   158  			name:          "disallow-pkg",
   159  			versions:      []string{"1.2.3", "1.3.4", "2.3.4", "2.4.5", "3.0.0"},
   160  			from:          "^1.2.3",
   161  			upgradeConfig: upgrade.Config{"disallow-pkg": upgrade.None},
   162  			want: result{
   163  				version: "^1.2.3",
   164  				ok:      false,
   165  			},
   166  		},
   167  		{
   168  			name:          "disallow-minor",
   169  			versions:      []string{"1.2.3", "1.3.4", "2.3.4", "2.4.5", "3.0.0"},
   170  			from:          "~1.2.3",
   171  			upgradeConfig: upgrade.Config{"disallow-minor": upgrade.Patch},
   172  			want: result{
   173  				version: "~1.2.3",
   174  				ok:      false,
   175  			},
   176  		},
   177  	}
   178  
   179  	for _, tt := range tests {
   180  		t.Run(tt.name, func(t *testing.T) {
   181  			cl := resolve.NewLocalClient()
   182  			pk := resolve.PackageKey{
   183  				Name:   tt.name,
   184  				System: resolve.NPM,
   185  			}
   186  			for _, v := range tt.versions {
   187  				cl.AddVersion(resolve.Version{
   188  					VersionKey: resolve.VersionKey{
   189  						PackageKey:  pk,
   190  						Version:     v,
   191  						VersionType: resolve.Concrete,
   192  					},
   193  				}, nil)
   194  			}
   195  
   196  			reqRelaxer := relaxer.NpmRelaxer{}
   197  			got, ok := reqRelaxer.Relax(t.Context(), cl, resolve.RequirementVersion{
   198  				VersionKey: resolve.VersionKey{
   199  					PackageKey:  pk,
   200  					VersionType: resolve.Requirement,
   201  					Version:     tt.from,
   202  				}}, tt.upgradeConfig)
   203  
   204  			if got.Version != tt.want.version || ok != tt.want.ok {
   205  				t.Errorf("Relax() = (%s, %v), want (%s, %v)", got.Version, ok, tt.want.version, tt.want.ok)
   206  			}
   207  		})
   208  	}
   209  }