diff options
84 files changed, 3417 insertions, 0 deletions
diff --git a/pactest/COPYING b/pactest/COPYING new file mode 100644 index 00000000..96e45911 --- /dev/null +++ b/pactest/COPYING @@ -0,0 +1,340 @@ + 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 + + Appendix: 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. + + <one line to give the program's name and a brief idea of what it does.> + Copyright (C) 19yy <name of author> + + 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., 675 Mass Ave, Cambridge, MA 02139, 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) 19yy 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. + + <signature of Ty Coon>, 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/pactest/ChangeLog b/pactest/ChangeLog new file mode 100644 index 00000000..fec0eb23 --- /dev/null +++ b/pactest/ChangeLog @@ -0,0 +1,29 @@ + +Release 0.3 (pending) +------------- +- added detection for fakeroot enabled pacman binaries and leftover lock +and core files. +- fixed number format for statistics line +- display elapsed times for each test cases +- added COPYING file +- added patch to disable fakeroot support for pacman 2.9.x +- added "--gdb" command line options to ease debugging (as suggested by VMiklos) +- added "--valgrind" option to run tests through valgrind memory checker +- added more test cases +- added gensync archives + +Release 0.2 (06/02/13) +----------- +- added support for directories, symlinks and altered files +- removed hardcoded references to package names in testcase scripts +- splited pactest.py in several modules +- lots of code optimizations +- created a home page to host the project +- added README, TODO and ChangeLog files + +Release 0.1 (06/01/30) +----------- +Initial release. + +Annoucement on the ArchLinux pacman-dev mailing list: +http://www.archlinux.org/pipermail/pacman-dev/2006-January/000186.html diff --git a/pactest/README b/pactest/README new file mode 100644 index 00000000..7ef24b1d --- /dev/null +++ b/pactest/README @@ -0,0 +1,304 @@ +README +====== + +pactest is a test suite for the ArchLinux package manager: pacman. + +It has a rather high level view of operations performed by pacman: it +automatically creates a test environment based on a test case file +description, the run pacman, and finally check the results of test according +to a set of rules defined in the test case. + +It is written in Python and makes available most of what can be found in +pacman's code to create ArchLinux packages or read and write databases entries. + +Each test case is defined in a separate file that is sourced in order to set +the environment. + +pactest creates the environment in the subdirectory "root" created in the +current directory. +The following directory structure is used: + - var/lib/pacman: databases path (local and sync ones) + - etc/pacman.conf for pacman configuration file + - var/cache/pkg: sync packages cache + - var/log/pactest.log: log file + - var/pub: location for pseudo sync repositories + - tmp: hold all local package archives (to be used with pacman -A or -U) + +Note: the logfile is used to capture all pacman outputs. + +Test case example: + self.description = "Install a package" + + p = pmpkg("dummy", "1.0-3") + p.files = ["bin/dummy", + "usr/man/man1/dummy.1"] + self.addpkg(p) + + self.args = "-A dummy-1.0-1.pkg.tar.gz" + + self.addrule("PACMAN_RETCODE=0") + self.addrule("PKG_EXIST=dummy") + for f in p.files: + self.addrule("FILE_EXIST=%s" % f) + +Basically, the above test case will try to install a package (dummy-1.0-3), +including two files, from a local archive, by calling "pacman -A" +Upon completion, it checks that: + - pacman returned no error code, + - a "dummy" entry exists in the "local" database + - all files from the package exist in the filesystem. + + +Installation +============ + +Simply extract the pactest tarball, jump into the newly created directory and +run pactest.py. See the usage section below. + +Remark: pacman 3.x restrictions regarding fakeroot must be disabled. +It can be done by configuring pacman with the --disable-fakeroot flag: + ./configure --disable-fakeroot + +For pacman 2.9.x releases, apply the patch found in the patches directory, +then export CFLAGS as following before rebuilding pacman: + export CFLAGS=-DNOFAKEROOT + + +Usage +===== + +pactest will run the suite of tests defined by the "--test" parameter. + +Example: + ./pactest.py --test=test/* + +This example will run tests from the "test" directory. +Note: several "--test" options can be passed to pactest. + +Use the ""help" option to get the full list of parameters: + ./pactest.py --help + + +Parameters +========== + +The test environment is described by the following basic parameters: + + description + ----------- + +A short string describing the aim of the test case. It is displayed on the +standard output during test execution. + + args + ---- + +A string of arguments that are passed to the pacman binary when the test is +run. + +Example: + self.args = "-S dummy" + + option + ------ + +A dictionnary that holds the data used in the pacman configuration file. +It has 3 keys, each one of them pointing at a list of strings: + - noupgrade + - noextract + - ignorepkg + +Examples: + self.option["noupgrade"] = ["etc/X11/xorg.conf", + "etc/pacman.conf"] + self.option["noextract"] = ["etc/lilo.conf"] + + filesystem + ---------- + +A list of strings describing a set of files supposed to exist in the filesystem +when the test case is run. +Upon test startup, pactest will automatically populate the test environment +filesystem with this list of files. + +Example: + self.filesystem = ["bin/dummy", + "etc/X11/xorg.conf.pacsave"] + +Note that all paths are relative ones, and thus file names should not start +with a "/". + + +Packages +======== + +The test case file description shall define a number of packages that can be +used to either populate a database, or to feed pacman with data needed during +its execution. + +This can be achieved by creating pmpkg objects, with the following constructor: + pmpkg(name, version) + +Both "name" and "version" are strings. Also, note that if not provided, the +version defaults to "1.0-1". + +Example: + pkg1 = pmpkg("dummy", "2.1-1") + pkg2 = pmpkg("foobar") + +All fields from a ArchLinux package can be set and modified directly with no +methods to access them. +Note: some fields are automatically set by pactest and should preferably not +be modified by hand (i.e. "md5sum", "size", or "csize"). + +Examples: + pkg.depends = ["pkg2", "pkg3>=2.0"] + pkg.files = ["bin/dummy", "etc/dummy.conf", "usr/man/man1/dummy.1"] + + +Databases +========= + +The test environment provides a way to create and fill databases (local or +sync ones). + +The following methods shall be used: + + * addpkg2db(database, package) + +Notes: "database" is a string, and "package" shall be a previously created +pmpkg object. + +Examples: + self.addpkg2db("local", lpkg) + self.addpkg2db("sync1", spkg11) + self.addpkg2db("sync1", spkg12) + self.addpkg2db("sync2", spkg21) + +Note: there is no need to explicitly create a database. The "local" one +already exists (even if empty), and sync databases are created on the fly when +a new database new is given. + + * addpkg(package) + +package is an existing pmpkg object. +It creates a package archive based on the given object. The resulting archive +is located in the temporary directory of the test environment, ready to be +supplied to pacman for test purposes. + + +Files +===== + +All files created by pactest are filled with a content defaulting to the file +name, with an additional line feed. +For instance, the content of a file "bin/dummy" created in the test environment +file system is: "bin/dummy\n". + +It is possible to create directories by appending a slash "/" to the name and +to create symlinks by appending an arrow followed by a filename " -> target". + +Note: only relative symlinks are supported. + +Example: + pkg = pmpkg("dummy") + pkg.files = ["bin/dummy", + "usr/local/", + "lib/libfoo.so.O", + "lib/libfoo.so -> ./libfoo.so.0"] + +In this example, "usr/local/" is a directory, and "libfoo.so" will be a +symlink pointing at "libfoo.so.0". It is usually a good idea to also define +the target of the symlink! + +It can be interesting for some tests to create altered files. This can be +done by appending one or more asterisks "*" to the file name. + +Example: + lpkg = pmpkg("dummy") + lpkg.files = ["bin/dummy"] + self.addpkg2db("local", lpkg) + + newpkg = pmpkg("dummy", "1.0-2") + newpkg.files = ["bin/dummy*"] + self.addpkg(newpkg) + + self.args = "-U dummy-1.0-2.pkg.tar.gz" + +In this case, package "lpkg" will install a file "bin/dummy" with "bin/dummy\n" +as its content. Upon package upgrade, newpkg will provide a file named +"bin/dummy" with "bin/dummy*\n" as its content. +This is useful to simulate that a file has been modified between two different +releases of a same package. + +The same also applies to files from the "filesystem" parameter of the test +environment, and to the "backup" attribute of a package object. + + +Rules +===== + +Finally, to check test success or failure, one shall define a set of rules. + + addrule(rule) + ------------- + +A rule is a string composed by a key and an item, joined with a "=" symbol. + +Examples: + self.addrule("PACMAN_RETCODE=0") + self.addrule("PKG_EXIST=dummy") + self.addrule("FILE_MODIFIED=bin/dummy") + self.addrule("PKG_DEPENDS=xorg|fontconfig") + +Note: an item can be divided into two arguments, as shown in the latter +example. + +All rules can be prepended with a bang "!" in order to tell pactest to expect +the exact opposite result. + +Example: + self.addrule("!FILE_MODIFIED=bin/dummy") + +Finally, the following rules are supported: + + . PACMAN rules + +Possible rules are: + + PACMAN_RETCODE=value + PACMAN_OUTPUT=value + +For the RETCODE one, pactest will compare pacman return code with the value +provided as an item. +For the OUTPUT one, pactest will grep pacman outputs for the given value. + +Note: PACMAN_OUTPUT should not be used. Pacman outputs are likely to change +from one release to another, so that it's reliability is quite low. + + . PKG rules + +For each rule, pactest will read the entry "name" from the local database and +challenge the requested data with it. + +Possible rules are: + + PKG_EXIST=name + PKG_MODIFIED=name + PKG_VERSION=name|version + PKG_DEPENDS=name|depname + PKG_REQUIREDBY=name|reqbyname + +Example: + PKG_DEPENDS=ncurses|glibc + +pactest will test the local database entry "ncurses" has "glibc" in its +DEPENDS field. + + . FILE rules + + FILE_EXIST=path/to/file + FILE_MODIFIED=path/to/file + FILE_PACNEW=path/to/file + FILE_PACSAVE=path/to/file + FILE_PACORIG=path/to/file diff --git a/pactest/TODO b/pactest/TODO new file mode 100644 index 00000000..437bf02c --- /dev/null +++ b/pactest/TODO @@ -0,0 +1,8 @@ +TODO +==== + +Features: +- implement gensync support + +Tests: +- add test cases for pacman -D and pacman -T diff --git a/pactest/pactest.py b/pactest/pactest.py new file mode 100755 index 00000000..2f7358ac --- /dev/null +++ b/pactest/pactest.py @@ -0,0 +1,73 @@ +#! /usr/bin/python +# +# Copyright (c) 2006 by Aurelien Foret <orelien@chez.com> +# +# 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. + + +import getopt +import sys +import glob +import os + +import pmenv +import util + + +__author__ = "Aurelien FORET" +__version__ = "0.3" + + +def usage(retcode): + """ + """ + print "Usage: %s [options] [[--test=<path/to/testfile.py>] ...]\n\n" % __file__ + sys.exit(retcode) + +if __name__ == "__main__": + env = pmenv.pmenv() + testcases = [] + + try: + opts, args = getopt.getopt(sys.argv[1:], + "d:hp:t:v", + ["debug=", "gdb", "help", "pacman=", "test=", "valgrind", "verbose", "nolog"]) + except getopt.GetoptError: + usage(1) + + for (cmd, param) in opts: + if cmd == "-v" or cmd == "--verbose": + util.verbose += 1 + elif cmd == "-d" or cmd == "--debug": + env.pacman["debug"] = int(param) + elif cmd == "-t" or cmd == "--test": + testcases.extend(glob.glob(param)) + elif cmd == "-p" or cmd == "--pacman": + env.pacman["bin"] = os.path.abspath(param) + elif cmd == "-h" or cmd == "--help": + usage(0) + elif cmd == "--nolog": + env.pacman["nolog"] = 1 + elif cmd == "--gdb": + env.pacman["gdb"] = 1 + elif cmd == "--valgrind": + env.pacman["valgrind"] = 1 + + for i in testcases: + env.addtest(i) + + env.run() + env.results() diff --git a/pactest/pmdb.py b/pactest/pmdb.py new file mode 100755 index 00000000..ebac9372 --- /dev/null +++ b/pactest/pmdb.py @@ -0,0 +1,363 @@ +#! /usr/bin/python +# +# Copyright (c) 2006 by Aurelien Foret <orelien@chez.com> +# +# 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. + + +import os +import tempfile +import shutil + +import pmpkg +from util import * + + +def _mkfilelist(files): + """Generate a list of files from the list supplied as an argument. + + Each path is decomposed to generate the list of all directories leading + to the file. + + Example with 'usr/local/bin/dummy': + The resulting list will be + usr/ + usr/local/ + usr/local/bin/ + usr/local/bin/dummy + """ + i = [] + for f in files: + dir = getfilename(f) + i.append(dir) + while "/" in dir: + [dir, tmp] = dir.rsplit("/", 1) + if not dir + "/" in files: + i.append(dir + "/") + i.sort() + return i + +def _mkbackuplist(backup): + """ + """ + return ["%s\t%s" % (getfilename(i), mkmd5sum(i)) for i in backup] + +def _getsection(fd): + """ + """ + i = [] + while 1: + line = fd.readline().strip("\n") + if not line: + break + i.append(line) + return i + +def _mksection(title, data): + """ + """ + s = "" + if isinstance(data, list): + s = "\n".join(data) + else: + s = data + return "%%%s%%\n" \ + "%s\n" % (title, s) + + +class pmdb: + """Database object + """ + + def __init__(self, treename, dbdir): + self.treename = treename + self.dbdir = dbdir + self.pkgs = [] + + def __str__(self): + return "%s" % self.treename + + def getpkg(self, name): + """ + """ + for pkg in self.pkgs: + if name == pkg.name: + return pkg + + def db_read(self, name): + """ + """ + + path = os.path.join(self.dbdir, self.treename) + if not os.path.isdir(path): + return None + + dbentry = "" + for roots, dirs, files in os.walk(path): + for i in dirs: + [pkgname, pkgver, pkgrel] = i.rsplit("-", 2) + if pkgname == name: + dbentry = i + break + if not dbentry: + return None + path = os.path.join(path, dbentry) + + [pkgname, pkgver, pkgrel] = dbentry.rsplit("-", 2) + pkg = pmpkg.pmpkg(pkgname, pkgver + "-" + pkgrel) + + # desc + filename = os.path.join(path, "desc") + fd = file(filename, "r") + while 1: + line = fd.readline() + if not line: + break + line = line.strip("\n") + if line == "%DESC%": + pkg.desc = fd.readline().strip("\n") + elif line == "%GROUPS%": + pkg.groups = _getsection(fd) + elif line == "%URL%": + pkg.url = fd.readline().strip("\n") + elif line == "%LICENSE%": + pkg.license = _getsection(fd) + elif line == "%ARCH%": + pkg.arch = fd.readline().strip("\n") + elif line == "%BUILDDATE%": + pkg.builddate = fd.readline().strip("\n") + elif line == "%INSTALLDATE%": + pkg.installdate = fd.readline().strip("\n") + elif line == "%PACKAGER%": + pkg.packager = fd.readline().strip("\n") + elif line == "%REASON%": + pkg.reason = int(fd.readline().strip("\n")) + elif line == "%SIZE%" or line == "%CSIZE%": + pkg.size = int(fd.readline().strip("\n")) + elif line == "%MD5SUM%": + pkg.md5sum = fd.readline().strip("\n") + elif line == "%REPLACES%": + pkg.replaces = _getsection(fd) + elif line == "%FORCE%": + fd.readline() + pkg.force = 1 + fd.close() + pkg.checksum["desc"] = getmd5sum(filename) + pkg.mtime["desc"] = getmtime(filename) + + # files + filename = os.path.join(path, "files") + fd = file(filename, "r") + while 1: + line = fd.readline() + if not line: + break + line = line.strip("\n") + if line == "%FILES%": + while line: + line = fd.readline().strip("\n") + if line and line[-1] != "/": + pkg.files.append(line) + if line == "%BACKUP%": + pkg.backup = _getsection(fd) + fd.close() + pkg.checksum["files"] = getmd5sum(filename) + pkg.mtime["files"] = getmtime(filename) + + # depends + filename = os.path.join(path, "depends") + fd = file(filename, "r") + while 1: + line = fd.readline() + if not line: + break + line = line.strip("\n") + if line == "%DEPENDS%": + pkg.depends = _getsection(fd) + elif line == "%REQUIREDBY%": + pkg.requiredby = _getsection(fd) + elif line == "%CONFLICTS%": + pkg.conflicts = _getsection(fd) + elif line == "%PROVIDES%": + pkg.provides = _getsection(fd) + elif line == "%REPLACES%": + pkg.replaces = _getsection(fd) + elif line == "%FORCE%": + fd.readline() + pkg.force = 1 + fd.close() + pkg.checksum["depends"] = getmd5sum(filename) + pkg.mtime["depends"] = getmtime(filename) + + # install + filename = os.path.join(path, "install") + if os.path.isfile(filename): + pkg.checksum["install"] = getmd5sum(filename) + pkg.mtime["install"] = getmtime(filename) + + return pkg + + # + # db_write is used to add both 'local' and 'sync' db entries + # + def db_write(self, pkg): + """ + """ + + path = os.path.join(self.dbdir, self.treename, pkg.fullname()) + if not os.path.isdir(path): + os.makedirs(path); + + # desc + # for local db entries: name, version, desc, groups, url, license, + # arch, builddate, installdate, packager, + # size, reason + # for sync entries: name, version, desc, groups, csize, md5sum, + # replaces, force + data = [_mksection("NAME", pkg.name)] + data.append(_mksection("VERSION", pkg.version)) + if pkg.desc: + data.append(_mksection("DESC", pkg.desc)) + if pkg.groups: + data.append(_mksection("GROUPS", pkg.groups)) + if self.treename == "local": + if pkg.url: + data.append(_mksection("URL", pkg.url)) + if pkg.license: + data.append(_mksection("LICENSE", pkg.license)) + if pkg.arch: + data.append(_mksection("ARCH", pkg.arch)) + if pkg.builddate: + data.append(_mksection("BUILDDATE", pkg.builddate)) + if pkg.installdate: + data.append(_mksection("INSTALLDATE", pkg.installdate)) + if pkg.packager: + data.append(_mksection("PACKAGER", pkg.packager)) + if pkg.size: + data.append(_mksection("SIZE", pkg.size)) + if pkg.reason: + data.append(_mksection("REASON", pkg.reason)) + else: + if pkg.csize: + data.append(_mksection("CSIZE", pkg.csize)) + if pkg.md5sum: + data.append(_mksection("MD5SUM", pkg.md5sum)) + if data: + data.append("") + filename = os.path.join(path, "desc") + mkfile(filename, "\n".join(data)) + pkg.checksum["desc"] = getmd5sum(filename) + pkg.mtime["desc"] = getmtime(filename) + + # files + # for local entries, fields are: files, backup + # for sync ones: none + if self.treename == "local": + data = [] + if pkg.files: + data.append(_mksection("FILES", _mkfilelist(pkg.files))) + if pkg.backup: + data.append(_mksection("BACKUP", _mkbackuplist(pkg.backup))) + if data: + data.append("") + filename = os.path.join(path, "files") + mkfile(filename, "\n".join(data)) + pkg.checksum["files"] = getmd5sum(filename) + pkg.mtime["files"] = getmtime(filename) + + # depends + # for local db entries: depends, requiredby, conflicts, provides + # for sync ones: depends, conflicts, provides + data = [] + if pkg.depends: + data.append(_mksection("DEPENDS", pkg.depends)) + if self.treename == "local": + if pkg.requiredby: + data.append(_mksection("REQUIREDBY", pkg.requiredby)) + if pkg.conflicts: + data.append(_mksection("CONFLICTS", pkg.conflicts)) + if pkg.provides: + data.append(_mksection("PROVIDES", pkg.provides)) + if not self.treename == "local": + if pkg.replaces: + data.append(_mksection("REPLACES", pkg.replaces)) + if pkg.force: + data.append(_mksection("FORCE", "")) + if data: + data.append("") + filename = os.path.join(path, "depends") + mkfile(filename, "\n".join(data)) + pkg.checksum["depends"] = getmd5sum(filename) + pkg.mtime["depends"] = getmtime(filename) + + # install + if self.treename == "local": + empty = 1 + for value in pkg.install.values(): + if value: + empty = 0 + if not empty: + filename = os.path.join(path, "install") + mkinstallfile(filename, pkg.install) + pkg.checksum["install"] = getmd5sum(filename) + pkg.mtime["install"] = getmtime(filename) + + def gensync(self, path): + """ + """ + + curdir = os.getcwd() + tmpdir = tempfile.mkdtemp() + os.chdir(tmpdir) + + for pkg in self.pkgs: + mkdescfile(pkg.fullname(), pkg) + + # Generate database archive + os.makedirs(path, 0755) + archive = os.path.join(path, "%s%s" % (self.treename, PM_EXT_DB)) + os.system("tar zcf %s *" % archive) + + os.chdir(curdir) + shutil.rmtree(tmpdir) + + def ispkgmodified(self, pkg): + """ + """ + + modified = 0 + + oldpkg = self.getpkg(pkg.name) + if not oldpkg: + return 0 + + dbg("oldpkg.checksum : %s" % oldpkg.checksum) + dbg("oldpkg.mtime : %s" % oldpkg.mtime) + + for key in pkg.mtime.keys(): + if key == "install" \ + and oldpkg.mtime[key] == (0, 0, 0) \ + and pkg.mtime[key] == (0, 0, 0): + continue + if not oldpkg.mtime[key][1:3] == pkg.mtime[key][1:3]: + modified += 1 + + return modified + + +if __name__ == "__main__": + db = pmdb("local") + print db diff --git a/pactest/pmenv.py b/pactest/pmenv.py new file mode 100755 index 00000000..5093612c --- /dev/null +++ b/pactest/pmenv.py @@ -0,0 +1,118 @@ +#! /usr/bin/python +# +# Copyright (c) 2006 by Aurelien Foret <orelien@chez.com> +# +# 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. + + +import os +import time + +import pmtest + + +class pmenv: + """Environment object + """ + + def __init__(self, root = "root"): + self.root = os.path.abspath(root) + self.pacman = { + "bin": "pacman", + "debug": 0, + "gdb": 0, + "valgrind": 0, + "nolog": 0 + } + self.testcases = [] + + def __str__(self): + return "root = %s\n" \ + "pacman = %s" \ + % (self.root, self.pacman) + + def addtest(self, testcase): + """ + """ + if not os.path.isfile(testcase): + err("file %s not found" % testcase) + return + test = pmtest.pmtest(testcase, self.root) + self.testcases.append(test) + + def run(self): + """ + """ + + for t in self.testcases: + print "=========="*8 + print "Running '%s'" % t.name.strip(".py") + + t.load() + print t.description + print "----------"*8 + + t.generate() + # Hack for mtimes consistency + modified = 0 + for i in t.rules: + if i.rule.find("MODIFIED") != -1: + modified = 1 + if modified: + time.sleep(3) + + t.run(self.pacman) + + t.check() + print "==> Test result" + if t.result["ko"] == 0: + print "\tPASSED" + else: + print "\tFAILED" + print + + def results(self): + """ + """ + passed = 0 + print "=========="*8 + print "Results" + print "----------"*8 + for test in self.testcases: + ok = test.result["ok"] + ko = test.result["ko"] + rules = len(test.rules) + if ko == 0: + print "[PASSED]", + passed += 1 + else: + print "[FAILED]", + print test.name.strip(".py").ljust(38), + print "Rules:", + print "OK = %2u KO = %2u SKIP = %2u" % (ok, ko, rules-(ok+ko)) + print "----------"*8 + total = len(self.testcases) + failed = total - passed + print "TOTAL = %3u" % total + if total: + print "PASSED = %3u (%6.2f%%)" % (passed, float(passed)*100/total) + print "FAILED = %3u (%6.2f%%)" % (failed, float(failed)*100/total) + print + + +if __name__ == "__main__": + env = pmenv("/tmp") + print env diff --git a/pactest/pmfile.py b/pactest/pmfile.py new file mode 100755 index 00000000..d78b09fa --- /dev/null +++ b/pactest/pmfile.py @@ -0,0 +1,65 @@ +#! /usr/bin/python +# +# Copyright (c) 2006 by Aurelien Foret <orelien@chez.com> +# +# 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. + + +import os + +from util import * + + +class pmfile: + """File object + """ + + def __init__(self, root, name): + self.name = name + self.root = root + + filename = os.path.join(self.root, self.name) + self.checksum = getmd5sum(filename) + self.mtime = getmtime(filename) + + def __str__(self): + return "%s (%s / %lu)" % (self.name, self.checksum, self.mtime) + + def ismodified(self): + """ + """ + + retval = 0 + + filename = os.path.join(self.root, self.name) + checksum = getmd5sum(filename) + mtime = getmtime(filename) + + if debug: + print "ismodified(%s)" % self.name + print "old: %s / %s" % (self.checksum, self.mtime) + print "new: %s / %s" % (checksum, mtime) + + if not self.checksum == checksum \ + or not (self.mtime[1], self.mtime[2]) == (mtime[1], mtime[2]): + retval = 1 + + return retval + + +if __name__ == "__main__": + f = pmfile("/tmp", "foobar") + print f diff --git a/pactest/pmpkg.py b/pactest/pmpkg.py new file mode 100755 index 00000000..b2a28f96 --- /dev/null +++ b/pactest/pmpkg.py @@ -0,0 +1,180 @@ +#! /usr/bin/python +# +# Copyright (c) 2006 by Aurelien Foret <orelien@chez.com> +# +# 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. + + +import os +import tempfile +import stat +import shutil + +from util import * + + +class pmpkg: + """Package object. + + Object holding data from an ArchLinux package. + """ + + def __init__(self, name, version = "1.0-1"): + # desc + self.name = name + self.version = version + self.desc = "" + self.groups = [] + self.url = "" + self.license = [] + self.arch = "" + self.builddate = "" + self.installdate = "" + self.packager = "" + self.size = 0 + self.csize = 0 + self.reason = 0 + self.md5sum = "" # sync only + self.replaces = [] # sync only (will be moved to depends) + self.force = 0 # sync only (will be moved to depends) + # depends + self.depends = [] + self.requiredby = [] # local only + self.conflicts = [] + self.provides = [] + # files + self.files = [] + self.backup = [] + # install + self.install = { + "pre_install": "", + "post_install": "", + "pre_remove": "", + "post_remove": "", + "pre_upgrade": "", + "post_upgrade": "" + } + self.checksum = { + "desc": "", + "depends": "", + "files": "", + "install": "" + } + self.mtime = { + "desc": (0, 0, 0), + "depends": (0, 0, 0), + "files": (0, 0, 0), + "install": (0, 0, 0) + } + + def __str__(self): + s = ["%s" % self.fullname()] + s.append("description: %s" % self.desc) + s.append("url: %s" % self.url) + s.append("depends: %s" % " ".join(self.depends)) + s.append("files: %s" % " ".join(self.files)) + s.append("reason: %d" % self.reason) + return "\n".join(s) + + def fullname(self): + """Long name of a package. + + Returns a string formatted as follows: "pkgname-pkgver". + """ + return "%s-%s" % (self.name, self.version) + + def filename(self): + """File name of a package, including its extension. + + Returns a string formatted as follows: "pkgname-pkgver.PKG_EXT_PKG". + """ + return "%s%s" % (self.fullname(), PM_EXT_PKG) + + def install_files(self, root): + """Install files in the filesystem located under "root". + + Files are created with content generated automatically. + """ + [mkfile(os.path.join(root, f), f) for f in self.files] + + def makepkg(self, path): + """Creates an ArchLinux package archive. + + A package archive is generated in the location 'path', based on the data + from the object. + """ + archive = os.path.join(path, self.filename()) + + curdir = os.getcwd() + tmpdir = tempfile.mkdtemp() + os.chdir(tmpdir) + + # Generate package file system + for f in self.files: + mkfile(f, f) + self.size += os.stat(getfilename(f))[stat.ST_SIZE] + + # .PKGINFO + data = ["pkgname = %s" % self.name] + data.append("pkgver = %s" % self.version) + data.append("pkgdesc = %s" % self.desc) + data.append("url = %s" % self.url) + data.append("builddate = %s" % self.builddate) + data.append("packager = %s" % self.packager) + data.append("size = %s" % self.size) + if self.arch: + data.append("arch = %s" % self.arch) + for i in self.license: + data.append("license = %s" % i) + for i in self.replaces: + data.append("replaces = %s" % i) + for i in self.groups: + data.append("group = %s" % i) + for i in self.depends: + data.append("depend = %s" % i) + for i in self.conflicts: + data.append("conflict = %s" % i) + for i in self.provides: + data.append("provides = %s" % i) + for i in self.backup: + data.append("backup = %s" % i) + mkfile(".PKGINFO", "\n".join(data)) + targets = ".PKGINFO" + + # .INSTALL + empty = 1 + for value in self.install.values(): + if value: + empty = 0 + if not empty: + mkinstallfile(".INSTALL", self.install) + targets += " .INSTALL" + + # .FILELIST + if self.files: + os.system("tar cvf /dev/null * | sort >.FILELIST") + targets += " .FILELIST *" + + # Generate package archive + os.system("tar zcf %s %s" % (archive, targets)) + + os.chdir(curdir) + shutil.rmtree(tmpdir) + + +if __name__ == "__main__": + pkg = pmpkg("dummy") + print pkg diff --git a/pactest/pmrule.py b/pactest/pmrule.py new file mode 100755 index 00000000..ad2e8930 --- /dev/null +++ b/pactest/pmrule.py @@ -0,0 +1,133 @@ +#! /usr/bin/python +# +# Copyright (c) 2006 by Aurelien Foret <orelien@chez.com> +# +# 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. + + +from util import * + + +class pmrule: + """Rule object + """ + + def __init__(self, rule): + self.rule = rule + self.false = 0 + self.result = 0 + + def __str__(self): + return "rule = %s" % self.rule + + def check(self, root, retcode, localdb, files): + """ + """ + + success = 1 + + [test, args] = self.rule.split("=") + if test[0] == "!": + self.false = 1 + test = test.lstrip("!") + [kind, case] = test.split("_") + if "|" in args: + [key, value] = args.split("|", 1) + else: + [key, value] = [args, None] + + if kind == "PACMAN": + if case == "RETCODE": + if retcode != int(key): + success = 0 + elif case == "OUTPUT": + if not grep(os.path.join(root, LOGFILE), key): + success = 0 + else: + success = -1 + elif kind == "PKG": + newpkg = localdb.db_read(key) + if not newpkg: + success = 0 + else: + dbg("newpkg.checksum : %s" % newpkg.checksum) + dbg("newpkg.mtime : %s" % newpkg.mtime) + if case == "EXIST": + success = 1 + elif case == "MODIFIED": + if not localdb.ispkgmodified(newpkg): + success = 0 + elif case == "VERSION": + if value != newpkg.version: + success = 0 + elif case == "GROUPS": + if not value in newpkg.groups: + success = 0 + elif case == "DEPENDS": + if not value in newpkg.depends: + success = 0 + elif case == "REQUIREDBY": + if not value in newpkg.requiredby: + success = 0 + elif case == "REASON": + if not newpkg.reason == int(value): + success = 0 + elif case == "FILES": + if not value in newpkg.files: + success = 0 + elif case == "BACKUP": + found = 0 + for f in newpkg.backup: + name, md5sum = f.split("\t") + if value == name: + found = 1 + if not found: + success = 0 + else: + success = -1 + elif kind == "FILE": + filename = os.path.join(root, key) + if case == "EXIST": + if not os.path.isfile(filename): + success = 0 + else: + if case == "MODIFIED": + for f in files: + if f.name == key: + if not f.ismodified(): + success = 0 + elif case == "PACNEW": + if not os.path.isfile("%s%s" % (filename, PM_PACNEW)): + success = 0 + elif case == "PACORIG": + if not os.path.isfile("%s%s" % (filename, PM_PACORIG)): + success = 0 + elif case == "PACSAVE": + if not os.path.isfile("%s%s" % (filename, PM_PACSAVE)): + success = 0 + else: + success = -1 + else: + success = -1 + + if self.false and success != -1: + success = not success + self.result = success + return success + + +if __name__ != "__main__": + rule = pmrule("PKG_EXIST=dummy") diff --git a/pactest/pmtest.py b/pactest/pmtest.py new file mode 100755 index 00000000..830202a5 --- /dev/null +++ b/pactest/pmtest.py @@ -0,0 +1,253 @@ +#! /usr/bin/python +# +# Copyright (c) 2006 by Aurelien Foret <orelien@chez.com> +# +# 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. + + +import os +import shutil +import time + +import pmrule +import pmdb +import pmfile +from pmpkg import pmpkg +from util import * + + +class pmtest: + """Test object + """ + + def __init__(self, name, root): + self.name = name + self.root = root + + def __str__(self): + return "name = %s\n" \ + "root = %s" % (self.name, self.root) + + def addpkg2db(self, treename, pkg): + """ + """ + if not treename in self.db: + self.db[treename] = pmdb.pmdb(treename, os.path.join(self.root, PM_DBPATH)) + self.db[treename].pkgs.append(pkg) + + def addpkg(self, pkg): + """ + """ + self.localpkgs.append(pkg) + + def addrule(self, rulename): + """ + """ + rule = pmrule.pmrule(rulename) + self.rules.append(rule) + + def load(self): + """ + """ + + # Reset test parameters + self.result = { + "ok": 0, + "ko": 0 + } + self.args = "" + self.retcode = 0 + self.db = { + "local": pmdb.pmdb("local", os.path.join(self.root, PM_DBPATH)) + } + self.localpkgs = [] + self.filesystem = [] + + self.description = "" + self.option = { + "noupgrade": [], + "ignorepkg": [], + "noextract": [] + } + + # Test rules + self.rules = [] + self.files = [] + + if os.path.isfile(self.name): + execfile(self.name) + else: + err("file %s does not exist!" % self.name) + + def generate(self): + """ + """ + + print "==> Generating test environment" + + # Cleanup leftover files from a previous test session + if os.path.isdir(self.root): + shutil.rmtree(self.root) + vprint("\t%s" % self.root) + + # Create directory structure + vprint(" Creating directory structure:") + dbdir = os.path.join(self.root, PM_DBPATH) + cachedir = os.path.join(self.root, PM_CACHEDIR) + syncdir = os.path.join(self.root, SYNCREPO) + tmpdir = os.path.join(self.root, TMPDIR) + logdir = os.path.join(self.root, os.path.dirname(LOGFILE)) + etcdir = os.path.join(self.root, os.path.dirname(PACCONF)) + for dir in [dbdir, cachedir, syncdir, tmpdir, logdir, etcdir]: + if not os.path.isdir(dir): + vprint("\t%s" % dir[len(self.root)+1:]) + os.makedirs(dir, 0755) + + # Configuration file + vprint(" Creating configuration file") + vprint("\t%s" % PACCONF) + mkcfgfile(PACCONF, self.root, self.option, self.db) + + # Creating packages + vprint(" Creating package archives") + for pkg in self.localpkgs: + vprint("\t%s" % os.path.join(TMPDIR, pkg.filename())) + pkg.makepkg(tmpdir) + for key, value in self.db.iteritems(): + if key == "local": + continue + for pkg in value.pkgs: + archive = pkg.filename() + vprint("\t%s" % os.path.join(PM_CACHEDIR, archive)) + pkg.makepkg(cachedir) + pkg.md5sum = getmd5sum(os.path.join(cachedir, archive)) + pkg.csize = os.stat(os.path.join(cachedir, archive))[stat.ST_SIZE] + + # Populating databases + vprint(" Populating databases") + for key, value in self.db.iteritems(): + for pkg in value.pkgs: + vprint("\t%s/%s" % (key, pkg.fullname())) + if key == "local": + pkg.installdate = time.ctime() + value.db_write(pkg) + + # Creating sync database archives + vprint(" Creating sync database archives") + for key, value in self.db.iteritems(): + if key == "local": + continue + archive = value.treename + PM_EXT_DB + vprint("\t" + os.path.join(SYNCREPO, archive)) + value.gensync(os.path.join(syncdir, value.treename)) + + # Filesystem + vprint(" Populating file system") + for pkg in self.db["local"].pkgs: + vprint("\tinstalling %s" % pkg.fullname()) + pkg.install_files(self.root) + for f in self.filesystem: + vprint("\t%s" % f) + mkfile(os.path.join(self.root, f), f) + + # Done. + vprint(" Taking a snapshot of the file system") + for roots, dirs, files in os.walk(self.root): + for i in files: + filename = os.path.join(roots, i) + f = pmfile.pmfile(self.root, filename.replace(self.root + "/", "")) + self.files.append(f) + vprint("\t%s" % f.name) + + def run(self, pacman): + """ + """ + + if os.path.isfile(PM_LOCK): + print "\tERROR: another pacman session is on-going -- skipping" + return + + print "==> Running test" + vprint("\tpacman %s" % self.args) + + cmd = ["fakeroot"] + if pacman["gdb"]: + cmd.append("libtool gdb --args") + if pacman["valgrind"]: + cmd.append("valgrind --tool=memcheck --leak-check=full --show-reachable=yes") + cmd.append("%s --noconfirm --config=%s --root=%s" \ + % (pacman["bin"], os.path.join(self.root, PACCONF), self.root)) + if pacman["debug"]: + cmd.append("--debug=%s" % pacman["debug"]) + cmd.append("%s" % self.args) + if not pacman["gdb"] and not pacman["valgrind"] and not pacman["nolog"]: + cmd.append(">%s 2>&1" % os.path.join(self.root, LOGFILE)) + dbg(" ".join(cmd)) + + # Change to the tmp dir before running pacman, so that local package + # archives are made available more easily. + curdir = os.getcwd() + tmpdir = os.path.join(self.root, TMPDIR) + os.chdir(tmpdir) + + t0 = time.time() + self.retcode = os.system(" ".join(cmd)) + t1 = time.time() + vprint("\ttime elapsed: %ds" % (t1-t0)) + + if self.retcode == None: + self.retcode = 0 + else: + self.retcode /= 256 + dbg("retcode = %s" % self.retcode) + os.chdir(curdir) + + # Check if pacman failed because of bad permissions + if self.retcode \ + and grep(os.path.join(self.root, LOGFILE), + "you cannot perform this operation unless you are root"): + print "\tERROR: pacman support for fakeroot is not disabled" + # Check if the lock is still there + if os.path.isfile(PM_LOCK): + print "\tERROR: %s not removed" % PM_LOCK + os.unlink(PM_LOCK) + # Look for a core file + if os.path.isfile(os.path.join(self.root, TMPDIR, "core")): + print "\tERROR: pacman dumped a core file" + + def check(self): + """ + """ + + print "==> Checking rules" + + for i in self.rules: + success = i.check(self.root, self.retcode, self.db["local"], self.files) + if success == 1: + msg = "OK" + self.result["ok"] += 1 + elif success == 0: + msg = "KO" + self.result["ko"] += 1 + else: + msg = "SKIP" + print "\t[%s] %s" % (msg, i.rule) + i.result = success + + +if __name__ == "__main__": + test = pmtest("test1", "./root") + print test diff --git a/pactest/tests/TESTS b/pactest/tests/TESTS new file mode 100644 index 00000000..67343750 --- /dev/null +++ b/pactest/tests/TESTS @@ -0,0 +1,61 @@ +add001: Install a package +add002: Install a package (already installed) +add003: Install a set of packages +add004: Install a set of the same package at different versions +add010: Install a package with a filesystem conflict +add011: Install a package with a filesystem conflict (--force) +add012: Install two packages with a conflicting file +add013: Install two packages with a conflicting file (--force) +add020: Install a package with an existing file +add021: Install a package with an existing file (new modified) +add030: Freshen a package +add031: Freshen a package (installed is newer) +add032: Freshen a package (installed is newer) +add040: Install a package with a missing dependency +add041: Install a package with a missing dependency (nodeps) +add042: Install a package with cascaded dependencies +add050: Install a package with a file in NoUpgrade +add060: Install a package with a file in NoExtract +query001: Query a package +remove010: Remove a package, with a file marked for backup +remove011: Remove a package, with a modified file marked for backup +remove020: Remove a package, with a file marked for backup (--nosave) +remove021: Remove a package, with a modified file marked for backup (--nosave) +smoke001: Install a thousand packages in a single transaction +sync001: Install a package from a sync db +sync002: Upgrade a package from a sync db +sync003: Install a package from a sync db, with a filesystem conflict +sync010: Install a package from a sync db, with its dependencies +sync040: Install two targets with a conflict +sync041: Install two conflicting targets +sync042: Install a sync package conflicting with a local one +sync043: Install a sync package conflicting with a local one +sync050: Install a virtual target (provided by a sync package) +sync100: Sysupgrade with a newer sync package +sync101: Sysupgrade with same version for local and sync packages +sync102: Sysupgrade with a newer local package +sync103: Sysupgrade with a local package not existing in sync db +sync110: Sysupgrade of a package pulling new dependencies +sync120: Sysupgrade of packages in 'IgnorePkg' +sync130: Sysupgrade with a sync package replacing a local one +sync131: Sysupgrade with a sync package replacing a set of local ones +sync132: Sysupgrade with a replacement for a local package out of date +sync133: Sysupgrade with a sync package replacing a local one in 'IgnorePkg' +sync134: Sysupgrade with a set of sync packages replacing a set local one +sync135: Sysupgrade with a set of sync packages replacing a set of local ones +sync897: System upgrade +sync898: System upgrade +sync899: System upgrade +sync990: Sync a package pulling a dependency conflicting with a target +sync992: Sync a package pulling a conflicting dependency +sync999: System upgrade +upgrade001: Upgrade a package (newer version) +upgrade002: Upgrade a package (same version) +upgrade003: Upgrade a package (lesser version) +upgrade004: Upgrade a package (not installed) +upgrade010: Upgrade a package, with a file in NoUpgrade +upgrade020: Upgrade a package, with a file in 'backup' (new modified) +upgrade021: Upgrade a package, with a file in 'backup' (local modified, new unchanged) +upgrade022: Upgrade a package, with a file in 'backup' (local and new modified) +upgrade030: Upgrade packages with various reasons +upgrade040: file relocation 1 diff --git a/pactest/tests/add001.py b/pactest/tests/add001.py new file mode 100644 index 00000000..159a54a3 --- /dev/null +++ b/pactest/tests/add001.py @@ -0,0 +1,13 @@ +self.description = "Install a package" + +p = pmpkg("dummy") +p.files = ["bin/dummy", + "usr/man/man1/dummy.1"] +self.addpkg(p) + +self.args = "-A %s" % p.filename() + +self.addrule("PACMAN_RETCODE=0") +self.addrule("PKG_EXIST=dummy") +for f in p.files: + self.addrule("FILE_EXIST=%s" % f) diff --git a/pactest/tests/add002.py b/pactest/tests/add002.py new file mode 100644 index 00000000..2ec90644 --- /dev/null +++ b/pactest/tests/add002.py @@ -0,0 +1,18 @@ +self.description = "Install a package (already installed)" + +lp = pmpkg("dummy") +lp.files = ["bin/dummy", + "usr/man/man1/dummy.1"] +self.addpkg2db("local", lp) + +p = pmpkg("dummy") +p.files = ["bin/dummy", + "usr/man/man1/dummy.1"] +self.addpkg(p) + +self.args = "-A %s" % p.filename() + +self.addrule("PACMAN_RETCODE=1") +self.addrule("!PKG_MODIFIED=dummy") +for f in lp.files: + self.addrule("!FILE_MODIFIED=%s" % f) diff --git a/pactest/tests/add003.py b/pactest/tests/add003.py new file mode 100644 index 00000000..bde87649 --- /dev/null +++ b/pactest/tests/add003.py @@ -0,0 +1,23 @@ +self.description = "Install a set of packages" + +p1 = pmpkg("pkg1") +p1.files = ["bin/pkg1", + "usr/man/man1/pkg1.1"] + +p2 = pmpkg("pkg2", "2.0-1") +p2.files = ["bin/pkg2", + "usr/man/man1/pkg2.1"] + +p3 = pmpkg("pkg3", "3.0-1") +p3.files = ["bin/pkg3", "usr/man/man1/pkg3.1"] + +for p in p1, p2, p3: + self.addpkg(p) + +self.args = "-A %s" % " ".join([p.filename() for p in p1, p2, p3]) + +self.addrule("PACMAN_RETCODE=0") +for p in p1, p2, p3: + self.addrule("PKG_EXIST=%s" % p.name) + for f in p.files: + self.addrule("FILE_EXIST=%s" % f) diff --git a/pactest/tests/add004.py b/pactest/tests/add004.py new file mode 100644 index 00000000..59ba45c6 --- /dev/null +++ b/pactest/tests/add004.py @@ -0,0 +1,12 @@ +self.description = "Install a set of the same package at different versions" + +p1 = pmpkg("dummy", "1.0-2") +p2 = pmpkg("dummy", "2.0-1") +p3 = pmpkg("dummy") +for p in p1, p2, p3: + self.addpkg(p) + +self.args = "-A %s" % " ".join([p.filename() for p in p1, p2, p3]) + +self.addrule("PACMAN_RETCODE=0") +self.addrule("PKG_VERSION=dummy|2.0-1") diff --git a/pactest/tests/add010.py b/pactest/tests/add010.py new file mode 100644 index 00000000..a7874746 --- /dev/null +++ b/pactest/tests/add010.py @@ -0,0 +1,15 @@ +self.description = "Install a package with a filesystem conflict" + +p = pmpkg("dummy") +p.files = ["bin/dummy", + "usr/man/man1/dummy.1"] +self.addpkg(p) + +self.filesystem = ["bin/dummy"] + +self.args = "-A %s" % p.filename() + +self.addrule("PACMAN_RETCODE=1") +self.addrule("!PKG_EXIST=dummy") +self.addrule("!FILE_MODIFIED=bin/dummy") +self.addrule("!FILE_EXIST=usr/man/man1/dummy.1") diff --git a/pactest/tests/add011.py b/pactest/tests/add011.py new file mode 100644 index 00000000..5d2ae43f --- /dev/null +++ b/pactest/tests/add011.py @@ -0,0 +1,14 @@ +self.description = "Install a package with a filesystem conflict (--force)" + +p = pmpkg("dummy") +p.files = ["bin/dummy", "usr/man/man1/dummy.1"] +self.addpkg(p) + +self.filesystem = ["bin/dummy"] + +self.args = "-Af %s" % p.filename() + +self.addrule("PACMAN_RETCODE=0") +self.addrule("PKG_EXIST=dummy") +self.addrule("FILE_MODIFIED=bin/dummy") +self.addrule("FILE_EXIST=usr/man/man1/dummy.1") diff --git a/pactest/tests/add012.py b/pactest/tests/add012.py new file mode 100644 index 00000000..291d1fba --- /dev/null +++ b/pactest/tests/add012.py @@ -0,0 +1,20 @@ +self.description = "Install two packages with a conflicting file" + +p1 = pmpkg("dummy") +p1.files = ["bin/dummy", + "usr/man/man1/dummy.1", + "usr/common"] + +p2 = pmpkg("foobar") +p2.files = ["bin/foobar", + "usr/man/man1/foobar.1", + "usr/common"] + +for p in p1, p2: + self.addpkg(p) + +self.args = "-A %s" % " ".join([p.filename() for p in p1, p2]) + +self.addrule("PACMAN_RETCODE=1") +self.addrule("!PKG_EXIST=dummy") +self.addrule("!PKG_EXIST=foobar") diff --git a/pactest/tests/add013.py b/pactest/tests/add013.py new file mode 100644 index 00000000..547ce001 --- /dev/null +++ b/pactest/tests/add013.py @@ -0,0 +1,23 @@ +self.description = "Install two packages with a conflicting file (--force)" + +p1 = pmpkg("dummy") +p1.files = ["bin/dummy", + "usr/man/man1/dummy.1", + "usr/common"] + +p2 = pmpkg("foobar") +p2.files = ["bin/foobar", + "usr/man/man1/foobar.1", + "usr/common"] + +for p in p1, p2: + self.addpkg(p) + +self.args = "-Af %s" % " ".join([p.filename() for p in p1, p2]) + +self.addrule("PACMAN_RETCODE=0") +for p in p1, p2: + self.addrule("PKG_EXIST=%s" % p.name) + self.addrule("PKG_FILES=%s|usr/common" % p.name) + for f in p.files: + self.addrule("FILE_EXIST=%s" % f) diff --git a/pactest/tests/add020.py b/pactest/tests/add020.py new file mode 100644 index 00000000..b435ddde --- /dev/null +++ b/pactest/tests/add020.py @@ -0,0 +1,15 @@ +self.description = "Install a package with an existing file" + +p = pmpkg("dummy") +p.files = ["etc/dummy.conf"] +self.addpkg(p) + +self.filesystem = ["etc/dummy.conf"] + +self.args = "-Af %s" % p.filename() + +self.addrule("PACMAN_RETCODE=0") +self.addrule("PKG_EXIST=dummy") +self.addrule("FILE_MODIFIED=etc/dummy.conf") +self.addrule("!FILE_PACNEW=etc/dummy.conf") +self.addrule("!FILE_PACORIG=etc/dummy.conf") diff --git a/pactest/tests/add021.py b/pactest/tests/add021.py new file mode 100644 index 00000000..ab96d156 --- /dev/null +++ b/pactest/tests/add021.py @@ -0,0 +1,16 @@ +self.description = "Install a package with an existing file (new modified)" + +p = pmpkg("dummy") +p.files = ["etc/dummy.conf*"] +p.backup = ["etc/dummy.conf"] +self.addpkg(p) + +self.filesystem = ["etc/dummy.conf"] + +self.args = "-Af %s" % p.filename() + +self.addrule("PACMAN_RETCODE=0") +self.addrule("PKG_EXIST=dummy") +self.addrule("FILE_MODIFIED=etc/dummy.conf") +self.addrule("!FILE_PACNEW=etc/dummy.conf") +self.addrule("FILE_PACORIG=etc/dummy.conf") diff --git a/pactest/tests/add030.py b/pactest/tests/add030.py new file mode 100644 index 00000000..d36311c0 --- /dev/null +++ b/pactest/tests/add030.py @@ -0,0 +1,18 @@ +self.description = "Freshen a package" + +lp = pmpkg("dummy") +lp.files = ["bin/dummy", + "usr/man/man1/dummy.1"] +self.addpkg2db("local", lp) + +p = pmpkg("dummy", "1.0-2") +p.files = ["bin/dummy", + "usr/man/man1/dummy.1"] +self.addpkg(p) + +self.args = "-F %s" % p.filename() + +self.addrule("PACMAN_RETCODE=0") +self.addrule("PKG_VERSION=dummy|1.0-2") +for f in p.files: + self.addrule("FILE_MODIFIED=%s" % f) diff --git a/pactest/tests/add031.py b/pactest/tests/add031.py new file mode 100644 index 00000000..38b0485c --- /dev/null +++ b/pactest/tests/add031.py @@ -0,0 +1,18 @@ +self.description = "Freshen a package (installed is newer)" + +lp = pmpkg("dummy", "1.0-2") +lp.files = ["bin/dummy", + "usr/man/man1/dummy.1"] +self.addpkg2db("local", lp) + +p = pmpkg("dummy") +p.files = ["bin/dummy", + "usr/man/man1/dummy.1"] +self.addpkg(p) + +self.args = "-F %s" % p.filename() + +self.addrule("PACMAN_RETCODE=1") +self.addrule("!PKG_MODIFIED=dummy") +for f in p.files: + self.addrule("!FILE_MODIFIED=%s" % f) diff --git a/pactest/tests/add032.py b/pactest/tests/add032.py new file mode 100644 index 00000000..00d9a6d0 --- /dev/null +++ b/pactest/tests/add032.py @@ -0,0 +1,18 @@ +self.description = "Freshen a package (installed is newer)" + +lp = pmpkg("dummy") +lp.files = ["bin/dummy", + "usr/man/man1/dummy.1"] +self.addpkg2db("local", lp) + +p = pmpkg("dummy") +p.files = ["bin/dummy", + "usr/man/man1/dummy.1"] +self.addpkg(p) + +self.args = "-F %s" % p.filename() + +self.addrule("PACMAN_RETCODE=1") +self.addrule("!PKG_MODIFIED=dummy") +for f in p.files: + self.addrule("!FILE_MODIFIED=%s" % f) diff --git a/pactest/tests/add040.py b/pactest/tests/add040.py new file mode 100644 index 00000000..2bb7f91b --- /dev/null +++ b/pactest/tests/add040.py @@ -0,0 +1,14 @@ +self.description = "Install a package with a missing dependency" + +p = pmpkg("dummy") +p.files = ["bin/dummy", + "usr/man/man1/dummy.1"] +p.depends = ["missdep"] +self.addpkg(p) + +self.args = "-A %s" % p.filename() + +self.addrule("PACMAN_RETCODE=1") +self.addrule("!PKG_EXIST=dummy") +for f in p.files: + self.addrule("!FILE_EXIST=%s" % f) diff --git a/pactest/tests/add041.py b/pactest/tests/add041.py new file mode 100644 index 00000000..af3ffe46 --- /dev/null +++ b/pactest/tests/add041.py @@ -0,0 +1,15 @@ +self.description = "Install a package with a missing dependency (nodeps)" + +p = pmpkg("dummy") +p.files = ["bin/dummy", + "usr/man/man1/dummy.1"] +p.depends = ["dep1"] +self.addpkg(p) + +self.args = "-Ad %s" % p.filename() + +self.addrule("PACMAN_RETCODE=0") +self.addrule("PKG_EXIST=dummy") +self.addrule("PKG_DEPENDS=dummy|dep1") +for f in p.files: + self.addrule("FILE_EXIST=%s" % f) diff --git a/pactest/tests/add042.py b/pactest/tests/add042.py new file mode 100644 index 00000000..a9b17c0f --- /dev/null +++ b/pactest/tests/add042.py @@ -0,0 +1,29 @@ +self.description = "Install a package with cascaded dependencies" + +p1 = pmpkg("dummy", "1.0-2") +p1.files = ["bin/dummy", + "usr/man/man1/dummy.1"] +p1.depends = ["dep1"] + +p2 = pmpkg("dep1") +p2.files = ["bin/dep1"] +p2.depends = ["dep2"] + +p3 = pmpkg("dep2") +p3.files = ["bin/dep2"] + +for p in p1, p2, p3: + self.addpkg(p) + +self.args = "-A %s" % " ".join([p.filename() for p in p1, p2, p3]) + +self.addrule("PACMAN_RETCODE=0") +self.addrule("PKG_VERSION=dummy|1.0-2") +for f in p1.files: + self.addrule("FILE_EXIST=%s" % f) +self.addrule("PKG_EXIST=dep1") +self.addrule("PKG_EXIST=dep2") +self.addrule("PKG_DEPENDS=dummy|dep1") +self.addrule("PKG_DEPENDS=dep1|dep2") +self.addrule("PKG_REQUIREDBY=dep1|dummy") +self.addrule("PKG_REQUIREDBY=dep2|dep1") diff --git a/pactest/tests/add050.py b/pactest/tests/add050.py new file mode 100644 index 00000000..f9b3b251 --- /dev/null +++ b/pactest/tests/add050.py @@ -0,0 +1,16 @@ +self.description = "Install a package with a file in NoUpgrade" + +p = pmpkg("dummy") +p.files = ["etc/dummy.conf"] +self.addpkg(p) + +self.filesystem = ["etc/dummy.conf"] + +self.option["noupgrade"] = ["etc/dummy.conf"] + +self.args = "-Af %s" % p.filename() + +self.addrule("PACMAN_RETCODE=0") +self.addrule("PKG_EXIST=dummy") +self.addrule("!FILE_MODIFIED=etc/dummy.conf") +self.addrule("FILE_PACNEW=etc/dummy.conf") diff --git a/pactest/tests/add060.py b/pactest/tests/add060.py new file mode 100644 index 00000000..4c5f17da --- /dev/null +++ b/pactest/tests/add060.py @@ -0,0 +1,15 @@ +self.description = "Install a package with a file in NoExtract" + +p = pmpkg("dummy") +p.files = ["bin/dummy", + "usr/man/man1/dummy.1"] +self.addpkg(p) + +self.option["noextract"] = ["usr/man/man1/dummy.1"] + +self.args = "-A %s" % p.filename() + +self.addrule("PACMAN_RETCODE=0") +self.addrule("PKG_EXIST=dummy") +self.addrule("FILE_EXIST=bin/dummy") +self.addrule("!FILE_EXIST=usr/man/man1/dummy.1") diff --git a/pactest/tests/dummy001.py b/pactest/tests/dummy001.py new file mode 100644 index 00000000..79e2bd00 --- /dev/null +++ b/pactest/tests/dummy001.py @@ -0,0 +1,19 @@ +self.description = "dummy test case" + +p1 = pmpkg("dummy") +p1.files = ["etc/dummy.conf*", + "lib/libdummy.so.0", + "lib/libdummy.so -> ./libdummy.so.0", + "usr/", + "bin/dummy"] +p1.backup = ["etc/dummy.conf*"] +p1.install['post_install'] = "echo toto"; +p1.url="ze url" +self.addpkg(p1) + +#p2 = pmpkg("dummy", "1.0-2") +#p2.files = ["etc/dummy.conf**"] +#p2.backup = ["etc/dummy.conf"] +#self.addpkg(p2) + +self.args = "-U %s" % p1.filename() diff --git a/pactest/tests/query001.py b/pactest/tests/query001.py new file mode 100644 index 00000000..fe689104 --- /dev/null +++ b/pactest/tests/query001.py @@ -0,0 +1,9 @@ +self.description = "Query a package" + +p = pmpkg("foobar") +p.files = ["bin/foobar"] +self.addpkg2db("local", p) + +self.args = "-Q foobar" + +self.addrule("PACMAN_OUTPUT=foobar") diff --git a/pactest/tests/remove010.py b/pactest/tests/remove010.py new file mode 100644 index 00000000..aff46f0e --- /dev/null +++ b/pactest/tests/remove010.py @@ -0,0 +1,12 @@ +self.description = "Remove a package, with a file marked for backup" + +p1 = pmpkg("dummy") +p1.files = ["etc/dummy.conf"] +p1.backup = ["etc/dummy.conf"] +self.addpkg2db("local", p1) + +self.args = "-R dummy" + +self.addrule("!PKG_EXIST=dummy") +self.addrule("!FILE_EXIST=etc/dummy.conf") +self.addrule("FILE_PACSAVE=etc/dummy.conf") diff --git a/pactest/tests/remove011.py b/pactest/tests/remove011.py new file mode 100644 index 00000000..afc03d45 --- /dev/null +++ b/pactest/tests/remove011.py @@ -0,0 +1,12 @@ +self.description = "Remove a package, with a modified file marked for backup" + +p1 = pmpkg("dummy") +p1.files = ["etc/dummy.conf*"] +p1.backup = ["etc/dummy.conf"] +self.addpkg2db("local", p1) + +self.args = "-R dummy" + +self.addrule("!PKG_EXIST=dummy") +self.addrule("!FILE_EXIST=etc/dummy.conf") +self.addrule("FILE_PACSAVE=etc/dummy.conf") diff --git a/pactest/tests/remove020.py b/pactest/tests/remove020.py new file mode 100644 index 00000000..293ad1bd --- /dev/null +++ b/pactest/tests/remove020.py @@ -0,0 +1,12 @@ +self.description = "Remove a package, with a file marked for backup (--nosave)" + +p1 = pmpkg("dummy") +p1.files = ["etc/dummy.conf"] +p1.backup = ["etc/dummy.conf"] +self.addpkg2db("local", p1) + +self.args = "-Rn dummy" + +self.addrule("!PKG_EXIST=dummy") +self.addrule("!FILE_EXIST=etc/dummy.conf") +self.addrule("!FILE_PACSAVE=etc/dummy.conf") diff --git a/pactest/tests/remove021.py b/pactest/tests/remove021.py new file mode 100644 index 00000000..388bf018 --- /dev/null +++ b/pactest/tests/remove021.py @@ -0,0 +1,12 @@ +self.description = "Remove a package, with a modified file marked for backup (--nosave)" + +p1 = pmpkg("dummy") +p1.files = ["etc/dummy.conf*"] +p1.backup = ["etc/dummy.conf"] +self.addpkg2db("local", p1) + +self.args = "-Rn dummy" + +self.addrule("!PKG_EXIST=dummy") +self.addrule("!FILE_EXIST=etc/dummy.conf") +self.addrule("!FILE_PACSAVE=etc/dummy.conf") diff --git a/pactest/tests/remove030.py b/pactest/tests/remove030.py new file mode 100644 index 00000000..ff81a263 --- /dev/null +++ b/pactest/tests/remove030.py @@ -0,0 +1,12 @@ +self.description = "Remove a package in HoldPkg" + +p1 = pmpkg("dummy") +self.addpkg2db("local", p1) + +self.option["holdpkg"] = ["dummy"] + +self.args = "-R dummy" + +self.addrule("!PKG_EXIST=dummy") +self.addrule("!FILE_EXIST=etc/dummy.conf") +self.addrule("!FILE_PACSAVE=etc/dummy.conf") diff --git a/pactest/tests/smoke001.py b/pactest/tests/smoke001.py new file mode 100644 index 00000000..85ee782b --- /dev/null +++ b/pactest/tests/smoke001.py @@ -0,0 +1,19 @@ +self.description = "Install a thousand packages in a single transaction" + +p = pmpkg("pkg1000") + +self.addpkg2db("local", p) + +for i in range(1000): + p = pmpkg("pkg%03d" % i) + p.depends = ["pkg%03d" % (i+1)] + p.files = ["usr/share/pkg%03d" % i] + self.addpkg(p) + +_list = [] +[_list.append(p.filename()) for p in self.localpkgs] +self.args = "-A %s" % " ".join(_list) + +self.addrule("PACMAN_RETCODE=0") +#for i in range(1000): +# self.addrule("PKG_EXIST=pkg%03d" %i) diff --git a/pactest/tests/sync001.py b/pactest/tests/sync001.py new file mode 100644 index 00000000..fc2015d4 --- /dev/null +++ b/pactest/tests/sync001.py @@ -0,0 +1,12 @@ +self.description = "Install a package from a sync db" + +sp = pmpkg("dummy") +sp.files = ["bin/dummy", + "usr/man/man1/dummy.1"] +self.addpkg2db("sync", sp) + +self.args = "-S dummy" + +self.addrule("PKG_EXIST=dummy") +for f in sp.files: + self.addrule("FILE_EXIST=%s" % f) diff --git a/pactest/tests/sync002.py b/pactest/tests/sync002.py new file mode 100644 index 00000000..43c99fbd --- /dev/null +++ b/pactest/tests/sync002.py @@ -0,0 +1,17 @@ +self.description = "Upgrade a package from a sync db" + +sp = pmpkg("dummy", "1.0-2") +sp.files = ["bin/dummy", + "usr/man/man1/dummy.1"] +self.addpkg2db("sync", sp) + +lp = pmpkg("dummy") +lp.files = ["bin/dummy", + "usr/man/man1/dummy.1"] +self.addpkg2db("local", lp) + +self.args = "-S dummy" + +self.addrule("PKG_VERSION=dummy|1.0-2") +for f in lp.files: + self.addrule("FILE_MODIFIED=%s" % f) diff --git a/pactest/tests/sync003.py b/pactest/tests/sync003.py new file mode 100644 index 00000000..3a480adf --- /dev/null +++ b/pactest/tests/sync003.py @@ -0,0 +1,12 @@ +self.description = "Install a package from a sync db, with a filesystem conflict" + +sp = pmpkg("dummy") +sp.files = ["bin/dummy", + "usr/man/man1/dummy.1"] +self.addpkg2db("sync", sp) + +self.filesystem = ["bin/dummy"] + +self.args = "-S dummy" + +self.addrule("!PKG_EXIST=dummy") diff --git a/pactest/tests/sync009.py b/pactest/tests/sync009.py new file mode 100644 index 00000000..fc2015d4 --- /dev/null +++ b/pactest/tests/sync009.py @@ -0,0 +1,12 @@ +self.description = "Install a package from a sync db" + +sp = pmpkg("dummy") +sp.files = ["bin/dummy", + "usr/man/man1/dummy.1"] +self.addpkg2db("sync", sp) + +self.args = "-S dummy" + +self.addrule("PKG_EXIST=dummy") +for f in sp.files: + self.addrule("FILE_EXIST=%s" % f) diff --git a/pactest/tests/sync010.py b/pactest/tests/sync010.py new file mode 100644 index 00000000..9e54eb62 --- /dev/null +++ b/pactest/tests/sync010.py @@ -0,0 +1,26 @@ +self.description = "Install a package from a sync db, with its dependencies" + +sp1 = pmpkg("dummy", "1.0-2") +sp1.files = ["bin/dummy", + "usr/man/man1/dummy.1"] +sp1.depends = ["dep1"] + +sp2 = pmpkg("dep1") +sp2.files = ["bin/dep1"] +sp2.depends = ["dep2"] + +sp3 = pmpkg("dep2") +sp3.files = ["bin/dep2"] + +for p in sp1, sp2, sp3: + self.addpkg2db("sync", p); + +self.args = "-S dummy" + +self.addrule("PKG_VERSION=dummy|1.0-2") +self.addrule("PKG_DEPENDS=dummy|dep1") +for f in sp1.files: + self.addrule("FILE_EXIST=%s" % f) +self.addrule("PKG_DEPENDS=dep1|dep2") +self.addrule("PKG_REQUIREDBY=dep1|dummy") +self.addrule("PKG_REQUIREDBY=dep2|dep1") diff --git a/pactest/tests/sync020.py b/pactest/tests/sync020.py new file mode 100644 index 00000000..eae699fe --- /dev/null +++ b/pactest/tests/sync020.py @@ -0,0 +1,19 @@ +self.description = "Install a group from a sync db" + +sp1 = pmpkg("pkg1") +sp1.groups = ["grp"] + +sp2 = pmpkg("pkg2") +sp2.groups = ["grp"] + +sp3 = pmpkg("pkg3") +sp3.groups = ["grp"] + +for p in sp1, sp2, sp3: + self.addpkg2db("sync", p); + +self.args = "-S grp" + +self.addrule("PACMAN_RETCODE=0") +for p in sp1, sp2, sp3: + self.addrule("PKG_EXIST=%s" % p.name) diff --git a/pactest/tests/sync021.py b/pactest/tests/sync021.py new file mode 100644 index 00000000..d8a5475b --- /dev/null +++ b/pactest/tests/sync021.py @@ -0,0 +1,21 @@ +self.description = "Install a group from a sync db, with a package in IgnorePkg" + +sp1 = pmpkg("pkg1") +sp1.groups = ["grp"] + +sp2 = pmpkg("pkg2") +sp2.groups = ["grp"] + +sp3 = pmpkg("pkg3") +sp3.groups = ["grp"] + +for p in sp1, sp2, sp3: + self.addpkg2db("sync", p); + +self.option["ignorepkg"] = ["pkg2"] + +self.args = "-S grp" + +self.addrule("PACMAN_RETCODE=0") +for p in sp1, sp2, sp3: + self.addrule("PKG_EXIST=%s" % p.name) diff --git a/pactest/tests/sync040.py b/pactest/tests/sync040.py new file mode 100644 index 00000000..73f6ee63 --- /dev/null +++ b/pactest/tests/sync040.py @@ -0,0 +1,15 @@ +self.description = "Install two targets with a conflict" + +sp1 = pmpkg("pkg1") +sp1.conflicts = ["pkg2"] + +sp2 = pmpkg("pkg2") + +for p in sp1, sp2: + self.addpkg2db("sync", p); + +self.args = "-S pkg1 pkg2" + +self.addrule("PACMAN_RETCODE=1") +for p in sp1, sp2: + self.addrule("!PKG_EXIST=%s" % p.name) diff --git a/pactest/tests/sync041.py b/pactest/tests/sync041.py new file mode 100644 index 00000000..a612e71f --- /dev/null +++ b/pactest/tests/sync041.py @@ -0,0 +1,16 @@ +self.description = "Install two conflicting targets" + +sp1 = pmpkg("pkg1") +sp1.conflicts = ["pkg2"] + +sp2 = pmpkg("pkg2") +sp2.conflicts = ["pkg1"] + +for p in sp1, sp2: + self.addpkg2db("sync", p); + +self.args = "-S pkg1 pkg2" + +self.addrule("PACMAN_RETCODE=1") +self.addrule("!PKG_EXIST=pkg1") +self.addrule("!PKG_EXIST=pkg2") diff --git a/pactest/tests/sync042.py b/pactest/tests/sync042.py new file mode 100644 index 00000000..200626d3 --- /dev/null +++ b/pactest/tests/sync042.py @@ -0,0 +1,14 @@ +self.description = "Install a sync package conflicting with a local one" + +sp = pmpkg("pkg1") +sp.conflicts = ["pkg2"] +self.addpkg2db("sync", sp); + +lp = pmpkg("pkg2") +self.addpkg2db("local", lp); + +self.args = "-S pkg1" + +self.addrule("PACMAN_RETCODE=0") +self.addrule("PKG_EXIST=pkg1") +self.addrule("!PKG_EXIST=pkg2") diff --git a/pactest/tests/sync043.py b/pactest/tests/sync043.py new file mode 100644 index 00000000..200626d3 --- /dev/null +++ b/pactest/tests/sync043.py @@ -0,0 +1,14 @@ +self.description = "Install a sync package conflicting with a local one" + +sp = pmpkg("pkg1") +sp.conflicts = ["pkg2"] +self.addpkg2db("sync", sp); + +lp = pmpkg("pkg2") +self.addpkg2db("local", lp); + +self.args = "-S pkg1" + +self.addrule("PACMAN_RETCODE=0") +self.addrule("PKG_EXIST=pkg1") +self.addrule("!PKG_EXIST=pkg2") diff --git a/pactest/tests/sync050.py b/pactest/tests/sync050.py new file mode 100644 index 00000000..6c7619be --- /dev/null +++ b/pactest/tests/sync050.py @@ -0,0 +1,10 @@ +self.description = "Install a virtual target (provided by a sync package)" + +sp1 = pmpkg("pkg1") +sp1.provides = ["pkg2"] +self.addpkg2db("sync", sp1); + +self.args = "-S pkg2" + +self.addrule("PACMAN_RETCODE=0") +self.addrule("PKG_EXIST=pkg1") diff --git a/pactest/tests/sync100.py b/pactest/tests/sync100.py new file mode 100644 index 00000000..a4997fb1 --- /dev/null +++ b/pactest/tests/sync100.py @@ -0,0 +1,12 @@ +self.description = "Sysupgrade with a newer sync package" + +sp = pmpkg("dummy", "1.0-2") +lp = pmpkg("dummy") + +self.addpkg2db("sync", sp) +self.addpkg2db("local", lp) + +self.args = "-Su" + +self.addrule("PACMAN_RETCODE=0") +self.addrule("PKG_VERSION=dummy|1.0-2") diff --git a/pactest/tests/sync101.py b/pactest/tests/sync101.py new file mode 100644 index 00000000..5d39ecb9 --- /dev/null +++ b/pactest/tests/sync101.py @@ -0,0 +1,12 @@ +self.description = "Sysupgrade with same version for local and sync packages" + +sp = pmpkg("dummy") +lp = pmpkg("dummy") + +self.addpkg2db("sync", sp) +self.addpkg2db("local", lp) + +self.args = "-Su" + +self.addrule("PACMAN_RETCODE=0") +self.addrule("!PKG_MODIFIED=dummy") diff --git a/pactest/tests/sync102.py b/pactest/tests/sync102.py new file mode 100644 index 00000000..40a7ec99 --- /dev/null +++ b/pactest/tests/sync102.py @@ -0,0 +1,12 @@ +self.description = "Sysupgrade with a newer local package" + +sp = pmpkg("dummy", "0.9-1") +lp = pmpkg("dummy") + +self.addpkg2db("sync", sp) +self.addpkg2db("local", lp) + +self.args = "-Su" + +self.addrule("PACMAN_RETCODE=0") +self.addrule("!PKG_MODIFIED=dummy") diff --git a/pactest/tests/sync103.py b/pactest/tests/sync103.py new file mode 100644 index 00000000..5d17790b --- /dev/null +++ b/pactest/tests/sync103.py @@ -0,0 +1,14 @@ +self.description = "Sysupgrade with a local package not existing in sync db" + +sp = pmpkg("spkg") + +self.addpkg2db("sync", sp) + +lp = pmpkg("lpkg") + +self.addpkg2db("local", lp) + +self.args = "-Su" + +self.addrule("PACMAN_RETCODE=0") +self.addrule("!PKG_MODIFIED=lpkg") diff --git a/pactest/tests/sync110.py b/pactest/tests/sync110.py new file mode 100644 index 00000000..08a1a890 --- /dev/null +++ b/pactest/tests/sync110.py @@ -0,0 +1,22 @@ +self.description = "Sysupgrade of a package pulling new dependencies" + +sp1 = pmpkg("pkg1", "1.0-2") +sp1.depends = ["pkg2"] + +sp2 = pmpkg("pkg2") +sp2.depends = ["pkg3"] + +sp3 = pmpkg("pkg3") + +for p in sp1, sp2, sp3: + self.addpkg2db("sync", p) + +lp1 = pmpkg("pkg1") +self.addpkg2db("local", lp1) + +self.args = "-Su" + +self.addrule("PACMAN_RETCODE=0") +self.addrule("PKG_VERSION=pkg1|1.0-2") +for p in sp2, sp3: + self.addrule("PKG_REASON=%s|1" % p.name) diff --git a/pactest/tests/sync120.py b/pactest/tests/sync120.py new file mode 100644 index 00000000..b8fc6747 --- /dev/null +++ b/pactest/tests/sync120.py @@ -0,0 +1,21 @@ +self.description = "Sysupgrade of packages in 'IgnorePkg'" + +sp1 = pmpkg("pkg1", "1.0-2") +sp2 = pmpkg("pkg2", "1.0-2") + +for p in sp1, sp2: + self.addpkg2db("sync", p) + +lp1 = pmpkg("pkg1") +lp2 = pmpkg("pkg2") + +for p in lp1, lp2: + self.addpkg2db("local", p) + +self.option["ignorepkg"] = ["pkg2"] + +self.args = "-Su" + +self.addrule("PACMAN_RETCODE=0") +self.addrule("PKG_VERSION=pkg1|1.0-2") +self.addrule("!PKG_MODIFIED=pkg2") diff --git a/pactest/tests/sync130.py b/pactest/tests/sync130.py new file mode 100644 index 00000000..afd196d1 --- /dev/null +++ b/pactest/tests/sync130.py @@ -0,0 +1,16 @@ +self.description = "Sysupgrade with a sync package replacing a local one" + +sp = pmpkg("pkg2") +sp.replaces = ["pkg1"] + +self.addpkg2db("sync", sp) + +lp = pmpkg("pkg1") + +self.addpkg2db("local", lp) + +self.args = "-Su" + +self.addrule("PACMAN_RETCODE=0") +self.addrule("!PKG_EXIST=pkg1") +self.addrule("PKG_EXIST=pkg2") diff --git a/pactest/tests/sync131.py b/pactest/tests/sync131.py new file mode 100644 index 00000000..d0ed1a9f --- /dev/null +++ b/pactest/tests/sync131.py @@ -0,0 +1,19 @@ +self.description = "Sysupgrade with a sync package replacing a set of local ones" + +sp = pmpkg("pkg4") +sp.replaces = ["pkg1", "pkg2", "pkg3"] + +self.addpkg2db("sync", sp) + +lp1 = pmpkg("pkg1") +lp2 = pmpkg("pkg2") + +for p in lp1, lp2: + self.addpkg2db("local", p) + +self.args = "-Su" + +self.addrule("PACMAN_RETCODE=0") +self.addrule("PKG_EXIST=pkg4") +for p in lp1, lp2: + self.addrule("!PKG_EXIST=%s" % p.name) diff --git a/pactest/tests/sync132.py b/pactest/tests/sync132.py new file mode 100644 index 00000000..5e85727d --- /dev/null +++ b/pactest/tests/sync132.py @@ -0,0 +1,18 @@ +self.description = "Sysupgrade with a replacement for a local package out of date" + +sp1 = pmpkg("pkg1") +sp1.replaces = ["pkg2"] +sp2 = pmpkg("pkg2", "2.0-1") + +for p in sp1, sp2: + self.addpkg2db("sync", p) + +lp = pmpkg("pkg2") + +self.addpkg2db("local", lp) + +self.args = "-Su" + +self.addrule("PACMAN_RETCODE=0") +self.addrule("PKG_EXIST=pkg1") +self.addrule("!PKG_EXIST=pkg2") diff --git a/pactest/tests/sync133.py b/pactest/tests/sync133.py new file mode 100644 index 00000000..b852a7fc --- /dev/null +++ b/pactest/tests/sync133.py @@ -0,0 +1,18 @@ +self.description = "Sysupgrade with a sync package replacing a local one in 'IgnorePkg'" + +sp = pmpkg("pkg2") +sp.replaces = ["pkg1"] + +self.addpkg2db("sync", sp) + +lp = pmpkg("pkg1") + +self.addpkg2db("local", lp) + +self.option["ignorepkg"] = ["pkg1"] + +self.args = "-Su" + +self.addrule("PACMAN_RETCODE=0") +self.addrule("PKG_EXIST=pkg1") +self.addrule("!PKG_EXIST=pkg2") diff --git a/pactest/tests/sync134.py b/pactest/tests/sync134.py new file mode 100644 index 00000000..572ab326 --- /dev/null +++ b/pactest/tests/sync134.py @@ -0,0 +1,21 @@ +self.description = "Sysupgrade with a set of sync packages replacing a set local one" + +sp1 = pmpkg("pkg2") +sp1.replaces = ["pkg1"] + +sp2 = pmpkg("pkg3") +sp2.replaces = ["pkg1"] + +for p in sp1, sp2: + self.addpkg2db("sync", p) + +lp = pmpkg("pkg1") + +self.addpkg2db("local", lp) + +self.args = "-Su" + +self.addrule("PACMAN_RETCODE=0") +self.addrule("!PKG_EXIST=pkg1") +for p in sp1, sp2: + self.addrule("PKG_EXIST=%s" % p.name) diff --git a/pactest/tests/sync135.py b/pactest/tests/sync135.py new file mode 100644 index 00000000..18c412aa --- /dev/null +++ b/pactest/tests/sync135.py @@ -0,0 +1,31 @@ +self.description = "Sysupgrade with a set of sync packages replacing a set of local ones" + +sp1 = pmpkg("pkg2") +sp1.replaces = ["pkg1"] + +sp2 = pmpkg("pkg3") +sp2.replaces = ["pkg1"] + +sp3 = pmpkg("pkg4") +sp3.replaces = ["pkg1", "pkg0"] + +sp4 = pmpkg("pkg5") +sp4.replaces = ["pkg0"] + +for p in sp1, sp2, sp3, sp4: + self.addpkg2db("sync", p) + +lp1 = pmpkg("pkg1") + +lp2 = pmpkg("pkg0") + +for p in lp1, lp2: + self.addpkg2db("local", p) + +self.args = "-Su" + +self.addrule("PACMAN_RETCODE=0") +for p in lp1, lp2: + self.addrule("!PKG_EXIST=%s" % p.name) +for p in sp1, sp2, sp3, sp4: + self.addrule("PKG_EXIST=%s" % p.name) diff --git a/pactest/tests/sync200.py b/pactest/tests/sync200.py new file mode 100644 index 00000000..82f30da1 --- /dev/null +++ b/pactest/tests/sync200.py @@ -0,0 +1,15 @@ +self.description = "Synchronize database" + +sp1 = pmpkg("spkg1", "1.0-1") +sp1.depends = ["spkg2"] +sp2 = pmpkg("spkg2", "2.0-1") +sp2.depends = ["spkg3"] +sp3 = pmpkg("spkg3", "3.0-1") +sp3.depends = ["spkg1"] + +for sp in sp1, sp2, sp3: + self.addpkg2db("sync", sp) + +self.args = "-Sy" + +self.addrule("PACMAN_RETCODE=0") diff --git a/pactest/tests/sync890.py b/pactest/tests/sync890.py new file mode 100644 index 00000000..0613128e --- /dev/null +++ b/pactest/tests/sync890.py @@ -0,0 +1,20 @@ +self.description = "conflict 'db vs targ'" + +sp = pmpkg("pkg3") + +self.addpkg2db("sync", sp) + +lp1 = pmpkg("pkg1") + +lp2 = pmpkg("pkg2") +lp2.conflicts = ["pkg3"] + +for p in lp1, lp2: + self.addpkg2db("local", p) + +self.args = "-S pkg3" + +self.addrule("PACMAN_RETCODE=0") +self.addrule("PKG_EXIST=pkg1") +self.addrule("!PKG_EXIST=pkg2") +self.addrule("PKG_EXIST=pkg3") diff --git a/pactest/tests/sync891.py b/pactest/tests/sync891.py new file mode 100644 index 00000000..7810ac93 --- /dev/null +++ b/pactest/tests/sync891.py @@ -0,0 +1,22 @@ +self.description = "conflict 'db vs targ'" + +sp1 = pmpkg("pkg2") +sp2 = pmpkg("pkg3") + +for p in sp1, sp2: + self.addpkg2db("sync", p) + +lp1 = pmpkg("pkg1") + +lp2 = pmpkg("pkg2") +lp2.conflicts = ["pkg3"] + +for p in lp1, lp2: + self.addpkg2db("local", p) + +self.args = "-S pkg2 pkg3" + +self.addrule("PACMAN_RETCODE=0") +self.addrule("PKG_EXIST=pkg1") +self.addrule("PKG_EXIST=pkg2") +self.addrule("PKG_EXIST=pkg3") diff --git a/pactest/tests/sync892.py b/pactest/tests/sync892.py new file mode 100644 index 00000000..9d37d682 --- /dev/null +++ b/pactest/tests/sync892.py @@ -0,0 +1,24 @@ +self.description = "conflict 'targ vs targ' and 'db vs targ'" + +sp1 = pmpkg("pkg2") +sp1.conflicts = ["pkg1"] + +sp2 = pmpkg("pkg3") + +for p in sp1, sp2: + self.addpkg2db("sync", p) + +lp1 = pmpkg("pkg1") + +lp2 = pmpkg("pkg2") +lp2.conflicts = ["pkg3"] + +for p in lp1, lp2: + self.addpkg2db("local", p) + +self.args = "-S pkg2 pkg3" + +self.addrule("PACMAN_RETCODE=0") +self.addrule("!PKG_EXIST=pkg1") +self.addrule("PKG_EXIST=pkg2") +self.addrule("PKG_EXIST=pkg3") diff --git a/pactest/tests/sync893.py b/pactest/tests/sync893.py new file mode 100644 index 00000000..7ab55383 --- /dev/null +++ b/pactest/tests/sync893.py @@ -0,0 +1,20 @@ +self.description = "conflict (bug)" + +sp1 = pmpkg("pkg1", "1.0-2") +sp1.conflicts = ["pkg2"] +self.addpkg2db("sync", sp1); + +sp2 = pmpkg("pkg2", "1.0-2") +self.addpkg2db("sync", sp2) + +lp1 = pmpkg("pkg1") +self.addpkg2db("local", lp1) + +lp2 = pmpkg("pkg2") +self.addpkg2db("local", lp2) + +self.args = "-S pkg1 pkg2" + +self.addrule("PACMAN_RETCODE=0") +self.addrule("PKG_EXIST=pkg1") +self.addrule("!PKG_EXIST=pkg2") diff --git a/pactest/tests/sync897.py b/pactest/tests/sync897.py new file mode 100644 index 00000000..adaaa1c2 --- /dev/null +++ b/pactest/tests/sync897.py @@ -0,0 +1,26 @@ +self.description = "System upgrade" + +sp1 = pmpkg("pkg1", "1.0-2") +sp1.conflicts = ["pkg2"] +sp1.provides = ["pkg2"] +self.addpkg2db("sync", sp1); + +sp2 = pmpkg("pkg2", "1.0-2") +self.addpkg2db("sync", sp2) + +lp1 = pmpkg("pkg1") +lp1.conflicts = ["pkg2"] +self.addpkg2db("local", lp1) + +lp2 = pmpkg("pkg2") +self.addpkg2db("local", lp2) + +lp3 = pmpkg("pkg3") +lp3.conflicts = ["pkg1"] +self.addpkg2db("local", lp3) + +self.args = "-Su" + +self.addrule("PACMAN_RETCODE=0") +self.addrule("PKG_EXIST=pkg1") +self.addrule("!PKG_EXIST=pkg2") diff --git a/pactest/tests/sync898.py b/pactest/tests/sync898.py new file mode 100644 index 00000000..06583217 --- /dev/null +++ b/pactest/tests/sync898.py @@ -0,0 +1,18 @@ +self.description = "System upgrade" + +sp1 = pmpkg("pkg1", "1.0-2") +sp1.conflicts = ["pkg2"] +sp1.provides = ["pkg2"] +self.addpkg2db("sync", sp1); + +sp2 = pmpkg("pkg2", "1.0-2") +self.addpkg2db("sync", sp2) + +lp1 = pmpkg("pkg1") +self.addpkg2db("local", lp1) + +self.args = "-S pkg1 pkg2" + +self.addrule("PACMAN_RETCODE=1") +self.addrule("!PKG_MODIFIED=pkg1") +self.addrule("!PKG_EXIST=pkg2") diff --git a/pactest/tests/sync899.py b/pactest/tests/sync899.py new file mode 100644 index 00000000..698c93ea --- /dev/null +++ b/pactest/tests/sync899.py @@ -0,0 +1,18 @@ +self.description = "System upgrade" + +sp1 = pmpkg("pkg1", "1.0-2") +sp1.conflicts = ["pkg2"] +sp1.provides = ["pkg2"] +self.addpkg2db("sync", sp1); + +lp1 = pmpkg("pkg1") +self.addpkg2db("local", lp1) + +lp2 = pmpkg("pkg2") +self.addpkg2db("local", lp2) + +self.args = "-Su" + +self.addrule("PACMAN_RETCODE=0") +self.addrule("PKG_EXIST=pkg1") +self.addrule("!PKG_EXIST=pkg2") diff --git a/pactest/tests/sync990.py b/pactest/tests/sync990.py new file mode 100644 index 00000000..1bf532c5 --- /dev/null +++ b/pactest/tests/sync990.py @@ -0,0 +1,20 @@ +self.description = "Sync a package pulling a dependency conflicting with a target" + +sp1 = pmpkg("pkg1") +sp1.depends = ["pkg3"] + +sp2 = pmpkg("pkg2") + +sp3 = pmpkg("pkg3") +sp3.conflicts = ["pkg2"] +sp3.provides = ["pkg2"] + +for p in sp1, sp2, sp3: + self.addpkg2db("sync", p) + +self.args = "-S pkg1 pkg2" + +self.addrule("PACMAN_RETCODE=0") +self.addrule("PKG_EXIST=pkg1") +self.addrule("PKG_EXIST=pkg2") +self.addrule("!PKG_EXIST=pkg3") diff --git a/pactest/tests/sync992.py b/pactest/tests/sync992.py new file mode 100644 index 00000000..fc07f0cc --- /dev/null +++ b/pactest/tests/sync992.py @@ -0,0 +1,23 @@ +self.description = "Sync a package pulling a conflicting dependency" + +sp1 = pmpkg("pkg1") +sp1.depends = ["pkg3"] + +sp2 = pmpkg("pkg2") + +sp3 = pmpkg("pkg3") +sp3.conflicts = ["pkg2"] +sp3.provides = ["pkg2"] + +for p in sp1, sp2, sp3: + self.addpkg2db("sync", p) + +lp1 = pmpkg("pkg2", "0.1-1") +self.addpkg2db("local", lp1) + +self.args = "-S pkg1 pkg2" + +self.addrule("PACMAN_RETCODE=0") +self.addrule("PKG_EXIST=pkg1") +self.addrule("!PKG_EXIST=pkg2") +self.addrule("PKG_EXIST=pkg3") diff --git a/pactest/tests/sync999.py b/pactest/tests/sync999.py new file mode 100644 index 00000000..69089fa1 --- /dev/null +++ b/pactest/tests/sync999.py @@ -0,0 +1,21 @@ +self.description = "System upgrade" + +sp1 = pmpkg("pkg1", "1.0-2") +sp1.conflicts = ["pkg2"] +sp1.provides = ["pkg2"] +self.addpkg2db("sync", sp1); + +sp2 = pmpkg("pkg2", "1.0-2") +self.addpkg2db("sync", sp2) + +lp1 = pmpkg("pkg1") +self.addpkg2db("local", lp1) + +lp2 = pmpkg("pkg2") +self.addpkg2db("local", lp2) + +self.args = "-Su" + +self.addrule("PACMAN_RETCODE=0") +self.addrule("PKG_EXIST=pkg1") +self.addrule("!PKG_EXIST=pkg2") diff --git a/pactest/tests/upgrade001.py b/pactest/tests/upgrade001.py new file mode 100644 index 00000000..2a9538e0 --- /dev/null +++ b/pactest/tests/upgrade001.py @@ -0,0 +1,18 @@ +self.description = "Upgrade a package (newer version)" + +lp = pmpkg("dummy") +lp.files = ["bin/dummy", + "usr/man/man1/dummy.1"] +self.addpkg2db("local", lp) + +p = pmpkg("dummy", "1.0-2") +p.files = ["bin/dummy", + "usr/man/man1/dummy.1"] +self.addpkg(p) + +self.args = "-U %s" % p.filename() + +self.addrule("PKG_MODIFIED=dummy") +self.addrule("PKG_VERSION=dummy|1.0-2") +for f in lp.files: + self.addrule("FILE_MODIFIED=%s" % f) diff --git a/pactest/tests/upgrade002.py b/pactest/tests/upgrade002.py new file mode 100644 index 00000000..d561d894 --- /dev/null +++ b/pactest/tests/upgrade002.py @@ -0,0 +1,18 @@ +self.description = "Upgrade a package (same version)" + +lp = pmpkg("dummy") +lp.files = ["bin/dummy", + "usr/man/man1/dummy.1"] +self.addpkg2db("local", lp) + +p = pmpkg("dummy") +p.files = ["bin/dummy", + "usr/man/man1/dummy.1"] +self.addpkg(p) + +self.args = "-U %s" % p.filename() + +self.addrule("PKG_MODIFIED=dummy") +self.addrule("PKG_VERSION=dummy|1.0-1") +for f in lp.files: + self.addrule("FILE_MODIFIED=%s" % f) diff --git a/pactest/tests/upgrade003.py b/pactest/tests/upgrade003.py new file mode 100644 index 00000000..dac21e59 --- /dev/null +++ b/pactest/tests/upgrade003.py @@ -0,0 +1,18 @@ +self.description = "Upgrade a package (lesser version)" + +lp = pmpkg("dummy", "1.0-2") +lp.files = ["bin/dummy", + "usr/man/man1/dummy.1"] +self.addpkg2db("local", lp) + +p = pmpkg("dummy") +p.files = ["bin/dummy", + "usr/man/man1/dummy.1"] +self.addpkg(p) + +self.args = "-U %s" % p.filename() + +self.addrule("PKG_MODIFIED=dummy") +self.addrule("PKG_VERSION=dummy|1.0-1") +for f in lp.files: + self.addrule("FILE_MODIFIED=%s" % f) diff --git a/pactest/tests/upgrade004.py b/pactest/tests/upgrade004.py new file mode 100644 index 00000000..31daf915 --- /dev/null +++ b/pactest/tests/upgrade004.py @@ -0,0 +1,12 @@ +self.description = "Upgrade a package (not installed)" + +p = pmpkg("dummy") +p.files = ["bin/dummy", + "usr/man/man1/dummy.1"] +self.addpkg(p) + +self.args = "-U %s" % p.filename() + +self.addrule("PKG_EXIST=dummy") +for f in p.files: + self.addrule("FILE_EXIST=%s" % f) diff --git a/pactest/tests/upgrade010.py b/pactest/tests/upgrade010.py new file mode 100644 index 00000000..04f3d816 --- /dev/null +++ b/pactest/tests/upgrade010.py @@ -0,0 +1,17 @@ +self.description = "Upgrade a package, with a file in NoUpgrade" + +lp = pmpkg("dummy") +lp.files = ["etc/dummy.conf"] +self.addpkg2db("local", lp) + +p = pmpkg("dummy", "1.0-2") +p.files = ["etc/dummy.conf"] +self.addpkg(p) + +self.option["noupgrade"] = ["etc/dummy.conf"] + +self.args = "-U %s" % p.filename() + +self.addrule("PKG_VERSION=dummy|1.0-2") +self.addrule("!FILE_MODIFIED=etc/dummy.conf") +self.addrule("FILE_PACNEW=etc/dummy.conf") diff --git a/pactest/tests/upgrade020.py b/pactest/tests/upgrade020.py new file mode 100644 index 00000000..bab00381 --- /dev/null +++ b/pactest/tests/upgrade020.py @@ -0,0 +1,17 @@ +self.description = "Upgrade a package, with a file in 'backup' (new modified)" + +lp = pmpkg("dummy") +lp.files = ["etc/dummy.conf"] +lp.backup = ["etc/dummy.conf"] +self.addpkg2db("local", lp) + +p = pmpkg("dummy", "1.0-2") +p.files = ["etc/dummy.conf*"] +p.backup = ["etc/dummy.conf"] +self.addpkg(p) + +self.args = "-U %s" % p.filename() + +self.addrule("PKG_VERSION=dummy|1.0-2") +self.addrule("FILE_MODIFIED=etc/dummy.conf") +self.addrule("!FILE_PACNEW=etc/dummy.conf") diff --git a/pactest/tests/upgrade021.py b/pactest/tests/upgrade021.py new file mode 100644 index 00000000..1ac0ceb5 --- /dev/null +++ b/pactest/tests/upgrade021.py @@ -0,0 +1,17 @@ +self.description = "Upgrade a package, with a file in 'backup' (local modified, new unchanged)" + +lp = pmpkg("dummy") +lp.files = ["etc/dummy.conf*"] +lp.backup = ["etc/dummy.conf"] +self.addpkg2db("local", lp) + +p = pmpkg("dummy", "1.0-2") +p.files = ["etc/dummy.conf"] +p.backup = ["etc/dummy.conf"] +self.addpkg(p) + +self.args = "-U %s" % p.filename() + +self.addrule("PKG_VERSION=dummy|1.0-2") +self.addrule("!FILE_MODIFIED=etc/dummy.conf") +self.addrule("!FILE_PACNEW=etc/dummy.conf") diff --git a/pactest/tests/upgrade022.py b/pactest/tests/upgrade022.py new file mode 100644 index 00000000..6bf12c15 --- /dev/null +++ b/pactest/tests/upgrade022.py @@ -0,0 +1,17 @@ +self.description = "Upgrade a package, with a file in 'backup' (local and new modified)" + +lp = pmpkg("dummy") +lp.files = ["etc/dummy.conf"] +lp.backup = ["etc/dummy.conf*"] +self.addpkg2db("local", lp) + +p = pmpkg("dummy", "1.0-2") +p.files = ["etc/dummy.conf**"] +p.backup = ["etc/dummy.conf"] +self.addpkg(p) + +self.args = "-U %s" % p.filename() + +self.addrule("PKG_VERSION=dummy|1.0-2") +self.addrule("!FILE_MODIFIED=etc/dummy.conf") +self.addrule("FILE_PACNEW=etc/dummy.conf") diff --git a/pactest/tests/upgrade030.py b/pactest/tests/upgrade030.py new file mode 100644 index 00000000..1082c32b --- /dev/null +++ b/pactest/tests/upgrade030.py @@ -0,0 +1,22 @@ +self.description = "Upgrade packages with various reasons" + +lp1 = pmpkg("pkg1") +lp1.reason = 0 +lp2 = pmpkg("pkg2") +lp2.reason = 1 + +for p in lp1, lp2: + self.addpkg2db("local", p) + +p1 = pmpkg("pkg1", "1.0-2") +p2 = pmpkg("pkg2", "1.0-2") + +for p in p1, p2: + self.addpkg(p) + +self.args = "-U %s" % " ".join([p.filename() for p in p1, p2]) +#self.args = "-Qi %s" % " ".join([p.name for p in lp1, lp2]) + +self.addrule("PACMAN_RETCODE=0") +self.addrule("PKG_REASON=pkg1|0") +self.addrule("PKG_REASON=pkg2|1") diff --git a/pactest/tests/upgrade040.py b/pactest/tests/upgrade040.py new file mode 100644 index 00000000..6946882e --- /dev/null +++ b/pactest/tests/upgrade040.py @@ -0,0 +1,25 @@ +self.description = "file relocation 1" + +lp1 = pmpkg("dummy") +lp1.files = ["bin/dummy", + "usr/share/file"] + +lp2 = pmpkg("foobar") +lp2.files = ["bin/foobar"] + +for p in lp1, lp2: + self.addpkg2db("local", p) + +p1 = pmpkg("dummy") +p1.files = ["bin/dummy"] + +p2 = pmpkg("foobar") +p2.files = ["bin/foobar", + "usr/share/file"] + +for p in p1, p2: + self.addpkg(p) + +self.args = "-U %s" % " ".join([p.filename() for p in p1, p2]) + +self.addrule("PACMAN_RETCODE=0") diff --git a/pactest/util.py b/pactest/util.py new file mode 100755 index 00000000..d7bb8c8e --- /dev/null +++ b/pactest/util.py @@ -0,0 +1,259 @@ +#! /usr/bin/python +# +# Copyright (c) 2006 by Aurelien Foret <orelien@chez.com> +# +# 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. + + +import sys +import os +import md5 +import stat + + +# ALPM +PM_ROOT = "/" +PM_DBPATH = "var/lib/pacman" +PM_CACHEDIR = "var/cache/pacman/pkg" +PM_LOCK = "/tmp/pacman.lck" +PM_EXT_PKG = ".pkg.tar.gz" +PM_EXT_DB = ".db.tar.gz" +PM_PACNEW = ".pacnew" +PM_PACORIG = ".pacorig" +PM_PACSAVE = ".pacsave" + +# Pacman +PACCONF = "etc/pacman.conf" + +# Pactest +TMPDIR = "tmp" +SYNCREPO = "var/pub" +LOGFILE = "var/log/pactest.log" + + +verbose = 0 +debug = 1 + + +def err(msg): + print "error: " + msg + sys.exit(1) + +def vprint(msg): + if verbose: + print msg + +def dbg(msg): + if debug: + print msg + + +# +# Methods to generate files +# + +def getfilename(name): + """ + """ + filename = "" + link = "" + if not name.find(" -> ") == -1: + filename, link = name.split(" -> ") + elif name[-1] == "*": + filename = name.rstrip("*") + else: + filename = name + return filename + +def mkfile(name, data = ""): + """ + """ + + isaltered = 0 + isdir = 0 + islink = 0 + link = "" + filename = "" + + if not name.find(" -> ") == -1: + islink = 1 + filename, link = name.split(" -> ") + elif name[-1] == "*": + isaltered = 1 + filename = name.rstrip("*") + else: + filename = name + if name[-1] == "/": + isdir = 1 + + if isdir: + path = filename + else: + path = os.path.dirname(filename) + try: + if path and not os.path.isdir(path): + os.makedirs(path, 0755) + except: + error("mkfile: could not create directory hierarchy '%s'" % path) + + if isdir: + return + if islink: + curdir = os.getcwd() + os.chdir(path) + os.symlink(link, os.path.basename(filename)) + os.chdir(curdir) + else: + fd = file(filename, "w") + if data: + fd.write(data) + if data[-1] != "\n": + fd.write("\n") + fd.close() + +def mkdescfile(filename, pkg): + """ + """ + + data = [] + + # desc + #data.append("pkgname = %s" % pkg.name) + #data.append("pkgver = %s" % pkg.version) + if pkg.desc: + data.append("pkgdesc = %s" % pkg.desc) + if pkg.url: + data.append("url = %s" % pkg.url) + if pkg.builddate: + data.append("builddate = %s" % pkg.builddate) + if pkg.packager: + data.append("packager = %s" % pkg.packager) + if pkg.size: + data.append("size = %s" % pkg.size) + if pkg.arch: + data.append("arch = %s" % pkg.arch) + for i in pkg.groups: + data.append("group = %s" % i) + for i in pkg.license: + data.append("license = %s" % i) + if pkg.md5sum: + data.append("md5sum = %s" % pkg.md5sum) + + # depends + for i in pkg.replaces: + data.append("replaces = %s" % i) + for i in pkg.depends: + data.append("depend = %s" % i) + for i in pkg.conflicts: + data.append("conflict = %s" % i) + for i in pkg.provides: + data.append("provides = %s" % i) + for i in pkg.backup: + data.append("backup = %s" % i) + if pkg.force: + data.append("force = 1") + + mkfile(filename, "\n".join(data)) + +def mkinstallfile(filename, install): + """ + """ + data = [] + for key, value in install.iteritems(): + if value: + data.append("%s() {\n%s\n}" % (key, value)) + + mkfile(filename, "\n".join(data)) + +def mkcfgfile(filename, root, option, db): + """ + """ + # Options + data = ["[options]"] + for key, value in option.iteritems(): + data.extend(["%s = %s" % (key, j) for j in value]) + + # Repositories + data.extend(["[%s]\n" \ + "server = file://%s\n" \ + % (value.treename, os.path.join(root, SYNCREPO, value.treename)) \ + for key, value in db.iteritems() if not key == "local"]) + + mkfile(os.path.join(root, filename), "\n".join(data)) + + +# +# MD5 helpers +# + +def getmd5sum(filename): + """ + """ + fd = open(filename, "rb") + checksum = md5.new() + while 1: + block = fd.read(1048576) + if not block: + break + checksum.update(block) + fd.close() + digest = checksum.digest() + return "%02x"*len(digest) % tuple(map(ord, digest)) + +def mkmd5sum(data): + """ + """ + checksum = md5.new() + checksum.update("%s\n" % data) + digest = checksum.digest() + return "%02x"*len(digest) % tuple(map(ord, digest)) + + +# +# Mtime helpers +# + +def getmtime(filename): + """ + """ + st = os.stat(filename) + return st[stat.ST_ATIME], st[stat.ST_MTIME], st[stat.ST_CTIME] + +def diffmtime(mt1, mt2): + """ORE: TBD + """ + return not mt1 == mt2 + + +# +# Miscellaneous +# + +def grep(filename, pattern): + found = 0 + fd = file(filename, "r") + while 1 and not found: + line = fd.readline() + if not line: + break + if line.find(pattern) != -1: + found = 1 + fd.close() + return found + + +if __name__ == "__main__": + pass |