gns3-server/tests/controller/test_link.py

243 lines
7.4 KiB
Python

#!/usr/bin/env python
#
# Copyright (C) 2016 GNS3 Technologies Inc.
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
import os
import pytest
import aiohttp
import asyncio
from unittest.mock import MagicMock
from gns3server.controller.link import Link
from gns3server.controller.node import Node
from gns3server.controller.compute import Compute
from gns3server.controller.project import Project
from tests.utils import AsyncioBytesIO, AsyncioMagicMock
@pytest.fixture
def project(controller):
return Project(controller=controller, name="Test")
@pytest.fixture
def compute():
return Compute("example.com", controller=MagicMock())
@pytest.fixture
def link(async_run, project, compute):
node1 = Node(project, compute, "node1", node_type="qemu")
node2 = Node(project, compute, "node2", node_type="qemu")
link = Link(project)
link.create = AsyncioMagicMock()
async_run(link.add_node(node1, 0, 4))
async_run(link.add_node(node2, 1, 3))
return link
def test_eq(project, link, controller):
assert link == Link(project, link_id=link.id)
assert link != "a"
assert link != Link(project)
def test_add_node(async_run, project, compute):
node1 = Node(project, compute, "node1", node_type="qemu")
link = Link(project)
link.create = AsyncioMagicMock()
link._project.controller.notification.emit = MagicMock()
project.dump = AsyncioMagicMock()
async_run(link.add_node(node1, 0, 4))
assert link._nodes == [
{
"node": node1,
"adapter_number": 0,
"port_number": 4,
'label': {
'y': -10,
'text': '0/4',
'x': -10,
'rotation': 0,
'style': 'font-size: 10; font-style: Verdana'
}
}
]
assert project.dump.called
assert not link._project.controller.notification.emit.called
assert not link.create.called
# We call link.created only when both side are created
node2 = Node(project, compute, "node2", node_type="qemu")
async_run(link.add_node(node2, 0, 4))
assert link.create.called
link._project.controller.notification.emit.assert_called_with("link.created", link.__json__())
def test_add_node_cloud(async_run, project, compute):
node1 = Node(project, compute, "node1", node_type="qemu")
node2 = Node(project, compute, "node2", node_type="cloud")
link = Link(project)
link.create = AsyncioMagicMock()
link._project.controller.notification.emit = MagicMock()
async_run(link.add_node(node1, 0, 4))
async_run(link.add_node(node2, 0, 4))
def test_add_node_cloud_to_cloud(async_run, project, compute):
"""
Cloud to cloud connection is not allowed
"""
node1 = Node(project, compute, "node1", node_type="cloud")
node2 = Node(project, compute, "node2", node_type="cloud")
link = Link(project)
link.create = AsyncioMagicMock()
link._project.controller.notification.emit = MagicMock()
async_run(link.add_node(node1, 0, 4))
with pytest.raises(aiohttp.web.HTTPConflict):
async_run(link.add_node(node2, 0, 4))
def test_json(async_run, project, compute):
node1 = Node(project, compute, "node1", node_type="qemu")
node2 = Node(project, compute, "node2", node_type="qemu")
link = Link(project)
link.create = AsyncioMagicMock()
async_run(link.add_node(node1, 0, 4))
async_run(link.add_node(node2, 1, 3))
assert link.__json__() == {
"link_id": link.id,
"project_id": project.id,
"nodes": [
{
"node_id": node1.id,
"adapter_number": 0,
"port_number": 4,
'label': {
'y': -10,
'text': '0/4',
'x': -10,
'rotation': 0,
'style': 'font-size: 10; font-style: Verdana'
}
},
{
"node_id": node2.id,
"adapter_number": 1,
"port_number": 3,
'label': {
'y': -10,
'text': '1/3',
'x': -10,
'rotation': 0,
'style': 'font-size: 10; font-style: Verdana'
}
}
],
"capturing": False,
"capture_file_name": None,
"capture_file_path": None
}
assert link.__json__(topology_dump=True) == {
"link_id": link.id,
"nodes": [
{
"node_id": node1.id,
"adapter_number": 0,
"port_number": 4,
'label': {
'y': -10,
'text': '0/4',
'x': -10,
'rotation': 0,
'style': 'font-size: 10; font-style: Verdana'
}
},
{
"node_id": node2.id,
"adapter_number": 1,
"port_number": 3,
'label': {
'y': -10,
'text': '1/3',
'x': -10,
'rotation': 0,
'style': 'font-size: 10; font-style: Verdana'
}
}
]
}
def test_start_streaming_pcap(link, async_run, tmpdir, project):
@asyncio.coroutine
def fake_reader():
output = AsyncioBytesIO()
yield from output.write(b"hello")
output.seek(0)
return output
link._capture_file_name = "test.pcap"
link._capturing = True
link.read_pcap_from_source = fake_reader
async_run(link._start_streaming_pcap())
with open(os.path.join(project.captures_directory, "test.pcap"), "rb") as f:
c = f.read()
assert c == b"hello"
def test_default_capture_file_name(project, compute, async_run):
node1 = Node(project, compute, "Hello@", node_type="qemu")
node2 = Node(project, compute, "w0.rld", node_type="qemu")
link = Link(project)
link.create = AsyncioMagicMock()
async_run(link.add_node(node1, 0, 4))
async_run(link.add_node(node2, 1, 3))
assert link.default_capture_file_name() == "Hello_0-4_to_w0rld_1-3.pcap"
def test_start_capture(link, async_run, tmpdir, project, controller):
@asyncio.coroutine
def fake_reader():
return AsyncioBytesIO()
link.read_pcap_from_source = fake_reader
controller._notification = MagicMock()
async_run(link.start_capture(capture_file_name="test.pcap"))
assert link._capturing
assert link._capture_file_name == "test.pcap"
controller._notification.emit.assert_called_with("link.updated", link.__json__())
def test_stop_capture(link, async_run, tmpdir, project, controller):
link._capturing = True
controller._notification = MagicMock()
async_run(link.stop_capture())
assert link._capturing is False
controller._notification.emit.assert_called_with("link.updated", link.__json__())