// Copyright 2024 Matthew Rich . All rights reserved. package resource import ( "context" "decl/tests/mocks" _ "encoding/json" _ "fmt" "github.com/docker/docker/api/types" "github.com/docker/docker/api/types/container" "github.com/docker/docker/api/types/network" ocispec "github.com/opencontainers/image-spec/specs-go/v1" "github.com/stretchr/testify/assert" "io" _ "net/http" _ "net/http/httptest" _ "net/url" _ "os" "strings" "testing" "bytes" ) func TestNewContainerResource(t *testing.T) { c := NewContainer(&mocks.MockContainerClient{}) assert.NotEqual(t, nil, c) } func TestReadContainer(t *testing.T) { ctx := context.Background() decl := ` name: "testcontainer" image: "alpine" state: present ` m := &mocks.MockContainerClient{ InjectContainerList: func(ctx context.Context, options container.ListOptions) ([]types.Container, error) { return []types.Container{ {ID: "123456789abc"}, {ID: "123456789def"}, }, nil }, InjectContainerInspect: func(ctx context.Context, containerID string) (types.ContainerJSON, error) { return types.ContainerJSON{ ContainerJSONBase: &types.ContainerJSONBase{ ID: "123456789abc", Name: "test", Image: "alpine", }}, nil }, InjectContainerWait: func(ctx context.Context, containerID string, condition container.WaitCondition) (<-chan container.WaitResponse, <-chan error) { var res container.WaitResponse resChan := make(chan container.WaitResponse) errChan := make(chan error, 1) go func() { resChan <- res }() return resChan, errChan }, InjectContainerLogs: func(ctx context.Context, containerID string, options container.LogsOptions) (io.ReadCloser, error) { return io.NopCloser(strings.NewReader("done.")), nil }, } c := NewContainer(m) assert.NotEqual(t, nil, c) e := c.LoadDecl(decl) assert.Equal(t, nil, e) assert.Equal(t, "testcontainer", c.Name) resourceYaml, readContainerErr := c.Read(ctx) assert.Equal(t, nil, readContainerErr) assert.Greater(t, len(resourceYaml), 0) } func TestCreateContainer(t *testing.T) { m := &mocks.MockContainerClient{ InjectContainerCreate: func(ctx context.Context, config *container.Config, hostConfig *container.HostConfig, networkingConfig *network.NetworkingConfig, platform *ocispec.Platform, containerName string) (container.CreateResponse, error) { return container.CreateResponse{ID: "abcdef012", Warnings: []string{}}, nil }, InjectContainerStop: func(context.Context, string, container.StopOptions) error { return nil }, InjectContainerRemove: func(context.Context, string, container.RemoveOptions) error { return nil }, InjectContainerWait: func(ctx context.Context, containerID string, condition container.WaitCondition) (<-chan container.WaitResponse, <-chan error) { var res container.WaitResponse resChan := make(chan container.WaitResponse) errChan := make(chan error, 1) go func() { resChan <- res }() return resChan, errChan }, InjectContainerLogs: func(ctx context.Context, containerID string, options container.LogsOptions) (io.ReadCloser, error) { return io.NopCloser(strings.NewReader("done.")), nil }, } decl := ` name: "testcontainer" image: "alpine" state: present ` c := NewContainer(m) e := c.LoadDecl(decl) assert.Equal(t, nil, e) assert.Equal(t, "testcontainer", c.Name) applyErr := c.Apply() assert.Equal(t, nil, applyErr) c.State = "absent" applyDeleteErr := c.Apply() assert.Equal(t, nil, applyDeleteErr) } // Detect the ContainerLog header for each entry func TestContainerLogOutput(t *testing.T) { logHeader := []byte{0x01, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x05} logHeader = append(logHeader, []byte(string("done."))...) logs := bytes.NewReader(logHeader) m := &mocks.MockContainerClient{ InjectContainerCreate: func(ctx context.Context, config *container.Config, hostConfig *container.HostConfig, networkingConfig *network.NetworkingConfig, platform *ocispec.Platform, containerName string) (container.CreateResponse, error) { return container.CreateResponse{ID: "abcdef012", Warnings: []string{}}, nil }, InjectContainerStop: func(context.Context, string, container.StopOptions) error { return nil }, InjectContainerRemove: func(context.Context, string, container.RemoveOptions) error { return nil }, InjectContainerWait: func(ctx context.Context, containerID string, condition container.WaitCondition) (<-chan container.WaitResponse, <-chan error) { var res container.WaitResponse resChan := make(chan container.WaitResponse) errChan := make(chan error, 1) go func() { resChan <- res }() return resChan, errChan }, InjectContainerLogs: func(ctx context.Context, containerID string, options container.LogsOptions) (io.ReadCloser, error) { return io.NopCloser(logs), nil }, } c := NewContainer(m) c.ReadFromContainer(context.Background()) assert.Equal(t, "done.", c.Stdout) }