conn_test.go 2.65 KB
Newer Older
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
1
2
3
4
5
6
7
8
9
10
package conn

import (
	"bytes"
	"fmt"
	"runtime"
	"sync"
	"testing"
	"time"

11
	"context"
Jeromy's avatar
Jeromy committed
12
	msgio "github.com/jbenet/go-msgio"
13
	travis "github.com/libp2p/go-libp2p/testutil/ci/travis"
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
14
15
)

Jeromy's avatar
Jeromy committed
16
17
18
19
func msgioWrap(c Conn) msgio.ReadWriter {
	return msgio.NewReadWriter(c)
}

Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
20
func testOneSendRecv(t *testing.T, c1, c2 Conn) {
Jeromy's avatar
Jeromy committed
21
22
23
	mc1 := msgioWrap(c1)
	mc2 := msgioWrap(c2)

Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
24
25
	log.Debugf("testOneSendRecv from %s to %s", c1.LocalPeer(), c2.LocalPeer())
	m1 := []byte("hello")
Jeromy's avatar
Jeromy committed
26
	if err := mc1.WriteMsg(m1); err != nil {
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
27
28
		t.Fatal(err)
	}
Jeromy's avatar
Jeromy committed
29
	m2, err := mc2.ReadMsg()
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
30
31
32
33
34
35
36
37
38
	if err != nil {
		t.Fatal(err)
	}
	if !bytes.Equal(m1, m2) {
		t.Fatal("failed to send: %s %s", m1, m2)
	}
}

func testNotOneSendRecv(t *testing.T, c1, c2 Conn) {
Jeromy's avatar
Jeromy committed
39
40
41
	mc1 := msgioWrap(c1)
	mc2 := msgioWrap(c2)

Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
42
	m1 := []byte("hello")
Jeromy's avatar
Jeromy committed
43
	if err := mc1.WriteMsg(m1); err == nil {
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
44
45
		t.Fatal("write should have failed", err)
	}
Jeromy's avatar
Jeromy committed
46
	_, err := mc2.ReadMsg()
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
	if err == nil {
		t.Fatal("read should have failed", err)
	}
}

func TestClose(t *testing.T) {
	// t.Skip("Skipping in favor of another test")

	ctx, cancel := context.WithCancel(context.Background())
	defer cancel()
	c1, c2, _, _ := setupSingleConn(t, ctx)

	testOneSendRecv(t, c1, c2)
	testOneSendRecv(t, c2, c1)

	c1.Close()
	testNotOneSendRecv(t, c1, c2)

	c2.Close()
	testNotOneSendRecv(t, c2, c1)
	testNotOneSendRecv(t, c1, c2)
}

func TestCloseLeak(t *testing.T) {
	// t.Skip("Skipping in favor of another test")
	if testing.Short() {
		t.SkipNow()
	}

76
	if travis.IsRunning() {
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
77
78
79
80
81
82
83
84
85
		t.Skip("this doesn't work well on travis")
	}

	var wg sync.WaitGroup

	runPair := func(num int) {
		ctx, cancel := context.WithCancel(context.Background())
		c1, c2, _, _ := setupSingleConn(t, ctx)

Jeromy's avatar
Jeromy committed
86
87
88
		mc1 := msgioWrap(c1)
		mc2 := msgioWrap(c2)

Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
89
90
		for i := 0; i < num; i++ {
			b1 := []byte(fmt.Sprintf("beep%d", i))
Jeromy's avatar
Jeromy committed
91
92
			mc1.WriteMsg(b1)
			b2, err := mc2.ReadMsg()
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
93
94
95
96
97
98
99
100
			if err != nil {
				panic(err)
			}
			if !bytes.Equal(b1, b2) {
				panic(fmt.Errorf("bytes not equal: %s != %s", b1, b2))
			}

			b2 = []byte(fmt.Sprintf("boop%d", i))
Jeromy's avatar
Jeromy committed
101
102
			mc2.WriteMsg(b2)
			b1, err = mc1.ReadMsg()
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
			if err != nil {
				panic(err)
			}
			if !bytes.Equal(b1, b2) {
				panic(fmt.Errorf("bytes not equal: %s != %s", b1, b2))
			}

			<-time.After(time.Microsecond * 5)
		}

		c1.Close()
		c2.Close()
		cancel() // close the listener
		wg.Done()
	}

	var cons = 5
	var msgs = 50
	log.Debugf("Running %d connections * %d msgs.\n", cons, msgs)
	for i := 0; i < cons; i++ {
		wg.Add(1)
		go runPair(msgs)
	}

	log.Debugf("Waiting...\n")
	wg.Wait()
	// done!

Jeromy's avatar
Jeromy committed
131
132
133
134
135
136
	time.Sleep(time.Millisecond * 150)
	ngr := runtime.NumGoroutine()
	if ngr > 25 {
		// note, this is really innacurate
		//panic("uncomment me to debug")
		t.Fatal("leaking goroutines:", ngr)
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
137
138
	}
}