Skip to content

Commit

Permalink
Handle parsing batch replies which minimal responses.
Browse files Browse the repository at this point in the history
A DELETE in a batch has no body, but it can also have very minimal headers,
ensure a reply where the batch only has a status line and one (or no) header
works correctly.

Fixes #378
  • Loading branch information
thomasvl committed Jun 26, 2020
1 parent 0befb07 commit 9fcd689
Show file tree
Hide file tree
Showing 4 changed files with 95 additions and 34 deletions.
26 changes: 12 additions & 14 deletions Source/GTLRCore.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,6 @@
4F3E9C931C6C32B7004192DE /* Drive1BatchPaging2.response.txt in Resources */ = {isa = PBXBuildFile; fileRef = 4F3E9C8E1C6C32B7004192DE /* Drive1BatchPaging2.response.txt */; };
4F3E9C941C6C32B7004192DE /* Drive1BatchPaging3.response.txt in Resources */ = {isa = PBXBuildFile; fileRef = 4F3E9C8F1C6C32B7004192DE /* Drive1BatchPaging3.response.txt */; };
4F3E9C951C6C32B7004192DE /* Drive1BatchPaging3.response.txt in Resources */ = {isa = PBXBuildFile; fileRef = 4F3E9C8F1C6C32B7004192DE /* Drive1BatchPaging3.response.txt */; };
4F6F2E721C615492001065A5 /* Drive1BatchCorrupt.response.txt in Resources */ = {isa = PBXBuildFile; fileRef = 4F6F2E701C615492001065A5 /* Drive1BatchCorrupt.response.txt */; };
4F6F2E731C615492001065A5 /* Drive1BatchCorrupt.response.txt in Resources */ = {isa = PBXBuildFile; fileRef = 4F6F2E701C615492001065A5 /* Drive1BatchCorrupt.response.txt */; };
4F6F2E7A1C6154AA001065A5 /* Drive1Corrupt.response.txt in Resources */ = {isa = PBXBuildFile; fileRef = 4F6F2E771C6154AA001065A5 /* Drive1Corrupt.response.txt */; };
4F6F2E7B1C6154AA001065A5 /* Drive1Corrupt.response.txt in Resources */ = {isa = PBXBuildFile; fileRef = 4F6F2E771C6154AA001065A5 /* Drive1Corrupt.response.txt */; };
4F934E671512712100C4EA34 /* GTLRBase64.h in Headers */ = {isa = PBXBuildFile; fileRef = 4F934E651512712100C4EA34 /* GTLRBase64.h */; settings = {ATTRIBUTES = (Public, ); }; };
Expand Down Expand Up @@ -389,6 +387,11 @@
F4D9D52A1D833D7C000EBBED /* GTLRDuration.m in Sources */ = {isa = PBXBuildFile; fileRef = F4D9D51E1D832DB5000EBBED /* GTLRDuration.m */; };
F4D9D52B1D833D7C000EBBED /* GTLRDuration.m in Sources */ = {isa = PBXBuildFile; fileRef = F4D9D51E1D832DB5000EBBED /* GTLRDuration.m */; };
F4D9D52C1D833D7D000EBBED /* GTLRDuration.m in Sources */ = {isa = PBXBuildFile; fileRef = F4D9D51E1D832DB5000EBBED /* GTLRDuration.m */; };
F4F2CFDA24A6530900F1B3A7 /* NoPayloadsBatch.response.txt in Resources */ = {isa = PBXBuildFile; fileRef = F4F2CFD924A6530900F1B3A7 /* NoPayloadsBatch.response.txt */; };
F4F2CFDB24A6530900F1B3A7 /* NoPayloadsBatch.response.txt in Resources */ = {isa = PBXBuildFile; fileRef = F4F2CFD924A6530900F1B3A7 /* NoPayloadsBatch.response.txt */; };
F4F2CFDC24A6530900F1B3A7 /* NoPayloadsBatch.response.txt in Resources */ = {isa = PBXBuildFile; fileRef = F4F2CFD924A6530900F1B3A7 /* NoPayloadsBatch.response.txt */; };
F4F2CFDD24A6674B00F1B3A7 /* Drive1BatchCorrupt.response.txt in Resources */ = {isa = PBXBuildFile; fileRef = F4ACE7E91DAD217700053F91 /* Drive1BatchCorrupt.response.txt */; };
F4F2CFDE24A6674C00F1B3A7 /* Drive1BatchCorrupt.response.txt in Resources */ = {isa = PBXBuildFile; fileRef = F4ACE7E91DAD217700053F91 /* Drive1BatchCorrupt.response.txt */; };
/* End PBXBuildFile section */

/* Begin PBXContainerItemProxy section */
Expand Down Expand Up @@ -421,7 +424,6 @@
4F3E9C8D1C6C32B7004192DE /* Drive1BatchPaging1.response.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = Drive1BatchPaging1.response.txt; path = Tests/Data/Drive1BatchPaging1.response.txt; sourceTree = "<group>"; };
4F3E9C8E1C6C32B7004192DE /* Drive1BatchPaging2.response.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = Drive1BatchPaging2.response.txt; path = Tests/Data/Drive1BatchPaging2.response.txt; sourceTree = "<group>"; };
4F3E9C8F1C6C32B7004192DE /* Drive1BatchPaging3.response.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = Drive1BatchPaging3.response.txt; path = Tests/Data/Drive1BatchPaging3.response.txt; sourceTree = "<group>"; };
4F6F2E701C615492001065A5 /* Drive1BatchCorrupt.response.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = Drive1BatchCorrupt.response.txt; path = Tests/Data/Drive1BatchCorrupt.response.txt; sourceTree = "<group>"; };
4F6F2E771C6154AA001065A5 /* Drive1Corrupt.response.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = Drive1Corrupt.response.txt; path = Tests/Data/Drive1Corrupt.response.txt; sourceTree = "<group>"; };
4F934E651512712100C4EA34 /* GTLRBase64.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = GTLRBase64.h; path = Utilities/GTLRBase64.h; sourceTree = "<group>"; };
4F934E661512712100C4EA34 /* GTLRBase64.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = GTLRBase64.m; path = Utilities/GTLRBase64.m; sourceTree = "<group>"; };
Expand Down Expand Up @@ -514,6 +516,7 @@
F4D9D51D1D832DB5000EBBED /* GTLRDuration.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = GTLRDuration.h; path = Objects/GTLRDuration.h; sourceTree = "<group>"; };
F4D9D51E1D832DB5000EBBED /* GTLRDuration.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = GTLRDuration.m; path = Objects/GTLRDuration.m; sourceTree = "<group>"; };
F4D9D5251D833D5D000EBBED /* GTLRDurationTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = GTLRDurationTest.m; path = Tests/GTLRDurationTest.m; sourceTree = "<group>"; };
F4F2CFD924A6530900F1B3A7 /* NoPayloadsBatch.response.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = NoPayloadsBatch.response.txt; path = Tests/Data/NoPayloadsBatch.response.txt; sourceTree = "<group>"; };
/* End PBXFileReference section */

/* Begin PBXFrameworksBuildPhase section */
Expand Down Expand Up @@ -615,7 +618,6 @@
089C1671FE841209C02AAC07 /* Frameworks and Libraries */,
19C28FB8FE9D52D311CA2CBB /* Products */,
F4A872741DAD1ED800D69E09 /* Frameworks */,
34AF73421FB4E3C80022335F /* Recovered References */,
);
name = GoogleBundle;
sourceTree = "<group>";
Expand Down Expand Up @@ -678,14 +680,6 @@
name = "GTLR Source";
sourceTree = "<group>";
};
34AF73421FB4E3C80022335F /* Recovered References */ = {
isa = PBXGroup;
children = (
4F6F2E701C615492001065A5 /* Drive1BatchCorrupt.response.txt */,
);
name = "Recovered References";
sourceTree = "<group>";
};
4F346DD20D7500C9006033E0 /* Common */ = {
isa = PBXGroup;
children = (
Expand Down Expand Up @@ -818,6 +812,7 @@
4FA824881C6BDAC700E11CCC /* Drive1Paging3.response.txt */,
4F3AA9161C600013008497BC /* Drive1ParamError.response.txt */,
F4A07B1B1E4293990035678A /* Drive1ParamErrorAsList.response.txt */,
F4F2CFD924A6530900F1B3A7 /* NoPayloadsBatch.response.txt */,
F4469DFE1C45757E00BCFAA1 /* URITemplateExtraTests.json */,
F4469DFF1C45757E00BCFAA1 /* URITemplateRFCTests.json */,
);
Expand Down Expand Up @@ -1188,6 +1183,7 @@
F4469E051C45758700BCFAA1 /* URITemplateRFCTests.json in Resources */,
F4469E041C45758700BCFAA1 /* URITemplateExtraTests.json in Resources */,
4F3AA91A1C600013008497BC /* Drive1ParamError.response.txt in Resources */,
F4F2CFDA24A6530900F1B3A7 /* NoPayloadsBatch.response.txt in Resources */,
4F3E9C931C6C32B7004192DE /* Drive1BatchPaging2.response.txt in Resources */,
4F3E9C811C6C12A1004192DE /* Classroom1NotFoundError.response.txt in Resources */,
4F3E9C911C6C32B7004192DE /* Drive1BatchPaging1.response.txt in Resources */,
Expand All @@ -1196,10 +1192,10 @@
4FA8248E1C6BDAC700E11CCC /* Drive1Paging3.response.txt in Resources */,
F4A07B1F1E4293A10035678A /* Drive1ParamErrorAsList.response.txt in Resources */,
4F3AA9181C600013008497BC /* Drive1AuthError.response.txt in Resources */,
4F6F2E731C615492001065A5 /* Drive1BatchCorrupt.response.txt in Resources */,
4FA8248A1C6BDAC700E11CCC /* Drive1Paging1.response.txt in Resources */,
4F6F2E7B1C6154AA001065A5 /* Drive1Corrupt.response.txt in Resources */,
4F2591411C5C3338009E0240 /* Drive1.response.txt in Resources */,
F4F2CFDE24A6674C00F1B3A7 /* Drive1BatchCorrupt.response.txt in Resources */,
4FA8248C1C6BDAC700E11CCC /* Drive1Paging2.response.txt in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
Expand All @@ -1219,6 +1215,7 @@
F4469E031C45758600BCFAA1 /* URITemplateRFCTests.json in Resources */,
4F3AA9191C600013008497BC /* Drive1ParamError.response.txt in Resources */,
F4469E021C45758600BCFAA1 /* URITemplateExtraTests.json in Resources */,
F4F2CFDB24A6530900F1B3A7 /* NoPayloadsBatch.response.txt in Resources */,
4F3E9C921C6C32B7004192DE /* Drive1BatchPaging2.response.txt in Resources */,
4F3E9C801C6C12A1004192DE /* Classroom1NotFoundError.response.txt in Resources */,
4F3E9C901C6C32B7004192DE /* Drive1BatchPaging1.response.txt in Resources */,
Expand All @@ -1227,10 +1224,10 @@
4FA8248D1C6BDAC700E11CCC /* Drive1Paging3.response.txt in Resources */,
F4A07B201E4293A20035678A /* Drive1ParamErrorAsList.response.txt in Resources */,
4F3AA9171C600013008497BC /* Drive1AuthError.response.txt in Resources */,
4F6F2E721C615492001065A5 /* Drive1BatchCorrupt.response.txt in Resources */,
4FA824891C6BDAC700E11CCC /* Drive1Paging1.response.txt in Resources */,
4F6F2E7A1C6154AA001065A5 /* Drive1Corrupt.response.txt in Resources */,
4F2591401C5C3338009E0240 /* Drive1.response.txt in Resources */,
F4F2CFDD24A6674B00F1B3A7 /* Drive1BatchCorrupt.response.txt in Resources */,
4FA8248B1C6BDAC700E11CCC /* Drive1Paging2.response.txt in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
Expand All @@ -1256,6 +1253,7 @@
F4ACE7DA1DAD20E100053F91 /* Classroom1NotFoundError.response.txt in Resources */,
F4ACE7DF1DAD20E100053F91 /* Drive1BatchPaging3.response.txt in Resources */,
F4ACE7E61DAD20E100053F91 /* Drive1Paging3.response.txt in Resources */,
F4F2CFDC24A6530900F1B3A7 /* NoPayloadsBatch.response.txt in Resources */,
F4ACE7E41DAD20E100053F91 /* Drive1Paging1.response.txt in Resources */,
F4ACE7E31DAD20E100053F91 /* Drive1Corrupt.response.txt in Resources */,
F4ACE7E51DAD20E100053F91 /* Drive1Paging2.response.txt in Resources */,
Expand Down
50 changes: 31 additions & 19 deletions Source/Objects/GTLRService.m
Original file line number Diff line number Diff line change
Expand Up @@ -1566,32 +1566,43 @@ - (GTLRBatchResponsePart *)responsePartWithMIMEPart:(GTMMIMEDocumentPart *)mimeP
targetBytes:"\r\n"
targetLength:2
foundOffsets:&offsets];
if (offsets.count < 2) {
// Lack of status line and inner headers is strange, but not fatal since
// if the JSON was delivered.
GTLR_DEBUG_LOG(@"GTLRService: Batch result cannot parse headers for request %@:\n%@",
responseContentID,
[[NSString alloc] initWithData:innerHeaderData
encoding:NSUTF8StringEncoding]);
} else {
NSString *statusString;
NSInteger statusCode;
[self getResponseLineFromData:innerHeaderData
statusCode:&statusCode
statusString:&statusString];
responsePart.statusCode = statusCode;
responsePart.statusString = statusString;
NSData *statusLine;
NSData *actualInnerHeaderData;
if (offsets.count) {
NSRange statusRange = NSMakeRange(0, offsets[0].unsignedIntegerValue);
statusLine = [innerHeaderData subdataWithRange:statusRange];

NSUInteger actualInnerHeaderOffset = offsets[0].unsignedIntegerValue + 2;
NSData *actualInnerHeaderData;
if (innerHeaderData.length - actualInnerHeaderOffset > 0) {
NSRange actualInnerHeaderRange =
NSMakeRange(actualInnerHeaderOffset,
innerHeaderData.length - actualInnerHeaderOffset);
actualInnerHeaderData = [innerHeaderData subdataWithRange:actualInnerHeaderRange];
}
responsePart.headers = [GTMMIMEDocument headersWithData:actualInnerHeaderData];
} else {
// There appears to only be a status line.
//
// This means there were no reponse headers. "Date" seems like it should
// be required, but https://tools.ietf.org/html/rfc7231#section-7.1.1.2
// lets even that be left off if a server doesn't have a clock it knows
// to be correct.
statusLine = innerHeaderData;
}

NSString *httpVersion;
NSString *statusString;
NSInteger statusCode;
[self getResponseLineFromData:statusLine
httpVersion:&httpVersion
statusCode:&statusCode
statusString:&statusString];
if (![httpVersion hasPrefix:@"HTTP/"]) {
GTLR_DEBUG_LOG(@"GTLRService: Batch result didn't have a standard HTTP Version: %@",
httpVersion);
}
responsePart.statusCode = statusCode;
responsePart.statusString = statusString;
responsePart.headers = [GTMMIMEDocument headersWithData:actualInnerHeaderData];

// Create JSON from the body.
// (if there is any, methods like delete return nothing)
Expand Down Expand Up @@ -1624,11 +1635,13 @@ - (GTLRBatchResponsePart *)responsePartWithMIMEPart:(GTMMIMEDocumentPart *)mimeP
}

- (void)getResponseLineFromData:(NSData *)data
httpVersion:(NSString **)outHTTPVersion
statusCode:(NSInteger *)outStatusCode
statusString:(NSString **)outStatusString {
// Sample response line:
// HTTP/1.1 200 OK

*outHTTPVersion = @"???";
*outStatusCode = -1;
*outStatusString = @"???";
NSString *responseLine = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
Expand All @@ -1639,8 +1652,7 @@ - (void)getResponseLineFromData:(NSData *)data
// scan.
NSCharacterSet *wsSet = [NSCharacterSet whitespaceAndNewlineCharacterSet];
NSCharacterSet *newlineSet = [NSCharacterSet newlineCharacterSet];
NSString *httpVersion;
if ([scanner scanUpToCharactersFromSet:wsSet intoString:&httpVersion]
if ([scanner scanUpToCharactersFromSet:wsSet intoString:outHTTPVersion]
&& [scanner scanInteger:outStatusCode]
&& [scanner scanUpToCharactersFromSet:newlineSet intoString:outStatusString]) {
// Got it all.
Expand Down
16 changes: 16 additions & 0 deletions Source/Tests/Data/NoPayloadsBatch.response.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
--batch_hXL_3_UnLsQ_AAYW6kQ4LYU
Content-Type: application/http
Content-ID: response-gtlr_39

HTTP/1.1 204 No Content
Date: Wed, 24 Jun 2020 09:21:24 GMT


--batch_hXL_3_UnLsQ_AAYW6kQ4LYU
Content-Type: application/http
Content-ID: response-gtlr_40

HTTP/1.1 204 No Content


--batch_hXL_3_UnLsQ_AAYW6kQ4LYU
37 changes: 36 additions & 1 deletion Source/Tests/GTLRServiceTest.m
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,10 @@ @implementation GTLRTestingSvc_FileList_Surrogate2
// Internal methods redeclared for testing.

@interface GTLRBatchResponsePart : NSObject
@property(nonatomic, assign) NSInteger statusCode;
@property(nonatomic, copy) NSString *statusString;
@property(nonatomic, strong) NSDictionary *headers;
@property(nonatomic, strong) NSError *parseError;
@end

@interface GTLRService (InternalMethods)
Expand Down Expand Up @@ -147,7 +150,8 @@ + (NSData *)dataForTestFileName:(NSString *)fileName {
" \"Drive1Empty.response.txt\": \"ewp9Cg==\","\
" \"Drive1Batch.response.txt\": \"LS1iYXRjaF8zYWpONDBZcFhaUV9BQmY1d3dfZ3h5Zw0KQ29udGVudC1UeXBlOiBhcHBsaWNhdGlvbi9odHRwDQpDb250ZW50LUlEOiByZXNwb25zZS1ndGxyXzQNCg0KSFRUUC8xLjEgNDA0IE5vdCBGb3VuZA0KQ29udGVudC1UeXBlOiBhcHBsaWNhdGlvbi9qc29uOyBjaGFyc2V0PVVURi04DQpEYXRlOiBNb24sIDAxIEZlYiAyMDE2IDIyOjUwOjU3IEdNVA0KRXhwaXJlczogTW9uLCAwMSBGZWIgMjAxNiAyMjo1MDo1NyBHTVQNCkNhY2hlLUNvbnRyb2w6IHByaXZhdGUsIG1heC1hZ2U9MA0KQ29udGVudC1MZW5ndGg6IDE3MDgyDQpYLVJlamVjdGVkLVJlYXNvbjogRmFpbGVkIHRvIHJlbW92ZSBFeGNhbGlidXIgZnJvbSBzdG9uZQ0KDQp7DQogImVycm9yIjogew0KICAiZXJyb3JzIjogWw0KICAgew0KICAgICJkb21haW4iOiAiZ2xvYmFsIiwNCiAgICAicmVhc29uIjogIm5vdEZvdW5kIiwNCiAgICAibWVzc2FnZSI6ICJGaWxlIG5vdCBmb3VuZDogYmFkSUQuIiwNCiAgICAibG9jYXRpb25UeXBlIjogInBhcmFtZXRlciIsDQogICAgImxvY2F0aW9uIjogImZpbGVJZCIsDQogICAgImRlYnVnSW5mbyI6ICJjb2RlOiBOT1RfRk9VTkQiDQogICB9DQogIF0sDQogICJjb2RlIjogNDA0LA0KICAibWVzc2FnZSI6ICJGaWxlIG5vdCBmb3VuZDogYmFkSUQuIg0KIH0NCn0NCg0KLS1iYXRjaF8zYWpONDBZcFhaUV9BQmY1d3dfZ3h5Zw0KQ29udGVudC1UeXBlOiBhcHBsaWNhdGlvbi9odHRwDQpDb250ZW50LUlEOiByZXNwb25zZS1ndGxyXzUNCg0KSFRUUC8xLjEgMjAwIE9LDQpDb250ZW50LVR5cGU6IGFwcGxpY2F0aW9uL2pzb247IGNoYXJzZXQ9VVRGLTgNCkRhdGU6IE1vbiwgMDEgRmViIDIwMTYgMjI6NTA6NTcgR01UDQpFeHBpcmVzOiBNb24sIDAxIEZlYiAyMDE2IDIyOjUwOjU3IEdNVA0KQ2FjaGUtQ29udHJvbDogcHJpdmF0ZSwgbWF4LWFnZT0wDQpDb250ZW50LUxlbmd0aDogNDQNClJldHJ5LUFmdGVyOiAzMDANCg0Kew0KICJraW5kIjogImRyaXZlI2ZpbGVMaXN0IiwNCiAiZmlsZXMiOiBbXQ0KfQ0KDQotLWJhdGNoXzNhak40MFlwWFpRX0FCZjV3d19neHlnDQpDb250ZW50LVR5cGU6IGFwcGxpY2F0aW9uL2h0dHANCkNvbnRlbnQtSUQ6IHJlc3BvbnNlLWd0bHJfNg0KDQpIVFRQLzEuMSAyMDAgT0sNCkNvbnRlbnQtVHlwZTogYXBwbGljYXRpb24vanNvbjsgY2hhcnNldD1VVEYtOA0KRGF0ZTogTW9uLCAwMSBGZWIgMjAxNiAyMjo1MDo1NyBHTVQNCkV4cGlyZXM6IE1vbiwgMDEgRmViIDIwMTYgMjI6NTA6NTcgR01UDQpDYWNoZS1Db250cm9sOiBwcml2YXRlLCBtYXgtYWdlPTANCkNvbnRlbnQtTGVuZ3RoOiA0NQ0KDQp7DQogInBhcmVudHMiOiBbDQogICIwQUxzdlpERHd0S3JoVWs5UFZBIg0KIF0NCn0NCg0KLS1iYXRjaF8zYWpONDBZcFhaUV9BQmY1d3dfZ3h5Zy0tDQo=\","\
" \"Drive1Corrupt.response.txt\": \"eyBhYmMgOjo9PSB9Cg==\","\
" \"Drive1Paging3.response.txt\": \"ewogICJraW5kIiA6ICJkcml2ZSNmaWxlTGlzdCIsCiAgImZpbGVzIiA6IFsKICAgIHsKICAgICAgIm1pbWVUeXBlIiA6ICJhcHBsaWNhdGlvblwvdm5kLmdvb2dsZS1hcHBzLnNwcmVhZHNoZWV0IiwKICAgICAgImlkIiA6ICIxZEtjQWJic3Y2UHJMYWdvTDJEX3I2IiwKICAgICAgImtpbmQiIDogImRyaXZlI2ZpbGUiLAogICAgICAibmFtZSIgOiAiMjAwNiB0YXggZGVkdWN0aW9ucyIsCiAgICAgICJ0cmFzaGVkIiA6IGZhbHNlCiAgICB9LAogICAgewogICAgICAibWltZVR5cGUiIDogImFwcGxpY2F0aW9uXC92bmQuZ29vZ2xlLWFwcHMuZG9jdW1lbnQiLAogICAgICAiaWQiIDogIjFNMFhZakdoRWJZMUJ6SHM1c3JPcFEiLAogICAgICAia2luZCIgOiAiZHJpdmUjZmlsZSIsCiAgICAgICJuYW1lIiA6ICJBbm90aGVyIGRvYyIsCiAgICAgICJ0cmFzaGVkIiA6IGZhbHNlCiAgICB9CiAgXQp9Cg==\""\
" \"Drive1Paging3.response.txt\": \"ewogICJraW5kIiA6ICJkcml2ZSNmaWxlTGlzdCIsCiAgImZpbGVzIiA6IFsKICAgIHsKICAgICAgIm1pbWVUeXBlIiA6ICJhcHBsaWNhdGlvblwvdm5kLmdvb2dsZS1hcHBzLnNwcmVhZHNoZWV0IiwKICAgICAgImlkIiA6ICIxZEtjQWJic3Y2UHJMYWdvTDJEX3I2IiwKICAgICAgImtpbmQiIDogImRyaXZlI2ZpbGUiLAogICAgICAibmFtZSIgOiAiMjAwNiB0YXggZGVkdWN0aW9ucyIsCiAgICAgICJ0cmFzaGVkIiA6IGZhbHNlCiAgICB9LAogICAgewogICAgICAibWltZVR5cGUiIDogImFwcGxpY2F0aW9uXC92bmQuZ29vZ2xlLWFwcHMuZG9jdW1lbnQiLAogICAgICAiaWQiIDogIjFNMFhZakdoRWJZMUJ6SHM1c3JPcFEiLAogICAgICAia2luZCIgOiAiZHJpdmUjZmlsZSIsCiAgICAgICJuYW1lIiA6ICJBbm90aGVyIGRvYyIsCiAgICAgICJ0cmFzaGVkIiA6IGZhbHNlCiAgICB9CiAgXQp9Cg==\","\
" \"NoPayloadsBatch.response.txt\": \"LS1iYXRjaF9oWExfM19VbkxzUV9BQVlXNmtRNExZVQ0KQ29udGVudC1UeXBlOiBhcHBsaWNhdGlvbi9odHRwDQpDb250ZW50LUlEOiByZXNwb25zZS1ndGxyXzM5DQoNCkhUVFAvMS4xIDIwNCBObyBDb250ZW50DQpEYXRlOiBXZWQsIDI0IEp1biAyMDIwIDA5OjIxOjI0IEdNVA0KDQoNCi0tYmF0Y2hfaFhMXzNfVW5Mc1FfQUFZVzZrUTRMWVUNCkNvbnRlbnQtVHlwZTogYXBwbGljYXRpb24vaHR0cA0KQ29udGVudC1JRDogcmVzcG9uc2UtZ3Rscl80MA0KDQpIVFRQLzEuMSAyMDQgTm8gQ29udGVudA0KDQoNCi0tYmF0Y2hfaFhMXzNfVW5Mc1FfQUFZVzZrUTRMWVUNCg==\""\
"}";

static dispatch_once_t onceToken;
Expand Down Expand Up @@ -1712,6 +1716,37 @@ - (void)performBatchQueryTestSkippingAuthorization:(BOOL)shouldSkipAuthorization
expectedExpirations:0];
}

- (void)testParsingMinimalBatchReplies {
// Deletes in a batch have no payload, ensure parsing works as expected.

NSData *responseData =
[[self class] dataForTestFileName:@"NoPayloadsBatch.response.txt"];;
XCTAssertNotNil(responseData);

GTLRService *service = [self driveServiceForTest];

NSArray *mimeParts =
[GTMMIMEDocument MIMEPartsWithBoundary:@"batch_hXL_3_UnLsQ_AAYW6kQ4LYU"
data:responseData];
XCTAssertNotNil(mimeParts);
XCTAssertEqual(mimeParts.count, 2U);

GTLRBatchResponsePart *part0 = [service responsePartWithMIMEPart:mimeParts[0]];
XCTAssertNotNil(part0);
XCTAssertEqual(part0.statusCode, 204);
XCTAssertEqualObjects(part0.statusString, @"No Content");
XCTAssertEqual(part0.headers.count, 1U);
XCTAssertEqualObjects(part0.headers[@"Date"], @"Wed, 24 Jun 2020 09:21:24 GMT");
XCTAssertNil(part0.parseError);

GTLRBatchResponsePart *part1 = [service responsePartWithMIMEPart:mimeParts[1]];
XCTAssertNotNil(part1);
XCTAssertEqual(part1.statusCode, 204);
XCTAssertEqualObjects(part1.statusString, @"No Content");
XCTAssertEqual(part1.headers.count, 0U);
XCTAssertNil(part1.parseError);
}

- (GTMSessionFetcherTestBlock)fetcherTestBlockForBatchPaging {
__block int pageCounter = 0;

Expand Down

0 comments on commit 9fcd689

Please sign in to comment.