# -*- coding: utf-8 -*-
'''
    :codeauthor: :email:`jmoney <justin@saltstack.com>`
'''

# Import Python libs
from __future__ import absolute_import

# Import Salt Libs
from salt.modules import cp
from salt.utils import templates
from salt.exceptions import CommandExecutionError

# Import Salt Testing Libs
from salttesting import skipIf, TestCase
from salttesting.helpers import ensure_in_syspath
from salttesting.mock import (
    MagicMock,
    mock_open,
    patch,
    NO_MOCK,
    NO_MOCK_REASON
)

ensure_in_syspath('../../')

# Globals
cp.__salt__ = {}
cp.__opts__ = {}
cp.__pillar__ = {}
cp.__grains__ = {}
cp.__context__ = {}


@skipIf(NO_MOCK, NO_MOCK_REASON)
class CpTestCase(TestCase):
    '''
    TestCase for salt.modules.cp module
    '''

    def test__render_filenames_undefined_template(self):
        '''
        Test if _render_filenames fails upon getting a template not in
        TEMPLATE_REGISTRY.
        '''
        path = '/srv/salt/saltines'
        dest = '/srv/salt/cheese'
        saltenv = 'base'
        template = 'biscuits'
        ret = (path, dest)
        self.assertRaises(CommandExecutionError,
                          cp._render_filenames,
                          path, dest, saltenv, template)

    def test__render_filenames_render_failed(self):
        '''
        Test if _render_filenames fails when template rendering fails.
        '''
        path = 'salt://saltines'
        dest = '/srv/salt/cheese'
        saltenv = 'base'
        template = 'jinja'
        file_data = 'Remember to keep your files well salted.'
        mock_jinja = lambda *args, **kwargs: {'result': False,
                                              'data': file_data}
        with patch.dict(templates.TEMPLATE_REGISTRY,
                        {'jinja': mock_jinja}):
            with patch('salt.utils.fopen', mock_open(read_data=file_data)):
                self.assertRaises(CommandExecutionError,
                                  cp._render_filenames,
                                  path, dest, saltenv, template)

    def test__render_filenames_success(self):
        '''
        Test if _render_filenames succeeds.
        '''
        path = 'salt://saltines'
        dest = '/srv/salt/cheese'
        saltenv = 'base'
        template = 'jinja'
        file_data = '/srv/salt/biscuits'
        mock_jinja = lambda *args, **kwargs: {'result': True,
                                              'data': file_data}
        ret = (file_data, file_data)  # salt.utils.fopen can only be mocked once
        with patch.dict(templates.TEMPLATE_REGISTRY,
                        {'jinja': mock_jinja}):
            with patch('salt.utils.fopen', mock_open(read_data=file_data)):
                self.assertEqual(cp._render_filenames(
                                 path, dest, saltenv, template), ret)

    @patch('salt.modules.cp.hash_file', MagicMock(return_value=False))
    def test_get_file_not_found(self):
        '''
        Test if get_file can't find the file.
        '''
        path = 'salt://saltines'
        dest = '/srv/salt/cheese'
        ret = ''
        self.assertEqual(cp.get_file(path, dest), ret)

    def test_get_file_str_success(self):
        '''
        Test if get_file_str succeeds.
        '''
        path = 'salt://saltines'
        dest = '/srv/salt/cheese/saltines'
        file_data = 'Remember to keep your files well salted.'
        saltenv = 'base'
        ret = file_data
        with patch('salt.utils.fopen', mock_open(read_data=file_data)):
            with patch('salt.modules.cp.cache_file',
                       MagicMock(return_value=dest)):
                self.assertEqual(cp.get_file_str(path, dest), ret)

    def test_push_non_absolute_path(self):
        '''
        Test if push fails on a non absolute path.
        '''
        path = '../saltines'
        ret = False

        self.assertEqual(cp.push(path), ret)

    def test_push_dir_non_absolute_path(self):
        '''
        Test if push_dir fails on a non absolute path.
        '''
        path = '../saltines'
        ret = False

        self.assertEqual(cp.push_dir(path), ret)


if __name__ == '__main__':
    from integration import run_tests
    run_tests(CpTestCase, needs_daemon=False)
