44package com.azure.storage.blob.specialized
55
66import com.azure.core.exception.UnexpectedLengthException
7+ import com.azure.core.util.CoreUtils
78import com.azure.storage.blob.APISpec
89import com.azure.storage.blob.BlobContainerClient
9- import com.azure.storage.blob.models.PageBlobCopyIncrementalRequestConditions
1010import com.azure.storage.blob.models.BlobErrorCode
1111import com.azure.storage.blob.models.BlobHttpHeaders
1212import com.azure.storage.blob.models.BlobRange
1313import com.azure.storage.blob.models.BlobRequestConditions
1414import com.azure.storage.blob.models.BlobStorageException
15+ import com.azure.storage.blob.models.ClearRange
1516import com.azure.storage.blob.models.CopyStatusType
16- import com.azure.storage.blob.options.BlobGetTagsOptions
17- import com.azure.storage.blob.options.PageBlobCopyIncrementalOptions
18- import com.azure.storage.blob.options.PageBlobCreateOptions
17+ import com.azure.storage.blob.models.PageBlobCopyIncrementalRequestConditions
1918import com.azure.storage.blob.models.PageBlobRequestConditions
2019import com.azure.storage.blob.models.PageRange
2120import com.azure.storage.blob.models.PublicAccessType
2221import com.azure.storage.blob.models.SequenceNumberActionType
22+ import com.azure.storage.blob.options.BlobGetTagsOptions
23+ import com.azure.storage.blob.options.PageBlobCopyIncrementalOptions
24+ import com.azure.storage.blob.options.PageBlobCreateOptions
25+ import com.azure.storage.common.implementation.Constants
2326import spock.lang.Ignore
2427import spock.lang.Unroll
2528
@@ -196,7 +199,7 @@ class PageBlobAPITest extends APISpec {
196199 null | null | garbageEtag | null | null | null
197200 null | null | null | receivedEtag | null | null
198201 null | null | null | null | garbageLeaseID | null
199- null | null | null | null | null | " \" notfoo\" = 'notbar'"
202+ null | null | null | null | null | " \" notfoo\" = 'notbar'"
200203 }
201204
202205 def " Create error" () {
@@ -756,7 +759,7 @@ class PageBlobAPITest extends APISpec {
756759 null | null | garbageEtag | null | null | null
757760 null | null | null | receivedEtag | null | null
758761 null | null | null | null | garbageLeaseID | null
759- null | null | null | null | null | " \" notfoo\" = 'notbar'"
762+ null | null | null | null | null | " \" notfoo\" = 'notbar'"
760763 }
761764
762765 def " Get page ranges error" () {
@@ -770,32 +773,81 @@ class PageBlobAPITest extends APISpec {
770773 thrown(BlobStorageException )
771774 }
772775
776+ @Unroll
773777 def " Get page ranges diff" () {
774778 setup :
775- bc. create(PageBlobClient . PAGE_BYTES * 2 , true )
779+ bc. create(4 * Constants . MB , true )
776780
777- bc. uploadPages(new PageRange (). setStart(PageBlobClient . PAGE_BYTES ). setEnd(PageBlobClient . PAGE_BYTES * 2 - 1 ),
778- new ByteArrayInputStream (getRandomByteArray(PageBlobClient . PAGE_BYTES )))
781+ bc. uploadPages(new PageRange (). setStart(0 ). setEnd(4 * Constants . MB - 1 ),
782+ new ByteArrayInputStream (getRandomByteArray(4 * Constants . MB )))
779783
780784 def snapId = bc. createSnapshot(). getSnapshotId()
781785
782- bc. uploadPages(new PageRange (). setStart(0 ). setEnd(PageBlobClient . PAGE_BYTES - 1 ),
783- new ByteArrayInputStream (getRandomByteArray(PageBlobClient . PAGE_BYTES )))
786+ rangesToUpdate. forEach({
787+ bc. uploadPages(it, new ByteArrayInputStream (getRandomByteArray((int ) (it. getEnd() - it. getStart()) + 1 )))
788+ })
784789
785- bc . clearPages( new PageRange () . setStart( PageBlobClient . PAGE_BYTES ) . setEnd( PageBlobClient . PAGE_BYTES * 2 - 1 ) )
790+ rangesToClear . forEach({ bc . clearPages(it) } )
786791
787792 when :
788- def response = bc. getPageRangesDiffWithResponse(new BlobRange (0 , PageBlobClient . PAGE_BYTES * 2 ), snapId, null , null , null )
793+ def response = bc. getPageRangesDiffWithResponse(new BlobRange (0 , 4 * Constants . MB ), snapId, null , null , null )
789794
790795 then :
791- response. getValue(). getPageRange(). size() == 1
792- response. getValue(). getPageRange(). get(0 ). getStart() == 0
793- response. getValue(). getPageRange(). get(0 ). getEnd() == PageBlobClient . PAGE_BYTES - 1
794- response. getValue(). getClearRange(). size() == 1
795- response. getValue(). getClearRange(). get(0 ). getStart() == PageBlobClient . PAGE_BYTES
796- response. getValue(). getClearRange(). get(0 ). getEnd() == PageBlobClient . PAGE_BYTES * 2 - 1
797796 validateBasicHeaders(response. getHeaders())
798- Integer . parseInt(response. getHeaders(). getValue(" x-ms-blob-content-length" )) == PageBlobClient . PAGE_BYTES * 2
797+ response. getValue(). getPageRange(). size() == expectedPageRanges. size()
798+ response. getValue(). getClearRange(). size() == expectedClearRanges. size()
799+
800+ for (def i = 0 ; i < expectedPageRanges. size(); i++ ) {
801+ def actualRange = response. getValue(). getPageRange(). get(i)
802+ def expectedRange = expectedPageRanges. get(i)
803+ expectedRange. getStart() == actualRange. getStart()
804+ expectedRange. getEnd() == actualRange. getEnd()
805+ }
806+
807+ for (def i = 0 ; i < expectedClearRanges. size(); i++ ) {
808+ def actualRange = response. getValue(). getClearRange(). get(i)
809+ def expectedRange = expectedClearRanges. get(i)
810+ expectedRange. getStart() == actualRange. getStart()
811+ expectedRange. getEnd() == actualRange. getEnd()
812+ }
813+
814+ Integer . parseInt(response. getHeaders(). getValue(" x-ms-blob-content-length" )) == 4 * Constants . MB
815+
816+ where :
817+ rangesToUpdate | rangesToClear | expectedPageRanges | expectedClearRanges
818+ createPageRanges() | createPageRanges() | createPageRanges() | createClearRanges()
819+ createPageRanges(0 , 511 ) | createPageRanges() | createPageRanges(0 , 511 ) | createClearRanges()
820+ createPageRanges() | createPageRanges(0 , 511 ) | createPageRanges() | createClearRanges(0 , 511 )
821+ createPageRanges(0 , 511 ) | createPageRanges(512 , 1023 ) | createPageRanges(0 , 511 ) | createClearRanges(512 , 1023 )
822+ createPageRanges(0 , 511 , 1024 , 1535 ) | createPageRanges(512 , 1023 , 1536 , 2047 ) | createPageRanges(0 , 511 , 1024 , 1535 ) | createClearRanges(512 , 1023 , 1536 , 2047 )
823+ }
824+
825+ static def createPageRanges (long ... offsets ) {
826+ def pageRanges = [] as List<PageRange >
827+
828+ if (CoreUtils . isNullOrEmpty(offsets)) {
829+ return pageRanges
830+ }
831+
832+ for (def i = 0 ; i < offsets. length / 2 ; i++ ) {
833+ pageRanges. add(new PageRange (). setStart(offsets[i * 2 ]). setEnd(offsets[i * 2 + 1 ]))
834+ }
835+
836+ return pageRanges
837+ }
838+
839+ static def createClearRanges (long ... offsets ) {
840+ def clearRanges = [] as List<ClearRange >
841+
842+ if (CoreUtils . isNullOrEmpty(offsets)) {
843+ return clearRanges
844+ }
845+
846+ for (def i = 0 ; i < offsets. length / 2 ; i++ ) {
847+ clearRanges. add(new ClearRange (). setStart(offsets[i * 2 ]). setEnd(offsets[i * 2 + 1 ]))
848+ }
849+
850+ return clearRanges
799851 }
800852
801853 def " Get page ranges diff min" () {
@@ -867,7 +919,7 @@ class PageBlobAPITest extends APISpec {
867919 null | null | garbageEtag | null | null | null
868920 null | null | null | receivedEtag | null | null
869921 null | null | null | null | garbageLeaseID | null
870- null | null | null | null | null | " \" notfoo\" = 'notbar'"
922+ null | null | null | null | null | " \" notfoo\" = 'notbar'"
871923 }
872924
873925 def " Get page ranges diff error" () {
@@ -1178,13 +1230,13 @@ class PageBlobAPITest extends APISpec {
11781230 bu2. copyIncrementalWithResponse(new PageBlobCopyIncrementalOptions (bc. getBlobUrl(), snapshot). setRequestConditions(mac), null , null ). getStatusCode() == 202
11791231
11801232 where :
1181- modified | unmodified | match | noneMatch | tags
1182- null | null | null | null | null
1183- oldDate | null | null | null | null
1184- null | newDate | null | null | null
1185- null | null | receivedEtag | null | null
1186- null | null | null | garbageEtag | null
1187- null | null | null | null | " \" foo\" = 'bar'"
1233+ modified | unmodified | match | noneMatch | tags
1234+ null | null | null | null | null
1235+ oldDate | null | null | null | null
1236+ null | newDate | null | null | null
1237+ null | null | receivedEtag | null | null
1238+ null | null | null | garbageEtag | null
1239+ null | null | null | null | " \" foo\" = 'bar'"
11881240 }
11891241
11901242 @Unroll
@@ -1204,18 +1256,18 @@ class PageBlobAPITest extends APISpec {
12041256 .setTagsConditions(tags)
12051257
12061258 when :
1207- bu2. copyIncrementalWithResponse(new PageBlobCopyIncrementalOptions (bc. getBlobUrl(), snapshot). setRequestConditions(mac),null , null )
1259+ bu2. copyIncrementalWithResponse(new PageBlobCopyIncrementalOptions (bc. getBlobUrl(), snapshot). setRequestConditions(mac), null , null )
12081260
12091261 then :
12101262 thrown(BlobStorageException )
12111263
12121264 where :
1213- modified | unmodified | match | noneMatch | tags
1214- newDate | null | null | null | null
1215- null | oldDate | null | null | null
1216- null | null | garbageEtag | null | null
1217- null | null | null | receivedEtag | null
1218- null | null | null | null | " \" notfoo\" = 'notbar'"
1265+ modified | unmodified | match | noneMatch | tags
1266+ newDate | null | null | null | null
1267+ null | oldDate | null | null | null
1268+ null | null | garbageEtag | null | null
1269+ null | null | null | receivedEtag | null
1270+ null | null | null | null | " \" notfoo\" = 'notbar'"
12191271 }
12201272
12211273 def " Start incremental copy error" () {
0 commit comments