diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index fc4ae82088..6749f22c9f 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -96,6 +96,34 @@ jobs: command: test args: --release --all --features ci_skip --no-fail-fast + test-package: + name: Test Package + runs-on: ubuntu-latest + strategy: + matrix: + rust: + - stable + - nightly + steps: + - name: Checkout + uses: actions/checkout@v2 + + - name: Install Rust (${{ matrix.rust }}) + uses: actions-rs/toolchain@v1 + with: + profile: minimal + toolchain: ${{ matrix.rust }} + override: true + + - name: Install cargo-all-features + run: | + cargo install cargo-all-features + + - name: Test + run: | + cd package + cargo test-all-features + codecov: name: Code Coverage runs-on: ubuntu-latest diff --git a/examples/fibonacci/Leo.toml b/examples/fibonacci/Leo.toml index 85cc1b1916..74409f8b14 100644 --- a/examples/fibonacci/Leo.toml +++ b/examples/fibonacci/Leo.toml @@ -1,4 +1,4 @@ -[package] +[project] name = "fibonacci" version = "0.1.0" description = "Returns a fibonnaci sequence" diff --git a/examples/fibonacci/README.md b/examples/fibonacci/README.md new file mode 100644 index 0000000000..be8c859831 --- /dev/null +++ b/examples/fibonacci/README.md @@ -0,0 +1 @@ +# fibonacci diff --git a/examples/hello-world/Leo.toml b/examples/hello-world/Leo.toml index b3cde2b151..7255a801f9 100644 --- a/examples/hello-world/Leo.toml +++ b/examples/hello-world/Leo.toml @@ -1,4 +1,4 @@ -[package] +[project] name = "hello-world" version = "0.1.0" description = "Returns the sum of two u32 integers" diff --git a/examples/hello-world/README.md b/examples/hello-world/README.md new file mode 100644 index 0000000000..1534e6cdf3 --- /dev/null +++ b/examples/hello-world/README.md @@ -0,0 +1 @@ +# hello-world diff --git a/examples/pedersen-hash/Leo.toml b/examples/pedersen-hash/Leo.toml index 13b7d80257..5076066fa2 100644 --- a/examples/pedersen-hash/Leo.toml +++ b/examples/pedersen-hash/Leo.toml @@ -1,4 +1,4 @@ -[package] +[project] name = "pedersen-hash" version = "0.1.0" description = "A 256bit hash function" diff --git a/examples/pedersen-hash/README.md b/examples/pedersen-hash/README.md new file mode 100644 index 0000000000..341d98f707 --- /dev/null +++ b/examples/pedersen-hash/README.md @@ -0,0 +1 @@ +# pedersen-hash diff --git a/examples/square-root/Leo.toml b/examples/square-root/Leo.toml index 00235bcba1..9717d86062 100644 --- a/examples/square-root/Leo.toml +++ b/examples/square-root/Leo.toml @@ -1,4 +1,4 @@ -[package] +[project] name = "square-root" version = "0.1.0" description = "prove knowledge of the square root `a` of a number `b`" diff --git a/examples/square-root/README.md b/examples/square-root/README.md new file mode 100644 index 0000000000..8536c68b02 --- /dev/null +++ b/examples/square-root/README.md @@ -0,0 +1 @@ +# square-root diff --git a/package/Cargo.toml b/package/Cargo.toml index 5edfb9df1f..54804fb86b 100644 --- a/package/Cargo.toml +++ b/package/Cargo.toml @@ -41,3 +41,9 @@ version = "0.5" [dev-dependencies.lazy_static] version = "1.3.0" + +[features] +default = [ "manifest_refactors" ] +manifest_refactors = [ "manifest_refactor_project", "manifest_refactor_remote" ] +manifest_refactor_project = [ ] +manifest_refactor_remote = [ ] diff --git a/package/src/root/manifest.rs b/package/src/root/manifest.rs index bb33dd63ac..485516c06d 100644 --- a/package/src/root/manifest.rs +++ b/package/src/root/manifest.rs @@ -33,14 +33,14 @@ pub struct Remote { #[derive(Deserialize)] pub struct Manifest { - pub package: Package, + pub project: Package, pub remote: Option, } impl Manifest { pub fn new(package_name: &str) -> Self { Self { - package: Package::new(package_name), + project: Package::new(package_name), remote: None, } } @@ -58,19 +58,19 @@ impl Manifest { } pub fn get_package_name(&self) -> String { - self.package.name.clone() + self.project.name.clone() } pub fn get_package_version(&self) -> String { - self.package.version.clone() + self.project.version.clone() } pub fn get_package_description(&self) -> Option { - self.package.description.clone() + self.project.description.clone() } pub fn get_package_license(&self) -> Option { - self.package.license.clone() + self.project.license.clone() } pub fn get_package_remote(&self) -> Option { @@ -90,7 +90,7 @@ impl Manifest { fn template(&self) -> String { format!( - r#"[package] + r#"[project] name = "{name}" version = "0.1.0" description = "The {name} package" @@ -99,7 +99,7 @@ license = "MIT" [remote] author = "[AUTHOR]" # Add your Aleo Package Manager username, team's name, or organization's name. "#, - name = self.package.name + name = self.project.name ) } } @@ -128,7 +128,11 @@ impl TryFrom<&PathBuf> for Manifest { let mut old_remote_format: Option<&str> = None; let mut new_remote_format_exists = false; - let mut new_toml = "".to_owned(); + // Toml file adhering to the new format. + let mut final_toml = "".to_owned(); + + // New Toml file format that should be written based on feature flags. + let mut refactored_toml = "".to_owned(); // Read each individual line of the toml file for line in buffer.lines() { @@ -138,6 +142,12 @@ impl TryFrom<&PathBuf> for Manifest { .split("=") // Split the line as 'remote' = '"{author}/{package_name}"' .collect::>()[1]; // Fetch just '"{author}/{package_name}"' old_remote_format = Some(remote); + + // Retain the old remote format if the `manifest_refactor_remote` is not enabled + if cfg!(not(feature = "manifest_refactor_remote")) { + refactored_toml += line; + refactored_toml += "\n"; + } continue; } @@ -145,8 +155,24 @@ impl TryFrom<&PathBuf> for Manifest { if line.starts_with("[remote]") { new_remote_format_exists = true; } - new_toml += line; - new_toml += "\n"; + + // If the old project format is being being used, update the toml file + // to use the new format instead. + if line.starts_with("[package]") { + final_toml += "[project]"; + + // Refactor the old project format if the `manifest_refactor_project` is enabled + match cfg!(feature = "manifest_refactor_project") { + true => refactored_toml += "[project]", + false => refactored_toml += line, + } + } else { + final_toml += line; + refactored_toml += line; + } + + final_toml += "\n"; + refactored_toml += "\n"; } // Update the remote format @@ -170,18 +196,23 @@ author = "{author}" ); // Append the new remote to the bottom of the manifest file. - new_toml += &new_remote; + final_toml += &new_remote; + + // Add the new remote format if the `manifest_refactor_remote` is enabled + if cfg!(feature = "manifest_refactor_remote") { + refactored_toml += &new_remote; + } } } // Rewrite the toml file if it has been updated - if buffer != new_toml { + if buffer != refactored_toml { let mut file = File::create(&path).map_err(|error| ManifestError::Creating(MANIFEST_FILENAME, error))?; - file.write_all(new_toml.as_bytes()) + file.write_all(refactored_toml.as_bytes()) .map_err(|error| ManifestError::Writing(MANIFEST_FILENAME, error))?; } // Read the toml file - Ok(toml::from_str(&new_toml).map_err(|error| ManifestError::Parsing(MANIFEST_FILENAME, error))?) + Ok(toml::from_str(&final_toml).map_err(|error| ManifestError::Parsing(MANIFEST_FILENAME, error))?) } } diff --git a/package/tests/initialize.rs b/package/tests/initialize.rs deleted file mode 100644 index 62dc23eb85..0000000000 --- a/package/tests/initialize.rs +++ /dev/null @@ -1,192 +0,0 @@ -// Copyright (C) 2019-2020 Aleo Systems Inc. -// This file is part of the Leo library. - -// The Leo library is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// The Leo library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with the Leo library. If not, see . - -use lazy_static::lazy_static; -use std::{ - cell::RefCell, - env, - fs, - path::PathBuf, - sync::atomic::{AtomicUsize, Ordering}, -}; - -const PACKAGE_TEST_DIRECTORY: &str = "package-testing"; - -thread_local! { - /// Establish a test id for each test. - static TEST_ID: RefCell> = RefCell::new(None); -} - -lazy_static! { - /// Create a testing directory for packages in `target/` - static ref TEST_DIR: PathBuf = { - let mut path = env::current_exe().unwrap(); - path.pop(); // Remove executable name - path.pop(); // Remove 'debug' - - // Attempt to point at the `target` directory - if path.file_name().and_then(|s| s.to_str()) != Some("target") { - path.pop(); - } - - path.push(PACKAGE_TEST_DIRECTORY); - fs::create_dir_all(&path).unwrap(); - - path - }; -} - -/// Create a new directory for each test based on the ID of the test. -fn test_dir() -> PathBuf { - static NEXT_ID: AtomicUsize = AtomicUsize::new(0); - - let id = NEXT_ID.fetch_add(1, Ordering::Relaxed); - TEST_ID.with(|n| *n.borrow_mut() = Some(id)); - - let path: PathBuf = TEST_DIR.join(&format!("t{}", id)).into(); - - if path.exists() { - if let Err(e) = fs::remove_dir_all(&path) { - panic!("failed to remove {:?}: {:?}", &path, e) - } - } - - fs::create_dir_all(&path).unwrap(); - - path -} - -// Tests for package initialization -mod initialize_package { - use super::*; - use leo_package::{ - inputs::{InputFile, InputsDirectory, StateFile}, - package::Package, - root::Manifest, - source::{LibraryFile, MainFile, SourceDirectory}, - }; - - const TEST_PACKAGE_NAME: &str = "test-package"; - - #[test] - fn initialize_valid_package() { - let test_directory = test_dir(); - - // Ensure a package can be initialized at the `test_directory` - assert!(Package::can_initialize(TEST_PACKAGE_NAME, false, &test_directory)); - - // Initialize a package at the `test_directory` - assert!(Package::initialize(TEST_PACKAGE_NAME, false, &test_directory).is_ok()); - - // Ensure a package is initialized at the `test_directory` - assert!(Package::is_initialized(TEST_PACKAGE_NAME, false, &test_directory)); - } - - #[test] - #[ignore] - fn initialize_fails_with_invalid_package_names() { - unimplemented!() - } - - #[test] - fn initialize_fails_with_existing_manifest() { - let test_directory = test_dir(); - - // Ensure a package can be initialized at the `test_directory` - assert!(Package::can_initialize(TEST_PACKAGE_NAME, false, &test_directory)); - - // Manually add a manifest file to the `test_directory` - Manifest::new(TEST_PACKAGE_NAME).write_to(&test_directory).unwrap(); - - // Attempt to initialize a package at the `test_directory` - assert!(Package::initialize(TEST_PACKAGE_NAME, false, &test_directory).is_err()); - - // Ensure package is not initialized at the `test_directory` - assert!(!Package::is_initialized(TEST_PACKAGE_NAME, false, &test_directory)); - } - - #[test] - fn initialize_fails_with_existing_library_file() { - let test_directory = test_dir(); - - // Ensure a package can be initialized at the `test_directory` - assert!(Package::can_initialize(TEST_PACKAGE_NAME, true, &test_directory)); - - // Manually add a source directory and a library file to the `test_directory` - SourceDirectory::create(&test_directory).unwrap(); - LibraryFile::new(TEST_PACKAGE_NAME).write_to(&test_directory).unwrap(); - - // Attempt to initialize a package at the `test_directory` - assert!(Package::initialize(TEST_PACKAGE_NAME, true, &test_directory).is_err()); - - // Ensure package is not initialized at the `test_directory` - assert!(!Package::is_initialized(TEST_PACKAGE_NAME, true, &test_directory)); - } - - #[test] - fn initialize_fails_with_existing_input_file() { - let test_directory = test_dir(); - - // Ensure a package can be initialized at the `test_directory` - assert!(Package::can_initialize(TEST_PACKAGE_NAME, false, &test_directory)); - - // Manually add an inputs directory and an input file to the `test_directory` - InputsDirectory::create(&test_directory).unwrap(); - InputFile::new(TEST_PACKAGE_NAME).write_to(&test_directory).unwrap(); - - // Attempt to initialize a package at the `test_directory` - assert!(Package::initialize(TEST_PACKAGE_NAME, false, &test_directory).is_err()); - - // Ensure package is not initialized at the `test_directory` - assert!(!Package::is_initialized(TEST_PACKAGE_NAME, false, &test_directory)); - } - - #[test] - fn initialize_fails_with_existing_state_file() { - let test_directory = test_dir(); - - // Ensure a package can be initialized at the `test_directory` - assert!(Package::can_initialize(TEST_PACKAGE_NAME, false, &test_directory)); - - // Manually add an inputs directory and a state file to the `test_directory` - InputsDirectory::create(&test_directory).unwrap(); - StateFile::new(TEST_PACKAGE_NAME).write_to(&test_directory).unwrap(); - - // Attempt to initialize a package at the `test_directory` - assert!(Package::initialize(TEST_PACKAGE_NAME, false, &test_directory).is_err()); - - // Ensure package is not initialized at the `test_directory` - assert!(!Package::is_initialized(TEST_PACKAGE_NAME, false, &test_directory)); - } - - #[test] - fn initialize_fails_with_existing_main_file() { - let test_directory = test_dir(); - - // Ensure a package can be initialized at the `test_directory` - assert!(Package::can_initialize(TEST_PACKAGE_NAME, false, &test_directory)); - - // Manually add a source directory and a main file to the `test_directory` - SourceDirectory::create(&test_directory).unwrap(); - MainFile::new(TEST_PACKAGE_NAME).write_to(&test_directory).unwrap(); - - // Attempt to initialize a package at the `test_directory` - assert!(Package::initialize(TEST_PACKAGE_NAME, false, &test_directory).is_err()); - - // Ensure package is not initialized at the `test_directory` - assert!(!Package::is_initialized(TEST_PACKAGE_NAME, false, &test_directory)); - } -} diff --git a/package/tests/initialize/initialize.rs b/package/tests/initialize/initialize.rs new file mode 100644 index 0000000000..82763d4124 --- /dev/null +++ b/package/tests/initialize/initialize.rs @@ -0,0 +1,134 @@ +// Copyright (C) 2019-2020 Aleo Systems Inc. +// This file is part of the Leo library. + +// The Leo library is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// The Leo library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with the Leo library. If not, see . + +use crate::test_dir; +use leo_package::{ + inputs::{InputFile, InputsDirectory, StateFile}, + package::Package, + root::Manifest, + source::{LibraryFile, MainFile, SourceDirectory}, +}; + +const TEST_PACKAGE_NAME: &str = "test-package"; + +#[test] +fn initialize_valid_package() { + let test_directory = test_dir(); + + // Ensure a package can be initialized at the `test_directory` + assert!(Package::can_initialize(TEST_PACKAGE_NAME, false, &test_directory)); + + // Initialize a package at the `test_directory` + assert!(Package::initialize(TEST_PACKAGE_NAME, false, &test_directory).is_ok()); + + // Ensure a package is initialized at the `test_directory` + assert!(Package::is_initialized(TEST_PACKAGE_NAME, false, &test_directory)); +} + +#[test] +#[ignore] +fn initialize_fails_with_invalid_package_names() { + unimplemented!() +} + +#[test] +fn initialize_fails_with_existing_manifest() { + let test_directory = test_dir(); + + // Ensure a package can be initialized at the `test_directory` + assert!(Package::can_initialize(TEST_PACKAGE_NAME, false, &test_directory)); + + // Manually add a manifest file to the `test_directory` + Manifest::new(TEST_PACKAGE_NAME).write_to(&test_directory).unwrap(); + + // Attempt to initialize a package at the `test_directory` + assert!(Package::initialize(TEST_PACKAGE_NAME, false, &test_directory).is_err()); + + // Ensure package is not initialized at the `test_directory` + assert!(!Package::is_initialized(TEST_PACKAGE_NAME, false, &test_directory)); +} + +#[test] +fn initialize_fails_with_existing_library_file() { + let test_directory = test_dir(); + + // Ensure a package can be initialized at the `test_directory` + assert!(Package::can_initialize(TEST_PACKAGE_NAME, true, &test_directory)); + + // Manually add a source directory and a library file to the `test_directory` + SourceDirectory::create(&test_directory).unwrap(); + LibraryFile::new(TEST_PACKAGE_NAME).write_to(&test_directory).unwrap(); + + // Attempt to initialize a package at the `test_directory` + assert!(Package::initialize(TEST_PACKAGE_NAME, true, &test_directory).is_err()); + + // Ensure package is not initialized at the `test_directory` + assert!(!Package::is_initialized(TEST_PACKAGE_NAME, true, &test_directory)); +} + +#[test] +fn initialize_fails_with_existing_input_file() { + let test_directory = test_dir(); + + // Ensure a package can be initialized at the `test_directory` + assert!(Package::can_initialize(TEST_PACKAGE_NAME, false, &test_directory)); + + // Manually add an inputs directory and an input file to the `test_directory` + InputsDirectory::create(&test_directory).unwrap(); + InputFile::new(TEST_PACKAGE_NAME).write_to(&test_directory).unwrap(); + + // Attempt to initialize a package at the `test_directory` + assert!(Package::initialize(TEST_PACKAGE_NAME, false, &test_directory).is_err()); + + // Ensure package is not initialized at the `test_directory` + assert!(!Package::is_initialized(TEST_PACKAGE_NAME, false, &test_directory)); +} + +#[test] +fn initialize_fails_with_existing_state_file() { + let test_directory = test_dir(); + + // Ensure a package can be initialized at the `test_directory` + assert!(Package::can_initialize(TEST_PACKAGE_NAME, false, &test_directory)); + + // Manually add an inputs directory and a state file to the `test_directory` + InputsDirectory::create(&test_directory).unwrap(); + StateFile::new(TEST_PACKAGE_NAME).write_to(&test_directory).unwrap(); + + // Attempt to initialize a package at the `test_directory` + assert!(Package::initialize(TEST_PACKAGE_NAME, false, &test_directory).is_err()); + + // Ensure package is not initialized at the `test_directory` + assert!(!Package::is_initialized(TEST_PACKAGE_NAME, false, &test_directory)); +} + +#[test] +fn initialize_fails_with_existing_main_file() { + let test_directory = test_dir(); + + // Ensure a package can be initialized at the `test_directory` + assert!(Package::can_initialize(TEST_PACKAGE_NAME, false, &test_directory)); + + // Manually add a source directory and a main file to the `test_directory` + SourceDirectory::create(&test_directory).unwrap(); + MainFile::new(TEST_PACKAGE_NAME).write_to(&test_directory).unwrap(); + + // Attempt to initialize a package at the `test_directory` + assert!(Package::initialize(TEST_PACKAGE_NAME, false, &test_directory).is_err()); + + // Ensure package is not initialized at the `test_directory` + assert!(!Package::is_initialized(TEST_PACKAGE_NAME, false, &test_directory)); +} diff --git a/package/tests/initialize/mod.rs b/package/tests/initialize/mod.rs new file mode 100644 index 0000000000..c0fbdb773b --- /dev/null +++ b/package/tests/initialize/mod.rs @@ -0,0 +1,17 @@ +// Copyright (C) 2019-2020 Aleo Systems Inc. +// This file is part of the Leo library. + +// The Leo library is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// The Leo library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with the Leo library. If not, see . + +pub mod initialize; diff --git a/package/tests/manifest/manifest.rs b/package/tests/manifest/manifest.rs new file mode 100644 index 0000000000..afce5bfa0a --- /dev/null +++ b/package/tests/manifest/manifest.rs @@ -0,0 +1,169 @@ +// Copyright (C) 2019-2020 Aleo Systems Inc. +// This file is part of the Leo library. + +// The Leo library is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// The Leo library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with the Leo library. If not, see . + +// Tests for package manifest + +use crate::test_dir; +use leo_package::root::{Manifest, MANIFEST_FILENAME}; + +use std::{ + convert::TryFrom, + fs::File, + io::{Read, Write}, + path::PathBuf, +}; + +const OLD_MANIFEST_FORMAT: &str = r#"[package] +name = "test-package" +version = "0.1.0" +description = "Testing manifest updates." +license = "MIT" +remote = "author/test-package" +"#; + +const NEW_REMOTE_FORMAT: &str = r#" +[remote] +author = "author" +"#; + +const OLD_PROJECT_FORMAT: &str = "[package]"; +const NEW_PROJECT_FORMAT: &str = "[project]"; + +/// Create a manifest file with outdated formatting. +fn create_outdated_manifest_file(path: PathBuf) -> PathBuf { + let mut path = path.to_owned(); + if path.is_dir() { + path.push(PathBuf::from(MANIFEST_FILENAME)); + } + + let mut file = File::create(&path).unwrap(); + file.write_all(OLD_MANIFEST_FORMAT.as_bytes()).unwrap(); + + path +} + +/// Read the manifest file into a string. +fn read_manifest_file(path: &PathBuf) -> String { + let mut file = File::open(path.clone()).unwrap(); + let size = file.metadata().unwrap().len() as usize; + + let mut buffer = String::with_capacity(size); + file.read_to_string(&mut buffer).unwrap(); + + buffer +} + +/// Read the manifest file and check that the remote format is updated. +fn remote_is_updated(path: &PathBuf) -> bool { + let manifest_string = read_manifest_file(&path); + for line in manifest_string.lines() { + if line.starts_with("remote") { + return false; + } + } + + manifest_string.contains(NEW_REMOTE_FORMAT) +} + +/// Read the manifest file and check that the project format is updated. +fn project_is_updated(path: &PathBuf) -> bool { + let manifest_string = read_manifest_file(&path); + + !manifest_string.contains(OLD_PROJECT_FORMAT) && manifest_string.contains(NEW_PROJECT_FORMAT) +} + +#[test] +#[cfg_attr( + any(feature = "manifest_refactor_project", feature = "manifest_refactor_remote"), + ignore +)] +fn test_manifest_no_refactors() { + // Create an outdated manifest file. + let test_directory = test_dir(); + let manifest_path = create_outdated_manifest_file(test_directory); + + // Load the manifest file, and discard the new struct. + let _manifest = Manifest::try_from(&manifest_path).unwrap(); + + // Check that the manifest file project has NOT been updated. + assert!(!project_is_updated(&manifest_path)); + + // Check that the manifest file remote has NOT been updated. + assert!(!remote_is_updated(&manifest_path)); +} + +#[test] +#[cfg_attr( + any(feature = "manifest_refactor_project", not(feature = "manifest_refactor_remote")), + ignore +)] +fn test_manifest_refactor_remote() { + // Create an outdated manifest file. + let test_directory = test_dir(); + let manifest_path = create_outdated_manifest_file(test_directory); + + // Load the manifest file, and discard the new struct. + let _manifest = Manifest::try_from(&manifest_path).unwrap(); + + // Check that the manifest file project has NOT been updated. + assert!(!project_is_updated(&manifest_path)); + + // Check that the manifest file remote has been updated. + assert!(remote_is_updated(&manifest_path)); +} + +#[test] +#[cfg_attr( + any(not(feature = "manifest_refactor_project"), feature = "manifest_refactor_remote"), + ignore +)] +fn test_manifest_refactor_project() { + // Create an outdated manifest file. + let test_directory = test_dir(); + let manifest_path = create_outdated_manifest_file(test_directory); + + // Load the manifest file, and discard the new struct. + let _manifest = Manifest::try_from(&manifest_path).unwrap(); + + // Check that the manifest file project has been updated. + assert!(project_is_updated(&manifest_path)); + + // Check that the manifest file remote has NOT been updated. + assert!(!remote_is_updated(&manifest_path)); +} + +#[test] +#[cfg_attr( + any( + not(feature = "manifest_refactor_project"), + not(feature = "manifest_refactor_remote") + ), + ignore +)] +fn test_manifest_refactors() { + // Create an outdated manifest file. + let test_directory = test_dir(); + let manifest_path = create_outdated_manifest_file(test_directory); + + // Load the manifest file, and discard the new struct. + let _manifest = Manifest::try_from(&manifest_path).unwrap(); + + // Check that the manifest file project has been updated. + assert!(project_is_updated(&manifest_path)); + + // Check that the manifest file remote has been updated. + assert!(remote_is_updated(&manifest_path)); +} diff --git a/package/tests/manifest/mod.rs b/package/tests/manifest/mod.rs new file mode 100644 index 0000000000..10d357ff78 --- /dev/null +++ b/package/tests/manifest/mod.rs @@ -0,0 +1,17 @@ +// Copyright (C) 2019-2020 Aleo Systems Inc. +// This file is part of the Leo library. + +// The Leo library is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// The Leo library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with the Leo library. If not, see . + +pub mod manifest; diff --git a/package/tests/mod.rs b/package/tests/mod.rs new file mode 100644 index 0000000000..0fe5d2f794 --- /dev/null +++ b/package/tests/mod.rs @@ -0,0 +1,73 @@ +// Copyright (C) 2019-2020 Aleo Systems Inc. +// This file is part of the Leo library. + +// The Leo library is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// The Leo library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with the Leo library. If not, see . + +pub mod initialize; +pub mod manifest; + +use lazy_static::lazy_static; +use std::{ + cell::RefCell, + env, + fs, + path::PathBuf, + sync::atomic::{AtomicUsize, Ordering}, +}; + +const PACKAGE_TEST_DIRECTORY: &str = "package-testing"; + +thread_local! { + /// Establish a test id for each test. + pub static TEST_ID: RefCell> = RefCell::new(None); +} + +lazy_static! { + /// Create a testing directory for packages in `target/` + pub static ref TEST_DIR: PathBuf = { + let mut path = env::current_exe().unwrap(); + path.pop(); // Remove executable name + path.pop(); // Remove 'debug' + + // Attempt to point at the `target` directory + if path.file_name().and_then(|s| s.to_str()) != Some("target") { + path.pop(); + } + + path.push(PACKAGE_TEST_DIRECTORY); + fs::create_dir_all(&path).unwrap(); + + path + }; +} + +/// Create a new directory for each test based on the ID of the test. +pub(crate) fn test_dir() -> PathBuf { + static NEXT_ID: AtomicUsize = AtomicUsize::new(0); + + let id = NEXT_ID.fetch_add(1, Ordering::Relaxed); + TEST_ID.with(|n| *n.borrow_mut() = Some(id)); + + let path: PathBuf = TEST_DIR.join(&format!("t{}", id)).into(); + + if path.exists() { + if let Err(e) = fs::remove_dir_all(&path) { + panic!("failed to remove {:?}: {:?}", &path, e) + } + } + + fs::create_dir_all(&path).unwrap(); + + path +}