github.com/datreeio/datree@v1.9.22-rc/pkg/fileReader/reader_test.go (about) 1 package fileReader 2 3 import ( 4 "io/fs" 5 "os" 6 "reflect" 7 "testing" 8 "time" 9 10 "github.com/stretchr/testify/assert" 11 "github.com/stretchr/testify/mock" 12 ) 13 14 type ioMock struct { 15 mock.Mock 16 } 17 18 func (c *ioMock) ReadFile(filename string) ([]byte, error) { 19 args := c.Called(filename) 20 return args.Get(0).([]byte), args.Error(1) 21 } 22 23 type readFileContentTestCase struct { 24 name string 25 args struct { 26 path string 27 } 28 mock struct { 29 readFilFn struct { 30 response []byte 31 err error 32 } 33 } 34 expected struct { 35 calledWith string 36 isCalled bool 37 response string 38 err error 39 } 40 } 41 42 func TestReadFileContent(t *testing.T) { 43 io := ioMock{} 44 45 tests := []readFileContentTestCase{ 46 { 47 name: "success - should override with opts.methods and return response", 48 args: struct{ path string }{ 49 path: "path/file.yaml", 50 }, 51 mock: struct { 52 readFilFn struct { 53 response []byte 54 err error 55 } 56 }{ 57 readFilFn: struct { 58 response []byte 59 err error 60 }{ 61 response: []byte("content in file"), 62 err: nil, 63 }, 64 }, 65 expected: struct { 66 calledWith string 67 isCalled bool 68 response string 69 err error 70 }{ 71 calledWith: "path/file.yaml", 72 isCalled: true, 73 response: "content in file", 74 err: nil, 75 }, 76 }, 77 } 78 79 for _, tt := range tests { 80 t.Run(tt.name, func(t *testing.T) { 81 io.On("ReadFile", mock.Anything).Return(tt.mock.readFilFn.response, tt.mock.readFilFn.err) 82 fileReader := &FileReader{ 83 glob: nil, 84 readFile: io.ReadFile, 85 } 86 87 res, err := fileReader.ReadFileContent(tt.args.path) 88 io.AssertCalled(t, "ReadFile", tt.expected.calledWith) 89 assert.Equal(t, tt.expected.response, res) 90 assert.Equal(t, tt.expected.err, err) 91 }) 92 } 93 } 94 95 type globMock struct { 96 mock.Mock 97 } 98 99 func (c *globMock) Glob(pattern string) (matches []string, err error) { 100 args := c.Called(pattern) 101 return args.Get(0).([]string), args.Error(1) 102 } 103 104 type statMock struct { 105 mock.Mock 106 } 107 108 func (c *statMock) Stat(name string) (os.FileInfo, error) { 109 args := c.Called(name) 110 return args.Get(0).(os.FileInfo), args.Error(1) 111 } 112 113 type absMock struct { 114 mock.Mock 115 } 116 117 func (c *absMock) Abs(path string) (string, error) { 118 args := c.Called(path) 119 return args.Get(0).(string), args.Error(1) 120 } 121 122 type filterFilesTestCase struct { 123 name string 124 args struct { 125 paths []string 126 excludePattern string 127 } 128 mock struct { 129 stat struct { 130 response fs.FileInfo 131 err error 132 } 133 } 134 expected struct { 135 filePaths []string 136 } 137 } 138 139 func TestFilterFiles(t *testing.T) { 140 stat := statMock{} 141 fileInfo := &MockFileInfo{} 142 143 tests := []filterFilesTestCase{ 144 { 145 name: "success", 146 args: struct { 147 paths []string 148 excludePattern string 149 }{ 150 paths: []string{"file1.yaml", "file2.yaml", "file3-exclude.yaml", "file4.yaml", "file5-exclude.yaml"}, 151 excludePattern: "exclude.yaml", 152 }, 153 mock: struct { 154 stat struct { 155 response fs.FileInfo 156 err error 157 } 158 }{ 159 stat: struct { 160 response fs.FileInfo 161 err error 162 }{ 163 response: fileInfo, 164 err: nil, 165 }, 166 }, 167 expected: struct{ filePaths []string }{ 168 filePaths: []string{"file1.yaml", "file2.yaml", "file4.yaml"}, 169 }, 170 }, 171 } 172 173 for _, tt := range tests { 174 t.Run(tt.name, func(t *testing.T) { 175 stat.On("Stat", mock.Anything).Return(tt.mock.stat.response, tt.mock.stat.err) 176 fileInfo.On("IsDir", mock.Anything).Return(false) 177 fileReader := &FileReader{ 178 glob: nil, 179 stat: stat.Stat, 180 } 181 182 filteredfiles, _ := fileReader.FilterFiles(tt.args.paths, tt.args.excludePattern) 183 stat.AssertCalled(t, "Stat", tt.expected.filePaths[0]) 184 fileInfo.AssertCalled(t, "IsDir") 185 assert.Equal(t, tt.expected.filePaths, filteredfiles) 186 }) 187 } 188 } 189 190 func TestCreateFileReader(t *testing.T) { 191 glob := globMock{} 192 io := ioMock{} 193 stat := statMock{} 194 abs := absMock{} 195 196 opt := &FileReaderOptions{ 197 Glob: glob.Glob, 198 ReadFile: io.ReadFile, 199 Stat: stat.Stat, 200 Abs: abs.Abs, 201 } 202 203 fileReader := CreateFileReader(opt) 204 205 expectedGlobFnValue := reflect.ValueOf(glob.Glob) 206 actualGlobFnValue := reflect.ValueOf(fileReader.glob) 207 208 assert.Equal(t, expectedGlobFnValue.Pointer(), actualGlobFnValue.Pointer()) 209 } 210 211 type getFilesPathsTestCase struct { 212 name string 213 args struct { 214 paths []string 215 } 216 mock struct { 217 stat struct { 218 response os.FileInfo 219 err error 220 } 221 abs struct { 222 response string 223 err error 224 } 225 } 226 expected struct { 227 stat struct { 228 calledWith string 229 isCalled bool 230 } 231 abs struct { 232 calledWith string 233 isCalled bool 234 } 235 response []string 236 err []error 237 } 238 } 239 240 func getFilesPaths_noMatchesTestCase() getFilesPathsTestCase { 241 return getFilesPathsTestCase{ 242 name: "success no matches", 243 args: struct{ paths []string }{ 244 paths: []string{}, 245 }, 246 mock: struct { 247 stat struct { 248 response os.FileInfo 249 err error 250 } 251 abs struct { 252 response string 253 err error 254 } 255 }{ 256 stat: struct { 257 response os.FileInfo 258 err error 259 }{ 260 response: nil, 261 err: nil, 262 }, 263 abs: struct { 264 response string 265 err error 266 }{ 267 response: "", 268 err: nil, 269 }, 270 }, 271 expected: struct { 272 stat struct { 273 calledWith string 274 isCalled bool 275 } 276 abs struct { 277 calledWith string 278 isCalled bool 279 } 280 response []string 281 err []error 282 }{ 283 stat: struct { 284 calledWith string 285 isCalled bool 286 }{ 287 calledWith: "", 288 isCalled: false, 289 }, 290 abs: struct { 291 calledWith string 292 isCalled bool 293 }{ 294 calledWith: "", 295 isCalled: false, 296 }, 297 response: nil, 298 err: nil, 299 }, 300 } 301 } 302 303 type MockFileInfo struct { 304 mock.Mock 305 FileName string 306 IsDirectory bool 307 } 308 309 func (mfi MockFileInfo) Name() string { return mfi.FileName } 310 func (mfi MockFileInfo) Size() int64 { return int64(8) } 311 func (mfi MockFileInfo) Mode() os.FileMode { return os.ModePerm } 312 func (mfi MockFileInfo) ModTime() time.Time { return time.Now() } 313 func (mfi MockFileInfo) Sys() interface{} { return nil } 314 315 func (c *MockFileInfo) IsDir() bool { 316 args := c.Called() 317 return args.Get(0).(bool) 318 } 319 320 func getFilesPaths_withMatchesTestCase() getFilesPathsTestCase { 321 mockFileInfo := &MockFileInfo{} 322 mockFileInfo.On("IsDir").Return(false) 323 324 return getFilesPathsTestCase{ 325 name: "success with matches", 326 args: struct{ paths []string }{ 327 paths: []string{"./fail-30.yaml"}, 328 }, 329 mock: struct { 330 stat struct { 331 response os.FileInfo 332 err error 333 } 334 abs struct { 335 response string 336 err error 337 } 338 }{ 339 stat: struct { 340 response os.FileInfo 341 err error 342 }{ 343 response: mockFileInfo, 344 err: nil, 345 }, 346 abs: struct { 347 response string 348 err error 349 }{ 350 response: "path", 351 err: nil, 352 }, 353 }, 354 expected: struct { 355 stat struct { 356 calledWith string 357 isCalled bool 358 } 359 abs struct { 360 calledWith string 361 isCalled bool 362 } 363 response []string 364 err []error 365 }{ 366 stat: struct { 367 calledWith string 368 isCalled bool 369 }{ 370 calledWith: "./fail-30.yaml", 371 isCalled: true, 372 }, 373 abs: struct { 374 calledWith string 375 isCalled bool 376 }{ 377 calledWith: "./fail-30.yaml", 378 isCalled: true, 379 }, 380 response: []string{"path"}, 381 err: nil, 382 }, 383 } 384 }