blob: 3664d9fd4399c227564262d91d684195ddd45553 [file] [log] [blame]
Rich Laneb90a1c42012-10-05 09:16:05 -07001"""
2Base classes for test cases
3
4Tests will usually inherit from one of these classes to have the controller
5and/or dataplane automatically set up.
6"""
7
8import logging
9import unittest
10
11from oftest import config
12import oftest.controller as controller
13import oftest.cstruct as ofp
14import oftest.message as message
15import oftest.dataplane as dataplane
16import oftest.action as action
17
18from oftest.testutils import *
19
20class SimpleProtocol(unittest.TestCase):
21 """
22 Root class for setting up the controller
23 """
24
25 def setUp(self):
26 logging.info("** START TEST CASE " + str(self))
27 self.controller = controller.Controller(
28 host=config["controller_host"],
29 port=config["controller_port"])
30 # clean_shutdown should be set to False to force quit app
31 self.clean_shutdown = True
32 self.controller.start()
33 #@todo Add an option to wait for a pkt transaction to ensure version
34 # compatibilty?
35 self.controller.connect(timeout=20)
36
37 # By default, respond to echo requests
38 self.controller.keep_alive = True
39
40 if not self.controller.active:
41 raise Exception("Controller startup failed")
42 if self.controller.switch_addr is None:
43 raise Exception("Controller startup failed (no switch addr)")
44 logging.info("Connected " + str(self.controller.switch_addr))
45 request = message.features_request()
46 reply, pkt = self.controller.transact(request)
47 self.assertTrue(reply is not None,
48 "Did not complete features_request for handshake")
49 self.supported_actions = reply.actions
50 logging.info("Supported actions: " + hex(self.supported_actions))
51
52 def inheritSetup(self, parent):
53 """
54 Inherit the setup of a parent
55
56 This allows running at test from within another test. Do the
57 following:
58
59 sub_test = SomeTestClass() # Create an instance of the test class
60 sub_test.inheritSetup(self) # Inherit setup of parent
61 sub_test.runTest() # Run the test
62
63 Normally, only the parent's setUp and tearDown are called and
64 the state after the sub_test is run must be taken into account
65 by subsequent operations.
66 """
67 logging.info("** Setup " + str(self) + " inheriting from "
68 + str(parent))
69 self.controller = parent.controller
70 self.supported_actions = parent.supported_actions
71
72 def tearDown(self):
73 logging.info("** END TEST CASE " + str(self))
74 self.controller.shutdown()
75 #@todo Review if join should be done on clean_shutdown
76 if self.clean_shutdown:
77 self.controller.join()
78
79 def runTest(self):
80 # Just a simple sanity check as illustration
81 logging.info("Running simple proto test")
82 self.assertTrue(self.controller.switch_socket is not None,
83 str(self) + 'No connection to switch')
84
85 def assertTrue(self, cond, msg):
86 if not cond:
87 logging.error("** FAILED ASSERTION: " + msg)
88 unittest.TestCase.assertTrue(self, cond, msg)
89
90class SimpleDataPlane(SimpleProtocol):
91 """
92 Root class that sets up the controller and dataplane
93 """
94 def setUp(self):
95 SimpleProtocol.setUp(self)
96 self.dataplane = dataplane.DataPlane(config)
97 for of_port, ifname in config["port_map"].items():
98 self.dataplane.port_add(ifname, of_port)
99
100 def inheritSetup(self, parent):
101 """
102 Inherit the setup of a parent
103
104 See SimpleProtocol.inheritSetup
105 """
106 SimpleProtocol.inheritSetup(self, parent)
107 self.dataplane = parent.dataplane
108
109 def tearDown(self):
110 logging.info("Teardown for simple dataplane test")
111 SimpleProtocol.tearDown(self)
112 if hasattr(self, 'dataplane'):
113 self.dataplane.kill(join_threads=self.clean_shutdown)
114 logging.info("Teardown done")
115
116 def runTest(self):
117 self.assertTrue(self.controller.switch_socket is not None,
118 str(self) + 'No connection to switch')
119 # self.dataplane.show()
120 # Would like an assert that checks the data plane
121
122class DataPlaneOnly(unittest.TestCase):
123 """
124 Root class that sets up only the dataplane
125 """
126
127 def setUp(self):
128 self.clean_shutdown = True
129 logging.info("** START DataPlaneOnly CASE " + str(self))
130 self.dataplane = dataplane.DataPlane(config)
131 for of_port, ifname in config["port_map"].items():
132 self.dataplane.port_add(ifname, of_port)
133
134 def tearDown(self):
135 logging.info("Teardown for simple dataplane test")
136 self.dataplane.kill(join_threads=self.clean_shutdown)
137 logging.info("Teardown done")
138
139 def runTest(self):
140 logging.info("DataPlaneOnly")
141 # self.dataplane.show()
142 # Would like an assert that checks the data plane