goagi.TestReadResponse   A
last analyzed

Complexity

Conditions 2

Size

Total Lines 24
Code Lines 19

Duplication

Lines 0
Ratio 0 %

Importance

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