pink_fox/application/inner/test/test.go

150 lines
3.4 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package test
import (
"database/sql"
"fmt"
"os"
"pink_fox/inner/config"
"pink_fox/packages/fw"
"regexp"
"strings"
)
var (
dbTest *DBTest = nil
)
type DBTest struct {
db *sql.DB
seedersPath string
}
func NewDBTest() *DBTest {
if dbTest == nil {
path := "/app/config-test.yml"
dbConf, err := config.LoadTestConfig(path)
if err != nil {
panic(err.Add("ошибка загрузки конфига"))
}
db, err := fw.CreateConnection(dbConf.Host, dbConf.Port, dbConf.User, dbConf.Password, dbConf.Database)
if err != nil {
panic(err.Add("ошибка соединение с базой данной"))
}
err = refreshDatabase(db, dbConf.Migrations, dbConf.Database, true)
if err != nil {
panic(err.Add("ошибка обновление базы данных"))
}
dbTest = &DBTest{
db: db,
seedersPath: "/app/database/seeders",
}
}
return dbTest
}
func (it *DBTest) GetDB() *sql.DB {
return it.db
}
func (it *DBTest) Seed(filename string) *DBTest {
path := it.seedersPath + "/" + filename
queryByte, err := os.ReadFile(path)
if err != nil {
panic(fw.ErrStr(fmt.Sprintf("ошибка загрузки файла для %s: %s", path, err)))
}
tx, err := it.db.Begin()
if err != nil {
panic(fw.ErrStr(fmt.Sprintf("ошибка запуска транзакции: %s", err)))
}
defer func() {
_ = tx.Rollback()
}()
cleanedData := it.removeSQLComments(string(queryByte))
queries := it.splitSQLQueries(cleanedData)
for _, query := range queries {
query = strings.TrimSpace(query)
if query == "" {
continue
}
if _, err = tx.Exec(query); err != nil {
panic(fmt.Errorf("ошибка в запросе `%s`: %s", query, err))
}
}
err = tx.Commit()
if err != nil {
panic(fmt.Sprintf("ошибка подтверждения транзакции: %s", err))
}
return it
}
func refreshDatabase(db *sql.DB, migrationsPath, dbName string, disableLogger bool) fw.Error {
err := fw.DropAppTable(db, dbName)
if err != nil {
return err.Tap()
}
return fw.MigrateUp(db, migrationsPath, disableLogger)
}
func (it *DBTest) removeSQLComments(sql string) string {
// Удаляем однострочные комментарии (-- до конца строки)
reSingleLine := regexp.MustCompile(`--.*`)
sql = reSingleLine.ReplaceAllString(sql, "")
// Удаляем многострочные комментарии (/* ... */)
reMultiLine := regexp.MustCompile(`/\*.*?\*/`)
sql = reMultiLine.ReplaceAllString(sql, "")
return sql
}
// splitSQLQueries разбивает SQL-код на отдельные запросы
func (it *DBTest) splitSQLQueries(sql string) []string {
var queries []string
var buffer strings.Builder
inString := false
quoteChar := byte(0)
for i := 0; i < len(sql); i++ {
char := sql[i]
switch {
case char == '\'' || char == '"':
if !inString {
inString = true
quoteChar = char
} else if char == quoteChar {
// Проверяем, не экранирована ли кавычка
if i > 0 && sql[i-1] == '\\' {
continue
}
inString = false
quoteChar = 0
}
buffer.WriteByte(char)
case char == ';' && !inString:
queries = append(queries, buffer.String())
buffer.Reset()
default:
buffer.WriteByte(char)
}
}
// Добавляем последний запрос (если есть)
if buffer.Len() > 0 {
queries = append(queries, buffer.String())
}
return queries
}