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