Skip to content

Commit 64fc8dd

Browse files
authored
feat: add eval regex and test (#167)
Signed-off-by: stonex <[email protected]>
1 parent 7a28a0f commit 64fc8dd

File tree

5 files changed

+112
-3
lines changed

5 files changed

+112
-3
lines changed

casbin/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,7 @@ set(CASBIN_SOURCE_FILES
6666
util/split.cpp
6767
util/ticker.cpp
6868
util/trim.cpp
69+
util/eval.cpp
6970
)
7071

7172
# Setting to C++ standard to C++17

casbin/util/eval.cpp

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
/*
2+
* Copyright 2020 The casbin Authors. All Rights Reserved.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
#include "pch.h"
18+
19+
#ifndef EVAL_CPP
20+
#define EVAL_CPP
21+
22+
#include <regex>
23+
24+
#include "./util.h"
25+
26+
namespace casbin {
27+
28+
std::regex evalReg("\\beval\\(([^)]*)\\)",
29+
std::regex_constants::icase);
30+
31+
// HasEval determine whether matcher contains function eval
32+
bool HasEval(const std::string& s) {
33+
return std::regex_search(s, evalReg);
34+
}
35+
36+
// ReplaceEvalWithMap replace function eval with the value of its parameters via given sets.
37+
std::string ReplaceEvalWithMap(const std::string& src, std::unordered_map<std::string, std::string>& sets) {
38+
std::string replacedExp = "";
39+
std::string srcCpy = src;
40+
std::smatch m;
41+
42+
while (std::regex_search(srcCpy, m, evalReg)) {
43+
if (m.empty()) {
44+
return src;
45+
}
46+
std::string key = m[1];
47+
bool found = sets.find(key) != sets.end();
48+
49+
replacedExp += m.prefix();
50+
if (!found) {
51+
replacedExp += m[0];
52+
} else {
53+
replacedExp += sets[key];
54+
}
55+
srcCpy = m.suffix();
56+
}
57+
58+
replacedExp += srcCpy;
59+
60+
return replacedExp;
61+
}
62+
63+
} // namespace casbin
64+
65+
#endif // EVAL_CPP

casbin/util/util.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,12 @@ std::string& RTrim(std::string& str, const std::string& chars = "\t\n\v\f\r ");
6565

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

68+
// HasEval determine whether matcher contains function eval
69+
bool HasEval(const std::string& s);
70+
71+
// ReplaceEvalWithMap replace function eval with the value of its parameters via given sets.
72+
std::string ReplaceEvalWithMap(const std::string& src, std::unordered_map<std::string, std::string>& sets);
73+
6874
} // namespace casbin
6975

7076
#endif

include/casbin/casbin_helpers.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -635,6 +635,12 @@ namespace casbin {
635635

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

638+
// HasEval determine whether matcher contains function eval
639+
bool HasEval(const std::string& s);
640+
641+
// ReplaceEvalWithMap replace function eval with the value of its parameters via given sets.
642+
std::string ReplaceEvalWithMap(const std::string& src, std::unordered_map<std::string, std::string>& sets);
643+
638644
// Exception class for Casbin Adapter Exception.
639645
class CasbinAdapterException : std::logic_error {
640646
public:

tests/util_test.cpp

Lines changed: 34 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ void TestEscapeAssertionFn(const std::string& s, const std::string& res){
2626
ASSERT_EQ(my_res, res);
2727
}
2828

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

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

63-
TEST(TestModel, TestArrayEquals) {
63+
TEST(TestUtil, TestArrayEquals) {
6464
TestArrayEqualsFn({"a", "b", "c"}, {"a", "b", "c"}, true);
6565
TestArrayEqualsFn({"a", "b", "c"}, {"a", "b"}, false);
6666
TestArrayEqualsFn({"a", "b", "c"}, {"a", "c", "b"}, true);
6767
TestArrayEqualsFn({"a", "b", "c"}, {}, false);
6868
}
6969

70+
void testContainEval(std::string s, bool res) {
71+
ASSERT_EQ(casbin::HasEval(s), res);
72+
}
73+
74+
TEST(TestUtil, TestContainEval) {
75+
testContainEval("eval() && a && b && c", true);
76+
testContainEval("eval) && a && b && c", false);
77+
testContainEval("eval)( && a && b && c", false);
78+
testContainEval("eval(c * (a + b)) && a && b && c", true);
79+
testContainEval("xeval() && a && b && c", false);
80+
}
81+
82+
void testReplaceEvalWithMap(std::string s, std::unordered_map<std::string, std::string> sets, std::string res) {
83+
ASSERT_EQ(casbin::ReplaceEvalWithMap(s, sets), res);
84+
}
85+
86+
TEST(TestUtil, TestReplaceEvalWithMap) {
87+
testReplaceEvalWithMap("eval(rule1)", {{"rule1", "a == b"}}, "a == b");
88+
testReplaceEvalWithMap("eval(rule1) && c && d", {{"rule1", "a == b"}}, "a == b && c && d");
89+
testReplaceEvalWithMap("eval(rule1)", {{}}, "eval(rule1)");
90+
testReplaceEvalWithMap("eval(rule1) && c && d", {{}}, "eval(rule1) && c && d");
91+
testReplaceEvalWithMap("eval(rule1) || eval(rule2)", {{"rule1", "a == b"}, {"rule2", "a == c"}}, "a == b || a == c");
92+
testReplaceEvalWithMap("eval(rule1) || eval(rule2) && c && d", {{"rule1", "a == b"}, {"rule2", "a == c"}}, "a == b || a == c && c && d");
93+
testReplaceEvalWithMap("eval(rule1) || eval(rule2)", {{"rule1", "a == b"}}, "a == b || eval(rule2)");
94+
testReplaceEvalWithMap("eval(rule1) || eval(rule2) && c && d", {{"rule1", "a == b"}}, "a == b || eval(rule2) && c && d");
95+
testReplaceEvalWithMap("eval(rule1) || eval(rule2)", {{"rule2", "a == b"}}, "eval(rule1) || a == b");
96+
testReplaceEvalWithMap("eval(rule1) || eval(rule2) && c && d", {{"rule2", "a == b"}}, "eval(rule1) || a == b && c && d");
97+
testReplaceEvalWithMap("eval(rule1) || eval(rule2)", {}, "eval(rule1) || eval(rule2)");
98+
testReplaceEvalWithMap("eval(rule1) || eval(rule2) && c && d", {}, "eval(rule1) || eval(rule2) && c && d");
99+
}
100+
70101
} // namespace

0 commit comments

Comments
 (0)