Skip to content

Commit ed29d43

Browse files
authored
Merge pull request #2015 from anarkiwi/master
increase clib lint score, and fix flake in test_tcpdump_nextline as ping can exit before test terminates it.
2 parents 20bdff1 + 180098e commit ed29d43

File tree

4 files changed

+98
-76
lines changed

4 files changed

+98
-76
lines changed

clib/clib_mininet_test_unit.py

+36-20
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@
55

66
import os
77
import re
8-
import time
98

109
from mininet.net import Mininet
1110

@@ -16,6 +15,7 @@
1615
from tcpdump_helper import TcpdumpHelper
1716
from docker_host import MakeDockerHost
1817

18+
1919
class FaucetSimpleTest(mininet_test_base.FaucetTestBase):
2020
"""Basic untagged VLAN test."""
2121

@@ -49,18 +49,29 @@ def test_ping_all(self):
4949
class FaucetTcpdumpHelperTest(FaucetSimpleTest):
5050
"""Test for TcpdumpHelper class"""
5151

52+
53+
def _terminate_with_zero(self, tcpdump_helper):
54+
term_returns = tcpdump_helper.terminate()
55+
self.assertEqual(
56+
0, term_returns, msg='terminate code not 0: %d' % term_returns)
57+
58+
def _terminate_with_nonzero(self, tcpdump_helper):
59+
term_returns = tcpdump_helper.terminate()
60+
self.assertNotEqual(
61+
0, term_returns, msg='terminate code s 0: %d' % term_returns)
62+
5263
def test_tcpdump_execute(self):
5364
"""Check tcpdump filter monitors ping using execute"""
5465
self.ping_all_when_learned()
5566
from_host = self.net.hosts[0]
5667
to_host = self.net.hosts[1]
5768
tcpdump_filter = ('icmp')
5869
tcpdump_helper = TcpdumpHelper(to_host, tcpdump_filter, [
59-
lambda: from_host.cmd('ping -c1 %s' % to_host.IP())])
70+
lambda: from_host.cmd('ping -c1 %s' % to_host.IP())])
6071
tcpdump_txt = tcpdump_helper.execute()
6172
self.assertTrue(re.search(
6273
'%s: ICMP echo request' % to_host.IP(), tcpdump_txt))
63-
self.assertEqual(tcpdump_helper.terminate(), 0, 'terminate result code')
74+
self._terminate_with_zero(tcpdump_helper)
6475

6576
def test_tcpdump_pcap(self):
6677
"""Check tcpdump creates pcap output"""
@@ -69,11 +80,12 @@ def test_tcpdump_pcap(self):
6980
to_host = self.net.hosts[1]
7081
tcpdump_filter = ('icmp')
7182
pcap_file = os.path.join(self.tmpdir, 'out.pcap')
72-
tcpdump_helper = TcpdumpHelper(to_host, tcpdump_filter, [
73-
lambda: from_host.cmd('ping -c3 %s' % to_host.IP())],
74-
pcap_out = pcap_file, packets = None)
75-
tcpdump_txt = tcpdump_helper.execute()
76-
self.assertEqual(tcpdump_helper.terminate(), 0, 'terminate result code')
83+
tcpdump_helper = TcpdumpHelper(
84+
to_host, tcpdump_filter,
85+
[lambda: from_host.cmd('ping -c3 %s' % to_host.IP())],
86+
pcap_out=pcap_file, packets=None)
87+
tcpdump_helper.execute()
88+
self._terminate_with_zero(tcpdump_helper)
7789
result = from_host.cmd('tcpdump -en -r %s' % pcap_file)
7890
self.assertEqual(result.count('ICMP echo reply'), 3, 'three icmp echo replies')
7991

@@ -83,14 +95,15 @@ def test_tcpdump_noblock(self):
8395
from_host = self.net.hosts[0]
8496
to_host = self.net.hosts[1]
8597
tcpdump_filter = ('icmp')
86-
tcpdump_helper = TcpdumpHelper(to_host, tcpdump_filter, [
87-
lambda: from_host.cmd('ping -c10 %s' % to_host.IP())],
88-
blocking = False, packets = None)
98+
tcpdump_helper = TcpdumpHelper(
99+
to_host, tcpdump_filter,
100+
[lambda: from_host.cmd('ping -c10 %s' % to_host.IP())],
101+
blocking=False, packets=None)
89102
count = 0
90103
while tcpdump_helper.next_line():
91104
count = count + 1
92105
self.assertTrue(count < 10, 'Too many ping results before noblock')
93-
self.assertNotEqual(tcpdump_helper.terminate(), 0, 'terminate result code')
106+
self._terminate_with_nonzero(tcpdump_helper)
94107

95108
def test_tcpdump_nextline(self):
96109
"""Check tcpdump filter monitors ping using next_line"""
@@ -99,7 +112,7 @@ def test_tcpdump_nextline(self):
99112
to_host = self.net.hosts[1]
100113
tcpdump_filter = ('icmp')
101114
tcpdump_helper = TcpdumpHelper(to_host, tcpdump_filter, [
102-
lambda: from_host.cmd('ping -c2 %s' % to_host.IP())])
115+
lambda: from_host.cmd('ping -c5 -i2 %s' % to_host.IP())])
103116

104117
self.assertTrue(re.search('proto ICMP', tcpdump_helper.next_line()))
105118
next_line = tcpdump_helper.next_line()
@@ -110,18 +123,18 @@ def test_tcpdump_nextline(self):
110123
self.assertFalse(re.search('ICMP', tcpdump_helper.next_line()))
111124
while tcpdump_helper.next_line():
112125
pass
113-
self.assertEqual(tcpdump_helper.terminate(), 0, 'terminate result code')
126+
self._terminate_with_zero(tcpdump_helper)
114127

115128

116129
class FaucetDockerHostTest(FaucetSimpleTest):
117130

118-
N_UNTAGGED=2
119-
N_EXTENDED=2
120-
EXTENDED_CLS=MakeDockerHost('faucet/test-host')
131+
N_UNTAGGED = 2
132+
N_EXTENDED = 2
133+
EXTENDED_CLS = MakeDockerHost('faucet/test-host')
121134

122135
def test_containers(self):
123136
"""Test containers to make sure they're actually docker."""
124-
count=0
137+
count = 0
125138
host_name = None
126139

127140
for host in self.net.hosts:
@@ -132,10 +145,13 @@ def test_containers(self):
132145
host.activate()
133146
host.wait()
134147

135-
self.assertTrue(count == self.N_EXTENDED,
148+
self.assertTrue(
149+
count == self.N_EXTENDED,
136150
'Found %d containers, expected %d' % (count, self.N_EXTENDED))
137151

138-
self.assertTrue(os.path.exists(os.path.join(self.tmpdir, host_name, 'tmp')),
152+
self.assertTrue(
153+
os.path.exists(
154+
os.path.join(self.tmpdir, host_name, 'tmp')),
139155
'container tmp dir missing')
140156

141157
host_log = os.path.join(self.tmpdir, host_name, 'activate.log')

clib/docker_host.py

+39-34
Original file line numberDiff line numberDiff line change
@@ -4,20 +4,20 @@
44
import operator
55
import os
66
import pty
7-
import re
87
import select
9-
import time
8+
from subprocess import PIPE, STDOUT
109

1110
# pylint: disable=import-error
1211
from mininet.log import error, debug
1312
from mininet.node import Host
14-
from subprocess import PIPE, STDOUT
1513

1614
from mininet_test_util import DEVNULL
1715

1816
def MakeDockerHost(image, prefix='mininet', startup_timeout_ms=None):
17+
1918
class ImageHost(DockerHost):
20-
def __init__( self, *args, **kwargs ):
19+
20+
def __init__(self, *args, **kwargs):
2121
host_name = args[0]
2222
kwargs['image'] = image
2323
assert kwargs['tmpdir'], 'tmpdir required for docker host'
@@ -29,7 +29,7 @@ def __init__( self, *args, **kwargs ):
2929
env_val = os.environ['DOCKER_STARTUP_TIMEOUT_MS']
3030
if env_val:
3131
kwargs['startup_timeout_ms'] = int(env_val)
32-
DockerHost.__init__(self, *args, **kwargs )
32+
DockerHost.__init__(self, *args, **kwargs)
3333
return ImageHost
3434

3535

@@ -59,22 +59,24 @@ class DockerHost(Host):
5959
vol_maps = None
6060
prefix = None
6161
startup_timeout_ms = None
62-
62+
container = None
63+
pollIn = None
64+
active_log = None
6365

6466
def __init__(self, name, image=None, tmpdir=None, prefix=None, env_vars=[],
65-
vol_maps=[], startup_timeout_ms=STARTUP_TIMEOUT_MS, **kwargs ):
67+
vol_maps=[], startup_timeout_ms=STARTUP_TIMEOUT_MS, **kwargs):
6668
self.image = image
6769
self.tmpdir = tmpdir
6870
self.prefix = prefix
6971
self.env_vars = env_vars
7072
self.vol_maps = vol_maps
7173
self.startup_timeout_ms = startup_timeout_ms
72-
Host.__init__( self, name, **kwargs )
74+
Host.__init__(self, name, **kwargs)
7375

74-
def startShell( self ):
75-
"Start a shell process for running commands"
76+
def startShell(self):
77+
"""Start a shell process for running commands."""
7678
if self.shell:
77-
error( "%s: shell is already running" )
79+
error('shell is already running')
7880
return
7981

8082
self.container = '%s-%s' % (self.prefix, self.name)
@@ -86,12 +88,13 @@ def startShell( self ):
8688
container_tmp_dir = os.path.join(os.path.abspath(self.tmpdir), 'tmp')
8789
tmp_volume = container_tmp_dir + ':/tmp'
8890

89-
base_cmd = [ "docker", "run", "-ti", "--privileged", "--entrypoint", "env",
90-
"--net=none", "-h", self.name, "--name", self.container ]
91-
env_args = reduce(operator.add, ([ '--env', var ] for var in self.env_vars), [])
92-
vol_args = reduce(operator.add, ([ '-v', var ] for var in self.vol_maps), [ '-v', tmp_volume ])
93-
image_args = [ self.image, "TERM=dumb", "PS1=" + chr(127), "bash", "--norc",
94-
"-is", "mininet:" + self.name ]
91+
base_cmd = ["docker", "run", "-ti", "--privileged", "--entrypoint", "env",
92+
"--net=none", "-h", self.name, "--name", self.container]
93+
env_args = reduce(operator.add, (['--env', var] for var in self.env_vars), [])
94+
vol_args = reduce(operator.add, (['-v', var] for var in self.vol_maps), ['-v', tmp_volume])
95+
image_args = [
96+
self.image, "TERM=dumb", "PS1=" + chr(127), "bash", "--norc",
97+
"-is", "mininet:" + self.name]
9598
cmd = base_cmd + env_args + vol_args + image_args
9699
self.master, self.slave = pty.openpty()
97100
debug('docker command "%s", fd %d, fd %d' % (' '.join(cmd), self.master, self.slave))
@@ -130,11 +133,11 @@ def startShell( self ):
130133
def kill(self, purge=False):
131134
debug('killing container %s.' % self.container)
132135
if purge:
133-
kill_cmd = [ "docker", "rm", "-f", self.container ]
136+
kill_cmd = ["docker", "rm", "-f", self.container]
134137
else:
135-
kill_cmd = [ "docker", "kill", self.container ]
138+
kill_cmd = ["docker", "kill", self.container]
136139
try:
137-
kill_pipe = self._popen( kill_cmd, stdin=DEVNULL, stdout=PIPE, stderr=STDOUT)
140+
kill_pipe = self._popen(kill_cmd, stdin=DEVNULL, stdout=PIPE, stderr=STDOUT)
138141
kill_pipe.stdout.readlines()
139142
kill_pipe.stdout.close()
140143
except:
@@ -144,8 +147,8 @@ def kill(self, purge=False):
144147

145148
def inspect_pid(self):
146149
try:
147-
pid_cmd = ["docker","inspect","--format={{ .State.Pid }}", self.container]
148-
pid_pipe = self._popen( pid_cmd, stdin=DEVNULL, stdout=PIPE, stderr=STDOUT)
150+
pid_cmd = ["docker", "inspect", "--format={{ .State.Pid }}", self.container]
151+
pid_pipe = self._popen(pid_cmd, stdin=DEVNULL, stdout=PIPE, stderr=STDOUT)
149152
ps_out = pid_pipe.stdout.readlines()
150153
pid_pipe.stdout.close()
151154
return int(ps_out[0])
@@ -200,37 +203,39 @@ def wait(self):
200203
self.active_pipe.returncode = self.active_pipe.wait()
201204
self.terminate()
202205
return self.active_pipe_returncode
203-
except Exception as e:
204-
error('Exception waiting for %s: %s' % (self.container, e))
206+
except Exception as err:
207+
error('Exception waiting for %s: %s' % (self.container, err))
205208
self.terminate()
206209
raise
207210

208-
def read( self, maxbytes=1024 ):
211+
def read(self, maxbytes=1024):
209212
poll_results = self.pollIn.poll(self.startup_timeout_ms)
210213
data_ready = poll_results and (poll_results[0][1] & select.POLLIN)
211-
assert data_ready, ('Timeout waiting for read data on %d after %ds' %
212-
(self.stdout.fileno(), self.startup_timeout_ms / 1000))
214+
assert data_ready, (
215+
'Timeout waiting for read data on %d after %ds' %
216+
(self.stdout.fileno(), self.startup_timeout_ms / 1e3))
213217
return Host.read(self, maxbytes)
214218

215219
def terminate(self):
216220
"""Override Mininet terminate() to partially avoid pty leak."""
217-
debug('Terminating container %s, shell %s, pipe %s' % (self.container, self.shell, self.active_pipe))
221+
debug('Terminating container %s, shell %s, pipe %s' % (
222+
self.container, self.shell, self.active_pipe))
218223
if self.slave:
219224
os.close(self.slave)
220225
self.slave = None
221226
if self.shell is not None:
222227
self.stdin.close()
223228
self.stdin = None
224229
self.master = None
225-
if self.shell.returncode == None:
230+
if self.shell.returncode is None:
226231
self.shell.kill()
227232
self.shell.poll()
228233
self.kill()
229234
self.shell = None
230235
if self.active_pipe:
231236
if self.active_pipe.stdout:
232237
self.active_pipe.stdout.close()
233-
if self.active_pipe.returncode == None:
238+
if self.active_pipe.returncode is None:
234239
self.active_pipe.kill()
235240
self.active_pipe.poll()
236241
self.active_pipe_returncode = self.active_pipe.returncode
@@ -241,15 +246,15 @@ def terminate(self):
241246
self.cleanup() # pylint: disable=no-member
242247
return self.active_pipe_returncode
243248

244-
def popen( self, *args, **kwargs ):
249+
def popen(self, *args, **kwargs):
245250
"""Return a Popen() object in node's namespace
246251
args: Popen() args, single list, or string
247252
kwargs: Popen() keyword args"""
248253
# -t is necessary to prevent docker from buffering output. It might cause
249254
# problems with some commands like shells that then assume they can output
250255
# all sorts of crazy control characters b/c it's a terminal.
251-
mncmd = [ 'docker', 'exec', '--env', 'TERM=dumb', '-t', self.container ]
252-
pipe = Host.popen( self, mncmd=mncmd, *args, **kwargs )
256+
mncmd = ['docker', 'exec', '--env', 'TERM=dumb', '-t', self.container]
257+
pipe = Host.popen(self, mncmd=mncmd, *args, **kwargs)
253258
if pipe:
254259
debug('docker pid %d: %s %s %s' % (pipe.pid, mncmd, args, kwargs))
255260
return pipe
@@ -259,7 +264,7 @@ def _popen(self, cmd, **params):
259264
# a normal interactive terminal would. So, put it in a separate process group
260265
# so it doesn't receive stray SIGINTs, rather relying on the message sent
261266
# from the owning process through the pty.
262-
if not 'preexec_fn' in params:
267+
if 'preexec_fn' not in params:
263268
params['preexec_fn'] = os.setpgrp
264269
pipe = super(DockerHost, self)._popen(cmd, **params)
265270
if pipe:

clib/mininet_test_topo.py

+5-5
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,7 @@ def terminate(self):
8181
if self.shell is not None:
8282
os.close(self.slave)
8383
self.stdin.close()
84-
if self.shell.returncode == None:
84+
if self.shell.returncode is None:
8585
self.shell.kill()
8686
self.shell.poll()
8787
self.cleanup() # pylint: disable=no-member
@@ -116,11 +116,11 @@ def start(self, controllers):
116116
for intf in switch_intfs)
117117
# Command to create controller entries
118118
clist = [(self.name + c.name, '%s:%s:%d' %
119-
(c.protocol, c.IP(), c.port))
119+
(c.protocol, c.IP(), c.port))
120120
for c in controllers]
121121
if self.listenPort:
122122
clist.append((self.name + '-listen',
123-
'ptcp:%s' % self.listenPort))
123+
'ptcp:%s' % self.listenPort))
124124
ccmd = '-- --id=@%s create Controller target=\\"%s\\"'
125125
if self.reconnectms:
126126
ccmd += ' max_backoff=%d' % self.reconnectms
@@ -138,12 +138,12 @@ def start(self, controllers):
138138
' -- add-br %s' % self +
139139
' -- set bridge %s controller=[%s]' % (self, cids) +
140140
self.bridgeOpts() +
141-
intfs )
141+
intfs)
142142
# switch interfaces on mininet host, must have no IP config.
143143
for intf in switch_intfs:
144144
for ipv in (4, 6):
145145
self.cmd('ip -%u addr flush dev %s' % (ipv, intf))
146-
assert '' == self.cmd('echo 1 > /proc/sys/net/ipv6/conf/%s/disable_ipv6' % intf)
146+
assert self.cmd('echo 1 > /proc/sys/net/ipv6/conf/%s/disable_ipv6' % intf) == ''
147147
# If necessary, restore TC config overwritten by OVS
148148
if not self.batch:
149149
for intf in self.intfList():

0 commit comments

Comments
 (0)