blob: 5ccefb114da1bd8dd366e46152009fe3fc5499df [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 sdk_metadata::JsonObject;
use crate::app::{Error, Result};
use crate::file_provider::{merge_files, FileProvider};
use crate::tarball::{InputTarball, OutputTarball, TarballContent};
/// Merges an element that should not have any variation.
pub fn merge_immutable_element<M, F, B, C, O>(
meta_path: &str, base: &B, complement: &C, output: &mut O,
) -> Result<()>
where
M: FileProvider + Eq + JsonObject,
F: TarballContent,
B: InputTarball<F>,
C: InputTarball<F>,
O: OutputTarball<F>,
{
let base_meta: M = base.get_metadata::<M>(meta_path)?;
let complement_meta: M = complement.get_metadata::<M>(meta_path)?;
merge_files(&base_meta, base, &complement_meta, complement, output)?;
if base_meta != complement_meta {
return Err(Error::MetaFilesDiffer)?;
}
output.write_json(meta_path, &base_meta)?;
Ok(())
}
#[cfg(test)]
#[macro_use]
pub mod tests {
use crate::testing::MockInputTarball;
pub fn create_source_tarball(meta: &str, data: &str, files: &Vec<&str>) -> MockInputTarball {
let result = MockInputTarball::new();
result.add(meta, data);
for file in files {
let content = format!("I am {}", file);
result.add(file, &content);
}
result
}
/// Generates a test verifying that an immutable element merges properly.
macro_rules! test_merge_immutable_success {
(
name = $name:ident,
merge = $merge:ident,
meta = $meta:expr,
data = $data:expr,
files = [$( $file:expr ),* $(,)?],
) => {
#[test]
pub fn $name() {
use crate::testing::MockOutputTarball;
let meta = $meta;
let data = $data;
let files: Vec<&str> = vec![$($file),*];
let base = $crate::immutable::tests::create_source_tarball(meta, &data, &files);
let complement = base.clone();
let mut output = MockOutputTarball::new();
$merge(meta, &base, &complement, &mut output).expect("Merge should not fail!");
output.assert_has_file(meta);
for file in files {
output.assert_has_file(file);
}
}
};
}
/// Generates a test verifying that different versions of an immutable element fail to merge.
macro_rules! test_merge_immutable_failure {
(
name = $name:ident,
merge = $merge:ident,
meta = $meta:expr,
base_data = $base_data:expr,
base_files = [$( $base_file:expr ),* $(,)?],
complement_data = $complement_data:expr,
complement_files = [$( $complement_file:expr ),* $(,)?],
) => {
#[test]
pub fn $name() {
use crate::testing::MockOutputTarball;
let base_files: Vec<&str> = vec![$($base_file),*];
let complement_files: Vec<&str> = vec![$($complement_file),*];
let meta = $meta;
let base = $crate::immutable::tests::create_source_tarball(meta, &$base_data, &base_files);
let complement = $crate::immutable::tests::create_source_tarball(meta, &$complement_data, &complement_files);
let mut output = MockOutputTarball::new();
assert!(
$merge(meta, &base, &complement, &mut output).is_err(),
"Merge should have failed due to metadata mismatch"
);
}
};
}
// And now, some actual tests of the merge_immutable_element method.
use sdk_metadata::testing::TestObject;
use crate::app::Result;
use crate::file_provider::FileProvider;
use crate::tarball::{InputTarball, OutputTarball};
use super::*;
impl FileProvider for TestObject {
fn get_common_files(&self) -> Vec<String> {
self.files.clone()
}
}
fn merge_foobar(
meta_path: &str, base: &impl InputTarball<String>, complement: &impl InputTarball<String>,
output: &mut impl OutputTarball<String>,
) -> Result<()> {
merge_immutable_element::<TestObject, _, _, _, _>(meta_path, base, complement, output)
}
test_merge_immutable_success! {
name = test_merge,
merge = merge_foobar,
meta = "foobar.json",
data = r#"
{
"name": "foobar",
"files": [
"a/file.ext"
]
}
"#,
files = [
"a/file.ext",
],
}
test_merge_immutable_failure! {
name = test_merge_failed,
merge = merge_foobar,
meta = "foobar.json",
base_data = r#"
{
"name": "foobar",
"files": [
"a/file.ext"
]
}
"#,
base_files = [
"a/file.ext",
],
complement_data = r#"
{
"name": "foobar",
"files": [
"a/file.ext",
"another/file.ext"
]
}
"#,
complement_files = [
"a/file.ext",
"another/file.ext",
],
}
}