|
1 | 1 | package memory
|
2 | 2 |
|
3 | 3 | import (
|
4 |
| - "context" |
| 4 | + "fmt" |
5 | 5 | "testing"
|
6 | 6 | "time"
|
7 | 7 | )
|
8 | 8 |
|
9 |
| -func shouldTakeAbout(t *testing.T, fn func(), expDur time.Duration, sloppynessFactor int, info string) { |
10 |
| - // on Dieter's laptop: |
11 |
| - // takes about <=15 micros for add/wait sequences |
12 |
| - // takes about 150micros for a add + blocking wait |
13 |
| - // on circleCI, takes 75micros for add/wait sequence |
14 |
| - slop := time.Duration(sloppynessFactor) * time.Microsecond |
15 |
| - pre := time.Now() |
16 |
| - fn() |
17 |
| - dur := time.Since(pre) |
18 |
| - if dur > expDur+slop || dur < expDur-slop { |
19 |
| - t.Fatalf("scenario %s. was supposed to take %s, but took %s", info, expDur, dur) |
| 9 | +var now = time.Unix(10, 0) |
| 10 | + |
| 11 | +func shouldTake(t *testing.T, tl *TimeLimiter, workDone, expDur time.Duration, info string) { |
| 12 | + |
| 13 | + // account for work done, as well as moving our clock forward by the same amount |
| 14 | + now.Add(workDone) |
| 15 | + tl.add(now, workDone) |
| 16 | + |
| 17 | + fmt.Println("now is now", now) |
| 18 | + dur := tl.wait(now) |
| 19 | + if dur != expDur { |
| 20 | + t.Fatalf("scenario %s. expected wait %s, got wait %s", info, expDur, dur) |
20 | 21 | }
|
| 22 | + |
| 23 | + // fake the "sleep" so we're a properly behaving caller |
| 24 | + now.Add(dur) |
21 | 25 | }
|
22 | 26 |
|
23 | 27 | func TestTimeLimiter(t *testing.T) {
|
24 | 28 | window := time.Second
|
25 | 29 | limit := 100 * time.Millisecond
|
26 | 30 |
|
27 |
| - ctx, cancel := context.WithCancel(context.Background()) |
28 |
| - tl := NewTimeLimiter(ctx, window, limit) |
| 31 | + tl := NewTimeLimiter(window, limit, now) |
29 | 32 |
|
30 | 33 | // TEST 1 : Start first window by doing work and seeing when it starts blocking
|
31 |
| - shouldTakeAbout(t, tl.Wait, 0, 100, "window 1: work done: 0 - wait should be 0") |
32 |
| - |
33 |
| - tl.Add(5 * time.Millisecond) |
34 |
| - shouldTakeAbout(t, tl.Wait, 0, 100, "window 1: work done: 5ms - wait should be 0") |
35 |
| - |
36 |
| - tl.Add(10 * time.Millisecond) |
37 |
| - shouldTakeAbout(t, tl.Wait, 0, 100, "window 1: work done: 15ms - wait should be 0") |
38 |
| - |
39 |
| - tl.Add(80 * time.Millisecond) |
40 |
| - shouldTakeAbout(t, tl.Wait, 0, 100, "window 1: work done: 95ms - wait should be 0") |
41 |
| - |
42 |
| - tl.Add(4 * time.Millisecond) |
43 |
| - shouldTakeAbout(t, tl.Wait, 0, 100, "window 1: work done: 99ms - wait should be 0") |
44 |
| - |
45 |
| - tl.Add(3 * time.Millisecond) |
46 |
| - |
47 |
| - shouldTakeAbout(t, tl.Wait, time.Second, 500, "window 1: work done: 102ms - almost no time has passed, so wait should be full window") |
| 34 | + shouldTake(t, tl, 0, 0, "window 1: work done: 0") |
| 35 | + shouldTake(t, tl, 5*time.Millisecond, 0, "window 1: work done: 5ms") |
| 36 | + shouldTake(t, tl, 10*time.Millisecond, 0, "window 1: work done: 15ms") |
| 37 | + shouldTake(t, tl, 80*time.Millisecond, 0, "window 1: work done: 95ms") |
| 38 | + shouldTake(t, tl, 4*time.Millisecond, 0, "window 1: work done: 99ms") |
| 39 | + shouldTake(t, tl, 3*time.Millisecond, time.Second-102*time.Millisecond, "window 1: work done: 102ms") |
48 | 40 |
|
49 | 41 | // TEST 2 : Now that we waited until a full window, should be able to up to limit work again
|
50 |
| - tl.Add(50 * time.Millisecond) |
51 |
| - shouldTakeAbout(t, tl.Wait, 0, 100, "window 2: work done: 50ms - wait should be 0") |
52 |
| - |
53 |
| - tl.Add(40 * time.Millisecond) |
54 |
| - shouldTakeAbout(t, tl.Wait, 0, 100, "window 2: work done: 90ms - wait should be 0") |
55 |
| - |
56 |
| - tl.Add(40 * time.Millisecond) |
57 |
| - shouldTakeAbout(t, tl.Wait, time.Second, 500, "window 2: work done: 130ms - wait should be 1s") |
58 |
| - |
59 |
| - // TEST 3 : Now that we waited until a full window, should be able to up to limit work again |
60 |
| - // but this time we cancel, so we don't have to wait as long |
61 |
| - tl.Add(50 * time.Millisecond) |
62 |
| - shouldTakeAbout(t, tl.Wait, 0, 100, "window 3: work done: 50ms - wait should be 0") |
63 |
| - |
64 |
| - tl.Add(40 * time.Millisecond) |
65 |
| - shouldTakeAbout(t, tl.Wait, 0, 100, "window 3: work done: 90ms - wait should be 0") |
66 |
| - |
67 |
| - tl.Add(40 * time.Millisecond) |
68 |
| - |
69 |
| - time.AfterFunc(500*time.Millisecond, cancel) |
70 |
| - shouldTakeAbout(t, tl.Wait, 500*time.Millisecond, 500, "window 3: work done: 130ms, canceling after 500ms - wait should be 500ms") |
| 42 | + shouldTake(t, tl, 50*time.Millisecond, 0, "window 2: work done: 50ms") |
| 43 | + shouldTake(t, tl, 40*time.Millisecond, 0, "window 2: work done: 90ms") |
| 44 | + shouldTake(t, tl, 40*time.Millisecond, time.Second-130*time.Millisecond, "window 2: work done: 130ms") |
71 | 45 | }
|
0 commit comments