diff --git a/demo_storage/test/config.h b/demo_storage/test/config.h new file mode 100644 index 0000000..db2f6fd --- /dev/null +++ b/demo_storage/test/config.h @@ -0,0 +1,46 @@ +/** Copyright 2020 Alibaba Group Holding Limited. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +#ifndef TEST_CONFIG_H_ +#define TEST_CONFIG_H_ + +// Define a new macro that is just like the standard C assert macro, +// except that it works even in optimized builds (where NDEBUG is +// defined) and it prints the failed assertion to stderr. +#ifndef ASSERT +#define ASSERT(x) \ + if (!(x)) { \ + char buf[2048]; \ + snprintf(buf, sizeof(buf), \ + "Assertion failed in \"%s\", line %d\n" \ + "\tProbable bug in software.\n", \ + __FILE__, __LINE__); \ + ABORT(buf); \ + } else // NOLINT +// The 'else' exists to catch the user's following semicolon +#endif + +// Define a new macro that is just like the standard C abort macro, +// except that it prints the failed assertion to stderr. +#ifndef ABORT +#define ABORT(msg) \ + do { \ + fprintf(stderr, "%s", msg); \ + fflush(stderr); \ + abort(); \ + } while (0) +#endif + +#endif // TEST_CONFIG_H_ diff --git a/demo_storage/test/test_index.cc b/demo_storage/test/test_index.cc new file mode 100644 index 0000000..07ea542 --- /dev/null +++ b/demo_storage/test/test_index.cc @@ -0,0 +1,201 @@ +/** Copyright 2020 Alibaba Group Holding Limited. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +#include + +// predefine for GRIN +#include "../predefine.h" +// storage headers +#include "storage/loadmoderngraph.h" +// test config headers +#include "test/config.h" +// GRIN headers +#include "index/external_id.h" +#include "index/internal_id.h" +#include "index/order.h" +#include "index/pk.h" +#include "property/primarykey.h" +#include "property/topology.h" +#include "property/type.h" +#include "topology/structure.h" +#include "topology/vertexlist.h" + +void test_index_order(GRIN_GRAPH graph) { + std::cout << "\n++++ test index: order ++++" << std::endl; + + std::cout << "test vertex order" << std::endl; + auto vtype = grin_get_vertex_type_by_id(graph, 0); + auto vertex_list = grin_get_vertex_list_by_type(graph, vtype); + size_t idx0 = 0, idx1 = 1; + auto v0 = grin_get_vertex_from_list(graph, vertex_list, idx0); + auto v1 = grin_get_vertex_from_list(graph, vertex_list, idx1); + ASSERT(grin_smaller_vertex(graph, v0, v1) == true); + ASSERT(grin_smaller_vertex(graph, v1, v0) == false); + + std::cout << "test get position of vertex from sorted list" << std::endl; + size_t pos0 = + grin_get_position_of_vertex_from_sorted_list(graph, vertex_list, v0); + size_t pos1 = + grin_get_position_of_vertex_from_sorted_list(graph, vertex_list, v1); + ASSERT(pos0 == idx0); + ASSERT(pos1 == idx1); + + // destroy + grin_destroy_vertex(graph, v0); + grin_destroy_vertex(graph, v1); + grin_destroy_vertex_list(graph, vertex_list); + grin_destroy_vertex_type(graph, vtype); + + std::cout << "---- test index: order completed ----" << std::endl; +} + +void test_internal_id(GRIN_GRAPH graph) { + std::cout << "\n++++ test index: internal id ++++" << std::endl; + + std::cout << "test vertex internal id" << std::endl; + auto vtype = grin_get_vertex_type_by_id(graph, 0); + auto vertex_list = grin_get_vertex_list_by_type(graph, vtype); + size_t idx0 = 0, idx1 = 1; + auto v0 = grin_get_vertex_from_list(graph, vertex_list, idx0); + auto v1 = grin_get_vertex_from_list(graph, vertex_list, idx1); + + // get internal id of vertex + auto id0 = grin_get_vertex_internal_id_by_type(graph, vtype, v0); + auto id1 = grin_get_vertex_internal_id_by_type(graph, vtype, v1); + std::cout << "internal id of v0 = " << id0 << std::endl; + std::cout << "internal id of v1 = " << id1 << std::endl; + + // get vertex by internal id + auto v0_from_id = grin_get_vertex_by_internal_id_by_type(graph, vtype, id0); + auto v1_from_id = grin_get_vertex_by_internal_id_by_type(graph, vtype, id1); + ASSERT(grin_equal_vertex(graph, v0, v0_from_id) == true); + ASSERT(grin_equal_vertex(graph, v1, v1_from_id) == true); + + auto lower_bound = + grin_get_vertex_internal_id_lower_bound_by_type(graph, vtype); + std::cout << "lower bound of internal id = " << lower_bound << std::endl; + auto upper_bound = + grin_get_vertex_internal_id_upper_bound_by_type(graph, vtype); + std::cout << "upper bound of internal id = " << upper_bound << std::endl; + + // destroy + grin_destroy_vertex(graph, v0); + grin_destroy_vertex(graph, v1); + grin_destroy_vertex(graph, v0_from_id); + grin_destroy_vertex(graph, v1_from_id); + grin_destroy_vertex_list(graph, vertex_list); + grin_destroy_vertex_type(graph, vtype); + + std::cout << "---- test index: internal id completed ----" << std::endl; +} + +void test_external_id(GRIN_GRAPH graph) { + std::cout << "\n++++ test index: external id ++++" << std::endl; + + std::cout << "test vertex external id: int64" << std::endl; + auto vtype = grin_get_vertex_type_by_id(graph, 0); + auto vertex_list = grin_get_vertex_list_by_type(graph, vtype); + size_t idx0 = 0, idx1 = 1; + auto v0 = grin_get_vertex_from_list(graph, vertex_list, idx0); + auto v1 = grin_get_vertex_from_list(graph, vertex_list, idx1); + + // get external id of int64 + auto id0 = grin_get_vertex_external_id_of_int64(graph, v0); + auto id1 = grin_get_vertex_external_id_of_int64(graph, v1); + std::cout << "external id of v0 = " << id0 << std::endl; + std::cout << "external id of v1 = " << id1 << std::endl; + + // get vertex by external id + auto v0_from_id = grin_get_vertex_by_external_id_of_int64(graph, id0); + auto v1_from_id = grin_get_vertex_by_external_id_of_int64(graph, id1); + ASSERT(grin_equal_vertex(graph, v0, v0_from_id) == true); + ASSERT(grin_equal_vertex(graph, v1, v1_from_id) == true); + + std::cout << "test vertex external id: string" << std::endl; + // get external id of string + auto id0_str = grin_get_vertex_external_id_of_string(graph, v0); + auto id1_str = grin_get_vertex_external_id_of_string(graph, v1); + std::cout << "external id of v0 = " << id0_str << std::endl; + std::cout << "external id of v1 = " << id1_str << std::endl; + + // get vertex by external id + auto v0_from_id_str = + grin_get_vertex_by_external_id_of_string(graph, id0_str); + auto v1_from_id_str = + grin_get_vertex_by_external_id_of_string(graph, id1_str); + ASSERT(grin_equal_vertex(graph, v0, v0_from_id_str) == true); + ASSERT(grin_equal_vertex(graph, v1, v1_from_id_str) == true); + + // destroy + grin_destroy_vertex(graph, v0); + grin_destroy_vertex(graph, v1); + grin_destroy_vertex(graph, v0_from_id); + grin_destroy_vertex(graph, v1_from_id); + grin_destroy_vertex(graph, v0_from_id_str); + grin_destroy_vertex(graph, v1_from_id_str); + grin_destroy_vertex_list(graph, vertex_list); + grin_destroy_vertex_type(graph, vtype); + + std::cout << "---- test index: internal id completed ----" << std::endl; +} + +void test_pk(GRIN_GRAPH graph) { + std::cout << "\n++++ test index: pk ++++" << std::endl; + + auto vertex_type = grin_get_vertex_type_by_id(graph, 0); + auto vertex_list = grin_get_vertex_list_by_type(graph, vertex_type); + auto v0 = grin_get_vertex_from_list(graph, vertex_list, 0); + auto row = grin_get_vertex_primary_keys_row(graph, v0); + auto v1 = grin_get_vertex_by_primary_keys_row(graph, vertex_type, row); + ASSERT(grin_equal_vertex(graph, v0, v1) == true); + std::cout << "vertex from pk is equal to the original vertex" << std::endl; + + std::cout << "---- test index: pk completed ----" << std::endl; +} + +int main() { + // load graph + std::cout << "load modern graph" << std::endl; + std::string graph_name = "modern_graph"; + char* graph_name_str = new char[graph_name.size() + 1]; + snprintf(graph_name_str, graph_name.size() + 1, "%s", graph_name.c_str()); + demo_storage_load_modern_graph(graph_name_str, 1, 0); + delete[] graph_name_str; + + // get grin graph + std::string uri = "demo_storage://" + graph_name; + std::cout << "get grin graph from uri: " << uri << std::endl; + char* uri_str = new char[uri.size() + 1]; + snprintf(uri_str, uri.size() + 1, "%s", uri.c_str()); + GRIN_GRAPH graph = grin_get_graph_from_storage(uri_str); + delete[] uri_str; + + // test index order + test_index_order(graph); + + // test internal id + test_internal_id(graph); + + // test external id + test_external_id(graph); + + // test pk + test_pk(graph); + + // destroy graph + grin_destroy_graph(graph); + + return 0; +} diff --git a/demo_storage/test/test_index_label.cc b/demo_storage/test/test_index_label.cc new file mode 100644 index 0000000..1f7836b --- /dev/null +++ b/demo_storage/test/test_index_label.cc @@ -0,0 +1,224 @@ +/** Copyright 2020 Alibaba Group Holding Limited. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +#include + +// predefine for GRIN +#include "../predefine.h" +// storage headers +#include "storage/loadmoderngraph.h" +// test config headers +#include "test/config.h" +// GRIN headers +#include "index/internal_id.h" +#include "index/label.h" +#include "index/order.h" +#include "property/topology.h" +#include "property/type.h" +#include "topology/edgelist.h" +#include "topology/structure.h" +#include "topology/vertexlist.h" + +void test_vertex_label(GRIN_GRAPH graph) { + std::cout << "\n++++ test index: vertex label ++++" << std::endl; + auto vertex_label_list = grin_get_vertex_label_list(graph); + auto vertex_label_list_size = + grin_get_label_list_size(graph, vertex_label_list); + std::cout << "vertex label list size: " << vertex_label_list_size + << std::endl; + + for (size_t i = 0; i < vertex_label_list_size; ++i) { + auto vertex_label = grin_get_label_from_list(graph, vertex_label_list, i); + auto vertex_label_name = grin_get_label_name(graph, vertex_label); + std::cout << "vertex label name: " << vertex_label_name << std::endl; + auto vertex_label_2 = grin_get_label_by_name(graph, vertex_label_name); + ASSERT(vertex_label == vertex_label_2); + + // get vertex types by label + auto vertex_type_list = + grin_get_vertex_type_list_by_label(graph, vertex_label); + auto vertex_type_list_size = + grin_get_label_list_size(graph, vertex_type_list); + std::cout << "vertex type list size for this label: " + << vertex_type_list_size << std::endl; + + // destroy + grin_destroy_label(graph, vertex_label); + grin_destroy_label(graph, vertex_label_2); + grin_destroy_vertex_type_list(graph, vertex_type_list); + } + + // destroy vertex label list + grin_destroy_label_list(graph, vertex_label_list); + + auto vertex_type = grin_get_vertex_type_by_name(graph, "person"); + auto vertex_list = grin_get_vertex_list_by_type(graph, vertex_type); + auto vertex = grin_get_vertex_from_list(graph, vertex_list, 0); + auto label_list = grin_get_label_list_by_vertex(graph, vertex); + auto label_list_size = grin_get_label_list_size(graph, label_list); + std::cout << "label list size for vertex person #0: " << label_list_size + << std::endl; + + for (size_t i = 0; i < label_list_size; ++i) { + auto label = grin_get_label_from_list(graph, label_list, i); + auto label_name = grin_get_label_name(graph, label); + std::cout << "label name: " << label_name << std::endl; + grin_destroy_label(graph, label); + } + + // get vertex list by label + auto label = grin_get_label_by_name(graph, "v_label_0"); + auto vertex_list_2 = + grin_get_vertex_list_by_type_by_label(graph, vertex_type, label); + auto vertex_list_size = grin_get_vertex_list_size(graph, vertex_list_2); + std::cout << "vertex list size for v_label_0 of type #0: " << vertex_list_size + << std::endl; + + // check array & iterator + auto iter = grin_get_vertex_list_begin(graph, vertex_list_2); + for (size_t i = 0; i < vertex_list_size; ++i) { + ASSERT(!grin_is_vertex_list_end(graph, iter)); + auto vertex = grin_get_vertex_from_list(graph, vertex_list_2, i); + auto vertex2 = grin_get_vertex_from_iter(graph, iter); + ASSERT(vertex == vertex2); + auto id = grin_get_vertex_internal_id_by_type(graph, vertex_type, vertex); + std::cout << "vertex internal id: " << id << std::endl; + // check order + auto pos = grin_get_position_of_vertex_from_sorted_list( + graph, vertex_list_2, vertex); + ASSERT(pos == i); + // get next & destroy + grin_get_next_vertex_list_iter(graph, iter); + grin_destroy_vertex(graph, vertex); + grin_destroy_vertex(graph, vertex2); + } + ASSERT(grin_is_vertex_list_end(graph, iter)); + grin_destroy_vertex_list_iter(graph, iter); + std::cout << "check array & iterator done" << std::endl; + + // destroy + grin_destroy_label(graph, label); + grin_destroy_label_list(graph, label_list); + grin_destroy_vertex(graph, vertex); + grin_destroy_vertex_list(graph, vertex_list); + grin_destroy_vertex_type(graph, vertex_type); + grin_destroy_vertex_list(graph, vertex_list_2); +} + +void test_edge_label(GRIN_GRAPH graph) { + std::cout << "\n++++ test index: edge label ++++" << std::endl; + auto edge_label_list = grin_get_edge_label_list(graph); + auto edge_label_list_size = grin_get_label_list_size(graph, edge_label_list); + std::cout << "edge label list size: " << edge_label_list_size << std::endl; + + for (size_t i = 0; i < edge_label_list_size; ++i) { + auto edge_label = grin_get_label_from_list(graph, edge_label_list, i); + auto edge_label_name = grin_get_label_name(graph, edge_label); + std::cout << "edge label name: " << edge_label_name << std::endl; + auto edge_label_2 = grin_get_label_by_name(graph, edge_label_name); + ASSERT(edge_label == edge_label_2); + + // get vertex types by label + auto edge_type_list = grin_get_edge_type_list_by_label(graph, edge_label); + auto edge_type_list_size = grin_get_label_list_size(graph, edge_type_list); + std::cout << "edge type list size for this label: " << edge_type_list_size + << std::endl; + + // destroy + grin_destroy_label(graph, edge_label); + grin_destroy_label(graph, edge_label_2); + grin_destroy_vertex_type_list(graph, edge_type_list); + } + + // destroy edge label list + grin_destroy_label_list(graph, edge_label_list); + + auto edge_type = grin_get_edge_type_by_name(graph, "knows"); + auto edge_list = grin_get_edge_list_by_type(graph, edge_type); + auto edge = grin_get_edge_from_list(graph, edge_list, 0); + auto label_list = grin_get_label_list_by_edge(graph, edge); + auto label_list_size = grin_get_label_list_size(graph, label_list); + std::cout << "label list size for edge knows #0: " << label_list_size + << std::endl; + + for (size_t i = 0; i < label_list_size; ++i) { + auto label = grin_get_label_from_list(graph, label_list, i); + auto label_name = grin_get_label_name(graph, label); + std::cout << "label name: " << label_name << std::endl; + grin_destroy_label(graph, label); + } + + // get edge list by label + auto label = grin_get_label_by_name(graph, "e_label_0"); + auto edge_list_2 = + grin_get_edge_list_by_type_by_label(graph, edge_type, label); + auto edge_list_size = grin_get_edge_list_size(graph, edge_list_2); + std::cout << "edge list size for e_label_0 of type #0: " << edge_list_size + << std::endl; + + // check array & iterator + auto iter = grin_get_edge_list_begin(graph, edge_list_2); + for (size_t i = 0; i < edge_list_size; ++i) { + ASSERT(!grin_is_edge_list_end(graph, iter)); + auto edge = grin_get_edge_from_list(graph, edge_list_2, i); + auto edge2 = grin_get_edge_from_iter(graph, iter); + ASSERT(edge == edge2); + std::cout << "edge " << i << std::endl; + // get next & destroy + grin_destroy_edge(graph, edge); + grin_destroy_edge(graph, edge2); + grin_get_next_edge_list_iter(graph, iter); + } + ASSERT(grin_is_edge_list_end(graph, iter)); + grin_destroy_edge_list_iter(graph, iter); + std::cout << "check array & iterator done" << std::endl; + + // destroy + grin_destroy_label(graph, label); + grin_destroy_label_list(graph, label_list); + grin_destroy_edge(graph, edge); + grin_destroy_edge_list(graph, edge_list); + grin_destroy_edge_type(graph, edge_type); + grin_destroy_edge_list(graph, edge_list_2); +} + +int main() { + // load graph + std::cout << "load modern graph" << std::endl; + std::string graph_name = "modern_graph"; + char* graph_name_str = new char[graph_name.size() + 1]; + snprintf(graph_name_str, graph_name.size() + 1, "%s", graph_name.c_str()); + demo_storage_load_modern_graph(graph_name_str, 1, 0); + delete[] graph_name_str; + + // get grin graph + std::string uri = "demo_storage://" + graph_name; + std::cout << "get grin graph from uri: " << uri << std::endl; + char* uri_str = new char[uri.size() + 1]; + snprintf(uri_str, uri.size() + 1, "%s", uri.c_str()); + GRIN_GRAPH graph = grin_get_graph_from_storage(uri_str); + delete[] uri_str; + + // test vertex label + test_vertex_label(graph); + + // test edge label + test_edge_label(graph); + + // destroy graph + grin_destroy_graph(graph); + + return 0; +} diff --git a/demo_storage/test/test_partition.cc b/demo_storage/test/test_partition.cc new file mode 100644 index 0000000..e8a9f0a --- /dev/null +++ b/demo_storage/test/test_partition.cc @@ -0,0 +1,120 @@ +/** Copyright 2020 Alibaba Group Holding Limited. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +#include + +// predefine for GRIN +#include "../predefine.h" +// storage headers +#include "storage/loadmoderngraph.h" +// test config headers +#include "test/config.h" +// GRIN headers +#include "partition/partition.h" +#include "topology/structure.h" + +void test_partition_partition(GRIN_PARTITIONED_GRAPH pg, unsigned n) { + std::cout << "\n++++ test partition: partition ++++" << std::endl; + + // check partition number + ASSERT(pg != GRIN_NULL_GRAPH); + auto partition_num = grin_get_total_partitions_number(pg); + ASSERT(partition_num == n); + std::cout << "partition number = " << partition_num << std::endl; + + // check partition list + auto partition_list = grin_get_local_partition_list(pg); + ASSERT(partition_list != GRIN_NULL_PARTITION_LIST); + auto partition_list_size = grin_get_partition_list_size(pg, partition_list); + ASSERT(partition_list_size == 1); + std::cout << "local partition number = " << partition_list_size << std::endl; + + // check create new partition list + auto new_partition_list = grin_create_partition_list(pg); + ASSERT(new_partition_list != GRIN_NULL_PARTITION_LIST); + for (auto i = 0; i < partition_list_size; ++i) { + // get & insert partition + auto partition = grin_get_partition_from_list(pg, partition_list, i); + auto status = + grin_insert_partition_to_list(pg, new_partition_list, partition); + ASSERT(status == true); + // check & destroy partition + auto partition_from_new_list = + grin_get_partition_from_list(pg, new_partition_list, i); + ASSERT(grin_equal_partition(pg, partition, partition_from_new_list) == + true); + grin_destroy_partition(pg, partition); + grin_destroy_partition(pg, partition_from_new_list); + } + ASSERT(grin_get_partition_list_size(pg, new_partition_list) == + partition_list_size); + grin_destroy_partition_list(pg, new_partition_list); + + // check partition id + auto partition_a = grin_get_partition_from_list(pg, partition_list, 0); + auto id = grin_get_partition_id(pg, partition_a); + auto partition_b = grin_get_partition_by_id(pg, id); + ASSERT(grin_equal_partition(pg, partition_a, partition_b) == true); + grin_destroy_partition(pg, partition_a); + grin_destroy_partition(pg, partition_b); + + // check get local graph + for (auto i = 0; i < partition_list_size; ++i) { + // get local graph from partition + auto partition = grin_get_partition_from_list(pg, partition_list, i); + auto info = grin_get_partition_info(pg, partition); + std::cout << "info of local partition " << i << std::endl; + std::cout << " " << static_cast(info) << std::endl; + auto graph = grin_get_local_graph_by_partition(pg, partition); + ASSERT(graph != GRIN_NULL_GRAPH); + // destroy + grin_destroy_partition(pg, partition); + grin_destroy_graph(graph); + } + + // destroy + grin_destroy_partition_list(pg, partition_list); + std::cout << "---- test partition: partition completed ----" << std::endl; +} + +int main() { + // load graph + uint32_t partition_num = 4; + uint32_t partition_id = 0; + std::cout << "load modern graph, partition_num = " << partition_num + << ", partition_id = " << partition_id << std::endl; + std::string graph_name = "modern_graph"; + char* graph_name_str = new char[graph_name.size() + 1]; + snprintf(graph_name_str, graph_name.size() + 1, "%s", graph_name.c_str()); + demo_storage_load_modern_graph(graph_name_str, partition_num, partition_id); + delete[] graph_name_str; + + // get grin graph + std::string uri = "demo_storage://" + graph_name + + "?partition_num=" + std::to_string(partition_num); + std::cout << "get grin graph from uri: " << uri << std::endl; + char* uri_str = new char[uri.size() + 1]; + snprintf(uri_str, uri.size() + 1, "%s", uri.c_str()); + GRIN_PARTITIONED_GRAPH pg = grin_get_partitioned_graph_from_storage(uri_str); + delete[] uri_str; + + // test partitioned graph + test_partition_partition(pg, partition_num); + + // destroy partitioned graph + grin_destroy_partitioned_graph(pg); + + return 0; +} diff --git a/demo_storage/test/test_partition_reference.cc b/demo_storage/test/test_partition_reference.cc new file mode 100644 index 0000000..048ec68 --- /dev/null +++ b/demo_storage/test/test_partition_reference.cc @@ -0,0 +1,276 @@ +/** Copyright 2020 Alibaba Group Holding Limited. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +#include + +// predefine for GRIN +#include "../predefine.h" +// storage headers +#include "storage/loadmoderngraph.h" +// test config headers +#include "test/config.h" +// GRIN headers +#include "partition/partition.h" +#include "partition/reference.h" +#include "property/topology.h" +#include "property/type.h" +#include "topology/edgelist.h" +#include "topology/structure.h" +#include "topology/vertexlist.h" + +void test_vertex_ref(GRIN_PARTITIONED_GRAPH pg, GRIN_GRAPH graph, + GRIN_VERTEX v) { + std::cout << "\n== test vertex ref ==" << std::endl; + + // check vertex ref + auto vr = grin_get_vertex_ref_by_vertex(graph, v); + auto v_from_vr = grin_get_vertex_from_vertex_ref(graph, vr); + ASSERT(grin_equal_vertex(graph, v, v_from_vr) == true); + + // serialize & deserialize vertex ref + auto msg = grin_serialize_vertex_ref(graph, vr); + std::cout << "serialized vertex ref = " << msg << std::endl; + auto vr_from_msg = grin_deserialize_to_vertex_ref(graph, msg); + auto v_from_vr_from_msg = grin_get_vertex_from_vertex_ref(graph, vr_from_msg); + ASSERT(grin_equal_vertex(graph, v, v_from_vr_from_msg) == true); + + // serialize & deserialize vertex ref as int64 + auto int64_msg = grin_serialize_vertex_ref_as_int64(graph, vr); + std::cout << "serialized vertex ref as int64 = " << int64_msg << std::endl; + auto vr_from_int64_msg = + grin_deserialize_int64_to_vertex_ref(graph, int64_msg); + auto v_from_vr_from_int64_msg = + grin_get_vertex_from_vertex_ref(graph, vr_from_int64_msg); + ASSERT(grin_equal_vertex(graph, v, v_from_vr_from_int64_msg) == true); + + // check master or mirror + auto is_master = grin_is_master_vertex(graph, v); + auto is_mirror = grin_is_mirror_vertex(graph, v); + ASSERT((is_master || is_mirror) && !(is_master && is_mirror)); + if (is_master) { + std::cout << "vertex is master, "; + } else { + std::cout << "vertex is mirror, "; + } + // get master partition id + auto master_partition = grin_get_master_partition_from_vertex_ref(graph, vr); + auto master_partition_id = grin_get_partition_id(pg, master_partition); + std::cout << "master partition id = " << master_partition_id << std::endl; + // get mirror_partition_list + if (is_master) { + ASSERT(grin_get_mirror_vertex_mirror_partition_list(graph, v) == + GRIN_NULL_PARTITION_LIST); + auto partition_list = + grin_get_master_vertex_mirror_partition_list(graph, v); + + std::cout << "mirror partition ids = "; + auto partition_list_size = grin_get_partition_list_size(pg, partition_list); + for (auto i = 0; i < partition_list_size; ++i) { + auto partition = grin_get_partition_from_list(pg, partition_list, i); + auto partition_id = grin_get_partition_id(pg, partition); + std::cout << " " << partition_id; + grin_destroy_partition(pg, partition); + } + std::cout << std::endl; + + grin_destroy_partition_list(pg, partition_list); + + } else { + ASSERT(grin_get_master_vertex_mirror_partition_list(graph, v) == + GRIN_NULL_PARTITION_LIST); + auto partition_list = + grin_get_mirror_vertex_mirror_partition_list(graph, v); + + std::cout << "mirror partition ids = "; + auto partition_list_size = grin_get_partition_list_size(pg, partition_list); + for (auto i = 0; i < partition_list_size; ++i) { + auto partition = grin_get_partition_from_list(pg, partition_list, i); + auto partition_id = grin_get_partition_id(pg, partition); + std::cout << " " << partition_id; + grin_destroy_partition(pg, partition); + } + std::cout << std::endl; + + grin_destroy_partition_list(pg, partition_list); + } + + // destroy + grin_destroy_partition(graph, master_partition); + grin_destroy_vertex(graph, v_from_vr); + grin_destroy_vertex(graph, v_from_vr_from_msg); + grin_destroy_vertex(graph, v_from_vr_from_int64_msg); + grin_destroy_vertex_ref(graph, vr); + grin_destroy_vertex_ref(graph, vr_from_msg); + grin_destroy_vertex_ref(graph, vr_from_int64_msg); + grin_destroy_serialized_vertex_ref(graph, msg); +} + +void test_edge_ref(GRIN_PARTITIONED_GRAPH pg, GRIN_GRAPH graph, GRIN_EDGE e) { + std::cout << "\n== test edge ref ==" << std::endl; + + // check edge ref + auto er = grin_get_vertex_ref_by_vertex(graph, e); + auto e_from_er = grin_get_vertex_from_vertex_ref(graph, er); + ASSERT(grin_equal_vertex(graph, e, e_from_er) == true); + + // serialize & deserialize edge ref + auto msg = grin_serialize_vertex_ref(graph, er); + std::cout << "serialized edge ref = " << msg << std::endl; + auto er_from_msg = grin_deserialize_to_vertex_ref(graph, msg); + auto e_from_er_from_msg = grin_get_vertex_from_vertex_ref(graph, er_from_msg); + ASSERT(grin_equal_vertex(graph, e, e_from_er_from_msg) == true); + + // check master or mirror + auto is_master = grin_is_master_vertex(graph, e); + auto is_mirror = grin_is_mirror_vertex(graph, e); + ASSERT((is_master || is_mirror) && !(is_master && is_mirror)); + if (is_master) { + std::cout << "edge is master, "; + } else { + std::cout << "edgeis mirror, "; + } + // get master partition id + auto master_partition = grin_get_master_partition_from_edge_ref(graph, er); + auto master_partition_id = grin_get_partition_id(pg, master_partition); + std::cout << "master partition id = " << master_partition_id << std::endl; + // get mirror_partition_list + if (is_master) { + ASSERT(grin_get_mirror_edge_mirror_partition_list(graph, e) == + GRIN_NULL_PARTITION_LIST); + auto partition_list = grin_get_master_edge_mirror_partition_list(graph, e); + + std::cout << "mirror partition ids = "; + auto partition_list_size = grin_get_partition_list_size(pg, partition_list); + for (auto i = 0; i < partition_list_size; ++i) { + auto partition = grin_get_partition_from_list(pg, partition_list, i); + auto partition_id = grin_get_partition_id(pg, partition); + std::cout << " " << partition_id; + grin_destroy_partition(pg, partition); + } + std::cout << std::endl; + + grin_destroy_partition_list(pg, partition_list); + + } else { + ASSERT(grin_get_master_edge_mirror_partition_list(graph, e) == + GRIN_NULL_PARTITION_LIST); + auto partition_list = grin_get_mirror_edge_mirror_partition_list(graph, e); + + std::cout << "mirror partition ids = "; + auto partition_list_size = grin_get_partition_list_size(pg, partition_list); + for (auto i = 0; i < partition_list_size; ++i) { + auto partition = grin_get_partition_from_list(pg, partition_list, i); + auto partition_id = grin_get_partition_id(pg, partition); + std::cout << " " << partition_id; + grin_destroy_partition(pg, partition); + } + std::cout << std::endl; + + grin_destroy_partition_list(pg, partition_list); + } + + // destroy + grin_destroy_partition(graph, master_partition); + grin_destroy_vertex(graph, e_from_er); + grin_destroy_vertex(graph, e_from_er_from_msg); + grin_destroy_vertex_ref(graph, er); + grin_destroy_vertex_ref(graph, er_from_msg); + grin_destroy_serialized_vertex_ref(graph, msg); +} + +void test_partition_reference(GRIN_PARTITIONED_GRAPH pg, unsigned n) { + std::cout << "\n++++ test partition: reference ++++" << std::endl; + + // check partition number + ASSERT(pg != GRIN_NULL_GRAPH); + auto partition_num = grin_get_total_partitions_number(pg); + ASSERT(partition_num == n); + + // create a local graph + auto partition0 = grin_get_partition_by_id(pg, 0); + auto graph = grin_get_local_graph_by_partition(pg, partition0); + + // test vertex ref + auto vtype = grin_get_vertex_type_by_id(graph, 0); + auto vertex_list = grin_get_vertex_list_by_type(graph, vtype); + // get vertex 0 & test + if (grin_get_vertex_list_size(graph, vertex_list) > 0) { + auto v = grin_get_vertex_from_list(graph, vertex_list, 0); + test_vertex_ref(pg, graph, v); + grin_destroy_vertex(graph, v); + } + // get vertex 1 & test + if (grin_get_vertex_list_size(graph, vertex_list) > 1) { + auto v = grin_get_vertex_from_list(graph, vertex_list, 1); + test_vertex_ref(pg, graph, v); + grin_destroy_vertex(graph, v); + } + + // test edge ref + auto etype = grin_get_edge_type_by_id(graph, 0); + auto edge_list = grin_get_edge_list_by_type(graph, etype); + // get edge 0 & test + if (grin_get_edge_list_size(graph, edge_list) > 0) { + auto e = grin_get_edge_from_list(graph, edge_list, 0); + test_edge_ref(pg, graph, e); + grin_destroy_edge(graph, e); + } + // get edge 1 & test + if (grin_get_edge_list_size(graph, edge_list) > 1) { + auto e = grin_get_edge_from_list(graph, edge_list, 1); + test_edge_ref(pg, graph, e); + grin_destroy_edge(graph, e); + } + + // destroy + grin_destroy_partition(graph, partition0); + grin_destroy_graph(graph); + grin_destroy_vertex_list(graph, vertex_list); + grin_destroy_vertex_type(graph, vtype); + grin_destroy_edge_list(graph, edge_list); + grin_destroy_edge_type(graph, etype); + + std::cout << "---- test partition: reference completed ----" << std::endl; +} + +int main() { + // load graph + uint32_t partition_num = 4; + uint32_t partition_id = 0; + std::cout << "load modern graph, partition_num = " << partition_num + << ", partition_id = " << partition_id << std::endl; + std::string graph_name = "modern_graph"; + char* graph_name_str = new char[graph_name.size() + 1]; + snprintf(graph_name_str, graph_name.size() + 1, "%s", graph_name.c_str()); + demo_storage_load_modern_graph(graph_name_str, partition_num, partition_id); + delete[] graph_name_str; + + // get grin graph + std::string uri = "demo_storage://" + graph_name + + "?partition_num=" + std::to_string(partition_num); + std::cout << "get grin graph from uri: " << uri << std::endl; + char* uri_str = new char[uri.size() + 1]; + snprintf(uri_str, uri.size() + 1, "%s", uri.c_str()); + GRIN_PARTITIONED_GRAPH pg = grin_get_partitioned_graph_from_storage(uri_str); + delete[] uri_str; + + // test partitioned graph + test_partition_reference(pg, partition_num); + + // destroy partitioned graph + grin_destroy_partitioned_graph(pg); + + return 0; +} diff --git a/demo_storage/test/test_partition_topology.cc b/demo_storage/test/test_partition_topology.cc new file mode 100644 index 0000000..47bad3f --- /dev/null +++ b/demo_storage/test/test_partition_topology.cc @@ -0,0 +1,364 @@ +/** Copyright 2020 Alibaba Group Holding Limited. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +#include + +// predefine for GRIN +#include "../predefine.h" +// storage headers +#include "storage/loadmoderngraph.h" +// test config headers +#include "test/config.h" +// GRIN headers +#include "index/order.h" +#include "partition/partition.h" +#include "partition/reference.h" +#include "partition/topology.h" +#include "property/topology.h" +#include "property/type.h" +#include "topology/adjacentlist.h" +#include "topology/edgelist.h" +#include "topology/structure.h" +#include "topology/vertexlist.h" + +void check_vertex_list(GRIN_GRAPH g, GRIN_VERTEX_LIST vl) { + // check vertex list + auto vl_size = grin_get_vertex_list_size(g, vl); + auto vl_iter = grin_get_vertex_list_begin(g, vl); + for (auto i = 0; i < vl_size; ++i) { + auto v0 = grin_get_vertex_from_list(g, vl, i); + ASSERT(grin_is_vertex_list_end(g, vl_iter) == false); + auto v1 = grin_get_vertex_from_iter(g, vl_iter); + ASSERT(grin_equal_vertex(g, v0, v1) == true); + grin_get_next_vertex_list_iter(g, vl_iter); + // destroy vertex + grin_destroy_vertex(g, v0); + grin_destroy_vertex(g, v1); + } + ASSERT(grin_is_vertex_list_end(g, vl_iter) == true); + // destroy vertex list iter + grin_destroy_vertex_list_iter(g, vl_iter); + + std::cout << "(Correct) check vertex list succeed" << std::endl; + + // test vertex order in list + if (vl_size >= 2) { + size_t idx0 = 0, idx1 = 1; + auto v0 = grin_get_vertex_from_list(g, vl, idx0); + auto v1 = grin_get_vertex_from_list(g, vl, idx1); + ASSERT(grin_smaller_vertex(g, v0, v1) == true); + ASSERT(grin_smaller_vertex(g, v1, v0) == false); + size_t pos0 = grin_get_position_of_vertex_from_sorted_list(g, vl, v0); + size_t pos1 = grin_get_position_of_vertex_from_sorted_list(g, vl, v1); + ASSERT(pos0 == idx0); + ASSERT(pos1 == idx1); + + // destroy vertex + grin_destroy_vertex(g, v0); + grin_destroy_vertex(g, v1); + + std::cout << "(Correct) check vertex order succeed" << std::endl; + } +} + +void test_vertex_list(GRIN_PARTITIONED_GRAPH pg, GRIN_GRAPH graph) { + std::cout << "\n== test vertex list ==" << std::endl; + // get vertex list + auto type = grin_get_vertex_type_by_name(graph, "person"); + auto vertex_list = grin_get_vertex_list_by_type(graph, type); + auto vertex_list_size = grin_get_vertex_list_size(graph, vertex_list); + std::cout << "vertex list for \"person\", size = " << vertex_list_size + << std::endl; + + // select master + auto master_vertex_list = + grin_get_vertex_list_by_type_select_master(graph, type); + auto master_vertex_list_size = + grin_get_vertex_list_size(graph, master_vertex_list); + std::cout << "master vertex list size = " << master_vertex_list_size + << std::endl; + check_vertex_list(graph, master_vertex_list); + + // select mirror + auto mirror_vertex_list = + grin_get_vertex_list_by_type_select_mirror(graph, type); + auto mirror_vertex_list_size = + grin_get_vertex_list_size(graph, mirror_vertex_list); + std::cout << "mirror vertex list size = " << mirror_vertex_list_size + << std::endl; + check_vertex_list(graph, mirror_vertex_list); + + // check vertex number + ASSERT(vertex_list_size == master_vertex_list_size + mirror_vertex_list_size); + + // select by partition + auto partition1 = grin_get_partition_by_id(pg, 1); + auto vertex_list1 = + grin_get_vertex_list_by_type_select_partition(graph, type, partition1); + auto vertex_list1_size = grin_get_vertex_list_size(graph, vertex_list1); + std::cout << "vertex list size of partition 1 = " << vertex_list1_size + << std::endl; + check_vertex_list(graph, vertex_list1); + + // destroy + grin_destroy_partition(graph, partition1); + grin_destroy_vertex_list(graph, vertex_list); + grin_destroy_vertex_list(graph, master_vertex_list); + grin_destroy_vertex_list(graph, mirror_vertex_list); + grin_destroy_vertex_list(graph, vertex_list1); + grin_destroy_vertex_type(graph, type); +} + +void check_edge_list(GRIN_GRAPH graph, GRIN_EDGE_LIST edge_list) { + // check edge list + auto el_size = grin_get_edge_list_size(graph, edge_list); + auto el_iter = grin_get_edge_list_begin(graph, edge_list); + for (auto i = 0; i < el_size; ++i) { + auto e0 = grin_get_edge_from_list(graph, edge_list, i); + ASSERT(grin_is_edge_list_end(graph, el_iter) == false); + auto e1 = grin_get_edge_from_iter(graph, el_iter); + grin_get_next_edge_list_iter(graph, el_iter); + auto v0_1 = grin_get_src_vertex_from_edge(graph, e0); + auto v0_2 = grin_get_dst_vertex_from_edge(graph, e0); + auto v1_1 = grin_get_src_vertex_from_edge(graph, e1); + auto v1_2 = grin_get_dst_vertex_from_edge(graph, e1); + ASSERT(grin_equal_vertex(graph, v0_1, v1_1) == true); + ASSERT(grin_equal_vertex(graph, v0_2, v1_2) == true); + // destroy vertex + grin_destroy_vertex(graph, v0_1); + grin_destroy_vertex(graph, v0_2); + grin_destroy_vertex(graph, v1_1); + grin_destroy_vertex(graph, v1_2); + // destroy edge + grin_destroy_edge(graph, e0); + grin_destroy_edge(graph, e1); + } + + ASSERT(grin_is_edge_list_end(graph, el_iter) == true); + // destroy edge list iter + grin_destroy_edge_list_iter(graph, el_iter); + + std::cout << "(Correct) check edge list succeed" << std::endl; +} + +void test_edge_list(GRIN_PARTITIONED_GRAPH pg, GRIN_GRAPH graph) { + std::cout << "\n== test edge list ==" << std::endl; + // get edge list + auto type = grin_get_edge_type_by_name(graph, "created"); + auto edge_list = grin_get_edge_list_by_type(graph, type); + auto edge_list_size = grin_get_edge_list_size(graph, edge_list); + std::cout << "edge list for \"created\", size = " << edge_list_size + << std::endl; + + // select master + auto master_edge_list = grin_get_edge_list_by_type_select_master(graph, type); + auto master_edge_list_size = grin_get_edge_list_size(graph, master_edge_list); + std::cout << "master edge list size = " << master_edge_list_size << std::endl; + check_edge_list(graph, master_edge_list); + + // select mirror + auto mirror_edge_list = grin_get_edge_list_by_type_select_mirror(graph, type); + auto mirror_edge_list_size = grin_get_edge_list_size(graph, mirror_edge_list); + std::cout << "mirror edge list size = " << mirror_edge_list_size << std::endl; + check_edge_list(graph, mirror_edge_list); + + // check edge number + ASSERT(edge_list_size == master_edge_list_size + mirror_edge_list_size); + + // select by partition + auto partition1 = grin_get_partition_by_id(pg, 1); + auto edge_list1 = + grin_get_edge_list_by_type_select_partition(graph, type, partition1); + auto edge_list1_size = grin_get_edge_list_size(graph, edge_list1); + std::cout << "edge list size of partition 1 = " << edge_list1_size + << std::endl; + check_edge_list(graph, edge_list1); + + // destroy + grin_destroy_partition(graph, partition1); + grin_destroy_edge_list(graph, edge_list); + grin_destroy_edge_list(graph, master_edge_list); + grin_destroy_edge_list(graph, mirror_edge_list); + grin_destroy_edge_list(graph, edge_list1); + grin_destroy_edge_type(graph, type); +} + +void check_adjacency_list(GRIN_GRAPH graph, GRIN_ADJACENT_LIST adj_list) { + // check adjacency list + auto al_size = grin_get_adjacent_list_size(graph, adj_list); + auto al_iter = grin_get_adjacent_list_begin(graph, adj_list); + for (auto i = 0; i < al_size; ++i) { + auto e0 = grin_get_edge_from_adjacent_list(graph, adj_list, i); + auto nbr0 = grin_get_neighbor_from_adjacent_list(graph, adj_list, i); + ASSERT(grin_is_adjacent_list_end(graph, al_iter) == false); + auto e1 = grin_get_edge_from_adjacent_list_iter(graph, al_iter); + auto nbr1 = grin_get_neighbor_from_adjacent_list_iter(graph, al_iter); + grin_get_next_adjacent_list_iter(graph, al_iter); + auto v0_1 = grin_get_src_vertex_from_edge(graph, e0); + auto v0_2 = grin_get_dst_vertex_from_edge(graph, e0); + auto v1_1 = grin_get_src_vertex_from_edge(graph, e1); + auto v1_2 = grin_get_dst_vertex_from_edge(graph, e1); + ASSERT(grin_equal_vertex(graph, v0_1, v1_1) == true); + ASSERT(grin_equal_vertex(graph, v0_2, v1_2) == true); + ASSERT(grin_equal_vertex(graph, nbr0, nbr1) == true); + // destroy vertex + grin_destroy_vertex(graph, v0_1); + grin_destroy_vertex(graph, v0_2); + grin_destroy_vertex(graph, v1_1); + grin_destroy_vertex(graph, v1_2); + grin_destroy_vertex(graph, nbr0); + grin_destroy_vertex(graph, nbr1); + // destroy edge + grin_destroy_edge(graph, e0); + grin_destroy_edge(graph, e1); + } + + ASSERT(grin_is_adjacent_list_end(graph, al_iter) == true); + // destroy adjacency list iter + grin_destroy_adjacent_list_iter(graph, al_iter); + + std::cout << "(Correct) check adjacency list succeed" << std::endl; +} + +void test_adjacency_list(GRIN_PARTITIONED_GRAPH pg, GRIN_GRAPH graph, + GRIN_VERTEX vertex, GRIN_DIRECTION dir) { + std::cout << "\n== test adjacency list: "; + if (dir == GRIN_DIRECTION::IN) + std::cout << "IN ==" << std::endl; + else if (dir == GRIN_DIRECTION::OUT) + std::cout << "OUT ==" << std::endl; + else + std::cout << "BOTH ==" << std::endl; + + // get adjacency list + auto edge_type = grin_get_edge_type_by_name(graph, "knows"); + auto adj_list = + grin_get_adjacent_list_by_edge_type(graph, dir, vertex, edge_type); + auto al_size = grin_get_adjacent_list_size(graph, adj_list); + std::cout << "adjacency list of \"knows\" for vertex #3, size = " << al_size + << std::endl; + + // select master + auto master_adj_list = + grin_get_adjacent_list_by_edge_type_select_master_neighbor( + graph, dir, vertex, edge_type); + auto master_al_size = grin_get_adjacent_list_size(graph, master_adj_list); + std::cout << "master adjacency list size = " << master_al_size << std::endl; + check_adjacency_list(graph, master_adj_list); + + // select mirror + auto mirror_adj_list = + grin_get_adjacent_list_by_edge_type_select_mirror_neighbor( + graph, dir, vertex, edge_type); + auto mirror_al_size = grin_get_adjacent_list_size(graph, mirror_adj_list); + std::cout << "mirror adjacency list size = " << mirror_al_size << std::endl; + check_adjacency_list(graph, mirror_adj_list); + + // check adjacency list size + ASSERT(al_size == master_al_size + mirror_al_size); + + // select by partition + auto partition1 = grin_get_partition_by_id(pg, 2); + auto adj_list2 = + grin_get_adjacent_list_by_edge_type_select_partition_neighbor( + graph, dir, vertex, edge_type, partition1); + auto adj_list2_size = grin_get_adjacent_list_size(graph, adj_list2); + std::cout << "adjacency list size of partition 2 = " << adj_list2_size + << std::endl; + check_adjacency_list(graph, adj_list2); + + // destroy + grin_destroy_partition(graph, partition1); + grin_destroy_adjacent_list(graph, adj_list); + grin_destroy_adjacent_list(graph, master_adj_list); + grin_destroy_adjacent_list(graph, mirror_adj_list); + grin_destroy_adjacent_list(graph, adj_list2); + grin_destroy_edge_type(graph, edge_type); +} + +void test_partition_topology(GRIN_PARTITIONED_GRAPH pg, unsigned n) { + std::cout << "\n++++ test partition: topology ++++" << std::endl; + + // check partition number + ASSERT(pg != GRIN_NULL_GRAPH); + auto partition_num = grin_get_total_partitions_number(pg); + ASSERT(partition_num == n); + + // local partitions + auto partition_list = grin_get_local_partition_list(pg); + ASSERT(partition_list != GRIN_NULL_PARTITION_LIST); + auto partition_list_size = grin_get_partition_list_size(pg, partition_list); + ASSERT(partition_list_size == 1); + + for (auto idx = 0; idx < partition_list_size; ++idx) { + auto partition_id = grin_get_partition_from_list(pg, partition_list, idx); + std::cout << "partition id = " << partition_id << std::endl; + // create a local graph + auto partition = grin_get_partition_by_id(pg, partition_id); + auto graph = grin_get_local_graph_by_partition(pg, partition); + + // get vertex + auto vtype = grin_get_vertex_type_by_name(graph, "person"); + auto vertex_list = grin_get_vertex_list_by_type(graph, vtype); + auto vertex = grin_get_vertex_from_list(graph, vertex_list, 3); + + // test + test_vertex_list(pg, graph); + test_edge_list(pg, graph); + test_adjacency_list(pg, graph, vertex, GRIN_DIRECTION::IN); + test_adjacency_list(pg, graph, vertex, GRIN_DIRECTION::OUT); + test_adjacency_list(pg, graph, vertex, GRIN_DIRECTION::BOTH); + + // destroy + grin_destroy_vertex_type(graph, vtype); + grin_destroy_vertex_list(graph, vertex_list); + grin_destroy_vertex(graph, vertex); + grin_destroy_partition(pg, partition); + grin_destroy_graph(graph); + } + + grin_destroy_partition_list(pg, partition_list); + std::cout << "\n---- test partition: topology completed ----" << std::endl; +} + +int main() { + // load graph + uint32_t partition_num = 4; + uint32_t partition_id = 0; + std::cout << "load modern graph, partition_num = " << partition_num + << ", partition_id = " << partition_id << std::endl; + std::string graph_name = "modern_graph"; + char* graph_name_str = new char[graph_name.size() + 1]; + snprintf(graph_name_str, graph_name.size() + 1, "%s", graph_name.c_str()); + demo_storage_load_modern_graph(graph_name_str, partition_num, partition_id); + delete[] graph_name_str; + + // get grin graph + std::string uri = "demo_storage://" + graph_name + + "?partition_num=" + std::to_string(partition_num); + std::cout << "get grin graph from uri: " << uri << std::endl; + char* uri_str = new char[uri.size() + 1]; + snprintf(uri_str, uri.size() + 1, "%s", uri.c_str()); + GRIN_PARTITIONED_GRAPH pg = grin_get_partitioned_graph_from_storage(uri_str); + delete[] uri_str; + + // test partitioned graph + test_partition_topology(pg, partition_num); + + // destroy partitioned graph + grin_destroy_partitioned_graph(pg); + + return 0; +} diff --git a/demo_storage/test/test_property_list.cc b/demo_storage/test/test_property_list.cc new file mode 100644 index 0000000..e6587cb --- /dev/null +++ b/demo_storage/test/test_property_list.cc @@ -0,0 +1,226 @@ +/** Copyright 2020 Alibaba Group Holding Limited. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +#include + +// predefine for GRIN +#include "../predefine.h" +// storage headers +#include "storage/loadmoderngraph.h" +// test config headers +#include "test/config.h" +// GRIN headers +#include "property/property.h" +#include "property/propertylist.h" +#include "property/type.h" +#include "topology/edgelist.h" +#include "topology/structure.h" +#include "topology/vertexlist.h" + +void test_vertex_property(GRIN_GRAPH graph, GRIN_VERTEX_PROPERTY property, + GRIN_VERTEX_TYPE vertex_type) { + // get property name + auto name = grin_get_vertex_property_name(graph, vertex_type, property); + std::cout << "name of vertex property: " << name << std::endl; + + // get property data type + auto data_type = grin_get_vertex_property_datatype(graph, property); + std::cout << "data type of vertex property: " << data_type << std::endl; + + // get vertex type from property + auto vertex_type2 = grin_get_vertex_type_from_property(graph, property); + ASSERT(grin_equal_vertex_type(graph, vertex_type, vertex_type2) == true); + + // get vertex property by name + auto property2 = grin_get_vertex_property_by_name(graph, vertex_type, name); + ASSERT(grin_equal_vertex_property(graph, property, property2) == true); + + // get vertex property by id + auto id = grin_get_vertex_property_id(graph, vertex_type, property); + auto property3 = grin_get_vertex_property_by_id(graph, vertex_type, id); + ASSERT(grin_equal_vertex_property(graph, property, property3) == true); + + // get vertex properties by name + auto property_list = grin_get_vertex_properties_by_name(graph, name); + auto n = grin_get_vertex_property_list_size(graph, property_list); + std::cout << "number of vertex properties with this name: " << n << std::endl; + + // destroy + grin_destroy_vertex_property(graph, property2); + grin_destroy_vertex_property(graph, property3); + grin_destroy_vertex_type(graph, vertex_type2); + grin_destroy_vertex_property_list(graph, property_list); +} + +void test_vertex_property_list(GRIN_GRAPH graph) { + std::cout << "\n++++ test property: property list (vertex) ++++" << std::endl; + + auto vertex_type_list = grin_get_vertex_type_list(graph); + for (auto i = 0; i < grin_get_vertex_type_list_size(graph, vertex_type_list); + i++) { + // get property list from vertex type + auto vertex_type = + grin_get_vertex_type_from_list(graph, vertex_type_list, i); + auto property_list = + grin_get_vertex_property_list_by_type(graph, vertex_type); + size_t n = grin_get_vertex_property_list_size(graph, property_list); + + std::cout << "\n==== test property: property (vertex) ++++" << std::endl; + std::cout << "size of property list of vtype " << i << ": " << n + << std::endl; + + // create property list + auto new_property_list = grin_create_vertex_property_list(graph); + + for (auto i = 0; i < n; i++) { + // get property from property list + auto property = + grin_get_vertex_property_from_list(graph, property_list, i); + // test methods on property + test_vertex_property(graph, property, vertex_type); + // insert property to property list + auto status = grin_insert_vertex_property_to_list( + graph, new_property_list, property); + ASSERT(status == true); + // destroy property + grin_destroy_vertex_property(graph, property); + } + + // compare size + ASSERT(grin_get_vertex_property_list_size(graph, new_property_list) == n); + + // destroy + grin_destroy_vertex_type(graph, vertex_type); + grin_destroy_vertex_property_list(graph, property_list); + grin_destroy_vertex_property_list(graph, new_property_list); + } + + // destroy + grin_destroy_vertex_type_list(graph, vertex_type_list); + + std::cout << "---- test property: property list (vertex) completed ----" + << std::endl; +} + +void test_edge_property(GRIN_GRAPH graph, GRIN_EDGE_PROPERTY property, + GRIN_EDGE_TYPE edge_type) { + // get property name + auto name = grin_get_edge_property_name(graph, edge_type, property); + std::cout << "name of edge property: " << name << std::endl; + + // get property data type + auto data_type = grin_get_edge_property_datatype(graph, property); + std::cout << "data type of edge property: " << data_type << std::endl; + + // get edge type from property + auto edge_type2 = grin_get_edge_type_from_property(graph, property); + ASSERT(grin_equal_edge_type(graph, edge_type, edge_type2) == true); + + // get edge property by name + auto property2 = grin_get_edge_property_by_name(graph, edge_type, name); + ASSERT(grin_equal_edge_property(graph, property, property2) == true); + + // get edge property by id + auto id = grin_get_edge_property_id(graph, edge_type, property); + auto property3 = grin_get_edge_property_by_id(graph, edge_type, id); + ASSERT(grin_equal_edge_property(graph, property, property3) == true); + + // get edge properties by name + auto property_list = grin_get_edge_properties_by_name(graph, name); + auto n = grin_get_edge_property_list_size(graph, property_list); + std::cout << "number of edge properties with this name: " << n << std::endl; + + // destroy + grin_destroy_edge_type(graph, edge_type2); + grin_destroy_edge_property(graph, property2); + grin_destroy_edge_property(graph, property3); + grin_destroy_edge_property_list(graph, property_list); +} + +void test_edge_property_list(GRIN_GRAPH graph) { + std::cout << "\n++++ test property: property list (edge) ++++" << std::endl; + + auto edge_type_list = grin_get_edge_type_list(graph); + for (auto i = 0; i < grin_get_edge_type_list_size(graph, edge_type_list); + i++) { + // get property list from edge type + auto edge_type = grin_get_edge_type_from_list(graph, edge_type_list, i); + auto property_list = grin_get_edge_property_list_by_type(graph, edge_type); + size_t n = grin_get_edge_property_list_size(graph, property_list); + + std::cout << "\n==== test property: property (edge) ++++" << std::endl; + std::cout << "size of property list of etype " << i << ": " << n + << std::endl; + + // create property list + auto new_property_list = grin_create_edge_property_list(graph); + + for (auto i = 0; i < n; i++) { + // get property from property list + auto property = grin_get_edge_property_from_list(graph, property_list, i); + // test methods on property + test_edge_property(graph, property, edge_type); + // insert property to property list + auto status = + grin_insert_edge_property_to_list(graph, new_property_list, property); + ASSERT(status == true); + // destroy property + grin_destroy_edge_property(graph, property); + } + + // compare size + ASSERT(grin_get_edge_property_list_size(graph, new_property_list) == n); + + // destroy + grin_destroy_edge_type(graph, edge_type); + grin_destroy_edge_property_list(graph, property_list); + grin_destroy_edge_property_list(graph, new_property_list); + } + + // destroy + grin_destroy_edge_type_list(graph, edge_type_list); + + std::cout << "---- test property: property list (edge) completed ----" + << std::endl; +} + +int main() { + // load graph + std::cout << "load modern graph" << std::endl; + std::string graph_name = "modern_graph"; + char* graph_name_str = new char[graph_name.size() + 1]; + snprintf(graph_name_str, graph_name.size() + 1, "%s", graph_name.c_str()); + demo_storage_load_modern_graph(graph_name_str, 1, 0); + delete[] graph_name_str; + + // get grin graph + std::string uri = "demo_storage://" + graph_name; + std::cout << "get grin graph from uri: " << uri << std::endl; + char* uri_str = new char[uri.size() + 1]; + snprintf(uri_str, uri.size() + 1, "%s", uri.c_str()); + GRIN_GRAPH graph = grin_get_graph_from_storage(uri_str); + delete[] uri_str; + + // test vertex property list + test_vertex_property_list(graph); + + // test edge property list + test_edge_property_list(graph); + + // destroy graph + grin_destroy_graph(graph); + + return 0; +} diff --git a/demo_storage/test/test_property_primarykey.cc b/demo_storage/test/test_property_primarykey.cc new file mode 100644 index 0000000..a3bff07 --- /dev/null +++ b/demo_storage/test/test_property_primarykey.cc @@ -0,0 +1,180 @@ +/** Copyright 2020 Alibaba Group Holding Limited. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +#include + +// predefine for GRIN +#include "../predefine.h" +// storage headers +#include "storage/loadmoderngraph.h" +// test config headers +#include "test/config.h" +// GRIN headers +#include "property/primarykey.h" +#include "property/property.h" +#include "property/propertylist.h" +#include "property/row.h" +#include "property/topology.h" +#include "property/type.h" +#include "topology/edgelist.h" +#include "topology/structure.h" +#include "topology/vertexlist.h" + +void test_vertex_property_primarykey(GRIN_GRAPH graph) { + std::cout << "\n++++ test property: primarykey (vertex) ++++" << std::endl; + + // get vertex types with primary key + auto primary_vertex_type_list = + grin_get_vertex_types_with_primary_keys(graph); + size_t n = grin_get_vertex_type_list_size(graph, primary_vertex_type_list); + std::cout << "number of vertex types with primary keys: " << n << std::endl; + + for (auto idx = 0; idx < n; ++idx) { + // get vertex type + auto vertex_type = + grin_get_vertex_type_from_list(graph, primary_vertex_type_list, idx); + std::cout << "\n---- test vertex type with primary key: " + << grin_get_vertex_type_name(graph, vertex_type) << " ----" + << std::endl; + + // get the property list for primary key + auto property_list = + grin_get_primary_keys_by_vertex_type(graph, vertex_type); + std::cout << "size of property list for primary key: " + << grin_get_vertex_property_list_size(graph, property_list) + << std::endl; + + // get row of primary keys for vertex A + std::cout << "get row of primary keys for vertex #0" << std::endl; + + auto vertex_list = grin_get_vertex_list_by_type(graph, vertex_type); + auto vertex = grin_get_vertex_from_list(graph, vertex_list, 0); + auto row = grin_get_vertex_primary_keys_row(graph, vertex); + + auto property_list_size = + grin_get_vertex_property_list_size(graph, property_list); + for (auto i = 0; i < property_list_size; ++i) { + auto property = + grin_get_vertex_property_from_list(graph, property_list, i); + ASSERT(grin_get_vertex_property_datatype(graph, property) == + GRIN_DATATYPE::Int64); + auto value = + grin_get_vertex_property_value_of_int64(graph, vertex, property); + auto value_in_row = grin_get_int64_from_row(graph, row, i); + ASSERT(value == value_in_row); + std::cout << "primary key: " + << grin_get_vertex_property_name(graph, vertex_type, property) + << ", value: " << value << std::endl; + grin_destroy_vertex_property(graph, property); + } + + // destroy + grin_destroy_vertex_property_list(graph, property_list); + grin_destroy_vertex_type(graph, vertex_type); + grin_destroy_vertex_list(graph, vertex_list); + grin_destroy_vertex(graph, vertex); + grin_destroy_row(graph, row); + } + // destroy vertex type list + grin_destroy_vertex_type_list(graph, primary_vertex_type_list); + + std::cout << "---- test property: primarykey (vertex) completed ----" + << std::endl; +} + +void test_edge_property_primarykey(GRIN_GRAPH graph) { + std::cout << "\n++++ test property: primarykey (edge) ++++" << std::endl; + + // get edge types with primary key + auto primary_edge_type_list = grin_get_edge_types_with_primary_keys(graph); + size_t n = grin_get_edge_type_list_size(graph, primary_edge_type_list); + std::cout << "number of edge types with primary keys: " << n << std::endl; + + for (auto idx = 0; idx < n; ++idx) { + // get edge type + auto edge_type = + grin_get_edge_type_from_list(graph, primary_edge_type_list, idx); + std::cout << "\n---- test edge type with primary key: " + << grin_get_edge_type_name(graph, edge_type) << " ----" + << std::endl; + + // get the property list for primary key + auto property_list = grin_get_primary_keys_by_edge_type(graph, edge_type); + std::cout << "size of property list for primary key: " + << grin_get_edge_property_list_size(graph, property_list) + << std::endl; + + // get row of primary keys for edge A + std::cout << "get row of primary keys for edge #0" << std::endl; + + auto edge_list = grin_get_edge_list_by_type(graph, edge_type); + auto edge = grin_get_edge_from_list(graph, edge_list, 0); + auto row = grin_get_edge_primary_keys_row(graph, edge); + + auto property_list_size = + grin_get_edge_property_list_size(graph, property_list); + for (auto i = 0; i < property_list_size; ++i) { + auto property = grin_get_edge_property_from_list(graph, property_list, i); + ASSERT(grin_get_edge_property_datatype(graph, property) == + GRIN_DATATYPE::Int64); + auto value = grin_get_edge_property_value_of_int64(graph, edge, property); + auto value_in_row = grin_get_int64_from_row(graph, row, i); + ASSERT(value == value_in_row); + std::cout << "primary key: " + << grin_get_edge_property_name(graph, edge_type, property) + << ", value: " << value << std::endl; + grin_destroy_edge_property(graph, property); + } + + // destroy + grin_destroy_edge_property_list(graph, property_list); + grin_destroy_edge_type(graph, edge_type); + grin_destroy_edge_list(graph, edge_list); + grin_destroy_edge(graph, edge); + grin_destroy_row(graph, row); + } + // destroy edge type list + grin_destroy_edge_type_list(graph, primary_edge_type_list); + + std::cout << "---- test property: primarykey (edge) completed ----" + << std::endl; +} + +int main() { + // load graph + std::cout << "load modern graph" << std::endl; + std::string graph_name = "modern_graph"; + char* graph_name_str = new char[graph_name.size() + 1]; + snprintf(graph_name_str, graph_name.size() + 1, "%s", graph_name.c_str()); + demo_storage_load_modern_graph(graph_name_str, 1, 0); + delete[] graph_name_str; + + // get grin graph + std::string uri = "demo_storage://" + graph_name; + std::cout << "get grin graph from uri: " << uri << std::endl; + char* uri_str = new char[uri.size() + 1]; + snprintf(uri_str, uri.size() + 1, "%s", uri.c_str()); + GRIN_GRAPH graph = grin_get_graph_from_storage(uri_str); + delete[] uri_str; + + // test property primary key + test_vertex_property_primarykey(graph); + test_edge_property_primarykey(graph); + + // destroy graph + grin_destroy_graph(graph); + + return 0; +} diff --git a/demo_storage/test/test_property_topology.cc b/demo_storage/test/test_property_topology.cc new file mode 100644 index 0000000..9a7dd59 --- /dev/null +++ b/demo_storage/test/test_property_topology.cc @@ -0,0 +1,196 @@ +/** Copyright 2020 Alibaba Group Holding Limited. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +#include + +// predefine for GRIN +#include "../predefine.h" +// storage headers +#include "storage/loadmoderngraph.h" +// test config headers +#include "test/config.h" +// GRIN headers +#include "property/topology.h" +#include "property/type.h" +#include "topology/adjacentlist.h" +#include "topology/edgelist.h" +#include "topology/structure.h" +#include "topology/vertexlist.h" + +void test_property_topology_vertex(GRIN_GRAPH graph) { + std::cout << "\n++++ test property: topology (vertex) ++++" << std::endl; + + // get vertex type list + auto vertex_type_list = grin_get_vertex_type_list(graph); + size_t n = grin_get_vertex_type_list_size(graph, vertex_type_list); + std::cout << "size of vertex type list = " << n << std::endl; + + for (auto i = 0; i < n; i++) { + std::cout << "\n== vertex type " << i << ": ==" << std::endl; + + // get vertex type from vertex type list + auto vertex_type = + grin_get_vertex_type_from_list(graph, vertex_type_list, i); + auto name = grin_get_vertex_type_name(graph, vertex_type); + size_t m = grin_get_vertex_num_by_type(graph, vertex_type); + std::cout << "name of vertex type " << i << ": " << name << std::endl; + std::cout << "vertex num of vertex type " << i << " = " << m << std::endl; + + // select vertex list + auto select_vertex_list = grin_get_vertex_list_by_type(graph, vertex_type); + std::cout << "size of vertex list of vertex type " << i << " = " + << grin_get_vertex_list_size(graph, select_vertex_list) + << std::endl; + ASSERT(grin_get_vertex_list_size(graph, select_vertex_list) == m); + + // destroy + grin_destroy_vertex_type(graph, vertex_type); + grin_destroy_vertex_list(graph, select_vertex_list); + } + + // destroy + grin_destroy_vertex_type_list(graph, vertex_type_list); + + std::cout << "---- test property: topology (vertex) completed ----" + << std::endl; +} + +void test_property_topology_edge(GRIN_GRAPH graph) { + std::cout << "\n++++ test property: topology (edge) ++++" << std::endl; + + // get edge type list + auto edge_type_list = grin_get_edge_type_list(graph); + size_t n = grin_get_edge_type_list_size(graph, edge_type_list); + std::cout << "size of edge type list = " << n << std::endl; + + for (auto i = 0; i < n; i++) { + std::cout << "\n== edge type " << i << ": ==" << std::endl; + + // get edge type from edge type list + auto edge_type = grin_get_edge_type_from_list(graph, edge_type_list, i); + size_t m = grin_get_edge_num_by_type(graph, edge_type); + std::cout << "edge num of edge type " << i << " = " << m << std::endl; + auto name = grin_get_edge_type_name(graph, edge_type); + std::cout << "name of edge type " << i << ": " << name << std::endl; + + // select edge list + auto select_edge_list = grin_get_edge_list_by_type(graph, edge_type); + auto it = grin_get_edge_list_begin(graph, select_edge_list); + auto count = 0; + while (grin_is_edge_list_end(graph, it) == false) { + grin_get_next_edge_list_iter(graph, it); + count++; + } + ASSERT(count == m); + std::cout << "size of edge list of edge type " << i << " = " << m + << std::endl; + + // destroy + grin_destroy_edge_list_iter(graph, it); + grin_destroy_edge_list(graph, select_edge_list); + grin_destroy_edge_type(graph, edge_type); + } + + // destroy + grin_destroy_edge_type_list(graph, edge_type_list); + + std::cout << "---- test property: topology (edge) completed ----" + << std::endl; +} + +void test_property_topology_adj_list(GRIN_GRAPH graph) { + std::cout << "\n++++ test property: topology (adj_list) ++++" << std::endl; + + // get edge type list + auto edge_type_list = grin_get_edge_type_list(graph); + size_t ne = grin_get_edge_type_list_size(graph, edge_type_list); + std::cout << "size of edge type list = " << ne << std::endl; + + // get vertex type list + auto vertex_type_list = grin_get_vertex_type_list(graph); + size_t nv = grin_get_vertex_type_list_size(graph, vertex_type_list); + std::cout << "size of vertex type list = " << nv << std::endl; + + // get vertex + auto vtype = grin_get_vertex_type_by_id(graph, 0); + auto vertex_list = grin_get_vertex_list_by_type(graph, vtype); + auto v = grin_get_vertex_from_list(graph, vertex_list, 3); + + // get adj list of vertex + for (auto i = 0; i < ne; i++) { + std::cout << "\n== edge type " << i << ": ==" << std::endl; + + // get edge type from edge type list + auto edge_type = grin_get_edge_type_from_list(graph, edge_type_list, i); + + // get adj list by edge type + auto select_adj_list = grin_get_adjacent_list_by_edge_type( + graph, GRIN_DIRECTION::BOTH, v, edge_type); + auto adj_list_it = grin_get_adjacent_list_begin(graph, select_adj_list); + auto adj_list_size = 0; + while (grin_is_adjacent_list_end(graph, adj_list_it) == false) { + grin_get_next_adjacent_list_iter(graph, adj_list_it); + adj_list_size++; + } + std::cout << "adj list size (BOTH) of edge type " << i + << " for vertex #3 = " << adj_list_size << std::endl; + + // destroy + grin_destroy_adjacent_list_iter(graph, adj_list_it); + grin_destroy_adjacent_list(graph, select_adj_list); + grin_destroy_edge_type(graph, edge_type); + } + + // destroy + grin_destroy_vertex_list(graph, vertex_list); + grin_destroy_vertex_type(graph, vtype); + grin_destroy_vertex_type_list(graph, vertex_type_list); + grin_destroy_edge_type_list(graph, edge_type_list); + + std::cout << "---- test property: topology (adj_list) completed ----" + << std::endl; +} + +int main() { + // load graph + std::cout << "load modern graph" << std::endl; + std::string graph_name = "modern_graph"; + char* graph_name_str = new char[graph_name.size() + 1]; + snprintf(graph_name_str, graph_name.size() + 1, "%s", graph_name.c_str()); + demo_storage_load_modern_graph(graph_name_str, 1, 0); + delete[] graph_name_str; + + // get grin graph + std::string uri = "demo_storage://" + graph_name; + std::cout << "get grin graph from uri: " << uri << std::endl; + char* uri_str = new char[uri.size() + 1]; + snprintf(uri_str, uri.size() + 1, "%s", uri.c_str()); + GRIN_GRAPH graph = grin_get_graph_from_storage(uri_str); + delete[] uri_str; + + // test property topology (vertex) + test_property_topology_vertex(graph); + + // test property topology (edge) + test_property_topology_edge(graph); + + // test property topology (adj_list) + test_property_topology_adj_list(graph); + + // destroy graph + grin_destroy_graph(graph); + + return 0; +} diff --git a/demo_storage/test/test_property_type.cc b/demo_storage/test/test_property_type.cc new file mode 100644 index 0000000..7340148 --- /dev/null +++ b/demo_storage/test/test_property_type.cc @@ -0,0 +1,244 @@ +/** Copyright 2020 Alibaba Group Holding Limited. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +#include +#include + +// predefine for GRIN +#include "../predefine.h" +// storage headers +#include "storage/loadmoderngraph.h" +// test config headers +#include "test/config.h" +// GRIN headers +#include "property/topology.h" +#include "property/type.h" +#include "topology/edgelist.h" +#include "topology/structure.h" +#include "topology/vertexlist.h" + +void test_property_type_vertex(GRIN_GRAPH graph) { + std::cout << "\n== test vertex type ==" << std::endl; + + // get vertex type from vertex + auto vtype = grin_get_vertex_type_by_id(graph, 0); + auto vertex_list = grin_get_vertex_list_by_type(graph, vtype); + size_t idx0 = 0, idx1 = 1; + auto v0 = grin_get_vertex_from_list(graph, vertex_list, idx0); + auto v1 = grin_get_vertex_from_list(graph, vertex_list, idx1); + auto vertex_type0 = grin_get_vertex_type(graph, v0); + auto vertex_type1 = grin_get_vertex_type(graph, v1); + + // destroy vertex & vertex list + grin_destroy_vertex(graph, v0); + grin_destroy_vertex(graph, v1); + grin_destroy_vertex_list(graph, vertex_list); + + // compare + ASSERT(grin_equal_vertex_type(graph, vertex_type0, vertex_type0) == true); + + // vertex type name + auto name = grin_get_vertex_type_name(graph, vertex_type0); + std::cout << "vertex type name of vertex 0: " << name << std::endl; + auto vertex_type3 = grin_get_vertex_type_by_name(graph, name); + ASSERT(grin_equal_vertex_type(graph, vertex_type0, vertex_type3) == true); + auto vertex_type4 = grin_get_vertex_type_by_name(graph, "invalid"); + ASSERT(vertex_type4 == GRIN_NULL_VERTEX_TYPE); + + // vertex type id + auto id = grin_get_vertex_type_id(graph, vertex_type0); + auto vertex_type5 = grin_get_vertex_type_by_id(graph, id); + ASSERT(grin_equal_vertex_type(graph, vertex_type0, vertex_type5) == true); + + // destroy vertex type + grin_destroy_vertex_type(graph, vertex_type0); + grin_destroy_vertex_type(graph, vertex_type1); + grin_destroy_vertex_type(graph, vertex_type3); + grin_destroy_vertex_type(graph, vertex_type5); + + // get vertex type list + auto vertex_type_list = grin_get_vertex_type_list(graph); + size_t n = grin_get_vertex_type_list_size(graph, vertex_type_list); + std::cout << "size of vertex type list = " << n << std::endl; + + // create vertex type list + auto new_vertex_type_list = grin_create_vertex_type_list(graph); + + // get vertex type from list and add to a new list + for (auto i = 0; i < n; i++) { + auto vertex_type = + grin_get_vertex_type_from_list(graph, vertex_type_list, i); + // insert to list + grin_insert_vertex_type_to_list(graph, new_vertex_type_list, vertex_type); + // get name from vertex type + auto name = grin_get_vertex_type_name(graph, vertex_type); + std::cout << "name of vertex type " << i << ": " << name << std::endl; + // destroy + grin_destroy_vertex_type(graph, vertex_type); + } + + size_t m = grin_get_vertex_type_list_size(graph, new_vertex_type_list); + std::cout << "size of new vertex type list = " << m << std::endl; + ASSERT(m == n); + + // destroy vertex type list + grin_destroy_vertex_type_list(graph, vertex_type_list); + grin_destroy_vertex_type_list(graph, new_vertex_type_list); + grin_destroy_vertex_type(graph, vtype); +} + +void test_property_type_edge(GRIN_GRAPH graph) { + std::cout << "\n== test edge type ==" << std::endl; + + auto etype = grin_get_edge_type_by_id(graph, 0); + auto edge_list = grin_get_edge_list_by_type(graph, etype); + auto e = grin_get_edge_from_list(graph, edge_list, 0); + + // get edge type from edge & compare + auto edge_type = grin_get_edge_type(graph, e); + ASSERT(grin_equal_edge_type(graph, edge_type, edge_type) == true); + + // destroy edge & edge list + grin_destroy_edge(graph, e); + grin_destroy_edge_list(graph, edge_list); + + // edge type name + auto name = grin_get_edge_type_name(graph, edge_type); + std::cout << "edge type name of edge 0: " << name << std::endl; + auto edge_type2 = grin_get_edge_type_by_name(graph, name); + ASSERT(grin_equal_edge_type(graph, edge_type, edge_type2) == true); + auto edge_type3 = grin_get_edge_type_by_name(graph, "invalid"); + + ASSERT(edge_type3 == GRIN_NULL_EDGE_TYPE); + + // edge type id + auto id = grin_get_edge_type_id(graph, edge_type); + auto edge_type4 = grin_get_edge_type_by_id(graph, id); + ASSERT(grin_equal_edge_type(graph, edge_type, edge_type4) == true); + + // destroy edge type + grin_destroy_edge_type(graph, edge_type); + grin_destroy_edge_type(graph, edge_type2); + grin_destroy_edge_type(graph, edge_type4); + + // get edge type list + auto edge_type_list = grin_get_edge_type_list(graph); + size_t n = grin_get_edge_type_list_size(graph, edge_type_list); + std::cout << "size of edge type list = " << n << std::endl; + + // create edge type list + auto new_edge_type_list = grin_create_edge_type_list(graph); + + // get edgetype from list and add to a new list + for (auto i = 0; i < n; i++) { + auto edge_type = grin_get_edge_type_from_list(graph, edge_type_list, i); + // insert to list + grin_insert_edge_type_to_list(graph, new_edge_type_list, edge_type); + // get name from edge type + auto name = grin_get_edge_type_name(graph, edge_type); + std::cout << "name of edge type " << i << ": " << name << std::endl; + // destroy + grin_destroy_edge_type(graph, edge_type); + } + + size_t m = grin_get_edge_type_list_size(graph, new_edge_type_list); + std::cout << "size of new edge type list = " << m << std::endl; + ASSERT(m == n); + + // destroy edge type list + grin_destroy_edge_type_list(graph, edge_type_list); + grin_destroy_edge_type_list(graph, new_edge_type_list); + grin_destroy_edge_type(graph, etype); +} + +void test_property_type_vertex_and_edge(GRIN_GRAPH graph) { + std::cout << "\n== test vertex and edge type ==" << std::endl; + + // get edge type list + auto edge_type_list = grin_get_edge_type_list(graph); + size_t n = grin_get_edge_type_list_size(graph, edge_type_list); + + if (n > 0) { + // get edge type from list + auto edge_type = grin_get_edge_type_from_list(graph, edge_type_list, 0); + + // get vertex types from edge type + auto src_type_list = grin_get_src_types_by_edge_type(graph, edge_type); + auto dst_type_list = grin_get_dst_types_by_edge_type(graph, edge_type); + ASSERT(grin_get_vertex_type_list_size(graph, src_type_list) == + grin_get_vertex_type_list_size(graph, dst_type_list)); + std::cout << "size of vertex type list from edge type = " + << grin_get_vertex_type_list_size(graph, dst_type_list) + << std::endl; + + // get edge type from vertex types + auto src_type = grin_get_vertex_type_from_list(graph, src_type_list, 0); + auto dst_type = grin_get_vertex_type_from_list(graph, dst_type_list, 0); + auto edge_type_list_2 = + grin_get_edge_types_by_vertex_type_pair(graph, src_type, dst_type); + std::cout << "size of edge type list from vertex type pair = " + << grin_get_edge_type_list_size(graph, edge_type_list_2) + << std::endl; + + // destroy + grin_destroy_edge_type(graph, edge_type); + grin_destroy_vertex_type_list(graph, src_type_list); + grin_destroy_vertex_type_list(graph, dst_type_list); + grin_destroy_vertex_type(graph, src_type); + grin_destroy_vertex_type(graph, dst_type); + grin_destroy_edge_type_list(graph, edge_type_list_2); + } + + // destroy edge type list + grin_destroy_edge_type_list(graph, edge_type_list); +} + +void test_property_type(GRIN_GRAPH graph) { + std::cout << "\n++++ test property: type ++++" << std::endl; + + test_property_type_vertex(graph); + + test_property_type_edge(graph); + + test_property_type_vertex_and_edge(graph); + + std::cout << "---- test property: type completed ----" << std::endl; +} + +int main() { + // load graph + std::cout << "load modern graph" << std::endl; + std::string graph_name = "modern_graph"; + char* graph_name_str = new char[graph_name.size() + 1]; + snprintf(graph_name_str, graph_name.size() + 1, "%s", graph_name.c_str()); + demo_storage_load_modern_graph(graph_name_str, 1, 0); + delete[] graph_name_str; + + // get grin graph + std::string uri = "demo_storage://" + graph_name; + std::cout << "get grin graph from uri: " << uri << std::endl; + char* uri_str = new char[uri.size() + 1]; + snprintf(uri_str, uri.size() + 1, "%s", uri.c_str()); + GRIN_GRAPH graph = grin_get_graph_from_storage(uri_str); + delete[] uri_str; + + // test property type + test_property_type(graph); + + // destroy graph + grin_destroy_graph(graph); + + return 0; +} diff --git a/demo_storage/test/test_property_value.cc b/demo_storage/test/test_property_value.cc new file mode 100644 index 0000000..dfc817b --- /dev/null +++ b/demo_storage/test/test_property_value.cc @@ -0,0 +1,327 @@ +/** Copyright 2020 Alibaba Group Holding Limited. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +#include + +// predefine for GRIN +#include "../predefine.h" +// storage headers +#include "storage/loadmoderngraph.h" +// test config headers +#include "test/config.h" +// GRIN headers +#include "common/error.h" +#include "property/property.h" +#include "property/propertylist.h" +#include "property/row.h" +#include "property/topology.h" +#include "property/type.h" +#include "topology/adjacentlist.h" +#include "topology/edgelist.h" +#include "topology/structure.h" +#include "topology/vertexlist.h" + +void test_property_row(GRIN_GRAPH graph) { + std::cout << "\n++++ test property: row ++++" << std::endl; + + // create row + auto row = grin_create_row(graph); + + // insert value to row + int32_t value0 = 0; + const char* value1 = "Test String"; + uint64_t value2 = 2; + double value3 = 3.3; + + std::cout << "put value0: " << value0 << std::endl; + std::cout << "put value1: " << value1 << std::endl; + std::cout << "put value2: " << value2 << std::endl; + std::cout << "put value3: " << value3 << std::endl; + auto status = grin_insert_int32_to_row(graph, row, value0); + ASSERT(status == true); + status = grin_insert_string_to_row(graph, row, value1); + ASSERT(status == true); + status = grin_insert_uint64_to_row(graph, row, value2); + ASSERT(status == true); + status = grin_insert_double_to_row(graph, row, value3); + ASSERT(status == true); + + // get value from row + auto value0_ = grin_get_int32_from_row(graph, row, 0); + auto value1_ = grin_get_string_from_row(graph, row, 1); + auto invalid_value = grin_get_float_from_row(graph, row, 100); + ASSERT(grin_get_last_error_code() == INVALID_VALUE && invalid_value == 0.0); + auto value2_ = grin_get_uint64_from_row(graph, row, 2); + auto value3_ = grin_get_double_from_row(graph, row, 3); + ASSERT(grin_get_last_error_code() == NO_ERROR); + + // check value + std::cout << "get value0: " << value0_ << std::endl; + std::cout << "get value1: " << value1_ << std::endl; + std::cout << "get value2: " << value2_ << std::endl; + std::cout << "get value3: " << value3_ << std::endl; + ASSERT(value0_ == value0); + ASSERT(strcmp(value1_, value1) == 0); + ASSERT(value2_ == value2); + ASSERT(value3_ == value3); + + // get const value ptr from row + auto value0_ptr = + grin_get_value_from_row(graph, row, GRIN_DATATYPE::Int32, 0); + ASSERT(grin_get_last_error_code() == NO_ERROR); + ASSERT(*static_cast(value0_ptr) == value0); + auto value1_ptr = + grin_get_value_from_row(graph, row, GRIN_DATATYPE::String, 1); + ASSERT(grin_get_last_error_code() == NO_ERROR); + ASSERT(strcmp(static_cast(value1_ptr), value1) == 0); + auto invalid_value_ptr = + grin_get_value_from_row(graph, row, GRIN_DATATYPE::Int32, 100); + ASSERT(grin_get_last_error_code() == INVALID_VALUE && + invalid_value_ptr == NULL); + std::cout << "check getting const value ptr from row completed" << std::endl; + + // destroy + grin_destroy_string_value(graph, value1_); + grin_destroy_row(graph, row); + + std::cout << "---- test property: row completed ----" << std::endl; +} + +void test_property_vertex(GRIN_GRAPH graph) { + std::cout << "\n++++ test property: vertex ++++" << std::endl; + + // get vertex type list + auto vertex_type_list = grin_get_vertex_type_list(graph); + size_t n = grin_get_vertex_type_list_size(graph, vertex_type_list); + std::cout << "size of vertex type list = " << n << std::endl; + + for (auto i = 0; i < n; i++) { + std::cout << "== vertex type " << i << ": ==" << std::endl; + auto vertex_type = + grin_get_vertex_type_from_list(graph, vertex_type_list, i); + + // get vertex list + auto vertex_list = grin_get_vertex_list_by_type(graph, vertex_type); + + // get property list by vertex type + auto property_list = + grin_get_vertex_property_list_by_type(graph, vertex_type); + auto property_list_size = + grin_get_vertex_property_list_size(graph, property_list); + + for (int property_id = 0; property_id < property_list_size; property_id++) { + // get vertex from vertex list + auto vertex = grin_get_vertex_from_list(graph, vertex_list, 0); + + // get property from property list + auto property = + grin_get_vertex_property_from_list(graph, property_list, property_id); + auto name = grin_get_vertex_property_name(graph, vertex_type, property); + auto data_type = grin_get_vertex_property_datatype(graph, property); + std::cout << "get value of property \"" << name << "\" for vertex 0" + << std::endl; + + // get row + auto r = grin_get_vertex_row(graph, vertex); + + // get const value ptr + auto value = grin_get_vertex_property_value(graph, vertex, property); + ASSERT(grin_get_last_error_code() == NO_ERROR); + + // check value from row and from property (int64) + if (data_type == GRIN_DATATYPE::Int64) { + auto value1 = grin_get_int64_from_row(graph, r, property_id); + auto value2 = + grin_get_vertex_property_value_of_int64(graph, vertex, property); + ASSERT(value1 == value2); + ASSERT(value1 == *static_cast(value)); + std::cout << "value of property \"" << name + << "\" for vertex 0 of vertex type " << i << ": " << value1 + << std::endl; + std::cout << "check values from row and from property are equal (int64)" + << std::endl; + } + + // check value from row and from property (string) + if (data_type == GRIN_DATATYPE::String) { + auto value1 = grin_get_string_from_row(graph, r, property_id); + auto value2 = + grin_get_vertex_property_value_of_string(graph, vertex, property); + ASSERT(grin_get_last_error_code() == NO_ERROR); + ASSERT(strcmp(value1, value2) == 0); + ASSERT(strcmp(value1, static_cast(value)) == 0); + + std::cout << "value of property \"" << name + << "\" for vertex 0 of vertex type " << i << ": " << value1 + << std::endl; + std::cout + << "check values from row and from property are equal (string)" + << std::endl; + + // destroy + grin_destroy_string_value(graph, value1); + grin_destroy_string_value(graph, value2); + } + + // check getting value of invalid property + auto invalid_value = grin_get_vertex_property_value( + graph, vertex, GRIN_NULL_VERTEX_PROPERTY); + ASSERT(grin_get_last_error_code() == INVALID_VALUE); + ASSERT(invalid_value == NULL); + auto invalid_value1 = grin_get_vertex_property_value_of_int64( + graph, vertex, GRIN_NULL_VERTEX_PROPERTY); + ASSERT(grin_get_last_error_code() == INVALID_VALUE); + ASSERT(invalid_value1 == 0); + std::cout << "check error_code is INVALID_VALUE when getting value of " + "invalid property" + << std::endl; + + // destroy + grin_destroy_row(graph, r); + grin_destroy_vertex(graph, vertex); + grin_destroy_vertex_property(graph, property); + } + + // destroy + grin_destroy_vertex_property_list(graph, property_list); + grin_destroy_vertex_list(graph, vertex_list); + grin_destroy_vertex_type(graph, vertex_type); + } + + // destroy + grin_destroy_vertex_type_list(graph, vertex_type_list); + + std::cout << "---- test property: vertex completed ----" << std::endl; +} + +void test_property_edge(GRIN_GRAPH graph) { + std::cout << "\n++++ test property: edge ++++" << std::endl; + + // get edge type list + auto edge_type_list = grin_get_edge_type_list(graph); + size_t n = grin_get_edge_type_list_size(graph, edge_type_list); + std::cout << "size of edge type list = " << n << std::endl; + + for (auto i = 0; i < n; i++) { + std::cout << "== edge type " << i << ": ==" << std::endl; + auto edge_type = grin_get_edge_type_from_list(graph, edge_type_list, i); + + // get edge list + auto edge_list = grin_get_edge_list_by_type(graph, edge_type); + + // get property list by edge type + auto property_list = grin_get_edge_property_list_by_type(graph, edge_type); + auto property_list_size = + grin_get_edge_property_list_size(graph, property_list); + + for (auto property_id = 0; property_id < property_list_size; + property_id++) { + // get edge from edge list iter + auto edge = grin_get_edge_from_list(graph, edge_list, 0); + + // get property from property list + auto property = + grin_get_edge_property_from_list(graph, property_list, property_id); + + auto name = grin_get_edge_property_name(graph, edge_type, property); + auto data_type = grin_get_edge_property_datatype(graph, property); + std::cout << "get value of property \"" << name << "\" for edge 0" + << std::endl; + + // get row + auto r = grin_get_edge_row(graph, edge); + + // get const value ptr + auto value = grin_get_edge_property_value(graph, edge, property); + ASSERT(grin_get_last_error_code() == NO_ERROR); + + // check value from row and from property (int64) + if (data_type == GRIN_DATATYPE::Double) { + auto value1 = grin_get_double_from_row(graph, r, property_id); + auto value2 = + grin_get_edge_property_value_of_double(graph, edge, property); + ASSERT(grin_get_last_error_code() == NO_ERROR); + ASSERT(value1 == value2); + ASSERT(value1 == *static_cast(value)); + std::cout << "value of property \"" << name + << "\" for edge 0 of edge type " << i << ": " << value1 + << std::endl; + std::cout + << "check values from row and from property are equal (double)" + << std::endl; + } + + // check getting value of invalid property + auto invalid_value = + grin_get_edge_property_value(graph, edge, GRIN_NULL_EDGE_PROPERTY); + ASSERT(grin_get_last_error_code() == INVALID_VALUE); + ASSERT(invalid_value == NULL); + auto invalid_value1 = grin_get_edge_property_value_of_int64( + graph, edge, GRIN_NULL_EDGE_PROPERTY); + ASSERT(grin_get_last_error_code() == INVALID_VALUE); + ASSERT(invalid_value1 == 0); + std::cout << "check error_code is INVALID_VALUE when getting value of " + "invalid property" + << std::endl; + + // destroy + grin_destroy_row(graph, r); + grin_destroy_edge(graph, edge); + grin_destroy_edge_property(graph, property); + } + + // destroy + grin_destroy_edge_property_list(graph, property_list); + grin_destroy_edge_list(graph, edge_list); + grin_destroy_edge_type(graph, edge_type); + } + + // destroy + grin_destroy_edge_type_list(graph, edge_type_list); + + std::cout << "---- test property: edge completed ----" << std::endl; +} + +int main() { + // load graph + std::cout << "load modern graph" << std::endl; + std::string graph_name = "modern_graph"; + char* graph_name_str = new char[graph_name.size() + 1]; + snprintf(graph_name_str, graph_name.size() + 1, "%s", graph_name.c_str()); + demo_storage_load_modern_graph(graph_name_str, 1, 0); + delete[] graph_name_str; + + // get grin graph + std::string uri = "demo_storage://" + graph_name; + std::cout << "get grin graph from uri: " << uri << std::endl; + char* uri_str = new char[uri.size() + 1]; + snprintf(uri_str, uri.size() + 1, "%s", uri.c_str()); + GRIN_GRAPH graph = grin_get_graph_from_storage(uri_str); + delete[] uri_str; + + // test property row + test_property_row(graph); + + // test property for vertex + test_property_vertex(graph); + + // test property for edge + test_property_edge(graph); + + // destroy graph + grin_destroy_graph(graph); + + return 0; +} diff --git a/demo_storage/test/test_topology.cc b/demo_storage/test/test_topology.cc new file mode 100644 index 0000000..f5a39e3 --- /dev/null +++ b/demo_storage/test/test_topology.cc @@ -0,0 +1,257 @@ +/** Copyright 2020 Alibaba Group Holding Limited. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +#include +#include + +// predefine for GRIN +#include "../predefine.h" +// storage headers +#include "storage/loadmoderngraph.h" +// test config headers +#include "test/config.h" +// GRIN headers +#include "common/message.h" +#include "property/topology.h" +#include "property/type.h" +#include "topology/adjacentlist.h" +#include "topology/edgelist.h" +#include "topology/structure.h" +#include "topology/vertexlist.h" + +void test_protobuf() { + std::cout << "\n++++ test protobuf ++++" << std::endl; + + std::cout << grin_get_static_storage_feature_msg() << std::endl; + + std::cout << "---- test protobuf ----" << std::endl; +} + +void test_topology_structure(GRIN_GRAPH graph) { + std::cout << "\n++++ test topology: structure ++++" << std::endl; + + std::cout << "is directed: " << grin_is_directed(graph) << std::endl; + + std::cout << "is multigraph: " << grin_is_multigraph(graph) << std::endl; + + std::cout << "---- test topology: structure ----" << std::endl; +} + +void test_topology_vertexlist(GRIN_GRAPH graph) { + std::cout << "\n++++ test topology: vertexlist ++++" << std::endl; + // get vertex list + auto vtype = grin_get_vertex_type_by_name(graph, "person"); + auto vertex_list = grin_get_vertex_list_by_type(graph, vtype); + + // test vertex list array + auto n = grin_get_vertex_list_size(graph, vertex_list); + std::cout << "vertex list size = " << n << std::endl; + auto v0 = grin_get_vertex_from_list(graph, vertex_list, 0); + auto v1 = grin_get_vertex_from_list(graph, vertex_list, 1); + auto v2 = grin_get_vertex_from_list(graph, vertex_list, 100000000); + ASSERT(grin_equal_vertex(graph, v0, v0) == true); + ASSERT(grin_equal_vertex(graph, v0, v1) == false); + ASSERT(v2 == GRIN_NULL_VERTEX); + + grin_destroy_vertex(graph, v0); + grin_destroy_vertex(graph, v1); + + // test vertex list iterator + auto it = grin_get_vertex_list_begin(graph, vertex_list); + auto count = 0; + while (grin_is_vertex_list_end(graph, it) == false) { + auto v = grin_get_vertex_from_iter(graph, it); + // methods on vertex + auto vdata_type = grin_get_vertex_data_datatype(graph, v); + auto vdata = grin_get_vertex_data_value(graph, v); + if (vdata_type == GRIN_DATATYPE::Int64) + std::cout << "data of \"person\" vertex #" << count << " = " + << *static_cast(vdata) << std::endl; + if (vdata_type == GRIN_DATATYPE::String) + std::cout << "data of \"person\" vertex #" << count << " = " + << static_cast(vdata) << std::endl; + grin_destroy_vertex(graph, v); + grin_get_next_vertex_list_iter(graph, it); + count++; + } + ASSERT(count == n); + grin_destroy_vertex_list_iter(graph, it); + + // destroy vertex list + grin_destroy_vertex_list(graph, vertex_list); + grin_destroy_vertex_type(graph, vtype); + + std::cout << "---- test topology: vertexlist ----" << std::endl; +} + +void test_topology_edgelist(GRIN_GRAPH graph) { + std::cout << "\n++++ test topology: edgelist ++++" << std::endl; + // get edge list + auto etype = grin_get_edge_type_by_name(graph, "knows"); + auto edge_list = grin_get_edge_list_by_type(graph, etype); + + // test edge list array + auto n = grin_get_edge_list_size(graph, edge_list); + std::cout << "edge list size = " << n << std::endl; + auto e0 = grin_get_edge_from_list(graph, edge_list, 0); + auto e1 = grin_get_edge_from_list(graph, edge_list, 1); + auto e2 = grin_get_edge_from_list(graph, edge_list, 100000000); + ASSERT(e2 == GRIN_NULL_EDGE); + + grin_destroy_vertex(graph, e0); + grin_destroy_vertex(graph, e1); + + // test edge list iterator + auto it = grin_get_edge_list_begin(graph, edge_list); + auto count = 0; + while (grin_is_edge_list_end(graph, it) == false) { + // methods on edge + auto e = grin_get_edge_from_iter(graph, it); + auto v1 = grin_get_src_vertex_from_edge(graph, e); + auto v2 = grin_get_dst_vertex_from_edge(graph, e); + auto edata_type = grin_get_edge_data_datatype(graph, e); + auto edata = grin_get_edge_data_value(graph, e); + if (edata_type == GRIN_DATATYPE::Double) + std::cout << "data of \"knows\" edge #" << count << " = " + << *static_cast(edata) << std::endl; + + grin_destroy_vertex(graph, v1); + grin_destroy_vertex(graph, v2); + grin_destroy_edge(graph, e); + grin_get_next_edge_list_iter(graph, it); + count++; + } + std::cout << "edge list size = " << count << std::endl; + grin_destroy_edge_list_iter(graph, it); + + // destroy edge list + grin_destroy_edge_list(graph, edge_list); + grin_destroy_edge_type(graph, etype); + + std::cout << "---- test topology: edgelist -----" << std::endl; +} + +void test_topology_adjlist(GRIN_GRAPH graph, GRIN_DIRECTION direction) { + std::cout << "test topology: adjlist "; + if (direction == GRIN_DIRECTION::IN) + std::cout << "IN" << std::endl; + else if (direction == GRIN_DIRECTION::OUT) + std::cout << "OUT" << std::endl; + else + std::cout << "BOTH" << std::endl; + // get adj list + auto vtype = grin_get_vertex_type_by_name(graph, "person"); + auto vertex_list = grin_get_vertex_list_by_type(graph, vtype); + auto etype = grin_get_edge_type_by_name(graph, "knows"); + auto v = grin_get_vertex_from_list(graph, vertex_list, 3); + auto adj_list = + grin_get_adjacent_list_by_edge_type(graph, direction, v, etype); + auto n = grin_get_adjacent_list_size(graph, adj_list); + + // iterate adj list + auto it = grin_get_adjacent_list_begin(graph, adj_list); + auto count = 0; + while (grin_is_adjacent_list_end(graph, it) == false) { + // iterator + auto e = grin_get_edge_from_adjacent_list_iter(graph, it); + auto v1 = grin_get_src_vertex_from_edge(graph, e); + auto v2 = grin_get_dst_vertex_from_edge(graph, e); + auto nbr = grin_get_neighbor_from_adjacent_list_iter(graph, it); + // array + auto e_ = grin_get_edge_from_adjacent_list(graph, adj_list, count); + auto v1_ = grin_get_src_vertex_from_edge(graph, e_); + auto v2_ = grin_get_dst_vertex_from_edge(graph, e_); + auto nbr_ = grin_get_neighbor_from_adjacent_list(graph, adj_list, count); + + // check src & dst + ASSERT(grin_equal_vertex(graph, v1, v1_) == true); + ASSERT(grin_equal_vertex(graph, v2, v2_) == true); + ASSERT(grin_equal_vertex(graph, v2, v) == true && + grin_equal_vertex(graph, v1, nbr) == true || + grin_equal_vertex(graph, v1, v) == true && + grin_equal_vertex(graph, v2, nbr) == true); + + grin_destroy_vertex(graph, v1); + grin_destroy_vertex(graph, v2); + grin_destroy_vertex(graph, nbr); + grin_destroy_edge(graph, e); + grin_destroy_vertex(graph, v1_); + grin_destroy_vertex(graph, v2_); + grin_destroy_vertex(graph, nbr_); + grin_destroy_edge(graph, e_); + grin_get_next_adjacent_list_iter(graph, it); + count++; + } + ASSERT(count == n); + std::cout << "adj list size of \"person\" vertex #3 = " << count << std::endl; + grin_destroy_adjacent_list_iter(graph, it); + + // destory + grin_destroy_vertex(graph, v); + grin_destroy_vertex_list(graph, vertex_list); + grin_destroy_vertex_type(graph, vtype); + grin_destroy_edge_type(graph, etype); + grin_destroy_adjacent_list(graph, adj_list); +} + +void test_topology_adjlist(GRIN_GRAPH graph) { + std::cout << "\n++++ test topology: adjlist ++++" << std::endl; + + test_topology_adjlist(graph, GRIN_DIRECTION::IN); + + test_topology_adjlist(graph, GRIN_DIRECTION::OUT); + + test_topology_adjlist(graph, GRIN_DIRECTION::BOTH); + + std::cout << "---- test topology: adjlist ----" << std::endl; +} + +int main() { + // load graph + std::cout << "load modern graph" << std::endl; + std::string graph_name = "modern_graph"; + char* graph_name_str = new char[graph_name.size() + 1]; + snprintf(graph_name_str, graph_name.size() + 1, "%s", graph_name.c_str()); + demo_storage_load_modern_graph(graph_name_str, 1, 0); + delete[] graph_name_str; + + // get grin graph + std::string uri = "demo_storage://" + graph_name; + std::cout << "get grin graph from uri: " << uri << std::endl; + char* uri_str = new char[uri.size() + 1]; + snprintf(uri_str, uri.size() + 1, "%s", uri.c_str()); + GRIN_GRAPH graph = grin_get_graph_from_storage(uri_str); + delete[] uri_str; + + // test protobuf + test_protobuf(); + + // test topology structure + test_topology_structure(graph); + + // test topology vertexlist + test_topology_vertexlist(graph); + + // test topology edgelist + test_topology_edgelist(graph); + + // test topology adjlist + test_topology_adjlist(graph); + + // destroy graph + grin_destroy_graph(graph); + + return 0; +}