You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

354 lines
10 KiB

  1. /*
  2. *
  3. * Copyright 2017 gRPC authors.
  4. *
  5. * Licensed under the Apache License, Version 2.0 (the "License");
  6. * you may not use this file except in compliance with the License.
  7. * You may obtain a copy of the License at
  8. *
  9. * http://www.apache.org/licenses/LICENSE-2.0
  10. *
  11. * Unless required by applicable law or agreed to in writing, software
  12. * distributed under the License is distributed on an "AS IS" BASIS,
  13. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  14. * See the License for the specific language governing permissions and
  15. * limitations under the License.
  16. *
  17. */
  18. package latency
  19. import (
  20. "bytes"
  21. "fmt"
  22. "net"
  23. "reflect"
  24. "sync"
  25. "testing"
  26. "time"
  27. )
  28. // bufConn is a net.Conn implemented by a bytes.Buffer (which is a ReadWriter).
  29. type bufConn struct {
  30. *bytes.Buffer
  31. }
  32. func (bufConn) Close() error { panic("unimplemented") }
  33. func (bufConn) LocalAddr() net.Addr { panic("unimplemented") }
  34. func (bufConn) RemoteAddr() net.Addr { panic("unimplemented") }
  35. func (bufConn) SetDeadline(t time.Time) error { panic("unimplemneted") }
  36. func (bufConn) SetReadDeadline(t time.Time) error { panic("unimplemneted") }
  37. func (bufConn) SetWriteDeadline(t time.Time) error { panic("unimplemneted") }
  38. func restoreHooks() func() {
  39. s := sleep
  40. n := now
  41. return func() {
  42. sleep = s
  43. now = n
  44. }
  45. }
  46. func TestConn(t *testing.T) {
  47. defer restoreHooks()()
  48. // Constant time.
  49. now = func() time.Time { return time.Unix(123, 456) }
  50. // Capture sleep times for checking later.
  51. var sleepTimes []time.Duration
  52. sleep = func(t time.Duration) { sleepTimes = append(sleepTimes, t) }
  53. wantSleeps := func(want ...time.Duration) {
  54. if !reflect.DeepEqual(want, sleepTimes) {
  55. t.Fatalf("sleepTimes = %v; want %v", sleepTimes, want)
  56. }
  57. sleepTimes = nil
  58. }
  59. // Use a fairly high latency to cause a large BDP and avoid sleeps while
  60. // writing due to simulation of full buffers.
  61. latency := 1 * time.Second
  62. c, err := (&Network{Kbps: 1, Latency: latency, MTU: 5}).Conn(bufConn{&bytes.Buffer{}})
  63. if err != nil {
  64. t.Fatalf("Unexpected error creating connection: %v", err)
  65. }
  66. wantSleeps(latency) // Connection creation delay.
  67. // 1 kbps = 128 Bps. Divides evenly by 1 second using nanos.
  68. byteLatency := time.Duration(time.Second / 128)
  69. write := func(b []byte) {
  70. n, err := c.Write(b)
  71. if n != len(b) || err != nil {
  72. t.Fatalf("c.Write(%v) = %v, %v; want %v, nil", b, n, err, len(b))
  73. }
  74. }
  75. write([]byte{1, 2, 3, 4, 5}) // One full packet
  76. pkt1Time := latency + byteLatency*5
  77. write([]byte{6}) // One partial packet
  78. pkt2Time := pkt1Time + byteLatency
  79. write([]byte{7, 8, 9, 10, 11, 12, 13}) // Two packets
  80. pkt3Time := pkt2Time + byteLatency*5
  81. pkt4Time := pkt3Time + byteLatency*2
  82. // No reads, so no sleeps yet.
  83. wantSleeps()
  84. read := func(n int, want []byte) {
  85. b := make([]byte, n)
  86. if rd, err := c.Read(b); err != nil || rd != len(want) {
  87. t.Fatalf("c.Read(<%v bytes>) = %v, %v; want %v, nil", n, rd, err, len(want))
  88. }
  89. if !reflect.DeepEqual(b[:len(want)], want) {
  90. t.Fatalf("read %v; want %v", b, want)
  91. }
  92. }
  93. read(1, []byte{1})
  94. wantSleeps(pkt1Time)
  95. read(1, []byte{2})
  96. wantSleeps()
  97. read(3, []byte{3, 4, 5})
  98. wantSleeps()
  99. read(2, []byte{6})
  100. wantSleeps(pkt2Time)
  101. read(2, []byte{7, 8})
  102. wantSleeps(pkt3Time)
  103. read(10, []byte{9, 10, 11})
  104. wantSleeps()
  105. read(10, []byte{12, 13})
  106. wantSleeps(pkt4Time)
  107. }
  108. func TestSync(t *testing.T) {
  109. defer restoreHooks()()
  110. // Infinitely fast CPU: time doesn't pass unless sleep is called.
  111. tn := time.Unix(123, 0)
  112. now = func() time.Time { return tn }
  113. sleep = func(d time.Duration) { tn = tn.Add(d) }
  114. // Simulate a 20ms latency network, then run sync across that and expect to
  115. // measure 20ms latency, or 10ms additional delay for a 30ms network.
  116. slowConn, err := (&Network{Kbps: 0, Latency: 20 * time.Millisecond, MTU: 5}).Conn(bufConn{&bytes.Buffer{}})
  117. if err != nil {
  118. t.Fatalf("Unexpected error creating connection: %v", err)
  119. }
  120. c, err := (&Network{Latency: 30 * time.Millisecond}).Conn(slowConn)
  121. if err != nil {
  122. t.Fatalf("Unexpected error creating connection: %v", err)
  123. }
  124. if c.(*conn).delay != 10*time.Millisecond {
  125. t.Fatalf("c.delay = %v; want 10ms", c.(*conn).delay)
  126. }
  127. }
  128. func TestSyncTooSlow(t *testing.T) {
  129. defer restoreHooks()()
  130. // Infinitely fast CPU: time doesn't pass unless sleep is called.
  131. tn := time.Unix(123, 0)
  132. now = func() time.Time { return tn }
  133. sleep = func(d time.Duration) { tn = tn.Add(d) }
  134. // Simulate a 10ms latency network, then attempt to simulate a 5ms latency
  135. // network and expect an error.
  136. slowConn, err := (&Network{Kbps: 0, Latency: 10 * time.Millisecond, MTU: 5}).Conn(bufConn{&bytes.Buffer{}})
  137. if err != nil {
  138. t.Fatalf("Unexpected error creating connection: %v", err)
  139. }
  140. errWant := "measured network latency (10ms) higher than desired latency (5ms)"
  141. if _, err := (&Network{Latency: 5 * time.Millisecond}).Conn(slowConn); err == nil || err.Error() != errWant {
  142. t.Fatalf("Conn() = _, %q; want _, %q", err, errWant)
  143. }
  144. }
  145. func TestListenerAndDialer(t *testing.T) {
  146. defer restoreHooks()()
  147. tn := time.Unix(123, 0)
  148. startTime := tn
  149. mu := &sync.Mutex{}
  150. now = func() time.Time {
  151. mu.Lock()
  152. defer mu.Unlock()
  153. return tn
  154. }
  155. // Use a fairly high latency to cause a large BDP and avoid sleeps while
  156. // writing due to simulation of full buffers.
  157. n := &Network{Kbps: 2, Latency: 1 * time.Second, MTU: 10}
  158. // 2 kbps = .25 kBps = 256 Bps
  159. byteLatency := func(n int) time.Duration {
  160. return time.Duration(n) * time.Second / 256
  161. }
  162. // Create a real listener and wrap it.
  163. l, err := net.Listen("tcp", "localhost:0")
  164. if err != nil {
  165. t.Fatalf("Unexpected error creating listener: %v", err)
  166. }
  167. defer l.Close()
  168. l = n.Listener(l)
  169. var serverConn net.Conn
  170. var scErr error
  171. scDone := make(chan struct{})
  172. go func() {
  173. serverConn, scErr = l.Accept()
  174. close(scDone)
  175. }()
  176. // Create a dialer and use it.
  177. clientConn, err := n.TimeoutDialer(net.DialTimeout)("tcp", l.Addr().String(), 2*time.Second)
  178. if err != nil {
  179. t.Fatalf("Unexpected error dialing: %v", err)
  180. }
  181. defer clientConn.Close()
  182. // Block until server's Conn is available.
  183. <-scDone
  184. if scErr != nil {
  185. t.Fatalf("Unexpected error listening: %v", scErr)
  186. }
  187. defer serverConn.Close()
  188. // sleep (only) advances tn. Done after connections established so sync detects zero delay.
  189. sleep = func(d time.Duration) {
  190. mu.Lock()
  191. defer mu.Unlock()
  192. if d > 0 {
  193. tn = tn.Add(d)
  194. }
  195. }
  196. seq := func(a, b int) []byte {
  197. buf := make([]byte, b-a)
  198. for i := 0; i < b-a; i++ {
  199. buf[i] = byte(i + a)
  200. }
  201. return buf
  202. }
  203. pkt1 := seq(0, 10)
  204. pkt2 := seq(10, 30)
  205. pkt3 := seq(30, 35)
  206. write := func(c net.Conn, b []byte) {
  207. n, err := c.Write(b)
  208. if n != len(b) || err != nil {
  209. t.Fatalf("c.Write(%v) = %v, %v; want %v, nil", b, n, err, len(b))
  210. }
  211. }
  212. write(serverConn, pkt1)
  213. write(serverConn, pkt2)
  214. write(serverConn, pkt3)
  215. write(clientConn, pkt3)
  216. write(clientConn, pkt1)
  217. write(clientConn, pkt2)
  218. if tn != startTime {
  219. t.Fatalf("unexpected sleep in write; tn = %v; want %v", tn, startTime)
  220. }
  221. read := func(c net.Conn, n int, want []byte, timeWant time.Time) {
  222. b := make([]byte, n)
  223. if rd, err := c.Read(b); err != nil || rd != len(want) {
  224. t.Fatalf("c.Read(<%v bytes>) = %v, %v; want %v, nil (read: %v)", n, rd, err, len(want), b[:rd])
  225. }
  226. if !reflect.DeepEqual(b[:len(want)], want) {
  227. t.Fatalf("read %v; want %v", b, want)
  228. }
  229. if !tn.Equal(timeWant) {
  230. t.Errorf("tn after read(%v) = %v; want %v", want, tn, timeWant)
  231. }
  232. }
  233. read(clientConn, len(pkt1)+1, pkt1, startTime.Add(n.Latency+byteLatency(len(pkt1))))
  234. read(serverConn, len(pkt3)+1, pkt3, tn) // tn was advanced by the above read; pkt3 is shorter than pkt1
  235. read(clientConn, len(pkt2), pkt2[:10], startTime.Add(n.Latency+byteLatency(len(pkt1)+10)))
  236. read(clientConn, len(pkt2), pkt2[10:], startTime.Add(n.Latency+byteLatency(len(pkt1)+len(pkt2))))
  237. read(clientConn, len(pkt3), pkt3, startTime.Add(n.Latency+byteLatency(len(pkt1)+len(pkt2)+len(pkt3))))
  238. read(serverConn, len(pkt1), pkt1, tn) // tn already past the arrival time due to prior reads
  239. read(serverConn, len(pkt2), pkt2[:10], tn)
  240. read(serverConn, len(pkt2), pkt2[10:], tn)
  241. // Sleep awhile and make sure the read happens disregarding previous writes
  242. // (lastSendEnd handling).
  243. sleep(10 * time.Second)
  244. write(clientConn, pkt1)
  245. read(serverConn, len(pkt1), pkt1, tn.Add(n.Latency+byteLatency(len(pkt1))))
  246. // Send, sleep longer than the network delay, then make sure the read happens
  247. // instantly.
  248. write(serverConn, pkt1)
  249. sleep(10 * time.Second)
  250. read(clientConn, len(pkt1), pkt1, tn)
  251. }
  252. func TestBufferBloat(t *testing.T) {
  253. defer restoreHooks()()
  254. // Infinitely fast CPU: time doesn't pass unless sleep is called.
  255. tn := time.Unix(123, 0)
  256. now = func() time.Time { return tn }
  257. // Capture sleep times for checking later.
  258. var sleepTimes []time.Duration
  259. sleep = func(d time.Duration) {
  260. sleepTimes = append(sleepTimes, d)
  261. tn = tn.Add(d)
  262. }
  263. wantSleeps := func(want ...time.Duration) error {
  264. if !reflect.DeepEqual(want, sleepTimes) {
  265. return fmt.Errorf("sleepTimes = %v; want %v", sleepTimes, want)
  266. }
  267. sleepTimes = nil
  268. return nil
  269. }
  270. n := &Network{Kbps: 8 /* 1KBps */, Latency: time.Second, MTU: 8}
  271. bdpBytes := (n.Kbps * 1024 / 8) * int(n.Latency/time.Second) // 1024
  272. c, err := n.Conn(bufConn{&bytes.Buffer{}})
  273. if err != nil {
  274. t.Fatalf("Unexpected error creating connection: %v", err)
  275. }
  276. wantSleeps(n.Latency) // Connection creation delay.
  277. write := func(n int, sleeps ...time.Duration) {
  278. if wt, err := c.Write(make([]byte, n)); err != nil || wt != n {
  279. t.Fatalf("c.Write(<%v bytes>) = %v, %v; want %v, nil", n, wt, err, n)
  280. }
  281. if err := wantSleeps(sleeps...); err != nil {
  282. t.Fatalf("After writing %v bytes: %v", n, err)
  283. }
  284. }
  285. read := func(n int, sleeps ...time.Duration) {
  286. if rd, err := c.Read(make([]byte, n)); err != nil || rd != n {
  287. t.Fatalf("c.Read(_) = %v, %v; want %v, nil", rd, err, n)
  288. }
  289. if err := wantSleeps(sleeps...); err != nil {
  290. t.Fatalf("After reading %v bytes: %v", n, err)
  291. }
  292. }
  293. write(8) // No reads and buffer not full, so no sleeps yet.
  294. read(8, time.Second+n.pktTime(8))
  295. write(bdpBytes) // Fill the buffer.
  296. write(1) // We can send one extra packet even when the buffer is full.
  297. write(n.MTU, n.pktTime(1)) // Make sure we sleep to clear the previous write.
  298. write(1, n.pktTime(n.MTU))
  299. write(n.MTU+1, n.pktTime(1), n.pktTime(n.MTU))
  300. tn = tn.Add(10 * time.Second) // Wait long enough for the buffer to clear.
  301. write(bdpBytes) // No sleeps required.
  302. }