From a1f57ae70b842b5b14e2b52a72526019afa2b3dd Mon Sep 17 00:00:00 2001 From: soulbird Date: Thu, 27 Oct 2022 11:00:21 +0800 Subject: [PATCH 01/13] fix(ai): remove BUILD_ROUTER event when ai module is unloaded --- apisix/core/event.lua | 4 + apisix/plugins/ai.lua | 8 ++ t/plugin/ai.t | 246 ++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 258 insertions(+) diff --git a/apisix/core/event.lua b/apisix/core/event.lua index 38459ff11060..006cd1a0a5e9 100644 --- a/apisix/core/event.lua +++ b/apisix/core/event.lua @@ -38,4 +38,8 @@ function _M.register(type, handler) events[type] = handler end +function _M.unregister(type) + events[type] = nil +end + return _M diff --git a/apisix/plugins/ai.lua b/apisix/plugins/ai.lua index 46c90ef2e668..150b543aee86 100644 --- a/apisix/plugins/ai.lua +++ b/apisix/plugins/ai.lua @@ -312,7 +312,15 @@ function _M.destroy() apisix.http_balancer_phase = orig_http_balancer_phase orig_http_balancer_phase = nil end + + event.unregister(event.CONST.BUILD_ROUTER) end +-- for test +_M.route_matching = ai_router_http_matching +_M.handle_upstream = ai_upstream +_M.http_balancer_phase = ai_http_balancer_phase + + return _M diff --git a/t/plugin/ai.t b/t/plugin/ai.t index 6d04c192041a..cf989da422f4 100644 --- a/t/plugin/ai.t +++ b/t/plugin/ai.t @@ -25,6 +25,51 @@ no_shuffle(); add_block_preprocessor(sub { my ($block) = @_; + if (!defined $block->extra_init_by_lua) { + my $extra_init_by_lua = <<_EOC_; + unload_ai_module = function () + local t = require("lib.test_admin").test + local data = [[ +deployment: + role: traditional + role_traditional: + config_provider: etcd + admin: + admin_key: null +apisix: + node_listen: 1984 +plugins: + ]] + require("lib.test_admin").set_config_yaml(data) + + return t('/apisix/admin/plugins/reload', + ngx.HTTP_PUT) + end + + load_ai_module = function () + local t = require("lib.test_admin").test + local data = [[ +deployment: + role: traditional + role_traditional: + config_provider: etcd + admin: + admin_key: null +apisix: + node_listen: 1984 +plugins: + - ai + ]] + require("lib.test_admin").set_config_yaml(data) + ngx.log(ngx.INFO, "load ai module again") + return t('/apisix/admin/plugins/reload', + ngx.HTTP_PUT) + end +_EOC_ + + $block->set_value("extra_init_by_lua", $extra_init_by_lua); + } + if ((!defined $block->error_log) && (!defined $block->no_error_log)) { $block->set_value("no_error_log", "[error]"); } @@ -929,3 +974,204 @@ done --- error_log renew route cache: count=3001 renew route cache: count=3002 + + + +=== TEST 15: enable(default) -> disable -> enable +--- http_config eval: $::HttpConfig +--- config + location /t { + content_by_lua_block { + local ai = require("apisix.plugins.ai") + local router = require("apisix.router") + local org_match = router.router_http.matching + local ai_match = ai.route_matching + + local apisix = require("apisix") + local org_upstream = apisix.handle_upstream + local ai_upstream = ai.handle_upstream + + local org_balancer_phase = apisix.http_balancer_phase + local ai_balancer_phase = ai.http_balancer_phase + + local t = require("lib.test_admin").test + -- register route + local code, body = t('/apisix/admin/routes/1', + ngx.HTTP_PUT, + [[{ + "host": "127.0.0.1", + "methods": ["GET"], + "upstream": { + "nodes": { + "127.0.0.1:1980": 1 + }, + "type": "roundrobin" + }, + "uri": "/hello" + }]] + ) + if code >= 300 then + ngx.status = code + ngx.say(body) + return + end + + local code = t('/hello', ngx.HTTP_GET) + assert(code == 200) + assert(router.router_http.matching == ai_match) + assert(apisix.handle_upstream == ai_upstream) + assert(apisix.http_balancer_phase == ai_balancer_phase) + + -- disable ai plugin + local code = unload_ai_module() + assert(code == 200) + ngx.sleep(2) + local code = t('/hello', ngx.HTTP_GET) + assert(code == 200) + assert(router.router_http.matching == org_match) + assert(apisix.handle_upstream == org_upstream) + assert(apisix.http_balancer_phase == org_balancer_phase) + + -- enable ai plugin + local code = load_ai_module() + assert(code == 200) + ngx.sleep(2) + local code = t('/hello', ngx.HTTP_GET) + assert(code == 200) + -- TODO: It's not very reasonable, we need to fix it + assert(router.router_http.matching == org_match) + assert(apisix.handle_upstream == org_upstream) + assert(apisix.http_balancer_phase == org_balancer_phase) + + -- register a new route and trigger a route tree rebuild + local code, body = t('/apisix/admin/routes/2', + ngx.HTTP_PUT, + [[{ + "host": "127.0.0.1", + "methods": ["GET"], + "upstream": { + "nodes": { + "127.0.0.1:1980": 1 + }, + "type": "roundrobin" + }, + "uri": "/echo" + }]] + ) + if code >= 300 then + ngx.status = code + ngx.say(body) + return + end + + local code = t('/echo', ngx.HTTP_GET) + assert(code == 200) + local new_ai = require("apisix.plugins.ai") + assert(router.router_http.matching == new_ai.route_matching) + assert(apisix.handle_upstream == new_ai.handle_upstream) + assert(apisix.http_balancer_phase == new_ai.http_balancer_phase) + } + } + + + +=== TEST 16: disable(default) -> enable -> disable +--- ONLY +--- yaml_config +deployment: + role: traditional + role_traditional: + config_provider: etcd + admin: + admin_key: null +apisix: + node_listen: 1984 +plugins: +--- http_config eval: $::HttpConfig +--- config + location /t { + content_by_lua_block { + local router = require("apisix.router") + local org_match = router.router_http.matching + local apisix = require("apisix") + local org_upstream = apisix.handle_upstream + local org_balancer_phase = apisix.http_balancer_phase + + local t = require("lib.test_admin").test + -- register route + local code, body = t('/apisix/admin/routes/1', + ngx.HTTP_PUT, + [[{ + "host": "127.0.0.1", + "methods": ["GET"], + "upstream": { + "nodes": { + "127.0.0.1:1980": 1 + }, + "type": "roundrobin" + }, + "uri": "/hello" + }]] + ) + if code >= 300 then + ngx.status = code + ngx.say(body) + return + end + + local code = t('/hello', ngx.HTTP_GET) + assert(code == 200) + assert(router.router_http.matching == org_match) + assert(apisix.handle_upstream == org_upstream) + assert(apisix.http_balancer_phase == org_balancer_phase) + + -- enable ai plugin + local code = load_ai_module() + assert(code == 200) + ngx.sleep(2) + local code = t('/hello', ngx.HTTP_GET) + assert(code == 200) + -- TODO: It's not very reasonable, we need to fix it + assert(router.router_http.matching == org_match) + assert(apisix.handle_upstream == org_upstream) + assert(apisix.http_balancer_phase == org_balancer_phase) + + -- register a new route and trigger a route tree rebuild + local code, body = t('/apisix/admin/routes/2', + ngx.HTTP_PUT, + [[{ + "host": "127.0.0.1", + "methods": ["GET"], + "upstream": { + "nodes": { + "127.0.0.1:1980": 1 + }, + "type": "roundrobin" + }, + "uri": "/echo" + }]] + ) + if code >= 300 then + ngx.status = code + ngx.say(body) + return + end + + local code = t('/echo', ngx.HTTP_GET) + assert(code == 200) + local ai = require("apisix.plugins.ai") + assert(router.router_http.matching == ai.route_matching) + assert(apisix.handle_upstream == ai.handle_upstream) + assert(apisix.http_balancer_phase == ai.http_balancer_phase) + + -- disable ai plugin + local code = unload_ai_module() + assert(code == 200) + ngx.sleep(2) + local code = t('/hello', ngx.HTTP_GET) + assert(code == 200) + assert(router.router_http.matching == org_match) + assert(apisix.handle_upstream == org_upstream) + assert(apisix.http_balancer_phase == org_balancer_phase) + } + } \ No newline at end of file From 5fdbd9f0240b3cba25f77c79af0ce52ba476417c Mon Sep 17 00:00:00 2001 From: soulbird Date: Thu, 27 Oct 2022 11:02:31 +0800 Subject: [PATCH 02/13] fix lint --- t/plugin/ai.t | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/t/plugin/ai.t b/t/plugin/ai.t index cf989da422f4..8271cfcde86b 100644 --- a/t/plugin/ai.t +++ b/t/plugin/ai.t @@ -1076,7 +1076,6 @@ renew route cache: count=3002 === TEST 16: disable(default) -> enable -> disable ---- ONLY --- yaml_config deployment: role: traditional @@ -1174,4 +1173,4 @@ plugins: assert(apisix.handle_upstream == org_upstream) assert(apisix.http_balancer_phase == org_balancer_phase) } - } \ No newline at end of file + } From aaf072cfc9af7d0370dd3c7710aa7ded0ec3c737 Mon Sep 17 00:00:00 2001 From: soulbird Date: Thu, 27 Oct 2022 14:40:22 +0800 Subject: [PATCH 03/13] remove redundant code --- t/plugin/ai.t | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/t/plugin/ai.t b/t/plugin/ai.t index 8271cfcde86b..fa56dc8cfbf5 100644 --- a/t/plugin/ai.t +++ b/t/plugin/ai.t @@ -61,7 +61,7 @@ plugins: - ai ]] require("lib.test_admin").set_config_yaml(data) - ngx.log(ngx.INFO, "load ai module again") + return t('/apisix/admin/plugins/reload', ngx.HTTP_PUT) end From 12e68bb951ffa883fd03308eb69ae049cacc772f Mon Sep 17 00:00:00 2001 From: soulbird Date: Thu, 27 Oct 2022 16:48:06 +0800 Subject: [PATCH 04/13] add assert info --- t/plugin/ai.t | 73 ++++++++++++++++++++++++++------------------------- 1 file changed, 37 insertions(+), 36 deletions(-) diff --git a/t/plugin/ai.t b/t/plugin/ai.t index fa56dc8cfbf5..9c75df5ee409 100644 --- a/t/plugin/ai.t +++ b/t/plugin/ai.t @@ -978,6 +978,7 @@ renew route cache: count=3002 === TEST 15: enable(default) -> disable -> enable +--- ONLY --- http_config eval: $::HttpConfig --- config location /t { @@ -1017,31 +1018,31 @@ renew route cache: count=3002 end local code = t('/hello', ngx.HTTP_GET) - assert(code == 200) - assert(router.router_http.matching == ai_match) - assert(apisix.handle_upstream == ai_upstream) - assert(apisix.http_balancer_phase == ai_balancer_phase) + assert(code == 200, "enable(default): access /hello") + assert(router.router_http.matching == ai_match, "enable(default): router_http.matching") + assert(apisix.handle_upstream == ai_upstream, "enable(default): ai_upstream") + assert(apisix.http_balancer_phase == ai_balancer_phase, "enable(default): http_balancer_phase") -- disable ai plugin local code = unload_ai_module() - assert(code == 200) + assert(code == 200, "disable ai plugin") ngx.sleep(2) local code = t('/hello', ngx.HTTP_GET) - assert(code == 200) - assert(router.router_http.matching == org_match) - assert(apisix.handle_upstream == org_upstream) - assert(apisix.http_balancer_phase == org_balancer_phase) + assert(code == 200, "disable: access /hello") + assert(router.router_http.matching == org_match, "disable: router_http.matching") + assert(apisix.handle_upstream == org_upstream, "disable: ai_upstream") + assert(apisix.http_balancer_phase == org_balancer_phase, "disable: http_balancer_phase") -- enable ai plugin local code = load_ai_module() - assert(code == 200) + assert(code == 200, "enable ai plugin") ngx.sleep(2) local code = t('/hello', ngx.HTTP_GET) - assert(code == 200) + assert(code == 200, "enable: access /hello") -- TODO: It's not very reasonable, we need to fix it - assert(router.router_http.matching == org_match) - assert(apisix.handle_upstream == org_upstream) - assert(apisix.http_balancer_phase == org_balancer_phase) + assert(router.router_http.matching == org_match, "enable: router_http.matching") + assert(apisix.handle_upstream == org_upstream, "enable: ai_upstream") + assert(apisix.http_balancer_phase == org_balancer_phase, "enable: http_balancer_phase") -- register a new route and trigger a route tree rebuild local code, body = t('/apisix/admin/routes/2', @@ -1065,11 +1066,11 @@ renew route cache: count=3002 end local code = t('/echo', ngx.HTTP_GET) - assert(code == 200) + assert(code == 200, "register again: access /echo") local new_ai = require("apisix.plugins.ai") - assert(router.router_http.matching == new_ai.route_matching) - assert(apisix.handle_upstream == new_ai.handle_upstream) - assert(apisix.http_balancer_phase == new_ai.http_balancer_phase) + assert(router.router_http.matching == new_ai.route_matching, "enable(after require): router_http.matching") + assert(apisix.handle_upstream == new_ai.handle_upstream, "enable(after require): handle_upstream") + assert(apisix.http_balancer_phase == new_ai.http_balancer_phase, "enable(after require): http_balancer_phase") } } @@ -1119,21 +1120,21 @@ plugins: end local code = t('/hello', ngx.HTTP_GET) - assert(code == 200) - assert(router.router_http.matching == org_match) - assert(apisix.handle_upstream == org_upstream) - assert(apisix.http_balancer_phase == org_balancer_phase) + assert(code == 200, "disable(default): access /hello") + assert(router.router_http.matching == org_match, "disable(default): router_http.matching") + assert(apisix.handle_upstream == org_upstream, "disable(default): handle_upstream") + assert(apisix.http_balancer_phase == org_balancer_phase, "disable(default): http_balancer_phase") -- enable ai plugin local code = load_ai_module() - assert(code == 200) + assert(code == 200, "enable ai plugin") ngx.sleep(2) local code = t('/hello', ngx.HTTP_GET) - assert(code == 200) + assert(code == 200, "enable: access /hello") -- TODO: It's not very reasonable, we need to fix it - assert(router.router_http.matching == org_match) - assert(apisix.handle_upstream == org_upstream) - assert(apisix.http_balancer_phase == org_balancer_phase) + assert(router.router_http.matching == org_match, "enable: router_http.matching") + assert(apisix.handle_upstream == org_upstream, "enable: handle_upstream") + assert(apisix.http_balancer_phase == org_balancer_phase, "enable: http_balancer_phase") -- register a new route and trigger a route tree rebuild local code, body = t('/apisix/admin/routes/2', @@ -1157,20 +1158,20 @@ plugins: end local code = t('/echo', ngx.HTTP_GET) - assert(code == 200) + assert(code == 200, "register again: access /echo") local ai = require("apisix.plugins.ai") - assert(router.router_http.matching == ai.route_matching) - assert(apisix.handle_upstream == ai.handle_upstream) - assert(apisix.http_balancer_phase == ai.http_balancer_phase) + assert(router.router_http.matching == ai.route_matching, "enable(after require): router_http.matching") + assert(apisix.handle_upstream == ai.handle_upstream, "enable(after require): handle_upstream") + assert(apisix.http_balancer_phase == ai.http_balancer_phase, "enable(after require): http_balancer_phase") -- disable ai plugin local code = unload_ai_module() - assert(code == 200) + assert(code == 200, "unload ai plugin") ngx.sleep(2) local code = t('/hello', ngx.HTTP_GET) - assert(code == 200) - assert(router.router_http.matching == org_match) - assert(apisix.handle_upstream == org_upstream) - assert(apisix.http_balancer_phase == org_balancer_phase) + assert(code == 200, "disable: access /hello") + assert(router.router_http.matching == org_match, "disable: router_http.matching") + assert(apisix.handle_upstream == org_upstream, "disable: handle_upstream") + assert(apisix.http_balancer_phase == org_balancer_phase, "disable: http_balancer_phase") } } From 990df1e7f7a8fd49481cb77438e63cac4bf259a7 Mon Sep 17 00:00:00 2001 From: soulbird Date: Thu, 27 Oct 2022 17:05:37 +0800 Subject: [PATCH 05/13] fix lint --- t/plugin/ai.t | 1 - 1 file changed, 1 deletion(-) diff --git a/t/plugin/ai.t b/t/plugin/ai.t index 9c75df5ee409..d12b49431c91 100644 --- a/t/plugin/ai.t +++ b/t/plugin/ai.t @@ -978,7 +978,6 @@ renew route cache: count=3002 === TEST 15: enable(default) -> disable -> enable ---- ONLY --- http_config eval: $::HttpConfig --- config location /t { From fd21fb358a8f229315a2c9d3ebdc8da170776d6b Mon Sep 17 00:00:00 2001 From: soulbird Date: Thu, 27 Oct 2022 20:19:20 +0800 Subject: [PATCH 06/13] use a separate file --- t/plugin/ai.t | 299 ------------------------------------------------- t/plugin/ai3.t | 283 ++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 283 insertions(+), 299 deletions(-) create mode 100644 t/plugin/ai3.t diff --git a/t/plugin/ai.t b/t/plugin/ai.t index d12b49431c91..f695788ec190 100644 --- a/t/plugin/ai.t +++ b/t/plugin/ai.t @@ -25,51 +25,6 @@ no_shuffle(); add_block_preprocessor(sub { my ($block) = @_; - if (!defined $block->extra_init_by_lua) { - my $extra_init_by_lua = <<_EOC_; - unload_ai_module = function () - local t = require("lib.test_admin").test - local data = [[ -deployment: - role: traditional - role_traditional: - config_provider: etcd - admin: - admin_key: null -apisix: - node_listen: 1984 -plugins: - ]] - require("lib.test_admin").set_config_yaml(data) - - return t('/apisix/admin/plugins/reload', - ngx.HTTP_PUT) - end - - load_ai_module = function () - local t = require("lib.test_admin").test - local data = [[ -deployment: - role: traditional - role_traditional: - config_provider: etcd - admin: - admin_key: null -apisix: - node_listen: 1984 -plugins: - - ai - ]] - require("lib.test_admin").set_config_yaml(data) - - return t('/apisix/admin/plugins/reload', - ngx.HTTP_PUT) - end -_EOC_ - - $block->set_value("extra_init_by_lua", $extra_init_by_lua); - } - if ((!defined $block->error_log) && (!defined $block->no_error_log)) { $block->set_value("no_error_log", "[error]"); } @@ -920,257 +875,3 @@ done qr/enable sample upstream/ --- grep_error_log_out enable sample upstream - - - -=== TEST 14: renew route cache ---- config - location /t { - content_by_lua_block { - local t = require("lib.test_admin").test - local http = require "resty.http" - local uri = "http://127.0.0.1:" .. ngx.var.server_port .. "/hello" - for k = 1, 2 do - local code, body = t('/apisix/admin/routes/' .. k, - ngx.HTTP_PUT, - [[{ - "host": "127.0.0.1", - "methods": ["GET"], - "plugins": { - "proxy-rewrite": { - "uri": "/hello" - } - }, - "upstream": { - "nodes": { - "127.0.0.1:1980": 1 - }, - "type": "roundrobin" - }, - "uri": "/hello]] .. k .. [[" - }]] - ) - if code >= 300 then - ngx.status = code - ngx.say(body) - return - end - ngx.sleep(1) - for i = 1, 2 do - local httpc = http.new() - local res, err = httpc:request_uri(uri .. k) - assert(res.status == 200) - if not res then - ngx.log(ngx.ERR, err) - return - end - end - end - ngx.say("done") - } - } ---- response_body -done ---- error_log -renew route cache: count=3001 -renew route cache: count=3002 - - - -=== TEST 15: enable(default) -> disable -> enable ---- http_config eval: $::HttpConfig ---- config - location /t { - content_by_lua_block { - local ai = require("apisix.plugins.ai") - local router = require("apisix.router") - local org_match = router.router_http.matching - local ai_match = ai.route_matching - - local apisix = require("apisix") - local org_upstream = apisix.handle_upstream - local ai_upstream = ai.handle_upstream - - local org_balancer_phase = apisix.http_balancer_phase - local ai_balancer_phase = ai.http_balancer_phase - - local t = require("lib.test_admin").test - -- register route - local code, body = t('/apisix/admin/routes/1', - ngx.HTTP_PUT, - [[{ - "host": "127.0.0.1", - "methods": ["GET"], - "upstream": { - "nodes": { - "127.0.0.1:1980": 1 - }, - "type": "roundrobin" - }, - "uri": "/hello" - }]] - ) - if code >= 300 then - ngx.status = code - ngx.say(body) - return - end - - local code = t('/hello', ngx.HTTP_GET) - assert(code == 200, "enable(default): access /hello") - assert(router.router_http.matching == ai_match, "enable(default): router_http.matching") - assert(apisix.handle_upstream == ai_upstream, "enable(default): ai_upstream") - assert(apisix.http_balancer_phase == ai_balancer_phase, "enable(default): http_balancer_phase") - - -- disable ai plugin - local code = unload_ai_module() - assert(code == 200, "disable ai plugin") - ngx.sleep(2) - local code = t('/hello', ngx.HTTP_GET) - assert(code == 200, "disable: access /hello") - assert(router.router_http.matching == org_match, "disable: router_http.matching") - assert(apisix.handle_upstream == org_upstream, "disable: ai_upstream") - assert(apisix.http_balancer_phase == org_balancer_phase, "disable: http_balancer_phase") - - -- enable ai plugin - local code = load_ai_module() - assert(code == 200, "enable ai plugin") - ngx.sleep(2) - local code = t('/hello', ngx.HTTP_GET) - assert(code == 200, "enable: access /hello") - -- TODO: It's not very reasonable, we need to fix it - assert(router.router_http.matching == org_match, "enable: router_http.matching") - assert(apisix.handle_upstream == org_upstream, "enable: ai_upstream") - assert(apisix.http_balancer_phase == org_balancer_phase, "enable: http_balancer_phase") - - -- register a new route and trigger a route tree rebuild - local code, body = t('/apisix/admin/routes/2', - ngx.HTTP_PUT, - [[{ - "host": "127.0.0.1", - "methods": ["GET"], - "upstream": { - "nodes": { - "127.0.0.1:1980": 1 - }, - "type": "roundrobin" - }, - "uri": "/echo" - }]] - ) - if code >= 300 then - ngx.status = code - ngx.say(body) - return - end - - local code = t('/echo', ngx.HTTP_GET) - assert(code == 200, "register again: access /echo") - local new_ai = require("apisix.plugins.ai") - assert(router.router_http.matching == new_ai.route_matching, "enable(after require): router_http.matching") - assert(apisix.handle_upstream == new_ai.handle_upstream, "enable(after require): handle_upstream") - assert(apisix.http_balancer_phase == new_ai.http_balancer_phase, "enable(after require): http_balancer_phase") - } - } - - - -=== TEST 16: disable(default) -> enable -> disable ---- yaml_config -deployment: - role: traditional - role_traditional: - config_provider: etcd - admin: - admin_key: null -apisix: - node_listen: 1984 -plugins: ---- http_config eval: $::HttpConfig ---- config - location /t { - content_by_lua_block { - local router = require("apisix.router") - local org_match = router.router_http.matching - local apisix = require("apisix") - local org_upstream = apisix.handle_upstream - local org_balancer_phase = apisix.http_balancer_phase - - local t = require("lib.test_admin").test - -- register route - local code, body = t('/apisix/admin/routes/1', - ngx.HTTP_PUT, - [[{ - "host": "127.0.0.1", - "methods": ["GET"], - "upstream": { - "nodes": { - "127.0.0.1:1980": 1 - }, - "type": "roundrobin" - }, - "uri": "/hello" - }]] - ) - if code >= 300 then - ngx.status = code - ngx.say(body) - return - end - - local code = t('/hello', ngx.HTTP_GET) - assert(code == 200, "disable(default): access /hello") - assert(router.router_http.matching == org_match, "disable(default): router_http.matching") - assert(apisix.handle_upstream == org_upstream, "disable(default): handle_upstream") - assert(apisix.http_balancer_phase == org_balancer_phase, "disable(default): http_balancer_phase") - - -- enable ai plugin - local code = load_ai_module() - assert(code == 200, "enable ai plugin") - ngx.sleep(2) - local code = t('/hello', ngx.HTTP_GET) - assert(code == 200, "enable: access /hello") - -- TODO: It's not very reasonable, we need to fix it - assert(router.router_http.matching == org_match, "enable: router_http.matching") - assert(apisix.handle_upstream == org_upstream, "enable: handle_upstream") - assert(apisix.http_balancer_phase == org_balancer_phase, "enable: http_balancer_phase") - - -- register a new route and trigger a route tree rebuild - local code, body = t('/apisix/admin/routes/2', - ngx.HTTP_PUT, - [[{ - "host": "127.0.0.1", - "methods": ["GET"], - "upstream": { - "nodes": { - "127.0.0.1:1980": 1 - }, - "type": "roundrobin" - }, - "uri": "/echo" - }]] - ) - if code >= 300 then - ngx.status = code - ngx.say(body) - return - end - - local code = t('/echo', ngx.HTTP_GET) - assert(code == 200, "register again: access /echo") - local ai = require("apisix.plugins.ai") - assert(router.router_http.matching == ai.route_matching, "enable(after require): router_http.matching") - assert(apisix.handle_upstream == ai.handle_upstream, "enable(after require): handle_upstream") - assert(apisix.http_balancer_phase == ai.http_balancer_phase, "enable(after require): http_balancer_phase") - - -- disable ai plugin - local code = unload_ai_module() - assert(code == 200, "unload ai plugin") - ngx.sleep(2) - local code = t('/hello', ngx.HTTP_GET) - assert(code == 200, "disable: access /hello") - assert(router.router_http.matching == org_match, "disable: router_http.matching") - assert(apisix.handle_upstream == org_upstream, "disable: handle_upstream") - assert(apisix.http_balancer_phase == org_balancer_phase, "disable: http_balancer_phase") - } - } diff --git a/t/plugin/ai3.t b/t/plugin/ai3.t new file mode 100644 index 000000000000..4c89dce1c75f --- /dev/null +++ b/t/plugin/ai3.t @@ -0,0 +1,283 @@ +# +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. +# The ASF licenses this file to You 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. +# +use t::APISIX 'no_plan'; + +repeat_each(1); +log_level('info'); +worker_connections(256); +no_root_location(); +no_shuffle(); + +add_block_preprocessor(sub { + my ($block) = @_; + + if (!defined $block->extra_init_by_lua) { + my $extra_init_by_lua = <<_EOC_; + unload_ai_module = function () + local t = require("lib.test_admin").test + local data = [[ +deployment: + role: traditional + role_traditional: + config_provider: etcd + admin: + admin_key: null +apisix: + node_listen: 1984 +plugins: + ]] + require("lib.test_admin").set_config_yaml(data) + + return t('/apisix/admin/plugins/reload', + ngx.HTTP_PUT) + end + + load_ai_module = function () + local t = require("lib.test_admin").test + local data = [[ +deployment: + role: traditional + role_traditional: + config_provider: etcd + admin: + admin_key: null +apisix: + node_listen: 1984 +plugins: + - ai + ]] + require("lib.test_admin").set_config_yaml(data) + + return t('/apisix/admin/plugins/reload', + ngx.HTTP_PUT) + end +_EOC_ + + $block->set_value("extra_init_by_lua", $extra_init_by_lua); + } + + if ((!defined $block->error_log) && (!defined $block->no_error_log)) { + $block->set_value("no_error_log", "[error]"); + } + + if (!defined $block->request) { + $block->set_value("request", "GET /t"); + } + +}); + +run_tests(); + +__DATA__ + +=== TEST 1: enable(default) -> disable -> enable +--- http_config eval: $::HttpConfig +--- config + location /t { + content_by_lua_block { + local ai = require("apisix.plugins.ai") + local router = require("apisix.router") + local org_match = router.router_http.matching + local ai_match = ai.route_matching + + local apisix = require("apisix") + local org_upstream = apisix.handle_upstream + local ai_upstream = ai.handle_upstream + + local org_balancer_phase = apisix.http_balancer_phase + local ai_balancer_phase = ai.http_balancer_phase + + local t = require("lib.test_admin").test + -- register route + local code, body = t('/apisix/admin/routes/1', + ngx.HTTP_PUT, + [[{ + "host": "127.0.0.1", + "methods": ["GET"], + "upstream": { + "nodes": { + "127.0.0.1:1980": 1 + }, + "type": "roundrobin" + }, + "uri": "/hello" + }]] + ) + if code >= 300 then + ngx.status = code + ngx.say(body) + return + end + + local code = t('/hello', ngx.HTTP_GET) + assert(code == 200, "enable(default): access /hello") + assert(router.router_http.matching == ai_match, "enable(default): router_http.matching") + assert(apisix.handle_upstream == ai_upstream, "enable(default): ai_upstream") + assert(apisix.http_balancer_phase == ai_balancer_phase, "enable(default): http_balancer_phase") + + -- disable ai plugin + local code = unload_ai_module() + assert(code == 200, "disable ai plugin") + ngx.sleep(2) + local code = t('/hello', ngx.HTTP_GET) + assert(code == 200, "disable: access /hello") + assert(router.router_http.matching == org_match, "disable: router_http.matching") + assert(apisix.handle_upstream == org_upstream, "disable: ai_upstream") + assert(apisix.http_balancer_phase == org_balancer_phase, "disable: http_balancer_phase") + + -- enable ai plugin + local code = load_ai_module() + assert(code == 200, "enable ai plugin") + ngx.sleep(2) + local code = t('/hello', ngx.HTTP_GET) + assert(code == 200, "enable: access /hello") + -- TODO: It's not very reasonable, we need to fix it + assert(router.router_http.matching == org_match, "enable: router_http.matching") + assert(apisix.handle_upstream == org_upstream, "enable: ai_upstream") + assert(apisix.http_balancer_phase == org_balancer_phase, "enable: http_balancer_phase") + + -- register a new route and trigger a route tree rebuild + local code, body = t('/apisix/admin/routes/2', + ngx.HTTP_PUT, + [[{ + "host": "127.0.0.1", + "methods": ["GET"], + "upstream": { + "nodes": { + "127.0.0.1:1980": 1 + }, + "type": "roundrobin" + }, + "uri": "/echo" + }]] + ) + if code >= 300 then + ngx.status = code + ngx.say(body) + return + end + + local code = t('/echo', ngx.HTTP_GET) + assert(code == 200, "register again: access /echo") + local new_ai = require("apisix.plugins.ai") + assert(router.router_http.matching == new_ai.route_matching, "enable(after require): router_http.matching") + assert(apisix.handle_upstream == new_ai.handle_upstream, "enable(after require): handle_upstream") + assert(apisix.http_balancer_phase == new_ai.http_balancer_phase, "enable(after require): http_balancer_phase") + } + } + + + +=== TEST 2: disable(default) -> enable -> disable +--- yaml_config +deployment: + role: traditional + role_traditional: + config_provider: etcd + admin: + admin_key: null +apisix: + node_listen: 1984 +plugins: +--- http_config eval: $::HttpConfig +--- config + location /t { + content_by_lua_block { + local router = require("apisix.router") + local org_match = router.router_http.matching + local apisix = require("apisix") + local org_upstream = apisix.handle_upstream + local org_balancer_phase = apisix.http_balancer_phase + + local t = require("lib.test_admin").test + -- register route + local code, body = t('/apisix/admin/routes/1', + ngx.HTTP_PUT, + [[{ + "host": "127.0.0.1", + "methods": ["GET"], + "upstream": { + "nodes": { + "127.0.0.1:1980": 1 + }, + "type": "roundrobin" + }, + "uri": "/hello" + }]] + ) + if code >= 300 then + ngx.status = code + ngx.say(body) + return + end + + local code = t('/hello', ngx.HTTP_GET) + assert(code == 200, "disable(default): access /hello") + assert(router.router_http.matching == org_match, "disable(default): router_http.matching") + assert(apisix.handle_upstream == org_upstream, "disable(default): handle_upstream") + assert(apisix.http_balancer_phase == org_balancer_phase, "disable(default): http_balancer_phase") + + -- enable ai plugin + local code = load_ai_module() + assert(code == 200, "enable ai plugin") + ngx.sleep(2) + local code = t('/hello', ngx.HTTP_GET) + assert(code == 200, "enable: access /hello") + -- TODO: It's not very reasonable, we need to fix it + assert(router.router_http.matching == org_match, "enable: router_http.matching") + assert(apisix.handle_upstream == org_upstream, "enable: handle_upstream") + assert(apisix.http_balancer_phase == org_balancer_phase, "enable: http_balancer_phase") + + -- register a new route and trigger a route tree rebuild + local code, body = t('/apisix/admin/routes/2', + ngx.HTTP_PUT, + [[{ + "host": "127.0.0.1", + "methods": ["GET"], + "upstream": { + "nodes": { + "127.0.0.1:1980": 1 + }, + "type": "roundrobin" + }, + "uri": "/echo" + }]] + ) + if code >= 300 then + ngx.status = code + ngx.say(body) + return + end + + local code = t('/echo', ngx.HTTP_GET) + assert(code == 200, "register again: access /echo") + local ai = require("apisix.plugins.ai") + assert(router.router_http.matching == ai.route_matching, "enable(after require): router_http.matching") + assert(apisix.handle_upstream == ai.handle_upstream, "enable(after require): handle_upstream") + assert(apisix.http_balancer_phase == ai.http_balancer_phase, "enable(after require): http_balancer_phase") + + -- disable ai plugin + local code = unload_ai_module() + assert(code == 200, "unload ai plugin") + ngx.sleep(2) + local code = t('/hello', ngx.HTTP_GET) + assert(code == 200, "disable: access /hello") + assert(router.router_http.matching == org_match, "disable: router_http.matching") + assert(apisix.handle_upstream == org_upstream, "disable: handle_upstream") + assert(apisix.http_balancer_phase == org_balancer_phase, "disable: http_balancer_phase") + } + } From 87e4ab080ad83267aa0086778eaaf16a514aba28 Mon Sep 17 00:00:00 2001 From: soulbird Date: Thu, 27 Oct 2022 20:21:48 +0800 Subject: [PATCH 07/13] recover test case --- t/plugin/ai.t | 55 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 55 insertions(+) diff --git a/t/plugin/ai.t b/t/plugin/ai.t index f695788ec190..8845156b7e5a 100644 --- a/t/plugin/ai.t +++ b/t/plugin/ai.t @@ -875,3 +875,58 @@ done qr/enable sample upstream/ --- grep_error_log_out enable sample upstream + + + +=== TEST 14: renew route cache +--- FIRST +--- config + location /t { + content_by_lua_block { + local t = require("lib.test_admin").test + local http = require "resty.http" + local uri = "http://127.0.0.1:" .. ngx.var.server_port .. "/hello" + for k = 1, 2 do + local code, body = t('/apisix/admin/routes/' .. k, + ngx.HTTP_PUT, + [[{ + "host": "127.0.0.1", + "methods": ["GET"], + "plugins": { + "proxy-rewrite": { + "uri": "/hello" + } + }, + "upstream": { + "nodes": { + "127.0.0.1:1980": 1 + }, + "type": "roundrobin" + }, + "uri": "/hello]] .. k .. [[" + }]] + ) + if code >= 300 then + ngx.status = code + ngx.say(body) + return + end + ngx.sleep(1) + for i = 1, 2 do + local httpc = http.new() + local res, err = httpc:request_uri(uri .. k) + assert(res.status == 200) + if not res then + ngx.log(ngx.ERR, err) + return + end + end + end + ngx.say("done") + } + } +--- response_body +done +--- error_log +renew route cache: count=3001 +renew route cache: count=3002 From 469bce5f0e1b08a9663ee92e151990f97ffac372 Mon Sep 17 00:00:00 2001 From: soulbird Date: Thu, 27 Oct 2022 20:22:16 +0800 Subject: [PATCH 08/13] remove redundant code --- t/plugin/ai.t | 1 - 1 file changed, 1 deletion(-) diff --git a/t/plugin/ai.t b/t/plugin/ai.t index 8845156b7e5a..6d04c192041a 100644 --- a/t/plugin/ai.t +++ b/t/plugin/ai.t @@ -879,7 +879,6 @@ enable sample upstream === TEST 14: renew route cache ---- FIRST --- config location /t { content_by_lua_block { From 90533f5e8de1f0f7676c091693170560be3d00d4 Mon Sep 17 00:00:00 2001 From: soulbird Date: Thu, 27 Oct 2022 20:23:06 +0800 Subject: [PATCH 09/13] remove redundant code --- t/plugin/ai3.t | 1 - 1 file changed, 1 deletion(-) diff --git a/t/plugin/ai3.t b/t/plugin/ai3.t index 4c89dce1c75f..09c5a6261e09 100644 --- a/t/plugin/ai3.t +++ b/t/plugin/ai3.t @@ -16,7 +16,6 @@ # use t::APISIX 'no_plan'; -repeat_each(1); log_level('info'); worker_connections(256); no_root_location(); From d2012686ceeb093a0333ad0248ff0cc0da944ec7 Mon Sep 17 00:00:00 2001 From: soulbird Date: Wed, 2 Nov 2022 21:55:48 +0800 Subject: [PATCH 10/13] juge by log --- apisix/http/router/radixtree_host_uri.lua | 2 + apisix/http/router/radixtree_uri.lua | 2 + .../router/radixtree_uri_with_parameter.lua | 2 + apisix/plugins/ai.lua | 10 +- t/plugin/ai3.t | 130 ++++++++---------- 5 files changed, 67 insertions(+), 79 deletions(-) diff --git a/apisix/http/router/radixtree_host_uri.lua b/apisix/http/router/radixtree_host_uri.lua index 449a6ccdbba7..70919763c7e6 100644 --- a/apisix/http/router/radixtree_host_uri.lua +++ b/apisix/http/router/radixtree_host_uri.lua @@ -155,6 +155,8 @@ end function _M.matching(api_ctx) + core.log.info("route match mode: radixtree_host_uri") + core.table.clear(match_opts) match_opts.method = api_ctx.var.request_method match_opts.remote_addr = api_ctx.var.remote_addr diff --git a/apisix/http/router/radixtree_uri.lua b/apisix/http/router/radixtree_uri.lua index 25789a4a3c63..6e546364ac14 100644 --- a/apisix/http/router/radixtree_uri.lua +++ b/apisix/http/router/radixtree_uri.lua @@ -50,6 +50,8 @@ end function _M.matching(api_ctx) + core.log.info("route match mode: radixtree_uri") + return base_router.match_uri(uri_router, match_opts, api_ctx) end diff --git a/apisix/http/router/radixtree_uri_with_parameter.lua b/apisix/http/router/radixtree_uri_with_parameter.lua index 696c74f0be4b..4bf7f3ebee5f 100644 --- a/apisix/http/router/radixtree_uri_with_parameter.lua +++ b/apisix/http/router/radixtree_uri_with_parameter.lua @@ -50,6 +50,8 @@ end function _M.matching(api_ctx) + core.log.info("route match mode: radixtree_uri_with_parameter") + return base_router.match_uri(uri_router, match_opts, api_ctx) end diff --git a/apisix/plugins/ai.lua b/apisix/plugins/ai.lua index 150b543aee86..6e8453e0864c 100644 --- a/apisix/plugins/ai.lua +++ b/apisix/plugins/ai.lua @@ -73,6 +73,8 @@ end local function ai_router_http_matching(api_ctx) + core.log.info("route match mode: ai_match") + local key = get_cache_key_func(api_ctx) core.log.info("route cache key: ", key) local api_ctx_cache = route_lrucache(key, nil, @@ -296,8 +298,6 @@ end function _M.destroy() - -- TODO: add test cases to cover this function - -- if the ai plugin is disabled at runtime, all functions replaced by the ai plugin are restored if orig_router_http_matching then router.router_http.matching = orig_router_http_matching orig_router_http_matching = nil @@ -317,10 +317,4 @@ function _M.destroy() end --- for test -_M.route_matching = ai_router_http_matching -_M.handle_upstream = ai_upstream -_M.http_balancer_phase = ai_http_balancer_phase - - return _M diff --git a/t/plugin/ai3.t b/t/plugin/ai3.t index 09c5a6261e09..76f15216ec9a 100644 --- a/t/plugin/ai3.t +++ b/t/plugin/ai3.t @@ -41,8 +41,13 @@ plugins: ]] require("lib.test_admin").set_config_yaml(data) - return t('/apisix/admin/plugins/reload', + local code, body = t('/apisix/admin/plugins/reload', ngx.HTTP_PUT) + if code >= 300 then + ngx.status = code + ngx.say(body) + return + end end load_ai_module = function () @@ -61,8 +66,13 @@ plugins: ]] require("lib.test_admin").set_config_yaml(data) - return t('/apisix/admin/plugins/reload', - ngx.HTTP_PUT) + local code, body = t('/apisix/admin/plugins/reload', + ngx.HTTP_PUT) + if code >= 300 then + ngx.status = code + ngx.say(body) + return + end end _EOC_ @@ -88,18 +98,6 @@ __DATA__ --- config location /t { content_by_lua_block { - local ai = require("apisix.plugins.ai") - local router = require("apisix.router") - local org_match = router.router_http.matching - local ai_match = ai.route_matching - - local apisix = require("apisix") - local org_upstream = apisix.handle_upstream - local ai_upstream = ai.handle_upstream - - local org_balancer_phase = apisix.http_balancer_phase - local ai_balancer_phase = ai.http_balancer_phase - local t = require("lib.test_admin").test -- register route local code, body = t('/apisix/admin/routes/1', @@ -121,33 +119,24 @@ __DATA__ ngx.say(body) return end - + -- enable route cache local code = t('/hello', ngx.HTTP_GET) - assert(code == 200, "enable(default): access /hello") - assert(router.router_http.matching == ai_match, "enable(default): router_http.matching") - assert(apisix.handle_upstream == ai_upstream, "enable(default): ai_upstream") - assert(apisix.http_balancer_phase == ai_balancer_phase, "enable(default): http_balancer_phase") + assert(code == 200) -- disable ai plugin - local code = unload_ai_module() - assert(code == 200, "disable ai plugin") - ngx.sleep(2) + unload_ai_module() + local code = t('/hello', ngx.HTTP_GET) - assert(code == 200, "disable: access /hello") - assert(router.router_http.matching == org_match, "disable: router_http.matching") - assert(apisix.handle_upstream == org_upstream, "disable: ai_upstream") - assert(apisix.http_balancer_phase == org_balancer_phase, "disable: http_balancer_phase") + assert(code == 200) -- enable ai plugin - local code = load_ai_module() - assert(code == 200, "enable ai plugin") - ngx.sleep(2) + load_ai_module() + + -- TODO: The route cache should be enabled, but since no new routes are registered, + -- the route tree is not rebuilt, + -- so it is not possible to switch to route cache mode, we should fix it local code = t('/hello', ngx.HTTP_GET) assert(code == 200, "enable: access /hello") - -- TODO: It's not very reasonable, we need to fix it - assert(router.router_http.matching == org_match, "enable: router_http.matching") - assert(apisix.handle_upstream == org_upstream, "enable: ai_upstream") - assert(apisix.http_balancer_phase == org_balancer_phase, "enable: http_balancer_phase") -- register a new route and trigger a route tree rebuild local code, body = t('/apisix/admin/routes/2', @@ -170,14 +159,23 @@ __DATA__ return end - local code = t('/echo', ngx.HTTP_GET) - assert(code == 200, "register again: access /echo") - local new_ai = require("apisix.plugins.ai") - assert(router.router_http.matching == new_ai.route_matching, "enable(after require): router_http.matching") - assert(apisix.handle_upstream == new_ai.handle_upstream, "enable(after require): handle_upstream") - assert(apisix.http_balancer_phase == new_ai.http_balancer_phase, "enable(after require): http_balancer_phase") + local code = t('/hello', ngx.HTTP_GET) + assert(code == 200) + + ngx.say("done") } } +--- response_body +done +--- grep_error_log eval +qr/route match mode: \S[^,]+/ +--- grep_error_log_out +route match mode: ai_match +route match mode: radixtree_uri +route match mode: radixtree_uri +route match mode: radixtree_uri +route match mode: ai_match +route match mode: radixtree_uri @@ -196,12 +194,6 @@ plugins: --- config location /t { content_by_lua_block { - local router = require("apisix.router") - local org_match = router.router_http.matching - local apisix = require("apisix") - local org_upstream = apisix.handle_upstream - local org_balancer_phase = apisix.http_balancer_phase - local t = require("lib.test_admin").test -- register route local code, body = t('/apisix/admin/routes/1', @@ -225,21 +217,13 @@ plugins: end local code = t('/hello', ngx.HTTP_GET) - assert(code == 200, "disable(default): access /hello") - assert(router.router_http.matching == org_match, "disable(default): router_http.matching") - assert(apisix.handle_upstream == org_upstream, "disable(default): handle_upstream") - assert(apisix.http_balancer_phase == org_balancer_phase, "disable(default): http_balancer_phase") + assert(code == 200) -- enable ai plugin - local code = load_ai_module() - assert(code == 200, "enable ai plugin") - ngx.sleep(2) + load_ai_module() + local code = t('/hello', ngx.HTTP_GET) - assert(code == 200, "enable: access /hello") - -- TODO: It's not very reasonable, we need to fix it - assert(router.router_http.matching == org_match, "enable: router_http.matching") - assert(apisix.handle_upstream == org_upstream, "enable: handle_upstream") - assert(apisix.http_balancer_phase == org_balancer_phase, "enable: http_balancer_phase") + assert(code == 200) -- register a new route and trigger a route tree rebuild local code, body = t('/apisix/admin/routes/2', @@ -262,21 +246,25 @@ plugins: return end - local code = t('/echo', ngx.HTTP_GET) - assert(code == 200, "register again: access /echo") - local ai = require("apisix.plugins.ai") - assert(router.router_http.matching == ai.route_matching, "enable(after require): router_http.matching") - assert(apisix.handle_upstream == ai.handle_upstream, "enable(after require): handle_upstream") - assert(apisix.http_balancer_phase == ai.http_balancer_phase, "enable(after require): http_balancer_phase") + local code = t('/hello', ngx.HTTP_GET) + assert(code == 200) -- disable ai plugin - local code = unload_ai_module() - assert(code == 200, "unload ai plugin") - ngx.sleep(2) + unload_ai_module() + local code = t('/hello', ngx.HTTP_GET) - assert(code == 200, "disable: access /hello") - assert(router.router_http.matching == org_match, "disable: router_http.matching") - assert(apisix.handle_upstream == org_upstream, "disable: handle_upstream") - assert(apisix.http_balancer_phase == org_balancer_phase, "disable: http_balancer_phase") + assert(code == 200) + + ngx.say("done") } } +--- response_body +done +--- grep_error_log eval +qr/route match mode: \S[^,]+/ +--- grep_error_log_out +route match mode: radixtree_uri +route match mode: radixtree_uri +route match mode: ai_match +route match mode: radixtree_uri +route match mode: radixtree_uri From c0c060206bf6b1bb10863a7e48498f9148b95870 Mon Sep 17 00:00:00 2001 From: soulbird Date: Wed, 2 Nov 2022 21:56:35 +0800 Subject: [PATCH 11/13] rename --- t/plugin/{ai3.t => ai4.t} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename t/plugin/{ai3.t => ai4.t} (100%) diff --git a/t/plugin/ai3.t b/t/plugin/ai4.t similarity index 100% rename from t/plugin/ai3.t rename to t/plugin/ai4.t From 726065099ad775d99766a146bc3579d4766238bb Mon Sep 17 00:00:00 2001 From: soulbird Date: Wed, 2 Nov 2022 21:59:47 +0800 Subject: [PATCH 12/13] fix lint --- t/plugin/ai4.t | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/t/plugin/ai4.t b/t/plugin/ai4.t index 76f15216ec9a..24282c4cbbfd 100644 --- a/t/plugin/ai4.t +++ b/t/plugin/ai4.t @@ -133,7 +133,7 @@ __DATA__ load_ai_module() -- TODO: The route cache should be enabled, but since no new routes are registered, - -- the route tree is not rebuilt, + -- the route tree is not rebuilt, -- so it is not possible to switch to route cache mode, we should fix it local code = t('/hello', ngx.HTTP_GET) assert(code == 200, "enable: access /hello") From bcd50539c7b8523d9208422f862565c9340365ee Mon Sep 17 00:00:00 2001 From: soulbird Date: Mon, 7 Nov 2022 10:42:11 +0800 Subject: [PATCH 13/13] rename --- t/plugin/{ai4.t => ai5.t} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename t/plugin/{ai4.t => ai5.t} (100%) diff --git a/t/plugin/ai4.t b/t/plugin/ai5.t similarity index 100% rename from t/plugin/ai4.t rename to t/plugin/ai5.t