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