// Copyright 2009 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. package ring import ( "fmt" "testing" ) // For debugging - keep around. func dump(r *Ring) { if r == nil { fmt.Println("empty") return } i, n := 0, r.Len() for p := r; i < n; p = p.next { fmt.Printf("%4d: %p = {<- %p | %p ->}\n", i, p, p.prev, p.next) i++ } fmt.Println() } func verify(t *testing.T, r *Ring, N int, sum int) { // Len n := r.Len() if n != N { t.Errorf("r.Len() == %d; expected %d", n, N) } // iteration n = 0 s := 0 r.Do(func(p any) { n++ if p != nil { s += p.(int) } }) if n != N { t.Errorf("number of forward iterations == %d; expected %d", n, N) } if sum >= 0 && s != sum { t.Errorf("forward ring sum = %d; expected %d", s, sum) } if r == nil { return } // connections if r.next != nil { var p *Ring // previous element for q := r; p == nil || q != r; q = q.next { if p != nil && p != q.prev { t.Errorf("prev = %p, expected q.prev = %p\n", p, q.prev) } p = q } if p != r.prev { t.Errorf("prev = %p, expected r.prev = %p\n", p, r.prev) } } // Next, Prev if r.Next() != r.next { t.Errorf("r.Next() != r.next") } if r.Prev() != r.prev { t.Errorf("r.Prev() != r.prev") } // Move if r.Move(0) != r { t.Errorf("r.Move(0) != r") } if r.Move(N) != r { t.Errorf("r.Move(%d) != r", N) } if r.Move(-N) != r { t.Errorf("r.Move(%d) != r", -N) } for i := 0; i < 10; i++ { ni := N + i mi := ni % N if r.Move(ni) != r.Move(mi) { t.Errorf("r.Move(%d) != r.Move(%d)", ni, mi) } if r.Move(-ni) != r.Move(-mi) { t.Errorf("r.Move(%d) != r.Move(%d)", -ni, -mi) } } } func TestCornerCases(t *testing.T) { var ( r0 *Ring r1 Ring ) // Basics verify(t, r0, 0, 0) verify(t, &r1, 1, 0) // Insert r1.Link(r0) verify(t, r0, 0, 0) verify(t, &r1, 1, 0) // Insert r1.Link(r0) verify(t, r0, 0, 0) verify(t, &r1, 1, 0) // Unlink r1.Unlink(0) verify(t, &r1, 1, 0) } func makeN(n int) *Ring { r := New(n) for i := 1; i <= n; i++ { r.Value = i r = r.Next() } return r } func sumN(n int) int { return (n*n + n) / 2 } func TestNew(t *testing.T) { for i := 0; i < 10; i++ { r := New(i) verify(t, r, i, -1) } for i := 0; i < 10; i++ { r := makeN(i) verify(t, r, i, sumN(i)) } } func TestLink1(t *testing.T) { r1a := makeN(1) var r1b Ring r2a := r1a.Link(&r1b) verify(t, r2a, 2, 1) if r2a != r1a { t.Errorf("a) 2-element link failed") } r2b := r2a.Link(r2a.Next()) verify(t, r2b, 2, 1) if r2b != r2a.Next() { t.Errorf("b) 2-element link failed") } r1c := r2b.Link(r2b) verify(t, r1c, 1, 1) verify(t, r2b, 1, 0) } func TestLink2(t *testing.T) { var r0 *Ring r1a := &Ring{Value: 42} r1b := &Ring{Value: 77} r10 := makeN(10) r1a.Link(r0) verify(t, r1a, 1, 42) r1a.Link(r1b) verify(t, r1a, 2, 42+77) r10.Link(r0) verify(t, r10, 10, sumN(10)) r10.Link(r1a) verify(t, r10, 12, sumN(10)+42+77) } func TestLink3(t *testing.T) { var r Ring n := 1 for i := 1; i < 10; i++ { n += i verify(t, r.Link(New(i)), n, -1) } } func TestUnlink(t *testing.T) { r10 := makeN(10) s10 := r10.Move(6) sum10 := sumN(10) verify(t, r10, 10, sum10) verify(t, s10, 10, sum10) r0 := r10.Unlink(0) verify(t, r0, 0, 0) r1 := r10.Unlink(1) verify(t, r1, 1, 2) verify(t, r10, 9, sum10-2) r9 := r10.Unlink(9) verify(t, r9, 9, sum10-2) verify(t, r10, 9, sum10-2) } func TestLinkUnlink(t *testing.T) { for i := 1; i < 4; i++ { ri := New(i) for j := 0; j < i; j++ { rj := ri.Unlink(j) verify(t, rj, j, -1) verify(t, ri, i-j, -1) ri.Link(rj) verify(t, ri, i, -1) } } } // Test that calling Move() on an empty Ring initializes it. func TestMoveEmptyRing(t *testing.T) { var r Ring r.Move(1) verify(t, &r, 1, 0) }