github.com/igggame/nebulas-go@v2.1.0+incompatible/nbre/test/runtime/nr/gtest_decycle.cpp (about) 1 // Copyright (C) 2018 go-nebulas authors 2 // 3 // This file is part of the go-nebulas library. 4 // 5 // the go-nebulas library is free software: you can redistribute it and/or 6 // modify 7 // it under the terms of the GNU General Public License as published by 8 // the Free Software Foundation, either version 3 of the License, or 9 // (at your option) any later version. 10 // 11 // the go-nebulas library is distributed in the hope that it will be useful, 12 // but WITHOUT ANY WARRANTY; without even the implied warranty of 13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 // GNU General Public License for more details. 15 // 16 // You should have received a copy of the GNU General Public License 17 // along with the go-nebulas library. If not, see 18 // <http://www.gnu.org/licenses/>. 19 // 20 21 #include "common/common.h" 22 #include "runtime/nr/graph/algo.h" 23 #include <gtest/gtest.h> 24 25 TEST(test_decycle, non_recursive_remove_cycles_based_on_time_sequence_case1) { 26 neb::rt::transaction_graph tg; 27 tg.add_edge(neb::to_address("a"), neb::to_address("a"), 1, 1); 28 tg.add_edge(neb::to_address("a"), neb::to_address("b"), 2, 2); 29 tg.add_edge(neb::to_address("b"), neb::to_address("c"), 3, 3); 30 tg.add_edge(neb::to_address("c"), neb::to_address("a"), 4, 4); 31 32 auto graph = tg.internal_graph(); 33 neb::rt::graph_algo::non_recursive_remove_cycles_based_on_time_sequence( 34 graph); 35 36 neb::rt::transaction_graph::viterator_t vi, vi_end; 37 38 for (boost::tie(vi, vi_end) = boost::vertices(graph); vi != vi_end; vi++) { 39 neb::rt::transaction_graph::oeiterator_t oei, oei_end; 40 for (boost::tie(oei, oei_end) = boost::out_edges(*vi, graph); 41 oei != oei_end; oei++) { 42 auto source = boost::source(*oei, graph); 43 auto target = boost::target(*oei, graph); 44 std::string source_name = 45 boost::get(boost::vertex_name_t(), graph, source); 46 std::string target_name = 47 boost::get(boost::vertex_name_t(), graph, target); 48 49 neb::wei_t val = boost::get(boost::edge_weight_t(), graph, *oei); 50 int64_t ts = boost::get(boost::edge_timestamp_t(), graph, *oei); 51 if (source_name.compare("b") == 0 && target_name.compare("c") == 0) { 52 EXPECT_TRUE(val == 1 && ts == 3); 53 } else if (source_name.compare("c") == 0 && 54 target_name.compare("a") == 0) { 55 EXPECT_TRUE(val == 2 && ts == 4); 56 } 57 } 58 } 59 } 60 61 TEST(test_decycle, non_recursive_remove_cycles_based_on_time_sequence_case2) { 62 neb::rt::transaction_graph tg; 63 tg.add_edge(neb::to_address("a"), neb::to_address("a"), 1, 1); 64 tg.add_edge(neb::to_address("a"), neb::to_address("b"), 2, 3); 65 tg.add_edge(neb::to_address("b"), neb::to_address("a"), 3, 2); 66 tg.add_edge(neb::to_address("b"), neb::to_address("c"), 4, 1); 67 tg.add_edge(neb::to_address("c"), neb::to_address("a"), 5, 5); 68 69 auto graph = tg.internal_graph(); 70 neb::rt::graph_algo::non_recursive_remove_cycles_based_on_time_sequence( 71 graph); 72 tg.write_to_graphviz("case2.txt"); 73 74 neb::rt::transaction_graph::viterator_t vi, vi_end; 75 76 for (boost::tie(vi, vi_end) = boost::vertices(graph); vi != vi_end; vi++) { 77 neb::rt::transaction_graph::oeiterator_t oei, oei_end; 78 for (boost::tie(oei, oei_end) = boost::out_edges(*vi, graph); 79 oei != oei_end; oei++) { 80 auto source = boost::source(*oei, graph); 81 auto target = boost::target(*oei, graph); 82 std::string source_name = 83 boost::get(boost::vertex_name_t(), graph, source); 84 std::string target_name = 85 boost::get(boost::vertex_name_t(), graph, target); 86 87 neb::wei_t val = boost::get(boost::edge_weight_t(), graph, *oei); 88 int64_t ts = boost::get(boost::edge_timestamp_t(), graph, *oei); 89 if (source_name.compare("b") == 0 && target_name.compare("a") == 0) { 90 EXPECT_TRUE(val == 1 && ts == 2) << "val: " << val; 91 } else if (source_name.compare("c") == 0 && 92 target_name.compare("b") == 0) { 93 EXPECT_TRUE(val == 4 && ts == 1); 94 } else if (source_name.compare("b") == 0 && 95 target_name.compare("a") == 0) { 96 EXPECT_TRUE(val == 5 && ts == 5); 97 } 98 } 99 } 100 } 101 102 TEST(test_decycle, non_recursive_remove_cycles_based_on_time_sequence_case3) { 103 neb::rt::transaction_graph tg; 104 tg.add_edge(neb::to_address("a"), neb::to_address("a"), 1, 1); 105 tg.add_edge(neb::to_address("a"), neb::to_address("b"), 3, 2); 106 tg.add_edge(neb::to_address("b"), neb::to_address("a"), 1, 3); 107 tg.add_edge(neb::to_address("b"), neb::to_address("c"), 2, 4); 108 tg.add_edge(neb::to_address("c"), neb::to_address("a"), 2, 5); 109 110 auto graph = tg.internal_graph(); 111 neb::rt::graph_algo::non_recursive_remove_cycles_based_on_time_sequence( 112 graph); 113 114 neb::rt::transaction_graph::viterator_t vi, vi_end; 115 tg.write_to_graphviz("case3.txt"); 116 117 for (boost::tie(vi, vi_end) = boost::vertices(graph); vi != vi_end; vi++) { 118 neb::rt::transaction_graph::oeiterator_t oei, oei_end; 119 boost::tie(oei, oei_end) = boost::out_edges(*vi, graph); 120 EXPECT_TRUE(oei == oei_end); 121 } 122 } 123 124 TEST(test_decycle, non_recursive_remove_cycles_based_on_time_sequence_case4) { 125 neb::rt::transaction_graph tg; 126 tg.add_edge(neb::to_address("a"), neb::to_address("b"), 2, 2); 127 tg.add_edge(neb::to_address("b"), neb::to_address("c"), 3, 1); 128 tg.add_edge(neb::to_address("c"), neb::to_address("d"), 1, 4); 129 tg.add_edge(neb::to_address("d"), neb::to_address("b"), 2, 4); 130 131 auto graph = tg.internal_graph(); 132 neb::rt::graph_algo::non_recursive_remove_cycles_based_on_time_sequence( 133 graph); 134 135 neb::rt::transaction_graph::viterator_t vi, vi_end; 136 for (boost::tie(vi, vi_end) = boost::vertices(graph); vi != vi_end; vi++) { 137 neb::rt::transaction_graph::oeiterator_t oei, oei_end; 138 for (boost::tie(oei, oei_end) = boost::out_edges(*vi, graph); 139 oei != oei_end; oei++) { 140 auto source = boost::source(*oei, graph); 141 auto target = boost::target(*oei, graph); 142 std::string source_name = 143 boost::get(boost::vertex_name_t(), graph, source); 144 std::string target_name = 145 boost::get(boost::vertex_name_t(), graph, target); 146 147 neb::wei_t val = boost::get(boost::edge_weight_t(), graph, *oei); 148 int64_t ts = boost::get(boost::edge_timestamp_t(), graph, *oei); 149 if (source_name.compare("a") == 0 && target_name.compare("b") == 0) { 150 EXPECT_TRUE(val == 2 && ts == 2); 151 } else if (source_name.compare("b") == 0 && 152 target_name.compare("c") == 0) { 153 EXPECT_TRUE(val == 2 && ts == 1); 154 } else if (source_name.compare("d") == 0 && 155 target_name.compare("b") == 0) { 156 EXPECT_TRUE(val == 1 && ts == 4); 157 } 158 } 159 } 160 } 161 162 TEST(test_decycle, non_recursive_remove_cycles_based_on_time_sequence_case5) { 163 neb::rt::transaction_graph tg; 164 char cc = 'z'; 165 int32_t n = 1000; 166 for (char ch = 'a'; ch < cc; ch++) { 167 for (int32_t i = 0; i < n; i++) { 168 tg.add_edge(neb::to_address(std::string(1, ch)), 169 neb::to_address(std::string(1, ch + 1)), ch - 'a' + 1, 170 ch - 'a' + 1); 171 } 172 } 173 for (int32_t i = 0; i < n; i++) { 174 tg.add_edge(neb::to_address(std::string(1, cc)), 175 neb::to_address(std::string(1, 'a')), cc - 'a' + 1, 176 cc - 'a' + 1); 177 } 178 179 auto graph = tg.internal_graph(); 180 LOG(INFO) << boost::num_vertices(graph); 181 LOG(INFO) << boost::num_edges(graph); 182 neb::rt::graph_algo::non_recursive_remove_cycles_based_on_time_sequence( 183 graph); 184 } 185 186 TEST(test_decycle, non_recursive_remove_cycles_based_on_time_sequence_case6) { 187 neb::rt::transaction_graph tg; 188 char cc = 'z'; 189 int32_t n = 100; 190 for (char ch = 'a'; ch <= cc; ch++) { 191 for (int32_t i = 0; i < n; i++) { 192 tg.add_edge(neb::to_address(std::string(1, ch)), 193 neb::to_address(std::string(1, ch)), ch - 'a' + 1, 194 ch - 'a' + 1); 195 } 196 } 197 198 auto graph = tg.internal_graph(); 199 neb::rt::graph_algo::non_recursive_remove_cycles_based_on_time_sequence( 200 graph); 201 EXPECT_EQ(boost::num_vertices(graph), cc - 'a' + 1); 202 EXPECT_EQ(boost::num_edges(graph), 0); 203 } 204 205 TEST(test_decycle, non_recursive_remove_cycles_based_on_time_sequence_case7) { 206 neb::rt::transaction_graph tg; 207 tg.add_edge(neb::to_address("a"), neb::to_address("b"), 1, 1); 208 tg.add_edge(neb::to_address("b"), neb::to_address("c"), 2, 1); 209 tg.add_edge(neb::to_address("c"), neb::to_address("d"), 3, 2); 210 tg.add_edge(neb::to_address("d"), neb::to_address("a"), 4, 2); 211 212 auto graph = tg.internal_graph(); 213 neb::rt::graph_algo::non_recursive_remove_cycles_based_on_time_sequence( 214 graph); 215 216 neb::rt::transaction_graph::viterator_t vi, vi_end; 217 for (boost::tie(vi, vi_end) = boost::vertices(graph); vi != vi_end; vi++) { 218 neb::rt::transaction_graph::oeiterator_t oei, oei_end; 219 for (boost::tie(oei, oei_end) = boost::out_edges(*vi, graph); 220 oei != oei_end; oei++) { 221 auto source = boost::source(*oei, graph); 222 auto target = boost::target(*oei, graph); 223 std::string source_name = 224 boost::get(boost::vertex_name_t(), graph, source); 225 std::string target_name = 226 boost::get(boost::vertex_name_t(), graph, target); 227 228 neb::wei_t val = boost::get(boost::edge_weight_t(), graph, *oei); 229 int64_t ts = boost::get(boost::edge_timestamp_t(), graph, *oei); 230 if (source_name.compare("b") == 0 && target_name.compare("c") == 0) { 231 EXPECT_TRUE(val == 1 && ts == 1); 232 } else if (source_name.compare("c") == 0 && 233 target_name.compare("d") == 0) { 234 EXPECT_TRUE(val == 2 && ts == 2); 235 } else if (source_name.compare("d") == 0 && 236 target_name.compare("a") == 0) { 237 EXPECT_TRUE(val == 3 && ts == 2); 238 } 239 } 240 } 241 } 242 243 TEST(test_decycle, non_recursive_remove_cycles_based_on_time_sequence_case8) { 244 neb::rt::transaction_graph tg; 245 tg.add_edge(neb::to_address("b"), neb::to_address("c"), 1, 1); 246 tg.add_edge(neb::to_address("c"), neb::to_address("d"), 2, 2); 247 tg.add_edge(neb::to_address("d"), neb::to_address("b"), 3, 3); 248 tg.add_edge(neb::to_address("a"), neb::to_address("d"), 1, 1); 249 tg.add_edge(neb::to_address("b"), neb::to_address("a"), 2, 2); 250 251 auto graph = tg.internal_graph(); 252 neb::rt::graph_algo::non_recursive_remove_cycles_based_on_time_sequence( 253 graph); 254 255 neb::rt::transaction_graph::viterator_t vi, vi_end; 256 for (boost::tie(vi, vi_end) = boost::vertices(graph); vi != vi_end; vi++) { 257 neb::rt::transaction_graph::oeiterator_t oei, oei_end; 258 for (boost::tie(oei, oei_end) = boost::out_edges(*vi, graph); 259 oei != oei_end; oei++) { 260 auto source = boost::source(*oei, graph); 261 auto target = boost::target(*oei, graph); 262 std::string source_name = 263 boost::get(boost::vertex_name_t(), graph, source); 264 std::string target_name = 265 boost::get(boost::vertex_name_t(), graph, target); 266 267 neb::wei_t val = boost::get(boost::edge_weight_t(), graph, *oei); 268 int64_t ts = boost::get(boost::edge_timestamp_t(), graph, *oei); 269 if (source_name.compare("c") == 0 && target_name.compare("d") == 0) { 270 EXPECT_TRUE(val == 1 && ts == 2); 271 } else if (source_name.compare("d") == 0 && 272 target_name.compare("b") == 0) { 273 EXPECT_TRUE(val == 2 && ts == 3); 274 } else if (source_name.compare("a") == 0 && 275 target_name.compare("d") == 0) { 276 EXPECT_TRUE(val == 1 && ts == 1); 277 } else if (source_name.compare("b") == 0 && 278 target_name.compare("a") == 0) { 279 EXPECT_TRUE(val == 2 && ts == 2); 280 } 281 } 282 } 283 } 284 285 TEST(test_decycle, non_recursive_remove_cycles_based_on_time_sequence_case9) { 286 neb::rt::transaction_graph tg; 287 char cc = 'z'; 288 int32_t n = 100; 289 for (char ch = 'a'; ch < cc; ch++) { 290 for (int32_t i = 0; i < n; i++) { 291 tg.add_edge(neb::to_address(std::string(1, ch)), 292 neb::to_address(std::string(1, ch + 1)), ch - 'a' + 1, 293 ch - 'a' + 1); 294 } 295 } 296 297 auto &graph = tg.internal_graph(); 298 auto before_v_nums = boost::num_vertices(graph); 299 auto before_e_nums = boost::num_edges(graph); 300 neb::rt::graph_algo::non_recursive_remove_cycles_based_on_time_sequence( 301 graph); 302 auto after_v_nums = boost::num_vertices(graph); 303 auto after_e_nums = boost::num_edges(graph); 304 EXPECT_EQ(before_v_nums, after_v_nums); 305 EXPECT_EQ(before_e_nums, after_e_nums); 306 } 307 308 TEST(test_decycle, non_recursive_remove_cycles_based_on_time_sequence_case10) { 309 neb::rt::transaction_graph tg; 310 std::queue<char> q; 311 char cc = 'z'; 312 int32_t n = 2; 313 q.push('a'); 314 char tail = 'a'; 315 while (!q.empty()) { 316 auto &ele = q.front(); 317 q.pop(); 318 char tmp_tail = tail; 319 if (tail + n < cc) { 320 for (auto i = 1; i <= n; i++) { 321 tg.add_edge(neb::to_address(std::string(1, ele)), 322 neb::to_address(std::string(1, tmp_tail + i)), 323 ele - 'a' + 1, ele - 'a' + 1); 324 q.push(tmp_tail + i); 325 tail++; 326 } 327 tmp_tail = tail; 328 } 329 } 330 331 auto graph = tg.internal_graph(); 332 auto before_v_nums = boost::num_vertices(graph); 333 auto before_e_nums = boost::num_edges(graph); 334 LOG(INFO) << before_v_nums << ',' << before_e_nums; 335 neb::rt::graph_algo::non_recursive_remove_cycles_based_on_time_sequence( 336 graph); 337 auto after_v_nums = boost::num_vertices(graph); 338 auto after_e_nums = boost::num_edges(graph); 339 EXPECT_EQ(before_v_nums, after_v_nums); 340 EXPECT_EQ(before_e_nums, after_e_nums); 341 } 342 343 TEST(test_decycle, non_recursive_remove_cycles_based_on_time_sequence_case11) { 344 neb::rt::transaction_graph tg; 345 char cc = 'z'; 346 int32_t n = 5; 347 int32_t tmp = cc - 'a' + 1; 348 349 for (char s = 'a'; s <= cc; s++) { 350 for (char t = 'a'; t <= cc; t++) { 351 int32_t s_ch = s - 'a' + 1; 352 int32_t t_ch = t - 'a' + 1; 353 for (int32_t i = 0; i < n; i++) { 354 tg.add_edge(neb::to_address(std::string(1, s)), 355 neb::to_address(std::string(1, t)), s_ch + tmp * t_ch + 1, 356 s_ch + tmp * t_ch + 1); 357 } 358 } 359 } 360 361 auto graph = tg.internal_graph(); 362 LOG(INFO) << "edge num: " << tg.edge_num(); 363 neb::rt::graph_algo::non_recursive_remove_cycles_based_on_time_sequence( 364 graph); 365 } 366 367 TEST(test_decycle, non_recursive_remove_cycles_based_on_time_sequence_case12) { 368 neb::rt::transaction_graph tg; 369 char cc = 'z'; 370 char ch_half = cc / 2; 371 int32_t n = 10; 372 int32_t tmp = cc - 'a' + 1; 373 374 for (char s = 'a'; s < ch_half; s++) { 375 for (char t = ch_half; t <= cc; t++) { 376 int32_t s_ch = s - 'a' + 1; 377 int32_t t_ch = t - 'a' + 1; 378 for (int32_t i = 0; i < n; i++) { 379 tg.add_edge(neb::to_address(std::string(1, s)), 380 neb::to_address(std::string(1, t)), s_ch + tmp * t_ch + 1, 381 s_ch + tmp * t_ch + 1); 382 } 383 } 384 } 385 386 auto graph = tg.internal_graph(); 387 neb::rt::graph_algo::non_recursive_remove_cycles_based_on_time_sequence( 388 graph); 389 } 390