# # 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. # BEGIN { if ($ENV{TEST_NGINX_CHECK_LEAK}) { $SkipReason = "unavailable for the hup tests"; } else { $ENV{TEST_NGINX_USE_HUP} = 1; undef $ENV{TEST_NGINX_USE_STAP}; } } use t::APISIX 'no_plan'; repeat_each(1); no_long_string(); no_shuffle(); no_root_location(); log_level('debug'); run_tests; __DATA__ === TEST 1: set proto(id: 1) --- config location /t { content_by_lua_block { local t = require("lib.test_admin").test local etcd = require("apisix.core.etcd") local code, body = t('/apisix/admin/proto/1', ngx.HTTP_PUT, [[{ "content" : "syntax = \"proto3\"; package helloworld; service Greeter { rpc SayHello (HelloRequest) returns (HelloReply) {} } message HelloRequest { string name = 1; } message HelloReply { string message = 1; }" }]] ) if code >= 300 then ngx.status = code end ngx.say(body) local res = assert(etcd.get('/proto/1')) local create_time = res.body.node.value.create_time assert(create_time ~= nil, "create_time is nil") local update_time = res.body.node.value.update_time assert(update_time ~= nil, "update_time is nil") } } --- request GET /t --- response_body passed --- no_error_log [error] === TEST 2: set proto(id: 2) --- config location /t { content_by_lua_block { local t = require("lib.test_admin").test local code, body = t('/apisix/admin/proto/2', ngx.HTTP_PUT, [[{ "content" : "syntax = \"proto3\"; package helloworld; service Greeter { rpc SayHello (HelloRequest) returns (HelloReply) {} } message HelloRequest { string name = 1; } message HelloReply { string message = 1; }" }]] ) if code >= 300 then ngx.status = code end ngx.say(body) } } --- request GET /t --- response_body passed --- no_error_log [error] === TEST 3: delete proto(id: 2) --- config location /t { content_by_lua_block { local t = require("lib.test_admin").test local code, body = t('/apisix/admin/proto/2', ngx.HTTP_DELETE ) if code >= 300 then ngx.status = code end ngx.say(body) } } --- request GET /t --- response_body passed --- no_error_log [error] === TEST 4: set routes(id: 1) --- config location /t { content_by_lua_block { local t = require("lib.test_admin").test local code, body = t('/apisix/admin/routes/1', ngx.HTTP_PUT, [[{ "methods": ["GET", "POST"], "uri": "/grpctest", "plugins": { "grpc-transcode": { "proto_id": "1", "service": "helloworld.Greeter", "method": "SayHello" } }, "upstream": { "scheme": "grpc", "type": "roundrobin", "nodes": { "127.0.0.1:50051": 1 } } }]] ) if code >= 300 then ngx.status = code end ngx.say(body) } } --- request GET /t --- response_body passed --- no_error_log [error] === TEST 5: hit route --- request GET /grpctest?name=world --- response_body eval qr/\{"message":"Hello world"\}/ --- no_error_log [error] === TEST 6: hit route by post --- request POST /grpctest name=world --- response_body eval qr/\{"message":"Hello world"\}/ --- no_error_log [error] === TEST 7: hit route by post json --- request POST /grpctest {"name": "world"} --- more_headers Content-Type: application/json --- response_body eval qr/\{"message":"Hello world"\}/ --- no_error_log [error] === TEST 8: wrong upstream scheme --- config location /t { content_by_lua_block { local t = require("lib.test_admin").test local code, body = t('/apisix/admin/routes/1', ngx.HTTP_PUT, [[{ "methods": ["GET"], "uri": "/grpctest", "plugins": { "grpc-transcode": { "proto_id": "1", "service": "helloworld.Greeter", "method": "SayHello" } }, "upstream": { "scheme": "asf", "type": "roundrobin", "nodes": { "127.0.0.1:50051": 1 } } }]] ) if code >= 300 then ngx.status = code end ngx.say(body) } } --- request GET /t --- error_code: 400 --- no_error_log [error] === TEST 9: wrong upstream address --- config location /t { content_by_lua_block { local t = require("lib.test_admin").test local code, body = t('/apisix/admin/routes/1', ngx.HTTP_PUT, [[{ "methods": ["GET"], "uri": "/grpctest", "plugins": { "grpc-transcode": { "proto_id": "1", "service": "helloworld.Greeter", "method": "SayHello" } }, "upstream": { "scheme": "grpc", "type": "roundrobin", "nodes": { "127.0.0.1:1970": 1 } } }]] ) if code >= 300 then ngx.status = code end ngx.say(body) } } --- request GET /t --- response_body passed --- no_error_log [error] === TEST 10: hit route (Connection refused) --- request GET /grpctest --- response_body eval qr/502 Bad Gateway/ --- error_log Connection refused) while connecting to upstream --- error_code: 502 === TEST 11: update proto(id: 1) --- config location /t { content_by_lua_block { local t = require("lib.test_admin").test local code, body = t('/apisix/admin/proto/1', ngx.HTTP_PUT, [[{ "content" : "syntax = \"proto3\"; package helloworld; service Greeter { rpc SayHello (HelloRequest) returns (HelloReply) {} rpc Plus (PlusRequest) returns (PlusReply) {} rpc SayHelloAfterDelay (HelloRequest) returns (HelloReply) {} } message HelloRequest { string name = 1; } message HelloReply { string message = 1; } message PlusRequest { int64 a = 1; int64 b = 2; } message PlusReply { int64 result = 1; }" }]] ) if code >= 300 then ngx.status = code end ngx.say(body) } } --- request GET /t --- response_body passed --- no_error_log [error] === TEST 12: set routes(id: 2) --- config location /t { content_by_lua_block { local t = require("lib.test_admin").test local code, body = t('/apisix/admin/routes/2', ngx.HTTP_PUT, [[{ "methods": ["GET"], "uri": "/grpc_plus", "plugins": { "grpc-transcode": { "proto_id": "1", "service": "helloworld.Greeter", "method": "Plus", "pb_option":["int64_as_string", "enum_as_name"] } }, "upstream": { "scheme": "grpc", "type": "roundrobin", "nodes": { "127.0.0.1:50051": 1 } } }]] ) if code >= 300 then ngx.status = code end ngx.say(body) } } --- request GET /t --- response_body passed --- no_error_log [error] === TEST 13: hit route --- request GET /grpc_plus?a=1&b=2 --- response_body eval qr/\{"result":3\}/ --- no_error_log [error] === TEST 14: hit route --- request GET /grpc_plus?a=1&b=2251799813685260 --- response_body eval qr/\{"result":"#2251799813685261"\}/ --- no_error_log [error] === TEST 15: set route3 deadline nodelay --- config location /t { content_by_lua_block { local t = require("lib.test_admin").test local code, body = t('/apisix/admin/routes/3', ngx.HTTP_PUT, [[{ "methods": ["GET"], "uri": "/grpc_deadline", "plugins": { "grpc-transcode": { "proto_id": "1", "service": "helloworld.Greeter", "method": "SayHello", "deadline": 500 } }, "upstream": { "scheme": "grpc", "type": "roundrobin", "nodes": { "127.0.0.1:50051": 1 } } }]] ) if code >= 300 then ngx.status = code end ngx.say(body) } } --- request GET /t --- response_body passed --- no_error_log [error] === TEST 16: hit route --- request GET /grpc_deadline?name=apisix --- response_body eval qr/\{"message":"Hello apisix"\}/ --- no_error_log [error] === TEST 17: set route4 deadline delay --- config location /t { content_by_lua_block { local t = require("lib.test_admin").test local code, body = t('/apisix/admin/routes/4', ngx.HTTP_PUT, [[{ "methods": ["GET"], "uri": "/grpc_delay", "plugins": { "grpc-transcode": { "proto_id": "1", "service": "helloworld.Greeter", "method": "SayHelloAfterDelay", "deadline": 500 } }, "upstream": { "scheme": "grpc", "type": "roundrobin", "nodes": { "127.0.0.1:50051": 1 } } }]] ) if code >= 300 then ngx.status = code end ngx.say(body) } } --- request GET /t --- response_body passed --- no_error_log [error] === TEST 18: hit route --- request GET /grpc_delay?name=apisix --- error_code: 504 === TEST 19: set routes: missing method --- config location /t { content_by_lua_block { local t = require("lib.test_admin").test local code, body = t('/apisix/admin/routes/1', ngx.HTTP_PUT, [[{ "uri": "/grpctest", "plugins": { "grpc-transcode": { "proto_id": "1", "service": "helloworld.Greeter" } } }]] ) if code >= 300 then ngx.status = code end ngx.print(body) } } --- request GET /t --- error_code: 400 --- response_body {"error_msg":"failed to check the configuration of plugin grpc-transcode err: property \"method\" is required"} --- no_error_log [error] === TEST 20: set proto(id: 1, with array parameter) --- config location /t { content_by_lua_block { local t = require("lib.test_admin").test local code, body = t('/apisix/admin/proto/1', ngx.HTTP_PUT, [[{ "content" : "syntax = \"proto3\"; package helloworld; service Greeter { rpc SayHello (HelloRequest) returns (HelloReply) {} } message HelloRequest { string name = 1; repeated string items = 2; } message HelloReply { string message = 1; repeated string items = 2; }" }]] ) if code >= 300 then ngx.status = code end ngx.say(body) } } --- request GET /t --- response_body passed --- no_error_log [error] === TEST 21: set routes(id: 1, with array parameter) --- config location /t { content_by_lua_block { local t = require("lib.test_admin").test local code, body = t('/apisix/admin/routes/1', ngx.HTTP_PUT, [[{ "methods": ["GET", "POST"], "uri": "/grpctest", "service_protocol": "grpc", "plugins": { "grpc-transcode": { "proto_id": "1", "service": "helloworld.Greeter", "method": "SayHello" } }, "upstream": { "scheme": "grpc", "type": "roundrobin", "nodes": { "127.0.0.1:50051": 1 } } }]] ) if code >= 300 then ngx.status = code end ngx.say(body) } } --- request GET /t --- response_body passed --- no_error_log [error] === TEST 22: hit route --- config location /t { content_by_lua_block { local t = require("lib.test_admin").test local code, body = t('/grpctest', ngx.HTTP_POST, [[ {"name":"apisix", "items": ["a","b","c"]} ]], [[ {"message":"Hello apisix", "items": ["a","b","c"]} ]], {["Content-Type"] = "application/json"} ) ngx.status = code } } --- request GET /t --- no_error_log [error] === TEST 23: set proto with enum --- config location /t { content_by_lua_block { local t = require("lib.test_admin").test local code, body = t('/apisix/admin/proto/1', ngx.HTTP_PUT, [[{ "content" : "syntax = \"proto3\"; package helloworld; service Greeter { rpc SayHello (HelloRequest) returns (HelloReply) {} } enum Gender { GENDER_UNKNOWN = 0; GENDER_MALE = 1; GENDER_FEMALE = 2; } message HelloRequest { string name = 1; repeated string items = 2; Gender gender = 3; } message HelloReply { string message = 1; repeated string items = 2; Gender gender = 3; }" }]] ) if code >= 300 then ngx.status = code end ngx.say(body) } } --- request GET /t --- response_body passed --- no_error_log [error] === TEST 24: hit route, no gender --- request POST /grpctest {"name":"world"} --- more_headers Content-Type: application/json --- response_body eval qr/"gender":"GENDER_UNKNOWN"/ --- no_error_log [error] === TEST 25: hit route, gender is a value --- request POST /grpctest {"name":"world","gender":2} --- more_headers Content-Type: application/json --- response_body eval qr/"gender":"GENDER_FEMALE"/ --- no_error_log [error] === TEST 26: hit route, gender is a name --- request POST /grpctest {"name":"world","gender":"GENDER_MALE"} --- more_headers Content-Type: application/json --- response_body eval qr/"gender":"GENDER_MALE"/ --- no_error_log [error] === TEST 27: hit route, bad gender --- request POST /grpctest {"name":"world","gender":"GENDER_MA"} --- more_headers Content-Type: application/json --- error_code: 400 --- error_log failed to encode request data to protobuf === TEST 28: set routes(decode enum as value) --- config location /t { content_by_lua_block { local t = require("lib.test_admin").test local code, body = t('/apisix/admin/routes/1', ngx.HTTP_PUT, [[{ "methods": ["GET", "POST"], "uri": "/grpctest", "service_protocol": "grpc", "plugins": { "grpc-transcode": { "proto_id": "1", "service": "helloworld.Greeter", "method": "SayHello", "pb_option":["enum_as_value"] } }, "upstream": { "scheme": "grpc", "type": "roundrobin", "nodes": { "127.0.0.1:50051": 1 } } }]] ) if code >= 300 then ngx.status = code end ngx.say(body) } } --- request GET /t --- response_body passed --- no_error_log [error] === TEST 29: hit route --- request POST /grpctest {"name":"world","gender":2} --- more_headers Content-Type: application/json --- response_body eval qr/"gender":2/ --- no_error_log [error]