summaryrefslogtreecommitdiff
path: root/tests
diff options
context:
space:
mode:
Diffstat (limited to 'tests')
-rw-r--r--tests/env/Dockerfile-elastic-mq.yaml4
-rw-r--r--tests/env/docker-compose.yaml74
-rw-r--r--tests/plugins/grpc/configs/.rr-grpc-init.yaml58
-rw-r--r--tests/plugins/grpc/configs/external.proto19
-rw-r--r--tests/plugins/grpc/configs/test.pb.go291
-rw-r--r--tests/plugins/grpc/configs/test.proto33
-rw-r--r--tests/plugins/grpc/grpc_plugin_test.go89
-rw-r--r--tests/plugins/grpc/php_server/.rr.yaml22
-rw-r--r--tests/plugins/grpc/php_server/composer.json23
-rw-r--r--tests/plugins/grpc/php_server/server.crt15
-rw-r--r--tests/plugins/grpc/php_server/server.key9
-rw-r--r--tests/plugins/grpc/php_server/service.proto11
-rw-r--r--tests/plugins/grpc/php_server/src/EchoService.php17
-rw-r--r--tests/plugins/grpc/php_server/src/GPBMetadata/Service.php27
-rw-r--r--tests/plugins/grpc/php_server/src/Service/EchoInterface.php22
-rw-r--r--tests/plugins/grpc/php_server/src/Service/Message.php58
-rw-r--r--tests/plugins/grpc/php_server/worker-grpc.php26
-rw-r--r--tests/plugins/grpc/plugin_test.go178
-rw-r--r--tests/plugins/grpc/testdata/import/Import/ServiceInterface.php32
-rw-r--r--tests/plugins/grpc/testdata/import/service.proto17
-rw-r--r--tests/plugins/grpc/testdata/import/sub/message.proto7
-rw-r--r--tests/plugins/grpc/testdata/import_custom/Test/CustomImport/ServiceInterface.php32
-rw-r--r--tests/plugins/grpc/testdata/import_custom/service.proto19
-rw-r--r--tests/plugins/grpc/testdata/import_custom/sub/message.proto14
-rw-r--r--tests/plugins/grpc/testdata/php_namespace/Test/CustomNamespace/ServiceInterface.php22
-rw-r--r--tests/plugins/grpc/testdata/php_namespace/service.proto15
-rw-r--r--tests/plugins/grpc/testdata/simple/TestSimple/SimpleServiceInterface.php22
-rw-r--r--tests/plugins/grpc/testdata/simple/simple.proto13
-rw-r--r--tests/plugins/grpc/testdata/use_empty/Test/ServiceInterface.php23
-rw-r--r--tests/plugins/grpc/testdata/use_empty/service.proto10
-rw-r--r--tests/plugins/jobs/jobs_with_toxics_test.go12
-rw-r--r--tests/plugins/logger/logger_test.go24
-rw-r--r--tests/plugins/websockets/websocket_plugin_test.go2
-rw-r--r--tests/psr-worker-bench.php2
-rwxr-xr-xtests/script.sh2
35 files changed, 1190 insertions, 54 deletions
diff --git a/tests/env/Dockerfile-elastic-mq.yaml b/tests/env/Dockerfile-elastic-mq.yaml
index e1513450..75d8a8ff 100644
--- a/tests/env/Dockerfile-elastic-mq.yaml
+++ b/tests/env/Dockerfile-elastic-mq.yaml
@@ -1,8 +1,8 @@
FROM openjdk:16
-ADD https://s3-eu-west-1.amazonaws.com/softwaremill-public/elasticmq-server-1.2.0.jar /
+ADD https://s3-eu-west-1.amazonaws.com/softwaremill-public/elasticmq-server-1.2.1.jar /
COPY custom.conf /
-ENTRYPOINT ["java", "-Dconfig.file=custom.conf", "-jar", "/elasticmq-server-1.2.0.jar"]
+ENTRYPOINT ["java", "-Dconfig.file=custom.conf", "-jar", "/elasticmq-server-1.2.1.jar"]
EXPOSE 9324
diff --git a/tests/env/docker-compose.yaml b/tests/env/docker-compose.yaml
index d93bc5af..8ef2a99b 100644
--- a/tests/env/docker-compose.yaml
+++ b/tests/env/docker-compose.yaml
@@ -1,44 +1,44 @@
-version: '3'
+version: "3"
services:
- memcached:
- image: memcached:latest
- ports:
- - "127.0.0.1:11211:11211"
- redis:
- image: redis:6
- ports:
- - "127.0.0.1:6379:6379"
- redis2:
- image: redis:6
- ports:
- - "127.0.0.1:6378:6379"
+ memcached:
+ image: memcached:latest
+ ports:
+ - "127.0.0.1:11211:11211"
+ redis:
+ image: redis:6
+ ports:
+ - "127.0.0.1:6379:6379"
+ redis2:
+ image: redis:6
+ ports:
+ - "127.0.0.1:6378:6379"
- toxicproxy:
- image: shopify/toxiproxy
- network_mode: "host"
+ toxicproxy:
+ image: ghcr.io/shopify/toxiproxy:latest
+ network_mode: host
- beanstalk:
- build:
- context: .
- dockerfile: Dockerfile-beanstalkd.yaml
- ports:
- - "127.0.0.1:11300:11300"
+ beanstalk:
+ build:
+ context: .
+ dockerfile: Dockerfile-beanstalkd.yaml
+ ports:
+ - "127.0.0.1:11300:11300"
- sqs:
- build:
- context: .
- dockerfile: Dockerfile-elastic-mq.yaml
- ports:
- - "127.0.0.1:9324:9324"
+ sqs:
+ build:
+ context: .
+ dockerfile: Dockerfile-elastic-mq.yaml
+ ports:
+ - "127.0.0.1:9324:9324"
- rabbitmq:
- image: rabbitmq:3-management
- ports:
- - "127.0.0.1:15672:15672"
- - "127.0.0.1:5672:5672"
+ rabbitmq:
+ image: rabbitmq:3-management
+ ports:
+ - "127.0.0.1:15672:15672"
+ - "127.0.0.1:5672:5672"
- prometheus:
- image: prom/prometheus
- ports:
- - "9090:9090"
+ prometheus:
+ image: prom/prometheus
+ ports:
+ - "9090:9090" \ No newline at end of file
diff --git a/tests/plugins/grpc/configs/.rr-grpc-init.yaml b/tests/plugins/grpc/configs/.rr-grpc-init.yaml
new file mode 100644
index 00000000..b743a766
--- /dev/null
+++ b/tests/plugins/grpc/configs/.rr-grpc-init.yaml
@@ -0,0 +1,58 @@
+rpc:
+ listen: "tcp://127.0.0.1:6001"
+
+server:
+ command: "php ../../psr-worker-bench.php"
+ relay: "pipes"
+ relay_timeout: "20s"
+
+# GRPC service configuration
+grpc:
+ # socket to listen
+ listen: "tcp://localhost:9001"
+
+ # proto root file
+ proto: "configs/test.proto"
+
+ # max send limit (MB)
+ max_send_msg_size: 50
+
+ # max receive limit (MB)
+ max_recv_msg_size: 50
+
+ # MaxConnectionIdle is a duration for the amount of time after which an
+ # idle connection would be closed by sending a GoAway. Idleness duration is
+ # defined since the most recent time the number of outstanding RPCs became
+ # zero or the connection establishment.
+ max_connection_idle: 0s
+
+ # MaxConnectionAge is a duration for the maximum amount of time a
+ # connection may exist before it will be closed by sending a GoAway. A
+ # random jitter of +/-10% will be added to MaxConnectionAge to spread out
+ # connection storms.
+ max_connection_age: 0s
+
+ # MaxConnectionAgeGrace is an additive period after MaxConnectionAge after
+ # which the connection will be forcibly closed.
+ max_connection_age_grace: 0s
+
+ # MaxConnectionAgeGrace is an additive period after MaxConnectionAge after
+ # which the connection will be forcibly closed.
+ max_concurrent_streams: 10
+
+ # After a duration of this time if the server doesn't see any activity it
+ # pings the client to see if the transport is still alive.
+ # If set below 1s, a minimum value of 1s will be used instead.
+ ping_time: 1s
+
+ # After having pinged for keepalive check, the server waits for a duration
+ # of Timeout and if no activity is seen even after that the connection is
+ # closed.
+ timeout: 200s
+
+ # Usual workers pool configuration
+ pool:
+ num_workers: 2
+ max_jobs: 0
+ allocate_timeout: 60s
+ destroy_timeout: 60
diff --git a/tests/plugins/grpc/configs/external.proto b/tests/plugins/grpc/configs/external.proto
new file mode 100644
index 00000000..2bbe806e
--- /dev/null
+++ b/tests/plugins/grpc/configs/external.proto
@@ -0,0 +1,19 @@
+syntax = "proto3";
+package tests;
+
+service External {
+ rpc Echo (Ping) returns (Pong) {
+ }
+
+ rpc Empty (EmptyMessage) returns (EmptyMessage) {
+
+ }
+}
+
+message Ping {
+ int64 value = 1;
+}
+
+message Pong {
+ int64 value = 1;
+} \ No newline at end of file
diff --git a/tests/plugins/grpc/configs/test.pb.go b/tests/plugins/grpc/configs/test.pb.go
new file mode 100644
index 00000000..5f30ceb6
--- /dev/null
+++ b/tests/plugins/grpc/configs/test.pb.go
@@ -0,0 +1,291 @@
+// Code generated by protoc-gen-go. DO NOT EDIT.
+// versions:
+// protoc-gen-go v1.27.1
+// protoc v3.17.3
+// source: test.proto
+
+package __
+
+import (
+ protoreflect "google.golang.org/protobuf/reflect/protoreflect"
+ protoimpl "google.golang.org/protobuf/runtime/protoimpl"
+ reflect "reflect"
+ sync "sync"
+)
+
+const (
+ // Verify that this generated code is sufficiently up-to-date.
+ _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
+ // Verify that runtime/protoimpl is sufficiently up-to-date.
+ _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
+)
+
+type Message struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+
+ Msg string `protobuf:"bytes,1,opt,name=msg,proto3" json:"msg,omitempty"`
+}
+
+func (x *Message) Reset() {
+ *x = Message{}
+ if protoimpl.UnsafeEnabled {
+ mi := &file_test_proto_msgTypes[0]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+ }
+}
+
+func (x *Message) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*Message) ProtoMessage() {}
+
+func (x *Message) ProtoReflect() protoreflect.Message {
+ mi := &file_test_proto_msgTypes[0]
+ if protoimpl.UnsafeEnabled && x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use Message.ProtoReflect.Descriptor instead.
+func (*Message) Descriptor() ([]byte, []int) {
+ return file_test_proto_rawDescGZIP(), []int{0}
+}
+
+func (x *Message) GetMsg() string {
+ if x != nil {
+ return x.Msg
+ }
+ return ""
+}
+
+type EmptyMessage struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+}
+
+func (x *EmptyMessage) Reset() {
+ *x = EmptyMessage{}
+ if protoimpl.UnsafeEnabled {
+ mi := &file_test_proto_msgTypes[1]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+ }
+}
+
+func (x *EmptyMessage) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*EmptyMessage) ProtoMessage() {}
+
+func (x *EmptyMessage) ProtoReflect() protoreflect.Message {
+ mi := &file_test_proto_msgTypes[1]
+ if protoimpl.UnsafeEnabled && x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use EmptyMessage.ProtoReflect.Descriptor instead.
+func (*EmptyMessage) Descriptor() ([]byte, []int) {
+ return file_test_proto_rawDescGZIP(), []int{1}
+}
+
+type DetailsMessageForException struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+
+ Code uint64 `protobuf:"varint,1,opt,name=code,proto3" json:"code,omitempty"`
+ Message string `protobuf:"bytes,2,opt,name=message,proto3" json:"message,omitempty"`
+}
+
+func (x *DetailsMessageForException) Reset() {
+ *x = DetailsMessageForException{}
+ if protoimpl.UnsafeEnabled {
+ mi := &file_test_proto_msgTypes[2]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+ }
+}
+
+func (x *DetailsMessageForException) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*DetailsMessageForException) ProtoMessage() {}
+
+func (x *DetailsMessageForException) ProtoReflect() protoreflect.Message {
+ mi := &file_test_proto_msgTypes[2]
+ if protoimpl.UnsafeEnabled && x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use DetailsMessageForException.ProtoReflect.Descriptor instead.
+func (*DetailsMessageForException) Descriptor() ([]byte, []int) {
+ return file_test_proto_rawDescGZIP(), []int{2}
+}
+
+func (x *DetailsMessageForException) GetCode() uint64 {
+ if x != nil {
+ return x.Code
+ }
+ return 0
+}
+
+func (x *DetailsMessageForException) GetMessage() string {
+ if x != nil {
+ return x.Message
+ }
+ return ""
+}
+
+var File_test_proto protoreflect.FileDescriptor
+
+var file_test_proto_rawDesc = []byte{
+ 0x0a, 0x0a, 0x74, 0x65, 0x73, 0x74, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x07, 0x73, 0x65,
+ 0x72, 0x76, 0x69, 0x63, 0x65, 0x22, 0x1b, 0x0a, 0x07, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65,
+ 0x12, 0x10, 0x0a, 0x03, 0x6d, 0x73, 0x67, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6d,
+ 0x73, 0x67, 0x22, 0x0e, 0x0a, 0x0c, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x4d, 0x65, 0x73, 0x73, 0x61,
+ 0x67, 0x65, 0x22, 0x4a, 0x0a, 0x1a, 0x44, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x73, 0x4d, 0x65, 0x73,
+ 0x73, 0x61, 0x67, 0x65, 0x46, 0x6f, 0x72, 0x45, 0x78, 0x63, 0x65, 0x70, 0x74, 0x69, 0x6f, 0x6e,
+ 0x12, 0x12, 0x0a, 0x04, 0x63, 0x6f, 0x64, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x04,
+ 0x63, 0x6f, 0x64, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x18,
+ 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x32, 0xf6,
+ 0x01, 0x0a, 0x04, 0x54, 0x65, 0x73, 0x74, 0x12, 0x2c, 0x0a, 0x04, 0x45, 0x63, 0x68, 0x6f, 0x12,
+ 0x10, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67,
+ 0x65, 0x1a, 0x10, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x4d, 0x65, 0x73, 0x73,
+ 0x61, 0x67, 0x65, 0x22, 0x00, 0x12, 0x2d, 0x0a, 0x05, 0x54, 0x68, 0x72, 0x6f, 0x77, 0x12, 0x10,
+ 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65,
+ 0x1a, 0x10, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x4d, 0x65, 0x73, 0x73, 0x61,
+ 0x67, 0x65, 0x22, 0x00, 0x12, 0x2b, 0x0a, 0x03, 0x44, 0x69, 0x65, 0x12, 0x10, 0x2e, 0x73, 0x65,
+ 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x1a, 0x10, 0x2e,
+ 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22,
+ 0x00, 0x12, 0x2c, 0x0a, 0x04, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x10, 0x2e, 0x73, 0x65, 0x72, 0x76,
+ 0x69, 0x63, 0x65, 0x2e, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x1a, 0x10, 0x2e, 0x73, 0x65,
+ 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0x00, 0x12,
+ 0x36, 0x0a, 0x04, 0x50, 0x69, 0x6e, 0x67, 0x12, 0x15, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63,
+ 0x65, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x1a, 0x15,
+ 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x4d, 0x65,
+ 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0x00, 0x42, 0x05, 0x5a, 0x03, 0x2e, 0x2f, 0x3b, 0x62, 0x06,
+ 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
+}
+
+var (
+ file_test_proto_rawDescOnce sync.Once
+ file_test_proto_rawDescData = file_test_proto_rawDesc
+)
+
+func file_test_proto_rawDescGZIP() []byte {
+ file_test_proto_rawDescOnce.Do(func() {
+ file_test_proto_rawDescData = protoimpl.X.CompressGZIP(file_test_proto_rawDescData)
+ })
+ return file_test_proto_rawDescData
+}
+
+var file_test_proto_msgTypes = make([]protoimpl.MessageInfo, 3)
+var file_test_proto_goTypes = []interface{}{
+ (*Message)(nil), // 0: service.Message
+ (*EmptyMessage)(nil), // 1: service.EmptyMessage
+ (*DetailsMessageForException)(nil), // 2: service.DetailsMessageForException
+}
+var file_test_proto_depIdxs = []int32{
+ 0, // 0: service.Test.Echo:input_type -> service.Message
+ 0, // 1: service.Test.Throw:input_type -> service.Message
+ 0, // 2: service.Test.Die:input_type -> service.Message
+ 0, // 3: service.Test.Info:input_type -> service.Message
+ 1, // 4: service.Test.Ping:input_type -> service.EmptyMessage
+ 0, // 5: service.Test.Echo:output_type -> service.Message
+ 0, // 6: service.Test.Throw:output_type -> service.Message
+ 0, // 7: service.Test.Die:output_type -> service.Message
+ 0, // 8: service.Test.Info:output_type -> service.Message
+ 1, // 9: service.Test.Ping:output_type -> service.EmptyMessage
+ 5, // [5:10] is the sub-list for method output_type
+ 0, // [0:5] is the sub-list for method input_type
+ 0, // [0:0] is the sub-list for extension type_name
+ 0, // [0:0] is the sub-list for extension extendee
+ 0, // [0:0] is the sub-list for field type_name
+}
+
+func init() { file_test_proto_init() }
+func file_test_proto_init() {
+ if File_test_proto != nil {
+ return
+ }
+ if !protoimpl.UnsafeEnabled {
+ file_test_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} {
+ switch v := v.(*Message); i {
+ case 0:
+ return &v.state
+ case 1:
+ return &v.sizeCache
+ case 2:
+ return &v.unknownFields
+ default:
+ return nil
+ }
+ }
+ file_test_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} {
+ switch v := v.(*EmptyMessage); i {
+ case 0:
+ return &v.state
+ case 1:
+ return &v.sizeCache
+ case 2:
+ return &v.unknownFields
+ default:
+ return nil
+ }
+ }
+ file_test_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} {
+ switch v := v.(*DetailsMessageForException); i {
+ case 0:
+ return &v.state
+ case 1:
+ return &v.sizeCache
+ case 2:
+ return &v.unknownFields
+ default:
+ return nil
+ }
+ }
+ }
+ type x struct{}
+ out := protoimpl.TypeBuilder{
+ File: protoimpl.DescBuilder{
+ GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
+ RawDescriptor: file_test_proto_rawDesc,
+ NumEnums: 0,
+ NumMessages: 3,
+ NumExtensions: 0,
+ NumServices: 1,
+ },
+ GoTypes: file_test_proto_goTypes,
+ DependencyIndexes: file_test_proto_depIdxs,
+ MessageInfos: file_test_proto_msgTypes,
+ }.Build()
+ File_test_proto = out.File
+ file_test_proto_rawDesc = nil
+ file_test_proto_goTypes = nil
+ file_test_proto_depIdxs = nil
+}
diff --git a/tests/plugins/grpc/configs/test.proto b/tests/plugins/grpc/configs/test.proto
new file mode 100644
index 00000000..2e1c90a9
--- /dev/null
+++ b/tests/plugins/grpc/configs/test.proto
@@ -0,0 +1,33 @@
+syntax = "proto3";
+
+package service;
+option go_package = "./;";
+
+service Test {
+ rpc Echo (Message) returns (Message) {
+ }
+
+ rpc Throw (Message) returns (Message) {
+ }
+
+ rpc Die (Message) returns (Message) {
+ }
+
+ rpc Info (Message) returns (Message) {
+ }
+
+ rpc Ping (EmptyMessage) returns (EmptyMessage) {
+ }
+}
+
+message Message {
+ string msg = 1;
+}
+
+message EmptyMessage {
+}
+
+message DetailsMessageForException {
+ uint64 code = 1;
+ string message = 2;
+} \ No newline at end of file
diff --git a/tests/plugins/grpc/grpc_plugin_test.go b/tests/plugins/grpc/grpc_plugin_test.go
new file mode 100644
index 00000000..b92282f7
--- /dev/null
+++ b/tests/plugins/grpc/grpc_plugin_test.go
@@ -0,0 +1,89 @@
+package grpc_test
+
+import (
+ "os"
+ "os/signal"
+ "sync"
+ "syscall"
+ "testing"
+ "time"
+
+ endure "github.com/spiral/endure/pkg/container"
+ "github.com/spiral/roadrunner/v2/plugins/config"
+ "github.com/spiral/roadrunner/v2/plugins/grpc"
+ "github.com/spiral/roadrunner/v2/plugins/informer"
+ "github.com/spiral/roadrunner/v2/plugins/logger"
+ "github.com/spiral/roadrunner/v2/plugins/resetter"
+ rpcPlugin "github.com/spiral/roadrunner/v2/plugins/rpc"
+ "github.com/spiral/roadrunner/v2/plugins/server"
+ "github.com/stretchr/testify/assert"
+)
+
+func TestGrpcInit(t *testing.T) {
+ cont, err := endure.NewContainer(nil, endure.SetLogLevel(endure.ErrorLevel))
+ assert.NoError(t, err)
+
+ cfg := &config.Viper{
+ Path: "configs/.rr-grpc-init.yaml",
+ Prefix: "rr",
+ }
+
+ err = cont.RegisterAll(
+ cfg,
+ &grpc.Plugin{},
+ &rpcPlugin.Plugin{},
+ &logger.ZapLogger{},
+ &server.Plugin{},
+ &informer.Plugin{},
+ &resetter.Plugin{},
+ )
+ assert.NoError(t, err)
+
+ err = cont.Init()
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ ch, err := cont.Serve()
+ assert.NoError(t, err)
+
+ sig := make(chan os.Signal, 1)
+ signal.Notify(sig, os.Interrupt, syscall.SIGINT, syscall.SIGTERM)
+
+ wg := &sync.WaitGroup{}
+ wg.Add(1)
+
+ stopCh := make(chan struct{}, 1)
+
+ go func() {
+ defer wg.Done()
+ for {
+ select {
+ case e := <-ch:
+ assert.Fail(t, "error", e.Error.Error())
+ err = cont.Stop()
+ if err != nil {
+ assert.FailNow(t, "error", err.Error())
+ }
+ case <-sig:
+ err = cont.Stop()
+ if err != nil {
+ assert.FailNow(t, "error", err.Error())
+ }
+ return
+ case <-stopCh:
+ // timeout
+ err = cont.Stop()
+ if err != nil {
+ assert.FailNow(t, "error", err.Error())
+ }
+ return
+ }
+ }
+ }()
+
+ time.Sleep(time.Second * 5)
+ stopCh <- struct{}{}
+
+ wg.Wait()
+}
diff --git a/tests/plugins/grpc/php_server/.rr.yaml b/tests/plugins/grpc/php_server/.rr.yaml
new file mode 100644
index 00000000..cc4a9300
--- /dev/null
+++ b/tests/plugins/grpc/php_server/.rr.yaml
@@ -0,0 +1,22 @@
+grpc:
+ listen: "tcp://:9001"
+ proto: "service.proto"
+ tls:
+ key: "server.key"
+ cert: "server.crt"
+ workers:
+ command: "php worker.php"
+ pool:
+ numWorkers: 4
+
+metrics:
+ address: localhost:2112
+
+limit:
+ interval: 1
+ services:
+ grpc:
+ maxMemory: 100
+ TTL: 0
+ idleTTL: 0
+ execTTL: 60 \ No newline at end of file
diff --git a/tests/plugins/grpc/php_server/composer.json b/tests/plugins/grpc/php_server/composer.json
new file mode 100644
index 00000000..b6303291
--- /dev/null
+++ b/tests/plugins/grpc/php_server/composer.json
@@ -0,0 +1,23 @@
+{
+ "name": "app/example-grpc-server",
+ "description": "Example GRPC Server",
+ "repositories": [
+ {
+ "type": "path",
+ "url": "../.."
+ }
+ ],
+ "require": {
+ "spiral/php-grpc": "*"
+ },
+ "require-dev": {
+ "grpc/grpc": "^1.36"
+ },
+ "autoload": {
+ "psr-4": {
+ "": "src"
+ }
+ },
+ "minimum-stability": "dev",
+ "prefer-stable": true
+}
diff --git a/tests/plugins/grpc/php_server/server.crt b/tests/plugins/grpc/php_server/server.crt
new file mode 100644
index 00000000..24d67fd7
--- /dev/null
+++ b/tests/plugins/grpc/php_server/server.crt
@@ -0,0 +1,15 @@
+-----BEGIN CERTIFICATE-----
+MIICTTCCAdOgAwIBAgIJAOKyUd+llTRKMAoGCCqGSM49BAMCMGMxCzAJBgNVBAYT
+AlVTMRMwEQYDVQQIDApDYWxpZm9ybmlhMRYwFAYDVQQHDA1TYW4gRnJhbmNpc2Nv
+MRMwEQYDVQQKDApSb2FkUnVubmVyMRIwEAYDVQQDDAlsb2NhbGhvc3QwHhcNMTgw
+OTMwMTMzNDUzWhcNMjgwOTI3MTMzNDUzWjBjMQswCQYDVQQGEwJVUzETMBEGA1UE
+CAwKQ2FsaWZvcm5pYTEWMBQGA1UEBwwNU2FuIEZyYW5jaXNjbzETMBEGA1UECgwK
+Um9hZFJ1bm5lcjESMBAGA1UEAwwJbG9jYWxob3N0MHYwEAYHKoZIzj0CAQYFK4EE
+ACIDYgAEVnbShsM+l5RR3wfWWmGhzuFGwNzKCk7i9xyobDIyBUxG/UUSfj7KKlUX
+puDnDEtF5xXcepl744CyIAYFLOXHb5WqI4jCOzG0o9f/00QQ4bQudJOdbqV910QF
+C2vb7Fxro1MwUTAdBgNVHQ4EFgQU9xUexnbB6ORKayA7Pfjzs33otsAwHwYDVR0j
+BBgwFoAU9xUexnbB6ORKayA7Pfjzs33otsAwDwYDVR0TAQH/BAUwAwEB/zAKBggq
+hkjOPQQDAgNoADBlAjEAue3HhR/MUhxoa9tSDBtOJT3FYbDQswrsdqBTz97CGKst
+e7XeZ3HMEvEXy0hGGEMhAjAqcD/4k9vViVppgWFtkk6+NFbm+Kw/QeeAiH5FgFSj
+8xQcb+b7nPwNLp3JOkXkVd4=
+-----END CERTIFICATE-----
diff --git a/tests/plugins/grpc/php_server/server.key b/tests/plugins/grpc/php_server/server.key
new file mode 100644
index 00000000..7501dd46
--- /dev/null
+++ b/tests/plugins/grpc/php_server/server.key
@@ -0,0 +1,9 @@
+-----BEGIN EC PARAMETERS-----
+BgUrgQQAIg==
+-----END EC PARAMETERS-----
+-----BEGIN EC PRIVATE KEY-----
+MIGkAgEBBDCQP8utxNbHR6xZOLAJgUhn88r6IrPqmN0MsgGJM/jePB+T9UhkmIU8
+PMm2HeScbcugBwYFK4EEACKhZANiAARWdtKGwz6XlFHfB9ZaYaHO4UbA3MoKTuL3
+HKhsMjIFTEb9RRJ+PsoqVRem4OcMS0XnFdx6mXvjgLIgBgUs5cdvlaojiMI7MbSj
+1//TRBDhtC50k51upX3XRAULa9vsXGs=
+-----END EC PRIVATE KEY-----
diff --git a/tests/plugins/grpc/php_server/service.proto b/tests/plugins/grpc/php_server/service.proto
new file mode 100644
index 00000000..60ff84a9
--- /dev/null
+++ b/tests/plugins/grpc/php_server/service.proto
@@ -0,0 +1,11 @@
+syntax = "proto3";
+package service;
+
+service Echo {
+ rpc Ping (Message) returns (Message) {
+ }
+}
+
+message Message {
+ string msg = 1;
+} \ No newline at end of file
diff --git a/tests/plugins/grpc/php_server/src/EchoService.php b/tests/plugins/grpc/php_server/src/EchoService.php
new file mode 100644
index 00000000..c2707811
--- /dev/null
+++ b/tests/plugins/grpc/php_server/src/EchoService.php
@@ -0,0 +1,17 @@
+<?php
+/**
+ * Sample GRPC PHP server.
+ */
+
+use Spiral\GRPC\ContextInterface;
+use Service\EchoInterface;
+use Service\Message;
+
+class EchoService implements EchoInterface
+{
+ public function Ping(ContextInterface $ctx, Message $in): Message
+ {
+ $out = new Message();
+ return $out->setMsg(strtoupper($in->getMsg()));
+ }
+} \ No newline at end of file
diff --git a/tests/plugins/grpc/php_server/src/GPBMetadata/Service.php b/tests/plugins/grpc/php_server/src/GPBMetadata/Service.php
new file mode 100644
index 00000000..c1b65b21
--- /dev/null
+++ b/tests/plugins/grpc/php_server/src/GPBMetadata/Service.php
@@ -0,0 +1,27 @@
+<?php
+# Generated by the protocol buffer compiler. DO NOT EDIT!
+# source: service.proto
+
+namespace GPBMetadata;
+
+class Service
+{
+ public static $is_initialized = false;
+
+ public static function initOnce() {
+ $pool = \Google\Protobuf\Internal\DescriptorPool::getGeneratedPool();
+
+ if (static::$is_initialized == true) {
+ return;
+ }
+ $pool->internalAddGeneratedFile(hex2bin(
+ "0a6e0a0d736572766963652e70726f746f12077365727669636522160a07" .
+ "4d657373616765120b0a036d736718012001280932340a044563686f122c" .
+ "0a0450696e6712102e736572766963652e4d6573736167651a102e736572" .
+ "766963652e4d6573736167652200620670726f746f33"
+ ));
+
+ static::$is_initialized = true;
+ }
+}
+
diff --git a/tests/plugins/grpc/php_server/src/Service/EchoInterface.php b/tests/plugins/grpc/php_server/src/Service/EchoInterface.php
new file mode 100644
index 00000000..5f336ace
--- /dev/null
+++ b/tests/plugins/grpc/php_server/src/Service/EchoInterface.php
@@ -0,0 +1,22 @@
+<?php
+# Generated by the protocol buffer compiler (spiral/grpc). DO NOT EDIT!
+# source: service.proto
+
+namespace Service;
+
+use Spiral\GRPC;
+
+interface EchoInterface extends GRPC\ServiceInterface
+{
+ // GRPC specific service name.
+ public const NAME = "service.Echo";
+
+ /**
+ * @param GRPC\ContextInterface $ctx
+ * @param Message $in
+ * @return Message
+ *
+ * @throws GRPC\Exception\InvokeException
+ */
+ public function Ping(GRPC\ContextInterface $ctx, Message $in): Message;
+}
diff --git a/tests/plugins/grpc/php_server/src/Service/Message.php b/tests/plugins/grpc/php_server/src/Service/Message.php
new file mode 100644
index 00000000..6c40c879
--- /dev/null
+++ b/tests/plugins/grpc/php_server/src/Service/Message.php
@@ -0,0 +1,58 @@
+<?php
+# Generated by the protocol buffer compiler. DO NOT EDIT!
+# source: service.proto
+
+namespace Service;
+
+use Google\Protobuf\Internal\GPBType;
+use Google\Protobuf\Internal\RepeatedField;
+use Google\Protobuf\Internal\GPBUtil;
+
+/**
+ * Generated from protobuf message <code>service.Message</code>
+ */
+class Message extends \Google\Protobuf\Internal\Message
+{
+ /**
+ * Generated from protobuf field <code>string msg = 1;</code>
+ */
+ private $msg = '';
+
+ /**
+ * Constructor.
+ *
+ * @param array $data {
+ * Optional. Data for populating the Message object.
+ *
+ * @type string $msg
+ * }
+ */
+ public function __construct($data = NULL) {
+ \GPBMetadata\Service::initOnce();
+ parent::__construct($data);
+ }
+
+ /**
+ * Generated from protobuf field <code>string msg = 1;</code>
+ * @return string
+ */
+ public function getMsg()
+ {
+ return $this->msg;
+ }
+
+ /**
+ * Generated from protobuf field <code>string msg = 1;</code>
+ * @param string $var
+ * @return $this
+ */
+ public function setMsg($var)
+ {
+ GPBUtil::checkString($var, True);
+ $this->msg = $var;
+
+ return $this;
+ }
+
+}
+
diff --git a/tests/plugins/grpc/php_server/worker-grpc.php b/tests/plugins/grpc/php_server/worker-grpc.php
new file mode 100644
index 00000000..683a2341
--- /dev/null
+++ b/tests/plugins/grpc/php_server/worker-grpc.php
@@ -0,0 +1,26 @@
+<?php
+/**
+ * Sample GRPC PHP server.
+ */
+
+use Service\EchoInterface;
+use Spiral\Goridge\StreamRelay;
+use Spiral\GRPC\Server;
+use Spiral\RoadRunner\Worker;
+
+require __DIR__ . '/vendor/autoload.php';
+
+$server = new Server(null, [
+ 'debug' => false, // optional (default: false)
+]);
+
+$server->registerService(EchoInterface::class, new EchoService());
+
+$worker = \method_exists(Worker::class, 'create')
+ // RoadRunner >= 2.x
+ ? Worker::create()
+ // RoadRunner 1.x
+ : new Worker(new StreamRelay(STDIN, STDOUT))
+;
+
+$server->serve($worker);
diff --git a/tests/plugins/grpc/plugin_test.go b/tests/plugins/grpc/plugin_test.go
new file mode 100644
index 00000000..cfbe0121
--- /dev/null
+++ b/tests/plugins/grpc/plugin_test.go
@@ -0,0 +1,178 @@
+package grpc
+
+import (
+ "io/ioutil"
+ "os"
+ "os/exec"
+ "strings"
+ "testing"
+
+ "github.com/stretchr/testify/assert"
+ "github.com/stretchr/testify/require"
+)
+
+func init() {
+ err := build()
+ if err != nil {
+ panic(err)
+ }
+}
+
+func build() error {
+ cmd := exec.Command("go", "build", "-o", "plugin", "../../../plugins/grpc/protoc_plugins/protoc-gen-php-grpc")
+ return cmd.Run()
+}
+
+func protoc(t *testing.T, args []string) {
+ cmd := exec.Command("protoc", "--plugin=protoc-gen-php-grpc=./plugin")
+ cmd.Args = append(cmd.Args, args...)
+ out, err := cmd.CombinedOutput()
+
+ if len(out) > 0 || err != nil {
+ t.Log("RUNNING: ", strings.Join(cmd.Args, " "))
+ }
+
+ if len(out) > 0 {
+ t.Log(string(out))
+ }
+
+ if err != nil {
+ t.Fatalf("protoc: %v", err)
+ }
+}
+
+func Test_Simple(t *testing.T) {
+ workdir, _ := os.Getwd()
+ tmpdir, err := ioutil.TempDir("", "proto-test")
+ require.NoError(t, err)
+
+ defer func() {
+ assert.NoError(t, os.RemoveAll(tmpdir))
+ }()
+
+ args := []string{
+ "-Itestdata",
+ "--php-grpc_out=" + tmpdir,
+ "simple/simple.proto",
+ }
+
+ protoc(t, args)
+
+ assertEqualFiles(
+ t,
+ workdir+"/testdata/simple/TestSimple/SimpleServiceInterface.php",
+ tmpdir+"/TestSimple/SimpleServiceInterface.php",
+ )
+}
+
+func Test_PhpNamespaceOption(t *testing.T) {
+ workdir, _ := os.Getwd()
+ tmpdir, err := ioutil.TempDir("", "proto-test")
+ require.NoError(t, err)
+
+ defer func() {
+ assert.NoError(t, os.RemoveAll(tmpdir))
+ }()
+
+ args := []string{
+ "-Itestdata",
+ "--php-grpc_out=" + tmpdir,
+ "php_namespace/service.proto",
+ }
+ protoc(t, args)
+
+ assertEqualFiles(
+ t,
+ workdir+"/testdata/php_namespace/Test/CustomNamespace/ServiceInterface.php",
+ tmpdir+"/Test/CustomNamespace/ServiceInterface.php",
+ )
+}
+
+func Test_UseImportedMessage(t *testing.T) {
+ workdir, _ := os.Getwd()
+ tmpdir, err := ioutil.TempDir("", "proto-test")
+ require.NoError(t, err)
+
+ defer func() {
+ assert.NoError(t, os.RemoveAll(tmpdir))
+ }()
+
+ args := []string{
+ "-Itestdata",
+ "--php-grpc_out=" + tmpdir,
+ "import/service.proto",
+ }
+ protoc(t, args)
+
+ assertEqualFiles(
+ t,
+ workdir+"/testdata/import/Import/ServiceInterface.php",
+ tmpdir+"/Import/ServiceInterface.php",
+ )
+}
+
+func Test_PhpNamespaceOptionInUse(t *testing.T) {
+ workdir, _ := os.Getwd()
+ tmpdir, err := ioutil.TempDir("", "proto-test")
+ require.NoError(t, err)
+
+ defer func() {
+ assert.NoError(t, os.RemoveAll(tmpdir))
+ }()
+
+ args := []string{
+ "-Itestdata",
+ "--php-grpc_out=" + tmpdir,
+ "import_custom/service.proto",
+ }
+ protoc(t, args)
+
+ assertEqualFiles(
+ t,
+ workdir+"/testdata/import_custom/Test/CustomImport/ServiceInterface.php",
+ tmpdir+"/Test/CustomImport/ServiceInterface.php",
+ )
+}
+
+func Test_UseOfGoogleEmptyMessage(t *testing.T) {
+ workdir, _ := os.Getwd()
+ tmpdir, err := ioutil.TempDir("", "proto-test")
+ require.NoError(t, err)
+
+ defer func() {
+ assert.NoError(t, os.RemoveAll(tmpdir))
+ }()
+
+ args := []string{
+ "-Itestdata",
+ "--php-grpc_out=" + tmpdir,
+ "use_empty/service.proto",
+ }
+ protoc(t, args)
+
+ assertEqualFiles(
+ t,
+ workdir+"/testdata/use_empty/Test/ServiceInterface.php",
+ tmpdir+"/Test/ServiceInterface.php",
+ )
+
+ assert.NoError(t, os.RemoveAll("plugin"))
+}
+
+func assertEqualFiles(t *testing.T, original, generated string) {
+ assert.FileExists(t, generated)
+
+ originalData, err := ioutil.ReadFile(original)
+ if err != nil {
+ t.Fatal("Can't find original file for comparison")
+ }
+
+ generatedData, err := ioutil.ReadFile(generated)
+ if err != nil {
+ t.Fatal("Can't find generated file for comparison")
+ }
+
+ // every OS has a special boy
+ r := strings.NewReplacer("\r\n", "", "\n", "")
+ assert.Equal(t, r.Replace(string(originalData)), r.Replace(string(generatedData)))
+}
diff --git a/tests/plugins/grpc/testdata/import/Import/ServiceInterface.php b/tests/plugins/grpc/testdata/import/Import/ServiceInterface.php
new file mode 100644
index 00000000..13e58daf
--- /dev/null
+++ b/tests/plugins/grpc/testdata/import/Import/ServiceInterface.php
@@ -0,0 +1,32 @@
+<?php
+# Generated by the protocol buffer compiler (spiral/php-grpc). DO NOT EDIT!
+# source: import/service.proto
+
+namespace Import;
+
+use Spiral\GRPC;
+use Import\Sub;
+
+interface ServiceInterface extends GRPC\ServiceInterface
+{
+ // GRPC specific service name.
+ public const NAME = "import.Service";
+
+ /**
+ * @param GRPC\ContextInterface $ctx
+ * @param Message $in
+ * @return Message
+ *
+ * @throws GRPC\Exception\InvokeException
+ */
+ public function SimpleMethod(GRPC\ContextInterface $ctx, Message $in): Message;
+
+ /**
+ * @param GRPC\ContextInterface $ctx
+ * @param Sub\Message $in
+ * @return Sub\Message
+ *
+ * @throws GRPC\Exception\InvokeException
+ */
+ public function ImportMethod(GRPC\ContextInterface $ctx, Sub\Message $in): Sub\Message;
+}
diff --git a/tests/plugins/grpc/testdata/import/service.proto b/tests/plugins/grpc/testdata/import/service.proto
new file mode 100644
index 00000000..5d888f09
--- /dev/null
+++ b/tests/plugins/grpc/testdata/import/service.proto
@@ -0,0 +1,17 @@
+syntax = "proto3";
+
+package import;
+
+import "import/sub/message.proto";
+
+service Service {
+ rpc SimpleMethod (Message) returns (Message) {
+ }
+
+ rpc ImportMethod (import.sub.Message) returns (import.sub.Message) {
+ }
+}
+
+message Message {
+ int64 id = 1;
+} \ No newline at end of file
diff --git a/tests/plugins/grpc/testdata/import/sub/message.proto b/tests/plugins/grpc/testdata/import/sub/message.proto
new file mode 100644
index 00000000..1db0313b
--- /dev/null
+++ b/tests/plugins/grpc/testdata/import/sub/message.proto
@@ -0,0 +1,7 @@
+syntax = "proto3";
+
+package import.sub;
+
+message Message {
+ int64 id = 1;
+} \ No newline at end of file
diff --git a/tests/plugins/grpc/testdata/import_custom/Test/CustomImport/ServiceInterface.php b/tests/plugins/grpc/testdata/import_custom/Test/CustomImport/ServiceInterface.php
new file mode 100644
index 00000000..b010ce4f
--- /dev/null
+++ b/tests/plugins/grpc/testdata/import_custom/Test/CustomImport/ServiceInterface.php
@@ -0,0 +1,32 @@
+<?php
+# Generated by the protocol buffer compiler (spiral/php-grpc). DO NOT EDIT!
+# source: import_custom/service.proto
+
+namespace Test\CustomImport;
+
+use Spiral\GRPC;
+use Test\CustomImport\Message;
+
+interface ServiceInterface extends GRPC\ServiceInterface
+{
+ // GRPC specific service name.
+ public const NAME = "import.Service";
+
+ /**
+ * @param GRPC\ContextInterface $ctx
+ * @param Message $in
+ * @return Message
+ *
+ * @throws GRPC\Exception\InvokeException
+ */
+ public function SimpleMethod(GRPC\ContextInterface $ctx, Message $in): Message;
+
+ /**
+ * @param GRPC\ContextInterface $ctx
+ * @param Message\Message $in
+ * @return Message\Message
+ *
+ * @throws GRPC\Exception\InvokeException
+ */
+ public function ImportMethod(GRPC\ContextInterface $ctx, Message\Message $in): Message\Message;
+}
diff --git a/tests/plugins/grpc/testdata/import_custom/service.proto b/tests/plugins/grpc/testdata/import_custom/service.proto
new file mode 100644
index 00000000..872aaae3
--- /dev/null
+++ b/tests/plugins/grpc/testdata/import_custom/service.proto
@@ -0,0 +1,19 @@
+syntax = "proto3";
+
+package import;
+
+option php_namespace = "Test\\CustomImport";
+
+import "import_custom/sub/message.proto";
+
+service Service {
+ rpc SimpleMethod (Message) returns (Message) {
+ }
+
+ rpc ImportMethod (import.sub.Message) returns (import.sub.Message) {
+ }
+}
+
+message Message {
+ int64 id = 1;
+} \ No newline at end of file
diff --git a/tests/plugins/grpc/testdata/import_custom/sub/message.proto b/tests/plugins/grpc/testdata/import_custom/sub/message.proto
new file mode 100644
index 00000000..5d722ca3
--- /dev/null
+++ b/tests/plugins/grpc/testdata/import_custom/sub/message.proto
@@ -0,0 +1,14 @@
+syntax = "proto3";
+
+package import.sub;
+option php_namespace = "Test\\CustomImport\\Message";
+
+
+service Service {
+ rpc AnotherMethod (Message) returns (Message) {
+ }
+}
+
+message Message {
+ int64 id = 1;
+} \ No newline at end of file
diff --git a/tests/plugins/grpc/testdata/php_namespace/Test/CustomNamespace/ServiceInterface.php b/tests/plugins/grpc/testdata/php_namespace/Test/CustomNamespace/ServiceInterface.php
new file mode 100644
index 00000000..2090ba97
--- /dev/null
+++ b/tests/plugins/grpc/testdata/php_namespace/Test/CustomNamespace/ServiceInterface.php
@@ -0,0 +1,22 @@
+<?php
+# Generated by the protocol buffer compiler (spiral/php-grpc). DO NOT EDIT!
+# source: php_namespace/service.proto
+
+namespace Test\CustomNamespace;
+
+use Spiral\GRPC;
+
+interface ServiceInterface extends GRPC\ServiceInterface
+{
+ // GRPC specific service name.
+ public const NAME = "testPhpNamespace.Service";
+
+ /**
+ * @param GRPC\ContextInterface $ctx
+ * @param SimpleMessage $in
+ * @return SimpleMessage
+ *
+ * @throws GRPC\Exception\InvokeException
+ */
+ public function SimpleMethod(GRPC\ContextInterface $ctx, SimpleMessage $in): SimpleMessage;
+}
diff --git a/tests/plugins/grpc/testdata/php_namespace/service.proto b/tests/plugins/grpc/testdata/php_namespace/service.proto
new file mode 100644
index 00000000..a3bfa3c0
--- /dev/null
+++ b/tests/plugins/grpc/testdata/php_namespace/service.proto
@@ -0,0 +1,15 @@
+syntax = "proto3";
+
+package testPhpNamespace;
+
+option php_namespace = "Test\\CustomNamespace";
+
+service Service {
+ rpc SimpleMethod (SimpleMessage) returns (SimpleMessage) {
+ }
+}
+
+message SimpleMessage {
+ int32 id = 1;
+ string name = 2;
+} \ No newline at end of file
diff --git a/tests/plugins/grpc/testdata/simple/TestSimple/SimpleServiceInterface.php b/tests/plugins/grpc/testdata/simple/TestSimple/SimpleServiceInterface.php
new file mode 100644
index 00000000..f9e84bf7
--- /dev/null
+++ b/tests/plugins/grpc/testdata/simple/TestSimple/SimpleServiceInterface.php
@@ -0,0 +1,22 @@
+<?php
+# Generated by the protocol buffer compiler (spiral/php-grpc). DO NOT EDIT!
+# source: simple/simple.proto
+
+namespace TestSimple;
+
+use Spiral\GRPC;
+
+interface SimpleServiceInterface extends GRPC\ServiceInterface
+{
+ // GRPC specific service name.
+ public const NAME = "testSimple.SimpleService";
+
+ /**
+ * @param GRPC\ContextInterface $ctx
+ * @param SimpleMessage $in
+ * @return SimpleMessage
+ *
+ * @throws GRPC\Exception\InvokeException
+ */
+ public function SimpleMethod(GRPC\ContextInterface $ctx, SimpleMessage $in): SimpleMessage;
+}
diff --git a/tests/plugins/grpc/testdata/simple/simple.proto b/tests/plugins/grpc/testdata/simple/simple.proto
new file mode 100644
index 00000000..aca3c1d9
--- /dev/null
+++ b/tests/plugins/grpc/testdata/simple/simple.proto
@@ -0,0 +1,13 @@
+syntax = "proto3";
+
+package testSimple;
+
+service SimpleService {
+ rpc SimpleMethod (SimpleMessage) returns (SimpleMessage) {
+ }
+}
+
+message SimpleMessage {
+ int32 id = 1;
+ string name = 2;
+} \ No newline at end of file
diff --git a/tests/plugins/grpc/testdata/use_empty/Test/ServiceInterface.php b/tests/plugins/grpc/testdata/use_empty/Test/ServiceInterface.php
new file mode 100644
index 00000000..fe6d345a
--- /dev/null
+++ b/tests/plugins/grpc/testdata/use_empty/Test/ServiceInterface.php
@@ -0,0 +1,23 @@
+<?php
+# Generated by the protocol buffer compiler (spiral/php-grpc). DO NOT EDIT!
+# source: use_empty/service.proto
+
+namespace Test;
+
+use Spiral\GRPC;
+use Google\Protobuf;
+
+interface ServiceInterface extends GRPC\ServiceInterface
+{
+ // GRPC specific service name.
+ public const NAME = "test.Service";
+
+ /**
+ * @param GRPC\ContextInterface $ctx
+ * @param Protobuf\GPBEmpty $in
+ * @return Protobuf\GPBEmpty
+ *
+ * @throws GRPC\Exception\InvokeException
+ */
+ public function Test(GRPC\ContextInterface $ctx, Protobuf\GPBEmpty $in): Protobuf\GPBEmpty;
+}
diff --git a/tests/plugins/grpc/testdata/use_empty/service.proto b/tests/plugins/grpc/testdata/use_empty/service.proto
new file mode 100644
index 00000000..8c68d8d3
--- /dev/null
+++ b/tests/plugins/grpc/testdata/use_empty/service.proto
@@ -0,0 +1,10 @@
+syntax = "proto3";
+
+package test;
+
+import "google/protobuf/empty.proto";
+
+service Service {
+ rpc Test (google.protobuf.Empty) returns (google.protobuf.Empty) {
+ }
+} \ No newline at end of file
diff --git a/tests/plugins/jobs/jobs_with_toxics_test.go b/tests/plugins/jobs/jobs_with_toxics_test.go
index 80fed8eb..84fbec48 100644
--- a/tests/plugins/jobs/jobs_with_toxics_test.go
+++ b/tests/plugins/jobs/jobs_with_toxics_test.go
@@ -27,10 +27,18 @@ import (
func TestDurabilityAMQP(t *testing.T) {
client := toxiproxy.NewClient("127.0.0.1:8474")
+ proxies, err := client.Proxies()
+ require.NoError(t, err)
+
+ for p := range proxies {
+ _ = proxies[p].Delete()
+ }
- _, err := client.CreateProxy("redial", "127.0.0.1:23679", "127.0.0.1:5672")
+ proxy, err := client.CreateProxy("redial", "127.0.0.1:23679", "127.0.0.1:5672")
require.NoError(t, err)
- defer deleteProxy("redial", t)
+ defer func() {
+ _ = proxy.Delete()
+ }()
cont, err := endure.NewContainer(nil, endure.SetLogLevel(endure.ErrorLevel))
require.NoError(t, err)
diff --git a/tests/plugins/logger/logger_test.go b/tests/plugins/logger/logger_test.go
index 05ca2d53..e077f0bc 100644
--- a/tests/plugins/logger/logger_test.go
+++ b/tests/plugins/logger/logger_test.go
@@ -346,18 +346,6 @@ func TestFileLogger(t *testing.T) {
wg.Wait()
}
-func httpEcho(t *testing.T) {
- req, err := http.NewRequest(http.MethodGet, "http://127.0.0.1:54224?hello=world", nil)
- assert.NoError(t, err)
-
- r, err := http.DefaultClient.Do(req)
- assert.NoError(t, err)
- assert.Equal(t, http.StatusCreated, r.StatusCode)
-
- err = r.Body.Close()
- assert.NoError(t, err)
-}
-
func TestMarshalObjectLogging(t *testing.T) {
container, err := endure.NewContainer(nil, endure.RetryOnFail(true), endure.SetLogLevel(endure.ErrorLevel))
if err != nil {
@@ -428,3 +416,15 @@ func TestMarshalObjectLogging(t *testing.T) {
stopCh <- struct{}{}
wg.Wait()
}
+
+func httpEcho(t *testing.T) {
+ req, err := http.NewRequest(http.MethodGet, "http://127.0.0.1:54224?hello=world", nil)
+ assert.NoError(t, err)
+
+ r, err := http.DefaultClient.Do(req)
+ assert.NoError(t, err)
+ assert.Equal(t, http.StatusCreated, r.StatusCode)
+
+ err = r.Body.Close()
+ assert.NoError(t, err)
+}
diff --git a/tests/plugins/websockets/websocket_plugin_test.go b/tests/plugins/websockets/websocket_plugin_test.go
index bfdc980b..3e74ca59 100644
--- a/tests/plugins/websockets/websocket_plugin_test.go
+++ b/tests/plugins/websockets/websocket_plugin_test.go
@@ -660,7 +660,7 @@ func RPCWsPubAsync(port string) func(t *testing.T) {
}()
go func() {
- messagesToVerify := make([]string, 0, 10)
+ messagesToVerify := make([]string, 0, 4)
messagesToVerify = append(messagesToVerify, `{"topic":"@join","payload":["foo","foo2"]}`)
messagesToVerify = append(messagesToVerify, `{"topic":"foo","payload":"hello, PHP"}`)
messagesToVerify = append(messagesToVerify, `{"topic":"@leave","payload":["foo"]}`)
diff --git a/tests/psr-worker-bench.php b/tests/psr-worker-bench.php
index 80fc435c..e809f380 100644
--- a/tests/psr-worker-bench.php
+++ b/tests/psr-worker-bench.php
@@ -1,7 +1,9 @@
<?php
+
/**
* @var Goridge\RelayInterface $relay
*/
+
use Spiral\Goridge;
use Spiral\RoadRunner;
diff --git a/tests/script.sh b/tests/script.sh
new file mode 100755
index 00000000..746fb768
--- /dev/null
+++ b/tests/script.sh
@@ -0,0 +1,2 @@
+#!/usr/bin/env bash
+php ../../../tests/client.php echo pipes \ No newline at end of file