@@ -270,6 +270,59 @@ func TestUploadSendsJSONLToS3(t *testing.T) {
270270 }
271271}
272272
273+ func TestUploadReusesLastObjectForSameRun (t * testing.T ) {
274+ current := time .Date (2026 , 7 , 12 , 20 , 17 , 3 , 0 , time .UTC )
275+ restore := stubNowFunc (t , func () time.Time { return current })
276+ defer restore ()
277+ var uploadedPaths []string
278+ server := httptest .NewServer (http .HandlerFunc (func (w http.ResponseWriter , r * http.Request ) {
279+ uploadedPaths = append (uploadedPaths , r .URL .EscapedPath ())
280+ w .WriteHeader (http .StatusOK )
281+ }))
282+ defer server .Close ()
283+
284+ dir := t .TempDir ()
285+ logPath := filepath .Join (dir , "runtime.jsonl" )
286+ if err := os .WriteFile (logPath , []byte ("{\" event\" :\" first\" }\n " ), 0644 ); err != nil {
287+ t .Fatalf ("write log: %v" , err )
288+ }
289+ cfg := Config {
290+ Upload : uploadS3 ,
291+ LogPath : logPath ,
292+ StatePath : filepath .Join (dir , "state.json" ),
293+ Bucket : "bucket" ,
294+ Prefix : "prefix" ,
295+ Provider : "cursor_cloud" ,
296+ RunID : "run" ,
297+ S3Region : "us-west-2" ,
298+ S3AccessKeyID : "AKIATEST" ,
299+ S3SecretKey : "secret" ,
300+ S3Endpoint : server .URL ,
301+ }
302+ if err := Upload (context .Background (), cfg , true ); err != nil {
303+ t .Fatalf ("first Upload returned error: %v" , err )
304+ }
305+
306+ current = current .Add (2 * time .Minute )
307+ if err := os .WriteFile (logPath , []byte ("{\" event\" :\" second\" }\n " ), 0644 ); err != nil {
308+ t .Fatalf ("rewrite log: %v" , err )
309+ }
310+ if err := Upload (context .Background (), cfg , true ); err != nil {
311+ t .Fatalf ("second Upload returned error: %v" , err )
312+ }
313+
314+ if len (uploadedPaths ) != 2 {
315+ t .Fatalf ("uploaded paths = %v, want 2 uploads" , uploadedPaths )
316+ }
317+ if uploadedPaths [0 ] != uploadedPaths [1 ] {
318+ t .Fatalf ("Upload used different object keys: first=%q second=%q" , uploadedPaths [0 ], uploadedPaths [1 ])
319+ }
320+ want := "/bucket/prefix/runtime/date=2026-07-12/1783887423-cursor_cloud-run.jsonl.gz"
321+ if uploadedPaths [0 ] != want {
322+ t .Fatalf ("upload path = %q, want %q" , uploadedPaths [0 ], want )
323+ }
324+ }
325+
273326func TestResolveRunIDUsesOnlyEnvironment (t * testing.T ) {
274327 t .Setenv ("CLAUDE_CODE_REMOTE_SESSION_ID" , "cse_env" )
275328 if got := resolveRunID (); got != "cse_env" {
@@ -302,9 +355,14 @@ func mustRSAKey(t *testing.T) *rsa.PrivateKey {
302355}
303356
304357func stubNow (t * testing.T , value time.Time ) func () {
358+ t .Helper ()
359+ return stubNowFunc (t , func () time.Time { return value .UTC () })
360+ }
361+
362+ func stubNowFunc (t * testing.T , fn func () time.Time ) func () {
305363 t .Helper ()
306364 old := nowUTC
307- nowUTC = func () time.Time { return value .UTC () }
365+ nowUTC = func () time.Time { return fn () .UTC () }
308366 return func () { nowUTC = old }
309367}
310368
0 commit comments