package alltransports

import (
	"testing"

	"github.com/containers/image/v5/directory"
	"github.com/containers/image/v5/transports"
	"github.com/stretchr/testify/assert"
	"github.com/stretchr/testify/require"
)

func TestParseImageName(t *testing.T) {
	// This primarily tests error handling, TestImageNameHandling is a table-driven
	// test for the expected values.
	for _, name := range []string{
		"",         // Empty
		"busybox",  // No transport name
		":busybox", // Empty transport name
		"docker:",  // Empty transport reference
	} {
		_, err := ParseImageName(name)
		assert.Error(t, err, name)
	}
}

// A table-driven test summarizing the various transports' behavior.
func TestImageNameHandling(t *testing.T) {
	// Always registered transports
	for _, c := range []struct{ transport, input, roundtrip string }{
		{"dir", "/etc", "/etc"},
		{"docker", "//busybox", "//busybox:latest"},
		{"docker", "//busybox:notlatest", "//busybox:notlatest"}, // This also tests handling of multiple ":" characters
		{"docker-archive", "/var/lib/oci/busybox.tar:busybox:latest", "/var/lib/oci/busybox.tar:docker.io/library/busybox:latest"},
		{"docker-archive", "busybox.tar:busybox:latest", "busybox.tar:docker.io/library/busybox:latest"},
		{"oci", "/etc:someimage", "/etc:someimage"},
		{"oci", "/etc:someimage:mytag", "/etc:someimage:mytag"},
		{"oci-archive", "/etc:someimage", "/etc:someimage"},
		{"oci-archive", "/etc:someimage:mytag", "/etc:someimage:mytag"},
		// "atomic" not tested here because it depends on per-user configuration for the default cluster.
		// "containers-storage" not tested here because it needs to initialize various directories on the fs.
	} {
		fullInput := c.transport + ":" + c.input
		ref, err := ParseImageName(fullInput)
		require.NoError(t, err, fullInput)
		s := transports.ImageName(ref)
		assert.Equal(t, c.transport+":"+c.roundtrip, s, fullInput)
	}

	// Possibly stubbed-out transports: Only verify that something is registered.
	for _, c := range []string{"docker-daemon", "ostree"} {
		transport := transports.Get(c)
		assert.NotNil(t, transport, c)
	}
}

func TestTransportFromImageName(t *testing.T) {
	dirTransport := TransportFromImageName("dir:/tmp/test")
	assert.Equal(t, dirTransport.Name(), directory.Transport.Name())
	unknownTransport := TransportFromImageName("unknown:ref:test")
	assert.Equal(t, unknownTransport, nil)
	invalidName := TransportFromImageName("unknown")
	assert.Equal(t, invalidName, nil)
}
