// Copyright 2020 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

use {
    anyhow::{format_err, Error},
    fidl_fidl_examples_routing_echo as fecho, fidl_fuchsia_data as fdata, fuchsia_async as fasync,
    fuchsia_component::server as fserver,
    fuchsia_component_test::{builder::*, mock, Moniker},
    futures::{channel::oneshot, lock::Mutex, StreamExt, TryStreamExt},
    std::sync::Arc,
};

const V1_ECHO_CLIENT_URL: &'static str =
    "fuchsia-pkg://fuchsia.com/fuchsia-component-test-tests#meta/echo_client.cmx";
const V2_ECHO_CLIENT_ABSOLUTE_URL: &'static str =
    "fuchsia-pkg://fuchsia.com/fuchsia-component-test-tests#meta/echo_client.cm";
const V2_ECHO_CLIENT_RELATIVE_URL: &'static str = "#meta/echo_client.cm";

const V1_ECHO_SERVER_URL: &'static str =
    "fuchsia-pkg://fuchsia.com/fuchsia-component-test-tests#meta/echo_server.cmx";
const V2_ECHO_SERVER_ABSOLUTE_URL: &'static str =
    "fuchsia-pkg://fuchsia.com/fuchsia-component-test-tests#meta/echo_server.cm";
const V2_ECHO_SERVER_RELATIVE_URL: &'static str = "#meta/echo_server.cm";

const DEFAULT_ECHO_STR: &'static str = "Hippos rule!";

#[fasync::run_singlethreaded(test)]
async fn protocol_with_uncle_test() -> Result<(), Error> {
    let (send_echo_server_called, receive_echo_server_called) = oneshot::channel();
    let sender = Arc::new(Mutex::new(Some(send_echo_server_called)));

    let mut builder = RealmBuilder::new().await?;
    builder
        .add_component(
            "echo-server",
            ComponentSource::mock(move |mock_handles: mock::MockHandles| {
                Box::pin(echo_server_mock(DEFAULT_ECHO_STR, sender.clone(), mock_handles))
            }),
        )
        .await?
        .add_eager_component(
            "parent/echo-client",
            ComponentSource::url(V2_ECHO_CLIENT_ABSOLUTE_URL),
        )
        .await?
        .add_route(CapabilityRoute {
            capability: Capability::protocol("fidl.examples.routing.echo.Echo"),
            source: RouteEndpoint::component("echo-server"),
            targets: vec![RouteEndpoint::component("parent/echo-client")],
        })?
        .add_route(CapabilityRoute {
            capability: Capability::protocol("fuchsia.logger.LogSink"),
            source: RouteEndpoint::AboveRoot,
            targets: vec![
                RouteEndpoint::component("echo-server"),
                RouteEndpoint::component("parent/echo-client"),
            ],
        })?;
    let _child_instance = builder.build().create().await?;

    receive_echo_server_called.await?;
    Ok(())
}

#[fasync::run_singlethreaded(test)]
async fn protocol_with_siblings_test() -> Result<(), Error> {
    let (send_echo_server_called, receive_echo_server_called) = oneshot::channel();
    let sender = Arc::new(Mutex::new(Some(send_echo_server_called)));

    let mut builder = RealmBuilder::new().await?;
    builder
        .add_eager_component("echo-client", ComponentSource::url(V2_ECHO_CLIENT_ABSOLUTE_URL))
        .await?
        .add_component(
            "echo-server",
            ComponentSource::mock(move |mock_handles: mock::MockHandles| {
                Box::pin(echo_server_mock(DEFAULT_ECHO_STR, sender.clone(), mock_handles))
            }),
        )
        .await?
        .add_route(CapabilityRoute {
            capability: Capability::protocol("fidl.examples.routing.echo.Echo"),
            source: RouteEndpoint::component("echo-server"),
            targets: vec![RouteEndpoint::component("echo-client")],
        })?
        .add_route(CapabilityRoute {
            capability: Capability::protocol("fuchsia.logger.LogSink"),
            source: RouteEndpoint::AboveRoot,
            targets: vec![
                RouteEndpoint::component("echo-client"),
                RouteEndpoint::component("echo-server"),
            ],
        })?;
    let _child_instance = builder.build().create().await?;

    receive_echo_server_called.await?;
    Ok(())
}

#[fasync::run_singlethreaded(test)]
async fn protocol_with_cousins_test() -> Result<(), Error> {
    let (send_echo_server_called, receive_echo_server_called) = oneshot::channel();
    let sender = Arc::new(Mutex::new(Some(send_echo_server_called)));

    let mut builder = RealmBuilder::new().await?;
    builder
        .add_eager_component(
            "parent-1/echo-client",
            ComponentSource::url(V2_ECHO_CLIENT_ABSOLUTE_URL),
        )
        .await?
        .add_component(
            "parent-2/echo-server",
            ComponentSource::mock(move |mock_handles: mock::MockHandles| {
                Box::pin(echo_server_mock(DEFAULT_ECHO_STR, sender.clone(), mock_handles))
            }),
        )
        .await?
        .add_route(CapabilityRoute {
            capability: Capability::protocol("fidl.examples.routing.echo.Echo"),
            source: RouteEndpoint::component("parent-2/echo-server"),
            targets: vec![RouteEndpoint::component("parent-1/echo-client")],
        })?
        .add_route(CapabilityRoute {
            capability: Capability::protocol("fuchsia.logger.LogSink"),
            source: RouteEndpoint::AboveRoot,
            targets: vec![
                RouteEndpoint::component("parent-1/echo-client"),
                RouteEndpoint::component("parent-2/echo-server"),
            ],
        })?;
    let _child_instance = builder.build().create().await?;

    receive_echo_server_called.await?;
    Ok(())
}

#[fasync::run_singlethreaded(test)]
async fn mock_component_with_a_child() -> Result<(), Error> {
    let (send_echo_server_called, receive_echo_server_called) = oneshot::channel();
    let sender = Arc::new(Mutex::new(Some(send_echo_server_called)));

    let mut builder = RealmBuilder::new().await?;
    builder
        .add_component(
            "echo-server",
            ComponentSource::mock(move |mock_handles: mock::MockHandles| {
                Box::pin(echo_server_mock(DEFAULT_ECHO_STR, sender.clone(), mock_handles))
            }),
        )
        .await?
        .add_eager_component(
            "echo-server/echo-client",
            ComponentSource::url(V2_ECHO_CLIENT_ABSOLUTE_URL),
        )
        .await?
        .add_route(CapabilityRoute {
            capability: Capability::protocol("fidl.examples.routing.echo.Echo"),
            source: RouteEndpoint::component("echo-server"),
            targets: vec![RouteEndpoint::component("echo-server/echo-client")],
        })?
        .add_route(CapabilityRoute {
            capability: Capability::protocol("fuchsia.logger.LogSink"),
            source: RouteEndpoint::AboveRoot,
            targets: vec![
                RouteEndpoint::component("echo-server"),
                RouteEndpoint::component("echo-server/echo-client"),
            ],
        })?;
    let _child_instance = builder.build().create().await?;

    receive_echo_server_called.await?;
    Ok(())
}

#[fasync::run_singlethreaded(test)]
async fn relative_echo_realm() -> Result<(), Error> {
    let mut builder = RealmBuilder::new().await?;
    builder
        .add_component(Moniker::root(), ComponentSource::url("#meta/echo_realm.cm"))
        .await?
        // This route will result in the imported echo_realm exposing this protocol, whereas before
        // it only offered it to echo_client
        .add_route(CapabilityRoute {
            capability: Capability::protocol("fidl.examples.routing.echo.Echo"),
            source: RouteEndpoint::component("echo_server"),
            targets: vec![RouteEndpoint::above_root()],
        })?;
    let realm_instance = builder.build().create().await?;

    let echo_proxy =
        realm_instance.root.connect_to_protocol_at_exposed_dir::<fecho::EchoMarker>()?;
    assert_eq!(Some("hello".to_string()), echo_proxy.echo_string(Some("hello")).await?);

    Ok(())
}

#[fasync::run_singlethreaded(test)]
async fn altered_echo_client_args() -> Result<(), Error> {
    let (send_echo_server_called, receive_echo_server_called) = oneshot::channel();
    let sender = Arc::new(Mutex::new(Some(send_echo_server_called)));

    let mut builder = RealmBuilder::new().await?;
    builder
        .add_component(Moniker::root(), ComponentSource::url("#meta/echo_realm.cm"))
        .await?
        .override_component(
            "echo_server",
            ComponentSource::mock(move |mock_handles: mock::MockHandles| {
                Box::pin(echo_server_mock("Whales rule!", sender.clone(), mock_handles))
            }),
        )
        .await?
        // echo_realm already has the offer we need, but we still need to add this route so that
        // the proper exposes are added to our mock component
        .add_route(CapabilityRoute {
            capability: Capability::protocol("fidl.examples.routing.echo.Echo"),
            source: RouteEndpoint::component("echo_server"),
            targets: vec![RouteEndpoint::component("echo_client")],
        })?;

    // Change the program.args section of the manifest, to alter the string it will try to echo
    let mut realm = builder.build();
    let mut echo_client_decl = realm.get_decl(&"echo_client".into()).await?;
    for entry in echo_client_decl.program.as_mut().unwrap().info.entries.as_mut().unwrap() {
        if entry.key.as_str() == "args" {
            entry.value = Some(Box::new(fdata::DictionaryValue::StrVec(vec![
                "Whales".to_string(),
                "rule!".to_string(),
            ])));
        }
    }
    realm.set_component(&"echo_client".into(), echo_client_decl).await?;
    let _realm_instance = realm.create().await?;

    receive_echo_server_called.await?;

    Ok(())
}

#[fasync::run_singlethreaded(test)]
async fn echo_clients() -> Result<(), Error> {
    // This test runs a series of echo clients from different sources against a mock echo server,
    // confirming that each client successfully connects to the server.

    let (send_echo_client_results, receive_echo_client_results) = oneshot::channel();
    let sender = Arc::new(Mutex::new(Some(send_echo_client_results)));
    let client_sources = vec![
        ComponentSource::legacy_url(V1_ECHO_CLIENT_URL),
        ComponentSource::url(V2_ECHO_CLIENT_ABSOLUTE_URL),
        ComponentSource::url(V2_ECHO_CLIENT_RELATIVE_URL),
        ComponentSource::mock(move |h| Box::pin(echo_client_mock(sender.clone(), h))),
    ];

    for client_source in client_sources {
        let (send_echo_server_called, receive_echo_server_called) = oneshot::channel();
        let sender = Arc::new(Mutex::new(Some(send_echo_server_called)));

        let mut builder = RealmBuilder::new().await?;
        builder
            .add_component(
                "echo-server",
                ComponentSource::mock(move |h| {
                    Box::pin(echo_server_mock(DEFAULT_ECHO_STR, sender.clone(), h))
                }),
            )
            .await?
            .add_eager_component("echo-client", client_source)
            .await?
            .add_route(CapabilityRoute {
                capability: Capability::protocol("fidl.examples.routing.echo.Echo"),
                source: RouteEndpoint::component("echo-server"),
                targets: vec![RouteEndpoint::component("echo-client")],
            })?
            .add_route(CapabilityRoute {
                capability: Capability::protocol("fuchsia.logger.LogSink"),
                source: RouteEndpoint::AboveRoot,
                targets: vec![
                    RouteEndpoint::component("echo-server"),
                    RouteEndpoint::component("echo-client"),
                ],
            })?;

        let _child_instance = builder.build().create().await?;

        receive_echo_server_called.await?;
    }

    receive_echo_client_results.await?;
    Ok(())
}

#[fasync::run_singlethreaded(test)]
async fn echo_servers() -> Result<(), Error> {
    // This test runs a series of echo servers from different sources against a mock echo client,
    // confirming that the client can successfully connect to and use each server.

    let (send_echo_server_called, receive_echo_server_called) = oneshot::channel();
    let sender = Arc::new(Mutex::new(Some(send_echo_server_called)));

    let server_sources = vec![
        ComponentSource::legacy_url(V1_ECHO_SERVER_URL),
        ComponentSource::url(V2_ECHO_SERVER_ABSOLUTE_URL),
        ComponentSource::url(V2_ECHO_SERVER_RELATIVE_URL),
        ComponentSource::mock(move |h| {
            Box::pin(echo_server_mock(DEFAULT_ECHO_STR, sender.clone(), h))
        }),
    ];

    for server_source in server_sources {
        let (send_echo_client_results, receive_echo_client_results) = oneshot::channel();
        let sender = Arc::new(Mutex::new(Some(send_echo_client_results)));

        let mut builder = RealmBuilder::new().await?;
        builder
            .add_component("echo-server", server_source)
            .await?
            .add_eager_component(
                "echo-client",
                ComponentSource::mock(move |h| Box::pin(echo_client_mock(sender.clone(), h))),
            )
            .await?
            .add_route(CapabilityRoute {
                capability: Capability::protocol("fidl.examples.routing.echo.Echo"),
                source: RouteEndpoint::component("echo-server"),
                targets: vec![RouteEndpoint::component("echo-client")],
            })?
            .add_route(CapabilityRoute {
                capability: Capability::protocol("fuchsia.logger.LogSink"),
                source: RouteEndpoint::AboveRoot,
                targets: vec![
                    RouteEndpoint::component("echo-server"),
                    RouteEndpoint::component("echo-client"),
                ],
            })?;

        let _child_instance = builder.build().create().await?;

        receive_echo_client_results.await?;
    }

    receive_echo_server_called.await?;
    Ok(())
}

// A mock echo server implementation, that will crash if it doesn't receive anything other than the
// contents of `expected_echo_str`. It takes and sends a message over `send_echo_server_called`
// once it receives one echo request.
async fn echo_server_mock(
    expected_echo_string: &'static str,
    send_echo_server_called: Arc<Mutex<Option<oneshot::Sender<()>>>>,
    mock_handles: mock::MockHandles,
) -> Result<(), Error> {
    let mut fs = fserver::ServiceFs::new();
    let mut tasks = vec![];
    fs.dir("svc").add_fidl_service(move |mut stream: fecho::EchoRequestStream| {
        let send_echo_server_called = send_echo_server_called.clone();
        tasks.push(fasync::Task::local(async move {
            while let Some(fecho::EchoRequest::EchoString { value, responder }) =
                stream.try_next().await.expect("failed to serve echo service")
            {
                assert_eq!(Some(expected_echo_string.to_string()), value);
                responder.send(value.as_ref().map(|s| &**s)).expect("failed to send echo response");
                send_echo_server_called
                    .lock()
                    .await
                    .take()
                    .unwrap()
                    .send(())
                    .expect("failed to send results");
            }
        }));
    });
    fs.serve_connection(mock_handles.outgoing_dir.into_channel())?;
    fs.collect::<()>().await;
    Ok(())
}

async fn echo_client_mock(
    send_echo_client_results: Arc<Mutex<Option<oneshot::Sender<()>>>>,
    mock_handles: mock::MockHandles,
) -> Result<(), Error> {
    let echo = mock_handles.connect_to_service::<fecho::EchoMarker>()?;
    let out = echo.echo_string(Some(DEFAULT_ECHO_STR)).await?;
    send_echo_client_results.lock().await.take().unwrap().send(()).expect("failed to send results");
    if Some(DEFAULT_ECHO_STR.to_string()) != out {
        return Err(format_err!("unexpected echo result: {:?}", out));
    }
    Ok(())
}
