// Copyright 2019 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,
    assert_matches::assert_matches,
    fidl_fuchsia_pkg_ext::RepositoryConfigBuilder,
    fidl_fuchsia_pkg_rewrite_ext::{Rule, RuleConfig},
    fuchsia_async as fasync,
    fuchsia_inspect::{
        assert_data_tree,
        reader::Property,
        testing::{AnyProperty, PropertyAssertion},
        tree_assertion,
    },
    fuchsia_pkg_testing::{serve::responder, PackageBuilder, RepositoryBuilder},
    futures::FutureExt as _,
    lib::MountsBuilder,
    lib::{TestEnvBuilder, EMPTY_REPO_PATH},
    std::sync::Arc,
};

#[fasync::run_singlethreaded(test)]
async fn initial_inspect_state() {
    let env = TestEnvBuilder::new().build().await;
    // Wait for inspect to be created
    env.wait_for_pkg_resolver_to_start().await;

    // Obtain inspect hierarchy
    let hierarchy = env.pkg_resolver_inspect_hierarchy().await;

    assert_data_tree!(
        hierarchy,
        root: {
            rewrite_manager: {
                dynamic_rules: {},
                dynamic_rules_path: format!("{:?}", Some(std::path::Path::new("rewrites.json"))),
                static_rules: {},
                generation: 0u64,
            },
            omaha_channel: {
                tuf_config_name: OptionDebugStringProperty::<String>::None,
                source: OptionDebugStringProperty::<String>::None,
            },
            experiments: {},
            repository_manager: {
                dynamic_configs_path: format!("{:?}", Some(std::path::Path::new("repositories.json"))),
                dynamic_configs: {},
                static_configs: {},
                persisted_repos_dir: "None".to_string(),
                repos: {},
                stats: {
                    mirrors: {}
                },
                tuf_metadata_timeout_seconds: 240u64,
            },
            resolver_service: {
                cache_fallbacks_due_to_not_found: 0u64,
                active_package_resolves: {}
            },
            blob_fetcher: {
                blob_header_timeout_seconds: 30u64,
                blob_body_timeout_seconds: 30u64,
                blob_download_resumption_attempts_limit: 50u64,
                queue: {},
            }
        }
    );
    env.stop().await;
}

#[fasync::run_singlethreaded(test)]
async fn adding_repo_updates_inspect_state() {
    let env = TestEnvBuilder::new().build().await;
    let config = RepositoryConfigBuilder::new("fuchsia-pkg://example.com".parse().unwrap()).build();
    let () = env.proxies.repo_manager.add(config.clone().into()).await.unwrap().unwrap();

    // Obtain inspect service and convert into a node hierarchy.
    let hierarchy = env.pkg_resolver_inspect_hierarchy().await;

    assert_data_tree!(
        hierarchy,
        root: contains {
            repository_manager: contains {
                dynamic_configs: {
                    "example.com": {
                        root_keys: {},
                        mirrors: {},
                    },
                },
            },
        }
    );
    env.stop().await;
}

#[fasync::run_singlethreaded(test)]
async fn resolving_package_updates_inspect_state() {
    let env = TestEnvBuilder::new().build().await;

    let pkg = PackageBuilder::new("just_meta_far").build().await.expect("created pkg");
    let repo = Arc::new(
        RepositoryBuilder::from_template_dir(EMPTY_REPO_PATH)
            .add_package(&pkg)
            .build()
            .await
            .unwrap(),
    );
    let served_repository = repo.server().start().unwrap();
    let repo_url = "fuchsia-pkg://example.com".parse().unwrap();
    let config = served_repository.make_repo_config(repo_url);
    let () = env.proxies.repo_manager.add(config.clone().into()).await.unwrap().unwrap();

    env.resolve_package("fuchsia-pkg://example.com/just_meta_far")
        .await
        .expect("package to resolve");

    assert_data_tree!(
        env.pkg_resolver_inspect_hierarchy().await,
        root: contains {
            repository_manager: contains {
                dynamic_configs: {
                    "example.com": {
                        root_keys: {
                          "0": format!("{:?}", config.root_keys()[0])
                        },
                        mirrors: {
                          "0": {
                            mirror_url: format!("{:?}", config.mirrors()[0].mirror_url()),
                            subscribe: format!("{:?}", config.mirrors()[0].subscribe()),
                            blob_mirror_url: format!("{:?}", config.mirrors()[0].blob_mirror_url())
                          }
                        },
                    }
                },
                repos: {
                    "example.com": {
                        merkles_successfully_resolved_count: 1u64,
                        last_merkle_successfully_resolved_time: OptionDebugStringProperty::Some(
                            AnyProperty
                        ),
                        "updating_tuf_client": {
                            update_check_success_count: 1u64,
                            update_check_failure_count: 0u64,
                            last_update_successfully_checked_time: OptionDebugStringProperty::Some(
                                AnyProperty
                            ),
                            updated_count: 1u64,
                            root_version: 1u64,
                            timestamp_version: 2u64,
                            snapshot_version: 2u64,
                            targets_version: 2u64,
                        }
                    },
                },
                stats: {
                    mirrors: {
                        format!("{}/blobs", served_repository.local_url()) => {
                            network_blips: 0u64,
                            network_rate_limits: 0u64,
                        },
                    },
                },
            },
        }
    );
    env.stop().await;
}

#[fasync::run_singlethreaded(test)]
async fn package_and_blob_queues() {
    // active_package_resolves exports the original and rewritten pkg urls, so we use a rewrite rule
    // and verify that the two exported urls are different.
    let env = TestEnvBuilder::new()
        .mounts(
            MountsBuilder::new()
                .dynamic_rewrite_rules(RuleConfig::Version1(vec![Rule::new(
                    "original.example.com",
                    "rewritten.example.com",
                    "/",
                    "/",
                )
                .unwrap()]))
                .enable_dynamic_config(lib::EnableDynamicConfig {
                    enable_dynamic_configuration: true,
                })
                .build(),
        )
        .build()
        .await;

    let pkg = PackageBuilder::new("just_meta_far").build().await.expect("created pkg");
    let repo = Arc::new(
        RepositoryBuilder::from_template_dir(EMPTY_REPO_PATH)
            .add_package(&pkg)
            .build()
            .await
            .unwrap(),
    );

    let meta_far_blob_path = format!("/blobs/{}", pkg.meta_far_merkle_root());

    let flake_first_attempt = responder::ForPath::new(
        meta_far_blob_path.clone(),
        responder::OverrideNth::new(1, responder::StaticResponseCode::server_error()),
    );

    let (blocking_responder, unblocking_closure_receiver) = responder::BlockResponseBodyOnce::new();
    let block_second_attempt = responder::ForPath::new(
        meta_far_blob_path.clone(),
        responder::OverrideNth::new(2, blocking_responder),
    );

    let served_repository = repo
        .server()
        .response_overrider(flake_first_attempt)
        .response_overrider(block_second_attempt)
        .start()
        .unwrap();
    let () = env
        .proxies
        .repo_manager
        .add(
            served_repository
                .make_repo_config("fuchsia-pkg://rewritten.example.com".parse().unwrap())
                .into(),
        )
        .await
        .unwrap()
        .unwrap();

    let resolve_fut =
        env.resolve_package("fuchsia-pkg://original.example.com/just_meta_far").boxed_local();
    let unblocker = unblocking_closure_receiver.await.unwrap();

    let inspect_state_fut = env
        .wait_for_pkg_resolver_inspect_state(tree_assertion!(
            root: contains {
                blob_fetcher: contains {
                    queue: contains {
                        pkg.meta_far_merkle_root().to_string() => contains {
                            attempts: {
                                "2": contains {
                                    state: "read http body"
                                }
                            }
                        }
                    }
                }
            }
        ))
        .boxed_local();

    // The resolve should not fail, but if it does because of a bug somewhere, awaiting the
    // inspect future would probably hang, and we want the test to fail instead of hang so that
    // the test stdout is printed.
    let resolve_fut = match futures::future::select(resolve_fut, inspect_state_fut).await {
        futures::future::Either::Left((resolve_res, _)) => {
            panic!("the resolve should not have completed: {:?}", resolve_res);
        }
        futures::future::Either::Right(((), resolve_fut)) => resolve_fut,
    };

    assert_data_tree!(
        env.pkg_resolver_inspect_hierarchy().await,
        root: contains {
            blob_fetcher: contains {
                queue: {
                    pkg.meta_far_merkle_root().to_string() => {
                        fetch_ts: AnyProperty,
                        source: "http",
                        mirror: format!("{}{}", served_repository.local_url(), meta_far_blob_path),
                        attempts: {
                            "2": {
                                state: "read http body",
                                state_ts: AnyProperty,
                                expected_size_bytes: 12288u64,
                                bytes_written: 0u64,
                            }
                        }
                    }
                }
            },
            resolver_service: contains {
                active_package_resolves: {
                    "fuchsia-pkg://original.example.com/just_meta_far": {
                        resolve_ts: AnyProperty,
                        rewritten_url: "fuchsia-pkg://rewritten.example.com/just_meta_far",
                    }
                }
            }
        }
    );

    // After completing the resolve there should be no active blob fetches.
    unblocker();
    let _pkg = resolve_fut.await.unwrap();

    assert_data_tree!(
        env.pkg_resolver_inspect_hierarchy().await,
        root: contains {
            blob_fetcher: contains {
                queue: {}
            }
        }
    );

    env.stop().await;
}

#[fasync::run_singlethreaded(test)]
async fn channel_in_vbmeta_appears_in_inspect_state() {
    let repo =
        Arc::new(RepositoryBuilder::from_template_dir(EMPTY_REPO_PATH).build().await.unwrap());
    let served_repository = repo.server().start().unwrap();
    let repo_url = "fuchsia-pkg://test-repo".parse().unwrap();
    let config = served_repository.make_repo_config(repo_url);
    let env = TestEnvBuilder::new()
        .tuf_repo_config_boot_arg("test-repo".to_string())
        .mounts(lib::MountsBuilder::new().static_repository(config.clone()).build())
        .build()
        .await;
    env.wait_for_pkg_resolver_to_start().await;

    let hierarchy = env.pkg_resolver_inspect_hierarchy().await;

    assert_data_tree!(
        hierarchy,
        root: contains {
            rewrite_manager: {
                dynamic_rules: {
                   "0": {
                        path_prefix_replacement: "/",
                        host_match: "fuchsia.com",
                        path_prefix_match: "/",
                        host_replacement: "test-repo",
                    }
                },
                dynamic_rules_path: "None",
                static_rules: {},
                generation: 0u64,
            },
            omaha_channel: {
                tuf_config_name: "test-repo",
                source: "Some(VbMeta)"
            },
        }
    );

    env.stop().await;
}

enum OptionDebugStringProperty<I> {
    Some(I),
    None,
}

impl<I> PropertyAssertion for OptionDebugStringProperty<I>
where
    I: PropertyAssertion,
{
    fn run(&self, actual: &Property) -> Result<(), anyhow::Error> {
        match actual {
            Property::String(name, value) => match self {
                OptionDebugStringProperty::Some(inner) => {
                    const PREFIX: &str = "Some(";
                    const SUFFIX: &str = ")";
                    if !value.starts_with(PREFIX) {
                        return Err(format_err!(
                            r#"expected property to be "Some(...", actual {:?}"#,
                            actual
                        ));
                    }
                    if !value.ends_with(SUFFIX) {
                        return Err(format_err!(
                            r#"expected property to be "...)", actual {:?}"#,
                            actual
                        ));
                    }
                    let inner_value = &value[PREFIX.len()..(value.len() - SUFFIX.len())];
                    inner.run(&Property::String(name.clone(), inner_value.to_owned()))
                }
                OptionDebugStringProperty::None => {
                    if value != "None" {
                        return Err(format_err!(
                            r#"expected property string to be "None", got {:?}"#,
                            actual
                        ));
                    }
                    Ok(())
                }
            },
            _wrong_type => Err(format_err!("expected string property, got {:?}", actual)),
        }
    }
}

#[test]
fn option_debug_string_property() {
    fn make_string_property(value: &str) -> Property {
        Property::String("name".to_owned(), value.to_owned())
    }

    fn dbg<D: std::fmt::Debug>(d: D) -> String {
        format!("{:?}", d)
    }

    // trivial ok
    assert_matches!(
        OptionDebugStringProperty::Some(AnyProperty).run(&make_string_property("Some()")),
        Ok(())
    );
    assert_matches!(
        OptionDebugStringProperty::<AnyProperty>::None.run(&make_string_property("None")),
        Ok(())
    );

    // trivial err
    assert_matches!(
        OptionDebugStringProperty::Some(AnyProperty).run(&make_string_property("None")),
        Err(_)
    );
    assert_matches!(
        OptionDebugStringProperty::Some(AnyProperty).run(&make_string_property("Some(foo")),
        Err(_)
    );
    assert_matches!(
        OptionDebugStringProperty::<AnyProperty>::None.run(&make_string_property("Some()")),
        Err(_)
    );

    // non-empty inner ok
    assert_matches!(
        OptionDebugStringProperty::Some(AnyProperty).run(&make_string_property("Some(value)")),
        Ok(())
    );
    assert_matches!(
        OptionDebugStringProperty::Some(dbg("string"))
            .run(&make_string_property("Some(\"string\")")),
        Ok(())
    );

    // non-empty inner err
    assert_matches!(
        OptionDebugStringProperty::Some(dbg("a")).run(&make_string_property("Some(\"b\")")),
        Err(_)
    );
}
