Skip to content
Snippets Groups Projects
Unverified Commit ce6ccb26 authored by laura-ding's avatar laura-ding Committed by GitHub
Browse files

Fix error msg and delete mock directory (#386)


* fix error msg

* add more error msg

Co-authored-by: default avatarYee <2520865+yixinglu@users.noreply.github.com>
parent 671cfba4
No related branches found
No related tags found
No related merge requests found
......@@ -34,50 +34,60 @@ protected:
<< it->first;
}
if (completeness == 0 || isCompleteRequire) {
LOG(ERROR) << "Request to storage failed in executor `" << name_ << "'";
return Status::Error("Request to storage failed in executor.");
return handleErrorCode(failedCodes.begin()->second,
failedCodes.begin()->first);
}
return Result::State::kPartialSuccess;
}
return Result::State::kSuccess;
}
Status handleErrorCode(nebula::storage::cpp2::ErrorCode code, PartitionID partId) {
Status handleErrorCode(nebula::storage::cpp2::ErrorCode code, PartitionID partId) const {
switch (code) {
case storage::cpp2::ErrorCode::E_INVALID_VID:
return Status::Error("Invalid vid.");
return Status::Error("Storage Error: Invalid vid.");
case storage::cpp2::ErrorCode::E_INVALID_FIELD_VALUE: {
std::string error = "Invalid field value: may be the filed is not NULL "
"or without default value or wrong schema.";
std::string error = "Storage Error: Invalid field value: "
"may be the filed is not NULL "
"or without default value or wrong schema.";
return Status::Error(std::move(error));
}
case storage::cpp2::ErrorCode::E_LEADER_CHANGED:
return Status::Error("Storage Error: Leader changed.");
case storage::cpp2::ErrorCode::E_INVALID_FILTER:
return Status::Error("Invalid filter.");
return Status::Error("Storage Error: Invalid filter.");
case storage::cpp2::ErrorCode::E_INVALID_UPDATER:
return Status::Error("Invalid Update col or yield col.");
return Status::Error("Storage Error: Invalid Update col or yield col.");
case storage::cpp2::ErrorCode::E_INVALID_SPACEVIDLEN:
return Status::Error("Storage Error: Invalid space vid len.");
case storage::cpp2::ErrorCode::E_SPACE_NOT_FOUND:
return Status::Error("Storage Error: Space not found.");
case storage::cpp2::ErrorCode::E_TAG_NOT_FOUND:
return Status::Error("Tag not found.");
return Status::Error("Storage Error: Tag not found.");
case storage::cpp2::ErrorCode::E_TAG_PROP_NOT_FOUND:
return Status::Error("Tag prop not found.");
return Status::Error("Storage Error: Tag prop not found.");
case storage::cpp2::ErrorCode::E_EDGE_NOT_FOUND:
return Status::Error("Edge not found.");
return Status::Error("Storage Error: Edge not found.");
case storage::cpp2::ErrorCode::E_EDGE_PROP_NOT_FOUND:
return Status::Error("Edge prop not found.");
return Status::Error("Storage Error: Edge prop not found.");
case storage::cpp2::ErrorCode::E_INDEX_NOT_FOUND:
return Status::Error("Storage Error: Index not found.");
case storage::cpp2::ErrorCode::E_INVALID_DATA:
return Status::Error("Invalid data, may be wrong value type.");
return Status::Error("Storage Error: Invalid data, may be wrong value type.");
case storage::cpp2::ErrorCode::E_NOT_NULLABLE:
return Status::Error("The not null field cannot be null.");
return Status::Error("Storage Error: The not null field cannot be null.");
case storage::cpp2::ErrorCode::E_FIELD_UNSET:
return Status::Error("The not null field doesn't have a default value.");
return Status::Error("Storage Error: "
"The not null field doesn't have a default value.");
case storage::cpp2::ErrorCode::E_OUT_OF_RANGE:
return Status::Error("Out of range value.");
return Status::Error("Storage Error: Out of range value.");
case storage::cpp2::ErrorCode::E_ATOMIC_OP_FAILED:
return Status::Error("Atomic operation failed.");
return Status::Error("Storage Error: Atomic operation failed.");
case storage::cpp2::ErrorCode::E_FILTER_OUT:
return Status::OK();
default:
auto status = Status::Error("Unknown error, part: %d, error code: %d.",
partId, static_cast<int32_t>(code));
auto status = Status::Error("Storage Error: part: %d, error code: %d.",
partId, static_cast<int32_t>(code));
LOG(ERROR) << status;
return status;
}
......
# Copyright (c) 2020 vesoft inc. All rights reserved.
#
# This source code is licensed under Apache 2.0 License,
# attached with Common Clause Condition 1.0, found in the LICENSES directory.
#
nebula_add_library(
mock_obj OBJECT
MetaCache.cpp
StorageCache.cpp
MockMetaServiceHandler.cpp
MockStorageServiceHandler.cpp
test/TestMain.cpp
test/TestEnv.cpp
test/TestBase.cpp
)
# nebula_add_subdirectory(test)
This diff is collapsed.
/* Copyright (c) 2020 vesoft inc. All rights reserved.
*
* This source code is licensed under Apache 2.0 License,
* attached with Common Clause Condition 1.0, found in the LICENSES directory.
*/
#ifndef EXECUTOR_METACACHE_H_
#define EXECUTOR_METACACHE_H_
#include "common/base/Base.h"
#include "common/base/StatusOr.h"
#include "common/base/ErrorOr.h"
#include "common/interface/gen-cpp2/meta_types.h"
namespace nebula {
namespace graph {
class MetaCache final {
public:
static MetaCache& instance() {
static MetaCache instance;
return instance;
}
Status createSpace(const meta::cpp2::CreateSpaceReq &req, GraphSpaceID &spaceId);
StatusOr<meta::cpp2::SpaceItem> getSpace(const meta::cpp2::GetSpaceReq &req);
StatusOr<std::vector<meta::cpp2::IdName>> listSpaces();
Status dropSpace(const meta::cpp2::DropSpaceReq &req);
Status createTag(const meta::cpp2::CreateTagReq &req, TagID &tagId);
StatusOr<meta::cpp2::Schema> getTag(const meta::cpp2::GetTagReq &req);
StatusOr<std::vector<meta::cpp2::TagItem>> listTags(const meta::cpp2::ListTagsReq &req);
Status createEdge(const meta::cpp2::CreateEdgeReq &req, EdgeType &edgeType);
StatusOr<meta::cpp2::Schema> getEdge(const meta::cpp2::GetEdgeReq &req);
StatusOr<std::vector<meta::cpp2::EdgeItem>> listEdges(const meta::cpp2::ListEdgesReq &req);
Status dropTag(const meta::cpp2::DropTagReq &req);
Status dropEdge(const meta::cpp2::DropEdgeReq &req);
Status AlterTag(const meta::cpp2::AlterTagReq &req);
Status AlterEdge(const meta::cpp2::AlterEdgeReq &req);
Status createTagIndex(const meta::cpp2::CreateTagIndexReq &req, IndexID &indexId);
Status createEdgeIndex(const meta::cpp2::CreateEdgeIndexReq &req, IndexID &indexId);
Status dropTagIndex(const meta::cpp2::DropTagIndexReq &req);
Status dropTagIndex(const meta::cpp2::DropEdgeIndexReq &req);
Status regConfigs(const std::vector<meta::cpp2::ConfigItem> &items);
Status setConfig(const meta::cpp2::ConfigItem &req);
Status heartBeat(const meta::cpp2::HBReq &req);
std::vector<meta::cpp2::HostItem> listHosts();
std::unordered_map<PartitionID, std::vector<HostAddr>> getParts();
////////////////////////////////////////////// ACL related mock ////////////////////////////////////
meta::cpp2::ExecResp createUser(const meta::cpp2::CreateUserReq& req);
meta::cpp2::ExecResp dropUser(const meta::cpp2::DropUserReq& req);
meta::cpp2::ExecResp alterUser(const meta::cpp2::AlterUserReq& req);
meta::cpp2::ExecResp grantRole(const meta::cpp2::GrantRoleReq& req);
meta::cpp2::ExecResp revokeRole(const meta::cpp2::RevokeRoleReq& req);
meta::cpp2::ListUsersResp listUsers(const meta::cpp2::ListUsersReq& req);
meta::cpp2::ListRolesResp listRoles(const meta::cpp2::ListRolesReq& req);
meta::cpp2::ExecResp changePassword(const meta::cpp2::ChangePasswordReq& req);
meta::cpp2::ListRolesResp getUserRoles(const meta::cpp2::GetUserRolesReq& req);
ErrorOr<meta::cpp2::ErrorCode, int64_t> balanceSubmit(std::vector<HostAddr> dels);
ErrorOr<meta::cpp2::ErrorCode, int64_t> balanceStop();
meta::cpp2::ErrorCode balanceLeaders();
ErrorOr<meta::cpp2::ErrorCode, std::vector<meta::cpp2::BalanceTask>>
showBalance(int64_t id);
ErrorOr<meta::cpp2::ErrorCode, meta::cpp2::AdminJobResult>
runAdminJob(const meta::cpp2::AdminJobReq& req);
Status createSnapshot();
Status dropSnapshot(const meta::cpp2::DropSnapshotReq& req);
StatusOr<std::vector<meta::cpp2::Snapshot>> listSnapshots();
private:
MetaCache() = default;
int64_t incId() {
return ++id_;
}
Status alterColumnDefs(meta::cpp2::Schema &schema,
const std::vector<meta::cpp2::AlterSchemaItem> &items);
Status alterSchemaProp(meta::cpp2::Schema &schema,
const meta::cpp2::SchemaProp &alterSchemaProp);
private:
enum class EntryType : int8_t {
SPACE = 0x01,
TAG = 0x02,
EDGE = 0x03,
INDEX = 0x04,
CONFIG = 0x05,
};
template<class T>
std::enable_if_t<std::is_integral<T>::value, meta::cpp2::ID>
to(T id, EntryType type) {
meta::cpp2::ID thriftID;
switch (type) {
case EntryType::SPACE:
thriftID.set_space_id(static_cast<GraphSpaceID>(id));
break;
case EntryType::TAG:
thriftID.set_tag_id(static_cast<TagID>(id));
break;
case EntryType::EDGE:
thriftID.set_edge_type(static_cast<EdgeType>(id));
break;
case EntryType::CONFIG:
break;
case EntryType::INDEX:
thriftID.set_index_id(static_cast<IndexID>(id));
break;
}
return thriftID;
}
private:
using HostMap = std::unordered_map<std::pair<GraphSpaceID, PartitionID>, HostAddr>;
using TagSchemas = std::unordered_map<std::string, meta::cpp2::TagItem>;
using EdgeSchemas = std::unordered_map<std::string, meta::cpp2::EdgeItem>;
using Indexes = std::unordered_map<std::string, meta::cpp2::IndexItem>;
struct SpaceInfoCache {
TagSchemas tagSchemas_;
EdgeSchemas edgeSchemas_;
Indexes tagIndexes_;
Indexes edgeIndexes_;
};
std::unordered_set<HostAddr> hostSet_;
std::unordered_map<std::string, GraphSpaceID> spaceIndex_;
std::unordered_map<GraphSpaceID, SpaceInfoCache> cache_;
std::unordered_map<GraphSpaceID, meta::cpp2::SpaceItem> spaces_;
int64_t id_{0};
std::unordered_map<std::string, meta::cpp2::Snapshot> snapshots_;
mutable folly::RWSpinLock lock_;
///////////////////////////////////////////// ACL cache ////////////////////////////////////////////
struct UserInfo {
std::string password;
// revserved
};
// username -> UserInfo
std::unordered_map<std::string, UserInfo> users_;
mutable folly::RWSpinLock userLock_;
// authority
using UserRoles =
std::unordered_map<std::string/*user*/, std::unordered_set<meta::cpp2::RoleType>>;
std::unordered_map<GraphSpaceID, UserRoles> roles_;
mutable folly::RWSpinLock roleLock_;
////////////////////////////////////////////// Balance /////////////////////////////////////////////
struct BalanceTask {
GraphSpaceID space;
PartitionID part;
HostAddr from;
HostAddr to;
meta::cpp2::TaskResult status;
};
struct BalanceJob {
meta::cpp2::TaskResult status;
};
std::unordered_map<int64_t, std::vector<BalanceTask>> balanceTasks_;
std::unordered_map<int64_t, BalanceJob> balanceJobs_;
////////////////////////////////////////////// Job /////////////////////////////////////////////////
struct JobDesc {
meta::cpp2::AdminCmd cmd_; // compact, flush ...
std::vector<std::string> paras_;
meta::cpp2::JobStatus status_;
int64_t startTime_;
int64_t stopTime_;
};
struct TaskDesc {
int32_t iTask_;
nebula::HostAddr dest_;
meta::cpp2::JobStatus status_;
int64_t startTime_;
int64_t stopTime_;
};
ErrorOr<meta::cpp2::ErrorCode, std::unordered_map<int64_t, JobDesc>::iterator>
checkJobId(const meta::cpp2::AdminJobReq& req) {
const auto &params = req.get_paras();
if (params.empty()) {
return meta::cpp2::ErrorCode::E_INVALID_PARM;
}
int64_t jobId;
try {
jobId = folly::to<int64_t>(params.front());
} catch (std::exception &e) {
LOG(ERROR) << e.what();
return meta::cpp2::ErrorCode::E_INVALID_PARM;
}
const auto job = jobs_.find(jobId);
if (job == jobs_.end()) {
return meta::cpp2::ErrorCode::E_INVALID_PARM;
}
return job;
}
mutable folly::RWSpinLock jobLock_;
// jobId => jobs
std::unordered_map<int64_t, JobDesc> jobs_;
// jobId => tasks
std::unordered_map<int64_t, std::vector<TaskDesc>> tasks_;
};
} // namespace graph
} // namespace nebula
#endif // EXECUTOR_METACACHE_H_
This diff is collapsed.
/* Copyright (c) 2020 vesoft inc. All rights reserved.
*
* This source code is licensed under Apache 2.0 License,
* attached with Common Clause Condition 1.0, found in the LICENSES directory.
*/
#include "mock/StorageCache.h"
DECLARE_int32(heartbeat_interval_secs);
namespace nebula {
namespace graph {
StorageCache::StorageCache(uint16_t metaPort) {
FLAGS_heartbeat_interval_secs = 1;
auto threadPool = std::make_shared<folly::IOThreadPoolExecutor>(1);
auto hostStatus = network::NetworkUtils::resolveHost("127.0.0.1", metaPort);
meta::MetaClientOptions options;
options.serviceName_ = "StorageCache";
metaClient_ = std::make_unique<meta::MetaClient>(threadPool,
std::move(hostStatus).value(), options);
metaClient_->waitForMetadReady();
mgr_ = std::make_unique<meta::ServerBasedSchemaManager>();
mgr_->init(metaClient_.get());
}
Status StorageCache::addVertices(const storage::cpp2::AddVerticesRequest& req) {
folly::RWSpinLock::WriteHolder holder(lock_);
auto spaceId = req.get_space_id();
auto spaceFind = cache_.find(spaceId);
SpaceDataInfo *spaceDataInfo = nullptr;
if (spaceFind != cache_.end()) {
spaceDataInfo = &spaceFind->second;
} else {
cache_[spaceId] = SpaceDataInfo();
spaceDataInfo = &cache_[spaceId];
}
std::unordered_map<TagID, std::vector<std::string>> propNames;
for (auto &prop : req.get_prop_names()) {
propNames[prop.first] = prop.second;
}
auto &parts = req.get_parts();
for (auto &part : parts) {
for (auto &vertex : part.second) {
auto vId = vertex.get_id();
auto findV = spaceDataInfo->vertices.find(vId.getStr());
std::unordered_map<TagID,
std::unordered_map<std::string, Value>> *vertexInfo = nullptr;
if (findV != spaceDataInfo->vertices.end()) {
vertexInfo = &findV->second;
} else {
spaceDataInfo->vertices[vId.getStr()] = {};
vertexInfo = &spaceDataInfo->vertices[vId.getStr()];
}
for (auto &tag : vertex.get_tags()) {
auto tagId = tag.get_tag_id();
auto propValues = tag.get_props();
if (propValues.size() != propNames[tagId].size()) {
return Status::Error("Wrong size");
}
auto ret = getTagWholeValue(spaceId, tagId, propValues, propNames[tagId]);
if (!ret.ok()) {
LOG(ERROR) << ret.status();
return ret.status();
}
(*vertexInfo)[tagId] = std::move(ret).value();
}
}
}
return Status::OK();
}
Status StorageCache::addEdges(const storage::cpp2::AddEdgesRequest& req) {
folly::RWSpinLock::WriteHolder holder(lock_);
auto spaceId = req.get_space_id();
auto spaceFind = cache_.find(spaceId);
SpaceDataInfo *spaceDataInfo = nullptr;
if (spaceFind != cache_.end()) {
spaceDataInfo = &spaceFind->second;
} else {
cache_[spaceId] = SpaceDataInfo();
spaceDataInfo = &cache_[spaceId];
}
std::vector<std::string> propNames = req.get_prop_names();
auto &parts = req.get_parts();
for (auto &part : parts) {
for (auto &edge : part.second) {
storage::cpp2::EdgeKey edgeKey;
edgeKey.set_src(edge.key.get_src());
auto edgeType = edge.key.get_edge_type();
edgeKey.set_edge_type(edgeType);
edgeKey.set_ranking(edge.key.get_ranking());
edgeKey.set_dst(edge.key.get_dst());
auto propValues = edge.get_props();
if (propValues.size() != propNames.size()) {
LOG(ERROR) << "Wrong size, propValues.size : " << propValues.size()
<< ", propNames.size : " << propNames.size();
return Status::Error("Wrong size");
}
auto ret = getEdgeWholeValue(spaceId, edgeType, propValues, propNames);
if (!ret.ok()) {
LOG(ERROR) << ret.status();
return ret.status();
}
spaceDataInfo->edges[edgeKey] = std::move(ret).value();
}
}
return Status::OK();
}
StatusOr<std::unordered_map<std::string, Value>>
StorageCache::getTagWholeValue(const GraphSpaceID spaceId,
const TagID tagId,
const std::vector<Value>& props,
const std::vector<std::string> &names) {
if (props.size() != names.size()) {
return Status::Error("Wrong size between props and names");
}
auto schema = mgr_->getTagSchema(spaceId, tagId);
if (schema == nullptr) {
return Status::Error("TagId `%d' not exist", tagId);
}
return getPropertyInfo(schema, props, names);
}
StatusOr<std::unordered_map<std::string, Value>>
StorageCache::getEdgeWholeValue(const GraphSpaceID spaceId,
const EdgeType edgeType,
const std::vector<Value>& props,
const std::vector<std::string> &names) {
if (props.size() != names.size()) {
return Status::Error("Wrong size between props and names");
}
auto schema = mgr_->getEdgeSchema(spaceId, std::abs(edgeType));
if (schema == nullptr) {
return Status::Error("EdgeType `%d' not exist", edgeType);
}
return getPropertyInfo(schema, props, names);
}
StatusOr<std::unordered_map<std::string, Value>>
StorageCache::getPropertyInfo(std::shared_ptr<const meta::NebulaSchemaProvider> schema,
const std::vector<Value>& props,
const std::vector<std::string> &names) {
auto number = schema->getNumFields();
if (number == 0 && props.size() == 0) {
return {};
}
if (number == 0 && props.size() != 0) {
return Status::Error("Wrong value about empty schema");
}
std::bitset<32> indexBitSet;
std::unordered_map<std::string, Value> propertyInfo;
auto index = 0u;
for (auto &item : names) {
auto filed = schema->field(item);
if (filed != nullptr) {
indexBitSet.set(index);
if (!filed->nullable() && props[index].isNull()) {
return Status::Error("Wrong null type `%s'", item.c_str());
}
propertyInfo.emplace(item, props[index]);
} else {
return Status::Error("Wrong prop name `%s'", item.c_str());
}
index++;
}
if (schema->getNumFields() != indexBitSet.count()) {
for (auto i = 0u; i < schema->getNumFields(); i++) {
if (indexBitSet[i] != 1) {
auto field = schema->field(i);
if (field != nullptr && !field->hasDefault()) {
return Status::Error("Prop name `%s' without default value",
field->name());
}
VLOG(1) << "Add default value, filed name: " << field->name();
propertyInfo.emplace(field->name(), field->defaultValue());
}
}
}
return propertyInfo;
}
} // namespace graph
} // namespace nebula
/* Copyright (c) 2020 vesoft inc. All rights reserved.
*
* This source code is licensed under Apache 2.0 License,
* attached with Common Clause Condition 1.0, found in the LICENSES directory.
*/
#ifndef EXECUTOR_STORAGECACHE_H_
#define EXECUTOR_STORAGECACHE_H_
#include "common/base/Base.h"
#include "common/base/StatusOr.h"
#include "common/interface/gen-cpp2/storage_types.h"
#include "common/clients/meta/MetaClient.h"
#include "common/meta/ServerBasedSchemaManager.h"
namespace nebula {
namespace graph {
struct EdgeHasher {
std::size_t operator()(const storage::cpp2::EdgeKey& k) const {
std::size_t hash_val = 0;
hash_val ^= ((std::hash<Value>()(k.get_src())) << 1);
hash_val ^= ((std::hash<int32_t>()(k.get_edge_type())) << 1);
hash_val ^= ((std::hash<int64_t>()(k.get_ranking())) << 1);
hash_val ^= ((std::hash<Value>()(k.get_dst())) << 1);
return hash_val;
}
};
using VerticesInfo = std::unordered_map<VertexID,
std::unordered_map<TagID, std::unordered_map<std::string, Value>>>;
using EdgesInfo = std::unordered_map<storage::cpp2::EdgeKey,
std::unordered_map<std::string, Value>, EdgeHasher>;
class StorageCache final {
public:
explicit StorageCache(uint16_t metaPort);
~StorageCache() = default;
Status addVertices(const storage::cpp2::AddVerticesRequest& req);
Status addEdges(const storage::cpp2::AddEdgesRequest& req);
private:
StatusOr<std::unordered_map<std::string, Value>>
getTagWholeValue(const GraphSpaceID spaceId,
const TagID tagId,
const std::vector<Value>& props,
const std::vector<std::string> &names);
StatusOr<std::unordered_map<std::string, Value>>
getEdgeWholeValue(const GraphSpaceID spaceId,
const EdgeType edgeType,
const std::vector<Value>& props,
const std::vector<std::string> &names);
StatusOr<std::unordered_map<std::string, Value>>
getPropertyInfo(std::shared_ptr<const meta::NebulaSchemaProvider> schema,
const std::vector<Value>& props,
const std::vector<std::string> &names);
private:
struct SpaceDataInfo {
SpaceDataInfo() = default;
~SpaceDataInfo() = default;
VerticesInfo vertices;
EdgesInfo edges;
};
std::unordered_map<GraphSpaceID, SpaceDataInfo> cache_;
mutable folly::RWSpinLock lock_;
std::unique_ptr<meta::MetaClient> metaClient_;
std::unique_ptr<meta::ServerBasedSchemaManager> mgr_;
};
} // namespace graph
} // namespace nebula
#endif // EXECUTOR_STORAGECACHE_H_
/* Copyright (c) 2020 vesoft inc. All rights reserved.
*
* This source code is licensed under Apache 2.0 License,
* attached with Common Clause Condition 1.0, found in the LICENSES directory.
*/
#include "common/base/Status.h"
#include "common/network/NetworkUtils.h"
#include "common/interface/gen-cpp2/common_types.h"
#include "mock/test/TestEnv.h"
#include "mock/test/TestBase.h"
#include <gtest/gtest.h>
DECLARE_int32(heartbeat_interval_secs);
namespace nebula {
namespace graph {
class AdminJobTest : public TestBase {
public:
void SetUp() override {
TestBase::SetUp();
client_ = gEnv->getGraphClient();
ASSERT_NE(nullptr, client_);
};
void TearDown() override {
TestBase::TearDown();
client_.reset();
};
protected:
std::unique_ptr<GraphClient> client_;
};
TEST_F(AdminJobTest, Error) {
{
// submit without space
cpp2::ExecutionResponse resp;
std::string query = "SUBMIT JOB COMPACT";
client_->execute(query, resp);
// TODO(shylock) semantic error?
ASSERT_ERROR_CODE(resp, cpp2::ErrorCode::E_SEMANTIC_ERROR);
}
{
// show one not exists
cpp2::ExecutionResponse resp;
std::string query = "SHOW JOB 233";
client_->execute(query, resp);
ASSERT_ERROR_CODE(resp, cpp2::ErrorCode::E_EXECUTION_ERROR);
}
{
// stop one not exists
cpp2::ExecutionResponse resp;
std::string query = "STOP JOB 233";
client_->execute(query, resp);
ASSERT_ERROR_CODE(resp, cpp2::ErrorCode::E_EXECUTION_ERROR);
}
}
TEST_F(AdminJobTest, Base) {
{
cpp2::ExecutionResponse resp;
std::string query = "CREATE SPACE space_for_default(partition_num=9, replica_factor=1);";
client_->execute(query, resp);
ASSERT_ERROR_CODE(resp, cpp2::ErrorCode::SUCCEEDED);
}
sleep(FLAGS_heartbeat_interval_secs + 1);
{
cpp2::ExecutionResponse resp;
std::string query = "USE space_for_default;";
client_->execute(query, resp);
ASSERT_ERROR_CODE(resp, cpp2::ErrorCode::SUCCEEDED);
}
{
// submit
cpp2::ExecutionResponse resp;
std::string query = "SUBMIT JOB COMPACT";
client_->execute(query, resp);
ASSERT_ERROR_CODE(resp, cpp2::ErrorCode::SUCCEEDED);
DataSet expected({"New Job Id"});
expected.emplace_back(Row({
2
}));
ASSERT_TRUE(verifyDataSetWithoutOrder(resp, expected));
}
{
// submit
cpp2::ExecutionResponse resp;
std::string query = "SUBMIT JOB FLUSH";
client_->execute(query, resp);
ASSERT_ERROR_CODE(resp, cpp2::ErrorCode::SUCCEEDED);
DataSet expected({"New Job Id"});
expected.emplace_back(Row({
3
}));
ASSERT_TRUE(verifyDataSetWithoutOrder(resp, expected));
}
{
// show all
cpp2::ExecutionResponse resp;
std::string query = "SHOW JOBS";
client_->execute(query, resp);
ASSERT_ERROR_CODE(resp, cpp2::ErrorCode::SUCCEEDED);
nebula::DataSet expected({"Job Id", "Command", "Status", "Start Time", "Stop Time"});
expected.emplace_back(Row({
2, "COMPACT", "QUEUE", 0, 0,
}));
expected.emplace_back(Row({
3, "FLUSH", "QUEUE", 0, 0
}));
ASSERT_TRUE(verifyDataSetWithoutOrder(resp, expected));
}
// TODO current not support should move it into show
/*
{
// show one
cpp2::ExecutionResponse resp;
std::string query = "SHOW JOB 2";
client_->execute(query, resp);
ASSERT_ERROR_CODE(resp, cpp2::ErrorCode::SUCCEEDED);
nebula::DataSet expected(
{"Job Id(TaskId)", "Command(Dest)", "Status", "Start Time", "Stop Time"});
expected.emplace_back(Row({2, "COMPACT", "QUEUE", 0, 0}));
expected.emplace_back(Row({1, "127.0.0.1", "QUEUE", 0, 0}));
ASSERT_TRUE(verifyDataSetWithoutOrder(resp, expected));
}
{
// stop one
cpp2::ExecutionResponse resp;
std::string query = "STOP JOB 2";
client_->execute(query, resp);
ASSERT_ERROR_CODE(resp, cpp2::ErrorCode::SUCCEEDED);
nebula::DataSet expected({"Result"});
expected.emplace_back(Row({"Job stopped"}));
ASSERT_TRUE(verifyDataSetWithoutOrder(resp, expected));
}
{
// show all
cpp2::ExecutionResponse resp;
std::string query = "SHOW JOBS";
client_->execute(query, resp);
ASSERT_ERROR_CODE(resp, cpp2::ErrorCode::SUCCEEDED);
nebula::DataSet expected({"Job Id", "Command", "Status", "Start Time", "Stop Time"});
expected.emplace_back(Row({
2, "COMPACT", "STOPPED", 0, 0,
}));
expected.emplace_back(Row({
3, "FLUSH", "QUEUE", 0, 0
}));
ASSERT_TRUE(verifyDataSetWithoutOrder(resp, expected));
}
{
// recover
cpp2::ExecutionResponse resp;
std::string query = "RECOVER JOB";
client_->execute(query, resp);
ASSERT_ERROR_CODE(resp, cpp2::ErrorCode::SUCCEEDED);
nebula::DataSet expected({"Recovered job num"});
expected.emplace_back(Row({
0
}));
ASSERT_TRUE(verifyDataSetWithoutOrder(resp, expected));
}
*/
}
} // namespace graph
} // namespace nebula
# Copyright (c) 2020 vesoft inc. All rights reserved.
#
# This source code is licensed under Apache 2.0 License,
# attached with Common Clause Condition 1.0, found in the LICENSES directory.
#
set(GRAPH_TEST_LIB
$<TARGET_OBJECTS:mock_obj>
$<TARGET_OBJECTS:util_obj>
$<TARGET_OBJECTS:service_obj>
$<TARGET_OBJECTS:session_obj>
$<TARGET_OBJECTS:query_engine_obj>
$<TARGET_OBJECTS:graph_flags_obj>
$<TARGET_OBJECTS:parser_obj>
$<TARGET_OBJECTS:validator_obj>
$<TARGET_OBJECTS:expr_visitor_obj>
$<TARGET_OBJECTS:planner_obj>
$<TARGET_OBJECTS:executor_obj>
$<TARGET_OBJECTS:scheduler_obj>
$<TARGET_OBJECTS:idgenerator_obj>
$<TARGET_OBJECTS:context_obj>
$<TARGET_OBJECTS:graph_auth_obj>
$<TARGET_OBJECTS:optimizer_obj>
$<TARGET_OBJECTS:common_time_function_obj>
$<TARGET_OBJECTS:common_expression_obj>
$<TARGET_OBJECTS:common_http_client_obj>
$<TARGET_OBJECTS:common_network_obj>
$<TARGET_OBJECTS:common_process_obj>
$<TARGET_OBJECTS:common_graph_client_obj>
$<TARGET_OBJECTS:common_storage_client_base_obj>
$<TARGET_OBJECTS:common_graph_storage_client_obj>
$<TARGET_OBJECTS:common_meta_client_obj>
$<TARGET_OBJECTS:common_stats_obj>
$<TARGET_OBJECTS:common_meta_thrift_obj>
$<TARGET_OBJECTS:common_graph_thrift_obj>
$<TARGET_OBJECTS:common_common_thrift_obj>
$<TARGET_OBJECTS:common_storage_thrift_obj>
$<TARGET_OBJECTS:common_thrift_obj>
$<TARGET_OBJECTS:common_meta_obj>
$<TARGET_OBJECTS:common_thread_obj>
$<TARGET_OBJECTS:common_time_obj>
$<TARGET_OBJECTS:common_fs_obj>
$<TARGET_OBJECTS:common_base_obj>
$<TARGET_OBJECTS:common_concurrent_obj>
$<TARGET_OBJECTS:common_datatypes_obj>
$<TARGET_OBJECTS:common_conf_obj>
$<TARGET_OBJECTS:common_file_based_cluster_id_man_obj>
$<TARGET_OBJECTS:common_charset_obj>
$<TARGET_OBJECTS:common_function_manager_obj>
$<TARGET_OBJECTS:common_http_client_obj>
$<TARGET_OBJECTS:common_encryption_obj>
$<TARGET_OBJECTS:common_agg_function_obj>
$<TARGET_OBJECTS:common_time_utils_obj>
)
nebula_add_test(
NAME
mock_server_test
SOURCES
TestMock.cpp
OBJECTS
${GRAPH_TEST_LIB}
LIBRARIES
${THRIFT_LIBRARIES}
gtest
gtest_main
proxygenhttpserver
proxygenlib
wangle
)
nebula_add_test(
NAME
schema_test
SOURCES
SchemaTest.cpp
OBJECTS
${GRAPH_TEST_LIB}
LIBRARIES
${THRIFT_LIBRARIES}
proxygenhttpserver
proxygenlib
wangle
gtest
gtest_main
)
nebula_add_test(
NAME
acl_test
SOURCES
ACLTest.cpp
OBJECTS
${GRAPH_TEST_LIB}
LIBRARIES
${THRIFT_LIBRARIES}
gtest
gtest_main
proxygenhttpserver
proxygenlib
wangle
)
nebula_add_test(
NAME
balance_test
SOURCES
BalanceTest.cpp
OBJECTS
${GRAPH_TEST_LIB}
LIBRARIES
proxygenhttpserver
proxygenlib
${THRIFT_LIBRARIES}
wangle
gtest
gtest_main
)
nebula_add_test(
NAME
admin_job_test
SOURCES
AdminJobTest.cpp
OBJECTS
${GRAPH_TEST_LIB}
LIBRARIES
proxygenhttpserver
proxygenlib
${THRIFT_LIBRARIES}
wangle
gtest
gtest_main
)
nebula_add_test(
NAME
snapshot_test
SOURCES
SnapshotTest.cpp
OBJECTS
${GRAPH_TEST_LIB}
LIBRARIES
${THRIFT_LIBRARIES}
proxygenhttpserver
proxygenlib
wangle
gtest
gtest_main
)
/* Copyright (c) 2020 vesoft inc. All rights reserved.
*
* This source code is licensed under Apache 2.0 License,
* attached with Common Clause Condition 1.0, found in the LICENSES directory.
*/
#include "common/base/Status.h"
#include "common/network/NetworkUtils.h"
#include "common/interface/gen-cpp2/common_types.h"
#include "mock/test/TestEnv.h"
#include "mock/test/TestBase.h"
#include <gtest/gtest.h>
DECLARE_int32(heartbeat_interval_secs);
namespace nebula {
namespace graph {
class SchemaTest : public TestBase {
public:
void SetUp() override {
TestBase::SetUp();
};
void TearDown() override {
TestBase::TearDown();
};
static void SetUpTestCase() {
client_ = gEnv->getGraphClient();
ASSERT_NE(nullptr, client_);
}
static void TearDownTestCase() {
client_.reset();
}
protected:
static std::unique_ptr<GraphClient> client_;
};
std::unique_ptr<GraphClient> SchemaTest::client_{nullptr};
TEST_F(SchemaTest, TestSpace) {
{
cpp2::ExecutionResponse resp;
std::string query = "CREATE SPACE space_for_default(partition_num=9, replica_factor=1);";
auto code = client_->execute(query, resp);
ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code);
}
{
cpp2::ExecutionResponse resp;
std::string query = "CREATE SPACE space_set_vid_type(partition_num=9, "
"replica_factor=1, vid_type=FIXED_STRING(20));";
auto code = client_->execute(query, resp);
ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code);
}
{
cpp2::ExecutionResponse resp;
std::string query = "DESC SPACE space_for_default;";
auto code = client_->execute(query, resp);
ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code);
std::vector<std::string> colNames = {"ID", "Name", "Partition Number", "Replica Factor",
"Charset", "Collate", "Vid Type"};
ASSERT_TRUE(verifyColNames(resp, colNames));
std::vector<Value> values = {1, "space_for_default", 9,
1, "utf8", "utf8_bin", "FIXED_STRING(8)"};
ASSERT_TRUE(verifyValues(resp, values));
}
{
cpp2::ExecutionResponse resp;
std::string query = "CREATE SPACE space_2("
"partition_num=9, replica_factor=1, vid_type=FIXED_STRING(20));";
auto code = client_->execute(query, resp);
ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code);
}
{
cpp2::ExecutionResponse resp;
std::string query = "SHOW SPACES;";
auto code = client_->execute(query, resp);
ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code);
std::vector<std::string> colNames = {"Name"};
ASSERT_TRUE(verifyColNames(resp, colNames));
std::vector<std::vector<Value>> values = {
{"space_2"},
{"space_for_default"},
{"space_set_vid_type"}
};
ASSERT_TRUE(verifyValues(resp, values));
}
// Show Create space
std::string createSpaceStr;
{
cpp2::ExecutionResponse resp;
std::string query = "SHOW CREATE SPACE space_2";
auto code = client_->execute(query, resp);
ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code);
createSpaceStr = "CREATE SPACE `space_2` ("
"partition_num = 9, "
"replica_factor = 1, "
"charset = utf8, "
"collate = utf8_bin, "
"vid_type = FIXED_STRING(20))";
std::vector<std::string> colNames = {"Space", "Create Space"};
ASSERT_TRUE(verifyColNames(resp, colNames));
std::vector<Value> values = {"space_2", createSpaceStr};
ASSERT_TRUE(verifyValues(resp, values));
}
// Drop space
{
cpp2::ExecutionResponse resp;
std::string query = "DROP SPACE space_2";
auto code = client_->execute(query, resp);
ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code);
}
{
cpp2::ExecutionResponse resp;
std::string query = "SHOW SPACES;";
auto code = client_->execute(query, resp);
ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code);
std::vector<std::string> colNames = {"Name"};
ASSERT_TRUE(verifyColNames(resp, colNames));
std::vector<std::vector<Value>> values = {{"space_for_default"}, {"space_set_vid_type"}};
ASSERT_TRUE(verifyValues(resp, values));
}
// use show create space result
{
cpp2::ExecutionResponse resp;
auto code = client_->execute(createSpaceStr, resp);
ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code);
std::string query = "SHOW SPACES;";
code = client_->execute(query, resp);
ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code);
std::vector<std::string> colNames = {"Name"};
ASSERT_TRUE(verifyColNames(resp, colNames));
std::vector<std::vector<Value>> values = {
{"space_2"},
{"space_for_default"},
{"space_set_vid_type"}
};
ASSERT_TRUE(verifyValues(resp, values));
}
}
TEST_F(SchemaTest, TestTag) {
sleep(FLAGS_heartbeat_interval_secs + 1);
{
cpp2::ExecutionResponse resp;
std::string query = "USE space_for_default";
auto code = client_->execute(query, resp);
ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code);
}
{
cpp2::ExecutionResponse resp;
std::string query = "CREATE TAG student(name STRING NOT NULL, "
"age INT8 DEFAULT 18, grade FIXED_STRING(10), start INT64 DEFAULT 2020)"
" ttl_duration = 3600, ttl_col = \"start\";";
auto code = client_->execute(query, resp);
ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code);
}
{
cpp2::ExecutionResponse resp;
std::string query = "DESC TAG student;";
auto code = client_->execute(query, resp);
ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code);
ASSERT_TRUE(resp.__isset.data);
std::vector<std::string> colNames = {"Field", "Type", "Null", "Default"};
ASSERT_TRUE(verifyColNames(resp, colNames));
std::vector<std::vector<Value>> values = {
{"name", "string", "NO", Value::kEmpty},
{"age", "int8", "YES", 18},
{"grade", "fixed_string(10)", "YES", Value::kEmpty},
{"start", "int64", "YES", 2020}};
ASSERT_TRUE(verifyValues(resp, values));
}
{
cpp2::ExecutionResponse resp;
std::string query = "CREATE TAG person(name STRING DEFAULT \"\", amount FLOAT);";
auto code = client_->execute(query, resp);
ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code);
}
{
cpp2::ExecutionResponse resp;
std::string query = "SHOW TAGS;";
auto code = client_->execute(query, resp);
ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code);
std::vector<std::string> colNames = {"Name"};
ASSERT_TRUE(verifyColNames(resp, colNames));
std::vector<std::vector<Value>> values = {{"person"}, {"student"}};
ASSERT_TRUE(verifyValues(resp, values));
}
// Show Create tag
std::string createTagStr;
{
cpp2::ExecutionResponse resp;
std::string query = "SHOW CREATE TAG student";
auto code = client_->execute(query, resp);
ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code);
createTagStr = "CREATE TAG `student` (\n"
" `name` string NOT NULL,\n"
" `age` int8 NULL DEFAULT 18,\n"
" `grade` fixed_string(10) NULL,\n"
" `start` int64 NULL DEFAULT 2020\n"
") ttl_duration = 3600, ttl_col = \"start\"";
std::vector<std::string> colNames = {"Tag", "Create Tag"};
ASSERT_TRUE(verifyColNames(resp, colNames));
std::vector<Value> values = {"student", createTagStr};
ASSERT_TRUE(verifyValues(resp, values));
}
{
cpp2::ExecutionResponse resp;
std::string query = "DROP TAG student;";
auto code = client_->execute(query, resp);
ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code);
}
{
cpp2::ExecutionResponse resp;
std::string query = "SHOW TAGS;";
auto code = client_->execute(query, resp);
ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code);
std::vector<std::string> colNames = {"Name"};
ASSERT_TRUE(verifyColNames(resp, colNames));
std::vector<Value> values = {"person"};
ASSERT_TRUE(verifyValues(resp, values));
}
// Check the show create tag result is ok
{
cpp2::ExecutionResponse resp;
auto code = client_->execute(createTagStr, resp);
ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code);
std::string query = "SHOW TAGS;";
code = client_->execute(query, resp);
ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code);
std::vector<std::string> colNames = {"Name"};
ASSERT_TRUE(verifyColNames(resp, colNames));
std::vector<std::vector<Value>> values = {{"person"}, {"student"}};
ASSERT_TRUE(verifyValues(resp, values));
}
{
cpp2::ExecutionResponse resp;
std::string query = "CREATE SPACE A; USE A; "
"CREATE TAG tag1(name STRING, age INT8, grade FIXED_STRING(10));";
auto code = client_->execute(query, resp);
ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code);
}
}
TEST_F(SchemaTest, TestEdge) {
{
cpp2::ExecutionResponse resp;
std::string query = "USE space_for_default; "
"CREATE EDGE schoolmate(start int NOT NULL, end int);";
auto code = client_->execute(query, resp);
ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code);
}
{
cpp2::ExecutionResponse resp;
std::string query = "DESC EDGE schoolmate;";
auto code = client_->execute(query, resp);
ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code);
ASSERT_TRUE(resp.__isset.data);
std::vector<std::string> colNames = {"Field", "Type", "Null", "Default"};
ASSERT_TRUE(verifyColNames(resp, colNames));
std::vector<std::vector<Value>> values = {
{"start", "int64", "NO", Value::kEmpty},
{"end", "int64", "YES", Value::kEmpty}};
ASSERT_TRUE(verifyValues(resp, values));
}
{
cpp2::ExecutionResponse resp;
std::string query = "CREATE EDGE like(name STRING NOT NULL DEFAULT \"\", amount FLOAT);";
auto code = client_->execute(query, resp);
ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code);
}
{
cpp2::ExecutionResponse resp;
std::string query = "SHOW EDGES;";
auto code = client_->execute(query, resp);
ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code);
std::vector<std::string> colNames = {"Name"};
ASSERT_TRUE(verifyColNames(resp, colNames));
std::vector<std::vector<Value>> values = {{"like"}, {"schoolmate"}};
ASSERT_TRUE(verifyValues(resp, values));
}
// Show Create edge
std::string createEdgeStr;
{
cpp2::ExecutionResponse resp;
std::string query = "SHOW CREATE EDGE like";
auto code = client_->execute(query, resp);
ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code);
createEdgeStr = "CREATE EDGE `like` (\n"
" `name` string NOT NULL DEFAULT \"\",\n"
" `amount` float NULL\n"
") ttl_duration = 0, ttl_col = \"\"";
std::vector<std::string> colNames = {"Edge", "Create Edge"};
ASSERT_TRUE(verifyColNames(resp, colNames));
std::vector<Value> values = {"like", createEdgeStr};
ASSERT_TRUE(verifyValues(resp, values));
}
{
cpp2::ExecutionResponse resp;
std::string query = "DROP EDGE like;";
auto code = client_->execute(query, resp);
ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code);
}
{
cpp2::ExecutionResponse resp;
std::string query = "SHOW EDGES;";
auto code = client_->execute(query, resp);
ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code);
std::vector<std::string> colNames = {"Name"};
ASSERT_TRUE(verifyColNames(resp, colNames));
std::vector<Value> values = {"schoolmate"};
ASSERT_TRUE(verifyValues(resp, values));
}
// Check the show create edge result is ok
{
cpp2::ExecutionResponse resp;
auto code = client_->execute(createEdgeStr, resp);
ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code);
std::string query = "SHOW EDGES;";
code = client_->execute(query, resp);
ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code);
std::vector<std::string> colNames = {"Name"};
ASSERT_TRUE(verifyColNames(resp, colNames));
std::vector<std::vector<Value>> values = {{"like"}, {"schoolmate"}};
ASSERT_TRUE(verifyValues(resp, values));
}
{
cpp2::ExecutionResponse resp;
std::string query = "CREATE SPACE B; USE B; "
"CREATE EDGE edge1(name STRING, age INT8, grade FIXED_STRING(10));";
auto code = client_->execute(query, resp);
ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code);
}
}
TEST_F(SchemaTest, TestAlterTag) {
{
cpp2::ExecutionResponse resp;
std::string query = "CREATE TAG alterTag(col1 STRING, col2 INT8, "
"col3 DOUBLE, col4 FIXED_STRING(10));";
auto code = client_->execute(query, resp);
ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code);
}
{
cpp2::ExecutionResponse resp;
std::string query = "ALTER TAG alterTag "
"ADD (col5 TIMESTAMP, col6 DATE NOT NULL), "
"CHANGE (col2 INT8 DEFAULT 10), "
"DROP (col4)";
auto code = client_->execute(query, resp);
ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code);
}
{
cpp2::ExecutionResponse resp;
std::string query = "DESC TAG alterTag;";
auto code = client_->execute(query, resp);
ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code);
ASSERT_TRUE(resp.__isset.data);
std::vector<std::string> colNames = {"Field", "Type", "Null", "Default"};
ASSERT_TRUE(verifyColNames(resp, colNames));
std::vector<std::vector<Value>> values = {
{Value("col1"), Value("string"), Value("YES"), Value()},
{Value("col2"), Value("int8"), Value("YES"), Value(10)},
{Value("col3"), Value("double"), Value("YES"), Value()},
{Value("col5"), Value("timestamp"), Value("YES"), Value()},
{Value("col6"), Value("date"), Value("NO"), Value()}};
ASSERT_TRUE(verifyValues(resp, values));
}
}
TEST_F(SchemaTest, TestAlterEdge) {
{
cpp2::ExecutionResponse resp;
std::string query = "CREATE EDGE alterEdge(col1 STRING, col2 INT8, "
"col3 DOUBLE, col4 FIXED_STRING(10));";
auto code = client_->execute(query, resp);
ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code);
}
{
cpp2::ExecutionResponse resp;
std::string query = "ALTER EDGE alterEdge "
"ADD (col5 TIMESTAMP, col6 DATE NOT NULL), "
"CHANGE (col2 INT8 DEFAULT 10), "
"DROP (col4)";
auto code = client_->execute(query, resp);
ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code);
}
{
cpp2::ExecutionResponse resp;
std::string query = "DESC EDGE alterEdge;";
auto code = client_->execute(query, resp);
ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code);
ASSERT_TRUE(resp.__isset.data);
std::vector<std::string> colNames = {"Field", "Type", "Null", "Default"};
ASSERT_TRUE(verifyColNames(resp, colNames));
std::vector<std::vector<Value>> values = {
{Value("col1"), Value("string"), Value("YES"), Value()},
{Value("col2"), Value("int8"), Value("YES"), Value(10)},
{Value("col3"), Value("double"), Value("YES"), Value()},
{Value("col5"), Value("timestamp"), Value("YES"), Value()},
{Value("col6"), Value("date"), Value("NO"), Value()}};
ASSERT_TRUE(verifyValues(resp, values));
}
}
TEST_F(SchemaTest, TestInsert) {
sleep(FLAGS_heartbeat_interval_secs + 1);
{
cpp2::ExecutionResponse resp;
std::string query = "USE space_for_default;";
auto code = client_->execute(query, resp);
ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code);
}
{
cpp2::ExecutionResponse resp;
std::string query = "USE space_for_default; INSERT VERTEX student(name, age, grade) "
"VALUES \"Tom\":(\"Tom\", 18, \"three\");";
auto code = client_->execute(query, resp);
ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code);
}
{
cpp2::ExecutionResponse resp;
std::string query = "INSERT VERTEX student(name, age, grade) "
"VALUES \"Lily\":(\"Lily\", 18, \"three\");";
auto code = client_->execute(query, resp);
ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code);
}
{
cpp2::ExecutionResponse resp;
std::string query = "INSERT VERTEX student(name, age, grade) "
"VALUES \"Tom\":(\"Tom\", 18, \"three\");"
"INSERT VERTEX student(name, age, grade) "
"VALUES \"Tom\":(\"Tom\", 18, \"three\");";
auto code = client_->execute(query, resp);
ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code);
}
{
cpp2::ExecutionResponse resp;
std::string query = "INSERT VERTEX student(name, age, grade) "
"VALUES 100:(\"100\", 17, \"three\");";
auto code = client_->execute(query, resp);
ASSERT_NE(cpp2::ErrorCode::SUCCEEDED, code);
}
{
cpp2::ExecutionResponse resp;
std::string query = "INSERT EDGE schoolmate(start, end) "
"VALUES \"Tom\"->\"Lily\":(2009, 2011)";
auto code = client_->execute(query, resp);
ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code);
}
{
cpp2::ExecutionResponse resp;
std::string query = "INSERT EDGE schoolmate(start, end) "
"VALUES \"Tom\"->\"Lily\":(2009, 2011)";
auto code = client_->execute(query, resp);
ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code);
}
{
cpp2::ExecutionResponse resp;
std::string query = "INSERT EDGE schoolmate(start, end) "
"VALUES \"Tom\"->\"Lily\":(2009, 2011);"
"INSERT EDGE schoolmate(start, end) "
"VALUES \"Tom\"->\"Lily\":(2009, 2011)";
auto code = client_->execute(query, resp);
ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code);
}
}
} // namespace graph
} // namespace nebula
/* Copyright (c) 2020 vesoft inc. All rights reserved.
*
* This source code is licensed under Apache 2.0 License,
* attached with Common Clause Condition 1.0, found in the LICENSES directory.
*/
#include "common/base/Status.h"
#include "common/network/NetworkUtils.h"
#include "common/interface/gen-cpp2/common_types.h"
#include "mock/test/TestEnv.h"
#include "mock/test/TestBase.h"
#include "context/QueryExpressionContext.h"
#include <gtest/gtest.h>
DECLARE_int32(heartbeat_interval_secs);
namespace nebula {
namespace graph {
class MockServerTest : public TestBase {
public:
void SetUp() override {
TestBase::SetUp();
};
void TearDown() override {
TestBase::TearDown();
};
};
TEST_F(MockServerTest, TestMeta) {
GraphSpaceID spaceId1 = 0;
GraphSpaceID spaceId2 = 0;
auto metaClient = gEnv->getMetaClient();
// Test space
{
// Create space
std::string spaceName1 = "TEST_SPACE1";
meta::cpp2::SpaceDesc spaceDesc1;
spaceDesc1.set_space_name(spaceName1);
spaceDesc1.set_partition_num(10);
spaceDesc1.set_replica_factor(1);
bool ifNotExists = true;
auto status = metaClient->createSpace(spaceDesc1, ifNotExists).get();
spaceId1 = status.value();
std::string spaceName2 = "TEST_SPACE2";
meta::cpp2::SpaceDesc spaceDesc2;
spaceDesc2.set_space_name(spaceName2);
spaceDesc2.set_partition_num(100);
spaceDesc2.set_replica_factor(3);
status = metaClient->createSpace(spaceDesc2, ifNotExists).get();
spaceId2 = status.value();
// Get space
auto getStatus = metaClient->getSpace(spaceName1).get();
ASSERT_TRUE(getStatus.ok());
ASSERT_EQ(spaceId1, getStatus.value().get_space_id());
ASSERT_EQ(10, getStatus.value().get_properties().get_partition_num());
ASSERT_EQ(1, getStatus.value().get_properties().get_replica_factor());
ASSERT_EQ(8, *getStatus.value().get_properties().get_vid_type().get_type_length());
getStatus = metaClient->getSpace(spaceName2).get();
ASSERT_TRUE(getStatus.ok());
ASSERT_EQ(spaceId2, getStatus.value().get_space_id());
ASSERT_EQ(100, getStatus.value().get_properties().get_partition_num());
ASSERT_EQ(3, getStatus.value().get_properties().get_replica_factor());
ASSERT_EQ(8, *getStatus.value().get_properties().get_vid_type().get_type_length());
// List spaces
auto listStatus = metaClient->listSpaces().get();
ASSERT_TRUE(listStatus.ok());
auto spaces = listStatus.value();
ASSERT_EQ(2, spaces.size());
std::vector<meta::SpaceIdName> expected;
expected.emplace_back(spaceId2, spaceName2);
expected.emplace_back(spaceId1, spaceName1);
ASSERT_EQ(expected, spaces);
}
QueryExpressionContext ctx;
// Test tag
{
// Create tag
for (auto i = 0u; i < 10; i++) {
meta::cpp2::Schema tagSchema;
meta::cpp2::ColumnDef col;
col.set_name(folly::stringPrintf("col_%d", i));
col.type.set_type(meta::cpp2::PropertyType::STRING);
ConstantExpression defaultValue("NULL");
col.set_default_value(defaultValue.encode());
std::vector<meta::cpp2::ColumnDef> cols;
cols.emplace_back(col);
tagSchema.set_columns(std::move(cols));
auto status = metaClient->createTagSchema(spaceId1,
folly::stringPrintf("tag_%d", i), tagSchema, false).get();
ASSERT_TRUE(status.ok());
}
// Get tag
for (auto i = 0u; i < 10; i++) {
auto status = metaClient->getTagSchema(spaceId1,
folly::stringPrintf("tag_%d", i)).get();
ASSERT_TRUE(status.ok());
auto schema = status.value();
ASSERT_EQ(1, schema.get_columns().size());
ASSERT_EQ(folly::stringPrintf("col_%d", i), schema.get_columns()[0].get_name());
ASSERT_EQ(meta::cpp2::PropertyType::STRING,
schema.get_columns()[0].get_type().get_type());
ASSERT_EQ("NULL", Expression::decode(
*schema.get_columns()[0].get_default_value())->eval(ctx(nullptr)).getStr());
}
// List tags
auto listStatus = metaClient->listTagSchemas(spaceId1).get();
ASSERT_TRUE(listStatus.ok());
ASSERT_EQ(10, listStatus.value().size());
// Drop tag
for (auto i = 5u; i < 10; i++) {
auto status = metaClient->dropTagSchema(spaceId1,
folly::stringPrintf("tag_%d", i), true).get();
ASSERT_TRUE(status.ok());
}
// List tags
listStatus = metaClient->listTagSchemas(spaceId1).get();
ASSERT_TRUE(listStatus.ok());
ASSERT_EQ(5, listStatus.value().size());
}
// Test edge
{
// Create edge
for (auto i = 0u; i < 10; i++) {
meta::cpp2::Schema edgeSchema;
meta::cpp2::ColumnDef col;
col.set_name(folly::stringPrintf("col_%d", i));
col.type.set_type(meta::cpp2::PropertyType::STRING);
ConstantExpression defaultValue("NULL");
col.set_default_value(defaultValue.encode());
std::vector<meta::cpp2::ColumnDef> cols;
cols.emplace_back(col);
edgeSchema.set_columns(std::move(cols));
auto status = metaClient->createEdgeSchema(spaceId1,
folly::stringPrintf("edge_%d", i), edgeSchema, false).get();
ASSERT_TRUE(status.ok());
}
// Get edge
for (auto i = 0u; i < 10; i++) {
auto status = metaClient->getEdgeSchema(spaceId1,
folly::stringPrintf("edge_%d", i)).get();
ASSERT_TRUE(status.ok());
auto schema = status.value();
ASSERT_EQ(1, schema.get_columns().size());
ASSERT_EQ(folly::stringPrintf("col_%d", i), schema.get_columns()[0].get_name());
ASSERT_EQ(meta::cpp2::PropertyType::STRING,
schema.get_columns()[0].get_type().get_type());
ASSERT_EQ("NULL", Expression::decode(
*schema.get_columns()[0].get_default_value())->eval(ctx(nullptr)).getStr());
}
// List edges
auto listStatus = metaClient->listEdgeSchemas(spaceId1).get();
ASSERT_TRUE(listStatus.ok());
ASSERT_EQ(10, listStatus.value().size());
// Drop edge
for (auto i = 5u; i < 10; i++) {
auto status = metaClient->dropEdgeSchema(spaceId1,
folly::stringPrintf("edge_%d", i), true).get();
ASSERT_TRUE(status.ok());
}
// List edges
listStatus = metaClient->listEdgeSchemas(spaceId1).get();
ASSERT_TRUE(listStatus.ok());
ASSERT_EQ(5, listStatus.value().size());
}
sleep(FLAGS_heartbeat_interval_secs + 1);
}
TEST_F(MockServerTest, DISABLED_TestStorage) {
auto storageClient = gEnv->getStorageClient();
GraphSpaceID space = 1;
std::vector<Value> props;
props.emplace_back("hello");
storage::cpp2::NewTag tag;
tag.set_tag_id(3);
tag.set_props(std::move(props));
std::vector<storage::cpp2::NewTag> tags;
tags.emplace_back(tag);
storage::cpp2::NewVertex vertex;
vertex.set_id("2020");
vertex.set_tags(std::move(tags));
std::vector<storage::cpp2::NewVertex> vertices;
vertices.emplace_back(std::move(vertex));
std::unordered_map<TagID, std::vector<std::string>> propNames;
propNames[3] = {"col"};
auto resp = storageClient->addVertices(space, vertices, propNames, false).get();
ASSERT_TRUE(resp.succeeded());
}
} // namespace graph
} // namespace nebula
......@@ -32,10 +32,12 @@ class TestInsert2(NebulaTestSuite):
def test_insert_out_of_range_id_size(self):
resp = self.execute('INSERT VERTEX student(name, age) VALUES "12345678901":("Tom", "2")')
self.check_resp_failed(resp)
self.check_error_msg(resp, 'Storage Error: Invalid vid.')
def test_insert_not_null_prop(self):
resp = self.execute('INSERT VERTEX student(name, age) VALUES "Tom":(NULL, 12)')
self.check_resp_failed(resp)
self.check_error_msg(resp, "Storage Error: The not null field cannot be null.")
def test_insert_with_fix_string(self):
# succeeded
......
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment