package service // import "github.com/docker/docker/integration/service"

import (
	"context"
	"fmt"
	"testing"

	"github.com/docker/docker/api/types"
	"github.com/docker/docker/api/types/filters"
	swarmtypes "github.com/docker/docker/api/types/swarm"
	"github.com/docker/docker/api/types/versions"
	"github.com/docker/docker/integration/internal/swarm"
	"gotest.tools/v3/assert"
	is "gotest.tools/v3/assert/cmp"
	"gotest.tools/v3/poll"
	"gotest.tools/v3/skip"
)

// TestServiceListWithStatuses tests that performing a ServiceList operation
// correctly uses the Status parameter, and that the resulting response
// contains correct service statuses.
//
// NOTE(dperny): because it's a pain to elicit the behavior of an unconverged
// service reliably, I'm not testing that an unconverged service returns X
// running and Y desired tasks. Instead, I'm just going to trust that I can
// successfully assign a value to another value without screwing it up. The
// logic for computing service statuses is in swarmkit anyway, not in the
// engine, and is well-tested there, so this test just needs to make sure that
// statuses get correctly associated with the right services.
func TestServiceListWithStatuses(t *testing.T) {
	skip.If(t, testEnv.IsRemoteDaemon)
	skip.If(t, testEnv.DaemonInfo.OSType == "windows")
	// statuses were added in API version 1.41
	skip.If(t, versions.LessThan(testEnv.DaemonInfo.ServerVersion, "1.41"))
	defer setupTest(t)()
	d := swarm.NewSwarm(t, testEnv)
	defer d.Stop(t)
	client := d.NewClientT(t)
	defer client.Close()

	ctx := context.Background()

	serviceCount := 3
	// create some services.
	for i := 0; i < serviceCount; i++ {
		spec := fullSwarmServiceSpec(fmt.Sprintf("test-list-%d", i), uint64(i+1))
		// for whatever reason, the args "-u root", when included, cause these
		// tasks to fail and exit. instead, we'll just pass no args, which
		// works.
		spec.TaskTemplate.ContainerSpec.Args = []string{}
		resp, err := client.ServiceCreate(ctx, spec, types.ServiceCreateOptions{
			QueryRegistry: false,
		})
		assert.NilError(t, err)
		id := resp.ID
		// we need to wait specifically for the tasks to be running, which the
		// serviceContainerCount function does not do. instead, we'll use a
		// bespoke closure right here.
		poll.WaitOn(t, func(log poll.LogT) poll.Result {
			filter := filters.NewArgs()
			filter.Add("service", id)
			tasks, err := client.TaskList(context.Background(), types.TaskListOptions{
				Filters: filter,
			})

			running := 0
			for _, task := range tasks {
				if task.Status.State == swarmtypes.TaskStateRunning {
					running++
				}
			}

			switch {
			case err != nil:
				return poll.Error(err)
			case running == i+1:
				return poll.Success()
			default:
				return poll.Continue(
					"running task count %d (%d total), waiting for %d",
					running, len(tasks), i+1,
				)
			}
		})
	}

	// now, let's do the list operation with no status arg set.
	resp, err := client.ServiceList(ctx, types.ServiceListOptions{})
	assert.NilError(t, err)
	assert.Check(t, is.Len(resp, serviceCount))
	for _, service := range resp {
		assert.Check(t, is.Nil(service.ServiceStatus))
	}

	// now try again, but with Status: true. This time, we should have statuses
	resp, err = client.ServiceList(ctx, types.ServiceListOptions{Status: true})
	assert.NilError(t, err)
	assert.Check(t, is.Len(resp, serviceCount))
	for _, service := range resp {
		replicas := *service.Spec.Mode.Replicated.Replicas

		assert.Assert(t, service.ServiceStatus != nil)
		// Use assert.Check to not fail out of the test if this fails
		assert.Check(t, is.Equal(service.ServiceStatus.DesiredTasks, replicas))
		assert.Check(t, is.Equal(service.ServiceStatus.RunningTasks, replicas))
	}

}
