Merge remote-tracking branch 'upstream/main' into dev

This commit is contained in:
onysd 2026-07-18 09:19:27 +03:00
commit 6b29556ef8
836 changed files with 1598388 additions and 64684 deletions

View file

@ -35,13 +35,13 @@ func TestLoadDefaultsAdvertiseIPToLoopback(t *testing.T) {
func TestLoadUsesExplicitAdvertiseIP(t *testing.T) {
disableDefaultConfigFile(t)
t.Setenv("TELESRV_ADVERTISE_IP", "203.0.113.10")
t.Setenv("TELESRV_ADVERTISE_IP", "192.0.2.10")
cfg, err := Load()
if err != nil {
t.Fatalf("Load: %v", err)
}
if cfg.AdvertiseIP != "203.0.113.10" {
if cfg.AdvertiseIP != "192.0.2.10" {
t.Fatalf("AdvertiseIP = %q, want explicit env", cfg.AdvertiseIP)
}
}
@ -57,6 +57,13 @@ func TestLoadMTProtoAdmissionAndRPCBudgets(t *testing.T) {
t.Setenv("TELESRV_MTPROTO_RPC_GLOBAL_WORKERS", "33")
t.Setenv("TELESRV_MTPROTO_RPC_GLOBAL_MAX_TASKS", "444")
t.Setenv("TELESRV_MTPROTO_RPC_GLOBAL_MAX_BYTES", "555555")
t.Setenv("TELESRV_MTPROTO_RPC_RESULT_CACHE_MAX_ENTRIES", "555")
t.Setenv("TELESRV_MTPROTO_RPC_RESULT_CACHE_MAX_BYTES", "70000000")
t.Setenv("TELESRV_MTPROTO_RPC_RESULT_CACHE_AUTH_MAX_ENTRIES", "444")
t.Setenv("TELESRV_MTPROTO_RPC_RESULT_CACHE_AUTH_MAX_BYTES", "40000000")
t.Setenv("TELESRV_MTPROTO_RPC_RESULT_CACHE_SESSION_MAX_ENTRIES", "333")
t.Setenv("TELESRV_MTPROTO_RPC_RESULT_CACHE_SESSION_MAX_BYTES", "20000000")
t.Setenv("TELESRV_MTPROTO_RPC_RESULT_PENDING_PER_AUTH", "222")
t.Setenv("TELESRV_MTPROTO_INBOUND_FRAME_GLOBAL_MAX_BYTES", "777777")
t.Setenv("TELESRV_MTPROTO_OUTBOUND_QUEUE_SIZE", "88")
t.Setenv("TELESRV_MTPROTO_OUTBOUND_CONTROL_QUEUE_SIZE", "22")
@ -77,6 +84,16 @@ func TestLoadMTProtoAdmissionAndRPCBudgets(t *testing.T) {
cfg.MTProtoRPCGlobalWorkers != 33 || cfg.MTProtoRPCGlobalMaxTasks != 444 || cfg.MTProtoRPCGlobalMaxBytes != 555555 {
t.Fatalf("rpc budget config = %d/%d/%v/%d/%d/%d", cfg.MTProtoRPCMaxInflight, cfg.MTProtoRPCQueueSize, cfg.MTProtoRPCTimeout, cfg.MTProtoRPCGlobalWorkers, cfg.MTProtoRPCGlobalMaxTasks, cfg.MTProtoRPCGlobalMaxBytes)
}
if cfg.MTProtoRPCResultCacheMaxEntries != 555 || cfg.MTProtoRPCResultCacheMaxBytes != 70000000 ||
cfg.MTProtoRPCResultCacheAuthMaxEntries != 444 || cfg.MTProtoRPCResultCacheAuthMaxBytes != 40000000 ||
cfg.MTProtoRPCResultCacheSessionMaxEntries != 333 || cfg.MTProtoRPCResultCacheSessionMaxBytes != 20000000 ||
cfg.MTProtoRPCResultPendingPerAuth != 222 {
t.Fatalf("rpc result cache config = global:%d/%d auth:%d/%d session:%d/%d pending/auth:%d",
cfg.MTProtoRPCResultCacheMaxEntries, cfg.MTProtoRPCResultCacheMaxBytes,
cfg.MTProtoRPCResultCacheAuthMaxEntries, cfg.MTProtoRPCResultCacheAuthMaxBytes,
cfg.MTProtoRPCResultCacheSessionMaxEntries, cfg.MTProtoRPCResultCacheSessionMaxBytes,
cfg.MTProtoRPCResultPendingPerAuth)
}
if cfg.MTProtoInboundFrameGlobalMaxBytes != 777777 {
t.Fatalf("inbound frame budget config = %d", cfg.MTProtoInboundFrameGlobalMaxBytes)
}
@ -88,6 +105,46 @@ func TestLoadMTProtoAdmissionAndRPCBudgets(t *testing.T) {
}
}
func TestLoadRPCResultFairBudgetDefaults(t *testing.T) {
disableDefaultConfigFile(t)
cfg, err := Load()
if err != nil {
t.Fatalf("Load: %v", err)
}
if cfg.MTProtoRPCResultCacheMaxEntries != 1<<18 || cfg.MTProtoRPCResultCacheMaxBytes != 64<<20 ||
cfg.MTProtoRPCResultCacheAuthMaxEntries != 1<<15 || cfg.MTProtoRPCResultCacheAuthMaxBytes != 32<<20 ||
cfg.MTProtoRPCResultCacheSessionMaxEntries != 1<<14 || cfg.MTProtoRPCResultCacheSessionMaxBytes != 16<<20 ||
cfg.MTProtoRPCResultPendingPerAuth != 1<<11 {
t.Fatalf("rpc_result fair defaults = global:%d/%d auth:%d/%d session:%d/%d pending/auth:%d",
cfg.MTProtoRPCResultCacheMaxEntries, cfg.MTProtoRPCResultCacheMaxBytes,
cfg.MTProtoRPCResultCacheAuthMaxEntries, cfg.MTProtoRPCResultCacheAuthMaxBytes,
cfg.MTProtoRPCResultCacheSessionMaxEntries, cfg.MTProtoRPCResultCacheSessionMaxBytes,
cfg.MTProtoRPCResultPendingPerAuth)
}
}
func TestLoadRejectsInvalidRPCResultFairBudgets(t *testing.T) {
tests := []struct {
name string
key string
value string
}{
{name: "entry hierarchy", key: "TELESRV_MTPROTO_RPC_RESULT_CACHE_MAX_ENTRIES", value: "1024"},
{name: "byte below outbound body", key: "TELESRV_MTPROTO_RPC_RESULT_CACHE_SESSION_MAX_BYTES", value: "16700000"},
{name: "byte hierarchy", key: "TELESRV_MTPROTO_RPC_RESULT_CACHE_AUTH_MAX_BYTES", value: "70000000"},
{name: "pending hierarchy", key: "TELESRV_MTPROTO_RPC_RESULT_PENDING_PER_AUTH", value: "9000"},
}
for _, test := range tests {
t.Run(test.name, func(t *testing.T) {
disableDefaultConfigFile(t)
t.Setenv(test.key, test.value)
if _, err := Load(); err == nil {
t.Fatalf("Load accepted invalid %s=%s", test.key, test.value)
}
})
}
}
func TestLoadOutboxPoisonPolicy(t *testing.T) {
disableDefaultConfigFile(t)
t.Setenv("TELESRV_OUTBOX_POISON_RETENTION", "2m")
@ -142,6 +199,7 @@ func TestLoadLoginEmailDefaultsDisabled(t *testing.T) {
t.Fatal("LoginEmailRequireSetup = true, want false")
}
if cfg.AuthCodeTTL != 5*time.Minute || cfg.AuthCodeMaxAttempts != 5 || cfg.LoginEmailCodeLength != 6 ||
cfg.PhoneCodeLength != 5 || cfg.PhoneCodeDeliveryProvider != "development" || cfg.EmailCodeDeliveryProvider != "smtp" ||
cfg.AuthCodePhoneRateLimit != 5 || cfg.AuthCodeAuthKeyRateLimit != 20 || cfg.AuthCodeRateWindow != 10*time.Minute {
t.Fatalf("auth/login email defaults = ttl=%v attempts=%d length=%d phone_limit=%d key_limit=%d window=%v",
cfg.AuthCodeTTL, cfg.AuthCodeMaxAttempts, cfg.LoginEmailCodeLength,
@ -194,6 +252,84 @@ func TestLoadLoginEmailRequiresSMTPWhenEnabled(t *testing.T) {
}
}
func TestLoadLoginEmailWebhookDoesNotRequireSMTP(t *testing.T) {
disableDefaultConfigFile(t)
t.Setenv("TELESRV_LOGIN_EMAIL_ENABLE", "true")
t.Setenv("TELESRV_EMAIL_CODE_DELIVERY_PROVIDER", "webhook")
t.Setenv("TELESRV_OTP_WEBHOOK_URL", "https://otp.example.test/v1/deliveries")
t.Setenv("TELESRV_OTP_WEBHOOK_SECRET", "test-secret")
t.Setenv("TELESRV_OTP_WEBHOOK_TIMEOUT", "3s")
t.Setenv("TELESRV_SMTP_HOST", "")
cfg, err := Load()
if err != nil {
t.Fatalf("Load: %v", err)
}
if cfg.EmailCodeDeliveryProvider != "webhook" || cfg.OTPWebhookURL != "https://otp.example.test/v1/deliveries" ||
cfg.OTPWebhookSecret != "test-secret" || cfg.OTPWebhookTimeout != 3*time.Second {
t.Fatalf("webhook config = %#v", cfg)
}
}
// TestLoadEmailSignupAloneRequiresSMTPWhenEnabled asserts that
// TELESRV_EMAIL_SIGNUP_ENABLE=true still requires a configured delivery
// channel even when TELESRV_LOGIN_EMAIL_ENABLE is off. Email-signup accounts
// share the same loginEmailSender/SMTP-or-webhook config as login email (see
// Config.EmailSignupEnable doc); the two features must gate identically, or
// an email-signup-only deployment would silently skip this validation and
// only find out at runtime that sendChangePhoneCodeByEmail/SendCode have a
// nil sender.
func TestLoadEmailSignupAloneRequiresSMTPWhenEnabled(t *testing.T) {
disableDefaultConfigFile(t)
t.Setenv("TELESRV_EMAIL_SIGNUP_ENABLE", "true")
t.Setenv("TELESRV_SMTP_HOST", "")
if _, err := Load(); err == nil {
t.Fatal("Load succeeded with email signup enabled but no SMTP host and no webhook provider")
}
}
// TestLoadEmailSignupAloneWebhookDoesNotRequireSMTP mirrors
// TestLoadLoginEmailWebhookDoesNotRequireSMTP for the email-signup-only case.
func TestLoadEmailSignupAloneWebhookDoesNotRequireSMTP(t *testing.T) {
disableDefaultConfigFile(t)
t.Setenv("TELESRV_EMAIL_SIGNUP_ENABLE", "true")
t.Setenv("TELESRV_EMAIL_CODE_DELIVERY_PROVIDER", "webhook")
t.Setenv("TELESRV_OTP_WEBHOOK_URL", "https://otp.example.test/v1/deliveries")
t.Setenv("TELESRV_OTP_WEBHOOK_SECRET", "test-secret")
t.Setenv("TELESRV_OTP_WEBHOOK_TIMEOUT", "3s")
t.Setenv("TELESRV_SMTP_HOST", "")
if _, err := Load(); err != nil {
t.Fatalf("Load: %v", err)
}
}
func TestLoadPhoneWebhookRequiresValidURL(t *testing.T) {
disableDefaultConfigFile(t)
t.Setenv("TELESRV_PHONE_CODE_DELIVERY_PROVIDER", "webhook")
t.Setenv("TELESRV_OTP_WEBHOOK_URL", "relative/path")
if _, err := Load(); err == nil {
t.Fatal("Load succeeded with relative OTP webhook URL")
}
}
func TestLoadPhoneWebhookConfig(t *testing.T) {
disableDefaultConfigFile(t)
t.Setenv("TELESRV_PHONE_CODE_DELIVERY_PROVIDER", "webhook")
t.Setenv("TELESRV_PHONE_CODE_LENGTH", "7")
t.Setenv("TELESRV_OTP_WEBHOOK_URL", "http://127.0.0.1:8080/otp")
cfg, err := Load()
if err != nil {
t.Fatalf("Load: %v", err)
}
if cfg.PhoneCodeDeliveryProvider != "webhook" || cfg.PhoneCodeLength != 7 {
t.Fatalf("phone webhook config = %#v", cfg)
}
}
func TestLoadKeepsAdminAndRtmpDefaultPortsSeparate(t *testing.T) {
disableDefaultConfigFile(t)
t.Setenv("TELESRV_ADMIN_UI_ADDR", "")