// package mock_env -- обеспечивает мок-окружение для тестов. package mock_env import ( "os" "strings" "gitp78su.ipnodns.ru/svi/kern/v4/lev0/defs" "gitp78su.ipnodns.ru/svi/kern/v4/lev0/helpers" ) type IMockEnv interface { // Pwd -- возвращает текущий рабочий каталог процесса Pwd() defs.ITxtFix } // MockEnv -- объект мок-окружения. type MockEnv struct { dictEnv map[defs.ATxt]defs.ITxtFix // Словарь переменных окружения pwd defs.ITxtFix // Текущий путь процесса fileName defs.ITxtFix // Полный путь к .env файлу strEnv defs.ITxtFix // Фактическое содержимое .env файла } // MakeEnv -- возвращает новое мок-окружение. func MakeEnv() *MockEnv { sf := &MockEnv{ dictEnv: map[defs.ATxt]defs.ITxtFix{}, } sf.setPath() sf.readEnv() sf.parseEnv() err := sf.SetAll() helpers.Hassert(err == nil, "MakeEnv(): SetAll, err=\n\t%v", []any{err}) return sf } // Парсит полученный текст .env для установки переменных окружения. func (sf *MockEnv) parseEnv() { lstStr := strings.SplitSeq(sf.strEnv.String(), "\n") for val := range lstStr { pair := strings.TrimSuffix(val, "\r") if pair == "" { continue } if strings.HasPrefix(val, "#") { continue } sf.parseEnvStr(defs.Txt(pair)) } } // Парсит строку окружения. func (sf *MockEnv) parseEnvStr(pair defs.ITxtFix) { lstPair := strings.Split(pair.String(), "=") helpers.Hassert(len(lstPair) >= 2, "MockEnv.parseEnvStr(): pair(%v) not have =", []any{pair}) key := lstPair[0] helpers.Hassert(key != "", "MockEnv.parseEnvStr(): in pair(%v) key is empty", []any{pair}) lstVal := lstPair[1:] val := "" for _, val_ := range lstVal { val += val_ + "=" } val = strings.TrimSuffix(val, "=") helpers.Hassert(val != "", "MockEnv.parseEnvStr(): in pair(%v) val is empty", []any{pair}) sf.dictEnv[defs.ATxt(key)] = defs.Txt(val) } // Читает файл переменных окружения. func (sf *MockEnv) readEnv() { binEnv, err := os.ReadFile(sf.fileName.String()) helpers.Hassert(err == nil, "MockEnv.readEnv(): in read %v, err=\n\t%v", []any{sf.fileName, err}) sf.strEnv = defs.Txt(string(binEnv)) } // Устанавливает текущий путь относительно проекта в dev. func (sf *MockEnv) setPath() { dir, err := os.Getwd() helpers.Hassert(err == nil, "MockEnv.setPath(): in get PWD, err=\n\t%v", []any{err}) lstDir := strings.Split(dir, "/") var pwd strings.Builder fileName := "" isFind := false for _, point := range lstDir { pwd.WriteString(point + "/") fileName = pwd.String() + ".env" _, err := os.ReadFile(fileName) if err == nil { isFind = true break } } helpers.Hassert(isFind, "MockEnv.setPath(): not find file .env", []any{}) sf.pwd = defs.Txt(pwd.String() + "/bin_dev") err = os.MkdirAll(sf.pwd.String(), 0750) helpers.Hassert(err == nil, "MockEnv.setPath(): in create PWD, err=\n\t%v", []any{err}) err = os.Chdir(sf.pwd.String()) helpers.Hassert(err == nil, "MockEnv.setPath(): in set cwd(%v), err=\n\t%v", []any{sf.pwd, err}) sf.fileName = defs.Txt(fileName) } // Pwd -- возвращает текущий рабочий каталог процесса. func (sf *MockEnv) Pwd() defs.ITxtFix { return sf.pwd } // SetAll -- поднимает все переменные окружения. func (sf *MockEnv) SetAll() error { sf.ResetAll() for key, val := range sf.dictEnv { sf.Reset(defs.Txt("key")) err := os.Setenv(string(key), val.String()) helpers.Hassert(err == nil, "MockEnv.SetAll(): in set env %v on key %v, err=\n\t%v", []any{key, val, err}) } return nil } // ResetAll -- сбрасывает все переменные окружения. func (sf *MockEnv) ResetAll() { for key := range sf.dictEnv { sf.Reset(defs.Txt(key)) } } // Reset -- сбрасывает конкретный ключ. func (sf *MockEnv) Reset(key defs.ITxtFix) { helpers.Hassert(key.Get() != "", "MockEnv.Reset(): key is empty", []any{}) err := os.Unsetenv(key.String()) helpers.Hassert(err == nil, "MockEnv.Reset(): in reset env %v, err=\n\t%v", []any{key, err}) }