blob: 3028e7241db8362539a60e51f9c6d62362d9ef57 [file] [log] [blame]
// Copyright 2021 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.
#![cfg(test)]
use {
fuchsia_async as fasync,
fuchsia_pkg_testing::{Package, PackageBuilder, RepositoryBuilder, SystemImageBuilder},
lib::{
EnableDynamicConfig, MountsBuilder, PersistedReposConfig, TestEnvBuilder, EMPTY_REPO_PATH,
},
std::{convert::TryInto, sync::Arc},
};
async fn test_package(name: &str, contents: &str) -> Package {
PackageBuilder::new(name)
.add_resource_at("p/t/o", format!("contents: {}\n", contents).as_bytes())
.build()
.await
.expect("build package")
}
// When a persisted repository configuration is present, and a dynamic repo is configured to
// persist metadata, this test validates that pkg-resolver can resolve a previously fetched package
// across a restart.
#[fasync::run_singlethreaded(test)]
async fn test_resolve_persisted_package_succeeds() {
let pkg_name = "test_resolve_persisted_package_succeeds";
let cache_pkg = test_package(pkg_name, "cache").await;
let system_image_package =
SystemImageBuilder::new().cache_packages(&[&cache_pkg]).build().await;
let mut env = TestEnvBuilder::new()
.mounts(
MountsBuilder::new()
.enable_dynamic_config(EnableDynamicConfig { enable_dynamic_configuration: true })
.persisted_repos_config(PersistedReposConfig {
persisted_repos_dir: "repos".to_string(),
})
.build(),
)
.system_image_and_extra_packages(&system_image_package, &[&cache_pkg])
.build()
.await;
// Resolve the package and ensure it's the cached version.
let pkg_url = format!("fuchsia-pkg://fuchsia.com/{}", pkg_name);
let package_dir = env.resolve_package(&pkg_url).await.unwrap();
cache_pkg.verify_contents(&package_dir).await.expect("to resolve the cached version");
// Put a copy of the package with altered contents in the repo to make sure
// we're getting the one from the cache.
let repo_pkg = test_package(pkg_name, "repo").await;
let repo = Arc::new(
RepositoryBuilder::from_template_dir(EMPTY_REPO_PATH)
.add_package(&system_image_package)
.add_package(&repo_pkg)
.build()
.await
.unwrap(),
);
let served_repository = repo.server().start().unwrap();
let repo_config = served_repository
.make_repo_config_with_persistent_storage("fuchsia-pkg://fuchsia.com".try_into().unwrap());
// System cache fallback is only triggered for fuchsia.com repos.
let () = env.proxies.repo_manager.add(repo_config.into()).await.unwrap().unwrap();
// Try to resolve again, make sure we see the new version.
let package_dir = env.resolve_package(&pkg_url).await.unwrap();
repo_pkg.verify_contents(&package_dir).await.expect("to resolve the new version");
assert!(cache_pkg.verify_contents(&package_dir).await.is_err());
served_repository.stop().await;
env.restart_pkg_resolver().await;
// Try a final resolve. If the persisted repo config works, this must resolve the second
// version of the package that we persisted from when the repo was live.
let package_dir = env.resolve_package(&pkg_url).await.unwrap();
repo_pkg.verify_contents(&package_dir).await.expect("to resolve the new version post-restart");
assert!(cache_pkg.verify_contents(&package_dir).await.is_err());
env.stop().await;
}
// When a persisted repository configuration is present, but lists an empty string, pkg-resolver
// should not persist TUF metadata.
#[fasync::run_singlethreaded(test)]
async fn test_resolve_empty_config_fails() {
let pkg_name = "test_resolve_empty_config_fails";
let cache_pkg = test_package(pkg_name, "cache").await;
let system_image_package =
SystemImageBuilder::new().cache_packages(&[&cache_pkg]).build().await;
let mut env = TestEnvBuilder::new()
.mounts(
MountsBuilder::new()
.enable_dynamic_config(EnableDynamicConfig { enable_dynamic_configuration: true })
.persisted_repos_config(PersistedReposConfig {
persisted_repos_dir: "".to_string(),
})
.build(),
)
.system_image_and_extra_packages(&system_image_package, &[&cache_pkg])
.build()
.await;
// Resolve the package and ensure it's the cached version.
let pkg_url = format!("fuchsia-pkg://fuchsia.com/{}", pkg_name);
let package_dir = env.resolve_package(&pkg_url).await.unwrap();
cache_pkg.verify_contents(&package_dir).await.expect("to resolve the cached version");
// Put a copy of the package with altered contents in the repo to make sure
// we're getting the one from the cache.
let repo_pkg = test_package(pkg_name, "repo").await;
let repo = Arc::new(
RepositoryBuilder::from_template_dir(EMPTY_REPO_PATH)
.add_package(&system_image_package)
.add_package(&repo_pkg)
.build()
.await
.unwrap(),
);
let served_repository = repo.server().start().unwrap();
let repo_config = served_repository
.make_repo_config_with_persistent_storage("fuchsia-pkg://fuchsia.com".try_into().unwrap());
// System cache fallback is only triggered for fuchsia.com repos.
let () = env.proxies.repo_manager.add(repo_config.into()).await.unwrap().unwrap();
// Try to resolve again. We expect to resolve the cached version because the pkg-resolver
// configuration does not allow us to instantiate a persisted repository.
let package_dir = env.resolve_package(&pkg_url).await.unwrap();
cache_pkg.verify_contents(&package_dir).await.expect("to resolve the cached version again");
assert!(repo_pkg.verify_contents(&package_dir).await.is_err());
served_repository.stop().await;
env.restart_pkg_resolver().await;
// Try a final resolve. Because the config lists an empty string, this should result in
// resolving to the cache_pkg.
let package_dir = env.resolve_package(&pkg_url).await.unwrap();
cache_pkg.verify_contents(&package_dir).await.expect("to finally resolve the cached version");
assert!(repo_pkg.verify_contents(&package_dir).await.is_err());
env.stop().await;
}
// When a persisted repo config is present, but dynamic repository configurations are disabled, we
// should not persist the TUF metadata.
#[fasync::run_singlethreaded(test)]
async fn test_resolve_dynamic_disabled_fails() {
let pkg_name = "test_resolve_dynamic_disabled_fails";
let cache_pkg = test_package(pkg_name, "cache").await;
let system_image_package =
SystemImageBuilder::new().cache_packages(&[&cache_pkg]).build().await;
let mut env = TestEnvBuilder::new()
.mounts(
MountsBuilder::new()
.enable_dynamic_config(EnableDynamicConfig { enable_dynamic_configuration: false })
.persisted_repos_config(PersistedReposConfig {
persisted_repos_dir: "repos".to_string(),
})
.build(),
)
.system_image_and_extra_packages(&system_image_package, &[&cache_pkg])
.build()
.await;
// Resolve the package and ensure it's the cached version.
let pkg_url = format!("fuchsia-pkg://fuchsia.com/{}", pkg_name);
let package_dir = env.resolve_package(&pkg_url).await.unwrap();
cache_pkg.verify_contents(&package_dir).await.expect("to resolve the cached version");
// Put a copy of the package with altered contents in the repo to make sure
// we're getting the one from the cache.
let repo_pkg = test_package(pkg_name, "repo").await;
let repo = Arc::new(
RepositoryBuilder::from_template_dir(EMPTY_REPO_PATH)
.add_package(&system_image_package)
.add_package(&repo_pkg)
.build()
.await
.unwrap(),
);
let served_repository = repo.server().start().unwrap();
let repo_config = served_repository
.make_repo_config_with_persistent_storage("fuchsia-pkg://fuchsia.com".try_into().unwrap());
// System cache fallback is only triggered for fuchsia.com repos. This will fail because
// dynamic repository configuration is itself disallowed in this configuration.
let _ = env
.proxies
.repo_manager
.add(repo_config.into())
.await
.unwrap()
.expect_err("can't set repo config");
// Because dynamic repositories cannot be created in this pkg-resolver configuration, we were
// unable to install the repository configuration to persist the repo, and we expect to resolve
// the cached package.
let package_dir = env.resolve_package(&pkg_url).await.unwrap();
cache_pkg.verify_contents(&package_dir).await.expect("to resolve the cached version again");
assert!(repo_pkg.verify_contents(&package_dir).await.is_err());
served_repository.stop().await;
env.restart_pkg_resolver().await;
// Try a final resolve. This will again return the cached version.
let package_dir = env.resolve_package(&pkg_url).await.unwrap();
cache_pkg.verify_contents(&package_dir).await.expect("to finally resolve the cached version");
assert!(repo_pkg.verify_contents(&package_dir).await.is_err());
env.stop().await;
}
// When a persisted repository configuration is not present, we should not persist TUF metadata.
#[fasync::run_singlethreaded(test)]
async fn test_resolve_no_config_fails() {
let pkg_name = "test_resolve_no_config_fails";
let cache_pkg = test_package(pkg_name, "cache").await;
let system_image_package =
SystemImageBuilder::new().cache_packages(&[&cache_pkg]).build().await;
let mut env = TestEnvBuilder::new()
.mounts(
MountsBuilder::new()
.enable_dynamic_config(EnableDynamicConfig { enable_dynamic_configuration: true })
.build(),
)
.system_image_and_extra_packages(&system_image_package, &[&cache_pkg])
.build()
.await;
// Resolve the package and ensure it's the cached version.
let pkg_url = format!("fuchsia-pkg://fuchsia.com/{}", pkg_name);
let package_dir = env.resolve_package(&pkg_url).await.unwrap();
cache_pkg.verify_contents(&package_dir).await.expect("to resolve the cached version");
// Put a copy of the package with altered contents in the repo to make sure
// we're getting the one from the cache.
let repo_pkg = test_package(pkg_name, "repo").await;
let repo = Arc::new(
RepositoryBuilder::from_template_dir(EMPTY_REPO_PATH)
.add_package(&system_image_package)
.add_package(&repo_pkg)
.build()
.await
.unwrap(),
);
let served_repository = repo.server().start().unwrap();
let repo_config = served_repository
.make_repo_config_with_persistent_storage("fuchsia-pkg://fuchsia.com".try_into().unwrap());
// System cache fallback is only triggered for fuchsia.com repos.
let () = env.proxies.repo_manager.add(repo_config.into()).await.unwrap().unwrap();
// Try to resolve again. We expect to resolve the cached version because the pkg-resolver
// configuration does not allow us to instantiate a persisted repository.
let package_dir = env.resolve_package(&pkg_url).await.unwrap();
cache_pkg.verify_contents(&package_dir).await.expect("to resolve the cached version again");
assert!(repo_pkg.verify_contents(&package_dir).await.is_err());
served_repository.stop().await;
env.restart_pkg_resolver().await;
// Try a final resolve. Because the config lists an empty string, this should result in
// resolving to the cache_pkg.
let package_dir = env.resolve_package(&pkg_url).await.unwrap();
cache_pkg.verify_contents(&package_dir).await.expect("to finally resolve the cached version");
assert!(repo_pkg.verify_contents(&package_dir).await.is_err());
env.stop().await;
}