1
0
mirror of https://github.com/GNS3/gns3-server synced 2025-05-10 19:08:53 +00:00

Refactor tests and upgrade dev package requirements

This commit is contained in:
grossmj 2025-01-17 19:12:44 +10:00
parent f6725a37dd
commit ba4e0c945d
No known key found for this signature in database
GPG Key ID: 1E7DD6DBB53FF3D7
29 changed files with 5074 additions and 4558 deletions

View File

@ -1,7 +1,7 @@
pytest==8.3.3 pytest==8.3.4
flake8==7.1.1 flake8==7.1.1
pytest-timeout==2.3.1 pytest-timeout==2.3.1
pytest-asyncio==0.21.2 pytest-asyncio==0.25.2
requests==2.32.3 requests==2.32.3
httpx==0.27.2 # version 0.24.1 is required by httpx_ws httpx==0.28.1
httpx_ws==0.6.2 httpx_ws==0.7.1

View File

@ -29,27 +29,29 @@ from gns3server.utils.path import get_default_project_directory
pytestmark = pytest.mark.asyncio pytestmark = pytest.mark.asyncio
async def test_get(app: FastAPI, compute_client: AsyncClient, windows_platform) -> None: class TestCapabilitiesRoutes:
response = await compute_client.get(app.url_path_for("compute:get_capabilities")) async def test_get(self, app: FastAPI, compute_client: AsyncClient, windows_platform) -> None:
assert response.status_code == status.HTTP_200_OK
assert response.json() == {'node_types': ['cloud', 'ethernet_hub', 'ethernet_switch', 'nat', 'vpcs', 'virtualbox', 'dynamips', 'frame_relay_switch', 'atm_switch', 'qemu', 'vmware', 'docker', 'iou'], response = await compute_client.get(app.url_path_for("compute:get_capabilities"))
'version': __version__, assert response.status_code == status.HTTP_200_OK
'platform': sys.platform, assert response.json() == {'node_types': ['cloud', 'ethernet_hub', 'ethernet_switch', 'nat', 'vpcs', 'virtualbox', 'dynamips', 'frame_relay_switch', 'atm_switch', 'qemu', 'vmware', 'docker', 'iou'],
'cpus': psutil.cpu_count(logical=True), 'version': __version__,
'memory': psutil.virtual_memory().total, 'platform': sys.platform,
'disk_size': psutil.disk_usage(get_default_project_directory()).total, 'cpus': psutil.cpu_count(logical=True),
} 'memory': psutil.virtual_memory().total,
'disk_size': psutil.disk_usage(get_default_project_directory()).total,
}
async def test_get_on_gns3vm(app: FastAPI, compute_client: AsyncClient, on_gns3vm) -> None: async def test_get_on_gns3vm(self, app: FastAPI, compute_client: AsyncClient, on_gns3vm) -> None:
response = await compute_client.get(app.url_path_for("compute:get_capabilities")) response = await compute_client.get(app.url_path_for("compute:get_capabilities"))
assert response.status_code == status.HTTP_200_OK assert response.status_code == status.HTTP_200_OK
assert response.json() == {'node_types': ['cloud', 'ethernet_hub', 'ethernet_switch', 'nat', 'vpcs', 'virtualbox', 'dynamips', 'frame_relay_switch', 'atm_switch', 'qemu', 'vmware', 'docker', 'iou'], assert response.json() == {'node_types': ['cloud', 'ethernet_hub', 'ethernet_switch', 'nat', 'vpcs', 'virtualbox', 'dynamips', 'frame_relay_switch', 'atm_switch', 'qemu', 'vmware', 'docker', 'iou'],
'version': __version__, 'version': __version__,
'platform': sys.platform, 'platform': sys.platform,
'cpus': psutil.cpu_count(logical=True), 'cpus': psutil.cpu_count(logical=True),
'memory': psutil.virtual_memory().total, 'memory': psutil.virtual_memory().total,
'disk_size': psutil.disk_usage(get_default_project_directory()).total, 'disk_size': psutil.disk_usage(get_default_project_directory()).total,
} }

View File

@ -28,154 +28,193 @@ from gns3server.compute.project import Project
pytestmark = pytest.mark.asyncio pytestmark = pytest.mark.asyncio
@pytest_asyncio.fixture(scope="function") class TestCloudNodesRoutes:
async def vm(app: FastAPI, compute_client: AsyncClient, compute_project: Project, on_gns3vm) -> dict:
with asyncio_patch("gns3server.compute.builtin.nodes.cloud.Cloud._start_ubridge"): @pytest_asyncio.fixture
response = await compute_client.post(app.url_path_for("compute:create_cloud", project_id=compute_project.id), async def vm(self, app: FastAPI, compute_client: AsyncClient, compute_project: Project, on_gns3vm) -> dict:
json={"name": "Cloud 1"})
assert response.status_code == status.HTTP_201_CREATED with asyncio_patch("gns3server.compute.builtin.nodes.cloud.Cloud._start_ubridge"):
return response.json() response = await compute_client.post(app.url_path_for("compute:create_cloud", project_id=compute_project.id),
json={"name": "Cloud 1"})
assert response.status_code == status.HTTP_201_CREATED
return response.json()
async def test_cloud_create(app: FastAPI, compute_client: AsyncClient, compute_project: Project) -> None: async def test_cloud_create(
self, app: FastAPI,
compute_client: AsyncClient,
compute_project: Project
) -> None:
with asyncio_patch("gns3server.compute.builtin.nodes.cloud.Cloud._start_ubridge"): with asyncio_patch("gns3server.compute.builtin.nodes.cloud.Cloud._start_ubridge"):
response = await compute_client.post(app.url_path_for("compute:create_cloud", project_id=compute_project.id), response = await compute_client.post(app.url_path_for("compute:create_cloud", project_id=compute_project.id),
json={"name": "Cloud 1"}) json={"name": "Cloud 1"})
assert response.status_code == 201 assert response.status_code == 201
assert response.json()["name"] == "Cloud 1" assert response.json()["name"] == "Cloud 1"
assert response.json()["project_id"] == compute_project.id assert response.json()["project_id"] == compute_project.id
async def test_get_cloud(app: FastAPI, compute_client: AsyncClient, compute_project: Project, vm: dict) -> None: async def test_get_cloud(
self, app: FastAPI,
compute_client: AsyncClient,
compute_project: Project,
vm: dict
) -> None:
response = await compute_client.get(app.url_path_for("compute:get_cloud", project_id=vm["project_id"], node_id=vm["node_id"])) response = await compute_client.get(app.url_path_for("compute:get_cloud", project_id=vm["project_id"], node_id=vm["node_id"]))
assert response.status_code == status.HTTP_200_OK
assert response.json()["name"] == "Cloud 1"
assert response.json()["project_id"] == compute_project.id
assert response.json()["status"] == "started"
async def test_cloud_nio_create_udp(app: FastAPI, compute_client: AsyncClient, compute_project: Project, vm: dict) -> None:
params = {"type": "nio_udp",
"lport": 4242,
"rport": 4343,
"rhost": "127.0.0.1"}
url = app.url_path_for("compute:create_cloud_nio",
project_id=vm["project_id"],
node_id=vm["node_id"],
adapter_number="0",
port_number="0")
response = await compute_client.post(url, json=params)
assert response.status_code == status.HTTP_201_CREATED
assert response.json()["type"] == "nio_udp"
async def test_cloud_nio_update_udp(app: FastAPI, compute_client: AsyncClient, compute_project: Project, vm: dict) -> None:
params = {"type": "nio_udp",
"lport": 4242,
"rport": 4343,
"rhost": "127.0.0.1"}
url = app.url_path_for("compute:create_cloud_nio",
project_id=vm["project_id"],
node_id=vm["node_id"],
adapter_number="0",
port_number="0")
await compute_client.post(url, json=params)
params["filters"] = {}
url = app.url_path_for("compute:create_cloud_nio",
project_id=vm["project_id"],
node_id=vm["node_id"],
adapter_number="0",
port_number="0")
response = await compute_client.put(url, json=params)
assert response.status_code == status.HTTP_201_CREATED
assert response.json()["type"] == "nio_udp"
async def test_cloud_delete_nio(app: FastAPI, compute_client: AsyncClient, compute_project: Project, vm: dict) -> None:
params = {"type": "nio_udp",
"lport": 4242,
"rport": 4343,
"rhost": "127.0.0.1"}
url = app.url_path_for("compute:create_cloud_nio",
project_id=vm["project_id"],
node_id=vm["node_id"],
adapter_number="0",
port_number="0")
await compute_client.post(url, json=params)
url = app.url_path_for("compute:delete_cloud_nio",
project_id=vm["project_id"],
node_id=vm["node_id"],
adapter_number="0",
port_number="0")
with asyncio_patch("gns3server.compute.builtin.nodes.cloud.Cloud._start_ubridge"):
response = await compute_client.delete(url)
assert response.status_code == status.HTTP_204_NO_CONTENT
async def test_cloud_delete(app: FastAPI, compute_client: AsyncClient, compute_project: Project, vm: dict) -> None:
response = await compute_client.delete(app.url_path_for("compute:delete_cloud", project_id=vm["project_id"], node_id=vm["node_id"]))
assert response.status_code == status.HTTP_204_NO_CONTENT
async def test_cloud_update(app: FastAPI, compute_client: AsyncClient, vm: dict) -> None:
response = await compute_client.put(app.url_path_for("compute:update_cloud", project_id=vm["project_id"], node_id=vm["node_id"]),
json={"name": "test"})
assert response.status_code == status.HTTP_200_OK
assert response.json()["name"] == "test"
async def test_cloud_start_capture(app: FastAPI, compute_client: AsyncClient, vm: dict) -> None:
params = {
"capture_file_name": "test.pcap",
"data_link_type": "DLT_EN10MB"
}
with asyncio_patch("gns3server.compute.builtin.nodes.cloud.Cloud.start_capture") as mock:
response = await compute_client.post(app.url_path_for("compute:start_cloud_capture",
project_id=vm["project_id"],
node_id=vm["node_id"],
adapter_number="0",
port_number="0"),
json=params)
assert response.status_code == status.HTTP_200_OK assert response.status_code == status.HTTP_200_OK
assert mock.called assert response.json()["name"] == "Cloud 1"
assert "test.pcap" in response.json()["pcap_file_path"] assert response.json()["project_id"] == compute_project.id
assert response.json()["status"] == "started"
async def test_cloud_stop_capture(app: FastAPI, compute_client: AsyncClient, vm: dict) -> None: async def test_cloud_nio_create_udp(
self, app: FastAPI,
compute_client: AsyncClient,
compute_project: Project,
vm: dict
) -> None:
with asyncio_patch("gns3server.compute.builtin.nodes.cloud.Cloud.stop_capture") as mock: params = {"type": "nio_udp",
response = await compute_client.post(app.url_path_for("compute:stop_cloud_capture", "lport": 4242,
project_id=vm["project_id"], "rport": 4343,
node_id=vm["node_id"], "rhost": "127.0.0.1"}
adapter_number="0",
port_number="0")) url = app.url_path_for("compute:create_cloud_nio",
project_id=vm["project_id"],
node_id=vm["node_id"],
adapter_number="0",
port_number="0")
response = await compute_client.post(url, json=params)
assert response.status_code == status.HTTP_201_CREATED
assert response.json()["type"] == "nio_udp"
async def test_cloud_nio_update_udp(
self, app: FastAPI,
compute_client: AsyncClient,
compute_project: Project,
vm: dict
) -> None:
params = {"type": "nio_udp",
"lport": 4242,
"rport": 4343,
"rhost": "127.0.0.1"}
url = app.url_path_for("compute:create_cloud_nio",
project_id=vm["project_id"],
node_id=vm["node_id"],
adapter_number="0",
port_number="0")
await compute_client.post(url, json=params)
params["filters"] = {}
url = app.url_path_for("compute:create_cloud_nio",
project_id=vm["project_id"],
node_id=vm["node_id"],
adapter_number="0",
port_number="0")
response = await compute_client.put(url, json=params)
assert response.status_code == status.HTTP_201_CREATED
assert response.json()["type"] == "nio_udp"
async def test_cloud_delete_nio(
self, app: FastAPI,
compute_client: AsyncClient,
compute_project: Project,
vm: dict
) -> None:
params = {"type": "nio_udp",
"lport": 4242,
"rport": 4343,
"rhost": "127.0.0.1"}
url = app.url_path_for("compute:create_cloud_nio",
project_id=vm["project_id"],
node_id=vm["node_id"],
adapter_number="0",
port_number="0")
await compute_client.post(url, json=params)
url = app.url_path_for("compute:delete_cloud_nio",
project_id=vm["project_id"],
node_id=vm["node_id"],
adapter_number="0",
port_number="0")
with asyncio_patch("gns3server.compute.builtin.nodes.cloud.Cloud._start_ubridge"):
response = await compute_client.delete(url)
assert response.status_code == status.HTTP_204_NO_CONTENT assert response.status_code == status.HTTP_204_NO_CONTENT
assert mock.called
# @pytest.mark.asyncio async def test_cloud_delete(
# async def test_cloud_pcap(compute_api, vm, compute_project): self, app: FastAPI,
# compute_client: AsyncClient,
# from itertools import repeat compute_project: Project,
# stream = repeat(42, times=10) vm: dict
# ) -> None:
# with asyncio_patch("gns3server.compute.builtin.nodes.cloud.Cloud.get_nio"):
# with asyncio_patch("gns3server.compute.builtin.Builtin.stream_pcap_file", return_value=stream): response = await compute_client.delete(app.url_path_for("compute:delete_cloud", project_id=vm["project_id"], node_id=vm["node_id"]))
# response = await compute_api.get("/projects/{project_id}/cloud/nodes/{node_id}/adapters/0/ports/0/pcap".format(project_id=compute_project.id, node_id=vm["node_id"])) assert response.status_code == status.HTTP_204_NO_CONTENT
# assert response.status_code == 200
#
async def test_cloud_update(
self, app: FastAPI,
compute_client: AsyncClient,
vm: dict
) -> None:
response = await compute_client.put(app.url_path_for("compute:update_cloud", project_id=vm["project_id"], node_id=vm["node_id"]),
json={"name": "test"})
assert response.status_code == status.HTTP_200_OK
assert response.json()["name"] == "test"
async def test_cloud_start_capture(
self, app: FastAPI,
compute_client: AsyncClient,
vm: dict
) -> None:
params = {
"capture_file_name": "test.pcap",
"data_link_type": "DLT_EN10MB"
}
with asyncio_patch("gns3server.compute.builtin.nodes.cloud.Cloud.start_capture") as mock:
response = await compute_client.post(app.url_path_for("compute:start_cloud_capture",
project_id=vm["project_id"],
node_id=vm["node_id"],
adapter_number="0",
port_number="0"),
json=params)
assert response.status_code == status.HTTP_200_OK
assert mock.called
assert "test.pcap" in response.json()["pcap_file_path"]
async def test_cloud_stop_capture(self, app: FastAPI, compute_client: AsyncClient, vm: dict) -> None:
with asyncio_patch("gns3server.compute.builtin.nodes.cloud.Cloud.stop_capture") as mock:
response = await compute_client.post(app.url_path_for("compute:stop_cloud_capture",
project_id=vm["project_id"],
node_id=vm["node_id"],
adapter_number="0",
port_number="0"))
assert response.status_code == status.HTTP_204_NO_CONTENT
assert mock.called
# @pytest.mark.asyncio
# async def test_cloud_pcap(self, compute_api, vm, compute_project):
#
# from itertools import repeat
# stream = repeat(42, times=10)
#
# with asyncio_patch("gns3server.compute.builtin.nodes.cloud.Cloud.get_nio"):
# with asyncio_patch("gns3server.compute.builtin.Builtin.stream_pcap_file", return_value=stream):
# response = await compute_api.get("/projects/{project_id}/cloud/nodes/{node_id}/adapters/0/ports/0/pcap".format(project_id=compute_project.id, node_id=vm["node_id"]))
# assert response.status_code == 200
#

View File

@ -26,41 +26,48 @@ from gns3server.compute.project import Project
pytestmark = pytest.mark.asyncio pytestmark = pytest.mark.asyncio
async def test_udp_allocation(app: FastAPI, compute_client: AsyncClient, compute_project: Project) -> None: class TestComputeRoutes:
response = await compute_client.post(app.url_path_for("compute:allocate_udp_port", project_id=compute_project.id), json={}) async def test_udp_allocation(
assert response.status_code == status.HTTP_201_CREATED self,
assert response.json()['udp_port'] is not None app: FastAPI,
compute_client: AsyncClient,
compute_project: Project
) -> None:
response = await compute_client.post(app.url_path_for("compute:allocate_udp_port", project_id=compute_project.id), json={})
assert response.status_code == status.HTTP_201_CREATED
assert response.json()['udp_port'] is not None
async def test_interfaces(app: FastAPI, compute_client: AsyncClient) -> None: async def test_interfaces(self, app: FastAPI, compute_client: AsyncClient) -> None:
response = await compute_client.get(app.url_path_for("compute:network_interfaces")) response = await compute_client.get(app.url_path_for("compute:network_interfaces"))
assert response.status_code == status.HTTP_200_OK assert response.status_code == status.HTTP_200_OK
assert isinstance(response.json(), list) assert isinstance(response.json(), list)
async def test_version_output(app: FastAPI, compute_client: AsyncClient) -> None: async def test_version_output(self, app: FastAPI, compute_client: AsyncClient) -> None:
response = await compute_client.get(app.url_path_for("compute:compute_version")) response = await compute_client.get(app.url_path_for("compute:compute_version"))
assert response.status_code == status.HTTP_200_OK assert response.status_code == status.HTTP_200_OK
assert response.json() == {'version': __version__} assert response.json() == {'version': __version__}
async def test_compute_authentication(app: FastAPI, compute_client: AsyncClient) -> None: async def test_compute_authentication(self, app: FastAPI, compute_client: AsyncClient) -> None:
response = await compute_client.get(app.url_path_for("compute:compute_version"), auth=("admin", "invalid_password")) response = await compute_client.get(app.url_path_for("compute:compute_version"), auth=("admin", "invalid_password"))
assert response.status_code == status.HTTP_401_UNAUTHORIZED assert response.status_code == status.HTTP_401_UNAUTHORIZED
# @pytest.mark.asyncio # @pytest.mark.asyncio
# async def test_debug_output(compute_api): # async def test_debug_output(compute_api):
# #
# response = await compute_api.get('/debug') # response = await compute_api.get('/debug')
# assert response.status_code == 200 # assert response.status_code == 200
async def test_statistics_output(app: FastAPI, compute_client: AsyncClient) -> None: async def test_statistics_output(self, app: FastAPI, compute_client: AsyncClient) -> None:
response = await compute_client.get(app.url_path_for("compute:compute_statistics")) response = await compute_client.get(app.url_path_for("compute:compute_statistics"))
assert response.status_code == status.HTTP_200_OK assert response.status_code == status.HTTP_200_OK

View File

@ -25,285 +25,299 @@ from unittest.mock import patch
from gns3server.compute.project import Project from gns3server.compute.project import Project
pytestmark = [pytest.mark.asyncio] pytestmark = pytest.mark.asyncio
@pytest.fixture class TestDockerNodesRoutes:
def base_params() -> dict:
"""Return standard parameters"""
params = { @pytest.fixture
"name": "DOCKER-TEST-1", def base_params(self) -> dict:
"image": "nginx", """Return standard parameters"""
"start_command": "nginx-daemon",
"adapters": 2, params = {
"environment": "YES=1\nNO=0", "name": "DOCKER-TEST-1",
"console_type": "telnet", "image": "nginx",
"console_resolution": "1280x1024", "start_command": "nginx-daemon",
"extra_hosts": "test:127.0.0.1" "adapters": 2,
} "environment": "YES=1\nNO=0",
return params "console_type": "telnet",
"console_resolution": "1280x1024",
"extra_hosts": "test:127.0.0.1"
}
return params
# @pytest.yield_fixture(autouse=True) # @pytest.yield_fixture(autouse=True)
# def mock_connection(): # def mock_connection():
# #
# docker = Docker.instance() # docker = Docker.instance()
# docker._connected = True # docker._connected = True
# docker._connector = MagicMock() # docker._connector = MagicMock()
# yield # yield
# Docker._instance = None # Docker._instance = None
@pytest_asyncio.fixture @pytest_asyncio.fixture
async def vm(app: FastAPI, compute_client: AsyncClient, compute_project: Project, base_params: dict) -> dict: async def vm(
self,
app: FastAPI,
compute_client: AsyncClient,
compute_project: Project,
base_params: dict
) -> dict:
with asyncio_patch("gns3server.compute.docker.Docker.list_images", return_value=[{"image": "nginx"}]): with asyncio_patch("gns3server.compute.docker.Docker.list_images", return_value=[{"image": "nginx"}]):
with asyncio_patch("gns3server.compute.docker.Docker.query", return_value={"Id": "8bd8153ea8f5"}): with asyncio_patch("gns3server.compute.docker.Docker.query", return_value={"Id": "8bd8153ea8f5"}):
with asyncio_patch("gns3server.compute.docker.DockerVM._get_container_state", return_value="exited"): with asyncio_patch("gns3server.compute.docker.DockerVM._get_container_state", return_value="exited"):
response = await compute_client.post(app.url_path_for("compute:create_docker_node", project_id=compute_project.id), response = await compute_client.post(app.url_path_for("compute:create_docker_node", project_id=compute_project.id),
json=base_params) json=base_params)
assert response.status_code == status.HTTP_201_CREATED assert response.status_code == status.HTTP_201_CREATED
return response.json() return response.json()
async def test_docker_create(app: FastAPI, compute_client: AsyncClient, compute_project: Project, base_params: dict) -> None: async def test_docker_create(
self, app: FastAPI,
compute_client: AsyncClient,
compute_project: Project,
base_params: dict
) -> None:
with asyncio_patch("gns3server.compute.docker.Docker.list_images", return_value=[{"image": "nginx"}]): with asyncio_patch("gns3server.compute.docker.Docker.list_images", return_value=[{"image": "nginx"}]):
with asyncio_patch("gns3server.compute.docker.Docker.query", return_value={"Id": "8bd8153ea8f5"}): with asyncio_patch("gns3server.compute.docker.Docker.query", return_value={"Id": "8bd8153ea8f5"}):
response = await compute_client.post( response = await compute_client.post(
app.url_path_for("compute:create_docker_node", project_id=compute_project.id), json=base_params app.url_path_for("compute:create_docker_node", project_id=compute_project.id), json=base_params
) )
assert response.status_code == status.HTTP_201_CREATED assert response.status_code == status.HTTP_201_CREATED
assert response.json()["name"] == "DOCKER-TEST-1" assert response.json()["name"] == "DOCKER-TEST-1"
assert response.json()["project_id"] == compute_project.id assert response.json()["project_id"] == compute_project.id
assert response.json()["container_id"] == "8bd8153ea8f5" assert response.json()["container_id"] == "8bd8153ea8f5"
assert response.json()["image"] == "nginx:latest" assert response.json()["image"] == "nginx:latest"
assert response.json()["adapters"] == 2 assert response.json()["adapters"] == 2
assert response.json()["environment"] == "YES=1\nNO=0" assert response.json()["environment"] == "YES=1\nNO=0"
assert response.json()["console_resolution"] == "1280x1024" assert response.json()["console_resolution"] == "1280x1024"
assert response.json()["extra_hosts"] == "test:127.0.0.1" assert response.json()["extra_hosts"] == "test:127.0.0.1"
@pytest.mark.parametrize( @pytest.mark.parametrize(
"name, status_code", "name, status_code",
( (
("valid-name.com", status.HTTP_201_CREATED), ("valid-name.com", status.HTTP_201_CREATED),
("42name", status.HTTP_201_CREATED), ("42name", status.HTTP_201_CREATED),
("424242", status.HTTP_409_CONFLICT), ("424242", status.HTTP_409_CONFLICT),
("name42", status.HTTP_201_CREATED), ("name42", status.HTTP_201_CREATED),
("name.424242", status.HTTP_409_CONFLICT), ("name.424242", status.HTTP_409_CONFLICT),
("-name", status.HTTP_409_CONFLICT), ("-name", status.HTTP_409_CONFLICT),
("name%-test", status.HTTP_409_CONFLICT), ("name%-test", status.HTTP_409_CONFLICT),
("x" * 63, status.HTTP_201_CREATED), ("x" * 63, status.HTTP_201_CREATED),
("x" * 64, status.HTTP_409_CONFLICT), ("x" * 64, status.HTTP_409_CONFLICT),
(("x" * 62 + ".") * 4, status.HTTP_201_CREATED), (("x" * 62 + ".") * 4, status.HTTP_201_CREATED),
("xx" + ("x" * 62 + ".") * 4, status.HTTP_409_CONFLICT), ("xx" + ("x" * 62 + ".") * 4, status.HTTP_409_CONFLICT),
), ),
) )
async def test_docker_create_with_invalid_name( async def test_docker_create_with_invalid_name(
app: FastAPI, self,
compute_client: AsyncClient, app: FastAPI,
compute_project: Project, compute_client: AsyncClient,
base_params: dict, compute_project: Project,
name: str, base_params: dict,
status_code: int name: str,
) -> None: status_code: int
) -> None:
base_params["name"] = name base_params["name"] = name
with asyncio_patch("gns3server.compute.docker.Docker.list_images", return_value=[{"image": "nginx"}]): with asyncio_patch("gns3server.compute.docker.Docker.list_images", return_value=[{"image": "nginx"}]):
with asyncio_patch("gns3server.compute.docker.Docker.query", return_value={"Id": "8bd8153ea8f5"}): with asyncio_patch("gns3server.compute.docker.Docker.query", return_value={"Id": "8bd8153ea8f5"}):
response = await compute_client.post( response = await compute_client.post(
app.url_path_for("compute:create_docker_node", project_id=compute_project.id), json=base_params app.url_path_for("compute:create_docker_node", project_id=compute_project.id), json=base_params
) )
assert response.status_code == status_code assert response.status_code == status_code
async def test_docker_start(app: FastAPI, compute_client: AsyncClient, vm: dict) -> None: async def test_docker_start(self, app: FastAPI, compute_client: AsyncClient, vm: dict) -> None:
with asyncio_patch("gns3server.compute.docker.docker_vm.DockerVM.start", return_value=True) as mock: with asyncio_patch("gns3server.compute.docker.docker_vm.DockerVM.start", return_value=True) as mock:
response = await compute_client.post(app.url_path_for("compute:start_docker_node", response = await compute_client.post(app.url_path_for("compute:start_docker_node",
project_id=vm["project_id"], project_id=vm["project_id"],
node_id=vm["node_id"])) node_id=vm["node_id"]))
assert mock.called
assert response.status_code == status.HTTP_204_NO_CONTENT
async def test_docker_stop(app: FastAPI, compute_client: AsyncClient, vm: dict) -> None:
with asyncio_patch("gns3server.compute.docker.docker_vm.DockerVM.stop", return_value=True) as mock:
response = await compute_client.post(app.url_path_for("compute:stop_docker_node",
project_id=vm["project_id"],
node_id=vm["node_id"]))
assert mock.called
assert response.status_code == status.HTTP_204_NO_CONTENT
async def test_docker_reload(app: FastAPI, compute_client: AsyncClient, vm: dict) -> None:
with asyncio_patch("gns3server.compute.docker.docker_vm.DockerVM.restart", return_value=True) as mock:
response = await compute_client.post(app.url_path_for("compute:reload_docker_node",
project_id=vm["project_id"],
node_id=vm["node_id"]))
assert mock.called
assert response.status_code == status.HTTP_204_NO_CONTENT
async def test_docker_delete(app: FastAPI, compute_client: AsyncClient, vm: dict) -> None:
with asyncio_patch("gns3server.compute.docker.docker_vm.DockerVM.delete", return_value=True) as mock:
response = await compute_client.delete(app.url_path_for("compute:delete_docker_node",
project_id=vm["project_id"],
node_id=vm["node_id"]))
assert mock.called
assert response.status_code == status.HTTP_204_NO_CONTENT
async def test_docker_pause(app: FastAPI, compute_client: AsyncClient, vm: dict) -> None:
with asyncio_patch("gns3server.compute.docker.docker_vm.DockerVM.pause", return_value=True) as mock:
response = await compute_client.post(app.url_path_for("compute:pause_docker_node",
project_id=vm["project_id"],
node_id=vm["node_id"]))
assert mock.called
assert response.status_code == status.HTTP_204_NO_CONTENT
async def test_docker_unpause(app: FastAPI, compute_client: AsyncClient, vm: dict) -> None:
with asyncio_patch("gns3server.compute.docker.docker_vm.DockerVM.unpause", return_value=True) as mock:
response = await compute_client.post(app.url_path_for("compute:unpause_docker_node",
project_id=vm["project_id"],
node_id=vm["node_id"]))
assert mock.called
assert response.status_code == status.HTTP_204_NO_CONTENT
async def test_docker_nio_create_udp(app: FastAPI, compute_client: AsyncClient, vm: dict) -> None:
params = {
"type": "nio_udp",
"lport": 4242,
"rport": 4343,
"rhost": "127.0.0.1"}
url = app.url_path_for("compute:create_docker_node_nio",
project_id=vm["project_id"],
node_id=vm["node_id"],
adapter_number="0",
port_number="0")
response = await compute_client.post(url, json=params)
assert response.status_code == status.HTTP_201_CREATED
assert response.json()["type"] == "nio_udp"
async def test_docker_update_nio(app: FastAPI, compute_client: AsyncClient, vm: dict) -> None:
params = {
"type": "nio_udp",
"lport": 4242,
"rport": 4343,
"rhost": "127.0.0.1"
}
url = app.url_path_for("compute:create_docker_node_nio",
project_id=vm["project_id"],
node_id=vm["node_id"],
adapter_number="0",
port_number="0")
response = await compute_client.post(url, json=params)
assert response.status_code == status.HTTP_201_CREATED
url = app.url_path_for("compute:update_docker_node_nio",
project_id=vm["project_id"],
node_id=vm["node_id"],
adapter_number="0",
port_number="0")
with asyncio_patch("gns3server.compute.docker.docker_vm.DockerVM.adapter_update_nio_binding"):
response = await compute_client.put(url, json=params)
assert response.status_code == status.HTTP_201_CREATED
async def test_docker_delete_nio(app: FastAPI, compute_client: AsyncClient, vm: dict) -> None:
url = app.url_path_for("compute:delete_docker_node_nio",
project_id=vm["project_id"],
node_id=vm["node_id"],
adapter_number="0",
port_number="0")
with asyncio_patch("gns3server.compute.docker.docker_vm.DockerVM.adapter_remove_nio_binding"):
response = await compute_client.delete(url)
assert response.status_code == status.HTTP_204_NO_CONTENT
async def test_docker_update(app: FastAPI, compute_client: AsyncClient, vm: dict, free_console_port: int) -> None:
params = {
"name": "test",
"console": free_console_port,
"start_command": "yes",
"environment": "GNS3=1\nGNS4=0",
"extra_hosts": "test:127.0.0.1"
}
with asyncio_patch("gns3server.compute.docker.docker_vm.DockerVM.update") as mock:
response = await compute_client.put(app.url_path_for("compute:update_docker_node",
project_id=vm["project_id"],
node_id=vm["node_id"]), json=params)
assert response.status_code == 200
assert mock.called
assert response.json()["name"] == "test"
assert response.json()["console"] == free_console_port
assert response.json()["start_command"] == "yes"
assert response.json()["environment"] == "GNS3=1\nGNS4=0"
assert response.json()["extra_hosts"] == "test:127.0.0.1"
async def test_docker_start_capture(app: FastAPI, compute_client: AsyncClient, vm: dict) -> None:
url = app.url_path_for("compute:start_docker_node_capture",
project_id=vm["project_id"],
node_id=vm["node_id"],
adapter_number="0",
port_number="0")
with patch("gns3server.compute.docker.docker_vm.DockerVM.is_running", return_value=True):
with asyncio_patch("gns3server.compute.docker.docker_vm.DockerVM.start_capture") as mock:
params = {"capture_file_name": "test.pcap", "data_link_type": "DLT_EN10MB"}
response = await compute_client.post(url, json=params)
assert response.status_code == status.HTTP_200_OK
assert mock.called assert mock.called
assert "test.pcap" in response.json()["pcap_file_path"]
async def test_docker_stop_capture(app: FastAPI, compute_client: AsyncClient, vm: dict) -> None:
url = app.url_path_for("compute:stop_docker_node_capture",
project_id=vm["project_id"],
node_id=vm["node_id"],
adapter_number="0",
port_number="0")
with patch("gns3server.compute.docker.docker_vm.DockerVM.is_running", return_value=True):
with asyncio_patch("gns3server.compute.docker.docker_vm.DockerVM.stop_capture") as mock:
response = await compute_client.post(url)
assert response.status_code == status.HTTP_204_NO_CONTENT assert response.status_code == status.HTTP_204_NO_CONTENT
async def test_docker_stop(self, app: FastAPI, compute_client: AsyncClient, vm: dict) -> None:
with asyncio_patch("gns3server.compute.docker.docker_vm.DockerVM.stop", return_value=True) as mock:
response = await compute_client.post(app.url_path_for("compute:stop_docker_node",
project_id=vm["project_id"],
node_id=vm["node_id"]))
assert mock.called assert mock.called
assert response.status_code == status.HTTP_204_NO_CONTENT
async def test_docker_duplicate(app: FastAPI, compute_client: AsyncClient, vm: dict, base_params: dict) -> None: async def test_docker_reload(self, app: FastAPI, compute_client: AsyncClient, vm: dict) -> None:
# create destination node first with asyncio_patch("gns3server.compute.docker.docker_vm.DockerVM.restart", return_value=True) as mock:
with asyncio_patch("gns3server.compute.docker.Docker.list_images", return_value=[{"image": "nginx"}]): response = await compute_client.post(app.url_path_for("compute:reload_docker_node",
with asyncio_patch("gns3server.compute.docker.Docker.query", return_value={"Id": "8bd8153ea8f5"}): project_id=vm["project_id"],
response = await compute_client.post(app.url_path_for("compute:create_docker_node", node_id=vm["node_id"]))
project_id=vm["project_id"]), json=base_params) assert mock.called
assert response.status_code == status.HTTP_201_CREATED assert response.status_code == status.HTTP_204_NO_CONTENT
params = {"destination_node_id": response.json()["node_id"]}
response = await compute_client.post(app.url_path_for("compute:duplicate_docker_node", async def test_docker_delete(self, app: FastAPI, compute_client: AsyncClient, vm: dict) -> None:
project_id=vm["project_id"],
node_id=vm["node_id"]), json=params) with asyncio_patch("gns3server.compute.docker.docker_vm.DockerVM.delete", return_value=True) as mock:
assert response.status_code == status.HTTP_201_CREATED response = await compute_client.delete(app.url_path_for("compute:delete_docker_node",
project_id=vm["project_id"],
node_id=vm["node_id"]))
assert mock.called
assert response.status_code == status.HTTP_204_NO_CONTENT
async def test_docker_pause(self, app: FastAPI, compute_client: AsyncClient, vm: dict) -> None:
with asyncio_patch("gns3server.compute.docker.docker_vm.DockerVM.pause", return_value=True) as mock:
response = await compute_client.post(app.url_path_for("compute:pause_docker_node",
project_id=vm["project_id"],
node_id=vm["node_id"]))
assert mock.called
assert response.status_code == status.HTTP_204_NO_CONTENT
async def test_docker_unpause(self, app: FastAPI, compute_client: AsyncClient, vm: dict) -> None:
with asyncio_patch("gns3server.compute.docker.docker_vm.DockerVM.unpause", return_value=True) as mock:
response = await compute_client.post(app.url_path_for("compute:unpause_docker_node",
project_id=vm["project_id"],
node_id=vm["node_id"]))
assert mock.called
assert response.status_code == status.HTTP_204_NO_CONTENT
async def test_docker_nio_create_udp(self, app: FastAPI, compute_client: AsyncClient, vm: dict) -> None:
params = {
"type": "nio_udp",
"lport": 4242,
"rport": 4343,
"rhost": "127.0.0.1"}
url = app.url_path_for("compute:create_docker_node_nio",
project_id=vm["project_id"],
node_id=vm["node_id"],
adapter_number="0",
port_number="0")
response = await compute_client.post(url, json=params)
assert response.status_code == status.HTTP_201_CREATED
assert response.json()["type"] == "nio_udp"
async def test_docker_update_nio(self, app: FastAPI, compute_client: AsyncClient, vm: dict) -> None:
params = {
"type": "nio_udp",
"lport": 4242,
"rport": 4343,
"rhost": "127.0.0.1"
}
url = app.url_path_for("compute:create_docker_node_nio",
project_id=vm["project_id"],
node_id=vm["node_id"],
adapter_number="0",
port_number="0")
response = await compute_client.post(url, json=params)
assert response.status_code == status.HTTP_201_CREATED
url = app.url_path_for("compute:update_docker_node_nio",
project_id=vm["project_id"],
node_id=vm["node_id"],
adapter_number="0",
port_number="0")
with asyncio_patch("gns3server.compute.docker.docker_vm.DockerVM.adapter_update_nio_binding"):
response = await compute_client.put(url, json=params)
assert response.status_code == status.HTTP_201_CREATED
async def test_docker_delete_nio(self, app: FastAPI, compute_client: AsyncClient, vm: dict) -> None:
url = app.url_path_for("compute:delete_docker_node_nio",
project_id=vm["project_id"],
node_id=vm["node_id"],
adapter_number="0",
port_number="0")
with asyncio_patch("gns3server.compute.docker.docker_vm.DockerVM.adapter_remove_nio_binding"):
response = await compute_client.delete(url)
assert response.status_code == status.HTTP_204_NO_CONTENT
async def test_docker_update(self, app: FastAPI, compute_client: AsyncClient, vm: dict, free_console_port: int) -> None:
params = {
"name": "test",
"console": free_console_port,
"start_command": "yes",
"environment": "GNS3=1\nGNS4=0",
"extra_hosts": "test:127.0.0.1"
}
with asyncio_patch("gns3server.compute.docker.docker_vm.DockerVM.update") as mock:
response = await compute_client.put(app.url_path_for("compute:update_docker_node",
project_id=vm["project_id"],
node_id=vm["node_id"]), json=params)
assert response.status_code == 200
assert mock.called
assert response.json()["name"] == "test"
assert response.json()["console"] == free_console_port
assert response.json()["start_command"] == "yes"
assert response.json()["environment"] == "GNS3=1\nGNS4=0"
assert response.json()["extra_hosts"] == "test:127.0.0.1"
async def test_docker_start_capture(self, app: FastAPI, compute_client: AsyncClient, vm: dict) -> None:
url = app.url_path_for("compute:start_docker_node_capture",
project_id=vm["project_id"],
node_id=vm["node_id"],
adapter_number="0",
port_number="0")
with patch("gns3server.compute.docker.docker_vm.DockerVM.is_running", return_value=True):
with asyncio_patch("gns3server.compute.docker.docker_vm.DockerVM.start_capture") as mock:
params = {"capture_file_name": "test.pcap", "data_link_type": "DLT_EN10MB"}
response = await compute_client.post(url, json=params)
assert response.status_code == status.HTTP_200_OK
assert mock.called
assert "test.pcap" in response.json()["pcap_file_path"]
async def test_docker_stop_capture(self, app: FastAPI, compute_client: AsyncClient, vm: dict) -> None:
url = app.url_path_for("compute:stop_docker_node_capture",
project_id=vm["project_id"],
node_id=vm["node_id"],
adapter_number="0",
port_number="0")
with patch("gns3server.compute.docker.docker_vm.DockerVM.is_running", return_value=True):
with asyncio_patch("gns3server.compute.docker.docker_vm.DockerVM.stop_capture") as mock:
response = await compute_client.post(url)
assert response.status_code == status.HTTP_204_NO_CONTENT
assert mock.called
async def test_docker_duplicate(self, app: FastAPI, compute_client: AsyncClient, vm: dict, base_params: dict) -> None:
# create destination node first
with asyncio_patch("gns3server.compute.docker.Docker.list_images", return_value=[{"image": "nginx"}]):
with asyncio_patch("gns3server.compute.docker.Docker.query", return_value={"Id": "8bd8153ea8f5"}):
response = await compute_client.post(app.url_path_for("compute:create_docker_node",
project_id=vm["project_id"]), json=base_params)
assert response.status_code == status.HTTP_201_CREATED
params = {"destination_node_id": response.json()["node_id"]}
response = await compute_client.post(app.url_path_for("compute:duplicate_docker_node",
project_id=vm["project_id"],
node_id=vm["node_id"]), json=params)
assert response.status_code == status.HTTP_201_CREATED

View File

@ -26,196 +26,208 @@ from httpx import AsyncClient
pytestmark = pytest.mark.asyncio pytestmark = pytest.mark.asyncio
# @pytest.yield_fixture(scope="module")
# async def vm(compute_api, compute_project, fake_image): class TestDynamipsNodesRoutes:
#
# dynamips_path = "/fake/dynamips" # @pytest.yield_fixture(scope="module")
# params = { # async def vm(compute_api, compute_project, fake_image):
# "name": "My router", #
# "platform": "c3745", # dynamips_path = "/fake/dynamips"
# "image": fake_image, # params = {
# "ram": 128 # "name": "My router",
# } # "platform": "c3745",
# with asyncio_patch("gns3server.compute.dynamips.nodes.router.Router.create", return_value=True) as mock: # "image": fake_image,
# response = await compute_api.post("/projects/{project_id}/dynamips/nodes".format(project_id=compute_project.id), params) # "ram": 128
# assert mock.called # }
# assert response.status == 201 # with asyncio_patch("gns3server.compute.dynamips.nodes.router.Router.create", return_value=True) as mock:
# # response = await compute_api.post("/projects/{project_id}/dynamips/nodes".format(project_id=compute_project.id), params)
# #with asyncio_patch("gns3server.compute.dynamips.Dynamips.find_dynamips", return_value=dynamips_path): # assert mock.called
# # yield response.json # assert response.status == 201
#
# #with asyncio_patch("gns3server.compute.dynamips.Dynamips.find_dynamips", return_value=dynamips_path):
# # yield response.json
# async def test_dynamips_vm_create(compute_api, compute_project, fake_image): # async def test_dynamips_vm_create(compute_api, compute_project, fake_image):
# #
# params = { # params = {
# "name": "My router", # "name": "My router",
# "platform": "c3745", # "platform": "c3745",
# "image": os.path.basename(fake_image), # "image": os.path.basename(fake_image),
# "ram": 128 # "ram": 128
# } # }
# #
# print(fake_image) # print(fake_image)
# #
# with asyncio_patch("gns3server.compute.dynamips.nodes.router.Router.create", return_value=True): # with asyncio_patch("gns3server.compute.dynamips.nodes.router.Router.create", return_value=True):
# response = await compute_api.post("/projects/{project_id}/dynamips/nodes".format(project_id=compute_project.id), params) # response = await compute_api.post("/projects/{project_id}/dynamips/nodes".format(project_id=compute_project.id), params)
# assert response.status == 201 # assert response.status == 201
# assert response.json["name"] == "My router" # assert response.json["name"] == "My router"
# assert response.json["project_id"] == compute_project.id # assert response.json["project_id"] == compute_project.id
# assert response.json["dynamips_id"] # assert response.json["dynamips_id"]
# def test_dynamips_vm_get(compute_api, project, vm): # def test_dynamips_vm_get(compute_api, project, vm):
# response = compute_api.get("/projects/{project_id}/dynamips/nodes/{node_id}".format(project_id=vm["project_id"], node_id=vm["node_id"]), example=True) # response = compute_api.get("/projects/{project_id}/dynamips/nodes/{node_id}".format(project_id=vm["project_id"], node_id=vm["node_id"]), example=True)
# assert response.status == 200 # assert response.status == 200
# assert response.route == "/projects/{project_id}/dynamips/nodes/{node_id}" # assert response.route == "/projects/{project_id}/dynamips/nodes/{node_id}"
# assert response.json["name"] == "My router" # assert response.json["name"] == "My router"
# assert response.json["project_id"] == project.id # assert response.json["project_id"] == project.id
# #
# #
# def test_dynamips_vm_start(compute_api, vm): # def test_dynamips_vm_start(compute_api, vm):
# with asyncio_patch("gns3server.compute.dynamips.nodes.router.Router.start", return_value=True) as mock: # with asyncio_patch("gns3server.compute.dynamips.nodes.router.Router.start", return_value=True) as mock:
# response = compute_api.post("/projects/{project_id}/dynamips/nodes/{node_id}/start".format(project_id=vm["project_id"], node_id=vm["node_id"])) # response = compute_api.post("/projects/{project_id}/dynamips/nodes/{node_id}/start".format(project_id=vm["project_id"], node_id=vm["node_id"]))
# assert mock.called # assert mock.called
# assert response.status == 204 # assert response.status == 204
# #
# #
# def test_dynamips_vm_stop(compute_api, vm): # def test_dynamips_vm_stop(compute_api, vm):
# with asyncio_patch("gns3server.compute.dynamips.nodes.router.Router.stop", return_value=True) as mock: # with asyncio_patch("gns3server.compute.dynamips.nodes.router.Router.stop", return_value=True) as mock:
# response = compute_api.post("/projects/{project_id}/dynamips/nodes/{node_id}/stop".format(project_id=vm["project_id"], node_id=vm["node_id"])) # response = compute_api.post("/projects/{project_id}/dynamips/nodes/{node_id}/stop".format(project_id=vm["project_id"], node_id=vm["node_id"]))
# assert mock.called # assert mock.called
# assert response.status == 204 # assert response.status == 204
# #
# #
# def test_dynamips_vm_suspend(compute_api, vm): # def test_dynamips_vm_suspend(compute_api, vm):
# with asyncio_patch("gns3server.compute.dynamips.nodes.router.Router.suspend", return_value=True) as mock: # with asyncio_patch("gns3server.compute.dynamips.nodes.router.Router.suspend", return_value=True) as mock:
# response = compute_api.post("/projects/{project_id}/dynamips/nodes/{node_id}/suspend".format(project_id=vm["project_id"], node_id=vm["node_id"])) # response = compute_api.post("/projects/{project_id}/dynamips/nodes/{node_id}/suspend".format(project_id=vm["project_id"], node_id=vm["node_id"]))
# assert mock.called # assert mock.called
# assert response.status == 204 # assert response.status == 204
# #
# #
# def test_dynamips_vm_resume(compute_api, vm): # def test_dynamips_vm_resume(compute_api, vm):
# with asyncio_patch("gns3server.compute.dynamips.nodes.router.Router.resume", return_value=True) as mock: # with asyncio_patch("gns3server.compute.dynamips.nodes.router.Router.resume", return_value=True) as mock:
# response = compute_api.post("/projects/{project_id}/dynamips/nodes/{node_id}/resume".format(project_id=vm["project_id"], node_id=vm["node_id"])) # response = compute_api.post("/projects/{project_id}/dynamips/nodes/{node_id}/resume".format(project_id=vm["project_id"], node_id=vm["node_id"]))
# assert mock.called # assert mock.called
# assert response.status == 204 # assert response.status == 204
# def test_vbox_nio_create_udp(compute_api, vm): # def test_vbox_nio_create_udp(compute_api, vm):
# #
# with asyncio_patch('gns3server.compute.virtualbox.virtualbox_vm.VirtualBoxVM.adapter_add_nio_binding') as mock: # with asyncio_patch('gns3server.compute.virtualbox.virtualbox_vm.VirtualBoxVM.adapter_add_nio_binding') as mock:
# response = compute_api.post("/projects/{project_id}/virtualbox/nodes/{node_id}/adapters/0/nio".format(project_id=vm["project_id"], # response = compute_api.post("/projects/{project_id}/virtualbox/nodes/{node_id}/adapters/0/nio".format(project_id=vm["project_id"],
# node_id=vm["node_id"]), {"type": "nio_udp", # node_id=vm["node_id"]), {"type": "nio_udp",
# "lport": 4242, # "lport": 4242,
# "rport": 4343, # "rport": 4343,
# "rhost": "127.0.0.1"}, # "rhost": "127.0.0.1"},
# example=True) # example=True)
# #
# assert mock.called # assert mock.called
# args, kwgars = mock.call_args # args, kwgars = mock.call_args
# assert args[0] == 0 # assert args[0] == 0
# #
# assert response.status == 201 # assert response.status == 201
# assert response.route == "/projects/{project_id}/virtualbox/nodes/{node_id}/adapters/{adapter_id:\d+}/nio" # assert response.route == "/projects/{project_id}/virtualbox/nodes/{node_id}/adapters/{adapter_id:\d+}/nio"
# assert response.json["type"] == "nio_udp" # assert response.json["type"] == "nio_udp"
# #
# #
# def test_vbox_delete_nio(compute_api, vm): # def test_vbox_delete_nio(compute_api, vm):
# #
# with asyncio_patch('gns3server.compute.virtualbox.virtualbox_vm.VirtualBoxVM.adapter_remove_nio_binding') as mock: # with asyncio_patch('gns3server.compute.virtualbox.virtualbox_vm.VirtualBoxVM.adapter_remove_nio_binding') as mock:
# response = compute_api.delete("/projects/{project_id}/virtualbox/nodes/{node_id}/adapters/0/nio".format(project_id=vm["project_id"], node_id=vm["node_id"]), example=True) # response = compute_api.delete("/projects/{project_id}/virtualbox/nodes/{node_id}/adapters/0/nio".format(project_id=vm["project_id"], node_id=vm["node_id"]), example=True)
# #
# assert mock.called # assert mock.called
# args, kwgars = mock.call_args # args, kwgars = mock.call_args
# assert args[0] == 0 # assert args[0] == 0
# #
# assert response.status == 204 # assert response.status == 204
# assert response.route == "/projects/{project_id}/virtualbox/nodes/{node_id}/adapters/{adapter_id:\d+}/nio" # assert response.route == "/projects/{project_id}/virtualbox/nodes/{node_id}/adapters/{adapter_id:\d+}/nio"
# #
# #
# def test_vbox_update(compute_api, vm, free_console_port): # def test_vbox_update(compute_api, vm, free_console_port):
# response = compute_api.put("/projects/{project_id}/virtualbox/nodes/{node_id}".format(project_id=vm["project_id"], node_id=vm["node_id"]), {"name": "test", # response = compute_api.put("/projects/{project_id}/virtualbox/nodes/{node_id}".format(project_id=vm["project_id"], node_id=vm["node_id"]), {"name": "test",
# "console": free_console_port}) # "console": free_console_port})
# assert response.status == 200 # assert response.status == 200
# assert response.json["name"] == "test" # assert response.json["name"] == "test"
# assert response.json["console"] == free_console_port # assert response.json["console"] == free_console_port
@pytest.fixture @pytest.fixture
def fake_image(tmpdir) -> str: def fake_image(self, tmpdir) -> str:
"""Create a fake Dynamips image on disk""" """Create a fake Dynamips image on disk"""
path = str(tmpdir / "7200.bin") path = str(tmpdir / "7200.bin")
with open(path, "wb+") as f: with open(path, "wb+") as f:
f.write(b'\x7fELF\x01\x02\x01') f.write(b'\x7fELF\x01\x02\x01')
os.chmod(path, stat.S_IREAD) os.chmod(path, stat.S_IREAD)
return path return path
@pytest.fixture @pytest.fixture
def fake_file(tmpdir) -> str: def fake_file(self, tmpdir) -> str:
"""Create a fake file disk""" """Create a fake file disk"""
path = str(tmpdir / "7200.txt") path = str(tmpdir / "7200.txt")
with open(path, "w+") as f: with open(path, "w+") as f:
f.write('1') f.write('1')
os.chmod(path, stat.S_IREAD) os.chmod(path, stat.S_IREAD)
return path return path
async def test_images(app: FastAPI, compute_client: AsyncClient, tmpdir, fake_image: str, fake_file: str) -> None: async def test_images(
self, app: FastAPI,
compute_client: AsyncClient,
tmpdir, fake_image: str,
fake_file: str
) -> None:
with patch("gns3server.utils.images.default_images_directory", return_value=str(tmpdir)): with patch("gns3server.utils.images.default_images_directory", return_value=str(tmpdir)):
response = await compute_client.get(app.url_path_for("compute:get_dynamips_images")) response = await compute_client.get(app.url_path_for("compute:get_dynamips_images"))
assert response.status_code == status.HTTP_200_OK assert response.status_code == status.HTTP_200_OK
assert response.json() == [{"filename": "7200.bin", assert response.json() == [{"filename": "7200.bin",
"path": "7200.bin", "path": "7200.bin",
"filesize": 7, "filesize": 7,
"md5sum": "b0d5aa897d937aced5a6b1046e8f7e2e"}] "md5sum": "b0d5aa897d937aced5a6b1046e8f7e2e"}]
async def test_upload_image(app: FastAPI, compute_client: AsyncClient, images_dir: str) -> None: async def test_upload_image(self, app: FastAPI, compute_client: AsyncClient, images_dir: str) -> None:
response = await compute_client.post(app.url_path_for("compute:upload_dynamips_image", filename="test2"), content=b"TEST") response = await compute_client.post(app.url_path_for("compute:upload_dynamips_image", filename="test2"), content=b"TEST")
assert response.status_code == status.HTTP_204_NO_CONTENT assert response.status_code == status.HTTP_204_NO_CONTENT
with open(os.path.join(images_dir, "IOS", "test2")) as f: with open(os.path.join(images_dir, "IOS", "test2")) as f:
assert f.read() == "TEST" assert f.read() == "TEST"
with open(os.path.join(images_dir, "IOS", "test2.md5sum")) as f: with open(os.path.join(images_dir, "IOS", "test2.md5sum")) as f:
checksum = f.read() checksum = f.read()
assert checksum == "033bd94b1168d7e4f0d644c3c95e35bf" assert checksum == "033bd94b1168d7e4f0d644c3c95e35bf"
async def test_upload_image_forbidden_location(app: FastAPI, compute_client: AsyncClient) -> None: async def test_upload_image_forbidden_location(self, app: FastAPI, compute_client: AsyncClient) -> None:
file_path = "%2e%2e/hello" file_path = "%2e%2e/hello"
response = await compute_client.post(app.url_path_for("compute:upload_dynamips_image", filename=file_path), content=b"TEST") response = await compute_client.post(app.url_path_for("compute:upload_dynamips_image", filename=file_path), content=b"TEST")
assert response.status_code == status.HTTP_403_FORBIDDEN assert response.status_code == status.HTTP_403_FORBIDDEN
async def test_download_image(app: FastAPI, compute_client: AsyncClient, images_dir: str) -> None: async def test_download_image(self, app: FastAPI, compute_client: AsyncClient, images_dir: str) -> None:
response = await compute_client.post(app.url_path_for("compute:upload_dynamips_image", filename="test3"), content=b"TEST") response = await compute_client.post(app.url_path_for("compute:upload_dynamips_image", filename="test3"), content=b"TEST")
assert response.status_code == status.HTTP_204_NO_CONTENT assert response.status_code == status.HTTP_204_NO_CONTENT
response = await compute_client.get(app.url_path_for("compute:download_dynamips_image", filename="test3")) response = await compute_client.get(app.url_path_for("compute:download_dynamips_image", filename="test3"))
assert response.status_code == status.HTTP_200_OK assert response.status_code == status.HTTP_200_OK
async def test_download_image_forbidden(app: FastAPI, compute_client: AsyncClient, tmpdir) -> None: async def test_download_image_forbidden(self, app: FastAPI, compute_client: AsyncClient, tmpdir) -> None:
file_path = "foo/%2e%2e/%2e%2e/%2e%2e/%2e%2e/%2e%2e/%2e%2e/etc/passwd" file_path = "foo/%2e%2e/%2e%2e/%2e%2e/%2e%2e/%2e%2e/%2e%2e/etc/passwd"
response = await compute_client.get(app.url_path_for("compute:download_dynamips_image", filename=file_path)) response = await compute_client.get(app.url_path_for("compute:download_dynamips_image", filename=file_path))
assert response.status_code == status.HTTP_403_FORBIDDEN assert response.status_code == status.HTTP_403_FORBIDDEN
@pytest.mark.skipif(os.getuid() == 0, reason="Root can delete any image") @pytest.mark.skipif(os.getuid() == 0, reason="Root can delete any image")
async def test_upload_image_permission_denied(app: FastAPI, compute_client: AsyncClient, images_dir: str) -> None: async def test_upload_image_permission_denied(
self, app: FastAPI,
compute_client: AsyncClient,
images_dir: str
) -> None:
os.makedirs(os.path.join(images_dir, "IOS"), exist_ok=True) os.makedirs(os.path.join(images_dir, "IOS"), exist_ok=True)
with open(os.path.join(images_dir, "IOS", "test2.tmp"), "w+") as f: with open(os.path.join(images_dir, "IOS", "test2.tmp"), "w+") as f:
f.write("") f.write("")
os.chmod(os.path.join(images_dir, "IOS", "test2.tmp"), 0) os.chmod(os.path.join(images_dir, "IOS", "test2.tmp"), 0)
response = await compute_client.post(app.url_path_for("compute:upload_dynamips_image", filename="test2"), content=b"TEST") response = await compute_client.post(app.url_path_for("compute:upload_dynamips_image", filename="test2"), content=b"TEST")
assert response.status_code == status.HTTP_409_CONFLICT assert response.status_code == status.HTTP_409_CONFLICT

View File

@ -28,427 +28,474 @@ from gns3server.compute.project import Project
pytestmark = pytest.mark.asyncio pytestmark = pytest.mark.asyncio
@pytest_asyncio.fixture class TestEthernetSwitchNodesRoutes:
async def ethernet_switch(app: FastAPI, compute_client: AsyncClient, compute_project: Project) -> dict:
params = {"name": "Ethernet Switch"} @pytest_asyncio.fixture
with asyncio_patch("gns3server.compute.dynamips.nodes.ethernet_switch.EthernetSwitch.create") as mock: async def ethernet_switch(self, app: FastAPI, compute_client: AsyncClient, compute_project: Project) -> dict:
response = await compute_client.post(
app.url_path_for("compute:create_ethernet_switch", project_id=compute_project.id), params = {"name": "Ethernet Switch"}
json=params with asyncio_patch("gns3server.compute.dynamips.nodes.ethernet_switch.EthernetSwitch.create") as mock:
response = await compute_client.post(
app.url_path_for("compute:create_ethernet_switch", project_id=compute_project.id),
json=params
)
assert mock.called
assert response.status_code == status.HTTP_201_CREATED
json_response = response.json()
node = compute_project.get_node(json_response["node_id"])
node._hypervisor = AsyncioMagicMock()
node._hypervisor.send = AsyncioMagicMock()
node._hypervisor.version = "0.2.16"
return json_response
async def test_ethernet_switch_create(
self, app: FastAPI,
compute_client: AsyncClient,
compute_project: Project
) -> None:
params = {"name": "Ethernet Switch 1"}
with asyncio_patch("gns3server.compute.dynamips.nodes.ethernet_switch.EthernetSwitch.create") as mock:
response = await compute_client.post(
app.url_path_for("compute:create_ethernet_switch", project_id=compute_project.id),
json=params
)
assert mock.called
assert response.status_code == status.HTTP_201_CREATED
assert response.json()["name"] == "Ethernet Switch 1"
assert response.json()["project_id"] == compute_project.id
async def test_ethernet_switch_get(
self, app: FastAPI,
compute_client: AsyncClient,
compute_project: Project,
ethernet_switch: dict
) -> None:
response = await compute_client.get(
app.url_path_for(
"compute:get_ethernet_switch",
project_id=ethernet_switch["project_id"],
node_id=ethernet_switch["node_id"]
)
) )
assert mock.called assert response.status_code == status.HTTP_200_OK
assert response.status_code == status.HTTP_201_CREATED assert response.json()["name"] == "Ethernet Switch"
json_response = response.json()
node = compute_project.get_node(json_response["node_id"])
node._hypervisor = AsyncioMagicMock()
node._hypervisor.send = AsyncioMagicMock()
node._hypervisor.version = "0.2.16"
return json_response
async def test_ethernet_switch_create(app: FastAPI, compute_client: AsyncClient, compute_project: Project) -> None:
params = {"name": "Ethernet Switch 1"}
with asyncio_patch("gns3server.compute.dynamips.nodes.ethernet_switch.EthernetSwitch.create") as mock:
response = await compute_client.post(
app.url_path_for("compute:create_ethernet_switch", project_id=compute_project.id),
json=params
)
assert mock.called
assert response.status_code == status.HTTP_201_CREATED
assert response.json()["name"] == "Ethernet Switch 1"
assert response.json()["project_id"] == compute_project.id assert response.json()["project_id"] == compute_project.id
assert response.json()["status"] == "started"
async def test_ethernet_switch_get(app: FastAPI, compute_client: AsyncClient, compute_project: Project, ethernet_switch: dict) -> None: async def test_ethernet_switch_duplicate(
self,
app: FastAPI,
compute_client: AsyncClient,
compute_project: Project,
ethernet_switch: dict
) -> None:
response = await compute_client.get( # create destination switch first
app.url_path_for( params = {"name": "Ethernet Switch 2"}
"compute:get_ethernet_switch", with asyncio_patch("gns3server.compute.dynamips.nodes.ethernet_switch.EthernetSwitch.create") as mock:
project_id=ethernet_switch["project_id"], response = await compute_client.post(
node_id=ethernet_switch["node_id"] app.url_path_for(
) "compute:create_ethernet_switch",
) project_id=compute_project.id),
assert response.status_code == status.HTTP_200_OK json=params
assert response.json()["name"] == "Ethernet Switch" )
assert response.json()["project_id"] == compute_project.id assert mock.called
assert response.json()["status"] == "started" assert response.status_code == status.HTTP_201_CREATED
params = {"destination_node_id": response.json()["node_id"]}
async def test_ethernet_switch_duplicate(
app: FastAPI,
compute_client: AsyncClient,
compute_project: Project,
ethernet_switch: dict
) -> None:
# create destination switch first
params = {"name": "Ethernet Switch 2"}
with asyncio_patch("gns3server.compute.dynamips.nodes.ethernet_switch.EthernetSwitch.create") as mock:
response = await compute_client.post( response = await compute_client.post(
app.url_path_for( app.url_path_for(
"compute:create_ethernet_switch", "compute:duplicate_ethernet_switch",
project_id=compute_project.id), project_id=ethernet_switch["project_id"],
json=params node_id=ethernet_switch["node_id"]), json=params
) )
assert mock.called
assert response.status_code == status.HTTP_201_CREATED assert response.status_code == status.HTTP_201_CREATED
params = {"destination_node_id": response.json()["node_id"]}
response = await compute_client.post( async def test_ethernet_switch_update(
app.url_path_for( self,
"compute:duplicate_ethernet_switch", app: FastAPI,
project_id=ethernet_switch["project_id"], compute_client: AsyncClient,
node_id=ethernet_switch["node_id"]), json=params compute_project: Project,
ethernet_switch: dict
) -> None:
params = {
"name": "test",
"console_type": "telnet"
}
response = await compute_client.put(
app.url_path_for(
"compute:update_ethernet_switch",
project_id=ethernet_switch["project_id"],
node_id=ethernet_switch["node_id"]),
json=params
)
assert response.status_code == status.HTTP_200_OK
assert response.json()["name"] == "test"
node = compute_project.get_node(ethernet_switch["node_id"])
node._hypervisor.send.assert_called_with("ethsw rename \"Ethernet Switch\" \"test\"")
async def test_ethernet_switch_update_ports(
self,
app: FastAPI,
compute_client: AsyncClient,
compute_project: Project,
ethernet_switch: dict
) -> None:
port_params = {
"ports_mapping": [
{
"name": "Ethernet0",
"port_number": 0,
"type": "qinq",
"vlan": 1
},
{
"name": "Ethernet1",
"port_number": 1,
"type": "qinq",
"vlan": 2,
"ethertype": "0x88A8"
},
{
"name": "Ethernet2",
"port_number": 2,
"type": "dot1q",
"vlan": 3,
},
{
"name": "Ethernet3",
"port_number": 3,
"type": "access",
"vlan": 4,
}
],
}
response = await compute_client.put(
app.url_path_for(
"compute:update_ethernet_switch",
project_id=ethernet_switch["project_id"],
node_id=ethernet_switch["node_id"]),
json=port_params
)
assert response.status_code == status.HTTP_200_OK
nio_params = {
"type": "nio_udp",
"lport": 4242,
"rport": 4343,
"rhost": "127.0.0.1"
}
for port_mapping in port_params["ports_mapping"]:
port_number = port_mapping["port_number"]
vlan = port_mapping["vlan"]
port_type = port_mapping["type"]
ethertype = port_mapping.get("ethertype", "")
url = app.url_path_for(
"compute:create_ethernet_switch_nio",
project_id=ethernet_switch["project_id"],
node_id=ethernet_switch["node_id"],
adapter_number="0",
port_number=f"{port_number}"
)
await compute_client.post(url, json=nio_params)
node = compute_project.get_node(ethernet_switch["node_id"])
nio = node.get_nio(port_number)
calls = [
call.send(f'nio create_udp {nio.name} 4242 127.0.0.1 4343'),
call.send(f'ethsw add_nio "Ethernet Switch" {nio.name}'),
call.send(f'ethsw set_{port_type}_port "Ethernet Switch" {nio.name} {vlan} {ethertype}'.strip())
]
node._hypervisor.send.assert_has_calls(calls)
node._hypervisor.send.reset_mock()
@pytest.mark.parametrize(
"ports_settings",
(
(
{
"name": "Ethernet0",
"port_number": 0,
"type": "dot42q", # invalid port type
"vlan": 1,
}
),
(
{
"name": "Ethernet0",
"port_number": 0,
"type": "access", # missing vlan field
}
),
(
{
"name": "Ethernet0",
"port_number": 0,
"type": "dot1q",
"vlan": 1,
"ethertype": "0x88A8" # EtherType is only for QinQ
}
),
(
{
"name": "Ethernet0",
"port_number": 0,
"type": "qinq",
"vlan": 1,
"ethertype": "0x4242" # not a valid EtherType
}
),
(
{
"name": "Ethernet0",
"port_number": 0,
"type": "access",
"vlan": 0, # minimum vlan number is 1
}
),
(
{
"name": "Ethernet0",
"port_number": 0,
"type": "access",
"vlan": 4242, # maximum vlan number is 4094
}
),
)
) )
assert response.status_code == status.HTTP_201_CREATED async def test_ethernet_switch_update_ports_invalid(
self,
app: FastAPI,
compute_client: AsyncClient,
ethernet_switch: dict,
ports_settings: dict,
) -> None:
port_params = {
"ports_mapping": [ports_settings]
}
response = await compute_client.put(
app.url_path_for(
"compute:update_ethernet_switch",
project_id=ethernet_switch["project_id"],
node_id=ethernet_switch["node_id"]),
json=port_params
)
assert response.status_code == status.HTTP_422_UNPROCESSABLE_ENTITY
async def test_ethernet_switch_update( async def test_ethernet_switch_delete(
app: FastAPI, self, app: FastAPI,
compute_client: AsyncClient, compute_client: AsyncClient,
compute_project: Project, ethernet_switch: dict
ethernet_switch: dict ) -> None:
) -> None:
params = { response = await compute_client.delete(
"name": "test", app.url_path_for(
"console_type": "telnet" "compute:delete_ethernet_switch",
} project_id=ethernet_switch["project_id"],
node_id=ethernet_switch["node_id"]
response = await compute_client.put( )
app.url_path_for( )
"compute:update_ethernet_switch", assert response.status_code == status.HTTP_204_NO_CONTENT
project_id=ethernet_switch["project_id"],
node_id=ethernet_switch["node_id"]),
json=params
)
assert response.status_code == status.HTTP_200_OK
assert response.json()["name"] == "test"
node = compute_project.get_node(ethernet_switch["node_id"])
node._hypervisor.send.assert_called_with("ethsw rename \"Ethernet Switch\" \"test\"")
async def test_ethernet_switch_update_ports( async def test_ethernet_switch_start(
app: FastAPI, self, app: FastAPI,
compute_client: AsyncClient, compute_client: AsyncClient,
compute_project: Project, ethernet_switch: dict
ethernet_switch: dict ) -> None:
) -> None:
port_params = { response = await compute_client.post(
"ports_mapping": [ app.url_path_for(
{ "compute:start_ethernet_switch",
"name": "Ethernet0", project_id=ethernet_switch["project_id"],
"port_number": 0, node_id=ethernet_switch["node_id"])
"type": "qinq", )
"vlan": 1 assert response.status_code == status.HTTP_204_NO_CONTENT
},
{
"name": "Ethernet1",
"port_number": 1,
"type": "qinq",
"vlan": 2,
"ethertype": "0x88A8"
},
{
"name": "Ethernet2",
"port_number": 2,
"type": "dot1q",
"vlan": 3,
},
{
"name": "Ethernet3",
"port_number": 3,
"type": "access",
"vlan": 4,
}
],
}
response = await compute_client.put(
app.url_path_for(
"compute:update_ethernet_switch",
project_id=ethernet_switch["project_id"],
node_id=ethernet_switch["node_id"]),
json=port_params
)
assert response.status_code == status.HTTP_200_OK
nio_params = { async def test_ethernet_switch_stop(
"type": "nio_udp", self, app: FastAPI,
"lport": 4242, compute_client: AsyncClient,
"rport": 4343, ethernet_switch: dict
"rhost": "127.0.0.1" ) -> None:
}
response = await compute_client.post(
app.url_path_for(
"compute:stop_ethernet_switch",
project_id=ethernet_switch["project_id"],
node_id=ethernet_switch["node_id"])
)
assert response.status_code == status.HTTP_204_NO_CONTENT
async def test_ethernet_switch_suspend(
self, app: FastAPI,
compute_client: AsyncClient,
ethernet_switch: dict
) -> None:
response = await compute_client.post(
app.url_path_for(
"compute:suspend_ethernet_switch",
project_id=ethernet_switch["project_id"],
node_id=ethernet_switch["node_id"])
)
assert response.status_code == status.HTTP_204_NO_CONTENT
async def test_ethernet_switch_reload(
self, app: FastAPI,
compute_client: AsyncClient,
ethernet_switch: dict
) -> None:
response = await compute_client.post(
app.url_path_for(
"compute:reload_ethernet_switch",
project_id=ethernet_switch["project_id"],
node_id=ethernet_switch["node_id"])
)
assert response.status_code == status.HTTP_204_NO_CONTENT
async def test_ethernet_switch_create_udp(
self,
app: FastAPI,
compute_client: AsyncClient,
compute_project: Project,
ethernet_switch: dict
) -> None:
params = {
"type": "nio_udp",
"lport": 4242,
"rport": 4343,
"rhost": "127.0.0.1"
}
for port_mapping in port_params["ports_mapping"]:
port_number = port_mapping["port_number"]
vlan = port_mapping["vlan"]
port_type = port_mapping["type"]
ethertype = port_mapping.get("ethertype", "")
url = app.url_path_for( url = app.url_path_for(
"compute:create_ethernet_switch_nio", "compute:create_ethernet_switch_nio",
project_id=ethernet_switch["project_id"], project_id=ethernet_switch["project_id"],
node_id=ethernet_switch["node_id"], node_id=ethernet_switch["node_id"],
adapter_number="0", adapter_number="0",
port_number=f"{port_number}" port_number="0"
) )
await compute_client.post(url, json=nio_params) response = await compute_client.post(url, json=params)
assert response.status_code == status.HTTP_201_CREATED
assert response.json()["type"] == "nio_udp"
node = compute_project.get_node(ethernet_switch["node_id"]) node = compute_project.get_node(ethernet_switch["node_id"])
nio = node.get_nio(port_number) nio = node.get_nio(0)
calls = [ calls = [
call.send(f'nio create_udp {nio.name} 4242 127.0.0.1 4343'), call.send(f'nio create_udp {nio.name} 4242 127.0.0.1 4343'),
call.send(f'ethsw add_nio "Ethernet Switch" {nio.name}'), call.send(f'ethsw add_nio "Ethernet Switch" {nio.name}'),
call.send(f'ethsw set_{port_type}_port "Ethernet Switch" {nio.name} {vlan} {ethertype}'.strip()) call.send(f'ethsw set_access_port "Ethernet Switch" {nio.name} 1')
] ]
node._hypervisor.send.assert_has_calls(calls) node._hypervisor.send.assert_has_calls(calls)
node._hypervisor.send.reset_mock()
@pytest.mark.parametrize( async def test_ethernet_switch_delete_nio(
"ports_settings", self,
( app: FastAPI,
( compute_client: AsyncClient,
{ compute_project: Project,
"name": "Ethernet0", ethernet_switch: dict
"port_number": 0, ) -> None:
"type": "dot42q", # invalid port type
"vlan": 1,
}
),
(
{
"name": "Ethernet0",
"port_number": 0,
"type": "access", # missing vlan field
}
),
(
{
"name": "Ethernet0",
"port_number": 0,
"type": "dot1q",
"vlan": 1,
"ethertype": "0x88A8" # EtherType is only for QinQ
}
),
(
{
"name": "Ethernet0",
"port_number": 0,
"type": "qinq",
"vlan": 1,
"ethertype": "0x4242" # not a valid EtherType
}
),
(
{
"name": "Ethernet0",
"port_number": 0,
"type": "access",
"vlan": 0, # minimum vlan number is 1
}
),
(
{
"name": "Ethernet0",
"port_number": 0,
"type": "access",
"vlan": 4242, # maximum vlan number is 4094
}
),
)
)
async def test_ethernet_switch_update_ports_invalid(
app: FastAPI,
compute_client: AsyncClient,
ethernet_switch: dict,
ports_settings: dict,
) -> None:
port_params = { params = {
"ports_mapping": [ports_settings] "type": "nio_udp",
} "lport": 4242,
"rport": 4343,
"rhost": "127.0.0.1"
}
response = await compute_client.put( url = app.url_path_for(
app.url_path_for( "compute:create_ethernet_switch_nio",
"compute:update_ethernet_switch",
project_id=ethernet_switch["project_id"], project_id=ethernet_switch["project_id"],
node_id=ethernet_switch["node_id"]), node_id=ethernet_switch["node_id"],
json=port_params adapter_number="0",
) port_number="0"
assert response.status_code == status.HTTP_422_UNPROCESSABLE_ENTITY
async def test_ethernet_switch_delete(app: FastAPI, compute_client: AsyncClient, ethernet_switch: dict) -> None:
response = await compute_client.delete(
app.url_path_for(
"compute:delete_ethernet_switch",
project_id=ethernet_switch["project_id"],
node_id=ethernet_switch["node_id"]
) )
) await compute_client.post(url, json=params)
assert response.status_code == status.HTTP_204_NO_CONTENT
node = compute_project.get_node(ethernet_switch["node_id"])
node._hypervisor.send.reset_mock()
nio = node.get_nio(0)
async def test_ethernet_switch_start(app: FastAPI, compute_client: AsyncClient, ethernet_switch: dict) -> None: url = app.url_path_for(
"compute:delete_ethernet_switch_nio",
response = await compute_client.post(
app.url_path_for(
"compute:start_ethernet_switch",
project_id=ethernet_switch["project_id"], project_id=ethernet_switch["project_id"],
node_id=ethernet_switch["node_id"]) node_id=ethernet_switch["node_id"],
) adapter_number="0",
assert response.status_code == status.HTTP_204_NO_CONTENT port_number="0"
)
response = await compute_client.delete(url)
async def test_ethernet_switch_stop(app: FastAPI, compute_client: AsyncClient, ethernet_switch: dict) -> None:
response = await compute_client.post(
app.url_path_for(
"compute:stop_ethernet_switch",
project_id=ethernet_switch["project_id"],
node_id=ethernet_switch["node_id"])
)
assert response.status_code == status.HTTP_204_NO_CONTENT
async def test_ethernet_switch_suspend(app: FastAPI, compute_client: AsyncClient, ethernet_switch: dict) -> None:
response = await compute_client.post(
app.url_path_for(
"compute:suspend_ethernet_switch",
project_id=ethernet_switch["project_id"],
node_id=ethernet_switch["node_id"])
)
assert response.status_code == status.HTTP_204_NO_CONTENT
async def test_ethernet_switch_reload(app: FastAPI, compute_client: AsyncClient, ethernet_switch: dict) -> None:
response = await compute_client.post(
app.url_path_for(
"compute:reload_ethernet_switch",
project_id=ethernet_switch["project_id"],
node_id=ethernet_switch["node_id"])
)
assert response.status_code == status.HTTP_204_NO_CONTENT
async def test_ethernet_switch_create_udp(
app: FastAPI,
compute_client: AsyncClient,
compute_project: Project,
ethernet_switch: dict
) -> None:
params = {
"type": "nio_udp",
"lport": 4242,
"rport": 4343,
"rhost": "127.0.0.1"
}
url = app.url_path_for(
"compute:create_ethernet_switch_nio",
project_id=ethernet_switch["project_id"],
node_id=ethernet_switch["node_id"],
adapter_number="0",
port_number="0"
)
response = await compute_client.post(url, json=params)
assert response.status_code == status.HTTP_201_CREATED
assert response.json()["type"] == "nio_udp"
node = compute_project.get_node(ethernet_switch["node_id"])
nio = node.get_nio(0)
calls = [
call.send(f'nio create_udp {nio.name} 4242 127.0.0.1 4343'),
call.send(f'ethsw add_nio "Ethernet Switch" {nio.name}'),
call.send(f'ethsw set_access_port "Ethernet Switch" {nio.name} 1')
]
node._hypervisor.send.assert_has_calls(calls)
async def test_ethernet_switch_delete_nio(
app: FastAPI,
compute_client: AsyncClient,
compute_project: Project,
ethernet_switch: dict
) -> None:
params = {
"type": "nio_udp",
"lport": 4242,
"rport": 4343,
"rhost": "127.0.0.1"
}
url = app.url_path_for(
"compute:create_ethernet_switch_nio",
project_id=ethernet_switch["project_id"],
node_id=ethernet_switch["node_id"],
adapter_number="0",
port_number="0"
)
await compute_client.post(url, json=params)
node = compute_project.get_node(ethernet_switch["node_id"])
node._hypervisor.send.reset_mock()
nio = node.get_nio(0)
url = app.url_path_for(
"compute:delete_ethernet_switch_nio",
project_id=ethernet_switch["project_id"],
node_id=ethernet_switch["node_id"],
adapter_number="0",
port_number="0"
)
response = await compute_client.delete(url)
assert response.status_code == status.HTTP_204_NO_CONTENT
calls = [
call(f'ethsw remove_nio "Ethernet Switch" {nio.name}'),
call(f'nio delete {nio.name}')
]
node._hypervisor.send.assert_has_calls(calls)
async def test_ethernet_switch_start_capture(app: FastAPI, compute_client: AsyncClient, ethernet_switch: dict) -> None:
params = {
"capture_file_name": "test.pcap",
"data_link_type": "DLT_EN10MB"
}
url = app.url_path_for("compute:start_ethernet_switch_capture",
project_id=ethernet_switch["project_id"],
node_id=ethernet_switch["node_id"],
adapter_number="0",
port_number="0")
with asyncio_patch("gns3server.compute.dynamips.nodes.ethernet_switch.EthernetSwitch.start_capture") as mock:
response = await compute_client.post(url, json=params)
assert response.status_code == status.HTTP_200_OK
assert mock.called
assert "test.pcap" in response.json()["pcap_file_path"]
async def test_ethernet_switch_stop_capture(app: FastAPI, compute_client: AsyncClient, ethernet_switch: dict) -> None:
url = app.url_path_for("compute:stop_ethernet_switch_capture",
project_id=ethernet_switch["project_id"],
node_id=ethernet_switch["node_id"],
adapter_number="0",
port_number="0")
with asyncio_patch("gns3server.compute.dynamips.nodes.ethernet_switch.EthernetSwitch.stop_capture") as mock:
response = await compute_client.post(url)
assert response.status_code == status.HTTP_204_NO_CONTENT assert response.status_code == status.HTTP_204_NO_CONTENT
assert mock.called
calls = [
call(f'ethsw remove_nio "Ethernet Switch" {nio.name}'),
call(f'nio delete {nio.name}')
]
node._hypervisor.send.assert_has_calls(calls)
async def test_ethernet_switch_start_capture(
self,
app: FastAPI,
compute_client: AsyncClient,
ethernet_switch: dict
) -> None:
params = {
"capture_file_name": "test.pcap",
"data_link_type": "DLT_EN10MB"
}
url = app.url_path_for("compute:start_ethernet_switch_capture",
project_id=ethernet_switch["project_id"],
node_id=ethernet_switch["node_id"],
adapter_number="0",
port_number="0")
with asyncio_patch("gns3server.compute.dynamips.nodes.ethernet_switch.EthernetSwitch.start_capture") as mock:
response = await compute_client.post(url, json=params)
assert response.status_code == status.HTTP_200_OK
assert mock.called
assert "test.pcap" in response.json()["pcap_file_path"]
async def test_ethernet_switch_stop_capture(
self,
app: FastAPI,
compute_client: AsyncClient,
ethernet_switch: dict
) -> None:
url = app.url_path_for("compute:stop_ethernet_switch_capture",
project_id=ethernet_switch["project_id"],
node_id=ethernet_switch["node_id"],
adapter_number="0",
port_number="0")
with asyncio_patch("gns3server.compute.dynamips.nodes.ethernet_switch.EthernetSwitch.stop_capture") as mock:
response = await compute_client.post(url)
assert response.status_code == status.HTTP_204_NO_CONTENT
assert mock.called

View File

@ -28,452 +28,502 @@ from unittest.mock import patch
from gns3server.compute.project import Project from gns3server.compute.project import Project
pytestmark = [pytest.mark.asyncio] pytestmark = pytest.mark.asyncio
@pytest.fixture class TestIOUNodesRoutes:
def fake_iou_bin(images_dir) -> str:
"""Create a fake IOU image on disk"""
path = os.path.join(images_dir, "IOU", "iou.bin") @pytest.fixture
with open(path, "w+") as f: def fake_iou_bin(self, images_dir) -> str:
f.write('\x7fELF\x01\x01\x01') """Create a fake IOU image on disk"""
os.chmod(path, stat.S_IREAD | stat.S_IEXEC)
return path path = os.path.join(images_dir, "IOU", "iou.bin")
with open(path, "w+") as f:
f.write('\x7fELF\x01\x01\x01')
os.chmod(path, stat.S_IREAD | stat.S_IEXEC)
return path
@pytest.fixture @pytest.fixture
def base_params(tmpdir, fake_iou_bin) -> dict: def base_params(self, tmpdir, fake_iou_bin) -> dict:
"""Return standard parameters""" """Return standard parameters"""
return {"application_id": 42, "name": "IOU-TEST-1", "path": "iou.bin"} return {"application_id": 42, "name": "IOU-TEST-1", "path": "iou.bin"}
@pytest_asyncio.fixture @pytest_asyncio.fixture
async def vm(app: FastAPI, compute_client: AsyncClient, compute_project: Project, base_params: dict) -> dict: async def vm(
self,
app: FastAPI,
compute_client: AsyncClient,
compute_project: Project,
base_params: dict
) -> dict:
response = await compute_client.post(app.url_path_for("compute:create_iou_node", project_id=compute_project.id), json=base_params) response = await compute_client.post(app.url_path_for("compute:create_iou_node", project_id=compute_project.id), json=base_params)
assert response.status_code == status.HTTP_201_CREATED assert response.status_code == status.HTTP_201_CREATED
return response.json() return response.json()
def startup_config_file(compute_project: Project, vm: dict) -> str: def startup_config_file(self, compute_project: Project, vm: dict) -> str:
directory = os.path.join(compute_project.path, "project-files", "iou", vm["node_id"]) directory = os.path.join(compute_project.path, "project-files", "iou", vm["node_id"])
os.makedirs(directory, exist_ok=True) os.makedirs(directory, exist_ok=True)
return os.path.join(directory, "startup-config.cfg") return os.path.join(directory, "startup-config.cfg")
async def test_iou_create(app: FastAPI, compute_client: AsyncClient, compute_project: Project, base_params: dict) -> None: async def test_iou_create(
self,
app: FastAPI,
compute_client: AsyncClient,
compute_project: Project,
base_params: dict
) -> None:
response = await compute_client.post(app.url_path_for("compute:create_iou_node", project_id=compute_project.id), json=base_params) response = await compute_client.post(app.url_path_for("compute:create_iou_node", project_id=compute_project.id), json=base_params)
assert response.status_code == status.HTTP_201_CREATED assert response.status_code == status.HTTP_201_CREATED
assert response.json()["name"] == "IOU-TEST-1" assert response.json()["name"] == "IOU-TEST-1"
assert response.json()["project_id"] == compute_project.id assert response.json()["project_id"] == compute_project.id
assert response.json()["serial_adapters"] == 2 assert response.json()["serial_adapters"] == 2
assert response.json()["ethernet_adapters"] == 2 assert response.json()["ethernet_adapters"] == 2
assert response.json()["ram"] == 256 assert response.json()["ram"] == 256
assert response.json()["nvram"] == 128 assert response.json()["nvram"] == 128
assert response.json()["l1_keepalives"] is False assert response.json()["l1_keepalives"] is False
async def test_iou_create_with_params(app: FastAPI, async def test_iou_create_with_params(
compute_client: AsyncClient, self,
compute_project: Project, app: FastAPI,
base_params: dict) -> None: compute_client: AsyncClient,
compute_project: Project,
base_params: dict
) -> None:
params = base_params params = base_params
params["ram"] = 1024 params["ram"] = 1024
params["nvram"] = 512 params["nvram"] = 512
params["serial_adapters"] = 4 params["serial_adapters"] = 4
params["ethernet_adapters"] = 0 params["ethernet_adapters"] = 0
params["l1_keepalives"] = True params["l1_keepalives"] = True
params["startup_config_content"] = "hostname test" params["startup_config_content"] = "hostname test"
params["use_default_iou_values"] = False params["use_default_iou_values"] = False
response = await compute_client.post(app.url_path_for("compute:create_iou_node", project_id=compute_project.id), json=params) response = await compute_client.post(app.url_path_for("compute:create_iou_node", project_id=compute_project.id), json=params)
assert response.status_code == status.HTTP_201_CREATED assert response.status_code == status.HTTP_201_CREATED
assert response.json()["name"] == "IOU-TEST-1" assert response.json()["name"] == "IOU-TEST-1"
assert response.json()["project_id"] == compute_project.id assert response.json()["project_id"] == compute_project.id
assert response.json()["serial_adapters"] == 4 assert response.json()["serial_adapters"] == 4
assert response.json()["ethernet_adapters"] == 0 assert response.json()["ethernet_adapters"] == 0
assert response.json()["ram"] == 1024 assert response.json()["ram"] == 1024
assert response.json()["nvram"] == 512 assert response.json()["nvram"] == 512
assert response.json()["l1_keepalives"] is True assert response.json()["l1_keepalives"] is True
assert response.json()["use_default_iou_values"] is False assert response.json()["use_default_iou_values"] is False
with open(startup_config_file(compute_project, response.json())) as f: with open(self.startup_config_file(compute_project, response.json())) as f:
assert f.read() == "hostname test" assert f.read() == "hostname test"
@pytest.mark.parametrize( @pytest.mark.parametrize(
"name, status_code", "name, status_code",
( (
("valid-name", status.HTTP_201_CREATED), ("valid-name", status.HTTP_201_CREATED),
("42name", status.HTTP_409_CONFLICT), ("42name", status.HTTP_409_CONFLICT),
("name42", status.HTTP_201_CREATED), ("name42", status.HTTP_201_CREATED),
("-name", status.HTTP_409_CONFLICT), ("-name", status.HTTP_409_CONFLICT),
("name%-test", status.HTTP_409_CONFLICT), ("name%-test", status.HTTP_409_CONFLICT),
("x" * 63, status.HTTP_201_CREATED), ("x" * 63, status.HTTP_201_CREATED),
("x" * 64, status.HTTP_409_CONFLICT), ("x" * 64, status.HTTP_409_CONFLICT),
), ),
)
async def test_iou_create_with_invalid_name(
app: FastAPI,
compute_client: AsyncClient,
compute_project: Project,
base_params: dict,
name: str,
status_code: int
) -> None:
base_params["name"] = name
response = await compute_client.post(
app.url_path_for("compute:create_iou_node", project_id=compute_project.id), json=base_params
) )
assert response.status_code == status_code async def test_iou_create_with_invalid_name(
self,
app: FastAPI,
compute_client: AsyncClient,
compute_project: Project,
base_params: dict,
name: str,
status_code: int
) -> None:
base_params["name"] = name
response = await compute_client.post(
app.url_path_for("compute:create_iou_node", project_id=compute_project.id), json=base_params
)
assert response.status_code == status_code
async def test_iou_create_startup_config_already_exist( async def test_iou_create_startup_config_already_exist(
app: FastAPI, self,
compute_client: AsyncClient, app: FastAPI,
compute_project: Project, compute_client: AsyncClient,
base_params: dict) -> None: compute_project: Project,
"""We don't erase a startup-config if already exist at project creation""" base_params: dict) -> None:
"""We don't erase a startup-config if already exist at project creation"""
node_id = str(uuid.uuid4()) node_id = str(uuid.uuid4())
startup_config_file_path = startup_config_file(compute_project, {'node_id': node_id}) startup_config_file_path = self.startup_config_file(compute_project, {'node_id': node_id})
with open(startup_config_file_path, 'w+') as f: with open(startup_config_file_path, 'w+') as f:
f.write("echo hello") f.write("echo hello")
params = base_params params = base_params
params["node_id"] = node_id params["node_id"] = node_id
params["startup_config_content"] = "hostname test" params["startup_config_content"] = "hostname test"
response = await compute_client.post(app.url_path_for("compute:create_iou_node", project_id=compute_project.id), json=params) response = await compute_client.post(app.url_path_for("compute:create_iou_node", project_id=compute_project.id), json=params)
assert response.status_code == status.HTTP_201_CREATED assert response.status_code == status.HTTP_201_CREATED
with open(startup_config_file(compute_project, response.json())) as f: with open(self.startup_config_file(compute_project, response.json())) as f:
assert f.read() == "echo hello" assert f.read() == "echo hello"
async def test_iou_get(app: FastAPI, compute_client: AsyncClient, compute_project: Project, vm: dict) -> None: async def test_iou_get(
self,
app: FastAPI,
compute_client: AsyncClient,
compute_project: Project,
vm: dict
) -> None:
response = await compute_client.get(app.url_path_for("compute:get_iou_node", project_id=vm["project_id"], node_id=vm["node_id"])) response = await compute_client.get(app.url_path_for("compute:get_iou_node", project_id=vm["project_id"], node_id=vm["node_id"]))
assert response.status_code == status.HTTP_200_OK assert response.status_code == status.HTTP_200_OK
assert response.json()["name"] == "IOU-TEST-1" assert response.json()["name"] == "IOU-TEST-1"
assert response.json()["project_id"] == compute_project.id assert response.json()["project_id"] == compute_project.id
assert response.json()["serial_adapters"] == 2 assert response.json()["serial_adapters"] == 2
assert response.json()["ethernet_adapters"] == 2 assert response.json()["ethernet_adapters"] == 2
assert response.json()["ram"] == 256 assert response.json()["ram"] == 256
assert response.json()["nvram"] == 128 assert response.json()["nvram"] == 128
assert response.json()["l1_keepalives"] is False assert response.json()["l1_keepalives"] is False
async def test_iou_start(app: FastAPI, compute_client: AsyncClient, vm: dict) -> None: async def test_iou_start(self, app: FastAPI, compute_client: AsyncClient, vm: dict) -> None:
with asyncio_patch("gns3server.compute.iou.iou_vm.IOUVM.start", return_value=True) as mock: with asyncio_patch("gns3server.compute.iou.iou_vm.IOUVM.start", return_value=True) as mock:
response = await compute_client.post(app.url_path_for("compute:start_iou_node", response = await compute_client.post(app.url_path_for("compute:start_iou_node",
project_id=vm["project_id"], project_id=vm["project_id"],
node_id=vm["node_id"]), json={}) node_id=vm["node_id"]), json={})
assert mock.called assert mock.called
assert response.status_code == status.HTTP_204_NO_CONTENT assert response.status_code == status.HTTP_204_NO_CONTENT
async def test_iou_start_with_iourc(app: FastAPI, compute_client: AsyncClient, vm: dict) -> None: async def test_iou_start_with_iourc(self, app: FastAPI, compute_client: AsyncClient, vm: dict) -> None:
params = {"iourc_content": "test"} params = {"iourc_content": "test"}
with asyncio_patch("gns3server.compute.iou.iou_vm.IOUVM.start", return_value=True) as mock: with asyncio_patch("gns3server.compute.iou.iou_vm.IOUVM.start", return_value=True) as mock:
response = await compute_client.post(app.url_path_for("compute:start_iou_node", response = await compute_client.post(app.url_path_for("compute:start_iou_node",
project_id=vm["project_id"], project_id=vm["project_id"],
node_id=vm["node_id"]), json=params) node_id=vm["node_id"]), json=params)
assert mock.called assert mock.called
assert response.status_code == status.HTTP_204_NO_CONTENT assert response.status_code == status.HTTP_204_NO_CONTENT
async def test_iou_stop(app: FastAPI, compute_client: AsyncClient, vm: dict) -> None: async def test_iou_stop(self, app: FastAPI, compute_client: AsyncClient, vm: dict) -> None:
with asyncio_patch("gns3server.compute.iou.iou_vm.IOUVM.stop", return_value=True) as mock: with asyncio_patch("gns3server.compute.iou.iou_vm.IOUVM.stop", return_value=True) as mock:
response = await compute_client.post(app.url_path_for("compute:stop_iou_node", response = await compute_client.post(app.url_path_for("compute:stop_iou_node",
project_id=vm["project_id"], project_id=vm["project_id"],
node_id=vm["node_id"])) node_id=vm["node_id"]))
assert mock.called assert mock.called
assert response.status_code == status.HTTP_204_NO_CONTENT assert response.status_code == status.HTTP_204_NO_CONTENT
async def test_iou_reload(app: FastAPI, compute_client: AsyncClient, vm: dict) -> None: async def test_iou_reload(self, app: FastAPI, compute_client: AsyncClient, vm: dict) -> None:
with asyncio_patch("gns3server.compute.iou.iou_vm.IOUVM.reload", return_value=True) as mock: with asyncio_patch("gns3server.compute.iou.iou_vm.IOUVM.reload", return_value=True) as mock:
response = await compute_client.post(app.url_path_for("compute:reload_iou_node", response = await compute_client.post(app.url_path_for("compute:reload_iou_node",
project_id=vm["project_id"], project_id=vm["project_id"],
node_id=vm["node_id"])) node_id=vm["node_id"]))
assert mock.called assert mock.called
assert response.status_code == status.HTTP_204_NO_CONTENT assert response.status_code == status.HTTP_204_NO_CONTENT
async def test_iou_delete(app: FastAPI, compute_client: AsyncClient, vm: dict) -> None: async def test_iou_delete(self, app: FastAPI, compute_client: AsyncClient, vm: dict) -> None:
with asyncio_patch("gns3server.compute.iou.IOU.delete_node", return_value=True) as mock: with asyncio_patch("gns3server.compute.iou.IOU.delete_node", return_value=True) as mock:
response = await compute_client.delete(app.url_path_for("compute:delete_iou_node", response = await compute_client.delete(app.url_path_for("compute:delete_iou_node",
project_id=vm["project_id"], project_id=vm["project_id"],
node_id=vm["node_id"])) node_id=vm["node_id"]))
assert mock.called assert mock.called
assert response.status_code == status.HTTP_204_NO_CONTENT assert response.status_code == status.HTTP_204_NO_CONTENT
async def test_iou_update(app: FastAPI, compute_client: AsyncClient, vm: dict, free_console_port: int) -> None: async def test_iou_update(
self, app: FastAPI,
compute_client: AsyncClient,
vm: dict,
free_console_port: int
) -> None:
params = { params = {
"name": "test", "name": "test",
"console": free_console_port, "console": free_console_port,
"ram": 512, "ram": 512,
"nvram": 2048, "nvram": 2048,
"ethernet_adapters": 4, "ethernet_adapters": 4,
"serial_adapters": 0, "serial_adapters": 0,
"l1_keepalives": True, "l1_keepalives": True,
"use_default_iou_values": True, "use_default_iou_values": True,
} }
response = await compute_client.put(app.url_path_for("compute:update_iou_node", response = await compute_client.put(app.url_path_for("compute:update_iou_node",
project_id=vm["project_id"], project_id=vm["project_id"],
node_id=vm["node_id"]), json=params) node_id=vm["node_id"]), json=params)
assert response.status_code == status.HTTP_200_OK assert response.status_code == status.HTTP_200_OK
assert response.json()["name"] == "test" assert response.json()["name"] == "test"
assert response.json()["console"] == free_console_port assert response.json()["console"] == free_console_port
assert response.json()["ethernet_adapters"] == 4 assert response.json()["ethernet_adapters"] == 4
assert response.json()["serial_adapters"] == 0 assert response.json()["serial_adapters"] == 0
assert response.json()["ram"] == 512 assert response.json()["ram"] == 512
assert response.json()["nvram"] == 2048 assert response.json()["nvram"] == 2048
assert response.json()["l1_keepalives"] is True assert response.json()["l1_keepalives"] is True
assert response.json()["use_default_iou_values"] is True assert response.json()["use_default_iou_values"] is True
async def test_iou_nio_create_udp(app: FastAPI, compute_client: AsyncClient, vm: dict) -> None: async def test_iou_nio_create_udp(self, app: FastAPI, compute_client: AsyncClient, vm: dict) -> None:
params = {"type": "nio_udp", params = {"type": "nio_udp",
"lport": 4242, "lport": 4242,
"rport": 4343, "rport": 4343,
"rhost": "127.0.0.1"} "rhost": "127.0.0.1"}
url = app.url_path_for("compute:create_iou_node_nio", url = app.url_path_for("compute:create_iou_node_nio",
project_id=vm["project_id"], project_id=vm["project_id"],
node_id=vm["node_id"], node_id=vm["node_id"],
adapter_number="1", adapter_number="1",
port_number="0") port_number="0")
response = await compute_client.post(url, json=params)
assert response.status_code == status.HTTP_201_CREATED
assert response.json()["type"] == "nio_udp"
async def test_iou_nio_update_udp(app: FastAPI, compute_client: AsyncClient, vm: dict) -> None:
params = {"type": "nio_udp",
"lport": 4242,
"rport": 4343,
"rhost": "127.0.0.1"}
url = app.url_path_for("compute:create_iou_node_nio",
project_id=vm["project_id"],
node_id=vm["node_id"],
adapter_number="1",
port_number="0")
await compute_client.post(url, json=params)
params["filters"] = {}
url = app.url_path_for("compute:update_iou_node_nio",
project_id=vm["project_id"],
node_id=vm["node_id"],
adapter_number="1",
port_number="0")
response = await compute_client.put(url, json=params)
assert response.status_code == status.HTTP_201_CREATED
assert response.json()["type"] == "nio_udp"
async def test_iou_nio_create_ethernet(app: FastAPI, compute_client: AsyncClient, vm: dict, ethernet_device: str) -> None:
params = {
"type": "nio_ethernet",
"ethernet_device": ethernet_device
}
url = app.url_path_for("compute:create_iou_node_nio",
project_id=vm["project_id"],
node_id=vm["node_id"],
adapter_number="1",
port_number="0")
response = await compute_client.post(url, json=params)
assert response.status_code == status.HTTP_201_CREATED
assert response.json()["type"] == "nio_ethernet"
assert response.json()["ethernet_device"] == ethernet_device
async def test_iou_nio_create_ethernet_different_port(app: FastAPI,
compute_client: AsyncClient,
vm: dict,
ethernet_device: str) -> None:
params = {
"type": "nio_ethernet",
"ethernet_device": ethernet_device
}
url = app.url_path_for("compute:create_iou_node_nio",
project_id=vm["project_id"],
node_id=vm["node_id"],
adapter_number="0",
port_number="3")
response = await compute_client.post(url, json=params)
assert response.status_code == status.HTTP_201_CREATED
assert response.json()["type"] == "nio_ethernet"
assert response.json()["ethernet_device"] == ethernet_device
async def test_iou_nio_create_tap(app: FastAPI, compute_client: AsyncClient, vm: dict, ethernet_device: str) -> None:
params = {
"type": "nio_tap",
"tap_device": ethernet_device
}
url = app.url_path_for("compute:create_iou_node_nio",
project_id=vm["project_id"],
node_id=vm["node_id"],
adapter_number="1",
port_number="0")
with patch("gns3server.compute.base_manager.BaseManager.has_privileged_access", return_value=True):
response = await compute_client.post(url, json=params) response = await compute_client.post(url, json=params)
assert response.status_code == status.HTTP_201_CREATED assert response.status_code == status.HTTP_201_CREATED
assert response.json()["type"] == "nio_tap" assert response.json()["type"] == "nio_udp"
async def test_iou_delete_nio(app: FastAPI, compute_client: AsyncClient, vm: dict) -> None: async def test_iou_nio_update_udp(self, app: FastAPI, compute_client: AsyncClient, vm: dict) -> None:
params = { params = {"type": "nio_udp",
"type": "nio_udp", "lport": 4242,
"lport": 4242, "rport": 4343,
"rport": 4343, "rhost": "127.0.0.1"}
"rhost": "127.0.0.1"
}
url = app.url_path_for("compute:create_iou_node_nio", url = app.url_path_for("compute:create_iou_node_nio",
project_id=vm["project_id"], project_id=vm["project_id"],
node_id=vm["node_id"], node_id=vm["node_id"],
adapter_number="1", adapter_number="1",
port_number="0") port_number="0")
await compute_client.post(url, json=params) await compute_client.post(url, json=params)
params["filters"] = {}
url = app.url_path_for("compute:delete_iou_node_nio", url = app.url_path_for("compute:update_iou_node_nio",
project_id=vm["project_id"], project_id=vm["project_id"],
node_id=vm["node_id"], node_id=vm["node_id"],
adapter_number="1", adapter_number="1",
port_number="0") port_number="0")
response = await compute_client.put(url, json=params)
response = await compute_client.delete(url) assert response.status_code == status.HTTP_201_CREATED
assert response.status_code == status.HTTP_204_NO_CONTENT assert response.json()["type"] == "nio_udp"
async def test_iou_start_capture(app: FastAPI, compute_client: AsyncClient, vm: dict) -> None: async def test_iou_nio_create_ethernet(
self,
app: FastAPI,
compute_client: AsyncClient,
vm: dict,
ethernet_device: str
) -> None:
params = { params = {
"capture_file_name": "test.pcap", "type": "nio_ethernet",
"data_link_type": "DLT_EN10MB" "ethernet_device": ethernet_device
} }
url = app.url_path_for("compute:start_iou_node_capture", url = app.url_path_for("compute:create_iou_node_nio",
project_id=vm["project_id"], project_id=vm["project_id"],
node_id=vm["node_id"], node_id=vm["node_id"],
adapter_number="0", adapter_number="1",
port_number="0") port_number="0")
with patch("gns3server.compute.iou.iou_vm.IOUVM.is_running", return_value=True): response = await compute_client.post(url, json=params)
with asyncio_patch("gns3server.compute.iou.iou_vm.IOUVM.start_capture") as mock: assert response.status_code == status.HTTP_201_CREATED
assert response.json()["type"] == "nio_ethernet"
assert response.json()["ethernet_device"] == ethernet_device
async def test_iou_nio_create_ethernet_different_port(
self,
app: FastAPI,
compute_client: AsyncClient,
vm: dict,
ethernet_device: str
) -> None:
params = {
"type": "nio_ethernet",
"ethernet_device": ethernet_device
}
url = app.url_path_for("compute:create_iou_node_nio",
project_id=vm["project_id"],
node_id=vm["node_id"],
adapter_number="0",
port_number="3")
response = await compute_client.post(url, json=params)
assert response.status_code == status.HTTP_201_CREATED
assert response.json()["type"] == "nio_ethernet"
assert response.json()["ethernet_device"] == ethernet_device
async def test_iou_nio_create_tap(
self,
app: FastAPI,
compute_client: AsyncClient,
vm: dict,
ethernet_device: str
) -> None:
params = {
"type": "nio_tap",
"tap_device": ethernet_device
}
url = app.url_path_for("compute:create_iou_node_nio",
project_id=vm["project_id"],
node_id=vm["node_id"],
adapter_number="1",
port_number="0")
with patch("gns3server.compute.base_manager.BaseManager.has_privileged_access", return_value=True):
response = await compute_client.post(url, json=params) response = await compute_client.post(url, json=params)
assert response.status_code == status.HTTP_200_OK assert response.status_code == status.HTTP_201_CREATED
assert mock.called assert response.json()["type"] == "nio_tap"
assert "test.pcap" in response.json()["pcap_file_path"]
async def test_iou_stop_capture(app: FastAPI, compute_client: AsyncClient, vm: dict) -> None: async def test_iou_delete_nio(
self,
app: FastAPI,
compute_client: AsyncClient,
vm: dict
) -> None:
url = app.url_path_for("compute:stop_iou_node_capture", params = {
project_id=vm["project_id"], "type": "nio_udp",
node_id=vm["node_id"], "lport": 4242,
adapter_number="0", "rport": 4343,
port_number="0") "rhost": "127.0.0.1"
}
with patch("gns3server.compute.iou.iou_vm.IOUVM.is_running", return_value=True): url = app.url_path_for("compute:create_iou_node_nio",
with asyncio_patch("gns3server.compute.iou.iou_vm.IOUVM.stop_capture") as mock: project_id=vm["project_id"],
response = await compute_client.post(url) node_id=vm["node_id"],
assert response.status_code == status.HTTP_204_NO_CONTENT adapter_number="1",
assert mock.called port_number="0")
await compute_client.post(url, json=params)
# @pytest.mark.asyncio url = app.url_path_for("compute:delete_iou_node_nio",
# async def test_iou_pcap(compute_api, vm, compute_project): project_id=vm["project_id"],
# node_id=vm["node_id"],
# with asyncio_patch("gns3server.compute.iou.iou_vm.IOUVM.get_nio"): adapter_number="1",
# with asyncio_patch("gns3server.compute.iou.IOU.stream_pcap_file"): port_number="0")
# response = await compute_client.get("/projects/{project_id}/iou/nodes/{node_id}/adapters/0/ports/0/pcap".format(project_id=compute_project.id, node_id=vm["node_id"]), raw=True)
# assert response.status_code == status.HTTP_200_OK
response = await compute_client.delete(url)
async def test_images(app: FastAPI, compute_client: AsyncClient, fake_iou_bin: str) -> None:
response = await compute_client.get(app.url_path_for("compute:get_iou_images"))
assert response.status_code == status.HTTP_200_OK
assert response.json() == [{"filename": "iou.bin", "path": "iou.bin", "filesize": 7, "md5sum": "e573e8f5c93c6c00783f20c7a170aa6c"}]
async def test_upload_image(app: FastAPI, compute_client: AsyncClient, tmpdir) -> None:
with patch("gns3server.compute.IOU.get_images_directory", return_value=str(tmpdir)):
response = await compute_client.post(app.url_path_for("compute:upload_iou_image", filename="test2"), content=b"TEST")
assert response.status_code == status.HTTP_204_NO_CONTENT assert response.status_code == status.HTTP_204_NO_CONTENT
with open(str(tmpdir / "test2")) as f:
assert f.read() == "TEST"
with open(str(tmpdir / "test2.md5sum")) as f: async def test_iou_start_capture(self, app: FastAPI, compute_client: AsyncClient, vm: dict) -> None:
checksum = f.read()
assert checksum == "033bd94b1168d7e4f0d644c3c95e35bf" params = {
"capture_file_name": "test.pcap",
"data_link_type": "DLT_EN10MB"
}
url = app.url_path_for("compute:start_iou_node_capture",
project_id=vm["project_id"],
node_id=vm["node_id"],
adapter_number="0",
port_number="0")
with patch("gns3server.compute.iou.iou_vm.IOUVM.is_running", return_value=True):
with asyncio_patch("gns3server.compute.iou.iou_vm.IOUVM.start_capture") as mock:
response = await compute_client.post(url, json=params)
assert response.status_code == status.HTTP_200_OK
assert mock.called
assert "test.pcap" in response.json()["pcap_file_path"]
async def test_upload_image_forbidden_location(app: FastAPI, compute_client: AsyncClient) -> None: async def test_iou_stop_capture(self, app: FastAPI, compute_client: AsyncClient, vm: dict) -> None:
file_path = "%2e%2e/hello" url = app.url_path_for("compute:stop_iou_node_capture",
response = await compute_client.post(app.url_path_for("compute:upload_dynamips_image", filename=file_path), content=b"TEST") project_id=vm["project_id"],
assert response.status_code == status.HTTP_403_FORBIDDEN node_id=vm["node_id"],
adapter_number="0",
port_number="0")
with patch("gns3server.compute.iou.iou_vm.IOUVM.is_running", return_value=True):
with asyncio_patch("gns3server.compute.iou.iou_vm.IOUVM.stop_capture") as mock:
response = await compute_client.post(url)
assert response.status_code == status.HTTP_204_NO_CONTENT
assert mock.called
async def test_download_image(app: FastAPI, compute_client: AsyncClient, images_dir: str) -> None: # @pytest.mark.asyncio
# async def test_iou_pcap(compute_api, vm, compute_project):
response = await compute_client.post(app.url_path_for("compute:upload_dynamips_image", filename="test3"), content=b"TEST") #
assert response.status_code == status.HTTP_204_NO_CONTENT # with asyncio_patch("gns3server.compute.iou.iou_vm.IOUVM.get_nio"):
# with asyncio_patch("gns3server.compute.iou.IOU.stream_pcap_file"):
response = await compute_client.get(app.url_path_for("compute:download_dynamips_image", filename="test3")) # response = await compute_client.get("/projects/{project_id}/iou/nodes/{node_id}/adapters/0/ports/0/pcap".format(project_id=compute_project.id, node_id=vm["node_id"]), raw=True)
assert response.status_code == status.HTTP_200_OK # assert response.status_code == status.HTTP_200_OK
async def test_download_image_forbidden(app: FastAPI, compute_client: AsyncClient, tmpdir) -> None: async def test_images(self, app: FastAPI, compute_client: AsyncClient, fake_iou_bin: str) -> None:
file_path = "foo/%2e%2e/%2e%2e/%2e%2e/%2e%2e/%2e%2e/%2e%2e/etc/passwd" response = await compute_client.get(app.url_path_for("compute:get_iou_images"))
response = await compute_client.get(app.url_path_for("compute:download_iou_image", filename=file_path)) assert response.status_code == status.HTTP_200_OK
assert response.status_code == status.HTTP_403_FORBIDDEN assert response.json() == [{"filename": "iou.bin", "path": "iou.bin", "filesize": 7, "md5sum": "e573e8f5c93c6c00783f20c7a170aa6c"}]
async def test_iou_duplicate(app: FastAPI, compute_client: AsyncClient, vm: dict, base_params: dict) -> None: async def test_upload_image(self, app: FastAPI, compute_client: AsyncClient, tmpdir) -> None:
# create destination node first with patch("gns3server.compute.IOU.get_images_directory", return_value=str(tmpdir)):
response = await compute_client.post(app.url_path_for("compute:create_iou_node", project_id=vm["project_id"]), json=base_params) response = await compute_client.post(app.url_path_for("compute:upload_iou_image", filename="test2"), content=b"TEST")
assert response.status_code == status.HTTP_201_CREATED assert response.status_code == status.HTTP_204_NO_CONTENT
params = {"destination_node_id": response.json()["node_id"]} with open(str(tmpdir / "test2")) as f:
assert f.read() == "TEST"
response = await compute_client.post(app.url_path_for("compute:duplicate_iou_node", with open(str(tmpdir / "test2.md5sum")) as f:
project_id=vm["project_id"], checksum = f.read()
node_id=vm["node_id"]), json=params) assert checksum == "033bd94b1168d7e4f0d644c3c95e35bf"
assert response.status_code == status.HTTP_201_CREATED
async def test_upload_image_forbidden_location(self, app: FastAPI, compute_client: AsyncClient) -> None:
file_path = "%2e%2e/hello"
response = await compute_client.post(app.url_path_for("compute:upload_dynamips_image", filename=file_path), content=b"TEST")
assert response.status_code == status.HTTP_403_FORBIDDEN
async def test_download_image(self, app: FastAPI, compute_client: AsyncClient, images_dir: str) -> None:
response = await compute_client.post(app.url_path_for("compute:upload_dynamips_image", filename="test3"), content=b"TEST")
assert response.status_code == status.HTTP_204_NO_CONTENT
response = await compute_client.get(app.url_path_for("compute:download_dynamips_image", filename="test3"))
assert response.status_code == status.HTTP_200_OK
async def test_download_image_forbidden(self, app: FastAPI, compute_client: AsyncClient, tmpdir) -> None:
file_path = "foo/%2e%2e/%2e%2e/%2e%2e/%2e%2e/%2e%2e/%2e%2e/etc/passwd"
response = await compute_client.get(app.url_path_for("compute:download_iou_image", filename=file_path))
assert response.status_code == status.HTTP_403_FORBIDDEN
async def test_iou_duplicate(self, app: FastAPI, compute_client: AsyncClient, vm: dict, base_params: dict) -> None:
# create destination node first
response = await compute_client.post(app.url_path_for("compute:create_iou_node", project_id=vm["project_id"]), json=base_params)
assert response.status_code == status.HTTP_201_CREATED
params = {"destination_node_id": response.json()["node_id"]}
response = await compute_client.post(app.url_path_for("compute:duplicate_iou_node",
project_id=vm["project_id"],
node_id=vm["node_id"]), json=params)
assert response.status_code == status.HTTP_201_CREATED

View File

@ -27,167 +27,188 @@ from gns3server.compute.project import Project
pytestmark = pytest.mark.asyncio pytestmark = pytest.mark.asyncio
@pytest_asyncio.fixture(scope="function") class TestNATNodesRoutes:
async def vm(app: FastAPI, compute_client: AsyncClient, compute_project: Project, ubridge_path: str, on_gns3vm) -> dict:
with asyncio_patch("gns3server.compute.builtin.nodes.nat.Nat._start_ubridge"): @pytest_asyncio.fixture
response = await compute_client.post(app.url_path_for("compute:create_nat_node", project_id=compute_project.id), async def vm(
json={"name": "Nat 1"}) self,
assert response.status_code == status.HTTP_201_CREATED app: FastAPI,
return response.json() compute_client: AsyncClient,
compute_project: Project,
ubridge_path: str,
on_gns3vm
) -> dict:
with asyncio_patch("gns3server.compute.builtin.nodes.nat.Nat._start_ubridge"):
response = await compute_client.post(app.url_path_for("compute:create_nat_node", project_id=compute_project.id),
json={"name": "Nat 1"})
assert response.status_code == status.HTTP_201_CREATED
return response.json()
async def test_nat_create(app: FastAPI, compute_client: AsyncClient, compute_project: Project, on_gns3vm) -> None: async def test_nat_create(
self,
app: FastAPI,
compute_client: AsyncClient,
compute_project: Project,
on_gns3vm
) -> None:
with asyncio_patch("gns3server.compute.builtin.nodes.nat.Nat._start_ubridge"): with asyncio_patch("gns3server.compute.builtin.nodes.nat.Nat._start_ubridge"):
response = await compute_client.post(app.url_path_for("compute:create_nat_node", project_id=compute_project.id), response = await compute_client.post(app.url_path_for("compute:create_nat_node", project_id=compute_project.id),
json={"name": "Nat 1"}) json={"name": "Nat 1"})
assert response.status_code == status.HTTP_201_CREATED assert response.status_code == status.HTTP_201_CREATED
assert response.json()["name"] == "Nat 1" assert response.json()["name"] == "Nat 1"
assert response.json()["project_id"] == compute_project.id assert response.json()["project_id"] == compute_project.id
async def test_nat_get(app: FastAPI, compute_client: AsyncClient, compute_project: Project, vm: dict) -> None: async def test_nat_get(
self,
app: FastAPI,
compute_client: AsyncClient,
compute_project: Project,
vm: dict
) -> None:
response = await compute_client.get(app.url_path_for("compute:get_nat_node", project_id=vm["project_id"], node_id=vm["node_id"])) response = await compute_client.get(app.url_path_for("compute:get_nat_node", project_id=vm["project_id"], node_id=vm["node_id"]))
assert response.status_code == status.HTTP_200_OK
assert response.json()["name"] == "Nat 1"
assert response.json()["project_id"] == compute_project.id
assert response.json()["status"] == "started"
async def test_nat_nio_create_udp(app: FastAPI, compute_client: AsyncClient, vm: dict) -> None:
params = {
"type": "nio_udp",
"lport": 4242,
"rport": 4343,
"rhost": "127.0.0.1"
}
url = app.url_path_for("compute:create_nat_node_nio",
project_id=vm["project_id"],
node_id=vm["node_id"],
adapter_number="0",
port_number="0")
with asyncio_patch("gns3server.compute.builtin.nodes.nat.Nat.add_nio"):
response = await compute_client.post(url, json=params)
assert response.status_code == status.HTTP_201_CREATED
assert response.json()["type"] == "nio_udp"
async def test_nat_nio_update_udp(app: FastAPI, compute_client: AsyncClient, vm: dict) -> None:
params = {
"type": "nio_udp",
"lport": 4242,
"rport": 4343,
"rhost": "127.0.0.1"
}
url = app.url_path_for("compute:create_nat_node_nio",
project_id=vm["project_id"],
node_id=vm["node_id"],
adapter_number="0",
port_number="0")
await compute_client.post(url, json=params)
params["filters"] = {}
url = app.url_path_for("compute:update_nat_node_nio",
project_id=vm["project_id"],
node_id=vm["node_id"],
adapter_number="0",
port_number="0")
response = await compute_client.put(url, json=params)
assert response.status_code == status.HTTP_201_CREATED
assert response.json()["type"] == "nio_udp"
async def test_nat_delete_nio(app: FastAPI, compute_client: AsyncClient, vm: dict) -> None:
params = {
"type": "nio_udp",
"lport": 4242,
"rport": 4343,
"rhost": "127.0.0.1"
}
url = app.url_path_for("compute:create_nat_node_nio",
project_id=vm["project_id"],
node_id=vm["node_id"],
adapter_number="0",
port_number="0")
with asyncio_patch("gns3server.compute.builtin.nodes.nat.Nat.add_nio"):
await compute_client.post(url, json=params)
url = app.url_path_for("compute:delete_nat_node_nio",
project_id=vm["project_id"],
node_id=vm["node_id"],
adapter_number="0",
port_number="0")
with asyncio_patch("gns3server.compute.builtin.nodes.nat.Nat.remove_nio") as mock:
response = await compute_client.delete(url)
assert mock.called
assert response.status_code == status.HTTP_204_NO_CONTENT
async def test_nat_delete(app: FastAPI, compute_client: AsyncClient, vm: dict) -> None:
response = await compute_client.delete(app.url_path_for("compute:delete_nat_node",
project_id=vm["project_id"],
node_id=vm["node_id"]))
assert response.status_code == status.HTTP_204_NO_CONTENT
async def test_nat_update(app: FastAPI, compute_client: AsyncClient, vm: dict) -> None:
response = await compute_client.put(app.url_path_for("compute:update_nat_node",
project_id=vm["project_id"],
node_id=vm["node_id"]), json={"name": "test"})
assert response.status_code == status.HTTP_200_OK
assert response.json()["name"] == "test"
async def test_nat_start_capture(app: FastAPI, compute_client: AsyncClient, vm: dict) -> None:
params = {
"capture_file_name": "test.pcap",
"data_link_type": "DLT_EN10MB"
}
url = app.url_path_for("compute:start_nat_node_capture",
project_id=vm["project_id"],
node_id=vm["node_id"],
adapter_number="0",
port_number="0")
with asyncio_patch("gns3server.compute.builtin.nodes.nat.Nat.start_capture") as mock:
response = await compute_client.post(url, json=params)
assert response.status_code == status.HTTP_200_OK assert response.status_code == status.HTTP_200_OK
assert mock.called assert response.json()["name"] == "Nat 1"
assert "test.pcap" in response.json()["pcap_file_path"] assert response.json()["project_id"] == compute_project.id
assert response.json()["status"] == "started"
async def test_nat_stop_capture(app: FastAPI, compute_client: AsyncClient, vm: dict) -> None: async def test_nat_nio_create_udp(self, app: FastAPI, compute_client: AsyncClient, vm: dict) -> None:
url = app.url_path_for("compute:stop_nat_node_capture", params = {
project_id=vm["project_id"], "type": "nio_udp",
node_id=vm["node_id"], "lport": 4242,
adapter_number="0", "rport": 4343,
port_number="0") "rhost": "127.0.0.1"
}
with asyncio_patch("gns3server.compute.builtin.nodes.nat.Nat.stop_capture") as mock: url = app.url_path_for("compute:create_nat_node_nio",
response = await compute_client.post(url) project_id=vm["project_id"],
node_id=vm["node_id"],
adapter_number="0",
port_number="0")
with asyncio_patch("gns3server.compute.builtin.nodes.nat.Nat.add_nio"):
response = await compute_client.post(url, json=params)
assert response.status_code == status.HTTP_201_CREATED
assert response.json()["type"] == "nio_udp"
async def test_nat_nio_update_udp(self, app: FastAPI, compute_client: AsyncClient, vm: dict) -> None:
params = {
"type": "nio_udp",
"lport": 4242,
"rport": 4343,
"rhost": "127.0.0.1"
}
url = app.url_path_for("compute:create_nat_node_nio",
project_id=vm["project_id"],
node_id=vm["node_id"],
adapter_number="0",
port_number="0")
await compute_client.post(url, json=params)
params["filters"] = {}
url = app.url_path_for("compute:update_nat_node_nio",
project_id=vm["project_id"],
node_id=vm["node_id"],
adapter_number="0",
port_number="0")
response = await compute_client.put(url, json=params)
assert response.status_code == status.HTTP_201_CREATED
assert response.json()["type"] == "nio_udp"
async def test_nat_delete_nio(self, app: FastAPI, compute_client: AsyncClient, vm: dict) -> None:
params = {
"type": "nio_udp",
"lport": 4242,
"rport": 4343,
"rhost": "127.0.0.1"
}
url = app.url_path_for("compute:create_nat_node_nio",
project_id=vm["project_id"],
node_id=vm["node_id"],
adapter_number="0",
port_number="0")
with asyncio_patch("gns3server.compute.builtin.nodes.nat.Nat.add_nio"):
await compute_client.post(url, json=params)
url = app.url_path_for("compute:delete_nat_node_nio",
project_id=vm["project_id"],
node_id=vm["node_id"],
adapter_number="0",
port_number="0")
with asyncio_patch("gns3server.compute.builtin.nodes.nat.Nat.remove_nio") as mock:
response = await compute_client.delete(url)
assert mock.called
assert response.status_code == status.HTTP_204_NO_CONTENT assert response.status_code == status.HTTP_204_NO_CONTENT
assert mock.called
# @pytest.mark.asyncio async def test_nat_delete(self, app: FastAPI, compute_client: AsyncClient, vm: dict) -> None:
# async def test_nat_pcap(compute_api, vm, compute_project):
# response = await compute_client.delete(app.url_path_for("compute:delete_nat_node",
# with asyncio_patch("gns3server.compute.builtin.nodes.nat.Nat.get_nio"): project_id=vm["project_id"],
# with asyncio_patch("gns3server.compute.builtin.Builtin.stream_pcap_file"): node_id=vm["node_id"]))
# response = await compute_client.get("/projects/{project_id}/nat/nodes/{node_id}/adapters/0/ports/0/pcap".format(project_id=compute_project.id, node_id=vm["node_id"]), raw=True)
# assert response.status_code == status.HTTP_200_OK assert response.status_code == status.HTTP_204_NO_CONTENT
async def test_nat_update(self, app: FastAPI, compute_client: AsyncClient, vm: dict) -> None:
response = await compute_client.put(app.url_path_for("compute:update_nat_node",
project_id=vm["project_id"],
node_id=vm["node_id"]), json={"name": "test"})
assert response.status_code == status.HTTP_200_OK
assert response.json()["name"] == "test"
async def test_nat_start_capture(self, app: FastAPI, compute_client: AsyncClient, vm: dict) -> None:
params = {
"capture_file_name": "test.pcap",
"data_link_type": "DLT_EN10MB"
}
url = app.url_path_for("compute:start_nat_node_capture",
project_id=vm["project_id"],
node_id=vm["node_id"],
adapter_number="0",
port_number="0")
with asyncio_patch("gns3server.compute.builtin.nodes.nat.Nat.start_capture") as mock:
response = await compute_client.post(url, json=params)
assert response.status_code == status.HTTP_200_OK
assert mock.called
assert "test.pcap" in response.json()["pcap_file_path"]
async def test_nat_stop_capture(self, app: FastAPI, compute_client: AsyncClient, vm: dict) -> None:
url = app.url_path_for("compute:stop_nat_node_capture",
project_id=vm["project_id"],
node_id=vm["node_id"],
adapter_number="0",
port_number="0")
with asyncio_patch("gns3server.compute.builtin.nodes.nat.Nat.stop_capture") as mock:
response = await compute_client.post(url)
assert response.status_code == status.HTTP_204_NO_CONTENT
assert mock.called
# @pytest.mark.asyncio
# async def test_nat_pcap(self, compute_api, vm, compute_project):
#
# with asyncio_patch("gns3server.compute.builtin.nodes.nat.Nat.get_nio"):
# with asyncio_patch("gns3server.compute.builtin.Builtin.stream_pcap_file"):
# response = await compute_client.get("/projects/{project_id}/nat/nodes/{node_id}/adapters/0/ports/0/pcap".format(project_id=compute_project.id, node_id=vm["node_id"]), raw=True)
# assert response.status_code == status.HTTP_200_OK

View File

@ -30,173 +30,197 @@ from gns3server.compute.project import Project
pytestmark = pytest.mark.asyncio pytestmark = pytest.mark.asyncio
@pytest.fixture class TestComputeProjectRoutes:
def base_params(tmpdir) -> dict:
"""Return standard parameters"""
params = { @pytest.fixture
"name": "test", def base_params(self, tmpdir) -> dict:
"project_id": str(uuid.uuid4()) """Return standard parameters"""
}
return params params = {
"name": "test",
"project_id": str(uuid.uuid4())
}
return params
async def test_create_project_without_dir(app: FastAPI, compute_client: AsyncClient, base_params: dict) -> None: async def test_create_project_without_dir(
self,
app: FastAPI,
compute_client: AsyncClient,
base_params: dict
) -> None:
response = await compute_client.post(app.url_path_for("compute:create_compute_project"), json=base_params) response = await compute_client.post(app.url_path_for("compute:create_compute_project"), json=base_params)
assert response.status_code == status.HTTP_201_CREATED assert response.status_code == status.HTTP_201_CREATED
assert response.json()["project_id"] == base_params["project_id"] assert response.json()["project_id"] == base_params["project_id"]
assert response.json()["name"] == base_params["name"] assert response.json()["name"] == base_params["name"]
async def test_show_project(app: FastAPI, compute_client: AsyncClient, base_params: dict) -> None: async def test_show_project(
self,
app: FastAPI,
compute_client: AsyncClient,
base_params: dict
) -> None:
response = await compute_client.post(app.url_path_for("compute:create_compute_project"), json=base_params) response = await compute_client.post(app.url_path_for("compute:create_compute_project"), json=base_params)
assert response.status_code == status.HTTP_201_CREATED assert response.status_code == status.HTTP_201_CREATED
response = await compute_client.get(app.url_path_for("compute:get_compute_project", project_id=base_params["project_id"])) response = await compute_client.get(app.url_path_for("compute:get_compute_project", project_id=base_params["project_id"]))
#print(response.json().keys()) #print(response.json().keys())
#assert len(response.json().keys()) == 3 #assert len(response.json().keys()) == 3
assert response.json()["project_id"] == base_params["project_id"] assert response.json()["project_id"] == base_params["project_id"]
assert response.json()["name"] == base_params["name"] assert response.json()["name"] == base_params["name"]
assert response.json()["variables"] is None assert response.json()["variables"] is None
async def test_show_project_invalid_uuid(app: FastAPI, compute_client: AsyncClient) -> None: async def test_show_project_invalid_uuid(self, app: FastAPI, compute_client: AsyncClient) -> None:
response = await compute_client.get(app.url_path_for("compute:get_compute_project", response = await compute_client.get(app.url_path_for("compute:get_compute_project",
project_id="50010203-0405-0607-0809-0a0b0c0d0e42")) project_id="50010203-0405-0607-0809-0a0b0c0d0e42"))
assert response.status_code == status.HTTP_404_NOT_FOUND assert response.status_code == status.HTTP_404_NOT_FOUND
async def test_list_projects(app: FastAPI, compute_client: AsyncClient) -> dict: async def test_list_projects(self, app: FastAPI, compute_client: AsyncClient) -> dict:
ProjectManager.instance()._projects = {} ProjectManager.instance()._projects = {}
params = {"name": "test", "project_id": "51010203-0405-0607-0809-0a0b0c0d0e0f"} params = {"name": "test", "project_id": "51010203-0405-0607-0809-0a0b0c0d0e0f"}
response = await compute_client.post(app.url_path_for("compute:create_compute_project"), json=params) response = await compute_client.post(app.url_path_for("compute:create_compute_project"), json=params)
assert response.status_code == status.HTTP_201_CREATED assert response.status_code == status.HTTP_201_CREATED
params = {"name": "test", "project_id": "52010203-0405-0607-0809-0a0b0c0d0e0b"} params = {"name": "test", "project_id": "52010203-0405-0607-0809-0a0b0c0d0e0b"}
response = await compute_client.post(app.url_path_for("compute:create_compute_project"), json=params) response = await compute_client.post(app.url_path_for("compute:create_compute_project"), json=params)
assert response.status_code == status.HTTP_201_CREATED assert response.status_code == status.HTTP_201_CREATED
response = await compute_client.get(app.url_path_for("compute:get_compute_projects")) response = await compute_client.get(app.url_path_for("compute:get_compute_projects"))
assert response.status_code == status.HTTP_200_OK assert response.status_code == status.HTTP_200_OK
assert len(response.json()) == 2 assert len(response.json()) == 2
assert "51010203-0405-0607-0809-0a0b0c0d0e0f" in [p["project_id"] for p in response.json()] assert "51010203-0405-0607-0809-0a0b0c0d0e0f" in [p["project_id"] for p in response.json()]
async def test_delete_project(app: FastAPI, compute_client: AsyncClient, compute_project: Project) -> None: async def test_delete_project(self, app: FastAPI, compute_client: AsyncClient, compute_project: Project) -> None:
with asyncio_patch("gns3server.compute.project.Project.delete", return_value=True) as mock: with asyncio_patch("gns3server.compute.project.Project.delete", return_value=True) as mock:
response = await compute_client.delete(app.url_path_for("compute:delete_compute_project", project_id=compute_project.id)) response = await compute_client.delete(app.url_path_for("compute:delete_compute_project", project_id=compute_project.id))
assert response.status_code == status.HTTP_204_NO_CONTENT assert response.status_code == status.HTTP_204_NO_CONTENT
assert mock.called assert mock.called
async def test_update_project(app: FastAPI, compute_client: AsyncClient, base_params: dict) -> None: async def test_update_project(self, app: FastAPI, compute_client: AsyncClient, base_params: dict) -> None:
response = await compute_client.post(app.url_path_for("compute:create_compute_project"), json=base_params) response = await compute_client.post(app.url_path_for("compute:create_compute_project"), json=base_params)
assert response.status_code == status.HTTP_201_CREATED assert response.status_code == status.HTTP_201_CREATED
params = {"variables": [{"name": "TEST1", "value": "VAL1"}]} params = {"variables": [{"name": "TEST1", "value": "VAL1"}]}
response = await compute_client.put(app.url_path_for("compute:update_compute_project", project_id=base_params["project_id"]), response = await compute_client.put(app.url_path_for("compute:update_compute_project", project_id=base_params["project_id"]),
json=params) json=params)
assert response.status_code == status.HTTP_200_OK assert response.status_code == status.HTTP_200_OK
assert response.json()["variables"] == [{"name": "TEST1", "value": "VAL1"}] assert response.json()["variables"] == [{"name": "TEST1", "value": "VAL1"}]
async def test_delete_project_invalid_uuid(app: FastAPI, compute_client: AsyncClient) -> None: async def test_delete_project_invalid_uuid(self, app: FastAPI, compute_client: AsyncClient) -> None:
response = await compute_client.delete(app.url_path_for("compute:delete_compute_project", project_id=str(uuid.uuid4()))) response = await compute_client.delete(app.url_path_for("compute:delete_compute_project", project_id=str(uuid.uuid4())))
assert response.status_code == status.HTTP_404_NOT_FOUND assert response.status_code == status.HTTP_404_NOT_FOUND
async def test_close_project(app: FastAPI, compute_client: AsyncClient, compute_project: Project) -> None: async def test_close_project(self, app: FastAPI, compute_client: AsyncClient, compute_project: Project) -> None:
with asyncio_patch("gns3server.compute.project.Project.close", return_value=True) as mock: with asyncio_patch("gns3server.compute.project.Project.close", return_value=True) as mock:
response = await compute_client.post(app.url_path_for("compute:close_compute_project", project_id=compute_project.id)) response = await compute_client.post(app.url_path_for("compute:close_compute_project", project_id=compute_project.id))
assert response.status_code == status.HTTP_204_NO_CONTENT assert response.status_code == status.HTTP_204_NO_CONTENT
assert mock.called assert mock.called
# @pytest.mark.asyncio # @pytest.mark.asyncio
# async def test_close_project_two_client_connected(compute_api, compute_project): # async def test_close_project_two_client_connected(compute_api, compute_project):
# #
# ProjectHandler._notifications_listening = {compute_project.id: 2} # ProjectHandler._notifications_listening = {compute_project.id: 2}
# with asyncio_patch("gns3server.compute.project.Project.close", return_value=True) as mock: # with asyncio_patch("gns3server.compute.project.Project.close", return_value=True) as mock:
# response = await compute_client.post("/projects/{project_id}/close".format(project_id=compute_project.id)) # response = await compute_client.post("/projects/{project_id}/close".format(project_id=compute_project.id))
# assert response.status_code == status.HTTP_204_NO_CONTENT # assert response.status_code == status.HTTP_204_NO_CONTENT
# assert not mock.called # assert not mock.called
async def test_close_project_invalid_uuid(app: FastAPI, compute_client: AsyncClient) -> None: async def test_close_project_invalid_uuid(self, app: FastAPI, compute_client: AsyncClient) -> None:
response = await compute_client.post(app.url_path_for("compute:close_compute_project", project_id=str(uuid.uuid4()))) response = await compute_client.post(app.url_path_for("compute:close_compute_project", project_id=str(uuid.uuid4())))
assert response.status_code == status.HTTP_404_NOT_FOUND assert response.status_code == status.HTTP_404_NOT_FOUND
async def test_get_file(app: FastAPI, compute_client: AsyncClient) -> None: async def test_get_file(self, app: FastAPI, compute_client: AsyncClient) -> None:
project = ProjectManager.instance().create_project(project_id="01010203-0405-0607-0809-0a0b0c0d0e0b") project = ProjectManager.instance().create_project(project_id="01010203-0405-0607-0809-0a0b0c0d0e0b")
with open(os.path.join(project.path, "hello"), "w+") as f: with open(os.path.join(project.path, "hello"), "w+") as f:
f.write("world") f.write("world")
response = await compute_client.get(app.url_path_for("compute:get_compute_project_file", project_id=project.id, file_path="hello")) response = await compute_client.get(app.url_path_for("compute:get_compute_project_file", project_id=project.id, file_path="hello"))
assert response.status_code == status.HTTP_200_OK assert response.status_code == status.HTTP_200_OK
assert response.content == b"world" assert response.content == b"world"
response = await compute_client.get(app.url_path_for("compute:get_compute_project_file", project_id=project.id, file_path="false")) response = await compute_client.get(app.url_path_for("compute:get_compute_project_file", project_id=project.id, file_path="false"))
assert response.status_code == status.HTTP_404_NOT_FOUND assert response.status_code == status.HTTP_404_NOT_FOUND
response = await compute_client.get(app.url_path_for("compute:get_compute_project_file", response = await compute_client.get(app.url_path_for("compute:get_compute_project_file",
project_id=project.id, project_id=project.id,
file_path="../hello")) file_path="../hello"))
assert response.status_code == status.HTTP_404_NOT_FOUND assert response.status_code == status.HTTP_404_NOT_FOUND
async def test_get_file_forbidden_location(app: FastAPI, compute_client: AsyncClient, config, tmpdir) -> None: async def test_get_file_forbidden_location(
self,
app: FastAPI,
compute_client: AsyncClient,
config,
tmpdir
) -> None:
config.settings.Server.projects_path = str(tmpdir) config.settings.Server.projects_path = str(tmpdir)
project = ProjectManager.instance().create_project(project_id="01010203-0405-0607-0809-0a0b0c0d0e0b") project = ProjectManager.instance().create_project(project_id="01010203-0405-0607-0809-0a0b0c0d0e0b")
file_path = "foo/%2e%2e/%2e%2e/%2e%2e/%2e%2e/%2e%2e/%2e%2e/etc/passwd" file_path = "foo/%2e%2e/%2e%2e/%2e%2e/%2e%2e/%2e%2e/%2e%2e/etc/passwd"
response = await compute_client.get( response = await compute_client.get(
app.url_path_for( app.url_path_for(
"compute:get_compute_project_file", "compute:get_compute_project_file",
project_id=project.id, project_id=project.id,
file_path=file_path file_path=file_path
)
) )
) assert response.status_code == status.HTTP_403_FORBIDDEN
assert response.status_code == status.HTTP_403_FORBIDDEN
async def test_write_file(app: FastAPI, compute_client: AsyncClient, config, tmpdir) -> None: async def test_write_file(self, app: FastAPI, compute_client: AsyncClient, config, tmpdir) -> None:
config.settings.Server.projects_path = str(tmpdir) config.settings.Server.projects_path = str(tmpdir)
project = ProjectManager.instance().create_project(project_id="01010203-0405-0607-0809-0a0b0c0d0e0b") project = ProjectManager.instance().create_project(project_id="01010203-0405-0607-0809-0a0b0c0d0e0b")
response = await compute_client.post(app.url_path_for("compute:write_compute_project_file", response = await compute_client.post(app.url_path_for("compute:write_compute_project_file",
project_id=project.id, project_id=project.id,
file_path="hello"), content=b"world") file_path="hello"), content=b"world")
assert response.status_code == status.HTTP_204_NO_CONTENT assert response.status_code == status.HTTP_204_NO_CONTENT
with open(os.path.join(project.path, "hello")) as f: with open(os.path.join(project.path, "hello")) as f:
assert f.read() == "world" assert f.read() == "world"
response = await compute_client.post(app.url_path_for("compute:write_compute_project_file", response = await compute_client.post(app.url_path_for("compute:write_compute_project_file",
project_id=project.id, project_id=project.id,
file_path="../hello")) file_path="../hello"))
assert response.status_code == status.HTTP_404_NOT_FOUND assert response.status_code == status.HTTP_404_NOT_FOUND
async def test_write_file_forbidden_location(app: FastAPI, compute_client: AsyncClient, config, tmpdir) -> None: async def test_write_file_forbidden_location(
self,
app: FastAPI,
compute_client: AsyncClient,
config,
tmpdir
) -> None:
config.settings.Server.projects_path = str(tmpdir) config.settings.Server.projects_path = str(tmpdir)
project = ProjectManager.instance().create_project(project_id="01010203-0405-0607-0809-0a0b0c0d0e0b") project = ProjectManager.instance().create_project(project_id="01010203-0405-0607-0809-0a0b0c0d0e0b")
file_path = "%2e%2e/hello" file_path = "%2e%2e/hello"
response = await compute_client.post(app.url_path_for("compute:write_compute_project_file", response = await compute_client.post(app.url_path_for("compute:write_compute_project_file",
project_id=project.id, project_id=project.id,
file_path=file_path), content=b"world") file_path=file_path), content=b"world")
assert response.status_code == status.HTTP_403_FORBIDDEN assert response.status_code == status.HTTP_403_FORBIDDEN

File diff suppressed because it is too large Load Diff

View File

@ -28,221 +28,223 @@ from gns3server.compute.project import Project
pytestmark = pytest.mark.asyncio pytestmark = pytest.mark.asyncio
@pytest_asyncio.fixture(scope="function") class TestVirtualBoxNodesRoutes:
async def vm(app: FastAPI, compute_client: AsyncClient, compute_project: Project) -> None:
vboxmanage_path = "/fake/VboxManage" @pytest_asyncio.fixture
params = { async def vm(self, app: FastAPI, compute_client: AsyncClient, compute_project: Project) -> None:
"name": "VMTEST",
"vmname": "VMTEST",
"linked_clone": False
}
with asyncio_patch("gns3server.compute.virtualbox.virtualbox_vm.VirtualBoxVM.create", return_value=True) as mock: vboxmanage_path = "/fake/VboxManage"
response = await compute_client.post(app.url_path_for("compute:create_virtualbox_node", project_id=compute_project.id), params = {
json=params) "name": "VMTEST",
assert mock.called "vmname": "VMTEST",
assert response.status_code == status.HTTP_201_CREATED "linked_clone": False
}
with patch("gns3server.compute.virtualbox.VirtualBox.find_vboxmanage", return_value=vboxmanage_path): with asyncio_patch("gns3server.compute.virtualbox.virtualbox_vm.VirtualBoxVM.create", return_value=True) as mock:
return response.json() response = await compute_client.post(app.url_path_for("compute:create_virtualbox_node", project_id=compute_project.id),
json=params)
assert mock.called
async def test_vbox_create(app: FastAPI, compute_client: AsyncClient, compute_project: Project) -> None:
params = {
"name": "VM1",
"vmname": "VM1",
"linked_clone": False
}
with asyncio_patch("gns3server.compute.virtualbox.virtualbox_vm.VirtualBoxVM.create", return_value=True):
response = await compute_client.post(app.url_path_for("compute:create_virtualbox_node", project_id=compute_project.id),
json=params)
assert response.status_code == status.HTTP_201_CREATED assert response.status_code == status.HTTP_201_CREATED
assert response.json()["name"] == "VM1"
with patch("gns3server.compute.virtualbox.VirtualBox.find_vboxmanage", return_value=vboxmanage_path):
return response.json()
async def test_vbox_create(self, app: FastAPI, compute_client: AsyncClient, compute_project: Project) -> None:
params = {
"name": "VM1",
"vmname": "VM1",
"linked_clone": False
}
with asyncio_patch("gns3server.compute.virtualbox.virtualbox_vm.VirtualBoxVM.create", return_value=True):
response = await compute_client.post(app.url_path_for("compute:create_virtualbox_node", project_id=compute_project.id),
json=params)
assert response.status_code == status.HTTP_201_CREATED
assert response.json()["name"] == "VM1"
assert response.json()["project_id"] == compute_project.id
async def test_vbox_get(self, app: FastAPI, compute_client: AsyncClient, compute_project: Project, vm: dict) -> None:
response = await compute_client.get(app.url_path_for("compute:get_virtualbox_node",
project_id=vm["project_id"],
node_id=vm["node_id"]))
assert response.status_code == status.HTTP_200_OK
assert response.json()["name"] == "VMTEST"
assert response.json()["project_id"] == compute_project.id assert response.json()["project_id"] == compute_project.id
async def test_vbox_get(app: FastAPI, compute_client: AsyncClient, compute_project: Project, vm: dict) -> None: async def test_vbox_start(self, app: FastAPI, compute_client: AsyncClient, vm: dict) -> None:
response = await compute_client.get(app.url_path_for("compute:get_virtualbox_node", with asyncio_patch("gns3server.compute.virtualbox.virtualbox_vm.VirtualBoxVM.start", return_value=True) as mock:
project_id=vm["project_id"],
node_id=vm["node_id"]))
assert response.status_code == status.HTTP_200_OK
assert response.json()["name"] == "VMTEST"
assert response.json()["project_id"] == compute_project.id
response = await compute_client.post(app.url_path_for("compute:start_virtualbox_node",
async def test_vbox_start(app: FastAPI, compute_client: AsyncClient, vm: dict) -> None: project_id=vm["project_id"],
node_id=vm["node_id"]))
with asyncio_patch("gns3server.compute.virtualbox.virtualbox_vm.VirtualBoxVM.start", return_value=True) as mock:
response = await compute_client.post(app.url_path_for("compute:start_virtualbox_node",
project_id=vm["project_id"],
node_id=vm["node_id"]))
assert mock.called
assert response.status_code == status.HTTP_204_NO_CONTENT
async def test_vbox_stop(app: FastAPI, compute_client: AsyncClient, vm: dict) -> None:
with asyncio_patch("gns3server.compute.virtualbox.virtualbox_vm.VirtualBoxVM.stop", return_value=True) as mock:
response = await compute_client.post(app.url_path_for("compute:stop_virtualbox_node",
project_id=vm["project_id"],
node_id=vm["node_id"]))
assert mock.called
assert response.status_code == status.HTTP_204_NO_CONTENT
async def test_vbox_suspend(app: FastAPI, compute_client: AsyncClient, vm: dict) -> None:
with asyncio_patch("gns3server.compute.virtualbox.virtualbox_vm.VirtualBoxVM.suspend", return_value=True) as mock:
response = await compute_client.post(app.url_path_for("compute:suspend_virtualbox_node",
project_id=vm["project_id"],
node_id=vm["node_id"]))
assert mock.called
assert response.status_code == status.HTTP_204_NO_CONTENT
async def test_vbox_resume(app: FastAPI, compute_client: AsyncClient, vm: dict) -> None:
with asyncio_patch("gns3server.compute.virtualbox.virtualbox_vm.VirtualBoxVM.resume", return_value=True) as mock:
response = await compute_client.post(app.url_path_for("compute:resume_virtualbox_node",
project_id=vm["project_id"],
node_id=vm["node_id"]))
assert mock.called
assert response.status_code == status.HTTP_204_NO_CONTENT
async def test_vbox_reload(app: FastAPI, compute_client: AsyncClient, vm: dict) -> None:
with asyncio_patch("gns3server.compute.virtualbox.virtualbox_vm.VirtualBoxVM.reload", return_value=True) as mock:
response = await compute_client.post(app.url_path_for("compute:reload_virtualbox_node",
project_id=vm["project_id"],
node_id=vm["node_id"]))
assert mock.called
assert response.status_code == status.HTTP_204_NO_CONTENT
async def test_vbox_nio_create_udp(app: FastAPI, compute_client: AsyncClient, vm: dict) -> None:
params = {
"type": "nio_udp",
"lport": 4242,
"rport": 4343,
"rhost": "127.0.0.1"
}
url = app.url_path_for("compute:create_virtualbox_node_nio",
project_id=vm["project_id"],
node_id=vm["node_id"],
adapter_number="0",
port_number="0")
with asyncio_patch('gns3server.compute.virtualbox.virtualbox_vm.VirtualBoxVM.adapter_add_nio_binding') as mock:
response = await compute_client.post(url, json=params)
assert mock.called
args, kwgars = mock.call_args
assert args[0] == 0
assert response.status_code == status.HTTP_201_CREATED
assert response.json()["type"] == "nio_udp"
# @pytest.mark.asyncio
# async def test_vbox_nio_update_udp(app: FastAPI, compute_client: AsyncClient, vm):
#
# params = {
# "type": "nio_udp",
# "lport": 4242,
# "rport": 4343,
# "rhost": "127.0.0.1",
# "filters": {}
# }
#
# with asyncio_patch('gns3server.compute.virtualbox.virtualbox_vm.VirtualBoxVM.ethernet_adapters'):
# with asyncio_patch('gns3server.compute.virtualbox.virtualbox_vm.VirtualBoxVM.adapter_remove_nio_binding'):
# response = await compute_client.put("/projects/{project_id}/virtualbox/nodes/{node_id}/adapters/0/ports/0/nio".format(project_id=vm["project_id"], node_id=vm["node_id"]), params)
#
# assert response.status_code == status.HTTP_201_CREATED
# assert response.json()["type"] == "nio_udp"
async def test_vbox_delete_nio(app: FastAPI, compute_client: AsyncClient, vm: dict) -> None:
url = app.url_path_for("compute:delete_virtualbox_node_nio",
project_id=vm["project_id"],
node_id=vm["node_id"],
adapter_number="0",
port_number="0")
with asyncio_patch('gns3server.compute.virtualbox.virtualbox_vm.VirtualBoxVM.adapter_remove_nio_binding') as mock:
response = await compute_client.delete(url)
assert mock.called
args, kwgars = mock.call_args
assert args[0] == 0
assert response.status_code == status.HTTP_204_NO_CONTENT
@pytest.mark.asyncio
async def test_vbox_update(app: FastAPI, compute_client: AsyncClient, vm, free_console_port):
params = {
"name": "test",
"console": free_console_port
}
response = await compute_client.put(app.url_path_for("compute:update_virtualbox_node",
project_id=vm["project_id"],
node_id=vm["node_id"]), json=params)
assert response.status_code == status.HTTP_200_OK
assert response.json()["name"] == "test"
assert response.json()["console"] == free_console_port
@pytest.mark.asyncio
async def test_virtualbox_start_capture(app: FastAPI, compute_client: AsyncClient, vm):
params = {
"capture_file_name": "test.pcap",
"data_link_type": "DLT_EN10MB"
}
url = app.url_path_for("compute:start_virtualbox_node_capture",
project_id=vm["project_id"],
node_id=vm["node_id"],
adapter_number="0",
port_number="0")
with patch("gns3server.compute.virtualbox.virtualbox_vm.VirtualBoxVM.is_running", return_value=True):
with asyncio_patch("gns3server.compute.virtualbox.virtualbox_vm.VirtualBoxVM.start_capture") as mock:
response = await compute_client.post(url, json=params)
assert response.status_code == status.HTTP_200_OK
assert mock.called assert mock.called
assert "test.pcap" in response.json()["pcap_file_path"]
@pytest.mark.asyncio
async def test_virtualbox_stop_capture(app: FastAPI, compute_client: AsyncClient, vm):
url = app.url_path_for("compute:stop_virtualbox_node_capture",
project_id=vm["project_id"],
node_id=vm["node_id"],
adapter_number="0",
port_number="0")
with patch("gns3server.compute.virtualbox.virtualbox_vm.VirtualBoxVM.is_running", return_value=True):
with asyncio_patch("gns3server.compute.virtualbox.virtualbox_vm.VirtualBoxVM.stop_capture") as mock:
response = await compute_client.post(url)
assert response.status_code == status.HTTP_204_NO_CONTENT assert response.status_code == status.HTTP_204_NO_CONTENT
async def test_vbox_stop(self, app: FastAPI, compute_client: AsyncClient, vm: dict) -> None:
with asyncio_patch("gns3server.compute.virtualbox.virtualbox_vm.VirtualBoxVM.stop", return_value=True) as mock:
response = await compute_client.post(app.url_path_for("compute:stop_virtualbox_node",
project_id=vm["project_id"],
node_id=vm["node_id"]))
assert mock.called assert mock.called
assert response.status_code == status.HTTP_204_NO_CONTENT
# @pytest.mark.asyncio async def test_vbox_suspend(self, app: FastAPI, compute_client: AsyncClient, vm: dict) -> None:
# async def test_virtualbox_pcap(app: FastAPI, compute_client: AsyncClient, vm, compute_project):
# with asyncio_patch("gns3server.compute.virtualbox.virtualbox_vm.VirtualBoxVM.suspend", return_value=True) as mock:
# with asyncio_patch("gns3server.compute.virtualbox.virtualbox_vm.VirtualBoxVM.get_nio"): response = await compute_client.post(app.url_path_for("compute:suspend_virtualbox_node",
# with asyncio_patch("gns3server.compute.virtualbox.VirtualBox.stream_pcap_file"): project_id=vm["project_id"],
# response = await compute_client.get("/projects/{project_id}/virtualbox/nodes/{node_id}/adapters/0/ports/0/pcap".format(project_id=compute_project.id, node_id=vm["node_id"]), raw=True) node_id=vm["node_id"]))
# assert response.status_code == status.HTTP_200_OK assert mock.called
assert response.status_code == status.HTTP_204_NO_CONTENT
async def test_vbox_resume(self, app: FastAPI, compute_client: AsyncClient, vm: dict) -> None:
with asyncio_patch("gns3server.compute.virtualbox.virtualbox_vm.VirtualBoxVM.resume", return_value=True) as mock:
response = await compute_client.post(app.url_path_for("compute:resume_virtualbox_node",
project_id=vm["project_id"],
node_id=vm["node_id"]))
assert mock.called
assert response.status_code == status.HTTP_204_NO_CONTENT
async def test_vbox_reload(self, app: FastAPI, compute_client: AsyncClient, vm: dict) -> None:
with asyncio_patch("gns3server.compute.virtualbox.virtualbox_vm.VirtualBoxVM.reload", return_value=True) as mock:
response = await compute_client.post(app.url_path_for("compute:reload_virtualbox_node",
project_id=vm["project_id"],
node_id=vm["node_id"]))
assert mock.called
assert response.status_code == status.HTTP_204_NO_CONTENT
async def test_vbox_nio_create_udp(self, app: FastAPI, compute_client: AsyncClient, vm: dict) -> None:
params = {
"type": "nio_udp",
"lport": 4242,
"rport": 4343,
"rhost": "127.0.0.1"
}
url = app.url_path_for("compute:create_virtualbox_node_nio",
project_id=vm["project_id"],
node_id=vm["node_id"],
adapter_number="0",
port_number="0")
with asyncio_patch('gns3server.compute.virtualbox.virtualbox_vm.VirtualBoxVM.adapter_add_nio_binding') as mock:
response = await compute_client.post(url, json=params)
assert mock.called
args, kwgars = mock.call_args
assert args[0] == 0
assert response.status_code == status.HTTP_201_CREATED
assert response.json()["type"] == "nio_udp"
# @pytest.mark.asyncio
# async def test_vbox_nio_update_udp(self, app: FastAPI, compute_client: AsyncClient, vm):
#
# params = {
# "type": "nio_udp",
# "lport": 4242,
# "rport": 4343,
# "rhost": "127.0.0.1",
# "filters": {}
# }
#
# with asyncio_patch('gns3server.compute.virtualbox.virtualbox_vm.VirtualBoxVM.ethernet_adapters'):
# with asyncio_patch('gns3server.compute.virtualbox.virtualbox_vm.VirtualBoxVM.adapter_remove_nio_binding'):
# response = await compute_client.put("/projects/{project_id}/virtualbox/nodes/{node_id}/adapters/0/ports/0/nio".format(project_id=vm["project_id"], node_id=vm["node_id"]), params)
#
# assert response.status_code == status.HTTP_201_CREATED
# assert response.json()["type"] == "nio_udp"
async def test_vbox_delete_nio(self, app: FastAPI, compute_client: AsyncClient, vm: dict) -> None:
url = app.url_path_for("compute:delete_virtualbox_node_nio",
project_id=vm["project_id"],
node_id=vm["node_id"],
adapter_number="0",
port_number="0")
with asyncio_patch('gns3server.compute.virtualbox.virtualbox_vm.VirtualBoxVM.adapter_remove_nio_binding') as mock:
response = await compute_client.delete(url)
assert mock.called
args, kwgars = mock.call_args
assert args[0] == 0
assert response.status_code == status.HTTP_204_NO_CONTENT
@pytest.mark.asyncio
async def test_vbox_update(self, app: FastAPI, compute_client: AsyncClient, vm, free_console_port):
params = {
"name": "test",
"console": free_console_port
}
response = await compute_client.put(app.url_path_for("compute:update_virtualbox_node",
project_id=vm["project_id"],
node_id=vm["node_id"]), json=params)
assert response.status_code == status.HTTP_200_OK
assert response.json()["name"] == "test"
assert response.json()["console"] == free_console_port
@pytest.mark.asyncio
async def test_virtualbox_start_capture(self, app: FastAPI, compute_client: AsyncClient, vm):
params = {
"capture_file_name": "test.pcap",
"data_link_type": "DLT_EN10MB"
}
url = app.url_path_for("compute:start_virtualbox_node_capture",
project_id=vm["project_id"],
node_id=vm["node_id"],
adapter_number="0",
port_number="0")
with patch("gns3server.compute.virtualbox.virtualbox_vm.VirtualBoxVM.is_running", return_value=True):
with asyncio_patch("gns3server.compute.virtualbox.virtualbox_vm.VirtualBoxVM.start_capture") as mock:
response = await compute_client.post(url, json=params)
assert response.status_code == status.HTTP_200_OK
assert mock.called
assert "test.pcap" in response.json()["pcap_file_path"]
@pytest.mark.asyncio
async def test_virtualbox_stop_capture(self, app: FastAPI, compute_client: AsyncClient, vm):
url = app.url_path_for("compute:stop_virtualbox_node_capture",
project_id=vm["project_id"],
node_id=vm["node_id"],
adapter_number="0",
port_number="0")
with patch("gns3server.compute.virtualbox.virtualbox_vm.VirtualBoxVM.is_running", return_value=True):
with asyncio_patch("gns3server.compute.virtualbox.virtualbox_vm.VirtualBoxVM.stop_capture") as mock:
response = await compute_client.post(url)
assert response.status_code == status.HTTP_204_NO_CONTENT
assert mock.called
# @pytest.mark.asyncio
# async def test_virtualbox_pcap(self, app: FastAPI, compute_client: AsyncClient, vm, compute_project):
#
# with asyncio_patch("gns3server.compute.virtualbox.virtualbox_vm.VirtualBoxVM.get_nio"):
# with asyncio_patch("gns3server.compute.virtualbox.VirtualBox.stream_pcap_file"):
# response = await compute_client.get("/projects/{project_id}/virtualbox/nodes/{node_id}/adapters/0/ports/0/pcap".format(project_id=compute_project.id, node_id=vm["node_id"]), raw=True)
# assert response.status_code == status.HTTP_200_OK

View File

@ -28,226 +28,246 @@ from gns3server.compute.project import Project
pytestmark = pytest.mark.asyncio pytestmark = pytest.mark.asyncio
@pytest_asyncio.fixture(scope="function") class TestVMwareNodesRoutes:
async def vm(app: FastAPI, compute_client: AsyncClient, compute_project: Project, vmx_path: str) -> dict:
params = { @pytest_asyncio.fixture
"name": "VMTEST", async def vm(self, app: FastAPI, compute_client: AsyncClient, compute_project: Project, vmx_path: str) -> dict:
"vmx_path": vmx_path,
"linked_clone": False
}
with asyncio_patch("gns3server.compute.vmware.vmware_vm.VMwareVM.create", return_value=True) as mock: params = {
response = await compute_client.post(app.url_path_for("compute:create_vmware_node", project_id=compute_project.id), "name": "VMTEST",
json=params) "vmx_path": vmx_path,
assert mock.called "linked_clone": False
assert response.status_code == status.HTTP_201_CREATED }
return response.json()
with asyncio_patch("gns3server.compute.vmware.vmware_vm.VMwareVM.create", return_value=True) as mock:
response = await compute_client.post(app.url_path_for("compute:create_vmware_node", project_id=compute_project.id),
json=params)
assert mock.called
assert response.status_code == status.HTTP_201_CREATED
return response.json()
@pytest.fixture @pytest.fixture
def vmx_path(tmpdir: str) -> str: def vmx_path(self, tmpdir: str) -> str:
""" """
Return a fake VMX file Return a fake VMX file
""" """
path = str(tmpdir / "test.vmx") path = str(tmpdir / "test.vmx")
with open(path, 'w+') as f: with open(path, 'w+') as f:
f.write("1") f.write("1")
return path return path
async def test_vmware_create(app: FastAPI, compute_client: AsyncClient, compute_project: Project, vmx_path: str) -> None: async def test_vmware_create(
self,
app: FastAPI,
compute_client: AsyncClient,
compute_project: Project,
vmx_path: str
) -> None:
params = { params = {
"name": "VM1", "name": "VM1",
"vmx_path": vmx_path, "vmx_path": vmx_path,
"linked_clone": False "linked_clone": False
} }
with asyncio_patch("gns3server.compute.vmware.vmware_vm.VMwareVM.create", return_value=True): with asyncio_patch("gns3server.compute.vmware.vmware_vm.VMwareVM.create", return_value=True):
response = await compute_client.post(app.url_path_for("compute:create_vmware_node", project_id=compute_project.id), response = await compute_client.post(app.url_path_for("compute:create_vmware_node", project_id=compute_project.id),
json=params) json=params)
assert response.status_code == status.HTTP_201_CREATED assert response.status_code == status.HTTP_201_CREATED
assert response.json()["name"] == "VM1" assert response.json()["name"] == "VM1"
assert response.json()["project_id"] == compute_project.id
async def test_vmware_get(
self,
app: FastAPI,
compute_client: AsyncClient,
compute_project: Project,
vm: dict
) -> None:
response = await compute_client.get(app.url_path_for("compute:get_vmware_node", project_id=vm["project_id"], node_id=vm["node_id"]))
assert response.status_code == status.HTTP_200_OK
assert response.json()["name"] == "VMTEST"
assert response.json()["project_id"] == compute_project.id assert response.json()["project_id"] == compute_project.id
async def test_vmware_get(app: FastAPI, compute_client: AsyncClient, compute_project: Project, vm: dict) -> None: async def test_vmware_start(self, app: FastAPI, compute_client: AsyncClient, vm: dict) -> None:
response = await compute_client.get(app.url_path_for("compute:get_vmware_node", project_id=vm["project_id"], node_id=vm["node_id"])) with asyncio_patch("gns3server.compute.vmware.vmware_vm.VMwareVM.start", return_value=True) as mock:
assert response.status_code == status.HTTP_200_OK response = await compute_client.post(app.url_path_for("compute:start_vmware_node",
assert response.json()["name"] == "VMTEST" project_id=vm["project_id"],
assert response.json()["project_id"] == compute_project.id node_id=vm["node_id"]))
async def test_vmware_start(app: FastAPI, compute_client: AsyncClient, vm: dict) -> None:
with asyncio_patch("gns3server.compute.vmware.vmware_vm.VMwareVM.start", return_value=True) as mock:
response = await compute_client.post(app.url_path_for("compute:start_vmware_node",
project_id=vm["project_id"],
node_id=vm["node_id"]))
assert mock.called
assert response.status_code == status.HTTP_204_NO_CONTENT
async def test_vmware_stop(app: FastAPI, compute_client: AsyncClient, vm: dict) -> None:
with asyncio_patch("gns3server.compute.vmware.vmware_vm.VMwareVM.stop", return_value=True) as mock:
response = await compute_client.post(app.url_path_for("compute:stop_vmware_node",
project_id=vm["project_id"],
node_id=vm["node_id"]))
assert mock.called
assert response.status_code == status.HTTP_204_NO_CONTENT
async def test_vmware_suspend(app: FastAPI, compute_client: AsyncClient, vm: dict) -> None:
with asyncio_patch("gns3server.compute.vmware.vmware_vm.VMwareVM.suspend", return_value=True) as mock:
response = await compute_client.post(app.url_path_for("compute:suspend_vmware_node",
project_id=vm["project_id"],
node_id=vm["node_id"]))
assert mock.called
assert response.status_code == status.HTTP_204_NO_CONTENT
async def test_vmware_resume(app: FastAPI, compute_client: AsyncClient, vm: dict) -> None:
with asyncio_patch("gns3server.compute.vmware.vmware_vm.VMwareVM.resume", return_value=True) as mock:
response = await compute_client.post(app.url_path_for("compute:resume_vmware_node",
project_id=vm["project_id"],
node_id=vm["node_id"]))
assert mock.called
assert response.status_code == status.HTTP_204_NO_CONTENT
async def test_vmware_reload(app: FastAPI, compute_client: AsyncClient, vm: dict) -> None:
with asyncio_patch("gns3server.compute.vmware.vmware_vm.VMwareVM.reload", return_value=True) as mock:
response = await compute_client.post(app.url_path_for("compute:reload_vmware_node",
project_id=vm["project_id"],
node_id=vm["node_id"]))
assert mock.called
assert response.status_code == status.HTTP_204_NO_CONTENT
async def test_vmware_nio_create_udp(app: FastAPI, compute_client: AsyncClient, vm: dict) -> None:
params = {
"type": "nio_udp",
"lport": 4242,
"rport": 4343,
"rhost": "127.0.0.1"
}
url = app.url_path_for("compute:create_vmware_node_nio",
project_id=vm["project_id"],
node_id=vm["node_id"],
adapter_number="0",
port_number="0")
with asyncio_patch('gns3server.compute.vmware.vmware_vm.VMwareVM.adapter_add_nio_binding') as mock:
response = await compute_client.post(url, json=params)
assert mock.called
args, kwgars = mock.call_args
assert args[0] == 0
assert response.status_code == status.HTTP_201_CREATED
assert response.json()["type"] == "nio_udp"
# @pytest.mark.asyncio
# async def test_vmware_nio_update_udp(app: FastAPI, compute_client: AsyncClient, vm):
#
# params = {
# "type": "nio_udp",
# "lport": 4242,
# "rport": 4343,
# "rhost": "127.0.0.1",
# "filters": {}
# }
#
# with asyncio_patch('gns3server.compute.vmware.vmware_vm.VMwareVM._ubridge_send'):
# with asyncio_patch('gns3server.compute.vmware.vmware_vm.VMwareVM.ethernet_adapters'):
# with patch('gns3server.compute.vmware.vmware_vm.VMwareVM._get_vnet') as mock:
# response = await compute_client.put("/projects/{project_id}/vmware/nodes/{node_id}/adapters/0/ports/0/nio".format(project_id=vm["project_id"], node_id=vm["node_id"]), params)
# assert response.status_code == status.HTTP_201_CREATED
# assert response.json()["type"] == "nio_udp"
async def test_vmware_delete_nio(app: FastAPI, compute_client: AsyncClient, vm: dict) -> None:
url = app.url_path_for("compute:delete_vmware_node_nio",
project_id=vm["project_id"],
node_id=vm["node_id"],
adapter_number="0",
port_number="0")
with asyncio_patch('gns3server.compute.vmware.vmware_vm.VMwareVM.adapter_remove_nio_binding') as mock:
response = await compute_client.delete(url)
assert mock.called
args, kwgars = mock.call_args
assert args[0] == 0
assert response.status_code == status.HTTP_204_NO_CONTENT
async def test_vmware_update(app: FastAPI, compute_client: AsyncClient, vm: dict, free_console_port: int) -> None:
params = {
"name": "test",
"console": free_console_port
}
response = await compute_client.put(app.url_path_for("compute:update_vmware_node",
project_id=vm["project_id"],
node_id=vm["node_id"]), json=params)
assert response.status_code == status.HTTP_200_OK
assert response.json()["name"] == "test"
assert response.json()["console"] == free_console_port
async def test_vmware_start_capture(app: FastAPI, compute_client: AsyncClient, vm: dict) -> None:
params = {
"capture_file_name": "test.pcap",
"data_link_type": "DLT_EN10MB"
}
url = app.url_path_for("compute:start_vmware_node_capture",
project_id=vm["project_id"],
node_id=vm["node_id"],
adapter_number="0",
port_number="0")
with patch("gns3server.compute.vmware.vmware_vm.VMwareVM.is_running", return_value=True):
with asyncio_patch("gns3server.compute.vmware.vmware_vm.VMwareVM.start_capture") as mock:
response = await compute_client.post(url, json=params)
assert response.status_code == status.HTTP_200_OK
assert mock.called assert mock.called
assert "test.pcap" in response.json()["pcap_file_path"]
async def test_vmware_stop_capture(app: FastAPI, compute_client: AsyncClient, vm: dict) -> None:
url = app.url_path_for("compute:stop_vmware_node_capture",
project_id=vm["project_id"],
node_id=vm["node_id"],
adapter_number="0",
port_number="0")
with patch("gns3server.compute.vmware.vmware_vm.VMwareVM.is_running", return_value=True):
with asyncio_patch("gns3server.compute.vmware.vmware_vm.VMwareVM.stop_capture") as mock:
response = await compute_client.post(url)
assert response.status_code == status.HTTP_204_NO_CONTENT assert response.status_code == status.HTTP_204_NO_CONTENT
async def test_vmware_stop(self, app: FastAPI, compute_client: AsyncClient, vm: dict) -> None:
with asyncio_patch("gns3server.compute.vmware.vmware_vm.VMwareVM.stop", return_value=True) as mock:
response = await compute_client.post(app.url_path_for("compute:stop_vmware_node",
project_id=vm["project_id"],
node_id=vm["node_id"]))
assert mock.called assert mock.called
assert response.status_code == status.HTTP_204_NO_CONTENT
# @pytest.mark.asyncio async def test_vmware_suspend(self, app: FastAPI, compute_client: AsyncClient, vm: dict) -> None:
# async def test_vmware_pcap(app: FastAPI, compute_client: AsyncClient, vm, compute_project):
# with asyncio_patch("gns3server.compute.vmware.vmware_vm.VMwareVM.suspend", return_value=True) as mock:
# with asyncio_patch("gns3server.compute.vmware.vmware_vm.VMwareVM.get_nio"): response = await compute_client.post(app.url_path_for("compute:suspend_vmware_node",
# with asyncio_patch("gns3server.compute.vmware.VMware.stream_pcap_file"): project_id=vm["project_id"],
# response = await compute_client.get("/projects/{project_id}/vmware/nodes/{node_id}/adapters/0/ports/0/pcap".format(project_id=compute_project.id, node_id=vm["node_id"]), raw=True) node_id=vm["node_id"]))
# assert response.status_code == status.HTTP_200_OK assert mock.called
assert response.status_code == status.HTTP_204_NO_CONTENT
async def test_vmware_resume(self, app: FastAPI, compute_client: AsyncClient, vm: dict) -> None:
with asyncio_patch("gns3server.compute.vmware.vmware_vm.VMwareVM.resume", return_value=True) as mock:
response = await compute_client.post(app.url_path_for("compute:resume_vmware_node",
project_id=vm["project_id"],
node_id=vm["node_id"]))
assert mock.called
assert response.status_code == status.HTTP_204_NO_CONTENT
async def test_vmware_reload(self, app: FastAPI, compute_client: AsyncClient, vm: dict) -> None:
with asyncio_patch("gns3server.compute.vmware.vmware_vm.VMwareVM.reload", return_value=True) as mock:
response = await compute_client.post(app.url_path_for("compute:reload_vmware_node",
project_id=vm["project_id"],
node_id=vm["node_id"]))
assert mock.called
assert response.status_code == status.HTTP_204_NO_CONTENT
async def test_vmware_nio_create_udp(self, app: FastAPI, compute_client: AsyncClient, vm: dict) -> None:
params = {
"type": "nio_udp",
"lport": 4242,
"rport": 4343,
"rhost": "127.0.0.1"
}
url = app.url_path_for("compute:create_vmware_node_nio",
project_id=vm["project_id"],
node_id=vm["node_id"],
adapter_number="0",
port_number="0")
with asyncio_patch('gns3server.compute.vmware.vmware_vm.VMwareVM.adapter_add_nio_binding') as mock:
response = await compute_client.post(url, json=params)
assert mock.called
args, kwgars = mock.call_args
assert args[0] == 0
assert response.status_code == status.HTTP_201_CREATED
assert response.json()["type"] == "nio_udp"
# @pytest.mark.asyncio
# async def test_vmware_nio_update_udp(self, app: FastAPI, compute_client: AsyncClient, vm):
#
# params = {
# "type": "nio_udp",
# "lport": 4242,
# "rport": 4343,
# "rhost": "127.0.0.1",
# "filters": {}
# }
#
# with asyncio_patch('gns3server.compute.vmware.vmware_vm.VMwareVM._ubridge_send'):
# with asyncio_patch('gns3server.compute.vmware.vmware_vm.VMwareVM.ethernet_adapters'):
# with patch('gns3server.compute.vmware.vmware_vm.VMwareVM._get_vnet') as mock:
# response = await compute_client.put("/projects/{project_id}/vmware/nodes/{node_id}/adapters/0/ports/0/nio".format(project_id=vm["project_id"], node_id=vm["node_id"]), params)
# assert response.status_code == status.HTTP_201_CREATED
# assert response.json()["type"] == "nio_udp"
async def test_vmware_delete_nio(self, app: FastAPI, compute_client: AsyncClient, vm: dict) -> None:
url = app.url_path_for("compute:delete_vmware_node_nio",
project_id=vm["project_id"],
node_id=vm["node_id"],
adapter_number="0",
port_number="0")
with asyncio_patch('gns3server.compute.vmware.vmware_vm.VMwareVM.adapter_remove_nio_binding') as mock:
response = await compute_client.delete(url)
assert mock.called
args, kwgars = mock.call_args
assert args[0] == 0
assert response.status_code == status.HTTP_204_NO_CONTENT
async def test_vmware_update(
self,
app: FastAPI,
compute_client: AsyncClient,
vm: dict,
free_console_port: int
) -> None:
params = {
"name": "test",
"console": free_console_port
}
response = await compute_client.put(app.url_path_for("compute:update_vmware_node",
project_id=vm["project_id"],
node_id=vm["node_id"]), json=params)
assert response.status_code == status.HTTP_200_OK
assert response.json()["name"] == "test"
assert response.json()["console"] == free_console_port
async def test_vmware_start_capture(self, app: FastAPI, compute_client: AsyncClient, vm: dict) -> None:
params = {
"capture_file_name": "test.pcap",
"data_link_type": "DLT_EN10MB"
}
url = app.url_path_for("compute:start_vmware_node_capture",
project_id=vm["project_id"],
node_id=vm["node_id"],
adapter_number="0",
port_number="0")
with patch("gns3server.compute.vmware.vmware_vm.VMwareVM.is_running", return_value=True):
with asyncio_patch("gns3server.compute.vmware.vmware_vm.VMwareVM.start_capture") as mock:
response = await compute_client.post(url, json=params)
assert response.status_code == status.HTTP_200_OK
assert mock.called
assert "test.pcap" in response.json()["pcap_file_path"]
async def test_vmware_stop_capture(self, app: FastAPI, compute_client: AsyncClient, vm: dict) -> None:
url = app.url_path_for("compute:stop_vmware_node_capture",
project_id=vm["project_id"],
node_id=vm["node_id"],
adapter_number="0",
port_number="0")
with patch("gns3server.compute.vmware.vmware_vm.VMwareVM.is_running", return_value=True):
with asyncio_patch("gns3server.compute.vmware.vmware_vm.VMwareVM.stop_capture") as mock:
response = await compute_client.post(url)
assert response.status_code == status.HTTP_204_NO_CONTENT
assert mock.called
# @pytest.mark.asyncio
# async def test_vmware_pcap(self, app: FastAPI, compute_client: AsyncClient, vm, compute_project):
#
# with asyncio_patch("gns3server.compute.vmware.vmware_vm.VMwareVM.get_nio"):
# with asyncio_patch("gns3server.compute.vmware.VMware.stream_pcap_file"):
# response = await compute_client.get("/projects/{project_id}/vmware/nodes/{node_id}/adapters/0/ports/0/pcap".format(project_id=compute_project.id, node_id=vm["node_id"]), raw=True)
# assert response.status_code == status.HTTP_200_OK

View File

@ -28,251 +28,279 @@ from gns3server.compute.project import Project
pytestmark = pytest.mark.asyncio pytestmark = pytest.mark.asyncio
@pytest_asyncio.fixture class TestVPCSNodesRoutes:
async def vm(app: FastAPI, compute_client: AsyncClient, compute_project: Project) -> None:
params = {"name": "PC TEST 1"} @pytest_asyncio.fixture
response = await compute_client.post(app.url_path_for("compute:create_vpcs_node", project_id=compute_project.id), json=params) async def vm(self, app: FastAPI, compute_client: AsyncClient, compute_project: Project) -> None:
assert response.status_code == status.HTTP_201_CREATED
return response.json() params = {"name": "PC TEST 1"}
response = await compute_client.post(app.url_path_for("compute:create_vpcs_node", project_id=compute_project.id), json=params)
assert response.status_code == status.HTTP_201_CREATED
return response.json()
async def test_vpcs_create(app: FastAPI, compute_client: AsyncClient, compute_project: Project) -> None: async def test_vpcs_create(self, app: FastAPI, compute_client: AsyncClient, compute_project: Project) -> None:
params = {"name": "PC TEST 1"} params = {"name": "PC TEST 1"}
response = await compute_client.post(app.url_path_for("compute:create_vpcs_node", project_id=compute_project.id), json=params) response = await compute_client.post(app.url_path_for("compute:create_vpcs_node", project_id=compute_project.id), json=params)
assert response.status_code == status.HTTP_201_CREATED assert response.status_code == status.HTTP_201_CREATED
assert response.json()["name"] == "PC TEST 1" assert response.json()["name"] == "PC TEST 1"
assert response.json()["project_id"] == compute_project.id assert response.json()["project_id"] == compute_project.id
async def test_vpcs_get(app: FastAPI, compute_client: AsyncClient, compute_project: Project, vm: dict) -> None: async def test_vpcs_get(
self,
app: FastAPI,
compute_client: AsyncClient,
compute_project: Project,
vm: dict
) -> None:
response = await compute_client.get(app.url_path_for("compute:get_vpcs_node", project_id=vm["project_id"], node_id=vm["node_id"])) response = await compute_client.get(app.url_path_for("compute:get_vpcs_node", project_id=vm["project_id"], node_id=vm["node_id"]))
assert response.status_code == status.HTTP_200_OK assert response.status_code == status.HTTP_200_OK
assert response.json()["name"] == "PC TEST 1" assert response.json()["name"] == "PC TEST 1"
assert response.json()["project_id"] == compute_project.id assert response.json()["project_id"] == compute_project.id
assert response.json()["status"] == "stopped" assert response.json()["status"] == "stopped"
async def test_vpcs_create_startup_script(app: FastAPI, compute_client: AsyncClient, compute_project: Project) -> None: async def test_vpcs_create_startup_script(
self,
app: FastAPI,
compute_client: AsyncClient,
compute_project: Project
) -> None:
params = { params = {
"name": "PC TEST 1", "name": "PC TEST 1",
"startup_script": "ip 192.168.1.2\necho TEST" "startup_script": "ip 192.168.1.2\necho TEST"
} }
response = await compute_client.post(app.url_path_for("compute:create_vpcs_node", project_id=compute_project.id), json=params) response = await compute_client.post(app.url_path_for("compute:create_vpcs_node", project_id=compute_project.id), json=params)
assert response.status_code == status.HTTP_201_CREATED assert response.status_code == status.HTTP_201_CREATED
assert response.json()["name"] == "PC TEST 1" assert response.json()["name"] == "PC TEST 1"
assert response.json()["project_id"] == compute_project.id assert response.json()["project_id"] == compute_project.id
async def test_vpcs_create_port(app: FastAPI, async def test_vpcs_create_port(
compute_client: AsyncClient, self,
compute_project: Project, app: FastAPI,
free_console_port: int) -> None: compute_client: AsyncClient,
compute_project: Project,
free_console_port: int
) -> None:
params = { params = {
"name": "PC TEST 1", "name": "PC TEST 1",
"console": free_console_port "console": free_console_port
} }
response = await compute_client.post(app.url_path_for("compute:create_vpcs_node", project_id=compute_project.id), json=params) response = await compute_client.post(app.url_path_for("compute:create_vpcs_node", project_id=compute_project.id), json=params)
assert response.status_code == status.HTTP_201_CREATED assert response.status_code == status.HTTP_201_CREATED
assert response.json()["name"] == "PC TEST 1" assert response.json()["name"] == "PC TEST 1"
assert response.json()["project_id"] == compute_project.id assert response.json()["project_id"] == compute_project.id
assert response.json()["console"] == free_console_port assert response.json()["console"] == free_console_port
async def test_vpcs_nio_create_udp(app: FastAPI, compute_client: AsyncClient, vm: dict) -> None: async def test_vpcs_nio_create_udp(self, app: FastAPI, compute_client: AsyncClient, vm: dict) -> None:
params = { params = {
"type": "nio_udp", "type": "nio_udp",
"lport": 4242, "lport": 4242,
"rport": 4343, "rport": 4343,
"rhost": "127.0.0.1" "rhost": "127.0.0.1"
} }
url = app.url_path_for("compute:create_vpcs_node_nio",
project_id=vm["project_id"],
node_id=vm["node_id"],
adapter_number="0",
port_number="0")
with asyncio_patch("gns3server.compute.vpcs.vpcs_vm.VPCSVM.add_ubridge_udp_connection"):
response = await compute_client.post(url, json=params)
assert response.status_code == status.HTTP_201_CREATED
assert response.json()["type"] == "nio_udp"
async def test_vpcs_nio_update_udp(app: FastAPI, compute_client: AsyncClient, vm: dict) -> None:
params = {
"type": "nio_udp",
"lport": 4242,
"rport": 4343,
"rhost": "127.0.0.1"
}
url = app.url_path_for("compute:create_vpcs_node_nio",
project_id=vm["project_id"],
node_id=vm["node_id"],
adapter_number="0",
port_number="0")
with asyncio_patch("gns3server.compute.vpcs.vpcs_vm.VPCSVM.add_ubridge_udp_connection"):
response = await compute_client.post(url, json=params)
assert response.status_code == status.HTTP_201_CREATED
params["filters"] = {}
url = app.url_path_for("compute:update_vpcs_node_nio",
project_id=vm["project_id"],
node_id=vm["node_id"],
adapter_number="0",
port_number="0")
response = await compute_client.put(url, json=params)
assert response.status_code == status.HTTP_201_CREATED
assert response.json()["type"] == "nio_udp"
async def test_vpcs_delete_nio(app: FastAPI, compute_client: AsyncClient, vm: dict) -> None:
params = {
"type": "nio_udp",
"lport": 4242,
"rport": 4343,
"rhost": "127.0.0.1"
}
with asyncio_patch("gns3server.compute.vpcs.vpcs_vm.VPCSVM._ubridge_send"):
url = app.url_path_for("compute:create_vpcs_node_nio", url = app.url_path_for("compute:create_vpcs_node_nio",
project_id=vm["project_id"], project_id=vm["project_id"],
node_id=vm["node_id"], node_id=vm["node_id"],
adapter_number="0", adapter_number="0",
port_number="0") port_number="0")
await compute_client.post(url, json=params)
url = app.url_path_for("compute:delete_vpcs_node_nio", with asyncio_patch("gns3server.compute.vpcs.vpcs_vm.VPCSVM.add_ubridge_udp_connection"):
response = await compute_client.post(url, json=params)
assert response.status_code == status.HTTP_201_CREATED
assert response.json()["type"] == "nio_udp"
async def test_vpcs_nio_update_udp(self, app: FastAPI, compute_client: AsyncClient, vm: dict) -> None:
params = {
"type": "nio_udp",
"lport": 4242,
"rport": 4343,
"rhost": "127.0.0.1"
}
url = app.url_path_for("compute:create_vpcs_node_nio",
project_id=vm["project_id"], project_id=vm["project_id"],
node_id=vm["node_id"], node_id=vm["node_id"],
adapter_number="0", adapter_number="0",
port_number="0") port_number="0")
response = await compute_client.delete(url)
assert response.status_code == status.HTTP_204_NO_CONTENT
with asyncio_patch("gns3server.compute.vpcs.vpcs_vm.VPCSVM.add_ubridge_udp_connection"):
async def test_vpcs_start(app: FastAPI, compute_client: AsyncClient, vm: dict) -> None:
with asyncio_patch("gns3server.compute.vpcs.vpcs_vm.VPCSVM.start", return_value=True) as mock:
response = await compute_client.post(app.url_path_for("compute:start_vpcs_node",
project_id=vm["project_id"],
node_id=vm["node_id"]))
assert mock.called
assert response.status_code == status.HTTP_204_NO_CONTENT
async def test_vpcs_stop(app: FastAPI, compute_client: AsyncClient, vm: dict) -> None:
with asyncio_patch("gns3server.compute.vpcs.vpcs_vm.VPCSVM.stop", return_value=True) as mock:
response = await compute_client.post(app.url_path_for("compute:stop_vpcs_node",
project_id=vm["project_id"],
node_id=vm["node_id"]))
assert mock.called
assert response.status_code == status.HTTP_204_NO_CONTENT
async def test_vpcs_reload(app: FastAPI, compute_client: AsyncClient, vm: dict) -> None:
with asyncio_patch("gns3server.compute.vpcs.vpcs_vm.VPCSVM.reload", return_value=True) as mock:
response = await compute_client.post(app.url_path_for("compute:reload_vpcs_node",
project_id=vm["project_id"],
node_id=vm["node_id"]))
assert mock.called
assert response.status_code == status.HTTP_204_NO_CONTENT
async def test_vpcs_delete(app: FastAPI, compute_client: AsyncClient, vm: dict) -> None:
with asyncio_patch("gns3server.compute.vpcs.VPCS.delete_node", return_value=True) as mock:
response = await compute_client.delete(app.url_path_for("compute:delete_vpcs_node",
project_id=vm["project_id"],
node_id=vm["node_id"]))
assert mock.called
assert response.status_code == status.HTTP_204_NO_CONTENT
async def test_vpcs_duplicate(app: FastAPI, compute_client: AsyncClient, compute_project: Project, vm: dict) -> None:
# create destination node first
params = {"name": "PC TEST 1"}
response = await compute_client.post(app.url_path_for("compute:create_vpcs_node", project_id=compute_project.id), json=params)
assert response.status_code == status.HTTP_201_CREATED
params = {"destination_node_id": response.json()["node_id"]}
response = await compute_client.post(app.url_path_for("compute:duplicate_vpcs_node",
project_id=vm["project_id"],
node_id=vm["node_id"]), json=params)
assert response.status_code == status.HTTP_201_CREATED
async def test_vpcs_update(app: FastAPI, compute_client: AsyncClient, vm: dict, free_console_port: int) -> None:
console_port = free_console_port
params = {
"name": "test",
"console": console_port
}
response = await compute_client.put(app.url_path_for("compute:update_vpcs_node",
project_id=vm["project_id"],
node_id=vm["node_id"]), json=params)
assert response.status_code == status.HTTP_200_OK
assert response.json()["name"] == "test"
assert response.json()["console"] == console_port
async def test_vpcs_start_capture(app: FastAPI, compute_client: AsyncClient, vm: dict) -> None:
params = {
"capture_file_name": "test.pcap",
"data_link_type": "DLT_EN10MB"
}
url = app.url_path_for("compute:start_vpcs_node_capture",
project_id=vm["project_id"],
node_id=vm["node_id"],
adapter_number="0",
port_number="0")
with patch("gns3server.compute.vpcs.vpcs_vm.VPCSVM.is_running", return_value=True):
with asyncio_patch("gns3server.compute.vpcs.vpcs_vm.VPCSVM.start_capture") as mock:
response = await compute_client.post(url, json=params) response = await compute_client.post(url, json=params)
assert response.status_code == status.HTTP_200_OK assert response.status_code == status.HTTP_201_CREATED
params["filters"] = {}
url = app.url_path_for("compute:update_vpcs_node_nio",
project_id=vm["project_id"],
node_id=vm["node_id"],
adapter_number="0",
port_number="0")
response = await compute_client.put(url, json=params)
assert response.status_code == status.HTTP_201_CREATED
assert response.json()["type"] == "nio_udp"
async def test_vpcs_delete_nio(self, app: FastAPI, compute_client: AsyncClient, vm: dict) -> None:
params = {
"type": "nio_udp",
"lport": 4242,
"rport": 4343,
"rhost": "127.0.0.1"
}
with asyncio_patch("gns3server.compute.vpcs.vpcs_vm.VPCSVM._ubridge_send"):
url = app.url_path_for("compute:create_vpcs_node_nio",
project_id=vm["project_id"],
node_id=vm["node_id"],
adapter_number="0",
port_number="0")
await compute_client.post(url, json=params)
url = app.url_path_for("compute:delete_vpcs_node_nio",
project_id=vm["project_id"],
node_id=vm["node_id"],
adapter_number="0",
port_number="0")
response = await compute_client.delete(url)
assert response.status_code == status.HTTP_204_NO_CONTENT
async def test_vpcs_start(self, app: FastAPI, compute_client: AsyncClient, vm: dict) -> None:
with asyncio_patch("gns3server.compute.vpcs.vpcs_vm.VPCSVM.start", return_value=True) as mock:
response = await compute_client.post(app.url_path_for("compute:start_vpcs_node",
project_id=vm["project_id"],
node_id=vm["node_id"]))
assert mock.called assert mock.called
assert "test.pcap" in response.json()["pcap_file_path"]
async def test_vpcs_stop_capture(app: FastAPI, compute_client: AsyncClient, vm: dict) -> None:
url = app.url_path_for("compute:stop_vpcs_node_capture",
project_id=vm["project_id"],
node_id=vm["node_id"],
adapter_number="0",
port_number="0")
with patch("gns3server.compute.vpcs.vpcs_vm.VPCSVM.is_running", return_value=True):
with asyncio_patch("gns3server.compute.vpcs.vpcs_vm.VPCSVM.stop_capture") as mock:
response = await compute_client.post(url)
assert response.status_code == status.HTTP_204_NO_CONTENT assert response.status_code == status.HTTP_204_NO_CONTENT
async def test_vpcs_stop(self, app: FastAPI, compute_client: AsyncClient, vm: dict) -> None:
with asyncio_patch("gns3server.compute.vpcs.vpcs_vm.VPCSVM.stop", return_value=True) as mock:
response = await compute_client.post(app.url_path_for("compute:stop_vpcs_node",
project_id=vm["project_id"],
node_id=vm["node_id"]))
assert mock.called assert mock.called
assert response.status_code == status.HTTP_204_NO_CONTENT
# @pytest.mark.asyncio async def test_vpcs_reload(self, app: FastAPI, compute_client: AsyncClient, vm: dict) -> None:
# async def test_vpcs_pcap(app: FastAPI, compute_client: AsyncClient, vm, compute_project: Project):
# with asyncio_patch("gns3server.compute.vpcs.vpcs_vm.VPCSVM.reload", return_value=True) as mock:
# with asyncio_patch("gns3server.compute.vpcs.vpcs_vm.VPCSVM.get_nio"): response = await compute_client.post(app.url_path_for("compute:reload_vpcs_node",
# with asyncio_patch("gns3server.compute.vpcs.VPCS.stream_pcap_file"): project_id=vm["project_id"],
# response = await compute_client.get("/projects/{project_id}/vpcs/nodes/{node_id}/adapters/0/ports/0/pcap".format(project_id=compute_project.id, node_id=vm["node_id"]), raw=True) node_id=vm["node_id"]))
# assert response.status_code == status.HTTP_200_OK assert mock.called
assert response.status_code == status.HTTP_204_NO_CONTENT
async def test_vpcs_delete(self, app: FastAPI, compute_client: AsyncClient, vm: dict) -> None:
with asyncio_patch("gns3server.compute.vpcs.VPCS.delete_node", return_value=True) as mock:
response = await compute_client.delete(app.url_path_for("compute:delete_vpcs_node",
project_id=vm["project_id"],
node_id=vm["node_id"]))
assert mock.called
assert response.status_code == status.HTTP_204_NO_CONTENT
async def test_vpcs_duplicate(
self,
app: FastAPI,
compute_client: AsyncClient,
compute_project: Project,
vm: dict
) -> None:
# create destination node first
params = {"name": "PC TEST 1"}
response = await compute_client.post(app.url_path_for("compute:create_vpcs_node", project_id=compute_project.id), json=params)
assert response.status_code == status.HTTP_201_CREATED
params = {"destination_node_id": response.json()["node_id"]}
response = await compute_client.post(app.url_path_for("compute:duplicate_vpcs_node",
project_id=vm["project_id"],
node_id=vm["node_id"]), json=params)
assert response.status_code == status.HTTP_201_CREATED
async def test_vpcs_update(
self,
app: FastAPI,
compute_client: AsyncClient,
vm: dict,
free_console_port: int
) -> None:
console_port = free_console_port
params = {
"name": "test",
"console": console_port
}
response = await compute_client.put(app.url_path_for("compute:update_vpcs_node",
project_id=vm["project_id"],
node_id=vm["node_id"]), json=params)
assert response.status_code == status.HTTP_200_OK
assert response.json()["name"] == "test"
assert response.json()["console"] == console_port
async def test_vpcs_start_capture(self, app: FastAPI, compute_client: AsyncClient, vm: dict) -> None:
params = {
"capture_file_name": "test.pcap",
"data_link_type": "DLT_EN10MB"
}
url = app.url_path_for("compute:start_vpcs_node_capture",
project_id=vm["project_id"],
node_id=vm["node_id"],
adapter_number="0",
port_number="0")
with patch("gns3server.compute.vpcs.vpcs_vm.VPCSVM.is_running", return_value=True):
with asyncio_patch("gns3server.compute.vpcs.vpcs_vm.VPCSVM.start_capture") as mock:
response = await compute_client.post(url, json=params)
assert response.status_code == status.HTTP_200_OK
assert mock.called
assert "test.pcap" in response.json()["pcap_file_path"]
async def test_vpcs_stop_capture(self, app: FastAPI, compute_client: AsyncClient, vm: dict) -> None:
url = app.url_path_for("compute:stop_vpcs_node_capture",
project_id=vm["project_id"],
node_id=vm["node_id"],
adapter_number="0",
port_number="0")
with patch("gns3server.compute.vpcs.vpcs_vm.VPCSVM.is_running", return_value=True):
with asyncio_patch("gns3server.compute.vpcs.vpcs_vm.VPCSVM.stop_capture") as mock:
response = await compute_client.post(url)
assert response.status_code == status.HTTP_204_NO_CONTENT
assert mock.called
# @pytest.mark.asyncio
# async def test_vpcs_pcap(self, app: FastAPI, compute_client: AsyncClient, vm, compute_project: Project):
#
# with asyncio_patch("gns3server.compute.vpcs.vpcs_vm.VPCSVM.get_nio"):
# with asyncio_patch("gns3server.compute.vpcs.VPCS.stream_pcap_file"):
# response = await compute_client.get("/projects/{project_id}/vpcs/nodes/{node_id}/adapters/0/ports/0/pcap".format(project_id=compute_project.id, node_id=vm["node_id"]), raw=True)
# assert response.status_code == status.HTTP_200_OK

View File

@ -27,43 +27,45 @@ from gns3server.config import Config
pytestmark = pytest.mark.asyncio pytestmark = pytest.mark.asyncio
async def test_shutdown_local(app: FastAPI, client: AsyncClient, config: Config) -> None: class TestControllerRoutes:
os.kill = MagicMock() async def test_shutdown_local(self, app: FastAPI, client: AsyncClient, config: Config) -> None:
config.settings.Server.local = True
response = await client.post(app.url_path_for("shutdown")) os.kill = MagicMock()
assert response.status_code == status.HTTP_204_NO_CONTENT config.settings.Server.local = True
assert os.kill.called response = await client.post(app.url_path_for("shutdown"))
assert response.status_code == status.HTTP_204_NO_CONTENT
assert os.kill.called
async def test_shutdown_non_local(app: FastAPI, client: AsyncClient, config: Config) -> None: async def test_shutdown_non_local(self, app: FastAPI, client: AsyncClient, config: Config) -> None:
response = await client.post(app.url_path_for("shutdown")) response = await client.post(app.url_path_for("shutdown"))
assert response.status_code == status.HTTP_403_FORBIDDEN assert response.status_code == status.HTTP_403_FORBIDDEN
# @pytest.mark.asyncio # @pytest.mark.asyncio
# async def test_debug(controller_api, config, tmpdir): # async def test_debug(controller_api, config, tmpdir):
# #
# config._main_config_file = str(tmpdir / "test.conf") # config._main_config_file = str(tmpdir / "test.conf")
# config.set("Server", "local", True) # config.set("Server", "local", True)
# response = await controller_api.post('/debug') # response = await controller_api.post('/debug')
# assert response.status_code == 201 # assert response.status_code == 201
# debug_dir = os.path.join(config.config_dir, "debug") # debug_dir = os.path.join(config.config_dir, "debug")
# assert os.path.exists(debug_dir) # assert os.path.exists(debug_dir)
# assert os.path.exists(os.path.join(debug_dir, "controller.txt")) # assert os.path.exists(os.path.join(debug_dir, "controller.txt"))
# #
# #
# @pytest.mark.asyncio # @pytest.mark.asyncio
# async def test_debug_non_local(controller_api, config, tmpdir): # async def test_debug_non_local(controller_api, config, tmpdir):
# #
# config._main_config_file = str(tmpdir / "test.conf") # config._main_config_file = str(tmpdir / "test.conf")
# config.set("Server", "local", False) # config.set("Server", "local", False)
# response = await controller_api.post('/debug') # response = await controller_api.post('/debug')
# assert response.status_code == 403 # assert response.status_code == 403
async def test_statistics_output(app: FastAPI, client: AsyncClient) -> None: async def test_statistics_output(self, app: FastAPI, client: AsyncClient) -> None:
response = await client.get(app.url_path_for("statistics")) response = await client.get(app.url_path_for("statistics"))
assert response.status_code == status.HTTP_200_OK assert response.status_code == status.HTTP_200_OK

View File

@ -26,89 +26,91 @@ from gns3server.controller.project import Project
pytestmark = pytest.mark.asyncio pytestmark = pytest.mark.asyncio
async def test_create_drawing(app: FastAPI, client: AsyncClient, project: Project) -> None: class TestDrawingsRoutes:
params = { async def test_create_drawing(self, app: FastAPI, client: AsyncClient, project: Project) -> None:
"svg": '<svg height="210" width="500"><line x1="0" y1="0" x2="200" y2="200" style="stroke:rgb(255,0,0);stroke-width:2" /></svg>',
"x": 10,
"y": 20,
"z": 0
}
response = await client.post(app.url_path_for("create_drawing", project_id=project.id), json=params) params = {
assert response.status_code == status.HTTP_201_CREATED "svg": '<svg height="210" width="500"><line x1="0" y1="0" x2="200" y2="200" style="stroke:rgb(255,0,0);stroke-width:2" /></svg>',
assert response.json()["drawing_id"] is not None "x": 10,
"y": 20,
"z": 0
}
response = await client.post(app.url_path_for("create_drawing", project_id=project.id), json=params)
assert response.status_code == status.HTTP_201_CREATED
assert response.json()["drawing_id"] is not None
async def test_get_drawing(app: FastAPI, client: AsyncClient, project: Project) -> None: async def test_get_drawing(self, app: FastAPI, client: AsyncClient, project: Project) -> None:
params = { params = {
"svg": '<svg height="210" width="500"><line x1="0" y1="0" x2="200" y2="200" style="stroke:rgb(255,0,0);stroke-width:2" /></svg>', "svg": '<svg height="210" width="500"><line x1="0" y1="0" x2="200" y2="200" style="stroke:rgb(255,0,0);stroke-width:2" /></svg>',
"x": 10, "x": 10,
"y": 20, "y": 20,
"z": 0 "z": 0
} }
response = await client.post(app.url_path_for("create_drawing", project_id=project.id), json=params) response = await client.post(app.url_path_for("create_drawing", project_id=project.id), json=params)
response = await client.get(app.url_path_for( response = await client.get(app.url_path_for(
"get_drawing", "get_drawing",
project_id=project.id, project_id=project.id,
drawing_id=response.json()["drawing_id"]) drawing_id=response.json()["drawing_id"])
) )
assert response.status_code == 200 assert response.status_code == 200
assert response.json()["x"] == 10 assert response.json()["x"] == 10
async def test_update_drawing(app: FastAPI, client: AsyncClient, project: Project) -> None: async def test_update_drawing(self, app: FastAPI, client: AsyncClient, project: Project) -> None:
params = { params = {
"svg": '<svg height="210" width="500"><line x1="0" y1="0" x2="200" y2="200" style="stroke:rgb(255,0,0);stroke-width:2" /></svg>', "svg": '<svg height="210" width="500"><line x1="0" y1="0" x2="200" y2="200" style="stroke:rgb(255,0,0);stroke-width:2" /></svg>',
"x": 10, "x": 10,
"y": 20, "y": 20,
"z": 0 "z": 0
} }
response = await client.post(app.url_path_for("create_drawing", project_id=project.id), json=params) response = await client.post(app.url_path_for("create_drawing", project_id=project.id), json=params)
response = await client.put(app.url_path_for( response = await client.put(app.url_path_for(
"update_drawing", "update_drawing",
project_id=project.id, project_id=project.id,
drawing_id=response.json()["drawing_id"]), drawing_id=response.json()["drawing_id"]),
json={"x": 42} json={"x": 42}
) )
assert response.status_code == status.HTTP_200_OK assert response.status_code == status.HTTP_200_OK
assert response.json()["x"] == 42 assert response.json()["x"] == 42
async def test_all_drawings(app: FastAPI, client: AsyncClient, project: Project) -> None: async def test_all_drawings(self, app: FastAPI, client: AsyncClient, project: Project) -> None:
params = { params = {
"svg": '<svg height="210" width="500"><line x1="0" y1="0" x2="200" y2="200" style="stroke:rgb(255,0,0);stroke-width:2" /></svg>', "svg": '<svg height="210" width="500"><line x1="0" y1="0" x2="200" y2="200" style="stroke:rgb(255,0,0);stroke-width:2" /></svg>',
"x": 10, "x": 10,
"y": 20, "y": 20,
"z": 0 "z": 0
} }
await client.post(app.url_path_for("create_drawing", project_id=project.id), json=params) await client.post(app.url_path_for("create_drawing", project_id=project.id), json=params)
response = await client.get(app.url_path_for("get_drawings", project_id=project.id)) response = await client.get(app.url_path_for("get_drawings", project_id=project.id))
assert response.status_code == status.HTTP_200_OK assert response.status_code == status.HTTP_200_OK
assert len(response.json()) == 1 assert len(response.json()) == 1
# test listing links from a closed project # test listing links from a closed project
await project.close(ignore_notification=True) await project.close(ignore_notification=True)
response = await client.get(app.url_path_for("get_drawings", project_id=project.id)) response = await client.get(app.url_path_for("get_drawings", project_id=project.id))
assert response.status_code == status.HTTP_200_OK assert response.status_code == status.HTTP_200_OK
assert len(response.json()) == 1 assert len(response.json()) == 1
async def test_delete_drawing(app: FastAPI, client: AsyncClient, project: Project) -> None: async def test_delete_drawing(self, app: FastAPI, client: AsyncClient, project: Project) -> None:
drawing = Drawing(project) drawing = Drawing(project)
project._drawings = {drawing.id: drawing} project._drawings = {drawing.id: drawing}
response = await client.delete(app.url_path_for( response = await client.delete(app.url_path_for(
"delete_drawing", "delete_drawing",
project_id=project.id, project_id=project.id,
drawing_id=drawing.id) drawing_id=drawing.id)
) )
assert response.status_code == status.HTTP_204_NO_CONTENT assert response.status_code == status.HTTP_204_NO_CONTENT
assert drawing.id not in project.drawings assert drawing.id not in project.drawings

View File

@ -24,32 +24,34 @@ from tests.utils import asyncio_patch
pytestmark = pytest.mark.asyncio pytestmark = pytest.mark.asyncio
async def test_list_vms(app: FastAPI, client: AsyncClient) -> None: class TestGNS3VMRoutes:
with asyncio_patch("gns3server.controller.gns3vm.vmware_gns3_vm.VMwareGNS3VM.list", return_value=[{"vmname": "test"}]): async def test_list_vms(self, app: FastAPI, client: AsyncClient) -> None:
response = await client.get(app.url_path_for("get_vms", engine="vmware"))
assert response.status_code == status.HTTP_200_OK with asyncio_patch("gns3server.controller.gns3vm.vmware_gns3_vm.VMwareGNS3VM.list", return_value=[{"vmname": "test"}]):
assert response.json() == [ response = await client.get(app.url_path_for("get_vms", engine="vmware"))
{ assert response.status_code == status.HTTP_200_OK
"vmname": "test" assert response.json() == [
} {
] "vmname": "test"
}
]
async def test_engines(app: FastAPI, client: AsyncClient) -> None: async def test_engines(self, app: FastAPI, client: AsyncClient) -> None:
response = await client.get(app.url_path_for("get_engines")) response = await client.get(app.url_path_for("get_engines"))
assert response.status_code == status.HTTP_200_OK assert response.status_code == status.HTTP_200_OK
assert len(response.json()) > 0 assert len(response.json()) > 0
async def test_put_gns3vm(app: FastAPI, client: AsyncClient) -> None: async def test_put_gns3vm(self, app: FastAPI, client: AsyncClient) -> None:
response = await client.put(app.url_path_for("update_gns3vm_settings"), json={"vmname": "TEST VM"}) response = await client.put(app.url_path_for("update_gns3vm_settings"), json={"vmname": "TEST VM"})
assert response.status_code == status.HTTP_200_OK assert response.status_code == status.HTTP_200_OK
assert response.json()["vmname"] == "TEST VM" assert response.json()["vmname"] == "TEST VM"
async def test_get_gns3vm(app: FastAPI, client: AsyncClient) -> None: async def test_get_gns3vm(self, app: FastAPI, client: AsyncClient) -> None:
response = await client.get(app.url_path_for("get_gns3vm_settings")) response = await client.get(app.url_path_for("get_gns3vm_settings"))
assert response.status_code == status.HTTP_200_OK assert response.status_code == status.HTTP_200_OK

View File

@ -35,30 +35,88 @@ from gns3server.controller.udp_link import UDPLink
pytestmark = pytest.mark.asyncio pytestmark = pytest.mark.asyncio
@pytest_asyncio.fixture class TestLinkRoutes:
async def nodes(compute: Compute, project: Project) -> Tuple[Node, Node]:
response = MagicMock() @pytest_asyncio.fixture
response.json = {"console": 2048} async def nodes(self, compute: Compute, project: Project) -> Tuple[Node, Node]:
compute.post = AsyncioMagicMock(return_value=response)
node1 = await project.add_node(compute, "node1", None, node_type="qemu") response = MagicMock()
node1._ports = [EthernetPort("E0", 0, 0, 3)] response.json = {"console": 2048}
node2 = await project.add_node(compute, "node2", None, node_type="qemu") compute.post = AsyncioMagicMock(return_value=response)
node2._ports = [EthernetPort("E0", 0, 2, 4)]
return node1, node2 node1 = await project.add_node(compute, "node1", None, node_type="qemu")
node1._ports = [EthernetPort("E0", 0, 0, 3)]
node2 = await project.add_node(compute, "node2", None, node_type="qemu")
node2._ports = [EthernetPort("E0", 0, 2, 4)]
return node1, node2
async def test_create_link(app: FastAPI, client: AsyncClient, project: Project, nodes: Tuple[Node, Node]) -> None: async def test_create_link(
self,
app: FastAPI,
client: AsyncClient,
project: Project,
nodes: Tuple[Node, Node]
) -> None:
node1, node2 = nodes node1, node2 = nodes
filters = { filters = {
"latency": [10], "latency": [10],
"frequency_drop": [50] "frequency_drop": [50]
} }
with asyncio_patch("gns3server.controller.udp_link.UDPLink.create") as mock:
response = await client.post(app.url_path_for("create_link", project_id=project.id), json={
"nodes": [
{
"node_id": node1.id,
"adapter_number": 0,
"port_number": 3,
"label": {
"text": "Text",
"x": 42,
"y": 0
}
},
{
"node_id": node2.id,
"adapter_number": 2,
"port_number": 4
}
],
"filters": filters
})
assert mock.called
assert response.status_code == status.HTTP_201_CREATED
assert response.json()["link_id"] is not None
assert len(response.json()["nodes"]) == 2
assert response.json()["nodes"][0]["label"]["x"] == 42
assert len(project.links) == 1
assert list(project.links.values())[0].filters == filters
async def test_create_link_failure(
self,
app: FastAPI,
client: AsyncClient,
compute: Compute,
project: Project
) -> None:
"""
Make sure the link is deleted if we failed to create it.
The failure is triggered by connecting the link to itself
"""
response = MagicMock()
response.json = {"console": 2048}
compute.post = AsyncioMagicMock(return_value=response)
node1 = await project.add_node(compute, "node1", None, node_type="qemu")
node1._ports = [EthernetPort("E0", 0, 0, 3), EthernetPort("E0", 0, 0, 4)]
with asyncio_patch("gns3server.controller.udp_link.UDPLink.create") as mock:
response = await client.post(app.url_path_for("create_link", project_id=project.id), json={ response = await client.post(app.url_path_for("create_link", project_id=project.id), json={
"nodes": [ "nodes": [
{ {
@ -71,6 +129,168 @@ async def test_create_link(app: FastAPI, client: AsyncClient, project: Project,
"y": 0 "y": 0
} }
}, },
{
"node_id": node1.id,
"adapter_number": 0,
"port_number": 4
}
]
})
assert response.status_code == status.HTTP_409_CONFLICT
assert len(project.links) == 0
async def test_get_link(
self,
app: FastAPI,
client: AsyncClient,
project: Project,
nodes: Tuple[Node, Node]
) -> None:
node1, node2 = nodes
with asyncio_patch("gns3server.controller.udp_link.UDPLink.create") as mock:
response = await client.post(app.url_path_for("create_link", project_id=project.id), json={
"nodes": [
{
"node_id": node1.id,
"adapter_number": 0,
"port_number": 3,
"label": {
"text": "Text",
"x": 42,
"y": 0
}
},
{
"node_id": node2.id,
"adapter_number": 2,
"port_number": 4
}
]
})
assert mock.called
link_id = response.json()["link_id"]
assert response.json()["nodes"][0]["label"]["x"] == 42
response = await client.get(app.url_path_for("get_link", project_id=project.id, link_id=link_id))
assert response.status_code == status.HTTP_200_OK
assert response.json()["nodes"][0]["label"]["x"] == 42
async def test_update_link_suspend(
self,
app: FastAPI,
client: AsyncClient,
project: Project,
nodes: Tuple[Node, Node]
) -> None:
node1, node2 = nodes
with asyncio_patch("gns3server.controller.udp_link.UDPLink.create") as mock:
response = await client.post(app.url_path_for("create_link", project_id=project.id), json={
"nodes": [
{
"node_id": node1.id,
"adapter_number": 0,
"port_number": 3,
"label": {
"text": "Text",
"x": 42,
"y": 0
}
},
{
"node_id": node2.id,
"adapter_number": 2,
"port_number": 4
}
]
})
assert mock.called
link_id = response.json()["link_id"]
assert response.json()["nodes"][0]["label"]["x"] == 42
response = await client.put(app.url_path_for("update_link", project_id=project.id, link_id=link_id), json={
"nodes": [
{
"node_id": node1.id,
"adapter_number": 0,
"port_number": 3,
"label": {
"text": "Hello",
"x": 64,
"y": 0
}
},
{
"node_id": node2.id,
"adapter_number": 2,
"port_number": 4
}
],
"suspend": True
})
assert response.status_code == status.HTTP_200_OK
assert response.json()["nodes"][0]["label"]["x"] == 64
assert response.json()["suspend"]
assert response.json()["filters"] == {}
async def test_update_link(
self,
app: FastAPI,
client: AsyncClient,
project: Project,
nodes: Tuple[Node, Node]
) -> None:
filters = {
"latency": [10],
"frequency_drop": [50]
}
node1, node2 = nodes
with asyncio_patch("gns3server.controller.udp_link.UDPLink.create") as mock:
response = await client.post(app.url_path_for("create_link", project_id=project.id), json={
"nodes": [
{
"node_id": node1.id,
"adapter_number": 0,
"port_number": 3,
"label": {
"text": "Text",
"x": 42,
"y": 0
}
},
{
"node_id": node2.id,
"adapter_number": 2,
"port_number": 4
}
]
})
assert mock.called
link_id = response.json()["link_id"]
assert response.json()["nodes"][0]["label"]["x"] == 42
response = await client.put(app.url_path_for("update_link", project_id=project.id, link_id=link_id), json={
"nodes": [
{
"node_id": node1.id,
"adapter_number": 0,
"port_number": 3,
"label": {
"text": "Hello",
"x": 64,
"y": 0
}
},
{ {
"node_id": node2.id, "node_id": node2.id,
"adapter_number": 2, "adapter_number": 2,
@ -80,308 +300,126 @@ async def test_create_link(app: FastAPI, client: AsyncClient, project: Project,
"filters": filters "filters": filters
}) })
assert mock.called assert response.status_code == status.HTTP_200_OK
assert response.status_code == status.HTTP_201_CREATED assert response.json()["nodes"][0]["label"]["x"] == 64
assert response.json()["link_id"] is not None assert list(project.links.values())[0].filters == filters
assert len(response.json()["nodes"]) == 2
assert response.json()["nodes"][0]["label"]["x"] == 42
assert len(project.links) == 1
assert list(project.links.values())[0].filters == filters
async def test_create_link_failure(app: FastAPI, client: AsyncClient, compute: Compute, project: Project) -> None: async def test_list_link(
""" self,
Make sure the link is deleted if we failed to create it. app: FastAPI,
client: AsyncClient,
project: Project,
nodes: Tuple[Node, Node]
) -> None:
The failure is triggered by connecting the link to itself filters = {
""" "latency": [10],
"frequency_drop": [50]
}
response = MagicMock() node1, node2 = nodes
response.json = {"console": 2048} nodes = [
compute.post = AsyncioMagicMock(return_value=response)
node1 = await project.add_node(compute, "node1", None, node_type="qemu")
node1._ports = [EthernetPort("E0", 0, 0, 3), EthernetPort("E0", 0, 0, 4)]
response = await client.post(app.url_path_for("create_link", project_id=project.id), json={
"nodes": [
{ {
"node_id": node1.id, "node_id": node1.id,
"adapter_number": 0, "adapter_number": 0,
"port_number": 3, "port_number": 3
"label": {
"text": "Text",
"x": 42,
"y": 0
}
}, },
{ {
"node_id": node1.id, "node_id": node2.id,
"adapter_number": 0, "adapter_number": 2,
"port_number": 4 "port_number": 4
} }
] ]
}) with asyncio_patch("gns3server.controller.udp_link.UDPLink.create") as mock:
await client.post(app.url_path_for("create_link", project_id=project.id), json={
"nodes": nodes,
"filters": filters
})
assert response.status_code == status.HTTP_409_CONFLICT
assert len(project.links) == 0
async def test_get_link(app: FastAPI, client: AsyncClient, project: Project, nodes: Tuple[Node, Node]) -> None:
node1, node2 = nodes
with asyncio_patch("gns3server.controller.udp_link.UDPLink.create") as mock:
response = await client.post(app.url_path_for("create_link", project_id=project.id), json={
"nodes": [
{
"node_id": node1.id,
"adapter_number": 0,
"port_number": 3,
"label": {
"text": "Text",
"x": 42,
"y": 0
}
},
{
"node_id": node2.id,
"adapter_number": 2,
"port_number": 4
}
]
})
assert mock.called
link_id = response.json()["link_id"]
assert response.json()["nodes"][0]["label"]["x"] == 42
response = await client.get(app.url_path_for("get_link", project_id=project.id, link_id=link_id))
assert response.status_code == status.HTTP_200_OK
assert response.json()["nodes"][0]["label"]["x"] == 42
async def test_update_link_suspend(app: FastAPI, client: AsyncClient, project: Project, nodes: Tuple[Node, Node]) -> None:
node1, node2 = nodes
with asyncio_patch("gns3server.controller.udp_link.UDPLink.create") as mock:
response = await client.post(app.url_path_for("create_link", project_id=project.id), json={
"nodes": [
{
"node_id": node1.id,
"adapter_number": 0,
"port_number": 3,
"label": {
"text": "Text",
"x": 42,
"y": 0
}
},
{
"node_id": node2.id,
"adapter_number": 2,
"port_number": 4
}
]
})
assert mock.called
link_id = response.json()["link_id"]
assert response.json()["nodes"][0]["label"]["x"] == 42
response = await client.put(app.url_path_for("update_link", project_id=project.id, link_id=link_id), json={
"nodes": [
{
"node_id": node1.id,
"adapter_number": 0,
"port_number": 3,
"label": {
"text": "Hello",
"x": 64,
"y": 0
}
},
{
"node_id": node2.id,
"adapter_number": 2,
"port_number": 4
}
],
"suspend": True
})
assert response.status_code == status.HTTP_200_OK
assert response.json()["nodes"][0]["label"]["x"] == 64
assert response.json()["suspend"]
assert response.json()["filters"] == {}
async def test_update_link(app: FastAPI, client: AsyncClient, project: Project, nodes: Tuple[Node, Node]) -> None:
filters = {
"latency": [10],
"frequency_drop": [50]
}
node1, node2 = nodes
with asyncio_patch("gns3server.controller.udp_link.UDPLink.create") as mock:
response = await client.post(app.url_path_for("create_link", project_id=project.id), json={
"nodes": [
{
"node_id": node1.id,
"adapter_number": 0,
"port_number": 3,
"label": {
"text": "Text",
"x": 42,
"y": 0
}
},
{
"node_id": node2.id,
"adapter_number": 2,
"port_number": 4
}
]
})
assert mock.called
link_id = response.json()["link_id"]
assert response.json()["nodes"][0]["label"]["x"] == 42
response = await client.put(app.url_path_for("update_link", project_id=project.id, link_id=link_id), json={
"nodes": [
{
"node_id": node1.id,
"adapter_number": 0,
"port_number": 3,
"label": {
"text": "Hello",
"x": 64,
"y": 0
}
},
{
"node_id": node2.id,
"adapter_number": 2,
"port_number": 4
}
],
"filters": filters
})
assert response.status_code == status.HTTP_200_OK
assert response.json()["nodes"][0]["label"]["x"] == 64
assert list(project.links.values())[0].filters == filters
async def test_list_link(app: FastAPI, client: AsyncClient, project: Project, nodes: Tuple[Node, Node]) -> None:
filters = {
"latency": [10],
"frequency_drop": [50]
}
node1, node2 = nodes
nodes = [
{
"node_id": node1.id,
"adapter_number": 0,
"port_number": 3
},
{
"node_id": node2.id,
"adapter_number": 2,
"port_number": 4
}
]
with asyncio_patch("gns3server.controller.udp_link.UDPLink.create") as mock:
await client.post(app.url_path_for("create_link", project_id=project.id), json={
"nodes": nodes,
"filters": filters
})
assert mock.called
response = await client.get(app.url_path_for("get_links", project_id=project.id))
assert response.status_code == status.HTTP_200_OK
assert len(response.json()) == 1
assert response.json()[0]["filters"] == filters
# test listing links from a closed project
await project.close(ignore_notification=True)
response = await client.get(app.url_path_for("get_links", project_id=project.id))
assert response.status_code == status.HTTP_200_OK
assert len(response.json()) == 1
assert response.json()[0]["filters"] == filters
async def test_reset_link(app: FastAPI, client: AsyncClient, project: Project) -> None:
link = UDPLink(project)
project._links = {link.id: link}
with asyncio_patch("gns3server.controller.udp_link.UDPLink.delete") as delete_mock:
with asyncio_patch("gns3server.controller.udp_link.UDPLink.create") as create_mock:
response = await client.post(app.url_path_for("reset_link", project_id=project.id, link_id=link.id))
assert delete_mock.called
assert create_mock.called
assert response.status_code == status.HTTP_200_OK
async def test_start_capture(app: FastAPI, client: AsyncClient, project: Project) -> None:
link = Link(project)
project._links = {link.id: link}
with asyncio_patch("gns3server.controller.link.Link.start_capture") as mock:
response = await client.post(app.url_path_for("start_capture", project_id=project.id, link_id=link.id), json={})
assert mock.called assert mock.called
assert response.status_code == status.HTTP_201_CREATED response = await client.get(app.url_path_for("get_links", project_id=project.id))
assert response.status_code == status.HTTP_200_OK
assert len(response.json()) == 1
assert response.json()[0]["filters"] == filters
# test listing links from a closed project
await project.close(ignore_notification=True)
response = await client.get(app.url_path_for("get_links", project_id=project.id))
assert response.status_code == status.HTTP_200_OK
assert len(response.json()) == 1
assert response.json()[0]["filters"] == filters
async def test_stop_capture(app: FastAPI, client: AsyncClient, project: Project) -> None: async def test_reset_link(self, app: FastAPI, client: AsyncClient, project: Project) -> None:
link = Link(project) link = UDPLink(project)
project._links = {link.id: link} project._links = {link.id: link}
with asyncio_patch("gns3server.controller.link.Link.stop_capture") as mock: with asyncio_patch("gns3server.controller.udp_link.UDPLink.delete") as delete_mock:
response = await client.post(app.url_path_for("stop_capture", project_id=project.id, link_id=link.id)) with asyncio_patch("gns3server.controller.udp_link.UDPLink.create") as create_mock:
response = await client.post(app.url_path_for("reset_link", project_id=project.id, link_id=link.id))
assert delete_mock.called
assert create_mock.called
assert response.status_code == status.HTTP_200_OK
async def test_start_capture(self, app: FastAPI, client: AsyncClient, project: Project) -> None:
link = Link(project)
project._links = {link.id: link}
with asyncio_patch("gns3server.controller.link.Link.start_capture") as mock:
response = await client.post(app.url_path_for("start_capture", project_id=project.id, link_id=link.id), json={})
assert mock.called
assert response.status_code == status.HTTP_201_CREATED
async def test_stop_capture(self, app: FastAPI, client: AsyncClient, project: Project) -> None:
link = Link(project)
project._links = {link.id: link}
with asyncio_patch("gns3server.controller.link.Link.stop_capture") as mock:
response = await client.post(app.url_path_for("stop_capture", project_id=project.id, link_id=link.id))
assert mock.called
assert response.status_code == status.HTTP_204_NO_CONTENT
# async def test_pcap(controller_api, http_client, project):
#
# async def pcap_capture():
# async with http_client.get(controller_api.get_url("/projects/{}/links/{}/pcap".format(project.id, link.id))) as response:
# response.body = await response.content.read(5)
# print("READ", response.body)
# return response
#
# with asyncio_patch("gns3server.controller.link.Link.capture_node") as mock:
# link = Link(project)
# link._capture_file_name = "test"
# link._capturing = True
# with open(link.capture_file_path, "w+") as f:
# f.write("hello")
# project._links = {link.id: link}
# response = await pcap_capture()
# assert mock.called
# assert response.status_code == 200
# assert b'hello' == response.body
async def test_delete_link(self, app: FastAPI, client: AsyncClient, project: Project) -> None:
link = Link(project)
project._links = {link.id: link}
with asyncio_patch("gns3server.controller.link.Link.delete") as mock:
response = await client.delete(app.url_path_for("delete_link", project_id=project.id, link_id=link.id))
assert mock.called assert mock.called
assert response.status_code == status.HTTP_204_NO_CONTENT assert response.status_code == status.HTTP_204_NO_CONTENT
# async def test_pcap(controller_api, http_client, project): async def test_list_filters(self, app: FastAPI, client: AsyncClient, project: Project) -> None:
#
# async def pcap_capture():
# async with http_client.get(controller_api.get_url("/projects/{}/links/{}/pcap".format(project.id, link.id))) as response:
# response.body = await response.content.read(5)
# print("READ", response.body)
# return response
#
# with asyncio_patch("gns3server.controller.link.Link.capture_node") as mock:
# link = Link(project)
# link._capture_file_name = "test"
# link._capturing = True
# with open(link.capture_file_path, "w+") as f:
# f.write("hello")
# project._links = {link.id: link}
# response = await pcap_capture()
# assert mock.called
# assert response.status_code == 200
# assert b'hello' == response.body
link = Link(project)
async def test_delete_link(app: FastAPI, client: AsyncClient, project: Project) -> None: project._links = {link.id: link}
with patch("gns3server.controller.link.Link.available_filters", return_value=FILTERS) as mock:
link = Link(project) response = await client.get(app.url_path_for("get_filters", project_id=project.id, link_id=link.id))
project._links = {link.id: link} assert mock.called
with asyncio_patch("gns3server.controller.link.Link.delete") as mock: assert response.status_code == status.HTTP_200_OK
response = await client.delete(app.url_path_for("delete_link", project_id=project.id, link_id=link.id)) assert response.json() == FILTERS
assert mock.called
assert response.status_code == status.HTTP_204_NO_CONTENT
async def test_list_filters(app: FastAPI, client: AsyncClient, project: Project) -> None:
link = Link(project)
project._links = {link.id: link}
with patch("gns3server.controller.link.Link.available_filters", return_value=FILTERS) as mock:
response = await client.get(app.url_path_for("get_filters", project_id=project.id, link_id=link.id))
assert mock.called
assert response.status_code == status.HTTP_200_OK
assert response.json() == FILTERS

View File

@ -31,416 +31,537 @@ from gns3server.controller.compute import Compute
pytestmark = pytest.mark.asyncio pytestmark = pytest.mark.asyncio
@pytest.fixture class TestNodeRoutes:
def node(project: Project, compute: Compute) -> Node:
node = Node(project, compute, "test", node_type="vpcs") @pytest.fixture
project._nodes[node.id] = node def node(self, project: Project, compute: Compute) -> Node:
return node
node = Node(project, compute, "test", node_type="vpcs")
project._nodes[node.id] = node
async def test_create_node(app: FastAPI, client: AsyncClient, project: Project, compute: Compute) -> None: return node
response = MagicMock()
response.json = {"console": 2048} async def test_create_node(self, app: FastAPI, client: AsyncClient, project: Project, compute: Compute) -> None:
compute.post = AsyncioMagicMock(return_value=response)
response = MagicMock()
response = await client.post(app.url_path_for("create_node", project_id=project.id), json={ response.json = {"console": 2048}
"name": "test", compute.post = AsyncioMagicMock(return_value=response)
"node_type": "vpcs",
"compute_id": "example.com", response = await client.post(app.url_path_for("create_node", project_id=project.id), json={
"properties": { "name": "test",
"startup_script": "echo test" "node_type": "vpcs",
} "compute_id": "example.com",
}) "properties": {
"startup_script": "echo test"
assert response.status_code == status.HTTP_201_CREATED }
assert response.json()["name"] == "test" })
assert "name" not in response.json()["properties"]
assert response.status_code == status.HTTP_201_CREATED
assert response.json()["name"] == "test"
async def test_list_node(app: FastAPI, client: AsyncClient, project: Project, compute: Compute) -> None: assert "name" not in response.json()["properties"]
response = MagicMock()
response.json = {"console": 2048} async def test_list_node(self, app: FastAPI, client: AsyncClient, project: Project, compute: Compute) -> None:
compute.post = AsyncioMagicMock(return_value=response)
response = MagicMock()
await client.post(app.url_path_for("create_node", project_id=project.id), json={ response.json = {"console": 2048}
"name": "test", compute.post = AsyncioMagicMock(return_value=response)
"node_type": "vpcs",
"compute_id": "example.com", await client.post(app.url_path_for("create_node", project_id=project.id), json={
"properties": { "name": "test",
"startup_script": "echo test" "node_type": "vpcs",
} "compute_id": "example.com",
}) "properties": {
"startup_script": "echo test"
response = await client.get(app.url_path_for("get_nodes", project_id=project.id)) }
assert response.status_code == status.HTTP_200_OK })
assert response.json()[0]["name"] == "test"
response = await client.get(app.url_path_for("get_nodes", project_id=project.id))
# test listing nodes from a closed project assert response.status_code == status.HTTP_200_OK
await project.close(ignore_notification=True) assert response.json()[0]["name"] == "test"
response = await client.get(app.url_path_for("get_nodes", project_id=project.id))
assert response.status_code == status.HTTP_200_OK # test listing nodes from a closed project
assert response.json()[0]["name"] == "test" await project.close(ignore_notification=True)
response = await client.get(app.url_path_for("get_nodes", project_id=project.id))
assert response.status_code == status.HTTP_200_OK
async def test_get_node(app: FastAPI, client: AsyncClient, project: Project, compute: Compute) -> None: assert response.json()[0]["name"] == "test"
response = MagicMock()
response.json = {"console": 2048} async def test_get_node(
compute.post = AsyncioMagicMock(return_value=response) self,
app: FastAPI,
response = await client.post(app.url_path_for("create_node", project_id=project.id), json={ client: AsyncClient,
"name": "test", project: Project,
"node_type": "vpcs", compute: Compute
"compute_id": "example.com", ) -> None:
"properties": {
"startup_script": "echo test" response = MagicMock()
} response.json = {"console": 2048}
}) compute.post = AsyncioMagicMock(return_value=response)
response = await client.get(app.url_path_for("get_node", project_id=project.id, node_id=response.json()["node_id"])) response = await client.post(app.url_path_for("create_node", project_id=project.id), json={
assert response.status_code == status.HTTP_200_OK "name": "test",
assert response.json()["name"] == "test" "node_type": "vpcs",
"compute_id": "example.com",
"properties": {
async def test_update_node(app: FastAPI, client: AsyncClient, project: Project, compute: Compute, node: Node) -> None: "startup_script": "echo test"
}
response = MagicMock() })
response.json = {"console": 2048}
compute.put = AsyncioMagicMock(return_value=response) response = await client.get(app.url_path_for("get_node", project_id=project.id, node_id=response.json()["node_id"]))
assert response.status_code == status.HTTP_200_OK
response = await client.put(app.url_path_for("update_node", project_id=project.id, node_id=node.id), json={ assert response.json()["name"] == "test"
"name": "test",
"node_type": "vpcs",
"compute_id": "example.com", async def test_update_node(
"properties": { self,
"startup_script": "echo test" app: FastAPI,
} client: AsyncClient,
}) project: Project,
compute: Compute,
assert response.status_code == 200 node: Node
assert response.json()["name"] == "test" ) -> None:
assert "name" not in response.json()["properties"]
response = MagicMock()
response.json = {"console": 2048}
async def test_start_all_nodes(app: FastAPI, client: AsyncClient, project: Project, compute: Compute) -> None: compute.put = AsyncioMagicMock(return_value=response)
compute.post = AsyncioMagicMock() response = await client.put(app.url_path_for("update_node", project_id=project.id, node_id=node.id), json={
response = await client.post(app.url_path_for("start_all_nodes", project_id=project.id)) "name": "test",
assert response.status_code == status.HTTP_204_NO_CONTENT "node_type": "vpcs",
"compute_id": "example.com",
"properties": {
async def test_stop_all_nodes(app: FastAPI, client: AsyncClient, project: Project, compute: Compute) -> None: "startup_script": "echo test"
}
compute.post = AsyncioMagicMock() })
response = await client.post(app.url_path_for("stop_all_nodes", project_id=project.id))
assert response.status_code == status.HTTP_204_NO_CONTENT assert response.status_code == 200
assert response.json()["name"] == "test"
assert "name" not in response.json()["properties"]
async def test_suspend_all_nodes(app: FastAPI, client: AsyncClient, project: Project, compute: Compute) -> None:
compute.post = AsyncioMagicMock() async def test_start_all_nodes(
response = await client.post(app.url_path_for("suspend_all_nodes", project_id=project.id)) self,
assert response.status_code == status.HTTP_204_NO_CONTENT app: FastAPI,
client: AsyncClient,
project: Project,
async def test_reload_all_nodes(app: FastAPI, client: AsyncClient, project: Project, compute: Compute) -> None: compute: Compute
) -> None:
compute.post = AsyncioMagicMock()
response = await client.post(app.url_path_for("reload_all_nodes", project_id=project.id)) compute.post = AsyncioMagicMock()
assert response.status_code == status.HTTP_204_NO_CONTENT response = await client.post(app.url_path_for("start_all_nodes", project_id=project.id))
assert response.status_code == status.HTTP_204_NO_CONTENT
async def test_reset_console_all_nodes(app: FastAPI, client: AsyncClient, project: Project, compute: Compute) -> None:
async def test_stop_all_nodes(
compute.post = AsyncioMagicMock() self,
response = await client.post(app.url_path_for("reset_console_all_nodes", project_id=project.id)) app: FastAPI,
assert response.status_code == status.HTTP_204_NO_CONTENT client: AsyncClient,
project: Project,
compute: Compute
async def test_start_node(app: FastAPI, client: AsyncClient, project: Project, compute: Compute, node: Node) -> None: ) -> None:
compute.post = AsyncioMagicMock() compute.post = AsyncioMagicMock()
response = await client.post(app.url_path_for("start_node", project_id=project.id, node_id=node.id), json={}) response = await client.post(app.url_path_for("stop_all_nodes", project_id=project.id))
assert response.status_code == status.HTTP_204_NO_CONTENT assert response.status_code == status.HTTP_204_NO_CONTENT
async def test_stop_node(app: FastAPI, client: AsyncClient, project: Project, compute: Compute, node: Node) -> None: async def test_suspend_all_nodes(
self,
compute.post = AsyncioMagicMock() app: FastAPI,
response = await client.post(app.url_path_for("stop_node", project_id=project.id, node_id=node.id)) client: AsyncClient,
assert response.status_code == status.HTTP_204_NO_CONTENT project: Project,
compute: Compute
async def test_suspend_node(app: FastAPI, client: AsyncClient, project: Project, compute: Compute, node: Node) -> None: ) -> None:
compute.post = AsyncioMagicMock() compute.post = AsyncioMagicMock()
response = await client.post(app.url_path_for("suspend_node", project_id=project.id, node_id=node.id)) response = await client.post(app.url_path_for("suspend_all_nodes", project_id=project.id))
assert response.status_code == status.HTTP_204_NO_CONTENT assert response.status_code == status.HTTP_204_NO_CONTENT
async def test_reload_node(app: FastAPI, client: AsyncClient, project: Project, compute: Compute, node: Node): async def test_reload_all_nodes(
self,
compute.post = AsyncioMagicMock() app: FastAPI,
response = await client.post(app.url_path_for("reload_node", project_id=project.id, node_id=node.id)) client: AsyncClient,
assert response.status_code == status.HTTP_204_NO_CONTENT project: Project,
compute: Compute
) -> None:
async def test_isolate_node(app: FastAPI, client: AsyncClient, project: Project, compute: Compute, node: Node):
compute.post = AsyncioMagicMock()
compute.post = AsyncioMagicMock() response = await client.post(app.url_path_for("reload_all_nodes", project_id=project.id))
response = await client.post(app.url_path_for("isolate_node", project_id=project.id, node_id=node.id)) assert response.status_code == status.HTTP_204_NO_CONTENT
assert response.status_code == status.HTTP_204_NO_CONTENT
async def test_reset_console_all_nodes(
async def test_unisolate_node(app: FastAPI, client: AsyncClient, project: Project, compute: Compute, node: Node): self,
app: FastAPI,
compute.post = AsyncioMagicMock() client: AsyncClient,
response = await client.post(app.url_path_for("unisolate_node", project_id=project.id, node_id=node.id)) project: Project,
assert response.status_code == status.HTTP_204_NO_CONTENT compute: Compute
) -> None:
async def test_duplicate_node( compute.post = AsyncioMagicMock()
app: FastAPI, response = await client.post(app.url_path_for("reset_console_all_nodes", project_id=project.id))
client: AsyncClient, assert response.status_code == status.HTTP_204_NO_CONTENT
project: Project,
compute: Compute,
node: Node) -> None: async def test_start_node(
self,
response = MagicMock() app: FastAPI,
response.json({"console": 2035}) client: AsyncClient,
compute.post = AsyncioMagicMock(return_value=response) project: Project,
compute: Compute,
response = await client.post(app.url_path_for("duplicate_node", project_id=project.id, node_id=node.id), node: Node
json={"x": 10, "y": 5, "z": 0}) ) -> None:
assert response.status_code == status.HTTP_201_CREATED
compute.post = AsyncioMagicMock()
response = await client.post(app.url_path_for("start_node", project_id=project.id, node_id=node.id), json={})
async def test_delete_node(app: FastAPI, client: AsyncClient, project: Project, compute: Compute, node: Node) -> None: assert response.status_code == status.HTTP_204_NO_CONTENT
compute.post = AsyncioMagicMock()
response = await client.delete(app.url_path_for("delete_node", project_id=project.id, node_id=node.id)) async def test_stop_node(
assert response.status_code == status.HTTP_204_NO_CONTENT self,
app: FastAPI,
client: AsyncClient,
async def test_dynamips_idle_pc( project: Project,
app: FastAPI, compute: Compute,
client: AsyncClient, node: Node
project: Project, ) -> None:
compute: Compute,
node: Node compute.post = AsyncioMagicMock()
) -> None: response = await client.post(app.url_path_for("stop_node", project_id=project.id, node_id=node.id))
assert response.status_code == status.HTTP_204_NO_CONTENT
response = MagicMock()
response.json = {"idlepc": "0x60606f54"} async def test_suspend_node(
compute.get = AsyncioMagicMock(return_value=response) self,
app: FastAPI,
node._node_type = "dynamips" # force Dynamips node type client: AsyncClient,
response = await client.get(app.url_path_for("auto_idlepc", project_id=project.id, node_id=node.id)) project: Project,
assert response.status_code == status.HTTP_200_OK compute: Compute,
assert response.json()["idlepc"] == "0x60606f54" node: Node
) -> None:
async def test_dynamips_idle_pc_wrong_node_type( compute.post = AsyncioMagicMock()
app: FastAPI, response = await client.post(app.url_path_for("suspend_node", project_id=project.id, node_id=node.id))
client: AsyncClient, assert response.status_code == status.HTTP_204_NO_CONTENT
project: Project,
compute: Compute,
node: Node async def test_reload_node(
) -> None: self,
app: FastAPI,
response = await client.get(app.url_path_for("auto_idlepc", project_id=project.id, node_id=node.id)) client: AsyncClient,
assert response.status_code == status.HTTP_400_BAD_REQUEST project: Project,
compute: Compute,
node: Node
async def test_dynamips_idlepc_proposals( ):
app: FastAPI,
client: AsyncClient, compute.post = AsyncioMagicMock()
project: Project, response = await client.post(app.url_path_for("reload_node", project_id=project.id, node_id=node.id))
compute: Compute, assert response.status_code == status.HTTP_204_NO_CONTENT
node: Node
) -> None:
async def test_isolate_node(
response = MagicMock() self,
response.json = ["0x60606f54", "0x33805a22"] app: FastAPI,
compute.get = AsyncioMagicMock(return_value=response) client: AsyncClient,
project: Project,
node._node_type = "dynamips" # force Dynamips node type compute: Compute,
response = await client.get(app.url_path_for("idlepc_proposals", project_id=project.id, node_id=node.id)) node: Node
assert response.status_code == status.HTTP_200_OK ):
assert response.json() == ["0x60606f54", "0x33805a22"]
compute.post = AsyncioMagicMock()
response = await client.post(app.url_path_for("isolate_node", project_id=project.id, node_id=node.id))
async def test_dynamips_idlepc_proposals_wrong_node_type( assert response.status_code == status.HTTP_204_NO_CONTENT
app: FastAPI,
client: AsyncClient,
project: Project, async def test_unisolate_node(
compute: Compute, self,
node: Node app: FastAPI,
) -> None: client: AsyncClient,
project: Project,
response = await client.get(app.url_path_for("idlepc_proposals", project_id=project.id, node_id=node.id)) compute: Compute,
assert response.status_code == status.HTTP_400_BAD_REQUEST node: Node
) -> None:
async def test_qemu_disk_image_create( compute.post = AsyncioMagicMock()
app: FastAPI, response = await client.post(app.url_path_for("unisolate_node", project_id=project.id, node_id=node.id))
client: AsyncClient, assert response.status_code == status.HTTP_204_NO_CONTENT
project: Project,
compute: Compute,
node: Node async def test_duplicate_node(
) -> None: self,
app: FastAPI,
response = MagicMock() client: AsyncClient,
compute.post = AsyncioMagicMock(return_value=response) project: Project,
compute: Compute,
node._node_type = "qemu" # force Qemu node type node: Node
response = await client.post( ) -> None:
app.url_path_for("create_disk_image", project_id=project.id, node_id=node.id, disk_name="hda_disk.qcow2"),
json={"format": "qcow2", "size": 30} response = MagicMock()
) response.json({"console": 2035})
assert response.status_code == status.HTTP_204_NO_CONTENT compute.post = AsyncioMagicMock(return_value=response)
response = await client.post(app.url_path_for("duplicate_node", project_id=project.id, node_id=node.id),
async def test_qemu_disk_image_create_wrong_node_type( json={"x": 10, "y": 5, "z": 0})
app: FastAPI, assert response.status_code == status.HTTP_201_CREATED
client: AsyncClient,
project: Project,
compute: Compute, async def test_delete_node(
node: Node self,
) -> None: app: FastAPI,
client: AsyncClient,
response = await client.post( project: Project,
app.url_path_for("create_disk_image", project_id=project.id, node_id=node.id, disk_name="hda_disk.qcow2"), compute: Compute,
json={"format": "qcow2", "size": 30} node: Node
) ) -> None:
assert response.status_code == status.HTTP_400_BAD_REQUEST
compute.post = AsyncioMagicMock()
response = await client.delete(app.url_path_for("delete_node", project_id=project.id, node_id=node.id))
async def test_qemu_disk_image_update( assert response.status_code == status.HTTP_204_NO_CONTENT
app: FastAPI,
client: AsyncClient,
project: Project, async def test_dynamips_idle_pc(
compute: Compute, self,
node: Node app: FastAPI,
) -> None: client: AsyncClient,
project: Project,
response = MagicMock() compute: Compute,
compute.put = AsyncioMagicMock(return_value=response) node: Node
) -> None:
node._node_type = "qemu" # force Qemu node type
response = await client.put( response = MagicMock()
app.url_path_for("update_disk_image", project_id=project.id, node_id=node.id, disk_name="hda_disk.qcow2"), response.json = {"idlepc": "0x60606f54"}
json={"extend": 10} compute.get = AsyncioMagicMock(return_value=response)
)
assert response.status_code == status.HTTP_204_NO_CONTENT node._node_type = "dynamips" # force Dynamips node type
response = await client.get(app.url_path_for("auto_idlepc", project_id=project.id, node_id=node.id))
assert response.status_code == status.HTTP_200_OK
async def test_qemu_disk_image_update_wrong_node_type( assert response.json()["idlepc"] == "0x60606f54"
app: FastAPI,
client: AsyncClient,
project: Project, async def test_dynamips_idle_pc_wrong_node_type(
compute: Compute, self,
node: Node app: FastAPI,
) -> None: client: AsyncClient,
project: Project,
response = await client.put( compute: Compute,
app.url_path_for("update_disk_image", project_id=project.id, node_id=node.id, disk_name="hda_disk.qcow2"), node: Node
json={"extend": 10} ) -> None:
)
assert response.status_code == status.HTTP_400_BAD_REQUEST response = await client.get(app.url_path_for("auto_idlepc", project_id=project.id, node_id=node.id))
assert response.status_code == status.HTTP_400_BAD_REQUEST
async def test_qemu_disk_image_delete(
app: FastAPI, async def test_dynamips_idlepc_proposals(
client: AsyncClient, self,
project: Project, app: FastAPI,
compute: Compute, client: AsyncClient,
node: Node project: Project,
) -> None: compute: Compute,
node: Node
response = MagicMock() ) -> None:
compute.delete = AsyncioMagicMock(return_value=response)
response = MagicMock()
node._node_type = "qemu" # force Qemu node type response.json = ["0x60606f54", "0x33805a22"]
response = await client.delete( compute.get = AsyncioMagicMock(return_value=response)
app.url_path_for("delete_disk_image", project_id=project.id, node_id=node.id, disk_name="hda_disk.qcow2")
) node._node_type = "dynamips" # force Dynamips node type
assert response.status_code == status.HTTP_204_NO_CONTENT response = await client.get(app.url_path_for("idlepc_proposals", project_id=project.id, node_id=node.id))
assert response.status_code == status.HTTP_200_OK
assert response.json() == ["0x60606f54", "0x33805a22"]
async def test_qemu_disk_image_delete_wrong_node_type(
app: FastAPI,
client: AsyncClient, async def test_dynamips_idlepc_proposals_wrong_node_type(
project: Project, self,
compute: Compute, app: FastAPI,
node: Node client: AsyncClient,
) -> None: project: Project,
compute: Compute,
response = await client.delete( node: Node
app.url_path_for("delete_disk_image", project_id=project.id, node_id=node.id, disk_name="hda_disk.qcow2") ) -> None:
)
assert response.status_code == status.HTTP_400_BAD_REQUEST response = await client.get(app.url_path_for("idlepc_proposals", project_id=project.id, node_id=node.id))
assert response.status_code == status.HTTP_400_BAD_REQUEST
async def test_get_file(app: FastAPI, client: AsyncClient, project: Project, compute: Compute, node: Node) -> None:
async def test_qemu_disk_image_create(
response = MagicMock() self,
response.body = b"world" app: FastAPI,
response.status = status.HTTP_200_OK client: AsyncClient,
compute.http_query = AsyncioMagicMock(return_value=response) project: Project,
compute: Compute,
response = await client.get(app.url_path_for("get_file", project_id=project.id, node_id=node.id, file_path="hello")) node: Node
assert response.status_code == status.HTTP_200_OK ) -> None:
assert response.content == b'world'
response = MagicMock()
compute.http_query.assert_called_with( compute.post = AsyncioMagicMock(return_value=response)
"GET",
"/projects/{project_id}/files/project-files/vpcs/{node_id}/hello".format( node._node_type = "qemu" # force Qemu node type
response = await client.post(
app.url_path_for("create_disk_image", project_id=project.id, node_id=node.id, disk_name="hda_disk.qcow2"),
json={"format": "qcow2", "size": 30}
)
assert response.status_code == status.HTTP_204_NO_CONTENT
async def test_qemu_disk_image_create_wrong_node_type(
self,
app: FastAPI,
client: AsyncClient,
project: Project,
compute: Compute,
node: Node
) -> None:
response = await client.post(
app.url_path_for("create_disk_image", project_id=project.id, node_id=node.id, disk_name="hda_disk.qcow2"),
json={"format": "qcow2", "size": 30}
)
assert response.status_code == status.HTTP_400_BAD_REQUEST
async def test_qemu_disk_image_update(
self,
app: FastAPI,
client: AsyncClient,
project: Project,
compute: Compute,
node: Node
) -> None:
response = MagicMock()
compute.put = AsyncioMagicMock(return_value=response)
node._node_type = "qemu" # force Qemu node type
response = await client.put(
app.url_path_for("update_disk_image", project_id=project.id, node_id=node.id, disk_name="hda_disk.qcow2"),
json={"extend": 10}
)
assert response.status_code == status.HTTP_204_NO_CONTENT
async def test_qemu_disk_image_update_wrong_node_type(
self,
app: FastAPI,
client: AsyncClient,
project: Project,
compute: Compute,
node: Node
) -> None:
response = await client.put(
app.url_path_for("update_disk_image", project_id=project.id, node_id=node.id, disk_name="hda_disk.qcow2"),
json={"extend": 10}
)
assert response.status_code == status.HTTP_400_BAD_REQUEST
async def test_qemu_disk_image_delete(
self,
app: FastAPI,
client: AsyncClient,
project: Project,
compute: Compute,
node: Node
) -> None:
response = MagicMock()
compute.delete = AsyncioMagicMock(return_value=response)
node._node_type = "qemu" # force Qemu node type
response = await client.delete(
app.url_path_for("delete_disk_image", project_id=project.id, node_id=node.id, disk_name="hda_disk.qcow2")
)
assert response.status_code == status.HTTP_204_NO_CONTENT
async def test_qemu_disk_image_delete_wrong_node_type(
self,
app: FastAPI,
client: AsyncClient,
project: Project,
compute: Compute,
node: Node
) -> None:
response = await client.delete(
app.url_path_for("delete_disk_image", project_id=project.id, node_id=node.id, disk_name="hda_disk.qcow2")
)
assert response.status_code == status.HTTP_400_BAD_REQUEST
async def test_get_file(
self,
app: FastAPI,
client: AsyncClient,
project: Project,
compute: Compute,
node: Node
) -> None:
response = MagicMock()
response.body = b"world"
response.status = status.HTTP_200_OK
compute.http_query = AsyncioMagicMock(return_value=response)
response = await client.get(app.url_path_for("get_file", project_id=project.id, node_id=node.id, file_path="hello"))
assert response.status_code == status.HTTP_200_OK
assert response.content == b'world'
compute.http_query.assert_called_with(
"GET",
"/projects/{project_id}/files/project-files/vpcs/{node_id}/hello".format(
project_id=project.id,
node_id=node.id),
timeout=None,
raw=True)
response = await client.get(app.url_path_for(
"get_file",
project_id=project.id, project_id=project.id,
node_id=node.id), node_id=node.id,
timeout=None, file_path="../hello"))
raw=True) assert response.status_code == status.HTTP_404_NOT_FOUND
response = await client.get(app.url_path_for(
"get_file",
project_id=project.id,
node_id=node.id,
file_path="../hello"))
assert response.status_code == status.HTTP_404_NOT_FOUND
async def test_post_file(app: FastAPI, client: AsyncClient, project: Project, compute: Compute, node: Node) -> None: async def test_post_file(
self,
app: FastAPI,
client: AsyncClient,
project: Project,
compute: Compute,
node: Node
) -> None:
compute.http_query = AsyncioMagicMock() compute.http_query = AsyncioMagicMock()
response = await client.post(app.url_path_for( response = await client.post(app.url_path_for(
"post_file", "post_file",
project_id=project.id, project_id=project.id,
node_id=node.id, node_id=node.id,
file_path="hello"), content=b"hello") file_path="hello"), content=b"hello")
assert response.status_code == status.HTTP_201_CREATED assert response.status_code == status.HTTP_201_CREATED
compute.http_query.assert_called_with("POST", "/projects/{project_id}/files/project-files/vpcs/{node_id}/hello".format(project_id=project.id, node_id=node.id), data=b'hello', timeout=None, raw=True) compute.http_query.assert_called_with("POST", "/projects/{project_id}/files/project-files/vpcs/{node_id}/hello".format(project_id=project.id, node_id=node.id), data=b'hello', timeout=None, raw=True)
response = await client.get("/projects/{project_id}/nodes/{node_id}/files/../hello".format(project_id=project.id, node_id=node.id)) response = await client.get("/projects/{project_id}/nodes/{node_id}/files/../hello".format(project_id=project.id, node_id=node.id))
assert response.status_code == status.HTTP_404_NOT_FOUND assert response.status_code == status.HTTP_404_NOT_FOUND
# @pytest.mark.asyncio # @pytest.mark.asyncio
# async def test_get_and_post_with_nested_paths_normalization(controller_api, project, node, compute): # async def test_get_and_post_with_nested_paths_normalization(controller_api, project, node, compute):
# #
# response = MagicMock() # response = MagicMock()
# response.body = b"world" # response.body = b"world"
# compute.http_query = AsyncioMagicMock(return_value=response) # compute.http_query = AsyncioMagicMock(return_value=response)
# response = await controller_api.get("/projects/{project_id}/nodes/{node_id}/files/hello\\nested".format(project_id=project.id, node_id=node.id)) # response = await controller_api.get("/projects/{project_id}/nodes/{node_id}/files/hello\\nested".format(project_id=project.id, node_id=node.id))
# assert response.status_code == 200 # assert response.status_code == 200
# assert response.content == b'world' # assert response.content == b'world'
# #
# compute.http_query.assert_called_with("GET", "/projects/{project_id}/files/project-files/vpcs/{node_id}/hello/nested".format(project_id=project.id, node_id=node.id), timeout=None, raw=True) # compute.http_query.assert_called_with("GET", "/projects/{project_id}/files/project-files/vpcs/{node_id}/hello/nested".format(project_id=project.id, node_id=node.id), timeout=None, raw=True)
# #
# compute.http_query = AsyncioMagicMock() # compute.http_query = AsyncioMagicMock()
# response = await controller_api.post("/projects/{project_id}/nodes/{node_id}/files/hello\\nested".format(project_id=project.id, node_id=node.id), body=b"hello", raw=True) # response = await controller_api.post("/projects/{project_id}/nodes/{node_id}/files/hello\\nested".format(project_id=project.id, node_id=node.id), body=b"hello", raw=True)
# assert response.status_code == 201 # assert response.status_code == 201
# #
# compute.http_query.assert_called_with("POST", "/projects/{project_id}/files/project-files/vpcs/{node_id}/hello/nested".format(project_id=project.id, node_id=node.id), data=b'hello', timeout=None, raw=True) # compute.http_query.assert_called_with("POST", "/projects/{project_id}/files/project-files/vpcs/{node_id}/hello/nested".format(project_id=project.id, node_id=node.id), data=b'hello', timeout=None, raw=True)

View File

@ -34,337 +34,274 @@ from gns3server.controller.compute import Compute
pytestmark = pytest.mark.asyncio pytestmark = pytest.mark.asyncio
@pytest_asyncio.fixture class TestControllerProjectRoutes:
async def project(app: FastAPI, client: AsyncClient, controller: Controller) -> Project:
project_id = str(uuid.uuid4()) @pytest_asyncio.fixture
params = {"name": "test", "project_id": project_id} async def project(self, app: FastAPI, client: AsyncClient, controller: Controller) -> Project:
await client.post(app.url_path_for("create_project"), json=params)
return controller.get_project(project_id) project_id = str(uuid.uuid4())
params = {"name": "test", "project_id": project_id}
await client.post(app.url_path_for("create_project"), json=params)
return controller.get_project(project_id)
async def test_create_project_with_path(app: FastAPI, client: AsyncClient, controller: Controller, config) -> None: async def test_create_project_with_path(
self,
app: FastAPI,
client: AsyncClient,
controller: Controller,
config
) -> None:
params = {"name": "test", "path": str(config.settings.Server.projects_path), "project_id": "00010203-0405-0607-0809-0a0b0c0d0e0f"} params = {"name": "test", "path": str(config.settings.Server.projects_path), "project_id": "00010203-0405-0607-0809-0a0b0c0d0e0f"}
response = await client.post(app.url_path_for("create_project"), json=params) response = await client.post(app.url_path_for("create_project"), json=params)
assert response.status_code == status.HTTP_201_CREATED
assert response.json()["name"] == "test"
assert response.json()["project_id"] == "00010203-0405-0607-0809-0a0b0c0d0e0f"
assert response.json()["status"] == "opened"
async def test_create_project_without_dir(app: FastAPI, client: AsyncClient, controller: Controller) -> None:
params = {"name": "test", "project_id": "10010203-0405-0607-0809-0a0b0c0d0e0f"}
response = await client.post(app.url_path_for("create_project"), json=params)
assert response.status_code == status.HTTP_201_CREATED
assert response.json()["project_id"] == "10010203-0405-0607-0809-0a0b0c0d0e0f"
assert response.json()["name"] == "test"
async def test_create_project_with_uuid(app: FastAPI, client: AsyncClient, controller: Controller) -> None:
params = {"name": "test", "project_id": "30010203-0405-0607-0809-0a0b0c0d0e0f"}
response = await client.post(app.url_path_for("create_project"), json=params)
assert response.status_code == 201
assert response.json()["project_id"] == "30010203-0405-0607-0809-0a0b0c0d0e0f"
assert response.json()["name"] == "test"
async def test_create_project_with_variables(app: FastAPI, client: AsyncClient, controller: Controller) -> None:
variables = [
{"name": "TEST1"},
{"name": "TEST2", "value": "value1"}
]
params = {"name": "test", "project_id": "30010203-0405-0607-0809-0a0b0c0d0e0f", "variables": variables}
response = await client.post(app.url_path_for("create_project"), json=params)
assert response.status_code == 201
assert response.json()["variables"] == [
{"name": "TEST1"},
{"name": "TEST2", "value": "value1"}
]
async def test_create_project_with_supplier(app: FastAPI, client: AsyncClient, controller: Controller) -> None:
supplier = {
'logo': 'logo.png',
'url': 'http://example.com/'
}
params = {"name": "test", "project_id": "30010203-0405-0607-0809-0a0b0c0d0e0f", "supplier": supplier}
response = await client.post(app.url_path_for("create_project"), json=params)
assert response.status_code == status.HTTP_201_CREATED
assert response.json()["supplier"] == supplier
async def test_update_project(app: FastAPI, client: AsyncClient, controller: Controller) -> None:
params = {"name": "test", "project_id": "10010203-0405-0607-0809-0a0b0c0d0e0f"}
response = await client.post(app.url_path_for("create_project"), json=params)
assert response.status_code == status.HTTP_201_CREATED
assert response.json()["project_id"] == "10010203-0405-0607-0809-0a0b0c0d0e0f"
assert response.json()["name"] == "test"
params = {"name": "test2"}
response = await client.put(app.url_path_for("update_project", project_id="10010203-0405-0607-0809-0a0b0c0d0e0f"),
json=params)
assert response.status_code == status.HTTP_200_OK
assert response.json()["name"] == "test2"
async def test_update_project_with_variables(app: FastAPI, client: AsyncClient, controller: Controller) -> None:
variables = [
{"name": "TEST1"},
{"name": "TEST2", "value": "value1"}
]
params = {"name": "test", "project_id": "10010203-0405-0607-0809-0a0b0c0d0e0f", "variables": variables}
response = await client.post(app.url_path_for("create_project"), json=params)
assert response.status_code == status.HTTP_201_CREATED
params = {"name": "test2"}
response = await client.put(app.url_path_for("update_project", project_id="10010203-0405-0607-0809-0a0b0c0d0e0f"),
json=params)
assert response.status_code == status.HTTP_200_OK
assert response.json()["variables"] == variables
async def test_list_projects(app: FastAPI, client: AsyncClient, controller: Controller) -> None:
params = {"name": "test", "project_id": "00010203-0405-0607-0809-0a0b0c0d0e0f"}
await client.post(app.url_path_for("create_project"), json=params)
response = await client.get(app.url_path_for("get_projects"))
assert response.status_code == status.HTTP_200_OK
projects = response.json()
assert projects[0]["name"] == "test"
async def test_get_project(app: FastAPI, client: AsyncClient, project: Project) -> None:
response = await client.get(app.url_path_for("get_project", project_id=project.id))
assert response.status_code == status.HTTP_200_OK
assert response.json()["name"] == "test"
async def test_delete_project(app: FastAPI, client: AsyncClient, project: Project, controller: Controller) -> None:
with asyncio_patch("gns3server.controller.project.Project.delete", return_value=True) as mock:
response = await client.delete(app.url_path_for("delete_project", project_id=project.id))
assert response.status_code == status.HTTP_204_NO_CONTENT
assert mock.called
assert project not in controller.projects
async def test_delete_project_invalid_uuid(app: FastAPI, client: AsyncClient) -> None:
response = await client.delete(app.url_path_for("delete_project", project_id=str(uuid.uuid4())))
assert response.status_code == status.HTTP_404_NOT_FOUND
async def test_close_project(app: FastAPI, client: AsyncClient, project: Project) -> None:
with asyncio_patch("gns3server.controller.project.Project.close", return_value=True) as mock:
response = await client.post(app.url_path_for("close_project", project_id=project.id))
assert response.status_code == status.HTTP_204_NO_CONTENT
assert mock.called
async def test_open_project(app: FastAPI, client: AsyncClient, project: Project) -> None:
with asyncio_patch("gns3server.controller.project.Project.open", return_value=True) as mock:
response = await client.post(app.url_path_for("open_project", project_id=project.id))
assert response.status_code == status.HTTP_201_CREATED assert response.status_code == status.HTTP_201_CREATED
assert mock.called assert response.json()["name"] == "test"
assert response.json()["project_id"] == "00010203-0405-0607-0809-0a0b0c0d0e0f"
assert response.json()["status"] == "opened"
async def test_load_project(app: FastAPI, client: AsyncClient, project: Project, config) -> None: async def test_create_project_without_dir(
self,
app: FastAPI,
client: AsyncClient,
controller: Controller
) -> None:
with asyncio_patch("gns3server.controller.Controller.load_project", return_value=project) as mock: params = {"name": "test", "project_id": "10010203-0405-0607-0809-0a0b0c0d0e0f"}
response = await client.post(app.url_path_for("load_project"), json={"path": "/tmp/test.gns3"}) response = await client.post(app.url_path_for("create_project"), json=params)
assert response.status_code == status.HTTP_201_CREATED assert response.status_code == status.HTTP_201_CREATED
mock.assert_called_with("/tmp/test.gns3") assert response.json()["project_id"] == "10010203-0405-0607-0809-0a0b0c0d0e0f"
assert response.json()["project_id"] == project.id assert response.json()["name"] == "test"
# @pytest.mark.asyncio async def test_create_project_with_uuid(
# async def test_notification(controller_api, http_client, project, controller): self,
# app: FastAPI,
# async with http_client.get(controller_api.get_url("/projects/{project_id}/notifications".format(project_id=project.id))) as response: client: AsyncClient,
# response.body = await response.content.read(200) controller: Controller
# controller.notification.project_emit("node.created", {"a": "b"}) ) -> None:
# response.body += await response.content.readany()
# assert response.status_code == 200 params = {"name": "test", "project_id": "30010203-0405-0607-0809-0a0b0c0d0e0f"}
# assert b'"action": "ping"' in response.body response = await client.post(app.url_path_for("create_project"), json=params)
# assert b'"cpu_usage_percent"' in response.body assert response.status_code == 201
# assert b'{"action": "node.created", "event": {"a": "b"}}\n' in response.body assert response.json()["project_id"] == "30010203-0405-0607-0809-0a0b0c0d0e0f"
# assert project.status_code == "opened" assert response.json()["name"] == "test"
#
#
# @pytest.mark.asyncio
# async def test_notification_invalid_id(controller_api):
#
# response = await controller_api.get("/projects/{project_id}/notifications".format(project_id=uuid.uuid4()))
# assert response.status_code == 404
# @pytest.mark.asyncio async def test_create_project_with_variables(
# async def test_notification_ws(controller_api, http_client, controller, project): self,
# app: FastAPI,
# ws = await http_client.ws_connect(controller_api.get_url("/projects/{project_id}/notifications/ws".format(project_id=project.id))) client: AsyncClient,
# answer = await ws.receive() controller: Controller
# answer = json.loads(answer.data) ) -> None:
# assert answer["action"] == "ping"
# variables = [
# controller.notification.project_emit("test", {}) {"name": "TEST1"},
# answer = await ws.receive() {"name": "TEST2", "value": "value1"}
# answer = json.loads(answer.data) ]
# assert answer["action"] == "test" params = {"name": "test", "project_id": "30010203-0405-0607-0809-0a0b0c0d0e0f", "variables": variables}
# response = await client.post(app.url_path_for("create_project"), json=params)
# if not ws.closed: assert response.status_code == 201
# await ws.close() assert response.json()["variables"] == [
# {"name": "TEST1"},
# assert project.status_code == "opened" {"name": "TEST2", "value": "value1"}
]
async def test_export_with_images(app: FastAPI, client: AsyncClient, tmpdir, project: Project) -> None: async def test_create_project_with_supplier(
self,
app: FastAPI,
client: AsyncClient,
controller: Controller
) -> None:
project.dump = MagicMock() supplier = {
os.makedirs(project.path, exist_ok=True) 'logo': 'logo.png',
with open(os.path.join(project.path, 'a'), 'w+') as f: 'url': 'http://example.com/'
f.write('hello')
os.makedirs(str(tmpdir / "IOS"))
with open(str(tmpdir / "IOS" / "test.image"), "w+") as f:
f.write("AAA")
topology = {
"topology": {
"nodes": [
{
"properties": {
"image": "test.image"
},
"node_type": "dynamips"
}
]
} }
} params = {"name": "test", "project_id": "30010203-0405-0607-0809-0a0b0c0d0e0f", "supplier": supplier}
with open(os.path.join(project.path, "test.gns3"), 'w+') as f: response = await client.post(app.url_path_for("create_project"), json=params)
json.dump(topology, f) assert response.status_code == status.HTTP_201_CREATED
assert response.json()["supplier"] == supplier
with patch("gns3server.compute.Dynamips.get_images_directory", return_value=str(tmpdir / "IOS")):
response = await client.get(app.url_path_for("export_project", project_id=project.id),
params={"include_images": "yes"})
assert response.status_code == status.HTTP_200_OK
assert response.headers['CONTENT-TYPE'] == 'application/gns3project'
assert response.headers['CONTENT-DISPOSITION'] == 'attachment; filename="{}.gns3project"'.format(project.name)
with open(str(tmpdir / 'project.zip'), 'wb+') as f:
f.write(response.content)
with zipfile_zstd.ZipFile(str(tmpdir / 'project.zip')) as myzip:
with myzip.open("a") as myfile:
content = myfile.read()
assert content == b"hello"
myzip.getinfo("images/IOS/test.image")
async def test_export_without_images(app: FastAPI, client: AsyncClient, tmpdir, project: Project) -> None: async def test_update_project(self, app: FastAPI, client: AsyncClient, controller: Controller) -> None:
project.dump = MagicMock() params = {"name": "test", "project_id": "10010203-0405-0607-0809-0a0b0c0d0e0f"}
os.makedirs(project.path, exist_ok=True) response = await client.post(app.url_path_for("create_project"), json=params)
with open(os.path.join(project.path, 'a'), 'w+') as f: assert response.status_code == status.HTTP_201_CREATED
f.write('hello') assert response.json()["project_id"] == "10010203-0405-0607-0809-0a0b0c0d0e0f"
assert response.json()["name"] == "test"
os.makedirs(str(tmpdir / "IOS")) params = {"name": "test2"}
with open(str(tmpdir / "IOS" / "test.image"), "w+") as f: response = await client.put(app.url_path_for("update_project", project_id="10010203-0405-0607-0809-0a0b0c0d0e0f"),
f.write("AAA") json=params)
assert response.status_code == status.HTTP_200_OK
assert response.json()["name"] == "test2"
topology = {
"topology": { async def test_update_project_with_variables(
"nodes": [ self,
{ app: FastAPI,
"properties": { client: AsyncClient,
"image": "test.image" controller: Controller
}, ) -> None:
"node_type": "dynamips"
} variables = [
] {"name": "TEST1"},
{"name": "TEST2", "value": "value1"}
]
params = {"name": "test", "project_id": "10010203-0405-0607-0809-0a0b0c0d0e0f", "variables": variables}
response = await client.post(app.url_path_for("create_project"), json=params)
assert response.status_code == status.HTTP_201_CREATED
params = {"name": "test2"}
response = await client.put(app.url_path_for("update_project", project_id="10010203-0405-0607-0809-0a0b0c0d0e0f"),
json=params)
assert response.status_code == status.HTTP_200_OK
assert response.json()["variables"] == variables
async def test_list_projects(self, app: FastAPI, client: AsyncClient, controller: Controller) -> None:
params = {"name": "test", "project_id": "00010203-0405-0607-0809-0a0b0c0d0e0f"}
await client.post(app.url_path_for("create_project"), json=params)
response = await client.get(app.url_path_for("get_projects"))
assert response.status_code == status.HTTP_200_OK
projects = response.json()
assert projects[0]["name"] == "test"
async def test_get_project(self, app: FastAPI, client: AsyncClient, project: Project) -> None:
response = await client.get(app.url_path_for("get_project", project_id=project.id))
assert response.status_code == status.HTTP_200_OK
assert response.json()["name"] == "test"
async def test_delete_project(
self,
app: FastAPI,
client: AsyncClient,
project: Project,
controller: Controller
) -> None:
with asyncio_patch("gns3server.controller.project.Project.delete", return_value=True) as mock:
response = await client.delete(app.url_path_for("delete_project", project_id=project.id))
assert response.status_code == status.HTTP_204_NO_CONTENT
assert mock.called
assert project not in controller.projects
async def test_delete_project_invalid_uuid(self, app: FastAPI, client: AsyncClient) -> None:
response = await client.delete(app.url_path_for("delete_project", project_id=str(uuid.uuid4())))
assert response.status_code == status.HTTP_404_NOT_FOUND
async def test_close_project(self, app: FastAPI, client: AsyncClient, project: Project) -> None:
with asyncio_patch("gns3server.controller.project.Project.close", return_value=True) as mock:
response = await client.post(app.url_path_for("close_project", project_id=project.id))
assert response.status_code == status.HTTP_204_NO_CONTENT
assert mock.called
async def test_open_project(self, app: FastAPI, client: AsyncClient, project: Project) -> None:
with asyncio_patch("gns3server.controller.project.Project.open", return_value=True) as mock:
response = await client.post(app.url_path_for("open_project", project_id=project.id))
assert response.status_code == status.HTTP_201_CREATED
assert mock.called
async def test_load_project(self, app: FastAPI, client: AsyncClient, project: Project, config) -> None:
with asyncio_patch("gns3server.controller.Controller.load_project", return_value=project) as mock:
response = await client.post(app.url_path_for("load_project"), json={"path": "/tmp/test.gns3"})
assert response.status_code == status.HTTP_201_CREATED
mock.assert_called_with("/tmp/test.gns3")
assert response.json()["project_id"] == project.id
# @pytest.mark.asyncio
# async def test_notification(controller_api, http_client, project, controller):
#
# async with http_client.get(controller_api.get_url("/projects/{project_id}/notifications".format(project_id=project.id))) as response:
# response.body = await response.content.read(200)
# controller.notification.project_emit("node.created", {"a": "b"})
# response.body += await response.content.readany()
# assert response.status_code == 200
# assert b'"action": "ping"' in response.body
# assert b'"cpu_usage_percent"' in response.body
# assert b'{"action": "node.created", "event": {"a": "b"}}\n' in response.body
# assert project.status_code == "opened"
#
#
# @pytest.mark.asyncio
# async def test_notification_invalid_id(controller_api):
#
# response = await controller_api.get("/projects/{project_id}/notifications".format(project_id=uuid.uuid4()))
# assert response.status_code == 404
# @pytest.mark.asyncio
# async def test_notification_ws(controller_api, http_client, controller, project):
#
# ws = await http_client.ws_connect(controller_api.get_url("/projects/{project_id}/notifications/ws".format(project_id=project.id)))
# answer = await ws.receive()
# answer = json.loads(answer.data)
# assert answer["action"] == "ping"
#
# controller.notification.project_emit("test", {})
# answer = await ws.receive()
# answer = json.loads(answer.data)
# assert answer["action"] == "test"
#
# if not ws.closed:
# await ws.close()
#
# assert project.status_code == "opened"
async def test_export_with_images(
self,
app: FastAPI,
client: AsyncClient,
tmpdir,
project: Project
) -> None:
project.dump = MagicMock()
os.makedirs(project.path, exist_ok=True)
with open(os.path.join(project.path, 'a'), 'w+') as f:
f.write('hello')
os.makedirs(str(tmpdir / "IOS"))
with open(str(tmpdir / "IOS" / "test.image"), "w+") as f:
f.write("AAA")
topology = {
"topology": {
"nodes": [
{
"properties": {
"image": "test.image"
},
"node_type": "dynamips"
}
]
}
} }
} with open(os.path.join(project.path, "test.gns3"), 'w+') as f:
with open(os.path.join(project.path, "test.gns3"), 'w+') as f: json.dump(topology, f)
json.dump(topology, f)
with patch("gns3server.compute.Dynamips.get_images_directory", return_value=str(tmpdir / "IOS"),): with patch("gns3server.compute.Dynamips.get_images_directory", return_value=str(tmpdir / "IOS")):
response = await client.get(app.url_path_for("export_project", project_id=project.id), response = await client.get(app.url_path_for("export_project", project_id=project.id),
params={"include_images": "0"}) params={"include_images": "yes"})
assert response.status_code == status.HTTP_200_OK assert response.status_code == status.HTTP_200_OK
assert response.headers['CONTENT-TYPE'] == 'application/gns3project'
assert response.headers['CONTENT-DISPOSITION'] == 'attachment; filename="{}.gns3project"'.format(project.name)
with open(str(tmpdir / 'project.zip'), 'wb+') as f:
f.write(response.content)
with zipfile_zstd.ZipFile(str(tmpdir / 'project.zip')) as myzip:
with myzip.open("a") as myfile:
content = myfile.read()
assert content == b"hello"
# Image should not exported
with pytest.raises(KeyError):
myzip.getinfo("images/IOS/test.image")
@pytest.mark.parametrize(
"compression, compression_level, status_code",
(
("none", None, status.HTTP_200_OK),
("none", 4, status.HTTP_400_BAD_REQUEST),
("zip", None, status.HTTP_200_OK),
("zip", 1, status.HTTP_200_OK),
("zip", 12, status.HTTP_400_BAD_REQUEST),
("bzip2", None, status.HTTP_200_OK),
("bzip2", 1, status.HTTP_200_OK),
("bzip2", 13, status.HTTP_400_BAD_REQUEST),
("lzma", None, status.HTTP_200_OK),
("lzma", 1, status.HTTP_400_BAD_REQUEST),
("zstd", None, status.HTTP_200_OK),
("zstd", 12, status.HTTP_200_OK),
("zstd", 23, status.HTTP_400_BAD_REQUEST),
)
)
async def test_export_compression(
app: FastAPI,
client: AsyncClient,
tmpdir,
project: Project,
compression: str,
compression_level: int,
status_code: int
) -> None:
project.dump = MagicMock()
os.makedirs(project.path, exist_ok=True)
topology = {
"topology": {
"nodes": [
{
"node_type": "qemu"
}
]
}
}
with open(os.path.join(project.path, "test.gns3"), 'w+') as f:
json.dump(topology, f)
params = {"compression": compression}
if compression_level:
params["compression_level"] = compression_level
response = await client.get(app.url_path_for("export_project", project_id=project.id), params=params)
assert response.status_code == status_code
if response.status_code == status.HTTP_200_OK:
assert response.headers['CONTENT-TYPE'] == 'application/gns3project' assert response.headers['CONTENT-TYPE'] == 'application/gns3project'
assert response.headers['CONTENT-DISPOSITION'] == 'attachment; filename="{}.gns3project"'.format(project.name) assert response.headers['CONTENT-DISPOSITION'] == 'attachment; filename="{}.gns3project"'.format(project.name)
@ -372,153 +309,269 @@ async def test_export_compression(
f.write(response.content) f.write(response.content)
with zipfile_zstd.ZipFile(str(tmpdir / 'project.zip')) as myzip: with zipfile_zstd.ZipFile(str(tmpdir / 'project.zip')) as myzip:
with myzip.open("project.gns3") as myfile: with myzip.open("a") as myfile:
myfile.read() content = myfile.read()
assert content == b"hello"
myzip.getinfo("images/IOS/test.image")
async def test_get_file(app: FastAPI, client: AsyncClient, project: Project) -> None: async def test_export_without_images(self, app: FastAPI, client: AsyncClient, tmpdir, project: Project) -> None:
os.makedirs(project.path, exist_ok=True) project.dump = MagicMock()
with open(os.path.join(project.path, 'hello'), 'w+') as f: os.makedirs(project.path, exist_ok=True)
f.write('world') with open(os.path.join(project.path, 'a'), 'w+') as f:
f.write('hello')
response = await client.get(app.url_path_for("get_file", project_id=project.id, file_path="hello")) os.makedirs(str(tmpdir / "IOS"))
assert response.status_code == status.HTTP_200_OK with open(str(tmpdir / "IOS" / "test.image"), "w+") as f:
assert response.content == b"world" f.write("AAA")
response = await client.get(app.url_path_for("get_file", project_id=project.id, file_path="false")) topology = {
assert response.status_code == status.HTTP_404_NOT_FOUND "topology": {
"nodes": [
response = await client.get(app.url_path_for("get_file", project_id=project.id, file_path="../hello")) {
assert response.status_code == status.HTTP_404_NOT_FOUND "properties": {
"image": "test.image"
},
async def test_get_file_forbidden_location(app: FastAPI, client: AsyncClient, project: Project) -> None: "node_type": "dynamips"
}
file_path = "foo/%2e%2e/%2e%2e/%2e%2e/%2e%2e/%2e%2e/%2e%2e/etc/passwd" ]
response = await client.get(app.url_path_for("get_file", project_id=project.id, file_path=file_path)) }
assert response.status_code == status.HTTP_403_FORBIDDEN
async def test_write_file(app: FastAPI, client: AsyncClient, project: Project) -> None:
response = await client.post(app.url_path_for("write_file", project_id=project.id, file_path="hello"),
content=b"world")
assert response.status_code == status.HTTP_204_NO_CONTENT
with open(os.path.join(project.path, "hello")) as f:
assert f.read() == "world"
response = await client.post(app.url_path_for("write_file", project_id=project.id, file_path="../hello"))
assert response.status_code == status.HTTP_404_NOT_FOUND
async def test_write_file_forbidden_location(app: FastAPI, client: AsyncClient, project: Project) -> None:
file_path = "%2e%2e/hello"
response = await client.post(app.url_path_for("write_file", project_id=project.id, file_path=file_path),
content=b"world")
assert response.status_code == status.HTTP_403_FORBIDDEN
async def test_write_and_get_file_with_leading_slashes_in_filename(
app: FastAPI,
client: AsyncClient,
project: Project) -> None:
response = await client.post(app.url_path_for("write_file", project_id=project.id, file_path="//hello"),
content=b"world")
assert response.status_code == status.HTTP_403_FORBIDDEN
response = await client.get(app.url_path_for("get_file", project_id=project.id, file_path="//hello"))
assert response.status_code == status.HTTP_403_FORBIDDEN
async def test_import(app: FastAPI, client: AsyncClient, tmpdir, controller: Controller) -> None:
with zipfile_zstd.ZipFile(str(tmpdir / "test.zip"), 'w') as myzip:
myzip.writestr("project.gns3", b'{"project_id": "c6992992-ac72-47dc-833b-54aa334bcd05", "version": "2.0.0", "name": "test"}')
myzip.writestr("demo", b"hello")
project_id = str(uuid.uuid4())
with open(str(tmpdir / "test.zip"), "rb") as f:
response = await client.post(app.url_path_for("import_project", project_id=project_id), content=f.read())
assert response.status_code == status.HTTP_201_CREATED
project = controller.get_project(project_id)
with open(os.path.join(project.path, "demo")) as f:
content = f.read()
assert content == "hello"
async def test_import_with_project_name(app: FastAPI, client: AsyncClient, tmpdir, controller: Controller) -> None:
with zipfile_zstd.ZipFile(str(tmpdir / "test.zip"), 'w') as myzip:
myzip.writestr("project.gns3", b'{"project_id": "c6992992-ac72-47dc-833b-54aa334bcd05", "version": "2.0.0", "name": "test"}')
myzip.writestr("demo", b"hello")
project_id = str(uuid.uuid4())
with open(str(tmpdir / "test.zip"), "rb") as f:
response = await client.post(
app.url_path_for("import_project", project_id=project_id),
content=f.read(),
params={"name": "my-imported-project-name"}
)
assert response.status_code == status.HTTP_201_CREATED
project = controller.get_project(project_id)
assert project.name == "my-imported-project-name"
async def test_duplicate(app: FastAPI, client: AsyncClient, project: Project) -> None:
response = await client.post(app.url_path_for("duplicate_project", project_id=project.id), json={"name": "hello"})
assert response.status_code == status.HTTP_201_CREATED
assert response.json()["name"] == "hello"
async def test_lock_unlock(app: FastAPI, client: AsyncClient, project: Project, compute: Compute) -> None:
# add a drawing and node to the project
params = {
"svg": '<svg height="210" width="500"><line x1="0" y1="0" x2="200" y2="200" style="stroke:rgb(255,0,0);stroke-width:2" /></svg>',
"x": 10,
"y": 20,
"z": 0
}
response = await client.post(app.url_path_for("create_drawing", project_id=project.id), json=params)
assert response.status_code == status.HTTP_201_CREATED
response = MagicMock()
response.json = {"console": 2048}
compute.post = AsyncioMagicMock(return_value=response)
response = await client.post(app.url_path_for("create_node", project_id=project.id), json={
"name": "test",
"node_type": "vpcs",
"compute_id": "example.com",
"properties": {
"startup_script": "echo test"
} }
}) with open(os.path.join(project.path, "test.gns3"), 'w+') as f:
assert response.status_code == status.HTTP_201_CREATED json.dump(topology, f)
response = await client.post(app.url_path_for("lock_project", project_id=project.id)) with patch("gns3server.compute.Dynamips.get_images_directory", return_value=str(tmpdir / "IOS"),):
assert response.status_code == status.HTTP_204_NO_CONTENT response = await client.get(app.url_path_for("export_project", project_id=project.id),
params={"include_images": "0"})
assert response.status_code == status.HTTP_200_OK
assert response.headers['CONTENT-TYPE'] == 'application/gns3project'
assert response.headers['CONTENT-DISPOSITION'] == 'attachment; filename="{}.gns3project"'.format(project.name)
for drawing in project.drawings.values(): with open(str(tmpdir / 'project.zip'), 'wb+') as f:
assert drawing.locked is True f.write(response.content)
for node in project.nodes.values():
assert node.locked is True
response = await client.get(app.url_path_for("locked_project", project_id=project.id)) with zipfile_zstd.ZipFile(str(tmpdir / 'project.zip')) as myzip:
assert response.status_code == status.HTTP_200_OK with myzip.open("a") as myfile:
assert response.json() is True content = myfile.read()
assert content == b"hello"
# Image should not exported
with pytest.raises(KeyError):
myzip.getinfo("images/IOS/test.image")
response = await client.post(app.url_path_for("unlock_project", project_id=project.id))
assert response.status_code == status.HTTP_204_NO_CONTENT
for drawing in project.drawings.values(): @pytest.mark.parametrize(
assert drawing.locked is False "compression, compression_level, status_code",
for node in project.nodes.values(): (
assert node.locked is False ("none", None, status.HTTP_200_OK),
("none", 4, status.HTTP_400_BAD_REQUEST),
("zip", None, status.HTTP_200_OK),
("zip", 1, status.HTTP_200_OK),
("zip", 12, status.HTTP_400_BAD_REQUEST),
("bzip2", None, status.HTTP_200_OK),
("bzip2", 1, status.HTTP_200_OK),
("bzip2", 13, status.HTTP_400_BAD_REQUEST),
("lzma", None, status.HTTP_200_OK),
("lzma", 1, status.HTTP_400_BAD_REQUEST),
("zstd", None, status.HTTP_200_OK),
("zstd", 12, status.HTTP_200_OK),
("zstd", 23, status.HTTP_400_BAD_REQUEST),
)
)
async def test_export_compression(
self,
app: FastAPI,
client: AsyncClient,
tmpdir,
project: Project,
compression: str,
compression_level: int,
status_code: int
) -> None:
project.dump = MagicMock()
os.makedirs(project.path, exist_ok=True)
topology = {
"topology": {
"nodes": [
{
"node_type": "qemu"
}
]
}
}
with open(os.path.join(project.path, "test.gns3"), 'w+') as f:
json.dump(topology, f)
params = {"compression": compression}
if compression_level:
params["compression_level"] = compression_level
response = await client.get(app.url_path_for("export_project", project_id=project.id), params=params)
assert response.status_code == status_code
if response.status_code == status.HTTP_200_OK:
assert response.headers['CONTENT-TYPE'] == 'application/gns3project'
assert response.headers['CONTENT-DISPOSITION'] == 'attachment; filename="{}.gns3project"'.format(project.name)
with open(str(tmpdir / 'project.zip'), 'wb+') as f:
f.write(response.content)
with zipfile_zstd.ZipFile(str(tmpdir / 'project.zip')) as myzip:
with myzip.open("project.gns3") as myfile:
myfile.read()
async def test_get_file(self, app: FastAPI, client: AsyncClient, project: Project) -> None:
os.makedirs(project.path, exist_ok=True)
with open(os.path.join(project.path, 'hello'), 'w+') as f:
f.write('world')
response = await client.get(app.url_path_for("get_file", project_id=project.id, file_path="hello"))
assert response.status_code == status.HTTP_200_OK
assert response.content == b"world"
response = await client.get(app.url_path_for("get_file", project_id=project.id, file_path="false"))
assert response.status_code == status.HTTP_404_NOT_FOUND
response = await client.get(app.url_path_for("get_file", project_id=project.id, file_path="../hello"))
assert response.status_code == status.HTTP_404_NOT_FOUND
async def test_get_file_forbidden_location(self, app: FastAPI, client: AsyncClient, project: Project) -> None:
file_path = "foo/%2e%2e/%2e%2e/%2e%2e/%2e%2e/%2e%2e/%2e%2e/etc/passwd"
response = await client.get(app.url_path_for("get_file", project_id=project.id, file_path=file_path))
assert response.status_code == status.HTTP_403_FORBIDDEN
async def test_write_file(self, app: FastAPI, client: AsyncClient, project: Project) -> None:
response = await client.post(app.url_path_for("write_file", project_id=project.id, file_path="hello"),
content=b"world")
assert response.status_code == status.HTTP_204_NO_CONTENT
with open(os.path.join(project.path, "hello")) as f:
assert f.read() == "world"
response = await client.post(app.url_path_for("write_file", project_id=project.id, file_path="../hello"))
assert response.status_code == status.HTTP_404_NOT_FOUND
async def test_write_file_forbidden_location(self, app: FastAPI, client: AsyncClient, project: Project) -> None:
file_path = "%2e%2e/hello"
response = await client.post(app.url_path_for("write_file", project_id=project.id, file_path=file_path),
content=b"world")
assert response.status_code == status.HTTP_403_FORBIDDEN
async def test_write_and_get_file_with_leading_slashes_in_filename(
self,
app: FastAPI,
client: AsyncClient,
project: Project) -> None:
response = await client.post(app.url_path_for("write_file", project_id=project.id, file_path="//hello"),
content=b"world")
assert response.status_code == status.HTTP_403_FORBIDDEN
response = await client.get(app.url_path_for("get_file", project_id=project.id, file_path="//hello"))
assert response.status_code == status.HTTP_403_FORBIDDEN
async def test_import(self, app: FastAPI, client: AsyncClient, tmpdir, controller: Controller) -> None:
with zipfile_zstd.ZipFile(str(tmpdir / "test.zip"), 'w') as myzip:
myzip.writestr("project.gns3", b'{"project_id": "c6992992-ac72-47dc-833b-54aa334bcd05", "version": "2.0.0", "name": "test"}')
myzip.writestr("demo", b"hello")
project_id = str(uuid.uuid4())
with open(str(tmpdir / "test.zip"), "rb") as f:
response = await client.post(app.url_path_for("import_project", project_id=project_id), content=f.read())
assert response.status_code == status.HTTP_201_CREATED
project = controller.get_project(project_id)
with open(os.path.join(project.path, "demo")) as f:
content = f.read()
assert content == "hello"
async def test_import_with_project_name(
self,
app: FastAPI,
client: AsyncClient,
tmpdir,
controller: Controller
) -> None:
with zipfile_zstd.ZipFile(str(tmpdir / "test.zip"), 'w') as myzip:
myzip.writestr("project.gns3", b'{"project_id": "c6992992-ac72-47dc-833b-54aa334bcd05", "version": "2.0.0", "name": "test"}')
myzip.writestr("demo", b"hello")
project_id = str(uuid.uuid4())
with open(str(tmpdir / "test.zip"), "rb") as f:
response = await client.post(
app.url_path_for("import_project", project_id=project_id),
content=f.read(),
params={"name": "my-imported-project-name"}
)
assert response.status_code == status.HTTP_201_CREATED
project = controller.get_project(project_id)
assert project.name == "my-imported-project-name"
async def test_duplicate(self, app: FastAPI, client: AsyncClient, project: Project) -> None:
response = await client.post(app.url_path_for("duplicate_project", project_id=project.id), json={"name": "hello"})
assert response.status_code == status.HTTP_201_CREATED
assert response.json()["name"] == "hello"
async def test_lock_unlock(self, app: FastAPI, client: AsyncClient, project: Project, compute: Compute) -> None:
# add a drawing and node to the project
params = {
"svg": '<svg height="210" width="500"><line x1="0" y1="0" x2="200" y2="200" style="stroke:rgb(255,0,0);stroke-width:2" /></svg>',
"x": 10,
"y": 20,
"z": 0
}
response = await client.post(app.url_path_for("create_drawing", project_id=project.id), json=params)
assert response.status_code == status.HTTP_201_CREATED
response = MagicMock()
response.json = {"console": 2048}
compute.post = AsyncioMagicMock(return_value=response)
response = await client.post(app.url_path_for("create_node", project_id=project.id), json={
"name": "test",
"node_type": "vpcs",
"compute_id": "example.com",
"properties": {
"startup_script": "echo test"
}
})
assert response.status_code == status.HTTP_201_CREATED
response = await client.post(app.url_path_for("lock_project", project_id=project.id))
assert response.status_code == status.HTTP_204_NO_CONTENT
for drawing in project.drawings.values():
assert drawing.locked is True
for node in project.nodes.values():
assert node.locked is True
response = await client.get(app.url_path_for("locked_project", project_id=project.id))
assert response.status_code == status.HTTP_200_OK
assert response.json() is True
response = await client.post(app.url_path_for("unlock_project", project_id=project.id))
assert response.status_code == status.HTTP_204_NO_CONTENT
for drawing in project.drawings.values():
assert drawing.locked is False
for node in project.nodes.values():
assert node.locked is False

View File

@ -30,47 +30,49 @@ from gns3server.controller.snapshot import Snapshot
pytestmark = pytest.mark.asyncio pytestmark = pytest.mark.asyncio
@pytest_asyncio.fixture class TestSnapshotRoutes:
async def project(app: FastAPI, client: AsyncClient, controller: Controller) -> Project:
u = str(uuid.uuid4()) @pytest_asyncio.fixture
params = {"name": "test", "project_id": u} async def project(self, app: FastAPI, client: AsyncClient, controller: Controller) -> Project:
await client.post(app.url_path_for("create_project"), json=params)
project = controller.get_project(u) u = str(uuid.uuid4())
return project params = {"name": "test", "project_id": u}
await client.post(app.url_path_for("create_project"), json=params)
controller_project = controller.get_project(u)
return controller_project
@pytest_asyncio.fixture @pytest_asyncio.fixture
async def snapshot(project: Project): async def snapshot(self, project: Project):
snapshot = await project.snapshot("test") controller_snapshot = await project.snapshot("test")
return snapshot return controller_snapshot
async def test_list_snapshots(app: FastAPI, client: AsyncClient, project: Project, snapshot: Snapshot) -> None: async def test_list_snapshots(self, app: FastAPI, client: AsyncClient, project: Project, snapshot: Snapshot) -> None:
assert snapshot.name == "test" assert snapshot.name == "test"
response = await client.get(app.url_path_for("get_snapshots", project_id=project.id)) response = await client.get(app.url_path_for("get_snapshots", project_id=project.id))
assert response.status_code == status.HTTP_200_OK assert response.status_code == status.HTTP_200_OK
assert len(response.json()) == 1 assert len(response.json()) == 1
async def test_delete_snapshot(app: FastAPI, client: AsyncClient, project: Project, snapshot: Snapshot) -> None: async def test_delete_snapshot(self, app: FastAPI, client: AsyncClient, project: Project, snapshot: Snapshot) -> None:
response = await client.delete(app.url_path_for("delete_snapshot", project_id=project.id, snapshot_id=snapshot.id)) response = await client.delete(app.url_path_for("delete_snapshot", project_id=project.id, snapshot_id=snapshot.id))
assert response.status_code == status.HTTP_204_NO_CONTENT assert response.status_code == status.HTTP_204_NO_CONTENT
assert not os.path.exists(snapshot.path) assert not os.path.exists(snapshot.path)
async def test_restore_snapshot(app: FastAPI, client: AsyncClient, project: Project, snapshot: Snapshot) -> None: async def test_restore_snapshot(self, app: FastAPI, client: AsyncClient, project: Project, snapshot: Snapshot) -> None:
response = await client.post(app.url_path_for("restore_snapshot", project_id=project.id, snapshot_id=snapshot.id)) response = await client.post(app.url_path_for("restore_snapshot", project_id=project.id, snapshot_id=snapshot.id))
assert response.status_code == status.HTTP_201_CREATED assert response.status_code == status.HTTP_201_CREATED
assert response.json()["name"] == project.name assert response.json()["name"] == project.name
async def test_create_snapshot(app: FastAPI, client: AsyncClient, project: Project) -> None: async def test_create_snapshot(self, app: FastAPI, client: AsyncClient, project: Project) -> None:
response = await client.post(app.url_path_for("create_snapshot", project_id=project.id), json={"name": "snap1"}) response = await client.post(app.url_path_for("create_snapshot", project_id=project.id), json={"name": "snap1"})
assert response.status_code == status.HTTP_201_CREATED assert response.status_code == status.HTTP_201_CREATED
assert len(os.listdir(os.path.join(project.path, "snapshots"))) == 1 assert len(os.listdir(os.path.join(project.path, "snapshots"))) == 1

View File

@ -28,41 +28,43 @@ from gns3server.controller import Controller
pytestmark = pytest.mark.asyncio pytestmark = pytest.mark.asyncio
async def test_symbols(app: FastAPI, client: AsyncClient) -> None: class TestSymbolRoutes:
response = await client.get(app.url_path_for("get_symbols")) async def test_symbols(self, app: FastAPI, client: AsyncClient) -> None:
assert response.status_code == status.HTTP_200_OK response = await client.get(app.url_path_for("get_symbols"))
assert {
'symbol_id': ':/symbols/classic/firewall.svg', assert response.status_code == status.HTTP_200_OK
'filename': 'firewall.svg', assert {
'builtin': True, 'symbol_id': ':/symbols/classic/firewall.svg',
'theme': 'Classic' 'filename': 'firewall.svg',
} in response.json() 'builtin': True,
'theme': 'Classic'
} in response.json()
async def test_get(app: FastAPI, client: AsyncClient, controller: Controller) -> None: async def test_get(self, app: FastAPI, client: AsyncClient, controller: Controller) -> None:
controller.symbols.theme = "Classic" controller.symbols.theme = "Classic"
url = app.url_path_for("get_symbol", symbol_id=urllib.parse.quote(':/symbols/classic/firewall.svg')) url = app.url_path_for("get_symbol", symbol_id=urllib.parse.quote(':/symbols/classic/firewall.svg'))
response = await client.get(url) response = await client.get(url)
assert response.status_code == status.HTTP_200_OK assert response.status_code == status.HTTP_200_OK
assert response.headers['CONTENT-TYPE'] == 'image/svg+xml' assert response.headers['CONTENT-TYPE'] == 'image/svg+xml'
assert response.headers['CONTENT-LENGTH'] == '9381' assert response.headers['CONTENT-LENGTH'] == '9381'
assert '</svg>' in response.text assert '</svg>' in response.text
# Reply with the default symbol # Reply with the default symbol
response = await client.get(app.url_path_for("get_symbol", symbol_id="404.png")) response = await client.get(app.url_path_for("get_symbol", symbol_id="404.png"))
assert response.status_code == status.HTTP_200_OK assert response.status_code == status.HTTP_200_OK
async def test_upload(app: FastAPI, client: AsyncClient, symbols_dir: str) -> None: async def test_upload(self, app: FastAPI, client: AsyncClient, symbols_dir: str) -> None:
response = await client.post(app.url_path_for("upload_symbol", symbol_id="test2"), content=b"TEST") response = await client.post(app.url_path_for("upload_symbol", symbol_id="test2"), content=b"TEST")
assert response.status_code == status.HTTP_204_NO_CONTENT assert response.status_code == status.HTTP_204_NO_CONTENT
with open(os.path.join(symbols_dir, "test2")) as f: with open(os.path.join(symbols_dir, "test2")) as f:
assert f.read() == "TEST" assert f.read() == "TEST"
response = await client.get(app.url_path_for("get_symbol", symbol_id="test2")) response = await client.get(app.url_path_for("get_symbol", symbol_id="test2"))
assert response.status_code == status.HTTP_200_OK assert response.status_code == status.HTTP_200_OK

View File

@ -254,22 +254,6 @@ class TestUserLogin:
assert "token_type" in response.json() assert "token_type" in response.json()
assert response.json().get("token_type") == "bearer" assert response.json().get("token_type") == "bearer"
async def test_user_can_authenticate_using_json(
self,
app: FastAPI,
unauthorized_client: AsyncClient,
test_user: User,
config: Config
) -> None:
credentials = {
"username": test_user.username,
"password": "user1_password",
}
response = await unauthorized_client.post(app.url_path_for("authenticate"), json=credentials)
assert response.status_code == status.HTTP_200_OK
assert response.json().get("access_token")
@pytest.mark.parametrize( @pytest.mark.parametrize(
"username, password, status_code", "username, password, status_code",
( (
@ -299,7 +283,19 @@ class TestUserLogin:
assert response.status_code == status_code assert response.status_code == status_code
assert "access_token" not in response.json() assert "access_token" not in response.json()
async def test_user_can_use_token_as_url_param(
class TestUnauthorizedUser:
async def test_user_cannot_access_own_data_if_not_authenticated(
self, app: FastAPI,
unauthorized_client: AsyncClient,
test_user: User,
) -> None:
response = await unauthorized_client.get(app.url_path_for("get_logged_in_user"))
assert response.status_code == status.HTTP_401_UNAUTHORIZED
async def test_user_can_authenticate_using_json(
self, self,
app: FastAPI, app: FastAPI,
unauthorized_client: AsyncClient, unauthorized_client: AsyncClient,
@ -311,15 +307,14 @@ class TestUserLogin:
"username": test_user.username, "username": test_user.username,
"password": "user1_password", "password": "user1_password",
} }
response = await unauthorized_client.post(app.url_path_for("authenticate"), json=credentials) response = await unauthorized_client.post(app.url_path_for("authenticate"), json=credentials)
assert response.status_code == status.HTTP_200_OK assert response.status_code == status.HTTP_200_OK
token = response.json().get("access_token") assert response.json().get("access_token")
token = response.json().get("access_token")
response = await unauthorized_client.get(app.url_path_for("statistics"), params={"token": token}) response = await unauthorized_client.get(app.url_path_for("statistics"), params={"token": token})
assert response.status_code == status.HTTP_200_OK assert response.status_code == status.HTTP_200_OK
class TestUserMe: class TestUserMe:
async def test_authenticated_user_can_retrieve_own_data( async def test_authenticated_user_can_retrieve_own_data(
@ -336,15 +331,6 @@ class TestUserMe:
assert user.email == test_user.email assert user.email == test_user.email
assert user.user_id == test_user.user_id assert user.user_id == test_user.user_id
async def test_user_cannot_access_own_data_if_not_authenticated(
self, app: FastAPI,
unauthorized_client: AsyncClient,
test_user: User,
) -> None:
response = await unauthorized_client.get(app.url_path_for("get_logged_in_user"))
assert response.status_code == status.HTTP_401_UNAUTHORIZED
async def test_authenticated_user_can_update_own_data( async def test_authenticated_user_can_update_own_data(
self, self,
app: FastAPI, app: FastAPI,

View File

@ -25,38 +25,41 @@ from gns3server.version import __version__
pytestmark = pytest.mark.asyncio pytestmark = pytest.mark.asyncio
async def test_version_output(app: FastAPI, client: AsyncClient) -> None: class TestVersionRoutes:
response = await client.get(app.url_path_for("get_version"))
assert response.status_code == status.HTTP_200_OK
assert response.json() == {'controller_host': '127.0.0.1', 'local': False, 'version': __version__}
async def test_version_input(app: FastAPI, client: AsyncClient) -> None: async def test_version_output(self, app: FastAPI, client: AsyncClient) -> None:
params = {'version': __version__} response = await client.get(app.url_path_for("get_version"))
response = await client.post(app.url_path_for("check_version"), json=params) assert response.status_code == status.HTTP_200_OK
assert response.status_code == status.HTTP_200_OK assert response.json() == {'controller_host': '127.0.0.1', 'local': False, 'version': __version__}
assert response.json() == {'version': __version__}
async def test_version_invalid_input(app: FastAPI, client: AsyncClient) -> None: async def test_version_input(self, app: FastAPI, client: AsyncClient) -> None:
params = {'version': "0.4.2"} params = {'version': __version__}
response = await client.post(app.url_path_for("check_version"), json=params) response = await client.post(app.url_path_for("check_version"), json=params)
assert response.status_code == status.HTTP_409_CONFLICT assert response.status_code == status.HTTP_200_OK
assert response.json() == {'message': 'Client version 0.4.2 is not the same as server version {}'.format(__version__)} assert response.json() == {'version': __version__}
async def test_version_invalid_input_schema(app: FastAPI, client: AsyncClient) -> None: async def test_version_invalid_input(self, app: FastAPI, client: AsyncClient) -> None:
params = {'version': "0.4.2", "bla": "blu"} params = {'version': "0.4.2"}
response = await client.post(app.url_path_for("check_version"), json=params) response = await client.post(app.url_path_for("check_version"), json=params)
assert response.status_code == status.HTTP_409_CONFLICT assert response.status_code == status.HTTP_409_CONFLICT
assert response.json() == {'message': 'Client version 0.4.2 is not the same as server version {}'.format(__version__)}
async def test_version_invalid_json(app: FastAPI, client: AsyncClient) -> None: async def test_version_invalid_input_schema(self, app: FastAPI, client: AsyncClient) -> None:
params = "BOUM" params = {'version': "0.4.2", "bla": "blu"}
response = await client.post(app.url_path_for("check_version"), json=params) response = await client.post(app.url_path_for("check_version"), json=params)
assert response.status_code == status.HTTP_422_UNPROCESSABLE_ENTITY assert response.status_code == status.HTTP_409_CONFLICT
async def test_version_invalid_json(self, app: FastAPI, client: AsyncClient) -> None:
params = "BOUM"
response = await client.post(app.url_path_for("check_version"), json=params)
assert response.status_code == status.HTTP_422_UNPROCESSABLE_ENTITY

View File

@ -29,55 +29,57 @@ from gns3server.utils.get_resource import get_resource
pytestmark = pytest.mark.asyncio pytestmark = pytest.mark.asyncio
def get_static(filename): class TestIndexRoutes:
current_dir = os.path.dirname(os.path.abspath(__file__)) def get_static(self, filename):
return os.path.join(os.path.abspath(os.path.join(current_dir, '../..', '..', 'gns3server', 'static')), filename)
current_dir = os.path.dirname(os.path.abspath(__file__))
return os.path.join(os.path.abspath(os.path.join(current_dir, '../..', '..', 'gns3server', 'static')), filename)
async def test_debug(app: FastAPI, client: AsyncClient) -> None: async def test_debug(self, app: FastAPI, client: AsyncClient) -> None:
response = await client.get(app.url_path_for("debug")) response = await client.get(app.url_path_for("debug"))
assert response.status_code == status.HTTP_200_OK
html = response.read().decode()
assert "Website" in html
assert __version__ in html
# @pytest.mark.asyncio
# async def test_controller(http_client, controller):
#
# await controller.add_project(name="test")
# response = await http_client.get('/controller')
# assert "test" in await response.text()
# assert response.status_code == 200
#
#
# @pytest.mark.asyncio
# async def test_compute(http_client):
#
# response = await http_client.get('/compute')
# assert response.status_code == 200
# @pytest.mark.asyncio
# async def test_project(http_client, controller):
#
# project = await controller.add_project(name="test")
# response = await http_client.get('/projects/{}'.format(project.id))
# assert response.status_code == 200
async def test_web_ui(app: FastAPI, client: AsyncClient) -> None:
response = await client.get(app.url_path_for("web_ui", file_path="index.html"))
assert response.status_code == status.HTTP_200_OK
async def test_web_ui_not_found(app: FastAPI, client: AsyncClient, tmpdir: str) -> None:
with patch('gns3server.utils.get_resource.get_resource') as mock:
mock.return_value = str(tmpdir)
response = await client.get(app.url_path_for("web_ui", file_path="not-found.txt"))
# should serve web-ui/index.html
assert response.status_code == status.HTTP_200_OK assert response.status_code == status.HTTP_200_OK
html = response.read().decode()
assert "Website" in html
assert __version__ in html
# @pytest.mark.asyncio
# async def test_controller(http_client, controller):
#
# await controller.add_project(name="test")
# response = await http_client.get('/controller')
# assert "test" in await response.text()
# assert response.status_code == 200
#
#
# @pytest.mark.asyncio
# async def test_compute(http_client):
#
# response = await http_client.get('/compute')
# assert response.status_code == 200
# @pytest.mark.asyncio
# async def test_project(http_client, controller):
#
# project = await controller.add_project(name="test")
# response = await http_client.get('/projects/{}'.format(project.id))
# assert response.status_code == 200
async def test_web_ui(self, app: FastAPI, client: AsyncClient) -> None:
response = await client.get(app.url_path_for("web_ui", file_path="index.html"))
assert response.status_code == status.HTTP_200_OK
async def test_web_ui_not_found(self, app: FastAPI, client: AsyncClient, tmpdir: str) -> None:
with patch('gns3server.utils.get_resource.get_resource') as mock:
mock.return_value = str(tmpdir)
response = await client.get(app.url_path_for("web_ui", file_path="not-found.txt"))
# should serve web-ui/index.html
assert response.status_code == status.HTTP_200_OK

View File

@ -44,40 +44,49 @@ ALLOWED_CONTROLLER_ENDPOINTS = [
("/v3/symbols/default_symbols", "GET") ("/v3/symbols/default_symbols", "GET")
] ]
class TestRoutes:
# Controller endpoints have a OAuth2 bearer token authentication # Controller endpoints have a OAuth2 bearer token authentication
async def test_controller_endpoints_require_authentication(app: FastAPI, unauthorized_client: AsyncClient) -> None: async def test_controller_endpoints_require_authentication(
self,
app: FastAPI,
unauthorized_client: AsyncClient
) -> None:
for route in app.routes: for route in app.routes:
if isinstance(route, APIRoute): if isinstance(route, APIRoute):
for method in list(route.methods): for method in list(route.methods):
if (route.path, method) not in ALLOWED_CONTROLLER_ENDPOINTS: if (route.path, method) not in ALLOWED_CONTROLLER_ENDPOINTS:
response = await getattr(unauthorized_client, method.lower())(route.path) response = await getattr(unauthorized_client, method.lower())(route.path)
assert response.status_code == status.HTTP_401_UNAUTHORIZED
elif isinstance(route, APIWebSocketRoute):
params = {"token": "wrong_token"}
async with AsyncClient(base_url="http://test-api", transport=ASGIWebSocketTransport(app)) as client:
async with aconnect_ws(route.path, client, params=params) as ws:
json_notification = await ws.receive_json()
assert json_notification['event'] == {
'message': 'Could not authenticate while connecting to controller WebSocket: Could not validate credentials'
}
# Compute endpoints have a basic HTTP authentication
async def test_compute_endpoints_require_authentication(app: FastAPI, unauthorized_client: AsyncClient) -> None:
for route in app.routes:
if isinstance(route, Mount):
for compute_route in route.routes:
if isinstance(compute_route, APIRoute):
for method in list(compute_route.methods):
response = await getattr(unauthorized_client, method.lower())(route.path + compute_route.path)
assert response.status_code == status.HTTP_401_UNAUTHORIZED assert response.status_code == status.HTTP_401_UNAUTHORIZED
elif isinstance(compute_route, APIWebSocketRoute): elif isinstance(route, APIWebSocketRoute):
async with AsyncClient(base_url="http://test-api", transport=ASGIWebSocketTransport(app)) as client: params = {"token": "wrong_token"}
async with aconnect_ws(route.path + compute_route.path, client, auth=("wrong_user", "password123")) as ws: async with AsyncClient(base_url="http://test-api", transport=ASGIWebSocketTransport(app=app)) as client:
json_notification = await ws.receive_json() async with aconnect_ws(route.path, client, params=params) as ws:
assert json_notification['event'] == { json_notification = await ws.receive_json()
'message': 'Could not authenticate while connecting to compute WebSocket: Could not validate credentials' assert json_notification['event'] == {
} 'message': 'Could not authenticate while connecting to controller WebSocket: Could not validate credentials'
}
# Compute endpoints have a basic HTTP authentication
async def test_compute_endpoints_require_authentication(
self,
app: FastAPI,
unauthorized_client: AsyncClient
) -> None:
for route in app.routes:
if isinstance(route, Mount):
for compute_route in route.routes:
if isinstance(compute_route, APIRoute):
for method in list(compute_route.methods):
response = await getattr(unauthorized_client, method.lower())(route.path + compute_route.path)
assert response.status_code == status.HTTP_401_UNAUTHORIZED
elif isinstance(compute_route, APIWebSocketRoute):
async with AsyncClient(base_url="http://test-api", transport=ASGIWebSocketTransport(app=app)) as client:
async with aconnect_ws(route.path + compute_route.path, client, auth=("wrong_user", "password123")) as ws:
json_notification = await ws.receive_json()
assert json_notification['event'] == {
'message': 'Could not authenticate while connecting to compute WebSocket: Could not validate credentials'
}

View File

@ -25,6 +25,8 @@ from gns3server.compute.nios.nio_udp import NIOUDP
from tests.utils import asyncio_patch from tests.utils import asyncio_patch
pytestmark = pytest.mark.asyncio
@pytest.fixture @pytest.fixture
def nio(): def nio():
@ -39,7 +41,6 @@ async def manager():
return m return m
@pytest.mark.asyncio
async def test_json_with_ports(on_gns3vm, compute_project, manager): async def test_json_with_ports(on_gns3vm, compute_project, manager):
ports = [ ports = [
@ -78,7 +79,7 @@ async def test_json_with_ports(on_gns3vm, compute_project, manager):
} }
def test_json_without_ports(on_gns3vm, compute_project, manager): async def test_json_without_ports(on_gns3vm, compute_project, manager):
""" """
If no interface is provide the cloud is pre-fill with non special interfaces If no interface is provide the cloud is pre-fill with non special interfaces
""" """
@ -117,7 +118,6 @@ def test_json_without_ports(on_gns3vm, compute_project, manager):
} }
@pytest.mark.asyncio
async def test_update_port_mappings(on_gns3vm, compute_project): async def test_update_port_mappings(on_gns3vm, compute_project):
""" """
We don't allow an empty interface in the middle of port list We don't allow an empty interface in the middle of port list
@ -158,7 +158,6 @@ async def test_update_port_mappings(on_gns3vm, compute_project):
assert cloud.ports_mapping == ports1 assert cloud.ports_mapping == ports1
@pytest.mark.asyncio
async def test_linux_ethernet_raw_add_nio(linux_platform, compute_project, nio): async def test_linux_ethernet_raw_add_nio(linux_platform, compute_project, nio):
ports = [ ports = [
{ {
@ -186,7 +185,6 @@ async def test_linux_ethernet_raw_add_nio(linux_platform, compute_project, nio):
]) ])
@pytest.mark.asyncio
async def test_linux_ethernet_raw_add_nio_bridge(linux_platform, compute_project, nio): async def test_linux_ethernet_raw_add_nio_bridge(linux_platform, compute_project, nio):
""" """
Bridge can't be connected directly to a cloud we use a tap in the middle Bridge can't be connected directly to a cloud we use a tap in the middle

View File

@ -1,5 +1,4 @@
import pytest import pytest
import asyncio
import pytest_asyncio import pytest_asyncio
import tempfile import tempfile
import shutil import shutil
@ -13,6 +12,7 @@ import stat
from fastapi import FastAPI from fastapi import FastAPI
from sqlalchemy.ext.asyncio import AsyncSession, create_async_engine from sqlalchemy.ext.asyncio import AsyncSession, create_async_engine
from httpx import AsyncClient from httpx import AsyncClient
from httpx_ws.transport import ASGIWebSocketTransport
from unittest.mock import MagicMock, patch from unittest.mock import MagicMock, patch
from pathlib import Path from pathlib import Path
@ -34,25 +34,14 @@ sys._called_from_test = True
sys.original_platform = sys.platform sys.original_platform = sys.platform
# https://github.com/pytest-dev/pytest-asyncio/issues/68 @pytest_asyncio.fixture(loop_scope="class", scope="class")
# this event_loop is used by pytest-asyncio, and redefining it
# is currently the only way of changing the scope of this fixture
@pytest.fixture(scope="class")
def event_loop(request):
loop = asyncio.get_event_loop_policy().new_event_loop()
yield loop
loop.close()
@pytest_asyncio.fixture(scope="class")
async def app() -> FastAPI: async def app() -> FastAPI:
from gns3server.api.server import app as gns3app from gns3server.api.server import app as gns3app
yield gns3app yield gns3app
@pytest_asyncio.fixture(scope="class") @pytest_asyncio.fixture(loop_scope="class", scope="class")
async def db_engine(): async def db_engine():
db_url = os.getenv("GNS3_TEST_DATABASE_URI", "sqlite+aiosqlite:///:memory:") # "sqlite:///./sql_test_app.db" db_url = os.getenv("GNS3_TEST_DATABASE_URI", "sqlite+aiosqlite:///:memory:") # "sqlite:///./sql_test_app.db"
@ -61,7 +50,7 @@ async def db_engine():
#await engine.sync_engine.dispose() #await engine.sync_engine.dispose()
@pytest_asyncio.fixture(scope="class") @pytest_asyncio.fixture(loop_scope="class", scope="class")
async def db_session(db_engine): async def db_session(db_engine):
# recreate database tables for each class # recreate database tables for each class
@ -82,7 +71,7 @@ async def db_session(db_engine):
await session.close() await session.close()
@pytest_asyncio.fixture @pytest_asyncio.fixture(loop_scope="class", scope="class")
async def base_client(app: FastAPI, db_session: AsyncSession) -> AsyncClient: async def base_client(app: FastAPI, db_session: AsyncSession) -> AsyncClient:
async def _get_test_db(): async def _get_test_db():
@ -94,14 +83,14 @@ async def base_client(app: FastAPI, db_session: AsyncSession) -> AsyncClient:
app.dependency_overrides[get_db_session] = _get_test_db app.dependency_overrides[get_db_session] = _get_test_db
async with AsyncClient( async with AsyncClient(
app=app,
base_url="http://test-api", base_url="http://test-api",
headers={"Content-Type": "application/json"} headers={"Content-Type": "application/json"},
transport=ASGIWebSocketTransport(app=app)
) as async_client: ) as async_client:
yield async_client yield async_client
@pytest_asyncio.fixture @pytest_asyncio.fixture(loop_scope="class", scope="class")
async def test_user(db_session: AsyncSession) -> User: async def test_user(db_session: AsyncSession) -> User:
new_user = schemas.UserCreate( new_user = schemas.UserCreate(
@ -121,7 +110,7 @@ async def test_user(db_session: AsyncSession) -> User:
return user return user
@pytest_asyncio.fixture @pytest_asyncio.fixture(loop_scope="class", scope="class")
async def test_compute(db_session: AsyncSession) -> Compute: async def test_compute(db_session: AsyncSession) -> Compute:
new_compute = schemas.ComputeCreate( new_compute = schemas.ComputeCreate(
@ -140,12 +129,12 @@ async def test_compute(db_session: AsyncSession) -> Compute:
return await compute_repo.create_compute(new_compute) return await compute_repo.create_compute(new_compute)
@pytest.fixture @pytest_asyncio.fixture(loop_scope="class", scope="class")
def unauthorized_client(base_client: AsyncClient, test_user: User) -> AsyncClient: def unauthorized_client(base_client: AsyncClient, test_user: User) -> AsyncClient:
return base_client return base_client
@pytest.fixture @pytest_asyncio.fixture(loop_scope="class", scope="class")
def authorized_client(base_client: AsyncClient, test_user: User) -> AsyncClient: def authorized_client(base_client: AsyncClient, test_user: User) -> AsyncClient:
access_token = auth_service.create_access_token(test_user.username) access_token = auth_service.create_access_token(test_user.username)
@ -156,7 +145,7 @@ def authorized_client(base_client: AsyncClient, test_user: User) -> AsyncClient:
return base_client return base_client
@pytest_asyncio.fixture @pytest_asyncio.fixture(loop_scope="class", scope="class")
async def client(base_client: AsyncClient) -> AsyncClient: async def client(base_client: AsyncClient) -> AsyncClient:
# The super admin is automatically created when the users table is created # The super admin is automatically created when the users table is created
@ -169,7 +158,7 @@ async def client(base_client: AsyncClient) -> AsyncClient:
return base_client return base_client
@pytest_asyncio.fixture @pytest_asyncio.fixture(loop_scope="class", scope="class")
async def compute_client(base_client: AsyncClient) -> AsyncClient: async def compute_client(base_client: AsyncClient) -> AsyncClient:
# default compute username is 'gns3' # default compute username is 'gns3'

2
tests/pytest.ini Normal file
View File

@ -0,0 +1,2 @@
[pytest]
asyncio_default_fixture_loop_scope=function