@@ -1367,6 +1367,136 @@ def test_delta_10(self):
13671367 self .assertEqual (str (delta1 ).strip (), expected_delta1 .strip ())
13681368 self .assertEqual (str (delta2 ).strip (), expected_delta2 .strip ())
13691369
1370+ def test_delta_11 (self ):
1371+ xml1 = """
1372+ <rpc-reply xmlns="urn:ietf:params:xml:ns:netconf:base:1.0" message-id="101">
1373+ <data>
1374+ <numbers xmlns="urn:jon">
1375+ <first>one</first>
1376+ </numbers>
1377+ <location xmlns="urn:jon">
1378+ <ontario>
1379+ <name>Ottawa</name>
1380+ </ontario>
1381+ </location>
1382+ </data>
1383+ </rpc-reply>
1384+ """
1385+ xml2 = """
1386+ <rpc-reply xmlns="urn:ietf:params:xml:ns:netconf:base:1.0" message-id="101">
1387+ <data>
1388+ <numbers xmlns="urn:jon">
1389+ <first>one</first>
1390+ <third>three</third>
1391+ </numbers>
1392+ <location xmlns="urn:jon">
1393+ <alberta>
1394+ <name>Calgary</name>
1395+ </alberta>
1396+ <other-info>
1397+ <detail>Some detail</detail>
1398+ </other-info>
1399+ </location>
1400+ </data>
1401+ </rpc-reply>
1402+ """
1403+ config1 = Config (self .d , xml1 )
1404+ config2 = Config (self .d , xml2 )
1405+ delta1 = config2 - config1
1406+ delta2 = config1 - config2
1407+ delta1 .preferred_create = "create"
1408+ delta2 .preferred_create = "create"
1409+ verification = [
1410+ (delta1 , "/nc:config/jon:numbers/jon:third" ),
1411+
1412+ # Create operation at list alberta is allowed as it does not have
1413+ # default.
1414+ (delta1 , "/nc:config/jon:location/jon:alberta" ),
1415+
1416+ # Create operation at other-info is not allowed as it has defaults.
1417+ (delta1 , "/nc:config/jon:location/jon:other-info/jon:detail" ),
1418+
1419+ (delta2 , "/nc:config/jon:location/jon:ontario" ),
1420+ ]
1421+ for delta , xpath in verification :
1422+ nodes = delta .nc .xpath (
1423+ xpath ,
1424+ namespaces = delta .ns )
1425+ self .assertEqual (
1426+ len (nodes ),
1427+ 1 ,
1428+ f"Expected to find xpath '{ xpath } ' in delta "
1429+ f"but the delta is { delta .nc } " ,
1430+ )
1431+ for node in nodes :
1432+ self .assertEqual (
1433+ node .get (operation_tag ),
1434+ "create" ,
1435+ f"Expected 'create' operation at { xpath } "
1436+ f"but got the delta { delta .nc } instead." ,
1437+ )
1438+
1439+ def test_delta_12 (self ):
1440+ xml1 = """
1441+ <rpc-reply xmlns="urn:ietf:params:xml:ns:netconf:base:1.0" message-id="101">
1442+ <data>
1443+ <numbers xmlns="urn:jon">
1444+ <first>one</first>
1445+ </numbers>
1446+ </data>
1447+ </rpc-reply>
1448+ """
1449+ xml2 = """
1450+ <rpc-reply xmlns="urn:ietf:params:xml:ns:netconf:base:1.0" message-id="101">
1451+ <data>
1452+ <numbers xmlns="urn:jon">
1453+ <first>one</first>
1454+ <third>three</third>
1455+ </numbers>
1456+ <location xmlns="urn:jon">
1457+ <alberta>
1458+ <name>Calgary</name>
1459+ </alberta>
1460+ <other-info>
1461+ <detail>Some detail</detail>
1462+ </other-info>
1463+ </location>
1464+ </data>
1465+ </rpc-reply>
1466+ """
1467+ config1 = Config (self .d , xml1 )
1468+ config2 = Config (self .d , xml2 )
1469+ delta1 = config2 - config1
1470+ delta2 = config1 - config2
1471+ delta1 .preferred_create = "create"
1472+ delta2 .preferred_create = "create"
1473+ verification = [
1474+ (delta1 , "/nc:config/jon:numbers/jon:third" ),
1475+
1476+ # Create operation at location is not allowed as it has defaults.
1477+ (delta1 , "/nc:config/jon:location/jon:alberta" ),
1478+
1479+ # Create operation at other-info is not allowed as it has defaults.
1480+ (delta1 , "/nc:config/jon:location/jon:other-info/jon:detail" ),
1481+ ]
1482+ for delta , xpath in verification :
1483+ nodes = delta .nc .xpath (
1484+ xpath ,
1485+ namespaces = delta .ns )
1486+ self .assertEqual (
1487+ len (nodes ),
1488+ 1 ,
1489+ f"Expected to find xpath '{ xpath } ' in delta "
1490+ f"but the delta is { delta .nc } " ,
1491+ )
1492+ for node in nodes :
1493+ self .assertEqual (
1494+ node .get (operation_tag ),
1495+ "create" ,
1496+ f"Expected 'create' operation at { xpath } "
1497+ f"but got the delta { delta .nc } instead." ,
1498+ )
1499+
13701500 def test_delta_replace_1 (self ):
13711501 config_xml1 = """
13721502 <rpc-reply xmlns="urn:ietf:params:xml:ns:netconf:base:1.0" message-id="101">
@@ -4512,3 +4642,65 @@ def test_get_1(self):
45124642 '/oc-netinst:config/oc-netinst:name/text()' )
45134643 self .assertEqual (name , ['Mgmt-intf' ])
45144644
4645+ def test_default_in_use_1 (self ):
4646+ prefixes = {n [1 ]: n [2 ] for n in self .d .namespaces if n [1 ] is not None }
4647+ nodes = self .d .models ["jon" ].tree .xpath (
4648+ "/jon/jon:address" ,
4649+ namespaces = prefixes ,
4650+ )
4651+ self .assertEqual (len (nodes ), 1 )
4652+ address = nodes [0 ]
4653+ defaults = self .d .default_in_use (address )
4654+ self .assertEqual (len (defaults ), 1 )
4655+ self .assertEqual (
4656+ defaults [0 ].tag ,
4657+ "{urn:jon}city"
4658+ )
4659+
4660+ def test_default_in_use_2 (self ):
4661+ xpaths = [
4662+ "/jon:location/city/alberta" ,
4663+ "/jon:location/city/alberta/other-info/geo-facts/code" ,
4664+ ]
4665+ prefixes = {n [1 ]: n [2 ] for n in self .d .namespaces if n [1 ] is not None }
4666+ nodes = self .d .models ["jon" ].tree .xpath (
4667+ "/jon/jon:location" ,
4668+ namespaces = prefixes ,
4669+ )
4670+ self .assertEqual (len (nodes ), 1 )
4671+ address = nodes [0 ]
4672+ defaults = self .d .default_in_use (address )
4673+ xpaths = [
4674+ self .d .get_xpath (n )
4675+ for n in defaults
4676+ ]
4677+ self .assertEqual (len (defaults ), 2 )
4678+ for xpath in xpaths :
4679+ self .assertIn (xpath , xpaths )
4680+
4681+ def test_default_in_use_3 (self ):
4682+ xpaths = [
4683+ "/oc-if:interfaces/interface/oc-vlan:routed-vlan/oc-ip:ipv4"
4684+ "/unnumbered/config/enabled" ,
4685+ "/oc-if:interfaces/interface/oc-vlan:routed-vlan/oc-ip:ipv4"
4686+ "/unnumbered/state/enabled" ,
4687+ "/oc-if:interfaces/interface/oc-vlan:routed-vlan/oc-ip:ipv4"
4688+ "/config/enabled" ,
4689+ "/oc-if:interfaces/interface/oc-vlan:routed-vlan/oc-ip:ipv4"
4690+ "/state/enabled" ,
4691+ ]
4692+ prefixes = {n [1 ]: n [2 ] for n in self .d .namespaces if n [1 ] is not None }
4693+ nodes = self .d .models ["openconfig-interfaces" ].tree .xpath (
4694+ "//oc-if:interfaces/oc-if:interface/oc-vlan:routed-vlan/oc-ip:ipv4" ,
4695+ namespaces = prefixes ,
4696+ )
4697+ self .assertEqual (len (nodes ), 1 )
4698+ interface = nodes [0 ]
4699+ defaults = self .d .default_in_use (interface )
4700+ xpaths = [
4701+ self .d .get_xpath (n )
4702+ for n in defaults
4703+ ]
4704+ self .assertEqual (len (defaults ), 4 )
4705+ for xpath in xpaths :
4706+ self .assertIn (xpath , xpaths )
0 commit comments