]> git.vpit.fr Git - perl/modules/IPC-MorseSignals.git/commitdiff
Importing IPC-MorseSignals-0.15.tar.gz v0.15
authorVincent Pit <vince@profvince.com>
Sun, 29 Jun 2008 16:37:20 +0000 (18:37 +0200)
committerVincent Pit <vince@profvince.com>
Sun, 29 Jun 2008 16:37:20 +0000 (18:37 +0200)
17 files changed:
Changes
META.yml
Makefile.PL
README
lib/IPC/MorseSignals.pm
lib/IPC/MorseSignals/Emitter.pm
lib/IPC/MorseSignals/Receiver.pm
samples/bench.pl
t/10-sigusr.t
t/20-emitter-obj.t
t/30-receiver-obj.t
t/50-self-plain.t
t/60-fork-plain.t
t/61-fork-utf8.t
t/62-fork-storable.t
t/70-speed.t
t/lib/IPC/MorseSignals/TestSuite.pm

diff --git a/Changes b/Changes
index 91a4f2b00e76c4ea8ef52dabf266b3ba4bd27d08..4df4fe6742678df5dd448eab4bdf1935504d27b5 100644 (file)
--- a/Changes
+++ b/Changes
@@ -1,14 +1,21 @@
 Revision history for IPC-MorseSignals
 
-0.14    2008-03-13
+0.15    2008-04-05 00:00 UTC
         + Fix : Correct die error when SIGUSR{1,2} aren't found.
-        + Tst : Don't reset the receiver state, flush the pipe instead.
-                SIGTSTP isn't needed anymore.
+        + Fix : Strip off duplicated targets when sending to multiple processes
+                at the same time.
+        + Tst : Lower base speed to 1024 bauds when forking.
+        + Tst : Don't reset the receiver state anymore, but always respawn.
+        + Tst : t/70-speed.t tests are now marked as TODO, so that they won't
+                block module installation.
         + Tst : Timeouts aren't truncated to 10 seconds anymore. This used to
                 result into physically logical failures. On the other hand, if
                 the required timeout now goes over 20 seconds, the test is
                 considered failed.
 
+0.14
+        Phantom version, maybe released through CPAN for a short amount of time.
+
 0.13    2008-03-10 15:25 UTC
         + Chg : Build prerequisites are now completely separated from run-time
                 prerequisites.
index d3ec65b9fce56c33d3ba8a38a19ddc6847f48e0b..091322c6696c1db451694f4ee34ac6f51fabcfaf 100644 (file)
--- a/META.yml
+++ b/META.yml
@@ -1,11 +1,11 @@
 --- #YAML:1.0
 name:                IPC-MorseSignals
-version:             0.14
+version:             0.15
 abstract:            Communicate between processes with Morse signals.
 license:             perl
 author:              
     - Vincent Pit <perl@profvince.com>
-generated_by:        ExtUtils::MakeMaker version 6.44
+generated_by:        ExtUtils::MakeMaker version 6.42
 distribution_type:   module
 requires:     
     Bit::MorseSignals:             0.05
index 9ee0b24e4280fa3a1988dcda4639e3f1a9bddf19..b9705a069d3c5697fd5052234606d276c649181e 100644 (file)
@@ -41,22 +41,22 @@ sub build_req {
 }
 
 WriteMakefile(
-    NAME                => 'IPC::MorseSignals',
-    AUTHOR              => 'Vincent Pit <perl@profvince.com>',
-    LICENSE             => 'perl',
-    VERSION_FROM        => 'lib/IPC/MorseSignals.pm',
-    ABSTRACT_FROM       => 'lib/IPC/MorseSignals.pm',
-    PL_FILES            => {},
-    PREREQ_PM => {
+    NAME          => 'IPC::MorseSignals',
+    AUTHOR        => 'Vincent Pit <perl@profvince.com>',
+    LICENSE       => 'perl',
+    VERSION_FROM  => 'lib/IPC/MorseSignals.pm',
+    ABSTRACT_FROM => 'lib/IPC/MorseSignals.pm',
+    PL_FILES      => {},
+    PREREQ_PM     => {
         'Bit::MorseSignals' => 0.05,
         'Carp'              => 0,
         'POSIX'             => 0,
         'Time::HiRes'       => 0,
     },
-    dist                => {
-        PREOP => 'pod2text lib/IPC/MorseSignals.pm > $(DISTVNAME)/README; '
-                 . build_req,
-        COMPRESS => 'gzip -9f', SUFFIX => 'gz',
+    dist          => {
+        PREOP      => 'pod2text lib/IPC/MorseSignals.pm > $(DISTVNAME)/README; '
+                      . build_req,
+        COMPRESS   => 'gzip -9f', SUFFIX => 'gz',
     },
-    clean               => { FILES => 'IPC-MorseSignals-*' },
+    clean         => { FILES => 'IPC-MorseSignals-* *.gcov *.gcda *.gcno cover_db' },
 );
diff --git a/README b/README
index 119ef391776f22bd9b9f5d20a53144646766fdec..698de2898b52aa5469373e22fcaaf7fafda47169 100644 (file)
--- a/README
+++ b/README
@@ -2,7 +2,7 @@ NAME
     IPC::MorseSignals - Communicate between processes with Morse signals.
 
 VERSION
-    Version 0.14
+    Version 0.15
 
 SYNOPSIS
         # In the sender process
index f4e96e82f870e877157ffb10f812d84be8e90615..2de81edd69dad927e6bd597842d8fe49463578d8 100644 (file)
@@ -9,11 +9,11 @@ IPC::MorseSignals - Communicate between processes with Morse signals.
 
 =head1 VERSION
 
-Version 0.14
+Version 0.15
 
 =cut
 
-our $VERSION = '0.14';
+our $VERSION = '0.15';
 
 =head1 SYNOPSIS
 
index 7e2dca0d27309590eaeba523138f201f7d6846c9..2b8a72a02f5d7ff4a3db0fdaa374408517e94b37 100644 (file)
@@ -16,11 +16,11 @@ IPC::MorseSignals::Emitter - Base class for IPC::MorseSignals emitters.
 
 =head1 VERSION
 
-Version 0.14
+Version 0.15
 
 =cut
 
-our $VERSION = '0.14';
+our $VERSION = '0.15';
 
 =head1 SYNOPSIS
 
@@ -45,7 +45,7 @@ sub _check_self {
 
 =head2 C<< new < delay => $seconds, speed => $bauds, %bme_options > >>
 
-Creates a new emitter object. C<delay> specifies the delay between two sends, in seconds, while C<speed> is the number of bits sent per second. The delay value has priority over the speed. Extra arguments are passed to L<Bit::MorseSignals::Emitter/new>.
+Creates a new emitter object. C<delay> specifies the delay between two sends, in seconds, while C<speed> is the number of bits sent per second. The delay value has priority over the speed. Default delay is 1 second. Extra arguments are passed to L<Bit::MorseSignals::Emitter/new>.
 
 =cut
 
@@ -68,7 +68,7 @@ sub new {
 
 =head2 C<send $pid>
 
-Sends messages enqueued with L<Bit::MorseSignals::Emitter/post> to the process C<$pid> (or to all the C<@$pid> if C<$pid> is an array reference).
+Sends messages enqueued with L<Bit::MorseSignals::Emitter/post> to the process C<$pid> (or to all the C<@$pid> if C<$pid> is an array reference, in which case duplicated targets are stripped off).
 
 =cut
 
@@ -76,8 +76,10 @@ sub send {
  my ($self, $dest) = @_;
  _check_self($self);
  return unless defined $dest;
- my @dests = grep $_ > 0, ref $dest eq 'ARRAY' ? map int, grep defined, @$dest
-                                               : int $dest;
+ my %count;
+ my @dests = grep $_ > 0 && !$count{$_}++, # Remove duplicates.
+              ref $dest eq 'ARRAY' ? map int, grep defined, @$dest
+                                   : int $dest;
  return unless @dests;
  while (defined(my $bit = $self->pop)) {
   my @sigs = (SIGUSR1, SIGUSR2);
index 7bd14163cf74edded74251545ea59dfc16e6aab9..03d1945d92e96462711e11c875a43da5aaedbb89 100644 (file)
@@ -14,11 +14,11 @@ IPC::MorseSignals::Receiver - Base class for IPC::MorseSignals receivers.
 
 =head1 VERSION
 
-Version 0.14
+Version 0.15
 
 =cut
 
-our $VERSION = '0.14';
+our $VERSION = '0.15';
 
 =head1 SYNOPSIS
 
index 2f7daaec9087dbe983f60ce1d511d7ef44b3ae82..9bd146e43a2776edfd64f1ab41c46af35e292568 100755 (executable)
@@ -9,28 +9,29 @@ use lib qw{blib/lib t/lib};
 
 use IPC::MorseSignals::TestSuite qw/init bench cleanup/;
 
-my $diag = sub { print STDERR "@_\n" };
+sub diag { print STDERR "@_\n" };
+*IPC::MorseSignals::TestSuite::diag = *main::diag;
 my @res;
 
 init 100;
 
-bench 4,    1,   $diag, \@res;
-bench 4,    4,   $diag, \@res;
-bench 4,    16,  $diag, \@res;
-bench 4,    64,  $diag, \@res;
-bench 4,    256, $diag, \@res;
-bench 16,   1,   $diag, \@res;
-bench 16,   4,   $diag, \@res;
-bench 16,   16,  $diag, \@res;
-bench 16,   64,  $diag, \@res;
-bench 64,   1,   $diag, \@res;
-bench 64,   4,   $diag, \@res;
-bench 64,   16,  $diag, \@res;
-bench 256,  1,   $diag, \@res;
-bench 256,  4,   $diag, \@res;
-bench 1024, 1,   $diag, \@res;
+bench 4,    1,   \@res;
+bench 4,    4,   \@res;
+bench 4,    16,  \@res;
+bench 4,    64,  \@res;
+bench 4,    256, \@res;
+bench 16,   1,   \@res;
+bench 16,   4,   \@res;
+bench 16,   16,  \@res;
+bench 16,   64,  \@res;
+bench 64,   1,   \@res;
+bench 64,   4,   \@res;
+bench 64,   16,  \@res;
+bench 256,  1,   \@res;
+bench 256,  4,   \@res;
+bench 1024, 1,   \@res;
 
 cleanup;
 
-print STDERR "=== Summary ===\n";
-print STDERR "$_\n" for @res;
+diag "\n=== Summary ===";
+diag $_ for @res;
index bfe2dc29ed9f56d198b1265c9a9a958ad89bf151..60b17b2a1833628c18aa30f85d94e4a2186e6705 100644 (file)
@@ -3,7 +3,7 @@
 use strict;
 use warnings;
 
-use Test::More tests => 2;
+use Test::More tests => 4;
 
 use POSIX qw/SIGUSR1 SIGUSR2/;
 
@@ -13,7 +13,9 @@ local $SIG{'USR1'} = sub { ++$a };
 local $SIG{'USR2'} = sub { ++$b };
 
 kill SIGUSR1 => $$;
-ok(($a == 1) && ($b == 0), 'SIGUSR1');
+is($a, 1, 'SIGUSR1 triggers $SIG{USR1}');
+is($b, 0, 'SIGUSR1 doesn\'t trigger $SIG{USR2}');
 
 kill SIGUSR2 => $$;
-ok(($a == 1) && ($b == 1), 'SIGUSR2');
+is($a, 1, 'SIGUSR2 doesn\'t trigger $SIG{USR1}');
+is($b, 1, 'SIGUSR2 triggers $SIG{USR2}');
index 97204fe8c42cc9b481f814232ccfeb33f4c1f7cf..bd88b12675475ca58eea61467fd0b9ec090f23a3 100644 (file)
@@ -7,9 +7,11 @@ use Test::More tests => 19;
 
 use IPC::MorseSignals::Emitter;
 
+sub neq { abs($_[0] - $_[1]) < ($_[1] / 10) };
+
 my $deuce = new IPC::MorseSignals::Emitter;
 ok(defined $deuce, 'BME object is defined');
-ok(ref $deuce eq 'IPC::MorseSignals::Emitter', 'IME object is valid');
+is(ref $deuce, 'IPC::MorseSignals::Emitter', 'IME object is valid');
 ok($deuce->isa('Bit::MorseSignals::Emitter'), 'IME is a BME');
 
 my $fake = { };
@@ -19,33 +21,33 @@ ok($@ && $@ =~ /^First\s+argument/, "IME methods only apply to IME objects");
 eval { Bit::MorseSignals::Emitter::reset($fake) };
 ok($@ && $@ =~ /^First\s+argument/, "BME methods only apply to BME objects");
 
-ok($deuce->delay == 1, 'default delay is 1');
-ok($deuce->speed == 1, 'default speed is 1');
+is($deuce->delay, 1, 'default delay is 1');
+is($deuce->speed, 1, 'default speed is 1');
 
 $deuce->delay(0.1);
-ok(abs($deuce->delay - 0.1) < 0.01, 'set delay is 0.1');
-ok($deuce->speed == 10, 'resulting speed is 10');
+ok(neq($deuce->delay, 0.1), 'set delay is 0.1');
+is($deuce->speed, 10, 'resulting speed is 10');
 
 $deuce->speed(100);
-ok($deuce->speed == 100, 'set speed is 100');
-ok(abs($deuce->delay - 0.01) < 0.001, 'resulting speed is 0.01');
+is($deuce->speed, 100, 'set speed is 100');
+ok(neq($deuce->delay, 0.01), 'resulting speed is 0.01');
 
 $deuce = new IPC::MorseSignals::Emitter delay => 0.25;
-ok(abs($deuce->delay - 0.25) < 0.025, 'initial delay is 0.25');
-ok($deuce->speed == 4, 'resulting initial speed is 4');
+ok(neq($deuce->delay, 0.25), 'initial delay is 0.25');
+is($deuce->speed, 4, 'resulting initial speed is 4');
 
 $deuce = new IPC::MorseSignals::Emitter speed => 40;
-ok($deuce->speed == 40, 'initial speed is 40');
-ok(abs($deuce->delay - 0.025) < 0.0025, 'resulting initial delay is 0.025');
+is($deuce->speed, 40, 'initial speed is 40');
+ok(neq($deuce->delay, 0.025), 'resulting initial delay is 0.025');
 
 $deuce = new IPC::MorseSignals::Emitter delay => 0.25, speed => 40;
-ok(abs($deuce->delay - 0.25) < 0.025, 'delay supersedes speed');
+ok(neq($deuce->delay, 0.25), 'delay supersedes speed');
 
 $deuce = new IPC::MorseSignals::Emitter delay => 0;
-ok($deuce->delay == 1, 'wrong delay results in 1');
+is($deuce->delay, 1, 'wrong delay results in 1');
 
 $deuce = new IPC::MorseSignals::Emitter speed => 0.1;
-ok($deuce->delay == 1, 'wrong speed results in 1');
+is($deuce->delay, 1, 'wrong speed results in 1');
 
 $deuce = new IPC::MorseSignals::Emitter delay => 0, speed => -0.1;
-ok($deuce->delay == 1, 'wrong delay and speed result in 1');
+is($deuce->delay, 1, 'wrong delay and speed result in 1');
index a2e4f19c7a5792a8f566514e87bb5503d324c28e..855a9d033430180d1a854ee429598f78e2e01d6b 100644 (file)
@@ -9,7 +9,7 @@ use IPC::MorseSignals::Receiver;
 
 my $pants = new IPC::MorseSignals::Receiver \%SIG;
 ok(defined $pants, 'IMR object is defined');
-ok(ref $pants eq 'IPC::MorseSignals::Receiver', 'IMR object is valid');
+is(ref $pants, 'IPC::MorseSignals::Receiver', 'IMR object is valid');
 ok($pants->isa('Bit::MorseSignals::Receiver'), 'IMR is a BMR');
 
 my $fake = { };
index d5031132b001958037607d2bdd2c9f253a9df20c..06c0a6008e061cc1fa9c2194b86f5d03e385dc0e 100644 (file)
@@ -14,7 +14,7 @@ my @msgs = qw/hlagh hlaghlaghlagh HLAGH HLAGHLAGHLAGH \x{0dd0}\x{00}
 my $deuce = new IPC::MorseSignals::Emitter speed => 1024;
 my $pants = new IPC::MorseSignals::Receiver \%SIG, done => sub {
  my $cur = shift @msgs;
- ok($_[1] eq $cur, 'got ' . $_[1] . ', received ' . $cur)
+ is($_[1], $cur, "message correctly received");
 };
 
 $deuce->post($_) for @msgs;
index 6d66cf9a58ad2f3c63241615b7e7dbe6c32aeb7e..043e99e35f7f0604eeab83a1f598b6e8c9d92b0c 100644 (file)
@@ -8,6 +8,8 @@ use Test::More tests => 7;
 use lib 't/lib';
 use IPC::MorseSignals::TestSuite qw/try init cleanup/;
 
+*IPC::MorseSignals::TestSuite::diag = *Test::More::diag;
+
 sub test {
  my ($desc, @args) = @_;
  my ($res, $speed, $len);
index 038beeada0c8fde8c2d5f6776d10012d881c61e7..c2c9c3425145edd9e6faab97c6aaf546b31e3638 100644 (file)
@@ -10,6 +10,8 @@ use Test::More tests => 5;
 use lib 't/lib';
 use IPC::MorseSignals::TestSuite qw/try init cleanup/;
 
+*IPC::MorseSignals::TestSuite::diag = *Test::More::diag;
+
 sub test {
  my ($desc, @args) = @_;
  my ($res, $speed, $len);
index 9d6f658be57aeb30cea47527f835071c64cd804b..56e36ebbd05fb611f5c54fea3bada47a2557baa5 100644 (file)
@@ -10,6 +10,8 @@ use Test::More tests => 8;
 use lib 't/lib';
 use IPC::MorseSignals::TestSuite qw/try init cleanup/;
 
+*IPC::MorseSignals::TestSuite::diag = *Test::More::diag;
+
 sub test {
  my ($desc, @args) = @_;
  my ($res, $speed, $len);
index fc6f031e7d43b19bf4d95fb67f4ce8a714b0590f..07dd76750d1b577a61a9aed43b896b8882cf92eb 100644 (file)
@@ -5,19 +5,22 @@ use warnings;
 
 use utf8;
 
-use Test::More tests => 3;
+my $n;
+use Test::More tests => 1 + ($n = 5);
 
 use lib 't/lib';
 use IPC::MorseSignals::TestSuite qw/bench init cleanup/;
 
-my $diag = sub { diag @_ };
+*IPC::MorseSignals::TestSuite::diag = *Test::More::diag;
+
 my @res;
 
-init 12;
+init 2 * $n;
 
-ok(bench(4,  1, $diag, \@res));
-ok(bench(4,  4, $diag, \@res));
-ok(bench(16, 1, $diag, \@res));
+TODO: {
+ local $TODO = 'This is just to give you a measure of which speed you should use';
+ ok(bench(2 ** ($n - $_),  2 ** $_, \@res)) for 0 .. $n;
+}
 
 cleanup;
 
index 8052a8588e3536a866a14a5fde9b946b5d29f558..570fa2762f2254c2304146dbbacd7be8b7e8872f 100644 (file)
@@ -4,7 +4,7 @@ use strict;
 use warnings;
 
 use Data::Dumper;
-use POSIX qw/pause SIGUSR1 SIGKILL EXIT_FAILURE/;
+use POSIX qw/pause SIGKILL EXIT_FAILURE/;
 
 use IPC::MorseSignals::Emitter;
 use IPC::MorseSignals::Receiver;
@@ -17,8 +17,10 @@ $Data::Dumper::Indent = 0;
 
 my ($lives, $pid, $rdr);
 
-my $ready = 0;
-$SIG{USR1} = sub { $ready = 1 };
+sub slaughter;
+local $SIG{INT} = sub { slaughter };
+
+sub diag { warn "# @_" }
 
 sub spawn {
  --$lives;
@@ -32,28 +34,25 @@ sub spawn {
   close $rdr or die "close() failed: $!";
   select $wtr;
   $| = 1;
-  my $ppid = getppid;
   my $rcv = new IPC::MorseSignals::Receiver \%SIG, done => sub {
    my $msg = Dumper($_[1]);
    $msg =~ s/\n\r/ /g;
    print $wtr "$msg\n";
-   kill SIGUSR1 => $ppid if $ppid;
   };
   $SIG{__WARN__} = sub {
    my $warn = join '', @_;
    $warn =~ s/\n\r/ /g;
    print $wtr "!warn:$warn\n";
-   kill SIGUSR1 => $ppid if $ppid;
   };
   print $wtr "!ok\n";
   pause while 1;
   exit EXIT_FAILURE;
  }
  close $wtr or die "close() failed: $!";
- my $t = <$rdr>;
  my $oldfh = select $rdr;
  $| = 1;
  select $oldfh;
+ my $t = <$rdr>;
 }
 
 sub slaughter {
@@ -63,13 +62,16 @@ sub slaughter {
  }
  if ($pid) {
   kill SIGKILL => $pid;
-  waitpid $pid, 0;
+  my $kid;
+  do {
+   $kid = waitpid $pid, 0;
+  } while ($kid != $pid && $kid != -1);
   undef $pid;
  }
 }
 
 sub respawn {
warn "# respawn ($lives lives left)";
diag "respawn ($lives lives left)";
  slaughter;
  spawn;
 }
@@ -88,14 +90,13 @@ my $snd = new IPC::MorseSignals::Emitter;
 
 sub try {
  my ($msg) = @_;
- my $speed = 2 ** 16;
+ my $speed = 2 ** 10;
  my $dump = Dumper($msg);
  1 while chomp $dump;
  $dump =~ s/\n\r/ /g; 
  $snd->reset;
  my $len = 0;
- my $ok  = 0;
- while (!$ok && (($speed /= 2) >= 1)) {
+ while (($speed /= 2) >= 1) {
   $snd->post($msg);
   $len = $snd->len;
   my $a = 1 + (int($len / $speed) || 1);
@@ -106,46 +107,22 @@ sub try {
    local $SIG{ALRM} = sub { die 'timeout' };
    local $SIG{__WARN__} = sub { $a = alarm 0; die 'do not want warnings' };
    alarm $a;
-   $ready = 0;
    $snd->send($pid);
-   pause until $ready;
    $r = <$rdr>;
    $a = alarm 0;
   };
-  if (!defined $r) { # Something bad happened, respawn
-   $snd->reset;
-   respawn;
-  } else {
+  if (defined $r) {
    1 while chomp $r;
-   if ($r eq $dump) {
-    $ok = 1;
-   } else {
-#    warn "# expected $dump, got $r";
-FLUSH:
-    while ($r =~ /^!warn:(.*)/) {
-     warn "# $1";
-     warn "# flushing for $a seconds\n";
-     eval {
-      local $SIG{ALRM} = sub { die 'timeout' };
-      alarm $a;
-      $r = <$rdr>;
-      $a = alarm 0;
-     };
-     if ($@) {
-      $snd->reset;
-      respawn;
-      last FLUSH;
-     }
-    }
-    sleep 1;
-   }
+   return 1, $speed, $len if $r eq $dump;
   }
+  $snd->reset;
+  respawn;
  }
- return $ok, $speed, $len;
+ return 0, $speed, $len;
 }
 
 sub bench {
- my ($l, $n, $diag, $res) = @_;
+ my ($l, $n, $res) = @_;
  my $speed = 2 ** 16;
  my $ok = 0;
  my @alpha = ('a' .. 'z');
@@ -157,7 +134,7 @@ sub bench {
  while (($ok < $n) && (($speed /= 2) >= 1)) {
   $ok = 0;
   my $desc = "$desc_base at $speed bits/s";
-  $diag->("try $desc...");
+  diag "try $desc...";
 TRY:
   for (1 .. $n) {
    $snd->post($msg);
@@ -168,38 +145,20 @@ TRY:
     local $SIG{ALRM} = sub { die 'timeout' };
     local $SIG{__WARN__} = sub { alarm 0; die 'do not want warnings' };
     alarm $a;
-    $ready = 0;
     $snd->send($pid);
-    pause until $ready;
     $r = <$rdr>;
     alarm 0;
    };
-   if (!defined $r) { # Something bad happened, respawn
-    $snd->reset;
-    respawn;
-    last TRY;
-   } else {
+   if (defined $r) {
     1 while chomp $r;
     if ($r eq $dump) {
      ++$ok;
-    } else {
-     while ($r =~ /^!warn:(.*)/) {
-      warn "# $1";
-      warn "# flushing for $a seconds\n";
-      eval {
-       local $SIG{ALRM} = sub { die 'timeout' };
-       alarm $a;
-       $r = <$rdr>;
-       $a = alarm 0;
-      };
-      if ($@) {
-       $snd->reset;
-       respawn;
-       last TRY;
-      }
-     }
+     next TRY;
     }
    }
+   $snd->reset;
+   respawn;
+   last TRY;
   }
  }
  push @$res, $desc_base . (($speed) ? ' at ' . $speed . ' bits/s' : ' failed');