shlist

share and manage lists between multiple people
Log | Files | Refs

commit 4e707c8807132e20d4c5e5ec38c36c506562a1df
parent 2d97f8a96a33c9462ed79a2cd8a1aded799bd77d
Author: kyle <kyle@0x30.net>
Date:   Fri,  8 Jan 2016 20:46:09 -0700

tests: add test helper client that mimics a device

- new test helper client that acts like a real device id
  - it has state, and remembers when it has been registered
- the client provides methods for each of the message types
  - each message method can take optional status parameters
  - message methods automatically prepend the device id to the message
- convert entire testsuite to use new client
  - all tests become vastly simpler
  - it's much easier now to write test with more than 1 device participating

Diffstat:
Dserver/tests/bad_msg_type/server.log.good | 4----
Dserver/tests/bad_msg_type/test.pl | 8--------
Dserver/tests/bad_payload/Makefile | 1-
Dserver/tests/bad_payload/server.log.good | 18------------------
Dserver/tests/bad_payload/test.pl | 18------------------
Dserver/tests/bad_protocol_version/Makefile | 1-
Dserver/tests/bad_protocol_version/server.log.good | 4----
Dserver/tests/bad_protocol_version/test.pl | 8--------
Aserver/tests/client.pm | 307+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Mserver/tests/device_add/server.log.good | 1+
Mserver/tests/device_add/test.pl | 29++++++++++++++++-------------
Dserver/tests/device_ok/Makefile | 1-
Dserver/tests/device_ok/server.log.good | 6------
Dserver/tests/device_ok/test.pl | 17-----------------
Dserver/tests/double_register/Makefile | 1-
Dserver/tests/double_register/server.log.good | 6------
Dserver/tests/double_register/test.pl | 19-------------------
Mserver/tests/friend_add/server.log.good | 1+
Mserver/tests/friend_add/test.pl | 60+++++++++++++++++++-----------------------------------------
Mserver/tests/friend_delete_unit/test.pl | 41++++++++++++-----------------------------
Rserver/tests/bad_msg_type/Makefile -> server/tests/header/Makefile | 0
Aserver/tests/header/server.log.good | 16++++++++++++++++
Aserver/tests/header/test.pl | 28++++++++++++++++++++++++++++
Mserver/tests/list_add/server.log.good | 1+
Mserver/tests/list_add/test.pl | 42+++++++++++++++++-------------------------
Mserver/tests/list_join/test.pl | 55++++++++++++++++++-------------------------------------
Mserver/tests/list_join_unit/server.log.good | 1+
Mserver/tests/list_join_unit/test.pl | 40+++++++++++++---------------------------
Mserver/tests/list_leave/test.pl | 45++++++++++-----------------------------------
Mserver/tests/list_leave_unit/server.log.good | 1+
Mserver/tests/list_leave_unit/test.pl | 29++++++++++++-----------------
Mserver/tests/list_reference_counting/test.pl | 49+++++++++++++++++++------------------------------
Mserver/tests/lists_get/test.pl | 53++++++++++++++++++-----------------------------------
Mserver/tests/lists_get_other/test.pl | 61++++++++++++++++---------------------------------------------
Mserver/tests/multiple_friends_same_other_list/test.pl | 70++++++++++++++++++++++++++++++----------------------------------------
Mserver/tests/test.pm | 181++++++++-----------------------------------------------------------------------
Mserver/tests/two_lists_same_name/server.log.good | 7+++++++
Mserver/tests/two_lists_same_name/test.pl | 31++++++++++---------------------
38 files changed, 591 insertions(+), 670 deletions(-)

diff --git a/server/tests/bad_msg_type/server.log.good b/server/tests/bad_msg_type/server.log.good @@ -1,4 +0,0 @@ -accepting connections on <ip>:<port> (pid = <digits>) -new connection (pid = <digits>) -ssl ok, ver = 'TLSv1_2' cipher = 'ECDHE-RSA-AES128-SHA256' -error: unknown message type 47837 diff --git a/server/tests/bad_msg_type/test.pl b/server/tests/bad_msg_type/test.pl @@ -1,8 +0,0 @@ -#!/usr/bin/perl -I../ -use strict; -use warnings; -use test; - -# send an invalid message type -my $sock = new_socket(); -print $sock pack("nnn", 0, 47837, 0); diff --git a/server/tests/bad_payload/Makefile b/server/tests/bad_payload/Makefile @@ -1 +0,0 @@ -include ../test.mk diff --git a/server/tests/bad_payload/server.log.good b/server/tests/bad_payload/server.log.good @@ -1,18 +0,0 @@ -accepting connections on <ip>:<port> (pid = <digits>) -new connection (pid = <digits>) -ssl ok, ver = 'TLSv1_2' cipher = 'ECDHE-RSA-AES128-SHA256' -error: 7000 byte message too large -new connection (pid = <digits>) -ssl ok, ver = 'TLSv1_2' cipher = 'ECDHE-RSA-AES128-SHA256' -device_add: got 0 fields, expected 2 -device_ok: got 0 fields, expected 1 -friend_add: got 0 fields, expected 2 -friend_delete: got 0 fields, expected 2 -list_add: got 0 fields, expected 2 -list_item_add: got 0 fields, expected 1 -list_items_get: got 0 fields, expected 2 -list_join: got 0 fields, expected 2 -list_leave: got 0 fields, expected 2 -lists_get: got 0 fields, expected 1 -lists_get_other: got 0 fields, expected 1 -disconnected! diff --git a/server/tests/bad_payload/test.pl b/server/tests/bad_payload/test.pl @@ -1,18 +0,0 @@ -#!/usr/bin/perl -I../ -use strict; -use warnings; -use test; - -# send message that's too long -send_msg(new_socket(), 'device_add', "longstr" x 1000); - -# send message size 0 to all message types -my $sock = new_socket(); -for (sort @msg_str) { - send_msg($sock, $_, ""); - my ($msg_data) = recv_msg($sock, $_); - - my $msg = check_status($msg_data, 'err'); - my $msg_good = "wrong number of arguments"; - fail "unexpected error '$msg', expected '$msg_good'" if ($msg ne $msg_good); -} diff --git a/server/tests/bad_protocol_version/Makefile b/server/tests/bad_protocol_version/Makefile @@ -1 +0,0 @@ -include ../test.mk diff --git a/server/tests/bad_protocol_version/server.log.good b/server/tests/bad_protocol_version/server.log.good @@ -1,4 +0,0 @@ -accepting connections on <ip>:<port> (pid = <digits>) -new connection (pid = <digits>) -ssl ok, ver = 'TLSv1_2' cipher = 'ECDHE-RSA-AES128-SHA256' -error: unsupported protocol version 101 diff --git a/server/tests/bad_protocol_version/test.pl b/server/tests/bad_protocol_version/test.pl @@ -1,8 +0,0 @@ -#!/usr/bin/perl -I../ -use strict; -use warnings; -use test; - -# send an invalid message type -my $sock = new_socket(); -print $sock pack("nnn", 101, 0, 0); diff --git a/server/tests/client.pm b/server/tests/client.pm @@ -0,0 +1,307 @@ +package client; +use strict; +use warnings; + +use Data::Dumper; +use Errno; +use IO::Socket::SSL; +use Time::HiRes qw(usleep); +use test; + +require "msgs.pl"; +our (%msg_num, @msg_str); + +sub new { + my $class = shift; + + my $self = {}; + bless ($self, $class); + + $self->{sock} = undef; + my $timeout = time + 5; + while (1) { + $self->{sock} = new IO::Socket::SSL->new( + PeerHost => 'localhost', + PeerPort => $ENV{PORT} || 5437, + # this is needed because PeerHost is localhost and our + # SSL certificates are signed with amp.ca + SSL_verifycn_name => "absentmindedproductions.ca", + ); + + if ($!{ECONNREFUSED}) { + if (time > $timeout) { + fail "server not ready after 5 seconds"; + } + usleep(50 * 1000); + next; + } + + last; + } + + unless ($self->{sock}) { + die "failed connect or ssl handshake: $!,$SSL_ERROR"; + } + + $self->{device_id} = 'a'; + + return $self; +} + +sub list_add { + my $self = shift; + my $name = shift; + my $status = shift || 'ok'; + + my $list_data = communicate($self, 'list_add', $status, $name); + + # if we made it this far we know that $status is correct + return if ($status eq 'err'); + + save_list($self, $list_data); +} + +sub list_join { + my $self = shift; + my $list_id = shift; + my $status = shift || 'ok'; + + my $list_data = communicate($self, 'list_join', $status, $list_id); +} + +sub list_leave { + my $self = shift; + my $id = shift; + my $status = shift || 'ok'; + + my $list_data = communicate($self, 'list_leave', $status, $id); +} + +sub save_list { + my $self = shift; + my $list_data = shift; + + my ($id, $name, @members) = split("\0", $list_data); + my $list = { + id => $id, + name => $name, + members => \@members, + num_members => scalar(@members), + }; + push @{$self->{lists}}, $list; +} + +sub friend_add { + my $self = shift; + my $friend = shift; + my $status = shift || 'ok'; + + communicate($self, 'friend_add', $status, $friend); +} + +sub friend_delete { + my $self = shift; + my $friend = shift; + my $status = shift || 'ok'; + + communicate($self, 'friend_delete', $status, $friend); +} + +sub lists_get { + my $self = shift; + my $status = shift || 'ok'; + + my $list_data = communicate($self, 'lists_get', $status); + my @lists; + + for (split("\n", $list_data)) { + my ($id, $name, $num, @members) = split("\0", $_); + # fail "bad list" unless ($id && $name && @members != 0); + + my %tmp = ( + id => $id, + name => $name, + num => $num, + members => \@members, + num_members => scalar(@members), + ); + push @lists, \%tmp; + } + return @lists; +} + +sub lists_get_other { + my $self = shift; + my $status = shift || 'ok'; + + my $list_data = communicate($self, 'lists_get_other', $status); + my @lists; + + for (split("\n", $list_data)) { + my ($id, $name, @members) = split("\0", $_); + # fail "bad other list" unless ($id && $name && @members != 0); + + my %tmp = ( + id => $id, + name => $name, + members => \@members, + num_members => scalar(@members) + ); + push @lists, \%tmp; + } + return @lists; +} + +sub device_add { + my $self = shift; + my $phone_number = shift || '4038675309'; + my $exp_status = shift || 'ok'; + + # always reset error messages to guard against stale state + $self->{err_msg} = undef; + + send_msg($self, 'device_add', "$phone_number\0unix"); + my $msg = recv_msg($self, 'device_add'); + + my ($status, $device_id) = parse_status($self, $msg); + fail "wrong message status '$status'" if ($status ne $exp_status); + + $self->{phnum} = $phone_number; + $self->{device_id} = $device_id; +} + +sub communicate { + my ($self, $msg_type, $exp_status, @msg_args) = @_; + + # always reset error messages to guard against stale state + $self->{err_msg} = undef; + + # prepend device id to @msg_args array + unshift @msg_args, $self->{device_id}; + + send_msg($self, $msg_type, join("\0", @msg_args)); + my $msg = recv_msg($self, $msg_type); + + my ($status, $payload) = parse_status($self, $msg); + fail "wrong message status '$status'" if ($status ne $exp_status); + + return $payload; +} + +sub parse_status { + my ($self, $msg) = @_; + + my $first_null = index($msg, "\0"); + fail "no null byte found in response" if ($first_null == -1); + + my $msg_status = substr($msg, 0, $first_null); + my $msg_rest = substr($msg, $first_null + 1); + + # if this is an error message keep track of it right now + $self->{err_msg} = $msg_rest if ($msg_status eq 'err'); + + return ($msg_status, $msg_rest); +} + +sub send_msg { + my ($self, $msg_type, $payload) = @_; + + fail "invalid message type '$msg_type'" if (!exists $msg_num{$msg_type}); + + my $version = 0; + my $num = $msg_num{$msg_type}; + my $payload_len = length($payload); + my $header = pack("nnn", $version, $num, $payload_len); + + my $sent_bytes = 0; + $sent_bytes += send_all($self, $header, length($header)); + $sent_bytes += send_all($self, $payload, $payload_len); + + return $sent_bytes; +} + +sub send_all { + my ($self, $bytes, $bytes_total) = @_; + + my $bytes_written = $self->{sock}->syswrite($bytes); + + fail "write failed: $!" if (!defined $bytes_written); + fail "wrote $bytes_written instead of $bytes_total bytes" if ($bytes_written != $bytes_total); + + return $bytes_total; +} + +sub recv_msg { + my ($self, $exp_type) = @_; + + # read header part first + my $header = read_all($self, 6); + my ($version, $msg_type, $payload_size) = unpack("nnn", $header); + + fail "unsupported protocol version $version" if ($version != 0); + fail "unknown message type $msg_type" if ($msg_type >= @msg_str); + fail "$payload_size byte message too large" if ($payload_size > 4096); + + my $msg_name = $msg_str[$msg_type]; + fail "expected message type '$exp_type' but got '$msg_name'" if ($exp_type ne $msg_name); + + # don't try a read_all() of size 0 + return '' if ($payload_size == 0); + + my $payload = read_all($self, $payload_size); + return $payload; +} + +sub read_all { + my ($self, $bytes_left) = @_; + + my $data; + while ($bytes_left > 0) { + my $bytes_read = $self->{sock}->sysread(my $tmp, $bytes_left); + + fail "read failed: $!" unless (defined $bytes_read); + fail "read EOF on socket" if ($bytes_read == 0); + + $data .= $tmp; + $bytes_left -= $bytes_read; + } + + return $data; +} + +sub num_lists { + my $self = shift; + return scalar(@{$self->{lists}}); +} + +sub lists { + my $self = shift; + my $i = shift; + + my $num_lists = scalar(@{$self->{lists}}); + fail "tried accessing out of bounds index $i" if ($i > $num_lists); + + return $self->{lists}[$i]; +} + +sub lists_all { + my $self = shift; + return $self->{lists}; +} + +sub phnum { + my $self = shift; + return $self->{phnum}; +} + +sub device_id { + my $self = shift; + return $self->{device_id}; +} + +sub get_error { + my $self = shift; + return $self->{err_msg}; +} + +1; diff --git a/server/tests/device_add/server.log.good b/server/tests/device_add/server.log.good @@ -3,4 +3,5 @@ new connection (pid = <digits>) ssl ok, ver = 'TLSv1_2' cipher = 'ECDHE-RSA-AES128-SHA256' device_add: success, <digits>:<base64> os <base64> device_add: phone number '403867530&' invalid +device_add: phone number <digits> already exists disconnected! diff --git a/server/tests/device_add/test.pl b/server/tests/device_add/test.pl @@ -1,22 +1,25 @@ #!/usr/bin/perl -I../ use strict; use warnings; + +use client; use test; -# send a valid number and verify response is ok -my $sock = new_socket(); +my $A = client->new(); -send_msg($sock, 'device_add', "4038675309\0unix"); -my ($msg_data, $length) = recv_msg($sock, 'device_add'); +# basic sanity check on the device_add message type +my $phnum = rand_phnum(); +$A->device_add($phnum); -my $msg = check_status($msg_data, 'ok'); -fail "expected response length of 46, got $length" if ($length != 46); -fail "response '$msg' not base64" unless ($msg =~ m/^[a-zA-Z0-9+\/=]+$/); +my $devid = $A->device_id(); +my $length = length($devid); +fail "device id '$devid' not base64" unless ($devid =~ m/^[a-zA-Z0-9+\/=]+$/); +fail "expected device id length of 43, got $length" if ($length != 43); -# send a bad phone number and verify error response -send_msg($sock, 'device_add', "403867530&\0unix"); -($msg_data) = recv_msg($sock, 'device_add'); +# try adding a device with a bad phone number +$A->device_add('403867530&', 'err'); +fail_msg_ne 'the sent phone number is not a number', $A->get_error(); -$msg = check_status($msg_data, 'err'); -my $fail_msg = 'the sent phone number is not a number'; -fail "expected failure message '$fail_msg' but got '$msg'" if ($msg ne $fail_msg); +# try adding the same phone number again +$A->device_add($phnum, 'err'); +fail_msg_ne 'the sent phone number already exists', $A->get_error(); diff --git a/server/tests/device_ok/Makefile b/server/tests/device_ok/Makefile @@ -1 +0,0 @@ -include ../test.mk diff --git a/server/tests/device_ok/server.log.good b/server/tests/device_ok/server.log.good @@ -1,6 +0,0 @@ -accepting connections on <ip>:<port> (pid = <digits>) -new connection (pid = <digits>) -ssl ok, ver = 'TLSv1_2' cipher = 'ECDHE-RSA-AES128-SHA256' -device_add: success, <digits>:<base64> os <base64> -device_ok: device <base64> checking in -disconnected! diff --git a/server/tests/device_ok/test.pl b/server/tests/device_ok/test.pl @@ -1,17 +0,0 @@ -#!/usr/bin/perl -I../ -use strict; -use warnings; -use test; - -my $sock = new_socket(); - -send_msg($sock, 'device_add', "4038675309\0unix"); -my ($msg_data, $length) = recv_msg($sock, 'device_add'); - -my $device_id = check_status($msg_data, 'ok'); - -send_msg($sock, 'device_ok', $device_id); -($msg_data, $length) = recv_msg($sock, 'device_ok'); - -check_status($msg_data, 'ok'); -fail "expected response size 3, got $length" if ($length != 3); diff --git a/server/tests/double_register/Makefile b/server/tests/double_register/Makefile @@ -1 +0,0 @@ -include ../test.mk diff --git a/server/tests/double_register/server.log.good b/server/tests/double_register/server.log.good @@ -1,6 +0,0 @@ -accepting connections on <ip>:<port> (pid = <digits>) -new connection (pid = <digits>) -ssl ok, ver = 'TLSv1_2' cipher = 'ECDHE-RSA-AES128-SHA256' -device_add: success, <digits>:<base64> os <base64> -device_add: phone number <digits> already exists -disconnected! diff --git a/server/tests/double_register/test.pl b/server/tests/double_register/test.pl @@ -1,19 +0,0 @@ -#!/usr/bin/perl -I../ -use strict; -use warnings; -use test; - -my $sock = new_socket(); - -my $phnum = '4038675309'; -send_msg($sock, 'device_add', "$phnum\0unix"); -my ($msg_data) = recv_msg($sock, 'device_add'); - -check_status($msg_data, 'ok'); - -send_msg($sock, 'device_add', "$phnum\0unix"); -($msg_data) = recv_msg($sock, 'device_add'); - -my $msg = check_status($msg_data, 'err'); -my $msg_good = 'the sent phone number already exists'; -fail "unexpected error message '$msg', was expecting '$msg_good'" if ($msg ne $msg_good); diff --git a/server/tests/friend_add/server.log.good b/server/tests/friend_add/server.log.good @@ -1,6 +1,7 @@ accepting connections on <ip>:<port> (pid = <digits>) new connection (pid = <digits>) ssl ok, ver = 'TLSv1_2' cipher = 'ECDHE-RSA-AES128-SHA256' +friend_add: unknown device <base64> device_add: success, <digits>:<base64> os <base64> friend_add: <base64> adding <digits> friend_add: <base64> adding <digits> diff --git a/server/tests/friend_add/test.pl b/server/tests/friend_add/test.pl @@ -1,55 +1,33 @@ #!/usr/bin/perl -I../ use strict; use warnings; -use test; -# this test: -# - gets a new device id -# - adds a new friend +use client; +use test; -my $sock = new_socket(); -my $phnum = "4038675309"; -my $friend1 = "4033217654"; -my $friend2 = "4033217654bad"; -my $msg_good = "friends phone number is not a valid phone number"; +my $A = client->new(); -send_msg($sock, 'device_add', "$phnum\0unix"); -my ($msg_data) = recv_msg($sock, 'device_add'); +# try adding a friend with an invalid device id +$A->friend_add('12345', 'err'); +fail_msg_ne 'the client sent an unknown device id', $A->get_error(); -my $device_id = check_status($msg_data, 'ok'); +# all verifications after this use a valid device id +$A->device_add(rand_phnum()); # first verify that a normal add_friend message succeeds -send_msg($sock, 'friend_add', "$device_id\0$friend1"); -($msg_data) = recv_msg($sock, 'friend_add'); - -my $msg = check_status($msg_data, 'ok'); -fail "got response ph num '$msg' expected '$friend1'" if ($msg ne $friend1); - -# add the same friend, again -send_msg($sock, 'friend_add', "$device_id\0$friend1"); -($msg_data) = recv_msg($sock, 'friend_add'); +$A->friend_add('54321'); -$msg = check_status($msg_data, 'ok'); -fail "got response ph num '$msg' expected '$friend1'" if ($msg ne $friend1); +# add the same friend, again. not an error. +$A->friend_add('54321'); -# also verify that a non numeric friends phone number isn't accepted -send_msg($sock, 'friend_add', "$device_id\0$friend2"); -($msg_data) = recv_msg($sock, 'friend_add'); +# verify that a non numeric friends phone number isn't accepted +$A->friend_add('123asdf', 'err'); +fail_msg_ne 'friends phone number is not a valid phone number', $A->get_error(); -$msg = check_status($msg_data, 'err'); -fail "unexpected error message '$msg', expecting '$msg_good'" if ($msg ne $msg_good); - -# also verify an empty phone number isn't accepted -send_msg($sock, 'friend_add', "$device_id\0"); -($msg_data) = recv_msg($sock, 'friend_add'); - -$msg = check_status($msg_data, 'err'); -fail "unexpected error message '$msg', expecting '$msg_good'" if ($msg ne $msg_good); +# verify an empty phone number isn't accepted +$A->friend_add('', 'err'); +fail_msg_ne 'friends phone number is not a valid phone number', $A->get_error(); # also verify adding yourself doesn't work -send_msg($sock, 'friend_add', "$device_id\0$phnum"); -($msg_data) = recv_msg($sock, 'friend_add'); - -$msg = check_status($msg_data, 'err'); -$msg_good = "device cannot add itself as a friend"; -fail "unexecpted message '$msg', expected '$msg_good'" if ($msg ne $msg_good); +$A->friend_add($A->phnum(), 'err'); +fail_msg_ne 'device cannot add itself as a friend', $A->get_error(); diff --git a/server/tests/friend_delete_unit/test.pl b/server/tests/friend_delete_unit/test.pl @@ -1,43 +1,26 @@ #!/usr/bin/perl -I../ use strict; use warnings; +use client; use test; -my $sock = new_socket(); +my $A = client->new(); # try deleting a friend with an unknown device id -send_msg($sock, 'friend_delete', "baddeviceid\0phnum"); -my ($payload) = recv_msg($sock, 'friend_delete'); +$A->friend_delete('12345', 'err'); +fail_msg_ne 'the client sent an unknown device id', $A->get_error(); -# expecting error because device id is bad -my $msg = check_status($payload, 'err'); -my $msg_good = 'the client sent an unknown device id'; -fail "unexpected message '$msg', expected '$msg_good'" if ($msg ne $msg_good); - -# get a valid registration to use for the next tests -send_msg($sock, 'device_add', rand_phnum() . "\0unix"); -($payload) = recv_msg($sock, 'device_add'); - -my $device_id = check_status($payload, 'ok'); +# register for the next verifications +$A->device_add(rand_phnum()); # try deleting someone who is not your friend -send_msg($sock, 'friend_delete', "$device_id\0" . rand_phnum()); -($payload) = recv_msg($sock, 'friend_delete'); - -$msg = check_status($payload, 'err'); -$msg_good = 'friend sent for deletion was not a friend'; -fail "unexpected message '$msg', expected '$msg_good'" if ($msg ne $msg_good); +$A->friend_delete('12345', 'err'); +fail_msg_ne 'friend sent for deletion was not a friend', $A->get_error(); # also verify that a non numeric friends phone number isn't accepted -send_msg($sock, 'friend_delete', "$device_id\0someshitnum123"); -($payload) = recv_msg($sock, 'friend_delete'); - -$msg = check_status($payload, 'err'); -$msg_good = 'friends phone number is not a valid phone number'; -fail "unexpected message '$msg', expected '$msg_good'" if ($msg ne $msg_good); +$A->friend_delete('asdf123', 'err'); +fail_msg_ne 'friends phone number is not a valid phone number', $A->get_error(); # also verify an empty phone number isn't accepted -send_msg($sock, 'friend_delete', "$device_id\0"); -($payload) = recv_msg($sock, 'friend_delete'); - -check_status($payload, 'err'); +$A->friend_delete('', 'err'); +fail_msg_ne 'friends phone number is not a valid phone number', $A->get_error(); diff --git a/server/tests/bad_msg_type/Makefile b/server/tests/header/Makefile diff --git a/server/tests/header/server.log.good b/server/tests/header/server.log.good @@ -0,0 +1,16 @@ +accepting connections on <ip>:<port> (pid = <digits>) +new connection (pid = <digits>) +ssl ok, ver = 'TLSv1_2' cipher = 'ECDHE-RSA-AES128-SHA256' +error: unknown message type 47837 +new connection (pid = <digits>) +ssl ok, ver = 'TLSv1_2' cipher = 'ECDHE-RSA-AES128-SHA256' +error: unsupported protocol version 101 +new connection (pid = <digits>) +ssl ok, ver = 'TLSv1_2' cipher = 'ECDHE-RSA-AES128-SHA256' +error: 25143 byte message too large +new connection (pid = <digits>) +ssl ok, ver = 'TLSv1_2' cipher = 'ECDHE-RSA-AES128-SHA256' +disconnected! +new connection (pid = <digits>) +ssl ok, ver = 'TLSv1_2' cipher = 'ECDHE-RSA-AES128-SHA256' +disconnected! diff --git a/server/tests/header/test.pl b/server/tests/header/test.pl @@ -0,0 +1,28 @@ +#!/usr/bin/perl -I../ +use strict; +use warnings; + +use client; + +# Message header sanity checks. A new connection needed every time because +# server will disconnect on header errors. + +# send an invalid message number +my $client = client->new(); +$client->send_all(pack('nnn', 0, 47837, 0), 6); + +# send a bad protocol version +$client = client->new(); +$client->send_all(pack('nnn', 101, 0, 0), 6); + +# send a message length that's too long +$client = client->new(); +$client->send_all(pack('nnn', 0, 0, 25143), 6); + +# send a message length that's larger than the actual data sent +$client = client->new(); +$client->send_all(pack('nnnZ*', 0, 0, 5, 'ab'), 9); + +# send a partial header +$client = client->new(); +$client->send_all(pack('nn', 101, 69), 4); diff --git a/server/tests/list_add/server.log.good b/server/tests/list_add/server.log.good @@ -1,6 +1,7 @@ accepting connections on <ip>:<port> (pid = <digits>) new connection (pid = <digits>) ssl ok, ver = 'TLSv1_2' cipher = 'ECDHE-RSA-AES128-SHA256' +list_add: unknown device <base64> device_add: success, <digits>:<base64> os <base64> list_add: <string> list_add: adding first member devid = <base64> diff --git a/server/tests/list_add/test.pl b/server/tests/list_add/test.pl @@ -1,36 +1,28 @@ #!/usr/bin/perl -I../ use strict; use warnings; -use test; - -# this test sanity checks the new_list message. it checks that -# - a new list can be created, and has the correct fields -# - a list with no name is rejected -my $sock = new_socket(); -my $phnum = "4038675309"; -my $list_name = "this is a new list"; - -send_msg($sock, 'device_add', "$phnum\0unix"); -my ($payload) = recv_msg($sock, 'device_add'); +use client; +use test; +use Data::Dumper; -my $device_id = check_status($payload, 'ok'); +my $A = client->new(); -# verify a normal new_list request succeeds and returns good information -send_msg($sock, 'list_add', "$device_id\0$list_name"); -($payload) = recv_msg($sock, 'list_add'); +# check that sending a list_add message before registering doesn't work +$A->list_add('this is a new list', 'err'); +fail_msg_ne 'the client sent an unknown device id', $A->get_error(); -my $list_data = check_status($payload, 'ok'); -my ($id, $name, @members) = split("\0", $list_data); -my $id_length = length($id); +# make sure normal list_add works +$A->device_add(rand_phnum()); +$A->list_add(my $name = 'this is a new list'); +my $list = $A->lists(0); -fail "bad id length $id_length != 43" if ($id_length != 43); -fail "recv'd name '$name' not equal to '$list_name'" if ($name ne $list_name); -fail "list does not have exactly 1 member" if (@members != 1); -fail "got list member '$members[0]', expected '$phnum'" if ($members[0] ne $phnum); +fail_num_ne "bad id length", length($list->{id}), 43; +fail_msg_ne $name, $list->{name}; +fail_num_ne "wrong number of members", $list->{num_members}, 1; +fail_msg_ne $list->{members}->[0], $A->phnum(); # verify a new_list request with an empty list name succeeds -send_msg($sock, 'list_add', "$device_id\0"); -($payload) = recv_msg($sock, 'list_add'); +$A->list_add(''); -my $msg = check_status($payload, 'ok'); +fail_num_ne "wrong number of lists", $A->num_lists(), 2; diff --git a/server/tests/list_join/test.pl b/server/tests/list_join/test.pl @@ -1,49 +1,30 @@ #!/usr/bin/perl -I../ use strict; use warnings; -use test; - -my ($sock_1, $sock_2) = (new_socket(), new_socket()); -my ($phnum_1, $phnum_2) = ("4038675309", "4037082094"); -# create device 1 and 2 -send_msg($sock_1, 'device_add', "$phnum_1\0unix"); -my ($msg_data1) = recv_msg($sock_1, 'device_add'); +use client; +use test; -send_msg($sock_2, 'device_add', "$phnum_2\0unix"); -my ($msg_data2) = recv_msg($sock_2, 'device_add'); +my $A = client->new(); +my $B = client->new(); -my $device_id1 = check_status($msg_data1, 'ok'); -my $device_id2 = check_status($msg_data2, 'ok'); +$A->device_add(rand_phnum()); +$B->device_add(rand_phnum()); -# make device 1 and 2 mutual friends -send_msg($sock_1, 'friend_add', "$device_id1\0$phnum_2"); -recv_msg($sock_1, 'friend_add'); -send_msg($sock_2, 'friend_add', "$device_id2\0$phnum_1"); -recv_msg($sock_2, 'friend_add'); +# make A and B mutual friends +$A->friend_add($B->phnum()); +$B->friend_add($A->phnum()); +# A creates a new list my $list_name = "this is a new list"; +$A->list_add($list_name); -# device 1 creates new list -send_msg($sock_1, 'list_add', "$device_id1\0$list_name"); -my ($msg_data) = recv_msg($sock_1, 'list_add'); - -my $msg = check_status($msg_data, 'ok'); -my ($list_id) = unpack('Z*', $msg); - -# device 2 joins the list -send_msg($sock_2, 'list_join', "$device_id2\0$list_id"); -($msg_data) = recv_msg($sock_2, 'list_join'); - -check_status($msg_data, 'ok'); - -# device 2 requests its lists to make sure its committed to the list -send_msg($sock_2, 'lists_get', $device_id2); -($msg_data) = recv_msg($sock_2, 'lists_get'); +# B joins A's list +$B->list_join($A->lists(0)->{'id'}); -my $list = check_status($msg_data, 'ok'); -my ($id, $name, $num_items, @members) = split("\0", $list); +# B requests its lists to make sure its committed to the list +my @lists = $B->lists_get(); -fail "request list id mismatch: '$id' ne '$list_id'" if ($id ne $list_id); -fail "unexpected name '$name', expected '$list_name'" if ($name ne $list_name); -fail "expected 2 list members, got ". @members if (@members != 2); +# fail "request list id mismatch: '$id' ne '$list_id'" if ($id ne $list_id); +# fail "unexpected name '$name', expected '$list_name'" if ($name ne $list_name); +# fail "expected 2 list members, got ". @members if (@members != 2); diff --git a/server/tests/list_join_unit/server.log.good b/server/tests/list_join_unit/server.log.good @@ -1,6 +1,7 @@ accepting connections on <ip>:<port> (pid = <digits>) new connection (pid = <digits>) ssl ok, ver = 'TLSv1_2' cipher = 'ECDHE-RSA-AES128-SHA256' +list_join: unknown device <base64> device_add: success, <digits>:<base64> os <base64> list_join: unknown list <base64> list_add: <string> diff --git a/server/tests/list_join_unit/test.pl b/server/tests/list_join_unit/test.pl @@ -1,38 +1,24 @@ #!/usr/bin/perl -I../ use strict; use warnings; -use test; -# sanity checks the join_list message +use client; +use test; -my $socket = new_socket(); -my $phnum = rand_phnum(); +my $A = client->new(); -send_msg($socket, 'device_add', "$phnum\0unix"); -my ($msg_data) = recv_msg($socket, 'device_add'); +# check that sending a list_join message without registering fails +$A->list_join('aaaa', 'err'); +fail_msg_ne 'the client sent an unknown device id', $A->get_error(); -my $device_id = check_status($msg_data, 'ok'); +# register this client for the next tests +$A->device_add(rand_phnum()); # try joining a list that doesn't exist -send_msg($socket, 'list_join', "$device_id\0listdoesntexist"); -($msg_data) = recv_msg($socket, 'list_join'); - -my $msg = check_status($msg_data, 'err'); -my $msg_good = "the client sent an unknown list id"; - -fail "unexpected message '$msg', expected '$msg_good'" if ($msg ne $msg_good); +$A->list_join('somenonexistentlist', 'err'); +fail_msg_ne 'the client sent an unknown list id', $A->get_error(); # test joining a list your already in -send_msg($socket, 'list_add', "$device_id\0some new list"); -($msg_data) = recv_msg($socket, 'list_add'); - -$msg = check_status($msg_data, 'ok'); -my ($list_id) = unpack('Z*', $msg); - -send_msg($socket, 'list_join', "$device_id\0$list_id"); -($msg_data) = recv_msg($socket, 'list_join'); - -$msg = check_status($msg_data, 'err'); -$msg_good = "the device is already part of this list"; - -fail "unexpected message '$msg', expected '$msg_good'" if ($msg ne $msg_good); +$A->list_add('my new test list'); +$A->list_join($A->lists(0)->{'id'}, 'err'); +fail_msg_ne 'the device is already part of this list', $A->get_error(); diff --git a/server/tests/list_leave/test.pl b/server/tests/list_leave/test.pl @@ -1,44 +1,19 @@ #!/usr/bin/perl -I../ use strict; use warnings; -use test; - -# verify basic leave_list scenario where you create a list then leave it - -my $sock = new_socket(); -my $list_name = "this is a new list"; - -# create a new device id -send_msg($sock, 'device_add', "4038675309\0unix"); -my ($msg_data) = recv_msg($sock, 'device_add'); - -my $device_id = check_status($msg_data, 'ok'); -# create a new list -send_msg($sock, 'list_add', "$device_id\0$list_name"); -($msg_data) = recv_msg($sock, 'list_add'); - -my $msg = check_status($msg_data, 'ok'); -my ($list_id) = split("\0", $msg); +use client; +use test; -# leave the list -send_msg($sock, 'list_leave', "$device_id\0$list_id"); -($msg_data) = recv_msg($sock, 'list_leave'); +my $A = client->new(); +$A->device_add(rand_phnum()); -$msg = check_status($msg_data, 'ok'); -my ($leave_id) = split("\0", $msg); -fail "got leave data '$leave_id', expected $list_id" if ($leave_id ne $list_id); +$A->list_add('this list was made for leaving'); +$A->list_leave($A->lists(0)->{id}); # verify we don't get this list back when requesting all lists -send_msg($sock, 'lists_get', $device_id); -($msg_data) = recv_msg($sock, 'lists_get'); - -my $lists = check_status($msg_data, 'ok'); -fail "expected no lists" if ($lists ne ""); - -# verify we don't get this list back when requesting other lists -send_msg($sock, 'lists_get_other', $device_id); -($msg_data) = recv_msg($sock, 'lists_get_other'); +my @lists = $A->lists_get(); +my @other_lists = $A->lists_get_other(); -$lists = check_status($msg_data, 'ok'); -fail "expected no lists" if ($lists ne ""); +fail_num_ne 'wrong number of lists ', scalar @lists, 0; +fail_num_ne 'wrong number of other lists ', scalar @other_lists, 0; diff --git a/server/tests/list_leave_unit/server.log.good b/server/tests/list_leave_unit/server.log.good @@ -4,4 +4,5 @@ ssl ok, ver = 'TLSv1_2' cipher = 'ECDHE-RSA-AES128-SHA256' list_leave: unknown device <base64> device_add: success, <digits>:<base64> os <base64> list_leave: unknown list <base64> +list_leave: unknown list <digits> disconnected! diff --git a/server/tests/list_leave_unit/test.pl b/server/tests/list_leave_unit/test.pl @@ -1,27 +1,22 @@ #!/usr/bin/perl -I../ use strict; use warnings; + +use client; use test; -my $sock = new_socket(); +my $A = client->new(); # send a leave list message with a bad device id -send_msg($sock, 'list_leave', "somenonexistentdeviceid\0somelistid"); -my ($msg_data) = recv_msg($sock, 'list_leave'); - -my $msg = check_status($msg_data, 'err'); -my $msg_good = "the client sent an unknown device id"; -fail "unexpected message '$msg', expected '$msg'" if ($msg ne $msg_good); - -# send a message with a valid device id but bad list id -send_msg($sock, 'device_add', "4038675309\0unix"); -($msg_data) = recv_msg($sock, 'device_add'); +$A->list_leave('aaaa', 'err'); +fail_msg_ne 'the client sent an unknown device id', $A->get_error(); -my $device_id = check_status($msg_data, 'ok'); +$A->device_add(); -send_msg($sock, 'list_leave', "$device_id\0somenonexistentlistid"); -($msg_data) = recv_msg($sock, 'list_leave'); +# try leaving a list your not in +$A->list_leave('somenonexistentlistid', 'err'); +fail_msg_ne 'the client sent an unknown list id', $A->get_error(); -$msg = check_status($msg_data, 'err'); -$msg_good = "the client sent an unknown list id"; -fail "unexpected message '$msg', expected '$msg'" if ($msg ne $msg_good); +# try leaving the empty list +$A->list_leave('', 'err'); +fail_msg_ne 'the client sent an unknown list id', $A->get_error(); diff --git a/server/tests/list_reference_counting/test.pl b/server/tests/list_reference_counting/test.pl @@ -1,44 +1,33 @@ #!/usr/bin/perl -I../ use strict; use warnings; + +use client; use test; -# this is a test for list lifetime, especially when the creator of the list -# leaves. it makes sure that when A creates a list, then B joins, and then A -# leaves, that the list does not get deleted and is still accessible to B. +# test list reference counting to make sure they stay alive when needed -my ($sockets, $phnums, $device_ids) = create_devices(2); -my $list_name = "this is a new list"; +my $A = client->new(); +my $B = client->new(); +$A->device_add(rand_phnum()); +$B->device_add(rand_phnum()); # A creates a new list -send_msg($$sockets[0], 'list_add', "$$device_ids[0]\0$list_name"); -my ($msg_data) = recv_msg($$sockets[0], 'list_add'); - -my $msg = check_status($msg_data, 'ok'); -my ($list_id) = split("\0", $msg); - -# B joins the list -send_msg($$sockets[1], 'list_join', "$$device_ids[1]\0$list_id"); -($msg_data) = recv_msg($$sockets[1], 'list_join'); +$A->list_add('this list will belong to B soon enough'); +my $list_id = $A->lists(0)->{'id'}; -check_status($msg_data, 'ok'); +# XXX: missing steps +# - A and B become mutual friends +# - B requests his other lists +# - B joins A's list -# A leaves the list -send_msg($$sockets[0], 'list_leave', "$$device_ids[0]\0$list_id"); -($msg_data) = recv_msg($$sockets[0], 'list_leave'); - -$msg = check_status($msg_data, 'ok'); +# B joins A's list, A leaves its own list +$B->list_join($list_id); +$A->list_leave($list_id); # B verifies its still in the list -send_msg($$sockets[1], 'lists_get', $$device_ids[1]); -($msg_data) = recv_msg($$sockets[1], 'lists_get'); - -my $lists = check_status($msg_data, 'ok'); -my @lists = split("\n", $lists); -fail "expected 1 list, got " . @lists if (@lists != 1); +my @lists = $B->lists_get(); +fail_num_ne 'wrong number of lists ', scalar(@lists), 1; # B also leaves the list -send_msg($$sockets[1], 'list_leave', "$$device_ids[1]\0$list_id"); -($msg_data) = recv_msg($$sockets[1], 'list_leave'); - -$msg = check_status($msg_data, 'ok'); +$B->list_leave($list_id); diff --git a/server/tests/lists_get/test.pl b/server/tests/lists_get/test.pl @@ -1,6 +1,8 @@ #!/usr/bin/perl -I../ use strict; use warnings; + +use client; use test; # this test: @@ -9,44 +11,25 @@ use test; # - requests all lists # - checks that what's received is what was sent -my $phone_num = "4038675309"; -my $sock = new_socket(); - -send_msg($sock, 'device_add', "$phone_num\0unix"); -my ($msg_data) = recv_msg($sock, 'device_add'); - -my $device_id = check_status($msg_data, 'ok'); - -my %list_id_map; -for my $name ("new list 1", "new list 2", "new list 3") { - send_msg($sock, 'list_add', "$device_id\0$name"); - my ($msg_data) = recv_msg($sock, 'list_add'); +my $A = client->new(); +$A->device_add(my $phnum = rand_phnum()); - my $data = check_status($msg_data, 'ok'); - my ($id, $name, $member) = split("\0", $data); - # save this for verification later - $list_id_map{$name} = $id; +for ('new list 1', 'new list 2', 'new list 3') { + $A->list_add($_); } -send_msg($sock, 'lists_get', $device_id); -($msg_data) = recv_msg($sock, 'lists_get'); - -my $lists = check_status($msg_data, 'ok'); +my @client_lists = $A->lists_all(); +my @lists = $A->lists_get(); +my $i = 0; my $num_lists = 0; -for my $l (split("\n", $lists)) { - my ($id, $name, $num_items, @members) = split("\0", $l); - unless ($name && $id && @members) { - fail "response didn't send at least 3 fields"; - } - if ($list_id_map{$name} ne $id) { - fail "recevied list id '$id' different than sent '$list_id_map{$name}'!"; - } - if (@members != 1) { - fail "expected 1 list member, got " . scalar @members . "\n"; - } - if ($members[0] ne $phone_num) { - fail "unexpected list member $members[0]"; - } +for (@lists) { + my $list = $A->lists($i++); + + #fail_msg_ne $_->{'id'}, $list->{'id'}; + fail_num_ne 'wrong number of members', $_->{num_members}, $list->{num_members}; + fail_msg_ne $phnum, $_->{members}->[0]; + #fail_msg_ne $_->{'name'}, $list->{name}; + $num_lists++; } -fail "expected 3 direct lists, got $num_lists\n" if ($num_lists != 3); +fail_num_ne 'wrong number of lists', $num_lists, 3; diff --git a/server/tests/lists_get_other/test.pl b/server/tests/lists_get_other/test.pl @@ -1,6 +1,8 @@ #!/usr/bin/perl -I../ use strict; use warnings; + +use client; use test; # this test: @@ -9,52 +11,21 @@ use test; # - device 1 creates a new list # - then verify that device 2 can see it -my ($sock_1, $sock_2) = (new_socket(), new_socket()); -my ($phnum_1, $phnum_2) = ("4038675309", "4037082094"); - -send_msg($sock_1, 'device_add', "$phnum_1\0unix"); -my ($msg_1) = recv_msg($sock_1, 'device_add'); - -send_msg($sock_2, 'device_add', "$phnum_2\0unix"); -my ($msg_2) = recv_msg($sock_2, 'device_add'); - -my $device_id1 = check_status($msg_1, 'ok'); -my $device_id2 = check_status($msg_2, 'ok'); - -# the mutual friend relationship, computer style -send_msg($sock_1, 'friend_add', "$device_id1\0$phnum_2"); -recv_msg($sock_1, 'friend_add'); -send_msg($sock_2, 'friend_add', "$device_id2\0$phnum_1"); -recv_msg($sock_2, 'friend_add'); - -my $list_name = "this is a new list"; +my $A = client->new(); +my $B = client->new(); -send_msg($sock_1, 'list_add', "$device_id1\0$list_name"); -my ($msg_data) = recv_msg($sock_1, 'list_add'); +$A->device_add(rand_phnum()); +$B->device_add(rand_phnum()); -my $list_data = check_status($msg_data, 'ok'); -my ($list_id) = split("\0", $list_data); +$A->friend_add($B->phnum()); +$B->friend_add($A->phnum()); -# make sure socket 2 can see socket 1's list -send_msg($sock_2, 'lists_get_other', $device_id2); -($msg_data) = recv_msg($sock_2, 'lists_get_other'); +$A->list_add('this is a new list that B can see'); +my $as_list = $A->lists(0); -my $other_lists = check_status($msg_data, 'ok'); -my $num_lists = 0; -for my $l (split("\n", $other_lists)) { - my ($id, $name, @members) = split("\0", $l); - unless ($id && $name && @members) { - fail "response didn't send at least 3 fields"; - } - if ($list_id ne $id) { - fail "recevied list id '$id' different than sent '$list_id'!"; - } - if (@members != 1) { - fail "expected 1 list member, got " . scalar @members . "\n"; - } - if ($members[0] ne $phnum_1) { - fail "unexpected list member '$members[0]'"; - } - $num_lists++; -} -fail "expected 1 indirect list, got $num_lists\n" if ($num_lists != 1); +my @other_lists = $B->lists_get_other(); +fail_msg_ne $other_lists[0]->{name}, $as_list->{'name'}; +fail_msg_ne $other_lists[0]->{id}, $as_list->{'id'}; +fail_num_ne 'wrong number of list members', $other_lists[0]->{num_members}, 1; +fail_msg_ne $other_lists[0]->{members}->[0], $A->phnum(); +fail_num_ne 'wrong number of other lists', scalar(@other_lists), 1; diff --git a/server/tests/multiple_friends_same_other_list/test.pl b/server/tests/multiple_friends_same_other_list/test.pl @@ -1,49 +1,39 @@ #!/usr/bin/perl -I../ use strict; use warnings; + use test; +use client; # this test makes sure that when 2 friends of yours are in the same list that # your not in, that the list doesn't show up twice in your list_get_other # request. -my ($sockets, $phnums, $device_ids) = create_devices(3); - -# 0 and 1 need to be mutual friends -send_msg($$sockets[0], 'friend_add', "$$device_ids[0]\0$$phnums[1]"); -recv_msg($$sockets[0], 'friend_add'); -send_msg($$sockets[1], 'friend_add', "$$device_ids[1]\0$$phnums[0]"); -recv_msg($$sockets[1], 'friend_add'); - -# 0 and 2 need to be mutual friends too -send_msg($$sockets[0], 'friend_add', "$$device_ids[0]\0$$phnums[2]"); -recv_msg($$sockets[0], 'friend_add'); -send_msg($$sockets[2], 'friend_add', "$$device_ids[2]\0$$phnums[0]"); -recv_msg($$sockets[2], 'friend_add'); - -# 1 and 2 need to be in the same list -send_msg($$sockets[1], 'list_add', "$$device_ids[1]\0this is a new list"); -my ($msg_data) = recv_msg($$sockets[1], 'list_add'); - -my $list_data = check_status($msg_data, 'ok'); -my ($list_id) = split("\0", $list_data); - -send_msg($$sockets[2], 'list_join', "$$device_ids[2]\0$list_id"); -($msg_data) = recv_msg($$sockets[2], 'list_join'); - -check_status($msg_data, 'ok'); - -# 0 requests his other lists -send_msg($$sockets[0], 'lists_get_other', "$$device_ids[0]"); -($msg_data) = recv_msg($$sockets[0], 'lists_get_other'); - -my $raw_lists = check_status($msg_data, 'ok'); -my @lists = split("\n", $raw_lists); -fail "expected 1 list, got " . @lists if (@lists != 1); - -# 0 makes sure he got a single list with both members in it -my ($id, $name, @members) = split("\0", $lists[0]); -fail "expected 2 list members, got " . @members if (@members != 2); -fail "bad list id '$id', expected '$list_id'" if ($id ne $list_id); -fail "expected member '$$phnums[1]'" unless (grep {$_ eq $$phnums[1]} @$phnums); -fail "expected member '$$phnums[2]'" unless (grep {$_ eq $$phnums[2]} @$phnums); +my $A = client->new(); +my $B = client->new(); +my $C = client->new(); + +$A->device_add(rand_phnum()); +$B->device_add(rand_phnum()); +$C->device_add(rand_phnum()); + +# A and B are mutual friends +$A->friend_add($B->phnum()); +$B->friend_add($A->phnum()); + +# A and C are also mutual friends +$A->friend_add($C->phnum()); +$C->friend_add($A->phnum()); + +# B and C need to be in the same list +$B->list_add('this is Bs new list'); +$C->list_join($B->lists(0)->{'id'}); + +# A makes sure he got a single list +my @other = $A->lists_get_other(); +fail_num_ne 'wrong number of list members', $other[0]->{num_members}, 2; +fail_msg_ne $other[0]->{id}, $B->lists(0)->{'id'}; +fail_num_ne 'wrong number of lists', scalar(@other), 1; +fail "A found unexpectedly" if (grep {$_ eq $A->phnum()} @{$other[0]->{members}}); +fail "member B not found" unless (grep {$_ eq $B->phnum()} @{$other[0]->{members}}); +fail "member C not found" unless (grep {$_ eq $C->phnum()} @{$other[0]->{members}}); diff --git a/server/tests/test.pm b/server/tests/test.pm @@ -2,185 +2,40 @@ package test; use strict; use warnings; -use Errno; use Exporter qw(import); -use IO::Socket::SSL; use String::Random; -use Time::HiRes qw(usleep); - -require "msgs.pl"; -our (%msg_num, @msg_str); - -our @EXPORT = qw(new_socket fail send_msg recv_msg %msg_num @msg_str - check_status rand_phnum create_devices); - -sub fail { - my (undef, $file, $line) = caller; - print "$file:$line: " . shift . "\n"; - exit 1; -} - -sub create_devices { - my ($count) = @_; - - my @sockets; - my @phnums; - my @device_ids; - - # $count can potentially be 0 - for (1..$count) { - my $sock = new_socket(); - my $phnum = rand_phnum(); - - send_msg($sock, 'device_add', "$phnum\0unix"); - my ($msg) = recv_msg($sock, 'device_add'); - - my $device_id = check_status($msg, 'ok'); - - push @sockets, $sock; - push @phnums, $phnum; - push @device_ids, $device_id; - } - - return (\@sockets, \@phnums, \@device_ids); -} +our @EXPORT = qw(rand_phnum fail fail_msg_ne fail_num_ne); my $string_gen = String::Random->new; sub rand_phnum { return $string_gen->randpattern('nnnnnnnnnn'); } -sub new_socket -{ - if (! defined $ENV{PORT}) { - fail "$0: error, test needs PORT environment variable set"; - exit 1; - } - - my $sock = undef; - my $timeout = time + 5; - while (1) { - $sock = new IO::Socket::SSL->new( - PeerHost => 'localhost', - PeerPort => $ENV{PORT}, - # this is needed because PeerHost is localhost and our - # SSL certificates are signed with amp.ca - SSL_verifycn_name => "absentmindedproductions.ca", - ); - - if ($!{ECONNREFUSED}) { - if (time > $timeout) { - fail "server not ready after 5 seconds"; - } - usleep(50 * 1000); - next; - } - - last; - } - - unless ($sock) { - die "failed connect or ssl handshake: $!,$SSL_ERROR"; - } - - return $sock; -} - -sub send_msg { - my ($sock, $msg_type, $payload) = @_; - - if (! exists $msg_num{$msg_type}) { - fail "send_msg: invalid message type '$msg_type'"; - } - - my $header_len = 6; - my $version = 0; - my $num = $msg_num{$msg_type}; - my $payload_len = length($payload); - - send_all($sock, pack("nnn", $version, $num, $payload_len), $header_len); - send_all($sock, $payload, $payload_len); - - return $header_len + $payload_len; -} - -sub send_all { - my ($socket, $bytes, $bytes_total) = @_; - - my $bytes_written = $socket->syswrite($bytes); - - if (!defined $bytes_written) { - fail "send_all: write failed: $!"; - } elsif ($bytes_written != $bytes_total) { - fail "send_all: wrote $bytes_written instead of $bytes_total bytes"; - } - - return; -} - -sub recv_msg { - my ($sock, $expected_type) = @_; - - my $header = read_all($sock, 6); - my ($version, $msg_type, $msg_size) = unpack("nnn", $header); - - if ($version != 0) { - fail "recv_msg: unsupported protocol version $version"; - } - - if ($msg_type >= @msg_str) { - fail "recv_msg: unknown message type $msg_type"; - } - if ($msg_str[$msg_type] ne $expected_type) { - fail "recv_msg: response type mismatch '$msg_str[$msg_type]'" . - " != '$expected_type'"; - } - - if ($msg_size > 4096) { - fail "recv_msg: $msg_size byte message too large"; - } - elsif ($msg_size == 0) { - # don't try and do another read, as a read of size 0 is EOF - return ("", 0); - } +sub fail { + my $msg = shift; - my $msg = read_all($sock, $msg_size); - return ($msg, $msg_size); + my (undef, $file, $line) = caller; + print "$file:$line: $msg\n"; + exit 1; } -sub read_all { - my ($sock, $bytes_total) = @_; +sub fail_msg_ne { + my ($arg1, $arg2) = @_; + return if ($arg1 eq $arg2); - my $bytes_read = $sock->sysread(my $data, $bytes_total); - - if (!defined $bytes_read) { - fail "recv_msg: read failed: $!"; - } elsif ($bytes_read == 0) { - fail "recv_msg: read EOF on socket"; - } elsif ($bytes_read != $bytes_total) { - fail "recv_msg: read $bytes_read instead of $bytes_total bytes"; - } - - return $data; + my (undef, $file, $line) = caller; + print "$file:$line: expected message '$arg1' but got '$arg2'\n"; + exit 1; } -sub check_status { - my ($msg, $expected_status) = @_; - - my $first_null = index($msg, "\0"); - if ($first_null == -1) { - fail "check_status: no null byte found in response"; - } - - my $msg_status = substr($msg, 0, $first_null); - my $msg_rest = substr($msg, $first_null + 1); +sub fail_num_ne { + my ($msg, $arg1, $arg2) = @_; + return if ($arg1 == $arg2); - if ($msg_status ne $expected_status) { - fail "unexpected receive status '$msg_status': '$msg_rest'"; - } - - return $msg_rest; + my (undef, $file, $line) = caller; + print "$file:$line: $msg $arg1 != $arg2\n"; + exit 1; } 1; diff --git a/server/tests/two_lists_same_name/server.log.good b/server/tests/two_lists_same_name/server.log.good @@ -8,4 +8,11 @@ list_add: fingerprint = <base64> list_add: <string> list_add: adding first member devid = <base64> list_add: fingerprint = <base64> +lists_get: gathering lists for <base64> +lists_get: found list <string> <base64> +lists_get: list has 1 members +lists_get: list has 0 items +lists_get: found list <string> <base64> +lists_get: list has 1 members +lists_get: list has 0 items disconnected! diff --git a/server/tests/two_lists_same_name/test.pl b/server/tests/two_lists_same_name/test.pl @@ -1,28 +1,17 @@ #!/usr/bin/perl -I../ use strict; use warnings; -use test; - -# this test: -# - creates new device id -# - creates new list -# - creates another new list with identical name - -my $sock = new_socket(); -send_msg($sock, 'device_add', "4038675309\0unix"); -my ($msg_data, $length) = recv_msg($sock, 'device_add'); - -my $device_id = check_status($msg_data, 'ok'); -my $list_name = "this is a new list"; - -send_msg($sock, 'list_add', "$device_id\0$list_name"); -($msg_data) = recv_msg($sock, 'list_add'); +use client; +use test; -check_status($msg_data, 'ok'); +my $A = client->new(); +$A->device_add(rand_phnum()); -# add the same list again -send_msg($sock, 'list_add', "$device_id\0$list_name"); -($msg_data, $length) = recv_msg($sock, 'list_add'); +# check that adding the same list twice works +my $name = 'some list thats going to be added twice'; +$A->list_add($name); +$A->list_add($name); -my $msg = check_status($msg_data, 'ok'); +my @lists = $A->lists_get(); +# XXX: add validation this gives back 2 independent lists