Bring changes from master to project-pineapples (#477)
* Fix aggregation functions on `null` and group-by inputs (#448) * Upgrade Antrl to 4.10.1 and remove antlr_lock (#441) * Update clang-tidy job (#476) * Add parser stress test (#463) NOTE: Doing this to have buildable comments on the project-pineapples branch Co-authored-by: gvolfing <107616712+gvolfing@users.noreply.github.com> Co-authored-by: Jure Bajic <jure.bajic@memgraph.com>
This commit is contained in:
@@ -73,6 +73,16 @@ Feature: Aggregations
|
||||
| n |
|
||||
| 5 |
|
||||
|
||||
Scenario: Count test 07:
|
||||
Given an empty graph
|
||||
When executing query:
|
||||
"""
|
||||
RETURN count(null)
|
||||
"""
|
||||
Then the result should be:
|
||||
| count(null) |
|
||||
| 0 |
|
||||
|
||||
Scenario: Sum test 01:
|
||||
Given an empty graph
|
||||
And having executed
|
||||
@@ -114,6 +124,16 @@ Feature: Aggregations
|
||||
| 4 | 0 |
|
||||
| 4 | 1 |
|
||||
|
||||
Scenario: Sum test 04:
|
||||
Given an empty graph
|
||||
When executing query:
|
||||
"""
|
||||
RETURN sum(null)
|
||||
"""
|
||||
Then the result should be:
|
||||
| sum(null) |
|
||||
| 0 |
|
||||
|
||||
Scenario: Avg test 01:
|
||||
Given an empty graph
|
||||
And having executed
|
||||
@@ -155,6 +175,16 @@ Feature: Aggregations
|
||||
| 2.0 | 0 |
|
||||
| 4.0 | 1 |
|
||||
|
||||
Scenario: Avg test 04:
|
||||
Given an empty graph
|
||||
When executing query:
|
||||
"""
|
||||
RETURN avg(null)
|
||||
"""
|
||||
Then the result should be:
|
||||
| avg(null) |
|
||||
| null |
|
||||
|
||||
Scenario: Min test 01:
|
||||
Given an empty graph
|
||||
And having executed
|
||||
@@ -196,6 +226,16 @@ Feature: Aggregations
|
||||
| 1 | 0 |
|
||||
| 4 | 1 |
|
||||
|
||||
Scenario: Min test 04:
|
||||
Given an empty graph
|
||||
When executing query:
|
||||
"""
|
||||
RETURN min(null)
|
||||
"""
|
||||
Then the result should be:
|
||||
| min(null) |
|
||||
| null |
|
||||
|
||||
Scenario: Max test 01:
|
||||
Given an empty graph
|
||||
And having executed
|
||||
@@ -237,6 +277,16 @@ Feature: Aggregations
|
||||
| 3 | 0 |
|
||||
| 4 | 1 |
|
||||
|
||||
Scenario: Max test 04:
|
||||
Given an empty graph
|
||||
When executing query:
|
||||
"""
|
||||
RETURN max(null)
|
||||
"""
|
||||
Then the result should be:
|
||||
| max(null) |
|
||||
| null |
|
||||
|
||||
Scenario: Collect test 01:
|
||||
Given an empty graph
|
||||
And having executed
|
||||
@@ -279,3 +329,18 @@ Feature: Aggregations
|
||||
| n |
|
||||
| {a_key: 13, b_key: 11, c_key: 12} |
|
||||
|
||||
Scenario: Combined aggregations - some evauluates to null:
|
||||
Given an empty graph
|
||||
And having executed
|
||||
"""
|
||||
CREATE (f)
|
||||
CREATE (n {property: 1})
|
||||
"""
|
||||
When executing query:
|
||||
"""
|
||||
MATCH (n) RETURN count(n) < n.property, count(n.property), count(n), avg(n.property), min(n.property), max(n.property), sum(n.property)
|
||||
"""
|
||||
Then the result should be:
|
||||
| count(n) < n.property | count(n.property) | count(n) | avg(n.property) | min(n.property) | max(n.property) | sum(n.property) |
|
||||
| false | 1 | 1 | 1.0 | 1 | 1 | 1 |
|
||||
| null | 0 | 1 | null | null | null | 0 |
|
||||
|
||||
@@ -20,6 +20,15 @@
|
||||
#include "utils/signals.hpp"
|
||||
#include "utils/stacktrace.hpp"
|
||||
|
||||
// This test was introduced because Antlr Cpp runtime doesn't work well in a
|
||||
// highly concurrent environment. Interpreter `interpret.hpp` contains
|
||||
// `antlr_lock` used to avoid crashes.
|
||||
// v4.6 and before -> Crashes.
|
||||
// v4.8 -> Does NOT crash but sometimes this tests does NOT finish.
|
||||
// Looks like a deadlock. -> The lock is still REQUIRED.
|
||||
// v4.9 -> Seems to be working.
|
||||
// v4.10 -> Seems to be working as well. -> antlr_lock removed
|
||||
|
||||
using namespace std::chrono_literals;
|
||||
|
||||
TEST(Antlr, Sigsegv) {
|
||||
|
||||
@@ -17,3 +17,6 @@ endfunction(add_stress_test)
|
||||
|
||||
add_stress_test(long_running.cpp)
|
||||
target_link_libraries(${test_prefix}long_running mg-communication mg-io mg-utils)
|
||||
|
||||
add_stress_test(parser.cpp)
|
||||
target_link_libraries(${test_prefix}parser mg-communication mg-io mg-utils mgclient)
|
||||
|
||||
@@ -26,6 +26,11 @@ SMALL_DATASET = [
|
||||
"options": ["--vertex-count", "40000", "--create-pack-size", "100"],
|
||||
"timeout": 5,
|
||||
},
|
||||
{
|
||||
"test": "parser.cpp",
|
||||
"options": ["--per-worker-query-count", "1000"],
|
||||
"timeout": 5,
|
||||
},
|
||||
{
|
||||
"test": "long_running.cpp",
|
||||
"options": ["--vertex-count", "1000", "--edge-count", "5000", "--max-time", "1", "--verify", "20"],
|
||||
@@ -42,30 +47,35 @@ SMALL_DATASET = [
|
||||
# bipartite.py and create_match.py run for approx. 15min
|
||||
# long_running runs for 5min x 6 times = 30min
|
||||
# long_running runs for 8h
|
||||
LARGE_DATASET = [
|
||||
{
|
||||
"test": "bipartite.py",
|
||||
"options": ["--u-count", "300", "--v-count", "300"],
|
||||
"timeout": 30,
|
||||
},
|
||||
{
|
||||
"test": "create_match.py",
|
||||
"options": ["--vertex-count", "500000", "--create-pack-size", "500"],
|
||||
"timeout": 30,
|
||||
},
|
||||
] + [
|
||||
{
|
||||
"test": "long_running.cpp",
|
||||
"options": ["--vertex-count", "10000", "--edge-count", "40000", "--max-time", "5", "--verify", "60"],
|
||||
"timeout": 16,
|
||||
},
|
||||
] * 6 + [
|
||||
{
|
||||
"test": "long_running.cpp",
|
||||
"options": ["--vertex-count", "200000", "--edge-count", "1000000", "--max-time", "480", "--verify", "300"],
|
||||
"timeout": 500,
|
||||
},
|
||||
]
|
||||
LARGE_DATASET = (
|
||||
[
|
||||
{
|
||||
"test": "bipartite.py",
|
||||
"options": ["--u-count", "300", "--v-count", "300"],
|
||||
"timeout": 30,
|
||||
},
|
||||
{
|
||||
"test": "create_match.py",
|
||||
"options": ["--vertex-count", "500000", "--create-pack-size", "500"],
|
||||
"timeout": 30,
|
||||
},
|
||||
]
|
||||
+ [
|
||||
{
|
||||
"test": "long_running.cpp",
|
||||
"options": ["--vertex-count", "10000", "--edge-count", "40000", "--max-time", "5", "--verify", "60"],
|
||||
"timeout": 16,
|
||||
},
|
||||
]
|
||||
* 6
|
||||
+ [
|
||||
{
|
||||
"test": "long_running.cpp",
|
||||
"options": ["--vertex-count", "200000", "--edge-count", "1000000", "--max-time", "480", "--verify", "300"],
|
||||
"timeout": 500,
|
||||
},
|
||||
]
|
||||
)
|
||||
|
||||
# paths
|
||||
SCRIPT_DIR = os.path.dirname(os.path.realpath(__file__))
|
||||
@@ -101,8 +111,7 @@ def run_test(args, test, options, timeout):
|
||||
# find binary
|
||||
if test.endswith(".py"):
|
||||
logging = "DEBUG" if args.verbose else "WARNING"
|
||||
binary = [args.python, "-u", os.path.join(SCRIPT_DIR, test),
|
||||
"--logging", logging]
|
||||
binary = [args.python, "-u", os.path.join(SCRIPT_DIR, test), "--logging", logging]
|
||||
elif test.endswith(".cpp"):
|
||||
exe = os.path.join(BUILD_DIR, "tests", "stress", test[:-4])
|
||||
binary = [exe]
|
||||
@@ -112,11 +121,10 @@ def run_test(args, test, options, timeout):
|
||||
# start test
|
||||
cmd = binary + ["--worker-count", str(THREADS)] + options
|
||||
start = time.time()
|
||||
ret_test = subprocess.run(cmd, cwd = SCRIPT_DIR, timeout = timeout * 60)
|
||||
ret_test = subprocess.run(cmd, cwd=SCRIPT_DIR, timeout=timeout * 60)
|
||||
|
||||
if ret_test.returncode != 0:
|
||||
raise Exception("Test '{}' binary returned non-zero ({})!".format(
|
||||
test, ret_test.returncode))
|
||||
raise Exception("Test '{}' binary returned non-zero ({})!".format(test, ret_test.returncode))
|
||||
|
||||
runtime = time.time() - start
|
||||
print(" Done after {:.3f} seconds".format(runtime))
|
||||
@@ -125,39 +133,54 @@ def run_test(args, test, options, timeout):
|
||||
|
||||
|
||||
# parse arguments
|
||||
parser = argparse.ArgumentParser(description = "Run stress tests on Memgraph.")
|
||||
parser.add_argument("--memgraph", default = os.path.join(BUILD_DIR,
|
||||
"memgraph"))
|
||||
parser.add_argument("--log-file", default = "")
|
||||
parser.add_argument("--data-directory", default = "")
|
||||
parser.add_argument("--python", default = os.path.join(SCRIPT_DIR,
|
||||
"ve3", "bin", "python3"), type = str)
|
||||
parser.add_argument("--large-dataset", action = "store_const",
|
||||
const = True, default = False)
|
||||
parser.add_argument("--use-ssl", action = "store_const",
|
||||
const = True, default = False)
|
||||
parser.add_argument("--verbose", action = "store_const",
|
||||
const = True, default = False)
|
||||
parser = argparse.ArgumentParser(description="Run stress tests on Memgraph.")
|
||||
parser.add_argument("--memgraph", default=os.path.join(BUILD_DIR, "memgraph"))
|
||||
parser.add_argument("--log-file", default="")
|
||||
parser.add_argument("--data-directory", default="")
|
||||
parser.add_argument("--python", default=os.path.join(SCRIPT_DIR, "ve3", "bin", "python3"), type=str)
|
||||
parser.add_argument("--large-dataset", action="store_const", const=True, default=False)
|
||||
parser.add_argument("--use-ssl", action="store_const", const=True, default=False)
|
||||
parser.add_argument("--verbose", action="store_const", const=True, default=False)
|
||||
args = parser.parse_args()
|
||||
|
||||
# generate temporary SSL certs
|
||||
if args.use_ssl:
|
||||
# https://unix.stackexchange.com/questions/104171/create-ssl-certificate-non-interactively
|
||||
subj = "/C=HR/ST=Zagreb/L=Zagreb/O=Memgraph/CN=db.memgraph.com"
|
||||
subprocess.run(["openssl", "req", "-new", "-newkey", "rsa:4096",
|
||||
"-days", "365", "-nodes", "-x509", "-subj", subj,
|
||||
"-keyout", KEY_FILE, "-out", CERT_FILE], check=True)
|
||||
subprocess.run(
|
||||
[
|
||||
"openssl",
|
||||
"req",
|
||||
"-new",
|
||||
"-newkey",
|
||||
"rsa:4096",
|
||||
"-days",
|
||||
"365",
|
||||
"-nodes",
|
||||
"-x509",
|
||||
"-subj",
|
||||
subj,
|
||||
"-keyout",
|
||||
KEY_FILE,
|
||||
"-out",
|
||||
CERT_FILE,
|
||||
],
|
||||
check=True,
|
||||
)
|
||||
|
||||
# start memgraph
|
||||
cwd = os.path.dirname(args.memgraph)
|
||||
cmd = [args.memgraph, "--bolt-num-workers=" + str(THREADS),
|
||||
"--storage-properties-on-edges=true",
|
||||
"--storage-snapshot-on-exit=true",
|
||||
"--storage-snapshot-interval-sec=600",
|
||||
"--storage-snapshot-retention-count=1",
|
||||
"--storage-wal-enabled=true",
|
||||
"--storage-recover-on-startup=false",
|
||||
"--query-execution-timeout-sec=1200"]
|
||||
cmd = [
|
||||
args.memgraph,
|
||||
"--bolt-num-workers=" + str(THREADS),
|
||||
"--storage-properties-on-edges=true",
|
||||
"--storage-snapshot-on-exit=true",
|
||||
"--storage-snapshot-interval-sec=600",
|
||||
"--storage-snapshot-retention-count=1",
|
||||
"--storage-wal-enabled=true",
|
||||
"--storage-recover-on-startup=false",
|
||||
"--query-execution-timeout-sec=1200",
|
||||
]
|
||||
if not args.verbose:
|
||||
cmd += ["--log-level", "WARNING"]
|
||||
if args.log_file:
|
||||
@@ -166,7 +189,7 @@ if args.data_directory:
|
||||
cmd += ["--data-directory", args.data_directory]
|
||||
if args.use_ssl:
|
||||
cmd += ["--bolt-cert-file", CERT_FILE, "--bolt-key-file", KEY_FILE]
|
||||
proc_mg = subprocess.Popen(cmd, cwd = cwd)
|
||||
proc_mg = subprocess.Popen(cmd, cwd=cwd)
|
||||
wait_for_server(7687)
|
||||
assert proc_mg.poll() is None, "The database binary died prematurely!"
|
||||
|
||||
@@ -174,10 +197,12 @@ assert proc_mg.poll() is None, "The database binary died prematurely!"
|
||||
@atexit.register
|
||||
def cleanup():
|
||||
global proc_mg
|
||||
if proc_mg.poll() != None: return
|
||||
if proc_mg.poll() != None:
|
||||
return
|
||||
proc_mg.kill()
|
||||
proc_mg.wait()
|
||||
|
||||
|
||||
# run tests
|
||||
runtimes = {}
|
||||
dataset = LARGE_DATASET if args.large_dataset else SMALL_DATASET
|
||||
|
||||
79
tests/stress/parser.cpp
Normal file
79
tests/stress/parser.cpp
Normal file
@@ -0,0 +1,79 @@
|
||||
// Copyright 2022 Memgraph Ltd.
|
||||
//
|
||||
// Use of this software is governed by the Business Source License
|
||||
// included in the file licenses/BSL.txt; by using this file, you agree to be bound by the terms of the Business Source
|
||||
// License, and you may not use this file except in compliance with the Business Source License.
|
||||
//
|
||||
// As of the Change Date specified in that file, in accordance with
|
||||
// the Business Source License, use of this software will be governed
|
||||
// by the Apache License, Version 2.0, included in the file
|
||||
// licenses/APL.txt.
|
||||
|
||||
#include <limits>
|
||||
#include <random>
|
||||
#include <thread>
|
||||
|
||||
#include <fmt/format.h>
|
||||
#include <gflags/gflags.h>
|
||||
|
||||
#include "communication/bolt/client.hpp"
|
||||
#include "io/network/endpoint.hpp"
|
||||
#include "mgclient.hpp"
|
||||
#include "utils/timer.hpp"
|
||||
|
||||
DEFINE_string(address, "127.0.0.1", "Server address");
|
||||
DEFINE_int32(port, 7687, "Server port");
|
||||
DEFINE_string(username, "", "Username for the database");
|
||||
DEFINE_string(password, "", "Password for the database");
|
||||
DEFINE_bool(use_ssl, false, "Set to true to connect with SSL to the server.");
|
||||
DEFINE_int32(worker_count, 1, "The number of concurrent workers executing queries against the server.");
|
||||
DEFINE_int32(per_worker_query_count, 100, "The number of queries each worker will try to execute.");
|
||||
|
||||
auto make_client() {
|
||||
mg::Client::Params params;
|
||||
params.host = FLAGS_address;
|
||||
params.port = static_cast<uint16_t>(FLAGS_port);
|
||||
params.use_ssl = FLAGS_use_ssl;
|
||||
return mg::Client::Connect(params);
|
||||
}
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
gflags::ParseCommandLineFlags(&argc, &argv, true);
|
||||
mg::Client::Init();
|
||||
|
||||
spdlog::info("Cleaning the database instance...");
|
||||
auto client = make_client();
|
||||
client->Execute("MATCH (n) DETACH DELETE n");
|
||||
client->DiscardAll();
|
||||
|
||||
spdlog::info(fmt::format("Starting parser stress test with {} workers and {} queries per worker...",
|
||||
FLAGS_worker_count, FLAGS_per_worker_query_count));
|
||||
std::vector<std::thread> threads;
|
||||
memgraph::utils::Timer timer;
|
||||
for (int i = 0; i < FLAGS_worker_count; ++i) {
|
||||
threads.push_back(std::thread([]() {
|
||||
auto client = make_client();
|
||||
std::mt19937 generator{std::random_device{}()};
|
||||
std::uniform_int_distribution<uint64_t> distribution{std::numeric_limits<uint64_t>::min(),
|
||||
std::numeric_limits<uint64_t>::max()};
|
||||
for (int i = 0; i < FLAGS_per_worker_query_count; ++i) {
|
||||
try {
|
||||
auto is_executed = client->Execute(fmt::format("MATCH (n:Label{}) RETURN n;", distribution(generator)));
|
||||
if (!is_executed) {
|
||||
LOG_FATAL("One of the parser stress test queries failed.");
|
||||
}
|
||||
client->FetchAll();
|
||||
} catch (const std::exception &e) {
|
||||
LOG_FATAL("One of the parser stress test queries failed.");
|
||||
}
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
||||
std::ranges::for_each(threads, [](auto &t) { t.join(); });
|
||||
spdlog::info(
|
||||
fmt::format("All queries executed in {:.4f}s. The parser managed to handle the load.", timer.Elapsed().count()));
|
||||
mg::Client::Finalize();
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -217,31 +217,40 @@ TEST_F(QueryPlanAggregateOps, WithData) {
|
||||
TEST_F(QueryPlanAggregateOps, WithoutDataWithGroupBy) {
|
||||
{
|
||||
auto results = AggregationResults(true, {Aggregation::Op::COUNT});
|
||||
EXPECT_EQ(results.size(), 0);
|
||||
EXPECT_EQ(results.size(), 1);
|
||||
EXPECT_EQ(results[0][0].type(), TypedValue::Type::Int);
|
||||
EXPECT_EQ(results[0][0].ValueInt(), 0);
|
||||
}
|
||||
{
|
||||
auto results = AggregationResults(true, {Aggregation::Op::SUM});
|
||||
EXPECT_EQ(results.size(), 0);
|
||||
EXPECT_EQ(results.size(), 1);
|
||||
EXPECT_EQ(results[0][0].type(), TypedValue::Type::Int);
|
||||
EXPECT_EQ(results[0][0].ValueInt(), 0);
|
||||
}
|
||||
{
|
||||
auto results = AggregationResults(true, {Aggregation::Op::AVG});
|
||||
EXPECT_EQ(results.size(), 0);
|
||||
EXPECT_EQ(results.size(), 1);
|
||||
EXPECT_EQ(results[0][0].type(), TypedValue::Type::Null);
|
||||
}
|
||||
{
|
||||
auto results = AggregationResults(true, {Aggregation::Op::MIN});
|
||||
EXPECT_EQ(results.size(), 0);
|
||||
EXPECT_EQ(results.size(), 1);
|
||||
EXPECT_EQ(results[0][0].type(), TypedValue::Type::Null);
|
||||
}
|
||||
{
|
||||
auto results = AggregationResults(true, {Aggregation::Op::MAX});
|
||||
EXPECT_EQ(results.size(), 0);
|
||||
EXPECT_EQ(results.size(), 1);
|
||||
EXPECT_EQ(results[0][0].type(), TypedValue::Type::Null);
|
||||
}
|
||||
{
|
||||
auto results = AggregationResults(true, {Aggregation::Op::COLLECT_LIST});
|
||||
EXPECT_EQ(results.size(), 0);
|
||||
EXPECT_EQ(results.size(), 1);
|
||||
EXPECT_EQ(results[0][0].type(), TypedValue::Type::List);
|
||||
}
|
||||
{
|
||||
auto results = AggregationResults(true, {Aggregation::Op::COLLECT_MAP});
|
||||
EXPECT_EQ(results.size(), 0);
|
||||
EXPECT_EQ(results.size(), 1);
|
||||
EXPECT_EQ(results[0][0].type(), TypedValue::Type::Map);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -260,7 +269,7 @@ TEST_F(QueryPlanAggregateOps, WithoutDataWithoutGroupBy) {
|
||||
// max
|
||||
EXPECT_TRUE(results[0][3].IsNull());
|
||||
// sum
|
||||
EXPECT_TRUE(results[0][4].IsNull());
|
||||
EXPECT_EQ(results[0][4].ValueInt(), 0);
|
||||
// avg
|
||||
EXPECT_TRUE(results[0][5].IsNull());
|
||||
// collect list
|
||||
|
||||
@@ -891,7 +891,6 @@ class TriggerStoreTest : public ::testing::Test {
|
||||
std::optional<memgraph::query::DbAccessor> dba;
|
||||
|
||||
memgraph::utils::SkipList<memgraph::query::QueryCacheEntry> ast_cache;
|
||||
memgraph::utils::SpinLock antlr_lock;
|
||||
memgraph::query::AllowEverythingAuthChecker auth_checker;
|
||||
|
||||
private:
|
||||
@@ -909,7 +908,7 @@ TEST_F(TriggerStoreTest, Restore) {
|
||||
|
||||
const auto reset_store = [&] {
|
||||
store.emplace(testing_directory);
|
||||
store->RestoreTriggers(&ast_cache, &*dba, &antlr_lock, memgraph::query::InterpreterConfig::Query{}, &auth_checker);
|
||||
store->RestoreTriggers(&ast_cache, &*dba, memgraph::query::InterpreterConfig::Query{}, &auth_checker);
|
||||
};
|
||||
|
||||
reset_store();
|
||||
@@ -930,12 +929,12 @@ TEST_F(TriggerStoreTest, Restore) {
|
||||
store->AddTrigger(
|
||||
trigger_name_before, trigger_statement,
|
||||
std::map<std::string, memgraph::storage::PropertyValue>{{"parameter", memgraph::storage::PropertyValue{1}}},
|
||||
event_type, memgraph::query::TriggerPhase::BEFORE_COMMIT, &ast_cache, &*dba, &antlr_lock,
|
||||
event_type, memgraph::query::TriggerPhase::BEFORE_COMMIT, &ast_cache, &*dba,
|
||||
memgraph::query::InterpreterConfig::Query{}, std::nullopt, &auth_checker);
|
||||
store->AddTrigger(
|
||||
trigger_name_after, trigger_statement,
|
||||
std::map<std::string, memgraph::storage::PropertyValue>{{"parameter", memgraph::storage::PropertyValue{"value"}}},
|
||||
event_type, memgraph::query::TriggerPhase::AFTER_COMMIT, &ast_cache, &*dba, &antlr_lock,
|
||||
event_type, memgraph::query::TriggerPhase::AFTER_COMMIT, &ast_cache, &*dba,
|
||||
memgraph::query::InterpreterConfig::Query{}, {owner}, &auth_checker);
|
||||
|
||||
const auto check_triggers = [&] {
|
||||
@@ -986,16 +985,16 @@ TEST_F(TriggerStoreTest, AddTrigger) {
|
||||
|
||||
// Invalid query in statements
|
||||
ASSERT_THROW(store.AddTrigger("trigger", "RETUR 1", {}, memgraph::query::TriggerEventType::VERTEX_CREATE,
|
||||
memgraph::query::TriggerPhase::BEFORE_COMMIT, &ast_cache, &*dba, &antlr_lock,
|
||||
memgraph::query::TriggerPhase::BEFORE_COMMIT, &ast_cache, &*dba,
|
||||
memgraph::query::InterpreterConfig::Query{}, std::nullopt, &auth_checker),
|
||||
memgraph::utils::BasicException);
|
||||
ASSERT_THROW(store.AddTrigger("trigger", "RETURN createdEdges", {}, memgraph::query::TriggerEventType::VERTEX_CREATE,
|
||||
memgraph::query::TriggerPhase::BEFORE_COMMIT, &ast_cache, &*dba, &antlr_lock,
|
||||
memgraph::query::TriggerPhase::BEFORE_COMMIT, &ast_cache, &*dba,
|
||||
memgraph::query::InterpreterConfig::Query{}, std::nullopt, &auth_checker),
|
||||
memgraph::utils::BasicException);
|
||||
|
||||
ASSERT_THROW(store.AddTrigger("trigger", "RETURN $parameter", {}, memgraph::query::TriggerEventType::VERTEX_CREATE,
|
||||
memgraph::query::TriggerPhase::BEFORE_COMMIT, &ast_cache, &*dba, &antlr_lock,
|
||||
memgraph::query::TriggerPhase::BEFORE_COMMIT, &ast_cache, &*dba,
|
||||
memgraph::query::InterpreterConfig::Query{}, std::nullopt, &auth_checker),
|
||||
memgraph::utils::BasicException);
|
||||
|
||||
@@ -1003,15 +1002,15 @@ TEST_F(TriggerStoreTest, AddTrigger) {
|
||||
"trigger", "RETURN $parameter",
|
||||
std::map<std::string, memgraph::storage::PropertyValue>{{"parameter", memgraph::storage::PropertyValue{1}}},
|
||||
memgraph::query::TriggerEventType::VERTEX_CREATE, memgraph::query::TriggerPhase::BEFORE_COMMIT, &ast_cache, &*dba,
|
||||
&antlr_lock, memgraph::query::InterpreterConfig::Query{}, std::nullopt, &auth_checker));
|
||||
memgraph::query::InterpreterConfig::Query{}, std::nullopt, &auth_checker));
|
||||
|
||||
// Inserting with the same name
|
||||
ASSERT_THROW(store.AddTrigger("trigger", "RETURN 1", {}, memgraph::query::TriggerEventType::VERTEX_CREATE,
|
||||
memgraph::query::TriggerPhase::BEFORE_COMMIT, &ast_cache, &*dba, &antlr_lock,
|
||||
memgraph::query::TriggerPhase::BEFORE_COMMIT, &ast_cache, &*dba,
|
||||
memgraph::query::InterpreterConfig::Query{}, std::nullopt, &auth_checker),
|
||||
memgraph::utils::BasicException);
|
||||
ASSERT_THROW(store.AddTrigger("trigger", "RETURN 1", {}, memgraph::query::TriggerEventType::VERTEX_CREATE,
|
||||
memgraph::query::TriggerPhase::AFTER_COMMIT, &ast_cache, &*dba, &antlr_lock,
|
||||
memgraph::query::TriggerPhase::AFTER_COMMIT, &ast_cache, &*dba,
|
||||
memgraph::query::InterpreterConfig::Query{}, std::nullopt, &auth_checker),
|
||||
memgraph::utils::BasicException);
|
||||
|
||||
@@ -1027,7 +1026,7 @@ TEST_F(TriggerStoreTest, DropTrigger) {
|
||||
|
||||
const auto *trigger_name = "trigger";
|
||||
store.AddTrigger(trigger_name, "RETURN 1", {}, memgraph::query::TriggerEventType::VERTEX_CREATE,
|
||||
memgraph::query::TriggerPhase::BEFORE_COMMIT, &ast_cache, &*dba, &antlr_lock,
|
||||
memgraph::query::TriggerPhase::BEFORE_COMMIT, &ast_cache, &*dba,
|
||||
memgraph::query::InterpreterConfig::Query{}, std::nullopt, &auth_checker);
|
||||
|
||||
ASSERT_THROW(store.DropTrigger("Unknown"), memgraph::utils::BasicException);
|
||||
@@ -1040,7 +1039,7 @@ TEST_F(TriggerStoreTest, TriggerInfo) {
|
||||
|
||||
std::vector<memgraph::query::TriggerStore::TriggerInfo> expected_info;
|
||||
store.AddTrigger("trigger", "RETURN 1", {}, memgraph::query::TriggerEventType::VERTEX_CREATE,
|
||||
memgraph::query::TriggerPhase::BEFORE_COMMIT, &ast_cache, &*dba, &antlr_lock,
|
||||
memgraph::query::TriggerPhase::BEFORE_COMMIT, &ast_cache, &*dba,
|
||||
memgraph::query::InterpreterConfig::Query{}, std::nullopt, &auth_checker);
|
||||
expected_info.push_back({"trigger", "RETURN 1", memgraph::query::TriggerEventType::VERTEX_CREATE,
|
||||
memgraph::query::TriggerPhase::BEFORE_COMMIT});
|
||||
@@ -1060,7 +1059,7 @@ TEST_F(TriggerStoreTest, TriggerInfo) {
|
||||
check_trigger_info();
|
||||
|
||||
store.AddTrigger("edge_update_trigger", "RETURN 1", {}, memgraph::query::TriggerEventType::EDGE_UPDATE,
|
||||
memgraph::query::TriggerPhase::AFTER_COMMIT, &ast_cache, &*dba, &antlr_lock,
|
||||
memgraph::query::TriggerPhase::AFTER_COMMIT, &ast_cache, &*dba,
|
||||
memgraph::query::InterpreterConfig::Query{}, std::nullopt, &auth_checker);
|
||||
expected_info.push_back({"edge_update_trigger", "RETURN 1", memgraph::query::TriggerEventType::EDGE_UPDATE,
|
||||
memgraph::query::TriggerPhase::AFTER_COMMIT});
|
||||
@@ -1174,7 +1173,7 @@ TEST_F(TriggerStoreTest, AnyTriggerAllKeywords) {
|
||||
for (const auto keyword : keywords) {
|
||||
SCOPED_TRACE(keyword);
|
||||
EXPECT_NO_THROW(store.AddTrigger(trigger_name, fmt::format("RETURN {}", keyword), {}, event_type,
|
||||
memgraph::query::TriggerPhase::BEFORE_COMMIT, &ast_cache, &*dba, &antlr_lock,
|
||||
memgraph::query::TriggerPhase::BEFORE_COMMIT, &ast_cache, &*dba,
|
||||
memgraph::query::InterpreterConfig::Query{}, std::nullopt, &auth_checker));
|
||||
store.DropTrigger(trigger_name);
|
||||
}
|
||||
@@ -1199,23 +1198,23 @@ TEST_F(TriggerStoreTest, AuthCheckerUsage) {
|
||||
|
||||
ASSERT_NO_THROW(store->AddTrigger("successfull_trigger_1", "CREATE (n:VERTEX) RETURN n", {},
|
||||
memgraph::query::TriggerEventType::EDGE_UPDATE,
|
||||
memgraph::query::TriggerPhase::AFTER_COMMIT, &ast_cache, &*dba, &antlr_lock,
|
||||
memgraph::query::TriggerPhase::AFTER_COMMIT, &ast_cache, &*dba,
|
||||
memgraph::query::InterpreterConfig::Query{}, std::nullopt, &mock_checker));
|
||||
|
||||
ASSERT_NO_THROW(store->AddTrigger("successfull_trigger_2", "CREATE (n:VERTEX) RETURN n", {},
|
||||
memgraph::query::TriggerEventType::EDGE_UPDATE,
|
||||
memgraph::query::TriggerPhase::AFTER_COMMIT, &ast_cache, &*dba, &antlr_lock,
|
||||
memgraph::query::TriggerPhase::AFTER_COMMIT, &ast_cache, &*dba,
|
||||
memgraph::query::InterpreterConfig::Query{}, owner, &mock_checker));
|
||||
|
||||
EXPECT_CALL(mock_checker, IsUserAuthorized(std::optional<std::string>{}, ElementsAre(Privilege::MATCH)))
|
||||
.Times(1)
|
||||
.WillOnce(Return(false));
|
||||
|
||||
ASSERT_THROW(store->AddTrigger("unprivileged_trigger", "MATCH (n:VERTEX) RETURN n", {},
|
||||
memgraph::query::TriggerEventType::EDGE_UPDATE,
|
||||
memgraph::query::TriggerPhase::AFTER_COMMIT, &ast_cache, &*dba, &antlr_lock,
|
||||
memgraph::query::InterpreterConfig::Query{}, std::nullopt, &mock_checker);
|
||||
, memgraph::utils::BasicException);
|
||||
ASSERT_THROW(
|
||||
store->AddTrigger("unprivileged_trigger", "MATCH (n:VERTEX) RETURN n", {},
|
||||
memgraph::query::TriggerEventType::EDGE_UPDATE, memgraph::query::TriggerPhase::AFTER_COMMIT,
|
||||
&ast_cache, &*dba, memgraph::query::InterpreterConfig::Query{}, std::nullopt, &mock_checker);
|
||||
, memgraph::utils::BasicException);
|
||||
|
||||
store.emplace(testing_directory);
|
||||
EXPECT_CALL(mock_checker, IsUserAuthorized(std::optional<std::string>{}, ElementsAre(Privilege::CREATE)))
|
||||
@@ -1223,8 +1222,8 @@ TEST_F(TriggerStoreTest, AuthCheckerUsage) {
|
||||
.WillOnce(Return(false));
|
||||
EXPECT_CALL(mock_checker, IsUserAuthorized(owner, ElementsAre(Privilege::CREATE))).Times(1).WillOnce(Return(true));
|
||||
|
||||
ASSERT_NO_THROW(store->RestoreTriggers(&ast_cache, &*dba, &antlr_lock, memgraph::query::InterpreterConfig::Query{},
|
||||
&mock_checker));
|
||||
ASSERT_NO_THROW(
|
||||
store->RestoreTriggers(&ast_cache, &*dba, memgraph::query::InterpreterConfig::Query{}, &mock_checker));
|
||||
|
||||
const auto triggers = store->GetTriggerInfo();
|
||||
ASSERT_EQ(triggers.size(), 1);
|
||||
|
||||
Reference in New Issue
Block a user