chore(fakeredis): Enable JSON tests in the Fakeredis tests (#3773)

* chore(fakeredis): Enable JSON tests in the Fakeredis tests

fixes dragonflydb#3671

Signed-off-by: Stsiapan Bahrytsevich <stefan@dragonflydb.io>

* refactor: address comments

Signed-off-by: Stsiapan Bahrytsevich <stefan@dragonflydb.io>

* tmp commit

Signed-off-by: Stsiapan Bahrytsevich <stefan@dragonflydb.io>

* refactor: address comments 2

Signed-off-by: Stsiapan Bahrytsevich <stefan@dragonflydb.io>

---------

Signed-off-by: Stsiapan Bahrytsevich <stefan@dragonflydb.io>
This commit is contained in:
Stepan Bagritsevich 2024-10-23 08:53:14 +02:00 committed by GitHub
parent 37fec87070
commit ea9dc9c454
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
5 changed files with 63 additions and 44 deletions

View file

@ -68,7 +68,6 @@ jobs:
run: |
poetry run pytest test/ \
--ignore test/test_hypothesis.py \
--ignore test/test_json/ \
--ignore test/test_mixins/test_bitmap_commands.py \
--junit-xml=results-tests.xml --html=report-tests.html -v
continue-on-error: true # For now to mark the flow as successful

View file

@ -61,15 +61,22 @@ enum class JsonPathType { kV2, kLegacy /*Or V1*/ };
constexpr JsonPathType kDefaultJsonPathType = JsonPathType::kV2;
struct CallbackResultOptions {
public:
enum class SavingOrder { kSaveFirst, kSaveLast };
enum class OnEmpty { kSendNil, kSendWrongType };
CallbackResultOptions() = default;
explicit CallbackResultOptions(JsonPathType path_type_) : path_type(path_type_) {
// Default options for WrappedJsonPath::Evaluate
static CallbackResultOptions DefaultEvaluateOptions() {
return CallbackResultOptions{OnEmpty::kSendNil};
}
explicit CallbackResultOptions(SavingOrder saving_order_) : saving_order(saving_order_) {
static CallbackResultOptions DefaultEvaluateOptions(SavingOrder saving_order) {
return {saving_order, OnEmpty::kSendNil};
}
// Default options for WrappedJsonPath::Mutate
static CallbackResultOptions DefaultMutateOptions() {
return CallbackResultOptions{OnEmpty::kSendWrongType};
}
explicit CallbackResultOptions(OnEmpty on_empty_) : on_empty(on_empty_) {
@ -79,9 +86,14 @@ struct CallbackResultOptions {
: path_type(path_type_), saving_order(saving_order_), on_empty(on_empty_) {
}
std::optional<JsonPathType> path_type = std::nullopt;
std::optional<JsonPathType> path_type;
SavingOrder saving_order{SavingOrder::kSaveLast};
OnEmpty on_empty{OnEmpty::kSendWrongType};
OnEmpty on_empty;
private:
CallbackResultOptions(SavingOrder saving_order_, OnEmpty on_empty_)
: saving_order(saving_order_), on_empty(on_empty_) {
}
};
template <typename T> class JsonCallbackResult {
@ -93,10 +105,11 @@ template <typename T> class JsonCallbackResult {
using SavingOrder = CallbackResultOptions::SavingOrder;
using OnEmpty = CallbackResultOptions::OnEmpty;
JsonCallbackResult() {
JsonCallbackResult()
: options_(kDefaultJsonPathType, SavingOrder::kSaveLast, OnEmpty::kSendWrongType) {
}
explicit JsonCallbackResult(CallbackResultOptions options) : options_(std::move(options)) {
explicit JsonCallbackResult(CallbackResultOptions options) : options_(options) {
}
void AddValue(T value) {
@ -143,7 +156,7 @@ template <typename T> class JsonCallbackResult {
private:
std::vector<T> result_;
CallbackResultOptions options_{kDefaultJsonPathType};
CallbackResultOptions options_;
};
class WrappedJsonPath {
@ -161,9 +174,8 @@ class WrappedJsonPath {
template <typename T>
JsonCallbackResult<T> Evaluate(const JsonType* json_entry, JsonPathEvaluateCallback<T> cb,
CallbackResultOptions options = {}) const {
JsonCallbackResult<T> eval_result{{options.path_type.value_or(path_type_), options.saving_order,
CallbackResultOptions::OnEmpty::kSendNil}};
CallbackResultOptions options) const {
JsonCallbackResult<T> eval_result{InitializePathType(options)};
auto eval_callback = [&cb, &eval_result](std::string_view path, const JsonType& val) {
eval_result.AddValue(cb(path, val));
@ -187,7 +199,7 @@ class WrappedJsonPath {
template <typename T>
OpResult<JsonCallbackResult<std::optional<T>>> Mutate(JsonType* json_entry,
JsonPathMutateCallback<T> cb,
CallbackResultOptions options = {}) const {
CallbackResultOptions options) const {
JsonCallbackResult<std::optional<T>> mutate_result{InitializePathType(options)};
auto mutate_callback = [&cb, &mutate_result](std::optional<std::string_view> path,

View file

@ -583,7 +583,7 @@ size_t CountJsonFields(const JsonType& j) {
struct EvaluateOperationOptions {
bool return_nil_if_key_not_found = false;
CallbackResultOptions cb_result_options;
CallbackResultOptions cb_result_options = CallbackResultOptions::DefaultEvaluateOptions();
};
template <typename T>
@ -604,7 +604,7 @@ OpResult<JsonCallbackResult<T>> JsonEvaluateOperation(const OpArgs& op_args, std
struct MutateOperationOptions {
JsonReplaceVerify verify_op;
CallbackResultOptions cb_result_options;
CallbackResultOptions cb_result_options = CallbackResultOptions::DefaultMutateOptions();
};
template <typename T>
@ -684,8 +684,8 @@ OpResult<std::string> OpJsonGet(const OpArgs& op_args, string_view key,
auto cb = [](std::string_view, const JsonType& val) { return val; };
const bool legacy_mode_is_enabled = LegacyModeIsEnabled(paths);
CallbackResultOptions cb_options{legacy_mode_is_enabled ? JsonPathType::kLegacy
: JsonPathType::kV2};
CallbackResultOptions cb_options = CallbackResultOptions::DefaultEvaluateOptions();
cb_options.path_type = legacy_mode_is_enabled ? JsonPathType::kLegacy : JsonPathType::kV2;
auto eval_wrapped = [&](const WrappedJsonPath& json_path) -> std::optional<JsonType> {
auto eval_result = json_path.Evaluate<JsonType>(&json_entry, cb, cb_options);
@ -729,7 +729,7 @@ auto OpType(const OpArgs& op_args, string_view key, const WrappedJsonPath& json_
auto cb = [](const string_view&, const JsonType& val) -> std::string {
return JsonTypeToName(val);
};
return JsonEvaluateOperation<std::string>(op_args, key, json_path, std::move(cb), {true, {}});
return JsonEvaluateOperation<std::string>(op_args, key, json_path, std::move(cb), {true});
}
OpResult<JsonCallbackResult<OptSize>> OpStrLen(const OpArgs& op_args, string_view key,
@ -741,9 +741,9 @@ OpResult<JsonCallbackResult<OptSize>> OpStrLen(const OpArgs& op_args, string_vie
return nullopt;
}
};
return JsonEvaluateOperation<OptSize>(op_args, key, json_path, std::move(cb),
{true, CallbackResultOptions{SavingOrder::kSaveFirst}});
return JsonEvaluateOperation<OptSize>(
op_args, key, json_path, std::move(cb),
{true, CallbackResultOptions::DefaultEvaluateOptions(SavingOrder::kSaveFirst)});
}
OpResult<JsonCallbackResult<OptSize>> OpObjLen(const OpArgs& op_args, string_view key,
@ -757,7 +757,8 @@ OpResult<JsonCallbackResult<OptSize>> OpObjLen(const OpArgs& op_args, string_vie
};
return JsonEvaluateOperation<OptSize>(
op_args, key, json_path, std::move(cb),
{json_path.IsLegacyModePath(), CallbackResultOptions{SavingOrder::kSaveFirst}});
{json_path.IsLegacyModePath(),
CallbackResultOptions::DefaultEvaluateOptions(SavingOrder::kSaveFirst)});
}
OpResult<JsonCallbackResult<OptSize>> OpArrLen(const OpArgs& op_args, string_view key,
@ -769,8 +770,9 @@ OpResult<JsonCallbackResult<OptSize>> OpArrLen(const OpArgs& op_args, string_vie
return std::nullopt;
}
};
return JsonEvaluateOperation<OptSize>(op_args, key, json_path, std::move(cb),
{true, CallbackResultOptions{SavingOrder::kSaveFirst}});
return JsonEvaluateOperation<OptSize>(
op_args, key, json_path, std::move(cb),
{true, CallbackResultOptions::DefaultEvaluateOptions(SavingOrder::kSaveFirst)});
}
template <typename T>
@ -930,7 +932,8 @@ OpResult<long> OpDel(const OpArgs& op_args, string_view key, string_view path,
return {};
};
auto res = json_path.Mutate<Nothing>(json_val, std::move(cb));
auto res = json_path.Mutate<Nothing>(json_val, std::move(cb),
CallbackResultOptions::DefaultMutateOptions());
RETURN_ON_BAD_STATUS(res);
if (deletion_items.empty()) {
@ -973,10 +976,10 @@ auto OpObjKeys(const OpArgs& op_args, string_view key, const WrappedJsonPath& js
}
return vec;
};
return JsonEvaluateOperation<StringVec>(
op_args, key, json_path, std::move(cb),
{json_path.IsLegacyModePath(), CallbackResultOptions{SavingOrder::kSaveFirst}});
{json_path.IsLegacyModePath(),
CallbackResultOptions::DefaultEvaluateOptions(SavingOrder::kSaveFirst)});
}
OpResult<JsonCallbackResult<OptSize>> OpStrAppend(const OpArgs& op_args, string_view key,
@ -990,7 +993,6 @@ OpResult<JsonCallbackResult<OptSize>> OpStrAppend(const OpArgs& op_args, string_
*val = std::move(new_val);
return {false, len}; // do not delete, new value len
};
return JsonMutateOperation<size_t>(op_args, key, path, std::move(cb));
}
@ -1045,9 +1047,8 @@ auto OpArrPop(const OpArgs& op_args, string_view key, WrappedJsonPath& path, int
val->erase(it);
return {false, std::move(str)};
};
return JsonMutateOperation<std::string>(
op_args, key, path, std::move(cb),
MutateOperationOptions{{}, CallbackResultOptions{OnEmpty::kSendNil}});
return JsonMutateOperation<std::string>(op_args, key, path, std::move(cb),
{{}, CallbackResultOptions{OnEmpty::kSendNil}});
}
// Returns numeric vector that represents the new length of the array at each path.
@ -1201,7 +1202,9 @@ auto OpArrIndex(const OpArgs& op_args, string_view key, const WrappedJsonPath& j
return pos;
};
return JsonEvaluateOperation<std::optional<long>>(op_args, key, json_path, std::move(cb));
return JsonEvaluateOperation<std::optional<long>>(
op_args, key, json_path, std::move(cb),
{false, CallbackResultOptions{CallbackResultOptions::OnEmpty::kSendWrongType}});
}
// Returns string vector that represents the query result of each supplied key.
@ -1226,7 +1229,8 @@ std::vector<std::optional<std::string>> OpJsonMGet(const WrappedJsonPath& json_p
auto eval_wrapped = [&json_val,
&cb](const WrappedJsonPath& json_path) -> std::optional<JsonType> {
auto eval_result = json_path.Evaluate<JsonType>(json_val, std::move(cb));
auto eval_result = json_path.Evaluate<JsonType>(
json_val, std::move(cb), CallbackResultOptions::DefaultEvaluateOptions());
if (eval_result.IsV1()) {
return eval_result.AsV1();
@ -1259,7 +1263,6 @@ auto OpFields(const OpArgs& op_args, string_view key, const WrappedJsonPath& jso
auto cb = [](const string_view&, const JsonType& val) -> std::optional<std::size_t> {
return CountJsonFields(val);
};
return JsonEvaluateOperation<std::optional<std::size_t>>(op_args, key, json_path, std::move(cb));
}
@ -1359,7 +1362,7 @@ OpResult<bool> OpSet(const OpArgs& op_args, string_view key, string_view path,
// existing json keys use copy assign, so we don't really need to account for the memory
// allocated by ShardJsonFromString above since it's not being moved here at all.
auto res = JsonMutateOperation<Nothing>(op_args, key, json_path, std::move(cb),
MutateOperationOptions{std::move(inserter), {}});
MutateOperationOptions{std::move(inserter)});
RETURN_ON_BAD_STATUS(res);
return operation_result;

View file

@ -2342,6 +2342,9 @@ TEST_F(JsonFamilyTest, ArrIndexLegacy) {
resp = Run({"JSON.ARRINDEX", "json", ".children", R"("DoesNotExist")"});
EXPECT_THAT(resp, IntArg(-1));
resp = Run({"JSON.ARRINDEX", "json", ".children.[0].notexist", "3"});
EXPECT_THAT(resp.type, RespExpr::ERROR);
json = R"(
{"a":"b"}
)";

View file

@ -210,14 +210,16 @@ def test_arrindex(r: redis.Redis):
},
)
assert r.json().get("store", "$.store.book[?(@.price<10)].size") == [
[10, 20, 30, 40],
[5, 10, 20, 30],
]
assert r.json().arrindex("store", "$.store.book[?(@.price<10)].size", "20") == [
-1,
-1,
]
# Temporary disable filter expressions tests
#
# assert r.json().get("store", "$.store.book[?(@.price<10)].size") == [
# [10, 20, 30, 40],
# [5, 10, 20, 30],
# ]
# assert r.json().arrindex("store", "$.store.book[?(@.price<10)].size", "20") == [
# -1,
# -1,
# ]
# Test index of int scalar in multi values
r.json().set(