Hi All,

= TL;DR =

[1], [2] and [3] have now landed meaning if you have issues assigned to you to improve cc-runtime's unit-test coverage (you know who you are), you can now see how close you can get to 100% for the files you are working on :-)


= Details =

The runtime now has access to a mock implementation of virtcontainers for testing.

= Rationale =

We have introduced the test mock to allow for fine-grained unit testing at the runtime-level without duplicating test code (virtcontainers already has a lot of tests, plus the runtime exercises the virtcontainers API using other types of testing).

The reason the implementation is being hosted in the virtcontainers package is that certain virtcontainers types (Pod and Container) only contain private fields and since some of the virtcontainers API calls return these types, it is necessary to introduce interfaces to allow tests to override these types and fully implement the virtcontainers API.

= HOWTO =

The runtime has been updated so that rather than calling vc.API(), it now calls vci.API(). For example, this:

    vc.CreatePod()

... is now:

    vci.CreatePod()

vci is not a package alias, but a variable that defines the particular virtcontainers implementation that the runtime is using. In normal operation, that of course is the official implementation [4]. However, the runtime tests switch that variable to the VCMock implementation [5], meaning that all the runtime tests will use a fake version of virtcontainers. This is achieved as follows:

// official virtcontainer implementation
var virtcontainersImpl = &vc.VCImpl{}

// testingImpl is a mock virtcontainers implementation used for testing
var testingImpl = &vcMock.VCMock{}

// XXX: vci is a variable used to access a particular virtcontainers implementation.
// (The tests switch to the VCMock implementation by assigning "vci = testingImpl").
var vci vc.VC = virtcontainersImpl


By default (and assuming a virtcontainers API call actually returns a value), the VCMock implementation will return an error. This error will contain information about the call being made (method name and parameter details). You can (and should!) test if the error comes from the mock framework as appropriate using the helper function like this:

    assert = assert.New(t)
          :
          :
   assert.Error(err)
   assert.True(vcMock.IsMockError(err))

Or,

   assert.Error(err)
   assert.False(vcMock.IsMockError(err))

If you don't want a particular virtcontainers (mock) API call to return an error, define a handler. For example,

func TestFoo(t *testing.T) {

    testingImpl.CreatePodFunc = func(podConfig vc.PodConfig) (vc.VCPod, error) {
        vc.VCPod{}, nil
    }

    pod, err := vci.CreatePod(config) // calls function above now rather than returning a vcMock error.
}

There is a handler for all the virtcontainers API calls [6][7]. For examples of tests showing the different behaviour of the mock (either returning an error, or calling a handler), see [8].

= Helper functions =

I've also added a bunch of utility functions to make writing the remaining unit tests easier [9].


Any problems, just shout (or jump on #clearcontainers on freenode to chat).

Cheers,

James

[1] - https://github.com/containers/virtcontainers/pull/348
[2] - https://github.com/clearcontainers/runtime/pull/448
[3] - https://github.com/clearcontainers/runtime/pull/450
[4] - https://github.com/containers/virtcontainers/
[5] - https://github.com/containers/virtcontainers/tree/master/pkg/vcMock
[6] - https://github.com/containers/virtcontainers/blob/master/pkg/vcMock/mock.go
[7] - Note that the mock doesn't include the virtcontainers "oci" package. It's possible we'll need to add that later, but from what I can see, I don't think this will be necessary.
[8] - https://github.com/containers/virtcontainers/blob/master/pkg/vcMock/mock_test.go
[9] - https://github.com/clearcontainers/runtime/pull/452

-----
https://clearlinux.org
Open Source Technology Center
Intel Corporation (UK) Ltd. - Co. Reg. #1134945 - Pipers Way, Swindon SN3 1RJ.