2018-02-05 21:05:59 +00:00
package opts // import "github.com/docker/docker/opts"
2013-12-02 22:33:33 +00:00
import (
2015-05-04 21:39:48 +00:00
"fmt"
2015-02-09 14:59:05 +00:00
"strings"
2013-12-02 22:33:33 +00:00
"testing"
2020-02-12 04:03:35 +00:00
"gotest.tools/v3/assert"
is "gotest.tools/v3/assert/cmp"
2013-12-02 22:33:33 +00:00
)
2014-07-09 21:47:55 +00:00
func TestValidateIPAddress ( t * testing . T ) {
if ret , err := ValidateIPAddress ( ` 1.2.3.4 ` ) ; err != nil || ret == "" {
t . Fatalf ( "ValidateIPAddress(`1.2.3.4`) got %s %s" , ret , err )
2013-12-02 22:33:33 +00:00
}
2014-07-09 21:47:55 +00:00
if ret , err := ValidateIPAddress ( ` 127.0.0.1 ` ) ; err != nil || ret == "" {
t . Fatalf ( "ValidateIPAddress(`127.0.0.1`) got %s %s" , ret , err )
2013-12-02 22:33:33 +00:00
}
2014-07-09 21:47:55 +00:00
if ret , err := ValidateIPAddress ( ` ::1 ` ) ; err != nil || ret == "" {
t . Fatalf ( "ValidateIPAddress(`::1`) got %s %s" , ret , err )
2013-12-02 22:33:33 +00:00
}
2014-07-09 21:47:55 +00:00
if ret , err := ValidateIPAddress ( ` 127 ` ) ; err == nil || ret != "" {
t . Fatalf ( "ValidateIPAddress(`127`) got %s %s" , ret , err )
2014-06-13 12:02:12 +00:00
}
2014-07-09 21:47:55 +00:00
if ret , err := ValidateIPAddress ( ` random invalid string ` ) ; err == nil || ret != "" {
t . Fatalf ( "ValidateIPAddress(`random invalid string`) got %s %s" , ret , err )
2013-12-02 22:33:33 +00:00
}
}
2014-02-07 16:48:14 +00:00
2015-05-04 21:39:48 +00:00
func TestMapOpts ( t * testing . T ) {
tmpMap := make ( map [ string ] string )
2015-05-05 04:18:28 +00:00
o := NewMapOpts ( tmpMap , logOptsValidator )
2015-05-04 21:39:48 +00:00
o . Set ( "max-size=1" )
if o . String ( ) != "map[max-size:1]" {
t . Errorf ( "%s != [map[max-size:1]" , o . String ( ) )
}
o . Set ( "max-file=2" )
if len ( tmpMap ) != 2 {
t . Errorf ( "map length %d != 2" , len ( tmpMap ) )
}
if tmpMap [ "max-file" ] != "2" {
t . Errorf ( "max-file = %s != 2" , tmpMap [ "max-file" ] )
}
if tmpMap [ "max-size" ] != "1" {
t . Errorf ( "max-size = %s != 1" , tmpMap [ "max-size" ] )
}
if o . Set ( "dummy-val=3" ) == nil {
2016-11-14 09:01:17 +00:00
t . Error ( "validator is not being called" )
2015-05-04 21:39:48 +00:00
}
}
2015-07-12 08:33:30 +00:00
func TestListOptsWithoutValidator ( t * testing . T ) {
2014-08-10 01:13:44 +00:00
o := NewListOpts ( nil )
o . Set ( "foo" )
2014-10-07 01:54:52 +00:00
if o . String ( ) != "[foo]" {
t . Errorf ( "%s != [foo]" , o . String ( ) )
}
o . Set ( "bar" )
if o . Len ( ) != 2 {
t . Errorf ( "%d != 2" , o . Len ( ) )
}
2015-07-12 08:33:30 +00:00
o . Set ( "bar" )
if o . Len ( ) != 3 {
t . Errorf ( "%d != 3" , o . Len ( ) )
}
2014-10-07 01:54:52 +00:00
if ! o . Get ( "bar" ) {
t . Error ( "o.Get(\"bar\") == false" )
}
if o . Get ( "baz" ) {
t . Error ( "o.Get(\"baz\") == true" )
}
o . Delete ( "foo" )
2015-07-12 08:33:30 +00:00
if o . String ( ) != "[bar bar]" {
t . Errorf ( "%s != [bar bar]" , o . String ( ) )
}
listOpts := o . GetAll ( )
if len ( listOpts ) != 2 || listOpts [ 0 ] != "bar" || listOpts [ 1 ] != "bar" {
t . Errorf ( "Expected [[bar bar]], got [%v]" , listOpts )
2014-10-07 01:54:52 +00:00
}
2015-07-12 08:33:30 +00:00
mapListOpts := o . GetMap ( )
if len ( mapListOpts ) != 1 {
t . Errorf ( "Expected [map[bar:{}]], got [%v]" , mapListOpts )
}
2014-08-10 01:13:44 +00:00
}
2015-07-12 08:33:30 +00:00
func TestListOptsWithValidator ( t * testing . T ) {
// Re-using logOptsvalidator (used by MapOpts)
o := NewListOpts ( logOptsValidator )
o . Set ( "foo" )
2017-03-31 01:35:04 +00:00
if o . String ( ) != "" {
t . Errorf ( ` %s != "" ` , o . String ( ) )
2015-07-12 08:33:30 +00:00
}
o . Set ( "foo=bar" )
2017-03-31 01:35:04 +00:00
if o . String ( ) != "" {
t . Errorf ( ` %s != "" ` , o . String ( ) )
2015-07-12 08:33:30 +00:00
}
o . Set ( "max-file=2" )
if o . Len ( ) != 1 {
t . Errorf ( "%d != 1" , o . Len ( ) )
}
if ! o . Get ( "max-file=2" ) {
t . Error ( "o.Get(\"max-file=2\") == false" )
}
if o . Get ( "baz" ) {
t . Error ( "o.Get(\"baz\") == true" )
}
o . Delete ( "max-file=2" )
2017-03-31 01:35:04 +00:00
if o . String ( ) != "" {
t . Errorf ( ` %s != "" ` , o . String ( ) )
2015-07-12 08:33:30 +00:00
}
}
func TestValidateDNSSearch ( t * testing . T ) {
2014-02-07 16:48:14 +00:00
valid := [ ] string {
2014-06-26 11:03:23 +00:00
` . ` ,
2014-02-07 16:48:14 +00:00
` a ` ,
` a. ` ,
` 1.foo ` ,
` 17.foo ` ,
` foo.bar ` ,
` foo.bar.baz ` ,
` foo.bar. ` ,
` foo.bar.baz ` ,
` foo1.bar2 ` ,
` foo1.bar2.baz ` ,
` 1foo.2bar. ` ,
` 1foo.2bar.baz ` ,
` foo-1.bar-2 ` ,
` foo-1.bar-2.baz ` ,
` foo-1.bar-2. ` ,
` foo-1.bar-2.baz ` ,
` 1-foo.2-bar ` ,
` 1-foo.2-bar.baz ` ,
` 1-foo.2-bar. ` ,
` 1-foo.2-bar.baz ` ,
}
invalid := [ ] string {
` ` ,
2014-06-26 11:03:23 +00:00
` ` ,
` ` ,
2014-02-07 16:48:14 +00:00
` 17 ` ,
` 17. ` ,
` .17 ` ,
` 17-. ` ,
` 17-.foo ` ,
` .foo ` ,
` foo-.bar ` ,
` -foo.bar ` ,
` foo.bar- ` ,
` foo.bar-.baz ` ,
` foo.-bar ` ,
` foo.-bar.baz ` ,
2017-05-21 23:24:07 +00:00
` foo.bar.baz.this.should.fail.on.long.name.because.it.is.longer.thanitshouldbethis.should.fail.on.long.name.because.it.is.longer.thanitshouldbethis.should.fail.on.long.name.because.it.is.longer.thanitshouldbethis.should.fail.on.long.name.because.it.is.longer.thanitshouldbe ` ,
2014-02-07 16:48:14 +00:00
}
for _ , domain := range valid {
2015-07-12 08:33:30 +00:00
if ret , err := ValidateDNSSearch ( domain ) ; err != nil || ret == "" {
t . Fatalf ( "ValidateDNSSearch(`" + domain + "`) got %s %s" , ret , err )
2014-02-07 16:48:14 +00:00
}
}
for _ , domain := range invalid {
2015-07-12 08:33:30 +00:00
if ret , err := ValidateDNSSearch ( domain ) ; err == nil || ret != "" {
t . Fatalf ( "ValidateDNSSearch(`" + domain + "`) got %s %s" , ret , err )
2014-02-07 16:48:14 +00:00
}
2015-07-12 08:33:30 +00:00
}
}
func TestValidateLabel ( t * testing . T ) {
2020-02-12 04:03:35 +00:00
testCases := [ ] struct {
name string
label string
expectedResult string
expectedErr string
} {
{
name : "lable with bad attribute format" ,
label : "label" ,
expectedErr : "bad attribute format: label" ,
} ,
{
name : "label with general format" ,
label : "key1=value1" ,
expectedResult : "key1=value1" ,
} ,
{
name : "label with more than one =" ,
label : "key1=value1=value2" ,
expectedResult : "key1=value1=value2" ,
} ,
{
name : "label with one more" ,
label : "key1=value1=value2=value3" ,
expectedResult : "key1=value1=value2=value3" ,
} ,
{
name : "label with no reserved com.docker.*" ,
label : "com.dockerpsychnotreserved.label=value" ,
expectedResult : "com.dockerpsychnotreserved.label=value" ,
} ,
{
name : "label with no reserved io.docker.*" ,
label : "io.dockerproject.not=reserved" ,
expectedResult : "io.dockerproject.not=reserved" ,
} ,
{
name : "label with no reserved org.dockerproject.*" ,
label : "org.docker.not=reserved" ,
expectedResult : "org.docker.not=reserved" ,
} ,
{
name : "label with reserved com.docker.*" ,
label : "com.docker.feature=enabled" ,
expectedErr : "label com.docker.feature=enabled is not allowed: the namespaces com.docker.*, io.docker.*, and org.dockerproject.* are reserved for internal use" ,
} ,
{
name : "label with reserved upcase com.docker.* " ,
label : "COM.docker.feature=enabled" ,
expectedErr : "label COM.docker.feature=enabled is not allowed: the namespaces com.docker.*, io.docker.*, and org.dockerproject.* are reserved for internal use" ,
} ,
{
name : "label with reserved io.docker.*" ,
label : "io.docker.configuration=0" ,
expectedErr : "label io.docker.configuration=0 is not allowed: the namespaces com.docker.*, io.docker.*, and org.dockerproject.* are reserved for internal use" ,
} ,
{
name : "label with reserved upcase io.docker.*" ,
label : "io.DOCKER.CONFIGURATion=0" ,
expectedErr : "label io.DOCKER.CONFIGURATion=0 is not allowed: the namespaces com.docker.*, io.docker.*, and org.dockerproject.* are reserved for internal use" ,
} ,
{
name : "label with reserved org.dockerproject.*" ,
label : "org.dockerproject.setting=on" ,
expectedErr : "label org.dockerproject.setting=on is not allowed: the namespaces com.docker.*, io.docker.*, and org.dockerproject.* are reserved for internal use" ,
} ,
{
name : "label with reserved upcase org.dockerproject.*" ,
label : "Org.Dockerproject.Setting=on" ,
expectedErr : "label Org.Dockerproject.Setting=on is not allowed: the namespaces com.docker.*, io.docker.*, and org.dockerproject.* are reserved for internal use" ,
} ,
2015-07-12 08:33:30 +00:00
}
2020-02-12 04:03:35 +00:00
for _ , testCase := range testCases {
testCase := testCase
t . Run ( testCase . name , func ( t * testing . T ) {
result , err := ValidateLabel ( testCase . label )
if testCase . expectedErr != "" {
assert . Error ( t , err , testCase . expectedErr )
} else {
assert . NilError ( t , err )
}
if testCase . expectedResult != "" {
assert . Check ( t , is . Equal ( result , testCase . expectedResult ) )
}
} )
2015-07-12 08:33:30 +00:00
}
}
2015-05-04 21:39:48 +00:00
func logOptsValidator ( val string ) ( string , error ) {
allowedKeys := map [ string ] string { "max-size" : "1" , "max-file" : "2" }
vals := strings . Split ( val , "=" )
if allowedKeys [ vals [ 0 ] ] != "" {
return val , nil
}
return "" , fmt . Errorf ( "invalid key %s" , vals [ 0 ] )
}
2015-12-10 23:35:10 +00:00
func TestNamedListOpts ( t * testing . T ) {
var v [ ] string
o := NewNamedListOptsRef ( "foo-name" , & v , nil )
o . Set ( "foo" )
if o . String ( ) != "[foo]" {
t . Errorf ( "%s != [foo]" , o . String ( ) )
}
if o . Name ( ) != "foo-name" {
t . Errorf ( "%s != foo-name" , o . Name ( ) )
}
if len ( v ) != 1 {
t . Errorf ( "expected foo to be in the values, got %v" , v )
}
}
func TestNamedMapOpts ( t * testing . T ) {
tmpMap := make ( map [ string ] string )
o := NewNamedMapOpts ( "max-name" , tmpMap , nil )
o . Set ( "max-size=1" )
if o . String ( ) != "map[max-size:1]" {
t . Errorf ( "%s != [map[max-size:1]" , o . String ( ) )
}
if o . Name ( ) != "max-name" {
t . Errorf ( "%s != max-name" , o . Name ( ) )
}
if _ , exist := tmpMap [ "max-size" ] ; ! exist {
t . Errorf ( "expected map-size to be in the values, got %v" , tmpMap )
}
}
2016-12-23 19:09:12 +00:00
func TestParseLink ( t * testing . T ) {
name , alias , err := ParseLink ( "name:alias" )
if err != nil {
t . Fatalf ( "Expected not to error out on a valid name:alias format but got: %v" , err )
}
if name != "name" {
t . Fatalf ( "Link name should have been name, got %s instead" , name )
}
if alias != "alias" {
t . Fatalf ( "Link alias should have been alias, got %s instead" , alias )
}
// short format definition
name , alias , err = ParseLink ( "name" )
if err != nil {
t . Fatalf ( "Expected not to error out on a valid name only format but got: %v" , err )
}
if name != "name" {
t . Fatalf ( "Link name should have been name, got %s instead" , name )
}
if alias != "name" {
t . Fatalf ( "Link alias should have been name, got %s instead" , alias )
}
// empty string link definition is not allowed
if _ , _ , err := ParseLink ( "" ) ; err == nil || ! strings . Contains ( err . Error ( ) , "empty string specified for links" ) {
t . Fatalf ( "Expected error 'empty string specified for links' but got: %v" , err )
}
// more than two colons are not allowed
if _ , _ , err := ParseLink ( "link:alias:wrong" ) ; err == nil || ! strings . Contains ( err . Error ( ) , "bad format for links: link:alias:wrong" ) {
t . Fatalf ( "Expected error 'bad format for links: link:alias:wrong' but got: %v" , err )
}
}