⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 builder.pm

📁 视频监控网络部分的协议ddns,的模块的实现代码,请大家大胆指正.
💻 PM
📖 第 1 页 / 共 3 页
字号:
package Test::Builder;use 5.004;# $^C was only introduced in 5.005-ish.  We do this to prevent# use of uninitialized value warnings in older perls.$^C ||= 0;use strict;use vars qw($VERSION);$VERSION = '0.74';$VERSION = eval $VERSION;    # make the alpha version come out as a number# Make Test::Builder thread-safe for ithreads.BEGIN {    use Config;    # Load threads::shared when threads are turned on.    # 5.8.0's threads are so busted we no longer support them.    if( $] >= 5.008001 && $Config{useithreads} && $INC{'threads.pm'}) {        require threads::shared;        # Hack around YET ANOTHER threads::shared bug.  It would         # occassionally forget the contents of the variable when sharing it.        # So we first copy the data, then share, then put our copy back.        *share = sub (\[$@%]) {            my $type = ref $_[0];            my $data;            if( $type eq 'HASH' ) {                %$data = %{$_[0]};            }            elsif( $type eq 'ARRAY' ) {                @$data = @{$_[0]};            }            elsif( $type eq 'SCALAR' ) {                $$data = ${$_[0]};            }            else {                die("Unknown type: ".$type);            }            $_[0] = &threads::shared::share($_[0]);            if( $type eq 'HASH' ) {                %{$_[0]} = %$data;            }            elsif( $type eq 'ARRAY' ) {                @{$_[0]} = @$data;            }            elsif( $type eq 'SCALAR' ) {                ${$_[0]} = $$data;            }            else {                die("Unknown type: ".$type);            }            return $_[0];        };    }    # 5.8.0's threads::shared is busted when threads are off    # and earlier Perls just don't have that module at all.    else {        *share = sub { return $_[0] };        *lock  = sub { 0 };    }}=head1 NAMETest::Builder - Backend for building test libraries=head1 SYNOPSIS  package My::Test::Module;  use Test::Builder;  require Exporter;  @ISA = qw(Exporter);  @EXPORT = qw(ok);  my $Test = Test::Builder->new;  $Test->output('my_logfile');  sub import {      my($self) = shift;      my $pack = caller;      $Test->exported_to($pack);      $Test->plan(@_);      $self->export_to_level(1, $self, 'ok');  }  sub ok {      my($test, $name) = @_;      $Test->ok($test, $name);  }=head1 DESCRIPTIONTest::Simple and Test::More have proven to be popular testing modules,but they're not always flexible enough.  Test::Builder provides the abuilding block upon which to write your own test libraries I<which canwork together>.=head2 Construction=over 4=item B<new>  my $Test = Test::Builder->new;Returns a Test::Builder object representing the current state of thetest.Since you only run one test per program C<new> always returns the sameTest::Builder object.  No matter how many times you call new(), you'regetting the same object.  This is called a singleton.  This is done so thatmultiple modules share such global information as the test counter andwhere test output is going.If you want a completely new Test::Builder object different from thesingleton, use C<create>.=cutmy $Test = Test::Builder->new;sub new {    my($class) = shift;    $Test ||= $class->create;    return $Test;}=item B<create>  my $Test = Test::Builder->create;Ok, so there can be more than one Test::Builder object and this is howyou get it.  You might use this instead of C<new()> if you're testinga Test::Builder based module, but otherwise you probably want C<new>.B<NOTE>: the implementation is not complete.  C<level>, for example, isstill shared amongst B<all> Test::Builder objects, even ones created usingthis method.  Also, the method name may change in the future.=cutsub create {    my $class = shift;    my $self = bless {}, $class;    $self->reset;    return $self;}=item B<reset>  $Test->reset;Reinitializes the Test::Builder singleton to its original state.Mostly useful for tests run in persistent environments where the sametest might be run multiple times in the same process.=cutuse vars qw($Level);sub reset {    my ($self) = @_;    # We leave this a global because it has to be localized and localizing    # hash keys is just asking for pain.  Also, it was documented.    $Level = 1;    $self->{Test_Died}    = 0;    $self->{Have_Plan}    = 0;    $self->{No_Plan}      = 0;    $self->{Original_Pid} = $$;    share($self->{Curr_Test});    $self->{Curr_Test}    = 0;    $self->{Test_Results} = &share([]);    $self->{Exported_To}    = undef;    $self->{Expected_Tests} = 0;    $self->{Skip_All}   = 0;    $self->{Use_Nums}   = 1;    $self->{No_Header}  = 0;    $self->{No_Ending}  = 0;    $self->_dup_stdhandles unless $^C;    return undef;}=back=head2 Setting up testsThese methods are for setting up tests and declaring how many thereare.  You usually only want to call one of these methods.=over 4=item B<exported_to>  my $pack = $Test->exported_to;  $Test->exported_to($pack);Tells Test::Builder what package you exported your functions to.This is important for getting TODO tests right.=cutsub exported_to {    my($self, $pack) = @_;    if( defined $pack ) {        $self->{Exported_To} = $pack;    }    return $self->{Exported_To};}=item B<plan>  $Test->plan('no_plan');  $Test->plan( skip_all => $reason );  $Test->plan( tests => $num_tests );A convenient way to set up your tests.  Call this and Test::Builderwill print the appropriate headers and take the appropriate actions.If you call plan(), don't call any of the other methods below.=cutsub plan {    my($self, $cmd, $arg) = @_;    return unless $cmd;    local $Level = $Level + 1;    if( $self->{Have_Plan} ) {        $self->croak("You tried to plan twice");    }    if( $cmd eq 'no_plan' ) {        $self->no_plan;    }    elsif( $cmd eq 'skip_all' ) {        return $self->skip_all($arg);    }    elsif( $cmd eq 'tests' ) {        if( $arg ) {            local $Level = $Level + 1;            return $self->expected_tests($arg);        }        elsif( !defined $arg ) {            $self->croak("Got an undefined number of tests");        }        elsif( !$arg ) {            $self->croak("You said to run 0 tests");        }    }    else {        my @args = grep { defined } ($cmd, $arg);        $self->croak("plan() doesn't understand @args");    }    return 1;}=item B<expected_tests>    my $max = $Test->expected_tests;    $Test->expected_tests($max);Gets/sets the # of tests we expect this test to run and prints outthe appropriate headers.=cutsub expected_tests {    my $self = shift;    my($max) = @_;    if( @_ ) {        $self->croak("Number of tests must be a positive integer.  You gave it '$max'")          unless $max =~ /^\+?\d+$/ and $max > 0;        $self->{Expected_Tests} = $max;        $self->{Have_Plan}      = 1;        $self->_print("1..$max\n") unless $self->no_header;    }    return $self->{Expected_Tests};}=item B<no_plan>  $Test->no_plan;Declares that this test will run an indeterminate # of tests.=cutsub no_plan {    my $self = shift;    $self->{No_Plan}   = 1;    $self->{Have_Plan} = 1;}=item B<has_plan>  $plan = $Test->has_planFind out whether a plan has been defined. $plan is either C<undef> (no plan has been set), C<no_plan> (indeterminate # of tests) or an integer (the number of expected tests).=cutsub has_plan {    my $self = shift;    return($self->{Expected_Tests}) if $self->{Expected_Tests};    return('no_plan') if $self->{No_Plan};    return(undef);};=item B<skip_all>  $Test->skip_all;  $Test->skip_all($reason);Skips all the tests, using the given $reason.  Exits immediately with 0.=cutsub skip_all {    my($self, $reason) = @_;    my $out = "1..0";    $out .= " # Skip $reason" if $reason;    $out .= "\n";    $self->{Skip_All} = 1;    $self->_print($out) unless $self->no_header;    exit(0);}=back=head2 Running testsThese actually run the tests, analogous to the functions in Test::More.They all return true if the test passed, false if the test failed.$name is always optional.=over 4=item B<ok>  $Test->ok($test, $name);Your basic test.  Pass if $test is true, fail if $test is false.  Justlike Test::Simple's ok().=cutsub ok {    my($self, $test, $name) = @_;    # $test might contain an object which we don't want to accidentally    # store, so we turn it into a boolean.    $test = $test ? 1 : 0;    $self->_plan_check;    lock $self->{Curr_Test};    $self->{Curr_Test}++;    # In case $name is a string overloaded object, force it to stringify.    $self->_unoverload_str(\$name);    $self->diag(<<ERR) if defined $name and $name =~ /^[\d\s]+$/;    You named your test '$name'.  You shouldn't use numbers for your test names.    Very confusing.ERR    my($pack, $file, $line) = $self->caller;    my $todo = $self->todo($pack);    $self->_unoverload_str(\$todo);    my $out;    my $result = &share({});    unless( $test ) {        $out .= "not ";        @$result{ 'ok', 'actual_ok' } = ( ( $todo ? 1 : 0 ), 0 );    }    else {        @$result{ 'ok', 'actual_ok' } = ( 1, $test );    }    $out .= "ok";    $out .= " $self->{Curr_Test}" if $self->use_numbers;    if( defined $name ) {        $name =~ s|#|\\#|g;     # # in a name can confuse Test::Harness.        $out   .= " - $name";        $result->{name} = $name;    }    else {        $result->{name} = '';    }    if( $todo ) {        $out   .= " # TODO $todo";        $result->{reason} = $todo;        $result->{type}   = 'todo';    }    else {        $result->{reason} = '';        $result->{type}   = '';    }    $self->{Test_Results}[$self->{Curr_Test}-1] = $result;    $out .= "\n";    $self->_print($out);    unless( $test ) {        my $msg = $todo ? "Failed (TODO)" : "Failed";        $self->_print_diag("\n") if $ENV{HARNESS_ACTIVE};	if( defined $name ) {	    $self->diag(qq[  $msg test '$name'\n]);	    $self->diag(qq[  at $file line $line.\n]);	}	else {	    $self->diag(qq[  $msg test at $file line $line.\n]);	}    }     return $test ? 1 : 0;}sub _unoverload {    my $self  = shift;    my $type  = shift;    $self->_try(sub { require overload } ) || return;    foreach my $thing (@_) {        if( $self->_is_object($$thing) ) {            if( my $string_meth = overload::Method($$thing, $type) ) {                $$thing = $$thing->$string_meth();            }        }    }}sub _is_object {    my($self, $thing) = @_;    return $self->_try(sub { ref $thing && $thing->isa('UNIVERSAL') }) ? 1 : 0;}sub _unoverload_str {    my $self = shift;    $self->_unoverload(q[""], @_);}    sub _unoverload_num {    my $self = shift;    $self->_unoverload('0+', @_);    for my $val (@_) {        next unless $self->_is_dualvar($$val);        $$val = $$val+0;    }}# This is a hack to detect a dualvar such as $!sub _is_dualvar {    my($self, $val) = @_;    local $^W = 0;    my $numval = $val+0;    return 1 if $numval != 0 and $numval ne $val;}=item B<is_eq>  $Test->is_eq($got, $expected, $name);Like Test::More's is().  Checks if $got eq $expected.  This is thestring version.=item B<is_num>  $Test->is_num($got, $expected, $name);Like Test::More's is().  Checks if $got == $expected.  This is thenumeric version.=cutsub is_eq {    my($self, $got, $expect, $name) = @_;    local $Level = $Level + 1;    $self->_unoverload_str(\$got, \$expect);    if( !defined $got || !defined $expect ) {        # undef only matches undef and nothing else        my $test = !defined $got && !defined $expect;        $self->ok($test, $name);        $self->_is_diag($got, 'eq', $expect) unless $test;        return $test;    }    return $self->cmp_ok($got, 'eq', $expect, $name);}sub is_num {    my($self, $got, $expect, $name) = @_;    local $Level = $Level + 1;    $self->_unoverload_num(\$got, \$expect);    if( !defined $got || !defined $expect ) {        # undef only matches undef and nothing else        my $test = !defined $got && !defined $expect;        $self->ok($test, $name);        $self->_is_diag($got, '==', $expect) unless $test;        return $test;    }    return $self->cmp_ok($got, '==', $expect, $name);}sub _is_diag {    my($self, $got, $type, $expect) = @_;    foreach my $val (\$got, \$expect) {        if( defined $$val ) {            if( $type eq 'eq' ) {                # quote and force string context                $$val = "'$$val'"            }            else {                # force numeric context                $self->_unoverload_num($val);            }        }        else {            $$val = 'undef';        }    }    return $self->diag(sprintf <<DIAGNOSTIC, $got, $expect);         got: %s    expected: %sDIAGNOSTIC}    =item B<isnt_eq>  $Test->isnt_eq($got, $dont_expect, $name);Like Test::More's isnt().  Checks if $got ne $dont_expect.  This isthe string version.=item B<isnt_num>  $Test->isnt_num($got, $dont_expect, $name);Like Test::More's isnt().  Checks if $got ne $dont_expect.  This isthe numeric version.=cutsub isnt_eq {    my($self, $got, $dont_expect, $name) = @_;    local $Level = $Level + 1;    if( !defined $got || !defined $dont_expect ) {        # undef only matches undef and nothing else        my $test = defined $got || defined $dont_expect;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -