File: 4-mock.t

package info (click to toggle)
libsms-aql-perl 1.03-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 132 kB
  • sloc: perl: 588; makefile: 2
file content (351 lines) | stat: -rw-r--r-- 12,235 bytes parent folder | download | duplicates (4)
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
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
#!/usr/bin/perl

# Tests for SMS::AQL using a mocked interface
#
# Thanks to Ton Voon @ Altinity (www.altinity.com) for providing this
# set of tests!
#
# $Id$

use strict;

use Test::More;
use LWP::UserAgent;


eval "use Test::MockObject::Extends";
plan skip_all => "Test::MockObject::Extends required for mock testing" 
    if $@;
    
# OK, we've got Test::MockObject::Extends, so we can go ahead:
plan tests => 92;


# NOTE - the test username and password is for testing SMS::AQL *only*,
# not to be used for any other purpose.  It is given a small amount of
# credit now and then, if you try to abuse it, it just won't get given
# any more credit.  So don't.
my $test_user = 'test_user';
my $test_pass = 'test_password';


use lib '../lib/';
use_ok('SMS::AQL');

my $warning;
my $sender;

# Catch warnings to test
local $SIG{__WARN__} = sub { $warning=shift };

$_ = SMS::AQL->new( { username => "this" } );
is($_, undef, "Fails to create new instance with only username");
like($warning, '/^Must supply username and password/', "Correct error message");

$_ = SMS::AQL->new( { password => "that" } );
is($_, undef, "Fails to create new instance with only password");
like($warning, '/^Must supply username and password/', "Correct error message");

$_ = SMS::AQL->new();
is($_, undef, "Fails to create new instance");
like($warning, '/^Must supply username and password/', "Correct error message");


ok($sender = new SMS::AQL({username => $test_user, password => $test_pass}), 
    'Create instance of SMS::AQL');

ok(ref $sender eq 'SMS::AQL', 
    '$sender is an instance of SMS::AQL');

# This wraps the ua so that methods can be overridden for testing purposes
my $mocked_ua = $sender->{ua} = Test::MockObject::Extends->new( $sender->{ua} );


$mocked_ua->mock("post", \&check_credit);
my $balance = $sender->credit();
is($balance, 501, "got account balance $balance");
is($sender->last_response, "AQSMS-CREDIT=501", "Got reply correctly");
is($sender->last_status, 1, "OK state");

sub check_credit {
	my ($self, $server, $postdata) = @_;
	my $expected = { username => "test_user", password => "test_password", cmd => "credit" };

	like( $server, '/^http:\/\/.*\/sms\/postmsg.php$/', "Server correct format: $server");
	is_deeply( $postdata, $expected, "Post data correct" );

	my $res = Test::MockObject->new();
	$res->set_true( "is_success" );
	$res->mock( "content", sub { "AQSMS-CREDIT=501" } );
	return $res;
}

$sender->{user} = "wrong_user";
$mocked_ua->mock( "post", \&check_credit_wrong_credentials );
$balance = $sender->credit;
is($balance, undef, "No balance received");
is($sender->last_response, "AQSMS-AUTHERROR", "Response gives AUTHERROR message");
is($sender->last_response_text, "The username and password supplied were incorrect", "Got nice text too");
is($sender->last_error, $sender->last_response_text, "And saved to last_error too");
is($sender->last_status, 0, "Error state");

sub check_credit_wrong_credentials {
	my ($self, $server, $postdata) = @_;
	my $expected = { username => "wrong_user", password => "test_password", cmd => "credit" };

	like( $server, '/^http:\/\/.*\/sms\/postmsg.php$/', "Server correct format: $server");
	is_deeply( $postdata, $expected, "Post data correct" );

	my $res = Test::MockObject->new();
	$res->set_true( "is_success" );
	$res->mock( "content", sub { "AQSMS-AUTHERROR" } );
	return $res;
}

$mocked_ua->mock( "post", sub { my $r = Test::MockObject->new(); $r->set_false( "is_success" ); return $r; } );
$balance = $sender->credit;
is($balance, undef, "No server available");
is($sender->last_error, "Could not get valid response from any server", "Correct error message");
is($sender->last_status, 0, "Error state");


my $rc = $sender->send_sms( "000", "Test text" );
is($rc, 0, "Sending failure due to no originator");
is($sender->last_error, "Cannot send message without sender specified", "And last_error set correctly");
is($sender->last_status, 0, "Error state");
like( $warning, '/^Cannot send message without sender specified/', "And right warning" );






#
# Sending tests
#
diag("Testing sending text, simulating all servers failing");
$sender->{user} = "test_user";
$mocked_ua->mock("post", 
    sub { 
        my $r = Test::MockObject->new(); 
        $r->set_false( "is_success" ); 
        return $r; 
    }
);
$rc = $sender->send_sms( "000", "Test text", { sender => "Altinity" } );
is($rc, 0, "No server available");
is($sender->last_error, "Could not get valid response from any server", 
    "Correct error message");
is($sender->last_status, 0, "Error state");


diag("Testing sending text, simulating success");
$mocked_ua->mock("post", \&send_text);
$rc = $sender->send_sms("000", "Testing text", { sender => "Altinity" });
is($rc, 1, "Successful send");
is($sender->last_response, "AQSMS-OK:1", "Got reply correctly");
is($sender->last_response_text, "OK", "Got text correctly");
is($sender->last_status, 1, "OK state");

my $message;
($rc, $message) = 
    $sender->send_sms("000", "Testing text", { sender => "Altinity" });
is($rc, 1, "Successful send on an array interface");
is($message, "OK", "With right message");
is($sender->last_status, 1, "OK state");

sub send_text {
	my ($self, $server, $postdata) = @_;
	my $expected = { 
        username => "test_user", 
        password => "test_password",
        orig     => "Altinity",
        to_num   => "000",
        message => "Testing text"
    };

	like($server, '/^http:\/\/.*\/sms\/postmsg-concat.php$/', 
        "Server correct format: $server");
	is_deeply( $postdata, $expected, "Post data correct" );

	my $res = Test::MockObject->new();
	$res->set_true( "is_success" );
	$res->mock( "content", sub { "AQSMS-OK:1" } );
	return $res;
}

diag("Testing sending text to invalid destination");
# I could only get an "AQSMS-INVALID_DESTINATION if I set the to_num as "bob".
# Setting a mobile number with a digit short, or 000 would still go through 
# as AQSMS-OK. However, SMS::AQL tries to cleanup the number, so using bob 
# fails because the postdata return "ob" instead. So for now, it makes sense 
# to just put a dummy number in because this is really a test for AQL's server
# - we just need to make sure we process this reply correctly.

$mocked_ua->mock("post", \&send_text_invalid_destination);
$rc = $sender->send_sms( "000", "Testing text to invalid dest", { sender => "Altinity" } );
is($rc, 0, "Expected error");
is($sender->last_response, "AQSMS-INVALID_DESTINATION", "Got expected reply");
is($sender->last_response_text, "Invalid destination", "Got text correctly");
is($sender->last_status, 0, "Error state");

($rc, $message) = $sender->send_sms( "000", "Testing text to invalid dest", { sender => "Altinity" } );
is($rc, 0, "Expected error on an array interface");
is($message, "Invalid destination", "With right message");
is($sender->last_status, 0, "Error state");

sub send_text_invalid_destination {
	my ($self, $server, $postdata) = @_;
	my $expected = { username => "test_user", password => "test_password", orig => "Altinity", to_num => "000", message=>"Testing text to invalid dest" };

	like( $server, '/^http:\/\/.*\/sms\/postmsg-concat.php$/', "Server correct format: $server");
	is_deeply( $postdata, $expected, "Post data correct" );

	my $res = Test::MockObject->new();
	$res->set_true( "is_success" );
	$res->mock( "content", sub { "AQSMS-INVALID_DESTINATION" } );
	return $res;
}


diag("Testing sending text, simulating failure due to no credit");
$mocked_ua->mock("post", \&send_text_no_credits);
$rc = $sender->send_sms(
    "000", "Testing text to invalid dest", { sender => "Altinity" }
);
is($rc, 0, "Expected error");
is($sender->last_response, "AQSMS-NOCREDIT", "Got expected reply");
is($sender->last_response_text, "Out of credits", "Got text correctly");
is($sender->last_status, 0, "Error state");

($rc, $message) = $sender->send_sms(
    "000", "Testing text to invalid dest", { sender => "Altinity" }
);
is($rc, 0, "Expected error on an array interface");
is($message, "Out of credits", "With right message");
is($sender->last_status, 0, "Error state");

sub send_text_no_credits {
	my ($self, $server, $postdata) = @_;
	my $expected = {
            username => "test_user",
            password => "test_password",
            orig     => "Altinity",
            to_num   => "000",
            message  => "Testing text to invalid dest"
    };

	like($server, qr{^http://.*/sms/postmsg-concat.php$}, 
        "Server correct format: $server");
	is_deeply( $postdata, $expected, "Post data correct" );

	my $res = Test::MockObject->new();
	$res->set_true( "is_success" );
	$res->mock( "content", sub { "AQSMS-NOCREDIT" } );
	return $res;
}

diag("Testing sending text, simulating unexected response");
$mocked_ua->mock("post", \&send_text_unexpected_response);
$rc = $sender->send_sms(
    "000", "Testing text to invalid dest", { sender => "Altinity" }
);
is($rc, 0, "Expected error");
is($sender->last_response, "AQSMS-NOTPROPER", "Got expected reply");
is($sender->last_response_text, 
    "Unrecognised response from server: AQSMS-NOTPROPER", "Got text correctly");
is($sender->last_status, 0, "Error state");


diag("Testing sending text, simulating invalid destination");
($rc, $message) = $sender->send_sms(
    "000", "Testing text to invalid dest", { sender => "Altinity" }
);
is($rc, 0, "Expected error on an array interface");
is($message, "Unrecognised response from server: AQSMS-NOTPROPER",
    "With right message");
is($sender->last_status, 0, "Error state");

sub send_text_unexpected_response {
	my ($self, $server, $postdata) = @_;
	my $expected = {
        username => "test_user",
        password => "test_password",
        orig     => "Altinity",
        to_num   => "000",
        message  => "Testing text to invalid dest"
    };

	like($server, qr{^http://.*/sms/postmsg-concat.php$}, 
        "Server correct format: $server");
	is_deeply( $postdata, $expected, "Post data correct" );

	my $res = Test::MockObject->new();
	$res->set_true( "is_success" );
	$res->mock( "content", sub { "AQSMS-NOTPROPER" } );
	return $res;
}


$mocked_ua->mock( "post", 
    sub { 
        my $r = Test::MockObject->new();
        $r->set_false( "is_success" );
        return $r; 
    }
);
$rc = $sender->send_sms(
    "000", "Testing text to invalid dest", { sender => "Altinity" }
);
is($rc, 0, "Expected error: No server available");
is($sender->last_error, "Could not get valid response from any server", 
    "Correct error message");
is($sender->last_status, 0, "Error state");

diag("Testing sending text, simulating all servers failing");
($rc, $message) = $sender->send_sms(
    "000", "Testing text to invalid dest", { sender => "Altinity" }
);
is($rc, 0, "Expected error: No server available");
is($message, "Could not get valid response from any server", 
    "With right message");
is($sender->last_status, 0, "Error state");




# now test new voice push functionality
diag("Testing voice push functionality");
$mocked_ua->mock("post", \&voice_push);
$rc = $sender->voice_push("000", "Testing voice");
is($rc, 1, 'Successful voice push send');
is($sender->last_response,      "VP_OK", "Got reply correctly" );
is($sender->last_response_text, "OK",         "Got text correctly"  );
is($sender->last_status,         1,           "OK state"            );

($rc, $message) = $sender->voice_push( "000", "Testing voice");
is($rc,                  1,    "Successful send on an array interface");
is($message,             "OK", "With right message"                   );
is($sender->last_status, 1,    "OK state"                             );

sub voice_push {
    my ($self, $server, $postdata) = @_;
    my $expected = { 
        username => "test_user", 
        password => "test_password", 
        msisdn   => "000", 
        message  => "Testing voice" 
    };

    like( $server, qr{^http://vp\d\.aql\.com/voice_push.php$}, 
        "Server correct format: $server");
    is_deeply( $postdata, $expected, "Post data correct" );

    my $res = Test::MockObject->new();
    $res->set_true( "is_success" );
    $res->mock( "content", sub { "VP_OK" } );
    return $res;
}

# TODO: write further tests for the voice push functionality, to ensure it
# handles all possible AQL responses correctly.