Skip to content

Commit

Permalink
feat: some adjustments to builtin functions (#162)
Browse files Browse the repository at this point in the history
* test: added cases for builtin functions errors

* style: conformed to casbin/casbin

- moved wrappers under respective functions
- moved keyMatch5

* fix: globMatch FunctionMap
  • Loading branch information
mikyll authored Nov 28, 2024
1 parent 399e18b commit 7ee85ed
Show file tree
Hide file tree
Showing 3 changed files with 90 additions and 53 deletions.
4 changes: 2 additions & 2 deletions src/model/FunctionMap.lua
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,10 @@ local FunctionMap = {
["keyGet2"] = BuiltInFunctions.keyGet2Func,
["keyMatch3"] = BuiltInFunctions.keyMatch3Func,
["keyMatch4"] = BuiltInFunctions.keyMatch4Func,
["keyMatch5"] = BuiltInFunctions.keyMatch4Func,
["regexMatch"] = BuiltInFunctions.regexMatchFunc,
["IPMatch"] = BuiltInFunctions.IPMatchFunc,
["globMatch"] = BuiltInFunctions.globMatch,
["keyMatch5"] = BuiltInFunctions.keyMatch4Func,
["globMatch"] = BuiltInFunctions.globMatchFunc,
}

-- FunctionMap provides a set of built in functions
Expand Down
102 changes: 51 additions & 51 deletions src/util/BuiltInFunctions.lua
Original file line number Diff line number Diff line change
Expand Up @@ -28,12 +28,6 @@ function BuiltInFunctions.validateVariadicArgs(expectedLen, args)
end
end

-- Wrapper for keyMatch
function BuiltInFunctions.keyMatchFunc(args)
BuiltInFunctions.validateVariadicArgs(2, args)
return BuiltInFunctions.keyMatch(args[1], args[2])
end

-- KeyMatch determines whether key1 matches the pattern of key2 (similar to RESTful path), key2 can contain a *.
-- For example, "/foo/bar" matches "/foo/*"
function BuiltInFunctions.keyMatch(key1, key2)
Expand All @@ -49,10 +43,10 @@ function BuiltInFunctions.keyMatch(key1, key2)
return (key1 == string.sub(key2, 1, i-1))
end

-- Wrapper for keyGet
function BuiltInFunctions.keyGetFunc(args)
-- Wrapper for keyMatch
function BuiltInFunctions.keyMatchFunc(args)
BuiltInFunctions.validateVariadicArgs(2, args)
return BuiltInFunctions.keyGet(args[1], args[2])
return BuiltInFunctions.keyMatch(args[1], args[2])
end

-- KeyGet returns the matched part
Expand All @@ -72,10 +66,10 @@ function BuiltInFunctions.keyGet(key1, key2)
return ""
end

-- Wrapper for keyMatch2
function BuiltInFunctions.keyMatch2Func(args)
-- Wrapper for keyGet
function BuiltInFunctions.keyGetFunc(args)
BuiltInFunctions.validateVariadicArgs(2, args)
return BuiltInFunctions.keyMatch2(args[1], args[2])
return BuiltInFunctions.keyGet(args[1], args[2])
end

-- KeyMatch2 determines whether key1 matches the pattern of key2 (similar to RESTful path), key2 can contain a *.
Expand All @@ -87,6 +81,12 @@ function BuiltInFunctions.keyMatch2(key1, key2)
return BuiltInFunctions.regexMatch(key1, "^"..key.."$")
end

-- Wrapper for keyMatch2
function BuiltInFunctions.keyMatch2Func(args)
BuiltInFunctions.validateVariadicArgs(2, args)
return BuiltInFunctions.keyMatch2(args[1], args[2])
end

-- KeyGet2 returns value matched pattern
-- For example, "/resource1" matches "/:resource"
-- if the pathVar == "resource", then "resource1" will be returned
Expand Down Expand Up @@ -117,12 +117,6 @@ function BuiltInFunctions.keyGet2Func(args)
return BuiltInFunctions.keyGet2(args[1], args[2],args[3])
end

-- Wrapper for keyMatch3
function BuiltInFunctions.keyMatch3Func(args)
BuiltInFunctions.validateVariadicArgs(2, args)
return BuiltInFunctions.keyMatch3(args[1], args[2])
end

-- KeyMatch3 determines whether key1 matches the pattern of key2 (similar to RESTful path), key2 can contain a *.
-- For example, "/foo/bar" matches "/foo/*", "/resource1" matches "/{resource}"
function BuiltInFunctions.keyMatch3(key1, key2)
Expand All @@ -131,10 +125,10 @@ function BuiltInFunctions.keyMatch3(key1, key2)
return BuiltInFunctions.regexMatch(key1, "^"..key.."$")
end

-- Wrapper for keyMatch4
function BuiltInFunctions.keyMatch4Func(args)
-- Wrapper for keyMatch3
function BuiltInFunctions.keyMatch3Func(args)
BuiltInFunctions.validateVariadicArgs(2, args)
return BuiltInFunctions.keyMatch4(args[1], args[2])
return BuiltInFunctions.keyMatch3(args[1], args[2])
end

-- KeyMatch4 determines whether key1 matches the pattern of key2 (similar to RESTful path), key2 can contain a *.
Expand Down Expand Up @@ -170,10 +164,34 @@ function BuiltInFunctions.keyMatch4(key1, key2)
return true
end

-- Wrapper for regexMatch
function BuiltInFunctions.regexMatchFunc(args)
-- Wrapper for keyMatch4
function BuiltInFunctions.keyMatch4Func(args)
BuiltInFunctions.validateVariadicArgs(2, args)
return BuiltInFunctions.regexMatch(args[1], args[2])
return BuiltInFunctions.keyMatch4(args[1], args[2])
end

-- KeyMatch5 determines whether key1 matches the pattern of key2 (similar to RESTful path), key2 can contain a *
-- For example,
-- - "/foo/bar?status=1&type=2" matches "/foo/bar"
-- - "/parent/child1" and "/parent/child1" matches "/parent/*"
-- - "/parent/child1?status=1" matches "/parent/*"
function BuiltInFunctions.keyMatch5(key1, key2)
local i = string.find(key1, "?", 1, true)

if i then
key1 = string.sub(key1, 1, i - 1)
end

key2 = string.gsub(key2, "/%*", "/.*")
key2 = string.gsub(key2, "%{[^/]+%}", "[^/]+")

return string.match(key1, "^" .. key2 .. "$") ~= nil
end

-- Wrapper for keyMatch5
function BuiltInFunctions.keyMatch5Func(args)
BuiltInFunctions.validateVariadicArgs(2, args)
return BuiltInFunctions.keyMatch5(args[1], args[2])
end

-- RegexMatch determines whether key1 matches the pattern of key2 in regular expression.
Expand All @@ -186,6 +204,12 @@ function BuiltInFunctions.regexMatch(key1, key2)
end
end

-- Wrapper for regexMatch
function BuiltInFunctions.regexMatchFunc(args)
BuiltInFunctions.validateVariadicArgs(2, args)
return BuiltInFunctions.regexMatch(args[1], args[2])
end

-- IPMatch determines whether IP address ip1 matches the pattern of IP address ip2, ip2 can be an IP address or a CIDR pattern.
-- For example, "192.168.2.123" matches "192.168.2.0/24"
function BuiltInFunctions.IPMatch(ip1, ip2)
Expand Down Expand Up @@ -232,12 +256,6 @@ function BuiltInFunctions.IPMatchFunc(args)
return BuiltInFunctions.IPMatch(args[1], args[2])
end

-- Wrapper for globMatch
function BuiltInFunctions.globMatchFunc(args)
BuiltInFunctions.validateVariadicArgs(2, args)
return BuiltInFunctions.globMatch(args[1], args[2])
end

-- GlobMatch determines whether key1 matches the pattern of key2 using glob pattern
function BuiltInFunctions.globMatch(key1, key2)
if posix.fnmatch(key2, key1, posix.FNM_PATHNAME or posix.FNM_PERIOD) == 0 then
Expand All @@ -247,28 +265,10 @@ function BuiltInFunctions.globMatch(key1, key2)
end
end

-- Wrapper for keyMatch5
function BuiltInFunctions.keyMatch5Func(args)
-- Wrapper for globMatch
function BuiltInFunctions.globMatchFunc(args)
BuiltInFunctions.validateVariadicArgs(2, args)
return BuiltInFunctions.keyMatch5(args[1], args[2])
end

-- KeyMatch5 determines whether key1 matches the pattern of key2 (similar to RESTful path), key2 can contain a *
-- For example,
-- - "/foo/bar?status=1&type=2" matches "/foo/bar"
-- - "/parent/child1" and "/parent/child1" matches "/parent/*"
-- - "/parent/child1?status=1" matches "/parent/*"
function BuiltInFunctions.keyMatch5(key1, key2)
local i = string.find(key1, "?", 1, true)

if i then
key1 = string.sub(key1, 1, i - 1)
end

key2 = string.gsub(key2, "/%*", "/.*")
key2 = string.gsub(key2, "%{[^/]+%}", "[^/]+")

return string.match(key1, "^" .. key2 .. "$") ~= nil
return BuiltInFunctions.globMatch(args[1], args[2])
end

-- GenerateGFunction is the factory method of the g(_, _) function.
Expand Down
37 changes: 37 additions & 0 deletions tests/util/built_in_functions_spec.lua
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,10 @@ local BuiltInFunctions = require("src.util.BuiltInFunctions")

describe("BuiltInFunctions tests", function ()
it("keyMatch tests", function ()
assert.has_error(function () BuiltInFunctions.keyMatchFunc({"/"}) end, "Expected 2 arguments, but got 1")
assert.has_error(function () BuiltInFunctions.keyMatchFunc({"/foo/create/123", "/*", "/foo/update/123"}) end, "Expected 2 arguments, but got 3")
assert.has_error(function () BuiltInFunctions.keyMatchFunc({"/foo", true}) end, "Argument must be a string")

assert.is.False(BuiltInFunctions.keyMatch("/foo", "/"))
assert.is.True(BuiltInFunctions.keyMatch("/foo", "/foo"))
assert.is.True(BuiltInFunctions.keyMatch("/foo", "/foo*"))
Expand All @@ -29,6 +33,10 @@ describe("BuiltInFunctions tests", function ()
end)

it("keyGet tests", function ()
assert.has_error(function () BuiltInFunctions.keyGetFunc({"/foo/bar/foo"}) end, "Expected 2 arguments, but got 1")
assert.has_error(function () BuiltInFunctions.keyGetFunc({"/foo/bar/foo", "/foo/*", "/bar"}) end, "Expected 2 arguments, but got 3")
assert.has_error(function () BuiltInFunctions.keyGetFunc({"/foo/bar/foo", true}) end, "Argument must be a string")

assert.are.same("", BuiltInFunctions.keyGet("/foo", "/foo"))
assert.are.same("", BuiltInFunctions.keyGet("/foo", "/foo*"))
assert.are.same("", BuiltInFunctions.keyGet("/foo", "/foo/*"))
Expand All @@ -41,6 +49,10 @@ describe("BuiltInFunctions tests", function ()
end)

it("keyMatch2 tests", function ()
assert.has_error(function () BuiltInFunctions.keyMatch2Func({"/"}) end, "Expected 2 arguments, but got 1")
assert.has_error(function () BuiltInFunctions.keyMatch2Func({"/foo/create/123", "/*", "/foo/update/123"}) end, "Expected 2 arguments, but got 3")
assert.has_error(function () BuiltInFunctions.keyMatch2Func({"/foo", true}) end, "Argument must be a string")

assert.is.False(BuiltInFunctions.keyMatch2("/foo", "/"))
assert.is.True(BuiltInFunctions.keyMatch2("/foo", "/foo"))
assert.is.True(BuiltInFunctions.keyMatch2("/foo", "/foo*"))
Expand Down Expand Up @@ -73,6 +85,11 @@ describe("BuiltInFunctions tests", function ()
end)

it("keyGet2 tests", function ()
assert.has_error(function () BuiltInFunctions.keyGet2Func({"/foo"}) end, "Expected 3 arguments, but got 1")
assert.has_error(function () BuiltInFunctions.keyGet2Func({"/foo", "/:bar"}) end, "Expected 3 arguments, but got 2")
assert.has_error(function () BuiltInFunctions.keyGet2Func({"/foo", "/:bar", "bar", "foobar"}) end, "Expected 3 arguments, but got 4")
assert.has_error(function () BuiltInFunctions.keyGet2Func({"/foo", "/:bar", true}) end, "Argument must be a string")

assert.are.equal("",BuiltInFunctions.keyGet2("/foo", "/foo", "id"))
assert.are.equal("",BuiltInFunctions.keyGet2("/foo", "/foo*", "id"))
assert.are.equal("",BuiltInFunctions.keyGet2("/foo", "/foo/*", "id"))
Expand Down Expand Up @@ -106,6 +123,10 @@ describe("BuiltInFunctions tests", function ()
end)

it("keyMatch3 tests", function ()
assert.has_error(function () BuiltInFunctions.keyMatch3Func({"/"}) end, "Expected 2 arguments, but got 1")
assert.has_error(function () BuiltInFunctions.keyMatch3Func({"/foo/create/123", "/*", "/foo/update/123"}) end, "Expected 2 arguments, but got 3")
assert.has_error(function () BuiltInFunctions.keyMatch3Func({"/foo", true}) end, "Argument must be a string")

assert.is.True(BuiltInFunctions.keyMatch3("/foo", "/foo"))
assert.is.True(BuiltInFunctions.keyMatch3("/foo", "/foo*"))
assert.is.False(BuiltInFunctions.keyMatch3("/foo", "/foo/*"))
Expand All @@ -132,6 +153,10 @@ describe("BuiltInFunctions tests", function ()
end)

it("keyMatch4 tests", function ()
assert.has_error(function () BuiltInFunctions.keyMatch4Func({"/parent/123/child/123"}) end, "Expected 2 arguments, but got 1")
assert.has_error(function () BuiltInFunctions.keyMatch4Func({"/parent/123/child/123", "/parent/{id}/child/{id}", true}) end, "Expected 2 arguments, but got 3")
assert.has_error(function () BuiltInFunctions.keyMatch4Func({"/parent/123/child/123", true}) end, "Argument must be a string")

assert.is.True(BuiltInFunctions.keyMatch4("/parent/123/child/123", "/parent/{id}/child/{id}"))
assert.is.False(BuiltInFunctions.keyMatch4("/parent/123/child/456", "/parent/{id}/child/{id}"))

Expand All @@ -148,6 +173,10 @@ describe("BuiltInFunctions tests", function ()
end)

it("regexMatch tests", function ()
assert.has_error(function () BuiltInFunctions.regexMatchFunc({"/topic/create"}) end, "Expected 2 arguments, but got 1")
assert.has_error(function () BuiltInFunctions.regexMatchFunc({"/topic/create/123", "/topic/create", "/topic/update"}) end, "Expected 2 arguments, but got 3")
assert.has_error(function () BuiltInFunctions.regexMatchFunc({"/topic/create", false}) end, "Argument must be a string")

assert.is.True(BuiltInFunctions.regexMatch("/topic/create", "/topic/create"))
assert.is.True(BuiltInFunctions.regexMatch("/topic/create/123", "/topic/create"))
assert.is.False(BuiltInFunctions.regexMatch("/topic/delete", "/topic/create"))
Expand All @@ -160,6 +189,10 @@ describe("BuiltInFunctions tests", function ()
end)

it("globMatch tests", function ()
assert.has_error(function () BuiltInFunctions.globMatchFunc({"/foo"}) end, "Expected 2 arguments, but got 1")
assert.has_error(function () BuiltInFunctions.globMatchFunc({"/foo", "/bar", "/foobar"}) end, "Expected 2 arguments, but got 3")
assert.has_error(function () BuiltInFunctions.globMatchFunc({"/foo", 128}) end, "Argument must be a string")

assert.is.True(BuiltInFunctions.globMatch("/foo", "/foo"))
assert.is.True(BuiltInFunctions.globMatch("/foo", "/foo*"))
assert.is.False(BuiltInFunctions.globMatch("/foo", "/foo/*"))
Expand Down Expand Up @@ -193,6 +226,10 @@ describe("BuiltInFunctions tests", function ()
end)

it("IPMatch tests", function ()
assert.has_error(function () BuiltInFunctions.IPMatchFunc({"192.168.2.123"}) end, "Expected 2 arguments, but got 1")
assert.has_error(function () BuiltInFunctions.IPMatchFunc({"192.168.2.123", "192.168.2.0/24", "192.168.2.0/26"}) end, "Expected 2 arguments, but got 3")
assert.has_error(function () BuiltInFunctions.IPMatchFunc({"192.168.2.123", 128}) end, "Argument must be a string")

assert.is.True(BuiltInFunctions.IPMatch("192.168.2.123", "192.168.2.0/24"))
assert.is.True(BuiltInFunctions.IPMatch("192.168.2.123", "192.168.2.0/25"))
assert.is.False(BuiltInFunctions.IPMatch("192.168.2.123", "192.168.2.0/26"))
Expand Down

0 comments on commit 7ee85ed

Please sign in to comment.