update_package/
name.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
5//! Typesafe wrappers around verifying the name of the update package.
6
7use fidl_fuchsia_io as fio;
8use fuchsia_pkg::{MetaPackage, MetaPackageError};
9use thiserror::Error;
10
11/// An error encountered while verifying the board.
12#[derive(Debug, Error)]
13#[allow(missing_docs)]
14pub enum VerifyNameError {
15    #[error("while opening meta/package")]
16    OpenMetaPackage(#[source] fuchsia_fs::node::OpenError),
17
18    #[error("while reading meta/package")]
19    ReadMetaPackage(#[source] fuchsia_fs::file::ReadError),
20
21    #[error("while reading meta/package")]
22    ParseMetaPackage(#[source] MetaPackageError),
23
24    #[error("expected package name 'update/0' found '{0:?}'")]
25    Invalid(MetaPackage),
26}
27
28pub(crate) async fn verify(proxy: &fio::DirectoryProxy) -> Result<(), VerifyNameError> {
29    let file = fuchsia_fs::directory::open_file(proxy, "meta/package", fio::PERM_READABLE)
30        .await
31        .map_err(VerifyNameError::OpenMetaPackage)?;
32    let contents = fuchsia_fs::file::read(&file).await.map_err(VerifyNameError::ReadMetaPackage)?;
33
34    let expected = MetaPackage::from_name_and_variant_zero("update".parse().unwrap());
35
36    let actual =
37        MetaPackage::deserialize(&mut &contents[..]).map_err(VerifyNameError::ParseMetaPackage)?;
38
39    if expected != actual {
40        return Err(VerifyNameError::Invalid(actual));
41    }
42
43    Ok(())
44}
45
46#[cfg(test)]
47mod tests {
48    use super::*;
49    use crate::TestUpdatePackage;
50    use assert_matches::assert_matches;
51    use fuchsia_pkg::{PackageName, PackageVariant};
52
53    fn make_meta_package(name: &str) -> Vec<u8> {
54        let meta_package = MetaPackage::from_name_and_variant_zero(name.parse().unwrap());
55        let mut bytes = vec![];
56        let () = meta_package.serialize(&mut bytes).unwrap();
57        bytes
58    }
59
60    #[fuchsia_async::run_singlethreaded(test)]
61    async fn allows_expected_name_and_variant() {
62        assert_matches!(
63            TestUpdatePackage::new()
64                .add_file("meta/package", make_meta_package("update"))
65                .await
66                .verify_name()
67                .await,
68            Ok(())
69        );
70    }
71
72    #[fuchsia_async::run_singlethreaded(test)]
73    async fn rejects_unexpected_name() {
74        assert_matches!(
75            TestUpdatePackage::new()
76                .add_file("meta/package", make_meta_package("invalid"))
77                .await
78                .verify_name()
79                .await,
80            Err(VerifyNameError::Invalid(actual))
81                if actual == MetaPackage::from_name_and_variant_zero("invalid".parse().unwrap())
82        );
83    }
84
85    #[fuchsia_async::run_singlethreaded(test)]
86    async fn rejects_unexpected_variant() {
87        let name: PackageName = "invalid".parse().unwrap();
88        let variant: PackageVariant = "42".parse().unwrap();
89        assert_matches!(
90            TestUpdatePackage::new()
91                .add_file("meta/package", br#"{"name":"invalid","version":"42"}"#)
92                .await
93                .verify_name()
94                .await,
95            Err(VerifyNameError::Invalid(actual))
96                if actual.name() == &name && actual.variant() == &variant
97        );
98    }
99    #[fuchsia_async::run_singlethreaded(test)]
100    async fn rejects_invalid_meta_package() {
101        assert_matches!(
102            TestUpdatePackage::new().add_file("meta/package", "bad json").await.verify_name().await,
103            Err(VerifyNameError::ParseMetaPackage(_))
104        );
105    }
106
107    #[fuchsia_async::run_singlethreaded(test)]
108    async fn rejects_missing_meta_package() {
109        assert_matches!(
110            TestUpdatePackage::new().verify_name().await,
111            Err(VerifyNameError::OpenMetaPackage(_)) | Err(VerifyNameError::ReadMetaPackage(_))
112        );
113    }
114}