blob: 87f4b4a6cf2e71f0599c70763682b5c8ec8ada30 [file] [log] [blame]
Tomáš Pecka04eb7372022-06-07 08:03:04 +02001#!/usr/bin/env python3
2
3import json
4import re
5import os
6import pathlib
7import shutil
8import subprocess
9import sys
10
11import pytest
12
13
14SCRIPT_ROOT = pathlib.Path(__file__).resolve().parent
15BR2_ROOT = (SCRIPT_ROOT / '../../').resolve()
16
17INSTALL_SCRIPT_PATH = BR2_ROOT / 'package/czechlight-cfg-fs/czechlight-install-yang.sh'
18MIGRATE_SCRIPT_PATH = BR2_ROOT / 'package/czechlight-cfg-fs/czechlight-migrate.sh'
19MIGRATE_DEFINITIONS_PATH = BR2_ROOT / 'package/czechlight-cfg-fs/czechlight-migration-list.sh'
20NETOPEER_SCRIPT_PATH = BR2_ROOT / 'submodules/buildroot/package/netopeer2/setup.sh'
21
22CLA_SYSREPO_PATH = BR2_ROOT / 'submodules/cla-sysrepo'
23VELIA_PATH = BR2_ROOT / 'submodules/velia'
24NETOPEER2_PATH = BR2_ROOT / 'submodules/dependencies/Netopeer2'
25
26
27def run_and_wait(ctx, desc, command_args):
28 print(f'executing {desc}')
29 with subprocess.Popen(command_args, stdout=sys.stdout, stderr=sys.stderr, env=ctx.get_env()) as proc:
30 proc.wait()
31 assert proc.returncode == 0
32
33
34class SysrepoFixture:
35 def __init__(self, test_directory, tmp_path):
36 test_directory = SCRIPT_ROOT / test_directory
37 self.test_name = test_directory.name
38
39 self.expected_file = test_directory / 'expected.json'
40 assert self.expected_file.is_file()
41
42 startup = test_directory / 'startup.json'
43 assert startup.is_file()
44
45 self.proc_cmdline = test_directory / 'cmdline'
46 assert self.proc_cmdline.is_file()
47
48 version_file = test_directory / 'version'
49 assert version_file.is_file()
50
51 tested_xpath_file = test_directory / 'xpath'
52 self.tested_xpath = tested_xpath_file.read_text() if tested_xpath_file.is_file() else None
53
54 self._running_directory = tmp_path / self.test_name
55 self._running_directory.mkdir()
56
57 self.startup_file = self._running_directory / 'startup.json'
58 shutil.copyfile(startup, self.startup_file)
59
60 self.export_file = self._running_directory / 'export.json'
61
62 self.version_file = self._running_directory / 'version'
63 shutil.copy(version_file, self.version_file)
64
65 def get_env(self):
66 res = os.environ.copy()
67 res['SYSREPO_SHM_PREFIX'] = self.test_name
68 res['SYSREPO_REPOSITORY_PATH'] = self._running_directory / 'sysrepo_repository'
69 res['CLA_YANG'] = CLA_SYSREPO_PATH / 'yang'
70 res['VELIA_YANG'] = VELIA_PATH / 'yang'
71 res['PROC_CMDLINE'] = self.proc_cmdline
72 res['CFG_VERSION_FILE'] = self.version_file
73 res['CFG_STARTUP_FILE'] = self.startup_file
74 res['NP2_MODULE_DIR'] = NETOPEER2_PATH / 'modules'
75 res['NP2_MODULE_PERMS'] = '0600'
76 res['USER'] = os.getlogin()
77 return res
78
79
80@pytest.fixture(scope='session')
81def max_version():
82 """
83 Fetches last version from czechlight-migrate script by sourcing the
84 migration definitions file and verifying the length of the migration
85 files array.
86 """
87 args = ["/bin/bash", "-c", "source " + str(MIGRATE_DEFINITIONS_PATH) + " && echo ${#MIGRATION_FILES[@]}"]
88 with subprocess.Popen(args, stdout=subprocess.PIPE, stderr=subprocess.PIPE) as proc:
89 proc.wait()
90 stdout, stderr = proc.communicate()
91 assert stderr.decode().strip() == ''
92 assert proc.returncode == 0
93
94 return int(stdout.decode().strip())
95
96
97@pytest.fixture
98def sysrepo_fixture(request, tmp_path):
99 return SysrepoFixture(pathlib.Path(SCRIPT_ROOT / 'data' / request.param), tmp_path)
100
101
102def find_test_directories():
103 return [pytest.param(dirname) for dirname in os.listdir(path=SCRIPT_ROOT / 'data')]
104
105
106@pytest.mark.parametrize("sysrepo_fixture", find_test_directories(), indirect=True)
107def test(sysrepo_fixture, max_version):
108 # prepare sysrepo
109 run_and_wait(sysrepo_fixture, 'netopeer2 setup.sh', [NETOPEER_SCRIPT_PATH])
110 run_and_wait(sysrepo_fixture, 'czechlight-install-yang.sh', [INSTALL_SCRIPT_PATH])
111 run_and_wait(sysrepo_fixture, 'restoring startup.json to sysrepo', ['sysrepocfg', '--datastore', 'startup', '--format', 'json', f'--import={sysrepo_fixture.startup_file}'])
112
113 current_version = int(sysrepo_fixture.version_file.read_text())
114
115 # perform the actual migration
116 print(f'migration: current version is {current_version}')
117 print('migration: applying migration script')
118 run_and_wait(sysrepo_fixture, 'migration', [MIGRATE_SCRIPT_PATH])
119
120 after_migration_version = int(sysrepo_fixture.version_file.read_text())
121 assert after_migration_version == max_version
122
123 print('migration: checking datastore contents')
124 export_args = ['sysrepocfg', '--datastore', 'startup', '-f', 'json', f'--export={sysrepo_fixture.export_file}']
125 if sysrepo_fixture.tested_xpath:
126 export_args += ['-x', sysrepo_fixture.tested_xpath]
127 run_and_wait(sysrepo_fixture, 'export', export_args)
128
129 with open(sysrepo_fixture.export_file, 'r') as fp_actual:
130 with open(sysrepo_fixture.expected_file, 'r') as fp_expected:
131 print(f'migration: comparing files {sysrepo_fixture.startup_file.name} and {sysrepo_fixture.expected_file.name}')
132
133 actual = json.load(fp_actual)
134 expected = json.load(fp_expected)
135 assert actual == expected