src/webcli/webcli_test.go
Rama main · réplica de lectura del repositorio original.
package webcli
import (
"context"
"os"
"reflect"
"strings"
"testing"
"time"
internalcli "github.com/schollz/croc/v11/internal/cli"
)
func TestStoreUploadEnvironmentConfiguration(t *testing.T) {
for _, tc := range []struct {
name string
env bool
args []string
rate int
active int
timeout time.Duration
proxies []string
}{
{name: "defaults", rate: 5, active: 2, timeout: 5 * time.Minute},
{name: "environment", env: true, rate: 60, active: 10, timeout: 2 * time.Minute, proxies: []string{"10.0.1.3/32", "::1/128"}},
{name: "flags override environment", env: true, args: []string{"--store-create-rate", "12", "--store-active-uploads", "3", "--store-upload-timeout", "30s", "--store-trusted-proxy", "127.0.0.1/32", "--store-trusted-proxy", "192.0.2.1/32"}, rate: 12, active: 3, timeout: 30 * time.Second, proxies: []string{"127.0.0.1/32", "192.0.2.1/32"}},
} {
t.Run(tc.name, func(t *testing.T) {
for key, value := range map[string]string{
"CROC_STORE_CREATE_RATE": "60", "CROC_STORE_ACTIVE_UPLOADS": "10",
"CROC_STORE_UPLOAD_TIMEOUT": "2m", "CROC_STORE_TRUSTED_PROXY": "10.0.1.3/32, ::1/128",
} {
t.Setenv(key, value)
if !tc.env {
if err := os.Unsetenv(key); err != nil {
t.Fatal(err)
}
}
}
app := newApp(context.Background())
app.Action = func(ctx *internalcli.Context) error {
if got := ctx.Int("store-create-rate"); got != tc.rate {
t.Errorf("create rate = %d, want %d", got, tc.rate)
}
if got := ctx.Int("store-active-uploads"); got != tc.active {
t.Errorf("active uploads = %d, want %d", got, tc.active)
}
if got := ctx.Duration("store-upload-timeout"); got != tc.timeout {
t.Errorf("upload timeout = %s, want %s", got, tc.timeout)
}
if got := ctx.StringSlice("store-trusted-proxy"); !reflect.DeepEqual(got, tc.proxies) {
t.Errorf("proxies = %v, want %v", got, tc.proxies)
}
return nil
}
if err := app.Run(append([]string{"croc-web"}, tc.args...)); err != nil {
t.Fatal(err)
}
})
}
}
func TestStoreUploadConfigurationValidation(t *testing.T) {
for _, tc := range []struct{ flag, value, message string }{
{"store-create-rate", "0", "--store-create-rate must be positive"},
{"store-create-rate", "-1", "--store-create-rate must be positive"},
{"store-active-uploads", "0", "--store-active-uploads must be positive"},
{"store-active-uploads", "-1", "--store-active-uploads must be positive"},
{"store-upload-timeout", "0s", "--store-upload-timeout must be positive"},
{"store-upload-timeout", "-1s", "--store-upload-timeout must be positive"},
{"store-trusted-proxy", "10.0.1.3", "invalid --store-trusted-proxy"},
} {
t.Run(tc.flag+"="+tc.value, func(t *testing.T) {
err := newApp(context.Background()).Run([]string{"croc-web", "--store-dir", t.TempDir(), "--" + tc.flag, tc.value})
if err == nil || !strings.Contains(err.Error(), tc.message) {
t.Fatalf("unexpected error: %v", err)
}
})
}
}
func TestAppIdentityAndArguments(t *testing.T) {
app := newApp(context.Background())
if app.Name != "croc-web" {
t.Fatalf("app name = %q, want croc-web", app.Name)
}
if err := app.Run([]string{"croc-web", "one.example", "two.example"}); err == nil {
t.Fatal("multiple public addresses unexpectedly succeeded")
}
}
func TestStoreDownloadsFlagParsing(t *testing.T) {
for _, testCase := range []struct {
name string
args []string
want int
}{
{name: "default", args: []string{"croc-web"}, want: 1},
{name: "custom", args: []string{"croc-web", "--store-downloads", "6"}, want: 6},
} {
t.Run(testCase.name, func(t *testing.T) {
t.Setenv("CROC_STORE_DOWNLOADS", "")
app := newApp(context.Background())
var got int
app.Action = func(ctx *internalcli.Context) error {
got = ctx.Int("store-downloads")
return nil
}
if err := app.Run(testCase.args); err != nil {
t.Fatalf("parse store downloads: %v", err)
}
if got != testCase.want {
t.Fatalf("store downloads = %d, want %d", got, testCase.want)
}
})
}
}
func TestStoreDownloadsEnvironmentConfiguration(t *testing.T) {
t.Setenv("CROC_STORE_DOWNLOADS", "12")
app := newApp(context.Background())
var got int
app.Action = func(ctx *internalcli.Context) error {
got = ctx.Int("store-downloads")
return nil
}
if err := app.Run([]string{"croc-web"}); err != nil {
t.Fatalf("parse store downloads environment: %v", err)
}
if got != 12 {
t.Fatalf("store downloads = %d, want 12", got)
}
}
func TestStoreDownloadsMustBePositiveWhenStorageIsEnabled(t *testing.T) {
err := newApp(context.Background()).Run([]string{
"croc-web",
"--store-dir", t.TempDir(),
"--store-downloads", "0",
})
if err == nil || err.Error() != "--store-downloads must be positive" {
t.Fatalf("unexpected error: %v", err)
}
}
func TestStoreMaxExpirationConfiguration(t *testing.T) {
t.Run("default is unlimited", func(t *testing.T) {
t.Setenv("CROC_STORE_MAX_EXPIRATION", "")
if err := os.Unsetenv("CROC_STORE_MAX_EXPIRATION"); err != nil {
t.Fatal(err)
}
app := newApp(context.Background())
var got string
app.Action = func(ctx *internalcli.Context) error {
got = ctx.String("store-max-expiration")
return nil
}
if err := app.Run([]string{"croc-web"}); err != nil {
t.Fatal(err)
}
if got != "0" {
t.Fatalf("store max expiration = %q, want 0", got)
}
})
t.Run("environment", func(t *testing.T) {
t.Setenv("CROC_STORE_MAX_EXPIRATION", "2w")
app := newApp(context.Background())
var got string
app.Action = func(ctx *internalcli.Context) error {
got = ctx.String("store-max-expiration")
return nil
}
if err := app.Run([]string{"croc-web"}); err != nil {
t.Fatal(err)
}
if got != "2w" {
t.Fatalf("store max expiration = %q, want 2w", got)
}
})
t.Run("flag overrides environment", func(t *testing.T) {
t.Setenv("CROC_STORE_MAX_EXPIRATION", "2w")
app := newApp(context.Background())
var got string
app.Action = func(ctx *internalcli.Context) error {
got = ctx.String("store-max-expiration")
return nil
}
if err := app.Run([]string{"croc-web", "--store-max-expiration", "3d"}); err != nil {
t.Fatal(err)
}
if got != "3d" {
t.Fatalf("store max expiration = %q, want 3d", got)
}
})
}
func TestStoreMaxExpirationValidation(t *testing.T) {
for _, value := range []string{"30s", "0m", "-1h"} {
t.Run(value, func(t *testing.T) {
err := newApp(context.Background()).Run([]string{
"croc-web",
"--store-dir", t.TempDir(),
"--store-max-expiration", value,
})
if err == nil || !strings.Contains(err.Error(), "invalid --store-max-expiration") {
t.Fatalf("unexpected error: %v", err)
}
})
}
}
func TestParseRelayPorts(t *testing.T) {
tests := map[string][]string{
"9009,9010,9011": {"9009", "9010", "9011"},
"9009, 9010, 9011": {"9009", "9010", "9011"},
" 9009 ,, 9010 ,": {"9009", "9010"},
"9009": {"9009"},
"": nil,
}
for input, expected := range tests {
if actual := parseRelayPorts(input); !reflect.DeepEqual(actual, expected) {
t.Fatalf("parseRelayPorts(%q) = %#v, want %#v", input, actual, expected)
}
}
}
func TestParseRelayHosts(t *testing.T) {
assertions := map[string][]string{
"1.getcroc.com,2.getcroc.com,3.getcroc.com,4.getcroc.com": {"1.getcroc.com", "2.getcroc.com", "3.getcroc.com", "4.getcroc.com"},
" relay.example ,, backup.example ": {"relay.example", "backup.example"},
"": nil,
}
for input, expected := range assertions {
if actual := parseRelayHosts(input); !reflect.DeepEqual(actual, expected) {
t.Fatalf("parseRelayHosts(%q) = %#v, want %#v", input, actual, expected)
}
}
}
func TestResolveServeAddress(t *testing.T) {
tests := []struct {
name string
publicAddress string
bindAddress string
bindExplicit bool
wantBind string
wantOrigin string
wantError bool
}{
{name: "defaults", bindAddress: "127.0.0.1:9014", wantBind: "127.0.0.1:9014", wantOrigin: "localhost:5173"},
{name: "public host uses default bind", publicAddress: "getcroc.com", bindAddress: "127.0.0.1:9014", wantBind: "127.0.0.1:9014", wantOrigin: "getcroc.com"},
{name: "local development host binds directly", publicAddress: "localhost:5173", bindAddress: "127.0.0.1:9014", wantBind: "localhost:5173", wantOrigin: "localhost:5173"},
{name: "explicit bind wins for local host", publicAddress: "localhost:5173", bindAddress: "0.0.0.0:8080", bindExplicit: true, wantBind: "0.0.0.0:8080", wantOrigin: "localhost:5173"},
{name: "loopback IP binds directly", publicAddress: "127.0.0.1:7000", bindAddress: "127.0.0.1:9014", wantBind: "127.0.0.1:7000", wantOrigin: "127.0.0.1:7000"},
{name: "rejects URL", publicAddress: "https://getcroc.com", bindAddress: "127.0.0.1:9014", wantError: true},
{name: "rejects invalid public port", publicAddress: "localhost:not-a-port", bindAddress: "127.0.0.1:9014", wantError: true},
{name: "rejects invalid bind", publicAddress: "getcroc.com", bindAddress: "localhost", bindExplicit: true, wantError: true},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
gotBind, gotOrigin, err := resolveServeAddress(tt.publicAddress, tt.bindAddress, tt.bindExplicit)
if tt.wantError {
if err == nil {
t.Fatal("expected an error")
}
return
}
if err != nil {
t.Fatalf("unexpected error: %v", err)
}
if gotBind != tt.wantBind {
t.Fatalf("bind = %q, want %q", gotBind, tt.wantBind)
}
if gotOrigin != tt.wantOrigin {
t.Fatalf("origin = %q, want %q", gotOrigin, tt.wantOrigin)
}
})
}
}
func TestParseByteSize(t *testing.T) {
tests := map[string]int64{
"1": 1,
"512MiB": 512 << 20,
"5GB": 5_000_000_000,
"2 GiB": 2 << 30,
}
for input, expected := range tests {
actual, err := parseByteSize(input)
if err != nil {
t.Fatalf("parseByteSize(%q): %v", input, err)
}
if actual != expected {
t.Fatalf("parseByteSize(%q) = %d, want %d", input, actual, expected)
}
}
for _, input := range []string{"", "-1", "1.5GiB", "999999999999999999999TiB"} {
if _, err := parseByteSize(input); err == nil {
t.Fatalf("parseByteSize(%q) unexpectedly succeeded", input)
}
}
}
func TestDeterminePassReadsFilesAndTrims(t *testing.T) {
path := t.TempDir() + "/pass"
if err := os.WriteFile(path, []byte("secret\n"), 0o600); err != nil {
t.Fatal(err)
}
if actual := determinePass(path); actual != "secret" {
t.Fatalf("password = %q, want secret", actual)
}
}