1: %%============================================================================== 2: %% Copyright 2019 Erlang Solutions Ltd. 3: %% 4: %% Licensed under the Apache License, Version 2.0 (the "License"); 5: %% you may not use this file except in compliance with the License. 6: %% You may obtain a copy of the License at 7: %% 8: %% http://www.apache.org/licenses/LICENSE-2.0 9: %% 10: %% Unless required by applicable law or agreed to in writing, software 11: %% distributed under the License is distributed on an "AS IS" BASIS, 12: %% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13: %% See the License for the specific language governing permissions and 14: %% limitations under the License. 15: %%============================================================================== 16: 17: -module(pubsub_backend_SUITE). 18: -compile([export_all, nowarn_export_all]). 19: -author('michael.uvarov@erlang-solutions.com'). 20: 21: -include_lib("common_test/include/ct.hrl"). 22: -include_lib("exml/include/exml.hrl"). 23: -include("mongoose.hrl"). 24: -include("jlib.hrl"). 25: -include("pubsub.hrl"). 26: 27: %%-------------------------------------------------------------------- 28: %% Suite configuration 29: %%-------------------------------------------------------------------- 30: 31: all() -> 32: [{group, tree_handling}]. 33: 34: groups() -> 35: [ 36: {tree_handling, [], tree_handling_tests()} 37: ]. 38: 39: tree_handling_tests() -> 40: [ 41: get_subnodes_case 42: ]. 43: 44: suite() -> 45: []. 46: 47: %%-------------------------------------------------------------------- 48: %% Init & teardown 49: %%-------------------------------------------------------------------- 50: 51: init_per_suite(Config) -> 52: ok = mnesia:create_schema([node()]), 53: mnesia:start(), 54: mod_pubsub_db_mnesia:start(), 55: {ok, _} = application:ensure_all_started(jid), 56: Config. 57: 58: end_per_suite(Config) -> 59: mod_pubsub_db_mnesia:stop(), 60: mnesia:stop(), 61: Config. 62: 63: init_per_group(_GroupName, Config) -> 64: Config. 65: 66: end_per_group(_GroupName, Config) -> 67: Config. 68: 69: init_per_testcase(_CaseName, Config) -> 70: Config. 71: 72: end_per_testcase(_CaseName, Config) -> 73: Config. 74: 75: %%-------------------------------------------------------------------- 76: %% Tree handling tests 77: %%-------------------------------------------------------------------- 78: 79: get_subnodes_case(_Config) -> 80: mod_pubsub_db_mnesia:transaction(fun() -> 81: get_subnodes_case_tr() 82: end, #{}). 83: 84: get_subnodes_case_tr() -> 85: create_jojo_tree(), 86: %% Get "root"-kinda nodes 87: compare_lists(people_with_both_parents_unknown(), nodes_to_names(get_subnodes(<<>>))), 88: %% Joseph has two children 89: compare_lists([<<"Josuke Higashikata">>, <<"Holy Kujo">>], 90: nodes_to_names(get_subnodes(<<"Joseph Joestar">>))), 91: %% Jotaro is a son of Holy 92: compare_lists([<<"Jotaro Kujo">>], 93: nodes_to_names(get_subnodes(<<"Holy Kujo">>))), 94: 95: HolyDescendants = get_subnodes_tree(<<"Holy Kujo">>), 96: HolyAncestors = get_parentnodes_tree(<<"Holy Kujo">>), 97: 98: %% level 0 is the last item 99: {0, _} = lists:last(HolyDescendants), 100: {0, _} = lists:last(HolyAncestors), 101: 102: %% Level 0 contains the node itself 103: compare_lists([<<"Holy Kujo">>], nodes_to_names(proplists:get_value(0, HolyDescendants))), 104: compare_lists([<<"Jotaro Kujo">>], nodes_to_names(proplists:get_value(1, HolyDescendants))), 105: compare_lists([<<"Jolyne Cujoh">>], nodes_to_names(proplists:get_value(2, HolyDescendants))), 106: compare_lists([], nodes_to_names(proplists:get_value(3, HolyDescendants))), 107: undefined = proplists:get_value(4, HolyDescendants), %% No such item on depth 4 108: 109: compare_lists([<<"Holy Kujo">>], nodes_to_names(proplists:get_value(0, HolyAncestors))), 110: compare_lists([<<"Joseph Joestar">>, <<"Suzi Q Joestar">>], nodes_to_names(proplists:get_value(1, HolyAncestors))), 111: compare_lists([<<"George Joestar II">>, <<"Elizabeth Joestar">>], nodes_to_names(proplists:get_value(2, HolyAncestors))), 112: compare_lists([<<"Erina Joestar">>, <<"Jonathan Joestar">>], nodes_to_names(proplists:get_value(3, HolyAncestors))), 113: compare_lists([<<"George Joestar I">>, <<"Mary Joestar">>], nodes_to_names(proplists:get_value(4, HolyAncestors))), 114: undefined = proplists:get_value(5, HolyAncestors), 115: 116: %% Dio not found 117: [] = get_subnodes(<<"Dio">>), 118: [ {1, []}, {0, [false]} ] = get_subnodes_tree(<<"Dio">>), 119: [ {0, []} ] = get_parentnodes_tree(<<"Dio">>), 120: ok. 121: 122: 123: %%-------------------------------------------------------------------- 124: %% Helpers 125: %%-------------------------------------------------------------------- 126: 127: make_node(Name, Parents) -> 128: #pubsub_node{nodeid = {host(), Name}, parents = Parents}. 129: 130: host() -> 131: <<"localhost">>. 132: 133: set_node(N) -> 134: mod_pubsub_db_mnesia:set_node(N). 135: 136: get_subnodes(Name) -> 137: mod_pubsub_db_mnesia:get_subnodes(host(), Name). 138: 139: get_subnodes_tree(Name) -> 140: mod_pubsub_db_mnesia:get_subnodes_tree(host(), Name). 141: 142: get_parentnodes_tree(Name) -> 143: mod_pubsub_db_mnesia:get_parentnodes_tree(host(), Name). 144: 145: %% https://jojo.fandom.com/wiki/Joestar_Family 146: create_jojo_tree() -> 147: set_node(make_node(<<"George Joestar I">>, [])), 148: set_node(make_node(<<"Mary Joestar">>, [])), 149: 150: set_node(make_node(<<"Jonathan Joestar">>, 151: [<<"George Joestar I">>, <<"Mary Joestar">>])), 152: set_node(make_node(<<"Erina Joestar">>, [])), 153: 154: set_node(make_node(<<"George Joestar II">>, 155: [<<"Jonathan Joestar">>, <<"Erina Joestar">>])), 156: set_node(make_node(<<"Elizabeth Joestar">>, [])), 157: 158: set_node(make_node(<<"Joseph Joestar">>, 159: [<<"George Joestar II">>, <<"Elizabeth Joestar">>])), 160: set_node(make_node(<<"Tomoko Higashikata">>, [])), 161: set_node(make_node(<<"Suzi Q Joestar">>, [])), 162: 163: set_node(make_node(<<"Josuke Higashikata">>, 164: [<<"Tomoko Higashikata">>, <<"Joseph Joestar">>])), 165: set_node(make_node(<<"Holy Kujo">>, 166: [<<"Joseph Joestar">>, <<"Suzi Q Joestar">>])), 167: 168: set_node(make_node(<<"Sadao Kujo">>, [])), 169: 170: set_node(make_node(<<"Jotaro Kujo">>, 171: [<<"Holy Kujo">>, <<"Sadao Kujo">>])), 172: 173: set_node(make_node(<<"Jolyne Cujoh">>, [<<"Jotaro Kujo">>])), 174: ok. 175: 176: nodes_to_names(Nodes) -> 177: [node_to_name(N) || N <- Nodes]. 178: 179: node_to_name(#pubsub_node{nodeid = {_, Name}}) -> 180: Name. 181: 182: people_with_both_parents_unknown() -> 183: [<<"Elizabeth Joestar">>, 184: <<"Erina Joestar">>, 185: <<"George Joestar I">>, 186: <<"Mary Joestar">>, 187: <<"Sadao Kujo">>, 188: <<"Suzi Q Joestar">>, 189: <<"Tomoko Higashikata">>]. 190: 191: %% Compare lists ignoring order 192: compare_lists(L1, L2) -> 193: SL1 = lists:sort(L1), 194: SL2 = lists:sort(L2), 195: case SL1 of 196: SL2 -> 197: ok; 198: _ -> 199: ct:fail({compare_lists, {expected, SL1}, {provided, SL2}}) 200: end.