From d3fe92665bae97c055fa5b5eeed0216a7de72b29 Mon Sep 17 00:00:00 2001 From: Eric Scouten Date: Fri, 8 Jul 2022 16:53:30 -0700 Subject: [PATCH] Refactor test code so it can be excluded from code coverage (#66) Test code is not part of the library as consumed by third parties, so (IMHO) should not be included in coverage reports. Since it's not (yet?) possible to exclude code at function or block level in stable builds, using this approach so that test code can be excluded via [cargo-llvm-cov's exclude by file path option](https://github.com/taiki-e/cargo-llvm-cov#exclude-file-from-coverage). --- .github/workflows/ci.yml | 2 +- src/lib.rs | 4 + .../tests}/fixtures/Purple Square.psd | Bin src/tests/fixtures/mod.rs | 38 +++++++ src/tests/mod.rs | 20 ++++ src/tests/xmp_date_time.rs | 24 ++++ src/tests/xmp_file.rs | 93 +++++++++++++++ src/tests/xmp_meta.rs | 48 ++++++++ src/xmp_date_time.rs | 15 --- src/xmp_file.rs | 107 ------------------ src/xmp_meta.rs | 49 -------- 11 files changed, 228 insertions(+), 172 deletions(-) rename {tests => src/tests}/fixtures/Purple Square.psd (100%) create mode 100644 src/tests/fixtures/mod.rs create mode 100644 src/tests/mod.rs create mode 100644 src/tests/xmp_date_time.rs create mode 100644 src/tests/xmp_file.rs create mode 100644 src/tests/xmp_meta.rs diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index c33bd65..883dc4c 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -36,7 +36,7 @@ jobs: - name: Generate code coverage env: RUST_BACKTRACE: "1" - run: cargo llvm-cov --all-features --lcov --output-path lcov.info + run: cargo llvm-cov --all-features --lcov --ignore-filename-regex tests --output-path lcov.info - name: Upload code coverage results uses: codecov/codecov-action@v3 diff --git a/src/lib.rs b/src/lib.rs index 4f0670b..71aa85d 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -16,6 +16,10 @@ #![doc = include_str!("../README.md")] mod ffi; + +#[cfg(test)] +mod tests; + mod xmp_date_time; mod xmp_file; mod xmp_meta; diff --git a/tests/fixtures/Purple Square.psd b/src/tests/fixtures/Purple Square.psd similarity index 100% rename from tests/fixtures/Purple Square.psd rename to src/tests/fixtures/Purple Square.psd diff --git a/src/tests/fixtures/mod.rs b/src/tests/fixtures/mod.rs new file mode 100644 index 0000000..f85193f --- /dev/null +++ b/src/tests/fixtures/mod.rs @@ -0,0 +1,38 @@ +// Copyright 2022 Adobe. All rights reserved. +// This file is licensed to you under the Apache License, +// Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0) +// or the MIT license (http://opensource.org/licenses/MIT), +// at your option. + +// Unless required by applicable law or agreed to in writing, +// this software is distributed on an "AS IS" BASIS, WITHOUT +// WARRANTIES OR REPRESENTATIONS OF ANY KIND, either express or +// implied. See the LICENSE-MIT and LICENSE-APACHE files for the +// specific language governing permissions and limitations under +// each license. + +use std::{ + env, fs, + path::{Path, PathBuf}, +}; + +pub(crate) fn fixture_path(name: &str) -> String { + let root_dir = &env::var("CARGO_MANIFEST_DIR").unwrap(); + + let mut path = PathBuf::from(root_dir); + path.push("src/tests/fixtures"); + path.push(name); + + assert!(path.exists()); + + path.to_str().unwrap().to_string() +} + +pub(crate) fn temp_copy_of_fixture(tempdir: &Path, name: &str) -> String { + let fixture_src = fixture_path(name); + let fixture_path = Path::join(tempdir, name); + let fixture_copy = fixture_path.as_path(); + + fs::copy(fixture_src, fixture_copy).unwrap(); + fixture_copy.display().to_string() +} diff --git a/src/tests/mod.rs b/src/tests/mod.rs new file mode 100644 index 0000000..f58ac99 --- /dev/null +++ b/src/tests/mod.rs @@ -0,0 +1,20 @@ +// Copyright 2022 Adobe. All rights reserved. +// This file is licensed to you under the Apache License, +// Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0) +// or the MIT license (http://opensource.org/licenses/MIT), +// at your option. + +// Unless required by applicable law or agreed to in writing, +// this software is distributed on an "AS IS" BASIS, WITHOUT +// WARRANTIES OR REPRESENTATIONS OF ANY KIND, either express or +// implied. See the LICENSE-MIT and LICENSE-APACHE files for the +// specific language governing permissions and limitations under +// each license. + +// Tests are grouped under this module so as to avoid +// having the test code itself included in coverage numbers. + +mod fixtures; +mod xmp_date_time; +mod xmp_file; +mod xmp_meta; diff --git a/src/tests/xmp_date_time.rs b/src/tests/xmp_date_time.rs new file mode 100644 index 0000000..6b71267 --- /dev/null +++ b/src/tests/xmp_date_time.rs @@ -0,0 +1,24 @@ +// Copyright 2020 Adobe. All rights reserved. +// This file is licensed to you under the Apache License, +// Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0) +// or the MIT license (http://opensource.org/licenses/MIT), +// at your option. + +// Unless required by applicable law or agreed to in writing, +// this software is distributed on an "AS IS" BASIS, WITHOUT +// WARRANTIES OR REPRESENTATIONS OF ANY KIND, either express or +// implied. See the LICENSE-MIT and LICENSE-APACHE files for the +// specific language governing permissions and limitations under +// each license. + +use crate::XmpDateTime; + +#[test] +fn new_empty() { + let mut _dt = XmpDateTime::new(); +} + +#[test] +fn current() { + let mut _dt = XmpDateTime::current(); +} diff --git a/src/tests/xmp_file.rs b/src/tests/xmp_file.rs new file mode 100644 index 0000000..de804c4 --- /dev/null +++ b/src/tests/xmp_file.rs @@ -0,0 +1,93 @@ +// Copyright 2020 Adobe. All rights reserved. +// This file is licensed to you under the Apache License, +// Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0) +// or the MIT license (http://opensource.org/licenses/MIT), +// at your option. + +// Unless required by applicable law or agreed to in writing, +// this software is distributed on an "AS IS" BASIS, WITHOUT +// WARRANTIES OR REPRESENTATIONS OF ANY KIND, either express or +// implied. See the LICENSE-MIT and LICENSE-APACHE files for the +// specific language governing permissions and limitations under +// each license. + +use std::path::PathBuf; + +use tempfile::tempdir; + +use crate::{tests::fixtures::*, xmp_ns, OpenFileOptions, XmpDateTime, XmpFile, XmpMeta}; + +#[test] +fn open_and_edit_file() { + let tempdir = tempdir().unwrap(); + let purple_square = temp_copy_of_fixture(tempdir.path(), "Purple Square.psd"); + + { + let mut f = XmpFile::new(); + + assert!(f + .open_file( + &purple_square, + OpenFileOptions::default().for_update().use_smart_handler() + ) + .is_ok()); + + let opt_m = f.xmp(); + assert!(opt_m.is_some()); + + XmpMeta::register_namespace("http://purl.org/dc/terms/", "dcterms"); + + let mut m = opt_m.unwrap(); + m.set_property("http://purl.org/dc/terms/", "provenance", "blah"); + + assert!(m.does_property_exist("http://purl.org/dc/terms/", "provenance")); + assert!(!m.does_property_exist("http://purl.org/dc/terms/", "provenancx")); + + if m.does_property_exist(xmp_ns::XMP, "MetadataDate") { + let updated_time = XmpDateTime::current(); + m.set_property_date(xmp_ns::XMP, "MetadataDate", &updated_time); + } + + assert!(f.can_put_xmp(&m)); + f.put_xmp(&m); + + f.close(); + } + + // Let's make sure we actually wrote to the file. + { + let mut f = XmpFile::new(); + + assert!(f + .open_file( + &purple_square, + OpenFileOptions::default().for_update().use_smart_handler() + ) + .is_ok()); + + let m = f.xmp().unwrap(); + + assert_eq!( + m.property("http://purl.org/dc/terms/", "provenance") + .unwrap(), + "blah" + ); + assert_eq!(m.property("http://purl.org/dc/terms/", "provenancx"), None); + } +} + +#[test] +fn open_fail() { + let bad_path = PathBuf::from("doesnotexist.jpg"); + + { + let mut f = XmpFile::new(); + + assert!(f + .open_file( + &bad_path, + OpenFileOptions::default().for_update().use_smart_handler() + ) + .is_err()); + } +} diff --git a/src/tests/xmp_meta.rs b/src/tests/xmp_meta.rs new file mode 100644 index 0000000..faee18e --- /dev/null +++ b/src/tests/xmp_meta.rs @@ -0,0 +1,48 @@ +// Copyright 2020 Adobe. All rights reserved. +// This file is licensed to you under the Apache License, +// Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0) +// or the MIT license (http://opensource.org/licenses/MIT), +// at your option. + +// Unless required by applicable law or agreed to in writing, +// this software is distributed on an "AS IS" BASIS, WITHOUT +// WARRANTIES OR REPRESENTATIONS OF ANY KIND, either express or +// implied. See the LICENSE-MIT and LICENSE-APACHE files for the +// specific language governing permissions and limitations under +// each license. + +use crate::{tests::fixtures::*, XmpMeta}; + +#[test] +fn new_empty() { + let mut _m = XmpMeta::new(); +} + +#[test] +fn from_file() { + let m = XmpMeta::from_file(fixture_path("Purple Square.psd")).unwrap(); + + assert_eq!( + m.property("http://ns.adobe.com/xap/1.0/", "CreatorTool") + .unwrap(), + "Adobe Photoshop CS2 Windows" + ); + + assert_eq!( + m.property("http://ns.adobe.com/photoshop/1.0/", "ICCProfile") + .unwrap(), + "Dell 1905FP Color Profile" + ); + + assert!(m + .property("http://ns.adobe.com/photoshop/1.0/", "ICCProfilx") + .is_none()); +} + +#[test] +fn register_namespace() { + assert_eq!( + XmpMeta::register_namespace("http://purl.org/dc/terms/", "dcterms"), + "dcterms:" + ); +} diff --git a/src/xmp_date_time.rs b/src/xmp_date_time.rs index 5ae5b4f..f34896f 100644 --- a/src/xmp_date_time.rs +++ b/src/xmp_date_time.rs @@ -50,18 +50,3 @@ impl XmpDateTime { } } } - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn new_empty() { - let mut _dt = XmpDateTime::new(); - } - - #[test] - fn current() { - let mut _dt = XmpDateTime::current(); - } -} diff --git a/src/xmp_file.rs b/src/xmp_file.rs index 03aa0b5..a85b0b7 100644 --- a/src/xmp_file.rs +++ b/src/xmp_file.rs @@ -282,110 +282,3 @@ fn path_to_cstr(path: &Path) -> Option { None => None, } } - -#[cfg(test)] -mod tests { - use super::*; - - use std::{ - env, fs, - path::{Path, PathBuf}, - }; - - use tempfile::tempdir; - - use crate::{xmp_ns, XmpDateTime}; - - fn fixture_path(name: &str) -> String { - let root_dir = &env::var("CARGO_MANIFEST_DIR").unwrap(); - - let mut path = PathBuf::from(root_dir); - path.push("tests/fixtures"); - path.push(name); - path.to_str().unwrap().to_string() - } - - fn temp_copy_of_fixture(tempdir: &Path, name: &str) -> String { - let fixture_src = fixture_path(name); - let fixture_path = Path::join(tempdir, name); - let fixture_copy = fixture_path.as_path(); - - fs::copy(fixture_src, fixture_copy).unwrap(); - fixture_copy.display().to_string() - } - - #[test] - fn open_and_edit_file() { - let tempdir = tempdir().unwrap(); - let purple_square = temp_copy_of_fixture(tempdir.path(), "Purple Square.psd"); - - { - let mut f = XmpFile::new(); - - assert!(f - .open_file( - &purple_square, - OpenFileOptions::default().for_update().use_smart_handler() - ) - .is_ok()); - - let opt_m = f.xmp(); - assert!(opt_m.is_some()); - - XmpMeta::register_namespace("http://purl.org/dc/terms/", "dcterms"); - - let mut m = opt_m.unwrap(); - m.set_property("http://purl.org/dc/terms/", "provenance", "blah"); - - assert!(m.does_property_exist("http://purl.org/dc/terms/", "provenance")); - assert!(!m.does_property_exist("http://purl.org/dc/terms/", "provenancx")); - - if m.does_property_exist(xmp_ns::XMP, "MetadataDate") { - let updated_time = XmpDateTime::current(); - m.set_property_date(xmp_ns::XMP, "MetadataDate", &updated_time); - } - - assert!(f.can_put_xmp(&m)); - f.put_xmp(&m); - - f.close(); - } - - // Let's make sure we actually wrote to the file. - { - let mut f = XmpFile::new(); - - assert!(f - .open_file( - &purple_square, - OpenFileOptions::default().for_update().use_smart_handler() - ) - .is_ok()); - - let m = f.xmp().unwrap(); - - assert_eq!( - m.property("http://purl.org/dc/terms/", "provenance") - .unwrap(), - "blah" - ); - assert_eq!(m.property("http://purl.org/dc/terms/", "provenancx"), None); - } - } - - #[test] - fn open_fail() { - let bad_path = PathBuf::from("doesnotexist.jpg"); - - { - let mut f = XmpFile::new(); - - assert!(f - .open_file( - &bad_path, - OpenFileOptions::default().for_update().use_smart_handler() - ) - .is_err()); - } - } -} diff --git a/src/xmp_meta.rs b/src/xmp_meta.rs index 28eed53..80b384a 100644 --- a/src/xmp_meta.rs +++ b/src/xmp_meta.rs @@ -201,52 +201,3 @@ impl XmpMeta { r != 0 } } - -#[cfg(test)] -mod tests { - use super::*; - - use std::{env, path::PathBuf}; - - fn fixture_path(name: &str) -> PathBuf { - let root_dir = &env::var("CARGO_MANIFEST_DIR").unwrap(); - let mut path = PathBuf::from(root_dir); - path.push("tests/fixtures"); - path.push(name); - path - } - - #[test] - fn new_empty() { - let mut _m = XmpMeta::new(); - } - - #[test] - fn from_file() { - let m = XmpMeta::from_file(fixture_path("Purple Square.psd")).unwrap(); - - assert_eq!( - m.property("http://ns.adobe.com/xap/1.0/", "CreatorTool") - .unwrap(), - "Adobe Photoshop CS2 Windows" - ); - - assert_eq!( - m.property("http://ns.adobe.com/photoshop/1.0/", "ICCProfile") - .unwrap(), - "Dell 1905FP Color Profile" - ); - - assert!(m - .property("http://ns.adobe.com/photoshop/1.0/", "ICCProfilx") - .is_none()); - } - - #[test] - fn register_namespace() { - assert_eq!( - XmpMeta::register_namespace("http://purl.org/dc/terms/", "dcterms"), - "dcterms:" - ); - } -}