Skip to content

Commit

Permalink
Fix exception when file type contains colon
Browse files Browse the repository at this point in the history
Signed-off-by: cui fliter <[email protected]>
  • Loading branch information
cuishuang committed Nov 10, 2023
1 parent 4ca4178 commit d091f86
Show file tree
Hide file tree
Showing 4 changed files with 70 additions and 1 deletion.
17 changes: 16 additions & 1 deletion internal/driver/fetch.go
Original file line number Diff line number Diff line change
Expand Up @@ -492,7 +492,9 @@ mapping:
func fetch(source string, duration, timeout time.Duration, ui plugin.UI, tr http.RoundTripper) (p *profile.Profile, src string, err error) {
var f io.ReadCloser

if sourceURL, timeout := adjustURL(source, duration, timeout); sourceURL != "" {
if isFile(source) {
f, err = os.Open(source)
} else if sourceURL, timeout := adjustURL(source, duration, timeout); sourceURL != "" {
ui.Print("Fetching profile over HTTP from " + sourceURL)
if duration > 0 {
ui.Print(fmt.Sprintf("Please wait... (%v)", duration))
Expand Down Expand Up @@ -614,3 +616,16 @@ func adjustURL(source string, duration, timeout time.Duration) (string, time.Dur
u.RawQuery = values.Encode()
return u.String(), timeout
}

// isFile validates if the profile source is a file, but it will be recognized
// as a link by url.Parse (when it contains `:`, like mem_2023-11-01_15:04:05).
// If such a file exists in the current directory, it will be recognized as a
// file rather than a link. Because colons are not allowed in file names on
// Windows systems, the Windows case should be ignored.
func isFile(source string) bool {
if runtime.GOOS == "windows" {
return false
}
_, err := os.Stat(source)
return err == nil
}
54 changes: 54 additions & 0 deletions internal/driver/fetch_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -216,6 +216,60 @@ func TestFetch(t *testing.T) {
}
}

func TestFetchWhenFileContainColon(t *testing.T) {
if runtime.GOOS == "windows" {
t.Skip("test assumes Unix paths")
}

// Rename file to solve the problem that when the file name contains a colon,
// an error occurs when the Windows system pulls the code.
err1 := os.Rename("testdata/go.crc32.cpu_2023-11-11_01_02_03", "testdata/go.crc32.cpu_2023-11-11_01:02:03")
if err1 != nil {
t.Errorf("rename file err: %v", err1)
return
}
err2 := os.Rename("go.crc32.cpu_2023-12-12_06_06_06", "go.crc32.cpu_2023-12-12_06:06:06")
if err2 != nil {
t.Errorf("rename file err: %v", err2)
return
}

defer func() {
os.Rename("testdata/go.crc32.cpu_2023-11-11_01:02:03", "testdata/go.crc32.cpu_2023-11-11_01_02_03")
os.Rename("go.crc32.cpu_2023-12-12_06:06:06", "go.crc32.cpu_2023-12-12_06_06_06")
}()

const path = "testdata/"
type testcase struct {
source, execName string
}

for _, tc := range []testcase{
// If the file containing a colon is in the current directory, an error will be reported
// and the test will not pass (the test will be passed after adding logic)
{path + "go.crc32.cpu_2023-11-11_01:02:03", ""},
// If the file containing colon is in a non-current directory, it can pass the test
// regardless of whether it is modified or not.
{"go.crc32.cpu_2023-12-12_06:06:06", ""},
} {
p, _, _, err := grabProfile(&source{ExecName: tc.execName}, tc.source, nil, testObj{}, &proftest.TestUI{T: t}, &httpTransport{})
if err != nil {
t.Fatalf("%s: %s", tc.source, err)
}
if len(p.Sample) == 0 {
t.Errorf("%s: want non-zero samples", tc.source)
}
if e := tc.execName; e != "" {
switch {
case len(p.Mapping) == 0 || p.Mapping[0] == nil:
t.Errorf("%s: want mapping[0].execName == %s, got no mappings", tc.source, e)
case p.Mapping[0].File != e:
t.Errorf("%s: want mapping[0].execName == %s, got %s", tc.source, e, p.Mapping[0].File)
}
}
}
}

func TestFetchWithBase(t *testing.T) {
baseConfig := currentConfig()
defer setCurrentConfig(baseConfig)
Expand Down
Binary file added internal/driver/go.crc32.cpu_2023-12-12_06:06:06
Binary file not shown.
Binary file not shown.

0 comments on commit d091f86

Please sign in to comment.