@@ -38,10 +38,53 @@ public class MockGcsBlobStore {
3838
3939    record  BlobVersion (String  path , long  generation , BytesReference  contents ) {}
4040
41-     record  ResumableUpload (String  uploadId , String  path , Long  ifGenerationMatch , BytesReference  contents , boolean  completed ) {
41+     record  ResumableUpload (
42+         String  uploadId ,
43+         String  path ,
44+         Long  ifGenerationMatch ,
45+         BytesReference  contents ,
46+         Integer  finalLength ,
47+         boolean  completed 
48+     ) {
49+ 
50+         ResumableUpload (String  uploadId , String  path , Long  ifGenerationMatch ) {
51+             this (uploadId , path , ifGenerationMatch , BytesArray .EMPTY , null , false );
52+         }
4253
43-         public  ResumableUpload  update (BytesReference  contents , boolean  completed ) {
44-             return  new  ResumableUpload (uploadId , path , ifGenerationMatch , contents , completed );
54+         public  ResumableUpload  update (BytesReference  contents ) {
55+             if  (completed ) {
56+                 throw  new  IllegalStateException ("Blob already completed" );
57+             }
58+             return  new  ResumableUpload (uploadId , path , ifGenerationMatch , contents , null , false );
59+         }
60+ 
61+         /** 
62+          * When we complete, we nullify our reference to the contents to allow it to be collected if it gets overwritten 
63+          */ 
64+         public  ResumableUpload  complete () {
65+             if  (completed ) {
66+                 throw  new  IllegalStateException ("Blob already completed" );
67+             }
68+             return  new  ResumableUpload (uploadId , path , ifGenerationMatch , null , contents .length (), true );
69+         }
70+ 
71+         public  HttpHeaderParser .Range  getRange () {
72+             int  length  = length ();
73+             if  (length  > 0 ) {
74+                 return  new  HttpHeaderParser .Range (0 , length  - 1 );
75+             } else  {
76+                 return  null ;
77+             }
78+         }
79+ 
80+         public  int  length () {
81+             if  (finalLength  != null ) {
82+                 return  finalLength ;
83+             }
84+             if  (contents  != null ) {
85+                 return  contents .length ();
86+             }
87+             return  0 ;
4588        }
4689    }
4790
@@ -93,7 +136,7 @@ BlobVersion updateBlob(String path, Long ifGenerationMatch, BytesReference conte
93136
94137    ResumableUpload  createResumableUpload (String  path , Long  ifGenerationMatch ) {
95138        final  String  uploadId  = UUIDs .randomBase64UUID ();
96-         final  ResumableUpload  value  = new  ResumableUpload (uploadId , path , ifGenerationMatch ,  BytesArray . EMPTY ,  false );
139+         final  ResumableUpload  value  = new  ResumableUpload (uploadId , path , ifGenerationMatch );
97140        resumableUploads .put (uploadId , value );
98141        return  value ;
99142    }
@@ -141,33 +184,25 @@ UpdateResponse updateResumableUpload(String uploadId, HttpHeaderParser.ContentRa
141184                    existing .contents ,
142185                    requestBody .slice (offset , requestBody .length ())
143186                );
144-                 valueToReturn  = existing .update (updatedContent ,  false );
187+                 valueToReturn  = existing .update (updatedContent );
145188            }
146189
147190            // Next we determine the response 
148191            if  (valueToReturn .completed ) {
149-                 updateResponse .set (new  UpdateResponse (RestStatus .OK .getStatus (), calculateRangeHeader ( valueToReturn )));
192+                 updateResponse .set (new  UpdateResponse (RestStatus .OK .getStatus (), valueToReturn . getRange ( )));
150193            } else  if  (contentRange .hasSize () && contentRange .size () == valueToReturn .contents .length ()) {
151-                 valueToReturn  = existing .update (valueToReturn .contents , true );
152194                updateBlob (valueToReturn .path (), valueToReturn .ifGenerationMatch (), valueToReturn .contents );
153-                 updateResponse .set (new  UpdateResponse (RestStatus .OK .getStatus (), calculateRangeHeader (valueToReturn )));
195+                 valueToReturn  = valueToReturn .complete ();
196+                 updateResponse .set (new  UpdateResponse (RestStatus .OK .getStatus (), valueToReturn .getRange ()));
154197            } else  {
155-                 updateResponse .set (new  UpdateResponse (RESUME_INCOMPLETE , calculateRangeHeader ( valueToReturn )));
198+                 updateResponse .set (new  UpdateResponse (RESUME_INCOMPLETE , valueToReturn . getRange ( )));
156199            }
157200            return  valueToReturn ;
158201        });
159202        assert  updateResponse .get () != null  : "Should always produce an update response" ;
160203        return  updateResponse .get ();
161204    }
162205
163-     private  static  HttpHeaderParser .Range  calculateRangeHeader (ResumableUpload  resumableUpload ) {
164-         return  resumableUpload .contents .length () > 0  ? new  HttpHeaderParser .Range (0 , resumableUpload .contents .length () - 1 ) : null ;
165-     }
166- 
167-     private  static  HttpHeaderParser .Range  calculateRangeHeader (BlobVersion  blob ) {
168-         return  blob .contents .length () > 0  ? new  HttpHeaderParser .Range (0 , blob .contents .length () - 1 ) : null ;
169-     }
170- 
171206    record  UpdateResponse (int  statusCode , HttpHeaderParser .Range  rangeHeader ) {}
172207
173208    void  deleteBlob (String  path ) {
0 commit comments