package dataext import ( "errors" "sync" "testing" ) func TestStack_PushPop(t *testing.T) { s := NewStack[int](false, 4) s.Push(1) s.Push(2) s.Push(3) if s.Length() != 3 { t.Fatalf("Length=%d", s.Length()) } if s.Empty() { t.Fatal("should not be empty") } v, err := s.Pop() if err != nil || v != 3 { t.Fatalf("Pop got (%d,%v)", v, err) } v, err = s.Pop() if err != nil || v != 2 { t.Fatalf("Pop got (%d,%v)", v, err) } v, err = s.Pop() if err != nil || v != 1 { t.Fatalf("Pop got (%d,%v)", v, err) } } func TestStack_PopEmpty(t *testing.T) { s := NewStack[int](false, 0) _, err := s.Pop() if !errors.Is(err, ErrEmptyStack) { t.Fatalf("expected ErrEmptyStack, got %v", err) } if !s.Empty() { t.Fatal("should be empty") } } func TestStack_Peek(t *testing.T) { s := NewStack[string](false, 0) if _, err := s.Peek(); !errors.Is(err, ErrEmptyStack) { t.Fatalf("expected ErrEmptyStack got %v", err) } s.Push("a") s.Push("b") v, err := s.Peek() if err != nil || v != "b" { t.Fatalf("Peek got (%q,%v)", v, err) } if s.Length() != 2 { t.Fatal("Peek must not pop") } } func TestStack_OptPopOptPeek(t *testing.T) { s := NewStack[int](false, 0) if s.OptPop() != nil { t.Fatal("OptPop on empty should return nil") } if s.OptPeek() != nil { t.Fatal("OptPeek on empty should return nil") } s.Push(7) if p := s.OptPeek(); p == nil || *p != 7 { t.Fatalf("OptPeek bad") } if p := s.OptPop(); p == nil || *p != 7 { t.Fatalf("OptPop bad") } if !s.Empty() { t.Fatal("should be empty after OptPop") } } func TestStack_ThreadSafe(t *testing.T) { s := NewStack[int](true, 0) var wg sync.WaitGroup const n = 200 wg.Add(n) for i := 0; i < n; i++ { go func(v int) { defer wg.Done() s.Push(v) }(i) } wg.Wait() if s.Length() != n { t.Fatalf("Length=%d want %d", s.Length(), n) } }