github.com/yogeshkumararora/slsa-github-generator@v1.10.1-0.20240520161934-11278bd5afb4/internal/utils/path_test.go (about)

     1  // Copyright 2022 SLSA Authors
     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  //     https://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 utils
    16  
    17  import (
    18  	"errors"
    19  	"os"
    20  	"path/filepath"
    21  	"testing"
    22  
    23  	"github.com/google/go-cmp/cmp"
    24  	"github.com/google/go-cmp/cmp/cmpopts"
    25  )
    26  
    27  func Test_PathIsUnderCurrentDirectory(t *testing.T) {
    28  	t.Parallel()
    29  
    30  	tests := []struct {
    31  		expected error
    32  		name     string
    33  		path     string
    34  	}{
    35  		{
    36  			name:     "valid same path",
    37  			path:     "./",
    38  			expected: nil,
    39  		},
    40  		{
    41  			name:     "valid path no slash",
    42  			path:     "./some/valid/path",
    43  			expected: nil,
    44  		},
    45  		{
    46  			name:     "valid path with slash",
    47  			path:     "./some/valid/path/",
    48  			expected: nil,
    49  		},
    50  		{
    51  			name:     "valid path with no dot",
    52  			path:     "some/valid/path/",
    53  			expected: nil,
    54  		},
    55  		{
    56  			name:     "some valid path",
    57  			path:     "../utils/some/valid/path",
    58  			expected: nil,
    59  		},
    60  		{
    61  			name:     "parent invalid path",
    62  			path:     "../invalid/path",
    63  			expected: ErrInvalidPath,
    64  		},
    65  		{
    66  			name:     "some invalid fullpath",
    67  			path:     "/some/invalid/fullpath",
    68  			expected: ErrInvalidPath,
    69  		},
    70  	}
    71  	for _, tt := range tests {
    72  		tt := tt // Re-initializing variable so it is not changed while executing the closure below
    73  		t.Run(tt.name, func(t *testing.T) {
    74  			t.Parallel()
    75  
    76  			err := PathIsUnderCurrentDirectory(tt.path)
    77  			if (err == nil && tt.expected != nil) ||
    78  				(err != nil && tt.expected == nil) {
    79  				t.Fatalf("unexpected error: %v", cmp.Diff(err, tt.expected, cmpopts.EquateErrors()))
    80  			}
    81  
    82  			if err != nil && !errors.Is(err, tt.expected) {
    83  				t.Fatalf("unexpected error: %v", cmp.Diff(err, tt.expected, cmpopts.EquateErrors()))
    84  			}
    85  		})
    86  	}
    87  }
    88  
    89  func Test_VerifyAttestationPath(t *testing.T) {
    90  	t.Parallel()
    91  
    92  	tests := []struct {
    93  		expected error
    94  		name     string
    95  		path     string
    96  	}{
    97  		{
    98  			name:     "valid file",
    99  			path:     "./path/to/valid.intoto.jsonl",
   100  			expected: nil,
   101  		},
   102  		{
   103  			name:     "invalid path",
   104  			path:     "../some/invalid/valid.intoto.jsonl",
   105  			expected: ErrInvalidPath,
   106  		},
   107  		{
   108  			name:     "invalid extension",
   109  			path:     "some/file.ntoto.jsonl",
   110  			expected: ErrInvalidPath,
   111  		},
   112  		{
   113  			name:     "invalid not exntension",
   114  			path:     "some/file.intoto.jsonl.",
   115  			expected: ErrInvalidPath,
   116  		},
   117  		{
   118  			name:     "invalid folder exntension",
   119  			path:     "file.intoto.jsonl/file",
   120  			expected: ErrInvalidPath,
   121  		},
   122  	}
   123  	for _, tt := range tests {
   124  		tt := tt // Re-initializing variable so it is not changed while executing the closure below
   125  		t.Run(tt.name, func(t *testing.T) {
   126  			t.Parallel()
   127  
   128  			err := VerifyAttestationPath(tt.path)
   129  			if (err == nil && tt.expected != nil) ||
   130  				(err != nil && tt.expected == nil) {
   131  				t.Fatalf("unexpected error: %v", cmp.Diff(err, tt.expected, cmpopts.EquateErrors()))
   132  			}
   133  
   134  			if err != nil && !errors.Is(err, tt.expected) {
   135  				t.Fatalf("unexpected error: %v", cmp.Diff(err, tt.expected, cmpopts.EquateErrors()))
   136  			}
   137  		})
   138  	}
   139  }
   140  
   141  func tempWD() (func() error, error) {
   142  	// Set up a temporary working directory for the test.
   143  	cwd, err := os.Getwd()
   144  	if err != nil {
   145  		return nil, err
   146  	}
   147  	tempwd, err := os.MkdirTemp("", "slsa-github-generator-tests")
   148  	if err != nil {
   149  		return nil, err
   150  	}
   151  	if err := os.Chdir(tempwd); err != nil {
   152  		return nil, err
   153  	}
   154  	return func() error {
   155  		if err := os.RemoveAll(tempwd); err != nil {
   156  			return err
   157  		}
   158  		return os.Chdir(cwd)
   159  	}, nil
   160  }
   161  
   162  func Test_CreateNewFileUnderCurrentDirectory(t *testing.T) {
   163  	tests := []struct {
   164  		expected     error
   165  		name         string
   166  		path         string
   167  		existingPath bool
   168  	}{
   169  		{
   170  			name:     "valid file cannot create",
   171  			path:     "./path/to/validfile",
   172  			expected: ErrInvalidPath,
   173  		},
   174  		{
   175  			name:     "invalid path",
   176  			path:     "../some/invalid/file",
   177  			expected: ErrInvalidPath,
   178  		},
   179  		{
   180  			name:         "existing file",
   181  			path:         "existing_file",
   182  			existingPath: true,
   183  			expected:     ErrInvalidPath,
   184  		},
   185  		{
   186  			name: "new file",
   187  			path: "new_file",
   188  		},
   189  		{
   190  			name:     "new file in sub-directory",
   191  			path:     "dir/new_file",
   192  			expected: ErrInvalidPath,
   193  		},
   194  	}
   195  	for _, tt := range tests {
   196  		tt := tt // Re-initializing variable so it is not changed while executing the closure below
   197  		t.Run(tt.name, func(t *testing.T) {
   198  			cleanup, err := tempWD()
   199  			if err != nil {
   200  				t.Fatal(err)
   201  			}
   202  			defer func() {
   203  				if err := cleanup(); err != nil {
   204  					t.Fatalf("unexpected error: %v", err)
   205  				}
   206  			}()
   207  
   208  			if tt.existingPath {
   209  				if _, err := CreateNewFileUnderCurrentDirectory(tt.path, os.O_WRONLY); err != nil {
   210  					t.Fatalf("unexpected error: %v", err)
   211  				}
   212  			}
   213  
   214  			_, err = CreateNewFileUnderCurrentDirectory(tt.path, os.O_WRONLY)
   215  			if (err == nil && tt.expected != nil) ||
   216  				(err != nil && tt.expected == nil) {
   217  				t.Fatalf("unexpected error: %v", cmp.Diff(err, tt.expected, cmpopts.EquateErrors()))
   218  			}
   219  
   220  			if err != nil && !errors.Is(err, tt.expected) {
   221  				t.Fatalf("unexpected error: %v", cmp.Diff(err, tt.expected, cmpopts.EquateErrors()))
   222  			}
   223  		})
   224  	}
   225  }
   226  
   227  func Test_PathIsUnderDirectory(t *testing.T) {
   228  	tests := []struct {
   229  		expected error
   230  		name     string
   231  		path     string
   232  		dir      string
   233  	}{
   234  		{
   235  			name:     "valid same path",
   236  			path:     "./",
   237  			dir:      "./",
   238  			expected: nil,
   239  		},
   240  		{
   241  			name:     "valid path no slash",
   242  			path:     "./some/valid/path",
   243  			dir:      ".",
   244  			expected: nil,
   245  		},
   246  		{
   247  			name:     "valid path with slash",
   248  			path:     "./some/valid/path/",
   249  			dir:      ".",
   250  			expected: nil,
   251  		},
   252  		{
   253  			name:     "valid path with no dot",
   254  			path:     "some/valid/path/",
   255  			dir:      "some/valid/",
   256  			expected: nil,
   257  		},
   258  		{
   259  			name: "some valid path",
   260  			path: "../utils/some/valid/path",
   261  			dir:  "../utils",
   262  		},
   263  		{
   264  			name:     "parent invalid path",
   265  			path:     "../invalid/path",
   266  			dir:      ".",
   267  			expected: ErrInvalidPath,
   268  		},
   269  		{
   270  			name: "some valid fullpath",
   271  			path: "/some/invalid/fullpath",
   272  			dir:  "/some",
   273  		},
   274  	}
   275  	for _, tt := range tests {
   276  		tt := tt // Re-initializing variable so it is not changed while executing the closure below
   277  		t.Run(tt.name, func(t *testing.T) {
   278  			t.Parallel()
   279  
   280  			wd, err := os.Getwd()
   281  			if err != nil {
   282  				t.Fatal(err)
   283  			}
   284  			d, err := filepath.Abs(filepath.Join(wd, tt.dir))
   285  			if err != nil {
   286  				t.Fatal(err)
   287  			}
   288  			err = PathIsUnderDirectory(tt.path, d)
   289  			if (err == nil && tt.expected != nil) ||
   290  				(err != nil && tt.expected == nil) {
   291  				t.Fatalf("unexpected error: %v", cmp.Diff(err, tt.expected, cmpopts.EquateErrors()))
   292  			}
   293  
   294  			if err != nil && !errors.Is(err, tt.expected) {
   295  				t.Fatalf("unexpected error: %v", cmp.Diff(err, tt.expected, cmpopts.EquateErrors()))
   296  			}
   297  		})
   298  	}
   299  }