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