-
Notifications
You must be signed in to change notification settings - Fork 0
/
server_test.go
159 lines (132 loc) · 3.46 KB
/
server_test.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
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
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
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
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
package main
import (
"testing"
"context"
"net"
"bufio"
)
const addr = ":9090"
const message = "sup?"
//This test shows Run terminates when the context is cancelled.
func TestRun(t *testing.T) {
//iterating ensures we are releasing all the resources we are using
//to prevent other tests from failing
//and increases the chance to find race conditions
for i := 0; i < 5; i++ {
ready := make(chan struct{})
ctx, cancel := context.WithCancel(context.Background())
finished := make(chan struct{})
go func() {
Run(addr, ready, ctx)
close(finished)
}()
<-ready //try removing this line
conn, err := net.Dial("tcp", addr)
if err != nil {
//cleanup resources to not affect other tests
cancel()
<-finished
t.Fatal(err)
}
//write a message
if _, err := conn.Write([]byte(message + "\n")); err != nil {
t.Error(err)
}
//get your message back
s, err := bufio.NewReader(conn).ReadString('\n')
if err != nil {
t.Error(err)
}
if s != message+"\n" {
t.Errorf("Expected '%s' but received '%s'", message, s)
}
conn.Close()
cancel()
<-finished
}
}
//This test shows Serve terminates when the context is cancelled.
func TestServe(t *testing.T) {
//iterating ensures we are releasing all the resources we are using
//and increases the chance to find race conditions
for i := 0; i < 5; i++ {
l, err := net.Listen("tcp", addr)
if err != nil {
t.Fatal(err)
}
ctx, cancel := context.WithCancel(context.Background())
finished := make(chan struct{})
ready := make(chan struct{})
handler := func(conn net.Conn, ctx context.Context) {
close(ready)
conn.Write([]byte(message + "\n"))
<-ctx.Done() //block until cancel() to ensure it is called within the test
}
go func() {
Serve(l, ctx, handler)
close(finished)
}()
conn, err := net.Dial("tcp", addr)
if err != nil {
t.Fatal(err)
}
<-ready //try removing this line
//ready is closed when the connection handler function is invoked
//it is then safe to close the listener
l.Close()
s, err := bufio.NewReader(conn).ReadString('\n')
if s != message+"\n" {
t.Fatalf("Expected '%s' but received '%s'", message, s)
}
cancel()
conn.Close()
//finished signals that all resources were released
//it is safe it run as many iterations as we like
<-finished
}
}
//This test shows PersistAndEcho writes the client's messages to the given channel
//echos the messages back to the client and exists when the context is cancelled.
func TestPersistAndEcho(t *testing.T) {
//for i:=0; i<100; i++ {
// func() { // test is full of defers
l, err := net.Listen("tcp", addr)
if err != nil {
t.Fatal(err)
}
defer l.Close()
cliConn, err := net.Dial("tcp", addr)
if err != nil {
t.Fatal()
}
defer cliConn.Close()
servConn, err := l.Accept()
if err != nil {
t.Fatal()
}
defer servConn.Close()
mCh := make(chan []byte)
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
finished := make(chan struct{})
go func() {
PersistAndEcho(mCh, servConn, ctx)
close(mCh)
close(finished)
}()
cliConn.Write([]byte(message + "\n"))
m := <-mCh //check message was persisted to the message channel mCh
if string(m) != message {
t.Fatalf("Expected '%s' but received '%s'", message, string(m))
}
s, err := bufio.NewReader(cliConn).ReadString('\n')
if s != message+"\n" {
t.Fatalf("Expected '%s' but received '%s'", message, s)
}
cliConn.Write([]byte("message with no delimiter"))
cancel()
<-mCh
<-finished
// }()
//}
}