def test_update_generated_objects_errors(stc):
    ctor = CScriptableCreator()
    stc_sys = CStcSystem.Instance()
    plLogger = PLLogger.GetLogger("test_update_generated_objects")
    plLogger.LogInfo("start")
    project = stc_sys.GetObject("Project")
    template = ctor.Create("StmTemplateConfig", project)
    dev = ctor.Create("EmulatedDevice", project)

    # No ProtocolConfig
    template.AddObject(dev, RelationType("GeneratedObject"))
    res = AllocCmd.update_generated_objects(template, 13)
    assert "Could not find a parent ProtocolConfig for" in res
    template.RemoveObject(dev, RelationType("GeneratedObject"))

    # No NetworkBlocks
    bgp = ctor.Create("BgpRouterConfig", dev)
    bgp_auth_params = bgp.GetObject("BgpAuthenticationParams")
    assert bgp_auth_params
    template.AddObject(bgp_auth_params, RelationType("GeneratedObject"))
    res = AllocCmd.update_generated_objects(template, 13)
    assert res == "Could not find any NetworkBlocks to update route counts on."
    template.RemoveObject(bgp_auth_params, RelationType("GeneratedObject"))

    # Not enough route count
    v4_route_config = ctor.Create("BgpIpv4RouteConfig", bgp)
    v6_route_config = ctor.Create("BgpIpv6RouteConfig", bgp)
    template.AddObject(v4_route_config, RelationType("GeneratedObject"))
    template.AddObject(v6_route_config, RelationType("GeneratedObject"))
    res = AllocCmd.update_generated_objects(template, 1)
    assert "Could not distribute at least one route to each block" \
        in res
def test_run_applied_value_static_only(stc):
    ctor = CScriptableCreator()
    stc_sys = CStcSystem.Instance()
    sequencer = stc_sys.GetObject("Sequencer")
    project = stc_sys.GetObject("Project")

    tags = project.GetObject("Tags")
    assert tags
    tag = ctor.Create("Tag", tags)
    tag.Set("Name", "UnitTestTag")

    # Create the StmTemplateMix
    mix_obj = ctor.Create("StmTemplateMix", project)

    # Create the StmTemplateConfigs
    tmpl1 = ctor.Create("StmTemplateConfig", mix_obj)
    tmpl2 = ctor.Create("StmTemplateConfig", mix_obj)
    tmpl3 = ctor.Create("StmTemplateConfig", mix_obj)
    assert tmpl1
    assert tmpl2
    assert tmpl3

    cmd = ctor.Create(PKG + ".AllocateRouteMixCountCommand", sequencer)

    gtc_p = patch(PKG + ".AllocateRouteMixCountCommand.get_this_cmd",
                  new=MagicMock(return_value=cmd))
    gtc_p.start()

    # Function signature
    # run(RouteMixList, RouteMixTagList, RouteCount)

    # Build the MixInfo
    comp_dict1 = {}
    comp_dict1["baseTemplateFile"] = "AllRouters.xml"
    comp_dict1["weight"] = "20"
    comp_dict2 = {}
    comp_dict2["baseTemplateFile"] = "AllRouters.xml"
    comp_dict2["weight"] = "50"
    comp_dict3 = {}
    comp_dict3["baseTemplateFile"] = "AllRouters.xml"
    comp_dict3["weight"] = "30"

    mix_info = {}
    mix_info["routeCount"] = 1
    mix_info["components"] = [comp_dict1, comp_dict2, comp_dict3]

    mix_obj.Set("MixInfo", json.dumps(mix_info))
    ret = AllocCmd.run([mix_obj.GetObjectHandle()], "", 1000)
    assert ret

    # Check the appliedValue
    mix_info = json.loads(mix_obj.Get("MixInfo"))
    comp_list = mix_info["components"]
    assert len(comp_list) == 3

    assert comp_list[0].get("appliedValue", 0) == 20
    assert comp_list[1].get("appliedValue", 0) == 50
    assert comp_list[2].get("appliedValue", 0) == 30

    gtc_p.stop()
def test_run_fail_validate_mix_object(stc):
    ctor = CScriptableCreator()
    stc_sys = CStcSystem.Instance()
    sequencer = stc_sys.GetObject("Sequencer")
    project = stc_sys.GetObject("Project")

    tags = project.GetObject("Tags")
    assert tags
    tag = ctor.Create("Tag", tags)
    tag.Set("Name", "UnitTestTag")

    cmd = ctor.Create(PKG + ".AllocateRouteMixCountCommand", sequencer)

    gtc_p = patch(PKG + ".AllocateRouteMixCountCommand.get_this_cmd",
                  new=MagicMock(return_value=cmd))
    gtc_p.start()

    # Function signature
    # run(RouteMixList, RouteMixTagList, RouteCount)

    # No mix objects specified
    ret = AllocCmd.run(None, "", 100)
    assert not ret
    assert "Neither RouteMixList nor RouteMixTagList specified a" \
        in cmd.Get("Status")

    # Invalid tag name (no Tag object)
    ret = AllocCmd.run(None, "InvalidTagName", 100)
    assert not ret
    assert "Neither RouteMixList nor RouteMixTagList specified a" \
        in cmd.Get("Status")

    # Empty tag (valid tag that doesn't tag anything)
    ret = AllocCmd.run(None, "UnitTestTag", 100)
    assert not ret
    assert "Neither RouteMixList nor RouteMixTagList specified a" \
        in cmd.Get("Status")

    gtc_p.stop()
def test_run_fail_validate_json_weights_and_counts(stc):
    ctor = CScriptableCreator()
    stc_sys = CStcSystem.Instance()
    sequencer = stc_sys.GetObject("Sequencer")
    project = stc_sys.GetObject("Project")

    tags = project.GetObject("Tags")
    assert tags
    tag = ctor.Create("Tag", tags)
    tag.Set("Name", "UnitTestTag")

    # Create the StmTemplateMix
    mix_obj = ctor.Create("StmTemplateMix", project)

    # Add the StmTemplateConfigs
    tmpl1 = ctor.Create("StmTemplateConfig", mix_obj)
    tmpl2 = ctor.Create("StmTemplateConfig", mix_obj)
    assert tmpl1
    assert tmpl2

    cmd = ctor.Create(PKG + ".AllocateRouteMixCountCommand", sequencer)

    gtc_p = patch(PKG + ".AllocateRouteMixCountCommand.get_this_cmd",
                  new=MagicMock(return_value=cmd))
    gtc_p.start()

    # Function signature
    # run(RouteMixList, RouteMixTagList, RouteCount)

    # Invalid RouteCount
    ret = AllocCmd.run([mix_obj.GetObjectHandle()], "", 0)
    assert not ret
    assert cmd.Get("Status") == "RouteCount must be at least 1."

    # Invalid number of components
    mix_info = {}
    mix_info["routeCuont"] = 1
    mix_info["components"] = []
    mix_obj.Set("MixInfo", json.dumps(mix_info))
    ret = AllocCmd.run([mix_obj.GetObjectHandle()], "", 100)
    assert not ret
    assert "but 0 components in the MixInfo.  These MUST match." \
        in cmd.Get("Status")

    # Invalid MixInfo JSON
    # mix_obj.Set("MixInfo", json.dumps({"invalid_json": "value"}))
    # ret = AllocCmd.run([mix_obj.GetObjectHandle()], "", 100)
    # assert not ret
    # assert cmd.Get("Status") == "Something...fill in when known")

    # Build the MixInfo
    comp_dict1 = {}
    comp_dict1["baseTemplateFile"] = "AllRouters.xml"
    comp_dict1["weight"] = "5"

    comp_dict2 = {}
    comp_dict2["baseTemplateFile"] = "AllRouters.xml"
    comp_dict2["weight"] = "5"

    mix_info = {}
    mix_info["routeCount"] = 100
    mix_info["components"] = [comp_dict1, comp_dict2]

    # Check error when total static count > total route count
    comp_dict1["weight"] = "500"
    comp_dict2["weight"] = "501"
    mix_obj.Set("MixInfo", json.dumps(mix_info))
    ret = AllocCmd.run([mix_obj.GetObjectHandle()], "", 1000)
    assert not ret
    assert "Sum total of the static counts (1001) exceeds the total" \
        in cmd.Get("Status")

    # Check error when total percent > 100%
    comp_dict1["weight"] = "50%"
    comp_dict2["weight"] = "51%"
    mix_obj.Set("MixInfo", json.dumps(mix_info))
    ret = AllocCmd.run([mix_obj.GetObjectHandle()], "", 1000)
    assert not ret
    assert "Sum total of the weights defined as percentages (101.0%) exceeds" \
        in cmd.Get("Status")

    # Check error when static count uses up all of the RouteCount
    # and there still are components that are defined by percent
    comp_dict1["weight"] = "23"
    comp_dict2["weight"] = "1%"
    mix_obj.Set("MixInfo", json.dumps(mix_info))
    ret = AllocCmd.run([mix_obj.GetObjectHandle()], "", 23)
    assert not ret
    assert "Not enough total RouteCount to distribute routes to all " \
        in cmd.Get("Status")
    assert "The required total static route count will use up all of the " \
        in cmd.Get("Status")

    # Check error when not enough routes for each component using
    # percent-based weighting to receive at least one route
    comp_dict1["weight"] = "50%"
    comp_dict1["weight"] = "50%"
    mix_obj.Set("MixInfo", json.dumps(mix_info))
    ret = AllocCmd.run([mix_obj.GetObjectHandle()], "", 1)
    assert not ret
    assert "Not enough total RouteCount to distribute routes to all " \
        in cmd.Get("Status")
    assert "there aren't enough routes left (1) such that each " + \
        "percent-based mix component will get at least one route." \
        in cmd.Get("Status")

    gtc_p.stop()
def test_update_generated_objects(stc):
    ctor = CScriptableCreator()
    stc_sys = CStcSystem.Instance()
    plLogger = PLLogger.GetLogger("test_update_generated_objects")
    plLogger.LogInfo("start")
    project = stc_sys.GetObject("Project")
    template = ctor.Create("StmTemplateConfig", project)

    # Single NetworkBlock
    dev = ctor.Create("EmulatedDevice", project)
    bgp = ctor.Create("BgpRouterConfig", dev)
    v4_route_config = ctor.Create("BgpIpv4RouteConfig", bgp)
    template.AddObject(v4_route_config, RelationType("GeneratedObject"))
    net_block = v4_route_config.GetObject("NetworkBlock")
    assert net_block
    assert net_block.Get("NetworkCount") == 1
    res = AllocCmd.update_generated_objects(template, 123)
    assert res == ""
    assert net_block.Get("NetworkCount") == 123

    # Multiple NetworkBlocks
    v6_route_config = ctor.Create("BgpIpv6RouteConfig", bgp)
    template.AddObject(v6_route_config, RelationType("GeneratedObject"))
    v6_net_block = v6_route_config.GetObject("NetworkBlock")
    assert v6_net_block
    assert v6_net_block.Get("NetworkCount") == 1
    res = AllocCmd.update_generated_objects(template, 123)
    assert res == ""
    assert net_block.Get("NetworkCount") == 62
    assert v6_net_block.Get("NetworkCount") == 61

    # Duplicate object type
    v6_route_config2 = ctor.Create("BgpIpv6RouteConfig", bgp)
    template.AddObject(v6_route_config2, RelationType("GeneratedObject"))
    v6_net_block2 = v6_route_config2.GetObject("NetworkBlock")
    assert v6_net_block2
    assert v6_net_block2.Get("NetworkCount") == 1
    res = AllocCmd.update_generated_objects(template, 125)
    assert res == ""
    assert net_block.Get("NetworkCount") == 42
    assert v6_net_block.Get("NetworkCount") == 42
    assert v6_net_block2.Get("NetworkCount") == 41

    # Different protocol type (ISIS)
    dev2 = ctor.Create("EmulatedDevice", project)
    isis = ctor.Create("IsisRouterConfig", dev2)
    lsp = ctor.Create("IsisLspConfig", isis)
    isis_v4_route_config = ctor.Create("Ipv4IsisRoutesConfig", lsp)
    template.AddObject(lsp, RelationType("GeneratedObject"))
    isis_v4_net_block = isis_v4_route_config.GetObject("NetworkBlock")
    assert isis_v4_net_block
    assert isis_v4_net_block.Get("NetworkCount") == 1
    res = AllocCmd.update_generated_objects(template, 200)
    assert res == ""
    assert net_block.Get("NetworkCount") == 67
    assert v6_net_block.Get("NetworkCount") == 67
    assert v6_net_block2.Get("NetworkCount") == 66
    assert isis_v4_net_block.Get("NetworkCount") == 200

    # Different protocol types on multiple objects
    bgp2 = ctor.Create("BgpRouterConfig", dev2)
    v6_route_config3 = ctor.Create("BgpIpv6RouteConfig", bgp2)
    v6_net_block3 = v6_route_config3.GetObject("NetworkBlock")
    assert v6_net_block3
    assert v6_net_block3.Get("NetworkCount") == 1
    template.AddObject(v6_route_config3, RelationType("GeneratedObject"))
    res = AllocCmd.update_generated_objects(template, 300)
    assert res == ""
    assert net_block.Get("NetworkCount") == 100
    assert v6_net_block.Get("NetworkCount") == 100
    assert v6_net_block2.Get("NetworkCount") == 100
    assert isis_v4_net_block.Get("NetworkCount") == 150
    assert v6_net_block3.Get("NetworkCount") == 150
def test_get_all_network_blocks(stc):
    ctor = CScriptableCreator()
    stc_sys = CStcSystem.Instance()
    plLogger = PLLogger.GetLogger("test_get_all_network_blocks")
    plLogger.LogInfo("start")
    project = stc_sys.GetObject("Project")

    dev = ctor.Create("EmulatedDevice", project)
    bgp = ctor.Create("BgpRouterConfig", dev)

    # No NetworkBlocks
    net_block_list = []
    AllocCmd.get_all_network_blocks(dev, net_block_list)
    assert len(net_block_list) == 0
    net_block_list = []
    AllocCmd.get_all_network_blocks(project, net_block_list)
    assert len(net_block_list) == 0

    # Add a NetworkBlock (IPv4)
    v4_route_config = ctor.Create("BgpIpv4RouteConfig", bgp)
    net_block_list = []
    AllocCmd.get_all_network_blocks(dev, net_block_list)
    assert len(net_block_list) == 1
    net_block_list = []
    AllocCmd.get_all_network_blocks(v4_route_config, net_block_list)
    assert len(net_block_list) == 1
    net_block_list = []
    bgpv4_net_block = v4_route_config.GetObject("NetworkBlock")
    AllocCmd.get_all_network_blocks(bgpv4_net_block, net_block_list)
    assert len(net_block_list) == 1

    # Add another NetworkBlock (IPv6)
    v6_route_config = ctor.Create("BgpIpv6RouteConfig", bgp)
    net_block_list = []
    AllocCmd.get_all_network_blocks(dev, net_block_list)
    assert len(net_block_list) == 2
    net_block_list = []
    AllocCmd.get_all_network_blocks(bgp, net_block_list)
    assert len(net_block_list) == 2
    net_block_list = []
    AllocCmd.get_all_network_blocks(v6_route_config, net_block_list)
    assert len(net_block_list) == 1

    # Add another router (ISIS)
    dev2 = ctor.Create("EmulatedDevice", project)
    isis = ctor.Create("IsisRouterConfig", dev2)
    lsp = ctor.Create("IsisLspConfig", isis)
    isis_v4_route_config = ctor.Create("Ipv4IsisRoutesConfig", lsp)
    assert isis_v4_route_config
    net_block_list = []
    AllocCmd.get_all_network_blocks(isis, net_block_list)
    assert len(net_block_list) == 1
    net_block_list = []
    AllocCmd.get_all_network_blocks(project, net_block_list)
    assert len(net_block_list) == 3