DBIO
view release on metacpan or search on metacpan
t/test/17_async_future_io_mro_walk.t view on Meta::CPAN
use strict;
use warnings;
use Test::More;
use DBIO::Test;
use DBIO::Storage::Async;
use DBIO::Storage::DBI;
use DBIO::Test::Storage;
# karr #67 -- ADR 0030, second future_io refinement.
#
# t/test/16_async_future_io_convention.t (karr #65) locked in the SINGLE
# candidate rule: future_io's transport adapter is ref($storage) . '::Async',
# tried exactly once. That works for a driver storage class directly under
# DBIO::Storage::DBI, but an EXTENSION storage_type subclass (the
# DBIO::PostgreSQL::Age::Storage / DBIO::PostgreSQL::PostGIS::Storage pattern
# -- isa the driver's own storage, not DBIO::Storage::DBI directly) has no
# ::Async sibling of its own and loses future_io entirely, even for plain CRUD,
# while the 'ev' registry mode (which already walks the MRO) keeps working on
# the very same schema. This is a core resolution gap, not a driver bug.
#
# The decided fix (see karr #67, ADR 0030 refinement): the future_io
# convention walks mro::get_linear_isa(ref($self)), most-specific first,
# exactly like the registry resolver (_resolve_async_mode_class) already does
# for 'ev'/'forked' -- but STOPS strictly BEFORE the generic
# DBIO::Storage::DBI base (never probes DBIO::Storage::DBI::Async or
# anything above it -- that hole is exactly what karr #65 banned). A
# candidate that LOADS but is not a DBIO::Storage::Async croaks immediately,
# it never silently falls through to a parent's otherwise-valid adapter.
#
# This file is the RED test for that fix: cases 2 and 4b below fail today
# (still single-candidate) and must turn green once the walk lands. Cases 1,
# 3, and 5 are regression guards -- already green today, and must STAY green
# after the fix. Case 6 (the generic-base stop boundary) lives in its own
# file, t/test/18_async_future_io_mro_walk_base_guard.t, because it plants a
# package directly into the real DBIO::Storage::DBI namespace and that
# pollution must never coexist in the same process as the classes here.
#
# Mock only (DBIO::Test::Storage, no real DBD). No event loop is exercised --
# these tests only drive the pure CLASS resolution path in
# DBIO::Storage::DBI::_async_storage; the resolved adapter is never asked to
# actually run a query (that CRUD round-trip is already covered by t/test/16).
# ---------------------------------------------------------------------------
# Fake driver hierarchy (ticket's illustrative names, Karr67::-namespaced here
# to avoid polluting the global namespace, matching the Karr66::/AsyncConv::
# convention already used by the sibling async tests).
# ---------------------------------------------------------------------------
# Case 1 (baseline): TestDrv::Storage + its own TestDrv::Storage::Async.
{
package Karr67::TestDrv::Storage;
use base 'DBIO::Test::Storage';
use mro 'c3';
}
{
package Karr67::TestDrv::Storage::Async;
use base 'DBIO::Storage::Async';
}
# Case 2: TestExt::Storage isa TestDrv::Storage, no ::Async of its own --
# must walk up and resolve TestDrv::Storage::Async.
{
package Karr67::TestExt::Storage;
use base 'Karr67::TestDrv::Storage';
use mro 'c3';
}
# Case 3: TestExt2::Storage isa TestDrv::Storage, WITH its own ::Async
# (itself a valid DBIO::Storage::Async, subclassing the parent's adapter) --
# the own one must win, not the parent's.
{
( run in 0.682 second using v1.01-cache-2.11-cpan-5e09290becf )