Files
Bridge-and-Join-s/modules/quikexport/server_test.go
T
zuevav 97e99b72c7 Экспорт QUIK — отдельная служба bj-quikexport; модули, выделенные из ядра, ставятся с обновлением
bj-quikexport (modules/quikexport + cmd/bj-quikexport, 127.0.0.1:8084): управление ARQA
quikexport перенесено из bj-server. Настройки у службы в /var/lib/bj/.bj/quik-export/settings.json
(при первом запуске переносятся из setup.json), раздел отдаётся фрагментом с индикатором меню,
действия отвечают X-BJ-Flash. bj-server встраивает раздел в «Настройку», проксирует формы
/admin/setup/quikexport/… и передаёт лицензию (X-BJ-Licensed). Общая проверка служебного
ключа — modules/modkit (им пользуется и bj-npr), общее для прокси — lkgateway/modules.go.

Выделенные из ядра модули (bj-npr, bj-quikexport: Component.FromCore) при обновлении ставятся и
там, где их ещё нет, если входят в лицензию: release.MarkSplitModules, request.json "new",
root-установщик ставит и включает unit-файл из комплекта. Если в обновлении меняется сам
установщик, модули ставятся после перезапуска bj-server (ensureSplitModules).

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-16 01:15:27 +03:00

75 lines
2.6 KiB
Go

package quikexport
import (
"net/http"
"net/http/httptest"
"net/url"
"os"
"path/filepath"
"strings"
"testing"
)
const testKey = "k-0123456789abcdef0123456789abcdef"
func TestServiceSectionAndSave(t *testing.T) {
dir := t.TempDir()
keyPath := filepath.Join(dir, "module.key")
setup := filepath.Join(dir, "setup.json")
store := filepath.Join(dir, "quik-export", "settings.json")
if err := os.WriteFile(keyPath, []byte(testKey+"\n"), 0o600); err != nil {
t.Fatal(err)
}
if err := os.WriteFile(setup, []byte(`{"quik_export":{"enabled":true,"quik_host":"10.0.0.1","quik_user":"exp","preset":"npr"}}`), 0o600); err != nil {
t.Fatal(err)
}
srv, err := New(Config{StorePath: store, SetupPath: setup, KeyPath: keyPath})
if err != nil {
t.Fatal(err)
}
if got := srv.store.Get(); got.QuikHost != "10.0.0.1" || !got.Enabled || got.QuikPort != 15100 {
t.Fatalf("перенос настроек из setup.json: %+v", got)
}
h := srv.Handler()
rec := httptest.NewRecorder()
h.ServeHTTP(rec, httptest.NewRequest(http.MethodGet, "/section", nil))
if rec.Code != http.StatusForbidden {
t.Fatalf("без ключа: код %d", rec.Code)
}
req := httptest.NewRequest(http.MethodGet, "/section", nil)
req.Header.Set("X-BJ-Module-Key", testKey)
req.Header.Set("X-BJ-Licensed", "1")
rec = httptest.NewRecorder()
h.ServeHTTP(rec, req)
if rec.Code != http.StatusOK {
t.Fatalf("раздел: код %d: %s", rec.Code, rec.Body.String())
}
body := rec.Body.String()
for _, want := range []string{"Подключение к серверу QUIK", `value="10.0.0.1"`, "/admin/setup/quikexport/apply"} {
if !strings.Contains(body, want) {
t.Errorf("в разделе нет %q", want)
}
}
if ind := rec.Header().Get("X-BJ-Indicator"); ind == "err" {
t.Errorf("индикатор при действующей лицензии: %q", ind)
}
form := url.Values{"part": {"quik"}, "quik_host": {"10.0.0.2"}, "quik_user": {"exp"}, "section": {"sec-quikexport"}}
req = httptest.NewRequest(http.MethodPost, "/admin/setup/quikexport", strings.NewReader(form.Encode()))
req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
req.Header.Set("X-BJ-Module-Key", testKey)
rec = httptest.NewRecorder()
h.ServeHTTP(rec, req)
if rec.Code != http.StatusNoContent || rec.Header().Get("X-BJ-Flash") == "" {
t.Fatalf("сохранение: код %d, flash %q", rec.Code, rec.Header().Get("X-BJ-Flash"))
}
if got := srv.store.Get(); got.QuikHost != "10.0.0.2" {
t.Fatalf("после сохранения quik_host = %q", got.QuikHost)
}
if fi, err := os.Stat(store); err != nil || fi.Mode().Perm() != 0o600 {
t.Fatalf("файл настроек: %v %v", fi, err)
}
}