Merge "Reduce the sleep time when send Arping package     - Sleep 1 second will cause this test take too long time"
diff --git a/TestON/drivers/common/cli/onosclidriver.py b/TestON/drivers/common/cli/onosclidriver.py
index e1d298a..93026c2 100644
--- a/TestON/drivers/common/cli/onosclidriver.py
+++ b/TestON/drivers/common/cli/onosclidriver.py
@@ -2139,6 +2139,9 @@
             main.cleanup()
             main.exit()
 
+    def checkFlowCount(self, min=0, timeout=60 ):
+        count = int(self.getTotalFlowsNum( timeout=timeout ))
+        return count if (count > min) else False
 
     def checkFlowsState( self, isPENDING=True, timeout=60 ):
         """
@@ -2291,7 +2294,7 @@
 
                 return totalFlows
 
-            return totalFlows
+            return int(totalFlows)
 
         except TypeError:
             main.log.exception( self.name + ": Object not as expected" )
diff --git a/TestON/drivers/common/cli/onosdriver.py b/TestON/drivers/common/cli/onosdriver.py
index e0a1a6a..4f32aab 100644
--- a/TestON/drivers/common/cli/onosdriver.py
+++ b/TestON/drivers/common/cli/onosdriver.py
@@ -1609,6 +1609,30 @@
             main.cleanup()
             main.exit()
 
+    def dumpFlows(self,ONOSIp, destDir, filename="flows" ):
+        """
+        Dump Flow Tables to a desired directory.
+        For debugging purposes, you may want to use
+        this function to capture flows at a given point in time.
+        Localtime will be attached to the filename
+
+        Required:
+            * ONOSIp: the IP of the target ONOS instance
+            * destDir: specify directory to copy to.
+              ex ) /tmp/
+        Optional:
+            * fileName: Name of the file
+        """
+
+        localtime = time.strftime( '%x %X' )
+        localtime = localtime.replace( "/", "" )
+        localtime = localtime.replace( " ", "_" )
+        localtime = localtime.replace( ":", "" )
+        if destDir[ -1: ] != "/":
+            destDir += "/"
+        cmd="flows > "+ str( destDir ) + str( filename ) + localtime
+        return self.onosCli(ONOSIp,cmd)
+
     def cpLogsToDir( self, logToCopy,
                      destDir, copyFileName="" ):
         """
diff --git a/TestON/tests/FUNC/FUNCintent/FUNCintent.py b/TestON/tests/FUNC/FUNCintent/FUNCintent.py
index ceb4b2d..080aa8f 100644
--- a/TestON/tests/FUNC/FUNCintent/FUNCintent.py
+++ b/TestON/tests/FUNC/FUNCintent/FUNCintent.py
@@ -209,8 +209,9 @@
         onosIsUp = main.TRUE
 
         for i in range( main.numCtrls ):
-            onosIsUp = main.ONOSbench.isup( main.ONOSip[ i ] )
-            if onosIsUp == main.TRUE:
+            isUp = main.ONOSbench.isup( main.ONOSip[ i ] )
+            onosIsUp = onosIsUp and isUp
+            if isUp == main.TRUE:
                 main.log.report( "ONOS instance {0} is up and ready".format( i + 1 ) )
             else:
                 main.log.report( "ONOS instance {0} may not be up, stop and ".format( i + 1 ) +
diff --git a/TestON/tests/FUNC/FUNCintent/dependencies/FuncIntentFunction.py b/TestON/tests/FUNC/FUNCintent/dependencies/FuncIntentFunction.py
index dbafffa..a596a01 100644
--- a/TestON/tests/FUNC/FUNCintent/dependencies/FuncIntentFunction.py
+++ b/TestON/tests/FUNC/FUNCintent/dependencies/FuncIntentFunction.py
@@ -1015,7 +1015,7 @@
         testResult = main.FALSE
 
     # Check Connectivity
-    if utilities.retry( f=scapyCheckConnection, retValue=main.FALSE, args=( main, senderNames, recipientNames ) ):
+    if utilities.retry( f=scapyCheckConnection, retValue=main.FALSE, args=( main, senderNames, recipientNames ), attempts=3, sleep=5 ):
         main.assertReturnString += 'Initial Ping Passed\n'
     else:
         main.assertReturnString += 'Initial Ping Failed\n'
diff --git a/TestON/tests/FUNC/FUNCnetCfg/FUNCnetCfg.py b/TestON/tests/FUNC/FUNCnetCfg/FUNCnetCfg.py
index 34bc72b..2c3622b 100644
--- a/TestON/tests/FUNC/FUNCnetCfg/FUNCnetCfg.py
+++ b/TestON/tests/FUNC/FUNCnetCfg/FUNCnetCfg.py
@@ -194,19 +194,18 @@
         onosIsUp = main.TRUE
 
         for i in range( main.numCtrls ):
-            onosIsUp = onosIsUp and main.ONOSbench.isup( main.ONOSip[ i ] )
-        if onosIsUp == main.TRUE:
-            main.log.report( "ONOS instance is up and ready" )
-        else:
-            main.log.report( "ONOS instance may not be up, stop and " +
-                             "start ONOS again " )
-            for i in range( main.numCtrls ):
+            isUp = main.ONOSbench.isup( main.ONOSip[ i ] )
+            onosIsUp = onosIsUp and isUp
+            if isUp == main.TRUE:
+                main.log.report( "ONOS instance {0} is up and ready".format( i + 1 ) )
+            else:
+                main.log.report( "ONOS instance {0} may not be up, stop and ".format( i + 1 ) +
+                                 "start ONOS again " )
                 stopResult = stopResult and \
                         main.ONOSbench.onosStop( main.ONOSip[ i ] )
-            for i in range( main.numCtrls ):
                 startResult = startResult and \
                         main.ONOSbench.onosStart( main.ONOSip[ i ] )
-        stepResult = onosIsUp and stopResult and startResult
+            stepResult = onosIsUp and stopResult and startResult
         utilities.assert_equals( expect=main.TRUE,
                                  actual=stepResult,
                                  onpass="ONOS service is ready",
@@ -488,10 +487,13 @@
         allowedDevices = [ "of:{}".format( str( i ).zfill( 16 ) ) for i in [ 1, 2, 4 ] ]
         print allowedDevices
         onosDevices = []
-        for sw in json.loads( devices ):
-            onosDevices.append( str( sw['id'] ) )
-        onosDevices.sort()
-        print onosDevices
+        try:
+            for sw in json.loads( devices ):
+                onosDevices.append( str( sw['id'] ) )
+            onosDevices.sort()
+            print onosDevices
+        except( TypeError, ValueError ):
+            main.log.error( "Problem loading devices" )
         utilities.assert_equals( expect=allowedDevices,
                                  actual=onosDevices,
                                  onpass="Only allowed devices are in ONOS",
@@ -500,15 +502,19 @@
 
         main.step( "Check device annotations" )
         keys = [ 'name', 'owner', 'rackAddress' ]
-        for sw in json.loads( devices ):
-            if "of:0000000000000001" in sw['id']:
-                s1Correct = True
-                for k in keys:
-                    if str( sw.get( 'annotations', {} ).get( k ) ) != str( main.s1Json[k] ):
-                        s1Correct = False
-                        main.log.debug( "{} is wrong on s1".format( k ) )
-                if not s1Correct:
-                    main.log.error( "Annotations for s1 are incorrect: {}".format( sw ) )
+        try:
+            for sw in json.loads( devices ):
+                if "of:0000000000000001" in sw['id']:
+                    s1Correct = True
+                    for k in keys:
+                        if str( sw.get( 'annotations', {} ).get( k ) ) != str( main.s1Json[k] ):
+                            s1Correct = False
+                            main.log.debug( "{} is wrong on s1".format( k ) )
+                    if not s1Correct:
+                        main.log.error( "Annotations for s1 are incorrect: {}".format( sw ) )
+        except( TypeError, ValueError ):
+            main.log.error( "Problem loading devices" )
+            s1Correct = False
         try:
             stepResult = s1Correct
         except NameError:
@@ -611,12 +617,15 @@
         main.log.debug( main.ONOSrest1.pprint( devices ) )
         allowedDevices = [ "of:{}".format( str( i ).zfill( 16 ) ) for i in [ 1, 2 ] ]
         onosDevices = []
-        for sw in json.loads( devices ):
-            onosDevices.append( str( sw.get( 'id' ) ) )
-        onosDevices.sort()
-        failMsg = "ONOS devices doesn't match the list of allowed devices.\n"
-        failMsg += "Expected devices: {}\nActual devices: {}".format( allowedDevices,
-                                                                      onosDevices )
+        try:
+            for sw in json.loads( devices ):
+                onosDevices.append( str( sw.get( 'id' ) ) )
+            onosDevices.sort()
+            failMsg = "ONOS devices doesn't match the list of allowed devices.\n"
+            failMsg += "Expected devices: {}\nActual devices: {}".format( allowedDevices,
+                                                                          onosDevices )
+        except( TypeError, ValueError ):
+            main.log.error( "Problem loading devices" )
         utilities.assert_equals( expect=allowedDevices,
                                  actual=onosDevices,
                                  onpass="Only allowed devices are in ONOS",
@@ -624,23 +633,27 @@
 
         main.step( "Check device annotations" )
         keys = [ 'name', 'owner', 'rackAddress' ]
-        for sw in json.loads( devices ):
-            if "of:0000000000000001" in sw.get( 'id' ):
-                s1Correct = True
-                for k in keys:
-                    if str( sw.get( 'annotations', {} ).get( k ) ) != str( main.s1Json[k] ):
-                        s1Correct = False
-                        main.log.debug( "{} is wrong on s1".format( k ) )
-                if not s1Correct:
-                    main.log.error( "Annotations for s1 are incorrect: {}".format( sw ) )
-            elif "of:0000000000000002" in sw['id']:
-                s2Correct = True
-                for k in keys:
-                    if str( sw.get( 'annotations', {} ).get( k ) ) != str( main.s2Json[k] ):
-                        s2Correct = False
-                        main.log.debug( "{} is wrong on s2".format( k ) )
-                if not s2Correct:
-                    main.log.error( "Annotations for s2 are incorrect: {}".format( sw ) )
+        try:
+            for sw in json.loads( devices ):
+                if "of:0000000000000001" in sw.get( 'id' ):
+                    s1Correct = True
+                    for k in keys:
+                        if str( sw.get( 'annotations', {} ).get( k ) ) != str( main.s1Json[k] ):
+                            s1Correct = False
+                            main.log.debug( "{} is wrong on s1".format( k ) )
+                    if not s1Correct:
+                        main.log.error( "Annotations for s1 are incorrect: {}".format( sw ) )
+                elif "of:0000000000000002" in sw['id']:
+                    s2Correct = True
+                    for k in keys:
+                        if str( sw.get( 'annotations', {} ).get( k ) ) != str( main.s2Json[k] ):
+                            s2Correct = False
+                            main.log.debug( "{} is wrong on s2".format( k ) )
+                    if not s2Correct:
+                        main.log.error( "Annotations for s2 are incorrect: {}".format( sw ) )
+        except( TypeError, ValueError ):
+            main.log.error( "Problem loading devices" )
+            stepResult = False
         try:
             stepResult = s1Correct and s2Correct
         except NameError:
diff --git a/TestON/tests/FUNC/FUNCoptical/FUNCoptical.py b/TestON/tests/FUNC/FUNCoptical/FUNCoptical.py
index ab4d3d0..c41a740 100644
--- a/TestON/tests/FUNC/FUNCoptical/FUNCoptical.py
+++ b/TestON/tests/FUNC/FUNCoptical/FUNCoptical.py
@@ -203,24 +203,22 @@
         onosIsUp = main.TRUE
 
         for i in range( main.numCtrls ):
-            onosIsUp = onosIsUp and main.ONOSbench.isup( main.ONOSip[ i ] )
-        if onosIsUp == main.TRUE:
-            main.log.report( "ONOS instance is up and ready" )
-        else:
-            main.log.report( "ONOS instance may not be up, stop and " +
-                             "start ONOS again " )
-
-            for i in range( main.numCtrls ):
-                stopResult = stopResult and \
-                        main.ONOSbench.onosStop( main.ONOSip[ i ] )
-            for i in range( main.numCtrls ):
-                startResult = startResult and \
-                        main.ONOSbench.onosStart( main.ONOSip[ i ] )
+            isUp = main.ONOSbench.isup( main.ONOSip[ i ] )
+            onosIsUp = onosIsUp and isUp
+            if isUp == main.TRUE:
+                main.log.report( "ONOS instance {0} is up and ready".format( i + 1 ) )
+            else:
+                main.log.report( "ONOS instance {0} may not be up, stop and ".format( i + 1 ) +
+                                 "start ONOS again " )
+                stopResult = stopResult and main.ONOSbench.onosStop( main.ONOSip[ i ] )
+                startResult = startResult and main.ONOSbench.onosStart( main.ONOSip[ i ] )
+                if not startResult or stopResult:
+                    main.log.report( "ONOS instance {0} did not start correctly.".format( i + 1) )
         stepResult = onosIsUp and stopResult and startResult
         utilities.assert_equals( expect=main.TRUE,
                                  actual=stepResult,
-                                 onpass="ONOS service is ready",
-                                 onfail="ONOS service did not start properly" )
+                                 onpass="ONOS service is ready on all nodes",
+                                 onfail="ONOS service did not start properly on all nodes" )
 
         main.step( "Start ONOS cli" )
         cliResult = main.TRUE
@@ -311,7 +309,7 @@
         main.case( "Running Pingall" )
         main.caseExplanation = "Use pingall to discover all hosts. Pingall is expected to fail."
         main.step( "Discover Hosts through Pingall" )
-        pingResult = main.LincOE.pingall( timeout = 600 )
+        pingResult = main.LincOE.pingall( timeout = 120 )
 
         utilities.assert_equals( expect=main.FALSE,
                                  actual=pingResult,
diff --git a/TestON/tests/USECASE/USECASE_SegmentRouting/README.md b/TestON/tests/USECASE/USECASE_SegmentRouting/README.md
index da75079..8240068 100644
--- a/TestON/tests/USECASE/USECASE_SegmentRouting/README.md
+++ b/TestON/tests/USECASE/USECASE_SegmentRouting/README.md
@@ -1,18 +1,33 @@
-This test is designed to verify basic connectivity the SegmentRouting application.
+This test is designed to verify basic connectivity the SegmentRouting application via pingaall.
 
 It consists of 
 
-1) Installing and Starting ONOS
-2) Starting Mininet and testing connectivity
+1) Configure and Install ONOS
+2) Start Mininet and check flow state
+2) Test connectivity
 
 Requirements
 
- - A single ONOS instance is required for the test, the application is currently not stable in a cluster.
+ - A single ONOS instance is required for the test, the application is currently not stable in a cluster as of today.
  - An updated version of the CPQD switch has to be running to make sure it supports group chaining.
 
 Step 1:
-In this step we copy the proper config file to ONOS, next we package ONOS and install it in the target machine.
+In this step, we copy config file to ONOS, next we package ONOS and install it in the target machine.
 
 Step 2:
 
-In this step we start a 2x2 leaf-spine topology, connect to ONOS, and next we send several pings between hosts to test connectivity.
+In this step we start the topology, connect to ONOS
+
+Step:3
+
+Here, we send several pings between hosts to test connectivity.
+
+Then Steps are repeated for different configurations and topologies.
+
+    Configurations:
+     1) APPS=openflow-base,netcfghostprovider,netcfglinksprovider
+     2) APPS=openflow
+
+    Topologies:
+     1) 2x2 Leaf-Spine
+     2) 4x4 Leaf-Spine
diff --git a/TestON/tests/USECASE/USECASE_SegmentRouting/USECASE_SegmentRouting.params b/TestON/tests/USECASE/USECASE_SegmentRouting/USECASE_SegmentRouting.params
index eb55d5f..1ef9eea 100755
--- a/TestON/tests/USECASE/USECASE_SegmentRouting/USECASE_SegmentRouting.params
+++ b/TestON/tests/USECASE/USECASE_SegmentRouting/USECASE_SegmentRouting.params
@@ -1,6 +1,6 @@
 <PARAMS>
 
-    <testcases>1,2,11,9,2,11,9,2,11,9,2,11,9</testcases>
+    <testcases>1,[2,3,4,10]*4</testcases>
 
     <SCALE>
         <size>1</size>
diff --git a/TestON/tests/USECASE/USECASE_SegmentRouting/USECASE_SegmentRouting.py b/TestON/tests/USECASE/USECASE_SegmentRouting/USECASE_SegmentRouting.py
index 7eb4dd7..0057a10 100644
--- a/TestON/tests/USECASE/USECASE_SegmentRouting/USECASE_SegmentRouting.py
+++ b/TestON/tests/USECASE/USECASE_SegmentRouting/USECASE_SegmentRouting.py
@@ -127,7 +127,7 @@
         for i in range( main.numCtrls ):
             tempOnosIp.append( main.ONOSip[i] )
         onosUser = main.params[ 'ENV' ][ 'cellUser' ]
-        main.step("Creating cell file")
+        main.step("Create and Apply cell file")
         main.ONOSbench.createCellFile( main.ONOSbench.ip_address,
                                        "temp",
                                        main.Mininet1.ip_address,
@@ -135,7 +135,6 @@
                                        tempOnosIp,
                                        onosUser )
 
-        main.step( "Apply cell to environment" )
         cellResult = main.ONOSbench.setCell( "temp" )
         verifyResult = main.ONOSbench.verifyCell()
         stepResult = cellResult and verifyResult
@@ -145,7 +144,7 @@
                                         "environment",
                                  onfail="Failed to apply cell to environment " )
 
-        main.step( "Creating ONOS package" )
+        main.step( "Create and Install ONOS package" )
         main.jsonFile=main.json.pop(0)
         main.ONOSbench.handle.sendline( "cp "+main.path+"/"+main.jsonFile+".json ~/onos/tools/package/config/network-cfg.json")
         packageResult = main.ONOSbench.onosPackage()
@@ -155,9 +154,8 @@
         #                         onpass="Successfully created ONOS package",
         #                         onfail="Failed to create ONOS package" )
 
-        time.sleep( main.startUpSleep )
+        #time.sleep( main.startUpSleep )
 
-        main.step( "Installing ONOS package" )
         onosInstallResult = main.TRUE
         for i in range( main.numCtrls ):
             onosInstallResult = onosInstallResult and \
@@ -187,13 +185,38 @@
                 startResult = startResult and \
                         main.ONOSbench.onosStart( main.ONOSip[ i ] )
         stepResult = onosIsUp and stopResult and startResult
+
         utilities.assert_equals( expect=main.TRUE,
                                  actual=stepResult,
                                  onpass="ONOS service is ready",
                                  onfail="ONOS service did not start properly" )
-        time.sleep( 2*main.startUpSleep )
+        #time.sleep( 2*main.startUpSleep )
+        main.ONOSbench.handle.sendline( "onos-secure-ssh")
+        main.step( "Checking if ONOS CLI is ready" )
+        cliResult = main.CLIs[0].startOnosCli( main.ONOSip[ 0 ],
+                                           commandlineTimeout=100, onosStartTimeout=600 )
+        utilities.assert_equals( expect=main.TRUE,
+                             actual=cliResult,
+                             onpass="ONOS CLI is ready",
+                             onfail="ONOS CLI is not ready" )
+        for i in range( 10 ):
+            ready = True
+            output = main.CLIs[0].summary()
+            if not output:
+                ready = False
+            if ready:
+                break
+            time.sleep( 10 )
+        utilities.assert_equals( expect=True, actual=ready,
+                                 onpass="ONOS summary command succeded",
+                                 onfail="ONOS summary command failed" )
 
-    def CASE9( self, main ):
+        if not ready:
+            main.log.error( "ONOS startup failed!" )
+            main.cleanup()
+            main.exit()
+
+    def CASE10( self, main ):
         '''
             Report errors/warnings/exceptions
         '''
@@ -214,7 +237,7 @@
                                     "Except" ],
                                   "s" )
 
-    def CASE11( self, main ):
+    def CASE3( self, main ):
         """
             Start mininet
         """
@@ -240,13 +263,44 @@
         if not topoResult:
             main.cleanup()
             main.exit()
-        main.step("Waiting for switch initialization and configuration")
-        time.sleep( 3*main.startUpSleep)
+        #main.step("Waiting for switch initialization and configuration")
+        main.step(" Check whether the flow count is bigger than 80" )
+        count =  utilities.retry( main.CLIs[0].checkFlowCount,
+                                 main.FALSE,
+                                 kwargs={'min':80},
+                                 attempts=10 )
+        utilities.assertEquals( \
+            expect=True,
+            actual=(count>0),
+            onpass="Flow count looks correct: "+str(count),
+            onfail="Flow count looks wrong: "+str(count) )
+
+        main.step( "Check whether all flow status are ADDED" )
+        flowCheck = utilities.retry( main.CLIs[0].checkFlowsState,
+                                 main.FALSE,
+                                 kwargs={'isPENDING':False},
+                                 attempts=10 )
+        utilities.assertEquals( \
+            expect=main.TRUE,
+            actual=flowCheck,
+            onpass="Flow status is correct!",
+            onfail="Flow status is wrong!" )
+        main.ONOSbench.dumpFlows( main.ONOSip[0],
+                 main.logdir, "flows" + main.jsonFile)
+        #time.sleep( 3*main.startUpSleep)
+
+    def CASE4( self, main ):
+        main.case( "Check full connectivity" )
+        main.log.report( "Check full connectivity" )
+
+        main.step("Check full connectivity")
         pa = main.Mininet1.pingall()
         utilities.assert_equals( expect=main.TRUE, actual=pa,
                                  onpass="Full connectivity successfully tested",
                                  onfail="Full connectivity failed" )
         # cleanup mininet
+        main.ONOSbench.dumpFlows( main.ONOSip[0],
+                 main.logdir, "flows" + main.jsonFile)
         main.ONOSbench.onosStop( main.ONOSip[0] )
         main.Mininet1.stopNet()