Script 'mail_helper' called by obssrc
Hello community,

here is the log from the commit of package 
python-proton-vpn-killswitch-network-manager for openSUSE:Factory checked in at 
2024-05-22 21:33:10
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing 
/work/SRC/openSUSE:Factory/python-proton-vpn-killswitch-network-manager (Old)
 and      
/work/SRC/openSUSE:Factory/.python-proton-vpn-killswitch-network-manager.new.1880
 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "python-proton-vpn-killswitch-network-manager"

Wed May 22 21:33:10 2024 rev:2 rq:1175825 version:0.4.4

Changes:
--------
--- 
/work/SRC/openSUSE:Factory/python-proton-vpn-killswitch-network-manager/python-proton-vpn-killswitch-network-manager.changes
        2024-03-21 17:00:45.805097873 +0100
+++ 
/work/SRC/openSUSE:Factory/.python-proton-vpn-killswitch-network-manager.new.1880/python-proton-vpn-killswitch-network-manager.changes
      2024-05-22 21:33:34.164376436 +0200
@@ -1,0 +2,6 @@
+Wed May 22 11:40:07 UTC 2024 - Alexandre Vicenzi <alexandre.vice...@suse.com>
+
+- Update to 0.4.4
+  * Fix random crashes when enabling/disabling the kill switch
+
+-------------------------------------------------------------------

Old:
----
  v0.4.3.tar.gz

New:
----
  v0.4.4.tar.gz

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ python-proton-vpn-killswitch-network-manager.spec ++++++
--- /var/tmp/diff_new_pack.3lqpE5/_old  2024-05-22 21:33:35.228415354 +0200
+++ /var/tmp/diff_new_pack.3lqpE5/_new  2024-05-22 21:33:35.228415354 +0200
@@ -19,7 +19,7 @@
 %define skip_python2 1
 %{?sle15_python_module_pythons}
 Name:           python-proton-vpn-killswitch-network-manager
-Version:        0.4.3
+Version:        0.4.4
 Release:        0
 Summary:        Proton VPN kill switch interface using NetworkManager
 License:        GPL-3.0-or-later

++++++ v0.4.3.tar.gz -> v0.4.4.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/python-proton-vpn-killswitch-network-manager-0.4.3/debian/changelog 
new/python-proton-vpn-killswitch-network-manager-0.4.4/debian/changelog
--- old/python-proton-vpn-killswitch-network-manager-0.4.3/debian/changelog     
2024-03-06 10:45:22.000000000 +0100
+++ new/python-proton-vpn-killswitch-network-manager-0.4.4/debian/changelog     
2024-04-30 15:26:05.000000000 +0200
@@ -1,3 +1,9 @@
+proton-vpn-killswitch-network-manager (0.4.4) unstable; urgency=medium
+
+  * Fix random crashes when enabling/disabling the kill switch
+
+ -- Josep Llaneras <josep.llane...@proton.ch>  Tue, 30 Apr 2024 15:24:53 +0200
+
 proton-vpn-killswitch-network-manager (0.4.3) unstable; urgency=medium
 
   * Fix crash on older distros when disabling connectivity checking
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/python-proton-vpn-killswitch-network-manager-0.4.3/integration/run.sh 
new/python-proton-vpn-killswitch-network-manager-0.4.4/integration/run.sh
--- old/python-proton-vpn-killswitch-network-manager-0.4.3/integration/run.sh   
2024-03-06 10:45:22.000000000 +0100
+++ new/python-proton-vpn-killswitch-network-manager-0.4.4/integration/run.sh   
1970-01-01 01:00:00.000000000 +0100
@@ -1,14 +0,0 @@
-#!/usr/bin/env bash
-
-if [[ "$CI" == "true" ]]
-then
-  # Only run these commands in CI
-  # The following dir is required by the system bus dbus daemon.
-  sudo mkdir -p /var/run/dbus
-  # Run system bus dbus daemon as it's required by NetworkManager.
-  sudo dbus-daemon --config-file=/usr/share/dbus-1/system.conf --print-address
-  # Run network manager as it's required by the integration tests.
-  NetworkManager
-fi
-
-python3 -m pytest tests/integration/test_killswitch_connection.py
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/python-proton-vpn-killswitch-network-manager-0.4.3/integration/test_killswitch_connection.py
 
new/python-proton-vpn-killswitch-network-manager-0.4.4/integration/test_killswitch_connection.py
--- 
old/python-proton-vpn-killswitch-network-manager-0.4.3/integration/test_killswitch_connection.py
    2024-03-06 10:45:22.000000000 +0100
+++ 
new/python-proton-vpn-killswitch-network-manager-0.4.4/integration/test_killswitch_connection.py
    1970-01-01 01:00:00.000000000 +0100
@@ -1,98 +0,0 @@
-import os
-
-import pytest
-import subprocess
-
-from proton.vpn.killswitch.backend.linux.networkmanager.killswitch_connection 
import (
-    KillSwitchConfig, KillSwitchConnectionHandler)
-from proton.vpn.killswitch.interface.exceptions import KillSwitchException
-
-
-TEST_HUMAN_READEABLE_ID = "test-pvpn-killswitch"
-TEST_INTERFACE_NAME = "testpvpn0"
-
-
-def _assert_connection_exist():
-    output = int(os.system(f"nmcli -g GENERAL.STATE c s 
\"{TEST_HUMAN_READEABLE_ID}\""))
-    assert output == 0
-
-
-def _assert_connection_does_not_exist():
-    output = int(os.system(f"nmcli -g GENERAL.STATE c s 
\"{TEST_HUMAN_READEABLE_ID}\""))
-    assert output != 0
-
-
-def _nmcli_del_connection():
-    os.system(f"nmcli c del {TEST_HUMAN_READEABLE_ID}")
-
-
-class TestIntegrationKillSwitchConnectionHandler:
-    def setup_class(cls):
-        _nmcli_del_connection()
-        _assert_connection_does_not_exist()
-
-    def teardown_class(cls):
-        _nmcli_del_connection()
-        _assert_connection_does_not_exist()
-
-    @pytest.fixture
-    def cleanup_env(self):
-        yield {}
-        _nmcli_del_connection()
-        _assert_connection_does_not_exist()
-
-    @pytest.fixture
-    def test_killswitch_config(self):
-        cfg = KillSwitchConfig()
-        cfg.human_readable_id = TEST_HUMAN_READEABLE_ID
-        cfg.interface_name = TEST_INTERFACE_NAME
-        yield cfg
-
-    def _nmcli_add_connection(self):
-        os.system(f"nmcli c a type dummy ifname {TEST_INTERFACE_NAME} con-name 
{TEST_HUMAN_READEABLE_ID}")
-
-    def get_ipv4_addresses(self):
-        nmcli_string = f"nmcli -g ipv4.addresses c s {TEST_HUMAN_READEABLE_ID}"
-        ipv4_addresses = subprocess.check_output(nmcli_string.split(" 
")).decode().strip("\n").split(",")
-        ipv4_addresses = tuple([addr.replace(" ", "") for addr in 
ipv4_addresses])
-        return ipv4_addresses
-
-    @pytest.mark.parametrize("arg", [None, KillSwitchConfig()])
-    def test_init_expected_args(self, arg):
-        KillSwitchConnectionHandler(arg)
-
-    @pytest.mark.parametrize("arg", [False, "TestString"])
-    def test_init_with_raises_exception(self, arg):
-        with pytest.raises(TypeError):
-            KillSwitchConnectionHandler(arg)
-
-    def test_add_and_remove_connection(self, cleanup_env, 
test_killswitch_config):
-        handler = KillSwitchConnectionHandler(test_killswitch_config)
-        handler.add()
-        _assert_connection_exist()
-        handler.remove()
-        _assert_connection_does_not_exist()
-
-    def test_update_connection(self, cleanup_env, test_killswitch_config):
-        handler = KillSwitchConnectionHandler(test_killswitch_config)
-        handler.add()
-        ipv4_addresses = self.get_ipv4_addresses()
-        handler.update("192.168.1.1")
-        updated_ipv4_addresses = self.get_ipv4_addresses()
-        assert ipv4_addresses != updated_ipv4_addresses
-
-    def test_add_connection_and_connection_exists_raises_exception(self, 
cleanup_env, test_killswitch_config):
-        self._nmcli_add_connection()
-        handler = KillSwitchConnectionHandler(test_killswitch_config)
-        with pytest.raises(KillSwitchException):
-            handler.add()
-
-    def 
test_update_connection_and_connection_does_not_exist_raises_exception(self, 
cleanup_env, test_killswitch_config):
-        handler = KillSwitchConnectionHandler(test_killswitch_config)
-        with pytest.raises(KillSwitchException):
-            handler.update("192.149.1.1")
-
-    def 
test_remove_connection_and_connection_does_not_exist_raises_exception(self, 
cleanup_env, test_killswitch_config):
-        handler = KillSwitchConnectionHandler(test_killswitch_config)
-        with pytest.raises(KillSwitchException):
-            handler.remove()
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/python-proton-vpn-killswitch-network-manager-0.4.3/proton/vpn/killswitch/backend/linux/networkmanager/killswitch_connection_handler.py
 
new/python-proton-vpn-killswitch-network-manager-0.4.4/proton/vpn/killswitch/backend/linux/networkmanager/killswitch_connection_handler.py
--- 
old/python-proton-vpn-killswitch-network-manager-0.4.3/proton/vpn/killswitch/backend/linux/networkmanager/killswitch_connection_handler.py
  2024-03-06 10:45:22.000000000 +0100
+++ 
new/python-proton-vpn-killswitch-network-manager-0.4.4/proton/vpn/killswitch/backend/linux/networkmanager/killswitch_connection_handler.py
  2024-04-30 15:26:05.000000000 +0200
@@ -32,11 +32,11 @@
 logger = logging.getLogger(__name__)
 
 
-def _get_connection_id(permanent: bool, ipv6: bool = False, routed: bool = 
False):
+def _get_connection_id(prefix: str, permanent: bool, ipv6: bool = False, 
routed: bool = False):
     if ipv6:
-        return f"pvpn-killswitch-ipv6{'-perm' if permanent else ''}"
+        return f"{prefix}-killswitch-ipv6{'-perm' if permanent else ''}"
 
-    return f"pvpn{'-routed' if routed else ''}-killswitch{'-perm' if permanent 
else ''}"
+    return f"{prefix}{'-routed' if routed else ''}-killswitch{'-perm' if 
permanent else ''}"
 
 
 def _get_interface_name(permanent: bool, ipv6: bool = False, routed: bool = 
False):
@@ -57,8 +57,9 @@
 class KillSwitchConnectionHandler:
     """Kill switch connection management."""
 
-    def __init__(self, nm_client: NMClient = None):
+    def __init__(self, nm_client: NMClient = None, connection_prefix: str = 
None):
         self._nm_client = nm_client
+        self._connection_prefix = connection_prefix or "pvpn"
         self._ipv6_ks_settings = KillSwitchIPConfig(
             addresses=["fdeb:446c:912d:08da::/64"],
             dns=["::1"],
@@ -80,7 +81,7 @@
 
         return KillSwitchIPConfig(
             addresses=["100.85.0.1/24"],
-            dns=["0.0.0.0"],
+            dns=["0.0.0.0"],  # nosec hardcoded_bind_all_interfaces
             dns_priority=-1400,
             gateway=gateway,
             ignore_auto_dns=True,
@@ -112,7 +113,7 @@
         require to be bonded to the VPN interface.."""
         await self._ensure_connectivity_check_is_disabled()
 
-        connection_id = _get_connection_id(permanent)
+        connection_id = _get_connection_id(self._connection_prefix, permanent)
         connection = self.nm_client.get_active_connection(
             conn_id=connection_id
         )
@@ -135,9 +136,10 @@
         await _wrap_future(
             self.nm_client.add_connection_async(kill_switch.connection, 
save_to_disk=permanent)
         )
+
         logger.debug(f"{'Permanent' if permanent else 'Non-permanent'} kill 
switch added.")
         await self._remove_connection(
-            connection_id=_get_connection_id(permanent=not permanent)
+            connection_id=_get_connection_id(self._connection_prefix, 
permanent=not permanent)
         )
         logger.debug(f"{'Non-permanent' if permanent else 'Permanent'} kill 
switch removed.")
 
@@ -152,7 +154,7 @@
         await self._ensure_connectivity_check_is_disabled()
 
         general_config = KillSwitchGeneralConfig(
-            human_readable_id=_get_connection_id(permanent, routed=True),
+            human_readable_id=_get_connection_id(self._connection_prefix, 
permanent, routed=True),
             interface_name=_get_interface_name(permanent, routed=True)
         )
         kill_switch = KillSwitchConnection(
@@ -170,7 +172,9 @@
         to prevent IPv6 leaks while using IPv4."""
         await self._ensure_connectivity_check_is_disabled()
 
-        connection_id = _get_connection_id(permanent=False, ipv6=True)
+        connection_id = _get_connection_id(
+            self._connection_prefix, permanent=False, ipv6=True
+        )
         connection = self.nm_client.get_active_connection(
             conn_id=connection_id)
 
@@ -198,21 +202,31 @@
     async def remove_full_killswitch_connection(self):
         """Removes full kill switch connection."""
         logger.debug("Removing full kill switch...")
-        await self._remove_connection(_get_connection_id(permanent=True))
-        await self._remove_connection(_get_connection_id(permanent=False))
+        await self._remove_connection(
+            _get_connection_id(self._connection_prefix, permanent=True)
+        )
+        await self._remove_connection(
+            _get_connection_id(self._connection_prefix, permanent=False)
+        )
         logger.debug("Full kill switch removed.")
 
     async def remove_routed_killswitch_connection(self):
         """Removes routed kill switch connection."""
         logger.debug("Removing routed kill switch...")
-        await self._remove_connection(_get_connection_id(permanent=True, 
routed=True))
-        await self._remove_connection(_get_connection_id(permanent=False, 
routed=True))
+        await self._remove_connection(
+            _get_connection_id(self._connection_prefix, permanent=True, 
routed=True)
+        )
+        await self._remove_connection(
+            _get_connection_id(self._connection_prefix, permanent=False, 
routed=True)
+        )
         logger.debug("Routed kill switch removed.")
 
     async def remove_ipv6_leak_protection(self):
         """Removes IPv6 kill switch connection."""
         logger.debug("Removing IPv6 leak protection...")
-        await self._remove_connection(_get_connection_id(permanent=False, 
ipv6=True))
+        await self._remove_connection(
+            _get_connection_id(self._connection_prefix, permanent=False, 
ipv6=True)
+        )
         logger.debug("IP6 leak protection removed.")
 
     async def _remove_connection(self, connection_id: str):
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/python-proton-vpn-killswitch-network-manager-0.4.3/proton/vpn/killswitch/backend/linux/networkmanager/nmclient.py
 
new/python-proton-vpn-killswitch-network-manager-0.4.4/proton/vpn/killswitch/backend/linux/networkmanager/nmclient.py
--- 
old/python-proton-vpn-killswitch-network-manager-0.4.3/proton/vpn/killswitch/backend/linux/networkmanager/nmclient.py
       2024-03-06 10:45:22.000000000 +0100
+++ 
new/python-proton-vpn-killswitch-network-manager-0.4.4/proton/vpn/killswitch/backend/linux/networkmanager/nmclient.py
       2024-04-30 15:26:05.000000000 +0200
@@ -106,7 +106,8 @@
         For more info:
         
https://developer.gnome.org/documentation/tutorials/main-contexts.html#checking-threading
         """
-        assert cls._main_context.is_owner()
+        if not cls._main_context.is_owner():
+            raise RuntimeError("Code being run outside GLib's main loop.")
 
     @classmethod
     def _run_on_glib_loop_thread(cls, function, *args, **kwargs) -> Future:
@@ -137,28 +138,32 @@
         """
         future_conn_activated = _create_future()
 
-        def _on_connection_added(nm_client, res, _user_data):
+        def _on_interface_state_changed(_device, new_state, _old_state, 
_reason):
+            """
+            Monitors kill switch interface state changes and resolves
+            the future as soon as the interface reaches the activated state
+            """
+            logger.debug(
+                f"{connection.get_interface_name()} interface state changed "
+                f"to {NM.DeviceState(new_state).value_name}"
+            )
             if (
-                    not nm_client or not res or
-                    not (remote_connection := 
nm_client.add_connection_finish(res))
+                    NM.DeviceState(new_state) == NM.DeviceState.ACTIVATED
+                    and not future_conn_activated.done()
             ):
-                future_conn_activated.set_exception(
-                    RuntimeError(f"Error setting adding KS connection: 
{nm_client=}, {res=}")
-                )
-                return
+                future_conn_activated.set_result(None)
 
-            def _on_interface_state_changed(_device, new_state, _old_state, 
_reason):
-                logger.debug(
-                    f"{remote_connection.get_interface_name()} interface state 
changed "
-                    f"to {NM.DeviceState(new_state).value_name}"
-                )
-                if (
-                        NM.DeviceState(new_state) == NM.DeviceState.ACTIVATED
-                        and not future_conn_activated.done()
-                ):
-                    future_conn_activated.set_result(remote_connection)
+        def _on_interface_added(_nm_client, device):
+            """
+            Monitors interface creation. As soon as the kill switch interface
+            is created it sets up the call back to monitor interface state 
changes.
+            """
+            logger.debug(
+                f"{device.get_iface()} interface added in state 
{device.get_state().value_name}"
+            )
+            if not device.get_iface() == connection.get_interface_name():
+                return
 
-            device = 
self._nm_client.get_device_by_iface(remote_connection.get_interface_name())
             handler_id = device.connect("state-changed", 
_on_interface_state_changed)
             future_conn_activated.add_done_callback(
                 lambda f: self._run_on_glib_loop_thread(
@@ -166,11 +171,29 @@
                 ).result()
             )
 
-            # The callback is manually called here because sometimes is never 
called. I assume that
-            # when we connect to the state-changes signal the interface has 
already been activated.
-            _on_interface_state_changed(device, device.get_state().real, None, 
None)
+        def _on_connection_added(nm_client, res, _user_data):
+            try:
+                # Make sure exceptions creating the connection are passed to 
the future.
+                nm_client.add_connection_finish(res)
+            except Exception as exc:  # pylint: disable=broad-except
+                future_conn_activated.set_exception(
+                    RuntimeError(
+                        f"Error setting adding KS connection: {nm_client=}, 
{res=}"
+                    ).with_traceback(exc.__traceback__)
+                )
+                return
 
         def _add_connection_async():
+            # Set up interface connection monitoring, which resolves the future
+            # once the kill switch is active.
+            handler_id = self._nm_client.connect("device-added", 
_on_interface_added)
+            future_conn_activated.add_done_callback(
+                lambda f: self._run_on_glib_loop_thread(
+                    GObject.signal_handler_disconnect, self._nm_client, 
handler_id
+                ).result()
+            )
+
+            # Add kill switch connection asynchronously.
             self._nm_client.add_connection_async(
                 connection=connection,
                 save_to_disk=save_to_disk,
@@ -195,29 +218,27 @@
         future_interface_removed = _create_future()
 
         def _on_connection_removed(connection, result, _user_data):
-            if not connection or not result or not 
connection.delete_finish(result):
+            try:
+                connection.delete_finish(result)
+            except Exception as exc:  # pylint: disable=broad-except
                 future_interface_removed.set_exception(
-                    RuntimeError(f"Error removing KS connection: 
{connection=}, {result=}")
+                    RuntimeError(
+                        f"Error removing KS connection: {connection=}, 
{result=}"
+                    ).with_traceback(exc.__traceback__)
                 )
-                return
 
-        def _on_interface_state_changed(device, new_state, _old_state, 
_reason):
+        def _on_interface_removed(_nm_client, device):
             logger.debug(
-                f"{device.get_iface()} interface state changed to "
-                f"{NM.DeviceState(new_state).value_name}"
+                f"{device.get_iface()} was removed."
             )
-            if (
-                    NM.DeviceState(new_state) == NM.DeviceState.DISCONNECTED
-                    and not future_interface_removed.done()
-            ):
+            if device.get_iface() == connection.get_interface_name():
                 future_interface_removed.set_result(None)
 
         def _remove_connection_async():
-            device = 
self._nm_client.get_device_by_iface(connection.get_interface_name())
-            handler_id = device.connect("state-changed", 
_on_interface_state_changed)
+            handler_id = self._nm_client.connect("device-removed", 
_on_interface_removed)
             future_interface_removed.add_done_callback(
                 lambda f: self._run_on_glib_loop_thread(
-                    GObject.signal_handler_disconnect, device, handler_id
+                    GObject.signal_handler_disconnect, self._nm_client, 
handler_id
                 ).result()
             )
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/python-proton-vpn-killswitch-network-manager-0.4.3/rpmbuild/SPECS/package.spec
 
new/python-proton-vpn-killswitch-network-manager-0.4.4/rpmbuild/SPECS/package.spec
--- 
old/python-proton-vpn-killswitch-network-manager-0.4.3/rpmbuild/SPECS/package.spec
  2024-03-06 10:45:22.000000000 +0100
+++ 
new/python-proton-vpn-killswitch-network-manager-0.4.4/rpmbuild/SPECS/package.spec
  2024-04-30 15:26:05.000000000 +0200
@@ -1,5 +1,5 @@
 %define unmangled_name proton-vpn-killswitch-network-manager
-%define version 0.4.3
+%define version 0.4.4
 %define release 1
 
 Prefix: %{_prefix}
@@ -52,6 +52,9 @@
 %defattr(-,root,root)
 
 %changelog
+* Tue Apr 30 2024 Josep Llaneras <josep.llane...@proton.ch> 0.4.4
+- Fix random crashes when enabling/disabling the kill switch
+
 * Wed Mar 06 2024 Josep Llaneras <josep.llane...@proton.ch> 0.4.3
 - Fix crash on older distros when disabling connectivity checking
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/python-proton-vpn-killswitch-network-manager-0.4.3/setup.py 
new/python-proton-vpn-killswitch-network-manager-0.4.4/setup.py
--- old/python-proton-vpn-killswitch-network-manager-0.4.3/setup.py     
2024-03-06 10:45:22.000000000 +0100
+++ new/python-proton-vpn-killswitch-network-manager-0.4.4/setup.py     
2024-04-30 15:26:05.000000000 +0200
@@ -4,7 +4,7 @@
 
 setup(
     name="proton-vpn-killswitch-network-manager",
-    version="0.4.3",
+    version="0.4.4",
     description="Proton Technologies VPN connector for linux",
     author="Proton Technologies",
     author_email="cont...@protonmail.com",
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/python-proton-vpn-killswitch-network-manager-0.4.3/tests/integration/run.sh 
new/python-proton-vpn-killswitch-network-manager-0.4.4/tests/integration/run.sh
--- 
old/python-proton-vpn-killswitch-network-manager-0.4.3/tests/integration/run.sh 
    1970-01-01 01:00:00.000000000 +0100
+++ 
new/python-proton-vpn-killswitch-network-manager-0.4.4/tests/integration/run.sh 
    2024-04-30 15:26:05.000000000 +0200
@@ -0,0 +1,14 @@
+#!/usr/bin/env bash
+
+if [[ "$CI" == "true" ]]
+then
+  # Only run these commands in CI
+  # The following dir is required by the system bus dbus daemon.
+  sudo mkdir -p /var/run/dbus
+  # Run system bus dbus daemon as it's required by NetworkManager.
+  sudo dbus-daemon --config-file=/usr/share/dbus-1/system.conf --print-address
+  # Run network manager as it's required by the integration tests.
+  NetworkManager
+fi
+
+python3 -m pytest tests/integration/test_killswitch_connection.py
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/python-proton-vpn-killswitch-network-manager-0.4.3/tests/integration/test_killswitch_connection.py
 
new/python-proton-vpn-killswitch-network-manager-0.4.4/tests/integration/test_killswitch_connection.py
--- 
old/python-proton-vpn-killswitch-network-manager-0.4.3/tests/integration/test_killswitch_connection.py
      1970-01-01 01:00:00.000000000 +0100
+++ 
new/python-proton-vpn-killswitch-network-manager-0.4.4/tests/integration/test_killswitch_connection.py
      2024-04-30 15:26:05.000000000 +0200
@@ -0,0 +1,94 @@
+import pytest
+import subprocess
+
+from 
proton.vpn.killswitch.backend.linux.networkmanager.killswitch_connection_handler
 import KillSwitchConnectionHandler
+
+FULL_KS_CONNECTION_ID = "test-killswitch"
+ROUTED_KS_CONNECTION_ID = "test-routed-killswitch"
+IPV6_KS_CONNECTION_ID = "test-killswitch-ipv6"
+TEST_INTERFACE_NAME = "testpvpn0"
+
+
+def _assert_connection_exist(connection_id):
+    subprocess.run(
+        ["nmcli", "-g", "GENERAL.STATE", "c", "s", f"{connection_id}"],
+        capture_output=True, check=True
+    )
+
+
+def _assert_connection_does_not_exist(connection_id):
+    with pytest.raises(subprocess.CalledProcessError):
+        subprocess.run(
+            ["nmcli", "-g", "GENERAL.STATE", "c", "s", f"{connection_id}"],
+            capture_output=True, check=True
+        )
+
+
+def _nmcli_add_connection(connection_id):
+    subprocess.run(
+        [
+            "nmcli", "c", "a", "type", "dummy", "ifname", 
f"{TEST_INTERFACE_NAME}",
+            "con-name", f"{connection_id}"
+        ],
+        capture_output=True, check=True
+    )
+
+
+def _nmcli_del_connection(connection_id):
+    subprocess.run(["nmcli", "c", "del", f"{connection_id}"], 
capture_output=True)
+
+
+@pytest.fixture
+def cleanup_env():
+    _nmcli_del_connection(FULL_KS_CONNECTION_ID)
+    _nmcli_del_connection(ROUTED_KS_CONNECTION_ID)
+    _nmcli_del_connection(IPV6_KS_CONNECTION_ID)
+    yield {}
+    _nmcli_del_connection(FULL_KS_CONNECTION_ID)
+    _nmcli_del_connection(ROUTED_KS_CONNECTION_ID)
+    _nmcli_del_connection(IPV6_KS_CONNECTION_ID)
+
+
+@pytest.mark.asyncio
+async def test_add_full_killswitch_connection(cleanup_env):
+    handler = KillSwitchConnectionHandler(connection_prefix="test")
+    await handler.add_full_killswitch_connection(permanent=False)
+    _assert_connection_exist(FULL_KS_CONNECTION_ID)
+
+
+@pytest.mark.asyncio
+async def test_remove_full_killswitch_connection(cleanup_env):
+    _nmcli_add_connection(FULL_KS_CONNECTION_ID)
+    handler = KillSwitchConnectionHandler(connection_prefix="test")
+    await handler.remove_full_killswitch_connection()
+    _assert_connection_does_not_exist(FULL_KS_CONNECTION_ID)
+
+
+@pytest.mark.asyncio
+async def test_add_routed_killswitch_connection(cleanup_env):
+    handler = KillSwitchConnectionHandler(connection_prefix="test")
+    await handler.add_routed_killswitch_connection(server_ip="192.168.1.1", 
permanent=False)
+    _assert_connection_exist(ROUTED_KS_CONNECTION_ID)
+
+
+@pytest.mark.asyncio
+async def test_remove_routed_killswitch_connection(cleanup_env):
+    _nmcli_add_connection(ROUTED_KS_CONNECTION_ID)
+    handler = KillSwitchConnectionHandler(connection_prefix="test")
+    await handler.remove_routed_killswitch_connection()
+    _assert_connection_does_not_exist(ROUTED_KS_CONNECTION_ID)
+
+
+@pytest.mark.asyncio
+async def test_add_ipv6_killswitch_connection(cleanup_env):
+    handler = KillSwitchConnectionHandler(connection_prefix="test")
+    await handler.add_ipv6_leak_protection()
+    _assert_connection_exist(IPV6_KS_CONNECTION_ID)
+
+
+@pytest.mark.asyncio
+async def test_remove_routed_killswitch_connection(cleanup_env):
+    _nmcli_add_connection(IPV6_KS_CONNECTION_ID)
+    handler = KillSwitchConnectionHandler(connection_prefix="test")
+    await handler.remove_ipv6_leak_protection()
+    _assert_connection_does_not_exist(IPV6_KS_CONNECTION_ID)

Reply via email to