-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathclient_server_udp_test.go
More file actions
204 lines (185 loc) · 6.62 KB
/
client_server_udp_test.go
File metadata and controls
204 lines (185 loc) · 6.62 KB
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
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
package net
import (
"crypto/sha512"
"fmt"
"hash"
"io"
"net"
"strings"
"testing"
)
// Основная функция UDP сервера.
func testUdpHandler(udpServer net.PacketConn) (err error) {
const bufLen, errConnClosed = 1024*64 - 8, "use of closed network connection"
var (
buf []byte
addr net.Addr
n int
)
for {
buf = make([]byte, bufLen)
if n, addr, err = udpServer.ReadFrom(buf); err != nil {
if strings.Contains(err.Error(), errConnClosed) {
err = nil
break
}
continue
}
go testUdpIncoming(udpServer, addr, buf[:n])
}
return
}
// Функция обработки входящих UDP пакетов.
func testUdpIncoming(udpServer net.PacketConn, addr net.Addr, buf []byte) {
var (
err error
h hash.Hash
)
h = sha512.New()
_, err = h.Write(buf)
if _, err = udpServer.WriteTo([]byte(fmt.Sprintf("%x", h.Sum(nil))), addr); err != nil {
println(fmt.Sprintf("запись во входящее соединение прервана ошибкой: %s", err))
}
}
// Функция создаёт процесс клиента, ожидая запуска горутины, возвращает ожидаемый результат и канал с результатом.
func testUdpClient(nut Interface, onStart chan<- struct{}, t *testing.T) (
ret string,
rsp chan []byte,
) {
const (
bufLen = 1024*64 - 8
content = `Предвижу всё: вас оскорбит
Печальной тайны объясненье.
Какое горькое презренье
Ваш гордый взгляд изобразит!
Чего хочу? с какою целью
Открою душу вам свою?
Какому злобному веселью,
Быть может, повод подаю!
Случайно вас когда-то встретя,
В вас искру нежности заметя,
Я ей поверить не посмел:
Привычке милой не дал ходу;
Свою постылую свободу
Я потерять не захотел.
Ещё одно нас разлучило...
Несчастной жертвой Ленской пал...
Ото всего, что сердцу мило,
Тогда я сердце оторвал;
Чужой для всех, ничем не связан,
Я думал: вольность и покой
Замена счастью. Боже мой!
Как я ошибся, как наказан!
Нет, поминутно видеть вас,
Повсюду следовать за вами,
Улыбку уст, движенье глаз
Ловить влюблёнными глазами,
Внимать вам долго, понимать
Душой всё ваше совершенство,
Пред вами в муках замирать,
Бледнеть и гаснуть... вот блаженство!
И я лишён того: для вас
Тащусь повсюду наудачу;
Мне дорог день, мне дорог час:
А я в напрасной скуке трачу
Судьбой отсчитанные дни.
И так уж тягостны они.
Я знаю: век уж мой измерен;
Но чтоб продлилась жизнь моя,
Я утром должен быть уверен,
Что с вами днём увижусь я...
Боюсь: в мольбе моей смиренной
Увидит ваш суровый взор
Затеи хитрости презренной —
И слышу гневный ваш укор.
Когда б вы знали, как ужасно
Томиться жаждою любви,
Пылать — и разумом всечасно
Смирять волнение в крови;
Желать обнять у вас колени,
И, зарыдав, у ваших ног
Излить мольбы, признанья, пени,
Всё, всё, что выразить бы мог,
А между тем притворным хладом
Вооружать и речь и взор,
Вести спокойный разговор,
Глядеть на вас весёлым взглядом!..
Но так и быть: я сам себе
Противиться не в силах боле;
Всё решено: я в вашей воле,
И предаюсь моей судьбе.`
)
var h hash.Hash
rsp = make(chan []byte, 10)
h = sha512.New()
_, _ = h.Write([]byte(content))
ret = fmt.Sprintf("%x", h.Sum(nil))
go func(ch chan<- struct{}) {
var (
err error
addr *net.UDPAddr
conn *net.UDPConn
buf []byte
n int
)
onStart <- struct{}{}
if addr, err = net.ResolveUDPAddr("udp", "127.0.0.1:8001"); err != nil {
t.Errorf("функция ResolveUDPAddr(), ошибка: %v, ожидалось: %v", err, nil)
}
if conn, err = net.DialUDP("udp", nil, addr); err != nil {
t.Errorf("функция DialUDP(), ошибка: %v, ожидалось: %v", err, nil)
}
if n, err = io.WriteString(conn, content); err != nil {
t.Errorf("функция conn.Write(), ошибка: %v, ожидалось: %v", err, nil)
}
buf = make([]byte, bufLen)
if n, err = conn.Read(buf); n > 0 {
rsp <- buf[:n]
}
switch err {
case nil:
case io.EOF:
err = nil
default:
t.Errorf("чтение входящего пакета прервано ошибкой: %s", err)
}
if err = conn.Close(); err != nil {
t.Errorf("функция conn.Close(), ошибка: %v, ожидалось: %v", err, nil)
}
nut.Stop()
close(rsp)
}(onStart)
return
}
// Тестирование UDP клиента и сервера, с обменом данными.
func TestClientServerUdp(t *testing.T) {
var (
err error
nut Interface
onStart chan struct{}
data string
response chan []byte
buf []byte
)
nut = New().
HandlerUdp(testUdpHandler).
ListenAndServeWithConfig(&Configuration{
Host: "127.0.0.1",
Port: 8001,
Mode: "udp",
})
// Контролируемый запуск клиента.
onStart = make(chan struct{})
data, response = testUdpClient(nut, onStart, t)
safeWait(onStart)
// Ожидание завершения сервера.
if err = nut.Wait().
Error(); err != nil {
t.Errorf("функция Wait(), ошибка: %v, ожидалась: %v", err, nil)
}
// Чтение результата из буферизированного канала, в него поступит контрольная сумма полученных сервером данных.
buf = <-response
if !strings.EqualFold(data, string(buf)) {
t.Errorf("тестирование сеанса связи между сервером и клиентом завершилось провалом")
}
}