blob: 7de344b3cad5370b9600894e14db393c2b8ebf1f [file] [log] [blame]
// 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::Error,
fidl::endpoints::{create_proxy, ServerEnd},
fidl_fuchsia_boot::{FactoryItemsMarker, FactoryItemsProxy},
fidl_fuchsia_factory::{
AlphaFactoryStoreProviderMarker, CastCredentialsFactoryStoreProviderMarker,
MiscFactoryStoreProviderMarker, PlayReadyFactoryStoreProviderMarker,
WeaveFactoryStoreProviderMarker, WidevineFactoryStoreProviderMarker,
},
fidl_fuchsia_io as fio, fuchsia_async as fasync,
fuchsia_component::client::connect_to_protocol,
fuchsia_fs::directory::DirentKind,
futures::stream::TryStreamExt,
nom::HexDisplay,
structopt::StructOpt,
};
#[derive(Debug, StructOpt)]
#[structopt(
name = "factoryctl command line tool, version 1.0.0",
about = "Commands to view factory contents"
)]
pub enum Opt {
#[structopt(name = "alpha")]
Alpha(FactoryStoreCmd),
#[structopt(name = "cast")]
Cast(FactoryStoreCmd),
#[structopt(name = "factory-items")]
FactoryItems(FactoryItemsCmd),
#[structopt(name = "misc")]
Misc(FactoryStoreCmd),
#[structopt(name = "playready")]
PlayReady(FactoryStoreCmd),
#[structopt(name = "weave")]
Weave(FactoryStoreCmd),
#[structopt(name = "widevine")]
Widevine(FactoryStoreCmd),
}
#[derive(Debug, StructOpt)]
pub enum FactoryStoreCmd {
#[structopt(name = "list")]
List,
#[structopt(name = "dump")]
Dump { name: String },
}
#[derive(Debug, StructOpt)]
pub enum FactoryItemsCmd {
#[structopt(name = "dump")]
Dump { extra: u32 },
}
const HEX_DISPLAY_CHUNK_SIZE: usize = 16;
/// Walks the given `dir`, appending the full path to every file and returning the list.
async fn list_files(dir_proxy: &fio::DirectoryProxy) -> Result<Vec<String>, Error> {
let mut stream = fuchsia_fs::directory::readdir_recursive(dir_proxy, /*timeout=*/ None);
let mut out = vec![];
while let Some(entry) = stream.try_next().await? {
if entry.kind == DirentKind::File {
out.push(entry.name);
}
}
Ok(out)
}
/// Processes a command from the command line.
async fn process_cmd<F>(cmd: FactoryStoreCmd, mut connect_fn: F) -> Result<Vec<String>, Error>
where
F: FnMut(ServerEnd<fio::DirectoryMarker>) -> (),
{
let (dir_proxy, dir_server_end) = create_proxy::<fio::DirectoryMarker>()?;
connect_fn(dir_server_end);
let out = match cmd {
FactoryStoreCmd::List => list_files(&dir_proxy).await?,
FactoryStoreCmd::Dump { name } => {
let file = fuchsia_fs::directory::open_file_no_describe(
&dir_proxy,
&name,
fio::OpenFlags::RIGHT_READABLE,
)?;
let contents = fuchsia_fs::file::read(&file).await?;
match std::str::from_utf8(&contents) {
Ok(value) => {
vec![value.to_string()]
}
Err(_) => {
vec![contents.to_hex(HEX_DISPLAY_CHUNK_SIZE)]
}
}
}
};
Ok(out)
}
async fn process_factory_items_cmd(
cmd: FactoryItemsCmd,
proxy: FactoryItemsProxy,
) -> Result<Vec<String>, Error> {
let mut out = vec![];
match cmd {
FactoryItemsCmd::Dump { extra } => {
let (vmo_opt, length) = proxy.get(extra).await.unwrap_or_else(|err| {
panic!("Failed to get factory item with extra {}: {:?}", extra, err);
});
match vmo_opt {
Some(ref vmo) if length > 0 => {
let mut buffer = vec![0; length as usize];
vmo.read(&mut buffer, 0)?;
out.push(buffer.to_hex(HEX_DISPLAY_CHUNK_SIZE));
}
_ => out.push("No valid vmo returned".to_string()),
};
out.push(format!("Length={}", length));
}
};
Ok(out)
}
#[fasync::run_singlethreaded]
async fn main() -> Result<(), Error> {
let opt = Opt::from_args();
let out = match opt {
Opt::Alpha(cmd) => {
let proxy = connect_to_protocol::<AlphaFactoryStoreProviderMarker>()
.expect("Failed to connect to AlphaFactoryStoreProvider service");
process_cmd(cmd, move |server_end| proxy.get_factory_store(server_end).unwrap()).await
}
Opt::Cast(cmd) => {
let proxy = connect_to_protocol::<CastCredentialsFactoryStoreProviderMarker>()
.expect("Failed to connect to CastCredentialsFactoryStoreProvider service");
process_cmd(cmd, move |server_end| proxy.get_factory_store(server_end).unwrap()).await
}
Opt::FactoryItems(cmd) => {
let proxy = connect_to_protocol::<FactoryItemsMarker>()
.expect("Failed to connect to FactoryItems service");
process_factory_items_cmd(cmd, proxy).await
}
Opt::Misc(cmd) => {
let proxy = connect_to_protocol::<MiscFactoryStoreProviderMarker>()
.expect("Failed to connect to PlayReadyFactoryStoreProvider service");
process_cmd(cmd, move |server_end| proxy.get_factory_store(server_end).unwrap()).await
}
Opt::PlayReady(cmd) => {
let proxy = connect_to_protocol::<PlayReadyFactoryStoreProviderMarker>()
.expect("Failed to connect to PlayReadyFactoryStoreProvider service");
process_cmd(cmd, move |server_end| proxy.get_factory_store(server_end).unwrap()).await
}
Opt::Weave(cmd) => {
let proxy = connect_to_protocol::<WeaveFactoryStoreProviderMarker>()
.expect("Failed to connect to WeaveFactoryStoreProvider service");
process_cmd(cmd, move |server_end| proxy.get_factory_store(server_end).unwrap()).await
}
Opt::Widevine(cmd) => {
let proxy = connect_to_protocol::<WidevineFactoryStoreProviderMarker>()
.expect("Failed to connect to WidevineFactoryStoreProvider service");
process_cmd(cmd, move |server_end| proxy.get_factory_store(server_end).unwrap()).await
}
}?;
// Write output to stdout.
for l in out {
println!("{}", l)
}
Ok(())
}
#[cfg(test)]
mod tests {
use {
super::*,
fidl_fuchsia_boot::{FactoryItemsRequest, FactoryItemsRequestStream},
fidl_fuchsia_factory::{
AlphaFactoryStoreProviderRequest, AlphaFactoryStoreProviderRequestStream,
CastCredentialsFactoryStoreProviderRequest,
CastCredentialsFactoryStoreProviderRequestStream, MiscFactoryStoreProviderRequest,
MiscFactoryStoreProviderRequestStream, PlayReadyFactoryStoreProviderRequest,
PlayReadyFactoryStoreProviderRequestStream, WeaveFactoryStoreProviderRequest,
WeaveFactoryStoreProviderRequestStream, WidevineFactoryStoreProviderRequest,
WidevineFactoryStoreProviderRequestStream,
},
fuchsia_async as fasync,
fuchsia_component::server as fserver,
fuchsia_component_test::{
Capability, ChildOptions, LocalComponentHandles, RealmBuilder, RealmInstance, Ref,
Route,
},
fuchsia_zircon as zx,
futures::StreamExt,
vfs::{
directory::entry_container::Directory, execution_scope::ExecutionScope,
file::vmo::read_only, tree_builder::TreeBuilder,
},
};
const ALPHA_TXT_FILE_NAME: &str = "txt/alpha.txt";
const CAST_TXT_FILE_NAME: &str = "txt/cast.txt";
const MISC_TXT_FILE_NAME: &str = "misc/misc.txt";
const PLAYREADY_TXT_FILE_NAME: &str = "txt/playready.txt";
const WEAVE_TXT_FILE_NAME: &str = "txt/weave.txt";
const WIDEVINE_TXT_FILE_NAME: &str = "widevine.txt";
const ALPHA_BIN_FILE_NAME: &str = "alpha.bin";
const CAST_BIN_FILE_NAME: &str = "cast.bin";
const MISC_BIN_FILE_NAME: &str = "bin/misc.bin";
const PLAYREADY_BIN_FILE_NAME: &str = "playready/playready.bin";
const WEAVE_BIN_FILE_NAME: &str = "weave.bin";
const WIDEVINE_BIN_FILE_NAME: &str = "widevine.bin";
const ALPHA_TXT_FILE_CONTENTS: &str = "an alpha file";
const CAST_TXT_FILE_CONTENTS: &str = "a cast file";
const MISC_TXT_FILE_CONTENTS: &str = "a misc file";
const PLAYREADY_TXT_FILE_CONTENTS: &str = "a playready file";
const WEAVE_TXT_FILE_CONTENTS: &str = "a weave file";
const WIDEVINE_TXT_FILE_CONTENTS: &str = "a widevine file";
const FACTORY_ITEM_CONTENTS: &[u8] = &[0xf0, 0xe8, 0x65, 0x94];
const ALPHA_BIN_FILE_CONTENTS: &[u8] = &[0xaa, 0xbb, 0xcc, 0xdd];
const CAST_BIN_FILE_CONTENTS: &[u8] = &[0x0, 0x18, 0xF1, 0x6d];
const MISC_BIN_FILE_CONTENTS: &[u8] = &[0x0, 0xf3, 0x17, 0xb6];
const PLAYREADY_BIN_FILE_CONTENTS: &[u8] = &[0x0e, 0xb8, 0x1a, 0xc6];
const WEAVE_BIN_FILE_CONTENTS: &[u8] = &[0xab, 0xcd, 0xef, 0x1];
const WIDEVINE_BIN_FILE_CONTENTS: &[u8] = &[0x0c, 0xee, 0x8a, 0x6f];
enum ServiceMarkers {
AlphaFactoryStore,
CastCredentialsFactoryStore,
MiscFactoryStore,
PlayReadyFactoryStore,
WeaveFactoryStore,
WidevineFactoryStore,
}
fn start_test_dir(
name: &'static str,
contents: &'static str,
name2: &'static str,
contents2: &'static [u8],
) -> Result<fio::DirectoryProxy, Error> {
let mut tree = TreeBuilder::empty_dir();
tree.add_entry(&name.split("/").collect::<Vec<&str>>(), read_only(contents)).unwrap();
tree.add_entry(&name2.split("/").collect::<Vec<&str>>(), read_only(contents2)).unwrap();
let test_dir = tree.build();
let (test_dir_proxy, test_dir_service) =
fidl::endpoints::create_proxy::<fio::DirectoryMarker>()?;
test_dir.open(
ExecutionScope::new(),
fio::OpenFlags::RIGHT_READABLE | fio::OpenFlags::DIRECTORY,
vfs::path::Path::dot(),
test_dir_service.into_channel().into(),
);
Ok(test_dir_proxy)
}
async fn items_mock(handles: LocalComponentHandles) -> Result<(), Error> {
let mut fs = fserver::ServiceFs::new();
let mut tasks = vec![];
fs.dir("svc").add_fidl_service(move |mut stream: FactoryItemsRequestStream| {
tasks.push(fasync::Task::local(async move {
while let Some(FactoryItemsRequest::Get { extra: _, responder }) =
stream.try_next().await.expect("failed to serve factory_items service")
{
let vmo = zx::Vmo::create(FACTORY_ITEM_CONTENTS.len() as u64).unwrap();
vmo.write(&FACTORY_ITEM_CONTENTS, 0).unwrap();
responder.send(Some(vmo), FACTORY_ITEM_CONTENTS.len() as u32).unwrap();
}
}));
});
fs.serve_connection(handles.outgoing_dir)?;
fs.collect::<()>().await;
Ok(())
}
async fn alpha_factory_store_handler(mut stream: AlphaFactoryStoreProviderRequestStream) {
while let Some(AlphaFactoryStoreProviderRequest::GetFactoryStore {
dir,
control_handle: _,
}) = stream.try_next().await.expect("failed to serve alpha_factory service")
{
let proxy = start_test_dir(
ALPHA_TXT_FILE_NAME,
ALPHA_TXT_FILE_CONTENTS,
ALPHA_BIN_FILE_NAME,
ALPHA_BIN_FILE_CONTENTS,
)
.unwrap();
proxy.clone(fio::OpenFlags::RIGHT_READABLE, dir.into_channel().into()).unwrap();
}
}
async fn cast_credentials_factory_store_handler(
mut stream: CastCredentialsFactoryStoreProviderRequestStream,
) {
while let Some(CastCredentialsFactoryStoreProviderRequest::GetFactoryStore {
dir,
control_handle: _,
}) =
stream.try_next().await.expect("failed to serve cast_credentials_factory service")
{
let proxy = start_test_dir(
CAST_TXT_FILE_NAME,
CAST_TXT_FILE_CONTENTS,
CAST_BIN_FILE_NAME,
CAST_BIN_FILE_CONTENTS,
)
.unwrap();
proxy.clone(fio::OpenFlags::RIGHT_READABLE, dir.into_channel().into()).unwrap();
}
}
async fn misc_factory_store_handler(mut stream: MiscFactoryStoreProviderRequestStream) {
while let Some(MiscFactoryStoreProviderRequest::GetFactoryStore {
dir,
control_handle: _,
}) = stream.try_next().await.expect("failed to serve misc_factory service")
{
let proxy = start_test_dir(
MISC_TXT_FILE_NAME,
MISC_TXT_FILE_CONTENTS,
MISC_BIN_FILE_NAME,
MISC_BIN_FILE_CONTENTS,
)
.unwrap();
proxy.clone(fio::OpenFlags::RIGHT_READABLE, dir.into_channel().into()).unwrap();
}
}
async fn play_ready_factory_store_handler(
mut stream: PlayReadyFactoryStoreProviderRequestStream,
) {
while let Some(PlayReadyFactoryStoreProviderRequest::GetFactoryStore {
dir,
control_handle: _,
}) = stream.try_next().await.expect("failed to serve play_ready_factory service")
{
let proxy = start_test_dir(
PLAYREADY_TXT_FILE_NAME,
PLAYREADY_TXT_FILE_CONTENTS,
PLAYREADY_BIN_FILE_NAME,
PLAYREADY_BIN_FILE_CONTENTS,
)
.unwrap();
proxy.clone(fio::OpenFlags::RIGHT_READABLE, dir.into_channel().into()).unwrap();
}
}
async fn weave_factory_store_handler(mut stream: WeaveFactoryStoreProviderRequestStream) {
while let Some(WeaveFactoryStoreProviderRequest::GetFactoryStore {
dir,
control_handle: _,
}) = stream.try_next().await.expect("failed to serve weave_factory service")
{
let proxy = start_test_dir(
WEAVE_TXT_FILE_NAME,
WEAVE_TXT_FILE_CONTENTS,
WEAVE_BIN_FILE_NAME,
WEAVE_BIN_FILE_CONTENTS,
)
.unwrap();
proxy.clone(fio::OpenFlags::RIGHT_READABLE, dir.into_channel().into()).unwrap();
}
}
async fn widevine_factory_store_handler(mut stream: WidevineFactoryStoreProviderRequestStream) {
while let Some(WidevineFactoryStoreProviderRequest::GetFactoryStore {
dir,
control_handle: _,
}) = stream.try_next().await.expect("failed to serve widevine_factory service")
{
let proxy = start_test_dir(
WIDEVINE_TXT_FILE_NAME,
WIDEVINE_TXT_FILE_CONTENTS,
WIDEVINE_BIN_FILE_NAME,
WIDEVINE_BIN_FILE_CONTENTS,
)
.unwrap();
proxy.clone(fio::OpenFlags::RIGHT_READABLE, dir.into_channel().into()).unwrap();
}
}
// The server_mock! macro creates a ServiceFs to run a given mock under a given name.
// Call like:
// server_mock!(foo_mock, FooProviderRequestStream, foo_handler);
//
// It will create service called `foo_mock` that handles `FooProviderRequestStream` requests
// via the `foo_handler` function.
macro_rules! server_mock {
( $func_name:ident, $strm:ty, $hndlr:ident ) => {
async fn $func_name(handles: LocalComponentHandles) -> Result<(), Error> {
let mut fs = fserver::ServiceFs::new();
fs.dir("svc").add_fidl_service(move |stream: $strm| {
fasync::Task::spawn($hndlr(stream)).detach();
});
fs.serve_connection(handles.outgoing_dir)?;
fs.collect::<()>().await;
Ok(())
}
};
}
//----------------------------------------------------------------------------------------------
// Create the mocks.
//
server_mock!(alpha_mock, AlphaFactoryStoreProviderRequestStream, alpha_factory_store_handler);
server_mock!(
cast_mock,
CastCredentialsFactoryStoreProviderRequestStream,
cast_credentials_factory_store_handler
);
server_mock!(misc_mock, MiscFactoryStoreProviderRequestStream, misc_factory_store_handler);
server_mock!(
play_ready_mock,
PlayReadyFactoryStoreProviderRequestStream,
play_ready_factory_store_handler
);
server_mock!(weave_mock, WeaveFactoryStoreProviderRequestStream, weave_factory_store_handler);
server_mock!(
widevine_mock,
WidevineFactoryStoreProviderRequestStream,
widevine_factory_store_handler
);
//
// End creating the mocks.
//----------------------------------------------------------------------------------------------
async fn get_factory_items_output(
realm: &RealmInstance,
cmd: FactoryItemsCmd,
) -> Result<Vec<String>, Error> {
let factory_items_proxy =
realm.root.connect_to_protocol_at_exposed_dir::<FactoryItemsMarker>()?;
process_factory_items_cmd(cmd, factory_items_proxy).await
}
async fn get_factory_store_output(
realm: &RealmInstance,
marker: ServiceMarkers,
cmd: FactoryStoreCmd,
) -> Result<Vec<String>, Error> {
match marker {
ServiceMarkers::AlphaFactoryStore => {
let proxy = realm
.root
.connect_to_protocol_at_exposed_dir::<AlphaFactoryStoreProviderMarker>()?;
process_cmd(cmd, |server_end| proxy.get_factory_store(server_end).unwrap()).await
}
ServiceMarkers::CastCredentialsFactoryStore => {
let proxy = realm
.root
.connect_to_protocol_at_exposed_dir::<CastCredentialsFactoryStoreProviderMarker>()?;
process_cmd(cmd, |server_end| proxy.get_factory_store(server_end).unwrap()).await
}
ServiceMarkers::MiscFactoryStore => {
let proxy = realm
.root
.connect_to_protocol_at_exposed_dir::<MiscFactoryStoreProviderMarker>()?;
process_cmd(cmd, |server_end| proxy.get_factory_store(server_end).unwrap()).await
}
ServiceMarkers::PlayReadyFactoryStore => {
let proxy = realm
.root
.connect_to_protocol_at_exposed_dir::<PlayReadyFactoryStoreProviderMarker>()?;
process_cmd(cmd, |server_end| proxy.get_factory_store(server_end).unwrap()).await
}
ServiceMarkers::WeaveFactoryStore => {
let proxy = realm
.root
.connect_to_protocol_at_exposed_dir::<WeaveFactoryStoreProviderMarker>()?;
process_cmd(cmd, |server_end| proxy.get_factory_store(server_end).unwrap()).await
}
ServiceMarkers::WidevineFactoryStore => {
let proxy = realm
.root
.connect_to_protocol_at_exposed_dir::<WidevineFactoryStoreProviderMarker>()?;
process_cmd(cmd, |server_end| proxy.get_factory_store(server_end).unwrap()).await
}
}
}
// The add_mock! macro adds a given mock component as a local child to the given BuildRealm
// with the given name.
macro_rules! add_mock {
( $builder:ident, $name:literal, $mock:ident ) => {
$builder
.add_local_child(
$name,
move |handles: LocalComponentHandles| Box::pin($mock(handles)),
ChildOptions::new(),
)
.await?
};
}
// The add_route! macro routes the named capability from the given component to the parent.
macro_rules! add_route {
( $builder:ident, $name:literal, $comp:ident ) => {
$builder
.add_route(
Route::new()
.capability(Capability::protocol_by_name($name))
.from(&$comp)
.to(Ref::parent()),
)
.await?
};
}
async fn build_realm() -> Result<RealmInstance, fuchsia_component_test::error::Error> {
let builder = RealmBuilder::new().await?;
// Add the mock components.
let factory_items = add_mock!(builder, "factory_items", items_mock);
let alpha_store = add_mock!(builder, "alpha", alpha_mock);
let cast_store = add_mock!(builder, "cast", cast_mock);
let misc_store = add_mock!(builder, "misc", misc_mock);
let play_ready_store = add_mock!(builder, "play_ready", play_ready_mock);
let weave_store = add_mock!(builder, "weave", weave_mock);
let widevine_store = add_mock!(builder, "widevine", widevine_mock);
// Add the capabilities.
builder
.add_route(
Route::new()
.capability(Capability::protocol_by_name("fuchsia.logger.LogSink"))
.from(Ref::parent())
.to(&factory_items)
.to(&alpha_store)
.to(&cast_store)
.to(&misc_store)
.to(&play_ready_store)
.to(&weave_store)
.to(&widevine_store),
)
.await?;
// Route these capabilities to the parent.
add_route!(builder, "fuchsia.boot.FactoryItems", factory_items);
add_route!(builder, "fuchsia.factory.AlphaFactoryStoreProvider", alpha_store);
add_route!(builder, "fuchsia.factory.CastCredentialsFactoryStoreProvider", cast_store);
add_route!(builder, "fuchsia.factory.MiscFactoryStoreProvider", misc_store);
add_route!(builder, "fuchsia.factory.PlayReadyFactoryStoreProvider", play_ready_store);
add_route!(builder, "fuchsia.factory.WeaveFactoryStoreProvider", weave_store);
add_route!(builder, "fuchsia.factory.WidevineFactoryStoreProvider", widevine_store);
builder.build().await
}
#[fasync::run_singlethreaded(test)]
async fn list_files() -> Result<(), Error> {
let realm = build_realm().await?;
for (marker, bin_name, txt_name) in vec![
(ServiceMarkers::AlphaFactoryStore, ALPHA_BIN_FILE_NAME, ALPHA_TXT_FILE_NAME),
(ServiceMarkers::CastCredentialsFactoryStore, CAST_BIN_FILE_NAME, CAST_TXT_FILE_NAME),
(ServiceMarkers::MiscFactoryStore, MISC_BIN_FILE_NAME, MISC_TXT_FILE_NAME),
(
ServiceMarkers::PlayReadyFactoryStore,
PLAYREADY_BIN_FILE_NAME,
PLAYREADY_TXT_FILE_NAME,
),
(ServiceMarkers::WeaveFactoryStore, WEAVE_BIN_FILE_NAME, WEAVE_TXT_FILE_NAME),
(ServiceMarkers::WidevineFactoryStore, WIDEVINE_BIN_FILE_NAME, WIDEVINE_TXT_FILE_NAME),
] {
let out = get_factory_store_output(&realm, marker, FactoryStoreCmd::List {}).await?;
assert_eq!(out.len(), 2);
assert_eq!(out[0], bin_name.to_string());
assert_eq!(out[1], txt_name.to_string());
}
Ok(())
}
#[fasync::run_singlethreaded(test)]
async fn dump_text_files() -> Result<(), Error> {
let realm = build_realm().await?;
for (marker, name, contents) in vec![
(ServiceMarkers::AlphaFactoryStore, ALPHA_TXT_FILE_NAME, ALPHA_TXT_FILE_CONTENTS),
(
ServiceMarkers::CastCredentialsFactoryStore,
CAST_TXT_FILE_NAME,
CAST_TXT_FILE_CONTENTS,
),
(ServiceMarkers::MiscFactoryStore, MISC_TXT_FILE_NAME, MISC_TXT_FILE_CONTENTS),
(
ServiceMarkers::PlayReadyFactoryStore,
PLAYREADY_TXT_FILE_NAME,
PLAYREADY_TXT_FILE_CONTENTS,
),
(ServiceMarkers::WeaveFactoryStore, WEAVE_TXT_FILE_NAME, WEAVE_TXT_FILE_CONTENTS),
(
ServiceMarkers::WidevineFactoryStore,
WIDEVINE_TXT_FILE_NAME,
WIDEVINE_TXT_FILE_CONTENTS,
),
] {
let out = get_factory_store_output(
&realm,
marker,
FactoryStoreCmd::Dump { name: name.to_string() },
)
.await?;
assert_eq!(out.len(), 1);
assert!(out[0].contains(contents));
}
Ok(())
}
#[fasync::run_singlethreaded(test)]
async fn dump_binary_files() -> Result<(), Error> {
let realm = build_realm().await?;
for (marker, name, contents) in vec![
(ServiceMarkers::AlphaFactoryStore, ALPHA_BIN_FILE_NAME, ALPHA_BIN_FILE_CONTENTS),
(
ServiceMarkers::CastCredentialsFactoryStore,
CAST_BIN_FILE_NAME,
CAST_BIN_FILE_CONTENTS,
),
(ServiceMarkers::MiscFactoryStore, MISC_BIN_FILE_NAME, MISC_BIN_FILE_CONTENTS),
(
ServiceMarkers::PlayReadyFactoryStore,
PLAYREADY_BIN_FILE_NAME,
PLAYREADY_BIN_FILE_CONTENTS,
),
(ServiceMarkers::WeaveFactoryStore, WEAVE_BIN_FILE_NAME, WEAVE_BIN_FILE_CONTENTS),
(
ServiceMarkers::WidevineFactoryStore,
WIDEVINE_BIN_FILE_NAME,
WIDEVINE_BIN_FILE_CONTENTS,
),
] {
let out = get_factory_store_output(
&realm,
marker,
FactoryStoreCmd::Dump { name: name.to_string() },
)
.await?;
assert_eq!(out.len(), 1);
assert!(out[0].contains("00000000"));
assert!(out[0].contains(&contents.to_hex(HEX_DISPLAY_CHUNK_SIZE)));
}
Ok(())
}
#[fasync::run_singlethreaded(test)]
async fn dump_factory_item() -> Result<(), Error> {
let realm = build_realm().await?;
let out = get_factory_items_output(&realm, FactoryItemsCmd::Dump { extra: 0 }).await?;
assert_eq!(out.len(), 2);
assert!(out[0].contains("00000000"));
assert!(out[0].contains(&FACTORY_ITEM_CONTENTS.to_hex(HEX_DISPLAY_CHUNK_SIZE)));
assert!(out[1].contains("Length=4"));
Ok(())
}
}