Source file src/cmd/go/internal/str/str_test.go

     1  // Copyright 2020 The Go Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  package str
     6  
     7  import (
     8  	"os"
     9  	"path/filepath"
    10  	"runtime"
    11  	"strings"
    12  	"testing"
    13  )
    14  
    15  var foldDupTests = []struct {
    16  	list   []string
    17  	f1, f2 string
    18  }{
    19  	{StringList("math/rand", "math/big"), "", ""},
    20  	{StringList("math", "strings"), "", ""},
    21  	{StringList("strings"), "", ""},
    22  	{StringList("strings", "strings"), "strings", "strings"},
    23  	{StringList("Rand", "rand", "math", "math/rand", "math/Rand"), "Rand", "rand"},
    24  }
    25  
    26  func TestFoldDup(t *testing.T) {
    27  	for _, tt := range foldDupTests {
    28  		f1, f2 := FoldDup(tt.list)
    29  		if f1 != tt.f1 || f2 != tt.f2 {
    30  			t.Errorf("foldDup(%q) = %q, %q, want %q, %q", tt.list, f1, f2, tt.f1, tt.f2)
    31  		}
    32  	}
    33  }
    34  
    35  func TestHasPathPrefix(t *testing.T) {
    36  	type testCase struct {
    37  		s, prefix string
    38  		want      bool
    39  	}
    40  	for _, tt := range []testCase{
    41  		{"", "", true},
    42  		{"", "/", false},
    43  		{"foo", "", true},
    44  		{"foo", "/", false},
    45  		{"foo", "foo", true},
    46  		{"foo", "foo/", false},
    47  		{"foo", "/foo", false},
    48  		{"foo/bar", "", true},
    49  		{"foo/bar", "foo", true},
    50  		{"foo/bar", "foo/", true},
    51  		{"foo/bar", "/foo", false},
    52  		{"foo/bar", "foo/bar", true},
    53  		{"foo/bar", "foo/bar/", false},
    54  		{"foo/bar", "/foo/bar", false},
    55  	} {
    56  		got := HasPathPrefix(tt.s, tt.prefix)
    57  		if got != tt.want {
    58  			t.Errorf("HasPathPrefix(%q, %q) = %v; want %v", tt.s, tt.prefix, got, tt.want)
    59  		}
    60  	}
    61  }
    62  
    63  func TestTrimFilePathPrefixSlash(t *testing.T) {
    64  	if os.PathSeparator != '/' {
    65  		t.Skipf("test requires slash-separated file paths")
    66  	}
    67  
    68  	type testCase struct {
    69  		s, prefix, want string
    70  	}
    71  	for _, tt := range []testCase{
    72  		{"/", "", "/"},
    73  		{"/", "/", ""},
    74  		{"/foo", "", "/foo"},
    75  		{"/foo", "/", "foo"},
    76  		{"/foo", "/foo", ""},
    77  		{"/foo/bar", "/foo", "bar"},
    78  		{"/foo/bar", "/foo/", "bar"},
    79  		{"/foo/", "/", "foo/"},
    80  		{"/foo/", "/foo", ""},
    81  		{"/foo/", "/foo/", ""},
    82  
    83  		// if prefix is not s's prefix, return s
    84  		{"", "/", ""},
    85  		{"/foo", "/bar", "/foo"},
    86  		{"/foo", "/foo/bar", "/foo"},
    87  		{"foo", "/foo", "foo"},
    88  		{"/foo", "foo", "/foo"},
    89  		{"/foo", "/foo/", "/foo"},
    90  	} {
    91  		got := TrimFilePathPrefix(tt.s, tt.prefix)
    92  		if got == tt.want {
    93  			t.Logf("TrimFilePathPrefix(%q, %q) = %q", tt.s, tt.prefix, got)
    94  		} else {
    95  			t.Errorf("TrimFilePathPrefix(%q, %q) = %q, want %q", tt.s, tt.prefix, got, tt.want)
    96  		}
    97  
    98  		if HasFilePathPrefix(tt.s, tt.prefix) {
    99  			joined := filepath.Join(tt.prefix, got)
   100  			if clean := filepath.Clean(tt.s); joined != clean {
   101  				t.Errorf("filepath.Join(%q, %q) = %q, want %q", tt.prefix, got, joined, clean)
   102  			}
   103  		}
   104  	}
   105  }
   106  
   107  func TestTrimFilePathPrefixWindows(t *testing.T) {
   108  	if runtime.GOOS != "windows" {
   109  		t.Skipf("test requires Windows file paths")
   110  	}
   111  	type testCase struct {
   112  		s, prefix, want string
   113  	}
   114  	for _, tt := range []testCase{
   115  		{`\`, ``, `\`},
   116  		{`\`, `\`, ``},
   117  		{`C:`, `C:`, ``},
   118  		{`C:\`, `C:`, `\`},
   119  		{`C:\`, `C:\`, ``},
   120  		{`C:\foo`, ``, `C:\foo`},
   121  		{`C:\foo`, `C:`, `\foo`},
   122  		{`C:\foo`, `C:\`, `foo`},
   123  		{`C:\foo`, `C:\foo`, ``},
   124  		{`C:\foo\`, `C:\foo`, ``},
   125  		{`C:\foo\bar`, `C:\foo`, `bar`},
   126  		{`C:\foo\bar`, `C:\foo\`, `bar`},
   127  		// if prefix is not s's prefix, return s
   128  		{`C:\foo`, `C:\bar`, `C:\foo`},
   129  		{`C:\foo`, `C:\foo\bar`, `C:\foo`},
   130  		{`C:`, `C:\`, `C:`},
   131  		// if volumes are different, return s
   132  		{`C:`, ``, `C:`},
   133  		{`C:\`, ``, `C:\`},
   134  		{`C:\foo`, ``, `C:\foo`},
   135  		{`C:\foo`, `\foo`, `C:\foo`},
   136  		{`C:\foo`, `D:\foo`, `C:\foo`},
   137  
   138  		//UNC path
   139  		{`\\host\share\foo`, `\\host\share`, `foo`},
   140  		{`\\host\share\foo`, `\\host\share\`, `foo`},
   141  		{`\\host\share\foo`, `\\host\share\foo`, ``},
   142  		{`\\host\share\foo\bar`, `\\host\share\foo`, `bar`},
   143  		{`\\host\share\foo\bar`, `\\host\share\foo\`, `bar`},
   144  		// if prefix is not s's prefix, return s
   145  		{`\\host\share\foo`, `\\host\share\bar`, `\\host\share\foo`},
   146  		{`\\host\share\foo`, `\\host\share\foo\bar`, `\\host\share\foo`},
   147  		// if either host or share name is different, return s
   148  		{`\\host\share\foo`, ``, `\\host\share\foo`},
   149  		{`\\host\share\foo`, `\foo`, `\\host\share\foo`},
   150  		{`\\host\share\foo`, `\\host\other\`, `\\host\share\foo`},
   151  		{`\\host\share\foo`, `\\other\share\`, `\\host\share\foo`},
   152  		{`\\host\share\foo`, `\\host\`, `\\host\share\foo`},
   153  		{`\\host\share\foo`, `\share\`, `\\host\share\foo`},
   154  
   155  		// only volume names are case-insensitive
   156  		{`C:\foo`, `c:`, `\foo`},
   157  		{`C:\foo`, `c:\foo`, ``},
   158  		{`c:\foo`, `C:`, `\foo`},
   159  		{`c:\foo`, `C:\foo`, ``},
   160  		{`C:\foo`, `C:\Foo`, `C:\foo`},
   161  		{`\\Host\Share\foo`, `\\host\share`, `foo`},
   162  		{`\\Host\Share\foo`, `\\host\share\foo`, ``},
   163  		{`\\host\share\foo`, `\\Host\Share`, `foo`},
   164  		{`\\host\share\foo`, `\\Host\Share\foo`, ``},
   165  		{`\\Host\Share\foo`, `\\Host\Share\Foo`, `\\Host\Share\foo`},
   166  	} {
   167  		got := TrimFilePathPrefix(tt.s, tt.prefix)
   168  		if got == tt.want {
   169  			t.Logf("TrimFilePathPrefix(%#q, %#q) = %#q", tt.s, tt.prefix, got)
   170  		} else {
   171  			t.Errorf("TrimFilePathPrefix(%#q, %#q) = %#q, want %#q", tt.s, tt.prefix, got, tt.want)
   172  		}
   173  
   174  		if HasFilePathPrefix(tt.s, tt.prefix) {
   175  			// Although TrimFilePathPrefix is only case-insensitive in the volume name,
   176  			// what we care about in testing Join is that absolute paths remain
   177  			// absolute and relative paths remaining relative — there is no harm in
   178  			// over-normalizing letters in the comparison, so we use EqualFold.
   179  			joined := filepath.Join(tt.prefix, got)
   180  			if clean := filepath.Clean(tt.s); !strings.EqualFold(joined, clean) {
   181  				t.Errorf("filepath.Join(%#q, %#q) = %#q, want %#q", tt.prefix, got, joined, clean)
   182  			}
   183  		}
   184  	}
   185  }
   186  

View as plain text