diff --git a/cdist/test/exec/local.py b/cdist/test/exec/local.py index 0865b7dc..a62beeaa 100644 --- a/cdist/test/exec/local.py +++ b/cdist/test/exec/local.py @@ -29,6 +29,8 @@ import random import time import datetime import argparse +import stat +import unittest import cdist import cdist.configuration as cc @@ -278,6 +280,85 @@ class LocalTestCase(test.CdistTestCase): for fmt, expected, actual in cases: self.assertEqual(expected, actual) + #------------------------------------------------------------------------ + # POLYGLOT tests: + # Ensure cdist is truely language-agnostic + # with proper support of shebang for "executable" scripts + #------------------------------------------------------------------------ + @staticmethod + def _mark_as_executable(script): + # grant execute permission to everyone + os.chmod(script, + (os.stat(script).st_mode & 0o777) + | stat.S_IEXEC | stat.S_IXGRP | stat.S_IXOTH) + + def test_polyglot_run_shell_script_with_exec_permisions(self): + xc = self.local + xc.create_files_dirs() + handle, script = self.mkstemp(dir=self.temp_dir) + with os.fdopen(handle, "w") as fd: + fd.writelines(["#!/bin/sh\n", "[ 1 == 1 ] && echo OK" ]) + + self._mark_as_executable(script) + + xc.run_script(script) + + def test_polyglot_run_shell_script_without_exec_permissions(self): + xc = self.local + xc.create_files_dirs() + handle, script = self.mkstemp(dir=self.temp_dir) + with os.fdopen(handle, "w") as fd: + fd.writelines(["#!/bin/sh\n", "[ 1 == 1 ] && echo OK" ]) + + xc.run_script(script) + + def test_polyglot_run_perl_script_with_exec_permissions(self): + xc = self.local + xc.create_files_dirs() + try: + xc.run(["/usr/bin/env", "perl", "-v"]) + except: + raise unittest.SkipTest( + 'perl interpreter or env program is not available.') + + handle, script = self.mkstemp(dir=self.temp_dir) + with os.fdopen(handle, "w") as fd: + fd.write( + """#!/usr/bin/env perl + use strict; + print 'OK'; + """) + + self._mark_as_executable(script) + + self.assertEqual(xc.run_script(script, return_output=True), "OK") + + def test_polyglot_run_perl_script_without_exec_permissions_and_fail(self): + xc = self.local + xc.create_files_dirs() + try: + xc.run(["/usr/bin/env", "perl", "-v"]) + except: + raise unittest.SkipTest( + 'perl interpreter or env program is not available.') + + handle, script = self.mkstemp(dir=self.temp_dir) + with os.fdopen(handle, "w") as fd: + fd.write( + """#!/usr/bin/env perl + use strict; + print 'OK'; + """) + + # NOTE that we deliberately abstain from setting execute permissions + # on the script, so that it ends up being fed into /bin/sh + # by the executor, which in turn should cause an error. + failed = False + try: + xc.run_script(script) + except: + failed = True + self.assertTrue(failed) if __name__ == "__main__": import unittest diff --git a/cdist/test/exec/remote.py b/cdist/test/exec/remote.py index b23f8447..ccba389f 100644 --- a/cdist/test/exec/remote.py +++ b/cdist/test/exec/remote.py @@ -23,6 +23,8 @@ import os import getpass import shutil import multiprocessing +import stat +import unittest import cdist from cdist import test @@ -220,6 +222,86 @@ class RemoteTestCase(test.CdistTestCase): self.assertEqual(output, "test_object\n") + #------------------------------------------------------------------------ + # POLYGLOT tests: + # Ensure cdist is truely language-agnostic + # with proper support of shebang for "executable" scripts + #------------------------------------------------------------------------ + @staticmethod + def _mark_as_executable(script): + # grant execute permission to everyone + os.chmod(script, + (os.stat(script).st_mode & 0o777) + | stat.S_IEXEC | stat.S_IXGRP | stat.S_IXOTH) + + def test_polyglot_run_shell_script_with_exec_permisions(self): + xc = self.remote + xc.create_files_dirs() + handle, script = self.mkstemp(dir=self.temp_dir) + with os.fdopen(handle, "w") as fd: + fd.writelines(["#!/bin/sh\n", "[ 1 == 1 ] && echo OK" ]) + + self._mark_as_executable(script) + + xc.run_script(script) + + def test_polyglot_run_shell_script_without_exec_permissions(self): + xc = self.remote + xc.create_files_dirs() + handle, script = self.mkstemp(dir=self.temp_dir) + with os.fdopen(handle, "w") as fd: + fd.writelines(["#!/bin/sh\n", "[ 1 == 1 ] && echo OK" ]) + + xc.run_script(script) + + def test_polyglot_run_perl_script_with_exec_permissions(self): + xc = self.remote + xc.create_files_dirs() + try: + xc.run(["/usr/bin/env", "perl", "-v"]) + except: + raise unittest.SkipTest( + 'perl interpreter or env program is not available.') + + handle, script = self.mkstemp(dir=self.temp_dir) + with os.fdopen(handle, "w") as fd: + fd.write( + """#!/usr/bin/env perl + use strict; + print 'OK'; + """) + + self._mark_as_executable(script) + + self.assertEqual(xc.run_script(script, return_output=True), "OK") + + def test_polyglot_run_perl_script_without_exec_permissions_and_fail(self): + xc = self.remote + xc.create_files_dirs() + try: + xc.run(["/usr/bin/env", "perl", "-v"]) + except: + raise unittest.SkipTest( + 'perl interpreter or env program is not available.') + + handle, script = self.mkstemp(dir=self.temp_dir) + with os.fdopen(handle, "w") as fd: + fd.write( + """#!/usr/bin/env perl + use strict; + print 'OK'; + """) + + # NOTE that we deliberately abstain from setting execute permissions + # on the script, so that it ends up being fed into /bin/sh + # by the executor, which in turn should cause an error. + failed = False + try: + xc.run_script(script) + except: + failed = True + self.assertTrue(failed) + if __name__ == '__main__': import unittest diff --git a/cdist/test/explorer/fixtures/conf/explorer/polyglot_perl b/cdist/test/explorer/fixtures/conf/explorer/polyglot_perl new file mode 100755 index 00000000..4f64de0f --- /dev/null +++ b/cdist/test/explorer/fixtures/conf/explorer/polyglot_perl @@ -0,0 +1,4 @@ +#!/usr/bin/env perl +use strict; + +print "Polyglot - perl\n"