From 3dd53ecdef64cb1bfaa08a8cca05ea0dfd7cfa03 Mon Sep 17 00:00:00 2001 From: rootile Date: Thu, 25 Jun 2026 20:27:05 +0200 Subject: [PATCH] tests: migrate fetchers.sh Change-Id: I3c2856dad2e06993717bcba437c5a0b46e74821f --- tests/functional/fetchers.sh | 96 -------------- tests/functional/meson.build | 1 - .../eval/fetchers/test_fetch_tree.py | 121 ++++++++++++++++++ 3 files changed, 121 insertions(+), 97 deletions(-) delete mode 100644 tests/functional/fetchers.sh create mode 100644 tests/functional2/eval/fetchers/test_fetch_tree.py diff --git a/tests/functional/fetchers.sh b/tests/functional/fetchers.sh deleted file mode 100644 index aa808af73..000000000 --- a/tests/functional/fetchers.sh +++ /dev/null @@ -1,96 +0,0 @@ -source common.sh - -requireGit - -clearStore - -testFetchTreeError() { - rawFetchTreeArg="${1?fetchTree arg missing}" - messageSubstring="${2?messageSubstring missing}" - - output="$(nix eval --impure --raw --expr "(builtins.fetchTree $rawFetchTreeArg).outPath" 2>&1)" && status=0 || status=$? - grepQuiet "$messageSubstring" <<<"$output" - test "$status" -ne 0 -} - -# github/gitlab/sourcehut fetcher input validation -for provider in github gitlab sourcehut; do - # ref/rev validation - testFetchTreeError \ - "{ type = \"$provider\"; owner = \"foo\"; repo = \"bar\"; ref = \",\"; }" \ - "URL '$provider:foo/bar' contains an invalid branch/tag name" - - testFetchTreeError \ - "\"$provider://host/foo/bar/,\"" \ - "URL '$provider://host/foo/bar/,', ',' is not a commit hash or a branch/tag name" - - testFetchTreeError \ - "\"$provider://host/foo/bar/f16d8f43dd0998cdb315a2cccf2e4d10027e7ca4?rev=abc\"" \ - "URL '$provider://host/foo/bar/f16d8f43dd0998cdb315a2cccf2e4d10027e7ca4?rev=abc' already contains a ref or rev" - - testFetchTreeError \ - "\"$provider://host/foo/bar/ref?ref=ref2\"" \ - "URL '$provider://host/foo/bar/ref?ref=ref2' already contains a ref or rev" - - # host validation - testFetchTreeError \ - "{ type = \"$provider\"; owner = \"foo\"; repo = \"bar\"; host = \"git_hub.com\"; }" \ - "URL '$provider:foo/bar' contains an invalid instance host" - - testFetchTreeError \ - "\"$provider://host/foo/bar/ref?host=git_hub.com\"" \ - "URL '$provider:foo/bar' contains an invalid instance host" - - # invalid attributes - testFetchTreeError \ - "{ type = \"$provider\"; owner = \"foo\"; repo = \"bar\"; wrong = true; }" \ - "unsupported input attribute 'wrong'" - - testFetchTreeError \ - "\"$provider://host/foo/bar/ref?wrong=1\"" \ - "unsupported input attribute 'wrong'" -done - -# unsupported attributes w/ tarball fetcher -testFetchTreeError \ - "\"https://host/foo?wrong=1\"" \ - "unsupported tarball input attribute 'wrong'. If you wanted to fetch a tarball with a query parameter, please use '{ type = \"tarball\"; url = \"...\"; }" - -# test for unsupported attributes / validation in git fetcher -testFetchTreeError \ - "\"git+https://github.com/owner/repo?invalid=1\"" \ - "unsupported input attribute 'invalid' for the 'git' scheme" - -testFetchTreeError \ - "\"git+https://github.com/owner/repo?url=foo\"" \ - "URL 'git+https://github.com/owner/repo?url=foo' must not override url via query param!" - -testFetchTreeError \ - "\"git+https://github.com/owner/repo?ref=foo.lock\"" \ - "invalid Git branch/tag name 'foo.lock'" - -testFetchTreeError \ - "{ type = \"git\"; url =\"https://github.com/owner/repo\"; ref = \"foo.lock\"; }" \ - "invalid Git branch/tag name 'foo.lock'" - -# same for mercurial -testFetchTreeError \ - "\"hg+https://forge.tld/owner/repo?invalid=1\"" \ - "unsupported input attribute 'invalid' for the 'hg' scheme" - -testFetchTreeError \ - "{ type = \"hg\"; url = \"https://forge.tld/owner/repo\"; invalid = 1; }" \ - "unsupported input attribute 'invalid' for the 'hg' scheme" - -testFetchTreeError \ - "\"hg+https://forge.tld/owner/repo?ref=,\"" \ - "invalid Mercurial branch/tag name ','" - -testFetchTreeError \ - "{ type = \"hg\"; url = \"https://forge.tld/owner/repo\"; ref = \",\"; }" \ - "invalid Mercurial branch/tag name ','" - -echo 'hello lix' > testfile -output="$(nix eval --expr '(builtins.fetchTree { path = "'"$(pwd)"'/testfile"; rev = "0000000000000000000000000000000000000000"; type = "path"; })' 2>&1)" && status=0 || status=$? -[ "$status" -eq 1 ] -grepQuiet "error: in pure evaluation mode, 'fetchTree' requires a locked input" <<<"$output" diff --git a/tests/functional/meson.build b/tests/functional/meson.build index 0a3d53a7f..14902b83c 100644 --- a/tests/functional/meson.build +++ b/tests/functional/meson.build @@ -50,7 +50,6 @@ functional_tests_scripts = [ 'fixed.sh', 'fetchGitRefs.sh', 'gc-runtime.sh', - 'fetchers.sh', 'fetchGit.sh', 'fetchGitLocked.sh', 'fetchurl.sh', diff --git a/tests/functional2/eval/fetchers/test_fetch_tree.py b/tests/functional2/eval/fetchers/test_fetch_tree.py new file mode 100644 index 000000000..bea0b63c1 --- /dev/null +++ b/tests/functional2/eval/fetchers/test_fetch_tree.py @@ -0,0 +1,121 @@ +from pathlib import Path +from testlib.fixtures.file_helper import File +from testlib.fixtures.file_helper import with_files +import pytest +from testlib.fixtures.nix import Nix + + +def fetch_tree_error( + nix: Nix, arg: str = "fetchTree arg missing", msg: str = "messageSubstring missing" +): + res = ( + nix.nix( + ["eval", "--impure", "--raw", "--expr", f"(builtins.fetchTree {arg}).outPath"], + flake=True, + ) + .run() + .expect(1) + ) + assert msg in res.stderr_plain + + +@pytest.mark.parametrize("provider", ["gitlab", "github", "sourcehut"]) +@pytest.mark.parametrize( + ("arg", "msg"), + [ + ( + '{ type = "@provider@"; owner = "foo"; repo = "bar"; ref = ",";}', + "URL '@provider@:foo/bar' contains an invalid branch/tag name", + ), + ( + '"@provider@://host/foo/bar/,"', + "URL '@provider@://host/foo/bar/,', ',' is not a commit hash or a branch/tag name", + ), + ( + '"@provider@://host/foo/bar/f16d8f43dd0998cdb315a2cccf2e4d10027e7ca4?rev=abc"', + "URL '@provider@://host/foo/bar/f16d8f43dd0998cdb315a2cccf2e4d10027e7ca4?rev=abc' already contains a ref or rev", + ), + ( + '"@provider@://host/foo/bar/ref?ref=ref2"', + "URL '@provider@://host/foo/bar/ref?ref=ref2' already contains a ref or rev", + ), + ( + '{ type = "@provider@"; owner = "foo"; repo = "bar"; host = "git_hub.com"; }', + "URL '@provider@:foo/bar' contains an invalid instance host", + ), + ( + '"@provider@://host/foo/bar/ref?host=git_hub.com"', + "URL '@provider@:foo/bar' contains an invalid instance host", + ), + ( + '{ type = "@provider@"; owner = "foo"; repo = "bar"; wrong = true; }', + "unsupported input attribute 'wrong'", + ), + ('"@provider@://host/foo/bar/ref?wrong=1"', "unsupported input attribute 'wrong'"), + ], +) +def test_provider_input_validation(nix: Nix, provider: str, arg: str, msg: str): + + fetch_tree_error(nix, arg.replace("@provider@", provider), msg.replace("@provider@", provider)) + + +@pytest.mark.parametrize( + ("arg", "msg"), + [ + # tarball fetchers + ( + '"https://host/foo?wrong=1"', + 'unsupported tarball input attribute \'wrong\'. If you wanted to fetch a tarball with a query parameter, please use \'{ type = "tarball"; url = "..."; }', + ), + # git fetchers + ( + '"git+https://github.com/owner/repo?invalid=1"', + "unsupported input attribute 'invalid' for the 'git' scheme", + ), + ( + '"git+https://github.com/owner/repo?url=foo"', + "URL 'git+https://github.com/owner/repo?url=foo' must not override url via query param!", + ), + ( + '"git+https://github.com/owner/repo?ref=foo.lock"', + "invalid Git branch/tag name 'foo.lock'", + ), + ( + '{ type = "git"; url ="https://github.com/owner/repo"; ref = "foo.lock"; }', + "invalid Git branch/tag name 'foo.lock'", + ), + # mercurial + ( + '"hg+https://forge.tld/owner/repo?invalid=1"', + "unsupported input attribute 'invalid' for the 'hg' scheme", + ), + ( + '{ type = "hg"; url = "https://forge.tld/owner/repo"; invalid = 1; }', + "unsupported input attribute 'invalid' for the 'hg' scheme", + ), + ('"hg+https://forge.tld/owner/repo?ref=,"', "invalid Mercurial branch/tag name ','"), + ( + '{ type = "hg"; url = "https://forge.tld/owner/repo"; ref = ",";}', + "invalid Mercurial branch/tag name ','", + ), + ], +) +def test_unsupported_attrs(nix: Nix, arg: str, msg: str): + fetch_tree_error(nix, arg, msg) + + +@with_files({"testfile": File("hello lix")}) +def test_fetch_tree_pure_eval(nix: Nix, files: Path): + res = ( + nix.nix( + [ + "eval", + "--expr", + f'(builtins.fetchTree {{ path = "{files}/testfile"; rev = "0000000000000000000000000000000000000000"; type = "path";}})', + ], + flake=True, + ) + .run() + .expect(1) + ) + assert "error: in pure evaluation mode, 'fetchTree' requires a locked input" in res.stderr_plain