Test Failed
Push — master ( 569253...ad9af8 )
by Vyacheslav
01:38
created

goagi.TestReadResponseTimeout   A

Complexity

Conditions 1

Size

Total Lines 20
Code Lines 16

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 16
nop 1
dl 0
loc 20
rs 9.6
c 0
b 0
f 0

1 Method

Rating   Name   Duplication   Size   Complexity  
A goagi.TestWriteTimeout 0 7 1
1
package goagi
2
3
import (
4
	"bytes"
5
	"io"
6
	"io/ioutil"
7
	"log"
8
	"net"
9
	"os"
10
	"strings"
11
	"testing"
12
	"time"
13
14
	"github.com/stretchr/testify/assert"
15
)
16
17
type stubReader struct {
18
	io.Reader
19
}
20
21
type stubWriter struct {
22
	io.Writer
23
	tout int64
24
}
25
26
func (w *stubWriter) SetWriteDeadline(t time.Time) error {
27
	w.tout = t.Sub(time.Now()).Milliseconds()
28
	return nil
29
}
30
31
var agiSetupInput = []string{
32
	"agi_network: yes",
33
	"agi_network_script: foo?",
34
	"agi_request: agi://127.0.0.1/foo?",
35
	"agi_channel: SIP/2222@default-00000023",
36
	"agi_language: en",
37
	"agi_type: SIP",
38
	"agi_uniqueid: 1397044468.0",
39
	"agi_version: 0.1",
40
	"agi_callerid: 5001",
41
	"agi_calleridname: Alice",
42
	"agi_callingpres: 67",
43
	"agi_callingani2: 0",
44
	"agi_callington: 0",
45
	"agi_callingtns: 0",
46
	"agi_dnid: 123456",
47
	"agi_rdnis: unknown",
48
	"agi_context: default",
49
	"agi_extension: 2222",
50
	"agi_priority: 1",
51
	"agi_enhanced: 0.0",
52
	"agi_accountcode: 0",
53
	"agi_threadid: 140536028174080",
54
	"agi_arg_1: argument1",
55
	"agi_arg_2: argument2",
56
}
57
58
func TestNew(t *testing.T) {
59
	input := strings.Join(agiSetupInput, "\n")
60
	input += "\n\n"
61
	logBuffer := new(bytes.Buffer)
62
	logger := log.New(logBuffer, "agi: ", log.Lmicroseconds)
63
	reader := &stubReader{strings.NewReader(input)}
64
	writer := &stubWriter{ioutil.Discard, 0}
65
66
	agi, err := New(reader, writer, logger)
67
	assert.Nil(t, err)
68
	assert.Equal(t, "SIP/2222@default-00000023", agi.Env("channel"))
69
	assert.Equal(t, "2222", agi.Env("extension"))
70
	assert.Empty(t, agi.Env("invalid_name"))
71
	assert.Equal(t, 2, len(agi.EnvArgs()))
72
	assert.Contains(t, logBuffer.String(), "agi_network: yes")
73
	assert.Contains(t, logBuffer.String(), "agi_threadid: 140536028174080")
74
}
75
76
func TestNewFail(t *testing.T) {
77
	reader, writer, err := os.Pipe()
78
	assert.Nil(t, err)
79
80
	reader.Close()
81
	agi, err := New(reader, writer, nil)
82
	assert.Nil(t, agi)
83
	assert.NotNil(t, err)
84
	assert.Contains(t, err.Error(), "closed")
85
}
86
87
func TestNewIOPipe(t *testing.T) {
88
	reader, writer, err := os.Pipe()
89
	assert.Nil(t, err)
90
	input := strings.Join(agiSetupInput, "\n")
91
	input += "\n\n"
92
93
	writer.WriteString(input)
94
	agi, err := New(reader, writer, nil)
95
	assert.Nil(t, err)
96
	assert.Equal(t, "2222", agi.Env("extension"))
97
	assert.Equal(t, 2, len(agi.EnvArgs()))
98
}
99
100
func TestNewNetPipe(t *testing.T) {
101
	reader, writer := net.Pipe()
102
	input := strings.Join(agiSetupInput, "\n")
103
	input += "\n\n"
104
105
	go writer.Write([]byte(input))
106
	agi, err := New(reader, writer, nil)
107
	assert.Nil(t, err)
108
	assert.Equal(t, "2222", agi.Env("extension"))
109
	assert.Equal(t, 2, len(agi.EnvArgs()))
110
}
111
112
func TestSessionInitDeviceFail(t *testing.T) {
113
	stdin, _, err := os.Pipe()
114
	assert.Nil(t, err)
115
	agi := &AGI{reader: stdin}
116
	stdin.Close()
117
	_, err = agi.sessionInit()
118
	assert.NotNil(t, err)
119
	assert.Contains(t, err.Error(), "closed")
120
}
121
122
func TestReadResponse(t *testing.T) {
123
	tests := []struct {
124
		input string
125
		code  int
126
		ishup bool
127
	}{
128
		{"100 result=0 Trying...\n", codeEarly, false},
129
		{"200 result=1\n", codeSucc, false},
130
		{"503 result=-2 Memory allocation failure\n", codeE503, false},
131
		{"510 Invalid or unknown command\n", codeE510, false},
132
		{"511 Command Not Premitted\n", codeE511, false},
133
		{"520 Invalid command syntax.\n", codeE520, false},
134
	}
135
136
	// run tests
137
	for _, test := range tests {
138
		reader := &stubReader{strings.NewReader(test.input)}
139
		agi := &AGI{reader: reader}
140
141
		res, code, err := agi.read()
142
		assert.Nil(t, err, test.input)
143
		assert.Equal(t, test.input, res)
144
		assert.Equal(t, test.code, code, test.input)
145
		assert.Equal(t, test.ishup, agi.isHUP, test.input)
146
	}
147
}
148
149
func TestReadResponseWithHangup(t *testing.T) {
150
	reader := &stubReader{strings.NewReader("HANGUP\n200 result=1\n")}
151
	agi := &AGI{reader: reader}
152
	res, code, err := agi.read()
153
	assert.Nil(t, err)
154
	assert.Equal(t, "200 result=1\n", res)
155
	assert.Equal(t, codeSucc, code)
156
	assert.True(t, agi.isHUP)
157
}
158
159
func TestReadResponseLongError520(t *testing.T) {
160
	input := "HANGUP\n520-Invalid command syntax.  Proper usage follows:\n" +
161
		"Usage: DATABASE GET\n" +
162
		"Retrieves an entry in the Asterisk database for a\n" +
163
		"given family and key.\n" +
164
		"Returns 0 if is not set. Returns 1 if \n" +
165
		"is set and returns the variable in parentheses.\n" +
166
		"Example return code: 200 result=1 (testvariable)\n" +
167
		"520 End of proper usage.\n"
168
	reader := &stubReader{strings.NewReader(input)}
169
	agi := &AGI{reader: reader}
170
	res, code, err := agi.read()
171
	assert.Nil(t, err)
172
	assert.Equal(t, input[7:], res)
173
	assert.Equal(t, codeE520, code)
174
	assert.True(t, agi.isHUP)
175
}
176
177
func TestReadResponseGarbage(t *testing.T) {
178
	tests := []string{
179
		"Usage: DATABASE GET\n" +
180
			"Retrieves an entry in the Asterisk database for a\n" +
181
			"given family and key.\n" +
182
			"Returns 0 if is not set. Returns 1 if \n" +
183
			"is set and returns the variable in parentheses.\n" +
184
			"Example return code: 200 result=1 (testvariable)\n" +
185
			"520 End of proper usage.\n",
186
		"\n", // empty string
187
		"2222222\n",
188
		"-1 result=4\n",
189
		"780 result=0\n",
190
	}
191
192
	for _, input := range tests {
193
		reader := &stubReader{strings.NewReader(input)}
194
		agi := &AGI{reader: reader}
195
		_, code, err := agi.read()
196
		assert.NotNil(t, err)
197
		assert.Contains(t, err.Error(), "Invalid input")
198
		assert.Zero(t, code)
199
	}
200
}
201
202
func TestReadResponseFail(t *testing.T) {
203
	stdin, _, err := os.Pipe()
204
	assert.Nil(t, err)
205
	agi := &AGI{reader: stdin}
206
	stdin.Close()
207
	_, _, err = agi.read()
208
	assert.NotNil(t, err)
209
	assert.Contains(t, err.Error(), "closed")
210
}
211
212
func TestWriteStdIO(t *testing.T) {
213
	reader, writer, err := os.Pipe()
214
	assert.Nil(t, err)
215
	agi := &AGI{writer: writer}
216
217
	err = agi.write([]byte("NOOP\n"))
218
	assert.Nil(t, err)
219
220
	buf := make([]byte, 32)
221
	n, _ := reader.Read(buf)
222
	assert.Equal(t, "NOOP\n", string(buf[:n]))
223
}
224
225
func TestWriteNetConn(t *testing.T) {
226
	reader, writer := net.Pipe()
227
228
	agi := &AGI{writer: writer}
229
230
	go func() {
231
		agi.write([]byte("ANSWER\n"))
232
		writer.Close()
233
	}()
234
235
	buf, _ := ioutil.ReadAll(reader)
236
	assert.Equal(t, "ANSWER\n", string(buf))
237
}
238
239
func TestWriteTimeout(t *testing.T) {
240
	_, writer := net.Pipe()
241
	agi := &AGI{writer: writer, wrtout: time.Millisecond * 100}
242
243
	err := agi.write([]byte("NOOP\n"))
244
	assert.NotNil(t, err)
245
	assert.Contains(t, err.Error(), "timeout")
246
}
247
248
func TestWriteFailSetTimeout(t *testing.T) {
249
	_, writer := net.Pipe()
250
	agi := &AGI{writer: writer, wrtout: time.Millisecond * 100}
251
252
	writer.Close()
253
	err := agi.write([]byte("NOOP\n"))
254
	assert.NotNil(t, err)
255
	assert.Contains(t, err.Error(), "closed")
256
}
257
258
func TestWriteFail(t *testing.T) {
259
	reader, writer, err := os.Pipe()
260
	assert.Nil(t, err)
261
	agi := &AGI{writer: writer}
262
263
	reader.Close()
264
	err = agi.write([]byte("HANGUP\n"))
265
	assert.NotNil(t, err)
266
	assert.Contains(t, err.Error(), "broken pipe")
267
}
268
269
func TestExecute(t *testing.T) {
270
	buf, reader, writer := stubReaderWriter("200 result=1")
271
	agi := &AGI{reader: reader, writer: writer, wrtout: rwDefaultTimeout * 5}
272
	resp, err := agi.execute("NOOP\n")
273
	assert.Nil(t, err)
274
	assert.Equal(t, "NOOP\n", buf.String())
275
	assert.Equal(t, 200, resp.Code())
276
	assert.Equal(t, 1, resp.Result())
277
	assert.True(t, writer.tout > 4000)
278
279
	resp, err = agi.execute("HANGUP\n")
280
	assert.NotNil(t, err)
281
	assert.Nil(t, resp)
282
283
	_, wr := net.Pipe()
284
	agi.writer = wr
285
	wr.Close()
286
	resp, err = agi.execute("HANGUP\n")
287
	assert.NotNil(t, err)
288
	assert.Contains(t, err.Error(), "closed")
289
}
290
291
func TestAGI(t *testing.T) {
292
}
293