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 }