@@ -90,3 +90,74 @@ func Test_getContents(t *testing.T) {
9090 // 所以最终会返回一个流,包含 chunk1 和 chunk2 的数据
9191 assert .Equal (t , 1 , len (readers ))
9292}
93+
94+ // Test_getContents_lastChunkSizeMismatch verifies that checkChunkSize receives
95+ // the correct chunk index (availableChunks[index]) rather than the requested
96+ // chunk index (idx). When the available anchor chunk is the last chunk with a
97+ // smaller size, passing the wrong index would cause a false size-mismatch error.
98+ func Test_getContents_lastChunkSizeMismatch (t * testing.T ) {
99+ memoryBucket , _ := memory .New (& storage.BucketConfig {}, sharedkv .NewEmpty ())
100+
101+ req , _ := http .NewRequestWithContext (t .Context (), http .MethodGet , "http://www.example.com/path/to/2.apk" , nil )
102+ req .Header .Set ("Range" , "bytes=524288-1672863" )
103+ objectID , _ := newObjectIDFromRequest (req , "" , true )
104+
105+ blockSize := uint64 (524288 )
106+ totalSize := blockSize * 3 + 100000 // 3 full chunks + 1 partial last chunk (100000 bytes)
107+
108+ c := & Caching {
109+ log : log .NewHelper (log .GetLogger ()),
110+ processor : mockProcessorChain (),
111+ id : objectID ,
112+ req : req ,
113+ opt : & cachingOption {
114+ SliceSize : blockSize ,
115+ },
116+ md : & object.Metadata {
117+ ID : objectID ,
118+ Size : totalSize ,
119+ BlockSize : blockSize ,
120+ Chunks : bitmap.Bitmap {},
121+ },
122+ bucket : memoryBucket ,
123+ proxyClient : proxy .New (),
124+ }
125+
126+ // Cached chunks: 0 (full) and 3 (last, partial)
127+ c .md .Chunks .Set (0 )
128+ c .md .Chunks .Set (3 )
129+
130+ // Write chunk 0 with full block size
131+ f0 , _ , err := memoryBucket .WriteChunkFile (context .Background (), objectID , 0 )
132+ assert .NoError (t , err )
133+ _ , _ = f0 .Write (makebuf (int (blockSize )))
134+ _ = f0 .Close ()
135+
136+ // Write chunk 3 (last chunk) with partial size
137+ f3 , _ , err := memoryBucket .WriteChunkFile (context .Background (), objectID , 3 )
138+ assert .NoError (t , err )
139+ _ , _ = f3 .Write (makebuf (int (totalSize % blockSize ))) // 100000 bytes
140+ _ = f3 .Close ()
141+
142+ // Request chunks 1, 2, 3
143+ // idx will be reqChunks[0]=1, but the anchor chunk found is chunk 3 (the last chunk).
144+ // Before the fix, checkChunkSize was called with idx=1 instead of 3,
145+ // causing it to expect full blockSize (524288) for a 100000-byte file.
146+ reqChunks := []uint32 {1 , 2 , 3 }
147+
148+ readers := make ([]io.ReadCloser , 0 , len (reqChunks ))
149+ for i := 0 ; i < len (reqChunks ); {
150+ reader , count , err := getContents (c , reqChunks , uint32 (i ))
151+ assert .NoError (t , err , "getContents should not return a size mismatch error" )
152+
153+ if count == - 1 {
154+ break
155+ }
156+
157+ readers = append (readers , reader )
158+ i += count
159+ }
160+
161+ t .Logf ("all readers %d" , len (readers ))
162+ assert .Equal (t , 1 , len (readers ))
163+ }
0 commit comments