// 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 {
    super::*,
    fidl_fuchsia_update_installer_ext::{start_update, StateId},
    pretty_assertions::assert_eq,
};

#[fasync::run_singlethreaded(test)]
async fn reboot_controller_detach_causes_deferred_reboot() {
    let env = TestEnv::builder().build().await;

    env.resolver
        .register_package("update", "upd4t3")
        .add_file("packages.json", make_packages_json([]))
        .add_file("epoch.json", make_epoch_json(SOURCE_EPOCH))
        .add_file("zbi", "fake zbi");

    // Start the system update.
    let (reboot_proxy, server_end) = fidl::endpoints::create_proxy().unwrap();
    let attempt = start_update(
        &UPDATE_PKG_URL.parse().unwrap(),
        default_options(),
        &env.installer_proxy(),
        Some(server_end),
    )
    .await
    .unwrap();

    // When we call detach, we should observe DeferReboot at the end.
    let () = reboot_proxy.detach().unwrap();
    assert_eq!(
        attempt.map(|res| res.unwrap()).collect::<Vec<_>>().await.last().unwrap().id(),
        StateId::DeferReboot
    );

    // Verify we didn't make a reboot call.
    assert!(!env.take_interactions().contains(&Reboot));
}

#[fasync::run_singlethreaded(test)]
async fn reboot_controller_unblock_causes_reboot() {
    let env = TestEnv::builder().build().await;

    env.resolver
        .register_package("update", "upd4t3")
        .add_file("packages.json", make_packages_json([]))
        .add_file("epoch.json", make_epoch_json(SOURCE_EPOCH))
        .add_file("zbi", "fake zbi");

    // Start the system update.
    let (reboot_proxy, server_end) = fidl::endpoints::create_proxy().unwrap();
    let attempt = start_update(
        &UPDATE_PKG_URL.parse().unwrap(),
        default_options(),
        &env.installer_proxy(),
        Some(server_end),
    )
    .await
    .unwrap();

    // When we call unblock, we should observe Reboot at the end.
    let () = reboot_proxy.unblock().unwrap();
    assert_eq!(
        attempt.map(|res| res.unwrap()).collect::<Vec<_>>().await.last().unwrap().id(),
        StateId::Reboot
    );

    // Verify we made a reboot call.
    assert_eq!(env.take_interactions().last().unwrap(), &Reboot);
}

#[fasync::run_singlethreaded(test)]
async fn reboot_controller_dropped_causes_reboot() {
    let env = TestEnv::builder().build().await;

    env.resolver
        .register_package("update", "upd4t3")
        .add_file("packages.json", make_packages_json([]))
        .add_file("epoch.json", make_epoch_json(SOURCE_EPOCH))
        .add_file("zbi", "fake zbi");

    // Start the system update.
    let (reboot_proxy, server_end) = fidl::endpoints::create_proxy().unwrap();
    let attempt = start_update(
        &UPDATE_PKG_URL.parse().unwrap(),
        default_options(),
        &env.installer_proxy(),
        Some(server_end),
    )
    .await
    .unwrap();

    // When we drop the reboot controller, we should observe Reboot at the end.
    drop(reboot_proxy);
    assert_eq!(
        attempt.map(|res| res.unwrap()).collect::<Vec<_>>().await.last().unwrap().id(),
        StateId::Reboot
    );

    // Verify we made a reboot call.
    assert_eq!(env.take_interactions().last().unwrap(), &Reboot);
}
