(t *testing.T)
| 343 | } |
| 344 | |
| 345 | func TestCopyFile(t *testing.T) { |
| 346 | t.Run("successful copy", func(t *testing.T) { |
| 347 | dir := t.TempDir() |
| 348 | src := filepath.Join(dir, "src.txt") |
| 349 | dst := filepath.Join(dir, "dst.txt") |
| 350 | content := []byte("file content") |
| 351 | |
| 352 | require.NoError(t, os.WriteFile(src, content, 0600), "Should create source file") |
| 353 | |
| 354 | err := CopyFile(src, dst) |
| 355 | require.NoError(t, err, "CopyFile should succeed for valid src and dst") |
| 356 | |
| 357 | got, readErr := os.ReadFile(dst) |
| 358 | require.NoError(t, readErr, "Should be able to read copied file") |
| 359 | assert.Equal(t, content, got, "Copied file content should match source") |
| 360 | }) |
| 361 | |
| 362 | t.Run("missing source file returns error", func(t *testing.T) { |
| 363 | dir := t.TempDir() |
| 364 | src := filepath.Join(dir, "nonexistent.txt") |
| 365 | dst := filepath.Join(dir, "dst.txt") |
| 366 | |
| 367 | err := CopyFile(src, dst) |
| 368 | require.Error(t, err, "CopyFile should return error when source does not exist") |
| 369 | }) |
| 370 | |
| 371 | t.Run("missing destination directory returns error", func(t *testing.T) { |
| 372 | dir := t.TempDir() |
| 373 | src := filepath.Join(dir, "src.txt") |
| 374 | dst := filepath.Join(dir, "missing_dir", "dst.txt") |
| 375 | |
| 376 | require.NoError(t, os.WriteFile(src, []byte("data"), 0600), "Should create source file") |
| 377 | |
| 378 | err := CopyFile(src, dst) |
| 379 | require.Error(t, err, "CopyFile should return error when destination directory does not exist") |
| 380 | }) |
| 381 | |
| 382 | t.Run("destination file is removed on io.Copy write failure", func(t *testing.T) { |
| 383 | // /dev/full is a Linux special device that always returns ENOSPC on |
| 384 | // writes, making it the most reliable way to inject an io.Copy error |
| 385 | // without modifying CopyFile's signature. |
| 386 | if runtime.GOOS != "linux" { |
| 387 | t.Skip("requires /dev/full (Linux only)") |
| 388 | } |
| 389 | if _, err := os.Stat("/dev/full"); err != nil { |
| 390 | t.Skip("/dev/full not available") |
| 391 | } |
| 392 | |
| 393 | dir := t.TempDir() |
| 394 | src := filepath.Join(dir, "src.txt") |
| 395 | dst := filepath.Join(dir, "dst.txt") |
| 396 | |
| 397 | require.NoError(t, os.WriteFile(src, []byte("hello"), 0600), "Should create source file") |
| 398 | |
| 399 | // Point dst at /dev/full via a symlink so that: |
| 400 | // - os.Create(dst) succeeds (opens /dev/full for writing) |
| 401 | // - io.Copy fails with ENOSPC (every write to /dev/full fails) |
| 402 | // - os.Remove(dst) removes the local symlink, not /dev/full itself |
nothing calls this directly
no test coverage detected