# Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to You under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. use strict; use warnings; use Test::More tests => 20; package TestObj; use base qw( Lucy::Object::Obj ); our $version = $Lucy::VERSION; package SonOfTestObj; use base qw( TestObj ); { sub to_string { my $self = shift; return "STRING: " . $self->SUPER::to_string; } sub serialize { my ( $self, $outstream ) = @_; $self->SUPER::serialize($outstream); $outstream->write_string("zowie"); } sub deserialize { my ( $self, $instream ) = @_; $self = $self->SUPER::deserialize($instream); $instream->read_string; return $self; } } package BadSerialize; use base qw( Lucy::Object::Obj ); { sub serialize { } } package BadDump; use base qw( Lucy::Object::Obj ); { sub dump { } } package main; use Storable qw( freeze thaw ); ok( defined $TestObj::version, "Using base class should grant access to " . "package globals in the Lucy:: namespace" ); # TODO: Port this test to C. eval { my $foo = Lucy::Object::Obj->new }; like( $@, qr/abstract/i, "Obj is an abstract class" ); my $object = TestObj->new; isa_ok( $object, "Lucy::Object::Obj", "Clownfish objects can be subclassed outside the Lucy hierarchy" ); # TODO: Port this test to C. eval { my $twin = $object->clone }; like( $@, qr/abstract/i, "clone throws an abstract method exception" ); ok( $object->is_a("Lucy::Object::Obj"), "custom is_a correct" ); ok( !$object->is_a("Lucy::Object"), "custom is_a too long" ); ok( !$object->is_a("Lucy"), "custom is_a substring" ); ok( !$object->is_a(""), "custom is_a blank" ); ok( !$object->is_a("thing"), "custom is_a wrong" ); eval { my $another_obj = TestObj->new( kill_me_now => 1 ) }; like( $@, qr/kill_me_now/, "reject bad param" ); my $stringified_perl_obj = "$object"; require Lucy::Object::Hash; my $hash = Lucy::Object::Hash->new; $hash->store( foo => $object ); is( $object->get_refcount, 2, "refcount increased via C code" ); is( $object->get_refcount, 2, "refcount increased via C code" ); undef $object; $object = $hash->fetch("foo"); is( "$object", $stringified_perl_obj, "same perl object as before" ); is( $object->get_refcount, 2, "correct refcount after retrieval" ); undef $hash; is( $object->get_refcount, 1, "correct refcount after destruction of ref" ); my $copy = thaw( freeze($object) ); is( ref($copy), ref($object), "freeze/thaw" ); $object = SonOfTestObj->new; like( $object->to_string, qr/STRING:.*?SonOfTestObj/, "overridden XS bindings can be called via SUPER" ); my $frozen = freeze($object); my $dupe = thaw($frozen); is( ref($dupe), ref($object), "override serialize/deserialize" ); SKIP: { skip( "Invalid serialization causes leaks", 1 ) if $ENV{LUCY_VALGRIND}; my $bad = BadSerialize->new; eval { my $froze = freeze($bad); }; like( $@, qr/empty/i, "Don't allow subclasses to perform invalid serialization" ); } SKIP: { skip( "Exception thrown within callback leaks", 1 ) if $ENV{LUCY_VALGRIND}; $hash = Lucy::Object::Hash->new; $hash->store( foo => BadDump->new ); eval { $hash->dump }; like( $@, qr/NULL/, "Don't allow methods without nullable return values to return NULL" ); }