Initial commit: omnichannel-mcp — MCP-сервер управления платформой Omnichannel
This commit is contained in:
@@ -0,0 +1,110 @@
|
||||
package configserver
|
||||
|
||||
import (
|
||||
"os"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestParseConfigDefaults(t *testing.T) {
|
||||
cfg, err := ParseConfig([]byte(`{"servers":[{"alias":"a","base_url":"http://h:5005","username":"u","password":"p"}]}`))
|
||||
if err != nil {
|
||||
t.Fatalf("ParseConfig: %v", err)
|
||||
}
|
||||
if !cfg.ReadOnly {
|
||||
t.Fatalf("read_only должен по умолчанию быть true (fail-safe)")
|
||||
}
|
||||
if cfg.Default != "a" {
|
||||
t.Fatalf("default = %q, ожидалось a", cfg.Default)
|
||||
}
|
||||
srv, err := cfg.Server("")
|
||||
if err != nil {
|
||||
t.Fatalf("Server: %v", err)
|
||||
}
|
||||
if srv.TimeoutSec != DefaultTimeoutSec || srv.MaxOutputBytes != DefaultMaxOutputBytes {
|
||||
t.Fatalf("дефолты лимитов не применены: %+v", srv)
|
||||
}
|
||||
}
|
||||
|
||||
func TestSingleServerShorthand(t *testing.T) {
|
||||
cfg, err := ParseConfig([]byte(`{"base_url":"http://h:5005","username":"u","password":"p"}`))
|
||||
if err != nil {
|
||||
t.Fatalf("ParseConfig: %v", err)
|
||||
}
|
||||
if len(cfg.Servers) != 1 || cfg.Servers[0].Alias != "default" {
|
||||
t.Fatalf("shorthand не сработал: %+v", cfg.Servers)
|
||||
}
|
||||
if cfg.Default != "default" {
|
||||
t.Fatalf("default = %q", cfg.Default)
|
||||
}
|
||||
}
|
||||
|
||||
func TestUnresolvedVarFails(t *testing.T) {
|
||||
t.Setenv("OMNI_PRESENT", "x")
|
||||
_ = os.Unsetenv("OMNI_MISSING")
|
||||
_, err := ParseConfig([]byte(`{"servers":[{"alias":"a","base_url":"${OMNI_MISSING}","username":"u","password":"p"}]}`))
|
||||
if err == nil {
|
||||
t.Fatal("ожидалась ошибка о незаданной переменной")
|
||||
}
|
||||
}
|
||||
|
||||
func TestUnknownFieldFails(t *testing.T) {
|
||||
_, err := ParseConfig([]byte(`{"servers":[{"alias":"a","base_url":"http://h:5005"}],"typo_field":1}`))
|
||||
if err == nil {
|
||||
t.Fatal("ожидалась ошибка строгого разбора неизвестного поля")
|
||||
}
|
||||
}
|
||||
|
||||
func TestHostAllowlist(t *testing.T) {
|
||||
_, err := ParseConfig([]byte(`{"servers":[{"alias":"a","base_url":"http://evil:5005"}],"allow_hosts":["good"]}`))
|
||||
if err == nil {
|
||||
t.Fatal("ожидалась ошибка: хост вне allow_hosts")
|
||||
}
|
||||
}
|
||||
|
||||
func TestServerUnknownAlias(t *testing.T) {
|
||||
cfg, err := ParseConfig([]byte(`{"servers":[{"alias":"a","base_url":"http://h:5005"}]}`))
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if _, err := cfg.Server("nope"); err == nil {
|
||||
t.Fatal("ожидалась ошибка неизвестного алиаса")
|
||||
}
|
||||
}
|
||||
|
||||
func TestLoadFileMergesLocal(t *testing.T) {
|
||||
dir := t.TempDir()
|
||||
main := filepath.Join(dir, "config.json")
|
||||
local := filepath.Join(dir, "config.local.json")
|
||||
|
||||
if err := os.WriteFile(main, []byte(`{
|
||||
"servers":[{"alias":"prod","base_url":"http://example:5005","username":"u","password":"p"}],
|
||||
"read_only": true
|
||||
}`), 0o600); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if err := os.WriteFile(local, []byte(`{
|
||||
"servers":[{"alias":"prod","base_url":"http://127.0.0.1:5005","password":"secret"}],
|
||||
"read_only": false
|
||||
}`), 0o600); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
cfg, err := LoadFile(main)
|
||||
if err != nil {
|
||||
t.Fatalf("LoadFile: %v", err)
|
||||
}
|
||||
if cfg.ReadOnly {
|
||||
t.Fatal("read_only из local не применён")
|
||||
}
|
||||
srv := cfg.Servers[0]
|
||||
if srv.BaseURL != "http://127.0.0.1:5005" {
|
||||
t.Fatalf("base_url не переопределён: %q", srv.BaseURL)
|
||||
}
|
||||
if srv.Username != "u" {
|
||||
t.Fatalf("username из main потерян: %q", srv.Username)
|
||||
}
|
||||
if srv.Password != "secret" {
|
||||
t.Fatalf("password из local не применён: %q", srv.Password)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user