TestCopyLiveDatabaseToFile now runs
after connection to local MySQL database is working for go tests
This commit is contained in:
@@ -193,10 +193,10 @@ func splitSkills(object []models.SkFertigkeit) ([]models.SkFertigkeit, []models.
|
|||||||
type ExperienceAndWealthResponse struct {
|
type ExperienceAndWealthResponse struct {
|
||||||
ExperiencePoints int `json:"experience_points"`
|
ExperiencePoints int `json:"experience_points"`
|
||||||
Wealth struct {
|
Wealth struct {
|
||||||
Goldstücke int `json:"gold_coins"` // GS
|
Goldstuecke int `json:"gold_coins"` // GS
|
||||||
Silberstücke int `json:"silver_coins"` // SS
|
Silberstuecke int `json:"silver_coins"` // SS
|
||||||
Kupferstücke int `json:"copper_coins"` // KS
|
Kupferstuecke int `json:"copper_coins"` // KS
|
||||||
TotalInGS int `json:"total_in_ss"` // Gesamt in Silberstücken
|
TotalInGS int `json:"total_in_ss"` // Gesamt in Silberstücken
|
||||||
} `json:"wealth"`
|
} `json:"wealth"`
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -225,9 +225,9 @@ func GetCharacterExperienceAndWealth(c *gin.Context) {
|
|||||||
response := ExperienceAndWealthResponse{
|
response := ExperienceAndWealthResponse{
|
||||||
ExperiencePoints: character.Erfahrungsschatz.EP,
|
ExperiencePoints: character.Erfahrungsschatz.EP,
|
||||||
}
|
}
|
||||||
response.Wealth.Goldstücke = gs
|
response.Wealth.Goldstuecke = gs
|
||||||
response.Wealth.Silberstücke = ss
|
response.Wealth.Silberstuecke = ss
|
||||||
response.Wealth.Kupferstücke = ks
|
response.Wealth.Kupferstuecke = ks
|
||||||
response.Wealth.TotalInGS = totalInSS
|
response.Wealth.TotalInGS = totalInSS
|
||||||
|
|
||||||
c.JSON(http.StatusOK, response)
|
c.JSON(http.StatusOK, response)
|
||||||
|
|||||||
@@ -599,6 +599,7 @@ func TestFinalizeCharacterCreation(t *testing.T) {
|
|||||||
UserID: 1,
|
UserID: 1,
|
||||||
Username: "bebe",
|
Username: "bebe",
|
||||||
Email: "frank@wuenscheonline.de",
|
Email: "frank@wuenscheonline.de",
|
||||||
|
Role: "admin",
|
||||||
}
|
}
|
||||||
err = database.DB.Create(&testUser).Error
|
err = database.DB.Create(&testUser).Error
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
|
|||||||
@@ -145,6 +145,10 @@ func LoadConfig() *Config {
|
|||||||
// loadEnvFile lädt eine .env-Datei falls vorhanden
|
// loadEnvFile lädt eine .env-Datei falls vorhanden
|
||||||
func loadEnvFile() {
|
func loadEnvFile() {
|
||||||
envFiles := []string{".env", ".env.local"}
|
envFiles := []string{".env", ".env.local"}
|
||||||
|
configFile := os.Getenv("CONFIG_FILE")
|
||||||
|
if configFile != "" {
|
||||||
|
envFiles = append(envFiles, configFile)
|
||||||
|
}
|
||||||
|
|
||||||
for _, envFile := range envFiles {
|
for _, envFile := range envFiles {
|
||||||
if _, err := os.Stat(envFile); err == nil {
|
if _, err := os.Stat(envFile); err == nil {
|
||||||
|
|||||||
@@ -70,7 +70,7 @@ func ConnectDatabaseOrig() *gorm.DB {
|
|||||||
// Falls keine URL konfiguriert ist, verwende Standard-MySQL-Konfiguration als Fallback
|
// Falls keine URL konfiguriert ist, verwende Standard-MySQL-Konfiguration als Fallback
|
||||||
dbURL := cfg.DatabaseURL
|
dbURL := cfg.DatabaseURL
|
||||||
if dbURL == "" {
|
if dbURL == "" {
|
||||||
dbURL = "bamort:bG4)efozrc@tcp(192.168.0.5:3306)/bamort?charset=utf8mb4&parseTime=True&loc=Local"
|
dbURL = "bamort:bG4)efozrc@tcp(localhost:3306)/bamort?charset=utf8mb4&parseTime=True&loc=Local"
|
||||||
logger.Warn("Keine DATABASE_URL konfiguriert, verwende Standard-MySQL-Konfiguration")
|
logger.Warn("Keine DATABASE_URL konfiguriert, verwende Standard-MySQL-Konfiguration")
|
||||||
cfg.DatabaseType = "mysql"
|
cfg.DatabaseType = "mysql"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -43,7 +43,9 @@ func TestMaintSetupCheck(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestGetMasterData(t *testing.T) {
|
func TestGetMasterData(t *testing.T) {
|
||||||
database.SetupTestDB() //(false)
|
// Ensure fresh database connection
|
||||||
|
database.DB = nil
|
||||||
|
database.SetupTestDB()
|
||||||
// Initialize a Gin router
|
// Initialize a Gin router
|
||||||
r := gin.Default()
|
r := gin.Default()
|
||||||
router.SetupGin(r)
|
router.SetupGin(r)
|
||||||
@@ -56,7 +58,9 @@ func TestGetMasterData(t *testing.T) {
|
|||||||
c.JSON(http.StatusOK, gin.H{"status": "Test OK"})
|
c.JSON(http.StatusOK, gin.H{"status": "Test OK"})
|
||||||
})
|
})
|
||||||
u := user.User{}
|
u := user.User{}
|
||||||
u.FirstId(1)
|
err := u.FirstId(1)
|
||||||
|
require.NoError(t, err, "Failed to load user with ID 1")
|
||||||
|
require.Equal(t, "admin", u.Role, "User 1 should be admin")
|
||||||
|
|
||||||
// Create a test HTTP request
|
// Create a test HTTP request
|
||||||
req, _ := http.NewRequest("GET", "/api/maintenance", nil)
|
req, _ := http.NewRequest("GET", "/api/maintenance", nil)
|
||||||
@@ -82,8 +86,8 @@ func TestGetMasterData(t *testing.T) {
|
|||||||
Weapons []models.Weapon `json:"weapons"`
|
Weapons []models.Weapon `json:"weapons"`
|
||||||
}
|
}
|
||||||
var dta dtaStruct
|
var dta dtaStruct
|
||||||
err := json.Unmarshal(respRecorder.Body.Bytes(), &dta)
|
errUnmarshal := json.Unmarshal(respRecorder.Body.Bytes(), &dta)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, errUnmarshal)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestGetMDSkillCategories(t *testing.T) {
|
func TestGetMDSkillCategories(t *testing.T) {
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
package maintenance
|
package maintenance
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bamort/config"
|
||||||
"bamort/database"
|
"bamort/database"
|
||||||
"bamort/models"
|
"bamort/models"
|
||||||
"bamort/user"
|
"bamort/user"
|
||||||
@@ -20,8 +21,13 @@ func TestCopyLiveDatabaseToFile(t *testing.T) {
|
|||||||
// Setup
|
// Setup
|
||||||
tempDir := t.TempDir()
|
tempDir := t.TempDir()
|
||||||
targetFile := filepath.Join(tempDir, "empty_backup.db")
|
targetFile := filepath.Join(tempDir, "empty_backup.db")
|
||||||
|
envpath, _ := filepath.Abs("../.env.test")
|
||||||
|
os.Setenv("CONFIG_FILE", envpath)
|
||||||
|
|
||||||
// Create empty live database (only migrate structures, no data)
|
config.Cfg = config.LoadConfig()
|
||||||
|
|
||||||
|
// Reset database connection to ensure we use environment config
|
||||||
|
database.DB = nil
|
||||||
database.ConnectDatabase()
|
database.ConnectDatabase()
|
||||||
liveDB := database.DB
|
liveDB := database.DB
|
||||||
require.NotNil(t, liveDB, "Live database should be connected")
|
require.NotNil(t, liveDB, "Live database should be connected")
|
||||||
@@ -51,7 +57,7 @@ func TestCopyLiveDatabaseToFile(t *testing.T) {
|
|||||||
var userCount int64
|
var userCount int64
|
||||||
err = targetDB.Model(&user.User{}).Count(&userCount).Error
|
err = targetDB.Model(&user.User{}).Count(&userCount).Error
|
||||||
require.NoError(t, err, "Should be able to count users")
|
require.NoError(t, err, "Should be able to count users")
|
||||||
assert.Equal(t, int64(2), userCount, "User table should be empty")
|
assert.GreaterOrEqual(t, userCount, int64(2), "User table should have more that 2 users")
|
||||||
|
|
||||||
// Copy target file to database.PreparedTestDB for permanent storage
|
// Copy target file to database.PreparedTestDB for permanent storage
|
||||||
// Close the database connection before copying
|
// Close the database connection before copying
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ import (
|
|||||||
"net/http"
|
"net/http"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
"reflect"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
@@ -299,19 +300,30 @@ func copyTableData(sourceDB, targetDB *gorm.DB, model interface{}) error {
|
|||||||
batchSize := 100
|
batchSize := 100
|
||||||
totalBatches := (int(count) + batchSize - 1) / batchSize
|
totalBatches := (int(count) + batchSize - 1) / batchSize
|
||||||
|
|
||||||
|
// Get the element type for creating slice of records
|
||||||
|
modelType := reflect.TypeOf(model).Elem()
|
||||||
|
|
||||||
for offset := 0; offset < int(count); offset += batchSize {
|
for offset := 0; offset < int(count); offset += batchSize {
|
||||||
batchNum := (offset / batchSize) + 1
|
batchNum := (offset / batchSize) + 1
|
||||||
logger.Debug("Kopiere Batch %d/%d für %s (Offset: %d, Limit: %d)", batchNum, totalBatches, tableName, offset, batchSize)
|
logger.Debug("Kopiere Batch %d/%d für %s (Offset: %d, Limit: %d)", batchNum, totalBatches, tableName, offset, batchSize)
|
||||||
|
|
||||||
var records []map[string]interface{}
|
// Create a slice of the model type using reflection
|
||||||
|
sliceType := reflect.SliceOf(modelType)
|
||||||
|
recordsValue := reflect.MakeSlice(sliceType, 0, batchSize)
|
||||||
|
recordsPtr := reflect.New(sliceType)
|
||||||
|
recordsPtr.Elem().Set(recordsValue)
|
||||||
|
|
||||||
// Batch aus MariaDB lesen
|
// Batch aus MariaDB lesen (use proper struct type instead of map)
|
||||||
if err := sourceDB.Model(model).Offset(offset).Limit(batchSize).Find(&records).Error; err != nil {
|
if err := sourceDB.Model(model).Offset(offset).Limit(batchSize).Find(recordsPtr.Interface()).Error; err != nil {
|
||||||
logger.Error("Fehler beim Lesen von Batch %d für %s: %s", batchNum, tableName, err.Error())
|
logger.Error("Fehler beim Lesen von Batch %d für %s: %s", batchNum, tableName, err.Error())
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(records) == 0 {
|
// Get the actual records from reflection
|
||||||
|
records := recordsPtr.Elem().Interface()
|
||||||
|
recordsLen := recordsPtr.Elem().Len()
|
||||||
|
|
||||||
|
if recordsLen == 0 {
|
||||||
logger.Debug("Keine weiteren Datensätze für %s", tableName)
|
logger.Debug("Keine weiteren Datensätze für %s", tableName)
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
@@ -320,12 +332,12 @@ func copyTableData(sourceDB, targetDB *gorm.DB, model interface{}) error {
|
|||||||
// Verwende Clauses.OnConflict um bestehende Datensätze zu ersetzen
|
// Verwende Clauses.OnConflict um bestehende Datensätze zu ersetzen
|
||||||
if err := targetDB.Model(model).Clauses(clause.OnConflict{
|
if err := targetDB.Model(model).Clauses(clause.OnConflict{
|
||||||
UpdateAll: true,
|
UpdateAll: true,
|
||||||
}).Create(&records).Error; err != nil {
|
}).Create(records).Error; err != nil {
|
||||||
logger.Error("Fehler beim Einfügen von Batch %d für %s: %s", batchNum, tableName, err.Error())
|
logger.Error("Fehler beim Einfügen von Batch %d für %s: %s", batchNum, tableName, err.Error())
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
logger.Debug("Batch %d/%d für %s erfolgreich kopiert (%d Datensätze)", batchNum, totalBatches, tableName, len(records))
|
logger.Debug("Batch %d/%d für %s erfolgreich kopiert (%d Datensätze)", batchNum, totalBatches, tableName, recordsLen)
|
||||||
}
|
}
|
||||||
|
|
||||||
logger.Info("Tabelle %s erfolgreich kopiert (%d Datensätze total)", tableName, count)
|
logger.Info("Tabelle %s erfolgreich kopiert (%d Datensätze total)", tableName, count)
|
||||||
|
|||||||
@@ -69,9 +69,9 @@ type Bennies struct {
|
|||||||
|
|
||||||
type Vermoegen struct {
|
type Vermoegen struct {
|
||||||
BamortCharTrait
|
BamortCharTrait
|
||||||
Goldstuecke int `json:"goldstücke"` // GS
|
Goldstuecke int `gorm:"column:goldstuecke" json:"goldstücke"` // GS
|
||||||
Silberstuecke int `json:"silberstücke"` // SS
|
Silberstuecke int `gorm:"column:silberstuecke" json:"silberstücke"` // SS
|
||||||
Kupferstuecke int `json:"kupferstücke"` // KS
|
Kupferstuecke int `gorm:"column:kupferstuecke" json:"kupferstücke"` // KS
|
||||||
}
|
}
|
||||||
|
|
||||||
type Char struct {
|
type Char struct {
|
||||||
|
|||||||
@@ -565,6 +565,7 @@ func TestRegisterUser(t *testing.T) {
|
|||||||
Username: "bebe",
|
Username: "bebe",
|
||||||
PasswordHash: "osiris",
|
PasswordHash: "osiris",
|
||||||
Email: "frank@wuenscheonline.de",
|
Email: "frank@wuenscheonline.de",
|
||||||
|
Role: "admin",
|
||||||
}
|
}
|
||||||
|
|
||||||
hashedPassword := md5.Sum([]byte(usr.PasswordHash))
|
hashedPassword := md5.Sum([]byte(usr.PasswordHash))
|
||||||
@@ -576,6 +577,7 @@ func TestRegisterUser(t *testing.T) {
|
|||||||
Username: "bubnu",
|
Username: "bubnu",
|
||||||
PasswordHash: "osiris",
|
PasswordHash: "osiris",
|
||||||
Email: "spacer@wuenscheonline.de",
|
Email: "spacer@wuenscheonline.de",
|
||||||
|
Role: "standard",
|
||||||
}
|
}
|
||||||
hashedPassword = md5.Sum([]byte(usr2.PasswordHash))
|
hashedPassword = md5.Sum([]byte(usr2.PasswordHash))
|
||||||
usr2.PasswordHash = hex.EncodeToString(hashedPassword[:])
|
usr2.PasswordHash = hex.EncodeToString(hashedPassword[:])
|
||||||
@@ -591,6 +593,7 @@ func TestLoginUser(t *testing.T) {
|
|||||||
Username: "logintest",
|
Username: "logintest",
|
||||||
PasswordHash: "osiris",
|
PasswordHash: "osiris",
|
||||||
Email: "login@test.com",
|
Email: "login@test.com",
|
||||||
|
Role: "standard",
|
||||||
}
|
}
|
||||||
hashedPassword := md5.Sum([]byte(usr.PasswordHash))
|
hashedPassword := md5.Sum([]byte(usr.PasswordHash))
|
||||||
usr.PasswordHash = hex.EncodeToString(hashedPassword[:])
|
usr.PasswordHash = hex.EncodeToString(hashedPassword[:])
|
||||||
@@ -686,6 +689,7 @@ func TestUser_EdgeCases(t *testing.T) {
|
|||||||
Username: "",
|
Username: "",
|
||||||
PasswordHash: "",
|
PasswordHash: "",
|
||||||
Email: "",
|
Email: "",
|
||||||
|
Role: "standard",
|
||||||
}
|
}
|
||||||
err := user.Save()
|
err := user.Save()
|
||||||
assert.NoError(t, err, "Should save user with empty strings")
|
assert.NoError(t, err, "Should save user with empty strings")
|
||||||
@@ -704,6 +708,7 @@ func TestUser_EdgeCases(t *testing.T) {
|
|||||||
Username: "longuser",
|
Username: "longuser",
|
||||||
PasswordHash: longString,
|
PasswordHash: longString,
|
||||||
Email: "long@example.com",
|
Email: "long@example.com",
|
||||||
|
Role: "standard",
|
||||||
}
|
}
|
||||||
err = user2.Create()
|
err = user2.Create()
|
||||||
assert.NoError(t, err, "Should create user with long password hash")
|
assert.NoError(t, err, "Should create user with long password hash")
|
||||||
@@ -717,6 +722,7 @@ func TestUser_ConcurrentAccess(t *testing.T) {
|
|||||||
Username: "concurrentuser",
|
Username: "concurrentuser",
|
||||||
PasswordHash: "hash",
|
PasswordHash: "hash",
|
||||||
Email: "concurrent@example.com",
|
Email: "concurrent@example.com",
|
||||||
|
Role: "standard",
|
||||||
}
|
}
|
||||||
err := user.Create()
|
err := user.Create()
|
||||||
require.NoError(t, err, "Should be able to create test user")
|
require.NoError(t, err, "Should be able to create test user")
|
||||||
|
|||||||
@@ -48,8 +48,8 @@ services:
|
|||||||
image: mariadb:11.4
|
image: mariadb:11.4
|
||||||
container_name: bamort-mariadb-dev
|
container_name: bamort-mariadb-dev
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
#ports:
|
ports:
|
||||||
# - "3306:3306"
|
- "3306:3306"
|
||||||
environment:
|
environment:
|
||||||
MARIADB_ROOT_PASSWORD: ${MARIADB_ROOT_PASSWORD:-secure_root_password}
|
MARIADB_ROOT_PASSWORD: ${MARIADB_ROOT_PASSWORD:-secure_root_password}
|
||||||
MARIADB_DATABASE: ${MARIADB_DATABASE:-bamort}
|
MARIADB_DATABASE: ${MARIADB_DATABASE:-bamort}
|
||||||
|
|||||||
Reference in New Issue
Block a user