mirror of
https://github.com/charmbracelet/crush.git
synced 2025-08-02 05:20:46 +03:00
fix: pkg
This commit is contained in:
34
internal/csync/slices.go
Normal file
34
internal/csync/slices.go
Normal file
@@ -0,0 +1,34 @@
|
||||
package csync
|
||||
|
||||
import (
|
||||
"iter"
|
||||
"sync"
|
||||
)
|
||||
|
||||
type LazySlice[K any] struct {
|
||||
inner []K
|
||||
mu sync.Mutex
|
||||
}
|
||||
|
||||
func NewLazySlice[K any](load func() []K) *LazySlice[K] {
|
||||
s := &LazySlice[K]{}
|
||||
s.mu.Lock()
|
||||
go func() {
|
||||
s.inner = load()
|
||||
s.mu.Unlock()
|
||||
}()
|
||||
return s
|
||||
}
|
||||
|
||||
func (s *LazySlice[K]) Iter() iter.Seq[K] {
|
||||
s.mu.Lock()
|
||||
inner := s.inner
|
||||
s.mu.Unlock()
|
||||
return func(yield func(K) bool) {
|
||||
for _, v := range inner {
|
||||
if !yield(v) {
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
86
internal/csync/slices_test.go
Normal file
86
internal/csync/slices_test.go
Normal file
@@ -0,0 +1,86 @@
|
||||
package csync
|
||||
|
||||
import (
|
||||
"sync/atomic"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestLazySlice_Iter(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
data := []string{"a", "b", "c"}
|
||||
s := NewLazySlice(func() []string {
|
||||
// TODO: use synctest when new Go is out.
|
||||
time.Sleep(10 * time.Millisecond) // Small delay to ensure loading happens
|
||||
return data
|
||||
})
|
||||
|
||||
var result []string
|
||||
for v := range s.Iter() {
|
||||
result = append(result, v)
|
||||
}
|
||||
|
||||
assert.Equal(t, data, result)
|
||||
}
|
||||
|
||||
func TestLazySlice_IterWaitsForLoading(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
var loaded atomic.Bool
|
||||
data := []string{"x", "y", "z"}
|
||||
|
||||
s := NewLazySlice(func() []string {
|
||||
// TODO: use synctest when new Go is out.
|
||||
time.Sleep(100 * time.Millisecond)
|
||||
loaded.Store(true)
|
||||
return data
|
||||
})
|
||||
|
||||
assert.False(t, loaded.Load(), "should not be loaded immediately")
|
||||
|
||||
var result []string
|
||||
for v := range s.Iter() {
|
||||
result = append(result, v)
|
||||
}
|
||||
|
||||
assert.True(t, loaded.Load(), "should be loaded after Iter")
|
||||
assert.Equal(t, data, result)
|
||||
}
|
||||
|
||||
func TestLazySlice_EmptySlice(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
s := NewLazySlice(func() []string {
|
||||
return []string{}
|
||||
})
|
||||
|
||||
var result []string
|
||||
for v := range s.Iter() {
|
||||
result = append(result, v)
|
||||
}
|
||||
|
||||
assert.Empty(t, result)
|
||||
}
|
||||
|
||||
func TestLazySlice_EarlyBreak(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
data := []string{"a", "b", "c", "d", "e"}
|
||||
s := NewLazySlice(func() []string {
|
||||
time.Sleep(10 * time.Millisecond) // Small delay to ensure loading happens
|
||||
return data
|
||||
})
|
||||
|
||||
var result []string
|
||||
for v := range s.Iter() {
|
||||
result = append(result, v)
|
||||
if len(result) == 2 {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
assert.Equal(t, []string{"a", "b"}, result)
|
||||
}
|
||||
@@ -10,8 +10,8 @@ import (
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/charmbracelet/crush/csync"
|
||||
"github.com/charmbracelet/crush/internal/config"
|
||||
"github.com/charmbracelet/crush/internal/csync"
|
||||
fur "github.com/charmbracelet/crush/internal/fur/provider"
|
||||
"github.com/charmbracelet/crush/internal/history"
|
||||
"github.com/charmbracelet/crush/internal/llm/prompt"
|
||||
|
||||
Reference in New Issue
Block a user