Fix function name in test code
[nfvbench.git] / test / test_nfvbench.py
1 #!/usr/bin/env python
2 # Copyright 2016 Cisco Systems, Inc.  All rights reserved.
3 #
4 #    Licensed under the Apache License, Version 2.0 (the "License"); you may
5 #    not use this file except in compliance with the License. You may obtain
6 #    a copy of the License at
7 #
8 #         http://www.apache.org/licenses/LICENSE-2.0
9 #
10 #    Unless required by applicable law or agreed to in writing, software
11 #    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12 #    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13 #    License for the specific language governing permissions and limitations
14 #    under the License.
15 #
16
17 from attrdict import AttrDict
18 import logging
19 from nfvbench.config import config_loads
20 from nfvbench.credentials import Credentials
21 from nfvbench.fluentd import FluentLogHandler
22 import nfvbench.log
23 from nfvbench.network import Interface
24 from nfvbench.network import Network
25 from nfvbench.specs import ChainType
26 from nfvbench.specs import Encaps
27 import nfvbench.traffic_gen.traffic_utils as traffic_utils
28 import os
29 import pytest
30 import sys
31
32 __location__ = os.path.realpath(os.path.join(os.getcwd(),
33                                              os.path.dirname(__file__)))
34
35
36
37 @pytest.fixture
38 def openstack_vxlan_spec():
39     return AttrDict(
40         {
41             'openstack': AttrDict({
42                 'vswitch': "VTS",
43                 'encaps': Encaps.VxLAN}
44             ),
45             'run_spec': AttrDict({
46                 'use_vpp': True
47             })
48         }
49     )
50
51 # =========================================================================
52 # PVP Chain tests
53 # =========================================================================
54
55 def test_chain_interface():
56     iface = Interface('testname', 'vpp', tx_packets=1234, rx_packets=4321)
57     assert iface.name == 'testname'
58     assert iface.device == 'vpp'
59     assert iface.get_packet_count('tx') == 1234
60     assert iface.get_packet_count('rx') == 4321
61     assert iface.get_packet_count('wrong_key') == 0
62
63
64 @pytest.fixture(scope='session')
65 def iface1():
66     return Interface('iface1', 'trex', tx_packets=10000, rx_packets=1234)
67
68
69 @pytest.fixture(scope='session')
70 def iface2():
71     return Interface('iface2', 'n9k', tx_packets=1234, rx_packets=9901)
72
73
74 @pytest.fixture(scope='session')
75 def iface3():
76     return Interface('iface3', 'n9k', tx_packets=9900, rx_packets=1234)
77
78
79 @pytest.fixture(scope='session')
80 def iface4():
81     return Interface('iface4', 'vpp', tx_packets=1234, rx_packets=9801)
82
83
84 @pytest.fixture(scope='session')
85 def net1(iface1, iface2, iface3, iface4):
86     return Network([iface1, iface2, iface3, iface4], reverse=False)
87
88
89 @pytest.fixture(scope='session')
90 def net2(iface1, iface2, iface3):
91     return Network([iface1, iface2, iface3], reverse=True)
92
93
94 def test_chain_network(net1, net2, iface1, iface2, iface3, iface4):
95     assert [iface1, iface2, iface3, iface4] == net1.get_interfaces()
96     assert [iface3, iface2, iface1] == net2.get_interfaces()
97     net2.add_interface(iface4)
98     assert [iface4, iface3, iface2, iface1] == net2.get_interfaces()
99
100
101 """
102 def test_chain_analysis(net1, monkeypatch, openstack_vxlan_spec):
103     def mock_empty(self, *args, **kwargs):
104         pass
105
106     monkeypatch.setattr(ServiceChain, '_setup', mock_empty)
107
108     f = ServiceChain(AttrDict({'service_chain': 'DUMMY'}), [], {'tor': {}}, openstack_vxlan_spec,
109                      lambda x, y, z: None)
110     result = f.get_analysis([net1])
111     assert result[1]['packet_drop_count'] == 99
112     assert result[1]['packet_drop_percentage'] == 0.99
113     assert result[2]['packet_drop_count'] == 1
114     assert result[2]['packet_drop_percentage'] == 0.01
115     assert result[3]['packet_drop_count'] == 99
116     assert result[3]['packet_drop_percentage'] == 0.99
117
118     net1.reverse = True
119     result = f.get_analysis([net1])
120     assert result[1]['packet_drop_count'] == 0
121     assert result[1]['packet_drop_percentage'] == 0.0
122     assert result[2]['packet_drop_count'] == 0
123     assert result[2]['packet_drop_percentage'] == 0.0
124     assert result[3]['packet_drop_count'] == 0
125     assert result[3]['packet_drop_percentage'] == 0.0
126
127
128 @pytest.fixture
129 def pvp_chain(monkeypatch, openstack_vxlan_spec):
130     tor_vni1 = Interface('vni-4097', 'n9k', 50, 77)
131     vsw_vni1 = Interface('vxlan_tunnel0', 'vpp', 77, 48)
132     vsw_vif1 = Interface('VirtualEthernet0/0/2', 'vpp', 48, 77)
133     vsw_vif2 = Interface('VirtualEthernet0/0/3', 'vpp', 77, 47)
134     vsw_vni2 = Interface('vxlan_tunnel1', 'vpp', 43, 77)
135     tor_vni2 = Interface('vni-4098', 'n9k', 77, 40)
136
137     def mock_init(self, *args, **kwargs):
138         self.vni_ports = [4097, 4098]
139         self.specs = openstack_vxlan_spec
140         self.clients = {
141             'vpp': AttrDict({
142                 'set_interface_counters': lambda: None,
143             })
144         }
145         self.worker = AttrDict({
146             'run': lambda: None,
147         })
148
149     def mock_empty(self, *args, **kwargs):
150         pass
151
152     def mock_get_network(self, traffic_port, vni_id, reverse=False):
153         if vni_id == 0:
154             return Network([tor_vni1, vsw_vni1, vsw_vif1], reverse)
155         else:
156             return Network([tor_vni2, vsw_vni2, vsw_vif2], reverse)
157
158     def mock_get_data(self):
159         return {}
160
161     monkeypatch.setattr(PVPChain, '_get_network', mock_get_network)
162     monkeypatch.setattr(PVPChain, '_get_data', mock_get_data)
163     monkeypatch.setattr(PVPChain, '_setup', mock_empty)
164     monkeypatch.setattr(VxLANWorker, '_clear_interfaces', mock_empty)
165     monkeypatch.setattr(PVPChain, '_generate_traffic', mock_empty)
166     monkeypatch.setattr(PVPChain, '__init__', mock_init)
167     return PVPChain(None, None, {'vm': None, 'vpp': None, 'tor': None, 'traffic': None}, None)
168
169
170 def test_pvp_chain_run(pvp_chain):
171     result = pvp_chain.run()
172     expected_result = {
173         'raw_data': {},
174         'stats': None,
175         'packet_analysis': {
176             'direction-forward': [
177                 OrderedDict([
178                     ('interface', 'vni-4097'),
179                     ('device', 'n9k'),
180                     ('packet_count', 50)
181                 ]),
182                 OrderedDict([
183                     ('interface', 'vxlan_tunnel0'),
184                     ('device', 'vpp'),
185                     ('packet_count', 48),
186                     ('packet_drop_count', 2),
187                     ('packet_drop_percentage', 4.0)
188                 ]),
189                 OrderedDict([
190                     ('interface', 'VirtualEthernet0/0/2'),
191                     ('device', 'vpp'),
192                     ('packet_count', 48),
193                     ('packet_drop_count', 0),
194                     ('packet_drop_percentage', 0.0)
195                 ]),
196                 OrderedDict([
197                     ('interface', 'VirtualEthernet0/0/3'),
198                     ('device', 'vpp'),
199                     ('packet_count', 47),
200                     ('packet_drop_count', 1),
201                     ('packet_drop_percentage', 2.0)
202                 ]),
203                 OrderedDict([
204                     ('interface', 'vxlan_tunnel1'),
205                     ('device', 'vpp'),
206                     ('packet_count', 43),
207                     ('packet_drop_count', 4),
208                     ('packet_drop_percentage', 8.0)
209                 ]),
210                 OrderedDict([
211                     ('interface', 'vni-4098'),
212                     ('device', 'n9k'),
213                     ('packet_count', 40),
214                     ('packet_drop_count', 3),
215                     ('packet_drop_percentage', 6.0)
216                 ])
217             ],
218             'direction-reverse': [
219                 OrderedDict([
220                     ('interface', 'vni-4098'),
221                     ('device', 'n9k'),
222                     ('packet_count', 77)
223                 ]),
224                 OrderedDict([
225                     ('interface', 'vxlan_tunnel1'),
226                     ('device', 'vpp'),
227                     ('packet_count', 77),
228                     ('packet_drop_count', 0),
229                     ('packet_drop_percentage', 0.0)
230                 ]),
231                 OrderedDict([
232                     ('interface', 'VirtualEthernet0/0/3'),
233                     ('device', 'vpp'),
234                     ('packet_count', 77),
235                     ('packet_drop_count', 0),
236                     ('packet_drop_percentage', 0.0)
237                 ]),
238                 OrderedDict([
239                     ('interface', 'VirtualEthernet0/0/2'),
240                     ('device', 'vpp'),
241                     ('packet_count', 77),
242                     ('packet_drop_count', 0),
243                     ('packet_drop_percentage', 0.0)
244                 ]),
245                 OrderedDict([
246                     ('interface', 'vxlan_tunnel0'),
247                     ('device', 'vpp'),
248                     ('packet_count', 77),
249                     ('packet_drop_count', 0),
250                     ('packet_drop_percentage', 0.0)
251                 ]),
252                 OrderedDict([
253                     ('interface', 'vni-4097'),
254                     ('device', 'n9k'),
255                     ('packet_count', 77),
256                     ('packet_drop_count', 0),
257                     ('packet_drop_percentage', 0.0)
258                 ])
259             ]
260         }
261     }
262     assert result == expected_result
263 """
264
265
266 # =========================================================================
267 # PVVP Chain tests
268 # =========================================================================
269
270 """
271 @pytest.fixture
272 def pvvp_chain(monkeypatch, openstack_vxlan_spec):
273     tor_vni1 = Interface('vni-4097', 'n9k', 50, 77)
274     vsw_vni1 = Interface('vxlan_tunnel0', 'vpp', 77, 48)
275     vsw_vif1 = Interface('VirtualEthernet0/0/2', 'vpp', 48, 77)
276     vsw_vif3 = Interface('VirtualEthernet0/0/0', 'vpp', 77, 47)
277     vsw_vif4 = Interface('VirtualEthernet0/0/1', 'vpp', 45, 77)
278     vsw_vif2 = Interface('VirtualEthernet0/0/3', 'vpp', 77, 44)
279     vsw_vni2 = Interface('vxlan_tunnel1', 'vpp', 43, 77)
280     tor_vni2 = Interface('vni-4098', 'n9k', 77, 40)
281
282     def mock_init(self, *args, **kwargs):
283         self.vni_ports = [4099, 4100]
284         self.v2vnet = V2VNetwork()
285         self.specs = openstack_vxlan_spec
286         self.clients = {
287             'vpp': AttrDict({
288                 'get_v2v_network': lambda reverse=None: Network([vsw_vif3, vsw_vif4], reverse),
289                 'set_interface_counters': lambda pvvp=None: None,
290                 'set_v2v_counters': lambda: None,
291             })
292         }
293         self.worker = AttrDict({
294             'run': lambda: None,
295         })
296
297     def mock_empty(self, *args, **kwargs):
298         pass
299
300     def mock_get_network(self, traffic_port, vni_id, reverse=False):
301         if vni_id == 0:
302             return Network([tor_vni1, vsw_vni1, vsw_vif1], reverse)
303         else:
304             return Network([tor_vni2, vsw_vni2, vsw_vif2], reverse)
305
306     def mock_get_data(self):
307         return {}
308
309     monkeypatch.setattr(PVVPChain, '_get_network', mock_get_network)
310     monkeypatch.setattr(PVVPChain, '_get_data', mock_get_data)
311     monkeypatch.setattr(PVVPChain, '_setup', mock_empty)
312     monkeypatch.setattr(VxLANWorker, '_clear_interfaces', mock_empty)
313     monkeypatch.setattr(PVVPChain, '_generate_traffic', mock_empty)
314     monkeypatch.setattr(PVVPChain, '__init__', mock_init)
315
316     return PVVPChain(None, None, {'vm': None, 'vpp': None, 'tor': None, 'traffic': None}, None)
317
318
319 def test_pvvp_chain_run(pvvp_chain):
320     result = pvvp_chain.run()
321
322     expected_result = {
323         'raw_data': {},
324         'stats': None,
325         'packet_analysis':
326             {'direction-forward': [
327                 OrderedDict([
328                     ('interface', 'vni-4097'),
329                     ('device', 'n9k'),
330                     ('packet_count', 50)
331                 ]),
332                 OrderedDict([
333                     ('interface', 'vxlan_tunnel0'),
334                     ('device', 'vpp'),
335                     ('packet_count', 48),
336                     ('packet_drop_count', 2),
337                     ('packet_drop_percentage', 4.0)
338                 ]),
339                 OrderedDict([
340                     ('interface', 'VirtualEthernet0/0/2'),
341                     ('device', 'vpp'),
342                     ('packet_count', 48),
343                     ('packet_drop_count', 0),
344                     ('packet_drop_percentage', 0.0)
345                 ]),
346                 OrderedDict([
347                     ('interface', 'VirtualEthernet0/0/0'),
348                     ('device', 'vpp'),
349                     ('packet_count', 47),
350                     ('packet_drop_count', 1),
351                     ('packet_drop_percentage', 2.0)
352                 ]),
353                 OrderedDict([
354                     ('interface', 'VirtualEthernet0/0/1'),
355                     ('device', 'vpp'),
356                     ('packet_count', 45),
357                     ('packet_drop_count', 2),
358                     ('packet_drop_percentage', 4.0)
359                 ]),
360                 OrderedDict([
361                     ('interface', 'VirtualEthernet0/0/3'),
362                     ('device', 'vpp'),
363                     ('packet_count', 44),
364                     ('packet_drop_count', 1),
365                     ('packet_drop_percentage', 2.0)
366                 ]),
367                 OrderedDict([
368                     ('interface', 'vxlan_tunnel1'),
369                     ('device', 'vpp'),
370                     ('packet_count', 43),
371                     ('packet_drop_count', 1),
372                     ('packet_drop_percentage', 2.0)
373                 ]),
374                 OrderedDict([
375                     ('interface', 'vni-4098'),
376                     ('device', 'n9k'),
377                     ('packet_count', 40),
378                     ('packet_drop_count', 3),
379                     ('packet_drop_percentage', 6.0)
380                 ])
381             ],
382             'direction-reverse': [
383                 OrderedDict([
384                     ('interface', 'vni-4098'),
385                     ('device', 'n9k'),
386                     ('packet_count', 77)
387                 ]),
388                 OrderedDict([
389                     ('interface', 'vxlan_tunnel1'),
390                     ('device', 'vpp'),
391                     ('packet_count', 77),
392                     ('packet_drop_count', 0),
393                     ('packet_drop_percentage', 0.0)
394                 ]),
395                 OrderedDict([
396                     ('interface', 'VirtualEthernet0/0/3'),
397                     ('device', 'vpp'),
398                     ('packet_count', 77),
399                     ('packet_drop_count', 0),
400                     ('packet_drop_percentage', 0.0)
401                 ]),
402                 OrderedDict([
403                     ('interface', 'VirtualEthernet0/0/1'),
404                     ('device', 'vpp'),
405                     ('packet_count', 77),
406                     ('packet_drop_count', 0),
407                     ('packet_drop_percentage', 0.0)
408                 ]),
409                 OrderedDict([
410                     ('interface', 'VirtualEthernet0/0/0'),
411                     ('device', 'vpp'),
412                     ('packet_count', 77),
413                     ('packet_drop_count', 0),
414                     ('packet_drop_percentage', 0.0)
415                 ]),
416                 OrderedDict([
417                     ('interface', 'VirtualEthernet0/0/2'),
418                     ('device', 'vpp'),
419                     ('packet_count', 77),
420                     ('packet_drop_count', 0),
421                     ('packet_drop_percentage', 0.0)
422                 ]),
423                 OrderedDict([
424                     ('interface', 'vxlan_tunnel0'),
425                     ('device', 'vpp'),
426                     ('packet_count', 77),
427                     ('packet_drop_count', 0),
428                     ('packet_drop_percentage', 0.0)
429                 ]),
430                 OrderedDict([
431                     ('interface', 'vni-4097'),
432                     ('device', 'n9k'),
433                     ('packet_count', 77),
434                     ('packet_drop_count', 0),
435                     ('packet_drop_percentage', 0.0)
436                 ])
437             ]}
438     }
439     assert result == expected_result
440 """
441
442 # =========================================================================
443 # Traffic client tests
444 # =========================================================================
445
446 def test_parse_rate_str():
447     parse_rate_str = traffic_utils.parse_rate_str
448     try:
449         assert parse_rate_str('100%') == {'rate_percent': '100.0'}
450         assert parse_rate_str('37.5%') == {'rate_percent': '37.5'}
451         assert parse_rate_str('100%') == {'rate_percent': '100.0'}
452         assert parse_rate_str('60pps') == {'rate_pps': '60'}
453         assert parse_rate_str('60kpps') == {'rate_pps': '60000'}
454         assert parse_rate_str('6Mpps') == {'rate_pps': '6000000'}
455         assert parse_rate_str('6gpps') == {'rate_pps': '6000000000'}
456         assert parse_rate_str('80bps') == {'rate_bps': '80'}
457         assert parse_rate_str('80bps') == {'rate_bps': '80'}
458         assert parse_rate_str('80kbps') == {'rate_bps': '80000'}
459         assert parse_rate_str('80kBps') == {'rate_bps': '640000'}
460         assert parse_rate_str('80Mbps') == {'rate_bps': '80000000'}
461         assert parse_rate_str('80 MBps') == {'rate_bps': '640000000'}
462         assert parse_rate_str('80Gbps') == {'rate_bps': '80000000000'}
463     except Exception as exc:
464         assert False, exc.message
465
466     def should_raise_error(str):
467         try:
468             parse_rate_str(str)
469         except Exception:
470             return True
471         else:
472             assert False
473
474     assert should_raise_error('101')
475     assert should_raise_error('201%')
476     assert should_raise_error('10Kbps')
477     assert should_raise_error('0kbps')
478     assert should_raise_error('0pps')
479     assert should_raise_error('-1bps')
480
481 def test_rate_conversion():
482     assert traffic_utils.load_to_bps(50, 10000000000) == pytest.approx(5000000000.0)
483     assert traffic_utils.load_to_bps(37, 10000000000) == pytest.approx(3700000000.0)
484     assert traffic_utils.load_to_bps(100, 10000000000) == pytest.approx(10000000000.0)
485
486     assert traffic_utils.bps_to_load(5000000000.0, 10000000000) == pytest.approx(50.0)
487     assert traffic_utils.bps_to_load(3700000000.0, 10000000000) == pytest.approx(37.0)
488     assert traffic_utils.bps_to_load(10000000000.0, 10000000000) == pytest.approx(100.0)
489
490     assert traffic_utils.bps_to_pps(500000, 64) == pytest.approx(744.047619048)
491     assert traffic_utils.bps_to_pps(388888, 1518) == pytest.approx(31.6066319896)
492     assert traffic_utils.bps_to_pps(9298322222, 340.3) == pytest.approx(3225895.85831)
493
494     assert traffic_utils.pps_to_bps(744.047619048, 64) == pytest.approx(500000)
495     assert traffic_utils.pps_to_bps(31.6066319896, 1518) == pytest.approx(388888)
496     assert traffic_utils.pps_to_bps(3225895.85831, 340.3) == pytest.approx(9298322222)
497
498
499 """
500 @pytest.fixture
501 def traffic_client(monkeypatch):
502
503     def mock_init(self, *args, **kwargs):
504         self.run_config = {
505             'bidirectional': False,
506             'l2frame_size': '64',
507             'duration_sec': 30,
508             'rates': [{'rate_percent': '10'}, {'rate_pps': '1'}]
509         }
510
511         self.config = AttrDict({
512             'generator_config': {
513                 'intf_speed': 10000000000
514             },
515             'ndr_run': True,
516             'pdr_run': True,
517             'single_run': False,
518             'attempts': 1,
519             'measurement': {
520                 'NDR': 0.0,
521                 'PDR': 0.1,
522                 'load_epsilon': 0.1
523             }
524         })
525
526         self.runner = AttrDict({
527             'time_elapsed': lambda: 30,
528             'stop': lambda: None,
529             'client': AttrDict({'get_stats': lambda: None})
530         })
531
532         self.current_load = None
533         self.dummy_stats = {
534             50.0: 72.6433562831,
535             25.0: 45.6095059858,
536             12.5: 0.0,
537             18.75: 27.218642979,
538             15.625: 12.68585861,
539             14.0625: 2.47154392563,
540             13.28125: 0.000663797066801,
541             12.890625: 0.0,
542             13.0859375: 0.0,
543             13.18359375: 0.00359387347122,
544             13.671875: 0.307939922531,
545             13.4765625: 0.0207718516156,
546             13.57421875: 0.0661795060969
547         }
548
549     def mock_modify_load(self, load):
550         self.run_config['rates'][0] = {'rate_percent': str(load)}
551         self.current_load = load
552
553     def mock_run_traffic(self):
554         yield {
555             'overall': {
556                 'drop_rate_percent': self.dummy_stats[self.current_load],
557                 'rx': {
558                     'total_pkts': 1,
559                     'avg_delay_usec': 0.0,
560                     'max_delay_usec': 0.0,
561                     'min_delay_usec': 0.0
562                 }
563             }
564         }
565
566     monkeypatch.setattr(TrafficClient, '__init__', mock_init)
567     monkeypatch.setattr(TrafficClient, 'modify_load', mock_modify_load)
568     monkeypatch.setattr(TrafficClient, 'run_traffic', mock_run_traffic)
569
570     return TrafficClient()
571
572
573 def test_ndr_pdr_search(traffic_client):
574     expected_results = {
575         'pdr': {
576             'l2frame_size': '64',
577             'initial_rate_type': 'rate_percent',
578             'stats': {
579                 'overall': {
580                     'drop_rate_percent': 0.0661795060969,
581                     'min_delay_usec': 0.0,
582                     'avg_delay_usec': 0.0,
583                     'max_delay_usec': 0.0
584                 }
585             },
586             'load_percent_per_direction': 13.57421875,
587             'rate_percent': 13.57422547,
588             'rate_bps': 1357422547.0,
589             'rate_pps': 2019974.0282738095,
590             'duration_sec': 30
591         },
592         'ndr': {
593             'l2frame_size': '64',
594             'initial_rate_type': 'rate_percent',
595             'stats': {
596                 'overall': {
597                     'drop_rate_percent': 0.0,
598                     'min_delay_usec': 0.0,
599                     'avg_delay_usec': 0.0,
600                     'max_delay_usec': 0.0
601                 }
602             },
603             'load_percent_per_direction': 13.0859375,
604             'rate_percent': 13.08594422,
605             'rate_bps': 1308594422.0,
606             'rate_pps': 1947313.1279761905,
607             'duration_sec': 30
608         }
609     }
610
611     results = traffic_client.get_ndr_and_pdr()
612     assert len(results) == 2
613     for result in results.values():
614         result.pop('timestamp_sec')
615         result.pop('time_taken_sec')
616     assert results == expected_results
617 """
618
619 # =========================================================================
620 # Other tests
621 # =========================================================================
622
623 def setup_module(module):
624     nfvbench.log.setup(mute_stdout=True)
625
626 def test_no_credentials():
627     cred = Credentials('/completely/wrong/path/openrc', None, False)
628     if cred.rc_auth_url:
629         # shouldn't get valid data unless user set environment variables
630         assert False
631     else:
632         assert True
633
634 # Because trex_stl_lib may not be installed when running unit test
635 # nfvbench.traffic_client will try to import STLError:
636 # from trex_stl_lib.api import STLError
637 # will raise ImportError: No module named trex_stl_lib.api
638 try:
639     import trex_stl_lib.api
640     assert(trex_stl_lib.api)
641 except ImportError:
642     # Make up a trex_stl_lib.api.STLError class
643     class STLError(Exception):
644         pass
645     from types import ModuleType
646     stl_lib_mod = ModuleType('trex_stl_lib')
647     sys.modules['trex_stl_lib'] = stl_lib_mod
648     api_mod = ModuleType('trex_stl_lib.api')
649     stl_lib_mod.api = api_mod
650     sys.modules['trex_stl_lib.api'] = api_mod
651     api_mod.STLError = STLError
652
653 from nfvbench.traffic_client import Device
654 from nfvbench.traffic_client import IpBlock
655
656
657 def test_ip_block():
658     ipb = IpBlock('10.0.0.0', '0.0.0.1', 256)
659     assert(ipb.get_ip() == '10.0.0.0')
660     assert(ipb.get_ip(255) == '10.0.0.255')
661     with pytest.raises(IndexError):
662         ipb.get_ip(256)
663     # verify with step larger than 1
664     ipb = IpBlock('10.0.0.0', '0.0.0.2', 256)
665     assert(ipb.get_ip() == '10.0.0.0')
666     assert(ipb.get_ip(1) == '10.0.0.2')
667     assert(ipb.get_ip(128) == '10.0.1.0')
668     assert(ipb.get_ip(255) == '10.0.1.254')
669     with pytest.raises(IndexError):
670         ipb.get_ip(256)
671
672 def check_config(configs, cc, fc, src_ip, dst_ip, step_ip):
673     '''Verify that the range configs for each chain have adjacent IP ranges
674     of the right size and without holes between chains
675     '''
676     step = Device.ip_to_int(step_ip)
677     cfc = 0
678     sip = Device.ip_to_int(src_ip)
679     dip = Device.ip_to_int(dst_ip)
680     for index in range(cc):
681         config = configs[index]
682         assert(config['ip_src_count'] == config['ip_dst_count'])
683         assert(Device.ip_to_int(config['ip_src_addr']) == sip)
684         assert(Device.ip_to_int(config['ip_dst_addr']) == dip)
685         count = config['ip_src_count']
686         cfc += count
687         sip += count * step
688         dip += count * step
689     assert(cfc == fc)
690
691 def create_device(fc, cc, ip, gip, tggip, step_ip):
692     return Device(0, 0, flow_count=fc, chain_count=cc, ip=ip, gateway_ip=gip, tg_gateway_ip=tggip,
693                   ip_addrs_step=step_ip,
694                   tg_gateway_ip_addrs_step=step_ip,
695                   gateway_ip_addrs_step=step_ip)
696
697 def check_device_flow_config(step_ip):
698     fc = 99999
699     cc = 10
700     ip0 = '10.0.0.0'
701     ip1 = '20.0.0.0'
702     tggip = '50.0.0.0'
703     gip = '60.0.0.0'
704     dev0 = create_device(fc, cc, ip0, gip, tggip, step_ip)
705     dev1 = create_device(fc, cc, ip1, gip, tggip, step_ip)
706     dev0.set_destination(dev1)
707     configs = dev0.get_stream_configs(ChainType.EXT)
708     check_config(configs, cc, fc, ip0, ip1, step_ip)
709
710 def test_device_flow_config():
711     check_device_flow_config('0.0.0.1')
712     check_device_flow_config('0.0.0.2')
713
714 def test_device_ip_range():
715     def ip_range_overlaps(ip0, ip1, flows):
716         tggip = '50.0.0.0'
717         gip = '60.0.0.0'
718         dev0 = create_device(flows, 10, ip0, gip, tggip, '0.0.0.1')
719         dev1 = create_device(flows, 10, ip1, gip, tggip, '0.0.0.1')
720         dev0.set_destination(dev1)
721         return dev0.ip_range_overlaps()
722     assert(not ip_range_overlaps('10.0.0.0', '20.0.0.0', 10000))
723     assert(ip_range_overlaps('10.0.0.0', '10.0.1.0', 10000))
724     assert(ip_range_overlaps('10.0.0.0', '10.0.1.0', 257))
725     assert(ip_range_overlaps('10.0.1.0', '10.0.0.0', 257))
726
727
728 def test_config():
729     refcfg = {1: 100, 2: {21: 100, 22: 200}, 3: None}
730     res1 = {1: 10, 2: {21: 100, 22: 200}, 3: None}
731     res2 = {1: 100, 2: {21: 1000, 22: 200}, 3: None}
732     res3 = {1: 100, 2: {21: 100, 22: 200}, 3: "abc"}
733     assert(config_loads("{}", refcfg) == refcfg)
734     assert(config_loads("{1: 10}", refcfg) == res1)
735     assert(config_loads("{2: {21: 1000}}", refcfg) == res2)
736     assert(config_loads('{3: "abc"}', refcfg) == res3)
737
738     # correctly fails
739     # pairs of input string and expected subset (None if identical)
740     fail_pairs = [
741         ["{4: 0}", None],
742         ["{2: {21: 100, 30: 50}}", "{2: {30: 50}}"],
743         ["{2: {0: 1, 1: 2}, 5: 5}", None],
744         ["{1: 'abc', 2: {21: 0}}", "{1: 'abc'}"],
745         ["{2: 100}", None]
746     ]
747     for fail_pair in fail_pairs:
748         with pytest.raises(Exception) as e_info:
749             config_loads(fail_pair[0], refcfg)
750         expected = fail_pair[1]
751         if expected is None:
752             expected = fail_pair[0]
753         assert expected in e_info.value.message
754
755     # whitelist keys
756     flavor = {'flavor': {'vcpus': 2, 'ram': 8192, 'disk': 0,
757               'extra_specs': {'hw:cpu_policy': 'dedicated'}}}
758     new_flavor = {'flavor': {'vcpus': 2, 'ram': 8192, 'disk': 0,
759                   'extra_specs': {'hw:cpu_policy': 'dedicated', 'hw:numa_nodes': 2}}}
760     assert(config_loads("{'flavor': {'extra_specs': {'hw:numa_nodes': 2}}}", flavor,
761                         whitelist_keys=['alpha', 'extra_specs']) == new_flavor)
762
763 def test_fluentd():
764     logger = logging.getLogger('fluent-logger')
765     handler = FluentLogHandler('nfvbench', fluentd_port=7081)
766     logger.addHandler(handler)
767     logger.setLevel(logging.INFO)
768     logger.info('test')
769     logger.warning('test %d', 100)
770     try:
771         raise Exception("test")
772     except Exception:
773         logger.exception("got exception")