This repository has been archived by the owner on Sep 14, 2019. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathsandbox_test.go
141 lines (116 loc) · 3.21 KB
/
sandbox_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
package main
import (
"log"
_ "math"
"strconv"
"sync"
"testing"
"time"
)
func TestSandbox(t *testing.T) {
if testing.Short() {
t.Skip("skipping test in short mode.")
}
t0 := time.Now()
wg := &sync.WaitGroup{}
wg.Add(1)
tm := NewTaskMaster(&TaskMasterInfo{
WaitGroup: wg,
Properties: make(map[string]string),
})
tm.Start()
sb := NewSandbox(&SandboxInfo{
Id: 1,
Properties: map[string]string{
"mongodb.run": "counters",
"mongodb.url": "mongodb://localhost:27017",
},
Duration: 15 * time.Second,
StartTime: t0,
Emitter: tm,
WaitGroup: wg,
Factory: func() Behavior { return &mongodb_behavior{} },
})
sb.Start()
countResponseTimes(tm)
if time.Since(t0) < (15 * time.Second) {
t.Errorf("This test should have taken at least %d seconds.", 15)
return
}
}
func TestSandboxWithMinWorkTime(t *testing.T) {
const (
TestDuration = 5 * time.Second
OpsPerStall = 10000
SleepDuration = 5 * time.Microsecond
StallDuration = 1 * time.Second
)
if testing.Short() {
t.Skip("skipping test in short mode.")
}
log.Printf("Running a %.2f second test...", TestDuration.Seconds())
t0 := time.Now()
wg := &sync.WaitGroup{}
wg.Add(1)
tm := NewTaskMaster(&TaskMasterInfo{
WaitGroup: wg,
Properties: make(map[string]string),
})
tm.Start()
sb := NewSandbox(&SandboxInfo{
Id: 1,
Properties: map[string]string{
"mongodb.run": "counters",
"mongodb.url": "mongodb://localhost:27017",
"internals.OpsPerStall": strconv.Itoa(OpsPerStall),
},
Duration: TestDuration,
StartTime: t0,
Emitter: tm,
WaitGroup: wg,
Factory: func() Behavior {
return &dummy_behavior{
sleep: SleepDuration,
}
},
})
sb.Start()
ops := countResponseTimes(tm)
if time.Since(t0) < TestDuration {
t.Errorf("This test should have taken at least %.1f seconds.", TestDuration.Seconds())
return
}
// When the response times are very small (on the order of nanoseconds),
// then other channels aren't serviced as fairly by the Go scheduler
// (I think -- I'm certainly not seeing code associated with some channels
// run (e.g. IO)). At those response times, the millisecond stall interval
// should dominate the ops/sec. That is, performing OpsPerStall ops should
// take far far less time that performing the stall. If we through out that
// term, then we can estimate the # of stalls, and put an upper bound on the
// number of ops.
expected_stalls := float64(TestDuration.Seconds()) / float64(StallDuration.Seconds())
if float64(sb.stalls) < expected_stalls {
t.Errorf("expected at least: %.4f stalls, observed: %d stalls",
expected_stalls, sb.stalls)
return
}
// Add a 1% fudge factor to the upper bound because of error
// in the measurement of the actual duration of the test.
expected_max_ops := float64(OpsPerStall) * expected_stalls * 1.01
if float64(ops) > expected_max_ops {
t.Errorf("expected at most: %.4f ops, observed: %d ops",
expected_max_ops, ops)
return
}
}
type dummy_behavior struct {
sleep time.Duration
}
func (*dummy_behavior) Init(props map[string]string) (err error) {
return
}
func (*dummy_behavior) Close() {}
func (this *dummy_behavior) Work(t0 time.Time) (res WorkResult) {
<-time.After(this.sleep)
return WRK_OK
}