fidl_fuchsia_update_ext/
commit.rs

1// Copyright 2020 The Fuchsia Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5use anyhow::anyhow;
6use fidl_fuchsia_update::CommitStatusProviderProxy;
7use zx::{self as zx, AsHandleRef};
8
9/// Whether the current system version is pending commit.
10#[derive(Copy, Clone, Debug, PartialEq)]
11pub enum CommitStatus {
12    /// The current system version is pending commit.
13    Pending,
14    /// The current system version is already committed.
15    Committed,
16}
17
18/// Queries the commit status using `provider`.
19pub async fn query_commit_status(
20    provider: &CommitStatusProviderProxy,
21) -> Result<CommitStatus, anyhow::Error> {
22    let event_pair = provider.is_current_system_committed().await?;
23    match event_pair.wait_handle(zx::Signals::USER_0, zx::MonotonicInstant::INFINITE_PAST) {
24        Ok(_) => Ok(CommitStatus::Committed),
25        Err(zx::Status::TIMED_OUT) => Ok(CommitStatus::Pending),
26        Err(status) => Err(anyhow!("unexpected status while asserting signal: {:?}", status)),
27    }
28}
29
30#[cfg(test)]
31mod tests {
32    use super::*;
33    use fidl::endpoints::create_proxy_and_stream;
34    use fidl_fuchsia_update::{CommitStatusProviderMarker, CommitStatusProviderRequest};
35    use fuchsia_async::{self as fasync};
36    use futures::StreamExt;
37    use zx::{HandleBased, Peered};
38
39    // Verifies that query_commit_status returns the expected CommitStatus.
40    #[fasync::run_singlethreaded(test)]
41    async fn test_query_commit_status() {
42        let (proxy, mut stream) = create_proxy_and_stream::<CommitStatusProviderMarker>();
43        let (p0, p1) = zx::EventPair::create();
44
45        let _fidl_server = fasync::Task::local(async move {
46            while let Some(Ok(req)) = stream.next().await {
47                let CommitStatusProviderRequest::IsCurrentSystemCommitted { responder } = req;
48                let () = responder.send(p1.duplicate_handle(zx::Rights::BASIC).unwrap()).unwrap();
49            }
50        });
51
52        // When no signals are asserted, we should report Pending.
53        assert_eq!(query_commit_status(&proxy).await.unwrap(), CommitStatus::Pending);
54
55        // When USER_0 is asserted, we should report Committed.
56        let () = p0.signal_peer(zx::Signals::NONE, zx::Signals::USER_0).unwrap();
57        assert_eq!(query_commit_status(&proxy).await.unwrap(), CommitStatus::Committed,);
58    }
59}