-
-
Notifications
You must be signed in to change notification settings - Fork 109
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Introduce new xml parser tests for various conversion commands
- Loading branch information
1 parent
5718be9
commit 60b5bf1
Showing
1 changed file
with
247 additions
and
13 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -12,14 +12,16 @@ | |
#import <monalxmpp/HelperTools.h> | ||
#import "MLBasePaser.h" | ||
|
||
NSString* _rawXML = @"<?xml version='1.0'?>\n\ | ||
static NSMutableArray<MLXMLNode*>* _parsedStanzas; | ||
static NSString* _rawXML = @"<?xml version='1.0'?>\n\ | ||
<stream:stream xmlns:stream='http://etherx.jabber.org/streams' version='1.0' xmlns='jabber:client' xml:lang='en' from='example.org' id='a344b8bb-518e-4456-9140-d15f66c1d2db'>\n\ | ||
\ | ||
<stream:features><mechanisms xmlns='urn:ietf:params:xml:ns:xmpp-sasl'><mechanism>SCRAM-SHA-1</mechanism><mechanism>PLAIN</mechanism></mechanisms></stream:features>\n\ | ||
\ | ||
<message from='[email protected]' id='some_id' xmlns='jabber:client'>\n\ | ||
<body>Message text</body>\n\ | ||
<body xmlns='urn:some:different:namespace'>This will NOT be used</body>\n\ | ||
<some xmlns='urn:some:different:namespace' fin='true' hello='0' world='1' number='42' uuid='18382ACA-EF9D-4BC9-8779-7901C63B6631' id='18382ACA' when='2002-09-10T23:08:25Z'>aGVsbG8gd29ybGQh</some>\n\ | ||
</message>\n\ | ||
\ | ||
<iq id='18382ACA-EF9D-4BC9-8779-7901C63B6631' to='[email protected]/Monal-iOS.ef313600' xmlns='jabber:client' type='result' from='[email protected]'><query xmlns='http://jabber.org/protocol/disco#info'><feature var='http://jabber.org/protocol/muc#request'/><feature var='muc_hidden'/><feature var='muc_unsecured'/><feature var='muc_membersonly'/><feature var='muc_unmoderated'/><feature var='muc_persistent'/><identity type='text' name='testchat gruppe' category='conference'/><feature var='urn:xmpp:mam:2'/><feature var='urn:xmpp:sid:0'/><feature var='muc_nonanonymous'/><feature var='http://jabber.org/protocol/muc'/><feature var='http://jabber.org/protocol/muc#stable_id'/><feature var='http://jabber.org/protocol/muc#self-ping-optimization'/><feature var='jabber:iq:register'/><feature var='vcard-temp'/><x type='result' xmlns='jabber:x:data'><field type='hidden' var='FORM_TYPE'><value>http://jabber.org/protocol/muc#roominfo</value></field><field label='Description' var='muc#roominfo_description' type='text-single'><value/></field><field label='Number of occupants' var='muc#roominfo_occupants' type='text-single'><value>2</value></field><field label='Allow members to invite new members' var='{http://prosody.im/protocol/muc}roomconfig_allowmemberinvites' type='boolean'><value>0</value></field><field label='Allow users to invite other users' var='muc#roomconfig_allowinvites' type='boolean'><value>0</value></field><field label='Title' var='muc#roomconfig_roomname' type='text-single'><value>testchat gruppe</value></field><field type='boolean' var='muc#roomconfig_changesubject'/><field type='text-single' var='{http://modules.prosody.im/mod_vcard_muc}avatar#sha1'/><field type='text-single' var='muc#roominfo_lang'><value/></field></x></query></iq>\n\ | ||
|
@@ -65,6 +67,32 @@ @interface ParserTest : XCTestCase | |
|
||
@implementation ParserTest | ||
|
||
//parse complete xml document once and collect parsed stanzas in _parsedStanzas to be processed by our individual tests later on | ||
+(void) setUp | ||
{ | ||
//yes, but this is not insecure because these are string literals boxed into an NSArray below rather than containing unchecked user input | ||
//see here: https://releases.llvm.org/13.0.0/tools/clang/docs/DiagnosticsReference.html#wformat-security | ||
#pragma clang diagnostic push | ||
#pragma clang diagnostic ignored "-Wformat-security" | ||
_parsedStanzas = [NSMutableArray new]; | ||
MLBasePaser* delegate = [[MLBasePaser alloc] initWithCompletion:^(MLXMLNode* _Nullable parsedStanza) { | ||
if(parsedStanza != nil) | ||
{ | ||
DDLogInfo(@"Got new parsed stanza: %@", parsedStanza); | ||
[_parsedStanzas addObject:parsedStanza]; | ||
} | ||
}]; | ||
#pragma clang diagnostic pop | ||
|
||
//create xml parser, configure our delegate and feed it with data | ||
NSXMLParser* xmlParser = [[NSXMLParser alloc] initWithData:[_rawXML dataUsingEncoding:NSUTF8StringEncoding]]; | ||
[xmlParser setShouldProcessNamespaces:YES]; | ||
[xmlParser setShouldReportNamespacePrefixes:YES]; //for debugging only | ||
[xmlParser setShouldResolveExternalEntities:NO]; | ||
[xmlParser setDelegate:delegate]; | ||
[xmlParser parse]; //blocking operation | ||
} | ||
|
||
-(void) setUp | ||
{ | ||
// Put setup code here. This method is called before the invocation of each test method in the class. | ||
|
@@ -75,14 +103,221 @@ -(void) tearDown | |
// Put teardown code here. This method is called after the invocation of each test method in the class. | ||
} | ||
|
||
-(void) testParseConversionBase64 | ||
{ | ||
for(unsigned long i=0; i<_parsedStanzas.count; i++) | ||
{ | ||
//stanza 1 should match | ||
id result = [_parsedStanzas[i] findFirst:@"{urn:some:different:namespace}some#|base64"]; | ||
if(i == 1) | ||
XCTAssertEqualObjects(result, [@"hello world!" dataUsingEncoding:NSUTF8StringEncoding]); | ||
else | ||
XCTAssertNil(result, "all other stanzas should not match: %lu", i); | ||
} | ||
} | ||
|
||
-(void) testParseConversionBoolean01 | ||
{ | ||
for(unsigned long i=0; i<_parsedStanzas.count; i++) | ||
{ | ||
//stanza 1 should match | ||
id result = [_parsedStanzas[i] findFirst:@"{urn:some:different:namespace}some@fin|bool"]; | ||
if(i == 1) | ||
XCTAssertEqualObjects(result, @YES); | ||
else | ||
XCTAssertNil(result, "all other stanzas should not match: %lu", i); | ||
} | ||
} | ||
|
||
-(void) testParseConversionBoolean02 | ||
{ | ||
for(unsigned long i=0; i<_parsedStanzas.count; i++) | ||
{ | ||
//stanza 1 should match | ||
id result = [_parsedStanzas[i] findFirst:@"{urn:some:different:namespace}some@hello|bool"]; | ||
if(i == 1) | ||
XCTAssertEqualObjects(result, @NO); | ||
else | ||
XCTAssertNil(result, "all other stanzas should not match: %lu", i); | ||
} | ||
} | ||
|
||
-(void) testParseConversionBoolean03 | ||
{ | ||
for(unsigned long i=0; i<_parsedStanzas.count; i++) | ||
{ | ||
//stanza 1 should match | ||
id result = [_parsedStanzas[i] findFirst:@"{urn:some:different:namespace}some@world|bool"]; | ||
if(i == 1) | ||
XCTAssertEqualObjects(result, @YES); | ||
else | ||
XCTAssertNil(result, "all other stanzas should not match: %lu", i); | ||
} | ||
} | ||
|
||
|
||
-(void) testParseConversionInt | ||
{ | ||
for(unsigned long i=0; i<_parsedStanzas.count; i++) | ||
{ | ||
//stanza 1 should match | ||
id result = [_parsedStanzas[i] findFirst:@"{urn:some:different:namespace}some@number|int"]; | ||
if(i == 1) | ||
XCTAssertEqualObjects(result, @42); | ||
else | ||
XCTAssertNil(result, "all other stanzas should not match: %lu", i); | ||
} | ||
} | ||
|
||
-(void) testParseConversionUUID | ||
{ | ||
for(unsigned long i=0; i<_parsedStanzas.count; i++) | ||
{ | ||
//stanza 1 should match | ||
id result = [_parsedStanzas[i] findFirst:@"{urn:some:different:namespace}some@uuid|uuid"]; | ||
if(i == 1) | ||
XCTAssertEqualObjects([result UUIDString], @"18382ACA-EF9D-4BC9-8779-7901C63B6631"); | ||
else | ||
XCTAssertNil(result, "all other stanzas should not match: %lu", i); | ||
} | ||
} | ||
|
||
-(void) testParseConversionUUIDCast01 | ||
{ | ||
for(unsigned long i=0; i<_parsedStanzas.count; i++) | ||
{ | ||
//stanza 1 should match | ||
id result = [_parsedStanzas[i] findFirst:@"{urn:some:different:namespace}some@uuid|uuidcast"]; | ||
if(i == 1) | ||
XCTAssertEqualObjects([result UUIDString], @"18382ACA-EF9D-4BC9-8779-7901C63B6631"); | ||
else | ||
XCTAssertNil(result, "all other stanzas should not match: %lu", i); | ||
} | ||
} | ||
|
||
-(void) testParseConversionUUIDCast02 | ||
{ | ||
for(unsigned long i=0; i<_parsedStanzas.count; i++) | ||
{ | ||
//stanza 1 should match | ||
id result = [_parsedStanzas[i] findFirst:@"{urn:some:different:namespace}some@id|uuidcast"]; | ||
if(i == 1) | ||
XCTAssertEqualObjects([result UUIDString], @"43363852-14A2-D540-E8CE-6BEA040CD228"); | ||
else | ||
XCTAssertNil(result, "all other stanzas should not match: %lu", i); | ||
} | ||
} | ||
|
||
-(void) testParseConversionDatetime | ||
{ | ||
NSDateFormatter* formatter = [[NSDateFormatter alloc] init]; | ||
[formatter setDateFormat:@"yyyyMMddHHmmss"]; | ||
formatter.timeZone = [NSTimeZone timeZoneForSecondsFromGMT:0]; | ||
NSDate* expectedDate = [formatter dateFromString:@"20020910230825"]; | ||
|
||
for(unsigned long i=0; i<_parsedStanzas.count; i++) | ||
{ | ||
//stanza 1 should match | ||
id result = [_parsedStanzas[i] findFirst:@"{urn:some:different:namespace}some@when|datetime"]; | ||
if(i == 1) | ||
XCTAssertEqualObjects(result, expectedDate); | ||
else | ||
XCTAssertNil(result, "all other stanzas should not match: %lu", i); | ||
} | ||
} | ||
|
||
-(void) testParseNoMatch | ||
{ | ||
for(unsigned long i=0; i<_parsedStanzas.count; i++) | ||
{ | ||
//no stanza should match | ||
id result = [_parsedStanzas[i] find:@"/{jabber:client}iq/{http://jabber.org/protocol/pubsub}pubsub/items<node~eu\\.siacs\\.conversations\\.axolotl\\.bundles:[0-9]+>@node"]; | ||
XCTAssertEqualObjects(result, @[], "no stanzas should match this"); | ||
} | ||
} | ||
|
||
-(void) testParseSaslMechanisms | ||
{ | ||
for(unsigned long i=0; i<_parsedStanzas.count; i++) | ||
{ | ||
//stanza 0 should match | ||
NSSet* result = [NSSet setWithArray:[_parsedStanzas[i] find:@"{urn:ietf:params:xml:ns:xmpp-sasl}mechanisms/mechanism#"]]; | ||
if(i == 0) | ||
XCTAssertEqualObjects(result, ([NSSet setWithArray:@[@"SCRAM-SHA-1", @"PLAIN"]]), "wrong mechanisms extracted"); | ||
else | ||
XCTAssertEqualObjects(result, [NSSet new], "all other stanzas should not match: %lu", i); | ||
} | ||
} | ||
|
||
-(void) testParseMessageBody | ||
{ | ||
for(unsigned long i=0; i<_parsedStanzas.count; i++) | ||
{ | ||
//stanza 1 should match | ||
id result = [_parsedStanzas[i] findFirst:@"body#"]; | ||
if(i == 1) | ||
XCTAssertEqualObjects(result, @"Message text"); | ||
else | ||
XCTAssertNil(result, "all other stanzas should not match: %lu", i); | ||
} | ||
} | ||
|
||
-(void) testParseDataFormsSubquery | ||
{ | ||
for(unsigned long i=0; i<_parsedStanzas.count; i++) | ||
{ | ||
//stanza 2 should match | ||
id result = [_parsedStanzas[i] findFirst:@"{http://jabber.org/protocol/disco#info}query/\\{http://jabber.org/protocol/muc#roominfo}result@muc#roomconfig_roomname\\"]; | ||
if(i == 2) | ||
XCTAssertEqualObjects(result, @"testchat gruppe"); | ||
else | ||
XCTAssertNil(result, "all other stanzas should not match: %lu", i); | ||
} | ||
} | ||
|
||
-(void) testParseWithFormatParameters | ||
{ | ||
for(unsigned long i=0; i<_parsedStanzas.count; i++) | ||
{ | ||
//stanza 3 should match | ||
NSArray* result = [_parsedStanzas[i] find:@"/<type=%@>/{http://jabber.org/protocol/pubsub}pubsub/subscription<node=%@><subscription=%s><jid=%@>", @"result", @"eu.siacs.conversations.axolotl.devicelist", "subscribed", @"[email protected]"]; | ||
if(i == 3) | ||
{ | ||
XCTAssertEqual(result.count, 1, "we expect exactly one match"); | ||
XCTAssertEqualObjects([result[0] XMLString], @"<subscription node='eu.siacs.conversations.axolotl.devicelist' subid='6795F13596465' subscription='subscribed' jid='[email protected]'/>", "failed to properly extract and stringify MLXMLNode"); | ||
} | ||
else | ||
XCTAssertEqualObjects(result, @[], "all other stanzas should not match: %lu", i); | ||
} | ||
} | ||
|
||
-(void) testParseCapsHash | ||
{ | ||
//stanza 4 should match, no non-match handling here | ||
unsigned long i = 4; | ||
|
||
//gajim disco hash testcase | ||
XCTAssertTrue([_parsedStanzas[i] check:@"/<id=disco1>"], "expected iq response having id 'disco1'"); | ||
|
||
//the the original implementation is in MLIQProcessor $$class_handler(handleEntityCapsDisco) | ||
NSMutableArray* identities = [NSMutableArray new]; | ||
for(MLXMLNode* identity in [_parsedStanzas[i] find:@"{http://jabber.org/protocol/disco#info}query/identity"]) | ||
[identities addObject:[NSString stringWithFormat:@"%@/%@/%@/%@", [identity findFirst:@"/@category"], [identity findFirst:@"/@type"], ([identity check:@"/@xml:lang"] ? [identity findFirst:@"/@xml:lang"] : @""), ([identity check:@"/@name"] ? [identity findFirst:@"/@name"] : @"")]]; | ||
NSSet* features = [NSSet setWithArray:[_parsedStanzas[i] find:@"{http://jabber.org/protocol/disco#info}query/feature@var"]]; | ||
NSArray* forms = [_parsedStanzas[i] find:@"{http://jabber.org/protocol/disco#info}query/{jabber:x:data}x"]; | ||
NSString* ver = [HelperTools getEntityCapsHashForIdentities:identities andFeatures:features andForms:forms]; | ||
DDLogDebug(@"Caps hash calculated: %@", ver); | ||
XCTAssertEqualObjects(ver, @"q07IKJEyjvHSyhy//CH0CxmKi8w=", "Caps hash NOT equal to testcase hash 'q07IKJEyjvHSyhy//CH0CxmKi8w='!"); | ||
} | ||
|
||
/* | ||
-(void) testParseXML | ||
{ | ||
//yes, but this is not insecure because these are string literals boxed into an NSArray below rather than containing unchecked user input | ||
//see here: https://releases.llvm.org/13.0.0/tools/clang/docs/DiagnosticsReference.html#wformat-security | ||
#pragma clang diagnostic push | ||
#pragma clang diagnostic ignored "-Wformat-security" | ||
__block int stanzaCounter = 0; | ||
__block unsigned long stanzaCounter = 0; | ||
MLBasePaser* delegate = [[MLBasePaser alloc] initWithCompletion:^(MLXMLNode* _Nullable parsedStanza) { | ||
if(parsedStanza != nil) | ||
{ | ||
|
@@ -93,28 +328,26 @@ -(void) testParseXML | |
id result00 = [parsedStanza find:@"/{jabber:client}iq/{http://jabber.org/protocol/pubsub}pubsub/items<node~eu\\.siacs\\.conversations\\.axolotl\\.bundles:[0-9]+>@node"]; | ||
XCTAssertEqualObjects(result00, @[], "no stanzas should match this"); | ||
/* | ||
//stanza 1 | ||
NSSet* result01 = [NSSet setWithArray:[parsedStanza find:@"{urn:ietf:params:xml:ns:xmpp-sasl}mechanisms/mechanism#"]]; | ||
if(stanzaCounter == 1) | ||
XCTAssertEqualObjects(result01, [NSSet setWithArray:@[@"SCRAM-SHA-1", @"PLAIN"]], "wrong mechanisms extracted"); | ||
else | ||
XCTAssertEqualObjects(result01, [NSSet new], "all other stanzas should not match: %d", stanzaCounter); | ||
*/ | ||
// //stanza 1 | ||
// NSSet* result01 = [NSSet setWithArray:[parsedStanza find:@"{urn:ietf:params:xml:ns:xmpp-sasl}mechanisms/mechanism#"]]; | ||
// if(stanzaCounter == 1) | ||
// XCTAssertEqualObjects(result01, [NSSet setWithArray:@[@"SCRAM-SHA-1", @"PLAIN"]], "wrong mechanisms extracted"); | ||
// else | ||
// XCTAssertEqualObjects(result01, [NSSet new], "all other stanzas should not match: %lu", stanzaCounter); | ||
//stanza 2 | ||
id result02 = [parsedStanza findFirst:@"body#"]; | ||
if(stanzaCounter == 2) | ||
XCTAssertEqualObjects(result02, @"Message text"); | ||
else | ||
XCTAssertNil(result02, "all other stanzas should not match: %d", stanzaCounter); | ||
XCTAssertNil(result02, "all other stanzas should not match: %lu", stanzaCounter); | ||
//stanza 3 | ||
id result03 = [parsedStanza findFirst:@"{http://jabber.org/protocol/disco#info}query/\\{http://jabber.org/protocol/muc#roominfo}result@muc#roomconfig_roomname\\"]; | ||
if(stanzaCounter == 3) | ||
XCTAssertEqualObjects(result03, @"testchat gruppe"); | ||
else | ||
XCTAssertNil(result03, "all other stanzas should not match: %d", stanzaCounter); | ||
XCTAssertNil(result03, "all other stanzas should not match: %lu", stanzaCounter); | ||
//stanza 4 | ||
NSArray* result04 = [parsedStanza find:@"/<type=%@>/{http://jabber.org/protocol/pubsub}pubsub/subscription<node=%@><subscription=%s><jid=%@>", @"result", @"eu.siacs.conversations.axolotl.devicelist", "subscribed", @"[email protected]"]; | ||
|
@@ -124,7 +357,7 @@ -(void) testParseXML | |
XCTAssertEqualObjects([result04[0] XMLString], @"<subscription node='eu.siacs.conversations.axolotl.devicelist' subid='6795F13596465' subscription='subscribed' jid='[email protected]'/>", "failed to properly extract and stringify MLXMLNode"); | ||
} | ||
else | ||
XCTAssertEqualObjects(result04, @[], "all other stanzas should not match: %d", stanzaCounter); | ||
XCTAssertEqualObjects(result04, @[], "all other stanzas should not match: %lu", stanzaCounter); | ||
//stanza 5 (no non-match handling here) | ||
if(stanzaCounter == 5) | ||
|
@@ -154,5 +387,6 @@ -(void) testParseXML | |
[xmlParser setDelegate:delegate]; | ||
[xmlParser parse]; //blocking operation | ||
} | ||
*/ | ||
|
||
@end |