// 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; for p := range r.Iter() { 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 sum(r *Ring) int { s := 0; for p := range r.Iter() { s += p.(int) } return s; } 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 < 100; 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); } } }