-
Notifications
You must be signed in to change notification settings - Fork 4
/
roach_test.go
225 lines (204 loc) · 6 KB
/
roach_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
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
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
//go:build !ci
// +build !ci
// Don't run these Roach tests on CI platforms. There were UDP problems 10/23/2020 on Travis.
package dastard
import (
"bytes"
"encoding/binary"
"fmt"
"net"
"testing"
"time"
)
func newBuffer(nchan, nsamp uint16, sampnum uint64) []byte {
buf := new(bytes.Buffer)
header := []interface{}{
uint8(0), // unused
uint8(1), // flag: 1=flux-ramp demodulation
nchan,
nsamp,
uint16(1), // flag: 1 means 2-byte words
sampnum,
}
for _, v := range header {
if err := binary.Write(buf, binary.BigEndian, v); err != nil {
fmt.Println("binary.Write failed:", err)
return buf.Bytes()
}
}
for i := uint16(0); i < nchan*nsamp; i++ {
if err := binary.Write(buf, binary.BigEndian, i); err != nil {
fmt.Println("binary.Write failed:", err)
break
}
}
return buf.Bytes()
}
func publishRoachPackets(port int, nchan uint16) (closer chan struct{}, err error) {
host := fmt.Sprintf("127.0.0.1:%d", port)
raddr, err := net.ResolveUDPAddr("udp", host)
if err != nil {
return nil, err
}
conn, err := net.DialUDP("udp", nil, raddr)
if err != nil {
return nil, err
}
nsamp := 8000 / (2 * nchan)
closer = make(chan struct{})
go func() {
defer conn.Close()
for i := uint64(0); ; i += uint64(nsamp) {
select {
case <-closer:
return
default:
buffer := newBuffer(nchan, nsamp, i)
conn.Write(buffer)
// fmt.Printf("Wrote buffer iteration %4d of size %d: %v\n", i, len(buffer), buffer[0:20])
time.Sleep(100 * time.Millisecond)
}
}
}()
return closer, nil
}
// TestDevice checks that the raw RoachDevice can receive and parse a header
func TestRoachDevice(t *testing.T) {
// Start generating Roach packets, until closer is closed.
port := 60001
var nchan uint16 = 40
packetSourceCloser, err := publishRoachPackets(port, nchan)
defer close(packetSourceCloser)
if err != nil {
t.Errorf("publishRoachPackets returned %v", err)
}
host := fmt.Sprintf("localhost:%d", port)
dev, err := NewRoachDevice(host, 40000.0)
if err != nil {
t.Errorf("NewRoachDevice returned %v", err)
}
dev.unwrapOpts.PulseSign = +1
dev.unwrapOpts.Bias = false
dev.unwrapOpts.RescaleRaw = true
dev.unwrapOpts.Unwrap = true
time.Sleep(50 * time.Millisecond)
err = dev.samplePacket()
if err != nil {
t.Errorf("samplePacket returned %v", err)
}
if dev.nchan != int(nchan) {
t.Errorf("parsed packet header says nchan=%d, want %d", dev.nchan, nchan)
}
nextBlock := make(chan *dataBlock)
go dev.readPackets(nextBlock)
timeout := time.NewTimer(time.Second)
select {
case <-timeout.C:
t.Errorf("RoachDevice.readPackets launched but no data received after timeout")
case block := <-nextBlock:
if len(block.segments) != dev.nchan {
t.Errorf("RoachDevice block has %d data segments, want %d", len(block.segments), dev.nchan)
}
for i, seg := range block.segments {
want := RawType(i/4) + 4096
if seg.rawData[0] != want {
t.Errorf("RoachDevice block.segments[%d][0] = %d, want %d",
i, seg.rawData[0], want)
}
if len(seg.rawData) != block.nSamp {
t.Errorf("RoachDevice block.segments[%d] length=%d, want %d", i, len(seg.rawData), block.nSamp)
}
}
if block.nSamp < 10 {
t.Errorf("RoachDevice block.nSamp = %d, want at least 10", block.nSamp)
}
}
}
// TestDevice checks that the full RoachSource can receive and parse a header
func TestRoachSource(t *testing.T) {
// Start generating Roach packets, until closer is closed.
port := 60005
var nchan uint16 = 40
packetSourceCloser, err := publishRoachPackets(port, nchan)
defer close(packetSourceCloser)
if err != nil {
t.Errorf("publishRoachPackets returned %v", err)
}
rs, err := NewRoachSource()
if err != nil {
t.Errorf("NewRoachSource returned %v", err)
}
host := fmt.Sprintf("localhost:%d", port)
config := RoachSourceConfig{
HostPort: []string{host},
Rates: []float64{40000.0, 50000.0}, // 2 Rates will be an error
AbacoUnwrapOptions: AbacoUnwrapOptions{
PulseSign: +1,
Unwrap: false,
},
}
err = rs.Configure(&config)
if err == nil {
t.Errorf("RoachSource.Configure should fail when HostPort and Rates are of unequal length")
}
config.Rates = config.Rates[0:1] // Fix rates so it's now of length 1
err = rs.Configure(&config)
if err != nil {
t.Errorf("RoachSource.Configure returned %v", err)
}
if len(rs.active) != 1 {
t.Errorf("RoachSource.active has length %d, want 1", len(rs.active))
}
dev := rs.active[0]
if dev.conn == nil {
t.Errorf("RoachSource[0].conn is nil, should be connected")
}
if dev.nchan != 0 {
t.Errorf("RoachSource[0].nchan before Sample is %d, should be 0", dev.nchan)
}
err = rs.Sample()
if err != nil {
t.Errorf("RoachSource.Sample returned %v", err)
}
if dev.nchan != int(nchan) {
t.Errorf("RoachSource[0].nchan after Sample is %d, should be %d", dev.nchan, nchan)
}
queuedRequests := make(chan func())
npre := 300
nsamp := 1000
err = Start(rs, queuedRequests, npre, nsamp)
if err != nil {
t.Errorf("Start(RoachSource,...) returned %v", err)
}
err = rs.Configure(&config)
if err == nil {
t.Errorf("RoachSource.Configure should fail when source is Active, but it didn't")
}
timeout := time.NewTimer(500 * time.Millisecond) // this was 200 Millisecond, but tests hung sometimes so I made it bigger
select {
case <-timeout.C:
t.Errorf("RoachDevice.readPackets launched but no data received after timeout")
case block := <-rs.nextBlock:
if len(block.segments) != dev.nchan {
t.Errorf("RoachSource block has %d data segments, want %d", len(block.segments), dev.nchan)
}
for i, seg := range block.segments {
want := RawType(i/4) + 4096
if seg.rawData[0] != want {
t.Errorf("RoachSource block.segments[%d][0] = %d, want %d",
i, seg.rawData[0], want)
}
if len(seg.rawData) != block.nSamp {
t.Errorf("RoachSource block.segments[%d] length=%d, want %d", i, len(seg.rawData), block.nSamp)
}
}
if block.nSamp < 10 {
t.Errorf("RoachSource block.nSamp = %d, want at least 10", block.nSamp)
}
<-timeout.C
}
err = rs.Stop()
if err != nil {
t.Errorf("RoachSource.Stop returned %v", err)
}
}