Statistics
| Branch: | Tag: | Revision:

mininet / mininet / test / test_walkthrough.py @ fc2a8fd5

History | View | Annotate | Download (11.7 KB)

1
#!/usr/bin/env python
2

    
3
"""
4
Tests for the Mininet Walkthrough
5

6
TODO: missing xterm test
7
"""
8

    
9
import unittest
10
import pexpect
11
import os
12
from time import sleep
13
from mininet.util import quietRun
14

    
15
class testWalkthrough( unittest.TestCase ):
16

    
17
    prompt = 'mininet>'
18

    
19
    # PART 1
20
    def testHelp( self ):
21
        "Check the usage message"
22
        p = pexpect.spawn( 'mn -h' )
23
        index = p.expect( [ 'Usage: mn', pexpect.EOF ] )
24
        self.assertEqual( index, 0 )
25

    
26
    def testWireshark( self ):
27
        "Use tshark to test the of dissector"
28
        tshark = pexpect.spawn( 'tshark -i lo -R of' )
29
        tshark.expect( 'Capturing on lo' )
30
        mn = pexpect.spawn( 'mn --test pingall' )
31
        mn.expect( '0% dropped' )
32
        tshark.expect( 'OFP 74 Hello' )
33
        tshark.sendintr()
34

    
35
    def testBasic( self ):
36
        "Test basic CLI commands (help, nodes, net, dump)"
37
        p = pexpect.spawn( 'mn' )
38
        p.expect( self.prompt )
39
        # help command
40
        p.sendline( 'help' )
41
        index = p.expect( [ 'commands', self.prompt ] )
42
        self.assertEqual( index, 0, 'No output for "help" command')
43
        # nodes command
44
        p.sendline( 'nodes' )
45
        p.expect( '([chs]\d ?){4}' )
46
        nodes = p.match.group( 0 ).split()
47
        self.assertEqual( len( nodes ), 4, 'No nodes in "nodes" command')
48
        p.expect( self.prompt )
49
        # net command
50
        p.sendline( 'net' )
51
        expected = [ x for x in nodes ]
52
        while len( expected ) > 0:
53
            index = p.expect( expected )
54
            node = p.match.group( 0 )
55
            expected.remove( node )
56
            p.expect( '\n' )
57
        self.assertEqual( len( expected ), 0, '"nodes" and "net" differ')
58
        p.expect( self.prompt )
59
        # dump command
60
        p.sendline( 'dump' )
61
        expected = [ '<\w+ (%s)' % n for n in nodes ]
62
        actual = []
63
        for _ in nodes:
64
            index = p.expect( expected )
65
            node = p.match.group( 1 )
66
            actual.append( node )
67
            p.expect( '\n' )
68
        self.assertEqual( actual.sort(), nodes.sort(), '"nodes" and "dump" differ' ) 
69
        p.expect( self.prompt )
70
        p.sendline( 'exit' )
71
        p.wait()
72

    
73
    def testHostCommands( self ):
74
        "Test ifconfig and ps on h1 and s1"
75
        p = pexpect.spawn( 'mn' )
76
        p.expect( self.prompt )
77
        interfaces = [ 'h1-eth0', 's1-eth1', '[^-]eth0', 'lo', self.prompt ]
78
        # h1 ifconfig
79
        p.sendline( 'h1 ifconfig -a' )
80
        ifcount = 0
81
        while True:
82
            index = p.expect( interfaces )
83
            if index == 0 or index == 3:
84
                ifcount += 1
85
            elif index == 1:
86
                self.fail( 's1 interface displayed in "h1 ifconfig"' )
87
            elif index == 2:
88
                self.fail( 'eth0 displayed in "h1 ifconfig"' )
89
            else:
90
                break
91
        self.assertEqual( ifcount, 2, 'Missing interfaces on h1')
92
        # s1 ifconfig
93
        p.sendline( 's1 ifconfig -a' )
94
        ifcount = 0
95
        while True:
96
            index = p.expect( interfaces )
97
            if index == 0:
98
                self.fail( 'h1 interface displayed in "s1 ifconfig"' )
99
            elif index == 1 or index == 2 or index == 3:
100
                ifcount += 1
101
            else:
102
                break
103
        self.assertEqual( ifcount, 3, 'Missing interfaces on s1')
104
        # h1 ps
105
        p.sendline( 'h1 ps -a' )
106
        p.expect( self.prompt )
107
        h1Output = p.before
108
        # s1 ps
109
        p.sendline( 's1 ps -a' )
110
        p.expect( self.prompt )
111
        s1Output = p.before
112
        # strip command from ps output
113
        h1Output = h1Output.split( '\n', 1 )[ 1 ]
114
        s1Output = s1Output.split( '\n', 1 )[ 1 ]
115
        self.assertEqual( h1Output, s1Output, 'h1 and s1 "ps" output differs')
116
        p.sendline( 'exit' )
117
        p.wait()
118

    
119
    def testConnectivity( self ):
120
        "Test ping and pingall"
121
        p = pexpect.spawn( 'mn' )
122
        p.expect( self.prompt )
123
        p.sendline( 'h1 ping -c 1 h2' )
124
        p.expect( '1 packets transmitted, 1 received' )
125
        p.expect( self.prompt )
126
        p.sendline( 'pingall' )
127
        p.expect( '0% dropped' )
128
        p.expect( self.prompt )
129
        p.sendline( 'exit' )
130
        p.wait()
131

    
132
    def testSimpleHTTP( self ):
133
        "Start an HTTP server on h1 and wget from h2"
134
        p = pexpect.spawn( 'mn' )
135
        p.expect( self.prompt )
136
        p.sendline( 'h1 python -m SimpleHTTPServer 80 &' )
137
        p.expect( self.prompt )
138
        p.sendline( ' h2 wget -O - h1' )
139
        p.expect( '200 OK' )
140
        p.expect( self.prompt )
141
        p.sendline( 'h1 kill %python' )
142
        p.expect( self.prompt )
143
        p.sendline( 'exit' )
144
        p.wait()
145

    
146
    # PART 2
147
    def testRegressionRun( self ):
148
        "Test pingpair (0% drop) and iperf (bw > 0) regression tests"
149
        # test pingpair
150
        p = pexpect.spawn( 'mn --test pingpair' )
151
        p.expect( '0% dropped' )
152
        p.expect( pexpect.EOF )
153
        # test iperf
154
        p = pexpect.spawn( 'mn --test iperf' )
155
        p.expect( "Results: \['([\d\.]+) .bits/sec'," )
156
        bw = float( p.match.group( 1 ) )
157
        self.assertTrue( bw > 0 )
158
        p.expect( pexpect.EOF )
159

    
160
    def testTopoChange( self ):
161
        "Test pingall on single,3 and linear,4 topos"
162
        # testing single,3
163
        p = pexpect.spawn( 'mn --test pingall --topo single,3' )
164
        p.expect( '(\d+)/(\d+) received')
165
        received = int( p.match.group( 1 ) )
166
        sent = int( p.match.group( 2 ) )
167
        self.assertEqual( sent, 6, 'Wrong number of pings sent in single,3' )
168
        self.assertEqual( sent, received, 'Dropped packets in single,3')
169
        p.expect( pexpect.EOF )
170
        # testing linear,4
171
        p = pexpect.spawn( 'mn --test pingall --topo linear,4' )
172
        p.expect( '(\d+)/(\d+) received')
173
        received = int( p.match.group( 1 ) )
174
        sent = int( p.match.group( 2 ) )
175
        self.assertEqual( sent, 12, 'Wrong number of pings sent in linear,4' )
176
        self.assertEqual( sent, received, 'Dropped packets in linear,4')
177
        p.expect( pexpect.EOF )
178

    
179
    def testLinkChange( self ):
180
        "Test TCLink bw and delay"
181
        p = pexpect.spawn( 'mn --link tc,bw=10,delay=10ms' )
182
        # test bw
183
        p.expect( self.prompt )
184
        p.sendline( 'iperf' )
185
        p.expect( "Results: \['([\d\.]+) Mbits/sec'," )
186
        bw = float( p.match.group( 1 ) )
187
        self.assertTrue( bw < 10.1, 'Bandwidth > 10 Mb/s')
188
        self.assertTrue( bw > 9.0, 'Bandwidth < 9 Mb/s')
189
        p.expect( self.prompt )
190
        # test delay
191
        p.sendline( 'h1 ping -c 4 h2' )
192
        p.expect( 'rtt min/avg/max/mdev = ([\d\.]+)/([\d\.]+)/([\d\.]+)/([\d\.]+) ms' )
193
        delay = float( p.match.group( 2 ) )
194
        self.assertTrue( delay > 40, 'Delay < 40ms' )
195
        self.assertTrue( delay < 45, 'Delay > 40ms' )
196
        p.expect( self.prompt )
197
        p.sendline( 'exit' )
198
        p.wait()
199

    
200
    def testVerbosity( self ):
201
        "Test debug and output verbosity"
202
        # test output
203
        p = pexpect.spawn( 'mn -v output' )
204
        p.expect( self.prompt )
205
        self.assertEqual( len( p.before ), 0, 'Too much output for "output"' )
206
        p.sendline( 'exit' )
207
        p.wait()
208
        # test debug
209
        p = pexpect.spawn( 'mn -v debug --test none' )
210
        p.expect( pexpect.EOF )
211
        lines = p.before.split( '\n' )
212
        self.assertTrue( len( lines ) > 100, "Debug output is too short" )
213

    
214
    def testCustomTopo( self ):
215
        "Start Mininet using a custom topo, then run pingall"
216
        custom = os.path.dirname( os.path.realpath( __file__ ) )
217
        custom = os.path.join( custom, '../../custom/topo-2sw-2host.py' )
218
        custom = os.path.normpath( custom )
219
        p = pexpect.spawn( 'mn --custom %s --topo mytopo --test pingall' % custom )
220
        p.expect( '0% dropped' )
221
        p.expect( pexpect.EOF )
222

    
223
    def testStaticMAC( self ):
224
        "Verify that MACs are set to easy to read numbers"
225
        p = pexpect.spawn( 'mn --mac' )
226
        p.expect( self.prompt )
227
        for i in range( 1, 3 ):
228
            p.sendline( 'h%d ifconfig' % i )
229
            p.expect( 'HWaddr 00:00:00:00:00:0%d' % i )
230
            p.expect( self.prompt )
231

    
232
    def testSwitches( self ):
233
        "Run iperf test using user and ovsk switches"
234
        switches = [ 'user', 'ovsk' ]
235
        for sw in switches:
236
            p = pexpect.spawn( 'mn --switch %s --test iperf' % sw )
237
            p.expect( "Results: \['([\d\.]+) .bits/sec'," )
238
            bw = float( p.match.group( 1 ) )
239
            self.assertTrue( bw > 0 )
240
            p.expect( pexpect.EOF )
241

    
242
    def testBenchmark( self ):
243
        "Run benchmark and verify that it takes less than 2 seconds"
244
        p = pexpect.spawn( 'mn --test none' )
245
        p.expect( 'completed in ([\d\.]+) seconds' )
246
        time = float( p.match.group( 1 ) )
247
        self.assertTrue( time < 2, 'Benchmark takes more than 2 seconds' )
248

    
249
    def testOwnNamespace( self ):
250
        "Test running user switch in its own namespace"
251
        p = pexpect.spawn( 'mn --innamespace --switch user' )
252
        p.expect( self.prompt )
253
        interfaces = [ 'h1-eth0', 's1-eth1', '[^-]eth0', 'lo', self.prompt ]
254
        p.sendline( 's1 ifconfig -a' )
255
        ifcount = 0
256
        while True:
257
            index = p.expect( interfaces )
258
            if index == 1 or index == 3:
259
                ifcount += 1
260
            elif index == 0:
261
                self.fail( 'h1 interface displayed in "s1 ifconfig"' )
262
            elif index == 2:
263
                self.fail( 'eth0 displayed in "s1 ifconfig"' )
264
            else:
265
                break
266
        self.assertEqual( ifcount, 2, 'Missing interfaces on s1' )
267
        # verify that all hosts a reachable
268
        p.sendline( 'pingall' )
269
        p.expect( '(\d+)% dropped' )
270
        dropped = int( p.match.group( 1 ) )
271
        self.assertEqual( dropped, 0, 'pingall failed')
272
        p.expect( self.prompt )
273
        p.sendline( 'exit' )
274
        p.wait()
275

    
276
    # PART 3
277
    def testPythonInterpreter( self ):
278
        "Test py and px by checking IP for h1 and adding h3"
279
        p = pexpect.spawn( 'mn' )
280
        p.expect( self.prompt )
281
        # test host IP
282
        p.sendline( 'py h1.IP()' )
283
        p.expect( '10.0.0.1' )
284
        p.expect( self.prompt )
285
        # test adding host
286
        p.sendline( "px net.addHost('h3')" )
287
        p.expect( self.prompt )
288
        p.sendline( "px net.addLink(s1, h3)" )
289
        p.expect( self.prompt )
290
        p.sendline( 'net' )
291
        p.expect( 'h3' )
292
        p.expect( self.prompt )
293
        p.sendline( 'py h3.MAC()' )
294
        p.expect( '([a-f0-9]{2}:?){6}' )
295
        p.expect( self.prompt )
296
        p.sendline( 'exit' )
297
        p.wait()
298

    
299
    def testLink( self ):
300
        "Test link CLI command using ping"
301
        p = pexpect.spawn( 'mn' )
302
        p.expect( self.prompt )
303
        p.sendline( 'link s1 h1 down' )
304
        p.expect( self.prompt )
305
        p.sendline( 'h1 ping -c 1 h2' )
306
        p.expect( 'unreachable' )
307
        p.expect( self.prompt )
308
        p.sendline( 'link s1 h1 up' )
309
        p.expect( self.prompt )
310
        p.sendline( 'h1 ping -c 1 h2' )
311
        p.expect( '0% packet loss' )
312
        p.expect( self.prompt )
313
        p.sendline( 'exit' )
314
        p.wait()
315

    
316
    @unittest.skipUnless( os.path.exists( '/tmp/pox' ) or
317
                          '1 received' in quietRun( 'ping -c 1 github.com' ),
318
                          'Github is not reachable; cannot download Pox' )
319
    def testRemoteController( self ):
320
        "Test Mininet using Pox controller"
321
        if not os.path.exists( '/tmp/pox' ):
322
            p = pexpect.spawn( 'git clone https://github.com/noxrepo/pox.git /tmp/pox' )
323
            p.expect( pexpect.EOF )
324
        pox = pexpect.spawn( '/tmp/pox/pox.py forwarding.l2_learning' )
325
        net = pexpect.spawn( 'mn --controller=remote,ip=127.0.0.1,port=6633 --test pingall' )
326
        net.expect( '0% dropped' )
327
        net.expect( pexpect.EOF )
328
        pox.sendintr()
329
        pox.wait()
330

    
331
if __name__ == '__main__':
332
    unittest.main()