View | Details | Raw Unified | Return to bug 26700
Collapse All | Expand All

(-)a/C4/SIP/t/000_sc_config_auth.t (-48 lines)
Lines 1-48 Link Here
1
#!/usr/bin/perl
2
# 
3
# check if SIP terminal can Auth based on the xml config
4
#
5
6
use strict;
7
use warnings;
8
use FindBin qw($Bin);
9
use lib "$Bin";
10
11
use Test::More tests => 15;
12
13
BEGIN {
14
	use_ok('C4::SIP::Sip::Constants', qw(:all));
15
	use_ok('SIPtest', qw(:basic :user1 :auth));
16
	use_ok('C4::Auth', qw(&check_api_auth));
17
	use_ok('C4::Context');
18
	use_ok('CGI');
19
	use_ok('Data::Dumper');
20
}
21
22
my ($status, $cookie, $sessionID, $uenv);
23
my $query = CGI->new();
24
ok($username, sprintf "\$username exported by SIPtest (%s)", ($username||''));
25
ok($password, sprintf "\$password exported by SIPtest (%s)", ($password||''));
26
27
ok($ENV{REMOTE_USER} = $username,          "set ENV{REMOTE_USER}");	# from SIPtest
28
ok($query->param(userid   => $username),   "set \$query->param('userid')");
29
ok($query->param(password => $password),   "set \$query->param('password')");
30
31
$status = api_auth();
32
$uenv = C4::Context->userenv;
33
ok($status,    sprintf "api_auth returned status (%s)",    ($status   ||''));
34
ok($uenv, "After  api_auth, Got C4::Context->userenv :" . ($uenv ? Dumper($uenv) : ''));
35
36
($status, $cookie, $sessionID) = check_api_auth($query, {circulate=>1}, "intranet");
37
38
ok($status,    sprintf "checkauth returned status (%s)",    ($status   ||''));
39
# ok($cookie,    sprintf "checkauth returned cookie (%s)",    ($cookie   ||''));
40
# ok($sessionID, sprintf "checkauth returned sessionID (%s)", ($sessionID||''));
41
42
diag "note: checkauth " . ($cookie    ? "returned cookie    ($cookie)\n"    : "did NOT return cookie\n"   ); 
43
diag "note: checkauth " . ($sessionID ? "returned sessionID ($sessionID)\n" : "did NOT return sessionID\n"); 
44
45
$uenv = C4::Context->userenv;
46
ok($uenv, "After checkauth, Got C4::Context->userenv :" . ($uenv ? Dumper($uenv) : ''));
47
48
diag "Done.";
(-)a/C4/SIP/t/00sc_status.t (-28 lines)
Lines 1-28 Link Here
1
#!/usr/bin/perl
2
# 
3
# sc_status: test basic connection, login, and response
4
# to the SC Status message, which has to be sent before
5
# anything else
6
7
use strict;
8
use warnings;
9
use FindBin qw($Bin);
10
use lib "$Bin";
11
12
use SIPtest qw($datepat $username $password $login_test $sc_status_test);
13
14
my $invalid_uname = { id => 'Invalid username',
15
		      msg => "9300CNinvalid$username|CO$password|CPThe floor|",
16
		      pat => qr/^940/,
17
		      fields => [], };
18
19
my $invalid_pwd = { id => 'Invalid password',
20
		      msg => "9300CN$username|COinvalid$password|CPThe floor|",
21
		      pat => qr/^940/,
22
		      fields => [], };
23
24
my @tests = ( $invalid_uname, $invalid_pwd, $login_test, $sc_status_test );
25
26
SIPtest::run_sip_tests(@tests);
27
28
1;
(-)a/C4/SIP/t/01patron_status.t (-80 lines)
Lines 1-80 Link Here
1
#!/usr/bin/perl
2
# 
3
# patron_status: check status of valid patron and invalid patron
4
5
use strict;
6
use warnings;
7
use FindBin qw($Bin);
8
use lib "$Bin";
9
10
use C4::SIP::Sip::Constants qw(:all);
11
use SIPtest qw($datepat $instid $currency :user1);
12
13
my @tests = (
14
	     $SIPtest::login_test,
15
	     $SIPtest::sc_status_test,
16
	     { id => 'valid Patron Status',
17
	       msg => "2300120060101    084237AO$instid|AA$user_barcode|AD$user_pin|AC|",
18
	       pat => qr/^24 [ Y]{13}\d{3}$datepat/,
19
	       fields => [
20
			  $SIPtest::field_specs{(FID_INST_ID)},
21
			  $SIPtest::field_specs{(FID_SCREEN_MSG)},
22
			  $SIPtest::field_specs{(FID_PRINT_LINE)},
23
			  { field    => FID_PERSONAL_NAME,
24
			    pat      => qr/^$user_fullname$/o,
25
			    required => 1, },
26
			  { field    => FID_PATRON_ID,
27
			    pat      => qr/^$user_barcode/o,
28
			    required => 1, },
29
			  { field    => FID_VALID_PATRON,
30
			    pat      => qr/^Y$/,
31
			    required => 0, },
32
			  { field    => FID_VALID_PATRON_PWD,
33
			    pat      => qr/^Y$/,
34
			    required => 0, },
35
			  { field    => FID_CURRENCY,
36
			    pat      => qr/^$currency$/io,
37
			    required => 0, },
38
			  { field    => FID_FEE_AMT,
39
			    pat      => qr/^[0-9.]+$/,
40
			    required => 0, },
41
			  ], },
42
	     { id => 'invalid password Patron Status',
43
	       msg => "2300120060101    084237AO$instid|AA$user_barcode|AC|ADbadw|",
44
	       pat => qr/^24[ Y]{14}\d{3}$datepat/,
45
	       fields => [
46
			  { field    => FID_PERSONAL_NAME,
47
			    pat      => qr/^$user_fullname$/o,
48
			    required => 1, },
49
			  { field    => FID_PATRON_ID,
50
			    pat      => qr/^$user_barcode$/o,
51
			    required => 1, },
52
			  { field    => FID_INST_ID,
53
			    pat      => qr/^$instid$/o,
54
			    required => 1, },
55
			  { field    => FID_VALID_PATRON_PWD,
56
			    pat      => qr/^N$/,
57
			    required => 1, },
58
			  { field    => FID_VALID_PATRON,
59
			    pat      => qr/^Y$/,
60
			    required => 1, },
61
			  ], },
62
	     { id => 'invalid Patron Status',
63
	       msg => "2300120060101    084237AO$instid|AAwshakespeare|AC|",
64
	       pat => qr/^24Y[ Y]{13}\d{3}$datepat/,
65
	       fields => [
66
			  { field    => FID_PERSONAL_NAME,
67
			    pat      => qr/^$/,
68
			    required => 1, },
69
			  { field    => FID_PATRON_ID,
70
			    pat      => qr/^wshakespeare$/,
71
			    required => 1, },
72
			  { field    => FID_INST_ID,
73
			    pat      => qr/^$instid$/o,
74
			    required => 1, },
75
			  ], },
76
	     );
77
78
         SIPtest::run_sip_tests(@tests);
79
80
1;
(-)a/C4/SIP/t/02patron_info.t (-169 lines)
Lines 1-169 Link Here
1
#!/usr/bin/perl
2
# patron_info: test Patron Information Response
3
4
use strict;
5
use warnings;
6
use FindBin qw($Bin);
7
use lib "$Bin";
8
use Clone qw(clone);
9
10
use C4::SIP::Sip::Constants qw(:all);
11
12
use SIPtest qw(:basic :user1);
13
14
# This is a template test case for the Patron Information
15
# message handling.  Because of the large number of fields,
16
# this template forms the basis for all of the different
17
# situations: valid patron no details, valid patron with each
18
# individual detail requested, invalid patron, invalid patron
19
# password, etc.
20
our $patron_info_test_template = {
21
    id => 'valid Patron Info no details',
22
    msg => "6300020060329    201700          AO$instid|AA$user_barcode|",
23
    pat => qr/^64 [ Y]{13}\d{3}$datepat(\d{4}){6}/,
24
    fields => [
25
	       $SIPtest::field_specs{(FID_INST_ID)},
26
	       $SIPtest::field_specs{(FID_SCREEN_MSG)},
27
	       $SIPtest::field_specs{(FID_PRINT_LINE)},
28
	       { field    => FID_PATRON_ID,
29
		 pat      => qr/^$user_barcode$/o,
30
		 required => 1, },
31
	       { field    => FID_PERSONAL_NAME,
32
		 pat      => qr/^$user_fullname$/o,
33
		 required => 1, },
34
	       $SIPtest::field_specs{(FID_HOLD_ITEMS_LMT)},
35
	       $SIPtest::field_specs{(FID_OVERDUE_ITEMS_LMT)},
36
	       $SIPtest::field_specs{(FID_CHARGED_ITEMS_LMT)},
37
	       { field    => FID_VALID_PATRON,
38
		 pat      => qr/^Y$/,
39
		 # Not required by the spec, but by the test
40
		 required => 1, },
41
	       $SIPtest::field_specs{(FID_CURRENCY)},
42
	       { field    => FID_FEE_AMT,
43
		 pat      => $textpat,
44
		 required => 0, },
45
	       { field    => FID_FEE_LMT,
46
		 pat      => $textpat,
47
		 required => 0, },
48
	       { field    => FID_HOME_ADDR,
49
		 pat      => qr/^$user_homeaddr$/o,
50
		 required => 1, }, # required by this test case
51
	       { field    => FID_EMAIL,
52
		 pat      => qr/^$user_email$/o,
53
		 required => 1, },
54
	       { field    => FID_HOME_PHONE,
55
		 pat      => qr/^$user_phone$/o,
56
		 required => 1, },
57
	       { field    => FID_PATRON_BIRTHDATE,
58
		 pat      => qr/^$user_birthday$/o,
59
		 required => 1, },
60
	       { field    => FID_PATRON_CLASS,
61
		 pat      => qr/^$user_ptype$/o,
62
		 required => 1, },
63
	       { field    => FID_INET_PROFILE,
64
		 pat      => qr/^$user_inet$/,
65
		 required => 1, },
66
	      ], };
67
68
our @tests = (
69
	     $SIPtest::login_test,
70
	     $SIPtest::sc_status_test,
71
	     clone($patron_info_test_template),
72
	);
73
74
75
# Create the test cases for the various summary detail fields
76
sub create_patron_summary_tests {
77
    my $test;
78
    my @patron_info_summary_tests = (
79
				     { field    => FID_HOLD_ITEMS,
80
				       pat      => $textpat,
81
				       required => 0, },
82
				     { field    => FID_OVERDUE_ITEMS,
83
				       pat      => $textpat,
84
				       required => 0, },
85
				     { field    => FID_CHARGED_ITEMS,
86
				       pat      => $textpat,
87
				       required => 0, },
88
# The test user has no items of these types, so the tests seem to fail
89
#				     { field    => FID_FINE_ITEMS,
90
#				       pat      => $textpat,
91
#				       required => 1, },
92
#				     { field    => FID_RECALL_ITEMS,
93
#				       pat      => $textpat,
94
#				       required => 0, },
95
#				     { field    => FID_UNAVAILABLE_HOLD_ITEMS,
96
#				       pat      => $textpat,
97
#				       required => 0, },
98
				     );
99
100
    foreach my $i (0 .. scalar @patron_info_summary_tests-1) {
101
	# The tests for each of the summary fields are exactly the
102
	# same as the basic one, except for the fact that there's
103
	# an extra field to test
104
105
	# Copy the hash, adjust it, add it to the end of the list
106
	$test = clone($patron_info_test_template);
107
108
	substr($test->{msg}, 23+$i, 1) = 'Y';
109
	$test->{id} = "valid Patron Info details: "
110
	    . $patron_info_summary_tests[$i]->{field};
111
	push @{$test->{fields}}, $patron_info_summary_tests[$i];
112
	push @tests, $test;
113
	}
114
}
115
116
sub create_invalid_patron_tests {
117
    my $test;
118
119
    $test = clone($patron_info_test_template);
120
    $test->{id} = "invalid Patron Info id";
121
    $test->{msg} =~ s/AA$user_barcode\|/AAberick|/o;
122
    $test->{pat} = qr/^64Y[ Y]{13}\d{3}$datepat(\d{4}){6}/;
123
    delete $test->{fields};
124
    $test->{fields} = [
125
		       $SIPtest::field_specs{(FID_INST_ID)},
126
		       $SIPtest::field_specs{(FID_SCREEN_MSG)},
127
		       $SIPtest::field_specs{(FID_PRINT_LINE)},
128
		       { field    => FID_PATRON_ID,
129
			 pat      => qr/^berick$/,
130
			 required => 1, },
131
		       { field    => FID_PERSONAL_NAME,
132
			 pat      => qr/^$/,
133
			 required => 1, },
134
		       { field    => FID_VALID_PATRON,
135
			 pat      => qr/^N$/,
136
			 required => 1, },
137
		       ];
138
    push @tests, $test;
139
140
    # Valid patron, invalid patron password
141
    $test = clone($patron_info_test_template);
142
    $test->{id} = "valid Patron Info, invalid password";
143
    $test->{msg} .= (FID_PATRON_PWD) . 'badpwd|';
144
    $test->{pat} = qr/^64[ Y]{14}\d{3}$datepat(\d{4}){6}/;
145
    delete $test->{fields};
146
    $test->{fields} = [
147
		       $SIPtest::field_specs{(FID_INST_ID)},
148
		       $SIPtest::field_specs{(FID_SCREEN_MSG)},
149
		       $SIPtest::field_specs{(FID_PRINT_LINE)},
150
		       { field    => FID_PATRON_ID,
151
			 pat      => qr/^$user_barcode$/,
152
			 required => 1, },
153
		       { field    => FID_PERSONAL_NAME,
154
			 pat      => qr/^$user_fullname$/,
155
			 required => 1, },
156
		       { field    => FID_VALID_PATRON,
157
			 pat      => qr/^Y$/,
158
			 required => 1, },
159
		       { field    => FID_VALID_PATRON_PWD,
160
			 pat      => qr/^N$/,
161
			 required => 1, },
162
		       ];
163
    push @tests, $test;
164
}
165
166
create_patron_summary_tests;
167
create_invalid_patron_tests;
168
SIPtest::run_sip_tests(@tests);
169
1;
(-)a/C4/SIP/t/03checkout.t (-215 lines)
Lines 1-215 Link Here
1
#!/usr/bin/perl
2
# checkout: test Checkout Response
3
4
use strict;
5
use warnings;
6
use FindBin qw($Bin);
7
use lib "$Bin";
8
use Clone qw(clone);
9
10
use CGI qw ( -utf8 );
11
12
use C4::SIP::Sip::Constants qw(:all);
13
use SIPtest qw(
14
		:basic
15
		$user_barcode
16
		:diacritic
17
        :item1
18
	);
19
20
my $patron_enable_template = {
21
    id => 'Renew All: prep: enable patron permissions',
22
    msg => "2520060102    084238AO$instid|AA$user_barcode|",
23
    pat => qr/^26 {4}[ Y]{10}000$datepat/o,
24
    fields => [],
25
};
26
27
my $patron_disable_template = {
28
    id => 'Checkout: block patron (prep to test checkout denied)',
29
    msg => "01N20060102    084238AO$instid|ALFees overrun|AA$user_barcode|",
30
    # response to block patron is a patron status message
31
    pat => qr/^24Y{4}[ Y]{10}000$datepat/o,
32
    fields => [],
33
};
34
35
my $checkin_template = {
36
	id => 'Checkout: cleanup: check in item',
37
	msg => "09N20050102    08423620060113    084235AP$item_owner|AO$instid|AB$item_barcode|ACterminal password|",
38
	pat => qr/^101YNN$datepat/o,
39
	fields => [],
40
};
41
42
my $checkout_test_template = {
43
    id => 'Checkout: valid item, valid patron',
44
    msg => "11YN20060329    203000                  AO$instid|AA$user_barcode|AB$item_barcode|AC|",
45
    pat => qr/^121NNY$datepat/,
46
    fields => [
47
	       $SIPtest::field_specs{(FID_INST_ID)},
48
	       $SIPtest::field_specs{(FID_SCREEN_MSG)},
49
	       $SIPtest::field_specs{(FID_PRINT_LINE)},
50
	       { field    => FID_PATRON_ID,
51
		 pat      => qr/^$user_barcode$/o,
52
		 required => 1, },
53
	       { field    => FID_ITEM_ID,
54
		 pat      => qr/^$item_barcode$/o,
55
		 required => 1, },
56
	       { field    => FID_TITLE_ID,
57
		 pat      => qr/^$item_title\s*$/o,
58
		 required => 1, },
59
	       { field    => FID_DUE_DATE,
60
		 pat      => $textpat,
61
		 required => 1, },
62
	       { field    => FID_FEE_TYPE,
63
		 pat      => qr/^\d{2}$/,
64
		 required => 0, },
65
	       { field    => FID_SECURITY_INHIBIT,
66
		 pat      => qr/^[YN]$/,
67
		 required => 0, },
68
	       { field    => FID_CURRENCY,
69
		 pat      => qr/^$currency$/o,
70
		 required => 0, },
71
	       { field    => FID_FEE_AMT,
72
		 pat      => qr/^[.0-9]+$/,
73
		 required => 0, },
74
	       { field    => FID_MEDIA_TYPE,
75
		 pat      => qr/^\d{3}$/,
76
		 required => 0, },
77
	       { field    => FID_ITEM_PROPS,
78
		 pat      => $textpat,
79
		 required => 0, },
80
	       { field    => FID_TRANSACTION_ID,
81
		 pat      => $textpat,
82
		 required => 0, },
83
	       ], };
84
85
my @tests = (
86
	     $SIPtest::login_test,
87
	     $SIPtest::sc_status_test,
88
	     clone($checkout_test_template),
89
	     # Don't check the item in, because we're about to test renew
90
	     );
91
92
my $test;
93
94
## Renewal OK
95
## Test this by checking out exactly the same book a second time.
96
## The only difference should be that the "Renewal OK" flag should now
97
## be 'Y'.
98
#$test = clone($checkout_test_template);
99
#$test->{id} = 'Checkout: patron renewal';
100
#$test->{pat} = qr/^121YNY$datepat/;
101
102
#push @tests, $test;
103
104
# NOW check it in
105
106
push @tests, $checkin_template;
107
108
# Valid Patron, item with diacritical in the title
109
#$test = clone($checkout_test_template);
110
#
111
#$test->{id} = 'Checkout: valid patron, diacritical character in title';
112
#$test->{msg} =~ s/AB$item_barcode/AB$item_diacritic_barcode/;
113
114
#foreach my $i (0 .. (scalar @{$test->{fields}})-1) {
115
#    my $field =  $test->{fields}[$i];
116
117
#    if ($field->{field} eq FID_ITEM_ID) {
118
#	$field->{pat} = qr/^$item_diacritic_barcode$/;
119
#    } elsif ($field->{field} eq FID_TITLE_ID) {
120
#	$field->{pat} = qr/^$item_diacritic_title\s*$/;
121
#    } elsif ($field->{field} eq FID_OWNER) {
122
#	$field->{pat} = qr/^$item_diacritic_owner$/;
123
#    }
124
#}
125
126
#push @tests, $test;
127
128
#$test = clone($checkin_template);
129
#$test->{msg} =~ s/AB$item_barcode/AB$item_diacritic_barcode/;
130
#push @tests, $test;
131
132
# Valid Patron, Invalid Item_id
133
$test = clone($checkout_test_template);
134
135
$test->{id} = 'Checkout: valid patron, invalid item';
136
$test->{msg} =~ s/AB$item_barcode/ABno-barcode/o;
137
$test->{pat} = qr/^120NUN$datepat/;
138
delete $test->{fields};
139
$test->{fields} = [
140
		   $SIPtest::field_specs{(FID_INST_ID)},
141
		   $SIPtest::field_specs{(FID_SCREEN_MSG)},
142
		   $SIPtest::field_specs{(FID_PRINT_LINE)},
143
		   { field    => FID_PATRON_ID,
144
		     pat      => qr/^$user_barcode$/o,
145
		     required => 1, },
146
		   { field    => FID_ITEM_ID,
147
		     pat      => qr/^no-barcode$/,
148
		     required => 1, },
149
		   { field    => FID_TITLE_ID,
150
		     pat      => qr/^$/,
151
		     required => 1, },
152
		   { field    => FID_DUE_DATE,
153
		     pat      => qr/^$/,
154
		     required => 1, },
155
		   { field    => FID_VALID_PATRON,
156
		     pat      => qr/^Y$/,
157
		     required => 1, },
158
		   ];
159
160
push @tests, $test;
161
162
# Invalid patron, valid item
163
$test = clone($checkout_test_template);
164
$test->{id} = 'Checkout: invalid patron, valid item';
165
$test->{msg} =~ s/AA$user_barcode/AAberick/;
166
$test->{pat} = qr/^120NUN$datepat/;
167
delete $test->{fields};
168
$test->{fields} = [
169
		   $SIPtest::field_specs{(FID_INST_ID)},
170
		   $SIPtest::field_specs{(FID_SCREEN_MSG)},
171
		   $SIPtest::field_specs{(FID_PRINT_LINE)},
172
		   { field    => FID_PATRON_ID,
173
		     pat      => qr/^berick$/,
174
		     required => 1, },
175
		   { field    => FID_ITEM_ID,
176
		     pat      => qr/^$item_barcode$/o,
177
		     required => 1, },
178
		   { field    => FID_TITLE_ID,
179
		     pat      => qr/^$item_title\s*$/o,
180
		     required => 1, },
181
		   { field    => FID_DUE_DATE,
182
		     pat      => qr/^$/,
183
		     required => 1, },
184
		   { field    => FID_VALID_PATRON,
185
		     pat      => qr/^N$/,
186
		     required => 1, },
187
		   ];
188
189
push @tests, $test;
190
191
# Needed: tests for blocked patrons, patrons with excessive
192
# fines/fees, magnetic media, charging fees to borrow items.
193
194
## Blocked patron
195
#$test = clone($checkout_test_template);
196
#$test->{id} = 'Checkout: Blocked patron';
197
#$test->{pat} = qr/^120NUN$datepat/;
198
#delete $test->{fields};
199
#$test->{fields} = [
200
#		   $SIPtest::field_specs{(FID_INST_ID)},
201
#		   $SIPtest::field_specs{(FID_SCREEN_MSG)},
202
#		   $SIPtest::field_specs{(FID_PRINT_LINE)},
203
#		   { field    => FID_PATRON_ID,
204
#		     pat      => qr/^$user_barcode$/,
205
#		     required => 1, },
206
#		   { field    => FID_VALID_PATRON,
207
#		     pat      => qr/^Y$/,
208
#		     required => 1, },
209
#		  ];
210
#
211
#push @tests, $patron_disable_template, $test, $patron_enable_template;
212
#
213
SIPtest::run_sip_tests(@tests);
214
215
1;
(-)a/C4/SIP/t/04patron_status.t (-100 lines)
Lines 1-100 Link Here
1
#!/usr/bin/perl
2
# patron_status: test Patron Status Response
3
4
use strict;
5
use warnings;
6
use FindBin qw($Bin);
7
use lib "$Bin";
8
use Clone qw(clone);
9
10
use C4::SIP::Sip::Constants qw(:all);
11
use SIPtest qw(:user1 :basic);
12
13
my $patron_status_test_template = {
14
    id => 'Patron Status: valid patron, no patron password',
15
    msg => "2300120060101    084237AO$instid|AA$user_barcode|AC$password|",
16
    pat => qr/^24[ Y]{14}001$datepat/,
17
    fields => [
18
	       $SIPtest::field_specs{(FID_INST_ID)},
19
	       $SIPtest::field_specs{(FID_SCREEN_MSG)},
20
	       $SIPtest::field_specs{(FID_PRINT_LINE)},
21
	       { field    => FID_PATRON_ID,
22
		 pat      => qr/^$user_barcode$/,
23
		 required => 1, },
24
	       { field    => FID_PERSONAL_NAME,
25
		 pat      => qr/^$user_fullname$/,
26
		 required => 1, },
27
	       { field    => FID_VALID_PATRON,
28
		 pat      => qr/^Y$/,
29
		 # Not required by the spec, but by the test
30
		 required => 1, },
31
	       $SIPtest::field_specs{(FID_CURRENCY)},
32
	       { field    => FID_FEE_AMT,
33
		 pat      => $textpat,
34
		 required => 0, },
35
	       ], };
36
37
my @tests = (
38
	     $SIPtest::login_test,
39
	     $SIPtest::sc_status_test,
40
	     clone($patron_status_test_template),
41
	     );
42
43
# Invalid patron
44
my $test = clone($patron_status_test_template);
45
46
$test->{id} = 'Patron Status: invalid id';
47
$test->{msg} =~ s/AA$user_barcode\|/AAbad_userid|/;
48
49
# The test assumes that the language sent by the terminal is
50
# just echoed back for invalid patrons.
51
$test->{pat} = qr/^24Y[ Y]{13}001$datepat/; 
52
53
delete $test->{fields};
54
$test->{fields} = [
55
		   $SIPtest::field_specs{(FID_INST_ID)},
56
		   $SIPtest::field_specs{(FID_SCREEN_MSG)},
57
		   $SIPtest::field_specs{(FID_PRINT_LINE)},
58
		   { field    => FID_PATRON_ID,
59
		     pat      => qr/^bad_userid$/,
60
		     required => 1, },
61
		   { field    => FID_PERSONAL_NAME,
62
		     pat      => qr/^$/,
63
		     required => 1, },
64
		   { field    => FID_VALID_PATRON,
65
		     pat      => qr/^N$/,
66
		     required => 1, },
67
		   ];
68
69
push @tests, $test;
70
71
# Valid patron, invalid patron password
72
$test = clone($patron_status_test_template);
73
$test->{id} = 'Patron Status: Valid patron, invalid patron password';
74
$test->{msg} .= (FID_PATRON_PWD) . 'badpwd|';
75
delete $test->{fields};
76
$test->{fields} = [
77
		 $SIPtest::field_specs{(FID_INST_ID)},
78
		 $SIPtest::field_specs{(FID_SCREEN_MSG)},
79
		 $SIPtest::field_specs{(FID_PRINT_LINE)},
80
		 { field    => FID_PATRON_ID,
81
		   pat      => qr/^$user_barcode$/,
82
		   required => 1, },
83
		 { field    => FID_PERSONAL_NAME,
84
		   pat      => qr/^$user_fullname$/,
85
		   required => 1, },
86
		 { field    => FID_VALID_PATRON,
87
		   pat      => qr/^Y$/,
88
		   required => 1, },
89
		 { field    => FID_VALID_PATRON_PWD,
90
		   pat      => qr/^N$/,
91
		   required => 1, },
92
		 ];
93
push @tests, $test;
94
95
# TODO: Need multiple patrons to test each individual 
96
# status field
97
98
SIPtest::run_sip_tests(@tests);
99
100
1;
(-)a/C4/SIP/t/05block_patron.t (-47 lines)
Lines 1-47 Link Here
1
#!/usr/bin/perl
2
# block_patron: test Block Patron Response
3
4
use strict;
5
use warnings;
6
use FindBin qw($Bin);
7
use lib "$Bin";
8
use Clone qw(clone);
9
10
use C4::SIP::Sip::Constants qw(:all);
11
12
use SIPtest qw(:basic :user1);
13
14
my $block_patron_test_template = {
15
    id => 'Block Patron: valid patron, card not retained',
16
    msg => "01N20060102    084238AO$instid|ALThis card is blocked.|AA$user_barcode|AC$password|",
17
    # response to block patron is a patron status message
18
    pat => qr/^24Y[ Y]{13}000$datepat/,
19
    fields => [
20
	       $SIPtest::field_specs{(FID_INST_ID)},
21
	       $SIPtest::field_specs{(FID_SCREEN_MSG)},
22
	       $SIPtest::field_specs{(FID_PRINT_LINE)},
23
	       { field    => FID_PATRON_ID,
24
		 pat      => qr/^$user_barcode$/o,
25
		 required => 1, },
26
	       { field    => FID_PERSONAL_NAME,
27
		 pat      => qr/^$user_fullname$/o,
28
		 required => 1, },
29
	       { field    => FID_VALID_PATRON,
30
		 pat      => qr/^Y$/,
31
		 # Not required by the spec, but by the test
32
		 required => 1, },
33
	       $SIPtest::field_specs{(FID_CURRENCY)},
34
	       { field    => FID_FEE_AMT,
35
		 pat      => $textpat,
36
		 required => 0, },
37
	       ], };
38
39
my @tests = (
40
	     $SIPtest::login_test,
41
	     $SIPtest::sc_status_test,
42
	     clone($block_patron_test_template),
43
	     );
44
45
         SIPtest::run_sip_tests(@tests);
46
47
1;
(-)a/C4/SIP/t/06patron_enable.t (-146 lines)
Lines 1-146 Link Here
1
#!/usr/bin/perl
2
# patron_enable: test  Patron Enable Response
3
4
use strict;
5
use warnings;
6
use FindBin qw($Bin);
7
use lib "$Bin";
8
use Clone qw(clone);
9
10
use C4::SIP::Sip::Constants qw(:all);
11
12
use SIPtest qw(:basic :user1);
13
14
my $patron_enable_test_template = {
15
    id => 'Patron Enable: valid patron',
16
    msg => "2520060102    084238AOUWOLS|AA$user_barcode|",
17
    pat => qr/^26 {4}[ Y]{10}000$datepat/,
18
    fields => [
19
	       $SIPtest::field_specs{(FID_INST_ID)},
20
	       $SIPtest::field_specs{(FID_SCREEN_MSG)},
21
	       $SIPtest::field_specs{(FID_PRINT_LINE)},
22
	       { field    => FID_PATRON_ID,
23
		 pat      => qr/^$user_barcode$/,
24
		 required => 1, },
25
	       { field    => FID_PERSONAL_NAME,
26
		 pat      => qr/^$user_fullname$/,
27
		 required => 1, },
28
	       { field    => FID_VALID_PATRON,
29
		 pat      => qr/^Y$/,
30
		 # Not required by the spec, but by the test
31
		 required => 1, },
32
	       ], };
33
34
# We need to disable the valid patron before we can
35
# ensure that they were properly enabled.
36
my $patron_disable_test_template = {
37
    id => 'Patron Enable: block patron (prep to test enabling)',
38
    msg => "01N20060102    084238AO$instid|ALBlocked patron for SIP test.|AA$user_barcode|",
39
    # response to block patron is a patron status message
40
    pat => qr/^24Y{4}[ Y]{10}000$datepat/,
41
    fields => [
42
	       $SIPtest::field_specs{(FID_INST_ID)},
43
	       { field    => FID_PATRON_ID,
44
		 pat      => qr/^$user_barcode$/,
45
		 required => 1, },
46
	       { field    => FID_PERSONAL_NAME,
47
		 pat      => qr/^$user_fullname$/,
48
		 required => 1, },
49
	       { field    => FID_VALID_PATRON,
50
		 pat      => qr/^Y$/,
51
		 # Not required by the spec, but by the test
52
		 required => 1, },
53
	       ], };
54
55
my @tests = (
56
	     $SIPtest::login_test,
57
	     $SIPtest::sc_status_test,
58
	     $patron_disable_test_template,
59
	     clone($patron_enable_test_template),
60
	     );
61
62
my $test;
63
64
# Valid patron, valid password
65
$test = clone($patron_enable_test_template);
66
$test->{id} = "Patron Enable: valid patron, valid password";
67
$test->{msg} .= FID_PATRON_PWD . "$user_pin|";
68
$test->{pat} = qr/^26 {4}[ Y]{10}000$datepat/;
69
delete $test->{fields};
70
$test->{fields} = [
71
		   $SIPtest::field_specs{(FID_INST_ID)},
72
		   $SIPtest::field_specs{(FID_SCREEN_MSG)},
73
		   $SIPtest::field_specs{(FID_PRINT_LINE)},
74
		   { field    => FID_PATRON_ID,
75
		     pat      => qr/^$user_barcode$/,
76
		     required => 1, },
77
		   { field    => FID_PERSONAL_NAME,
78
		     pat      => qr/^$user_fullname$/,
79
		     required => 1, },
80
		   { field    => FID_VALID_PATRON,
81
		     pat      => qr/^Y$/,
82
		     # Not required by the spec, but by the test
83
		     required => 1, },
84
		   { field    => FID_VALID_PATRON_PWD,
85
		     pat      => qr/^Y$/,
86
		     required => 1, },
87
		   ];
88
89
push @tests, $patron_disable_test_template, $test;
90
91
# Valid patron, invalid password
92
$test = clone($patron_enable_test_template);
93
$test->{id} = "Patron Enable: valid patron, invalid password";
94
$test->{msg} .= FID_PATRON_PWD . 'bad password|';
95
$test->{pat} = qr/^26[ Y]{14}000$datepat/;
96
delete $test->{fields};
97
$test->{fields} = [
98
		   $SIPtest::field_specs{(FID_INST_ID)},
99
		   $SIPtest::field_specs{(FID_SCREEN_MSG)},
100
		   $SIPtest::field_specs{(FID_PRINT_LINE)},
101
		   { field    => FID_PATRON_ID,
102
		     pat      => qr/^$user_barcode$/,
103
		     required => 1, },
104
		   { field    => FID_PERSONAL_NAME,
105
		     pat      => qr/^$user_fullname$/,
106
		     required => 1, },
107
		   { field    => FID_VALID_PATRON,
108
		     pat      => qr/^Y$/,
109
		     # Not required by the spec, but by the test
110
		     required => 1, },
111
		   { field    => FID_VALID_PATRON_PWD,
112
		     pat      => qr/^N$/,
113
		     required => 1, },
114
		   ];
115
116
push @tests, $patron_disable_test_template, $test;
117
# After this test, the patron is left disabled, so re-enable
118
push @tests, $patron_enable_test_template;
119
120
# Invalid patron
121
$test = clone($patron_enable_test_template);
122
$test->{id} =~ s/valid/invalid/;
123
$test->{msg} =~ s/AA$user_barcode\|/AAbad_barcode|/;
124
$test->{pat} =  qr/^26Y{4}[ Y]{10}000$datepat/;
125
delete $test->{fields};
126
$test->{fields} = [
127
		   $SIPtest::field_specs{(FID_INST_ID)},
128
		   $SIPtest::field_specs{(FID_SCREEN_MSG)},
129
		   $SIPtest::field_specs{(FID_PRINT_LINE)},
130
		   { field    => FID_PATRON_ID,
131
		     pat      => qr/^bad_barcode$/,
132
		     required => 1, },
133
		   { field    => FID_PERSONAL_NAME,
134
		     pat      => qr/^$/,
135
		     required => 1, },
136
		   { field    => FID_VALID_PATRON,
137
		     pat      => qr/^N$/,
138
		     # Not required by the spec, but by the test
139
		     required => 1, },
140
		   ];
141
142
push @tests, $test;
143
144
SIPtest::run_sip_tests(@tests);
145
146
1;
(-)a/C4/SIP/t/07hold.t (-191 lines)
Lines 1-191 Link Here
1
#!/usr/bin/perl
2
# patron_enable: test  Patron Enable Response
3
4
use strict;
5
use warnings;
6
use FindBin qw($Bin);
7
use lib "$Bin";
8
use Clone qw(clone);
9
10
use C4::SIP::Sip::Constants qw(:all);
11
12
use SIPtest qw(:basic :user1 :user2 :item1 :item2);
13
14
my $hold_test_template = {
15
    id => "Place Hold: valid item ($item_barcode), valid patron ($user_barcode)",	 #BS could be another branch
16
    msg => "15+20060415    110158BW20060815    110158|BS$instid|BY2|AO$instid|AA$user_barcode|AB$item_barcode|",
17
    pat => qr/^161Y$datepat/,
18
    fields => [
19
	       $SIPtest::field_specs{(FID_INST_ID)},
20
	       $SIPtest::field_specs{(FID_SCREEN_MSG)},
21
	       $SIPtest::field_specs{(FID_PRINT_LINE)},
22
	       { field    => FID_PATRON_ID,
23
		 pat      => qr/^$user_barcode$/,
24
		 required => 1, },
25
	       { field    => FID_EXPIRATION,
26
		 pat      => $datepat,
27
		 required => 0, },
28
	       { field    => FID_QUEUE_POS,
29
		 pat      => qr/^1$/,
30
		 required => 0, },
31
	       { field    => FID_PICKUP_LOCN,
32
		 pat      => qr/^$item_owner$/,
33
		 required => 0, },
34
	       { field    => FID_TITLE_ID,
35
		 pat      => qr/^$item_title$/,
36
		 required => 0, },
37
	       { field    => FID_ITEM_ID,
38
		 pat      => qr/^$item_barcode$/,
39
		 required => 0, },
40
	       ],};
41
42
my $tmp_msg = "6300020060329    201700          AO$instid|AA$user_barcode|";
43
my $hold_count_test_template0 = {
44
    id => "Confirm patron ($user_barcode) has 0 holds",
45
    msg => $tmp_msg,
46
    pat => qr/^64 [ Y]{13}\d{3}${datepat}0000(\d{4}){5}/,
47
    fields => [],
48
};
49
my $hold_count_test_template1 = {
50
    id => "Confirm patron ($user_barcode) has 1 hold",
51
    msg => $tmp_msg,
52
    pat => qr/^64 [ Y]{13}\d{3}${datepat}((0001(\d{4}){4}0000)|(0000(\d{4}){4}0001))/,
53
		# The tricky part at the end here is because we don't know whether
54
		# the hold will count as "waiting" or unavailable.
55
		# But it will be one or the other!
56
    fields => [],
57
};
58
59
my @tests = (
60
	     $SIPtest::login_test,								# 1
61
	     $SIPtest::sc_status_test,							# 2
62
	     $hold_test_template, $hold_count_test_template1,	# 3,4
63
	     );
64
65
my $test;
66
67
# Hold Queue: second hold placed on item
68
$test = clone($hold_test_template);
69
$test->{id} = "Place 2nd hold on item ($item_barcode) for user ($user2_barcode)";
70
$test->{msg} =~ s/AA$user_barcode\|/AA$user2_barcode|/;
71
$test->{pat} = qr/^161N$datepat/;
72
foreach my $i (0 .. (scalar @{$test->{fields}})-1) {
73
	my $field =  $test->{fields}[$i];
74
	if ($field->{field} eq FID_PATRON_ID) {
75
		$field->{pat} = qr/^$user2_barcode$/;
76
	} elsif ($field->{field} eq FID_QUEUE_POS) {
77
		$field->{pat} = qr/^2$/;
78
	}
79
}
80
81
push @tests, $test;											# 5
82
83
# Cancel hold: valid hold
84
$test = clone($hold_test_template);
85
$test->{id} = "Cancel Hold: valid hold for user ($user_barcode)";
86
$test->{msg} =~ s/\+/-/;
87
$test->{pat} = qr/^161[NY]$datepat/;
88
delete $test->{fields};
89
$test->{fields} = [
90
		   $SIPtest::field_specs{(FID_INST_ID)},
91
		   $SIPtest::field_specs{(FID_SCREEN_MSG)},
92
		   $SIPtest::field_specs{(FID_PRINT_LINE)},
93
		   { field    => FID_PATRON_ID,
94
		     pat      => qr/^$user_barcode$/,
95
		     required => 1, },
96
		   ];
97
98
push @tests, $test, $hold_count_test_template0;				# 6,7
99
100
# Cancel Hold: no hold on item
101
# $test is already set up to cancel a hold, just change
102
# the field tests
103
$test = clone($test);
104
$test->{id} = 'Cancel Hold: no hold on specified item';
105
$test->{pat} = qr/^160N$datepat/;
106
107
push @tests, $test, $hold_count_test_template0;				# 8,9
108
109
# Cleanup: cancel 2nd user's hold too.
110
$test = clone($hold_test_template);
111
$test->{id} = "Cancel hold: cleanup hold for 2nd patron ($user2_barcode)";
112
$test->{msg} =~ s/\+/-/;
113
$test->{msg} =~ s/$user_barcode/$user2_barcode/;
114
$test->{pat} = qr/^161[NY]$datepat/;
115
delete $test->{fields};
116
$test->{fields} = [
117
		   $SIPtest::field_specs{(FID_INST_ID)},
118
		   $SIPtest::field_specs{(FID_SCREEN_MSG)},
119
		   $SIPtest::field_specs{(FID_PRINT_LINE)},
120
		   { field    => FID_PATRON_ID,
121
		     pat      => qr/^$user2_barcode$/,
122
		     required => 1, },
123
		   ];
124
125
push @tests, $test;											# 11
126
127
# Place hold: valid patron, item, invalid patron pwd
128
$test = clone($hold_test_template);
129
$test->{id} = 'Place hold: invalid patron password';
130
$test->{msg} .= FID_PATRON_PWD . 'bad password|';
131
$test->{pat} = qr/^160N$datepat/;
132
delete $test->{fields};
133
$test->{fields} = [
134
		   $SIPtest::field_specs{(FID_INST_ID)},
135
		   $SIPtest::field_specs{(FID_SCREEN_MSG)},
136
		   $SIPtest::field_specs{(FID_PRINT_LINE)},
137
		   { field    => FID_PATRON_ID,
138
		     pat      => qr/^$user_barcode$/,
139
		     required => 1, },
140
		   ];
141
142
push @tests, $test, $hold_count_test_template0;				# 12,13
143
144
# Place hold: invalid patron
145
$test = clone($hold_test_template);
146
$test->{id} = 'Place hold: invalid patron';
147
$test->{msg} =~ s/AA$user_barcode\|/AAbad_barcode|/;
148
$test->{pat} = qr/^160N$datepat/;
149
delete $test->{fields};
150
$test->{fields} = [
151
		   $SIPtest::field_specs{(FID_INST_ID)},
152
		   $SIPtest::field_specs{(FID_SCREEN_MSG)},
153
		   $SIPtest::field_specs{(FID_PRINT_LINE)},
154
		   { field    => FID_PATRON_ID,
155
		     pat      => qr/^bad_barcode$/,
156
		     required => 1, },
157
		   ];
158
159
# There's no patron to check the number of holds against
160
push @tests, $test;											# 14
161
162
# Place hold: invalid item
163
$test = clone($hold_test_template);
164
$test->{id} = 'Place hold: invalid item';
165
$test->{msg} =~ s/AB$item_barcode\|/ABnosuchitem|/;
166
$test->{pat} = qr/^160N$datepat/;
167
delete $test->{fields};
168
$test->{fields} = [
169
		   $SIPtest::field_specs{(FID_INST_ID)},
170
		   $SIPtest::field_specs{(FID_SCREEN_MSG)},
171
		   $SIPtest::field_specs{(FID_PRINT_LINE)},
172
		   { field    => FID_PATRON_ID,
173
		     pat      => qr/^$user_barcode$/,
174
		     required => 1, },
175
		   { field    => FID_ITEM_ID,
176
		     pat      => qr/^nosuchitem$/,
177
		     required => 0, },
178
		   ];
179
180
push @tests, $test, $hold_count_test_template0;				# 15
181
182
# Still need tests for:
183
#     - valid patron not permitted to place holds
184
#     - valid item, not allowed to hold item
185
#     - multiple holds on item: correct queue position management
186
#     - setting and verifying hold expiry dates (requires ILS support)
187
#     - 3M checkin extensions for hold/ILL routing
188
189
SIPtest::run_sip_tests(@tests);
190
191
1;
(-)a/C4/SIP/t/08checkin.t (-86 lines)
Lines 1-86 Link Here
1
#!/usr/bin/perl
2
# checkin: test Checkin Response
3
4
use strict;
5
use warnings;
6
use FindBin qw($Bin);
7
use lib "$Bin";
8
use Clone qw(clone);
9
10
use C4::SIP::Sip::Constants qw(:all);
11
use SIPtest qw(:basic :user1 :item1);
12
13
# Checkout response, format:
14
# code: 12
15
# success: 0 or 1
16
# renewal ok: Y or N
17
# magnetic media: Y, N or U
18
# desensitize: Y or N
19
# date
20
21
# Checkin response, format:
22
# code: 10
23
# success: 0 or 1
24
# resensitize: Y or N
25
# magnetic media: Y, N or U
26
# alert: Y or N
27
# date
28
29
my $checkout_template = {
30
    id  => "Checkin: prep: check out item ($item_barcode)",
31
    msg => "11YN20060329    203000                  AO$instid|AA$user_barcode|AB$item_barcode|AC|",
32
    pat => qr/^121N[NYU][NY]$datepat/,
33
    fields => [],
34
};
35
36
my $checkin_test_template = {
37
    id  => "Checkin: Item ($item_barcode) is checked out",
38
    msg => "09N20060102    08423620060113    084235AP$item_owner|AO$instid|AB$item_barcode|AC$password|",
39
    pat => qr/^101[NY][NYU]N$datepat/,
40
    fields => [
41
        $SIPtest::field_specs{(FID_INST_ID   )},
42
        $SIPtest::field_specs{(FID_SCREEN_MSG)},
43
        $SIPtest::field_specs{(FID_PRINT_LINE)},
44
        { field    => FID_PATRON_ID,
45
          pat      => qr/^$user_barcode$/,
46
          required => 1, },
47
        { field    => FID_ITEM_ID,
48
          pat      => qr/^$item_barcode$/,
49
          required => 1, },
50
        { field    => FID_PERM_LOCN,
51
          pat      => $textpat,
52
          required => 1, },
53
        { field    => FID_TITLE_ID,
54
          pat      => qr/^$item_title\s*$/,
55
          required => 1, }, # not required by the spec.
56
        { field    => FID_DESTINATION_LOCATION,
57
          pat      => qr/^$item_owner\s*$/,
58
          required => 0, }, # 3M Extension
59
   ],};
60
61
my @tests = (
62
	$SIPtest::login_test,
63
	$SIPtest::sc_status_test,
64
	$checkout_template,
65
	$checkin_test_template,
66
	);
67
68
my $test;
69
70
# Checkin item that's not checked out.  Basically, this
71
# is identical to the first case, except the header says that
72
# the ILS didn't check the item in, and there's no patron id.
73
$test = clone($checkin_test_template);
74
$test->{id}  = 'Checkin: Item not checked out';
75
$test->{pat} = qr/^100[NY][NYU][NY]$datepat/o;
76
$test->{fields} = [grep $_->{field} ne FID_PATRON_ID, @{$test->{fields}}];
77
78
push @tests, $test;
79
80
# 
81
# Still need tests for magnetic media
82
# 
83
84
SIPtest::run_sip_tests(@tests);
85
86
1;
(-)a/C4/SIP/t/09renew.t (-155 lines)
Lines 1-155 Link Here
1
#!/usr/bin/perl
2
# renew: test Renew Response
3
4
use strict;
5
use warnings;
6
use FindBin qw($Bin);
7
use lib "$Bin";
8
use Clone qw(clone);
9
10
use C4::SIP::Sip::Constants qw(:all);
11
12
use SIPtest qw(:basic :user1 :item1);
13
14
my $checkout_template = {
15
	id => "Renew:    prep: check out item ($item_barcode) to patron ($user_barcode)",
16
	msg => "11YN20060329    203000                  AO$instid|AA$user_barcode|AB$item_barcode|AC|",
17
	pat => qr/^121NNY$datepat/,
18
	fields => [],
19
};
20
21
my $checkin_template = {
22
	id => "Renew: cleanup: check in item ($item_barcode)",
23
	msg => "09N20060102    08423620060113    084235AP$item_owner|AO$instid|AB$item_barcode|AC$password|",
24
	pat => qr/^101YNN$datepat/,
25
	fields => [],
26
};
27
28
# my $hold_template = {
29
# id => 'Renew: prep: place hold on item',
30
# msg =>"15+20060415    110158BW20060815    110158|BSTaylor|BY2|AO$instid|AAmiker|AB$item_barcode|",
31
# pat => qr/^161N$datepat/,
32
# fields => [],
33
# };
34
#
35
# my $cancel_hold_template = {
36
# id => 'Renew: cleanup: cancel hold on item',
37
# msg =>"15-20060415    110158BW20060815    110158|BSTaylor|BY2|AO$instid|AAmiker|AB$item_barcode|",
38
# pat => qr/^161[NY]$datepat/,
39
# fields => [],
40
# };
41
#
42
43
my $renew_test_template = {
44
	id => "Renew: RENEW 1, item ($item_barcode) to patron ($user_barcode), renewal OK, no 3rd party, no fees",
45
	msg => "29NN20060102    084236                  AO$instid|AA$user_barcode|AB$item_barcode|",
46
	pat => qr/^301Y[UN][UN]$datepat/,
47
	fields => [
48
	      $SIPtest::field_specs{(FID_INST_ID)},
49
	      $SIPtest::field_specs{(FID_SCREEN_MSG)},
50
	      $SIPtest::field_specs{(FID_PRINT_LINE)},
51
	      { field    => FID_PATRON_ID,
52
			pat      => qr/^$user_barcode$/,
53
			required => 1, },
54
	      { field    => FID_ITEM_ID,
55
			pat      => qr/^$item_barcode$/,
56
			required => 1, },
57
	      { field    => FID_TITLE_ID,
58
			pat      => qr/^$item_title\s*$/,
59
			required => 1, },
60
	      { field    => FID_DUE_DATE,
61
			pat      => qr/^$datepat$/,
62
			required => 1, },
63
	      { field    => FID_SECURITY_INHIBIT,
64
			pat      => qr/^[YN]$/,
65
			required => 0, },
66
	],
67
};
68
69
my @tests = (
70
	$SIPtest::login_test,
71
	$SIPtest::sc_status_test,
72
	$checkout_template,
73
	$renew_test_template,
74
);
75
76
SIPtest::run_sip_tests(@tests); exit;   # debug hack
77
78
my $test;
79
80
# Renew: item checked out, identify by title
81
#$test = clone($renew_test_template);
82
#$test->{id} = 'Renew: identify item by title';
83
#$test->{msg} =~ s/AB$item_barcode\|/AJ$item_title|/;
84
## Everything else should be the same
85
#push @tests, $test;
86
#
87
## Renew: Item checked out, but another patron has placed a hold
88
#$test = clone($renew_test_template);
89
#$test->{id} = 'Renew: Item has outstanding hold';
90
#$test->{pat} = qr/^300NUN$datepat/;
91
#foreach my $field (@{$test->{fields}}) {
92
#    if ($field->{field} eq FID_DUE_DATE || $field->{field} eq FID_TITLE_ID) {
93
#	$field->{pat} = qr/^$/;
94
#    }
95
#}
96
#
97
#push @tests, $hold_template, $test, $cancel_hold_template;
98
#
99
#
100
# Tests for impossible renewals.
101
#
102
# Renew: item not checked out.  Basically the same, except
103
# for the leader test.
104
105
$test = clone($renew_test_template);
106
$test->{id} = 'Renew: item not checked out at all';
107
$test->{pat} = qr/^300NUN$datepat/;
108
foreach my $field (@{$test->{fields}}) {
109
	if ($field->{field} eq FID_DUE_DATE) {
110
		$field->{pat} = qr/^$/;
111
	} elsif ($field->{field} eq FID_TITLE_ID) {
112
		$field->{pat} = qr/^($item_title\s*|)$/;
113
	}
114
}
115
116
push @tests, $checkin_template, $test;
117
118
$test = clone($renew_test_template);
119
$test->{id} = 'Renew: Invalid item (bad-item)';
120
$test->{msg} =~ s/AB[^|]+/ABbad-item/;
121
$test->{pat} = qr/^300NUN$datepat/;
122
foreach my $field (@{$test->{fields}}) {
123
	if ($field->{field} eq FID_TITLE_ID || $field->{field} eq FID_DUE_DATE) {
124
		$field->{pat} = qr/^$/;
125
	} elsif ($field->{field} eq FID_ITEM_ID) {
126
		$field->{pat} = qr/^bad-item$/;
127
	}
128
}
129
130
push @tests, $test;
131
132
$test = clone($renew_test_template);
133
$test->{id} = 'Renew: Invalid user (bad_barcode)';
134
$test->{msg} =~ s/AA$user_barcode/AAbad_barcode/;
135
$test->{pat} = qr/^300NUN$datepat/;
136
foreach my $field (@{$test->{fields}}) {
137
	if ($field->{field} eq FID_DUE_DATE) {
138
		$field->{pat} = qr/^$/;
139
	} elsif ($field->{field} eq FID_PATRON_ID) {
140
		$field->{pat} = qr/^bad_barcode$/;
141
	} elsif ($field->{field} eq FID_TITLE_ID) {
142
		$field->{pat} = qr/^($item_title\s*|)$/;
143
	}
144
}
145
146
push @tests, $test;
147
148
# Still need tests for
149
#     - renewing a for-fee item
150
#     - patrons that are not permitted to renew
151
#     - renewing item that has reached limit on number of renewals
152
153
SIPtest::run_sip_tests(@tests);
154
155
1;
(-)a/C4/SIP/t/10renew_all.t (-132 lines)
Lines 1-132 Link Here
1
#!/usr/bin/perl
2
# renew_all: test Renew All Response
3
4
use strict;
5
use warnings;
6
use FindBin qw($Bin);
7
use lib "$Bin";
8
use Clone qw(clone);
9
10
use C4::SIP::Sip::Constants qw(:all);
11
12
use SIPtest qw(:basic :user1 :item1 :item2);
13
14
my $enable_template = {
15
    id => 'Renew All: prep: enable patron permissions',
16
    msg => "2520060102    084238AO$instid|AA$user_barcode|",
17
    pat => qr/^26 {4}[ Y]{10}000$datepat/,
18
    fields => [],
19
};
20
21
# reset_checkin_templates will be used to reset the status of the items if needed
22
# If "make test" is used (all tests at once), after the tests 08 and 09, the item stays checked out and this raises an error here
23
# so we begin with a Checkin, awaiting for the minimal answer : ^10 (Checkin response)
24
# Both results (101 and 100, for OK and NON OK) must be accepted, because if we run this test alone, the item won't necessarily be checked out
25
# and the checkin attempt will then result in a "100" code, which is not a problem (we are just preparing the renewal tests)
26
my @reset_checkin_templates = (
27
    {
28
        id => "Renew All: prep: check in $item_barcode (used in previous tests)",
29
        msg => "09N20060102    08423620060113    084235AP$item_owner|AO$instid|AB$item_barcode|AC$password|",
30
        pat    => qr/^10/,
31
        fields => [],
32
    },
33
    {
34
        id => "Renew All: prep: check in $item2_barcode (used in previous tests)",
35
        msg => "09N20060102    08423620060113    084235AP$item2_owner|AO$instid|AB$item2_barcode|AC$password|",
36
        pat    => qr/^10/,
37
        fields => [],
38
    }
39
);
40
41
# Checkout as a preparation for renewal
42
my @checkout_templates = (
43
	{    id => "Renew All: prep: check out $item_barcode to $user_barcode",
44
		msg => "11YN20060329    203000                  AO$instid|AA$user_barcode|AB$item_barcode|AC$password|",
45
		pat => qr/^121NNY$datepat/,
46
		fields => [],},
47
	{    id => "Renew All: prep: check out $item2_barcode to $user_barcode",
48
		msg => "11YN20060329    203000                  AO$instid|AA$user_barcode|AB$item2_barcode|AC$password|",
49
		pat => qr/^121NNY$datepat/,
50
		fields => [],}
51
);
52
53
my $renew_all_test_template = {
54
	 id => "Renew All: patron ($user_barcode) with 1 item ($item_barcode) checked out, no patron password",
55
	msg => "6520060102    084236AO$instid|AA$user_barcode|",
56
	pat => qr/^66100010000$datepat/,
57
	fields => [
58
       $SIPtest::field_specs{(FID_INST_ID)},
59
       $SIPtest::field_specs{(FID_SCREEN_MSG)},
60
       $SIPtest::field_specs{(FID_PRINT_LINE)},
61
       { field   => FID_RENEWED_ITEMS,
62
	 	pat      => qr/^$item_barcode$/,
63
	 	required => 1, },
64
	]
65
};
66
67
# check the book in, when done testing
68
my @checkin_templates = (
69
    {
70
        id => "Renew All: prep: check in $item_barcode",
71
        msg => "09N20060102    08423620060113    084235AP$item_owner|AO$instid|AB$item_barcode|AC$password|",
72
        pat    => qr/^101YNN$datepat/,
73
        fields => [],
74
    },
75
    {
76
        id => "Renew All: prep: check in $item2_barcode",
77
        msg => "09N20060102    08423620060113    084235AP$item2_owner|AO$instid|AB$item2_barcode|AC$password|",
78
        pat    => qr/^101YNN$datepat/,
79
        fields => [],
80
    }
81
);
82
83
84
85
my @tests = (
86
	     $SIPtest::login_test,
87
	     $SIPtest::sc_status_test,
88
	     );
89
90
my $test;
91
92
# WIP?
93
$test = clone($renew_all_test_template);
94
$test->{id} = 'Renew All: Valid patron, two items checked out';
95
$test->{pat} = qr/^66100020000$datepat/;
96
foreach my $i (0 .. (scalar @{$test->{fields}})-1) {
97
	my $field =  $test->{fields}[$i];
98
	if ($field->{field} eq FID_RENEWED_ITEMS) {
99
		$field->{pat} = qr/^$item_barcode\|$item2_barcode$/;
100
	}
101
}
102
103
#push @tests, @checkout_templates[0..1], $renew_all_test_template, @checkin_templates[0..1];
104
105
$test = clone($renew_all_test_template);
106
$test->{id} = 'Renew All: valid patron, invalid patron password';
107
$test->{msg} .= (FID_PATRON_PWD) . 'bad_pwd|';
108
$test->{pat} = qr/^66000000000$datepat/;
109
delete $test->{fields};
110
$test->{fields} = [
111
	       $SIPtest::field_specs{(FID_INST_ID)},
112
	       $SIPtest::field_specs{(FID_SCREEN_MSG)},
113
	       $SIPtest::field_specs{(FID_PRINT_LINE)},
114
		  ];
115
116
push @tests, $reset_checkin_templates[0], $checkout_templates[0], $test, $checkin_templates[0];
117
118
$test = clone($renew_all_test_template);
119
$test->{id} = 'Renew All: invalid patron';
120
$test->{msg} =~ s/AA$user_barcode/AAbad_barcode/;
121
$test->{pat} = qr/^66000000000$datepat/;
122
delete $test->{fields};
123
$test->{fields} = [
124
	       $SIPtest::field_specs{(FID_INST_ID)},
125
	       $SIPtest::field_specs{(FID_SCREEN_MSG)},
126
	       $SIPtest::field_specs{(FID_PRINT_LINE)},
127
		  ];
128
push @tests, $test;
129
130
SIPtest::run_sip_tests(@tests);
131
132
1;
(-)a/C4/SIP/t/11item_info.t (-43 lines)
Lines 1-43 Link Here
1
#!/usr/bin/perl
2
# Item Information test
3
4
use strict;
5
use warnings;
6
use FindBin qw($Bin);
7
use lib "$Bin";
8
use Clone qw(clone);
9
10
use C4::SIP::Sip::Constants qw(:all);
11
use SIPtest qw(:basic :user1 :item1);
12
13
my $item_info_test_template = {
14
	id  => "Item Information: check info for available item ($item_barcode)",
15
	msg => "1720060110    215612AO$instid|AB$item_barcode|",
16
	pat => qr/^180[13]0201$datepat/, # status of 'other' or 'available'
17
	fields => [
18
		$SIPtest::field_specs{(FID_SCREEN_MSG)},
19
		$SIPtest::field_specs{(FID_PRINT_LINE)},
20
		{ field    => FID_ITEM_ID,
21
		  pat      => qr/^$item_barcode$/,
22
		  required => 1, },
23
		{ field    => FID_TITLE_ID,
24
		  pat      => qr/^$item_title\s*$/,
25
		  required => 1, },
26
		{ field    => FID_MEDIA_TYPE,
27
		  pat      => qr/^\d{3}$/,
28
		  required => 0, },
29
		{ field    => FID_OWNER,
30
		  pat      => qr/^$item_owner$/,
31
		  required => 0, },
32
	],
33
};
34
35
my @tests = (
36
	$SIPtest::login_test,
37
	$SIPtest::sc_status_test,
38
	$item_info_test_template,
39
);
40
41
SIPtest::run_sip_tests(@tests);
42
43
1;
(-)a/C4/SIP/t/Makefile (-17 lines)
Lines 1-17 Link Here
1
# 
2
# 
3
# 
4
5
TESTS = 000_sc_config_auth.t \
6
	00sc_status.t 01patron_status.t 02patron_info.t 03checkout.t \
7
	04patron_status.t 05block_patron.t 06patron_enable.t 07hold.t \
8
	08checkin.t 09renew.t 10renew_all.t 11item_info.t
9
10
OILS_TESTS = 00sc_status.t 01patron_status.t 02patron_info.t 03checkout.t \
11
	08checkin.t 09renew.t 11item_info.t 05block_patron.t
12
13
test-openils:
14
	prove -I.. $(OILS_TESTS)
15
16
test:
17
	prove -I../ -I./ $(TESTS)
(-)a/C4/SIP/t/README (-50 lines)
Lines 1-50 Link Here
1
CONFIGURING THE TEST SUITE
2
3
Before you can run the test suite, you need to configure certain
4
information about the SIP server and the ILS data in the file
5
SIPtest.pm.
6
7
RUNNING THE TESTS
8
9
Every file tests a different protocol transaction.
10
Unfortunately, a lot of test cases are missing, but the basics
11
are tested, as are most of the simple error conditions (invalid
12
users, unknown items, checking in item that's not checked out).
13
14
To run a single test, just run
15
16
   perl -I.. <file>
17
18
If the test fails, the output should be pretty clear about what
19
went wrong (assuming you can read raw SIP packets).
20
21
To run all the tests, just type
22
23
   make test
24
25
Right now, that will run tests for functionality that isn't
26
supported in the Evergreen environment (the two main cases are
27
enable patron and hold management).  To run just the Evergreen tests, use
28
29
       make test-openils
30
31
which will run just the tests
32
33
	00sc_status.t
34
	01patron_status.t
35
	02patron_info.t
36
	03checkout.t
37
	06patron_enable.t
38
	08checkin.t
39
	09renew.t
40
	11item_info.t
41
	05block_patron.t
42
43
NOTE: the Block Patron tests are run last because "Patron Enable"
44
isn't supported.  Thus, after running the "Block Patron" test,
45
manual intervention is required to unblock the test patron.
46
47
The Renew All tests will fail when running the stub "ILS"
48
implementation unless there's only one ILS server running.  This
49
won't be a problem for any real backend implementation that
50
properly manages the database of users and items.
(-)a/C4/SIP/t/SIPtest.pm (-282 lines)
Lines 1-281 Link Here
1
package SIPtest;
2
3
use strict;
4
use warnings;
5
6
use Exporter;
7
use vars qw(@ISA @EXPORT @EXPORT_OK %EXPORT_TAGS);
8
9
use Data::Dumper;
10
11
BEGIN {
12
	@ISA = qw(Exporter);
13
	%EXPORT_TAGS = (
14
		auth  => [qw(&api_auth)],
15
		basic => [qw($datepat $textpat $login_test $sc_status_test
16
						$instid $instid2 $currency $server $username $password)],
17
    # duplicate user1 and item1 as user2 and item2
18
    # w/ tags like $user2_pin instead of $user_pin
19
		user1 => [qw($user_barcode  $user_pin  $user_fullname  $user_homeaddr  $user_email
20
						$user_phone  $user_birthday  $user_ptype  $user_inet)],
21
        user2 => [qw($user2_barcode  $user._pin  $user2_fullname  $user2_homeaddr  $user2_email
22
                        $user2_phone  $user2_birthday  $user2_ptype  $user2_inet)],
23
		item1 => [qw($item_barcode  $item_title  $item_owner )],
24
        item2 => [qw($item2_barcode  $item2_title  $item2_owner )],
25
    # we've got item3_* also
26
        item3 => [qw($item3_barcode  $item3_title  $item3_owner )],
27
		diacritic => [qw($item_diacritic_barcode $item_diacritic_title $item_diacritic_owner)],
28
	);
29
	# From perldoc Exporter
30
	# Add all the other ":class" tags to the ":all" class, deleting duplicates
31
	my %seen;
32
	push @{$EXPORT_TAGS{all}},
33
		grep {!$seen{$_}++} @{$EXPORT_TAGS{$_}} foreach keys %EXPORT_TAGS;
34
	Exporter::export_ok_tags('all');	# Anything in a tag is in OK_EXPORT
35
	# print Dumper(\%EXPORT_TAGS);		# Uncomment if you want to see the results of these tricks.
36
}
37
38
# The number of tests is set in run_sip_tests() below, based
39
# on the size of the array of tests.
40
use Test::More;
41
use CGI qw ( -utf8 );
42
43
use IO::Socket::INET;
44
use C4::SIP::Sip qw(:all);
45
use C4::SIP::Sip::Checksum qw(verify_cksum);
46
use C4::SIP::Sip::Constants qw(:all);
47
48
use C4::Auth qw(&check_api_auth);
49
use C4::Context;
50
51
# TODO: just read SIPconfig.xml and extract what we can....
52
# 
53
# Configuration parameters to run the test suite
54
#
55
our $instid   = 'CPL';  # branchcode
56
our $instid2  = 'FPL';  # branchcode
57
our $currency = 'USD';	# 'CAD';
58
our $server   = 'localhost:6001'; 	# Address of the SIP server
59
60
# SIP username and password to connect to the server.
61
# See SIPconfig.xml for the correct values.
62
our $username = 'term1';
63
our $password = 'term1';
64
65
# ILS Information
66
67
# NOTE: make sure to escape the data for use in RegExp.
68
# Valid user barcode and corresponding user password/pin and full name
69
our $user_barcode = '23529001000463';
70
our $user_pin     = 'fn5zS';
71
our $user_fullname= 'Edna Acosta';
72
our $user_homeaddr= '7896 Library Rd\.';
73
our $user_email   = 'patron\@liblime\.com';
74
our $user_phone   = '\(212\) 555-1212';
75
our $user_birthday= '19800424';   # YYYYMMDD, ANSI X3.30
76
our $user_ptype   = 'PT';
77
our $user_inet    = 'Y';
78
79
# Another valid user
80
our $user2_barcode = '23529000240482';
81
our $user2_pin     = 'jw937';
82
our $user2_fullname= 'Jamie White';
83
our $user2_homeaddr= '937 Library Rd\.';
84
our $user2_email   = 'patron\@liblime\.com';
85
our $user2_phone   = '\(212\) 555-1212';
86
our $user2_birthday= '19500422';    # YYYYMMDD, ANSI X3.30
87
our $user2_ptype   = 'T';
88
our $user2_inet    = 'Y';
89
90
# Valid item barcode and corresponding title
91
our $item_barcode = '502326000005';
92
our $item_title   = 'How I became a pirate /';
93
our $item_owner   = 'CPL';
94
95
# Another valid item
96
our $item2_barcode = '502326000011';
97
our $item2_title   = 'The biggest, smallest, fastest, tallest things you\'ve ever heard of /';
98
our $item2_owner   = 'CPL';
99
100
# A third valid item
101
our $item3_barcode = '502326000240';
102
our $item3_title   = 'The girl who owned a city /';
103
our $item3_owner   = 'FPL';
104
105
# An item with a diacritical in the title
106
our $item_diacritic_barcode = '502326001030';
107
our $item_diacritic_titlea  = 'Hari Poṭer u-geviʻa ha-esh /';
108
our $item_diacritic_owner   = 'CPL';
109
110
# End configuration
111
112
# Pattern for a SIP datestamp, to be used by individual tests to
113
# match timestamp fields (duh).
114
our $datepat = '\d{8} {4}\d{6}';
115
116
# Pattern for a random text field (may be empty)
117
our $textpat = qr/^[^|]*$/;
118
119
our %field_specs = (
120
	    (FID_SCREEN_MSG) => { field    => FID_SCREEN_MSG,
121
					pat      => $textpat,
122
					required => 0, },
123
	    (FID_PRINT_LINE) => { field    => FID_PRINT_LINE,
124
					pat      => $textpat,
125
					required => 0, },
126
	    (FID_INST_ID)    => { field    => FID_INST_ID,
127
					pat      => qr/^$instid$/o,
128
					required => 1, },
129
	    (FID_HOLD_ITEMS_LMT)=> { field    => FID_HOLD_ITEMS_LMT,
130
					pat      => qr/^\d{4}$/,
131
					required => 0, },
132
	    (FID_OVERDUE_ITEMS_LMT)=> { field    => FID_OVERDUE_ITEMS_LMT,
133
					pat      => qr/^\d{4}$/,
134
					required => 0, },
135
	    (FID_CHARGED_ITEMS_LMT)=> { field    => FID_CHARGED_ITEMS_LMT,
136
					pat      => qr/^\d{4}$/,
137
					required => 0, },
138
	    (FID_VALID_PATRON) => { field    => FID_VALID_PATRON,
139
				    pat      => qr/^[NY]$/,
140
				    required => 0, },
141
	    (FID_VALID_PATRON_PWD)=> { field    => FID_VALID_PATRON_PWD,
142
					pat      => qr/^[NY]$/,
143
					required => 0, },
144
	    (FID_CURRENCY)   => { field    => FID_CURRENCY,
145
					pat      => qr/^$currency$/io,
146
					required => 0, },
147
	);
148
149
# Login and SC Status are always the first two messages that
150
# the terminal sends to the server, so just create the test
151
# cases here and reference them in the individual test files.
152
153
our $login_test = { id => 'login',
154
		    msg => "9300CN$username|CO$password|CPThe floor|",
155
		    pat => qr/^941/,
156
		    fields => [], };
157
158
our $sc_status_test = { id => 'SC status',
159
			msg => '9910302.00',
160
			pat => qr/^98[YN]{6}\d{3}\d{3}$datepat(2\.00|1\.00)/,
161
			fields => [
162
				   $field_specs{(FID_SCREEN_MSG)},
163
				   $field_specs{(FID_PRINT_LINE)},
164
				   $field_specs{(FID_INST_ID)},
165
				   { field    => 'AM',
166
				     pat      => $textpat,
167
				     required => 0, },
168
				   { field    => 'BX',
169
				     pat      => qr/^[YN]{16}$/,
170
				     required => 1, },
171
				   { field    => 'AN',
172
				     pat      => $textpat,
173
				     required => 0, },
174
				   ],
175
			};
176
177
sub one_msg {
178
    my ($sock, $test, $seqno) = @_;
179
    my $resp;
180
    my %fields;
181
182
    # If reading or writing fails, then the server's dead,
183
    # so there's no point in continuing.
184
    if ( !write_msg( { seqno => $seqno }, $test->{msg}, $sock ) ) {
185
        BAIL_OUT("Write failure in $test->{id}");
186
    }
187
188
    my $rv = sysread( $sock, $resp, 10000000 ); # 10000000 is a big number
189
190
    if ( !$rv ) {
191
        BAIL_OUT("Read failure in $test->{id}");
192
    }
193
194
	chomp($resp);
195
	$resp =~ tr/\cM//d;
196
	$resp =~ s/\015?\012$//;
197
	chomp($resp);
198
199
	if (!verify_cksum($resp)) {
200
		fail("$test->{id} checksum($resp)");
201
		return;
202
	}
203
	if ($resp !~ $test->{pat}) {
204
		fail("match leader $test->{id}");
205
		diag("Response '$resp' doesn't match pattern '$test->{pat}'");
206
		return;
207
	}
208
209
	# Split the tagged fields of the response into (name, value)
210
	# pairs and stuff them into the hash.
211
	$resp =~ $test->{pat};
212
	%fields = substr($resp, $+[0]) =~ /(..)([^|]*)\|/go;
213
214
    # print STDERR 	"one_msg ( test ) : " . Dumper($test) . "\n" .
215
    # 				"one_msg (fields) : " . Dumper(\%fields);
216
	if (!defined($test->{fields})) {
217
		diag("TODO: $test->{id} field tests not written yet");
218
	} else {
219
	# If there are no tagged fields, then 'fields' should be an
220
	# empty list which will automatically skip this loop
221
	foreach my $ftest (@{$test->{fields}}) {
222
	    my $field = $ftest->{field};
223
224
	    if ($ftest->{required} && !exists($fields{$field})) {
225
		fail("$test->{id}: required field '$field' not found in '$resp'");
226
		return;
227
	    }
228
229
	    if (exists($fields{$field}) && ($fields{$field} !~ $ftest->{pat})) {
230
		fail("$test->{id} field test $field");
231
		diag("Field '$field' pattern '$ftest->{pat}' fails to match value '$fields{$field}' in message '$resp'");
232
		return;
233
	    }
234
	}
235
    }
236
    pass("$test->{id}");
237
    return;
238
}
239
240
sub api_auth {
241
	# AUTH
242
	$ENV{REMOTE_USER} = $username;
243
	my $query = CGI->new();
244
	$query->param(userid   => $username);
245
	$query->param(password => $password);
246
	my ($status, $cookie, $sessionID) = check_api_auth($query, {circulate=>1}, "intranet");
247
	print STDERR "check_api_auth returns " . ($status || 'undef') . "\n";
248
	# print STDERR "api_auth userenv = " . &dump_userenv;
249
	return $status;
250
}
251
252
sub dump_userenv {
253
	my $userenv = C4::Context->userenv;
254
	return "# userenv: EMPTY\n" unless ($userenv);
255
	my $userbranch = $userenv->{branch};
256
	return "# userenv: " . Dumper($userenv)
257
		. ($userbranch ? "BRANCH FOUND: $userbranch\n" : "NO BRANCH FOUND\n");
258
}
259
260
sub run_sip_tests {
261
    my ($sock, $seqno);
262
263
    $Sip::error_detection = 1;
264
    $/ = "\015\012";	# must use correct record separator
265
266
    $sock = IO::Socket::INET->new(PeerAddr => $server,
267
				 Type     => SOCK_STREAM);
268
269
    BAIL_OUT('failed to create connection to server') unless $sock;
270
271
    $seqno = 1;
272
	# print STDERR "Number of tests : ",  scalar (@_), "\n";
273
    plan tests => scalar(@_);
274
    foreach my $test (@_) {
275
		# print STDERR "Test $seqno:" . Dumper($test);
276
		one_msg($sock, $test, $seqno++);
277
		$seqno %= 10;		# sequence number is one digit
278
    }
279
}
280
281
1;
282
- 

Return to bug 26700