convert from the bottom up
[dbsrgits/DBIx-Class.git] / t / storage / replicated.t
index 67f8618..7e903be 100644 (file)
@@ -1,40 +1,38 @@
 use strict;
 use warnings;
-use lib qw(t/lib);
+
 use Test::More;
+
+BEGIN {
+  require DBIx::Class;
+  plan skip_all => 'Test needs ' . DBIx::Class::Optional::Dependencies->req_missing_for ('test_replicated')
+    unless DBIx::Class::Optional::Dependencies->req_ok_for ('test_replicated');
+}
+
 use Test::Exception;
-use DBICTest;
 use List::Util 'first';
 use Scalar::Util 'reftype';
 use File::Spec;
 use IO::Handle;
+use Class::Inspector;
 
-BEGIN {
-    eval { require Test::Moose; Test::Moose->import() };
-    plan skip_all => "Need Test::Moose to run this test" if $@;
-      require DBIx::Class;
+use lib qw(t/lib);
+use DBICTest;
 
-    plan skip_all => 'Test needs ' . DBIx::Class::Optional::Dependencies->req_missing_for ('replicated')
-      unless DBIx::Class::Optional::Dependencies->req_ok_for ('replicated');
-}
+my $var_dir = quotemeta ( File::Spec->catdir(qw/t var/) );
 
 use_ok 'DBIx::Class::Storage::DBI::Replicated::Pool';
 use_ok 'DBIx::Class::Storage::DBI::Replicated::Balancer';
 use_ok 'DBIx::Class::Storage::DBI::Replicated::Replicant';
 use_ok 'DBIx::Class::Storage::DBI::Replicated';
 
-use Moose();
-use MooseX::Types();
-note "Using Moose version $Moose::VERSION and MooseX::Types version $MooseX::Types::VERSION";
-
 =head1 HOW TO USE
 
     This is a test of the replicated storage system.  This will work in one of
     two ways, either it was try to fake replication with a couple of SQLite DBs
     and creative use of copy, or if you define a couple of %ENV vars correctly
     will try to test those.  If you do that, it will assume the setup is properly
-    replicating.  Your results may vary, but I have demonstrated this to work with
-    mysql native replication.
+    replicating.  
 
 =cut
 
@@ -63,6 +61,7 @@ TESTSCHEMACLASSES: {
         my $self = $class->SUPER::new(@_);
 
         $self->schema( $self->init_schema($schema_method) );
+
         return $self;
     }
 
@@ -88,7 +87,7 @@ TESTSCHEMACLASSES: {
             balancer_type=>'::Random',
             balancer_args=>{
               auto_validate_every=>100,
-          master_read_weight => 1
+              master_read_weight => 1
             },
           }
         },
@@ -105,7 +104,10 @@ TESTSCHEMACLASSES: {
         balancer_type=>'::Random',
         balancer_args=> {
           auto_validate_every=>100,
-      master_read_weight => 1
+          master_read_weight => 1
+        },
+        pool_args=>{
+            maximum_lag=>1,
         },
         deploy_args=>{
           add_drop_table => 1,
@@ -120,22 +122,18 @@ TESTSCHEMACLASSES: {
     ## --------------------------------------------------------------------- ##
     ## Add a connect_info option to test option merging.
     ## --------------------------------------------------------------------- ##
+
     {
     package DBIx::Class::Storage::DBI::Replicated;
 
-    use Moose;
-
-    __PACKAGE__->meta->make_mutable;
-
+    use Moo;
     around connect_info => sub {
       my ($next, $self, $info) = @_;
       $info->[3]{master_option} = 1;
       $self->$next($info);
     };
 
-    __PACKAGE__->meta->make_immutable;
-
-    no Moose;
+    no Moo;
     }
 
     ## --------------------------------------------------------------------- ##
@@ -256,6 +254,7 @@ my $replicated;
 
 for my $method (qw/by_connect_info by_storage_type/) {
   undef $replicated;
+
   ok $replicated = $replicated_class->new($method)
       => "Created a replication object $method";
 
@@ -270,67 +269,45 @@ for my $method (qw/by_connect_info by_storage_type/) {
       => 'configured balancer_type';
 }
 
-### check that all Storage::DBI methods are handled by ::Replicated
+## Check that all Storage::DBI methods are handled by ::Replicated
 {
-  my @storage_dbi_methods = Class::MOP::Class
-    ->initialize('DBIx::Class::Storage::DBI')->get_all_method_names;
+  ## Get a bunch of methods to check
+  my @storage_dbi_methods = @{Class::Inspector->methods('DBIx::Class::Storage::DBI')||[]};
 
-  my @replicated_methods  = DBIx::Class::Storage::DBI::Replicated->meta
-    ->get_all_method_names;
-
-# remove constants and OTHER_CRAP
+  ## remove constants and OTHER_CRAP
   @storage_dbi_methods = grep !/^[A-Z_]+\z/, @storage_dbi_methods;
 
-# remove CAG accessors
+  ## remove CAG accessors
   @storage_dbi_methods = grep !/_accessor\z/, @storage_dbi_methods;
 
-# remove DBIx::Class (the root parent, with CAG and stuff) methods
-  my @root_methods = Class::MOP::Class->initialize('DBIx::Class')
-    ->get_all_method_names;
-  my %count;
-  $count{$_}++ for (@storage_dbi_methods, @root_methods);
-
-  @storage_dbi_methods = grep $count{$_} != 2, @storage_dbi_methods;
+  ## we need to exclude this stuff as well
+  my %root_methods = map { $_ => 1 } @{Class::Inspector->methods('DBIx::Class')};
 
-# make hashes
-  my %storage_dbi_methods;
-  @storage_dbi_methods{@storage_dbi_methods} = ();
-  my %replicated_methods;
-  @replicated_methods{@replicated_methods} = ();
+  @storage_dbi_methods = grep { !$root_methods{$_} } @storage_dbi_methods;
 
-# remove ::Replicated-specific methods
-  for my $method (@replicated_methods) {
-    delete $replicated_methods{$method}
-      unless exists $storage_dbi_methods{$method};
+  ## anything missing?
+  my @missing_methods;
+  for my $method (@storage_dbi_methods) {
+    push @missing_methods, $method
+      unless $replicated->schema->storage->can($method);
   }
-  @replicated_methods = keys %replicated_methods;
-
-# check that what's left is implemented
-  %count = ();
-  $count{$_}++ for (@storage_dbi_methods, @replicated_methods);
 
-  if ((grep $count{$_} == 2, @storage_dbi_methods) == @storage_dbi_methods) {
+  if(scalar(@missing_methods)) {
+    my $missing = join (',', @missing_methods);
+    fail "the following DBIx::Class::Storage::DBI methods are unimplemented: $missing";
+  } else {
     pass 'all DBIx::Class::Storage::DBI methods implemented';
-  }
-  else {
-    my @unimplemented = grep $count{$_} == 1, @storage_dbi_methods;
-
-    fail 'the following DBIx::Class::Storage::DBI methods are unimplemented: '
-      . "@unimplemented";
-  }
+  }  
 }
 
-ok $replicated->schema->storage->meta
-    => 'has a meta object';
-
 isa_ok $replicated->schema->storage->master
     => 'DBIx::Class::Storage::DBI';
 
 isa_ok $replicated->schema->storage->pool
     => 'DBIx::Class::Storage::DBI::Replicated::Pool';
 
-does_ok $replicated->schema->storage->balancer
-    => 'DBIx::Class::Storage::DBI::Replicated::Balancer';
+ok  $replicated->schema->storage->balancer->does('DBIx::Class::Storage::DBI::Replicated::Balancer'),
+  'does Balancer';
 
 ok my @replicant_connects = $replicated->generate_replicant_connect_info
     => 'got replication connect information';
@@ -366,9 +343,8 @@ my @all_storage_opts =
   grep { (reftype($_)||'') eq 'HASH' }
     map @{ $_->_connect_info }, @all_storages;
 
-is ((grep $_->{master_option}, @all_storage_opts),
-    3
-    => 'connect_info was merged from master to replicants');
+  is ((grep $_->{master_option}, @all_storage_opts), 3,
+    'connect_info was merged from master to replicants');
 
 my @replicant_names = keys %{ $replicated->schema->storage->replicants };
 
@@ -377,30 +353,33 @@ ok @replicant_names, "found replicant names @replicant_names";
 ## Silence warning about not supporting the is_replicating method if using the
 ## sqlite dbs.
 $replicated->schema->storage->debugobj->silence(1)
-  if first { m{^t/} } @replicant_names;
+  if first { $_ =~ /$var_dir/ } @replicant_names;
 
 isa_ok $replicated->schema->storage->balancer->current_replicant
     => 'DBIx::Class::Storage::DBI';
 
 $replicated->schema->storage->debugobj->silence(0);
 
-ok $replicated->schema->storage->pool->has_replicants
+ok scalar(keys(%{$replicated->schema->storage->pool->replicants}))
     => 'does have replicants';
 
-is $replicated->schema->storage->pool->num_replicants => 2
+is scalar(keys(%{$replicated->schema->storage->pool->replicants})), 2
     => 'has two replicants';
 
-does_ok $replicated_storages[0]
-    => 'DBIx::Class::Storage::DBI::Replicated::Replicant';
 
-does_ok $replicated_storages[1]
-    => 'DBIx::Class::Storage::DBI::Replicated::Replicant';
+ok $replicated_storages[0]->does('DBIx::Class::Storage::DBI::Replicated::Replicant'),
+  'does Replicant';
+
+ok $replicated_storages[1]->does('DBIx::Class::Storage::DBI::Replicated::Replicant'),
+  'does Replicant';
 
-does_ok $replicated->schema->storage->replicants->{$replicant_names[0]}
-    => 'DBIx::Class::Storage::DBI::Replicated::Replicant';
+ok $replicated->schema->storage->replicants->{$replicant_names[0]}
+    ->does('DBIx::Class::Storage::DBI::Replicated::Replicant'),
+    'Does Replicant';
 
-does_ok $replicated->schema->storage->replicants->{$replicant_names[1]}
-    => 'DBIx::Class::Storage::DBI::Replicated::Replicant';
+ok $replicated->schema->storage->replicants->{$replicant_names[1]}
+    ->does('DBIx::Class::Storage::DBI::Replicated::Replicant'),
+    'Does Replicant';
 
 ## Add some info to the database
 
@@ -425,7 +404,7 @@ $replicated->schema->storage->replicants->{$replicant_names[1]}->active(1);
 ## Silence warning about not supporting the is_replicating method if using the
 ## sqlite dbs.
 $replicated->schema->storage->debugobj->silence(1)
-  if first { m{^t/} } @replicant_names;
+  if first { $_ =~ /$var_dir/ } @replicant_names;
 
 $replicated->schema->storage->pool->validate_replicants;
 
@@ -597,7 +576,7 @@ $replicated->schema->storage->replicants->{$replicant_names[1]}->active(0);
         "got last query from a master: $debug{dsn}";
 
     like $fallback_warning, qr/falling back to master/
-        => 'emits falling back to master warning';
+        => 'emits falling back to master debug';
 
     $replicated->schema->storage->debugfh($oldfh);
 }
@@ -608,17 +587,29 @@ $replicated->schema->storage->replicants->{$replicant_names[1]}->active(1);
 ## Silence warning about not supporting the is_replicating method if using the
 ## sqlite dbs.
 $replicated->schema->storage->debugobj->silence(1)
-  if first { m{^t/} } @replicant_names;
+  if first { $_ =~ /$var_dir/ } @replicant_names;
 
 $replicated->schema->storage->pool->validate_replicants;
 
 $replicated->schema->storage->debugobj->silence(0);
 
-ok $replicated->schema->resultset('Artist')->find(2)
-    => 'Returned to replicates';
+{
+    ## catch the fallback to master warning
+    open my $debugfh, '>', \my $return_warning;
+    my $oldfh = $replicated->schema->storage->debugfh;
+    $replicated->schema->storage->debugfh($debugfh);
+
+    ok $replicated->schema->resultset('Artist')->find(2)
+        => 'Return to replicants';
 
-is $debug{storage_type}, 'REPLICANT',
-    "got last query from a replicant: $debug{dsn}";
+    is $debug{storage_type}, 'REPLICANT',
+      "got last query from a replicant: $debug{dsn}";
+
+    like $return_warning, qr/Moved back to slave/
+        => 'emits returning to slave debug';
+
+    $replicated->schema->storage->debugfh($oldfh);
+}
 
 ## Getting slave status tests
 
@@ -734,7 +725,7 @@ ok my $transaction = sub {
         ->schema
         ->populate('Artist', [
             [ qw/artistid name/ ],
-            [ $id, "Children of the Grave"],
+            [ $id, "Children of the Grave $id"],
         ]);
 
     ok my $result = $replicated->schema->resultset('Artist')->find($id)