1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200
|
// Copyright 2022 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package web
import (
"net/url"
"runtime"
"testing"
)
func TestURLToFilePath(t *testing.T) {
for _, tc := range urlTests() {
if tc.url == "" {
continue
}
tc := tc
t.Run(tc.url, func(t *testing.T) {
u, err := url.Parse(tc.url)
if err != nil {
t.Fatalf("url.Parse(%q): %v", tc.url, err)
}
path, err := URLToFilePath(u)
if err != nil {
if err.Error() == tc.wantErr {
return
}
if tc.wantErr == "" {
t.Fatalf("urlToFilePath(%v): %v; want <nil>", u, err)
} else {
t.Fatalf("urlToFilePath(%v): %v; want %s", u, err, tc.wantErr)
}
}
if path != tc.filePath || tc.wantErr != "" {
t.Fatalf("urlToFilePath(%v) = %q, <nil>; want %q, %s", u, path, tc.filePath, tc.wantErr)
}
})
}
}
func TestURLFromFilePath(t *testing.T) {
for _, tc := range urlTests() {
if tc.filePath == "" {
continue
}
tc := tc
t.Run(tc.filePath, func(t *testing.T) {
u, err := URLFromFilePath(tc.filePath)
if err != nil {
if err.Error() == tc.wantErr {
return
}
if tc.wantErr == "" {
t.Fatalf("urlFromFilePath(%v): %v; want <nil>", tc.filePath, err)
} else {
t.Fatalf("urlFromFilePath(%v): %v; want %s", tc.filePath, err, tc.wantErr)
}
}
if tc.wantErr != "" {
t.Fatalf("urlFromFilePath(%v) = <nil>; want error: %s", tc.filePath, tc.wantErr)
}
wantURL := tc.url
if tc.canonicalURL != "" {
wantURL = tc.canonicalURL
}
if u.String() != wantURL {
t.Errorf("urlFromFilePath(%v) = %v; want %s", tc.filePath, u, wantURL)
}
})
}
}
func urlTests() []urlTest {
if runtime.GOOS == "windows" {
return urlTestsWindows
}
return urlTestsOthers
}
type urlTest struct {
url string
filePath string
canonicalURL string // If empty, assume equal to url.
wantErr string
}
var urlTestsOthers = []urlTest{
// Examples from RFC 8089:
{
url: `file:///path/to/file`,
filePath: `/path/to/file`,
},
{
url: `file:/path/to/file`,
filePath: `/path/to/file`,
canonicalURL: `file:///path/to/file`,
},
{
url: `file://localhost/path/to/file`,
filePath: `/path/to/file`,
canonicalURL: `file:///path/to/file`,
},
// We reject non-local files.
{
url: `file://host.example.com/path/to/file`,
wantErr: "file URL specifies non-local host",
},
}
var urlTestsWindows = []urlTest{
// Examples from https://blogs.msdn.microsoft.com/ie/2006/12/06/file-uris-in-windows/:
{
url: `file://laptop/My%20Documents/FileSchemeURIs.doc`,
filePath: `\\laptop\My Documents\FileSchemeURIs.doc`,
},
{
url: `file:///C:/Documents%20and%20Settings/davris/FileSchemeURIs.doc`,
filePath: `C:\Documents and Settings\davris\FileSchemeURIs.doc`,
},
{
url: `file:///D:/Program%20Files/Viewer/startup.htm`,
filePath: `D:\Program Files\Viewer\startup.htm`,
},
{
url: `file:///C:/Program%20Files/Music/Web%20Sys/main.html?REQUEST=RADIO`,
filePath: `C:\Program Files\Music\Web Sys\main.html`,
canonicalURL: `file:///C:/Program%20Files/Music/Web%20Sys/main.html`,
},
{
url: `file://applib/products/a-b/abc_9/4148.920a/media/start.swf`,
filePath: `\\applib\products\a-b\abc_9\4148.920a\media\start.swf`,
},
{
url: `file:////applib/products/a%2Db/abc%5F9/4148.920a/media/start.swf`,
wantErr: "file URL missing drive letter",
},
{
url: `C:\Program Files\Music\Web Sys\main.html?REQUEST=RADIO`,
wantErr: "non-file URL",
},
// The example "file://D:\Program Files\Viewer\startup.htm" errors out in
// url.Parse, so we substitute a slash-based path for testing instead.
{
url: `file://D:/Program Files/Viewer/startup.htm`,
wantErr: "file URL encodes volume in host field: too few slashes?",
},
// The blog post discourages the use of non-ASCII characters because they
// depend on the user's current codepage. However, when we are working with Go
// strings we assume UTF-8 encoding, and our url package refuses to encode
// URLs to non-ASCII strings.
{
url: `file:///C:/exampleㄓ.txt`,
filePath: `C:\exampleㄓ.txt`,
canonicalURL: `file:///C:/example%E3%84%93.txt`,
},
{
url: `file:///C:/example%E3%84%93.txt`,
filePath: `C:\exampleㄓ.txt`,
},
// Examples from RFC 8089:
// We allow the drive-letter variation from section E.2, because it is
// simpler to support than not to. However, we do not generate the shorter
// form in the reverse direction.
{
url: `file:c:/path/to/file`,
filePath: `c:\path\to\file`,
canonicalURL: `file:///c:/path/to/file`,
},
// We encode the UNC share name as the authority following section E.3.1,
// because that is what the Microsoft blog post explicitly recommends.
{
url: `file://host.example.com/Share/path/to/file.txt`,
filePath: `\\host.example.com\Share\path\to\file.txt`,
},
// We decline the four- and five-slash variations from section E.3.2.
// The paths in these URLs would change meaning under path.Clean.
{
url: `file:////host.example.com/path/to/file`,
wantErr: "file URL missing drive letter",
},
{
url: `file://///host.example.com/path/to/file`,
wantErr: "file URL missing drive letter",
},
}
|