Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Implement an Unknown variant in the artifact locations #2320

Merged
merged 6 commits into from
Feb 21, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion mithril-client-cli/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "mithril-client-cli"
version = "0.11.1"
version = "0.11.2"
description = "A Mithril Client"
authors = { workspace = true }
edition = { workspace = true }
Expand Down
159 changes: 101 additions & 58 deletions mithril-client-cli/src/commands/cardano_db_v2/show.rs
Original file line number Diff line number Diff line change
Expand Up @@ -85,21 +85,17 @@ impl CardanoDbShowCommand {
],
];

for digest_location in digest_location_rows(&cardano_db_message.locations.digests) {
cardano_db_table.push(digest_location);
}

for immutables_location in
immutables_location_rows(&cardano_db_message.locations.immutables)
{
cardano_db_table.push(immutables_location);
}

for ancillary_location in
ancillary_location_rows(&cardano_db_message.locations.ancillary)
{
cardano_db_table.push(ancillary_location);
}
cardano_db_table.append(&mut digest_location_rows(
&cardano_db_message.locations.digests,
));

cardano_db_table.append(&mut immutables_location_rows(
&cardano_db_message.locations.immutables,
));

cardano_db_table.append(&mut ancillary_location_rows(
&cardano_db_message.locations.ancillary,
));

cardano_db_table.push(vec![
"Created".cell(),
Expand All @@ -117,61 +113,60 @@ impl CardanoDbShowCommand {
}
}

fn digest_location_iter(locations: &[DigestLocation]) -> impl Iterator<Item = String> + use<'_> {
locations.iter().filter_map(|location| match location {
DigestLocation::Aggregator { uri } => Some(format!("Aggregator, uri: \"{}\"", uri)),
DigestLocation::CloudStorage { uri } => Some(format!("CloudStorage, uri: \"{}\"", uri)),
DigestLocation::Unknown => None,
})
}

fn digest_location_rows(locations: &[DigestLocation]) -> Vec<Vec<CellStruct>> {
let location_name = "Digest location";
format_location_rows("Digest location", digest_location_iter(locations))
}

locations
.iter()
.enumerate()
.map(|(index, location)| match location {
DigestLocation::Aggregator { uri } => {
vec![
format!("{location_name} ({})", index + 1).cell(),
format!("Aggregator, uri: \"{}\"", uri).cell(),
]
}
DigestLocation::CloudStorage { uri } => {
vec![
format!("{location_name} ({})", index + 1).cell(),
format!("CloudStorage, uri: \"{}\"", uri).cell(),
]
}
})
.collect()
fn immutables_location_iter(
locations: &[ImmutablesLocation],
) -> impl Iterator<Item = String> + use<'_> {
locations.iter().filter_map(|location| match location {
ImmutablesLocation::CloudStorage { uri } => match uri {
MultiFilesUri::Template(template_uri) => Some(format!(
"CloudStorage, template_uri: \"{}\"",
template_uri.0
)),
},
ImmutablesLocation::Unknown => None,
})
}

fn immutables_location_rows(locations: &[ImmutablesLocation]) -> Vec<Vec<CellStruct>> {
let location_name = "Immutables location";
format_location_rows("Immutables location", immutables_location_iter(locations))
}

locations
.iter()
.enumerate()
.map(|(index, location)| match location {
ImmutablesLocation::CloudStorage { uri } => match uri {
MultiFilesUri::Template(template_uri) => {
vec![
format!("{location_name} ({})", index + 1).cell(),
format!("CloudStorage, template_uri: \"{}\"", template_uri.0).cell(),
]
}
},
})
.collect()
fn ancillary_location_iter(
locations: &[AncillaryLocation],
) -> impl Iterator<Item = String> + use<'_> {
locations.iter().filter_map(|location| match location {
AncillaryLocation::CloudStorage { uri } => Some(format!("CloudStorage, uri: \"{uri}\"")),
AncillaryLocation::Unknown => None,
})
}

fn ancillary_location_rows(locations: &[AncillaryLocation]) -> Vec<Vec<CellStruct>> {
let location_name = "Ancillary location";
format_location_rows("Ancillary location", ancillary_location_iter(locations))
}

fn format_location_rows(
location_name: &str,
locations: impl Iterator<Item = String>,
) -> Vec<Vec<CellStruct>> {
locations
.iter()
.enumerate()
.map(|(index, location)| match location {
AncillaryLocation::CloudStorage { uri } => {
vec![
format!("{location_name} ({})", index + 1).cell(),
format!("CloudStorage, uri: \"{}\"", uri).cell(),
]
}
.map(|(index, cell_content)| {
vec![
format!("{location_name} ({})", index + 1).cell(),
cell_content.cell(),
]
})
.collect()
}
Expand Down Expand Up @@ -212,6 +207,22 @@ mod tests {
assert!(rows_rendered.contains("Aggregator, uri: \"http://aggregator.net/\""));
}

#[test]
fn digest_location_rows_display_and_count_only_known_location() {
let locations = vec![
DigestLocation::Unknown,
DigestLocation::CloudStorage {
uri: "http://cloudstorage.com/".to_string(),
},
];

let rows = digest_location_rows(&locations);
assert_eq!(1, rows.len());

let rows_rendered = rows.table().display().unwrap().to_string();
assert!(rows_rendered.contains("Digest location (1)"));
}

#[test]
fn immutables_location_rows_when_no_uri_found() {
let rows = immutables_location_rows(&[]);
Expand Down Expand Up @@ -243,6 +254,22 @@ mod tests {
assert!(rows_rendered.contains("CloudStorage, template_uri: \"http://cloudstorage2.com/\""));
}

#[test]
fn immutables_location_row_display_and_count_only_known_location() {
let locations = vec![
ImmutablesLocation::Unknown {},
ImmutablesLocation::CloudStorage {
uri: MultiFilesUri::Template(TemplateUri("http://cloudstorage2.com/".to_string())),
},
];

let rows = immutables_location_rows(&locations);
assert_eq!(1, rows.len());

let rows_rendered = rows.table().display().unwrap().to_string();
assert!(rows_rendered.contains("Immutables location (1)"));
}

#[test]
fn ancillary_location_rows_when_no_uri_found() {
let rows = ancillary_location_rows(&[]);
Expand Down Expand Up @@ -273,4 +300,20 @@ mod tests {
assert!(rows_rendered.contains("Ancillary location (2)"));
assert!(rows_rendered.contains("CloudStorage, uri: \"http://cloudstorage2.com/\""));
}

#[test]
fn ancillary_location_rows_display_and_count_only_known_location() {
let locations = vec![
AncillaryLocation::Unknown {},
AncillaryLocation::CloudStorage {
uri: "http://cloudstorage2.com/".to_string(),
},
];

let rows = ancillary_location_rows(&locations);
assert_eq!(1, rows.len());

let rows_rendered = rows.table().display().unwrap().to_string();
assert!(rows_rendered.contains("Ancillary location (1)"));
}
}
2 changes: 1 addition & 1 deletion mithril-client/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "mithril-client"
version = "0.11.3"
version = "0.11.4"
description = "Mithril client library"
authors = { workspace = true }
edition = { workspace = true }
Expand Down
17 changes: 17 additions & 0 deletions mithril-client/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
args = `arg="$(filter-out $@,$(MAKECMDGOALS))" && echo $${arg:-${1}}`

CARGO = cargo
FEATURES := fs unstable

all: test build

Expand All @@ -25,3 +26,19 @@ clean:

doc:
${CARGO} doc --no-deps --open --features full

# Compute the powerset of all the given features and save it to a file
.feature-sets:
powerset() { [ $$# -eq 0 ] && echo || (shift; powerset "$$@") | while read r ; do echo "$$1 $$r"; echo "$$r"; done };\
powerset $$(echo "$(FEATURES)") > .features-sets

check-all-features-set: .feature-sets
# Read the file to run cargo clippy on all those features sets
cat .features-sets | while read features_set; do \
echo "Clippy client with feature '$$features_set''"; \
${CARGO} clippy -p mithril-client --features "$$features_set"; \
done
echo "Clippy client without features"; \
${CARGO} clippy -p mithril-client

rm .features-sets
47 changes: 40 additions & 7 deletions mithril-client/src/cardano_database_client/api.rs
Original file line number Diff line number Diff line change
Expand Up @@ -115,31 +115,34 @@ impl CardanoDatabaseClient {
pub(crate) mod test_dependency_injector {
use super::*;

use crate::{
aggregator_client::MockAggregatorClient,
feedback::FeedbackReceiver,
file_downloader::{FileDownloader, MockFileDownloaderBuilder},
test_utils,
};
use crate::aggregator_client::MockAggregatorClient;
#[cfg(feature = "fs")]
use crate::file_downloader::{FileDownloader, MockFileDownloaderBuilder};
#[cfg(feature = "fs")]
use crate::{feedback::FeedbackReceiver, test_utils};

/// Dependency injector for `CardanoDatabaseClient` for testing purposes.
pub(crate) struct CardanoDatabaseClientDependencyInjector {
aggregator_client: MockAggregatorClient,
#[cfg(feature = "fs")]
http_file_downloader: Arc<dyn FileDownloader>,
#[cfg(feature = "fs")]
feedback_receivers: Vec<Arc<dyn FeedbackReceiver>>,
}

impl CardanoDatabaseClientDependencyInjector {
pub(crate) fn new() -> Self {
Self {
aggregator_client: MockAggregatorClient::new(),
#[cfg(feature = "fs")]
http_file_downloader: Arc::new(
MockFileDownloaderBuilder::default()
.with_compression(None)
.with_success()
.with_times(0)
.build(),
),
#[cfg(feature = "fs")]
feedback_receivers: vec![],
}
}
Expand All @@ -153,6 +156,7 @@ pub(crate) mod test_dependency_injector {
self
}

#[cfg(feature = "fs")]
pub(crate) fn with_http_file_downloader(
self,
http_file_downloader: Arc<dyn FileDownloader>,
Expand All @@ -163,6 +167,7 @@ pub(crate) mod test_dependency_injector {
}
}

#[cfg(feature = "fs")]
pub(crate) fn with_feedback_receivers(
self,
feedback_receivers: &[Arc<dyn FeedbackReceiver>],
Expand All @@ -173,6 +178,7 @@ pub(crate) mod test_dependency_injector {
}
}

#[cfg(feature = "fs")]
pub(crate) fn build_cardano_database_client(self) -> CardanoDatabaseClient {
CardanoDatabaseClient::new(
Arc::new(self.aggregator_client),
Expand All @@ -181,15 +187,23 @@ pub(crate) mod test_dependency_injector {
test_utils::test_logger(),
)
}

#[cfg(not(feature = "fs"))]
pub(crate) fn build_cardano_database_client(self) -> CardanoDatabaseClient {
CardanoDatabaseClient::new(Arc::new(self.aggregator_client))
}
}

mod tests {
use mockall::predicate;

use crate::{aggregator_client::AggregatorRequest, feedback::StackFeedbackReceiver};
use crate::aggregator_client::AggregatorRequest;
#[cfg(feature = "fs")]
use crate::feedback::StackFeedbackReceiver;

use super::*;

#[cfg(feature = "fs")]
#[test]
fn test_cardano_database_client_dependency_injector_builds() {
let _ = CardanoDatabaseClientDependencyInjector::new()
Expand All @@ -214,5 +228,24 @@ pub(crate) mod test_dependency_injector {
.with_feedback_receivers(&[Arc::new(StackFeedbackReceiver::new())])
.build_cardano_database_client();
}

#[cfg(not(feature = "fs"))]
#[test]
fn test_cardano_database_client_dependency_injector_builds() {
let _ = CardanoDatabaseClientDependencyInjector::new()
.with_aggregator_client_mock_config(|http_client| {
let message = vec![CardanoDatabaseSnapshotListItem {
hash: "hash-123".to_string(),
..CardanoDatabaseSnapshotListItem::dummy()
}];
http_client
.expect_get_content()
.with(predicate::eq(
AggregatorRequest::ListCardanoDatabaseSnapshots,
))
.return_once(move |_| Ok(serde_json::to_string(&message).unwrap()));
})
.build_cardano_database_client();
}
}
}
Loading
Loading