Imported Upstream version 3.3.3
[debian/amanda] / installcheck / Amanda_IPC_Binary.pl
1 # Copyright (c) 2009-2012 Zmanda, Inc.  All Rights Reserved.
2 #
3 # This program is free software; you can redistribute it and/or
4 # modify it under the terms of the GNU General Public License
5 # as published by the Free Software Foundation; either version 2
6 # of the License, or (at your option) any later version.
7 #
8 # This program is distributed in the hope that it will be useful, but
9 # WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
10 # or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
11 # for more details.
12 #
13 # You should have received a copy of the GNU General Public License along
14 # with this program; if not, write to the Free Software Foundation, Inc.,
15 # 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
16 #
17 # Contact information: Zmanda Inc, 465 S. Mathilda Ave., Suite 300
18 # Sunnyvale, CA 94086, USA, or: http://www.zmanda.com
19
20 use Test::More tests => 15;
21 use strict;
22 use warnings;
23
24 use lib "@amperldir@";
25 use Installcheck;
26 use Amanda::IPC::Binary;
27 use IO::Handle;
28 use Amanda::Debug;
29 use Data::Dumper;
30 use Carp;
31 use POSIX;
32
33 ##
34 # Define a test protocol
35
36 package TestProtocol;
37 use base "Amanda::IPC::Binary";
38 use Amanda::IPC::Binary;
39
40 # cmd_id's
41 use constant SIMPLE => 1;
42 use constant FOO => 2;
43 use constant BAR => 3;
44
45 # arg_id's
46 use constant NAME => 1;
47 use constant NICKNAME => 2;
48 use constant MANDATORY => 3;
49 use constant OPTIONAL => 4;
50
51 magic(0x1234);
52
53 command(SIMPLE);
54
55 command(FOO,
56     NAME, $IPC_BINARY_STRING,
57     NICKNAME, $IPC_BINARY_STRING);
58
59 command(BAR,
60     MANDATORY, 0,
61     OPTIONAL, $IPC_BINARY_OPTIONAL);
62
63 package main;
64
65 # set up debugging so debug output doesn't interfere with test results
66 Amanda::Debug::dbopen("installcheck");
67 Installcheck::log_test_output();
68
69 # and disable Debug's die() and warn() overrides
70 Amanda::Debug::disable_die_override();
71
72 sub to_bytes {
73     my @result;
74     for my $byte (@_) {
75         if (length($byte) == 1) {
76             push @result, $byte;
77         } else {
78             push @result, chr(hex($byte));
79         }
80     }
81     return join('', @result);
82 }
83
84 sub to_hex {
85     my ($bytes) = @_;
86     my @result;
87     for my $byte (split //, $bytes) {
88         if ((ord($byte) >= ord('a') and ord($byte) <= ord('z')) || $byte eq '-') {
89             push @result, $byte;
90         } else {
91             push @result, sprintf("%02x", ord($byte));
92         }
93     }
94
95     return join(" ", @result);
96 }
97
98 # first, try reading a pre-defined sequence of bytes; this lets us make sure
99 # byte-ordering is right on all platforms.
100 my $fh;
101 my $tmpfile = "$Installcheck::TMP/ipc-binary-test";
102 my ($chan, $msg);
103
104 open($fh, ">", $tmpfile);
105 print $fh to_bytes(
106     qw(12 34), # magic
107     qw(00 01), # cmd_id = SIMPLE
108     qw(00 00 00 0A), # length
109     qw(00 00), # count
110
111     qw(12 34), # magic
112     qw(00 02), # cmd_id = FOO
113     qw(00 00 00 22), # length
114     qw(00 02), # n_args
115     qw(00 00 00 07), # length
116     qw(00 01), # arg_id = NAME
117     qw(n i k o l a s), # data
118     qw(00 00 00 05), # length
119     qw(00 02), # arg_id = NICKNAME
120     qw(a t r u s), # data
121
122     qw(12 34), # magic
123     qw(00 03), # cmd_id = BAR
124     qw(00 00 00 1f), # length
125     qw(00 01), # n_args
126     qw(00 00 00 0f), # length
127     qw(00 03), # arg_id = MANDATORY
128     qw(v e r b o d e n - v r u c h t), # data
129
130     qw(12 34), # magic
131     qw(00 03), # cmd_id = BAR
132     qw(00 00 00 29), # length
133     qw(00 02), # n_args
134     qw(00 00 00 0a), # length
135     qw(00 03), # arg_id = MANDATORY
136     qw(o u d e - g e u z e), # data
137     qw(00 00 00 09), # length
138     qw(00 04), # arg_id = OPTIONAL
139     qw(r o d e n b a c h), # data
140 );
141 close($fh);
142
143 open($fh, "<", $tmpfile);
144
145 $chan = TestProtocol->new();
146
147 $msg = $chan->read_message($fh);
148 is($msg->{'cmd_id'}, TestProtocol::SIMPLE,
149     "got SIMPLE");
150
151 $msg = $chan->read_message($fh);
152 is($msg->{'cmd_id'}, TestProtocol::FOO,
153     "got FOO");
154 is($msg->{'args'}[TestProtocol::NAME], "nikolas",
155     "got NAME arg");
156 is($msg->{'args'}[TestProtocol::NICKNAME], "atrus",
157     "got NICKNAME arg");
158
159 $msg = $chan->read_message($fh);
160 is($msg->{'cmd_id'}, TestProtocol::BAR,
161     "got BAR");
162 is($msg->{'args'}[TestProtocol::MANDATORY], "verboden-vrucht",
163     "got MANDATORY arg");
164 is($msg->{'args'}[TestProtocol::OPTIONAL], undef,
165     "got no OPTIONAL arg");
166
167 $msg = $chan->read_message($fh);
168 is($msg->{'cmd_id'}, TestProtocol::BAR,
169     "got BAR");
170 is($msg->{'args'}[TestProtocol::MANDATORY], "oude-geuze",
171     "got MANDATORY arg");
172 is($msg->{'args'}[TestProtocol::OPTIONAL], "rodenbach",
173     "got OPTIONAL arg");
174
175 $msg = $chan->read_message($fh);
176 is($msg, undef, "no more messages");
177
178 close($fh);
179
180 # now try writing a set of messages, and check that the result is what it should be
181 open($fh, ">", $tmpfile);
182 $chan = TestProtocol->new();
183
184 ok($chan->write_message($fh, $chan->message(
185         TestProtocol::FOO,
186         TestProtocol::NAME, "james",
187         TestProtocol::NICKNAME, "jimmy")),
188     "wrote FOO message");
189
190 ok($chan->write_message($fh, $chan->message(
191         TestProtocol::BAR,
192         TestProtocol::MANDATORY, "absolutely",
193         TestProtocol::OPTIONAL, "maybe")),
194     "wrote BAR message with optional arg");
195
196 ok($chan->write_message($fh, $chan->message(
197         TestProtocol::BAR,
198         TestProtocol::MANDATORY, "yessir")),
199     "wrote BAR message without optional arg");
200
201 $chan->close();
202 close($fh);
203
204 my $bytes_expected = to_bytes(
205     qw(12 34), # magic
206     qw(00 02), # cmd_id = FOO
207     qw(00 00 00 20), # length
208     qw(00 02), # n_args
209     qw(00 00 00 05), # length
210     qw(00 01), # arg_id = NAME
211     qw(j a m e s), # data
212     qw(00 00 00 05), # length
213     qw(00 02), # arg_id = NICKNAME
214     qw(j i m m y), # data
215
216     qw(12 34), # magic
217     qw(00 03), # cmd_id = BAR
218     qw(00 00 00 25), # length
219     qw(00 02), # n_args
220     qw(00 00 00 0a), # length
221     qw(00 03), # arg_id = MANDATORY
222     qw(a b s o l u t e l y), # data
223     qw(00 00 00 05), # length
224     qw(00 04), # arg_id = OPTIONAL
225     qw(m a y b e), # data
226
227     qw(12 34), # magic
228     qw(00 03), # cmd_id = BAR
229     qw(00 00 00 16), # length
230     qw(00 01), # n_args
231     qw(00 00 00 06), # length
232     qw(00 03), # arg_id = MANDATORY
233     qw(y e s s i r), # data
234 );
235
236 # slurp the contents of the temp file and see if it matches
237 open($fh, "<", $tmpfile);
238 my $bytes_written = do { local $/; <$fh> };
239 close($fh);
240
241 is(to_hex($bytes_written),
242    to_hex($bytes_expected),
243     "got the expected bytes");