aboutsummaryrefslogtreecommitdiffstats
path: root/pkg/rpcserver/rpcserver_test.go
diff options
context:
space:
mode:
authorSabyrzhan Tasbolatov <snovitoll@gmail.com>2024-09-04 21:33:28 +0500
committerAleksandr Nogikh <nogikh@google.com>2024-09-09 16:49:28 +0000
commitcb2d8b3aef0920cbb5521f948e262598efc3fc1c (patch)
treea5dd2e30ebaa63b2835fa6656e8e7078054829a0 /pkg/rpcserver/rpcserver_test.go
parent10df4c09063bf091d9d003880e4d1044b0ec163d (diff)
pkg/rpcserver: add unit tests, Manager mocks
Added more test coverage of the package and created an interface of rpcserver to use it as the dependency (for syz-manager). Also tried to cover with tests a private method handleConn(), though it calls handleRunnerConn which has a separate logic in Handshake(), which within handleConn() unit test we should've mocked. This will require a refactoring of `runners map[int]*Runner` and runner.go in general with a separate interface which we can mock as well. General idea is to have interfaces of Server (rpc), Runner etc. and mock a compound logic like Handshake during a separate public (or private if it has callable, if-else logic) method unit-testing.
Diffstat (limited to 'pkg/rpcserver/rpcserver_test.go')
-rw-r--r--pkg/rpcserver/rpcserver_test.go209
1 files changed, 209 insertions, 0 deletions
diff --git a/pkg/rpcserver/rpcserver_test.go b/pkg/rpcserver/rpcserver_test.go
new file mode 100644
index 000000000..3252ddd4f
--- /dev/null
+++ b/pkg/rpcserver/rpcserver_test.go
@@ -0,0 +1,209 @@
+// Copyright 2024 syzkaller project authors. All rights reserved.
+// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file.
+
+package rpcserver
+
+import (
+ "net"
+ "testing"
+
+ "github.com/stretchr/testify/assert"
+
+ "github.com/google/syzkaller/pkg/flatrpc"
+ "github.com/google/syzkaller/pkg/mgrconfig"
+ "github.com/google/syzkaller/pkg/rpcserver/mocks"
+ "github.com/google/syzkaller/prog"
+ "github.com/google/syzkaller/sys/targets"
+)
+
+func getTestDefaultCfg() mgrconfig.Config {
+ return mgrconfig.Config{
+ Type: targets.Linux,
+ Sandbox: "none",
+ Derived: mgrconfig.Derived{
+ TargetOS: targets.TestOS,
+ TargetArch: targets.TestArch64,
+ TargetVMArch: targets.TestArch64,
+ Timeouts: targets.Timeouts{Slowdown: 1},
+ },
+ }
+}
+
+func TestNew(t *testing.T) {
+ defaultCfg := getTestDefaultCfg()
+
+ nilServer := func(s Server) {
+ assert.Nil(t, s)
+ }
+
+ tests := []struct {
+ name string
+ modifyCfg func() *mgrconfig.Config
+ debug bool
+ expectedServCheck func(Server)
+ expectsErr bool
+ expectedErr error
+ }{
+ {
+ name: "unknown Sandbox",
+ modifyCfg: func() *mgrconfig.Config {
+ cfg := defaultCfg
+ cfg.Sandbox = "unknown"
+ return &cfg
+ },
+ expectedServCheck: nilServer,
+ expectsErr: true,
+ },
+ {
+ name: "experimental features",
+ modifyCfg: func() *mgrconfig.Config {
+ cfg := defaultCfg
+ cfg.Experimental = mgrconfig.Experimental{
+ RemoteCover: false,
+ CoverEdges: true,
+ }
+ return &cfg
+ },
+ expectedServCheck: func(srv Server) {
+ s := srv.(*server)
+ assert.Equal(t, s.cfg.Config.Features, flatrpc.AllFeatures&(^flatrpc.FeatureExtraCoverage))
+ assert.Nil(t, s.serv)
+ },
+ },
+ }
+
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ cfg := tt.modifyCfg()
+
+ var err error
+ cfg.Target, err = prog.GetTarget(cfg.TargetOS, cfg.TargetArch)
+ assert.NoError(t, err)
+
+ serv, err := New(cfg, nil, tt.debug)
+ if tt.expectedErr != nil {
+ assert.Equal(t, tt.expectedErr, err)
+ } else if tt.expectsErr {
+ assert.Error(t, err)
+ } else {
+ assert.Nil(t, err)
+ }
+ tt.expectedServCheck(serv)
+ })
+ }
+}
+
+func TestCheckRevisions(t *testing.T) {
+ tests := []struct {
+ name string
+ req *flatrpc.ConnectRequest
+ target *prog.Target
+ noError bool
+ }{
+ {
+ name: "error - different Arch",
+ req: &flatrpc.ConnectRequest{
+ Arch: "arch",
+ },
+ target: &prog.Target{
+ Arch: "arch2",
+ },
+ },
+ {
+ name: "error - different GitRevision",
+ req: &flatrpc.ConnectRequest{
+ Arch: "arch",
+ GitRevision: "different",
+ },
+ target: &prog.Target{
+ Arch: "arch",
+ },
+ },
+ {
+ name: "error - different SyzRevision",
+ req: &flatrpc.ConnectRequest{
+ Arch: "arch",
+ GitRevision: prog.GitRevision,
+ SyzRevision: "1",
+ },
+ target: &prog.Target{
+ Arch: "arch",
+ Revision: "2",
+ },
+ },
+ {
+ name: "ok",
+ req: &flatrpc.ConnectRequest{
+ Arch: "arch",
+ GitRevision: prog.GitRevision,
+ SyzRevision: "1",
+ },
+ target: &prog.Target{
+ Arch: "arch",
+ Revision: "1",
+ },
+ noError: true,
+ },
+ }
+
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ err := checkRevisions(tt.req, tt.target)
+ if tt.noError {
+ assert.NoError(t, err)
+ } else {
+ assert.Error(t, err)
+ }
+ })
+ }
+}
+
+func TestHandleConn(t *testing.T) {
+ inConn, outConn := net.Pipe()
+ serverConn := flatrpc.NewConn(inConn)
+ clientConn := flatrpc.NewConn(outConn)
+
+ managerMock := mocks.NewManager(t)
+ debug := false
+ defaultCfg := getTestDefaultCfg()
+
+ tests := []struct {
+ name string
+ modifyCfg func() *mgrconfig.Config
+ req *flatrpc.ConnectRequest
+ }{
+ {
+ name: "error, cfg.VMLess = false - unknown VM tries to connect",
+ modifyCfg: func() *mgrconfig.Config {
+ return &defaultCfg
+ },
+ req: &flatrpc.ConnectRequest{
+ Id: 2, // Valid Runner id is 1.
+ Arch: "64",
+ GitRevision: prog.GitRevision,
+ SyzRevision: "1",
+ },
+ },
+ }
+
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ cfg := tt.modifyCfg()
+
+ var err error
+ cfg.Target, err = prog.GetTarget(cfg.TargetOS, cfg.TargetArch)
+ cfg.Target.Revision = tt.req.SyzRevision
+ assert.NoError(t, err)
+
+ s, err := New(cfg, managerMock, debug)
+ assert.NoError(t, err)
+ serv := s.(*server)
+
+ injectExec := make(chan bool)
+ serv.CreateInstance(1, injectExec, nil)
+
+ go flatrpc.Send(clientConn, tt.req)
+ serv.handleConn(serverConn)
+ })
+ }
+}