Merge branch 'master' of github.com:floodlight/oftest
diff --git a/src/python/.gitignore b/src/python/.gitignore
index 21adf03..4b0053b 100644
--- a/src/python/.gitignore
+++ b/src/python/.gitignore
@@ -1,3 +1,4 @@
 /build/
 /dist/
 /oftest.egg-info/
+*.pyc
diff --git a/tests/basic.py b/tests/basic.py
index 5a286fe..feda04f 100644
--- a/tests/basic.py
+++ b/tests/basic.py
@@ -41,6 +41,8 @@
 
 test_prio = {}
 
+TEST_VID_DEFAULT = 2
+
 def test_set_init(config):
     """
     Set up function for basic test classes
@@ -253,9 +255,13 @@
         self.assertEqual(rc, 0, "Failed to delete all flows")
         self.assertEqual(do_barrier(self.controller), 0, "Barrier failed")
 
+        vid = test_param_get(self.config, 'vid', default=TEST_VID_DEFAULT)
+
         for of_port in basic_port_map.keys():
             for pkt, pt in [
                (simple_tcp_packet(), "simple TCP packet"),
+               (simple_tcp_packet(dl_vlan_enable=True,dl_vlan=vid,pktlen=108), 
+                "simple tagged TCP packet"),
                (simple_eth_packet(), "simple Ethernet packet"),
                (simple_eth_packet(pktlen=40), "tiny Ethernet packet")]:
 
@@ -557,5 +563,44 @@
                              ofp.OFPPC_NO_FLOOD, basic_logger)
         self.assertTrue(rv != -1, "Error sending port mod")
 
+class PortConfigModErr(SimpleProtocol):
+    """
+    Modify a bit in port config on an invalid port and verify
+    error message is received.
+    """
+
+    def runTest(self):
+        basic_logger.info("Running " + str(self))
+
+        # pick a random bad port number
+        bad_port = random.randint(1, ofp.OFPP_MAX)
+        count = 0
+        while (count < 50) and (bad_port in basic_port_map.keys()):
+            bad_port = random.randint(1, ofp.OFPP_MAX)
+            count = count + 1
+        self.assertTrue(count < 50, "Error selecting bad port")
+        basic_logger.info("Select " + str(bad_port) + " as invalid port")
+
+        rv = port_config_set(self.controller, bad_port,
+                             ofp.OFPPC_NO_FLOOD, ofp.OFPPC_NO_FLOOD,
+                             basic_logger)
+        self.assertTrue(rv != -1, "Error sending port mod")
+
+        # poll for error message
+        while True:
+            (response, raw) = self.controller.poll(ofp.OFPT_ERROR, 2)
+            if not response:  # Timeout
+                break
+            if response.code == ofp.OFPPMFC_BAD_PORT:
+                basic_logger.info("Received error message with OFPPMFC_BAD_PORT code")
+                break
+            if not basic_config["relax"]:  # Only one attempt to match
+                break
+            count += 1
+            if count > 10:   # Too many tries
+                break
+
+        self.assertTrue(response is not None, 'Did not receive error message')
+
 if __name__ == "__main__":
     print "Please run through oft script:  ./oft --test_spec=basic"
diff --git a/tests/flow_query.py b/tests/flow_query.py
index 6044758..bad4749 100644
--- a/tests/flow_query.py
+++ b/tests/flow_query.py
@@ -62,6 +62,7 @@
 
 import unittest
 import random
+import time
 
 import oftest.controller  as controller
 import oftest.cstruct     as ofp
@@ -1562,6 +1563,9 @@
     
         return result
 
+    def settle(self):
+        time.sleep(2)
+
 # FLOW ADD 5
 #
 # OVERVIEW
@@ -1652,6 +1656,8 @@
 
         result = True
 
+        sw.settle()  # Allow switch to settle and generate any notifications
+        
         # Check for any error messages
 
         if not sw.errors_verify(0):
@@ -1757,6 +1763,8 @@
 
         result = True
 
+        sw.settle()  # Allow switch to settle and generate any notifications
+
         # Check for any error messages
 
         if not sw.errors_verify(0):
@@ -1863,6 +1871,8 @@
 
         result = True
 
+        sw.settle()  # Allow switch to settle and generate any notifications
+
         # Check for any error messages
 
         if not sw.errors_verify(0):
@@ -1895,6 +1905,8 @@
 
         self.assertTrue(sw.barrier(), "Barrier failed")
 
+        sw.settle()  # Allow switch to settle and generate any notifications
+
         # Check for expected error message
 
         if not sw.errors_verify(1, \
@@ -2012,6 +2024,8 @@
 
         result = True
 
+        sw.settle()  # Allow switch to settle and generate any notifications
+
         # Check for any error messages
 
         if not sw.errors_verify(0):
@@ -2141,6 +2155,8 @@
 
         result = True
 
+        sw.settle()  # Allow switch to settle and generate any notifications
+
         # Check for expected error message
 
         if not sw.errors_verify(1, \
@@ -2257,6 +2273,8 @@
 
         result = True
 
+        sw.settle()  # Allow switch to settle and generate any notifications
+
         # Check for any error messages
 
         if not sw.errors_verify(0):
@@ -2355,6 +2373,8 @@
 
         result = True
 
+        sw.settle()  # Allow switch to settle and generate any notifications
+
         # Check for any error messages
 
         if not sw.errors_verify(0):
@@ -2414,6 +2434,8 @@
         # Do barrier, to make sure all flows are in
         self.assertTrue(sw.barrier(), "Barrier failed")
 
+        sw.settle()  # Allow switch to settle and generate any notifications
+
         # Check for error message
 
         if not sw.errors_verify(0):
@@ -2509,6 +2531,8 @@
 
         result = True
 
+        sw.settle()  # Allow switch to settle and generate any notifications
+
         # Check for any error messages
 
         if not sw.errors_verify(0):
@@ -2600,6 +2624,8 @@
 
         result = True
 
+        sw.settle()  # Allow switch to settle and generate any notifications
+
         # Check for any error messages
 
         if not sw.errors_verify(0):
@@ -2621,6 +2647,8 @@
 
         self.assertTrue(sw.barrier(), "Barrier failed")
 
+        sw.settle()  # Allow switch to settle and generate any notifications
+
         # Check for any error messages
 
         if not sw.errors_verify(0):
@@ -2731,6 +2759,8 @@
 
         result = True
 
+        sw.settle()  # Allow switch to settle and generate any notifications
+
         # Check for any error messages
 
         if not sw.errors_verify(0):
@@ -2827,6 +2857,8 @@
 
         result = True
 
+        sw.settle()  # Allow switch to settle and generate any notifications
+
         # Check for any error messages
 
         if not sw.errors_verify(0):
@@ -2886,6 +2918,8 @@
         # Do barrier, to make sure all flows are in
         self.assertTrue(sw.barrier(), "Barrier failed")
 
+        sw.settle()  # Allow switch to settle and generate any notifications
+
         # Check for error message
 
         if not sw.errors_verify(0):
@@ -3006,6 +3040,8 @@
 
         result = True
 
+        sw.settle()  # Allow switch to settle and generate any notifications
+
         # Check for expected "removed" message
 
         if not sw.errors_verify(0):
diff --git a/tests/oft b/tests/oft
index ce6e4ce..81d378e 100755
--- a/tests/oft
+++ b/tests/oft
@@ -124,6 +124,7 @@
 import time
 import os
 import imp
+import random
 
 pydir = os.path.join(os.path.dirname(__file__), '..', 'src', 'python')
 if os.path.exists(os.path.join(pydir, 'oftest')):
@@ -185,6 +186,7 @@
     "fail_skipped"       : False,
     "default_timeout"    : 2,
     "minsize"            : 0,
+    "random_seed"        : None,
 }
 
 # Default test priority
@@ -281,6 +283,9 @@
     parser.add_option("--minsize", type="int", 
                       help="Minimum allowable packet size on the dataplane.", 
                       default=0)
+    parser.add_option("--random-seed", type="int",
+                      help="Random number generator seed",
+                      default=None)
 
     # Might need this if other parsers want command line
     # parser.allow_interspersed_args = False
@@ -593,6 +598,10 @@
           "sudo or as root."
     exit(1)
 
+if config["random_seed"] is not None:
+    logging.info("Random seed: %d" % config["random_seed"])
+    random.seed(config["random_seed"])
+
 
 if __name__ == "__main__":
     logging.info("*** TEST RUN START: " + time.asctime())