Something went wrong. Try again.
forked from tailscale/tailscale
Something went wrong. Try again.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115// Copyright (c) Tailscale Inc & contributors// SPDX-License-Identifier: BSD-3-Clause
package driveimpl
import ( "os" "path/filepath" "testing"
"tailscale.com/drive")
// Unicode filenames from https://github.com/tailscale/tailscale/issues/15020,// in both NFC (precomposed) and NFD (decomposed) forms. The two forms are// canonically equivalent but byte-wise different, so on// normalization-sensitive filesystems like ext4 they name different files.const ( nfcName = "\u30c6\u30ba\u30c8 \u00e4.wav" // テズト ä.wav, precomposed nfdName = "\u30c6\u30b9\u3099\u30c8 a\u0308.wav" // same name, decomposed nfcDir = "\u30ae\u30bf\u30fc" // ギター, precomposed nfdDir = "\u30ad\u3099\u30bf\u30fc" // same name, decomposed)
// TestUnicodeRoundTrip verifies that a file written via WebDAV with a// non-ASCII name can be statted and read back with the identical name.func TestUnicodeRoundTrip(t *testing.T) { s := newSystem(t) s.addRemote(remote1) s.addShare(remote1, share11, drive.PermissionReadWrite)
s.writeFile("writing unicode file should succeed", remote1, share11, nfcName, "hello", true) s.checkFileStatus(remote1, share11, nfcName) s.checkFileContents(remote1, share11, nfcName)}
// TestUnicodeNormalizationMismatch verifies that a file whose on-disk name is// in one Unicode normalization form can be read, statted and overwritten via// WebDAV using a canonically equivalent name in the other form. This is what// happens when a macOS WebDAV client (which sends NFD paths) accesses a share// with NFC filenames on disk, and vice versa.func TestUnicodeNormalizationMismatch(t *testing.T) { tests := []struct { name string onDisk, viaRequest string }{ {"nfc-on-disk-nfd-request", nfcName, nfdName}, {"nfd-on-disk-nfc-request", nfdName, nfcName}, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { s := newSystem(t) s.addRemote(remote1) s.addShare(remote1, share11, drive.PermissionReadWrite)
// Write the file directly to disk with one form, then read and // stat it via WebDAV using the other form. s.write(remote1, share11, tt.onDisk, "hello world") if got := s.readViaWebDAV(remote1, share11, tt.viaRequest); got != "hello world" { t.Errorf("read: got %q, want %q", got, "hello world") } s.statViaWebDAV(remote1, share11, tt.viaRequest)
// Overwriting via the other form must update the existing file // rather than creating a second one. s.writeFile("overwrite with equivalent name should succeed", remote1, share11, tt.viaRequest, "updated", true) if got := s.read(remote1, share11, tt.onDisk); got != "updated" { t.Errorf("read from disk after overwrite: got %q, want %q", got, "updated") } shareDir := s.remotes[remote1].shares[share11] entries, err := os.ReadDir(shareDir) if err != nil { t.Fatal(err) } if len(entries) != 1 { t.Errorf("got %d files on disk, want 1: %q", len(entries), entries) } }) }}
// TestUnicodeNormalizationMismatchInDir is like// TestUnicodeNormalizationMismatch, but with the mismatch in a directory// component of the path rather than in the filename.func TestUnicodeNormalizationMismatchInDir(t *testing.T) { s := newSystem(t) s.addRemote(remote1) s.addShare(remote1, share11, drive.PermissionReadWrite)
shareDir := s.remotes[remote1].shares[share11] if err := os.Mkdir(filepath.Join(shareDir, nfcDir), 0755); err != nil { t.Fatal(err) } s.write(remote1, share11, filepath.Join(nfcDir, nfcName), "hello world")
got := s.readViaWebDAV(remote1, share11, nfdDir+"/"+nfdName) if got != "hello world" { t.Errorf("read: got %q, want %q", got, "hello world") }}
// TestUnicodeNewFileKeepsRequestedName verifies that creating a new file// keeps the exact bytes of the name that the client sent when no equivalent// file exists yet.func TestUnicodeNewFileKeepsRequestedName(t *testing.T) { s := newSystem(t) s.addRemote(remote1) s.addShare(remote1, share11, drive.PermissionReadWrite)
s.writeFile("writing new NFD file should succeed", remote1, share11, nfdName, "hello", true) if got := s.read(remote1, share11, nfdName); got != "hello" { t.Errorf("read from disk: got %q, want %q", got, "hello") }}