github.com/google/osv-scalibr@v0.4.1/guidedremediation/internal/manifest/python/pipfile_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 python 16 17 import ( 18 "os" 19 "path/filepath" 20 "testing" 21 22 "deps.dev/util/resolve" 23 "deps.dev/util/resolve/dep" 24 "github.com/google/go-cmp/cmp" 25 "github.com/google/osv-scalibr/fs" 26 "github.com/google/osv-scalibr/guidedremediation/internal/manifest" 27 "github.com/google/osv-scalibr/guidedremediation/result" 28 ) 29 30 func TestReadPipfile(t *testing.T) { 31 fsys := fs.DirFS("./testdata/pipfile") 32 pipfileRW, _ := GetPipfileReadWriter() 33 got, err := pipfileRW.Read("Pipfile", fsys) 34 if err != nil { 35 t.Fatalf("error reading manifest: %v", err) 36 } 37 38 var devDepType dep.Type 39 devDepType.AddAttr(dep.Dev, "") 40 41 want := testManifest{ 42 FilePath: "Pipfile", 43 Root: resolve.Version{ 44 VersionKey: resolve.VersionKey{ 45 PackageKey: resolve.PackageKey{ 46 System: resolve.PyPI, 47 Name: "rootproject", 48 }, 49 VersionType: resolve.Concrete, 50 Version: "1.0.0", 51 }, 52 }, 53 System: resolve.PyPI, 54 Requirements: []resolve.RequirementVersion{ 55 { 56 VersionKey: resolve.VersionKey{ 57 PackageKey: resolve.PackageKey{System: resolve.PyPI, Name: "requests"}, 58 Version: "*", 59 VersionType: resolve.Requirement, 60 }, 61 }, 62 { 63 VersionKey: resolve.VersionKey{ 64 PackageKey: resolve.PackageKey{System: resolve.PyPI, Name: "flask"}, 65 Version: "==2.0.1", 66 VersionType: resolve.Requirement, 67 }, 68 }, 69 { 70 VersionKey: resolve.VersionKey{ 71 PackageKey: resolve.PackageKey{System: resolve.PyPI, Name: "numpy"}, 72 Version: ">=1.20.0,<2.0.0", 73 VersionType: resolve.Requirement, 74 }, 75 }, 76 { 77 VersionKey: resolve.VersionKey{ 78 PackageKey: resolve.PackageKey{System: resolve.PyPI, Name: "pandas"}, 79 Version: "~=1.3.0", 80 VersionType: resolve.Requirement, 81 }, 82 }, 83 { 84 VersionKey: resolve.VersionKey{ 85 PackageKey: resolve.PackageKey{System: resolve.PyPI, Name: "django"}, 86 Version: ">=3.2", 87 VersionType: resolve.Requirement, 88 }, 89 }, 90 { 91 VersionKey: resolve.VersionKey{ 92 PackageKey: resolve.PackageKey{System: resolve.PyPI, Name: "sentry-sdk"}, 93 Version: ">=1.0.0", 94 VersionType: resolve.Requirement, 95 }, 96 }, 97 { 98 VersionKey: resolve.VersionKey{ 99 PackageKey: resolve.PackageKey{System: resolve.PyPI, Name: "gunicorn"}, 100 Version: "*", 101 VersionType: resolve.Requirement, 102 }, 103 }, 104 { 105 VersionKey: resolve.VersionKey{ 106 PackageKey: resolve.PackageKey{System: resolve.PyPI, Name: "waitress"}, 107 Version: "*", 108 VersionType: resolve.Requirement, 109 }, 110 }, 111 { 112 VersionKey: resolve.VersionKey{ 113 PackageKey: resolve.PackageKey{System: resolve.PyPI, Name: "private-package"}, 114 Version: "*", 115 VersionType: resolve.Requirement, 116 }, 117 }, 118 { 119 VersionKey: resolve.VersionKey{ 120 PackageKey: resolve.PackageKey{System: resolve.PyPI, Name: "pytest"}, 121 Version: ">=6.0.0", 122 VersionType: resolve.Requirement, 123 }, 124 Type: devDepType, 125 }, 126 { 127 VersionKey: resolve.VersionKey{ 128 PackageKey: resolve.PackageKey{System: resolve.PyPI, Name: "black"}, 129 Version: "==21.5b2", 130 VersionType: resolve.Requirement, 131 }, 132 Type: devDepType, 133 }, 134 { 135 VersionKey: resolve.VersionKey{ 136 PackageKey: resolve.PackageKey{System: resolve.PyPI, Name: "mypy"}, 137 Version: "*", 138 VersionType: resolve.Requirement, 139 }, 140 Type: devDepType, 141 }, 142 { 143 VersionKey: resolve.VersionKey{ 144 PackageKey: resolve.PackageKey{System: resolve.PyPI, Name: "sphinx"}, 145 Version: ">=4.0.0", 146 VersionType: resolve.Requirement, 147 }, 148 Type: devDepType, 149 }, 150 }, 151 Groups: map[manifest.RequirementKey][]string{ 152 manifest.RequirementKey(resolve.PackageKey{System: resolve.PyPI, Name: "pytest"}): {"dev"}, 153 manifest.RequirementKey(resolve.PackageKey{System: resolve.PyPI, Name: "black"}): {"dev"}, 154 manifest.RequirementKey(resolve.PackageKey{System: resolve.PyPI, Name: "mypy"}): {"dev"}, 155 manifest.RequirementKey(resolve.PackageKey{System: resolve.PyPI, Name: "sphinx"}): {"dev"}, 156 }, 157 } 158 checkManifest(t, "Manifest", got, want) 159 } 160 161 func TestWritePipfile(t *testing.T) { 162 rw, _ := GetPipfileReadWriter() 163 fsys := fs.DirFS("./testdata/pipfile") 164 manif, err := rw.Read("Pipfile", fsys) 165 if err != nil { 166 t.Fatalf("error reading manifest: %v", err) 167 } 168 169 patches := []result.Patch{ 170 { 171 PackageUpdates: []result.PackageUpdate{ 172 { 173 Name: "flask", 174 VersionFrom: "==2.0.1", 175 VersionTo: "==2.0.2", 176 }, 177 { 178 Name: "pandas", 179 VersionFrom: "~=1.3.0", 180 VersionTo: ">=1.4.0,<2.0.0", 181 }, 182 { 183 Name: "numpy", 184 VersionFrom: ">=1.20.0,<2.0.0", 185 VersionTo: ">=2.0.0,<3.0.0", 186 }, 187 { 188 Name: "black", 189 VersionFrom: "==21.5b2", 190 VersionTo: "==22.0.0", 191 }, 192 }, 193 }, 194 } 195 outDir := t.TempDir() 196 outFile := filepath.Join(outDir, "Pipfile") 197 198 if err := rw.Write(manif, fsys, patches, outFile); err != nil { 199 t.Fatalf("failed to write manifest: %v", err) 200 } 201 202 got, err := os.ReadFile(outFile) 203 if err != nil { 204 t.Fatalf("failed to read got Pipfile: %v", err) 205 } 206 want, err := os.ReadFile(filepath.Join("./testdata/pipfile", "want.Pipfile")) 207 if err != nil { 208 t.Fatalf("failed to read want Pipfile: %v", err) 209 } 210 if diff := cmp.Diff(want, got); diff != "" { 211 t.Errorf("Pipfile (-want +got):\n%s", diff) 212 } 213 }