Skip to content

Commit

Permalink
feat: add eval regex and test (#167)
Browse files Browse the repository at this point in the history
Signed-off-by: stonex <1479765922@qq.com>
  • Loading branch information
sheny1xuan authored Nov 19, 2021
1 parent 7a28a0f commit 64fc8dd
Show file tree
Hide file tree
Showing 5 changed files with 112 additions and 3 deletions.
1 change: 1 addition & 0 deletions casbin/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ set(CASBIN_SOURCE_FILES
util/split.cpp
util/ticker.cpp
util/trim.cpp
util/eval.cpp
)

# Setting to C++ standard to C++17
Expand Down
65 changes: 65 additions & 0 deletions casbin/util/eval.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
/*
* Copyright 2020 The casbin Authors. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

#include "pch.h"

#ifndef EVAL_CPP
#define EVAL_CPP

#include <regex>

#include "./util.h"

namespace casbin {

std::regex evalReg("\\beval\\(([^)]*)\\)",
std::regex_constants::icase);

// HasEval determine whether matcher contains function eval
bool HasEval(const std::string& s) {
return std::regex_search(s, evalReg);
}

// ReplaceEvalWithMap replace function eval with the value of its parameters via given sets.
std::string ReplaceEvalWithMap(const std::string& src, std::unordered_map<std::string, std::string>& sets) {
std::string replacedExp = "";
std::string srcCpy = src;
std::smatch m;

while (std::regex_search(srcCpy, m, evalReg)) {
if (m.empty()) {
return src;
}
std::string key = m[1];
bool found = sets.find(key) != sets.end();

replacedExp += m.prefix();
if (!found) {
replacedExp += m[0];
} else {
replacedExp += sets[key];
}
srcCpy = m.suffix();
}

replacedExp += srcCpy;

return replacedExp;
}

} // namespace casbin

#endif // EVAL_CPP
6 changes: 6 additions & 0 deletions casbin/util/util.h
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,12 @@ std::string& RTrim(std::string& str, const std::string& chars = "\t\n\v\f\r ");

std::string Trim(std::string& str, const std::string& chars = "\t\n\v\f\r ");

// HasEval determine whether matcher contains function eval
bool HasEval(const std::string& s);

// ReplaceEvalWithMap replace function eval with the value of its parameters via given sets.
std::string ReplaceEvalWithMap(const std::string& src, std::unordered_map<std::string, std::string>& sets);

} // namespace casbin

#endif
6 changes: 6 additions & 0 deletions include/casbin/casbin_helpers.h
Original file line number Diff line number Diff line change
Expand Up @@ -635,6 +635,12 @@ namespace casbin {

std::string Trim(std::string& str, const std::string& chars = "\t\n\v\f\r ");

// HasEval determine whether matcher contains function eval
bool HasEval(const std::string& s);

// ReplaceEvalWithMap replace function eval with the value of its parameters via given sets.
std::string ReplaceEvalWithMap(const std::string& src, std::unordered_map<std::string, std::string>& sets);

// Exception class for Casbin Adapter Exception.
class CasbinAdapterException : std::logic_error {
public:
Expand Down
37 changes: 34 additions & 3 deletions tests/util_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ void TestEscapeAssertionFn(const std::string& s, const std::string& res){
ASSERT_EQ(my_res, res);
}

TEST(TestModel, TestEscapeAssertion) {
TEST(TestUtil, TestEscapeAssertion) {
TestEscapeAssertionFn("r.attr.value == p.attr", "r_attr.value == p_attr");
TestEscapeAssertionFn("r.attp.value || p.attr", "r_attp.value || p_attr");
TestEscapeAssertionFn("r.attp.value &&p.attr", "r_attp.value &&p_attr");
Expand All @@ -47,7 +47,7 @@ void TestRemoveCommentsFn(const std::string& s, const std::string& res) {
ASSERT_EQ(my_res, res);
}

TEST(TestModel, TestRemoveComments) {
TEST(TestUtil, TestRemoveComments) {
TestRemoveCommentsFn("r.act == p.act # comments", "r.act == p.act");
TestRemoveCommentsFn("r.act == p.act#comments", "r.act == p.act");
TestRemoveCommentsFn("r.act == p.act###", "r.act == p.act");
Expand All @@ -60,11 +60,42 @@ void TestArrayEqualsFn(const std::vector<std::string>& a, const std::vector<std:
ASSERT_EQ(my_res, res);
}

TEST(TestModel, TestArrayEquals) {
TEST(TestUtil, TestArrayEquals) {
TestArrayEqualsFn({"a", "b", "c"}, {"a", "b", "c"}, true);
TestArrayEqualsFn({"a", "b", "c"}, {"a", "b"}, false);
TestArrayEqualsFn({"a", "b", "c"}, {"a", "c", "b"}, true);
TestArrayEqualsFn({"a", "b", "c"}, {}, false);
}

void testContainEval(std::string s, bool res) {
ASSERT_EQ(casbin::HasEval(s), res);
}

TEST(TestUtil, TestContainEval) {
testContainEval("eval() && a && b && c", true);
testContainEval("eval) && a && b && c", false);
testContainEval("eval)( && a && b && c", false);
testContainEval("eval(c * (a + b)) && a && b && c", true);
testContainEval("xeval() && a && b && c", false);
}

void testReplaceEvalWithMap(std::string s, std::unordered_map<std::string, std::string> sets, std::string res) {
ASSERT_EQ(casbin::ReplaceEvalWithMap(s, sets), res);
}

TEST(TestUtil, TestReplaceEvalWithMap) {
testReplaceEvalWithMap("eval(rule1)", {{"rule1", "a == b"}}, "a == b");
testReplaceEvalWithMap("eval(rule1) && c && d", {{"rule1", "a == b"}}, "a == b && c && d");
testReplaceEvalWithMap("eval(rule1)", {{}}, "eval(rule1)");
testReplaceEvalWithMap("eval(rule1) && c && d", {{}}, "eval(rule1) && c && d");
testReplaceEvalWithMap("eval(rule1) || eval(rule2)", {{"rule1", "a == b"}, {"rule2", "a == c"}}, "a == b || a == c");
testReplaceEvalWithMap("eval(rule1) || eval(rule2) && c && d", {{"rule1", "a == b"}, {"rule2", "a == c"}}, "a == b || a == c && c && d");
testReplaceEvalWithMap("eval(rule1) || eval(rule2)", {{"rule1", "a == b"}}, "a == b || eval(rule2)");
testReplaceEvalWithMap("eval(rule1) || eval(rule2) && c && d", {{"rule1", "a == b"}}, "a == b || eval(rule2) && c && d");
testReplaceEvalWithMap("eval(rule1) || eval(rule2)", {{"rule2", "a == b"}}, "eval(rule1) || a == b");
testReplaceEvalWithMap("eval(rule1) || eval(rule2) && c && d", {{"rule2", "a == b"}}, "eval(rule1) || a == b && c && d");
testReplaceEvalWithMap("eval(rule1) || eval(rule2)", {}, "eval(rule1) || eval(rule2)");
testReplaceEvalWithMap("eval(rule1) || eval(rule2) && c && d", {}, "eval(rule1) || eval(rule2) && c && d");
}

} // namespace

0 comments on commit 64fc8dd

Please sign in to comment.