tailscale/feature/taildrop/resume_test.go
kari-ts d897d809d6
feature/taildrop: do not use m.opts.Dir for Android (#16316)
In Android, we are prompting the user to select a Taildrop directory when they first receive a Taildrop: we block writes on Taildrop dir selection. This means that we cannot use Dir inside managerOptions, since the http request would not get the new Taildrop extension. This PR removes, in the Android case, the reliance on m.opts.Dir, and instead has FileOps hold the correct directory.

This expands FileOps to be the Taildrop interface for all file system operations.

Updates tailscale/corp#29211

Signed-off-by: kari-ts <kari@tailscale.com>

restore tstest
2025-08-01 15:10:00 -07:00

78 lines
1.9 KiB
Go

// Copyright (c) Tailscale Inc & AUTHORS
// SPDX-License-Identifier: BSD-3-Clause
package taildrop
import (
"bytes"
"io"
"math/rand"
"os"
"path/filepath"
"testing"
"testing/iotest"
"tailscale.com/util/must"
)
func TestResume(t *testing.T) {
oldBlockSize := blockSize
defer func() { blockSize = oldBlockSize }()
blockSize = 256
dir := t.TempDir()
m := managerOptions{Logf: t.Logf, fileOps: must.Get(newFileOps(dir))}.New()
defer m.Shutdown()
rn := rand.New(rand.NewSource(0))
want := make([]byte, 12345)
must.Get(io.ReadFull(rn, want))
t.Run("resume-noexist", func(t *testing.T) {
r := io.Reader(bytes.NewReader(want))
next, close, err := m.HashPartialFile("", "foo")
must.Do(err)
defer close()
offset, r, err := resumeReader(r, next)
must.Do(err)
must.Do(close()) // Windows wants the file handle to be closed to rename it.
must.Get(m.PutFile("", "foo", r, offset, -1))
got := must.Get(os.ReadFile(filepath.Join(dir, "foo")))
if !bytes.Equal(got, want) {
t.Errorf("content mismatches")
}
})
t.Run("resume-retry", func(t *testing.T) {
rn := rand.New(rand.NewSource(0))
for i := 0; true; i++ {
r := io.Reader(bytes.NewReader(want))
next, close, err := m.HashPartialFile("", "bar")
must.Do(err)
defer close()
offset, r, err := resumeReader(r, next)
must.Do(err)
must.Do(close()) // Windows wants the file handle to be closed to rename it.
numWant := rn.Int63n(min(int64(len(want))-offset, 1000) + 1)
if offset < int64(len(want)) {
r = io.MultiReader(io.LimitReader(r, numWant), iotest.ErrReader(io.ErrClosedPipe))
}
if _, err := m.PutFile("", "bar", r, offset, -1); err == nil {
break
}
if i > 1000 {
t.Fatalf("too many iterations to complete the test")
}
}
got := must.Get(os.ReadFile(filepath.Join(dir, "bar")))
if !bytes.Equal(got, want) {
t.Errorf("content mismatches")
}
})
}