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  }