Skip to content

Commit

Permalink
test: server 包完善部分测试用例
Browse files Browse the repository at this point in the history
  • Loading branch information
kercylan98 committed Jan 15, 2024
1 parent 22449ff commit bbf70fa
Show file tree
Hide file tree
Showing 17 changed files with 387 additions and 102 deletions.
27 changes: 26 additions & 1 deletion server/network.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,22 @@ import (
"time"
)

// Network 服务器运行的网络模式
// - 根据不同的网络模式,服务器将会产生不同的行为,该类型将在服务器创建时候指定
//
// 服务器支持的网络模式如下:
// - NetworkNone 该模式下不监听任何网络端口,仅开启消息队列,适用于纯粹的跨服服务器等情况
// - NetworkTcp 该模式下将会监听 TCP 协议的所有地址,包括 IPv4 和 IPv6
// - NetworkTcp4 该模式下将会监听 TCP 协议的 IPv4 地址
// - NetworkTcp6 该模式下将会监听 TCP 协议的 IPv6 地址
// - NetworkUdp 该模式下将会监听 UDP 协议的所有地址,包括 IPv4 和 IPv6
// - NetworkUdp4 该模式下将会监听 UDP 协议的 IPv4 地址
// - NetworkUdp6 该模式下将会监听 UDP 协议的 IPv6 地址
// - NetworkUnix 该模式下将会监听 Unix 协议的地址
// - NetworkHttp 该模式下将会监听 HTTP 协议的地址
// - NetworkWebsocket 该模式下将会监听 Websocket 协议的地址
// - NetworkKcp 该模式下将会监听 KCP 协议的地址
// - NetworkGRPC 该模式下将会监听 GRPC 协议的地址
type Network string

const (
Expand Down Expand Up @@ -321,7 +337,16 @@ func (n Network) websocketMode(state chan<- error, srv *Server) {
}((&listener{srv: srv, Listener: l, state: state}).init(), mux)
}

// IsSocket 返回当前服务器的网络模式是否为 Socket 模式
// IsSocket 返回当前服务器的网络模式是否为 Socket 模式,目前为止仅有如下几种模式为 Socket 模式:
// - NetworkTcp
// - NetworkTcp4
// - NetworkTcp6
// - NetworkUdp
// - NetworkUdp4
// - NetworkUdp6
// - NetworkUnix
// - NetworkKcp
// - NetworkWebsocket
func (n Network) IsSocket() bool {
return collection.KeyInMap(socketNetworks, n)
}
51 changes: 51 additions & 0 deletions server/options_example_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
package server_test

import (
"fmt"
"github.com/kercylan98/minotaur/server"
"github.com/kercylan98/minotaur/utils/times"
"time"
)

// 服务器在启动时将阻塞 1s,模拟了慢消息的过程,这时候如果通过 RegMessageLowExecEvent 函数注册过慢消息事件,将会收到该事件的消息
// - 该示例中,将在收到慢消息时关闭服务器
func ExampleWithLowMessageDuration() {
srv := server.New(server.NetworkNone,
server.WithLowMessageDuration(time.Second),
)
srv.RegStartFinishEvent(func(srv *server.Server) {
time.Sleep(time.Second)
})
srv.RegMessageLowExecEvent(func(srv *server.Server, message *server.Message, cost time.Duration) {
srv.Shutdown()
fmt.Println(times.GetSecond(cost))
})
if err := srv.RunNone(); err != nil {
panic(err)
}
// Output:
// 1
}

// 服务器在启动时将发布一条阻塞 1s 的异步消息,模拟了慢消息的过程,这时候如果通过 RegMessageLowExecEvent 函数注册过慢消息事件,将会收到该事件的消息
// - 该示例中,将在收到慢消息时关闭服务器
func ExampleWithAsyncLowMessageDuration() {
srv := server.New(server.NetworkNone,
server.WithAsyncLowMessageDuration(time.Second),
)
srv.RegStartFinishEvent(func(srv *server.Server) {
srv.PushAsyncMessage(func() error {
time.Sleep(time.Second)
return nil
}, nil)
})
srv.RegMessageLowExecEvent(func(srv *server.Server, message *server.Message, cost time.Duration) {
srv.Shutdown()
fmt.Println(times.GetSecond(cost))
})
if err := srv.RunNone(); err != nil {
panic(err)
}
// Output:
// 1
}
109 changes: 109 additions & 0 deletions server/options_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
package server_test

import (
"fmt"
"github.com/kercylan98/minotaur/server"
"github.com/kercylan98/minotaur/utils/random"
"testing"
"time"
)

func TestWithLowMessageDuration(t *testing.T) {
var cases = []struct {
name string
duration time.Duration
}{
{name: "TestWithLowMessageDuration", duration: server.DefaultLowMessageDuration},
{name: "TestWithLowMessageDuration_Zero", duration: 0},
{name: "TestWithLowMessageDuration_Negative", duration: -server.DefaultAsyncLowMessageDuration},
}

for _, c := range cases {
c := c
t.Run(c.name, func(t *testing.T) {
networks := server.GetNetworks()
for i := 0; i < len(networks); i++ {
low := false
network := networks[i]
srv := server.New(network,
server.WithLowMessageDuration(c.duration),
)
srv.RegMessageLowExecEvent(func(srv *server.Server, message *server.Message, cost time.Duration) {
low = true
srv.Shutdown()
})
srv.RegStartFinishEvent(func(srv *server.Server) {
if c.duration <= 0 {
srv.Shutdown()
return
}
time.Sleep(server.DefaultLowMessageDuration)
})
var lis string
switch network {
case server.NetworkNone, server.NetworkUnix:
lis = "addr"
default:
lis = fmt.Sprintf(":%d", random.UsablePort())
}
if err := srv.Run(lis); err != nil {
t.Fatalf("%s run error: %s", network, err)
}
if !low && c.duration > 0 {
t.Fatalf("%s low message not exec", network)
}
}
})
}
}

func TestWithAsyncLowMessageDuration(t *testing.T) {
var cases = []struct {
name string
duration time.Duration
}{
{name: "TestWithAsyncLowMessageDuration", duration: time.Millisecond * 100},
{name: "TestWithAsyncLowMessageDuration_Zero", duration: 0},
{name: "TestWithAsyncLowMessageDuration_Negative", duration: -server.DefaultAsyncLowMessageDuration},
}

for _, c := range cases {
t.Run(c.name, func(t *testing.T) {
networks := server.GetNetworks()
for i := 0; i < len(networks); i++ {
low := false
network := networks[i]
srv := server.New(network,
server.WithAsyncLowMessageDuration(c.duration),
)
srv.RegMessageLowExecEvent(func(srv *server.Server, message *server.Message, cost time.Duration) {
low = true
srv.Shutdown()
})
srv.RegStartFinishEvent(func(srv *server.Server) {
if c.duration <= 0 {
srv.Shutdown()
return
}
srv.PushAsyncMessage(func() error {
time.Sleep(c.duration)
return nil
}, nil)
})
var lis string
switch network {
case server.NetworkNone, server.NetworkUnix:
lis = fmt.Sprintf("%s%d", "addr", random.Int(0, 9999))
default:
lis = fmt.Sprintf(":%d", random.UsablePort())
}
if err := srv.Run(lis); err != nil {
t.Fatalf("%s run error: %s", network, err)
}
if !low && c.duration > 0 {
t.Fatalf("%s low message not exec", network)
}
}
})
}
}
2 changes: 1 addition & 1 deletion server/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -149,7 +149,7 @@ func (srv *Server) Run(addr string) (err error) {
return nil
}

// IsSocket 是否是 Socket 模式
// IsSocket 通过执行 Network.IsSocket 函数检查该服务器是否是 Socket 模式
func (srv *Server) IsSocket() bool {
return srv.network.IsSocket()
}
Expand Down
41 changes: 32 additions & 9 deletions server/server_example_test.go
Original file line number Diff line number Diff line change
@@ -1,30 +1,53 @@
package server_test

import (
"fmt"
"github.com/kercylan98/minotaur/server"
"time"
)

// 该案例将创建一个简单的 WebSocket 服务器,如果需要更多的服务器类型可参考 [` Network `](#struct_Network) 部分
// - server.WithLimitLife(time.Millisecond) 通常不是在正常开发应该使用的,在这里只是为了让服务器在启动完成后的 1 毫秒后自动关闭
//
// 该案例的输出结果为 true
func ExampleNew() {
srv := server.New(server.NetworkWebsocket, server.WithLimitLife(time.Millisecond))
srv.RegConnectionReceivePacketEvent(func(srv *server.Server, conn *server.Conn, packet []byte) {
conn.Write(packet)
})
if err := srv.Run(":9999"); err != nil {
panic(err)
}
fmt.Println(srv != nil)
// Output:
// true
}

// 该案例将创建两个不同类型的服务器,其中 WebSocket 是一个 Socket 服务器,而 Http 是一个非 Socket 服务器
//
// 可知案例输出结果为:
// - true
// - false
func ExampleServer_IsSocket() {
srv1 := server.New(server.NetworkWebsocket)
fmt.Println(srv1.IsSocket())
srv2 := server.New(server.NetworkHttp)
fmt.Println(srv2.IsSocket())
// Output:
// true
// false
}

// 该案例将创建一个简单的 WebSocket 服务器并启动监听 `:9999/` 作为 WebSocket 监听地址,如果需要更多的服务器类型可参考 [` Network `](#struct_Network) 部分
// - 当服务器启动失败后,将会返回错误信息并触发 panic
// - server.WithLimitLife(time.Millisecond) 通常不是在正常开发应该使用的,在这里只是为了让服务器在启动完成后的 1 毫秒后自动关闭
func ExampleServer_Run() {
srv := server.New(server.NetworkWebsocket, server.WithLimitLife(time.Millisecond))
srv.RegConnectionReceivePacketEvent(func(srv *server.Server, conn *server.Conn, packet []byte) {
conn.Write(packet)
})
if err := srv.Run(":9999"); err != nil {
panic(err)
}
// Output:
}

// RunNone 函数并没有特殊的意义,该函数内部调用了 `srv.Run("")` 函数,仅是一个语法糖,用来表示服务器不需要监听任何地址
func ExampleServer_RunNone() {
srv := server.New(server.NetworkNone)
if err := srv.RunNone(); err != nil {
panic(err)
}
// Output:
}
Loading

0 comments on commit bbf70fa

Please sign in to comment.