Added some testcases for the various file uri transforms to download_test.go
Moved some of the code for normalizing a Windows file uri to a regular path into it's own function NormalizeWindowsURL
This commit is contained in:
parent
281dd1258a
commit
da9c94b345
|
@ -101,6 +101,44 @@ func (d *DownloadClient) Cancel() {
|
|||
// TODO(mitchellh): Implement
|
||||
}
|
||||
|
||||
// Take a uri and convert it to a path that makes sense on the Windows platform
|
||||
func NormalizeWindowsURL(basepath string, url url.URL) string {
|
||||
// This logic must correspond to the same logic in the NormalizeWindowsURL
|
||||
// function found in common/config.go since that function _also_ checks that
|
||||
// the url actually exists in file form.
|
||||
|
||||
const UNCPrefix = string(os.PathSeparator)+string(os.PathSeparator)
|
||||
|
||||
// move any extra path components that were parsed into Host due
|
||||
// to UNC into the url.Path field so that it's PathSeparators get
|
||||
// normalized
|
||||
if len(url.Host) >= len(UNCPrefix) && url.Host[:len(UNCPrefix)] == UNCPrefix {
|
||||
idx := strings.Index(url.Host[len(UNCPrefix):], string(os.PathSeparator))
|
||||
if idx > -1 {
|
||||
url.Path = filepath.ToSlash(url.Host[idx+len(UNCPrefix):]) + url.Path
|
||||
url.Host = url.Host[:idx+len(UNCPrefix)]
|
||||
}
|
||||
}
|
||||
|
||||
// clean up backward-slashes since they only matter when part of a unc path
|
||||
urlPath := filepath.ToSlash(url.Path)
|
||||
|
||||
// semi-absolute path (current drive letter) -- file:///absolute/path
|
||||
if url.Host == "" && len(urlPath) > 0 && urlPath[0] == '/' {
|
||||
return path.Join(filepath.VolumeName(basepath), urlPath)
|
||||
|
||||
// relative path -- file://./relative/path
|
||||
// file://relative/path
|
||||
} else if url.Host == "" || (len(url.Host) > 0 && url.Host[0] == '.') {
|
||||
return path.Join(filepath.ToSlash(basepath), urlPath)
|
||||
}
|
||||
|
||||
// absolute path
|
||||
// UNC -- file://\\host/share/whatever
|
||||
// drive -- file://c:/absolute/path
|
||||
return path.Join(url.Host, urlPath)
|
||||
}
|
||||
|
||||
func (d *DownloadClient) Get() (string, error) {
|
||||
// If we already have the file and it matches, then just return the target path.
|
||||
if verify, _ := d.VerifyChecksum(d.config.TargetPath); verify {
|
||||
|
@ -133,49 +171,17 @@ func (d *DownloadClient) Get() (string, error) {
|
|||
// locally and we don't make a copy. Normally we would copy or download.
|
||||
log.Printf("[DEBUG] Using local file: %s", finalPath)
|
||||
|
||||
// FIXME:
|
||||
// cwd should point to the path relative to client.json, but
|
||||
// since this isn't exposed to us anywhere, we use os.Getwd()
|
||||
// to figure it out.
|
||||
cwd,err := os.Getwd()
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("Unable to get working directory")
|
||||
}
|
||||
|
||||
// convert the actual file uri to a windowsy path
|
||||
// (this logic must correspond to the same logic in common/config.go)
|
||||
// transform the actual file uri to a windowsy path if we're being windowsy.
|
||||
if runtime.GOOS == "windows" {
|
||||
const UNCPrefix = string(os.PathSeparator)+string(os.PathSeparator)
|
||||
|
||||
// move any extra path components that were parsed into Host due
|
||||
// to UNC into the url.Path field so that it's PathSeparators get
|
||||
// normalized
|
||||
if len(url.Host) >= len(UNCPrefix) && url.Host[:len(UNCPrefix)] == UNCPrefix {
|
||||
idx := strings.Index(url.Host[len(UNCPrefix):], string(os.PathSeparator))
|
||||
if idx > -1 {
|
||||
url.Path = filepath.ToSlash(url.Host[idx+len(UNCPrefix):]) + url.Path
|
||||
url.Host = url.Host[:idx+len(UNCPrefix)]
|
||||
}
|
||||
}
|
||||
|
||||
// clean up backward-slashes since they only matter when part of a unc path
|
||||
urlPath := filepath.ToSlash(url.Path)
|
||||
|
||||
// semi-absolute path (current drive letter) -- file:///absolute/path
|
||||
if url.Host == "" && len(urlPath) > 0 && urlPath[0] == '/' {
|
||||
finalPath = path.Join(filepath.VolumeName(cwd), urlPath)
|
||||
|
||||
// relative path -- file://./relative/path
|
||||
// file://relative/path
|
||||
} else if url.Host == "" || (len(url.Host) > 0 && url.Host[0] == '.') {
|
||||
finalPath = path.Join(filepath.ToSlash(cwd), urlPath)
|
||||
|
||||
// absolute path
|
||||
} else {
|
||||
// UNC -- file://\\host/share/whatever
|
||||
// drive -- file://c:/absolute/path
|
||||
finalPath = path.Join(url.Host, urlPath)
|
||||
// FIXME: cwd should point to a path relative to the TEMPLATE path,
|
||||
// but since this isn't exposed to us anywhere, we use os.Getwd()
|
||||
// and assume the user ran packer in the same directory that
|
||||
// any relative files are located at.
|
||||
cwd,err := os.Getwd()
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("Unable to get working directory")
|
||||
}
|
||||
finalPath = NormalizeWindowsURL(cwd, *url)
|
||||
}
|
||||
|
||||
// Keep track of the source so we can make sure not to delete this later
|
||||
|
|
|
@ -9,6 +9,8 @@ import (
|
|||
"net/http/httptest"
|
||||
"os"
|
||||
"runtime"
|
||||
"strings"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
)
|
||||
|
||||
|
@ -382,5 +384,106 @@ func TestDownloadFileUrl(t *testing.T) {
|
|||
if _, err = os.Stat(sourcePath); err != nil {
|
||||
t.Errorf("Could not stat source file: %s", sourcePath)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// SimulateFileUriDownload is a simple utility function that converts a uri
|
||||
// into a testable file path whilst ignoring a correct checksum match, stripping
|
||||
// UNC path info, and then calling stat to ensure the correct file exists.
|
||||
// (used by TestFileUriTransforms)
|
||||
func SimulateFileUriDownload(t *testing.T, uri string) (string,error) {
|
||||
// source_path is a file path and source is a network path
|
||||
source := fmt.Sprintf(uri)
|
||||
t.Logf("Trying to download %s", source)
|
||||
|
||||
config := &DownloadConfig{
|
||||
Url: source,
|
||||
// This should be wrong. We want to make sure we don't delete
|
||||
Checksum: []byte("nope"),
|
||||
Hash: HashForType("sha256"),
|
||||
CopyFile: false,
|
||||
}
|
||||
|
||||
// go go go
|
||||
client := NewDownloadClient(config)
|
||||
path, err := client.Get()
|
||||
|
||||
// ignore any non-important checksum errors if it's not a unc path
|
||||
if !strings.HasPrefix(path, "\\\\") && err.Error() != "checksums didn't match expected: 6e6f7065" {
|
||||
t.Fatalf("Unexpected failure; expected checksum not to match")
|
||||
}
|
||||
|
||||
// if it's a unc path, then remove the host and share name so we don't have
|
||||
// to force the user to enable ADMIN$ and Windows File Sharing
|
||||
if strings.HasPrefix(path, "\\\\") {
|
||||
res := strings.SplitN(path, "/", 3)
|
||||
path = "/" + res[2]
|
||||
}
|
||||
|
||||
if _, err = os.Stat(path); err != nil {
|
||||
t.Errorf("Could not stat source file: %s", path)
|
||||
}
|
||||
return path,err
|
||||
}
|
||||
|
||||
// TestFileUriTransforms tests the case where we use a local file uri
|
||||
// for iso_url. There's a few different formats that a file uri can exist as
|
||||
// and so we try to test the most useful and common ones.
|
||||
func TestFileUriTransforms(t *testing.T) {
|
||||
const testpath = /* have your */ "test-fixtures/fileurl/cake" /* and eat it too */
|
||||
const host = "localhost"
|
||||
|
||||
var cwd string
|
||||
var volume string
|
||||
var share string
|
||||
|
||||
cwd, err := os.Getwd()
|
||||
if err != nil {
|
||||
t.Fatalf("Unable to detect working directory: %s", err)
|
||||
return
|
||||
}
|
||||
cwd = filepath.ToSlash(cwd)
|
||||
volume = filepath.VolumeName(cwd)
|
||||
share = volume
|
||||
if share[len(share)-1] == ':' {
|
||||
share = share[:len(share)-1] + "$"
|
||||
}
|
||||
cwd = cwd[len(volume):]
|
||||
|
||||
t.Logf("TestFileUriTransforms : Running with cwd : '%s'", cwd)
|
||||
t.Logf("TestFileUriTransforms : Running with volume : '%s'", volume)
|
||||
|
||||
// ./relative/path -> ./relative/path
|
||||
// /absolute/path -> /absolute/path
|
||||
// c:/windows/absolute -> c:/windows/absolute
|
||||
// \\host/sharename/file -> \\host/sharename/file
|
||||
testcases := []string{
|
||||
"./%s",
|
||||
cwd + "/%s",
|
||||
volume + cwd + "/%s",
|
||||
"\\\\" + host + "/" + share + "/" + cwd[1:] + "/%s",
|
||||
}
|
||||
|
||||
// all regular slashed testcases
|
||||
for _,testcase := range testcases {
|
||||
uri := "file://" + fmt.Sprintf(testcase, testpath)
|
||||
t.Logf("TestFileUriTransforms : Trying Uri '%s'", uri)
|
||||
res,err := SimulateFileUriDownload(t, uri)
|
||||
if err != nil {
|
||||
t.Errorf("Unable to transform uri '%s' into a path : %v", uri, err)
|
||||
}
|
||||
t.Errorf("TestFileUriTransforms : Result Path '%s'", res)
|
||||
}
|
||||
|
||||
// ...and finally the oddball windows native path
|
||||
// \\host\sharename\file -> \\host/sharename/file
|
||||
testpath_native := filepath.FromSlash(testpath)
|
||||
testcase_native := "\\\\" + host + "\\" + share + "\\" + filepath.FromSlash(cwd[1:]) + "\\%s"
|
||||
uri := "file://" + fmt.Sprintf(testcase_native, testpath_native)
|
||||
t.Logf("TestFileUriTransforms : Trying Uri '%s'", uri)
|
||||
res,err := SimulateFileUriDownload(t, uri)
|
||||
if err != nil {
|
||||
t.Errorf("Unable to transform uri '%s' into a path", uri)
|
||||
return
|
||||
}
|
||||
t.Errorf("TestFileUriTransforms : Result Path '%s'", res)
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue