# Copyright (c) 2011 - 2017, Intel Corporation.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""``test_fixtures.py``
Unittests for TAF fixtures`
"""
import copy
import os
import xmlrpc.client
from unittest.mock import patch, MagicMock, Mock
import pytest
from .common import FakeXMLRPCServer
from testlib import fixtures
from testlib import common3
# config of environment
ENV = [
{"name": "Zero Cross", "entry_type": "cross", "instance_type": "static_ons", "id": "5",
"kprio": 10, "sprio": 300, "cprio": 300, "tprio": 300},
{"name": "IXIA-103", "entry_type": "tg", "instance_type": "ixiahl", "id": "03",
"ip_host": "192.168.0.250", "kprio": 200, "sprio": 200, "cprio": 200, "tprio": 200,
"ports": [[1, 1, 1], [1, 1, 2]]},
{"name": "sct01or", "entry_type": "switch", "instance_type": "seacliff", "id": "1",
"kprio": 100, "ip_host": "192.168.0.11", "ip_port": "8081",
"use_sshtun": 1, "sshtun_user": "admin", "sshtun_pass": "admin",
"sshtun_port": 22, "default_gw": "192.168.0.1", "net_mask": "255.255.255.0",
"ports_count": 52, "pwboard_host": "10.10.10.10", "pwboard_port": "23", "halt": 0,
"use_serial": False,
"portserv_host": "10.10.10.11", "portserv_user": "admin",
"portserv_pass": "password", "portserv_tty": 6, "portserv_port": 2501,
"telnet_loginprompt": "localhost login:", "telnet_passprompt": "Password:",
"telnet_user": "admin", "telnet_pass": "admin",
"telnet_prompt": "[admin@localhost ~]$",
"cli_user": "admin", "cli_user_passw": "admin", "cli_user_prompt": "Switch ",
"ports": [],
"related_id": []},
{"name": "sct02or", "entry_type": "switch", "instance_type": "seacliff", "id": "2",
"kprio": 100, "ip_host": "192.168.0.12", "ip_port": "8081",
"use_sshtun": 1, "sshtun_user": "admin", "sshtun_pass": "admin",
"sshtun_port": 22, "default_gw": "192.168.0.1", "net_mask": "255.255.255.0",
"ports_count": 52, "pwboard_host": "10.10.10.12", "pwboard_port": "22", "halt": 0,
"use_serial": False,
"portserv_host": "10.10.10.13", "portserv_user": "admin",
"portserv_pass": "password", "portserv_tty": 6, "portserv_port": 2502,
"telnet_loginprompt": "localhost login:", "telnet_passprompt": "Password:",
"telnet_user": "admin", "telnet_pass": "admin",
"telnet_prompt": "[admin@localhost ~]$",
"cli_user": "admin", "cli_user_passw": "admin", "cli_user_prompt": "Switch ",
"ports": [],
"related_id": []},
]
# simplified setup
SETUP_SIMPLIFIED = {
"env": [
{"id": "03", "ports": [[1, 1, 1], [1, 1, 2], [1, 1, 3], [1, 1, 4], [1, 1, 5]]},
{"id": "1", "ports": [5, 4, 3, 2, 1]},
{"id": "5", "related_id": ["03", "1"]},
],
"cross":
{"5":
[
["03", 1, "1", 1],
["03", 2, "1", 2],
["03", 3, "1", 3],
["03", 4, "1", 4],
["03", 5, "1", 5],
],
},
}
# simplified setup with port_list
SETUP_SIMPLIFIED_LIST = {
"env": [
{"id": "03", "ports": [[1, 1, 1], [1, 1, 2], [1, 1, 3], [1, 1, 4], [1, 1, 5]]},
{"id": "1", "port_list": [[5, 10000],
[4, 10000],
[3, 10000],
[2, 10000],
[1, 40000]]},
{"id": "5", "related_id": ["03", "1"]},
],
"cross":
{"5":
[
["03", 1, "1", 1],
["03", 2, "1", 2],
["03", 3, "1", 3],
["03", 4, "1", 4],
["03", 5, "1", 5],
],
},
}
# complex setup
SETUP_COMPLEX = {
"env": [
{"id": "03", "ports": [[1, 1, 1], [1, 1, 2], [1, 1, 3], [1, 1, 4], [1, 1, 5]]},
{"id": "1", "ports": [1, 2, 3, 6, 7]},
{"id": "2", "ports": [3, 4, 8, 9]},
{"id": "5", "related_id": ["03", "1", "2"]},
],
"cross":
{"5":
[
["03", 1, "1", 1],
["03", 2, "1", 2],
["03", 3, "1", 3],
["03", 3, "2", 1],
["03", 4, "2", 2],
["1", 4, "2", 3],
["1", 5, "2", 4],
],
},
}
[docs]class EnvTest(object):
def __init__(self, setup, env):
self.setup_dict = setup
self.env = env
[docs] def start(self, request, monkeypatch, xmlrpcs):
for serv in xmlrpcs:
serv.lags = []
serv.ports_to_lags = []
_env_list = self.env
_setup_dict = self.setup_dict
# first method for monkeypatching
def _setup(self, x):
_s = copy.deepcopy(_setup_dict)
return _s
# second method for monkeypatching
def _conf(self, x):
_e = copy.deepcopy(_env_list)
return _e
def clearconfig(*args, **kwargs):
pass
# monkeypatching methods _get_conf and _get_setup
monkeypatch.setattr(common3.Environment, "_get_conf", _conf)
monkeypatch.setattr(common3.Environment, "_get_setup", _setup)
# define environment with fake class
# mock Tkinter so we don't need Ixia installed
# I only know how to do this with mock, if monkeypatch can do this we should use that
with patch.dict('sys.modules', {'Tkinter': MagicMock()}):
env = common3.Environment(FakeOpts())
# Create fake XMLRPC server
for switch, serv in zip(iter(env.switch.values()), xmlrpcs): # pylint: disable=no-member
# use the actual port of the server from the BaseServer superclass attribute
prox = xmlrpc.client.ServerProxy('http://{0[0]}:{0[1]}'.format(serv.server.server_address))
switch.xmlproxy = prox # pylint: disable=no-member
switch.hw.max_lags = 256 # pylint: disable=no-member
switch.clearconfig = clearconfig
return env
# fake class for options
[docs]class FakeOpts(object):
# fake json file
setup = "setup.json"
# fake json file
env = ""
get_only = True
build_path = ''
ui = 'ons_xmlrpc'
@pytest.fixture(scope="module")
[docs]def fake_xmlrpc(request):
servers = set()
for port in {9001, 9002}:
# make unique ports per PID so we don't have errno 98 Address already in use races.
xml = FakeXMLRPCServer(port + os.getpid())
xml.start()
servers.add(xml)
def _stop():
for serv in servers:
serv.stop()
request.addfinalizer(_stop)
return servers
@pytest.fixture()
[docs]def env(request, monkeypatch, fake_xmlrpc):
"""Fixture of environment with LXC for unittests of methods get_ports and get_speed.
"""
env = EnvTest(SETUP_SIMPLIFIED, ENV)
return env.start(request, monkeypatch, fake_xmlrpc)
@pytest.fixture()
[docs]def env_list(request, monkeypatch, fake_xmlrpc):
"""Fixture of environment with LXC for unittests of methods get_ports and get_speed.
"""
env = EnvTest(SETUP_SIMPLIFIED_LIST, ENV)
return env.start(request, monkeypatch, fake_xmlrpc)
@pytest.fixture()
[docs]def env_complex(request, monkeypatch, fake_xmlrpc):
"""Fixture of environment with LXC for unittests of methods get_ports and get_speed.
"""
env = EnvTest(SETUP_COMPLEX, ENV)
return env.start(request, monkeypatch, fake_xmlrpc)
# Tests for env_lag fixture
[docs]def test_env_lag_1(request, env):
"""Verify env_lag fixture adds LAGs into ports list.
"""
fixtures.env_lag(request, env)
for _switch in env.switch.values():
_switch.clearconfig()
assert env.switch[1].ports == [5, 4, 3, 2, 1, 3800, 3801, 3802, 3803, 3804]
assert env.switch[1].port_list == []
[docs]def test_env_lag_2(request, env):
"""Verify env_lag fixture adds LAGs into LagsAdmin table.
"""
fixtures.env_lag(request, env)
for _switch in env.switch.values():
_switch.clearconfig()
lags = set(x['lagId'] for x in env.switch[1].ui.get_table_lags())
assert lags == {3800, 3801, 3802, 3803, 3804}
[docs]def test_env_lag_3(request, env):
"""Verify env_lag fixture adds ports to LAGs.
"""
fixtures.env_lag(request, env)
for _switch in env.switch.values():
_switch.clearconfig()
ports_lags = {x['portId']: x['lagId']
for x in env.switch[1].ui.get_table_ports2lag()}
assert ports_lags == {5: 3800, 4: 3801, 3: 3802, 2: 3803, 1: 3804}
[docs]def test_env_lag_4(request, env_list):
"""Verify env_lag fixture adds LAGs into port_list.
"""
fixtures.env_lag(request, env_list)
for _switch in env_list.switch.values():
_switch.clearconfig()
assert env_list.switch[1].ports == [5, 4, 3, 2, 1, 3800, 3801, 3802, 3803, 3804]
assert env_list.switch[1].port_list == [[5, 10000],
[4, 10000],
[3, 10000],
[2, 10000],
[1, 40000],
[3800, 10000],
[3801, 10000],
[3802, 10000],
[3803, 10000],
[3804, 40000]]
[docs]def test_env_lag_5(request, env_list):
"""Verify env_lag fixture adds LAGs into LagsAdmin table.
"""
fixtures.env_lag(request, env_list)
for _switch in env_list.switch.values():
_switch.clearconfig()
lags = set(x['lagId'] for x in env_list.switch[1].ui.get_table_lags())
assert lags == {3800, 3801, 3802, 3803, 3804}
[docs]def test_env_lag_6(request, env_list):
"""Verify env_lag fixture adds ports to LAGs.
"""
fixtures.env_lag(request, env_list)
for _switch in env_list.switch.values():
_switch.clearconfig()
ports_lags = {x['portId']: x['lagId']
for x in env_list.switch[1].ui.get_table_ports2lag()}
assert ports_lags == {5: 3800, 4: 3801, 3: 3802, 2: 3803, 1: 3804}
[docs]def test_env_lag_7(request, env):
"""Verify env_lag fixture changes links in setup file.
"""
fixtures.env_lag(request, env)
for _switch in env.switch.values():
_switch.clearconfig()
assert env.setup["cross"]['5'] == [['03', 1, '1', 6],
['03', 2, '1', 7],
['03', 3, '1', 8],
['03', 4, '1', 9],
['03', 5, '1', 10]]
[docs]def test_env_lag_8(request, env_list):
"""Verify env_lag fixture changes links in setup file.
"""
fixtures.env_lag(request, env_list)
for _switch in env_list.switch.values():
_switch.clearconfig()
assert env_list.setup["cross"]['5'] == [['03', 1, '1', 6],
['03', 2, '1', 7],
['03', 3, '1', 8],
['03', 4, '1', 9],
['03', 5, '1', 10]]
[docs]def test_env_lag_9(request, env):
"""Verify env_lag fixture doesn't add LAGs into ports list in case max_lags is less than links count.
"""
env.switch[1].hw.max_lags = 4
fixtures.env_lag(request, env)
with pytest.raises(pytest.skip.Exception):
for _switch in env.switch.values():
_switch.clearconfig()
assert env.switch[1].ports == [5, 4, 3, 2, 1]
assert env.switch[1].port_list == []
[docs]def test_env_lag_10(request, env_list):
"""Verify env_lag fixture doesn't add LAGs into ports list in case max_lags is less than links count.
"""
env_list.switch[1].hw.max_lags = 4
fixtures.env_lag(request, env_list)
with pytest.raises(pytest.skip.Exception):
for _switch in env_list.switch.values():
_switch.clearconfig()
assert env_list.switch[1].ports == [5, 4, 3, 2, 1]
assert env_list.switch[1].port_list == [[5, 10000],
[4, 10000],
[3, 10000],
[2, 10000],
[1, 40000]]
[docs]def test_env_lag_11(request, env):
"""Verify env_lag fixture doesn't add LAGs into ports list in case port is already in LAG.
"""
env.switch[1].ui.create_lag(3900, 100, "Static", "None")
env.switch[1].ui.create_lag_ports([1, ], 3900, 100)
fixtures.env_lag(request, env)
with pytest.raises(pytest.skip.Exception):
for _switch in env.switch.values():
_switch.clearconfig()
assert env.switch[1].ports == [5, 4, 3, 2, 1]
assert env.switch[1].port_list == []
[docs]def test_env_lag_12(request, env_list):
"""Verify env_lag fixture doesn't add LAGs into ports list in case port is already in LAG.
"""
env_list.switch[1].ui.create_lag(3900, 100, "Static", "None")
env_list.switch[1].ui.create_lag_ports([1, ], 3900, 100)
fixtures.env_lag(request, env_list)
with pytest.raises(pytest.skip.Exception):
for _switch in env_list.switch.values():
_switch.clearconfig()
assert env_list.switch[1].ports == [5, 4, 3, 2, 1]
assert env_list.switch[1].port_list == [[5, 10000],
[4, 10000],
[3, 10000],
[2, 10000],
[1, 40000]]
[docs]def test_env_lag_13(request, env_complex):
"""Verify env_lag fixture adds LAGs into ports list in complex setup.
"""
fixtures.env_lag(request, env_complex)
for _switch in env_complex.switch.values():
_switch.clearconfig()
assert env_complex.switch[1].ports == [1, 2, 3, 6, 7, 3800, 3801, 3802, 3803, 3804]
assert env_complex.switch[1].port_list == []
assert env_complex.switch[2].ports == [3, 4, 8, 9, 3800, 3801, 3803, 3804]
assert env_complex.switch[2].port_list == []
[docs]def test_env_lag_14(request, env_complex):
"""Verify env_lag fixture adds LAGs into LagsAdmin table in complex setup.
"""
fixtures.env_lag(request, env_complex)
for _switch in env_complex.switch.values():
_switch.clearconfig()
lags = set(x['lagId'] for x in env_complex.switch[1].ui.get_table_lags())
assert lags == {3800, 3801, 3802, 3803, 3804}
lags = set(x['lagId'] for x in env_complex.switch[2].ui.get_table_lags())
assert lags == {3800, 3801, 3803, 3804}
[docs]def test_env_lag_15(request, env_complex):
"""Verify env_lag fixture adds ports to LAGs in complex setup.
"""
fixtures.env_lag(request, env_complex)
for _switch in env_complex.switch.values():
_switch.clearconfig()
ports_lags = {x['portId']: x['lagId']
for x in env_complex.switch[1].ui.get_table_ports2lag()}
assert ports_lags == {1: 3800, 2: 3801, 3: 3802, 6: 3803, 7: 3804}
ports_lags = {x['portId']: x['lagId']
for x in env_complex.switch[2].ui.get_table_ports2lag()}
assert ports_lags == {3: 3800, 4: 3801, 8: 3803, 9: 3804}
[docs]class TestLagIdGenerator(object):
[docs] def test_none_if_no_args(self):
g = fixtures.LagIdGenerator()
assert g.generate_lag() is None
[docs] def test_ignore_none(self):
g = fixtures.LagIdGenerator()
d1 = Mock()
d1.id = 1
d1.hw.max_lags = 200
assert g.generate_lag(d1, None) == g.INITIAL_LAG
assert g.INITIAL_LAG not in g.free_lags[d1.id]
[docs] def test_intersection(self):
g = fixtures.LagIdGenerator()
d1 = Mock()
d1.id = 1
d1.hw.max_lags = 200
d2 = Mock()
d2.id = 2
d2.hw.max_lags = 200
d1_allocated = [g.generate_lag(d1, None) for r in range(5)]
assert g.generate_lag(d1, d2) not in d1_allocated
[docs] def test_stop_iteration_when_no_intersection(self):
g = fixtures.LagIdGenerator()
d1 = Mock()
d1.id = 1
d1.hw.max_lags = 200
d2 = Mock()
d2.id = 2
d2.hw.max_lags = 3
d1_allocated = [g.generate_lag(d1, None) for r in range(5)]
with pytest.raises(StopIteration) as excinfo:
assert g.generate_lag(d1, d2) not in d1_allocated
assert excinfo.type == StopIteration
[docs] def test_handle_same_device_twice(self):
g = fixtures.LagIdGenerator()
d1 = Mock()
d1.id = 1
d1.hw.max_lags = 200
assert g.generate_lag(d1, d1) == g.INITIAL_LAG
assert g.INITIAL_LAG not in g.free_lags[d1.id]