Initial commit
This commit is contained in:
360
vendor/github.com/hyperhq/libcompose/config/validation_test.go
generated
vendored
Normal file
360
vendor/github.com/hyperhq/libcompose/config/validation_test.go
generated
vendored
Normal file
@@ -0,0 +1,360 @@
|
||||
package config
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func testValidSchema(t *testing.T, serviceMap RawServiceMap) {
|
||||
err := validate(serviceMap, "v1")
|
||||
assert.Nil(t, err)
|
||||
|
||||
for name, service := range serviceMap {
|
||||
err := validateServiceConstraints(service, name)
|
||||
assert.Nil(t, err)
|
||||
}
|
||||
}
|
||||
|
||||
func testInvalidSchema(t *testing.T, serviceMap RawServiceMap, errMsgs []string, errCount int) {
|
||||
var combinedErrMsg bytes.Buffer
|
||||
|
||||
err := validate(serviceMap, "v2")
|
||||
if err != nil {
|
||||
combinedErrMsg.WriteString(err.Error())
|
||||
combinedErrMsg.WriteRune('\n')
|
||||
}
|
||||
|
||||
for name, service := range serviceMap {
|
||||
err := validateServiceConstraints(service, name)
|
||||
if err != nil {
|
||||
combinedErrMsg.WriteString(err.Error())
|
||||
combinedErrMsg.WriteRune('\n')
|
||||
}
|
||||
}
|
||||
|
||||
for _, errMsg := range errMsgs {
|
||||
assert.True(t, strings.Contains(combinedErrMsg.String(), errMsg))
|
||||
}
|
||||
|
||||
// gojsonschema has bugs that can cause extraneous errors
|
||||
// This makes sure we don't have more errors than expected
|
||||
assert.True(t, strings.Count(combinedErrMsg.String(), "\n") == errCount)
|
||||
}
|
||||
|
||||
func TestInvalidServiceNames(t *testing.T) {
|
||||
invalidServiceNames := []string{"?not?allowed", " ", "", "!", "/"}
|
||||
|
||||
for _, invalidServiceName := range invalidServiceNames {
|
||||
testInvalidSchema(t, RawServiceMap{
|
||||
invalidServiceName: map[string]interface{}{
|
||||
"image": "busybox",
|
||||
},
|
||||
}, []string{fmt.Sprintf("Invalid service name '%s' - only [a-zA-Z0-9\\._\\-] characters are allowed", invalidServiceName)}, 1)
|
||||
}
|
||||
}
|
||||
|
||||
func TestValidServiceNames(t *testing.T) {
|
||||
validServiceNames := []string{"_", "-", ".__.", "_what-up.", "what_.up----", "whatup"}
|
||||
|
||||
for _, validServiceName := range validServiceNames {
|
||||
testValidSchema(t, RawServiceMap{
|
||||
validServiceName: map[string]interface{}{
|
||||
"image": "busybox",
|
||||
},
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
func TestConfigInvalidPorts(t *testing.T) {
|
||||
portsValues := []interface{}{
|
||||
map[string]interface{}{
|
||||
"1": "8000",
|
||||
},
|
||||
false,
|
||||
0,
|
||||
"8000",
|
||||
}
|
||||
|
||||
for _, portsValue := range portsValues {
|
||||
testInvalidSchema(t, RawServiceMap{
|
||||
"web": map[string]interface{}{
|
||||
"image": "busybox",
|
||||
"ports": portsValue,
|
||||
},
|
||||
}, []string{"Service 'web' configuration key 'ports' contains an invalid type, it should be an array"}, 1)
|
||||
}
|
||||
|
||||
testInvalidSchema(t, RawServiceMap{
|
||||
"web": map[string]interface{}{
|
||||
"image": "busybox",
|
||||
"ports": []interface{}{
|
||||
"8000",
|
||||
"8000",
|
||||
},
|
||||
},
|
||||
}, []string{"Service 'web' configuration key 'ports' value [8000 8000] has non-unique elements"}, 1)
|
||||
}
|
||||
*/
|
||||
|
||||
/*
|
||||
func TestConfigValidPorts(t *testing.T) {
|
||||
portsValues := []interface{}{
|
||||
[]interface{}{"8000", "9000"},
|
||||
[]interface{}{"8000"},
|
||||
[]interface{}{8000},
|
||||
[]interface{}{"127.0.0.1::8000"},
|
||||
[]interface{}{"49153-49154:3002-3003"},
|
||||
}
|
||||
|
||||
for _, portsValue := range portsValues {
|
||||
testValidSchema(t, RawServiceMap{
|
||||
"web": map[string]interface{}{
|
||||
"image": "busybox",
|
||||
"ports": portsValue,
|
||||
},
|
||||
})
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
func TestConfigHint(t *testing.T) {
|
||||
testInvalidSchema(t, RawServiceMap{
|
||||
"foo": map[string]interface{}{
|
||||
"image": "busybox",
|
||||
"privilege": "something",
|
||||
},
|
||||
}, []string{"Unsupported config option for foo service: 'privilege'"}, 1)
|
||||
}
|
||||
|
||||
func TestTypeShouldBeAnArray(t *testing.T) {
|
||||
testInvalidSchema(t, RawServiceMap{
|
||||
"foo": map[string]interface{}{
|
||||
"image": "busybox",
|
||||
"links": "an_link",
|
||||
},
|
||||
}, []string{"Service 'foo' configuration key 'links' contains an invalid type, it should be an array"}, 1)
|
||||
}
|
||||
|
||||
func TestInvalidTypeWithMultipleValidTypes(t *testing.T) {
|
||||
testInvalidSchema(t, RawServiceMap{
|
||||
"web": map[string]interface{}{
|
||||
"image": "busybox",
|
||||
"mem_limit": []interface{}{
|
||||
"array_elem",
|
||||
},
|
||||
},
|
||||
}, []string{"Unsupported config option for web service: 'mem_limit'"}, 1)
|
||||
}
|
||||
|
||||
func TestInvalidNotUniqueItems(t *testing.T) {
|
||||
// Test property with array as only valid type
|
||||
testInvalidSchema(t, RawServiceMap{
|
||||
"foo": map[string]interface{}{
|
||||
"image": "busybox",
|
||||
"devices": []string{
|
||||
"/dev/foo:/dev/foo",
|
||||
"/dev/foo:/dev/foo",
|
||||
},
|
||||
},
|
||||
}, []string{"Unsupported config option for foo service: 'devices'"}, 1)
|
||||
|
||||
// Test property with multiple valid types
|
||||
testInvalidSchema(t, RawServiceMap{
|
||||
"foo": map[string]interface{}{
|
||||
"image": "busybox",
|
||||
"environment": []string{
|
||||
"KEY=VAL",
|
||||
"KEY=VAL",
|
||||
},
|
||||
},
|
||||
}, []string{"Service 'foo' configuration key 'environment' contains non unique items, please remove duplicates from [KEY=VAL KEY=VAL]"}, 1)
|
||||
}
|
||||
|
||||
func TestInvalidListOfStringsFormat(t *testing.T) {
|
||||
testInvalidSchema(t, RawServiceMap{
|
||||
"web": map[string]interface{}{
|
||||
"image": "busybox",
|
||||
"command": []interface{}{
|
||||
1,
|
||||
},
|
||||
},
|
||||
}, []string{"Service 'web' configuration key 'command' contains 1, which is an invalid type, it should be a string"}, 1)
|
||||
}
|
||||
|
||||
func TestInvalidExtraHostsString(t *testing.T) {
|
||||
testInvalidSchema(t, RawServiceMap{
|
||||
"web": map[string]interface{}{
|
||||
"image": "busybox",
|
||||
"extra_hosts": "somehost:162.242.195.82",
|
||||
},
|
||||
}, []string{"Unsupported config option for web service: 'extra_hosts'"}, 1)
|
||||
}
|
||||
|
||||
/*
|
||||
func TestValidConfigWhichAllowsTwoTypeDefinitions(t *testing.T) {
|
||||
for _, exposeValue := range []interface{}{"8000", 9000} {
|
||||
testValidSchema(t, RawServiceMap{
|
||||
"web": map[string]interface{}{
|
||||
"image": "busybox",
|
||||
"expose": []interface{}{
|
||||
exposeValue,
|
||||
},
|
||||
},
|
||||
})
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
func TestValidConfigOneOfStringOrList(t *testing.T) {
|
||||
entrypointValues := []interface{}{
|
||||
[]interface{}{
|
||||
"sh",
|
||||
},
|
||||
"sh",
|
||||
}
|
||||
|
||||
for _, entrypointValue := range entrypointValues {
|
||||
testValidSchema(t, RawServiceMap{
|
||||
"web": map[string]interface{}{
|
||||
"image": "busybox",
|
||||
"entrypoint": entrypointValue,
|
||||
},
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestInvalidServiceProperty(t *testing.T) {
|
||||
testInvalidSchema(t, RawServiceMap{
|
||||
"web": map[string]interface{}{
|
||||
"image": "busybox",
|
||||
"invalid_property": "value",
|
||||
},
|
||||
}, []string{"Unsupported config option for web service: 'invalid_property'"}, 1)
|
||||
}
|
||||
|
||||
func TestServiceInvalidMissingImageAndBuild(t *testing.T) {
|
||||
testInvalidSchema(t, RawServiceMap{
|
||||
"web": map[string]interface{}{},
|
||||
}, []string{"Service 'web' has neither an image nor a build path specified. Exactly one must be provided."}, 1)
|
||||
}
|
||||
|
||||
func TestServiceInvalidSpecifiesImageAndBuild(t *testing.T) {
|
||||
testInvalidSchema(t, RawServiceMap{
|
||||
"web": map[string]interface{}{
|
||||
"image": "busybox",
|
||||
"build": ".",
|
||||
},
|
||||
}, []string{"Unsupported config option for web service: 'build'"}, 1)
|
||||
}
|
||||
|
||||
func TestServiceInvalidSpecifiesImageAndDockerfile(t *testing.T) {
|
||||
testInvalidSchema(t, RawServiceMap{
|
||||
"web": map[string]interface{}{
|
||||
"image": "busybox",
|
||||
"dockerfile": "Dockerfile",
|
||||
},
|
||||
}, []string{"Unsupported config option for web service: 'dockerfile'"}, 1)
|
||||
}
|
||||
|
||||
func TestInvalidServiceForMultipleErrors(t *testing.T) {
|
||||
testInvalidSchema(t, RawServiceMap{
|
||||
"foo": map[string]interface{}{
|
||||
"image": "busybox",
|
||||
// "ports": "invalid_type",
|
||||
"links": "an_type",
|
||||
"environment": []string{
|
||||
"KEY=VAL",
|
||||
"KEY=VAL",
|
||||
},
|
||||
},
|
||||
}, []string{
|
||||
// "Service 'foo' configuration key 'ports' contains an invalid type, it should be an array",
|
||||
"Service 'foo' configuration key 'links' contains an invalid type, it should be an array",
|
||||
"Service 'foo' configuration key 'environment' contains non unique items, please remove duplicates from [KEY=VAL KEY=VAL]",
|
||||
}, 2)
|
||||
}
|
||||
|
||||
func TestInvalidServiceWithAdditionalProperties(t *testing.T) {
|
||||
testInvalidSchema(t, RawServiceMap{
|
||||
"foo": map[string]interface{}{
|
||||
"image": "busybox",
|
||||
// "ports": "invalid_type",
|
||||
"---": "nope",
|
||||
"environment": []string{
|
||||
"KEY=VAL",
|
||||
"KEY=VAL",
|
||||
},
|
||||
},
|
||||
}, []string{
|
||||
// "Service 'foo' configuration key 'ports' contains an invalid type, it should be an array",
|
||||
"Unsupported config option for foo service: '---'",
|
||||
"Service 'foo' configuration key 'environment' contains non unique items, please remove duplicates from [KEY=VAL KEY=VAL]",
|
||||
}, 2)
|
||||
}
|
||||
|
||||
func TestMultipleInvalidServices(t *testing.T) {
|
||||
testInvalidSchema(t, RawServiceMap{
|
||||
"foo1": map[string]interface{}{
|
||||
"image": "busybox",
|
||||
// "ports": "invalid_type",
|
||||
},
|
||||
"foo2": map[string]interface{}{
|
||||
"image": "busybox",
|
||||
// "ports": "invalid_type",
|
||||
},
|
||||
}, []string{
|
||||
// "Service 'foo1' configuration key 'ports' contains an invalid type, it should be an array",
|
||||
// "Service 'foo2' configuration key 'ports' contains an invalid type, it should be an array",
|
||||
}, 0)
|
||||
}
|
||||
|
||||
func TestMixedInvalidServicesAndInvalidServiceNames(t *testing.T) {
|
||||
testInvalidSchema(t, RawServiceMap{
|
||||
//"foo1": map[string]interface{}{
|
||||
// "image": "busybox",
|
||||
// "ports": "invalid_type",
|
||||
// },
|
||||
"???": map[string]interface{}{
|
||||
"image": "busybox",
|
||||
},
|
||||
// "foo2": map[string]interface{}{
|
||||
// "image": "busybox",
|
||||
// "ports": "invalid_type",
|
||||
// },
|
||||
}, []string{
|
||||
// "Service 'foo1' configuration key 'ports' contains an invalid type, it should be an array",
|
||||
"Invalid service name '???' - only [a-zA-Z0-9\\._\\-] characters are allowed",
|
||||
// "Service 'foo2' configuration key 'ports' contains an invalid type, it should be an array",
|
||||
}, 1)
|
||||
}
|
||||
|
||||
func TestMultipleInvalidServicesForMultipleErrors(t *testing.T) {
|
||||
testInvalidSchema(t, RawServiceMap{
|
||||
"foo1": map[string]interface{}{
|
||||
"image": "busybox",
|
||||
// "ports": "invalid_type",
|
||||
"environment": []string{
|
||||
"KEY=VAL",
|
||||
"KEY=VAL",
|
||||
},
|
||||
},
|
||||
"foo2": map[string]interface{}{
|
||||
"image": "busybox",
|
||||
// "ports": "invalid_type",
|
||||
"environment": []string{
|
||||
"KEY=VAL",
|
||||
"KEY=VAL",
|
||||
},
|
||||
},
|
||||
}, []string{
|
||||
// "Service 'foo1' configuration key 'ports' contains an invalid type, it should be an array",
|
||||
"Service 'foo1' configuration key 'environment' contains non unique items, please remove duplicates from [KEY=VAL KEY=VAL]",
|
||||
// "Service 'foo2' configuration key 'ports' contains an invalid type, it should be an array",
|
||||
"Service 'foo2' configuration key 'environment' contains non unique items, please remove duplicates from [KEY=VAL KEY=VAL]",
|
||||
}, 2)
|
||||
}
|
||||
Reference in New Issue
Block a user