mirror of
https://github.com/netbirdio/netbird.git
synced 2026-09-12 17:59:06 +02:00
The iOS SDK package gets the same platform handle the Android bindings carry: transfers, receiving policy, and per-sender rules on one profile, attached to the engine when the client starts. Payloads are path-based rather than stream-based, since the app group container is readable from both processes, and the platform sink is dropped for the same reason: delivery lands on the filesystem directly. The default destination is seeded in the constructor because the app process opens handles of its own while the extension is down.
183 lines
5.1 KiB
Go
183 lines
5.1 KiB
Go
//go:build ios
|
|
|
|
package NetBirdSDK
|
|
|
|
import (
|
|
"errors"
|
|
"io"
|
|
"os"
|
|
"path/filepath"
|
|
"strings"
|
|
"testing"
|
|
|
|
"github.com/netbirdio/netbird/client/internal/filedrop"
|
|
)
|
|
|
|
func TestPayloadFileReadsFromPath(t *testing.T) {
|
|
path := filepath.Join(t.TempDir(), "greeting.txt")
|
|
if err := os.WriteFile(path, []byte("hello world"), 0o600); err != nil {
|
|
t.Fatalf("write payload: %v", err)
|
|
}
|
|
|
|
payloads := NewFileDropPayloads()
|
|
if err := payloads.AddFile("greeting.txt", 11, "text/plain", path); err != nil {
|
|
t.Fatalf("AddFile: %v", err)
|
|
}
|
|
if payloads.Length() != 1 {
|
|
t.Fatalf("expected 1 payload, got %d", payloads.Length())
|
|
}
|
|
|
|
stream, err := payloads.items[0].Open(0)
|
|
if err != nil {
|
|
t.Fatalf("Open: %v", err)
|
|
}
|
|
got, err := io.ReadAll(stream)
|
|
if err != nil {
|
|
t.Fatalf("ReadAll: %v", err)
|
|
}
|
|
if string(got) != "hello world" {
|
|
t.Fatalf("got %q, want %q", got, "hello world")
|
|
}
|
|
if err := stream.Close(); err != nil {
|
|
t.Fatalf("Close: %v", err)
|
|
}
|
|
}
|
|
|
|
func TestPayloadFileHonoursOffset(t *testing.T) {
|
|
path := filepath.Join(t.TempDir(), "greeting.txt")
|
|
if err := os.WriteFile(path, []byte("hello world"), 0o600); err != nil {
|
|
t.Fatalf("write payload: %v", err)
|
|
}
|
|
|
|
payloads := NewFileDropPayloads()
|
|
if err := payloads.AddFile("greeting.txt", 11, "", path); err != nil {
|
|
t.Fatalf("AddFile: %v", err)
|
|
}
|
|
|
|
stream, err := payloads.items[0].Open(6)
|
|
if err != nil {
|
|
t.Fatalf("Open: %v", err)
|
|
}
|
|
defer stream.Close()
|
|
|
|
got, err := io.ReadAll(stream)
|
|
if err != nil {
|
|
t.Fatalf("ReadAll: %v", err)
|
|
}
|
|
if string(got) != "world" {
|
|
t.Fatalf("got %q, want %q", got, "world")
|
|
}
|
|
}
|
|
|
|
func TestPayloadRejectsMissingPathAndOversizedText(t *testing.T) {
|
|
payloads := NewFileDropPayloads()
|
|
|
|
if err := payloads.AddFile("no-path.bin", 1, "", ""); err == nil {
|
|
t.Fatal("expected an error for a file without a path")
|
|
}
|
|
if err := payloads.AddFile("", 1, "", "/tmp/x"); err == nil {
|
|
t.Fatal("expected an error for an empty file name")
|
|
}
|
|
if err := payloads.AddText("big", strings.Repeat("x", filedrop.MaxInlineTextSize+1)); err == nil {
|
|
t.Fatal("expected an error for oversized text")
|
|
}
|
|
if payloads.Length() != 0 {
|
|
t.Fatalf("expected no payloads, got %d", payloads.Length())
|
|
}
|
|
}
|
|
|
|
func TestFileDropPersistsSettingsPerProfile(t *testing.T) {
|
|
configDir := t.TempDir()
|
|
writeTestProfile(t, configDir, "aaaaaaaabbbbbbbbccccccccdddddddd")
|
|
writeTestProfile(t, configDir, "11111111222222223333333344444444")
|
|
|
|
first, err := NewFileDrop(configDir, "aaaaaaaabbbbbbbbccccccccdddddddd")
|
|
if err != nil {
|
|
t.Fatalf("NewFileDrop: %v", err)
|
|
}
|
|
defer first.Close()
|
|
|
|
if err := first.SetMode(FileDropModeAutoAccept); err != nil {
|
|
t.Fatalf("SetMode: %v", err)
|
|
}
|
|
if err := first.SetPeerRule("peer-key", FileDropRuleBlock); err != nil {
|
|
t.Fatalf("SetPeerRule: %v", err)
|
|
}
|
|
|
|
second, err := NewFileDrop(configDir, "11111111222222223333333344444444")
|
|
if err != nil {
|
|
t.Fatalf("NewFileDrop: %v", err)
|
|
}
|
|
defer second.Close()
|
|
|
|
if got := second.Mode(); got != FileDropModeAsk {
|
|
t.Fatalf("second profile mode = %d, want the default %d", got, FileDropModeAsk)
|
|
}
|
|
if got := second.PeerRule("peer-key"); got != FileDropRuleDefault {
|
|
t.Fatalf("second profile rule = %d, want %d", got, FileDropRuleDefault)
|
|
}
|
|
|
|
reopened, err := NewFileDrop(configDir, "aaaaaaaabbbbbbbbccccccccdddddddd")
|
|
if err != nil {
|
|
t.Fatalf("NewFileDrop: %v", err)
|
|
}
|
|
defer reopened.Close()
|
|
|
|
if got := reopened.Mode(); got != FileDropModeAutoAccept {
|
|
t.Fatalf("reopened mode = %d, want %d", got, FileDropModeAutoAccept)
|
|
}
|
|
if got := reopened.PeerRule("peer-key"); got != FileDropRuleBlock {
|
|
t.Fatalf("reopened rule = %d, want %d", got, FileDropRuleBlock)
|
|
}
|
|
}
|
|
|
|
func TestFileDropSeedsDefaultDestination(t *testing.T) {
|
|
configDir := t.TempDir()
|
|
writeTestProfile(t, configDir, "aaaaaaaabbbbbbbbccccccccdddddddd")
|
|
|
|
fd, err := NewFileDrop(configDir, "aaaaaaaabbbbbbbbccccccccdddddddd")
|
|
if err != nil {
|
|
t.Fatalf("NewFileDrop: %v", err)
|
|
}
|
|
defer fd.Close()
|
|
|
|
want := filepath.Join(configDir, filedropDataSubdir, "aaaaaaaabbbbbbbbccccccccdddddddd", "incoming")
|
|
if got := fd.DestinationDir(); got != want {
|
|
t.Fatalf("destination = %q, want %q", got, want)
|
|
}
|
|
}
|
|
|
|
func TestFileDropSendWithoutTunnelFails(t *testing.T) {
|
|
configDir := t.TempDir()
|
|
writeTestProfile(t, configDir, "aaaaaaaabbbbbbbbccccccccdddddddd")
|
|
|
|
fd, err := NewFileDrop(configDir, "aaaaaaaabbbbbbbbccccccccdddddddd")
|
|
if err != nil {
|
|
t.Fatalf("NewFileDrop: %v", err)
|
|
}
|
|
defer fd.Close()
|
|
|
|
payloads := NewFileDropPayloads()
|
|
if err := payloads.AddText("note", "hi"); err != nil {
|
|
t.Fatalf("AddText: %v", err)
|
|
}
|
|
|
|
if _, err := fd.Send("peer-key", "peer", "100.64.0.2", payloads); !errors.Is(err, filedrop.ErrNotConnected) {
|
|
t.Fatalf("Send error = %v, want %v", err, filedrop.ErrNotConnected)
|
|
}
|
|
if _, err := fd.Send("peer-key", "peer", "100.64.0.2", NewFileDropPayloads()); err == nil {
|
|
t.Fatal("expected an error when there is nothing to send")
|
|
}
|
|
if _, err := fd.Send("peer-key", "peer", "not-an-ip", payloads); err == nil {
|
|
t.Fatal("expected an error for an unparseable peer address")
|
|
}
|
|
}
|
|
|
|
func writeTestProfile(t *testing.T, configDir, id string) {
|
|
t.Helper()
|
|
|
|
if _, err := NewProfileManager(configDir).impl.ProfilePrefs(id); err != nil {
|
|
t.Fatalf("resolve prefs for %s: %v", id, err)
|
|
}
|
|
}
|