TestDownloadFileRetryLogic tests the retry logic structure of DownloadFile
(t *testing.T)
| 70 | |
| 71 | // TestDownloadFileRetryLogic tests the retry logic structure of DownloadFile |
| 72 | func TestDownloadFileRetryLogic(t *testing.T) { |
| 73 | testData := "hello world\n" |
| 74 | fileName := "testfile.txt" |
| 75 | attempts := 0 |
| 76 | |
| 77 | // Simulate server that fails first few times then succeeds |
| 78 | handlerThatFailsThenSucceeds := func(w http.ResponseWriter, r *http.Request) { |
| 79 | attempts++ |
| 80 | if attempts <= 2 { // First 2 attempts fail |
| 81 | t.Logf("simulating server error (attempt %d)", attempts) |
| 82 | http.Error(w, "server temporarily unavailable", http.StatusInternalServerError) |
| 83 | return |
| 84 | } |
| 85 | t.Logf("responding 200 OK (attempt %d)", attempts) |
| 86 | _, _ = io.WriteString(w, testData) |
| 87 | } |
| 88 | |
| 89 | tmpDir := t.TempDir() |
| 90 | |
| 91 | t.Run("server errors then success with retries", func(t *testing.T) { |
| 92 | attempts = 0 |
| 93 | ts := httptest.NewServer(http.HandlerFunc(handlerThatFailsThenSucceeds)) |
| 94 | defer ts.Close() |
| 95 | |
| 96 | dest := filepath.Join(tmpDir, "retry-success.txt") |
| 97 | err := util.DownloadFile(dest, ts.URL+"/"+fileName, false, "") |
| 98 | require.NoError(t, err) |
| 99 | require.Equal(t, 3, attempts, "expected exactly 3 attempts (2 failures + 1 success)") |
| 100 | |
| 101 | content, err := os.ReadFile(dest) |
| 102 | require.NoError(t, err) |
| 103 | require.Equal(t, testData, string(content)) |
| 104 | }) |
| 105 | |
| 106 | t.Run("server errors exhaust all retries", func(t *testing.T) { |
| 107 | attempts = 0 |
| 108 | // Server always returns error |
| 109 | ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { |
| 110 | attempts++ |
| 111 | t.Logf("simulating server error (attempt %d)", attempts) |
| 112 | http.Error(w, "server permanently unavailable", http.StatusInternalServerError) |
| 113 | })) |
| 114 | defer ts.Close() |
| 115 | |
| 116 | dest := filepath.Join(tmpDir, "retry-fail.txt") |
| 117 | // Set DdevDebug directly since the package variable is cached at init time |
| 118 | origDebug := globalconfig.DdevDebug |
| 119 | globalconfig.DdevDebug = true |
| 120 | t.Cleanup(func() { globalconfig.DdevDebug = origDebug }) |
| 121 | // Also set log level since UserOut is initialized at package load time |
| 122 | origLevel := output.UserOut.GetLevel() |
| 123 | output.UserOut.SetLevel(log.DebugLevel) |
| 124 | t.Cleanup(func() { output.UserOut.SetLevel(origLevel) }) |
| 125 | |
| 126 | restoreOutput := util.CaptureUserOut() |
| 127 | err := util.DownloadFile(dest, ts.URL+"/"+fileName, false, "") |
| 128 | out := restoreOutput() |
| 129 |
nothing calls this directly
no test coverage detected