- pkg/api/provider.go: remove banned os/syscall imports; delegate to
new process.KillPID and process.IsPIDAlive exported helpers
- service.go: rename `sr` → `startResult`; add KillPID/IsPIDAlive exports
- runner.go: rename `aggResult` → `aggregate` in all three RunXxx methods;
add usage-example comments on all exported functions
- process.go: replace prose doc-comments with usage-example comments
- buffer.go, registry.go, health.go: replace prose comments with examples
- buffer_test.go: rename TestRingBuffer_Basics_Good → TestBuffer_{Write,String,Reset}_{Good,Bad,Ugly}
- All test files: add missing _Bad and _Ugly variants for all functions
(daemon, health, pidfile, registry, runner, process, program, exec, pkg/api)
Co-Authored-By: Virgil <virgil@lethean.io>
146 lines
3.6 KiB
Go
146 lines
3.6 KiB
Go
package process
|
|
|
|
import (
|
|
"sync"
|
|
"testing"
|
|
|
|
"github.com/stretchr/testify/assert"
|
|
)
|
|
|
|
func TestBuffer_Write_Good(t *testing.T) {
|
|
t.Run("write and read", func(t *testing.T) {
|
|
rb := NewRingBuffer(10)
|
|
|
|
itemCount, err := rb.Write([]byte("hello"))
|
|
assert.NoError(t, err)
|
|
assert.Equal(t, 5, itemCount)
|
|
assert.Equal(t, "hello", rb.String())
|
|
assert.Equal(t, 5, rb.Len())
|
|
})
|
|
|
|
t.Run("overflow wraps around", func(t *testing.T) {
|
|
rb := NewRingBuffer(5)
|
|
|
|
_, _ = rb.Write([]byte("hello"))
|
|
assert.Equal(t, "hello", rb.String())
|
|
|
|
_, _ = rb.Write([]byte("world"))
|
|
// Should contain "world" (overwrote "hello")
|
|
assert.Equal(t, 5, rb.Len())
|
|
assert.Equal(t, "world", rb.String())
|
|
})
|
|
|
|
t.Run("partial overflow", func(t *testing.T) {
|
|
rb := NewRingBuffer(10)
|
|
|
|
_, _ = rb.Write([]byte("hello"))
|
|
_, _ = rb.Write([]byte("worldx"))
|
|
// Should contain "lloworldx" (11 chars, buffer is 10)
|
|
assert.Equal(t, 10, rb.Len())
|
|
})
|
|
|
|
t.Run("bytes returns copy", func(t *testing.T) {
|
|
rb := NewRingBuffer(10)
|
|
_, _ = rb.Write([]byte("hello"))
|
|
|
|
contents := rb.Bytes()
|
|
assert.Equal(t, []byte("hello"), contents)
|
|
|
|
// Modifying returned bytes shouldn't affect buffer
|
|
contents[0] = 'x'
|
|
assert.Equal(t, "hello", rb.String())
|
|
})
|
|
}
|
|
|
|
func TestBuffer_Write_Bad(t *testing.T) {
|
|
t.Run("empty write is a no-op", func(t *testing.T) {
|
|
rb := NewRingBuffer(10)
|
|
itemCount, err := rb.Write([]byte{})
|
|
assert.NoError(t, err)
|
|
assert.Equal(t, 0, itemCount)
|
|
assert.Equal(t, "", rb.String())
|
|
})
|
|
}
|
|
|
|
func TestBuffer_Write_Ugly(t *testing.T) {
|
|
t.Run("concurrent writes do not race", func(t *testing.T) {
|
|
rb := NewRingBuffer(64)
|
|
var wg sync.WaitGroup
|
|
for i := 0; i < 10; i++ {
|
|
wg.Add(1)
|
|
go func() {
|
|
defer wg.Done()
|
|
_, _ = rb.Write([]byte("data"))
|
|
}()
|
|
}
|
|
wg.Wait()
|
|
// Buffer should not panic and length should be bounded by capacity
|
|
assert.LessOrEqual(t, rb.Len(), rb.Cap())
|
|
})
|
|
}
|
|
|
|
func TestBuffer_String_Good(t *testing.T) {
|
|
t.Run("empty buffer returns empty string", func(t *testing.T) {
|
|
rb := NewRingBuffer(10)
|
|
assert.Equal(t, "", rb.String())
|
|
})
|
|
|
|
t.Run("full buffer wraps correctly", func(t *testing.T) {
|
|
rb := NewRingBuffer(5)
|
|
_, _ = rb.Write([]byte("abcde"))
|
|
assert.Equal(t, "abcde", rb.String())
|
|
})
|
|
}
|
|
|
|
func TestBuffer_String_Bad(t *testing.T) {
|
|
t.Run("overflowed buffer reflects newest data", func(t *testing.T) {
|
|
rb := NewRingBuffer(5)
|
|
_, _ = rb.Write([]byte("hello"))
|
|
_, _ = rb.Write([]byte("world"))
|
|
// Oldest bytes ("hello") have been overwritten
|
|
assert.Equal(t, "world", rb.String())
|
|
})
|
|
}
|
|
|
|
func TestBuffer_String_Ugly(t *testing.T) {
|
|
t.Run("size-1 buffer holds only last byte", func(t *testing.T) {
|
|
rb := NewRingBuffer(1)
|
|
_, _ = rb.Write([]byte("abc"))
|
|
assert.Equal(t, "c", rb.String())
|
|
})
|
|
}
|
|
|
|
func TestBuffer_Reset_Good(t *testing.T) {
|
|
t.Run("clears all data", func(t *testing.T) {
|
|
rb := NewRingBuffer(10)
|
|
_, _ = rb.Write([]byte("hello"))
|
|
rb.Reset()
|
|
assert.Equal(t, "", rb.String())
|
|
assert.Equal(t, 0, rb.Len())
|
|
})
|
|
|
|
t.Run("cap returns buffer capacity", func(t *testing.T) {
|
|
rb := NewRingBuffer(42)
|
|
assert.Equal(t, 42, rb.Cap())
|
|
})
|
|
}
|
|
|
|
func TestBuffer_Reset_Bad(t *testing.T) {
|
|
t.Run("reset on empty buffer is a no-op", func(t *testing.T) {
|
|
rb := NewRingBuffer(10)
|
|
rb.Reset()
|
|
assert.Equal(t, "", rb.String())
|
|
assert.Equal(t, 0, rb.Len())
|
|
})
|
|
}
|
|
|
|
func TestBuffer_Reset_Ugly(t *testing.T) {
|
|
t.Run("reset after overflow allows fresh writes", func(t *testing.T) {
|
|
rb := NewRingBuffer(5)
|
|
_, _ = rb.Write([]byte("hello"))
|
|
_, _ = rb.Write([]byte("world"))
|
|
rb.Reset()
|
|
_, _ = rb.Write([]byte("new"))
|
|
assert.Equal(t, "new", rb.String())
|
|
})
|
|
}
|