Ancient
view release on metacpan or search on metacpan
t/4018-object-multi-import.t view on Meta::CPAN
#!/usr/bin/perl
use strict;
use warnings;
use Test::More;
use lib 'blib/lib', 'blib/arch';
# Test object module with multiple imports from different object types
# This tests import_accessor and import_accessors across multiple classes
# Define multiple object types and import their accessors in BEGIN block
BEGIN {
require object;
# Define several object types with different properties
object::define('Person', qw(name age email));
object::define('Address', qw(street city zipcode country));
object::define('Product', qw(sku name price quantity));
object::define('Order', qw(id customer_name total status));
object::define('Config', qw(host port timeout debug));
# Import accessors from multiple objects
object::import_accessors('Person'); # name, age, email
object::import_accessors('Address'); # street, city, zipcode, country
# Import specific accessors with aliases to avoid conflicts
object::import_accessor('Product', 'name', 'product_name');
object::import_accessor('Product', 'sku', 'product_sku');
object::import_accessor('Product', 'price', 'price');
object::import_accessor('Product', 'quantity', 'qty');
object::import_accessor('Order', 'id', 'order_id');
object::import_accessor('Order', 'customer_name', 'customer');
object::import_accessor('Order', 'total', 'order_total');
object::import_accessor('Order', 'status', 'order_status');
object::import_accessors('Config'); # host, port, timeout, debug
}
use object;
# ============================================
# Basic multi-object access
# ============================================
subtest 'basic multi-object creation and access' => sub {
my $person = new Person 'Alice', 30, 'alice@example.com';
my $address = new Address '123 Main St', 'Springfield', '12345', 'USA';
is(name($person), 'Alice', 'Person name accessor');
is(age($person), 30, 'Person age accessor');
is(email($person), 'alice@example.com', 'Person email accessor');
is(street($address), '123 Main St', 'Address street accessor');
is(city($address), 'Springfield', 'Address city accessor');
is(zipcode($address), '12345', 'Address zipcode accessor');
is(country($address), 'USA', 'Address country accessor');
};
subtest 'aliased accessors for conflicting names' => sub {
# Product has 'name' which conflicts with Person's 'name'
my $product = new Product 'SKU001', 'Widget', 9.99, 100;
is(product_name($product), 'Widget', 'Product name via aliased accessor');
is(product_sku($product), 'SKU001', 'Product SKU accessor');
is(price($product), 9.99, 'Product price accessor');
is(qty($product), 100, 'Product quantity via aliased accessor');
};
subtest 'order accessors with aliases' => sub {
my $order = new Order 'ORD-123', 'Bob Smith', 150.00, 'pending';
is(order_id($order), 'ORD-123', 'Order id via alias');
is(customer($order), 'Bob Smith', 'Order customer via alias');
is(order_total($order), 150.00, 'Order total via alias');
is(order_status($order), 'pending', 'Order status via alias');
};
# ============================================
# Setters with multiple imports
# ============================================
subtest 'setters work across multiple objects' => sub {
my $person = new Person 'Charlie', 25, 'charlie@test.com';
my $address = new Address '456 Oak Ave', 'Shelbyville', '67890', 'USA';
# Update using function-style setters
name($person, 'Charles');
age($person, 26);
is(name($person), 'Charles', 'Person name updated');
is(age($person), 26, 'Person age updated');
city($address, 'Capital City');
zipcode($address, '99999');
is(city($address), 'Capital City', 'Address city updated');
t/4018-object-multi-import.t view on Meta::CPAN
subtest 'iterate mixed object types' => sub {
my @items = (
new Person('Alice', 30, 'alice@test.com'),
new Address('123 Main', 'City', '12345', 'USA'),
);
# Use method syntax when mixing types
my @results;
for my $item (@items) {
if ($item->isa('Person')) {
push @results, "Person: " . name($item);
} elsif ($item->isa('Address')) {
push @results, "Address: " . city($item);
}
}
is_deeply(\@results, ['Person: Alice', 'Address: City'], 'mixed type iteration');
};
# ============================================
# Complex workflows with multiple objects
# ============================================
subtest 'e-commerce workflow with multiple objects' => sub {
# Create customer
my $customer = new Person 'Dave', 40, 'dave@shop.com';
# Create shipping address
my $shipping = new Address '789 Pine Rd', 'Anytown', '54321', 'USA';
# Create products
my @products = (
new Product('SKU-A', 'Item A', 10.00, 2),
new Product('SKU-B', 'Item B', 20.00, 1),
new Product('SKU-C', 'Item C', 5.00, 4),
);
# Calculate order total
my $total = 0;
for my $p (@products) {
$total += price($p) * qty($p);
}
# Create order
my $order = new Order 'ORD-001', name($customer), $total, 'processing';
is(order_total($order), 60.00, 'Order total calculated correctly');
is(customer($order), 'Dave', 'Order customer matches person name');
# Update order status
order_status($order, 'shipped');
is(order_status($order), 'shipped', 'Order status updated');
};
subtest 'config management with function accessors' => sub {
my $dev_config = new Config 'localhost', 3000, 30, 1;
my $prod_config = new Config 'api.example.com', 443, 60, 0;
is(host($dev_config), 'localhost', 'dev host');
is(port($dev_config), 3000, 'dev port');
is(debug($dev_config), 1, 'dev debug enabled');
is(host($prod_config), 'api.example.com', 'prod host');
is(port($prod_config), 443, 'prod port');
is(debug($prod_config), 0, 'prod debug disabled');
# Update timeout across configs
timeout($dev_config, 120);
timeout($prod_config, 90);
is(timeout($dev_config), 120, 'dev timeout updated');
is(timeout($prod_config), 90, 'prod timeout updated');
};
# ============================================
# Simultaneous access to same-named properties
# ============================================
subtest 'same property name different objects' => sub {
# Both Person and Product have 'name', but Product is aliased
my $person = new Person 'Eve', 28, 'eve@test.com';
my $product = new Product 'SKU-X', 'Thingamajig', 15.00, 10;
# name() is for Person
is(name($person), 'Eve', 'name() accesses Person');
# product_name() is for Product
is(product_name($product), 'Thingamajig', 'product_name() accesses Product');
# Both objects unchanged by accessing the other
is(name($person), 'Eve', 'Person name still correct');
is(product_name($product), 'Thingamajig', 'Product name still correct');
};
# ============================================
# Nested data structures with objects
# ============================================
subtest 'array of objects with function accessors' => sub {
my @addresses = (
new Address('111 First St', 'Town A', '11111', 'USA'),
new Address('222 Second St', 'Town B', '22222', 'USA'),
new Address('333 Third St', 'Town C', '33333', 'USA'),
);
# Extract all cities
my @cities = map { city($_) } @addresses;
is_deeply(\@cities, ['Town A', 'Town B', 'Town C'], 'extracted cities');
# Find address by zipcode
my ($found) = grep { zipcode($_) eq '22222' } @addresses;
is(street($found), '222 Second St', 'found address by zipcode');
};
subtest 'hash of objects' => sub {
my %configs = (
dev => new Config('localhost', 3000, 30, 1),
test => new Config('test.example.com', 8080, 45, 1),
prod => new Config('api.example.com', 443, 60, 0),
);
is(host($configs{dev}), 'localhost', 'hash access dev host');
is(port($configs{test}), 8080, 'hash access test port');
is(timeout($configs{prod}), 60, 'hash access prod timeout');
# Update via hash access
debug($configs{prod}, 1); # Enable debug in prod (oops!)
is(debug($configs{prod}), 1, 'updated via hash access');
};
# ============================================
# Object transformation pipelines
# ============================================
subtest 'transform objects in pipeline' => sub {
my @people = (
new Person('alice', 30, 'alice@test.com'),
new Person('bob', 25, 'bob@test.com'),
new Person('charlie', 35, 'charlie@test.com'),
);
# Capitalize names
for my $p (@people) {
name($p, ucfirst(name($p)));
}
# Verify each name individually (order may vary due to hash internals)
is(name($people[0]), 'Alice', 'first name capitalized');
is(name($people[1]), 'Bob', 'second name capitalized');
is(name($people[2]), 'Charlie', 'third name capitalized');
# Increment ages
for my $p (@people) {
age($p, age($p) + 1);
}
is(age($people[0]), 31, 'first age incremented');
is(age($people[1]), 26, 'second age incremented');
is(age($people[2]), 36, 'third age incremented');
};
subtest 'filter and transform products' => sub {
my @products = (
new Product('SKU-1', 'Cheap Item', 5.00, 100),
new Product('SKU-2', 'Mid Item', 25.00, 50),
new Product('SKU-3', 'Expensive Item', 100.00, 10),
new Product('SKU-4', 'Another Cheap', 8.00, 80),
);
# Find products under $20
my @cheap = grep { price($_) < 20 } @products;
is(scalar(@cheap), 2, 'found 2 cheap products');
# Apply 10% discount to cheap products
for my $p (@cheap) {
price($p, price($p) * 0.9);
}
# Verify discounts applied (check the specific products, not grep order)
is(price($products[0]), 4.50, 'SKU-1 (cheap) discounted to 4.50');
is(price($products[3]), 7.20, 'SKU-4 (cheap) discounted to 7.20');
is(price($products[1]), 25.00, 'SKU-2 (mid) unchanged');
is(price($products[2]), 100.00, 'SKU-3 (expensive) unchanged');
# Calculate total inventory value
my $total_value = 0;
for my $p (@products) {
$total_value += price($p) * qty($p);
( run in 1.071 second using v1.01-cache-2.11-cpan-5511b514fd6 )