From 3de07595b0138d7e2433db967100091bee14e898 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vin=C3=ADcius=20Ferr=C3=A3o?= <2031761+viniciusferrao@users.noreply.github.com> Date: Tue, 13 Oct 2026 23:41:04 -0300 Subject: [PATCH] test(table): cover the cache after a rollback A cached reader that saw an update before a rollback must see the committed value after the rollback. This also holds when the rollback goes through another table on the same handle, and after a table failed to open on that handle. --- xCAT-test/unit/table_rollback_shared_cache.t | 31 ++++++++++++++++++++ xCAT-test/unit/table_setattribswhere_cache.t | 10 +++++++ 2 files changed, 41 insertions(+) create mode 100644 xCAT-test/unit/table_rollback_shared_cache.t diff --git a/xCAT-test/unit/table_rollback_shared_cache.t b/xCAT-test/unit/table_rollback_shared_cache.t new file mode 100644 index 000000000..3863da659 --- /dev/null +++ b/xCAT-test/unit/table_rollback_shared_cache.t @@ -0,0 +1,31 @@ +#!/usr/bin/env perl +use strict; +use warnings; +use FindBin; +use lib "$FindBin::Bin/../../perl-xCAT"; +use File::Temp qw(tempdir); +use Test::More; + +# A generic DBI database gives all tables of one autocommit mode one handle, as MySQL and PostgreSQL do. +my $fixture = tempdir(CLEANUP => 1); +$ENV{XCATCFG} = "dbi:SQLite:dbname=$fixture/xcatdb"; +require xCAT::Table; + +xCAT::Table->new('nodelist', -create => 1)->setAttribs({ node => 'cachenode' }, { groups => 'compute' }); +my $scripts = xCAT::Table->new('postscripts', -create => 1, -autocommit => 0); +my $other = xCAT::Table->new('site', -create => 1, -autocommit => 0); +is($scripts->{dbh}, $other->{dbh}, 'the tables share one handle'); +$scripts->setAttribs({ node => 'cachenode' }, { postscripts => 'committed script' }); +$scripts->commit; + +$scripts->setAttribsWhere(xCAT::Table::delimitcol('node') . " = 'cachenode'", { postscripts => 'rejected script' }); +my ($entry) = $scripts->getNodeAttribs('cachenode', ['postscripts'], prefetchcache => 1); +is($entry && $entry->{postscripts}, 'rejected script', 'the cached reader sees the update before the rollback'); + +# A table that does not exist fails to open on the same handle. +ok(!xCAT::Table->new('networks', -create => 0, -autocommit => 0), 'a table that does not exist fails to open'); +ok(eval { $other->rollback; 1 }, 'the rollback completes after a table failed to open') or diag($@); +($entry) = $scripts->getNodeAttribs('cachenode', ['postscripts'], prefetchcache => 1); +is($entry && $entry->{postscripts}, 'committed script', 'a rollback through another table of the handle refreshes the cache'); + +done_testing(); diff --git a/xCAT-test/unit/table_setattribswhere_cache.t b/xCAT-test/unit/table_setattribswhere_cache.t index 62c74018a..c53273c25 100644 --- a/xCAT-test/unit/table_setattribswhere_cache.t +++ b/xCAT-test/unit/table_setattribswhere_cache.t @@ -26,4 +26,14 @@ is($rc, 0, 'the conditional update succeeds'); ($entry) = $tab->getNodeAttribs('cachenode', ['postscripts'], prefetchcache => 1); is($entry && $entry->{postscripts}, 'script after the update', 'the cached reader sees the conditional update at once'); +{ + # A cached read sees a conditional update before the rollback rejects it. + $tab->setAttribsWhere(xCAT::Table::delimitcol('node') . " = 'cachenode'", { postscripts => 'script that the rollback rejects' }); + ($entry) = $tab->getNodeAttribs('cachenode', ['postscripts'], prefetchcache => 1); + is($entry && $entry->{postscripts}, 'script that the rollback rejects', 'the cached reader sees the update before the rollback'); + $tab->rollback; + ($entry) = $tab->getNodeAttribs('cachenode', ['postscripts'], prefetchcache => 1); + is($entry && $entry->{postscripts}, 'script after the update', 'the cached reader sees the committed value after the rollback'); +} + done_testing();