github.com/portworx/docker@v1.12.1/volume/volume_test.go (about)

     1  package volume
     2  
     3  import (
     4  	"runtime"
     5  	"strings"
     6  	"testing"
     7  )
     8  
     9  func TestParseMountSpec(t *testing.T) {
    10  	var (
    11  		valid   []string
    12  		invalid map[string]string
    13  	)
    14  
    15  	if runtime.GOOS == "windows" {
    16  		valid = []string{
    17  			`d:\`,
    18  			`d:`,
    19  			`d:\path`,
    20  			`d:\path with space`,
    21  			// TODO Windows post TP5 - readonly support `d:\pathandmode:ro`,
    22  			`c:\:d:\`,
    23  			`c:\windows\:d:`,
    24  			`c:\windows:d:\s p a c e`,
    25  			`c:\windows:d:\s p a c e:RW`,
    26  			`c:\program files:d:\s p a c e i n h o s t d i r`,
    27  			`0123456789name:d:`,
    28  			`MiXeDcAsEnAmE:d:`,
    29  			`name:D:`,
    30  			`name:D::rW`,
    31  			`name:D::RW`,
    32  			// TODO Windows post TP5 - readonly support `name:D::RO`,
    33  			`c:/:d:/forward/slashes/are/good/too`,
    34  			// TODO Windows post TP5 - readonly support `c:/:d:/including with/spaces:ro`,
    35  			`c:\Windows`,             // With capital
    36  			`c:\Program Files (x86)`, // With capitals and brackets
    37  		}
    38  		invalid = map[string]string{
    39  			``:                                 "Invalid volume specification: ",
    40  			`.`:                                "Invalid volume specification: ",
    41  			`..\`:                              "Invalid volume specification: ",
    42  			`c:\:..\`:                          "Invalid volume specification: ",
    43  			`c:\:d:\:xyzzy`:                    "Invalid volume specification: ",
    44  			`c:`:                               "cannot be c:",
    45  			`c:\`:                              `cannot be c:\`,
    46  			`c:\notexist:d:`:                   `The system cannot find the file specified`,
    47  			`c:\windows\system32\ntdll.dll:d:`: `Source 'c:\windows\system32\ntdll.dll' is not a directory`,
    48  			`name<:d:`:                         `Invalid volume specification`,
    49  			`name>:d:`:                         `Invalid volume specification`,
    50  			`name::d:`:                         `Invalid volume specification`,
    51  			`name":d:`:                         `Invalid volume specification`,
    52  			`name\:d:`:                         `Invalid volume specification`,
    53  			`name*:d:`:                         `Invalid volume specification`,
    54  			`name|:d:`:                         `Invalid volume specification`,
    55  			`name?:d:`:                         `Invalid volume specification`,
    56  			`name/:d:`:                         `Invalid volume specification`,
    57  			`d:\pathandmode:rw`:                `Invalid volume specification`,
    58  			`con:d:`:                           `cannot be a reserved word for Windows filenames`,
    59  			`PRN:d:`:                           `cannot be a reserved word for Windows filenames`,
    60  			`aUx:d:`:                           `cannot be a reserved word for Windows filenames`,
    61  			`nul:d:`:                           `cannot be a reserved word for Windows filenames`,
    62  			`com1:d:`:                          `cannot be a reserved word for Windows filenames`,
    63  			`com2:d:`:                          `cannot be a reserved word for Windows filenames`,
    64  			`com3:d:`:                          `cannot be a reserved word for Windows filenames`,
    65  			`com4:d:`:                          `cannot be a reserved word for Windows filenames`,
    66  			`com5:d:`:                          `cannot be a reserved word for Windows filenames`,
    67  			`com6:d:`:                          `cannot be a reserved word for Windows filenames`,
    68  			`com7:d:`:                          `cannot be a reserved word for Windows filenames`,
    69  			`com8:d:`:                          `cannot be a reserved word for Windows filenames`,
    70  			`com9:d:`:                          `cannot be a reserved word for Windows filenames`,
    71  			`lpt1:d:`:                          `cannot be a reserved word for Windows filenames`,
    72  			`lpt2:d:`:                          `cannot be a reserved word for Windows filenames`,
    73  			`lpt3:d:`:                          `cannot be a reserved word for Windows filenames`,
    74  			`lpt4:d:`:                          `cannot be a reserved word for Windows filenames`,
    75  			`lpt5:d:`:                          `cannot be a reserved word for Windows filenames`,
    76  			`lpt6:d:`:                          `cannot be a reserved word for Windows filenames`,
    77  			`lpt7:d:`:                          `cannot be a reserved word for Windows filenames`,
    78  			`lpt8:d:`:                          `cannot be a reserved word for Windows filenames`,
    79  			`lpt9:d:`:                          `cannot be a reserved word for Windows filenames`,
    80  		}
    81  
    82  	} else {
    83  		valid = []string{
    84  			"/home",
    85  			"/home:/home",
    86  			"/home:/something/else",
    87  			"/with space",
    88  			"/home:/with space",
    89  			"relative:/absolute-path",
    90  			"hostPath:/containerPath:ro",
    91  			"/hostPath:/containerPath:rw",
    92  			"/rw:/ro",
    93  		}
    94  		invalid = map[string]string{
    95  			"":                "Invalid volume specification",
    96  			"./":              "Invalid volume destination",
    97  			"../":             "Invalid volume destination",
    98  			"/:../":           "Invalid volume destination",
    99  			"/:path":          "Invalid volume destination",
   100  			":":               "Invalid volume specification",
   101  			"/tmp:":           "Invalid volume destination",
   102  			":test":           "Invalid volume specification",
   103  			":/test":          "Invalid volume specification",
   104  			"tmp:":            "Invalid volume destination",
   105  			":test:":          "Invalid volume specification",
   106  			"::":              "Invalid volume specification",
   107  			":::":             "Invalid volume specification",
   108  			"/tmp:::":         "Invalid volume specification",
   109  			":/tmp::":         "Invalid volume specification",
   110  			"/path:rw":        "Invalid volume specification",
   111  			"/path:ro":        "Invalid volume specification",
   112  			"/rw:rw":          "Invalid volume specification",
   113  			"path:ro":         "Invalid volume specification",
   114  			"/path:/path:sw":  `invalid mode: sw`,
   115  			"/path:/path:rwz": `invalid mode: rwz`,
   116  		}
   117  	}
   118  
   119  	for _, path := range valid {
   120  		if _, err := ParseMountSpec(path, "local"); err != nil {
   121  			t.Fatalf("ParseMountSpec(`%q`) should succeed: error %q", path, err)
   122  		}
   123  	}
   124  
   125  	for path, expectedError := range invalid {
   126  		if _, err := ParseMountSpec(path, "local"); err == nil {
   127  			t.Fatalf("ParseMountSpec(`%q`) should have failed validation. Err %v", path, err)
   128  		} else {
   129  			if !strings.Contains(err.Error(), expectedError) {
   130  				t.Fatalf("ParseMountSpec(`%q`) error should contain %q, got %v", path, expectedError, err.Error())
   131  			}
   132  		}
   133  	}
   134  }
   135  
   136  // testParseMountSpec is a structure used by TestParseMountSpecSplit for
   137  // specifying test cases for the ParseMountSpec() function.
   138  type testParseMountSpec struct {
   139  	bind      string
   140  	driver    string
   141  	expDest   string
   142  	expSource string
   143  	expName   string
   144  	expDriver string
   145  	expRW     bool
   146  	fail      bool
   147  }
   148  
   149  func TestParseMountSpecSplit(t *testing.T) {
   150  	var cases []testParseMountSpec
   151  	if runtime.GOOS == "windows" {
   152  		cases = []testParseMountSpec{
   153  			{`c:\:d:`, "local", `d:`, `c:\`, ``, "", true, false},
   154  			{`c:\:d:\`, "local", `d:\`, `c:\`, ``, "", true, false},
   155  			// TODO Windows post TP5 - Add readonly support {`c:\:d:\:ro`, "local", `d:\`, `c:\`, ``, "", false, false},
   156  			{`c:\:d:\:rw`, "local", `d:\`, `c:\`, ``, "", true, false},
   157  			{`c:\:d:\:foo`, "local", `d:\`, `c:\`, ``, "", false, true},
   158  			{`name:d::rw`, "local", `d:`, ``, `name`, "local", true, false},
   159  			{`name:d:`, "local", `d:`, ``, `name`, "local", true, false},
   160  			// TODO Windows post TP5 - Add readonly support {`name:d::ro`, "local", `d:`, ``, `name`, "local", false, false},
   161  			{`name:c:`, "", ``, ``, ``, "", true, true},
   162  			{`driver/name:c:`, "", ``, ``, ``, "", true, true},
   163  		}
   164  	} else {
   165  		cases = []testParseMountSpec{
   166  			{"/tmp:/tmp1", "", "/tmp1", "/tmp", "", "", true, false},
   167  			{"/tmp:/tmp2:ro", "", "/tmp2", "/tmp", "", "", false, false},
   168  			{"/tmp:/tmp3:rw", "", "/tmp3", "/tmp", "", "", true, false},
   169  			{"/tmp:/tmp4:foo", "", "", "", "", "", false, true},
   170  			{"name:/named1", "", "/named1", "", "name", "", true, false},
   171  			{"name:/named2", "external", "/named2", "", "name", "external", true, false},
   172  			{"name:/named3:ro", "local", "/named3", "", "name", "local", false, false},
   173  			{"local/name:/tmp:rw", "", "/tmp", "", "local/name", "", true, false},
   174  			{"/tmp:tmp", "", "", "", "", "", true, true},
   175  		}
   176  	}
   177  
   178  	for _, c := range cases {
   179  		m, err := ParseMountSpec(c.bind, c.driver)
   180  		if c.fail {
   181  			if err == nil {
   182  				t.Fatalf("Expected error, was nil, for spec %s\n", c.bind)
   183  			}
   184  			continue
   185  		}
   186  
   187  		if m == nil || err != nil {
   188  			t.Fatalf("ParseMountSpec failed for spec %s driver %s error %v\n", c.bind, c.driver, err.Error())
   189  			continue
   190  		}
   191  
   192  		if m.Destination != c.expDest {
   193  			t.Fatalf("Expected destination %s, was %s, for spec %s\n", c.expDest, m.Destination, c.bind)
   194  		}
   195  
   196  		if m.Source != c.expSource {
   197  			t.Fatalf("Expected source %s, was %s, for spec %s\n", c.expSource, m.Source, c.bind)
   198  		}
   199  
   200  		if m.Name != c.expName {
   201  			t.Fatalf("Expected name %s, was %s for spec %s\n", c.expName, m.Name, c.bind)
   202  		}
   203  
   204  		if m.Driver != c.expDriver {
   205  			t.Fatalf("Expected driver %s, was %s, for spec %s\n", c.expDriver, m.Driver, c.bind)
   206  		}
   207  
   208  		if m.RW != c.expRW {
   209  			t.Fatalf("Expected RW %v, was %v for spec %s\n", c.expRW, m.RW, c.bind)
   210  		}
   211  	}
   212  }