func TestDoneMax(t *testing.T) {
	now := time.Now().Second()
	runtime.GOMAXPROCS(4)
	fmt.Printf("Test: Paxos Max() after Done()s ...\n")
	const npaxos = 3
	var pxa []*Paxos = make([]*Paxos, npaxos)
	var pxh []string = make([]string, npaxos)
	defer cleanup(pxa)
	for i := 0; i < npaxos; i++ {
		pxh[i] = port("donemax", i)
	}
	for i := 0; i < npaxos; i++ {
		pxa[i] = Make(pxh, i, nil)
	}
	pxa[0].Start(0, "x")
	waitn(t, pxa, 0, npaxos)
	for i := 1; i <= 10; i++ {
		pxa[0].Start(i, "y")
		waitn(t, pxa, i, npaxos)
	}
	for i := 0; i < npaxos; i++ {
		pxa[i].Done(10)
	}
	for i := 0; i < npaxos; i++ {
		pxa[i].Start(10, "z")
	}
	time.Sleep(2 * time.Second)
	for i := 0; i < npaxos; i++ {
		mx := pxa[i].Max()
		if mx != 10 {
			t.Fatalf("Max() did not return correct result %d after calling Done(); returned %d", 10, mx)
		}
	}
	fmt.Printf("  ... Passed\n")
	fmt.Printf("diff = %d\n", time.Now().Second() - now)
}
does Max() work after Done()s?
package paxos
import "testing"
import "runtime"
import "strconv"
import "os"
import "time"
import "fmt"
import "math/rand"
import crand "crypto/rand"
import "encoding/base64"
import "sync/atomic"
func randstring(n int) string {
	b := make([]byte, 2*n)
	crand.Read(b)
	s := base64.URLEncoding.EncodeToString(b)
	return s[0:n]
}
func port(tag string, host int) string {
	s := "/var/tmp/824-"
	s += strconv.Itoa(os.Getuid()) + "/"
	os.Mkdir(s, 0777)
	s += "px-"
	s += strconv.Itoa(os.Getpid()) + "-"
	s += tag + "-"
	s += strconv.Itoa(host)
	return s
}
func ndecided(t *testing.T, pxa []*Paxos, seq int) int {
	count := 0
	var v interface{}
	for i := 0; i < len(pxa); i++ {
		if pxa[i] != nil {
			decided, v1 := pxa[i].Status(seq)
			if decided == Decided {
				if count > 0 && v != v1 {
					t.Fatalf("decided values do not match; seq=%v i=%v v=%v v1=%v",
						seq, i, v, v1)
				}
				count++
				v = v1
			}
		}
	}
	return count
}
func waitn(t *testing.T, pxa []*Paxos, seq int, wanted int) {
	to := 10 * time.Millisecond
	for iters := 0; iters < 30; iters++ {
		if ndecided(t, pxa, seq) >= wanted {
			break
		}
		time.Sleep(to)
		if to < time.Second {
			to *= 2
		}
	}
	nd := ndecided(t, pxa, seq)
	if nd < wanted {
		t.Fatalf("too few decided; seq=%v ndecided=%v wanted=%v", seq, nd, wanted)
	}
}
func waitmajority(t *testing.T, pxa []*Paxos, seq int) {
	waitn(t, pxa, seq, (len(pxa)/2)+1)
}
func checkmax(t *testing.T, pxa []*Paxos, seq int, max int) {
	time.Sleep(3 * time.Second)
	nd := ndecided(t, pxa, seq)
	if nd > max {
		t.Fatalf("too many decided; seq=%v ndecided=%v max=%v", seq, nd, max)
	}
}
func cleanup(pxa []*Paxos) {
	for i := 0; i < len(pxa); i++ {
		if pxa[i] != nil {
			pxa[i].Kill()
		}
	}
}
func noTestSpeed(t *testing.T) {
	runtime.GOMAXPROCS(4)
	const npaxos = 3
	var pxa []*Paxos = make([]*Paxos, npaxos)
	var pxh []string = make([]string, npaxos)
	defer cleanup(pxa)
	for i := 0; i < npaxos; i++ {
		pxh[i] = port("time", i)
	}
	for i := 0; i < npaxos; i++ {
		pxa[i] = Make(pxh, i, nil)
	}
	t0 := time.Now()
	for i := 0; i < 20; i++ {
		pxa[0].Start(i, "x")
		waitn(t, pxa, i, npaxos)
	}
	d := time.Since(t0)
	fmt.Printf("20 agreements %v seconds\n", d.Seconds())
}
func TestBasic(t *testing.T) {
	now := time.Now().Second()
	runtime.GOMAXPROCS(4)
	const npaxos = 3
	var pxa []*Paxos = make([]*Paxos, npaxos)
	var pxh []string = make([]string, npaxos)
	defer cleanup(pxa)
	for i := 0; i < npaxos; i++ {
		pxh[i] = port("basic", i)
	}
	for i := 0; i < npaxos; i++ {
		pxa[i] = Make(pxh, i, nil)
	}
	fmt.Printf("Test: Single proposer ...\n")
	pxa[0].Start(0, "hello")
	waitn(t, pxa, 0, npaxos)
	fmt.Printf("  ... Passed\n")
	fmt.Printf("Test: Many proposers, same value ...\n")
	for i := 0; i < npaxos; i++ {
		pxa[i].Start(1, 77)
	}
	waitn(t, pxa, 1, npaxos)
	fmt.Printf("  ... Passed\n")
	fmt.Printf("Test: Many proposers, different values ...\n")
	pxa[0].Start(2, 100)
	pxa[1].Start(2, 101)
	pxa[2].Start(2, 102)
	waitn(t, pxa, 2, npaxos)
	fmt.Printf("  ... Passed\n")
	fmt.Printf("Test: Out-of-order instances ...\n")
	pxa[0].Start(7, 700)
	pxa[0].Start(6, 600)
	pxa[1].Start(5, 500)
	waitn(t, pxa, 7, npaxos)
	pxa[0].Start(4, 400)
	pxa[1].Start(3, 300)
	waitn(t, pxa, 6, npaxos)
	waitn(t, pxa, 5, npaxos)
	waitn(t, pxa, 4, npaxos)
	waitn(t, pxa, 3, npaxos)
	if pxa[0].Max() != 7 {
		t.Fatalf("wrong Max()")
	}
	fmt.Printf("  ... Passed\n")
	fmt.Printf("diff = %d\n", time.Now().Second() - now)
}
func TestDeaf(t *testing.T) {
	now := time.Now().Second()
	runtime.GOMAXPROCS(4)
	const npaxos = 5
	var pxa []*Paxos = make([]*Paxos, npaxos)
	var pxh []string = make([]string, npaxos)
	defer cleanup(pxa)
	for i := 0; i < npaxos; i++ {
		pxh[i] = port("deaf", i)
	}
	for i := 0; i < npaxos; i++ {
		pxa[i] = Make(pxh, i, nil)
	}
	fmt.Printf("Test: Deaf proposer ...\n")
	pxa[0].Start(0, "hello")
	waitn(t, pxa, 0, npaxos)
	os.Remove(pxh[0])
	os.Remove(pxh[npaxos-1])
	pxa[1].Start(1, "goodbye")
	waitmajority(t, pxa, 1)
	time.Sleep(1 * time.Second)
	if ndecided(t, pxa, 1) != npaxos-2 {
		t.Fatalf("a deaf peer heard about a decision")
	}
	pxa[0].Start(1, "xxx")
	waitn(t, pxa, 1, npaxos-1)
	time.Sleep(1 * time.Second)
	if ndecided(t, pxa, 1) != npaxos-1 {
		t.Fatalf("a deaf peer heard about a decision")
	}
	pxa[npaxos-1].Start(1, "yyy")
	waitn(t, pxa, 1, npaxos)
	fmt.Printf("  ... Passed\n")
	fmt.Printf("diff = %d\n", time.Now().Second() - now)
}
func TestForget(t *testing.T) {
	now := time.Now().Second()
	runtime.GOMAXPROCS(4)
	const npaxos = 6
	var pxa []*Paxos = make([]*Paxos, npaxos)
	var pxh []string = make([]string, npaxos)
	defer cleanup(pxa)
	for i := 0; i < npaxos; i++ {
		pxh[i] = port("gc", i)
	}
	for i := 0; i < npaxos; i++ {
		pxa[i] = Make(pxh, i, nil)
	}
	fmt.Printf("Test: Forgetting ...\n")
	for i := 0; i < npaxos; i++ {
		m := pxa[i].Min()
		if m > 0 {
			t.Fatalf("wrong initial Min() %v", m)
		}
	}
	pxa[0].Start(0, "00")
	pxa[1].Start(1, "11")
	pxa[2].Start(2, "22")
	pxa[0].Start(6, "66")
	pxa[1].Start(7, "77")
	waitn(t, pxa, 0, npaxos)
	for i := 0; i < npaxos; i++ {
		m := pxa[i].Min()
		if m != 0 {
			t.Fatalf("wrong Min() %v; expected 0", m)
		}
	}
	waitn(t, pxa, 1, npaxos)
	for i := 0; i < npaxos; i++ {
		m := pxa[i].Min()
		if m != 0 {
			t.Fatalf("wrong Min() %v; expected 0", m)
		}
	}
	for i := 0; i < npaxos; i++ {
		pxa[i].Done(0)
	}
	for i := 1; i < npaxos; i++ {
		pxa[i].Done(1)
	}
	for i := 0; i < npaxos; i++ {
		pxa[i].Start(8+i, "xx")
	}
	allok := false
	for iters := 0; iters < 12; iters++ {
		allok = true
		for i := 0; i < npaxos; i++ {
			s := pxa[i].Min()
			if s != 1 {
				allok = false
			}
		}
		if allok {
			break
		}
		time.Sleep(1 * time.Second)
	}
	if allok != true {
		t.Fatalf("Min() did not advance after Done()")
	}
	fmt.Printf("  ... Passed\n")
	fmt.Printf("diff = %d\n", time.Now().Second() - now)
}
func TestManyForget(t *testing.T) {
	now := time.Now().Second()
	runtime.GOMAXPROCS(4)
	const npaxos = 3
	var pxa []*Paxos = make([]*Paxos, npaxos)
	var pxh []string = make([]string, npaxos)
	defer cleanup(pxa)
	for i := 0; i < npaxos; i++ {
		pxh[i] = port("manygc", i)
	}
	for i := 0; i < npaxos; i++ {
		pxa[i] = Make(pxh, i, nil)
		pxa[i].setunreliable(true)
	}
	fmt.Printf("Test: Lots of forgetting ...\n")
	const maxseq = 20
	go func() {
		na := rand.Perm(maxseq)
		for i := 0; i < len(na); i++ {
			seq := na[i]
			j := (rand.Int() % npaxos)
			v := rand.Int()
			pxa[j].Start(seq, v)
			runtime.Gosched()
		}
	}()
	done := make(chan bool)
	go func() {
		for {
			select {
			case <-done:
				return
			default:
			}
			seq := (rand.Int() % maxseq)
			i := (rand.Int() % npaxos)
			if seq >= pxa[i].Min() {
				decided, _ := pxa[i].Status(seq)
				if decided == Decided {
					pxa[i].Done(seq)
				}
			}
			runtime.Gosched()
		}
	}()
	time.Sleep(5 * time.Second)
	done <- true
	for i := 0; i < npaxos; i++ {
		pxa[i].setunreliable(false)
	}
	time.Sleep(2 * time.Second)
	for seq := 0; seq < maxseq; seq++ {
		for i := 0; i < npaxos; i++ {
			if seq >= pxa[i].Min() {
				pxa[i].Status(seq)
			}
		}
	}
	fmt.Printf("  ... Passed\n")
	fmt.Printf("diff = %d\n", time.Now().Second() - now)
}
func TestForgetMem(t *testing.T) {
	now := time.Now().Second()
	runtime.GOMAXPROCS(4)
	fmt.Printf("Test: Paxos frees forgotten instance memory ...\n")
	const npaxos = 3
	var pxa []*Paxos = make([]*Paxos, npaxos)
	var pxh []string = make([]string, npaxos)
	defer cleanup(pxa)
	for i := 0; i < npaxos; i++ {
		pxh[i] = port("gcmem", i)
	}
	for i := 0; i < npaxos; i++ {
		pxa[i] = Make(pxh, i, nil)
	}
	pxa[0].Start(0, "x")
	waitn(t, pxa, 0, npaxos)
	runtime.GC()
	var m0 runtime.MemStats
	runtime.ReadMemStats(&m0)
	for i := 1; i <= 10; i++ {
		big := make([]byte, 1000000)
		for j := 0; j < len(big); j++ {
			big[j] = byte('a' + rand.Int()%26)
		}
		pxa[0].Start(i, string(big))
		waitn(t, pxa, i, npaxos)
	}
	runtime.GC()
	var m1 runtime.MemStats
	runtime.ReadMemStats(&m1)
	for i := 0; i < npaxos; i++ {
		pxa[i].Done(10)
	}
	for i := 0; i < npaxos; i++ {
		pxa[i].Start(11+i, "z")
	}
	time.Sleep(3 * time.Second)
	for i := 0; i < npaxos; i++ {
		if pxa[i].Min() != 11 {
			t.Fatalf("expected Min() %v, got %v\n", 11, pxa[i].Min())
		}
	}
	runtime.GC()
	var m2 runtime.MemStats
	runtime.ReadMemStats(&m2)
	if m2.Alloc > (m1.Alloc / 2) {
		t.Fatalf("memory use did not shrink enough")
	}
	again := make([]string, 10)
	for seq := 0; seq < npaxos && seq < 10; seq++ {
		again[seq] = randstring(20)
		for i := 0; i < npaxos; i++ {
			fate, _ := pxa[i].Status(seq)
			if fate != Forgotten {
				t.Fatalf("seq %d < Min() %d but not Forgotten", seq, pxa[i].Min())
			}
			pxa[i].Start(seq, again[seq])
		}
	}
	time.Sleep(1 * time.Second)
	for seq := 0; seq < npaxos && seq < 10; seq++ {
		for i := 0; i < npaxos; i++ {
			fate, v := pxa[i].Status(seq)
			if fate != Forgotten || v == again[seq] {
				t.Fatalf("seq %d < Min() %d but not Forgotten", seq, pxa[i].Min())
			}
		}
	}
	fmt.Printf("  ... Passed\n")
	fmt.Printf("diff = %d\n", time.Now().Second() - now)
}