我编写了两个单元测试来验证提供/应答机制是否在我的应用程序中正确实现。第一个单元测试在收到报价时验证对等方的行为,而第二个单元测试在创建报价时验证对等方的行为。对于我的单元测试,我使用了以下模拟报价和模拟答案:
提供 :
var mockOffer { "sdp": "v=0\r\n" +
"o=- 7282588543017546346 2 IN IP4 127.0.0.1\r\n" +
"s=-\r\n" +
"t=0 0\r\n" +
"a=group:BUNDLE audio video\r\n" +
"a=msid-semantic: WMS\r\n" +
"m=audio 1 RTP/SAVPF 111 103 104 0 8 106 105 13 126\r\n" +
"c=IN IP4 0.0.0.0\r\n" +
"a=rtcp:1 IN IP4 0.0.0.0\r\n" +
"a=ice-ufrag:IJU9DHoiy8+X8FtX\r\n" +
"a=ice-pwd:3qgT9ydEM/CMkgan8ZWvgvbg\r\n" +
"a=ice-options:google-ice\r\n" +
"a=fingerprint:sha-256 54:90:7A:6F:BC:46:C4:5F:25:B9:02:97:3D:A7:53:5D:B4:F6:CE:55:EB:78:51:84:0C:41:0B:2B:21:AA:CD:05\r\n" +
"a=setup:actpass\r\n" +
"a=mid:audio\r\n" +
"a=extmap:1 urn:ietf:params:rtp-hdrext:ssrc-audio-level\r\n" +
"a=recvonly\r\n" +
"a=rtcp-mux\r\n" +
"a=crypto:1 AES_CM_128_HMAC_SHA1_80 inline:gC/fmSmErYS1MaaCQnXZRtKR6l8yWMc5zbOpdVT8\r\n" +
"a=rtpmap:111 opus/48000/2\r\n" +
"a=fmtp:111 minptime=10\r\n" +
"a=rtpmap:103 ISAC/16000\r\n" +
"a=rtpmap:104 ISAC/32000\r\n" +
"a=rtpmap:0 PCMU/8000\r\n" +
"a=rtpmap:8 PCMA/8000\r\n" +
"a=rtpmap:106 CN/32000\r\n" +
"a=rtpmap:105 CN/16000\r\n" +
"a=rtpmap:13 CN/8000\r\n" +
"a=rtpmap:126 telephone-event/8000\r\n" +
"a=maxptime:60\r\n" +
"m=video 1 RTP/SAVPF 100 116 117\r\n" +
"c=IN IP4 0.0.0.0\r\n" +
"a=rtcp:1 IN IP4 0.0.0.0\r\n" +
"a=ice-ufrag:IJU9DHoiy8+X8FtX\r\n" +
"a=ice-pwd:3qgT9ydEM/CMkgan8ZWvgvbg\r\n" +
"a=ice-options:google-ice\r\n" +
"a=fingerprint:sha-256 54:90:7A:6F:BC:46:C4:5F:25:B9:02:97:3D:A7:53:5D:B4:F6:CE:55:EB:78:51:84:0C:41:0B:2B:21:AA:CD:05\r\n" +
"a=setup:actpass\r\n" +
"a=mid:video\r\n" +
"a=extmap:2 urn:ietf:params:rtp-hdrext:toffset\r\n" +
"a=extmap:3 http://www.webrtc.org/experiments/rtp-hdrext/abs-send-time\r\n" +
"a=recvonly\r\n" +
"a=rtcp-mux\r\n" +
"a=crypto:1 AES_CM_128_HMAC_SHA1_80 inline:gC/fmSmErYS1MaaCQnXZRtKR6l8yWMc5zbOpdVT8\r\n" +
"a=rtpmap:100 VP8/90000\r\n" +
"a=rtcp-fb:100 ccm fir\r\n" +
"a=rtcp-fb:100 nack\r\n" +
"a=rtcp-fb:100 nack pli\r\n" +
"a=rtcp-fb:100 goog-remb\r\n" +
"a=rtpmap:116 red/90000\r\n" +
"a=rtpmap:117 ulpfec/90000\r\n",
"type":"offer"};
回答 :
var mockAnswer = {"sdp":
"v=0\r\n" +
"o=- 6465573306213105510 2 IN IP4 127.0.0.1\r\n" +
"s=-\r\n" +
"t=0 0\r\n" +
"a=group:BUNDLE audio video\r\n" +
"a=msid-semantic: WMS\r\n" +
"m=audio 1 RTP/SAVPF 111 103 104 0 8 106 105 13 126\r\n" +
"c=IN IP4 0.0.0.0\r\n" +
"a=rtcp:1 IN IP4 0.0.0.0\r\n" +
"a=ice-ufrag:AyBahFUhrQOPtHlQ\r\n" +
"a=ice-pwd:QGUAtvpJDqYq2F8BUH2ZWdGv\r\n" +
"a=fingerprint:sha-256 54:90:7A:6F:BC:46:C4:5F:25:B9:02:97:3D:A7:53:5D:B4:F6:CE:55:EB:78:51:84:0C:41:0B:2B:21:AA:CD:05\r\n" +
"a=setup:active\r\n" +
"a=mid:audio\r\n" +
"a=extmap:1 urn:ietf:params:rtp-hdrext:ssrc-audio-level\r\n" +
"a=sendonly\r\n" +
"a=rtcp-mux\r\n" +
"a=rtpmap:111 opus/48000/2\r\n" +
"a=fmtp:111 minptime=10\r\n" +
"a=rtpmap:103 ISAC/16000\r\n" +
"a=rtpmap:104 ISAC/32000\r\n" +
"a=rtpmap:0 PCMU/8000\r\n" +
"a=rtpmap:8 PCMA/8000\r\n" +
"a=rtpmap:106 CN/32000\r\n" +
"a=rtpmap:105 CN/16000\r\n" +
"a=rtpmap:13 CN/8000\r\n" +
"a=rtpmap:126 telephone-event/8000\r\n" +
"a=maxptime:60\r\n" +
"m=video 1 RTP/SAVPF 100 116 117\r\n" +
"c=IN IP4 0.0.0.0\r\n" +
"a=rtcp:1 IN IP4 0.0.0.0\r\n" +
"a=ice-ufrag:AyBahFUhrQOPtHlQ\r\n" +
"a=ice-pwd:QGUAtvpJDqYq2F8BUH2ZWdGv\r\n" +
"a=fingerprint:sha-256 54:90:7A:6F:BC:46:C4:5F:25:B9:02:97:3D:A7:53:5D:B4:F6:CE:55:EB:78:51:84:0C:41:0B:2B:21:AA:CD:05\r\n" +
"a=setup:active\r\n" +
"a=mid:video\r\n" +
"a=extmap:2 urn:ietf:params:rtp-hdrext:toffset\r\n" +
"a=extmap:3 http://www.webrtc.org/experiments/rtp-hdrext/abs-send-time\r\n" +
"a=sendonly\r\n" +
"a=rtcp-mux\r\n" +
"a=rtpmap:100 VP8/90000\r\n" +
"a=rtcp-fb:100 ccm fir\r\n" +
"a=rtcp-fb:100 nack\r\n" +
"a=rtcp-fb:100 nack pli\r\n" +
"a=rtcp-fb:100 goog-remb\r\n" +
"a=rtpmap:116 red/90000\r\n" +
"a=rtpmap:117 ulpfec/90000\r\n",
"type": "answer"};
注意:它们是使用 createAnswer 和 createOffer 方法生成的。
- 第一个问题为什么有两个指纹字段?
第一个单元测试反映了对等方收到远程提议并回复答案时的场景。我用报价调用 setRemoteDescriptor,然后用答案调用 serLocalDescriptor。该测试工作正常,不会引发错误,并且 SignallingState 会根据执行的操作而更改(即 setRemoteDescriptor 导致 SignalingState 更改 have-remote-offer 等..)。
单元测试 :
it("Test the signalStatus machine when a peer receives an offer", function(done){
var peerReceiver = new app.PeerConnection("mock_receiver", session, false);
var successRemote = function(){
console.log("Remote descriptor installed successfully.");
expect(peerReceiver.getSignalingState()).toEqual("have-remote-offer");
peerReceiver._setLocalDescriptor(mockAnswer, successLocal, failure);
};
var successLocal = function(){
console.log("Local descriptor installed successfully.");
expect(peerReceiver.getSignalingState()).toEqual("stable");
done();
}.bind(this);
var failure = function(error){
console.log("Error installing SDP." + error);
expect(error).toBeNull();
done();
}.bind(this);
expect(peerReceiver.getSignalingState()).toEqual("none");
peerReceiver._setRemoteDescription(mockOffer, successRemote,failure);
});
第二个单元测试使用相同的模拟答案和报价,但它反映了当对等方创建并设置本地报价并将从远程对等方收到的答案设置为远程报价时的场景。测试使用报价调用 setLocalDescriptor。结果,SIngnalingState 更改为 have-local-offer。然后使用 mockAnswer 调用 setRemoteDescription。此调用生成以下错误:
ERROR : Failed to set remote answer sdp: Failed to push down transport description: Failed to apply remote fingerprint.
可能是什么原因?难道我做错了什么?offer和answer中的指纹完全相同,如果指纹有问题,那么第一次单元测试也应该有问题。我一无所知。欢迎任何建议,建议。:D
单元测试失败:
it("Test the signalStatus machine when a peer sends an offer", function(done){
var peerSender = new app.PeerConnection("mock_sender", session, false);
var successRemote = function(){
console.log("Remote descriptor installed successfully.");
expect(peerSender.getSignalingState()).toEqual("stable");
done();
};
var successLocal = function(){
console.log("Local descriptor installed successfully.");
expect(peerSender.getSignalingState()).toEqual("have-local-offer");
peerSender._setRemoteDescription(mockAnswer, successRemote,failure);
}.bind(this);
var failure = function(error){
console.log("Error installing SDP." + error);
expect(error).toBeNull();
done();
}.bind(this);
expect(peerSender.getSignalingState()).toEqual("none");
peerSender._setLocalDescriptor(mockOffer, successLocal,failure);
});
RPCPeerConnection 对象,当产生错误时:
RTCPeerConnection {ondatachannel: null, oniceconnectionstatechange: function, onremovestream: function, onaddstream: function, onsignalingstatechange: function…}
iceConnectionState: "new"
iceGatheringState: "new"
localDescription: RTCSessionDescription
onaddstream: function (stream) { self.onRemoteStreamAdded(stream);}
ondatachannel: null
onicecandidate: function (e) { self.onIceCandidate(e, pc.iceGatheringState)}
oniceconnectionstatechange: function (e) { self.onIceConnectionStatusStateChange(e)}
onnegotiationneeded: null
onremovestream: function (stream) { self.onRemoteStreamRemoved(stream);}
onsignalingstatechange: function (e) {self.onSignalingStateChange(e)}
remoteDescription: null
signalingState: "have-local-offer"
__proto__: RTCPeerConnection
PeerConnection.js:287
Error installing SDP.undefined
完整的源代码可以在这里找到
如果您需要更多信息,请与我们联系。