@@ -1,11 +1,13 @@
11package csync
22
33import (
4+ "sync"
45 "sync/atomic"
56 "testing"
67 "time"
78
89 "github.com/stretchr/testify/assert"
10+ "github.com/stretchr/testify/require"
911)
1012
1113func TestLazySlice_Seq(t *testing.T) {
@@ -85,3 +87,210 @@ func TestLazySlice_EarlyBreak(t *testing.T) {
8587
8688 assert.Equal(t, []string{"a", "b"}, result)
8789}
90+
91+func TestSlice(t *testing.T) {
92+ t.Run("NewSlice", func(t *testing.T) {
93+ s := NewSlice[int]()
94+ assert.Equal(t, 0, s.Len())
95+ })
96+
97+ t.Run("NewSliceFrom", func(t *testing.T) {
98+ original := []int{1, 2, 3}
99+ s := NewSliceFrom(original)
100+ assert.Equal(t, 3, s.Len())
101+
102+ // Verify it's a copy, not a reference
103+ original[0] = 999
104+ val, ok := s.Get(0)
105+ require.True(t, ok)
106+ assert.Equal(t, 1, val)
107+ })
108+
109+ t.Run("Append", func(t *testing.T) {
110+ s := NewSlice[string]()
111+ s.Append("hello")
112+ s.Append("world")
113+
114+ assert.Equal(t, 2, s.Len())
115+ val, ok := s.Get(0)
116+ require.True(t, ok)
117+ assert.Equal(t, "hello", val)
118+
119+ val, ok = s.Get(1)
120+ require.True(t, ok)
121+ assert.Equal(t, "world", val)
122+ })
123+
124+ t.Run("Prepend", func(t *testing.T) {
125+ s := NewSlice[string]()
126+ s.Append("world")
127+ s.Prepend("hello")
128+
129+ assert.Equal(t, 2, s.Len())
130+ val, ok := s.Get(0)
131+ require.True(t, ok)
132+ assert.Equal(t, "hello", val)
133+
134+ val, ok = s.Get(1)
135+ require.True(t, ok)
136+ assert.Equal(t, "world", val)
137+ })
138+
139+ t.Run("Delete", func(t *testing.T) {
140+ s := NewSliceFrom([]int{1, 2, 3, 4, 5})
141+
142+ // Delete middle element
143+ ok := s.Delete(2)
144+ assert.True(t, ok)
145+ assert.Equal(t, 4, s.Len())
146+
147+ expected := []int{1, 2, 4, 5}
148+ actual := s.Slice()
149+ assert.Equal(t, expected, actual)
150+
151+ // Delete out of bounds
152+ ok = s.Delete(10)
153+ assert.False(t, ok)
154+ assert.Equal(t, 4, s.Len())
155+
156+ // Delete negative index
157+ ok = s.Delete(-1)
158+ assert.False(t, ok)
159+ assert.Equal(t, 4, s.Len())
160+ })
161+
162+ t.Run("Get", func(t *testing.T) {
163+ s := NewSliceFrom([]string{"a", "b", "c"})
164+
165+ val, ok := s.Get(1)
166+ require.True(t, ok)
167+ assert.Equal(t, "b", val)
168+
169+ // Out of bounds
170+ _, ok = s.Get(10)
171+ assert.False(t, ok)
172+
173+ // Negative index
174+ _, ok = s.Get(-1)
175+ assert.False(t, ok)
176+ })
177+
178+ t.Run("Set", func(t *testing.T) {
179+ s := NewSliceFrom([]string{"a", "b", "c"})
180+
181+ ok := s.Set(1, "modified")
182+ assert.True(t, ok)
183+
184+ val, ok := s.Get(1)
185+ require.True(t, ok)
186+ assert.Equal(t, "modified", val)
187+
188+ // Out of bounds
189+ ok = s.Set(10, "invalid")
190+ assert.False(t, ok)
191+
192+ // Negative index
193+ ok = s.Set(-1, "invalid")
194+ assert.False(t, ok)
195+ })
196+
197+ t.Run("SetSlice", func(t *testing.T) {
198+ s := NewSlice[int]()
199+ s.Append(1)
200+ s.Append(2)
201+
202+ newItems := []int{10, 20, 30}
203+ s.SetSlice(newItems)
204+
205+ assert.Equal(t, 3, s.Len())
206+ assert.Equal(t, newItems, s.Slice())
207+
208+ // Verify it's a copy
209+ newItems[0] = 999
210+ val, ok := s.Get(0)
211+ require.True(t, ok)
212+ assert.Equal(t, 10, val)
213+ })
214+
215+ t.Run("Clear", func(t *testing.T) {
216+ s := NewSliceFrom([]int{1, 2, 3})
217+ assert.Equal(t, 3, s.Len())
218+
219+ s.Clear()
220+ assert.Equal(t, 0, s.Len())
221+ })
222+
223+ t.Run("Slice", func(t *testing.T) {
224+ original := []int{1, 2, 3}
225+ s := NewSliceFrom(original)
226+
227+ copy := s.Slice()
228+ assert.Equal(t, original, copy)
229+
230+ // Verify it's a copy
231+ copy[0] = 999
232+ val, ok := s.Get(0)
233+ require.True(t, ok)
234+ assert.Equal(t, 1, val)
235+ })
236+
237+ t.Run("Seq", func(t *testing.T) {
238+ s := NewSliceFrom([]int{1, 2, 3})
239+
240+ var result []int
241+ for v := range s.Seq() {
242+ result = append(result, v)
243+ }
244+
245+ assert.Equal(t, []int{1, 2, 3}, result)
246+ })
247+
248+ t.Run("SeqWithIndex", func(t *testing.T) {
249+ s := NewSliceFrom([]string{"a", "b", "c"})
250+
251+ var indices []int
252+ var values []string
253+ for i, v := range s.Seq2() {
254+ indices = append(indices, i)
255+ values = append(values, v)
256+ }
257+
258+ assert.Equal(t, []int{0, 1, 2}, indices)
259+ assert.Equal(t, []string{"a", "b", "c"}, values)
260+ })
261+
262+ t.Run("ConcurrentAccess", func(t *testing.T) {
263+ s := NewSlice[int]()
264+ const numGoroutines = 100
265+ const itemsPerGoroutine = 10
266+
267+ var wg sync.WaitGroup
268+
269+ // Concurrent appends
270+ for i := 0; i < numGoroutines; i++ {
271+ wg.Add(1)
272+ go func(start int) {
273+ defer wg.Done()
274+ for j := 0; j < itemsPerGoroutine; j++ {
275+ s.Append(start*itemsPerGoroutine + j)
276+ }
277+ }(i)
278+ }
279+
280+ // Concurrent reads
281+ for i := 0; i < numGoroutines; i++ {
282+ wg.Add(1)
283+ go func() {
284+ defer wg.Done()
285+ for j := 0; j < itemsPerGoroutine; j++ {
286+ s.Len() // Just read the length
287+ }
288+ }()
289+ }
290+
291+ wg.Wait()
292+
293+ // Should have all items
294+ assert.Equal(t, numGoroutines*itemsPerGoroutine, s.Len())
295+ })
296+}