github.com/josephvusich/fdf@v0.0.0-20230522095411-9326dd32e33f/scanner_test.go (about) 1 package main 2 3 import ( 4 "fmt" 5 "io" 6 "io/ioutil" 7 "os" 8 "path/filepath" 9 "testing" 10 11 "github.com/josephvusich/go-matchers" 12 "github.com/josephvusich/go-matchers/glob" 13 "github.com/mattn/go-zglob" 14 "github.com/stretchr/testify/require" 15 ) 16 17 func TestScanner_SelectAndSwap(t *testing.T) { 18 assert := require.New(t) 19 20 s := newScanner() 21 s.options.Protect = matchers.RuleSet{} 22 m, err := glob.NewMatcher("/foo_001") 23 assert.NoError(err) 24 m2, err := glob.NewMatcher("/foo") 25 assert.NoError(err) 26 s.options.Protect.Add(m, true) 27 s.options.MustKeep.Add(m2, true) 28 29 current := newFileRecord("/foo", nil, "foo", "") 30 match := newFileRecord("/foo_001", nil, "foo_001", "") 31 32 swapMatch, err := s.selectAndSwap(current, match, matchCopyName) 33 assert.ErrorIs(err, fileIsSkipped) 34 35 s.options.MustKeep = matchers.RuleSet{DefaultInclude: true} 36 current.satisfiesKept = nil 37 match.satisfiesKept = nil 38 39 swapMatch, err = s.selectAndSwap(current, match, matchCopyName) 40 assert.NoError(err) 41 assert.False(swapMatch) 42 43 s.options.Protect = matchers.RuleSet{} 44 current.protect = nil 45 match.protect = nil 46 47 swapMatch, err = s.selectAndSwap(current, match, matchContent) 48 assert.NoError(err) 49 assert.True(swapMatch) 50 51 current.protect = nil 52 current.satisfiesKept = nil 53 match.protect = nil 54 match.satisfiesKept = nil 55 s.options.MustKeep.Add(m, true) 56 57 swapMatch, err = s.selectAndSwap(current, match, matchContent) 58 assert.NoError(err) 59 assert.False(swapMatch) 60 } 61 62 func TestScanner_SelectAndSwapMustKeep(t *testing.T) { 63 assert := require.New(t) 64 65 s := newScanner() 66 s.options.Protect = matchers.RuleSet{} 67 m, err := glob.NewMatcher("/foo_001") 68 assert.NoError(err) 69 s.options.Protect.Add(m, true) 70 71 current := newFileRecord("/foo", nil, "foo", "") 72 match := newFileRecord("/foo_001", nil, "foo_001", "") 73 74 swapMatch, err := s.selectAndSwap(current, match, matchCopyName) 75 assert.NoError(err) 76 assert.False(swapMatch) 77 78 s.options.Protect = matchers.RuleSet{} 79 current.protect = nil 80 match.protect = nil 81 82 swapMatch, err = s.selectAndSwap(current, match, matchContent) 83 assert.NoError(err) 84 assert.True(swapMatch) 85 } 86 87 func TestScanner_NoVerb(t *testing.T) { 88 assert := require.New(t) 89 setupTest(assert, func(l *testLayout, validate func(*testLayout)) { 90 scanner := newScanner() 91 scanner.options.MatchMode = matchContent 92 scanner.options.Recursive = true 93 scanner.options.minSize = 1 94 95 assert.NoError(scanner.Scan()) 96 fmt.Println(scanner.totals.PrettyFormat(scanner.options.Verb())) 97 assert.Equal(uint64(16), scanner.totals.Files.count) 98 assert.Equal(uint64(73), scanner.totals.Files.size) 99 assert.Equal(uint64(6), scanner.totals.Unique.count) 100 assert.Equal(uint64(33), scanner.totals.Unique.size) 101 assert.Equal(uint64(0), scanner.totals.Links.count) 102 assert.Equal(uint64(0), scanner.totals.Links.size) 103 assert.Equal(uint64(0), scanner.totals.Cloned.count) 104 assert.Equal(uint64(0), scanner.totals.Cloned.size) 105 assert.Equal(uint64(10), scanner.totals.Dupes.count) 106 assert.Equal(uint64(40), scanner.totals.Dupes.size) 107 assert.Equal(uint64(0), scanner.totals.Processed.count) 108 assert.Equal(uint64(0), scanner.totals.Processed.size) 109 assert.Equal(uint64(6), scanner.totals.Skipped.count) 110 assert.Equal(uint64(0), scanner.totals.Skipped.size) 111 assert.Equal(uint64(0), scanner.totals.Errors.count) 112 assert.Equal(uint64(0), scanner.totals.Errors.size) 113 validate(l) 114 }) 115 } 116 117 func TestScanner_LinkUnlink(t *testing.T) { 118 assert := require.New(t) 119 setupTest(assert, func(l *testLayout, validate func(*testLayout)) { 120 // Phase 1: Hardlink 121 scanner := newScanner() 122 scanner.options.makeLinks = true 123 scanner.options.Recursive = true 124 scanner.options.MatchMode = matchContent 125 126 assert.NoError(scanner.Scan()) 127 fmt.Println(scanner.totals.PrettyFormat(scanner.options.Verb())) 128 assert.Equal(uint64(22), scanner.totals.Files.count) 129 assert.Equal(uint64(73), scanner.totals.Files.size) 130 assert.Equal(uint64(7), scanner.totals.Unique.count) 131 assert.Equal(uint64(33), scanner.totals.Unique.size) 132 assert.Equal(uint64(15), scanner.totals.Links.count) 133 assert.Equal(uint64(40), scanner.totals.Links.size) 134 assert.Equal(uint64(0), scanner.totals.Cloned.count) 135 assert.Equal(uint64(0), scanner.totals.Cloned.size) 136 assert.Equal(uint64(0), scanner.totals.Dupes.count) 137 assert.Equal(uint64(0), scanner.totals.Dupes.size) 138 assert.Equal(uint64(15), scanner.totals.Processed.count) 139 assert.Equal(uint64(40), scanner.totals.Processed.size) 140 assert.Equal(uint64(0), scanner.totals.Skipped.count) 141 assert.Equal(uint64(0), scanner.totals.Skipped.size) 142 assert.Equal(uint64(0), scanner.totals.Errors.count) 143 assert.Equal(uint64(0), scanner.totals.Errors.size) 144 validate(l) 145 146 // Validate hardlink behavior 147 func() { 148 f, err := os.OpenFile(filepath.Join(l.dirs[0], "bar"), os.O_WRONLY, 0666) 149 assert.NoError(err) 150 defer f.Close() 151 _, err = f.Seek(0, io.SeekStart) 152 assert.NoError(err) 153 assert.NoError(f.Truncate(0)) 154 _, err = f.WriteString("hello world") 155 assert.NoError(err) 156 l.content["bar"] = "hello world" 157 l.content["bar2"] = "hello world" 158 l.content["bar3"] = "hello world" 159 }() 160 validate(l) 161 162 // Phase 2: Copy 163 scanner = newScanner() 164 scanner.options.splitLinks = true 165 scanner.options.Recursive = true 166 scanner.options.MatchMode = matchContent 167 168 assert.NoError(scanner.Scan()) 169 fmt.Println(scanner.totals.PrettyFormat(scanner.options.Verb())) 170 assert.Equal(uint64(22), scanner.totals.Files.count) 171 assert.Equal(uint64(115), scanner.totals.Files.size) 172 assert.Equal(uint64(7), scanner.totals.Unique.count) 173 assert.Equal(uint64(40), scanner.totals.Unique.size) 174 assert.Equal(uint64(0), scanner.totals.Links.count) 175 assert.Equal(uint64(0), scanner.totals.Links.size) 176 assert.Equal(uint64(0), scanner.totals.Cloned.count) 177 assert.Equal(uint64(0), scanner.totals.Cloned.size) 178 assert.Equal(uint64(15), scanner.totals.Dupes.count) 179 assert.Equal(uint64(75), scanner.totals.Dupes.size) 180 assert.Equal(uint64(15), scanner.totals.Processed.count) 181 assert.Equal(uint64(75), scanner.totals.Processed.size) 182 assert.Equal(uint64(0), scanner.totals.Skipped.count) 183 assert.Equal(uint64(0), scanner.totals.Skipped.size) 184 assert.Equal(uint64(0), scanner.totals.Errors.count) 185 assert.Equal(uint64(0), scanner.totals.Errors.size) 186 validate(l) 187 188 // Validate hardlink split 189 for i := 0; i < len(l.dirs); i++ { 190 func(i int) { 191 f, err := os.OpenFile(filepath.Join(l.dirs[i], "bar"), os.O_WRONLY, 0666) 192 assert.NoError(err) 193 defer f.Close() 194 _, err = f.Seek(0, io.SeekStart) 195 assert.NoError(err) 196 assert.NoError(f.Truncate(0)) 197 _, err = f.WriteString("goodbye world") 198 assert.NoError(err) 199 }(i) 200 } 201 l.content["bar"] = "goodbye world" 202 validate(l) 203 }) 204 } 205 206 func TestScanner_Delete(t *testing.T) { 207 assert := require.New(t) 208 setupTest(assert, func(l *testLayout, validate func(*testLayout)) { 209 scanner := newScanner() 210 scanner.options.deleteDupes = true 211 scanner.options.Recursive = true 212 scanner.options.MatchMode = matchContent 213 214 assert.NoError(scanner.Scan()) 215 fmt.Println(scanner.totals.PrettyFormat(scanner.options.Verb())) 216 assert.Equal(uint64(22), scanner.totals.Files.count) 217 assert.Equal(uint64(73), scanner.totals.Files.size) 218 assert.Equal(uint64(7), scanner.totals.Unique.count) 219 assert.Equal(uint64(33), scanner.totals.Unique.size) 220 assert.Equal(uint64(0), scanner.totals.Links.count) 221 assert.Equal(uint64(0), scanner.totals.Links.size) 222 assert.Equal(uint64(0), scanner.totals.Cloned.count) 223 assert.Equal(uint64(0), scanner.totals.Cloned.size) 224 assert.Equal(uint64(0), scanner.totals.Dupes.count) 225 assert.Equal(uint64(0), scanner.totals.Dupes.size) 226 assert.Equal(uint64(15), scanner.totals.Processed.count) 227 assert.Equal(uint64(40), scanner.totals.Processed.size) 228 assert.Equal(uint64(0), scanner.totals.Skipped.count) 229 assert.Equal(uint64(0), scanner.totals.Skipped.size) 230 assert.Equal(uint64(0), scanner.totals.Errors.count) 231 assert.Equal(uint64(0), scanner.totals.Errors.size) 232 l.contentOverride = true 233 l.content = map[string]string{ 234 "a/bar": "bar\n", 235 "a/diffContent": "fizz\n", 236 "a/diffSize": "foobar\n", 237 "a/empty": "", 238 "a/foo": "foo\n", 239 "b/diffContent": "buzz\n", 240 "b/diffSize": "foobar2\n", 241 } 242 validate(l) 243 }) 244 } 245 246 func TestScanner_DeleteProtect(t *testing.T) { 247 assert := require.New(t) 248 setupTest(assert, func(l *testLayout, validate func(*testLayout)) { 249 scanner := newScanner() 250 assert.Empty(scanner.options.ParseArgs([]string{`fdf`, `-rd`, `--protect`, `./b/**/*`, `-m`, `content`, `-z`, `0`})) 251 assert.True(scanner.options.deleteDupes) 252 assert.True(scanner.options.Recursive) 253 assert.Equal(matchContent, scanner.options.MatchMode) 254 255 assert.NoError(scanner.Scan()) 256 fmt.Println(scanner.totals.PrettyFormat(scanner.options.Verb())) 257 assert.Equal(uint64(22), scanner.totals.Files.count) 258 assert.Equal(uint64(73), scanner.totals.Files.size) 259 assert.Equal(uint64(13), scanner.totals.Unique.count) 260 assert.Equal(uint64(49), scanner.totals.Unique.size) 261 assert.Equal(uint64(0), scanner.totals.Links.count) 262 assert.Equal(uint64(0), scanner.totals.Links.size) 263 assert.Equal(uint64(0), scanner.totals.Cloned.count) 264 assert.Equal(uint64(0), scanner.totals.Cloned.size) 265 assert.Equal(uint64(0), scanner.totals.Dupes.count) 266 assert.Equal(uint64(0), scanner.totals.Dupes.size) 267 assert.Equal(uint64(9), scanner.totals.Processed.count) 268 assert.Equal(uint64(24), scanner.totals.Processed.size) 269 assert.Equal(uint64(0), scanner.totals.Skipped.count) 270 assert.Equal(uint64(0), scanner.totals.Skipped.size) 271 assert.Equal(uint64(0), scanner.totals.Errors.count) 272 assert.Equal(uint64(0), scanner.totals.Errors.size) 273 l.contentOverride = true 274 l.content = map[string]string{ 275 "a/diffContent": "fizz\n", 276 "a/diffSize": "foobar\n", 277 "b/bar": "bar\n", 278 "b/bar2": "bar\n", 279 "b/bar3": "bar\n", 280 "b/empty": "", 281 "b/empty2": "", 282 "b/empty3": "", 283 "b/foo": "foo\n", 284 "b/foo2": "foo\n", 285 "b/foo3": "foo\n", 286 "b/diffContent": "buzz\n", 287 "b/diffSize": "foobar2\n", 288 } 289 validate(l) 290 }) 291 } 292 293 func TestScanner_NameSize(t *testing.T) { 294 assert := require.New(t) 295 setupTest(assert, func(l *testLayout, validate func(*testLayout)) { 296 // Phase 1: Hardlink 297 scanner := newScanner() 298 scanner.options.MatchMode = matchName | matchSize 299 scanner.options.makeLinks = true 300 scanner.options.Recursive = true 301 302 assert.NoError(scanner.Scan()) 303 fmt.Println(scanner.totals.PrettyFormat(scanner.options.Verb())) 304 assert.Equal(uint64(22), scanner.totals.Files.count) 305 assert.Equal(uint64(73), scanner.totals.Files.size) 306 assert.Equal(uint64(12), scanner.totals.Unique.count) 307 assert.Equal(uint64(44), scanner.totals.Unique.size) 308 assert.Equal(uint64(10), scanner.totals.Links.count) 309 assert.Equal(uint64(29), scanner.totals.Links.size) 310 assert.Equal(uint64(0), scanner.totals.Cloned.count) 311 assert.Equal(uint64(0), scanner.totals.Cloned.size) 312 assert.Equal(uint64(0), scanner.totals.Dupes.count) 313 assert.Equal(uint64(0), scanner.totals.Dupes.size) 314 assert.Equal(uint64(10), scanner.totals.Processed.count) 315 assert.Equal(uint64(29), scanner.totals.Processed.size) 316 assert.Equal(uint64(0), scanner.totals.Skipped.count) 317 assert.Equal(uint64(0), scanner.totals.Skipped.size) 318 assert.Equal(uint64(0), scanner.totals.Errors.count) 319 assert.Equal(uint64(0), scanner.totals.Errors.size) 320 l.diffContent[1] = l.diffContent[0] 321 validate(l) 322 }) 323 } 324 325 func TestScanner_NameContent(t *testing.T) { 326 assert := require.New(t) 327 setupTest(assert, func(l *testLayout, validate func(*testLayout)) { 328 // Phase 1: Hardlink 329 scanner := newScanner() 330 scanner.options.MatchMode = matchName | matchContent 331 scanner.options.makeLinks = true 332 scanner.options.Recursive = true 333 334 assert.NoError(scanner.Scan()) 335 fmt.Println(scanner.totals.PrettyFormat(scanner.options.Verb())) 336 assert.Equal(uint64(22), scanner.totals.Files.count) 337 assert.Equal(uint64(73), scanner.totals.Files.size) 338 assert.Equal(uint64(13), scanner.totals.Unique.count) 339 assert.Equal(uint64(49), scanner.totals.Unique.size) 340 assert.Equal(uint64(9), scanner.totals.Links.count) 341 assert.Equal(uint64(24), scanner.totals.Links.size) 342 assert.Equal(uint64(0), scanner.totals.Cloned.count) 343 assert.Equal(uint64(0), scanner.totals.Cloned.size) 344 assert.Equal(uint64(0), scanner.totals.Dupes.count) 345 assert.Equal(uint64(0), scanner.totals.Dupes.size) 346 assert.Equal(uint64(9), scanner.totals.Processed.count) 347 assert.Equal(uint64(24), scanner.totals.Processed.size) 348 assert.Equal(uint64(0), scanner.totals.Skipped.count) 349 assert.Equal(uint64(0), scanner.totals.Skipped.size) 350 assert.Equal(uint64(0), scanner.totals.Errors.count) 351 assert.Equal(uint64(0), scanner.totals.Errors.size) 352 validate(l) 353 }) 354 } 355 356 func TestScanner_CopyNameContent(t *testing.T) { 357 assert := require.New(t) 358 359 l := &testLayout{ 360 dirs: []string{ 361 "./a", 362 "./b", 363 }, 364 content: map[string]string{ 365 "bar": "bar\n", 366 "Copy of bar": "bar\n", 367 "bar (1)": "bar\n", 368 "bar-01": "bar\n", 369 "foo": "bar\n", 370 "bar.foo": "bar\n", 371 }, 372 diffContent: []string{ 373 "fizz\n", 374 "buzz\n", 375 }, 376 diffSize: []string{ 377 "foobar\n", 378 "foobar2\n", 379 }, 380 } 381 382 setupTestLayout(assert, l, func(l *testLayout, validate func(*testLayout)) { 383 scanner := newScanner() 384 scanner.options.MatchMode = matchCopyName | matchContent 385 scanner.options.makeLinks = true 386 scanner.options.Recursive = true 387 388 assert.NoError(scanner.Scan()) 389 fmt.Println(scanner.totals.PrettyFormat(scanner.options.Verb())) 390 assert.Equal(uint64(16), scanner.totals.Files.count) 391 assert.Equal(uint64(73), scanner.totals.Files.size) 392 assert.Equal(uint64(7), scanner.totals.Unique.count) 393 assert.Equal(uint64(37), scanner.totals.Unique.size) 394 assert.Equal(uint64(9), scanner.totals.Links.count) 395 assert.Equal(uint64(36), scanner.totals.Links.size) 396 assert.Equal(uint64(0), scanner.totals.Cloned.count) 397 assert.Equal(uint64(0), scanner.totals.Cloned.size) 398 assert.Equal(uint64(0), scanner.totals.Dupes.count) 399 assert.Equal(uint64(0), scanner.totals.Dupes.size) 400 assert.Equal(uint64(9), scanner.totals.Processed.count) 401 assert.Equal(uint64(36), scanner.totals.Processed.size) 402 assert.Equal(uint64(0), scanner.totals.Skipped.count) 403 assert.Equal(uint64(0), scanner.totals.Skipped.size) 404 assert.Equal(uint64(0), scanner.totals.Errors.count) 405 assert.Equal(uint64(0), scanner.totals.Errors.size) 406 validate(l) 407 }) 408 } 409 410 func TestScanner_NameSuffix(t *testing.T) { 411 assert := require.New(t) 412 413 l := &testLayout{ 414 dirs: []string{ 415 "./a", 416 "./b", 417 }, 418 content: map[string]string{ 419 "bar": "bar\n", 420 "Copy of bar": "bar\n", 421 "bar (1)": "bar\n", 422 "bar-01": "bar\n", 423 "foo": "bar\n", 424 "bar.foo": "bar\n", 425 }, 426 diffContent: []string{ 427 "fizz\n", 428 "buzz\n", 429 }, 430 diffSize: []string{ 431 "foobar\n", 432 "foobar2\n", 433 }, 434 } 435 436 setupTestLayout(assert, l, func(l *testLayout, validate func(*testLayout)) { 437 scanner := newScanner() 438 scanner.options.MatchMode = matchNameSuffix | matchContent 439 scanner.options.deleteDupes = true 440 scanner.options.Recursive = true 441 442 assert.NoError(scanner.Scan()) 443 fmt.Println(scanner.totals.PrettyFormat(scanner.options.Verb())) 444 assert.Equal(uint64(16), scanner.totals.Files.count) 445 assert.Equal(uint64(73), scanner.totals.Files.size) 446 assert.Equal(uint64(8), scanner.totals.Unique.count) 447 assert.Equal(uint64(41), scanner.totals.Unique.size) 448 assert.Equal(uint64(0), scanner.totals.Links.count) 449 assert.Equal(uint64(0), scanner.totals.Links.size) 450 assert.Equal(uint64(0), scanner.totals.Cloned.count) 451 assert.Equal(uint64(0), scanner.totals.Cloned.size) 452 assert.Equal(uint64(0), scanner.totals.Dupes.count) 453 assert.Equal(uint64(0), scanner.totals.Dupes.size) 454 assert.Equal(uint64(8), scanner.totals.Processed.count) 455 assert.Equal(uint64(32), scanner.totals.Processed.size) 456 assert.Equal(uint64(0), scanner.totals.Skipped.count) 457 assert.Equal(uint64(0), scanner.totals.Skipped.size) 458 assert.Equal(uint64(0), scanner.totals.Errors.count) 459 assert.Equal(uint64(0), scanner.totals.Errors.size) 460 l.contentOverride = true 461 l.content = map[string]string{ 462 "a/bar": "bar\n", 463 "a/bar (1)": "bar\n", 464 "a/bar.foo": "bar\n", 465 "a/bar-01": "bar\n", 466 "a/diffContent": "fizz\n", 467 "a/diffSize": "foobar\n", 468 "b/diffContent": "buzz\n", 469 "b/diffSize": "foobar2\n", 470 } 471 validate(l) 472 }) 473 } 474 475 func TestScanner_NameOnly(t *testing.T) { 476 assert := require.New(t) 477 setupTest(assert, func(l *testLayout, validate func(*testLayout)) { 478 // Phase 1: Hardlink 479 scanner := newScanner() 480 scanner.options.MatchMode = matchName 481 scanner.options.makeLinks = true 482 scanner.options.Recursive = true 483 484 assert.NoError(scanner.Scan()) 485 fmt.Println(scanner.totals.PrettyFormat(scanner.options.Verb())) 486 assert.Equal(uint64(22), scanner.totals.Files.count) 487 assert.Equal(uint64(73), scanner.totals.Files.size) 488 assert.Equal(uint64(11), scanner.totals.Unique.count) 489 // this might change by one if the other file is found first 490 assert.Equal(uint64(36), scanner.totals.Unique.size) 491 assert.Equal(uint64(11), scanner.totals.Links.count) 492 assert.Equal(uint64(36), scanner.totals.Links.size) 493 assert.Equal(uint64(0), scanner.totals.Cloned.count) 494 assert.Equal(uint64(0), scanner.totals.Cloned.size) 495 assert.Equal(uint64(0), scanner.totals.Dupes.count) 496 assert.Equal(uint64(0), scanner.totals.Dupes.size) 497 assert.Equal(uint64(11), scanner.totals.Processed.count) 498 // this will be one larger than Unique size because b/diffSize becomes smaller 499 assert.Equal(uint64(37), scanner.totals.Processed.size) 500 assert.Equal(uint64(0), scanner.totals.Skipped.count) 501 assert.Equal(uint64(0), scanner.totals.Skipped.size) 502 assert.Equal(uint64(0), scanner.totals.Errors.count) 503 assert.Equal(uint64(0), scanner.totals.Errors.size) 504 l.diffContent[1] = l.diffContent[0] 505 l.diffSize[1] = l.diffSize[0] 506 validate(l) 507 }) 508 } 509 510 func TestScanner_SizeOnly(t *testing.T) { 511 assert := require.New(t) 512 setupTest(assert, func(l *testLayout, validate func(*testLayout)) { 513 // Phase 1: Hardlink 514 scanner := newScanner() 515 scanner.options.MatchMode = matchSize 516 scanner.options.makeLinks = true 517 scanner.options.Recursive = true 518 519 assert.NoError(scanner.Scan()) 520 fmt.Println(scanner.totals.PrettyFormat(scanner.options.Verb())) 521 assert.Equal(uint64(22), scanner.totals.Files.count) 522 assert.Equal(uint64(73), scanner.totals.Files.size) 523 assert.Equal(uint64(5), scanner.totals.Unique.count) 524 assert.Equal(uint64(24), scanner.totals.Unique.size) 525 assert.Equal(uint64(17), scanner.totals.Links.count) 526 assert.Equal(uint64(49), scanner.totals.Links.size) 527 assert.Equal(uint64(0), scanner.totals.Cloned.count) 528 assert.Equal(uint64(0), scanner.totals.Cloned.size) 529 assert.Equal(uint64(0), scanner.totals.Dupes.count) 530 assert.Equal(uint64(0), scanner.totals.Dupes.size) 531 assert.Equal(uint64(17), scanner.totals.Processed.count) 532 assert.Equal(uint64(49), scanner.totals.Processed.size) 533 assert.Equal(uint64(0), scanner.totals.Skipped.count) 534 assert.Equal(uint64(0), scanner.totals.Skipped.size) 535 assert.Equal(uint64(0), scanner.totals.Errors.count) 536 assert.Equal(uint64(0), scanner.totals.Errors.size) 537 l.content["foo"] = l.content["bar"] 538 l.content["foo2"] = l.content["bar"] 539 l.content["foo3"] = l.content["bar"] 540 l.diffContent[1] = l.diffContent[0] 541 validate(l) 542 }) 543 } 544 545 func TestScanner_SkipHeader(t *testing.T) { 546 assert := require.New(t) 547 setupTest(assert, func(l *testLayout, validate func(*testLayout)) { 548 scanner := newScanner() 549 scanner.options.MatchMode = matchContent 550 scanner.options.makeLinks = true 551 scanner.options.Recursive = true 552 scanner.options.SkipHeader = 3 553 554 assert.NoError(scanner.Scan()) 555 fmt.Println(scanner.totals.PrettyFormat(scanner.options.Verb())) 556 assert.Equal(uint64(16), scanner.totals.Files.count) 557 assert.Equal(uint64(73), scanner.totals.Files.size) 558 assert.Equal(uint64(4), scanner.totals.Unique.count) 559 assert.Equal(uint64(24), scanner.totals.Unique.size) 560 assert.Equal(uint64(12), scanner.totals.Links.count) 561 assert.Equal(uint64(49), scanner.totals.Links.size) 562 assert.Equal(uint64(0), scanner.totals.Cloned.count) 563 assert.Equal(uint64(0), scanner.totals.Cloned.size) 564 assert.Equal(uint64(0), scanner.totals.Dupes.count) 565 assert.Equal(uint64(0), scanner.totals.Dupes.size) 566 assert.Equal(uint64(12), scanner.totals.Processed.count) 567 assert.Equal(uint64(49), scanner.totals.Processed.size) 568 assert.Equal(uint64(6), scanner.totals.Skipped.count) 569 assert.Equal(uint64(0), scanner.totals.Skipped.size) 570 assert.Equal(uint64(0), scanner.totals.Errors.count) 571 assert.Equal(uint64(0), scanner.totals.Errors.size) 572 l.content["foo"] = l.content["bar"] 573 l.content["foo2"] = l.content["bar"] 574 l.content["foo3"] = l.content["bar"] 575 l.diffContent[1] = l.diffContent[0] 576 validate(l) 577 }) 578 } 579 580 func TestScanner_Parent(t *testing.T) { 581 assert := require.New(t) 582 l := &testLayout{ 583 dirs: []string{ 584 "./foo/a", 585 "./foo/b", 586 "./bar/a", 587 "./bar/b", 588 }, 589 content: map[string]string{ 590 "fizz1": "fizz", 591 "fizz2": "fizz", 592 "buzz": "buzz", 593 }, 594 diffContent: nil, 595 diffSize: nil, 596 } 597 setupTestLayout(assert, l, func(l *testLayout, validate func(*testLayout)) { 598 scanner := newScanner() 599 assert.Empty(scanner.options.ParseArgs([]string{`fdf`, `-rd`, `-m`, `content+parent`, `-z`, `0`})) 600 assert.True(scanner.options.deleteDupes) 601 assert.True(scanner.options.Recursive) 602 assert.Equal(matchContent|matchParent, scanner.options.MatchMode) 603 604 assert.NoError(scanner.Scan()) 605 fmt.Println(scanner.totals.PrettyFormat(scanner.options.Verb())) 606 assert.Equal(uint64(12), scanner.totals.Files.count) 607 assert.Equal(uint64(48), scanner.totals.Files.size) 608 assert.Equal(uint64(4), scanner.totals.Unique.count) 609 assert.Equal(uint64(16), scanner.totals.Unique.size) 610 assert.Equal(uint64(0), scanner.totals.Links.count) 611 assert.Equal(uint64(0), scanner.totals.Links.size) 612 assert.Equal(uint64(0), scanner.totals.Cloned.count) 613 assert.Equal(uint64(0), scanner.totals.Cloned.size) 614 assert.Equal(uint64(0), scanner.totals.Dupes.count) 615 assert.Equal(uint64(0), scanner.totals.Dupes.size) 616 assert.Equal(uint64(8), scanner.totals.Processed.count) 617 assert.Equal(uint64(32), scanner.totals.Processed.size) 618 assert.Equal(uint64(0), scanner.totals.Skipped.count) 619 assert.Equal(uint64(0), scanner.totals.Skipped.size) 620 assert.Equal(uint64(0), scanner.totals.Errors.count) 621 assert.Equal(uint64(0), scanner.totals.Errors.size) 622 l.contentOverride = true 623 l.content = map[string]string{ 624 "bar/a/fizz1": "fizz", 625 "bar/a/buzz": "buzz", 626 "bar/b/fizz1": "fizz", 627 "bar/b/buzz": "buzz", 628 } 629 validate(l) 630 }) 631 } 632 633 func TestScanner_Path(t *testing.T) { 634 assert := require.New(t) 635 l := &testLayout{ 636 dirs: []string{ 637 "./foo/a", 638 "./foo/b", 639 "./bar/a", 640 "./bar/b", 641 }, 642 content: map[string]string{ 643 "fizz1": "fizz", 644 "fizz2": "fizz", 645 "buzz": "buzz", 646 }, 647 diffContent: nil, 648 diffSize: nil, 649 } 650 setupTestLayout(assert, l, func(l *testLayout, validate func(*testLayout)) { 651 scanner := newScanner() 652 assert.Empty(scanner.options.ParseArgs([]string{`fdf`, `-rd`, `-m`, `path+content`, `-z`, `0`})) 653 assert.True(scanner.options.deleteDupes) 654 assert.True(scanner.options.Recursive) 655 assert.Equal(matchContent|matchParent|matchPathSuffix, scanner.options.MatchMode) 656 657 assert.NoError(scanner.Scan()) 658 fmt.Println(scanner.totals.PrettyFormat(scanner.options.Verb())) 659 assert.Equal(uint64(12), scanner.totals.Files.count) 660 assert.Equal(uint64(48), scanner.totals.Files.size) 661 assert.Equal(uint64(8), scanner.totals.Unique.count) 662 assert.Equal(uint64(32), scanner.totals.Unique.size) 663 assert.Equal(uint64(0), scanner.totals.Links.count) 664 assert.Equal(uint64(0), scanner.totals.Links.size) 665 assert.Equal(uint64(0), scanner.totals.Cloned.count) 666 assert.Equal(uint64(0), scanner.totals.Cloned.size) 667 assert.Equal(uint64(0), scanner.totals.Dupes.count) 668 assert.Equal(uint64(0), scanner.totals.Dupes.size) 669 assert.Equal(uint64(4), scanner.totals.Processed.count) 670 assert.Equal(uint64(16), scanner.totals.Processed.size) 671 assert.Equal(uint64(0), scanner.totals.Skipped.count) 672 assert.Equal(uint64(0), scanner.totals.Skipped.size) 673 assert.Equal(uint64(0), scanner.totals.Errors.count) 674 assert.Equal(uint64(0), scanner.totals.Errors.size) 675 l.contentOverride = true 676 l.content = map[string]string{ 677 "foo/a/fizz1": "fizz", 678 "foo/a/buzz": "buzz", 679 "foo/b/fizz1": "fizz", 680 "foo/b/buzz": "buzz", 681 "bar/a/fizz1": "fizz", 682 "bar/a/buzz": "buzz", 683 "bar/b/fizz1": "fizz", 684 "bar/b/buzz": "buzz", 685 } 686 validate(l) 687 }) 688 } 689 690 func TestScanner_PathSuffix(t *testing.T) { 691 assert := require.New(t) 692 l := &testLayout{ 693 dirs: []string{ 694 "./foo/a", 695 "./foo/b", 696 "./bar/a", 697 "./bar/b", 698 }, 699 content: map[string]string{ 700 "fizz1": "fizz", 701 "fizz2": "fizz", 702 "buzz": "buzz", 703 }, 704 diffContent: nil, 705 diffSize: nil, 706 } 707 setupTestLayout(assert, l, func(l *testLayout, validate func(*testLayout)) { 708 scanner := newScanner() 709 assert.Empty(scanner.options.ParseArgs([]string{`fdf`, `-rd`, `-m`, `relpath+content`, `-z`, `0`})) 710 assert.True(scanner.options.deleteDupes) 711 assert.True(scanner.options.Recursive) 712 assert.Equal(matchContent|matchParent|matchPathSuffix, scanner.options.MatchMode) 713 714 assert.NoError(scanner.Scan("./foo", "./bar")) 715 fmt.Println(scanner.totals.PrettyFormat(scanner.options.Verb())) 716 assert.Equal(uint64(12), scanner.totals.Files.count) 717 assert.Equal(uint64(48), scanner.totals.Files.size) 718 assert.Equal(uint64(4), scanner.totals.Unique.count) 719 assert.Equal(uint64(16), scanner.totals.Unique.size) 720 assert.Equal(uint64(0), scanner.totals.Links.count) 721 assert.Equal(uint64(0), scanner.totals.Links.size) 722 assert.Equal(uint64(0), scanner.totals.Cloned.count) 723 assert.Equal(uint64(0), scanner.totals.Cloned.size) 724 assert.Equal(uint64(0), scanner.totals.Dupes.count) 725 assert.Equal(uint64(0), scanner.totals.Dupes.size) 726 assert.Equal(uint64(8), scanner.totals.Processed.count) 727 assert.Equal(uint64(32), scanner.totals.Processed.size) 728 assert.Equal(uint64(0), scanner.totals.Skipped.count) 729 assert.Equal(uint64(0), scanner.totals.Skipped.size) 730 assert.Equal(uint64(0), scanner.totals.Errors.count) 731 assert.Equal(uint64(0), scanner.totals.Errors.size) 732 l.contentOverride = true 733 l.content = map[string]string{ 734 "foo/a/fizz1": "fizz", 735 "foo/a/buzz": "buzz", 736 "foo/b/fizz1": "fizz", 737 "foo/b/buzz": "buzz", 738 } 739 validate(l) 740 }) 741 } 742 743 type testLayout struct { 744 dirs []string 745 746 // Duplicated per dirList[n] 747 content map[string]string 748 749 // Used for certain cases, such as delete, that need to override the default layout 750 // If this is set, content keys are relative paths and all other fields are ignored 751 contentOverride bool 752 753 // dirList[n]/different == different[n] 754 diffContent []string 755 756 // dirList[n]/diffsize == diffsize[n] 757 diffSize []string 758 } 759 760 func setupTest(assert *require.Assertions, f func(l *testLayout, validate func(*testLayout))) { 761 l := &testLayout{ 762 dirs: []string{ 763 "./a", 764 "./b", 765 }, 766 content: map[string]string{ 767 "bar": "bar\n", 768 "bar2": "bar\n", 769 "bar3": "bar\n", 770 "foo": "foo\n", 771 "foo2": "foo\n", 772 "foo3": "foo\n", 773 "empty": "", 774 "empty2": "", 775 "empty3": "", 776 }, 777 diffContent: []string{ 778 "fizz\n", 779 "buzz\n", 780 }, 781 diffSize: []string{ 782 "foobar\n", 783 "foobar2\n", 784 }, 785 } 786 setupTestLayout(assert, l, f) 787 } 788 789 func setupTestLayout(assert *require.Assertions, l *testLayout, f func(l *testLayout, validate func(*testLayout))) { 790 dir, err := ioutil.TempDir("", "fdftest") 791 assert.NoError(err) 792 defer os.RemoveAll(dir) 793 assert.NoError(os.Chdir(dir)) 794 795 for i, d := range l.dirs { 796 assert.NoError(os.MkdirAll(d, 0777)) 797 for f, c := range l.content { 798 assert.NoError(ioutil.WriteFile(filepath.Join(d, fmt.Sprintf("%s", f)), []byte(c), 0666)) 799 } 800 if len(l.diffContent) != 0 { 801 assert.NoError(ioutil.WriteFile(filepath.Join(d, "diffContent"), []byte(l.diffContent[i]), 0666)) 802 } 803 if len(l.diffSize) != 0 { 804 assert.NoError(ioutil.WriteFile(filepath.Join(d, "diffSize"), []byte(l.diffSize[i]), 0666)) 805 } 806 } 807 808 f(l, func(l *testLayout) { 809 glob, err := zglob.Glob("./**/*") 810 var g []string 811 for _, x := range glob { 812 st, err := os.Stat(x) 813 assert.NoError(err) 814 if !st.IsDir() { 815 g = append(g, x) 816 } 817 } 818 assert.NoError(err) 819 820 if l.contentOverride { 821 assert.Len(g, len(l.content), "wrong number of files") 822 823 for f, c := range l.content { 824 b, err := ioutil.ReadFile(f) 825 assert.NoError(err) 826 assert.Equalf(c, string(b), "%s", f) 827 } 828 } else { 829 assert.Len(g, (len(l.dirs)*len(l.content))+len(l.diffContent)+len(l.diffSize)) 830 831 for i, d := range l.dirs { 832 for f, c := range l.content { 833 b, err := ioutil.ReadFile(filepath.Join(d, f)) 834 assert.NoError(err) 835 assert.Equalf(c, string(b), "%s", f) 836 } 837 if len(l.diffContent) != 0 { 838 b, err := ioutil.ReadFile(filepath.Join(d, "diffContent")) 839 assert.NoError(err) 840 assert.Equal(l.diffContent[i], string(b)) 841 } 842 if len(l.diffSize) != 0 { 843 b, err := ioutil.ReadFile(filepath.Join(d, "diffSize")) 844 assert.NoError(err) 845 assert.Equal(l.diffSize[i], string(b)) 846 } 847 } 848 } 849 }) 850 }