From 0ac1b64433814072ae517aecf0476a864387003e Mon Sep 17 00:00:00 2001 From: "Mark A. Grondona" Date: Thu, 9 Dec 2021 10:49:20 -0800 Subject: [PATCH] testsuite: add tests for FluxURIResolver, flux-uri Problem: No tests exist for the Python FluxURIResolver class and its front-end tool flux-uri. Add a small set of tests for the base URI and FluxJobURI classes to the python tests as t/python/t0025-uri.py, and a larger set of functionality tests in t2802-uri-cmd.t which use the flux-uri(1) command. --- t/Makefile.am | 2 + t/python/t0025-uri.py | 57 +++++++++++++++++++++++++ t/t2802-uri-cmd.t | 99 +++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 158 insertions(+) create mode 100755 t/python/t0025-uri.py create mode 100755 t/t2802-uri-cmd.t diff --git a/t/Makefile.am b/t/Makefile.am index 09182ba61d09..f4e2d296ad5e 100644 --- a/t/Makefile.am +++ b/t/Makefile.am @@ -174,6 +174,7 @@ TESTSCRIPTS = \ t2703-mini-bulksubmit.t \ t2800-jobs-cmd.t \ t2801-top-cmd.t \ + t2802-uri-cmd.t \ t2900-job-timelimits.t \ t3000-mpi-basic.t \ t3001-mpi-personalities.t \ @@ -212,6 +213,7 @@ TESTSCRIPTS = \ python/t0022-resource-set.py \ python/t0023-executor.py \ python/t0024-util.py \ + python/t0025-uri.py \ python/t1000-service-add-remove.py if HAVE_FLUX_SECURITY diff --git a/t/python/t0025-uri.py b/t/python/t0025-uri.py new file mode 100755 index 000000000000..e60e491352e4 --- /dev/null +++ b/t/python/t0025-uri.py @@ -0,0 +1,57 @@ +#!/usr/bin/env python3 + +############################################################### +# Copyright 2021 Lawrence Livermore National Security, LLC +# (c.f. AUTHORS, NOTICE.LLNS, COPYING) +# +# This file is part of the Flux resource manager framework. +# For details, see https://github.com/flux-framework. +# +# SPDX-License-Identifier: LGPL-3.0 +############################################################### + +import unittest +import platform +import subflux # To set up PYTHONPATH +from pycotap import TAPTestRunner +from flux.uri import JobURI, FluxURIResolver + + +class TestJobURI(unittest.TestCase): + def test_parse_remote(self): + uri = JobURI("ssh://foo.com/tmp/foo?tag=bar&x=y") + self.assertEqual(uri.uri, "ssh://foo.com/tmp/foo?tag=bar&x=y") + self.assertEqual(uri.remote, "ssh://foo.com/tmp/foo?tag=bar&x=y") + self.assertEqual(uri.local, "local:///tmp/foo") + self.assertEqual(uri.scheme, "ssh") + self.assertEqual(uri.netloc, "foo.com") + self.assertEqual(uri.path, "/tmp/foo") + self.assertEqual(uri.query, "tag=bar&x=y") + self.assertEqual(uri.fragment, "") + self.assertEqual(uri.params, "") + + def test_parse_local(self): + hostname = platform.uname()[1] + uri = JobURI("local:///tmp/foo") + self.assertEqual(uri.uri, "local:///tmp/foo") + self.assertEqual(str(uri), "local:///tmp/foo") + self.assertEqual(uri.remote, f"ssh://{hostname}/tmp/foo") + self.assertEqual(uri.local, "local:///tmp/foo") + self.assertEqual(uri.scheme, "local") + self.assertEqual(uri.netloc, "") + self.assertEqual(uri.path, "/tmp/foo") + self.assertEqual(uri.query, "") + self.assertEqual(uri.fragment, "") + self.assertEqual(uri.params, "") + + def test_parse_errors(self): + with self.assertRaises(ValueError) as error: + JobURI("foo:///tmp/bar").remote + with self.assertRaises(ValueError) as error: + JobURI("foo:///tmp/bar").local + with self.assertRaises(ValueError) as error: + JobURI("") + + +if __name__ == "__main__": + unittest.main(testRunner=TAPTestRunner()) diff --git a/t/t2802-uri-cmd.t b/t/t2802-uri-cmd.t new file mode 100755 index 000000000000..bb40cdde0e9e --- /dev/null +++ b/t/t2802-uri-cmd.t @@ -0,0 +1,99 @@ +#!/bin/sh + +test_description='Test flux uri command' + +. $(dirname $0)/sharness.sh + +test_under_flux 1 + +testssh="${SHARNESS_TEST_SRCDIR}/scripts/tssh" + +test_expect_success 'flux-uri -h prints list of resolvers' ' + flux uri --help >help.out >help.out 2>&1 && + test_debug "cat help.out" && + grep "Supported resolver schemes" help.out +' +test_expect_success 'flux-uri rejects invalid URI' ' + test_expect_code 1 flux uri bar && + test_expect_code 1 flux uri bar:foo +' +test_expect_success 'flux-uri pid resolver works' ' + test "$(flux uri pid:$$)" = "$FLUX_URI" +' +test_expect_success 'flux-uri pid resolver works on flux-broker' ' + test "$(flux uri pid:$(flux getattr broker.pid))" = "$FLUX_URI" +' +test_expect_success 'flux-uri pid resolver fails for nonexistent pid' ' + test_expect_code 1 flux uri pid:123456 +' +test_expect_success NO_CHAIN_LINT 'flux-uri pid scheme fails for non-flux pid' ' + pid=$(bash -c "unset FLUX_URI;sleep 30 >/dev/null 2>&1 & echo \$!") && + test_expect_code 1 flux uri pid:$pid && + kill $pid +' +test_expect_success 'start a small hierarchy of Flux instances' ' + cat <<-EOF >batch.sh && + #!/bin/sh + jobid=\$(flux mini submit -n1 flux start flux mini run sleep 300) && + flux --parent job memo \$(flux getattr jobid) jobid=\$jobid && + flux job attach \$jobid + EOF + chmod +x batch.sh && + jobid=$(flux mini batch -n1 batch.sh) && + flux job wait-event -T offset -vt 15 -c 2 $jobid memo +' +test_expect_success 'flux uri resolves jobid argument' ' + flux proxy $(flux uri --local $jobid) flux getattr jobid >jobid1.out && + test "$(cat jobid1.out)" = "$jobid" +' +test_expect_success 'flux uri resolves hierarchical jobid argument' ' + jobid2=$(flux jobs -no {user.jobid} $jobid) && + test_debug "echo attempting to resolve jobid:${jobid}/${jobid2}" && + uri=$(FLUX_SSH=$testssh flux uri --local jobid:${jobid}/${jobid2}) && + test_debug "echo jobid:${jobid}/${jobid2} is ${uri}" && + uri=$(FLUX_SSH=$testssh flux uri --local ${jobid}/${jobid2}) && + test_debug "echo ${jobid}/${jobid2} is ${uri}" +' +test_expect_success 'flux uri jobid returns error for non-instance job' ' + id=$(flux mini submit sleep 600) && + test_expect_code 1 flux uri $id +' +test_expect_success 'flux uri jobid scheme returns error for invalid jobid' ' + test_expect_code 1 flux uri jobid:boop +' +test_expect_success 'setup fake srun and scontrol cmds for mock slurm testing' ' + # slurm resolver runs `srun flux uri slurm:jobid` + # mock the execution of that command here by just returning a uri + cat <<-EOF >srun && + #!/bin/sh + test -n "\$SRUN_FAIL" && exit 1 + exec flux uri pid:$$ + EOF + chmod +x srun && + # slurm resolver attempts to list pids from `scontrol listpids` + # return a single listpids line with our pid for mocking + # set + cat <<-EOF >scontrol && + #!/bin/sh + test -n "\$REMOTE" && exit 1 + echo "PID JOBID STEPID LOCALID GLOBALID" + echo "1 1234 1234 0 0" + echo "$$ 1234 1234 0 0" + EOF + chmod +x scontrol +' +test_expect_success 'flux-uri mock testing of slurm resolver works' ' + result=$(PATH=$(pwd):$PATH flux uri --local slurm:1234) && + test_debug "echo slurm:1234 got $result" && + test "$result" = "$FLUX_URI" && + result=$(PATH=$(pwd):$PATH REMOTE=t flux uri --local slurm:1234) && + test_debug "echo slurm:1234 with REMOTE=t got $result" && + test "$result" = "$FLUX_URI" && + ( export PATH=$(pwd):$PATH REMOTE=t SRUN_FAIL=t && + test_expect_code 1 flux uri slurm:1234 ) +' +test_expect_success 'cleanup jobs' ' + flux job cancelall -f && + flux queue drain +' +test_done