mirror of
https://github.com/MHSanaei/3x-ui.git
synced 2026-11-12 08:05:00 +03:00
perf(tests): copy a migrated template DB instead of migrating per test
Most tests opened a throwaway panel DB with database.InitDB, which runs the full AutoMigrate + seed on an empty file every time: ~230ms, and ~850ms under -race because GORM's reflection-heavy migration is what the detector slows most. internal/web/service does this in ~550 of its 830 tests, so the CI race job spent ~10 of its ~14.6 minutes re-migrating empty databases. internal/database/dbtest.InitDB migrates once per test process, then hands each test its own copy of that file (~130ms under -race) and registers the CloseDB cleanup. The copy then goes through InitDB like a panel restart, so every test still starts from the state a fresh install has. Tests that reopen an existing file, migrate a hand-built legacy DB or target Postgres keep calling database.InitDB. Locally under -race: internal/web/service 626s (last CI run) -> 114s, internal/sub 246s -> 35s.
This commit is contained in:
@@ -100,8 +100,8 @@ question it already answers.
|
|||||||
subtests and `t.Helper()` on helpers. An assertion must pin the exact value,
|
subtests and `t.Helper()` on helpers. An assertion must pin the exact value,
|
||||||
typed error or emitted string — `err != nil` and `len(x) > 0` are findings,
|
typed error or emitted string — `err != nil` and `len(x) > 0` are findings,
|
||||||
not nits. Prefer real dependencies: a throwaway DB via
|
not nits. Prefer real dependencies: a throwaway DB via
|
||||||
`database.InitDB(filepath.Join(t.TempDir(), "x-ui.db"))` with `t.Cleanup`, and
|
`dbtest.InitDB(t, filepath.Join(t.TempDir(), "x-ui.db"))`
|
||||||
`httptest` for HTTP. `internal/sub`'s `initSubDB(t)` is the template.
|
(`internal/database/dbtest`), and `httptest` for HTTP. `internal/sub`'s `initSubDB(t)` is the template.
|
||||||
A test must FAIL without its fix; one that passes either way certifies
|
A test must FAIL without its fix; one that passes either way certifies
|
||||||
nothing and then gets cited as proof the fix works.
|
nothing and then gets cited as proof the fix works.
|
||||||
|
|
||||||
|
|||||||
@@ -154,9 +154,11 @@ file locations when it can answer in one hop.
|
|||||||
- Stdlib `testing` only (no testify). Table-driven, `t.Run` subtests,
|
- Stdlib `testing` only (no testify). Table-driven, `t.Run` subtests,
|
||||||
`t.Helper()` on helpers. Assert the exact value / typed error / emitted
|
`t.Helper()` on helpers. Assert the exact value / typed error / emitted
|
||||||
string, never just `err != nil`. Prefer real deps over mocks: throwaway DB via
|
string, never just `err != nil`. Prefer real deps over mocks: throwaway DB via
|
||||||
`database.InitDB(filepath.Join(t.TempDir(), "x-ui.db"))` +
|
`dbtest.InitDB(t, filepath.Join(t.TempDir(), "x-ui.db"))`
|
||||||
`t.Cleanup(func() { _ = database.CloseDB() })`; `httptest` for HTTP.
|
(`internal/database/dbtest`: copies a once-migrated template and registers
|
||||||
`internal/sub`'s `initSubDB(t)` is the template.
|
`CloseDB` cleanup; a fresh `database.InitDB` costs ~7x more, ~850ms under
|
||||||
|
`-race`); `httptest` for HTTP. Keep `database.InitDB` for reopening a file or
|
||||||
|
migrating a hand-built legacy DB. `internal/sub`'s `initSubDB(t)` is the template.
|
||||||
- Code must pass `golangci-lint run` (gofumpt + goimports formatting): `make lint`.
|
- Code must pass `golangci-lint run` (gofumpt + goimports formatting): `make lint`.
|
||||||
- Postgres, xray-gRPC-e2e and scale tests `t.Skip` unless `XUI_TEST_PG_DSN`,
|
- Postgres, xray-gRPC-e2e and scale tests `t.Skip` unless `XUI_TEST_PG_DSN`,
|
||||||
`XUI_DB_TYPE`+`XUI_DB_DSN`, `XRAY_E2E_BINARY` or `XUI_SCALE_TEST` is set — a
|
`XUI_DB_TYPE`+`XUI_DB_DSN`, `XRAY_E2E_BINARY` or `XUI_SCALE_TEST` is set — a
|
||||||
|
|||||||
+1
-1
@@ -253,7 +253,7 @@ Tests live next to the code (`foo.go` ↔ `foo_test.go`); frontend specs and gol
|
|||||||
|
|
||||||
- **Stdlib `testing` only** — no testify. Table-driven with `t.Run` subtests and `t.Helper()` on helpers.
|
- **Stdlib `testing` only** — no testify. Table-driven with `t.Run` subtests and `t.Helper()` on helpers.
|
||||||
- **Assert the contract, not internals.** Pin the exact value / typed error / emitted string — not `err != nil` or `len > 0`. A test that still passes when the behavior is broken is worse than no test.
|
- **Assert the contract, not internals.** Pin the exact value / typed error / emitted string — not `err != nil` or `len > 0`. A test that still passes when the behavior is broken is worse than no test.
|
||||||
- **Real dependencies over mocks.** Get a throwaway DB with `database.InitDB(filepath.Join(t.TempDir(), "x-ui.db"))` + `t.Cleanup(func() { _ = database.CloseDB() })` (Windows-safe), and use `httptest` servers for HTTP. The `internal/sub` suite's `initSubDB(t)` is the template.
|
- **Real dependencies over mocks.** Get a throwaway DB with `dbtest.InitDB(t, filepath.Join(t.TempDir(), "x-ui.db"))` from `internal/database/dbtest`: it copies a once-migrated template (migrating from scratch per test is ~7x slower, worst under `-race`) and closes the DB before `t.TempDir` cleanup (Windows-safe). Keep `database.InitDB` for reopening an existing file or migrating a hand-built legacy DB. Use `httptest` servers for HTTP. The `internal/sub` suite's `initSubDB(t)` is the template.
|
||||||
|
|
||||||
### Running
|
### Running
|
||||||
|
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ import (
|
|||||||
|
|
||||||
"github.com/mhsanaei/3x-ui/v3/internal/config"
|
"github.com/mhsanaei/3x-ui/v3/internal/config"
|
||||||
"github.com/mhsanaei/3x-ui/v3/internal/database"
|
"github.com/mhsanaei/3x-ui/v3/internal/database"
|
||||||
|
"github.com/mhsanaei/3x-ui/v3/internal/database/dbtest"
|
||||||
"github.com/mhsanaei/3x-ui/v3/internal/database/model"
|
"github.com/mhsanaei/3x-ui/v3/internal/database/model"
|
||||||
"github.com/mhsanaei/3x-ui/v3/internal/web/service/panel"
|
"github.com/mhsanaei/3x-ui/v3/internal/web/service/panel"
|
||||||
)
|
)
|
||||||
@@ -16,10 +17,7 @@ import (
|
|||||||
func newTokenCLIEnv(t *testing.T) {
|
func newTokenCLIEnv(t *testing.T) {
|
||||||
t.Helper()
|
t.Helper()
|
||||||
t.Setenv("XUI_DB_FOLDER", t.TempDir())
|
t.Setenv("XUI_DB_FOLDER", t.TempDir())
|
||||||
if err := database.InitDB(config.GetDBPath()); err != nil {
|
dbtest.InitDB(t, config.GetDBPath())
|
||||||
t.Fatalf("init db: %v", err)
|
|
||||||
}
|
|
||||||
t.Cleanup(func() { _ = database.CloseDB() })
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func tokenNames(t *testing.T) []string {
|
func tokenNames(t *testing.T) []string {
|
||||||
|
|||||||
@@ -0,0 +1,67 @@
|
|||||||
|
// Package dbtest opens throwaway panel databases for tests. Migrating a new
|
||||||
|
// SQLite file costs ~850ms under -race; copying a migrated template ~130ms.
|
||||||
|
package dbtest
|
||||||
|
|
||||||
|
import (
|
||||||
|
"os"
|
||||||
|
"path/filepath"
|
||||||
|
"sync"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/mhsanaei/3x-ui/v3/internal/config"
|
||||||
|
"github.com/mhsanaei/3x-ui/v3/internal/database"
|
||||||
|
)
|
||||||
|
|
||||||
|
var migrated struct {
|
||||||
|
once sync.Once
|
||||||
|
data []byte
|
||||||
|
err error
|
||||||
|
}
|
||||||
|
|
||||||
|
// InitDB opens a new, fully migrated panel database at path and closes it when
|
||||||
|
// t ends. Reopen an existing file with database.InitDB instead.
|
||||||
|
func InitDB(t testing.TB, path string) {
|
||||||
|
t.Helper()
|
||||||
|
if config.GetDBKind() != "postgres" {
|
||||||
|
if _, err := os.Stat(path); err == nil {
|
||||||
|
t.Fatalf("dbtest.InitDB would overwrite existing %s; reopen it with database.InitDB", path)
|
||||||
|
}
|
||||||
|
data, err := migratedTemplate()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("build template database: %v", err)
|
||||||
|
}
|
||||||
|
if err := os.MkdirAll(filepath.Dir(path), 0o700); err != nil {
|
||||||
|
t.Fatalf("create database dir: %v", err)
|
||||||
|
}
|
||||||
|
if err := os.WriteFile(path, data, 0o600); err != nil {
|
||||||
|
t.Fatalf("copy template database: %v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if err := database.InitDB(path); err != nil {
|
||||||
|
t.Fatalf("InitDB: %v", err)
|
||||||
|
}
|
||||||
|
t.Cleanup(func() { _ = database.CloseDB() })
|
||||||
|
}
|
||||||
|
|
||||||
|
func migratedTemplate() ([]byte, error) {
|
||||||
|
migrated.once.Do(func() {
|
||||||
|
dir, err := os.MkdirTemp("", "xui-dbtest-")
|
||||||
|
if err != nil {
|
||||||
|
migrated.err = err
|
||||||
|
return
|
||||||
|
}
|
||||||
|
defer os.RemoveAll(dir)
|
||||||
|
path := filepath.Join(dir, "template.db")
|
||||||
|
if err := database.InitDB(path); err != nil {
|
||||||
|
migrated.err = err
|
||||||
|
return
|
||||||
|
}
|
||||||
|
// Closing the last connection checkpoints the WAL into the main file.
|
||||||
|
if err := database.CloseDB(); err != nil {
|
||||||
|
migrated.err = err
|
||||||
|
return
|
||||||
|
}
|
||||||
|
migrated.data, migrated.err = os.ReadFile(path)
|
||||||
|
})
|
||||||
|
return migrated.data, migrated.err
|
||||||
|
}
|
||||||
@@ -0,0 +1,36 @@
|
|||||||
|
package dbtest
|
||||||
|
|
||||||
|
import (
|
||||||
|
"path/filepath"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/mhsanaei/3x-ui/v3/internal/database"
|
||||||
|
"github.com/mhsanaei/3x-ui/v3/internal/database/model"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestInitDBGivesEachTestItsOwnDatabase(t *testing.T) {
|
||||||
|
t.Run("first test writes", func(t *testing.T) {
|
||||||
|
InitDB(t, filepath.Join(t.TempDir(), "x-ui.db"))
|
||||||
|
if err := database.GetDB().Create(&model.Setting{Key: "dbtestProbe", Value: "first"}).Error; err != nil {
|
||||||
|
t.Fatalf("write probe: %v", err)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("next test starts clean", func(t *testing.T) {
|
||||||
|
InitDB(t, filepath.Join(t.TempDir(), "x-ui.db"))
|
||||||
|
var leaked int64
|
||||||
|
if err := database.GetDB().Model(&model.Setting{}).Where("key = ?", "dbtestProbe").Count(&leaked).Error; err != nil {
|
||||||
|
t.Fatalf("count probe: %v", err)
|
||||||
|
}
|
||||||
|
if leaked != 0 {
|
||||||
|
t.Fatalf("database holds %d probe rows written by the previous test; copies must not share state", leaked)
|
||||||
|
}
|
||||||
|
var admins int64
|
||||||
|
if err := database.GetDB().Model(&model.User{}).Count(&admins).Error; err != nil {
|
||||||
|
t.Fatalf("count users: %v", err)
|
||||||
|
}
|
||||||
|
if admins != 1 {
|
||||||
|
t.Fatalf("users = %d, want the 1 seeded admin a fresh install has", admins)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
@@ -6,17 +6,13 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/mhsanaei/3x-ui/v3/internal/database"
|
"github.com/mhsanaei/3x-ui/v3/internal/database"
|
||||||
|
"github.com/mhsanaei/3x-ui/v3/internal/database/dbtest"
|
||||||
"github.com/mhsanaei/3x-ui/v3/internal/database/model"
|
"github.com/mhsanaei/3x-ui/v3/internal/database/model"
|
||||||
)
|
)
|
||||||
|
|
||||||
func initSubDB(t *testing.T) {
|
func initSubDB(t *testing.T) {
|
||||||
t.Helper()
|
t.Helper()
|
||||||
if err := database.InitDB(filepath.Join(t.TempDir(), "x-ui.db")); err != nil {
|
dbtest.InitDB(t, filepath.Join(t.TempDir(), "x-ui.db"))
|
||||||
t.Fatalf("InitDB: %v", err)
|
|
||||||
}
|
|
||||||
// Close the handle before t.TempDir cleanup so Windows doesn't refuse to
|
|
||||||
// remove the still-open sqlite file.
|
|
||||||
t.Cleanup(func() { _ = database.CloseDB() })
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// The subscription page's Copy URL must be built from the same host the
|
// The subscription page's Copy URL must be built from the same host the
|
||||||
|
|||||||
@@ -6,17 +6,14 @@ import (
|
|||||||
"path/filepath"
|
"path/filepath"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/mhsanaei/3x-ui/v3/internal/database"
|
"github.com/mhsanaei/3x-ui/v3/internal/database/dbtest"
|
||||||
"github.com/mhsanaei/3x-ui/v3/internal/web/service"
|
"github.com/mhsanaei/3x-ui/v3/internal/web/service"
|
||||||
)
|
)
|
||||||
|
|
||||||
// #6559: the Master panel must send a stable X-HWID when fetching external
|
// #6559: the Master panel must send a stable X-HWID when fetching external
|
||||||
// subscriptions, otherwise an HWID-limited donor answers 404.
|
// subscriptions, otherwise an HWID-limited donor answers 404.
|
||||||
func TestFetchSendsStableHwid(t *testing.T) {
|
func TestFetchSendsStableHwid(t *testing.T) {
|
||||||
if err := database.InitDB(filepath.Join(t.TempDir(), "x-ui.db")); err != nil {
|
dbtest.InitDB(t, filepath.Join(t.TempDir(), "x-ui.db"))
|
||||||
t.Fatalf("InitDB: %v", err)
|
|
||||||
}
|
|
||||||
t.Cleanup(func() { _ = database.CloseDB() })
|
|
||||||
|
|
||||||
var gotHwid string
|
var gotHwid string
|
||||||
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/mhsanaei/3x-ui/v3/internal/database"
|
"github.com/mhsanaei/3x-ui/v3/internal/database"
|
||||||
|
"github.com/mhsanaei/3x-ui/v3/internal/database/dbtest"
|
||||||
"github.com/mhsanaei/3x-ui/v3/internal/database/model"
|
"github.com/mhsanaei/3x-ui/v3/internal/database/model"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -302,10 +303,7 @@ func TestExpandEntryCacheHitWritesNothing(t *testing.T) {
|
|||||||
|
|
||||||
func TestFetchUsesConfiguredExternalSubUserAgent(t *testing.T) {
|
func TestFetchUsesConfiguredExternalSubUserAgent(t *testing.T) {
|
||||||
resetSubscriptionCache(t)
|
resetSubscriptionCache(t)
|
||||||
if err := database.InitDB(filepath.Join(t.TempDir(), "ua.db")); err != nil {
|
dbtest.InitDB(t, filepath.Join(t.TempDir(), "ua.db"))
|
||||||
t.Fatalf("InitDB: %v", err)
|
|
||||||
}
|
|
||||||
t.Cleanup(func() { _ = database.CloseDB() })
|
|
||||||
|
|
||||||
const customUA = "Happ/4.2.1"
|
const customUA = "Happ/4.2.1"
|
||||||
if err := database.GetDB().Create(&model.Setting{
|
if err := database.GetDB().Create(&model.Setting{
|
||||||
@@ -333,10 +331,7 @@ func TestFetchUsesConfiguredExternalSubUserAgent(t *testing.T) {
|
|||||||
|
|
||||||
func TestFetchFallsBackToDefaultExternalSubUserAgent(t *testing.T) {
|
func TestFetchFallsBackToDefaultExternalSubUserAgent(t *testing.T) {
|
||||||
resetSubscriptionCache(t)
|
resetSubscriptionCache(t)
|
||||||
if err := database.InitDB(filepath.Join(t.TempDir(), "ua-default.db")); err != nil {
|
dbtest.InitDB(t, filepath.Join(t.TempDir(), "ua-default.db"))
|
||||||
t.Fatalf("InitDB: %v", err)
|
|
||||||
}
|
|
||||||
t.Cleanup(func() { _ = database.CloseDB() })
|
|
||||||
|
|
||||||
var gotUA string
|
var gotUA string
|
||||||
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/mhsanaei/3x-ui/v3/internal/database"
|
"github.com/mhsanaei/3x-ui/v3/internal/database"
|
||||||
|
"github.com/mhsanaei/3x-ui/v3/internal/database/dbtest"
|
||||||
"github.com/mhsanaei/3x-ui/v3/internal/database/model"
|
"github.com/mhsanaei/3x-ui/v3/internal/database/model"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -15,10 +16,7 @@ func seedSubDB(t *testing.T) {
|
|||||||
t.Helper()
|
t.Helper()
|
||||||
dbDir := t.TempDir()
|
dbDir := t.TempDir()
|
||||||
t.Setenv("XUI_DB_FOLDER", dbDir)
|
t.Setenv("XUI_DB_FOLDER", dbDir)
|
||||||
if err := database.InitDB(filepath.Join(dbDir, "x-ui.db")); err != nil {
|
dbtest.InitDB(t, filepath.Join(dbDir, "x-ui.db"))
|
||||||
t.Fatalf("InitDB: %v", err)
|
|
||||||
}
|
|
||||||
t.Cleanup(func() { _ = database.CloseDB() })
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// seedSubInbound creates a VLESS inbound with one client wired into the
|
// seedSubInbound creates a VLESS inbound with one client wired into the
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ import (
|
|||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
|
|
||||||
"github.com/mhsanaei/3x-ui/v3/internal/database"
|
"github.com/mhsanaei/3x-ui/v3/internal/database"
|
||||||
|
"github.com/mhsanaei/3x-ui/v3/internal/database/dbtest"
|
||||||
"github.com/mhsanaei/3x-ui/v3/internal/database/model"
|
"github.com/mhsanaei/3x-ui/v3/internal/database/model"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -27,10 +28,7 @@ func initHwidSubRouter(t *testing.T, limit int) (*gin.Engine, string) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
t.Setenv("XUI_DB_FOLDER", tmp)
|
t.Setenv("XUI_DB_FOLDER", tmp)
|
||||||
if err := database.InitDB(filepath.Join(tmp, "x-ui.db")); err != nil {
|
dbtest.InitDB(t, filepath.Join(tmp, "x-ui.db"))
|
||||||
t.Fatalf("InitDB: %v", err)
|
|
||||||
}
|
|
||||||
t.Cleanup(func() { _ = database.CloseDB() })
|
|
||||||
|
|
||||||
const subID = "sub-hwid-route"
|
const subID = "sub-hwid-route"
|
||||||
const email = "route@example.com"
|
const email = "route@example.com"
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/mhsanaei/3x-ui/v3/internal/database"
|
"github.com/mhsanaei/3x-ui/v3/internal/database"
|
||||||
|
"github.com/mhsanaei/3x-ui/v3/internal/database/dbtest"
|
||||||
"github.com/mhsanaei/3x-ui/v3/internal/database/model"
|
"github.com/mhsanaei/3x-ui/v3/internal/database/model"
|
||||||
"github.com/mhsanaei/3x-ui/v3/internal/xray"
|
"github.com/mhsanaei/3x-ui/v3/internal/xray"
|
||||||
)
|
)
|
||||||
@@ -19,10 +20,7 @@ func initMutDB(t *testing.T) {
|
|||||||
t.Helper()
|
t.Helper()
|
||||||
dbDir := t.TempDir()
|
dbDir := t.TempDir()
|
||||||
t.Setenv("XUI_DB_FOLDER", dbDir)
|
t.Setenv("XUI_DB_FOLDER", dbDir)
|
||||||
if err := database.InitDB(filepath.Join(dbDir, "x-ui.db")); err != nil {
|
dbtest.InitDB(t, filepath.Join(dbDir, "x-ui.db"))
|
||||||
t.Fatalf("InitDB: %v", err)
|
|
||||||
}
|
|
||||||
t.Cleanup(func() { _ = database.CloseDB() })
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// --- json_service.go:40 — rules are merged into routing only when non-empty ---
|
// --- json_service.go:40 — rules are merged into routing only when non-empty ---
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ import (
|
|||||||
yaml "github.com/goccy/go-yaml"
|
yaml "github.com/goccy/go-yaml"
|
||||||
|
|
||||||
"github.com/mhsanaei/3x-ui/v3/internal/database"
|
"github.com/mhsanaei/3x-ui/v3/internal/database"
|
||||||
|
"github.com/mhsanaei/3x-ui/v3/internal/database/dbtest"
|
||||||
)
|
)
|
||||||
|
|
||||||
func mergeRemoteClashRulesYAML(base map[string]any, raw string) error {
|
func mergeRemoteClashRulesYAML(base map[string]any, raw string) error {
|
||||||
@@ -607,10 +608,7 @@ func TestRemoteRoutingHTTPClientRejectsLoopback(t *testing.T) {
|
|||||||
|
|
||||||
func TestRemoteRoutingPersistedLoadRetriesAfterDatabaseBecomesReady(t *testing.T) {
|
func TestRemoteRoutingPersistedLoadRetriesAfterDatabaseBecomesReady(t *testing.T) {
|
||||||
dbPath := filepath.Join(t.TempDir(), "x-ui.db")
|
dbPath := filepath.Join(t.TempDir(), "x-ui.db")
|
||||||
if err := database.InitDB(dbPath); err != nil {
|
dbtest.InitDB(t, dbPath)
|
||||||
t.Fatalf("init db: %v", err)
|
|
||||||
}
|
|
||||||
t.Cleanup(func() { _ = database.CloseDB() })
|
|
||||||
|
|
||||||
deeplink, err := normalizeHappRouting([]byte(`{"Name":"persisted-after-ready"}`))
|
deeplink, err := normalizeHappRouting([]byte(`{"Name":"persisted-after-ready"}`))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/mhsanaei/3x-ui/v3/internal/database"
|
"github.com/mhsanaei/3x-ui/v3/internal/database"
|
||||||
|
"github.com/mhsanaei/3x-ui/v3/internal/database/dbtest"
|
||||||
"github.com/mhsanaei/3x-ui/v3/internal/database/model"
|
"github.com/mhsanaei/3x-ui/v3/internal/database/model"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -18,10 +19,7 @@ import (
|
|||||||
func TestGetSubs_DuplicateSettingsClients_Deduped(t *testing.T) {
|
func TestGetSubs_DuplicateSettingsClients_Deduped(t *testing.T) {
|
||||||
dbDir := t.TempDir()
|
dbDir := t.TempDir()
|
||||||
t.Setenv("XUI_DB_FOLDER", dbDir)
|
t.Setenv("XUI_DB_FOLDER", dbDir)
|
||||||
if err := database.InitDB(filepath.Join(dbDir, "x-ui.db")); err != nil {
|
dbtest.InitDB(t, filepath.Join(dbDir, "x-ui.db"))
|
||||||
t.Fatalf("InitDB: %v", err)
|
|
||||||
}
|
|
||||||
t.Cleanup(func() { _ = database.CloseDB() })
|
|
||||||
|
|
||||||
const subId = "sub-dup"
|
const subId = "sub-dup"
|
||||||
const email = "dup@example.com"
|
const email = "dup@example.com"
|
||||||
@@ -76,10 +74,7 @@ func TestGetSubs_DuplicateSettingsClients_Deduped(t *testing.T) {
|
|||||||
func TestMatchingClients_DedupsCaseInsensitiveEmail(t *testing.T) {
|
func TestMatchingClients_DedupsCaseInsensitiveEmail(t *testing.T) {
|
||||||
dbDir := t.TempDir()
|
dbDir := t.TempDir()
|
||||||
t.Setenv("XUI_DB_FOLDER", dbDir)
|
t.Setenv("XUI_DB_FOLDER", dbDir)
|
||||||
if err := database.InitDB(filepath.Join(dbDir, "x-ui.db")); err != nil {
|
dbtest.InitDB(t, filepath.Join(dbDir, "x-ui.db"))
|
||||||
t.Fatalf("InitDB: %v", err)
|
|
||||||
}
|
|
||||||
t.Cleanup(func() { _ = database.CloseDB() })
|
|
||||||
|
|
||||||
const subId = "s1"
|
const subId = "s1"
|
||||||
const uuid = "11111111-2222-4333-8444-555555555555"
|
const uuid = "11111111-2222-4333-8444-555555555555"
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/mhsanaei/3x-ui/v3/internal/database"
|
"github.com/mhsanaei/3x-ui/v3/internal/database"
|
||||||
|
"github.com/mhsanaei/3x-ui/v3/internal/database/dbtest"
|
||||||
"github.com/mhsanaei/3x-ui/v3/internal/database/model"
|
"github.com/mhsanaei/3x-ui/v3/internal/database/model"
|
||||||
"github.com/mhsanaei/3x-ui/v3/internal/web/service"
|
"github.com/mhsanaei/3x-ui/v3/internal/web/service"
|
||||||
"github.com/mhsanaei/3x-ui/v3/internal/xray"
|
"github.com/mhsanaei/3x-ui/v3/internal/xray"
|
||||||
@@ -15,12 +16,7 @@ import (
|
|||||||
|
|
||||||
func setupInfoNodeTestDB(t *testing.T) {
|
func setupInfoNodeTestDB(t *testing.T) {
|
||||||
t.Helper()
|
t.Helper()
|
||||||
if err := database.InitDB(t.TempDir() + "/test_infonode.db"); err != nil {
|
dbtest.InitDB(t, t.TempDir()+"/test_infonode.db")
|
||||||
t.Fatalf("InitDB: %v", err)
|
|
||||||
}
|
|
||||||
t.Cleanup(func() {
|
|
||||||
_ = database.CloseDB()
|
|
||||||
})
|
|
||||||
db := database.GetDB()
|
db := database.GetDB()
|
||||||
if err := db.AutoMigrate(
|
if err := db.AutoMigrate(
|
||||||
&model.Inbound{},
|
&model.Inbound{},
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/mhsanaei/3x-ui/v3/internal/database"
|
"github.com/mhsanaei/3x-ui/v3/internal/database"
|
||||||
|
"github.com/mhsanaei/3x-ui/v3/internal/database/dbtest"
|
||||||
"github.com/mhsanaei/3x-ui/v3/internal/database/model"
|
"github.com/mhsanaei/3x-ui/v3/internal/database/model"
|
||||||
"github.com/mhsanaei/3x-ui/v3/internal/xray"
|
"github.com/mhsanaei/3x-ui/v3/internal/xray"
|
||||||
)
|
)
|
||||||
@@ -17,10 +18,7 @@ import (
|
|||||||
func TestStatsForClient_OrphanedInboundIdFallback(t *testing.T) {
|
func TestStatsForClient_OrphanedInboundIdFallback(t *testing.T) {
|
||||||
dbDir := t.TempDir()
|
dbDir := t.TempDir()
|
||||||
t.Setenv("XUI_DB_FOLDER", dbDir)
|
t.Setenv("XUI_DB_FOLDER", dbDir)
|
||||||
if err := database.InitDB(filepath.Join(dbDir, "x-ui.db")); err != nil {
|
dbtest.InitDB(t, filepath.Join(dbDir, "x-ui.db"))
|
||||||
t.Fatalf("InitDB: %v", err)
|
|
||||||
}
|
|
||||||
t.Cleanup(func() { _ = database.CloseDB() })
|
|
||||||
|
|
||||||
const email = "old-client@example.com"
|
const email = "old-client@example.com"
|
||||||
const total = int64(100) * gb
|
const total = int64(100) * gb
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/mhsanaei/3x-ui/v3/internal/database"
|
"github.com/mhsanaei/3x-ui/v3/internal/database"
|
||||||
|
"github.com/mhsanaei/3x-ui/v3/internal/database/dbtest"
|
||||||
"github.com/mhsanaei/3x-ui/v3/internal/database/model"
|
"github.com/mhsanaei/3x-ui/v3/internal/database/model"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -16,10 +17,7 @@ import (
|
|||||||
func TestGetSubs_OrdersBySubSortIndexThenId(t *testing.T) {
|
func TestGetSubs_OrdersBySubSortIndexThenId(t *testing.T) {
|
||||||
dbDir := t.TempDir()
|
dbDir := t.TempDir()
|
||||||
t.Setenv("XUI_DB_FOLDER", dbDir)
|
t.Setenv("XUI_DB_FOLDER", dbDir)
|
||||||
if err := database.InitDB(filepath.Join(dbDir, "x-ui.db")); err != nil {
|
dbtest.InitDB(t, filepath.Join(dbDir, "x-ui.db"))
|
||||||
t.Fatalf("InitDB: %v", err)
|
|
||||||
}
|
|
||||||
t.Cleanup(func() { _ = database.CloseDB() })
|
|
||||||
|
|
||||||
const subId = "sub-sort"
|
const subId = "sub-sort"
|
||||||
db := database.GetDB()
|
db := database.GetDB()
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/mhsanaei/3x-ui/v3/internal/database"
|
"github.com/mhsanaei/3x-ui/v3/internal/database"
|
||||||
|
"github.com/mhsanaei/3x-ui/v3/internal/database/dbtest"
|
||||||
"github.com/mhsanaei/3x-ui/v3/internal/database/model"
|
"github.com/mhsanaei/3x-ui/v3/internal/database/model"
|
||||||
"github.com/mhsanaei/3x-ui/v3/internal/xray"
|
"github.com/mhsanaei/3x-ui/v3/internal/xray"
|
||||||
)
|
)
|
||||||
@@ -12,10 +13,7 @@ import (
|
|||||||
func TestAggregateTrafficByEmails_FallsBackToClientLimits(t *testing.T) {
|
func TestAggregateTrafficByEmails_FallsBackToClientLimits(t *testing.T) {
|
||||||
dbDir := t.TempDir()
|
dbDir := t.TempDir()
|
||||||
t.Setenv("XUI_DB_FOLDER", dbDir)
|
t.Setenv("XUI_DB_FOLDER", dbDir)
|
||||||
if err := database.InitDB(filepath.Join(dbDir, "x-ui.db")); err != nil {
|
dbtest.InitDB(t, filepath.Join(dbDir, "x-ui.db"))
|
||||||
t.Fatalf("InitDB: %v", err)
|
|
||||||
}
|
|
||||||
t.Cleanup(func() { _ = database.CloseDB() })
|
|
||||||
|
|
||||||
const email = "node-client@example.com"
|
const email = "node-client@example.com"
|
||||||
const totalBytes = int64(300) * 1024 * 1024 * 1024
|
const totalBytes = int64(300) * 1024 * 1024 * 1024
|
||||||
|
|||||||
@@ -16,6 +16,7 @@ import (
|
|||||||
|
|
||||||
"github.com/mhsanaei/3x-ui/v3/internal/config"
|
"github.com/mhsanaei/3x-ui/v3/internal/config"
|
||||||
"github.com/mhsanaei/3x-ui/v3/internal/database"
|
"github.com/mhsanaei/3x-ui/v3/internal/database"
|
||||||
|
"github.com/mhsanaei/3x-ui/v3/internal/database/dbtest"
|
||||||
"github.com/mhsanaei/3x-ui/v3/internal/database/model"
|
"github.com/mhsanaei/3x-ui/v3/internal/database/model"
|
||||||
xuilogger "github.com/mhsanaei/3x-ui/v3/internal/logger"
|
xuilogger "github.com/mhsanaei/3x-ui/v3/internal/logger"
|
||||||
"github.com/mhsanaei/3x-ui/v3/internal/xray"
|
"github.com/mhsanaei/3x-ui/v3/internal/xray"
|
||||||
@@ -38,10 +39,7 @@ func setupScaleSubDB(t *testing.T) {
|
|||||||
}
|
}
|
||||||
switch strings.ToLower(strings.TrimSpace(os.Getenv("XUI_SCALE_TEST"))) {
|
switch strings.ToLower(strings.TrimSpace(os.Getenv("XUI_SCALE_TEST"))) {
|
||||||
case "1", "true", "yes":
|
case "1", "true", "yes":
|
||||||
if err := database.InitDB(filepath.Join(t.TempDir(), "scale.db")); err != nil {
|
dbtest.InitDB(t, filepath.Join(t.TempDir(), "scale.db"))
|
||||||
t.Fatalf("InitDB(sqlite): %v", err)
|
|
||||||
}
|
|
||||||
t.Cleanup(func() { _ = database.CloseDB() })
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
t.Skip("set XUI_SCALE_TEST=1 (sqlite) or XUI_DB_TYPE=postgres + XUI_DB_DSN (postgres) to run the scale benchmark")
|
t.Skip("set XUI_SCALE_TEST=1 (sqlite) or XUI_DB_TYPE=postgres + XUI_DB_DSN (postgres) to run the scale benchmark")
|
||||||
|
|||||||
@@ -15,6 +15,7 @@ import (
|
|||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
|
|
||||||
"github.com/mhsanaei/3x-ui/v3/internal/database"
|
"github.com/mhsanaei/3x-ui/v3/internal/database"
|
||||||
|
"github.com/mhsanaei/3x-ui/v3/internal/database/dbtest"
|
||||||
"github.com/mhsanaei/3x-ui/v3/internal/database/model"
|
"github.com/mhsanaei/3x-ui/v3/internal/database/model"
|
||||||
"github.com/mhsanaei/3x-ui/v3/internal/util/crypto"
|
"github.com/mhsanaei/3x-ui/v3/internal/util/crypto"
|
||||||
"github.com/mhsanaei/3x-ui/v3/internal/web/session"
|
"github.com/mhsanaei/3x-ui/v3/internal/web/session"
|
||||||
@@ -31,10 +32,7 @@ func newAPIAuthTestEngine(t *testing.T) (*gin.Engine, *APIController) {
|
|||||||
gin.SetMode(gin.TestMode)
|
gin.SetMode(gin.TestMode)
|
||||||
dbDir := t.TempDir()
|
dbDir := t.TempDir()
|
||||||
t.Setenv("XUI_DB_FOLDER", dbDir)
|
t.Setenv("XUI_DB_FOLDER", dbDir)
|
||||||
if err := database.InitDB(filepath.Join(dbDir, "x-ui.db")); err != nil {
|
dbtest.InitDB(t, filepath.Join(dbDir, "x-ui.db"))
|
||||||
t.Fatalf("InitDB: %v", err)
|
|
||||||
}
|
|
||||||
t.Cleanup(func() { _ = database.CloseDB() })
|
|
||||||
engine := gin.New()
|
engine := gin.New()
|
||||||
store := cookie.NewStore([]byte("api-auth-test-secret"))
|
store := cookie.NewStore([]byte("api-auth-test-secret"))
|
||||||
engine.Use(sessions.Sessions("3x-ui", store))
|
engine.Use(sessions.Sessions("3x-ui", store))
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ import (
|
|||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
|
|
||||||
"github.com/mhsanaei/3x-ui/v3/internal/database"
|
"github.com/mhsanaei/3x-ui/v3/internal/database"
|
||||||
|
"github.com/mhsanaei/3x-ui/v3/internal/database/dbtest"
|
||||||
"github.com/mhsanaei/3x-ui/v3/internal/database/model"
|
"github.com/mhsanaei/3x-ui/v3/internal/database/model"
|
||||||
"github.com/mhsanaei/3x-ui/v3/internal/web/entity"
|
"github.com/mhsanaei/3x-ui/v3/internal/web/entity"
|
||||||
"github.com/mhsanaei/3x-ui/v3/internal/web/service"
|
"github.com/mhsanaei/3x-ui/v3/internal/web/service"
|
||||||
@@ -22,10 +23,7 @@ func seedPartlyApplyingClient(t *testing.T, email string, basePort int) (healthy
|
|||||||
t.Helper()
|
t.Helper()
|
||||||
dbDir := t.TempDir()
|
dbDir := t.TempDir()
|
||||||
t.Setenv("XUI_DB_FOLDER", dbDir)
|
t.Setenv("XUI_DB_FOLDER", dbDir)
|
||||||
if err := database.InitDB(filepath.Join(dbDir, "x-ui.db")); err != nil {
|
dbtest.InitDB(t, filepath.Join(dbDir, "x-ui.db"))
|
||||||
t.Fatalf("InitDB: %v", err)
|
|
||||||
}
|
|
||||||
t.Cleanup(func() { _ = database.CloseDB() })
|
|
||||||
|
|
||||||
db := database.GetDB()
|
db := database.GetDB()
|
||||||
ids := make([]int, 0, 2)
|
ids := make([]int, 0, 2)
|
||||||
@@ -129,10 +127,7 @@ func TestDeleteHandlerFlagsRestartOnPartialApply(t *testing.T) {
|
|||||||
func TestImportHandlerFlagsRestartWhenTrafficRestoreFails(t *testing.T) {
|
func TestImportHandlerFlagsRestartWhenTrafficRestoreFails(t *testing.T) {
|
||||||
dbDir := t.TempDir()
|
dbDir := t.TempDir()
|
||||||
t.Setenv("XUI_DB_FOLDER", dbDir)
|
t.Setenv("XUI_DB_FOLDER", dbDir)
|
||||||
if err := database.InitDB(filepath.Join(dbDir, "x-ui.db")); err != nil {
|
dbtest.InitDB(t, filepath.Join(dbDir, "x-ui.db"))
|
||||||
t.Fatalf("InitDB: %v", err)
|
|
||||||
}
|
|
||||||
t.Cleanup(func() { _ = database.CloseDB() })
|
|
||||||
db := database.GetDB()
|
db := database.GetDB()
|
||||||
ib := &model.Inbound{
|
ib := &model.Inbound{
|
||||||
UserId: 1, Enable: true, Port: 43340, Tag: "in-import-partial",
|
UserId: 1, Enable: true, Port: 43340, Tag: "in-import-partial",
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ import (
|
|||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
|
|
||||||
"github.com/mhsanaei/3x-ui/v3/internal/database"
|
"github.com/mhsanaei/3x-ui/v3/internal/database"
|
||||||
|
"github.com/mhsanaei/3x-ui/v3/internal/database/dbtest"
|
||||||
"github.com/mhsanaei/3x-ui/v3/internal/database/model"
|
"github.com/mhsanaei/3x-ui/v3/internal/database/model"
|
||||||
"github.com/mhsanaei/3x-ui/v3/internal/web/service"
|
"github.com/mhsanaei/3x-ui/v3/internal/web/service"
|
||||||
"github.com/mhsanaei/3x-ui/v3/internal/xray"
|
"github.com/mhsanaei/3x-ui/v3/internal/xray"
|
||||||
@@ -45,10 +46,7 @@ func TestClientRenewalPreviewHTTP(t *testing.T) {
|
|||||||
{name: "negative count", zone: "UTC", count: -1, invalid: true, wantError: "renewal preview reset and resetCount must not be negative\n"},
|
{name: "negative count", zone: "UTC", count: -1, invalid: true, wantError: "renewal preview reset and resetCount must not be negative\n"},
|
||||||
} {
|
} {
|
||||||
t.Run(tt.name, func(t *testing.T) {
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
if err := database.InitDB(filepath.Join(t.TempDir(), "x-ui.db")); err != nil {
|
dbtest.InitDB(t, filepath.Join(t.TempDir(), "x-ui.db"))
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
t.Cleanup(func() { _ = database.CloseDB() })
|
|
||||||
db := database.GetDB()
|
db := database.GetDB()
|
||||||
if err := db.Create(&model.Setting{Key: "timeLocation", Value: tt.zone}).Error; err != nil {
|
if err := db.Create(&model.Setting{Key: "timeLocation", Value: tt.zone}).Error; err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ import (
|
|||||||
"github.com/op/go-logging"
|
"github.com/op/go-logging"
|
||||||
|
|
||||||
"github.com/mhsanaei/3x-ui/v3/internal/database"
|
"github.com/mhsanaei/3x-ui/v3/internal/database"
|
||||||
|
"github.com/mhsanaei/3x-ui/v3/internal/database/dbtest"
|
||||||
"github.com/mhsanaei/3x-ui/v3/internal/database/model"
|
"github.com/mhsanaei/3x-ui/v3/internal/database/model"
|
||||||
xuilogger "github.com/mhsanaei/3x-ui/v3/internal/logger"
|
xuilogger "github.com/mhsanaei/3x-ui/v3/internal/logger"
|
||||||
"github.com/mhsanaei/3x-ui/v3/internal/web/entity"
|
"github.com/mhsanaei/3x-ui/v3/internal/web/entity"
|
||||||
@@ -25,10 +26,7 @@ func newHostTestDB(t *testing.T) {
|
|||||||
gin.SetMode(gin.TestMode)
|
gin.SetMode(gin.TestMode)
|
||||||
dbDir := t.TempDir()
|
dbDir := t.TempDir()
|
||||||
t.Setenv("XUI_DB_FOLDER", dbDir)
|
t.Setenv("XUI_DB_FOLDER", dbDir)
|
||||||
if err := database.InitDB(filepath.Join(dbDir, "x-ui.db")); err != nil {
|
dbtest.InitDB(t, filepath.Join(dbDir, "x-ui.db"))
|
||||||
t.Fatalf("InitDB: %v", err)
|
|
||||||
}
|
|
||||||
t.Cleanup(func() { _ = database.CloseDB() })
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type hostEnvelope struct {
|
type hostEnvelope struct {
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ import (
|
|||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
|
|
||||||
"github.com/mhsanaei/3x-ui/v3/internal/database"
|
"github.com/mhsanaei/3x-ui/v3/internal/database"
|
||||||
|
"github.com/mhsanaei/3x-ui/v3/internal/database/dbtest"
|
||||||
"github.com/mhsanaei/3x-ui/v3/internal/database/model"
|
"github.com/mhsanaei/3x-ui/v3/internal/database/model"
|
||||||
"github.com/mhsanaei/3x-ui/v3/internal/util/crypto"
|
"github.com/mhsanaei/3x-ui/v3/internal/util/crypto"
|
||||||
"github.com/mhsanaei/3x-ui/v3/internal/web/runtime"
|
"github.com/mhsanaei/3x-ui/v3/internal/web/runtime"
|
||||||
@@ -23,10 +24,7 @@ func TestNodeSyncPushSkipsOperatorTLSGuard(t *testing.T) {
|
|||||||
gin.SetMode(gin.TestMode)
|
gin.SetMode(gin.TestMode)
|
||||||
dbDir := t.TempDir()
|
dbDir := t.TempDir()
|
||||||
t.Setenv("XUI_DB_FOLDER", dbDir)
|
t.Setenv("XUI_DB_FOLDER", dbDir)
|
||||||
if err := database.InitDB(filepath.Join(dbDir, "x-ui.db")); err != nil {
|
dbtest.InitDB(t, filepath.Join(dbDir, "x-ui.db"))
|
||||||
t.Fatalf("InitDB: %v", err)
|
|
||||||
}
|
|
||||||
t.Cleanup(func() { _ = database.CloseDB() })
|
|
||||||
prev := runtime.GetManager()
|
prev := runtime.GetManager()
|
||||||
runtime.SetManager(runtime.NewManager(runtime.LocalDeps{APIPort: func() int { return 0 }, SetNeedRestart: func() {}}))
|
runtime.SetManager(runtime.NewManager(runtime.LocalDeps{APIPort: func() int { return 0 }, SetNeedRestart: func() {}}))
|
||||||
t.Cleanup(func() { runtime.SetManager(prev) })
|
t.Cleanup(func() { runtime.SetManager(prev) })
|
||||||
|
|||||||
@@ -16,6 +16,7 @@ import (
|
|||||||
"gorm.io/gorm"
|
"gorm.io/gorm"
|
||||||
|
|
||||||
"github.com/mhsanaei/3x-ui/v3/internal/database"
|
"github.com/mhsanaei/3x-ui/v3/internal/database"
|
||||||
|
"github.com/mhsanaei/3x-ui/v3/internal/database/dbtest"
|
||||||
"github.com/mhsanaei/3x-ui/v3/internal/database/model"
|
"github.com/mhsanaei/3x-ui/v3/internal/database/model"
|
||||||
"github.com/mhsanaei/3x-ui/v3/internal/web/locale"
|
"github.com/mhsanaei/3x-ui/v3/internal/web/locale"
|
||||||
)
|
)
|
||||||
@@ -25,10 +26,7 @@ func newNodeCredentialTestEngine(t *testing.T) *gin.Engine {
|
|||||||
gin.SetMode(gin.TestMode)
|
gin.SetMode(gin.TestMode)
|
||||||
dbDir := t.TempDir()
|
dbDir := t.TempDir()
|
||||||
t.Setenv("XUI_DB_FOLDER", dbDir)
|
t.Setenv("XUI_DB_FOLDER", dbDir)
|
||||||
if err := database.InitDB(filepath.Join(dbDir, "x-ui.db")); err != nil {
|
dbtest.InitDB(t, filepath.Join(dbDir, "x-ui.db"))
|
||||||
t.Fatalf("InitDB: %v", err)
|
|
||||||
}
|
|
||||||
t.Cleanup(func() { _ = database.CloseDB() })
|
|
||||||
|
|
||||||
engine := gin.New()
|
engine := gin.New()
|
||||||
engine.Use(func(c *gin.Context) {
|
engine.Use(func(c *gin.Context) {
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ import (
|
|||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
|
|
||||||
"github.com/mhsanaei/3x-ui/v3/internal/database"
|
"github.com/mhsanaei/3x-ui/v3/internal/database"
|
||||||
|
"github.com/mhsanaei/3x-ui/v3/internal/database/dbtest"
|
||||||
"github.com/mhsanaei/3x-ui/v3/internal/database/model"
|
"github.com/mhsanaei/3x-ui/v3/internal/database/model"
|
||||||
"github.com/mhsanaei/3x-ui/v3/internal/util/crypto"
|
"github.com/mhsanaei/3x-ui/v3/internal/util/crypto"
|
||||||
"github.com/mhsanaei/3x-ui/v3/internal/web/locale"
|
"github.com/mhsanaei/3x-ui/v3/internal/web/locale"
|
||||||
@@ -57,10 +58,7 @@ func TestValidateRegex(t *testing.T) {
|
|||||||
|
|
||||||
func TestAPITokenMutationRoutesEnforceExpectedScope(t *testing.T) {
|
func TestAPITokenMutationRoutesEnforceExpectedScope(t *testing.T) {
|
||||||
t.Setenv("XUI_DB_FOLDER", t.TempDir())
|
t.Setenv("XUI_DB_FOLDER", t.TempDir())
|
||||||
if err := database.InitDB(filepath.Join(t.TempDir(), "x-ui.db")); err != nil {
|
dbtest.InitDB(t, filepath.Join(t.TempDir(), "x-ui.db"))
|
||||||
t.Fatalf("InitDB: %v", err)
|
|
||||||
}
|
|
||||||
t.Cleanup(func() { _ = database.CloseDB() })
|
|
||||||
row := &model.ApiToken{Name: "route-scope", Token: crypto.HashTokenSHA256("token"), Enabled: true, Scope: model.ApiScopeNodeSync}
|
row := &model.ApiToken{Name: "route-scope", Token: crypto.HashTokenSHA256("token"), Enabled: true, Scope: model.ApiScopeNodeSync}
|
||||||
if err := database.GetDB().Create(row).Error; err != nil {
|
if err := database.GetDB().Create(row).Error; err != nil {
|
||||||
t.Fatalf("seed token: %v", err)
|
t.Fatalf("seed token: %v", err)
|
||||||
@@ -95,10 +93,7 @@ func TestAPITokenMutationRoutesEnforceExpectedScope(t *testing.T) {
|
|||||||
// rebind the authenticator without presenting a current code.
|
// rebind the authenticator without presenting a current code.
|
||||||
func TestUpdateSettingRequiresCodeToReplaceTwoFactorToken(t *testing.T) {
|
func TestUpdateSettingRequiresCodeToReplaceTwoFactorToken(t *testing.T) {
|
||||||
t.Setenv("XUI_DB_FOLDER", t.TempDir())
|
t.Setenv("XUI_DB_FOLDER", t.TempDir())
|
||||||
if err := database.InitDB(filepath.Join(t.TempDir(), "x-ui.db")); err != nil {
|
dbtest.InitDB(t, filepath.Join(t.TempDir(), "x-ui.db"))
|
||||||
t.Fatalf("InitDB: %v", err)
|
|
||||||
}
|
|
||||||
t.Cleanup(func() { _ = database.CloseDB() })
|
|
||||||
|
|
||||||
settingService := service.SettingService{}
|
settingService := service.SettingService{}
|
||||||
if err := settingService.SetTwoFactorToken("ORIGINALSECRET234567"); err != nil {
|
if err := settingService.SetTwoFactorToken("ORIGINALSECRET234567"); err != nil {
|
||||||
@@ -195,13 +190,8 @@ func TestTestDiscordEndpoint(t *testing.T) {
|
|||||||
|
|
||||||
// Setup DB
|
// Setup DB
|
||||||
t.Setenv("XUI_DB_FOLDER", t.TempDir())
|
t.Setenv("XUI_DB_FOLDER", t.TempDir())
|
||||||
if err := database.InitDB(filepath.Join(t.TempDir(), "x-ui.db")); err != nil {
|
dbtest.InitDB(t, filepath.Join(t.TempDir(), "x-ui.db"))
|
||||||
t.Fatalf("InitDB: %v", err)
|
t.Cleanup(func() { SetDiscordService(nil) })
|
||||||
}
|
|
||||||
t.Cleanup(func() {
|
|
||||||
_ = database.CloseDB()
|
|
||||||
SetDiscordService(nil)
|
|
||||||
})
|
|
||||||
|
|
||||||
settingService := service.SettingService{}
|
settingService := service.SettingService{}
|
||||||
svc := discord.NewDiscordService(settingService)
|
svc := discord.NewDiscordService(settingService)
|
||||||
|
|||||||
@@ -11,16 +11,13 @@ import (
|
|||||||
|
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
|
|
||||||
"github.com/mhsanaei/3x-ui/v3/internal/database"
|
"github.com/mhsanaei/3x-ui/v3/internal/database/dbtest"
|
||||||
)
|
)
|
||||||
|
|
||||||
func setupSubBalancerRouter(t *testing.T) *gin.Engine {
|
func setupSubBalancerRouter(t *testing.T) *gin.Engine {
|
||||||
t.Helper()
|
t.Helper()
|
||||||
t.Setenv("XUI_DB_FOLDER", t.TempDir())
|
t.Setenv("XUI_DB_FOLDER", t.TempDir())
|
||||||
if err := database.InitDB(filepath.Join(t.TempDir(), "x-ui.db")); err != nil {
|
dbtest.InitDB(t, filepath.Join(t.TempDir(), "x-ui.db"))
|
||||||
t.Fatalf("InitDB: %v", err)
|
|
||||||
}
|
|
||||||
t.Cleanup(func() { _ = database.CloseDB() })
|
|
||||||
gin.SetMode(gin.TestMode)
|
gin.SetMode(gin.TestMode)
|
||||||
router := gin.New()
|
router := gin.New()
|
||||||
NewSubBalancerController(router.Group("/panel/api"))
|
NewSubBalancerController(router.Group("/panel/api"))
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ import (
|
|||||||
"gorm.io/gorm"
|
"gorm.io/gorm"
|
||||||
|
|
||||||
"github.com/mhsanaei/3x-ui/v3/internal/database"
|
"github.com/mhsanaei/3x-ui/v3/internal/database"
|
||||||
|
"github.com/mhsanaei/3x-ui/v3/internal/database/dbtest"
|
||||||
"github.com/mhsanaei/3x-ui/v3/internal/database/model"
|
"github.com/mhsanaei/3x-ui/v3/internal/database/model"
|
||||||
"github.com/mhsanaei/3x-ui/v3/internal/web/locale"
|
"github.com/mhsanaei/3x-ui/v3/internal/web/locale"
|
||||||
)
|
)
|
||||||
@@ -21,10 +22,7 @@ func TestWarpIntervalReportsClockPersistenceFailure(t *testing.T) {
|
|||||||
gin.SetMode(gin.TestMode)
|
gin.SetMode(gin.TestMode)
|
||||||
dbDir := t.TempDir()
|
dbDir := t.TempDir()
|
||||||
t.Setenv("XUI_DB_FOLDER", dbDir)
|
t.Setenv("XUI_DB_FOLDER", dbDir)
|
||||||
if err := database.InitDB(filepath.Join(dbDir, "x-ui.db")); err != nil {
|
dbtest.InitDB(t, filepath.Join(dbDir, "x-ui.db"))
|
||||||
t.Fatalf("InitDB: %v", err)
|
|
||||||
}
|
|
||||||
t.Cleanup(func() { _ = database.CloseDB() })
|
|
||||||
db := database.GetDB()
|
db := database.GetDB()
|
||||||
for _, setting := range []*model.Setting{
|
for _, setting := range []*model.Setting{
|
||||||
{Key: "warpUpdateInterval", Value: "0"},
|
{Key: "warpUpdateInterval", Value: "0"},
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ import (
|
|||||||
"github.com/op/go-logging"
|
"github.com/op/go-logging"
|
||||||
|
|
||||||
"github.com/mhsanaei/3x-ui/v3/internal/database"
|
"github.com/mhsanaei/3x-ui/v3/internal/database"
|
||||||
|
"github.com/mhsanaei/3x-ui/v3/internal/database/dbtest"
|
||||||
"github.com/mhsanaei/3x-ui/v3/internal/database/model"
|
"github.com/mhsanaei/3x-ui/v3/internal/database/model"
|
||||||
xuilogger "github.com/mhsanaei/3x-ui/v3/internal/logger"
|
xuilogger "github.com/mhsanaei/3x-ui/v3/internal/logger"
|
||||||
)
|
)
|
||||||
@@ -47,15 +48,7 @@ func setupIntegrationDB(t *testing.T) {
|
|||||||
log.SetFlags(origLogFlags)
|
log.SetFlags(origLogFlags)
|
||||||
})
|
})
|
||||||
|
|
||||||
if err := database.InitDB(filepath.Join(dbDir, "x-ui.db")); err != nil {
|
dbtest.InitDB(t, filepath.Join(dbDir, "x-ui.db"))
|
||||||
t.Fatalf("database.InitDB failed: %v", err)
|
|
||||||
}
|
|
||||||
// LIFO cleanup order: this runs before t.TempDir's own cleanup.
|
|
||||||
t.Cleanup(func() {
|
|
||||||
if err := database.CloseDB(); err != nil {
|
|
||||||
t.Logf("database.CloseDB warning: %v", err)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// enforceIpLimitForTest runs the same two steps processObserved does: select
|
// enforceIpLimitForTest runs the same two steps processObserved does: select
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/mhsanaei/3x-ui/v3/internal/database"
|
"github.com/mhsanaei/3x-ui/v3/internal/database"
|
||||||
|
"github.com/mhsanaei/3x-ui/v3/internal/database/dbtest"
|
||||||
"github.com/mhsanaei/3x-ui/v3/internal/database/model"
|
"github.com/mhsanaei/3x-ui/v3/internal/database/model"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -197,10 +198,7 @@ func TestPartitionLiveIps_ConcurrentLiveIpsSortedAscending(t *testing.T) {
|
|||||||
func TestGetInboundByEmailFallbackIgnoresProtocolScalarFields(t *testing.T) {
|
func TestGetInboundByEmailFallbackIgnoresProtocolScalarFields(t *testing.T) {
|
||||||
dbDir := t.TempDir()
|
dbDir := t.TempDir()
|
||||||
t.Setenv("XUI_DB_FOLDER", dbDir)
|
t.Setenv("XUI_DB_FOLDER", dbDir)
|
||||||
if err := database.InitDB(filepath.Join(dbDir, "x-ui.db")); err != nil {
|
dbtest.InitDB(t, filepath.Join(dbDir, "x-ui.db"))
|
||||||
t.Fatalf("InitDB: %v", err)
|
|
||||||
}
|
|
||||||
t.Cleanup(func() { _ = database.CloseDB() })
|
|
||||||
|
|
||||||
inbound := &model.Inbound{
|
inbound := &model.Inbound{
|
||||||
UserId: 1,
|
UserId: 1,
|
||||||
|
|||||||
@@ -15,6 +15,7 @@ import (
|
|||||||
|
|
||||||
"github.com/mhsanaei/3x-ui/v3/internal/config"
|
"github.com/mhsanaei/3x-ui/v3/internal/config"
|
||||||
"github.com/mhsanaei/3x-ui/v3/internal/database"
|
"github.com/mhsanaei/3x-ui/v3/internal/database"
|
||||||
|
"github.com/mhsanaei/3x-ui/v3/internal/database/dbtest"
|
||||||
"github.com/mhsanaei/3x-ui/v3/internal/database/model"
|
"github.com/mhsanaei/3x-ui/v3/internal/database/model"
|
||||||
xuilogger "github.com/mhsanaei/3x-ui/v3/internal/logger"
|
xuilogger "github.com/mhsanaei/3x-ui/v3/internal/logger"
|
||||||
)
|
)
|
||||||
@@ -35,10 +36,7 @@ func setupScaleJobDB(t *testing.T) {
|
|||||||
}
|
}
|
||||||
switch strings.ToLower(strings.TrimSpace(os.Getenv("XUI_SCALE_TEST"))) {
|
switch strings.ToLower(strings.TrimSpace(os.Getenv("XUI_SCALE_TEST"))) {
|
||||||
case "1", "true", "yes":
|
case "1", "true", "yes":
|
||||||
if err := database.InitDB(filepath.Join(t.TempDir(), "scale.db")); err != nil {
|
dbtest.InitDB(t, filepath.Join(t.TempDir(), "scale.db"))
|
||||||
t.Fatalf("InitDB(sqlite): %v", err)
|
|
||||||
}
|
|
||||||
t.Cleanup(func() { _ = database.CloseDB() })
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
t.Skip("set XUI_SCALE_TEST=1 (sqlite) or XUI_DB_TYPE=postgres + XUI_DB_DSN (postgres) to run the scale benchmark")
|
t.Skip("set XUI_SCALE_TEST=1 (sqlite) or XUI_DB_TYPE=postgres + XUI_DB_DSN (postgres) to run the scale benchmark")
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/mhsanaei/3x-ui/v3/internal/database"
|
"github.com/mhsanaei/3x-ui/v3/internal/database"
|
||||||
|
"github.com/mhsanaei/3x-ui/v3/internal/database/dbtest"
|
||||||
"github.com/mhsanaei/3x-ui/v3/internal/database/model"
|
"github.com/mhsanaei/3x-ui/v3/internal/database/model"
|
||||||
"github.com/mhsanaei/3x-ui/v3/internal/web/service"
|
"github.com/mhsanaei/3x-ui/v3/internal/web/service"
|
||||||
)
|
)
|
||||||
@@ -13,10 +14,7 @@ func initLdapJobDB(t *testing.T) {
|
|||||||
t.Helper()
|
t.Helper()
|
||||||
dbDir := t.TempDir()
|
dbDir := t.TempDir()
|
||||||
t.Setenv("XUI_DB_FOLDER", dbDir)
|
t.Setenv("XUI_DB_FOLDER", dbDir)
|
||||||
if err := database.InitDB(filepath.Join(dbDir, "x-ui.db")); err != nil {
|
dbtest.InitDB(t, filepath.Join(dbDir, "x-ui.db"))
|
||||||
t.Fatalf("InitDB: %v", err)
|
|
||||||
}
|
|
||||||
t.Cleanup(func() { _ = database.CloseDB() })
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestBuildClient_ConvertsDefaultTotalGBToBytes(t *testing.T) {
|
func TestBuildClient_ConvertsDefaultTotalGBToBytes(t *testing.T) {
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ import (
|
|||||||
"github.com/op/go-logging"
|
"github.com/op/go-logging"
|
||||||
|
|
||||||
"github.com/mhsanaei/3x-ui/v3/internal/database"
|
"github.com/mhsanaei/3x-ui/v3/internal/database"
|
||||||
|
"github.com/mhsanaei/3x-ui/v3/internal/database/dbtest"
|
||||||
"github.com/mhsanaei/3x-ui/v3/internal/database/model"
|
"github.com/mhsanaei/3x-ui/v3/internal/database/model"
|
||||||
xuilogger "github.com/mhsanaei/3x-ui/v3/internal/logger"
|
xuilogger "github.com/mhsanaei/3x-ui/v3/internal/logger"
|
||||||
"github.com/mhsanaei/3x-ui/v3/internal/web/runtime"
|
"github.com/mhsanaei/3x-ui/v3/internal/web/runtime"
|
||||||
@@ -53,10 +54,7 @@ func TestHeartbeatDropsSubNodesOfNodesItNoLongerProbes(t *testing.T) {
|
|||||||
for _, tc := range cases {
|
for _, tc := range cases {
|
||||||
t.Run(tc.name, func(t *testing.T) {
|
t.Run(tc.name, func(t *testing.T) {
|
||||||
xuilogger.InitLogger(logging.ERROR)
|
xuilogger.InitLogger(logging.ERROR)
|
||||||
if err := database.InitDB(filepath.Join(t.TempDir(), "x-ui.db")); err != nil {
|
dbtest.InitDB(t, filepath.Join(t.TempDir(), "x-ui.db"))
|
||||||
t.Fatalf("InitDB: %v", err)
|
|
||||||
}
|
|
||||||
t.Cleanup(func() { _ = database.CloseDB() })
|
|
||||||
runtime.SetManager(runtime.NewManager(runtime.LocalDeps{APIPort: func() int { return 0 }, SetNeedRestart: func() {}}))
|
runtime.SetManager(runtime.NewManager(runtime.LocalDeps{APIPort: func() int { return 0 }, SetNeedRestart: func() {}}))
|
||||||
t.Cleanup(func() { runtime.SetManager(nil) })
|
t.Cleanup(func() { runtime.SetManager(nil) })
|
||||||
|
|
||||||
|
|||||||
@@ -16,6 +16,7 @@ import (
|
|||||||
"github.com/op/go-logging"
|
"github.com/op/go-logging"
|
||||||
|
|
||||||
"github.com/mhsanaei/3x-ui/v3/internal/database"
|
"github.com/mhsanaei/3x-ui/v3/internal/database"
|
||||||
|
"github.com/mhsanaei/3x-ui/v3/internal/database/dbtest"
|
||||||
"github.com/mhsanaei/3x-ui/v3/internal/database/model"
|
"github.com/mhsanaei/3x-ui/v3/internal/database/model"
|
||||||
xuilogger "github.com/mhsanaei/3x-ui/v3/internal/logger"
|
xuilogger "github.com/mhsanaei/3x-ui/v3/internal/logger"
|
||||||
"github.com/mhsanaei/3x-ui/v3/internal/web/runtime"
|
"github.com/mhsanaei/3x-ui/v3/internal/web/runtime"
|
||||||
@@ -26,10 +27,7 @@ import (
|
|||||||
// whole table made every node store and echo back the entire fleet's IPs.
|
// whole table made every node store and echo back the entire fleet's IPs.
|
||||||
func TestNodeTrafficSyncPushesOnlyHostedClientIps(t *testing.T) {
|
func TestNodeTrafficSyncPushesOnlyHostedClientIps(t *testing.T) {
|
||||||
xuilogger.InitLogger(logging.ERROR)
|
xuilogger.InitLogger(logging.ERROR)
|
||||||
if err := database.InitDB(filepath.Join(t.TempDir(), "x-ui.db")); err != nil {
|
dbtest.InitDB(t, filepath.Join(t.TempDir(), "x-ui.db"))
|
||||||
t.Fatalf("InitDB: %v", err)
|
|
||||||
}
|
|
||||||
t.Cleanup(func() { _ = database.CloseDB() })
|
|
||||||
service.StartTrafficWriter()
|
service.StartTrafficWriter()
|
||||||
t.Cleanup(service.StopTrafficWriter)
|
t.Cleanup(service.StopTrafficWriter)
|
||||||
runtime.SetManager(runtime.NewManager(runtime.LocalDeps{APIPort: func() int { return 0 }, SetNeedRestart: func() {}}))
|
runtime.SetManager(runtime.NewManager(runtime.LocalDeps{APIPort: func() int { return 0 }, SetNeedRestart: func() {}}))
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import (
|
|||||||
"github.com/op/go-logging"
|
"github.com/op/go-logging"
|
||||||
|
|
||||||
"github.com/mhsanaei/3x-ui/v3/internal/database"
|
"github.com/mhsanaei/3x-ui/v3/internal/database"
|
||||||
|
"github.com/mhsanaei/3x-ui/v3/internal/database/dbtest"
|
||||||
"github.com/mhsanaei/3x-ui/v3/internal/database/model"
|
"github.com/mhsanaei/3x-ui/v3/internal/database/model"
|
||||||
xuilogger "github.com/mhsanaei/3x-ui/v3/internal/logger"
|
xuilogger "github.com/mhsanaei/3x-ui/v3/internal/logger"
|
||||||
"github.com/mhsanaei/3x-ui/v3/internal/web/runtime"
|
"github.com/mhsanaei/3x-ui/v3/internal/web/runtime"
|
||||||
@@ -18,10 +19,7 @@ import (
|
|||||||
// must drop their online sets itself: a disabled node here, a deleted one below.
|
// must drop their online sets itself: a disabled node here, a deleted one below.
|
||||||
func TestNodeTrafficSyncDropsOnlineClientsOfUnsyncedNodes(t *testing.T) {
|
func TestNodeTrafficSyncDropsOnlineClientsOfUnsyncedNodes(t *testing.T) {
|
||||||
xuilogger.InitLogger(logging.ERROR)
|
xuilogger.InitLogger(logging.ERROR)
|
||||||
if err := database.InitDB(filepath.Join(t.TempDir(), "x-ui.db")); err != nil {
|
dbtest.InitDB(t, filepath.Join(t.TempDir(), "x-ui.db"))
|
||||||
t.Fatalf("InitDB: %v", err)
|
|
||||||
}
|
|
||||||
t.Cleanup(func() { _ = database.CloseDB() })
|
|
||||||
runtime.SetManager(runtime.NewManager(runtime.LocalDeps{APIPort: func() int { return 0 }, SetNeedRestart: func() {}}))
|
runtime.SetManager(runtime.NewManager(runtime.LocalDeps{APIPort: func() int { return 0 }, SetNeedRestart: func() {}}))
|
||||||
t.Cleanup(func() { runtime.SetManager(nil) })
|
t.Cleanup(func() { runtime.SetManager(nil) })
|
||||||
process := xray.NewTestProcess(nil, "")
|
process := xray.NewTestProcess(nil, "")
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ import (
|
|||||||
"github.com/op/go-logging"
|
"github.com/op/go-logging"
|
||||||
|
|
||||||
"github.com/mhsanaei/3x-ui/v3/internal/database"
|
"github.com/mhsanaei/3x-ui/v3/internal/database"
|
||||||
|
"github.com/mhsanaei/3x-ui/v3/internal/database/dbtest"
|
||||||
"github.com/mhsanaei/3x-ui/v3/internal/database/model"
|
"github.com/mhsanaei/3x-ui/v3/internal/database/model"
|
||||||
"github.com/mhsanaei/3x-ui/v3/internal/eventbus"
|
"github.com/mhsanaei/3x-ui/v3/internal/eventbus"
|
||||||
xuilogger "github.com/mhsanaei/3x-ui/v3/internal/logger"
|
xuilogger "github.com/mhsanaei/3x-ui/v3/internal/logger"
|
||||||
@@ -24,10 +25,7 @@ import (
|
|||||||
func goingDownNodes(t *testing.T, n int) {
|
func goingDownNodes(t *testing.T, n int) {
|
||||||
t.Helper()
|
t.Helper()
|
||||||
xuilogger.InitLogger(logging.ERROR)
|
xuilogger.InitLogger(logging.ERROR)
|
||||||
if err := database.InitDB(filepath.Join(t.TempDir(), "x-ui.db")); err != nil {
|
dbtest.InitDB(t, filepath.Join(t.TempDir(), "x-ui.db"))
|
||||||
t.Fatalf("InitDB: %v", err)
|
|
||||||
}
|
|
||||||
t.Cleanup(func() { _ = database.CloseDB() })
|
|
||||||
runtime.SetManager(runtime.NewManager(runtime.LocalDeps{APIPort: func() int { return 0 }, SetNeedRestart: func() {}}))
|
runtime.SetManager(runtime.NewManager(runtime.LocalDeps{APIPort: func() int { return 0 }, SetNeedRestart: func() {}}))
|
||||||
t.Cleanup(func() { runtime.SetManager(nil) })
|
t.Cleanup(func() { runtime.SetManager(nil) })
|
||||||
srv := httptest.NewServer(nil)
|
srv := httptest.NewServer(nil)
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/mhsanaei/3x-ui/v3/internal/database"
|
"github.com/mhsanaei/3x-ui/v3/internal/database"
|
||||||
|
"github.com/mhsanaei/3x-ui/v3/internal/database/dbtest"
|
||||||
"github.com/mhsanaei/3x-ui/v3/internal/database/model"
|
"github.com/mhsanaei/3x-ui/v3/internal/database/model"
|
||||||
"github.com/mhsanaei/3x-ui/v3/internal/xray"
|
"github.com/mhsanaei/3x-ui/v3/internal/xray"
|
||||||
)
|
)
|
||||||
@@ -15,10 +16,7 @@ func initResetJobDB(t *testing.T) {
|
|||||||
t.Helper()
|
t.Helper()
|
||||||
dbDir := t.TempDir()
|
dbDir := t.TempDir()
|
||||||
t.Setenv("XUI_DB_FOLDER", dbDir)
|
t.Setenv("XUI_DB_FOLDER", dbDir)
|
||||||
if err := database.InitDB(filepath.Join(dbDir, "x-ui.db")); err != nil {
|
dbtest.InitDB(t, filepath.Join(dbDir, "x-ui.db"))
|
||||||
t.Fatalf("InitDB: %v", err)
|
|
||||||
}
|
|
||||||
t.Cleanup(func() { _ = database.CloseDB() })
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type seededClient struct {
|
type seededClient struct {
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ import (
|
|||||||
|
|
||||||
"github.com/robfig/cron/v3"
|
"github.com/robfig/cron/v3"
|
||||||
|
|
||||||
"github.com/mhsanaei/3x-ui/v3/internal/database"
|
"github.com/mhsanaei/3x-ui/v3/internal/database/dbtest"
|
||||||
"github.com/mhsanaei/3x-ui/v3/internal/web/global"
|
"github.com/mhsanaei/3x-ui/v3/internal/web/global"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -44,10 +44,7 @@ func inContractScope(method, path string) bool {
|
|||||||
|
|
||||||
func registeredContractRoutes(t *testing.T) map[string]bool {
|
func registeredContractRoutes(t *testing.T) map[string]bool {
|
||||||
t.Helper()
|
t.Helper()
|
||||||
if err := database.InitDB(filepath.Join(t.TempDir(), "x-ui.db")); err != nil {
|
dbtest.InitDB(t, filepath.Join(t.TempDir(), "x-ui.db"))
|
||||||
t.Fatalf("init db: %v", err)
|
|
||||||
}
|
|
||||||
t.Cleanup(func() { _ = database.CloseDB() })
|
|
||||||
|
|
||||||
previous := global.GetWebServer()
|
previous := global.GetWebServer()
|
||||||
s := NewServer()
|
s := NewServer()
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/mhsanaei/3x-ui/v3/internal/database"
|
"github.com/mhsanaei/3x-ui/v3/internal/database"
|
||||||
|
"github.com/mhsanaei/3x-ui/v3/internal/database/dbtest"
|
||||||
"github.com/mhsanaei/3x-ui/v3/internal/database/model"
|
"github.com/mhsanaei/3x-ui/v3/internal/database/model"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -14,10 +15,7 @@ func setupBulkDB(t *testing.T) {
|
|||||||
t.Helper()
|
t.Helper()
|
||||||
dbDir := t.TempDir()
|
dbDir := t.TempDir()
|
||||||
t.Setenv("XUI_DB_FOLDER", dbDir)
|
t.Setenv("XUI_DB_FOLDER", dbDir)
|
||||||
if err := database.InitDB(filepath.Join(dbDir, "x-ui.db")); err != nil {
|
dbtest.InitDB(t, filepath.Join(dbDir, "x-ui.db"))
|
||||||
t.Fatalf("InitDB: %v", err)
|
|
||||||
}
|
|
||||||
t.Cleanup(func() { _ = database.CloseDB() })
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func clientsSettings(t *testing.T, clients []model.Client) string {
|
func clientsSettings(t *testing.T, clients []model.Client) string {
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/mhsanaei/3x-ui/v3/internal/database"
|
"github.com/mhsanaei/3x-ui/v3/internal/database"
|
||||||
|
"github.com/mhsanaei/3x-ui/v3/internal/database/dbtest"
|
||||||
"github.com/mhsanaei/3x-ui/v3/internal/database/model"
|
"github.com/mhsanaei/3x-ui/v3/internal/database/model"
|
||||||
"github.com/mhsanaei/3x-ui/v3/internal/xray"
|
"github.com/mhsanaei/3x-ui/v3/internal/xray"
|
||||||
)
|
)
|
||||||
@@ -16,10 +17,7 @@ import (
|
|||||||
func TestResetClientExpiryTimeByEmail_MultiInbound(t *testing.T) {
|
func TestResetClientExpiryTimeByEmail_MultiInbound(t *testing.T) {
|
||||||
dbDir := t.TempDir()
|
dbDir := t.TempDir()
|
||||||
t.Setenv("XUI_DB_FOLDER", dbDir)
|
t.Setenv("XUI_DB_FOLDER", dbDir)
|
||||||
if err := database.InitDB(filepath.Join(dbDir, "x-ui.db")); err != nil {
|
dbtest.InitDB(t, filepath.Join(dbDir, "x-ui.db"))
|
||||||
t.Fatalf("InitDB: %v", err)
|
|
||||||
}
|
|
||||||
t.Cleanup(func() { _ = database.CloseDB() })
|
|
||||||
|
|
||||||
db := database.GetDB()
|
db := database.GetDB()
|
||||||
|
|
||||||
@@ -91,10 +89,7 @@ func TestResetClientExpiryTimeByEmail_MultiInbound(t *testing.T) {
|
|||||||
func TestSetClientEnableByEmail_MultiInbound(t *testing.T) {
|
func TestSetClientEnableByEmail_MultiInbound(t *testing.T) {
|
||||||
dbDir := t.TempDir()
|
dbDir := t.TempDir()
|
||||||
t.Setenv("XUI_DB_FOLDER", dbDir)
|
t.Setenv("XUI_DB_FOLDER", dbDir)
|
||||||
if err := database.InitDB(filepath.Join(dbDir, "x-ui.db")); err != nil {
|
dbtest.InitDB(t, filepath.Join(dbDir, "x-ui.db"))
|
||||||
t.Fatalf("InitDB: %v", err)
|
|
||||||
}
|
|
||||||
t.Cleanup(func() { _ = database.CloseDB() })
|
|
||||||
|
|
||||||
db := database.GetDB()
|
db := database.GetDB()
|
||||||
|
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/mhsanaei/3x-ui/v3/internal/database"
|
"github.com/mhsanaei/3x-ui/v3/internal/database"
|
||||||
|
"github.com/mhsanaei/3x-ui/v3/internal/database/dbtest"
|
||||||
"github.com/mhsanaei/3x-ui/v3/internal/database/model"
|
"github.com/mhsanaei/3x-ui/v3/internal/database/model"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -14,10 +15,7 @@ import (
|
|||||||
func TestEffectiveFlowsByEmails(t *testing.T) {
|
func TestEffectiveFlowsByEmails(t *testing.T) {
|
||||||
dbDir := t.TempDir()
|
dbDir := t.TempDir()
|
||||||
t.Setenv("XUI_DB_FOLDER", dbDir)
|
t.Setenv("XUI_DB_FOLDER", dbDir)
|
||||||
if err := database.InitDB(filepath.Join(dbDir, "x-ui.db")); err != nil {
|
dbtest.InitDB(t, filepath.Join(dbDir, "x-ui.db"))
|
||||||
t.Fatalf("InitDB: %v", err)
|
|
||||||
}
|
|
||||||
t.Cleanup(func() { _ = database.CloseDB() })
|
|
||||||
db := database.GetDB()
|
db := database.GetDB()
|
||||||
|
|
||||||
const vision = "xtls-rprx-vision"
|
const vision = "xtls-rprx-vision"
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/mhsanaei/3x-ui/v3/internal/database"
|
"github.com/mhsanaei/3x-ui/v3/internal/database"
|
||||||
|
"github.com/mhsanaei/3x-ui/v3/internal/database/dbtest"
|
||||||
"github.com/mhsanaei/3x-ui/v3/internal/database/model"
|
"github.com/mhsanaei/3x-ui/v3/internal/database/model"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -46,10 +47,7 @@ func TestClientWithInboundFlow_GatesByInboundCapability(t *testing.T) {
|
|||||||
func TestFlowIsolation_VisionDoesNotLeakToWsInbound(t *testing.T) {
|
func TestFlowIsolation_VisionDoesNotLeakToWsInbound(t *testing.T) {
|
||||||
dbDir := t.TempDir()
|
dbDir := t.TempDir()
|
||||||
t.Setenv("XUI_DB_FOLDER", dbDir)
|
t.Setenv("XUI_DB_FOLDER", dbDir)
|
||||||
if err := database.InitDB(filepath.Join(dbDir, "x-ui.db")); err != nil {
|
dbtest.InitDB(t, filepath.Join(dbDir, "x-ui.db"))
|
||||||
t.Fatalf("InitDB: %v", err)
|
|
||||||
}
|
|
||||||
t.Cleanup(func() { _ = database.CloseDB() })
|
|
||||||
|
|
||||||
db := database.GetDB()
|
db := database.GetDB()
|
||||||
|
|
||||||
@@ -95,10 +93,7 @@ func TestFlowIsolation_VisionDoesNotLeakToWsInbound(t *testing.T) {
|
|||||||
func TestEffectiveFlow_NonFlowInboundSyncedLastDoesNotHideVision(t *testing.T) {
|
func TestEffectiveFlow_NonFlowInboundSyncedLastDoesNotHideVision(t *testing.T) {
|
||||||
dbDir := t.TempDir()
|
dbDir := t.TempDir()
|
||||||
t.Setenv("XUI_DB_FOLDER", dbDir)
|
t.Setenv("XUI_DB_FOLDER", dbDir)
|
||||||
if err := database.InitDB(filepath.Join(dbDir, "x-ui.db")); err != nil {
|
dbtest.InitDB(t, filepath.Join(dbDir, "x-ui.db"))
|
||||||
t.Fatalf("InitDB: %v", err)
|
|
||||||
}
|
|
||||||
t.Cleanup(func() { _ = database.CloseDB() })
|
|
||||||
|
|
||||||
db := database.GetDB()
|
db := database.GetDB()
|
||||||
reality := &model.Inbound{Tag: "vless-reality", Enable: true, Port: 40001, Protocol: model.VLESS, StreamSettings: `{"network":"tcp","security":"reality"}`}
|
reality := &model.Inbound{Tag: "vless-reality", Enable: true, Port: 40001, Protocol: model.VLESS, StreamSettings: `{"network":"tcp","security":"reality"}`}
|
||||||
@@ -145,10 +140,7 @@ func TestEffectiveFlow_NonFlowInboundSyncedLastDoesNotHideVision(t *testing.T) {
|
|||||||
func TestEffectiveFlow_ClearedFlowStaysCleared(t *testing.T) {
|
func TestEffectiveFlow_ClearedFlowStaysCleared(t *testing.T) {
|
||||||
dbDir := t.TempDir()
|
dbDir := t.TempDir()
|
||||||
t.Setenv("XUI_DB_FOLDER", dbDir)
|
t.Setenv("XUI_DB_FOLDER", dbDir)
|
||||||
if err := database.InitDB(filepath.Join(dbDir, "x-ui.db")); err != nil {
|
dbtest.InitDB(t, filepath.Join(dbDir, "x-ui.db"))
|
||||||
t.Fatalf("InitDB: %v", err)
|
|
||||||
}
|
|
||||||
t.Cleanup(func() { _ = database.CloseDB() })
|
|
||||||
|
|
||||||
db := database.GetDB()
|
db := database.GetDB()
|
||||||
reality := &model.Inbound{Tag: "vless-reality", Enable: true, Port: 41001, Protocol: model.VLESS, StreamSettings: `{"network":"tcp","security":"reality"}`}
|
reality := &model.Inbound{Tag: "vless-reality", Enable: true, Port: 41001, Protocol: model.VLESS, StreamSettings: `{"network":"tcp","security":"reality"}`}
|
||||||
@@ -191,10 +183,7 @@ func TestEffectiveFlow_ClearedFlowStaysCleared(t *testing.T) {
|
|||||||
func TestAttach_PreservesVisionFlowWhenCanonicalColumnZeroed(t *testing.T) {
|
func TestAttach_PreservesVisionFlowWhenCanonicalColumnZeroed(t *testing.T) {
|
||||||
dbDir := t.TempDir()
|
dbDir := t.TempDir()
|
||||||
t.Setenv("XUI_DB_FOLDER", dbDir)
|
t.Setenv("XUI_DB_FOLDER", dbDir)
|
||||||
if err := database.InitDB(filepath.Join(dbDir, "x-ui.db")); err != nil {
|
dbtest.InitDB(t, filepath.Join(dbDir, "x-ui.db"))
|
||||||
t.Fatalf("InitDB: %v", err)
|
|
||||||
}
|
|
||||||
t.Cleanup(func() { _ = database.CloseDB() })
|
|
||||||
|
|
||||||
db := database.GetDB()
|
db := database.GetDB()
|
||||||
|
|
||||||
@@ -267,10 +256,7 @@ func TestAttach_PreservesVisionFlowWhenCanonicalColumnZeroed(t *testing.T) {
|
|||||||
func TestBulkAttach_PreservesVisionFlowWhenCanonicalColumnZeroed(t *testing.T) {
|
func TestBulkAttach_PreservesVisionFlowWhenCanonicalColumnZeroed(t *testing.T) {
|
||||||
dbDir := t.TempDir()
|
dbDir := t.TempDir()
|
||||||
t.Setenv("XUI_DB_FOLDER", dbDir)
|
t.Setenv("XUI_DB_FOLDER", dbDir)
|
||||||
if err := database.InitDB(filepath.Join(dbDir, "x-ui.db")); err != nil {
|
dbtest.InitDB(t, filepath.Join(dbDir, "x-ui.db"))
|
||||||
t.Fatalf("InitDB: %v", err)
|
|
||||||
}
|
|
||||||
t.Cleanup(func() { _ = database.CloseDB() })
|
|
||||||
|
|
||||||
db := database.GetDB()
|
db := database.GetDB()
|
||||||
|
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/mhsanaei/3x-ui/v3/internal/database"
|
"github.com/mhsanaei/3x-ui/v3/internal/database"
|
||||||
|
"github.com/mhsanaei/3x-ui/v3/internal/database/dbtest"
|
||||||
"github.com/mhsanaei/3x-ui/v3/internal/database/model"
|
"github.com/mhsanaei/3x-ui/v3/internal/database/model"
|
||||||
"github.com/mhsanaei/3x-ui/v3/internal/web/runtime"
|
"github.com/mhsanaei/3x-ui/v3/internal/web/runtime"
|
||||||
)
|
)
|
||||||
@@ -13,10 +14,7 @@ import (
|
|||||||
func TestSetRemoteTraffic_PreservesPanelLocalGroupAndComment(t *testing.T) {
|
func TestSetRemoteTraffic_PreservesPanelLocalGroupAndComment(t *testing.T) {
|
||||||
dbDir := t.TempDir()
|
dbDir := t.TempDir()
|
||||||
t.Setenv("XUI_DB_FOLDER", dbDir)
|
t.Setenv("XUI_DB_FOLDER", dbDir)
|
||||||
if err := database.InitDB(filepath.Join(dbDir, "x-ui.db")); err != nil {
|
dbtest.InitDB(t, filepath.Join(dbDir, "x-ui.db"))
|
||||||
t.Fatalf("InitDB: %v", err)
|
|
||||||
}
|
|
||||||
t.Cleanup(func() { _ = database.CloseDB() })
|
|
||||||
|
|
||||||
db := database.GetDB()
|
db := database.GetDB()
|
||||||
|
|
||||||
@@ -82,10 +80,7 @@ func TestSetRemoteTraffic_PreservesPanelLocalGroupAndComment(t *testing.T) {
|
|||||||
func TestSyncInbound_KeepsGroupWhenIncomingEmpty(t *testing.T) {
|
func TestSyncInbound_KeepsGroupWhenIncomingEmpty(t *testing.T) {
|
||||||
dbDir := t.TempDir()
|
dbDir := t.TempDir()
|
||||||
t.Setenv("XUI_DB_FOLDER", dbDir)
|
t.Setenv("XUI_DB_FOLDER", dbDir)
|
||||||
if err := database.InitDB(filepath.Join(dbDir, "x-ui.db")); err != nil {
|
dbtest.InitDB(t, filepath.Join(dbDir, "x-ui.db"))
|
||||||
t.Fatalf("InitDB: %v", err)
|
|
||||||
}
|
|
||||||
t.Cleanup(func() { _ = database.CloseDB() })
|
|
||||||
|
|
||||||
db := database.GetDB()
|
db := database.GetDB()
|
||||||
|
|
||||||
@@ -125,10 +120,7 @@ func TestSyncInbound_KeepsGroupWhenIncomingEmpty(t *testing.T) {
|
|||||||
func TestClientUpdate_ClearsGroup(t *testing.T) {
|
func TestClientUpdate_ClearsGroup(t *testing.T) {
|
||||||
dbDir := t.TempDir()
|
dbDir := t.TempDir()
|
||||||
t.Setenv("XUI_DB_FOLDER", dbDir)
|
t.Setenv("XUI_DB_FOLDER", dbDir)
|
||||||
if err := database.InitDB(filepath.Join(dbDir, "x-ui.db")); err != nil {
|
dbtest.InitDB(t, filepath.Join(dbDir, "x-ui.db"))
|
||||||
t.Fatalf("InitDB: %v", err)
|
|
||||||
}
|
|
||||||
t.Cleanup(func() { _ = database.CloseDB() })
|
|
||||||
|
|
||||||
db := database.GetDB()
|
db := database.GetDB()
|
||||||
|
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/mhsanaei/3x-ui/v3/internal/database"
|
"github.com/mhsanaei/3x-ui/v3/internal/database"
|
||||||
|
"github.com/mhsanaei/3x-ui/v3/internal/database/dbtest"
|
||||||
"github.com/mhsanaei/3x-ui/v3/internal/database/model"
|
"github.com/mhsanaei/3x-ui/v3/internal/database/model"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -12,10 +13,7 @@ func initClientHwidTestDB(t *testing.T) {
|
|||||||
t.Helper()
|
t.Helper()
|
||||||
dbDir := t.TempDir()
|
dbDir := t.TempDir()
|
||||||
t.Setenv("XUI_DB_FOLDER", dbDir)
|
t.Setenv("XUI_DB_FOLDER", dbDir)
|
||||||
if err := database.InitDB(filepath.Join(dbDir, "x-ui.db")); err != nil {
|
dbtest.InitDB(t, filepath.Join(dbDir, "x-ui.db"))
|
||||||
t.Fatalf("InitDB: %v", err)
|
|
||||||
}
|
|
||||||
t.Cleanup(func() { _ = database.CloseDB() })
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func seedHwidClient(t *testing.T, limit int) *model.ClientRecord {
|
func seedHwidClient(t *testing.T, limit int) *model.ClientRecord {
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/mhsanaei/3x-ui/v3/internal/database"
|
"github.com/mhsanaei/3x-ui/v3/internal/database"
|
||||||
|
"github.com/mhsanaei/3x-ui/v3/internal/database/dbtest"
|
||||||
"github.com/mhsanaei/3x-ui/v3/internal/database/model"
|
"github.com/mhsanaei/3x-ui/v3/internal/database/model"
|
||||||
|
|
||||||
"gorm.io/gorm"
|
"gorm.io/gorm"
|
||||||
@@ -188,10 +189,7 @@ func TestSetClientLimitHwidIsSerializedWithSyncInbound(t *testing.T) {
|
|||||||
func BenchmarkSetClientLimitHwidSerialized(b *testing.B) {
|
func BenchmarkSetClientLimitHwidSerialized(b *testing.B) {
|
||||||
dbDir := b.TempDir()
|
dbDir := b.TempDir()
|
||||||
b.Setenv("XUI_DB_FOLDER", dbDir)
|
b.Setenv("XUI_DB_FOLDER", dbDir)
|
||||||
if err := database.InitDB(filepath.Join(dbDir, "x-ui.db")); err != nil {
|
dbtest.InitDB(b, filepath.Join(dbDir, "x-ui.db"))
|
||||||
b.Fatalf("InitDB: %v", err)
|
|
||||||
}
|
|
||||||
b.Cleanup(func() { _ = database.CloseDB() })
|
|
||||||
StartTrafficWriter()
|
StartTrafficWriter()
|
||||||
b.Cleanup(StopTrafficWriter)
|
b.Cleanup(StopTrafficWriter)
|
||||||
db := database.GetDB()
|
db := database.GetDB()
|
||||||
|
|||||||
@@ -5,16 +5,14 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/mhsanaei/3x-ui/v3/internal/database"
|
"github.com/mhsanaei/3x-ui/v3/internal/database"
|
||||||
|
"github.com/mhsanaei/3x-ui/v3/internal/database/dbtest"
|
||||||
"github.com/mhsanaei/3x-ui/v3/internal/database/model"
|
"github.com/mhsanaei/3x-ui/v3/internal/database/model"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestSyncInbound_UpdatesMtprotoSecretAndAdTag(t *testing.T) {
|
func TestSyncInbound_UpdatesMtprotoSecretAndAdTag(t *testing.T) {
|
||||||
dbDir := t.TempDir()
|
dbDir := t.TempDir()
|
||||||
t.Setenv("XUI_DB_FOLDER", dbDir)
|
t.Setenv("XUI_DB_FOLDER", dbDir)
|
||||||
if err := database.InitDB(filepath.Join(dbDir, "x-ui.db")); err != nil {
|
dbtest.InitDB(t, filepath.Join(dbDir, "x-ui.db"))
|
||||||
t.Fatalf("InitDB: %v", err)
|
|
||||||
}
|
|
||||||
t.Cleanup(func() { _ = database.CloseDB() })
|
|
||||||
|
|
||||||
db := database.GetDB()
|
db := database.GetDB()
|
||||||
|
|
||||||
|
|||||||
@@ -5,16 +5,14 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/mhsanaei/3x-ui/v3/internal/database"
|
"github.com/mhsanaei/3x-ui/v3/internal/database"
|
||||||
|
"github.com/mhsanaei/3x-ui/v3/internal/database/dbtest"
|
||||||
"github.com/mhsanaei/3x-ui/v3/internal/database/model"
|
"github.com/mhsanaei/3x-ui/v3/internal/database/model"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestSyncInbound_PreservesCredentialsAcrossProtocols(t *testing.T) {
|
func TestSyncInbound_PreservesCredentialsAcrossProtocols(t *testing.T) {
|
||||||
dbDir := t.TempDir()
|
dbDir := t.TempDir()
|
||||||
t.Setenv("XUI_DB_FOLDER", dbDir)
|
t.Setenv("XUI_DB_FOLDER", dbDir)
|
||||||
if err := database.InitDB(filepath.Join(dbDir, "x-ui.db")); err != nil {
|
dbtest.InitDB(t, filepath.Join(dbDir, "x-ui.db"))
|
||||||
t.Fatalf("InitDB: %v", err)
|
|
||||||
}
|
|
||||||
t.Cleanup(func() { _ = database.CloseDB() })
|
|
||||||
|
|
||||||
db := database.GetDB()
|
db := database.GetDB()
|
||||||
|
|
||||||
@@ -74,10 +72,7 @@ func TestSyncInbound_PreservesCredentialsAcrossProtocols(t *testing.T) {
|
|||||||
func TestSyncInbound_AllowsClearingFlow(t *testing.T) {
|
func TestSyncInbound_AllowsClearingFlow(t *testing.T) {
|
||||||
dbDir := t.TempDir()
|
dbDir := t.TempDir()
|
||||||
t.Setenv("XUI_DB_FOLDER", dbDir)
|
t.Setenv("XUI_DB_FOLDER", dbDir)
|
||||||
if err := database.InitDB(filepath.Join(dbDir, "x-ui.db")); err != nil {
|
dbtest.InitDB(t, filepath.Join(dbDir, "x-ui.db"))
|
||||||
t.Fatalf("InitDB: %v", err)
|
|
||||||
}
|
|
||||||
t.Cleanup(func() { _ = database.CloseDB() })
|
|
||||||
|
|
||||||
db := database.GetDB()
|
db := database.GetDB()
|
||||||
|
|
||||||
|
|||||||
@@ -11,17 +11,14 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/mhsanaei/3x-ui/v3/internal/database"
|
"github.com/mhsanaei/3x-ui/v3/internal/database/dbtest"
|
||||||
"github.com/mhsanaei/3x-ui/v3/internal/web/service"
|
"github.com/mhsanaei/3x-ui/v3/internal/web/service"
|
||||||
)
|
)
|
||||||
|
|
||||||
func setupTestDB(t *testing.T) service.SettingService {
|
func setupTestDB(t *testing.T) service.SettingService {
|
||||||
t.Helper()
|
t.Helper()
|
||||||
dbPath := filepath.Join(t.TempDir(), "x-ui.db")
|
dbPath := filepath.Join(t.TempDir(), "x-ui.db")
|
||||||
if err := database.InitDB(dbPath); err != nil {
|
dbtest.InitDB(t, dbPath)
|
||||||
t.Fatalf("init db: %v", err)
|
|
||||||
}
|
|
||||||
t.Cleanup(func() { _ = database.CloseDB() })
|
|
||||||
return service.SettingService{}
|
return service.SettingService{}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ import (
|
|||||||
"sync"
|
"sync"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/mhsanaei/3x-ui/v3/internal/database"
|
"github.com/mhsanaei/3x-ui/v3/internal/database/dbtest"
|
||||||
"github.com/mhsanaei/3x-ui/v3/internal/web/service"
|
"github.com/mhsanaei/3x-ui/v3/internal/web/service"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -132,10 +132,7 @@ func startFakeSMTPServer(t *testing.T) (string, func() []string) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestSendUsesBareAddressFromNameAddrSmtpFrom(t *testing.T) {
|
func TestSendUsesBareAddressFromNameAddrSmtpFrom(t *testing.T) {
|
||||||
if err := database.InitDB(filepath.Join(t.TempDir(), "x-ui.db")); err != nil {
|
dbtest.InitDB(t, filepath.Join(t.TempDir(), "x-ui.db"))
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
t.Cleanup(func() { _ = database.CloseDB() })
|
|
||||||
|
|
||||||
addr, recordedLines := startFakeSMTPServer(t)
|
addr, recordedLines := startFakeSMTPServer(t)
|
||||||
host, portStr, err := net.SplitHostPort(addr)
|
host, portStr, err := net.SplitHostPort(addr)
|
||||||
@@ -182,10 +179,7 @@ func TestSendUsesBareAddressFromNameAddrSmtpFrom(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestConnectionReportsMissingFrom(t *testing.T) {
|
func TestConnectionReportsMissingFrom(t *testing.T) {
|
||||||
if err := database.InitDB(filepath.Join(t.TempDir(), "x-ui.db")); err != nil {
|
dbtest.InitDB(t, filepath.Join(t.TempDir(), "x-ui.db"))
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
t.Cleanup(func() { _ = database.CloseDB() })
|
|
||||||
|
|
||||||
settingService := service.SettingService{}
|
settingService := service.SettingService{}
|
||||||
mustSet := func(name string, err error) {
|
mustSet := func(name string, err error) {
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ import (
|
|||||||
"golang.org/x/crypto/chacha20poly1305"
|
"golang.org/x/crypto/chacha20poly1305"
|
||||||
|
|
||||||
"github.com/mhsanaei/3x-ui/v3/internal/database"
|
"github.com/mhsanaei/3x-ui/v3/internal/database"
|
||||||
|
"github.com/mhsanaei/3x-ui/v3/internal/database/dbtest"
|
||||||
"github.com/mhsanaei/3x-ui/v3/internal/database/model"
|
"github.com/mhsanaei/3x-ui/v3/internal/database/model"
|
||||||
"github.com/mhsanaei/3x-ui/v3/internal/logger"
|
"github.com/mhsanaei/3x-ui/v3/internal/logger"
|
||||||
)
|
)
|
||||||
@@ -30,10 +31,7 @@ func initHappTestDB(t *testing.T) {
|
|||||||
if err := os.WriteFile(filepath.Join(dbDir, "config.json"), []byte(`{"log":{}}`), 0o600); err != nil {
|
if err := os.WriteFile(filepath.Join(dbDir, "config.json"), []byte(`{"log":{}}`), 0o600); err != nil {
|
||||||
t.Fatalf("write Xray config: %v", err)
|
t.Fatalf("write Xray config: %v", err)
|
||||||
}
|
}
|
||||||
if err := database.InitDB(filepath.Join(dbDir, "x-ui.db")); err != nil {
|
dbtest.InitDB(t, filepath.Join(dbDir, "x-ui.db"))
|
||||||
t.Fatalf("InitDB: %v", err)
|
|
||||||
}
|
|
||||||
t.Cleanup(func() { _ = database.CloseDB() })
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func seedHappClient(t *testing.T, subID string) *model.ClientRecord {
|
func seedHappClient(t *testing.T, subID string) *model.ClientRecord {
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/mhsanaei/3x-ui/v3/internal/database"
|
"github.com/mhsanaei/3x-ui/v3/internal/database"
|
||||||
|
"github.com/mhsanaei/3x-ui/v3/internal/database/dbtest"
|
||||||
"github.com/mhsanaei/3x-ui/v3/internal/database/model"
|
"github.com/mhsanaei/3x-ui/v3/internal/database/model"
|
||||||
|
|
||||||
"gorm.io/gorm"
|
"gorm.io/gorm"
|
||||||
@@ -18,10 +19,7 @@ func setupClientIpTestDB(t *testing.T) {
|
|||||||
t.Helper()
|
t.Helper()
|
||||||
dbDir := t.TempDir()
|
dbDir := t.TempDir()
|
||||||
t.Setenv("XUI_DB_FOLDER", dbDir)
|
t.Setenv("XUI_DB_FOLDER", dbDir)
|
||||||
if err := database.InitDB(filepath.Join(dbDir, "x-ui.db")); err != nil {
|
dbtest.InitDB(t, filepath.Join(dbDir, "x-ui.db"))
|
||||||
t.Fatalf("InitDB: %v", err)
|
|
||||||
}
|
|
||||||
t.Cleanup(func() { _ = database.CloseDB() })
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func marshalIps(t *testing.T, entries ...clientIpEntry) string {
|
func marshalIps(t *testing.T, entries ...clientIpEntry) string {
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/mhsanaei/3x-ui/v3/internal/database"
|
"github.com/mhsanaei/3x-ui/v3/internal/database"
|
||||||
|
"github.com/mhsanaei/3x-ui/v3/internal/database/dbtest"
|
||||||
"github.com/mhsanaei/3x-ui/v3/internal/database/model"
|
"github.com/mhsanaei/3x-ui/v3/internal/database/model"
|
||||||
"github.com/mhsanaei/3x-ui/v3/internal/xray"
|
"github.com/mhsanaei/3x-ui/v3/internal/xray"
|
||||||
)
|
)
|
||||||
@@ -26,10 +27,7 @@ import (
|
|||||||
func TestAddClientTraffic_MatchesByEmail(t *testing.T) {
|
func TestAddClientTraffic_MatchesByEmail(t *testing.T) {
|
||||||
dbDir := t.TempDir()
|
dbDir := t.TempDir()
|
||||||
t.Setenv("XUI_DB_FOLDER", dbDir)
|
t.Setenv("XUI_DB_FOLDER", dbDir)
|
||||||
if err := database.InitDB(filepath.Join(dbDir, "x-ui.db")); err != nil {
|
dbtest.InitDB(t, filepath.Join(dbDir, "x-ui.db"))
|
||||||
t.Fatalf("InitDB: %v", err)
|
|
||||||
}
|
|
||||||
t.Cleanup(func() { _ = database.CloseDB() })
|
|
||||||
|
|
||||||
db := database.GetDB()
|
db := database.GetDB()
|
||||||
|
|
||||||
@@ -97,10 +95,7 @@ func TestAddClientTraffic_MatchesByEmail(t *testing.T) {
|
|||||||
func TestAdjustTraffics_DelayedStartConvertsDespiteStaleInboundId(t *testing.T) {
|
func TestAdjustTraffics_DelayedStartConvertsDespiteStaleInboundId(t *testing.T) {
|
||||||
dbDir := t.TempDir()
|
dbDir := t.TempDir()
|
||||||
t.Setenv("XUI_DB_FOLDER", dbDir)
|
t.Setenv("XUI_DB_FOLDER", dbDir)
|
||||||
if err := database.InitDB(filepath.Join(dbDir, "x-ui.db")); err != nil {
|
dbtest.InitDB(t, filepath.Join(dbDir, "x-ui.db"))
|
||||||
t.Fatalf("InitDB: %v", err)
|
|
||||||
}
|
|
||||||
t.Cleanup(func() { _ = database.CloseDB() })
|
|
||||||
|
|
||||||
db := database.GetDB()
|
db := database.GetDB()
|
||||||
|
|
||||||
@@ -166,10 +161,7 @@ func TestAdjustTraffics_DelayedStartConvertsDespiteStaleInboundId(t *testing.T)
|
|||||||
func TestAddClientTraffic_ExpiryWriteOnlyForConvertedClients(t *testing.T) {
|
func TestAddClientTraffic_ExpiryWriteOnlyForConvertedClients(t *testing.T) {
|
||||||
dbDir := t.TempDir()
|
dbDir := t.TempDir()
|
||||||
t.Setenv("XUI_DB_FOLDER", dbDir)
|
t.Setenv("XUI_DB_FOLDER", dbDir)
|
||||||
if err := database.InitDB(filepath.Join(dbDir, "x-ui.db")); err != nil {
|
dbtest.InitDB(t, filepath.Join(dbDir, "x-ui.db"))
|
||||||
t.Fatalf("InitDB: %v", err)
|
|
||||||
}
|
|
||||||
t.Cleanup(func() { _ = database.CloseDB() })
|
|
||||||
|
|
||||||
db := database.GetDB()
|
db := database.GetDB()
|
||||||
|
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/mhsanaei/3x-ui/v3/internal/database"
|
"github.com/mhsanaei/3x-ui/v3/internal/database"
|
||||||
|
"github.com/mhsanaei/3x-ui/v3/internal/database/dbtest"
|
||||||
"github.com/mhsanaei/3x-ui/v3/internal/database/model"
|
"github.com/mhsanaei/3x-ui/v3/internal/database/model"
|
||||||
|
|
||||||
"gorm.io/gorm"
|
"gorm.io/gorm"
|
||||||
@@ -95,10 +96,7 @@ func initFlowTestDB(t *testing.T) *gorm.DB {
|
|||||||
t.Helper()
|
t.Helper()
|
||||||
dbDir := t.TempDir()
|
dbDir := t.TempDir()
|
||||||
t.Setenv("XUI_DB_FOLDER", dbDir)
|
t.Setenv("XUI_DB_FOLDER", dbDir)
|
||||||
if err := database.InitDB(filepath.Join(dbDir, "x-ui.db")); err != nil {
|
dbtest.InitDB(t, filepath.Join(dbDir, "x-ui.db"))
|
||||||
t.Fatalf("InitDB: %v", err)
|
|
||||||
}
|
|
||||||
t.Cleanup(func() { _ = database.CloseDB() })
|
|
||||||
return database.GetDB()
|
return database.GetDB()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/mhsanaei/3x-ui/v3/internal/database"
|
"github.com/mhsanaei/3x-ui/v3/internal/database"
|
||||||
|
"github.com/mhsanaei/3x-ui/v3/internal/database/dbtest"
|
||||||
"github.com/mhsanaei/3x-ui/v3/internal/database/model"
|
"github.com/mhsanaei/3x-ui/v3/internal/database/model"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -16,10 +17,7 @@ import (
|
|||||||
func TestRestoreVisionFlowForEligibleInbound(t *testing.T) {
|
func TestRestoreVisionFlowForEligibleInbound(t *testing.T) {
|
||||||
dbDir := t.TempDir()
|
dbDir := t.TempDir()
|
||||||
t.Setenv("XUI_DB_FOLDER", dbDir)
|
t.Setenv("XUI_DB_FOLDER", dbDir)
|
||||||
if err := database.InitDB(filepath.Join(dbDir, "x-ui.db")); err != nil {
|
dbtest.InitDB(t, filepath.Join(dbDir, "x-ui.db"))
|
||||||
t.Fatalf("InitDB: %v", err)
|
|
||||||
}
|
|
||||||
t.Cleanup(func() { _ = database.CloseDB() })
|
|
||||||
db := database.GetDB()
|
db := database.GetDB()
|
||||||
|
|
||||||
const vision = "xtls-rprx-vision"
|
const vision = "xtls-rprx-vision"
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ import (
|
|||||||
"gorm.io/gorm"
|
"gorm.io/gorm"
|
||||||
|
|
||||||
"github.com/mhsanaei/3x-ui/v3/internal/database"
|
"github.com/mhsanaei/3x-ui/v3/internal/database"
|
||||||
|
"github.com/mhsanaei/3x-ui/v3/internal/database/dbtest"
|
||||||
"github.com/mhsanaei/3x-ui/v3/internal/database/model"
|
"github.com/mhsanaei/3x-ui/v3/internal/database/model"
|
||||||
"github.com/mhsanaei/3x-ui/v3/internal/xray"
|
"github.com/mhsanaei/3x-ui/v3/internal/xray"
|
||||||
)
|
)
|
||||||
@@ -22,10 +23,7 @@ import (
|
|||||||
func TestMigrationRequirements_BackfillsClientTrafficsWithMultiDomainInbound(t *testing.T) {
|
func TestMigrationRequirements_BackfillsClientTrafficsWithMultiDomainInbound(t *testing.T) {
|
||||||
dbDir := t.TempDir()
|
dbDir := t.TempDir()
|
||||||
t.Setenv("XUI_DB_FOLDER", dbDir)
|
t.Setenv("XUI_DB_FOLDER", dbDir)
|
||||||
if err := database.InitDB(filepath.Join(dbDir, "x-ui.db")); err != nil {
|
dbtest.InitDB(t, filepath.Join(dbDir, "x-ui.db"))
|
||||||
t.Fatalf("InitDB: %v", err)
|
|
||||||
}
|
|
||||||
t.Cleanup(func() { _ = database.CloseDB() })
|
|
||||||
|
|
||||||
db := database.GetDB()
|
db := database.GetDB()
|
||||||
|
|
||||||
@@ -96,10 +94,7 @@ func TestMigrationRequirements_BackfillsClientTrafficsWithMultiDomainInbound(t *
|
|||||||
func TestMigrationRequirementsReturnsAddClientStatFailure(t *testing.T) {
|
func TestMigrationRequirementsReturnsAddClientStatFailure(t *testing.T) {
|
||||||
dbDir := t.TempDir()
|
dbDir := t.TempDir()
|
||||||
t.Setenv("XUI_DB_FOLDER", dbDir)
|
t.Setenv("XUI_DB_FOLDER", dbDir)
|
||||||
if err := database.InitDB(filepath.Join(dbDir, "x-ui.db")); err != nil {
|
dbtest.InitDB(t, filepath.Join(dbDir, "x-ui.db"))
|
||||||
t.Fatalf("InitDB: %v", err)
|
|
||||||
}
|
|
||||||
t.Cleanup(func() { _ = database.CloseDB() })
|
|
||||||
db := database.GetDB()
|
db := database.GetDB()
|
||||||
first := &model.Inbound{UserId: 1, Tag: "first", Port: 31001, Protocol: model.VLESS, Settings: `{"clients":[{"email":"first@example.test","id":"id-1"}]}`, StreamSettings: `{}`}
|
first := &model.Inbound{UserId: 1, Tag: "first", Port: 31001, Protocol: model.VLESS, Settings: `{"clients":[{"email":"first@example.test","id":"id-1"}]}`, StreamSettings: `{}`}
|
||||||
if err := db.Create(first).Error; err != nil {
|
if err := db.Create(first).Error; err != nil {
|
||||||
@@ -136,10 +131,7 @@ func TestMigrationRequirementsReturnsAddClientStatFailure(t *testing.T) {
|
|||||||
func TestMigrationRequirements_CleansLegacyZeroAddrTag(t *testing.T) {
|
func TestMigrationRequirements_CleansLegacyZeroAddrTag(t *testing.T) {
|
||||||
dbDir := t.TempDir()
|
dbDir := t.TempDir()
|
||||||
t.Setenv("XUI_DB_FOLDER", dbDir)
|
t.Setenv("XUI_DB_FOLDER", dbDir)
|
||||||
if err := database.InitDB(filepath.Join(dbDir, "x-ui.db")); err != nil {
|
dbtest.InitDB(t, filepath.Join(dbDir, "x-ui.db"))
|
||||||
t.Fatalf("InitDB: %v", err)
|
|
||||||
}
|
|
||||||
t.Cleanup(func() { _ = database.CloseDB() })
|
|
||||||
|
|
||||||
db := database.GetDB()
|
db := database.GetDB()
|
||||||
legacy := &model.Inbound{
|
legacy := &model.Inbound{
|
||||||
|
|||||||
@@ -5,14 +5,12 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/mhsanaei/3x-ui/v3/internal/database"
|
"github.com/mhsanaei/3x-ui/v3/internal/database"
|
||||||
|
"github.com/mhsanaei/3x-ui/v3/internal/database/dbtest"
|
||||||
"github.com/mhsanaei/3x-ui/v3/internal/database/model"
|
"github.com/mhsanaei/3x-ui/v3/internal/database/model"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestSetInboundSubSortIndexLeavesSettingsUntouched(t *testing.T) {
|
func TestSetInboundSubSortIndexLeavesSettingsUntouched(t *testing.T) {
|
||||||
if err := database.InitDB(filepath.Join(t.TempDir(), "x-ui.db")); err != nil {
|
dbtest.InitDB(t, filepath.Join(t.TempDir(), "x-ui.db"))
|
||||||
t.Fatalf("init db: %v", err)
|
|
||||||
}
|
|
||||||
t.Cleanup(func() { _ = database.CloseDB() })
|
|
||||||
|
|
||||||
const settings = `{"clients":[{"email":"a@example.test","id":"11111111-1111-1111-1111-111111111111"}]}`
|
const settings = `{"clients":[{"email":"a@example.test","id":"11111111-1111-1111-1111-111111111111"}]}`
|
||||||
ib := &model.Inbound{UserId: 1, Remark: "r", Port: 21001, Protocol: model.VLESS, Settings: settings, SubSortIndex: 1, Enable: true}
|
ib := &model.Inbound{UserId: 1, Remark: "r", Port: 21001, Protocol: model.VLESS, Settings: settings, SubSortIndex: 1, Enable: true}
|
||||||
@@ -57,10 +55,7 @@ func TestSetInboundSubSortIndexUsesNarrowNodeUpdate(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestSetInboundSubSortIndexPreservesNegative(t *testing.T) {
|
func TestSetInboundSubSortIndexPreservesNegative(t *testing.T) {
|
||||||
if err := database.InitDB(filepath.Join(t.TempDir(), "x-ui.db")); err != nil {
|
dbtest.InitDB(t, filepath.Join(t.TempDir(), "x-ui.db"))
|
||||||
t.Fatalf("init db: %v", err)
|
|
||||||
}
|
|
||||||
t.Cleanup(func() { _ = database.CloseDB() })
|
|
||||||
|
|
||||||
ib := &model.Inbound{UserId: 1, Remark: "r", Port: 21003, Protocol: model.VLESS, Settings: `{"clients":[]}`, SubSortIndex: 1, Enable: true}
|
ib := &model.Inbound{UserId: 1, Remark: "r", Port: 21003, Protocol: model.VLESS, Settings: `{"clients":[]}`, SubSortIndex: 1, Enable: true}
|
||||||
if err := database.GetDB().Create(ib).Error; err != nil {
|
if err := database.GetDB().Create(ib).Error; err != nil {
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/mhsanaei/3x-ui/v3/internal/database"
|
"github.com/mhsanaei/3x-ui/v3/internal/database"
|
||||||
|
"github.com/mhsanaei/3x-ui/v3/internal/database/dbtest"
|
||||||
"github.com/mhsanaei/3x-ui/v3/internal/database/model"
|
"github.com/mhsanaei/3x-ui/v3/internal/database/model"
|
||||||
"github.com/mhsanaei/3x-ui/v3/internal/xray"
|
"github.com/mhsanaei/3x-ui/v3/internal/xray"
|
||||||
)
|
)
|
||||||
@@ -17,10 +18,7 @@ import (
|
|||||||
func TestGetClientTrafficTgBot_SettingsSerializationStyles(t *testing.T) {
|
func TestGetClientTrafficTgBot_SettingsSerializationStyles(t *testing.T) {
|
||||||
dbDir := t.TempDir()
|
dbDir := t.TempDir()
|
||||||
t.Setenv("XUI_DB_FOLDER", dbDir)
|
t.Setenv("XUI_DB_FOLDER", dbDir)
|
||||||
if err := database.InitDB(filepath.Join(dbDir, "x-ui.db")); err != nil {
|
dbtest.InitDB(t, filepath.Join(dbDir, "x-ui.db"))
|
||||||
t.Fatalf("InitDB: %v", err)
|
|
||||||
}
|
|
||||||
t.Cleanup(func() { _ = database.CloseDB() })
|
|
||||||
|
|
||||||
db := database.GetDB()
|
db := database.GetDB()
|
||||||
|
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/mhsanaei/3x-ui/v3/internal/crypto/nodetoken"
|
"github.com/mhsanaei/3x-ui/v3/internal/crypto/nodetoken"
|
||||||
"github.com/mhsanaei/3x-ui/v3/internal/database"
|
"github.com/mhsanaei/3x-ui/v3/internal/database/dbtest"
|
||||||
piaprotocol "github.com/mhsanaei/3x-ui/v3/internal/pia"
|
piaprotocol "github.com/mhsanaei/3x-ui/v3/internal/pia"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -48,10 +48,7 @@ func (f *fakePiaRegistrar) RegisterKey(_ context.Context, server piaprotocol.Wir
|
|||||||
|
|
||||||
func setupPiaService(t *testing.T) *PiaService {
|
func setupPiaService(t *testing.T) *PiaService {
|
||||||
t.Helper()
|
t.Helper()
|
||||||
if err := database.InitDB(filepath.Join(t.TempDir(), "x-ui.db")); err != nil {
|
dbtest.InitDB(t, filepath.Join(t.TempDir(), "x-ui.db"))
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
t.Cleanup(func() { _ = database.CloseDB() })
|
|
||||||
payload := []byte(`{"version":6,"groups":{"wg":[{"name":"wireguard","ports":[1337]}]},"regions":[{"id":"us-east","name":"US East","country":"US","geo":false,"offline":false,"port_forward":true,"servers":{"wg":[{"ip":"198.51.100.10","cn":"useast1"},{"ip":"198.51.100.20","cn":"useast2"}]}},{"id":"de-berlin","name":"Berlin","country":"DE","geo":false,"offline":false,"port_forward":false,"servers":{"wg":[{"ip":"203.0.113.10","cn":"berlin1"}]}}]}`)
|
payload := []byte(`{"version":6,"groups":{"wg":[{"name":"wireguard","ports":[1337]}]},"regions":[{"id":"us-east","name":"US East","country":"US","geo":false,"offline":false,"port_forward":true,"servers":{"wg":[{"ip":"198.51.100.10","cn":"useast1"},{"ip":"198.51.100.20","cn":"useast2"}]}},{"id":"de-berlin","name":"Berlin","country":"DE","geo":false,"offline":false,"port_forward":false,"servers":{"wg":[{"ip":"203.0.113.10","cn":"berlin1"}]}}]}`)
|
||||||
svc := NewPiaService()
|
svc := NewPiaService()
|
||||||
svc.Auth = fakePiaAuth{token: "tokentokentokentoken12"}
|
svc.Auth = fakePiaAuth{token: "tokentokentokentoken12"}
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/mhsanaei/3x-ui/v3/internal/database"
|
"github.com/mhsanaei/3x-ui/v3/internal/database"
|
||||||
|
"github.com/mhsanaei/3x-ui/v3/internal/database/dbtest"
|
||||||
"github.com/mhsanaei/3x-ui/v3/internal/database/model"
|
"github.com/mhsanaei/3x-ui/v3/internal/database/model"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -69,10 +70,7 @@ func withWarpAPIBase(t *testing.T, base string) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestChangeWarpIPPreservesLicenseKey(t *testing.T) {
|
func TestChangeWarpIPPreservesLicenseKey(t *testing.T) {
|
||||||
if err := database.InitDB(filepath.Join(t.TempDir(), "x-ui.db")); err != nil {
|
dbtest.InitDB(t, filepath.Join(t.TempDir(), "x-ui.db"))
|
||||||
t.Fatalf("InitDB: %v", err)
|
|
||||||
}
|
|
||||||
t.Cleanup(func() { _ = database.CloseDB() })
|
|
||||||
|
|
||||||
const license = "WARPPLLUS-KEY-0123456789abcdefgh" // 32 chars, >= 26 gate
|
const license = "WARPPLLUS-KEY-0123456789abcdefgh" // 32 chars, >= 26 gate
|
||||||
seedWarp(t, license)
|
seedWarp(t, license)
|
||||||
@@ -124,10 +122,7 @@ func TestChangeWarpIPPreservesLicenseKey(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestChangeWarpIPKeepsLicenseWhenReapplyFails(t *testing.T) {
|
func TestChangeWarpIPKeepsLicenseWhenReapplyFails(t *testing.T) {
|
||||||
if err := database.InitDB(filepath.Join(t.TempDir(), "x-ui.db")); err != nil {
|
dbtest.InitDB(t, filepath.Join(t.TempDir(), "x-ui.db"))
|
||||||
t.Fatalf("InitDB: %v", err)
|
|
||||||
}
|
|
||||||
t.Cleanup(func() { _ = database.CloseDB() })
|
|
||||||
|
|
||||||
const license = "WARPPLLUS-KEY-0123456789abcdefgh"
|
const license = "WARPPLLUS-KEY-0123456789abcdefgh"
|
||||||
seedWarp(t, license)
|
seedWarp(t, license)
|
||||||
|
|||||||
@@ -7,14 +7,11 @@ import (
|
|||||||
"path/filepath"
|
"path/filepath"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/mhsanaei/3x-ui/v3/internal/database"
|
"github.com/mhsanaei/3x-ui/v3/internal/database/dbtest"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestDoWarpRequestCapsResponseBody(t *testing.T) {
|
func TestDoWarpRequestCapsResponseBody(t *testing.T) {
|
||||||
if err := database.InitDB(filepath.Join(t.TempDir(), "x-ui.db")); err != nil {
|
dbtest.InitDB(t, filepath.Join(t.TempDir(), "x-ui.db"))
|
||||||
t.Fatalf("InitDB: %v", err)
|
|
||||||
}
|
|
||||||
t.Cleanup(func() { _ = database.CloseDB() })
|
|
||||||
|
|
||||||
oversize := maxResponseSize + 4096
|
oversize := maxResponseSize + 4096
|
||||||
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ import (
|
|||||||
"gorm.io/gorm"
|
"gorm.io/gorm"
|
||||||
|
|
||||||
"github.com/mhsanaei/3x-ui/v3/internal/database"
|
"github.com/mhsanaei/3x-ui/v3/internal/database"
|
||||||
|
"github.com/mhsanaei/3x-ui/v3/internal/database/dbtest"
|
||||||
"github.com/mhsanaei/3x-ui/v3/internal/database/model"
|
"github.com/mhsanaei/3x-ui/v3/internal/database/model"
|
||||||
"github.com/mhsanaei/3x-ui/v3/internal/web/runtime"
|
"github.com/mhsanaei/3x-ui/v3/internal/web/runtime"
|
||||||
"github.com/mhsanaei/3x-ui/v3/internal/xray"
|
"github.com/mhsanaei/3x-ui/v3/internal/xray"
|
||||||
@@ -18,10 +19,7 @@ func initTrafficTestDB(t *testing.T) *gorm.DB {
|
|||||||
t.Helper()
|
t.Helper()
|
||||||
dbDir := t.TempDir()
|
dbDir := t.TempDir()
|
||||||
t.Setenv("XUI_DB_FOLDER", dbDir)
|
t.Setenv("XUI_DB_FOLDER", dbDir)
|
||||||
if err := database.InitDB(filepath.Join(dbDir, "x-ui.db")); err != nil {
|
dbtest.InitDB(t, filepath.Join(dbDir, "x-ui.db"))
|
||||||
t.Fatalf("InitDB: %v", err)
|
|
||||||
}
|
|
||||||
t.Cleanup(func() { _ = database.CloseDB() })
|
|
||||||
return database.GetDB()
|
return database.GetDB()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/mhsanaei/3x-ui/v3/internal/database"
|
"github.com/mhsanaei/3x-ui/v3/internal/database"
|
||||||
|
"github.com/mhsanaei/3x-ui/v3/internal/database/dbtest"
|
||||||
"github.com/mhsanaei/3x-ui/v3/internal/database/model"
|
"github.com/mhsanaei/3x-ui/v3/internal/database/model"
|
||||||
"github.com/mhsanaei/3x-ui/v3/internal/util/crypto"
|
"github.com/mhsanaei/3x-ui/v3/internal/util/crypto"
|
||||||
)
|
)
|
||||||
@@ -14,14 +15,7 @@ func setupAPITokenTestDB(t *testing.T) {
|
|||||||
t.Helper()
|
t.Helper()
|
||||||
dbDir := t.TempDir()
|
dbDir := t.TempDir()
|
||||||
t.Setenv("XUI_DB_FOLDER", dbDir)
|
t.Setenv("XUI_DB_FOLDER", dbDir)
|
||||||
if err := database.InitDB(filepath.Join(dbDir, "x-ui.db")); err != nil {
|
dbtest.InitDB(t, filepath.Join(dbDir, "x-ui.db"))
|
||||||
t.Fatalf("InitDB: %v", err)
|
|
||||||
}
|
|
||||||
t.Cleanup(func() {
|
|
||||||
if err := database.CloseDB(); err != nil {
|
|
||||||
t.Fatalf("CloseDB: %v", err)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestAPITokenScopeExpiryAndExpectedRevoke(t *testing.T) {
|
func TestAPITokenScopeExpiryAndExpectedRevoke(t *testing.T) {
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ import (
|
|||||||
|
|
||||||
"github.com/mhsanaei/3x-ui/v3/internal/config"
|
"github.com/mhsanaei/3x-ui/v3/internal/config"
|
||||||
"github.com/mhsanaei/3x-ui/v3/internal/database"
|
"github.com/mhsanaei/3x-ui/v3/internal/database"
|
||||||
|
"github.com/mhsanaei/3x-ui/v3/internal/database/dbtest"
|
||||||
"github.com/mhsanaei/3x-ui/v3/internal/database/model"
|
"github.com/mhsanaei/3x-ui/v3/internal/database/model"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -36,10 +37,7 @@ func TestApiTokenCreatedAtSeconds(t *testing.T) {
|
|||||||
|
|
||||||
func TestRecreateByNamePreservesTokenWhenReplacementFails(t *testing.T) {
|
func TestRecreateByNamePreservesTokenWhenReplacementFails(t *testing.T) {
|
||||||
t.Setenv("XUI_DB_FOLDER", t.TempDir())
|
t.Setenv("XUI_DB_FOLDER", t.TempDir())
|
||||||
if err := database.InitDB(config.GetDBPath()); err != nil {
|
dbtest.InitDB(t, config.GetDBPath())
|
||||||
t.Fatalf("init db: %v", err)
|
|
||||||
}
|
|
||||||
t.Cleanup(func() { _ = database.CloseDB() })
|
|
||||||
|
|
||||||
svc := ApiTokenService{}
|
svc := ApiTokenService{}
|
||||||
first, err := svc.RecreateByName("cli-fallback")
|
first, err := svc.RecreateByName("cli-fallback")
|
||||||
@@ -73,10 +71,7 @@ func TestRecreateByNamePreservesTokenWhenReplacementFails(t *testing.T) {
|
|||||||
// and now takes operator input from -tokenName, so it must cap it too.
|
// and now takes operator input from -tokenName, so it must cap it too.
|
||||||
func TestRecreateByNameRejectsOverlongName(t *testing.T) {
|
func TestRecreateByNameRejectsOverlongName(t *testing.T) {
|
||||||
t.Setenv("XUI_DB_FOLDER", t.TempDir())
|
t.Setenv("XUI_DB_FOLDER", t.TempDir())
|
||||||
if err := database.InitDB(config.GetDBPath()); err != nil {
|
dbtest.InitDB(t, config.GetDBPath())
|
||||||
t.Fatalf("init db: %v", err)
|
|
||||||
}
|
|
||||||
t.Cleanup(func() { _ = database.CloseDB() })
|
|
||||||
|
|
||||||
const wantErr = "token name must be 64 characters or fewer"
|
const wantErr = "token name must be 64 characters or fewer"
|
||||||
|
|
||||||
@@ -95,10 +90,7 @@ func TestRecreateByNameRejectsOverlongName(t *testing.T) {
|
|||||||
|
|
||||||
func TestRecreateByNameKeepsOneToken(t *testing.T) {
|
func TestRecreateByNameKeepsOneToken(t *testing.T) {
|
||||||
t.Setenv("XUI_DB_FOLDER", t.TempDir())
|
t.Setenv("XUI_DB_FOLDER", t.TempDir())
|
||||||
if err := database.InitDB(config.GetDBPath()); err != nil {
|
dbtest.InitDB(t, config.GetDBPath())
|
||||||
t.Fatalf("init db: %v", err)
|
|
||||||
}
|
|
||||||
t.Cleanup(func() { _ = database.CloseDB() })
|
|
||||||
|
|
||||||
svc := ApiTokenService{}
|
svc := ApiTokenService{}
|
||||||
first, err := svc.RecreateByName("cli-fallback")
|
first, err := svc.RecreateByName("cli-fallback")
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/mhsanaei/3x-ui/v3/internal/config"
|
"github.com/mhsanaei/3x-ui/v3/internal/config"
|
||||||
"github.com/mhsanaei/3x-ui/v3/internal/database"
|
"github.com/mhsanaei/3x-ui/v3/internal/database/dbtest"
|
||||||
)
|
)
|
||||||
|
|
||||||
var sponsorTestNow = time.Date(2026, 10, 15, 0, 0, 0, 0, time.UTC)
|
var sponsorTestNow = time.Date(2026, 10, 15, 0, 0, 0, 0, time.UTC)
|
||||||
@@ -131,10 +131,7 @@ func TestActiveSponsorsResolvesLogoAndSlots(t *testing.T) {
|
|||||||
func setupSponsorServer(t *testing.T, body string) *atomic.Int32 {
|
func setupSponsorServer(t *testing.T, body string) *atomic.Int32 {
|
||||||
t.Helper()
|
t.Helper()
|
||||||
t.Setenv("XUI_DB_FOLDER", t.TempDir())
|
t.Setenv("XUI_DB_FOLDER", t.TempDir())
|
||||||
if err := database.InitDB(config.GetDBPath()); err != nil {
|
dbtest.InitDB(t, config.GetDBPath())
|
||||||
t.Fatalf("init db: %v", err)
|
|
||||||
}
|
|
||||||
t.Cleanup(func() { _ = database.CloseDB() })
|
|
||||||
|
|
||||||
var hits atomic.Int32
|
var hits atomic.Int32
|
||||||
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ import (
|
|||||||
|
|
||||||
"github.com/mhsanaei/3x-ui/v3/internal/amneziawgnet"
|
"github.com/mhsanaei/3x-ui/v3/internal/amneziawgnet"
|
||||||
"github.com/mhsanaei/3x-ui/v3/internal/database"
|
"github.com/mhsanaei/3x-ui/v3/internal/database"
|
||||||
|
"github.com/mhsanaei/3x-ui/v3/internal/database/dbtest"
|
||||||
"github.com/mhsanaei/3x-ui/v3/internal/database/model"
|
"github.com/mhsanaei/3x-ui/v3/internal/database/model"
|
||||||
xuilogger "github.com/mhsanaei/3x-ui/v3/internal/logger"
|
xuilogger "github.com/mhsanaei/3x-ui/v3/internal/logger"
|
||||||
)
|
)
|
||||||
@@ -27,14 +28,7 @@ func setupConflictDB(t *testing.T) {
|
|||||||
|
|
||||||
dbDir := t.TempDir()
|
dbDir := t.TempDir()
|
||||||
t.Setenv("XUI_DB_FOLDER", dbDir)
|
t.Setenv("XUI_DB_FOLDER", dbDir)
|
||||||
if err := database.InitDB(filepath.Join(dbDir, "x-ui.db")); err != nil {
|
dbtest.InitDB(t, filepath.Join(dbDir, "x-ui.db"))
|
||||||
t.Fatalf("InitDB: %v", err)
|
|
||||||
}
|
|
||||||
t.Cleanup(func() {
|
|
||||||
if err := database.CloseDB(); err != nil {
|
|
||||||
t.Logf("CloseDB warning: %v", err)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func seedInboundConflict(t *testing.T, tag, listen string, port int, protocol model.Protocol, streamSettings, settings string) {
|
func seedInboundConflict(t *testing.T, tag, listen string, port int, protocol model.Protocol, streamSettings, settings string) {
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ import (
|
|||||||
|
|
||||||
"github.com/mhsanaei/3x-ui/v3/internal/config"
|
"github.com/mhsanaei/3x-ui/v3/internal/config"
|
||||||
"github.com/mhsanaei/3x-ui/v3/internal/database"
|
"github.com/mhsanaei/3x-ui/v3/internal/database"
|
||||||
|
"github.com/mhsanaei/3x-ui/v3/internal/database/dbtest"
|
||||||
"github.com/mhsanaei/3x-ui/v3/internal/database/model"
|
"github.com/mhsanaei/3x-ui/v3/internal/database/model"
|
||||||
xuilogger "github.com/mhsanaei/3x-ui/v3/internal/logger"
|
xuilogger "github.com/mhsanaei/3x-ui/v3/internal/logger"
|
||||||
"github.com/mhsanaei/3x-ui/v3/internal/xray"
|
"github.com/mhsanaei/3x-ui/v3/internal/xray"
|
||||||
@@ -41,10 +42,7 @@ func setupScaleDB(t *testing.T) {
|
|||||||
if dbPath == "" {
|
if dbPath == "" {
|
||||||
dbPath = filepath.Join(t.TempDir(), "scale.db")
|
dbPath = filepath.Join(t.TempDir(), "scale.db")
|
||||||
}
|
}
|
||||||
if err := database.InitDB(dbPath); err != nil {
|
dbtest.InitDB(t, dbPath)
|
||||||
t.Fatalf("InitDB(sqlite): %v", err)
|
|
||||||
}
|
|
||||||
t.Cleanup(func() { _ = database.CloseDB() })
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import (
|
|||||||
"path/filepath"
|
"path/filepath"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/mhsanaei/3x-ui/v3/internal/database"
|
"github.com/mhsanaei/3x-ui/v3/internal/database/dbtest"
|
||||||
)
|
)
|
||||||
|
|
||||||
// A panel restarts with an empty snapshot until the @2s ticker fires, and a
|
// A panel restarts with an empty snapshot until the @2s ticker fires, and a
|
||||||
@@ -12,10 +12,7 @@ import (
|
|||||||
func TestCurrentStatusSamplesBeforeFirstTick(t *testing.T) {
|
func TestCurrentStatusSamplesBeforeFirstTick(t *testing.T) {
|
||||||
dbDir := t.TempDir()
|
dbDir := t.TempDir()
|
||||||
t.Setenv("XUI_DB_FOLDER", dbDir)
|
t.Setenv("XUI_DB_FOLDER", dbDir)
|
||||||
if err := database.InitDB(filepath.Join(dbDir, "x-ui.db")); err != nil {
|
dbtest.InitDB(t, filepath.Join(dbDir, "x-ui.db"))
|
||||||
t.Fatalf("InitDB: %v", err)
|
|
||||||
}
|
|
||||||
t.Cleanup(func() { _ = database.CloseDB() })
|
|
||||||
|
|
||||||
svc := &ServerService{}
|
svc := &ServerService{}
|
||||||
if svc.LastStatus() != nil {
|
if svc.LastStatus() != nil {
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ import (
|
|||||||
"sync"
|
"sync"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/mhsanaei/3x-ui/v3/internal/database"
|
"github.com/mhsanaei/3x-ui/v3/internal/database/dbtest"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Loyalsoldier and runetfreedom write "<hash> geoip.dat"; chocolate4u writes
|
// Loyalsoldier and runetfreedom write "<hash> geoip.dat"; chocolate4u writes
|
||||||
@@ -141,10 +141,7 @@ func geofileTestEnv(t *testing.T, entries map[string]geofileEntry) string {
|
|||||||
|
|
||||||
dbDir := t.TempDir()
|
dbDir := t.TempDir()
|
||||||
t.Setenv("XUI_DB_FOLDER", dbDir)
|
t.Setenv("XUI_DB_FOLDER", dbDir)
|
||||||
if err := database.InitDB(filepath.Join(dbDir, "x-ui.db")); err != nil {
|
dbtest.InitDB(t, filepath.Join(dbDir, "x-ui.db"))
|
||||||
t.Fatalf("InitDB: %v", err)
|
|
||||||
}
|
|
||||||
t.Cleanup(func() { _ = database.CloseDB() })
|
|
||||||
|
|
||||||
binFolder := t.TempDir()
|
binFolder := t.TempDir()
|
||||||
t.Setenv("XUI_BIN_FOLDER", binFolder)
|
t.Setenv("XUI_BIN_FOLDER", binFolder)
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/mhsanaei/3x-ui/v3/internal/database"
|
"github.com/mhsanaei/3x-ui/v3/internal/database"
|
||||||
|
"github.com/mhsanaei/3x-ui/v3/internal/database/dbtest"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestSniffImportKind(t *testing.T) {
|
func TestSniffImportKind(t *testing.T) {
|
||||||
@@ -30,10 +31,7 @@ func TestSniffImportKind(t *testing.T) {
|
|||||||
|
|
||||||
t.Run("panel migration dump", func(t *testing.T) {
|
t.Run("panel migration dump", func(t *testing.T) {
|
||||||
dbPath := filepath.Join(t.TempDir(), "x-ui.db")
|
dbPath := filepath.Join(t.TempDir(), "x-ui.db")
|
||||||
if err := database.InitDB(dbPath); err != nil {
|
dbtest.InitDB(t, dbPath)
|
||||||
t.Fatalf("InitDB: %v", err)
|
|
||||||
}
|
|
||||||
t.Cleanup(func() { _ = database.CloseDB() })
|
|
||||||
dump, err := database.DumpSQLiteToBytes(dbPath)
|
dump, err := database.DumpSQLiteToBytes(dbPath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("DumpSQLiteToBytes: %v", err)
|
t.Fatalf("DumpSQLiteToBytes: %v", err)
|
||||||
|
|||||||
@@ -6,15 +6,13 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/mhsanaei/3x-ui/v3/internal/database"
|
"github.com/mhsanaei/3x-ui/v3/internal/database"
|
||||||
|
"github.com/mhsanaei/3x-ui/v3/internal/database/dbtest"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestStageSQLiteUploadRebuildsFromDump(t *testing.T) {
|
func TestStageSQLiteUploadRebuildsFromDump(t *testing.T) {
|
||||||
dir := t.TempDir()
|
dir := t.TempDir()
|
||||||
dbPath := filepath.Join(dir, "x-ui.db")
|
dbPath := filepath.Join(dir, "x-ui.db")
|
||||||
if err := database.InitDB(dbPath); err != nil {
|
dbtest.InitDB(t, dbPath)
|
||||||
t.Fatalf("InitDB: %v", err)
|
|
||||||
}
|
|
||||||
t.Cleanup(func() { _ = database.CloseDB() })
|
|
||||||
dump, err := database.DumpSQLiteToBytes(dbPath)
|
dump, err := database.DumpSQLiteToBytes(dbPath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("DumpSQLiteToBytes: %v", err)
|
t.Fatalf("DumpSQLiteToBytes: %v", err)
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/mhsanaei/3x-ui/v3/internal/database"
|
"github.com/mhsanaei/3x-ui/v3/internal/database/dbtest"
|
||||||
)
|
)
|
||||||
|
|
||||||
// A box with no IPv6 route spends 3s per lookup service, and a status sample
|
// A box with no IPv6 route spends 3s per lookup service, and a status sample
|
||||||
@@ -15,10 +15,7 @@ import (
|
|||||||
func TestStatusSampleDoesNotWaitOnPublicIPLookup(t *testing.T) {
|
func TestStatusSampleDoesNotWaitOnPublicIPLookup(t *testing.T) {
|
||||||
dbDir := t.TempDir()
|
dbDir := t.TempDir()
|
||||||
t.Setenv("XUI_DB_FOLDER", dbDir)
|
t.Setenv("XUI_DB_FOLDER", dbDir)
|
||||||
if err := database.InitDB(filepath.Join(dbDir, "x-ui.db")); err != nil {
|
dbtest.InitDB(t, filepath.Join(dbDir, "x-ui.db"))
|
||||||
t.Fatalf("InitDB: %v", err)
|
|
||||||
}
|
|
||||||
t.Cleanup(func() { _ = database.CloseDB() })
|
|
||||||
|
|
||||||
release := make(chan struct{})
|
release := make(chan struct{})
|
||||||
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/mhsanaei/3x-ui/v3/internal/database"
|
"github.com/mhsanaei/3x-ui/v3/internal/database"
|
||||||
|
"github.com/mhsanaei/3x-ui/v3/internal/database/dbtest"
|
||||||
"github.com/mhsanaei/3x-ui/v3/internal/util/crypto"
|
"github.com/mhsanaei/3x-ui/v3/internal/util/crypto"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -16,10 +17,7 @@ func setupSettingMtlsDB(t *testing.T) *SettingService {
|
|||||||
t.Helper()
|
t.Helper()
|
||||||
dbDir := t.TempDir()
|
dbDir := t.TempDir()
|
||||||
t.Setenv("XUI_DB_FOLDER", dbDir)
|
t.Setenv("XUI_DB_FOLDER", dbDir)
|
||||||
if err := database.InitDB(filepath.Join(dbDir, "x-ui.db")); err != nil {
|
dbtest.InitDB(t, filepath.Join(dbDir, "x-ui.db"))
|
||||||
t.Fatalf("InitDB: %v", err)
|
|
||||||
}
|
|
||||||
t.Cleanup(func() { _ = database.CloseDB() })
|
|
||||||
return &SettingService{}
|
return &SettingService{}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ import (
|
|||||||
"github.com/xlzd/gotp"
|
"github.com/xlzd/gotp"
|
||||||
|
|
||||||
"github.com/mhsanaei/3x-ui/v3/internal/database"
|
"github.com/mhsanaei/3x-ui/v3/internal/database"
|
||||||
|
"github.com/mhsanaei/3x-ui/v3/internal/database/dbtest"
|
||||||
"github.com/mhsanaei/3x-ui/v3/internal/database/model"
|
"github.com/mhsanaei/3x-ui/v3/internal/database/model"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -52,14 +53,7 @@ func TestResetSettingsRegeneratesSubscriptionPaths(t *testing.T) {
|
|||||||
|
|
||||||
func setupSettingTestDB(t *testing.T) {
|
func setupSettingTestDB(t *testing.T) {
|
||||||
t.Helper()
|
t.Helper()
|
||||||
if err := database.InitDB(filepath.Join(t.TempDir(), "x-ui.db")); err != nil {
|
dbtest.InitDB(t, filepath.Join(t.TempDir(), "x-ui.db"))
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
t.Cleanup(func() {
|
|
||||||
if err := database.CloseDB(); err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestGetAllSettingViewRedactsSecrets(t *testing.T) {
|
func TestGetAllSettingViewRedactsSecrets(t *testing.T) {
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ import (
|
|||||||
|
|
||||||
"github.com/op/go-logging"
|
"github.com/op/go-logging"
|
||||||
|
|
||||||
"github.com/mhsanaei/3x-ui/v3/internal/database"
|
"github.com/mhsanaei/3x-ui/v3/internal/database/dbtest"
|
||||||
"github.com/mhsanaei/3x-ui/v3/internal/database/model"
|
"github.com/mhsanaei/3x-ui/v3/internal/database/model"
|
||||||
xuilogger "github.com/mhsanaei/3x-ui/v3/internal/logger"
|
xuilogger "github.com/mhsanaei/3x-ui/v3/internal/logger"
|
||||||
)
|
)
|
||||||
@@ -20,14 +20,7 @@ func setupSubBalancerDB(t *testing.T) {
|
|||||||
subBalancerLoggerOnce.Do(func() { xuilogger.InitLogger(logging.ERROR) })
|
subBalancerLoggerOnce.Do(func() { xuilogger.InitLogger(logging.ERROR) })
|
||||||
dbDir := t.TempDir()
|
dbDir := t.TempDir()
|
||||||
t.Setenv("XUI_DB_FOLDER", dbDir)
|
t.Setenv("XUI_DB_FOLDER", dbDir)
|
||||||
if err := database.InitDB(filepath.Join(dbDir, "x-ui.db")); err != nil {
|
dbtest.InitDB(t, filepath.Join(dbDir, "x-ui.db"))
|
||||||
t.Fatalf("InitDB: %v", err)
|
|
||||||
}
|
|
||||||
t.Cleanup(func() {
|
|
||||||
if err := database.CloseDB(); err != nil {
|
|
||||||
t.Logf("CloseDB warning: %v", err)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestSubBalancerServiceCRUD(t *testing.T) {
|
func TestSubBalancerServiceCRUD(t *testing.T) {
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/mhsanaei/3x-ui/v3/internal/database"
|
"github.com/mhsanaei/3x-ui/v3/internal/database"
|
||||||
|
"github.com/mhsanaei/3x-ui/v3/internal/database/dbtest"
|
||||||
"github.com/mhsanaei/3x-ui/v3/internal/database/model"
|
"github.com/mhsanaei/3x-ui/v3/internal/database/model"
|
||||||
|
|
||||||
"github.com/mymmrac/telego"
|
"github.com/mymmrac/telego"
|
||||||
@@ -15,10 +16,7 @@ import (
|
|||||||
|
|
||||||
func seedPickerInbounds(t *testing.T, protocols ...model.Protocol) {
|
func seedPickerInbounds(t *testing.T, protocols ...model.Protocol) {
|
||||||
t.Helper()
|
t.Helper()
|
||||||
if err := database.InitDB(filepath.Join(t.TempDir(), "x-ui.db")); err != nil {
|
dbtest.InitDB(t, filepath.Join(t.TempDir(), "x-ui.db"))
|
||||||
t.Fatalf("InitDB: %v", err)
|
|
||||||
}
|
|
||||||
t.Cleanup(func() { _ = database.CloseDB() })
|
|
||||||
for i, protocol := range protocols {
|
for i, protocol := range protocols {
|
||||||
port := 20000 + i
|
port := 20000 + i
|
||||||
ib := &model.Inbound{Remark: string(protocol), Enable: true, Port: port, Protocol: protocol, Tag: fmt.Sprintf("inbound-%d", port), Settings: `{}`}
|
ib := &model.Inbound{Remark: string(protocol), Enable: true, Port: port, Protocol: protocol, Tag: fmt.Sprintf("inbound-%d", port), Settings: `{}`}
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import (
|
|||||||
"path/filepath"
|
"path/filepath"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/mhsanaei/3x-ui/v3/internal/database"
|
"github.com/mhsanaei/3x-ui/v3/internal/database/dbtest"
|
||||||
|
|
||||||
"github.com/mymmrac/telego"
|
"github.com/mymmrac/telego"
|
||||||
)
|
)
|
||||||
@@ -12,10 +12,7 @@ import (
|
|||||||
// Regression test: keying the add-client wizard by chat alone left the two
|
// Regression test: keying the add-client wizard by chat alone left the two
|
||||||
// admins of a group chat filling in one client between them.
|
// admins of a group chat filling in one client between them.
|
||||||
func TestAddClientDraftIsPerAdminInGroupChat(t *testing.T) {
|
func TestAddClientDraftIsPerAdminInGroupChat(t *testing.T) {
|
||||||
if err := database.InitDB(filepath.Join(t.TempDir(), "x-ui.db")); err != nil {
|
dbtest.InitDB(t, filepath.Join(t.TempDir(), "x-ui.db"))
|
||||||
t.Fatalf("InitDB: %v", err)
|
|
||||||
}
|
|
||||||
t.Cleanup(func() { _ = database.CloseDB() })
|
|
||||||
|
|
||||||
const (
|
const (
|
||||||
groupChat = int64(-1001234567890)
|
groupChat = int64(-1001234567890)
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/mhsanaei/3x-ui/v3/internal/database"
|
"github.com/mhsanaei/3x-ui/v3/internal/database/dbtest"
|
||||||
|
|
||||||
"github.com/mymmrac/telego"
|
"github.com/mymmrac/telego"
|
||||||
)
|
)
|
||||||
@@ -84,10 +84,7 @@ func lastDraftCard(t *testing.T, texts []string) string {
|
|||||||
// Regression test: one package-level draft per bot meant an admin's new client
|
// Regression test: one package-level draft per bot meant an admin's new client
|
||||||
// was filled in by another chat's steps.
|
// was filled in by another chat's steps.
|
||||||
func TestAddClientDraftIsPerChat(t *testing.T) {
|
func TestAddClientDraftIsPerChat(t *testing.T) {
|
||||||
if err := database.InitDB(filepath.Join(t.TempDir(), "x-ui.db")); err != nil {
|
dbtest.InitDB(t, filepath.Join(t.TempDir(), "x-ui.db"))
|
||||||
t.Fatalf("InitDB: %v", err)
|
|
||||||
}
|
|
||||||
t.Cleanup(func() { _ = database.CloseDB() })
|
|
||||||
|
|
||||||
const (
|
const (
|
||||||
chatA = int64(7101)
|
chatA = int64(7101)
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/mhsanaei/3x-ui/v3/internal/database"
|
"github.com/mhsanaei/3x-ui/v3/internal/database/dbtest"
|
||||||
"github.com/mhsanaei/3x-ui/v3/internal/web/locale"
|
"github.com/mhsanaei/3x-ui/v3/internal/web/locale"
|
||||||
"github.com/mhsanaei/3x-ui/v3/internal/xray"
|
"github.com/mhsanaei/3x-ui/v3/internal/xray"
|
||||||
|
|
||||||
@@ -35,10 +35,7 @@ func clientInfoLocalizer(t *testing.T) {
|
|||||||
// Regression test: a start-after-first-use client is stored as a negative duration,
|
// Regression test: a start-after-first-use client is stored as a negative duration,
|
||||||
// and a disabled one rendered it as a 1969 date.
|
// and a disabled one rendered it as a 1969 date.
|
||||||
func TestClientInfoShowsStartAfterFirstUseWhenDisabled(t *testing.T) {
|
func TestClientInfoShowsStartAfterFirstUseWhenDisabled(t *testing.T) {
|
||||||
if err := database.InitDB(filepath.Join(t.TempDir(), "x-ui.db")); err != nil {
|
dbtest.InitDB(t, filepath.Join(t.TempDir(), "x-ui.db"))
|
||||||
t.Fatalf("InitDB: %v", err)
|
|
||||||
}
|
|
||||||
t.Cleanup(func() { _ = database.CloseDB() })
|
|
||||||
clientInfoLocalizer(t)
|
clientInfoLocalizer(t)
|
||||||
|
|
||||||
traffic := &xray.ClientTraffic{
|
traffic := &xray.ClientTraffic{
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/mhsanaei/3x-ui/v3/internal/database"
|
"github.com/mhsanaei/3x-ui/v3/internal/database"
|
||||||
|
"github.com/mhsanaei/3x-ui/v3/internal/database/dbtest"
|
||||||
"github.com/mhsanaei/3x-ui/v3/internal/database/model"
|
"github.com/mhsanaei/3x-ui/v3/internal/database/model"
|
||||||
"github.com/mhsanaei/3x-ui/v3/internal/web/global"
|
"github.com/mhsanaei/3x-ui/v3/internal/web/global"
|
||||||
"github.com/mhsanaei/3x-ui/v3/internal/xray"
|
"github.com/mhsanaei/3x-ui/v3/internal/xray"
|
||||||
@@ -33,10 +34,7 @@ func newLinksCallbackTgbot(t *testing.T, email string) (*Tgbot, func(string) int
|
|||||||
swapTestBot(t, mock.URL)
|
swapTestBot(t, mock.URL)
|
||||||
t.Cleanup(mock.Close)
|
t.Cleanup(mock.Close)
|
||||||
|
|
||||||
if err := database.InitDB(filepath.Join(t.TempDir(), "x-ui.db")); err != nil {
|
dbtest.InitDB(t, filepath.Join(t.TempDir(), "x-ui.db"))
|
||||||
t.Fatalf("InitDB: %v", err)
|
|
||||||
}
|
|
||||||
t.Cleanup(func() { _ = database.CloseDB() })
|
|
||||||
|
|
||||||
inbound := &model.Inbound{
|
inbound := &model.Inbound{
|
||||||
UserId: 1,
|
UserId: 1,
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/mhsanaei/3x-ui/v3/internal/database"
|
"github.com/mhsanaei/3x-ui/v3/internal/database"
|
||||||
|
"github.com/mhsanaei/3x-ui/v3/internal/database/dbtest"
|
||||||
"github.com/mhsanaei/3x-ui/v3/internal/database/model"
|
"github.com/mhsanaei/3x-ui/v3/internal/database/model"
|
||||||
"github.com/mhsanaei/3x-ui/v3/internal/xray"
|
"github.com/mhsanaei/3x-ui/v3/internal/xray"
|
||||||
|
|
||||||
@@ -59,10 +60,7 @@ func seedReportClients(t *testing.T, remark string, emails []string) {
|
|||||||
|
|
||||||
func initReportDB(t *testing.T) *Tgbot {
|
func initReportDB(t *testing.T) *Tgbot {
|
||||||
t.Helper()
|
t.Helper()
|
||||||
if err := database.InitDB(filepath.Join(t.TempDir(), "x-ui.db")); err != nil {
|
dbtest.InitDB(t, filepath.Join(t.TempDir(), "x-ui.db"))
|
||||||
t.Fatalf("InitDB: %v", err)
|
|
||||||
}
|
|
||||||
t.Cleanup(func() { _ = database.CloseDB() })
|
|
||||||
|
|
||||||
origRunning := isRunning
|
origRunning := isRunning
|
||||||
t.Cleanup(func() { isRunning = origRunning })
|
t.Cleanup(func() { isRunning = origRunning })
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ import (
|
|||||||
"sync"
|
"sync"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/mhsanaei/3x-ui/v3/internal/database"
|
"github.com/mhsanaei/3x-ui/v3/internal/database/dbtest"
|
||||||
"github.com/mhsanaei/3x-ui/v3/internal/database/model"
|
"github.com/mhsanaei/3x-ui/v3/internal/database/model"
|
||||||
|
|
||||||
"github.com/mymmrac/telego"
|
"github.com/mymmrac/telego"
|
||||||
@@ -58,10 +58,7 @@ func swapTestBot(t *testing.T, url string) {
|
|||||||
|
|
||||||
func newStaleButtonTgbot(t *testing.T) *Tgbot {
|
func newStaleButtonTgbot(t *testing.T) *Tgbot {
|
||||||
t.Helper()
|
t.Helper()
|
||||||
if err := database.InitDB(filepath.Join(t.TempDir(), "x-ui.db")); err != nil {
|
dbtest.InitDB(t, filepath.Join(t.TempDir(), "x-ui.db"))
|
||||||
t.Fatalf("InitDB: %v", err)
|
|
||||||
}
|
|
||||||
t.Cleanup(func() { _ = database.CloseDB() })
|
|
||||||
return &Tgbot{}
|
return &Tgbot{}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/mhsanaei/3x-ui/v3/internal/database"
|
"github.com/mhsanaei/3x-ui/v3/internal/database/dbtest"
|
||||||
"github.com/mhsanaei/3x-ui/v3/internal/eventbus"
|
"github.com/mhsanaei/3x-ui/v3/internal/eventbus"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -61,10 +61,7 @@ func runObservatory(t *testing.T, threshold int, seq []probe) []eventbus.EventTy
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestApplyObservatoryDebounce(t *testing.T) {
|
func TestApplyObservatoryDebounce(t *testing.T) {
|
||||||
if err := database.InitDB(filepath.Join(t.TempDir(), "x-ui.db")); err != nil {
|
dbtest.InitDB(t, filepath.Join(t.TempDir(), "x-ui.db"))
|
||||||
t.Fatalf("init db: %v", err)
|
|
||||||
}
|
|
||||||
t.Cleanup(func() { _ = database.CloseDB() })
|
|
||||||
|
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
name string
|
name string
|
||||||
@@ -150,10 +147,7 @@ func TestValidObsTag(t *testing.T) {
|
|||||||
|
|
||||||
func TestApplyObservatoryKeepsUnicodeTags(t *testing.T) {
|
func TestApplyObservatoryKeepsUnicodeTags(t *testing.T) {
|
||||||
dbDir := t.TempDir()
|
dbDir := t.TempDir()
|
||||||
if err := database.InitDB(filepath.Join(dbDir, "x-ui.db")); err != nil {
|
dbtest.InitDB(t, filepath.Join(dbDir, "x-ui.db"))
|
||||||
t.Fatalf("InitDB: %v", err)
|
|
||||||
}
|
|
||||||
t.Cleanup(func() { _ = database.CloseDB() })
|
|
||||||
|
|
||||||
s := &XrayMetricsService{settingService: SettingService{}}
|
s := &XrayMetricsService{settingService: SettingService{}}
|
||||||
s.applyObservatory(time.Unix(1000, 0), map[string]rawObsEntry{
|
s.applyObservatory(time.Unix(1000, 0), map[string]rawObsEntry{
|
||||||
|
|||||||
Reference in New Issue
Block a user