import os
import pytest
import shutil
import hashlib
from calculate.templates.template_processor import DirectoryProcessor,\
                                                   TemplateWrapper
from calculate.utils.package import PackageAtomName, Version, Package,\
                                    NonePackage
from calculate.utils.files import join_paths
from calculate.utils.io_module import IOModule
from calculate.templates.template_engine import Variables


CHROOT_PATH = os.path.join(os.getcwd(),
                           'tests/templates/testfiles/test_dir_processor_root')
ROOT_PATH = '/etc'
CONFIG_PATH = os.path.join(CHROOT_PATH, 'var/lib/calculate/config')
CONFIG_ARCHIVE_PATH = os.path.join(CHROOT_PATH,
                                   'var/lib/calculate/config-archive')
EXECUTE_ARCHIVE_PATH = os.path.join(CHROOT_PATH,
                                    'var/lib/calculate/.execute')

test_package_name_1 = PackageAtomName(
                        {'pkg_path': os.path.join(
                                  CHROOT_PATH,
                                  'var/db/pkg/test-category/test-package-1.0'),
                         'version': Version('1.0')})

test_package_name_0 = PackageAtomName(
                   {'pkg_path': os.path.join(
                             CHROOT_PATH,
                             'var/db/pkg/test-category/test-package-0.9.6-r1'),
                    'version': Version('0.9.6-r1')})

other_package_name = PackageAtomName(
                        {'pkg_path': os.path.join(
                                 CHROOT_PATH,
                                 'var/db/pkg/test-category/other-package-1.1'),
                         'version': Version('1.1')})

new_package_name = PackageAtomName(
                        {'pkg_path': os.path.join(
                                 CHROOT_PATH,
                                 'var/db/pkg/test-category/new-package-0.1.1'),
                         'version': Version('1.0')})

# Вместо модуля переменных.
group = Variables({'bool': True,
                   'list': [1, 2, 3]})

ns = Variables({'variable_1': 'value_1',
                'variable_2': 'value_2',
                'group': group})

install = Variables({'os_disk_dev': 'os_disk_dev_value',
                     'version': 1.5,
                     'number': 128,
                     'boolean': False,
                     'type': 'static',
                     'path': '/usr/sbin'})

merge = Variables({'var_1': 674,
                   'var_2': 48,
                   'version': 1.0,
                   'calculate_domains': 'lists.calculate-linux.org',
                   'ip_value': '127.0.0.0/8'})

main = Variables({'cl_template_path':
                  '{0},{1}'.format(os.path.join(CHROOT_PATH,
                                                'templates'),
                                   os.path.join(CHROOT_PATH,
                                                'var/calculate/templates')),
                  'cl_chroot_path': CHROOT_PATH,
                  'cl_root_path': ROOT_PATH,
                  'cl_config_path': CONFIG_PATH,
                  'cl_config_archive': CONFIG_ARCHIVE_PATH,
                  'cl_exec_dir_path': EXECUTE_ARCHIVE_PATH,
                  'cl_ignore_files': '*.swp'})

test = ({'test_root': CHROOT_PATH})

datavars = Variables({'install': install,
                      'merge': merge,
                      'ns': ns,
                      'main': main,
                      'test': test,
                      'custom': Variables()})


def show_tree(dir_path, indent=0):
    print('{}{}/'.format(' ' * 4 * indent, os.path.basename(dir_path)))
    indent += 1
    for node in os.scandir(dir_path):
        if node.is_dir():
            show_tree(node.path, indent=indent)
        else:
            print('{}{}'.format(' ' * 4 * indent, node.name))


@pytest.mark.directory_processor
class TestDirectoryProcessor:
    def test_create_testfiles(self):
        TemplateWrapper._protected_is_set = False

        shutil.copytree(os.path.join(CHROOT_PATH, 'etc.backup'),
                        os.path.join(CHROOT_PATH, 'etc'),
                        symlinks=True)
        shutil.copytree(os.path.join(CHROOT_PATH, 'var.backup'),
                        os.path.join(CHROOT_PATH, 'var'),
                        symlinks=True)

    def test_if_templates_consist_only_one_directory_with_a_single_calculate_directory_file_with_the_append_skip_parameter__the_directory_processor_does_nothing(self):
        datavars.main['cl_template_path'] = os.path.join(CHROOT_PATH,
                                                         'templates_0')
        directory_processor = DirectoryProcessor('install',
                                                 datavars_module=datavars)
        directory_processor.process_template_directories()

        assert directory_processor.template_executor.\
            changed_files == {}

    def test_if_templates_consist_only_one_directory_with_a_calculate_directory_file_and_a_single_template_file__the_directory_processor_creates_new_file_and_adds_one_in_the_CONTENTS_file(self):
        datavars.main['cl_template_path'] = os.path.join(CHROOT_PATH,
                                                         'templates_1')
        directory_processor = DirectoryProcessor('install',
                                                 datavars_module=datavars)
        directory_processor.process_template_directories()
        header = ('#' + '-' * 79 + '\n' +
                  '# Modified by Calculate Utilities 4.0\n' +
                  '# Processed template files:\n' +
                  '# ' + '{0}' + '\n' +
                  '#' + '-' * 79 + '\n')

        header = header.format('\n# '.join(
                                        [join_paths(
                                            CHROOT_PATH,
                                            'templates_1/root/file_0')]))
        output_text = '{0}{1}'.format(header,
                                      ("options {\n    parameter-1 "
                                       + datavars.ns.variable_1
                                       + ";\n    parameter-2 "
                                       + datavars.ns.variable_2
                                       + ";\n};\n"))

        assert os.path.exists(join_paths(CHROOT_PATH, '/etc/file_0'))
        test_package = Package(test_package_name_1, chroot_path=CHROOT_PATH)
        assert '/etc/file_0' in test_package
        with open(join_paths(CHROOT_PATH, '/etc/file_0'), 'r') as output_file:
            output_file_text = output_file.read()
            assert output_file_text == output_text

        assert directory_processor.template_executor.\
            changed_files == {join_paths(CHROOT_PATH, 'etc/file_0'): 'N'}

    def test_if_templates_consist_only_one_directory_with_a_calculate_directory_file_and_a_single_other_directory_with_same_a_file__the_directory_processor_creates_new_directory(self):
        datavars.main['cl_template_path'] = os.path.join(CHROOT_PATH,
                                                         'templates_2')
        directory_processor = DirectoryProcessor('install',
                                                 datavars_module=datavars)
        directory_processor.process_template_directories()

        assert os.path.exists(join_paths(CHROOT_PATH, '/etc/dir_1'))

        assert directory_processor.template_executor.\
            changed_files == {join_paths(CHROOT_PATH, '/etc/dir_1'): 'N'}

    def test_if_templates_consist_only_one_directory_with_a_calculate_directory_file_and_a_single_other_directory_without_calculate_directory_file__the_directory_processor_creates_new_directory(self):
        datavars.main['cl_template_path'] = os.path.join(CHROOT_PATH,
                                                         'templates_4')
        if not os.path.exists(os.path.join(CHROOT_PATH,
                                           'templates_4/root/dir_3')):
            os.mkdir(os.path.join(CHROOT_PATH, 'templates_4/root/dir_3'))

        directory_processor = DirectoryProcessor('install',
                                                 datavars_module=datavars)
        directory_processor.process_template_directories()

        assert os.path.exists(join_paths(CHROOT_PATH, '/etc/dir_3'))

        assert directory_processor.template_executor.\
            changed_files == {join_paths(CHROOT_PATH, '/etc/dir_3'): 'N'}

    def test_if_templates_consist_only_one_directory_with_a_calculate_directory_file_with_a_single_directory_with_a_single_template_file__the_directory_processor_creates_new_directory_and_file_and_adds_one_in_the_CONTENTS_file(self):
        datavars.main['cl_template_path'] = os.path.join(CHROOT_PATH,
                                                         'templates_3')
        directory_processor = DirectoryProcessor('install',
                                                 datavars_module=datavars)
        directory_processor.process_template_directories()
        header = ('#' + '-' * 79 + '\n' +
                  '# Modified by Calculate Utilities 4.0\n' +
                  '# Processed template files:\n' +
                  '# ' + '{0}' + '\n' +
                  '#' + '-' * 79 + '\n')

        header = header.format('\n# '.join(
                                        [join_paths(
                                            CHROOT_PATH,
                                            'templates_3/root/dir_2/file_0')]))
        output_text = '{0}{1}'.format(header,
                                      ("options {\n    parameter-1 "
                                       + datavars.ns.variable_1
                                       + ";\n    parameter-2 "
                                       + datavars.ns.variable_2
                                       + ";\n};\n"))

        assert os.path.exists(join_paths(CHROOT_PATH, '/etc/dir_2'))
        assert os.path.exists(join_paths(CHROOT_PATH, '/etc/dir_2/file_0'))
        test_package = Package(test_package_name_1, chroot_path=CHROOT_PATH)
        assert '/etc/dir_2' in test_package
        assert '/etc/dir_2/file_0' in test_package
        with open(join_paths(CHROOT_PATH,
                             '/etc/dir_2/file_0'), 'r') as output_file:
            output_file_text = output_file.read()
            assert output_file_text == output_text

        assert directory_processor.template_executor.\
            changed_files == {
                             join_paths(CHROOT_PATH, '/etc/dir_2'): 'N',
                             join_paths(CHROOT_PATH, '/etc/dir_2/file_0'): 'N'}

    def test_if_templates_consist_only_one_directory_with_a_calculate_directory_file_and_with_two_directories_with_a_template_files__the_directory_processor_creates_all_new_directories_and_files_and_adds_them_in_the_CONTENTS_file(self):
        datavars.main['cl_template_path'] = os.path.join(CHROOT_PATH,
                                                         'templates_5')
        directory_processor = DirectoryProcessor('install',
                                                 datavars_module=datavars)
        directory_processor.process_template_directories()
        header = ('#' + '-' * 79 + '\n' +
                  '# Modified by Calculate Utilities 4.0\n' +
                  '# Processed template files:\n' +
                  '# ' + '{0}' + '\n' +
                  '#' + '-' * 79 + '\n')

        header_1 = header.format('\n# '.join(
                                     [join_paths(
                                        CHROOT_PATH,
                                        'templates_5/root/dir_4/file_0')]))
        output_text_1 = '{0}{1}'.format(header_1,
                                        ("options {\n    parameter-1 "
                                         + datavars.ns.variable_1
                                         + ";\n    parameter-2 "
                                         + datavars.ns.variable_2
                                         + ";\n};\n"))
        header_2 = header.format('\n# '.join(
                                     [join_paths(
                                        CHROOT_PATH,
                                        'templates_5/root/dir_5/file_0')]))
        output_text_2 = '{0}{1}'.format(header_2,
                                        ("options {\n    parameter-1 "
                                         + datavars.ns.variable_1
                                         + ";\n    parameter-2 "
                                         + datavars.ns.variable_2
                                         + ";\n};\n"))

        assert os.path.exists(join_paths(CHROOT_PATH, '/etc/dir_4'))
        assert os.path.exists(join_paths(CHROOT_PATH, '/etc/dir_4/file_0'))
        test_package = Package(test_package_name_1, chroot_path=CHROOT_PATH)
        assert '/etc/dir_4' in test_package
        assert '/etc/dir_4/file_0' in test_package
        with open(join_paths(CHROOT_PATH,
                             '/etc/dir_4/file_0'), 'r') as output_file:
            output_file_text = output_file.read()
            assert output_file_text == output_text_1

        # Для подробностей см. шаблон.
        assert os.path.exists(join_paths(CHROOT_PATH, '/etc/dir_5'))
        assert os.path.exists(join_paths(CHROOT_PATH, '/etc/dir_5/dir_6'))
        assert os.path.exists(join_paths(CHROOT_PATH,
                                         '/etc/dir_5/dir_6/file_0'))
        test_package = Package(test_package_name_1, chroot_path=CHROOT_PATH)
        assert '/etc/dir_5' in test_package
        assert '/etc/dir_5/dir_6' in test_package
        assert '/etc/dir_5/dir_6/file_0' in test_package
        with open(join_paths(CHROOT_PATH,
                             '/etc/dir_5/dir_6/file_0'), 'r') as output_file:
            output_file_text = output_file.read()
            assert output_file_text == output_text_2

        assert directory_processor.template_executor.\
            changed_files == {
                       join_paths(CHROOT_PATH, '/etc/dir_4'): 'N',
                       join_paths(CHROOT_PATH, '/etc/dir_4/file_0'): 'N',
                       join_paths(CHROOT_PATH, '/etc/dir_5/dir_6'): 'N',
                       join_paths(CHROOT_PATH, '/etc/dir_5/dir_6/file_0'): 'N'}

    def test_if_templates_consist_only_one_directory_with_a_calculate_directory_file_and_a_single_template_file_and_there_is_a_file_without_user_changes_on_its_target_path__the_directory_processor_joins_a_template_file_with_a_target_file_and_updates_the_CONTENTS_file(self):
        datavars.main['cl_template_path'] = os.path.join(CHROOT_PATH,
                                                         'templates_6')
        directory_processor = DirectoryProcessor('install',
                                                 datavars_module=datavars)
        directory_processor.process_template_directories()
        header = ('#' + '-' * 79 + '\n' +
                  '# Modified by Calculate Utilities 4.0\n' +
                  '# Processed template files:\n' +
                  '# ' + '{0}' + '\n' +
                  '#' + '-' * 79 + '\n')

        header = header.format('\n# '.join(
                                       [join_paths(
                                            CHROOT_PATH,
                                            'templates_6/root/file_1')]))
        output_text = '{0}{1}'.format(header,
                                      ("options {\n    parameter-0 yes;"
                                       + "\n    parameter-1 "
                                       + datavars.ns.variable_1
                                       + ";\n    parameter-2 "
                                       + datavars.ns.variable_2
                                       + ";\n};\n"))

        test_package = Package(new_package_name, chroot_path=CHROOT_PATH)

        assert os.path.exists(join_paths(CHROOT_PATH, '/etc/file_1'))
        with open(join_paths(CHROOT_PATH, '/etc/file_1'), 'r') as output_file:
            output_file_text = output_file.read()
            assert output_file_text == output_text
        assert '/etc/file_1' in test_package
        assert test_package.check_contents_data('/etc/file_1',
                                                hashlib.md5(
                                                    output_text.encode()
                                                           ).hexdigest())

        assert directory_processor.template_executor.\
            changed_files == {join_paths(CHROOT_PATH, '/etc/file_1'): 'M'}

    def test_if_templates_consist_only_one_directory_with_a_calculate_directory_file_with_a_single_directory_with_a_single_template_file_and_there_is_a_file_without_user_changes_on_its_target_path__the_directory_processor_joins_a_template_file_with_a_target_file_and_updates_the_CONTENTS_file(self):
        datavars.main['cl_template_path'] = os.path.join(CHROOT_PATH,
                                                         'templates_7')
        directory_processor = DirectoryProcessor('install',
                                                 datavars_module=datavars)
        directory_processor.process_template_directories()
        header = ('#' + '-' * 79 + '\n' +
                  '# Modified by Calculate Utilities 4.0\n' +
                  '# Processed template files:\n' +
                  '# ' + '{0}' + '\n' +
                  '#' + '-' * 79 + '\n')

        header = header.format('\n# '.join(
                                       [join_paths(
                                            CHROOT_PATH,
                                            'templates_7/root/dir_6/file_0')]))
        output_text = '{0}{1}'.format(header,
                                      ("options {\n    parameter-0 yes;"
                                       + "\n    parameter-1 "
                                       + datavars.ns.variable_1
                                       + ";\n    parameter-2 "
                                       + datavars.ns.variable_2
                                       + ";\n};\n"))

        assert os.path.exists(join_paths(CHROOT_PATH, '/etc/dir_6'))
        assert os.path.exists(join_paths(CHROOT_PATH, '/etc/dir_6/file_0'))
        test_package = Package(new_package_name, chroot_path=CHROOT_PATH)
        assert '/etc/dir_6' in test_package
        assert '/etc/dir_6/file_0' in test_package
        with open(join_paths(CHROOT_PATH,
                             '/etc/dir_6/file_0'), 'r') as output_file:
            output_file_text = output_file.read()
            assert output_file_text == output_text
        assert test_package.check_contents_data('/etc/dir_6/file_0',
                                         hashlib.md5(
                                             output_text.encode()).hexdigest())
        assert directory_processor.template_executor.\
            changed_files == {join_paths(CHROOT_PATH,
                                         '/etc/dir_6/file_0'): 'M'}

    def test_if_templates_consist_only_one_directory_with_a_calculate_directory_file_and_a_single_template_file_and_there_is_a_file_with_user_changes_on_its_target_path__the_directory_processor_joins_a_template_file_with_a_target_file_and_updates_the_CONTENTS_file(self):
        datavars.main['cl_template_path'] = os.path.join(CHROOT_PATH,
                                                         'templates_8')
        directory_processor = DirectoryProcessor('install',
                                                 datavars_module=datavars)
        directory_processor.process_template_directories()
        header = ('#' + '-' * 79 + '\n' +
                  '# Modified by Calculate Utilities 4.0\n' +
                  '# Processed template files:\n' +
                  '# ' + '{0}' + '\n' +
                  '#' + '-' * 79 + '\n')

        header = header.format('\n# '.join(
                                       [join_paths(
                                            CHROOT_PATH,
                                            'templates_8/root/file_2')]))
        output_text = '{0}{1}'.format(header,
                                      ("options {\n    parameter-0 yes;"
                                       + "\n    parameter-1 "
                                       + datavars.ns.variable_1
                                       + ";\n    parameter-2 "
                                       + datavars.ns.variable_2
                                       + ";\n};\n"))

        assert os.path.exists(join_paths(CHROOT_PATH, '/etc/file_2'))
        assert os.path.exists(join_paths(CHROOT_PATH, '/etc/._cfg0000_file_2'))

        test_package = Package(new_package_name, chroot_path=CHROOT_PATH)
        assert '/etc/file_2' in test_package
        with open(join_paths(CHROOT_PATH,
                             '/etc/._cfg0000_file_2'), 'r') as output_file:
            output_file_text = output_file.read()
            assert output_file_text == output_text
        assert test_package.check_contents_data('/etc/._cfg0000_file_2',
                                         hashlib.md5(
                                             output_text.encode()).hexdigest())

        assert directory_processor.template_executor.\
            changed_files == {join_paths(CHROOT_PATH,
                                         '/etc/file_2'): 'C'}

    def test_if_templates_consist_only_one_directory_with_a_calculate_directory_file_one_template_directory_and_a_single_template_file_with_a_target_path_to_a_file_removed_by_user_in_the_last_one__the_directory_processor_creates_a_new_empty_cfg_file__joins_template_with_it_and_updates_the_CONTENTS_file(self):
        datavars.main['cl_template_path'] = os.path.join(CHROOT_PATH,
                                                         'templates_9')
        directory_processor = DirectoryProcessor('install',
                                                 datavars_module=datavars)
        directory_processor.process_template_directories()
        header = ('#' + '-' * 79 + '\n' +
                  '# Modified by Calculate Utilities 4.0\n' +
                  '# Processed template files:\n' +
                  '# ' + '{0}' + '\n' +
                  '#' + '-' * 79 + '\n')

        header = header.format('\n# '.join(
                                       [join_paths(
                                            CHROOT_PATH,
                                            'templates_9/root/etc/file_3')]))
        output_text = '{0}{1}'.format(header,
                                      ("options {\n    parameter-1 "
                                       + datavars.ns.variable_1
                                       + ";\n    parameter-2 "
                                       + datavars.ns.variable_2
                                       + ";\n};\n"))

        assert not os.path.exists(join_paths(CHROOT_PATH, '/etc/file_3'))
        assert os.path.exists(join_paths(CHROOT_PATH, '/etc/._cfg0000_file_3'))

        test_package = Package(new_package_name, chroot_path=CHROOT_PATH)
        assert '/etc/file_3' in test_package
        with open(join_paths(CHROOT_PATH,
                             '/etc/._cfg0000_file_3'), 'r') as output_file:
            output_file_text = output_file.read()
            assert output_file_text == output_text
        assert test_package.check_contents_data('/etc/._cfg0000_file_3',
                                         hashlib.md5(
                                             output_text.encode()).hexdigest())

        assert directory_processor.template_executor.\
            changed_files == {join_paths(CHROOT_PATH,
                                         '/etc/file_3'): 'C'}

    def test_if_templates_are_hierarchy_of_a_multiple_template_files_with_a_removed_or_changed_by_user_targets_and_there_is_the_autoupdate_parameter_in_the_root_calculate_directory_template__the_directory_processor_uses_autoupdate_parameter_for_all_templates_and_joins_all_templates_as_if_target_files_have_no_user_changes(self):
        datavars.main['cl_template_path'] = os.path.join(CHROOT_PATH,
                                                         'templates_10')
        directory_processor = DirectoryProcessor('install',
                                                 datavars_module=datavars)
        directory_processor.process_template_directories()
        header = ('#' + '-' * 79 + '\n' +
                  '# Modified by Calculate Utilities 4.0\n' +
                  '# Processed template files:\n' +
                  '# ' + '{0}' + '\n' +
                  '#' + '-' * 79 + '\n')

        header_1 = header.format('\n# '.join(
                                       [join_paths(
                                            CHROOT_PATH,
                                            'templates_10/root/etc/file_4')]))
        output_text_1 = '{0}{1}'.format(header_1,
                                        ("options {\n    parameter-0 no;"
                                         + "\n    parameter-1 "
                                         + datavars.ns.variable_1
                                         + ";\n    parameter-2 "
                                         + datavars.ns.variable_2
                                         + ";\n};\n"))
        header_2 = header.format('\n# '.join(
                                       [join_paths(
                                            CHROOT_PATH,
                                            'templates_10/root/etc/file_5')]))
        output_text_2 = '{0}{1}'.format(header_2,
                                        ("options {\n    parameter-1 "
                                         + datavars.ns.variable_1
                                         + ";\n    parameter-2 "
                                         + datavars.ns.variable_2
                                         + ";\n};\n"))

        header_3 = header.format('\n# '.join(
                                   [join_paths(
                                       CHROOT_PATH,
                                       'templates_10/root/etc/dir_7/file_0')]))
        output_text_3 = '{0}{1}'.format(header_3,
                                        ("options {\n    parameter-0 no;"
                                         + "\n    parameter-1 "
                                         + datavars.ns.variable_1
                                         + ";\n    parameter-2 "
                                         + datavars.ns.variable_2
                                         + ";\n};\n"))

        assert os.path.exists(join_paths(CHROOT_PATH, '/etc/file_4'))
        assert not os.path.exists(join_paths(CHROOT_PATH,
                                             '/etc/._cfg0001_file_4'))
        assert os.path.exists(join_paths(CHROOT_PATH, '/etc/file_5'))
        assert not os.path.exists(join_paths(CHROOT_PATH,
                                             '/etc/._cfg0001_file_5'))
        assert os.path.exists(join_paths(CHROOT_PATH, '/etc/dir_7/file_0'))
        assert not os.path.exists(join_paths(CHROOT_PATH,
                                             '/etc/dir_7/._cfg0001_file_0'))

        test_package = Package(new_package_name, chroot_path=CHROOT_PATH)
        assert '/etc/file_4' in test_package
        assert '/etc/file_5' in test_package
        assert '/etc/dir_7/file_0' in test_package

        with open(join_paths(CHROOT_PATH,
                             '/etc/file_4'), 'r') as output_file:
            output_file_text = output_file.read()
            assert output_file_text == output_text_1
        assert test_package.check_contents_data('/etc/file_4',
                                         hashlib.md5(
                                           output_text_1.encode()).hexdigest())
        with open(join_paths(CHROOT_PATH,
                             '/etc/file_5'), 'r') as output_file:
            output_file_text = output_file.read()
            assert output_file_text == output_text_2
        assert test_package.check_contents_data('/etc/file_5',
                                         hashlib.md5(
                                           output_text_2.encode()).hexdigest())
        with open(join_paths(CHROOT_PATH,
                             '/etc/dir_7/file_0'), 'r') as output_file:
            output_file_text = output_file.read()
            assert output_file_text == output_text_3
        assert test_package.check_contents_data('/etc/dir_7/file_0',
                                                hashlib.md5(
                                                    output_text_3.encode()
                                                           ).hexdigest())

        assert directory_processor.template_executor.\
            changed_files == {join_paths(CHROOT_PATH,
                                         '/etc/file_4'): 'M',
                              join_paths(CHROOT_PATH,
                                         '/etc/file_5'): 'N',
                              join_paths(CHROOT_PATH,
                                         '/etc/dir_7/file_0'): 'M'}

    def test_if_the_template_directory_have_no_the_action_parameter_value_and_append_parameter_is_not_skip__the_directory_processor_skips_this_template_branch_and_sets_warning(self):
        datavars.main['cl_template_path'] = os.path.join(CHROOT_PATH,
                                                         'templates_11')
        io_module = IOModule(save_messages=True)
        warning_message = ("Action parameter is not set for template:"
                           " {0}").format(join_paths(
                                                   CHROOT_PATH,
                                                   '/templates_11/root/dir_8'))
        directory_processor = DirectoryProcessor('install',
                                                 datavars_module=datavars,
                                                 output_module=io_module)
        directory_processor.process_template_directories()
        assert not os.path.exists(join_paths(CHROOT_PATH, '/etc/dir_8'))
        assert io_module.messages[-1] == ('warning', warning_message)

        assert directory_processor.template_executor.\
            changed_files == {}

    def test_if_the_template_has_two_root_directories_with_different_action_values_and_directory_processor_intialized_for_the_one_of_this_actions__the_directory_processor_skips_one_this_template_s_roots_and_processed_a_template_s_root_with_the_same_action_parameter_value(self):
        datavars.main['cl_template_path'] = os.path.join(CHROOT_PATH,
                                                         'templates_12')
        io_module = IOModule(save_messages=True)
        warning_message = ("Action parameter value '{0}' does not match its"
                           " current value '{1}'. Template: {2}").format(
                                                   'update',
                                                   'install',
                                                   join_paths(
                                                      CHROOT_PATH,
                                                      '/templates_12/root_1'))
        directory_processor = DirectoryProcessor('install',
                                                 datavars_module=datavars,
                                                 output_module=io_module)
        directory_processor.process_template_directories()
        assert os.path.exists(join_paths(CHROOT_PATH, '/etc/file_6'))
        assert not os.path.exists(join_paths(CHROOT_PATH, '/etc/file_7'))
        assert ('warning', warning_message) in io_module.messages

        assert directory_processor.template_executor.\
            changed_files == {join_paths(CHROOT_PATH,
                                         '/etc/file_6'): 'N'}

    def test_if_some_template_directories_have_no_the_action_parameter_value_but_the_append_parameter_s_value_is_skip__the_directory_processor_does_not_stop_the_directories_processing_and_sends_no_warnings(self):
        datavars.main['cl_template_path'] = os.path.join(CHROOT_PATH,
                                                         'templates_13')
        directory_processor = DirectoryProcessor('install',
                                                 datavars_module=datavars)
        directory_processor.process_template_directories()
        assert os.path.exists(join_paths(CHROOT_PATH, '/etc/file_8'))

        assert directory_processor.template_executor.\
            changed_files == {join_paths(CHROOT_PATH,
                                         '/etc/file_8'): 'N'}

    def test_if_template_s_directory_contains_two_directories_with_single_template_files_that_belongs_to_a_different_packages_and_target_files_does_not_exist__the_directory_processor_creates_two_files_and_adds_them_to_a_different_packages(self):
        datavars.main['cl_template_path'] = os.path.join(CHROOT_PATH,
                                                         'templates_14')
        directory_processor = DirectoryProcessor('install',
                                                 datavars_module=datavars)
        directory_processor.process_template_directories()

        test_package = Package(test_package_name_1, chroot_path=CHROOT_PATH)
        other_package = Package(other_package_name, chroot_path=CHROOT_PATH)

        assert os.path.exists(join_paths(CHROOT_PATH, '/etc/dir_9'))
        assert os.path.exists(join_paths(CHROOT_PATH, '/etc/dir_9/file_0'))
        assert '/etc/dir_9/file_0' in other_package

        assert os.path.exists(join_paths(CHROOT_PATH, '/etc/dir_10'))
        assert os.path.exists(join_paths(CHROOT_PATH, '/etc/dir_10/file_0'))
        assert '/etc/dir_10/file_0' in test_package

        assert directory_processor.template_executor.\
            changed_files == {join_paths(CHROOT_PATH,
                                         '/etc/dir_9/file_0'): 'N',
                              join_paths(CHROOT_PATH,
                                         '/etc/dir_10/file_0'): 'N',
                              join_paths(CHROOT_PATH,
                                         '/etc/dir_9'): 'N',
                              join_paths(CHROOT_PATH,
                                         '/etc/dir_10'): 'N'}

    def test_if_template_s_directory_contains_one_directory_with_a_template_file_without_a_package_value_target_file_does_not_exist_and_template_executor_is_not_able_to_detect_package_using_target_path__the_directory_processor_skips_this_template_and_sets_error_in_the_output(self):
        datavars.main['cl_template_path'] = os.path.join(CHROOT_PATH,
                                                         'templates_15')
        error_message = ("Template execution error: collision: 'package' "
                         "parameter is not defined for template with 'append' "
                         "parameter. Template: {}"
                         ).format(os.path.join(CHROOT_PATH,
                                               'templates_15/root/dir_11'))

        io_module = IOModule(save_messages=True)
        directory_processor = DirectoryProcessor('install',
                                                 datavars_module=datavars,
                                                 output_module=io_module)
        directory_processor.process_template_directories()

        assert not os.path.exists(join_paths(CHROOT_PATH,
                                             '/etc/dir_11'))
        assert not os.path.exists(join_paths(CHROOT_PATH,
                                             '/etc/dir_11/file_0'))
        assert ('error', error_message) in io_module.messages

        assert directory_processor.template_executor.\
            changed_files == {}

    def test_if_template_s_directory_contains_one_directory_with_a_template_file_without_a_package_value_target_file_exists_and_template_executor_is_able_to_detect_package_using_target_path__the_directory_processor_joins_template_to_a_target_file_and_updates_the_CONTENTS_file(self):
        datavars.main['cl_template_path'] = os.path.join(CHROOT_PATH,
                                                         'templates_16')

        directory_processor = DirectoryProcessor('install',
                                                 datavars_module=datavars)
        directory_processor.process_template_directories()
        new_package = Package(new_package_name, chroot_path=CHROOT_PATH)

        assert os.path.exists(join_paths(CHROOT_PATH,
                                         '/etc/dir_12'))
        assert os.path.exists(join_paths(CHROOT_PATH,
                                         '/etc/dir_12/file_0'))
        assert '/etc/dir_12/file_0' in new_package

        assert directory_processor.template_executor.\
            changed_files == {join_paths(CHROOT_PATH,
                                         '/etc/dir_12/file_0'): 'M'}

    def test_if_template_s_directory_contains_two_directories_with_single_template_files_that_belongs_to_a_different_packages_and_target_files_does_not_exist_and_directory_processor_is_used_for_a_package__the_directory_processor_creates_one_file_using_template_with_actual_package_parameter_and_adds_it_to_a_package_and_add_to_the_packages_file_trees_a_directory_with_an_other_template(self):
        datavars.main['cl_template_path'] = os.path.join(CHROOT_PATH,
                                                         'templates_17')
        directory_processor = DirectoryProcessor('install',
                                                 datavars_module=datavars,
                                                 package=other_package_name)
        directory_processor.process_template_directories()

        test_package = Package(test_package_name_1, chroot_path=CHROOT_PATH)
        other_package = Package(other_package_name, chroot_path=CHROOT_PATH)

        assert os.path.exists(join_paths(CHROOT_PATH, '/etc/dir_13'))
        assert os.path.exists(join_paths(CHROOT_PATH, '/etc/dir_13/file_0'))
        assert '/etc/dir_13/file_0' in other_package

        assert not os.path.exists(join_paths(CHROOT_PATH, '/etc/dir_14'))
        assert not os.path.exists(join_paths(CHROOT_PATH,
                                             '/etc/dir_14/file_0'))
        assert '/etc/dir_14/file_0' not in test_package

        assert directory_processor.template_executor.\
            changed_files == {join_paths(CHROOT_PATH,
                                         '/etc/dir_13'): 'N',
                              join_paths(CHROOT_PATH,
                                         '/etc/dir_13/file_0'): 'N'}

    def test_if_template_s_directory_contains_two_directories_with_single_template_files_that_belongs_to_a_different_packages_and_target_files_does_not_exist_and_one_of_a_template_files_has_the_merge_parameter_with_other_package_and_directory_processor_is_used_for_a_package__the_directory_processor_creates_one_file_using_template_with_actual_package_parameter_and_then_uses_the_packages_file_tree_to_merge_an_other_package(self):
        datavars.main['cl_template_path'] = os.path.join(CHROOT_PATH,
                                                         'templates_18')
        directory_processor = DirectoryProcessor('install',
                                                 datavars_module=datavars,
                                                 package=other_package_name)
        directory_processor.process_template_directories()

        test_package = Package(test_package_name_1, chroot_path=CHROOT_PATH)
        other_package = Package(other_package_name, chroot_path=CHROOT_PATH)

        assert os.path.exists(join_paths(CHROOT_PATH, '/etc/dir_15'))
        assert os.path.exists(join_paths(CHROOT_PATH, '/etc/dir_15/file_0'))
        assert '/etc/dir_15/file_0' in other_package

        assert os.path.exists(join_paths(CHROOT_PATH, '/etc/dir_16'))
        assert os.path.exists(join_paths(CHROOT_PATH,
                                         '/etc/dir_16/file_0'))
        assert '/etc/dir_16/file_0' in test_package

        assert directory_processor.template_executor.\
            changed_files == {join_paths(CHROOT_PATH,
                                         '/etc/dir_15'): 'N',
                              join_paths(CHROOT_PATH,
                                         '/etc/dir_15/file_0'): 'N',
                              join_paths(CHROOT_PATH,
                                         '/etc/dir_16'): 'N',
                              join_paths(CHROOT_PATH,
                                         '/etc/dir_16/file_0'): 'N'}

    def test_if_template_s_directory_contains_a_template_directory_which_target_is_a_link_to_an_other_directory_and_force_parameter_is_not_set__the_directory_processor_changes_a_template_target_path_to_a_link_source_path_and_joins_all_templates_from_the_template_directory(self):
        datavars.main['cl_template_path'] = os.path.join(CHROOT_PATH,
                                                         'templates_19')
        directory_processor = DirectoryProcessor('install',
                                                 datavars_module=datavars)
        directory_processor.process_template_directories()
        test_package = Package(test_package_name_1, chroot_path=CHROOT_PATH)

        # Для разнообразия один из шаблонов удаляет файл, а не создает.
        assert not os.path.exists(join_paths(CHROOT_PATH,
                                             '/etc/dir_18/file_0'))
        assert '/etc/dir_18/file_0' not in test_package

        assert os.path.exists(join_paths(CHROOT_PATH,
                                         '/etc/dir_18/dir_0'))
        assert os.path.exists(join_paths(CHROOT_PATH,
                                         '/etc/dir_18/dir_0/file_0'))
        assert '/etc/dir_18/dir_0/file_0' in test_package

        assert directory_processor.template_executor.\
            changed_files == {join_paths(CHROOT_PATH,
                                         '/etc/dir_18/dir_0'): 'N',
                              join_paths(CHROOT_PATH,
                                         '/etc/dir_18/dir_0/file_0'): 'N',
                              join_paths(CHROOT_PATH,
                                         '/etc/dir_18/file_0'): 'D'}

    def test_if_template_s_directory_contains_a_template_directory_which_target_is_a_link_to_an_other_directory_and_force_parameter_is_set__the_directory_processor_removes_link_on_a_target_path_and_joins_all_templates_from_a_template_directory(self):
        datavars.main['cl_template_path'] = os.path.join(CHROOT_PATH,
                                                         'templates_20')
        directory_processor = DirectoryProcessor('install',
                                                 datavars_module=datavars)
        directory_processor.process_template_directories()
        test_package = Package(test_package_name_1, chroot_path=CHROOT_PATH)

        # Для разнообразия один из шаблонов удаляет файл, а не создает.
        # Но в данном случае он ничего не сделает.
        assert os.path.exists(join_paths(CHROOT_PATH,
                                         '/etc/dir_20/file_0'))
        assert '/etc/dir_20/file_0' not in test_package

        assert not os.path.islink(join_paths(CHROOT_PATH, '/etc/dir_19'))
        assert os.path.isdir(join_paths(CHROOT_PATH, '/etc/dir_19'))

        assert os.path.exists(join_paths(CHROOT_PATH,
                                         '/etc/dir_19/dir_0'))
        assert os.path.exists(join_paths(CHROOT_PATH,
                                         '/etc/dir_19/dir_0/file_0'))
        assert '/etc/dir_19/dir_0/file_0' in test_package

        assert directory_processor.template_executor.\
            changed_files == {join_paths(CHROOT_PATH,
                                         '/etc/dir_19'): 'N',
                              join_paths(CHROOT_PATH,
                                         '/etc/dir_19/dir_0'): 'N',
                              join_paths(CHROOT_PATH,
                                         '/etc/dir_19/dir_0/file_0'): 'N'}

    def test_if_template_s_directory_contains_some_directories_with_single_template_files_that_belongs_to_a_different_packages_and_target_files_does_not_exist_and_one_of_a_template_file_has_the_merge_parameter_with_other_packages_and_directory_processor_is_used_for_a_package__the_directory_processor_creates_one_file_using_template_with_actual_package_parameter_and_then_uses_the_packages_file_trees_to_merge_other_packages(self):
        datavars.main['cl_template_path'] = os.path.join(CHROOT_PATH,
                                                         'templates_21')
        directory_processor = DirectoryProcessor('install',
                                                 datavars_module=datavars,
                                                 package=other_package_name)
        directory_processor.process_template_directories()

        test_package = Package(test_package_name_1, chroot_path=CHROOT_PATH)
        other_package = Package(other_package_name, chroot_path=CHROOT_PATH)
        new_package = Package(new_package_name, chroot_path=CHROOT_PATH)

        assert os.path.exists(join_paths(CHROOT_PATH, '/etc/dir_21'))
        assert os.path.exists(join_paths(CHROOT_PATH, '/etc/dir_21/file_0'))
        assert '/etc/dir_21/file_0' in other_package

        assert os.path.exists(join_paths(CHROOT_PATH, '/etc/dir_22'))
        assert os.path.exists(join_paths(CHROOT_PATH,
                                         '/etc/dir_22/file_0'))
        assert '/etc/dir_22/file_0' in test_package

        assert os.path.exists(join_paths(CHROOT_PATH, '/etc/dir_23'))
        assert os.path.exists(join_paths(CHROOT_PATH,
                                         '/etc/dir_23/file_0'))
        assert '/etc/dir_23/file_0' in new_package

        assert directory_processor.template_executor.\
            changed_files == {
                              join_paths(CHROOT_PATH,
                                         '/etc/dir_21'): 'N',
                              join_paths(CHROOT_PATH,
                                         '/etc/dir_21/file_0'): 'N',
                              join_paths(CHROOT_PATH,
                                         '/etc/dir_22'): 'N',
                              join_paths(CHROOT_PATH,
                                         '/etc/dir_22/file_0'): 'N',
                              join_paths(CHROOT_PATH,
                                         '/etc/dir_23'): 'N',
                              join_paths(CHROOT_PATH,
                                         '/etc/dir_23/file_0'): 'N'
                              }

    def test_if_template_s_directory_contains_some_directories_with_single_template_files_that_belong_to_a_different_packages_and_target_files_does_not_exist_and_some_of_a_template_files_have_the_merge_parameters_with_other_packages_and_directory_processor_is_used_for_a_package__the_directory_processor_creates_one_file_using_template_with_actual_package_parameter_and_then_uses_the_packages_file_trees_to_merge_other_packages(self):
        datavars.main['cl_template_path'] = os.path.join(CHROOT_PATH,
                                                         'templates_22')
        directory_processor = DirectoryProcessor(
                                         'install',
                                         datavars_module=datavars,
                                         package='test-category/other-package')
        directory_processor.process_template_directories()

        test_package = Package(test_package_name_1, chroot_path=CHROOT_PATH)
        other_package = Package(other_package_name, chroot_path=CHROOT_PATH)
        new_package = Package(new_package_name, chroot_path=CHROOT_PATH)

        assert os.path.exists(join_paths(CHROOT_PATH, '/etc/dir_24'))
        assert os.path.exists(join_paths(CHROOT_PATH, '/etc/dir_24/file_0'))
        assert '/etc/dir_24/file_0' in other_package

        assert os.path.exists(join_paths(CHROOT_PATH, '/etc/dir_25'))
        assert os.path.exists(join_paths(CHROOT_PATH,
                                         '/etc/dir_25/file_0'))
        assert '/etc/dir_25/file_0' in test_package

        assert os.path.exists(join_paths(CHROOT_PATH, '/etc/dir_26'))
        assert os.path.exists(join_paths(CHROOT_PATH,
                                         '/etc/dir_26/file_0'))
        assert '/etc/dir_26/file_0' in new_package

        assert directory_processor.template_executor.\
            changed_files == {
                              join_paths(CHROOT_PATH,
                                         '/etc/dir_24'): 'N',
                              join_paths(CHROOT_PATH,
                                         '/etc/dir_24/file_0'): 'N',
                              join_paths(CHROOT_PATH,
                                         '/etc/dir_25'): 'N',
                              join_paths(CHROOT_PATH,
                                         '/etc/dir_25/file_0'): 'N',
                              join_paths(CHROOT_PATH,
                                         '/etc/dir_26'): 'N',
                              join_paths(CHROOT_PATH,
                                         '/etc/dir_26/file_0'): 'N'
                              }

    def test_if_template_s_directory_contains_some_directories_with_single_template_files_and_file_that_belong_to_a_different_packages_and_target_files_does_not_exist_and_some_of_a_template_files_have_the_merge_parameters_with_other_packages_and_directory_processor_is_used_for_a_package__the_directory_processor_creates_one_file_using_template_with_actual_package_parameter_and_then_uses_the_packages_file_trees_to_merge_other_packages(self):
        datavars.main['cl_template_path'] = os.path.join(CHROOT_PATH,
                                                         'templates_23')
        directory_processor = DirectoryProcessor(
                                         'install',
                                         datavars_module=datavars,
                                         package='test-category/other-package')
        directory_processor.process_template_directories()

        test_package = Package(test_package_name_1, chroot_path=CHROOT_PATH)
        other_package = Package(other_package_name, chroot_path=CHROOT_PATH)

        print('DIRECTORY TREE:')
        for key in directory_processor.packages_file_trees.keys():
            print("{} -> {}".format(
                                 key,
                                 directory_processor.packages_file_trees[key]))

        assert os.path.exists(join_paths(CHROOT_PATH, '/etc/dir_27'))
        assert os.path.exists(join_paths(CHROOT_PATH, '/etc/dir_27/file_0'))
        assert '/etc/dir_27/file_0' in test_package

        assert os.path.exists(join_paths(CHROOT_PATH, '/etc/dir_28'))
        assert os.path.exists(join_paths(CHROOT_PATH,
                                         '/etc/dir_28/file_0'))
        assert '/etc/dir_28/file_0' in other_package

        assert os.path.exists(join_paths(CHROOT_PATH, '/etc/file_9'))
        assert '/etc/file_9' in test_package

        assert directory_processor.template_executor.\
            changed_files == {
                              join_paths(CHROOT_PATH,
                                         '/etc/dir_27'): 'N',
                              join_paths(CHROOT_PATH,
                                         '/etc/dir_27/file_0'): 'N',
                              join_paths(CHROOT_PATH,
                                         '/etc/dir_28'): 'N',
                              join_paths(CHROOT_PATH,
                                         '/etc/dir_28/file_0'): 'N',
                              join_paths(CHROOT_PATH,
                                         '/etc/file_9'): 'N'
                              }

    def test_if_templates_consist_only_one_directory_with_a_calculate_directory_file_a_single_template_file_with_condition_and_condition_is_true__the_directory_processor_creates_new_file_and_adds_one_in_the_CONTENTS_file(self):
        datavars.main['cl_template_path'] = os.path.join(CHROOT_PATH,
                                                         'templates_24')
        directory_processor = DirectoryProcessor('install',
                                                 datavars_module=datavars)
        directory_processor.process_template_directories()

        test_package = Package(test_package_name_1, chroot_path=CHROOT_PATH)
        assert os.path.exists(join_paths(CHROOT_PATH, '/etc/file_10'))
        assert '/etc/file_10' in test_package

        assert directory_processor.template_executor.\
            changed_files == {join_paths(CHROOT_PATH,
                                         '/etc/file_10'): 'N'}

    def test_if_templates_consist_only_one_directory_with_a_calculate_directory_file_a_single_template_file_with_condition_and_condition_is_false__the_directory_processor_does_nothing(self):
        datavars.main['cl_template_path'] = os.path.join(CHROOT_PATH,
                                                         'templates_25')
        directory_processor = DirectoryProcessor('install',
                                                 datavars_module=datavars)
        directory_processor.process_template_directories()

        test_package = Package(test_package_name_1, chroot_path=CHROOT_PATH)
        assert not os.path.exists(join_paths(CHROOT_PATH, '/etc/file_11'))
        assert '/etc/file_11' not in test_package

        assert directory_processor.template_executor.\
            changed_files == {}

    def test_if_templates_consist_only_one_directory_with_a_calculate_directory_file_with_a_single_directory_that_contains_calculate_directory_file_with_condition_that_is_true_and_a_single_template_file__the_directory_processor_creates_new_directory_and_file_and_adds_one_in_the_CONTENTS_file(self):
        datavars.main['cl_template_path'] = os.path.join(CHROOT_PATH,
                                                         'templates_26')
        directory_processor = DirectoryProcessor('install',
                                                 datavars_module=datavars)
        directory_processor.process_template_directories()

        test_package = Package(test_package_name_1, chroot_path=CHROOT_PATH)

        assert os.path.exists(join_paths(CHROOT_PATH, '/etc/dir_29'))
        assert os.path.exists(join_paths(CHROOT_PATH, '/etc/dir_29/file_0'))

        assert '/etc/dir_29' in test_package
        assert '/etc/dir_29/file_0' in test_package

        assert directory_processor.template_executor.\
            changed_files == {join_paths(CHROOT_PATH,
                                         '/etc/dir_29'): 'N',
                              join_paths(CHROOT_PATH,
                                         '/etc/dir_29/file_0'): 'N'}

    def test_if_templates_consist_only_one_directory_with_a_calculate_directory_file_with_a_single_directory_that_contains_calculate_directory_file_with_condition_that_is_false_and_a_single_template_file__the_directory_processor_creates_new_directory_and_file_and_adds_one_in_the_CONTENTS_file(self):
        datavars.main['cl_template_path'] = os.path.join(CHROOT_PATH,
                                                         'templates_27')
        directory_processor = DirectoryProcessor('install',
                                                 datavars_module=datavars)
        directory_processor.process_template_directories()

        test_package = Package(test_package_name_1, chroot_path=CHROOT_PATH)

        assert not os.path.exists(join_paths(CHROOT_PATH,
                                             '/etc/dir_30'))
        assert not os.path.exists(join_paths(CHROOT_PATH,
                                             '/etc/dir_30/file_0'))

        assert '/etc/dir_30' not in test_package
        assert '/etc/dir_30/file_0' not in test_package

        assert directory_processor.template_executor.\
            changed_files == {}

    def test_if_templates_contain_a_template_file_with_a_target_path_to_a_file_with_some_cfg_files_and_changes_in_the_template_is_the_same_as_in_the_last_cfg_file__the_directory_processor_does_nothing(self):
        datavars.main['cl_template_path'] = os.path.join(CHROOT_PATH,
                                                         'templates_28')
        cfg_path_1 = os.path.join(CHROOT_PATH, 'etc/._cfg0000_file_12')
        cfg_path_2 = os.path.join(CHROOT_PATH, 'etc/._cfg0001_file_12')

        directory_processor = DirectoryProcessor('install',
                                                 datavars_module=datavars)
        directory_processor.process_template_directories()

        directory_processor = DirectoryProcessor('install',
                                                 datavars_module=datavars)
        directory_processor.process_template_directories()

        assert os.path.exists(join_paths(CHROOT_PATH, 'etc/file_12'))
        assert os.path.exists(cfg_path_1)
        assert not os.path.exists(cfg_path_2)

        assert '/etc/file_12'\
            in directory_processor.template_executor.calculate_config_file

        assert directory_processor.template_executor.\
            changed_files == {}

    def test_if_templates_contain_a_template_file_with_the_run_parameter_and_a_correct_script___the_directory_processor_runs_the_script_using_the_interpreter_from_the_run_parameter(self):
        datavars.main['cl_template_path'] = os.path.join(CHROOT_PATH,
                                                         'templates_29')
        directory_processor = DirectoryProcessor('install',
                                                 datavars_module=datavars)
        directory_processor.process_template_directories()

        # Скрипт создает файл.
        assert os.path.exists(join_paths(CHROOT_PATH, 'etc/file_13'))

        # Из скрипта не получить список файлов измененных или созданных
        # шаблоном.
        assert directory_processor.template_executor.\
            changed_files == {}

    def test_if_templates_contain_a_directory_with_a_calculate_directory_file_with_the_run_parameter_and_a_correct_script___the_directory_processor_runs_the_script_using_the_interpreter_from_the_run_parameter(self):
        datavars.main['cl_template_path'] = os.path.join(CHROOT_PATH,
                                                         'templates_30')
        directory_processor = DirectoryProcessor('install',
                                                 datavars_module=datavars)
        directory_processor.process_template_directories()

        # Скрипт создает файл.
        assert not os.path.exists(join_paths(CHROOT_PATH, 'etc/file_14'))

        assert directory_processor.template_executor.\
            changed_files == {}

    def test_if_templates_contain_some_files_with_the_exec_parameter_and_a_correct_scripts___the_directory_processor_saves_all_the_scripts_in_the_special_execute_directory_and_runs_all_the_files_after_all_templates_are_joined_and_packages_from_the_merge_parameter_is_processed(self):
        datavars.main['cl_template_path'] = os.path.join(CHROOT_PATH,
                                                         'templates_31')
        directory_processor = DirectoryProcessor('install',
                                                 datavars_module=datavars)
        directory_processor.process_template_directories()

        assert os.path.exists(join_paths(CHROOT_PATH, 'etc/dir_31'))
        assert os.path.exists(join_paths(CHROOT_PATH, 'etc/dir_31/file_0'))
        assert os.path.exists(join_paths(CHROOT_PATH, 'etc/file_17'))

        assert os.path.exists(join_paths(CHROOT_PATH, 'etc/file_15'))
        with open(join_paths(CHROOT_PATH, '/etc/file_15'), 'r') as file_15:
            file_text = file_15.read()
            assert file_text == 'There is a strange type = static'

        assert os.path.exists(join_paths(CHROOT_PATH, 'etc/file_16'))
        with open(join_paths(CHROOT_PATH, '/etc/file_16'), 'r') as file_16:
            file_text = file_16.read()
            assert file_text == 'There is a value = 128'

        assert directory_processor.template_executor.\
            changed_files == {join_paths(CHROOT_PATH,
                                         '/etc/dir_31'): 'N',
                              join_paths(CHROOT_PATH,
                                         '/etc/dir_31/file_0'): 'N',
                              join_paths(CHROOT_PATH,
                                         '/etc/file_17'): 'N'}

    def test_multiple_actions(self):
        datavars.main['cl_template_path'] = os.path.join(CHROOT_PATH,
                                                         'templates_32')
        directory_processor = DirectoryProcessor(['install', 'update'],
                                                 datavars_module=datavars)
        directory_processor.process_template_directories()
        test_package = Package(test_package_name_1, chroot_path=CHROOT_PATH)

        assert os.path.exists(join_paths(CHROOT_PATH,
                                         'etc/dir_32'))
        assert os.path.exists(join_paths(CHROOT_PATH,
                                         'etc/dir_32/file_0'))
        assert '/etc/dir_32/file_0' in test_package

        assert os.path.exists(join_paths(CHROOT_PATH,
                                         'etc/dir_33'))
        assert os.path.exists(join_paths(CHROOT_PATH,
                                         'etc/dir_33/file_0'))
        assert '/etc/dir_33/file_0' in test_package

        assert directory_processor.template_executor.\
            changed_files == {join_paths(CHROOT_PATH,
                                         '/etc/dir_32'): 'N',
                              join_paths(CHROOT_PATH,
                                         '/etc/dir_32/file_0'): 'N',
                              join_paths(CHROOT_PATH,
                                         '/etc/dir_33'): 'N',
                              join_paths(CHROOT_PATH,
                                         '/etc/dir_33/file_0'): 'N'}

    def test_None_package(self):
        datavars.main['cl_template_path'] = os.path.join(CHROOT_PATH,
                                                         'templates_33')
        directory_processor = DirectoryProcessor(['install', 'update'],
                                                 datavars_module=datavars)
        directory_processor.process_template_directories()
        test_package = Package(test_package_name_1, chroot_path=CHROOT_PATH)

        assert os.path.exists(join_paths(CHROOT_PATH,
                                         'etc/dir_35'))
        assert os.path.exists(join_paths(CHROOT_PATH,
                                         'etc/dir_35/file_0'))
        assert '/etc/dir_35/file_0' in test_package

        assert directory_processor.template_executor.\
            changed_files == {join_paths(CHROOT_PATH,
                                         '/etc/dir_35'): 'N',
                              join_paths(CHROOT_PATH,
                                         '/etc/dir_35/file_0'): 'N'}

    def test_handlers_basic(self):
        try:
            datavars.main['cl_template_path'] = os.path.join(CHROOT_PATH,
                                                             'templates_35')
            directory_processor = DirectoryProcessor(
                                           'install',
                                           datavars_module=datavars,
                                           package='test-category/test-package'
                                                     )
            directory_processor.process_template_directories()
            test_package = Package(test_package_name_1, chroot_path=CHROOT_PATH)

            # Тестируем handler_0 -- это просто обработчик-скрипт.
            assert os.path.exists(join_paths(CHROOT_PATH,
                                             'etc/dir_37'))
            assert os.path.exists(join_paths(CHROOT_PATH,
                                             'etc/dir_37/file_0'))
            assert '/etc/dir_37/file_0' in test_package

            # Тестируем handler_0 -- это просто обработчик-шаблон с notify.
            assert os.path.exists(join_paths(CHROOT_PATH,
                                             'etc/dir_38'))
            assert os.path.exists(join_paths(CHROOT_PATH,
                                             'etc/dir_38/file_0'))

            # Тестируем handler_1 -- это просто обработчик-шаблон с notify.
            assert os.path.exists(join_paths(CHROOT_PATH,
                                             'etc/dir_39'))
            assert os.path.exists(join_paths(CHROOT_PATH,
                                             'etc/dir_39/file_0'))

            # Тестируем handler_2 -- это просто обработчик-скрипт с notify.
            assert os.path.exists(join_paths(CHROOT_PATH,
                                             'etc/dir_40'))
            assert os.path.exists(join_paths(CHROOT_PATH,
                                             'etc/dir_40/file_0'))

            # Тестируем handler_3 -- это обработчик-шаблон с notify к
            # вызвавшему его handler_2 и handler_4, спрятанный в директории,
            # не являющейся обработчиком.
            assert os.path.exists(join_paths(CHROOT_PATH,
                                             'etc/dir_41'))
            assert os.path.exists(join_paths(CHROOT_PATH,
                                             'etc/dir_41/file_0'))

            # Тестируем handler_4 -- это обработчик с exec и notify.
            assert os.path.exists(join_paths(CHROOT_PATH,
                                             'etc/dir_42'))
            assert os.path.exists(join_paths(CHROOT_PATH,
                                             'etc/dir_42/file_0'))

            # Тестируем handler_5 -- это обработчик-директория.
            assert os.path.exists(join_paths(CHROOT_PATH,
                                             'etc/dir_43'))
            assert os.path.exists(join_paths(CHROOT_PATH,
                                             'etc/dir_43/file_0'))

            # Тестируем handler_6 -- это обработчик из обработчика-директрии.
            # Этот обработчик не выполняется.
            assert not os.path.exists(join_paths(CHROOT_PATH,
                                                 'etc/dir_44'))

            # Тестируем handler_7 -- это обработчик с параметром package.
            # Этот обработчик не выполняется.
            assert not os.path.exists(join_paths(CHROOT_PATH,
                                                 'etc/dir_45'))

            # Тестируем handler_8 -- это обработчик с параметром merge.
            # Этот обработчик не выполняется.
            assert not os.path.exists(join_paths(CHROOT_PATH,
                                                 'etc/dir_46'))

            # Тестируем handler_9 -- это обработчик замещенный другим.
            # Этот обработчик не выполняется.
            assert not os.path.exists(join_paths(CHROOT_PATH,
                                                 'etc/dir_47'))
            assert os.path.exists(join_paths(CHROOT_PATH,
                                             'etc/dir_48'))

            assert directory_processor.template_executor.\
                changed_files == {join_paths(CHROOT_PATH,
                                             '/etc/dir_37'): 'N',
                                  join_paths(CHROOT_PATH,
                                             '/etc/dir_37/file_0'): 'N',
                                  join_paths(CHROOT_PATH,
                                             '/etc/dir_39/file_0'): 'N',
                                  join_paths(CHROOT_PATH,
                                             '/etc/dir_41/file_0'): 'N',
                                  join_paths(CHROOT_PATH,
                                             '/etc/dir_43/file_0'): 'N',
                                  join_paths(CHROOT_PATH,
                                             '/etc/dir_48/file_0'): 'N'}
        except KeyboardInterrupt:
            assert False

    def test_merge_order(self):
        datavars.main['cl_template_path'] = os.path.join(CHROOT_PATH,
                                                         'templates_36')
        directory_processor = DirectoryProcessor(
                                       'install',
                                       datavars_module=datavars,
                                       package='test-category/test-package'
                                                 )
        directory_processor.process_template_directories()

        expected_output = {}
        real_output = {}

        for number in range(0, 3):
            expected_output.update({'file_{}'.format(number):
                                    'from script_{}'.format(number)})
            output_path = os.path.join(CHROOT_PATH,
                                       'etc/dir_50/file_{}'
                                       .format(number))
            with open(output_path, 'r') as output_file:
                output_text = output_file.read()
                real_output.update({'file_{}'.format(number): output_text})

        assert real_output == expected_output

        assert directory_processor.template_executor.\
            changed_files == {}

    def test_group_parameter_without_merge(self):
        datavars.main['cl_template_path'] = os.path.join(CHROOT_PATH,
                                                         'templates_37')
        directory_processor = DirectoryProcessor(
                'install',
                datavars_module=datavars,
                package='test-category/test-package',
                build='test-category/build-package-2.1:0[use_1,use_2]',
                uninstall='test-category/unmerged-package-1.0.1:1[use_1,use_2]'
                                                )
        assert 'build' in datavars.main.cl.groups
        assert 'uninstall' in datavars.main.cl.groups
        directory_processor.process_template_directories()
        assert os.path.exists(join_paths(CHROOT_PATH, '/etc/dir_51'))
        assert os.path.exists(join_paths(CHROOT_PATH, '/etc/dir_51/file_0'))

        assert os.path.exists(join_paths(CHROOT_PATH, '/etc/dir_52'))
        assert os.path.exists(join_paths(CHROOT_PATH, '/etc/dir_52/file_0'))

        assert os.path.exists(join_paths(CHROOT_PATH, '/etc/dir_53'))
        assert os.path.exists(join_paths(CHROOT_PATH, '/etc/dir_53/file_0'))

        assert os.path.exists(join_paths(CHROOT_PATH, '/etc/dir_54'))
        assert os.path.exists(join_paths(CHROOT_PATH, '/etc/dir_54/file_0'))

        assert directory_processor.template_executor.\
            changed_files == {join_paths(CHROOT_PATH,
                                         'etc/dir_51'): 'N',
                              join_paths(CHROOT_PATH,
                                         'etc/dir_51/file_0'): 'N'}

    def test_group_parameter_with_merge_parameter(self):
        datavars.main['cl_template_path'] = os.path.join(CHROOT_PATH,
                                                         'templates_38')
        directory_processor = DirectoryProcessor(
                'install',
                datavars_module=datavars,
                package='test-category/test-package',
                build='test-category/build-package-2.1:0[use_1,use_2]',
                uninstall='test-category/unmerged-package-1.0.1:1[use_1,use_2]'
                                                )
        assert 'build' in datavars.main.cl.groups
        assert 'uninstall' in datavars.main.cl.groups

        directory_processor.process_template_directories()
        assert os.path.exists(join_paths(CHROOT_PATH, '/etc/dir_55'))
        assert os.path.exists(join_paths(CHROOT_PATH, '/etc/dir_55/file_0'))

        assert os.path.exists(join_paths(CHROOT_PATH, '/etc/dir_56'))
        assert os.path.exists(join_paths(CHROOT_PATH, '/etc/dir_56/file_0'))

        assert directory_processor.template_executor.\
            changed_files == {join_paths(CHROOT_PATH,
                                         'etc/dir_55'): 'N',
                              join_paths(CHROOT_PATH,
                                         'etc/dir_55/file_0'): 'N',
                              join_paths(CHROOT_PATH,
                                         'etc/dir_56'): 'N',
                              join_paths(CHROOT_PATH,
                                         'etc/dir_56/file_0'): 'N'}

    def test_solving_collisions_for_the_same_packages_from_different_slots(self):
        datavars.main['cl_template_path'] = os.path.join(CHROOT_PATH,
                                                         'templates_39')
        directory_processor = DirectoryProcessor(
                                          'install',
                                          datavars_module=datavars,
                                          package='test-category/test-package'
                                                )

        header = ('#' + '-' * 79 + '\n' +
                  '# Modified by Calculate Utilities 4.0\n' +
                  '# Processed template files:\n' +
                  '# ' + '{0}' + '\n' +
                  '#' + '-' * 79 + '\n')

        header = header.format('\n# '.
                               join([join_paths(
                                       CHROOT_PATH,
                                       'templates_39/install/dir_57/file_0')]))
        output_text = '{0}{1}'.format(header,
                                      ("options {\n    parameter-0 yes;"
                                       + "\n    parameter-1 "
                                       + datavars.ns.variable_1
                                       + ";\n    parameter-2 "
                                       + datavars.ns.variable_2
                                       + ";\n};\n"))

        directory_processor.process_template_directories()
        test_package_0 = Package(test_package_name_0, chroot_path=CHROOT_PATH)
        test_package_1 = Package(test_package_name_1, chroot_path=CHROOT_PATH)

        assert os.path.exists(join_paths(CHROOT_PATH, '/etc/dir_57'))
        assert os.path.exists(join_paths(CHROOT_PATH, '/etc/dir_57/file_0'))
        with open(join_paths(CHROOT_PATH,
                             '/etc/dir_57/file_0'), 'r') as output:
            output = output.read()
            assert output_text == output
        assert '/etc/dir_57' in test_package_1
        assert '/etc/dir_57/file_0' in test_package_1
        assert '/etc/dir_57/file_0' not in test_package_0

    def test_solving_collisions_for_the_same_packages_from_different_slots_but_slot_was_set_in_the_package_parameter(self):
        datavars.main['cl_template_path'] = os.path.join(CHROOT_PATH,
                                                         'templates_40')
        directory_processor = DirectoryProcessor(
                                          'install',
                                          datavars_module=datavars)

        output_text = "options {\n    parameter-0 yes;\n};\n"

        directory_processor.process_template_directories()
        test_package_0 = Package(test_package_name_0, chroot_path=CHROOT_PATH)
        test_package_1 = Package(test_package_name_1, chroot_path=CHROOT_PATH)

        assert os.path.exists(join_paths(CHROOT_PATH, '/etc/dir_58'))
        assert os.path.exists(join_paths(CHROOT_PATH, '/etc/dir_58/file_0'))
        with open(join_paths(CHROOT_PATH,
                             '/etc/dir_58/file_0'), 'r') as output:
            output = output.read()
            assert output_text == output

        assert '/etc/dir_58' not in test_package_1
        assert '/etc/dir_58/file_0' not in test_package_1

        assert '/etc/dir_58' in test_package_0
        assert '/etc/dir_58/file_0' in test_package_0

    def test_solving_collisions_for_the_same_packages_from_different_slots_but_slot_was_set_in_the_for_package_parameter(self):
        datavars.main['cl_template_path'] = os.path.join(CHROOT_PATH,
                                                         'templates_41')
        directory_processor = DirectoryProcessor(
                                         'install',
                                         datavars_module=datavars,
                                         package='test-category/test-package:1'
                                                )

        output_text = "options {\n    parameter-0 yes;\n};\n"

        directory_processor.process_template_directories()
        test_package_0 = Package(test_package_name_0, chroot_path=CHROOT_PATH)
        test_package_1 = Package(test_package_name_1, chroot_path=CHROOT_PATH)

        assert os.path.exists(join_paths(CHROOT_PATH, '/etc/dir_59'))
        assert os.path.exists(join_paths(CHROOT_PATH, '/etc/dir_59/file_0'))
        with open(join_paths(CHROOT_PATH,
                             '/etc/dir_59/file_0'), 'r') as output:
            output = output.read()
            assert output_text == output

        assert '/etc/dir_59' not in test_package_1
        assert '/etc/dir_59/file_0' not in test_package_1

        assert '/etc/dir_59' in test_package_0
        assert '/etc/dir_59/file_0' in test_package_0

    def test_copy_file_using_source(self):
        datavars.main['cl_template_path'] = os.path.join(CHROOT_PATH,
                                                         'templates_42')
        directory_processor = DirectoryProcessor(
                                         'install',
                                         datavars_module=datavars,
                                         package='test-category/test-package'
                                                )
        directory_processor.process_template_directories()
        assert os.path.exists(join_paths(CHROOT_PATH, '/etc/copy.gif'))

    # def test_for_new_file(self):
    #     datavars.main['cl_template_path'] = os.path.join(CHROOT_PATH,
    #                                                      'templates_43')
    #     directory_processor = DirectoryProcessor(
    #                                      'merge',
    #                                      datavars_module=datavars,
    #                                      package='test-category/test-package'
    #                                             )

    def test_view_tree(self):
        list_path = join_paths(CHROOT_PATH, '/etc')
        show_tree(list_path)
        assert True

    def test_for_removing_testfile(self):
        shutil.rmtree(os.path.join(CHROOT_PATH, 'etc'))
        shutil.rmtree(os.path.join(CHROOT_PATH, 'var'))
