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
|
// 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) {
|
func (d *DownloadClient) Get() (string, error) {
|
||||||
// If we already have the file and it matches, then just return the target path.
|
// If we already have the file and it matches, then just return the target path.
|
||||||
if verify, _ := d.VerifyChecksum(d.config.TargetPath); verify {
|
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.
|
// locally and we don't make a copy. Normally we would copy or download.
|
||||||
log.Printf("[DEBUG] Using local file: %s", finalPath)
|
log.Printf("[DEBUG] Using local file: %s", finalPath)
|
||||||
|
|
||||||
// FIXME:
|
// transform the actual file uri to a windowsy path if we're being windowsy.
|
||||||
// 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)
|
|
||||||
if runtime.GOOS == "windows" {
|
if runtime.GOOS == "windows" {
|
||||||
const UNCPrefix = string(os.PathSeparator)+string(os.PathSeparator)
|
// 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()
|
||||||
// move any extra path components that were parsed into Host due
|
// and assume the user ran packer in the same directory that
|
||||||
// to UNC into the url.Path field so that it's PathSeparators get
|
// any relative files are located at.
|
||||||
// normalized
|
cwd,err := os.Getwd()
|
||||||
if len(url.Host) >= len(UNCPrefix) && url.Host[:len(UNCPrefix)] == UNCPrefix {
|
if err != nil {
|
||||||
idx := strings.Index(url.Host[len(UNCPrefix):], string(os.PathSeparator))
|
return "", fmt.Errorf("Unable to get working directory")
|
||||||
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)
|
|
||||||
}
|
}
|
||||||
|
finalPath = NormalizeWindowsURL(cwd, *url)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Keep track of the source so we can make sure not to delete this later
|
// Keep track of the source so we can make sure not to delete this later
|
||||||
|
|
|
@ -9,6 +9,8 @@ import (
|
||||||
"net/http/httptest"
|
"net/http/httptest"
|
||||||
"os"
|
"os"
|
||||||
"runtime"
|
"runtime"
|
||||||
|
"strings"
|
||||||
|
"path/filepath"
|
||||||
"testing"
|
"testing"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -382,5 +384,106 @@ func TestDownloadFileUrl(t *testing.T) {
|
||||||
if _, err = os.Stat(sourcePath); err != nil {
|
if _, err = os.Stat(sourcePath); err != nil {
|
||||||
t.Errorf("Could not stat source file: %s", sourcePath)
|
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