Files
trivy/pkg/rpc/server/server_test.go
Teppei Fukuda 74717b888e feat: support client/server mode (#295)
* chore(app): change dir

* feat(rpc): add a proto file and auto-generated files

* chore(dep): add dependencies

* fix(app): fix import path

* fix(integration): fix import path

* fix(protoc): use enum for severity

* chore(Makefile): add fmt andd protoc

* chore(clang): add .clang-format

* refactor: split functions for client/server (#296)

* refactor(db): split db.Download

* refactor(standalone): create a different package

* refactor(vulnerability): split FillAndFilter

* fix(protoc): use enum for severity

* chore(Makefile): add fmt andd protoc

* chore(clang): add .clang-format

* fix(db): remove an unused variable

* fix(db): expose the github client as an argument of constructor

* refactor(vulnerability): add the detail message

* feat(rpc): add rpc client (#302)

* fix(protoc): use enum for severity

* chore(Makefile): add fmt andd protoc

* chore(clang): add .clang-format

* feat(rpc): convert types

* feat(rpc): add rpc client

* token: Refactor to handle bad headers being set

Signed-off-by: Simarpreet Singh <simar@linux.com>

* feat(rpc): add rpc server (#303)

* feat(rpc): add rpc server

* feat(utils): add CopyFile

* feat(server/config): add config struct

* feat(detector): add detector

* feat(scanner): delegate procedures to detector

* fix(scanner): fix the interface

* test(mock): add mocks

* test(rpc/server): add tests

* test(rpc/ospkg/server): add tests

* tets(os/detector): add tests

* refactor(library): move directories

* chore(dependency): add google/wire

* refactor(library): introduce google/wire

* refactor(ospkg/detector): move directory

* feat(rpc): add eosl

* refactor(ospkg): introduce google/wire

* refactor(wire): bind an interface

* refactor(client): use wire.Struct

* chore(Makefile): fix wire

* test(server): add AssertExpectations

* test(server): add AssertExpectations

* refactor(server): remove debug log

* refactor(error): add more context messages

* test(server): fix error message

* refactor(test): create a constructor of mock

* refactor(config): remove an unused variable

* test(config): add an assertion to test the config struct

* feat(client/server): add sub commands (#304)

* feat(rpc): add rpc server

* feat(utils): add CopyFile

* feat(server/config): add config struct

* feat(detector): add detector

* feat(scanner): delegate procedures to detector

* fix(scanner): fix the interface

* feat(client/server): add sub commands

* merge(server3)

* test(scan): remove an unused mock

* refactor(client): generate the constructor by wire

* fix(cli): change the default port

* fix(server): use auto-generated constructor

* feat(ospkg): return eosl

* test(integration): add integration tests for client/server (#306)

* fix(server): remove unnecessary options

* test(integration): add integration tests for client/server

* fix(server): wrap an error

* fix(server): change the update interval

* fix(server): display the error detail

* test(config): add an assertion to test the config struct

* fix(client): returns an error when failing to initizlie a logger

* test(ospkg/server): add eosl

* Squashed commit of the following:

* test(server): refactor and add tests (#307)

* test(github): create a mock

* test(db): create a mock

* test(server): add tests for DB hot update

* chore(db): add a log message

* refactor(db): introduce google/wire

* refactor(rpc): move directory

* refactor(injector): fix import name

* refactor(import): remove new lines

* fix(server): display the error detail

* fix(server): change the update interval

* fix(server): wrap an error

* test(integration): add integration tests for client/server

* fix(server): remove unnecessary options

* refactor(server): return an error when failing to initialize a logger

* refactor(server): remove unused error

* fix(client/server): fix default port

* chore(README): add client/server

* chore(README): update
2019-12-13 15:00:11 +02:00

158 lines
3.8 KiB
Go

package server
import (
"context"
"io/ioutil"
"os"
"path/filepath"
"sync"
"testing"
"time"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/mock"
"github.com/stretchr/testify/require"
"golang.org/x/xerrors"
"github.com/aquasecurity/trivy-db/pkg/db"
dbFile "github.com/aquasecurity/trivy/pkg/db"
"github.com/aquasecurity/trivy/pkg/log"
)
func TestMain(m *testing.M) {
log.InitLogger(false, false)
os.Exit(m.Run())
}
func Test_dbWorker_update(t *testing.T) {
type needsUpdateInput struct {
appVersion string
skip bool
}
type needsUpdateOutput struct {
needsUpdate bool
err error
}
type needsUpdate struct {
input needsUpdateInput
output needsUpdateOutput
}
type download struct {
call bool
err error
}
type args struct {
appVersion string
}
tests := []struct {
name string
needsUpdate needsUpdate
download download
args args
want db.Metadata
wantErr string
}{
{
name: "happy path",
needsUpdate: needsUpdate{
input: needsUpdateInput{appVersion: "1", skip: false},
output: needsUpdateOutput{needsUpdate: true},
},
download: download{
call: true,
},
args: args{appVersion: "1"},
want: db.Metadata{
Version: 1,
Type: db.TypeFull,
NextUpdate: time.Date(3000, 1, 1, 0, 0, 0, 0, time.UTC),
UpdatedAt: time.Date(3000, 1, 1, 0, 0, 0, 0, time.UTC),
},
},
{
name: "not update",
needsUpdate: needsUpdate{
input: needsUpdateInput{appVersion: "1", skip: false},
output: needsUpdateOutput{needsUpdate: false},
},
args: args{appVersion: "1"},
},
{
name: "NeedsUpdate returns an error",
needsUpdate: needsUpdate{
input: needsUpdateInput{appVersion: "1", skip: false},
output: needsUpdateOutput{err: xerrors.New("fail")},
},
args: args{appVersion: "1"},
wantErr: "failed to check if db needs an update",
},
{
name: "Download returns an error",
needsUpdate: needsUpdate{
input: needsUpdateInput{appVersion: "1", skip: false},
output: needsUpdateOutput{needsUpdate: true},
},
download: download{
call: true,
err: xerrors.New("fail"),
},
args: args{appVersion: "1"},
wantErr: "failed DB hot update",
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
cacheDir, err := ioutil.TempDir("", "server-test")
require.NoError(t, err, tt.name)
require.NoError(t, db.Init(cacheDir), tt.name)
mockDBClient := new(dbFile.MockClient)
mockDBClient.On("NeedsUpdate", mock.Anything,
tt.needsUpdate.input.appVersion, false, tt.needsUpdate.input.skip).Return(
tt.needsUpdate.output.needsUpdate, tt.needsUpdate.output.err)
if tt.download.call {
mockDBClient.On("Download", mock.Anything, mock.Anything, false).Run(
func(args mock.Arguments) {
// fake download: copy testdata/new.db to tmpDir/db/trivy.db
content, err := ioutil.ReadFile("testdata/new.db")
require.NoError(t, err, tt.name)
tmpDir := args.String(1)
dbPath := db.Path(tmpDir)
require.NoError(t, os.MkdirAll(filepath.Dir(dbPath), 0777), tt.name)
err = ioutil.WriteFile(dbPath, content, 0444)
require.NoError(t, err, tt.name)
}).Return(tt.download.err)
}
w := newDBWorker(mockDBClient)
var dbUpdateWg, requestWg sync.WaitGroup
err = w.update(context.Background(), tt.args.appVersion, cacheDir,
&dbUpdateWg, &requestWg)
if tt.wantErr != "" {
require.NotNil(t, err, tt.name)
assert.Contains(t, err.Error(), tt.wantErr, tt.name)
return
} else {
assert.NoError(t, err, tt.name)
}
if !tt.download.call {
return
}
dbc := db.Config{}
got, err := dbc.GetMetadata()
assert.NoError(t, err, tt.name)
assert.Equal(t, tt.want, got, tt.name)
mockDBClient.AssertExpectations(t)
})
}
}