|
8 | 8 | "path/filepath" |
9 | 9 | "strings" |
10 | 10 | "testing" |
| 11 | + "time" |
11 | 12 | ) |
12 | 13 |
|
13 | 14 | func TestWriteFile(t *testing.T) { |
@@ -159,6 +160,36 @@ func TestInstallFile(t *testing.T) { |
159 | 160 | } |
160 | 161 | } |
161 | 162 |
|
| 163 | +func TestInstallFileWithLimitedSizeCreatesTempFileInTargetDir(t *testing.T) { |
| 164 | + targetDir := t.TempDir() |
| 165 | + tmpDir := t.TempDir() |
| 166 | + t.Setenv("TMPDIR", tmpDir) |
| 167 | + |
| 168 | + filename := filepath.Join(targetDir, "target.txt") |
| 169 | + reader := &blockingReader{ |
| 170 | + started: make(chan struct{}), |
| 171 | + unblock: make(chan struct{}), |
| 172 | + } |
| 173 | + errCh := make(chan error, 1) |
| 174 | + go func() { |
| 175 | + errCh <- InstallFileWithLimitedSize(filename, reader, 0o644, 1024) |
| 176 | + }() |
| 177 | + |
| 178 | + <-reader.started |
| 179 | + |
| 180 | + if !waitForTempFile(t, targetDir, filepath.Base(filename)) { |
| 181 | + t.Fatalf("expected pending temp file in target directory %q", targetDir) |
| 182 | + } |
| 183 | + if hasTempFile(t, tmpDir, filepath.Base(filename)) { |
| 184 | + t.Fatalf("expected no pending temp file in TMPDIR %q", tmpDir) |
| 185 | + } |
| 186 | + |
| 187 | + close(reader.unblock) |
| 188 | + if err := <-errCh; err != nil { |
| 189 | + t.Fatalf("unexpected error: %v", err) |
| 190 | + } |
| 191 | +} |
| 192 | + |
162 | 193 | func TestInstallFileWithLimitedSize(t *testing.T) { |
163 | 194 | tests := []struct { |
164 | 195 | name string |
@@ -391,3 +422,44 @@ type errReader struct { |
391 | 422 | func (e *errReader) Read(_ []byte) (int, error) { |
392 | 423 | return 0, e.err |
393 | 424 | } |
| 425 | + |
| 426 | +type blockingReader struct { |
| 427 | + started chan struct{} |
| 428 | + unblock chan struct{} |
| 429 | + sent bool |
| 430 | +} |
| 431 | + |
| 432 | +func (r *blockingReader) Read(p []byte) (int, error) { |
| 433 | + if !r.sent { |
| 434 | + r.sent = true |
| 435 | + p[0] = 'x' |
| 436 | + close(r.started) |
| 437 | + return 1, nil |
| 438 | + } |
| 439 | + |
| 440 | + <-r.unblock |
| 441 | + return 0, io.EOF |
| 442 | +} |
| 443 | + |
| 444 | +func waitForTempFile(t *testing.T, dir, targetBase string) bool { |
| 445 | + t.Helper() |
| 446 | + |
| 447 | + deadline := time.Now().Add(2 * time.Second) |
| 448 | + for time.Now().Before(deadline) { |
| 449 | + if hasTempFile(t, dir, targetBase) { |
| 450 | + return true |
| 451 | + } |
| 452 | + time.Sleep(10 * time.Millisecond) |
| 453 | + } |
| 454 | + return false |
| 455 | +} |
| 456 | + |
| 457 | +func hasTempFile(t *testing.T, dir, targetBase string) bool { |
| 458 | + t.Helper() |
| 459 | + |
| 460 | + matches, err := filepath.Glob(filepath.Join(dir, "."+targetBase+"*")) |
| 461 | + if err != nil { |
| 462 | + t.Fatalf("glob temp files: %v", err) |
| 463 | + } |
| 464 | + return len(matches) > 0 |
| 465 | +} |
0 commit comments