Some checks failed
Tests / unit-tests (push) Failing after 22s
Uklonjen multi-tab sistem — sada jedna PTY sesija po stranici. Dodat idle detection: status "Završeno", flash animacija, browser notifikacija i treptanje naslova kad je tab u pozadini. CSS premešten iz inline stilova u style.css. Dodat /api/projects endpoint i testovi za PTY sesije. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
137 lines
3.1 KiB
Go
137 lines
3.1 KiB
Go
package main
|
|
|
|
import (
|
|
"testing"
|
|
)
|
|
|
|
func TestRingBuffer(t *testing.T) {
|
|
t.Run("write and read", func(t *testing.T) {
|
|
rb := NewRingBuffer(10)
|
|
rb.Write([]byte("hello"))
|
|
got := rb.Bytes()
|
|
if string(got) != "hello" {
|
|
t.Errorf("got %q, want %q", got, "hello")
|
|
}
|
|
})
|
|
|
|
t.Run("wrap around", func(t *testing.T) {
|
|
rb := NewRingBuffer(5)
|
|
rb.Write([]byte("abcdefgh")) // wraps around
|
|
got := rb.Bytes()
|
|
if string(got) != "defgh" {
|
|
t.Errorf("got %q, want %q", got, "defgh")
|
|
}
|
|
})
|
|
|
|
t.Run("exact size", func(t *testing.T) {
|
|
rb := NewRingBuffer(5)
|
|
rb.Write([]byte("abcde"))
|
|
got := rb.Bytes()
|
|
if string(got) != "abcde" {
|
|
t.Errorf("got %q, want %q", got, "abcde")
|
|
}
|
|
})
|
|
|
|
t.Run("empty", func(t *testing.T) {
|
|
rb := NewRingBuffer(10)
|
|
got := rb.Bytes()
|
|
if len(got) != 0 {
|
|
t.Errorf("expected empty, got %q", got)
|
|
}
|
|
})
|
|
|
|
t.Run("multiple writes", func(t *testing.T) {
|
|
rb := NewRingBuffer(8)
|
|
rb.Write([]byte("abc"))
|
|
rb.Write([]byte("def"))
|
|
got := rb.Bytes()
|
|
if string(got) != "abcdef" {
|
|
t.Errorf("got %q, want %q", got, "abcdef")
|
|
}
|
|
})
|
|
|
|
t.Run("overflow multiple writes", func(t *testing.T) {
|
|
rb := NewRingBuffer(5)
|
|
rb.Write([]byte("abc"))
|
|
rb.Write([]byte("defgh")) // total 8, buffer 5
|
|
got := rb.Bytes()
|
|
if string(got) != "defgh" {
|
|
t.Errorf("got %q, want %q", got, "defgh")
|
|
}
|
|
})
|
|
}
|
|
|
|
func TestPTYSessionManager(t *testing.T) {
|
|
t.Run("new manager has no sessions", func(t *testing.T) {
|
|
m := &PTYSessionManager{
|
|
sessions: make(map[string]*PTYSession),
|
|
stopCh: make(chan struct{}),
|
|
}
|
|
if len(m.sessions) != 0 {
|
|
t.Error("expected empty sessions")
|
|
}
|
|
})
|
|
|
|
t.Run("different session keys create separate sessions", func(t *testing.T) {
|
|
m := &PTYSessionManager{
|
|
sessions: make(map[string]*PTYSession),
|
|
stopCh: make(chan struct{}),
|
|
}
|
|
|
|
// Use /tmp as a safe projectDir for testing
|
|
sess1, isNew1, err := m.GetOrCreate("arv:1", "/tmp")
|
|
if err != nil {
|
|
t.Fatalf("GetOrCreate arv:1: %v", err)
|
|
}
|
|
if !isNew1 {
|
|
t.Error("expected arv:1 to be new")
|
|
}
|
|
defer sess1.Close()
|
|
|
|
sess2, isNew2, err := m.GetOrCreate("arv:2", "/tmp")
|
|
if err != nil {
|
|
t.Fatalf("GetOrCreate arv:2: %v", err)
|
|
}
|
|
if !isNew2 {
|
|
t.Error("expected arv:2 to be new")
|
|
}
|
|
defer sess2.Close()
|
|
|
|
if sess1 == sess2 {
|
|
t.Error("expected different session objects for different keys")
|
|
}
|
|
|
|
if len(m.sessions) != 2 {
|
|
t.Errorf("expected 2 sessions, got %d", len(m.sessions))
|
|
}
|
|
})
|
|
|
|
t.Run("same session key returns existing session", func(t *testing.T) {
|
|
m := &PTYSessionManager{
|
|
sessions: make(map[string]*PTYSession),
|
|
stopCh: make(chan struct{}),
|
|
}
|
|
|
|
sess1, isNew1, err := m.GetOrCreate("arv:1", "/tmp")
|
|
if err != nil {
|
|
t.Fatalf("GetOrCreate: %v", err)
|
|
}
|
|
if !isNew1 {
|
|
t.Error("expected first call to be new")
|
|
}
|
|
defer sess1.Close()
|
|
|
|
sess2, isNew2, err := m.GetOrCreate("arv:1", "/tmp")
|
|
if err != nil {
|
|
t.Fatalf("GetOrCreate second: %v", err)
|
|
}
|
|
if isNew2 {
|
|
t.Error("expected second call to reuse existing session")
|
|
}
|
|
|
|
if sess1 != sess2 {
|
|
t.Error("expected same session object for same key")
|
|
}
|
|
})
|
|
}
|