diff --git a/src/model/FunctionMap.lua b/src/model/FunctionMap.lua index 570c2a6..5939124 100644 --- a/src/model/FunctionMap.lua +++ b/src/model/FunctionMap.lua @@ -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 diff --git a/src/util/BuiltInFunctions.lua b/src/util/BuiltInFunctions.lua index ee653c4..5c51310 100644 --- a/src/util/BuiltInFunctions.lua +++ b/src/util/BuiltInFunctions.lua @@ -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) @@ -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 @@ -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 *. @@ -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 @@ -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) @@ -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 *. @@ -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. @@ -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) @@ -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 @@ -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. diff --git a/tests/util/built_in_functions_spec.lua b/tests/util/built_in_functions_spec.lua index c496c91..f7ef8aa 100644 --- a/tests/util/built_in_functions_spec.lua +++ b/tests/util/built_in_functions_spec.lua @@ -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*")) @@ -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/*")) @@ -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*")) @@ -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")) @@ -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/*")) @@ -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}")) @@ -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")) @@ -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/*")) @@ -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"))