@ -8,198 +8,10 @@ import (
"io/ioutil"
"io/ioutil"
"os"
"os"
"path/filepath"
"path/filepath"
"reflect"
"runtime"
"runtime"
"strings"
"testing"
"testing"
"github.com/golang/dep/internal/test"
"github.com/pkg/errors"
)
)
// This function tests HadFilepathPrefix. It should test it on both case
// sensitive and insensitive situations. However, the only reliable way to test
// case-insensitive behaviour is if using case-insensitive filesystem. This
// cannot be guaranteed in an automated test. Therefore, the behaviour of the
// tests is not to test case sensitivity on *nix and to assume that Windows is
// case-insensitive. Please see link below for some background.
//
// https://superuser.com/questions/266110/how-do-you-make-windows-7-fully-case-sensitive-with-respect-to-the-filesystem
//
// NOTE: NTFS can be made case-sensitive. However many Windows programs,
// including Windows Explorer do not handle gracefully multiple files that
// differ only in capitalization. It is possible that this can cause these tests
// to fail on some setups.
func TestHasFilepathPrefix ( t * testing . T ) {
dir , err := ioutil . TempDir ( "" , "dep" )
if err != nil {
t . Fatal ( err )
}
defer os . RemoveAll ( dir )
// dir2 is the same as dir but with different capitalization on Windows to
// test case insensitivity
var dir2 string
if runtime . GOOS == "windows" {
dir = strings . ToLower ( dir )
dir2 = strings . ToUpper ( dir )
} else {
dir2 = dir
}
// For testing trailing and repeated separators
sep := string ( os . PathSeparator )
cases := [ ] struct {
path string
prefix string
want bool
} {
{ filepath . Join ( dir , "a" , "b" ) , filepath . Join ( dir2 ) , true } ,
{ filepath . Join ( dir , "a" , "b" ) , dir2 + sep + sep + "a" , true } ,
{ filepath . Join ( dir , "a" , "b" ) , filepath . Join ( dir2 , "a" ) + sep , true } ,
{ filepath . Join ( dir , "a" , "b" ) + sep , filepath . Join ( dir2 ) , true } ,
{ dir + sep + sep + filepath . Join ( "a" , "b" ) , filepath . Join ( dir2 , "a" ) , true } ,
{ filepath . Join ( dir , "a" , "b" ) , filepath . Join ( dir2 , "a" ) , true } ,
{ filepath . Join ( dir , "a" , "b" ) , filepath . Join ( dir2 , "a" , "b" ) , true } ,
{ filepath . Join ( dir , "a" , "b" ) , filepath . Join ( dir2 , "c" ) , false } ,
{ filepath . Join ( dir , "a" , "b" ) , filepath . Join ( dir2 , "a" , "d" , "b" ) , false } ,
{ filepath . Join ( dir , "a" , "b" ) , filepath . Join ( dir2 , "a" , "b2" ) , false } ,
{ filepath . Join ( dir ) , filepath . Join ( dir2 , "a" , "b" ) , false } ,
{ filepath . Join ( dir , "ab" ) , filepath . Join ( dir2 , "a" , "b" ) , false } ,
{ filepath . Join ( dir , "ab" ) , filepath . Join ( dir2 , "a" ) , false } ,
{ filepath . Join ( dir , "123" ) , filepath . Join ( dir2 , "123" ) , true } ,
{ filepath . Join ( dir , "123" ) , filepath . Join ( dir2 , "1" ) , false } ,
{ filepath . Join ( dir , "⌘" ) , filepath . Join ( dir2 , "⌘" ) , true } ,
{ filepath . Join ( dir , "a" ) , filepath . Join ( dir2 , "⌘" ) , false } ,
{ filepath . Join ( dir , "⌘" ) , filepath . Join ( dir2 , "a" ) , false } ,
}
for _ , c := range cases {
if err := os . MkdirAll ( c . path , 0755 ) ; err != nil {
t . Fatal ( err )
}
if err = os . MkdirAll ( c . prefix , 0755 ) ; err != nil {
t . Fatal ( err )
}
got , err := HasFilepathPrefix ( c . path , c . prefix )
if err != nil {
t . Fatalf ( "unexpected error: %s" , err )
}
if c . want != got {
t . Fatalf ( "dir: %q, prefix: %q, expected: %v, got: %v" , c . path , c . prefix , c . want , got )
}
}
}
// This function tests HadFilepathPrefix. It should test it on both case
// sensitive and insensitive situations. However, the only reliable way to test
// case-insensitive behaviour is if using case-insensitive filesystem. This
// cannot be guaranteed in an automated test. Therefore, the behaviour of the
// tests is not to test case sensitivity on *nix and to assume that Windows is
// case-insensitive. Please see link below for some background.
//
// https://superuser.com/questions/266110/how-do-you-make-windows-7-fully-case-sensitive-with-respect-to-the-filesystem
//
// NOTE: NTFS can be made case-sensitive. However many Windows programs,
// including Windows Explorer do not handle gracefully multiple files that
// differ only in capitalization. It is possible that this can cause these tests
// to fail on some setups.
func TestHasFilepathPrefix_Files ( t * testing . T ) {
dir , err := ioutil . TempDir ( "" , "dep" )
if err != nil {
t . Fatal ( err )
}
defer os . RemoveAll ( dir )
// dir2 is the same as dir but with different capitalization on Windows to
// test case insensitivity
var dir2 string
if runtime . GOOS == "windows" {
dir = strings . ToLower ( dir )
dir2 = strings . ToUpper ( dir )
} else {
dir2 = dir
}
existingFile := filepath . Join ( dir , "exists" )
if err = os . MkdirAll ( existingFile , 0755 ) ; err != nil {
t . Fatal ( err )
}
nonExistingFile := filepath . Join ( dir , "does_not_exists" )
cases := [ ] struct {
path string
prefix string
want bool
err bool
} {
{ existingFile , filepath . Join ( dir2 ) , true , false } ,
{ nonExistingFile , filepath . Join ( dir2 ) , false , true } ,
}
for _ , c := range cases {
got , err := HasFilepathPrefix ( c . path , c . prefix )
if err != nil && ! c . err {
t . Fatalf ( "unexpected error: %s" , err )
}
if c . want != got {
t . Fatalf ( "dir: %q, prefix: %q, expected: %v, got: %v" , c . path , c . prefix , c . want , got )
}
}
}
func TestEquivalentPaths ( t * testing . T ) {
h := test . NewHelper ( t )
h . TempDir ( "dir" )
h . TempDir ( "dir2" )
h . TempFile ( "file" , "" )
h . TempFile ( "file2" , "" )
h . TempDir ( "DIR" )
h . TempFile ( "FILE" , "" )
testcases := [ ] struct {
p1 , p2 string
caseSensitiveEquivalent bool
caseInensitiveEquivalent bool
err bool
} {
{ h . Path ( "dir" ) , h . Path ( "dir" ) , true , true , false } ,
{ h . Path ( "file" ) , h . Path ( "file" ) , true , true , false } ,
{ h . Path ( "dir" ) , h . Path ( "dir2" ) , false , false , false } ,
{ h . Path ( "file" ) , h . Path ( "file2" ) , false , false , false } ,
{ h . Path ( "dir" ) , h . Path ( "file" ) , false , false , false } ,
{ h . Path ( "dir" ) , h . Path ( "DIR" ) , false , true , false } ,
{ strings . ToLower ( h . Path ( "dir" ) ) , strings . ToUpper ( h . Path ( "dir" ) ) , false , true , true } ,
}
caseSensitive , err := IsCaseSensitiveFilesystem ( h . Path ( "dir" ) )
if err != nil {
t . Fatal ( "unexpcted error:" , err )
}
for _ , tc := range testcases {
got , err := EquivalentPaths ( tc . p1 , tc . p2 )
if err != nil && ! tc . err {
t . Error ( "unexpected error:" , err )
}
if caseSensitive {
if tc . caseSensitiveEquivalent != got {
t . Errorf ( "expected EquivalentPaths(%q, %q) to be %t on case-sensitive filesystem, got %t" , tc . p1 , tc . p2 , tc . caseSensitiveEquivalent , got )
}
} else {
if tc . caseInensitiveEquivalent != got {
t . Errorf ( "expected EquivalentPaths(%q, %q) to be %t on case-insensitive filesystem, got %t" , tc . p1 , tc . p2 , tc . caseInensitiveEquivalent , got )
}
}
}
}
func TestRenameWithFallback ( t * testing . T ) {
func TestRenameWithFallback ( t * testing . T ) {
dir , err := ioutil . TempDir ( "" , "dep" )
dir , err := ioutil . TempDir ( "" , "dep" )
if err != nil {
if err != nil {
@ -238,158 +50,6 @@ func TestRenameWithFallback(t *testing.T) {
}
}
}
}
func TestIsCaseSensitiveFilesystem ( t * testing . T ) {
isLinux := runtime . GOOS == "linux"
isWindows := runtime . GOOS == "windows"
isMacOS := runtime . GOOS == "darwin"
if ! isLinux && ! isWindows && ! isMacOS {
t . Skip ( "Run this test on Windows, Linux and macOS only" )
}
dir , err := ioutil . TempDir ( "" , "TestCaseSensitivity" )
if err != nil {
t . Fatal ( err )
}
defer os . RemoveAll ( dir )
var want bool
if isLinux {
want = true
} else {
want = false
}
got , err := IsCaseSensitiveFilesystem ( dir )
if err != nil {
t . Fatalf ( "unexpected error message: \n\t(GOT) %+v" , err )
}
if want != got {
t . Fatalf ( "unexpected value returned: \n\t(GOT) %t\n\t(WNT) %t" , got , want )
}
}
func TestReadActualFilenames ( t * testing . T ) {
// We are trying to skip this test on file systems which are case-sensiive. We could
// have used `fs.IsCaseSensitiveFilesystem` for this check. However, the code we are
// testing also relies on `fs.IsCaseSensitiveFilesystem`. So a bug in
// `fs.IsCaseSensitiveFilesystem` could prevent this test from being run. This is the
// only scenario where we prefer the OS heuristic over doing the actual work of
// validating filesystem case sensitivity via `fs.IsCaseSensitiveFilesystem`.
if runtime . GOOS != "windows" && runtime . GOOS != "darwin" {
t . Skip ( "skip this test on non-Windows, non-macOS" )
}
h := test . NewHelper ( t )
defer h . Cleanup ( )
h . TempDir ( "" )
tmpPath := h . Path ( "." )
// First, check the scenarios for which we expect an error.
_ , err := ReadActualFilenames ( filepath . Join ( tmpPath , "does_not_exists" ) , [ ] string { "" } )
switch {
case err == nil :
t . Fatal ( "expected err for non-existing folder" )
// use `errors.Cause` because the error is wrapped and returned
case ! os . IsNotExist ( errors . Cause ( err ) ) :
t . Fatalf ( "unexpected error: %+v" , err )
}
h . TempFile ( "tmpFile" , "" )
_ , err = ReadActualFilenames ( h . Path ( "tmpFile" ) , [ ] string { "" } )
switch {
case err == nil :
t . Fatal ( "expected err for passing file instead of directory" )
case err != errPathNotDir :
t . Fatalf ( "unexpected error: %+v" , err )
}
cases := [ ] struct {
createFiles [ ] string
names [ ] string
want map [ string ] string
} {
// If we supply no filenames to the function, it should return an empty map.
{ nil , nil , map [ string ] string { } } ,
// If the directory contains the given file with different case, it should return
// a map which has the given filename as the key and actual filename as the value.
{
[ ] string { "test1.txt" } ,
[ ] string { "Test1.txt" } ,
map [ string ] string { "Test1.txt" : "test1.txt" } ,
} ,
// 1. If the given filename is same as the actual filename, map should have the
// same key and value for the file.
// 2. If the given filename is present with different case for file extension,
// it should return a map which has the given filename as the key and actual
// filename as the value.
// 3. If the given filename is not present even with a different case, the map
// returned should not have an entry for that filename.
{
[ ] string { "test2.txt" , "test3.TXT" } ,
[ ] string { "test2.txt" , "Test3.txt" , "Test4.txt" } ,
map [ string ] string {
"test2.txt" : "test2.txt" ,
"Test3.txt" : "test3.TXT" ,
} ,
} ,
}
for _ , c := range cases {
for _ , file := range c . createFiles {
h . TempFile ( file , "" )
}
got , err := ReadActualFilenames ( tmpPath , c . names )
if err != nil {
t . Fatalf ( "unexpected error: %+v" , err )
}
if ! reflect . DeepEqual ( c . want , got ) {
t . Fatalf ( "returned value does not match expected: \n\t(GOT) %v\n\t(WNT) %v" ,
got , c . want )
}
}
}
func TestGenTestFilename ( t * testing . T ) {
cases := [ ] struct {
str string
want string
} {
{ "abc" , "Abc" } ,
{ "ABC" , "aBC" } ,
{ "AbC" , "abC" } ,
{ "αβγ" , "Αβγ" } ,
{ "123" , "123" } ,
{ "1a2" , "1A2" } ,
{ "12a" , "12A" } ,
{ "⌘" , "⌘" } ,
}
for _ , c := range cases {
got := genTestFilename ( c . str )
if c . want != got {
t . Fatalf ( "str: %q, expected: %q, got: %q" , c . str , c . want , got )
}
}
}
func BenchmarkGenTestFilename ( b * testing . B ) {
cases := [ ] string {
strings . Repeat ( "a" , 128 ) ,
strings . Repeat ( "A" , 128 ) ,
strings . Repeat ( "α " , 128 ) ,
strings . Repeat ( "1" , 128 ) ,
strings . Repeat ( "⌘" , 128 ) ,
}
for i := 0 ; i < b . N ; i ++ {
for _ , str := range cases {
genTestFilename ( str )
}
}
}
func TestCopyDir ( t * testing . T ) {
func TestCopyDir ( t * testing . T ) {
dir , err := ioutil . TempDir ( "" , "dep" )
dir , err := ioutil . TempDir ( "" , "dep" )
if err != nil {
if err != nil {
@ -843,117 +503,6 @@ func setupInaccessibleDir(t *testing.T, op func(dir string) error) func() {
return cleanup
return cleanup
}
}
func TestEnsureDir ( t * testing . T ) {
h := test . NewHelper ( t )
defer h . Cleanup ( )
h . TempDir ( "." )
h . TempFile ( "file" , "" )
tmpPath := h . Path ( "." )
var dn string
cleanup := setupInaccessibleDir ( t , func ( dir string ) error {
dn = filepath . Join ( dir , "dir" )
return os . Mkdir ( dn , 0777 )
} )
defer cleanup ( )
tests := map [ string ] bool {
// [success] A dir already exists for the given path.
tmpPath : true ,
// [success] Dir does not exist but parent dir exists, so should get created.
filepath . Join ( tmpPath , "testdir" ) : true ,
// [failure] Dir and parent dir do not exist, should return an error.
filepath . Join ( tmpPath , "notexist" , "testdir" ) : false ,
// [failure] Regular file present at given path.
h . Path ( "file" ) : false ,
// [failure] Path inaccessible.
dn : false ,
}
if runtime . GOOS == "windows" {
// This test doesn't work on Microsoft Windows because
// of the differences in how file permissions are
// implemented. For this to work, the directory where
// the directory exists should be inaccessible.
delete ( tests , dn )
}
for path , shouldEnsure := range tests {
err := EnsureDir ( path , 0777 )
if shouldEnsure {
if err != nil {
t . Fatalf ( "unexpected error %q for %q" , err , path )
} else if ok , err := IsDir ( path ) ; ! ok {
t . Fatalf ( "expected directory to be preset at %q" , path )
t . Fatal ( err )
}
} else if err == nil {
t . Fatalf ( "expected error for path %q, got none" , path )
}
}
}
func TestIsRegular ( t * testing . T ) {
wd , err := os . Getwd ( )
if err != nil {
t . Fatal ( err )
}
var fn string
cleanup := setupInaccessibleDir ( t , func ( dir string ) error {
fn = filepath . Join ( dir , "file" )
fh , err := os . Create ( fn )
if err != nil {
return err
}
return fh . Close ( )
} )
defer cleanup ( )
tests := map [ string ] struct {
exists bool
err bool
} {
wd : { false , true } ,
filepath . Join ( wd , "testdata" ) : { false , true } ,
filepath . Join ( wd , "testdata" , "test.file" ) : { true , false } ,
filepath . Join ( wd , "this_file_does_not_exist.thing" ) : { false , false } ,
fn : { false , true } ,
}
if runtime . GOOS == "windows" {
// This test doesn't work on Microsoft Windows because
// of the differences in how file permissions are
// implemented. For this to work, the directory where
// the file exists should be inaccessible.
delete ( tests , fn )
}
for f , want := range tests {
got , err := IsRegular ( f )
if err != nil {
if want . exists != got {
t . Fatalf ( "expected %t for %s, got %t" , want . exists , f , got )
}
if ! want . err {
t . Fatalf ( "expected no error, got %v" , err )
}
} else {
if want . err {
t . Fatalf ( "expected error for %s, got none" , f )
}
}
if got != want . exists {
t . Fatalf ( "expected %t for %s, got %t" , want , f , got )
}
}
}
func TestIsDir ( t * testing . T ) {
func TestIsDir ( t * testing . T ) {
wd , err := os . Getwd ( )
wd , err := os . Getwd ( )
if err != nil {
if err != nil {
@ -999,61 +548,6 @@ func TestIsDir(t *testing.T) {
}
}
}
}
func TestIsNonEmptyDir ( t * testing . T ) {
wd , err := os . Getwd ( )
if err != nil {
t . Fatal ( err )
}
h := test . NewHelper ( t )
defer h . Cleanup ( )
h . TempDir ( "empty" )
testCases := [ ] struct {
path string
empty bool
err bool
} {
{ wd , true , false } ,
{ "testdata" , true , false } ,
{ filepath . Join ( wd , "fs.go" ) , false , true } ,
{ filepath . Join ( wd , "this_file_does_not_exist.thing" ) , false , false } ,
{ h . Path ( "empty" ) , false , false } ,
}
// This test case doesn't work on Microsoft Windows because of the
// differences in how file permissions are implemented.
if runtime . GOOS != "windows" {
var inaccessibleDir string
cleanup := setupInaccessibleDir ( t , func ( dir string ) error {
inaccessibleDir = filepath . Join ( dir , "empty" )
return os . Mkdir ( inaccessibleDir , 0777 )
} )
defer cleanup ( )
testCases = append ( testCases , struct {
path string
empty bool
err bool
} { inaccessibleDir , false , true } )
}
for _ , want := range testCases {
got , err := IsNonEmptyDir ( want . path )
if want . err && err == nil {
if got {
t . Fatalf ( "wanted false with error for %v, but got true" , want . path )
}
t . Fatalf ( "wanted an error for %v, but it was nil" , want . path )
}
if got != want . empty {
t . Fatalf ( "wanted %t for %v, but got %t" , want . empty , want . path , got )
}
}
}
func TestIsSymlink ( t * testing . T ) {
func TestIsSymlink ( t * testing . T ) {
dir , err := ioutil . TempDir ( "" , "dep" )
dir , err := ioutil . TempDir ( "" , "dep" )
if err != nil {
if err != nil {