146 lines
3.8 KiB
Go
146 lines
3.8 KiB
Go
package main
|
|
|
|
import (
|
|
"bytes"
|
|
"context"
|
|
"encoding/json"
|
|
"io"
|
|
"net/http"
|
|
"os"
|
|
"path/filepath"
|
|
"sync"
|
|
"testing"
|
|
)
|
|
|
|
func request(t *testing.T, s *service, method, path string, body []byte) (int, []byte) {
|
|
t.Helper()
|
|
req, _ := http.NewRequest(method, "http://test"+path, bytes.NewReader(body))
|
|
req.Header.Set("Content-Type", "application/json")
|
|
resp, err := s.app.Test(req)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
defer resp.Body.Close()
|
|
raw, err := io.ReadAll(resp.Body)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
return resp.StatusCode, raw
|
|
}
|
|
|
|
func TestMemoryUpdatesAndCommands(t *testing.T) {
|
|
dir, id := fixture(t)
|
|
data, err := loadSnapshots(dir, id)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
s := newService(data, "secret")
|
|
var published []envelope
|
|
s.publish = func(_ context.Context, _ string, raw []byte) (string, error) {
|
|
var msg envelope
|
|
json.Unmarshal(raw, &msg)
|
|
published = append(published, msg)
|
|
return "confirmed", nil
|
|
}
|
|
before, err := os.ReadFile(filepath.Join(dir, "tasks/1.json"))
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
var task map[string]any
|
|
json.Unmarshal(before, &task)
|
|
task["task_revision"] = float64(123)
|
|
updated, _ := json.Marshal(task)
|
|
code, raw := request(t, s, "PUT", "/test/config/tasks/1", updated)
|
|
if code != 200 {
|
|
t.Fatalf("update: %d %s", code, raw)
|
|
}
|
|
if len(published) != 0 {
|
|
t.Fatal("configuration update sent automatic command")
|
|
}
|
|
s.mu.RLock()
|
|
got := s.data.tasks["1"]
|
|
s.mu.RUnlock()
|
|
if !bytes.Equal(got, updated) {
|
|
t.Fatal("update not in memory")
|
|
}
|
|
code, _ = request(t, s, "PUT", "/test/config/tasks/1", []byte(`{"invalid":true}`))
|
|
if code != 400 {
|
|
t.Fatal(code)
|
|
}
|
|
task["task_id"] = "2"
|
|
bad, _ := json.Marshal(task)
|
|
code, _ = request(t, s, "PUT", "/test/config/tasks/1", bad)
|
|
if code != 400 {
|
|
t.Fatal(code)
|
|
}
|
|
code, _ = request(t, s, "PUT", "/test/config/tasks/2", updated)
|
|
if code != 404 {
|
|
t.Fatal(code)
|
|
}
|
|
for _, action := range []string{"start", "resume", "edit"} {
|
|
code, raw = request(t, s, "POST", "/test/task-controls", []byte(`{"event_id":"ctrl-`+action+`","task_id":"1","action":"`+action+`","reason":"manual test"}`))
|
|
if code != 200 {
|
|
t.Fatalf("%s %d %s", action, code, raw)
|
|
}
|
|
}
|
|
code, _ = request(t, s, "POST", "/test/task-controls", []byte(`{"event_id":"ctrl-stop","task_id":"1","action":"stop"}`))
|
|
if code != 400 {
|
|
t.Fatal(code)
|
|
}
|
|
code, raw = request(t, s, "POST", "/test/sip-refresh", []byte(`{"event_id":"sip-test","trunk_id":"trunk-mock","change_type":"enabled","revision":8}`))
|
|
if code != 200 {
|
|
t.Fatalf("sip %d %s", code, raw)
|
|
}
|
|
code, raw = request(t, s, "POST", "/test/calls", []byte(`{"event_id":"call-http","task_id":"1","callee":"123456"}`))
|
|
if code != 200 {
|
|
t.Fatalf("call %d %s", code, raw)
|
|
}
|
|
code, raw = request(t, s, "GET", "/test/events?event_id=call-http", nil)
|
|
if code != 200 || !bytes.Contains(raw, []byte(`"confirmed"`)) {
|
|
t.Fatalf("query: %d %s", code, raw)
|
|
}
|
|
code, _ = request(t, s, "POST", "/test/calls", []byte(`{"event_id":"bad","task_id":"1","callee":"123","unknown":true}`))
|
|
if code != 400 {
|
|
t.Fatal(code)
|
|
}
|
|
after, _ := os.ReadFile(filepath.Join(dir, "tasks/1.json"))
|
|
if !bytes.Equal(before, after) {
|
|
t.Fatal("file changed")
|
|
}
|
|
reloaded, err := loadSnapshots(dir, id)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if !bytes.Equal(reloaded.tasks["1"], before) {
|
|
t.Fatal("restart restored memory changes")
|
|
}
|
|
}
|
|
|
|
func TestConcurrentMemoryReadAndUpdate(t *testing.T) {
|
|
dir, id := fixture(t)
|
|
data, err := loadSnapshots(dir, id)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
s := newService(data, "secret")
|
|
var wg sync.WaitGroup
|
|
for i := 0; i < 8; i++ {
|
|
wg.Add(1)
|
|
go func() {
|
|
defer wg.Done()
|
|
for j := 0; j < 10; j++ {
|
|
if err := s.replace("task", "1", data.tasks["1"]); err != nil {
|
|
t.Error(err)
|
|
}
|
|
s.mu.RLock()
|
|
_, err := s.data.page("")
|
|
s.mu.RUnlock()
|
|
if err != nil {
|
|
t.Error(err)
|
|
}
|
|
}
|
|
}()
|
|
}
|
|
wg.Wait()
|
|
}
|