diff --git a/src/tests/helper.py b/src/tests/helper.py index f7033148a..cc0710494 100644 --- a/src/tests/helper.py +++ b/src/tests/helper.py @@ -1,24 +1,22 @@ -#!/usr/bin/env python3 -# -# Copyright (C) 2018 VyOS maintainers and contributors +# Copyright (C) 2018-2024 VyOS maintainers and contributors # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License version 2 or later as # published by the Free Software Foundation. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see <http://www.gnu.org/licenses/>. import sys import importlib.util def prepare_module(file_path='', module_name=''): spec = importlib.util.spec_from_file_location(module_name, file_path) module = importlib.util.module_from_spec(spec) spec.loader.exec_module(module) sys.modules[module_name] = module diff --git a/src/tests/test_config_diff.py b/src/tests/test_config_diff.py index 61a2f3487..39e17613a 100644 --- a/src/tests/test_config_diff.py +++ b/src/tests/test_config_diff.py @@ -1,69 +1,67 @@ -#!/usr/bin/env python3 -# # Copyright (C) 2023-2024 VyOS maintainers and contributors # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License version 2 or later as # published by the Free Software Foundation. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see <http://www.gnu.org/licenses/>. import vyos.configtree from unittest import TestCase class TestConfigDiff(TestCase): def setUp(self): with open('tests/data/config.left', 'r') as f: config_string = f.read() self.config_left = vyos.configtree.ConfigTree(config_string) with open('tests/data/config.right', 'r') as f: config_string = f.read() self.config_right = vyos.configtree.ConfigTree(config_string) self.config_null = vyos.configtree.ConfigTree('') def test_unit(self): diff = vyos.configtree.DiffTree(self.config_left, self.config_null) sub = diff.sub self.assertEqual(sub.to_string(), self.config_left.to_string()) diff = vyos.configtree.DiffTree(self.config_null, self.config_left) add = diff.add self.assertEqual(add.to_string(), self.config_left.to_string()) def test_symmetry(self): lr_diff = vyos.configtree.DiffTree(self.config_left, self.config_right) rl_diff = vyos.configtree.DiffTree(self.config_right, self.config_left) sub = lr_diff.sub add = rl_diff.add self.assertEqual(sub.to_string(), add.to_string()) add = lr_diff.add sub = rl_diff.sub self.assertEqual(add.to_string(), sub.to_string()) def test_identity(self): lr_diff = vyos.configtree.DiffTree(self.config_left, self.config_right) sub = lr_diff.sub inter = lr_diff.inter add = lr_diff.add r_union = vyos.configtree.union(add, inter) l_union = vyos.configtree.union(sub, inter) self.assertEqual(r_union.to_string(), self.config_right.to_string(ordered_values=True)) self.assertEqual(l_union.to_string(), self.config_left.to_string(ordered_values=True)) diff --git a/src/tests/test_config_parser.py b/src/tests/test_config_parser.py index c69732daa..9a4f02859 100644 --- a/src/tests/test_config_parser.py +++ b/src/tests/test_config_parser.py @@ -1,55 +1,53 @@ -#!/usr/bin/env python3 -# # Copyright (C) 2018-2024 VyOS maintainers and contributors # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License version 2 or later as # published by the Free Software Foundation. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see <http://www.gnu.org/licenses/>. import vyos.configtree from unittest import TestCase class TestConfigParser(TestCase): def setUp(self): with open('tests/data/config.valid', 'r') as f: config_string = f.read() self.config = vyos.configtree.ConfigTree(config_string) def test_top_level_valueless(self): self.assertTrue(self.config.exists(["top-level-valueless-node"])) def test_top_level_leaf(self): self.assertTrue(self.config.exists(["top-level-leaf-node"])) self.assertEqual(self.config.return_value(["top-level-leaf-node"]), "foo") def test_top_level_tag(self): self.assertTrue(self.config.exists(["top-level-tag-node"])) # Sorting is now intentional, during parsing of config self.assertEqual(self.config.list_nodes(["top-level-tag-node"]), ["bar", "foo"]) def test_copy(self): self.config.copy(["top-level-tag-node", "bar"], ["top-level-tag-node", "baz"]) print(self.config.to_string()) self.assertTrue(self.config.exists(["top-level-tag-node", "baz"])) def test_copy_duplicate(self): with self.assertRaises(vyos.configtree.ConfigTreeError): self.config.copy(["top-level-tag-node", "foo"], ["top-level-tag-node", "bar"]) def test_rename(self): self.config.rename(["top-level-tag-node", "bar"], "quux") print(self.config.to_string()) self.assertTrue(self.config.exists(["top-level-tag-node", "quux"])) def test_rename_duplicate(self): with self.assertRaises(vyos.configtree.ConfigTreeError): self.config.rename(["top-level-tag-node", "foo"], "bar") diff --git a/src/tests/test_configverify.py b/src/tests/test_configverify.py index 15ccdf13d..f1ec65cd2 100644 --- a/src/tests/test_configverify.py +++ b/src/tests/test_configverify.py @@ -1,33 +1,31 @@ -#!/usr/bin/env python3 -# -# Copyright (C) 2020 VyOS maintainers and contributors +# Copyright (C) 2020-2024 VyOS maintainers and contributors # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License version 2 or later as # published by the Free Software Foundation. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see <http://www.gnu.org/licenses/>. from unittest import TestCase from vyos.configverify import verify_diffie_hellman_length from vyos.utils.process import cmd dh_file = '/tmp/dh.pem' class TestDictSearch(TestCase): def setUp(self): pass def test_dh_key_none(self): self.assertFalse(verify_diffie_hellman_length('/tmp/non_existing_file', '1024')) def test_dh_key_512(self): key_len = '512' cmd(f'openssl dhparam -out {dh_file} {key_len}') self.assertTrue(verify_diffie_hellman_length(dh_file, key_len)) diff --git a/src/tests/test_dependency_graph.py b/src/tests/test_dependency_graph.py index f682e87bb..f3f1db376 100644 --- a/src/tests/test_dependency_graph.py +++ b/src/tests/test_dependency_graph.py @@ -1,31 +1,29 @@ -#!/usr/bin/env python3 -# -# Copyright (C) 2023 VyOS maintainers and contributors +# Copyright (C) 2023-2024 VyOS maintainers and contributors # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License version 2 or later as # published by the Free Software Foundation. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see <http://www.gnu.org/licenses/>. import os from vyos.configdep import check_dependency_graph _here = os.path.dirname(__file__) ddir = os.path.join(_here, '../../data/config-mode-dependencies') from unittest import TestCase class TestDependencyGraph(TestCase): def setUp(self): pass def test_acyclic(self): res = check_dependency_graph(dependency_dir=ddir) self.assertTrue(res) diff --git a/src/tests/test_dict_search.py b/src/tests/test_dict_search.py index 2435d89c7..6b4bc933a 100644 --- a/src/tests/test_dict_search.py +++ b/src/tests/test_dict_search.py @@ -1,84 +1,82 @@ -#!/usr/bin/env python3 -# -# Copyright (C) 2020 VyOS maintainers and contributors +# Copyright (C) 2020-2024 VyOS maintainers and contributors # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License version 2 or later as # published by the Free Software Foundation. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see <http://www.gnu.org/licenses/>. from unittest import TestCase from vyos.utils.dict import dict_search from vyos.utils.dict import dict_search_recursive data = { 'string': 'fooo', 'nested': {'string': 'bar', 'empty': '', 'list': ['foo', 'bar']}, 'non': {}, 'list': ['bar', 'baz'], 'dict': {'key_1': {}, 'key_2': 'vyos'}, 'interfaces': {'dummy': {'dum0': {'address': ['192.0.2.17/29']}}, 'ethernet': {'eth0': {'address': ['2001:db8::1/64', '192.0.2.1/29'], 'description': 'Test123', 'duplex': 'auto', 'hw_id': '00:00:00:00:00:01', 'speed': 'auto'}, 'eth1': {'address': ['192.0.2.9/29'], 'description': 'Test456', 'duplex': 'auto', 'hw_id': '00:00:00:00:00:02', 'speed': 'auto'}}} } class TestDictSearch(TestCase): def setUp(self): pass def test_non_existing_keys(self): # TestDictSearch: Return False when querying for non-existent key self.assertEqual(dict_search('non_existing', data), None) self.assertEqual(dict_search('non.existing.fancy.key', data), None) def test_string(self): # TestDictSearch: Return value when querying string self.assertEqual(dict_search('string', data), data['string']) def test_list(self): # TestDictSearch: Return list items when querying list self.assertEqual(dict_search('list', data), data['list']) def test_dict_key_value(self): # TestDictSearch: Return dictionary keys value when value is present self.assertEqual(dict_search('dict.key_2', data), data['dict']['key_2']) def test_nested_dict_key_value(self): # TestDictSearch: Return string value of last key when querying for a nested string self.assertEqual(dict_search('nested.string', data), data['nested']['string']) def test_nested_dict_key_empty(self): # TestDictSearch: Return False when querying for a nested string whose last key is empty self.assertEqual(dict_search('nested.empty', data), '') self.assertFalse(dict_search('nested.empty', data)) def test_nested_list(self): # TestDictSearch: Return list items when querying nested list self.assertEqual(dict_search('nested.list', data), data['nested']['list']) def test_invalid_input(self): # TestDictSearch: Return list items when querying nested list self.assertEqual(dict_search('nested.list', None), None) self.assertEqual(dict_search(None, data), None) def test_dict_search_recursive(self): # Test nested search in dictionary tmp = list(dict_search_recursive(data, 'hw_id')) self.assertEqual(len(tmp), 2) tmp = list(dict_search_recursive(data, 'address')) self.assertEqual(len(tmp), 3) diff --git a/src/tests/test_find_device_file.py b/src/tests/test_find_device_file.py old mode 100755 new mode 100644 index f18043d65..21fc113f9 --- a/src/tests/test_find_device_file.py +++ b/src/tests/test_find_device_file.py @@ -1,35 +1,33 @@ -#!/usr/bin/env python3 -# -# Copyright (C) 2020 VyOS maintainers and contributors +# Copyright (C) 2020-2024 VyOS maintainers and contributors # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License version 2 or later as # published by the Free Software Foundation. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see <http://www.gnu.org/licenses/>. from unittest import TestCase from vyos.utils.system import find_device_file class TestDeviceFile(TestCase): """ used to find USB devices on target """ def setUp(self): pass def test_null(self): self.assertEqual(find_device_file('null'), '/dev/null') def test_zero(self): self.assertEqual(find_device_file('zero'), '/dev/zero') def test_input_event(self): self.assertEqual(find_device_file('event0'), '/dev/input/event0') def test_non_existing(self): self.assertFalse(find_device_file('vyos')) diff --git a/src/tests/test_initial_setup.py b/src/tests/test_initial_setup.py index f85bf1265..4cd5fb169 100644 --- a/src/tests/test_initial_setup.py +++ b/src/tests/test_initial_setup.py @@ -1,101 +1,99 @@ -#!/usr/bin/env python3 -# # Copyright (C) 2018-2024 VyOS maintainers and contributors # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License version 2 or later as # published by the Free Software Foundation. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see <http://www.gnu.org/licenses/>. import unittest import vyos.configtree import vyos.initialsetup as vis from unittest import TestCase from vyos.xml_ref import definition from vyos.xml_ref.pkg_cache.vyos_1x_cache import reference class TestInitialSetup(TestCase): def setUp(self): with open('tests/data/config.boot.default', 'r') as f: config_string = f.read() self.config = vyos.configtree.ConfigTree(config_string) self.xml = definition.Xml() self.xml.define(reference) def test_set_user_password(self): vis.set_user_password(self.config, 'vyos', 'vyosvyos') # Old password hash from the default config old_pw = '$6$QxPS.uk6mfo$9QBSo8u1FkH16gMyAVhus6fU3LOzvLR9Z9.82m3tiHFAxTtIkhaZSWssSgzt4v4dGAL8rhVQxTg0oAG9/q11h/' new_pw = self.config.return_value(["system", "login", "user", "vyos", "authentication", "encrypted-password"]) # Just check it changed the hash, don't try to check if hash is good self.assertNotEqual(old_pw, new_pw) def test_disable_user_password(self): vis.disable_user_password(self.config, 'vyos') new_pw = self.config.return_value(["system", "login", "user", "vyos", "authentication", "encrypted-password"]) self.assertEqual(new_pw, '!') def test_set_ssh_key_with_name(self): test_ssh_key = " ssh-rsa fakedata vyos@vyos " vis.set_user_ssh_key(self.config, 'vyos', test_ssh_key) key_type = self.config.return_value(["system", "login", "user", "vyos", "authentication", "public-keys", "vyos@vyos", "type"]) key_data = self.config.return_value(["system", "login", "user", "vyos", "authentication", "public-keys", "vyos@vyos", "key"]) self.assertEqual(key_type, 'ssh-rsa') self.assertEqual(key_data, 'fakedata') self.assertTrue(self.xml.is_tag(["system", "login", "user", "vyos", "authentication", "public-keys"])) def test_set_ssh_key_without_name(self): # If key file doesn't include a name, the function will use user name for the key name test_ssh_key = " ssh-rsa fakedata " vis.set_user_ssh_key(self.config, 'vyos', test_ssh_key) key_type = self.config.return_value(["system", "login", "user", "vyos", "authentication", "public-keys", "vyos", "type"]) key_data = self.config.return_value(["system", "login", "user", "vyos", "authentication", "public-keys", "vyos", "key"]) self.assertEqual(key_type, 'ssh-rsa') self.assertEqual(key_data, 'fakedata') self.assertTrue(self.xml.is_tag(["system", "login", "user", "vyos", "authentication", "public-keys"])) def test_create_user(self): vis.create_user(self.config, 'jrandomhacker', password='qwerty', key=" ssh-rsa fakedata jrandomhacker@foovax ") self.assertTrue(self.config.exists(["system", "login", "user", "jrandomhacker"])) self.assertTrue(self.config.exists(["system", "login", "user", "jrandomhacker", "authentication", "public-keys", "jrandomhacker@foovax"])) self.assertTrue(self.config.exists(["system", "login", "user", "jrandomhacker", "authentication", "encrypted-password"])) self.assertEqual(self.config.return_value(["system", "login", "user", "jrandomhacker", "level"]), "admin") def test_set_hostname(self): vis.set_host_name(self.config, "vyos-test") self.assertEqual(self.config.return_value(["system", "host-name"]), "vyos-test") def test_set_name_servers(self): vis.set_name_servers(self.config, ["192.0.2.10", "203.0.113.20"]) servers = self.config.return_values(["system", "name-server"]) self.assertIn("192.0.2.10", servers) self.assertIn("203.0.113.20", servers) def test_set_gateway(self): vis.set_default_gateway(self.config, '192.0.2.1') self.assertTrue(self.config.exists(['protocols', 'static', 'route', '0.0.0.0/0', 'next-hop', '192.0.2.1'])) self.assertTrue(self.xml.is_tag(['protocols', 'static', 'multicast', 'route', '0.0.0.0/0', 'next-hop'])) self.assertTrue(self.xml.is_tag(['protocols', 'static', 'multicast', 'route'])) if __name__ == "__main__": unittest.main() diff --git a/src/tests/test_op_mode.py b/src/tests/test_op_mode.py index 90963b3c5..23f709653 100644 --- a/src/tests/test_op_mode.py +++ b/src/tests/test_op_mode.py @@ -1,65 +1,62 @@ -#!/usr/bin/env python3 -# -# Copyright (C) 2022 VyOS maintainers and contributors +# Copyright (C) 2022-2024 VyOS maintainers and contributors # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License version 2 or later as # published by the Free Software Foundation. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see <http://www.gnu.org/licenses/>. from unittest import TestCase import vyos.opmode class TestVyOSOpMode(TestCase): def test_field_name_normalization(self): from vyos.opmode import _normalize_field_name self.assertEqual(_normalize_field_name(" foo bar "), "foo_bar") self.assertEqual(_normalize_field_name("foo-bar"), "foo_bar") self.assertEqual(_normalize_field_name("foo (bar) baz"), "foo_bar_baz") self.assertEqual(_normalize_field_name("load%"), "load_percentage") def test_dict_fields_normalization_non_unique(self): from vyos.opmode import _normalize_field_names # Space and dot are both replaced by an underscore, # so dicts like this cannor be normalized uniquely data = {"foo bar": True, "foo.bar": False} with self.assertRaises(vyos.opmode.InternalError): _normalize_field_names(data) def test_dict_fields_normalization_simple_dict(self): from vyos.opmode import _normalize_field_names data = {"foo bar": True, "Bar-Baz": False} self.assertEqual(_normalize_field_names(data), {"foo_bar": True, "bar_baz": False}) def test_dict_fields_normalization_nested_dict(self): from vyos.opmode import _normalize_field_names data = {"foo bar": True, "bar-baz": {"baz-quux": {"quux-xyzzy": False}}} self.assertEqual(_normalize_field_names(data), {"foo_bar": True, "bar_baz": {"baz_quux": {"quux_xyzzy": False}}}) def test_dict_fields_normalization_mixed(self): from vyos.opmode import _normalize_field_names data = [{"foo bar": True, "bar-baz": [{"baz-quux": {"quux-xyzzy": [False]}}]}] self.assertEqual(_normalize_field_names(data), [{"foo_bar": True, "bar_baz": [{"baz_quux": {"quux_xyzzy": [False]}}]}]) def test_dict_fields_normalization_primitive(self): from vyos.opmode import _normalize_field_names data = [1, False, "foo"] self.assertEqual(_normalize_field_names(data), [1, False, "foo"]) - diff --git a/src/tests/test_task_scheduler.py b/src/tests/test_task_scheduler.py index 130f825e6..795ffeb9d 100644 --- a/src/tests/test_task_scheduler.py +++ b/src/tests/test_task_scheduler.py @@ -1,129 +1,127 @@ -#!/usr/bin/env python3 -# -# Copyright (C) 2018-2023 VyOS maintainers and contributors +# Copyright (C) 2018-2024 VyOS maintainers and contributors # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License version 2 or later as # published by the Free Software Foundation. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see <http://www.gnu.org/licenses/>. import os import tempfile import unittest import importlib from vyos import ConfigError try: task_scheduler = importlib.import_module("src.conf_mode.system_task-scheduler") except ModuleNotFoundError: # for unittest.main() import sys sys.path.append(os.path.join(os.path.dirname(__file__), '../..')) task_scheduler = importlib.import_module("src.conf_mode.system_task-scheduler") class TestUpdateCrontab(unittest.TestCase): def test_verify(self): tests = [ {'name': 'one_task', 'tasks': [{'name': 'aaa', 'interval': '60m', 'spec': '', 'executable': '/bin/ls', 'args': '-l'}], 'expected': None }, {'name': 'has_interval_and_spec', 'tasks': [{'name': 'aaa', 'interval': '60m', 'spec': '0 * * * *', 'executable': '/bin/ls', 'args': '-l'}], 'expected': ConfigError }, {'name': 'has_no_interval_and_spec', 'tasks': [{'name': 'aaa', 'interval': '', 'spec': '', 'executable': '/bin/ls', 'args': '-l'}], 'expected': ConfigError }, {'name': 'invalid_interval', 'tasks': [{'name': 'aaa', 'interval': '1y', 'spec': '', 'executable': '/bin/ls', 'args': '-l'}], 'expected': ConfigError }, {'name': 'invalid_interval_min', 'tasks': [{'name': 'aaa', 'interval': '61m', 'spec': '', 'executable': '/bin/ls', 'args': '-l'}], 'expected': ConfigError }, {'name': 'invalid_interval_hour', 'tasks': [{'name': 'aaa', 'interval': '25h', 'spec': '', 'executable': '/bin/ls', 'args': '-l'}], 'expected': ConfigError }, {'name': 'invalid_interval_day', 'tasks': [{'name': 'aaa', 'interval': '32d', 'spec': '', 'executable': '/bin/ls', 'args': '-l'}], 'expected': ConfigError }, {'name': 'no_executable', 'tasks': [{'name': 'aaa', 'interval': '60m', 'spec': '', 'executable': '', 'args': ''}], 'expected': ConfigError }, {'name': 'invalid_executable', 'tasks': [{'name': 'aaa', 'interval': '60m', 'spec': '', 'executable': '/bin/aaa', 'args': ''}], 'expected': ConfigError } ] for t in tests: with self.subTest(msg=t['name'], tasks=t['tasks'], expected=t['expected']): if t['expected'] is not None: with self.assertRaises(t['expected']): task_scheduler.verify(t['tasks']) else: task_scheduler.verify(t['tasks']) def test_generate(self): tests = [ {'name': 'zero_task', 'tasks': [], 'expected': [] }, {'name': 'one_task', 'tasks': [{'name': 'aaa', 'interval': '60m', 'spec': '', 'executable': '/bin/ls', 'args': '-l'}], 'expected': [ '### Generated by vyos-update-crontab.py ###', '*/60 * * * * root sg vyattacfg \"/bin/ls -l\"'] }, {'name': 'one_task_with_hour', 'tasks': [{'name': 'aaa', 'interval': '10h', 'spec': '', 'executable': '/bin/ls', 'args': '-l'}], 'expected': [ '### Generated by vyos-update-crontab.py ###', '0 */10 * * * root sg vyattacfg \"/bin/ls -l\"'] }, {'name': 'one_task_with_day', 'tasks': [{'name': 'aaa', 'interval': '10d', 'spec': '', 'executable': '/bin/ls', 'args': '-l'}], 'expected': [ '### Generated by vyos-update-crontab.py ###', '0 0 */10 * * root sg vyattacfg \"/bin/ls -l\"'] }, {'name': 'multiple_tasks', 'tasks': [{'name': 'aaa', 'interval': '60m', 'spec': '', 'executable': '/bin/ls', 'args': '-l'}, {'name': 'bbb', 'interval': '', 'spec': '0 0 * * *', 'executable': '/bin/ls', 'args': '-ltr'} ], 'expected': [ '### Generated by vyos-update-crontab.py ###', '*/60 * * * * root sg vyattacfg \"/bin/ls -l\"', '0 0 * * * root sg vyattacfg \"/bin/ls -ltr\"'] } ] for t in tests: with self.subTest(msg=t['name'], tasks=t['tasks'], expected=t['expected']): task_scheduler.crontab_file = tempfile.mkstemp()[1] task_scheduler.generate(t['tasks']) if len(t['expected']) > 0: self.assertTrue(os.path.isfile(task_scheduler.crontab_file)) with open(task_scheduler.crontab_file) as f: actual = f.read() self.assertEqual(t['expected'], actual.splitlines()) os.remove(task_scheduler.crontab_file) else: self.assertFalse(os.path.isfile(task_scheduler.crontab_file)) if __name__ == "__main__": unittest.main() diff --git a/src/tests/test_template.py b/src/tests/test_template.py index dbb86b40b..6377f6da5 100644 --- a/src/tests/test_template.py +++ b/src/tests/test_template.py @@ -1,194 +1,192 @@ -#!/usr/bin/env python3 -# # Copyright (C) 2020-2024 VyOS maintainers and contributors # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License version 2 or later as # published by the Free Software Foundation. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see <http://www.gnu.org/licenses/>. import vyos.template from vyos.utils.network import interface_exists from ipaddress import ip_network from unittest import TestCase class TestVyOSTemplate(TestCase): def setUp(self): pass def test_is_interface(self): for interface in ['lo', 'eth0']: if interface_exists(interface): self.assertTrue(vyos.template.is_interface(interface)) else: self.assertFalse(vyos.template.is_interface(interface)) self.assertFalse(vyos.template.is_interface('non-existent')) def test_is_ip(self): self.assertTrue(vyos.template.is_ip('192.0.2.1')) self.assertTrue(vyos.template.is_ip('2001:db8::1')) self.assertFalse(vyos.template.is_ip('VyOS')) def test_is_ipv4(self): self.assertTrue(vyos.template.is_ipv4('192.0.2.1')) self.assertTrue(vyos.template.is_ipv4('192.0.2.0/24')) self.assertTrue(vyos.template.is_ipv4('192.0.2.1/32')) self.assertFalse(vyos.template.is_ipv4('2001:db8::1')) self.assertFalse(vyos.template.is_ipv4('2001:db8::/64')) self.assertFalse(vyos.template.is_ipv4('VyOS')) def test_is_ipv6(self): self.assertTrue(vyos.template.is_ipv6('2001:db8::1')) self.assertTrue(vyos.template.is_ipv6('2001:db8::/64')) self.assertTrue(vyos.template.is_ipv6('2001:db8::1/64')) self.assertFalse(vyos.template.is_ipv6('192.0.2.1')) self.assertFalse(vyos.template.is_ipv6('192.0.2.0/24')) self.assertFalse(vyos.template.is_ipv6('192.0.2.1/32')) self.assertFalse(vyos.template.is_ipv6('VyOS')) def test_address_from_cidr(self): self.assertEqual(vyos.template.address_from_cidr('192.0.2.0/24'), '192.0.2.0') self.assertEqual(vyos.template.address_from_cidr('2001:db8::/48'), '2001:db8::') with self.assertRaises(ValueError): # ValueError: 192.0.2.1/24 has host bits set self.assertEqual(vyos.template.address_from_cidr('192.0.2.1/24'), '192.0.2.1') with self.assertRaises(ValueError): # ValueError: 2001:db8::1/48 has host bits set self.assertEqual(vyos.template.address_from_cidr('2001:db8::1/48'), '2001:db8::1') network_v4 = '192.0.2.0/26' self.assertEqual(vyos.template.address_from_cidr(network_v4), str(ip_network(network_v4).network_address)) def test_netmask_from_cidr(self): self.assertEqual(vyos.template.netmask_from_cidr('192.0.2.0/24'), '255.255.255.0') self.assertEqual(vyos.template.netmask_from_cidr('192.0.2.128/25'), '255.255.255.128') self.assertEqual(vyos.template.netmask_from_cidr('2001:db8::/48'), 'ffff:ffff:ffff::') with self.assertRaises(ValueError): # ValueError: 192.0.2.1/24 has host bits set self.assertEqual(vyos.template.netmask_from_cidr('192.0.2.1/24'), '255.255.255.0') with self.assertRaises(ValueError): # ValueError: 2001:db8:1:/64 has host bits set self.assertEqual(vyos.template.netmask_from_cidr('2001:db8:1:/64'), 'ffff:ffff:ffff:ffff::') network_v4 = '192.0.2.0/26' self.assertEqual(vyos.template.netmask_from_cidr(network_v4), str(ip_network(network_v4).netmask)) def test_first_host_address(self): self.assertEqual(vyos.template.first_host_address('10.0.0.0/24'), '10.0.0.1') self.assertEqual(vyos.template.first_host_address('10.0.0.10/24'), '10.0.0.1') self.assertEqual(vyos.template.first_host_address('10.0.0.255/24'), '10.0.0.1') self.assertEqual(vyos.template.first_host_address('10.0.0.128/25'), '10.0.0.129') self.assertEqual(vyos.template.first_host_address('2001:db8::/64'), '2001:db8::1') self.assertEqual(vyos.template.first_host_address('2001:db8::1000/64'), '2001:db8::1') self.assertEqual(vyos.template.first_host_address('2001:db8::ffff:ffff:ffff:ffff/64'), '2001:db8::1') def test_last_host_address(self): self.assertEqual(vyos.template.last_host_address('10.0.0.0/24'), '10.0.0.254') self.assertEqual(vyos.template.last_host_address('10.0.0.128/25'), '10.0.0.254') self.assertEqual(vyos.template.last_host_address('2001:db8::/64'), '2001:db8::ffff:ffff:ffff:ffff') def test_increment_ip(self): self.assertEqual(vyos.template.inc_ip('10.0.0.0/24', '2'), '10.0.0.2') self.assertEqual(vyos.template.inc_ip('10.0.0.0', '2'), '10.0.0.2') self.assertEqual(vyos.template.inc_ip('10.0.0.0', '10'), '10.0.0.10') self.assertEqual(vyos.template.inc_ip('2001:db8::/64', '2'), '2001:db8::2') self.assertEqual(vyos.template.inc_ip('2001:db8::', '10'), '2001:db8::a') def test_decrement_ip(self): self.assertEqual(vyos.template.dec_ip('10.0.0.100/24', '1'), '10.0.0.99') self.assertEqual(vyos.template.dec_ip('10.0.0.90', '10'), '10.0.0.80') self.assertEqual(vyos.template.dec_ip('2001:db8::b/64', '10'), '2001:db8::1') self.assertEqual(vyos.template.dec_ip('2001:db8::f', '5'), '2001:db8::a') def test_is_network(self): self.assertFalse(vyos.template.is_ip_network('192.0.2.0')) self.assertFalse(vyos.template.is_ip_network('192.0.2.1/24')) self.assertTrue(vyos.template.is_ip_network('192.0.2.0/24')) self.assertFalse(vyos.template.is_ip_network('2001:db8::')) self.assertFalse(vyos.template.is_ip_network('2001:db8::ffff')) self.assertTrue(vyos.template.is_ip_network('2001:db8::/48')) self.assertTrue(vyos.template.is_ip_network('2001:db8:1000::/64')) def test_is_network(self): self.assertTrue(vyos.template.compare_netmask('10.0.0.0/8', '20.0.0.0/8')) self.assertTrue(vyos.template.compare_netmask('10.0.0.0/16', '20.0.0.0/16')) self.assertFalse(vyos.template.compare_netmask('10.0.0.0/8', '20.0.0.0/16')) self.assertFalse(vyos.template.compare_netmask('10.0.0.1', '20.0.0.0/16')) self.assertTrue(vyos.template.compare_netmask('2001:db8:1000::/48', '2001:db8:2000::/48')) self.assertTrue(vyos.template.compare_netmask('2001:db8:1000::/64', '2001:db8:2000::/64')) self.assertFalse(vyos.template.compare_netmask('2001:db8:1000::/48', '2001:db8:2000::/64')) def test_cipher_to_string(self): ESP_DEFAULT = 'aes256gcm128-sha256-ecp256,aes128ccm64-sha256-ecp256' IKEv2_DEFAULT = 'aes256gcm128-sha256-ecp256,aes128ccm128-md5_128-modp1024' data = { 'esp_group': { 'ESP_DEFAULT': { 'compression': 'disable', 'lifetime': '3600', 'mode': 'tunnel', 'pfs': 'dh-group19', 'proposal': { '10': { 'encryption': 'aes256gcm128', 'hash': 'sha256', }, '20': { 'encryption': 'aes128ccm64', 'hash': 'sha256', } } } }, 'ike_group': { 'IKEv2_DEFAULT': { 'close_action': 'none', 'dead_peer_detection': { 'action': 'hold', 'interval': '30', 'timeout': '120' }, 'ikev2_reauth': 'no', 'key_exchange': 'ikev2', 'lifetime': '10800', 'mobike': 'disable', 'proposal': { '10': { 'dh_group': '19', 'encryption': 'aes256gcm128', 'hash': 'sha256' }, '20': { 'dh_group': '2', 'encryption': 'aes128ccm128', 'hash': 'md5_128' }, } } }, } for group_name, group_config in data['esp_group'].items(): ciphers = vyos.template.get_esp_ike_cipher(group_config) self.assertIn(ESP_DEFAULT, ','.join(ciphers)) for group_name, group_config in data['ike_group'].items(): ciphers = vyos.template.get_esp_ike_cipher(group_config) self.assertIn(IKEv2_DEFAULT, ','.join(ciphers)) diff --git a/src/tests/test_utils.py b/src/tests/test_utils.py index 9ae329ced..7bfd2618e 100644 --- a/src/tests/test_utils.py +++ b/src/tests/test_utils.py @@ -1,28 +1,26 @@ -#!/usr/bin/env python3 -# -# Copyright (C) 2020-2023 VyOS maintainers and contributors +# Copyright (C) 2020-2024 VyOS maintainers and contributors # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License version 2 or later as # published by the Free Software Foundation. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see <http://www.gnu.org/licenses/>. from unittest import TestCase class TestVyOSUtils(TestCase): def test_key_mangling(self): from vyos.utils.dict import mangle_dict_keys data = {"foo-bar": {"baz-quux": None}} expected_data = {"foo_bar": {"baz_quux": None}} new_data = mangle_dict_keys(data, '-', '_') self.assertEqual(new_data, expected_data) def test_sysctl_read(self): from vyos.utils.system import sysctl_read self.assertEqual(sysctl_read('net.ipv4.conf.lo.forwarding'), '1') diff --git a/src/tests/test_utils_network.py b/src/tests/test_utils_network.py index 5a6dc2586..d68dec16f 100644 --- a/src/tests/test_utils_network.py +++ b/src/tests/test_utils_network.py @@ -1,50 +1,45 @@ -#!/usr/bin/env python3 -# -# Copyright (C) 2020-2023 VyOS maintainers and contributors +# Copyright (C) 2020-2024 VyOS maintainers and contributors # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License version 2 or later as # published by the Free Software Foundation. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see <http://www.gnu.org/licenses/>. import vyos.utils.network from unittest import TestCase class TestVyOSUtilsNetwork(TestCase): def setUp(self): pass def test_is_addr_assigned(self): self.assertTrue(vyos.utils.network.is_addr_assigned('127.0.0.1')) self.assertTrue(vyos.utils.network.is_addr_assigned('::1')) self.assertFalse(vyos.utils.network.is_addr_assigned('127.251.255.123')) def test_is_ipv6_link_local(self): self.assertFalse(vyos.utils.network.is_ipv6_link_local('169.254.0.1')) self.assertTrue(vyos.utils.network.is_ipv6_link_local('fe80::')) self.assertTrue(vyos.utils.network.is_ipv6_link_local('fe80::affe:1')) self.assertTrue(vyos.utils.network.is_ipv6_link_local('fe80::affe:1%eth0')) self.assertFalse(vyos.utils.network.is_ipv6_link_local('2001:db8::')) self.assertFalse(vyos.utils.network.is_ipv6_link_local('2001:db8::%eth0')) self.assertFalse(vyos.utils.network.is_ipv6_link_local('VyOS')) self.assertFalse(vyos.utils.network.is_ipv6_link_local('::1')) self.assertFalse(vyos.utils.network.is_ipv6_link_local('::1%lo')) def test_is_ipv6_link_local(self): self.assertTrue(vyos.utils.network.is_loopback_addr('127.0.0.1')) self.assertTrue(vyos.utils.network.is_loopback_addr('127.0.1.1')) self.assertTrue(vyos.utils.network.is_loopback_addr('127.1.1.1')) self.assertTrue(vyos.utils.network.is_loopback_addr('::1')) self.assertFalse(vyos.utils.network.is_loopback_addr('::2')) self.assertFalse(vyos.utils.network.is_loopback_addr('192.0.2.1')) - - -