Skip to content

Commit

Permalink
Add tests
Browse files Browse the repository at this point in the history
  • Loading branch information
mickel8 committed Feb 4, 2024
1 parent fa5d0c1 commit a474162
Show file tree
Hide file tree
Showing 7 changed files with 167 additions and 18 deletions.
28 changes: 16 additions & 12 deletions lib/ex_webrtc/peer_connection.ex
Original file line number Diff line number Diff line change
Expand Up @@ -167,16 +167,21 @@ defmodule ExWebRTC.PeerConnection do
GenServer.call(peer_connection, {:remove_track, sender_id})
end

@spec get_stats(peer_connection()) :: %{String.t() => term()}
def get_stats(peer_connection) do
GenServer.call(peer_connection, :get_stats)
end

@spec send_rtp(peer_connection(), String.t(), ExRTP.Packet.t()) :: :ok
def send_rtp(peer_connection, track_id, packet) do
GenServer.cast(peer_connection, {:send_rtp, track_id, packet})
end

@doc """
Returns peer connection's statistics.
See [RTCStatsReport](https://www.w3.org/TR/webrtc/#rtcstatsreport-object) for the output structure.
"""
@spec get_stats(peer_connection()) :: %{(atom() | integer()) => map()}
def get_stats(peer_connection) do
GenServer.call(peer_connection, :get_stats)
end

@spec close(peer_connection()) :: :ok
def close(peer_connection) do
GenServer.stop(peer_connection)
Expand Down Expand Up @@ -666,23 +671,22 @@ defmodule ExWebRTC.PeerConnection do
type: :peer_connection,
timestamp: timestamp,
signaling_state: state.signaling_state,
ice_state: state.ice_state,
ice_gathering_state: state.ice_gathering_state,
dtls_state: state.dtls_state,
negotiation_needed: state.negotiation_needed,
connection_state: state.conn_state
},
transport: %{
id: :transport,
type: :transport,
timestamp: timestamp,
ice_state: ice_stats.state,
ice_gathering_state: state.ice_gathering_state,
ice_role: ice_stats.role,
ice_local_ufrag: ice_stats.local_ufrag,
dtls_state: state.dtls_state,
bytes_sent: ice_stats.bytes_sent,
bytes_received: ice_stats.bytes_received,
packets_sent: ice_stats.packets_sent,
packets_received: ice_stats.packets_received,
ice_role: ice_stats.role,
ice_local_ufrag: ice_stats.local_ufrag,
ice_state: ice_stats.state
packets_received: ice_stats.packets_received
},
local_certificate: %{
id: :local_certificate,
Expand Down
2 changes: 1 addition & 1 deletion lib/ex_webrtc/rtp_receiver.ex
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ defmodule ExWebRTC.RTPReceiver do
@doc false
@spec recv(t(), ExRTP.Packet.t(), binary()) :: t()
def recv(receiver, packet, raw_packet) do
# FIXME assign ssrc when applying local/remote description
# TODO assign ssrc when applying local/remote description
# As RTPReceiver is only used for the purpose of statistics,
# it's good enough to take the ssrc from the packet but
# the preffered implementation would be to take it from the SDP
Expand Down
6 changes: 3 additions & 3 deletions lib/ex_webrtc/rtp_sender.ex
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ defmodule ExWebRTC.RTPSender do
next_seq_num = sender.last_seq_num + 1 &&& 0xFFFF
packet = %{packet | payload_type: sender.pt, ssrc: sender.ssrc, sequence_number: next_seq_num}

packet =
data =
packet
|> ExRTP.Packet.add_extension(mid_ext)
|> ExRTP.Packet.encode()
Expand All @@ -100,11 +100,11 @@ defmodule ExWebRTC.RTPSender do
sender
| last_seq_num: next_seq_num,
packets_sent: sender.packets_sent + 1,
bytes_sent: sender.bytes_sent + byte_size(packet),
bytes_sent: sender.bytes_sent + byte_size(data),
markers_sent: sender.markers_sent + Utils.to_int(packet.marker)
}

{packet, sender}
{data, sender}
end

@doc false
Expand Down
2 changes: 1 addition & 1 deletion lib/ex_webrtc/utils.ex
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ defmodule ExWebRTC.Utils do
id
end

@spec to_int(boolean()) :: non_neg_integer()
@spec to_int(boolean()) :: 0 | 1
def to_int(false), do: 0
def to_int(true), do: 1
end
47 changes: 47 additions & 0 deletions test/ex_webrtc/peer_connection_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -722,6 +722,53 @@ defmodule ExWebRTC.PeerConnectionTest do
end
end

test "get_stats/2" do
{:ok, pc} = PeerConnection.start_link()

assert %{
peer_connection: %{
id: :peer_connection,
type: :peer_connection,
timestamp: timestamp,
signaling_state: :stable,
negotiation_needed: false,
connection_state: :new
},
transport: %{
id: :transport,
type: :transport,
timestamp: timestamp,
ice_state: :new,
ice_gathering_state: :new,
dtls_state: :new,
bytes_sent: 0,
bytes_received: 0,
packets_sent: 0,
packets_received: 0
},
local_certificate: %{
id: :local_certificate,
type: :certificate,
timestamp: timestamp,
fingerprint_algorithm: :sha_256
},
remote_certificate: %{
id: :remote_certificate,
type: :certificate,
timestamp: timestamp,
fingerprint: nil,
fingerprint_algorithm: nil,
base64_certificate: nil
}
} = stats = PeerConnection.get_stats(pc)

assert stats.transport.ice_role in [:controlling, :controlled]
assert is_binary(stats.transport.ice_local_ufrag)

assert is_binary(stats.local_certificate.fingerprint)
assert is_binary(stats.local_certificate.base64_certificate)
end

test "close/1" do
{:ok, pc} = PeerConnection.start()
{:links, links} = Process.info(pc, :links)
Expand Down
52 changes: 52 additions & 0 deletions test/ex_webrtc/rtp_receiver_test.exs
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
defmodule ExWebRTC.RTPReceiverTest do
use ExUnit.Case, async: true

alias ExRTP.Packet
alias ExWebRTC.{MediaStreamTrack, RTPReceiver}

test "get_stats/2" do
timestamp = System.os_time(:millisecond)
payload = <<1, 2, 3>>

track = MediaStreamTrack.new(:audio)
receiver = %RTPReceiver{track: track}

assert %{
id: receiver.track.id,
type: :inbound_rtp,
timestamp: timestamp,
ssrc: nil,
bytes_received: 0,
packets_received: 0,
markers_received: 0
} == RTPReceiver.get_stats(receiver, timestamp)

packet1 = Packet.new(payload, ssrc: 1234)
raw_packet1 = Packet.encode(packet1)
receiver = RTPReceiver.recv(receiver, packet1, raw_packet1)

assert %{
id: receiver.track.id,
type: :inbound_rtp,
timestamp: timestamp,
ssrc: 1234,
bytes_received: byte_size(raw_packet1),
packets_received: 1,
markers_received: 0
} == RTPReceiver.get_stats(receiver, timestamp)

packet2 = Packet.new(payload, ssrc: 1234, marker: true)
raw_packet2 = Packet.encode(packet2)
receiver = RTPReceiver.recv(receiver, packet2, raw_packet2)

assert %{
id: receiver.track.id,
type: :inbound_rtp,
timestamp: timestamp,
ssrc: 1234,
bytes_received: byte_size(raw_packet1) + byte_size(raw_packet2),
packets_received: 2,
markers_received: 1
} == RTPReceiver.get_stats(receiver, timestamp)
end
end
48 changes: 47 additions & 1 deletion test/ex_webrtc/rtp_sender_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ defmodule ExWebRTC.RTPSenderTest do
@max_seq_num (1 <<< 32) - 1
@ssrc 354_947

test "send/2" do
setup do
track = MediaStreamTrack.new(:audio)

codec = %RTPCodecParameters{
Expand All @@ -25,6 +25,11 @@ defmodule ExWebRTC.RTPSenderTest do
rtp_hdr_exts = [%Extmap{id: 1, uri: "urn:ietf:params:rtp-hdrext:sdes:mid"}]

sender = RTPSender.new(track, codec, rtp_hdr_exts, "1", @ssrc)

%{sender: sender}
end

test "send/2", %{sender: sender} do
sender = %RTPSender{sender | last_seq_num: 10_000}

packet = ExRTP.Packet.new(<<>>)
Expand Down Expand Up @@ -52,4 +57,45 @@ defmodule ExWebRTC.RTPSenderTest do
# marker flag shouldn't be overwritten
assert packet.marker == true
end

test "get_stats/2", %{sender: sender} do
timestamp = System.os_time(:millisecond)
payload = <<1, 2, 3>>

assert %{
timestamp: timestamp,
type: :outbound_rtp,
id: sender.id,
ssrc: sender.ssrc,
packets_sent: 0,
bytes_sent: 0,
markers_sent: 0
} == RTPSender.get_stats(sender, timestamp)

packet = ExRTP.Packet.new(payload)
{data1, sender} = RTPSender.send(sender, packet)

assert %{
timestamp: timestamp,
type: :outbound_rtp,
id: sender.id,
ssrc: sender.ssrc,
packets_sent: 1,
bytes_sent: byte_size(data1),
markers_sent: 0
} == RTPSender.get_stats(sender, timestamp)

packet = ExRTP.Packet.new(payload, marker: true)
{data2, sender} = RTPSender.send(sender, packet)

assert %{
timestamp: timestamp,
type: :outbound_rtp,
id: sender.id,
ssrc: sender.ssrc,
packets_sent: 2,
bytes_sent: byte_size(data1) + byte_size(data2),
markers_sent: 1
} == RTPSender.get_stats(sender, timestamp)
end
end

0 comments on commit a474162

Please sign in to comment.