Merge "add tests for partial failures of MPSP and SPMP intents"
diff --git a/TestON/drivers/common/cli/onosclidriver.py b/TestON/drivers/common/cli/onosclidriver.py
index 832fe29..3e94166 100644
--- a/TestON/drivers/common/cli/onosclidriver.py
+++ b/TestON/drivers/common/cli/onosclidriver.py
@@ -1402,7 +1402,8 @@
             setEthSrc="",
             setEthDst="",
             vlanId="",
-            setVlan="" ):
+            setVlan="",
+            partial=False ):
         """
         Note:
             This function assumes the format of all ingress devices
@@ -1470,6 +1471,8 @@
                 cmd += " -v " + str( vlanId )
             if setVlan:
                 cmd += " --setVlan " + str( setVlan )
+            if partial:
+                cmd += " --partial"
 
             # Check whether the user appended the port
             # or provided it as an input
@@ -1554,7 +1557,8 @@
             setEthSrc="",
             setEthDst="",
             vlanId="",
-            setVlan="" ):
+            setVlan="",
+            partial=False ):
         """
         Note:
             This function assumes the format of all egress devices
@@ -1622,6 +1626,8 @@
                 cmd += " -v " + str( vlanId )
             if setVlan:
                 cmd += " --setVlan " + str( setVlan )
+            if partial:
+                cmd += " --partial"
 
             # Check whether the user appended the port
             # or provided it as an input
@@ -2351,7 +2357,7 @@
         except ( TypeError, ValueError ):
             main.log.exception( "{}: Object not as expected: {!r}".format( self.name, rawFlows ) )
             return None
-        
+
         except AssertionError:
             main.log.exception( "" )
             return None
diff --git a/TestON/tests/FUNC/FUNCintent/FUNCintent.py b/TestON/tests/FUNC/FUNCintent/FUNCintent.py
index 7dc6fb3..9cd16a8 100644
--- a/TestON/tests/FUNC/FUNCintent/FUNCintent.py
+++ b/TestON/tests/FUNC/FUNCintent/FUNCintent.py
@@ -1931,6 +1931,9 @@
         """
         Tests Multi to Single Point Intent and Single to Multi Point Intent End Point Failure
         """
+        # At some later point discussion on this behavior in MPSP and SPMP intents
+        # will be reoppened and this test case may need to be updated to reflect
+        # the outcomes of that discussion
         if main.initialized == main.FALSE:
             main.log.error( "Test components did not start correctly, skipping further tests" )
             main.skipCase()
@@ -1955,10 +1958,9 @@
             main.initialized = main.FALSE
             main.skipCase()
         main.case( "Test Multi to Single End Point Failure" )
-        main.step( "Installing Multi to Single Point intents" )
-
-        main.assertReturnString = "Assertion results for IPV4 multi to single \
-                                  point intent end point failure with no options set\n"
+        main.step( "Installing Multi to Single Point intents with no options set" )
+        main.assertReturnString = "Assertion results for IPV4 multi to single " +\
+                                  "point intent end point failure with no options set\n"
         senders = [
             { "name":"h16", "device":"of:0000000000000006/8" },
             { "name":"h24", "device":"of:0000000000000007/8" }
@@ -2004,8 +2006,60 @@
                                  onpass=main.assertReturnString,
                                  onfail=main.assertReturnString )
 
+        main.step( "Installing Multi to Single Point intents with partial failure allowed" )
+
+        main.assertReturnString = "Assertion results for IPV4 multi to single " +\
+                                  "with partial failures allowed\n"
+        senders = [
+            { "name":"h16", "device":"of:0000000000000006/8" },
+            { "name":"h24", "device":"of:0000000000000007/8" }
+        ]
+        recipients = [
+            { "name":"h8", "device":"of:0000000000000005/8" }
+        ]
+        isolatedSenders = [
+            { "name":"h24"}
+        ]
+        isolatedRecipients = []
+        testResult = main.FALSE
+        installResult = main.FALSE
+        installResult = main.intentFunction.installMultiToSingleIntent(
+                                         main,
+                                         name="NOOPTION",
+                                         senders=senders,
+                                         recipients=recipients,
+                                         sw1="s5",
+                                         sw2="s2",
+                                         partial=True )
+
+        if installResult:
+            testResult = main.intentFunction.testEndPointFail(
+                                         main,
+                                         intentId=installResult,
+                                         name="NOOPTION",
+                                         senders=senders,
+                                         recipients=recipients,
+                                         isolatedSenders=isolatedSenders,
+                                         isolatedRecipients=isolatedRecipients,
+                                         sw1="s6",
+                                         sw2="s2",
+                                         sw3="s4",
+                                         sw4="s1",
+                                         sw5="s3",
+                                         expectedLink1=16,
+                                         expectedLink2=14,
+                                         partial=True )
+        else:
+            main.CLIs[ 0 ].removeAllIntents( purge=True )
+
+        utilities.assert_equals( expect=main.TRUE,
+                                 actual=testResult,
+                                 onpass=main.assertReturnString,
+                                 onfail=main.assertReturnString )
+
         main.step( "NOOPTION: Install and test single point to multi point intents" )
-        main.assertReturnString = "Assertion results for IPV4 single to multi point intent with no options set\n"
+        main.assertReturnString = "Assertion results for IPV4 single to multi " +\
+                                  "point intent with no options set\n"
         senders = [
             { "name":"h8", "device":"of:0000000000000005/8" }
         ]
@@ -2013,7 +2067,8 @@
             { "name":"h16", "device":"of:0000000000000006/8" },
             { "name":"h24", "device":"of:0000000000000007/8" }
         ]
-        isolatedSenders = [
+        isolatedSenders = []
+        isolatedRecipients = [
             { "name":"h24"}
         ]
         testResult = main.FALSE
@@ -2049,5 +2104,56 @@
                                  actual=testResult,
                                  onpass=main.assertReturnString,
                                  onfail=main.assertReturnString )
+        # Right now this functionality doesn't work properly in SPMP intents
+        main.step( "NOOPTION: Install and test single point to multi point " +\
+                   "intents with partial failures allowed" )
+        main.assertReturnString = "Assertion results for IPV4 single to multi " +\
+                                  "point intent with partial failures allowed\n"
+        senders = [
+            { "name":"h8", "device":"of:0000000000000005/8" }
+        ]
+        recipients = [
+            { "name":"h16", "device":"of:0000000000000006/8" },
+            { "name":"h24", "device":"of:0000000000000007/8" }
+        ]
+        isolatedSenders = []
+        isolatedRecipients = [
+            { "name":"h24"}
+        ]
+        testResult = main.FALSE
+        installResult = main.FALSE
+        installResult = main.intentFunction.installSingleToMultiIntent(
+                                         main,
+                                         name="NOOPTION",
+                                         senders=senders,
+                                         recipients=recipients,
+                                         sw1="s5",
+                                         sw2="s2",
+                                         partial=True)
+
+        if installResult:
+            testResult = main.intentFunction.testEndPointFail(
+                                         main,
+                                         intentId=installResult,
+                                         name="NOOPTION",
+                                         senders=senders,
+                                         recipients=recipients,
+                                         isolatedSenders=isolatedSenders,
+                                         isolatedRecipients=isolatedRecipients,
+                                         sw1="s6",
+                                         sw2="s2",
+                                         sw3="s4",
+                                         sw4="s1",
+                                         sw5="s3",
+                                         expectedLink1=16,
+                                         expectedLink2=14,
+                                         partial=True )
+        else:
+            main.CLIs[ 0 ].removeAllIntents( purge=True )
+
+        utilities.assert_equals( expect=main.TRUE,
+                                 actual=testResult,
+                                 onpass=main.assertReturnString,
+                                 onfail=main.assertReturnString )
 
         main.intentFunction.report( main )
\ No newline at end of file
diff --git a/TestON/tests/FUNC/FUNCintent/dependencies/FuncIntentFunction.py b/TestON/tests/FUNC/FUNCintent/dependencies/FuncIntentFunction.py
index c3104a5..1caa472 100644
--- a/TestON/tests/FUNC/FUNCintent/dependencies/FuncIntentFunction.py
+++ b/TestON/tests/FUNC/FUNCintent/dependencies/FuncIntentFunction.py
@@ -699,7 +699,8 @@
                                 tcp="",
                                 sw1="",
                                 sw2="",
-                                setVlan=""):
+                                setVlan="",
+                                partial=False ):
     """
     Installs a Single to Multi Point Intent
 
@@ -787,7 +788,8 @@
                                             tcpSrc="",
                                             tcpDst="",
                                             vlanId=vlanId,
-                                            setVlan=setVlan )
+                                            setVlan=setVlan,
+                                            partial=partial )
     except (KeyError, TypeError):
         errorMsg = "There was a problem loading the hosts data."
         if intentId:
@@ -815,7 +817,8 @@
                                 tcp="",
                                 sw1="",
                                 sw2="",
-                                setVlan=""):
+                                setVlan="",
+                                partial=False ):
     """
     Installs a Multi to Single Point Intent
 
@@ -902,7 +905,8 @@
                                             tcpSrc="",
                                             tcpDst="",
                                             vlanId=vlanId,
-                                            setVlan=setVlan )
+                                            setVlan=setVlan,
+                                            partial=partial )
     except (KeyError, TypeError):
         errorMsg = "There was a problem loading the hosts data."
         if intentId:
@@ -1162,7 +1166,8 @@
                       sw4="",
                       sw5="",
                       expectedLink1=0,
-                      expectedLink2=0 ):
+                      expectedLink2=0,
+                      partial=False ):
     """
     Test Single to Multipoint Topology for Endpoint failures
     """
@@ -1215,9 +1220,9 @@
 
     # Check flows count in each node
     if utilities.retry( f=checkFlowsCount, retValue=main.FALSE,
-                        args=[ main ] ) and utilities.retry( f=checkFlowsState,
-                                                             retValue=main.FALSE,
-                                                             args=[ main ] ):
+                        args=[ main ], attempts=5 ) and utilities.retry( f=checkFlowsState,
+                                                                         retValue=main.FALSE,
+                                                                         args=[ main ], attempts=5 ):
         main.assertReturnString += 'Initial Flow State Passed\n'
     else:
         main.assertReturnString += 'Intial Flow State Failed\n'
@@ -1285,55 +1290,107 @@
         main.assertReturnString += 'Isolation link Down Failed\n'
         testResult = main.FALSE
 
-    # Check intent state
-    if utilities.retry( f=checkIntentState, retValue=main.FALSE,
-                        args=( main, [ intentId ] ), sleep=main.checkIntentSleep ):
-        main.assertReturnString += 'Isolation link Down Intent State Passed\n'
-    else:
-        main.assertReturnString += 'Isolation link Down Intent State Failed\n'
-        testResult = main.FALSE
+    if partial:
+        # Check intent state
+        if utilities.retry( f=checkIntentState, retValue=main.FALSE,
+                            args=( main, [ intentId ] ), sleep=main.checkIntentSleep ):
+            main.assertReturnString += 'Partial failure isolation link Down Intent State Passed\n'
+        else:
+            main.assertReturnString += 'Partial failure isolation link Down Intent State Failed\n'
+            testResult = main.FALSE
 
-    # Check flows count in each node
-    if utilities.retry( f=checkFlowsCount, retValue=main.FALSE,
-                        args=[ main ] ) and utilities.retry( f=checkFlowsState,
-                                                             retValue=main.FALSE, args=[ main ] ):
-        main.assertReturnString += 'Isolation link Down Flow State Passed\n'
-    else:
-        main.assertReturnString += 'Isolation link Down Flow State Failed\n'
-        testResult = main.FALSE
+        # Check flows count in each node
+        if utilities.retry( f=checkFlowsCount, retValue=main.FALSE,
+                            args=[ main ], attempts=5 ) and utilities.retry( f=checkFlowsState,
+                                                                             retValue=main.FALSE,
+                                                                             args=[ main ], attempts=5 ):
+            main.assertReturnString += 'Partial failure isolation link Down Flow State Passed\n'
+        else:
+            main.assertReturnString += 'Partial failure isolation link Down Flow State Failed\n'
+            testResult = main.FALSE
 
-    # Check OnosTopology
-    if utilities.retry( f=checkTopology, retValue=main.FALSE, args=( main, expectedLink2 ) ):
-        main.assertReturnString += 'Isolation link Down Topology State Passed\n'
-    else:
-        main.assertReturnString += 'Isolation link Down Topology State Failed\n'
-        testResult = main.FALSE
+        # Check OnosTopology
+        if utilities.retry( f=checkTopology, retValue=main.FALSE, args=( main, expectedLink2 ) ):
+            main.assertReturnString += 'Partial failure isolation link Down Topology State Passed\n'
+        else:
+            main.assertReturnString += 'Partial failure isolation link Down Topology State Failed\n'
+            testResult = main.FALSE
 
-    # Check Connectivity
-    # First check connectivity of any isolated senders to recipients
-    if isolatedSenderNames:
-        if scapyCheckConnection( main, isolatedSenderNames, recipientNames, None, None, None, None, main.TRUE ):
+        # Check Connectivity
+        # First check connectivity of any isolated senders to recipients
+        if isolatedSenderNames:
+            if scapyCheckConnection( main, isolatedSenderNames, recipientNames, None, None, None, None, main.TRUE ):
+                main.assertReturnString += 'Partial failure isolation link Down Connectivity Check Passed\n'
+            else:
+                main.assertReturnString += 'Partial failure isolation link Down Connectivity Check Failed\n'
+                testResult = main.FALSE
+
+        # Next check connectivity of senders to any isolated recipients
+        if isolatedRecipientNames:
+            if scapyCheckConnection( main, senderNames, isolatedRecipientNames, None, None, None, None, main.TRUE ):
+                main.assertReturnString += 'Partial failure isolation link Down Connectivity Check Passed\n'
+            else:
+                main.assertReturnString += 'Partial failure isolation link Down Connectivity Check Failed\n'
+                testResult = main.FALSE
+
+        # Next check connectivity of connected senders and recipients
+        if utilities.retry( f=scapyCheckConnection, retValue=main.FALSE,
+                            args=( main, connectedSenderNames , connectedRecipientNames ) ):
+            main.assertReturnString += 'Partial failure isolation link Down Connectivity Check Passed\n'
+        else:
+            main.assertReturnString += 'Partial failure isolation link Down Connectivity Check Failed\n'
+            testResult = main.FALSE
+    else:
+        # Check intent state
+        if not utilities.retry( f=checkIntentState, retValue=main.TRUE,
+                            args=( main, [ intentId ] ), sleep=main.checkIntentSleep ):
+            main.assertReturnString += 'Isolation link Down Intent State Passed\n'
+        else:
+            main.assertReturnString += 'Isolation link Down Intent State Failed\n'
+            testResult = main.FALSE
+
+        # Check flows count in each node
+        if utilities.retry( f=checkFlowsCount, retValue=main.FALSE,
+                            args=[ main ], attempts=5 ) and utilities.retry( f=checkFlowsState,
+                                                                             retValue=main.FALSE,
+                                                                             args=[ main ], attempts=5 ):
+            main.assertReturnString += 'Isolation link Down Flow State Passed\n'
+        else:
+            main.assertReturnString += 'Isolation link Down Flow State Failed\n'
+            testResult = main.FALSE
+
+        # Check OnosTopology
+        if utilities.retry( f=checkTopology, retValue=main.FALSE, args=( main, expectedLink2 ) ):
+            main.assertReturnString += 'Isolation link Down Topology State Passed\n'
+        else:
+            main.assertReturnString += 'Isolation link Down Topology State Failed\n'
+            testResult = main.FALSE
+
+        # Check Connectivity
+        # First check connectivity of any isolated senders to recipients
+        if isolatedSenderNames:
+            if scapyCheckConnection( main, isolatedSenderNames, recipientNames, None, None, None, None, main.TRUE ):
+                main.assertReturnString += 'Isolation link Down Connectivity Check Passed\n'
+            else:
+                main.assertReturnString += 'Isolation link Down Connectivity Check Failed\n'
+                testResult = main.FALSE
+
+        # Next check connectivity of senders to any isolated recipients
+        if isolatedRecipientNames:
+            if scapyCheckConnection( main, senderNames, isolatedRecipientNames, None, None, None, None, main.TRUE ):
+                main.assertReturnString += 'Isolation link Down Connectivity Check Passed\n'
+            else:
+                main.assertReturnString += 'Isolation link Down Connectivity Check Failed\n'
+                testResult = main.FALSE
+
+        # Next check connectivity of connected senders and recipients
+        if utilities.retry( f=scapyCheckConnection, retValue=main.TRUE,
+                            args=( main, connectedSenderNames , connectedRecipientNames, None, None, None, None, main.TRUE ) ):
             main.assertReturnString += 'Isolation link Down Connectivity Check Passed\n'
         else:
             main.assertReturnString += 'Isolation link Down Connectivity Check Failed\n'
             testResult = main.FALSE
 
-    # Next check connectivity of senders to any isolated recipients
-    if isolatedRecipientNames:
-        if scapyCheckConnection( main, senderNames, isolatedRecipientNames, None, None, None, None, main.TRUE ):
-            main.assertReturnString += 'Isolation link Down Connectivity Check Passed\n'
-        else:
-            main.assertReturnString += 'Isolation link Down Connectivity Check Failed\n'
-            testResult = main.FALSE
-
-    # Next check connectivity of connected senders and recipients
-    if utilities.retry( f=scapyCheckConnection, retValue=main.FALSE,
-                        args=( main, connectedSenderNames , connectedRecipientNames ) ):
-        main.assertReturnString += 'Isolation link Down Connectivity Check Passed\n'
-    else:
-        main.assertReturnString += 'Isolation link Down Connectivity Check Failed\n'
-        testResult = main.FALSE
-
     # Bring the links back up
     # Bring first link up
     if utilities.retry( f=link, retValue=main.FALSE, args=( main, sw1, sw2, "up" ) ):
@@ -1369,8 +1426,9 @@
 
     # Check flows count in each node
     if utilities.retry( f=checkFlowsCount, retValue=main.FALSE,
-                        args=[ main ] ) and utilities.retry( f=checkFlowsState,
-                                                             retValue=main.FALSE, args=[ main ] ):
+                        args=[ main ], sleep=5, attempts=5 ) and utilities.retry( f=checkFlowsState,
+                                                                         retValue=main.FALSE,
+                                                                         args=[ main ], sleep=5, attempts=5 ):
         main.assertReturnString += 'Link Up Flow State Passed\n'
     else:
         main.assertReturnString += 'Link Up Flow State Failed\n'