mirror of
https://github.com/dragonflydb/dragonfly.git
synced 2025-05-10 18:05:44 +02:00
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:
parent
37fec87070
commit
ea9dc9c454
5 changed files with 63 additions and 44 deletions
1
.github/workflows/test-fakeredis.yml
vendored
1
.github/workflows/test-fakeredis.yml
vendored
|
@ -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
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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"}
|
||||
)";
|
||||
|
|
|
@ -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(
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue