func TestConcurrentOne(t *testing.T) {
	runtime.GOMAXPROCS(4)
	rn := MakeNetwork()
	js := &JunkServer{}
	svc := MakeService(js)
	rs := MakeServer()
	rs.AddService(svc)
	rn.AddServer(1000, rs)
	e := rn.MakeEnd("c")
	rn.Connect("c", 1000)
	rn.Enable("c", true)
	ch := make(chan int)
	nrpcs := 20
	for ii := 0; ii < nrpcs; ii++ {
		go func(i int) {
			n := 0
			defer func() { ch <- n }()
			arg := 100 + i
			reply := ""
			e.Call("JunkServer.Handler2", arg, &reply)
			wanted := "handler2-" + strconv.Itoa(arg)
			if reply != wanted {
				t.Fatalf("wrong reply %v from Handler2, expecting %v\n",
					reply, wanted)
			}
			n += 1
		}(ii)
	}
	total := 0
	for ii := 0; ii < nrpcs; ii++ {
		x := <-ch
		total += x
	}
	if total != nrpcs {
		t.Fatalf("wrong number of RPCs completed, got %v, expected %v\n",
			total, nrpcs)
	}
	js.mu.Lock()
	defer js.mu.Unlock()
	if len(js.log2) != nrpcs {
		t.Fatal("wrong number of RPCs delivered")
	}
	n := rn.GetCount(1000)
	if n != total {
		t.Fatalf("wrong GetCount() %v, expected %v\n", n, total)
	}
}
test concurrent RPCs from a single ClientEnd
package labrpc
import "testing"
import "strconv"
import "sync"
import "runtime"
import "time"
import "fmt"
type JunkArgs struct {
	X int
}
type JunkReply struct {
	X string
}
type JunkServer struct {
	mu   sync.Mutex
	log1 []string
	log2 []int
}
func (js *JunkServer) Handler1(args string, reply *int) error {
	js.mu.Lock()
	defer js.mu.Unlock()
	js.log1 = append(js.log1, args)
	*reply, _ = strconv.Atoi(args)
	return nil
}
func (js *JunkServer) Handler2(args int, reply *string) error {
	js.mu.Lock()
	defer js.mu.Unlock()
	js.log2 = append(js.log2, args)
	*reply = "handler2-" + strconv.Itoa(args)
	return nil
}
func (js *JunkServer) Handler3(args int, reply *int) error {
	js.mu.Lock()
	defer js.mu.Unlock()
	time.Sleep(20 * time.Second)
	*reply = -args
	return nil
}
func (js *JunkServer) Handler4(args *JunkArgs, reply *JunkReply) error {
	reply.X = "pointer"
	return nil
}
func (js *JunkServer) Handler5(args JunkArgs, reply *JunkReply) error {
	reply.X = "no pointer"
	return nil
}
func TestBasic(t *testing.T) {
	runtime.GOMAXPROCS(4)
	rn := MakeNetwork()
	e := rn.MakeEnd("end1-99")
	js := &JunkServer{}
	svc := MakeService(js)
	rs := MakeServer()
	rs.AddService(svc)
	rn.AddServer("server99", rs)
	rn.Connect("end1-99", "server99")
	rn.Enable("end1-99", true)
	{
		reply := ""
		e.Call("JunkServer.Handler2", 111, &reply)
		if reply != "handler2-111" {
			t.Fatal("wrong reply from Handler2")
		}
	}
	{
		reply := 0
		e.Call("JunkServer.Handler1", "9099", &reply)
		if reply != 9099 {
			t.Fatal("wrong reply from Handler1")
		}
	}
}
func TestTypes(t *testing.T) {
	runtime.GOMAXPROCS(4)
	rn := MakeNetwork()
	e := rn.MakeEnd("end1-99")
	js := &JunkServer{}
	svc := MakeService(js)
	rs := MakeServer()
	rs.AddService(svc)
	rn.AddServer("server99", rs)
	rn.Connect("end1-99", "server99")
	rn.Enable("end1-99", true)
	{
		var args JunkArgs
		var reply JunkReply
		e.Call("JunkServer.Handler4", &args, &reply)
		if reply.X != "pointer" {
			t.Fatal("wrong reply from Handler4")
		}
	}
	{
		var args JunkArgs
		var reply JunkReply
		e.Call("JunkServer.Handler5", args, &reply)
		if reply.X != "no pointer" {
			t.Fatal("wrong reply from Handler5")
		}
	}
}
func TestDisconnect(t *testing.T) {
	runtime.GOMAXPROCS(4)
	rn := MakeNetwork()
	e := rn.MakeEnd("end1-99")
	js := &JunkServer{}
	svc := MakeService(js)
	rs := MakeServer()
	rs.AddService(svc)
	rn.AddServer("server99", rs)
	rn.Connect("end1-99", "server99")
	{
		reply := ""
		e.Call("JunkServer.Handler2", 111, &reply)
		if reply != "" {
			t.Fatal("unexpected reply from Handler2")
		}
	}
	rn.Enable("end1-99", true)
	{
		reply := 0
		e.Call("JunkServer.Handler1", "9099", &reply)
		if reply != 9099 {
			t.Fatal("wrong reply from Handler1")
		}
	}
}
func TestCounts(t *testing.T) {
	runtime.GOMAXPROCS(4)
	rn := MakeNetwork()
	e := rn.MakeEnd("end1-99")
	js := &JunkServer{}
	svc := MakeService(js)
	rs := MakeServer()
	rs.AddService(svc)
	rn.AddServer(99, rs)
	rn.Connect("end1-99", 99)
	rn.Enable("end1-99", true)
	for i := 0; i < 17; i++ {
		reply := ""
		e.Call("JunkServer.Handler2", i, &reply)
		wanted := "handler2-" + strconv.Itoa(i)
		if reply != wanted {
			t.Fatalf("wrong reply %v from Handler1, expecting %v\n", reply, wanted)
		}
	}
	n := rn.GetCount(99)
	if n != 17 {
		t.Fatalf("wrong GetCount() %v, expected 17\n", n)
	}
}
func TestConcurrentMany(t *testing.T) {
	runtime.GOMAXPROCS(4)
	rn := MakeNetwork()
	js := &JunkServer{}
	svc := MakeService(js)
	rs := MakeServer()
	rs.AddService(svc)
	rn.AddServer(1000, rs)
	ch := make(chan int)
	nclients := 20
	nrpcs := 10
	for ii := 0; ii < nclients; ii++ {
		go func(i int) {
			n := 0
			defer func() { ch <- n }()
			e := rn.MakeEnd(i)
			rn.Connect(i, 1000)
			rn.Enable(i, true)
			for j := 0; j < nrpcs; j++ {
				arg := i*100 + j
				reply := ""
				e.Call("JunkServer.Handler2", arg, &reply)
				wanted := "handler2-" + strconv.Itoa(arg)
				if reply != wanted {
					t.Fatalf("wrong reply %v from Handler1, expecting %v\n",
						reply, wanted)
				}
				n += 1
			}
		}(ii)
	}
	total := 0
	for ii := 0; ii < nclients; ii++ {
		x := <-ch
		total += x
	}
	if total != nclients*nrpcs {
		t.Fatalf("wrong number of RPCs completed, got %v, expected %v\n",
			total, nclients*nrpcs)
	}
	n := rn.GetCount(1000)
	if n != total {
		t.Fatalf("wrong GetCount() %v, expected %v\n", n, total)
	}
}
func TestUnreliable(t *testing.T) {
	runtime.GOMAXPROCS(4)
	rn := MakeNetwork()
	rn.Reliable(false)
	js := &JunkServer{}
	svc := MakeService(js)
	rs := MakeServer()
	rs.AddService(svc)
	rn.AddServer(1000, rs)
	ch := make(chan int)
	nclients := 300
	for ii := 0; ii < nclients; ii++ {
		go func(i int) {
			n := 0
			defer func() { ch <- n }()
			e := rn.MakeEnd(i)
			rn.Connect(i, 1000)
			rn.Enable(i, true)
			arg := i * 100
			reply := ""
			ok := e.Call("JunkServer.Handler2", arg, &reply)
			if ok {
				wanted := "handler2-" + strconv.Itoa(arg)
				if reply != wanted {
					t.Fatalf("wrong reply %v from Handler1, expecting %v\n",
						reply, wanted)
				}
				n += 1
			}
		}(ii)
	}
	total := 0
	for ii := 0; ii < nclients; ii++ {
		x := <-ch
		total += x
	}
	if total == nclients || total == 0 {
		t.Fatal("all RPCs succeeded despite unreliable")
	}
}