A number of equivalent-logic ::FC refactors
[dbsrgits/DBIx-Class.git] / t / row / filter_column.t
index a844962..fb8dd00 100644 (file)
@@ -2,18 +2,19 @@ use strict;
 use warnings;
 
 use Test::More;
+use Test::Exception;
 use lib qw(t/lib);
 use DBICTest;
 
 my $from_storage_ran = 0;
 my $to_storage_ran = 0;
 my $schema = DBICTest->init_schema();
-DBICTest::Schema::Artist->load_components('FilterColumn');
+DBICTest::Schema::Artist->load_components(qw(FilterColumn InflateColumn));
 DBICTest::Schema::Artist->filter_column(rank => {
   filter_from_storage => sub { $from_storage_ran++; $_[1] * 2 },
   filter_to_storage   => sub { $to_storage_ran++; $_[1] / 2 },
 });
-Class::C3->reinitialize();
+Class::C3->reinitialize() if DBIx::Class::_ENV_::OLD_MRO;
 
 my $artist = $schema->resultset('Artist')->create( { rank => 20 } );
 
@@ -68,66 +69,152 @@ MC: {
    is $cd->artist->rank, 20, 'artist rank gets correctly filtered w/ MC';
 }
 
-my $expected_from = $from_storage_ran;
-my $expected_to   = $to_storage_ran;
+CACHE_TEST: {
+  my $expected_from = $from_storage_ran;
+  my $expected_to   = $to_storage_ran;
+
+  # ensure we are creating a fresh obj
+  $artist = $schema->resultset('Artist')->single($artist->ident_condition);
+
+  is $from_storage_ran, $expected_from, 'from has not run yet';
+  is $to_storage_ran, $expected_to, 'to has not run yet';
+
+  $artist->rank;
+  cmp_ok (
+    $artist->get_filtered_column('rank'),
+      '!=',
+    $artist->get_column('rank'),
+    'filter/unfilter differ'
+  );
+  is $from_storage_ran, ++$expected_from, 'from ran once, therefor caches';
+  is $to_storage_ran, $expected_to,  'to did not run';
+
+  $artist->rank(6);
+  is $from_storage_ran, $expected_from, 'from did not run';
+  is $to_storage_ran, ++$expected_to,  'to ran once';
+
+  ok ($artist->is_column_changed ('rank'), 'Column marked as dirty');
+
+  $artist->rank;
+  is $from_storage_ran, $expected_from, 'from did not run';
+  is $to_storage_ran, $expected_to,  'to did not run';
+
+  $artist->update;
+
+  $artist->set_column(rank => 3);
+  ok (! $artist->is_column_changed ('rank'), 'Column not marked as dirty on same set_column value');
+  is ($artist->rank, '6', 'Column set properly (cache blown)');
+  is $from_storage_ran, ++$expected_from, 'from ran once (set_column blew cache)';
+  is $to_storage_ran, $expected_to,  'to did not run';
+
+  $artist->rank(6);
+  ok (! $artist->is_column_changed ('rank'), 'Column not marked as dirty on same accessor-set value');
+  is ($artist->rank, '6', 'Column set properly');
+  is $from_storage_ran, $expected_from, 'from did not run';
+  is $to_storage_ran, ++$expected_to,  'to did run once (call in to set_column)';
+
+  $artist->store_column(rank => 4);
+  ok (! $artist->is_column_changed ('rank'), 'Column not marked as dirty on differing store_column value');
+  is ($artist->rank, '8', 'Cache properly blown');
+  is $from_storage_ran, ++$expected_from, 'from did not run';
+  is $to_storage_ran, $expected_to,  'to did not run';
+}
+
+# test in-memory operations
+for my $artist_maker (
+  sub { $schema->resultset('Artist')->new({ rank => 42 }) },
+  sub { my $art = $schema->resultset('Artist')->new({}); $art->rank(42); $art },
+) {
+
+  my $expected_from = $from_storage_ran;
+  my $expected_to   = $to_storage_ran;
 
-# ensure we are creating a fresh obj
-$artist = $schema->resultset('Artist')->single($artist->ident_condition);
+  my $artist = $artist_maker->();
 
-is $from_storage_ran, $expected_from, 'from has not run yet';
-is $to_storage_ran, $expected_to, 'to has not run yet';
+  is $from_storage_ran, $expected_from, 'from has not run yet';
+  is $to_storage_ran, $expected_to, 'to has not run yet';
+
+  ok( ! $artist->has_column_loaded('artistid'), 'pk not loaded' );
+  ok( $artist->has_column_loaded('rank'), 'Filtered column marked as loaded under new' );
+  is( $artist->rank, 42, 'Proper unfiltered value' );
+  is( $artist->get_column('rank'), 21, 'Proper filtered value' );
+}
 
-$artist->rank;
-cmp_ok (
-  $artist->get_filtered_column('rank'),
-    '!=',
-  $artist->get_column('rank'),
-  'filter/unfilter differ'
-);
-is $from_storage_ran, ++$expected_from, 'from ran once, therefor caches';
-is $to_storage_ran, $expected_to,  'to did not run';
+IC_DIE: {
+  throws_ok {
+     DBICTest::Schema::Artist->inflate_column(rank =>
+        { inflate => sub {}, deflate => sub {} }
+     );
+  } qr/InflateColumn can not be used on a column with a declared FilterColumn filter/, q(Can't inflate column after filter column);
+
+  DBICTest::Schema::Artist->inflate_column(name =>
+     { inflate => sub {}, deflate => sub {} }
+  );
+
+  throws_ok {
+     DBICTest::Schema::Artist->filter_column(name => {
+        filter_to_storage => sub {},
+        filter_from_storage => sub {}
+     });
+  } qr/FilterColumn can not be used on a column with a declared InflateColumn inflator/, q(Can't filter column after inflate column);
+}
 
-$artist->rank(6);
-is $from_storage_ran, $expected_from, 'from did not run';
-is $to_storage_ran, ++$expected_to,  'to ran once';
+# test when we do not set both filter_from_storage/filter_to_storage
+DBICTest::Schema::Artist->filter_column(rank => {
+  filter_to_storage => sub { $to_storage_ran++; $_[1] },
+});
+Class::C3->reinitialize() if DBIx::Class::_ENV_::OLD_MRO;
 
-ok ($artist->is_column_changed ('rank'), 'Column marked as dirty');
+ASYMMETRIC_TO_TEST: {
+  # initialise value
+  $artist->rank(20);
+  $artist->update;
 
-$artist->rank;
-is $from_storage_ran, ++$expected_from, 'from ran once';
-is $to_storage_ran, $expected_to,  'to did not run';
+  my $expected_from = $from_storage_ran;
+  my $expected_to   = $to_storage_ran;
 
-$artist->rank;
-is $from_storage_ran, $expected_from, 'from did not run';
-is $to_storage_ran, $expected_to,  'to did not run';
+  $artist->rank(10);
+  ok ($artist->is_column_changed ('rank'), 'Column marked as dirty on accessor-set value');
+  is ($artist->rank, '10', 'Column set properly');
+  is $from_storage_ran, $expected_from, 'from did not run';
+  is $to_storage_ran, ++$expected_to,  'to did run';
 
-$artist->update;
+  $artist->discard_changes;
 
-$artist->set_column(rank => 3);
-ok (! $artist->is_column_changed ('rank'), 'Column not marked as dirty on same set_column value');
-is ($artist->rank, '6', 'Column set properly (cache blown)');
-is $from_storage_ran, ++$expected_from, 'from ran once (set_column blew cache)';
-is $to_storage_ran, $expected_to,  'to did not run';
-
-$artist->rank(6);
-ok (! $artist->is_column_changed ('rank'), 'Column not marked as dirty on same accessor-set value');
-is ($artist->rank, '6', 'Column set properly');
-is $from_storage_ran, $expected_from, 'from did not run';
-is $to_storage_ran, $expected_to,  'to did not run';
-
-$artist->store_column(rank => 4);
-ok (! $artist->is_column_changed ('rank'), 'Column not marked as dirty on differing store_column value');
-is ($artist->rank, '6', 'Filtered column still contains old value (cache not blown)');
-is $from_storage_ran, $expected_from, 'from did not run';
-is $to_storage_ran, $expected_to,  'to did not run';
-
-$artist->set_column(rank => 4);
-TODO: {
-  local $TODO = 'There seems to be no way around that much wizardry... which is ok';
-  ok ($artist->is_column_changed ('rank'), 'Column marked as dirty on out-of-sync set_column value');
+  is ($artist->rank, '20', 'Column set properly');
+  is $from_storage_ran, $expected_from, 'from did not run';
+  is $to_storage_ran, $expected_to,  'to did not run';
 }
-is ($artist->rank, '8', 'Column set properly (cache blown)');
-is $from_storage_ran, ++$expected_from, 'from ran once (set_column blew cache)';
-is $to_storage_ran, $expected_to,  'to did not run';
+
+DBICTest::Schema::Artist->filter_column(rank => {
+  filter_from_storage => sub { $from_storage_ran++; $_[1] },
+});
+Class::C3->reinitialize() if DBIx::Class::_ENV_::OLD_MRO;
+
+ASYMMETRIC_FROM_TEST: {
+  # initialise value
+  $artist->rank(23);
+  $artist->update;
+
+  my $expected_from = $from_storage_ran;
+  my $expected_to   = $to_storage_ran;
+
+  $artist->rank(13);
+  ok ($artist->is_column_changed ('rank'), 'Column marked as dirty on accessor-set value');
+  is ($artist->rank, '13', 'Column set properly');
+  is $from_storage_ran, $expected_from, 'from did not run';
+  is $to_storage_ran, $expected_to,  'to did not run';
+
+  $artist->discard_changes;
+
+  is ($artist->rank, '23', 'Column set properly');
+  is $from_storage_ran, ++$expected_from, 'from did run';
+  is $to_storage_ran, $expected_to,  'to did not run';
+}
+
+throws_ok { DBICTest::Schema::Artist->filter_column( rank => {} ) }
+  qr/\QAn invocation of filter_column() must specify either a filter_from_storage or filter_to_storage/,
+  'Correctly throws exception for empty attributes'
+;
 
 done_testing;