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.
 
 
 

569 lines
17 KiB

  1. // Copyright 2015 Google Inc. All rights reserved.
  2. //
  3. // Licensed under the Apache License, Version 2.0 (the "License");
  4. // you may not use this file except in compliance with the License.
  5. // You may obtain a copy of the License at
  6. //
  7. // http://www.apache.org/licenses/LICENSE-2.0
  8. //
  9. // Unless required by applicable law or agreed to in writing, software
  10. // distributed under the License is distributed on an "AS IS" BASIS,
  11. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. // See the License for the specific language governing permissions and
  13. // limitations under the License.
  14. package trafficshape
  15. import (
  16. "bytes"
  17. "io"
  18. "io/ioutil"
  19. "net"
  20. "net/http"
  21. "net/http/httptest"
  22. "sync"
  23. "testing"
  24. "time"
  25. )
  26. func TestListenerRead(t *testing.T) {
  27. t.Parallel()
  28. l, err := net.Listen("tcp", "[::]:0")
  29. if err != nil {
  30. t.Fatalf("net.Listen(): got %v, want no error", err)
  31. }
  32. tsl := NewListener(l)
  33. defer tsl.Close()
  34. if got := tsl.ReadBitrate(); got != DefaultBitrate {
  35. t.Errorf("tsl.ReadBitrate(): got %d, want DefaultBitrate", got)
  36. }
  37. if got := tsl.WriteBitrate(); got != DefaultBitrate {
  38. t.Errorf("tsl.WriteBitrate(): got %d, want DefaultBitrate", got)
  39. }
  40. tsl.SetReadBitrate(40) // 4 bytes per second
  41. if got, want := tsl.ReadBitrate(), int64(40); got != want {
  42. t.Errorf("tsl.ReadBitrate(): got %d, want %d", got, want)
  43. }
  44. tsl.SetWriteBitrate(40) // 4 bytes per second
  45. if got, want := tsl.WriteBitrate(), int64(40); got != want {
  46. t.Errorf("tsl.WriteBitrate(): got %d, want %d", got, want)
  47. }
  48. tsl.SetLatency(time.Second)
  49. if got, want := tsl.Latency(), time.Second; got != want {
  50. t.Errorf("tsl.Latency(): got %s, want %s", got, want)
  51. }
  52. var wg sync.WaitGroup
  53. wg.Add(1)
  54. want := bytes.Repeat([]byte("*"), 16)
  55. go func() {
  56. // Dial the local listener.
  57. c, err := net.Dial("tcp", tsl.Addr().String())
  58. if err != nil {
  59. t.Fatalf("net.Dial(): got %v, want no error", err)
  60. }
  61. defer c.Close()
  62. // Wait for the signal that it's okay to write to the connection; ensure
  63. // the test is ready to read it.
  64. wg.Wait()
  65. c.Write(want)
  66. }()
  67. tsc, err := tsl.Accept()
  68. if err != nil {
  69. t.Fatalf("tsl.Accept(): got %v, want no error", err)
  70. }
  71. defer tsc.Close()
  72. // Signal to the write goroutine that it may begin writing.
  73. wg.Done()
  74. start := time.Now()
  75. got, err := ioutil.ReadAll(tsc)
  76. end := time.Now()
  77. if err != nil {
  78. t.Fatalf("tsc.Read(): got %v, want no error", err)
  79. }
  80. if !bytes.Equal(got, want) {
  81. t.Errorf("tsc.Read(): got %q, want %q", got, want)
  82. }
  83. // Breakdown of ~3s minimum:
  84. // 1 second for the initial latency
  85. // ~2-3 seconds for throttled read
  86. // - 4 bytes per second with 16 bytes total = 3 seconds (first four bytes
  87. // are read immediately at the zeroth second; 0:4, 1:8, 2:12, 3:16)
  88. // - the drain ticker begins before the initial start time so some of that
  89. // tick time is unaccounted for in the difference; potentially up to a
  90. // full second (the drain interval). For example, if the ticker is 300ms
  91. // into its tick before start is calculated we will believe that the
  92. // throttled read will have occurred in 2.7s. Allow for up to drain
  93. // interval in skew to account for this and ensure the test does not
  94. // flake.
  95. //
  96. // The test runtime should be negligible compared the latency simulation, so
  97. // we assume the ~3s (> 2.95s) is accounted for by throttling and latency in
  98. // the worst case (we read and a new tick happens immediately).
  99. min := 2*time.Second + 950*time.Millisecond
  100. max := 4*time.Second + 50*time.Millisecond
  101. if got := end.Sub(start); !between(got, min, max) {
  102. t.Errorf("tsc.Read(): took %s, want within [%s, %s]", got, min, max)
  103. }
  104. }
  105. func TestListenerWrite(t *testing.T) {
  106. t.Parallel()
  107. l, err := net.Listen("tcp", "[::]:0")
  108. if err != nil {
  109. t.Fatalf("net.Listen(): got %v, want no error", err)
  110. }
  111. tsl := NewListener(l)
  112. defer tsl.Close()
  113. tsl.SetReadBitrate(40) // 4 bytes per second
  114. tsl.SetWriteBitrate(40) // 4 bytes per second
  115. tsl.SetLatency(time.Second)
  116. var wg sync.WaitGroup
  117. wg.Add(1)
  118. want := bytes.Repeat([]byte("*"), 16)
  119. var start time.Time
  120. var end time.Time
  121. go func() {
  122. // Dial the local listener.
  123. c, err := net.Dial("tcp", tsl.Addr().String())
  124. if err != nil {
  125. t.Fatalf("net.Dial(): got %v, want no error", err)
  126. }
  127. defer c.Close()
  128. // Wait for the signal that it's okay to read from the connection; ensure
  129. // the test is ready to write to it.
  130. wg.Wait()
  131. got, err := ioutil.ReadAll(c)
  132. if err != nil {
  133. t.Fatalf("c.Read(): got %v, want no error", err)
  134. }
  135. if !bytes.Equal(got, want) {
  136. t.Errorf("c.Read(): got %q, want %q", got, want)
  137. }
  138. }()
  139. tsc, err := tsl.Accept()
  140. if err != nil {
  141. t.Fatalf("tsl.Accept(): got %v, want no error", err)
  142. }
  143. // Signal to the write goroutine that it may begin writing.
  144. wg.Done()
  145. start = time.Now()
  146. n, err := tsc.Write(want)
  147. end = time.Now()
  148. tsc.Close()
  149. if err != nil {
  150. t.Fatalf("tsc.Write(): got %v, want no error", err)
  151. }
  152. if got, want := n, len(want); got != want {
  153. t.Errorf("tsc.Write(): got %d bytes, want %d bytes", got, want)
  154. }
  155. // Breakdown of ~3s minimum:
  156. // 1 second for the initial latency
  157. // ~2-3 seconds for throttled write
  158. // - 4 bytes per second with 16 bytes total = 3 seconds (first four bytes
  159. // are written immediately at the zeroth second; 0:4, 1:8, 2:12, 3:16)
  160. // - the drain ticker begins before the initial start time so some of that
  161. // tick time is unaccounted for in the difference; potentially up to a
  162. // full second (the drain interval). For example, if the ticker is 300ms
  163. // into its tick before start is calculated we will believe that the
  164. // throttled write will have occurred in 2.7s. Allow for up to drain
  165. // interval in skew to account for this and ensure the test does not
  166. // flake.
  167. //
  168. // The test runtime should be negligible compared the latency simulation, so
  169. // we assume the ~3s (> 2.95s) is accounted for by throttling and latency in
  170. // the worst case (we write and a new tick happens immediately).
  171. min := 2*time.Second + 950*time.Millisecond
  172. max := 4*time.Second + 50*time.Millisecond
  173. if got := end.Sub(start); !between(got, min, max) {
  174. t.Errorf("tsc.Write(): took %s, want within [%s, %s]", got, min, max)
  175. }
  176. }
  177. func TestListenerWriteTo(t *testing.T) {
  178. t.Parallel()
  179. l, err := net.Listen("tcp", "[::]:0")
  180. if err != nil {
  181. t.Fatalf("net.Listen(): got %v, want no error", err)
  182. }
  183. tsl := NewListener(l)
  184. defer tsl.Close()
  185. tsl.SetReadBitrate(40) // 4 bytes per second
  186. tsl.SetWriteBitrate(40) // 4 bytes per second
  187. tsl.SetLatency(time.Second)
  188. var wg sync.WaitGroup
  189. wg.Add(1)
  190. want := bytes.Repeat([]byte("*"), 16)
  191. go func() {
  192. // Dial the local listener.
  193. c, err := net.Dial("tcp", tsl.Addr().String())
  194. if err != nil {
  195. t.Fatalf("net.Dial(): got %v, want no error", err)
  196. }
  197. defer c.Close()
  198. // Wait for the signal that it's okay to write to the connection; ensure
  199. // the test is ready to read it.
  200. wg.Wait()
  201. c.Write(want)
  202. }()
  203. tsc, err := tsl.Accept()
  204. if err != nil {
  205. t.Fatalf("tsl.Accept(): got %v, want no error", err)
  206. }
  207. defer tsc.Close()
  208. // Signal to the write goroutine that it may begin writing.
  209. wg.Done()
  210. got := &bytes.Buffer{}
  211. wt, ok := tsc.(io.WriterTo)
  212. if !ok {
  213. t.Fatal("tsc.(io.WriterTo): got !ok, want ok")
  214. }
  215. start := time.Now()
  216. n, err := wt.WriteTo(got)
  217. end := time.Now()
  218. if err != io.EOF {
  219. t.Fatalf("tsc.WriteTo(): got %v, want io.EOF", err)
  220. }
  221. if got, want := n, int64(len(want)); got != want {
  222. t.Errorf("tsc.WriteTo(): got %d bytes, want %d bytes", got, want)
  223. }
  224. if !bytes.Equal(got.Bytes(), want) {
  225. t.Errorf("tsc.WriteTo(): got %q, want %q", got.Bytes(), want)
  226. }
  227. // Breakdown of ~3s minimum:
  228. // 1 second for the initial latency
  229. // ~2-3 seconds for throttled read
  230. // - 4 bytes per second with 16 bytes total = 3 seconds (first four bytes
  231. // are read immediately at the zeroth second; 0:4, 1:8, 2:12, 3:16)
  232. // - the drain ticker begins before the initial start time so some of that
  233. // tick time is unaccounted for in the difference; potentially up to a
  234. // full second (the drain interval). For example, if the ticker is 300ms
  235. // into its tick before start is calculated we will believe that the
  236. // throttled read will have occurred in 2.7s. Allow for up to drain
  237. // interval in skew to account for this and ensure the test does not
  238. // flake.
  239. //
  240. // The test runtime should be negligible compared the latency simulation, so
  241. // we assume the ~3s (> 2.95s) is accounted for by throttling and latency in
  242. // the worst case (we read and a new tick happens immediately).
  243. min := 2*time.Second + 950*time.Millisecond
  244. max := 4*time.Second + 50*time.Millisecond
  245. if got := end.Sub(start); !between(got, min, max) {
  246. t.Errorf("tsc.WriteTo(): took %s, want within [%s, %s]", got, min, max)
  247. }
  248. }
  249. func TestListenerReadFrom(t *testing.T) {
  250. t.Parallel()
  251. l, err := net.Listen("tcp", "[::]:0")
  252. if err != nil {
  253. t.Fatalf("net.Listen(): got %v, want no error", err)
  254. }
  255. tsl := NewListener(l)
  256. defer tsl.Close()
  257. tsl.SetReadBitrate(40) // 4 bytes per second
  258. tsl.SetWriteBitrate(40) // 4 bytes per second
  259. tsl.SetLatency(time.Second)
  260. var wg sync.WaitGroup
  261. wg.Add(1)
  262. want := bytes.Repeat([]byte("*"), 16)
  263. var start time.Time
  264. var end time.Time
  265. go func() {
  266. // Dial the local listener.
  267. c, err := net.Dial("tcp", tsl.Addr().String())
  268. if err != nil {
  269. t.Fatalf("net.Dial(): got %v, want no error", err)
  270. }
  271. defer c.Close()
  272. // Wait for the signal that it's okay to read from the connection; ensure
  273. // the test is ready to write it.
  274. wg.Wait()
  275. got, err := ioutil.ReadAll(c)
  276. if err != nil {
  277. t.Fatalf("c.Read(): got %v, want no error", err)
  278. }
  279. if !bytes.Equal(got, want) {
  280. t.Errorf("c.Read(): got %q, want %q", got, want)
  281. }
  282. }()
  283. tsc, err := tsl.Accept()
  284. if err != nil {
  285. t.Fatalf("tsl.Accept(): got %v, want no error", err)
  286. }
  287. // Signal to the write goroutine that it may begin writing.
  288. wg.Done()
  289. buf := bytes.NewReader(want)
  290. rf, ok := tsc.(io.ReaderFrom)
  291. if !ok {
  292. t.Fatal("tsc.(io.ReaderFrom): got !ok, want ok")
  293. }
  294. start = time.Now()
  295. n, err := rf.ReadFrom(buf)
  296. end = time.Now()
  297. tsc.Close()
  298. if err != nil {
  299. t.Fatalf("tsc.ReadFrom(): got %v, want no error", err)
  300. }
  301. if got, want := n, int64(len(want)); got != want {
  302. t.Errorf("tsc.ReadFrom(): got %d bytes, want %d bytes", got, want)
  303. }
  304. // Breakdown of ~3s minimum:
  305. // 1 second for the initial latency
  306. // ~2-3 seconds for throttled writes
  307. // - 4 bytes per second with 16 bytes total = 3 seconds (first four bytes
  308. // are written immediately at the zeroth second; 0:4, 1:8, 2:12, 3:16)
  309. // - the drain ticker begins before the initial start time so some of that
  310. // tick time is unaccounted for in the difference; potentially up to a
  311. // full second (the drain interval). For example, if the ticker is 300ms
  312. // into its tick before start is calculated we will believe that the
  313. // throttled write will have occurred in 2.7s. Allow for up to drain
  314. // interval in skew to account for this and ensure the test does not
  315. // flake.
  316. //
  317. // The test runtime should be negligible compared the latency simulation, so
  318. // we assume the ~3s (> 2.95s) is accounted for by throttling and latency in
  319. // the worst case (we write and a new tick happens immediately).
  320. min := 2*time.Second + 950*time.Millisecond
  321. max := 4*time.Second + 50*time.Millisecond
  322. if got := end.Sub(start); !between(got, min, max) {
  323. t.Errorf("tsc.ReadFrom(): took %s, want within [%s, %s]", got, min, max)
  324. }
  325. }
  326. func between(d, min, max time.Duration) bool {
  327. return d >= min && d <= max
  328. }
  329. type throttleAssertion struct {
  330. Offset int64
  331. ThrottleContext *ThrottleContext
  332. }
  333. type actionByteAssertion struct {
  334. Offset int64
  335. NextActionInfo *NextActionInfo
  336. }
  337. func TestActionsAndThrottles(t *testing.T) {
  338. l, err := net.Listen("tcp", "[::]:0")
  339. if err != nil {
  340. t.Fatalf("net.Listen(): got %v, want no error", err)
  341. }
  342. tt := []struct {
  343. jsonString string
  344. throttleAssertions []throttleAssertion
  345. actionByteAssertions []actionByteAssertion
  346. }{
  347. {
  348. jsonString: `{"trafficshape":{"shapes":[{"url_regex":"http://example/example", "max_global_bandwidth":1000, "throttles":[{"bytes":"500-1000","bandwidth":100},{"bytes":"1000-2000","bandwidth":300},{"bytes":"2001-","bandwidth":400}],
  349. "halts":[{"byte":530,"duration": 5, "count": 1}],"close_connections":[{"byte":1078,"count":1}]}]}}`,
  350. throttleAssertions: []throttleAssertion{
  351. {
  352. Offset: 10,
  353. ThrottleContext: &ThrottleContext{ThrottleNow: false},
  354. },
  355. {
  356. Offset: 700,
  357. ThrottleContext: &ThrottleContext{ThrottleNow: true, Bandwidth: 100},
  358. },
  359. {
  360. Offset: 1000,
  361. ThrottleContext: &ThrottleContext{ThrottleNow: true, Bandwidth: 300},
  362. },
  363. {
  364. Offset: 5000,
  365. ThrottleContext: &ThrottleContext{ThrottleNow: true, Bandwidth: 400},
  366. },
  367. },
  368. actionByteAssertions: []actionByteAssertion{
  369. {
  370. Offset: 501,
  371. NextActionInfo: &NextActionInfo{ActionNext: true, ByteOffset: 530, Index: 1},
  372. },
  373. {
  374. Offset: 900,
  375. NextActionInfo: &NextActionInfo{ActionNext: true, ByteOffset: 1000, Index: 2},
  376. },
  377. {
  378. Offset: 1015,
  379. NextActionInfo: &NextActionInfo{ActionNext: true, ByteOffset: 1078, Index: 3},
  380. },
  381. {
  382. Offset: 2001,
  383. NextActionInfo: &NextActionInfo{ActionNext: true, ByteOffset: 2001, Index: 5},
  384. },
  385. },
  386. },
  387. }
  388. for i, tc := range tt {
  389. tsl := NewListener(l)
  390. defer tsl.Close()
  391. h := NewHandler(tsl)
  392. req, err := http.NewRequest("POST", "test", bytes.NewBufferString(tc.jsonString))
  393. if err != nil {
  394. t.Fatalf("%d. http.NewRequest(): got %v, want no error", i, err)
  395. }
  396. rw := httptest.NewRecorder()
  397. h.ServeHTTP(rw, req)
  398. if got, want := rw.Code, 200; got != want {
  399. t.Errorf("%d. rw.Code: got %d, want %d", i+1, got, want)
  400. }
  401. conn, err := net.Dial("tcp", l.Addr().String())
  402. defer conn.Close()
  403. if err != nil {
  404. t.Fatalf("net.Dial(): got %v, want no error", err)
  405. }
  406. tsconn := tsl.GetTrafficShapedConn(conn)
  407. tsconn.Context = &Context{
  408. Shaping: true,
  409. URLRegex: "http://example/example",
  410. }
  411. for _, ta := range tc.throttleAssertions {
  412. if got, want := *tsconn.GetCurrentThrottle(ta.Offset), *ta.ThrottleContext; got != want {
  413. t.Errorf("tc.%d CurtThrottleInfo at %d got %+v, want %+v", i+1, ta.Offset, got, want)
  414. }
  415. }
  416. for _, aba := range tc.actionByteAssertions {
  417. if got, want := *tsconn.GetNextActionFromByte(aba.Offset), *aba.NextActionInfo; got != want {
  418. t.Errorf("tc.%d NextActionInfo at %d got %+v, want %+v", i+1, aba.Offset, got, want)
  419. }
  420. }
  421. }
  422. }
  423. func TestActionsAfterUpdatingCounts(t *testing.T) {
  424. l, err := net.Listen("tcp", "[::]:0")
  425. if err != nil {
  426. t.Fatalf("net.Listen(): got %v, want no error", err)
  427. }
  428. jsonString := `{"trafficshape":{"shapes":[{"url_regex":"http://example/example", "max_global_bandwidth":1000, "throttles":[{"bytes":"500-1000","bandwidth":100}],
  429. "halts":[{"byte":530,"duration": 5, "count": 1},{"byte":550,"duration": 5, "count": 1}],"close_connections":[{"byte":1078,"count":1}]}]}}`
  430. tsl := NewListener(l)
  431. defer tsl.Close()
  432. h := NewHandler(tsl)
  433. req, err := http.NewRequest("POST", "test", bytes.NewBufferString(jsonString))
  434. if err != nil {
  435. t.Fatalf("http.NewRequest(): got %v, want no error", err)
  436. }
  437. rw := httptest.NewRecorder()
  438. h.ServeHTTP(rw, req)
  439. if got, want := rw.Code, 200; got != want {
  440. t.Errorf("rw.Code: got %d, want %d", got, want)
  441. }
  442. conn, err := net.Dial("tcp", l.Addr().String())
  443. defer conn.Close()
  444. if err != nil {
  445. t.Fatalf("net.Dial(): got %v, want no error", err)
  446. }
  447. tsconn := tsl.GetTrafficShapedConn(conn)
  448. tsconn.Context = &Context{
  449. Shaping: true,
  450. URLRegex: "http://example/example",
  451. }
  452. actions := tsconn.Shapes.M[tsconn.Context.URLRegex].Shape.Actions
  453. nai := []*NextActionInfo{
  454. &NextActionInfo{ActionNext: true, ByteOffset: 530, Index: 1},
  455. &NextActionInfo{ActionNext: true, ByteOffset: 550, Index: 2},
  456. &NextActionInfo{ActionNext: true, ByteOffset: 1000, Index: 3},
  457. &NextActionInfo{ActionNext: true, ByteOffset: 1078, Index: 4},
  458. &NextActionInfo{ActionNext: false},
  459. }
  460. if got, want := *tsconn.GetNextActionFromByte(515), *nai[0]; got != want {
  461. t.Errorf("NextActionInfo at %d got %+v, want %+v", 515, got, want)
  462. }
  463. actions[1].decrementCount()
  464. if got, want := *tsconn.GetNextActionFromByte(515), *nai[1]; got != want {
  465. t.Errorf("NextActionInfo at %d got %+v, want %+v", 515, got, want)
  466. }
  467. actions[2].decrementCount()
  468. if got, want := *tsconn.GetNextActionFromByte(515), *nai[2]; got != want {
  469. t.Errorf("NextActionInfo at %d got %+v, want %+v", 515, got, want)
  470. }
  471. if got, want := *tsconn.GetNextActionFromByte(1015), *nai[3]; got != want {
  472. t.Errorf("NextActionInfo at %d got %+v, want %+v", 1015, got, want)
  473. }
  474. actions[4].decrementCount()
  475. if got, want := *tsconn.GetNextActionFromByte(1015), *nai[4]; got != want {
  476. t.Errorf("NextActionInfo at %d got %+v, want %+v", 1015, got, want)
  477. }
  478. }