From bdfd1616de36aec8af8d3b91962da9319c255bf0 Mon Sep 17 00:00:00 2001 From: Jakub Witczak Date: Sat, 14 Oct 2023 20:18:32 +0200 Subject: [PATCH 1/2] public_key: pubkey_policy_tree_SUITE and tree visualization --- lib/public_key/test/Makefile | 3 +- .../test/pubkey_policy_tree_SUITE.erl | 350 ++++++++++++++++++ 2 files changed, 352 insertions(+), 1 deletion(-) create mode 100644 lib/public_key/test/pubkey_policy_tree_SUITE.erl diff --git a/lib/public_key/test/Makefile b/lib/public_key/test/Makefile index 57879c20e667..239e078193fe 100644 --- a/lib/public_key/test/Makefile +++ b/lib/public_key/test/Makefile @@ -33,7 +33,8 @@ MODULES= \ public_key_SUITE \ pbe_SUITE \ pkits_SUITE \ - pubkey_cert_SUITE + pubkey_cert_SUITE \ + pubkey_policy_tree_SUITE ERL_FILES= $(MODULES:%=%.erl) diff --git a/lib/public_key/test/pubkey_policy_tree_SUITE.erl b/lib/public_key/test/pubkey_policy_tree_SUITE.erl new file mode 100644 index 000000000000..0e4004baf83a --- /dev/null +++ b/lib/public_key/test/pubkey_policy_tree_SUITE.erl @@ -0,0 +1,350 @@ +-module(pubkey_policy_tree_SUITE). +-compile([export_all, nowarn_export_all]). + +-include_lib("stdlib/include/assert.hrl"). + +-define(PRE_SCRIPT, "
~n").
+-define(POST_SCRIPT, "~n
"). + +%% -define(DEBUG, true). + +-ifdef(DEBUG). +-define(FWR(Fmt, Args), + begin + io:fwrite(user, "dbg: " ++ Fmt, Args) + end). +-else. +-define(FWR(Fmt, Args), ok). +-endif. + +-define(PAL_MMD(MMD), + begin + %% ?FWR("~s~n", [MMD]), + ct:log(MMD), + ?FWR("~n", []) + end). +-define(ANY_POLICY_OID, {2,5,29,32,0}). +-define(ROOT_TN, pubkey_policy_tree:root()). +-define(EMPTY_VPT, {}). +-define(ROOT_PN, + begin + {AnyPolicyNode, _} = ?ROOT_TN, + AnyPolicyNode + %% ?PN(?ANY_POLICY_OID) + end). +-define(PN(VP), pubkey_policy_tree:policy_node(VP, [], [])). +-define(PN(VP, EPS), pubkey_policy_tree:policy_node(VP, [], EPS)). + +%% Note: trees used for testing below might not make much sense from +%% RFC5280 perspective and can be improved for sure; but can be good +%% enough for checking some general tree handling code + +all() -> [add_leaves, + add_leaf_siblings, + all_leaves, + prune_leaves, + prune_tree_and_leaves, + constrained_policy_node_set, + valid_policy_node_set, + any_leaves, + prune_tree_shorter_branch, + prune_invalid_nodes]. + +any_leaves(_Config) -> + AL = + fun(Tree) -> + pubkey_policy_tree:any_leaves(Tree) + end, + ?assertEqual([], AL(?EMPTY_VPT)), + TreeWithAnyPolicyLeaf = {?ROOT_PN, + [{?PN("GOLD"), + [?PN(?ANY_POLICY_OID)]}]}, + log_tree_diagram("TreeWithAnyPolicyLeaf", TreeWithAnyPolicyLeaf), + ?assertEqual([?PN(?ANY_POLICY_OID)], AL(TreeWithAnyPolicyLeaf)), + TreeWithAnyPolicyNode1 = {?ROOT_PN, + [{?PN(?ANY_POLICY_OID), + [?PN("GOLD")]}, + {?PN("SILVER", ["A"]), + [?PN("SILVER", ["B"])]}]}, + log_tree_diagram("TreeWithAnyPolicyNode1", TreeWithAnyPolicyNode1), + ?assertEqual([], AL(TreeWithAnyPolicyNode1)), + ok. + +constrained_policy_node_set(_Config) -> + TreeWithAnyPolicyLeaf = {?ROOT_PN, + [{?PN("GOLD"), + [?PN(?ANY_POLICY_OID)]}]}, + TreeWithAnyPolicyNode1 = {?ROOT_PN, + [{?PN(?ANY_POLICY_OID), + [?PN("GOLD")]}, + {?PN("SILVER", ["A"]), + [?PN("SILVER", ["B"])]}]}, + TreeWithAnyPolicyNode2 = {?ROOT_PN, + [{?PN(?ANY_POLICY_OID), + [{?PN("GOLD", ["GOLD", "SILVER"]), + [?PN("SILVER")]}]}]}, + CS = + fun(Tree) -> + pubkey_policy_tree:constrained_policy_node_set(Tree) + end, + ?assertEqual([], CS(?EMPTY_VPT)), + ?assertEqual([?PN(?ANY_POLICY_OID)], CS(TreeWithAnyPolicyLeaf)), + ?assertEqual([?PN("SILVER", ["A"]), ?PN("GOLD")], CS(TreeWithAnyPolicyNode1)), + ?assertEqual([?PN("GOLD", ["GOLD", "SILVER"])], CS(TreeWithAnyPolicyNode2)), + ok. + +valid_policy_node_set(_Config) -> + VS = + fun(Tree) -> + pubkey_policy_tree:valid_policy_node_set(Tree) + end, + ?assertEqual([], VS(?EMPTY_VPT)), + TreeWithAnyPolicyLeaf = {?ROOT_PN, + [{?PN("GOLD"), + [?PN(?ANY_POLICY_OID)]}]}, + log_tree_diagram("TreeWithAnyPolicyLeaf", TreeWithAnyPolicyLeaf), + ?assertEqual([?PN("GOLD")], VS(TreeWithAnyPolicyLeaf)), + TreeWithAnyPolicyNode1 = {?ROOT_PN, + [{?PN(?ANY_POLICY_OID), + [?PN("GOLD")]}, + {?PN("SILVER", ["A"]), + [?PN("SILVER", ["B"])]}]}, + log_tree_diagram("TreeWithAnyPolicyNode1", TreeWithAnyPolicyNode1), + ?assertEqual([?PN(?ANY_POLICY_OID), ?PN("SILVER", ["A"]), ?PN("GOLD")], + VS(TreeWithAnyPolicyNode1)), + TreeWithAnyPolicyNode2 = {?ROOT_PN, + [{?PN(?ANY_POLICY_OID), + [{?PN("GOLD", ["GOLD", "SILVER"]), + [?PN("SILVER")]}]}]}, + log_tree_diagram("TreeWithAnyPolicyNode2", TreeWithAnyPolicyNode2), + ?assertEqual([?PN(?ANY_POLICY_OID), ?PN("GOLD", ["GOLD", "SILVER"])], + VS(TreeWithAnyPolicyNode2)), + ok. + +prune_invalid_nodes(_Config) -> + Children0 = [{?PN("GOLD"), [?PN("GOLD")]}, + {?PN("BLUE"), []}, % policy_tree_node type terminating branch - pruning target + ?PN("SILVER")], % leaf of policy_node type + Tree0 = {?ROOT_PN, Children0 ++ + [{?PN("GOLD"), [?ROOT_PN]}]}, + Tree0 = pubkey_policy_tree:prune_invalid_nodes(Tree0, []), + + {ok, Tree1} = explain(Tree0, + [{prune_invalid_nodes, [[?PN("SILVER")]]}, + {prune_invalid_nodes, [[?PN("BLUE")]]}, + {prune_invalid_nodes, [[?PN("GOLD")]]}]), + ?EMPTY_VPT = Tree1, + + %% prune node + Tree2 = {?ROOT_PN, Children0 ++ + [{?PN(?ANY_POLICY_OID), [?ROOT_PN]}]}, + {ok, Tree3} = explain(Tree2, + [{prune_invalid_nodes, [[?PN("SILVER")]]}, + {prune_invalid_nodes, [[?PN("BLUE")]]}, + {prune_invalid_nodes, [[?PN("GOLD")]]}, + {prune_invalid_nodes, [[?PN(?ANY_POLICY_OID)]]}, + {prune_invalid_nodes, [[?ROOT_PN]]}]), + Expected = {?ROOT_PN, [{?PN(?ANY_POLICY_OID), + [?ROOT_PN]}]}, + ?assertEqual(Expected, Tree3), + ok. + +prune_leaves(_Config) -> + NullVPT = pubkey_policy_tree:empty(), + ?assertEqual(NullVPT, pubkey_policy_tree:prune_leaves(NullVPT, null)), + Tree0 = {?ROOT_PN, + [{?PN("GOLD"), [?PN("GOLD"), ?PN("GOLD2")]}, + {?PN("GOLD"), [?PN(?ANY_POLICY_OID), ?PN(?ANY_POLICY_OID)]}]}, + {ok, Tree} = explain(Tree0, [{prune_leaves, ["GOLD"]}, + {prune_leaves, [?ANY_POLICY_OID]}]), + ?assertEqual({?ROOT_PN, + [{?PN("GOLD"), [?PN("GOLD2")]}, + {?PN("GOLD"), []}]}, Tree), + ok. + +prune_tree_and_leaves(_Config) -> + Tree0 = {?ROOT_PN, + [{?PN("SILVER", ["SILVER"]), + []}, + {?PN("GOLD", ["GOLD"]), + [?PN("GOLD", ["GOLD"])]}]}, + Instructions = [{prune_tree, []}, + {prune_leaves, ["GOLD"]}], + {ok, Tree} = explain(Tree0, Instructions), + Expected = {?ROOT_PN, + [{?PN("GOLD", ["GOLD"]), []}]}, + Expected = Tree, + ok. + +prune_tree_shorter_branch(_Config) -> + %% shorter branch ending with leaf is not expected to be pruned + Tree0 = {?ROOT_PN, + [{?PN("GOLD"), [?PN("GOLD")]}, + ?PN("SILVER")]}, + Instructions = [{prune_tree, []}], + {ok, Tree0} = explain(Tree0, Instructions), + ok. + +all_leaves(_Config) -> + Tree1 = {?ROOT_PN, + [{?PN("GOLD"), + [{?PN("GOLD"), []}, + {?PN("SILVER"), [?PN("GOLD"), ?PN("SILVER")]}]}, + {?PN("SILVER"), + [{?PN("GOLD"), []}, + {?PN("SILVER"), [?PN("GOLD"), ?PN("SILVER")]}]}]}, + log_tree_diagram("Tree1", Tree1), + ?assertEqual([?PN("GOLD"), ?PN("SILVER"), ?PN("GOLD"), ?PN("SILVER")], + pubkey_policy_tree:all_leaves(Tree1)), + ok. + +add_leaves(_Config) -> + RootTree = pubkey_policy_tree:root(), + AddLeavesFun1 = + fun(_) -> [?PN("GOLD"), ?PN("SILVER")] end, + AddLeavesFun2 = + fun(#{valid_policy := "SILVER"}) -> + [?PN("GOLD"), ?PN("SILVER")]; + (_) -> + [] + end, + Instructions = [{add_leaves, [AddLeavesFun1]}, + {add_leaves, [AddLeavesFun1]}, + {add_leaves, [AddLeavesFun2]}], + {ok, Tree} = explain(RootTree, Instructions), + ?assertEqual({?ROOT_PN, + [{?PN("GOLD"), + [{?PN("GOLD"), []}, + {?PN("SILVER"), [?PN("GOLD"), ?PN("SILVER")]}]}, + {?PN("SILVER"), + [{?PN("GOLD"), []}, + {?PN("SILVER"), [?PN("GOLD"), ?PN("SILVER")]}]}]}, + Tree), + ok. + +add_leaf_siblings(_Config) -> + RootTree = pubkey_policy_tree:root(), + AddLeavesFun1 = + fun(_) -> [?PN("GOLD"), ?PN("SILVER")] end, + AddLeavesFun2 = + fun(#{valid_policy := ?ANY_POLICY_OID}) -> + [?PN("GOLD"), ?PN("SILVER")]; + (_) -> + [] + end, + Instructions = [{add_leaf_siblings, [AddLeavesFun1]}, + {add_leaf_siblings, [AddLeavesFun1]}, + {add_leaf_siblings, [AddLeavesFun2]} + ], + {ok, Tree} = explain(RootTree, Instructions), + ?assertEqual({?ROOT_PN, + [?PN("GOLD"), ?PN("SILVER"), + ?PN("GOLD"), ?PN("SILVER"), + ?PN("GOLD"), ?PN("SILVER")]}, + Tree), + ok. + +%%-------------------------------------------------------------------- +%% Internal API +%%-------------------------------------------------------------------- +explain(InitTree, Instructions) -> + ct:log("=============================================~nSTEP: 0)"), + ct:log("Instructions=~n~p", [Instructions]), + ?PAL_MMD(to_mmd("0) Initial tree", InitTree)), + explain(InitTree, Instructions, 1). + +explain(Tree, [], _) -> + {ok, Tree}; +explain(Tree0, [{FunctionName, Args} | Rest], N) -> + Title = io_lib:format("~p) pubkey_policy_tree:~p()", [N, FunctionName]), + ct:log("=============================================~nSTEP: ~s", [Title]), + Tree = apply(pubkey_policy_tree, FunctionName, [Tree0 | Args]), + ?PAL_MMD(to_mmd(Title, Tree)), + explain(Tree, Rest, N+1). + +log_tree_diagram(Title, Tree) -> + ?PAL_MMD(to_mmd(Title, Tree)), + ok. + +to_mmd(Title, Tree) -> + ct:log("Diagram input tree~n~p", [Tree]), + {NodeInfo, Arrows} = traverse(Tree), + ?PRE_SCRIPT ++ + "---~ntitle: " ++ Title ++ "~n---~n" ++ + "flowchart TD~n" ++ + NodeInfo ++ "~n" ++ Arrows ++ "~n" + ?POST_SCRIPT. + +traverse(TreeNode = {_PolicyNode, _NoChildren = []}) -> + Path = [1], + NodeId = nid(Path), + ?FWR("Node (no children): ~p~n", [lists:reverse(Path)]), + {"", io_lib:format("~s~s~n", [NodeId, node_desc(NodeId, TreeNode)])}; +traverse(TreeNode = {}) -> + Path = [1], + NodeId = nid(Path), + ?FWR("NULL tree: ~p~n", [lists:reverse(Path)]), + {"", io_lib:format("~s~s~n", [NodeId, node_desc(NodeId, TreeNode)])}; +traverse(Tree) -> + traverse(Tree, [1], {#{}, []}). + +traverse(#{}, _Path, Acc) -> + ?FWR("Node (leaf found): ~p~n", [lists:reverse(_Path)]), + Acc; +traverse({_Node, _NoChildren = []}, _Path = [1], _Acc = {NodeInfo0, Arrows}) -> + %% traverse end + ?FWR("END Node (no children): ~p~n", [lists:reverse(_Path)]), + NodeInfo = maps:fold(fun(K, V, Acc) -> + Acc ++ K ++ V ++ "~n" + end, + "", NodeInfo0), + {NodeInfo, Arrows}; +traverse({_Node, _NoChildren = []}, _Path, Acc) -> + ?FWR("Node (no children): ~p~n", [lists:reverse(_Path)]), + Acc; +traverse(TreeNode = {PolicyNode, Children = [Child | Rest]}, Path, _Acc = {NodeInfo0, Arrows0}) -> + NodeId = nid(Path), + ChildId = nid([length(Children) | Path]), + Fmt = "~s --> ~s~n", + Args = [NodeId, ChildId], + Arrows1 = Arrows0 ++ io_lib:format(Fmt, Args), + NodeInfo = store_new_nodes([{NodeId, TreeNode}, {ChildId, Child}], NodeInfo0), + Acc2 = traverse(Child, [length(Children) | Path], {NodeInfo, Arrows1}), % traverse vertically + traverse({PolicyNode, Rest}, Path, Acc2). % traverse horizontally + +store_new_nodes([], NodeInfo) -> + NodeInfo; +store_new_nodes([{Id, Node} | Rest] , NodeInfo0) -> + NodeInfo = case maps:is_key(Id, NodeInfo0) of + true -> + NodeInfo0; + false -> + NodeDesc = node_desc(Id, Node), + NodeInfo0#{Id => NodeDesc} + end, + store_new_nodes(Rest, NodeInfo). + +node_desc(Path, {}) -> + io_lib:format("[\"(NULL) ~s\"]", [Path]); +node_desc(Path, #{valid_policy := VP, expected_policy_set := EPS}) -> + io_lib:format("[\"(L) ~s\nvp: ~s\neps: ~s\"]", [Path, p(VP), ps(EPS)]); +node_desc(Path, {#{valid_policy := VP, expected_policy_set := EPS}, _}) -> + io_lib:format("[\"(N) ~s\nvp: ~s\neps: ~s\"]", [Path, p(VP), ps(EPS)]). + +nid(Path) -> + nid(Path, ""). + +nid([], Acc) -> + "N_" ++ lists:reverse(Acc); +nid([Node], Acc) -> + nid([], Acc ++ integer_to_list(Node)); +nid([Node | Rest], Acc) -> + nid(Rest, Acc ++ integer_to_list(Node) ++ "-"). + +ps(ExpectedPolicySet) -> + [io_lib:format("~s ", [p(P)]) || P <- ExpectedPolicySet]. + +p(?ANY_POLICY_OID) -> + "anyPolicy"; +p(P) -> + P. From 45e4c996880fc3d2b7e5a117f837624418b68f3a Mon Sep 17 00:00:00 2001 From: Jakub Witczak Date: Tue, 7 Nov 2023 13:20:52 +0100 Subject: [PATCH 2/2] public_key: review comments applied --- .../test/pubkey_policy_tree_SUITE.erl | 125 ++++++++---------- 1 file changed, 55 insertions(+), 70 deletions(-) diff --git a/lib/public_key/test/pubkey_policy_tree_SUITE.erl b/lib/public_key/test/pubkey_policy_tree_SUITE.erl index 0e4004baf83a..c152e7567e02 100644 --- a/lib/public_key/test/pubkey_policy_tree_SUITE.erl +++ b/lib/public_key/test/pubkey_policy_tree_SUITE.erl @@ -2,6 +2,7 @@ -compile([export_all, nowarn_export_all]). -include_lib("stdlib/include/assert.hrl"). +-include_lib("public_key/include/public_key.hrl"). -define(PRE_SCRIPT, "
~n").
 -define(POST_SCRIPT, "~n
"). @@ -23,14 +24,12 @@ ct:log(MMD), ?FWR("~n", []) end). --define(ANY_POLICY_OID, {2,5,29,32,0}). -define(ROOT_TN, pubkey_policy_tree:root()). -define(EMPTY_VPT, {}). -define(ROOT_PN, begin {AnyPolicyNode, _} = ?ROOT_TN, AnyPolicyNode - %% ?PN(?ANY_POLICY_OID) end). -define(PN(VP), pubkey_policy_tree:policy_node(VP, [], [])). -define(PN(VP, EPS), pubkey_policy_tree:policy_node(VP, [], EPS)). @@ -56,41 +55,21 @@ any_leaves(_Config) -> pubkey_policy_tree:any_leaves(Tree) end, ?assertEqual([], AL(?EMPTY_VPT)), - TreeWithAnyPolicyLeaf = {?ROOT_PN, - [{?PN("GOLD"), - [?PN(?ANY_POLICY_OID)]}]}, - log_tree_diagram("TreeWithAnyPolicyLeaf", TreeWithAnyPolicyLeaf), - ?assertEqual([?PN(?ANY_POLICY_OID)], AL(TreeWithAnyPolicyLeaf)), - TreeWithAnyPolicyNode1 = {?ROOT_PN, - [{?PN(?ANY_POLICY_OID), - [?PN("GOLD")]}, - {?PN("SILVER", ["A"]), - [?PN("SILVER", ["B"])]}]}, - log_tree_diagram("TreeWithAnyPolicyNode1", TreeWithAnyPolicyNode1), - ?assertEqual([], AL(TreeWithAnyPolicyNode1)), + log_tree_diagram("tree_with_any_policy_leaf()", tree_with_any_policy_leaf()), + ?assertEqual([?PN(?anyPolicy)], AL(tree_with_any_policy_leaf())), + log_tree_diagram("tree_with_any_policy_node1()", tree_with_any_policy_node1()), + ?assertEqual([], AL(tree_with_any_policy_node1())), ok. constrained_policy_node_set(_Config) -> - TreeWithAnyPolicyLeaf = {?ROOT_PN, - [{?PN("GOLD"), - [?PN(?ANY_POLICY_OID)]}]}, - TreeWithAnyPolicyNode1 = {?ROOT_PN, - [{?PN(?ANY_POLICY_OID), - [?PN("GOLD")]}, - {?PN("SILVER", ["A"]), - [?PN("SILVER", ["B"])]}]}, - TreeWithAnyPolicyNode2 = {?ROOT_PN, - [{?PN(?ANY_POLICY_OID), - [{?PN("GOLD", ["GOLD", "SILVER"]), - [?PN("SILVER")]}]}]}, CS = fun(Tree) -> pubkey_policy_tree:constrained_policy_node_set(Tree) end, ?assertEqual([], CS(?EMPTY_VPT)), - ?assertEqual([?PN(?ANY_POLICY_OID)], CS(TreeWithAnyPolicyLeaf)), - ?assertEqual([?PN("SILVER", ["A"]), ?PN("GOLD")], CS(TreeWithAnyPolicyNode1)), - ?assertEqual([?PN("GOLD", ["GOLD", "SILVER"])], CS(TreeWithAnyPolicyNode2)), + ?assertEqual([?PN(?anyPolicy)], CS(tree_with_any_policy_leaf())), + ?assertEqual([?PN("SILVER", ["A"]), ?PN("GOLD")], CS(tree_with_any_policy_node1())), + ?assertEqual([?PN("GOLD", ["GOLD", "SILVER"])], CS(tree_with_any_policy_node2())), ok. valid_policy_node_set(_Config) -> @@ -99,26 +78,14 @@ valid_policy_node_set(_Config) -> pubkey_policy_tree:valid_policy_node_set(Tree) end, ?assertEqual([], VS(?EMPTY_VPT)), - TreeWithAnyPolicyLeaf = {?ROOT_PN, - [{?PN("GOLD"), - [?PN(?ANY_POLICY_OID)]}]}, - log_tree_diagram("TreeWithAnyPolicyLeaf", TreeWithAnyPolicyLeaf), - ?assertEqual([?PN("GOLD")], VS(TreeWithAnyPolicyLeaf)), - TreeWithAnyPolicyNode1 = {?ROOT_PN, - [{?PN(?ANY_POLICY_OID), - [?PN("GOLD")]}, - {?PN("SILVER", ["A"]), - [?PN("SILVER", ["B"])]}]}, - log_tree_diagram("TreeWithAnyPolicyNode1", TreeWithAnyPolicyNode1), - ?assertEqual([?PN(?ANY_POLICY_OID), ?PN("SILVER", ["A"]), ?PN("GOLD")], - VS(TreeWithAnyPolicyNode1)), - TreeWithAnyPolicyNode2 = {?ROOT_PN, - [{?PN(?ANY_POLICY_OID), - [{?PN("GOLD", ["GOLD", "SILVER"]), - [?PN("SILVER")]}]}]}, - log_tree_diagram("TreeWithAnyPolicyNode2", TreeWithAnyPolicyNode2), - ?assertEqual([?PN(?ANY_POLICY_OID), ?PN("GOLD", ["GOLD", "SILVER"])], - VS(TreeWithAnyPolicyNode2)), + log_tree_diagram("tree_with_any_policy_leaf()", tree_with_any_policy_leaf()), + ?assertEqual([?PN("GOLD")], VS(tree_with_any_policy_leaf())), + log_tree_diagram("tree_with_any_policy_node1()", tree_with_any_policy_node1()), + ?assertEqual([?PN(?anyPolicy), ?PN("SILVER", ["A"]), ?PN("GOLD")], + VS(tree_with_any_policy_node1())), + log_tree_diagram("tree_with_any_policy_node2()", tree_with_any_policy_node2()), + ?assertEqual([?PN(?anyPolicy), ?PN("GOLD", ["GOLD", "SILVER"])], + VS(tree_with_any_policy_node2())), ok. prune_invalid_nodes(_Config) -> @@ -128,23 +95,21 @@ prune_invalid_nodes(_Config) -> Tree0 = {?ROOT_PN, Children0 ++ [{?PN("GOLD"), [?ROOT_PN]}]}, Tree0 = pubkey_policy_tree:prune_invalid_nodes(Tree0, []), - {ok, Tree1} = explain(Tree0, [{prune_invalid_nodes, [[?PN("SILVER")]]}, {prune_invalid_nodes, [[?PN("BLUE")]]}, {prune_invalid_nodes, [[?PN("GOLD")]]}]), ?EMPTY_VPT = Tree1, - %% prune node Tree2 = {?ROOT_PN, Children0 ++ - [{?PN(?ANY_POLICY_OID), [?ROOT_PN]}]}, + [{?PN(?anyPolicy), [?ROOT_PN]}]}, {ok, Tree3} = explain(Tree2, [{prune_invalid_nodes, [[?PN("SILVER")]]}, {prune_invalid_nodes, [[?PN("BLUE")]]}, {prune_invalid_nodes, [[?PN("GOLD")]]}, - {prune_invalid_nodes, [[?PN(?ANY_POLICY_OID)]]}, + {prune_invalid_nodes, [[?PN(?anyPolicy)]]}, {prune_invalid_nodes, [[?ROOT_PN]]}]), - Expected = {?ROOT_PN, [{?PN(?ANY_POLICY_OID), + Expected = {?ROOT_PN, [{?PN(?anyPolicy), [?ROOT_PN]}]}, ?assertEqual(Expected, Tree3), ok. @@ -154,9 +119,9 @@ prune_leaves(_Config) -> ?assertEqual(NullVPT, pubkey_policy_tree:prune_leaves(NullVPT, null)), Tree0 = {?ROOT_PN, [{?PN("GOLD"), [?PN("GOLD"), ?PN("GOLD2")]}, - {?PN("GOLD"), [?PN(?ANY_POLICY_OID), ?PN(?ANY_POLICY_OID)]}]}, + {?PN("GOLD"), [?PN(?anyPolicy), ?PN(?anyPolicy)]}]}, {ok, Tree} = explain(Tree0, [{prune_leaves, ["GOLD"]}, - {prune_leaves, [?ANY_POLICY_OID]}]), + {prune_leaves, [?anyPolicy]}]), ?assertEqual({?ROOT_PN, [{?PN("GOLD"), [?PN("GOLD2")]}, {?PN("GOLD"), []}]}, Tree), @@ -187,12 +152,12 @@ prune_tree_shorter_branch(_Config) -> all_leaves(_Config) -> Tree1 = {?ROOT_PN, - [{?PN("GOLD"), - [{?PN("GOLD"), []}, - {?PN("SILVER"), [?PN("GOLD"), ?PN("SILVER")]}]}, - {?PN("SILVER"), - [{?PN("GOLD"), []}, - {?PN("SILVER"), [?PN("GOLD"), ?PN("SILVER")]}]}]}, + [{?PN("GOLD"), + [{?PN("GOLD"), []}, + {?PN("SILVER"), [?PN("GOLD"), ?PN("SILVER")]}]}, + {?PN("SILVER"), + [{?PN("GOLD"), []}, + {?PN("SILVER"), [?PN("GOLD"), ?PN("SILVER")]}]}]}, log_tree_diagram("Tree1", Tree1), ?assertEqual([?PN("GOLD"), ?PN("SILVER"), ?PN("GOLD"), ?PN("SILVER")], pubkey_policy_tree:all_leaves(Tree1)), @@ -223,12 +188,13 @@ add_leaves(_Config) -> ok. add_leaf_siblings(_Config) -> - RootTree = pubkey_policy_tree:root(), AddLeavesFun1 = fun(_) -> [?PN("GOLD"), ?PN("SILVER")] end, AddLeavesFun2 = - fun(#{valid_policy := ?ANY_POLICY_OID}) -> - [?PN("GOLD"), ?PN("SILVER")]; + fun(#{valid_policy := ?anyPolicy}) -> + [?PN("PINK")]; + (#{valid_policy := "SILVER"}) -> + [?PN("PURPLE")]; (_) -> [] end, @@ -236,11 +202,12 @@ add_leaf_siblings(_Config) -> {add_leaf_siblings, [AddLeavesFun1]}, {add_leaf_siblings, [AddLeavesFun2]} ], - {ok, Tree} = explain(RootTree, Instructions), + {ok, Tree} = explain(tree_with_any_policy_node1(), Instructions), ?assertEqual({?ROOT_PN, - [?PN("GOLD"), ?PN("SILVER"), - ?PN("GOLD"), ?PN("SILVER"), - ?PN("GOLD"), ?PN("SILVER")]}, + [{?PN(?anyPolicy), + [?PN("GOLD"), ?PN("GOLD"), ?PN("SILVER"), ?PN("GOLD"), ?PN("SILVER"), ?PN("PINK")]}, + {?PN("SILVER", ["A"]), + [?PN("SILVER", ["B"]), ?PN("GOLD"), ?PN("SILVER"), ?PN("GOLD"), ?PN("SILVER"), ?PN("PURPLE")]}]}, Tree), ok. @@ -344,7 +311,25 @@ nid([Node | Rest], Acc) -> ps(ExpectedPolicySet) -> [io_lib:format("~s ", [p(P)]) || P <- ExpectedPolicySet]. -p(?ANY_POLICY_OID) -> +p(?anyPolicy) -> "anyPolicy"; p(P) -> P. + +tree_with_any_policy_leaf() -> + {?ROOT_PN, + [{?PN("GOLD"), + [?PN(?anyPolicy)]}]}. + +tree_with_any_policy_node1() -> + {?ROOT_PN, + [{?PN(?anyPolicy), + [?PN("GOLD")]}, + {?PN("SILVER", ["A"]), + [?PN("SILVER", ["B"])]}]}. + +tree_with_any_policy_node2() -> + {?ROOT_PN, + [{?PN(?anyPolicy), + [{?PN("GOLD", ["GOLD", "SILVER"]), + [?PN("SILVER")]}]}]}.