prepare func tests for openroadm v2.2.1 support
[transportpce.git] / tests / transportpce_tests / 1.2.1 / test_renderer_service_path_nominal.py
1 #!/usr/bin/env python
2
3 #############################################################################
4 # Copyright (c) 2017 Orange, Inc. and others.  All rights reserved.
5 #
6 # All rights reserved. This program and the accompanying materials
7 # are made available under the terms of the Apache License, Version 2.0
8 # which accompanies this distribution, and is available at
9 # http://www.apache.org/licenses/LICENSE-2.0
10 #############################################################################
11
12 import unittest
13 import requests
14 import time
15 import subprocess
16 import signal
17 import json
18 import os
19 import psutil
20 import shutil
21 from unittest.result import failfast
22
23
24 class TransportPCERendererTesting(unittest.TestCase):
25
26     honeynode_process1 = None
27     honeynode_process2 = None
28     odl_process = None
29     restconf_baseurl = "http://localhost:8181/restconf"
30
31 #START_IGNORE_XTESTING
32
33     @classmethod
34     def __start_honeynode1(cls):
35         executable = ("./honeynode/2.1/honeynode-distribution/target/honeynode-distribution-1.18.01-hc"
36                       "/honeynode-distribution-1.18.01/honeycomb-tpce")
37         if os.path.isfile(executable):
38             with open('honeynode1.log', 'w') as outfile:
39                 cls.honeynode_process1 = subprocess.Popen(
40                     [executable, "17830", "sample_configs/openroadm/2.1/oper-ROADMA.xml"],
41                     stdout=outfile)
42
43     @classmethod
44     def __start_honeynode2(cls):
45         executable = ("./honeynode/2.1/honeynode-distribution/target/honeynode-distribution-1.18.01-hc"
46                       "/honeynode-distribution-1.18.01/honeycomb-tpce")
47         if os.path.isfile(executable):
48             with open('honeynode2.log', 'w') as outfile:
49                 cls.honeynode_process2 = subprocess.Popen(
50                     [executable, "17831", "sample_configs/openroadm/2.1/oper-XPDRA.xml"],
51                     stdout=outfile)
52
53     @classmethod
54     def __start_odl(cls):
55         executable = "../karaf/target/assembly/bin/karaf"
56         with open('odl.log', 'w') as outfile:
57             cls.odl_process = subprocess.Popen(
58                 ["bash", executable, "server"], stdout=outfile,
59                 stdin=open(os.devnull))
60
61     @classmethod
62     def setUpClass(cls):
63         cls.__start_honeynode1()
64         time.sleep(40)
65         cls.__start_honeynode2()
66         time.sleep(40)
67         cls.__start_odl()
68         time.sleep(60)
69
70     @classmethod
71     def tearDownClass(cls):
72         for child in psutil.Process(cls.odl_process.pid).children():
73             child.send_signal(signal.SIGINT)
74             child.wait()
75         cls.odl_process.send_signal(signal.SIGINT)
76         cls.odl_process.wait()
77         for child in psutil.Process(cls.honeynode_process1.pid).children():
78             child.send_signal(signal.SIGINT)
79             child.wait()
80         cls.honeynode_process1.send_signal(signal.SIGINT)
81         cls.honeynode_process1.wait()
82         for child in psutil.Process(cls.honeynode_process2.pid).children():
83             child.send_signal(signal.SIGINT)
84             child.wait()
85         cls.honeynode_process2.send_signal(signal.SIGINT)
86         cls.honeynode_process2.wait()
87
88     def setUp(self):
89         print ("execution of {}".format(self.id().split(".")[-1]))
90         time.sleep(10)
91
92 #END_IGNORE_XTESTING
93
94     def test_01_rdm_device_connected(self):
95         url = ("{}/config/network-topology:"
96                "network-topology/topology/topology-netconf/node/ROADMA"
97                .format(self.restconf_baseurl))
98         data = {"node": [{
99              "node-id": "ROADMA",
100              "netconf-node-topology:username": "admin",
101              "netconf-node-topology:password": "admin",
102              "netconf-node-topology:host": "127.0.0.1",
103              "netconf-node-topology:port": "17830",
104              "netconf-node-topology:tcp-only": "false",
105              "netconf-node-topology:pass-through": {}}]}
106         headers = {'content-type': 'application/json'}
107         response = requests.request(
108              "PUT", url, data=json.dumps(data), headers=headers,
109               auth=('admin', 'admin'))
110         self.assertEqual(response.status_code, requests.codes.created)
111         time.sleep(20)
112
113     def test_02_xpdr_device_connected(self):
114         url = ("{}/config/network-topology:"
115                "network-topology/topology/topology-netconf/node/XPDRA"
116               .format(self.restconf_baseurl))
117         data = {"node": [{
118             "node-id": "XPDRA",
119             "netconf-node-topology:username": "admin",
120             "netconf-node-topology:password": "admin",
121             "netconf-node-topology:host": "127.0.0.1",
122             "netconf-node-topology:port": "17831",
123             "netconf-node-topology:tcp-only": "false",
124             "netconf-node-topology:pass-through": {}}]}
125         headers = {'content-type': 'application/json'}
126         response = requests.request(
127             "PUT", url, data=json.dumps(data), headers=headers,
128             auth=('admin', 'admin'))
129         self.assertEqual(response.status_code, requests.codes.created)
130         time.sleep(20)
131
132     def test_03_rdm_portmapping(self):
133         url = ("{}/config/transportpce-portmapping:network/"
134                "nodes/ROADMA"
135                .format(self.restconf_baseurl))
136         headers = {'content-type': 'application/json'}
137         response = requests.request(
138              "GET", url, headers=headers, auth=('admin', 'admin'))
139         self.assertEqual(response.status_code, requests.codes.ok)
140         res = response.json()
141         self.assertIn(
142              {'supporting-port': 'L1', 'supporting-circuit-pack-name': '2/0',
143               'logical-connection-point': 'DEG1-TTP-TXRX'},
144              res['nodes'][0]['mapping'])
145         self.assertIn(
146              {'supporting-port': 'C7', 'supporting-circuit-pack-name': '4/0',
147               'logical-connection-point': 'SRG1-PP7-TXRX'},
148              res['nodes'][0]['mapping'])
149
150     def test_04_xpdr_portmapping(self):
151         url = ("{}/config/transportpce-portmapping:network/"
152                "nodes/XPDRA"
153                .format(self.restconf_baseurl))
154         headers = {'content-type': 'application/json'}
155         response = requests.request(
156              "GET", url, headers=headers, auth=('admin', 'admin'))
157         self.assertEqual(response.status_code, requests.codes.ok)
158         res = response.json()
159         self.assertIn(
160              {'supporting-port': '1', 'supporting-circuit-pack-name': '1/0/1-PLUG-NET',
161               'logical-connection-point': 'XPDR1-NETWORK1'},
162              res['nodes'][0]['mapping'])
163         self.assertIn(
164              {'supporting-port': 'C1',
165               'supporting-circuit-pack-name': '1/0/C1-PLUG-CLIENT',
166               'logical-connection-point': 'XPDR1-CLIENT1'},
167              res['nodes'][0]['mapping'])
168
169     def test_05_service_path_create(self):
170         url = "{}/operations/transportpce-device-renderer:service-path".format(self.restconf_baseurl)
171         data = {"renderer:input": {
172              "renderer:service-name": "service_test",
173              "renderer:wave-number": "7",
174              "renderer:modulation-format": "qpsk",
175              "renderer:operation": "create",
176              "renderer:nodes": [
177                  {"renderer:node-id": "ROADMA",
178                   "renderer:src-tp": "SRG1-PP7-TXRX",
179                   "renderer:dest-tp": "DEG1-TTP-TXRX"},
180                  {"renderer:node-id": "XPDRA",
181                   "renderer:src-tp": "XPDR1-CLIENT1",
182                   "renderer:dest-tp": "XPDR1-NETWORK1"}]}}
183         headers = {'content-type': 'application/json'}
184         response = requests.request(
185              "POST", url, data=json.dumps(data),
186              headers=headers, auth=('admin', 'admin'))
187         self.assertEqual(response.status_code, requests.codes.ok)
188         res = response.json()
189         self.assertIn('Roadm-connection successfully created for nodes: ROADMA', res["output"]["result"])
190
191     def test_06_service_path_create_rdm_check(self):
192         url = ("{}/config/network-topology:network-topology/topology/topology-netconf/"
193                 "node/ROADMA/yang-ext:mount/org-openroadm-device:org-openroadm-device/"
194                 "interface/DEG1-TTP-TXRX-7"
195                 .format(self.restconf_baseurl))
196         headers = {'content-type': 'application/json'}
197         response = requests.request(
198              "GET", url, headers=headers, auth=('admin', 'admin'))
199         self.assertEqual(response.status_code, requests.codes.ok)
200         res = response.json()
201         self.assertDictContainsSubset({'name': 'DEG1-TTP-TXRX-7', 'administrative-state': 'inService',
202               'supporting-circuit-pack-name': '2/0',
203               'type': 'org-openroadm-interfaces:opticalChannel',
204               'supporting-port': 'L1'}, res['interface'][0])
205         self.assertDictEqual(
206              {'wavelength-number': 7},
207              res['interface'][0]['org-openroadm-optical-channel-interfaces:och'])
208
209     def test_07_service_path_create_rdm_check(self):
210         url = ("{}/config/network-topology:network-topology/topology/topology-netconf/"
211                 "node/ROADMA/yang-ext:mount/org-openroadm-device:org-openroadm-device/"
212                 "interface/SRG1-PP7-TXRX-7"
213                 .format(self.restconf_baseurl))
214         headers = {'content-type': 'application/json'}
215         response = requests.request(
216              "GET", url, headers=headers, auth=('admin', 'admin'))
217         self.assertEqual(response.status_code, requests.codes.ok)
218         res = response.json()
219         self.assertDictContainsSubset(
220              {'name': 'SRG1-PP7-TXRX-7', 'administrative-state': 'inService',
221               'supporting-circuit-pack-name': '4/0',
222               'type': 'org-openroadm-interfaces:opticalChannel',
223               'supporting-port': 'C7'},
224              res['interface'][0])
225         self.assertDictEqual(
226              {'wavelength-number': 7},
227              res['interface'][0]['org-openroadm-optical-channel-interfaces:och'])
228
229     def test_08_service_path_create_rdm_check(self):
230         url = ("{}/config/network-topology:network-topology/topology/topology-netconf/"
231                "node/ROADMA/yang-ext:mount/org-openroadm-device:org-openroadm-device/"
232                "roadm-connections/SRG1-PP7-TXRX-DEG1-TTP-TXRX-7"
233                .format(self.restconf_baseurl))
234         headers = {'content-type': 'application/json'}
235         response = requests.request(
236              "GET", url, headers=headers, auth=('admin', 'admin'))
237         self.assertEqual(response.status_code, requests.codes.ok)
238         res = response.json()
239         self.assertDictContainsSubset(
240              {'connection-number': 'SRG1-PP7-TXRX-DEG1-TTP-TXRX-7',
241               'wavelength-number': 7,
242               'opticalControlMode': 'off'},
243              res['roadm-connections'][0])
244         self.assertDictEqual(
245              {'src-if': 'SRG1-PP7-TXRX-7'},
246              res['roadm-connections'][0]['source'])
247         self.assertDictEqual(
248              {'dst-if': 'DEG1-TTP-TXRX-7'},
249              res['roadm-connections'][0]['destination'])
250
251     def test_09_service_path_create_xpdr_check(self):
252         url = ("{}/config/network-topology:network-topology/topology/topology-netconf/"
253                 "node/XPDRA/yang-ext:mount/org-openroadm-device:org-openroadm-device/"
254                 "interface/XPDR1-NETWORK1-7"
255                 .format(self.restconf_baseurl))
256         headers = {'content-type': 'application/json'}
257         response = requests.request(
258              "GET", url, headers=headers, auth=('admin', 'admin'))
259         self.assertEqual(response.status_code, requests.codes.ok)
260         res = response.json()
261         self.assertDictContainsSubset(
262              {'name': 'XPDR1-NETWORK1-7', 'administrative-state': 'inService',
263               'supporting-circuit-pack-name': '1/0/1-PLUG-NET',
264               'type': 'org-openroadm-interfaces:opticalChannel',
265               'supporting-port': '1'},
266              res['interface'][0])
267         self.assertDictEqual(
268              {u'rate': u'org-openroadm-optical-channel-interfaces:R100G',
269               u'transmit-power':-5,
270               u'wavelength-number': 7,
271               u'modulation-format': u'dp-qpsk'},
272              res['interface'][0]['org-openroadm-optical-channel-interfaces:och'])
273
274     def test_10_service_path_create_xpdr_check(self):
275         url = ("{}/config/network-topology:network-topology/topology/topology-netconf/"
276                 "node/XPDRA/yang-ext:mount/org-openroadm-device:org-openroadm-device/"
277                 "interface/XPDR1-NETWORK1-OTU"
278                 .format(self.restconf_baseurl))
279         headers = {'content-type': 'application/json'}
280         response = requests.request(
281              "GET", url, headers=headers, auth=('admin', 'admin'))
282         self.assertEqual(response.status_code, requests.codes.ok)
283         res = response.json()
284         self.assertDictContainsSubset(
285              {'name': 'XPDR1-NETWORK1-OTU', 'administrative-state': 'inService',
286               'supporting-circuit-pack-name': '1/0/1-PLUG-NET',
287               'type': 'org-openroadm-interfaces:otnOtu',
288               'supporting-port': '1',
289               'supporting-interface': 'XPDR1-NETWORK1-7'},
290              res['interface'][0])
291         self.assertDictEqual(
292              {u'rate': u'org-openroadm-otn-otu-interfaces:OTU4',
293               u'fec': u'scfec'},
294              res['interface'][0]['org-openroadm-otn-otu-interfaces:otu'])
295
296     def test_11_service_path_create_xpdr_check(self):
297         url = ("{}/config/network-topology:network-topology/topology/topology-netconf/"
298                 "node/XPDRA/yang-ext:mount/org-openroadm-device:org-openroadm-device/"
299                 "interface/XPDR1-NETWORK1-ODU"
300                 .format(self.restconf_baseurl))
301         headers = {'content-type': 'application/json'}
302         response = requests.request(
303              "GET", url, headers=headers, auth=('admin', 'admin'))
304         self.assertEqual(response.status_code, requests.codes.ok)
305         res = response.json()
306         self.assertDictContainsSubset(
307              {'name': 'XPDR1-NETWORK1-ODU', 'administrative-state': 'inService',
308               'supporting-circuit-pack-name': '1/0/1-PLUG-NET',
309               'type': 'org-openroadm-interfaces:otnOdu',
310               'supporting-port': '1',
311               'supporting-interface': 'XPDR1-NETWORK1-OTU'},
312              res['interface'][0])
313         self.assertDictContainsSubset(
314              {'rate': 'org-openroadm-otn-odu-interfaces:ODU4',
315               u'monitoring-mode': u'terminated'},
316              res['interface'][0]['org-openroadm-otn-odu-interfaces:odu'])
317         self.assertDictEqual({u'exp-payload-type': u'07', u'payload-type': u'07'},
318                               res['interface'][0]['org-openroadm-otn-odu-interfaces:odu']['opu'])
319
320     def test_12_service_path_create_xpdr_check(self):
321         url = ("{}/config/network-topology:network-topology/topology/topology-netconf/"
322                "node/XPDRA/yang-ext:mount/org-openroadm-device:org-openroadm-device/"
323                "interface/XPDR1-CLIENT1-ETHERNET"
324                .format(self.restconf_baseurl))
325         headers = {'content-type': 'application/json'}
326         response = requests.request(
327              "GET", url, headers=headers, auth=('admin', 'admin'))
328         self.assertEqual(response.status_code, requests.codes.ok)
329         res = response.json()
330         self.assertDictContainsSubset(
331              {'name': 'XPDR1-CLIENT1-ETHERNET', 'administrative-state': 'inService',
332               'supporting-circuit-pack-name': '1/0/C1-PLUG-CLIENT',
333               'type': 'org-openroadm-interfaces:ethernetCsmacd',
334               'supporting-port': 'C1'},
335              res['interface'][0])
336         self.assertDictEqual(
337              {'speed': 100000,
338               'mtu': 9000,
339               'auto-negotiation': 'enabled',
340               'duplex': 'full',
341               'fec': 'off'},
342              res['interface'][0]['org-openroadm-ethernet-interfaces:ethernet'])
343
344     def test_13_service_path_create_xpdr_check(self):
345         url = ("{}/config/network-topology:network-topology/topology/topology-netconf/"
346                 "node/XPDRA/yang-ext:mount/org-openroadm-device:org-openroadm-device/"
347                 "circuit-packs/1%2F0%2F1-PLUG-NET"
348                 .format(self.restconf_baseurl))
349         headers = {'content-type': 'application/json'}
350         response = requests.request(
351              "GET", url, headers=headers, auth=('admin', 'admin'))
352         self.assertEqual(response.status_code, requests.codes.ok)
353         res = response.json()
354         self.assertIn('not-reserved-inuse', res['circuit-packs'][0]["equipment-state"])
355
356     def test_14_service_path_delete(self):
357         url = "{}/operations/transportpce-device-renderer:service-path".format(self.restconf_baseurl)
358         data = {"renderer:input": {
359              "renderer:service-name": "service_test",
360              "renderer:wave-number": "7",
361              "renderer:operation": "delete",
362              "renderer:nodes": [
363                  {"renderer:node-id": "ROADMA",
364                   "renderer:src-tp": "SRG1-PP7-TXRX",
365                   "renderer:dest-tp": "DEG1-TTP-TXRX"},
366                  {"renderer:node-id": "XPDRA",
367                   "renderer:src-tp": "XPDR1-CLIENT1",
368                   "renderer:dest-tp": "XPDR1-NETWORK1"}]}}
369         headers = {'content-type': 'application/json'}
370         response = requests.request(
371              "POST", url, data=json.dumps(data),
372              headers=headers, auth=('admin', 'admin'))
373         self.assertEqual(response.status_code, requests.codes.ok)
374         self.assertEqual(response.json(), {
375              'output': {'result': 'Request processed', 'success': True}})
376
377     def test_15_service_path_delete_rdm_check(self):
378         url = ("{}/config/network-topology:network-topology/topology/topology-netconf/"
379                 "node/ROADMA/yang-ext:mount/org-openroadm-device:org-openroadm-device/"
380                 "interface/DEG1-TTP-TXRX-7"
381                 .format(self.restconf_baseurl))
382         headers = {'content-type': 'application/json'}
383         response = requests.request(
384              "GET", url, headers=headers, auth=('admin', 'admin'))
385         self.assertEqual(response.status_code, requests.codes.not_found)
386         res = response.json()
387         self.assertIn(
388              {"error-type":"application", "error-tag":"data-missing",
389               "error-message":"Request could not be completed because the relevant data model content does not exist"},
390              res['errors']['error'])
391
392     def test_16_service_path_delete_rdm_check(self):
393         url = ("{}/config/network-topology:network-topology/topology/topology-netconf/"
394                "node/ROADMA/yang-ext:mount/org-openroadm-device:org-openroadm-device/"
395                "interface/SRG1-PP7-TXRX-7"
396                .format(self.restconf_baseurl))
397         headers = {'content-type': 'application/json'}
398         response = requests.request(
399              "GET", url, headers=headers, auth=('admin', 'admin'))
400         self.assertEqual(response.status_code, requests.codes.not_found)
401         res = response.json()
402         self.assertIn(
403              {"error-type":"application", "error-tag":"data-missing", "error-message":"Request could not be completed because the relevant data model content does not exist"},
404              res['errors']['error'])
405
406     def test_17_service_path_delete_rdm_check(self):
407         url = ("{}/config/network-topology:network-topology/topology/topology-netconf/"
408                "node/ROADMA/yang-ext:mount/org-openroadm-device:org-openroadm-device/"
409                "roadm-connections/SRG1-PP7-TXRX-DEG1-TTP-TXRX-7"
410                .format(self.restconf_baseurl))
411         headers = {'content-type': 'application/json'}
412         response = requests.request(
413              "GET", url, headers=headers, auth=('admin', 'admin'))
414         self.assertEqual(response.status_code, requests.codes.not_found)
415         res = response.json()
416         self.assertIn(
417              {"error-type":"application", "error-tag":"data-missing", "error-message":"Request could not be completed because the relevant data model content does not exist"},
418              res['errors']['error'])
419
420     def test_18_service_path_delete_xpdr_check(self):
421         url = ("{}/config/network-topology:network-topology/topology/topology-netconf/"
422                "node/XPDRA/yang-ext:mount/org-openroadm-device:org-openroadm-device/"
423                "interface/XPDR1-NETWORK1-7"
424                .format(self.restconf_baseurl))
425         headers = {'content-type': 'application/json'}
426         response = requests.request(
427              "GET", url, headers=headers, auth=('admin', 'admin'))
428         self.assertEqual(response.status_code, requests.codes.not_found)
429         res = response.json()
430         self.assertIn(
431              {"error-type":"application", "error-tag":"data-missing", "error-message":"Request could not be completed because the relevant data model content does not exist"},
432              res['errors']['error'])
433
434     def test_19_service_path_delete_xpdr_check(self):
435         url = ("{}/config/network-topology:network-topology/topology/topology-netconf/"
436                "node/XPDRA/yang-ext:mount/org-openroadm-device:org-openroadm-device/"
437                "interface/XPDR1-NETWORK1-OTU"
438                .format(self.restconf_baseurl))
439         headers = {'content-type': 'application/json'}
440         response = requests.request(
441              "GET", url, headers=headers, auth=('admin', 'admin'))
442         self.assertEqual(response.status_code, requests.codes.not_found)
443         res = response.json()
444         self.assertIn(
445              {"error-type":"application", "error-tag":"data-missing", "error-message":"Request could not be completed because the relevant data model content does not exist"},
446              res['errors']['error'])
447
448     def test_20_service_path_delete_xpdr_check(self):
449         url = ("{}/config/network-topology:network-topology/topology/topology-netconf/"
450                "node/XPDRA/yang-ext:mount/org-openroadm-device:org-openroadm-device/"
451                "interface/XPDR1-NETWORK1-ODU"
452                .format(self.restconf_baseurl))
453         headers = {'content-type': 'application/json'}
454         response = requests.request(
455              "GET", url, headers=headers, auth=('admin', 'admin'))
456         self.assertEqual(response.status_code, requests.codes.not_found)
457         res = response.json()
458         self.assertIn(
459              {"error-type":"application", "error-tag":"data-missing", "error-message":"Request could not be completed because the relevant data model content does not exist"},
460              res['errors']['error'])
461
462     def test_21_service_path_delete_xpdr_check(self):
463         url = ("{}/config/network-topology:network-topology/topology/topology-netconf/"
464                "node/XPDRA/yang-ext:mount/org-openroadm-device:org-openroadm-device/"
465                "interface/XPDR1-CLIENT1-ETHERNET"
466                .format(self.restconf_baseurl))
467         headers = {'content-type': 'application/json'}
468         response = requests.request(
469              "GET", url, headers=headers, auth=('admin', 'admin'))
470         self.assertEqual(response.status_code, requests.codes.not_found)
471         res = response.json()
472         self.assertIn(
473              {"error-type":"application", "error-tag":"data-missing", "error-message":"Request could not be completed because the relevant data model content does not exist"},
474              res['errors']['error'])
475
476     def test_22_service_path_delete_xpdr_check(self):
477         url = ("{}/config/network-topology:network-topology/topology/topology-netconf/"
478                "node/XPDRA/yang-ext:mount/org-openroadm-device:org-openroadm-device/"
479                "circuit-packs/1%2F0%2F1-PLUG-NET"
480                .format(self.restconf_baseurl))
481         headers = {'content-type': 'application/json'}
482         response = requests.request(
483             "GET", url, headers=headers, auth=('admin', 'admin'))
484         self.assertEqual(response.status_code, requests.codes.ok)
485         res = response.json()
486         self.assertEqual('not-reserved-available', res["circuit-packs"][0]['equipment-state'])
487
488     def test_23_rdm_device_disconnected(self):
489         url = ("{}/config/network-topology:"
490                "network-topology/topology/topology-netconf/node/ROADMA"
491                .format(self.restconf_baseurl))
492         headers = {'content-type': 'application/json'}
493         response = requests.request(
494               "DELETE", url, headers=headers,
495               auth=('admin', 'admin'))
496         self.assertEqual(response.status_code, requests.codes.ok)
497         time.sleep(20)
498
499     def test_24_xpdr_device_disconnected(self):
500         url = ("{}/config/network-topology:"
501                 "network-topology/topology/topology-netconf/node/XPDRA"
502                .format(self.restconf_baseurl))
503         headers = {'content-type': 'application/json'}
504         response = requests.request(
505              "DELETE", url, headers=headers,
506              auth=('admin', 'admin'))
507         self.assertEqual(response.status_code, requests.codes.ok)
508         time.sleep(20)
509
510
511 if __name__ == "__main__":
512     unittest.main(verbosity=2, failfast=True)