| 1 | package pathidentity |
| 2 | |
| 3 | import ( |
| 4 | "errors" |
| 5 | "fmt" |
| 6 | "syscall" |
| 7 | "testing" |
| 8 | ) |
| 9 | |
| 10 | func TestDarwinIdentityKeyToleratesVolumesThatDoNotAnswer(t *testing.T) { |
| 11 | const path = "/Volumes/remote/Proj/Café.go" |
| 12 | fixed := func(value string, err error) func(string) (string, error) { |
| 13 | return func(string) (string, error) { return value, err } |
| 14 | } |
| 15 | pathconf := func(value int, err error) func(string) (int, error) { |
| 16 | return func(string) (int, error) { return value, err } |
| 17 | } |
| 18 | cases := []struct { |
| 19 | name string |
| 20 | volume darwinVolume |
| 21 | want string |
| 22 | }{ |
| 23 | {"fuse pathconf EINVAL", darwinVolume{fixed("macfuse", nil), pathconf(-1, syscall.EINVAL)}, path}, |
| 24 | {"fuse pathconf ENOTSUP", darwinVolume{fixed("macfuse", nil), pathconf(-1, fmt.Errorf("pathconf: %w", syscall.ENOTSUP))}, path}, |
| 25 | {"statfs failure", darwinVolume{fixed("", syscall.EIO), pathconf(1, nil)}, path}, |
| 26 | {"case-insensitive apfs", darwinVolume{fixed("apfs", nil), pathconf(0, nil)}, "/volumes/remote/proj/café.go"}, |
| 27 | } |
| 28 | for _, tc := range cases { |
| 29 | t.Run(tc.name, func(t *testing.T) { |
| 30 | got, err := darwinIdentityKeyBy(path, "/Volumes/remote", tc.volume) |
| 31 | if err != nil { |
| 32 | t.Fatalf("identity key failed: %v", err) |
| 33 | } |
| 34 | if got != tc.want { |
| 35 | t.Fatalf("identity key = %q, want %q", got, tc.want) |
| 36 | } |
| 37 | }) |
| 38 | } |
| 39 | } |
| 40 | |
| 41 | func TestDarwinIdentityKeyKeepsOtherPathconfFailures(t *testing.T) { |
| 42 | volume := darwinVolume{ |
| 43 | fsType: func(string) (string, error) { return "apfs", nil }, |
| 44 | caseSensitive: func(string) (int, error) { return -1, syscall.EACCES }, |
| 45 | } |
| 46 | if _, err := darwinIdentityKeyBy("/p", "/", volume); !errors.Is(err, syscall.EACCES) { |
| 47 | t.Fatalf("error = %v, want EACCES", err) |
| 48 | } |
| 49 | } |
| 50 |