Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
161 changes: 161 additions & 0 deletions tests/test_autostart.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,161 @@
#
# This file is part of VIRL 2
# Copyright (c) 2019-2025, Cisco Systems, Inc.
# All rights reserved.
#
# Python bindings for the Cisco VIRL 2 Network Simulation Platform
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
from unittest.mock import MagicMock, Mock

import pytest

from virl2_client.models import Lab

RESOURCE_POOL_MANAGER = Mock()


def conditional_side_effect(*args, **kwargs):
_ = args
resp = kwargs.get("json", {})
if autostart := resp.get("autostart"):
if not isinstance(autostart.get("enabled"), bool):
raise ValueError("Invalid value for enabled")
if priority := autostart.get("priority"):
if not isinstance(priority, int) or not 0 <= priority <= 10000:
raise ValueError("Invalid value for priority")
if delay := autostart.get("delay"):
if not isinstance(delay, int) or not 0 <= delay <= 86400:
raise ValueError("Invalid value for delay")


def test_autostart_initial_values():
"""Test that new lab has correct initial autostart values."""
session = MagicMock()
lab = Lab(
"test_lab",
"1",
session,
"user",
"pass",
auto_sync=False,
resource_pool_manager=RESOURCE_POOL_MANAGER,
)
assert lab._autostart == {"enabled": False, "priority": None, "delay": None}


def test_lab_autostart_setter():
"""Test setting the autostart parameter on a Lab instance."""
session = MagicMock()
lab = Lab(
title="Test Lab",
lab_id="lab-id",
session=session,
username="user",
password="pass",
auto_sync=False,
resource_pool_manager=RESOURCE_POOL_MANAGER,
)

lab.set_autostart(enabled=True, priority=5, delay=10)
assert lab.autostart == {"enabled": True, "priority": 5, "delay": 10}
session.patch.assert_called_once_with(
"labs/lab-id", json={"autostart": {"enabled": True, "priority": 5, "delay": 10}}
)


def test_lab_autostart_setter_invalid():
"""Test setting invalid autostart parameters raises ValueError."""
session = MagicMock()
session.patch.side_effect = conditional_side_effect
lab = Lab(
title="Test Lab",
lab_id="lab-id",
session=session,
username="user",
password="pass",
auto_sync=False,
resource_pool_manager=RESOURCE_POOL_MANAGER,
)

with pytest.raises(ValueError):
lab.set_autostart(enabled="yes", priority=5, delay=10)
with pytest.raises(ValueError):
lab.set_autostart(enabled=True, priority="yes", delay=10)
with pytest.raises(ValueError):
lab.set_autostart(enabled=True, priority=-1, delay=10)
with pytest.raises(ValueError):
lab.set_autostart(enabled=True, priority=10001, delay=10)
with pytest.raises(ValueError):
lab.set_autostart(enabled=True, priority=5, delay="yes")
with pytest.raises(ValueError):
lab.set_autostart(enabled=True, priority=5, delay=-10)
with pytest.raises(ValueError):
lab.set_autostart(enabled=True, priority=5, delay=86401)


def test_lab_autostart_setter_no_change():
"""Test that setting autostart to the same value does not trigger an API call."""
session = MagicMock()
lab = Lab(
title="Test Lab",
lab_id="lab-id",
session=session,
username="user",
password="pass",
auto_sync=False,
resource_pool_manager=RESOURCE_POOL_MANAGER,
)
lab._autostart = {"enabled": True, "priority": 5, "delay": 10}

lab.set_autostart()
session.patch.assert_not_called()

lab.set_autostart(enabled=True, priority=5, delay=10)
session.patch.assert_called()


def test_lab_autostart_setter_partial_update():
"""Test that setting only some autostart parameters updates correctly."""
session = MagicMock()
lab = Lab(
title="Test Lab",
lab_id="lab-id",
session=session,
username="user",
password="pass",
auto_sync=False,
resource_pool_manager=RESOURCE_POOL_MANAGER,
)
lab._autostart = {"enabled": False, "priority": None, "delay": None}

lab.set_autostart(enabled=True)
assert lab.autostart == {"enabled": True, "priority": None, "delay": None}
session.patch.assert_called_with(
"labs/lab-id",
json={"autostart": {"enabled": True, "priority": None, "delay": None}},
)

lab.set_autostart(priority=7)
assert lab.autostart == {"enabled": True, "priority": 7, "delay": None}
session.patch.assert_called_with(
"labs/lab-id",
json={"autostart": {"enabled": True, "priority": 7, "delay": None}},
)

lab.set_autostart(delay=15)
assert lab.autostart == {"enabled": True, "priority": 7, "delay": 15}
session.patch.assert_called_with(
"labs/lab-id", json={"autostart": {"enabled": True, "priority": 7, "delay": 15}}
)
233 changes: 0 additions & 233 deletions tests/test_client_library_labs.py
Original file line number Diff line number Diff line change
Expand Up @@ -494,236 +494,3 @@ def test_node_clear_discovered_addresses(respx_mock):
assert interface2.discovered_mac_address is None

respx_mock.assert_all_called()


def test_lab_autostart_initial_values():
"""Test that new lab has correct initial autostart values."""
session = MagicMock()
lab = Lab(
"test_lab",
"1",
session,
"user",
"pass",
auto_sync=False,
resource_pool_manager=RESOURCE_POOL_MANAGER,
)

assert lab._autostart == {"enabled": False, "priority": None, "delay": None}


@pytest.mark.parametrize(
"enabled,priority,delay",
[
(True, 100, 60),
(False, 500, 300),
(True, None, None),
(False, 0, 0),
(True, 10000, 86400),
],
)
def test_lab_autostart_properties(enabled, priority, delay):
"""Test autostart property getters and setters."""
from unittest.mock import patch

session = MagicMock()
session.patch.return_value = Mock()
lab = Lab(
"test_lab",
"1",
session,
"user",
"pass",
auto_sync=False,
resource_pool_manager=RESOURCE_POOL_MANAGER,
)

with patch.object(lab, "sync_topology_if_outdated"):
lab.autostart_enabled = enabled
lab.autostart_priority = priority
lab.autostart_delay = delay

assert lab.autostart_enabled == enabled
assert lab.autostart_priority == priority
assert lab.autostart_delay == delay

assert lab._autostart == {
"enabled": enabled,
"priority": priority,
"delay": delay,
}


def test_lab_set_autostart():
"""Test set_autostart convenience method."""
from unittest.mock import patch

session = MagicMock()
session.patch.return_value = Mock()
lab = Lab(
"test_lab",
"1",
session,
"user",
"pass",
auto_sync=False,
resource_pool_manager=RESOURCE_POOL_MANAGER,
)

with patch.object(lab, "sync_topology_if_outdated"):
# Test setting all values at once
lab.set_autostart(enabled=True, priority=500, delay=120)

assert lab._autostart == {"enabled": True, "priority": 500, "delay": 120}
assert lab.autostart_enabled is True
assert lab.autostart_priority == 500
assert lab.autostart_delay == 120

# Test validation in convenience method
with pytest.raises(
ValueError, match="autostart_priority must be between 0 and 10000"
):
lab.set_autostart(enabled=True, priority=15000)

with pytest.raises(
ValueError, match="autostart_delay must be between 0 and 86400"
):
lab.set_autostart(enabled=True, delay=100000)


@pytest.mark.parametrize(
"property_name,invalid_value,error_match",
[
("autostart_priority", 15000, "between 0 and 10000"),
("autostart_priority", -1, "between 0 and 10000"),
("autostart_delay", 100000, "between 0 and 86400"),
("autostart_delay", -1, "between 0 and 86400"),
],
)
def test_lab_autostart_validation(property_name, invalid_value, error_match):
"""Test autostart property validation."""
session = MagicMock()
lab = Lab(
"test_lab",
"1",
session,
"user",
"pass",
auto_sync=False,
resource_pool_manager=RESOURCE_POOL_MANAGER,
)

with pytest.raises(ValueError, match=error_match):
setattr(lab, property_name, invalid_value)


@pytest.mark.parametrize("has_autostart", [True, False])
def test_lab_import_autostart(has_autostart):
"""Test importing lab topology with/without autostart configuration."""
session = MagicMock()
lab = Lab(
"test_lab",
"1",
session,
"user",
"pass",
auto_sync=False,
resource_pool_manager=RESOURCE_POOL_MANAGER,
)

topology = {
"lab": {"title": "Test Lab", "description": "Test", "notes": "Notes"},
"nodes": [],
"links": [],
}

if has_autostart:
topology["lab"]["autostart"] = {"enabled": True, "priority": 200, "delay": 180}
expected = {"enabled": True, "priority": 200, "delay": 180}
else:
expected = {"enabled": False, "priority": None, "delay": None}

lab._import_lab(topology)
assert lab._autostart == expected


@pytest.mark.parametrize("has_autostart", [True, False])
def test_lab_import_autostart_new_field(has_autostart):
"""Test importing lab topology with/without autostart configuration (new field name)."""
session = MagicMock()
lab = Lab(
"test_lab",
"1",
session,
"user",
"pass",
auto_sync=False,
resource_pool_manager=RESOURCE_POOL_MANAGER,
)

topology = {
"lab": {"title": "Test Lab", "description": "Test", "notes": "Notes"},
"nodes": [],
"links": [],
}

if has_autostart:
topology["lab"]["autostart"] = {"enabled": True, "priority": 200, "delay": 180}
expected = {"enabled": True, "priority": 200, "delay": 180}
else:
expected = {"enabled": False, "priority": None, "delay": None}

lab._import_lab(topology)
assert lab._autostart == expected


def test_lab_update_properties_autostart():
"""Test updating lab properties with partial autostart configuration."""
session = MagicMock()
lab = Lab(
"test_lab",
"1",
session,
"user",
"pass",
auto_sync=False,
resource_pool_manager=RESOURCE_POOL_MANAGER,
)

lab._autostart = {"enabled": False, "priority": 100, "delay": 200}

properties = {
"title": "Updated Lab",
"autostart": {"enabled": True, "priority": 300},
}

lab.update_lab_properties(properties)

assert lab._title == "Updated Lab"
assert lab._autostart == {"enabled": True, "priority": 300, "delay": 200}


def test_lab_update_properties_autostart_new_field():
"""Test updating lab properties with partial autostart configuration (new field name)."""
session = MagicMock()
lab = Lab(
"test_lab",
"1",
session,
"user",
"pass",
auto_sync=False,
resource_pool_manager=RESOURCE_POOL_MANAGER,
)

lab._autostart = {"enabled": False, "priority": 100, "delay": 200}

properties = {
"title": "Updated Lab",
"autostart": {"enabled": True, "priority": 300},
}

lab.update_lab_properties(properties)

assert lab._title == "Updated Lab"
assert lab._autostart == {"enabled": True, "priority": 300, "delay": 200}
Loading