Files
l-ui/internal/database/inbound_port_unique_migration_test.go
T
Muse 6a5ee8f77b rename: 3x-ui/x-ui -> L-UI/l-ui/lui-agent (paths, services, env, assets)
Display L-UI; panel binary/process l-ui, agent lui-agent.
Dirs /usr/local/l-ui, /etc/l-ui, /var/log/l-ui; DB /etc/l-ui/l-ui.db
(name file drives it via GetName), probe.db beside it, cert
/etc/l-ui/cert, bin /usr/local/l-ui/bin. Services l-ui.service /
lui-agent.service, OpenRC lui-agent, l-ui.sh, cmd/lui-agent.
Env prefix XUI_ -> LUI_ (code reads new prefix only). Release
assets l-ui-linux-* / lui-agent-linux-*; Gitea repo rogue/l-ui is
a placeholder pending user confirmation (see selfupdate.go note).
Go module path github.com/mhsanaei/3x-ui/v3 intentionally kept.
Versions unchanged: panel V2.6.0 / agent A2.5.0.
2026-10-24 12:00:55 +00:00

77 lines
2.8 KiB
Go

package database
import (
"path/filepath"
"testing"
"github.com/mhsanaei/3x-ui/v3/internal/database/model"
"gorm.io/driver/sqlite"
"gorm.io/gorm"
)
const legacyInboundsDDL = "CREATE TABLE `inbounds` (`id` integer PRIMARY KEY AUTOINCREMENT,`user_id` integer,`up` integer,`down` integer,`total` integer,`remark` text,`enable` numeric,`expiry_time` integer,`listen` text,`port` integer UNIQUE,`protocol` text,`settings` text,`stream_settings` text,`tag` text UNIQUE,`sniffing` text)"
func openLegacyPortUniqueDB(t *testing.T) string {
t.Helper()
dbPath := filepath.Join(t.TempDir(), "l-ui.db")
legacy, err := gorm.Open(sqlite.Open(dbPath), &gorm.Config{})
if err != nil {
t.Fatalf("open legacy db: %v", err)
}
if err := legacy.Exec(legacyInboundsDDL).Error; err != nil {
t.Fatalf("create legacy inbounds: %v", err)
}
if err := legacy.Exec(
`INSERT INTO inbounds (user_id, remark, enable, port, protocol, settings, stream_settings, tag, sniffing)
VALUES (1, 'preexisting', 1, 80, 'vless', '{"clients":[]}', '{}', 'in-80-tcp', '{}')`,
).Error; err != nil {
t.Fatalf("seed legacy inbound: %v", err)
}
sqlDB, err := legacy.DB()
if err != nil {
t.Fatalf("legacy db handle: %v", err)
}
if err := sqlDB.Close(); err != nil {
t.Fatalf("close legacy db: %v", err)
}
return dbPath
}
func TestDropLegacyInboundPortUnique(t *testing.T) {
dbPath := openLegacyPortUniqueDB(t)
if err := InitDB(dbPath); err != nil {
t.Fatalf("InitDB over legacy schema: %v", err)
}
t.Cleanup(func() { _ = CloseDB() })
var preexisting model.Inbound
if err := GetDB().Where("tag = ?", "in-80-tcp").First(&preexisting).Error; err != nil {
t.Fatalf("preexisting inbound lost in rebuild: %v", err)
}
if preexisting.Remark != "preexisting" || preexisting.Port != 80 {
t.Fatalf("preexisting inbound corrupted: remark=%q port=%d", preexisting.Remark, preexisting.Port)
}
nodeA, nodeB := 1, 2
samePortA := &model.Inbound{UserId: 1, Tag: "node-a-80", Enable: true, Port: 80, Protocol: model.VLESS, Remark: "a", Settings: `{"clients":[]}`, NodeID: &nodeA}
samePortB := &model.Inbound{UserId: 1, Tag: "node-b-80", Enable: true, Port: 80, Protocol: model.VLESS, Remark: "b", Settings: `{"clients":[]}`, NodeID: &nodeB}
if err := GetDB().Create(samePortA).Error; err != nil {
t.Fatalf("create node-a inbound on port 80: %v", err)
}
if err := GetDB().Create(samePortB).Error; err != nil {
t.Fatalf("create node-b inbound on port 80: %v", err)
}
var dupTag model.Inbound
dupErr := GetDB().Create(&model.Inbound{UserId: 1, Tag: "in-80-tcp", Enable: true, Port: 90, Protocol: model.VLESS, Settings: `{"clients":[]}`}).Error
if dupErr == nil {
t.Fatalf("duplicate tag insert succeeded, want unique violation; row=%v", dupTag)
}
if err := dropLegacyInboundPortUnique(); err != nil {
t.Fatalf("second dropLegacyInboundPortUnique run: %v", err)
}
}