github.com/lineaje-labs/syft@v0.98.1-0.20231227153149-9e393f60ff1b/syft/file/cataloger/filemetadata/cataloger_test.go (about)

     1  package filemetadata
     2  
     3  import (
     4  	"os"
     5  	"testing"
     6  
     7  	"github.com/stretchr/testify/assert"
     8  	"github.com/stretchr/testify/require"
     9  
    10  	stereoscopeFile "github.com/anchore/stereoscope/pkg/file"
    11  	"github.com/anchore/stereoscope/pkg/imagetest"
    12  	"github.com/anchore/syft/syft/file"
    13  	"github.com/anchore/syft/syft/source"
    14  )
    15  
    16  func TestFileMetadataCataloger(t *testing.T) {
    17  	testImage := "image-file-type-mix"
    18  
    19  	img := imagetest.GetFixtureImage(t, "docker-archive", testImage)
    20  
    21  	c := NewCataloger()
    22  
    23  	src, err := source.NewFromStereoscopeImageObject(img, testImage, nil)
    24  	require.NoError(t, err)
    25  
    26  	resolver, err := src.FileResolver(source.SquashedScope)
    27  	require.NoError(t, err)
    28  
    29  	actual, err := c.Catalog(resolver)
    30  	require.NoError(t, err)
    31  
    32  	tests := []struct {
    33  		path     string
    34  		exists   bool
    35  		expected file.Metadata
    36  		err      bool
    37  	}{
    38  		// note: it is difficult to add a hardlink-based test in a cross-platform way and is already covered well in stereoscope
    39  		{
    40  			path:   "/file-1.txt",
    41  			exists: true,
    42  			expected: file.Metadata{
    43  				FileInfo: stereoscopeFile.ManualInfo{
    44  					NameValue: "file-1.txt",
    45  					ModeValue: 0644,
    46  					SizeValue: 7,
    47  				},
    48  				Path:     "/file-1.txt",
    49  				Type:     stereoscopeFile.TypeRegular,
    50  				UserID:   1,
    51  				GroupID:  2,
    52  				MIMEType: "text/plain",
    53  			},
    54  		},
    55  		{
    56  			path:   "/symlink-1",
    57  			exists: true,
    58  			expected: file.Metadata{
    59  				Path: "/symlink-1",
    60  				FileInfo: stereoscopeFile.ManualInfo{
    61  					NameValue: "symlink-1",
    62  					ModeValue: 0777 | os.ModeSymlink,
    63  				},
    64  				Type:            stereoscopeFile.TypeSymLink,
    65  				LinkDestination: "file-1.txt",
    66  				UserID:          0,
    67  				GroupID:         0,
    68  				MIMEType:        "",
    69  			},
    70  		},
    71  		{
    72  			path:   "/char-device-1",
    73  			exists: true,
    74  			expected: file.Metadata{
    75  				Path: "/char-device-1",
    76  				FileInfo: stereoscopeFile.ManualInfo{
    77  					NameValue: "char-device-1",
    78  					ModeValue: 0644 | os.ModeDevice | os.ModeCharDevice,
    79  				},
    80  				Type:     stereoscopeFile.TypeCharacterDevice,
    81  				UserID:   0,
    82  				GroupID:  0,
    83  				MIMEType: "",
    84  			},
    85  		},
    86  		{
    87  			path:   "/block-device-1",
    88  			exists: true,
    89  			expected: file.Metadata{
    90  				Path: "/block-device-1",
    91  				FileInfo: stereoscopeFile.ManualInfo{
    92  					NameValue: "block-device-1",
    93  					ModeValue: 0644 | os.ModeDevice,
    94  				},
    95  				Type:     stereoscopeFile.TypeBlockDevice,
    96  				UserID:   0,
    97  				GroupID:  0,
    98  				MIMEType: "",
    99  			},
   100  		},
   101  		{
   102  			path:   "/fifo-1",
   103  			exists: true,
   104  			expected: file.Metadata{
   105  				Path: "/fifo-1",
   106  				FileInfo: stereoscopeFile.ManualInfo{
   107  					NameValue: "fifo-1",
   108  					ModeValue: 0644 | os.ModeNamedPipe,
   109  				},
   110  				Type:     stereoscopeFile.TypeFIFO,
   111  				UserID:   0,
   112  				GroupID:  0,
   113  				MIMEType: "",
   114  			},
   115  		},
   116  		{
   117  			path:   "/bin",
   118  			exists: true,
   119  			expected: file.Metadata{
   120  				Path: "/bin",
   121  				FileInfo: stereoscopeFile.ManualInfo{
   122  					NameValue: "bin",
   123  					ModeValue: 0755 | os.ModeDir,
   124  				},
   125  				Type:     stereoscopeFile.TypeDirectory,
   126  				UserID:   0,
   127  				GroupID:  0,
   128  				MIMEType: "",
   129  			},
   130  		},
   131  	}
   132  
   133  	for _, test := range tests {
   134  		t.Run(test.path, func(t *testing.T) {
   135  			_, ref, err := img.SquashedTree().File(stereoscopeFile.Path(test.path))
   136  			require.NoError(t, err)
   137  
   138  			l := file.NewLocationFromImage(test.path, *ref.Reference, img)
   139  
   140  			if _, ok := actual[l.Coordinates]; ok {
   141  				// we're not interested in keeping the test fixtures up to date with the latest file modification times
   142  				// thus ModTime is not under test
   143  				fi := test.expected.FileInfo.(stereoscopeFile.ManualInfo)
   144  				fi.ModTimeValue = actual[l.Coordinates].ModTime()
   145  				test.expected.FileInfo = fi
   146  			}
   147  
   148  			assert.True(t, test.expected.Equal(actual[l.Coordinates]))
   149  		})
   150  	}
   151  
   152  }
   153  
   154  func TestFileMetadataCataloger_GivenCoordinates(t *testing.T) {
   155  	testImage := "image-file-type-mix"
   156  
   157  	img := imagetest.GetFixtureImage(t, "docker-archive", testImage)
   158  
   159  	c := NewCataloger()
   160  
   161  	src, err := source.NewFromStereoscopeImageObject(img, testImage, nil)
   162  	require.NoError(t, err)
   163  
   164  	resolver, err := src.FileResolver(source.SquashedScope)
   165  	require.NoError(t, err)
   166  
   167  	tests := []struct {
   168  		path     string
   169  		exists   bool
   170  		expected file.Metadata
   171  		err      bool
   172  	}{
   173  		{
   174  			path:   "/file-1.txt",
   175  			exists: true,
   176  			expected: file.Metadata{
   177  				FileInfo: stereoscopeFile.ManualInfo{
   178  					NameValue: "file-1.txt",
   179  					ModeValue: 0644,
   180  					SizeValue: 7,
   181  				},
   182  				Path:     "/file-1.txt",
   183  				Type:     stereoscopeFile.TypeRegular,
   184  				UserID:   1,
   185  				GroupID:  2,
   186  				MIMEType: "text/plain",
   187  			},
   188  		},
   189  	}
   190  
   191  	for _, test := range tests {
   192  		t.Run(test.path, func(t *testing.T) {
   193  			_, ref, err := img.SquashedTree().File(stereoscopeFile.Path(test.path))
   194  			require.NoError(t, err)
   195  
   196  			l := file.NewLocationFromImage(test.path, *ref.Reference, img)
   197  
   198  			// note: an important difference between this test and the previous is that this test is using a list
   199  			// of specific coordinates to catalog
   200  			actual, err := c.Catalog(resolver, l.Coordinates)
   201  			require.NoError(t, err)
   202  			require.Len(t, actual, 1)
   203  
   204  			if _, ok := actual[l.Coordinates]; ok {
   205  				// we're not interested in keeping the test fixtures up to date with the latest file modification times
   206  				// thus ModTime is not under test
   207  				fi := test.expected.FileInfo.(stereoscopeFile.ManualInfo)
   208  				fi.ModTimeValue = actual[l.Coordinates].ModTime()
   209  				test.expected.FileInfo = fi
   210  			}
   211  
   212  			assert.True(t, test.expected.Equal(actual[l.Coordinates]))
   213  		})
   214  	}
   215  
   216  }