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: add a perl test section #1230

Merged
merged 7 commits into from
Dec 4, 2024
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
41 changes: 14 additions & 27 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
@@ -1,33 +1,20 @@
exclude: '(\.patch|\.diff|\.snap|\.ambr|test-data/recipes/test-parsing/.+)$'

repos:
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v4.4.0
hooks:
- id: check-yaml
- id: end-of-file-fixer
- id: trailing-whitespace
- repo: https://github.com/psf/black
rev: 23.9.1
hooks:
- id: black
args: [--safe, --quiet]
- repo: https://github.com/pre-commit/mirrors-isort
rev: v5.10.1
hooks:
- id: isort
exclude: tests/data
- repo: https://github.com/PyCQA/flake8
rev: 6.1.0
hooks:
- id: flake8
args: ['--max-line-length=120']
language_version: python3
additional_dependencies:
- flake8-typing-imports==1.15.0
- flake8-builtins==2.1.0
- flake8-bugbear==23.9.16
- flake8-isort==6.1.0
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v4.4.0
hooks:
- id: check-yaml
- id: end-of-file-fixer
- id: trailing-whitespace

- repo: https://github.com/astral-sh/ruff-pre-commit
rev: v0.1.6
hooks:
- id: ruff
args: [--fix, --exit-non-zero-on-fix]
- id: ruff-format

- repo: local
hooks:
- id: rustfmt
Expand Down
2 changes: 1 addition & 1 deletion py-rattler-build/README.md
Original file line number Diff line number Diff line change
@@ -1 +1 @@
# Python bindings to rattler-build
# Python bindings to rattler-build
3 changes: 2 additions & 1 deletion py-rattler-build/tests/unit/test_basic.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import rattler_build
from pathlib import Path

import rattler_build


def test_basic() -> None:
parent_cargo_toml = Path(__file__).parent.parent.parent.parent / "Cargo.toml"
Expand Down
70 changes: 69 additions & 1 deletion src/package_test/run_test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,8 @@ use crate::{
env_vars,
metadata::PlatformWithVirtualPackages,
recipe::parser::{
CommandsTest, DownstreamTest, PythonTest, PythonVersion, Script, ScriptContent, TestType,
CommandsTest, DownstreamTest, PerlTest, PythonTest, PythonVersion, Script, ScriptContent,
TestType,
},
render::solver::create_environment,
source::copy_dir::CopyDir,
Expand Down Expand Up @@ -425,6 +426,10 @@ pub async fn run_test(
.run_test(&pkg, &package_folder, &prefix, &config)
.await?
}
TestType::Perl { perl } => {
perl.run_test(&pkg, &package_folder, &prefix, &config)
.await?
}
TestType::Downstream(downstream) if downstream_package.is_none() => {
downstream
.run_test(&pkg, package_file, &prefix, &config)
Expand Down Expand Up @@ -591,6 +596,69 @@ impl PythonTest {
}
}

impl PerlTest {
/// Execute the Perl test
pub async fn run_test(
&self,
pkg: &ArchiveIdentifier,
path: &Path,
prefix: &Path,
config: &TestConfiguration,
) -> Result<(), TestError> {
let span = tracing::info_span!("Running perl test");
let _guard = span.enter();

let match_spec = MatchSpec::from_str(
format!("{}={}={}", pkg.name, pkg.version, pkg.build_string).as_str(),
ParseStrictness::Lenient,
)?;

let dependencies = vec![
MatchSpec::from_str("perl", ParseStrictness::Strict).unwrap(),
match_spec,
];

create_environment(
"test",
&dependencies,
config
.host_platform
.as_ref()
.unwrap_or(&config.current_platform),
prefix,
&config.channels,
&config.tool_configuration,
config.channel_priority,
config.solve_strategy,
)
.await
.map_err(TestError::TestEnvironmentSetup)?;

let mut imports = String::new();
tracing::info!("Testing perl imports:\n");

for module in &self.uses {
writeln!(imports, "use {};", module)?;
tracing::info!(" use {};", module);
}
tracing::info!("\n");

let script = Script {
content: ScriptContent::Command(imports.clone()),
interpreter: Some("perl".into()),
..Script::default()
};

let tmp_dir = tempfile::tempdir()?;
script
.run_script(Default::default(), tmp_dir.path(), path, prefix, None, None)
.await
.map_err(|e| TestError::TestFailed(e.to_string()))?;

Ok(())
}
}

impl CommandsTest {
/// Execute the command test
pub async fn run_test(
Expand Down
2 changes: 1 addition & 1 deletion src/recipe/parser.rs
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ pub use self::{
source::{GitRev, GitSource, GitUrl, PathSource, Source, UrlSource},
test::{
CommandsTest, CommandsTestFiles, CommandsTestRequirements, DownstreamTest,
PackageContentsTest, PythonTest, PythonVersion, TestType,
PackageContentsTest, PerlTest, PythonTest, PythonVersion, TestType,
},
};

Expand Down
30 changes: 29 additions & 1 deletion src/recipe/parser/test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,13 @@ impl Default for PythonTest {
}
}

/// A special Perl test that checks if the imports are available and runs `cpanm check`.
#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct PerlTest {
/// List of perl `uses` to test
pub uses: Vec<String>,
}

/// A test that runs the tests of a downstream package.
#[derive(Debug, Default, Clone, PartialEq, Serialize, Deserialize)]
pub struct DownstreamTest {
Expand All @@ -137,6 +144,11 @@ pub enum TestType {
/// The imports to test and the `pip check` flag
python: PythonTest,
},
/// A Perl test that will test if the modules are available
Perl {
/// The modules to test
perl: PerlTest,
},
/// A test that executes multiple commands in a freshly created environment
Command(CommandsTest),
/// A test that runs the tests of a downstream package
Expand Down Expand Up @@ -247,10 +259,14 @@ impl TryConvertNode<TestType> for RenderedMappingNode {
let package_contents = as_mapping(value, key_str)?.try_convert(key_str)?;
test = TestType::PackageContents { package_contents };
}
"perl" => {
let perl = as_mapping(value, key_str)?.try_convert(key_str)?;
test = TestType::Perl { perl };
}
invalid => Err(vec![_partialerror!(
*key.span(),
ErrorKind::InvalidField(invalid.to_string().into()),
help = format!("expected fields for {name} is one of `python`, `script`, `downstream`, `package_contents`")
help = format!("expected fields for {name} is one of `python`, `perl`, `script`, `downstream`, `package_contents`")
)])?
}
Ok(())
Expand Down Expand Up @@ -383,6 +399,18 @@ impl TryConvertNode<CommandsTest> for RenderedMappingNode {
}
}

///////////////////////////
/// Perl Test ///
///////////////////////////

impl TryConvertNode<PerlTest> for RenderedMappingNode {
fn try_convert(&self, _name: &str) -> Result<PerlTest, Vec<PartialParsingError>> {
let mut perl_test = PerlTest::default();
validate_keys!(perl_test, self.iter(), uses);
Ok(perl_test)
}
}

///////////////////////////
/// Package Contents ///
///////////////////////////
Expand Down
40 changes: 40 additions & 0 deletions test-data/recipes/perl-test/recipe.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
context:
version: 0.03

package:
name: perl-call-context
version: ${{ version }}

source:
url: https://cpan.metacpan.org/authors/id/F/FE/FELIPE/Call-Context-${{ version }}.tar.gz
sha256: 0ee6bf46bc72755adb7a6b08e79d12e207de5f7809707b3c353b58cb2f0b5a26

build:
number: 0
noarch: generic
script:
- perl Makefile.PL INSTALLDIRS=site NO_PERLLOCAL=1 NO_PACKLIST=1
- make
- make test
- make install
- echo "LICENSE-ARTISTIC" > LICENSE-ARTISTIC
- echo "LICENSE-GPL" > LICENSE-GPL

requirements:
build:
- make
host:
- perl

tests:
- perl:
uses:
- Call::Context

about:
license: GPL-1.0-or-later OR Artistic-1.0-Perl
license_file:
- LICENSE-ARTISTIC
- LICENSE-GPL
summary: Sanity-check calling context
homepage: http://metacpan.org/pod/Call-Context
9 changes: 9 additions & 0 deletions test/end-to-end/__snapshots__/test_tests.ambr
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# serializer version: 1
# name: test_perl_tests
'''
- perl:
uses:
- Call::Context

'''
# ---
3 changes: 1 addition & 2 deletions test/end-to-end/test_simple.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,7 @@
import pytest
import requests
import yaml
from helpers import (RattlerBuild, check_build_output, get_extracted_package,
get_package)
from helpers import RattlerBuild, check_build_output, get_extracted_package, get_package


def test_functionality(rattler_build: RattlerBuild):
Expand Down
20 changes: 20 additions & 0 deletions test/end-to-end/test_tests.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import os
from pathlib import Path

import pytest
from helpers import RattlerBuild, get_extracted_package


@pytest.mark.skipif(
os.name == "nt", reason="recipe does not support execution on windows"
)
def test_perl_tests(
rattler_build: RattlerBuild, recipes: Path, tmp_path: Path, snapshot
):
rattler_build.build(recipes / "perl-test", tmp_path)
pkg = get_extracted_package(tmp_path, "perl-call-context")

assert (pkg / "info" / "tests" / "tests.yaml").exists()
content = (pkg / "info" / "tests" / "tests.yaml").read_text()

assert snapshot == content
Loading