From fefe9af5b2ef2821d42476921b63b1e8aa925104 Mon Sep 17 00:00:00 2001 From: Thilo Molitor Date: Mon, 10 Feb 2025 03:27:30 +0100 Subject: [PATCH] DRAFT: Implement MLHandler and SDP parser tests --- Monal/Classes/MonalAppDelegate.m | 28 +- Monal/Monal.xcodeproj/project.pbxproj | 16 +- Monal/MonalXMPPUnitTests/HandlerTest.m | 155 +++++++++ Monal/MonalXMPPUnitTests/ParserTest.m | 9 + Monal/MonalXMPPUnitTests/SDPTest.m | 450 +++++++++++++++++++++++++ 5 files changed, 633 insertions(+), 25 deletions(-) create mode 100644 Monal/MonalXMPPUnitTests/HandlerTest.m create mode 100644 Monal/MonalXMPPUnitTests/ParserTest.m create mode 100644 Monal/MonalXMPPUnitTests/SDPTest.m diff --git a/Monal/Classes/MonalAppDelegate.m b/Monal/Classes/MonalAppDelegate.m index af1b2737f4..c4a3ef9d89 100644 --- a/Monal/Classes/MonalAppDelegate.m +++ b/Monal/Classes/MonalAppDelegate.m @@ -166,7 +166,7 @@ -(void) runParserTests -(void) runSDPTests { - DDLogVerbose(@"SDP2XML: %@", [HelperTools sdp2xml:@"v=0\n\ + NSArray* xmlNodes = [HelperTools sdp2xml:@"v=0\n\ o=- 2005859539484728435 2 IN IP4 127.0.0.1\n\ s=-\n\ t=0 0\n\ @@ -288,29 +288,10 @@ -(void) runSDPTests a=setup:actpass\n\ a=mid:2\n\ a=sctp-port:5000\n\ -a=max-message-size:262144\n" withInitiator:YES]); -} - -$$class_handler(handlerTest01, $$ID(NSObject*, dummyObj)) - DDLogError(@"HandlerTest01 completed"); -$$ +a=max-message-size:262144\n" withInitiator:YES]; -$$class_handler(handlerTest02, $$ID(monal_void_block_t, dummyCallback)) - DDLogError(@"HandlerTest02 completed"); -$$ - --(void) runHandlerTests -{ - DDLogError(@"NSClassFromString: '%@'", NSClassFromString(@"monal_void_block_t")); - - if([^{} isKindOfClass:[NSObject class]]) - DDLogError(@"isKindOfClass"); - - MLHandler* handler01 = $newHandler([self class], handlerTest01); - $call(handler01, $ID(dummyObj, [NSString new])); - - MLHandler* handler02 = $newHandler([self class], handlerTest02); - $call(handler02, $ID(dummyCallback, ^{})); + DDLogVerbose(@"SDP2XML: %@", xmlNodes); + DDLogDebug(@"XML2SDP: %@", [HelperTools xml2sdp:xmlNodes[2] withInitiator:YES]); } -(id) init @@ -334,6 +315,7 @@ -(id) init //[self runSDPTests]; //[HelperTools flushLogsWithTimeout:0.250]; //[self runHandlerTests]; + //exit(0); return self; } diff --git a/Monal/Monal.xcodeproj/project.pbxproj b/Monal/Monal.xcodeproj/project.pbxproj index 57e43f98ff..2bfc9ac090 100644 --- a/Monal/Monal.xcodeproj/project.pbxproj +++ b/Monal/Monal.xcodeproj/project.pbxproj @@ -77,8 +77,6 @@ 26E8462824EABAED00ECE419 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 26E8462A24EABAED00ECE419 /* Main.storyboard */; }; 26F9794D1ACAC73A0008E005 /* MLContactCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = 26F9794C1ACAC73A0008E005 /* MLContactCell.xib */; }; 26FE3BCB1C61A6C3003CC230 /* MLResizingTextView.m in Sources */ = {isa = PBXBuildFile; fileRef = 26FE3BCA1C61A6C3003CC230 /* MLResizingTextView.m */; }; - 341F44662CAF427500AA6C7D /* MLPromise.h in Headers */ = {isa = PBXBuildFile; fileRef = 341F44642CAF427500AA6C7D /* MLPromise.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 341F44672CAF427500AA6C7D /* MLPromise.m in Sources */ = {isa = PBXBuildFile; fileRef = 341F44652CAF427500AA6C7D /* MLPromise.m */; }; 340F0CA02D2425A4006224D0 /* MLMessage.h in Headers */ = {isa = PBXBuildFile; fileRef = 26611024238F17B20030A4EE /* MLMessage.h */; settings = {ATTRIBUTES = (Public, ); }; }; 340F0CA12D2425AA006224D0 /* MLXMPPConnection.h in Headers */ = {isa = PBXBuildFile; fileRef = 26611015238F08AC0030A4EE /* MLXMPPConnection.h */; settings = {ATTRIBUTES = (Public, ); }; }; 340F0CA22D2425C4006224D0 /* XMPPPresence.h in Headers */ = {isa = PBXBuildFile; fileRef = 264E34591787BAB100BC7BD0 /* XMPPPresence.h */; settings = {ATTRIBUTES = (Public, ); }; }; @@ -86,6 +84,8 @@ 340F0CA42D2425D9006224D0 /* MLXMPPIdentity.h in Headers */ = {isa = PBXBuildFile; fileRef = 26611010238F08980030A4EE /* MLXMPPIdentity.h */; settings = {ATTRIBUTES = (Public, ); }; }; 340F0CA52D2425E1006224D0 /* MLLogFileManager.h in Headers */ = {isa = PBXBuildFile; fileRef = C15D504824C727CC002F75BB /* MLLogFileManager.h */; settings = {ATTRIBUTES = (Public, ); }; }; 340F0CA62D24267B006224D0 /* MLXMLNode.h in Headers */ = {isa = PBXBuildFile; fileRef = 260C51D2177F44AD0039634B /* MLXMLNode.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 341F44662CAF427500AA6C7D /* MLPromise.h in Headers */ = {isa = PBXBuildFile; fileRef = 341F44642CAF427500AA6C7D /* MLPromise.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 341F44672CAF427500AA6C7D /* MLPromise.m in Sources */ = {isa = PBXBuildFile; fileRef = 341F44652CAF427500AA6C7D /* MLPromise.m */; }; 3424B4E72D232BE2009F6503 /* MLContact.h in Headers */ = {isa = PBXBuildFile; fileRef = 26611029238F17CA0030A4EE /* MLContact.h */; settings = {ATTRIBUTES = (Public, ); }; }; 3424B4E82D232BE7009F6503 /* DataLayer.h in Headers */ = {isa = PBXBuildFile; fileRef = 2601D9A80FBF255D004DB939 /* DataLayer.h */; settings = {ATTRIBUTES = (Public, ); }; }; 3424B4E92D232BEB009F6503 /* xmpp.h in Headers */ = {isa = PBXBuildFile; fileRef = 260C51CF177F08F50039634B /* xmpp.h */; settings = {ATTRIBUTES = (Public, ); }; }; @@ -188,6 +188,9 @@ 84C1CD502A8C764D007076ED /* SwiftHelpers.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84C1CD4F2A8C764D007076ED /* SwiftHelpers.swift */; }; 84C1CD522A8F617F007076ED /* MLStreamRedirect.m in Sources */ = {isa = PBXBuildFile; fileRef = 84C1CD512A8F617F007076ED /* MLStreamRedirect.m */; }; 84C1CD542A8F6196007076ED /* MLStreamRedirect.h in Headers */ = {isa = PBXBuildFile; fileRef = 84C1CD532A8F6196007076ED /* MLStreamRedirect.h */; }; + 84C6F6032D597FB20015575E /* ParserTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 84C6F6022D597FB20015575E /* ParserTest.m */; }; + 84C6F6052D597FD10015575E /* SDPTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 84C6F6042D597FD10015575E /* SDPTest.m */; }; + 84C6F6072D597FF40015575E /* HandlerTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 84C6F6062D597FF40015575E /* HandlerTest.m */; }; 84D31CE628653B83006D7926 /* WebRTCClient.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84D31CE528653B83006D7926 /* WebRTCClient.swift */; }; 84E231F32C16A9CE00735FB7 /* SVGView in Frameworks */ = {isa = PBXBuildFile; productRef = 84E231F22C16A9CE00735FB7 /* SVGView */; }; 84E55E7D2964424E003E191A /* ActiveChatsViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 261A6284176C156500059090 /* ActiveChatsViewController.m */; }; @@ -626,6 +629,9 @@ 84C1CD4F2A8C764D007076ED /* SwiftHelpers.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SwiftHelpers.swift; sourceTree = ""; }; 84C1CD512A8F617F007076ED /* MLStreamRedirect.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = MLStreamRedirect.m; sourceTree = ""; }; 84C1CD532A8F6196007076ED /* MLStreamRedirect.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MLStreamRedirect.h; sourceTree = ""; }; + 84C6F6022D597FB20015575E /* ParserTest.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ParserTest.m; sourceTree = ""; }; + 84C6F6042D597FD10015575E /* SDPTest.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SDPTest.m; sourceTree = ""; }; + 84C6F6062D597FF40015575E /* HandlerTest.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = HandlerTest.m; sourceTree = ""; }; 84D31CE528653B83006D7926 /* WebRTCClient.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = WebRTCClient.swift; path = Classes/WebRTCClient.swift; sourceTree = SOURCE_ROOT; }; 84F194C32C0FE70900F0A994 /* es-AR */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "es-AR"; path = "external/es-AR.lproj/Main.strings"; sourceTree = ""; }; 84F194C42C0FE74500F0A994 /* es-AR */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "es-AR"; path = "external/es-AR.lproj/Settings.strings"; sourceTree = ""; }; @@ -1461,6 +1467,9 @@ C1049188261301530054AC9E /* MonalXMPPUnitTests.swift */, C104918A261301530054AC9E /* Info.plist */, C1B940E826144AF400E9D290 /* MonalXMPPUnitTests-Bridging-Header.h */, + 84C6F6022D597FB20015575E /* ParserTest.m */, + 84C6F6042D597FD10015575E /* SDPTest.m */, + 84C6F6062D597FF40015575E /* HandlerTest.m */, ); path = MonalXMPPUnitTests; sourceTree = ""; @@ -2272,8 +2281,11 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( + 84C6F6072D597FF40015575E /* HandlerTest.m in Sources */, + 84C6F6032D597FB20015575E /* ParserTest.m in Sources */, C1049189261301530054AC9E /* MonalXMPPUnitTests.swift in Sources */, C1B940EA26144AF500E9D290 /* AESGCMTest.m in Sources */, + 84C6F6052D597FD10015575E /* SDPTest.m in Sources */, C1049199261301710054AC9E /* MLCryptoTest.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; diff --git a/Monal/MonalXMPPUnitTests/HandlerTest.m b/Monal/MonalXMPPUnitTests/HandlerTest.m new file mode 100644 index 0000000000..3102780b06 --- /dev/null +++ b/Monal/MonalXMPPUnitTests/HandlerTest.m @@ -0,0 +1,155 @@ +// +// HandlerTest.m +// MonalXMPPUnitTests +// +// Created by admin on 10.02.25. +// Copyright © 2025 monal-im.org. All rights reserved. +// + +#import +#import +#import +#import + +@interface HandlerTest : XCTestCase +//TODO: why is that needed for instance handlers at all? other parts of our code also don't need these declarations. +//TODO: and weird thing: class handlers don't seem to throw a compiler error in here, too. +-(void) MLInstanceHandler_handlerTestInstanceHandler_withArguments:(NSDictionary*) _callerArgs andBoundArguments:(NSDictionary*) _boundArgs; +@end + +@implementation HandlerTest + +-(void) setUp +{ + // Put setup code here. This method is called before the invocation of each test method in the class. +} + +-(void) tearDown +{ + // Put teardown code here. This method is called after the invocation of each test method in the class. +} + +-(void) testMonalVoidBlock +{ + id voidblock = NSClassFromString(@"monal_void_block_t"); + XCTAssert([^{} isKindOfClass:voidblock], "void block should be kind of monal_void_block_t"); +} + +-(void) testVoidBlockIsNSObject +{ + XCTAssert([^{} isKindOfClass:[NSObject class]], "void block should be kind of NSObject"); +} + +$$class_handler(handlerTestStringObject, $$ID(NSObject*, dummyObj)) + XCTAssertEqualObjects(dummyObj, @"dummy string", "handler01 should have gotten 'dummy string'"); +$$ + +-(void) testHandlerStringObject +{ + MLHandler* handler = $newHandler([self class], handlerTestStringObject); + $call(handler, $ID(dummyObj, @"dummy string")); +} + +$$class_handler(handlerTestBlockArgument, $$ID(monal_void_block_t, dummyCallback)) + dummyCallback(); +$$ + +-(void) testHandlerBlockArgument +{ + XCTestExpectation* expectation = [self expectationWithDescription:@"handlerTestBlockArgument should call callback block"]; + expectation.expectedFulfillmentCount = 1; + expectation.assertForOverFulfill = YES; + + MLHandler* handler = $newHandler([self class], handlerTestBlockArgument); + $call(handler, $ID(dummyCallback, (^{ + [expectation fulfill]; + }))); + + [self waitForExpectations:@[expectation] timeout:1.0]; +} + +$$instance_handler(handlerTestInstanceHandler, testcase, $$ID(XCTestCase*, testcase), $$ID(XCTestExpectation*, expectation), $$ID(monal_void_block_t, someCallback), $$ID(NSString*, dummyObj)) + XCTAssertEqualObjects(dummyObj, @"dummy string", "handler03 should have gotten 'dummy string'"); + [self handlerTestInstanceHandlerSubcall:expectation]; + someCallback(); +$$ + +-(void) handlerTestInstanceHandlerSubcall:(XCTestExpectation*) expectation +{ + [expectation fulfill]; +} + +-(void) testHandlerInstanceHandler +{ + XCTestExpectation* expectation = [self expectationWithDescription:@"handlerTestInstanceHandler should fulfill this twice"]; + expectation.expectedFulfillmentCount = 2; + expectation.assertForOverFulfill = YES; + + MLHandler* handler = $newHandler(self, handlerTestInstanceHandler); + $call(handler, $ID(dummyObj, @"dummy string"), $ID(dummyCallback, (^{ + [expectation fulfill]; + }))); + + [self waitForExpectations:@[expectation] timeout:1.0]; +} + +$$class_handler(handlerTestMandatoryArgument, $$ID(monal_void_block_t, dummyCallback)) + dummyCallback(); +$$ + +-(void) testHandlerMandatoryArgument +{ + MLHandler* handler = $newHandler([self class], handlerTestMandatoryArgument); + XCTAssertThrows(($call(handler, $ID(something, @"something"))), "missing mandatory dummyCallback should trigger an exception"); +} + +$$class_handler(handlerTestMissingOptionalArgument, $_ID(NSString*, dummy)) + XCTAssertNil(dummy, "missing optional argument should be nil"); +$$ + +-(void) testHandlerMissingOptionalArgument +{ + MLHandler* handler = $newHandler([self class], handlerTestMissingOptionalArgument, $ID(dummy2, @"dummy2")); + XCTAssertNoThrow(($call(handler, $ID(something, @"something"))), "missing optional dummy argument should not trigger an error"); +} + +$$class_handler(handlerTestGivenOptionalArgument, $_ID(NSString*, dummy)) + XCTAssertNotNil(dummy, "given optional argument should not be nil"); +$$ + +-(void) testHandlerGivenOptionalArgument +{ + MLHandler* handler = $newHandler([self class], handlerTestGivenOptionalArgument, $ID(dummy, @"dummy")); + XCTAssertNoThrow(($call(handler, $ID(something, @"something"))), "giving optional dummy argument should not trigger an error"); +} + +$$class_handler(handlerTestWithInvalidation01, $_ID(NSString*, dummy)) + XCTAssertTrue(NO, "this handler should never be called"); +$$ +$$class_handler(handlerTestWithInvalidationInvalidation01, $_ID(NSString*, something)) + XCTAssertEqualObjects(something, @"something01", "handlerTestWithInvalidationInvalidation01 should have gotten 'something01'"); +$$ + +-(void) testHandlerWithInvalidation01 +{ + MLHandler* handler = $newHandlerWithInvalidation([self class], handlerTestWithInvalidation01, handlerTestWithInvalidationInvalidation01, $ID(dummy2, @"dummy2")); + XCTAssertNoThrow(($invalidate(handler, $ID(something, @"something01"))), "calling an invalidation should not trigger an error"); + XCTAssertThrow(($call(handler, $ID(something, @"something02"))), "calling a handler after its invaidation should trigger an error"); + XCTAssertThrow(($invalidate(handler, $ID(something, @"something03"))), "calling an invalidation twice should trigger an error"); +} + +$$class_handler(handlerTestWithInvalidation02, $$ID(NSString*, dummy2)) + XCTAssertEqualObjects(dummy2, @"dummy2", "handlerTestWithInvalidation02 should have gotten 'dummy2'"); +$$ +$$class_handler(handlerTestWithInvalidationInvalidation02, $_ID(NSString*, something)) + XCTAssertTrue(NO, "this invalidation should never be called"); +$$ + +-(void) testHandlerWithInvalidation02 +{ + MLHandler* handler = $newHandlerWithInvalidation([self class], handlerTestWithInvalidation02, handlerTestWithInvalidationInvalidation02, $ID(dummy2, @"dummy2")); + XCTAssertNoThrow(($call(handler, $ID(something, @"something01"))), "calling a handler should not trigger an error"); + XCTAssertThrow(($invalidate(handler, $ID(something, @"something02"))), "calling an invalidation after its handler should trigger an error"); +} + +@end diff --git a/Monal/MonalXMPPUnitTests/ParserTest.m b/Monal/MonalXMPPUnitTests/ParserTest.m new file mode 100644 index 0000000000..cc49c556d2 --- /dev/null +++ b/Monal/MonalXMPPUnitTests/ParserTest.m @@ -0,0 +1,9 @@ +// +// ParserTest.m +// MonalXMPPUnitTests +// +// Created by admin on 10.02.25. +// Copyright © 2025 monal-im.org. All rights reserved. +// + +#import diff --git a/Monal/MonalXMPPUnitTests/SDPTest.m b/Monal/MonalXMPPUnitTests/SDPTest.m new file mode 100644 index 0000000000..4893c1d601 --- /dev/null +++ b/Monal/MonalXMPPUnitTests/SDPTest.m @@ -0,0 +1,450 @@ +// +// SDPTest.m +// MonalXMPPUnitTests +// +// Created by admin on 10.02.25. +// Copyright © 2025 monal-im.org. All rights reserved. +// + +#import +#import +#import +#import +#import + +static NSString* _rawSDPString = @"v=0\n\ +o=- 2005859539484728435 2 IN IP4 127.0.0.1\n\ +s=-\n\ +t=0 0\n\ +a=group:BUNDLE 0 1 2\n\ +a=extmap-allow-mixed\n\ +a=msid-semantic: WMS stream\n\ +m=audio 9 UDP/TLS/RTP/SAVPF 111 63 9 102 0 8 13 110 126\n\ +c=IN IP4 0.0.0.0\n\ +a=candidate:1076231993 2 udp 41885694 198.51.100.52 50002 typ relay raddr 0.0.0.0 rport 0 generation 0 ufrag V4as network-id 2 network-cost 10\n\ +a=rtcp:9 IN IP4 0.0.0.0\n\ +a=ice-ufrag:Pt2c\n\ +a=ice-pwd:XKe021opw+vupIkkLCI1+kP4\n\ +a=ice-options:trickle renomination\n\ +a=fingerprint:sha-256 1F:CE:47:40:5F:F2:FC:66:F2:21:F7:7D:3D:D6:0D:B0:67:6F:BD:CF:8B:0E:B7:90:5D:8C:33:9E:AD:F2:CB:FC\n\ +a=setup:actpass\n\ +a=mid:0\n\ +a=extmap:1 urn:ietf:params:rtp-hdrext:ssrc-audio-level\n\ +a=extmap:2 http://www.webrtc.org/experiments/rtp-hdrext/abs-send-time\n\ +a=extmap:3 http://www.ietf.org/id/draft-holmer-rmcat-transport-wide-cc-extensions-01\n\ +a=extmap:4 urn:ietf:params:rtp-hdrext:sdes:mid\n\ +a=sendrecv\n\ +a=msid:stream audio0\n\ +a=rtcp-mux\n\ +a=rtpmap:111 opus/48000/2\n\ +a=rtcp-fb:111 transport-cc\n\ +a=fmtp:111 minptime=10;useinbandfec=1\n\ +a=rtpmap:63 red/48000/2\n\ +a=fmtp:63 111/111\n\ +a=rtpmap:9 G722/8000\n\ +a=rtpmap:102 ILBC/8000\n\ +a=rtpmap:0 PCMU/8000\n\ +a=rtpmap:8 PCMA/8000\n\ +a=rtpmap:13 CN/8000\n\ +a=rtpmap:110 telephone-event/48000\n\ +a=rtpmap:126 telephone-event/8000\n\ +a=ssrc:109112503 cname:vUpPwDICjVuwEwGO\n\ +a=ssrc:109112503 msid:stream audio0\n\ +m=video 9 UDP/TLS/RTP/SAVPF 96 97 98 99 100 101 127 103 35 36 104 105 106\n\ +c=IN IP4 0.0.0.0\n\ +a=rtcp:9 IN IP4 0.0.0.0\n\ +a=ice-ufrag:Pt2c\n\ +a=ice-pwd:XKe021opw+vupIkkLCI1+kP4\n\ +a=ice-options:trickle renomination\n\ +a=fingerprint:sha-256 1F:CE:47:40:5F:F2:FC:66:F2:21:F7:7D:3D:D6:0D:B0:67:6F:BD:CF:8B:0E:B7:90:5D:8C:33:9E:AD:F2:CB:FC\n\ +a=setup:actpass\n\ +a=mid:1\n\ +a=extmap:14 urn:ietf:params:rtp-hdrext:toffset\n\ +a=extmap:2 http://www.webrtc.org/experiments/rtp-hdrext/abs-send-time\n\ +a=extmap:13 urn:3gpp:video-orientation\n\ +a=extmap:3 http://www.ietf.org/id/draft-holmer-rmcat-transport-wide-cc-extensions-01\n\ +a=extmap:5 http://www.webrtc.org/experiments/rtp-hdrext/playout-delay\n\ +a=extmap:6 http://www.webrtc.org/experiments/rtp-hdrext/video-content-type\n\ +a=extmap:7 http://www.webrtc.org/experiments/rtp-hdrext/video-timing\n\ +a=extmap:8 http://www.webrtc.org/experiments/rtp-hdrext/color-space\n\ +a=extmap:4 urn:ietf:params:rtp-hdrext:sdes:mid\n\ +a=extmap:10 urn:ietf:params:rtp-hdrext:sdes:rtp-stream-id\n\ +a=extmap:11 urn:ietf:params:rtp-hdrext:sdes:repaired-rtp-stream-id\n\ +a=sendrecv\n\ +a=msid:stream video0\n\ +a=rtcp-mux\n\ +a=rtcp-rsize\n\ +a=rtpmap:96 H264/90000\n\ +a=rtcp-fb:96 goog-remb\n\ +a=rtcp-fb:96 transport-cc\n\ +a=rtcp-fb:96 ccm fir\n\ +a=rtcp-fb:96 nack\n\ +a=rtcp-fb:96 nack pli\n\ +a=fmtp:96 level-asymmetry-allowed=1;packetization-mode=1;profile-level-id=640c34\n\ +a=rtpmap:97 rtx/90000\n\ +a=fmtp:97 apt=96\n\ +a=rtpmap:98 H264/90000\n\ +a=rtcp-fb:98 goog-remb\n\ +a=rtcp-fb:98 transport-cc\n\ +a=rtcp-fb:98 ccm fir\n\ +a=rtcp-fb:98 nack\n\ +a=rtcp-fb:98 nack pli\n\ +a=fmtp:98 level-asymmetry-allowed=1;packetization-mode=1;profile-level-id=42e034\n\ +a=rtpmap:99 rtx/90000\n\ +a=fmtp:99 apt=98\n\ +a=rtpmap:100 VP8/90000\n\ +a=rtcp-fb:100 goog-remb\n\ +a=rtcp-fb:100 transport-cc\n\ +a=rtcp-fb:100 ccm fir\n\ +a=rtcp-fb:100 nack\n\ +a=rtcp-fb:100 nack pli\n\ +a=rtpmap:101 rtx/90000\n\ +a=fmtp:101 apt=100\n\ +a=rtpmap:127 VP9/90000\n\ +a=rtcp-fb:127 goog-remb\n\ +a=rtcp-fb:127 transport-cc\n\ +a=rtcp-fb:127 ccm fir\n\ +a=rtcp-fb:127 nack\n\ +a=rtcp-fb:127 nack pli\n\ +a=rtpmap:103 rtx/90000\n\ +a=fmtp:103 apt=127\n\ +a=rtpmap:35 AV1/90000\n\ +a=rtcp-fb:35 goog-remb\n\ +a=rtcp-fb:35 transport-cc\n\ +a=rtcp-fb:35 ccm fir\n\ +a=rtcp-fb:35 nack\n\ +a=rtcp-fb:35 nack pli\n\ +a=rtpmap:36 rtx/90000\n\ +a=fmtp:36 apt=35\n\ +a=rtpmap:104 red/90000\n\ +a=rtpmap:105 rtx/90000\n\ +a=fmtp:105 apt=104\n\ +a=rtpmap:106 ulpfec/90000\n\ +a=ssrc-group:FID 3733210709 4025710505\n\ +a=ssrc:3733210709 cname:vUpPwDICjVuwEwGO\n\ +a=ssrc:3733210709 msid:stream video0\n\ +a=ssrc:4025710505 cname:vUpPwDICjVuwEwGO\n\ +a=ssrc:4025710505 msid:stream video0\n\ +m=application 9 UDP/DTLS/SCTP webrtc-datachannel\n\ +c=IN IP4 0.0.0.0\n\ +a=ice-ufrag:Pt2c\n\ +a=ice-pwd:XKe021opw+vupIkkLCI1+kP4\n\ +a=ice-options:trickle renomination\n\ +a=fingerprint:sha-256 1F:CE:47:40:5F:F2:FC:66:F2:21:F7:7D:3D:D6:0D:B0:67:6F:BD:CF:8B:0E:B7:90:5D:8C:33:9E:AD:F2:CB:FC\n\ +a=setup:actpass\n\ +a=mid:2\n\ +a=sctp-port:5000\n\ +a=max-message-size:262144\n"; + +static NSString* _rawXMLString = @"1F:CE:47:40:5F:F2:FC:66:F2:21:F7:7D:3D:D6:0D:B0:67:6F:BD:CF:8B:0E:B7:90:5D:8C:33:9E:AD:F2:CB:FC1F:CE:47:40:5F:F2:FC:66:F2:21:F7:7D:3D:D6:0D:B0:67:6F:BD:CF:8B:0E:B7:90:5D:8C:33:9E:AD:F2:CB:FC"; + +static NSString* _rawXMLInputString = @"\ +\ + \ + \ + \ + \ + \ + \ + \ + \ + 3D:7C:7D:EC:CC:84:39:F2:46:A9:10:03:9E:09:FD:4D:E7:9A:49:6D:54:84:F5:5A:10:C1:09:A3:1F:B1:68:D2\ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + 3D:7C:7D:EC:CC:84:39:F2:46:A9:10:03:9E:09:FD:4D:E7:9A:49:6D:54:84:F5:5A:10:C1:09:A3:1F:B1:68:D2\ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ +"; + NSString* _rawSDPOutputString = @"v=0\ +o=- 2005859539484728435 2 IN IP4 127.0.0.1\ +s=-\ +t=0 0\ +a=group:BUNDLE 0 1\ +a=msid-semantic: WMS stream\ +m=audio 9 UDP/TLS/RTP/SAVP 13 111 63 9 110 0 102 8 126\ +c=IN IP4 0.0.0.0\ +a=sendrecv\ +a=mid:0\ +a=rtcp:9 IN IP4 0.0.0.0\ +a=ice-pwd:+g6eHJ3YWHoXNdOM60q0LH85\ +a=ice-ufrag:LlJY\ +a=fingerprint:sha-256 3D:7C:7D:EC:CC:84:39:F2:46:A9:10:03:9E:09:FD:4D:E7:9A:49:6D:54:84:F5:5A:10:C1:09:A3:1F:B1:68:D2\ +a=setup:actpass\ +a=extmap-allow-mixed\ +a=extmap:1 urn:ietf:params:rtp-hdrext:ssrc-audio-level\ +a=extmap:2 http://www.webrtc.org/experiments/rtp-hdrext/abs-send-time\ +a=extmap:3 http://www.ietf.org/id/draft-holmer-rmcat-transport-wide-cc-extensions-01\ +a=extmap:4 urn:ietf:params:rtp-hdrext:sdes:mid\ +a=rtcp-mux\ +a=rtpmap:13 CN/8000\ +a=rtpmap:111 opus/48000/2\ +a=rtcp-fb:111 transport-cc\ +a=fmtp:111 minptime=10;useinbandfec=1\ +a=rtpmap:63 red/48000/2\ +a=fmtp:63 111/111\ +a=rtpmap:9 G722/8000\ +a=rtpmap:110 telephone-event/48000\ +a=rtpmap:0 PCMU/8000\ +a=rtpmap:102 ILBC/8000\ +a=rtpmap:8 PCMA/8000\ +a=rtpmap:126 telephone-event/8000\ +a=ssrc:388312053 cname:EKc2Iz0i3z5nyiVy\ +a=ssrc:388312053 msid:stream audio0\ +a=ice-options:trickle renomination\ +m=video 9 UDP/TLS/RTP/SAVP 98 127 106 35 103 97 99 36 96 104 100 101 105\ +c=IN IP4 0.0.0.0\ +a=sendrecv\ +a=mid:1\ +a=rtcp:9 IN IP4 0.0.0.0\ +a=ice-pwd:+g6eHJ3YWHoXNdOM60q0LH85\ +a=ice-ufrag:LlJY\ +a=fingerprint:sha-256 3D:7C:7D:EC:CC:84:39:F2:46:A9:10:03:9E:09:FD:4D:E7:9A:49:6D:54:84:F5:5A:10:C1:09:A3:1F:B1:68:D2\ +a=setup:actpass\ +a=extmap-allow-mixed\ +a=extmap:14 urn:ietf:params:rtp-hdrext:toffset\ +a=extmap:2 http://www.webrtc.org/experiments/rtp-hdrext/abs-send-time\ +a=extmap:13 urn:3gpp:video-orientation\ +a=extmap:3 http://www.ietf.org/id/draft-holmer-rmcat-transport-wide-cc-extensions-01\ +a=extmap:5 http://www.webrtc.org/experiments/rtp-hdrext/playout-delay\ +a=extmap:6 http://www.webrtc.org/experiments/rtp-hdrext/video-content-type\ +a=extmap:7 http://www.webrtc.org/experiments/rtp-hdrext/video-timing\ +a=extmap:8 http://www.webrtc.org/experiments/rtp-hdrext/color-space\ +a=extmap:4 urn:ietf:params:rtp-hdrext:sdes:mid\ +a=extmap:10 urn:ietf:params:rtp-hdrext:sdes:rtp-stream-id\ +a=extmap:11 urn:ietf:params:rtp-hdrext:sdes:repaired-rtp-stream-id\ +a=rtcp-mux\ +a=ssrc-group:FID 4017423501 2821445958\ +a=rtpmap:98 H264/90000\ +a=rtcp-fb:98 goog-remb\ +a=rtcp-fb:98 transport-cc\ +a=rtcp-fb:98 ccm fir\ +a=rtcp-fb:98 nack\ +a=rtcp-fb:98 nack pli\ +a=fmtp:98 profile-level-id=42e034;level-asymmetry-allowed=1;packetization-mode=1\ +a=rtpmap:127 VP9/90000\ +a=rtcp-fb:127 goog-remb\ +a=rtcp-fb:127 transport-cc\ +a=rtcp-fb:127 ccm fir\ +a=rtcp-fb:127 nack\ +a=rtcp-fb:127 nack pli\ +a=fmtp:127 \ +a=rtpmap:106 ulpfec/90000\ +a=rtpmap:35 AV1/90000\ +a=rtcp-fb:35 goog-remb\ +a=rtcp-fb:35 transport-cc\ +a=rtcp-fb:35 ccm fir\ +a=rtcp-fb:35 nack\ +a=rtcp-fb:35 nack pli\ +a=fmtp:35 \ +a=rtpmap:103 rtx/90000\ +a=fmtp:103 apt=127\ +a=rtpmap:97 rtx/90000\ +a=fmtp:97 apt=96\ +a=rtpmap:99 rtx/90000\ +a=fmtp:99 apt=98\ +a=rtpmap:36 rtx/90000\ +a=fmtp:36 apt=35\ +a=rtpmap:96 H264/90000\ +a=rtcp-fb:96 goog-remb\ +a=rtcp-fb:96 transport-cc\ +a=rtcp-fb:96 ccm fir\ +a=rtcp-fb:96 nack\ +a=rtcp-fb:96 nack pli\ +a=fmtp:96 profile-level-id=640c34;level-asymmetry-allowed=1;packetization-mode=1\ +a=rtpmap:104 red/90000\ +a=rtpmap:100 VP8/90000\ +a=rtcp-fb:100 goog-remb\ +a=rtcp-fb:100 transport-cc\ +a=rtcp-fb:100 ccm fir\ +a=rtcp-fb:100 nack\ +a=rtcp-fb:100 nack pli\ +a=fmtp:100 \ +a=rtpmap:101 rtx/90000\ +a=fmtp:101 apt=100\ +a=rtpmap:105 rtx/90000\ +a=fmtp:105 apt=104\ +a=ssrc:4017423501 cname:EKc2Iz0i3z5nyiVy\ +a=ssrc:4017423501 msid:stream video0\ +a=ssrc:2821445958 cname:EKc2Iz0i3z5nyiVy\ +a=ssrc:2821445958 msid:stream video0\ +a=ice-options:trickle renomination\ +"; + +@interface SDPTest : XCTestCase +@end + +@implementation SDPTest + +-(void) setUp +{ + // Put setup code here. This method is called before the invocation of each test method in the class. +} + +-(void) tearDown +{ + // Put teardown code here. This method is called after the invocation of each test method in the class. +} + + +-(void) testRawSDP2XMLString +{ + NSString* xmlString = [JingleSDPBridge getJingleStringForSDPString:_rawSDPString withInitiator:YES]; + XCTAssertEqualObjects(xmlString, _rawXMLString, "rust parsed sdp should match xml string"); +} + +-(void) testRawXMLString2SDP +{ + NSString* sdpString = [JingleSDPBridge getSDPStringForJingleString:_rawXMLInputString withInitiator:YES]; + XCTAssertEqualObjects(sdpString, _rawSDPOutputString, "rust parsed sdp should match xml string"); +} + +-(void) testSDP2XMLNodes +{ + NSArray* xmlNodes = [HelperTools sdp2xml:_rawSDPString withInitiator:YES]; + NSArray* xmlStrings = @[ + @"", + @"1F:CE:47:40:5F:F2:FC:66:F2:21:F7:7D:3D:D6:0D:B0:67:6F:BD:CF:8B:0E:B7:90:5D:8C:33:9E:AD:F2:CB:FC", + @"1F:CE:47:40:5F:F2:FC:66:F2:21:F7:7D:3D:D6:0D:B0:67:6F:BD:CF:8B:0E:B7:90:5D:8C:33:9E:AD:F2:CB:FC", + ]; + int i = 0; + for(MLXMLNode* node in xmlNodes) + XCTAssertEqualObjects(node.XMLString, xmlStrings[i++], "sdp should be parsed into proper xml strings"); +} + +-(void) testXMLNodes2SDP +{ + NSString* sdpString = [HelperTools xml2sdp:xmlNodes withInitiator:YES]; + XCTAssertEqualObjects(sdpString, _rawSDPString, "xml2sdp should produce a proper sdp string"); +} + +@end \ No newline at end of file