webrtc-connection 0.2.0

WebRTC connection.
Documentation
#[cfg(test)]
mod connection {
    use webrtc_connection::utils::test_helpers::create_connection_pair;
    
    /// Base test that creates a connection that uses in-memory `DuplexStream`
    /// for the signaling channel.
    #[tokio::test]
    async fn must_connect() {
        // test that we establish a connection
        create_connection_pair().await;
    }

    mod on_remote_channel_stream {
        use webrtc_connection::utils::test_helpers::create_connection_pair;

        #[tokio::test]
        async fn expose_on_remote_channel_stream() {
            let (mut client_connection, mut server_connection) = create_connection_pair().await;

            let client_on_remote_channel = client_connection.on_remote_channel();
            let server_on_remote_channel = server_connection.on_remote_channel();

            assert!(
                client_on_remote_channel.is_ok(),
                "Client connection must expose \"on_remote_channel\" stream.",
            );

            assert!(
                server_on_remote_channel.is_ok(),
                "Server connection must expose \"on_remote_channel\" stream.",
            );

            assert!(
                client_connection.on_remote_channel().is_err(),
                "Client connection must expose \"on_remote_channel\" stream only once.",
            );

            assert!(
                server_connection.on_remote_channel().is_err(),
                "Server connection must expose \"on_remote_channel\" stream only once.",
            );

            client_connection.off_remote_channel(client_on_remote_channel.unwrap()).unwrap();
            assert!(
                client_connection.on_remote_channel().is_ok(),
                "Client connection must be able to receive \"on_remote_channel\" listener back.",
            );

            assert!(
                server_connection.on_remote_channel().is_err(),
                "Server connection must stay as \"None\".",
            );

            server_connection.off_remote_channel(server_on_remote_channel.unwrap()).unwrap();
            assert!(
                server_connection.on_remote_channel().is_ok(),
                "Server connection must be able to receive \"on_remote_channel\" listener back.",
            );
        }
    }

    /// Test the `on_remote_channel` logic, for the cases when the cahnnel
    /// is initialized from the server, client or both sides.
    mod events {
        use tokio::try_join;
        use connection_utils::Connected;
        use cs_utils::{random_number, random_str};
        use webrtc_connection::utils::test_helpers::create_connection_pair;

        #[tokio::test]
        async fn must_expose_on_data_channel_event_stream_server_initialized() {
            // test that we establish a connection
            let (mut client_connection, mut server_connection) = create_connection_pair().await;

            let channel_name = format!("test channel {}", random_str(8));
            let channel_name1 = channel_name.clone();
            let channel_name2 = channel_name.clone();

            let mut on_data_channel = client_connection.on_remote_channel()
                .expect("Cannot get \"on_remote_channel\" stream.");

            let _res = try_join!(
                tokio::spawn(async move {
                    let channel = on_data_channel
                        .recv()
                        .await
                        .expect("Cannot receive remote channel creation event.");

                    assert_eq!(
                        *channel.label(),
                        channel_name1,
                    );
                }),
                tokio::spawn(async move {
                    let channel = server_connection
                        .channel(channel_name2.clone())
                        .await
                        .expect("Cannot create channel.");

                    assert_eq!(
                        *channel.label(),
                        channel_name2,
                    );
                }),
            ).unwrap();
        }

        #[tokio::test]
        async fn must_expose_on_data_channel_event_stream_client_initialized() {
            // test that we establish a connection
            let (mut client_connection, mut server_connection) = create_connection_pair().await;

            let channel_name = format!("test channel {}", random_str(8));
            let channel_name1 = channel_name.clone();
            let channel_name2 = channel_name.clone();

            let mut on_data_channel = server_connection.on_remote_channel()
                .expect("Cannot get \"on_remote_channel\" stream.");

            let _res = try_join!(
                tokio::spawn(async move {
                    loop {
                        let channel = on_data_channel
                            .recv()
                            .await
                            .expect("Cannot receive remote channel creation event.");

                        // During the connection initialization phase, we need to create
                        // data channel, otherwise the connection won't be set up. That connection
                        // has the default label of "default_channel" so we filter this one out
                        // from our tests.
                        if channel.label() == "default_channel" {
                            continue;
                        }

                        assert_eq!(
                            *channel.label(),
                            channel_name1,
                        );

                        break;
                    }
                }),
                tokio::spawn(async move {
                    loop {
                        let channel = client_connection
                            .channel(channel_name2.clone())
                            .await
                            .expect("Cannot create channel.");

                        // During the connection initialization phase, we need to create
                        // data channel, otherwise the connection won't be set up. That connection
                        // has the default label of "default_channel" so we filter this one out
                        // from our tests.
                        if channel.label() == "default_channel" {
                            continue;
                        }

                        assert_eq!(
                            *channel.label(),
                            channel_name2,
                        );

                        break;
                    }
                }),
            ).unwrap();
        }

        #[tokio::test]
        async fn must_expose_on_data_channel_event_stream_bidirectional() {
            // test that we establish a connection
            let (client_connection, server_connection) = create_connection_pair().await;

            fn create_channel_labels(
                prefix: String,
                channels_count: usize,
            ) -> Vec<String> {
                let mut res = vec![];
                for _i in 0..channels_count {
                    res.push(format!("{}_{}", &prefix, random_str(6)));
                }

                return res;
            }

            let mut client_create_channels = vec!["default_channel".to_string()];
            client_create_channels
                .append(&mut create_channel_labels(
                    "client_channel".to_string(),
                    random_number(1..=5),
                ));

            let client_create_channels1 = client_create_channels.clone();
            let client_create_channels2 = client_create_channels.clone();

            let server_create_channels = create_channel_labels(
                "server_channel".to_string(),
                random_number(1..=5),
            );

            let server_create_channels1 = server_create_channels.clone();
            let server_create_channels2 = server_create_channels.clone();

            async fn test_connection_channels(
                mut connection: Box<dyn Connected>,
                create_channel_labels: Vec<String>,
                receive_channel_labels: Vec<String>,
            ) {
                let mut on_remote_channel = connection.on_remote_channel()
                    .expect("Cannot get \"on_remote_channel\" stream.");

                let mut received_channels = vec![];

                let _res = try_join!(
                    tokio::spawn(async move {
                        loop {
                            let channel = on_remote_channel
                                .recv()
                                .await
                                .expect("Cannot receive remote channel creation event.");

                            received_channels.push(channel.label().clone());

                            if received_channels.len() == receive_channel_labels.len() {
                                assert_eq!(
                                    received_channels.join(""),
                                    receive_channel_labels.join(""),
                                    "Received channels must match.",
                                );

                                break;
                            }
                        }
                    }),
                    tokio::spawn(async move {
                        for label in create_channel_labels {
                            let channel = connection
                                .channel(label.clone())
                                .await
                                .expect(
                                    &format!("Cannot create channel [{}]", &label),
                                );

                            assert_eq!(
                                *channel.label(),
                                label,
                                "Created channel labels must match.",
                            );
                        }
                    }),
                ).unwrap();
            }

            let _res = try_join!(
                tokio::spawn(async move {
                    test_connection_channels(
                        client_connection,
                        client_create_channels1,
                        server_create_channels1,
                    ).await;
                }),
                tokio::spawn(async move {
                    test_connection_channels(
                        server_connection,
                        server_create_channels2,
                        client_create_channels2,
                    ).await;
                }),
            ).unwrap();
        }
    }
}