diff --git a/virtcontainers/clh.go b/virtcontainers/clh.go index 3e11da9217..53d60e777a 100644 --- a/virtcontainers/clh.go +++ b/virtcontainers/clh.go @@ -44,6 +44,11 @@ const ( clhReady ) +const ( + clhStateCreated = "Created" + clhStateRunning = "Running" +) + const ( // Values are mandatory by http API // Values based on: @@ -63,6 +68,19 @@ const ( maxClhVcpus = uint32(64) ) +// Interface that hides the implementation of openAPI client +// If the client changes its methods, this interface should do it as well, +// The main purpose is to hide the client in an interface to allow mock testing. +// This is an interface that has to match with OpenAPI CLH client +type clhClient interface { + VmmPingGet(ctx context.Context) (chclient.VmmPingResponse, *http.Response, error) + ShutdownVMM(ctx context.Context) (*http.Response, error) + CreateVM(ctx context.Context, vmConfig chclient.VmConfig) (*http.Response, error) + // No lint: golint suggest to rename to VMInfoGet. + VmInfoGet(ctx context.Context) (chclient.VmInfo, *http.Response, error) //nolint:golint + BootVM(ctx context.Context) (*http.Response, error) +} + type CloudHypervisorVersion struct { Major int Minor int @@ -91,7 +109,7 @@ type cloudHypervisor struct { store *store.VCStore config HypervisorConfig ctx context.Context - APIClient *chclient.DefaultApiService + APIClient clhClient version CloudHypervisorVersion vmconfig chclient.VmConfig cmdOutput bytes.Buffer @@ -927,7 +945,7 @@ func (clh *cloudHypervisor) isClhRunning(timeout uint) (bool, error) { } -func (clh *cloudHypervisor) client() *chclient.DefaultApiService { +func (clh *cloudHypervisor) client() clhClient { if clh.APIClient == nil { clh.APIClient = clh.newAPIClient() } @@ -996,7 +1014,7 @@ func (clh *cloudHypervisor) bootVM(ctx context.Context) error { clh.Logger().Debugf("VM state after create: %#v", info) - if info.State != "Created" { + if info.State != clhStateCreated { return fmt.Errorf("VM state is not 'Created' after 'CreateVM'") } @@ -1015,7 +1033,7 @@ func (clh *cloudHypervisor) bootVM(ctx context.Context) error { clh.Logger().Debugf("VM state after boot: %#v", info) - if info.State != "Running" { + if info.State != clhStateRunning { return fmt.Errorf("VM state is not 'Running' after 'BootVM'") } diff --git a/virtcontainers/clh_test.go b/virtcontainers/clh_test.go index edf6c5a2fa..9a7be249a0 100644 --- a/virtcontainers/clh_test.go +++ b/virtcontainers/clh_test.go @@ -6,10 +6,41 @@ package virtcontainers import ( - "github.com/stretchr/testify/assert" + "context" + "net/http" "testing" + + chclient "github.com/kata-containers/runtime/virtcontainers/pkg/cloud-hypervisor/client" + "github.com/stretchr/testify/assert" ) +type clhClientMock struct { + vmInfo chclient.VmInfo +} + +func (c *clhClientMock) VmmPingGet(ctx context.Context) (chclient.VmmPingResponse, *http.Response, error) { + return chclient.VmmPingResponse{}, nil, nil +} + +func (c *clhClientMock) ShutdownVMM(ctx context.Context) (*http.Response, error) { + return nil, nil +} + +func (c *clhClientMock) CreateVM(ctx context.Context, vmConfig chclient.VmConfig) (*http.Response, error) { + c.vmInfo.State = clhStateCreated + return nil, nil +} + +//nolint:golint +func (c *clhClientMock) VmInfoGet(ctx context.Context) (chclient.VmInfo, *http.Response, error) { + return c.vmInfo, nil, nil +} + +func (c *clhClientMock) BootVM(ctx context.Context) (*http.Response, error) { + c.vmInfo.State = clhStateRunning + return nil, nil +} + func TestCloudHypervisorAddVSock(t *testing.T) { assert := assert.New(t) clh := cloudHypervisor{} @@ -22,3 +53,12 @@ func TestCloudHypervisorAddVSock(t *testing.T) { assert.Equal(clh.vmconfig.Vsock[1].Cid, int64(2)) assert.Equal(clh.vmconfig.Vsock[1].Sock, "path2") } + +func TestCloudHypervisorBootVM(t *testing.T) { + clh := &cloudHypervisor{} + clh.APIClient = &clhClientMock{} + var ctx context.Context + if err := clh.bootVM(ctx); err != nil { + t.Errorf("cloudHypervisor.bootVM() error = %v", err) + } +}