@@ -8,8 +8,18 @@ import (
88 "net/http/httptest"
99 "strings"
1010 "testing"
11+ "time"
1112)
1213
14+ // fastRetry compresses the retry backoff so tests that exercise the retry
15+ // path don't sleep for real seconds. It restores the original on cleanup.
16+ func fastRetry (t * testing.T ) {
17+ t .Helper ()
18+ orig := downloadRetryBackoff
19+ downloadRetryBackoff = time .Millisecond
20+ t .Cleanup (func () { downloadRetryBackoff = orig })
21+ }
22+
1323func fullManifestJSON (extraFields string ) string {
1424 return fmt .Sprintf (`{
1525 "version": 1,
@@ -31,7 +41,7 @@ func TestFetchManifest_HappyPath(t *testing.T) {
3141 }))
3242 defer srv .Close ()
3343
34- m , err := FetchManifest (context .Background (), srv .URL )
44+ m , err := FetchManifest (context .Background (), srv .URL , nil )
3545 if err != nil {
3646 t .Fatalf ("FetchManifest: %v" , err )
3747 }
@@ -66,7 +76,7 @@ func TestFetchManifest_EnvOverride(t *testing.T) {
6676 defer srv .Close ()
6777
6878 t .Setenv (envManifest , srv .URL )
69- if _ , err := FetchManifest (context .Background (), "https://default/manifest.json" ); err != nil {
79+ if _ , err := FetchManifest (context .Background (), "https://default/manifest.json" , nil ); err != nil {
7080 t .Fatalf ("FetchManifest: %v" , err )
7181 }
7282 if ! served {
@@ -81,7 +91,7 @@ func TestFetchManifest_RejectsUnsupportedVersion(t *testing.T) {
8191 }))
8292 defer srv .Close ()
8393
84- _ , err := FetchManifest (context .Background (), srv .URL )
94+ _ , err := FetchManifest (context .Background (), srv .URL , nil )
8595 if ! errors .Is (err , ErrUnsupportedManifestVersion ) {
8696 t .Fatalf ("want ErrUnsupportedManifestVersion, got %v" , err )
8797 }
@@ -94,7 +104,7 @@ func TestFetchManifest_RejectsEmptyPlatforms(t *testing.T) {
94104 }))
95105 defer srv .Close ()
96106
97- _ , err := FetchManifest (context .Background (), srv .URL )
107+ _ , err := FetchManifest (context .Background (), srv .URL , nil )
98108 if err == nil || ! strings .Contains (err .Error (), "platforms is empty" ) {
99109 t .Errorf ("want empty-platforms error, got %v" , err )
100110 }
@@ -106,24 +116,53 @@ func TestFetchManifest_RejectsUnknownFields(t *testing.T) {
106116 }))
107117 defer srv .Close ()
108118
109- _ , err := FetchManifest (context .Background (), srv .URL )
119+ _ , err := FetchManifest (context .Background (), srv .URL , nil )
110120 if err == nil || ! strings .Contains (err .Error (), "unknown field" ) {
111121 t .Errorf ("want unknown-field rejection, got %v" , err )
112122 }
113123}
114124
115125func TestFetchManifest_HTTPError (t * testing.T ) {
126+ fastRetry (t )
116127 srv := httptest .NewServer (http .HandlerFunc (func (w http.ResponseWriter , r * http.Request ) {
117128 http .Error (w , "not found" , http .StatusNotFound )
118129 }))
119130 defer srv .Close ()
120131
121- _ , err := FetchManifest (context .Background (), srv .URL )
132+ _ , err := FetchManifest (context .Background (), srv .URL , nil )
122133 if err == nil || ! strings .Contains (err .Error (), "404" ) {
123134 t .Errorf ("want HTTP 404, got %v" , err )
124135 }
125136}
126137
138+ // TestFetchManifest_RetriesTransient verifies a transient 5xx (e.g. a
139+ // GitHub CDN 504) is retried and the fetch ultimately succeeds.
140+ func TestFetchManifest_RetriesTransient (t * testing.T ) {
141+ fastRetry (t )
142+ var attempts int
143+ srv := httptest .NewServer (http .HandlerFunc (func (w http.ResponseWriter , r * http.Request ) {
144+ attempts ++
145+ if attempts < 3 {
146+ http .Error (w , "gateway timeout" , http .StatusGatewayTimeout )
147+ return
148+ }
149+ w .Header ().Set ("Content-Type" , "application/json" )
150+ _ , _ = w .Write ([]byte (fullManifestJSON ("" )))
151+ }))
152+ defer srv .Close ()
153+
154+ m , err := FetchManifest (context .Background (), srv .URL , nil )
155+ if err != nil {
156+ t .Fatalf ("FetchManifest after transient 504s: %v" , err )
157+ }
158+ if m .Version != 1 {
159+ t .Errorf ("Version = %d, want 1" , m .Version )
160+ }
161+ if attempts != 3 {
162+ t .Errorf ("attempts = %d, want 3 (two 504s then success)" , attempts )
163+ }
164+ }
165+
127166func TestArtifactsForCurrentPlatform_NotFound (t * testing.T ) {
128167 m := & Manifest {
129168 Version : 1 ,
0 commit comments