From f6163b0b7ef4ce7ba1ee477b159dc4578940683c Mon Sep 17 00:00:00 2001 From: Sweet Tea Dorminy Date: Sun, 30 Mar 2025 14:07:44 -0400 Subject: [PATCH 1/8] Test::Unit: Delete in favor of packaged version. Test::Unit version 0.25 is packaged by Fedora. No need for us to use a local one. --- perl/third/Makefile | 1 - perl/third/Test-Unit-0.25/AUTHORS | 70 - perl/third/Test-Unit-0.25/COPYING.Artistic | 131 - perl/third/Test-Unit-0.25/COPYING.GPL-2 | 340 - perl/third/Test-Unit-0.25/ChangeLog | 1335 -- perl/third/Test-Unit-0.25/Changes | 52 - perl/third/Test-Unit-0.25/MANIFEST | 84 - perl/third/Test-Unit-0.25/META.yml | 14 - perl/third/Test-Unit-0.25/Makefile.PL | 17 - perl/third/Test-Unit-0.25/README | 83 - perl/third/Test-Unit-0.25/TestLister.pl | 27 - perl/third/Test-Unit-0.25/TestRunner.pl | 13 - perl/third/Test-Unit-0.25/TkTestRunner.pl | 7 - perl/third/Test-Unit-0.25/doc/TODO | 303 - .../Test-Unit-0.25/doc/class-diagram.dia | 12011 ---------------- .../Test-Unit-0.25/doc/class-diagram.png | Bin 178018 -> 0 bytes .../Test-Unit-0.25/doc/class-diagram.txt | 198 - perl/third/Test-Unit-0.25/doc/consensus.txt | 166 - .../Test-Unit-0.25/doc/release-checklist | 173 - .../examples/Experimental/Sample.pm | 33 - perl/third/Test-Unit-0.25/examples/README | 16 - .../Test-Unit-0.25/examples/fail_example.pm | 60 - .../third/Test-Unit-0.25/examples/patch100132 | 41 - .../Test-Unit-0.25/examples/patch100132-1 | 50 - .../Test-Unit-0.25/examples/patch100132-2 | 69 - perl/third/Test-Unit-0.25/examples/tester.png | Bin 53974 -> 0 bytes perl/third/Test-Unit-0.25/lib/Test/Unit.pm | 127 - .../Test-Unit-0.25/lib/Test/Unit/Assert.pm | 726 - .../Test-Unit-0.25/lib/Test/Unit/Assertion.pm | 92 - .../lib/Test/Unit/Assertion/Boolean.pm | 63 - .../lib/Test/Unit/Assertion/CodeRef.pm | 125 - .../lib/Test/Unit/Assertion/Exception.pm | 90 - .../lib/Test/Unit/Assertion/Regexp.pm | 99 - .../Test-Unit-0.25/lib/Test/Unit/Debug.pm | 118 - .../Test-Unit-0.25/lib/Test/Unit/Decorator.pm | 72 - .../Test-Unit-0.25/lib/Test/Unit/Error.pm | 57 - .../Test-Unit-0.25/lib/Test/Unit/Exception.pm | 103 - .../Test-Unit-0.25/lib/Test/Unit/Failure.pm | 47 - .../lib/Test/Unit/HarnessUnit.pm | 157 - .../Test-Unit-0.25/lib/Test/Unit/Listener.pm | 99 - .../Test-Unit-0.25/lib/Test/Unit/Loader.pm | 211 - .../lib/Test/Unit/Procedural.pm | 211 - .../Test-Unit-0.25/lib/Test/Unit/Result.pm | 254 - .../Test-Unit-0.25/lib/Test/Unit/Runner.pm | 100 - .../lib/Test/Unit/Runner/Terminal.pm | 172 - .../Test-Unit-0.25/lib/Test/Unit/Setup.pm | 63 - .../Test-Unit-0.25/lib/Test/Unit/Test.pm | 147 - .../Test-Unit-0.25/lib/Test/Unit/TestCase.pm | 441 - .../lib/Test/Unit/TestRunner.pm | 273 - .../Test-Unit-0.25/lib/Test/Unit/TestSuite.pm | 360 - .../lib/Test/Unit/TkTestRunner.pm | 697 - .../Test-Unit-0.25/lib/Test/Unit/Tutorial.pm | 61 - .../lib/Test/Unit/UnitHarness.pm | 236 - .../Test-Unit-0.25/lib/Test/Unit/Warning.pm | 42 - perl/third/Test-Unit-0.25/t/all_tests.t | 13 - perl/third/Test-Unit-0.25/t/assert.t | 14 - .../Test-Unit-0.25/t/tlib/ActiveTestTest.pm | 60 - perl/third/Test-Unit-0.25/t/tlib/AllTests.pm | 86 - .../third/Test-Unit-0.25/t/tlib/AssertTest.pm | 584 - .../Test-Unit-0.25/t/tlib/BadSuite/BadUse.pm | 5 - .../t/tlib/BadSuite/SyntaxError.pm | 7 - .../Test-Unit-0.25/t/tlib/BadSuitesTest.pm | 28 - .../Test-Unit-0.25/t/tlib/ExceptionChecker.pm | 100 - .../Test-Unit-0.25/t/tlib/FilteredSuite.pm | 36 - .../t/tlib/InheritedInheritedTestCase.pm | 14 - .../t/tlib/InheritedSuite/OverrideNew.pm | 14 - .../t/tlib/InheritedSuite/OverrideNewName.pm | 16 - .../t/tlib/InheritedSuite/Simple.pm | 10 - .../t/tlib/InheritedSuite/TestNames.pm | 28 - .../t/tlib/InheritedTestCase.pm | 14 - .../Test-Unit-0.25/t/tlib/ListenerTest.pm | 89 - .../Test-Unit-0.25/t/tlib/NoTestCaseClass.pm | 10 - .../Test-Unit-0.25/t/tlib/NoTestCases.pm | 17 - .../Test-Unit-0.25/t/tlib/OneTestCase.pm | 17 - .../Test-Unit-0.25/t/tlib/OverrideTestCase.pm | 15 - .../third/Test-Unit-0.25/t/tlib/RunnerTest.pm | 89 - perl/third/Test-Unit-0.25/t/tlib/Success.pm | 13 - perl/third/Test-Unit-0.25/t/tlib/SuiteTest.pm | 167 - .../t/tlib/TestAssertionCodeRef.pm | 15 - .../third/Test-Unit-0.25/t/tlib/TestObject.pm | 10 - perl/third/Test-Unit-0.25/t/tlib/TestTest.pm | 290 - perl/third/Test-Unit-0.25/t/tlib/TornDown.pm | 27 - perl/third/Test-Unit-0.25/t/tlib/WasRun.pm | 22 - perl/third/Test-Unit-0.25/t/tlib/WillDie.pm | 22 - perl/third/Test-Unit-0.25/t/try_examples.t | 113 - 85 files changed, 22482 deletions(-) delete mode 100644 perl/third/Test-Unit-0.25/AUTHORS delete mode 100644 perl/third/Test-Unit-0.25/COPYING.Artistic delete mode 100644 perl/third/Test-Unit-0.25/COPYING.GPL-2 delete mode 100644 perl/third/Test-Unit-0.25/ChangeLog delete mode 100644 perl/third/Test-Unit-0.25/Changes delete mode 100644 perl/third/Test-Unit-0.25/MANIFEST delete mode 100644 perl/third/Test-Unit-0.25/META.yml delete mode 100644 perl/third/Test-Unit-0.25/Makefile.PL delete mode 100644 perl/third/Test-Unit-0.25/README delete mode 100755 perl/third/Test-Unit-0.25/TestLister.pl delete mode 100755 perl/third/Test-Unit-0.25/TestRunner.pl delete mode 100755 perl/third/Test-Unit-0.25/TkTestRunner.pl delete mode 100644 perl/third/Test-Unit-0.25/doc/TODO delete mode 100644 perl/third/Test-Unit-0.25/doc/class-diagram.dia delete mode 100644 perl/third/Test-Unit-0.25/doc/class-diagram.png delete mode 100644 perl/third/Test-Unit-0.25/doc/class-diagram.txt delete mode 100644 perl/third/Test-Unit-0.25/doc/consensus.txt delete mode 100644 perl/third/Test-Unit-0.25/doc/release-checklist delete mode 100644 perl/third/Test-Unit-0.25/examples/Experimental/Sample.pm delete mode 100644 perl/third/Test-Unit-0.25/examples/README delete mode 100644 perl/third/Test-Unit-0.25/examples/fail_example.pm delete mode 100644 perl/third/Test-Unit-0.25/examples/patch100132 delete mode 100644 perl/third/Test-Unit-0.25/examples/patch100132-1 delete mode 100644 perl/third/Test-Unit-0.25/examples/patch100132-2 delete mode 100644 perl/third/Test-Unit-0.25/examples/tester.png delete mode 100644 perl/third/Test-Unit-0.25/lib/Test/Unit.pm delete mode 100644 perl/third/Test-Unit-0.25/lib/Test/Unit/Assert.pm delete mode 100644 perl/third/Test-Unit-0.25/lib/Test/Unit/Assertion.pm delete mode 100644 perl/third/Test-Unit-0.25/lib/Test/Unit/Assertion/Boolean.pm delete mode 100644 perl/third/Test-Unit-0.25/lib/Test/Unit/Assertion/CodeRef.pm delete mode 100644 perl/third/Test-Unit-0.25/lib/Test/Unit/Assertion/Exception.pm delete mode 100644 perl/third/Test-Unit-0.25/lib/Test/Unit/Assertion/Regexp.pm delete mode 100644 perl/third/Test-Unit-0.25/lib/Test/Unit/Debug.pm delete mode 100644 perl/third/Test-Unit-0.25/lib/Test/Unit/Decorator.pm delete mode 100644 perl/third/Test-Unit-0.25/lib/Test/Unit/Error.pm delete mode 100644 perl/third/Test-Unit-0.25/lib/Test/Unit/Exception.pm delete mode 100644 perl/third/Test-Unit-0.25/lib/Test/Unit/Failure.pm delete mode 100644 perl/third/Test-Unit-0.25/lib/Test/Unit/HarnessUnit.pm delete mode 100644 perl/third/Test-Unit-0.25/lib/Test/Unit/Listener.pm delete mode 100644 perl/third/Test-Unit-0.25/lib/Test/Unit/Loader.pm delete mode 100644 perl/third/Test-Unit-0.25/lib/Test/Unit/Procedural.pm delete mode 100644 perl/third/Test-Unit-0.25/lib/Test/Unit/Result.pm delete mode 100644 perl/third/Test-Unit-0.25/lib/Test/Unit/Runner.pm delete mode 100644 perl/third/Test-Unit-0.25/lib/Test/Unit/Runner/Terminal.pm delete mode 100644 perl/third/Test-Unit-0.25/lib/Test/Unit/Setup.pm delete mode 100644 perl/third/Test-Unit-0.25/lib/Test/Unit/Test.pm delete mode 100644 perl/third/Test-Unit-0.25/lib/Test/Unit/TestCase.pm delete mode 100644 perl/third/Test-Unit-0.25/lib/Test/Unit/TestRunner.pm delete mode 100644 perl/third/Test-Unit-0.25/lib/Test/Unit/TestSuite.pm delete mode 100644 perl/third/Test-Unit-0.25/lib/Test/Unit/TkTestRunner.pm delete mode 100644 perl/third/Test-Unit-0.25/lib/Test/Unit/Tutorial.pm delete mode 100644 perl/third/Test-Unit-0.25/lib/Test/Unit/UnitHarness.pm delete mode 100644 perl/third/Test-Unit-0.25/lib/Test/Unit/Warning.pm delete mode 100644 perl/third/Test-Unit-0.25/t/all_tests.t delete mode 100644 perl/third/Test-Unit-0.25/t/assert.t delete mode 100644 perl/third/Test-Unit-0.25/t/tlib/ActiveTestTest.pm delete mode 100644 perl/third/Test-Unit-0.25/t/tlib/AllTests.pm delete mode 100644 perl/third/Test-Unit-0.25/t/tlib/AssertTest.pm delete mode 100644 perl/third/Test-Unit-0.25/t/tlib/BadSuite/BadUse.pm delete mode 100644 perl/third/Test-Unit-0.25/t/tlib/BadSuite/SyntaxError.pm delete mode 100644 perl/third/Test-Unit-0.25/t/tlib/BadSuitesTest.pm delete mode 100644 perl/third/Test-Unit-0.25/t/tlib/ExceptionChecker.pm delete mode 100644 perl/third/Test-Unit-0.25/t/tlib/FilteredSuite.pm delete mode 100644 perl/third/Test-Unit-0.25/t/tlib/InheritedInheritedTestCase.pm delete mode 100644 perl/third/Test-Unit-0.25/t/tlib/InheritedSuite/OverrideNew.pm delete mode 100644 perl/third/Test-Unit-0.25/t/tlib/InheritedSuite/OverrideNewName.pm delete mode 100644 perl/third/Test-Unit-0.25/t/tlib/InheritedSuite/Simple.pm delete mode 100644 perl/third/Test-Unit-0.25/t/tlib/InheritedSuite/TestNames.pm delete mode 100644 perl/third/Test-Unit-0.25/t/tlib/InheritedTestCase.pm delete mode 100644 perl/third/Test-Unit-0.25/t/tlib/ListenerTest.pm delete mode 100644 perl/third/Test-Unit-0.25/t/tlib/NoTestCaseClass.pm delete mode 100644 perl/third/Test-Unit-0.25/t/tlib/NoTestCases.pm delete mode 100644 perl/third/Test-Unit-0.25/t/tlib/OneTestCase.pm delete mode 100644 perl/third/Test-Unit-0.25/t/tlib/OverrideTestCase.pm delete mode 100644 perl/third/Test-Unit-0.25/t/tlib/RunnerTest.pm delete mode 100644 perl/third/Test-Unit-0.25/t/tlib/Success.pm delete mode 100644 perl/third/Test-Unit-0.25/t/tlib/SuiteTest.pm delete mode 100644 perl/third/Test-Unit-0.25/t/tlib/TestAssertionCodeRef.pm delete mode 100644 perl/third/Test-Unit-0.25/t/tlib/TestObject.pm delete mode 100644 perl/third/Test-Unit-0.25/t/tlib/TestTest.pm delete mode 100644 perl/third/Test-Unit-0.25/t/tlib/TornDown.pm delete mode 100644 perl/third/Test-Unit-0.25/t/tlib/WasRun.pm delete mode 100644 perl/third/Test-Unit-0.25/t/tlib/WillDie.pm delete mode 100644 perl/third/Test-Unit-0.25/t/try_examples.t diff --git a/perl/third/Makefile b/perl/third/Makefile index cf76abe..eb6e200 100644 --- a/perl/third/Makefile +++ b/perl/third/Makefile @@ -11,7 +11,6 @@ SUBDIRS:= \ Log-Dispatch-FileRotate-1.11 \ Proc-Simple-1.32 \ Shuffle-1.4 \ - Test-Unit-0.25 \ interface-0.02 \ all: ${SUBDIRS} diff --git a/perl/third/Test-Unit-0.25/AUTHORS b/perl/third/Test-Unit-0.25/AUTHORS deleted file mode 100644 index 4804ac4..0000000 --- a/perl/third/Test-Unit-0.25/AUTHORS +++ /dev/null @@ -1,70 +0,0 @@ -# PerlUnit was originally written as a port of Kent Beck and Erich -# Gamma's xUnit testing framework by Christian Lemburg and Brian -# Ewins, and is now maintained by Adam Spiers and the rest of the -# PerlUnit team. -# -# The following is an alphabetical list of all the people who've -# contributed code and effort to making PerlUnit what it is today. -# Where possible we have included their Sourceforge usernames and -# preferred email addresses. -# -# The use of this database for anything other than PerlUnit -# development is strictly forbidden. (Passive distribution with the -# PerlUnit source code package is naturally allowed) - -Adam Spiers adamspiers -Brian Ewins ba22a -Cayte Linder cayte -Christian Lemburg clemburg -David Esposito davide -J.E. Fritz jefritz -Kevin Connor wallisalviar -Matthew Astley mca1001 (was mca-gdl) -Michael Schwern/Test::More project for the deep structure comparison routines -Piers Cawley pdcawley -Zhon Johansen zhon - - - -As far as copyright years go (as if anyone cares), this may serve as a -vague starting guide for who put together the bulk of the project: - - 2000 ba22a, clemburg - 2001 clemburg, pdcawley - 2002 adamspiers, pdcawley - -Where specific files in the project have been contributed by one -person and that person has claimed the copyright, I have left their -authorship. - -The rest of the files have moved over to a more boilerplate style -crediting the PerlUnit Development Team and referring to the -Test::Unit docs and this file. This is simply for maintenance sanity. - - - - -All rights reserved. This program is free software; you can -redistribute it and/or modify it under the same terms as Perl itself: - ------------------------------------------------------------------------------- - Perl copyright: ------------------------------------------------------------------------------- - Copyright 1989-2001, Larry Wall All rights reserved. - - This program is free software; you can redistribute it and/or modify - it under the terms of either: - - a) the GNU General Public License as published by the Free Software - Foundation; either version 1, or (at your option) any later - version, or - - b) the "Artistic License" which comes with Perl. - ------------------------------------------------------------------------------- - -The GNU GPL version 2 is included here in the file COPYING.GPL-2 . -You may use version 1 instead, but it has been superceded for good -reasons... - -The Artistic License is included here in the file COPYING.Artistic diff --git a/perl/third/Test-Unit-0.25/COPYING.Artistic b/perl/third/Test-Unit-0.25/COPYING.Artistic deleted file mode 100644 index 5f22124..0000000 --- a/perl/third/Test-Unit-0.25/COPYING.Artistic +++ /dev/null @@ -1,131 +0,0 @@ - - - - - The "Artistic License" - - Preamble - -The intent of this document is to state the conditions under which a -Package may be copied, such that the Copyright Holder maintains some -semblance of artistic control over the development of the package, -while giving the users of the package the right to use and distribute -the Package in a more-or-less customary fashion, plus the right to make -reasonable modifications. - -Definitions: - - "Package" refers to the collection of files distributed by the - Copyright Holder, and derivatives of that collection of files - created through textual modification. - - "Standard Version" refers to such a Package if it has not been - modified, or has been modified in accordance with the wishes - of the Copyright Holder as specified below. - - "Copyright Holder" is whoever is named in the copyright or - copyrights for the package. - - "You" is you, if you're thinking about copying or distributing - this Package. - - "Reasonable copying fee" is whatever you can justify on the - basis of media cost, duplication charges, time of people involved, - and so on. (You will not be required to justify it to the - Copyright Holder, but only to the computing community at large - as a market that must bear the fee.) - - "Freely Available" means that no fee is charged for the item - itself, though there may be fees involved in handling the item. - It also means that recipients of the item may redistribute it - under the same conditions they received it. - -1. You may make and give away verbatim copies of the source form of the -Standard Version of this Package without restriction, provided that you -duplicate all of the original copyright notices and associated disclaimers. - -2. You may apply bug fixes, portability fixes and other modifications -derived from the Public Domain or from the Copyright Holder. A Package -modified in such a way shall still be considered the Standard Version. - -3. You may otherwise modify your copy of this Package in any way, provided -that you insert a prominent notice in each changed file stating how and -when you changed that file, and provided that you do at least ONE of the -following: - - a) place your modifications in the Public Domain or otherwise make them - Freely Available, such as by posting said modifications to Usenet or - an equivalent medium, or placing the modifications on a major archive - site such as uunet.uu.net, or by allowing the Copyright Holder to include - your modifications in the Standard Version of the Package. - - b) use the modified Package only within your corporation or organization. - - c) rename any non-standard executables so the names do not conflict - with standard executables, which must also be provided, and provide - a separate manual page for each non-standard executable that clearly - documents how it differs from the Standard Version. - - d) make other distribution arrangements with the Copyright Holder. - -4. You may distribute the programs of this Package in object code or -executable form, provided that you do at least ONE of the following: - - a) distribute a Standard Version of the executables and library files, - together with instructions (in the manual page or equivalent) on where - to get the Standard Version. - - b) accompany the distribution with the machine-readable source of - the Package with your modifications. - - c) give non-standard executables non-standard names, and clearly - document the differences in manual pages (or equivalent), together - with instructions on where to get the Standard Version. - - d) make other distribution arrangements with the Copyright Holder. - -5. You may charge a reasonable copying fee for any distribution of this -Package. You may charge any fee you choose for support of this -Package. You may not charge a fee for this Package itself. However, -you may distribute this Package in aggregate with other (possibly -commercial) programs as part of a larger (possibly commercial) software -distribution provided that you do not advertise this Package as a -product of your own. You may embed this Package's interpreter within -an executable of yours (by linking); this shall be construed as a mere -form of aggregation, provided that the complete Standard Version of the -interpreter is so embedded. - -6. The scripts and library files supplied as input to or produced as -output from the programs of this Package do not automatically fall -under the copyright of this Package, but belong to whoever generated -them, and may be sold commercially, and may be aggregated with this -Package. If such scripts or library files are aggregated with this -Package via the so-called "undump" or "unexec" methods of producing a -binary executable image, then distribution of such an image shall -neither be construed as a distribution of this Package nor shall it -fall under the restrictions of Paragraphs 3 and 4, provided that you do -not represent such an executable image as a Standard Version of this -Package. - -7. C subroutines (or comparably compiled subroutines in other -languages) supplied by you and linked into this Package in order to -emulate subroutines and variables of the language defined by this -Package shall not be considered part of this Package, but are the -equivalent of input as in Paragraph 6, provided these subroutines do -not change the language in any way that would cause it to fail the -regression tests for the language. - -8. Aggregation of this Package with a commercial distribution is always -permitted provided that the use of this Package is embedded; that is, -when no overt attempt is made to make this Package's interfaces visible -to the end user of the commercial distribution. Such use shall not be -construed as a distribution of this Package. - -9. The name of the Copyright Holder may not be used to endorse or promote -products derived from this software without specific prior written permission. - -10. THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR -IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED -WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. - - The End diff --git a/perl/third/Test-Unit-0.25/COPYING.GPL-2 b/perl/third/Test-Unit-0.25/COPYING.GPL-2 deleted file mode 100644 index d60c31a..0000000 --- a/perl/third/Test-Unit-0.25/COPYING.GPL-2 +++ /dev/null @@ -1,340 +0,0 @@ - GNU GENERAL PUBLIC LICENSE - Version 2, June 1991 - - Copyright (C) 1989, 1991 Free Software Foundation, Inc. - 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. - - Preamble - - The licenses for most software are designed to take away your -freedom to share and change it. By contrast, the GNU General Public -License is intended to guarantee your freedom to share and change free -software--to make sure the software is free for all its users. This -General Public License applies to most of the Free Software -Foundation's software and to any other program whose authors commit to -using it. (Some other Free Software Foundation software is covered by -the GNU Library General Public License instead.) You can apply it to -your programs, too. - - When we speak of free software, we are referring to freedom, not -price. Our General Public Licenses are designed to make sure that you -have the freedom to distribute copies of free software (and charge for -this service if you wish), that you receive source code or can get it -if you want it, that you can change the software or use pieces of it -in new free programs; and that you know you can do these things. - - To protect your rights, we need to make restrictions that forbid -anyone to deny you these rights or to ask you to surrender the rights. -These restrictions translate to certain responsibilities for you if you -distribute copies of the software, or if you modify it. - - For example, if you distribute copies of such a program, whether -gratis or for a fee, you must give the recipients all the rights that -you have. You must make sure that they, too, receive or can get the -source code. And you must show them these terms so they know their -rights. - - We protect your rights with two steps: (1) copyright the software, and -(2) offer you this license which gives you legal permission to copy, -distribute and/or modify the software. - - Also, for each author's protection and ours, we want to make certain -that everyone understands that there is no warranty for this free -software. If the software is modified by someone else and passed on, we -want its recipients to know that what they have is not the original, so -that any problems introduced by others will not reflect on the original -authors' reputations. - - Finally, any free program is threatened constantly by software -patents. We wish to avoid the danger that redistributors of a free -program will individually obtain patent licenses, in effect making the -program proprietary. To prevent this, we have made it clear that any -patent must be licensed for everyone's free use or not licensed at all. - - The precise terms and conditions for copying, distribution and -modification follow. - - GNU GENERAL PUBLIC LICENSE - TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION - - 0. This License applies to any program or other work which contains -a notice placed by the copyright holder saying it may be distributed -under the terms of this General Public License. The "Program", below, -refers to any such program or work, and a "work based on the Program" -means either the Program or any derivative work under copyright law: -that is to say, a work containing the Program or a portion of it, -either verbatim or with modifications and/or translated into another -language. (Hereinafter, translation is included without limitation in -the term "modification".) Each licensee is addressed as "you". - -Activities other than copying, distribution and modification are not -covered by this License; they are outside its scope. The act of -running the Program is not restricted, and the output from the Program -is covered only if its contents constitute a work based on the -Program (independent of having been made by running the Program). -Whether that is true depends on what the Program does. - - 1. You may copy and distribute verbatim copies of the Program's -source code as you receive it, in any medium, provided that you -conspicuously and appropriately publish on each copy an appropriate -copyright notice and disclaimer of warranty; keep intact all the -notices that refer to this License and to the absence of any warranty; -and give any other recipients of the Program a copy of this License -along with the Program. - -You may charge a fee for the physical act of transferring a copy, and -you may at your option offer warranty protection in exchange for a fee. - - 2. You may modify your copy or copies of the Program or any portion -of it, thus forming a work based on the Program, and copy and -distribute such modifications or work under the terms of Section 1 -above, provided that you also meet all of these conditions: - - a) You must cause the modified files to carry prominent notices - stating that you changed the files and the date of any change. - - b) You must cause any work that you distribute or publish, that in - whole or in part contains or is derived from the Program or any - part thereof, to be licensed as a whole at no charge to all third - parties under the terms of this License. - - c) If the modified program normally reads commands interactively - when run, you must cause it, when started running for such - interactive use in the most ordinary way, to print or display an - announcement including an appropriate copyright notice and a - notice that there is no warranty (or else, saying that you provide - a warranty) and that users may redistribute the program under - these conditions, and telling the user how to view a copy of this - License. (Exception: if the Program itself is interactive but - does not normally print such an announcement, your work based on - the Program is not required to print an announcement.) - -These requirements apply to the modified work as a whole. If -identifiable sections of that work are not derived from the Program, -and can be reasonably considered independent and separate works in -themselves, then this License, and its terms, do not apply to those -sections when you distribute them as separate works. But when you -distribute the same sections as part of a whole which is a work based -on the Program, the distribution of the whole must be on the terms of -this License, whose permissions for other licensees extend to the -entire whole, and thus to each and every part regardless of who wrote it. - -Thus, it is not the intent of this section to claim rights or contest -your rights to work written entirely by you; rather, the intent is to -exercise the right to control the distribution of derivative or -collective works based on the Program. - -In addition, mere aggregation of another work not based on the Program -with the Program (or with a work based on the Program) on a volume of -a storage or distribution medium does not bring the other work under -the scope of this License. - - 3. You may copy and distribute the Program (or a work based on it, -under Section 2) in object code or executable form under the terms of -Sections 1 and 2 above provided that you also do one of the following: - - a) Accompany it with the complete corresponding machine-readable - source code, which must be distributed under the terms of Sections - 1 and 2 above on a medium customarily used for software interchange; or, - - b) Accompany it with a written offer, valid for at least three - years, to give any third party, for a charge no more than your - cost of physically performing source distribution, a complete - machine-readable copy of the corresponding source code, to be - distributed under the terms of Sections 1 and 2 above on a medium - customarily used for software interchange; or, - - c) Accompany it with the information you received as to the offer - to distribute corresponding source code. (This alternative is - allowed only for noncommercial distribution and only if you - received the program in object code or executable form with such - an offer, in accord with Subsection b above.) - -The source code for a work means the preferred form of the work for -making modifications to it. For an executable work, complete source -code means all the source code for all modules it contains, plus any -associated interface definition files, plus the scripts used to -control compilation and installation of the executable. However, as a -special exception, the source code distributed need not include -anything that is normally distributed (in either source or binary -form) with the major components (compiler, kernel, and so on) of the -operating system on which the executable runs, unless that component -itself accompanies the executable. - -If distribution of executable or object code is made by offering -access to copy from a designated place, then offering equivalent -access to copy the source code from the same place counts as -distribution of the source code, even though third parties are not -compelled to copy the source along with the object code. - - 4. You may not copy, modify, sublicense, or distribute the Program -except as expressly provided under this License. Any attempt -otherwise to copy, modify, sublicense or distribute the Program is -void, and will automatically terminate your rights under this License. -However, parties who have received copies, or rights, from you under -this License will not have their licenses terminated so long as such -parties remain in full compliance. - - 5. You are not required to accept this License, since you have not -signed it. However, nothing else grants you permission to modify or -distribute the Program or its derivative works. These actions are -prohibited by law if you do not accept this License. Therefore, by -modifying or distributing the Program (or any work based on the -Program), you indicate your acceptance of this License to do so, and -all its terms and conditions for copying, distributing or modifying -the Program or works based on it. - - 6. Each time you redistribute the Program (or any work based on the -Program), the recipient automatically receives a license from the -original licensor to copy, distribute or modify the Program subject to -these terms and conditions. You may not impose any further -restrictions on the recipients' exercise of the rights granted herein. -You are not responsible for enforcing compliance by third parties to -this License. - - 7. If, as a consequence of a court judgment or allegation of patent -infringement or for any other reason (not limited to patent issues), -conditions are imposed on you (whether by court order, agreement or -otherwise) that contradict the conditions of this License, they do not -excuse you from the conditions of this License. If you cannot -distribute so as to satisfy simultaneously your obligations under this -License and any other pertinent obligations, then as a consequence you -may not distribute the Program at all. For example, if a patent -license would not permit royalty-free redistribution of the Program by -all those who receive copies directly or indirectly through you, then -the only way you could satisfy both it and this License would be to -refrain entirely from distribution of the Program. - -If any portion of this section is held invalid or unenforceable under -any particular circumstance, the balance of the section is intended to -apply and the section as a whole is intended to apply in other -circumstances. - -It is not the purpose of this section to induce you to infringe any -patents or other property right claims or to contest validity of any -such claims; this section has the sole purpose of protecting the -integrity of the free software distribution system, which is -implemented by public license practices. Many people have made -generous contributions to the wide range of software distributed -through that system in reliance on consistent application of that -system; it is up to the author/donor to decide if he or she is willing -to distribute software through any other system and a licensee cannot -impose that choice. - -This section is intended to make thoroughly clear what is believed to -be a consequence of the rest of this License. - - 8. If the distribution and/or use of the Program is restricted in -certain countries either by patents or by copyrighted interfaces, the -original copyright holder who places the Program under this License -may add an explicit geographical distribution limitation excluding -those countries, so that distribution is permitted only in or among -countries not thus excluded. In such case, this License incorporates -the limitation as if written in the body of this License. - - 9. The Free Software Foundation may publish revised and/or new versions -of the General Public License from time to time. Such new versions will -be similar in spirit to the present version, but may differ in detail to -address new problems or concerns. - -Each version is given a distinguishing version number. If the Program -specifies a version number of this License which applies to it and "any -later version", you have the option of following the terms and conditions -either of that version or of any later version published by the Free -Software Foundation. If the Program does not specify a version number of -this License, you may choose any version ever published by the Free Software -Foundation. - - 10. If you wish to incorporate parts of the Program into other free -programs whose distribution conditions are different, write to the author -to ask for permission. For software which is copyrighted by the Free -Software Foundation, write to the Free Software Foundation; we sometimes -make exceptions for this. Our decision will be guided by the two goals -of preserving the free status of all derivatives of our free software and -of promoting the sharing and reuse of software generally. - - NO WARRANTY - - 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY -FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN -OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES -PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED -OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS -TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE -PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, -REPAIR OR CORRECTION. - - 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING -WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR -REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, -INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING -OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED -TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY -YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER -PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE -POSSIBILITY OF SUCH DAMAGES. - - END OF TERMS AND CONDITIONS - - How to Apply These Terms to Your New Programs - - If you develop a new program, and you want it to be of the greatest -possible use to the public, the best way to achieve this is to make it -free software which everyone can redistribute and change under these terms. - - To do so, attach the following notices to the program. It is safest -to attach them to the start of each source file to most effectively -convey the exclusion of warranty; and each file should have at least -the "copyright" line and a pointer to where the full notice is found. - - - Copyright (C) - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - - -Also add information on how to contact you by electronic and paper mail. - -If the program is interactive, make it output a short notice like this -when it starts in an interactive mode: - - Gnomovision version 69, Copyright (C) year name of author - Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. - This is free software, and you are welcome to redistribute it - under certain conditions; type `show c' for details. - -The hypothetical commands `show w' and `show c' should show the appropriate -parts of the General Public License. Of course, the commands you use may -be called something other than `show w' and `show c'; they could even be -mouse-clicks or menu items--whatever suits your program. - -You should also get your employer (if you work as a programmer) or your -school, if any, to sign a "copyright disclaimer" for the program, if -necessary. Here is a sample; alter the names: - - Yoyodyne, Inc., hereby disclaims all copyright interest in the program - `Gnomovision' (which makes passes at compilers) written by James Hacker. - - , 1 April 1989 - Ty Coon, President of Vice - -This General Public License does not permit incorporating your program into -proprietary programs. If your program is a subroutine library, you may -consider it more useful to permit linking proprietary applications with the -library. If this is what you want to do, use the GNU Library General -Public License instead of this License. diff --git a/perl/third/Test-Unit-0.25/ChangeLog b/perl/third/Test-Unit-0.25/ChangeLog deleted file mode 100644 index 0f8e9e9..0000000 --- a/perl/third/Test-Unit-0.25/ChangeLog +++ /dev/null @@ -1,1335 +0,0 @@ -2005-10-15 Matthew Astley - - * doc/release-checklist, doc/TODO, ChangeLog: updates for release - - * lib/Test/Unit.pm: version 0.25 - - * MANIFEST: add licence and class-diagram files, remove old - exmample; keep in "make manifest" generated order - - * t/tlib/AssertTest.pm (test_fail_assert_not_null): extra check, - for SF bug #610499 - - * lib/Test/Unit/Assert.pm (assert_deep_equals): fix comparisons of - cyclic structures (thanks flacoste, SF patch #678422), comparisons - of undefs (thanks flacoste, Debian BTS #249678), comparison of - SCALAR refs - - * t/tlib/AssertTest.pm (test_assert_deep_equals): add modified - test from SF bug #1012115; modified test from flacoste's SF patch - #678422; more tests on SCALAR refs, and improve the regexp - -2005-08-19 Matthew Astley - - * doc/TODO: notes on HarnessUnit, UnitHarness; more on stuff I'd - like to do later - - * examples/README: minor update - -2005-08-03 Matthew Astley - - * doc/class-diagram.{dia,txt,png}: first stab at a UML class - diagram, see how it goes - -2005-08-01 Matthew Astley - - * lib/Test/Unit.pm, lib/Test/Unit/TkTestRunner.pm, lib/Test/Unit/TestRunner.pm: - put links to COPYING.* in Test::Unit; move copyright notices from - testrunner modules to Test::Unit - - * lib/Test/Unit/, t/tlib/AllTests.pm: set AUTHOR POD - sections to the same boilerplate, in files that don't appear to be - single-author -- as described in the top level AUTHORS file - - * AUTHORS: update authors list with SF ids and what I found while - boilerplating the PODs; add explicit copy of the Perl licence, - taken from Debian perl-base package v5.8.4-2 - - * COPYING.Artistic, COPYING.GPL-2: licences copied from Debian - base-files package v3.0.12 - -2005-07-31 Matthew Astley - - * lib/Test/Unit/Assert.pm (is_numeric): change the test to match - only lone numbers. fix SF bug#1014540 - - *** NB. this causes assert_equals to switch from assert_num_equals - to assert_str_equals in some cases - - * t/tlib/AssertTest.pm (test_numericness, test_assert_equals): - tests for new is_numeric - - - * lib/Test/Unit/TkTestRunner.pm: make "Show..." dialog text expand - with window and include annotations. fixes SF bug#1018619 - - * t/try_examples.t: clear out useless 'use lib's; remove dup $^O - check; fix RT bug#3963 (thanks ILYAM); improve skipping of - untested items - - * examples/tester.png: update screenshot of Tk test runner; mark - as binary - - * examples/tester.pl: remove old Tk code - Test::SuiteWrapper went - away 2000-02-21 - -2005-07-30 Matthew Astley - - * t/try_examples.t: - Fix SF bug#908422 (track changing testing output format); - Thanks: dholland, eksiegerman - [aka. SF bug#1245490, RT bug#2244] - - * .cvsignore: ignore build stuff - - - -- other changes Adam made since REL_0_24, but aren't mentioned - already. I list them partly so I know where my towel is: - - * AUTHORS: Adam became maintainer - - * doc/TODO: updated - - * lib/Test/Unit/Decorator.pm: some minor change I've not investigated - - * lib/Test/Unit/Procedural.pm: - fix bug spotted by Matthias Ferber (and Ken) in run() (which is - usually overridden) [SF bug#760491, RT bug#3058] - - * lib/Test/Unit/Runner.pm: improve filtering, POD - - * lib/Test/Unit/TestCase.pm: POD for filtering - - * t/tlib/RunnerTest.pm: new test for T:U:TestRunner, just tests - filtering; uses the new t/tlib/FilteredSuite.pm - -2002-06-20 Adam Spiers - - * lib/Test/Unit/TestCase.pm: document new filtering via coderefs - - * MANIFEST, lib/Test/Unit/Test.pm, lib/Test/Unit/TestSuite.pm, t/tlib/AllTests.pm, t/tlib/FilteredSuite.pm: - - remove ALL filtering hack, and instead allow filtering via coderefs: - - sub filter {{ - foo_tests => sub { - my $method = shift; - return $method =~ /foo/; - }, - everything => sub { 1 }, - - # method lists still work - another_token => [ qw/test_method1 test_method2/ ], - }} - - - add tests for filtering mechanism - -2002-06-14 Adam Spiers - - * lib/Test/Unit.pm: version 0.24 - - * ChangeLog: new stuff for 0.24 - - * MANIFEST: - 'make manifest' revealed more missing files, though none of them crucial - - * AUTHORS: change Adam's email address - - * lib/Test/Unit/TestRunner.pm: - Don't die if the run was unsuccessful; we might want to reuse the runner - for another run. - - * MANIFEST: argh! 0.23's MANIFEST was missing several crucial files. - -2002-06-13 Adam Spiers - - * lib/Test/Unit/Runner/Terminal.pm: forgot to update the pod - - * .cvsignore: ignore tarballs - - * doc/release-checklist: typo - - * README, doc/release-checklist: - cut down on the poor maintainer's workload - - * Changes: deprecate this file - - * ChangeLog: new stuff for 0.23 - - * lib/Test/Unit.pm: version 0.23 - - * doc/TODO: mention that Attribute::Handlers probably won't work - - * t/tlib/TestTest.pm, lib/Test/Unit/Error.pm, lib/Test/Unit/Exception.pm, lib/Test/Unit/Result.pm, lib/Test/Unit/TestCase.pm: - Rework the exception handling mechanisms of run_protected/run_bare so - that run-time exceptions in set_up or tear_down no longer halt the - framework, and neither do user-defined exceptions thrown in the test - methods themselves (where the framework only used to handle - straight-forward exceptions where $@ was a scalar, I think). Some - assumptions about Error.pm internals have had to be made, - unfortunately. - - * lib/Test/Unit/Procedural.pm: remove spurious 'use' line - -2002-06-12 Adam Spiers - - * lib/Test/Unit/Debug.pm: allow debugging to a file with debug_to_file - -2002-06-10 Adam Spiers - - * lib/Test/Unit/Runner/Terminal.pm: - use \e[4A\r instead of \e[4F, which not all terminals support - - * lib/Test/Unit/Runner/Terminal.pm: - Ahem. Forgot to change package name. - - * lib/Test/Unit/TkTestRunner.pm: - check that something is selected when the user clicks 'Show...' - - * lib/Test/Unit/TkTestRunner.pm: disable broken rerun button - - * MANIFEST, lib/Test/Unit/Listener.pm, lib/Test/Unit/Runner.pm, lib/Test/Unit/Runner/Terminal.pm, lib/Test/Unit/TestRunner.pm, lib/Test/Unit/TestSuite.pm: - - new start_suite/end_suite events sent to listeners, to track where - current test is in the suite hierarchy ($runner->suites_running) - - - new T::U::Runner::Terminal runner which uses terminal escape - sequences to show which suites/tests are currently being run - - - result object now stored in the runner - - * lib/Test/Unit/TkTestRunner.pm: clean up of code style - - * lib/Test/Unit/Listener.pm: - pseudo-document the parameters for the listener interface - -2002-05-23 Adam Spiers - - * doc/TODO, lib/Test/Unit/TestCase.pm: - (poorly) document @TESTS and the filtering mechanism - - * lib/Test/Unit.pm: version 0.22 - - * ChangeLog: - get this uptodate by merging auto-generated entries with existing ones - - * lib/Test/Unit/TestSuite.pm: - allow 'ALL' as a magic test name which matches all methods in this class, e.g. - - package MyTest37; - - use base qw(Test::Unit::TestCase); - - ... - - sub filter {{ - skip_thirty_seven => [ 'ALL' ], - slow => [ qw(test_I_am_slow test_I_am_slow_too) ], - }} - - * lib/Test/Unit/Assert.pm, t/tlib/AssertTest.pm: - assert_(str|num)(_not)?_equals now fail with undef parameters, - to avoid tests passing by accident. The user should either use - assert_null/assert_not_null, or check for undef before the assertion. - -2002-05-23 Adam Spiers - - * lib/Test/Unit/TestSuite.pm: - allow 'ALL' as a magic test name which matches all methods in this class, e.g. - - package MyTest37; - - use base qw(Test::Unit::TestCase); - - ... - - sub filter {{ - skip_thirty_seven => [ 'ALL' ], - slow => [ qw(test_I_am_slow test_I_am_slow_too) ], - }} - - * lib/Test/Unit/Assert.pm, t/tlib/AssertTest.pm: - assert_(str|num)(_not)?_equals now fail with undef parameters, - to avoid tests passing by accident. The user should either use - assert_null/assert_not_null, or check for undef before the assertion. - -2002-05-14 Adam Spiers - - * lib/Test/Unit/TestCase.pm: bit more debugging - -2002-03-26 Adam Spiers - - * lib/Test/Unit.pm: version 0.21 - - * lib/Test/Unit/Assert.pm, t/tlib/AssertTest.pm: - avoid UNIVERSAL::isa, which is buggy with 5.6.0 (see perldelta) - -2002-03-18 Adam Spiers - - * t/tlib/AssertTest.pm: - update boolean assertion tests for new failure message - - * doc/TODO: do_run should be public - - * lib/Test/Unit/Assertion/Boolean.pm: - slightly nicer default assertion failure message - -2002-03-04 Adam Spiers - - * lib/Test/Unit/Test.pm, lib/Test/Unit/TestCase.pm: - avoid namespace clashes in TestCase objects (thanks to jonasbn for - pointing this problem out) - - * README: update the prerequisites - -2002-02-20 Adam Spiers - - * lib/Test/Unit/Assert.pm: - reintroduce caveat about $self->assert($foo =~ /$bar/) - -2002-02-12 Adam Spiers - - * lib/Test/Unit/Assert.pm, t/tlib/AssertTest.pm: - make $self->assert([1]); work - -2002-02-05 Adam Spiers - - * lib/Test/Unit/Assert.pm, t/tlib/AssertTest.pm: - assert_deep_equals takes references 'A' and 'B', not 'got' and 'expected' - -2002-02-04 Adam Spiers - - * t/tlib/AllTests.pm, t/tlib/AssertTest.pm, t/tlib/ExceptionChecker.pm, t/tlib/TestObject.pm, t/tlib/WillDie.pm: - - factor out exception checking into ExceptionChecker - - move TestObject class into separate file - - tests for test-case methods which die ( they pass but I am still - getting funny results from my real-world test-cases )-: - - * doc/TODO: @TESTS needs testing - -2002-01-29 Adam Spiers - - * lib/Test/Unit/HarnessUnit.pm, lib/Test/Unit/Runner.pm, lib/Test/Unit/TkTestRunner.pm: - factor create_test_result - - * lib/Test/Unit/Assert.pm, t/tlib/AssertTest.pm: - - new assert_deep_equals for comparing deep structures, mostly - ripped out of Test::More - - some tests weren't getting run because of identical hash keys - when I should have been using arrays (doh!) - -2002-01-23 Adam Spiers - - * doc/TODO: need to document @TESTS - -2002-01-09 Adam Spiers - - * lib/Test/Unit/TestRunner.pm: - missed a rename from output() to annotations() - -2002-01-08 Adam Spiers - - * MANIFEST, lib/Test/Unit/Assert.pm, lib/Test/Unit/Assertion/CodeRef.pm, lib/Test/Unit/Assertion/Exception.pm, lib/Test/Unit/Assertion/Regexp.pm, t/assert.t, t/tlib/AssertTest.pm: - - Fix breakage where coderef assertions were not failing. Coderef - assertions are now expected to throw Test::Unit::Failures - ($self->fail() is a convenient way of doing this; see updated docs). - - New tests for assert(). - - New multi_assert() for using multiple argument sets with one assertion - (plus tests). - - New assert_raises() for asserting that a coderef raises a particular - class of exception (plus tests). - - * t/tlib/TestTest.pm: the famous scalar/regexp problem - -2001-12-20 Adam Spiers - - * lib/Test/Unit/Assertion.pm: whitespace - -2001-12-19 Adam Spiers - - * lib/Test/Unit/TestCase.pm: - missed a print -> annotate change in the pod - - * t/tlib/AssertTest.pm: 3 more tests for ok() - -2001-12-18 Adam Spiers - - * lib/Test/Unit/Loader.pm: - fix problem with symbol tables containing symbol tables - - * lib/Test/Unit/TestCase.pm, lib/Test/Unit/TestRunner.pm: - rename print() to annotate() - -2001-12-11 Adam Spiers - - * lib/Test/Unit/Assert.pm, t/tlib/AssertTest.pm: - - Add new assert_matches() and assert_does_not_match() assertions, - as requested by Matthias Ferber, and new tests for them of course. - - - Start testing for the correct messages in T::U::Failure objects - (see check_exception()). In particular this tests that the optional - MESSAGE args are processed correctly when reporting failures. - - - Improved behaviour of assert_equals() and assert_not_equals() with - undefined parameters. - - - Added more stringent tests for assert_equals() and assert_not_equals(). - Some of these are possibly debatable. I think the assert_equals() - matrix should be retired in favour of the check_failures() style tests - used to check assert_not_equals(), since the latter also check the - failure message and originating file/line (added a #FIXME for this). - - - Fixed reversed got/expected message with $self->ok(sub { 2 + 2 }, 4); - Spotted this as a bonus of the new check_exception(), yay. - - * lib/Test/Unit/TestRunner.pm, t/try_examples.t: - autoflush TestRunner's output stream - -2001-12-07 Adam Spiers - - * lib/Test/Unit/TestRunner.pm: Don't need that \n *either*. Doh! - - * lib/Test/Unit/TestRunner.pm: don't need that \n either - -2001-12-06 Adam Spiers - - * lib/Test/Unit/TestCase.pm: document print() - -2001-12-05 Adam Spiers - - * doc/TODO, lib/Test/Unit/Exception.pm, lib/Test/Unit/Result.pm, lib/Test/Unit/TestCase.pm, lib/Test/Unit/TestRunner.pm: - can now call $self->print("debugging stuff") within test case methods - and if the test fails or "errors" you get to see all the debugging - accumulated from the above calls - -2001-12-04 Adam Spiers - - * doc/TODO: ideas from Test::More - - * doc/TODO: $Error::Depth bug fixed (I think) - - * lib/Test/Unit/Assert.pm: - We seem to have obtained an extra 2 stack frames somewhere along the line. - This makes the new, more stringent exception checking tests in AssertTest.pm - pass. - - * t/tlib/AssertTest.pm: - - Added hairiness to failure/error testing, so it now doesn't just - check that the exception was raised, but also checks that its file() - and line() methods point correctly to the source of the failed assertion. - - Refactored duplicated code from check_failures() and check_errors() into - check_exceptions() - - * lib/Test/Unit/TestCase.pm: tiny cosmetic tweak - - * TestLister.pl, lib/Test/Unit/TestCase.pm, lib/Test/Unit/TestSuite.pm: - simple but pretty script for listing suite structure rather than running it - - * examples/fail_example.pm, lib/Test/Unit/Debug.pm: - missed a few DEBUGs in fail_example.pm - - * Makefile.PL, doc/TODO: - require base.pm version 1, so that a warning is generated for buggy - base.pms - - * lib/Test/Unit.pm: link to AUTHORS file - - * TestRunner.pl: example usage of debugging - - * lib/Test/Unit/Loader.pm: avoid warning - - * AUTHORS: Kevin was listed twice - -2001-12-03 Piers Cawley - - * AUTHORS: Added the list of Authors who've written code for PerlUnit. - Almost certainly incomplete. Add your details please. - -2001-12-03 Adam Spiers - - * lib/Test/Unit/HarnessUnit.pm: don't need that \n - - * doc/TODO: fixed - - * lib/Test/Unit/HarnessUnit.pm, lib/Test/Unit/Loader.pm, lib/Test/Unit/Result.pm, lib/Test/Unit/Setup.pm, lib/Test/Unit/Test.pm, lib/Test/Unit/TestCase.pm, lib/Test/Unit/TestRunner.pm, lib/Test/Unit/TestSuite.pm, lib/Test/Unit/UnitHarness.pm, t/all_tests.t, t/tlib/ListenerTest.pm, MANIFEST, lib/Test/Unit/Assert.pm, lib/Test/Unit/Debug.pm, lib/Test/Unit/Decorator.pm, lib/Test/Unit/Exception.pm: - All debugging now happens through a simple unified debugging class - Test::Unit::Debug. This allows the user to turn debugging on/off - dynamically, still on a per-package basis, but in a more convenient - way. Also eliminates the problem with `make test' failing when - DEBUG is "compiled in". - - * doc/TODO: more jobs - - * t/tlib/TestTest.pm: should have a name - - * t/tlib/TestTest.pm: - give inner classes names to avoid warnings in debugging - -2001-11-30 Adam Spiers - - * lib/Test/Unit/TestCase.pm: - this could come in handy when overriding list_tests() - -2001-11-30 Piers Cawley - - * lib/Test/Unit.pm: - Added a feedback section to Test::Unit's pod, suggesting that users - join perlunit-users and generally give us some feedback. - -2001-11-29 Adam Spiers - - * lib/Test/Unit/Loader.pm: forgot to put this die() in - - * MANIFEST, Makefile.PL, lib/Test/Unit.pm, lib/Test/Unit/Loader.pm, lib/Test/Unit/Procedural.pm, lib/Test/Unit/Test.pm, lib/Test/Unit/TestRunner.pm, lib/Test/Unit/TestSuite.pm, lib/Test/Unit/Warning.pm, t/tlib/AllTests.pm, t/tlib/InheritedSuite/OverrideNew.pm, t/tlib/InheritedSuite/OverrideNewName.pm, t/tlib/InheritedSuite/Simple.pm, t/tlib/InheritedSuite/TestNames.pm, t/tlib/SuiteTest.pm: - some major improvements: - - fixed the existing suite-building API, extended it, documented it fully, - added/improved tests for it - - reintroduced Test/Unit.pm, this time as a placeholder for $VERSION - and some introductory pod containing pointers to the other modules - - massive refactoring of Test::Unit::Loader - - factored out Test::Unit::Suite::_warning into Test::Unit::Warning, so - it could be used elsewhere - [I think he meant Test::Unit::TestSuite::_warning -- mca, - trying to prevent confusion] - - fixed NoTestCaseClass test - - * examples/fail_example.pm, t/try_examples.t: - add a couple of comments now I know what this Decorator/Setup business is about - - * t/try_examples.t: - skip properly, don't just mark as TODO because they aren't TODO - - * lib/Test/Unit/Decorator.pm: whitespace - - * lib/Test/Unit/Setup.pm: don't want those prototypes - - * lib/Test/Unit/UnitHarness.pm: - - @ISA = ('Exporter') line was overriding use base lines - - whitespace now matches conventions we decided on - - * t/all_tests.t, t/assert.t, t/try_examples.t: - these should be executable - -2001-11-28 Adam Spiers - - * examples/README: get this up to date (ish) - - * lib/Test/Unit/Loader.pm: - - get_package_name_from_file() never worked before (missing assignment - to $filename). - - remove dependency on FileHandle; this saves us a bit of code bloat - if we're not using UnitHarness. - - * t/try_examples.t: - I think this is right for fail_example.pm, maybe ... - - * examples/fail_example.pm: - fail_example_testsuite_setup package needs to come second, otherwise - Test::Unit::Loader::get_package_name_from_file returns the wrong suite. - - * t/tlib/ActiveTestTest.pm, t/tlib/Success.pm: - - refactoring: no point having more than one Success test case - - it should really have at least one successful test in it - - * lib/Test/Unit/Loader.pm: fix the pod - - * lib/Test/Unit/Loader.pm: - more suitable variable names - - don't need no strict 'refs' - - cosmetics - - * lib/Test/Unit/TestRunner.pm: - TestRunner can run test cases *and* test suites - - * lib/Test/Unit/HarnessUnit.pm: missing use - - * doc/TODO: copyright stuff - -2001-11-27 Adam Spiers - - * doc/TODO, lib/Test/Unit/TestSuite.pm: - Allow test suites to be derived from Test::Unit::TestSuite! - This turned out to be a relatively small change, and paves - the way for vast improvements IMO. The old API should still - work perfectly. - - * MANIFEST, README, doc/TODO, examples/patch100132, examples/patch100132-1, examples/patch100132-2, lib/Test/Unit.pm, lib/Test/Unit/Procedural.pm: - renamed Test::Unit to Test::Unit::Procedural - - * lib/Test/Unit/Test.pm, lib/Test/Unit/TestRunner.pm: - get the versioning uptodate and CPAN-compliant - - * TestRunner.pl, TkTestRunner.pl: - there's no reason why these shouldn't be executable - -2001-11-16 Adam Spiers - - * doc/TODO: done that - - * lib/Test/Unit/Loader.pm, t/tlib/AllTests.pm, t/tlib/BadSuite/BadUse.pm, t/tlib/BadSuite/SyntaxError.pm, t/tlib/BadSuitesTest.pm: - - might as well have some debugging in Loader if we have DEBUG - - fix misleading error when a suite has a bad dependency - - add tests for correct runner error message in above bad dependency - case, and for a straightforward syntax error - -2001-11-15 Piers Cawley - - * MANIFEST: Added doc/TODO - -2001-11-15 Adam Spiers - - * lib/Test/Unit/Test.pm: forgot to test DEBUG - - * doc/TODO: done some work on runner state and filtering - - * lib/Test/Unit/TestSuite.pm: only add tests via add_test() - - * MANIFEST, lib/Test/Unit/HarnessUnit.pm, lib/Test/Unit/Runner.pm, lib/Test/Unit/Test.pm, lib/Test/Unit/TestCase.pm, lib/Test/Unit/TestRunner.pm, lib/Test/Unit/TestSuite.pm, lib/Test/Unit/TkTestRunner.pm, lib/Test/Unit/UnitHarness.pm: - - add new Runner base class which is an appropriate place for runner state - common between all runners - - - very basic example of its usage: filter tokens - add something like - this to your test case - - sub filter {{ - 'slow' => [ 'test_a_slow_one', 'test_another_slow_one' ], - 'really_slow' => [ 'test_wow_really_slow' ], - }} - - then you can filter out slow tests via - - my $runner = new Test::Unit::TestRunner(); - $runner->filter(qw/slow really_slow/); - $runner->start($class); - - * lib/Test/Unit/TestRunner.pm: - tidy up output a bit - - use T::U::Loader for loading main suite - - * doc/TODO: done that - - * t/all_tests.t, t/assert.t, t/tlib/ActiveTestTest.pm, t/tlib/AllTests.pm, t/tlib/AssertTest.pm, t/tlib/InheritedInheritedTestCase.pm, t/tlib/InheritedTestCase.pm, t/tlib/ListenerTest.pm, t/tlib/NoTestCaseClass.pm, t/tlib/NoTestCases.pm, t/tlib/OneTestCase.pm, t/tlib/OverrideTestCase.pm, t/tlib/Success.pm, t/tlib/SuiteTest.pm, t/tlib/TestAssertionCodeRef.pm, t/tlib/TestTest.pm, t/tlib/TornDown.pm, t/tlib/WasRun.pm, t/try_examples.t, MANIFEST, README, lib/Test/Unit/Assert.pm, lib/Test/Unit/TestCase.pm, lib/Test/Unit/TestRunner.pm, lib/Test/Unit/TestSuite.pm, lib/Test/Unit/TkTestRunner.pm, lib/Test/Unit/Tutorial.pm: - move lib/Test/Unit/tests/*.pm to t/tlib - - * doc/TODO, doc/consensus.txt: moved some stuff to TODO - - * doc/consensus.txt: - removing stuff about new assertion mechanism, this is now in HEAD - and documented (Test::Unit::Assert*) - - * doc/TODO, doc/consensus.txt: new doc/TODO - -2001-11-14 Adam Spiers - - * lib/Test/Unit/Assertion/Boolean.pm: - get optional messages working just like with assert_str_equals etc. - -2001-11-13 Adam Spiers - - * lib/Test/Unit/Assert.pm: - add support to ok() for optional comments - - make ok() raise error not failure with bad args - - fix assert_num_equals ditching optional comment - - * lib/Test/Unit/Assertion/Regexp.pm: making debugging more readable - - * lib/Test/Unit/Assertion/Boolean.pm: - - fix typo which was hiding optional failure comment - - making debugging more readable - - * lib/Test/Unit/Exception.pm: improve legibility of failures - - * lib/Test/Unit/Assert.pm: - finish ok() wrapper, and add tests for it - - some refactoring into new check_failures() in T/U/tests/AssertTest.pm - -2001-11-12 Adam Spiers - - * Makefile.PL: - need 5.005 for qr//, thanks to Quinn Weaver for pointing that out - -2001-11-12 Piers Cawley - - * lib/Test/Unit/Assertion.pm, lib/Test/Unit/Assertion/Boolean.pm, lib/Test/Unit/Assertion/CodeRef.pm, lib/Test/Unit/Assertion/Regexp.pm, lib/Test/Unit/Decorator.pm, lib/Test/Unit/Error.pm, lib/Test/Unit/Exception.pm, lib/Test/Unit/ExceptionError.pm, lib/Test/Unit/ExceptionFailure.pm, lib/Test/Unit/Failure.pm, lib/Test/Unit/HarnessUnit.pm, lib/Test/Unit/InnerClass.pm, lib/Test/Unit/Listener.pm, lib/Test/Unit/Loader.pm, lib/Test/Unit/Result.pm, lib/Test/Unit/Setup.pm, lib/Test/Unit/Test.pm, lib/Test/Unit/TestCase.pm, lib/Test/Unit/TestDecorator.pm, lib/Test/Unit/TestFailure.pm, lib/Test/Unit/TestListener.pm, lib/Test/Unit/TestLoader.pm, lib/Test/Unit/TestResult.pm, lib/Test/Unit/TestRunner.pm, lib/Test/Unit/TestSetup.pm, lib/Test/Unit/TestSuite.pm, lib/Test/Unit/TkTestRunner.pm, lib/Test/Unit/UnitHarness.pm, t/all_tests.t, t/assert.t, t/try_examples.t, .cvsignore, ChangeLog, Changes, MANIFEST, MANIFEST.SKIP, Makefile.PL, examples/README, examples/fail_example.pm, examples/patch100132, examples/procedural-adding-suites-example.pl, examples/procedural-another-package-example.pl, examples/procedural-fail-example.pl, examples/procedural-ok-example.pl, lib/Test/Unit.pm, lib/Test/Unit/Assert.pm: - Merged changes from PDC_REFACTOR branch. - - * Makefile.PL, lib/Test/Unit/TestCase.pm: - Tidied up some formatting in Test::Unit::TestCase and added a dependency - to Makefile.PL - -2001-11-12 Adam Spiers - - * doc/consensus.txt: coding style - -2001-11-07 Adam Spiers - - * lib/Test/Unit/Assert.pm: ok(): support more cases - - * lib/Test/Unit/Assert.pm: - oops, ok() needs to reverse order of got/expected args - - * ChangeLog: - Bring ChangeLog uptodate for this branch. Hmm, maybe we should just - let CVS and rcs2log do the hard work as far as change logs are - concerned. - - * doc/consensus.txt: - only edit consensus.txt in HEAD - - consensus on use vs. require - - * lib/Test/Unit/Exception.pm: cosmetics in failure output - - * lib/Test/Unit/Assert.pm: - cosmetics in failure output - - add missing require (thanks to Hans Donner ) - - add a controversial but very convenient and harmless alias: - &ok -> &assert_equals - - * .cvsignore: New file. - - * .cvsignore: cvs-ignore Makefile - - * doc/consensus.txt: deal with broken base.pm issue - -2001-10-31 Piers Cawley - - * MANIFEST: Tidied up the MANIFEST so make tardist works. - - * MANIFEST, t/try_examples.t: - Fixed t/try_examples.t to recognize a passing test. - -2001-10-30 Piers Cawley - - * lib/Test/Unit/TestRunner.pm, lib/Test/Unit/UnitHarness.pm, Makefile.PL: - Tidied up output of TestRunner - Added prerequisites to Makefile.PL - Removed some dependencies on Test::Unit::InnerClass - -2001-10-26 Adam Spiers - - * lib/Test/Unit/tests/AssertTest.pm: fix barewords error - -2001-10-25 Adam Spiers - - * doc/consensus.txt: todo: check for broken Error.pms - -2001-09-07 pdcawley - - * ChangeLog: Added some stuff in the ChangeLog - - * lib/Test/Unit/Result.pm: More doc fixes. - - * lib/Test/Unit/Result.pm, lib/Test/Unit/TestCase.pm: - Doctored Test::Unit::Result again, so that if $test->run_bare *does* - return false we actually add a failure instead of just leaving things - up in the air (causes a problem with test harnesses if we don't) - - * lib/Test/Unit/Assert.pm, lib/Test/Unit/TestCase.pm, lib/Test/Unit/tests/AssertTest.pm, ChangeLog: - Tidied up the documentation in Test::Unit::Assert. - Made sure that Test::Unit::TestCase::run_bare returns true if it doesn't - throw an exception. - - * lib/Test/Unit/TestCase.pm: An attempt at improving the documentation. - - * lib/Test/Unit/Setup.pm: New file. - - * Changes, MANIFEST, examples/README, examples/fail_example.pm, lib/Test/Unit/Setup.pm, lib/Test/Unit/TestSetup.pm: - Renamed Test::Unit::TestSetup to Test::Unit::Setup - - * lib/Test/Unit/Listener.pm, lib/Test/Unit/tests/ListenerTest.pm: - New file. - - * MANIFEST, lib/Test/Unit/HarnessUnit.pm, lib/Test/Unit/Listener.pm, lib/Test/Unit/TestListener.pm, lib/Test/Unit/TestRunner.pm, lib/Test/Unit/TkTestRunner.pm, lib/Test/Unit/UnitHarness.pm, lib/Test/Unit/tests/AllTests.pm, lib/Test/Unit/tests/ListenerTest.pm, lib/Test/Unit/tests/TestListenerTest.pm: - Renamed Test::Unit::TestListener to Test::Unit::Listener - - * lib/Test/Unit/Decorator.pm: New file. - - * MANIFEST, lib/Test/Unit/Decorator.pm, lib/Test/Unit/TestDecorator.pm, lib/Test/Unit/TestSetup.pm: - Renamed Test::Unit::TestDecorator to Test::Unit::Decorator - - * lib/Test/Unit/Loader.pm: New file. - - * ChangeLog, MANIFEST, lib/Test/Unit/HarnessUnit.pm, lib/Test/Unit/Loader.pm, lib/Test/Unit/TestListener.pm, lib/Test/Unit/TestLoader.pm, lib/Test/Unit/TkTestRunner.pm: - Renamed Test::Unit::TestLoader to Test::Unit::Loader - -2001-09-07 Piers Cawley - - * lib/Test/Unit/TestCase.pm - (run_bare): Made sure it returns true if it doesn't throw an exception. - - * lib/Test/Unit/tests/AssertTest.pm - (test_fail_assert_not_equals): - (test_success_assert_not_equals): Added tests for assert_not_equals. - - * lib/Test/Unit/Assert.pm - Doc fixes. - (assert_not_equals): Aadded the option to assert that things - aren't equal. Also added appropriate - (assert_(str|num)_not_equals) methods. - -2001-09-02 Piers Cawley - - * lib/Test/Unit/Loader.pm - (load): Improved the error message when a file can be found, but - has a syntax error. - - * lib/Test/Unit/TestFailure.pm: - Removed. - - * lib/Test/Unit/InnerClass.pm: - Removed - - * lib/Test/Unit/tests/AssertTest.pm - Switched to a ResultsMatrix style of testing. Seems to work quite - well... - - * lib/Test/Unit/Assert.pm - (is_numeric): Got rid of warnings when the argument isn't numeric. - - * t/all_tests.t: - * t/assert_test.t: - Got rid of C since blib should be handling that. - - * lib/Test/Unit/tests/TestTest.pm: - Basic refactoring to use Class::Inner. - (make_dummy_testcase): New helper method to make anonymous - classes used in many of the tests. - - * lib/Test/Unit/Assertion/Boolean.pm - (do_assertion): Switched to a slightly more sensible way of - generating failure messages. - - * lib/Test/Unit/Loader.pm - (load): Changed the order in which we call C and - C. - - * lib/Test/Unit/TestResult.pm: - Removed dependency on Test::Unit::TestFailure. - - * lib/Test/Unit/ExceptionError.pm - (make_from_error_simple): Fixed things up slightly. This method - maybe needs a leading underscore; Framework users should probably - never see it... - - * lib/Test/Unit/Assertion.pm - (fail): Fixed things to put appropriate information into the - thrown exception. - - * lib/Test/Unit/Assert.pm: - General refactoring work to get things working with the CPAN - modules. - (assert): Now, when an exception is generated, we try and get the - appropriate caller information for setting -line and -file. Which - is nice. - (assert_equals): Fixed to use try/catch. Fixed a nasty bug with @_ - getting silently emptied via try, so now, before we call try, we - copy @_ to @args and use that inside the closure, otherwise - assert_equals would always return true. - (assert_str_equals,assert_num_equals,assert_null,assert_not_null): - All now set $Error::Depth correctly. - - * lib/Test/Unit/Exception.pm - (stringify): Tidied up stringification. - (failed_test, thrown_exception): We now conform to the - Test::Unit::TestFailure interface. Which means that we can get rid - of Test::Unit::TestFailure itself. Which is nice. - - * lib/Test/Unit.pm: - Switched to using Devel::Symdump, Class::Inner and Error - (assert): Moved to the try/catch style. - (create_suite): Vaguely major refactoring. Switched to using - Devel::Symdump and Class::Inner instead of the hand rolled symbol - table manipulation and Test::Unit::InnerClass - -2001-08-31 Piers Cawley - - * lib/Test/Unit.pm: Fixed a silly typo induced bug. - - * MANIFEST, MANIFEST.SKIP, Makefile.PL, examples/patch100132, examples/procedural-adding-suites-example.pl, examples/procedural-another-package-example.pl, examples/procedural-fail-example.pl, examples/procedural-ok-example.pl, lib/Test/Unit.pm, lib/Test/Unit/Assertion.pm, lib/Test/Unit/Assertion/Boolean.pm, lib/Test/Unit/Assertion/CodeRef.pm, lib/Test/Unit/Assertion/Regexp.pm, lib/Test/Unit/Exception.pm, lib/Test/Unit/ExceptionError.pm, lib/Test/Unit/HarnessUnit.pm, lib/Test/Unit/InnerClass.pm, lib/Test/Unit/Test.pm, lib/Test/Unit/TestCase.pm, lib/Test/Unit/TestDecorator.pm, lib/Test/Unit/TestFailure.pm, lib/Test/Unit/TestLoader.pm, lib/Test/Unit/TestResult.pm, lib/Test/Unit/TestRunner.pm, lib/Test/Unit/TestSetup.pm, lib/Test/Unit/TestSuite.pm, t/try_examples.t: - Beginnings of a major refactoring. - - 1. Replace Test::Unit::InnerClass with Class::Inner - 2. Use Error.pm as the basis for exception handling and try/catch/... - in place of eval. - 3. Use Devel::Symdump in place of hand rolled symbol table manipulation. - 4. Also includes an attempt at an 'assert_equals' that does the right - thing in most cases. Tries to make reasonable guesses about numeric or - string comparison, and can make use of object based equality things. - 5. Started to port jUnit tests that make sense in the context of PerlUnit. - - TODO: Need to get the procedural Test::Unit working. Or abandon it. However, - it does do some stuff that Test::More and friends don't (no plan testing - that actually produces a sensible 'test count') - - Write more tests. (Patches welcome) - - * t/assert.t: - Calls the (too) simple set of tests for Test::Unit::Assert and friends. - - * t/assert.t: New file. - -2001-08-30 Piers Cawley - - * lib/Test/Unit/Assert.pm: - Removed some warnings when called with 'undef'. - Also added a stringification of undef to when reporting failures... - -2001-06-18 Christian Lemburg - - * Changes, MANIFEST, examples/README, examples/fail_example.pm, lib/Test/Unit.pm, lib/Test/Unit/TestDecorator.pm, lib/Test/Unit/TestResult.pm, lib/Test/Unit/TestSetup.pm: - added TestSetup and TestDecorator by Kevin Connor - -2001-05-05 Christian Lemburg - - * README, Changes: for version 0.14 - - * t/try_examples.t: do not assume order of tests will be constant - - * lib/Test/Unit/Assertion/Boolean.pm: - fix for problem with use base and older perls - - * lib/Test/Unit/Assert.pm: document Piers additions - - * lib/Test/Unit.pm: new version, updated team member list - -2001-04-27 Matthew Astley - - * t/try_examples.t: add redirection warning for Win32 - -2001-04-09 Matthew Astley - - * doc/consensus.txt: - wittering about packaging, plus my vague plan for things I fancy doing - - * t/try_examples.t: - checks STDOUT & STDERR together, from invoking the examples - doesn't look at return codes - -2001-03-19 Piers Cawley - - * lib/Test/Unit.pm, lib/Test/Unit/InnerClass.pm, lib/Test/Unit/TestSuite.pm, lib/Test/Unit/UnitHarness.pm: - Redid Test::Unit::InnerClass to be more 'classlike'. (ie, calling - Test::Unit::InnerClass::make_inner_class as a class method rather than as a - direct subroutine call) - - Added Test::Unit::InnerClass::make_inner_class_with_coderefs - Instead of taking an extension_text argument, takes a hash of coderefs - and uses the keys as method names. Lets you do closure magic and the like - when creating inner classes. - - Moved Test::Unit::InnerClass::make_inner_class to - T::U::IC::make_inner_class_with_text. The make_inner_class subroutine now - looks at $_[2] to determine whether to dispatch to the _with_text version - of the method or the _with_coderefs version. - - Modified all the clients of Test::Unit::InnerClass to do proper Class based - method dispatch. - - Modified Test::Unit::tests::TestTest to create some of its inner classes using - the 'hash of coderefs' approach. - - Didn't do the documentation yet. - -2001-03-17 Christian Lemburg - - * Makefile.PL: - take version number for distribution file from lib/Test/Unit.pm - - * doc/release-checklist: - changed to take distribution file version number from lib/Test/Unit.pm - - * doc/release-checklist: more documentation on release procedure - - * doc/release-checklist: - added documentation on release procedure and explanation of version number stuff - - * lib/Test/Unit.pm: - Added version number again, it has to be in the module, added explanation - -2001-03-08 Piers Cawley - - * MANIFEST.SKIP, Makefile.PL, lib/Test/Unit/Assert.pm, lib/Test/Unit/Assertion.pm, lib/Test/Unit/Assertion/Boolean.pm, lib/Test/Unit/Assertion/CodeRef.pm, lib/Test/Unit/Assertion/Regexp.pm, lib/Test/Unit/Exception.pm, lib/Test/Unit/TestFailure.pm, lib/Test/Unit/TestRunner.pm, MANIFEST: - Merged the pdc_coderefassert branch. - -2001-03-07 Adam Spiers - - * lib/Test/Unit/TestCase.pm: add missing use - -2001-03-06 Piers Cawley - - * doc/consensus.txt: Added some commentary - - * lib/Test/Unit/Assert.pm: - Stopped Test::Unit::Assert::normalize_assert from dying when passed an - object that can't 'do_assertion'. Instead treats it as the argument for - Test::Unit::Assertion::Boolean::new. - - (Came across this bug while testing some of my 'real' code). - - This should also mean that, if you - - package Foo; - - use overload - bool => sub {...} - - Then assertion will continue to work properly. - - I've added a test for the simple case -- - T:U:t:TestTest::test_assert_with_non_assertion_object (essentially it's - always going to be true in this instance), but not for the case where - 'bool' is overridden. I'll leave that as an exercise for the interested - reader (plus I'm not sure how to make inner classes do overrides). - -2001-03-06 Matthew Astley - - * doc/consensus.txt: updates - -2001-03-05 Piers Cawley - - * lib/Test/Unit/Assert.pm, lib/Test/Unit/Assertion.pm: - Added some appropriate 'require's to these class files. - - * Makefile.PL, lib/Test/Unit/Assertion.pm, lib/Test/Unit/Assertion/Boolean.pm, lib/Test/Unit/Assertion/CodeRef.pm, lib/Test/Unit/Assertion/Regexp.pm: - Added a bunch of documentation to T::U::Assertion and its subclasses. - - Removed the dependency on B::Deparse (I think. If someone who hasn't got - this installed could test it...) - -2001-03-05 Adam Spiers - - * t/fail.t: Removing to avoid misguided fails on `make test'. - Brian can resurrect it if he wants when he resurfaces. - - * lib/Test/Unit/TestResult.pm: - slightly more informative debug message in run() - -2001-03-02 Piers Cawley - - * lib/Test/Unit/Assertion/Regexp.pm: Corrected a typo. - - * lib/Test/Unit/Assertion.pm, lib/Test/Unit/Assertion/Boolean.pm, lib/Test/Unit/Assertion/CodeRef.pm, lib/Test/Unit/Assertion/Regexp.pm: - New file. - - * lib/Test/Unit/Assert.pm, lib/Test/Unit/Assertion.pm, lib/Test/Unit/Assertion/Boolean.pm, lib/Test/Unit/Assertion/CodeRef.pm, lib/Test/Unit/Assertion/Regexp.pm: - Reified assertions. - - Added assertion classes for coderefs, regular expressions and booleans. - - Now Test::Unit::Assert::assert takes the first argument, the assertion, - creates an appropriate assertion object, and calls the object's do_assertion - method. - - This seems to be a win. - - Check out T::U::tests::SuiteTest and the 'basic_assertion' method. This is - possibly using a coderef for the sake of it, but it's one way of testing it - hard... - - If you check out T::U::tests::TestTest you'll see a big win on the - regexp front. - - Instead of - - $self->assert(scalar("foo" =~ /bar/), "Should not match"); - - we have - - $self->assert(qr/bar/, "foo"); - - (I haven't worked out how to name such an assertion, but the default - error message for that would look like: - 'foo' did not match /(?-xism:bar)/ - - which is pretty useful already) - -2001-02-28 Matthew Astley - - * doc/consensus.txt: append - - * lib/Test/Unit/TestCase.pm: Use the class 'isa' not the global one - - * doc/consensus.txt, lib/Test/Unit/TestCase.pm: - fix exceptions that look like object names - -2001-02-27 Matthew Astley - - * doc/consensus.txt: First cut should mention most current issues - -2001-02-27 Piers Cawley - - * Makefile.PL: Added the B::Deparse prerequisite. - - * MANIFEST, lib/Test/Unit/Assert.pm, lib/Test/Unit/Exception.pm, lib/Test/Unit/TestFailure.pm, lib/Test/Unit/TestRunner.pm: - Added an option to call assert with a coderef (currently using the - coderef_assert method, but if this is accepted we'll make the 'assert' - method DTRT.) - - Taken advantage of this to tidy up the kind of error reporting that - gets done. Which is nice. Still needs a pile of work done, but I think it's - a start. - -2001-02-27 Christian Lemburg - - * lib/Test/Unit/TestCase.pm, lib/Test/Unit/TestSuite.pm: - patch by Piers Cawley to fix overriden tests - -2001-02-22 Adam Spiers - - * lib/Test/Unit/Exception.pm: - fixed small bug where new() was assumed to be always used as an - instance method and never as a class method - - * lib/Test/Unit/InnerClass.pm: - - slightly improve legibility and remove need for no strict 'refs' - - die with helpful error if compilation of inner class fails - - * lib/Test/Unit/HarnessUnit.pm: - - make runner output more concise and legible - - do not exit(-1) on failures, as that breaks TestHarness - - output $exception->to_string() rather than $exception->stacktrace() - to avoid hiding valuable error messages - - standardise whitespace - - * lib/Test/Unit/TestListener.pm: fix trivial braino in croak message - -2001-02-22 Matthew Astley - - * doc/release-checklist: - Stash consensus reached so far on the mailing list - -2001-02-20 Matthew Astley - - * lib/Test/Unit/Assert.pm, lib/Test/Unit/Exception.pm, lib/Test/Unit/ExceptionError.pm, lib/Test/Unit/ExceptionFailure.pm, lib/Test/Unit/HarnessUnit.pm, lib/Test/Unit/InnerClass.pm, lib/Test/Unit/Test.pm, lib/Test/Unit/TestCase.pm, lib/Test/Unit/TestFailure.pm, lib/Test/Unit/TestListener.pm, lib/Test/Unit/TestLoader.pm, lib/Test/Unit/TestResult.pm, lib/Test/Unit/TestRunner.pm, lib/Test/Unit/TestSuite.pm, lib/Test/Unit/TkTestRunner.pm, lib/Test/Unit/Tutorial.pm, lib/Test/Unit/UnitHarness.pm, lib/Test/Unit.pm: - Fixes Bug#133287: Remove indentation from pod - -2001-02-17 Christian Lemburg - - * README, Changes, Makefile.PL: version 0.13 - - * lib/Test/Unit.pm: removed misleading version info - - * lib/Test/Unit.pm: - make people aware of message arg - - * examples/procedural-fail-example.pl: - show that procedural interface can handle regex problem - - * lib/Test/Unit.pm: added function prototype for assert() - - * lib/Test/Unit/Assert.pm: - added documentation about regex in boolean context - - * lib/Test/Unit/TkTestRunner.pm: - make the GUI adhere to hide of stacktrace, too - patch by David Esposito - - * lib/Test/Unit/Assert.pm: - mention optional message arg to assert - variant of patch by David Esposito - - * lib/Test/Unit/Assert.pm, lib/Test/Unit/TestCase.pm: - corrected patch to hide backtrace - -2001-02-06 Christian Lemburg - - * Changes, Makefile.PL, README, lib/Test/Unit.pm, lib/Test/Unit/Assert.pm, lib/Test/Unit/Exception.pm, lib/Test/Unit/TestCase.pm: - added patch by Matthew Astley to quell backtrace on failed tests - -2000-07-09 Christian Lemburg - - * lib/Test/Unit/TestCase.pm: - Eliminated two blanks in pod documentation that caused problems - -2000-05-07 Christian Lemburg - - * Changes, MANIFEST, README, test.pl: moved to standard CPAN style - - * examples/README: corrected typo - - * examples/Experimental/Sample.pm, examples/README, examples/patch100132, examples/patch100132-1, examples/patch100132-2: - added explanation of examples, added reply to patch100132 - -2000-04-22 Christian Lemburg - - * lib/Test/Unit.pm, lib/Test/Unit/Assert.pm, lib/Test/Unit/Exception.pm, lib/Test/Unit/ExceptionError.pm, lib/Test/Unit/ExceptionFailure.pm, lib/Test/Unit/HarnessUnit.pm, lib/Test/Unit/InnerClass.pm, lib/Test/Unit/Test.pm, lib/Test/Unit/TestCase.pm, lib/Test/Unit/TestFailure.pm, lib/Test/Unit/TestListener.pm, lib/Test/Unit/TestLoader.pm, lib/Test/Unit/TestResult.pm, lib/Test/Unit/TestRunner.pm, lib/Test/Unit/TestSuite.pm, lib/Test/Unit/TkTestRunner.pm, lib/Test/Unit/Tutorial.pm, lib/Test/Unit/UnitHarness.pm: - added and/or modified documentation - - * lib/Test/Unit/TestResult.pm, lib/Test/Unit/HarnessUnit.pm, lib/Test/Unit/InnerClass.pm, lib/Test/Unit/Test.pm, lib/Test/Unit/TestSuite.pm, lib/Test/Unit/Assert.pm, lib/Test/Unit/Exception.pm, lib/Test/Unit/ExceptionError.pm, lib/Test/Unit/ExceptionFailure.pm, lib/Test/Unit/Tutorial.pm: - added documentation - - * lib/Test/Unit/TestCase.pm, lib/Test/Unit.pm: modified documentation - - * lib/Test/Unit.pm: added documentation - -2000-03-06 Christian Lemburg - - * lib/Test/Unit/TestCase.pm: Fixed bug in POD - - * lib/Test/Unit/TestCase.pm: better documentation - - * lib/Test/Unit.pm: removed useless paranoid reload avoidance code - -2000-03-05 Christian Lemburg - - * lib/Test/Unit/Tutorial.pm: - container for tutorial on unit testing with framework - - * examples/procedural-adding-suites-example.pl: - example for procedural API test suite composition feature - - * README: procedural API can now compose test suites, too - - * lib/Test/Unit.pm: - added procedural API test suites composing feature add_suite() - -2000-03-04 Christian Lemburg - - * README, examples/procedural-another-package-example.pl: - added inter-package suite creation and run features to Procedural API - - * lib/Test/Unit.pm: added inter-package suite creation and run features - - * lib/Test/Unit/Exception.pm: - changed stacktrace to begin at level of caller of Exception->new() - - * lib/Test/Unit/TestCase.pm: - fixed run_bare() debug output to say it comes from run_bare, not _run_bare - - * lib/Test/Unit/HarnessUnit.pm, lib/Test/Unit/TestCase.pm: - removed useless middleman _run() - - * lib/Test/Unit.pm: - exported names will be seen on multiple uses, added filehandle arg to run_suite - - * lib/Test/Unit/TestRunner.pm: - removed _run method, changed exit() to die() and return for ending run - -2000-02-29 Christian Lemburg - - * lib/Test/Unit/TestCase.pm: first start at some documentation - - * lib/Test/Unit/Test.pm, lib/Test/Unit/TestSuite.pm: - enlarged Test interface (name, to_string), TestSuite run() returns result - - * lib/Test/Unit/TestSuite.pm: - fixed bug in eval subroutine run_test in warning() - missing right curly - -2000-02-27 Brian Ewins - - * lib/Test/Unit/TkTestRunner.pm: Fixed copyright notice - -2000-02-27 Christian Lemburg - - * README, examples/procedural-fail-example.pl, examples/procedural-ok-example.pl: - removed use lib from procedural API examples, use -I on commandline instead - -2000-02-26 Christian Lemburg - - * lib/Test/Unit/TestRunner.pm: - TestRunner now also uses Benchmark for timing info - - * examples/procedural-fail-example.pl: - show we also can handle messages ... has not been advertised yet ... - - * README, examples/procedural-fail-example.pl, examples/procedural-ok-example.pl, lib/Test/Unit.pm: - first cut at a procedural API wrapper, with examples (see README) - - * lib/Test/Unit/Exception.pm: nicer output again - - * lib/Test/Unit/Exception.pm, lib/Test/Unit/TestFailure.pm: - modified stringifying methods and their interplay for nicer output on errors - - * lib/Test/Unit/Test.pm, lib/Test/Unit/TestCase.pm: - Test inherits from Assert now, so TestCase and TestSuite can now assert() - -2000-02-25 Christian Lemburg - - * lib/Test/Unit/InnerClass.pm: - removed use of constant module to avoid warnings when reloading in test - -2000-02-25 Brian Ewins - - * lib/Test/Unit/TkTestRunner.pm: Fixed the File and About dialogs. - -2000-02-24 Christian Lemburg - - * lib/Test/Unit/Exception.pm: - separated to_string(), get_message(), and stacktrace() - -2000-02-24 Brian Ewins - - * lib/Test/Unit/TkTestRunner.pm: - Whoops forgot line to set the number of planned tests in - progress bar... - - * TkTestRunner.pl, lib/Test/Unit/TestLoader.pm, lib/Test/Unit/TkTestRunner.pm, lib/Test/Unit/UnitHarness.pm: - Many updates to GUI, now nearer to JUnit. Private stub - exceptions/testcases used in UnitHarness to complete - wrapping. - -2000-02-23 Christian Lemburg - - * MANIFEST, README, lib/Test/Unit/InnerClass.pm, lib/Test/Unit/TestCase.pm, lib/Test/Unit/TestSuite.pm, lib/Test/Unit/UnitHarness.pm: - fixed make_inner_class(), put it in own module, changed calls, added testcase - -2000-02-23 Brian Ewins - - * lib/Test/Unit/HarnessUnit.pm, lib/Test/Unit/TkTestRunner.pm, lib/Test/Unit/UnitHarness.pm, t/fail.t: - Lots of GUI bug fixes. Doh! - - * lib/Test/Unit/TestLoader.pm, lib/Test/Unit/TkTestRunner.pm: - Bugfixes in GUI and Loader now recognizes arbitrary .pm's - - * lib/Test/Unit/TestLoader.pm, lib/Test/Unit/TkTestRunner.pm, lib/Test/Unit/UnitHarness.pm: - Nicer looking but still incomplete GUI with - all-new 'ArrayBar' widget. Support for '.t' tests - added to TestLoader, so now GUI supports them again. - Display of .t fails should be improved next... - GUI shows progress correctly *except* when dealing with - .t tests because 'plan()' method isnt implemented in - TestRunner. - Exception details dialog added. Currently the code to - collect these details for .t tests (ie the 'verbose' - output between ok/not ok messages) is not collected. - -2000-02-22 Christian Lemburg - - * lib/Test/Unit/TestSuite.pm: - fixed extraction of test suite to work across whole inheritance tree - - * lib/Test/Unit/TestResult.pm: - deleted useless sanity check method clone_listeners - - * lib/Test/Unit/TestSuite.pm: - resolved overloading of constructor by introducing string constructor empty_new - - * lib/Test/Unit/TestRunner.pm: - deleted sub extract_class_name and changed suite method test to can() - -2000-02-22 Brian Ewins - - * t/all_tests.t, lib/Test/Unit/HarnessUnit.pm, lib/Test/Unit/TestLoader.pm: - Fleshed out HarnessUnit and implemented (sortof) tests for it. - TestLoader was updated to recognize classes with a suite method. - -2000-02-22 Christian Lemburg - - * lib/Test/Unit/TestCase.pm, lib/Test/Unit/TestResult.pm, lib/Test/Unit/TestRunner.pm, lib/Test/Unit/TestSuite.pm, README, test.pl: - added TestSuite tests - 21 tests running OK - -2000-02-21 Brian Ewins - - * README, TkTestRunner.pl, lib/Test/SuiteWrapper.pm, lib/Test/Unit/HarnessUnit.pm, lib/Test/Unit/TestListener.pm, lib/Test/Unit/TestLoader.pm, lib/Test/Unit/TestResult.pm, lib/Test/Unit/TestRunner.pm, lib/Test/Unit/TkTestRunner.pm, lib/Test/Unit/UnitHarness.pm: - Integrated TkTestRunner. Added partial TestLoader and - fleshed out TestListener. - -2000-02-21 Christian Lemburg - - * lib/Test/Unit.pm: - Deleted Unit.pm - it has been splitted to separate class files - - * MANIFEST, README, TestRunner.pl, lib/Test/Unit/Assert.pm, lib/Test/Unit/Exception.pm, lib/Test/Unit/ExceptionError.pm, lib/Test/Unit/ExceptionFailure.pm, lib/Test/Unit/Test.pm, lib/Test/Unit/TestCase.pm, lib/Test/Unit/TestFailure.pm, lib/Test/Unit/TestListener.pm, lib/Test/Unit/TestResult.pm, lib/Test/Unit/TestRunner.pm, lib/Test/Unit/TestSuite.pm, test.pl: - Running first version, separate class files, CPAN style method names - -2000-02-20 Brian Ewins - - * Changes, MANIFEST, Makefile.PL, examples/tester.pl, examples/tester.png, lib/Test/SuiteWrapper.pm, lib/Test/Unit.pm, test.pl: - A work area for the new 'Test::Unit'. This currently contains: - - standard CPAN bundling - - Christian's test.pl and new Unit.pm (as lib/Test/Unit.pm) - - my own 'Test::SuiteWrapper.pm', which works on test::harness - tests; - - examples/tester.pl - a Tk gui for using SuiteWrapper. - - examples/tester.png - a screenshot. oooh. - diff --git a/perl/third/Test-Unit-0.25/Changes b/perl/third/Test-Unit-0.25/Changes deleted file mode 100644 index dc0d11b..0000000 --- a/perl/third/Test-Unit-0.25/Changes +++ /dev/null @@ -1,52 +0,0 @@ -****************************************************************************** -* Due to lack of time, this file has been deprecated in favour of the -* automatically generated ChangeLog file. Sorry. -****************************************************************************** - - -Revision history for Perl extension Test::Unit. - -0.14 - lots of changes and additions: - Piers Cawley fixed a bad bug that caused inherited tests to - be called on the parent class instead of the inheriting class. - Piers Cawley also put in a lot of new functionality for regular - expression assertions and coderef assertions. - Matthew Astley fixed the POD documentation. - Matthew Astley and Adam Spiers fixed a number of smaller things. - Greatly improved formatting of failure reports. - Version number is now (hopefully) handled correctly for CPAN. - Kevin Connor ported Setup and TestDecorator to Perl. - -0.13 - patched the patch from 0.12, added patches by David Esposito, - (documentation for optional message arg to assert(), make - TkTestRunner use to_string() for exception display), added - documentation on problems in using assert() with regexes and - messages, fixed these problems for the procedural style - interface (where they can be solved) - -0.12 - added patch by Matthew Astley (method to quell backtrace on - failed tests, see Test::Unit::TestCase). - -0.11 - - fixed bugs in self tests that caused failed tests under HPUX - and Solaris - -0.1 - - much revised and extended due to PerlUnit effort - (see http://sourceforge.net/project?group_id=2653) - - INCOMPATIBLE CHANGES: old interface style is discontinued - (if you want support for this, use the old 0.06 version) - - resembles JUnit approach much more closely - - adapters to Test::Harness style tests - - GUI test runner using Tk - - stack traces for errors and failures - - object-oriented implementation approach supporting - test inheritance and test specialization - -0.06 - - first CPAN release -0.05 - - initial release version - -0.01 - 0.04 - - development versions diff --git a/perl/third/Test-Unit-0.25/MANIFEST b/perl/third/Test-Unit-0.25/MANIFEST deleted file mode 100644 index 5742438..0000000 --- a/perl/third/Test-Unit-0.25/MANIFEST +++ /dev/null @@ -1,84 +0,0 @@ -AUTHORS -ChangeLog -Changes -COPYING.Artistic -COPYING.GPL-2 -doc/class-diagram.dia -doc/class-diagram.png -doc/class-diagram.txt -doc/consensus.txt -doc/release-checklist -doc/TODO -examples/Experimental/Sample.pm -examples/fail_example.pm -examples/patch100132 -examples/patch100132-1 -examples/patch100132-2 -examples/README -examples/tester.png -lib/Test/Unit.pm -lib/Test/Unit/Assert.pm -lib/Test/Unit/Assertion.pm -lib/Test/Unit/Assertion/Boolean.pm -lib/Test/Unit/Assertion/CodeRef.pm -lib/Test/Unit/Assertion/Exception.pm -lib/Test/Unit/Assertion/Regexp.pm -lib/Test/Unit/Debug.pm -lib/Test/Unit/Decorator.pm -lib/Test/Unit/Error.pm -lib/Test/Unit/Exception.pm -lib/Test/Unit/Failure.pm -lib/Test/Unit/HarnessUnit.pm -lib/Test/Unit/Listener.pm -lib/Test/Unit/Loader.pm -lib/Test/Unit/Procedural.pm -lib/Test/Unit/Result.pm -lib/Test/Unit/Runner.pm -lib/Test/Unit/Runner/Terminal.pm -lib/Test/Unit/Setup.pm -lib/Test/Unit/Test.pm -lib/Test/Unit/TestCase.pm -lib/Test/Unit/TestRunner.pm -lib/Test/Unit/TestSuite.pm -lib/Test/Unit/TkTestRunner.pm -lib/Test/Unit/Tutorial.pm -lib/Test/Unit/UnitHarness.pm -lib/Test/Unit/Warning.pm -Makefile.PL -MANIFEST -README -t/all_tests.t -t/assert.t -t/tlib/ActiveTestTest.pm -t/tlib/AllTests.pm -t/tlib/AssertTest.pm -t/tlib/BadSuite/BadUse.pm -t/tlib/BadSuite/SyntaxError.pm -t/tlib/BadSuitesTest.pm -t/tlib/ExceptionChecker.pm -t/tlib/FilteredSuite.pm -t/tlib/InheritedInheritedTestCase.pm -t/tlib/InheritedSuite/OverrideNew.pm -t/tlib/InheritedSuite/OverrideNewName.pm -t/tlib/InheritedSuite/Simple.pm -t/tlib/InheritedSuite/TestNames.pm -t/tlib/InheritedTestCase.pm -t/tlib/ListenerTest.pm -t/tlib/NoTestCaseClass.pm -t/tlib/NoTestCases.pm -t/tlib/OneTestCase.pm -t/tlib/OverrideTestCase.pm -t/tlib/RunnerTest.pm -t/tlib/Success.pm -t/tlib/SuiteTest.pm -t/tlib/TestAssertionCodeRef.pm -t/tlib/TestObject.pm -t/tlib/TestTest.pm -t/tlib/TornDown.pm -t/tlib/WasRun.pm -t/tlib/WillDie.pm -t/try_examples.t -TestLister.pl -TestRunner.pl -TkTestRunner.pl -META.yml Module meta-data (added by MakeMaker) diff --git a/perl/third/Test-Unit-0.25/META.yml b/perl/third/Test-Unit-0.25/META.yml deleted file mode 100644 index eadb451..0000000 --- a/perl/third/Test-Unit-0.25/META.yml +++ /dev/null @@ -1,14 +0,0 @@ -# http://module-build.sourceforge.net/META-spec.html -#XXXXXXX This is a prototype!!! It will change in the future!!! XXXXX# -name: Test-Unit -version: 0.25 -version_from: lib/Test/Unit.pm -installdirs: site -requires: - base: 1 - Class::Inner: 0 - Devel::Symdump: 0 - Error: 0 - -distribution_type: module -generated_by: ExtUtils::MakeMaker version 6.17 diff --git a/perl/third/Test-Unit-0.25/Makefile.PL b/perl/third/Test-Unit-0.25/Makefile.PL deleted file mode 100644 index 0fb3241..0000000 --- a/perl/third/Test-Unit-0.25/Makefile.PL +++ /dev/null @@ -1,17 +0,0 @@ -use ExtUtils::MakeMaker; - -# See lib/ExtUtils/MakeMaker.pm for details of how to influence -# the contents of the Makefile that is written. - -require 5.005; - -WriteMakefile( - 'NAME' => 'Test::Unit', - 'VERSION_FROM' => 'lib/Test/Unit.pm', # finds $VERSION - 'PREREQ_PM' => { - Class::Inner => 0, - Devel::Symdump => 0, - Error => 0, - base => 1, - }, -); diff --git a/perl/third/Test-Unit-0.25/README b/perl/third/Test-Unit-0.25/README deleted file mode 100644 index 35c9cfb..0000000 --- a/perl/third/Test-Unit-0.25/README +++ /dev/null @@ -1,83 +0,0 @@ -NAME - Test::Unit::* - a unit testing framework for Perl - -DESCRIPTION - - Test::Unit::* is a sophisticated unit testing framework for Perl - that is derived from the JUnit testing framework for Java by Kent - Beck and Erich Gamma. - - While this framework is originally intended to support unit - testing in an object-oriented development paradigm (with support - for inheritance of tests etc.), Test::Unit::Procedural is intended - to provide a simpler interface to the framework that is more - suitable for use in a scripting style environment. - - Therefore, Test::Unit::Procedural does not provide much support - for an object-oriented approach to unit testing - if you want - that, please have a look at Test::Unit::TestCase (also included in - this install). - - A short tutorial on the object-oriented approach can be found in - the documentation of Test::Unit::TestCase (the test base class). - The Test::Unit self-test suite (contained in t/tlib) is a good - example of this approach. - - There is also a GUI based interface to the testing framework. - The "TkTestRunner.pl" script shows how to invoke it. - - The testing framework also features adapters for tests in the - Test::Harness style to tests in the unit testing framework style - and vice versa - see Test::Unit::HarnessUnit and - Test::Unit::UnitHarness. An example of this approach is the - self-test of the unit testing framework that you start with the - 'make test' command (see t/all_tests.t). - -PREREQUISITES - Class::Inner, Devel::Symdump and Error.pm are required. A new-ish - version of base.pm (> 1.0) is required to avoid the problem where - earlier versions failed to compile in the parent class. The Tk - module is needed for the GUI. - -INSTALLATION - Once you have installed the prerequisites, just perform the usual - incantation (replacing 'x.yy' with the current version): - - gunzip Test-Unit-x.yy.tar.gz - tar -xvf Test-Unit-x.yy.tar - cd Test-Unit-x.yy - perl Makefile.PL - make - make test - make install - -AUTHOR - Copyright (c) 2000, 2001 Christian Lemburg, . - - All rights reserved. This program is free software; you can - redistribute it and/or modify it under the same terms as - Perl itself. - - Thanks go to the other PerlUnit framework people: - Brian Ewins, Cayte Lindner, J.E. Fritz, Zhon Johansen, - Piers Cawley, Adam Spiers - - Thanks for patches go to: - Matthew Astley, David Esposito. - -SEE ALSO - - Test::Unit::TestCase (included in this install) - - the README file in the examples directory - - Refactoring -- Improving The Design Of Existing Code. - Martin Fowler. Addison-Wesley, 1999. - - http://www.xProgramming.com/ - -EXAMPLES - Use TestRunner.pl like this (lib adjusted for this directory): - - perl -w -I./lib -I./t/tlib TestRunner.pl AllTests - - Use TkTestRunner like this: - - perl -w -I./lib -I./t/tlib TkTestRunner.pl AllTests - diff --git a/perl/third/Test-Unit-0.25/TestLister.pl b/perl/third/Test-Unit-0.25/TestLister.pl deleted file mode 100755 index 73d8281..0000000 --- a/perl/third/Test-Unit-0.25/TestLister.pl +++ /dev/null @@ -1,27 +0,0 @@ -#!/usr/bin/perl -w - -use strict; - -use Getopt::Long; -use Test::Unit::Loader; - -my %opts = (); -GetOptions(\%opts, 'help', 'testcases'); -usage() if $opts{help}; - -foreach my $test (@ARGV) { - my $suite = Test::Unit::Loader::load($test); - print join '', @{ $suite->list($opts{testcases}) }; -} - -sub usage { - die < [ ... ] - -Options: - --testcases, -t List testcases contained in (sub)suites - --help, -h - -Tests can be package names or file names. -EOF -} diff --git a/perl/third/Test-Unit-0.25/TestRunner.pl b/perl/third/Test-Unit-0.25/TestRunner.pl deleted file mode 100755 index f95b469..0000000 --- a/perl/third/Test-Unit-0.25/TestRunner.pl +++ /dev/null @@ -1,13 +0,0 @@ -#!/usr/bin/perl -w - -use strict; - -use Test::Unit::Debug qw(debug_pkgs); -use Test::Unit::TestRunner; - -# Uncomment and edit to debug individual packages. -#debug_pkgs(qw/Test::Unit::TestCase/); - -my $testrunner = Test::Unit::TestRunner->new(); -$testrunner->start(@ARGV); - diff --git a/perl/third/Test-Unit-0.25/TkTestRunner.pl b/perl/third/Test-Unit-0.25/TkTestRunner.pl deleted file mode 100755 index e8356d7..0000000 --- a/perl/third/Test-Unit-0.25/TkTestRunner.pl +++ /dev/null @@ -1,7 +0,0 @@ -#!/usr/bin/perl -w - -use strict; - -use Test::Unit::TkTestRunner; - -Test::Unit::TkTestRunner::main(@ARGV); diff --git a/perl/third/Test-Unit-0.25/doc/TODO b/perl/third/Test-Unit-0.25/doc/TODO deleted file mode 100644 index ffc563e..0000000 --- a/perl/third/Test-Unit-0.25/doc/TODO +++ /dev/null @@ -1,303 +0,0 @@ -PerlUnit TODO -============= - -Here's our roadmap. It should give you an idea of what is planned, -and in some cases when it's planned for and/or who's going to do it. -Only update this file on the main branch! - -See also doc/consensus.txt. - -* Before release 1.0 - -None of these are big jobs, but Adam thinks they should all be done -before 1.0 if we want the framework to gain respect and widespread -usage; after all, many people will check out PerlUnit for the first -time when they hear 1.0 being announced, and first impressions count -for a lot. - -** Rename Test::Unit::HarnessUnit and Test::Unit::UnitHarness - -Not sure what to yet, but we want to get these big API changes out of -the way before we bump the version number. - -*** HarnessUnit -"A Test::Unit::Runner which outputs Test::Harness-style output" - -Used for most of our self-tests. - -*** UnitHarness -"A makeover of Test::Harness to allow its tests to be retrofitted as -unit tests". Seems to need some work, but is neat for running t/*.t - -What uses it? I can't see anything here, but we may have real live -(and quiet) users. - -It's referenced from T:U:Loader, but only used for certain inputs. - -** Get working build on 5.7.2 and 5.8.0 - -Now seems happy on Debian 5.8.4-2, and I'll cheerfully let the -cpan-testers find out about the others. - -** Rename do_run to run_suite - -in the runners. - -Is this to match T:U:Procedural and T:U:TkTestRunner ? - -** Tidy up copyrights, credits, and licensing - -We had copyrights, licenses, and out of date author attributions in -pretty much every file in the distribution. Tidied up 2005-07 mca. - -> It would be good to move all the copyrights and credits into one or -> two files (COPYING or LICENSE or AUTHORS, say), - -There are still some single-author files: - - T:U:Assertion* - - T:U:Decorator - T:U:Setup - - T:U:Tutorial - -> and then to change the licensing/credit bits and pieces in all the -> other files into something which refers to that one file, and also -> states that none of the files should be distributed separately, only -> as an entire package, thereby preventing the copyright-containing -> file from being disassociated from the others. - -Well I've done a chunk of that. It's not clear that the project -licences need or seek to prevent dissociation of files from the -project. - - -* Document stuff better - -** TestRunner::do_run should be public - -Requested by Matthias Ferber, so that suites can be dynamically -generated by providing parameters. - -** Filtering mechanism is poorly documented. - -** Test::Unit::Tutorial is AWOL - -** examples are old and sparse -Useful stuff has been on the lists... - -** class diagram -We have one at doc/class-diagram.* - -Dunno if it's much good. Notes include specific TODOs at the bottom. - - -* Nice to have before 1.0 - -Some of these could be left until after 1.0. Adam thinks it makes -sense to do them before the release, however; none of them are big -jobs. - -** @TESTS isn't tested. - -** Pinch more assertions from Test::More - -I don't think there's even any particular reason against importing -them directly from Test::More. No point in duplicating code across -CPAN modules without good reason. - -I like these ones: - -*** use_ok(), require_ok(), eq_set() - -import straight in - -*** is_deeply() - -either import or write using FreezeThaw::cmpStr or Data::Compare -or whatever - -*** eq_array(), eq_hash() - -Hmm. Test::Unit::Assertion::Array / Test::Unit::Assertion::Hash? - -*** Easier assertion-set extensibility - -mca: I extend test cases by having a standard (for me) superclass, -into which I pile assorted stuff. It would be nice to provide such -functionality easily and without kinking everyone's inheritance tree. - -Also, may need to avoid bloating the standard assertions set. The -overhead for the compiler is small, but the learning curve ends up -looking much steeper than it needs to be. - -Options... - - - provide "simple" and "hedgehog (bristling)" versions of TestCase - - - use import options to determine assertion set - - - leave them all in, but split the documentation - - - spread them into Piers' T:U:A:* structure... need to investigate - - -** Rethink how the tests are split up between the t/*.t. - -Currently we have t/all_tests.t, which is clearly a misnomer, and we -have some tests for the assertion code being run from that rather than -from t/assert.t. - -** Test::Unit::Loader working with whole directories. - -Test::Unit::Loader::load_test_dir() needs to be finished. - -* After 1.0 - -No harm done if they end up being done before 1.0 though, of course. - -** Test filtering - -Piers suggested the beautiful idea of using Attribute::Handlers so you -could do things like: - - sub test_something : todo {...} - sub test_something : skip_if() {...} - sub test_something : skip {...} - -Adam needs this for work ASAP, and will probably implement it very soon. -There is already a primitive filtering mechanism in place which is -controlled by the filter() and filter_method() methods. - -Update: Adam met up with Piers a few months ago and together they -figured out that Attribute::Handlers may be unusable due to its -magic happening in the BEGIN phase, whereas all user test code gets -compiled at run-time via Test::Unit::Loader. Hmm. - -** Tests to add - -*** PerlUnit selftests - -**** die errors that look like variable names [mca] - -A test that fails with an error like - - die '$lotsofdollars'; - -and make sure it gets wrapped into an ExceptionError - -**** doing the right OOP thing in constructors and isa() checks - -Possibly a test that overrides the 'isa' method so Piers' fix to my -patch - - (back to using $exception->isa(C) instead of UNIVERSAL::isa($exception,C)) - -can be exercised. - -Also Adam has patched some of the PerlUnit constructors to allow -passing a classname instead of being invoked as a method. - -**** check for broken Error.pm overloading of exceptions [as] - -Older Error.pms don't do boolean overload, so - - eval { ... }; - if ($@) { - ... - } - -could break. We should check for that. - -*** Generic tests for users to include - -Matthew wrote some. Whether anyone else wants them remains to be seen. - -The potentially useful ones: - -**** test_SubsAllNeedTests - -Checks all subs in a module are tested. Take the code and put it -somewhere else. - -**** test_PodChecker - -Look the sourcecode up in %INC and run it through the Pod::Checker -(which spits out stuff to STDOUT regardless). - -**** test_HaveWarnings - -Check $^W .. a bit cheeky. I was actually after a check for -strictness, after forgetting to use it in some module I broke off, but -this is either tricky or impossible. - -[Impossible I believe. That's kind of the point of lexical scope after all - -- pdc] - -*** Test coverage tests - -There was a big thread on this but it's someone else's turn to write -about that. 8-) -- mca - -Current thinking is to keep test-coverage tests away from the executed -tests, mainly so you can have a script which draws a pretty chart of -how well your code is tested. Adam has some code for this. - -* Personal TODO lists - -Moved here from doc/consensus.txt. - -** Matthew - -tktestrunner: ctrl-q, file menu shortcut - -assert_deep_equals patches: - check Test::More for updates - can we do that direct use linkage? - do I need to backport the patches we have? - -move the scripts somewhere so they get installed in a bin/ - -put version numbers in all modules (my or our or oldestyle?) -as below, - - - if derived from CVS, with a note somewhere about bumping CVS - versions if files take non-linear routes somewhere - - - cd src/Test-Unit; grep -rL VERSION lib/ | grep -v CVS/ - -*** integrate Debianisations and credit the relevant folks -/usr/share/doc/libtest-unit-perl/changelog.Debian.gz - -note, dropped from Debian unstable: - http://bugs.debian.org/279805 - http://bugs.debian.org/317416 - -*** update top-level README - -*** Periodic checks -(should go in doc/release-checklist, or better yet in an installation -test) - -Search for Test::* and check they still exist - -Search for 'package' ... UnitHarness contains >1 - -http://www.cpan.org/modules/04pause.html says: - Please make sure all your *.pm files contain a $VERSION variable that - conforms to the CPAN rules, i.e. the complete computation of $VERSION - must take place on the one first line within the module that assigns - to it. You can test if this is the case by running - - perl -MExtUtils::MakeMaker -le 'print MM->parse_version(shift)' 'file' - -*** Find a neat way to run unit-tested programs without the suite - -It's convenient for medium sized projects to stick the test subs in -the classes they test, but then you have a run-time dependence on perlunit. - -**** Local Variables: -**** mode: outline -**** End: - diff --git a/perl/third/Test-Unit-0.25/doc/class-diagram.dia b/perl/third/Test-Unit-0.25/doc/class-diagram.dia deleted file mode 100644 index caffaf2..0000000 --- a/perl/third/Test-Unit-0.25/doc/class-diagram.dia +++ /dev/null @@ -1,12011 +0,0 @@ - - - - - - - - - - - - - #A4# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - #Test::Unit::Failure# - - - ## - - - ## - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - #Test::Unit::Assert# - - - ## - - - ## - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - #assert# - - - ## - - - ## - - - - - - ## - - - - - - - - - - - - - - - - - - #normalize_assertion# - - - ## - - - ## - - - - - - ## - - - - - - - - - - - - - - - - - - #assert_raises# - - - ## - - - ## - - - - - - ## - - - - - - - - - - - - - - - - - - #do_assertion# - - - ## - - - ## - - - - - - ## - - - - - - - - - - - - - - - - - - #multi_assert# - - - ## - - - ## - - - - - - ## - - - - - - - - - - - - - - - - - - #is_numeric# - - - ## - - - ## - - - - - - ## - - - - - - - - - - - - - - - - - - #assert_equals# - - - ## - - - ## - - - - - - ## - - - - - - - - - - - - - - - - - - #ok# - - - ## - - - ## - - - - - - ## - - - - - - - - - - - - - - - - - - #assert_not_equals# - - - ## - - - ## - - - - - - ## - - - - - - - - - - - - - - - - - - #assert_deep_equals# - - - ## - - - ## - - - - - - ## - - - - - - - - - - - - - - - - - - #_deep_check# - - - ## - - - ## - - - - - - ## - - - - - - - - - - - - - - - - - - #_eq_array# - - - ## - - - ## - - - - - - ## - - - - - - - - - - - - - - - - - - #_eq_hash# - - - ## - - - ## - - - - - - ## - - - - - - - - - - - - - - - - - - #_format_stack# - - - ## - - - ## - - - - - - ## - - - - - - - - - - - - - - - - - - #fail# - - - ## - - - ## - - - - - - ## - - - - - - - - - - - - - - - - - - #error# - - - ## - - - ## - - - - - - ## - - - - - - - - - - - - - - - - - - #quell_backtrace# - - - ## - - - ## - - - - - - ## - - - - - - - - - - - - - - - - - - #get_backtrace_on_fail# - - - ## - - - ## - - - - - - ## - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - #Test::Unit::Procedural# - - - ## - - - ## - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - #add_to_suites# - - - ## - - - ## - - - - - - ## - - - - - - - - - - - - - - - - - - #assert# - - - ## - - - ## - - - - - - ## - - - - - - - - - - - - - - - - - - #create_suite# - - - ## - - - ## - - - - - - ## - - - - - - - - - - - - - - - - - - #run_suite# - - - ## - - - ## - - - - - - ## - - - - - - - - - - - - - - - - - - #add_suite# - - - ## - - - ## - - - - - - ## - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - #Test::Unit::Error# - - - ## - - - ## - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - #make_new_from_error# - - - ## - - - ## - - - - - - ## - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - #Test::Unit::Result# - - - ## - - - ## - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - #_Listeners# - - - ## - - - ## - - - ## - - - - - - - - - - - - - - #_Errors# - - - ## - - - ## - - - ## - - - - - - - - - - - - - - #_Failures# - - - ## - - - ## - - - ## - - - - - - - - - - - - - - #_Run_tests# - - - ## - - - ## - - - ## - - - - - - - - - - - - - - #_Stop# - - - ## - - - ## - - - ## - - - - - - - - - - - - - - - - #new# - - - ## - - - ## - - - - - - ## - - - - - - - - - - - - - - - - - - #tell_listeners# - - - ## - - - ## - - - - - - ## - - - - - - - - - - - - - - - - - - #add_error# - - - ## - - - ## - - - - - - ## - - - - - - - - - - - - - - - - - - #add_failure# - - - ## - - - ## - - - - - - ## - - - - - - - - - - - - - - - - - - #add_pass# - - - ## - - - ## - - - - - - ## - - - - - - - - - - - - - - - - - - #add_listener# - - - ## - - - ## - - - - - - ## - - - - - - - - - - - - - - - - - - #listeners# - - - ## - - - ## - - - - - - ## - - - - - - - - - - - - - - - - - - #end_test# - - - ## - - - ## - - - - - - ## - - - - - - - - - - - - - - - - - - #error_count# - - - ## - - - ## - - - - - - ## - - - - - - - - - - - - - - - - - - #errors# - - - ## - - - ## - - - - - - ## - - - - - - - - - - - - - - - - - - #failure_count# - - - ## - - - ## - - - - - - ## - - - - - - - - - - - - - - - - - - #failures# - - - ## - - - ## - - - - - - ## - - - - - - - - - - - - - - - - - - #run# - - - ## - - - ## - - - - - - ## - - - - - - - - - - - - - - - - - - #run_protected# - - - ## - - - ## - - - - - - ## - - - - - - - - - - - - - - - - - - #run_count# - - - ## - - - ## - - - - - - ## - - - - - - - - - - - - - - - - - - #run_count_inc# - - - ## - - - ## - - - - - - ## - - - - - - - - - - - - - - - - - - #should_stop# - - - ## - - - ## - - - - - - ## - - - - - - - - - - - - - - - - - - #start_test# - - - ## - - - ## - - - - - - ## - - - - - - - - - - - - - - - - - - #stop# - - - ## - - - ## - - - - - - ## - - - - - - - - - - - - - - - - - - #was_successful# - - - ## - - - ## - - - - - - ## - - - - - - - - - - - - - - - - - - #to_string# - - - ## - - - ## - - - - - - ## - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - #Test::Unit::Loader# - - - ## - - - ## - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - #obj_load# - - - ## - - - ## - - - - - - ## - - - - - - - - - - - - - - - - - - #compile# - - - ## - - - ## - - - - - - ## - - - - - - - - - - - - - - - - - - #compile_class# - - - ## - - - ## - - - - - - ## - - - - - - - - - - - - - - - - - - #compile_file# - - - ## - - - ## - - - - - - ## - - - - - - - - - - - - - - - - - - #load# - - - ## - - - ## - - - - - - ## - - - - - - - - - - - - - - - - - - #load_test# - - - ## - - - ## - - - - - - ## - - - - - - - - - - - - - - - - - - #load_test_suite# - - - ## - - - ## - - - - - - ## - - - - - - - - - - - - - - - - - - #load_test_case# - - - ## - - - ## - - - - - - ## - - - - - - - - - - - - - - - - - - #extract_testcases# - - - ## - - - ## - - - - - - ## - - - - - - - - - - - - - - - - - - #load_test_harness_test# - - - ## - - - ## - - - - - - ## - - - - - - - - - - - - - - - - - - #load_test_dir# - - - ## - - - ## - - - - - - ## - - - - - - - - - - - - - - - - - - #get_package_name_from_file# - - - ## - - - ## - - - - - - ## - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - #Test::Unit::Runner::Terminal# - - - ## - - - ## - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - #_last_test# - - - ## - - - ## - - - ## - - - - - - - - - - - - - - - - #start_suite# - - - ## - - - ## - - - - - - ## - - - - - - - - - - - - - - - - - - #end_suite# - - - ## - - - ## - - - - - - ## - - - - - - - - - - - - - - - - - - #start_test# - - - ## - - - ## - - - - - - ## - - - - - - - - - - - - - - - - - - #end_test# - - - ## - - - ## - - - - - - ## - - - - - - - - - - - - - - - - - - #add_error# - - - ## - - - ## - - - - - - ## - - - - - - - - - - - - - - - - - - #add_failure# - - - ## - - - ## - - - - - - ## - - - - - - - - - - - - - - - - - - #add_pass# - - - ## - - - ## - - - - - - ## - - - - - - - - - - - - - - - - - - #_update_status# - - - ## - - - ## - - - - - - ## - - - - - - - - - - - - - - - - - - #print_result# - - - ## - - - ## - - - - - - ## - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - #Test::Unit::Assertion# - - - ## - - - ## - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - #fail# - - - ## - - - ## - - - - - - ## - - - - - - - - - - - - - - - - - - #do_assertion# - - - ## - - - ## - - - - - - ## - - - - - - - - - - - - - - - - - - #new# - - - ## - - - ## - - - - - - ## - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - #Test::Unit::UnitHarness# - - - ## - - - ## - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - #_Name# - - - ## - - - ## - - - ## - - - - - - - - - - - - - - #_Names# - - - ## - - - ## - - - ## - - - - - - - - - - - - - - - - #new# - - - ## - - - ## - - - - - - ## - - - - - - - - - - - - - - - - - - #run# - - - ## - - - ## - - - - - - ## - - - - - - - - - - - - - - - - - - #name# - - - ## - - - ## - - - - - - ## - - - - - - - - - - - - - - - - - - #names# - - - ## - - - ## - - - - - - ## - - - - - - - - - - - - - - - - - - #add_test# - - - ## - - - ## - - - - - - ## - - - - - - - - - - - - - - - - - - #add_test_method# - - - ## - - - ## - - - - - - ## - - - - - - - - - - - - - - - - - - #count_test_cases# - - - ## - - - ## - - - - - - ## - - - - - - - - - - - - - - - - - - #to_string# - - - ## - - - ## - - - - - - ## - - - - - - - - - - - - - - - - - - #warning# - - - ## - - - ## - - - - - - ## - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - #Test::Unit::TkTestRunner# - - - ## - - - ## - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - #frame# - - - ## - - - ## - - - ## - - - - - - - - - - - - - - #number_of_errors# - - - ## - - - ## - - - ## - - - - - - - - - - - - - - #number_of_failures# - - - ## - - - ## - - - ## - - - - - - - - - - - - - - #failure_list# - - - ## - - - ## - - - ## - - - - - - - - - - - - - - #failed_tests# - - - ## - - - ## - - - ## - - - - - - - - - - - - - - #exceptions# - - - ## - - - ## - - - ## - - - - - - - - - - - - - - #planned# - - - ## - - - ## - - - ## - - - - - - - - - - - - - - #suite_name# - - - ## - - - ## - - - ## - - - - - - - - - - - - - - #suite_label# - - - ## - - - ## - - - ## - - - - - - - - - - - - - - #suite_field# - - - ## - - - ## - - - ## - - - - - - - - - - - - - - #add_text_listener# - - - ## - - - ## - - - ## - - - - - - - - - - - - - - #run# - - - ## - - - ## - - - ## - - - - - - - - - - - - - - #progress_bar# - - - ## - - - ## - - - ## - - - - - - - - - - - - - - #failure_label# - - - ## - - - ## - - - ## - - - - - - - - - - - - - - #quit_button# - - - ## - - - ## - - - ## - - - - - - - - - - - - - - #rerun_button# - - - ## - - - ## - - - ## - - - - - - - - - - - - - - #show_error_button# - - - ## - - - ## - - - ## - - - - - - - - - - - - - - #status_line_box# - - - ## - - - ## - - - ## - - - - - - - - - - - - - - #runs# - - - ## - - - ## - - - ## - - - - - - - - - - - - - - #status_line# - - - ## - - - ## - - - ## - - - - - - - - - - - - - - #listbox# - - - ## - - - ## - - - ## - - - - - - - - - - - - - - #number_of_runs# - - - ## - - - ## - - - ## - - - - - - - - - - - - - - #runner# - - - ## - - - ## - - - ## - - - - - - - - - - - - - - #result# - - - ## - - - ## - - - ## - - - - - - - - - - - - - - #start_time# - - - ## - - - ## - - - ## - - - - - - - - - - - - - - #finish_time# - - - ## - - - ## - - - ## - - - - - - - - - - - - - - #run_time# - - - ## - - - ## - - - ## - - - - - - - - - - - - - - - - #new# - - - ## - - - ## - - - - - - ## - - - - - - - - - - - - - - - - - - #about# - - - ## - - - ## - - - - - - ## - - - - - - - - - - - - - - - - - - #add_error# - - - ## - - - ## - - - - - - ## - - - - - - - - - - - - - - - - - - #add_failure# - - - ## - - - ## - - - - - - ## - - - - - - - - - - - - - - - - - - #append_failure# - - - ## - - - ## - - - - - - ## - - - - - - - - - - - - - - - - - - #plan# - - - ## - - - ## - - - - - - ## - - - - - - - - - - - - - - - - - - #choose_file# - - - ## - - - ## - - - - - - ## - - - - - - - - - - - - - - - - - - #create_punit_menu# - - - ## - - - ## - - - - - - ## - - - - - - - - - - - - - - - - - - #create_menus# - - - ## - - - ## - - - - - - ## - - - - - - - - - - - - - - - - - - #create_ui# - - - ## - - - ## - - - - - - ## - - - - - - - - - - - - - - - - - - #end_test# - - - ## - - - ## - - - - - - ## - - - - - - - - - - - - - - - - - - #get_test# - - - ## - - - ## - - - - - - ## - - - - - - - - - - - - - - - - - - #is_error_selected# - - - ## - - - ## - - - - - - ## - - - - - - - - - - - - - - - - - - #load_frame_icon# - - - ## - - - ## - - - - - - ## - - - - - - - - - - - - - - - - - - #main# - - - ## - - - ## - - - - - - ## - - - - - - - - - - - - - - - - - - #rerun# - - - ## - - - ## - - - - - - ## - - - - - - - - - - - - - - - - - - #reset# - - - ## - - - ## - - - - - - ## - - - - - - - - - - - - - - - - - - #run# - - - ## - - - ## - - - - - - ## - - - - - - - - - - - - - - - - - - #run_failed# - - - ## - - - ## - - - - - - ## - - - - - - - - - - - - - - - - - - #run_suite# - - - ## - - - ## - - - - - - ## - - - - - - - - - - - - - - - - - - #show_error_trace# - - - ## - - - ## - - - - - - ## - - - - - - - - - - - - - - - - - - #show_info# - - - ## - - - ## - - - - - - ## - - - - - - - - - - - - - - - - - - #show_status# - - - ## - - - ## - - - - - - ## - - - - - - - - - - - - - - - - - - #start# - - - ## - - - ## - - - - - - ## - - - - - - - - - - - - - - - - - - #start_test# - - - ## - - - ## - - - - - - ## - - - - - - - - - - - - - - - - - - #add_pass# - - - ## - - - ## - - - - - - ## - - - - - - - - - - - - - - - - - - #update# - - - ## - - - ## - - - - - - ## - - - - - - - - - - - - - - - - - - #add_to_history# - - - ## - - - ## - - - - - - ## - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - #Test::Unit::Assertion::CodeRef# - - - ## - - - ## - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - #new# - - - ## - - - ## - - - - - - ## - - - - - - - - - - - - - - - - - - #do_assertion# - - - ## - - - ## - - - - - - ## - - - - - - - - - - - - - - - - - - #to_string# - - - ## - - - ## - - - - - - ## - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - #Test::Unit::HarnessUnit# - - - ## - - - ## - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - #_Print_stream# - - - ## - - - ## - - - ## - - - - - - - - - - - - - - - - #new# - - - ## - - - ## - - - - - - ## - - - - - - - - - - - - - - - - - - #print_stream# - - - ## - - - ## - - - - - - ## - - - - - - - - - - - - - - - - - - #_print# - - - ## - - - ## - - - - - - ## - - - - - - - - - - - - - - - - - - #start_test# - - - ## - - - ## - - - - - - ## - - - - - - - - - - - - - - - - - - #not_ok# - - - ## - - - ## - - - - - - ## - - - - - - - - - - - - - - - - - - #ok# - - - ## - - - ## - - - - - - ## - - - - - - - - - - - - - - - - - - #add_error# - - - ## - - - ## - - - - - - ## - - - - - - - - - - - - - - - - - - #add_failure# - - - ## - - - ## - - - - - - ## - - - - - - - - - - - - - - - - - - #add_pass# - - - ## - - - ## - - - - - - ## - - - - - - - - - - - - - - - - - - #end_test# - - - ## - - - ## - - - - - - ## - - - - - - - - - - - - - - - - - - #do_run# - - - ## - - - ## - - - - - - ## - - - - - - - - - - - - - - - - - - #main# - - - ## - - - ## - - - - - - ## - - - - - - - - - - - - - - - - - - #run# - - - ## - - - ## - - - - - - ## - - - - - - - - - - - - - - - - - - #start# - - - ## - - - ## - - - - - - ## - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - #Test::Unit::Assertion::Exception# - - - ## - - - ## - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - #new# - - - ## - - - ## - - - - - - ## - - - - - - - - - - - - - - - - - - #do_assertion# - - - ## - - - ## - - - - - - ## - - - - - - - - - - - - - - - - - - #to_string# - - - ## - - - ## - - - - - - ## - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - #Test::Unit::Setup# - - - ## - - - ## - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - #run# - - - ## - - - ## - - - - - - ## - - - - - - - - - - - - - - - - - - #set_up# - - - ## - - - ## - - - - - - ## - - - - - - - - - - - - - - - - - - #tear_down# - - - ## - - - ## - - - - - - ## - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - #Test::Unit::Runner# - - - ## - - - ## - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - #_result# - - - ## - - - ## - - - ## - - - - - - - - - - - - - - #_suites_running# - - - ## - - - ## - - - ## - - - - - - - - - - - - - - #_filter# - - - ## - - - ## - - - ## - - - - - - - - - - - - - - - - #create_test_result# - - - ## - - - ## - - - - - - ## - - - - - - - - - - - - - - - - - - #result# - - - ## - - - ## - - - - - - ## - - - - - - - - - - - - - - - - - - #start_suite# - - - ## - - - ## - - - - - - ## - - - - - - - - - - - - - - - - - - #end_suite# - - - ## - - - ## - - - - - - ## - - - - - - - - - - - - - - - - - - #suites_running# - - - ## - - - ## - - - - - - ## - - - - - - - - - - - - - - - - - - #filter# - - - ## - - - ## - - - - - - ## - - - - - - - - - - - - - - - - - - #reset_filter# - - - ## - - - ## - - - - - - ## - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - #Test::Unit::Assertion::Boolean# - - - ## - - - ## - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - #new# - - - ## - - - ## - - - - - - ## - - - - - - - - - - - - - - - - - - #do_assertion# - - - ## - - - ## - - - - - - ## - - - - - - - - - - - - - - - - - - #to_string# - - - ## - - - ## - - - - - - ## - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - #Test::Unit::UnitHarness::Exception# - - - ## - - - ## - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - #stacktrace# - - - ## - - - ## - - - ## - - - - - - - - - - - - - - - - #new# - - - ## - - - ## - - - - - - ## - - - - - - - - - - - - - - - - - - #stacktrace# - - - ## - - - ## - - - - - - ## - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - #Test::Unit::TestCase# - - - ## - - - ## - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - #__PACKAGE__ . "_annotations# - - - ## - - - ## - - - ## - - - - - - - - - - - - - - #__PACKAGE__ . "_name# - - - ## - - - ## - - - ## - - - - - - - - - - - - - - - - #new# - - - ## - - - ## - - - - - - ## - - - - - - - - - - - - - - - - - - #annotate# - - - ## - - - ## - - - - - - ## - - - - - - - - - - - - - - - - - - #annotations# - - - ## - - - ## - - - - - - ## - - - - - - - - - - - - - - - - - - #count_test_cases# - - - ## - - - ## - - - - - - ## - - - - - - - - - - - - - - - - - - #create_result# - - - ## - - - ## - - - - - - ## - - - - - - - - - - - - - - - - - - #name# - - - ## - - - ## - - - - - - ## - - - - - - - - - - - - - - - - - - #run# - - - ## - - - ## - - - - - - ## - - - - - - - - - - - - - - - - - - #run_bare# - - - ## - - - ## - - - - - - ## - - - - - - - - - - - - - - - - - - #run_test# - - - ## - - - ## - - - - - - ## - - - - - - - - - - - - - - - - - - #set_up# - - - ## - - - ## - - - - - - ## - - - - - - - - - - - - - - - - - - #tear_down# - - - ## - - - ## - - - - - - ## - - - - - - - - - - - - - - - - - - #to_string# - - - ## - - - ## - - - - - - ## - - - - - - - - - - - - - - - - - - #make_test_from_coderef# - - - ## - - - ## - - - - - - ## - - - - - - - - - - - - - - - - - - #list_tests# - - - ## - - - ## - - - - - - ## - - - - - - - - - - - - - - - - - - #get_matching_methods# - - - ## - - - ## - - - - - - ## - - - - - - - - - - - - - - - - - - #list# - - - ## - - - ## - - - - - - ## - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - #Test::Unit::TestSuite# - - - ## - - - ## - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - #_Name# - - - ## - - - ## - - - ## - - - - - - - - - - - - - - #_Tests# - - - ## - - - ## - - - ## - - - - - - - - - - - - - - - - #empty_new# - - - ## - - - ## - - - - - - ## - - - - - - - - - - - - - - - - - - #new# - - - ## - - - ## - - - - - - ## - - - - - - - - - - - - - - - - - - #suite# - - - ## - - - ## - - - - - - ## - - - - - - - - - - - - - - - - - - #name# - - - ## - - - ## - - - - - - ## - - - - - - - - - - - - - - - - - - #names# - - - ## - - - ## - - - - - - ## - - - - - - - - - - - - - - - - - - #list# - - - ## - - - ## - - - - - - ## - - - - - - - - - - - - - - - - - - #add_test# - - - ## - - - ## - - - - - - ## - - - - - - - - - - - - - - - - - - #count_test_cases# - - - ## - - - ## - - - - - - ## - - - - - - - - - - - - - - - - - - #run# - - - ## - - - ## - - - - - - ## - - - - - - - - - - - - - - - - - - #filter_test# - - - ## - - - ## - - - - - - ## - - - - - - - - - - - - - - - - - - #test_at# - - - ## - - - ## - - - - - - ## - - - - - - - - - - - - - - - - - - #test_count# - - - ## - - - ## - - - - - - ## - - - - - - - - - - - - - - - - - - #tests# - - - ## - - - ## - - - - - - ## - - - - - - - - - - - - - - - - - - #to_string# - - - ## - - - ## - - - - - - ## - - - - - - - - - - - - - - - - - - #add_warning# - - - ## - - - ## - - - - - - ## - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - #Test::Unit::Exception# - - - ## - - - ## - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - #_hide_backtrace# - - - ## - - - ## - - - ## - - - - - - - - - - - - - - - - #throw_new# - - - ## - - - ## - - - - - - ## - - - - - - - - - - - - - - - - - - #stacktrace# - - - ## - - - ## - - - - - - ## - - - - - - - - - - - - - - - - - - #get_message# - - - ## - - - ## - - - - - - ## - - - - - - - - - - - - - - - - - - #hide_backtrace# - - - ## - - - ## - - - - - - ## - - - - - - - - - - - - - - - - - - #stringify# - - - ## - - - ## - - - - - - ## - - - - - - - - - - - - - - - - - - #to_string# - - - ## - - - ## - - - - - - ## - - - - - - - - - - - - - - - - - - #failed_test# - - - ## - - - ## - - - - - - ## - - - - - - - - - - - - - - - - - - #thrown_exception# - - - ## - - - ## - - - - - - ## - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - #Test::Unit::Test# - - - ## - - - ## - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - #count_test_cases# - - - ## - - - ## - - - - - - ## - - - - - - - - - - - - - - - - - - #run# - - - ## - - - ## - - - - - - ## - - - - - - - - - - - - - - - - - - #name# - - - ## - - - ## - - - - - - ## - - - - - - - - - - - - - - - - - - #to_string# - - - ## - - - ## - - - - - - ## - - - - - - - - - - - - - - - - - - #filter_method# - - - ## - - - ## - - - - - - ## - - - - - - - - - - - - - - - - - - #filter# - - - ## - - - ## - - - - - - ## - - - - - - - - - - - - - - - - - - #_find_sym# - - - ## - - - ## - - - - - - ## - - - - - - - - - - - - - - - - - - #MODIFY_CODE_ATTRIBUTES# - - - ## - - - ## - - - - - - ## - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - #Test::Unit::Listener# - - - ## - - - ## - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - #new# - - - ## - - - ## - - - - - - ## - - - - - - - - - - - - - - - - - - #start_suite# - - - ## - - - ## - - - - - - ## - - - - - - - - - - - - - - - - - - #start_test# - - - ## - - - ## - - - - - - ## - - - - - - - - - - - - - - - - - - #add_error# - - - ## - - - ## - - - - - - ## - - - - - - - - - - - - - - - - - - #add_failure# - - - ## - - - ## - - - - - - ## - - - - - - - - - - - - - - - - - - #end_test# - - - ## - - - ## - - - - - - ## - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - #Test::Unit::Decorator# - - - ## - - - ## - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - #_fTest# - - - ## - - - ## - - - ## - - - - - - - - - - - - - - - - #new# - - - ## - - - ## - - - - - - ## - - - - - - - - - - - - - - - - - - #basic_run# - - - ## - - - ## - - - - - - ## - - - - - - - - - - - - - - - - - - #count_test_cases# - - - ## - - - ## - - - - - - ## - - - - - - - - - - - - - - - - - - #run# - - - ## - - - ## - - - - - - ## - - - - - - - - - - - - - - - - - - #to_string# - - - ## - - - ## - - - - - - ## - - - - - - - - - - - - - - - - - - #get_test# - - - ## - - - ## - - - - - - ## - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - #Test::Unit::Assertion::Regexp# - - - ## - - - ## - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - #new# - - - ## - - - ## - - - - - - ## - - - - - - - - - - - - - - - - - - #do_assertion# - - - ## - - - ## - - - - - - ## - - - - - - - - - - - - - - - - - - #to_string# - - - ## - - - ## - - - - - - ## - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - #Test::Unit::TestRunner# - - - ## - - - ## - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - #_Print_stream# - - - ## - - - ## - - - ## - - - - - - - - - - - - - - - - #new# - - - ## - - - ## - - - - - - ## - - - - - - - - - - - - - - - - - - #print_stream# - - - ## - - - ## - - - - - - ## - - - - - - - - - - - - - - - - - - #_print# - - - ## - - - ## - - - - - - ## - - - - - - - - - - - - - - - - - - #add_error# - - - ## - - - ## - - - - - - ## - - - - - - - - - - - - - - - - - - #add_failure# - - - ## - - - ## - - - - - - ## - - - - - - - - - - - - - - - - - - #add_pass# - - - ## - - - ## - - - - - - ## - - - - - - - - - - - - - - - - - - #do_run# - - - ## - - - ## - - - - - - ## - - - - - - - - - - - - - - - - - - #end_test# - - - ## - - - ## - - - - - - ## - - - - - - - - - - - - - - - - - - #main# - - - ## - - - ## - - - - - - ## - - - - - - - - - - - - - - - - - - #print_result# - - - ## - - - ## - - - - - - ## - - - - - - - - - - - - - - - - - - #print_errors# - - - ## - - - ## - - - - - - ## - - - - - - - - - - - - - - - - - - #print_failures# - - - ## - - - ## - - - - - - ## - - - - - - - - - - - - - - - - - - #print_header# - - - ## - - - ## - - - - - - ## - - - - - - - - - - - - - - - - - - #run# - - - ## - - - ## - - - - - - ## - - - - - - - - - - - - - - - - - - #run_and_wait# - - - ## - - - ## - - - - - - ## - - - - - - - - - - - - - - - - - - #start# - - - ## - - - ## - - - - - - ## - - - - - - - - - - - - - - - - - - #start_test# - - - ## - - - ## - - - - - - ## - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ## - - - ## - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ## - - - ## - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ## - - - ## - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ## - - - ## - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ## - - - ## - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ## - - - ## - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ## - - - ## - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ## - - - ## - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ## - - - ## - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ## - - - ## - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ## - - - ## - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ## - - - ## - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ## - - - ## - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ## - - - ## - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ## - - - ## - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ## - - - ## - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ## - - - ## - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ## - - - ## - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ## - - - ## - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ## - - - ## - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ## - - - ## - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ## - - - ## - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ## - - - ## - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ## - - - ## - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ## - - - ## - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ## - - - ## - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ## - - - ## - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ## - - - ## - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ## - - - ## - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ## - - - ## - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ## - - - ## - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ## - - - ## - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ## - - - ## - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ## - - - ## - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ## - - - ## - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ## - - - ## - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ## - - - ## - - - - - - - - - - - - - - - - - - - - - - - - #Error# - - - ## - - - ## - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ## - - - ## - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ## - - - ## - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ## - - - ## - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ## - - - ## - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ## - - - ## - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ## - - - ## - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ## - - - ## - - - - - - - - - - - - - - - - - - - - - - - - #Test::Unit::Warning# - - - ## - - - ## - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - #_message# - - - ## - - - ## - - - ## - - - - - - - - - - - - - - - - #run_test# - - - ## - - - ## - - - - - - ## - - - - - - - - - - - - - - - - - - #new# - - - ## - - - ## - - - - - - ## - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - #Test::Unit::UnitHarness::TestCase# - - - ## - - - ## - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - #run_test# - - - ## - - - ## - - - - - - ## - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - #(c) 2005 PerlUnit project <http://perlunit.sf.net/> -Class diagram generated by autodia <http://droogs.org/autodia> -and some tweaking, for "v0.24 plus bugfixes and filtering", -the CVS "HEAD" version 2005-07-01# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - #See doc/class-diagram.txt for caveats!# - - - - - - - - - - - - - - - - - - - - - diff --git a/perl/third/Test-Unit-0.25/doc/class-diagram.png b/perl/third/Test-Unit-0.25/doc/class-diagram.png deleted file mode 100644 index beeaf438758c58951d70391b00857d757fd10de8..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 178018 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∨jU<>w(Y~SX!7qGS37{+(B3Y&a=ZB2q$q50bQc&R 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 XvqQ})G>twTEzm7_HFUnLiQoSN;7GKr diff --git a/perl/third/Test-Unit-0.25/doc/class-diagram.txt b/perl/third/Test-Unit-0.25/doc/class-diagram.txt deleted file mode 100644 index 1a121b2..0000000 --- a/perl/third/Test-Unit-0.25/doc/class-diagram.txt +++ /dev/null @@ -1,198 +0,0 @@ --*- outline -*- (this mark tells Emacs to use '*' heading levels) - - -* Comments on the class diagrams -Diagram is in early stages so - - - there are probably better ways to carve it up - - - there are bugs in it, take it as an overview - -Please let me know if it's helpful -- mca1001 - - -I've coloured parts of the full diagram, to try to show where to -start. And starting may be all you need. - -** Classes to interact with directly (yellow) -These classes have fairly thorough POD and are intended as the main -interfaces for "the user". - -Test::Unit::Procedural is all you need for simple work, but reduces -flexibility. You don't need it at all for the explicit object -oriented approach. - -Test::Unit::TestCase is what you inherit you tests from, if you take -the explicit OO approach. - -Test::Unit::TestSuite can be used to put your TestCases together in -groups or trees, and make it easier to manage more complex OO test -systems. - -** Test runners (green) -One of these will be used to manage the running of your test suite. -They all do basically the same thing, but their outputs are different: -interactive GUI, terminal and Test::Harness linkage. - -Generally, an instance will be made for you by whatever script you use -to kick off the test run, e.g. TestRunner.pl or TkTestRunner.pl - -** Things you'll probably see (red) -If something die()s during your test - any sort of error - this is -caught and wrapped as a Test::Unit::Error object. - -When a test assertion fails, an instance of Test::Unit::Failure is -created and "thrown". - -These objects then percolate into the depths of the mechanism, to be -collected and reported later. I'm being vague, to spare you the -details. - -Test::Unit::Assert isn't for use explicitly in your code, but the -manpage contains a handy breakdown of the various assert methods you -can use. - - -* Construction of class diagram -** Generate the bulk of the diagram -I fired up "autodia" aka. "autodial" with - - cd $PROJDIR - autodia.pl -d lib/ -rC - dia-gnome autodia.out.xml & - -Then I started moving boxes around. Don't worry, they are joined -together! It helps to set the "autoroute" property on the -connectors... use the "group properties..." dialog? I didn't get as -far as hacking the template to fix this. - -...shuffle boxes until they're close to the relevant thing and you -have a big tangle of class usage. Time to simplify. Probably easier -if you crib my layout. - -[later] It doesn't list inheritance outside the codebase...? Or just -not for "use base". And not for Test::Unit::TestSuite, -Test::Unit::Warning... argh. - -** Remove stuff that isn't helping -There are dependencies in there which don't need to be graphed. - -List of class/what uses it, plus rough notes: - - base - used by many classes - - Config - Test::Unit::UnitHarness - - Error - base class for Test::Unit::Exception, so left on the diagram - also used by - Test::Unit::Procedural - Test::Unit::Assertion::Exception - Test::Unit::Assert - Test::Unit::Result - Test::Unit::TestCase - - File::Basename - Test::Unit::TkTestRunner - - Tk, Tk::BrowseEntry - Test::Unit::TkTestRunner - - - Tk::ROText Tk::ArrayBar (?) should be TkTestRunner - Tk::DialogBox Tk::ArrayBar (?) - Tk::Derived Tk::ArrayBar - Tk::Canvas Tk::ArrayBar - - Devel::Symdump -> what's this all about, then? - Test::Unit::Procedural - Test::Unit::TestCase - - Filehandle - Test::Unit::Loader - Test::Unit::UnitHarness - - Benchmark -> candidate for moving to Test::Unit::Runner - Test::Unit::TestRunner - Test::Unit::TkTestRunner - - Exporter -> (list incomplete) -> may be useful to know... - Test::Unit::Debug - Test::Unit::Procedural - Test::Unit::UnitHarness - - - Class::Inner -> was split off this project at some point? - Test::Unit::Procedural - Test::Unit::UnitHarness - Test::Unit::TestCase - - Tk:ArrayBar -> is part of Test::Unit::TkTestRunner, interesting in its own right, but not relevant here - - - Test::Unit::Debug - used by many things, but basically dull - Test::Unit::Assertion::CodeRef - Test::Unit::Assert - Test::Unit::Assertion::Exception - Test::Unit::TestSuite - Test::Unit::Result - Test::Unit::Test - Test::Unit::TestCase - Test::Unit::UnitHarness - Test::Unit::Loader - - Test::Unit::Loader -> used by many things; headed towards "scary" -> looks like it should be used by the Runner instead? - Test::Unit::Listener - Test::Unit::TestSuite - Test::Unit::HarnessUnit - Test::Unit::TkTestRunner - Test::Unit::TestRunner - uses - Test::Unit::UnitHarness - Test::Unit::TestSuite - - Test::Unit::Warning - mundane helper class - Test::Unit::TestSuite - Test::Unit::Loader - - Test::Unit::Tutorial - contains no code - - Test::Unit - contains only constants - Test::Unit::TestRunner - Test::Unit::TkTestRunner - -** TO DO - -Filter method & members: some detail is obsolete, should be hidden, -takes up too much space. - -Ensure all classes are shown. - -Mark presence of/need for docs, level of detail, position on learning -parabola. - -Um, I'm just about to add more stuff. Doh. - -Check uses & inheritance lines are correct and significant. How -tedious. - -It would be nice to cover all the classes with at least some -explanation of what they are and how they fit in, but there's no point -duplicating POD material. Maybe break out the relevant parts into -another diagram that shows the examples too? - -A similar diagram (sequence diagram?) for how the tests are loaded, -built into suites, run and reported. diff --git a/perl/third/Test-Unit-0.25/doc/consensus.txt b/perl/third/Test-Unit-0.25/doc/consensus.txt deleted file mode 100644 index c761b1e..0000000 --- a/perl/third/Test-Unit-0.25/doc/consensus.txt +++ /dev/null @@ -1,166 +0,0 @@ --*- outline -*- - -* Intro - -We were wondering how we should go about keeping track of the -consensuses (sp?) we reached on the perlunit-devel mailing list. -Matthew was all for a cumbersome set of tags so we could grep the list -for "points". Christian suggested a simple text file in CVS which we -modify as appropriate. This is a compromise - a simple text file -marked up for use with emacs' "outline-mode". Most of the active -developers use emacs. - -Issues currently being discussed on the list can be kept track of here -by listing any suggestions made or conclusions which were reached. -Once it's decided what needs to be done, the details should be moved -to doc/TODO and someone will get on with implementing them. - -Please only update this file on the main branch! - -** Links back to the mailing list - -Might be handy for those with local archives, but dropping message-ids -in this file will make a mess IMHO -- mca - -* Coding conventions - -If in doubt, conform to the style shown in the existing code. - -** use vs. require - -After a discussion on perlunit-devel in March 2001, subject 'Towards -sensible failure messages', we settled on use rather than require, except -where we only want to load a module if we need it, of course. - -** whitespace - -No hard tabs, 4 column indent level. - -* Auto-adding tests, Test::Unit::TestSuite->new() - -** interaction with inheritance - -Broken in v0.13, it will take SUPER::test_foo if test_foo is -an inheritted method in the class being scanned. - -Fixed by Piers. - -** regexps to pull functions called /^test/ - -I think current consensus is to change the default to /^test[_A-Z]/ -but make it configurable. - -I seem to have lost that thread -- mca - -* Debug methods - -Not much agreement yet, here are some of the suggestions - -** $self->debug() - -A dead/unused patch from Matthew, the idea was a default debug in the -base T:U:TestCase class and methods to override it. Messy and -inconvenient. - -** $self->listener->debug($@) - -Some say listeners are Java-ish. Others say that they're good anyway. -9-) - -Arguments are headed towards something like - debug( level => 123, - user => "simple message", - developer => "complicated message" ); -or some variation on the theme. - -This all looks rather verbose so far though. 8-( - -** clever things with caller() - -one vote for [MCA] (provided you can override it) -one vote against? [PDC] - -* Documentation - -** Where? - -Where should it be kept? At the moment it lives almost entirely in POD -and mailing list/message board format, and so is inaccessible. - -A pod2html pass of released software should probably be served on the -website. - -Matthew's (almost finished) cvspublish.pl script could do most of this -but is probably overkill. Also it doesn't grok MANIFEST files. - -There is a documentation manager on SF. The front door is not too -friendly and there is no back door to the data inside it. - -** API & PerlUnit overview - -Current favourite is to point at the JUnit docs. - -There is in 'src/api' a set of basic perl modules containing the -essence of the structure, but they're getting old. - -Also, the SF message boards have some knowledge which needs -distilling. - -* Namespace pollution - -** classes used during self-tests - -We're going to try to avoid it while generating "inner classes" or -whatever, for the self-tests. - -** keys in the TestCase object hash [not yet discussed] - -T:U::TestCase::new is biting into namespace belonging to classes -inherited from T:U::TestCase .. currently it only takes _name ... I'm -wondering whether we should go to '__' prefix in the C tradition for -"magic things", since the perlunit user shouldn't need to mess with -this? -- mca - -Not sure I understand what you're getting at here. The PITA approach would be -to name all the keys used only by T:U::TestCase as - -'Test::Unit::TestCase::keyname', which is a pain to work with, but probably -the best practice. See the discussion in Damian Conway's Object Oriented Perl. - - -- pdc - -* TODO lists - -Moved to doc/TODO. - -* Packaging - -[mca: Christian has SourceForge and CPAN packaging pretty much wrapped -up *cough*, this is documented in another file in this directory] - -** Debian GNU/Linux - -[mca: Since I use perlunit for production work, I'm tempted to roll a -package if it's not too tricky. There is a stack of reading to do -first though (I'm not an official Debian developer) - -Relevant bit from /usr/doc/dh-make-perl/README - - dh-make-perl will create the files required to build - a debian source package out of a perl package. - This works for most simple packages and is also useful - for getting started with packaging perl modules. - - There is an override mechanism in place to handle most of - the little changes that may be needed for some modules - (this hasn't been tested much, though). - - Using this program is no excuse for not reading the - debian developer documentation, including the policy, - the perl policy, the packaging manual and so on. - -See also http://www.uk.debian.org/devel/ ] - -** RedHat - -[mca: I made a RH package a long time ago... don't remember how] diff --git a/perl/third/Test-Unit-0.25/doc/release-checklist b/perl/third/Test-Unit-0.25/doc/release-checklist deleted file mode 100644 index 3612d04..0000000 --- a/perl/third/Test-Unit-0.25/doc/release-checklist +++ /dev/null @@ -1,173 +0,0 @@ - - This is out of date in places. I haven't investigated which places. - - Note that there are multiple bug trackers, listed here in what mca - considers the order of preference, - - http://sourceforge.net/tracker/?group_id=2653&atid=102653 - http://rt.cpan.org/NoAuth/Bugs.html?Dist=Test-Unit - http://bugs.debian.org/libtest-unit-perl - - Also note use of ChangeLog instead of Changes, and parts of doc/TODO - -------------------------------------------------- -The procedure should be: -------------------------------------------------- - -Prerequisites: -Make sure all the tests run OK. -Make sure all the examples run OK. - -1. Commit new files in src/Test-Unit -2. lib/Test/Unit.pm - put in the new $VERSION for the distribution -3. MANIFEST if files are to be added to the tarball - ("make manifest" will add new files and tell you, but check they're - not local cruft from your working copy. Get a clean checkout of - the working copy to ensure no files are missing, or that you have - removed deleted files from MANIFEST.) -4. cvs rtag -r HEAD REL_0_14 releasemodule - (with the $VERSION number from above) -5. make clean ; perl Makefile.PL ; make tardist -6. upload to incoming as per Sourceforge docs -7. notify current CPAN maintainer to get an upload - - -------------------------------------------------- -Explanation on version number synchronization: -------------------------------------------------- - -The CPAN module will decide to upgrade a module when the version number -of the module installed locally is less than the highest version number -of any version of the module it can find on CPAN. It will find out the -distribution file this module is in, and then install this distribution -file. This can lead to surprising results for distribution files that -contain multiple modules. - -Take this common situation: package Foo-0.22.tar.gz contains modules -Foo, Foo::Bar, and Foo::Baz. Now, something changes in Foo::Bar, and -Foo::Bar gets a new version number. The module author happily uploads -Foo-0.23.tar.gz to CPAN. - -Now, will the CPAN module use Foo-0.23.tar.gz to upgrade package Foo if you -tell it "install Foo"? No. CPAN will look at the version number for Foo, -determine it has not changed compared to the locally installed version, -and do nothing. You have to tell it "install Foo::Bar" to get the new -distribution file, which is bad, since nobody will know she has to -do that. - -The solution is to make sure any time a distribution file gets upgraded, -its top level module should get a new, higher version number. This way, -things will work like people expect them to work. - -Please note that any module on CPAN should have a version number, even -if it is contained in a package with many other modules. This ensures -that people can require a certain version of any module in a given -distribution file. - - -------------------------------------------------- -References -------------------------------------------------- - -Date: Wed, 21 Feb 2001 14:06:35 +0000 -From: Matthew Astley -To: perlunit-devel@lists.sourceforge.net -Subject: Re: [Perlunit-devel] CVS tags / release procedure -Message-ID: <20010221140635.P25661@grantadesign.com> -References: <20010220215614.H25661@grantadesign.com> <000901c09bf0$a1641140$9f0010ac@aixonix.de> <20010221130709.A9412@thelonious.new.ox.ac.uk> <20010220215614.H25661@grantadesign.com> <000901c09bf0$a1641140$9f0010ac@aixonix.de> -In-Reply-To: <000901c09bf0$a1641140$9f0010ac@aixonix.de>; from lemburg@aixonix.de on Wed, Feb 21, 2001 at 11:25:36AM +0100 - -On Wed, Feb 21, 2001 at 11:25:36AM +0100, Christian Lemburg wrote: - -> OK so far, I suggest to replace the manual tar with -> "make clean ; perl Makefile.PL ; make tardist" -> (your perl will do the Right CPAN Thing for you). - -[revised] - - Commit new files in src/Test-Unit-0.1 including - - - Changes (section for release at the top) - - - Makefile.PL (set new $VERSION) - - - README (Version numbers on installation commands .. surely we - could put something generic in here?) - - - MANIFEST if files are to be added to the tarball - - cvs rtag -r HEAD REL_0_14 releasemodule - - cvs exp -r REL_0_14 -d Test-Unit-n.nn src/Test-Unit-0.1 - - make clean ; perl Makefile.PL ; make tardist - - (upload to incoming as per Sourceforge docs) - - -As for the CPAN stuff, is this complicated? Presumably the significant -changes are documented in ExtUtils::MakeMaker? - -Also, since there's filtering via MANIFEST, is there any need to -'export' instead of running from a checked out working copy? Could -Makefile.PL enquire of CVS or the top of the Changes file which -version we're releasing? - -I'm thinking about reducing the number of things that need trivial -tweaks before making a release. - -> > I'm left thinking that it could be handy to tag files as development -> > only, so for example I could drop my GenericTests.pm into place but -> > tag it as mine/not for release. It's rather hard for someone to commit -> > on a patch, I think? - -So we've a solution to this separate problem, but perhaps we should -hold off the feature creep until we've got more tests in? - -(any bright ideas for ways to tie the docs to the tests so the can -fail a test when we tweak things? I'm just about to digress hugely so -I'll save it for another post) - -> > * tag release stuff as STABLE or similar, then do -> > -> > cvs rtag -r STABLE REL_0_14 releasemodule -[patches commands above, nb. "-r HEAD" instead of "-r STABLE"] -> > -> > and export that. -> -> That would be my preferred option. - -Would suit me too, since ATM we've no way to backtrace to a release. -Only thing is, if you can release a checked out copy, the export is a -little wasteful. - - -Matthew #8-) - - -From: "Christian Lemburg" -To: "Matthew Astley" , - -References: <20010220215614.H25661@grantadesign.com> <000901c09bf0$a1641140$9f0010ac@aixonix.de> <20010221130709.A9412@thelonious.new.ox.ac.uk> <20010220215614.H25661@grantadesign.com> <000901c09bf0$a1641140$9f0010ac@aixonix.de> <20010221140635.P25661@grantadesign.com> -Subject: Re: [Perlunit-devel] CVS tags / release procedure -Date: Wed, 21 Feb 2001 15:58:34 +0100 - -> Also, since there's filtering via MANIFEST, is there any need to -> 'export' instead of running from a checked out working copy? Could -> Makefile.PL enquire of CVS or the top of the Changes file which -> version we're releasing? - -No. You can just run from a checked out working copy. -At least that was what I did until now. - -Cheers, - -Christian - - - -_______________________________________________ -Perlunit-devel mailing list -Perlunit-devel@lists.sourceforge.net -http://lists.sourceforge.net/lists/listinfo/perlunit-devel - diff --git a/perl/third/Test-Unit-0.25/examples/Experimental/Sample.pm b/perl/third/Test-Unit-0.25/examples/Experimental/Sample.pm deleted file mode 100644 index 2b60c9d..0000000 --- a/perl/third/Test-Unit-0.25/examples/Experimental/Sample.pm +++ /dev/null @@ -1,33 +0,0 @@ -package Experimental::Sample; - -use strict; -use vars qw($VERSION @ISA @EXPORT $SIGNPOST $test_suite); - -require Exporter; - -@ISA = qw(Exporter); - - -sub new { - my $pkg = shift; - my $self = { @_ }; - - - bless($self, $pkg); - - return $self; -} - -# object methods - public - -sub name { - my ( $self, $name ) = @_; - if( defined( $name ) ){ - $self->{name} = $name; - } - return $self->{name}; -} - - -1; -__END__ diff --git a/perl/third/Test-Unit-0.25/examples/README b/perl/third/Test-Unit-0.25/examples/README deleted file mode 100644 index d29c92c..0000000 --- a/perl/third/Test-Unit-0.25/examples/README +++ /dev/null @@ -1,16 +0,0 @@ -This directory contains examples of the framework in use. -It's a bit out of date now... - -tester.png: ------------ -This is a screenshot of the GUI running (view with a PNG viewer, e.g., -your favorite web browser). Also visible on the SF screenshot page. - -patch100132*, fail_example.pm ------------------------------ - -Very mysterious. They get used by 'make test' via t/try_examples.t -though. fail_example.pm is supposed to be an example for -TestDecorator and Setup. You can run it via: - - perl -I../lib/ ../TestRunner.pl fail_example diff --git a/perl/third/Test-Unit-0.25/examples/fail_example.pm b/perl/third/Test-Unit-0.25/examples/fail_example.pm deleted file mode 100644 index f7acde1..0000000 --- a/perl/third/Test-Unit-0.25/examples/fail_example.pm +++ /dev/null @@ -1,60 +0,0 @@ -package fail_example; # this is the test case to be decorated - -use strict; - -use Test::Unit::Debug qw(debug debugged); -use Test::Unit::TestSuite; - -use base qw(Test::Unit::TestCase); - -sub test_ok { - my $self = shift(); - $self->assert(23 == 23); -} - -sub test_fail { - my $self = shift(); - $DB::single = $DB::single; # avoid 'used only once' warning - $DB::single = 1 if debugged(); #this breaks into the debugger - $self->assert(scalar "born" =~ /loose/, "Born to lose ..."); -} - -sub set_up { - my $self = shift()->SUPER::set_up(@_); - debug("hello world\n"); -} - -sub tear_down { - my $self = shift(); - debug("leaving world again\n"); - $self->SUPER::tear_down(@_); -} - -sub suite { - my $testsuite = Test::Unit::TestSuite->new(__PACKAGE__); - my $wrapper = fail_example_testsuite_setup->new($testsuite); - return $wrapper; -} - -1; - -package fail_example_testsuite_setup; -# this suite will decorate fail_example with additional fixture - -use strict; -use Test::Unit::Debug qw(debug); - -use base qw(Test::Unit::Setup); - -sub set_up { - my $self = shift()->SUPER::set_up(@_); - debug("fail_example_testsuite_setup\n"); -} - -sub tear_down { - my $self = shift(); - debug("fail_example_testsuite_tear_down\n"); - $self->SUPER::tear_down(@_); -} - -1; diff --git a/perl/third/Test-Unit-0.25/examples/patch100132 b/perl/third/Test-Unit-0.25/examples/patch100132 deleted file mode 100644 index 002d5b9..0000000 --- a/perl/third/Test-Unit-0.25/examples/patch100132 +++ /dev/null @@ -1,41 +0,0 @@ -#!/usr/bin/perl -w - -use strict; - -use Experimental::Sample; -use Test::Unit::Procedural; - -use constant DEBUG => 0; - -# code to be tested will be somewhere around here - -# define tests, set_up and tear_down - -sub test_ok_1 { - assert(23 == 23); -} - -sub test_ok_2 { - assert(42 == 42); -} - -sub test_ok_3 { - my $sample = new Experimental::Sample(); - $sample->name( 'Joe' ); - assert( 'Joe' eq $sample->name() ); -} - -sub set_up { - print "hello world\n" if DEBUG; -} - -sub tear_down { - print "leaving world again\n" if DEBUG; -} - -# and run them - - -create_suite( 'Experimental::Sample' ); -create_suite; -run_suite(); diff --git a/perl/third/Test-Unit-0.25/examples/patch100132-1 b/perl/third/Test-Unit-0.25/examples/patch100132-1 deleted file mode 100644 index 8cedb01..0000000 --- a/perl/third/Test-Unit-0.25/examples/patch100132-1 +++ /dev/null @@ -1,50 +0,0 @@ -#!/usr/bin/perl -w - -use strict; - -use Experimental::Sample; -use Test::Unit::Procedural; - -use constant DEBUG => 0; - -# code to be tested will be somewhere around here - -# define tests, set_up and tear_down - -sub test_ok_1 { - assert(23 == 23); -} - -sub test_ok_2 { - assert(42 == 42); -} - -sub test_ok_3 { - my $sample = new Experimental::Sample(); - $sample->name( 'Joe' ); - assert( 'Joe' eq $sample->name() ); -} - -sub set_up { - print "hello world\n" if DEBUG; -} - -sub tear_down { - print "leaving world again\n" if DEBUG; -} - -# and run them - -# This will not work, as the test methods were -# defined in package main: -# -# create_suite( 'Experimental::Sample' ); -# run_suite(); -# -# We need to create the default suite -# (created from package main) to pick -# our test methods up - they just use the -# methods in Experimental::Sample ... - -create_suite(); -run_suite(); diff --git a/perl/third/Test-Unit-0.25/examples/patch100132-2 b/perl/third/Test-Unit-0.25/examples/patch100132-2 deleted file mode 100644 index 1d5af7c..0000000 --- a/perl/third/Test-Unit-0.25/examples/patch100132-2 +++ /dev/null @@ -1,69 +0,0 @@ -#!/usr/bin/perl -w - -use strict; - -use Experimental::Sample; -use Test::Unit::Procedural; - -use constant DEBUG => 0; - -# code to be tested will be somewhere around here - -# define tests, set_up and tear_down - -sub test_ok_1 { - assert(23 == 23); -} - -sub test_ok_2 { - assert(42 == 42); -} - -sub test_ok_3 { - my $sample = new Experimental::Sample(); - $sample->name( 'Joe' ); - assert( 'Joe' eq $sample->name() ); -} - -sub set_up { - print "hello world\n" if DEBUG; -} - -sub tear_down { - print "leaving world again\n" if DEBUG; -} - -# and run them - -# This will not work, as the test methods were -# defined in package main: -# -# create_suite( 'Experimental::Sample' ); -# run_suite(); -# -# We need to create the default suite to pick -# our test methods up - they just use the -# methods in Experimental::Sample ... -# -# The other way is to define the tests in -# package Experimental::Sample itself. -# Then we can proceed as indicated above, -# but we obviously need to run the suite -# we created, not the default suite: - -sub Experimental::Sample::test_ok_1 { - assert(23 == 23); -} - -sub Experimental::Sample::test_ok_2 { - assert(42 == 42); -} - -sub Experimental::Sample::test_ok_3 { - my $sample = new Experimental::Sample(); - $sample->name( 'Joe' ); - assert( 'Joe' eq $sample->name() ); -} - -create_suite( 'Experimental::Sample' ); -run_suite( 'Experimental::Sample' ); diff --git a/perl/third/Test-Unit-0.25/examples/tester.png b/perl/third/Test-Unit-0.25/examples/tester.png deleted file mode 100644 index 5bda5eccdd352aa75bc221dae81461c05809a7ab..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 53974 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

{G z{&@>L)Lb>R->%q9N^q(x>N8)u6lHG9eIsQlL$|^zOmfTtzN6%jrB(dOjoFT*V5tF# zK}JYP^yThs0jWrFQwrW%y^qYbm!;-)PN(QfYn-k~pPQx12da9$cQHF;#NJAK6Nf|0 z;JSjEkxnf!CM%MD)Mklhlmji35>S77x*l7C>6|T+a1J)Vj1-qQbX>qfPtb7by^NYx z9|D;D*2=&NB#~ZNK&Ly10siNULsuVV#MVAEAsx%1U;O;xfl);g?f7E6jN!BqobfJB z&47x_9eP1}5u9TyJb1gKWg+%hM!>LxCo{@_&H<#r*~Wzj?H)Kt|;WrQ%y^{$4uE+Ati4G_CaC@-bI-JEA! zQlg2!HgP>Nel&@(T8}`@NuacOAXlQF1F61M7 zWCIovW?Glpfa2r+m&9kG&(q8uw|YWVyiIK`$68)Ow>{SO&sKM3g3gLF9^l&8{WpD2 zt_7*fU;6*>K$Q{zGgAlO$N}PDaSV^BVX$UudwKfHyzoqJuF&bs@CIom)d!S^1k2)g z!7tVZtn%tdo-+5D&K5i{VoEj>hnon7<8ZofY5eo#qdiC(5LOaKblYTebl-l=b_iFo zEw%s0Q8k#hjQbgZ0C%s}i6fWsJhrF7!R>fM38$SE#W!7XOrIRVOL^Nhq)_~CFFa3W zp;ZhpFpR~swBkr2sW_EfMaw=0P1@!;?~@UIRvCTLzEo#fNj<5$>n6SUmLQ3t@@#^J z>q3Gk4|HZkp^sdD3VhcVcXVC}qPuj|d$Yc{ztduu%8Pb1NyN&>LvFg&ii5;6lgq|f zMJFmM-az_`yH;uS2sB~E)mwo^29s(U&El9&)oO zpOg3xO4j~seVT|_BMFbMdvOml1Nea#`DFxz;sY-=f{ku{OAM81D`VBtqbTDnFK0^~ z5|sU9YVysf=X%<*NSNot%Wfcy?s$g}WTerhIUB`#w%6~^OpgmUAV!^JYpD%|)K1}$ z=c2)Cr!fsq;-&^s+4+6h$>BTYs>jE8eS(;Q{x^rt#jZzu`YTc_i~CVUJcD#cXI|Yf zZRyn_5laGU2i@gmvTCjSOZ0NFByVqT5cuQrFVOtG?CsmL;;j|MjdMqc;XJXN`U0V7u^IE{#W}hz(6|v!%`xM`TR&V<$OI z{ClP$`pZ({upvT3ZUHKi2evv+8jQzEWYCB|t(7cmI;2N)UgPl49OQFijfh}cuw5WJ zRu*?Seq(A8{zq^%G&;q4Rn4NDZq63^^x7pN^6bi{v`Wx#AwT@BZ-(p)5|xBJYY5_R zXa|2KLC~^uFjT_83n)aI6^d8&%k00#7 zrn9_r=;66LW8l2Ak@#u8Exb4boYxW-i6kPh#xx5-Y~MkX03$k56jep{m@nVQ zAM|qtrNTMKZ~>&jaHpiXN|HX$zZ~vzKi^51POy~vF1c}cwJRzGU*XKU(Q_MQ=?-88 z!yDLyVVrddU}3YdB~s)9vzXf*6&mAlK-)!4F zI`q&0)JQrf{B`X&-_7z+A}E9)iBnQxZi}31sz#i*OX`k|~w9PewtEh8fLUjfoTrs}4F@VFb`Vu0rF3Z!9OZSe%<4 z?_?hp&wfG%x!v$jyCz?*y}XovAX(TE@vg(9kVc({S8ygREQyV?G{)*soL0oxkhRQF zY)^^YkA5)`LM?U;0xFL~QO}XGLp^Q`%FP@_+k-|%0C=%Mm#gZkPaCr(MQ6xM%lxNV>dVG0;`{@NtFqN6USM_?x-B5JipgFLeDIJx6ZAJgxU<KtG9U7y_8V5-ph-9O~e@_w!APOIs?8IOBRzS7*JmIBnJ9UE5UJTMZ93myA zu4tOa&?v$T^lU`kqZiBG4UtSOls1=;AzI;z>Hh|QA{$=0HAx*rE;GPiV6 zt8clc4vTlUc1J2JPHH~bg~@`XB{FG_Rd1I91H)jJl@Qe+`XI6lmRiJkgKqCkDUwIW zjCE+*P1soKS&vPidjGA4!gfnG5xt9H&%RnT>+W38F0p@ovlmHvOhrY4-d6j}t&lLb zo-;b!*fHfDE`v;T!eShcwirXvwx5;5nU@&?B|<%^-2+yZWW4uXUXoy$8%;9Alr}9h zMlfj!hpshP{z-Un(d+!5lt8gp0Z*{-uQz&Ydf4^Gw&@|6ak@n?CB`0)e5q2Oqz*zM zP&$#8{N_3p?1Eu3mLw>?!%Dr1Es0Gl0{L1>Yl}gX-{hlCtMLf?ggQ!zC_P4H4(gWx zebh7*7NvG2*fq;iqwwBnc9li{2%C*VZmt=Cpsf{#twUt_J_aeAHMv6_1cSW~N?r4# zMoX6yi|DvCWrE9*Z8}X7+>1Z4VfjhA-WP{+NV(YHY6q?)E7KUy=aLv~pYIoJokh+) z*Aj|z?3S|&&?qiIj{GJSRc4O%;&N9m!S!K7RjQN!-}I)u)sqS3=r8#?dq*r6YeFMR zV*>3VRRL0;xAbr&K=wP^5r?>2$tje^1-zjTdEJs1`(!N}BBFvSlUdKeZ^3u~MmdnI zAgoO~Uh;M{^xO@8Yu`7{6oi{!>qkQcz*}NSOAjBpRd@ZOb zoqU_*ou)5pqX)st$B+WnE?D=SFO7KXdc_^GYXscp47p4e1!%r5r4RffzEfB^DN+e} z&c^5yD&;BkuB25#wDNUVlRi+9x_s9JD3G{1NAy2PS9g+69f0zkNJlcUs}trcEzoI` z5R2;eZ$yD!aP_7kF%}UnUi~?AgTvIuox`YeZAq;h*Tap5Kgo0hl3figR{H~_Ff)~s zmBP+OPFGMA*0&UH<%&-PCzi52r3$}BP=}Q%&J4q3keG^X6`JiHZ)REBdqi$ypNsN+ zr3vYMoZk_X!wjYVR}D@d6Yp9B=D12NT)H}4AXZ&hQ$XntN^~5}KNqZlw@(#DL@3@* zN7_%OpCc+v=b9RsMq@owyqCXMm+sHLeNPz>kg@JMlH23ffIepsbf0z}MfQ6{lWQ@T zP#yG>FZvcA<@QD>C5^0+3#U<6d2K~}L>BpHDbpzMeeDN|GKx{(YnQodCrE>3N%X|L zCom8>|N9xZ8Vyd%M`|dNUGD~TUU)$WKKxxo2Xz`Qr)TBtX5w~F78GOH_?H|zJctFQ zVH?p_0G!dvzm%UVM^xhInu@wv@mS^hQTuvpCuqIl*{RFMeu)1*00RUdd-wJI{{kR8 zUN*s-c_%SBzaIOuvmG-!o9#cC!xMyWCouRNv=90(p?cIc6r91V zp+-_lIMhTDcdO|~<6P3)U(@Lfa99r`uXI(wm@<2W<*hY$xT~`55*U;-T?`zTpe^2< z-WVXtcAfc!!2n<G@rX8@!+a|@$s=P$S6j~lgYg*WQSdEocWz!e;bzOE=NtL#~ z%&9UzjiY$}uNtmxzY14gRLDsB)D~&Y`2|L@y&r~|Q$dR`dVXbQvo0Z-*=V`qPnr0O zw9!iD$DRwUz~=5d2-mR^jhM^20ez206byCr7CTRa9{zeNx8|+AYwnO-CeZgPpkCaQ zj?`XKY(L-g*pp^->TVslidnY?XrHSQ~Jf4~#v^*|BcjM3Zp4SKqx)ZZ*$M@NQ`}6+x2Ev}_F|2uXh{&1%C&AOO9TX&5l=gyiU;vUhBGj%Egnc7ulYm`;L*eAL66ROEbrYYog=HafQO-}CRQm4?PND@_Mw zy=#KkF{V%OXXf;~-klRNB#tq>H;hjwDdA_zQ<>c{d6jY zqeRJ4KjoE_ZQgn@p_SIF&Htqd8>Ge{evMMPr^{ors{Zo5 zXkOk;GpcVEDb&FA@sRqP)ZWCp`_rF%_E$gt{O`T@x7Jm(wh6bD{b*aRleOdF6s;T5 z%e!3DGlI}B^tTq)Zw?8XJ(jEr16aE&cFl`C+Z^2QpGVl`&^Q`+O;QPi&jV1K?7^p~ z9@U@!@TY(BFaPv-eDaeYfBKhy@$(=3@Mr(#&wq-|PAsjFH`a^fS|Q{prFLNHN2m?u zerdqW)TuTo>`@CIKpKCI34(2u)vCJLbf~T4W?@}Smt}F<)~}P)U)VG;t;OvkXDYLP zC`eW_UW&2B%P4R3dgOAJ7M0QveU586+Gvz@vJi^PY;JZiOK;xw_gonJ^+RQ<=yZr8 z>s_$sf_A8ROSXC2>d$iXB*X3!Lx$dt$VGKBb@^X=ixo<=dNk{IC&#D7LC=|_Si z?*;pSK~$k_j#J^Awd_Q+jD-4%vsh`16Yha}LO4E<>Y=zhsOByPmq(*g!Y@Ai;xB&m z^TPpO{_5qIpTGR{(_jANM}J+tdT^*+Ul?c$Bv~e>2kP1|JD|7(Gyl~1)=uE~f?1Vk zl`_Iw5n!7DRIwP6=57huo=8$Ihgt{_K5 z$(-;>>NodIbtF?|EXQ|i|8U{CkT_ge+_7Po4zhmzo0nhz=H=IN6)nGa>;)3)7y{_` zAAwmIs}2|#g+TEA+6aGP3Dt_z#qu?kbBx)IbpcZg{WYEhs`SD}lcN}6ma>&G%TOU@ zbyL{SF~$nPW%}r*Alhqy9vR}MG6q6M>L`%9`4iPi2P0jbScaF0zSp+Yip8!^%IR;E zS5GqX+)}z;itqi(S(ANvuJj4{1g5`Hv6;PtQF5mbyzCl0_e#OkgU|rRY=$7jB zW+PZQv6rg1Tcg03t5V-THqQ>G7|V8Ckj>SqYbWa^mWn>#nQ=vHDJw-j>ho?}gW95^ znm#ZH)aK}dh+IR$SgJBKGSaJ=KRT}lTXE3x+D$++aW)4lGT2bN;3`7O{ zvsDjYUkT8~WVf?0UPQbka%ERB4^QxK|DJc$LEPVHfru-X1I40KP-qeHts)cE$qgdj z(jr+)6x2(zPVDreY8{SiLU_+7jH~zWsoZjkoPet7#oabg1zxApl|Be@rg;;6C_wi1xiJ!vp?I{W!_F0Xr8UY93V*her~GvzJA-lSEOcycmg zR@M0B8ujxWnHKvjOz3YHl=EQUkyT>?%~I}!5&K0<(5-o`4gtW}@}eBnnx7u9?Nqb# z-xio_BwX1BZ&v9%Vd&1!$b(Cb>xNi3V41l)p1NjHxGXw{D~?QM8J|6n3{(o9k-9d3 z%JmOgcNp!>9<(Nc+|||0%(sO$iL?}y_8K|53)Y_gl-$2kF`yJ)@oegGD7#OB()Yts zt4mzo@T#C?-)#%8%9GRD4+Lveo%a;cj*f-4UIVUw2<=KWJ2!`N`W?RhCQtP$%jkhn z1`V#-0A%jIa}yVKd6xj|)xZ_B@W7E+MfOdRA+;%8i)J9+{VT}i7`l(mro+6`upT~j zl|&r`VVPaB1sj#Ncd)Dzhzt&>gz8|0pA~u3X+6v@&F#v^eloX~w`!NSTdcs?_;i;c zChb8j2zM`8Z}%bn|Nit2%Z_EZ^~Fh;Ih7)!i zFOuf{6f-bYx0c?->>!#Vfl}B{yG*ab`neqDA2f;JJvX}cqiC~pxP>W6zp*XOCa^!R zj7X@ejc=C=x#ju7;e4prIM`G${gR}<4q1grGhf#Y#BX#dDQr`OUFy`nhXvOi2r+Fy z>i1;qblgXM7z|8g+phP7etx_vhu7L2bMz)EZ_~Brr!W(ntj_ZLP9^zD4n@ax9tJ z-?`LqN9>K{XjM^WWwl*8|IQ&KAsBeuEY+5pDm-|_tm9JZYqXzn_IAPA-$)Py@E?zL zRb>|`UZ0!(;>RlZfdht#`;{=>OLt%?>Ua~w&Uyrg!h?Ry8KO_EDJ3*z6|c(SBmzS? zT=tE$uBA4c9y&nx-Dk(m>n0OR`=nmd4R8Q|_w@QIj=BGn^<1`3JT2wfG`)fA^ufw_ zWQYM_RD^3*n+(QaOfwpuj8d(WL=;Og*a!sPNw^XHy$&k%7Eme;UbqNKYf}wpMi~O2wJaq&27=BcYk3T4=YFK91s)I@aR=P~vt)m9Efus#IR=+CD>9T5eTjO7V5d-t z2D{PziZf9dJF6K{36mc!!L;XklZ`Cq(-{z!RP>;0Y+}Z4r^jyg>$*el#QdY2xPaDp z^+rKwL7}H2Dh~jS0vxDFg2SsSN?$o9FbFe2e`OfgznXhF-3}lq^v@V>wK)k|ktDXv)k9K{M z!$3VB)7%*F1haw-kuP)?keXehQz+LM)9`ZfnrC9;X5dFQOp)U>^Kb6E3<%4xgpaI; zjbL8+RXi>*O+KK}8LcS3WsBG45MP^UxLg`nEseFqwozEzd>KmNSZ{r?y>a>me|u1r z!l_6wH%AiJlqH}lvci%XiWouYHPTl2us(~5Fet9h8d?ikLM3&4i-3iUtkiv+`}&*` zQG11z?nWyd!L(&9u>(U#Q)%Ln3$uUAiBZT2%(ilHMEe>*rPORiw?G)I00NIZeeHIn zier>zP;L{5Ufs<|WH|QFl_iw1PJ>Q#uDQw!LR-`aTDgYWxWpn0BRK+Pt7BnAhKBA3 zX1G~n9)b%{xaLIH84JO)S$QSn^XmCmkj!GQ(XXL and L. (There -will also eventually be a tutorial in -L. - -However C is the procedural style -interface to a sophisticated unit testing framework for Perl -that . Test::Unit is intended to provide a simpler -interface to the framework that is more suitable for use in a -scripting style environment. Therefore, Test::Unit does not -provide much support for an object-oriented approach to unit -testing. - -=head1 COPYRIGHT - -Copyright (c) 2000-2002, 2005 the PerlUnit Development Team -(see the F file included in this distribution). - -All rights reserved. This program is free software; you can -redistribute it and/or modify it under the same terms as Perl itself. - -That is, under the terms of either of: - -=over 4 - -=item * - -The GNU General Public License as published by the Free Software -Foundation; either version 1, or (at your option) any later version. - -The text of version 2 is included in the PerlUnit distribution package -as F. - -=item * - -The "Artistic License" which comes with Perl. - -The text of this is included in the PerlUnit distribution package as -F. - -=back - -=head1 SEE ALSO - -=over 4 - -=item * - -L - -=item * - -L - -=item * - -L - -=back - -=head1 FEEDBACK - -The Perl Unit development team are humans. In part we develop stuff -because it scratches our collective itch but we'd also really like to -know if it scratches yours. - -Please subscribe to the perlunit-users mailing list at -L and let -us know what you love and hate about PerlUnit and what else you want -to do with it. - -=cut - -package Test::Unit; - -use strict; -use vars qw($VERSION); - -# NOTE: this version number has to be kept in sync with the -# number in the distribution file name (the distribution file -# is the tarball for CPAN release) because the CPAN module -# decides to fetch the tarball by looking at the version of -# this module if you say "install Test::Unit" in the CPAN -# shell. "make tardist" should do this automatically. - -BEGIN { - $VERSION = '0.25'; -} - -# Constants for notices displayed to the user: - -use constant COPYRIGHT_SHORT => < <<'END_COPYRIGHT_NOTICE'; -This is PerlUnit version $Test::Unit::VERSION. -Copyright (C) 2000-2002, 2005 Christian Lemburg, Brian Ewins, et. al. - - -PerlUnit is a Unit Testing framework based on JUnit. -See http://c2.com/cgi/wiki?TestingFrameworks - -PerlUnit is free software, redistributable under the -same terms as Perl. -END_COPYRIGHT_NOTICE - - -1; -__END__ diff --git a/perl/third/Test-Unit-0.25/lib/Test/Unit/Assert.pm b/perl/third/Test-Unit-0.25/lib/Test/Unit/Assert.pm deleted file mode 100644 index 5d5cde0..0000000 --- a/perl/third/Test-Unit-0.25/lib/Test/Unit/Assert.pm +++ /dev/null @@ -1,726 +0,0 @@ -package Test::Unit::Assert; - - -use strict; - -use Test::Unit::Debug qw(debug); -use Test::Unit::Failure; -use Test::Unit::Error; -use Test::Unit::Exception; - -use Test::Unit::Assertion::CodeRef; - -use Error qw/:try/; -use Carp; - -sub assert { - my $self = shift; - my $assertion = $self->normalize_assertion(shift); - $self->do_assertion($assertion, (caller($Error::Depth))[0 .. 2], @_); -} - -sub normalize_assertion { - my $self = shift; - my $assertion = shift; - - if (!ref($assertion) || ref($assertion) =~ 'ARRAY') { - debug((defined $assertion ? $assertion : '_undef_') . - " normalized as boolean\n"); - require Test::Unit::Assertion::Boolean; - return Test::Unit::Assertion::Boolean->new($assertion); - } - - # If we're this far, we must have a reference. - - if (eval {$assertion->isa('Regexp')}) { - debug("$assertion normalized as Regexp\n"); - require Test::Unit::Assertion::Regexp; - return Test::Unit::Assertion::Regexp->new($assertion); - } - - if (ref($assertion) eq 'CODE') { - debug("$assertion normalized as coderef\n"); - require Test::Unit::Assertion::CodeRef; - return Test::Unit::Assertion::CodeRef->new($assertion); - } - -# if (ref($assertion) eq 'SCALAR') { -# debug("$assertion normalized as scalar ref\n"); -# require Test::Unit::Assertion::Scalar; -# return Test::Unit::Assertion::Scalar->new($assertion); -# } - - if (ref($assertion) !~ /^(GLOB|LVALUE|REF|SCALAR)$/) { - debug("$assertion already an object\n"); - require Test::Unit::Assertion::Boolean; - return $assertion->can('do_assertion') ? $assertion : - Test::Unit::Assertion::Boolean->new($assertion); - } - else { - die "Don't know how to normalize $assertion (ref ", ref($assertion), ")\n"; - } -} - -sub assert_raises { - my $self = shift; - require Test::Unit::Assertion::Exception; - my $assertion = Test::Unit::Assertion::Exception->new(shift); - my ($asserter, $file, $line) = caller($Error::Depth); - my $exception = - $self->do_assertion($assertion, (caller($Error::Depth))[0 .. 2], @_); -} - -sub do_assertion { - my $self = shift; - my $assertion = shift; - my $asserter = shift; - my $file = shift; - my $line = shift; - debug("Asserting [$assertion] from $asserter in $file line $line\n"); - my @args = @_; - try { $assertion->do_assertion(@args) } - catch Test::Unit::Exception with { - my $e = shift; - debug(" Caught $e, rethrowing from $asserter, $file line $line\n"); - $e->throw_new(-package => $asserter, - -file => $file, - -line => $line, - -object => $self); - } -} - -sub multi_assert { - my $self = shift; - my ($assertion, @argsets) = @_; - my ($asserter, $file, $line) = caller($Error::Depth); - foreach my $argset (@argsets) { - try { - $self->assert($assertion, @$argset); - } - catch Test::Unit::Exception with { - my $e = shift; - debug(" Caught $e, rethrowing from $asserter, $file line $line\n"); - $e->throw_new(-package => $asserter, - -file => $file, - -line => $line, - -object => $self); - } - } -} - -sub is_numeric { - my $str = shift; - local $^W; - return defined $str && ! ($str == 0 && $str !~ /^\s*[+-]?0(e0)?\s*$/i); -} - -# First argument determines the comparison type. -sub assert_equals { - my $self = shift; - my($asserter, $file, $line) = caller($Error::Depth); - my @args = @_; - try { - if (! defined($args[0]) and ! defined($args[1])) { - # pass - } - elsif (defined($args[0]) xor defined($args[1])) { - $self->fail('one arg was not defined'); - } - elsif (is_numeric($args[0])) { - $self->assert_num_equals(@args); - } - elsif (eval {ref($args[0]) && $args[0]->isa('UNIVERSAL')}) { - require overload; - if (overload::Method($args[0], '==')) { - $self->assert_num_equals(@args); - } - else { - $self->assert_str_equals(@args); - } - } - else { - $self->assert_str_equals(@args); - } - } - catch Test::Unit::Exception with { - my $e = shift; - $e->throw_new(-package => $asserter, - -file => $file, - -line => $line, - -object => $self); - } -} - -sub ok { # To make porting from Test easier - my $self = shift; - my @args = @_; - local $Error::Depth = $Error::Depth + 1; - if (@args == 1) { - $self->assert($args[0]); # boolean assertion - } - elsif (@args >= 2 && @args <= 3) { - if (ref($args[0]) eq 'CODE') { - my $code = shift @args; - my $expected = shift @args; - $self->assert_equals($expected, $code->(), @args); - } - elsif (eval {$args[1]->isa('Regexp')}) { - my $got = shift @args; - my $re = shift @args; - $self->assert($re, $got, @args); - } - else { - my $got = shift @args; - my $expected = shift @args; - $self->assert_equals($expected, $got, @args); - } - } - else { - $self->error('ok() called with wrong number of args'); - } -} - -sub assert_not_equals { - my $self = shift; - my($asserter,$file,$line) = caller($Error::Depth); - my @args = @_; - try { - if (! defined($args[0]) && ! defined($args[1])) { - my $first = shift @args; - my $second = shift @args; - $self->fail(@args ? join('', @args) : 'both args were undefined'); - } - elsif (defined($args[0]) xor defined($args[1])) { - # succeed - } - elsif (is_numeric($args[0])) { - $self->assert_num_not_equals(@args); - } - elsif (eval {ref($args[0]) && $args[0]->isa('UNIVERSAL')}) { - require overload; - if (overload::Method($args[0], '==')) { - $self->assert_num_not_equals(@args); - } - else { - $self->assert_str_not_equals(@args); - } - } - else { - $self->assert_str_not_equals(@args); - } - } - catch Test::Unit::Exception with { - my $e = shift; - $e->throw_new(-package => $asserter, - -file => $file, - -line => $line, - -object => $self,); - }; -} - -# Shamelessly pinched from Test::More and adapted to Test::Unit. -our %Seen_Refs = (); -our @Data_Stack; -my $DNE = bless [], 'Does::Not::Exist'; -sub assert_deep_equals { - my $self = shift; - my $this = shift; - my $that = shift; - - local $Error::Depth = $Error::Depth + 1; - - if (! ref $this || ! ref $that) { - Test::Unit::Failure->throw( - -text => @_ ? join('', @_) - : 'Both arguments were not references' - ); - } - - local @Data_Stack = (); - local %Seen_Refs = (); - if (! $self->_deep_check($this, $that)) { - Test::Unit::Failure->throw( - -text => @_ ? join('', @_) - : $self->_format_stack(@Data_Stack) - ); - } -} - -sub _deep_check { - my $self = shift; - my ($e1, $e2) = @_; - - if ( ! defined $e1 || ! defined $e2 ) { - return 1 if !defined $e1 && !defined $e2; - push @Data_Stack, { vals => [$e1, $e2] }; - return 0; - } - - return 0 if ( (defined $e1 && $e1 eq $DNE) - || (defined $e2 && $e2 eq $DNE )); - - return 1 if $e1 eq $e2; - if ( ref $e1 && ref $e2 ) { - my $e2_ref = "$e2"; - return 1 if defined $Seen_Refs{$e1} && $Seen_Refs{$e1} eq $e2_ref; - $Seen_Refs{$e1} = $e2_ref; - } - - if (UNIVERSAL::isa($e1, 'ARRAY') and UNIVERSAL::isa($e2, 'ARRAY')) { - return $self->_eq_array($e1, $e2); - } - elsif (UNIVERSAL::isa($e1, 'HASH') and UNIVERSAL::isa($e2, 'HASH')) { - return $self->_eq_hash($e1, $e2); - } - elsif (UNIVERSAL::isa($e1, 'REF') and UNIVERSAL::isa($e2, 'REF')) { - push @Data_Stack, { type => 'REF', vals => [$e1, $e2] }; - my $ok = $self->_deep_check($$e1, $$e2); - pop @Data_Stack if $ok; - return $ok; - } - elsif (UNIVERSAL::isa($e1, 'SCALAR') and UNIVERSAL::isa($e2, 'SCALAR')) { - push @Data_Stack, { type => 'REF', vals => [$e1, $e2] }; - return $self->_deep_check($$e1, $$e2); - } - else { - push @Data_Stack, { vals => [$e1, $e2] }; - return 0; - } -} - -sub _eq_array { - my $self = shift; - my($a1, $a2) = @_; - return 1 if $a1 eq $a2; - - my $ok = 1; - my $max = $#$a1 > $#$a2 ? $#$a1 : $#$a2; - for (0..$max) { - my $e1 = $_ > $#$a1 ? $DNE : $a1->[$_]; - my $e2 = $_ > $#$a2 ? $DNE : $a2->[$_]; - - push @Data_Stack, { type => 'ARRAY', idx => $_, vals => [$e1, $e2] }; - $ok = $self->_deep_check($e1,$e2); - pop @Data_Stack if $ok; - - last unless $ok; - } - return $ok; -} - -sub _eq_hash { - my $self = shift; - my($a1, $a2) = @_; - return 1 if $a1 eq $a2; - - my $ok = 1; - my $bigger = keys %$a1 > keys %$a2 ? $a1 : $a2; - foreach my $k (keys %$bigger) { - my $e1 = exists $a1->{$k} ? $a1->{$k} : $DNE; - my $e2 = exists $a2->{$k} ? $a2->{$k} : $DNE; - - push @Data_Stack, { type => 'HASH', idx => $k, vals => [$e1, $e2] }; - $ok = $self->_deep_check($e1, $e2); - pop @Data_Stack if $ok; - - last unless $ok; - } - - return $ok; -} - -sub _format_stack { - my $self = shift; - my @Stack = @_; - - my $var = '$FOO'; - my $did_arrow = 0; - foreach my $entry (@Stack) { - my $type = $entry->{type} || ''; - my $idx = $entry->{'idx'}; - if( $type eq 'HASH' ) { - $var .= "->" unless $did_arrow++; - $var .= "{$idx}"; - } - elsif( $type eq 'ARRAY' ) { - $var .= "->" unless $did_arrow++; - $var .= "[$idx]"; - } - elsif( $type eq 'REF' ) { - $var = "\${$var}"; - } - } - - my @vals = @{$Stack[-1]{vals}}[0,1]; - - my @vars = (); - ($vars[0] = $var) =~ s/\$FOO/ \$a/; - ($vars[1] = $var) =~ s/\$FOO/ \$b/; - - my $out = "Structures begin differing at:\n"; - foreach my $idx (0..$#vals) { - my $val = $vals[$idx]; - $vals[$idx] = !defined $val ? 'undef' : - $val eq $DNE ? "Does not exist" - : "'$val'"; - } - - $out .= "$vars[0] = $vals[0]\n"; - $out .= "$vars[1] = $vals[1]\n"; - - return $out; -} - -{ - my %assert_subs = ( - str_equals => sub { - my $str1 = shift; - my $str2 = shift; - defined $str1 or - Test::Unit::Failure->throw( - -text => @_ ? join('',@_) : - "expected value was undef; should be using assert_null?" - ); - defined $str2 or - Test::Unit::Failure->throw( - -text => @_ ? join('',@_) : "expected '$str1', got undef" - ); - $str1 eq $str2 or - Test::Unit::Failure->throw( - -text => @_ ? join('',@_) : "expected '$str1', got '$str2'" - ); - }, - str_not_equals => sub { - my $str1 = shift; - my $str2 = shift; - defined $str1 or - Test::Unit::Failure->throw( - -text => @_ ? join('',@_) : - "expected value was undef; should be using assert_not_null?" - ); - defined $str2 or - Test::Unit::Failure->throw( - -text => @_ ? join('',@_) : - "expected a string ne '$str1', got undef" - ); - $str1 ne $str2 or - Test::Unit::Failure->throw( - -text => @_ ? join('',@_) : "'$str1' and '$str2' should differ" - ); - }, - num_equals => sub { - my $num1 = shift; - my $num2 = shift; - defined $num1 or - Test::Unit::Failure->throw( - -text => @_ ? join('',@_) : - "expected value was undef; should be using assert_null?" - ); - defined $num2 or - Test::Unit::Failure->throw( - -text => @_ ? join('',@_) : "expected '$num1', got undef" - ); - # silence `Argument "" isn't numeric in numeric eq (==)' warnings - local $^W; - $num1 == $num2 or - Test::Unit::Failure->throw( - -text => @_ ? join('', @_) : "expected $num1, got $num2" - ); - }, - num_not_equals => sub { - my $num1 = shift; - my $num2 = shift; - defined $num1 or - Test::Unit::Failure->throw( - -text => @_ ? join('',@_) : - "expected value was undef; should be using assert_not_null?" - ); - defined $num2 or - Test::Unit::Failure->throw( - -text => @_ ? join('',@_) : - "expected a number != '$num1', got undef" - ); - # silence `Argument "" isn't numeric in numeric ne (!=)' warnings - local $^W; - $num1 != $num2 or - Test::Unit::Failure->throw( - -text => @_ ? join('', @_) : "$num1 and $num2 should differ" - ); - }, - matches => sub { - my $regexp = shift; - eval { $regexp->isa('Regexp') } or - Test::Unit::Error->throw( - -text => "arg 1 to assert_matches() must be a regexp" - ); - my $string = shift; - $string =~ $regexp or - Test::Unit::Failure->throw - (-text => @_ ? join('', @_) : - "$string didn't match /$regexp/"); - }, - does_not_match => sub { - my $regexp = shift; - eval { $regexp->isa('Regexp') } or - Test::Unit::Error->throw( - -text => "arg 1 to assert_does_not_match() must be a regexp" - ); - my $string = shift; - $string !~ $regexp or - Test::Unit::Failure->throw - (-text => @_ ? join('', @_) : - "$string matched /$regexp/"); - }, - null => sub { - my $arg = shift; - !defined($arg) or - Test::Unit::Failure->throw - (-text => @_ ? join('',@_) : "$arg is defined"); - }, - not_null => sub { - my $arg = shift; - defined($arg) or - Test::Unit::Failure->throw - (-text => @_ ? join('', @_) : " unexpected"); - }, - ); - foreach my $type (keys %assert_subs) { - my $assertion = Test::Unit::Assertion::CodeRef->new($assert_subs{$type}); - no strict 'refs'; - *{"Test::Unit::Assert::assert_$type"} = - sub { - local $Error::Depth = $Error::Depth + 3; - my $self = shift; - $assertion->do_assertion(@_); - }; - } -} - -sub fail { - my $self = shift; - debug(ref($self) . "::fail() called\n"); - my($asserter,$file,$line) = caller($Error::Depth); - my $message = join '', @_; - Test::Unit::Failure->throw(-text => $message, - -object => $self, - -file => $file, - -line => $line); -} - -sub error { - my $self = shift; - debug(ref($self) . "::error() called\n"); - my($asserter,$file,$line) = caller($Error::Depth); - my $message = join '', @_; - Test::Unit::Error->throw(-text => $message, - -object => $self, - -file => $file, - -line => $line); -} - -sub quell_backtrace { - my $self = shift; - carp "quell_backtrace deprecated"; -} - -sub get_backtrace_on_fail { - my $self = shift; - carp "get_backtrace_on_fail deprecated"; -} - - - -1; -__END__ - -=head1 NAME - -Test::Unit::Assert - unit testing framework assertion class - -=head1 SYNOPSIS - - # this class is not intended to be used directly, - # normally you get the functionality by subclassing from - # Test::Unit::TestCase - - use Test::Unit::TestCase; - - # more code here ... - - $self->assert($your_condition_here, $your_optional_message_here); - - # or, for regular expression comparisons: - $self->assert(qr/some_pattern/, $result); - - # or, for functional style coderef tests: - $self->assert(sub { - $_[0] == $_[1] - or $self->fail("Expected $_[0], got $_[1]"); - }, 1, 2); - - # or, for old style regular expression comparisons - # (strongly deprecated; see warning below) - $self->assert(scalar("foo" =~ /bar/), $your_optional_message_here); - - # Or, if you don't mind us guessing - $self->assert_equals('expected', $actual [, $optional_message]); - $self->assert_equals(1,$actual); - $self->assert_not_equals('not expected', $actual [, $optional_message]); - $self->assert_not_equals(0,1); - - # Or, if you want to force the comparator - $self->assert_num_equals(1,1); - $self->assert_num_not_equals(1,0); - $self->assert_str_equals('string','string'); - $self->assert_str_not_equals('stringA', 'stringB'); - - # assert defined/undefined status - $self->assert_null(undef); - $self->assert_not_null(''); - -=head1 DESCRIPTION - -This class contains the various standard assertions used within the -framework. With the exception of the C, all -the assertion methods take an optional message after the mandatory -fields. The message can either be a single string, or a list, which -will get concatenated. - -Although you can specify a message, it is hoped that the default error -messages generated when an assertion fails will be good enough for -most cases. - -=head2 Methods - -=over 4 - -=item assert_equals(EXPECTED, ACTUAL [, MESSAGE]) - -=item assert_not_equals(NOTEXPECTED, ACTUAL [, MESSAGE]) - -The catch all assertions of (in)equality. We make a guess about -whether to test for numeric or string (in)equality based on the first -argument. If it looks like a number then we do a numeric test, if it -looks like a string, we do a string test. - -If the first argument is an object, we check to see if the C<'=='> -operator has been overloaded and use that if it has, otherwise we do -the string test. - -=item assert_num_equals - -=item assert_num_not_equals - -Force numeric comparison with these two. - -=item assert_str_equals - -=item assert_str_not_equals - -Force string comparison - -=item assert_matches(qr/PATTERN/, STRING [, MESSAGE]) - -=item assert_does_not_match(qr/PATTERN/, STRING [, MESSAGE]) - -Assert that STRING does or does not match the PATTERN regex. - -=item assert_deep_equals(A, B [, MESSAGE ]) - -Assert that reference A is a deep copy of reference B. The references -can be complex, deep structures. If they are different, the default -message will display the place where they start differing. - -B This is NOT well-tested on circular references. Nor am I -quite sure what will happen with filehandles. - -=item assert_null(ARG [, MESSAGE]) - -=item assert_not_null(ARG [, MESSAGE]) - -Assert that ARG is defined or not defined. - -=item assert(BOOLEAN [, MESSAGE]) - -Checks if the BOOLEAN expression returns a true value that is neither -a CODE ref nor a REGEXP. Note that MESSAGE is almost non optional in -this case, otherwise all the assertion has to go on is the truth or -otherwise of the boolean. - -If you want to use the "old" style for testing regular expression -matching, please be aware of this: the arguments to assert() are -evaluated in list context, e.g. making a failing regex "pull" the -message into the place of the first argument. Since this is usually -just plain wrong, please use scalar() to force the regex comparison -to yield a useful boolean value. - -=item assert(qr/PATTERN/, ACTUAL [, MESSAGE]) - -Matches ACTUAL against the PATTERN regex. If you omit MESSAGE, you -should get a sensible error message. - -=item assert(CODEREF, @ARGS) - -Calls CODEREF->(@ARGS). Assertion fails if this returns false (or -throws Test::Unit::Failure) - -=item assert_raises(EXCEPTION_CLASS, CODEREF [, MESSAGE]) - -Calls CODEREF->(). Assertion fails unless an exception of class -EXCEPTION_CLASS is raised. - -=item multi_assert(ASSERTION, @ARGSETS) - -Calls $self->assert(ASSERTION, @$ARGSET) for each $ARGSET in @ARGSETS. - -=item ok(@ARGS) - -Simulates the behaviour of the L module. B - -=back - -=head1 AUTHOR - -Copyright (c) 2000-2002, 2005 the PerlUnit Development Team -(see L or the F file included in this -distribution). - -All rights reserved. This program is free software; you can -redistribute it and/or modify it under the same terms as Perl itself. - -=head1 SEE ALSO - -=over 4 - -=item * - -L - -=item * - -L - -=item * - -L - -=item * - -L - -=item * - -L - -=item * - -L - -=item * - -The framework self-testing suite -(L) - -=back - -=cut diff --git a/perl/third/Test-Unit-0.25/lib/Test/Unit/Assertion.pm b/perl/third/Test-Unit-0.25/lib/Test/Unit/Assertion.pm deleted file mode 100644 index 948a6e6..0000000 --- a/perl/third/Test-Unit-0.25/lib/Test/Unit/Assertion.pm +++ /dev/null @@ -1,92 +0,0 @@ -package Test::Unit::Assertion; - -use strict; - -use Carp; -use Test::Unit::Failure; - -use overload '""' => 'to_string'; - -sub fail { - my $self = shift; - my($asserter, $file, $line) = caller(2); # We're always called from - # within an Assertion... - Test::Unit::Failure->throw(-object => $self, - -file => $file, - -line => $line, - -text => join '', @_); -} - -sub do_assertion { - Carp::croak("$_[0] forgot to override do_assertion"); -} - -sub new { - Carp::croak("$_[0] forgot to override new"); -} - -1; - -__END__ - -=head1 NAME - -Test::Unit::Assertion - The abstract base class for assertions - -=head1 NAME - -Any assertion class that expects to plug into Test::Unit::Assert needs -to implement this interface. - -=head2 Required methods - -=over 4 - -=item new - -Creates a new assertion object. Takes whatever arguments you desire. -Isn't strictly necessary for the framework to work with this class but -is generally considered a good idea. - -=item do_assertion - -This is the important one. If Test::Unit::Assert::assert is called -with an object as its first argument then it does: - - $_[0]->do_assertion(@_[1 .. $#_]) || - $self->fail("Assertion failed"); - -This means that C should return true if the assertion -succeeds and false if it doesn't. Or, you can fail by throwing a -Test::Unit::Failure object, which will get caught further up -the stack and used to produce a sensible error report. Generally it's -good practice for do_assertion to die with a meaningful error on -assertion failure rather than just returning false. - -=back - - -=head1 AUTHOR - -Copyright (c) 2001 Piers Cawley Epdcawley@iterative-software.comE. - -All rights reserved. This program is free software; you can -redistribute it and/or modify it under the same terms as Perl itself. - -=head1 SEE ALSO - -=over 4 - -=item * - -L - -=item * - -L - -=item * - -L - -=back diff --git a/perl/third/Test-Unit-0.25/lib/Test/Unit/Assertion/Boolean.pm b/perl/third/Test-Unit-0.25/lib/Test/Unit/Assertion/Boolean.pm deleted file mode 100644 index 773645b..0000000 --- a/perl/third/Test-Unit-0.25/lib/Test/Unit/Assertion/Boolean.pm +++ /dev/null @@ -1,63 +0,0 @@ -package Test::Unit::Assertion::Boolean; - -use strict; - -# adding this fixes the 'Can't locate object method "fail" via package -# "Test::Unit::Assertion::Boolean"' problem under perl 5.005 - Christian -use Test::Unit::Assertion; -use Test::Unit::Failure; - - -use base 'Test::Unit::Assertion'; - -use overload 'bool' => sub {$ {$_[0]}}; - -sub new { - my $class = shift; - my $bool = shift; - - my $self = \$bool; - bless $self, $class; -} - -sub do_assertion { - my $self = shift; - $$self or $self->fail( @_ ? join('', @_) : "Boolean assertion failed"); -} - -sub to_string { - my $self = shift; - ($$self ? 'TRUE' : 'FALSE') . ' boolean assertion'; -} - -1; - -__END__ - -=head1 NAME - -Test::Unit::Assertion::Boolean - A boolean assertion - -=head1 SYNOPSIS - -Pay no attention to the man behind the curtain. This is simply a -boolean assertion that exists solely to rationalize the way -Test::Unit::Assert::assert does its thing. You should never have to -instantiate one of these directly. Ever. Go away. There's nothing to -see here. - - -=head1 AUTHOR - -Copyright (c) 2001 Piers Cawley Epdcawley@iterative-software.comE. - -All rights reserved. This program is free software; you can -redistribute it and/or modify it under the same terms as Perl itself. - -=head1 SEE ALSO - -Look, I've told you, there's nothing going on here. If you go looking -at the listing of this module you'll see that it does almost nothing. -Why on earth you're still reading at this point is something of a -mystery to me. After all, if you're hacking on the Test::Unit source -code you'll be able to use the Source. diff --git a/perl/third/Test-Unit-0.25/lib/Test/Unit/Assertion/CodeRef.pm b/perl/third/Test-Unit-0.25/lib/Test/Unit/Assertion/CodeRef.pm deleted file mode 100644 index e871f04..0000000 --- a/perl/third/Test-Unit-0.25/lib/Test/Unit/Assertion/CodeRef.pm +++ /dev/null @@ -1,125 +0,0 @@ -package Test::Unit::Assertion::CodeRef; - -use strict; -use base qw/Test::Unit::Assertion/; - -use Carp; -use Test::Unit::Debug qw(debug); - -my $deparser; - -sub new { - my $class = shift; - my $code = shift; - croak "$class\::new needs a CODEREF" unless ref($code) eq 'CODE'; - bless \$code => $class; -} - -sub do_assertion { - my $self = shift; - my $possible_object = $_[0]; - debug("Called do_assertion(" . ($possible_object || 'undef') . ")\n"); - if (ref($possible_object) and - ref($possible_object) ne 'Regexp' and - eval { $possible_object->isa('UNIVERSAL') }) - { - debug(" [$possible_object] isa [" . ref($possible_object) . "]\n"); - $possible_object->$$self(@_[1..$#_]); - } - else { - debug(" asserting [$self]" - . (@_ ? " on args " . join(', ', map { $_ || '' } @_) : '') - . "\n"); - $$self->(@_); - } -} - -sub to_string { - my $self = shift; - if (eval "require B::Deparse") { - $deparser ||= B::Deparse->new("-p"); - return join '', "sub ", $deparser->coderef2text($$self); - } - else { - return "sub { - # If you had a working B::Deparse, you'd know what was in - # this subroutine. -}"; - } -} - -1; -__END__ - -=head1 NAME - -Test::Unit::Assertion::CodeRef - A delayed evaluation assertion using a Coderef - -=head1 SYNOPSIS - - require Test::Unit::Assertion::CodeRef; - - my $assert_eq = - Test::Unit::Assertion::CodeRef->new(sub { - $_[0] eq $_[1] - or Test::Unit::Failure->throw(-text => - "Expected '$_[0]', got '$_[1]'\n"); - }); - - $assert_eq->do_assertion('foo', 'bar'); - -Although this is how you'd use Test::Unit::Assertion::CodeRef -directly, it is more usually used indirectly via -Test::Unit::Test::assert, which instantiates a -Test::Unit::Assertion::CodeRef when passed a Coderef as its first -argument. - -=head1 IMPLEMENTS - -Test::Unit::Assertion::CodeRef implements the Test::Unit::Assertion -interface, which means it can be plugged into the Test::Unit::TestCase -and friends' C method with no ill effects. - -=head1 DESCRIPTION - -This class is used by the framework to allow us to do assertions in a -'functional' manner. It is typically used generated automagically in -code like: - - $self->assert(sub { - $_[0] == $_[1] - or $self->fail("Expected $_[0], got $_[1]"); - }, 1, 2); - -(Note that if Damian Conway's Perl6 RFC for currying ever comes to -pass then we'll be able to do this as: - - $self->assert(^1 == ^2 || $self->fail("Expected ^1, got ^2"), 1, 2) - -which will be nice...) - -If you have a working B::Deparse installed with your perl installation -then, if an assertion fails, you'll see a listing of the decompiled -coderef (which will be sadly devoid of comments, but should still be -useful) - -=head1 AUTHOR - -Copyright (c) 2001 Piers Cawley Epdcawley@iterative-software.comE. - -All rights reserved. This program is free software; you can -redistribute it and/or modify it under the same terms as Perl itself. - -=head1 SEE ALSO - -=over 4 - -=item * - -L - -=item * - -L - -=back diff --git a/perl/third/Test-Unit-0.25/lib/Test/Unit/Assertion/Exception.pm b/perl/third/Test-Unit-0.25/lib/Test/Unit/Assertion/Exception.pm deleted file mode 100644 index 86d857f..0000000 --- a/perl/third/Test-Unit-0.25/lib/Test/Unit/Assertion/Exception.pm +++ /dev/null @@ -1,90 +0,0 @@ -package Test::Unit::Assertion::Exception; - -use strict; -use base qw/Test::Unit::Assertion/; - -use Carp; -use Error qw/:try/; -use Test::Unit::Debug qw(debug); - -my $deparser; - -sub new { - my $class = shift; - my $exception_class = shift; - croak "$class\::new needs an exception class" unless $exception_class; - bless \$exception_class => $class; -} - -sub do_assertion { - my $self = shift; - my $coderef = shift; - my $exception_class = $$self; - - my $exception; - try { - &$coderef(); - } - catch $exception_class with { - $exception = shift; - }; - - if (! $exception || ! $exception->isa($$self)) { - $self->fail(@_ ? $_[0] : "No $exception_class was raised"); - } - return $exception; # so that it can be stored in the test for the - # user to get at. -} - -sub to_string { - my $self = shift; - return "$$self exception assertion"; -} - -1; -__END__ - -=head1 NAME - -Test::Unit::Assertion::Exception - A assertion for raised exceptions - -=head1 SYNOPSIS - - require Test::Unit::Assertion::Exception; - - my $assert_raised = - Test::Unit::Assertion::Exception->new('MyException'); - - # This should succeed - $assert_eq->do_assertion(sub { MyException->throw() }); - - # This should fail - $assert_eq->do_assertion(sub { }); - -=head1 DESCRIPTION - -Although the SYNOPSIS shows how you'd use -Test::Unit::Assertion::Exception directly, it is more sensibly used -indirectly via C, which -instantiates a C. - -=head1 AUTHOR - -Copyright (c) 2001 Piers Cawley Epdcawley@iterative-software.comE. - -All rights reserved. This program is free software; you can -redistribute it and/or modify it under the same terms as Perl itself. - -=head1 SEE ALSO - -=over 4 - -=item * - -L - -=item * - -L - -=back diff --git a/perl/third/Test-Unit-0.25/lib/Test/Unit/Assertion/Regexp.pm b/perl/third/Test-Unit-0.25/lib/Test/Unit/Assertion/Regexp.pm deleted file mode 100644 index c625417..0000000 --- a/perl/third/Test-Unit-0.25/lib/Test/Unit/Assertion/Regexp.pm +++ /dev/null @@ -1,99 +0,0 @@ -package Test::Unit::Assertion::Regexp; - -use strict; -use Test::Unit::Assertion; -use base qw/Test::Unit::Assertion/; - -sub new { - my $class = shift; - my $regex = shift; - - bless \$regex, $class; -} - -sub do_assertion { - my $self = shift; - my $target = shift; - $target =~ $$self or - $self->fail(@_ ? $_[0] : "'$target' did not match /$$self/"); -} - -sub to_string { - my $self = shift; - "/$$self/ regexp assertion"; -} - -1; - -__END__ - -=head1 NAME - -Test::Unit::Assertion::Regexp - Assertion with regex matching - -=head1 SYNOPSIS - - require Test::Unit::Assertion::Regexp; - - my $assert_re = - Test::Unit::Assertion::Regexp->new(qr/a_pattern/); - - $assert_re->do_assertion('a_string'); - -This is rather more detail than the average user will need. -Test::Unit::Assertion::Regexp objects are generated automagically by -Test::Unit::Assert::assert when it is passed a regular expression as -its first parameter. - - sub test_foo { - ... - $self->assert(qr/some_pattern/, $result); - } - -If the assertion fails then the object throws an exception with -details of the pattern and the string it failed to match against. - -Note that if you need to do a 'string does I match this pattern' -type of assertion then you can do: - - $self->assert(qr/(?!some_pattern)/, $some_string) - -ie. Make use of the negative lookahead assertion. - -=head1 IMPLEMENTS - -Test::Unit::Assertion::Regexp implements the Test::Unit::Assertion -interface, which means it can be plugged into the Test::Unit::TestCase -and friends' C method with no ill effects. - -=head1 DESCRIPTION - -The class is used by the framework to provide sensible 'automatic' -reports when a match fails. The old: - - $self->assert(scalar($foo =~ /pattern/), "$foo didn't match /.../"); - -seems rather clumsy compared to this. If the regexp assertion fails, -then the user is given a sensible error message, with the pattern and -the string that failed to match it... - -=head1 AUTHOR - -Copyright (c) 2001 Piers Cawley Epdcawley@iterative-software.comE. - -All rights reserved. This program is free software; you can -redistribute it and/or modify it under the same terms as Perl itself. - -=head1 SEE ALSO - -=over 4 - -=item * - -L - -=item * - -L - -=back diff --git a/perl/third/Test-Unit-0.25/lib/Test/Unit/Debug.pm b/perl/third/Test-Unit-0.25/lib/Test/Unit/Debug.pm deleted file mode 100644 index 4fc94c4..0000000 --- a/perl/third/Test-Unit-0.25/lib/Test/Unit/Debug.pm +++ /dev/null @@ -1,118 +0,0 @@ -package Test::Unit::Debug; - -=head1 NAME - -Test::Unit::Debug - framework debugging control - -=head1 SYNOPSIS - - package MyRunner; - - use Test::Unit::Debug qw(debug_to_file debug_pkg); - - debug_to_file('foo.log'); - debug_pkg('Test::Unit::TestCase'); - -=cut - -use strict; - -use base 'Exporter'; -use vars qw(@EXPORT_OK); -@EXPORT_OK = qw(debug debug_to_file - debug_pkg no_debug_pkg debug_pkgs no_debug_pkgs debugged); - -my %DEBUG = (); -my $out = \*STDERR; - -=head1 ROUTINES - -=head2 debug_to_file($file) - -Switch debugging to C<$file>. - -=cut - -sub debug_to_file { - my ($file) = @_; - open(DEBUG, ">$file") or die "Couldn't open $file for writing"; - $out = \*DEBUG; -} - -=head2 debug_to_stderr() - -Switch debugging to STDERR (this is the default). - -=cut - -sub debug_to_stderr { - $out = \*STDERR; -} - -sub debug { - my ($package, $filename, $line) = caller(); - print $out @_ if $DEBUG{$package}; -} - -=head2 debug_pkg($pkg) - -Enable debugging in package C<$pkg>. - -=cut - -sub debug_pkg { - $DEBUG{$_[0]} = 1; -} - -=head2 debug_pkgs(@pkgs) - -Enable debugging in the packages C<@pkgs>. - -=cut - -sub debug_pkgs { - $DEBUG{$_} = 1 foreach @_; -} - -=head2 debug_pkg($pkg) - -Enable debugging in package C<$pkg>. - -=cut - -sub no_debug_pkg { - $DEBUG{$_[0]} = 0; -} - -=head2 debug_pkgs(@pkgs) - -Disable debugging in the packages C<@pkgs>. - -=cut - -sub no_debug_pkgs { - $DEBUG{$_} = 0 foreach @_; -} - -sub debugged { - my ($package, $filename, $line) = caller(); - return $DEBUG{$_[0] || $package}; -} - - -=head1 AUTHOR - -Copyright (c) 2000-2002, 2005 the PerlUnit Development Team -(see L or the F file included in this -distribution). - -All rights reserved. This program is free software; you can -redistribute it and/or modify it under the same terms as Perl itself. - -=head1 SEE ALSO - -L - -=cut - -1; diff --git a/perl/third/Test-Unit-0.25/lib/Test/Unit/Decorator.pm b/perl/third/Test-Unit-0.25/lib/Test/Unit/Decorator.pm deleted file mode 100644 index a49fd05..0000000 --- a/perl/third/Test-Unit-0.25/lib/Test/Unit/Decorator.pm +++ /dev/null @@ -1,72 +0,0 @@ -package Test::Unit::Decorator; -use strict; - -use base qw(Test::Unit::Test); - -sub new { - my $class = shift; - my ($fTest) = @_; - return bless { _fTest => $fTest }, $class; -} - -sub basic_run { - my $self = shift; - my ($result) = @_; - $self->{_fTest}->run($result); -} - -sub count_test_cases() { - my $self = shift; - return $self->{_fTest}->count_test_cases(); -} -sub run { - my $self = shift; - my ($result) = @_; - $self->basic_run($result); -} - -sub to_string { - my $self = shift; - "$self->{_fTest}"; -} - -sub get_test { - my $self = shift; - return $self->{_fTest}; -} - -1; -__END__ - - -=head1 NAME - -Test::Unit::Decorator - unit testing framework helper class - -=head1 SYNOPSIS - - # A Decorator for Tests. Use TestDecorator as the base class - # for defining new test decorators. Test decorator subclasses - # can be introduced to add behaviour before or after a test - # is run. - -=head1 DESCRIPTION - -A Decorator for Tests. Use TestDecorator as the base class -for defining new test decorators. Test decorator subclasses -can be introduced to add behaviour before or after a test -is run. - -=head1 AUTHOR - -Copyright (c) 2001 Kevin Connor - -All rights reserved. This program is free software; you can -redistribute it and/or modify it under the same terms as -Perl itself. - -=head1 SEE ALSO - -L - -=cut diff --git a/perl/third/Test-Unit-0.25/lib/Test/Unit/Error.pm b/perl/third/Test-Unit-0.25/lib/Test/Unit/Error.pm deleted file mode 100644 index 0d66152..0000000 --- a/perl/third/Test-Unit-0.25/lib/Test/Unit/Error.pm +++ /dev/null @@ -1,57 +0,0 @@ -package Test::Unit::Error; -use strict; -use base qw(Test::Unit::Exception); - -# This is a hack to effectively rebless an unknown user exception as a -# Test::Unit::Error, which is nice because all Test::Unit::Exceptions -# have nice stringify() methods. -sub make_new_from_error { - my $self = shift; - my $ex = shift; - my $object = shift; - $self->new(%$ex, -object => $object); -} - -1; -__END__ - -=head1 NAME - -Test::Unit::Error - unit testing framework exception class - -=head1 SYNOPSIS - -This class is not intended to be used directly - -=head1 DESCRIPTION - -This class is used by the framework to communicate the occurrence of -run-time errors (that is, syntax errors and the like, not failed -tests, as the latter are classified as failures) generated by user -code. When such an error occurs, an instance of this class will be -thrown and caught internally in the framework. - -=head1 AUTHOR - -Copyright (c) 2000-2002, 2005 the PerlUnit Development Team -(see L or the F file included in this -distribution). - -All rights reserved. This program is free software; you can -redistribute it and/or modify it under the same terms as Perl itself. - -=head1 SEE ALSO - -=over 4 - -=item * - -L - -=item * - -L - -=back - -=cut diff --git a/perl/third/Test-Unit-0.25/lib/Test/Unit/Exception.pm b/perl/third/Test-Unit-0.25/lib/Test/Unit/Exception.pm deleted file mode 100644 index 48ee5d6..0000000 --- a/perl/third/Test-Unit-0.25/lib/Test/Unit/Exception.pm +++ /dev/null @@ -1,103 +0,0 @@ -package Test::Unit::Exception; - -use strict; - -use Carp; -use Error; - -use base 'Error'; - -sub throw_new { - my $self = shift; - my $class = ref $self; - $class->throw(%{$self || {}},@_); -} - -sub stacktrace { - my $self = shift; - warn "Stacktrace is deprecated and no longer works" -} - -sub get_message { - my $self = shift; - $self->text; -} - -sub hide_backtrace { - my $self = shift; - $self->{_hide_backtrace} = 1; -} - -sub stringify { - my $self = shift; - my $file = $self->file; - my $line = $self->line; - my $message = $self->text || 'Died'; - my $object = $self->object; - - my $str = "$file:$line"; - $str .= ' - ' . $object->to_string() if $object && $object->can('to_string'); - $str .= "\n" . $message; - return $str; -} - -sub to_string { - my $self = shift; - $self->stringify; -} - -sub failed_test { - carp "Test::Unit::Exception::failed_test called"; - return $_[0]->object; -} - -sub thrown_exception { - carp "Test::Unit::Exception::thrown_exception called"; - return $_[0]->object; -} - -1; -__END__ - -=head1 NAME - -Test::Unit::Exception - unit testing framework exception class - -=head1 SYNOPSIS - -This class is not intended to be used directly - -=head1 DESCRIPTION - -This class is used by the framework to communicate the result of -assertions, which will throw an instance of a subclass of this class -in case of errors or failures. - -=head1 AUTHOR - -Copyright (c) 2000-2002, 2005 the PerlUnit Development Team -(see L or the F file included in this -distribution). - -All rights reserved. This program is free software; you can -redistribute it and/or modify it under the same terms as Perl itself. - -=head1 SEE ALSO - -=over 4 - -=item * - -L - -=item * - -L - -=item * - -L - -=back - -=cut diff --git a/perl/third/Test-Unit-0.25/lib/Test/Unit/Failure.pm b/perl/third/Test-Unit-0.25/lib/Test/Unit/Failure.pm deleted file mode 100644 index e340fd7..0000000 --- a/perl/third/Test-Unit-0.25/lib/Test/Unit/Failure.pm +++ /dev/null @@ -1,47 +0,0 @@ -package Test::Unit::Failure; -use strict; -use base qw(Test::Unit::Exception); - -1; -__END__ - - -=head1 NAME - -Test::Unit::Failure - unit testing framework exception class - -=head1 SYNOPSIS - -This class is not intended to be used directly - -=head1 DESCRIPTION - -This class is used by the framework to communicate the result of -assertions, which will throw an instance of this class in case of -failures (that is, failed tests, not syntax errors and the like, these -are classified as errors). - -=head1 AUTHOR - -Copyright (c) 2000-2002, 2005 the PerlUnit Development Team -(see L or the F file included in this -distribution). - -All rights reserved. This program is free software; you can -redistribute it and/or modify it under the same terms as Perl itself. - -=head1 SEE ALSO - -=over 4 - -=item * - -L - -=item * - -L - -=back - -=cut diff --git a/perl/third/Test-Unit-0.25/lib/Test/Unit/HarnessUnit.pm b/perl/third/Test-Unit-0.25/lib/Test/Unit/HarnessUnit.pm deleted file mode 100644 index 9369ad8..0000000 --- a/perl/third/Test-Unit-0.25/lib/Test/Unit/HarnessUnit.pm +++ /dev/null @@ -1,157 +0,0 @@ -package Test::Unit::HarnessUnit; -# this is a test runner which outputs in the same -# format that Test::Harness expects. -use strict; - -use base qw(Test::Unit::Runner); - -use Test::Unit::TestSuite; -use Test::Unit::Loader; - -sub new { - my $class = shift; - my ($filehandle) = @_; - # should really use the IO::Handle package here. - # this is very ugly. - $filehandle = \*STDOUT unless $filehandle; - bless { _Print_stream => $filehandle }, $class; -} - -sub print_stream { - my $self = shift; - return $self->{_Print_stream}; -} - -sub _print { - my $self = shift; - my (@args) = @_; - $self->{_Print_stream}->print( @args); -} - -sub start_test { - my $self=shift; - my $test=shift; -} - -sub not_ok { - my $self = shift; - my ($test, $exception) = @_; - $self->_print("\nnot ok ERROR ", - $test->name(), - "\n$exception\n"); -} - -sub ok { - my $self = shift; - my ($test) = @_; - $self->_print("ok PASS " . $test->name() . "\n"); -} - -sub add_error { - my $self = shift; - $self->not_ok(@_); -} - -sub add_failure { - my $self = shift; - $self->not_ok(@_); -} - -sub add_pass { - my $self = shift; - $self->ok(@_); -} - -sub end_test { - my $self = shift; - my ($test) = @_; -} - -sub do_run { - my $self = shift; - my ($suite) = @_; - my $result = $self->create_test_result(); - $result->add_listener($self); - $suite->run($result, $self); -} - -sub main { - my $self = shift; - my $a_test_runner = __PACKAGE__->new; - $a_test_runner->start(@_); -} - -sub run { - my $self = shift; - my ($class) = @_; - my $a_test_runner = Test::Unit::TestRunner->new(); - if ($class->isa("Test::Unit::Test")) { - $a_test_runner->do_run($class, 0); - } else { - $a_test_runner->do_run(Test::Unit::TestSuite->new($class), 0); - } -} - -sub start { - my $self = shift; - my (@args) = @_; - - my $test_case = ""; - my $wait = 0; - my $suite = Test::Unit::Loader::load(@args); - if ($suite) { - my $count=$suite->count_test_cases(); - $self->_print("STARTING TEST RUN\n1..$count\n"); - $self->do_run($suite); - exit(0); - } else { - $self->_print("Invalid argument to test runner: $args[0]\n"); - exit(1); - } -} - -1; -__END__ - - -=head1 NAME - -Test::Unit::HarnessUnit - unit testing framework helper class - -=head1 SYNOPSIS - -This class is not intended to be used directly - -=head1 DESCRIPTION - -This is a test runner which outputs in the same format that -Test::Harness expects. - -=head1 AUTHOR - -Copyright (c) 2000-2002, 2005 the PerlUnit Development Team -(see L or the F file included in this -distribution). - -All rights reserved. This program is free software; you can -redistribute it and/or modify it under the same terms as Perl itself. - -=head1 SEE ALSO - -=over 4 - -=item * - -L - -=item * - -L - -=item * - -L - -=back - -=cut diff --git a/perl/third/Test-Unit-0.25/lib/Test/Unit/Listener.pm b/perl/third/Test-Unit-0.25/lib/Test/Unit/Listener.pm deleted file mode 100644 index 80937de..0000000 --- a/perl/third/Test-Unit-0.25/lib/Test/Unit/Listener.pm +++ /dev/null @@ -1,99 +0,0 @@ -package Test::Unit::Listener; -use Test::Unit::Loader; -use Carp; -use strict; - -sub new { - my $class = shift; - croak "call to abstract constructor ${class}::new"; -} - -sub start_suite { - my $self = shift; - my $class = ref($self); - my ($suite) = @_; - croak "call to abstract method ${class}::start_suite"; -} - -sub start_test { - my $self = shift; - my $class = ref($self); - my ($test) = @_; - croak "call to abstract method ${class}::start_test"; -} - -sub add_error { - my $self = shift; - my $class = ref($self); - my ($test, $exception) = @_; - croak "call to abstract method ${class}::add_error"; -} - -sub add_failure { - my $self = shift; - my $class = ref($self); - my ($test, $exception) = @_; - croak "call to abstract method ${class}::add_failure"; -} - -sub end_test { - my $self = shift; - my $class = ref($self); - my ($test) = @_; - croak "call to abstract method ${class}::end_test"; -} - -1; -__END__ - - -=head1 NAME - -Test::Unit::Listener - unit testing framework abstract base class - -=head1 SYNOPSIS - -This class is not intended to be used directly - -=head1 DESCRIPTION - -This class is used by the framework to define the interface of a test -listener. It is an abstract base class implemented by the test -runners. - -Due to the nature of the Perl OO implementation, this class is not -really needed, but rather serves as documentation of the interface. - -Each of the add_ methods gets two arguments: C and C. -The test is a Test::Unit::Test and the exception is a -Test::Unit::Exception. Typically you want to display -Cname()> and keep the rest as details. - -=head1 AUTHOR - -Copyright (c) 2000-2002, 2005 the PerlUnit Development Team -(see L or the F file included in this -distribution). - -All rights reserved. This program is free software; you can -redistribute it and/or modify it under the same terms as Perl itself. - -=head1 SEE ALSO - -=over 4 - -=item * - -L - -=item * - -L - -=item * - -L - -=back - -=cut diff --git a/perl/third/Test-Unit-0.25/lib/Test/Unit/Loader.pm b/perl/third/Test-Unit-0.25/lib/Test/Unit/Loader.pm deleted file mode 100644 index 3e803fb..0000000 --- a/perl/third/Test-Unit-0.25/lib/Test/Unit/Loader.pm +++ /dev/null @@ -1,211 +0,0 @@ -package Test::Unit::Loader; - -use strict; - -use FileHandle; -use Test::Unit::Debug qw(debug); -use Test::Unit::TestSuite; -use Test::Unit::TestCase; -use Test::Unit::UnitHarness; -use Test::Unit::Warning; - -# should really do something in here about a local @INC. -sub obj_load { shift; load(@_) } - -# Compiles a target. Returns the package if successful. -sub compile { - my $target = shift; - debug("Test::Unit::Loader::compile($target) called\n"); - - if ($target =~ /^\w+(::\w+)*$/) { - compile_class($target); - return $target; - } - elsif ($target =~ /\.pm$/) { - compile_file($target); - # In this case I need to figure out what the class was I just loaded! - return get_package_name_from_file($target); - } - else { - return undef; - } -} - -sub compile_class { - my $classname = shift; - debug(" Test::Unit::Loader::compile_class($classname) called\n"); - # Check if the package exists already. - { - no strict 'refs'; - if (my @keys = grep { ! /::$/ } keys %{"$classname\::"}) { - debug(" package $classname already exists (@keys); not compiling.\n"); - return; - } - } - # No? Try 'require'ing it - eval "require $classname"; - die $@ if $@; - debug(" $classname compiled OK as class name\n"); -} - -sub compile_file { - my $file = shift; - debug(" Test::Unit::Loader::compile_file($file) called\n"); - eval qq{require "$file"}; - die $@ if $@; - debug(" $file compiled OK as filename\n"); -} - -sub load { - my $target = shift; - debug("Test::Unit::Loader::load($target) called\n"); - - my $suite = load_test($target) - || load_test_harness_test($target) - || load_test_dir($target); - return $suite if $suite; - - die "Couldn't load $target in any of the supported ways"; -} - -sub load_test { - my $target = shift; - debug("Test::Unit::Loader::load_test($target) called\n"); - my $package = compile($target); - return unless $package; - debug(" compile returned $package\n"); - my $suite = load_test_suite($package) || load_test_case($package); - die "`$target' was not a valid Test::Unit::Test\n" unless $suite; - return $suite; -} - -sub load_test_suite { - my $package = shift; - debug(" Test::Unit::Loader::load_test_suite($package) called\n"); - if ($package->can("suite")) { - debug(" $package has a suite() method\n"); - return $package->suite(); - } -} - -sub load_test_case { - my $package = shift; - debug(" Test::Unit::Loader::load_test_case($package) called\n"); - if ($package->isa("Test::Unit::TestCase")) { - debug(" $package isa Test::Unit::TestCase\n"); - return Test::Unit::TestSuite->new($package); - } -} - -sub extract_testcases { - my $classname = shift; - - my @testcases = (); - - foreach my $method ($classname->list_tests()) { - if ( my $a_class_instance = $classname->new($method) ) { - push @testcases, $a_class_instance; - } - else { - push @testcases, Test::Unit::Warning->new( - "extract_testcases: Couldn't create a $classname object" - ); - } - } - - push @testcases, Test::Unit::Warning->new("No tests found in $classname") - unless @testcases; - - return @testcases; -} - -sub load_test_harness_test { - my $target = shift; - - foreach my $file ("$target", "$target.t", "t/$target", "t/$target.t" ) { - if (-r $file) { - # are the next 3 lines really necessary? - open(FH, $file) or next; - my $first = ; - close(FH) or next; - return Test::Unit::UnitHarness->new($file); - } - } - return undef; -} - -sub load_test_dir { - my $test_dir = shift; - if (-d $test_dir) { - die "This is a test directory. I haven't implemented that.\n"; - return Test::Unit::UnitHarness::new_dir($test_dir); - } -} - -# The next bit of code is a helper function which attempts -# to identify the class we are trying to use from a '.pm' -# file. If we've reached this point, we managed to 'require' -# the file already, but we dont know the file the package was -# loaded from. Somehow I feel this information is in perl -# somwhere but if it is I dont know where... -sub get_package_name_from_file { - my $filename = shift; - my $real_path = $INC{$filename}; - die "Can't find $filename in @INC: $!" - unless $real_path && open(FH, $real_path); - while () { - if (/^\s*package\s+([\w:]+)/) { - close(FH); - return $1; - } - } - die "Can't find a package in $filename"; -} - -1; -__END__ - - -=head1 NAME - -Test::Unit::Loader - unit testing framework helper class - -=head1 SYNOPSIS - -This class is not intended to be used directly. - -=head1 DESCRIPTION - -This class is used by the framework to load test classes into the -runtime environment. It handles test case and test suite classes -(referenced either via their package names or the files containing -them), Test::Harness style test files, and directory names. - -=head1 AUTHOR - -Copyright (c) 2000-2002, 2005 the PerlUnit Development Team -(see L or the F file included in this -distribution). - -All rights reserved. This program is free software; you can -redistribute it and/or modify it under the same terms as Perl itself. - -=head1 SEE ALSO - -=over 4 - -=item * - -L - -=item * - -L - -=item * - -L - -=back - -=cut diff --git a/perl/third/Test-Unit-0.25/lib/Test/Unit/Procedural.pm b/perl/third/Test-Unit-0.25/lib/Test/Unit/Procedural.pm deleted file mode 100644 index 18ea77b..0000000 --- a/perl/third/Test-Unit-0.25/lib/Test/Unit/Procedural.pm +++ /dev/null @@ -1,211 +0,0 @@ -package Test::Unit::Procedural; - -use strict; - -use Test::Unit::TestSuite; -use Test::Unit::TestRunner; - -use base 'Exporter'; - -use vars qw(@EXPORT); -@EXPORT = qw(assert create_suite run_suite add_suite); - -# Helper classes -use Devel::Symdump; -use Class::Inner; - -# Exception handling -use Error qw/:try/; -use Test::Unit::Exception; -use Test::Unit::Failure; - -# private - -my $test_suite = Test::Unit::TestSuite->empty_new("Test::Unit"); -my %suites = (); -%suites = ('Test::Unit' => $test_suite); - -sub add_to_suites { - my $suite_holder = shift; - if (not exists $suites{$suite_holder}) { - my $test_suite = Test::Unit::TestSuite->empty_new($suite_holder); - $suites{$suite_holder} = $test_suite; - } -} - -# public - -sub assert ($;$) { - my($condition, $message) = @_; - my($asserter,$file,$line) = caller(1); - - add_to_suites($asserter); - try { - $suites{$asserter}->assert($condition, $message); - } - catch Test::Unit::Exception with { - my $e = shift; - $e->throw_new( - -package => $asserter, - -file => $file, - -line => $line); - } -} - -sub create_suite { - my ($test_package_name) = @_; - $test_package_name = caller() unless defined($test_package_name); - add_to_suites($test_package_name); - - no strict 'refs'; - - my $set_up_func = sub {}; - my $tear_down_func = sub {}; - - my $st = Devel::Symdump->new($test_package_name); - my @set_up_candidates = grep /::set_up$/, $st->functions; - $set_up_func = \&{$set_up_candidates[0]} if @set_up_candidates; - - my @tear_down_candidates = grep /::tear_down$/, $st->functions; - $tear_down_func = \&{$tear_down_candidates[0]} if @tear_down_candidates; - - for my $test_method (grep /::test[^:]*$/, $st->functions) { - my($method_name) = $test_method =~ /::(test[^:]*)/; - my $subref = \&{$test_method}; - my $test_case = Class::Inner->new - (parent => 'Test::Unit::TestCase', - methods => {set_up => $set_up_func, - tear_down => $tear_down_func, - $method_name => $subref, - }, - args => [$method_name],); - $suites{$test_package_name}->add_test($test_case); - } -} - -sub run_suite { - my ($test_package_name, $filehandle) = @_; - $test_package_name = caller() unless defined($test_package_name); - my $test_runner = Test::Unit::TestRunner->new($filehandle); - $test_runner->do_run($suites{$test_package_name}); -} - -sub add_suite { - my ($to_be_added, $to_add_to) = @_; - $to_add_to = caller() unless defined($to_add_to); - die "Error: no suite '$to_be_added'" unless exists $suites{$to_be_added}; - die "Error: no suite '$to_add_to'" unless exists $suites{$to_add_to}; - $suites{$to_add_to}->add_test($suites{$to_be_added}); -} - -1; -__END__ - -=head1 NAME - -Test::Unit::Procedural - Procedural style unit testing interface - -=head1 SYNOPSIS - - use Test::Unit::Procedural; - - # your code to be tested goes here - - sub foo { return 23 }; - sub bar { return 42 }; - - # define tests - - sub test_foo { assert(foo() == 23, "Your message here"); } - sub test_bar { assert(bar() == 42, "I will be printed if this fails"); } - - # set_up and tear_down are used to - # prepare and release resources need for testing - - sub set_up { print "hello world\n"; } - sub tear_down { print "leaving world again\n"; } - - # run your test - - create_suite(); - run_suite(); - -=head1 DESCRIPTION - -Test::Unit::Procedural is the procedural style interface to a -sophisticated unit testing framework for Perl that is derived from the -JUnit testing framework for Java by Kent Beck and Erich Gamma. While -this framework is originally intended to support unit testing in an -object-oriented development paradigm (with support for inheritance of -tests etc.), Test::Unit::Procedural is intended to provide a simpler -interface to the framework that is more suitable for use in a -scripting style environment. Therefore, Test::Unit::Procedural does -not provide much support for an object-oriented approach to unit -testing - if you want that, please have a look at -L. - -You test a given unit (a script, a module, whatever) by using -Test::Unit::Procedural, which exports the following routines into your -namespace: - -=over 4 - -=item assert() - -used to assert that a boolean condition is true - -=item create_suite() - -used to create a test suite consisting of all methods with a name -prefix of C - -=item run_suite() - -runs the test suite (text output) - -=item add_suite() - -used to add test suites to each other - -=back - -For convenience, C will automatically build a test -suite for a given package. This will build a test case for each -subroutine in the package given that has a name starting with C -and pack them all together into one TestSuite object for easy testing. -If you dont give a package name to C, the current -package is taken as default. - -Test output is one status line (a "." for every successful test run, -or an "F" for any failed test run, to indicate progress), one result -line ("OK" or "!!!FAILURES!!!"), and possibly many lines reporting -detailed error messages for any failed tests. - -Please remember, Test::Unit::Procedural is intended to be a simple and -convenient interface. If you need more functionality, take the -object-oriented approach outlined in L. - -=head1 AUTHOR - -Copyright (c) 2000-2002, 2005 the PerlUnit Development Team -(see L or the F file included in this -distribution). - -All rights reserved. This program is free software; you can -redistribute it and/or modify it under the same terms as Perl itself. - -=head1 SEE ALSO - -=over 4 - -=item * - -L - -=item * - -the procedural style examples in the examples directory - -=back - -=cut diff --git a/perl/third/Test-Unit-0.25/lib/Test/Unit/Result.pm b/perl/third/Test-Unit-0.25/lib/Test/Unit/Result.pm deleted file mode 100644 index 203f601..0000000 --- a/perl/third/Test-Unit-0.25/lib/Test/Unit/Result.pm +++ /dev/null @@ -1,254 +0,0 @@ -package Test::Unit::Result; -use strict; - -use Test::Unit::Debug qw(debug); -use Test::Unit::Error; -use Test::Unit::Failure; - -use Error qw/:try/; - -sub new { - my $class = shift; - bless { - _Failures => [], - _Errors => [], - _Listeners => [], - _Run_tests => 0, - _Stop => 0, - }, $class; -} - -sub tell_listeners { - my $self = shift; - my $method = shift; - foreach (@{$self->listeners}) { - $_->$method(@_); - } -} - -sub add_error { - my $self = shift; - debug($self . "::add_error() called\n"); - my ($test, $exception) = @_; - $exception->{-object} = $test; - push @{$self->errors()}, $exception; - $self->tell_listeners(add_error => @_); -} - -sub add_failure { - my $self = shift; - debug($self . "::add_failure() called\n"); - my ($test, $exception) = @_; - $exception->{-object} = $test; - push @{$self->failures()}, $exception; - $self->tell_listeners(add_failure => @_); -} - -sub add_pass { - my $self = shift; - debug($self . "::add_pass() called\n"); - my ($test) = @_; - $self->tell_listeners(add_pass => @_); -} - -sub add_listener { - my $self = shift; - debug($self . "::add_listener() called\n"); - my ($listener) = @_; - push @{$self->listeners()}, $listener; -} - -sub listeners { - my $self = shift; - return $self->{_Listeners}; -} - -sub end_test { - my $self = shift; - my ($test) = @_; - $self->tell_listeners(end_test => $test); -} - -sub error_count { - my $self = shift; - return scalar @{$self->{_Errors}}; -} - -sub errors { - my $self = shift; - return $self->{_Errors}; -} - -sub failure_count { - my $self = shift; - return scalar @{$self->{_Failures}}; -} - -sub failures { - my $self = shift; - return $self->{_Failures}; -} - -sub run { - my $self = shift; - my ($test) = @_; - debug(sprintf "%s::run(%s) called\n", $self, $test->name()); - $self->start_test($test); - - # This closure may look convoluted, but it allows Test::Unit::Setup - # to work cleanly. - $self->run_protected( - $test, - sub { - $test->run_bare() ? - $self->add_pass($test) - : $self->add_failure($test); - } - ); - - $self->end_test($test); -} - -sub run_protected { - my $self = shift; - my $test = shift; - my $protectable = shift; - debug("$self\::run_protected($test, $protectable) called\n"); - - try { - &$protectable(); - } - catch Test::Unit::Failure with { - $self->add_failure($test, shift); - } - catch Error with { - # *Any* exception which isn't a failure or - # Test::Unit::Exception should get rebuilt and added to the - # result as a Test::Unit::Error, so that the stringify() - # method can be called on it for nice reporting. - my $error = shift; - $error = Test::Unit::Error->make_new_from_error($error) - unless $error->isa('Test::Unit::Exception'); - $self->add_error($test, $error); - }; -} - -sub run_count { - my $self = shift; - return $self->{_Run_tests}; -} - -sub run_count_inc { - my $self = shift; - ++$self->{_Run_tests}; - return $self->{_Run_tests}; -} - -sub should_stop { - my $self = shift; - return $self->{_Stop}; -} - -sub start_test { - my $self = shift; - my ($test) = @_; - $self->run_count_inc(); - $self->tell_listeners(start_test => $test); -} - -sub stop { - my $self = shift; - $self->{_Stop} = 1; -} - -sub was_successful { - my $self = shift; - return ($self->failure_count() == 0) && ($self->error_count() == 0); -} - -sub to_string { - my $self = shift; - my $class = ref($self); - debug($class . "::to_string() called\n"); -} - -1; -__END__ - - -=head1 NAME - -Test::Unit::Result - unit testing framework helper class - -=head1 SYNOPSIS - -This class is not intended to be used directly - -=head1 DESCRIPTION - -This class is used by the framework to record the results of tests, -which will throw an instance of a subclass of Test::Unit::Exception in -case of errors or failures. - -To achieve this, this class gets called with a test case as argument. -It will call this test case's run method back and catch any exceptions -thrown. - -It could be argued that Test::Unit::Result is the heart of the -PerlUnit framework, since TestCase classes vary, and you can use one -of several Test::Unit::TestRunners, but we always gather the results -in a Test::Unit::Result object. - -This is the quintessential call tree of the communication needed to -record the results of a given test: - - $aTestCase->run() { - # creates result - $aTestResult->run($aTestCase) { - # catches exception and records it - $aTestCase->run_bare() { - # runs test method inside eval - $aTestCase->run_test() { - # calls method $aTestCase->name() - # and propagates exception - # method will call Assert::assert() - # to cause failure if test fails on - # test assertion - # it finds this because $aTestCase is-a Assert - } - } - } - } - -Note too that, in the presence of Test::Unit::TestSuites, this call -tree can get a little more convoluted, but if you bear the above in -mind it should be apparent what's going on. - -=head1 AUTHOR - -Copyright (c) 2000-2002, 2005 the PerlUnit Development Team -(see L or the F file included in this -distribution). - -All rights reserved. This program is free software; you can -redistribute it and/or modify it under the same terms as Perl itself. - -=head1 SEE ALSO - -=over 4 - -=item * - -L - -=item * - -L - -=item * - -L - -=back - -=cut diff --git a/perl/third/Test-Unit-0.25/lib/Test/Unit/Runner.pm b/perl/third/Test-Unit-0.25/lib/Test/Unit/Runner.pm deleted file mode 100644 index cc2ce7d..0000000 --- a/perl/third/Test-Unit-0.25/lib/Test/Unit/Runner.pm +++ /dev/null @@ -1,100 +0,0 @@ -package Test::Unit::Runner; - -=head1 NAME - -Test::Unit::Runner - abstract base class for test runners - -=head1 SYNOPSIS - - my $runner = Test::Unit::TestRunner->new(); - $runner->filter(@filter_tokens); - $runner->start(...); - -=head1 DESCRIPTION - -This class is a parent class of all test runners, and hence is not -intended to be used directly. It provides functionality such as state -(e.g. run-time options) available to all runner classes. - -=cut - -use strict; - -use Test::Unit::Result; - -use base qw(Test::Unit::Listener); - -sub create_test_result { - my $self = shift; - return $self->{_result} = Test::Unit::Result->new(); -} - -sub result { shift->{_result} } - -sub start_suite { - my $self = shift; - my ($suite) = @_; - push @{ $self->{_suites_running} }, $suite; -} - -sub end_suite { - my $self = shift; - my ($suite) = @_; - pop @{ $self->{_suites_running} }; -} - -=head2 suites_running() - -Returns an array stack of the current suites running. When a new -suite is started, it is pushed on the stack, and it is popped on -completion. Hence the first element in the returned array is -the top-level suite, and the last is the innermost suite. - -=cut - -sub suites_running { - my $self = shift; - return @{ $self->{_suites_running} || [] }; -} - -=head2 filter([ @tokens ]) - -Set the runner's filter tokens to the given list. - -=cut - -sub filter { - my $self = shift; - $self->{_filter} = [ @_ ] if @_; - return @{ $self->{_filter} || [] }; -} - -=head2 reset_filter() - -Clears the current filter. - -=cut - -sub reset_filter { - my $self = shift; - $self->{_filter} = []; -} - -1; - -=head1 AUTHOR - -Copyright (c) 2000-2002, 2005 the PerlUnit Development Team -(see L or the F file included in this -distribution). - -All rights reserved. This program is free software; you can -redistribute it and/or modify it under the same terms as Perl itself. - -=head1 SEE ALSO - -L, -L, -L - -=cut diff --git a/perl/third/Test-Unit-0.25/lib/Test/Unit/Runner/Terminal.pm b/perl/third/Test-Unit-0.25/lib/Test/Unit/Runner/Terminal.pm deleted file mode 100644 index 8a8d410..0000000 --- a/perl/third/Test-Unit-0.25/lib/Test/Unit/Runner/Terminal.pm +++ /dev/null @@ -1,172 +0,0 @@ -package Test::Unit::Runner::Terminal; -use strict; - -use base qw(Test::Unit::TestRunner); - -sub start_suite { - my $self = shift; - $self->SUPER::start_suite(@_); - $self->_update_status; -} - -sub end_suite { - my $self = shift; - $self->SUPER::end_suite(@_); - $self->_update_status; -} - -sub start_test { - my $self = shift; - my ($test) = @_; - $self->{_last_test} = $test->name; - $self->_update_status; -} - -sub end_test { - my $self = shift; - my ($test) = @_; - $self->{_last_test} = ''; - $self->_update_status; -} - -sub add_error { - my $self = shift; - my ($test, $exception) = @_; - $self->_update_status; -} - -sub add_failure { - my $self = shift; - my ($test, $exception) = @_; - $self->_update_status; -} - -sub add_pass { - my $self = shift; - my ($test) = @_; - $self->_update_status; -} - -sub _update_status { - my $self = shift; - my $result = $self->result; - - # \e[2A goes two lines up - # \e[K clears to end of line - # \e[J clears below - # \e7 saves cursor position - # \e8 restores cursor position - my $template = <_print( - sprintf $template, - $result->run_count, - $result->failure_count, - $result->error_count, - join(' -> ', map { $_->name || '?' } $self->suites_running), - $self->{_last_test} || '', - ); -} - -sub print_result { - my $self = shift; - $self->_print("\e[J"); # clear status lines below - $self->SUPER::print_result(@_); -} - -1; -__END__ - - -=head1 NAME - -Test::Unit::Runner::Terminal - unit testing framework helper class - -=head1 SYNOPSIS - - use Test::Unit::Runner::Terminal; - - my $testrunner = Test::Unit::Runner::Terminal->new(); - $testrunner->start($my_test_class); - -=head1 DESCRIPTION - -This class is a test runner for the command line style use -of the testing framework. - -It is similar to its parent class, Test::Unit::TestRunner, but it uses -terminal escape sequences to continually update a more informative -status report as the runner progresses through the tests than just a -string of dots, E's and F's. The status report indicates the number -of tests run, the number of failures and errors encountered, which -test is currently being run, and where it lives in the suite -hierarchy. - -The class needs one argument, which is the name of the class -encapsulating the tests to be run. - -=head1 OPTIONS - -=over 4 - -=item -wait - -wait for user confirmation between tests - -=item -v - -version info - -=back - - -=head1 AUTHOR - -Copyright (c) 2000-2002, 2005 the PerlUnit Development Team -(see L or the F file included in this -distribution). - -All rights reserved. This program is free software; you can -redistribute it and/or modify it under the same terms as Perl itself. - -=head1 SEE ALSO - -=over 4 - -=item * - -L - -=item * - -L - -=item * - -L - -=item * - -L - -=item * - -L - -=item * - -For further examples, take a look at the framework self test -collection (t::tlib::AllTests). - -=back - -=cut diff --git a/perl/third/Test-Unit-0.25/lib/Test/Unit/Setup.pm b/perl/third/Test-Unit-0.25/lib/Test/Unit/Setup.pm deleted file mode 100644 index 823475b..0000000 --- a/perl/third/Test-Unit-0.25/lib/Test/Unit/Setup.pm +++ /dev/null @@ -1,63 +0,0 @@ -package Test::Unit::Setup; -use strict; - -use base qw(Test::Unit::Decorator); - -sub run { - my $self = shift(); - my($result) = @_; - my $protectable = sub { - $self->set_up(); - $self->basic_run($result); - $self->tear_down(); - }; - $result->run_protected($self, $protectable); -} - -# Sets up the fixture. Override to set up additional fixture -# state. - -sub set_up { - print "Suite setup\n"; -} - -# Tears down the fixture. Override to tear down the additional -# fixture state. - -sub tear_down { - print "Suite teardown\n"; -} - -1; -__END__ - - -=head1 NAME - -Test::Unit::Setup - unit testing framework helper class - -=head1 SYNOPSIS - - # A Decorator to set up and tear down additional fixture state. - # Subclass Setup and insert it into your tests when you want - # to set up additional state once before the tests are run. - -=head1 DESCRIPTION - -A Decorator to set up and tear down additional fixture state. -Subclass Setup and insert it into your tests when you want -to set up additional state once before the tests are run. - -=head1 AUTHOR - -Copyright (c) 2001 Kevin Connor - -All rights reserved. This program is free software; you can -redistribute it and/or modify it under the same terms as -Perl itself. - -=head1 SEE ALSO - -L, L - -=cut diff --git a/perl/third/Test-Unit-0.25/lib/Test/Unit/Test.pm b/perl/third/Test-Unit-0.25/lib/Test/Unit/Test.pm deleted file mode 100644 index 7f02e36..0000000 --- a/perl/third/Test-Unit-0.25/lib/Test/Unit/Test.pm +++ /dev/null @@ -1,147 +0,0 @@ -package Test::Unit::Test; -use strict; - -use Carp; - -use Test::Unit::Debug qw(debug); - -use base qw(Test::Unit::Assert); - -sub count_test_cases { - my $self = shift; - my $class = ref($self); - croak "call to abstract method ${class}::count_test_cases"; -} - -sub run { - my $self = shift; - my $class = ref($self); - croak "call to abstract method ${class}::run"; -} - -sub name { - my $self = shift; - my $class = ref($self); - croak "call to abstract method ${class}::name"; -} - -sub to_string { - my $self = shift; - return $self->name(); -} - -sub filter_method { - my $self = shift; - my ($token) = @_; - - my $filtered = $self->filter->{$token}; - return unless $filtered; - - if (ref $filtered eq 'ARRAY') { - return grep $self->name eq $_, @$filtered; - } - elsif (ref $filtered eq 'CODE') { - return $filtered->($self->name); - } - else { - die "Didn't understand filtering definition for token $token in ", - ref($self), "\n"; - } -} - -my %filter = (); - -sub filter { \%filter } - -# use Attribute::Handlers; - -# sub Filter : ATTR(CODE) { -# my ($pkg, $symbol, $referent, $attr, $data, $phase) = @_; -# print "attr $attr (data $data) on $pkg\::*{$symbol}{NAME}\n"; -# # return (); -# } - -sub _find_sym { # pinched from Attribute::Handlers - my ($pkg, $ref) = @_; - my $type = ref($ref); - no strict 'refs'; - warn "type $type\n"; - while (my ($name, $sym) = each %{$pkg."::"} ) { - use Data::Dumper; -# warn Dumper(*$sym); - warn "name $name sym $sym (" . (*{$sym}{$type} || '?') . ") matches?\n"; - return \$sym if *{$sym}{$type} && *{$sym}{$type} == $ref; - } -} - -sub MODIFY_CODE_ATTRIBUTES { - my ($pkg, $subref, @attrs) = @_; - my @bad = (); - foreach my $attr (@attrs) { - if ($attr =~ /^Filter\((.*)\)$/) { - my @tokens = split /\s+|\s*,\s*/, $1; - my $sym = _find_sym($pkg, $subref); - if ($sym) { - push @{ $filter{$_} }, *{$sym}{NAME} foreach @tokens; - } - else { - warn "Couldn't find symbol for $subref in $pkg\n" unless $sym; - push @bad, $attr; - } - } - else { - push @bad, $attr; - } - } - return @bad; -} - -1; -__END__ - - -=head1 NAME - -Test::Unit::Test - unit testing framework abstract base class - -=head1 SYNOPSIS - -This class is not intended to be used directly - -=head1 DESCRIPTION - -This class is used by the framework to define the interface of a test. -It is an abstract base class implemented by Test::Unit::TestCase and -Test::Unit::TestSuite. - -Due to the nature of the Perl OO implementation, this class is not -really needed, but rather serves as documentation of the interface. - -=head1 AUTHOR - -Copyright (c) 2000-2002, 2005 the PerlUnit Development Team -(see L or the F file included in this -distribution). - -All rights reserved. This program is free software; you can -redistribute it and/or modify it under the same terms as Perl itself. - -=head1 SEE ALSO - -=over 4 - -=item * - -L - -=item * - -L - -=item * - -L - -=back - -=cut diff --git a/perl/third/Test-Unit-0.25/lib/Test/Unit/TestCase.pm b/perl/third/Test-Unit-0.25/lib/Test/Unit/TestCase.pm deleted file mode 100644 index fd9232a..0000000 --- a/perl/third/Test-Unit-0.25/lib/Test/Unit/TestCase.pm +++ /dev/null @@ -1,441 +0,0 @@ -package Test::Unit::TestCase; -use strict; - -use base qw(Test::Unit::Test); - -use Test::Unit::Debug qw(debug); -use Test::Unit::Failure; -use Test::Unit::Error; -use Test::Unit::Result; - -use Devel::Symdump; -use Class::Inner; -use Error qw/:try/; - -sub new { - my $class = shift; - my ($name) = @_; - bless { - __PACKAGE__ . '_name' => $name, - __PACKAGE__ . '_annotations' => '', - }, $class; -} - -sub annotate { - my $self = shift; - $self->{__PACKAGE__ . '_annotations'} .= join '', @_; -} - -sub annotations { $_[0]->{__PACKAGE__ . '_annotations'} } - -sub count_test_cases { - my $self = shift; - return 1; -} - -sub create_result { - my $self = shift; - return Test::Unit::Result->new(); -} - -sub name { - my $self = shift; - return $self->{__PACKAGE__ . '_name'}; -} - -sub run { - my $self = shift; - debug(ref($self), "::run() called on ", $self->name, "\n"); - my ($result, $runner) = @_; - $result ||= create_result(); - $result->run($self); - return $result; -} - -sub run_bare { - my $self = shift; - debug(" ", ref($self), "::run_bare() called on ", $self->name, "\n"); - $self->set_up(); - # Make sure tear_down happens if and only if set_up() succeeds. - try { - $self->run_test(); - 1; - } - finally { - $self->tear_down; - }; -} - -sub run_test { - my $self = shift; - debug(" ", ref($self) . "::run_test() called on ", $self->name, "\n"); - my $method = $self->name(); - if ($self->can($method)) { - debug(" running `$method'\n"); - $self->$method(); - } else { - $self->fail(" Method `$method' not found"); - } -} - -sub set_up { 1 } - -sub tear_down { 1 } - -sub to_string { - my $self = shift; - my $class = ref($self); - return ($self->name() || "ANON") . "(" . $class . ")"; -} - -sub make_test_from_coderef { - my ($self, $coderef, @args) = @_; - die "Need a coderef argument" unless $coderef; - return Class::Inner->new(parent => ($self || ref $self), - methods => {run_test => $coderef}, - args => [ @args ]); -} - - -# Returns a list of the tests run by this class and its superclasses. -# DO NOT OVERRIDE THIS UNLESS YOU KNOW WHAT YOU ARE DOING! -sub list_tests { - my $class = ref($_[0]) || $_[0]; - my @tests = (); - no strict 'refs'; - if (@{"$class\::TESTS"}) { - push @tests, @{"$class\::TESTS"}; - } - else { - push @tests, $class->get_matching_methods(qr/::(test[^:]*)$/); - } - push @tests, map {$_->can('list_tests') ? $_->list_tests : () } @{"$class\::ISA"}; - my %tests = map {$_ => ''} @tests; - return keys %tests; -} - -sub get_matching_methods { - my $class = ref($_[0]) || $_[0]; - my $re = $_[1]; - my $st = Devel::Symdump->new($class); - return map { /$re/ ? $1 : () } $st->functions(); -} - -sub list { - my $self = shift; - my $show_testcases = shift; - return $show_testcases ? - [ ($self->name() || 'anonymous testcase') . "\n" ] - : []; -} - -1; -__END__ - - - -=head1 NAME - -Test::Unit::TestCase - unit testing framework base class - -=head1 SYNOPSIS - - package FooBar; - use base qw(Test::Unit::TestCase); - - sub new { - my $self = shift()->SUPER::new(@_); - # your state for fixture here - return $self; - } - - sub set_up { - # provide fixture - } - sub tear_down { - # clean up after test - } - sub test_foo { - my $self = shift; - my $obj = ClassUnderTest->new(...); - $self->assert_not_null($obj); - $self->assert_equals('expected result', $obj->foo); - $self->assert(qr/pattern/, $obj->foobar); - } - sub test_bar { - # test the bar feature - } - -=head1 DESCRIPTION - -Test::Unit::TestCase is the 'workhorse' of the PerlUnit framework. -When writing tests, you generally subclass Test::Unit::TestCase, write -C and C functions if you need them, a bunch of -C test methods, then do - - $ TestRunner.pl My::TestCase::Class - -and watch as your tests fail/succeed one after another. Or, if you -want your tests to work under Test::Harness and the standard perlish -'make test', you'd write a t/foo.t that looked like: - - use Test::Unit::HarnessUnit; - my $r = Test::Unit::HarnessUnit->new(); - $r->start('My::TestCase::Class'); - -=head2 How To Use Test::Unit::TestCase - -(Taken from the JUnit TestCase class documentation) - -A test case defines the "fixture" (resources need for testing) to run -multiple tests. To define a test case: - -=over 4 - -=item 1 - -implement a subclass of TestCase - -=item 2 - -define instance variables that store the state of the fixture (I -suppose if you are using Class::MethodMaker this is possible...) - -=item 3 - -initialize the fixture state by overriding C - -=item 4 - -clean-up after a test by overriding C. - -=back - - -Implement your tests as methods. By default, all methods that match -the regex C are taken to be test methods (see -L and L). Note that, by -default all the tests defined in the current class and all of its -parent classes will be run. To change this behaviour, see L. - -By default, each test runs in its own fixture so there can be no side -effects among test runs. Here is an example: - - package MathTest; - use base qw(Test::Unit::TestCase); - - sub new { - my $self = shift()->SUPER::new(@_); - $self->{value_1} = 0; - $self->{value_2} = 0; - return $self; - } - - sub set_up { - my $self = shift; - $self->{value_1} = 2; - $self->{value_2} = 3; - } - -For each test implement a method which interacts with the fixture. -Verify the expected results with assertions specified by calling -C<$self-Eassert()> with a boolean value. - - sub test_add { - my $self = shift; - my $result = $self->{value_1} + $self->{value_2}; - $self->assert($result == 5); - } - -Once the methods are defined you can run them. The normal way to do -this uses reflection to implement C. It dynamically finds -and invokes a method. For this the name of the test case has to -correspond to the test method to be run. The tests to be run can be -collected into a TestSuite. The framework provides different test -runners, which can run a test suite and collect the results. A test -runner either expects a method C as the entry point to get a -test to run or it will extract the suite automatically. - -=head2 Writing Test Methods - -The return value of your test method is completely irrelevant. The -various test runners assume that a test is executed successfully if no -exceptions are thrown. Generally, you will not have to deal directly -with exceptions, but will write tests that look something like: - - sub test_something { - my $self = shift; - # Execute some code which gives some results. - ... - # Make assertions about those results - $self->assert_equals('expected value', $resultA); - $self->assert_not_null($result_object); - $self->assert(qr/some_pattern/, $resultB); - } - -The assert methods throw appropriate exceptions when the assertions fail, -which will generally stringify nicely to give you sensible error reports. - -L has more details on the various different -C methods. - -L describes the Exceptions used within the -C framework. - -=head2 Helper methods - -=over 4 - -=item make_test_from_coderef (CODEREF, [NAME]) - -Takes a coderef and an optional name and returns a Test case that -inherits from the object on which it was called, which has the coderef -installed as its C method. L has more details -on how this is generated. - -=item list_tests - -Returns the list of test methods in this class and its parents. You -can override this in your own classes, but remember to call -C in there too. Uses C. - -=item get_matching_methods (REGEXP) - -Returns the list of methods in this class matching REGEXP. - -=item set_up - -=item tear_down - -If you don't have any setup or tear down code that needs to be run, we -provide a couple of null methods. Override them if you need to. - -=item annotate (MESSAGE) - -You can accumulate helpful debugging for each testcase method via this -method, and it will only be outputted if the test fails or encounters -an error. - -=back - -=head2 How it All Works - -The PerlUnit framework is achingly complex. The basic idea is that you -get to write your tests independently of the manner in which they will -be run, either via a C type script, or through one of the -provided TestRunners, the framework will handle all that for you. And -it does. So for the purposes of someone writing tests, in the majority -of cases the answer is 'It just does.'. - -Of course, if you're trying to extend the framework, life gets a -little more tricky. The core class that you should try and grok is -probably Test::Unit::Result, which, in tandem with whichever -TestRunner is being used mediates the process of running tests, -stashes the results and generally sits at the centre of everything. - -Better docs will be forthcoming. - -=head1 NOTES - -Here's a few things to remember when you're writing your test suite: - -Tests are run in 'random' order; the list of tests in your TestCase -are generated automagically from its symbol table, which is a hash, so -methods aren't sorted there. - -If you need to specify the test order, you can do one of the -following: - -=over 4 - -=item * Set @TESTS - - our @TESTS = qw(my_test my_test_2); - -This is the simplest, and recommended way. - -=item * Override the C method - -to return an ordered list of methodnames - -=item * Provide a C method - -which returns a Test::Unit::TestSuite. - -=back - -However, even if you do manage to specify the test order, be careful, -object data will not be retained from one test to another, if you want -to use persistent data you'll have to use package lexicals or globals. -(Yes, this is probably a bug). - -If you only need to restrict which tests are run, there is a filtering -mechanism available. Override the C method in your testcase -class to return a hashref whose keys are filter tokens and whose -values are either arrayrefs of test method names or coderefs which take -the method name as the sole parameter and return true if and only if it -should be filtered, e.g. - - sub filter {{ - slow => [ qw(my_slow_test my_really_slow_test) ], - matching_foo => sub { - my $method = shift; - return $method =~ /foo/; - } - }} - -Then, set the filter state in your runner before the test run starts: - - # @filter_tokens = ( 'slow', ... ); - $runner->filter(@filter_tokens); - $runner->start(@args); - -This interface is public, but currently undocumented (see -F). - -=head1 BUGS - -See note 1 for at least one bug that's got me scratching my head. -There's bound to be others. - -=head1 AUTHOR - -Copyright (c) 2000-2002, 2005 the PerlUnit Development Team -(see L or the F file included in this -distribution). - -All rights reserved. This program is free software; you can -redistribute it and/or modify it under the same terms as Perl itself. - -=head1 SEE ALSO - -=over 4 - -=item * - -L - -=item * - -L - -=item * - -L - -=item * - -L - -=item * - -L - -=item * - -For further examples, take a look at the framework self test -collection (t::tlib::AllTests). - -=back - -=cut diff --git a/perl/third/Test-Unit-0.25/lib/Test/Unit/TestRunner.pm b/perl/third/Test-Unit-0.25/lib/Test/Unit/TestRunner.pm deleted file mode 100644 index 52d94f0..0000000 --- a/perl/third/Test-Unit-0.25/lib/Test/Unit/TestRunner.pm +++ /dev/null @@ -1,273 +0,0 @@ -package Test::Unit::TestRunner; -use strict; - -use base qw(Test::Unit::Runner); - -use Test::Unit; # for copyright & version number -use Test::Unit::TestSuite; -use Test::Unit::Loader; -use Test::Unit::Result; - -use Benchmark; - -sub new { - my $class = shift; - my ($filehandle) = @_; - $filehandle = \*STDOUT unless $filehandle; - select((select($filehandle), $| = 1)[0]); - bless { _Print_stream => $filehandle }, $class; -} - -sub print_stream { - my $self = shift; - return $self->{_Print_stream}; -} - -sub _print { - my $self = shift; - my (@args) = @_; - $self->print_stream->print(@args); -} - -sub add_error { - my $self = shift; - my ($test, $exception) = @_; - $self->_print("E"); -} - -sub add_failure { - my $self = shift; - my ($test, $exception) = @_; - $self->_print("F"); -} - -sub add_pass { - # in this runner passes are ignored. -} - -sub do_run { - my $self = shift; - my ($suite, $wait) = @_; - my $result = $self->create_test_result(); - $result->add_listener($self); - my $start_time = new Benchmark(); - $suite->run($result, $self); - my $end_time = new Benchmark(); - - $self->print_result($result, $start_time, $end_time); - - if ($wait) { - print " to continue"; # go to STDIN any case - ; - } - - $self->_print("\nTest was not successful.\n") - unless $result->was_successful; - - return $result->was_successful; -} - -sub end_test { -} - -sub main { - my $self = shift; - my $a_test_runner = Test::Unit::TestRunner->new(); - $a_test_runner->start(@_); -} - -sub print_result { - my $self = shift; - my ($result, $start_time, $end_time) = @_; - - my $run_time = timediff($end_time, $start_time); - $self->_print("\n", "Time: ", timestr($run_time), "\n"); - - $self->print_header($result); - $self->print_errors($result); - $self->print_failures($result); -} - -sub print_errors { - my $self = shift; - my ($result) = @_; - return unless my $error_count = $result->error_count(); - my $msg = "\nThere " . - ($error_count == 1 ? - "was 1 error" - : "were $error_count errors") . - ":\n"; - $self->_print($msg); - - my $i = 0; - for my $e (@{$result->errors()}) { - chomp(my $e_to_str = $e); - $i++; - $self->_print("$i) $e_to_str\n"); - $self->_print("\nAnnotations:\n", $e->object->annotations()) - if $e->object->annotations(); - } -} - -sub print_failures { - my $self = shift; - my ($result) = @_; - return unless my $failure_count = $result->failure_count; - my $msg = "\nThere " . - ($failure_count == 1 ? - "was 1 failure" - : "were $failure_count failures") . - ":\n"; - $self->_print($msg); - - my $i = 0; - for my $f (@{$result->failures()}) { - chomp(my $f_to_str = $f); - $self->_print("\n") if $i++; - $self->_print("$i) $f_to_str\n"); - $self->_print("\nAnnotations:\n", $f->object->annotations()) - if $f->object->annotations(); - } -} - -sub print_header { - my $self = shift; - my ($result) = @_; - if ($result->was_successful()) { - $self->_print("\n", "OK", " (", $result->run_count(), " tests)\n"); - } else { - $self->_print("\n", "!!!FAILURES!!!", "\n", - "Test Results:\n", - "Run: ", $result->run_count(), - ", Failures: ", $result->failure_count(), - ", Errors: ", $result->error_count(), - "\n"); - } -} - -sub run { - my $self = shift; - my ($class) = @_; - my $a_test_runner = Test::Unit::TestRunner->new(); - $a_test_runner->do_run(Test::Unit::TestSuite->new($class), 0); -} - -sub run_and_wait { - my $self = shift; - my ($test) = @_; - my $a_test_runner = Test::Unit::TestRunner->new(); - $a_test_runner->do_run(Test::Unit::TestSuite->new($test), 1); -} - -sub start { - my $self = shift; - my (@args) = @_; - - my $test = ""; - my $wait = 0; - - for (my $i = 0; $i < @args; $i++) { - if ($args[$i] eq "-wait") { - $wait = 1; - } elsif ($args[$i] eq "-v") { - print Test::Unit::COPYRIGHT_SHORT; - } else { - $test = $args[$i]; - } - } - if ($test eq "") { - die "Usage: TestRunner.pl [-wait] name, where name is the name of the Test class\n"; - } - - my $suite = Test::Unit::Loader::load($test); - $self->do_run($suite, $wait); -} - -sub start_test { - my $self = shift; - my ($test) = @_; - $self->_print("."); -} - -1; -__END__ - - -=head1 NAME - -Test::Unit::TestRunner - unit testing framework helper class - -=head1 SYNOPSIS - - use Test::Unit::TestRunner; - - my $testrunner = Test::Unit::TestRunner->new(); - $testrunner->start($my_test_class); - -=head1 DESCRIPTION - -This class is the test runner for the command line style use -of the testing framework. - -It is used by simple command line tools like the F -script provided. - -The class needs one argument, which is the name of the class -encapsulating the tests to be run. - -=head1 OPTIONS - -=over 4 - -=item -wait - -wait for user confirmation between tests - -=item -v - -version info - -=back - - -=head1 AUTHOR - -Copyright (c) 2000-2002, 2005 the PerlUnit Development Team -(see L or the F file included in this -distribution). - -All rights reserved. This program is free software; you can -redistribute it and/or modify it under the same terms as Perl itself. - -=head1 SEE ALSO - -=over 4 - -=item * - -L - -=item * - -L - -=item * - -L - -=item * - -L - -=item * - -L - -=item * - -For further examples, take a look at the framework self test -collection (t::tlib::AllTests). - -=back - -=cut diff --git a/perl/third/Test-Unit-0.25/lib/Test/Unit/TestSuite.pm b/perl/third/Test-Unit-0.25/lib/Test/Unit/TestSuite.pm deleted file mode 100644 index 356dcb5..0000000 --- a/perl/third/Test-Unit-0.25/lib/Test/Unit/TestSuite.pm +++ /dev/null @@ -1,360 +0,0 @@ -package Test::Unit::TestSuite; -use strict; - -=head1 NAME - -Test::Unit::TestSuite - unit testing framework base class - -=cut - -use base 'Test::Unit::Test'; - -use Carp; - -use Test::Unit::Debug qw(debug); -use Test::Unit::TestCase; -use Test::Unit::Loader; -use Test::Unit::Warning; - -=head1 SYNOPSIS - - package MySuite; - - use base qw(Test::Unit::TestSuite); - - sub name { 'My very own test suite' } - sub include_tests { qw(MySuite1 MySuite2 MyTestCase1 ...) } - -This is the easiest way of building suites; there are many more. Read on ... - -=head1 DESCRIPTION - -This class provides the functionality for building test suites in -several different ways. - -Any module can be a test suite runnable by the framework if it -provides a C method which returns a C -object, e.g. - - use Test::Unit::TestSuite; - - # more code here ... - - sub suite { - my $class = shift; - - # Create an empty suite. - my $suite = Test::Unit::TestSuite->empty_new("A Test Suite"); - # Add some tests to it via $suite->add_test() here - - return $suite; - } - -This is useful if you want your test suite to be contained in the module -it tests, for example. - -Alternatively, you can have "standalone" test suites, which inherit directly -from C, e.g.: - - package MySuite; - - use base qw(Test::Unit::TestSuite); - - sub new { - my $class = shift; - my $self = $class->SUPER::empty_new(); - # Build your suite here - return $self; - } - - sub name { 'My very own test suite' } - -or if your C is going to do nothing more interesting than add -tests from other suites and testcases via C, you can use the -C method as shorthand: - - package MySuite; - - use base qw(Test::Unit::TestSuite); - - sub name { 'My very own test suite' } - sub include_tests { qw(MySuite1 MySuite2 MyTestCase1 ...) } - -This is the easiest way of building suites. - -=head1 CONSTRUCTORS - -=head2 empty_new ([NAME]) - - my $suite = Test::Unit::TestSuite->empty_new('my suite name'); - -Creates a fresh suite with no tests. - -=cut - -sub empty_new { - my $this = shift; - my $classname = ref $this || $this; - my $name = shift || ''; - - my $self = { - _Tests => [], - _Name => $name, - }; - bless $self, $classname; - - debug(ref($self), "::empty_new($name) called\n"); - return $self; -} - -=head2 new ([ CLASSNAME | TEST ]) - -If a test suite is provided as the argument, it merely returns that -suite. If a test case is provided, it extracts all test case methods -from the test case (see L) into a new -test suite. - -If the class this method is being run in has an C method -which returns an array of class names, it will also automatically add -the tests from those classes into the newly constructed suite object. - -=cut - -sub new { - my $class = shift; - my $classname = shift || ''; # Avoid a warning - debug("$class\::new($classname) called\n"); - - my $self = $class->empty_new(); - - if ($classname) { - Test::Unit::Loader::compile_class($classname); - if (eval { $classname->isa('Test::Unit::TestCase') }) { - $self->{_Name} = "suite extracted from $classname"; - my @testcases = Test::Unit::Loader::extract_testcases($classname); - foreach my $testcase (@testcases) { - $self->add_test($testcase); - } - } - elsif (eval { $classname->can('suite') }) { - return $classname->suite(); - } - else { - my $error = "Class $classname was not a test case or test suite.\n"; - #$self->add_warning($error); - die $error; - } - } - - if ($self->can('include_tests')) { - foreach my $test ($self->include_tests()) { - $self->add_test($test); - } - } - - return $self; -} - -=head1 METHODS - -=cut - -sub suite { - my $class = shift; - croak "suite() is not an instance method" if ref $class; - $class->new(@_); -} - -=head2 name() - -Returns the suite's human-readable name. - -=cut - -sub name { - my $self = shift; - croak "Override name() in subclass to set name\n" if @_; - return $self->{_Name}; -} - -=head2 names() - -Returns an arrayref of the names of all tests in the suite. - -=cut - -sub names { - my $self = shift; - my @test_list = @{$self->tests}; - return [ map {$_->name} @test_list ] if @test_list; -} - -=head2 list (SHOW_TESTCASES) - -Produces a human-readable indented lists of the suite and the subsuites -it contains. If the first parameter is true, also lists any testcases -contained in the suite and its subsuites. - -=cut - -sub list { - my $self = shift; - my $show_testcases = shift; - my $first = ($self->name() || 'anonymous Test::Unit::TestSuite'); - $first .= " - " . ref($self) unless ref($self) eq __PACKAGE__; - $first .= "\n"; - my @lines = ( $first ); - foreach my $test (@{ $self->tests() }) { - push @lines, map " $_", @{ $test->list($show_testcases) }; - } - return \@lines; -} - -=head2 add_test (TEST_CLASSNAME | TEST_OBJECT) - -You can add a test object to a suite with this method, by passing -either its classname, or the object itself as the argument. - -Of course, there are many ways of getting the object too ... - - # Get and add an existing suite. - $suite->add_test('MySuite1'); - - # This is exactly equivalent: - $suite->add_test(Test::Unit::TestSuite->new('MySuite1')); - - # So is this, provided MySuite1 inherits from Test::Unit::TestSuite. - use MySuite1; - $suite->add_test(MySuite1->new()); - - # Extract yet another suite by way of suite() method and add it to - # $suite. - use MySuite2; - $suite->add_test(MySuite2->suite()); - - # Extract test case methods from MyModule::TestCase into a - # new suite and add it to $suite. - $suite->add_test(Test::Unit::TestSuite->new('MyModule::TestCase')); - -=cut - -sub add_test { - my $self = shift; - my ($test) = @_; - debug('+ ', ref($self), "::add_test($test) called\n"); - $test = Test::Unit::Loader::load_test($test) unless ref $test; - croak "`$test' could not be interpreted as a Test::Unit::Test object" - unless eval { $test->isa('Test::Unit::Test') }; - push @{$self->tests}, $test; -} - -sub count_test_cases { - my $self = shift; - my $count; - $count += $_->count_test_cases for @{$self->tests}; - return $count; -} - -sub run { - my $self = shift; - my ($result, $runner) = @_; - - debug("$self\::run($result, ", $runner || 'undef', ") called\n"); - - $result ||= create_result(); - $result->tell_listeners(start_suite => $self); - - $self->add_warning("No tests found in " . $self->name()) - unless @{ $self->tests() }; - - for my $t (@{$self->tests()}) { - if ($runner && $self->filter_test($runner, $t)) { - debug(sprintf "+ skipping '%s'\n", $t->name()); - next; - } - debug(sprintf "+ didn't skip '%s'\n", $t->name()); - - last if $result->should_stop(); - $t->run($result, $runner); - } - - $result->tell_listeners(end_suite => $self); - - return $result; -} - -sub filter_test { - my $self = shift; - my ($runner, $test) = @_; - - debug(sprintf "checking whether to filter '%s'\n", $test->name); - - my @filter_tokens = $runner->filter(); - - foreach my $token (@filter_tokens) { - my $filtered = $test->filter_method($token); - debug(" - by token $token? ", $filtered ? 'yes' : 'no', "\n"); - return 1 if $filtered; - } - - return 0; -} - -sub test_at { - my $self = shift; - my ($index) = @_; - return $self->tests()->[$index]; -} - -sub test_count { - my $self = shift; - return scalar @{$self->tests()}; -} - -sub tests { - my $self = shift; - return $self->{_Tests}; -} - -sub to_string { - my $self = shift; - return $self->name(); -} - -sub add_warning { - my $self = shift; - $self->add_test(Test::Unit::Warning->new(join '', @_)); -} - -1; -__END__ - -=head1 AUTHOR - -Copyright (c) 2000-2002, 2005 the PerlUnit Development Team -(see L or the F file included in this -distribution). - -All rights reserved. This program is free software; you can -redistribute it and/or modify it under the same terms as Perl itself. - -=head1 SEE ALSO - -=over 4 - -=item * - -L - -=item * - -L - -=item * - -For further examples, take a look at the framework self test -collection (t::tlib::AllTests). - -=back - -=cut diff --git a/perl/third/Test-Unit-0.25/lib/Test/Unit/TkTestRunner.pm b/perl/third/Test-Unit-0.25/lib/Test/Unit/TkTestRunner.pm deleted file mode 100644 index 595c442..0000000 --- a/perl/third/Test-Unit-0.25/lib/Test/Unit/TkTestRunner.pm +++ /dev/null @@ -1,697 +0,0 @@ -#!/usr/bin/perl -w - -package Test::Unit::TkTestRunner; - -use strict; - -use base qw(Test::Unit::Runner); - -use Tk; -use Tk::BrowseEntry; -use Benchmark; - -use Test::Unit; # for copyright & version number -use Test::Unit::Result; -use Test::Unit::Loader; - -sub new { - my $self = bless {}, shift; - return $self; -} - -sub about { - my $self = shift; - my $dialog = $self->{frame}->DialogBox( - -title => 'About PerlUnit', - -buttons => [ 'OK' ] - ); - my $text = $dialog->add("ROText"); #, -width => 80, -height => 20); - $text->insert("end", Test::Unit::COPYRIGHT_NOTICE); - $text->pack(); - $dialog->Show(); -} - -sub add_error { - my $self = shift; - $self->{number_of_errors} = $self->{result}->error_count(); - $self->append_failure("Error", @_); - $self->update(); -} - -sub add_failure { - my $self = shift; - $self->{number_of_failures} = $self->{result}->failure_count(); - $self->append_failure("Failure", @_); - $self->update(); -} - -sub append_failure { - my ($self, $kind, $test, $exception)=@_; - my $message = $test->name(); #bad juju!! - if ($message) { - $kind .= ":".substr($message, 0, 100); - } - $self->{failure_list}->insert("end", $message); - push @{$self->{failed_tests}}, $test; - push @{$self->{exceptions}}, $exception; -} - -sub plan{ - my $self = shift; - $self->{planned} = shift; -} - - -sub choose_file { - my $self = shift; - my $name = $self->{suite_name}; - my @types = ([ 'All Files', '*' ]); - my $dir = undef; - if (defined $name) { - require File::Basename; - my $sfx; - ($name, $dir, $sfx) = File::Basename::fileparse($name, '\..*'); - if (defined($sfx) && length($sfx)) { - unshift(@types, [ 'Similar Files', [$sfx]]); - $name .= $sfx; - } - } - my $file = $self->{frame}->getOpenFile( - -title => "Select test case", - -initialdir => $dir, - -initialfile => $name, - -filetypes => \@types - ); - if (defined $file) { - $file=~s/\/+/\//g; - } - $self->{suite_name} = $file; -} - -sub create_punit_menu { - my $self = shift; - my $main_menu = $self->{frame}->Menu( - -type => 'menubar', - -menuitems => [ - [ - cascade => 'F~ile', - -menuitems => [ - [ - command => 'O~pen', - -command => sub { $self->choose_file() } - ], - [ - command => 'Ex~it', - -command => sub { $self->{frame}->destroy() } - ], - ], - ], - [ - cascade => 'H~elp', - -menuitems => [ - [ - command => 'A~bout PerlUnit', - -command => sub { $self->about() } - ], - ], - ], - ], - ); - return $main_menu; -} - -sub create_menus { - my $self = shift; - $self->{frame}->configure(-menu => $self->create_punit_menu()); -} - -sub create_ui { - my $self = shift; - # Lay the window out.... - my $mw = $self->{frame} = MainWindow->new( - -title => 'Run Test Suite', - -width => 200 - ); - # I need stretchy labels, Tk doesnt have them - my $mklabel = sub { - my (@args)=@_; - $self->{$args[0]} = $args[2]; - $mw->Entry( - -textvariable => \$self->{$args[0]}, - -justify => $args[1], - -relief => 'flat', - -state => 'disabled' - ); - }; - $self->create_menus(); - $self->{suite_label} = $mw->Label( - -text => 'Enter the name of the TestCase:' - ); - $self->{suite_name} = "x"; - $self->{suite_field} = $mw->BrowseEntry( - -textvariable => \$self->{suite_name}, - -choices => [], - ); - $self->{add_text_listener} = sub { $self->run_suite() }; - $self->{run} = $mw->Button( - -text => 'Run', - -state => 'normal', - -command => sub { $self->run_suite() } - ); - - my $lab1 = $mw->Label(-text => "Runs:"); - my $lab2 = &{$mklabel}('number_of_runs', 'right', 0); - my $lab3 = $mw->Label(-text => "Errors:"); - my $lab4 = &{$mklabel}('number_of_errors', 'right', 0); - my $lab5 = $mw->Label(-text => "Failures:"); - my $lab6 = &{$mklabel}('number_of_failures', 'right', 0); - - $self->{progress_bar} = $mw->ArrayBar( - -width => 20, - -length => 400, - -colors => [ 'green', 'red', 'grey' ] - ); - $self->{failure_label} = $mw->Label( - -text => 'Errors and Failures:', - -justify => 'left' - ); - $self->{failure_list} = $mw->Scrolled('Listbox', -scrollbars => 'e'); - $self->{failure_list}->insert("end", "", "", "", "", "", ""); - - $self->{quit_button} = $mw->Button( - -text => 'Quit', - -command => sub { $mw->destroy() } - ); - - $self->{rerun_button} = $mw->Button( - -text => 'ReRun', - -state => 'normal', - -command => sub { $self->rerun() } - ); - $self->{show_error_button} = $mw->Button( - -text => 'Show...', - -state => 'normal', - -command => sub { $self->show_error_trace() } - ); - - - $self->{status_line_box}= &{$mklabel}('status_line', 'left', 'Status line'); - $self->{status_line_box}->configure(-relief => 'sunken', -bg => 'grey'); - - # Bindings go here, so objects are already defined. - $self->{failure_list}->bind('' => sub { $self->show_error_trace() }); - - # all geometry management BELOW this point. Otherwise bindings - # wont work. - $self->{suite_label}->form( - -left => [ '%0' ], - -top => [ '%0' ], - -fill => 'x' - ); - $self->{run}->form( - -right => [ '%100' ], - -top => [ $self->{suite_label} ], - ); - $self->{suite_field}->form( - -left => [ '%0' ], - -right => [$self->{run}], - -top => [$self->{suite_label}], -fill => 'x' - ); - - $lab1->form(-left => ['%0'], -top => [$self->{suite_field}, 10]); - $lab2->form(-left => [$lab1], -top => [$self->{suite_field}, 10], -fill => 'x'); - $lab3->form(-left => [$lab2], -top => [$self->{suite_field}, 10]); - $lab4->form(-left => [$lab3], -top => [$self->{suite_field}, 10], -fill => 'x'); - $lab5->form(-left => [$lab4], -top => [$self->{suite_field}, 10]); - $lab6->form(-left => [$lab5], -top => [$self->{suite_field}, 10], -fill => 'x'); - - - $self->{progress_bar}->form(-left => [ '%0' ], -top => [$lab6, 10]); - $self->{failure_label}->form( - -left => [ '%0' ], - -top => [$self->{progress_bar}, 10], - -right => [ '%100' ] - ); - $self->{failure_list}->form( - -left => [ '%0' ], - -top => [$self->{failure_label}], - -right => [ '%100' ], - -fill => 'both' - ); - # this is in a wierd order 'cos Quit keeps trying to resize. - $self->{quit_button}->form( - -right => [ '%100' ], - -bottom => [ '%100' ], - -fill => 'none' - ); - $self->{show_error_button}->form( - -right => [ '%100' ], - -bottom => [$self->{quit_button}], - -top => [$self->{failure_list}] - ); -# Rerun doesn't work yet. -# $self->{rerun_button}->form( -# -right => [$self->{show_error_button}], -# -top => [$self->{failure_list}] -# ); - - $self->{status_line_box}->form( - -left => [ '%0' ], - -right => [$self->{quit_button}], - -bottom => [ '%100' ], - -top => [$self->{show_error_button}], - -fill => 'x' - ); - - $self->reset(); - return $mw; -} - -sub end_test { - my $self = shift; - $self->{runs} = $self->{result}->run_count(); - $self->update(); -} - -sub get_test { - my $self = shift; - my $suite = Test::Unit::Loader->obj_load(shift); - $self->{status_line}=""; - return $suite; -} - -sub is_error_selected { - my $self = shift; - ($self->{listbox}->curselection>=0)?1:0; -} - -sub load_frame_icon { - # not implemented -} - -sub main { - my $main = new Test::Unit::TkTestRunner()->start(@_); -} - -sub rerun { - # not implemented and not going to! - my $self = shift; - my $index = $self->{failure_list}->curselection; - return if $index < 0; - my $test = $self->{failed_tests}->[$index]; - #if (! $test->isa("Test::Unit::TestCase")) { - $self->show_status("Could not reload test."); - #} - # Not sure how to do this... -} - -sub reset { - my $self = shift; - $self->{number_of_errors} = 0; - $self->{number_of_failures} = 0; - $self->{number_of_runs} = 0; - $self->{planned} = 0; - $self->{failure_list}->delete(0, "end"); - $self->{exceptions} = []; - $self->{failed_tests} = []; - $self->{progress_bar}->value(0, 0, 1); -} - -sub run { - my $self = shift; - $self->run_suite(); -} - -sub run_failed { - my $self = shift; - # not implemented -} - -sub run_suite { - my $self = shift; - my $suite; - if (defined($self->{runner})) { - $self->{result}->stop(); - } - else { - $self->add_to_history(); - $self->{run}->configure(-text => "Stop"); - $self->show_info("Initializing..."); - $self->reset(); - $self->show_info("Load Test Case..."); - eval { - $suite = $self->get_test($self->{suite_name}); - }; - if ($@ or !$suite) { - $suite = undef; - $self->show_status("Could not load test!"); - } - if ($suite) { - $self->{runner} = 1; - $self->{planned} = $suite->count_test_cases(); - $self->{result} = $self->create_test_result(); - $self->{result}->add_listener($self); - $self->show_info("Running..."); - $self->{start_time} = new Benchmark(); - $suite->run($self->{result}); - if ($self->{result}->should_stop()) { - $self->show_status("Stopped"); - } - else { - $self->{finish_time} = new Benchmark(); - $self->{run_time} = timediff($self->{finish_time}, - $self->{start_time}); - $self->show_info("Finished: ".timestr($self->{run_time}, 'nop')); - } - } - $self->{runner} = undef; - $self->{result} = undef; - $self->{run}->configure(-text => "Run"); - } -} - -sub show_error_trace { - # pop up a text dialog containing the details. - my $self = shift; - my $dialog = $self->{frame}->DialogBox( - -title => 'Details', - -buttons => [ 'OK' ] - ); - my $selected = $self->{failure_list}->curselection; - return unless defined($selected) && $self->{exceptions}[$selected]; - my $text = $dialog->add("Scrolled", "ROText", -width => 80, -height => 20) - ->pack(-expand => 1, -fill => 'both'); - $text->insert("end", $self->{exceptions}[$selected]->to_string()); - - my $e = $self->{exceptions}[$selected]; - if ($e->object->annotations()) { - foreach my $data ("\n\nAnnotations:\n", $e->object->annotations()) { - $text->insert("end", $data); # third arg would be a tag - } - } - - $dialog->Show(); -} - -sub show_info { - my $self = shift; - $self->{status_line} = shift; - $self->{status_line_box}->configure(-bg => 'grey'); -} - -sub show_status { - my $self = shift; - $self->{status_line} = shift; - $self->{status_line_box}->configure(-bg => 'red'); -} - -sub start { - my $self = shift; - my (@args)=@_; - my $mw = $self->create_ui(); - if (@args) { - $self->{suite_name} = shift @args; - } - MainLoop; -} - -sub start_test { - my $self = shift; - my $test = shift; - $self->{number_of_runs} = $self->{result}->run_count(); - $self->show_info("Running: " . $test->name()); -} - -sub add_pass { - my $self = shift; - my ($test, $exception)=@_; - $self->update(); -} - -sub update { - my $self = shift; - my $result = $self->{result}; - my $total = $result->run_count(); - my $failures = $result->failure_count(); - my $errors = $result->error_count(); - my $passes = $total-$failures-$errors; - my $bad = $failures+$errors; - #$passes = $result->run_count(); - my $todo = ($total>$self->{planned})?0:$self->{planned}-$total; - $self->{progress_bar}->value($passes, $bad, $todo); - # force entry into the event loop. - # this makes it nearly like its threaded... - #sleep 1; - $self->{frame}->update(); -} - -sub add_to_history { - my $self = shift; - my $new_item = $self->{suite_name}; - my $h = $self->{suite_field}; - my $choices = $h->cget('-choices'); - my @choices = (); - if (ref($choices)) { - @choices=@{$h->cget('-choices')}; - } - elsif ($choices) { - # extraordinarily bad - choices is a scalar if theres - # only one, and undefined if there are none! - @choices = ($h->cget('-choices')); - } - @choices = ($new_item, grep {$_ ne $new_item} @choices); - if (@choices>10) { - @choices=@choices[0..9]; - } - $h->configure(-choices => \@choices); -} - -package Tk::ArrayBar; -# progressbar doesnt cut it. -# This expects a variable which is an array ref, and -# a matching list of colours. Sortof like stacked progress bars. -# Heavily - ie almost totally - based on the code in ProgressBar. -use Tk; -use Tk::Canvas; -use Tk::ROText; -use Tk::DialogBox; -use Carp; -use strict; - -use base qw(Tk::Derived Tk::Canvas); - -Construct Tk::Widget 'ArrayBar'; - -sub ClassInit { - my ($class, $mw) = @_; - - $class->SUPER::ClassInit($mw); - - $mw->bind($class, '', [ '_layoutRequest', 1 ]); -} - -sub Populate { - my($c, $args) = @_; - - $c->ConfigSpecs( - -width => [ PASSIVE => undef, undef, 0 ], - '-length' => [ PASSIVE => undef, undef, 0 ], - -padx => [ PASSIVE => 'padX', 'Pad', 0 ], - -pady => [ PASSIVE => 'padY', 'Pad', 0 ], - -colors => [ PASSIVE => undef, undef, undef ], - -relief => [ SELF => 'relief', 'Relief', 'sunken' ], - -value => [ METHOD => undef, undef, undef ], - -variable => [ PASSIVE => undef, undef, [ 0 ] ], - -anchor => [ METHOD => 'anchor', 'Anchor', 'w' ], - -resolution => [ PASSIVE => undef, undef, 1.0 ], - -highlightthickness => [ - SELF => 'highlightThickness', 'HighlightThickness', 0 - ], - -troughcolor => [ - PASSIVE => 'troughColor', 'Background', 'grey55' - ], - ); - - _layoutRequest($c, 1); - $c->OnDestroy([ Destroyed => $c ]); -} - -sub anchor { - my $c = shift; - my $var = \$c->{Configure}{'-anchor'}; - my $old = $$var; - - if (@_) { - my $new = shift; - croak "bad anchor position \"$new\": must be n, s, w or e" - unless $new =~ /^[news]$/; - $$var = $new; - } - - $old; -} - -sub _layoutRequest { - my $c = shift; - my $why = shift; - $c->afterIdle([ '_arrange', $c ]) unless $c->{layout_pending}; - $c->{layout_pending} |= $why; -} - -sub _arrange { - my $c = shift; - my $why = $c->{layout_pending}; - - $c->{layout_pending} = 0; - - my $w = $c->Width; - my $h = $c->Height; - my $bw = $c->cget('-borderwidth') + $c->cget('-highlightthickness'); - my $x = abs(int($c->{Configure}{'-padx'})) + $bw; - my $y = abs(int($c->{Configure}{'-pady'})) + $bw; - my $value = $c->cget('-variable'); - my $horz = $c->{Configure}{'-anchor'} =~ /[ew]/i ? 1 : 0; - my $dir = $c->{Configure}{'-anchor'} =~ /[ne]/i ? -1 : 1; - - if ($w == 1 && $h == 1) { - my $bw = $c->cget('-borderwidth'); - $h = $c->pixels($c->cget('-length')) || 40; - $w = $c->pixels($c->cget('-width')) || 20; - - ($w, $h) = ($h, $w) if $horz; - $c->GeometryRequest($w, $h); - $c->parent->update; - $c->update; - - $w = $c->Width; - $h = $c->Height; - } - - $w -= $x*2; - $h -= $y*2; - - my $length = $horz ? $w : $h; - my $width = $horz ? $h : $w; - # at this point we have the length and width of the - # bar independent of orientation and padding. - # blocks and gaps are not used. - - # unlike progressbar I need to redraw these each time. - # actually resizing them might be better... - my $colors = $c->{Configure}{'-colors'} || [ 'green', 'red', 'grey55' ]; - $c->delete($c->find('all')); - $c->createRectangle( - 0, 0, $w+$x*2, $h+$y*2, - -fill => $c->{Configure}{'-troughcolor'}, - -width => 0, - -outline => undef - ); - my $total; - my $count_value = scalar(@$value)-1; - foreach my $val (@$value) { - $total += $val > 0 ? $val : 0; - } - # prevent div by zero and give a nice initial appearance. - $total = $total ? $total : 1; - my $curx = $x; - my $cury = $y; - foreach my $index (0..$count_value) { - my $size = ($length*$value->[$index])/$total; - my $ud = $horz?$width:$size; - my $lr = $horz?$size:$width; - $c->{cover}->[$index] = $c->createRectangle( - $curx, $cury, $curx+$lr-1, $cury+$ud-1, - -fill => $colors->[$index], - -width => 1, - -outline => 'black' - ); - $curx+=$horz?$lr:0; - $cury+=$horz?0:$ud; - } -} - -sub value { - my $c = shift; - my $val = $c->cget('-variable'); - - if (@_) { - $c->configure(-variable => [@_]); - _layoutRequest($c, 2); - } -} - -sub Destroyed { - my $c = shift; - my $var = delete $c->{'-variable'}; - untie $$var if defined($var) && ref($var); -} - -1; -__END__ - - -=head1 NAME - -Test::Unit::TkTestRunner - unit testing framework helper class - -=head1 SYNOPSIS - - use Test::Unit::TkTestRunner; - Test::Unit::TkTestRunner::main($my_testcase_class); - -=head1 DESCRIPTION - -This class is the test runner for the GUI style use of the testing -framework. - -It is used by simple command line tools like the F -script provided. - -The class needs as arguments the names of the classes encapsulating -the tests to be run. - -=head1 AUTHOR - -Copyright (c) 2000-2002, 2005 the PerlUnit Development Team -(see L or the F file included in this -distribution). - -All rights reserved. This program is free software; you can -redistribute it and/or modify it under the same terms as Perl itself. - -=head1 SEE ALSO - -=over 4 - -=item * - -L - -=item * - -L - -=item * - -L - -=item * - -L - -=item * - -L - -=item * - -L - -=item * - -For further examples, take a look at the framework self test -collection (t::tlib::AllTests). - -=back - -=cut diff --git a/perl/third/Test-Unit-0.25/lib/Test/Unit/Tutorial.pm b/perl/third/Test-Unit-0.25/lib/Test/Unit/Tutorial.pm deleted file mode 100644 index f441b26..0000000 --- a/perl/third/Test-Unit-0.25/lib/Test/Unit/Tutorial.pm +++ /dev/null @@ -1,61 +0,0 @@ -package Test::Unit::Tutorial; - -# this is only a container for the Test::Unit tutorial -# to allow viewing tutorial-style documentation on -# unit testing by way of the perldoc utility. - -1; -__END__ - -=head1 NAME - -Test::Unit::Tutorial - Tutorial on unit testing - -=head1 SYNOPSIS - - perldoc Test::Unit::Tutorial - -=head1 DESCRIPTION - -Here should be extensive documentation on what unit testing is, why it -is useful, and how to do it with the Test::Unit collection of modules. - -Sorry for not implementing this yet. - -Please have a look at the examples in the examples directory and read -the F file that came with this distribution. - -A short tutorial on how to use the unit testing framework is included -in L. - -Further examples can be found by looking at the self test collection, -starting in t::tlib::AllTests. - -=head1 AUTHOR - -Christian Lemburg Elemburg@acm.orgE - -=head1 SEE ALSO - -=over 4 - -=item * - -The module documentation for all modules in the Test::Unit tree. - -=item * - -I -Martin Fowler. Addison-Wesley, 1999. - -=item * - -The JUnit (unit testing framework for Java) documentation. - -=item * - -http://www.xProgramming.com/ - -=back - -=cut diff --git a/perl/third/Test-Unit-0.25/lib/Test/Unit/UnitHarness.pm b/perl/third/Test-Unit-0.25/lib/Test/Unit/UnitHarness.pm deleted file mode 100644 index ae033f4..0000000 --- a/perl/third/Test-Unit-0.25/lib/Test/Unit/UnitHarness.pm +++ /dev/null @@ -1,236 +0,0 @@ -# This is a makeover of Test::Harness to allow its tests -# to be retrofitted as unit tests. -package Test::Unit::UnitHarness; - -BEGIN {require 5.002;} -use base qw(Test::Unit::Runner Test::Unit::Test Exporter); - -use Config; -use Carp; -use Class::Inner; -use FileHandle; - -use Test::Unit::Debug qw(debug); -use Test::Unit::TestCase; -use Test::Unit::Exception; - -use strict; - -use vars qw($VERSION $verbose $switches $have_devel_corestack $curtest - @EXPORT @EXPORT_OK); -$have_devel_corestack = 0; - -$VERSION = "1.1502"; - -@EXPORT = qw(&runtests); -@EXPORT_OK = qw($verbose $switches); - -$verbose = 0; -$switches = "-w"; - -# class and object methods - -sub new { - my $class = shift; - my ($name) = @_; - - my @_Tests = (); - my $self = { - _Tests => \@_Tests, - _Name => $name, - _Names => [], - }; - bless $self, $class; - debug(ref($self) . "::new($name) called\n"); - - return $self; -} - -sub run { - my $self = shift; - my $result = shift; - my $test = $self->{_Name}; - my $fh = new FileHandle; - my $next = 1; - my $max = 0; - my $message = ""; - - # pass -I flags to children - my $old5lib = $ENV{PERL5LIB}; - local($ENV{'PERL5LIB'}) = join($Config{path_sep}, @INC); - - if ($^O eq 'VMS') { $switches =~ s/-(\S*[A-Z]\S*)/"-$1"/g } - - $fh->open($test) or print "can't open $test. $!\n"; - my $first = <$fh>; - my $s = $switches; - $s .= q[ "-T"] if $first =~ /^#!.*\bperl.*-\w*T/; - $fh->close or print "can't close $test. $!\n"; - my $cmd = "$^X $s $test|"; - $cmd = "MCR $cmd" if $^O eq 'VMS'; - $fh->open($cmd) or print "can't run $test. $!\n"; - for my $line (<$fh>) { - print $line if $verbose; - - if ($line =~ /^1\.\.([0-9]+)/) { - # Not supported in Result - It's needed!!! - #$result->plan($1); - $next = 1; - $max = $1; - $message = ""; - } - elsif ($max && $line =~ /^(not\s+)?ok\b/) { - my $this = $next; - if ($line =~ /^not ok\s*(\d*)/) { - $this = $1 if $1 > 0; - my $testcase = new Test::Unit::TestCase("$test case $this"); - $result->start_test($testcase); - $result->add_failure( - Test::Unit::UnitHarness::TestCase->new("$test case $this"), - Test::Unit::UnitHarness::Exception->new($message) - ); - $result->end_test($testcase); - $message = ""; - } - elsif ($line =~ /^ok\s*(\d*)/) { - $this = $1 if $1; - my $testcase = - Test::Unit::UnitHarness::TestCase->new("$test case $this"); - $result->start_test($testcase); - $result->add_pass($testcase); - $result->end_test($testcase); - $message = ""; - } - $next++; - } - else { - # this is the message, not the medium... - # this wasnt part of the Test::Harness protocol, so it - # must be output from the program. Collect this, it might - # prove useful! - $message .= $line; - } - } - $fh->close; # must close to reap child resource values - if ($^O eq 'VMS') { - if (defined $old5lib) { - $ENV{PERL5LIB} = $old5lib; - } else { - delete $ENV{PERL5LIB}; - } - } -} - -sub name { - my $self = shift; - return $self->{_Name}; -} - -sub names { - my $self = shift; - return $self->{_Names}; -} - -sub add_test { - croak "This is suite is not mutable."; -} - -sub add_test_method { - croak "This suite is not mutable."; -} - -sub count_test_cases { - return 0; -} - -sub to_string { - my $self = shift; - return $self->{_Name}; -} - -sub warning { - my $self = shift; - my ($message) = @_; - return Class::Inner->new( - parent => 'Test::Unit::TestCase', - methods => { run_test => sub { (shift)->fail($message) } }, - args => ['warning'], - ); -} - -package Test::Unit::UnitHarness::TestCase; -use base qw(Test::Unit::TestCase); - -sub run_test { - my $self = shift; - my $class = ref($self); - my $method = $self->name(); - $self->fail("This test is not restartable"); -} - -package Test::Unit::UnitHarness::Exception; -use base qw(Test::Unit::Exception); -use strict; - -sub new { - my $class = shift; - my ($message) = @_; - my $stacktrace = ''; - - $message = '' unless defined($message); - $stacktrace = $class . ": Output from external test\n" - . $message . "\n"; - - bless { stacktrace => $stacktrace }, $class; -} - -sub stacktrace { - my $self = shift; - return $self->{stacktrace}; -} - -1; - -__END__ - -=head1 NAME - -Test::Unit::UnitHarness - unit testing framework helper class - -=head1 SYNOPSIS - -This class is not intended to be used directly - -=head1 DESCRIPTION - -This is a makeover of Test::Harness to allow its tests to be -retrofitted as unit tests. - -=head1 AUTHOR - -Copyright (c) 2000-2002, 2005 the PerlUnit Development Team -(see L or the F file included in this -distribution). - -All rights reserved. This program is free software; you can -redistribute it and/or modify it under the same terms as Perl itself. - -=head1 SEE ALSO - -=over 4 - -=item * - -L - -=item * - -L - -=item * - -L - -=back - -=cut diff --git a/perl/third/Test-Unit-0.25/lib/Test/Unit/Warning.pm b/perl/third/Test-Unit-0.25/lib/Test/Unit/Warning.pm deleted file mode 100644 index 3acf4c2..0000000 --- a/perl/third/Test-Unit-0.25/lib/Test/Unit/Warning.pm +++ /dev/null @@ -1,42 +0,0 @@ -package Test::Unit::Warning; - -use strict; -use base 'Test::Unit::TestCase'; - -=head1 NAME - -Test::Unit::Warning - helper TestCase for adding warnings to a suite - -=head1 DESCRIPTION - -Used by L and others to provide messages that -come up when the suite runs. - -=cut - -sub run_test { - my $self = shift; - $self->fail($self->{_message}); -} - -sub new { - my $class = shift; - my $self = $class->SUPER::new('warning'); - $self->{_message} = shift; - return $self; -} - -1; - - -=head1 AUTHOR - -Copyright (c) 2000-2002, 2005 the PerlUnit Development Team -(see L or the F file included in this -distribution). - -All rights reserved. This program is free software; you can -redistribute it and/or modify it under the same terms as Perl itself. - -=cut - diff --git a/perl/third/Test-Unit-0.25/t/all_tests.t b/perl/third/Test-Unit-0.25/t/all_tests.t deleted file mode 100644 index f55d5cd..0000000 --- a/perl/third/Test-Unit-0.25/t/all_tests.t +++ /dev/null @@ -1,13 +0,0 @@ -#!/usr/bin/perl -w - -use strict; - -use Test::Unit::Debug qw(debug_pkgs); -use Test::Unit::HarnessUnit; - -#debug_pkgs(qw{Test::Unit::Result}); - -use lib 't/tlib', 'tlib'; - -my $testrunner = Test::Unit::HarnessUnit->new(); -$testrunner->start("AllTests"); diff --git a/perl/third/Test-Unit-0.25/t/assert.t b/perl/third/Test-Unit-0.25/t/assert.t deleted file mode 100644 index c87d2de..0000000 --- a/perl/third/Test-Unit-0.25/t/assert.t +++ /dev/null @@ -1,14 +0,0 @@ -#!/usr/bin/perl -w - -use strict; - -use Test::Unit::HarnessUnit; -use Test::Unit::Debug qw(debug_pkgs); - -#debug_pkgs(qw/Test::Unit::Assert/); -#debug_pkgs(qw/Test::Unit::Assertion::CodeRef/); - -use lib 't/tlib', 'tlib'; - -my $testrunner = Test::Unit::HarnessUnit->new(); -$testrunner->start("AssertTest"); diff --git a/perl/third/Test-Unit-0.25/t/tlib/ActiveTestTest.pm b/perl/third/Test-Unit-0.25/t/tlib/ActiveTestTest.pm deleted file mode 100644 index 4fbff4a..0000000 --- a/perl/third/Test-Unit-0.25/t/tlib/ActiveTestTest.pm +++ /dev/null @@ -1,60 +0,0 @@ -package ActiveTestTest; - -use strict; - -use Test::Unit::TestCase (); -use base 'Test::Unit::TestCase'; -use Test::Unit::Result; -use Test::Unit::TestSuite (); -use Success; - -sub testActiveTest { - my $self = shift; - my $test = $self->create_active_test_suite; - my $result = Test::Unit::Result->new; - $test->run($result); - $self->assert_equals(100, $result->run_count); - $self->assert_equals(0, $result->failure_count); - $self->assert_equals(0, $result->error_count); -} - -# sub test_active_repeated_test { -# my $self = shift; -# my $test = Test::Unit::RepeatedTest($self->create_active_test_suite, 5); -# my $result = Result->new; -# $test->run($result); -# $self->assert_equals(500, $result->run_count); -# $self->assert_equals(0, $result->failure_count); -# $self->assert_equals(0, $result->error_count); -# } - -# sub test_active_repeated_test0 { -# my $self = shift; -# my $test = Test::Unit::RepeatedTest($self->create_active_test_suite, 0); -# my $result = Result->new; -# $test->run($result); -# $self->assert_equals(0, $result->run_count); -# $self->assert_equals(0, $result->failure_count); -# $self->assert_equals(0, $result->error_count); -# } - -# sub test_active_repeated_test1 { -# my $self = shift; -# my $test = Test::Unit::RepeatedTest($self->create_active_test_suite, 1); -# my $result = Result->new; -# $test->run($result); -# $self->assert_equals(100, $result->run_count); -# $self->assert_equals(0, $result->failure_count); -# $self->assert_equals(0, $result->error_count); -# } - -sub create_active_test_suite () { - my $self = shift; - my $suite = Test::Unit::TestSuite->new; - for (1 .. 100) { - $suite->add_test(Success->new("test_success")); - } - return $suite; -} - -1; diff --git a/perl/third/Test-Unit-0.25/t/tlib/AllTests.pm b/perl/third/Test-Unit-0.25/t/tlib/AllTests.pm deleted file mode 100644 index 9cbaac9..0000000 --- a/perl/third/Test-Unit-0.25/t/tlib/AllTests.pm +++ /dev/null @@ -1,86 +0,0 @@ -package AllTests; - -use Test::Unit::TestSuite; -use SuiteTest; -use InheritedSuite::Simple; -use InheritedSuite::TestNames; - -sub new { - my $class = shift; - return bless {}, $class; -} - -sub suite { - my $class = shift; - my $suite = Test::Unit::TestSuite->empty_new("Framework Tests"); - - # We now add the various test cases and suites to this suite - # in deliberately different ways, so as to implicitly test - # the different interfaces by which one can add/construct tests. - - # Add test cases in 3 different ways. The first 3 extract all - # test_* methods, and the last extracts only 1 method. - $suite->add_test(Test::Unit::TestSuite->new('TestTest')); - $suite->add_test('ListenerTest'); - $suite->add_test('BadSuitesTest'); - $suite->add_test('RunnerTest'); - $suite->add_test('WillDie'); - $suite->add_test(InheritedSuite::TestNames->new('test_names')); - - # Add test suites in 4 different ways. - $suite->add_test(SuiteTest->suite()); - $suite->add_test(InheritedSuite::Simple->new()); - $suite->add_test('InheritedSuite::OverrideNew'); -# $suite->add_test(Test::Unit::TestSuite->new('InheritedSuite::OverrideNewName')); - - return $suite; -} - -1; -__END__ - - -=head1 NAME - -AllTests - unit testing framework self tests - -=head1 SYNOPSIS - - # command line style use - - perl TestRunner.pl AllTests - - # GUI style use - - perl TkTestRunner.pl AllTests - - -=head1 DESCRIPTION - -This class is used by the unit testing framework to encapsulate all -the self tests of the framework. - -=head1 AUTHOR - -Copyright (c) 2000-2002, 2005 the PerlUnit Development Team -(see L or the F file included in this -distribution). - -All rights reserved. This program is free software; you can -redistribute it and/or modify it under the same terms as Perl itself. - -=head1 SEE ALSO - -=over 4 - -=item * - -L - -=item * - -L - -=back - -=cut diff --git a/perl/third/Test-Unit-0.25/t/tlib/AssertTest.pm b/perl/third/Test-Unit-0.25/t/tlib/AssertTest.pm deleted file mode 100644 index 5307aea..0000000 --- a/perl/third/Test-Unit-0.25/t/tlib/AssertTest.pm +++ /dev/null @@ -1,584 +0,0 @@ -package AssertTest; - -use strict; - -use ExceptionChecker; -use TestObject; -use Test::Unit::TestCase; -use Test::Unit::Failure; -use Test::Unit::Error; - -use Error qw/:try/; -use Class::Inner; - -use vars qw/@ISA/; -@ISA = qw(Test::Unit::TestCase ExceptionChecker); - - -sub test_assert_equals { - my $self = shift; - my $o = TestObject->new(); - $self->assert_equals($o, $o); - - $self->check_failures - ("expected 'start o:MyClass=HASH(0x1404343f0) | any o:MyClass=HASH(0x1404343f0) e:start | any o:MyClass=HASH(0x1404343f0) e:in', got 'start o: e: | any o:start e: | any o:in e:'" => - # A false-negative that burned me; problem with is_numeric - # Test must be all on one line - [ __LINE__, sub { shift->assert_equals("start o:MyClass=HASH(0x1404343f0) | any o:MyClass=HASH(0x1404343f0) e:start | any o:MyClass=HASH(0x1404343f0) e:in", "start o: e: | any o:start e: | any o:in e:"); } ], - ); -} - -# ...and the root of that problem in test_assert_equals -sub test_numericness { - my $self = shift; - my %tests = - ( 1 => 't', - 0 => 't', - '0xF00' => 'f', # controversial? but if you +=10 then it's == 10 - '15e7' => 't', - '15E7' => 't', - "not 0" => 'f', - "not 4" => 'f', - " \n 5E2" => 't', - " \t 0E0 " => 't', - ); - foreach my $str (keys %tests) { - my $expect = $tests{$str}; - my $actual = Test::Unit::Assert::is_numeric($str) ? 't' : 'f'; - $self->fail("For string '$str', expect $expect but got $actual") - unless $expect eq $actual; - } -} - - -sub test_assert { - my $self = shift; - $self->assert(1); - $self->assert(1, 'should be true'); - $self->assert(qr/foo/, 'foobar'); - $self->assert(qr/foo/, 'foobar', 'should match /foo/'); - my $coderef = sub { - $_[0] eq $_[1] or $self->fail("$_[0] ne $_[1]"); - }; - $self->assert($coderef, 'a', 'a'); - $self->assert([]); - $self->assert([ 'foo', 7 ]); - $self->check_failures( - 'Boolean assertion failed' => [ __LINE__, sub { shift->assert(undef) } ], - 'Boolean assertion failed' => [ __LINE__, sub { shift->assert(0) } ], - 'Boolean assertion failed' => [ __LINE__, sub { shift->assert('') } ], - - 'bang' => [ __LINE__, sub { shift->assert(0, 'bang') } ], - 'bang' => [ __LINE__, sub { shift->assert('', 'bang') } ], - "'qux' did not match /(?-xism:foo)/" - => [ __LINE__, sub { shift->assert(qr/foo/, 'qux') } ], - 'bang' => [ __LINE__, sub { shift->assert(qr/foo/, 'qux', 'bang') } ], - 'a ne b'=> [ __LINE__, sub { shift->assert($coderef, 'a', 'b') } ], - ); -} - -sub test_assert_str_equals { - my $self = shift; - my @pass = ( - ['', ''], - [0, 0], - [1, 1], - ['foo', 'foo'], - ); - foreach my $pair (@pass) { - my ($expected, $got) = @$pair; - $self->assert_str_equals($expected, $got); - $self->assert_str_equals($expected, $got, 'failure message'); - } - $self->check_failures( - 'expected value was undef; should be using assert_null?' => - [ __LINE__, sub { shift->assert_str_equals(undef, undef) } ], - 'expected value was undef; should be using assert_null?' => - [ __LINE__, sub { shift->assert_str_equals(undef, 0) } ], - 'expected value was undef; should be using assert_null?' => - [ __LINE__, sub { shift->assert_str_equals(undef, '') } ], - 'expected value was undef; should be using assert_null?' => - [ __LINE__, sub { shift->assert_str_equals(undef, 'foo') } ], - "expected '', got undef" => - [ __LINE__, sub { shift->assert_str_equals('', undef) } ], - "expected 'foo', got undef" => - [ __LINE__, sub { shift->assert_str_equals('foo', undef) } ], - "expected '', got '0'" => - [ __LINE__, sub { shift->assert_str_equals('', 0) } ], - "expected '0', got ''" => - [ __LINE__, sub { shift->assert_str_equals(0, '') } ], - "expected '0', got undef" => - [ __LINE__, sub { shift->assert_str_equals(0, undef) } ], - "expected '0', got '1'" => - [ __LINE__, sub { shift->assert_str_equals(0, 1) } ], - "expected '0', got '-0'" => - [ __LINE__, sub { shift->assert_str_equals(0, '-0') } ], - "expected '-0', got '0'" => - [ __LINE__, sub { shift->assert_str_equals('-0', 0) } ], - "expected 'foo', got 'bar'" => - [ __LINE__, sub { shift->assert_str_equals('foo', 'bar') } ], - - ); -} - -sub test_multi_assert { - my $self = shift; - my $assertion = sub { - $_[0] =~ /1/ - or Test::Unit::Failure->throw(-text => "first arg missing 1"); - $_[1] eq 'cluck' - or Test::Unit::Failure->throw(-text => "what? no chickens!?"); - }; - - $self->multi_assert( - $assertion, - [ 1, 'cluck' ], - [ 'el1te', 'cluck' ], - ); - - $self->check_failures( - 'first arg missing 1' - => [ __LINE__, sub { shift->multi_assert($assertion, [ 2, 'cluck' ]) - } ], - 'what? no chickens!?' - => [ __LINE__, sub { shift->multi_assert($assertion, [ 1, 'cluck' ], - [ 1, 'moo' ]) - } ], - ); - -} - -sub test_assert_matches { - my $self = shift; - $self->assert_matches(qr/ob/i, 'fooBar'); - $self->check_errors( - 'arg 1 to assert_matches() must be a regexp' - => [ __LINE__, sub { shift->assert_matches(1, 2) } ] - ); -} - -sub test_assert_does_not_match { - my $self = shift; - $self->assert_does_not_match(qr/ob/, 'fooBar'); - $self->check_errors( - 'arg 1 to assert_does_not_match() must be a regexp' - => [ __LINE__, sub { shift->assert_does_not_match(1, 2) } ] - ); -} - -sub test_assert_equals_null { - my $self = shift; - $self->assert_equals(undef, undef); -} - -# sub assertion_has_failed { -# my $error = shift; -# return eval {ref($error) && $error->isa('Test::Unit::Failure')}; -# } - -# Not sure this has meaning in Perl -# sub test_assert_null_not_equals_null { -# my $self = shift; -# eval { $self->assert_equals(undef, TestObject->new()) }; -# $self->fail unless assertion_has_failed($@); -# } - -@AssertTest::Exception::ISA = 'Error'; -sub test_assert_raises { - my $self = shift; - $self->assert_raises( - 'AssertTest::Exception', - sub { AssertTest::Exception->throw(-text => 'boom'); } - ); - $self->assert_str_equals('boom', AssertTest::Exception->prior->{-text}); - $self->assert_raises( - 'Error::Simple', - sub { die "bang"; } - ); - $self->assert_str_equals('bang', AssertTest::Exception->prior->{-text}); - $self->check_failures( - 'No AssertTest::Exception was raised' - => [ - __LINE__ + 1, - sub { shift->assert_raises('AssertTest::Exception', sub {}) } - ], - 'zxc' - => [ - __LINE__ + 1, - sub { shift->assert_raises('AssertTest::Exception', sub {}, 'zxc') } - ], - ); -} - -sub test_ok_boolean { - my $self = shift; - $self->ok(1); - $self->check_failures( - 'Boolean assertion failed' => [ __LINE__, sub { shift->ok(0) } ], - 'Boolean assertion failed' => [ __LINE__, sub { shift->ok('') } ], - 'Boolean assertion failed' => [ __LINE__, sub { shift->ok(undef) } ], - ); -} - -sub test_ok_bad_args { - my $self = shift; - $self->check_errors( - 'ok() called with wrong number of args' - => [ __LINE__, sub { shift->ok() } ], - 'ok() called with wrong number of args' - => [ __LINE__, sub { shift->ok(1, 2, 3, 4) } ], - ); -} - -sub test_ok_equals { - my $self = shift; - foreach my $args ([0, 0], [2, 2], [1.34, 1.34], - ['foo', 'foo'], ['', ''], [undef, undef], - [sub {2+2}, 4], ['fixed', qr/x/]) { - $self->ok(@$args); - $self->ok(@$args, 'comment'); - } -} - -sub test_ok_not_equals { - my $self = shift; - my $adder = sub { 2+2 }; - my @checks = ( - # interface is ok(GOT, EXPECTED); - q{expected 1, got 0} => [ 0, 1 ], - q{expected 0, got 1} => [ 1, 0 ], - q{expected 3, got 2} => [ 2, 3 ], - q{expected -57.001, got -57} => [ -57, -57.001 ], - q{expected 'bar', got 'foo'} => [ 'foo', 'bar' ], - q{expected '', got 'foo'} => [ 'foo', '' ], - q{expected 'foo', got ''} => [ '', 'foo' ], - q{expected 5, got 4} => [ $adder, 5 ], - q{'foo' did not match /(?-xism:x)/} => [ 'foo', qr/x/ ], - ); - my @tests = (); - while (@checks) { - my $expected = shift @checks; - my $args = shift @checks; - push @tests, $expected => [ __LINE__, sub { shift->ok(@$args) } ]; - push @tests, 'failure comment' - => [ __LINE__, sub { shift->ok(@$args, 'failure comment') } ]; - } - $self->check_failures(@tests); -} - -sub test_fail { - my $self = shift; - $self->check_failures( - '' => [ __LINE__, sub { shift->fail() } ], - 'failure message' => [ __LINE__, sub { shift->fail('failure message') } ], - ); -} - -sub test_succeed_assert_null { - my $self = shift; - $self->assert_null(undef); -} - -sub test_fail_assert_null { - my $self = shift; - $self->check_failures( - 'Defined is defined' - => [ __LINE__, sub { shift->assert_null('Defined') } ], - 'Weirdness' - => [ __LINE__, sub { shift->assert_null('Defined', 'Weirdness') } ], - ); -} - -sub test_success_assert_not_equals { - my $self = shift; - $self->assert_not_equals(1, 0); - $self->assert_not_equals(0, 1); - $self->assert_not_equals(0, 1E10); - $self->assert_not_equals(1E10, 0); - $self->assert_not_equals(1, 2); - $self->assert_not_equals('string', 1); - $self->assert_not_equals(1, 'string'); - $self->assert_not_equals('string', 0); - # $self->assert_not_equals(0,'string'); # Numeric comparison done here.. - # $self->assert_not_equals(0, ''); # Numeric comparison done here.. - $self->assert_not_equals('', 0); - $self->assert_not_equals(undef, 0); - $self->assert_not_equals(0, undef); - # $self->assert_not_equals(0, ''); FIXME - $self->assert_not_equals(undef, ''); - $self->assert_not_equals('', undef); -} - -sub test_fail_assert_not_equals { - my $self = shift; - my @pairs = ( - # Some of these are debatable, but at least including the tests - # will alert us if any of the outcomes change. - "0 and 0 should differ" => [ 0, 0 ], - "0 and 0 should differ" => [ 0, '0' ], - "0 and 0 should differ" => [ '0', 0 ], - "0 and 0 should differ" => [ '0', '0' ], - "1 and 1 should differ" => [ 1, 1 ], - "1 and 1 should differ" => [ 1, '1' ], - "1 and 1 should differ" => [ '1', 1 ], - "1 and 1 should differ" => [ '1', '1' ], - "0 and should differ" => [ 0, '' ], # Numeric comparison - "0 and string should differ" => [ 0, 'string' ], # Numeric comparison - "'' and '' should differ" => [ '', '' ], - "both args were undefined" => [ undef, undef ], - ); - my @tests = (); - while (@pairs) { - my $expected = shift @pairs; - my $pair = shift @pairs; - push @tests, $expected - => [ __LINE__, sub { shift->assert_not_equals(@$pair) } ]; - push @tests, "$expected with comment", - => [ __LINE__, sub { shift->assert_not_equals(@$pair, - "$expected with comment") } ]; - } - $self->check_failures(@tests); -} - -sub test_fail_assert_not_null { - my $self = shift; - $self->check_failures( - ' unexpected' - => [ __LINE__, sub { shift->assert_not_null(undef) } ], - ' unexpected' - => [ __LINE__, sub { shift->assert_not_null() } ], - # nb. $self->assert_not_null(@emptylist, "message") is not - # going to do what you expected! - 'Weirdness' - => [ __LINE__, sub { shift->assert_not_null(undef, 'Weirdness') } ] - ); -} - -sub test_succeed_assert_not_null { - my $self = shift; - $self->assert_not_null(TestObject->new); - $self->assert_not_null(''); - $self->assert_not_null('undef'); - $self->assert_not_null(0); - $self->assert_not_null(10); -} - -sub test_assert_deep_equals { - my $self = shift; - - $self->assert_deep_equals([], []); - $self->assert_deep_equals({}, {}); - $self->assert_deep_equals([ 0, 3, 5 ], [ 0, 3, 5 ]); - my $hashref = { a => 2, b => 4 }; - $self->assert_deep_equals($hashref, $hashref); - $self->assert_deep_equals($hashref, { b => 4, a => 2 }); - my $complex = { - array => [ 1, $hashref, 3 ], - undefined => undef, - number => 3.2, - string => 'hi mom', - deeper => { - and => [ - even => [ qw(deeper wahhhhh) ], - { foo => 11, bar => 12 } - ], - }, - }; - $self->assert_deep_equals( - $complex, - { - array => [ 1, $hashref, 3 ], - undefined => undef, - number => 3.2, - string => 'hi mom', - deeper => { - and => [ - even => [ qw(deeper wahhhhh) ], - { - foo => 11, bar => 12 } - ], - }, - }, - ); - - my $differ = sub { - my ($a, $b) = @_; - qr/^Structures\ begin\ differing\ at: $ \n - \S*\s* \$a .* = .* (?-x:$a) .* $ \n - \S*\s* \$b .* = .* (?-x:$b)/mx; - }; - - my %families; # key=test-purpose, value=assorted circular structures - foreach my $key (qw(orig copy bad_copy)) { - my %family = ( john => { name => 'John Doe', - spouse => undef, - children => [], - }, - jane => { name => 'Jane Doe', - spouse => undef, - children => [], - }, - baby => { name => 'Baby Doll', -# spouse => undef, - children => [], - }, - ); - $family{john}{spouse} = $family{jane}; - $family{jane}{spouse} = $family{john}; - push @{$family{john}{children}}, $family{baby}; - push @{$family{jane}{children}}, $family{baby}; - $families{$key} = \%family; - } - $families{bad_copy}->{jane}{spouse} = $families{bad_copy}->{baby}; # was ->{john} - - # Breakage under test is infinite recursion, to memory exhaustion! - # Jump through hoops to avoid killing people's boxes - { - my $old_isa = \&UNIVERSAL::isa; - # Pick on isa() because it'll be called from any deep-ing code - local $^W = 0; - local *UNIVERSAL::isa = sub { - die "Giving up on deep recursion for assert_deep_equals" - if defined caller(500); - return $old_isa->(@_); - }; - $self->assert_deep_equals($families{orig}, $families{copy}); - } - - my ($H, $H2, $G) = qw(hello hello goodbye); - - my @pairs = ( - 'Both arguments were not references' => [ undef, 0 ], - 'Both arguments were not references' => [ 0, undef ], - 'Both arguments were not references' => [ 0, 1 ], - 'Both arguments were not references' => [ 0, '' ], - 'Both arguments were not references' => [ '', 0 ], - $differ->(qw/'ARRAY 'HASH/) => [ [], {} ], - $differ->(qw/'ARRAY 'HASH/) => [ [1,2], {1,2} ], - $differ->( "'ARRAY", " undef" ) => [ { 'test' => []}, - { 'test' => undef } ], - $differ->( "'ARRAY", 'not exist' ) => [ { 'test' => []}, {} ], - $differ->( 'undef', "'ARRAY" ) => [ { 'test' => undef }, - { 'test' => []} ], - $differ->( "''", " undef" ) => [ [ '' ], [ undef ] ], - $differ->( "'undef'", " undef" ) => [ [ 'undef' ], [ undef ] ], - $differ->('not exist', "'3'") => [ [1,2], [1,2,3] ], - $differ->("'3'", "not exist") => [ [1,2,3], [1,2] ], - $differ->("'wahhhhh'", "'wahhhh'") => [ - $complex, - { - array => [ 1, $hashref, 3 ], - undefined => undef, - number => 3.2, - string => 'hi mom', - deeper => { - and => [ - even => [ qw(deeper wahhhh) ], - { foo => 11, bar => 12 } - ], - }, - } - ], - $differ->( 'HASH', 'not exist') => [$families{orig}, $families{bad_copy}], # test may be fragile due to recursion ordering? - $differ->("'3'", "'5'") => [ [ \$H, 3 ], [ \$H2, 5 ] ], - $differ->("'hello'", "'goodbye'") => [ { world => \$H }, { world => \$G } ], - $differ->("'hello'", "'goodbye'") => [ [ \$H, "world" ], [ \$G, "world" ] ], - ); - - my @tests = (); - while (@pairs) { - my $expected = shift @pairs; - my $pair = shift @pairs; - push @tests, $expected, - [ __LINE__, sub { shift->assert_deep_equals(@$pair) } ]; - push @tests, "$expected with comment", - [ __LINE__, sub { shift->assert_deep_equals(@$pair, - "$expected with comment") } ]; - } - $self->check_failures(@tests); -} - -# Key = assert_method -# Value = [[@arg_list],undef/expected exception] -# FIXME: These should probably be merged with the tests for assert_not_equals() -# somehow, since the failures aren't currently tested for the correct message -# via check_exception(), or originating file/line via check_file_and_line(). -my %test_hash = ( - assert_equals => { - success => [ - { args => [0,'foo'], name => "0 == 'foo'" }, - { args => [1,'1.0'], name => "1 == '1.0'" }, - { args => ['1.0', 1], name => "'1.0' == 1" }, - { args => ['foo', 'foo'], name => 'foo eq foo' }, - { args => ['0e0', 0], name => '0E0 == 0' }, - { args => [0, 'foo'], name => "0 == 'foo'" }, - { args => [undef, undef], name => "both undef" }, - { args => [0, 0], name => "0 == 0" }, - { args => [0, 0.0], name => "0 == 0.0" }, - { args => [0.0, 0], name => "0.0 == 0" }, - { args => [0.0, 0.0], name => "0.0 == 0.0" }, - { args => ['', ''], name => "'' == ''" }, - ], - 'Test::Unit::Failure' => [ - { args => [1,'foo'], name => "1 != 'foo'" }, - { args => ['foo', 0], name => "'foo' ne 0" }, - { args => ['foo', 1], name => "'foo' ne 1" }, - { args => [0,1], name => "0 != 1" }, - { args => ['foo', 'bar'], name => "'foo' ne 'bar'" }, - { args => ['foo', undef], name => "'foo' ne undef" }, - { args => [undef, 'foo'], name => "undef ne 'foo'" }, - # { args => [0, ''], name => "0 ne ''" }, # numeric compare - - ], - }, -); - -sub suite { - my $self = shift; - my $suite = Test::Unit::TestSuite->empty_new("Assertion Tests"); - foreach my $test ($self->make_tests_from_matrix(\%test_hash)) { - $suite->add_test($test); - } - foreach my $test ($self->list_tests) { - no strict 'refs'; - $suite->add_test($self->make_test_from_coderef(sub {my $self = shift; $self->$test(@_)},$test)); - } - return $suite; -} - - -sub make_tests_from_matrix { - my $self = shift; - my $matrix = shift; - my @tests; - foreach my $method_name (keys %$matrix) { - # Build 'successful' tests. - foreach my $spec (@{$matrix->{$method_name}{success}}) { - push @tests, $self->make_test_from_coderef - (sub { - my $self = shift; - $self->$method_name(@{$spec->{args}}); - }, $spec->{name}); - } - - foreach my $outcome (grep {$_ ne 'success'} keys %{$matrix->{$method_name}}) { - foreach my $spec (@{$matrix->{$method_name}{$outcome}}) { - push @tests, $self->make_test_from_coderef - (sub { - my $self = shift; - try { - $self->$method_name(@{$spec->{args}}); - 0; - } - catch $outcome with { - 1; - } or Test::Unit::Failure->throw(-text => $spec->{name}, - -object => $self); - }, $spec->{name}); - } - } - } - return @tests; -} - -1; diff --git a/perl/third/Test-Unit-0.25/t/tlib/BadSuite/BadUse.pm b/perl/third/Test-Unit-0.25/t/tlib/BadSuite/BadUse.pm deleted file mode 100644 index 214d80e..0000000 --- a/perl/third/Test-Unit-0.25/t/tlib/BadSuite/BadUse.pm +++ /dev/null @@ -1,5 +0,0 @@ -package BadSuite::BadUse; - -use TestSuite::NonExistent; - -1; diff --git a/perl/third/Test-Unit-0.25/t/tlib/BadSuite/SyntaxError.pm b/perl/third/Test-Unit-0.25/t/tlib/BadSuite/SyntaxError.pm deleted file mode 100644 index 4e682da..0000000 --- a/perl/third/Test-Unit-0.25/t/tlib/BadSuite/SyntaxError.pm +++ /dev/null @@ -1,7 +0,0 @@ -package BadSuite::SyntaxError; - -sub broken_method { - my $self = -} - -1; diff --git a/perl/third/Test-Unit-0.25/t/tlib/BadSuitesTest.pm b/perl/third/Test-Unit-0.25/t/tlib/BadSuitesTest.pm deleted file mode 100644 index ea398ad..0000000 --- a/perl/third/Test-Unit-0.25/t/tlib/BadSuitesTest.pm +++ /dev/null @@ -1,28 +0,0 @@ -package BadSuitesTest; - -use strict; - -use Test::Unit::TestCase; -use Test::Unit::TestRunner; - -use base 'Test::Unit::TestCase'; - -sub test_suite_with_syntax_error { - my $self = shift; - my $runner = Test::Unit::TestRunner->new(); - eval { - $runner->start('BadSuite::SyntaxError'); - }; - $self->assert(qr!^syntax error at .*/SyntaxError\.pm!, "$@"); -} - -sub test_suite_with_bad_use { - my $self = shift; - my $runner = Test::Unit::TestRunner->new(); - eval { - $runner->start('BadSuite::BadUse'); - }; - $self->assert(qr!^Can't locate TestSuite/NonExistent\.pm in \@INC!, "$@"); -} - -1; diff --git a/perl/third/Test-Unit-0.25/t/tlib/ExceptionChecker.pm b/perl/third/Test-Unit-0.25/t/tlib/ExceptionChecker.pm deleted file mode 100644 index ee07cd8..0000000 --- a/perl/third/Test-Unit-0.25/t/tlib/ExceptionChecker.pm +++ /dev/null @@ -1,100 +0,0 @@ -package ExceptionChecker; - -use strict; -use warnings; - -use Test::Unit::Error; -use Test::Unit::Failure; - -use Error qw(:try); - -sub check_failures { - my $self = shift; - $self->check_exceptions('Test::Unit::Failure', @_); -} - -sub check_errors { - my $self = shift; - $self->check_exceptions('Test::Unit::Error', @_); -} - -sub check_exceptions { - my $self = shift; - my ($exception_class, @tests) = @_; - my ($asserter, $file, $line) - = caller($Error::Depth + 1); # EVIL hack! Assumes check_exceptions - # always called via check_{failures,errors}. - # My brain hurts too much right now to think - # of a better way. - while (@tests) { - my $expected = shift @tests; - my $test_components = shift @tests; - my ($test_code_line, $test) = @$test_components; - my $exception; - try { - $self->$test(); - } - catch $exception_class with { - $exception = shift; - } - catch Error::Simple with { - $exception = shift; - } - otherwise { - $exception = 0; - }; - - try { - $self->check_exception($exception_class, $expected, $exception); - $self->check_file_and_line($exception, - $file, - $test_code_line); - } - catch Test::Unit::Failure with { - my $failure = shift; - $failure->throw_new( - -package => $asserter, - -file => $file, - -line => $line, - -object => $self - ); - } - } -} - -sub check_exception { - my $self = shift; - my ($exception_class, $expected, $exception) = @_; - Test::Unit::Failure->throw( - -text => "Didn't get $exception_class `$expected'", - -object => $self, - ) unless $exception; - - my $got = $exception->text(); - Test::Unit::Failure->throw( - -text => "Expected $exception_class `$expected', got `$got'", - -object => $self, - ) unless UNIVERSAL::isa($expected, 'Regexp') - ? $got =~ /$expected/ : $got eq $expected; -} - -sub check_file_and_line { - my $self = shift; - my ($exception, $expected_file, $test_code_line) = @_; - if ($exception->file() ne $expected_file) { - throw Test::Unit::Failure( - -text => "failure's file() should have returned $expected_file" - . " (line $test_code_line), not " . $exception->file(), - -object => $self, - ); - } - if ($exception->line() != $test_code_line) { - throw Test::Unit::Failure( - -text => "failure's line() should have returned " - . "$test_code_line, not " . $exception->line(), - -object => $self, - ); - } -} - -1; diff --git a/perl/third/Test-Unit-0.25/t/tlib/FilteredSuite.pm b/perl/third/Test-Unit-0.25/t/tlib/FilteredSuite.pm deleted file mode 100644 index d86d9ba..0000000 --- a/perl/third/Test-Unit-0.25/t/tlib/FilteredSuite.pm +++ /dev/null @@ -1,36 +0,0 @@ -package FilteredSuite; - -use base 'Test::Unit::TestCase'; - -sub filter {{ - token_filtering_via_method_list => [ - qw/test_filtered_method1 test_filtered_method2/ - ], - token_filtering_via_sub => sub { - my ($method) = @_; - return 1 if $method =~ /method3$/; - }, - broken_token => 'nonsense', -}} - -sub test_filtered_method1 { - my $self = shift; - die "test_filtered_method1 should get filtered via method list"; -} - -sub test_filtered_method2 { - my $self = shift; - die "test_filtered_method2 should get filtered via method list"; -} - -sub test_filtered_method3 { - my $self = shift; - die "test_filtered_method3 should get filtered via sub"; -} - -sub test_unfiltered_method1 { - my $self = shift; - $self->assert('trooooo'); -} - -1; diff --git a/perl/third/Test-Unit-0.25/t/tlib/InheritedInheritedTestCase.pm b/perl/third/Test-Unit-0.25/t/tlib/InheritedInheritedTestCase.pm deleted file mode 100644 index d0feec5..0000000 --- a/perl/third/Test-Unit-0.25/t/tlib/InheritedInheritedTestCase.pm +++ /dev/null @@ -1,14 +0,0 @@ -package InheritedInheritedTestCase; - -# Test class used in SuiteTest - -use base qw(InheritedTestCase); - -sub new { - shift()->SUPER::new(@_); -} - -sub test3 { -} - -1; diff --git a/perl/third/Test-Unit-0.25/t/tlib/InheritedSuite/OverrideNew.pm b/perl/third/Test-Unit-0.25/t/tlib/InheritedSuite/OverrideNew.pm deleted file mode 100644 index 94171b4..0000000 --- a/perl/third/Test-Unit-0.25/t/tlib/InheritedSuite/OverrideNew.pm +++ /dev/null @@ -1,14 +0,0 @@ -package InheritedSuite::OverrideNew; - -use strict; - -use base qw(Test::Unit::TestSuite); - -sub new { - my $class = shift; - my $self = $class->SUPER::empty_new('Inherited suite overriding new()'); - $self->add_test(Test::Unit::TestSuite->new('Success')); - return $self; -} - -1; diff --git a/perl/third/Test-Unit-0.25/t/tlib/InheritedSuite/OverrideNewName.pm b/perl/third/Test-Unit-0.25/t/tlib/InheritedSuite/OverrideNewName.pm deleted file mode 100644 index 4be286b..0000000 --- a/perl/third/Test-Unit-0.25/t/tlib/InheritedSuite/OverrideNewName.pm +++ /dev/null @@ -1,16 +0,0 @@ -package InheritedSuite::OverrideNewName; - -use strict; - -use base qw(Test::Unit::TestSuite); - -sub new { - my $class = shift; - my $self = $class->SUPER::empty_new(); - $self->add_test(Test::Unit::TestSuite->new('Success')); - return $self; -} - -sub name { 'Inherited suite overriding new() and name()' } - -1; diff --git a/perl/third/Test-Unit-0.25/t/tlib/InheritedSuite/Simple.pm b/perl/third/Test-Unit-0.25/t/tlib/InheritedSuite/Simple.pm deleted file mode 100644 index c966c23..0000000 --- a/perl/third/Test-Unit-0.25/t/tlib/InheritedSuite/Simple.pm +++ /dev/null @@ -1,10 +0,0 @@ -package InheritedSuite::Simple; - -use strict; - -use base qw(Test::Unit::TestSuite); - -sub include_tests { 'Success' } -sub name { 'Simple inherited suite' } - -1; diff --git a/perl/third/Test-Unit-0.25/t/tlib/InheritedSuite/TestNames.pm b/perl/third/Test-Unit-0.25/t/tlib/InheritedSuite/TestNames.pm deleted file mode 100644 index 1baa964..0000000 --- a/perl/third/Test-Unit-0.25/t/tlib/InheritedSuite/TestNames.pm +++ /dev/null @@ -1,28 +0,0 @@ -package InheritedSuite::TestNames; - -# This class is probably overkill :-) - -use strict; - -use base 'Test::Unit::TestCase'; - -use InheritedSuite::Simple; -use InheritedSuite::OverrideNew; -use InheritedSuite::OverrideNewName; - -sub test_names { - my $self = shift; - - my $simple = InheritedSuite::Simple->new(); - $self->assert_str_equals('Simple inherited suite', $simple->name()); - - my $override_new = InheritedSuite::OverrideNew->new(); - $self->assert_str_equals('Inherited suite overriding new()', - $override_new->name()); - - my $override_new_name = InheritedSuite::OverrideNewName->new(); - $self->assert_str_equals('Inherited suite overriding new() and name()', - $override_new_name->name()); -} - -1; diff --git a/perl/third/Test-Unit-0.25/t/tlib/InheritedTestCase.pm b/perl/third/Test-Unit-0.25/t/tlib/InheritedTestCase.pm deleted file mode 100644 index 75a3600..0000000 --- a/perl/third/Test-Unit-0.25/t/tlib/InheritedTestCase.pm +++ /dev/null @@ -1,14 +0,0 @@ -package InheritedTestCase; - -# Test class used in SuiteTest - -use base qw(OneTestCase); - -sub new { - shift()->SUPER::new(@_); -} - -sub test2 { -} - -1; diff --git a/perl/third/Test-Unit-0.25/t/tlib/ListenerTest.pm b/perl/third/Test-Unit-0.25/t/tlib/ListenerTest.pm deleted file mode 100644 index 2a9cd0b..0000000 --- a/perl/third/Test-Unit-0.25/t/tlib/ListenerTest.pm +++ /dev/null @@ -1,89 +0,0 @@ -package ListenerTest; - -# Test class used in SuiteTest - -use base qw(Test::Unit::TestCase Test::Unit::Listener); - -use Test::Unit::Result; - -sub new { - my $self = shift()->SUPER::new(@_); - $self->{_my_result} = 0; - $self->{_my_start_count} = 0; - $self->{_my_end_count} = 0; - $self->{_my_failure_count} = 0; - $self->{_my_error_count} = 0; - return $self; -} - -sub add_error { - my $self = shift; - my ($test, $t) = @_; - $self->{_my_error_count}++; -} - -sub add_failure { - my $self = shift; - my ($test, $t) = @_; - $self->{_my_failure_count}++; -} - -sub end_test { - my $self = shift; - my ($test) = @_; - $self->{_my_end_count}++; -} - -sub set_up { - my $self = shift; - $self->{_my_result} = Test::Unit::Result->new(); - $self->{_my_result}->add_listener($self); - $self->{_my_start_count} = 0; - $self->{_my_end_count} = 0; - $self->{_my_failure_count} = 0; -} - -sub start_test { - my $self = shift; - $self->{_my_start_count}++; -} - -sub add_pass { -} - -# the tests -sub make_dummy_testcase { - my $self = shift; - my $sub = pop; - my $method_name = shift || 'run_test'; - - Class::Inner->new(parent => 'Test::Unit::TestCase', - methods => { $method_name => $sub }, - args => [ $method_name ]); -} - -sub test_error { - my $self = shift; - my $test = $self->make_dummy_testcase(sub {die}); - $test->run($self->{_my_result}); - $self->assert(1 == $self->{_my_error_count}); - $self->assert(1 == $self->{_my_end_count}); -} - -sub test_failure { - my $self = shift; - my $test = $self->make_dummy_testcase(sub {shift->fail()}); - $test->run($self->{_my_result}); - $self->assert(1 == $self->{_my_failure_count}); - $self->assert(1 == $self->{_my_end_count}); -} - -sub test_start_stop { - my $self = shift; - my $test = $self->make_dummy_testcase(sub {}); - $test->run($self->{_my_result}); - $self->assert(1 == $self->{_my_start_count}); - $self->assert(1 == $self->{_my_end_count}); -} - -1; diff --git a/perl/third/Test-Unit-0.25/t/tlib/NoTestCaseClass.pm b/perl/third/Test-Unit-0.25/t/tlib/NoTestCaseClass.pm deleted file mode 100644 index 2a41acd..0000000 --- a/perl/third/Test-Unit-0.25/t/tlib/NoTestCaseClass.pm +++ /dev/null @@ -1,10 +0,0 @@ -package NoTestCaseClass; -use strict; - -sub new { -} - -sub testSuccess { -} - -1; diff --git a/perl/third/Test-Unit-0.25/t/tlib/NoTestCases.pm b/perl/third/Test-Unit-0.25/t/tlib/NoTestCases.pm deleted file mode 100644 index 57c0828..0000000 --- a/perl/third/Test-Unit-0.25/t/tlib/NoTestCases.pm +++ /dev/null @@ -1,17 +0,0 @@ -package NoTestCases; -use strict; - -use base qw(Test::Unit::TestCase); - -sub new { - my $class = shift; - my ($name) = @_; - my $self = bless {}, $class; - my $a_test_case = $self->SUPER::new($name); - return bless $a_test_case, $class; -} - -sub no_test_case { -} - -1; diff --git a/perl/third/Test-Unit-0.25/t/tlib/OneTestCase.pm b/perl/third/Test-Unit-0.25/t/tlib/OneTestCase.pm deleted file mode 100644 index 1951373..0000000 --- a/perl/third/Test-Unit-0.25/t/tlib/OneTestCase.pm +++ /dev/null @@ -1,17 +0,0 @@ -package OneTestCase; - -# Test class used in SuiteTest - -use base qw(Test::Unit::TestCase); - -sub new { - shift()->SUPER::new(@_); -} - -sub no_test_case { -} - -sub test_case { -} - -1; diff --git a/perl/third/Test-Unit-0.25/t/tlib/OverrideTestCase.pm b/perl/third/Test-Unit-0.25/t/tlib/OverrideTestCase.pm deleted file mode 100644 index 72da562..0000000 --- a/perl/third/Test-Unit-0.25/t/tlib/OverrideTestCase.pm +++ /dev/null @@ -1,15 +0,0 @@ -package OverrideTestCase; -use strict; - -# Test class used in SuiteTest - -use base qw(OneTestCase); - -sub new { - shift()->SUPER::new(@_); -} - -sub test_case { -} - -1; diff --git a/perl/third/Test-Unit-0.25/t/tlib/RunnerTest.pm b/perl/third/Test-Unit-0.25/t/tlib/RunnerTest.pm deleted file mode 100644 index 5d2918b..0000000 --- a/perl/third/Test-Unit-0.25/t/tlib/RunnerTest.pm +++ /dev/null @@ -1,89 +0,0 @@ -package RunnerTest; - -use strict; - -use Test::Unit::TestRunner; - -use base 'Test::Unit::TestCase'; - -sub set_up { - my $self = shift; - open(DEVNULL, '>/dev/null') or die "Couldn't open(>/dev/null): $!"; - $self->{runner} = Test::Unit::TestRunner->new(\*DEVNULL); -} - -sub tear_down { - my $self = shift; - close(DEVNULL); -} - -sub test_reset_filtering { - my $self = shift; - - $self->{runner}->filter('random_token'); - $self->{runner}->reset_filter; - - $self->assert(! $self->{runner}->start('FilteredSuite'), - "run wasn't supposed to succeed"); - my $result = $self->{runner}->result; - $self->assert_num_equals(4, $result->run_count); - $self->assert_num_equals(3, $result->error_count); - $self->assert_num_equals(0, $result->failure_count); -} - -sub test_filter_via_method_list { - my $self = shift; - - $self->{runner}->filter('token_filtering_via_method_list'); - - $self->assert(! $self->{runner}->start('FilteredSuite'), - "run wasn't supposed to succeed"); - my $result = $self->{runner}->result; - $self->assert_num_equals(2, $result->run_count); - $self->assert_num_equals(1, $result->error_count); - $self->assert_num_equals(0, $result->failure_count); -} - -sub test_filter_via_sub { - my $self = shift; - $self->{runner}->filter('token_filtering_via_sub'); - - $self->assert(! $self->{runner}->start('FilteredSuite'), - "run wasn't supposed to succeed"); - my $result = $self->{runner}->result; - $self->assert_num_equals(3, $result->run_count); - $self->assert_num_equals(2, $result->error_count); - $self->assert_num_equals(0, $result->failure_count); -} - -sub test_filter_via_both { - my $self = shift; - $self->{runner}->filter( - 'token_filtering_via_method_list', - 'token_filtering_via_sub', - 'nonexistent_token', # this has to be allowed - ); - - $self->assert($self->{runner}->start('FilteredSuite'), - "run wasn't supposed to fail"); - my $result = $self->{runner}->result; - $self->assert_num_equals(1, $result->run_count); - $self->assert_num_equals(0, $result->error_count); - $self->assert_num_equals(0, $result->failure_count); -} - -sub test_filter_broken_token { - my $self = shift; - $self->{runner}->filter('broken_token'); - - eval { - $self->{runner}->start('FilteredSuite'); - }; - my $exception = $@; # have to save $@ otherwise the assertion messes it up - $self->assert_str_equals( - "Didn't understand filtering definition for token broken_token in FilteredSuite\n", - $exception - ); -} - -1; diff --git a/perl/third/Test-Unit-0.25/t/tlib/Success.pm b/perl/third/Test-Unit-0.25/t/tlib/Success.pm deleted file mode 100644 index e100f1b..0000000 --- a/perl/third/Test-Unit-0.25/t/tlib/Success.pm +++ /dev/null @@ -1,13 +0,0 @@ -package Success; - -use strict; -use warnings; - -use base 'Test::Unit::TestCase'; - -sub test_success { - my $self = shift; - $self->assert(1); -} - -1; diff --git a/perl/third/Test-Unit-0.25/t/tlib/SuiteTest.pm b/perl/third/Test-Unit-0.25/t/tlib/SuiteTest.pm deleted file mode 100644 index e9f8d84..0000000 --- a/perl/third/Test-Unit-0.25/t/tlib/SuiteTest.pm +++ /dev/null @@ -1,167 +0,0 @@ -package SuiteTest; - -use strict; - -use base qw(Test::Unit::TestCase); - -use Test::Unit::Result; -use Test::Unit::TestSuite; -use TornDown; -use WasRun; -require Test::Unit::Assertion::CodeRef; - -my %method_hash = (runs => 'run_count', - failures => 'failure_count', - success => 'was_successful', - errors => 'error_count',); -sub new { - my $self = shift()->SUPER::new(@_); - $self->{_my_result} = undef; - $self->{__default_assertion} = - Test::Unit::Assertion::CodeRef->new(sub { - my $arg_hash = shift; - for (qw/runs failures errors/) { - next unless exists $arg_hash->{$_}; - my $method = $method_hash{$_}; - my $expected = $arg_hash->{$_}; - my $got = $self->result->$method(); - $expected == $got or - die "Expected $expected $_, got $got\n"; - } - if (exists $arg_hash->{'success'}) { - my $method = $method_hash{'success'}; - my $expected = $arg_hash->{'success'}; - my $got = $self->result->$method(); - $expected && $got || !$expected && !$got or - die "Expected ", $expected ? 'success,' : 'failure,', - ' got ', $got ? 'success.' : 'failure.', "\n"; - } - 1; - }); - return $self; -} - -sub basic_assertion { - my $self = shift; - $self->{__default_assertion}->do_assertion(ref($_[0]) ? shift : {@_}); -} - -sub result { - my $self = shift; - return $self->{_my_result}; -} - -sub set_up { - my $self = shift; - $self->{_my_result} = Test::Unit::Result->new(); -} - -sub suite { - my $class = shift; - my $suite = Test::Unit::TestSuite->empty_new("Suite Tests"); - $suite->add_test(SuiteTest->new("test_no_test_case_class")); - $suite->add_test(SuiteTest->new("test_no_test_cases")); - $suite->add_test(SuiteTest->new("test_one_test_case")); - $suite->add_test(SuiteTest->new("test_not_existing_test_case")); - $suite->add_test(SuiteTest->new("test_inherited_tests")); - $suite->add_test(SuiteTest->new("test_inherited_inherited_tests")); - $suite->add_test(SuiteTest->new("test_shadowed_tests")); - $suite->add_test(SuiteTest->new("test_complex_inheritance")); - return $suite; -} - -# test subs - -sub test_inherited_tests { - my $self = shift; - my $suite = Test::Unit::TestSuite->new("InheritedTestCase"); - $suite->run($self->result()); - $self->basic_assertion({success => 1, runs => 2}); - $self->assert($self->result()->was_successful()); - $self->assert(2 == $self->result->run_count); -} - -sub test_complex_inheritance { - my $self = shift; - eval q{ - package _SuperClass; - use base qw(Test::Unit::TestCase); - sub test_case { - my $self = shift; - $self->assert($self->override_this_method ); - } - sub override_this_method { 0 ; } - - package _SubClass; - use base qw(_SuperClass); - sub override_this_method { 1 ; } - }; - die $@ if $@; - my $suite = Test::Unit::TestSuite->new("_SubClass"); - my $result = $self->result; - $suite->run($result); - - $self->assert($result->was_successful()); - $self->assert(1 == $self->result->run_count); -} - -sub test_inherited_inherited_tests { - my $self = shift; - my $suite = Test::Unit::TestSuite->new("InheritedInheritedTestCase"); - $suite->run($self->result()); - $self->basic_assertion(success => 1, runs => 3); - $self->assert($self->result()->was_successful()); - $self->assert(3 == $self->result()->run_count()); -} - -sub test_no_test_case_class { - my $self = shift; - eval { - my $suite = Test::Unit::TestSuite->new("NoTestCaseClass"); - }; - $self->assert_str_equals("Class NoTestCaseClass was not a test case or test suite.\n", "$@"); -} - -sub test_no_test_cases { - my $self = shift; - my $t = Test::Unit::TestSuite->new("NoTestCases"); - $t->run($self->result()); - $self->basic_assertion(runs => 1, failures => 1, success => 0); - $self->assert(1 == $self->result()->run_count()); # warning test - $self->assert(1 == $self->result()->failure_count()); - $self->assert(not $self->result()->was_successful()); -} - -sub test_not_existing_test_case { - my $self = shift; - my $t = SuiteTest->new("not_existing_method"); - $t->run($self->result()); - $self->basic_assertion(runs => 1, failures => 1, errors => 0); - $self->assert(1 == $self->result()->run_count()); - $self->assert(1 == $self->result()->failure_count()); - $self->assert(0 == $self->result()->error_count()); -} - -sub test_one_test_case { - my $self = shift; - my $t = Test::Unit::TestSuite->new("OneTestCase"); - $t->run($self->result()); - $self->basic_assertion(runs => 1, failures => 0, errors => 0, success => 1); - $self->assert(1 == $self->result()->run_count()); - $self->assert(0 == $self->result()->failure_count()); - $self->assert(0 == $self->result()->error_count()); - $self->assert($self->result()->was_successful()); -} - -sub test_shadowed_tests { - my $self = shift; - my $t = Test::Unit::TestSuite->new("OverrideTestCase"); - $t->run($self->result()); - $self->basic_assertion(runs => 1); - $self->assert(1 == $self->result()->run_count()); -} - - - -1; - diff --git a/perl/third/Test-Unit-0.25/t/tlib/TestAssertionCodeRef.pm b/perl/third/Test-Unit-0.25/t/tlib/TestAssertionCodeRef.pm deleted file mode 100644 index 32af870..0000000 --- a/perl/third/Test-Unit-0.25/t/tlib/TestAssertionCodeRef.pm +++ /dev/null @@ -1,15 +0,0 @@ -package TestAssertionCodeRef; -use strict; - -use base qw(Test::Unit::TestCase); - -sub test_case_to_string { my $self = shift; $self->assert(sub { my -$self = shift; $self->to_string eq shift; }, $self, -"test_noy_to_string(" . ref($self) . ")"); } - -sub test_with_a_regex { - my $self = shift; - $self->assert(qr/foo/, 'foo'); - $self->assert(qr/bar/, 'foo'); -} -1; diff --git a/perl/third/Test-Unit-0.25/t/tlib/TestObject.pm b/perl/third/Test-Unit-0.25/t/tlib/TestObject.pm deleted file mode 100644 index 966096d..0000000 --- a/perl/third/Test-Unit-0.25/t/tlib/TestObject.pm +++ /dev/null @@ -1,10 +0,0 @@ -package TestObject; - -use strict; - -sub new { - my $class = shift; - bless [@_], $class; -} - -1; diff --git a/perl/third/Test-Unit-0.25/t/tlib/TestTest.pm b/perl/third/Test-Unit-0.25/t/tlib/TestTest.pm deleted file mode 100644 index a0dd590..0000000 --- a/perl/third/Test-Unit-0.25/t/tlib/TestTest.pm +++ /dev/null @@ -1,290 +0,0 @@ -package TestTest; -use strict; - -use base qw(Test::Unit::TestCase); - -use TornDown; -use WasRun; -use Test::Unit::Error; -use Test::Unit::Failure; -use Class::Inner; -use Error qw/:try/; - -sub verify_error { - my $self = shift; - my ($test) = @_; - my $result = $test->run(); - $self->assert_num_equals(1, $result->run_count()); - $self->assert_num_equals(0, $result->failure_count()); - $self->assert_num_equals(1, $result->error_count()); - $self->assert(! $result->was_successful()); -} - -sub verify_failure { - my $self = shift; - my ($test) = @_; - my $result = $test->run(); - $self->assert_num_equals(1, $result->run_count()); - $self->assert_num_equals(1, $result->failure_count()); - $self->assert_num_equals(0, $result->error_count()); - $self->assert(! $result->was_successful()); -} - -sub verify_success { - my $self = shift; - my ($test) = @_; - my $result = $test->run(); - $self->assert_num_equals(1, $result->run_count()); - $self->assert_num_equals(0, $result->failure_count()); - $self->assert_num_equals(0, $result->error_count()); - $self->assert($result->was_successful()); -} - -# test subs - -sub make_dummy_testcase { - my $self = shift; - my $sub = pop; - my $method_name = shift || 'run_test'; - my $test_name = (caller(1))[3] . '_inner'; - - Class::Inner->new(parent => 'Test::Unit::TestCase', - methods => { $method_name => $sub }, - args => [ $test_name ]); -} - -sub test_case_to_string { - my $self = shift; - $self->assert(qr"test_case_to_string\(TestTest\)", - $self->to_string); - $self->assert($self->to_string() eq "test_case_to_string(TestTest)"); -} - -sub test_error { - my $self = shift; - my $error = $self->make_dummy_testcase( - sub { Test::Unit::Error->throw(-object => $self); } - ); - $self->verify_error($error); -} - -sub test_die { - my $self = shift; - my $fail = $self->make_dummy_testcase(sub { my $self = shift; die "died" }); - $self->verify_error($fail); -} - -sub test_fail { - my $self = shift; - my $fail = $self->make_dummy_testcase(sub { my $self = shift; fail() }); - $self->verify_error($fail); -} - -sub test_failure { - my $self = shift; - my $failure = $self->make_dummy_testcase( - sub { - my $self = shift; - $self->assert(0); - } - ); - $self->verify_failure($failure); -} - -sub test_failure_exception { - my $self = shift; - try { - $self->fail; - } - catch Test::Unit::Failure with { - 1; - } - otherwise { - $self->fail; - } -} - -sub test_run_and_tear_down_both_throw { - my $self = shift; - my $fails = Class::Inner->new( - parent => 'TornDown', - methods => { - run_test => sub { - throw Test::Unit::Error -object => $_[0]; - }, - tear_down => sub { - my $self = shift; - $self->SUPER; - die "this tear_down dies"; - }, - }, - args => [ 'test_run_and_tear_down_both_throw_inner' ], - ); - $self->verify_error($fails); - $self->assert($fails->torn_down()); -} - -sub test_run_and_tear_down_both_throw2 { - my $self = shift; - my $fails = Class::Inner->new( - parent => 'TornDown', - methods => { - run_test => sub { - die "this run_test dies"; - }, - tear_down => sub { - my $self = shift; - $self->SUPER; - throw Test::Unit::Error -object => $_[0]; - }, - }, - args => [ 'test_run_and_tear_down_both_throw2_inner' ], - ); - $self->verify_error($fails); - $self->assert($fails->torn_down()); -} - -sub test_runner_printing { - my $self = shift; - $self->assert("1.05" eq (1050 / 1000)); -} - -sub test_setup_fails { - my $self = shift; - my $fails = Class::Inner->new( - parent => 'Test::Unit::TestCase', - methods => { - set_up => sub { - my $self = shift; - throw Test::Unit::Error -object => $self; - }, - run_test => sub {}, - }, - args => [ 'test_setup_fails_inner' ], - ); - $self->verify_error($fails); -} - -sub test_success { - my $self = shift; - my $success = $self->make_dummy_testcase(sub {shift->assert(1)}); - $self->verify_success($success); -} - -sub test_tear_down_after_error { - my $self = shift; - my $fails = Class::Inner->new( - parent => 'TornDown', - methods => { dummy => sub {} }, - args => [ 'test_tear_down_after_error_inner' ], - ); - $self->verify_error($fails); - $self->assert($fails->torn_down()); -} - -sub test_tear_down_dies { - my $self = shift; - my $fails = Class::Inner->new( - parent => 'Test::Unit::TestCase', - methods => { - tear_down => sub { die "this tear_down dies" }, - run_test => {} - }, - args => [ 'test_tear_down_dies_inner' ], - ); - $self->verify_error($fails); -} - -sub test_tear_down_fails { - my $self = shift; - my $fails = Class::Inner->new( - parent => 'Test::Unit::TestCase', - methods => { - tear_down => sub { - Test::Unit::Error->throw( - -text => "this tear_down throws an Error" - ); - }, - run_test => {} - }, - args => [ 'test_tear_down_fails_inner' ], - ); - $self->verify_error($fails); -} - -sub test_set_up_dies_no_tear_down { - my $self = shift; - my $fails = Class::Inner->new( - parent => 'TornDown', - methods => { set_up => sub { die "this set_up dies" } }, - args => [ 'test_set_up_dies_no_tear_down_inner' ], - ); - $self->verify_error($fails); - $self->assert(! $fails->torn_down()); -} - -sub test_set_up_throws_no_tear_down { - my $self = shift; - my $fails = Class::Inner->new( - parent => 'TornDown', - methods => { - set_up => sub { - Test::Unit::Error->throw( - -text => "this set_up throws an Error" - ); - } - }, - args => [ 'test_set_up_throws_no_tear_down_inner' ], - ); - $self->verify_error($fails); - $self->assert(! $fails->torn_down()); -} - -sub test_was_not_successful { - my $self = shift; - my $failure = $self->make_dummy_testcase(sub { shift->fail }); - $self->verify_failure($failure); -} - -sub test_was_run { - my $self = shift; - my $test = WasRun->new("WasRun"); - $test->run(); - $self->assert($test->was_run()); -} - -sub test_was_successful { - my $self = shift; - my $success = $self->make_dummy_testcase(sub { shift->assert(1) }); - $self->verify_success($success); -} - -sub test_assert_on_matching_regex { - my $self = shift; - my $matching_regex = $self->make_dummy_testcase - (sub { - my $self = shift; - $self->assert(scalar('foo' =~ /foo/), 'foo matches foo (boolean)'); - $self->assert(qr/foo/, 'foo', 'foo matches foo (Assertion::Regex)'); - }); - $self->verify_success($matching_regex); -} - -sub test_assert_on_failing_regex { - my $self = shift; - - my $matching_regex = $self->make_dummy_testcase - (sub { - my $self = shift; - $self->assert(scalar("foo" =~ /bar/), "Should not have matched!"); - $self->assert(qr/bar/, "foo"); - }); - $self->verify_failure($matching_regex); -} - -sub test_assert_with_non_assertion_object { - my $self = shift; - my $obj = bless {}, 'NonExistentClass'; - $self->assert($obj, "Object should eval to true"); -} -1; diff --git a/perl/third/Test-Unit-0.25/t/tlib/TornDown.pm b/perl/third/Test-Unit-0.25/t/tlib/TornDown.pm deleted file mode 100644 index f8cba6e..0000000 --- a/perl/third/Test-Unit-0.25/t/tlib/TornDown.pm +++ /dev/null @@ -1,27 +0,0 @@ -package TornDown; - -use base qw(Test::Unit::TestCase); - -sub new { - my $self = shift()->SUPER::new(@_); - $self->{_TornDown} = 0; - return $self; -} - -sub tear_down { - my $self = shift; - $self->{_TornDown} = 1; -} - -sub torn_down { - my $self = shift; - return $self->{_TornDown}; -} - -sub run_test { - my $self = shift; - my $e = new Test::Unit::Error(); - die $e; -} - -1; diff --git a/perl/third/Test-Unit-0.25/t/tlib/WasRun.pm b/perl/third/Test-Unit-0.25/t/tlib/WasRun.pm deleted file mode 100644 index ac76e91..0000000 --- a/perl/third/Test-Unit-0.25/t/tlib/WasRun.pm +++ /dev/null @@ -1,22 +0,0 @@ -package WasRun; -use strict; - -use base qw(Test::Unit::TestCase); - -sub new { - my $self = shift()->SUPER::new(@_); - $self->{_TornDown} = 0; - return $self; -} - -sub run_test { - my $self = shift; - $self->{_WasRun} = 1; -} - -sub was_run { - my $self = shift; - return $self->{_WasRun}; -} - -1; diff --git a/perl/third/Test-Unit-0.25/t/tlib/WillDie.pm b/perl/third/Test-Unit-0.25/t/tlib/WillDie.pm deleted file mode 100644 index 5e49279..0000000 --- a/perl/third/Test-Unit-0.25/t/tlib/WillDie.pm +++ /dev/null @@ -1,22 +0,0 @@ -package WillDie; - -use Error; - -use base qw(Test::Unit::TestCase ExceptionChecker); - -sub test_dies { - my $self = shift; - $self->check_errors( - 'Died' => [ __LINE__, sub { die; } ], - 'BANG' => [ __LINE__, sub { die "BANG"; } ], - ); -} - -sub test_throws_error_simple { - my $self = shift; - $self->check_errors( - 'BANG!' => [ __LINE__, sub { Error::Simple->throw("BANG!"); } ], - ); -} - -1; diff --git a/perl/third/Test-Unit-0.25/t/try_examples.t b/perl/third/Test-Unit-0.25/t/try_examples.t deleted file mode 100644 index 8a04370..0000000 --- a/perl/third/Test-Unit-0.25/t/try_examples.t +++ /dev/null @@ -1,113 +0,0 @@ -#!/usr/bin/perl -w - -use strict; - -# using the standard built-in 'Test' module (assume nothing) -use Test; - - -foreach (qw(Makefile.PL Makefile examples lib t)) { - die("Please run 'make test' from the top-level source directory\n". - "(I can't see $_)\n") - unless -e $_; -} - -my %skip = map { ("examples/$_") => 1 } - qw(. .. CVS Experimental README tester.png); -my @examples = grep { ! $skip{$_} } glob("examples/*"); - -my %guru_checked = ( - - "examples/patch100132" => <<'EGC', -... -Time: 0 wallclock secs ( 0.00 usr + 0.00 sys = 0.00 CPU) - -OK (3 tests) -EGC - - "examples/patch100132-1" => <<'EGC', -... -Time: 0 wallclock secs ( 0.00 usr + 0.00 sys = 0.00 CPU) - -OK (3 tests) -EGC - - "examples/patch100132-2" => <<'EGC', -... -Time: 0 wallclock secs ( 0.01 usr + 0.00 sys = 0.01 CPU) - -OK (3 tests) -EGC - - "examples/fail_example.pm" => <<'EGC', -Suite setup -.F.Suite teardown - -Time: 0 wallclock secs ( 0.01 usr + 0.00 sys = 0.01 CPU) - -!!!FAILURES!!! -Test Results: -Run: 2, Failures: 1, Errors: 0 - -There was 1 failure: -1) examples/fail_example.pm:19 - test_fail(fail_example) -Born to lose ... - -Test was not successful. -EGC - - ); - -plan(tests => scalar(@examples)); - -foreach my $e (keys %guru_checked) { - warn("Guru ".(defined $guru_checked{$e} ? 'answer' : 'excuse'). - " exists for '$e' but there is no test file\n") - unless grep { $_ eq $e } @examples; -} - - -warn("\n > The STDERR redirection may not work or may behave differently under\n". - " > your OS '$^O'. That will probably cause this test to fail.\n") - if grep { $^O =~ $_ } ( qr/win/i ); -# This will apply to various OSes. Is there a "capable of doing unix -# redirections" flag somewhere? - - -# Attempt to get hold of the correct perl to run the examples. I -# think we want $ENV{FULLPERLRUN} when running "make test", but that -# doesn't filter down to us. $ENV{PERL5LIB} is set correctly though. -my $perl = $^X || "perl"; -# warn "running examples with \$perl='$perl'\n under \@INC=(@INC)\n with PERL5LIB=$ENV{PERL5LIB}\n"; - - -foreach my $e (@examples) { - if (defined $guru_checked{$e}) { - # get program output - my $runner = $e =~ /\.pm$/ ? './TestRunner.pl ' : ''; - my $cmd = "$perl -I examples $runner$e 2>&1"; -# warn "cmd $cmd\n"; - my $out = `$cmd`; - foreach ($out, $guru_checked{$e}) { - # mess about with start & end newlines - s/^\n+//; - $_ .= "\n" unless /\n$/; - # bin the naughty carriage returns - s/\r//g; - # we can't assume the order of tests will be the same - s/^[.F]+\n?Suite teardown$/TEST-RUN-SUMMARY/sm; - s/::Load[0-9_]+Anonymous[0-9_]+/::LOAD_ANONYMOUS_CLASSNAME/; - # indent lines with '# ' so they're comments if the test fails - s/\n/\n# /g; - # hide things that look like CPU usage - s{Time:\s+[\d\.]+\s+wallclock secs \([\d\s\.]+usr\s+\+[\d\s\.]+sys\s+=[\d\s\.]+CPU\)} - {TIME-SUMMARY}g; - } - ok($out, $guru_checked{$e}); - } else { - skip( (exists $guru_checked{$e} - ? "Skip $e: not yet checked" - : 0), - "nothing", "data at \$guru_checked{$e}"); - } -} From 325ad9eaa300428e0e8baf6816da9af26c01e34b Mon Sep 17 00:00:00 2001 From: Sweet Tea Dorminy Date: Sun, 30 Mar 2025 14:12:49 -0400 Subject: [PATCH 2/8] third: Delete Config-Properties It's unused, and additionally it's packaged for Fedora. --- perl/third/Config-Properties-0.41/.cvsignore | 3 - perl/third/Config-Properties-0.41/Changes | 43 --- perl/third/Config-Properties-0.41/MANIFEST | 6 - perl/third/Config-Properties-0.41/Makefile.PL | 8 - .../Config-Properties-0.41/Properties.pm | 293 ------------------ perl/third/Config-Properties-0.41/README | 50 --- perl/third/Config-Properties-0.41/test.pl | 20 -- perl/third/Makefile | 1 - 8 files changed, 424 deletions(-) delete mode 100644 perl/third/Config-Properties-0.41/.cvsignore delete mode 100644 perl/third/Config-Properties-0.41/Changes delete mode 100644 perl/third/Config-Properties-0.41/MANIFEST delete mode 100644 perl/third/Config-Properties-0.41/Makefile.PL delete mode 100644 perl/third/Config-Properties-0.41/Properties.pm delete mode 100644 perl/third/Config-Properties-0.41/README delete mode 100644 perl/third/Config-Properties-0.41/test.pl diff --git a/perl/third/Config-Properties-0.41/.cvsignore b/perl/third/Config-Properties-0.41/.cvsignore deleted file mode 100644 index 0b5bd39..0000000 --- a/perl/third/Config-Properties-0.41/.cvsignore +++ /dev/null @@ -1,3 +0,0 @@ -Makefile -blib -pm_to_blib diff --git a/perl/third/Config-Properties-0.41/Changes b/perl/third/Config-Properties-0.41/Changes deleted file mode 100644 index f0ee38a..0000000 --- a/perl/third/Config-Properties-0.41/Changes +++ /dev/null @@ -1,43 +0,0 @@ -Revision history for Perl extension Config::Properties. - -0.41 Tue Jul 10 00:00:00 2002 - - Fixed value checks in most methods that incorrectly treated the - value '0' or the empty string as an undefined value. I could not - contact the original author in any way (tried 3 email addresses - and news://comp.lang.perl.modules), so I uploaded this version - myself. Craig Manley (c.manley at skybound.nl). - -0.40 Tue Jul 10 11:32:00 2001 - - 0.4 (almost half-way there) release - - Add format/getFormat/setFormat() to change the appearance of saved properties - (thanks to David Boyce for the idea) - - Added POD documenation for format feature - - Typo fixes in POD - - Add reference to official JavaDoc (idea thanks to David Boyce) - Randy Jay Yarger (ryarger@mediaone.net) - - - Fixed default handling when retrieving a property value - David Boyce (dsb@world.std.com) - -0.03 Sat May 19 21:56:10 2001 - - Corrected Object Oriented behavior (was using class variables for everying, - now using instance variables) - - Skip blank lines (spotted by Eric Zylberstejn and Christian Niles) - - Fixed borked packaging (#$@% Windows!) (spotted by Ken Ho, - Michael Peterson and David Boyce) - - Fixed incorrect version number (spotted by Michael Peterson and David Boyce) - Randy Jay Yarger (ryarger@mediaone.net) - - - Allow the escape characters proscribed by the Java API spec - Christian Niles (can207@nyu.edu) - -0.02 Thu May 03 21:19:00 2001 - - Fixed bug relating to doubled escape characters(\\). - Thanks to David Boyce for the spot. - Randy Jay Yarger (ryarger@mediaone.net) - -0.01 Wed Jan 17 15:38:07 2001 - - original version; created by h2xs 1.20 with options - -X -n Config::Properties - Randy Jay Yarger (ryarger@mediaone.net) - diff --git a/perl/third/Config-Properties-0.41/MANIFEST b/perl/third/Config-Properties-0.41/MANIFEST deleted file mode 100644 index 94f1896..0000000 --- a/perl/third/Config-Properties-0.41/MANIFEST +++ /dev/null @@ -1,6 +0,0 @@ -Changes -Makefile.PL -MANIFEST -Properties.pm -test.pl -README \ No newline at end of file diff --git a/perl/third/Config-Properties-0.41/Makefile.PL b/perl/third/Config-Properties-0.41/Makefile.PL deleted file mode 100644 index ffdad24..0000000 --- a/perl/third/Config-Properties-0.41/Makefile.PL +++ /dev/null @@ -1,8 +0,0 @@ -use ExtUtils::MakeMaker; -# See lib/ExtUtils/MakeMaker.pm for details of how to influence -# the contents of the Makefile that is written. -WriteMakefile( - 'NAME' => 'Config::Properties', - 'VERSION_FROM' => 'Properties.pm', # finds $VERSION - 'PREREQ_PM' => {}, # e.g., Module::Name => 1.1 -); diff --git a/perl/third/Config-Properties-0.41/Properties.pm b/perl/third/Config-Properties-0.41/Properties.pm deleted file mode 100644 index e980941..0000000 --- a/perl/third/Config-Properties-0.41/Properties.pm +++ /dev/null @@ -1,293 +0,0 @@ -package Config::Properties; - -use strict; -use warnings; - -our $VERSION = '0.41'; - -# new() - Constructor -# -# The constructor can take one optional argument "$defaultProperties" -# which is an instance of Config::Properties to be used as defaults -# for this object. -sub new { - my $proto = shift; - my $defaultProperties = shift; - my $perlMode = shift; - - my $class = ref($proto) || $proto; - my $self = { - 'PERL_MODE' => (defined($perlMode) && $perlMode) ? 1 : 0, - 'defaults' => $defaultProperties, - 'format' => '%s=%s', - 'properties' => {} - }; - bless($self, $class); - - return $self; -} - -# setProperty() - Set the value for a specific property -sub setProperty { - my $self = shift; - my $key = shift; - my $value = shift; - unless(defined($key) && length($key) && defined($value)) { - die "Config::Properties.setProperty( key, value )"; - } - my $oldValue = $self->{'properties'}{ $key }; - $self->{'properties'}{ $key } = $value; - return $oldValue; -} - -# getProperties() - Return a hashref of all of the properties -sub getProperties { - my $self = shift; - return $self->{'properties'}; -} - -# setFormat() - Set the output format for the properties -sub setFormat { - my $self = shift; - my $format = shift; - unless(defined($format) && length($format)) { - die "Config::Properties.format( string )"; - } - $self->{'format'} = $format; -} - -# format() - Alias for get/setFormat(); -sub format { - my $self = shift; - my $format = shift; - if (defined($format) && length($format)) { - return $self->setFormat($format); - } - else { - return $self->getFormat(); - } -} - -# getFormat() - Return the output format for the properties -sub getFormat { - my $self = shift; - return $self->{'format'}; -} - -# load() - Load the properties from a filehandle -sub load { - my $self = shift; - my $file = shift; - unless(defined($file)) { - die "Config::Properties.load( file )"; - } - while (<$file>) { - $self->process_line($_, $file); - } -} - -# process_line() - Recursive function used to parse a line from the -# properties file. -sub process_line { - my $self = shift; - #print "XXX" . join("::", @_) . "XXX\n"; - my $line = shift; - my $file = shift; - unless(defined($line) && defined($file)) { - die "Config::Properties.process_line( line, file )"; - } - $line =~ s/\015?\012$//; - if ($line =~ /^\s*(\#|\!|$)/) { - return; - } - if ($line =~ /(\\+)$/ and length($1) % 2) { - $line =~ s/\\$//; - my $newline = <$file>; - $newline =~ s/^\s*//; - return $self->process_line($line . $newline, $file); - } - - #print "XXX: " . $line . "\n"; - $line =~ /^\s*([^\s:=]+)(\s*|\s*(\:|\=|\s)\s*(.*?))$/; - #print "1: $1 2: $2 3: $3 4: $4\n"; - unless(defined($1) && length($1)) { - die "Config::Properties.process_line: invalid property line"; - } - - #$properties{ $1 } = ($4 || ""); - #the javadoc for Properties states that both the name and value - #can be escaped. The regex above will break though if ':','=', or - #whitespace are included. - $self->{'properties'}{ unescape($1) } = (defined($4) && length($4)) ? unescape($4) : ''; # Value ($4) may be '0' ! -} - -# unescape() - converts escaped characters to their real counterparts. -sub unescape { - my $value = shift; - - while ($value =~ m/\\(.)/g) { - my $result = $1; - - if ($result eq 't') { - $result = "\t"; - } elsif ($result eq 'n') { - $result = "\n"; - } elsif ($result eq 'r') { - $result = "\r"; - } elsif ($result eq 's') { - $result = ' '; - } - - my $start = (pos $value) - 2; - pos $value = $start; - $value =~ s/\\./$result/; - pos $value = ($start + 1); - } - - return $value; -} - -# reallySave() - Utility function that performs the actual saving of -# the properties file to a filehandle. -sub reallySave { - #print "XXX" . join("::", @_) . "XXX\n"; - my $self = shift; - my $file = shift; - unless(defined($file)) { - die "Config::Properties.reallySave( file )"; - } - foreach (keys %{$self->{properties}}) { - printf $file $self->{'format'} . "\n", $_, $self->{properties}{$_}; - } -} - -# save() - Save the properties to a filehandle with the given header. -sub save { - #print "XXX" . join("::", @_) . "XXX\n"; - my $self = shift; - my $file = shift; - my $header = shift; - unless(defined($file) && defined($header) && length($header)) { - die "Config::Properties.save( file, header )"; - } - print $file "#$header\n"; - print $file '#' . localtime() . "\n"; - $self->reallySave( $file ); -} - -# store() - Synonym for save() -sub store { - my $self = shift; - $self->save(@_); -} - -# getProperty() - Return the value of a property key. Returns the default -# for that key (if there is one) if no value exists for that key. -sub getProperty { - my $self = shift; - my $key = shift; - my $default = shift; - unless(defined($key) && length($key)) { # Key can be '0'! - die "Config::Properties.getProperty( key )"; - } - my $value = $self->{properties}{ $key }; - if ($self->{defaults} && !defined($value)) { # Value can be '0' or empty string! - $value = $self->{defaults}->getProperty($key); - } - return defined($value) ? $value : $default; # $value can be 0 or empty string if key exists! -} - -# propertyName() - Returns an array of the keys of the Properties -sub propertyNames { - my $self = shift; - return keys %{$self->{properties}}; -} - -# list() - Same as store() except that it doesn't include a header. -# Meant for debugging use. -sub list { - my $self = shift; - my $file = shift or die "Config::Properties.list( file )"; - print $file "-- listing properties --"; - $self->reallySave( $file ); -} - -# setPerlMode() - Sets the value (true/false) of the PERL_MODE parameter. -sub setPerlMode { - my $self = shift; - my $mode = shift; - return $self->{'PERL_MODE'} = (defined($mode) && $mode) ? 1 : 0; -} - -# perlMode() - Returns the current PERL_MODE setting (Default is false) -sub perlMode { - my $self = shift; - return $self->{'PERL_MODE'}; -} - -1; -__END__ - -=head1 NAME - -Config::Properties - read Java-style properties files - -=head1 SYNOPSIS - -use Config::Properties; - -my $properties = new Config::Properties(); -$properties->load( $fileHandle ); - -$value = $properties->getProperty( $key ); -$properties->setProperty( $key, $value ); - -$properties->format( '%s => %s' ); -$properties->store( $fileHandle, $header ); - -=head1 DESCRIPTION - -Config::Properties is an near implementation of the java.util.Properties API. -It is designed to allow easy reading, writing and manipulation of Java-style -property files. - -The format of a Java-style property file is that of a key-value pair seperated -by either whitespace, the colon (:) character, or the equals (=) character. -Whitespace before the key and on either side of the seperator is ignored. - -Lines that begin with either a hash (#) or a bang (!) are considered comment -lines and ignored. - -A backslash (\) at the end of a line signifies a continuation and the next -line is counted as part of the current line (minus the backslash, any whitespace -after the backslash, the line break, and any whitespace at the beginning of the next line). - -The official references used to determine this format can be found in the Java API docs -for java.util.Properties at http://java.sun.com/j2se/1.3/docs/api/index.html. - -When a property file is saved it is in the format "key=value" for each line. This can -be changed by setting the format attribute using either $object->format( $format_string ) or -$object->setFormat( $format_string ) (they do the same thing). The format string is fed to -printf and must contain exactly two %s format characters. The first will be replaced with -the key of the property and the second with the value. The string can contain no other -printf control characters, but can be anything else. A newline will be automatically added -to the end of the string. You an get the current format string either by using -$object->format() (with no arguments) or $object->getFormat(). - -If a true third parameter is passed to the constructor, the Config::Properties object -be created in PERL_MODE. This can be set at any time by passing a true or false value -into the setPerlMode() instance method. If in PERL_MODE, the behavior of the object -may be expanded, enhanced and/or just plain different than the Java API spec. - -The following is a list of the current behavior changed under PERL_MODE: - -* Ummm... nothing yet. - -The current (true/false) value of PERL_MODE can be retrieved with the perlMode instance -variable. - -=head1 AUTHOR - -C was developed by Randy Jay Yarger. - -=cut diff --git a/perl/third/Config-Properties-0.41/README b/perl/third/Config-Properties-0.41/README deleted file mode 100644 index 071fcb1..0000000 --- a/perl/third/Config-Properties-0.41/README +++ /dev/null @@ -1,50 +0,0 @@ -Config::Properties -============= - -Description ------------ - -Config::Properties is an near implementation of the java.util.Properties API. -It is designed to allow easy reading, writing and manipulation of Java-style -property files. - -The format of a Java-style property file is that of a key-value pair seperated -by either whitespace, the colon (:) character, or the equals (=) character. -Whitespace before the key and on either side of the seperator is ignored. - -Lines that begin with either a hash (#) or a bang (!) are considered comment -lines and ignored. - -A backslash (\) at the end of a line signifies a continuation and the next -line is counted as part of the current line (minus the backslash, any whitespace -after the backslash, the line break, and any whitespace at the beginning of the next line). - -When a property file is saved it is in the format "key=value" for each line. - -Copyright ---------- - -Copyright (c) 2001 Randy Jay Yarger. All Rights Reserved. - -This program is free software; you can redistribute it and/or modify -it under the same terms as Perl itself. - -Installation ------------- - -> perl Makefile.PL -> make - -... and if you like - -> make test - -... and then - -> make install -> perldoc Config::Properties - -Author ------- - -Randy Jay Yarger diff --git a/perl/third/Config-Properties-0.41/test.pl b/perl/third/Config-Properties-0.41/test.pl deleted file mode 100644 index eaffa9c..0000000 --- a/perl/third/Config-Properties-0.41/test.pl +++ /dev/null @@ -1,20 +0,0 @@ -# Before `make install' is performed this script should be runnable with -# `make test'. After `make install' it should work as `perl test.pl' - -######################### We start with some black magic to print on failure. - -# Change 1..1 below to 1..last_test_to_print . -# (It may become useful if the test is moved to ./t subdirectory.) - -BEGIN { $| = 1; print "1..1\n"; } -END {print "not ok 1\n" unless $loaded;} -use Config::Properties; -$loaded = 1; -print "ok 1\n"; - -######################### End of black magic. - -# Insert your test code below (better if it prints "ok 13" -# (correspondingly "not ok 13") depending on the success of chunk 13 -# of the test code): - diff --git a/perl/third/Makefile b/perl/third/Makefile index eb6e200..5d44068 100644 --- a/perl/third/Makefile +++ b/perl/third/Makefile @@ -6,7 +6,6 @@ PWD:= $(shell pwd) LIB:= ${PWD}/../lib SUBDIRS:= \ - Config-Properties-0.41 \ IPC-Session-0.05 \ Log-Dispatch-FileRotate-1.11 \ Proc-Simple-1.32 \ From 26b80309d2f879ba55a6316867323c7b7c921553 Mon Sep 17 00:00:00 2001 From: Sweet Tea Dorminy Date: Sun, 30 Mar 2025 14:15:59 -0400 Subject: [PATCH 3/8] third: Remove interface. It's unused. --- perl/third/Makefile | 1 - perl/third/interface-0.02/.cvsignore | 3 - perl/third/interface-0.02/Makefile.PL | 7 - perl/third/interface-0.02/interface.pm | 294 ------------------------- 4 files changed, 305 deletions(-) delete mode 100644 perl/third/interface-0.02/.cvsignore delete mode 100644 perl/third/interface-0.02/Makefile.PL delete mode 100755 perl/third/interface-0.02/interface.pm diff --git a/perl/third/Makefile b/perl/third/Makefile index 5d44068..27d1422 100644 --- a/perl/third/Makefile +++ b/perl/third/Makefile @@ -10,7 +10,6 @@ SUBDIRS:= \ Log-Dispatch-FileRotate-1.11 \ Proc-Simple-1.32 \ Shuffle-1.4 \ - interface-0.02 \ all: ${SUBDIRS} diff --git a/perl/third/interface-0.02/.cvsignore b/perl/third/interface-0.02/.cvsignore deleted file mode 100644 index 0b5bd39..0000000 --- a/perl/third/interface-0.02/.cvsignore +++ /dev/null @@ -1,3 +0,0 @@ -Makefile -blib -pm_to_blib diff --git a/perl/third/interface-0.02/Makefile.PL b/perl/third/interface-0.02/Makefile.PL deleted file mode 100644 index 8681fa5..0000000 --- a/perl/third/interface-0.02/Makefile.PL +++ /dev/null @@ -1,7 +0,0 @@ -use ExtUtils::MakeMaker; -# See lib/ExtUtils/MakeMaker.pm for details of how to influence -# the contents of the Makefile that is written. -WriteMakefile( - 'NAME' => 'interface', - 'VERSION_FROM' => 'interface.pm', # finds $VERSION -); diff --git a/perl/third/interface-0.02/interface.pm b/perl/third/interface-0.02/interface.pm deleted file mode 100755 index 57b4f61..0000000 --- a/perl/third/interface-0.02/interface.pm +++ /dev/null @@ -1,294 +0,0 @@ -package interface; - -# -# given the name of package that specifies an interface, verify that we do -# indeed implement everything required by that interface. -# - -use 5.006; - -# we just aren't the kind of module you'd bring home to meet the parents - -# use strict; -# use warnings; - -our $VERSION = '0.02'; - -# per-package locks to avoid reentry when we make them finish loading - -my %locks; - -sub import { - - my $callerpackage = caller; - - return 1 if($locks{$callerpackage}); $locks{$callerpackage} = 1; - - shift; my @interfaces = @_; - - # they need to finish loading before we can inspect what methods they've defined - eval "use $callerpackage;"; - - my $gripes; my $newgripes; - - foreach my $i (@interfaces) { - - do { - eval "package $callerpackage; use $i;"; - die "$callerpackage: interface $i could not be loaded: $@" if($@); - }; - - $newgripes = check_implements($i, $callerpackage); - $gripes .= ", and " if($gripes and $newgripes); - $gripes .= $newgripes if($newgripes); - - # since they implement all required methods, nothing in $i will ever be called. - # however, we need this so that $callerpackage->isa($i) is true. - - push @{$callerpackage.'::ISA'}, $i; - - } - - if($gripes) { - - die "$callerpackage is missing methods: $gripes"; - - } - - undef $locks{$callerpackage}; - -} - - -sub check_implements { - - my $implements = shift; - my $callerpackage = shift; - my $gripes; - - my $gripesf = 0; - - foreach my $i (grep { defined &{$implements.'::'.$_} } keys %{$implements.'::'}) { - - - # unless(defined &{$callerpackage.'::'.$i}) - - unless($callerpackage->can($i)) { - $gripesf = 1; - $gripes .= ', ' if $gripes; - $gripes .= $i; - } - - } - - return $gripes . " from $implements" if($gripesf); - return $gripes; - -} - -1; - -__END__ - -=head1 NAME - -interface - simple compile time interface checking for OO Perl - -=head1 SYNOPSIS - - package Foo; - - use interface 'Iterator', 'Generator', 'Clonable', 'DBI::DBD'; - -=head1 ABSTRACT - -Compile-time interface compliance testing. Inspects the methods defined -in your module, and compares them against the methods defined in the -modules you list. Requires no special or additional syntax. - -Should you fail to implement any method contained in any of the listed -classes, compile will abort with an error message. - -=head1 DESCRIPTION - -Methods starting with an underscore are ignored, and assumed not to -be part of the interface. - -The modules listed on the C line will be added to your -C<@ISA> array. This isn't done to re-use code from them - interface -definitions should be empty code stubs, or perhaps a reference -implementation. It is done so that your module asses the C<< ->isa() >> -test for the name of the package that you're implementing the interface -of. This tells Perl that your module may be used in place of the -modules you implement the interface of. - -Sample interface definition: - - package TestInterface; - - sub foo { } - - sub bar { } - - sub baz { } - - 1; - -A package claiming to implement the interface "TestInterface" would need to -define the methods C, C, and C. - -An "interface" may need some explaination. It's an Object Orientation -idea, also known as polymorphism, that says that you should be able -to use interchangeable objects interchangably. Thank heavens the OO -people came and showed us the light! - -The flip side of polymorphism is type safety. In Perl, C<< ->isa() >> lets -you check to make sure something is derived from a base class. The -logic goes that if its derived from a base class, and we're looking -for an object that fills the need of the base class, then the subclass -will work just as well, and we can accept it. Extending objects is -done by subclassing base classes and passing off the subclasses as -versions of the original. - -While this OO rote might almost have you convinced that the world -works this way, this turns out to be almostly completely useless. -In the real world, there are only a few reasons that one object is -used in place of another: Someone wrote some really horrible code, -and you want to swap out their object with a better version of the -same thing. You're switching to an object that does the same thing -but in a different way, for example using a database store instead -of a flat file store. You're making some minor changes to an existing -object and you want to be able to extend the base class in other -directions in the future. Only in the last case is inherited code -with subclassing even useful. -In fact, there is a move towards using composition (has-a) instead -of inheritance (is-a) across the whole -industry, mainly because they got tired of people pointing out that -OO sucks because inheritance only serves to make a great big mess -of otherwise clean code. - -Seperating the interface from the implementation lets you make -multiple implementations of an idea. They can share code with -each other, but they don't have to. The programmer has assured -us that their module does what is required by stating that it -implements the interface. While this isn't proof that the -code works, climaing to implement an interface is a kind of -contract. The programmer knows what work is required of him and -she has agreed to deliver on it. - -The interface definition can be a package full of stub methods -that don't do anything, or it could be an actual working -implementation of an object you're striving for compatability -with. The first case is cleanist, and the package full of stubs -serves as good documentation. The second case can be handy -in cases where the first case wasn't done but someone ignored -the Wisdom of the Interface and wrote a package anyway. - -The Wisdom of the Interface says to write an interface for each -new kind of object that could have multiple implementations. -The interfaces serves as a contract for the minimum features -needed to implement an object of that type. When working with -objects - creating them, checking types when you accept them, etc - -always work with the interface type, never the type of an -individual implementation. This keeps your code generic. - -In order to do the composition thing (has-a), you contain one or -more objects that you need to do your work, you implement an -interface that dispatches method calls to those objects. Perhaps -your new() method creates those objects and stores them in instance -variables. - -=head2 EXPORT - -None. EXPORT is silly. You stay in your namespace, I'll stay in mine. - -=head1 DIAGNOSTICS - -Failing to implement a required method will generate a fatal similar to the following: - -Baz is missing methods: bar from Stub, and import from your, and import from ImplicitThis at interface.pm line 47. -BEGIN failed--compilation aborted at Baz.pm line 5. - -=head2 AGNOSTICS - -Hear the one about the insomniac dyslexic agnostic? He stayed up all night wondering -if there was a Dog. - -=head1 SEE ALSO - -See http://www.perldesignpatterns.com/ for more on Perl OO, including information -about how and why to use interfaces. - -Damian Conway. Speaking of Damian, this is a cheap knockoff of his Class::Contract module. -However, we have no special syntax! - -Speaking of speaking of Damian Conway, if you ever get a chance to see him talk, you -should go. - -NEXT.pm, by Damian Conway. - -Object::Lexical, also by myself. - -protocol.pm, by James Smith, also on CPAN - -=head1 CHANGES - - 0.01: Initial release. - 0.02: Stephen Nelson submitted a typo report. Thanks! - Mention of protocol.pm by James Smith - An object is now considered to implemenant an interface if it ->can() - do something, not just if it has a method. - Hacked on docs a bit. - -=head1 BUGS - -Yes. - -This will very likely break highly introspective code, for example, anything -Damian Conway might write. - -Does not work with packages not stored in a file where "use" can find them. This -bug applies to programs run from "perl -e" and in subpackages burried in -other packages. Code in the "main" package cannot use this module for this reason. - -Does not work when AUTOLOAD is used to dispatch method calls. Modules that use AUTOLOAD -cannot be used as an interface definition, and modules that use AUTOLOAD cannot be -tested to comply with an interface definition. - -It should be an error to use two different interfaces that both declare a method -of the same name, as it would be ambigious which you are intending to implement. -I haven't decided. Perhaps I'll just make this warning. - -This module was done in pragma-style without permission. I'm interested on -feedback on how to handle this. - -Another arrangement worth considering is to create a Class::Interface thing -that the interface uses, not your code. When you use that interface, the code -is awaken, and import() inspects your code without exporting anything. This -would just move the logic around. Interfaces would be marked interfaces -rather than the people who use the interfaces making them as interfaces. -Once again, thoughts and suggestions encouraged. - -The code is frightening. - -There are spelling and grammar errors in this POD documentation. - -My Wiki is really slow because my computer is slow, doesn't have much memory, and -its 4000 lines of code. I need to trim that down. I think I could do it in about 400 -lines. Update: TinyWiki is borne. TinyWiki is no more than 100 lines, now by -definition. It is fast enough. - -=head1 AUTHOR - -Scott Walters, SWALTERS, Root of all Evil, Escott@slowass.netE - -=head1 COPYRIGHT AND LICENSE - -Copyright 2002, 2003 by Scott Walters - -This library is free software; you can redistribute it and/or modify -it under the same terms as Perl itself. If you don't believe in free -software, just remember that free software programmers are gnome-like. -I wouldn't want to be visited by gnomes. - -=cut From 5c077ba649bd9827b3d49ac43288856981781b56 Mon Sep 17 00:00:00 2001 From: Sweet Tea Dorminy Date: Sun, 30 Mar 2025 14:16:44 -0400 Subject: [PATCH 4/8] third: Remove Shuffle for being unused --- perl/third/Makefile | 1 - perl/third/Shuffle-1.4/.cvsignore | 3 - perl/third/Shuffle-1.4/MANIFEST | 4 - perl/third/Shuffle-1.4/Makefile.PL | 7 -- perl/third/Shuffle-1.4/Shuffle.pm | 178 ----------------------------- perl/third/Shuffle-1.4/test.pl | 79 ------------- 6 files changed, 272 deletions(-) delete mode 100644 perl/third/Shuffle-1.4/.cvsignore delete mode 100644 perl/third/Shuffle-1.4/MANIFEST delete mode 100644 perl/third/Shuffle-1.4/Makefile.PL delete mode 100644 perl/third/Shuffle-1.4/Shuffle.pm delete mode 100644 perl/third/Shuffle-1.4/test.pl diff --git a/perl/third/Makefile b/perl/third/Makefile index 27d1422..7bca66b 100644 --- a/perl/third/Makefile +++ b/perl/third/Makefile @@ -9,7 +9,6 @@ SUBDIRS:= \ IPC-Session-0.05 \ Log-Dispatch-FileRotate-1.11 \ Proc-Simple-1.32 \ - Shuffle-1.4 \ all: ${SUBDIRS} diff --git a/perl/third/Shuffle-1.4/.cvsignore b/perl/third/Shuffle-1.4/.cvsignore deleted file mode 100644 index 0b5bd39..0000000 --- a/perl/third/Shuffle-1.4/.cvsignore +++ /dev/null @@ -1,3 +0,0 @@ -Makefile -blib -pm_to_blib diff --git a/perl/third/Shuffle-1.4/MANIFEST b/perl/third/Shuffle-1.4/MANIFEST deleted file mode 100644 index fe1432e..0000000 --- a/perl/third/Shuffle-1.4/MANIFEST +++ /dev/null @@ -1,4 +0,0 @@ -MANIFEST -Makefile.PL -Shuffle.pm -test.pl diff --git a/perl/third/Shuffle-1.4/Makefile.PL b/perl/third/Shuffle-1.4/Makefile.PL deleted file mode 100644 index 1d58b61..0000000 --- a/perl/third/Shuffle-1.4/Makefile.PL +++ /dev/null @@ -1,7 +0,0 @@ -use ExtUtils::MakeMaker; -# See lib/ExtUtils/MakeMaker.pm for details of how to influence -# the contents of the Makefile that is written. -WriteMakefile( - 'NAME' => 'Algorithm::Numerical::Shuffle', - 'VERSION_FROM' => 'Shuffle.pm', # finds $VERSION -); diff --git a/perl/third/Shuffle-1.4/Shuffle.pm b/perl/third/Shuffle-1.4/Shuffle.pm deleted file mode 100644 index c8db2cd..0000000 --- a/perl/third/Shuffle-1.4/Shuffle.pm +++ /dev/null @@ -1,178 +0,0 @@ -package Algorithm::Numerical::Shuffle; - -################################################################################ -# -# $Author: abigail $ -# -# $Date: 2000/03/08 05:57:40 $ -# -# $Id: Shuffle.pm,v 1.4 2000/03/08 05:57:40 abigail Exp abigail $ -# -# $Log: Shuffle.pm,v $ -# Revision 1.4 2000/03/08 05:57:40 abigail -# Fixed bug that prevented in situ shuffling. -# Changed the wording of the license once again. (MIT/X style) -# -# Revision 1.3 1999/03/01 20:54:06 abigail -# Changed package name to Algorithm::* -# Changed license. -# -# Revision 1.2 1998/09/09 20:48:12 abigail -# - Make shuffle() work with empty lists. -# - Changed license to Artistic only. -# -# Revision 1.1 1998/04/23 17:58:07 abigail -# Initial revision -# -# -# -################################################################################ - -use strict; -use Exporter; - - -use vars qw /$VERSION @ISA @EXPORT @EXPORT_OK/; - -@ISA = qw /Exporter/; -@EXPORT = qw //; -@EXPORT_OK = qw /shuffle/; - -($VERSION) = '$Revision: 1.4 $' =~ /(\d+\.\d+)/; - -sub shuffle { - return @_ if !@_ || ref $_ [0] eq 'ARRAY' && !@{$_ [0]}; - my $array = @_ == 1 && ref $_ [0] eq 'ARRAY' ? shift : [@_]; - for (my $i = @$array; -- $i;) { - my $r = int rand ($i + 1); - ($array -> [$i], $array -> [$r]) = ($array -> [$r], $array -> [$i]); - } - wantarray ? @$array : $array; -} - - -__END__ - -=head1 NAME - -Algorithm::Numerical::Shuffle - Shuffle a list. - -=head1 SYNOPSIS - - use Algorithm::Numerical::Shuffle qw /shuffle/; - - @shuffled = shuffle (1, 2, 3, 4, 5, 6, 7); - - $in_situ = [qw /one two three four five six/]; - shuffle $in_situ; - -=head1 DESCRIPTION - -C performs a one pass, fair shuffle on a list. If the list is -passed as a reference to an array, the shuffle is done in situ. - -The subroutine returns the list in list context, and a reference to -the list in scalar context. - -=head1 COMPLEXITY - -The running time of the algorithm is linear in the size of the list. -For an in situ shuffle, the memory overhead is constant; otherwise, -linear extra memory is used. - -=head1 LITERATURE - -The algorithm used is discussed by Knuth [3]. It was first published -by Fisher and Yates [2], and later by Durstenfeld [1]. - -=head1 CAVEAT - -Salfi [4] points to a big caveat. If the outcome of a random generator -is solely based on the value of the previous outcome, like a linear -congruential method, then the outcome of a shuffle depends on exactly -three things: the shuffling algorithm, the input and the seed of the -random generator. Hence, for a given list and a given algorithm, the -outcome of the shuffle is purely based on the seed. Many modern computers -have 32 bit random numbers, hence a 32 bit seed. Hence, there are at -most 2^32 possible shuffles of a list, foreach of the possible algorithms. -But for a list of n elements, there are n! possible permutations. -Which means that a shuffle of a list of 13 elements will not generate -certain permutations, as 13! > 2^32. - -=head1 REFERENCES - -=over - -=item [1] - -R. Durstenfeld: I, B<7>, 1964. pp 420. - -=item [2] - -R. A. Fisher and F. Yates: I. London, 1938. -Example 12. - -=item [3] - -D. E. Knuth: I, Volume 2, Third edition. -Section 3.4.2, Algorithm P, pp 145. Reading: Addison-Wesley, 1997. -ISBN: 0-201-89684-2. - -=item [4] - -R. Salfi: I. Vienna: 1974, pp 28 - 35. - -=back - -=head1 HISTORY - - $Date: 2000/03/08 05:57:40 $ - - $Log: Shuffle.pm,v $ - Revision 1.4 2000/03/08 05:57:40 abigail - Fixed bug that prevented in situ shuffling. - Changed the wording of the license once again. (MIT/X style) - - Revision 1.3 1999/03/01 20:54:06 abigail - Changed package name to Algorithm::* - Changed license. - - Revision 1.2 1998/09/09 20:48:12 abigail - - Make shuffle() work with empty lists. - - Changed license to Artistic only. - - Revision 1.1 1998/04/23 17:58:07 abigail - Initial revision - - -=head1 AUTHOR - -This package was written by Abigail. - -=head1 COPYRIGHT - -Copyright 1998, 1999, 2000 by Abigail. - -=head1 LICENSE - -This program is copyright 1998-2000 by Abigail. - -Permission is hereby granted, free of charge, to any person obtaining a -copy of this software and associated documentation files (the "Software"), -to deal in the Software without restriction, including without limitation -the rights to use, copy, modify, merge, publish, distribute, sublicense, -and/or sell copies of the Software, and to permit persons to whom the -Software is furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included -in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT -OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. - -=cut diff --git a/perl/third/Shuffle-1.4/test.pl b/perl/third/Shuffle-1.4/test.pl deleted file mode 100644 index de26629..0000000 --- a/perl/third/Shuffle-1.4/test.pl +++ /dev/null @@ -1,79 +0,0 @@ -# Before `make install' is performed this script should be runnable with -# `make test'. After `make install' it should work as `perl test.pl' - -######################### We start with some black magic to print on failure. - -# Change 1..1 below to 1..last_test_to_print . -# (It may become useful if the test is moved to ./t subdirectory.) - -BEGIN { $| = 1; print "1..5\n"; } -END {print "not ok 1\n" unless $loaded;} -use Algorithm::Numerical::Shuffle qw /shuffle/; -$loaded = 1; -print "ok 1\n"; - -######################### End of black magic. - -# Insert your test code below (better if it prints "ok 13" -# (correspondingly "not ok 13") depending on the success of chunk 13 -# of the test code): - -my $test_num = 2; - -eval { - my @a = shuffle (); - if (@a) { - print "not ok ", $test_num ++, "\n"; - } - else { - print "ok ", $test_num ++, "\n"; - } -}; - -if ($@) {print "... error: $@\n";} - -eval { - my $a = []; - shuffle $a; - - if (@$a) { - print "not ok ", $test_num ++, "\n"; - } - else { - print "ok ", $test_num ++, "\n"; - } -}; - -if ($@) {print "... error: $@\n";} - -eval { - my @a = (0 .. 9); - my @b = shuffle @a; - my @c = sort {$a <=> $b} @b; - - if (@a != @c || "@a" != "@c") { - print "not ok ", $test_num ++, "\n"; - } - else { - print "ok ", $test_num ++, "\n"; - } -}; - -if ($@) {print "... error: $@\n";} - -eval { - my $A = [0 .. 9]; - my $B = [0 .. 9]; - shuffle $B; - my @C = sort {$a <=> $b} @$B; - - if (@$A != @C || "@$A" != "@C") { - print "not ok ", $test_num ++, "\n"; - } - else { - print "ok ", $test_num ++, "\n"; - } -}; - -if ($@) {print "... error: $@\n";} - From 81886b38dd1b215143325567c578f8b3d55c3104 Mon Sep 17 00:00:00 2001 From: Sweet Tea Dorminy Date: Sun, 30 Mar 2025 14:20:16 -0400 Subject: [PATCH 5/8] third: Remove Log-Dispatch-FileRotate as unused --- .../Log-Dispatch-FileRotate-1.11/.cvsignore | 3 - .../Log-Dispatch-FileRotate-1.11/Changes | 42 - .../FileRotate.pm | 867 ------------------ .../Log-Dispatch-FileRotate-1.11/MANIFEST | 6 - .../Log-Dispatch-FileRotate-1.11/Makefile.PL | 18 - .../third/Log-Dispatch-FileRotate-1.11/README | 231 ----- .../Log-Dispatch-FileRotate-1.11/test.pl | 126 --- perl/third/Makefile | 1 - 8 files changed, 1294 deletions(-) delete mode 100644 perl/third/Log-Dispatch-FileRotate-1.11/.cvsignore delete mode 100644 perl/third/Log-Dispatch-FileRotate-1.11/Changes delete mode 100644 perl/third/Log-Dispatch-FileRotate-1.11/FileRotate.pm delete mode 100644 perl/third/Log-Dispatch-FileRotate-1.11/MANIFEST delete mode 100644 perl/third/Log-Dispatch-FileRotate-1.11/Makefile.PL delete mode 100644 perl/third/Log-Dispatch-FileRotate-1.11/README delete mode 100644 perl/third/Log-Dispatch-FileRotate-1.11/test.pl diff --git a/perl/third/Log-Dispatch-FileRotate-1.11/.cvsignore b/perl/third/Log-Dispatch-FileRotate-1.11/.cvsignore deleted file mode 100644 index 0b5bd39..0000000 --- a/perl/third/Log-Dispatch-FileRotate-1.11/.cvsignore +++ /dev/null @@ -1,3 +0,0 @@ -Makefile -blib -pm_to_blib diff --git a/perl/third/Log-Dispatch-FileRotate-1.11/Changes b/perl/third/Log-Dispatch-FileRotate-1.11/Changes deleted file mode 100644 index 7607830..0000000 --- a/perl/third/Log-Dispatch-FileRotate-1.11/Changes +++ /dev/null @@ -1,42 +0,0 @@ -Revision history for Perl extension Log::Dispatch::FileRotate. - -0.01 Tue Oct 1 01:12:30 2002 - - original version; created by h2xs 1.20 with options - -AX -n Log::Dispatch::FileRotate - -1.01 Tue Oct 1 01:21:54 EST 2002 - - Real code copied over h2xs stuff. - -1.03 Mon Nov 18 17:19:06 EST 2002 - - added multiple writer stuff. Use flock() to handle locks - -1.04 Wed Nov 20 13:43:04 EST 2002 - - added Time based constraints. - -1.05 Thu Nov 21 09:28:42 EST 2002 - - fixed typos in hash key - -1.06 Tue Apr 29 16:08:37 EST 2003 - - moved inode tests around a bit to fix a warning message - -1.07 Sun May 4 23:42:03 EST 2003 - - fixed up locking in a forked environment - - speed up in time mode. Cache recurrences. Much quicker now :-) - -1.08 Thu Jun 5 11:27:49 EST 2003 - - now build log.conf at 'make test' time as we keep having people - fail due to bad TZ settings - - Also added some more testing on the recurrances - -1.09 Thu Jun 5 17:57:46 EST 2003 - - Even better testing of TZ issues. Try to see if we can work around - them by ignoring and then testing results. - -1.10 Mon Jun 23 09:40:34 EST 2003 - - Seems defaulting to size in Megs happened between 1.05 and 1.06 - which is not what people want. So back to bytes now. - -1.11 Thu Sep 25 11:18:04 EST 2003 - - Forgot to update the Doco from 1.10. - - Added some missing log4j recurrence patterns and made them - case insensitive diff --git a/perl/third/Log-Dispatch-FileRotate-1.11/FileRotate.pm b/perl/third/Log-Dispatch-FileRotate-1.11/FileRotate.pm deleted file mode 100644 index 435a7de..0000000 --- a/perl/third/Log-Dispatch-FileRotate-1.11/FileRotate.pm +++ /dev/null @@ -1,867 +0,0 @@ -package Log::Dispatch::FileRotate; - -require 5.005; -use strict; - -use Log::Dispatch::Output; - -use base qw( Log::Dispatch::Output ); - -use Log::Dispatch::File; # We are a wrapper around Log::Dispatch::File - -use Date::Manip; # For time based recurring rotations - -use Params::Validate qw(validate SCALAR BOOLEAN); -Params::Validate::validation_options( allow_extra => 1 ); - -use vars qw[ $VERSION ]; - -$VERSION = sprintf "%d.%02d", q$Revision: 1.11 $ =~ /: (\d+)\.(\d+)/; - -sub new -{ - my $proto = shift; - my $class = ref $proto || $proto; - - my %p = @_; - - my $self = bless {}, $class; - - $self->{'debug'} = 0; - $self->_basic_init(%p); - $self->{'LDF'} = Log::Dispatch::File->new(%p); # Our log - - # Keep a copy of interesting stuff as well - $self->{params} = \%p; - - # Turn ON/OFF debugging as required - $p{'DEBUG'} ? $self->debug(1) : $self->debug(0); - - # Size defaults to 10meg in all failure modes, hopefully - my $ten_meg = 1024*1024*10; - my $two_gig = 1024*1024*1024*2; - my $size = $p{size}; - $size = $ten_meg unless $size =~ /^\d+$/ && $size < $two_gig && $size > 0; - $self->{size} = $size; - - # Max number of files defaults to 1. No limit enforced here. Only - # positive whole numbers allowed - $self->{max} = $p{max}; - $self->{max} = 1 unless $self->{max} =~ /^\d+$/ && $self->{max} ; - - # Get a name for our Lock file - my $name = $self->{params}->{filename}; - my ($dir,$f) = $name =~ m{^(.*/)(.*)$}; - $f = $name unless $f; - $dir = './' unless $dir; - - my $lockfile = $dir.".".$f.".LCK.$$"; - warn "Lock file is $lockfile\n" if $self->{'debug'}; - $self->{'lf'} = $lockfile; - - # Have we been called with a time based rotation pattern then setup - # timebased stuff. TZ is important and must match current TZ or all - # bets are off! - if(defined $p{'TZ'}) - { - Date_Init("TZ=".$p{'TZ'}); # EADT or EAST when not in daylight savings - } - if(defined $p{'DatePattern'}) - { - $self->setDatePattern($p{'DatePattern'}); - } - - return $self; -} - - -########################################################################### -# -# Subroutine setDatePattern -# -# Args: a single string or ArrayRef of strings -# -# Rtns: Nothing -# -# Description: -# Set a recurrance for file rotation. We accept Date::Manip -# recurrances and the log4j/DailyRollingFileAppender patterns -# -# Date:Manip => -# 0:0:0:0:5:30:0 every 5 hours and 30 minutes -# 0:0:0:2*12:30:0 every 2 days at 12:30 (each day) -# 3*1:0:2:12:0:0 every 3 years on Jan 2 at noon -# -# DailyRollingFileAppender => -# yyyy-MM -# yyyy-ww -# yyyy-MM-dd -# yyyy-MM-dd-a -# yyyy-MM-dd-HH -# yyyy-MM-dd-HH-MM -# -# To specify multiple recurances in a single string seperate them with a -# comma: yyyy-MM-dd,0:0:0:2*12:30:0 -# -sub setDatePattern -{ - my $self = shift; # My object - my($arg) = shift; - - local($_); # Don't crap on $_ - my @pats = (); - - my %lookup = ( - # Y:M:W:D:H:M:S - 'yyyy-mm' => '0:1*0:1:0:0:0', # Every Month - 'yyyy-ww' => '0:0:1*0:0:0:0', # Every week - 'yyyy-dd' => '0:0:0:1*0:0:0', # Every day - 'yyyy-mm-dd' => '0:0:0:1*0:0:0', # Every day - 'yyyy-dd-a' => '0:0:0:1*12:0:0', # Every day 12noon - 'yyyy-mm-dd-a' => '0:0:0:1*12:0:0', # Every day 12noon - 'yyyy-dd-hh' => '0:0:0:0:1*0:0', # Every hour - 'yyyy-mm-dd-hh' => '0:0:0:0:1*0:0', # Every hour - 'yyyy-dd-hh-mm' => '0:0:0:0:0:1*0', # Every minute - 'yyyy-mm-dd-hh-mm' => '0:0:0:0:0:1*0', # Every minute - ); - - # Convert arg to array - if( ref($arg) eq 'ARRAY' ) - { - @pats = @$arg; - } - elsif( !ref($arg) ) - { - $arg =~ s/\s+//go; - @pats = split(/;/,$arg); - } - else - { - die "Bad reference type argument ".ref($arg); - } - - # Handle (possibly multiple) recurrances - foreach my $pat (@pats) - { - # Convert any log4j patterns across - if($pat =~ /^yyyy/i) # Then log4j style - { - $pat = lc($pat); # Use lowercase lookup - # Default to daily on bad pattern - unless(grep($pat eq $_,keys %lookup)) - { - warn "Bad Rotation pattern ($pat) using yyyy-dd\n"; - $pat = 'yyyy-dd'; - } - $pat = $lookup{$pat}; - } - - my $abs = $self->_get_next_occurance($pat); - warn "Adding [epoch secs,pat] =>[$abs,$pat]\n" if $self->{debug}; - my $ref = [$abs, $pat]; - push(@{$self->{'recurrance'}}, $ref); - - } - -} - - -sub log_message -{ - my $self = shift; - my %p = @_; - - my $max_size = $self->{size}; - my $numfiles = $self->{max}; - my $name = $self->{params}->{filename}; - my $fh = $self->{LDF}->{fh}; - - # Prime our time based data outside the critical code area - my ($in_time_mode,$time_to_rotate) = $self->time_to_rotate(); - - # Handle critical code for logging. No changes if someone else is in - if( !$self->lfhlock_test() ) - { - warn "$$ waiting on lock\n" if $self->{debug}; - $self->lfhlock() || return; - } - - my $size = (stat($fh))[7]; # Stat the handle to get real size - my $inode = (stat($fh))[1]; # get real inode - my $finode = (stat($name))[1]; # Stat the name for comparision - warn localtime()." $$ s=$size, i=$inode, f=$finode, n=$name\n" if $self->{debug}; - - # If finode and inode are the same then nobody has done a rename - # under us and we can continue. Otherwise just close and reopen. - # Time mode overrides Size mode - if(!defined($finode) || $inode != $finode) - { - # Oops someone moved things on us. So just reopen our log - delete $self->{LDF}; # Should get rid of current LDF - $self->{LDF} = Log::Dispatch::File->new(%{$self->{params}}); # Our log - - warn localtime()." $$ Someone else rotated: normal log\n" if $self->{debug}; - $self->logit($p{message}); - } - elsif($in_time_mode && !$time_to_rotate) - { - warn localtime()." $$ In time mode: normal log\n" if $self->{debug}; - $self->logit($p{message}); - } - elsif(!$in_time_mode && defined($size) && $size < $max_size ) - { - warn localtime()." $$ In size mode: normal log\n" if $self->{debug}; - $self->logit($p{message}); - } - # Need to rotate - elsif(($in_time_mode && $time_to_rotate) || - (!$in_time_mode && $size) - ) - { - # Shut down the log - delete $self->{LDF}; # Should get rid of current LDF - - my $idx = $numfiles -1; - - warn localtime() . " $$ Rotating\n" if $self->{debug}; - while($idx >= 0) - { - if($idx <= 0) - { - warn "$$ rename $name $name.1\n" if $self->{debug}; - rename($name, "$name.1"); - } - else - { - warn "$$ rename $name.$idx $name.".($idx+1)."\n" if $self->{debug}; - rename("$name.$idx", "$name.".($idx+1)); - } - - $idx--; - } - warn localtime() . " $$ Rotating Done\n" if $self->{debug}; - - # reopen the logfile for writing. - $self->{LDF} = Log::Dispatch::File->new(%{$self->{params}}); # Our log - - # Write it out - warn localtime()." $$ rotated: normal log\n" if $self->{debug}; - $self->logit($p{message}); - } - #else size is zero :-} just don't do anything! - - $self->lfhunlock(); -} - -sub DESTROY -{ - my $self = shift; - - if ( $self->{LDF} ) - { - delete $self->{LDF}; # Should get rid of current LDF - } - - # Clean up locks - close $self->{lfh} if $self->{lfh}; - unlink $self->{lf} if -f $self->{lf}; -} - -sub logit -{ - my $self = $_[0]; - - $self->lock(); - $self->{LDF}->log_message(message => $_[1]); - $self->unlock(); - return; -} - - -########################################################################### -# -# Subroutine time_to_rotate -# -# Args: none -# -# Rtns: (1,n) if we are in time mode and its time to rotate -# n defines the number of timers that expired -# (1,0) if we are in time mode but not ready to rotate -# (0,0) otherwise -# -# Description: -# time_to_rotate - update internal clocks and return status as -# defined above -# -# -# my ($in_time_mode,$time_to_rotate) = $self->time_to_rotate(); -sub time_to_rotate -{ - my $self = shift; # My object - my $mode = defined($self->{'recurrance'}); - my $rotate = 0; - - if($mode) - { - # Then do some checking and update ourselves if we think we need - # to rotate. Wether we rotate or not is up to our caller. We - # assume they know what they are doing! - - # Check need for rotation. Loop through our recurrances looking - # for expiration times. Any we find that have expired we update. - my $tm = time(); - my @recur = @{$self->{'recurrance'}}; - @{$self->{'recurrance'}} = (); - for my $rec (@recur) - { - my ($abs,$pat) = @$rec; - - # Extra checking - unless(defined $abs && $abs) - { - warn "Bad time found for recurrance pattern $pat: $abs\n"; - next; - } - my $dorotate = 0; - if($abs <= $tm) - { - # Then we need to rotate - $abs = $self->_get_next_occurance($pat); - unless(defined $abs && $abs) - { - warn "Next occurance is null for $pat\n"; - $abs = 0; - } - $rotate++; - $dorotate++; # Just for debugging - } - push(@{$self->{'recurrance'}},[$abs,$pat]) if $abs; - my $next = localtime($abs); - warn "time_to_rotate(mode,rotate,next) => ($mode,$dorotate,$next)\n" if $self->{debug}; - } - - } - - warn "time_to_rotate(mode,rotate) => ($mode,$rotate)\n" if $self->{debug}; - return wantarray ? ($mode,$rotate) : $rotate; -} - -########################################################################### -# -# Subroutine _gen_occurance -# -# Args: Date::Manip occurance pattern -# -# Rtns: array of epoch seconds for next few events -# -sub _gen_occurance -{ - my $self = shift; # My object - my $pat = shift; - my $range = ''; - - if($pat =~ /^0:0:0:0:0/) # Small recurrance less than 1 hour - { - $range = "4 hours later"; - } - elsif($pat =~ /^0:0:0:0/) # recurrance less than 1 day - { - $range = "4 days later"; - } - elsif($pat =~ /^0:0:0:/) # recurrance less than 1 week - { - $range = "4 weeks later"; - } - elsif($pat =~ /^0:0:/) # recurrance less than 1 month - { - $range = "4 months later"; - } - elsif($pat =~ /^0:/) # recurrance less than 1 year - { - $range = "24 months later"; - } - else # years - { - my($yrs) = m/^(\d+):/; - $yrs = 1 unless $yrs; - my $months = $yrs * 4 * 12; - - $range = "$months months later"; - } - - # The next date must start at least 1 second away from now other wise - # we may rotate for every message we recieve with in this second :-( - my $start = DateCalc("now","+ 1 second"); - - my @dates = ParseRecur($pat,"now",$start,$range); - - # Just in case we have a bad parse or our assumptions are wrong. - # We default to days - unless(scalar @dates >= 2) - { - warn "Failed to parse ($pat). Going daily\n"; - @dates = ParseRecur('0:0:0:1*0:0:0',"now","now","1 months later"); - } - - my @epochs = map {UnixDate($_,'%s')} @dates; - - # Clean out epochs that occur before now, being careful not to loop - # forever (thanks James). - shift(@epochs) while @epochs && $epochs[0] <= time(); - - warn "Recurrances are at: @epochs\n" if $self->{debug}; - warn "No recurrances found! Probably a timezone issue!\n" unless @epochs; - - return @epochs; -} - -########################################################################### -# -# Subroutine _get_next_occurance -# -# Args: Date::Manip occurance pattern -# -# Rtns: epoch seconds for next event -# -# We don't want to call Date::Manip::ParseRecur too often as it is very -# expensive. So, we cache what is returned from _gen_occurance(). -sub _get_next_occurance -{ - my $self = shift; # My object - my $pat = shift; - - # If this is first time or we are close to the end of our current - # list of recurrances then generate some new ones - if(!defined $self->{'epochs'}{$pat} || scalar(@{$self->{'epochs'}{$pat}}) < 2) - { - @{$self->{'epochs'}{$pat}} = $self->_gen_occurance($pat); - } - - return( shift(@{$self->{'epochs'}{$pat}}) ); -} - - -# Lock and unlock routines. For when we need to write a message. -use Fcntl ':flock'; # import LOCK_* constants - -sub lock -{ - my $self = shift; - - flock($self->{LDF}->{fh},LOCK_EX); - - # Make sure we are at the EOF - seek($self->{LDF}->{fh}, 0, 2); - - warn localtime() ." $$ Locked\n" if $self->{debug}; - return; -} - -sub unlock -{ - my $self = shift; - flock($self->{LDF}->{fh},LOCK_UN); - warn localtime() . " $$ unLocked\n" if $self->{debug}; -} - -# Lock and unlock routines. For when we need to roll the logs. -# -# Note: On May 1, Dan Waldheim's good news was: -# I discovered something interesting about forked processes and locking. -# If the parent "open"s the filehandle and then forks, exclusive locks -# don't work properly between the parent and children. Anyone can grab a -# lock while someone else thinks they have it. To work properly the -# "open" has to be done within each process. -# -# Thanks Dan -sub lfhlock_test -{ - my $self = shift; - - if (open(LFH, ">>$self->{lf}")) - { - $self->{lfh} = *LFH; - if (flock($self->{lfh}, LOCK_EX | LOCK_NB)) - { - warn "$$ got lock on Lock File ".$self->{lfh}."\n" if $self->{debug}; - return 1; - } - } - else - { - $self->{lfh} = 0; - warn "$$ couldn't get lock on Lock File\n" if $self->{debug}; - return 0; - } -} - -sub lfhlock -{ - my $self = shift; - - if (!$self->{lfh}) - { - if (!open(LFH, ">>$self->{lf}")) - { - return 0; - } - $self->{lfh} = *LFH; - } - - flock($self->{lfh},LOCK_EX); -} - -sub lfhunlock -{ - my $self = shift; - - if($self->{lfh}) - { - flock($self->{lfh},LOCK_UN); - close $self->{lfh}; - $self->{lfh} = 0; - } -} - -sub debug -{ - $_[0]->{'debug'} = $_[1]; -} - -__END__ - -=head1 NAME - -Log::Dispatch::FileRotate - Log to files that archive/rotate themselves - -=head1 SYNOPSIS - - use Log::Dispatch::FileRotate; - - my $file = Log::Dispatch::FileRotate->new( name => 'file1', - min_level => 'info', - filename => 'Somefile.log', - mode => 'append' , - size => 10, - max => 6, - ); - # or for a time based rotation - - my $file = Log::Dispatch::FileRotate->new( name => 'file1', - min_level => 'info', - filename => 'Somefile.log', - mode => 'append' , - TZ => 'AEDT', - DatePattern => 'yyyy-dd-HH', - ); - - $file->log( level => 'info', message => "your comment\n" ); - -=head1 DESCRIPTION - -This module provides a simple object for logging to files under the -Log::Dispatch::* system, and automatically rotating them according to -different constraints. This is basically a Log::Dispatch::File wrapper -with additions. To that end the arguments - - name, min_level, filename and mode - -behave the same as Log::Dispatch::File. So see its man page -(perldoc Log::Dispatch::File) - -The arguments size and max specify the maximum size and maximum -number of log files created. The size defaults to 10M and the max number -of files defaults to 1. If DatePattern is not defined then we default to -working in size mode. That is, use size values for deciding when to rotate. - -Once DatePattern is defined FileRotate will move into time mode. Once -this happens file rotation ignores size constraints and uses the defined -date pattern constraints. - -If you setup a config file using Log::Log4perl::init_and_watch() or the -like, you can switch between modes just by commenting out the DatePattern -line. - -When using DatePattern make sure TZ is defined correctly and that the TZ -you use is understood by Date::Manip. We use Date::Manip to generate our -recurrences. Bad TZ equals bad recurrences equals surprises! Read the -Date::Manip man page for more details on TZ. - -DatePattern will default to a daily rotate if your entered pattern is -incorrect. You will also get a warning message. - -If you have multiple writers that were started at different times you -will find each writer will try to rotate the log file at a recurrence -calculated from its start time. To sync all the writers just use a config -file and update it after starting your last writer. This will cause -Log::Dispatch::FileRotate->new() to be called by each of the writers -close to the same time, and if your recurrences aren't too close together -all should sync up just nicely. - -We handle multiple writers using flock(). - -=head1 DatePattern - -As I said earlier we use Date::Manip for generating our recurrence -events. This means we can understand Date::Manip's recurrence patterns -and the normal log4j DatePatterns. We don't use DatePattern to define the -extension of the log file though. - -DatePattern can therfore take forms like: - - - Date::Manip style - 0:0:0:0:5:30:0 every 5 hours and 30 minutes - 0:0:0:2*12:30:0 every 2 days at 12:30 (each day) - 3*1:0:2:12:0:0 every 3 years on Jan 2 at noon - - DailyRollingFileAppender log4j style - yyyy-MM every month - yyyy-ww every week - yyyy-MM-dd every day - yyyy-MM-dd-a every day at noon - yyyy-MM-dd-HH every hour - yyyy-MM-dd-HH-MM every minute - -To specify multiple recurrences in a single string separate them with a -semicolon: - yyyy-MM-dd; 0:0:0:2*12:30:0 - -This says we want to rotate every day AND every 2 days at 12:30. Put in -as many as you like. - -A complete description of Date::Manip recurrences is beyond us here -except to quote (from the man page): - - A recur description is a string of the format - Y:M:W:D:H:MN:S . Exactly one of the colons may - optionally be replaced by an asterisk, or an asterisk - may be prepended to the string. - - Any value "N" to the left of the asterisk refers to - the "Nth" one. Any value to the right of the asterisk - refers to a value as it appears on a calendar/clock. - Values to the right can be listed a single values, - ranges (2 numbers separated by a dash "-"), or a comma - separated list of values or ranges. In a few cases, - negative values are appropriate. - - This is best illustrated by example. - - 0:0:2:1:0:0:0 every 2 weeks and 1 day - 0:0:0:0:5:30:0 every 5 hours and 30 minutes - 0:0:0:2*12:30:0 every 2 days at 12:30 (each day) - 3*1:0:2:12:0:0 every 3 years on Jan 2 at noon - 0:1*0:2:12,14:0:0 2nd of every month at 12:00 and 14:00 - 1:0:0*45:0:0:0 45th day of every year - 0:1*4:2:0:0:0 4th tuesday (day 2) of every month - 0:1*-1:2:0:0:0 last tuesday of every month - 0:1:0*-2:0:0:0 2nd to last day of every month - - - -=head1 METHODS - -=over 4 - -=item * new(%p) - -This method takes a hash of parameters. The following options are -valid: - -=item -- name ($) - -The name of the object (not the filename!). Required. - -=item -- size ($) - -The maxium (or close to) size the log file can grow too. - -=item -- max ($) - -The maxium number of log files to create. - - -=item -- TZ ($) - -The TimeZone time based calculations should be done in. This should match -Date::Manip's concept of timezones and of course your machines timezone. -Date::Manip will normally work everything out for you. Except in my case -where EST means Eastern Standard Time in Australia not the US! I had to -use AEST or EADT instead. Here is a list of Date::Manip's timezones -straight from its man page. - - - The following timezone names are currently understood (and - can be used in parsing dates). These are zones defined in - RFC 822. - - Universal: GMT, UT - US zones : EST, EDT, CST, CDT, MST, MDT, PST, PDT - Military : A to Z (except J) - Other : +HHMM or -HHMM - ISO 8601 : +HH:MM, +HH, -HH:MM, -HH - - In addition, the following timezone abbreviations are also - accepted. - - IDLW -1200 International Date Line West - NT -1100 Nome - HST -1000 Hawaii Standard - CAT -1000 Central Alaska - AHST -1000 Alaska-Hawaii Standard - AKST -0900 Alaska Standard - YST -0900 Yukon Standard - HDT -0900 Hawaii Daylight - AKDT -0800 Alaska Daylight - YDT -0800 Yukon Daylight - PST -0800 Pacific Standard - PDT -0700 Pacific Daylight - MST -0700 Mountain Standard - MDT -0600 Mountain Daylight - CST -0600 Central Standard - CDT -0500 Central Daylight - EST -0500 Eastern Standard - SAT -0400 Chile - EDT -0400 Eastern Daylight - AST -0400 Atlantic Standard - ADT -0300 Atlantic Daylight - NDT -0230 Newfoundland Daylight - AT -0200 Azores - WAT -0100 West Africa - GMT +0000 Greenwich Mean - UT +0000 Universal (Coordinated) - UTC +0000 Universal (Coordinated) - WET +0000 Western European - WEST +0000 Alias for Western European - CET +0100 Central European - FWT +0100 French Winter - MET +0100 Middle European - MEZ +0100 Middle European - MEWT +0100 Middle European Winter - SWT +0100 Swedish Winter - BST +0100 British Summer bst=Brazil standard -0300 - GB +0100 GMT with daylight savings - CEST +0200 Central European Summer - EET +0200 Eastern Europe, USSR Zone 1 - FST +0200 French Summer - MEST +0200 Middle European Summer - MESZ +0200 Middle European Summer - METDST +0200 An alias for MEST used by HP-UX - SAST +0200 South African Standard - SST +0200 Swedish Summer sst=South Sumatra +0700 - EEST +0300 Eastern Europe Summer - BT +0300 Baghdad, USSR Zone 2 - MSK +0300 Moscow - IT +0330 Iran - ZP4 +0400 USSR Zone 3 - MSD +0300 Moscow Daylight - ZP5 +0500 USSR Zone 4 - IST +0530 Indian Standard - ZP6 +0600 USSR Zone 5 - CCT +0800 China Coast, USSR Zone 7 - AWST +0800 West Australian Standard - WST +0800 West Australian Standard - PHT +0800 Asia Manila - JST +0900 Japan Standard, USSR Zone 8 - ROK +0900 Republic of Korea - CAST +0930 Central Australian Standard - EAST +1000 Eastern Australian Standard - GST +1000 Guam Standard, USSR Zone 9 gst=Greenland Std - CADT +1030 Central Australian Daylight - EADT +1100 Eastern Australian Daylight - IDLE +1200 International Date Line East - NZST +1200 New Zealand Standard - NZT +1200 New Zealand - NZDT +1300 New Zealand Daylight - - - -=item -- DatePattern ($) - -The DatePattern as defined above. - -=item -- min_level ($) - -The minimum logging level this object will accept. See the -Log::Dispatch documentation for more information. Required. - -=item -- max_level ($) - -The maximum logging level this obejct will accept. See the -Log::Dispatch documentation for more information. This is not -required. By default the maximum is the highest possible level (which -means functionally that the object has no maximum). - -=item -- filename ($) - -The filename to be opened for writing. This is the base name. Rotated log -files will be renamed filename.1 thru to filename.C. Where max is the -paramater defined above. - -=item -- mode ($) - -The mode the file should be opened with. Valid options are 'write', -'>', 'append', '>>', or the relevant constants from Fcntl. The -default is 'write'. - -=item -- autoflush ($) - -Whether or not the file should be autoflushed. This defaults to true. - -=item -- callbacks( \& or [ \&, \&, ... ] ) - -This parameter may be a single subroutine reference or an array -reference of subroutine references. These callbacks will be called in -the order they are given and passed a hash containing the following keys: - - ( message => $log_message, level => $log_level ) - -The callbacks are expected to modify the message and then return a -single scalar containing that modified message. These callbacks will -be called when either the C or C methods are called and -will only be applied to a given message once. - -=item -- DEBUG ($) - -Turn on lots of warning messages to STDERR about what this module is -doing if set to 1. Really only useful to me. - -=item * log_message( message => $ ) - -Sends a message to the appropriate output. Generally this shouldn't -be called directly but should be called through the C method -(in Log::Dispatch::Output). - -=item * setDatePattern( $ or [ $, $, ... ] ) - -Set a new suite of recurrances for file rotation. You can pass in a -single string or a reference to an array of strings. Multiple recurrences -can also be define within a single string by seperating them with a -semi-colon (;) - -See the discussion above regarding the setDatePattern paramater for more -details. - -=back - -=head1 TODO - -compression, signal based rotates, proper test suite - -Could possibly use Logfile::Rotate as well/instead. - -=head1 AUTHOR - -Mark Pfeiffer, inspired by -Dave Rolsky's, , code :-) - -Kevin Goess suggested multiple writers should be -supported. He also conned me into doing the time based stuff. -Thanks Kevin! :-) - -Thanks also to Dan Waldheim for helping with some of the -locking issues in a forked environment. - -=cut - diff --git a/perl/third/Log-Dispatch-FileRotate-1.11/MANIFEST b/perl/third/Log-Dispatch-FileRotate-1.11/MANIFEST deleted file mode 100644 index 3c804ea..0000000 --- a/perl/third/Log-Dispatch-FileRotate-1.11/MANIFEST +++ /dev/null @@ -1,6 +0,0 @@ -Changes -FileRotate.pm -MANIFEST -Makefile.PL -test.pl -README diff --git a/perl/third/Log-Dispatch-FileRotate-1.11/Makefile.PL b/perl/third/Log-Dispatch-FileRotate-1.11/Makefile.PL deleted file mode 100644 index aa79525..0000000 --- a/perl/third/Log-Dispatch-FileRotate-1.11/Makefile.PL +++ /dev/null @@ -1,18 +0,0 @@ -use ExtUtils::MakeMaker; -# See lib/ExtUtils/MakeMaker.pm for details of how to influence -# the contents of the Makefile that is written. -WriteMakefile( - 'NAME' => 'Log::Dispatch::FileRotate', - 'VERSION_FROM' => 'FileRotate.pm', # finds $VERSION - 'PREREQ_PM' => {}, # e.g., Module::Name => 1.1 - 'ABSTRACT_FROM' => 'FileRotate.pm', - 'AUTHOR' => '"Mark Pfeiffer" ', - 'clean' => {FILES => "*.log*"}, - PREREQ_PM => { - 'Log::Log4perl' => '0.23', # or a minimum workable version - 'Log::Dispatch::Output' => 0, - 'Date::Manip' => 0, - 'Params::Validate' => 0, - 'Fcntl' => 0, - } -); diff --git a/perl/third/Log-Dispatch-FileRotate-1.11/README b/perl/third/Log-Dispatch-FileRotate-1.11/README deleted file mode 100644 index b6e7482..0000000 --- a/perl/third/Log-Dispatch-FileRotate-1.11/README +++ /dev/null @@ -1,231 +0,0 @@ -NAME - Log::Dispatch::FileRotate - Log to files that archive/rotate themselves - -SYNOPSIS - use Log::Dispatch::FileRotate; - - my $file = Log::Dispatch::FileRotate->new( name => 'file1', - min_level => 'info', - filename => 'Somefile.log', - mode => 'append' , - size => 10, - max => 6, - ); - # or for a time based rotation - - my $file = Log::Dispatch::FileRotate->new( name => 'file1', - min_level => 'info', - filename => 'Somefile.log', - mode => 'append' , - TZ => 'AEDT', - DatePattern => 'yyyy-dd-HH', - ); - - $file->log( level => 'info', message => "your comment\n" ); - -DESCRIPTION - This module provides a simple object for logging to files under the - Log::Dispatch::* system, and automatically rotating them according to - different constraints. This is basically a Log::Dispatch::File wrapper - with additions. To that end the arguments - - name, min_level, filename and mode - - behave the same as Log::Dispatch::File. So see its man page (perldoc - Log::Dispatch::File) - - The arguments size and max specify the maximum size (in meg) and maximum - number of log files created. The size defaults to 10M and the max number - of files defaults to 1. If DatePattern is not defined then we default to - working in size mode. That is, use size values for deciding when to - rotate. - - Once DatePattern is defined FileRotate will move into time mode. Once - this happens file rotation ignores size constraints and uses the defined - date pattern constraints. - - If you setup a config file using Log::Log4perl::init_and_watch() or the - like, you can switch between modes just by commenting out the - DatePattern line. - - When using DatePattern make sure TZ is defined correctly and that the TZ - you use is understood by Date::Manip. We use Date::Manip to generate our - recurrences. Bad TZ equals bad recurrences equals surprises! Read the - Date::Manip man page for more details on TZ. - - DatePattern will default to a daily rotate if your entered pattern is - incorrect. You will also get a warning message. - - If you have multiple writers that were started at different times you - will find each writer will try to rotate the log file at a recurrence - calculated from its start time. To sync all the writers just use a - config file and update it after starting your last writer. This will - cause Log::Dispatch::FileRotate->new() to be called by each of the - writers close to the same time, and if your recurrences aren't too close - together all should sync up just nicely. - - We handle multiple writers using flock(). - -DatePattern - As I said earlier we use Date::Manip for generating our recurrence - events. This means we can understand Date::Manip's recurrence patterns - and the normal log4j DatePatterns. We don't use DatePattern to define - the extension of the log file though. - - DatePattern can therfore take forms like: - - Date::Manip style - 0:0:0:0:5:30:0 every 5 hours and 30 minutes - 0:0:0:2*12:30:0 every 2 days at 12:30 (each day) - 3*1:0:2:12:0:0 every 3 years on Jan 2 at noon - - DailyRollingFileAppender log4j style - yyyy-MM every month - yyyy-ww every week - yyyy-MM-dd every day - yyyy-MM-dd-a every day at noon - yyyy-MM-dd-HH every hour - yyyy-MM-dd-HH-MM every minute - - To specify multiple recurrences in a single string separate them with a - semicolon: yyyy-MM-dd; 0:0:0:2*12:30:0 - - This says we want to rotate every day AND every 2 days at 12:30. Put in - as many as you like. - - A complete description of Date::Manip recurrences is beyond us here - except to quote (from the man page): - - A recur description is a string of the format - Y:M:W:D:H:MN:S . Exactly one of the colons may - optionally be replaced by an asterisk, or an asterisk - may be prepended to the string. - - Any value "N" to the left of the asterisk refers to - the "Nth" one. Any value to the right of the asterisk - refers to a value as it appears on a calendar/clock. - Values to the right can be listed a single values, - ranges (2 numbers separated by a dash "-"), or a comma - separated list of values or ranges. In a few cases, - negative values are appropriate. - - This is best illustrated by example. - - 0:0:2:1:0:0:0 every 2 weeks and 1 day - 0:0:0:0:5:30:0 every 5 hours and 30 minutes - 0:0:0:2*12:30:0 every 2 days at 12:30 (each day) - 3*1:0:2:12:0:0 every 3 years on Jan 2 at noon - 0:1*0:2:12,14:0:0 2nd of every month at 12:00 and 14:00 - 1:0:0*45:0:0:0 45th day of every year - 0:1*4:2:0:0:0 4th tuesday (day 2) of every month - 0:1*-1:2:0:0:0 last tuesday of every month - 0:1:0*-2:0:0:0 2nd to last day of every month - -METHODS - * new(%p) - This method takes a hash of parameters. The following options are - valid: - - -- name ($) - The name of the object (not the filename!). Required. - - -- size ($) - The maxium (or close to) size the log file can grow too. - - -- max ($) - The maxium number of log files to create. - - -- TZ ($) - The TimeZone time based calculations should be done in. This should - match Date::Manip's concept of timezones and of course your machines - timezone. Date::Manip will normally work everything out for you. - Except in my case where EST means Eastern Standard Time in Australia - not the US! I had to use AEST or EADT instead. Here is a list of - Date::Manip's timezones straight from its man page. - - The following timezone names are currently understood (and - can be used in parsing dates). These are zones defined in - RFC 822. - - Universal: GMT, UT - US zones : EST, EDT, CST, CDT, MST, MDT, PST, PDT - Military : A to Z (except J) - Other : +HHMM or -HHMM - ISO 8601 : +HH:MM, +HH, -HH:MM, -HH - - In addition, the following timezone abbreviations are also - accepted. - - [ .. snip ... ] - - -- DatePattern ($) - The DatePattern as defined above. - - -- min_level ($) - The minimum logging level this object will accept. See the - Log::Dispatch documentation for more information. Required. - - -- max_level ($) - The maximum logging level this obejct will accept. See the - Log::Dispatch documentation for more information. This is not - required. By default the maximum is the highest possible level - (which means functionally that the object has no maximum). - - -- filename ($) - The filename to be opened for writing. This is the base name. - Rotated log files will be renamed filename.1 thru to filename."max". - Where max is the paramater defined above. - - -- mode ($) - The mode the file should be opened with. Valid options are 'write', - '>', 'append', '>>', or the relevant constants from Fcntl. The - default is 'write'. - - -- autoflush ($) - Whether or not the file should be autoflushed. This defaults to - true. - - -- callbacks( \& or [ \&, \&, ... ] ) - This parameter may be a single subroutine reference or an array - reference of subroutine references. These callbacks will be called - in the order they are given and passed a hash containing the - following keys: - - ( message => $log_message, level => $log_level ) - - The callbacks are expected to modify the message and then return a - single scalar containing that modified message. These callbacks will - be called when either the "log" or "log_to" methods are called and - will only be applied to a given message once. - - -- DEBUG ($) - Turn on lots of warning messages to STDERR about what this module is - doing if set to 1. Really only useful to me. - - * log_message( message => $ ) - Sends a message to the appropriate output. Generally this shouldn't - be called directly but should be called through the "log()" method - (in Log::Dispatch::Output). - - * setDatePattern( $ or [ $, $, ... ] ) - Set a new suite of recurrances for file rotation. You can pass in a - single string or a reference to an array of strings. Multiple - recurrences can also be define within a single string by seperating - them with a semi-colon (;) - - See the discussion above regarding the setDatePattern paramater for - more details. - -TODO - compression, signal based rotates, proper test suite - - Could possibly use Logfile::Rotate as well/instead. - -AUTHOR - Mark Pfeiffer, inspired by Dave Rolsky's, - , code :-) - - Kevin Goess suggested multiple writers should be - supported. He also conned me into doing the time based stuff. Thanks - Kevin! :-) - diff --git a/perl/third/Log-Dispatch-FileRotate-1.11/test.pl b/perl/third/Log-Dispatch-FileRotate-1.11/test.pl deleted file mode 100644 index b725552..0000000 --- a/perl/third/Log-Dispatch-FileRotate-1.11/test.pl +++ /dev/null @@ -1,126 +0,0 @@ -#!/usr/bin/perl -w - -# Before `make install' is performed this script should be runnable with -# `make test'. After `make install' it should work as `perl test.pl' - -######################### We start with some black magic to print on failure. - -# Change 1..1 below to 1..last_test_to_print . -# (It may become useful if the test is moved to ./t subdirectory.) - -BEGIN { $| = 1; print "1..5\n"; } -END {print "not ok 1\n" unless $loaded;} -use Log::Log4perl; -use Log::Dispatch::FileRotate; -$loaded = 1; -print "ok 1\n"; - -######################### End of black magic. - -# Insert your test code below (better if it prints "ok 13" -# (correspondingly "not ok 13") depending on the success of chunk 13 -# of the test code): - -# First lets build a conf file for use latter -use Date::Manip; -my $tz; -eval '$tz= Date_TimeZone();'; -if($@) -{ - #print "ERROR Unable to determine timezone! Lets see if it matters..\n"; - my $start = DateCalc("now","+ 1 second"); - my @dates = ParseRecur('0:0:0:0:0:1*0',"now",$start,'20 minutes later'); - - # Should get about 20 in the array - my @epochs = map {UnixDate($_,'%s')} @dates; - shift(@epochs) while @epochs && $epochs[0] <= time(); - - # If no epochs left then Timezone issue is going to bite us! - # all bets are off. - if( @epochs ) - { - #print "It looks like we can get by without a timezone. Lucky!\n"; - print "ok 2\n"; - } - else - { - print "**** Time Zone problem: All bets are off. ****\n"; - print "not ok 2\n"; - } - $tz = ''; - -} -else -{ - #print "Your timezone is $tz.\n"; - $tz = "log4j.appender.FILE.TZ=$tz"; - print "ok 2\n"; -} - - -my $config = < log.conf") || die "Can't create log.conf"; -print CONF $config; -close(CONF); - -Log::Log4perl::init_and_watch("log.conf",10); -print "ok 3\n"; - -my $logger = Log::Log4perl->get_logger('nms.cisco.utility'); -my $logger1 = Log::Log4perl->get_logger('nms'); - -print "ok 4\n\n"; - -print "while true; do clear;ls -ltr| grep myerrs; sleep 1; done\n\n"; -print "Type this in another xterm in this directory to see the logs -changing. You can also edit log.conf and change params to see what will -happen to the log files. - -You can also run a number of 'make test' commands to see how we behave -with multiple writers to log files. - -Edit test.pl and uncomment the 'sleep 1' line if you want to -see time rotation happening -"; - -my $i = 4; -while ($i <= 65 ) -{ - $logger->debug($$ . ' this is a debug message'); - $logger->info($$ . ' this is an info message'); - $logger->warn($$ . ' etc'); - $logger->error($$ . ' ..'); - $logger->fatal($$ . ' ..'); - - $logger1->info($$ . ' this is an info message via logger1'); - $i++; -# sleep 1; - print "."; -} -print "\n"; -print "ok 5\n"; - diff --git a/perl/third/Makefile b/perl/third/Makefile index 7bca66b..5a38cca 100644 --- a/perl/third/Makefile +++ b/perl/third/Makefile @@ -7,7 +7,6 @@ LIB:= ${PWD}/../lib SUBDIRS:= \ IPC-Session-0.05 \ - Log-Dispatch-FileRotate-1.11 \ Proc-Simple-1.32 \ all: ${SUBDIRS} From 683b2d5c7f762a3b58a8d755434e396fe45e9971 Mon Sep 17 00:00:00 2001 From: Sweet Tea Dorminy Date: Sun, 30 Mar 2025 14:21:55 -0400 Subject: [PATCH 6/8] third: Remove IPC::Session as unused --- perl/third/IPC-Session-0.05/.cvsignore | 3 - perl/third/IPC-Session-0.05/ChangeLog | 50 --- perl/third/IPC-Session-0.05/MANIFEST | 7 - perl/third/IPC-Session-0.05/Makefile.PL | 7 - perl/third/IPC-Session-0.05/Session.pm | 444 ------------------------ perl/third/IPC-Session-0.05/t/csh.t | 41 --- perl/third/IPC-Session-0.05/t/sh.t | 41 --- perl/third/IPC-Session-0.05/t/timeout.t | 27 -- perl/third/Makefile | 1 - 9 files changed, 621 deletions(-) delete mode 100644 perl/third/IPC-Session-0.05/.cvsignore delete mode 100644 perl/third/IPC-Session-0.05/ChangeLog delete mode 100644 perl/third/IPC-Session-0.05/MANIFEST delete mode 100644 perl/third/IPC-Session-0.05/Makefile.PL delete mode 100644 perl/third/IPC-Session-0.05/Session.pm delete mode 100644 perl/third/IPC-Session-0.05/t/csh.t delete mode 100644 perl/third/IPC-Session-0.05/t/sh.t delete mode 100644 perl/third/IPC-Session-0.05/t/timeout.t diff --git a/perl/third/IPC-Session-0.05/.cvsignore b/perl/third/IPC-Session-0.05/.cvsignore deleted file mode 100644 index 0b5bd39..0000000 --- a/perl/third/IPC-Session-0.05/.cvsignore +++ /dev/null @@ -1,3 +0,0 @@ -Makefile -blib -pm_to_blib diff --git a/perl/third/IPC-Session-0.05/ChangeLog b/perl/third/IPC-Session-0.05/ChangeLog deleted file mode 100644 index 7c70a88..0000000 --- a/perl/third/IPC-Session-0.05/ChangeLog +++ /dev/null @@ -1,50 +0,0 @@ -2001-04-12 14:11 stevegt - - * Session.pm: significant rewrite to fix csh bug, provide real - detection of remote shell type, flush stderr and stdout before - every send - -2001-02-27 12:25 stevegt - - * MANIFEST, Session.pm, test.pl, test1, t/sh.t, t/timeout.t, - t/csh.t, MANIFEST, Changes: fix errno not getting returned in - scalar context, fix csh incompatibility - -2000-03-02 02:10 stevegt - - * MANIFEST, Session.pm, test3, lib/IPC/Session.pm: releasing to - CPAN - -1998-10-12 22:42 stevegt - - * lib/IPC/Session.pm: checkpoint before working at home mping works - working on how to bypass dead interfaces - -1998-08-13 20:47 stevegt - - * test2: test version of SYNOPSIS - -1998-08-13 20:46 stevegt - - * lib/IPC/Session.pm: clean up CHANGES section - -1998-08-06 17:24 stevegt - - * lib/IPC/Session.pm: Session.pm package v0.02 switch to unbuffered - non-blocking I/O add timeout() remove need for FileHandle.pm add - cloning - -1998-08-05 11:35 stevegt - - * lib/IPC/Session.pm: released package v0.01 - -1998-08-04 15:14 stevegt - - * Changes, MANIFEST, Makefile.PL, test.pl, lib/IPC/Session.pm: - Initial revision - -1998-08-04 15:14 stevegt - - * Changes, MANIFEST, Makefile.PL, test.pl, lib/IPC/Session.pm: - created - diff --git a/perl/third/IPC-Session-0.05/MANIFEST b/perl/third/IPC-Session-0.05/MANIFEST deleted file mode 100644 index b246f4b..0000000 --- a/perl/third/IPC-Session-0.05/MANIFEST +++ /dev/null @@ -1,7 +0,0 @@ -ChangeLog -MANIFEST -Makefile.PL -Session.pm -t/csh.t -t/sh.t -t/timeout.t diff --git a/perl/third/IPC-Session-0.05/Makefile.PL b/perl/third/IPC-Session-0.05/Makefile.PL deleted file mode 100644 index 617a637..0000000 --- a/perl/third/IPC-Session-0.05/Makefile.PL +++ /dev/null @@ -1,7 +0,0 @@ -use ExtUtils::MakeMaker; -# See lib/ExtUtils/MakeMaker.pm for details of how to influence -# the contents of the Makefile that is written. -WriteMakefile( - 'NAME' => 'IPC::Session', - 'VERSION_FROM' => 'Session.pm', # finds $VERSION -); diff --git a/perl/third/IPC-Session-0.05/Session.pm b/perl/third/IPC-Session-0.05/Session.pm deleted file mode 100644 index 3eaeccc..0000000 --- a/perl/third/IPC-Session-0.05/Session.pm +++ /dev/null @@ -1,444 +0,0 @@ -package IPC::Session; - -use strict; -use FileHandle; -use IPC::Open3; -use Time::HiRes qw(sleep); - -use vars qw($VERSION); - -$VERSION = '0.05'; - -=head1 NAME - -IPC::Session - Drive ssh or other interactive shell, local or remote (like 'expect') - -=head1 SYNOPSIS - - use IPC::Session; - - # open ssh session to fred - # -- set timeout of 30 seconds for all send() calls - my $session = new IPC::Session("ssh fred",30); - - $session->send("hostname"); # run `hostname` command on fred - print $session->stdout(); # prints "fred" - $session->send("date"); # run `date` within same ssh - print $session->stdout(); # prints date - - # use like 'expect': - $session->send("uname -s"); - for ($session->stdout) - { - /IRIX/ && do { $netstat = "/usr/etc/netstat" }; - /ConvexOS/ && do { $netstat = "/usr/ucb/netstat" }; - /Linux/ && do { $netstat = "/bin/netstat" }; - } - - # errno returned in scalar context: - $errno = $session->send("$netstat -rn"); - # try this: - $session->send("grep '^$user:' /etc/passwd") - && warn "$user not there"; - - # hash returned in array context: - %netstat = $session->send("$netstat -in"); - print "$netstat{'stdout'}\n"; # prints interface table - print "$netstat{'stderr'}\n"; # prints nothing (hopefully) - print "$netstat{'errno'}\n"; # prints 0 - -=head1 DESCRIPTION - -This module encapsulates the open3() function call (see L) -and its associated filehandles. This makes it easy to maintain -multiple interactive command sessions, such as multiple persistent -'ssh' and/or 'rsh' sessions, within the same perl script. - -The remote shell session is kept open for the life of the object; this -avoids the overhead of repeatedly opening remote shells via multiple -ssh or rsh calls. This persistence is particularly useful if you are -using ssh for your remote shell invocation; it helps you overcome -the high ssh startup time. - -For applications requiring remote command invocation, this module -provides functionality that is similar to 'expect' or Expect.pm, -but in a lightweight more Perlish package, with discrete STDOUT, -STDERR, and return code processing. - -By the way, there's nothing inherently ssh-ish about IPC::Session -- it -doesn't even know anything about ssh, as a matter of fact. It will -work with any interactive shell that supports 'echo'. For instance, -'make test' just drives a local /bin/sh session. - -=head1 METHODS - -=head2 my $session = new IPC::Session("ssh fred",30); - -The constructor accepts the command string to be used to open the remote -shell session, such as ssh or rsh; it also accepts an optional timeout -value, in seconds. It returns a reference to the unique session object. - -If the timeout is not specified then it defaults to 60 seconds. -The timeout value can also be changed later; see L<"timeout()">. - -=cut - -sub new -{ - my $class=shift; - $class = (ref $class || $class); - my $self={}; - bless $self, $class; - - my ($cmd,$timeout,$handler)=@_; - $self->{'handler'} = $handler || sub {die @_}; - $timeout=60 unless defined $timeout; - $self->{'timeout'} = $timeout; - - local(*IN,*OUT,*ERR); # so we can use more than one of these objects - $self->{pid} = open3(\*IN,\*OUT,\*ERR,$cmd); - ($self->{pid}) || &{$self->{'handler'}}($!); - - ($self->{'stdin'},$self->{'stdout'},$self->{'stderr'}) = (*IN,*OUT,*ERR); - - # Set to autoflush. - for (*IN,*OUT,*ERR) { - select; - $|++; - } - select STDOUT; - - # determine target shell - $self->{'shell'} = $self->getshell(); - - return $self; -} - -sub getshell -{ - my $self=shift; - my ($tag, $shout); - - $tag=$self->tx('stdin', "echo;echo csherrno=\$status\n"); - $shout=$self->rx('stdout', $tag); - return "csh" if $shout =~ /csherrno=0/; - - $tag=$self->tx('stdin', "echo;echo bsherrno=\$?\n"); - $shout=$self->rx('stdout', $tag); - return "bsh" if $shout =~ /bsherrno=0/; - - die "unable to determine remote shell\n"; -} - -sub tx -{ - my ($self,$handle,$cmd) = @_; - my $fh=$self->{$handle}; - my $shell = $self->{'shell'} || ""; - - my $eot="_EoT_" . rand() . "_"; - - # run command - print $fh "$cmd\n"; - - print $fh "echo $eot"; - print $fh " errno=\$?" if $shell eq "bsh"; - print $fh " errno=\$status" if $shell eq "csh"; - print $fh "\n"; - - # call /bin/sh to work around csh stupidity -- csh doesn't support - # redirection of stderr... BUG this will only work if there is a - # /bin/sh on target machine - my $stderrcmd; - $stderrcmd="/bin/sh -c 'echo $eot >&2'\n" if $shell eq "csh"; - $stderrcmd= "echo $eot >&2\n" if $shell eq "bsh"; - print $fh $stderrcmd if $shell; - return $eot; -} - -sub rx -{ - my ($self,$handle, $eot, $timeout) = @_; - $timeout = $self->{'timeout'} unless defined($timeout); - my $fh=$self->{$handle}; - - my $rin = my $win = my $ein = ''; - vec($rin,fileno($fh),1) = 1; - $ein = $rin; - - # Why two nested loops? So we can do eot pattern match (below) - # against a full line at a time, while getting one character at a - # time. Do we need to get only one character at a time? Probably - # not, but it evolved this way. It does let us parse and linebreak - # on the \n character, include newlines in the output, but not - # include the eot marker. - - # get full text - my $out=""; - my $errno=""; - while (!select(undef,undef,my $eout=$ein,0)) # while !eof() - { - # get one line of text - my $outl = ""; - while (!select(undef,undef,my $eout=$ein,0)) # while !eof() - { - # wait for output on handle - my $nready=select(my $rout=$rin, undef, undef, $timeout); - return $nready if $timeout==0; - - # handle timeout - &{$self->{'handler'}}("timeout on $handle") unless $nready; - - # read one char - my $outc; - my $ret = sysread($self->{$handle},$outc,1); - if (!$ret) { - my $msg; - if (defined($ret)) { - $msg = "eof read error"; - } else { - $msg = "read error: $!"; - } - $msg .= " from $handle (already read: $out)"; - if ($handle ne 'stderr') { - # This will in most cases not return since stderr is likely - # to be at EOF. - $msg .= ", stderr: " . $self->rx('stderr', $eot, $timeout); - } - &{$self->{'handler'}}($msg); - } - - # include newlines in output - $outl .= $outc; - last if $outc eq "\n"; - } - # store snarfed return code - $outl =~ /$eot errno=(\d+)/ && ($errno = $1); - - # eot pattern match -- don't include eot tag in output - if ($outl =~ s/$eot.*//s) { - $out .= $outl; - last; - } - $out .= $outl; - } - - return $out unless wantarray; - return $out,$errno; -} - -sub rxready -{ - my $self=shift; - my $handle = shift; - return $self->rx($handle,"dummy",0); -} - -sub rxflush -{ - my $self=shift; - my $handle = shift; - my $tag = shift || ".*"; - while($self->rxready($handle)) - { - $self->rx($handle,$tag) - } -} - -=head2 $commandhandle = $session->send("hostname"); - -The send() method accepts a command string to be executed on the remote -host. The command will be executed in the context of the default shell -of the remote user (unless you start a different shell by sending the -appropriate command...). All shell escapes, command line terminators, pipes, -redirectors, etc. are legal and should work, though you of course will -have to escape special characters that have meaning to Perl. - -In a scalar context, this method returns the return code produced by the -command string. - -In an array context, this method returns a hash containing the return code -as well as the full text of the command string's output from the STDOUT -and STDERR file handles. The hash keys are 'stdout', 'stderr', and -'errno'. - -=cut - -sub send -{ - my $self=shift; - my $cmd=join(' ',@_); - - # send the command - $self->rxflush('stdout'); - $self->rxflush('stderr'); - my $tag = $self->tx('stdin',$cmd); - - # snarf the output until we hit eot marker on both streams - my ($stdout,$errno) = $self->rx('stdout', $tag); - my $stderr = $self->rx('stderr', $tag); - - $self->{'out'}{'stdout'} = $stdout; - $self->{'out'}{'stderr'} = $stderr; - $self->{'out'}{'errno'} = $errno; - - return $self->{'out'}{'errno'} unless wantarray; - return ( - errno => $self->{'out'}{'errno'}, - stdout => $self->{'out'}{'stdout'}, - stderr => $self->{'out'}{'stderr'} - ); -} - -=head2 print $session->stdout(); - -Returns the full STDOUT text generated from the last send() command string. - -Also available via array context return codes -- see L<"send()">. - -=cut - -sub stdout -{ - my $self=shift; - return $self->{'out'}{'stdout'}; -} - -=head2 print $session->stderr(); - -Returns the full STDERR text generated from the last send() command string. - -Also available via array context return codes -- see L<"send()">. - -=cut - -sub stderr -{ - my $self=shift; - return $self->{'out'}{'stderr'}; -} - -=head2 print $session->errno(); - -Returns the return code generated from the last send() command string. - -Also available via array context return codes -- see L<"send()">. - -=cut - -sub errno -{ - my $self=shift; - return $self->{'out'}{'errno'}; -} - -=head2 $session->timeout(90); - -Allows you to change the timeout for subsequent send() calls. - -The timeout value is in seconds. Fractional seconds are allowed. -The timeout applies to all send() calls. - -Returns the current timeout if called with no args. - -=cut - -sub timeout -{ - my $self=shift; - $self->{'timeout'} = ( shift || $self->{'timeout'}); - return $self->{'timeout'}; -} - -sub handler -{ - my $self=shift; - $self->{'handler'} = ( shift || $self->{'handler'}); - return $self->{'handler'}; -} - -=head2 $session->close(); - -Kill the child process and then reap it. This will prevent lots of -defunct processes from accumulating. - -=cut - -sub close { - my ($self) = @_; - kill(15, $self->{pid}); - sleep(0.25); - if (kill(0, $self->{pid}) > 0) { - kill(9, $self->{pid}); - } - waitpid($self->{pid}, 0); - $self->{pid} = 0; -} - -sub DESTROY { - my ($self) = @_; - # Preserve EVAL_ERROR so any nested eval{}s won't clear the exception - # that may have caused this destructor to be called. - local $@; - - ($self->{pid}) && ($self->close()); -} - -=head1 BUGS/RESTRICTIONS - -=over 4 - -=item * - -The remote shell command you specify in new() is assumed to not prompt -for any passwords or present any challenge codes; i.e.; you must use -.rhosts, authorized_keys, ssh-agent, or the equivalent, and must be -prepared to answer any passphrase prompt if using ssh. You can -either run ssh-add ahead of time and provide the passphrase, have -your script do that itself, or simply set the passphrase to null (if -your security model allows it). - -=item * - -There must be a working /bin/sh on the target machine. - -=back - -=head1 AUTHOR - - Steve Traugott - -=head1 SEE ALSO - -L, -L, -L, -L, -L - -=cut - -1; - -__END__ - my $vec = ''; - vec($vec,fileno($self->{'stdout'}),1) = 1; - warn unpack("b*",$vec) . "\n"; - select($vec, undef, undef, $self->{'timeout'}) - && sysread($self->{'stdout'},my $shout,9999); - $shell="bsh" if $shout =~ /bsherrno=0/; - - - my $vstderr = ''; - vec($vstderr,fileno($self->{'stdout'}),1) = 1; - warn unpack("b*",$rin) . "\n"; - select($vstderr, undef, undef, $self->{'timeout'}) - - - warn unpack("b*",$rin) . "\n"; - vec($rin,fileno($self->{'stderr'}),1) = 1; - - - die; - - diff --git a/perl/third/IPC-Session-0.05/t/csh.t b/perl/third/IPC-Session-0.05/t/csh.t deleted file mode 100644 index 683cc4a..0000000 --- a/perl/third/IPC-Session-0.05/t/csh.t +++ /dev/null @@ -1,41 +0,0 @@ -# Before `make install' is performed this script should be runnable with -# `make test'. After `make install' it should work as `perl test.pl' - -######################### We start with some black magic to print on failure. - -# Change 1..1 below to 1..last_test_to_print . -# (It may become useful if the test is moved to ./t subdirectory.) - -BEGIN { $| = 1; print "1..10\n"; } -END {print "not ok 1\n" unless $loaded;} -use IPC::Session; -$loaded = 1; -print "ok 1\n"; - -######################### End of black magic. - - -# open local sh session -my $session = new IPC::Session("/bin/csh",15); -print "ok 2\n" if $session; - -$session->send("echo hello"); -chomp(my $hello = $session->stdout()); -print "ok 3\n" if $hello eq "hello"; - -my $uname=`uname`; -print "ok 4\n" if $uname; -$session->send("uname"); -print "ok 5\n" if $uname eq $session->stdout(); -print "ok 6\n" unless $session->stderr(); - -# errno returned in scalar context: -my $errno = $session->send('/bin/sh -c "exit 99"'); -print "ok 7\n" if $errno == 99; - -# hash returned in array context: -my %ls = $session->send("ls t/sh.t doesnotexist"); -print "ok 8\n" if $ls{'stdout'} =~ /t\/sh/; -print "ok 9\n" if $ls{'stderr'} =~ /doesnotexist/; -print "ok 10\n" if $ls{'errno'} != 0; - diff --git a/perl/third/IPC-Session-0.05/t/sh.t b/perl/third/IPC-Session-0.05/t/sh.t deleted file mode 100644 index 4f39227..0000000 --- a/perl/third/IPC-Session-0.05/t/sh.t +++ /dev/null @@ -1,41 +0,0 @@ -# Before `make install' is performed this script should be runnable with -# `make test'. After `make install' it should work as `perl test.pl' - -######################### We start with some black magic to print on failure. - -# Change 1..1 below to 1..last_test_to_print . -# (It may become useful if the test is moved to ./t subdirectory.) - -BEGIN { $| = 1; print "1..10\n"; } -END {print "not ok 1\n" unless $loaded;} -use IPC::Session; -$loaded = 1; -print "ok 1\n"; - -######################### End of black magic. - - -# open local sh session -my $session = new IPC::Session("/bin/sh",15); -print "ok 2\n" if $session; - -$session->send("echo hello"); -chomp(my $hello = $session->stdout()); -print "ok 3\n" if $hello eq "hello"; - -my $uname=`uname`; -print "ok 4\n" if $uname; -$session->send("uname"); -print "ok 5\n" if $uname eq $session->stdout(); -print "ok 6\n" unless $session->stderr(); - -# errno returned in scalar context: -my $errno = $session->send('/bin/sh -c "exit 99"'); -print "ok 7\n" if $errno == 99; - -# hash returned in array context: -my %ls = $session->send("ls t/sh.t doesnotexist"); -print "ok 8\n" if $ls{'stdout'} =~ /t\/sh/; -print "ok 9\n" if $ls{'stderr'} =~ /doesnotexist/; -print "ok 10\n" if $ls{'errno'} != 0; - diff --git a/perl/third/IPC-Session-0.05/t/timeout.t b/perl/third/IPC-Session-0.05/t/timeout.t deleted file mode 100644 index 7b9b911..0000000 --- a/perl/third/IPC-Session-0.05/t/timeout.t +++ /dev/null @@ -1,27 +0,0 @@ - -# Before `make install' is performed this script should be runnable with -# `make test'. After `make install' it should work as `perl test.pl' - -######################### We start with some black magic to print on failure. - -# Change 1..1 below to 1..last_test_to_print . -# (It may become useful if the test is moved to ./t subdirectory.) - -BEGIN { $| = 1; print "1..4\n"; } -END {print "not ok 1\n" unless $loaded;} -use IPC::Session; -$loaded = 1; -print "ok 1\n"; - -######################### End of black magic. - - -# open local sh session -my $session = new IPC::Session("/bin/sh",5); -print "ok 2\n" if $session; - -eval { $session->send("sleep 3") }; -print "ok 3\n" unless $@; -eval { $session->send("sleep 10") }; -print "ok 4\n" if $@; - diff --git a/perl/third/Makefile b/perl/third/Makefile index 5a38cca..f72d35f 100644 --- a/perl/third/Makefile +++ b/perl/third/Makefile @@ -6,7 +6,6 @@ PWD:= $(shell pwd) LIB:= ${PWD}/../lib SUBDIRS:= \ - IPC-Session-0.05 \ Proc-Simple-1.32 \ all: ${SUBDIRS} From 779ba42d4d29920c401968450531d26b92f128b5 Mon Sep 17 00:00:00 2001 From: Sweet Tea Dorminy Date: Sun, 30 Mar 2025 14:24:49 -0400 Subject: [PATCH 7/8] third: remove Proc::Simple in favor of package This is packaged up already. Just use that version. --- perl/third/Makefile | 3 +- perl/third/Proc-Simple-1.32/.licensizer.yml | 18 - perl/third/Proc-Simple-1.32/Changes | 105 --- perl/third/Proc-Simple-1.32/MANIFEST | 21 - perl/third/Proc-Simple-1.32/MANIFEST.SKIP | 12 - perl/third/Proc-Simple-1.32/META.json | 47 -- perl/third/Proc-Simple-1.32/META.yml | 25 - perl/third/Proc-Simple-1.32/Makefile.PL | 21 - perl/third/Proc-Simple-1.32/README | 311 -------- perl/third/Proc-Simple-1.32/Simple.pm | 841 -------------------- perl/third/Proc-Simple-1.32/eg/parproc.pl | 36 - perl/third/Proc-Simple-1.32/t/bin/test-prog | 13 - perl/third/Proc-Simple-1.32/t/destroy.t | 84 -- perl/third/Proc-Simple-1.32/t/esub.t | 33 - perl/third/Proc-Simple-1.32/t/exit.t | 37 - perl/third/Proc-Simple-1.32/t/muarg.t | 20 - perl/third/Proc-Simple-1.32/t/mult.t | 33 - perl/third/Proc-Simple-1.32/t/sh-c.t | 53 -- perl/third/Proc-Simple-1.32/t/simple.t | 54 -- perl/third/Proc-Simple-1.32/t/stdouterr.t | 30 - perl/third/Proc-Simple-1.32/t/time.t | 38 - perl/third/Proc-Simple-1.32/t/wait.t | 21 - 22 files changed, 1 insertion(+), 1855 deletions(-) delete mode 100644 perl/third/Proc-Simple-1.32/.licensizer.yml delete mode 100644 perl/third/Proc-Simple-1.32/Changes delete mode 100644 perl/third/Proc-Simple-1.32/MANIFEST delete mode 100644 perl/third/Proc-Simple-1.32/MANIFEST.SKIP delete mode 100644 perl/third/Proc-Simple-1.32/META.json delete mode 100644 perl/third/Proc-Simple-1.32/META.yml delete mode 100644 perl/third/Proc-Simple-1.32/Makefile.PL delete mode 100644 perl/third/Proc-Simple-1.32/README delete mode 100644 perl/third/Proc-Simple-1.32/Simple.pm delete mode 100755 perl/third/Proc-Simple-1.32/eg/parproc.pl delete mode 100755 perl/third/Proc-Simple-1.32/t/bin/test-prog delete mode 100644 perl/third/Proc-Simple-1.32/t/destroy.t delete mode 100755 perl/third/Proc-Simple-1.32/t/esub.t delete mode 100755 perl/third/Proc-Simple-1.32/t/exit.t delete mode 100755 perl/third/Proc-Simple-1.32/t/muarg.t delete mode 100755 perl/third/Proc-Simple-1.32/t/mult.t delete mode 100755 perl/third/Proc-Simple-1.32/t/sh-c.t delete mode 100755 perl/third/Proc-Simple-1.32/t/simple.t delete mode 100755 perl/third/Proc-Simple-1.32/t/stdouterr.t delete mode 100644 perl/third/Proc-Simple-1.32/t/time.t delete mode 100644 perl/third/Proc-Simple-1.32/t/wait.t diff --git a/perl/third/Makefile b/perl/third/Makefile index f72d35f..2c9638c 100644 --- a/perl/third/Makefile +++ b/perl/third/Makefile @@ -5,8 +5,7 @@ PWD:= $(shell pwd) LIB:= ${PWD}/../lib -SUBDIRS:= \ - Proc-Simple-1.32 \ +SUBDIRS:= all: ${SUBDIRS} diff --git a/perl/third/Proc-Simple-1.32/.licensizer.yml b/perl/third/Proc-Simple-1.32/.licensizer.yml deleted file mode 100644 index a5265eb..0000000 --- a/perl/third/Proc-Simple-1.32/.licensizer.yml +++ /dev/null @@ -1,18 +0,0 @@ -# .licensizer.yml - -author: - text: | - 1996, Mike Schilli - header: AUTHORS - mode: verbatim - -license: - text: | - Copyright 1996-2011 by Mike Schilli, all rights reserved. - This program is free software, you can redistribute it and/or - modify it under the same terms as Perl itself. - header: LEGALESE - -path_exclude: - - t/ - - blib/ diff --git a/perl/third/Proc-Simple-1.32/Changes b/perl/third/Proc-Simple-1.32/Changes deleted file mode 100644 index 17f479c..0000000 --- a/perl/third/Proc-Simple-1.32/Changes +++ /dev/null @@ -1,105 +0,0 @@ -###################################################################### - Proc::Simple CHANGES -###################################################################### - - 1.32 (2015/11/15) - (ms) [rt.cpan.org #108215] open() calls now use the safe form. - - 1.31 (2012/11/17) - (ms) To better deal with the race condition in the - previous release, kill the newly created child - process first, then send a killpg to its process - group and ignore the outcome. - - (ms) [RT 81203] Jim A Kessler reported a perl 5.16 issue - with the "AutoLoader" line, so I went ahead and removed - all references to "Exporter" and "AutoLoader", as - Proc::Simple isn't using them at all. - - From 1.29: - [RT 69782] Zefram reported race condition in t/sh-c.t, - fixed by adding polling loop. - - Found that kill(-sig, pid) sometimes fails with - 'process id not found' although a previous kill(0, pid) - succeeded. This is a race condition condition caused - by a newly forked child that hasn't called setsid() yet - and therefore its new process group id doesn't exist yet, - although the child responds to poll(). kill() now - deals with this case. - From 1.28: - [RT 69103] Typo fix by Salvatore Bonaccorso - Added support for processes called via 'sh -c' by - system() (see "Shell Processes" note in the manpage). - From 1.27: - [RT 62802] Pod fix by Salvatore Bonaccorso - [RT 63833] Applied patch to stop reaping PIDs of - no longer existing processes (submitted by perlbotics). - Added licensizer - [RT 63833] (second part) Added cleanup() class method - to delete timing data of reaped processes, avoiding - infinite memory growth on long-running processes - - From 1.26: [RT 62285] Pod fix for redirect_output() - Fixed github link - - from 1.25: Localize special variables so that the exit status - from waitpid doesn't leak out, causing exit status - to be incorrect (RT33440, fixed by Brad Cavanagh). - - from 1.24: Added copyright header - - from 1.23: Applied doc patch by Janne Chr. Schulz - - from 1.22: Applied patch by Jeff Holt, providing start - and end time of the forked process via t0() and t1(). - - from 1.21: Added patch by Chip Capelik to provide a wait() - method waiting for a process to terminate. - - from 1.20: Added patch by Tobias Jahn , - to redirect STDOUT or STDERR of the child process upon - request. - - from 1.19: Fixed bug which occurred on failed fork()s, as - reported anonymously on the CPAN bug tracker. - - from 1.18: Added multi-arg start method (proposed by - Clauss Strauch ) - - from 1.17: Fixed Version difference between Makefile.PL - and Simple by using VERSION_FROM (thanks - Andreas Koenig) - - from 1.16: Fixed bug with Proc::Simple instances which - were DESTROYED before they were ever started. - Many thanks to Russell Fulton (r.fulton@auckland.ac.nz) - for pointing this out. - - from 1.15: Added %DESTROYED hash for processes which might - still in zombie state right after their objects - went out of business. THE_REAPER will take care - of them. - - from 1.14: Added exit_status() method and a smart - REAPER which reaps only processes we've started before. - - from 1.13: Replaced two erronous uses of 'exists' by 'defined'. - Thanks to Rolf.Beutner@telekom.de for pointing this - out. - from 1.12: To fight problems with zombies, replaced the wait() - function by a NOWAIT waitpid on systems that - support it. - - Tim Jenness included - kill_on_destroy/sig_on_destroy/pid methods. - - from 1.11: binkley's error: threw out waitpid, wait is - performed by signal handler now. - - from 1.1: Process is now called Proc::Simple to fit in the - CPAN namespace, corrections Andreas Koenig suggested. - -First Release: 05/22/96 - -Michael Schilli procsimple@perlmeister.com diff --git a/perl/third/Proc-Simple-1.32/MANIFEST b/perl/third/Proc-Simple-1.32/MANIFEST deleted file mode 100644 index d0785d7..0000000 --- a/perl/third/Proc-Simple-1.32/MANIFEST +++ /dev/null @@ -1,21 +0,0 @@ -.licensizer.yml -Changes -eg/parproc.pl -Makefile.PL -MANIFEST -MANIFEST.SKIP -META.yml Module meta-data (added by MakeMaker) -README -Simple.pm -t/bin/test-prog -t/destroy.t -t/esub.t -t/exit.t -t/muarg.t -t/mult.t -t/sh-c.t -t/simple.t -t/stdouterr.t -t/time.t -t/wait.t -META.json Module JSON meta-data (added by MakeMaker) diff --git a/perl/third/Proc-Simple-1.32/MANIFEST.SKIP b/perl/third/Proc-Simple-1.32/MANIFEST.SKIP deleted file mode 100644 index 4b8c1e7..0000000 --- a/perl/third/Proc-Simple-1.32/MANIFEST.SKIP +++ /dev/null @@ -1,12 +0,0 @@ -.gz -.git -blib -^Makefile$ -^Makefile.old$ -CVS -.cvsignore -docs -MANIFEST.bak -adm/release -MYMETA.json -MYMETA.yml diff --git a/perl/third/Proc-Simple-1.32/META.json b/perl/third/Proc-Simple-1.32/META.json deleted file mode 100644 index c371d0a..0000000 --- a/perl/third/Proc-Simple-1.32/META.json +++ /dev/null @@ -1,47 +0,0 @@ -{ - "abstract" : "unknown", - "author" : [ - "unknown" - ], - "dynamic_config" : 1, - "generated_by" : "ExtUtils::MakeMaker version 7.04, CPAN::Meta::Converter version 2.142690", - "license" : [ - "unknown" - ], - "meta-spec" : { - "url" : "http://search.cpan.org/perldoc?CPAN::Meta::Spec", - "version" : "2" - }, - "name" : "Proc-Simple", - "no_index" : { - "directory" : [ - "t", - "inc" - ] - }, - "prereqs" : { - "build" : { - "requires" : { - "ExtUtils::MakeMaker" : "0" - } - }, - "configure" : { - "requires" : { - "ExtUtils::MakeMaker" : "0" - } - }, - "runtime" : { - "requires" : { - "IO::Handle" : "0", - "Test::More" : "0" - } - } - }, - "release_status" : "stable", - "resources" : { - "repository" : { - "url" : "http://github.com/mschilli/proc-simple-perl" - } - }, - "version" : "1.32" -} diff --git a/perl/third/Proc-Simple-1.32/META.yml b/perl/third/Proc-Simple-1.32/META.yml deleted file mode 100644 index bcc35db..0000000 --- a/perl/third/Proc-Simple-1.32/META.yml +++ /dev/null @@ -1,25 +0,0 @@ ---- -abstract: unknown -author: - - unknown -build_requires: - ExtUtils::MakeMaker: '0' -configure_requires: - ExtUtils::MakeMaker: '0' -dynamic_config: 1 -generated_by: 'ExtUtils::MakeMaker version 7.04, CPAN::Meta::Converter version 2.142690' -license: unknown -meta-spec: - url: http://module-build.sourceforge.net/META-spec-v1.4.html - version: '1.4' -name: Proc-Simple -no_index: - directory: - - t - - inc -requires: - IO::Handle: '0' - Test::More: '0' -resources: - repository: http://github.com/mschilli/proc-simple-perl -version: '1.32' diff --git a/perl/third/Proc-Simple-1.32/Makefile.PL b/perl/third/Proc-Simple-1.32/Makefile.PL deleted file mode 100644 index 6535f64..0000000 --- a/perl/third/Proc-Simple-1.32/Makefile.PL +++ /dev/null @@ -1,21 +0,0 @@ - -use ExtUtils::MakeMaker; - -my $meta_merge = { - META_MERGE => { - resources => { - repository => 'http://github.com/mschilli/proc-simple-perl', - }, - } -}; - -WriteMakefile( - 'VERSION_FROM' => "Simple.pm", - 'NAME' => 'Proc::Simple', - 'dist' => { COMPRESS=>"gzip", SUFFIX=>"gz" }, - PREREQ_PM => { - 'Test::More' => 0, - 'IO::Handle' => 0, - }, - $ExtUtils::MakeMaker::VERSION >= 6.50 ? (%$meta_merge) : (), -); diff --git a/perl/third/Proc-Simple-1.32/README b/perl/third/Proc-Simple-1.32/README deleted file mode 100644 index a262340..0000000 --- a/perl/third/Proc-Simple-1.32/README +++ /dev/null @@ -1,311 +0,0 @@ -###################################################################### - Proc::Simple 1.32 -###################################################################### - -NAME - Proc::Simple -- launch and control background processes - -SYNOPSIS - use Proc::Simple; - - $myproc = Proc::Simple->new(); # Create a new process object - - $myproc->start("shell-command-line"); # Launch an external program - $myproc->start("command", # Launch an external program - "param", ...); # with parameters - - $myproc->start(sub { ... }); # Launch a perl subroutine - $myproc->start(\&subroutine); # Launch a perl subroutine - $myproc->start(\&subroutine, # Launch a perl subroutine - $param, ...); # with parameters - - $running = $myproc->poll(); # Poll Running Process - - $exit_status = $myproc->wait(); # Wait until process is done - - $proc->kill_on_destroy(1); # Set kill on destroy - $proc->signal_on_destroy("KILL"); # Specify signal to be sent - # on destroy - - $myproc->kill(); # Kill Process (SIGTERM) - - - - $myproc->kill("SIGUSR1"); # Send specified signal - - $myproc->exit_status(); # Return exit status of process - - - Proc::Simple::debug($level); # Turn debug on - -DESCRIPTION - The Proc::Simple package provides objects mimicing real-life processes - from a user's point of view. A new process object is created by - - $myproc = Proc::Simple->new(); - - Either external programs or perl subroutines can be launched and - controlled as processes in the background. - - A 10-second sleep process, for example, can be launched as an external - program as in - - $myproc->start("/bin/sleep 10"); # or - $myproc->start("/bin/sleep", "10"); - - or as a perl subroutine, as in - - sub mysleep { sleep(shift); } # Define mysleep() - $myproc->start(\&mysleep, 10); # Launch it. - - or even as - - $myproc->start(sub { sleep(10); }); - - The *start* Method returns immediately after starting the specified - process in background, i.e. there's no blocking. It returns *1* if the - process has been launched successfully and *0* if not. - - The *poll* method checks if the process is still running - - $running = $myproc->poll(); - - and returns *1* if it is, *0* if it's not. Finally, - - $myproc->kill(); - - terminates the process by sending it the SIGTERM signal. As an option, - another signal can be specified. - - $myproc->kill("SIGUSR1"); - - sends the SIGUSR1 signal to the running process. *kill* returns *1* if - it succeeds in sending the signal, *0* if it doesn't. - - The methods are discussed in more detail in the next section. - - A destructor is provided so that a signal can be sent to the forked - processes automatically should the process object be destroyed or if the - process exits. By default this behaviour is turned off (see the - kill_on_destroy and signal_on_destroy methods). - -METHODS - The following methods are available: - - new (Constructor) - Create a new instance of this class by writing - - $proc = new Proc::Simple; - - or - - $proc = Proc::Simple->new(); - - It takes no arguments. - - start - Launches a new process. The "start()" method can be used to launch - both external programs (like "/bin/echo") or one of your - self-defined subroutines (like "foo()") in a new process. - - For an external program to be started, call - - $status = $proc->start("program-name"); - - If you want to pass a couple of parameters to the launched program, - there's two options: You can either pass them in one argument like - in - - $status = $proc->start("/bin/echo hello world"); - - or in several arguments like in - - $status = $proc->start("/bin/echo", "hello", "world"); - - Just as in Perl's function "system()", there's a big difference - between the two methods: If you provide one argument containing a - blank-separated command line, your shell is going to process any - meta-characters (if you choose to use some) before the process is - actually launched: - - $status = $proc->start("/bin/ls -l /etc/initt*"); - - will expand "/etc/initt*" to "/etc/inittab" before running the "ls" - command. If, on the other hand, you say - - $status = $proc->start("/bin/ls", "-l", "*"); - - the "*" will stay unexpanded, meaning you'll look for a file with - the literal name "*" (which is unlikely to exist on your system - unless you deliberately create confusingly named files :). For more - info on this, look up "perldoc -f exec". - - If, on the other hand, you want to start a Perl subroutine in the - background, simply provide the function reference like - - $status = $proc->start(\&your_function); - - or supply an unnamed subroutine: - - $status = $proc->start( sub { sleep(1) } ); - - You can also provide additional parameters to be passed to the - function: - - $status = $proc->start(\&printme, "hello", "world"); - - The *start* Method returns immediately after starting the specified - process in background, i.e. non-blocking mode. It returns *1* if the - process has been launched successfully and *0* if not. - - poll - The *poll* method checks if the process is still running - - $running = $myproc->poll(); - - and returns *1* if it is, *0* if it's not. - - kill - The kill() method: - - $myproc->kill(); - - terminates the process by sending it the SIGTERM signal. As an - option, another signal can be specified. - - $myproc->kill("SIGUSR1"); - - sends the SIGUSR1 signal to the running process. *kill* returns *1* - if it succeeds in sending the signal, *0* if it doesn't. - - kill_on_destroy - Set a flag to determine whether the process attached to this object - should be killed when the object is destroyed. By default, this flag - is set to false. The current value is returned. - - $current = $proc->kill_on_destroy; - $proc->kill_on_destroy(1); # Set flag to true - $proc->kill_on_destroy(0); # Set flag to false - - signal_on_destroy - Method to set the signal that will be sent to the process when the - object is destroyed (Assuming kill_on_destroy is true). Returns the - current setting. - - $current = $proc->signal_on_destroy; - $proc->signal_on_destroy("KILL"); - - redirect_output - Redirects stdout and/or stderr output to a file. Specify undef to - leave the stderr/stdout handles of the process alone. - - # stdout to a file, left stderr unchanged - $proc->redirect_output ("/tmp/someapp.stdout", undef); - - # stderr to a file, left stdout unchanged - $proc->redirect_output (undef, "/tmp/someapp.stderr"); - - # stdout and stderr to a separate file - $proc->redirect_output ("/tmp/someapp.stdout", "/tmp/someapp.stderr"); - - Call this method before running the start method. - - pid Returns the pid of the forked process associated with this object - - $pid = $proc->pid; - - t0 Returns the start time() of the forked process associated with this - object - - $t0 = $proc->t0(); - - t1 Returns the stop time() of the forked process associated with this - object - - $t1 = $proc->t1(); - - DESTROY (Destructor) - Object destructor. This method is called when the object is - destroyed (eg with "undef" or on exiting perl). If kill_on_destroy - is true the process associated with the object is sent the - signal_on_destroy signal (SIGTERM if undefined). - - exit_status - Returns the exit status of the process as the $! variable indicates. - If the process is still running, "undef" is returned. - - wait - The *wait* method: - - $exit_status = $myproc->wait(); - - waits until the process is done and returns its exit status. - - debug - Switches debug messages on and off -- Proc::Simple::debug(1) - switches them on, Proc::Simple::debug(0) keeps Proc::Simple quiet. - - cleanup - Proc::Simple keeps around data of terminated processes, e.g. you can - check via "t0()" and "t1()" how long a process ran, even if it's - long gone. Over time, this data keeps occupying more and more memory - and if you have a long-running program, you might want to run - "Proc::Simple->cleanup()" every once in a while to get rid of data - pertaining to processes no longer in use. - -NOTE - Please keep in mind that there is no guarantee that the SIGTERM signal - really terminates a process. Processes can have signal handlers defined - that avoid the shutdown. If in doubt, whether a process still exists, - check it repeatedly with the *poll* routine after sending the signal. - -Shell Processes - If you pass a shell program to Proc::Simple, it'll use "exec()" to - launch it. As noted in Perl's "exec()" manpage, simple commands for the - one-argument version of "exec()" will be passed to "execvp()" directly, - while commands containing characters like ";" or "*" will be passed to a - shell to make sure those get the shell expansion treatment. - - This has the interesting side effect that if you launch something like - - $p->start("./womper *"); - - then you'll see two processes in your process list: - - $ ps auxww | grep womper - mschilli 9126 11:21 0:00 sh -c ./womper * - mschilli 9127 11:21 0:00 /usr/local/bin/perl -w ./womper ... - - A regular "kill()" on the process PID would only kill the first process, - but Proc::Simple's "kill()" will use a negative signal and send it to - the first process (9126). Since it has marked the process as a process - group leader when it created it previously (via setsid()), this will - cause both processes above to receive the signal sent by "kill()". - -Contributors - Tim Jenness did - kill_on_destroy/signal_on_destroy/pid - - Mark R. Southern worked on EXIT_STATUS - tracking - - Tobias Jahn added redirection to - stdout/stderr - - Clauss Strauch suggested the - multi-arg start()-methods. - - Chip Capelik contributed a patch with the wait() method. - - Jeff Holt provided a patch for time tracking with t0() and t1(). - - Brad Cavanagh fixed RT33440 (unreliable $?) - -AUTHOR - 1996, Mike Schilli - -LICENSE - Copyright 1996-2011 by Mike Schilli, all rights reserved. This program - is free software, you can redistribute it and/or modify it under the - same terms as Perl itself. - diff --git a/perl/third/Proc-Simple-1.32/Simple.pm b/perl/third/Proc-Simple-1.32/Simple.pm deleted file mode 100644 index 8dde0f7..0000000 --- a/perl/third/Proc-Simple-1.32/Simple.pm +++ /dev/null @@ -1,841 +0,0 @@ -###################################################################### -package Proc::Simple; -###################################################################### -# Copyright 1996-2001 by Michael Schilli, all rights reserved. -# -# This program is free software, you can redistribute it and/or -# modify it under the same terms as Perl itself. -# -# The newest version of this module is available on -# http://perlmeister.com/devel -# or on your favourite CPAN site under -# CPAN/modules/by-author/id/MSCHILLI -# -###################################################################### - -=head1 NAME - -Proc::Simple -- launch and control background processes - -=head1 SYNOPSIS - - use Proc::Simple; - - $myproc = Proc::Simple->new(); # Create a new process object - - $myproc->start("shell-command-line"); # Launch an external program - $myproc->start("command", # Launch an external program - "param", ...); # with parameters - - $myproc->start(sub { ... }); # Launch a perl subroutine - $myproc->start(\&subroutine); # Launch a perl subroutine - $myproc->start(\&subroutine, # Launch a perl subroutine - $param, ...); # with parameters - - $running = $myproc->poll(); # Poll Running Process - - $exit_status = $myproc->wait(); # Wait until process is done - - $proc->kill_on_destroy(1); # Set kill on destroy - $proc->signal_on_destroy("KILL"); # Specify signal to be sent - # on destroy - - $myproc->kill(); # Kill Process (SIGTERM) - - - - $myproc->kill("SIGUSR1"); # Send specified signal - - $myproc->exit_status(); # Return exit status of process - - - Proc::Simple::debug($level); # Turn debug on - -=head1 DESCRIPTION - -The Proc::Simple package provides objects mimicing real-life -processes from a user's point of view. A new process object is created by - - $myproc = Proc::Simple->new(); - -Either external programs or perl subroutines can be launched and -controlled as processes in the background. - -A 10-second sleep process, for example, can be launched -as an external program as in - - $myproc->start("/bin/sleep 10"); # or - $myproc->start("/bin/sleep", "10"); - -or as a perl subroutine, as in - - sub mysleep { sleep(shift); } # Define mysleep() - $myproc->start(\&mysleep, 10); # Launch it. - -or even as - - $myproc->start(sub { sleep(10); }); - -The I Method returns immediately after starting the -specified process in background, i.e. there's no blocking. -It returns I<1> if the process has been launched -successfully and I<0> if not. - -The I method checks if the process is still running - - $running = $myproc->poll(); - -and returns I<1> if it is, I<0> if it's not. Finally, - - $myproc->kill(); - -terminates the process by sending it the SIGTERM signal. As an -option, another signal can be specified. - - $myproc->kill("SIGUSR1"); - -sends the SIGUSR1 signal to the running process. I returns I<1> if -it succeeds in sending the signal, I<0> if it doesn't. - -The methods are discussed in more detail in the next section. - -A destructor is provided so that a signal can be sent to -the forked processes automatically should the process object be -destroyed or if the process exits. By default this -behaviour is turned off (see the kill_on_destroy and -signal_on_destroy methods). - -=cut - -require 5.003; -use strict; -use vars qw($VERSION %EXIT_STATUS %INTERVAL - %DESTROYED); - -use POSIX; -use IO::Handle; - -$VERSION = '1.32'; - -###################################################################### -# Globals: Debug and the mysterious waitpid nohang constant. -###################################################################### -my $Debug = 0; -my $WNOHANG = get_system_nohang(); - -###################################################################### - -=head1 METHODS - -The following methods are available: - -=over 4 - -=item new (Constructor) - -Create a new instance of this class by writing - - $proc = new Proc::Simple; - -or - - $proc = Proc::Simple->new(); - -It takes no arguments. - -=cut - -###################################################################### -# $proc_obj=Proc::Simple->new(); - Constructor -###################################################################### -sub new { - my $proto = shift; - my $class = ref($proto) || $proto; - - my $self = {}; - - # Init instance variables - $self->{'kill_on_destroy'} = undef; - $self->{'signal_on_destroy'} = undef; - $self->{'pid'} = undef; - $self->{'redirect_stdout'} = undef; - $self->{'redirect_stderr'} = undef; - - bless($self, $class); -} - -###################################################################### - -=item start - -Launches a new process. -The C method can be used to launch both external programs -(like C) or one of your self-defined subroutines -(like C) in a new process. - -For an external program to be started, call - - $status = $proc->start("program-name"); - -If you want to pass a couple of parameters to the launched program, -there's two options: You can either pass them in one argument like -in - - $status = $proc->start("/bin/echo hello world"); - -or in several arguments like in - - $status = $proc->start("/bin/echo", "hello", "world"); - -Just as in Perl's function C, there's a big difference -between the two methods: If you provide one argument containing -a blank-separated command line, your shell is going to -process any meta-characters (if you choose to use some) before -the process is actually launched: - - $status = $proc->start("/bin/ls -l /etc/initt*"); - -will expand C to C before running the C -command. If, on the other hand, you say - - $status = $proc->start("/bin/ls", "-l", "*"); - -the C<*> will stay unexpanded, meaning you'll look for a file with the -literal name C<*> (which is unlikely to exist on your system unless -you deliberately create confusingly named files :). For -more info on this, look up C. - -If, on the other hand, you want to start a Perl subroutine -in the background, simply provide the function reference like - - $status = $proc->start(\&your_function); - -or supply an unnamed subroutine: - - $status = $proc->start( sub { sleep(1) } ); - -You can also provide additional parameters to be passed to the function: - - $status = $proc->start(\&printme, "hello", "world"); - -The I Method returns immediately after starting the -specified process in background, i.e. non-blocking mode. -It returns I<1> if the process has been launched -successfully and I<0> if not. - -=cut - -###################################################################### -# $ret = $proc_obj->start("prg"); - Launch process -###################################################################### -sub start { - my $self = shift; - my ($func, @params) = @_; - - # Reap Zombies automatically - $SIG{'CHLD'} = \&THE_REAPER; - - # Fork a child process - $self->{'pid'} = fork(); - return 0 unless defined $self->{'pid'}; # return Error if fork failed - - if($self->{pid} == 0) { # Child - # Mark it as process group leader, so that we can kill - # the process group later. Note that there's a race condition - # here because there's a window in time (while you're reading - # this comment) between child startup and its new process group - # id being defined. This means that killpg() to the child during - # this time frame will fail. Proc::Simple's kill() method deals l - # with it, see comments there. - POSIX::setsid(); - $self->dprt("setsid called ($$)"); - - if (defined $self->{'redirect_stderr'}) { - $self->dprt("STDERR -> $self->{'redirect_stderr'}"); - open(STDERR, ">", $self->{'redirect_stderr'}) ; - autoflush STDERR 1 ; - } - - if (defined $self->{'redirect_stdout'}) { - $self->dprt("STDOUT -> $self->{'redirect_stdout'}"); - open(STDOUT, ">", $self->{'redirect_stdout'}) ; - autoflush STDOUT 1 ; - } - - if(ref($func) eq "CODE") { - $self->dprt("Launching code"); - $func->(@params); exit 0; # Start perl subroutine - } else { - $self->dprt("Launching $func @params"); - exec $func, @params; # Start shell process - exit 0; # In case something goes wrong - } - } elsif($self->{'pid'} > 0) { # Parent: - $INTERVAL{$self->{'pid'}}{'t0'} = time(); - $self->dprt("START($self->{'pid'})"); - # Register PID - $EXIT_STATUS{$self->{'pid'}} = undef; - $INTERVAL{$self->{'pid'}}{'t1'} = undef; - return 1; # return OK - } else { - return 0; # this shouldn't occur - } -} - -###################################################################### - -=item poll - -The I method checks if the process is still running - - $running = $myproc->poll(); - -and returns I<1> if it is, I<0> if it's not. - -=cut - -###################################################################### -# $ret = $proc_obj->poll(); - Check process status -# 1="running" 0="not running" -###################################################################### -sub poll { - my $self = shift; - - $self->dprt("Polling"); - - # There's some weirdness going on with the signal handler. - # It runs into timing problems, so let's have poll() call - # the REAPER every time to make sure we're getting rid of - # defuncts. - $self->THE_REAPER(); - - if(defined($self->{pid})) { - if(CORE::kill(0, $self->{pid})) { - $self->dprt("POLL($self->{pid}) RESPONDING"); - return 1; - } else { - $self->dprt("POLL($self->{pid}) NOT RESPONDING"); - } - } else { - $self->dprt("POLL(NOT DEFINED)"); - } - - 0; -} - -###################################################################### - -=item kill - -The kill() method: - - $myproc->kill(); - -terminates the process by sending it the SIGTERM signal. As an -option, another signal can be specified. - - $myproc->kill("SIGUSR1"); - -sends the SIGUSR1 signal to the running process. I returns I<1> if -it succeeds in sending the signal, I<0> if it doesn't. - -=cut - -###################################################################### -# $ret = $proc_obj->kill([SIGXXX]); - Send signal to process -# Default-Signal: SIGTERM -###################################################################### -sub kill { - my $self = shift; - my $sig = shift; - - # If no signal specified => SIGTERM-Signal - $sig = POSIX::SIGTERM() unless defined $sig; - - # Use numeric signal if we get a string - if( $sig !~ /^[-\d]+$/ ) { - $sig =~ s/^SIG//g; - $sig = eval "POSIX::SIG${sig}()"; - } - - # Process initialized at all? - if( !defined $self->{'pid'} ) { - $self->dprt("No pid set"); - return 0; - } - - # Send signal - if(CORE::kill($sig, $self->{'pid'})) { - $self->dprt("KILL($sig, $self->{'pid'}) OK"); - - # now kill process group of process to make sure that shell - # processes containing shell characters, which get launched via - # "sh -c" are killed along with their launching shells. - # This might fail because of the race condition explained in - # start(), so we ignore the outcome. - CORE::kill(-$sig, $self->{'pid'}); - } else { - $self->dprt("KILL($sig, $self->{'pid'}) failed ($!)"); - return 0; - } - - 1; -} - -###################################################################### - -=item kill_on_destroy - -Set a flag to determine whether the process attached -to this object should be killed when the object is -destroyed. By default, this flag is set to false. -The current value is returned. - - $current = $proc->kill_on_destroy; - $proc->kill_on_destroy(1); # Set flag to true - $proc->kill_on_destroy(0); # Set flag to false - -=cut - -###################################################################### -# Method to set the kill_on_destroy flag -###################################################################### -sub kill_on_destroy { - my $self = shift; - if (@_) { $self->{kill_on_destroy} = shift; } - return $self->{kill_on_destroy}; -} - -###################################################################### - -=item signal_on_destroy - -Method to set the signal that will be sent to the -process when the object is destroyed (Assuming -kill_on_destroy is true). Returns the current setting. - - $current = $proc->signal_on_destroy; - $proc->signal_on_destroy("KILL"); - -=cut - -###################################################################### -# Send a signal on destroy -# undef means send the default signal (SIGTERM) -###################################################################### -sub signal_on_destroy { - my $self = shift; - if (@_) { $self->{signal_on_destroy} = shift; } - return $self->{signal_on_destroy}; -} - -###################################################################### - -=item redirect_output - -Redirects stdout and/or stderr output to a file. -Specify undef to leave the stderr/stdout handles of the process alone. - - # stdout to a file, left stderr unchanged - $proc->redirect_output ("/tmp/someapp.stdout", undef); - - # stderr to a file, left stdout unchanged - $proc->redirect_output (undef, "/tmp/someapp.stderr"); - - # stdout and stderr to a separate file - $proc->redirect_output ("/tmp/someapp.stdout", "/tmp/someapp.stderr"); - -Call this method before running the start method. - -=cut - -###################################################################### -sub redirect_output { -###################################################################### - - my $self = shift ; - ($self->{'redirect_stdout'}, $self->{'redirect_stderr'}) = @_ ; - - 1 ; -} - -###################################################################### - -=item pid - -Returns the pid of the forked process associated with -this object - - $pid = $proc->pid; - -=cut - -###################################################################### -sub pid { -###################################################################### - my $self = shift; - - # Allow the pid to be set - assume this is only - # done internally so don't document this behaviour in the - # pod. - if (@_) { $self->{'pid'} = shift; } - return $self->{'pid'}; -} - -###################################################################### - -=item t0 - -Returns the start time() of the forked process associated with -this object - - $t0 = $proc->t0(); - -=cut - -###################################################################### -sub t0 { -###################################################################### - my $self = shift; - - return $INTERVAL{$self->{'pid'}}{'t0'}; -} - -###################################################################### - -=item t1 - -Returns the stop time() of the forked process associated with -this object - - $t1 = $proc->t1(); - -=cut - -###################################################################### -sub t1 { -###################################################################### - my $self = shift; - - return $INTERVAL{$self->{'pid'}}{'t1'}; -} - -=item DESTROY (Destructor) - -Object destructor. This method is called when the -object is destroyed (eg with "undef" or on exiting -perl). If kill_on_destroy is true the process -associated with the object is sent the signal_on_destroy -signal (SIGTERM if undefined). - -=cut - -###################################################################### -# Destroy method -# This is run automatically on undef -# Should probably not bother if a poll shows that the process is not -# running. -###################################################################### -sub DESTROY { - my $self = shift; - - # Localize special variables so that the exit status from waitpid - # doesn't leak out, causing exit status to be incorrect. - local( $., $@, $!, $^E, $? ); - - # Processes never started don't have to be cleaned up in - # any special way. - return unless $self->pid(); - - # If the kill_on_destroy flag is true then - # We need to send a signal to the process - if ($self->kill_on_destroy) { - $self->dprt("Kill on DESTROY"); - if (defined $self->signal_on_destroy) { - $self->kill($self->signal_on_destroy); - } else { - $self->dprt("Sending KILL"); - $self->kill; - } - } - delete $EXIT_STATUS{ $self->pid }; - if( $self->poll() ) { - $DESTROYED{ $self->pid } = 1; - } -} - -###################################################################### - -=item exit_status - -Returns the exit status of the process as the $! variable indicates. -If the process is still running, C is returned. - -=cut - -###################################################################### -# returns the exit status of the child process, undef if the child -# hasn't yet exited -###################################################################### -sub exit_status{ - my( $self ) = @_; - return $EXIT_STATUS{ $self->pid }; -} - -###################################################################### - -=item wait - -The I method: - - $exit_status = $myproc->wait(); - -waits until the process is done and returns its exit status. - -=cut - -###################################################################### -# waits until the child process terminates and then -# returns the exit status of the child process. -###################################################################### -sub wait { - my $self = shift; - - local $SIG{CHLD}; # disable until we're done - - my $pid = $self->pid(); - - # test if the signal handler reap'd this pid some time earlier or even just - # a split second before localizing $SIG{CHLD} above; also kickout if - # they've wait'd or waitpid'd on this pid before ... - - return $EXIT_STATUS{$pid} if defined $EXIT_STATUS{$pid}; - - # all systems support FLAGS==0 (accg to: perldoc -f waitpid) - my $res = waitpid $pid, 0; - my $rc = $?; - - $INTERVAL{$pid}{'t1'} = time(); - $EXIT_STATUS{$pid} = $rc; - dprt("", "For $pid, reaped '$res' with exit_status=$rc"); - - return $rc; -} - -###################################################################### -# Reaps processes, uses the magic WNOHANG constant -###################################################################### -sub THE_REAPER { - - # Localize special variables so that the exit status from waitpid - # doesn't leak out, causing exit status to be incorrect. - local( $., $@, $!, $^E, $? ); - - my $child; - my $now = time(); - - if(defined $WNOHANG) { - # Try to reap every process we've ever started and - # whichs Proc::Simple object hasn't been destroyed. - # - # This is getting really ugly. But if we just call the REAPER - # for every SIG{CHLD} event, code like this will fail: - # - # use Proc::Simple; - # $proc = Proc::Simple->new(); $proc->start(\&func); sleep(5); - # sub func { open(PIPE, "/bin/ls |"); @a = ; sleep(1); - # close(PIPE) or die "PIPE failed"; } - # - # Reason: close() doesn't like it if the spawn has - # been reaped already. Oh well. - # - - # First, check if we can reap the processes which - # went out of business because their kill_on_destroy - # flag was set and their objects were destroyed. - foreach my $pid (keys %DESTROYED) { - if(my $res = waitpid($pid, $WNOHANG) > 0) { - # We reaped a zombie - delete $DESTROYED{$pid}; - dprt("", "Reaped: $pid"); - } - } - - foreach my $pid (keys %EXIT_STATUS) { - dprt("", "Trying to reap $pid"); - if( defined $EXIT_STATUS{$pid} ) { - dprt("", "exit status of $pid is defined - not reaping"); - next; - } - if(my $res = waitpid($pid, $WNOHANG) > 0) { - # We reaped a truly running process - $EXIT_STATUS{$pid} = $?; - $INTERVAL{$pid}{'t1'} = $now; - dprt("", "Reaped: $pid"); - } else { - dprt("", "waitpid returned '$res'"); - } - } - } else { - # If we don't have $WNOHANG, we don't have a choice anyway. - # Just reap everything. - dprt("", "reap everything for lack of WNOHANG"); - $child = CORE::wait(); - $EXIT_STATUS{$child} = $?; - $INTERVAL{$child}{'t1'} = $now; - } - - # Don't reset signal handler for crappy sysV systems. Screw them. - # This caused problems with Irix 6.2 - # $SIG{'CHLD'} = \&THE_REAPER; -} - -###################################################################### - -=item debug - -Switches debug messages on and off -- Proc::Simple::debug(1) switches -them on, Proc::Simple::debug(0) keeps Proc::Simple quiet. - -=cut - -# Proc::Simple::debug($level) - Turn debug on/off -sub debug { $Debug = shift; } - -###################################################################### - -=item cleanup - -Proc::Simple keeps around data of terminated processes, e.g. you can check via -C and C how long a process ran, even if it's long gone. Over time, -this data keeps occupying more and more memory and if you have a long-running -program, you might want to run Ccleanup()> every once in a -while to get rid of data pertaining to processes no longer in use. - -=cut - -sub cleanup { - - for my $pid ( keys %INTERVAL ) { - if( !exists $DESTROYED{ $pid } ) { - # process has been reaped already, safe to delete - # its start/stop time - delete $INTERVAL{ $pid }; - } - } -} - -###################################################################### -# Internal debug print function -###################################################################### -sub dprt { - my $self = shift; - if($Debug) { - require Time::HiRes; - my ($seconds, $microseconds) = Time::HiRes::gettimeofday(); - print "[$seconds.$microseconds] ", ref($self), "> @_\n"; - } -} - -###################################################################### -sub get_system_nohang { -###################################################################### -# This is for getting the WNOHANG constant of the system -- but since -# the waitpid(-1, &WNOHANG) isn't supported on all Unix systems, and -# we still want Proc::Simple to run on every system, we have to -# quietly perform some tests to figure out if -- or if not. -# The function returns the constant, or undef if it's not available. -###################################################################### - my $nohang; - - open(SAVEERR, ">&STDERR"); - - # If the system doesn't even know /dev/null, forget about it. - open(STDERR, ">/dev/null") || return undef; - # Close stderr, since some weirdo POSIX modules write nasty - # error messages - close(STDERR); - - # Check for the constant - eval 'use POSIX ":sys_wait_h"; $nohang = &WNOHANG;'; - - # Re-open STDERR - open(STDERR, ">&SAVEERR"); - close(SAVEERR); - - # If there was an error, return undef - return undef if $@; - - return $nohang; -} - -1; - -__END__ - -=back - -=head1 NOTE - -Please keep in mind that there is no guarantee that the SIGTERM -signal really terminates a process. Processes can have signal -handlers defined that avoid the shutdown. -If in doubt, whether a process still exists, check it -repeatedly with the I routine after sending the signal. - -=head1 Shell Processes - -If you pass a shell program to Proc::Simple, it'll use C to -launch it. As noted in Perl's C manpage, simple commands for -the one-argument version of C will be passed to -C directly, while commands containing characters -like C<;> or C<*> will be passed to a shell to make sure those get -the shell expansion treatment. - -This has the interesting side effect that if you launch something like - - $p->start("./womper *"); - -then you'll see two processes in your process list: - - $ ps auxww | grep womper - mschilli 9126 11:21 0:00 sh -c ./womper * - mschilli 9127 11:21 0:00 /usr/local/bin/perl -w ./womper ... - -A regular C on the process PID would only kill the first -process, but Proc::Simple's C will use a negative signal -and send it to the first process (9126). Since it has marked the -process as a process group leader when it created it previously -(via setsid()), this will cause both processes above to receive the -signal sent by C. - -=head1 Contributors - -Tim Jenness - did kill_on_destroy/signal_on_destroy/pid - -Mark R. Southern - worked on EXIT_STATUS tracking - -Tobias Jahn - added redirection to stdout/stderr - -Clauss Strauch -suggested the multi-arg start()-methods. - -Chip Capelik contributed a patch with the wait() method. - -Jeff Holt provided a patch for time tracking with t0() and t1(). - -Brad Cavanagh fixed RT33440 (unreliable $?) - -=head1 AUTHOR - - 1996, Mike Schilli - -=head1 LICENSE - -Copyright 1996-2011 by Mike Schilli, all rights reserved. -This program is free software, you can redistribute it and/or -modify it under the same terms as Perl itself. - diff --git a/perl/third/Proc-Simple-1.32/eg/parproc.pl b/perl/third/Proc-Simple-1.32/eg/parproc.pl deleted file mode 100755 index a0fb42c..0000000 --- a/perl/third/Proc-Simple-1.32/eg/parproc.pl +++ /dev/null @@ -1,36 +0,0 @@ -#!/usr/local/bin/perl -w -###################################################################### -# parproc.pl -- Sample script, runs 10 jobs, 5 at a time. -# -# From the book Perl Power! (Addison-Wesley) by Michael Schilli 1999 -###################################################################### - -use Proc::Simple; - -$| = 1; # debuffer output -$max_parallel_jobs = 5; # jobs processed in parallel -@running = (); # array of running jobs - -foreach $job (1..9) { # create pseudo jobs - push(@todo, "sleep 3"); -} - -###################################################################### - # while there are jobs to do -while($#todo >= 0 || $#running >= 0) { # or started ones are running - @running = grep { $_->poll() } @running; # remove finished jobs - - if($#running + 1 < $max_parallel_jobs && # space free in running? - defined($job = pop(@todo))) { # ... and job available - - print "Starting job '$job' ... "; - $proc = Proc::Simple->new(); # new process - $proc->start($job) || die "Cannot start job $job"; - push(@running, $proc); # include in running list - - print "STARTED. (Remaining: ", $#todo+1, - " Running: ", $#running + 1, ")\n"; - next; # proceed without delay - } - sleep(1); # pause ... and proceed -} diff --git a/perl/third/Proc-Simple-1.32/t/bin/test-prog b/perl/third/Proc-Simple-1.32/t/bin/test-prog deleted file mode 100755 index 376ce4c..0000000 --- a/perl/third/Proc-Simple-1.32/t/bin/test-prog +++ /dev/null @@ -1,13 +0,0 @@ - -# test perl program - -use FindBin qw($Bin); - -my $testfile = "$Bin/../test-prog-running"; - -open FILE, ">$testfile" or die "Can't open $testfile: $!"; -close FILE; - -$SIG{ TERM } = sub { unlink $testfile; }; - -sleep 30; diff --git a/perl/third/Proc-Simple-1.32/t/destroy.t b/perl/third/Proc-Simple-1.32/t/destroy.t deleted file mode 100644 index 1cef54b..0000000 --- a/perl/third/Proc-Simple-1.32/t/destroy.t +++ /dev/null @@ -1,84 +0,0 @@ -#!/usr/bin/perl -w - -# Test the destructor code -# This test code has two parts: -# i) Fork a perl infinite loop -# Retrieve the process id of the forked process -# Undef the object -# Try to kill the forked process - -# ii)Fork a perl infinite loop -# Retrieve the process id of the forked process -# Set the kill_on_destroy flag -# Undef the object -# Try to kill the forked process - -# In the first test the kill should succeed (since the process -# will still be running. In the second test the kill will fail -# since the destructor will have already killed the process. -# A sleep of 1 is inserted to make sure the kill signal arrives -# and the process shuts down before we check. -# We check the process is running by looking at the return -# value from perl kill. - - -use Proc::Simple; -use Test::More; - -plan tests => 5; - -### -### Simple Test of destroy -### - -### Test code - -$coderef = sub { while (1) { sleep(1) } }; # infinite loop - -$psh = Proc::Simple->new(); - -ok($psh->start($coderef)); # 1 - -# Retrieve the process id (so that we can look for it later) - -my $pid = $psh->pid; - -# Destroy object - process should still be running -undef $psh; - -# Process should still be running - now kill it -# The sleep is here to make the test fair with the -# ond_destroy test later -sleep 2; -ok($result = kill "SIGTERM", $pid); # 2 - -ok($result == 1, "check result"); # 3 -# print "Result should equal 1 if process was killed by us: $result\n"; - -# Now try the same thing with the kill_on_destroy flag set - -$psh = Proc::Simple->new(); - -ok($psh->start($coderef)); # 4 - -# Retrieve the process id (so that we can look for it later) - -my $pid2 = $psh->pid; - -# Set flag -$psh->kill_on_destroy(1); - -# Destroy object - after that, process should terminate -undef $psh; - -# Process should no longer be running -# The sleep makes sure that the process has died by the time -# we get there -$i = 0; -while($i++ < 10) { - last unless kill 0, $pid2; - sleep(1); -} - -# Okay if we returned before the 10 secs expired -ok($i<10); diff --git a/perl/third/Proc-Simple-1.32/t/esub.t b/perl/third/Proc-Simple-1.32/t/esub.t deleted file mode 100755 index 3582320..0000000 --- a/perl/third/Proc-Simple-1.32/t/esub.t +++ /dev/null @@ -1,33 +0,0 @@ -#!/usr/bin/perl -w - -use Proc::Simple; - -package EmptySubclass; -@ISA = qw(Proc::Simple); -1; - - -package Main; -use Test::More; -plan tests => 3; - -### -### Empty Subclass test -### -# Proc::Simple::debug(1); - -$psh = EmptySubclass->new(); - -ok($psh->start("sleep 10")); # 1 - -while(!$psh->poll) { - sleep 1; } - -ok($psh->kill()) or die; # 2 - -while($psh->poll) { - sleep 1; } - -ok(1, "the end"); - -1; diff --git a/perl/third/Proc-Simple-1.32/t/exit.t b/perl/third/Proc-Simple-1.32/t/exit.t deleted file mode 100755 index 87bae06..0000000 --- a/perl/third/Proc-Simple-1.32/t/exit.t +++ /dev/null @@ -1,37 +0,0 @@ -#!/usr/bin/perl -w -################################################## -# Check the exit status feature -################################################## - -use Proc::Simple; -use Test::More; -plan tests => 1; - -#Proc::Simple::debug(1); - -$proc = Proc::Simple->new(); - -$proc->start("ls . >/dev/null"); -while($proc->poll()) { - sleep(1); -} - -if(defined $proc->exit_status()) { - $stat = $proc->exit_status(); -} else { - $stat = "undef"; -} -Proc::Simple->dprt("EXIT: '$stat'"); - -open PIPE, "ls |" or die "Cannot open pipe"; -my $data = ; -close PIPE or die "Cannot close pipe"; - -if(defined $proc->exit_status()) { - $stat = $proc->exit_status(); -} else { - $stat = "undef"; -} -Proc::Simple->dprt("EXIT: '$stat'"); - -is $stat, 0, "stat 0"; diff --git a/perl/third/Proc-Simple-1.32/t/muarg.t b/perl/third/Proc-Simple-1.32/t/muarg.t deleted file mode 100755 index f380c77..0000000 --- a/perl/third/Proc-Simple-1.32/t/muarg.t +++ /dev/null @@ -1,20 +0,0 @@ -#!/usr/bin/perl -w - -use Proc::Simple; -use Test::More; - -plan tests => 4; - -$psh = Proc::Simple->new(); - -ok($psh->start("sleep", "1")); # 1 -while($psh->poll) { - sleep 1; } -ok(!$psh->poll()); # 2 Must be dead - -sub mysleep { sleep(@_); } - -ok($psh->start(\&mysleep, 1)); # 3 -while($psh->poll) { - sleep 1; } -ok(!$psh->poll()); # 4 Must have been terminated diff --git a/perl/third/Proc-Simple-1.32/t/mult.t b/perl/third/Proc-Simple-1.32/t/mult.t deleted file mode 100755 index e786c3b..0000000 --- a/perl/third/Proc-Simple-1.32/t/mult.t +++ /dev/null @@ -1,33 +0,0 @@ -#!/usr/bin/perl -w - -use Proc::Simple; -use Test::More; -plan tests => 80; - -### -### Multiple Processes Test -### -#Proc::Simple->debug(1); - -foreach $i (0..19) { - $psh[$i] = Proc::Simple->new(); -} - -foreach $i (@psh) { - ok($i->start("sleep 60")); # 1-20 -} - -foreach $i (@psh) { - while(!$i->poll) { - sleep 1; } - ok($i->poll()); # Check each process, kill it - ok($i->kill()); # and check again: 21-80 - while($i->poll) { - sleep 1; } - ok(!$i->poll()); -} - -Proc::Simple->cleanup(); - -1; - diff --git a/perl/third/Proc-Simple-1.32/t/sh-c.t b/perl/third/Proc-Simple-1.32/t/sh-c.t deleted file mode 100755 index 4bc25eb..0000000 --- a/perl/third/Proc-Simple-1.32/t/sh-c.t +++ /dev/null @@ -1,53 +0,0 @@ -#!/usr/bin/perl -w - -use strict; -use Proc::Simple; -use Test::More; -use FindBin qw($Bin); - -my $runfile = "$Bin/test-prog-running"; - -plan tests => 3; - -unlink $runfile; # cleanup leftover from previous runs - -my $psh = Proc::Simple->new(); - - # contains a wildcard, so will be launched via sh -c -$psh->start("$^X $Bin/bin/test-prog *"); - -while( ! $psh->poll() ) { - # diag "waiting for process to start"; - sleep 1; -} - -ok 1, "process is up"; - - # wait for shell to spawn perl process -while( !-f $runfile ) { - # diag "waiting for process to create runfile $runfile"; - sleep 1; -} - -$psh->kill(); - -while( $psh->poll() ) { - # diag "waiting for process to shut down"; - sleep 1; -} - -ok 1, "process is down"; - -# as pointed out in [rt.cpan.org #69782], at this point, the grandchild -# might not have terminated yet or deleted the runfile, although its -# parent (the shell process) is gone. Allow 10 seconds max. -for(1..10) { - if( !-f "$Bin/test-prog-running" ) { - last; - } - sleep 1; -} - -ok !-f "$Bin/test-prog-running", "running file unlinked"; - -1; diff --git a/perl/third/Proc-Simple-1.32/t/simple.t b/perl/third/Proc-Simple-1.32/t/simple.t deleted file mode 100755 index bb7ce9c..0000000 --- a/perl/third/Proc-Simple-1.32/t/simple.t +++ /dev/null @@ -1,54 +0,0 @@ -#!/usr/bin/perl -w - -use Proc::Simple; - -package EmptySubclass; -@ISA = qw(Proc::Simple); -1; - -package Main; -use Test::More; - -plan tests => 10; - -### -### Simple Test -### - -### Shell commands - -# Proc::Simple::debug(1); -$psh = Proc::Simple->new(); - -ok($psh->start("sleep 1")); # 1 -while($psh->poll) { - sleep 1; } -ok(!$psh->poll()); # 2 Must have been terminated - -ok($psh->start("sleep 10")); # 3 -while(!$psh->poll) { - sleep 1; } -ok($psh->kill()); # 4 -while($psh->poll) { - sleep 1; } -ok(!$psh->poll()); # 5 Must have been terminated - - -### Perl subroutines -$psub = Proc::Simple->new(); - -ok($psub->start(sub { sleep 1 })); # 6 -while($psub->poll) { - sleep 1; } -ok(!$psub->poll()); # 7 Must have been terminated - -ok($psub->start(sub { sleep 10 })); # 8 -while(!$psub->poll) { - sleep 1; } - -ok($psub->kill("SIGTERM")); # 9 -while($psub->poll) { - sleep 1; } -ok(!$psub->poll()); # 10 Must have been terminated - -1; diff --git a/perl/third/Proc-Simple-1.32/t/stdouterr.t b/perl/third/Proc-Simple-1.32/t/stdouterr.t deleted file mode 100755 index 8a079bb..0000000 --- a/perl/third/Proc-Simple-1.32/t/stdouterr.t +++ /dev/null @@ -1,30 +0,0 @@ -#!/usr/bin/perl -w - -use Proc::Simple; -use Test::More; - -plan tests => 2; - -sub test_output { - print "hello stdout\n"; - print STDERR "hello stderr\n"; -} - -my $p = Proc::Simple->new(); -$p->redirect_output ("stdout.txt", "stderr.txt"); -$p->start(\&test_output); -while($p->poll()) { -} - -open FILE, "; -close FILE; - -open FILE, "; -close FILE; - -is $stderr, "hello stderr\n", "hello stderr"; -is $stdout, "hello stdout\n", "hello stdout"; - -unlink("stdout.txt", "stderr.txt"); diff --git a/perl/third/Proc-Simple-1.32/t/time.t b/perl/third/Proc-Simple-1.32/t/time.t deleted file mode 100644 index 025abb0..0000000 --- a/perl/third/Proc-Simple-1.32/t/time.t +++ /dev/null @@ -1,38 +0,0 @@ -#!/usr/bin/perl -w -################################################## -# Check the exit status feature -################################################## - -use Test::More tests => 9; -use Proc::Simple; - -#Proc::Simple::debug(1); - -my $errortolerance = 2; # this is necessary if the system under test is quite busy -my $proc = Proc::Simple->new(); - -my $t0 = time(); -my $start_rc = $proc->start("sleep 5"); -ok($start_rc, 'start'); - -my $wait_rc = $proc->wait(); -my $t1 = time(); -ok(! $proc->poll(), "process has exited"); -ok(defined $wait_rc, "wait_rc defined"); - -my $exit_rc = $proc->exit_status(); -ok(defined $exit_rc, "exit_rc defined"); - -ok(defined $proc->t0, "t0 defined"); -ok(defined $proc->t1, "t1 defined"); - -my $t0diff = abs($proc->t0 - $t0); -ok($t0diff <= $errortolerance, "t0-proc->t0 <= $errortolerance"); - -my $t1diff = abs($proc->t1 - $t1); -ok($t1diff <= $errortolerance, "t1-proc->t1 <= $errortolerance"); - -my $actela = $t1 - $t0; -my $pmela = $proc->t1 - $proc->t0; -my $eladiff = abs($actela - $pmela); -ok($eladiff < $errortolerance, "eladiff <= $errortolerance"); diff --git a/perl/third/Proc-Simple-1.32/t/wait.t b/perl/third/Proc-Simple-1.32/t/wait.t deleted file mode 100644 index ab21d4e..0000000 --- a/perl/third/Proc-Simple-1.32/t/wait.t +++ /dev/null @@ -1,21 +0,0 @@ -#!/usr/bin/perl -w -################################################## -# Check the exit status feature -################################################## - -use Test::More tests => 4; -use Proc::Simple; - -#Proc::Simple::debug(1); - -my $proc = Proc::Simple->new(); - -my $start_rc = $proc->start("sleep 1"); -ok($start_rc, 'start'); - -my $wait_rc = $proc->wait(); -ok(! $proc->poll(), "process has exited"); -ok(defined $wait_rc, "wait_rc defined"); - -my $exit_rc = $proc->exit_status(); -ok(defined $exit_rc, "exit_rc defined"); From 83edbe9c7f35585a86299aa94852a3c7159067d3 Mon Sep 17 00:00:00 2001 From: Sweet Tea Dorminy Date: Sun, 30 Mar 2025 14:25:18 -0400 Subject: [PATCH 8/8] remove third/ --- perl/Makefile | 2 +- perl/third/.cvsignore | 3 --- perl/third/Makefile | 33 --------------------------------- 3 files changed, 1 insertion(+), 37 deletions(-) delete mode 100644 perl/third/.cvsignore delete mode 100644 perl/third/Makefile diff --git a/perl/Makefile b/perl/Makefile index 98f52c9..52cfa76 100644 --- a/perl/Makefile +++ b/perl/Makefile @@ -8,7 +8,7 @@ PWD:= $(shell pwd) LIB:= ${PWD}/lib DESTDIR:= ${PWD}/build -SUBDIRS:= third +SUBDIRS:= CHECKIN_SUBDIRS := Permabit SYMLINKS:= Permabit Pdoc DOCTREES:= \ diff --git a/perl/third/.cvsignore b/perl/third/.cvsignore deleted file mode 100644 index d6cf293..0000000 --- a/perl/third/.cvsignore +++ /dev/null @@ -1,3 +0,0 @@ -bin -man -share diff --git a/perl/third/Makefile b/perl/third/Makefile deleted file mode 100644 index 2c9638c..0000000 --- a/perl/third/Makefile +++ /dev/null @@ -1,33 +0,0 @@ -# Makefile for all perl modules -# -# $Id: //eng/main/src/perl/third/Makefile#17 $ - -PWD:= $(shell pwd) -LIB:= ${PWD}/../lib - -SUBDIRS:= - -all: ${SUBDIRS} - -${SUBDIRS}: - ${MAKE} $@/Makefile - ${MAKE} -C $@ - ${MAKE} -C $@ install - -%/Makefile: %/Makefile.PL - cd ${@D}; \ - perl Makefile.PL PERL="/usr/bin/perl -I${LIB}" \ - LIB=${LIB} PREFIX=${PWD} < /dev/null; - -clean: regen-makefiles - for dir in ${SUBDIRS}; do \ - ${MAKE} -C $$dir clean; \ - done - -regen-makefiles: - for dir in ${SUBDIRS}; do \ - rm -f $$dir/Makefile; \ - ${MAKE} $$dir/Makefile; \ - done - -.PHONY:: ${SUBDIRS} all clean regen-makefiles