mirror of
https://github.com/containers/image.git
synced 2025-04-18 19:44:05 +03:00
187 lines
11 KiB
Go
187 lines
11 KiB
Go
//go:build !containers_image_storage_stub
|
|
|
|
package storage
|
|
|
|
import (
|
|
"fmt"
|
|
"testing"
|
|
|
|
"github.com/containers/image/v5/docker/reference"
|
|
"github.com/stretchr/testify/assert"
|
|
"github.com/stretchr/testify/require"
|
|
)
|
|
|
|
const (
|
|
sha256digestHex = "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef"
|
|
sha256Digest2 = "sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
|
|
)
|
|
|
|
func TestTransportName(t *testing.T) {
|
|
assert.Equal(t, "containers-storage", Transport.Name())
|
|
}
|
|
|
|
func TestTransportSetGetStore(t *testing.T) {
|
|
Transport.SetStore(nil)
|
|
res := Transport.GetStoreIfSet()
|
|
assert.Nil(t, res)
|
|
store := newStore(t) // Calls SetStore
|
|
res = Transport.GetStoreIfSet()
|
|
assert.Equal(t, store, res)
|
|
Transport.SetStore(nil)
|
|
}
|
|
|
|
func TestTransportParseStoreReference(t *testing.T) {
|
|
const digest3 = "sha256:bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb"
|
|
|
|
store := newStore(t)
|
|
|
|
Transport.SetStore(nil)
|
|
for _, c := range []struct{ input, expectedRef, expectedID string }{
|
|
{"", "", ""}, // Empty input
|
|
// Handling of the store prefix
|
|
// FIXME? Should we be silently discarding input like this?
|
|
{"[unterminated", "", ""}, // Unterminated store specifier
|
|
{"[garbage]busybox", "docker.io/library/busybox:latest", ""}, // Store specifier is overridden by the store we pass to ParseStoreReference
|
|
|
|
{"UPPERCASEISINVALID", "", ""}, // Invalid single-component name
|
|
{"sha256:" + sha256digestHex, "docker.io/library/sha256:" + sha256digestHex, ""}, // Valid single-component name; the hex part is not an ID unless it has a "@" prefix, so it looks like a tag
|
|
// FIXME: This test is now incorrect, this should not fail _if the image ID matches_
|
|
{sha256digestHex, "", ""}, // Invalid single-component ID; not an ID without a "@" prefix, so it's parsed as a name, but names aren't allowed to look like IDs
|
|
{"@" + sha256digestHex, "", sha256digestHex}, // Valid single-component ID
|
|
{"@sha256:" + sha256digestHex, "", ""}, // Invalid un-named @digest
|
|
// "aaaa", either a valid image ID prefix, or a short form of docker.io/library/aaaa, untested
|
|
{"sha256:ab", "docker.io/library/sha256:ab", ""}, // Valid single-component name, explicit tag
|
|
{"busybox", "docker.io/library/busybox:latest", ""}, // Valid single-component name, implicit tag
|
|
{"busybox:notlatest", "docker.io/library/busybox:notlatest", ""}, // Valid single-component name, explicit tag
|
|
{"docker.io/library/busybox:notlatest", "docker.io/library/busybox:notlatest", ""}, // Valid single-component name, everything explicit
|
|
|
|
{"UPPERCASEISINVALID@" + sha256digestHex, "", ""}, // Invalid name in name@digestOrID
|
|
{"busybox@ab", "", ""}, // Invalid ID in name@digestOrID
|
|
{"busybox@", "", ""}, // Empty ID in name@digestOrID
|
|
{"busybox@sha256:ab", "", ""}, // Invalid digest in name@digestOrID
|
|
{"busybox@sha256:" + sha256digestHex, "docker.io/library/busybox@sha256:" + sha256digestHex, ""}, // Valid name@digest, no tag
|
|
{"busybox@" + sha256digestHex, "docker.io/library/busybox:latest", sha256digestHex}, // Valid name@ID, implicit tag
|
|
// "busybox@aaaa", a valid image ID prefix, untested
|
|
{"busybox:notlatest@" + sha256digestHex, "docker.io/library/busybox:notlatest", sha256digestHex}, // Valid name@ID, explicit tag
|
|
{"docker.io/library/busybox:notlatest@" + sha256digestHex, "docker.io/library/busybox:notlatest", sha256digestHex}, // Valid name@ID, everything explicit
|
|
{"docker.io/library/busybox:notlatest@" + sha256Digest2, "docker.io/library/busybox:notlatest@" + sha256Digest2, ""}, // Valid name:tag@digest, everything explicit
|
|
|
|
{"busybox@sha256:" + sha256digestHex + "@ab", "", ""}, // Invalid ID in name@digest@ID
|
|
{"busybox@ab@" + sha256digestHex, "", ""}, // Invalid digest in name@digest@ID
|
|
{"busybox@@" + sha256digestHex, "", ""}, // Invalid digest in name@digest@ID
|
|
{"busybox@" + sha256Digest2 + "@" + sha256digestHex, "docker.io/library/busybox@" + sha256Digest2, sha256digestHex}, // name@digest@ID
|
|
{"docker.io/library/busybox@" + sha256Digest2 + "@" + sha256digestHex, "docker.io/library/busybox@" + sha256Digest2, sha256digestHex}, // name@digest@ID, everything explicit
|
|
{"docker.io/library/busybox:notlatest@sha256:" + sha256digestHex + "@" + sha256digestHex, "docker.io/library/busybox:notlatest@sha256:" + sha256digestHex, sha256digestHex}, // name:tag@digest@ID, everything explicit
|
|
// "busybox@sha256:"+sha256digestHex+"@aaaa", a valid image ID prefix, untested
|
|
{"busybox:notlatest@" + sha256Digest2 + "@" + digest3 + "@" + sha256digestHex, "", ""}, // name@digest@ID, with name containing another digest
|
|
} {
|
|
storageRef, err := Transport.ParseStoreReference(store, c.input)
|
|
if c.expectedRef == "" && c.expectedID == "" {
|
|
assert.Error(t, err, c.input)
|
|
} else {
|
|
require.NoError(t, err, c.input)
|
|
assert.Equal(t, store, storageRef.transport.store, c.input)
|
|
if c.expectedRef == "" {
|
|
assert.Nil(t, storageRef.named, c.input)
|
|
} else {
|
|
dockerRef, err := reference.ParseNormalizedNamed(c.expectedRef)
|
|
require.NoError(t, err)
|
|
require.NotNil(t, storageRef.named, c.input)
|
|
assert.Equal(t, dockerRef.String(), storageRef.named.String())
|
|
}
|
|
assert.Equal(t, c.expectedID, storageRef.id, c.input)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestTransportParseReference(t *testing.T) {
|
|
store := newStore(t)
|
|
driver := store.GraphDriverName()
|
|
root := store.GraphRoot()
|
|
|
|
for _, c := range []struct{ prefix, expectedDriver, expectedRoot, expectedRunRoot string }{
|
|
{"", driver, root, ""}, // Implicit store location prefix
|
|
{"[unterminated", "", "", ""}, // Unterminated store specifier
|
|
{"[]", "", "", ""}, // Empty store specifier
|
|
{"[relative/path]", "", "", ""}, // Non-absolute graph root path
|
|
{"[" + driver + "@relative/path]", "", "", ""}, // Non-absolute graph root path
|
|
{"[@" + root + "suffix2]", "", "", ""}, // Empty graph driver
|
|
{"[" + driver + "@]", "", "", ""}, // Empty root path
|
|
{"[thisisunknown@" + root + "suffix2]", "", "", ""}, // Unknown graph driver
|
|
{"[" + root + "suffix1]", "", "", ""}, // A valid root path, but no run dir
|
|
{"[" + driver + "@" + root + "suffix3+relative/path]", "", "", ""}, // Non-absolute run dir
|
|
{"[" + driver + "@" + root + "suffix3+" + root + "suffix4]",
|
|
driver,
|
|
root + "suffix3",
|
|
root + "suffix4"}, // A valid root@graph+run set
|
|
{"[" + driver + "@" + root + "suffix3+" + root + "suffix4:options,options,options]",
|
|
driver,
|
|
root + "suffix3",
|
|
root + "suffix4"}, // A valid root@graph+run+options set
|
|
} {
|
|
t.Logf("parsing %q", c.prefix+"busybox")
|
|
ref, err := Transport.ParseReference(c.prefix + "busybox")
|
|
if c.expectedDriver == "" {
|
|
assert.Error(t, err, c.prefix)
|
|
} else {
|
|
require.NoError(t, err, c.prefix)
|
|
storageRef, ok := ref.(*storageReference)
|
|
require.True(t, ok, c.prefix)
|
|
assert.Equal(t, c.expectedDriver, storageRef.transport.store.GraphDriverName(), c.prefix)
|
|
assert.Equal(t, c.expectedRoot, storageRef.transport.store.GraphRoot(), c.prefix)
|
|
if c.expectedRunRoot != "" {
|
|
assert.Equal(t, c.expectedRunRoot, storageRef.transport.store.RunRoot(), c.prefix)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestTransportValidatePolicyConfigurationScope(t *testing.T) {
|
|
store := newStore(t)
|
|
driver := store.GraphDriverName()
|
|
root := store.GraphRoot()
|
|
storeSpec := fmt.Sprintf("[%s@%s]", driver, root) // As computed in PolicyConfigurationNamespaces
|
|
|
|
// Valid inputs
|
|
for _, scope := range []string{
|
|
"[" + root + "suffix1]", // driverlessStoreSpec in PolicyConfigurationNamespaces
|
|
"[" + driver + "@" + root + "suffix3]", // storeSpec in PolicyConfigurationNamespaces
|
|
storeSpec + "@" + sha256digestHex, // ID only
|
|
storeSpec + "docker.io", // Host name only
|
|
storeSpec + "docker.io/library", // A repository namespace
|
|
storeSpec + "docker.io/library/busybox", // A repository name
|
|
storeSpec + "docker.io/library/busybox:notlatest", // name:tag
|
|
storeSpec + "docker.io/library/busybox:notlatest@" + sha256digestHex, // name@ID
|
|
storeSpec + "docker.io/library/busybox@" + sha256Digest2, // name@digest
|
|
storeSpec + "docker.io/library/busybox@" + sha256Digest2 + "@" + sha256digestHex, // name@digest@ID
|
|
storeSpec + "docker.io/library/busybox:notlatest@" + sha256Digest2, // name:tag@digest
|
|
storeSpec + "docker.io/library/busybox:notlatest@" + sha256Digest2 + "@" + sha256digestHex, // name:tag@digest@ID
|
|
} {
|
|
err := Transport.ValidatePolicyConfigurationScope(scope)
|
|
assert.NoError(t, err, scope)
|
|
}
|
|
|
|
// Invalid inputs
|
|
for _, scope := range []string{
|
|
"busybox", // Unprefixed reference
|
|
"[unterminated", // Unterminated store specifier
|
|
"[]", // Empty store specifier
|
|
"[relative/path]", // Non-absolute graph root path
|
|
"[" + driver + "@relative/path]", // Non-absolute graph root path
|
|
// "[thisisunknown@" + root + "suffix2]", // Unknown graph driver FIXME: validate against storage.ListGraphDrivers() once that's available
|
|
storeSpec + "@", // An incomplete two-component name
|
|
|
|
storeSpec + "docker.io/library/busybox@sha256:ab", // Invalid digest in name@digest
|
|
storeSpec + "docker.io/library/busybox@ab", // Invalid ID in name@ID
|
|
storeSpec + "docker.io/library/busybox@", // Empty ID/digest in name@ID
|
|
storeSpec + "docker.io/library/busybox@@" + sha256digestHex, // Empty digest in name@digest@ID
|
|
storeSpec + "docker.io/library/busybox@ab@" + sha256digestHex, // Invalid digest in name@digest@ID
|
|
storeSpec + "docker.io/library/busybox@sha256:ab@" + sha256digestHex, // Invalid digest in name@digest@ID
|
|
storeSpec + "docker.io/library/busybox@" + sha256Digest2 + "@", // Empty ID in name@digest@ID
|
|
storeSpec + "docker.io/library/busybox@" + sha256Digest2 + "@ab", // Invalid ID in name@digest@ID
|
|
} {
|
|
err := Transport.ValidatePolicyConfigurationScope(scope)
|
|
assert.Error(t, err, scope)
|
|
}
|
|
}
|