<commit_before># -*- coding: utf-8 -*-
'''
    :codeauthor: <NAME> (<EMAIL>)


    tests.integration.shell.call
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
'''

# Import python libs
from __future__ import absolute_import
import logging
import os
import re
import shutil
import sys

# Import Salt Testing libs
from tests.support.case import ShellCase
from tests.support.unit import skipIf
from tests.support.paths import FILES, TMP
from tests.support.mixins import ShellCaseCommonTestsMixin
from tests.support.helpers import flaky, with_tempfile
from tests.integration.utils import testprogram

# Import salt libs
import salt.utils.files
import salt.utils.json
import salt.utils.platform
import salt.utils.yaml
from salt.ext import six

log = logging.getLogger(__name__)


class CallTest(ShellCase, testprogram.TestProgramCase, ShellCaseCommonTestsMixin):

    _call_binary_ = 'salt-call'

    def test_default_output(self):
        out = self.run_call('-l quiet test.fib 3')

        expect = ['local:',
                  '    - 2']
        self.assertEqual(expect, out[:-1])

    def test_text_output(self):
        out = self.run_call('-l quiet --out txt test.fib 3')

        expect = [
            'local: (2'
        ]

        self.assertEqual(''.join(expect), ''.join(out).rsplit(",", 1)[0])

    def test_json_out_indent(self):
        out = self.run_call('test.ping -l quiet --out=json --out-indent=-1')
        self.assertIn('"local": true', ''.join(out))

        out = self.run_call('test.ping -l quiet --out=json --out-indent=0')
        self.assertIn('"local": true', ''.join(out))

        out = self.run_call('test.ping -l quiet --out=json --out-indent=1')
        self.assertIn('"local": true', ''.join(out))

    def test_local_sls_call(self):
        fileroot = os.path.join(FILES, 'file', 'base')
        out = self.run_call('--file-root {0} --local state.sls saltcalllocal'.format(fileroot))
        self.assertIn('Name: test.echo', ''.join(out))
        self.assertIn('Result: True', ''.join(out))
        self.assertIn('hello', ''.join(out))
        self.assertIn('Succeeded: 1', ''.join(out))

    @with_tempfile()
    def test_local_salt_call(self, name):
        '''
        This tests to make sure that salt-call does not execute the
        function twice, see https://github.com/saltstack/salt/pull/49552
        '''
        def _run_call(cmd):
            cmd = '--out=json --local ' + cmd
            return salt.utils.json.loads(''.join(self.run_call(cmd)))['local']

        ret = _run_call('state.single file.append name={0} text="foo"'.format(name))
        ret = ret[next(iter(ret))]

        # Make sure we made changes
        assert ret['changes']

        # 2nd sanity check: make sure that "foo" only exists once in the file
        with salt.utils.files.fopen(name) as fp_:
            contents = fp_.read()
        assert contents.count('foo') == 1, contents

    @skipIf(sys.platform.startswith('win'), 'This test does not apply on Win')
    @flaky
    def test_user_delete_kw_output(self):
        ret = self.run_call('-l quiet -d user.delete')
        assert 'salt \'*\' user.delete name remove=True force=True' in ''.join(ret)

    def test_salt_documentation_too_many_arguments(self):
        '''
        Test to see if passing additional arguments shows an error
        '''
        data = self.run_call('-d virtualenv.create /tmp/ve', catch_stderr=True)
        self.assertIn('You can only get documentation for one method at one time', '\n'.join(data[1]))

    def test_issue_6973_state_highstate_exit_code(self):
        '''
        If there is no tops/master_tops or state file matches
        for this minion, salt-call should exit non-zero if invoked with
        option --retcode-passthrough
        '''
        src = os.path.join(FILES, 'file/base/top.sls')
        dst = os.path.join(FILES, 'file/base/top.sls.bak')
        shutil.move(src, dst)
        expected_comment = 'No states found for this minion'
        try:
            stdout, retcode = self.run_call(
                '-l quiet --retcode-passthrough state.highstate',
                with_retcode=True
            )
        finally:
            shutil.move(dst, src)
        self.assertIn(expected_comment, ''.join(stdout))
        self.assertNotEqual(0, retcode)

    @skipIf(sys.platform.startswith('win'), 'This test does not apply on Win')
    @skipIf(True, 'to be re-enabled when #23623 is merged')
    def test_return(self):
        self.run_call('cmd.run "echo returnTOmaster"')
        jobs = [a for a in self.run_run('jobs.list_jobs')]

        self.assertTrue(True in ['returnTOmaster' in j for j in jobs])
        # lookback jid
        first_match = [(i, j)
                       for i, j in enumerate(jobs)
                       if 'returnTOmaster' in j][0]
        jid, idx = None, first_match[0]
        while idx > 0:
            jid = re.match("([0-9]+):", jobs[idx])
            if jid:
                jid = jid.group(1)
                break
            idx -= 1
        assert idx > 0
        assert jid
        master_out = [
            a for a in self.run_run('jobs.lookup_jid {0}'.format(jid))
        ]
        self.assertTrue(True in ['returnTOmaster' in a for a in master_out])

    @skipIf(salt.utils.platform.is_windows(), 'Skip on Windows')
    def test_syslog_file_not_found(self):
        '''
        test when log_file is set to a syslog file that does not exist
        '''
        old_cwd = os.getcwd()
        config_dir = os.path.join(TMP, 'log_file_incorrect')
        if not os.path.isdir(config_dir):
            os.makedirs(config_dir)

        os.chdir(config_dir)

        with salt.utils.files.fopen(self.get_config_file_path('minion'), 'r') as fh_:
            minion_config = salt.utils.yaml.load(fh_.read())
            minion_config['log_file'] = 'file:///dev/doesnotexist'
            with salt.utils.files.fopen(os.path.join(config_dir, 'minion'), 'w') as fh_:
                fh_.write(
                    salt.utils.yaml.dump(minion_config, default_flow_style=False)
                )
        ret = self.run_script(
            'salt-call',
            '--config-dir {0} cmd.run "echo foo"'.format(
                config_dir
            ),
            timeout=60,
            catch_stderr=True,
            with_retcode=True
        )
        try:
            if sys.version_info >= (3, 5, 4):
                self.assertIn('local:', ret[0])
                self.assertIn('[WARNING ] The log_file does not exist. Logging not setup correctly or syslog service not started.', ret[1])
                self.assertEqual(ret[2], 0)
            else:
                self.assertIn(
                    'Failed to setup the Syslog logging handler', '\n'.join(ret[1])
                )
                self.assertEqual(ret[2], 2)
        finally:
            self.chdir(old_cwd)
            if os.path.isdir(config_dir):
                shutil.rmtree(config_dir)

    @skipIf(True, 'This test is unreliable. Need to investigate why more deeply.')<commit_msg>Allow more time for slow test<commit_after># -*- coding: utf-8 -*-
'''
    :codeauthor: <NAME> (<EMAIL>)


    tests.integration.shell.call
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
'''

# Import python libs
from __future__ import absolute_import
import logging
import os
import re
import shutil
import sys

# Import Salt Testing libs
from tests.support.case import ShellCase
from tests.support.unit import skipIf
from tests.support.paths import FILES, TMP
from tests.support.mixins import ShellCaseCommonTestsMixin
from tests.support.helpers import flaky, with_tempfile
from tests.integration.utils import testprogram

# Import salt libs
import salt.utils.files
import salt.utils.json
import salt.utils.platform
import salt.utils.yaml
from salt.ext import six

log = logging.getLogger(__name__)


class CallTest(ShellCase, testprogram.TestProgramCase, ShellCaseCommonTestsMixin):

    _call_binary_ = 'salt-call'

    def test_default_output(self):
        out = self.run_call('-l quiet test.fib 3')

        expect = ['local:',
                  '    - 2']
        self.assertEqual(expect, out[:-1])

    def test_text_output(self):
        out = self.run_call('-l quiet --out txt test.fib 3')

        expect = [
            'local: (2'
        ]

        self.assertEqual(''.join(expect), ''.join(out).rsplit(",", 1)[0])

    def test_json_out_indent(self):
        out = self.run_call('test.ping -l quiet --out=json --out-indent=-1')
        self.assertIn('"local": true', ''.join(out))

        out = self.run_call('test.ping -l quiet --out=json --out-indent=0')
        self.assertIn('"local": true', ''.join(out))

        out = self.run_call('test.ping -l quiet --out=json --out-indent=1')
        self.assertIn('"local": true', ''.join(out))

    def test_local_sls_call(self):
        fileroot = os.path.join(FILES, 'file', 'base')
        out = self.run_call('--file-root {0} --local state.sls saltcalllocal'.format(fileroot))
        self.assertIn('Name: test.echo', ''.join(out))
        self.assertIn('Result: True', ''.join(out))
        self.assertIn('hello', ''.join(out))
        self.assertIn('Succeeded: 1', ''.join(out))

    @with_tempfile()
    def test_local_salt_call(self, name):
        '''
        This tests to make sure that salt-call does not execute the
        function twice, see https://github.com/saltstack/salt/pull/49552
        '''
        def _run_call(cmd):
            cmd = '--out=json --local ' + cmd
            return salt.utils.json.loads(''.join(self.run_call(cmd)))['local']

        ret = _run_call('state.single file.append name={0} text="foo"'.format(name))
        ret = ret[next(iter(ret))]

        # Make sure we made changes
        assert ret['changes']

        # 2nd sanity check: make sure that "foo" only exists once in the file
        with salt.utils.files.fopen(name) as fp_:
            contents = fp_.read()
        assert contents.count('foo') == 1, contents

    @skipIf(sys.platform.startswith('win'), 'This test does not apply on Win')
    @flaky
    def test_user_delete_kw_output(self):
        ret = self.run_call('-l quiet -d user.delete')
        assert 'salt \'*\' user.delete name remove=True force=True' in ''.join(ret)

    def test_salt_documentation_too_many_arguments(self):
        '''
        Test to see if passing additional arguments shows an error
        '''
        data = self.run_call('-d virtualenv.create /tmp/ve', catch_stderr=True)
        self.assertIn('You can only get documentation for one method at one time', '\n'.join(data[1]))

    def test_issue_6973_state_highstate_exit_code(self):
        '''
        If there is no tops/master_tops or state file matches
        for this minion, salt-call should exit non-zero if invoked with
        option --retcode-passthrough
        '''
        src = os.path.join(FILES, 'file/base/top.sls')
        dst = os.path.join(FILES, 'file/base/top.sls.bak')
        shutil.move(src, dst)
        expected_comment = 'No states found for this minion'
        try:
            stdout, retcode = self.run_call(
                '-l quiet --retcode-passthrough state.highstate',
                with_retcode=True
            )
        finally:
            shutil.move(dst, src)
        self.assertIn(expected_comment, ''.join(stdout))
        self.assertNotEqual(0, retcode)

    @skipIf(sys.platform.startswith('win'), 'This test does not apply on Win')
    @skipIf(True, 'to be re-enabled when #23623 is merged')
    def test_return(self):
        self.run_call('cmd.run "echo returnTOmaster"')
        jobs = [a for a in self.run_run('jobs.list_jobs')]

        self.assertTrue(True in ['returnTOmaster' in j for j in jobs])
        # lookback jid
        first_match = [(i, j)
                       for i, j in enumerate(jobs)
                       if 'returnTOmaster' in j][0]
        jid, idx = None, first_match[0]
        while idx > 0:
            jid = re.match("([0-9]+):", jobs[idx])
            if jid:
                jid = jid.group(1)
                break
            idx -= 1
        assert idx > 0
        assert jid
        master_out = [
            a for a in self.run_run('jobs.lookup_jid {0}'.format(jid))
        ]
        self.assertTrue(True in ['returnTOmaster' in a for a in master_out])

    @skipIf(salt.utils.platform.is_windows(), 'Skip on Windows')
    def test_syslog_file_not_found(self):
        '''
        test when log_file is set to a syslog file that does not exist
        '''
        old_cwd = os.getcwd()
        config_dir = os.path.join(TMP, 'log_file_incorrect')
        if not os.path.isdir(config_dir):
            os.makedirs(config_dir)

        os.chdir(config_dir)

        with salt.utils.files.fopen(self.get_config_file_path('minion'), 'r') as fh_:
            minion_config = salt.utils.yaml.load(fh_.read())
            minion_config['log_file'] = 'file:///dev/doesnotexist'
            with salt.utils.files.fopen(os.path.join(config_dir, 'minion'), 'w') as fh_:
                fh_.write(
                    salt.utils.yaml.dump(minion_config, default_flow_style=False)
                )
        ret = self.run_script(
            'salt-call',
            '--config-dir {0} cmd.run "echo foo"'.format(
                config_dir
            ),
            timeout=120,
            catch_stderr=True,
            with_retcode=True
        )
        try:
            if sys.version_info >= (3, 5, 4):
                self.assertIn('local:', ret[0])
                self.assertIn('[WARNING ] The log_file does not exist. Logging not setup correctly or syslog service not started.', ret[1])
                self.assertEqual(ret[2], 0)
            else:
                self.assertIn(
                    'Failed to setup the Syslog logging handler', '\n'.join(ret[1])
                )
                self.assertEqual(ret[2], 2)
        finally:
            self.chdir(old_cwd)
            if os.path.isdir(config_dir):
                shutil.rmtree(config_dir)

    @skipIf(True, 'This test is unreliable. Need to investigate why more deeply.')
{'fraction_non_alphanumeric': 0.13040074026621112, 'fraction_numerical': 0.007758559328066054, 'mean_word_length': 2.2151029748283753, 'pattern_counts': {'":': 6, '<': 7, '<?xml version=': 0, '>': 13, 'https://': 2, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2999209', 'n_tokens_mistral': 4487, 'n_tokens_neox': 4294, 'n_words': 1060}