stats: add a retry mechanism in a symlink test
[vpp.git] / test / test_stats_client.py
1 #!/usr/bin/env python3
2
3 import unittest
4 import psutil
5 import sys
6 import six
7 from vpp_papi.vpp_stats import VPPStats
8
9 from framework import tag_fixme_vpp_workers
10 from framework import VppTestCase, VppTestRunner
11 from scapy.layers.l2 import Ether
12 from scapy.layers.inet import IP
13
14
15 @tag_fixme_vpp_workers
16 class StatsClientTestCase(VppTestCase):
17     """Test Stats Client"""
18
19     @classmethod
20     def setUpClass(cls):
21         super(StatsClientTestCase, cls).setUpClass()
22
23     @classmethod
24     def tearDownClass(cls):
25         super(StatsClientTestCase, cls).tearDownClass()
26
27     @classmethod
28     def setUpConstants(cls):
29         cls.extra_vpp_statseg_config = "per-node-counters on"
30         cls.extra_vpp_statseg_config += "update-interval 0.05"
31         super(StatsClientTestCase, cls).setUpConstants()
32
33     def test_set_errors(self):
34         """Test set errors"""
35         self.assertEqual(self.statistics.set_errors(), {})
36         self.assertEqual(
37             self.statistics.get_counter('/err/ethernet-input/no error'), [0])
38
39     def test_client_fd_leak(self):
40         """Test file descriptor count - VPP-1486"""
41
42         cls = self.__class__
43         p = psutil.Process()
44         initial_fds = p.num_fds()
45
46         for _ in range(100):
47             stats = VPPStats(socketname=cls.get_stats_sock_path())
48             stats.disconnect()
49
50         ending_fds = p.num_fds()
51         self.assertEqual(initial_fds, ending_fds,
52                          "initial client side file descriptor count: %s "
53                          "is not equal to "
54                          "ending client side file descriptor count: %s" % (
55                              initial_fds, ending_fds))
56
57     def test_symlink_values(self):
58         """Test symlinks reported values"""
59         self.create_pg_interfaces(range(2))
60
61         for i in self.pg_interfaces:
62             i.admin_up()
63             i.config_ip4()
64             i.resolve_arp()
65
66         p = list()
67         for i in range(5):
68             packet = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
69                       IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4))
70             p.append(packet)
71
72         self.send_and_expect(self.pg0, p, self.pg1)
73
74         pg1_tx = self.statistics.get_counter('/interfaces/pg1/tx')
75         if_tx = self.statistics.get_counter('/if/tx')
76
77         self.assertEqual(pg1_tx[0]['bytes'],
78                          if_tx[0][self.pg1.sw_if_index]['bytes'])
79         for i in self.pg_interfaces:
80             i.unconfig()
81             i.admin_down()
82
83     def test_symlink_add_del_interfaces(self):
84         """Test symlinks when adding and deleting interfaces"""
85         # We first create and delete interfaces
86         self.create_loopback_interfaces(1)
87         self.create_pg_interfaces(range(1))
88         self.loop0.remove_vpp_config()
89         self.create_pg_interfaces(range(2))
90
91         for i in self.pg_interfaces:
92             i.admin_up()
93             i.config_ip4()
94             i.resolve_arp()
95
96         p = list()
97         bytes_to_send = 0
98         for i in range(5):
99             packet = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
100                       IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4))
101             bytes_to_send += len(packet)
102             p.append(packet)
103
104         tx_before_sending = self.statistics.get_counter('/interfaces/pg1/tx')
105         rx_before_sending = self.statistics.get_counter('/interfaces/pg0/rx')
106         self.send_and_expect(self.pg0, p, self.pg1)
107         tx = self.statistics.get_counter('/interfaces/pg1/tx')
108         rx = self.statistics.get_counter('/interfaces/pg0/rx')
109
110         # We wait for nodes symlinks to update (interfaces created/deleted).
111         # ... and packets to be sent
112         self.sleep(0.1)
113         for _ in range(5):
114             try:
115                 vectors = self.statistics.get_counter('/nodes/pg1-tx/vectors')
116                 if vectors[0] == 0:
117                     raise ValueError("Nodes counters are not up to date")
118                 break
119             except:
120                 t, v, tb = sys.exc_info()
121
122                 self.sleep(0.1)
123                 continue
124         else:
125             six.reraise(t, v, tb)
126
127         self.assertEqual(tx[0]['bytes'] - tx_before_sending[0]['bytes'],
128                          bytes_to_send)
129         self.assertEqual(tx[0]['packets'] - tx_before_sending[0]['packets'],
130                          5)
131         self.assertEqual(rx[0]['bytes'] - rx_before_sending[0]['bytes'],
132                          bytes_to_send)
133         self.assertEqual(rx[0]['packets'] - rx_before_sending[0]['packets'],
134                          5)
135         self.assertEqual(vectors[0], rx[0]['packets'])
136
137         for i in self.pg_interfaces:
138             i.unconfig()
139             i.admin_down()
140
141     def test_index_consistency(self):
142         """Test index consistency despite changes in the stats"""
143         d = self.statistics.ls(['/if/names'])
144         self.create_loopback_interfaces(10)
145         for i in range(10):
146             try:
147                 s = self.statistics.dump(d)
148                 break
149             except:
150                 pass
151         k, v = s.popitem()
152         self.assertEqual(len(v), 11)
153
154         for i in self.lo_interfaces:
155             i.remove_vpp_config()
156
157     @unittest.skip("Manual only")
158     def test_mem_leak(self):
159         def loop():
160             print('Running loop')
161             for i in range(50):
162                 rv = self.vapi.papi.tap_create_v2(id=i, use_random_mac=1)
163                 self.assertEqual(rv.retval, 0)
164                 rv = self.vapi.papi.tap_delete_v2(sw_if_index=rv.sw_if_index)
165                 self.assertEqual(rv.retval, 0)
166
167         before = self.statistics.get_counter('/mem/statseg/used')
168         loop()
169         self.vapi.cli("memory-trace on stats-segment")
170         for j in range(100):
171             loop()
172         print(self.vapi.cli("show memory stats-segment verbose"))
173         print('AFTER', before,
174               self.statistics.get_counter('/mem/statseg/used'))
175
176
177 if __name__ == '__main__':
178     unittest.main(testRunner=VppTestRunner)