From dcce2748108c2c9eb852fa58ff8d945cca9a04f3 Mon Sep 17 00:00:00 2001 From: Nils Wentzell Date: Thu, 22 Mar 2018 15:33:59 +0100 Subject: [PATCH 001/272] Initial commit --- LICENSE | 674 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ README.md | 2 + 2 files changed, 676 insertions(+) create mode 100644 LICENSE create mode 100644 README.md diff --git a/LICENSE b/LICENSE new file mode 100644 index 00000000..94a9ed02 --- /dev/null +++ b/LICENSE @@ -0,0 +1,674 @@ + GNU GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The GNU General Public License is a free, copyleft license for +software and other kinds of works. + + The licenses for most software and other practical works are designed +to take away your freedom to share and change the works. By contrast, +the GNU General Public License is intended to guarantee your freedom to +share and change all versions of a program--to make sure it remains free +software for all its users. We, the Free Software Foundation, use the +GNU General Public License for most of our software; it applies also to +any other work released this way by its authors. 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 +them 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 prevent others from denying you +these rights or asking you to surrender the rights. Therefore, you have +certain responsibilities if you distribute copies of the software, or if +you modify it: responsibilities to respect the freedom of others. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must pass on to the recipients the same +freedoms that you received. 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. + + Developers that use the GNU GPL protect your rights with two steps: +(1) assert copyright on the software, and (2) offer you this License +giving you legal permission to copy, distribute and/or modify it. + + For the developers' and authors' protection, the GPL clearly explains +that there is no warranty for this free software. For both users' and +authors' sake, the GPL requires that modified versions be marked as +changed, so that their problems will not be attributed erroneously to +authors of previous versions. + + Some devices are designed to deny users access to install or run +modified versions of the software inside them, although the manufacturer +can do so. This is fundamentally incompatible with the aim of +protecting users' freedom to change the software. The systematic +pattern of such abuse occurs in the area of products for individuals to +use, which is precisely where it is most unacceptable. Therefore, we +have designed this version of the GPL to prohibit the practice for those +products. If such problems arise substantially in other domains, we +stand ready to extend this provision to those domains in future versions +of the GPL, as needed to protect the freedom of users. + + Finally, every program is threatened constantly by software patents. +States should not allow patents to restrict development and use of +software on general-purpose computers, but in those that do, we wish to +avoid the special danger that patents applied to a free program could +make it effectively proprietary. To prevent this, the GPL assures that +patents cannot be used to render the program non-free. + + The precise terms and conditions for copying, distribution and +modification follow. + + TERMS AND CONDITIONS + + 0. Definitions. + + "This License" refers to version 3 of the GNU General Public License. + + "Copyright" also means copyright-like laws that apply to other kinds of +works, such as semiconductor masks. + + "The Program" refers to any copyrightable work licensed under this +License. Each licensee is addressed as "you". "Licensees" and +"recipients" may be individuals or organizations. + + To "modify" a work means to copy from or adapt all or part of the work +in a fashion requiring copyright permission, other than the making of an +exact copy. The resulting work is called a "modified version" of the +earlier work or a work "based on" the earlier work. + + A "covered work" means either the unmodified Program or a work based +on the Program. + + To "propagate" a work means to do anything with it that, without +permission, would make you directly or secondarily liable for +infringement under applicable copyright law, except executing it on a +computer or modifying a private copy. Propagation includes copying, +distribution (with or without modification), making available to the +public, and in some countries other activities as well. + + To "convey" a work means any kind of propagation that enables other +parties to make or receive copies. Mere interaction with a user through +a computer network, with no transfer of a copy, is not conveying. + + An interactive user interface displays "Appropriate Legal Notices" +to the extent that it includes a convenient and prominently visible +feature that (1) displays an appropriate copyright notice, and (2) +tells the user that there is no warranty for the work (except to the +extent that warranties are provided), that licensees may convey the +work under this License, and how to view a copy of this License. If +the interface presents a list of user commands or options, such as a +menu, a prominent item in the list meets this criterion. + + 1. Source Code. + + The "source code" for a work means the preferred form of the work +for making modifications to it. "Object code" means any non-source +form of a work. + + A "Standard Interface" means an interface that either is an official +standard defined by a recognized standards body, or, in the case of +interfaces specified for a particular programming language, one that +is widely used among developers working in that language. + + The "System Libraries" of an executable work include anything, other +than the work as a whole, that (a) is included in the normal form of +packaging a Major Component, but which is not part of that Major +Component, and (b) serves only to enable use of the work with that +Major Component, or to implement a Standard Interface for which an +implementation is available to the public in source code form. A +"Major Component", in this context, means a major essential component +(kernel, window system, and so on) of the specific operating system +(if any) on which the executable work runs, or a compiler used to +produce the work, or an object code interpreter used to run it. + + The "Corresponding Source" for a work in object code form means all +the source code needed to generate, install, and (for an executable +work) run the object code and to modify the work, including scripts to +control those activities. However, it does not include the work's +System Libraries, or general-purpose tools or generally available free +programs which are used unmodified in performing those activities but +which are not part of the work. For example, Corresponding Source +includes interface definition files associated with source files for +the work, and the source code for shared libraries and dynamically +linked subprograms that the work is specifically designed to require, +such as by intimate data communication or control flow between those +subprograms and other parts of the work. + + The Corresponding Source need not include anything that users +can regenerate automatically from other parts of the Corresponding +Source. + + The Corresponding Source for a work in source code form is that +same work. + + 2. Basic Permissions. + + All rights granted under this License are granted for the term of +copyright on the Program, and are irrevocable provided the stated +conditions are met. This License explicitly affirms your unlimited +permission to run the unmodified Program. The output from running a +covered work is covered by this License only if the output, given its +content, constitutes a covered work. This License acknowledges your +rights of fair use or other equivalent, as provided by copyright law. + + You may make, run and propagate covered works that you do not +convey, without conditions so long as your license otherwise remains +in force. You may convey covered works to others for the sole purpose +of having them make modifications exclusively for you, or provide you +with facilities for running those works, provided that you comply with +the terms of this License in conveying all material for which you do +not control copyright. Those thus making or running the covered works +for you must do so exclusively on your behalf, under your direction +and control, on terms that prohibit them from making any copies of +your copyrighted material outside their relationship with you. + + Conveying under any other circumstances is permitted solely under +the conditions stated below. Sublicensing is not allowed; section 10 +makes it unnecessary. + + 3. Protecting Users' Legal Rights From Anti-Circumvention Law. + + No covered work shall be deemed part of an effective technological +measure under any applicable law fulfilling obligations under article +11 of the WIPO copyright treaty adopted on 20 December 1996, or +similar laws prohibiting or restricting circumvention of such +measures. + + When you convey a covered work, you waive any legal power to forbid +circumvention of technological measures to the extent such circumvention +is effected by exercising rights under this License with respect to +the covered work, and you disclaim any intention to limit operation or +modification of the work as a means of enforcing, against the work's +users, your or third parties' legal rights to forbid circumvention of +technological measures. + + 4. Conveying Verbatim Copies. + + You may convey 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; +keep intact all notices stating that this License and any +non-permissive terms added in accord with section 7 apply to the code; +keep intact all notices of the absence of any warranty; and give all +recipients a copy of this License along with the Program. + + You may charge any price or no price for each copy that you convey, +and you may offer support or warranty protection for a fee. + + 5. Conveying Modified Source Versions. + + You may convey a work based on the Program, or the modifications to +produce it from the Program, in the form of source code under the +terms of section 4, provided that you also meet all of these conditions: + + a) The work must carry prominent notices stating that you modified + it, and giving a relevant date. + + b) The work must carry prominent notices stating that it is + released under this License and any conditions added under section + 7. This requirement modifies the requirement in section 4 to + "keep intact all notices". + + c) You must license the entire work, as a whole, under this + License to anyone who comes into possession of a copy. This + License will therefore apply, along with any applicable section 7 + additional terms, to the whole of the work, and all its parts, + regardless of how they are packaged. This License gives no + permission to license the work in any other way, but it does not + invalidate such permission if you have separately received it. + + d) If the work has interactive user interfaces, each must display + Appropriate Legal Notices; however, if the Program has interactive + interfaces that do not display Appropriate Legal Notices, your + work need not make them do so. + + A compilation of a covered work with other separate and independent +works, which are not by their nature extensions of the covered work, +and which are not combined with it such as to form a larger program, +in or on a volume of a storage or distribution medium, is called an +"aggregate" if the compilation and its resulting copyright are not +used to limit the access or legal rights of the compilation's users +beyond what the individual works permit. Inclusion of a covered work +in an aggregate does not cause this License to apply to the other +parts of the aggregate. + + 6. Conveying Non-Source Forms. + + You may convey a covered work in object code form under the terms +of sections 4 and 5, provided that you also convey the +machine-readable Corresponding Source under the terms of this License, +in one of these ways: + + a) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by the + Corresponding Source fixed on a durable physical medium + customarily used for software interchange. + + b) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by a + written offer, valid for at least three years and valid for as + long as you offer spare parts or customer support for that product + model, to give anyone who possesses the object code either (1) a + copy of the Corresponding Source for all the software in the + product that is covered by this License, on a durable physical + medium customarily used for software interchange, for a price no + more than your reasonable cost of physically performing this + conveying of source, or (2) access to copy the + Corresponding Source from a network server at no charge. + + c) Convey individual copies of the object code with a copy of the + written offer to provide the Corresponding Source. This + alternative is allowed only occasionally and noncommercially, and + only if you received the object code with such an offer, in accord + with subsection 6b. + + d) Convey the object code by offering access from a designated + place (gratis or for a charge), and offer equivalent access to the + Corresponding Source in the same way through the same place at no + further charge. You need not require recipients to copy the + Corresponding Source along with the object code. If the place to + copy the object code is a network server, the Corresponding Source + may be on a different server (operated by you or a third party) + that supports equivalent copying facilities, provided you maintain + clear directions next to the object code saying where to find the + Corresponding Source. Regardless of what server hosts the + Corresponding Source, you remain obligated to ensure that it is + available for as long as needed to satisfy these requirements. + + e) Convey the object code using peer-to-peer transmission, provided + you inform other peers where the object code and Corresponding + Source of the work are being offered to the general public at no + charge under subsection 6d. + + A separable portion of the object code, whose source code is excluded +from the Corresponding Source as a System Library, need not be +included in conveying the object code work. + + A "User Product" is either (1) a "consumer product", which means any +tangible personal property which is normally used for personal, family, +or household purposes, or (2) anything designed or sold for incorporation +into a dwelling. In determining whether a product is a consumer product, +doubtful cases shall be resolved in favor of coverage. For a particular +product received by a particular user, "normally used" refers to a +typical or common use of that class of product, regardless of the status +of the particular user or of the way in which the particular user +actually uses, or expects or is expected to use, the product. A product +is a consumer product regardless of whether the product has substantial +commercial, industrial or non-consumer uses, unless such uses represent +the only significant mode of use of the product. + + "Installation Information" for a User Product means any methods, +procedures, authorization keys, or other information required to install +and execute modified versions of a covered work in that User Product from +a modified version of its Corresponding Source. The information must +suffice to ensure that the continued functioning of the modified object +code is in no case prevented or interfered with solely because +modification has been made. + + If you convey an object code work under this section in, or with, or +specifically for use in, a User Product, and the conveying occurs as +part of a transaction in which the right of possession and use of the +User Product is transferred to the recipient in perpetuity or for a +fixed term (regardless of how the transaction is characterized), the +Corresponding Source conveyed under this section must be accompanied +by the Installation Information. But this requirement does not apply +if neither you nor any third party retains the ability to install +modified object code on the User Product (for example, the work has +been installed in ROM). + + The requirement to provide Installation Information does not include a +requirement to continue to provide support service, warranty, or updates +for a work that has been modified or installed by the recipient, or for +the User Product in which it has been modified or installed. Access to a +network may be denied when the modification itself materially and +adversely affects the operation of the network or violates the rules and +protocols for communication across the network. + + Corresponding Source conveyed, and Installation Information provided, +in accord with this section must be in a format that is publicly +documented (and with an implementation available to the public in +source code form), and must require no special password or key for +unpacking, reading or copying. + + 7. Additional Terms. + + "Additional permissions" are terms that supplement the terms of this +License by making exceptions from one or more of its conditions. +Additional permissions that are applicable to the entire Program shall +be treated as though they were included in this License, to the extent +that they are valid under applicable law. If additional permissions +apply only to part of the Program, that part may be used separately +under those permissions, but the entire Program remains governed by +this License without regard to the additional permissions. + + When you convey a copy of a covered work, you may at your option +remove any additional permissions from that copy, or from any part of +it. (Additional permissions may be written to require their own +removal in certain cases when you modify the work.) You may place +additional permissions on material, added by you to a covered work, +for which you have or can give appropriate copyright permission. + + Notwithstanding any other provision of this License, for material you +add to a covered work, you may (if authorized by the copyright holders of +that material) supplement the terms of this License with terms: + + a) Disclaiming warranty or limiting liability differently from the + terms of sections 15 and 16 of this License; or + + b) Requiring preservation of specified reasonable legal notices or + author attributions in that material or in the Appropriate Legal + Notices displayed by works containing it; or + + c) Prohibiting misrepresentation of the origin of that material, or + requiring that modified versions of such material be marked in + reasonable ways as different from the original version; or + + d) Limiting the use for publicity purposes of names of licensors or + authors of the material; or + + e) Declining to grant rights under trademark law for use of some + trade names, trademarks, or service marks; or + + f) Requiring indemnification of licensors and authors of that + material by anyone who conveys the material (or modified versions of + it) with contractual assumptions of liability to the recipient, for + any liability that these contractual assumptions directly impose on + those licensors and authors. + + All other non-permissive additional terms are considered "further +restrictions" within the meaning of section 10. If the Program as you +received it, or any part of it, contains a notice stating that it is +governed by this License along with a term that is a further +restriction, you may remove that term. If a license document contains +a further restriction but permits relicensing or conveying under this +License, you may add to a covered work material governed by the terms +of that license document, provided that the further restriction does +not survive such relicensing or conveying. + + If you add terms to a covered work in accord with this section, you +must place, in the relevant source files, a statement of the +additional terms that apply to those files, or a notice indicating +where to find the applicable terms. + + Additional terms, permissive or non-permissive, may be stated in the +form of a separately written license, or stated as exceptions; +the above requirements apply either way. + + 8. Termination. + + You may not propagate or modify a covered work except as expressly +provided under this License. Any attempt otherwise to propagate or +modify it is void, and will automatically terminate your rights under +this License (including any patent licenses granted under the third +paragraph of section 11). + + However, if you cease all violation of this License, then your +license from a particular copyright holder is reinstated (a) +provisionally, unless and until the copyright holder explicitly and +finally terminates your license, and (b) permanently, if the copyright +holder fails to notify you of the violation by some reasonable means +prior to 60 days after the cessation. + + Moreover, your license from a particular copyright holder is +reinstated permanently if the copyright holder notifies you of the +violation by some reasonable means, this is the first time you have +received notice of violation of this License (for any work) from that +copyright holder, and you cure the violation prior to 30 days after +your receipt of the notice. + + Termination of your rights under this section does not terminate the +licenses of parties who have received copies or rights from you under +this License. If your rights have been terminated and not permanently +reinstated, you do not qualify to receive new licenses for the same +material under section 10. + + 9. Acceptance Not Required for Having Copies. + + You are not required to accept this License in order to receive or +run a copy of the Program. Ancillary propagation of a covered work +occurring solely as a consequence of using peer-to-peer transmission +to receive a copy likewise does not require acceptance. However, +nothing other than this License grants you permission to propagate or +modify any covered work. These actions infringe copyright if you do +not accept this License. Therefore, by modifying or propagating a +covered work, you indicate your acceptance of this License to do so. + + 10. Automatic Licensing of Downstream Recipients. + + Each time you convey a covered work, the recipient automatically +receives a license from the original licensors, to run, modify and +propagate that work, subject to this License. You are not responsible +for enforcing compliance by third parties with this License. + + An "entity transaction" is a transaction transferring control of an +organization, or substantially all assets of one, or subdividing an +organization, or merging organizations. If propagation of a covered +work results from an entity transaction, each party to that +transaction who receives a copy of the work also receives whatever +licenses to the work the party's predecessor in interest had or could +give under the previous paragraph, plus a right to possession of the +Corresponding Source of the work from the predecessor in interest, if +the predecessor has it or can get it with reasonable efforts. + + You may not impose any further restrictions on the exercise of the +rights granted or affirmed under this License. For example, you may +not impose a license fee, royalty, or other charge for exercise of +rights granted under this License, and you may not initiate litigation +(including a cross-claim or counterclaim in a lawsuit) alleging that +any patent claim is infringed by making, using, selling, offering for +sale, or importing the Program or any portion of it. + + 11. Patents. + + A "contributor" is a copyright holder who authorizes use under this +License of the Program or a work on which the Program is based. The +work thus licensed is called the contributor's "contributor version". + + A contributor's "essential patent claims" are all patent claims +owned or controlled by the contributor, whether already acquired or +hereafter acquired, that would be infringed by some manner, permitted +by this License, of making, using, or selling its contributor version, +but do not include claims that would be infringed only as a +consequence of further modification of the contributor version. For +purposes of this definition, "control" includes the right to grant +patent sublicenses in a manner consistent with the requirements of +this License. + + Each contributor grants you a non-exclusive, worldwide, royalty-free +patent license under the contributor's essential patent claims, to +make, use, sell, offer for sale, import and otherwise run, modify and +propagate the contents of its contributor version. + + In the following three paragraphs, a "patent license" is any express +agreement or commitment, however denominated, not to enforce a patent +(such as an express permission to practice a patent or covenant not to +sue for patent infringement). To "grant" such a patent license to a +party means to make such an agreement or commitment not to enforce a +patent against the party. + + If you convey a covered work, knowingly relying on a patent license, +and the Corresponding Source of the work is not available for anyone +to copy, free of charge and under the terms of this License, through a +publicly available network server or other readily accessible means, +then you must either (1) cause the Corresponding Source to be so +available, or (2) arrange to deprive yourself of the benefit of the +patent license for this particular work, or (3) arrange, in a manner +consistent with the requirements of this License, to extend the patent +license to downstream recipients. "Knowingly relying" means you have +actual knowledge that, but for the patent license, your conveying the +covered work in a country, or your recipient's use of the covered work +in a country, would infringe one or more identifiable patents in that +country that you have reason to believe are valid. + + If, pursuant to or in connection with a single transaction or +arrangement, you convey, or propagate by procuring conveyance of, a +covered work, and grant a patent license to some of the parties +receiving the covered work authorizing them to use, propagate, modify +or convey a specific copy of the covered work, then the patent license +you grant is automatically extended to all recipients of the covered +work and works based on it. + + A patent license is "discriminatory" if it does not include within +the scope of its coverage, prohibits the exercise of, or is +conditioned on the non-exercise of one or more of the rights that are +specifically granted under this License. You may not convey a covered +work if you are a party to an arrangement with a third party that is +in the business of distributing software, under which you make payment +to the third party based on the extent of your activity of conveying +the work, and under which the third party grants, to any of the +parties who would receive the covered work from you, a discriminatory +patent license (a) in connection with copies of the covered work +conveyed by you (or copies made from those copies), or (b) primarily +for and in connection with specific products or compilations that +contain the covered work, unless you entered into that arrangement, +or that patent license was granted, prior to 28 March 2007. + + Nothing in this License shall be construed as excluding or limiting +any implied license or other defenses to infringement that may +otherwise be available to you under applicable patent law. + + 12. No Surrender of Others' Freedom. + + If 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 convey a +covered work so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you may +not convey it at all. For example, if you agree to terms that obligate you +to collect a royalty for further conveying from those to whom you convey +the Program, the only way you could satisfy both those terms and this +License would be to refrain entirely from conveying the Program. + + 13. Use with the GNU Affero General Public License. + + Notwithstanding any other provision of this License, you have +permission to link or combine any covered work with a work licensed +under version 3 of the GNU Affero General Public License into a single +combined work, and to convey the resulting work. The terms of this +License will continue to apply to the part which is the covered work, +but the special requirements of the GNU Affero General Public License, +section 13, concerning interaction through a network will apply to the +combination as such. + + 14. Revised Versions of this License. + + The Free Software Foundation may publish revised and/or new versions of +the GNU 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 that a certain numbered version of the GNU General +Public License "or any later version" applies to it, you have the +option of following the terms and conditions either of that numbered +version or of any later version published by the Free Software +Foundation. If the Program does not specify a version number of the +GNU General Public License, you may choose any version ever published +by the Free Software Foundation. + + If the Program specifies that a proxy can decide which future +versions of the GNU General Public License can be used, that proxy's +public statement of acceptance of a version permanently authorizes you +to choose that version for the Program. + + Later license versions may give you additional or different +permissions. However, no additional obligations are imposed on any +author or copyright holder as a result of your choosing to follow a +later version. + + 15. Disclaimer of Warranty. + + 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. + + 16. Limitation of Liability. + + IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS +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. + + 17. Interpretation of Sections 15 and 16. + + If the disclaimer of warranty and limitation of liability provided +above cannot be given local legal effect according to their terms, +reviewing courts shall apply local law that most closely approximates +an absolute waiver of all civil liability in connection with the +Program, unless a warranty or assumption of liability accompanies a +copy of the Program in return for a fee. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +state the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 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, see . + +Also add information on how to contact you by electronic and paper mail. + + If the program does terminal interaction, make it output a short +notice like this when it starts in an interactive mode: + + Copyright (C) + This program 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, your program's commands +might be different; for a GUI interface, you would use an "about box". + + You should also get your employer (if you work as a programmer) or school, +if any, to sign a "copyright disclaimer" for the program, if necessary. +For more information on this, and how to apply and follow the GNU GPL, see +. + + The GNU 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 Lesser General +Public License instead of this License. But first, please read +. diff --git a/README.md b/README.md new file mode 100644 index 00000000..57a6a1e4 --- /dev/null +++ b/README.md @@ -0,0 +1,2 @@ +# app4triqs +An example application using cpp2py and triqs. From 2b76c51f1271e5f5c798b17d55bf5c99eefdd37f Mon Sep 17 00:00:00 2001 From: Nils Wentzell Date: Thu, 22 Mar 2018 18:11:39 +0100 Subject: [PATCH 002/272] First draft of the triqs application skeleton --- .clang-format | 45 +++++++++++ .clang-tidy | 1 + .travis.yml | 51 ++++++++++++ CMakeLists.txt | 60 ++++++++++++++ Dockerfile | 10 +++ Jenkinsfile | 113 +++++++++++++++++++++++++++ c++/app4triqs/CMakeLists.txt | 19 +++++ c++/app4triqs/toto.cpp | 37 +++++++++ c++/app4triqs/toto.hpp | 68 ++++++++++++++++ doc/CMakeLists.txt | 58 ++++++++++++++ doc/_static/logo_erc.jpg | Bin 0 -> 195026 bytes doc/_templates/sideb.html | 7 ++ doc/about.rst | 3 + doc/conf.py.in | 32 ++++++++ doc/contents.rst | 12 +++ doc/documentation.rst | 12 +++ doc/index.rst | 11 +++ doc/install.rst | 62 +++++++++++++++ doc/issues.rst | 23 ++++++ python/app4triqs/CMakeLists.txt | 21 +++++ python/app4triqs/__init__.py | 29 +++++++ python/app4triqs/toto_module_desc.py | 51 ++++++++++++ python/app4triqs/version.py.in | 31 ++++++++ share/CMakeLists.txt | 17 ++++ share/app4triqs.modulefile.in | 39 +++++++++ share/app4triqsvars.sh.in | 13 +++ test/CMakeLists.txt | 4 + test/c++/CMakeLists.txt | 11 +++ test/c++/toto.cpp | 32 ++++++++ test/python/CMakeLists.txt | 12 +++ test/python/Toto.py | 42 ++++++++++ test/python/chain.py | 17 ++++ 32 files changed, 943 insertions(+) create mode 100644 .clang-format create mode 100644 .clang-tidy create mode 100644 .travis.yml create mode 100644 CMakeLists.txt create mode 100644 Dockerfile create mode 100644 Jenkinsfile create mode 100644 c++/app4triqs/CMakeLists.txt create mode 100644 c++/app4triqs/toto.cpp create mode 100644 c++/app4triqs/toto.hpp create mode 100644 doc/CMakeLists.txt create mode 100644 doc/_static/logo_erc.jpg create mode 100644 doc/_templates/sideb.html create mode 100644 doc/about.rst create mode 100644 doc/conf.py.in create mode 100644 doc/contents.rst create mode 100644 doc/documentation.rst create mode 100644 doc/index.rst create mode 100644 doc/install.rst create mode 100644 doc/issues.rst create mode 100644 python/app4triqs/CMakeLists.txt create mode 100644 python/app4triqs/__init__.py create mode 100644 python/app4triqs/toto_module_desc.py create mode 100644 python/app4triqs/version.py.in create mode 100644 share/CMakeLists.txt create mode 100644 share/app4triqs.modulefile.in create mode 100644 share/app4triqsvars.sh.in create mode 100644 test/CMakeLists.txt create mode 100644 test/c++/CMakeLists.txt create mode 100644 test/c++/toto.cpp create mode 100644 test/python/CMakeLists.txt create mode 100644 test/python/Toto.py create mode 100644 test/python/chain.py diff --git a/.clang-format b/.clang-format new file mode 100644 index 00000000..10b38401 --- /dev/null +++ b/.clang-format @@ -0,0 +1,45 @@ +BasedOnStyle: LLVM + +AccessModifierOffset: 0 +AlignAfterOpenBracket: Align +AlignConsecutiveAssignments: true +AlignConsecutiveDeclarations: false +AlignEscapedNewlinesLeft: false +AlignOperands: false +AlignTrailingComments: true +AllowAllParametersOfDeclarationOnNextLine: false +AllowShortBlocksOnASingleLine: true +AllowShortCaseLabelsOnASingleLine: true +AllowShortFunctionsOnASingleLine: All +AllowShortIfStatementsOnASingleLine: true +AllowShortLoopsOnASingleLine: true +AlwaysBreakBeforeMultilineStrings: true +AlwaysBreakTemplateDeclarations: false +BinPackArguments: true +BinPackParameters: true +BreakBeforeBinaryOperators: NonAssignment +BreakBeforeBraces: Attach +BreakBeforeTernaryOperators: false +BreakConstructorInitializersBeforeComma: false +BreakStringLiterals: false +ColumnLimit: 150 +ConstructorInitializerAllOnOneLineOrOnePerLine: true +ConstructorInitializerIndentWidth: 3 +ContinuationIndentWidth: 3 +Cpp11BracedListStyle: true +DerivePointerBinding : false +IndentCaseLabels: true +IndentWidth: 2 +Language: Cpp +MaxEmptyLinesToKeep: 1 +NamespaceIndentation : All +PointerAlignment: Right +ReflowComments: false +SortIncludes: false +SpaceAfterControlStatementKeyword: true +SpaceBeforeAssignmentOperators: true +SpaceInEmptyParentheses: false +SpacesInParentheses: false +Standard: Cpp11 +TabWidth: 2 +UseTab: Never diff --git a/.clang-tidy b/.clang-tidy new file mode 100644 index 00000000..8103eae9 --- /dev/null +++ b/.clang-tidy @@ -0,0 +1 @@ +Checks: '-*,modernize-*,cppcoreguidelines-*' diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 00000000..7ebf8f58 --- /dev/null +++ b/.travis.yml @@ -0,0 +1,51 @@ + +language: cpp +sudo: required +dist: trusty + +compiler: + - gcc + # - clang + +before_install: + - sudo add-apt-repository 'deb http://apt.llvm.org/trusty/ llvm-toolchain-trusty-5.0 main' -y + - wget -O - https://apt.llvm.org/llvm-snapshot.gpg.key|sudo apt-key add - + - sudo add-apt-repository ppa:ubuntu-toolchain-r/test -y + - sudo apt-get update + - sudo apt-get install -y --allow-unauthenticated g++-7 clang-5.0 + - export LIBRARY_PATH=/usr/lib/llvm-5.0/lib:$LIBRARY_PATH + - sudo update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-7 60 --slave /usr/bin/g++ g++ /usr/bin/g++-7 + - sudo update-alternatives --install /usr/bin/clang clang /usr/bin/clang-5.0 60 --slave /usr/bin/clang++ clang++ /usr/bin/clang++-5.0 + - sudo apt-get install -y --allow-unauthenticated libboost-all-dev cmake git libgfortran3 gfortran openmpi-bin openmpi-common openmpi-doc libopenmpi-dev libblas-dev liblapack-dev libfftw3-dev libgmp-dev hdf5-tools libhdf5-serial-dev python-h5py python-dev python-numpy python-scipy python-jinja2 python-virtualenv python-matplotlib python-tornado python-zmq python-mpi4py python-mako clang-format-5.0 libclang-5.0-dev python-clang-5.0 python-sphinx libjs-mathjax valgrind libnfft3-dev + +install: true + +script: + # ===== Set up Cpp2Py + - git clone https://github.com/triqs/cpp2py + - mkdir cpp2py/build && cd cpp2py/build + - git checkout master + - cmake .. -DCMAKE_CXX_COMPILER=/usr/bin/${CXX} -DPYTHON_INTERPRETER=/usr/bin/python -DCMAKE_INSTALL_PREFIX=$TRAVIS_BUILD_DIR/root_install + - make -j8 install + - cd $TRAVIS_BUILD_DIR + - source root_install/share/cpp2pyvars.sh + # ===== Set up TRIQS + - git clone https://github.com/TRIQS/triqs --branch unstable + - mkdir triqs/build && cd triqs/build + - git checkout unstable + - cmake .. -DCMAKE_CXX_COMPILER=/usr/bin/${CXX} -DBuild_Tests=OFF -DCMAKE_INSTALL_PREFIX=$TRAVIS_BUILD_DIR/root_install -DCMAKE_BUILD_TYPE=Debug + - make -j8 install + - cd $TRAVIS_BUILD_DIR + - source root_install/share/triqsvars.sh + # ===== Set up CTINT and Test using fsanitize=address + - mkdir build && cd build + - cmake .. -DCMAKE_BUILD_TYPE=Debug -DCMAKE_CXX_COMPILER=/usr/bin/${CXX} -DGTAU_IS_COMPLEX=ON -DINTERACTION_IS_COMPLEX=ON -DCMAKE_CXX_FLAGS='-fsanitize=address -fno-omit-frame-pointer -fuse-ld=gold -Wno-register -Wno-macro-redefined' + - make -j8 + - export ASAN_SYMBOLIZER_PATH=/usr/lib/llvm-5.0/bin/llvm-symbolizer + - export ASAN_OPTIONS=symbolize=1:detect_leaks=0 + - export CTEST_OUTPUT_ON_FAILURE=1 + - cd test/c++ && ctest + - if [ "$CXX" = g++ ]; then export LD_PRELOAD=/usr/lib/gcc/x86_64-linux-gnu/7/libasan.so; elif [ "$CXX" = clang++ ]; then export LD_PRELOAD=/usr/lib/llvm-5.0/lib/clang/5.0.1/lib/linux/libclang_rt.asan-x86_64.so; fi + - cd ../python && ctest + - cd ../../ + - unset LD_PRELOAD diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 00000000..78e5d33d --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,60 @@ +# Version number +set (APP4TRIQS_VERSION "1.5") + +# Start configuration +cmake_minimum_required(VERSION 2.8) +project(app4triqs CXX) + +# Default to Release build type +if(NOT CMAKE_BUILD_TYPE) + set(CMAKE_BUILD_TYPE Release CACHE STRING "Type of build" FORCE) +endif() +message( STATUS "-------- BUILD-TYPE: ${CMAKE_BUILD_TYPE} -------------") + +# Use shared libraries +set(BUILD_SHARED_LIBS ON) + +# Load TRIQS and Cpp2Py +find_package(TRIQS 1.5 EXACT REQUIRED) +find_package(Cpp2Py 1.5 EXACT REQUIRED) + +# We will need the FindNNFT of triqs, so we adjust CMake Module Path to find it +list(APPEND CMAKE_MODULE_PATH ${TRIQS_ROOT}/share/cmake) + +# Default Install directory to TRIQS_ROOT if not given. Checks an absolute name is given. +if(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT OR (NOT IS_ABSOLUTE ${CMAKE_INSTALL_PREFIX})) + message(STATUS " No install prefix given (or invalid). Defaulting to TRIQS_ROOT") + set(CMAKE_INSTALL_PREFIX ${TRIQS_ROOT} CACHE PATH "default install path" FORCE) +endif() +message(STATUS "-------- CMAKE_INSTALL_PREFIX: ${CMAKE_INSTALL_PREFIX} -------------") + +# Macro defined in TRIQS which picks the hash of repo. +triqs_get_git_hash_of_source_dir(APP4TRIQS_GIT_HASH) +message(STATUS "Git hash: ${APP4TRIQS_GIT_HASH}") + +# Common to all targets (c++, python, tests). +include_directories(c++) + +# Set up the rpath for compiled executable +triqs_set_rpath_for_all_targets() + +add_subdirectory(c++/app4triqs) +if(${TRIQS_WITH_PYTHON_SUPPORT}) + add_subdirectory(python/app4triqs) +endif() + +# Tests +enable_testing() +add_subdirectory(test) + +# Additional configuration files +add_subdirectory(share) + +option(Build_Documentation "Build documentation" OFF) +if(${Build_Documentation}) + if(NOT ${TRIQS_WITH_DOCUMENTATION}) + message("Error: TRIQS library has not been compiled with its documentation") + else() + add_subdirectory(doc) + endif() +endif() diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 00000000..909e37a6 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,10 @@ +# See ../triqs/packaging for other options +FROM flatironinstitute/triqs:master-ubuntu-clang + +COPY . ${SRC}/app4triqs +WORKDIR ${BUILD}/app4triqs +RUN chown build . +USER build +RUN cmake ${SRC}/app4triqs -DTRIQS_ROOT=${INSTALL} && make -j2 && make test +USER root +RUN make install diff --git a/Jenkinsfile b/Jenkinsfile new file mode 100644 index 00000000..4416c6c9 --- /dev/null +++ b/Jenkinsfile @@ -0,0 +1,113 @@ +def app4triqsBranch = env.CHANGE_TARGET ?: env.BRANCH_NAME +def app4triqsProject = '/TRIQS/app4triqs/' + app4triqsBranch.replaceAll('/', '%2F') + +properties([ + disableConcurrentBuilds(), + buildDiscarder(logRotator(numToKeepStr: '10', daysToKeepStr: '30')), + pipelineTriggers([ + upstream( + threshold: 'SUCCESS', + upstreamProjects: app4triqsProject + ) + ]) +]) + +def platforms = [:] + +def dockerPlatforms = ["ubuntu-clang", "ubuntu-gcc", "centos-gcc"] +for (int i = 0; i < dockerPlatforms.size(); i++) { + def platform = dockerPlatforms[i] + platforms[platform] = { -> stage(platform) { + timeout(time: 1, unit: 'HOURS') { + node('docker') { + checkout scm + /* construct a Dockerfile for this base */ + sh """ + ( echo "FROM flatironinstitute/app4triqs:${app4triqsBranch}-${env.STAGE_NAME}" ; sed '0,/^FROM /d' Dockerfile ) > Dockerfile.jenkins + mv -f Dockerfile.jenkins Dockerfile + """ + /* build and tag */ + def img = docker.build("flatironinstitute/app4triqs:${env.BRANCH_NAME}-${env.STAGE_NAME}") + /* but we don't need the tag so clean it up (alternatively, could refacter to run in container) */ + sh "docker rmi ${img.imageName()}" + } + } + } } +} + +def osxPlatforms = [ + ["gcc", ['CC=gcc-7', 'CXX=g++-7']], + ["clang", ['CC=/usr/local/opt/llvm/bin/clang', 'CXX=/usr/local/opt/llvm/bin/clang++', 'CXXFLAGS=-I/usr/local/opt/llvm/include', 'LDFLAGS=-L/usr/local/opt/llvm/lib']] +] +for (int i = 0; i < osxPlatforms.size(); i++) { + def platformEnv = osxPlatforms[i] + def platform = platformEnv[0] + platforms["osx-$platform"] = { -> stage("osx-$platform") { + timeout(time: 1, unit: 'HOURS') { + node('osx && triqs') { + def srcDir = pwd() + def tmpDir = pwd(tmp:true) + def buildDir = "$tmpDir/build" + def installDir = "$tmpDir/install" + + dir(installDir) { + deleteDir() + } + + copyArtifacts(projectName: app4triqsProject, selector: upstream(fallbackToLastSuccessful: true), filter: "osx-${platform}.zip") + unzip(zipFile: "osx-${platform}.zip", dir: installDir) + /* fixup zip-stripped permissions (JENKINS-13128) */ + sh "chmod +x $installDir/bin/*" + + checkout scm + + dir(buildDir) { withEnv(platformEnv[1]+[ + "PATH=$installDir/bin:/usr/local/bin:/usr/bin:/bin:/usr/sbin", + "CPATH=$installDir/include", + "LIBRARY_PATH=$installDir/lib", + "CMAKE_PREFIX_PATH=$installDir/share/cmake"]) { + deleteDir() + sh "cmake $srcDir -DTRIQS_ROOT=$installDir" + sh "make -j2" + try { + sh "make test" + } catch (exc) { + archiveArtifacts(artifacts: 'Testing/Temporary/LastTest.log') + throw exc + } + sh "make install" + } } + // zip(zipFile: "osx-${platform}.zip", archive: true, dir: installDir) + } + } + } } +} + +try { + parallel platforms +} catch (err) { + emailext( + subject: "\$PROJECT_NAME - Build # \$BUILD_NUMBER - FAILED", + body: """\$PROJECT_NAME - Build # \$BUILD_NUMBER - FAILED + +$err + +Check console output at \$BUILD_URL to view full results. + +Building \$BRANCH_NAME for \$CAUSE +\$JOB_DESCRIPTION + +Chages: +\$CHANGES + +End of build log: +\${BUILD_LOG,maxLines=60} + """, + to: 'nils.wentzell@gmail.com, dsimon@flatironinstitute.org', + recipientProviders: [ + [$class: 'DevelopersRecipientProvider'], + ], + replyTo: '$DEFAULT_REPLYTO' + ) + throw err +} diff --git a/c++/app4triqs/CMakeLists.txt b/c++/app4triqs/CMakeLists.txt new file mode 100644 index 00000000..449b23ee --- /dev/null +++ b/c++/app4triqs/CMakeLists.txt @@ -0,0 +1,19 @@ +file(GLOB_RECURSE sources RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} *.cpp) +add_library(app4triqs_c ${sources}) + +target_link_libraries(app4triqs_c PUBLIC triqs) +target_compile_options(app4triqs_c PUBLIC -std=c++17) + +target_compile_definitions(app4triqs_c PUBLIC + APP4TRIQS_GIT_HASH=${APP4TRIQS_GIT_HASH} + TRIQS_GIT_HASH=${TRIQS_GIT_HASH} + $<$:DEBUG_APP4TRIQS> + $<$:TRIQS_ARRAYS_ENFORCE_BOUNDCHECK> + #$<$:MYOPTION> # Add compile definintions for option + ) + +# Install +install(TARGETS app4triqs_c DESTINATION lib) + +# If other applications need our headers, we can install them as well +# install(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} DESTINATION include FILES_MATCHING PATTERN "*.hpp" PATTERN "*.h") diff --git a/c++/app4triqs/toto.cpp b/c++/app4triqs/toto.cpp new file mode 100644 index 00000000..6186f754 --- /dev/null +++ b/c++/app4triqs/toto.cpp @@ -0,0 +1,37 @@ +#include +#include "./toto.hpp" + +namespace app4triqs { + + toto &toto::operator+=(toto const &b) { + this->i += b.i; + return *this; + } + + toto toto::operator+(toto const &b) const { + auto res = *this; + res += b; + return res; + } + + bool toto::operator==(toto const &b) const { return (this->i == b.i); } + + void h5_write(triqs::h5::group grp, std::string subgroup_name, toto const &m) { + grp = subgroup_name.empty() ? grp : grp.create_group(subgroup_name); + h5_write(grp, "i", m.i); + h5_write_attribute(grp, "TRIQS_HDF5_data_scheme", toto::hdf5_scheme()); + } + + void h5_read(triqs::h5::group grp, std::string subgroup_name, toto &m) { + grp = subgroup_name.empty() ? grp : grp.open_group(subgroup_name); + int i; + h5_read(grp, "i", i); + m = toto(i); + } + + int chain(int i, int j) { + int n_digits_j = j > 0 ? (int)log10(j) + 1 : 1; + return i * int(pow(10, n_digits_j)) + j; + } + +} // namespace app4triqs diff --git a/c++/app4triqs/toto.hpp b/c++/app4triqs/toto.hpp new file mode 100644 index 00000000..17c4df2b --- /dev/null +++ b/c++/app4triqs/toto.hpp @@ -0,0 +1,68 @@ +#pragma once +#include +#include + +namespace app4triqs { + + /** + * A very useful and important class + * + * @note A Useful note + */ + class toto { + + int i = 0.0; + + public: + toto() = default; + + // Copy construction + toto(toto const &) = default; + toto(toto &&) = default; + + /** + * Construct from integer + * + * @param i_ a scalar + */ + toto(int i_) : i(i_) {} + + /// Copy assignment + toto &operator=(toto const &) = default; + toto &operator=(toto &&) = default; + + /// Simple accessor + int get_i() const { return i; } + + /// Arithmetic operations + toto operator+(toto const &b) const; + toto &operator+=(toto const &b); + + /// Comparison + bool operator==(toto const &b) const; + + /// HDF5 + static std::string hdf5_scheme() { return "Toto"; } + + friend void h5_write(triqs::h5::group grp, std::string subgroup_name, toto const &m); + + friend void h5_read(triqs::h5::group grp, std::string subgroup_name, toto &m); + + /// Serialization + template void serialize(Archive &ar, const unsigned int version) { ar &i; } + }; + + /** + * Chain digits of two integers + * + * Chain the decimal digits of two integers i and j, and return the result + * + * @param :math:`i` The first integer + * @param :math:`j` The second integer + * @return An integer containing the digits of both i and j + * + * @remark + */ + int chain(int i, int j); + +} // namespace app4triqs diff --git a/doc/CMakeLists.txt b/doc/CMakeLists.txt new file mode 100644 index 00000000..05eed6c9 --- /dev/null +++ b/doc/CMakeLists.txt @@ -0,0 +1,58 @@ +# Generate the conf.py +configure_file(${CMAKE_CURRENT_SOURCE_DIR}/conf.py.in ${CMAKE_CURRENT_BINARY_DIR}/conf.py @ONLY) + +# --------------------------------- +# Top Sphinx target +# --------------------------------- +# Sources +file(GLOB_RECURSE sources *.rst) + +set(sphinx_top ${CMAKE_CURRENT_BINARY_DIR}/html/contents.html) +add_custom_command(OUTPUT ${sphinx_top} DEPENDS ${sources} + COMMAND ${TRIQS_SPHINXBUILD_EXECUTABLE} -c . -j8 -b html ${CMAKE_CURRENT_BINARY_DIR} html) +add_custom_target(docs_sphinx ALL DEPENDS ${sphinx_top} ${CMAKE_CURRENT_BINARY_DIR}) + +# Application must be compiled first +add_dependencies(docs_sphinx app4triqs_c) + +# ------------------------------------------------------------------------------------------------ +# Copy the directory substructure and link all files with relevant extensions +# cp_rs is a script in cpp2py/bin, it mimics cp -rs on Linux +# and filters the relevant extension +# ------------------------------------------------------------------------------------------------ + +set(EXT_FOR_DOC "rst png txt css_t conf css js gif jpg py html bib") +execute_process(COMMAND cp_rs ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR} ${EXT_FOR_DOC}) + +# --------------------------------- +# Generate C++ doc with c++2rst +# --------------------------------- + +add_custom_target(docs_cpp2rst) + +macro(generate_docs header_file) + add_custom_command (TARGET docs_cpp2rst + COMMAND c++2rst + ${header_file} + -N app4triqs + --output_directory ${CMAKE_CURRENT_BINARY_DIR}/cpp2rst_generated + --cxxflags="-std=c++17" + -I ${CMAKE_SOURCE_DIR}/c++ + -I ${TRIQS_ROOT}/include + 2>&1 >> cpp2rst.log + ) +endmacro(generate_docs) + +generate_docs(${CMAKE_SOURCE_DIR}/c++/app4triqs/toto.hpp) + +add_dependencies(docs_sphinx docs_cpp2rst) + +# --------------------------------- +# Install +# --------------------------------- +install(DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/html/ COMPONENT documentation DESTINATION share/doc/app4triqs + FILES_MATCHING + REGEX "\\.(html|pdf|png|gif|jpg|js|xsl|css|py|txt|inv|bib)$" + PATTERN "_*" + ) + diff --git a/doc/_static/logo_erc.jpg b/doc/_static/logo_erc.jpg new file mode 100644 index 0000000000000000000000000000000000000000..b7181ee00db47c1803cc9f04c4ac74825fd62171 GIT binary patch literal 195026 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 hGmi?xgP~8HaVi`Xa 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 literal 0 HcmV?d00001 diff --git a/doc/_templates/sideb.html b/doc/_templates/sideb.html new file mode 100644 index 00000000..11622acf --- /dev/null +++ b/doc/_templates/sideb.html @@ -0,0 +1,7 @@ + diff --git a/doc/about.rst b/doc/about.rst new file mode 100644 index 00000000..8fc7917d --- /dev/null +++ b/doc/about.rst @@ -0,0 +1,3 @@ +.. _about: + +An example application using cpp2py and triqs. diff --git a/doc/conf.py.in b/doc/conf.py.in new file mode 100644 index 00000000..0bdc06f9 --- /dev/null +++ b/doc/conf.py.in @@ -0,0 +1,32 @@ +# -*- coding: utf-8 -*- +# +# TRIQS documentation build configuration file + +extensions = ['sphinx.ext.autodoc', + 'sphinx.ext.mathjax', + 'sphinx.ext.intersphinx', + 'matplotlib.sphinxext.plot_directive'] + +source_suffix = '.rst' + +project = u'APP4TRIQS - An example triqs application' +copyright = u'2018 - The TRIQS Developers' + +mathjax_path = "@TRIQS_MATHJAX_PATH@/MathJax.js?config=default" +templates_path = ['@CMAKE_SOURCE_DIR@/doc/_templates'] + +html_theme = 'triqs' +html_theme_path = ['@TRIQS_THEMES_PATH@'] +html_show_sphinx = False +html_context = {'header_title': 'app4triqs', + 'header_subtitle': 'An example application using cpp2py and triqs', + 'header_links': [['Install', 'install'], + ['Documentation', 'documentation'], + ['Issues', 'issues'], + ['About app4triqs', 'about']]} +html_static_path = ['@CMAKE_SOURCE_DIR@/doc/_static'] +html_sidebars = {'index': ['sideb.html', 'searchbox.html']} + +htmlhelp_basename = 'TRIQSIntdoc' + +intersphinx_mapping = {'python': ('http://docs.python.org/2.7', None), 'triqslibs': ('http://ipht.cea.fr/triqs', None)} diff --git a/doc/contents.rst b/doc/contents.rst new file mode 100644 index 00000000..109c3171 --- /dev/null +++ b/doc/contents.rst @@ -0,0 +1,12 @@ + +Table of contents +================= + +.. toctree:: + :maxdepth: 5 + + index + documentation + install + issues + about diff --git a/doc/documentation.rst b/doc/documentation.rst new file mode 100644 index 00000000..6bec32ee --- /dev/null +++ b/doc/documentation.rst @@ -0,0 +1,12 @@ +.. _documentation: + +Documentation +============= + +Reference manual +---------------- + +.. toctree:: + :maxdepth: 1 + + cpp2rst_generated/app4triqs/compute_Sigma_Hedin diff --git a/doc/index.rst b/doc/index.rst new file mode 100644 index 00000000..6e5c1710 --- /dev/null +++ b/doc/index.rst @@ -0,0 +1,11 @@ +.. _welcome: + +App4Triqs +========= + +An example application using cpp2py and triqs. + +This documentation is generated based on the doc/\*.rst files and +the comments in the sources and headers. + +Lets have a look at the :ref:`documentation`. diff --git a/doc/install.rst b/doc/install.rst new file mode 100644 index 00000000..4cfb66a3 --- /dev/null +++ b/doc/install.rst @@ -0,0 +1,62 @@ +.. highlight:: bash + +.. _install: + +Installation +============ + + +Prerequisite +------------------- + +#. The :ref:`TRIQS ` toolbox (see :ref:`TRIQS installation instruction `). + In the following, we will suppose that it is installed in the ``path_to_triqs`` directory. + +Installation steps +------------------ + +#. Download the sources from github:: + + $ git clone https://github.com/triqs/app4triqs.git app4triqs.src + +#. Create an empty build directory where you will compile the code:: + + $ mkdir app4triqs.build && cd app4triqs.build + +#. Make sure that you have added the TRIQS and Cpp2Py installation to your environment variables:: + + $ source path_to_triqs/share/cpp2pyvarsh.sh + $ source path_to_triqs/share/triqsvarsh.sh + +#. In the build directory call cmake:: + + $ cmake ../app4triqs.src + +#. Compile the code, run the tests and install the application:: + + $ make + $ make test + $ make install + +Version compatibility +--------------------- + +Be careful that the version of the TRIQS library and of the solver must be +compatible (more information on the :ref:`TRIQS website `). +As the TRILEX project is currently still in alpha phase (unstable), it can +only be compiled against the unstable branch of triqs. + +Custom CMake options +-------------------- + +Functionality of ``app4triqs`` can be tweaked using extra compile-time options passed to CMake:: + + cmake -DOPTION1=value1 -DOPTION2=value2 ... ../app4triqs.src + ++-----------------------------------------------------------------------+-----------------------------------------------+ +| Options | Syntax | ++=======================================================================+===============================================+ +| Specify an installation path other than path_to_triqs | -DCMAKE_INSTALL_PREFIX=path_to_app4triqs | ++-----------------------------------------------------------------------+-----------------------------------------------+ +| Build the documentation locally | -DBuild_Documentation=ON | ++-----------------------------------------------------------------------+-----------------------------------------------+ diff --git a/doc/issues.rst b/doc/issues.rst new file mode 100644 index 00000000..ea52b95c --- /dev/null +++ b/doc/issues.rst @@ -0,0 +1,23 @@ +.. _issues: + +Reporting issues +================ + +Please report all problems and bugs directly at the github issue page +``_. In order to make it easier for us +to solve the issue please follow these guidelines: + +#. In all cases specify which version of the application you are using. You can + find the version number in the file :file:`CMakeLists.txt` at the root of the + application sources. + +#. If you have a problem during the installation, give us information about + your operating system and the compiler you are using. Include the outputs of + the ``cmake`` and ``make`` commands as well as the ``CMakeCache.txt`` file + which is in the build directory. Please include these outputs in a + `gist `_ file referenced in the issue. + +#. If you are experiencing a problem during the execution of the application, provide + a script which allows to quickly reproduce the problem. + +Thanks! diff --git a/python/app4triqs/CMakeLists.txt b/python/app4triqs/CMakeLists.txt new file mode 100644 index 00000000..2784e7ff --- /dev/null +++ b/python/app4triqs/CMakeLists.txt @@ -0,0 +1,21 @@ +# Build the python module +add_cpp2py_module(toto_module) + +target_link_libraries(toto_module app4triqs_c) + +# We need to include the convertes.hxx files +target_include_directories(toto_module PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}) + +# Configure the version +configure_file(version.py.in version.py) + +# All Python files. Copy them in the build dir to have a complete package for the tests. +set(PYTHON_SOURCES __init__.py) +foreach(f ${PYTHON_SOURCES}) + configure_file(${f} ${f} COPYONLY) +endforeach() + +# Install python module to proper location +set(PYTHON_LIB_DEST ${CPP2PY_PYTHON_LIB_DEST_ROOT}/app4triqs) +install(TARGETS toto_module DESTINATION ${PYTHON_LIB_DEST}) +install(FILES ${PYTHON_SOURCES} ${CMAKE_CURRENT_BINARY_DIR}/version.py DESTINATION ${PYTHON_LIB_DEST}) diff --git a/python/app4triqs/__init__.py b/python/app4triqs/__init__.py new file mode 100644 index 00000000..a44ad9d7 --- /dev/null +++ b/python/app4triqs/__init__.py @@ -0,0 +1,29 @@ +################################################################################ +# +# App4Triqs: Test application for Triqs +# +# Copyright (C) 2018 by The Simons Foundation +# Author: H. U.R. Strand +# +# App4Triqs 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 3 of the License, or (at your option) any later +# version. +# +# App4Triqs 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 +# App4Triqs. If not, see . +# +################################################################################ + +r""" +DOC + +""" +from toto_module import Toto, chain + +__all__ = ['Toto', 'chain'] diff --git a/python/app4triqs/toto_module_desc.py b/python/app4triqs/toto_module_desc.py new file mode 100644 index 00000000..a9117fc2 --- /dev/null +++ b/python/app4triqs/toto_module_desc.py @@ -0,0 +1,51 @@ +# Generated automatically using the command : +# c++2py ../../c++/app4triqs/toto.hpp -p --members_read_only -N app4triqs -a app4triqs -m toto_module -o toto_module -C pytriqs --cxxflags="-std=c++17" +from cpp2py.wrap_generator import * + +# The module +module = module_(full_name = "toto_module", doc = "", app_name = "app4triqs") + +# Imports + +# Add here all includes +module.add_include("app4triqs/toto.hpp") + +# Add here anything to add in the C++ code at the start, e.g. namespace using +module.add_preamble(""" +#include +#include + +using namespace app4triqs; +""") + + +# The class toto +c = class_( + py_type = "Toto", # name of the python class + c_type = "app4triqs::toto", # name of the C++ class + doc = """A very useful and important class\n\n @note A Useful note""", # doc of the C++ class + hdf5 = True, + arithmetic = ("add_only"), + comparisons = "==", + serializable = "tuple", +) + +c.add_constructor("""()""", doc = """""") + +c.add_constructor("""(int i_)""", doc = """Construct from integer\n\n :param i_: a scalar""") + +c.add_method("""std::string hdf5_scheme ()""", + is_static = True, + doc = """HDF5""") + +c.add_property(name = "i", + getter = cfunction("int get_i ()"), + doc = """Simple accessor""") + +module.add_class(c) + +module.add_function ("int app4triqs::chain (int i, int j)", doc = """Chain digits of two integers\n\n Chain the decimal digits of two integers i and j, and return a new \n\n @param :math:`i` The first integer\n @param :math:`j` The second integer \n @return An integer containing the digits of both i and j\n\n @remark""") + + + +module.generate_code() diff --git a/python/app4triqs/version.py.in b/python/app4triqs/version.py.in new file mode 100644 index 00000000..b28d0875 --- /dev/null +++ b/python/app4triqs/version.py.in @@ -0,0 +1,31 @@ +################################################################################ +# +# App4Triqs: Test application for Triqs +# +# Copyright (C) 2018 by The Simons Foundation +# Author: H. U.R. Strand +# +# App4Triqs 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 3 of the License, or (at your option) any later +# version. +# +# App4Triqs 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 +# App4Triqs. If not, see . +# +################################################################################ + +version = "@APP4TRIQS_VERSION@" +triqs_hash = "@TRIQS_GIT_HASH@" +app4triqs_hash = "@APP4TRIQS_GIT_HASH@" + +def show_version(): + print "\nYou are using app4triqs version %s, release %s\n"%(version, release) + +def show_git_hash(): + print "\nYou are using app4triqs git hash %s based on triqs git hash %s\n"%(app4triqs_hash, triqs_hash) diff --git a/share/CMakeLists.txt b/share/CMakeLists.txt new file mode 100644 index 00000000..734a9a5d --- /dev/null +++ b/share/CMakeLists.txt @@ -0,0 +1,17 @@ +if(NOT CMAKE_INSTALL_PREFIX STREQUAL TRIQS_ROOT) + + configure_file(${CMAKE_CURRENT_SOURCE_DIR}/app4triqs.modulefile.in ${CMAKE_CURRENT_BINARY_DIR}/app4triqs.modulefile @ONLY) + install(FILES ${CMAKE_CURRENT_BINARY_DIR}/app4triqs.modulefile DESTINATION ${CMAKE_INSTALL_PREFIX}/share) + + configure_file(${CMAKE_CURRENT_SOURCE_DIR}/app4triqsvars.sh.in ${CMAKE_CURRENT_BINARY_DIR}/app4triqsvars.sh @ONLY) + install(FILES ${CMAKE_CURRENT_BINARY_DIR}/app4triqsvars.sh DESTINATION ${CMAKE_INSTALL_PREFIX}/share) + + message(STATUS "***************************************************************") + message(STATUS "* Custom install Location. Use: ") + message(STATUS "* ") + message(STATUS "* source ${CMAKE_INSTALL_PREFIX}/share/app4triqsvars.sh ") + message(STATUS "* ") + message(STATUS "* to set up the environment variables ") + message(STATUS "***************************************************************") + +endif() diff --git a/share/app4triqs.modulefile.in b/share/app4triqs.modulefile.in new file mode 100644 index 00000000..c6b2d12d --- /dev/null +++ b/share/app4triqs.modulefile.in @@ -0,0 +1,39 @@ +#%Module1.0 +# +# To be installed as ${MODULEPATH}/app4triqs/@APP4TRIQS_VERSION@ + +set name app4triqs +set version @APP4TRIQS_VERSION@ +set root @CMAKE_INSTALL_PREFIX@ +set git_hash @APP4TRIQS_GIT_HASH@ + +set url "https://github.com/TRIQS/app4triqs" +set description "An example application using cpp2py and triqs." + +module-whatis "$description" + +proc ModulesHelp { } { + global description url version git_hash + puts stderr "Description: $description" + puts stderr "URL: $url" + puts stderr "Version: $version" + puts stderr "Git hash: $git_hash" +} + +# You may need to edit the next line if cpp2py module is installed +# under a different name in your setup. +prereq cpp2py/@CPP2PY_VERSION@ + +# Only one version of app4triqs can be loaded at a time +conflict $name + +setenv APP4TRIQS_ROOT $root +setenv APP4TRIQS_VERSION $version +setenv APP4TRIQS_GIT_HASH $git_hash + +prepend-path PATH $root/bin +prepend-path CPATH $root/include +prepend-path LIBRARY_PATH $root/lib +prepend-path LD_LIBRARY_PATH $root/lib +prepend-path PYTHONPATH $root/@CPP2PY_PYTHON_LIB_DEST_ROOT@ +prepend-path CMAKE_PREFIX_PATH $root/share/cmake diff --git a/share/app4triqsvars.sh.in b/share/app4triqsvars.sh.in new file mode 100644 index 00000000..ff0abab6 --- /dev/null +++ b/share/app4triqsvars.sh.in @@ -0,0 +1,13 @@ +# Source this in your environment. + +export TRIQS_ROOT=@CMAKE_INSTALL_PREFIX@ + +export CPATH=@CMAKE_INSTALL_PREFIX@/include:$CPATH +export PATH=@CMAKE_INSTALL_PREFIX@/bin:$PATH +export LIBRARY_PATH=@CMAKE_INSTALL_PREFIX@/lib:$LIBRARY_PATH +export LD_LIBRARY_PATH=@CMAKE_INSTALL_PREFIX@/lib:$LD_LIBRARY_PATH +export PYTHONPATH=@CMAKE_INSTALL_PREFIX@/@CPP2PY_PYTHON_LIB_DEST_ROOT@:$PYTHONPATH +export CMAKE_PREFIX_PATH=@CMAKE_INSTALL_PREFIX@/share/cmake:$CMAKE_PREFIX_PATH + + + diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt new file mode 100644 index 00000000..4e0ce259 --- /dev/null +++ b/test/CMakeLists.txt @@ -0,0 +1,4 @@ +add_subdirectory(c++) +if (${TRIQS_WITH_PYTHON_SUPPORT}) + add_subdirectory(python) +endif() diff --git a/test/c++/CMakeLists.txt b/test/c++/CMakeLists.txt new file mode 100644 index 00000000..d3eb0202 --- /dev/null +++ b/test/c++/CMakeLists.txt @@ -0,0 +1,11 @@ +# Copy reference h5 files to binary dir +file(GLOB all_h5_files *.h5) +file(COPY ${all_h5_files} DESTINATION ${CMAKE_CURRENT_BINARY_DIR}) + +set(all_tests toto) + +foreach(t ${all_tests}) + add_executable(${t} ${CMAKE_CURRENT_SOURCE_DIR}/${t}.cpp) + target_link_libraries(${t} app4triqs_c gtest) + add_test(${t} ${CMAKE_CURRENT_BINARY_DIR}/${t}) +endforeach() diff --git a/test/c++/toto.cpp b/test/c++/toto.cpp new file mode 100644 index 00000000..85779be7 --- /dev/null +++ b/test/c++/toto.cpp @@ -0,0 +1,32 @@ +#include +#include + +using namespace app4triqs; + +TEST(Toto, Add) { + + toto a(0); + toto b(2); + + auto c = a + b; + EXPECT_EQ(c, b); +} + +TEST(Toto, H5) { + + toto a(0); + { // Local scope for file + triqs::h5::file f("f.h5", H5F_ACC_TRUNC); + h5_write(f, "a", a); + } + + toto a2; + { + triqs::h5::file f("f.h5", H5F_ACC_RDWR); + h5_read(f, "a", a2); + } + + EXPECT_EQ(a, a2); +} + +MAKE_MAIN; diff --git a/test/python/CMakeLists.txt b/test/python/CMakeLists.txt new file mode 100644 index 00000000..6864a634 --- /dev/null +++ b/test/python/CMakeLists.txt @@ -0,0 +1,12 @@ +# Copy h5 files to binary dir +file(GLOB all_h5_files *.h5) +file(COPY ${all_h5_files} DESTINATION ${CMAKE_CURRENT_BINARY_DIR}) + +set(all_tests Toto chain) + +foreach(t ${all_tests}) + add_test(NAME ${t} COMMAND python ${CMAKE_CURRENT_SOURCE_DIR}/${t}.py) +endforeach() + +# Set the PythonPath : put the build dir first (in case there is an installed version). +set_property(TEST ${all_tests} PROPERTY ENVIRONMENT PYTHONPATH=${CMAKE_BINARY_DIR}/python:$ENV{PYTHONPATH} ) diff --git a/test/python/Toto.py b/test/python/Toto.py new file mode 100644 index 00000000..52c9058d --- /dev/null +++ b/test/python/Toto.py @@ -0,0 +1,42 @@ +#!/usr/bin/env python + +import unittest + +from app4triqs import Toto +from pytriqs.archive import * +from pytriqs.utility import mpi + +class test_toto(unittest.TestCase): + + def test_add(self): + + a=Toto(0) + b=Toto(2) + + c=a+b + self.assertEqual(c, b) + + + def test_h5(self): + + a=Toto(0) + with HDFArchive("f.h5",'a') as A: + A["a"] = a + with HDFArchive("f.h5",'r') as A: + a_read = A["a"] + self.assertEqual(a, a_read) + + + def test_mpi(self): + + a=Toto(0) + + if mpi.is_master_node(): + a=Toto(1) + mpi.bcast(a) + + self.assertEqual(a, Toto(1)) + + +if __name__ == '__main__': + unittest.main() diff --git a/test/python/chain.py b/test/python/chain.py new file mode 100644 index 00000000..e0dcfc8e --- /dev/null +++ b/test/python/chain.py @@ -0,0 +1,17 @@ +#!/usr/bin/env python + +import unittest + +from app4triqs import chain + +class test_chain(unittest.TestCase): + + def test_chain(self): + + i = 111 + j = 222 + ij = chain(i,j) + self.assertEqual(ij, 111222) + +if __name__ == '__main__': + unittest.main() From 6bf4afd316acc4f064b18915a6faf23715d1a5bb Mon Sep 17 00:00:00 2001 From: Nils Wentzell Date: Fri, 23 Mar 2018 16:59:38 +0100 Subject: [PATCH 003/272] Adding cmake config files to install targets, Major cleaning --- CMakeLists.txt | 19 ++++++-------- c++/app4triqs/CMakeLists.txt | 17 +++++++------ doc/CMakeLists.txt | 25 +++++++++++++------ doc/about.rst | 3 +++ doc/conf.py.in | 2 +- doc/contents.rst | 18 ++++++++++--- doc/documentation.rst | 12 --------- doc/index.rst | 8 +++--- doc/install.rst | 4 +-- python/app4triqs/__init__.py | 22 ---------------- python/app4triqs/version.py.in | 22 ---------------- share/CMakeLists.txt | 16 ++++++++---- share/app4triqsvars.sh.in | 3 --- share/cmake/CMakeLists.txt | 10 ++++++++ share/cmake/app4triqs-config-version.cmake.in | 13 ++++++++++ share/cmake/app4triqs-config.cmake.in | 20 +++++++++++++++ 16 files changed, 113 insertions(+), 101 deletions(-) delete mode 100644 doc/documentation.rst create mode 100644 share/cmake/CMakeLists.txt create mode 100644 share/cmake/app4triqs-config-version.cmake.in create mode 100644 share/cmake/app4triqs-config.cmake.in diff --git a/CMakeLists.txt b/CMakeLists.txt index 78e5d33d..854ebccb 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,5 +1,5 @@ # Version number -set (APP4TRIQS_VERSION "1.5") +set(APP4TRIQS_VERSION "1.5") # Start configuration cmake_minimum_required(VERSION 2.8) @@ -9,31 +9,28 @@ project(app4triqs CXX) if(NOT CMAKE_BUILD_TYPE) set(CMAKE_BUILD_TYPE Release CACHE STRING "Type of build" FORCE) endif() -message( STATUS "-------- BUILD-TYPE: ${CMAKE_BUILD_TYPE} -------------") +message( STATUS "-------- BUILD-TYPE: ${CMAKE_BUILD_TYPE} --------") # Use shared libraries set(BUILD_SHARED_LIBS ON) # Load TRIQS and Cpp2Py -find_package(TRIQS 1.5 EXACT REQUIRED) -find_package(Cpp2Py 1.5 EXACT REQUIRED) +find_package(TRIQS ${APP4TRIQS_VERSION} EXACT REQUIRED) +find_package(Cpp2Py ${APP4TRIQS_VERSION} EXACT REQUIRED) # We will need the FindNNFT of triqs, so we adjust CMake Module Path to find it list(APPEND CMAKE_MODULE_PATH ${TRIQS_ROOT}/share/cmake) # Default Install directory to TRIQS_ROOT if not given. Checks an absolute name is given. if(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT OR (NOT IS_ABSOLUTE ${CMAKE_INSTALL_PREFIX})) - message(STATUS " No install prefix given (or invalid). Defaulting to TRIQS_ROOT") + message(STATUS "No install prefix given (or invalid). Defaulting to TRIQS_ROOT") set(CMAKE_INSTALL_PREFIX ${TRIQS_ROOT} CACHE PATH "default install path" FORCE) endif() -message(STATUS "-------- CMAKE_INSTALL_PREFIX: ${CMAKE_INSTALL_PREFIX} -------------") +message(STATUS "-------- INSTALL_PREFIX: ${CMAKE_INSTALL_PREFIX} --------") -# Macro defined in TRIQS which picks the hash of repo. +# Fetch the git hash of app4triqs triqs_get_git_hash_of_source_dir(APP4TRIQS_GIT_HASH) -message(STATUS "Git hash: ${APP4TRIQS_GIT_HASH}") - -# Common to all targets (c++, python, tests). -include_directories(c++) +message(STATUS "app4triqs git hash: ${APP4TRIQS_GIT_HASH}") # Set up the rpath for compiled executable triqs_set_rpath_for_all_targets() diff --git a/c++/app4triqs/CMakeLists.txt b/c++/app4triqs/CMakeLists.txt index 449b23ee..fefb6564 100644 --- a/c++/app4triqs/CMakeLists.txt +++ b/c++/app4triqs/CMakeLists.txt @@ -3,17 +3,18 @@ add_library(app4triqs_c ${sources}) target_link_libraries(app4triqs_c PUBLIC triqs) target_compile_options(app4triqs_c PUBLIC -std=c++17) +target_include_directories(app4triqs_c PUBLIC $) -target_compile_definitions(app4triqs_c PUBLIC - APP4TRIQS_GIT_HASH=${APP4TRIQS_GIT_HASH} - TRIQS_GIT_HASH=${TRIQS_GIT_HASH} - $<$:DEBUG_APP4TRIQS> - $<$:TRIQS_ARRAYS_ENFORCE_BOUNDCHECK> - #$<$:MYOPTION> # Add compile definintions for option +target_compile_definitions(app4triqs_c PRIVATE + APP4TRIQS_GIT_HASH=${APP4TRIQS_GIT_HASH} + TRIQS_GIT_HASH=${TRIQS_GIT_HASH} + $<$:DEBUG_APP4TRIQS> + $<$:TRIQS_ARRAYS_ENFORCE_BOUNDCHECK> + #$<$:MYOPTION> # Add compile definintions for option ) # Install -install(TARGETS app4triqs_c DESTINATION lib) +install(TARGETS app4triqs_c EXPORT app4triqs-targets DESTINATION lib) # If other applications need our headers, we can install them as well -# install(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} DESTINATION include FILES_MATCHING PATTERN "*.hpp" PATTERN "*.h") +install(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} DESTINATION include FILES_MATCHING PATTERN "*.hpp" PATTERN "*.h") diff --git a/doc/CMakeLists.txt b/doc/CMakeLists.txt index 05eed6c9..658139b9 100644 --- a/doc/CMakeLists.txt +++ b/doc/CMakeLists.txt @@ -30,16 +30,25 @@ execute_process(COMMAND cp_rs ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY add_custom_target(docs_cpp2rst) +get_property(TRIQS_INCLUDE_DIRS TARGET triqs PROPERTY INTERFACE_INCLUDE_DIRECTORIES) +get_property(APP4TRIQS_INCLUDE_DIRS TARGET app4triqs_c PROPERTY INTERFACE_INCLUDE_DIRECTORIES) + +set(CPP2RST_INCLUDE_DIRS ${TRIQS_INCLUDE_DIRS} ${APP4TRIQS_INCLUDE_DIRS}) +foreach(I ${CPP2RST_INCLUDE_DIRS}) + set (CPP2RST_INCLUDE_COMMAND ${CPP2RST_INCLUDE_COMMAND} --includes ${I}) +endforeach() + macro(generate_docs header_file) add_custom_command (TARGET docs_cpp2rst - COMMAND c++2rst - ${header_file} - -N app4triqs - --output_directory ${CMAKE_CURRENT_BINARY_DIR}/cpp2rst_generated - --cxxflags="-std=c++17" - -I ${CMAKE_SOURCE_DIR}/c++ - -I ${TRIQS_ROOT}/include - 2>&1 >> cpp2rst.log + COMMAND c++2rst + ${header_file} + -N app4triqs + --output_directory ${CMAKE_CURRENT_BINARY_DIR}/cpp2rst_generated + ${CPP2RST_INCLUDE_COMMAND} + --cxxflags="-std=c++17" + -I ${CMAKE_SOURCE_DIR}/c++ + -I ${TRIQS_ROOT}/include + 2>&1 >> cpp2rst.log ) endmacro(generate_docs) diff --git a/doc/about.rst b/doc/about.rst index 8fc7917d..c0ec4464 100644 --- a/doc/about.rst +++ b/doc/about.rst @@ -1,3 +1,6 @@ .. _about: +About app4triqs +=============== + An example application using cpp2py and triqs. diff --git a/doc/conf.py.in b/doc/conf.py.in index 0bdc06f9..cc68de4d 100644 --- a/doc/conf.py.in +++ b/doc/conf.py.in @@ -29,4 +29,4 @@ html_sidebars = {'index': ['sideb.html', 'searchbox.html']} htmlhelp_basename = 'TRIQSIntdoc' -intersphinx_mapping = {'python': ('http://docs.python.org/2.7', None), 'triqslibs': ('http://ipht.cea.fr/triqs', None)} +intersphinx_mapping = {'python': ('http://docs.python.org/2.7', None), 'triqslibs': ('https://triqs.ipht.cnrs.fr/unstable', None)} diff --git a/doc/contents.rst b/doc/contents.rst index 109c3171..16954194 100644 --- a/doc/contents.rst +++ b/doc/contents.rst @@ -1,12 +1,24 @@ +.. _contents: -Table of contents -================= +Documentation +============= + +Contents +-------- .. toctree:: :maxdepth: 5 index - documentation install issues about + +Reference manual +---------------- + +.. toctree:: + :maxdepth: 5 + + cpp2rst_generated/app4triqs/toto + cpp2rst_generated/app4triqs/chain diff --git a/doc/documentation.rst b/doc/documentation.rst deleted file mode 100644 index 6bec32ee..00000000 --- a/doc/documentation.rst +++ /dev/null @@ -1,12 +0,0 @@ -.. _documentation: - -Documentation -============= - -Reference manual ----------------- - -.. toctree:: - :maxdepth: 1 - - cpp2rst_generated/app4triqs/compute_Sigma_Hedin diff --git a/doc/index.rst b/doc/index.rst index 6e5c1710..d342e1ad 100644 --- a/doc/index.rst +++ b/doc/index.rst @@ -1,11 +1,11 @@ .. _welcome: -App4Triqs +app4triqs ========= An example application using cpp2py and triqs. -This documentation is generated based on the doc/\*.rst files and -the comments in the sources and headers. +This documentation is generated based on `rst `_ files +and the comments in the sources and headers. -Lets have a look at the :ref:`documentation`. +Lets have a look at the :ref:`documentation `. diff --git a/doc/install.rst b/doc/install.rst index 4cfb66a3..ed132b75 100644 --- a/doc/install.rst +++ b/doc/install.rst @@ -43,8 +43,8 @@ Version compatibility Be careful that the version of the TRIQS library and of the solver must be compatible (more information on the :ref:`TRIQS website `). -As the TRILEX project is currently still in alpha phase (unstable), it can -only be compiled against the unstable branch of triqs. +As app4triqs is still in alpha phase (unstable), it can only be compiled against the +unstable branch of triqs. Custom CMake options -------------------- diff --git a/python/app4triqs/__init__.py b/python/app4triqs/__init__.py index a44ad9d7..d00e4749 100644 --- a/python/app4triqs/__init__.py +++ b/python/app4triqs/__init__.py @@ -1,25 +1,3 @@ -################################################################################ -# -# App4Triqs: Test application for Triqs -# -# Copyright (C) 2018 by The Simons Foundation -# Author: H. U.R. Strand -# -# App4Triqs 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 3 of the License, or (at your option) any later -# version. -# -# App4Triqs 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 -# App4Triqs. If not, see . -# -################################################################################ - r""" DOC diff --git a/python/app4triqs/version.py.in b/python/app4triqs/version.py.in index b28d0875..dfcc5436 100644 --- a/python/app4triqs/version.py.in +++ b/python/app4triqs/version.py.in @@ -1,25 +1,3 @@ -################################################################################ -# -# App4Triqs: Test application for Triqs -# -# Copyright (C) 2018 by The Simons Foundation -# Author: H. U.R. Strand -# -# App4Triqs 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 3 of the License, or (at your option) any later -# version. -# -# App4Triqs 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 -# App4Triqs. If not, see . -# -################################################################################ - version = "@APP4TRIQS_VERSION@" triqs_hash = "@TRIQS_GIT_HASH@" app4triqs_hash = "@APP4TRIQS_GIT_HASH@" diff --git a/share/CMakeLists.txt b/share/CMakeLists.txt index 734a9a5d..c12791b6 100644 --- a/share/CMakeLists.txt +++ b/share/CMakeLists.txt @@ -1,10 +1,16 @@ +add_subdirectory(cmake) + if(NOT CMAKE_INSTALL_PREFIX STREQUAL TRIQS_ROOT) - configure_file(${CMAKE_CURRENT_SOURCE_DIR}/app4triqs.modulefile.in ${CMAKE_CURRENT_BINARY_DIR}/app4triqs.modulefile @ONLY) - install(FILES ${CMAKE_CURRENT_BINARY_DIR}/app4triqs.modulefile DESTINATION ${CMAKE_INSTALL_PREFIX}/share) - - configure_file(${CMAKE_CURRENT_SOURCE_DIR}/app4triqsvars.sh.in ${CMAKE_CURRENT_BINARY_DIR}/app4triqsvars.sh @ONLY) - install(FILES ${CMAKE_CURRENT_BINARY_DIR}/app4triqsvars.sh DESTINATION ${CMAKE_INSTALL_PREFIX}/share) + configure_file(app4triqs.modulefile.in app4triqs.modulefile @ONLY) + configure_file(app4triqsvars.sh.in app4triqsvars.sh @ONLY) + + install( + FILES + ${CMAKE_CURRENT_BINARY_DIR}/app4triqs.modulefile + ${CMAKE_CURRENT_BINARY_DIR}/app4triqsvars.sh + DESTINATION share + ) message(STATUS "***************************************************************") message(STATUS "* Custom install Location. Use: ") diff --git a/share/app4triqsvars.sh.in b/share/app4triqsvars.sh.in index ff0abab6..8bab403f 100644 --- a/share/app4triqsvars.sh.in +++ b/share/app4triqsvars.sh.in @@ -8,6 +8,3 @@ export LIBRARY_PATH=@CMAKE_INSTALL_PREFIX@/lib:$LIBRARY_PATH export LD_LIBRARY_PATH=@CMAKE_INSTALL_PREFIX@/lib:$LD_LIBRARY_PATH export PYTHONPATH=@CMAKE_INSTALL_PREFIX@/@CPP2PY_PYTHON_LIB_DEST_ROOT@:$PYTHONPATH export CMAKE_PREFIX_PATH=@CMAKE_INSTALL_PREFIX@/share/cmake:$CMAKE_PREFIX_PATH - - - diff --git a/share/cmake/CMakeLists.txt b/share/cmake/CMakeLists.txt new file mode 100644 index 00000000..0ebacec0 --- /dev/null +++ b/share/cmake/CMakeLists.txt @@ -0,0 +1,10 @@ +configure_file(app4triqs-config.cmake.in app4triqs-config.cmake @ONLY) +configure_file(app4triqs-config-version.cmake.in app4triqs-config-version.cmake @ONLY) +install( + FILES + ${CMAKE_CURRENT_BINARY_DIR}/app4triqs-config.cmake + ${CMAKE_CURRENT_BINARY_DIR}/app4triqs-config-version.cmake + DESTINATION share/cmake +) + +install(EXPORT app4triqs-targets DESTINATION share/cmake) diff --git a/share/cmake/app4triqs-config-version.cmake.in b/share/cmake/app4triqs-config-version.cmake.in new file mode 100644 index 00000000..9d1cb5c4 --- /dev/null +++ b/share/cmake/app4triqs-config-version.cmake.in @@ -0,0 +1,13 @@ +set(PACKAGE_VERSION @APP4TRIQS_VERSION@) + +if (PACKAGE_FIND_VERSION VERSION_EQUAL PACKAGE_VERSION) + set(PACKAGE_VERSION_EXACT TRUE) +endif() + +if (PACKAGE_FIND_VERSION VERSION_LESS PACKAGE_VERSION) + set(PACKAGE_VERSION_COMPATIBLE TRUE) +endif() + +if (PACKAGE_FIND_VERSION VERSION_GREATER PACKAGE_VERSION) + set(PACKAGE_VERSION_UNSUITABLE TRUE) +endif() diff --git a/share/cmake/app4triqs-config.cmake.in b/share/cmake/app4triqs-config.cmake.in new file mode 100644 index 00000000..90d20551 --- /dev/null +++ b/share/cmake/app4triqs-config.cmake.in @@ -0,0 +1,20 @@ +# Multiple inclusion guard +if (NOT APP4TRIQS_FOUND) +set(APP4TRIQS_FOUND True) + +# version +set(APP4TRIQS_VERSION @APP4TRIQS_VERSION@) +set(APP4TRIQS_GIT_HASH @APP4TRIQS_GIT_HASH@) + +# Root of the installation +set(APP4TRIQS_ROOT @CMAKE_INSTALL_PREFIX@) + +# include the exported targets of this project +include(@CMAKE_INSTALL_PREFIX@/share/cmake/app4triqs-targets.cmake) + +MESSAGE(STATUS "Found APP4TRIQSConfig.cmake with version ${APP4TRIQS_VERSION}, hash = ${APP4TRIQS_GIT_HASH}") + +# Documentation +set(APP4TRIQS_WITH_DOCUMENTATION @Build_Documentation@) + +endif (NOT APP4TRIQS_FOUND) From 616479d883508e935732d1936483f91c2e1a46bf Mon Sep 17 00:00:00 2001 From: Dylan Simon Date: Fri, 23 Mar 2018 15:30:28 -0400 Subject: [PATCH 004/272] [jenkins] Use persistent osx triqs install; cleanup Should now match dft_tools and soon cthyb --- Dockerfile | 8 ++-- Jenkinsfile | 125 ++++++++++++++++++++++++++++++++-------------------- 2 files changed, 81 insertions(+), 52 deletions(-) diff --git a/Dockerfile b/Dockerfile index 909e37a6..cc505119 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,10 +1,12 @@ # See ../triqs/packaging for other options FROM flatironinstitute/triqs:master-ubuntu-clang -COPY . ${SRC}/app4triqs -WORKDIR ${BUILD}/app4triqs +ARG APPNAME=app4triqs +COPY . $SRC/$APPNAME +WORKDIR $BUILD/$APPNAME RUN chown build . USER build -RUN cmake ${SRC}/app4triqs -DTRIQS_ROOT=${INSTALL} && make -j2 && make test +ARG BUILD_DOC=0 +RUN cmake $SRC/$APPNAME -DTRIQS_ROOT=${INSTALL} -DBuild_Documentation=${BUILD_DOC} && make -j2 && make test USER root RUN make install diff --git a/Jenkinsfile b/Jenkinsfile index 4416c6c9..fc008598 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -1,5 +1,8 @@ -def app4triqsBranch = env.CHANGE_TARGET ?: env.BRANCH_NAME -def app4triqsProject = '/TRIQS/app4triqs/' + app4triqsBranch.replaceAll('/', '%2F') +def projectName = "app4triqs" +def documentationPlatform = "ubuntu-clang" +def triqsBranch = env.CHANGE_TARGET ?: env.BRANCH_NAME +def triqsProject = '/TRIQS/triqs/' + triqsBranch.replaceAll('/', '%2F') +def publish = !env.BRANCH_NAME.startsWith("PR-") && projectName != "app4triqs" properties([ disableConcurrentBuilds(), @@ -7,32 +10,34 @@ properties([ pipelineTriggers([ upstream( threshold: 'SUCCESS', - upstreamProjects: app4triqsProject + upstreamProjects: triqsProject ) ]) ]) +/* map of all builds to run, populated below */ def platforms = [:] def dockerPlatforms = ["ubuntu-clang", "ubuntu-gcc", "centos-gcc"] +/* .each is currently broken in jenkins */ for (int i = 0; i < dockerPlatforms.size(); i++) { def platform = dockerPlatforms[i] - platforms[platform] = { -> stage(platform) { - timeout(time: 1, unit: 'HOURS') { - node('docker') { + platforms[platform] = { -> node('docker') { + stage(platform) { timeout(time: 1, unit: 'HOURS') { checkout scm /* construct a Dockerfile for this base */ sh """ - ( echo "FROM flatironinstitute/app4triqs:${app4triqsBranch}-${env.STAGE_NAME}" ; sed '0,/^FROM /d' Dockerfile ) > Dockerfile.jenkins + ( echo "FROM flatironinstitute/triqs:${triqsBranch}-${env.STAGE_NAME}" ; sed '0,/^FROM /d' Dockerfile ) > Dockerfile.jenkins mv -f Dockerfile.jenkins Dockerfile """ /* build and tag */ - def img = docker.build("flatironinstitute/app4triqs:${env.BRANCH_NAME}-${env.STAGE_NAME}") - /* but we don't need the tag so clean it up (alternatively, could refacter to run in container) */ - sh "docker rmi ${img.imageName()}" - } + def img = docker.build("flatironinstitute/${projectName}:${env.BRANCH_NAME}-${env.STAGE_NAME}", "--build-arg BUILD_DOC=${platform==documentationPlatform} .") + if (!publish || platform != documentationPlatform) { + /* but we don't need the tag so clean it up (except for documentation) */ + sh "docker rmi --no-prune ${img.imageName()}" } } } + } } } def osxPlatforms = [ @@ -42,51 +47,73 @@ def osxPlatforms = [ for (int i = 0; i < osxPlatforms.size(); i++) { def platformEnv = osxPlatforms[i] def platform = platformEnv[0] - platforms["osx-$platform"] = { -> stage("osx-$platform") { - timeout(time: 1, unit: 'HOURS') { - node('osx && triqs') { - def srcDir = pwd() - def tmpDir = pwd(tmp:true) - def buildDir = "$tmpDir/build" - def installDir = "$tmpDir/install" - - dir(installDir) { - deleteDir() - } - - copyArtifacts(projectName: app4triqsProject, selector: upstream(fallbackToLastSuccessful: true), filter: "osx-${platform}.zip") - unzip(zipFile: "osx-${platform}.zip", dir: installDir) - /* fixup zip-stripped permissions (JENKINS-13128) */ - sh "chmod +x $installDir/bin/*" - - checkout scm - - dir(buildDir) { withEnv(platformEnv[1]+[ - "PATH=$installDir/bin:/usr/local/bin:/usr/bin:/bin:/usr/sbin", - "CPATH=$installDir/include", - "LIBRARY_PATH=$installDir/lib", - "CMAKE_PREFIX_PATH=$installDir/share/cmake"]) { - deleteDir() - sh "cmake $srcDir -DTRIQS_ROOT=$installDir" - sh "make -j2" - try { - sh "make test" - } catch (exc) { - archiveArtifacts(artifacts: 'Testing/Temporary/LastTest.log') - throw exc - } - sh "make install" - } } - // zip(zipFile: "osx-${platform}.zip", archive: true, dir: installDir) + platforms["osx-$platform"] = { -> node('osx && triqs') { + stage("osx-$platform") { timeout(time: 1, unit: 'HOURS') { + def srcDir = pwd() + def tmpDir = pwd(tmp:true) + def buildDir = "$tmpDir/build" + def installDir = "$tmpDir/install" + def triqsDir = "${env.HOME}/install/triqs/${triqsBranch}/${platform}" + dir(installDir) { + deleteDir() } - } + + checkout scm + dir(buildDir) { withEnv(platformEnv[1]+[ + "PATH=$triqsDir/bin:/usr/local/bin:/usr/bin:/bin:/usr/sbin", + "CPATH=$triqsDir/include", + "LIBRARY_PATH=$triqsDir/lib", + "CMAKE_PREFIX_PATH=$triqsDir/share/cmake"]) { + deleteDir() + sh "cmake $srcDir -DCMAKE_INSTALL_PREFIX=$installDir -DTRIQS_ROOT=$triqsDir" + sh "make -j3" + try { + sh "make test" + } catch (exc) { + archiveArtifacts(artifacts: 'Testing/Temporary/LastTest.log') + throw exc + } + sh "make install" + } } + } } } } } try { parallel platforms + if (publish) { node("docker") { + stage("publish") { timeout(time: 1, unit: 'HOURS') { + def commit = sh(returnStdout: true, script: "git rev-parse HEAD").trim() + def workDir = pwd() + dir("$workDir/gh-pages") { + def subdir = env.BRANCH_NAME + git(url: "ssh://git@github.com/TRIQS/${projectName}.git", branch: "gh-pages", credentialsId: "ssh", changelog: false) + sh "rm -rf ${subdir}" + docker.image("flatironinstitute/${projectName}:${env.BRANCH_NAME}-${documentationPlatform}").inside() { + sh "cp -rp \$INSTALL/share/doc/${projectName} ${subdir}" + } + sh "git add -A ${subdir}" + sh """ + git commit --author='Flatiron Jenkins ' --allow-empty -m 'Generated documentation for ${env.BRANCH_NAME}' -m '${env.BUILD_TAG} ${commit}' + """ + // note: credentials used above don't work (need JENKINS-28335) + sh "git push origin gh-pages" + } + dir("$workDir/docker") { try { + git(url: "ssh://git@github.com/TRIQS/docker.git", branch: env.BRANCH_NAME, credentialsId: "ssh", changelog: false) + sh "echo '160000 commit ${commit}\t${projectName}' | git update-index --index-info" + sh """ + git commit --author='Flatiron Jenkins ' --allow-empty -m 'Autoupdate ${projectName}' -m '${env.BUILD_TAG}' + """ + // note: credentials used above don't work (need JENKINS-28335) + sh "git push origin ${env.BRANCH_NAME}" + } catch (err) { + echo "Failed to update docker repo" + } } + } } + } } } catch (err) { - emailext( + if (env.BRANCH_NAME != "jenkins") emailext( subject: "\$PROJECT_NAME - Build # \$BUILD_NUMBER - FAILED", body: """\$PROJECT_NAME - Build # \$BUILD_NUMBER - FAILED From f2d7e84bdddb272c5ead5fbd01f6c39a34e758d2 Mon Sep 17 00:00:00 2001 From: Nils Wentzell Date: Sun, 25 Mar 2018 19:00:54 +0200 Subject: [PATCH 005/272] Major update and Cleaning -consistent indends in all cmake files -add static analyzer checks with both cppcheck and clang-tidy -add dynamic analyzer checks with Address Sanitizer and option ASAN -add dynamic analyzer checks with Undefined Behavior Sanitizer and option UBSAN -Further Cleaning and Comments --- .clang-tidy | 1 + .travis.yml | 12 ++---- CMakeLists.txt | 12 +++--- c++/app4triqs/CMakeLists.txt | 71 ++++++++++++++++++++++++++++--- c++/app4triqs/toto.hpp | 19 +++++---- doc/CMakeLists.txt | 40 ++++++++--------- python/app4triqs/CMakeLists.txt | 2 +- share/CMakeLists.txt | 30 ++++++------- share/cmake/CMakeLists.txt | 8 ++-- share/cmake/Findlibasan_rt.cmake | 50 ++++++++++++++++++++++ share/cmake/Findlibubsan_rt.cmake | 50 ++++++++++++++++++++++ test/c++/CMakeLists.txt | 17 ++++++++ test/python/CMakeLists.txt | 6 ++- 13 files changed, 245 insertions(+), 73 deletions(-) create mode 100644 share/cmake/Findlibasan_rt.cmake create mode 100644 share/cmake/Findlibubsan_rt.cmake diff --git a/.clang-tidy b/.clang-tidy index 8103eae9..65767475 100644 --- a/.clang-tidy +++ b/.clang-tidy @@ -1 +1,2 @@ Checks: '-*,modernize-*,cppcoreguidelines-*' +HeaderFilterRegex: 'app4triqs' diff --git a/.travis.yml b/.travis.yml index 7ebf8f58..8ccba8e8 100644 --- a/.travis.yml +++ b/.travis.yml @@ -37,15 +37,11 @@ script: - make -j8 install - cd $TRAVIS_BUILD_DIR - source root_install/share/triqsvars.sh - # ===== Set up CTINT and Test using fsanitize=address + # ===== Set up CTINT and Test with Sanitizer Checks - mkdir build && cd build - - cmake .. -DCMAKE_BUILD_TYPE=Debug -DCMAKE_CXX_COMPILER=/usr/bin/${CXX} -DGTAU_IS_COMPLEX=ON -DINTERACTION_IS_COMPLEX=ON -DCMAKE_CXX_FLAGS='-fsanitize=address -fno-omit-frame-pointer -fuse-ld=gold -Wno-register -Wno-macro-redefined' - - make -j8 + - cmake .. -DCMAKE_BUILD_TYPE=Debug -DCMAKE_CXX_COMPILER=/usr/bin/${CXX} -DASAN=ON -DUBSAN=ON + - export UBSAN_SYMBOLIZER_PATH=/usr/lib/llvm-5.0/bin/llvm-symbolizer - export ASAN_SYMBOLIZER_PATH=/usr/lib/llvm-5.0/bin/llvm-symbolizer - export ASAN_OPTIONS=symbolize=1:detect_leaks=0 - export CTEST_OUTPUT_ON_FAILURE=1 - - cd test/c++ && ctest - - if [ "$CXX" = g++ ]; then export LD_PRELOAD=/usr/lib/gcc/x86_64-linux-gnu/7/libasan.so; elif [ "$CXX" = clang++ ]; then export LD_PRELOAD=/usr/lib/llvm-5.0/lib/clang/5.0.1/lib/linux/libclang_rt.asan-x86_64.so; fi - - cd ../python && ctest - - cd ../../ - - unset LD_PRELOAD + - make -j8 && make test diff --git a/CMakeLists.txt b/CMakeLists.txt index 854ebccb..cae84058 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -2,7 +2,7 @@ set(APP4TRIQS_VERSION "1.5") # Start configuration -cmake_minimum_required(VERSION 2.8) +cmake_minimum_required(VERSION 3.6) project(app4triqs CXX) # Default to Release build type @@ -14,13 +14,10 @@ message( STATUS "-------- BUILD-TYPE: ${CMAKE_BUILD_TYPE} --------") # Use shared libraries set(BUILD_SHARED_LIBS ON) -# Load TRIQS and Cpp2Py +# Load Dependencies find_package(TRIQS ${APP4TRIQS_VERSION} EXACT REQUIRED) find_package(Cpp2Py ${APP4TRIQS_VERSION} EXACT REQUIRED) -# We will need the FindNNFT of triqs, so we adjust CMake Module Path to find it -list(APPEND CMAKE_MODULE_PATH ${TRIQS_ROOT}/share/cmake) - # Default Install directory to TRIQS_ROOT if not given. Checks an absolute name is given. if(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT OR (NOT IS_ABSOLUTE ${CMAKE_INSTALL_PREFIX})) message(STATUS "No install prefix given (or invalid). Defaulting to TRIQS_ROOT") @@ -35,9 +32,12 @@ message(STATUS "app4triqs git hash: ${APP4TRIQS_GIT_HASH}") # Set up the rpath for compiled executable triqs_set_rpath_for_all_targets() +# Build and install the app4triqs library add_subdirectory(c++/app4triqs) + +# Build and install the app4triqs python module if(${TRIQS_WITH_PYTHON_SUPPORT}) - add_subdirectory(python/app4triqs) + add_subdirectory(python/app4triqs) endif() # Tests diff --git a/c++/app4triqs/CMakeLists.txt b/c++/app4triqs/CMakeLists.txt index fefb6564..70777499 100644 --- a/c++/app4triqs/CMakeLists.txt +++ b/c++/app4triqs/CMakeLists.txt @@ -1,20 +1,77 @@ -file(GLOB_RECURSE sources RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} *.cpp) +file(GLOB_RECURSE sources *.cpp *.hpp) add_library(app4triqs_c ${sources}) target_link_libraries(app4triqs_c PUBLIC triqs) target_compile_options(app4triqs_c PUBLIC -std=c++17) target_include_directories(app4triqs_c PUBLIC $) - target_compile_definitions(app4triqs_c PRIVATE APP4TRIQS_GIT_HASH=${APP4TRIQS_GIT_HASH} TRIQS_GIT_HASH=${TRIQS_GIT_HASH} - $<$:DEBUG_APP4TRIQS> + $<$:APP4TRIQS_DEBUG> $<$:TRIQS_ARRAYS_ENFORCE_BOUNDCHECK> - #$<$:MYOPTION> # Add compile definintions for option ) -# Install +# Install library and headers install(TARGETS app4triqs_c EXPORT app4triqs-targets DESTINATION lib) - -# If other applications need our headers, we can install them as well install(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} DESTINATION include FILES_MATCHING PATTERN "*.hpp" PATTERN "*.h") + + +# ========= Static Analyzer Checks ========== + +# Locate static analyzer tools +find_program(CPPCHECK_EXECUTABLE NAMES "cppcheck" PATHS ENV PATH) +find_program(CLANG_TIDY_EXECUTABLE NAMES "clang-tidy" PATHS ENV PATH) + +# Run clang-tidy if found +if(CLANG_TIDY_EXECUTABLE) + message(STATUS "clang-tidy found: ${CLANG_TIDY_EXECUTABLE}") + set_target_properties(app4triqs_c PROPERTIES CXX_CLANG_TIDY "${CLANG_TIDY_EXECUTABLE}") +else() + message(STATUS "clang-tidy not found in $PATH. Please consider installing clang-tidy for additional checks!") +endif() + +# Run cppcheck if found +if(CPPCHECK_EXECUTABLE) + message(STATUS "cppcheck found: ${CPPCHECK_EXECUTABLE}") + add_custom_command( + TARGET app4triqs_c + COMMAND echo "--- Running cppcheck ---\n" + COMMAND ${CPPCHECK_EXECUTABLE} + --enable=warning,style,performance,portability + --std=c++14 + --template=gcc + --verbose + --quiet + ${sources} + COMMAND echo "------------------------\n" + ) +else() + message(STATUS "cppcheck not found in $PATH. Please consider installing cppcheck for additional checks!") +endif() + + +# ========= Dynamic Analyzer Checks ========== + +# Address Sanitizer +option(ASAN OFF "Compile library and executables with LLVM Address Sanitizer") +if(ASAN) + if(${CMAKE_SYSTEM_NAME} MATCHES "Darwin") + message(FATAL_ERROR "Address Sanitizer Checks currently not compatible with OSX.") + endif() + list(APPEND CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/share/cmake) + find_package(libasan_rt REQUIRED) + target_compile_options(app4triqs_c PUBLIC -fsanitize=address -fno-omit-frame-pointer) + target_link_libraries(app4triqs_c INTERFACE "-fsanitize=address -fno-omit-frame-pointer") +endif() + +# Undefined Behavior Sanitizer +option(UBSAN OFF "Compile library and executables with LLVM Undefined Behavior Sanitizer") +if(UBSAN) + if(${CMAKE_SYSTEM_NAME} MATCHES "Darwin") + message(FATAL_ERROR "Undefined Behavior Sanitizer Checks currently not compatible with OSX.") + endif() + list(APPEND CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/share/cmake) + find_package(libubsan_rt REQUIRED) + target_compile_options(app4triqs_c PUBLIC -fsanitize=undefined -fno-omit-frame-pointer -fno-sanitize=vptr) + target_link_libraries(app4triqs_c INTERFACE "-fsanitize=undefined -fno-omit-frame-pointer") +endif() diff --git a/c++/app4triqs/toto.hpp b/c++/app4triqs/toto.hpp index 17c4df2b..44e6195b 100644 --- a/c++/app4triqs/toto.hpp +++ b/c++/app4triqs/toto.hpp @@ -14,20 +14,22 @@ namespace app4triqs { int i = 0.0; public: - toto() = default; - - // Copy construction - toto(toto const &) = default; - toto(toto &&) = default; + toto() = default; /** * Construct from integer * * @param i_ a scalar */ - toto(int i_) : i(i_) {} + explicit toto(int i_) : i(i_) {} - /// Copy assignment + ~toto() = default; + + // Copy/Move construction + toto(toto const &) = default; + toto(toto &&) = default; + + /// Copy/Move assignment toto &operator=(toto const &) = default; toto &operator=(toto &&) = default; @@ -45,7 +47,6 @@ namespace app4triqs { static std::string hdf5_scheme() { return "Toto"; } friend void h5_write(triqs::h5::group grp, std::string subgroup_name, toto const &m); - friend void h5_read(triqs::h5::group grp, std::string subgroup_name, toto &m); /// Serialization @@ -58,7 +59,7 @@ namespace app4triqs { * Chain the decimal digits of two integers i and j, and return the result * * @param :math:`i` The first integer - * @param :math:`j` The second integer + * @param :math:`j` The second integer * @return An integer containing the digits of both i and j * * @remark diff --git a/doc/CMakeLists.txt b/doc/CMakeLists.txt index 658139b9..24fccf0e 100644 --- a/doc/CMakeLists.txt +++ b/doc/CMakeLists.txt @@ -1,10 +1,9 @@ -# Generate the conf.py +# Generate the sphinx config file configure_file(${CMAKE_CURRENT_SOURCE_DIR}/conf.py.in ${CMAKE_CURRENT_BINARY_DIR}/conf.py @ONLY) # --------------------------------- # Top Sphinx target # --------------------------------- -# Sources file(GLOB_RECURSE sources *.rst) set(sphinx_top ${CMAKE_CURRENT_BINARY_DIR}/html/contents.html) @@ -20,48 +19,45 @@ add_dependencies(docs_sphinx app4triqs_c) # cp_rs is a script in cpp2py/bin, it mimics cp -rs on Linux # and filters the relevant extension # ------------------------------------------------------------------------------------------------ - set(EXT_FOR_DOC "rst png txt css_t conf css js gif jpg py html bib") execute_process(COMMAND cp_rs ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR} ${EXT_FOR_DOC}) # --------------------------------- # Generate C++ doc with c++2rst # --------------------------------- - add_custom_target(docs_cpp2rst) get_property(TRIQS_INCLUDE_DIRS TARGET triqs PROPERTY INTERFACE_INCLUDE_DIRECTORIES) get_property(APP4TRIQS_INCLUDE_DIRS TARGET app4triqs_c PROPERTY INTERFACE_INCLUDE_DIRECTORIES) - set(CPP2RST_INCLUDE_DIRS ${TRIQS_INCLUDE_DIRS} ${APP4TRIQS_INCLUDE_DIRS}) + foreach(I ${CPP2RST_INCLUDE_DIRS}) set (CPP2RST_INCLUDE_COMMAND ${CPP2RST_INCLUDE_COMMAND} --includes ${I}) endforeach() macro(generate_docs header_file) - add_custom_command (TARGET docs_cpp2rst - COMMAND c++2rst - ${header_file} - -N app4triqs - --output_directory ${CMAKE_CURRENT_BINARY_DIR}/cpp2rst_generated - ${CPP2RST_INCLUDE_COMMAND} - --cxxflags="-std=c++17" - -I ${CMAKE_SOURCE_DIR}/c++ - -I ${TRIQS_ROOT}/include - 2>&1 >> cpp2rst.log - ) + add_custom_command( + TARGET docs_cpp2rst + COMMAND c++2rst + ${header_file} + -N app4triqs + --output_directory ${CMAKE_CURRENT_BINARY_DIR}/cpp2rst_generated + ${CPP2RST_INCLUDE_COMMAND} + --cxxflags="-std=c++17" + -I ${CMAKE_SOURCE_DIR}/c++ + -I ${TRIQS_ROOT}/include + 2>&1 >> cpp2rst.log + ) endmacro(generate_docs) generate_docs(${CMAKE_SOURCE_DIR}/c++/app4triqs/toto.hpp) - add_dependencies(docs_sphinx docs_cpp2rst) # --------------------------------- # Install # --------------------------------- install(DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/html/ COMPONENT documentation DESTINATION share/doc/app4triqs - FILES_MATCHING - REGEX "\\.(html|pdf|png|gif|jpg|js|xsl|css|py|txt|inv|bib)$" - PATTERN "_*" - ) - + FILES_MATCHING + REGEX "\\.(html|pdf|png|gif|jpg|js|xsl|css|py|txt|inv|bib)$" + PATTERN "_*" +) diff --git a/python/app4triqs/CMakeLists.txt b/python/app4triqs/CMakeLists.txt index 2784e7ff..f7ec1c0c 100644 --- a/python/app4triqs/CMakeLists.txt +++ b/python/app4triqs/CMakeLists.txt @@ -12,7 +12,7 @@ configure_file(version.py.in version.py) # All Python files. Copy them in the build dir to have a complete package for the tests. set(PYTHON_SOURCES __init__.py) foreach(f ${PYTHON_SOURCES}) - configure_file(${f} ${f} COPYONLY) + configure_file(${f} ${f} COPYONLY) endforeach() # Install python module to proper location diff --git a/share/CMakeLists.txt b/share/CMakeLists.txt index c12791b6..961203f6 100644 --- a/share/CMakeLists.txt +++ b/share/CMakeLists.txt @@ -2,22 +2,22 @@ add_subdirectory(cmake) if(NOT CMAKE_INSTALL_PREFIX STREQUAL TRIQS_ROOT) - configure_file(app4triqs.modulefile.in app4triqs.modulefile @ONLY) - configure_file(app4triqsvars.sh.in app4triqsvars.sh @ONLY) + configure_file(app4triqs.modulefile.in app4triqs.modulefile @ONLY) + configure_file(app4triqsvars.sh.in app4triqsvars.sh @ONLY) - install( - FILES - ${CMAKE_CURRENT_BINARY_DIR}/app4triqs.modulefile - ${CMAKE_CURRENT_BINARY_DIR}/app4triqsvars.sh - DESTINATION share - ) + install( + FILES + ${CMAKE_CURRENT_BINARY_DIR}/app4triqs.modulefile + ${CMAKE_CURRENT_BINARY_DIR}/app4triqsvars.sh + DESTINATION share + ) - message(STATUS "***************************************************************") - message(STATUS "* Custom install Location. Use: ") - message(STATUS "* ") - message(STATUS "* source ${CMAKE_INSTALL_PREFIX}/share/app4triqsvars.sh ") - message(STATUS "* ") - message(STATUS "* to set up the environment variables ") - message(STATUS "***************************************************************") + message(STATUS "***************************************************************") + message(STATUS "* Custom install Location. Use: ") + message(STATUS "* ") + message(STATUS "* source ${CMAKE_INSTALL_PREFIX}/share/app4triqsvars.sh ") + message(STATUS "* ") + message(STATUS "* to set up the environment variables ") + message(STATUS "***************************************************************") endif() diff --git a/share/cmake/CMakeLists.txt b/share/cmake/CMakeLists.txt index 0ebacec0..80301486 100644 --- a/share/cmake/CMakeLists.txt +++ b/share/cmake/CMakeLists.txt @@ -1,10 +1,10 @@ configure_file(app4triqs-config.cmake.in app4triqs-config.cmake @ONLY) configure_file(app4triqs-config-version.cmake.in app4triqs-config-version.cmake @ONLY) install( - FILES - ${CMAKE_CURRENT_BINARY_DIR}/app4triqs-config.cmake - ${CMAKE_CURRENT_BINARY_DIR}/app4triqs-config-version.cmake - DESTINATION share/cmake + FILES + ${CMAKE_CURRENT_BINARY_DIR}/app4triqs-config.cmake + ${CMAKE_CURRENT_BINARY_DIR}/app4triqs-config-version.cmake + DESTINATION share/cmake ) install(EXPORT app4triqs-targets DESTINATION share/cmake) diff --git a/share/cmake/Findlibasan_rt.cmake b/share/cmake/Findlibasan_rt.cmake new file mode 100644 index 00000000..7e0c0f56 --- /dev/null +++ b/share/cmake/Findlibasan_rt.cmake @@ -0,0 +1,50 @@ +# Copyright Nils Wentzell 2018 +# Distributed under the GNU GENERAL PUBLIC LICENSE Version 3.0. +# See accompanying file LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt +# +# This cmake find module looks for the LLVM Address Sanitizer Runtime Library +# It sets up : ASAN_RT_LIBRARY + +# This module finds the LLVM Address Sanitizer Runtime Library +# latter case skip to the "Boost CMake" section below. For the former +# +# Use this module by invoking find_package with the form:: +# +# find_package(libasan_rt [REQUIRED]) +# +# Results are reported in:: +# +# ASAN_RT_LIBRARY Address Sanitizer Runtime Library + +if(${CMAKE_CXX_COMPILER_ID} STREQUAL "Clang") + set(name clang_rt.asan-x86_64) +elseif(${CMAKE_CXX_COMPILER_ID} STREQUAL "GNU") + set(name asan) +else() + message(FATAL_ERROR "LLVM Address Sanitizer is not available for your compiler") +endif() + +find_library(ASAN_RT_LIBRARY + NAMES ${name} + PATHS + ENV LIBRARY_PATH + ENV LD_INCLUDE_PATH + /usr/lib + /usr/local/lib + /usr/lib/gcc/*/* + /usr/lib/clang/*/lib/linux + /usr/lib/llvm-*/lib/clang/*/lib/linux + /usr/local/opt/llvm/lib/clang/*/lib/darwin +) + +mark_as_advanced(ASAN_RT_LIBRARY) + +# Imported target +add_library(libasan_rt SHARED IMPORTED) +set_property(TARGET libasan_rt PROPERTY IMPORTED_LOCATION ${ASAN_RT_LIBRARY}) + +include(FindPackageHandleStandardArgs) +find_package_handle_standard_args("Address Sanitizer Runtime Library" + REQUIRED_VARS ASAN_RT_LIBRARY + FAIL_MESSAGE "Address Sanitizer Runtime Libraries not found! Consider installing for additional checks!" +) diff --git a/share/cmake/Findlibubsan_rt.cmake b/share/cmake/Findlibubsan_rt.cmake new file mode 100644 index 00000000..a22990ae --- /dev/null +++ b/share/cmake/Findlibubsan_rt.cmake @@ -0,0 +1,50 @@ +# Copyright Nils Wentzell 2018 +# Distributed under the GNU GENERAL PUBLIC LICENSE Version 3.0. +# See accompanying file LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt +# +# This cmake find module looks for the LLVM Undefined Behavior Sanitizer Runtime Library +# It sets up : UBSAN_RT_LIBRARY + +# This module finds the LLVM Undefined Behavior Sanitizer Runtime Library +# latter case skip to the "Boost CMake" section below. For the former +# +# Use this module by invoking find_package with the form:: +# +# find_package(libubsan_rt [REQUIRED]) +# +# Results are reported in:: +# +# UBSAN_RT_LIBRARY Undefined Behavior Sanitizer Runtime Library + +if(${CMAKE_CXX_COMPILER_ID} STREQUAL "Clang") + set(name clang_rt.ubsan_standalone-x86_64) +elseif(${CMAKE_CXX_COMPILER_ID} STREQUAL "GNU") + set(name ubsan) +else() + message(FATAL_ERROR "Undefined Behavior Sanitizer is not available for your compiler") +endif() + +find_library(UBSAN_RT_LIBRARY + NAMES ${name} + PATHS + ENV LIBRARY_PATH + ENV LD_INCLUDE_PATH + /usr/lib + /usr/local/lib + /usr/lib/gcc/*/* + /usr/lib/clang/*/lib/linux + /usr/lib/llvm-*/lib/clang/*/lib/linux + /usr/local/opt/llvm/lib/clang/*/lib/darwin +) + +mark_as_advanced(UBSAN_RT_LIBRARY) + +# Imported target +add_library(libubsan_rt SHARED IMPORTED) +set_property(TARGET libubsan_rt PROPERTY IMPORTED_LOCATION ${UBSAN_RT_LIBRARY}) + +include(FindPackageHandleStandardArgs) +find_package_handle_standard_args("Undefined Behavior Sanitizer Runtime Library" + REQUIRED_VARS UBSAN_RT_LIBRARY + FAIL_MESSAGE "Undefined Behavior Sanitizer Runtime Libraries not found! Consider installing for additional checks!" +) diff --git a/test/c++/CMakeLists.txt b/test/c++/CMakeLists.txt index d3eb0202..3d81aa69 100644 --- a/test/c++/CMakeLists.txt +++ b/test/c++/CMakeLists.txt @@ -8,4 +8,21 @@ foreach(t ${all_tests}) add_executable(${t} ${CMAKE_CURRENT_SOURCE_DIR}/${t}.cpp) target_link_libraries(${t} app4triqs_c gtest) add_test(${t} ${CMAKE_CURRENT_BINARY_DIR}/${t}) + # Run clang-tidy if found + #if(CLANG_TIDY_EXECUTABLE) + #set_target_properties(${t} PROPERTIES CXX_CLANG_TIDY "${CLANG_TIDY_EXECUTABLE}") + #endif() + ## Run cppcheck if found + #if(CPPCHECK_EXECUTABLE) + #add_custom_command( + #TARGET ${t} + #COMMAND ${CPPCHECK_EXECUTABLE} + #--enable=warning,style,performance,portability + #--std=c++14 + #--template=gcc + #--verbose + #--quiet + #${CMAKE_CURRENT_SOURCE_DIR}/${t}.cpp + #) + #endif() endforeach() diff --git a/test/python/CMakeLists.txt b/test/python/CMakeLists.txt index 6864a634..6d7e7c44 100644 --- a/test/python/CMakeLists.txt +++ b/test/python/CMakeLists.txt @@ -9,4 +9,8 @@ foreach(t ${all_tests}) endforeach() # Set the PythonPath : put the build dir first (in case there is an installed version). -set_property(TEST ${all_tests} PROPERTY ENVIRONMENT PYTHONPATH=${CMAKE_BINARY_DIR}/python:$ENV{PYTHONPATH} ) +set_property(TEST ${all_tests} PROPERTY + ENVIRONMENT + PYTHONPATH=${CMAKE_BINARY_DIR}/python:$ENV{PYTHONPATH} + LD_PRELOAD=$<$:${ASAN_RT_LIBRARY}>:$<$:${UBSAN_RT_LIBRARY}> +) From 78ff2fb17806647bc83274dff396523e00960c9f Mon Sep 17 00:00:00 2001 From: Nils Wentzell Date: Sun, 25 Mar 2018 19:07:14 +0200 Subject: [PATCH 006/272] check clang travis build --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 8ccba8e8..a93b2bfd 100644 --- a/.travis.yml +++ b/.travis.yml @@ -5,7 +5,7 @@ dist: trusty compiler: - gcc - # - clang + - clang before_install: - sudo add-apt-repository 'deb http://apt.llvm.org/trusty/ llvm-toolchain-trusty-5.0 main' -y From f0b49145da40e5a7e7e491778ad071477de77c5d Mon Sep 17 00:00:00 2001 From: Nils Wentzell Date: Sun, 25 Mar 2018 19:38:25 +0200 Subject: [PATCH 007/272] Disable clang build and stronger restriction on clang tidy headers --- .clang-tidy | 2 +- .travis.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.clang-tidy b/.clang-tidy index 65767475..1d93efea 100644 --- a/.clang-tidy +++ b/.clang-tidy @@ -1,2 +1,2 @@ Checks: '-*,modernize-*,cppcoreguidelines-*' -HeaderFilterRegex: 'app4triqs' +HeaderFilterRegex: 'c++/app4triqs' diff --git a/.travis.yml b/.travis.yml index a93b2bfd..c1f93971 100644 --- a/.travis.yml +++ b/.travis.yml @@ -5,7 +5,7 @@ dist: trusty compiler: - gcc - - clang + #- clang before_install: - sudo add-apt-repository 'deb http://apt.llvm.org/trusty/ llvm-toolchain-trusty-5.0 main' -y From e3c4366d548d9dfa89997b26a9b09438dd570424 Mon Sep 17 00:00:00 2001 From: Nils Wentzell Date: Sun, 25 Mar 2018 19:57:55 +0200 Subject: [PATCH 008/272] Enable all compiler warnings, Include Triqs headers as SYSTEM, fix linker for sanitizers --- CMakeLists.txt | 7 +++++-- c++/app4triqs/CMakeLists.txt | 5 +++-- test/python/CMakeLists.txt | 2 +- 3 files changed, 9 insertions(+), 5 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index cae84058..58aabb33 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -14,11 +14,14 @@ message( STATUS "-------- BUILD-TYPE: ${CMAKE_BUILD_TYPE} --------") # Use shared libraries set(BUILD_SHARED_LIBS ON) +# Enable compiler warnings for the whole project +add_definitions(-Wall) + # Load Dependencies find_package(TRIQS ${APP4TRIQS_VERSION} EXACT REQUIRED) find_package(Cpp2Py ${APP4TRIQS_VERSION} EXACT REQUIRED) -# Default Install directory to TRIQS_ROOT if not given. Checks an absolute name is given. +# Default Install directory to TRIQS_ROOT if not given or invalid. if(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT OR (NOT IS_ABSOLUTE ${CMAKE_INSTALL_PREFIX})) message(STATUS "No install prefix given (or invalid). Defaulting to TRIQS_ROOT") set(CMAKE_INSTALL_PREFIX ${TRIQS_ROOT} CACHE PATH "default install path" FORCE) @@ -29,7 +32,7 @@ message(STATUS "-------- INSTALL_PREFIX: ${CMAKE_INSTALL_PREFIX} --------") triqs_get_git_hash_of_source_dir(APP4TRIQS_GIT_HASH) message(STATUS "app4triqs git hash: ${APP4TRIQS_GIT_HASH}") -# Set up the rpath for compiled executable +# Set up the rpath for all compiled executables triqs_set_rpath_for_all_targets() # Build and install the app4triqs library diff --git a/c++/app4triqs/CMakeLists.txt b/c++/app4triqs/CMakeLists.txt index 70777499..c6e0fb2d 100644 --- a/c++/app4triqs/CMakeLists.txt +++ b/c++/app4triqs/CMakeLists.txt @@ -4,6 +4,7 @@ add_library(app4triqs_c ${sources}) target_link_libraries(app4triqs_c PUBLIC triqs) target_compile_options(app4triqs_c PUBLIC -std=c++17) target_include_directories(app4triqs_c PUBLIC $) +target_include_directories(app4triqs_c SYSTEM PUBLIC ${TRIQS_ROOT}/include) target_compile_definitions(app4triqs_c PRIVATE APP4TRIQS_GIT_HASH=${APP4TRIQS_GIT_HASH} TRIQS_GIT_HASH=${TRIQS_GIT_HASH} @@ -61,7 +62,7 @@ if(ASAN) list(APPEND CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/share/cmake) find_package(libasan_rt REQUIRED) target_compile_options(app4triqs_c PUBLIC -fsanitize=address -fno-omit-frame-pointer) - target_link_libraries(app4triqs_c INTERFACE "-fsanitize=address -fno-omit-frame-pointer") + target_link_libraries(app4triqs_c INTERFACE "-fsanitize=address -fno-omit-frame-pointer -fuse-ld=gold") endif() # Undefined Behavior Sanitizer @@ -73,5 +74,5 @@ if(UBSAN) list(APPEND CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/share/cmake) find_package(libubsan_rt REQUIRED) target_compile_options(app4triqs_c PUBLIC -fsanitize=undefined -fno-omit-frame-pointer -fno-sanitize=vptr) - target_link_libraries(app4triqs_c INTERFACE "-fsanitize=undefined -fno-omit-frame-pointer") + target_link_libraries(app4triqs_c INTERFACE "-fsanitize=undefined -fno-omit-frame-pointer -fuse-ld=gold") endif() diff --git a/test/python/CMakeLists.txt b/test/python/CMakeLists.txt index 6d7e7c44..efdef3bd 100644 --- a/test/python/CMakeLists.txt +++ b/test/python/CMakeLists.txt @@ -8,7 +8,7 @@ foreach(t ${all_tests}) add_test(NAME ${t} COMMAND python ${CMAKE_CURRENT_SOURCE_DIR}/${t}.py) endforeach() -# Set the PythonPath : put the build dir first (in case there is an installed version). +# Set the PythonPath and the Sanitizer Library Preloads set_property(TEST ${all_tests} PROPERTY ENVIRONMENT PYTHONPATH=${CMAKE_BINARY_DIR}/python:$ENV{PYTHONPATH} From f65e5bfbad9d38f5c5101517fc089b5419be1ecc Mon Sep 17 00:00:00 2001 From: Nils Wentzell Date: Mon, 26 Mar 2018 00:31:39 +0200 Subject: [PATCH 009/272] Further cleanining, switching to static library -Disable LINTing in test macros with comment // NOLINT -Enable static analyzers for c++ tests -Switch app4triqs_c to static library Dynamic was pickung up previously installed libapp4triqs_c.so in tests Also there is no need to be dynamic for applications -Fix previous change in HeaderFilterRegex: 'app4triqs/c++' was blocking all headers for clang-tidy checks. 'app4triqs' works well, but we cannot install any other headers into app4triqs folder structure. We thus had to create INSTALL_DIR in travis.yml --- .clang-tidy | 2 +- .travis.yml | 17 ++++++++--------- CMakeLists.txt | 9 +++------ c++/app4triqs/CMakeLists.txt | 12 ++++++------ test/c++/CMakeLists.txt | 32 ++++++++++++++++---------------- test/c++/toto.cpp | 10 +++++----- test/python/Toto.py | 2 +- 7 files changed, 40 insertions(+), 44 deletions(-) diff --git a/.clang-tidy b/.clang-tidy index 1d93efea..65767475 100644 --- a/.clang-tidy +++ b/.clang-tidy @@ -1,2 +1,2 @@ Checks: '-*,modernize-*,cppcoreguidelines-*' -HeaderFilterRegex: 'c++/app4triqs' +HeaderFilterRegex: 'app4triqs' diff --git a/.travis.yml b/.travis.yml index c1f93971..876b4cab 100644 --- a/.travis.yml +++ b/.travis.yml @@ -21,25 +21,24 @@ before_install: install: true script: + - export INSTALL_DIR=$HOME/root_install # We should install outside the repository # ===== Set up Cpp2Py - git clone https://github.com/triqs/cpp2py - mkdir cpp2py/build && cd cpp2py/build - - git checkout master - - cmake .. -DCMAKE_CXX_COMPILER=/usr/bin/${CXX} -DPYTHON_INTERPRETER=/usr/bin/python -DCMAKE_INSTALL_PREFIX=$TRAVIS_BUILD_DIR/root_install + - cmake .. -DCMAKE_CXX_COMPILER=/usr/bin/${CXX} -DPYTHON_INTERPRETER=/usr/bin/python -DCMAKE_INSTALL_PREFIX=$INSTALL_DIR - make -j8 install - - cd $TRAVIS_BUILD_DIR - - source root_install/share/cpp2pyvars.sh + - source $INSTALL_DIR/share/cpp2pyvars.sh # ===== Set up TRIQS + - cd $TRAVIS_BUILD_DIR - git clone https://github.com/TRIQS/triqs --branch unstable - mkdir triqs/build && cd triqs/build - - git checkout unstable - - cmake .. -DCMAKE_CXX_COMPILER=/usr/bin/${CXX} -DBuild_Tests=OFF -DCMAKE_INSTALL_PREFIX=$TRAVIS_BUILD_DIR/root_install -DCMAKE_BUILD_TYPE=Debug + - cmake .. -DCMAKE_CXX_COMPILER=/usr/bin/${CXX} -DBuild_Tests=OFF -DCMAKE_INSTALL_PREFIX=$INSTALL_DIR - make -j8 install - - cd $TRAVIS_BUILD_DIR - - source root_install/share/triqsvars.sh + - source $INSTALL_DIR/share/triqsvars.sh # ===== Set up CTINT and Test with Sanitizer Checks + - cd $TRAVIS_BUILD_DIR - mkdir build && cd build - - cmake .. -DCMAKE_BUILD_TYPE=Debug -DCMAKE_CXX_COMPILER=/usr/bin/${CXX} -DASAN=ON -DUBSAN=ON + - cmake .. -DCMAKE_CXX_COMPILER=/usr/bin/${CXX} -DASAN=ON -DUBSAN=ON - export UBSAN_SYMBOLIZER_PATH=/usr/lib/llvm-5.0/bin/llvm-symbolizer - export ASAN_SYMBOLIZER_PATH=/usr/lib/llvm-5.0/bin/llvm-symbolizer - export ASAN_OPTIONS=symbolize=1:detect_leaks=0 diff --git a/CMakeLists.txt b/CMakeLists.txt index 58aabb33..886280b9 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -11,11 +11,11 @@ if(NOT CMAKE_BUILD_TYPE) endif() message( STATUS "-------- BUILD-TYPE: ${CMAKE_BUILD_TYPE} --------") -# Use shared libraries -set(BUILD_SHARED_LIBS ON) +# Build static libraries +set(BUILD_SHARED_LIBS OFF) # Enable compiler warnings for the whole project -add_definitions(-Wall) +add_definitions(-Wall -fPIC) # Load Dependencies find_package(TRIQS ${APP4TRIQS_VERSION} EXACT REQUIRED) @@ -32,9 +32,6 @@ message(STATUS "-------- INSTALL_PREFIX: ${CMAKE_INSTALL_PREFIX} --------") triqs_get_git_hash_of_source_dir(APP4TRIQS_GIT_HASH) message(STATUS "app4triqs git hash: ${APP4TRIQS_GIT_HASH}") -# Set up the rpath for all compiled executables -triqs_set_rpath_for_all_targets() - # Build and install the app4triqs library add_subdirectory(c++/app4triqs) diff --git a/c++/app4triqs/CMakeLists.txt b/c++/app4triqs/CMakeLists.txt index c6e0fb2d..92a6f4da 100644 --- a/c++/app4triqs/CMakeLists.txt +++ b/c++/app4triqs/CMakeLists.txt @@ -1,10 +1,12 @@ -file(GLOB_RECURSE sources *.cpp *.hpp) +file(GLOB_RECURSE sources *.cpp) add_library(app4triqs_c ${sources}) +# Link against triqs and use headers with SYSTEM flag for better warning messages target_link_libraries(app4triqs_c PUBLIC triqs) -target_compile_options(app4triqs_c PUBLIC -std=c++17) -target_include_directories(app4triqs_c PUBLIC $) target_include_directories(app4triqs_c SYSTEM PUBLIC ${TRIQS_ROOT}/include) + +target_compile_options(app4triqs_c PUBLIC -std=c++17 -fPIC) +target_include_directories(app4triqs_c PUBLIC $) target_compile_definitions(app4triqs_c PRIVATE APP4TRIQS_GIT_HASH=${APP4TRIQS_GIT_HASH} TRIQS_GIT_HASH=${TRIQS_GIT_HASH} @@ -36,7 +38,6 @@ if(CPPCHECK_EXECUTABLE) message(STATUS "cppcheck found: ${CPPCHECK_EXECUTABLE}") add_custom_command( TARGET app4triqs_c - COMMAND echo "--- Running cppcheck ---\n" COMMAND ${CPPCHECK_EXECUTABLE} --enable=warning,style,performance,portability --std=c++14 @@ -44,8 +45,7 @@ if(CPPCHECK_EXECUTABLE) --verbose --quiet ${sources} - COMMAND echo "------------------------\n" - ) + ) else() message(STATUS "cppcheck not found in $PATH. Please consider installing cppcheck for additional checks!") endif() diff --git a/test/c++/CMakeLists.txt b/test/c++/CMakeLists.txt index 3d81aa69..f6f8aad3 100644 --- a/test/c++/CMakeLists.txt +++ b/test/c++/CMakeLists.txt @@ -9,20 +9,20 @@ foreach(t ${all_tests}) target_link_libraries(${t} app4triqs_c gtest) add_test(${t} ${CMAKE_CURRENT_BINARY_DIR}/${t}) # Run clang-tidy if found - #if(CLANG_TIDY_EXECUTABLE) - #set_target_properties(${t} PROPERTIES CXX_CLANG_TIDY "${CLANG_TIDY_EXECUTABLE}") - #endif() - ## Run cppcheck if found - #if(CPPCHECK_EXECUTABLE) - #add_custom_command( - #TARGET ${t} - #COMMAND ${CPPCHECK_EXECUTABLE} - #--enable=warning,style,performance,portability - #--std=c++14 - #--template=gcc - #--verbose - #--quiet - #${CMAKE_CURRENT_SOURCE_DIR}/${t}.cpp - #) - #endif() + if(CLANG_TIDY_EXECUTABLE) + set_target_properties(${t} PROPERTIES CXX_CLANG_TIDY "${CLANG_TIDY_EXECUTABLE}") + endif() + # Run cppcheck if found + if(CPPCHECK_EXECUTABLE) + add_custom_command( + TARGET ${t} + COMMAND ${CPPCHECK_EXECUTABLE} + --enable=warning,style,performance,portability + --std=c++14 + --template=gcc + --verbose + --quiet + ${CMAKE_CURRENT_SOURCE_DIR}/${t}.cpp + ) + endif() endforeach() diff --git a/test/c++/toto.cpp b/test/c++/toto.cpp index 85779be7..a94b4946 100644 --- a/test/c++/toto.cpp +++ b/test/c++/toto.cpp @@ -3,16 +3,16 @@ using namespace app4triqs; -TEST(Toto, Add) { +TEST(Toto, Add) { // NOLINT toto a(0); toto b(2); auto c = a + b; - EXPECT_EQ(c, b); + EXPECT_EQ(c, b); // NOLINT } -TEST(Toto, H5) { +TEST(Toto, H5) { // NOLINT toto a(0); { // Local scope for file @@ -26,7 +26,7 @@ TEST(Toto, H5) { h5_read(f, "a", a2); } - EXPECT_EQ(a, a2); + EXPECT_EQ(a, a2); // NOLINT } -MAKE_MAIN; +MAKE_MAIN; // NOLINT diff --git a/test/python/Toto.py b/test/python/Toto.py index 52c9058d..744235f9 100644 --- a/test/python/Toto.py +++ b/test/python/Toto.py @@ -20,7 +20,7 @@ class test_toto(unittest.TestCase): def test_h5(self): a=Toto(0) - with HDFArchive("f.h5",'a') as A: + with HDFArchive("f.h5",'w') as A: A["a"] = a with HDFArchive("f.h5",'r') as A: a_read = A["a"] From 172b2da58f9538bd50b0a4eb8bb6d0cf1251a9e9 Mon Sep 17 00:00:00 2001 From: Dylan Simon Date: Mon, 26 Mar 2018 16:30:04 -0400 Subject: [PATCH 010/272] [jenkins] don't allow empty docker updates just fail and ignore --- Jenkinsfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Jenkinsfile b/Jenkinsfile index fc008598..d43268f8 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -103,7 +103,7 @@ try { git(url: "ssh://git@github.com/TRIQS/docker.git", branch: env.BRANCH_NAME, credentialsId: "ssh", changelog: false) sh "echo '160000 commit ${commit}\t${projectName}' | git update-index --index-info" sh """ - git commit --author='Flatiron Jenkins ' --allow-empty -m 'Autoupdate ${projectName}' -m '${env.BUILD_TAG}' + git commit --author='Flatiron Jenkins ' -m 'Autoupdate ${projectName}' -m '${env.BUILD_TAG}' """ // note: credentials used above don't work (need JENKINS-28335) sh "git push origin ${env.BRANCH_NAME}" From ed918caf40f96ca223c572c8dfce58f516b05911 Mon Sep 17 00:00:00 2001 From: Nils Wentzell Date: Tue, 27 Mar 2018 13:54:10 +0200 Subject: [PATCH 011/272] remove cpp2py header include --- c++/app4triqs/toto.hpp | 1 - 1 file changed, 1 deletion(-) diff --git a/c++/app4triqs/toto.hpp b/c++/app4triqs/toto.hpp index 44e6195b..c62393ea 100644 --- a/c++/app4triqs/toto.hpp +++ b/c++/app4triqs/toto.hpp @@ -1,5 +1,4 @@ #pragma once -#include #include namespace app4triqs { From afd3ae12f2661286cf857908f0b924206fa31b21 Mon Sep 17 00:00:00 2001 From: Nils Wentzell Date: Wed, 28 Mar 2018 10:59:05 +0200 Subject: [PATCH 012/272] updating README with instructions --- README.md | 28 +++++++++++++++++++++++++++- 1 file changed, 27 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 57a6a1e4..64b4af2f 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,28 @@ # app4triqs -An example application using cpp2py and triqs. + +An example application using cpp2py and triqs +--------------------------------------------- + +To use this skeleton for a new triqs application, the following steps are necessary: + +* Create a repository, e.g. https://github.com/myuser/mynewapp + +* Run the following commands (replacing myuser and mynewapp accordingly) + +```bash +git clone https://github.com/triqs/app4triqs --branch unstable mynewapp +cd mynewapp +git remote set-url https://github.com/myuser/mynewapp +find . -type f | grep -v .git | xargs sed -i 's/app4triqs/mynewapp/g; s/APP4TRIQS/MYNEWAPP/g' +find . | grep -v .git | xargs rename app4triqs mytriqsapp +git add -A +git commit -m "Create mynewapp from github.com/triqs/app4triqs skeleton" +git push +``` + +If you prefer to use the SSH interface to the remote repository, +replace the http link accordingly + +``` +https://github.com/myuser/mynewapp --> git@github.com:myuser/mynewapp +``` From d8f6932888135c0dd5523394e8d7bc19ae06012b Mon Sep 17 00:00:00 2001 From: Nils Wentzell Date: Fri, 6 Apr 2018 14:35:21 +0200 Subject: [PATCH 013/272] Make static analyzers optional --- c++/app4triqs/CMakeLists.txt | 51 ++++++++++++++++++++---------------- 1 file changed, 28 insertions(+), 23 deletions(-) diff --git a/c++/app4triqs/CMakeLists.txt b/c++/app4triqs/CMakeLists.txt index 92a6f4da..2674e7a9 100644 --- a/c++/app4triqs/CMakeLists.txt +++ b/c++/app4triqs/CMakeLists.txt @@ -21,33 +21,38 @@ install(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} DESTINATION include FILES_MATCHING # ========= Static Analyzer Checks ========== -# Locate static analyzer tools -find_program(CPPCHECK_EXECUTABLE NAMES "cppcheck" PATHS ENV PATH) -find_program(CLANG_TIDY_EXECUTABLE NAMES "clang-tidy" PATHS ENV PATH) +option(ANALYZE_SOURCES OFF "Run static analyzer checks if found (clang-tidy, cppcheck)") +if(ANALYZE_SOURCES) -# Run clang-tidy if found -if(CLANG_TIDY_EXECUTABLE) - message(STATUS "clang-tidy found: ${CLANG_TIDY_EXECUTABLE}") - set_target_properties(app4triqs_c PROPERTIES CXX_CLANG_TIDY "${CLANG_TIDY_EXECUTABLE}") -else() - message(STATUS "clang-tidy not found in $PATH. Please consider installing clang-tidy for additional checks!") -endif() + # Locate static analyzer tools + find_program(CPPCHECK_EXECUTABLE NAMES "cppcheck" PATHS ENV PATH) + find_program(CLANG_TIDY_EXECUTABLE NAMES "clang-tidy" PATHS ENV PATH) -# Run cppcheck if found -if(CPPCHECK_EXECUTABLE) - message(STATUS "cppcheck found: ${CPPCHECK_EXECUTABLE}") - add_custom_command( + # Run clang-tidy if found + if(CLANG_TIDY_EXECUTABLE) + message(STATUS "clang-tidy found: ${CLANG_TIDY_EXECUTABLE}") + set_target_properties(app4triqs_c PROPERTIES CXX_CLANG_TIDY "${CLANG_TIDY_EXECUTABLE}") + else() + message(STATUS "clang-tidy not found in $PATH. Please consider installing clang-tidy for additional checks!") + endif() + + # Run cppcheck if found + if(CPPCHECK_EXECUTABLE) + message(STATUS "cppcheck found: ${CPPCHECK_EXECUTABLE}") + add_custom_command( TARGET app4triqs_c COMMAND ${CPPCHECK_EXECUTABLE} - --enable=warning,style,performance,portability - --std=c++14 - --template=gcc - --verbose - --quiet - ${sources} - ) -else() - message(STATUS "cppcheck not found in $PATH. Please consider installing cppcheck for additional checks!") + --enable=warning,style,performance,portability + --std=c++14 + --template=gcc + --verbose + --quiet + ${sources} + ) + else() + message(STATUS "cppcheck not found in $PATH. Please consider installing cppcheck for additional checks!") + endif() + endif() From ee1e563c82db95e0b72dbd015f69366fb8959b40 Mon Sep 17 00:00:00 2001 From: Nils Wentzell Date: Fri, 6 Apr 2018 14:36:32 +0200 Subject: [PATCH 014/272] Lowering cmake version requirement, removing fPIC global flag --- CMakeLists.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 886280b9..f45b10fc 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -2,7 +2,7 @@ set(APP4TRIQS_VERSION "1.5") # Start configuration -cmake_minimum_required(VERSION 3.6) +cmake_minimum_required(VERSION 2.8.12) project(app4triqs CXX) # Default to Release build type @@ -15,7 +15,7 @@ message( STATUS "-------- BUILD-TYPE: ${CMAKE_BUILD_TYPE} --------") set(BUILD_SHARED_LIBS OFF) # Enable compiler warnings for the whole project -add_definitions(-Wall -fPIC) +add_definitions(-Wall) # Load Dependencies find_package(TRIQS ${APP4TRIQS_VERSION} EXACT REQUIRED) From c6a0079b89faf8e0e74f4ccc9615432c63d4d1e8 Mon Sep 17 00:00:00 2001 From: Nils Wentzell Date: Fri, 6 Apr 2018 15:10:42 +0200 Subject: [PATCH 015/272] travis update to llvm7 and xenial --- .travis.yml | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/.travis.yml b/.travis.yml index 876b4cab..09ecd2f9 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,22 +1,22 @@ language: cpp sudo: required -dist: trusty +dist: xenial compiler: - gcc #- clang before_install: - - sudo add-apt-repository 'deb http://apt.llvm.org/trusty/ llvm-toolchain-trusty-5.0 main' -y + - sudo add-apt-repository 'deb http://apt.llvm.org/xenial/ llvm-toolchain-xenial main' -y - wget -O - https://apt.llvm.org/llvm-snapshot.gpg.key|sudo apt-key add - - sudo add-apt-repository ppa:ubuntu-toolchain-r/test -y - sudo apt-get update - - sudo apt-get install -y --allow-unauthenticated g++-7 clang-5.0 - - export LIBRARY_PATH=/usr/lib/llvm-5.0/lib:$LIBRARY_PATH + - sudo apt-get install -y --allow-unauthenticated g++-7 clang-7 + - export LIBRARY_PATH=/usr/lib/llvm-7/lib:$LIBRARY_PATH - sudo update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-7 60 --slave /usr/bin/g++ g++ /usr/bin/g++-7 - - sudo update-alternatives --install /usr/bin/clang clang /usr/bin/clang-5.0 60 --slave /usr/bin/clang++ clang++ /usr/bin/clang++-5.0 - - sudo apt-get install -y --allow-unauthenticated libboost-all-dev cmake git libgfortran3 gfortran openmpi-bin openmpi-common openmpi-doc libopenmpi-dev libblas-dev liblapack-dev libfftw3-dev libgmp-dev hdf5-tools libhdf5-serial-dev python-h5py python-dev python-numpy python-scipy python-jinja2 python-virtualenv python-matplotlib python-tornado python-zmq python-mpi4py python-mako clang-format-5.0 libclang-5.0-dev python-clang-5.0 python-sphinx libjs-mathjax valgrind libnfft3-dev + - sudo update-alternatives --install /usr/bin/clang clang /usr/bin/clang-7 60 --slave /usr/bin/clang++ clang++ /usr/bin/clang++-7 + - sudo apt-get install -y --allow-unauthenticated libboost-all-dev cmake git libgfortran3 gfortran openmpi-bin openmpi-common openmpi-doc libopenmpi-dev libblas-dev liblapack-dev libfftw3-dev libgmp-dev hdf5-tools libhdf5-serial-dev python-h5py python-dev python-numpy python-scipy python-jinja2 python-virtualenv python-matplotlib python-tornado python-zmq python-mpi4py python-mako clang-format-7 libclang-7-dev python-clang-7 python-sphinx libjs-mathjax valgrind libnfft3-dev install: true @@ -35,12 +35,12 @@ script: - cmake .. -DCMAKE_CXX_COMPILER=/usr/bin/${CXX} -DBuild_Tests=OFF -DCMAKE_INSTALL_PREFIX=$INSTALL_DIR - make -j8 install - source $INSTALL_DIR/share/triqsvars.sh - # ===== Set up CTINT and Test with Sanitizer Checks + # ===== Set up app4triqs and test - cd $TRAVIS_BUILD_DIR - mkdir build && cd build - cmake .. -DCMAKE_CXX_COMPILER=/usr/bin/${CXX} -DASAN=ON -DUBSAN=ON - - export UBSAN_SYMBOLIZER_PATH=/usr/lib/llvm-5.0/bin/llvm-symbolizer - - export ASAN_SYMBOLIZER_PATH=/usr/lib/llvm-5.0/bin/llvm-symbolizer + - export UBSAN_SYMBOLIZER_PATH=/usr/lib/llvm-7/bin/llvm-symbolizer + - export ASAN_SYMBOLIZER_PATH=/usr/lib/llvm-7/bin/llvm-symbolizer - export ASAN_OPTIONS=symbolize=1:detect_leaks=0 - export CTEST_OUTPUT_ON_FAILURE=1 - make -j8 && make test From 51368b1d66536be9ce81c5643fbda3d6e5ec2643 Mon Sep 17 00:00:00 2001 From: Dylan Simon Date: Fri, 6 Apr 2018 11:27:06 -0400 Subject: [PATCH 016/272] [jenkins] more comments and explanation --- Jenkinsfile | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/Jenkinsfile b/Jenkinsfile index d43268f8..04ad7484 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -1,7 +1,11 @@ -def projectName = "app4triqs" +def projectName = "app4triqs" /* set to app/repo name */ + +/* which platform to build documentation on */ def documentationPlatform = "ubuntu-clang" +/* depend on triqs upstream branch/project */ def triqsBranch = env.CHANGE_TARGET ?: env.BRANCH_NAME def triqsProject = '/TRIQS/triqs/' + triqsBranch.replaceAll('/', '%2F') +/* whether to publish the results (disabled for template project) */ def publish = !env.BRANCH_NAME.startsWith("PR-") && projectName != "app4triqs" properties([ @@ -18,6 +22,8 @@ properties([ /* map of all builds to run, populated below */ def platforms = [:] +/****************** linux builds (in docker) */ +/* Each platform must have a cooresponding Dockerfile.PLATFORM in triqs/packaging */ def dockerPlatforms = ["ubuntu-clang", "ubuntu-gcc", "centos-gcc"] /* .each is currently broken in jenkins */ for (int i = 0; i < dockerPlatforms.size(); i++) { @@ -40,6 +46,7 @@ for (int i = 0; i < dockerPlatforms.size(); i++) { } } } +/****************** osx builds (on host) */ def osxPlatforms = [ ["gcc", ['CC=gcc-7', 'CXX=g++-7']], ["clang", ['CC=/usr/local/opt/llvm/bin/clang', 'CXX=/usr/local/opt/llvm/bin/clang++', 'CXXFLAGS=-I/usr/local/opt/llvm/include', 'LDFLAGS=-L/usr/local/opt/llvm/lib']] @@ -79,12 +86,15 @@ for (int i = 0; i < osxPlatforms.size(); i++) { } } } +/****************** wrap-up */ try { parallel platforms if (publish) { node("docker") { + /* Publish results */ stage("publish") { timeout(time: 1, unit: 'HOURS') { def commit = sh(returnStdout: true, script: "git rev-parse HEAD").trim() def workDir = pwd() + /* Update documention on gh-pages branch */ dir("$workDir/gh-pages") { def subdir = env.BRANCH_NAME git(url: "ssh://git@github.com/TRIQS/${projectName}.git", branch: "gh-pages", credentialsId: "ssh", changelog: false) @@ -99,6 +109,7 @@ try { // note: credentials used above don't work (need JENKINS-28335) sh "git push origin gh-pages" } + /* Update docker repo submodule */ dir("$workDir/docker") { try { git(url: "ssh://git@github.com/TRIQS/docker.git", branch: env.BRANCH_NAME, credentialsId: "ssh", changelog: false) sh "echo '160000 commit ${commit}\t${projectName}' | git update-index --index-info" @@ -108,11 +119,13 @@ try { // note: credentials used above don't work (need JENKINS-28335) sh "git push origin ${env.BRANCH_NAME}" } catch (err) { + /* Ignore, non-critical -- might not exist on this branch */ echo "Failed to update docker repo" } } } } } } } catch (err) { + /* send email on build failure (declarative pipeline's post section would work better) */ if (env.BRANCH_NAME != "jenkins") emailext( subject: "\$PROJECT_NAME - Build # \$BUILD_NUMBER - FAILED", body: """\$PROJECT_NAME - Build # \$BUILD_NUMBER - FAILED From 907f469bab89628facc1beaabf287b0a1a087b5b Mon Sep 17 00:00:00 2001 From: Dylan Simon Date: Fri, 6 Apr 2018 11:29:06 -0400 Subject: [PATCH 017/272] [jenkins] Remove hard-coded app name from Dockerfile --- Dockerfile | 2 +- Jenkinsfile | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Dockerfile b/Dockerfile index cc505119..560ce4ef 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,7 +1,7 @@ # See ../triqs/packaging for other options FROM flatironinstitute/triqs:master-ubuntu-clang -ARG APPNAME=app4triqs +ARG APPNAME COPY . $SRC/$APPNAME WORKDIR $BUILD/$APPNAME RUN chown build . diff --git a/Jenkinsfile b/Jenkinsfile index 04ad7484..1d8bb2d3 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -37,7 +37,7 @@ for (int i = 0; i < dockerPlatforms.size(); i++) { mv -f Dockerfile.jenkins Dockerfile """ /* build and tag */ - def img = docker.build("flatironinstitute/${projectName}:${env.BRANCH_NAME}-${env.STAGE_NAME}", "--build-arg BUILD_DOC=${platform==documentationPlatform} .") + def img = docker.build("flatironinstitute/${projectName}:${env.BRANCH_NAME}-${env.STAGE_NAME}", "--build-arg APPNAME=${projectName} --build-arg BUILD_DOC=${platform==documentationPlatform} .") if (!publish || platform != documentationPlatform) { /* but we don't need the tag so clean it up (except for documentation) */ sh "docker rmi --no-prune ${img.imageName()}" From 3174a27c703ecfd3b5344ecb2c40f558cb646fd8 Mon Sep 17 00:00:00 2001 From: Dylan Simon Date: Fri, 6 Apr 2018 11:37:30 -0400 Subject: [PATCH 018/272] [jenkins] Add CPP2RST_INCLUDE_DIRS hack for docs --- Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index 560ce4ef..4a7dd330 100644 --- a/Dockerfile +++ b/Dockerfile @@ -7,6 +7,6 @@ WORKDIR $BUILD/$APPNAME RUN chown build . USER build ARG BUILD_DOC=0 -RUN cmake $SRC/$APPNAME -DTRIQS_ROOT=${INSTALL} -DBuild_Documentation=${BUILD_DOC} && make -j2 && make test +RUN cmake $SRC/$APPNAME -DTRIQS_ROOT=${INSTALL} -DBuild_Documentation=${BUILD_DOC} -DCPP2RST_INCLUDE_DIRS=--includes=/usr/lib/llvm-${LLVM}/include/c++/v1 && make -j2 && make test USER root RUN make install From 27cfe25967058504fab37cbe320a3c027612aa9a Mon Sep 17 00:00:00 2001 From: Dylan Simon Date: Fri, 6 Apr 2018 11:43:10 -0400 Subject: [PATCH 019/272] [jenkins] Use CPP2RST_INCLUDE_COMMAND instead --- Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index 4a7dd330..39978459 100644 --- a/Dockerfile +++ b/Dockerfile @@ -7,6 +7,6 @@ WORKDIR $BUILD/$APPNAME RUN chown build . USER build ARG BUILD_DOC=0 -RUN cmake $SRC/$APPNAME -DTRIQS_ROOT=${INSTALL} -DBuild_Documentation=${BUILD_DOC} -DCPP2RST_INCLUDE_DIRS=--includes=/usr/lib/llvm-${LLVM}/include/c++/v1 && make -j2 && make test +RUN cmake $SRC/$APPNAME -DTRIQS_ROOT=${INSTALL} -DBuild_Documentation=${BUILD_DOC} -DCPP2RST_INCLUDE_COMMAND=--includes=/usr/lib/llvm-${LLVM}/include/c++/v1 && make -j2 && make test USER root RUN make install From 364c99d2924a0bcc246158ac64259171916be387 Mon Sep 17 00:00:00 2001 From: Dylan Simon Date: Fri, 6 Apr 2018 11:55:25 -0400 Subject: [PATCH 020/272] [jenkins] expand LLVM arg Doesn't propagate from parent image --- Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index 39978459..87991393 100644 --- a/Dockerfile +++ b/Dockerfile @@ -7,6 +7,6 @@ WORKDIR $BUILD/$APPNAME RUN chown build . USER build ARG BUILD_DOC=0 -RUN cmake $SRC/$APPNAME -DTRIQS_ROOT=${INSTALL} -DBuild_Documentation=${BUILD_DOC} -DCPP2RST_INCLUDE_COMMAND=--includes=/usr/lib/llvm-${LLVM}/include/c++/v1 && make -j2 && make test +RUN cmake $SRC/$APPNAME -DTRIQS_ROOT=${INSTALL} -DBuild_Documentation=${BUILD_DOC} -DCPP2RST_INCLUDE_COMMAND=--includes=/usr/lib/llvm-5.0/include/c++/v1 && make -j2 && make test USER root RUN make install From e8a14a340648d415d4e93e2a6c0b8f69b982a12e Mon Sep 17 00:00:00 2001 From: Dylan Simon Date: Tue, 10 Apr 2018 12:01:37 -0400 Subject: [PATCH 021/272] [jenkins] Remove unnecessary CPP2RST_INCLUDE flags Fixed by cpp2py build in triqs efd7b0f7d855a0b5ae260d0fd7a6031cec068072 --- Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index 87991393..560ce4ef 100644 --- a/Dockerfile +++ b/Dockerfile @@ -7,6 +7,6 @@ WORKDIR $BUILD/$APPNAME RUN chown build . USER build ARG BUILD_DOC=0 -RUN cmake $SRC/$APPNAME -DTRIQS_ROOT=${INSTALL} -DBuild_Documentation=${BUILD_DOC} -DCPP2RST_INCLUDE_COMMAND=--includes=/usr/lib/llvm-5.0/include/c++/v1 && make -j2 && make test +RUN cmake $SRC/$APPNAME -DTRIQS_ROOT=${INSTALL} -DBuild_Documentation=${BUILD_DOC} && make -j2 && make test USER root RUN make install From 82b10c1983070f5017d360e410e51086dac2130e Mon Sep 17 00:00:00 2001 From: Nils Wentzell Date: Tue, 24 Apr 2018 22:23:44 +0200 Subject: [PATCH 022/272] [travis] avoid apt-get install failure, add ubsan options --- .travis.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.travis.yml b/.travis.yml index 09ecd2f9..3499b5af 100644 --- a/.travis.yml +++ b/.travis.yml @@ -12,6 +12,7 @@ before_install: - wget -O - https://apt.llvm.org/llvm-snapshot.gpg.key|sudo apt-key add - - sudo add-apt-repository ppa:ubuntu-toolchain-r/test -y - sudo apt-get update + - sudo rm -f /var/lib/apt/lists/lock /var/cache/apt/archives/lock /var/lib/dpkg/lock # Avoid the occasional apt-get install failure for xenial image - sudo apt-get install -y --allow-unauthenticated g++-7 clang-7 - export LIBRARY_PATH=/usr/lib/llvm-7/lib:$LIBRARY_PATH - sudo update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-7 60 --slave /usr/bin/g++ g++ /usr/bin/g++-7 @@ -41,6 +42,7 @@ script: - cmake .. -DCMAKE_CXX_COMPILER=/usr/bin/${CXX} -DASAN=ON -DUBSAN=ON - export UBSAN_SYMBOLIZER_PATH=/usr/lib/llvm-7/bin/llvm-symbolizer - export ASAN_SYMBOLIZER_PATH=/usr/lib/llvm-7/bin/llvm-symbolizer + - export UBSAN_OPTIONS=symbolize=1:print_stacktrace=1 - export ASAN_OPTIONS=symbolize=1:detect_leaks=0 - export CTEST_OUTPUT_ON_FAILURE=1 - make -j8 && make test From 6aa4eee0f47b460f9863a8cba602fc3166d35a42 Mon Sep 17 00:00:00 2001 From: Nils Wentzell Date: Tue, 24 Apr 2018 23:31:52 +0200 Subject: [PATCH 023/272] [cmake] Fixing usage of ubsan with Minimal RT, some cleaning - Use UBsan Minimal RT if found - Prioritize gcc-7 directories over older - Set UBSan options for c++/python tests --- share/cmake/Findlibasan_rt.cmake | 1 + share/cmake/Findlibubsan_rt.cmake | 33 +++++++++++++++++++++---------- test/c++/CMakeLists.txt | 6 ++++++ test/python/CMakeLists.txt | 8 +++++++- 4 files changed, 37 insertions(+), 11 deletions(-) diff --git a/share/cmake/Findlibasan_rt.cmake b/share/cmake/Findlibasan_rt.cmake index 7e0c0f56..60828a3a 100644 --- a/share/cmake/Findlibasan_rt.cmake +++ b/share/cmake/Findlibasan_rt.cmake @@ -31,6 +31,7 @@ find_library(ASAN_RT_LIBRARY ENV LD_INCLUDE_PATH /usr/lib /usr/local/lib + /usr/lib/gcc/*/7 /usr/lib/gcc/*/* /usr/lib/clang/*/lib/linux /usr/lib/llvm-*/lib/clang/*/lib/linux diff --git a/share/cmake/Findlibubsan_rt.cmake b/share/cmake/Findlibubsan_rt.cmake index a22990ae..8b6dc7e5 100644 --- a/share/cmake/Findlibubsan_rt.cmake +++ b/share/cmake/Findlibubsan_rt.cmake @@ -14,7 +14,20 @@ # # Results are reported in:: # -# UBSAN_RT_LIBRARY Undefined Behavior Sanitizer Runtime Library +# UBSAN_RT_LIBRARY Undefined Behavior Sanitizer Runtime Library +# [UBSAN_MINIMAL_RT_LIBRARY] Minimal version of UBSan Runtime, To be used in combination with Asan + +set(TRIAL_PATHS + ENV LIBRARY_PATH + ENV LD_INCLUDE_PATH + /usr/lib + /usr/local/lib + /usr/lib/gcc/7/* + /usr/lib/gcc/*/* + /usr/lib/clang/*/lib/linux + /usr/lib/llvm-*/lib/clang/*/lib/linux + /usr/local/opt/llvm/lib/clang/*/lib/darwin +) if(${CMAKE_CXX_COMPILER_ID} STREQUAL "Clang") set(name clang_rt.ubsan_standalone-x86_64) @@ -26,17 +39,17 @@ endif() find_library(UBSAN_RT_LIBRARY NAMES ${name} - PATHS - ENV LIBRARY_PATH - ENV LD_INCLUDE_PATH - /usr/lib - /usr/local/lib - /usr/lib/gcc/*/* - /usr/lib/clang/*/lib/linux - /usr/lib/llvm-*/lib/clang/*/lib/linux - /usr/local/opt/llvm/lib/clang/*/lib/darwin + PATHS ${TRIAL_PATHS} ) +# Try to find UBSan Minimal Runtime for Clang +if(${CMAKE_CXX_COMPILER_ID} STREQUAL "Clang") + find_library(UBSAN_MINIMAL_RT_LIBRARY + NAMES clang_rt.ubsan_minimal-x86_64 + PATHS ${TRIAL_PATHS} + ) +endif() + mark_as_advanced(UBSAN_RT_LIBRARY) # Imported target diff --git a/test/c++/CMakeLists.txt b/test/c++/CMakeLists.txt index f6f8aad3..b445b900 100644 --- a/test/c++/CMakeLists.txt +++ b/test/c++/CMakeLists.txt @@ -26,3 +26,9 @@ foreach(t ${all_tests}) ) endif() endforeach() + +# Set UBSan Options for all tests +set_property(TEST ${all_tests} PROPERTY + ENVIRONMENT + UBSAN_OPTIONS=print_stacktrace=1:halt_on_error=1 +) diff --git a/test/python/CMakeLists.txt b/test/python/CMakeLists.txt index efdef3bd..c1241802 100644 --- a/test/python/CMakeLists.txt +++ b/test/python/CMakeLists.txt @@ -8,9 +8,15 @@ foreach(t ${all_tests}) add_test(NAME ${t} COMMAND python ${CMAKE_CURRENT_SOURCE_DIR}/${t}.py) endforeach() -# Set the PythonPath and the Sanitizer Library Preloads +# If ASAN=ON use minimal runtime of UBSAN if it exists +if(${ASAN} AND UBSAN_MINIMAL_RT_LIBRARY) + set(UBSAN_RT_LIBRARY ${UBSAN_MINIMAL_RT_LIBRARY}) +endif() + +# Set the PythonPath, Sanitizer Library Preloads and UBSan Options for all tests set_property(TEST ${all_tests} PROPERTY ENVIRONMENT PYTHONPATH=${CMAKE_BINARY_DIR}/python:$ENV{PYTHONPATH} LD_PRELOAD=$<$:${ASAN_RT_LIBRARY}>:$<$:${UBSAN_RT_LIBRARY}> + UBSAN_OPTIONS=print_stacktrace=1:halt_on_error=1 ) From 6be41fb47a1efb74ff08cf8d013a8f9be001aea9 Mon Sep 17 00:00:00 2001 From: Nils Wentzell Date: Tue, 24 Apr 2018 23:59:32 +0200 Subject: [PATCH 024/272] [cmake] Prepend UBSan options to Env --- test/c++/CMakeLists.txt | 2 +- test/python/CMakeLists.txt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/test/c++/CMakeLists.txt b/test/c++/CMakeLists.txt index b445b900..012d07d1 100644 --- a/test/c++/CMakeLists.txt +++ b/test/c++/CMakeLists.txt @@ -30,5 +30,5 @@ endforeach() # Set UBSan Options for all tests set_property(TEST ${all_tests} PROPERTY ENVIRONMENT - UBSAN_OPTIONS=print_stacktrace=1:halt_on_error=1 + UBSAN_OPTIONS=print_stacktrace=1:halt_on_error=1:$ENV{UBSAN_OPTIONS} ) diff --git a/test/python/CMakeLists.txt b/test/python/CMakeLists.txt index c1241802..624768f4 100644 --- a/test/python/CMakeLists.txt +++ b/test/python/CMakeLists.txt @@ -18,5 +18,5 @@ set_property(TEST ${all_tests} PROPERTY ENVIRONMENT PYTHONPATH=${CMAKE_BINARY_DIR}/python:$ENV{PYTHONPATH} LD_PRELOAD=$<$:${ASAN_RT_LIBRARY}>:$<$:${UBSAN_RT_LIBRARY}> - UBSAN_OPTIONS=print_stacktrace=1:halt_on_error=1 + UBSAN_OPTIONS=print_stacktrace=1:halt_on_error=1:$ENV{UBSAN_OPTIONS} ) From 51345aff2d3dc3ee07ddc00bea55d27d50219530 Mon Sep 17 00:00:00 2001 From: Dylan Simon Date: Mon, 14 May 2018 15:26:28 -0400 Subject: [PATCH 025/272] [cmake] Add BUILD_DEBIAN_PACKAGE option and rules --- CMakeLists.txt | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index f45b10fc..15f80ea0 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -55,3 +55,16 @@ if(${Build_Documentation}) add_subdirectory(doc) endif() endif() + +option(BUILD_DEBIAN_PACKAGE "Build a deb package" OFF) +if(BUILD_DEBIAN_PACKAGE) + if(NOT CMAKE_INSTALL_PREFIX STREQUAL "/usr") + message(FATAL_ERROR "CMAKE_INSTALL_PREFIX must be /usr for packaging") + endif() + SET(CPACK_GENERATOR "DEB") + SET(CPACK_PACKAGE_VERSION ${APP4TRIQS_VERSION}) + SET(CPACK_PACKAGE_CONTACT "https://github.com/TRIQS/app4triqs") + EXECUTE_PROCESS(COMMAND dpkg --print-architecture OUTPUT_VARIABLE CMAKE_DEBIAN_PACKAGE_ARCHITECTURE OUTPUT_STRIP_TRAILING_WHITESPACE) + SET(CPACK_DEBIAN_PACKAGE_DEPENDS "libc6 (>= 2.23), libgcc1 (>= 1:8), libstdc++6, python, libpython2.7, libopenmpi1.10, libhdf5-10, libgmp10, libfftw3-double3, libibverbs1, libgfortran3, zlib1g, libsz2, libhwloc5, libquadmath0, libaec0, libnuma1, libltdl7, libblas3, liblapack3, python-numpy, python-h5py, python-jinja2, python-mako, python-mpi4py, python-matplotlib, python-scipy, cpp2py (= ${APP4TRIQS_VERSION}), triqs (= ${APP4TRIQS_VERSION})") + INCLUDE(CPack) +endif() From 0fb5342c6b450106b5d6940df324040284007440 Mon Sep 17 00:00:00 2001 From: Dylan Simon Date: Mon, 21 May 2018 16:04:25 -0400 Subject: [PATCH 026/272] [cmake] deb pkg works with libgcc1 1:6 The default on xenial --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 15f80ea0..647ded04 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -65,6 +65,6 @@ if(BUILD_DEBIAN_PACKAGE) SET(CPACK_PACKAGE_VERSION ${APP4TRIQS_VERSION}) SET(CPACK_PACKAGE_CONTACT "https://github.com/TRIQS/app4triqs") EXECUTE_PROCESS(COMMAND dpkg --print-architecture OUTPUT_VARIABLE CMAKE_DEBIAN_PACKAGE_ARCHITECTURE OUTPUT_STRIP_TRAILING_WHITESPACE) - SET(CPACK_DEBIAN_PACKAGE_DEPENDS "libc6 (>= 2.23), libgcc1 (>= 1:8), libstdc++6, python, libpython2.7, libopenmpi1.10, libhdf5-10, libgmp10, libfftw3-double3, libibverbs1, libgfortran3, zlib1g, libsz2, libhwloc5, libquadmath0, libaec0, libnuma1, libltdl7, libblas3, liblapack3, python-numpy, python-h5py, python-jinja2, python-mako, python-mpi4py, python-matplotlib, python-scipy, cpp2py (= ${APP4TRIQS_VERSION}), triqs (= ${APP4TRIQS_VERSION})") + SET(CPACK_DEBIAN_PACKAGE_DEPENDS "libc6 (>= 2.23), libgcc1 (>= 1:6), libstdc++6, python, libpython2.7, libopenmpi1.10, libhdf5-10, libgmp10, libfftw3-double3, libibverbs1, libgfortran3, zlib1g, libsz2, libhwloc5, libquadmath0, libaec0, libnuma1, libltdl7, libblas3, liblapack3, python-numpy, python-h5py, python-jinja2, python-mako, python-mpi4py, python-matplotlib, python-scipy, cpp2py (= ${APP4TRIQS_VERSION}), triqs (= ${APP4TRIQS_VERSION})") INCLUDE(CPack) endif() From 7f0e6283f0132ffaea0817cee5db0b8736be5631 Mon Sep 17 00:00:00 2001 From: Nils Wentzell Date: Sun, 27 May 2018 02:06:15 +0200 Subject: [PATCH 027/272] grep app4triqs version from latest annotated git tag --- CMakeLists.txt | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 647ded04..552985bf 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,5 +1,5 @@ -# Version number -set(APP4TRIQS_VERSION "1.5") +# Version number from the latest annotated git tag +execute_process(COMMAND git describe --abbrev=0 OUTPUT_VARIABLE APP4TRIQS_VERSION) # Start configuration cmake_minimum_required(VERSION 2.8.12) @@ -18,8 +18,8 @@ set(BUILD_SHARED_LIBS OFF) add_definitions(-Wall) # Load Dependencies -find_package(TRIQS ${APP4TRIQS_VERSION} EXACT REQUIRED) -find_package(Cpp2Py ${APP4TRIQS_VERSION} EXACT REQUIRED) +find_package(TRIQS 1.5 REQUIRED) +find_package(Cpp2Py 1.5 REQUIRED) # Default Install directory to TRIQS_ROOT if not given or invalid. if(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT OR (NOT IS_ABSOLUTE ${CMAKE_INSTALL_PREFIX})) From 2cd1a9384fdb6e310f2d21611b33589b5fd9ba65 Mon Sep 17 00:00:00 2001 From: Nils Wentzell Date: Fri, 1 Jun 2018 09:38:03 -0400 Subject: [PATCH 028/272] [cmake] app4triqs version detection via git, some cleaning in conf.py.in --- CMakeLists.txt | 18 ++++++++++++------ doc/conf.py.in | 14 ++++++++++++-- 2 files changed, 24 insertions(+), 8 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 552985bf..2347786f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,6 +1,3 @@ -# Version number from the latest annotated git tag -execute_process(COMMAND git describe --abbrev=0 OUTPUT_VARIABLE APP4TRIQS_VERSION) - # Start configuration cmake_minimum_required(VERSION 2.8.12) project(app4triqs CXX) @@ -28,9 +25,18 @@ if(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT OR (NOT IS_ABSOLUTE ${CMAKE_INSTA endif() message(STATUS "-------- INSTALL_PREFIX: ${CMAKE_INSTALL_PREFIX} --------") -# Fetch the git hash of app4triqs +# Use git to detect App4Triqs version and git hash +execute_process(COMMAND bash "-c" "${TRIQS_GIT_EXECUTABLE} describe | sed \"s/-\\([0-9]*\\)-.*/.\\1/g\"" + WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}" + OUTPUT_VARIABLE APP4TRIQS_VERSION + OUTPUT_STRIP_TRAILING_WHITESPACE +) +if(NOT APP4TRIQS_VERSION) + set(APP4TRIQS_VERSION 1.5) +endif() triqs_get_git_hash_of_source_dir(APP4TRIQS_GIT_HASH) -message(STATUS "app4triqs git hash: ${APP4TRIQS_GIT_HASH}") +MESSAGE(STATUS "app4triqs version : ${APP4TRIQS_VERSION}") +message(STATUS "Git hash: ${APP4TRIQS_GIT_HASH}") # Build and install the app4triqs library add_subdirectory(c++/app4triqs) @@ -65,6 +71,6 @@ if(BUILD_DEBIAN_PACKAGE) SET(CPACK_PACKAGE_VERSION ${APP4TRIQS_VERSION}) SET(CPACK_PACKAGE_CONTACT "https://github.com/TRIQS/app4triqs") EXECUTE_PROCESS(COMMAND dpkg --print-architecture OUTPUT_VARIABLE CMAKE_DEBIAN_PACKAGE_ARCHITECTURE OUTPUT_STRIP_TRAILING_WHITESPACE) - SET(CPACK_DEBIAN_PACKAGE_DEPENDS "libc6 (>= 2.23), libgcc1 (>= 1:6), libstdc++6, python, libpython2.7, libopenmpi1.10, libhdf5-10, libgmp10, libfftw3-double3, libibverbs1, libgfortran3, zlib1g, libsz2, libhwloc5, libquadmath0, libaec0, libnuma1, libltdl7, libblas3, liblapack3, python-numpy, python-h5py, python-jinja2, python-mako, python-mpi4py, python-matplotlib, python-scipy, cpp2py (= ${APP4TRIQS_VERSION}), triqs (= ${APP4TRIQS_VERSION})") + SET(CPACK_DEBIAN_PACKAGE_DEPENDS "libc6 (>= 2.23), libgcc1 (>= 1:6), libstdc++6, python, libpython2.7, libopenmpi1.10, libhdf5-10, libgmp10, libfftw3-double3, libibverbs1, libgfortran3, zlib1g, libsz2, libhwloc5, libquadmath0, libaec0, libnuma1, libltdl7, libblas3, liblapack3, python-numpy, python-h5py, python-jinja2, python-mako, python-mpi4py, python-matplotlib, python-scipy, cpp2py (>= 1.5), triqs (>= 1.5)") INCLUDE(CPack) endif() diff --git a/doc/conf.py.in b/doc/conf.py.in index cc68de4d..195e871d 100644 --- a/doc/conf.py.in +++ b/doc/conf.py.in @@ -2,15 +2,25 @@ # # TRIQS documentation build configuration file +import sys +sys.path.insert(0, "@TRIQS_SPHINXEXT_PATH@/numpydoc") + extensions = ['sphinx.ext.autodoc', 'sphinx.ext.mathjax', 'sphinx.ext.intersphinx', + 'sphinx.ext.doctest', + 'sphinx.ext.todo', + 'sphinx.ext.viewcode', + 'sphinx.ext.autosummary', + 'plot_directive', + 'numpydoc', 'matplotlib.sphinxext.plot_directive'] source_suffix = '.rst' project = u'APP4TRIQS - An example triqs application' copyright = u'2018 - The TRIQS Developers' +version = '@APP4TRIQS_VERSION' mathjax_path = "@TRIQS_MATHJAX_PATH@/MathJax.js?config=default" templates_path = ['@CMAKE_SOURCE_DIR@/doc/_templates'] @@ -27,6 +37,6 @@ html_context = {'header_title': 'app4triqs', html_static_path = ['@CMAKE_SOURCE_DIR@/doc/_static'] html_sidebars = {'index': ['sideb.html', 'searchbox.html']} -htmlhelp_basename = 'TRIQSIntdoc' +htmlhelp_basename = 'APP4TRIQSdoc' -intersphinx_mapping = {'python': ('http://docs.python.org/2.7', None), 'triqslibs': ('https://triqs.ipht.cnrs.fr/unstable', None)} +intersphinx_mapping = {'python': ('http://docs.python.org/2.7', None), 'triqslibs': ('https://triqs.github.io/triqs', None)} From 35a48aad807832798e1fe5235a29d5a2fd8a04f3 Mon Sep 17 00:00:00 2001 From: Nils Wentzell Date: Fri, 1 Jun 2018 16:51:49 +0200 Subject: [PATCH 029/272] [cmake] Adjust fallback version --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 2347786f..4652a148 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -32,7 +32,7 @@ execute_process(COMMAND bash "-c" "${TRIQS_GIT_EXECUTABLE} describe | sed \"s/-\ OUTPUT_STRIP_TRAILING_WHITESPACE ) if(NOT APP4TRIQS_VERSION) - set(APP4TRIQS_VERSION 1.5) + set(APP4TRIQS_VERSION 0.1) endif() triqs_get_git_hash_of_source_dir(APP4TRIQS_GIT_HASH) MESSAGE(STATUS "app4triqs version : ${APP4TRIQS_VERSION}") From 7c8f5569ca029d577003bc0692175408518aa699 Mon Sep 17 00:00:00 2001 From: Dylan Simon Date: Fri, 1 Jun 2018 11:10:49 -0400 Subject: [PATCH 030/272] [cpack] Switch to autogenerated shlib and deps --- CMakeLists.txt | 4 +++- Jenkinsfile | 4 ++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 2347786f..033250ec 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -71,6 +71,8 @@ if(BUILD_DEBIAN_PACKAGE) SET(CPACK_PACKAGE_VERSION ${APP4TRIQS_VERSION}) SET(CPACK_PACKAGE_CONTACT "https://github.com/TRIQS/app4triqs") EXECUTE_PROCESS(COMMAND dpkg --print-architecture OUTPUT_VARIABLE CMAKE_DEBIAN_PACKAGE_ARCHITECTURE OUTPUT_STRIP_TRAILING_WHITESPACE) - SET(CPACK_DEBIAN_PACKAGE_DEPENDS "libc6 (>= 2.23), libgcc1 (>= 1:6), libstdc++6, python, libpython2.7, libopenmpi1.10, libhdf5-10, libgmp10, libfftw3-double3, libibverbs1, libgfortran3, zlib1g, libsz2, libhwloc5, libquadmath0, libaec0, libnuma1, libltdl7, libblas3, liblapack3, python-numpy, python-h5py, python-jinja2, python-mako, python-mpi4py, python-matplotlib, python-scipy, cpp2py (>= 1.5), triqs (>= 1.5)") + SET(CPACK_DEBIAN_PACKAGE_DEPENDS "python, python-numpy, python-h5py, python-jinja2, python-mako, python-mpi4py, python-matplotlib, python-scipy, cpp2py (>= 1.5), triqs (>= 2.0)") + SET(CPACK_DEBIAN_PACKAGE_SHLIBDEPS ON) + SET(CPACK_DEBIAN_PACKAGE_GENERATE_SHLIBS ON) INCLUDE(CPack) endif() diff --git a/Jenkinsfile b/Jenkinsfile index 1d8bb2d3..2e40e92f 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -41,8 +41,8 @@ for (int i = 0; i < dockerPlatforms.size(); i++) { if (!publish || platform != documentationPlatform) { /* but we don't need the tag so clean it up (except for documentation) */ sh "docker rmi --no-prune ${img.imageName()}" - } - } } + } + } } } } } From 2cbaac664fb603ae09f08f2e889705e1b29e22cd Mon Sep 17 00:00:00 2001 From: Dylan Simon Date: Fri, 1 Jun 2018 11:12:35 -0400 Subject: [PATCH 031/272] Add .dockerignore Without .git, for all the good it does --- .dockerignore | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 .dockerignore diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 00000000..6e7a76a5 --- /dev/null +++ b/.dockerignore @@ -0,0 +1,2 @@ +Dockerfile +Jenkinsfile From 04d7aef339c2501fbbfe6aa70bda65ec10af58ec Mon Sep 17 00:00:00 2001 From: Nils Wentzell Date: Sun, 3 Jun 2018 13:45:57 -0400 Subject: [PATCH 032/272] [deb] Adjust dependency generation --- CMakeLists.txt | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 4652a148..e4a2b692 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -71,6 +71,8 @@ if(BUILD_DEBIAN_PACKAGE) SET(CPACK_PACKAGE_VERSION ${APP4TRIQS_VERSION}) SET(CPACK_PACKAGE_CONTACT "https://github.com/TRIQS/app4triqs") EXECUTE_PROCESS(COMMAND dpkg --print-architecture OUTPUT_VARIABLE CMAKE_DEBIAN_PACKAGE_ARCHITECTURE OUTPUT_STRIP_TRAILING_WHITESPACE) - SET(CPACK_DEBIAN_PACKAGE_DEPENDS "libc6 (>= 2.23), libgcc1 (>= 1:6), libstdc++6, python, libpython2.7, libopenmpi1.10, libhdf5-10, libgmp10, libfftw3-double3, libibverbs1, libgfortran3, zlib1g, libsz2, libhwloc5, libquadmath0, libaec0, libnuma1, libltdl7, libblas3, liblapack3, python-numpy, python-h5py, python-jinja2, python-mako, python-mpi4py, python-matplotlib, python-scipy, cpp2py (>= 1.5), triqs (>= 1.5)") + SET(CPACK_DEBIAN_PACKAGE_DEPENDS "triqs (>= 1.5), cpp2py (>= 1.5)") + SET(CPACK_DEBIAN_PACKAGE_SHLIBDEPS ON) + SET(CPACK_DEBIAN_PACKAGE_GENERATE_SHLIBS ON) INCLUDE(CPack) endif() From 4a7ffbdf92e30678a4a2bece0bc1ea7dd958937b Mon Sep 17 00:00:00 2001 From: Nils Wentzell Date: Sun, 3 Jun 2018 22:28:24 -0400 Subject: [PATCH 033/272] [doc] Fix few doc problems, add changelog --- ChangeLog.md | 1 + doc/CMakeLists.txt | 2 +- doc/ChangeLog.md | 7 +++++++ doc/changelog.rst | 8 ++++++++ doc/conf.py.in | 3 +-- doc/index.rst | 5 +++++ 6 files changed, 23 insertions(+), 3 deletions(-) create mode 120000 ChangeLog.md create mode 100644 doc/ChangeLog.md create mode 100644 doc/changelog.rst diff --git a/ChangeLog.md b/ChangeLog.md new file mode 120000 index 00000000..9e080e26 --- /dev/null +++ b/ChangeLog.md @@ -0,0 +1 @@ +doc/ChangeLog.md \ No newline at end of file diff --git a/doc/CMakeLists.txt b/doc/CMakeLists.txt index 24fccf0e..40bbedc8 100644 --- a/doc/CMakeLists.txt +++ b/doc/CMakeLists.txt @@ -19,7 +19,7 @@ add_dependencies(docs_sphinx app4triqs_c) # cp_rs is a script in cpp2py/bin, it mimics cp -rs on Linux # and filters the relevant extension # ------------------------------------------------------------------------------------------------ -set(EXT_FOR_DOC "rst png txt css_t conf css js gif jpg py html bib") +set(EXT_FOR_DOC "rst png txt css_t conf css js gif jpg py html bib md") execute_process(COMMAND cp_rs ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR} ${EXT_FOR_DOC}) # --------------------------------- diff --git a/doc/ChangeLog.md b/doc/ChangeLog.md new file mode 100644 index 00000000..0806d26b --- /dev/null +++ b/doc/ChangeLog.md @@ -0,0 +1,7 @@ +Version 0.1 +----------- + +Some Changes +~~~~~~~~~~~~ + +* ... diff --git a/doc/changelog.rst b/doc/changelog.rst new file mode 100644 index 00000000..7c169e86 --- /dev/null +++ b/doc/changelog.rst @@ -0,0 +1,8 @@ +.. _changelog: + +Changelog +========= + +This document describes the main changes in APP4TRIQS. + +.. include:: ChangeLog.md diff --git a/doc/conf.py.in b/doc/conf.py.in index 195e871d..d93c0c0b 100644 --- a/doc/conf.py.in +++ b/doc/conf.py.in @@ -13,8 +13,7 @@ extensions = ['sphinx.ext.autodoc', 'sphinx.ext.viewcode', 'sphinx.ext.autosummary', 'plot_directive', - 'numpydoc', - 'matplotlib.sphinxext.plot_directive'] + 'numpydoc'] source_suffix = '.rst' diff --git a/doc/index.rst b/doc/index.rst index d342e1ad..b4cd7805 100644 --- a/doc/index.rst +++ b/doc/index.rst @@ -3,6 +3,11 @@ app4triqs ========= +.. sidebar:: app4triqs 0.1 + + This is the homepage app4triqs Version 0.1 + For the changes in 0.1, Cf :ref:`changelog page ` + An example application using cpp2py and triqs. This documentation is generated based on `rst `_ files From 81ed3a96963436ed57cfb7fd4a4f7f5ce8102f7f Mon Sep 17 00:00:00 2001 From: Nils Wentzell Date: Sun, 3 Jun 2018 22:32:24 -0400 Subject: [PATCH 034/272] [doc] Fix a few doc warnings --- doc/conf.py.in | 2 +- doc/contents.rst | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/doc/conf.py.in b/doc/conf.py.in index d93c0c0b..26f1cfe3 100644 --- a/doc/conf.py.in +++ b/doc/conf.py.in @@ -38,4 +38,4 @@ html_sidebars = {'index': ['sideb.html', 'searchbox.html']} htmlhelp_basename = 'APP4TRIQSdoc' -intersphinx_mapping = {'python': ('http://docs.python.org/2.7', None), 'triqslibs': ('https://triqs.github.io/triqs', None)} +intersphinx_mapping = {'python': ('http://docs.python.org/2.7', None), 'triqslibs': ('https://triqs.github.io/triqs/master', None)} diff --git a/doc/contents.rst b/doc/contents.rst index 16954194..217ae295 100644 --- a/doc/contents.rst +++ b/doc/contents.rst @@ -12,6 +12,7 @@ Contents index install issues + changelog about Reference manual From 6d2a788ed37fd7f2280228c3e2b2e76b7f0fe9fa Mon Sep 17 00:00:00 2001 From: Dylan Simon Date: Fri, 8 Jun 2018 10:40:39 -0400 Subject: [PATCH 035/272] [jenkins] Support brew installed in other places --- Jenkinsfile | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/Jenkinsfile b/Jenkinsfile index 2e40e92f..942075ea 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -49,7 +49,7 @@ for (int i = 0; i < dockerPlatforms.size(); i++) { /****************** osx builds (on host) */ def osxPlatforms = [ ["gcc", ['CC=gcc-7', 'CXX=g++-7']], - ["clang", ['CC=/usr/local/opt/llvm/bin/clang', 'CXX=/usr/local/opt/llvm/bin/clang++', 'CXXFLAGS=-I/usr/local/opt/llvm/include', 'LDFLAGS=-L/usr/local/opt/llvm/lib']] + ["clang", ['CC=$BREW/opt/llvm/bin/clang', 'CXX=$BREW/opt/llvm/bin/clang++', 'CXXFLAGS=-I$BREW/opt/llvm/include', 'LDFLAGS=-L$BREW/opt/llvm/lib']] ] for (int i = 0; i < osxPlatforms.size(); i++) { def platformEnv = osxPlatforms[i] @@ -66,10 +66,10 @@ for (int i = 0; i < osxPlatforms.size(); i++) { } checkout scm - dir(buildDir) { withEnv(platformEnv[1]+[ - "PATH=$triqsDir/bin:/usr/local/bin:/usr/bin:/bin:/usr/sbin", - "CPATH=$triqsDir/include", - "LIBRARY_PATH=$triqsDir/lib", + dir(buildDir) { withEnv(platformEnv[1].collect { it.replace('\$BREW', env.BREW) } + [ + "PATH=$triqsDir/bin:${env.BREW}/bin:/usr/bin:/bin:/usr/sbin", + "CPATH=$triqsDir/include:${env.BREW}/include", + "LIBRARY_PATH=$triqsDir/lib:${env.BREW}/lib", "CMAKE_PREFIX_PATH=$triqsDir/share/cmake"]) { deleteDir() sh "cmake $srcDir -DCMAKE_INSTALL_PREFIX=$installDir -DTRIQS_ROOT=$triqsDir" From 331bbc8068ac0cc457e608d60f9928eec9577e67 Mon Sep 17 00:00:00 2001 From: Dylan Simon Date: Fri, 22 Jun 2018 11:15:27 -0400 Subject: [PATCH 036/272] [jenkins] move docs to separate gh-pages repo --- Jenkinsfile | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/Jenkinsfile b/Jenkinsfile index 942075ea..638e9426 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -30,13 +30,13 @@ for (int i = 0; i < dockerPlatforms.size(); i++) { def platform = dockerPlatforms[i] platforms[platform] = { -> node('docker') { stage(platform) { timeout(time: 1, unit: 'HOURS') { - checkout scm - /* construct a Dockerfile for this base */ - sh """ - ( echo "FROM flatironinstitute/triqs:${triqsBranch}-${env.STAGE_NAME}" ; sed '0,/^FROM /d' Dockerfile ) > Dockerfile.jenkins - mv -f Dockerfile.jenkins Dockerfile - """ - /* build and tag */ + checkout scm + /* construct a Dockerfile for this base */ + sh """ + ( echo "FROM flatironinstitute/triqs:${triqsBranch}-${env.STAGE_NAME}" ; sed '0,/^FROM /d' Dockerfile ) > Dockerfile.jenkins + mv -f Dockerfile.jenkins Dockerfile + """ + /* build and tag */ def img = docker.build("flatironinstitute/${projectName}:${env.BRANCH_NAME}-${env.STAGE_NAME}", "--build-arg APPNAME=${projectName} --build-arg BUILD_DOC=${platform==documentationPlatform} .") if (!publish || platform != documentationPlatform) { /* but we don't need the tag so clean it up (except for documentation) */ @@ -72,8 +72,8 @@ for (int i = 0; i < osxPlatforms.size(); i++) { "LIBRARY_PATH=$triqsDir/lib:${env.BREW}/lib", "CMAKE_PREFIX_PATH=$triqsDir/share/cmake"]) { deleteDir() - sh "cmake $srcDir -DCMAKE_INSTALL_PREFIX=$installDir -DTRIQS_ROOT=$triqsDir" - sh "make -j3" + sh "cmake $srcDir -DCMAKE_INSTALL_PREFIX=$installDir -DTRIQS_ROOT=$triqsDir" + sh "make -j3" try { sh "make test" } catch (exc) { @@ -96,30 +96,30 @@ try { def workDir = pwd() /* Update documention on gh-pages branch */ dir("$workDir/gh-pages") { - def subdir = env.BRANCH_NAME - git(url: "ssh://git@github.com/TRIQS/${projectName}.git", branch: "gh-pages", credentialsId: "ssh", changelog: false) + def subdir = "${projectName}/${env.BRANCH_NAME}" + git(url: "ssh://git@github.com/TRIQS/TRIQS.github.io.git", branch: "master", credentialsId: "ssh", changelog: false) sh "rm -rf ${subdir}" docker.image("flatironinstitute/${projectName}:${env.BRANCH_NAME}-${documentationPlatform}").inside() { sh "cp -rp \$INSTALL/share/doc/${projectName} ${subdir}" } sh "git add -A ${subdir}" sh """ - git commit --author='Flatiron Jenkins ' --allow-empty -m 'Generated documentation for ${env.BRANCH_NAME}' -m '${env.BUILD_TAG} ${commit}' + git commit --author='Flatiron Jenkins ' --allow-empty -m 'Generated documentation for ${subdir}' -m '${env.BUILD_TAG} ${commit}' """ // note: credentials used above don't work (need JENKINS-28335) - sh "git push origin gh-pages" + sh "git push origin master" } /* Update docker repo submodule */ dir("$workDir/docker") { try { git(url: "ssh://git@github.com/TRIQS/docker.git", branch: env.BRANCH_NAME, credentialsId: "ssh", changelog: false) sh "echo '160000 commit ${commit}\t${projectName}' | git update-index --index-info" sh """ - git commit --author='Flatiron Jenkins ' -m 'Autoupdate ${projectName}' -m '${env.BUILD_TAG}' + git commit --author='Flatiron Jenkins ' --allow-empty -m 'Autoupdate ${projectName}' -m '${env.BUILD_TAG}' """ // note: credentials used above don't work (need JENKINS-28335) sh "git push origin ${env.BRANCH_NAME}" } catch (err) { - /* Ignore, non-critical -- might not exist on this branch */ + /* Ignore, non-critical -- might not exist on this branch */ echo "Failed to update docker repo" } } } } From af8f3ad824e5858ee793f744ad590f0f3a91a8c8 Mon Sep 17 00:00:00 2001 From: Nils Wentzell Date: Thu, 30 Aug 2018 18:05:04 -0400 Subject: [PATCH 037/272] Minor fixes and adjustments --- CMakeLists.txt | 2 +- README.md | 4 ++-- c++/app4triqs/CMakeLists.txt | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index e4a2b692..521bb4ab 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -25,7 +25,7 @@ if(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT OR (NOT IS_ABSOLUTE ${CMAKE_INSTA endif() message(STATUS "-------- INSTALL_PREFIX: ${CMAKE_INSTALL_PREFIX} --------") -# Use git to detect App4Triqs version and git hash +# Use git to detect app4triqs version and git hash execute_process(COMMAND bash "-c" "${TRIQS_GIT_EXECUTABLE} describe | sed \"s/-\\([0-9]*\\)-.*/.\\1/g\"" WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}" OUTPUT_VARIABLE APP4TRIQS_VERSION diff --git a/README.md b/README.md index 64b4af2f..16c57cc7 100644 --- a/README.md +++ b/README.md @@ -12,9 +12,9 @@ To use this skeleton for a new triqs application, the following steps are necess ```bash git clone https://github.com/triqs/app4triqs --branch unstable mynewapp cd mynewapp -git remote set-url https://github.com/myuser/mynewapp +git remote set-url origin https://github.com/myuser/mynewapp find . -type f | grep -v .git | xargs sed -i 's/app4triqs/mynewapp/g; s/APP4TRIQS/MYNEWAPP/g' -find . | grep -v .git | xargs rename app4triqs mytriqsapp +find . | grep -v .git | xargs rename 's/app4triqs/mytriqsapp/' git add -A git commit -m "Create mynewapp from github.com/triqs/app4triqs skeleton" git push diff --git a/c++/app4triqs/CMakeLists.txt b/c++/app4triqs/CMakeLists.txt index 2674e7a9..24344a90 100644 --- a/c++/app4triqs/CMakeLists.txt +++ b/c++/app4triqs/CMakeLists.txt @@ -16,7 +16,7 @@ target_compile_definitions(app4triqs_c PRIVATE # Install library and headers install(TARGETS app4triqs_c EXPORT app4triqs-targets DESTINATION lib) -install(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} DESTINATION include FILES_MATCHING PATTERN "*.hpp" PATTERN "*.h") +install(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} DESTINATION include/app4triqs FILES_MATCHING PATTERN "*.hpp" PATTERN "*.h") # ========= Static Analyzer Checks ========== From 73642c01a09e381196dab9e24f69ccbbe2234c1f Mon Sep 17 00:00:00 2001 From: Nils Wentzell Date: Wed, 12 Sep 2018 11:29:47 -0400 Subject: [PATCH 038/272] [doc] Update website logos --- doc/_templates/sideb.html | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/doc/_templates/sideb.html b/doc/_templates/sideb.html index 11622acf..5b1c7b8e 100644 --- a/doc/_templates/sideb.html +++ b/doc/_templates/sideb.html @@ -1,7 +1,14 @@ -

+

CEA Ecole Polytechnique
CNRS ERC + Flatiron Institute +
+ Simons Foundation +

+
+

+ Visit the project on GitHub

From de2792361e85f77bb5d34f1250bb31b08b5cc040 Mon Sep 17 00:00:00 2001 From: Dylan Simon Date: Mon, 17 Sep 2018 13:41:37 -0400 Subject: [PATCH 039/272] jenkins: fix typo in email alert --- Jenkinsfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Jenkinsfile b/Jenkinsfile index 638e9426..c835cc67 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -137,7 +137,7 @@ Check console output at \$BUILD_URL to view full results. Building \$BRANCH_NAME for \$CAUSE \$JOB_DESCRIPTION -Chages: +Changes: \$CHANGES End of build log: From afe06474ff19d57718f128b8854175801a3d592e Mon Sep 17 00:00:00 2001 From: Nils Wentzell Date: Mon, 17 Sep 2018 15:00:40 -0400 Subject: [PATCH 040/272] [cmake] Fix python environment for doc generation --- doc/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/CMakeLists.txt b/doc/CMakeLists.txt index 40bbedc8..c131ac34 100644 --- a/doc/CMakeLists.txt +++ b/doc/CMakeLists.txt @@ -8,7 +8,7 @@ file(GLOB_RECURSE sources *.rst) set(sphinx_top ${CMAKE_CURRENT_BINARY_DIR}/html/contents.html) add_custom_command(OUTPUT ${sphinx_top} DEPENDS ${sources} - COMMAND ${TRIQS_SPHINXBUILD_EXECUTABLE} -c . -j8 -b html ${CMAKE_CURRENT_BINARY_DIR} html) + COMMAND PYTHONPATH=${CMAKE_BINARY_DIR}/python:$ENV{PYTHONPATH} ${TRIQS_SPHINXBUILD_EXECUTABLE} -c . -j8 -b html ${CMAKE_CURRENT_BINARY_DIR} html) add_custom_target(docs_sphinx ALL DEPENDS ${sphinx_top} ${CMAKE_CURRENT_BINARY_DIR}) # Application must be compiled first From 548993e1d0927652448552af556c16f2c1edb9bf Mon Sep 17 00:00:00 2001 From: Nils Wentzell Date: Wed, 12 Sep 2018 11:29:47 -0400 Subject: [PATCH 041/272] [doc] Update website logos --- doc/_templates/sideb.html | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/doc/_templates/sideb.html b/doc/_templates/sideb.html index 11622acf..5b1c7b8e 100644 --- a/doc/_templates/sideb.html +++ b/doc/_templates/sideb.html @@ -1,7 +1,14 @@ -

+

CEA Ecole Polytechnique
CNRS ERC + Flatiron Institute +
+ Simons Foundation +

+
+

+ Visit the project on GitHub

From 9f03870f26f821eb39fa7aa2bea9d27c6a1429dd Mon Sep 17 00:00:00 2001 From: Nils Wentzell Date: Thu, 11 Oct 2018 17:17:12 -0400 Subject: [PATCH 042/272] [cmake] Use CPLUS_INCLUDE_PATH over CPATH to favor -isystem includes --- Jenkinsfile | 2 +- share/app4triqs.modulefile.in | 2 +- share/app4triqsvars.sh.in | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Jenkinsfile b/Jenkinsfile index c835cc67..64afe7eb 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -68,7 +68,7 @@ for (int i = 0; i < osxPlatforms.size(); i++) { checkout scm dir(buildDir) { withEnv(platformEnv[1].collect { it.replace('\$BREW', env.BREW) } + [ "PATH=$triqsDir/bin:${env.BREW}/bin:/usr/bin:/bin:/usr/sbin", - "CPATH=$triqsDir/include:${env.BREW}/include", + "CPLUS_INCLUDE_PATH=$triqsDir/include:${env.BREW}/include", "LIBRARY_PATH=$triqsDir/lib:${env.BREW}/lib", "CMAKE_PREFIX_PATH=$triqsDir/share/cmake"]) { deleteDir() diff --git a/share/app4triqs.modulefile.in b/share/app4triqs.modulefile.in index c6b2d12d..d34d9cc7 100644 --- a/share/app4triqs.modulefile.in +++ b/share/app4triqs.modulefile.in @@ -32,7 +32,7 @@ setenv APP4TRIQS_VERSION $version setenv APP4TRIQS_GIT_HASH $git_hash prepend-path PATH $root/bin -prepend-path CPATH $root/include +prepend-path CPLUS_INCLUDE_PATH $root/include prepend-path LIBRARY_PATH $root/lib prepend-path LD_LIBRARY_PATH $root/lib prepend-path PYTHONPATH $root/@CPP2PY_PYTHON_LIB_DEST_ROOT@ diff --git a/share/app4triqsvars.sh.in b/share/app4triqsvars.sh.in index 8bab403f..ebcb27a3 100644 --- a/share/app4triqsvars.sh.in +++ b/share/app4triqsvars.sh.in @@ -2,7 +2,7 @@ export TRIQS_ROOT=@CMAKE_INSTALL_PREFIX@ -export CPATH=@CMAKE_INSTALL_PREFIX@/include:$CPATH +export CPLUS_INCLUDE_PATH=@CMAKE_INSTALL_PREFIX@/include:$CPLUS_INCLUDE_PATH export PATH=@CMAKE_INSTALL_PREFIX@/bin:$PATH export LIBRARY_PATH=@CMAKE_INSTALL_PREFIX@/lib:$LIBRARY_PATH export LD_LIBRARY_PATH=@CMAKE_INSTALL_PREFIX@/lib:$LD_LIBRARY_PATH From 24d619b8be6c6cc64e78dba7b7bb177ac60ef222 Mon Sep 17 00:00:00 2001 From: Nils Wentzell Date: Thu, 11 Oct 2018 17:17:53 -0400 Subject: [PATCH 043/272] [cmake] Add Debug flags, Update Triqs version, optional tests --- CMakeLists.txt | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 521bb4ab..109b8476 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -12,10 +12,13 @@ message( STATUS "-------- BUILD-TYPE: ${CMAKE_BUILD_TYPE} --------") set(BUILD_SHARED_LIBS OFF) # Enable compiler warnings for the whole project -add_definitions(-Wall) +add_compile_options(-Wall + $<$:-Og> + $<$:-ggdb3> + ) # Load Dependencies -find_package(TRIQS 1.5 REQUIRED) +find_package(TRIQS 2.0 REQUIRED) find_package(Cpp2Py 1.5 REQUIRED) # Default Install directory to TRIQS_ROOT if not given or invalid. @@ -47,8 +50,11 @@ if(${TRIQS_WITH_PYTHON_SUPPORT}) endif() # Tests -enable_testing() -add_subdirectory(test) +option(Build_Tests "Build tests" ON) +if(${Build_Tests}) + enable_testing() + add_subdirectory(test) +endif() # Additional configuration files add_subdirectory(share) From 46cbea69d9e80374fc99b39cb628d4d063bfc9fd Mon Sep 17 00:00:00 2001 From: Nils Wentzell Date: Tue, 20 Nov 2018 17:53:10 -0500 Subject: [PATCH 044/272] [cmake] Enable CMP0074, adjust if(obj) statements --- CMakeLists.txt | 12 ++++++++---- share/cmake/Findlibasan_rt.cmake | 2 +- share/cmake/Findlibubsan_rt.cmake | 2 +- 3 files changed, 10 insertions(+), 6 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 109b8476..10c13b98 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,6 +1,9 @@ # Start configuration cmake_minimum_required(VERSION 2.8.12) project(app4triqs CXX) +if(POLICY CMP0074) + cmake_policy(SET CMP0074 NEW) +endif() # Default to Release build type if(NOT CMAKE_BUILD_TYPE) @@ -51,7 +54,7 @@ endif() # Tests option(Build_Tests "Build tests" ON) -if(${Build_Tests}) +if(Build_Tests) enable_testing() add_subdirectory(test) endif() @@ -60,10 +63,11 @@ endif() add_subdirectory(share) option(Build_Documentation "Build documentation" OFF) -if(${Build_Documentation}) - if(NOT ${TRIQS_WITH_DOCUMENTATION}) - message("Error: TRIQS library has not been compiled with its documentation") +if(Build_Documentation) + if(NOT TRIQS_WITH_DOCUMENTATION) + message(WARNING "TRIQS library has not been compiled with its documentation! Cannot build documentation.") else() + message(STATUS "Documentation Build enabled") add_subdirectory(doc) endif() endif() diff --git a/share/cmake/Findlibasan_rt.cmake b/share/cmake/Findlibasan_rt.cmake index 60828a3a..919375ee 100644 --- a/share/cmake/Findlibasan_rt.cmake +++ b/share/cmake/Findlibasan_rt.cmake @@ -28,7 +28,7 @@ find_library(ASAN_RT_LIBRARY NAMES ${name} PATHS ENV LIBRARY_PATH - ENV LD_INCLUDE_PATH + ENV LD_LIBRARY_PATH /usr/lib /usr/local/lib /usr/lib/gcc/*/7 diff --git a/share/cmake/Findlibubsan_rt.cmake b/share/cmake/Findlibubsan_rt.cmake index 8b6dc7e5..d8a14d1b 100644 --- a/share/cmake/Findlibubsan_rt.cmake +++ b/share/cmake/Findlibubsan_rt.cmake @@ -19,7 +19,7 @@ set(TRIAL_PATHS ENV LIBRARY_PATH - ENV LD_INCLUDE_PATH + ENV LD_LIBRARY_PATH /usr/lib /usr/local/lib /usr/lib/gcc/7/* From 759bb9da1d035119c58b32c9f9ab35472263052c Mon Sep 17 00:00:00 2001 From: Nils Wentzell Date: Wed, 21 Nov 2018 16:52:55 -0500 Subject: [PATCH 045/272] Fix the sanitizers for MacOs --- c++/app4triqs/CMakeLists.txt | 19 +++++++-------- c++/app4triqs/toto.hpp | 2 +- share/cmake/Findlibasan_rt.cmake | 6 ++++- share/cmake/Findlibubsan_rt.cmake | 19 +++++++++++---- test/python/CMakeLists.txt | 39 ++++++++++++++++++++++++------- 5 files changed, 60 insertions(+), 25 deletions(-) diff --git a/c++/app4triqs/CMakeLists.txt b/c++/app4triqs/CMakeLists.txt index 24344a90..d19f0dee 100644 --- a/c++/app4triqs/CMakeLists.txt +++ b/c++/app4triqs/CMakeLists.txt @@ -58,26 +58,25 @@ endif() # ========= Dynamic Analyzer Checks ========== +# Make additional cmake Modules available +list(APPEND CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/share/cmake) + # Address Sanitizer option(ASAN OFF "Compile library and executables with LLVM Address Sanitizer") if(ASAN) - if(${CMAKE_SYSTEM_NAME} MATCHES "Darwin") - message(FATAL_ERROR "Address Sanitizer Checks currently not compatible with OSX.") - endif() - list(APPEND CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/share/cmake) find_package(libasan_rt REQUIRED) target_compile_options(app4triqs_c PUBLIC -fsanitize=address -fno-omit-frame-pointer) - target_link_libraries(app4triqs_c INTERFACE "-fsanitize=address -fno-omit-frame-pointer -fuse-ld=gold") + target_link_libraries(app4triqs_c INTERFACE "-fsanitize=address -fno-omit-frame-pointer") endif() # Undefined Behavior Sanitizer option(UBSAN OFF "Compile library and executables with LLVM Undefined Behavior Sanitizer") if(UBSAN) - if(${CMAKE_SYSTEM_NAME} MATCHES "Darwin") - message(FATAL_ERROR "Undefined Behavior Sanitizer Checks currently not compatible with OSX.") - endif() - list(APPEND CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/share/cmake) find_package(libubsan_rt REQUIRED) target_compile_options(app4triqs_c PUBLIC -fsanitize=undefined -fno-omit-frame-pointer -fno-sanitize=vptr) - target_link_libraries(app4triqs_c INTERFACE "-fsanitize=undefined -fno-omit-frame-pointer -fuse-ld=gold") + target_link_libraries(app4triqs_c INTERFACE "-fsanitize=undefined -fno-omit-frame-pointer") +endif() + +if(ASAN OR UBSAN AND ${CMAKE_CXX_COMPILER_ID} STREQUAL "GNU") + target_link_libraries(app4triqs_c INTERFACE "-fuse-ld=gold") endif() diff --git a/c++/app4triqs/toto.hpp b/c++/app4triqs/toto.hpp index c62393ea..ea4f3052 100644 --- a/c++/app4triqs/toto.hpp +++ b/c++/app4triqs/toto.hpp @@ -10,7 +10,7 @@ namespace app4triqs { */ class toto { - int i = 0.0; + int i = 0; public: toto() = default; diff --git a/share/cmake/Findlibasan_rt.cmake b/share/cmake/Findlibasan_rt.cmake index 919375ee..3b7ddfc9 100644 --- a/share/cmake/Findlibasan_rt.cmake +++ b/share/cmake/Findlibasan_rt.cmake @@ -17,7 +17,11 @@ # ASAN_RT_LIBRARY Address Sanitizer Runtime Library if(${CMAKE_CXX_COMPILER_ID} STREQUAL "Clang") - set(name clang_rt.asan-x86_64) + if(${CMAKE_SYSTEM_NAME} MATCHES "Darwin") + set(name clang_rt.asan_osx_dynamic) + elseif() + set(name clang_rt.asan-x86_64) + endif() elseif(${CMAKE_CXX_COMPILER_ID} STREQUAL "GNU") set(name asan) else() diff --git a/share/cmake/Findlibubsan_rt.cmake b/share/cmake/Findlibubsan_rt.cmake index d8a14d1b..547b4b36 100644 --- a/share/cmake/Findlibubsan_rt.cmake +++ b/share/cmake/Findlibubsan_rt.cmake @@ -30,7 +30,11 @@ set(TRIAL_PATHS ) if(${CMAKE_CXX_COMPILER_ID} STREQUAL "Clang") - set(name clang_rt.ubsan_standalone-x86_64) + if(${CMAKE_SYSTEM_NAME} MATCHES "Darwin") + set(name clang_rt.ubsan_osx_dynamic) + else() + set(name clang_rt.ubsan_standalone-x86_64) + endif() elseif(${CMAKE_CXX_COMPILER_ID} STREQUAL "GNU") set(name ubsan) else() @@ -42,16 +46,23 @@ find_library(UBSAN_RT_LIBRARY PATHS ${TRIAL_PATHS} ) +mark_as_advanced(UBSAN_RT_LIBRARY) + # Try to find UBSan Minimal Runtime for Clang if(${CMAKE_CXX_COMPILER_ID} STREQUAL "Clang") + if(${CMAKE_SYSTEM_NAME} MATCHES "Darwin") + set(name libclang_rt.ubsan_minimal_osx_dynamic) + else() + set(name clang_rt.ubsan_minimal-x86_64) + endif() + find_library(UBSAN_MINIMAL_RT_LIBRARY - NAMES clang_rt.ubsan_minimal-x86_64 + NAMES ${name} PATHS ${TRIAL_PATHS} ) + mark_as_advanced(UBSAN_MINIMAL_RT_LIBRARY) endif() -mark_as_advanced(UBSAN_RT_LIBRARY) - # Imported target add_library(libubsan_rt SHARED IMPORTED) set_property(TARGET libubsan_rt PROPERTY IMPORTED_LOCATION ${UBSAN_RT_LIBRARY}) diff --git a/test/python/CMakeLists.txt b/test/python/CMakeLists.txt index 624768f4..50185e8b 100644 --- a/test/python/CMakeLists.txt +++ b/test/python/CMakeLists.txt @@ -4,19 +4,40 @@ file(COPY ${all_h5_files} DESTINATION ${CMAKE_CURRENT_BINARY_DIR}) set(all_tests Toto chain) +# Nasty Workaround for Mac Os Homebrew Python to find the proper Sanitizer Compatible Python Executable +if(${CMAKE_SYSTEM_NAME} MATCHES "Darwin") + execute_process(COMMAND bash "-c" "readlink -f $(which python) | xargs dirname" OUTPUT_VARIABLE PYTHON_EXECUTABLE OUTPUT_STRIP_TRAILING_WHITESPACE) + set(PYTHON_EXECUTABLE "${PYTHON_EXECUTABLE}/../Resources/Python.app/Contents/MacOS/Python") + if(NOT EXISTS ${PYTHON_EXECUTABLE}) + message(FATAL_ERROR "Could not find the proper Python executable for MacOs") + endif() +else() + set(PYTHON_EXECUTABLE python) +endif() + +message(STATUS "Python Executable: ${PYTHON_EXECUTABLE}") + foreach(t ${all_tests}) - add_test(NAME ${t} COMMAND python ${CMAKE_CURRENT_SOURCE_DIR}/${t}.py) + add_test(NAME ${t} COMMAND ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/${t}.py) endforeach() +# Set the PythonPath +set_property(TEST ${all_tests} PROPERTY ENVIRONMENT PYTHONPATH=${CMAKE_BINARY_DIR}/python:$ENV{PYTHONPATH}) + +# === Preload Sanitizer Libraries === + # If ASAN=ON use minimal runtime of UBSAN if it exists -if(${ASAN} AND UBSAN_MINIMAL_RT_LIBRARY) +if(ASAN AND UBSAN_MINIMAL_RT_LIBRARY) set(UBSAN_RT_LIBRARY ${UBSAN_MINIMAL_RT_LIBRARY}) endif() -# Set the PythonPath, Sanitizer Library Preloads and UBSan Options for all tests -set_property(TEST ${all_tests} PROPERTY - ENVIRONMENT - PYTHONPATH=${CMAKE_BINARY_DIR}/python:$ENV{PYTHONPATH} - LD_PRELOAD=$<$:${ASAN_RT_LIBRARY}>:$<$:${UBSAN_RT_LIBRARY}> - UBSAN_OPTIONS=print_stacktrace=1:halt_on_error=1:$ENV{UBSAN_OPTIONS} -) +# Set the Sanitizer Library Preloads and UBSan Options for all tests +if(ASAN OR UBSAN) + set_property(TEST ${all_tests} PROPERTY + ENVIRONMENT + PYTHONPATH=${CMAKE_BINARY_DIR}/python:$ENV{PYTHONPATH} + LD_PRELOAD=$<$:${ASAN_RT_LIBRARY}>:$<$:${UBSAN_RT_LIBRARY}> + DYLD_INSERT_LIBRARIES=$<$:${ASAN_RT_LIBRARY}>:$<$:${UBSAN_RT_LIBRARY}> + UBSAN_OPTIONS=print_stacktrace=1:halt_on_error=1:$ENV{UBSAN_OPTIONS} + ) +endif() From 002642f97c888b956d20d4be5e9cb16f461d6716 Mon Sep 17 00:00:00 2001 From: Nils Wentzell Date: Wed, 21 Nov 2018 16:59:19 -0500 Subject: [PATCH 046/272] Change standard install path of cmake files --- share/app4triqsvars.sh.in | 2 +- share/cmake/CMakeLists.txt | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/share/app4triqsvars.sh.in b/share/app4triqsvars.sh.in index ebcb27a3..620c991c 100644 --- a/share/app4triqsvars.sh.in +++ b/share/app4triqsvars.sh.in @@ -7,4 +7,4 @@ export PATH=@CMAKE_INSTALL_PREFIX@/bin:$PATH export LIBRARY_PATH=@CMAKE_INSTALL_PREFIX@/lib:$LIBRARY_PATH export LD_LIBRARY_PATH=@CMAKE_INSTALL_PREFIX@/lib:$LD_LIBRARY_PATH export PYTHONPATH=@CMAKE_INSTALL_PREFIX@/@CPP2PY_PYTHON_LIB_DEST_ROOT@:$PYTHONPATH -export CMAKE_PREFIX_PATH=@CMAKE_INSTALL_PREFIX@/share/cmake:$CMAKE_PREFIX_PATH +export CMAKE_PREFIX_PATH=@CMAKE_INSTALL_PREFIX@/lib/cmake/app4triqs:$CMAKE_PREFIX_PATH diff --git a/share/cmake/CMakeLists.txt b/share/cmake/CMakeLists.txt index 80301486..062ed6c6 100644 --- a/share/cmake/CMakeLists.txt +++ b/share/cmake/CMakeLists.txt @@ -4,7 +4,7 @@ install( FILES ${CMAKE_CURRENT_BINARY_DIR}/app4triqs-config.cmake ${CMAKE_CURRENT_BINARY_DIR}/app4triqs-config-version.cmake - DESTINATION share/cmake + DESTINATION lib/cmake/app4triqs ) -install(EXPORT app4triqs-targets DESTINATION share/cmake) +install(EXPORT app4triqs-targets DESTINATION lib/cmake/app4triqs) From 9e442be0e0a3424d4a7805235f3e65c4983482ca Mon Sep 17 00:00:00 2001 From: Nils Wentzell Date: Mon, 26 Nov 2018 12:03:54 -0500 Subject: [PATCH 047/272] Always export compile commands to json file --- CMakeLists.txt | 3 +++ 1 file changed, 3 insertions(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index 10c13b98..ee4776cb 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -14,6 +14,9 @@ message( STATUS "-------- BUILD-TYPE: ${CMAKE_BUILD_TYPE} --------") # Build static libraries set(BUILD_SHARED_LIBS OFF) +# Export the list of compile-commands into compile_commands.json +set(CMAKE_EXPORT_COMPILE_COMMANDS ON) + # Enable compiler warnings for the whole project add_compile_options(-Wall $<$:-Og> From aef818bc286ac7792c1a2faa8da0a7286f4d3c55 Mon Sep 17 00:00:00 2001 From: Nils Wentzell Date: Mon, 26 Nov 2018 12:04:35 -0500 Subject: [PATCH 048/272] add float-cast-overflow and float-divide-by-zero to ubsan checks --- c++/app4triqs/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/c++/app4triqs/CMakeLists.txt b/c++/app4triqs/CMakeLists.txt index d19f0dee..477db797 100644 --- a/c++/app4triqs/CMakeLists.txt +++ b/c++/app4triqs/CMakeLists.txt @@ -74,7 +74,7 @@ option(UBSAN OFF "Compile library and executables with LLVM Undefined Behavior S if(UBSAN) find_package(libubsan_rt REQUIRED) target_compile_options(app4triqs_c PUBLIC -fsanitize=undefined -fno-omit-frame-pointer -fno-sanitize=vptr) - target_link_libraries(app4triqs_c INTERFACE "-fsanitize=undefined -fno-omit-frame-pointer") + target_link_libraries(app4triqs_c INTERFACE "-fsanitize=undefined -fsanitize=float-divide-by-zero -fsanitize=float-cast-overflow -fno-omit-frame-pointer") endif() if(ASAN OR UBSAN AND ${CMAKE_CXX_COMPILER_ID} STREQUAL "GNU") From 837c886e60389f60032eb3f3a76199b2c29b7506 Mon Sep 17 00:00:00 2001 From: Nils Wentzell Date: Mon, 26 Nov 2018 18:33:03 -0500 Subject: [PATCH 049/272] [cmake] Minor fix in Findlibasan_rt.cmake --- share/cmake/Findlibasan_rt.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/share/cmake/Findlibasan_rt.cmake b/share/cmake/Findlibasan_rt.cmake index 3b7ddfc9..b42f26ae 100644 --- a/share/cmake/Findlibasan_rt.cmake +++ b/share/cmake/Findlibasan_rt.cmake @@ -19,7 +19,7 @@ if(${CMAKE_CXX_COMPILER_ID} STREQUAL "Clang") if(${CMAKE_SYSTEM_NAME} MATCHES "Darwin") set(name clang_rt.asan_osx_dynamic) - elseif() + else() set(name clang_rt.asan-x86_64) endif() elseif(${CMAKE_CXX_COMPILER_ID} STREQUAL "GNU") From 0335e53adfe40be2a2476e186dd9bdaeac43ad4b Mon Sep 17 00:00:00 2001 From: Nils Wentzell Date: Wed, 28 Nov 2018 13:02:26 -0500 Subject: [PATCH 050/272] Adjust cmake-related install dirs to more standard directories --- Jenkinsfile | 2 +- share/app4triqs.modulefile.in | 2 +- share/app4triqsvars.sh.in | 2 +- share/cmake/app4triqs-config.cmake.in | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Jenkinsfile b/Jenkinsfile index 64afe7eb..8c5b73b5 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -70,7 +70,7 @@ for (int i = 0; i < osxPlatforms.size(); i++) { "PATH=$triqsDir/bin:${env.BREW}/bin:/usr/bin:/bin:/usr/sbin", "CPLUS_INCLUDE_PATH=$triqsDir/include:${env.BREW}/include", "LIBRARY_PATH=$triqsDir/lib:${env.BREW}/lib", - "CMAKE_PREFIX_PATH=$triqsDir/share/cmake"]) { + "CMAKE_PREFIX_PATH=$triqsDir/lib/cmake/triqs"]) { deleteDir() sh "cmake $srcDir -DCMAKE_INSTALL_PREFIX=$installDir -DTRIQS_ROOT=$triqsDir" sh "make -j3" diff --git a/share/app4triqs.modulefile.in b/share/app4triqs.modulefile.in index d34d9cc7..2c870cd0 100644 --- a/share/app4triqs.modulefile.in +++ b/share/app4triqs.modulefile.in @@ -36,4 +36,4 @@ prepend-path CPLUS_INCLUDE_PATH $root/include prepend-path LIBRARY_PATH $root/lib prepend-path LD_LIBRARY_PATH $root/lib prepend-path PYTHONPATH $root/@CPP2PY_PYTHON_LIB_DEST_ROOT@ -prepend-path CMAKE_PREFIX_PATH $root/share/cmake +prepend-path CMAKE_PREFIX_PATH $root/lib/cmake/triqs diff --git a/share/app4triqsvars.sh.in b/share/app4triqsvars.sh.in index 620c991c..a7df20b3 100644 --- a/share/app4triqsvars.sh.in +++ b/share/app4triqsvars.sh.in @@ -7,4 +7,4 @@ export PATH=@CMAKE_INSTALL_PREFIX@/bin:$PATH export LIBRARY_PATH=@CMAKE_INSTALL_PREFIX@/lib:$LIBRARY_PATH export LD_LIBRARY_PATH=@CMAKE_INSTALL_PREFIX@/lib:$LD_LIBRARY_PATH export PYTHONPATH=@CMAKE_INSTALL_PREFIX@/@CPP2PY_PYTHON_LIB_DEST_ROOT@:$PYTHONPATH -export CMAKE_PREFIX_PATH=@CMAKE_INSTALL_PREFIX@/lib/cmake/app4triqs:$CMAKE_PREFIX_PATH +export CMAKE_PREFIX_PATH=@CMAKE_INSTALL_PREFIX@/lib/cmake/triqs:$CMAKE_PREFIX_PATH diff --git a/share/cmake/app4triqs-config.cmake.in b/share/cmake/app4triqs-config.cmake.in index 90d20551..2cd3b660 100644 --- a/share/cmake/app4triqs-config.cmake.in +++ b/share/cmake/app4triqs-config.cmake.in @@ -10,7 +10,7 @@ set(APP4TRIQS_GIT_HASH @APP4TRIQS_GIT_HASH@) set(APP4TRIQS_ROOT @CMAKE_INSTALL_PREFIX@) # include the exported targets of this project -include(@CMAKE_INSTALL_PREFIX@/share/cmake/app4triqs-targets.cmake) +include(@CMAKE_INSTALL_PREFIX@/lib/cmake/triqs/app4triqs-targets.cmake) MESSAGE(STATUS "Found APP4TRIQSConfig.cmake with version ${APP4TRIQS_VERSION}, hash = ${APP4TRIQS_GIT_HASH}") From 16fe4b2eabed9786f02bbd63ad053d5b5ceaf45b Mon Sep 17 00:00:00 2001 From: Nils Wentzell Date: Thu, 29 Nov 2018 10:46:57 -0500 Subject: [PATCH 051/272] Minor correction to 759bb9d --- test/python/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/python/CMakeLists.txt b/test/python/CMakeLists.txt index 50185e8b..0a4ccfb5 100644 --- a/test/python/CMakeLists.txt +++ b/test/python/CMakeLists.txt @@ -5,7 +5,7 @@ file(COPY ${all_h5_files} DESTINATION ${CMAKE_CURRENT_BINARY_DIR}) set(all_tests Toto chain) # Nasty Workaround for Mac Os Homebrew Python to find the proper Sanitizer Compatible Python Executable -if(${CMAKE_SYSTEM_NAME} MATCHES "Darwin") +if(${CMAKE_SYSTEM_NAME} MATCHES "Darwin" AND (ASAN OR UBSAN)) execute_process(COMMAND bash "-c" "readlink -f $(which python) | xargs dirname" OUTPUT_VARIABLE PYTHON_EXECUTABLE OUTPUT_STRIP_TRAILING_WHITESPACE) set(PYTHON_EXECUTABLE "${PYTHON_EXECUTABLE}/../Resources/Python.app/Contents/MacOS/Python") if(NOT EXISTS ${PYTHON_EXECUTABLE}) From a42838a8db2995ce28f964ddacb405fa14bd2b02 Mon Sep 17 00:00:00 2001 From: Dylan Simon Date: Thu, 29 Nov 2018 14:20:35 -0500 Subject: [PATCH 052/272] [jenkins] Add CTEST_OUTPUT_ON_FAILURE=1 --- Dockerfile | 2 +- Jenkinsfile | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Dockerfile b/Dockerfile index 560ce4ef..1d7149fb 100644 --- a/Dockerfile +++ b/Dockerfile @@ -7,6 +7,6 @@ WORKDIR $BUILD/$APPNAME RUN chown build . USER build ARG BUILD_DOC=0 -RUN cmake $SRC/$APPNAME -DTRIQS_ROOT=${INSTALL} -DBuild_Documentation=${BUILD_DOC} && make -j2 && make test +RUN cmake $SRC/$APPNAME -DTRIQS_ROOT=${INSTALL} -DBuild_Documentation=${BUILD_DOC} && make -j2 && make test CTEST_OUTPUT_ON_FAILURE=1 USER root RUN make install diff --git a/Jenkinsfile b/Jenkinsfile index 8c5b73b5..d0f1d409 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -75,7 +75,7 @@ for (int i = 0; i < osxPlatforms.size(); i++) { sh "cmake $srcDir -DCMAKE_INSTALL_PREFIX=$installDir -DTRIQS_ROOT=$triqsDir" sh "make -j3" try { - sh "make test" + sh "make test CTEST_OUTPUT_ON_FAILURE=1" } catch (exc) { archiveArtifacts(artifacts: 'Testing/Temporary/LastTest.log') throw exc From 29b50180181b41c3c4f8254e653281330d59219b Mon Sep 17 00:00:00 2001 From: Dylan Simon Date: Tue, 4 Dec 2018 13:50:12 -0500 Subject: [PATCH 053/272] [jenkins] try a more robust git push --- Jenkinsfile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Jenkinsfile b/Jenkinsfile index d0f1d409..bdf66480 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -107,7 +107,7 @@ try { git commit --author='Flatiron Jenkins ' --allow-empty -m 'Generated documentation for ${subdir}' -m '${env.BUILD_TAG} ${commit}' """ // note: credentials used above don't work (need JENKINS-28335) - sh "git push origin master" + sh "git push origin master || { git pull --rebase origin master && git push origin master ; }" } /* Update docker repo submodule */ dir("$workDir/docker") { try { @@ -117,7 +117,7 @@ try { git commit --author='Flatiron Jenkins ' --allow-empty -m 'Autoupdate ${projectName}' -m '${env.BUILD_TAG}' """ // note: credentials used above don't work (need JENKINS-28335) - sh "git push origin ${env.BRANCH_NAME}" + sh "git push origin ${env.BRANCH_NAME} || { git pull --rebase origin ${env.BRANCH_NAME} && git push origin ${env.BRANCH_NAME} ; }" } catch (err) { /* Ignore, non-critical -- might not exist on this branch */ echo "Failed to update docker repo" From 9d1a19b26f418665edd76a9a470eb8c7d595f685 Mon Sep 17 00:00:00 2001 From: Nils Wentzell Date: Tue, 22 Jan 2019 10:21:09 -0500 Subject: [PATCH 054/272] [deb] Remove explicit cpp2py package dependency (deduced from triqs) --- CMakeLists.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index ee4776cb..4fce04df 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -44,7 +44,7 @@ if(NOT APP4TRIQS_VERSION) set(APP4TRIQS_VERSION 0.1) endif() triqs_get_git_hash_of_source_dir(APP4TRIQS_GIT_HASH) -MESSAGE(STATUS "app4triqs version : ${APP4TRIQS_VERSION}") +message(STATUS "app4triqs version : ${APP4TRIQS_VERSION}") message(STATUS "Git hash: ${APP4TRIQS_GIT_HASH}") # Build and install the app4triqs library @@ -84,7 +84,7 @@ if(BUILD_DEBIAN_PACKAGE) SET(CPACK_PACKAGE_VERSION ${APP4TRIQS_VERSION}) SET(CPACK_PACKAGE_CONTACT "https://github.com/TRIQS/app4triqs") EXECUTE_PROCESS(COMMAND dpkg --print-architecture OUTPUT_VARIABLE CMAKE_DEBIAN_PACKAGE_ARCHITECTURE OUTPUT_STRIP_TRAILING_WHITESPACE) - SET(CPACK_DEBIAN_PACKAGE_DEPENDS "triqs (>= 1.5), cpp2py (>= 1.5)") + SET(CPACK_DEBIAN_PACKAGE_DEPENDS "triqs (>= 1.5)") SET(CPACK_DEBIAN_PACKAGE_SHLIBDEPS ON) SET(CPACK_DEBIAN_PACKAGE_GENERATE_SHLIBS ON) INCLUDE(CPack) From 412c0c5b7360f568f91a2ec43d1f3845c1ecdd03 Mon Sep 17 00:00:00 2001 From: Nils Wentzell Date: Mon, 28 Jan 2019 15:04:03 -0500 Subject: [PATCH 055/272] [jenkins] Build deb packages only for tagged releases --- Jenkinsfile | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/Jenkinsfile b/Jenkinsfile index bdf66480..f093242e 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -93,6 +93,7 @@ try { /* Publish results */ stage("publish") { timeout(time: 1, unit: 'HOURS') { def commit = sh(returnStdout: true, script: "git rev-parse HEAD").trim() + def release = sh(returnStdout: true, script: "git describe --exact-match HEAD || true").trim() def workDir = pwd() /* Update documention on gh-pages branch */ dir("$workDir/gh-pages") { @@ -110,7 +111,7 @@ try { sh "git push origin master || { git pull --rebase origin master && git push origin master ; }" } /* Update docker repo submodule */ - dir("$workDir/docker") { try { + if (release) { dir("$workDir/docker") { try { git(url: "ssh://git@github.com/TRIQS/docker.git", branch: env.BRANCH_NAME, credentialsId: "ssh", changelog: false) sh "echo '160000 commit ${commit}\t${projectName}' | git update-index --index-info" sh """ @@ -121,7 +122,7 @@ try { } catch (err) { /* Ignore, non-critical -- might not exist on this branch */ echo "Failed to update docker repo" - } } + } } } } } } } } catch (err) { From 50c1ce40a50c7f1a2a9bb34291b1dbba724bf8f6 Mon Sep 17 00:00:00 2001 From: Nils Wentzell Date: Thu, 21 Feb 2019 11:00:59 -0500 Subject: [PATCH 056/272] [jenkins] Adjust email adressses for jenkins reports --- Jenkinsfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Jenkinsfile b/Jenkinsfile index f093242e..7871a347 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -144,7 +144,7 @@ Changes: End of build log: \${BUILD_LOG,maxLines=60} """, - to: 'nils.wentzell@gmail.com, dsimon@flatironinstitute.org', + to: 'nwentzell@flatironinstitute.org, dsimon@flatironinstitute.org', recipientProviders: [ [$class: 'DevelopersRecipientProvider'], ], From da10fdeb55149aebbbddb9643b6f874d7890d07e Mon Sep 17 00:00:00 2001 From: Nils Wentzell Date: Tue, 5 Mar 2019 15:19:57 -0500 Subject: [PATCH 057/272] [cmake] Define version numbers explicitly --- CMakeLists.txt | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 4fce04df..2093dfa7 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -34,15 +34,11 @@ if(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT OR (NOT IS_ABSOLUTE ${CMAKE_INSTA endif() message(STATUS "-------- INSTALL_PREFIX: ${CMAKE_INSTALL_PREFIX} --------") -# Use git to detect app4triqs version and git hash -execute_process(COMMAND bash "-c" "${TRIQS_GIT_EXECUTABLE} describe | sed \"s/-\\([0-9]*\\)-.*/.\\1/g\"" - WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}" - OUTPUT_VARIABLE APP4TRIQS_VERSION - OUTPUT_STRIP_TRAILING_WHITESPACE -) -if(NOT APP4TRIQS_VERSION) - set(APP4TRIQS_VERSION 0.1) -endif() +# Define the app4triqs version numbers and get the git hash +set(APP4TRIQS_VERSION_MAJOR 0) +set(APP4TRIQS_VERSION_MINOR 1) +set(APP4TRIQS_VERSION_PATCH 0) +set(APP4TRIQS_VERSION ${APP4TRIQS_VERSION_MAJOR}.${APP4TRIQS_VERSION_MINOR}.${APP4TRIQS_VERSION_PATCH}) triqs_get_git_hash_of_source_dir(APP4TRIQS_GIT_HASH) message(STATUS "app4triqs version : ${APP4TRIQS_VERSION}") message(STATUS "Git hash: ${APP4TRIQS_GIT_HASH}") @@ -84,7 +80,7 @@ if(BUILD_DEBIAN_PACKAGE) SET(CPACK_PACKAGE_VERSION ${APP4TRIQS_VERSION}) SET(CPACK_PACKAGE_CONTACT "https://github.com/TRIQS/app4triqs") EXECUTE_PROCESS(COMMAND dpkg --print-architecture OUTPUT_VARIABLE CMAKE_DEBIAN_PACKAGE_ARCHITECTURE OUTPUT_STRIP_TRAILING_WHITESPACE) - SET(CPACK_DEBIAN_PACKAGE_DEPENDS "triqs (>= 1.5)") + SET(CPACK_DEBIAN_PACKAGE_DEPENDS "triqs (>= 2.1)") SET(CPACK_DEBIAN_PACKAGE_SHLIBDEPS ON) SET(CPACK_DEBIAN_PACKAGE_GENERATE_SHLIBS ON) INCLUDE(CPack) From 4d2ba072266c6694052974996f098430309b4bf4 Mon Sep 17 00:00:00 2001 From: Nils Wentzell Date: Tue, 2 Apr 2019 11:13:11 -0400 Subject: [PATCH 058/272] Make generation of generated docs optional through docs_cpp2rst target --- doc/CMakeLists.txt | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/doc/CMakeLists.txt b/doc/CMakeLists.txt index c131ac34..08168908 100644 --- a/doc/CMakeLists.txt +++ b/doc/CMakeLists.txt @@ -22,9 +22,9 @@ add_dependencies(docs_sphinx app4triqs_c) set(EXT_FOR_DOC "rst png txt css_t conf css js gif jpg py html bib md") execute_process(COMMAND cp_rs ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR} ${EXT_FOR_DOC}) -# --------------------------------- -# Generate C++ doc with c++2rst -# --------------------------------- +# ----------------------------------------------------------------------------- +# Make an optional target that allows us to regenerate the C++ doc with c++2rst +# ----------------------------------------------------------------------------- add_custom_target(docs_cpp2rst) get_property(TRIQS_INCLUDE_DIRS TARGET triqs PROPERTY INTERFACE_INCLUDE_DIRECTORIES) @@ -41,7 +41,7 @@ macro(generate_docs header_file) COMMAND c++2rst ${header_file} -N app4triqs - --output_directory ${CMAKE_CURRENT_BINARY_DIR}/cpp2rst_generated + --output_directory ${CMAKE_CURRENT_SOURCE_DIR}/cpp2rst_generated ${CPP2RST_INCLUDE_COMMAND} --cxxflags="-std=c++17" -I ${CMAKE_SOURCE_DIR}/c++ @@ -51,7 +51,6 @@ macro(generate_docs header_file) endmacro(generate_docs) generate_docs(${CMAKE_SOURCE_DIR}/c++/app4triqs/toto.hpp) -add_dependencies(docs_sphinx docs_cpp2rst) # --------------------------------- # Install From 095409d8797f36474e0d6a2b169813f17560aef9 Mon Sep 17 00:00:00 2001 From: Nils Wentzell Date: Tue, 2 Apr 2019 18:07:03 -0400 Subject: [PATCH 059/272] Major cleaning, Synchronize project structure with qmc codes --- CMakeLists.txt | 38 +++++++++------- LICENSE => COPYING.txt | 0 LICENSE.txt | 16 +++++++ c++/app4triqs/CMakeLists.txt | 40 ++++++++++------- doc/CMakeLists.txt | 3 +- doc/_templates/sideb.html | 2 +- doc/conf.py.in | 4 +- doc/index.rst | 2 +- python/app4triqs/CMakeLists.txt | 15 +++---- python/app4triqs/__init__.py | 23 ++++++++++ python/app4triqs/version.py.in | 25 ++++++++++- share/cmake/Findlibasan_rt.cmake | 55 ----------------------- share/cmake/Findlibubsan_rt.cmake | 74 ------------------------------- test/CMakeLists.txt | 5 ++- test/c++/CMakeLists.txt | 30 ++++++------- test/python/CMakeLists.txt | 50 +++++---------------- 16 files changed, 149 insertions(+), 233 deletions(-) rename LICENSE => COPYING.txt (100%) create mode 100644 LICENSE.txt delete mode 100644 share/cmake/Findlibasan_rt.cmake delete mode 100644 share/cmake/Findlibubsan_rt.cmake diff --git a/CMakeLists.txt b/CMakeLists.txt index 2093dfa7..ac52a8a7 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -29,10 +29,10 @@ find_package(Cpp2Py 1.5 REQUIRED) # Default Install directory to TRIQS_ROOT if not given or invalid. if(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT OR (NOT IS_ABSOLUTE ${CMAKE_INSTALL_PREFIX})) - message(STATUS "No install prefix given (or invalid). Defaulting to TRIQS_ROOT") + message(STATUS " No install prefix given (or invalid). Defaulting to TRIQS_ROOT") set(CMAKE_INSTALL_PREFIX ${TRIQS_ROOT} CACHE PATH "default install path" FORCE) endif() -message(STATUS "-------- INSTALL_PREFIX: ${CMAKE_INSTALL_PREFIX} --------") +message(STATUS "-------- CMAKE_INSTALL_PREFIX: ${CMAKE_INSTALL_PREFIX} --------") # Define the app4triqs version numbers and get the git hash set(APP4TRIQS_VERSION_MAJOR 0) @@ -46,11 +46,6 @@ message(STATUS "Git hash: ${APP4TRIQS_GIT_HASH}") # Build and install the app4triqs library add_subdirectory(c++/app4triqs) -# Build and install the app4triqs python module -if(${TRIQS_WITH_PYTHON_SUPPORT}) - add_subdirectory(python/app4triqs) -endif() - # Tests option(Build_Tests "Build tests" ON) if(Build_Tests) @@ -58,19 +53,28 @@ if(Build_Tests) add_subdirectory(test) endif() +if(TRIQS_WITH_PYTHON_SUPPORT) + # Python interface + add_subdirectory(python/app4triqs) + + # Build the documentation + option(Build_Documentation "Build documentation" OFF) + if(Build_Documentation) + if(NOT TRIQS_WITH_DOCUMENTATION) + message(WARNING "TRIQS library has not been compiled with its documentation! Cannot build documentation.") + else() + message(STATUS "Documentation Build enabled") + add_subdirectory(doc) + endif() + endif() +else() + message(WARNING "TRIQS library has been installed without Python support. Cannot build the Python Interface and Documentation.") +endif() + # Additional configuration files add_subdirectory(share) -option(Build_Documentation "Build documentation" OFF) -if(Build_Documentation) - if(NOT TRIQS_WITH_DOCUMENTATION) - message(WARNING "TRIQS library has not been compiled with its documentation! Cannot build documentation.") - else() - message(STATUS "Documentation Build enabled") - add_subdirectory(doc) - endif() -endif() - +# Debian Package option(BUILD_DEBIAN_PACKAGE "Build a deb package" OFF) if(BUILD_DEBIAN_PACKAGE) if(NOT CMAKE_INSTALL_PREFIX STREQUAL "/usr") diff --git a/LICENSE b/COPYING.txt similarity index 100% rename from LICENSE rename to COPYING.txt diff --git a/LICENSE.txt b/LICENSE.txt new file mode 100644 index 00000000..78c28051 --- /dev/null +++ b/LICENSE.txt @@ -0,0 +1,16 @@ +TRIQS: a Toolbox for Research in Interacting Quantum Systems + +Copyright (C) 2014 by P. Seth, I. Krivenko, M. Ferrero, O. Parcollet + +TRIQS 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 3 of the License, or (at your option) any later +version. + +TRIQS 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 +TRIQS (in the file COPYING.txt in this directory). If not, see +. diff --git a/c++/app4triqs/CMakeLists.txt b/c++/app4triqs/CMakeLists.txt index 477db797..f1c3abe8 100644 --- a/c++/app4triqs/CMakeLists.txt +++ b/c++/app4triqs/CMakeLists.txt @@ -1,22 +1,23 @@ file(GLOB_RECURSE sources *.cpp) add_library(app4triqs_c ${sources}) -# Link against triqs and use headers with SYSTEM flag for better warning messages +# Link against dependencies target_link_libraries(app4triqs_c PUBLIC triqs) -target_include_directories(app4triqs_c SYSTEM PUBLIC ${TRIQS_ROOT}/include) +# Configure compilation target_compile_options(app4triqs_c PUBLIC -std=c++17 -fPIC) target_include_directories(app4triqs_c PUBLIC $) -target_compile_definitions(app4triqs_c PRIVATE +target_compile_definitions(app4triqs_c PUBLIC APP4TRIQS_GIT_HASH=${APP4TRIQS_GIT_HASH} - TRIQS_GIT_HASH=${TRIQS_GIT_HASH} + TRIQS_GIT_HASH=${TRIQS_GIT_HASH} $<$:APP4TRIQS_DEBUG> - $<$:TRIQS_ARRAYS_ENFORCE_BOUNDCHECK> - ) + $<$:TRIQS_DEBUG> + $<$:TRIQS_ARRAYS_ENFORCE_BOUNDCHECK> + ) # Install library and headers install(TARGETS app4triqs_c EXPORT app4triqs-targets DESTINATION lib) -install(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} DESTINATION include/app4triqs FILES_MATCHING PATTERN "*.hpp" PATTERN "*.h") +install(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} DESTINATION include FILES_MATCHING PATTERN "*.hpp" PATTERN "*.h") # ========= Static Analyzer Checks ========== @@ -58,25 +59,32 @@ endif() # ========= Dynamic Analyzer Checks ========== -# Make additional cmake Modules available -list(APPEND CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/share/cmake) - +set(sanitizers "") # Address Sanitizer option(ASAN OFF "Compile library and executables with LLVM Address Sanitizer") if(ASAN) - find_package(libasan_rt REQUIRED) - target_compile_options(app4triqs_c PUBLIC -fsanitize=address -fno-omit-frame-pointer) + list(APPEND sanitizers asan) + target_compile_options(app4triqs_c PRIVATE -fsanitize=address -fno-omit-frame-pointer -ggdb3) target_link_libraries(app4triqs_c INTERFACE "-fsanitize=address -fno-omit-frame-pointer") + if(NOT DEFINED ENV{ASAN_OPTIONS}) + message(WARNING "ASAN_OPTIONS is not set. Consider setting ASAN_OPTIONS=symbolize=1:detect_leaks=0 when running tests") + endif() endif() # Undefined Behavior Sanitizer option(UBSAN OFF "Compile library and executables with LLVM Undefined Behavior Sanitizer") if(UBSAN) - find_package(libubsan_rt REQUIRED) - target_compile_options(app4triqs_c PUBLIC -fsanitize=undefined -fno-omit-frame-pointer -fno-sanitize=vptr) + list(APPEND sanitizers ubsan) + target_compile_options(app4triqs_c PUBLIC -fsanitize=undefined -fsanitize=float-divide-by-zero -fsanitize=float-cast-overflow -fno-omit-frame-pointer -ggdb3) target_link_libraries(app4triqs_c INTERFACE "-fsanitize=undefined -fsanitize=float-divide-by-zero -fsanitize=float-cast-overflow -fno-omit-frame-pointer") + if(NOT DEFINED ENV{UBSAN_OPTIONS}) + message(WARNING "UBSAN_OPTIONS is not set. Consider setting UBSAN_OPTIONS=symbolize=1:print_stacktrace=1:halt_on_error=1 when running tests") + endif() endif() -if(ASAN OR UBSAN AND ${CMAKE_CXX_COMPILER_ID} STREQUAL "GNU") - target_link_libraries(app4triqs_c INTERFACE "-fuse-ld=gold") +if(sanitizers) + find_package(sanitizer REQUIRED ${sanitizers}) + if (${CMAKE_CXX_COMPILER_ID} STREQUAL "GNU") + target_link_libraries(app4triqs_c INTERFACE "-fuse-ld=gold") + endif() endif() diff --git a/doc/CMakeLists.txt b/doc/CMakeLists.txt index 08168908..3b0d75e5 100644 --- a/doc/CMakeLists.txt +++ b/doc/CMakeLists.txt @@ -4,6 +4,7 @@ configure_file(${CMAKE_CURRENT_SOURCE_DIR}/conf.py.in ${CMAKE_CURRENT_BINARY_DIR # --------------------------------- # Top Sphinx target # --------------------------------- +# Sources file(GLOB_RECURSE sources *.rst) set(sphinx_top ${CMAKE_CURRENT_BINARY_DIR}/html/contents.html) @@ -19,7 +20,7 @@ add_dependencies(docs_sphinx app4triqs_c) # cp_rs is a script in cpp2py/bin, it mimics cp -rs on Linux # and filters the relevant extension # ------------------------------------------------------------------------------------------------ -set(EXT_FOR_DOC "rst png txt css_t conf css js gif jpg py html bib md") +set(EXT_FOR_DOC "rst png txt css_t conf css js gif jpg py html bib h5 md") execute_process(COMMAND cp_rs ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR} ${EXT_FOR_DOC}) # ----------------------------------------------------------------------------- diff --git a/doc/_templates/sideb.html b/doc/_templates/sideb.html index 5b1c7b8e..7df7dffd 100644 --- a/doc/_templates/sideb.html +++ b/doc/_templates/sideb.html @@ -10,5 +10,5 @@


- Visit the project on GitHub + Visit the project on GitHub

diff --git a/doc/conf.py.in b/doc/conf.py.in index 26f1cfe3..1d95c317 100644 --- a/doc/conf.py.in +++ b/doc/conf.py.in @@ -3,6 +3,7 @@ # TRIQS documentation build configuration file import sys +sys.path.insert(0, "@TRIQS_SPHINXEXT_PATH@/autorun") sys.path.insert(0, "@TRIQS_SPHINXEXT_PATH@/numpydoc") extensions = ['sphinx.ext.autodoc', @@ -13,7 +14,8 @@ extensions = ['sphinx.ext.autodoc', 'sphinx.ext.viewcode', 'sphinx.ext.autosummary', 'plot_directive', - 'numpydoc'] + 'numpydoc', + 'autorun'] source_suffix = '.rst' diff --git a/doc/index.rst b/doc/index.rst index b4cd7805..001e69b4 100644 --- a/doc/index.rst +++ b/doc/index.rst @@ -6,7 +6,7 @@ app4triqs .. sidebar:: app4triqs 0.1 This is the homepage app4triqs Version 0.1 - For the changes in 0.1, Cf :ref:`changelog page ` + For changes see, Cf :ref:`changelog page ` An example application using cpp2py and triqs. diff --git a/python/app4triqs/CMakeLists.txt b/python/app4triqs/CMakeLists.txt index f7ec1c0c..3eb11b72 100644 --- a/python/app4triqs/CMakeLists.txt +++ b/python/app4triqs/CMakeLists.txt @@ -1,21 +1,18 @@ # Build the python module add_cpp2py_module(toto_module) - target_link_libraries(toto_module app4triqs_c) -# We need to include the convertes.hxx files -target_include_directories(toto_module PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}) - # Configure the version configure_file(version.py.in version.py) # All Python files. Copy them in the build dir to have a complete package for the tests. -set(PYTHON_SOURCES __init__.py) -foreach(f ${PYTHON_SOURCES}) - configure_file(${f} ${f} COPYONLY) +file(GLOB_RECURSE python_sources RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} *.py) +list(FILTER python_sources EXCLUDE REGEX "_desc.py") +foreach(file ${python_sources}) + configure_file(${file} ${file} COPYONLY) endforeach() # Install python module to proper location -set(PYTHON_LIB_DEST ${CPP2PY_PYTHON_LIB_DEST_ROOT}/app4triqs) +set(PYTHON_LIB_DEST ${TRIQS_PYTHON_LIB_DEST_ROOT}/app4triqs) install(TARGETS toto_module DESTINATION ${PYTHON_LIB_DEST}) -install(FILES ${PYTHON_SOURCES} ${CMAKE_CURRENT_BINARY_DIR}/version.py DESTINATION ${PYTHON_LIB_DEST}) +install(FILES ${python_sources} ${CMAKE_CURRENT_BINARY_DIR}/version.py DESTINATION ${PYTHON_LIB_DEST}) diff --git a/python/app4triqs/__init__.py b/python/app4triqs/__init__.py index d00e4749..591133ee 100644 --- a/python/app4triqs/__init__.py +++ b/python/app4triqs/__init__.py @@ -1,3 +1,26 @@ +################################################################################ +# +# TRIQS: a Toolbox for Research in Interacting Quantum Systems +# +# Copyright (C) 2016-2018, N. Wentzell +# Copyright (C) 2018-2019, The Simons Foundation +# author: N. Wentzell +# +# TRIQS 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 3 of the License, or (at your option) any later +# version. +# +# TRIQS 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 +# TRIQS. If not, see . +# +################################################################################ + r""" DOC diff --git a/python/app4triqs/version.py.in b/python/app4triqs/version.py.in index dfcc5436..d6c83d2d 100644 --- a/python/app4triqs/version.py.in +++ b/python/app4triqs/version.py.in @@ -1,9 +1,32 @@ +################################################################################ +# +# TRIQS: a Toolbox for Research in Interacting Quantum Systems +# +# Copyright (C) 2016-2018, N. Wentzell +# Copyright (C) 2018-2019, Simons Foundation +# author: N. Wentzell +# +# TRIQS 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 3 of the License, or (at your option) any later +# version. +# +# TRIQS 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 +# TRIQS. If not, see . +# +################################################################################ + version = "@APP4TRIQS_VERSION@" triqs_hash = "@TRIQS_GIT_HASH@" app4triqs_hash = "@APP4TRIQS_GIT_HASH@" def show_version(): - print "\nYou are using app4triqs version %s, release %s\n"%(version, release) + print "\nYou are using app4triqs version %s\n"%version def show_git_hash(): print "\nYou are using app4triqs git hash %s based on triqs git hash %s\n"%(app4triqs_hash, triqs_hash) diff --git a/share/cmake/Findlibasan_rt.cmake b/share/cmake/Findlibasan_rt.cmake deleted file mode 100644 index b42f26ae..00000000 --- a/share/cmake/Findlibasan_rt.cmake +++ /dev/null @@ -1,55 +0,0 @@ -# Copyright Nils Wentzell 2018 -# Distributed under the GNU GENERAL PUBLIC LICENSE Version 3.0. -# See accompanying file LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt -# -# This cmake find module looks for the LLVM Address Sanitizer Runtime Library -# It sets up : ASAN_RT_LIBRARY - -# This module finds the LLVM Address Sanitizer Runtime Library -# latter case skip to the "Boost CMake" section below. For the former -# -# Use this module by invoking find_package with the form:: -# -# find_package(libasan_rt [REQUIRED]) -# -# Results are reported in:: -# -# ASAN_RT_LIBRARY Address Sanitizer Runtime Library - -if(${CMAKE_CXX_COMPILER_ID} STREQUAL "Clang") - if(${CMAKE_SYSTEM_NAME} MATCHES "Darwin") - set(name clang_rt.asan_osx_dynamic) - else() - set(name clang_rt.asan-x86_64) - endif() -elseif(${CMAKE_CXX_COMPILER_ID} STREQUAL "GNU") - set(name asan) -else() - message(FATAL_ERROR "LLVM Address Sanitizer is not available for your compiler") -endif() - -find_library(ASAN_RT_LIBRARY - NAMES ${name} - PATHS - ENV LIBRARY_PATH - ENV LD_LIBRARY_PATH - /usr/lib - /usr/local/lib - /usr/lib/gcc/*/7 - /usr/lib/gcc/*/* - /usr/lib/clang/*/lib/linux - /usr/lib/llvm-*/lib/clang/*/lib/linux - /usr/local/opt/llvm/lib/clang/*/lib/darwin -) - -mark_as_advanced(ASAN_RT_LIBRARY) - -# Imported target -add_library(libasan_rt SHARED IMPORTED) -set_property(TARGET libasan_rt PROPERTY IMPORTED_LOCATION ${ASAN_RT_LIBRARY}) - -include(FindPackageHandleStandardArgs) -find_package_handle_standard_args("Address Sanitizer Runtime Library" - REQUIRED_VARS ASAN_RT_LIBRARY - FAIL_MESSAGE "Address Sanitizer Runtime Libraries not found! Consider installing for additional checks!" -) diff --git a/share/cmake/Findlibubsan_rt.cmake b/share/cmake/Findlibubsan_rt.cmake deleted file mode 100644 index 547b4b36..00000000 --- a/share/cmake/Findlibubsan_rt.cmake +++ /dev/null @@ -1,74 +0,0 @@ -# Copyright Nils Wentzell 2018 -# Distributed under the GNU GENERAL PUBLIC LICENSE Version 3.0. -# See accompanying file LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt -# -# This cmake find module looks for the LLVM Undefined Behavior Sanitizer Runtime Library -# It sets up : UBSAN_RT_LIBRARY - -# This module finds the LLVM Undefined Behavior Sanitizer Runtime Library -# latter case skip to the "Boost CMake" section below. For the former -# -# Use this module by invoking find_package with the form:: -# -# find_package(libubsan_rt [REQUIRED]) -# -# Results are reported in:: -# -# UBSAN_RT_LIBRARY Undefined Behavior Sanitizer Runtime Library -# [UBSAN_MINIMAL_RT_LIBRARY] Minimal version of UBSan Runtime, To be used in combination with Asan - -set(TRIAL_PATHS - ENV LIBRARY_PATH - ENV LD_LIBRARY_PATH - /usr/lib - /usr/local/lib - /usr/lib/gcc/7/* - /usr/lib/gcc/*/* - /usr/lib/clang/*/lib/linux - /usr/lib/llvm-*/lib/clang/*/lib/linux - /usr/local/opt/llvm/lib/clang/*/lib/darwin -) - -if(${CMAKE_CXX_COMPILER_ID} STREQUAL "Clang") - if(${CMAKE_SYSTEM_NAME} MATCHES "Darwin") - set(name clang_rt.ubsan_osx_dynamic) - else() - set(name clang_rt.ubsan_standalone-x86_64) - endif() -elseif(${CMAKE_CXX_COMPILER_ID} STREQUAL "GNU") - set(name ubsan) -else() - message(FATAL_ERROR "Undefined Behavior Sanitizer is not available for your compiler") -endif() - -find_library(UBSAN_RT_LIBRARY - NAMES ${name} - PATHS ${TRIAL_PATHS} -) - -mark_as_advanced(UBSAN_RT_LIBRARY) - -# Try to find UBSan Minimal Runtime for Clang -if(${CMAKE_CXX_COMPILER_ID} STREQUAL "Clang") - if(${CMAKE_SYSTEM_NAME} MATCHES "Darwin") - set(name libclang_rt.ubsan_minimal_osx_dynamic) - else() - set(name clang_rt.ubsan_minimal-x86_64) - endif() - - find_library(UBSAN_MINIMAL_RT_LIBRARY - NAMES ${name} - PATHS ${TRIAL_PATHS} - ) - mark_as_advanced(UBSAN_MINIMAL_RT_LIBRARY) -endif() - -# Imported target -add_library(libubsan_rt SHARED IMPORTED) -set_property(TARGET libubsan_rt PROPERTY IMPORTED_LOCATION ${UBSAN_RT_LIBRARY}) - -include(FindPackageHandleStandardArgs) -find_package_handle_standard_args("Undefined Behavior Sanitizer Runtime Library" - REQUIRED_VARS UBSAN_RT_LIBRARY - FAIL_MESSAGE "Undefined Behavior Sanitizer Runtime Libraries not found! Consider installing for additional checks!" -) diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 4e0ce259..51d3086f 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -1,4 +1,5 @@ add_subdirectory(c++) -if (${TRIQS_WITH_PYTHON_SUPPORT}) - add_subdirectory(python) + +if(${TRIQS_WITH_PYTHON_SUPPORT}) + add_subdirectory(python) endif() diff --git a/test/c++/CMakeLists.txt b/test/c++/CMakeLists.txt index 012d07d1..533922e1 100644 --- a/test/c++/CMakeLists.txt +++ b/test/c++/CMakeLists.txt @@ -1,34 +1,32 @@ -# Copy reference h5 files to binary dir -file(GLOB all_h5_files *.h5) -file(COPY ${all_h5_files} DESTINATION ${CMAKE_CURRENT_BINARY_DIR}) +# Copy h5 files to binary dir +file(GLOB_RECURSE all_h5_ref_files RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} *.ref.h5) +foreach(file ${all_h5_ref_files}) + configure_file(${file} ${file} COPYONLY) +endforeach() +# List of all tests set(all_tests toto) -foreach(t ${all_tests}) - add_executable(${t} ${CMAKE_CURRENT_SOURCE_DIR}/${t}.cpp) - target_link_libraries(${t} app4triqs_c gtest) - add_test(${t} ${CMAKE_CURRENT_BINARY_DIR}/${t}) +foreach(test ${all_tests}) + get_filename_component(test_name ${test} NAME_WE) + add_executable(${test_name} ${test}) + target_link_libraries(${test_name} app4triqs_c gtest) + add_test(${test_name} ${test_name}) # Run clang-tidy if found if(CLANG_TIDY_EXECUTABLE) - set_target_properties(${t} PROPERTIES CXX_CLANG_TIDY "${CLANG_TIDY_EXECUTABLE}") + set_target_properties(${test_name} PROPERTIES CXX_CLANG_TIDY "${CLANG_TIDY_EXECUTABLE}") endif() # Run cppcheck if found if(CPPCHECK_EXECUTABLE) add_custom_command( - TARGET ${t} + TARGET ${test_name} COMMAND ${CPPCHECK_EXECUTABLE} --enable=warning,style,performance,portability --std=c++14 --template=gcc --verbose --quiet - ${CMAKE_CURRENT_SOURCE_DIR}/${t}.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/${test}.cpp ) endif() endforeach() - -# Set UBSan Options for all tests -set_property(TEST ${all_tests} PROPERTY - ENVIRONMENT - UBSAN_OPTIONS=print_stacktrace=1:halt_on_error=1:$ENV{UBSAN_OPTIONS} -) diff --git a/test/python/CMakeLists.txt b/test/python/CMakeLists.txt index 0a4ccfb5..813f28c5 100644 --- a/test/python/CMakeLists.txt +++ b/test/python/CMakeLists.txt @@ -1,43 +1,15 @@ # Copy h5 files to binary dir -file(GLOB all_h5_files *.h5) -file(COPY ${all_h5_files} DESTINATION ${CMAKE_CURRENT_BINARY_DIR}) - -set(all_tests Toto chain) - -# Nasty Workaround for Mac Os Homebrew Python to find the proper Sanitizer Compatible Python Executable -if(${CMAKE_SYSTEM_NAME} MATCHES "Darwin" AND (ASAN OR UBSAN)) - execute_process(COMMAND bash "-c" "readlink -f $(which python) | xargs dirname" OUTPUT_VARIABLE PYTHON_EXECUTABLE OUTPUT_STRIP_TRAILING_WHITESPACE) - set(PYTHON_EXECUTABLE "${PYTHON_EXECUTABLE}/../Resources/Python.app/Contents/MacOS/Python") - if(NOT EXISTS ${PYTHON_EXECUTABLE}) - message(FATAL_ERROR "Could not find the proper Python executable for MacOs") - endif() -else() - set(PYTHON_EXECUTABLE python) -endif() - -message(STATUS "Python Executable: ${PYTHON_EXECUTABLE}") - -foreach(t ${all_tests}) - add_test(NAME ${t} COMMAND ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/${t}.py) +file(GLOB_RECURSE all_h5_ref_files RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} *.ref.h5) +foreach(file ${all_h5_ref_files}) + configure_file(${file} ${file} COPYONLY) endforeach() -# Set the PythonPath -set_property(TEST ${all_tests} PROPERTY ENVIRONMENT PYTHONPATH=${CMAKE_BINARY_DIR}/python:$ENV{PYTHONPATH}) +# List of all tests +set(all_tests Toto chain) -# === Preload Sanitizer Libraries === - -# If ASAN=ON use minimal runtime of UBSAN if it exists -if(ASAN AND UBSAN_MINIMAL_RT_LIBRARY) - set(UBSAN_RT_LIBRARY ${UBSAN_MINIMAL_RT_LIBRARY}) -endif() - -# Set the Sanitizer Library Preloads and UBSan Options for all tests -if(ASAN OR UBSAN) - set_property(TEST ${all_tests} PROPERTY - ENVIRONMENT - PYTHONPATH=${CMAKE_BINARY_DIR}/python:$ENV{PYTHONPATH} - LD_PRELOAD=$<$:${ASAN_RT_LIBRARY}>:$<$:${UBSAN_RT_LIBRARY}> - DYLD_INSERT_LIBRARIES=$<$:${ASAN_RT_LIBRARY}>:$<$:${UBSAN_RT_LIBRARY}> - UBSAN_OPTIONS=print_stacktrace=1:halt_on_error=1:$ENV{UBSAN_OPTIONS} - ) -endif() +foreach(test ${all_tests}) + get_filename_component(test_name ${test} NAME_WE) + get_filename_component(test_dir ${test} DIRECTORY) + add_test(NAME ${test_name} COMMAND ${TRIQS_PYTHON_INTERPRETER} ${CMAKE_CURRENT_SOURCE_DIR}/${test_dir}/${test_name}.py WORKING_DIRECTORY test/python/${test_dir}) + set_property(TEST ${test_name} APPEND PROPERTY ENVIRONMENT PYTHONPATH=${CMAKE_BINARY_DIR}/python:$ENV{PYTHONPATH} ${SANITIZER_RT_PRELOAD}) +endforeach() From ff9536bf915f66527710105c66fd97aacdd220c5 Mon Sep 17 00:00:00 2001 From: Nils Wentzell Date: Fri, 12 Apr 2019 17:54:14 -0400 Subject: [PATCH 060/272] [cmake] Fix in specification of working directory for python tests --- test/python/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/python/CMakeLists.txt b/test/python/CMakeLists.txt index 813f28c5..e4a2c0c6 100644 --- a/test/python/CMakeLists.txt +++ b/test/python/CMakeLists.txt @@ -10,6 +10,6 @@ set(all_tests Toto chain) foreach(test ${all_tests}) get_filename_component(test_name ${test} NAME_WE) get_filename_component(test_dir ${test} DIRECTORY) - add_test(NAME ${test_name} COMMAND ${TRIQS_PYTHON_INTERPRETER} ${CMAKE_CURRENT_SOURCE_DIR}/${test_dir}/${test_name}.py WORKING_DIRECTORY test/python/${test_dir}) + add_test(NAME ${test_name} COMMAND ${TRIQS_PYTHON_INTERPRETER} ${CMAKE_CURRENT_SOURCE_DIR}/${test_dir}/${test_name}.py WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/${test_dir}) set_property(TEST ${test_name} APPEND PROPERTY ENVIRONMENT PYTHONPATH=${CMAKE_BINARY_DIR}/python:$ENV{PYTHONPATH} ${SANITIZER_RT_PRELOAD}) endforeach() From 7f29a3f6245d1f060324d28957bf50c905f0dde8 Mon Sep 17 00:00:00 2001 From: Nils Wentzell Date: Mon, 15 Apr 2019 12:11:01 -0400 Subject: [PATCH 061/272] Additional docs and cleaning in XXX-config.cmake.in file --- share/cmake/app4triqs-config.cmake.in | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/share/cmake/app4triqs-config.cmake.in b/share/cmake/app4triqs-config.cmake.in index 2cd3b660..f175ce4d 100644 --- a/share/cmake/app4triqs-config.cmake.in +++ b/share/cmake/app4triqs-config.cmake.in @@ -1,20 +1,24 @@ +# This file allows other CMake Projects to find us +# We provide general project information +# and reestablish the exported CMake Targets + # Multiple inclusion guard -if (NOT APP4TRIQS_FOUND) +if(NOT APP4TRIQS_FOUND) set(APP4TRIQS_FOUND True) # version set(APP4TRIQS_VERSION @APP4TRIQS_VERSION@) set(APP4TRIQS_GIT_HASH @APP4TRIQS_GIT_HASH@) -# Root of the installation +# Root of the installation set(APP4TRIQS_ROOT @CMAKE_INSTALL_PREFIX@) -# include the exported targets of this project +# Include the exported targets of this project include(@CMAKE_INSTALL_PREFIX@/lib/cmake/triqs/app4triqs-targets.cmake) MESSAGE(STATUS "Found APP4TRIQSConfig.cmake with version ${APP4TRIQS_VERSION}, hash = ${APP4TRIQS_GIT_HASH}") -# Documentation +# Was the Project built with Documentation? set(APP4TRIQS_WITH_DOCUMENTATION @Build_Documentation@) -endif (NOT APP4TRIQS_FOUND) +endif() From b1ba2d4d68474bf36aea64a2057caf853bb86391 Mon Sep 17 00:00:00 2001 From: Nils Wentzell Date: Mon, 15 Apr 2019 12:20:35 -0400 Subject: [PATCH 062/272] Update README to account for alternate rename commands --- README.md | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 16c57cc7..3217fe99 100644 --- a/README.md +++ b/README.md @@ -14,12 +14,21 @@ git clone https://github.com/triqs/app4triqs --branch unstable mynewapp cd mynewapp git remote set-url origin https://github.com/myuser/mynewapp find . -type f | grep -v .git | xargs sed -i 's/app4triqs/mynewapp/g; s/APP4TRIQS/MYNEWAPP/g' -find . | grep -v .git | xargs rename 's/app4triqs/mytriqsapp/' +find . -type d | grep -v .git | xargs rename app4triqs mynewapp +find . -type f | grep -v .git | xargs rename app4triqs mynewapp git add -A git commit -m "Create mynewapp from github.com/triqs/app4triqs skeleton" git push ``` +Depending on which version of the rename command you are using you may +need to replace the aforementioned rename commands as follows + +```bash +find . -type d | grep -v .git | xargs rename 's/app4triqs/mynewapp/' +find . -type f | grep -v .git | xargs rename 's/app4triqs/mynewapp/' +``` + If you prefer to use the SSH interface to the remote repository, replace the http link accordingly From 66164ed8a45fabd484670807000574aaf85bdca3 Mon Sep 17 00:00:00 2001 From: Nils Wentzell Date: Mon, 15 Apr 2019 16:45:59 -0400 Subject: [PATCH 063/272] Bump cmake version requirement --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index ac52a8a7..06b5531d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,5 +1,5 @@ # Start configuration -cmake_minimum_required(VERSION 2.8.12) +cmake_minimum_required(VERSION 3.0.2 FATAL_ERROR) project(app4triqs CXX) if(POLICY CMP0074) cmake_policy(SET CMP0074 NEW) From 57c5c8a892517adadd4e5a8026ef4c3e458e2fe1 Mon Sep 17 00:00:00 2001 From: Nils Wentzell Date: Tue, 16 Apr 2019 11:17:12 -0400 Subject: [PATCH 064/272] [cmake] Remove remainders of separate cpp2py install (now included with triqs) --- .travis.yml | 6 ------ doc/install.rst | 1 - share/app4triqs.modulefile.in | 10 +++++----- 3 files changed, 5 insertions(+), 12 deletions(-) diff --git a/.travis.yml b/.travis.yml index 3499b5af..8071e2a3 100644 --- a/.travis.yml +++ b/.travis.yml @@ -23,12 +23,6 @@ install: true script: - export INSTALL_DIR=$HOME/root_install # We should install outside the repository - # ===== Set up Cpp2Py - - git clone https://github.com/triqs/cpp2py - - mkdir cpp2py/build && cd cpp2py/build - - cmake .. -DCMAKE_CXX_COMPILER=/usr/bin/${CXX} -DPYTHON_INTERPRETER=/usr/bin/python -DCMAKE_INSTALL_PREFIX=$INSTALL_DIR - - make -j8 install - - source $INSTALL_DIR/share/cpp2pyvars.sh # ===== Set up TRIQS - cd $TRAVIS_BUILD_DIR - git clone https://github.com/TRIQS/triqs --branch unstable diff --git a/doc/install.rst b/doc/install.rst index ed132b75..916ae846 100644 --- a/doc/install.rst +++ b/doc/install.rst @@ -25,7 +25,6 @@ Installation steps #. Make sure that you have added the TRIQS and Cpp2Py installation to your environment variables:: - $ source path_to_triqs/share/cpp2pyvarsh.sh $ source path_to_triqs/share/triqsvarsh.sh #. In the build directory call cmake:: diff --git a/share/app4triqs.modulefile.in b/share/app4triqs.modulefile.in index 2c870cd0..15b8baa0 100644 --- a/share/app4triqs.modulefile.in +++ b/share/app4triqs.modulefile.in @@ -20,9 +20,9 @@ proc ModulesHelp { } { puts stderr "Git hash: $git_hash" } -# You may need to edit the next line if cpp2py module is installed -# under a different name in your setup. -prereq cpp2py/@CPP2PY_VERSION@ +# You may need to edit the next line if the triqs module +# is installed under a different name in your setup. +prereq triqs/@TRIQS_VERSION@ # Only one version of app4triqs can be loaded at a time conflict $name @@ -35,5 +35,5 @@ prepend-path PATH $root/bin prepend-path CPLUS_INCLUDE_PATH $root/include prepend-path LIBRARY_PATH $root/lib prepend-path LD_LIBRARY_PATH $root/lib -prepend-path PYTHONPATH $root/@CPP2PY_PYTHON_LIB_DEST_ROOT@ -prepend-path CMAKE_PREFIX_PATH $root/lib/cmake/triqs +prepend-path PYTHONPATH $root/@TRIQS_PYTHON_LIB_DEST_ROOT@ +prepend-path CMAKE_PREFIX_PATH $root/lib/cmake/app4triqs From 00b940dc17282e74de713f93cfc666893324c83b Mon Sep 17 00:00:00 2001 From: Nils Wentzell Date: Tue, 16 Apr 2019 15:04:04 -0400 Subject: [PATCH 065/272] [doc] Synchronize install page with qmc solvers --- doc/install.rst | 54 +++++++++++++++++++++++++++++++------------------ 1 file changed, 34 insertions(+), 20 deletions(-) diff --git a/doc/install.rst b/doc/install.rst index 916ae846..288e9328 100644 --- a/doc/install.rst +++ b/doc/install.rst @@ -2,32 +2,32 @@ .. _install: -Installation -============ +Compiling AP4TRIQS from source +============================== Prerequisite ------------------- -#. The :ref:`TRIQS ` toolbox (see :ref:`TRIQS installation instruction `). - In the following, we will suppose that it is installed in the ``path_to_triqs`` directory. +#. The :ref:`TRIQS ` library, see :ref:`TRIQS installation instruction `. + In the following, we assume that Triqs is installed in the ``path_to_triqs`` directory. Installation steps ------------------ -#. Download the sources from github:: +#. Download the source code of the latest stable version by cloning the ``TRIQS/app4triqs`` repository from GitHub:: - $ git clone https://github.com/triqs/app4triqs.git app4triqs.src + $ git clone https://github.com/TRIQS/app4triqs app4triqs.src -#. Create an empty build directory where you will compile the code:: +#. Create and move to a new directory where you will compile the code:: $ mkdir app4triqs.build && cd app4triqs.build -#. Make sure that you have added the TRIQS and Cpp2Py installation to your environment variables:: +#. Ensure that your shell contains the TRIQS environment variables by sourcing the ``triqsvars.sh`` file from your TRIQS installation:: $ source path_to_triqs/share/triqsvarsh.sh -#. In the build directory call cmake:: +#. In the build directory call cmake, including any additional custom CMake options, see below:: $ cmake ../app4triqs.src @@ -40,22 +40,36 @@ Installation steps Version compatibility --------------------- -Be careful that the version of the TRIQS library and of the solver must be +Be careful that the version of the TRIQS library and of the application must be compatible (more information on the :ref:`TRIQS website `). -As app4triqs is still in alpha phase (unstable), it can only be compiled against the -unstable branch of triqs. +In particular you should make sure that the Major and Minor Version number +of the application and TRIQS agree. +If you want to use a particular version of the application, go into the directory with the sources +and look at all available versions:: + + $ cd app4triqs.src && git tag + +Checkout the version of the code that you want:: + + $ git checkout 2.1.0 + +Then follow the steps 2 to 4 described above to compile the code. Custom CMake options -------------------- Functionality of ``app4triqs`` can be tweaked using extra compile-time options passed to CMake:: - cmake -DOPTION1=value1 -DOPTION2=value2 ... ../app4triqs.src + cmake ../app4triqs.src -DOPTION1=value1 -DOPTION2=value2 ... ../app4triqs.src -+-----------------------------------------------------------------------+-----------------------------------------------+ -| Options | Syntax | -+=======================================================================+===============================================+ -| Specify an installation path other than path_to_triqs | -DCMAKE_INSTALL_PREFIX=path_to_app4triqs | -+-----------------------------------------------------------------------+-----------------------------------------------+ -| Build the documentation locally | -DBuild_Documentation=ON | -+-----------------------------------------------------------------------+-----------------------------------------------+ ++-----------------------------------------------------------------+-----------------------------------------------+ +| Options | Syntax | ++=================================================================+===============================================+ +| Specify an installation path other than path_to_triqs | -DCMAKE_INSTALL_PREFIX=path_to_app4triqs | ++-----------------------------------------------------------------+-----------------------------------------------+ +| Build in Debugging Mode | -DCMAKE_BUILD_TYPE=Debug | ++-----------------------------------------------------------------+-----------------------------------------------+ +| Disable testing (not recommended) | -DBuild_Tests=OFF | ++-----------------------------------------------------------------+-----------------------------------------------+ +| Build the documentation | -DBuild_Documentation=ON | ++-----------------------------------------------------------------+-----------------------------------------------+ From 0f8cf50cd4649d9f02c9839b47bb084353551895 Mon Sep 17 00:00:00 2001 From: Dylan Simon Date: Tue, 16 Apr 2019 15:43:03 -0400 Subject: [PATCH 066/272] [jenkins] always update submodules on unstable/master not just for tagged commits like release branches --- Jenkinsfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Jenkinsfile b/Jenkinsfile index 7871a347..dea1a782 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -93,7 +93,7 @@ try { /* Publish results */ stage("publish") { timeout(time: 1, unit: 'HOURS') { def commit = sh(returnStdout: true, script: "git rev-parse HEAD").trim() - def release = sh(returnStdout: true, script: "git describe --exact-match HEAD || true").trim() + def release = env.BRANCH_NAME.toCharacter().isLetter() || sh(returnStdout: true, script: "git describe --exact-match HEAD || true").trim() def workDir = pwd() /* Update documention on gh-pages branch */ dir("$workDir/gh-pages") { From 9e606ab9ca0bd3620c3af92ca2722add2d1c8969 Mon Sep 17 00:00:00 2001 From: Nils Wentzell Date: Tue, 16 Apr 2019 16:32:26 -0400 Subject: [PATCH 067/272] [cmake] Bump Version number and triqs requirement to 2.2(dev) --- CMakeLists.txt | 8 ++++---- doc/index.rst | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 06b5531d..d65ac171 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -24,7 +24,7 @@ add_compile_options(-Wall ) # Load Dependencies -find_package(TRIQS 2.0 REQUIRED) +find_package(TRIQS 2.2 REQUIRED) find_package(Cpp2Py 1.5 REQUIRED) # Default Install directory to TRIQS_ROOT if not given or invalid. @@ -35,8 +35,8 @@ endif() message(STATUS "-------- CMAKE_INSTALL_PREFIX: ${CMAKE_INSTALL_PREFIX} --------") # Define the app4triqs version numbers and get the git hash -set(APP4TRIQS_VERSION_MAJOR 0) -set(APP4TRIQS_VERSION_MINOR 1) +set(APP4TRIQS_VERSION_MAJOR 2) +set(APP4TRIQS_VERSION_MINOR 2) set(APP4TRIQS_VERSION_PATCH 0) set(APP4TRIQS_VERSION ${APP4TRIQS_VERSION_MAJOR}.${APP4TRIQS_VERSION_MINOR}.${APP4TRIQS_VERSION_PATCH}) triqs_get_git_hash_of_source_dir(APP4TRIQS_GIT_HASH) @@ -84,7 +84,7 @@ if(BUILD_DEBIAN_PACKAGE) SET(CPACK_PACKAGE_VERSION ${APP4TRIQS_VERSION}) SET(CPACK_PACKAGE_CONTACT "https://github.com/TRIQS/app4triqs") EXECUTE_PROCESS(COMMAND dpkg --print-architecture OUTPUT_VARIABLE CMAKE_DEBIAN_PACKAGE_ARCHITECTURE OUTPUT_STRIP_TRAILING_WHITESPACE) - SET(CPACK_DEBIAN_PACKAGE_DEPENDS "triqs (>= 2.1)") + SET(CPACK_DEBIAN_PACKAGE_DEPENDS "triqs (>= 2.2)") SET(CPACK_DEBIAN_PACKAGE_SHLIBDEPS ON) SET(CPACK_DEBIAN_PACKAGE_GENERATE_SHLIBS ON) INCLUDE(CPack) diff --git a/doc/index.rst b/doc/index.rst index 001e69b4..97e25432 100644 --- a/doc/index.rst +++ b/doc/index.rst @@ -3,9 +3,9 @@ app4triqs ========= -.. sidebar:: app4triqs 0.1 +.. sidebar:: app4triqs 2.2 - This is the homepage app4triqs Version 0.1 + This is the homepage app4triqs Version 2.2 For changes see, Cf :ref:`changelog page ` An example application using cpp2py and triqs. From d64b27495eb5b85adde38c5ebc57c5b8a6594b90 Mon Sep 17 00:00:00 2001 From: Nils Wentzell Date: Tue, 16 Apr 2019 16:56:44 -0400 Subject: [PATCH 068/272] Bump cpp2py version requirement --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index d65ac171..18eb0de3 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -25,7 +25,7 @@ add_compile_options(-Wall # Load Dependencies find_package(TRIQS 2.2 REQUIRED) -find_package(Cpp2Py 1.5 REQUIRED) +find_package(Cpp2Py 1.6 REQUIRED) # Default Install directory to TRIQS_ROOT if not given or invalid. if(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT OR (NOT IS_ABSOLUTE ${CMAKE_INSTALL_PREFIX})) From 6177707c73425cf2d89577b675c98457089e4c1a Mon Sep 17 00:00:00 2001 From: Dylan Simon Date: Tue, 16 Apr 2019 17:41:46 -0400 Subject: [PATCH 069/272] [jenkins] check branch name in simpler way that works --- Jenkinsfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Jenkinsfile b/Jenkinsfile index dea1a782..b7d3e649 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -93,7 +93,7 @@ try { /* Publish results */ stage("publish") { timeout(time: 1, unit: 'HOURS') { def commit = sh(returnStdout: true, script: "git rev-parse HEAD").trim() - def release = env.BRANCH_NAME.toCharacter().isLetter() || sh(returnStdout: true, script: "git describe --exact-match HEAD || true").trim() + def release = env.BRANCH_NAME == "master" || env.BRANCH_NAME == "unstable" || sh(returnStdout: true, script: "git describe --exact-match HEAD || true").trim() def workDir = pwd() /* Update documention on gh-pages branch */ dir("$workDir/gh-pages") { From f4ba085165a2976a175435f43a995493d98018ad Mon Sep 17 00:00:00 2001 From: Nils Wentzell Date: Tue, 16 Apr 2019 17:54:07 -0400 Subject: [PATCH 070/272] Add missing logos to docs --- doc/_static/logo_cea.png | Bin 0 -> 40013 bytes doc/_static/logo_cnrs.png | Bin 0 -> 224175 bytes doc/_static/logo_x.png | Bin 0 -> 248543 bytes 3 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 doc/_static/logo_cea.png create mode 100644 doc/_static/logo_cnrs.png create mode 100644 doc/_static/logo_x.png diff --git a/doc/_static/logo_cea.png b/doc/_static/logo_cea.png new file mode 100644 index 0000000000000000000000000000000000000000..1a28b4397aa7c390457f019800f7a65c7abf3207 GIT binary patch literal 40013 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 literal 0 HcmV?d00001 diff --git a/doc/_static/logo_cnrs.png b/doc/_static/logo_cnrs.png new file mode 100644 index 0000000000000000000000000000000000000000..53c7af0e0fb9492806da932e5d609393e771aa4c GIT binary patch literal 224175 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
&7U=H`4hX3 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
  • 6uW3GEsq<5kRLR5*5TC5>XK0WbNWE zs>wj`@9g-EyeTh1Q^&PBQUzYfN{Hf$b#19_RM-W_O+WwKS&wk5bSQTLDlx4X-3p*) zQnw49$JaX!>f^M6`af1v^jJ`RiQUTE+$eA+$e^f7Leva zG)z~5!sZ5_Un-Z0`rEgnNl38QuVs7A7ej7lB<^*+^TJ4(9-tFFy3CK%Y_#P%wR$EA zV;{eLdk?Ultju1BDzxUK0Zzn=_IX>l2J*;4pG==fOVd|ua+*6swiX~Y%k=h6P9MNo zIzEoD39zxTnKLCG%`G^!J>#pK`aM404$X@&R0WR1Y{Mu5Z?XQs-qz9*MP3Vx-fKrG z<*-zm8{)s1`eb44@eYi=D@~gE`r#GZ6k*c96$Mig;#{qw;%f39@+QR&P^pNpbby)D z-X#s3^y;}13NZC~@VNn0o#N(-H^0hNb?8IPMg~~;LY6J8XU*P$itTf{_rb{{BsG=H zqZgu(Pd^z*j|A*3X@N6O5!PpzMD&zbASjjqMN@UhUP|D#GP=TiJmrSX&cH|_3Vo!b z<@@&wTUzc75(9l5>kX+EsjD~vfAS%<7!$VW=I>Xu|F+mNUE>CN}vydL@SbE>I1AtMPjiOpV;{AVPmM=kwvcv3y70Iw2{Zbl{RIl{8_a zpukAH>7`&|)d++l4MjLH9`mKJ&_*+2lYRA|5-joxjO|>RH9G$IofuOF;nbkH{S?# zC!##9ockVI|4hL9U_ylly5M6t`hg!Q$Jd=Q^;A7avJ;WL*RZ+bn=gI&E%1 zk^e%6vCe#%_0S)hP5(n87igDHWo|vZI=QR$Ah!t{U(3*N0`Ve5okx-OJ`9+K8 ztQ`A_6VPBv6eOu=EK`vTy>MLZ&ZhQSkHj0QWb657+;Qqf%`su(icPOkna1)(@<*pH z7ca@3x9VNi|C?GP z|0`BzX@w&rTTC}HFCXP!MYK~Qa<8|#bjup<{nlZ+9P&^n4X8}G*&&9!2u3H^O=nMk z^WVY8p8(UD`=~_kh*M_Tq(OL$nKBZ&VG@yxi%Ixnf$aH2QbfQ8{2}mh*81%lL4b&2 zZxd173@CP2fE#9z3DklHz5c+k?^BeB7`?IzE?_h1$)W*cS8TFzS3bY+TIkS=Mo$m0 zDR$4@lAuEoamj%x9Av`5!|L!W@&-r}NRUfK-&>-}*NlLhJ!F6*x|WAB1fxMg0&F|t zBLPL{9cgc5wES%5kwYJ**X%4 zR1<{wprMa3((`hO_sU~AY&L~Bya9Cx!4ICOk%Ocf!bI7-=K@&>m<9OWXgaXlX=Ht` z;eu^3IhkdtLnEQkPj%&X0W)WVUYQt$7?%4nbe2B8C^na}56Q5wACI)J0O%P97Z>z$ zP#R%^v9R+7CTX!~MQSEqu-0G_UpM4TiVf zj_ibJ_z`RUvdseyE1ZzKZM%cD4{0b3@3QGKlkpful!pV30*LgcKD&ZRTU>~(sJK4E z1q+OVJzp}NNH;m&2Ft!9pPFCzx*{rFvZ%VXlf1NmRL@GsXhCoJi@So09w`~a!{hHk zLuKnQ2t8YylnkV?47fP#oVXRyx|)k~j!5Tu^ip#o-UUap+{uP)Fg)3~h-C?S5r~^) z1+wtTCMn*}pF4l*qAGWR?_X?)q*za>sO8&pmTu}-yqhR4d0A|B%%_@lu~65BLp1)Pr8`cKWAIoD#=|(bec(>_iLQZpSJe4-Av!Y?xnd( zclPdWBr05aNSLtYpKk7|xI>_n`*&kdS(&|21VCMI7>J-%SmOKfX?mqo_qh4bXO|~Fyl6i8^`hDTNW6fJn1{Qk-YH2(=jMc- z^q;8oRN-(o!sb#heW14vP$B#pvl=c&cAQKhr{(jF+z;$nAxCYsT-%c57nI`0Luj)1 z7sfG9%PFpY-Cmb`ap{q+a+)iT9}xfIcX!wGjhC}qOrSBD$s}(JW=sE(u;=2vlLUU* zq~t>ttD2aNSrL56`!a`C1hn`@NYAw4~CX2S8CG2q= z`YkK=*CO+Mx-V`JE}|$_V$nQVd^>=6BnOv&rz{^saM9Jn@Tor@Fk2@`18{8PfqYZ zBniivE)K;~H+!yPWfVVz`7Oj5I{r&32ZR!K5DGd~mkd20#yi0&o%>-4NXdrw#=jps zxuXL5LS$Hm5p6*nJrYu;SIOul_U>d zDDUP(GerJQKJ3qJ));){O^~%g>D!(L_&lUW>BnQ5QqeF4o`7?G-@m!m<DI z0EZA5fzwzLsyO3%gwcnw_Ef3O46kOHdQ zQuIxiq^^e-fS8F(#+BFFngeVgMBONG4XI*@aW8QVjPwv`5p8y;%bM;0r#(aVQJW5n z3K(@G<$~byAlB5R^g$ac+L)Avp4HQsOn)rrwnH=>m{mtiG{)UwnjotvTlCIDi~Iih z4+)L9SAvcm&qGPcIPxe6!lwz_;lp;)d~>ngWw}sT!4=1Vg%uPN9v=PJK(9J5Zr;N5 z?XfUoE`mTzY~=XFMajgv>(70Cea!-QH)i5UIwj&7E`BkwsO=!8bsP2&pjzC=k|!(H zKdnPnh|AePtb;p0saxM$vF(gLs=$p3VnbKHc}>_YwM;1QYUI{l?*xF0x%$ZW-42e9 ztKSx`xuMTuvU0Rs3za{sR^d+kjs0ct%8D|ji?B>?YWz9rhv)4=5_id2`!XsGW`@2O zTn1ExfarPwv#3Ce-|q9R+vtiVlTgaspY;7YX%TafEz?T~3@S zT)94ado>CbBZvzq+#hpH9@)Qqo`oMEZqAWj*w7Xa`@+rp+avtoLY*PA#t@(xvFMOU zo=fnDSbckkgzCOgvMM6oigzUwWuQQd0_L0ubRnSkH8J`}dq$C4>C9@@DNe z(q6aF-5gP6>~b*X+Il|hT;niFMnleIXyNFKGI#RxlgV`UL;GuqMWo`D@hPcpI45`? zcamhay-8L=T|Shd>EDl%b0e~${KQpZL8nN&6vX>P2sa>edN=)P^Qe!6JKk=ZC_&kFW6Tau}Js77hH^HA&x|p8G89>qu^_Y|EK0JssFwZ1B8J3Mycmi3`~l zY2DCe3$ZBjy=EF+`W}c{svakGdn^_1HQp&1qCn+sDt0Euc>YOIvI;6`;duVY_^VrJ zQW9}0&yi>H?WOhgKmuVq zNVVg8_^^E}`zhipcsQm2JvPd=4**HTSXK@^mIS^exCMNC^xzI2p2fPajjh@wFt~2! zO~I220xp+9RX{>93EluXxEKw>5cq?*RhR3FSGo@nlp|==gPR3Y_r78|%pXciBV2w= zS3(AQ$|FDk{?{~mAfhGMfIGp;t?_+W7{>b4&pfitG$E++ab2Id%Wc-G>bZagH)3sV z86_obPN99ob5u^Q4k5oV3zy9?dZWr*o2`itfYUd#nhmmvz%q7nTH0-pT7<-gfZ&65 zOh{xeRXyRbaoL%92pm*!OL^sh+XRf8d_R&|vVmVs8^=KRm7AXh>(*tJD;x?mpp)Qy zcGR!u>(om)_pswAP*Bo_9dX=-7H>tf4dg*!Cr4f=^X+D4_o$rYH^!*G8dWGGgC!Fd z|D&tpZwZI#iy}gOOOTBgdf>k zL-)Hpk}a{VbNWj4o)}JDvWkgVhaJQ{n3&Sq*rA;i;=j%Nb(ST4*w3hfb}i>H7WYNL z{xxD##f+{unO3EXrm;Ad?HcBPf`8lDkn^FbDWoxu6~#MUN%;Na34uMg4_EoN7)^BE z>$+zurl@V4t-1STzTeB02wiCin2@zRC~3E4$EAO?Gb!}^+@e*lzMWAD@p_nYOzmJQ zlNY$>(LZ z)mE26J>){iP(;9+HEe!LkSyYz6J3aHJN@%qdS;U%%p&2TN#81=cmfUbV9i(eZT#tH zM(KJcDgrbG1)ttAyHlsbW2uLZo+aUv`eI{5TT{QiTbjf(Re8>yHPK#FC6fwT$-Lbt zU`Q4r53}=_UIAP3_k5DPQCev>-ow64>J7Y}I%rx%2?Y=c>rP{2R9&OkrY$Zji<;k4 zhoZ~J3fpQ3BMYAn_z!CBI<*lPcTesCg=`a#c(sYCsW7U_BCu1d1=SNp$C!M7$H+S~ zJE-Az#4-J>0+A2NxxO&99sS&etZvpcvW2U!n8{r|;Wj2ygh!(FQ_*&UG$l1*gatbk zcT6DCky}lKX(_`&PVlBGd~qX$+WPyxS<3w(P2U)5(ir#le~;P-tqGJm2(7s=i<$gg zzb1zX&x>~r?zfJP+2hpK#Yj)0F$Rm2)6}FdqM~7aVxyVF{u@#EZNbXOY;&@8NeW+v zmt>9qw!+2#!{bST7+oCkah^HDvlF?R|Af<4d&XbgdzAiNHJ!`kSC^;ho5T{~3c8&D zZVZwaInTEKSk2M~^6+ zWc4~iLmTTi+@p$k+L;rWa&=>Km5$s*-@JJPlfUMBZr+F8q5H^|cc?I61BLtfBz| zATWm(YFeV0_yq++Im--ELphZ}=fA+fgkKNgCk9fNfS$~x090v`MQdpjBRaKU<%A6@ zR1{ZF@A`X5UO-2O45@rRpXn1=!J>BN{F!#|gjvvGp}<8Lwow7K<40efetJw03ZBjW z?;l%T_h=A$qO&I}T#xSj^ML7d=F>{s(Hw~%y6+we2z2qBv<<_;2u<)7V3ztZS^=$f zStB{LaGq6xRSlZ&mKJXs8lhkSp)bLD{$uLm^U-^wCQ+cNfw>0An!Gs&cmjivG^3=H zPGSP%ZL!0JMW=*Hf`|_Hv4x>QBU=-G(5PB17lq2|*{J_1E@J6~lUbZoFfD%50h)2I z_bLhF6P6V_S8GZ`EnkKfIy&^g%z(ikn`~v9RgSZKIo`kYqj@;Su7$mR+^w|fL%xkJzHhr?W{tbo%cuIZA0K3QN0P9LxG#%zzGa+o z$n>*F(=;fAI?_l-DlO7#)#&_uHMQ!6WDtv5hI&bS7kK!D}11KVkvGwlX-LF?6i*1Tn*{fxE8L{xetDmW}Mi)18T5|Wp z0=}~!HHpxVI{WO!r){oBV4#wedY+Y#3H|$xn}lyOMOF5ZYvYw@9+yWggsyfv8eqP| ziTlj&vhQ)+v;zU#_alM~5dq}k*9bFTqV-k$ZMVs<-aTevAyBes|NQ|&RmD@)#23Q? zXUrOiPw~C8rxEN%WovySTV=>F1iUe*duaZx0v&;{A&^c=gOi?e8ry5aJzDw|#3zFS ztMehl#{|E>gnl6mU8S1LKz_};>=7yvim@hT3I&~l;1bXvq$H#daxa7ORT0FDKol?3 z2QVu5akj~Y-i72~uEF6|auF?b*+Jp`!1Gsm0Qfu{5d5a8SzMd|bxyo~-3!o6?H@*P zAaq;*Lx&_Fedp{nb91PGv!}Ngq!$pX6PK6*tLO3}G7#!wgn}qnKokSF1y$x%i=A4@ zZ|-*tIb<2&h68XJ6xXP8(Kd)+018q-a1PYEh=&3?9C~7o7C;|>qK8hV;lsXxh{uUA zz*m6M4f=nnsX>*N0M-S_fSQgD(6K^G6C~<)D|-h;2GjrMou+`3*u#T#gg`V0wZDaz zaD$S(9@I!xyx@`&JOCBTpMxKFo}6@Xu&F>e&b{d+&<->(i$MzwC#Rz=uONSVf}9{Q zSQqb#5DvLL+|YDLc>JaulBqsCAk*;;49D`|9;}Xvm*;d?7RsJ$ina&h7A>M-zv7d< zuRb>$Tm48}o#Q*f|MB4DAAACPrEzCpoq>3@IMHYNcWfr5mM=dx-+_-H&dNy1n~cC1 zz+x39blVvR8}em0BWkRV-s5`=+U8Ty9xfXFaEOUPovcxPGJu}cqoMIyVbnPcG2i4S zYJ90*sC~XBct`O-=XTFcR$Mh{FQzcO2d~$>=q-u~jFqLJhPlV@c4DQ0A!%Xz^OdDoXM%xVILt!CiG`SRLMZt&~G$?Tfk&|6O z&Rr-(UeLrdI5j5JTXDssyPyXuORW%l6%-XY;s>ZgyEK0DssZ{2k7ZrW_LZe__A1yB z6r!VX*(!=#OHrn{iOI;!9`A27v{JcvM52lr@Auz*PdMB+|2JyT+Gxoe9c_;MhH1xX z``Q}A&oS)JLUys|n#tpp=tGz*orJ0rW6VaJoKl`GiZP`e6Gw2R4TFE=u4Q1bv|zzq zY;V7t-Qr%z{5|Tir0(=DT~>x%WXHOi*i=KW#DB3l)bTtV!o-qEAVqA76An{WT@2@k zfj8|*X!vut<>FX2AYjMHrcsEr3vngxclx1-YJjOu`QlK&C5_PC&ct04nfNIivkbn= z=k@~gQ`88;?^u%ddFF{%*f-7zG`I6KtgPhZ*alF{5GZN{kvKp_(*8;t7Ps!xv!+WB zvjM1y>QX9(L2kdWTxvNi1W>u*c~mz85$nHZbHlgJ4uI_9?`W45=W03d@HAMi5Czk=GNk0Z~ zynubRc5v8%N+f|}1JJQh{|}&!p;HCSBS6gzg#1t+ZoCW@M(7+U?qg2jS#4$om5s?>|kR%)d9%m65>Pk;oH*z59JJ5fL2pz>l0*WBhop zTMu0GhK4JbmhNtDU=-SFnFR2^ipm>6_KMz4#Cm{V8BE5I^G8h$;KZ}_P|b;zjm0%HeFOvdifH1ehEU-5?I&?J?nhq@ep29C>PhZYDP?b~Wg) zhPfL2<8q)h4Eo*OvY>n7^ZHr-%5zpMwR@ANaF_Pdo3o96;+HQo+qWwZlx(Z87oXMJ z-(@w%3c!~j8#Tjhiq#s^(Mn4peFT&Nu|1X@44+mU4Z9{YOR<005dDbc=L+!F9Nd)u zvN_wvJ>ik4=&*S~7kq{(dq-=MsL!L$G~0*1It4sQDYd`Kj{m$6u#=pRS>gw(4^!`5 zvk>6+_+&xe#+VK=AYcmdAeMBKE(~PQo(FU z^Wyi+Z%z@;2undTb!!^g?VQJ{6Y$Cmuo?O$UyZ^E-J|&^no~aQ8$Kf1zWcs@KY*J= z*f;STtGZB4LruZc9I?9cGYp%BmF~Tkl&1m99j5QEigw@2b)3rO_P~NYyT!Waym+15 zoM@N-*f}_R@^2LF-q&Pc<+hM-Z{n#+(pH8tAcrC|KNfMJ1=glh+FKyY=C0#R;4=+H zlrS*Tl`}D9OTUeu&Ed)&P>8_}5BXME zQjlMbGKJeTH8lp7lE!8C=jtkqrRB658d4a<{lBV>N0=;Q&F8ArM3s=4+4qEBE8Q$Eu8Qm28J*yR3i&6D31Gs@t*!=w4k<-NbkOWV%ID}0dZa+Aa^e7_;Wgnf?Bq{ZxUIO* zMq0Kp4fW8Lf^TM^U{ zkxQyxPsIB603n;Q=mR$hp{wz%ad1c&Fq7H34`)r}07&~sa3VtWw8IrSy-hBujligo zoSY2a6$)ff9RiYVoAgI#R?mgZ_^s~TzgYK^JJ4|jA$<{YONUr;5MysFAPA25ssMPq zp^R)U(*E>O9L5N7J_4^1Z-Z$mbs=Mni>Y)mF|)#gI~7F|B`<`5u+0qnNkcBAPS z&GKA61OT@#R2>dDl5yvCTiz<00&fwq%DIhKUydEF?Hy&tRiLGTfJWr7^z};`$_T1T z`;Cn4hsh(%7wJ*opHY=EnHWt_My%IrO4B8ah4l^~Q!yfh5jdY|Js0)aAQKVt30x!H z{0~B`j7_3;FbQ$mv4#Yej0D@VEi9-QC?cskxQa@SU9DR!ouGV+9RmnW&ay z;5%mmPQ{VD*qGCa&h97$BC{Hd2;{HIUy9r733TvY^lG9EnFg&>#^eYq?Y!a5{AgF? z`<`03+lP-6F9~1uJ#XZIegfAF>mP4kGp!-0;4xo*Z92~<5Tz3QOAxRn~1cN7+k;xg(n8fJ2scSMV)fHkX}?m_ODf+ z6_|o;7lt#rQi~!9rk0(9duA!dj^{gDLj;yTJ!pc?0rckMMM?nERn%uT#=Pnw6Z{lV zHuK?!#nGp1Pxn`C-LlJqr*Hw~Dmn(;W}LwXd;k_*OGBzOpIq_`?M2O;!2gwokx^_a zfI&_baJlPX;p^A9EG$H+PY4@&aZW{*SR9GXPDXEky=sHmA>bH7w55f>#RM{6Ya!jdkx;`U9m<$C_bkNbdoB3y`oipMF(fU8B=E_U z>A|Qw*r4>5Io=6ijDJ_I zUmdp8^3gO(*%^S5CKC)}A}yiQ3vGajq39EboP+9?y6lRHCr_)-fh%;`=jlIigg^pA z+i4iaE8+c%M2+66pf(;Jd}+!C66k!s+u(CXyrt?)T1!o@hBH*^BU~;2 z#sHZ`FO|)`6Fy2~hQEb3h*bk~#EvHbfmKyiJArv{oF*MK`tCC^11KFcKA-RDYUNQ6 z)UyqPpmPp1(+v7LkfJ#M-5t{Bf`Dkx+r6*Y2#p{C2c-55nv%xhsnAI?-27p$9?9=v%!(`^sJYWRlx1TXdWotp{rs*@frYN47Hua2}W+)Jv;;qCYwO zlp~i*bSaOPI%vja-9@BEj)soG&Nth;|0mOPGw+Vyu!E-=u#RAyolUX*@B+1v77*7|smyUBcvUQ^kL_Yo z((ojctV~hX&MX;v&WkM{UVD8!DO?nNYpagyE)Z@0;@S=@z;+YLB*~a zIS;F{pgn2!X-_)o)=Rt1^~J~UdP8sC@#>6i0j=sLXqa3F0$q=E?pToB=s}1G>(dmpG9gP??9)*EPS(~pxYAm+nT@Y%QzMv}?E>}PJ;i2W?;OtI+hnl7e zFR6~P0Mow{r}ghLITQx4EbN{#xy#UKZAK>#6Q+VgR@5fLHHr$=K0jNZo|Pa>d6O5G z48I;US%9rufT(RnijRwq$=*;AonyZ;n20I*>pmTQ*1xs$rM>rm+8cDfkE4c1E>sf}MPO_lC8*Y<#p)E|U*=TxlIM1wpofJ0aQB%~l2Z zbLtqb9^FBeX+K6`QmrR2Wyw{)f6dqEg9KL;MHadt0}_NL=1=Xw>~Cf7K$SS)c(qRp zf-}d~rVOh=(x7|m6_P{i8Iq{yKC#8+p?uR|G7It)5fT~(BT)OvOVnp8mR3JxB-9D; zZ7Scl4T88nHQ! zGmx9e2O1Q-t*4`Kf+3|>9h#*{B^#}0VP}hQLe%MR2qe^Iy25v0ge#WwR`3nb2m*6cnt>}QAjSjCp)`;j$Dn^mBN)@`*S~6f48zI5i9i$Ey)U?H?8v3RyFE5Ba_119n@Kn2M zF@qIWg1TyoJW$u^uP)&h1J%;B6zf)=#;<#C>Khr{Z)vsWs&JzQeEnyrUr#ft&GcR} z4%<*p#Ziq@3~{jH=;<^j6VX!4jLWo-zai>HLyt`u;vJvm3=Bzu^%|@>w$LLYvQ$uEw&S0---=RVhr$ z*;-soiC$0r0-R-B@+1RTj4DnDPKXt+#Thc3$(2PNL8io4Q4`M=j^g@_pLTx*H$1am ztI}~$>Sug2)ad?=Oycld;VFHWz<-)#hJ!a$Eu&9AL-4pUFp*yQeD5crYivw@0Wxn^ zC3Z=&+BbG?oT~hL=A;0 zT1KJUWM*bU^&&nwAmp{myjOgCG%M0v2O3#K?+Bm10F+}itL-goDv+y^30=*a0%#H^ zgp%;i3!*TfuA6vi^1Qa9&-^Ut+)q<}HhkjXv;Z;6dJQ5y0FtO88;h$`@58L<=vdKs ztCIkdtT)uR`DRT`uECoQpocC=RESl->7qTq5fV;ia|FuSV?BOC$FSF%)r`6oT2RoW%K~XWL%!RUP~wXN{Wkz} z;b$8;oW=`{*@lu1bU?Zkv>eHwXa|~qW-(?s^B&r{fMs*#KuJh;`W<-wQ(wPVeLQ*J z9CADR!}yslGL#DoTC8F=#%E_`si%T z$58PQ!{M^60A@DgUJT| zjNZr;bt^051&IY~E4%FrHf6`{dvkJaPC~m(S}v0Ge>FLrU&nufkxUj*ge68%zDC+| z%9*D^U+Lq=S72E!0RLjZO$=N!{naT#9}2_CK2NJe;Q^zd#V@wW>1CZ~sE8LR)JHK@tU~^U%k?wnrIAm zGazHpab?h4=rj%y?Wr;Lv>jk^p*vRM0(S zbW{lpchC(A6oJshAav97OutEBc%XnDYA=o?U@cH#7{^NS1b)gFc9BqPIc$gtBpJoR z@P60>qo6IwMnVHpuiY%!$W@DxLNypc`o!-y{u7$j_FM)sx!Rw_QOZ@kZU^PJn%Je{~FT{iL z#emQhy37&Cm&TNgl5II`R~EK0YX@gsP1zvv-l&iiI!~ZkQsnNCi|GS(%*Lv8%G`8p z)HabWh5gGya{}l3=pQgw@5nL*Wqn7v7vgavp8yJV_FG-K%JTwAAFc>%zRXlhrQ9;4 zn0UW)ydmUY-N&GVG{L^)a9_m#aAr849u0ZfW+tlU(8%wC@;+0R7dHhN%aq_zt2OEV zk^A#tuwO`{^U`f9?65G~hd%=6Oh&R?Gn$jOju;`>Jg?S5yRcK7jSQbx7;6 zH%H``ev+2%nh~{PQJV@13;pl<-x-uTs{1spSczXkV-pY5mPD}s)EU-&qCuLe4r7N? zMbU2aX6#qW@^9>lFB9g5Y5$6F`*;fU!$1BleQa`A5^&xlcCEMYy#8DVFSZKLq2y5cqsRWXZ>lsWiN)_ndv7^tM;NK z5D8(9zb!JB%FsLIV&zyZgee&wuMeT7p24SOIT-60(~*71uHS4J32h(w5JJutOyX87?wz(2=i{csb(u(66RrX4TEq#8UOzD|(d{cz5 zq&VzvxC?rX&#gmS5loU5w0Zc)sN@7@C+o_rtTHitcf@1~)i5YIH->JS`t#1vFQob7m4?`TUm!9-Z+9Y0XP_Ir|jB1gR;1(_|^4RTyqpJ=(_XUBQ(up?`|D@ zuAII9eyD3M%kad0{b8~PHF=!CZ1nA7CxeXa@~eEck{|7EJfa?(zK?S$ZZajZy&Q;o z?;R{>%<6g(9{zJmbZB{eY1=g>@B#mKV4iHq0Sbin#~AKI)r)WBWPv`Fn}~+?U!qUY z3dZaBKC=V12nlF&1Cf*;bX1_6v< z)_}wf%F3c-WEVOezQP^1TcQxF@OU`pi}bTtF%yacG4ysy1BX?;y%)mDKhT}L2@N2% zqTQA`K7D6nnAM&a7LV&}j{zX1i*qW(L~??&k4LXq4ePl|iT{oXp#p!KWv0sAbvmo> zMdk`SKxKLqkK&;$RIB4?S+5JaIkkJl*)6`Q4v9MTEFUI2XyVW(G2x z9ie*Tw#uU7BP1oM!hNtFo}6rq!++}UFt3F_Ira{1SpF0#c&t5S`0&S&!`6aYqSxPb z+T5e@7n|RWJV35>>TK|VRd5YR-!?BiE$YU$?{6-^R1O5mVkH{u;G^-ybOU8URbp2N zN%8fA$FqR{)EL94n2KQVpN&9i>@&?Cy9X|2e5%jshw4A8ROqf1!wCONu{rS)8p4DL0uDZ7%AWYwVN!S zeQ#?@oU5quyg%ztU(%+K!n$Q`Di4g)p+-Vm<>!-)v^A>5b2;vk6nVThjUnS7j=*OI zGJt;c7xVA9%?wzt(4f8Bd3%@`6o7)k5EI;z;F~^fK48Tl7wYPjCj<^5+6%#L=c7sD z=F0cQjF~1|)kTf0e%?>h z)!Q|thBkaKc9$m+RO|C;C&Buot4Z^ven9v^pj}Ym=BICIch}<2k1IaBV?q~b=}~J& zcqoWr`3`qy4G2N(g@ZOmNrPs>>?5K>rojR0(U-982ytH;Jw;*;ffpg?H5 zh3%?-@(tz3O=S>`WCm@3#~(X3Ryzw2#G+^^b6f@r4Z37-d$0)tYE1(Uz2_N}I!?P# zg`Vy&fZ83HBfzu}()eW;biQ+l#d)~UJ{l0um>V%bNse+w;!XOHLj`cT;1Jt=Nh)bA zS!4qLy?&YpsM-2};S?%b0%`P+QWl8UV;fd{GgIGx3I|@=kOWr{l;P-oMSB z2ncL zg@pop4U-WN{Xbi4jeF8wllboaE!o(^X}@bNVVWu|ZcN6KGX#rNSaS8m&sD3QU{pdrS4UAp-y2#* zF3T$5q~ckuim{u{!x0+{ac=5bmI#HuaiDz|wz4$^4;Og;`#?+0;HpeI6f3x~x^t%u z8nQ6$nnTxBMEhe%^C@%8|3++aZ@bjNou@?m^t>I|2>-Y`!z_%+_>u)}qhi-~`F>a3 z_hH@E+xc4F#QgJyT8Tz3PP&ndtn0UUwbf$IxA9|}>t$t=ztM>)rxcvKg1;m;?45K- zY4zD@w|_p$JT~h-S0d35d#x>CY#3gZLp`29h+S^loJ)?T$Qi&#bwr|Cb9JSa?Q^9A z?(gAa;hd@QX(`VL`LnmiR`mlxKdbG5vxHG|A@W_-I>5x}$WpD*51=Y*09}ZvX ziqV_-n>KaD%g|x4EkZ7qtz(>}r6p*7C(fL%1`!VKhqIj^nHk#430d{?>*|vGqK1GN zqtW>c2Xt$8vpv5*v=lY9aEYPd)XxUtq(VCox*+A?_evZY;1K<5-J#ZLb3I@muu7W% zN(24<=D|AK8NQF}OwhN%Qlsa2K0rUfYZ0$Tl5Ep&yxi*PG5S}9J7&V3g`q{Li6HCiXXvwLvRUBwLs#*H=lY$XqOjF|uWd5+g0tJSY~YN$UNXxhMH z3o@BtI&~R*F*m2(m^Yh=$|`bI_6s}~V;|Q4y!+@3P!O%}??*ruiuJFUmHg?bbOm}J z?DM6cHE;+9)FQ9^?m5^x>H`CxW2%)ifUB$uYnK6@*wl+$j+iC8RN$XRKX`V1i@KWY zm_4rMESsLP(Tm&vV{fou|60)h&iS|X+bPVyMpg-w-JCJWbia8R$*P==)L89ShKr8h zgSq6)L|qtHu7>x!jn|Bhk1jIym<7*!q*2_WFBZ6PY=Ig+3lTw~&Im1T~A|h<>|A_P^z&fkaV{ z5IYo$kwI#*@Gae>0)H72w%R#VLV#Ki&B+t;d0*1hAFO(k`#b~Nt8=iR)(TW9l2+p= z0(LwzqsG{^HDeOt%%mNxAbdM|Ne;$84j-(I<`NJagVA{47ZM89$v$SG z{`=4WKiRip8r-ila_QeuB#t~ok=Nbjqd|i&bU(HG%xq$ISRfbTA#8gLuf_UaX2mfb z9P$@8@uoe7q}!E$Z9y=W$>qG{fAi-AP-gc+v0&4|XbVwKW%6>U6l;ilYRk>#lrlfq zx+`i%+}A_UU;f%s^I*L{Vtc>65&LhwnYHX4Z0%TZ#_4epUu5ZygMY?Yw%>c+vX_4ad|2lzs0x ztYIZ4=AzpOC(VNc^Gfi*%;!Nz12B>pAvujz4Zr~+c5Sl`JKOK^WPV@WEvcvXl2gs9;^s0@ z`Fg~`xBK+l1lj%<-oWBw7&oXt8xAKaq7>)5O@T%Yrzs5Lk4-QAkbK}7$Og*!@jZRAT<}Dm zF90xs3{CK)HL>F5yQ%4EsZrIpPC*GgDY?ag8fW;B`yE^d`2_`m+tXS=flEH0skqSb z_-F|%ffGsp-Z3qLX$ZS>m}70trGzjJUyB|v@} z+xPZcCg99ApXDXaQ~8uMWS;L#T6If6K>RC54GH%w#A|nP)#BF)HBy8N9I2 z%JCIrN;c7;oklJZ@@+yBi&`4@FO6D;w{&zth}Zcn%RJ!7h@KK%Ye$9NOuGK{yl@iz z5*_nm-^)v7j_z`5LA$Ckk)7DC3{~YJy8Umg=M^u1LI!h#j@3P@xl(pp7l;`f2D4%MYg+h*~1KGKbKy6%+;#C#-VabdFkbY z-5^doK}43fX}G~JUZj?;z#|`3sDI|9W`Sw-&91)b{ln>h4(&~e%9uG_4b^c3Xd2?R z_?aAxCGDk4{fy7Y5sbG8!Vx;&ONaeR8y=j6QK?PB6yA~oA(F>-=bguKiL^Gy*JO4y z1{$V30gM6j$?c8cZxuFXT@%gb{E=?=o!_2IG$3!Lan~b2v{WH3vFl4#djVSiQ5u^0vHm&XYSKr}sog5hS#!LJ)qk5&8Kq?T*Xi{W)9 zNV?o~V*36BQv@_|f$lyC|F_Kc4EYl&D66NU8s}!b)JzL#)1XL8HYdQQah9N!X;p|* z0e;ft>5L61-U0Ih4IFknBr^6lq@%p2z08}Wg-HOsoci-8c!N0jC?zUzl7>VLhq91^ z0?AGuT>DZ?$?K0Typ90fZ0GY$0PBYdZ{!9aH#aw=b0S|{osBMBO>p}KwH;5{E{u6>qz{MXd z{u!{Q0H8r1!tkhRk~52sRawmz^-Gwx5Tpt)hG?@Y*STo^v;Y;`D^s& z@@|Q;z2~Isa^c!Ne0$svv|>*s7pz4L>sQCB;7VCGz z_C#wRjcE6hfKBfWtr}^Y2hP)*pW$4F=j*m?9L@HEz`awrnud<{+)?d^`;9)qaC$Hq zQ?<_XvCoo6=;iut{&{(n&Cl;%1o&(4NXmmhBB9g>TAGrLeXm}_XZ#`D*nFCVXWIf1 z8}VwKd_rBp^1`sRc-mw+;}=-ExS@Rs)EhFKTrVB#Og_jzD|sy+o*#^s{0uPTa{Mt? z_9O91W4Uc@S@j`E|8>nKEw!XLNwVQb^Q~ImiEM#Aw8sfdRJI-f2-B{&5}_RD(%uHb z2oPtN2GAVi1s>oV@au|@q{C`?!(e1rW{Mv{`G@0`X;mB3!$H2qyWAa(aX)EIG%c(PRz z2YLBtUB>>JF&VFfFi|ridp(l`qokcI%t)*s1|@WX!>sA5H`StdG0hSzY2Qeep5Bf9BZuEIivIy8Po$8<(Lbi#e zB}E56(eEAYkw?lO3Ywb!--QdDppd=^gd*RchWDQe%wwZWSLnV?3jnX|PLAIw@D>q~ z5Lp0>zvWn4IWMlW)5F^wfg2B|Z>|aph>7}av+OcpZaK+b)2k8W$%C=tZFKrDYbRQ$ z1`rUGV0c|yDX9>MJgm9M0w8Gx{gJ~q_?0HZ>^AR z{PE3|lH1}7sVI+30xapC64J_pNy3yy?~>T30|(!cr>l;w^ehC45^dUc6}ePtDH&dF zg?Q}4+hCksk{N1SJp}O@<0U!PY(ZI>n5C0rvzvLh;jD$>$>g%R<_FdHH%pQC$Gz`P z7x6^z*D$TEPk($CB!I2kFvS{#gCd?@P}t|O!z$(VNvFk~r7Q(TVV+sWtrp|-Sz)d_(E}d{eGX(v~M-*$hqXul%Z0 zL3I!C06`RDtnd}`O|2p=Cr7>c3%Md3Fm9TH$h5_pEjZu%jaRsmj<=WAtcF6;rj$da z$wPZqIkHUrelzvR0VtKGvDVmc(i8ygvZu8oqgp?4bPl&CgJJOZ=3u40Yv|;JI@yNi z^4S|41~F1*75E`HC%ae%4O33j;%+8v&4td|h>S(X&07Oa^>rnT8B&MAngMg6{58t; zbB2qZhVx$!FFlMNoHP8R4k-T{a*8%n?~0E|>WS!8v_@_~v8;+Y!GKo5yua5>_r`zn#;>eDANq? zhy4%%0ZWErAUc=Duu;i-Ij{k60SO^+?2rn$hJl^R#bf{ngyjsJBa&@SPB*?>zJS>= zn`YpG9%JXOgMnGr?2Sd0JYj4Cu=;&SXbY#J9^K)y7%IPQR{H(BuJM@PQYT>jn=;Qq z{6JyC(N{A)Rpc(dx4IaWu1;zRM2(Y6(67LEdSg7AEi6yOtS;c!F95|s(%Fx)n`eff zM;6d~g8c=Q`$9l6I9${j@UG7{iAC;DB>-#ymI$MTdi%O?w_5#t{;X1+h{efq+^4*L zVHX&+2jge;9j}}3eitrK?}FVzu?7?Ewr6wkLlG_;PZ6E~GFC}R7FnX28f)qcd0G%6 z)(GYuPw2#N{1F&;rmr~VSjcEC_N2J@1e&*>3RD>a^wR`Q#(9NPwhAM$M1$imeR3c zCF>S!ai_G;RLBcIUiO_{YKjk*f9H68@vQaq+%`!{4zk{qr%$|<*PR?+R?=fqb`j`5 z>?4TD66pj0*>&R+2_b9N)_z7^xpq}Rh+PU_jI0+q<3h+9rKwbg^RHQ)naWS?K5f+= ze_tmf@Kzp7BhTpC+V%Hcv}W+F{6+MNQsd}Cc0!@w*!y+pxz7-w9o*v-b>wf`5*1_~ zK#}Xfy$-GpQa;~ou<)y#u{hVHRQc|~fbwN1>!p@4TmgPfG)YJV2%R{c9{mWNwh+P% zR3O59J>X&;?qy!`1{2m|o4W`wD4MK&nY)(D3#PyjPdXriw;%a?Z=orl70c1)Yd_(B)MT=#c=PbZA2L-$83 zk1RFYZq)#V%Kmf@wVw@qVg<2&|UBehG z)pH8MXpB#m+sX}^z`mU_&f`Kyl}VdC0v|$OnoL!Bys~G*{x}jaLV*kdL8S!xYU@_b z0aVCPq!1#Rktc-`j?$fB^7;*tI9^|&8bN(ll5gy#s)l6q?HxZLg>uOF6+x<{q1e*=hzGyeqjSfOvJ5m0Z1%^3P+8ML_P6^;3`Z~oRT*n_CV_LdF!1|>Zgrh@jCWZ=%oY^887FEzU^RR^S zqBjKvDyGVRox23uIlyd8(_N`<6yC8<#$L zSBb{>je8K*bzbZ=$q;^zF)~w+(${bsi|+&Ee%18vGcVfB3FB^GR$@8e)X6eO#^5kw z4oO&t$(z@lUy^ng4sH@@nY)t-y|t5<(%W_%J8w#w!nj~O_@>r*6?Nx6@y;V#HJ(Ka z-kGsRQ9Wz2V!vHkvq{fmWx|TSzk;;CRphaR=!s66F&YV9s!%_*?uhGpM)U!@!|O&9 ziId>pVn_B7=3;MxCqI?*?ACL~4b^r&=cJX#t5-x!!Xw}r*gH&924E;xb$|})PMme7 z1jr<*teti4=&vdWg)Gk=Tge98Jmf|L`MuD)f8T13hk}9b`J>R99!^8AHyI0;I>Fr~ z>8)INR{6K0qXb#rIH#9kOxRqR+u&%7Fa7zYo=0fNn|1arwnjd3{{WUQR zD~aUnjQL)v1GY%~efRt*&-TME_SNv9%k2;@U|`S3$bHa;{sDBS)vZlnVsukQ&N}FR z@bN5bi@L5mzztN^H91GX5E@Jy@^@LoWjHynar%242!uR!$4&Gh1K%?r&Km%(G z!jWN?!xPh6B|4%|M9W6tZf9B=f0vjd8*|sf@AH~t`pan(ZW|#zd5k6EbwL3#8)(J7 zE})c=W!h3L(fCoAUsn{IBYcZ2I$xjet-^W55)(4`Utva{k68sOa?sJTw^bS|BB`6c zG#I#h*JL8K``*6s(xZ+QedGfPFW%m(?Bd8sgXZAUcKaezKyn;SM~;iEXrM8;mGRpl z8Tk$rh9y>!TmDJ##CrKqR7#h9&`eiCNs*Z$u>VJnu~tnx#q8ns?<`~YmQJfPEznB6 z-A)2s3Uz z)X^aOpDaa0q`OkHzX-huKX@fu~+;1S)1q)tYPOg29KwWME zfV+Up`n7YxP{ilw8`jvFr}8UKkvO~6a!$s2@R0>oDg+-uhWd@4(!o~bw6~8BVljz` z$RVze;S{3sI$JR;MlyO!X(M&&YjIyvSE($yk&+>m%4diTB7+|jMXn4xXC2Fil$v0HzM=1w!{Neh9HC>Fi?)n+5<`iT-X zNtZ{r-|>KLSt^wYF_BL@jDOW*rXN}HkCJRY?#U)%w`Z?5H%ens;M1OZ=lCu!x_oWq? zBkJx%?n22<#;&ofi+8Xa-*b%!kHVMkYAzxxJfcraA3MvOdEXt+5$}-n3$;n;*#k3( zmILvS=!K**dOtq=70<}9goNWDip8IR;ATSg6Duj@F2BUgi?Q7&Gkf54PyaJ5m!|@4 zvmkj=AhY{IsPHsy@^qO6ZvI&{`At1BLj4;v^=pF5Bx!~$5wW4RgDAWdf0Gi0lT|FB zL(@NgSqRe8)TNcy!0tOvj|?Bc2VzE@gN2T2c7FIS=|XKuqFxwHU!3A!{q4jrwtWW= zd~a*r|5kQJcvompn1ufRRu{V2rRL`4UDMv~x(g>$n0B(Zx5?*7rQ0eVk1s_O*R>Vy z^E!;xu<^lFZV68h&E(5tJTh9#cRJOSNj`SIbY?p_T<(=`SuO@2Mdi()iZ4jnc3 z-x)cCs_0swfWkDI4eht8|84o#?o=Hew_GQFB{$w{l@dqKPAv2iFLF{}*)BUsv%pd} zgX8vb>ZaiJy=4yO$Uac*>5-;%tm_yye0unP4OM;SEFt^LxQea+fKLf_CDXt&;GImz zg4bW6%UsOOCCT_^Hr7rzs=ZX~RCpG0t~lVH0W>UK)re%kw3y}h@cY?t_8*M20iHxz z(?#mx61^GG52O>GQDLiv#Vu~y6J7P;rjl3)g4`hwl?25gp`$lsGK|&$3k7l*JMD&)T1zDn1-cFj|MqNOAd74AUPA-9 z`J0DxTpCRH85uQZH9AtEq2L>!OO_-4&cP0Vswmrr`?>{ z8^)B9uTi<(VdY5T>vu6>bjwfcbPH^}HNp6lJsio}MxZ6KwsG?HPc}oZP$*48eFkY< zSG`(cyO4pVxml(f7S>^4BjYQnI?f7w~a6PxmcP&p+C0 z%TTZOkK3ikB1_%YW)As;E^N9fxIy|UDaC<$cjD55$hBG`wK~P1X!wZ1Q$7q*(IE(r z3N}0vR8%Q3`Z_$=u74(mTzHTd;6D$`FbgRSlxHEz*eu1;5scX^?|ru$tWAJmZr4wF zG7I<+V^f&?GiXj4MMT9GAD^i52LatR z7F+NaK7*&D>Wqm7RUx4hx-J!8GpVIx9QPM>Nc;0#_MAc1=+BlDza9{0@z6~R7Tsi( z{3NO<1!A9%XPlr(=1YeFWhsF45^-LTb=ab(rIL5i@vva;tT+%X%DSC_<4MtSx>_xvOiU{AQe{3=@H^1U~a(I%9Ehcb~=Ed)C zB7M}_2dbOZ1cWvLo*C`=zee9Ma@!T%hq|ln2Wi!{SUZsmWCsSfP_Nf8{eD$m`1Nl^ z5{7%PST)mh#$t8FNftMEC}H{U7|%(~j{Wlq!urOy4c6gSAXEY7{;60|1xj1FM%+A- zi^kr-2OA0mBfTp(YF$b(4Ie5*W1@{Ff<2l)dA0nnmBkN+iSJjRiy8q2y7guo!~JA= z1Rx+fpu$gW9?)Dahdn}|tmW5Y(}lHzY&8PhFbf{SoA$h1@XCH6!hM6-Jz-;OOPx8g zZq6*_NBhSJ#tR$6`gXwqzKMhG2k@@G03BqYC6FUaoKX_X13~PK!$}xp=a?B#!CEY@ z^8<|9@$XP%xOiR3ty6;Cd*rAPb|E3i-Ls>VwFz3O^xHhb)k@wrX`6rw2K2IMsqtr+ zLjIQBG9}^yS*4y4jOJ(p6*O?)F8}UG?f#~C;cb&;t_GhciWOseJ8)|COZt`1|IuP_ zW>mq{S#xnmv*K_l?F+f#DpcWf4hx=APJK>?#o5s$0)Ap0fl%5(fOo5U>1lH2Yrp^r zfi;=0#+oQM^Yy0y+P?6bme^}y5e~A-*D+XO-vZ1RHfd*NNR2LT@rC|vO0@o+*89@t zh|SDIS(h$UP z3n999n&H@^jj@V010O!W{2xtc6;M^zMr%^KdgJ0b1t~y2H1-==Nn@@<87yZwD$f;RWMp*e_WH3nZEx}QqR$Vmo_4P zNTLe#rbEwTDs#~ENdJ5j#YYfGsg;MBi`$mg``a(xG4t})+b^;%)tISGg(w#_TVm|U z;<3yz>eGI5WbD_`5Jm5?mD4HL4X3^Ej;F?x!;@nwFkt`tJ8&0?h+4s@$P|a2e4Mzc zc^d3bM8~Tpn(OME$hUAn=&bpMDLDW~6jVFC2uZrzd@9%h&@R|U9PwVF7%YtfyWaG1 z%7)+p{af?V>HjPX?@z&q##G10Ua=Htuu)aw)Qj=nH$OW_Lh$={GX%{Ou<_BJR`j3c zV;dvb>&cTVhn~vlNw*sPAk@BR@ZFounbXr|HnM9gH7Zu#qd`3{Ag&hX9>GB?uITeR zP9|xn!cy2lF@Oh3O|aTX0n_@K#rZF%_hpK76ewTE+_HCE=j{3d;dxwrY~KE- zZL!{hmrWQ1RNp*2Z0RB&UN*j-9#%^*XT@}3Ee&9Updzx5_a+dhG-(q2L{DJt)vi|r z>LEqL`Csq^6bfl}jm_=pVD80TYx%!T(y|Z0|F7}YTwNl@P3-}zTib6;n36ziO5TTR zE*_vr9cWo*3dqDsth9q1Sxv_~^}G!k;Prj(VKN`EHw5M!y5fP_B(S923(){-l4^$G zC{msg0p9rWpJ(Xab4sH|gi-;|%qTcHyE}syu;jnHzt%v1Se}H*^}U$`6g};hlSY5K z?ww(IzTynwD&pE{{%_b*M~mn88c1i*CC<(%GMOXmvIp9D@dA073S2ZlA*Z~2(|^-=z~*s2Z-)0 z?{?H_X)ITntHVFTtwUYKaHprcm+m>fv=B3$6s#v>#G$s0=VfK9E>)AUJ-l z2&x*f`c{-;0x5>8uB)KZGWozVErjim`qJuTE~Lt&C8<)s*6sFI36@ip{Kxs)|1X58 zTT~q|^&L`bt%3B1-C#jUMTK}7zu82VufGHyBRZsqu|&Ik8*SH|pz@_C3_X z*3OZ3gMVDN^mioW^|UQufF%*H#M2kja6oWf|4qonP>M}}RRe4h01$GxnV2)j?e19l z9~YH@$_W+}RGy?$i9i0X)5w@;?)OpT76SXSiA!OW)0+?9x!f@19Z!j)gNLkwciQ-| zZ|hgpqXQM$#t_5>T|=MG`y71FR?S}^$}wg#;6`lJs8Wr|whI3iVN8pDjzhdJ1gb_Y zR$>Q?JWfu%K)vRR?KKAU>gu98!xf=iiGXXgKc*WIly~yxreTVb9g7on(grpjTB=?C zew3})U>?ES^BG5cWHC?*78U~G*0b(ML|nNOovl_&zguFCiAk8Ufl$~yKRtFPM9%(W z;pfQJ;7^oChM%j>;I!`pU2cK>DDO$VM?M~lNvAInkiPHsC9}cA5p4P$FmPCP>!!5w zXw(uhY-$V8UTHkis|Ld6u7OXpClQQ3%Oh2OPI7L4dVG8pmybV~>N z99bhbuyFlY1EXhTvXS&Js>EpJxBLKC48_9(4|p?x%EJ3%f0pY5_Q}Z!yID&VV2}de ztCTq3BHGIUxF&fvJ&csym0w{(Z_teu#lO3!=$rW^!x}W^NLyRSBJJ|LLMuG3K`qu~ zNfs;V+mt!o)FEh8q$T$xEXJ3|#hDEZjF^G2b+BHN)qB3LQ~2zito;Cg)g42}sNPR^eC#tj&66V~)T>^XEk>|?`%~zvIsOCFL>ee$NqAz1 z6aje(O#_T2vh`#NT>h5%fj=?+tFssdj6CC^zPk%s#|b)oF-W@O`e4NRH~huOT9-GT zo+`T~#TN)a1Z7Fw{C=&iNCqIKzWQ)3P}@0{BbMuWWiL>kLM$o}ZH7&wZLrE)Prc9u zC&_R^G;X}$;6yt_7|0BW%q{9If*8HH9Cl#}e+>IIs5Vp;zSuDttLl=GFJpeMxa$#S zgsIgcWt62bLCyLJMrWA!D+G@#@d6!aTU<-;7~Y$LV)Q*BgqsvhE~6V7C==964ZptS zPv)e>^lM0G?~`W^iLnfE+S(!L73h)e8Xq`l;e}U;N++g(cjAbiaI~Xes(ZjDp`d_8 zuENyxh-MVqK(lA^)h!1{{PvTC_q7si(f*Jk-*Z+ML__n_@a=jM8z<2Hfk+^LUb6D} zm|$OQCBnhw>NK$jE@0XyKCoE#Js-q_4M=QSN(>rpux_?mBS17KcVl_FBR@+Z;}1r2 z-h`$X=7CNd;ymfv=yry-Jva!*R+*=Jqdc%JsP9=X6Y%|16eF`RfH}uLj@We4oCb6y zC(POqe4j$DxuW0xEn(8Q=;e$ItV+!LHW=ku&xmKQrwSD|pbU^zy-0UM-!3U|_eIRV1f2(x##-pvitQ8(d7u7!pG3FU39Yka!o$4Y7*7xvQ8k7ZQiZ;SgOZE!G{lB zRADc#A-hP08^hoJFJh+c4xu=5?^j6W$c=>c07u+ClSD~=Z{ceFIee_93QHUcsFBgZ`AlK#`SG;~kfB>S-($Lehu~&J@>kdD z>@Ofeu8tnJkCtz{r%inu4wRwug(|@b^_uy#??JF^e@{DxSZCV>o&V#|*GpZ(H{!8Q z>2iVBL@lX(4UT;@Ru=N8=6_0!Y!tWFQur3Dxrzzt_ZQ7c@WUW)geS!?-u*p@-5mB~ zv(Y){tDh+{Q6gk8EXri@U6$2ny2m_f(*vA<65*u2DJxW7t40%(_pcIF z*J%#d76g^H{|Hbb@=Hrm{_2BZs(n(9&^;smO&jqUpuz)cc`y_Zy`3R|dGXn8o1s;* zreaHN(j=9!_RJ(qU)}zGTufbk$$0!6^-pEt#D^GQ*86enuUJCQ_=hLxM%1|Y-QZ9iy%fwt-8k(%N>?GIemTiTq1 zjTI=(VtX{VeUgZL#{2c)LhPaMj}^-g#t~Zy(H($KHnM z49B|fe3=I3iOCy@ky!srx)hGIh!>rEl1@GK!DvAVe&6!6d)2%d?{qN!P23qH+-5jU zMchnJrpdKB^39Tnv5#Ms!Rdbt^>$wlJ6?I@dRKEvGlxvO9OyQBj8#0}%)#(LGTc(R z&(o}`$wB9_5qq#C-`tJfxKWAE7Vmv=&4qi2W)y$<3VwuQ9eG`@F@qM`dM5W@XJBo}lI>PlPnw=kj0~Y%^I=J$ zLhRha!oWk8)qIIs5zi1-4s(Z?NhN`TcW__B30Gn_Z6uxJH2KZ@kow9ry9k~GnZmIWTwG9h(V9MIz7s)gZ}(0eg8fyJW$%YAA8 zlX-FpMVjI(qFnmQYwF$3bMBJ&Rq}JQ+OAtccf1dGv382R7^lYrtVN2`cgquYPDN5O ztQ#XUBe>}%FW4yOc|1r3P<*bBe;oIIt}<>6mGHJDzu5|qm?SQ12rUazE$z*j@h3J| znp9V&Upw0Bd>ryUrY2f^|E-3udg$TLKefU{`>{h(V`knA)IdpG2uZZ%n`bZTZm&D6 zYtv(hD~7DFHD-Dtjgp(m7H(=vNP}eb7y8LZ$Zmwp)81jUH`=I(>K`-f=b7a6_AWYDST5$4Il6>2(7w0GuTv+M5%(LtfGMi#JbRj>0Gxh6HIG1WX#af$R{c2nh&Qe4hxD7X!{hUVNv&1@s_IV!)?8cs6nq4h>gDU!(1IKDJJI*9(T z*{=tA(~>SiJdOOryfh)XjG?~Rlxc)DZ?7_%)8cBMclb`7@5D@`rD$A$&X<52rWVUaJ*Wf@rA znWuZOI|s5V<<`aFejqFm^rEA@Vw+~~aMr2^Ur)+73% zN@(A6=9(Dr6W+IE1ZBsSN6MHGN_hv9VquAPok;ngjr2FYJF$DkY&=Z;-_^v7M^Bn0 z$o~oIsUo37;dcglY2#Lybu5UcOfMaGcpqz?0!p#l@e=5bz-kDE+PCMZwtFh|zn3vC zeHjvA(3>Tr!b0Q4hP_ynWxnF)!G_;Dm8mbcUjgrEnt%%xj0Ogh+hDQNG^qB%0x*vV zoQBvH;m!BPrMB`kT8Tnps-tz<%5yc`P>A-(fat>aVd9`jYUpo!0hoUryfz?_GT4#- zOHx8v#%%U}vIm^A@Z{MHE|^j%P)WBT`0^4ZaUC9uwXM#vi8Zap{;nm zY-^$YT=1zt40&4A3kPSjIW&k!%Aj`%4~Z+~Brs+Y@yds)RhW_Lo%Fb;cCbOX2fWDg z!0$ii{x{bsolWjIOehGE^*svOk$i@xyiV$E z=6_pz%{bVuC9P4(4ntF|G{MMyeevk;$S%7T1!ep4-*?;37o?!q>na){3!0~^9q9u> zkJw}+a$`LlTa4mXL-8k1RXNq?;z8ap+-*T()|k2>T?IL)6(%JS`y0+&@OtNhmq|x- z-YKbEPurSz@<+$ZpR-zZQI*YRc(C>d?EHZeGF!u?v>Xz9V00^`O3320u1zwfxmfsk z9TJD%v>HJqt%(Nt*#pdZ033ASV&?Z5?EJVv2?cQL$!_tWk8cElcYj%Qj`zGHez1Q6 z)`I%%e=~>+6?c8iKM>$kzutR4Ki=G(xCE%&ye+=o)GiO!Mp(X(L`{q)nD@!#!jyq| zn`Cgr2F8-J;bhV0QvAjZ&=P}wSI95aKmUtp2zbL8LN z%0zYjg=f;pv07;ef54ynclb$hgV&DP#p}STphCCW<&2YuKqVN71C=&nAjE?}IaTmu zee8}1bz>RJH28DUB^u#sF8TEO^4$i`HTg#J3&-{g z_04}f%=h9FBO@cYpeL~k+3phIcRgq*Ho)`p54K$2Z(v4E#xsw?l^yWfsuMn5lB<4> zJ*D|qDONwxJ$#)*GJ`7e1wq{-`fN(%^!#5KiqN8IkSblvE^Y{(Ig4xwmV{;qQPFG8 z#m^9-95yS4oZ#{m-Sn4^PJ5$a{Ea6ySG;hvm`aB78Y7NQ%kwgxz5-<~iE2>#OPV4I z8AzQ|kzov7$PZ`}pSAaPAPT@a_FRZ^r%yQbuA}-^7DML z4oqyG^fg11WXaM+H`lM$J7n`|qD4obPvAtq17=OHt3`d7B05AGKA2N4F9q3%u9$bx zM(QnLSEx zqcvO{Y&;+`&!rHa|uH* z=VFBRTOr~y)E%q3@JTu+8Hf|~AcN1ba~Hc{7OyYf{LgA#jGoGW5L(wtN*%bGM1yH^ z^>Ardj3bGFixOo)D*@Lf{6B_j^lniNMHLBA^q8S}-(QUN#Kd0z{m|_fKdq6&;N}+m zp16v4FcQH|hTr8_DXGWP#Df=W;=KvV13GTvc(GDBs&ZkIwd2yOoayJk$B96+3&ASl zlTAkFM;%Ydvlt*zy)IwiY6hc4tEw{8*_Hs)+(^^2z=N^;a zaYYiQKmj5`(5*BzSYn6KwYfVDsjN z#9$2WwixIyT&OKYh>jZ?g$?q1iKS8h9|F-3kmDyOZ732D5*aEjBF6$3pbiC7q!~MH z?Ky{OdaX&iVR7E1w?A6$nX#@fVpBETmh^!rZC4Prnk7}9zyUdSrk18sn1-M`zXLb( z^4#_TIvVVwInPnfauErY(Cg!47DoQ)bMJN1uaR%gm||V;Z;e8w88MN*Zt2LL#LsXm zt;nmBE5aL!UOddFlkjsUA~iYZ*UzK}Q)99}W{nvd2a^D$vcztt`XYR1#&K7-JMX%E z-f85{zW6$$q4kKqil)a?3%{U(*lo=c>GpV!)cvS$32>^Q>HF)@mq0c8N`}Yi@h~ItHmFF8PX2Xrp%n& z+0pudX zv9s9~Mi6w|`sMOJ=Bc*!suPN^`9~$;FXLr(c!f}kyg%zjq1G(dbtNYU?wYqAgz4%$ z8^s=3s-bmX$(d4nJxxi<>!7>x{+ET+vomiI@(lv9>57sJQf3wBjg~7;56gDH0!~xL zj_WWNUXNAqWg07n4wbV?xM$Q)lp@ho&x?$^QJEXps(>_|QgtptQ4mO1=0T>Q+!R@J z`rk(1i~#go>OUJj=iTHAw)~K67kYLa=s)FGF2_%(Y|Fuoegt1cY#`PULC!lNoc|9b0^L^)jB zGi2b;TmB-3zD;WC*D6Z3_!;Ca`pu8+1ABVEB3Dm~sUs1SXp6n)XSr;M?(m1`-%y1` zs7{%nyb&>i)R+n${a5*P)lgVE3zIR!=pC4tiEfOu?ghpMS5s#B z_#dN+>9`Xvr-mvFH5YJ&gS73zVFH4JBcO6$X+EL@Q;|@ob>`wTx~-&Rq4ITU6m}BI zK__Q3e zfBZD$DvQ%4;cR7@1j`0BPF~I)u)%~b*70H{awMR6|1)+}dOdlj`)yR#NzK`RvrLA! zcbq*Lxj5VczMKL|;{Nvmd2{tqJY=6#)c@HO_yM?6WEB%n;uJ4fmU!Fz7@hldFQS^w zj`r>bB37Gni9TNv-Bsbes|qJkP^K;XB$tKBl|u6D*J>c}@A`zP!UW>*eSDFM)KX9y zPZN`F^Kp;vjsLw`S0^z+1R-~}4R0jPC3N0qyv*b!okNDK-k(jcsmui(zh-=h+{8pW z2kedmM5+F!BB>Dc>3CcQ!~7z2JoC>WEqZ-Gt1LzW|L}@xo?_9@vzRbhxxj|a+UcsR zqY#XU#bCJmiLr$nu$fwE&njol{Da$9CAv!z1P4LtI&}v@pKpB68__I zC~D@fxiS}A4SW99KmM}}6BFi?!wI;R5q`(Fyaq?2Qx<=_8gc$=S!?(Ma{kfJh9~+fv_b1I>%-@#g=0|P~7LyDC??Uaeqjv2Pw7e_~T*W@?{r4ej z>=$J2CBGe^6h&O6jV)s1ili_uvphGxN>9wI`@7iZbBVuGO!ta>e0YT2PCY#B#I zZ_V_+zg~<=_Ret=Q$|FLdw<4F`k*}eAnug!n=5o~4MPJwKfQWlSf^eIisI8oZ;&je zNcfwupm8GK0g*B64miA3*EH+c*so*P`RTT7`r&*=1_#D{U?1;mabg`T`0*-gcBS08 z(5||j(qjs?#*%p2m2lhsVp+ssU=YlT1etlNex+88)hf@v21s}2ahp%YxVW^DiigAmp=7r_p`YFFB!tOx>;PT(6JG;%!x2w zs~x+BL`H}2B%fLJEXz#HZ-#x+*0YN9ov@#jlEnoh#tfDr)!JI-Uk5S9CtZ>Yh@cgk)<9qlKaovlYoFvZ_2PQ zUt5_@6hjwPQFIw}^i?!8xzp~ap^KtdBbE~`*-EHZ@J;|N8=TtUGPYjJU0m|)T{b1)F9AFTe%5=MMGcqn(@RI688`G z!;xP|*4(6y>x|jzji61X^1n4Fe(wRNL>zGhjm>!)^zi&HUG^^2+1-Gdj2oK)tL0Oe zz{ceEBF5!^TRT7xk|Yz+#GbTETO^A?KEqtCb$%5!rW;bm@ zxHE6iF!rYoz>c<%A@Lo35I%%S|PIhedK>{D;uxGFS=#GW`^sRFNH4(%5uQ9S(!5Y~HCuV7Se8WrVBYNe* zt9=w4@t$uE%RA;78p1D?0~vZR9D`^EJcnJ92S@$LmLo}ESEZB~k4I*qE<0_}0I_Bj z67M?(<5p+ujSkOHkv+jsa^9s<6-MIy)7p&aUp{QI z`MO;acAfGNG7xk-fU4f-dY+c#pZ#Oj;n>nBFK*KKZ3=xj;&pC^>|t~Ep3y!~i{rbg z(~c?PGcykSJzBI_L>(nIyQ;oQJ|R>nqlxO}D$gHL`hn=zvq?~TOYL&Jx0`rCs+-^| z9{VyCl`cApK{2*my`xdDnasWKm6h8YD4fxbomvs?+6Bv>t+t$Zf4al0CmHFALfXXf zBG5#?9!@dhziqL2Y~3c z{q1H`Wucf4sI{!ndCvT(1FVo<%Fj{pZ!TEFd?tN@m=T4jmO&)aq#zIuI?F+PvQMzaH;% zzAz2cy7td6#rPFEA#AV|q=6Bg?tH1XZblC-402F@a?j;FMab#t{UD}=PV&R6gFsf$ z-S3^WZtZXP_QQF#6lI-Bnk;`4BkU{{DoP6H3NkWss7{(wW+9*#B2HqJ#VeZUPwfbU z8IEA>D8Pwi9``?QYQ0R2-cPeOUu|iZ5Su1r91$v^(%D761-Tb7}Z4DnFAr&%wzk-^bO|o8Q6V+lUag(p#YbfB$!BdWQ2JS&swH> zXWNlM)FJ*--x{gnJH&jAQP*T&SGkrL>V?|$olGbt)Xs`to> z$7me%3CPu1f9}7`BP~iQ9+4Bs8aX77c4f?YqekT-V>%cj+3h-CCQh<3DUO-*K!>k3&$V zFiSjZ?CQxzC@TpL#@%h1fRh&^LD+n_BzeC3uX|^{pNVBR-;)f|kSBUE!+m}lIVnRQ z%Mzm*mgIqI>q;pqAUAYAqLSHJXIoF1v(XVfEU={kpSU`!g-jIl>1>u(o$BLv#QdS? zSBv*@wwBbkzcU$=!C{XhEk;tYD_pVb+ib7uz>cPciE+Sx(NFyp2Nr_=RrB@B$jH0c zcFDFdF8ISFm?K#LPdaP4QS?d(&arlc7-t^z|bR~{^u;-r>Obfqsr z_Ud$_%a(ZI_Z)SC(4i5pHM*Ed8Raw4qNEa|sT(}$Ixv`n`G&Ku_cKD|$5a;i+7H`) zYEJ8H?w46tRld^IA&nsJ!lFe-bTWSVp~`5$efr^3e4x0vh&R=818T`b+Usbe3X^;^ zf;0vi>{(?xf*@Op;WEJ&)hxzTEg=6v@Z&$)Zm%EKkzAr}?^)EM4YSCW&HD~sf18jM z6X7Mo3(d#wj}tR}?7SQs@BHdQ-L)Gx#g98se||cjVDwzE$wUh+|8MktLe5SKMU4Bm z3SHC!<@7d_l2P|xX*{VC_dj9{zIwgnmv>Wa+wbHkU3(E>s&Mku7HFyOBq3Hq>Eb0r z>FEm_60cL7r%~qB25H+)yO+b|1mB--jR5(78>i;LjbG5%<(tQ~azd?gq`=rYGCP%E zToCY*G-nkNDd)z5Q%neheb*c{)Ul{p?*1JWe-Q3MVJ`L{2?c01SWOPPDHzNWOh@u4 zLL*KMdaWc%?ybazYH_P0c1eB+PUK4D!jJ(zr=~Kj>DCk|1%eeD5}pfCHUNCt*gv!K zEY85RAEnWoBpLif9bzE8ZNxv$eKt+Cs%XD0+WqkJ73o;jC)F1Zw9Im>M|hzSC={11 zxneOWuaZsj)m^%W7*~4=Qp4d3Lu07=88fJ6e=d$0Bvs(cLYB~zFM2-D_6R&tn8#$_ z$IPZVNm<*tFBc$~W40f5rN1;+!Z<@KgtMET+3oU27zi%xnBu9hCm#JRzTscX%%tYR zq~9|;`j}U_yeeG~QB5dS70!_#pP*u$3ZQMDy90g_1htX2GRV|Y!=a~-(G+XZ$L^vT zNjKl;3ty`Lv5;P@V640eykkkUZ_Thf#0p4#=(p$2kY<%%<1bf^02betjrz1)(JLB` zQMe4%8n7ueOS19+)RCJu^lh{vYq>MV8&zCM;b=+<>xqu5?KKX9-xG0$Mf4FLDD#@B>oqlX-+LwAmyg6;XfA;3B<*uppv z5hdJ`;MV=CRbW?zlW1(u4Hza}8#cCq9{}_E@nrHO`q_FeoJ)j!wE5K%_OPaJNu!OY zNUm>m3zekmvtr(m*5iXhZj zmT2wZ>6(1QEv;%FOMW*A(=-V`RYuCk0Sj> zbGYqzJ=^-3l8HRInYFK|oAGCj8ucerKSjTt_%E@i1xBM$SvQLf+)nF{ zVq7hHQMRHV_G(gg|EEO=aSTi%Zm}kihoo>Q3B5ehpRxhV{;Y3nlVFp=O#CI3$GjMX zj5FtKF51u=)2CSD31Ms7>k{IHLEvXrW_ohOd~EA!Z6?xsClsRJw#3vb z=&}8>-(rR(Se$m%pv;?+m6EY5SZ#!D^A|k5< zA_QmDpo+lR>L~lg70(#Wt9Msj*(+~$pW`bo>+EM~{p)_dY^gGpwrp19#RNDRBaQ0c z>>Fz*TEiz_KBhFpY+(#T?U8;7#?&Xk4aZ8$%OmbjJ6HlzCi|PtG+%KI;cWhx>()R7 z7rkJvD&6qUJ>gskEBq-3T;Jzq@{2>jnC{KT-wd06H>Mvy%9kU}e-ia4?|A`OPygdb zg4{7hCV$HcT`+Q>ql>o+`Lte>!4BG2kgNa$bRHb1e_Az4)n2-iJxbGtfqTS?Zac>4 z(F{oXUt<8ux{XWz$O)B_Fg$8EsEjC~!qDlbplE7A49_!)~tm4_v{ou(S6={(G~1d%i0REHui4olMz7*PZLM7o@Qe|G_>pe!;*1U(_K5nEpmZhc51L&l5VxC&)QeaaEfImdI76WiZ-zj4?9 zlCXvyi@6~Pw0>#JkLdpXo~ec7EI4Fons(FHDRB7}AXVG4<=JYB`YU9fPSi1JNw zy4f6UjCFbU{z#P`9S_A|P6l0-s63Q>X+2^%t?V>^5&9*cs$=>5#N4o%eYz@z9R?H! zfCVtdVjt&TrCH}ULEmD+#`ONzGJ+WbdCdr@MY?0wCd-2tqA~b!N0|`PL+_fTu;cL2UJw zEwk8w9sjoL2ZD0Mfj7)=2IFo`WZ8L1lbK!|ecs!w`LHKk0xR}Uu*H6KZ(;B~L6Gz6 zoq)qqyFXjy;6fv3ZRp=%BlOXn8HS?qZLEG9Ii_g*g*|Ck0H<-8Yhy6_*g$lDPv2ky_=R zt94lwmjOQs^bY`C0KBqw;LwMo_)QZs&{BgES|2(2Xd3(DC`}r6ED1HWsk`6VGy82o z{JxuIgvI^hLNp)3Taiq}h?VeqCE;}opEBXpFD3P>Fd4}yKLo?#&{&(9G~WuTPt>uv zF1at7&$+6es4NlXEYg{h9)ueZ0q&=E7c z+@L|Qfcz%A_P*HI==^uBuKuP?mYIGH8WAFE)3BZH0O2b!(yXl2bjkUsX%U6^D42F{ zJOFQ}U?B(3^Vg7S(~UaTX}#|uMR#&pjV9rvjuM4K6TV_)Ni1Ji;nFzGQJWlB_TNrV zRfIm89;oR9Ck>`drz#a(ND1Jg!py@kdjs?rsuXV8HySpjT$NFeR;Sp4vVDExVJ_R~ z>~V;8P+cj?vV9Jg24QENUc!f-!ozf={TZ1!(|?es;a?;(oR*1qX~D zfNc2IdqnjG5gT(V8f9P|`0-H5chI`FEkbZhWq zJ|P^7?M3;`51mZmY)p>T$o(<#%3p3bitOdccXc0r|RLhlG6a8(STW8Vp!9H()UT}&=EtT-zCHkSKixnO^iQpD^0 zXKMS$KL|CcV6LB}UF0TIK+{&At0&==LE}bG6n~bBv|>aG_-zAkn9GVADH*-R zX@2GVL>RUIh}rX%nfuitp9L1Q3a!7cRl$?vY(cLl57e9M6SY+#_xydJQc z3f2>tFSGoZFHXLAo=u}v6Klwt!OBZYIv9^xXTI8(@f0WK7VXPx!uC#w9>+XCxLlR= zIW62s-QIq8&H8V&5XCDsZ?7a~y|=O=osYk@p8mDEoDKej|JW=k^0F&V77E9VBp!1O zhP6zT_2=2k%@g!^`*;~)F_Ob;D6*_Fa>5=VXNOF~ceT^q{Si9v&bhtk+C_iTAT7%o z5GO0cIUkm6iKu;~Rt#*RUm;#0e!VSIt|*Rb_rb*fvd4zM)KaCn@&B z^ikmw99XHn#daL5NosHFJmt3KcLN3aAM@Y8n=H@5k676oa{u<$O~8yly@#nEVZ_Gq zR3CWv#urkOgqiONrg%9!9&;c?MY^o{O{=OHfnq+_f0vA1&IkW91JEXIWst|jlBx_; zzfDV^9{TO;4~wc

    gu+EO-0lk?5fpk@FatVvC1~c}oxl1C;X1RM22z=4r|Ep*JkUX-tVPrsj3Do?NVKLTK&l#A6ziWZAjmv|8?x45AtS z_kX>apVX()K!RY<{ZUB&o_Zfxpt8F87vCkigaIhwv1+IRntW(z4|mKjEi2YM5GJ5# zX-UVn)?jtIs;DE(@^d-j^T$W*CnH-RVa10lef7Q`1a5#9KxRub#6*1B){YQ@^gHxL zQBu;Fb(6N@arP5iiNEMjx0!7!@1?i{7owCWO< zA7^vwqUU#R&CvjYRYE8sknZtwu`=(%Q@JjKEa>j1jqU=zRN88psxs-JxgrWQD4h8x z$;{;ToUSa0zQKqAU2sT~X&k>+6|G|!t>T{?})8$S5%+#LpB7z%tlHI zvjm^~P{?q@rDG@m-Im9IfKi@UP|jlVt!x-cWbqFqm=hUOTaqM>R{8}48T;gJ=IPH; z4d+rZlpF;8z!`KEW)r(zRE!Ys1+8HZDcIoCC&W5)Aw)8&k}6Zkk`eH}wudF2xIlR_ zBVe^XcE-spSE4Dog}o@+jq)=eB09YbApP3{-FH|3Xx@WRAlR2cY~(;W%%#i%CjI6l zO9%zJtb8XSZWS4sE!NA7AJ?IPDz5v0p5xIrH$MoIEQ2uxP%4({vZgn9`}`|iyhIYq zt9YNVw5A&!0(sBx(3JcMqzL@|RT#_d^5(*d`Xi<1gBI7L!e`;Gci-tnbTUH|;S?R{ z5!8ZZ6QsFYi<2e%?8zSwV*U<^h{+E6oBZBc%hR(>+0%P2wZg4c&J5pkFa2fVhncW= zHQC0Zj-EyM-%GP1pPMj{WA@oGYw{sQ)Gm((_c~2!qk$d#CD%@zvxtJs!Tc4kV|F>o z!rD?)m?>CWWRSfM=3jX|O=eSwdFG%FBS{(2QKAs3m5o#$Vr?E{g!~)3**YX)qY>hl zv62%f?Upql%?B|})M8IGH?`@X5rgAjIEV_U(PyZ;jb(X*!6?rH52!_J!wbVltk{6R zIf8zP3o7m5oqHxDz#Uc;j=z2m9L1 z9K3R>Khzj+2u@1i#B}*Gs;tc7yQRRic%?lNR3ZP)&18D&_NKqf0yrKP2-DJ3Oa zC5=Vbhe~(7SwG$WVJovV+sAm{c;BJL@h*ytXcbeZhsJYD^nW&d348_}RK69e&m)lbH z*L2PpFmoia9BG(HR%U<{U#>q$_Y}WOAf6YeDnLgNMDzW-3jg#wJ@xi--Vbw-*dtvt z-1lSI&vgwCq~8Q3iHwfl-d|ai_TLjm5Dck*iN_QK_b>+W@nt;*VtD45rxw)-jL zgSeO^2!ZVXuS2OBcR@Xeo;f*QOV-begfvulj0m==nLp%Qv`+>QI6(&vsXqrEy_bFj z2vxwkxByYG><1S(Y(5R}m@={(-ev+}3uFvMx!R5x7gu-RvLBK>UZ%ar{;R4bLSqD$ znjm>aWZnl6Q*+cfu83c5w7{clyYGLWII7%bb^kBU59NB(X$9AlN|9*CAoVk8SnR&o0QkmQjT6jpf?c`JZ24_U7X~yVOKwg< ztI;n33JFNT+c?xz`?o40cd?DN`;o|E24Cj!m6a2C4_`)kyyJpn6c|(SU5Xi_uN0?9 z|2%sr>EbJ+keR@kLNj69QG`u|8vN_~azwu~e&)87qFD38-5|%q{^-^5+6ScauS#c& zUZ_9a)20Hk>kPCdZMN78#7*54b1YYJD=*5eQpssLI&+O`&b40SD@O2ansDQ@KnsVC z4IhE&HP~#^hrqqmu;XHvMhU+(NxD48WfS4x!?A%Yybi@0a-zyF-ZFDX`a=-Wi`RU07>pI@~T3px|M;!o;!V)-`A z5C*uZXdCn{q1VIPt3RKk2Ll^pIFpzeG?nuZBa-3@NP!GA$4~UJkCFddOSGkoXHZ?1 zL;c@<<5E|D!8FU}fTrxV^|c(61v&Eo}PVGjJI1Cbx$jUN^p9#Zt}WS8E!) zF-&Q%C!=$RH^3nzY-0Jth@2SfPU$DTPI(YYUh@MeP4__eC9fROoTA)}E+v^l|0G?F zt|n8i+b1;q^mq?j6=d>%3x)6aI!+&PmCnZ^Qj#nku457HPKIJ=6K7wAyCU(9Q3k>1 z+II*v89gmd>wt_{VpNSUr!}m1Ck^Pu6JDz6z=A*ksE+yPU)!sEt|3E*VYJg% zBpZfO@N%5GoTCP%iqZN}wvc$GFSu!Dp?m^nlN!t4$BO+RHnwm?0<%)c+<{7jBYjEr zEQIyw;r-kq66?bOj~DZufB(E8lax`(nrRcg55>e)r^%9R$Nb4?mhBwBqJAx(V^l)# z7TtLE%(p`vp;V7*l>Xxa((i7(`D0bhg{-uMA6*aUo;8-ddq_{w&q(RvfeLc;d$E{Q)dZ&o}$QJ`CjCK zJ6AF0w7w>V+!IGR23AkPZ+>D#Fr98aDEnDWO(~<}Q2RSW-p3D3H$?F&F{h3*7q8S? zqWmA4zA`F{wriW_qPtP)?vN0ryF*Gsq(eF+q`SMjrKOQZxB*Zth2q-;Xu1 zd=+9s1*Wj1Qi|b`!xwqiormP9@@)G%MAy|DCY62G)$RS?H6zsUr|@wKE!Ta^6cU;Jm1pN&{3k- zi)4>PpGJaTH9M3WI%2K|1Q6Pze;~b|W38s)B^=@LF$=6wL$9zIfn+o3~(-UjW%5?*Y=r3*1V4jo(fCWN?wHB};$ca3G7WM}4m z)+$W&FNlAs0(_~CeV*Blx#8)=MB8A-E1z+DB)YOs0bF5_8nFZc*<@1e@ENVBtXE}} z^lh<1)39-vxlikkLH1%W;5yGPN@>%nB&SKAy7x={f?IXm989*@!X^B-7M4rNly#-DedyJl0? zwdBO|B3YwjY!22&f>kS0C2yy8lfR63<($1LJ`RI}l11?1`@pPZX5*z$erarr^fBUL z9KS&Q`xq!<`tEiM5AalSTdiw5dkO&$LrylH=3RL@awH3Ana_fI2oy4x3xV|>#DL7jb)9D&Fjl)R887X zGUN1<@GX3h&Wvxce6A1`K`oqamB!**A4*x>T2Ng2?UUbKQ$eM~>;XJ^N*~p|y%f)` zh1DaSv1RlY#UP@zDkicKYUJGIB_TP>-@_aDShn+Rj}<;EM#lSLrC0R1A+sPAxa|(s4zX9}+~~uwV-CNn>{W^8`5r`MxI75LdT!1} z*kOSuP(piuLNsrIdS8)R7zIQoJ`ki|Lk%)?CbZunBJQ9| znw5T3Q@zEgNub2tgimGR4m3hZ>D<|P`Q>AuA`QHB>EW~Q;UzlJK=XqX_Rb+P8>AgO z_e^9;CM*`WgjWp0bs+up8eL$)=4|wD~716=C~#k}%u)I@a@eras4^Y?9PWS&kn z$jImeO$eyWRL~|w8u2z+XmDe#*=Qv zcW;-6x!TkCm4Au^X^eVghOXdIE{FRKE+*|3QnPQNiP4jSHZoyf7{FI2~}!8CE{ zYFg~lAyz{7(<8f9d{`AfqFT7`7!=R$b+STiJJba1eMVTj{_=sG7z+5 z=_DJ~qC47=7F{+Q$nQ{(w>T{1DXHXX9Eobsk&qW^5K5@_Lbs56d+TQ{Gkbe2Y1#Ji zGvdZ~#SP!*;?vNL(I?*BgLo4gsE!r5N=}~COh89PPbDl8vTgpWqZvKIa3 zXsveS&a&am|GSrjQIsD9?nUe;OB#%x8uQvtQPFMzQ5A5BeW&)&f2ME=i?N^f#y&f zkF-1%_!JR_uFMnD?G0!7r@s`+Kf*`~ha@3BLO+&87nMq@HMn|sGIHTGh(FhbT(6&Id>D%in^@s~lKpfu_D!8s86YHHF#r+&L7f{d^ZSzw%|~sK`;sxOj%F{RrBoc zMn3CaDfEkUQCoeRW^qA>C7eS+A>NXii| zV7&Wn)(Yz32^Gs8RJCHFm^4nR6W~8sGx+EEGe&XLYz-qm+;n@kTn$SyWNgIKeMC{% z=N7ZQ=$|}_w+-wG9dcc`U60efC$o66aHA6TT7$`W{dwctm|e}zZ*0z3R11>h$%3Fx zeg>95+XK;Vp|)>ya{7mKvd>OF7$|%Zf#IUUOJ`w7K>6ai6C!l`;Ph|#lGD;`DDr&U zR19`l%U?jiwMj|;?ATxZiPNZ@B*E{ZI9-<9Sn)6Xdn24_N?q#F(%_1AV*z3Jlb391 zQvq;rs)dhes8783-74LQ#cz#We`3s^fkukM?vGF)wnpm@nT?xKLhqNkiDw>El!Cft zrFuw}(8%C0`s_8J(=Wn#gKkhgLpL_Sq8DW* zKNfkeVxzoZ;AX_|spqMiG)~?N*{Li1D(@(#PAO^1#3$fYGLPa{j&*Wv`FI+JB8WeX zF}mGX*T@bnH{6S{PYbmfsfI~~zV(c9DE4@8`OC<|TV-SdMnb&%Ad07VjFsf0FT(HE zV~S2sS9tdJTTJn&L<$CD{XelkIR8fO;Z@*bClm?MIghp zis{9L4hkAf4l@Kq=QjavPD{Kg@q*Z|3(9zUXl3G3VxzjZ+3T;BaJc?gYd#LEhlyEr z)o0^^R1yy9X!7;*%M9R6;#{`MJdvpPp&$UpKX>!MxU!E#+^whwz!4}4S)gV-Y-_=H zyzwFq%skcm<+kS$*h%?H;9U>YMIRbb3S2uFE=OsijVEEnAU?=$M`HH!#LDR#js+5N zt(7HFNW}8T{}vwhwXp0*Sew2~wSEs=G@MSL0lw^w4q~F+zo0{YF%N2hNG@)`bb6nY z$IWT_djQb*1HE_L?1P35%hHqNA-ac&W=d9*(FR$N9}CCEm$4*IVH zzzR3GK>M&;#X!j3;jiO&^`!JddgqiRH@eR0N$BpwoAnoX1u4rET+b0kYZ5D`7s-4# zKl{hXiOVRNS7hDE&dA)luJA7^G?fKu@ ztE!}jo1>&r7G}8ILPWvpmv~|n<4N%?{{D<2&;n_R;Qy;o!YHsyxoO#TiIw~_$?DIt zWQ8jxB_=hwT7EhQ%u3$Zm)$w2aP@OMR=i;1;W?mp2bz=S!gvlqZT>rY)Xg7o=NAxF z8~`9nD2weJd>W_T?%-B5@F-#8UR);#3aWekNnU);a(O*3rg%m8v4n3zRF(r0y7}k?~p55>Jd1f>ghSWuTxP4G8dbg6eNl3*BcGYVh z_D61Vo{k)fk>lkE)oV#i%_;ayB@o?Rrf(IKO$Xa7%NypN-%Jpi>L95SMfs7^v2bVV zdS9my-L4oKY<o1aWB-aaj|?SeksgnQ?lPATevWc(yr}74zAXCEju~ zLGauO%!*$j%L~^ngb_l+@#K_x^O0|;!24{jJnqK)7s`k=z)H{#J{h%DgQG8^1QZ9zZ4uZ z!wVEik$d7s4Y5>6R;|(u+e~E{0pSHG&|kUU6Xa}2+#U*Q922yoQYTG87M*_fl{NO~ zC^SU*!Jaj-`p!|f_FY#T9>{lz%_n0d|K5=K?8LGfP#;vG$$3dfH&V(x)`;b%9-o|j zt5th7cYp#H)o)iPccf19odHqDT``;}rOm{qkk=XGW~m?~x;B&g!s% z_tA&bLtH}+;9@6hLi~p%#_=$4W?Yha=DX|bh{0$9!)kO}djKU(fs6*aaH{>wA9lvr z_&=>+B2UL>bOSgUiY9f>f$#MB{pxczIFNzA{l#vW>L2JHzpmu8N6yEQPU=!4czrbq z1l*64U+T(J0Ny=10uGHgrl_LHriHR_Mfs$1jFNQ=(9|{{HcbM1+AKu0zu1!D6*4x2 z_?f)W?(~)LhIQ;OGS0^Q z$*wq~-w$)hHXirJ@7|~dWWQ5`ujEJEjHL}5nC1mr%xR=x6pWSLUm?3x3?#?hOVkZ91 z8p8E^J`~0x?k=z_9UV@B1x8HU=j(xB2N=oO66;~LsxXn5t3mbF0qz5<`r%RWJARmc z6{eJ-+DNGJA)se+b$arin_cH6b(%nmyi9fRzwVezs7i!mnY;eG@x>r}eR4XGvz10A z8c!2j9Lhlhf%{~f%X-q$1tQHr7B^4{jm3qCffJA9q8h78aIC#{K!8)1CHZ%W79D_1yNH~H;!HO2!5+3xEEjfW4Zn^A!j zp|MnUm}HRptKwKSMwZ}uoe;f(UdxB*Vh^*@^LDz9Ol9fue}};6zg4?+-?jL?2w8-E z8aoU&9Q}auwUVB$G^g`0ef|9?0llawtimm`YxB@Iwev1O#={(6VS`AwPbIK)^dKijQ-3v6fk|V6&0A3AzkZ;2H!?=gM2BW>{7a8!YtK%#E!Vec_K$t1fEXUa$h0Q)5G}Czl|6S`lwjEj!-v zf!c`U(RX|j8KW-M zOuM$Xoh0eAq7^-{89d)OrFZ(Immb(@Hx{PQbUHh?lA4exF$B(;Nbr-p;NzCU@}fPr zoti%FO(;*(P^8XI44yzFD5rI|nztl;WzmshYn>N=&9vasEktW28B(X2I~U%2t9vCI z$fz^O2C5Av7~)Cdpq1h7kU#JEe2Fao>!v=onj;fNxYmOzo2-hn$t$w@Y{9}MhKOjK zwy1UH?|&?^^CMj3CQy|D5!A>HfU#aIgmGMCO+{hBWjX<8PRwm(IK4>yOCGw_v! zY_dR8RWNG>qBU-?p4Wx#7fe$?#su0;7^|^@`4W@MQ${c-Z4LkHoyFHWibUvs`SUbd zqTLglTPZNHlw)CXPPG)2~{(Vq$10Rs)InppO&u&saw&)u>s*Tg@Q^9?L(k`$xJ+Wj+M*8R{K43ve%$A*v*L!5!zgMQMxXqtmxdV?VB8@ zSE)kZj3zR^Sc)anJsVhBi3ag-$rq`KUXOj6*OI;g9R}5I#!vR+wrGmo9=I?U2y3X{ zi<}o56UxF9$xW`n0E{6?b{c|IdP8_ zSObsaTmT6M3Qv1@c$Cf`q`D@hImPPzesK(o?O&=!DT|AQj0Euq)b&wl=wQzCgSqSB zqGZ982plbKY*$K%axD%W+)5x{^6Q84=Mu1^SIpj`f;ZXE|>TMv_y*7KFTT7J%T5 z@YadHG;n9Owr!6Sc#AVk!;s)>eHSwPP_R<`R$3=4eIv=let2H+JzN1i7ef9rB9jRR zfy!Y?-bh=+J@=F8Bl!1PKKR5yEC)+B`_Bc^M8^YZ2vSCvJ zE}e3Zt8heVCA#z>?>r>)JXPjL)&j!blSNdMLzvLD28U5qAx`pT;P#+ zyk6z?C&4r|4hNb#(D6>8U8%r8+FG%0!2}%Gf6FZi)mRu#`Iu0DE}%{Dy6Hv+*09HH z7>OPpko?d>gX<@WS*FGrtIZx-bn#l2&EgE(4S-3n=eNAI$fdWFwNqfLw9;&!B{W+ zpVFS%W#Pnf8|>8M(jy&P6s$Ie{veq5eq-%hTuArIu!I%NCE4NoQ}q%CDV?!2G@ya> z`C(L^C*J^?2APxdfOdRz7kQ*}&i|UrpXoh^ujM^agZzHo=<|}&=dno!yv7gr&FDP8 ztgwS1l@4R12(YskzpPWxb6_-ALDnxap=e67g?(Pe-#% z3=B60(198;D$%=UWu;Q5(T3zYlYe|hS$HgEAX+t>GoW|`QOd6q2L*vD$0K6%#$Pz# z$B!TUUN;<2zzBr({(IWu-oF&wKFaPvMsCadMC`AYh15fX!iiLbpThnl69m4dft^Tl z?GO22%F|M6hg~QR{&xUYHmTuWT)voL{<5%R*jmd1BT+>?t z%2#+vBZYJUj=+}ockV9~a^>|l_VQOw%Zy=-C~9)f2%rs5;xAUt84qw{+dTSUw>C}k z$5=3eTMlH71v;&M%%csjI!8nlMgR|bt*3v{f$#4Kp?)uQj8G3qk|QA|hG}DNP#H!R zwM6ZY*^d}SuGeMtcTA%Q2kcd*Bo#TM$UF^=2$#&3Ivz=gC~+`^a`*6XyPwR?WGtPR zMXwo~!cLUxO%xYtlo+0d%E^5GAaoq0!%R@lvEx^Cvp2POP{4Mf4#a-DcBIo0>DNss z?dH?79!#sKruV);tS{8kug;`LELrJsN@9tqq;CD+&5rsR_GYI86P!N>jUw(e|EW{7 zB`QRs2<^bhaxiSJnHb|S%&MZ@Bp)M1x6TFTLoql?lV z>ukxQ#Qjv?vjayz!ew|xgTRCymxRh7Sx`!NU=rw0anf_oWBT-P3;iIpCL1c3ens|R zq)}ZfCraSy7TC#WV1mo?_wU4owmMcbQ}qh=aJJ8P&Lnw41o?xLad0UDzNnxR(o$uEhu^PGMktVPqvlfnY}W#c^`|?0!A< z3@IV&?)HxGvjDIdD=KN4kMN5UkTiFuqz=eEw_CEB5_IsNJE>XK1nwv0e0#uAZZ5u< zQ5E0e@p2weSz{chE)0SbmPI(R1YTe=(ip9|NLr>VUF{R$>u~_e3tE;C_4N3cRH1ja ztNTkRFtbl3iszISd~_A&u&O+NzZ&Cm(kZDL-J7L7iz)r{E1Ixj%2n5&Vf%Vq!ES6Q z%)0IU{56x7A*st;(Tg$f12Dp=G&fgKp7)8B6CW=~GP1v%hso63U0$BF>2N6WbUa%sIS38?~7q!M6XPl#CW~?(gpuM8)l# z$4$x2{at%mz{kbTnh@LFcV>K`7ekn;pRz(ykh4tuJ7G^-+m8gCy_>mA>K4B?(h^px zeG@CMS*1`D5Tm|a=RrGw={jeB^fRvVAIWu>8mUp52J;#Ff z8!Hw@1TOSAwNH*lU)|jJplHJ7{_KUDY~*EMD9r2QB~29-j$7yn%4C_ispl4>x(>25 zmnpoYol&}3Op&j=smpjKz;^6rU2Q6rt$TRj=9xF+}q)H54Mr*uq>I zecf0Z6eDIpW2iM7auI4YEkN;l+gr2rUi3QXZX#(j~jh2FmqONesX;{qrXS6 z(cv`Rl>}8bkcKz7g`h8h+0JOImvXM!a6+ZMlGsiwLb25R;O2VpH0R6k0irr?f}iFS z3FLFIeJ~kYOJL4QXEHAzTb}f7s(=cdpHB{32(g|6EE@yAG{bnGzugW`)NB20k~{lj zdT8J+2q)#>=MNR1o}V9hxJ}^zlVY--`vSm}xv3!HwLC!-R4S-wdM*oMP+rKNcF)_B z_MZvu;fM)gYS;*a3}90l7HQQm4C2GxPr4f}G$=+kX(@A)>KTG)@x!H-bLsc9{@H;$ z0+31llT?;#@_){>cF)vZg^XM*#uY~VK8Er=ahse=uHOG~<{R}}p&Dg+WF$bl;711$ z)+|51utgBEep(6NUjBN$qW1?6n+&4wKb>x40<$uU=+$}lX=g}F)wy?BCs}}zR_(7+ z`)x+A&75mEq%iStlif$LtBYdRN}_z0<{QS@&1THG@blxQM&?9d zFm4wWEyH#>vpPaiso;WPb#5+22_%@!esKjio<>|wHrFdHCAMQiqf)g*_nTV0{Y5XN zy5pYHuKkkmjoa6LKy@JIFc8WrX6z^Kktt~S3)}~xzQ87H#B;iLKvwGJHftRL^Wx#) z0=LI$_&_(N3F)Q@S+t~kt7rz8vt;S?LZiAt6cZrqa6{oh``tkYfFzU__1lG55y_S# zmhtx$a~Z>*e6JSZ>rbxND_*E5Nc;qXouD!+_w!Q7boFH+yraM^Zi zzf%58ZyP4!pTNNQrd#DbW0}+6lbKd?$BjBH%WQtJcJFwR;6SlhQsmfc5Y69pxMbnahy3$!FF5PEjxu4U#!pT{%} z5auP4w=Y^_FnWI~A^drF$$m1>DKt@%<2|fmQ!@v;D-c8!X#xw~L!OmaLp_|(XM=CR zm-EYgWu-6HN5GTrUt6PCdy|Pqsd9F|g04jLPlhq5VGagceC5s8cGON z;r?=l5EApsoFCB$Q50JR<;lefa+quWPjN^$Voo=57EfSD&$F!J1@Tw1k^{=uggae= zA!=ffKqt+QnUs^^FVVRFUZ0G-sx;m0GI+P_69}SIIQ+|!c@m~Fd6>8=o%`RN^w zeo^^9@G{aC>1GLh{ra$VH2d)Ir(twYwUE#`cKuCwLq_G_ltr)S@=vIh|9e!ZFt79w zTB7O4*RtHMYFrL9v%MUsK@os1wS1)t{ILC*t2=^CN0Lw7u2+8gBi0G(3o;QjpZ1gK z0FM;Vey7lCTMyNu?~sdP=hAvBjkQF-+;Ohgt!xxY|1M@JKv&13sl1ixG^fj_Y4Y_o zace1sipe<9ddRKwAO@e_z-El__>j*X^+3!k`bdw`Su2W&e_e@m6R1&mYG{6HsFl1- zip|@}AGDinU!3m*()7PkK<4WD#Ari+hFXjy$>E%rP!9uRy#6jE5#A=!*~yI>?AZA66;8R2>7xk?Hz_Q zy#FzoX9trEmxh5Yrt%a$i}uwsz(Ex3LaJ7dC=}K68A$oEUcU~w&<|BNv}hFuaXmx&uDhfAw|QvU;j|_1Iy~CgpoY=%cOE)o zRDa($w#|Oh^Htk-%sZ4XAm%7Ry~C2AR*|724EU=neJclCgv4DbNKY)mQ} zKG)Gxp&y3+goNi6Q!t^sGz7;>is5##s|tO)z=g8$HD69Y{b+67+uL(kWlesXHy%wj zP$Qfk&1=}b$l{%woLLb^zqr!WY4_lz2a%G4bBAC=+K^rPj%Xeb*0XnIeKhxI0WG=$-51ypnA4A|5dm{4E!d_7^Hw#gX(;Av+U3@o^$Tr zq*=^px!g@><8=$4y?FNe{`$DY&kWEbTDT3@fic9E-TX?oY05>5)qX&-<64(VblbLQ zc5^9;i3%i~jKSx_+EEHlp^ zCi9Aw%tS(iZ8MVAlBZ_dwQfF)Z|rKqwr67VMMV*-(mHqduxoSrz5arbR@!wco~2le zZV|6zsv7p>lBs~#n*0y5_qX?*x1LW=>lvzLLE}6t#{Q?JJYzb>qLQ0f#GLCbx!~Q+ zZH~|0u}E4~$^u**3Q9L0c&X|kGJ}PFAE?fdy^}PzygDZRlz>~dJ(?{==j*`O!%yJ{ zcsG`R^zfuVe`l#XN0WwkDO2SIbh^G!NU=fhde0*|LQgd>yFq}c+O;&{K z^>_&u)ke%vI**=C~z5dO!)uQjXxw;57r;JBz#{ zEr8)Lsq1!OV?5+y6C~7;`!QSvL0tU>=bvt!t?nRFYAKGnn|}zgrtcursyQ`tKMFY8 zPWzW0s-O3AfUDLu%AMI4N|!n*jc?dU(VoEJ*5}JV%4D{G6G`mR98CB8bPy3p#bwU2 zeU0@zn?f>0jYf|zGn@Y4#Z$*rVT=exkht%d9TlD(8C}eDde?|u=a4!XU(Nl@$}c^c zNrEW|%mFsj+Q_5fX~~XqeyeBm?hY2Gu?OFxANo)A*IFMYJ?4=9zJ@8X$DHOVKuDw- zOE;AdQzkb$88R0DI7(U+WVxOFHjepzk&Z~yHH9~T z198STs;wxXA?!gG55eMFX!mp*h$t;Dj|f5|nqGQglr=%|XnpfAQUC?pfwA9aW`?kMP)Rwr(TN6!?L0odVh}zFnrNP$EhpFmi8tC z@%-;igL7`-iE3Ir1;yt#XW?PM;;wdfs~m5Dq?SY#f65ujyaLO)?0q!WEW`Chu5%bW z)~lV7f&m#=({5eS*pPc;uiVb>Zyr0-a^=!Z7>eTHaQv+6Nu3XTb+~`r%s!Tfk<#^izM2L>d2*=u5`;?>k0d z@fT@iZyyUnJBfp#l-F)+nQmTeDI9?*GdL!Sx4579OW_p(g0_ ztFNN^t~jN>y|24a%$&8LVdU4V9`IPJ4)815G`L1>6oRVZj^EHBT-F?A68q?BzU)A6 zkmdFVfcC?3TyA$f$t(76xjo_Wjqke20yI!J$(dr11v|-Bd(ct@YWc;rLuA$LF?HCC z>(D=x=iT28#v|Ya^H+vNoqAALa(?33hL&34}t&uIlqMe!`J+rfQQmZ#g;r@J`U${zRv=tyR_jH( zN`vlyA&I*6p(8Hi|v9LD|VOi6MBk4?IjcU;^Q5ypd;vcUNyn35Jz zl}0xH)jKtyI$e^r7J=0A^sPezVt*HpW(b6|9(QCwQDLx$#+AgOn#Ul>Tq?9225Zxn zoovtM$Kt+3xi~kKl=v?u2)i251b$#GfL{y=9*1AlGOG5ETSL(K1QUcIS6`8f^6#zC zpwHva8KKTwMI@W9P?mr?g@Z$*wL!{Zxsz8MbJKrkj37L zn?K>`Jnv%B#Qbq$clzOxJD1y}SLE_QlS!P5E1_aH`Myf!6}gF-;VUgYR}wfGj9t!b z5v7}fU9`-kig0w1UCt4=To+$^Bt5Ad{NMf9S_eXDd%h;Cwx`+0SR0W9fQG5@@OA_ zucbfxtyutX7-!l0{t#*hI-0>317?d(C9rAMW$ih#wW6kmP&PlDjiiAWZB6=OXIP(U zRQ_RSB76LQc^J%4@gTSE-h4}mU`WH9aw~$QVcn~AmXT6t7f?|G=#_DUDa$md6xD%B zZT0!yX95(4Qi~usy*C+JyX~l`Pju`S;EK0lCoY$s?MHvJWXvKexH}mdEuytwvWbqGB<3ErRK$8$D5I^#q$TI`8+C zQvDq^qZV6g1QIS@0YvG$^FNu+J}e~}Qi%^Bt)^y=(?Z9~9ju#*LZM0*33%&{F5;}`adN1h1+ z@>WI%bMx*%Q2*aDYK^Qg-uxBNz<@~{iia(GpXVzzkgUCRaO__!HgUJcV*Kh3+UU*+ z03ZPaz#VcZr@Cp`aYX0VU|h5u(aGHE=_uv;Kf_+241vW?k^>SlKs9YSY+Tar@N$IELs#MIF$OQAtSQJ~rq{l7fdFx}8u$@;H z>#=trXRJWPcQ}F|6P@Awmp?bJS$Cw}{z&j)!&uH>8|!JHw$FS|yzMiLht))4*voKx zQ6})Z{giMZ#JZj(P;jepNz?w4AO${m@f$_T{oR)6hmuWAZv;8M@5owD?yOC zoj;Q^3@f4PJ4SAbk*87EZ!fFd%Ra|4@Z!<`*>q;0_fk-HS&TU>8E%t&PMaN$Iha|P zC69W1Kd}K3w-n3akU;C?oY(F9-@CpG>rOQMWQNK57-ed`C5d*>!wcm$|59=ZB>r5U zZ63I|aNpfc2UR>Bx1D2N>S7dWNSA;&M<@9^psODJIAAkVKFHVide0bR#$c1|ml*20 zguaU))_+?uIiB@~goLD9U;udTK)qsT?(r9{*-7s;%LvBo;j`V%-ugV9=Pb0kv5%Q0 zfY+XPUhgMxrfvaqb*xDIU)m|PY;MenOOLlrQn*>@fBX^ApyT$uo)ZQzl!R#;|CWWp zBxL<0x3v?~kW3?+%4n4xaab{eZ9`hv!4aO-OXzCSoKRI2L zq8k37p~eVN)~Q#!WzhmGrb$v*bWF@zV5s`;W(~gUAQZa#tTi1;<;1{+U)PB}ym_+B zxT*H>2%ZprCZFepGI?nu2v4CJwd=zsPR~X=%?vY@xy6{PEJ=j!LQmZO??rl7Z%PcT zRaj;1WK775s@Uc#TKqufANVaPAn0UhdVE!mu^Yd8982y$If#tO ziw4mq1Lr8b($zPx-62`&_?7wGw-?Z{KM;)l&Wmqr&&*=n&pwGApQ&>ZXBm9(3#7=8 z)6J*IM{K)ahkaVYV?Tc~rw>ykVTPwl`t*U-#4A$XY+`MIndodV9C4IsVC|FI6tW2S zggpYB3ifMjY)P3El{gak?{*Om6gUqhoo$0p@B=bYW|}_iO)G7QODP7TL~GM@x=GR_ zJsKRgV@nS4x?#=BVT0`)J?)szw2W(N1aQD<5R8e{+U*TAyTB3c!U!?OU|!8cF^2 zTnpj2t^|Q82C6wRyT_(tIzxL z;E7pP@~S_^%SP5E2RZH3Ttz1>J3L0+j>nvBN6(8mbCIj9P2=Mr6%J3qz5DabJ7MDy zH4%-TJ42|yjmvDS+mkhtJe`yhW0_0RL@`}p{qFDm^d3%e7h`6Cv2@J&_)&Y?)7?Q^ z?dIF7p)-DHD^h{rEAeNh{*&!;@>7a-co@m@D(|5q3B@M}>iAaU8!uxy7m}ur zqSJb&`LfxQ;M`mbWw5=Ya;Wdaua;VX3Nf_TB4Pd*Xkqg?C?;V;l%t^tFW~qCfvA`n31C0d@~t@I z&9pvnEv?I7BY2rlM6_8cLjEu0dtGeJMaG73tbMsMpBR&G1Dviu^_3 z{wltADxsKo_R~Hwel(jip=IVSO|vq$Clq85W+%D*=>|^k;~Vm3_l?vIbhD0WR)O}m z^^83l=z%c#t_>gl?qU&ORqH67|DH#Weu(=Sf<;}xCd^vQOhMZ(U^mE6nA6{~7De)i zvvl;jnoe_-msA4iK^ky4f{#Qvd3YrHcy$`LJiH(4LRy~6Y0QcD*T! z%an9X=&Nfz1r(X&f*y%LDUbz37L>*M=)gBUNvjr++{_fq;|0B>?Q&;rR2hA+9I6w4 z({x*n)my%WmU;js*Vgocg=5RZu%yO$0Z&86gcgSt9E;cK9fLX}Hk`%l3~)`oCXJ;O z@1)Sf$f|g16cyqR;;&yM4K?3otQ4A&}~| zoFRKO;RHa>PWJnz?`GRvhI`u-5GtAOhLUe*+k4|Xw-d?%xP;w*HmM)BTcX;2JiaBR z5;+Kca-VTG8DrIJ`p9M~k`_r36CCN}wJJ;gO}xSZ!l>Q0`-v@$7fnA*u;@05pEl~l z#ierr95P#g=1-hp3h9I1VqFRZm1!iKgz(5g6Dj|{@wQ{^M~3p7Ct!i@LjV}fxAw4iexbx9f9(ZZ_S^m~&$RnpF;j|x^ju|-vf z&9?Cf1P$fW7tJxuKxfv;P*tR!iT4v4e02isv>a|uj6i-ZG5n>V1P-7ALua)lW-Z5U z+Q-6goi}(^7PPA^Uh5y!&t|m@zk5G=ynFt~4Ww--{=NXub6on|G_|sV$WfJ|dGhs5 zl{sO(1o9IbHR6S{G{UgCKNoTmLvB;aQi!HI$yYYw^nYVM{h<^fv;_iF$wMC;3=25z zK@T?r!e$`;7|1|fYDMI}O=Uamg#Ns0i3CwNqvrCbkA2WN0Stx`c3QDyayx$5@6^rJ zjxT?q05k)2+!K7c^txT1MiNA`d}4V>Zz#V}xZnnu<-SbFy($=bJM;)ENmC3&H8z~b z;7-!!F?qFTIFc-yK83pUn~%4JHvcp^?y(c|LgwE+Iv5x!#W?ryoSehvZ@#`NdT

  • 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

    - Visit the project on GitHub + Visit the project on GitHub

    diff --git a/doc/index.rst b/doc/index.rst index 97e25432..4119935f 100644 --- a/doc/index.rst +++ b/doc/index.rst @@ -3,12 +3,12 @@ app4triqs ========= -.. sidebar:: app4triqs 2.2 +.. sidebar:: app4triqs 2.2.0 - This is the homepage app4triqs Version 2.2 - For changes see, Cf :ref:`changelog page ` + This is the homepage of app4triqs v2.2.0. + For changes see the :ref:`changelog page `. -An example application using cpp2py and triqs. +An example application using cpp2py and TRIQS. This documentation is generated based on `rst `_ files and the comments in the sources and headers. diff --git a/doc/install.rst b/doc/install.rst index 288e9328..1b0ed56e 100644 --- a/doc/install.rst +++ b/doc/install.rst @@ -2,15 +2,15 @@ .. _install: -Compiling AP4TRIQS from source -============================== +Compiling app4triqs from source +=================================== -Prerequisite -------------------- +Prerequisites +------------- #. The :ref:`TRIQS ` library, see :ref:`TRIQS installation instruction `. - In the following, we assume that Triqs is installed in the ``path_to_triqs`` directory. + In the following, we assume that TRIQS is installed in the directory ``path_to_triqs``. Installation steps ------------------ @@ -40,12 +40,10 @@ Installation steps Version compatibility --------------------- -Be careful that the version of the TRIQS library and of the application must be -compatible (more information on the :ref:`TRIQS website `). -In particular you should make sure that the Major and Minor Version number -of the application and TRIQS agree. -If you want to use a particular version of the application, go into the directory with the sources -and look at all available versions:: +Keep in mind that the version of ``app4triqs`` must be compatible with your TRIQS library version, +see :ref:`TRIQS website `. +In particular the Major and Minor Version numbers have to be the same. +To use a particular version, go into the directory with the sources, and look at all available versions:: $ cd app4triqs.src && git tag @@ -53,12 +51,12 @@ Checkout the version of the code that you want:: $ git checkout 2.1.0 -Then follow the steps 2 to 4 described above to compile the code. +and follow steps 2 to 4 above to compile the code. Custom CMake options -------------------- -Functionality of ``app4triqs`` can be tweaked using extra compile-time options passed to CMake:: +The compilation of ``app4triqs`` can be configured using CMake-options:: cmake ../app4triqs.src -DOPTION1=value1 -DOPTION2=value2 ... ../app4triqs.src From 8529bc164a2ba1510ef1555396c95a9b17ecead3 Mon Sep 17 00:00:00 2001 From: "Hugo U. R. Strand" Date: Wed, 24 Apr 2019 15:37:15 -0400 Subject: [PATCH 084/272] [doc] add contents.rst and documentation.rst The upper doc link was broken, it expected a documentation.rst to exist. Small polish of text. --- doc/about.rst | 4 +++- doc/conf.py.in | 2 +- doc/contents.rst | 39 ++++----------------------------------- doc/documentation.rst | 43 +++++++++++++++++++++++++++++++++++++++++++ doc/index.rst | 2 +- 5 files changed, 52 insertions(+), 38 deletions(-) create mode 100644 doc/documentation.rst diff --git a/doc/about.rst b/doc/about.rst index c0ec4464..69272ffc 100644 --- a/doc/about.rst +++ b/doc/about.rst @@ -3,4 +3,6 @@ About app4triqs =============== -An example application using cpp2py and triqs. +An example application using ``cpp2py`` and TRIQS. + +Written and maintained by N. Wentzell with contributions from H. U.R. Strand. diff --git a/doc/conf.py.in b/doc/conf.py.in index 4f7cb541..3d6f952d 100644 --- a/doc/conf.py.in +++ b/doc/conf.py.in @@ -20,7 +20,7 @@ extensions = ['sphinx.ext.autodoc', source_suffix = '.rst' project = u'APP4TRIQS - An example triqs application' -copyright = u'2018 - The TRIQS Developers' +copyright = u'2018 Simons Foundation - authors: N. Wentzell and H. U.R. Strand' version = '@APP4TRIQS_VERSION@' mathjax_path = "@TRIQS_MATHJAX_PATH@/MathJax.js?config=default" diff --git a/doc/contents.rst b/doc/contents.rst index 7a599350..2cd84574 100644 --- a/doc/contents.rst +++ b/doc/contents.rst @@ -1,43 +1,12 @@ -.. _contents: - -Documentation -============= - -Contents --------- - -.. math:: - - (a + b)^2 &= (a + b)(a + b) \\ - &= a^2 + 2ab + b^2 - +Table of contents +================= .. toctree:: - :maxdepth: 5 + :maxdepth: 2 index install + documentation issues - changelog about -C++ reference manual --------------------- - -.. toctree:: - :maxdepth: 5 - - cpp2rst_generated/app4triqs/toto - cpp2rst_generated/app4triqs/chain - -Python reference manual ------------------------ - -.. automodule:: app4triqs - :members: - -.. autoclass:: app4triqs.toto_module.toto - :members: - -.. autofunction:: app4triqs.toto_module.chain - diff --git a/doc/documentation.rst b/doc/documentation.rst new file mode 100644 index 00000000..63c830fc --- /dev/null +++ b/doc/documentation.rst @@ -0,0 +1,43 @@ +.. _documentation: + +Documentation +============= + +Contents +-------- + +.. math:: + + (a + b)^2 &= (a + b)(a + b) \\ + &= a^2 + 2ab + b^2 + + +.. toctree:: + :maxdepth: 5 + + index + install + issues + changelog + about + +C++ reference manual +-------------------- + +.. toctree:: + :maxdepth: 5 + + cpp2rst_generated/app4triqs/toto + cpp2rst_generated/app4triqs/chain + +Python reference manual +----------------------- + +.. automodule:: app4triqs + :members: + +.. autoclass:: app4triqs.toto_module.Toto + :members: + +.. autofunction:: app4triqs.toto_module.chain + diff --git a/doc/index.rst b/doc/index.rst index 4119935f..6281ea07 100644 --- a/doc/index.rst +++ b/doc/index.rst @@ -13,4 +13,4 @@ An example application using cpp2py and TRIQS. This documentation is generated based on `rst `_ files and the comments in the sources and headers. -Lets have a look at the :ref:`documentation `. +Lets have a look at the :ref:`documentation `. From f9415b7385a9794fd7286d15873c83621ab7b9c3 Mon Sep 17 00:00:00 2001 From: Nils Wentzell Date: Thu, 25 Apr 2019 14:26:36 -0400 Subject: [PATCH 085/272] Minor Corrections to PR #3 --- doc/_templates/sideb.html | 2 +- doc/conf.py.in | 2 +- doc/install.rst | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/doc/_templates/sideb.html b/doc/_templates/sideb.html index 9e3966a5..b4cc0b15 100644 --- a/doc/_templates/sideb.html +++ b/doc/_templates/sideb.html @@ -10,5 +10,5 @@


    - Visit the project on GitHub + Visit the project on GitHub

    diff --git a/doc/conf.py.in b/doc/conf.py.in index 3d6f952d..5ab9baaa 100644 --- a/doc/conf.py.in +++ b/doc/conf.py.in @@ -20,7 +20,7 @@ extensions = ['sphinx.ext.autodoc', source_suffix = '.rst' project = u'APP4TRIQS - An example triqs application' -copyright = u'2018 Simons Foundation - authors: N. Wentzell and H. U.R. Strand' +copyright = u'2017-2018 N. Wentzell, O. Parcollet 2018-2019 The Simons Foundation, authors: N. Wentzell, H. Strand, O. Parcollet' version = '@APP4TRIQS_VERSION@' mathjax_path = "@TRIQS_MATHJAX_PATH@/MathJax.js?config=default" diff --git a/doc/install.rst b/doc/install.rst index 1b0ed56e..38303d11 100644 --- a/doc/install.rst +++ b/doc/install.rst @@ -3,7 +3,7 @@ .. _install: Compiling app4triqs from source -=================================== +=============================== Prerequisites From 038b41bd47f029201c464ce6bff49831e012da81 Mon Sep 17 00:00:00 2001 From: Olivier Parcollet Date: Thu, 25 Apr 2019 15:48:21 -0400 Subject: [PATCH 086/272] minor --- c++/app4triqs/toto.hpp | 25 ++++++++++++++++++++++++- doc/contents.rst | 14 ++++++++++++++ 2 files changed, 38 insertions(+), 1 deletion(-) diff --git a/c++/app4triqs/toto.hpp b/c++/app4triqs/toto.hpp index 024d619c..ee3b05ef 100644 --- a/c++/app4triqs/toto.hpp +++ b/c++/app4triqs/toto.hpp @@ -62,7 +62,9 @@ namespace app4triqs { /** * Chain digits of two integers * - * Chain the decimal digits of two integers i and j, and return the result + * @head A set of functions that implement chaining + * + * @tail Do I really need to explain more ? * * @param i The first integer * @param j The second integer @@ -71,5 +73,26 @@ namespace app4triqs { * @remark */ int chain(int i, int j); + + /** + * Chain digits of three integers + * + * @param i The first integer + * @param j The second integer + * @param k The third integer + * @return An integer containing the digits of both i and j + * + * @remark + */ + int chain(int i, int j, int k); + + /** + * Chain digits of one integers + * + * @param i The first integer + * + * @remark + */ + int chain(int i); } // namespace app4triqs diff --git a/doc/contents.rst b/doc/contents.rst index 2cd84574..b6e57375 100644 --- a/doc/contents.rst +++ b/doc/contents.rst @@ -10,3 +10,17 @@ Table of contents issues about +Python +------ + +.. automodule:: app4triqs + :members: + +Reference manual +---------------- + +.. toctree:: + :maxdepth: 1 + + cpp2rst_generated/app4triqs/toto + cpp2rst_generated/app4triqs/chain From aff1c3fdecfbf29ab6d8f28008f1a2e70c6bcd04 Mon Sep 17 00:00:00 2001 From: Nils Wentzell Date: Thu, 25 Apr 2019 17:19:46 -0400 Subject: [PATCH 087/272] Update License file initially copied from triqs project --- LICENSE.txt | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/LICENSE.txt b/LICENSE.txt index 78c28051..4b35411e 100644 --- a/LICENSE.txt +++ b/LICENSE.txt @@ -1,16 +1,18 @@ -TRIQS: a Toolbox for Research in Interacting Quantum Systems +app4triqs - An example application using triqs and cpp2py -Copyright (C) 2014 by P. Seth, I. Krivenko, M. Ferrero, O. Parcollet +Copyright (C) 2017-2018, N. Wentzell, O. Parcollet +Copyright (C) 2018-2019, The Simons Foundation + authors: N. Wentzell, D. Simons, H. Strand, O. Parcollet -TRIQS is free software: you can redistribute it and/or modify it under the +app4triqs 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 3 of the License, or (at your option) any later version. -TRIQS is distributed in the hope that it will be useful, but WITHOUT ANY +app4triqs 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 -TRIQS (in the file COPYING.txt in this directory). If not, see +app4triqs (in the file COPYING.txt in this directory). If not, see . From 1d2e845f66baa1e25bbacc4083e6b2db7c77b7df Mon Sep 17 00:00:00 2001 From: Nils Wentzell Date: Fri, 26 Apr 2019 10:20:06 -0400 Subject: [PATCH 088/272] [doc] Disable copy of rst-files to binary dir --- doc/CMakeLists.txt | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/doc/CMakeLists.txt b/doc/CMakeLists.txt index ed7d1c4b..d3e766f7 100644 --- a/doc/CMakeLists.txt +++ b/doc/CMakeLists.txt @@ -9,20 +9,12 @@ file(GLOB_RECURSE sources *.rst) set(sphinx_top ${CMAKE_CURRENT_BINARY_DIR}/html/contents.html) add_custom_command(OUTPUT ${sphinx_top} DEPENDS ${sources} - COMMAND PYTHONPATH=${CMAKE_BINARY_DIR}/python:$ENV{PYTHONPATH} ${TRIQS_SPHINXBUILD_EXECUTABLE} -c . -j8 -b html ${CMAKE_CURRENT_BINARY_DIR} html) + COMMAND PYTHONPATH=${CMAKE_BINARY_DIR}/python:$ENV{PYTHONPATH} ${TRIQS_SPHINXBUILD_EXECUTABLE} -c . -j8 -b html ${CMAKE_CURRENT_SOURCE_DIR} html) add_custom_target(docs_sphinx ALL DEPENDS ${sphinx_top} ${CMAKE_CURRENT_BINARY_DIR}) # Application must be compiled first add_dependencies(docs_sphinx app4triqs_c toto_module) -# ------------------------------------------------------------------------------------------------ -# Copy the directory substructure and link all files with relevant extensions -# cp_rs is a script in cpp2py/bin, it mimics cp -rs on Linux -# and filters the relevant extension -# ------------------------------------------------------------------------------------------------ -set(EXT_FOR_DOC "rst png txt css_t conf css js gif jpg py html bib h5 md") -execute_process(COMMAND cp_rs ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR} ${EXT_FOR_DOC}) - # ----------------------------------------------------------------------------- # Make an optional target that allows us to regenerate the C++ doc with c++2rst # ----------------------------------------------------------------------------- From 219bd830a5355ec3aa7b5a901f574cad11bc7019 Mon Sep 17 00:00:00 2001 From: Nils Wentzell Date: Fri, 26 Apr 2019 10:23:36 -0400 Subject: [PATCH 089/272] [doc] Minor cleanings of app4triqs doc examples --- c++/app4triqs/toto.hpp | 4 ++-- doc/ChangeLog.md | 4 ++-- doc/conf.py.in | 2 +- doc/contents.rst | 15 +-------------- doc/documentation.rst | 4 ++-- 5 files changed, 8 insertions(+), 21 deletions(-) diff --git a/c++/app4triqs/toto.hpp b/c++/app4triqs/toto.hpp index ee3b05ef..92353c44 100644 --- a/c++/app4triqs/toto.hpp +++ b/c++/app4triqs/toto.hpp @@ -13,7 +13,7 @@ namespace app4triqs { int i = 0; public: - toto() = default; + toto() = default; /** * Construct from integer @@ -40,7 +40,7 @@ namespace app4triqs { * * @param u Nothing useful */ - int f(int u) { return u;} + int f(int u) { return u; } /// Arithmetic operations toto operator+(toto const &b) const; diff --git a/doc/ChangeLog.md b/doc/ChangeLog.md index 0806d26b..ae187f62 100644 --- a/doc/ChangeLog.md +++ b/doc/ChangeLog.md @@ -1,5 +1,5 @@ -Version 0.1 ------------ +Version 2.2.0 +------------- Some Changes ~~~~~~~~~~~~ diff --git a/doc/conf.py.in b/doc/conf.py.in index 5ab9baaa..32b6f1a3 100644 --- a/doc/conf.py.in +++ b/doc/conf.py.in @@ -20,7 +20,7 @@ extensions = ['sphinx.ext.autodoc', source_suffix = '.rst' project = u'APP4TRIQS - An example triqs application' -copyright = u'2017-2018 N. Wentzell, O. Parcollet 2018-2019 The Simons Foundation, authors: N. Wentzell, H. Strand, O. Parcollet' +copyright = u'2017-2018 N. Wentzell, O. Parcollet 2018-2019 The Simons Foundation, authors: N. Wentzell, D. Simons, H. Strand, O. Parcollet' version = '@APP4TRIQS_VERSION@' mathjax_path = "@TRIQS_MATHJAX_PATH@/MathJax.js?config=default" diff --git a/doc/contents.rst b/doc/contents.rst index b6e57375..725589f8 100644 --- a/doc/contents.rst +++ b/doc/contents.rst @@ -8,19 +8,6 @@ Table of contents install documentation issues + changelog about -Python ------- - -.. automodule:: app4triqs - :members: - -Reference manual ----------------- - -.. toctree:: - :maxdepth: 1 - - cpp2rst_generated/app4triqs/toto - cpp2rst_generated/app4triqs/chain diff --git a/doc/documentation.rst b/doc/documentation.rst index 63c830fc..4f59764e 100644 --- a/doc/documentation.rst +++ b/doc/documentation.rst @@ -3,14 +3,14 @@ Documentation ============= -Contents --------- .. math:: (a + b)^2 &= (a + b)(a + b) \\ &= a^2 + 2ab + b^2 +Table of Contents +----------------- .. toctree:: :maxdepth: 5 From c387828bd23e8187b81c96265673c4750103cabe Mon Sep 17 00:00:00 2001 From: Nils Wentzell Date: Fri, 26 Apr 2019 10:24:46 -0400 Subject: [PATCH 090/272] [cmake] Important path/variable fixes in cmake-generated files --- share/CMakeLists.txt | 6 +++--- share/app4triqsvars.sh.in | 4 ++-- share/cmake/app4triqs-config.cmake.in | 4 ++-- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/share/CMakeLists.txt b/share/CMakeLists.txt index 961203f6..21174a40 100644 --- a/share/CMakeLists.txt +++ b/share/CMakeLists.txt @@ -13,11 +13,11 @@ if(NOT CMAKE_INSTALL_PREFIX STREQUAL TRIQS_ROOT) ) message(STATUS "***************************************************************") - message(STATUS "* Custom install Location. Use: ") + message(STATUS "* Custom install Location. Use: ") message(STATUS "* ") message(STATUS "* source ${CMAKE_INSTALL_PREFIX}/share/app4triqsvars.sh ") - message(STATUS "* ") - message(STATUS "* to set up the environment variables ") + message(STATUS "* ") + message(STATUS "* to set up the environment variables ") message(STATUS "***************************************************************") endif() diff --git a/share/app4triqsvars.sh.in b/share/app4triqsvars.sh.in index a7df20b3..c99750fc 100644 --- a/share/app4triqsvars.sh.in +++ b/share/app4triqsvars.sh.in @@ -1,10 +1,10 @@ # Source this in your environment. -export TRIQS_ROOT=@CMAKE_INSTALL_PREFIX@ +export APP4TRIQS_ROOT=@CMAKE_INSTALL_PREFIX@ export CPLUS_INCLUDE_PATH=@CMAKE_INSTALL_PREFIX@/include:$CPLUS_INCLUDE_PATH export PATH=@CMAKE_INSTALL_PREFIX@/bin:$PATH export LIBRARY_PATH=@CMAKE_INSTALL_PREFIX@/lib:$LIBRARY_PATH export LD_LIBRARY_PATH=@CMAKE_INSTALL_PREFIX@/lib:$LD_LIBRARY_PATH export PYTHONPATH=@CMAKE_INSTALL_PREFIX@/@CPP2PY_PYTHON_LIB_DEST_ROOT@:$PYTHONPATH -export CMAKE_PREFIX_PATH=@CMAKE_INSTALL_PREFIX@/lib/cmake/triqs:$CMAKE_PREFIX_PATH +export CMAKE_PREFIX_PATH=@CMAKE_INSTALL_PREFIX@/lib/cmake/app4triqs:$CMAKE_PREFIX_PATH diff --git a/share/cmake/app4triqs-config.cmake.in b/share/cmake/app4triqs-config.cmake.in index f175ce4d..cc0c253c 100644 --- a/share/cmake/app4triqs-config.cmake.in +++ b/share/cmake/app4triqs-config.cmake.in @@ -14,9 +14,9 @@ set(APP4TRIQS_GIT_HASH @APP4TRIQS_GIT_HASH@) set(APP4TRIQS_ROOT @CMAKE_INSTALL_PREFIX@) # Include the exported targets of this project -include(@CMAKE_INSTALL_PREFIX@/lib/cmake/triqs/app4triqs-targets.cmake) +include(@CMAKE_INSTALL_PREFIX@/lib/cmake/app4triqs/app4triqs-targets.cmake) -MESSAGE(STATUS "Found APP4TRIQSConfig.cmake with version ${APP4TRIQS_VERSION}, hash = ${APP4TRIQS_GIT_HASH}") +message(STATUS "Found app4triqs-config.cmake with version ${APP4TRIQS_VERSION}, hash = ${APP4TRIQS_GIT_HASH}") # Was the Project built with Documentation? set(APP4TRIQS_WITH_DOCUMENTATION @Build_Documentation@) From c492078f7742dc72158b689cf6580d2021305da1 Mon Sep 17 00:00:00 2001 From: Nils Wentzell Date: Fri, 26 Apr 2019 12:40:44 -0400 Subject: [PATCH 091/272] [doc] Major cleaning of doc targets and CMakeLists.txt --- CMakeLists.txt | 2 +- c++/app4triqs/CMakeLists.txt | 2 +- doc/CMakeLists.txt | 60 ++++++++++++++++++++---------------- 3 files changed, 35 insertions(+), 29 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 75fcf704..736b0311 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -31,7 +31,7 @@ find_package(Cpp2Py 1.6 REQUIRED) # Default Install directory to TRIQS_ROOT if not given or invalid. if(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT OR (NOT IS_ABSOLUTE ${CMAKE_INSTALL_PREFIX})) - message(STATUS " No install prefix given (or invalid). Defaulting to TRIQS_ROOT") + message(STATUS "No install prefix given (or invalid). Defaulting to TRIQS_ROOT") set(CMAKE_INSTALL_PREFIX ${TRIQS_ROOT} CACHE PATH "default install path" FORCE) endif() message(STATUS "-------- CMAKE_INSTALL_PREFIX: ${CMAKE_INSTALL_PREFIX} --------") diff --git a/c++/app4triqs/CMakeLists.txt b/c++/app4triqs/CMakeLists.txt index f1c3abe8..53e038b5 100644 --- a/c++/app4triqs/CMakeLists.txt +++ b/c++/app4triqs/CMakeLists.txt @@ -5,7 +5,7 @@ add_library(app4triqs_c ${sources}) target_link_libraries(app4triqs_c PUBLIC triqs) # Configure compilation -target_compile_options(app4triqs_c PUBLIC -std=c++17 -fPIC) +target_compile_options(app4triqs_c PUBLIC -fPIC) target_include_directories(app4triqs_c PUBLIC $) target_compile_definitions(app4triqs_c PUBLIC APP4TRIQS_GIT_HASH=${APP4TRIQS_GIT_HASH} diff --git a/doc/CMakeLists.txt b/doc/CMakeLists.txt index d3e766f7..2c1e3366 100644 --- a/doc/CMakeLists.txt +++ b/doc/CMakeLists.txt @@ -4,42 +4,48 @@ configure_file(${CMAKE_CURRENT_SOURCE_DIR}/conf.py.in ${CMAKE_CURRENT_BINARY_DIR # --------------------------------- # Top Sphinx target # --------------------------------- -# Sources -file(GLOB_RECURSE sources *.rst) +# Sphinx has internal caching, always run it +add_custom_target(docs_sphinx ALL) +add_custom_command( + TARGET docs_sphinx + COMMAND PYTHONPATH=${CMAKE_BINARY_DIR}/python:$ENV{PYTHONPATH} ${TRIQS_SPHINXBUILD_EXECUTABLE} -c . -j8 -b html ${CMAKE_CURRENT_SOURCE_DIR} html +) -set(sphinx_top ${CMAKE_CURRENT_BINARY_DIR}/html/contents.html) -add_custom_command(OUTPUT ${sphinx_top} DEPENDS ${sources} - COMMAND PYTHONPATH=${CMAKE_BINARY_DIR}/python:$ENV{PYTHONPATH} ${TRIQS_SPHINXBUILD_EXECUTABLE} -c . -j8 -b html ${CMAKE_CURRENT_SOURCE_DIR} html) -add_custom_target(docs_sphinx ALL DEPENDS ${sphinx_top} ${CMAKE_CURRENT_BINARY_DIR}) - -# Application must be compiled first -add_dependencies(docs_sphinx app4triqs_c toto_module) +# Autodoc usage requires the python modules to be built first +get_property(CPP2PY_MODULES_LIST GLOBAL PROPERTY CPP2PY_MODULES_LIST) +add_dependencies(docs_sphinx ${CPP2PY_MODULES_LIST}) # ----------------------------------------------------------------------------- -# Make an optional target that allows us to regenerate the C++ doc with c++2rst +# Create an optional target that allows us to regenerate the C++ doc with c++2rst # ----------------------------------------------------------------------------- -add_custom_target(docs_cpp2rst) - -get_property(TRIQS_INCLUDE_DIRS TARGET triqs PROPERTY INTERFACE_INCLUDE_DIRECTORIES) -get_property(APP4TRIQS_INCLUDE_DIRS TARGET app4triqs_c PROPERTY INTERFACE_INCLUDE_DIRECTORIES) -set(CPP2RST_INCLUDE_DIRS ${TRIQS_INCLUDE_DIRS} ${APP4TRIQS_INCLUDE_DIRS}) - -foreach(I ${CPP2RST_INCLUDE_DIRS}) - set (CPP2RST_INCLUDE_COMMAND ${CPP2RST_INCLUDE_COMMAND} --includes ${I}) +foreach(t app4triqs_c triqs) + get_property(INCLUDE_DIRS TARGET ${t} PROPERTY INTERFACE_INCLUDE_DIRECTORIES) + get_property(SYSTEM_INCLUDE_DIRS TARGET ${t} PROPERTY INTERFACE_SYSTEM_INCLUDE_DIRECTORIES) + if(SYTEM_INCLUDE_DIRS) + list(REMOVE_ITEM INCLUDE_DIRS ${SYSTEM_INCLUDE_DIRS}) + endif() + foreach(DIR ${INCLUDE_DIRS}) + set(CPP2RST_INCLUDE_FLAGS ${CPP2RST_INCLUDE_FLAGS} -I${DIR}) + endforeach() + foreach(DIR ${SYSTEM_INCLUDE_DIRS}) + set(CPP2RST_INCLUDE_FLAGS ${CPP2RST_INCLUDE_FLAGS} -isystem=${DIR}) + endforeach() + get_property(COMPILE_OPTIONS TARGET ${t} PROPERTY INTERFACE_COMPILE_OPTIONS) + set(CPP2RST_CXXFLAGS ${CPP2RST_CXXFLAGS} ${COMPILE_OPTIONS}) endforeach() +add_custom_target(docs_cpp2rst) macro(generate_docs header_file) add_custom_command( TARGET docs_cpp2rst - COMMAND c++2rst - ${header_file} - -N app4triqs - --output_directory ${CMAKE_CURRENT_SOURCE_DIR}/cpp2rst_generated - ${CPP2RST_INCLUDE_COMMAND} - --cxxflags="-std=c++17" - -I ${CMAKE_SOURCE_DIR}/c++ - -I ${TRIQS_ROOT}/include - 2>&1 >> cpp2rst.log + COMMAND rm -rf ${CMAKE_CURRENT_SOURCE_DIR}/cpp2rst_generated + COMMAND + c++2rst + ${header_file} + -N app4triqs + --output_directory ${CMAKE_CURRENT_SOURCE_DIR}/cpp2rst_generated + --cxxflags="${CPP2RST_CXXFLAGS}" + ${CPP2RST_INCLUDE_FLAGS} ) endmacro(generate_docs) From debb784431fb7934501e63cc0cfc82081ac544d4 Mon Sep 17 00:00:00 2001 From: Dylan Simon Date: Mon, 29 Apr 2019 11:55:14 -0400 Subject: [PATCH 092/272] [jenkins] Rename docker repo to packaging --- Jenkinsfile | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Jenkinsfile b/Jenkinsfile index e5a6e8b0..1091d87f 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -110,9 +110,9 @@ try { // note: credentials used above don't work (need JENKINS-28335) sh "git push origin master || { git pull --rebase origin master && git push origin master ; }" } - /* Update docker repo submodule */ - if (release) { dir("$workDir/docker") { try { - git(url: "ssh://git@github.com/TRIQS/docker.git", branch: env.BRANCH_NAME, credentialsId: "ssh", changelog: false) + /* Update packaging repo submodule */ + if (release) { dir("$workDir/packaging") { try { + git(url: "ssh://git@github.com/TRIQS/packaging.git", branch: env.BRANCH_NAME, credentialsId: "ssh", changelog: false) sh "test -d ${projectName}" sh "echo '160000 commit ${commit}\t${projectName}' | git update-index --index-info" sh """ @@ -122,7 +122,7 @@ try { sh "git push origin ${env.BRANCH_NAME} || { git pull --rebase origin ${env.BRANCH_NAME} && git push origin ${env.BRANCH_NAME} ; }" } catch (err) { /* Ignore, non-critical -- might not exist on this branch */ - echo "Failed to update docker repo" + echo "Failed to update packaging repo" } } } } } } } From 81c1a4aa14770d14fa664fc0376fffd74f0f0120 Mon Sep 17 00:00:00 2001 From: Dylan Simon Date: Mon, 29 Apr 2019 14:51:15 -0400 Subject: [PATCH 093/272] [jenkins] allow packaging module to be triqs_* Use triqs_PKG if it exists, otherwise PKG --- Jenkinsfile | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/Jenkinsfile b/Jenkinsfile index 1091d87f..8688e750 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -113,13 +113,14 @@ try { /* Update packaging repo submodule */ if (release) { dir("$workDir/packaging") { try { git(url: "ssh://git@github.com/TRIQS/packaging.git", branch: env.BRANCH_NAME, credentialsId: "ssh", changelog: false) - sh "test -d ${projectName}" - sh "echo '160000 commit ${commit}\t${projectName}' | git update-index --index-info" - sh """ - git commit --author='Flatiron Jenkins ' --allow-empty -m 'Autoupdate ${projectName}' -m '${env.BUILD_TAG}' - """ // note: credentials used above don't work (need JENKINS-28335) - sh "git push origin ${env.BRANCH_NAME} || { git pull --rebase origin ${env.BRANCH_NAME} && git push origin ${env.BRANCH_NAME} ; }" + sh """#!/bin/bash -ex + dir="${projectName}" + [[ -d triqs_\$dir ]] && dir=triqs_\$dir || [[ -d \$dir ]] + echo "160000 commit ${commit}\t\$dir" | git update-index --index-info + git commit --author='Flatiron Jenkins ' --allow-empty -m 'Autoupdate ${projectName}' -m '${env.BUILD_TAG}' + git push origin ${env.BRANCH_NAME} || { git pull --rebase origin ${env.BRANCH_NAME} && git push origin ${env.BRANCH_NAME} ; } + """ } catch (err) { /* Ignore, non-critical -- might not exist on this branch */ echo "Failed to update packaging repo" From 950181497528eeb4334e0b0d2a2a6bdd96dca8a2 Mon Sep 17 00:00:00 2001 From: Dylan Simon Date: Thu, 2 May 2019 13:42:36 -0400 Subject: [PATCH 094/272] [jenkins] skip empty packaging commits No use in doing an extra rebuild --- Jenkinsfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Jenkinsfile b/Jenkinsfile index 8688e750..092729cf 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -118,7 +118,7 @@ try { dir="${projectName}" [[ -d triqs_\$dir ]] && dir=triqs_\$dir || [[ -d \$dir ]] echo "160000 commit ${commit}\t\$dir" | git update-index --index-info - git commit --author='Flatiron Jenkins ' --allow-empty -m 'Autoupdate ${projectName}' -m '${env.BUILD_TAG}' + git commit --author='Flatiron Jenkins ' -m 'Autoupdate ${projectName}' -m '${env.BUILD_TAG}' git push origin ${env.BRANCH_NAME} || { git pull --rebase origin ${env.BRANCH_NAME} && git push origin ${env.BRANCH_NAME} ; } """ } catch (err) { From 5fda45520c2729210db0289d373a9112c26aad3c Mon Sep 17 00:00:00 2001 From: Nils Wentzell Date: Wed, 22 May 2019 16:50:43 -0400 Subject: [PATCH 095/272] [doc] Keep toctree (depth2) in index.rst --- doc/index.rst | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/doc/index.rst b/doc/index.rst index 6281ea07..f2610ec6 100644 --- a/doc/index.rst +++ b/doc/index.rst @@ -13,4 +13,7 @@ An example application using cpp2py and TRIQS. This documentation is generated based on `rst `_ files and the comments in the sources and headers. -Lets have a look at the :ref:`documentation `. +Learn how to use app4triqs in the :ref:`documentation`. + +.. toctree:: + :maxdepth: 2 From 3676be09db293d0d215521b4293585ad0ad4bff3 Mon Sep 17 00:00:00 2001 From: Nils Wentzell Date: Wed, 22 May 2019 16:51:03 -0400 Subject: [PATCH 096/272] Add issue templates for bug and feature request --- .github/ISSUE_TEMPLATE/bug.md | 46 +++++++++++++++++++++++++++++++ .github/ISSUE_TEMPLATE/feature.md | 30 ++++++++++++++++++++ 2 files changed, 76 insertions(+) create mode 100644 .github/ISSUE_TEMPLATE/bug.md create mode 100644 .github/ISSUE_TEMPLATE/feature.md diff --git a/.github/ISSUE_TEMPLATE/bug.md b/.github/ISSUE_TEMPLATE/bug.md new file mode 100644 index 00000000..1763232d --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug.md @@ -0,0 +1,46 @@ +--- +name: Bug report +about: Create a report to help us improve +title: Bug report +labels: bug + +--- + + + +### Prerequisites + +* [ ] Put an X between the brackets on this line if you have done all of the following: + * Checked that your issue isn't already filed: https://github.com/issues?utf8=%E2%9C%93&q=is%3Aissue+user%3Atriqs + +### Description + +[Description of the issue] + +### Steps to Reproduce + +1. [First Step] +2. [Second Step] +3. [and so on...] + +**Expected behavior:** [What you expect to happen] + +**Actual behavior:** [What actually happens] + +**Reproduces how often:** [What percentage of the time does it reproduce?] + +### Versions + +You can get this information from copy and pasting the output of +```bash +python -c "from app4triqs.version import *; show_version(); show_git_hash();" +``` +from the command line. Also, please include the OS and what version of the OS you're running. + +### Additional Information + +Any additional information, configuration or data that might be necessary to reproduce the issue. diff --git a/.github/ISSUE_TEMPLATE/feature.md b/.github/ISSUE_TEMPLATE/feature.md new file mode 100644 index 00000000..136768cd --- /dev/null +++ b/.github/ISSUE_TEMPLATE/feature.md @@ -0,0 +1,30 @@ +--- +name: Feature request +about: Suggest an idea for this project +title: Feature request +labels: feature + +--- + + + +### Summary + +One paragraph explanation of the feature. + +### Motivation + +Why are we doing this? What use cases does it support? What is the expected outcome? + +### Describe alternatives you've considered + +A clear and concise description of the alternative solutions you've considered. +Be sure to explain why the existing customizability of app4triqs isn't suitable for this feature. + +### Additional context + +Add any other context about the feature request here. From 93856f9440567062ca55e48b4b6cec64b96000ef Mon Sep 17 00:00:00 2001 From: Nils Wentzell Date: Wed, 5 Jun 2019 10:52:43 -0400 Subject: [PATCH 097/272] Minor rewording in readme --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 3217fe99..7ae2b7c2 100644 --- a/README.md +++ b/README.md @@ -1,9 +1,9 @@ # app4triqs -An example application using cpp2py and triqs ---------------------------------------------- +A skeleton for a TRIQS application +---------------------------------- -To use this skeleton for a new triqs application, the following steps are necessary: +To adapt this skeleton for a new triqs application, the following steps are necessary: * Create a repository, e.g. https://github.com/myuser/mynewapp From eca87051cb75f8c9c8b8ab59d1901f6087d7a2ba Mon Sep 17 00:00:00 2001 From: Nils Wentzell Date: Wed, 5 Jun 2019 10:56:50 -0400 Subject: [PATCH 098/272] [travis] Fix llvm setup in .travis file, enable clang build --- .travis.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index 8071e2a3..3cffaf72 100644 --- a/.travis.yml +++ b/.travis.yml @@ -5,10 +5,10 @@ dist: xenial compiler: - gcc - #- clang + - clang before_install: - - sudo add-apt-repository 'deb http://apt.llvm.org/xenial/ llvm-toolchain-xenial main' -y + - sudo add-apt-repository 'deb http://apt.llvm.org/xenial/ llvm-toolchain-xenial-7 main' -y - wget -O - https://apt.llvm.org/llvm-snapshot.gpg.key|sudo apt-key add - - sudo add-apt-repository ppa:ubuntu-toolchain-r/test -y - sudo apt-get update From 53e4f257e85d7c54d3e514485d8d71a712bf88a9 Mon Sep 17 00:00:00 2001 From: Nils Wentzell Date: Wed, 5 Jun 2019 11:29:17 -0400 Subject: [PATCH 099/272] [travis] Add build-passing status image to README --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index 7ae2b7c2..de67e629 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,5 @@ +[![Build Status](https://travis-ci.org/TRIQS/app4triqs.svg?branch=unstable)](https://travis-ci.org/TRIQS/app4triqs) + # app4triqs A skeleton for a TRIQS application From 162bf1a482b044315828aa0c64330e0b8785b437 Mon Sep 17 00:00:00 2001 From: Nils Wentzell Date: Wed, 26 Jun 2019 10:55:03 -0400 Subject: [PATCH 100/272] [travis] Build triqs in debug mode, build only with two cores --- .travis.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.travis.yml b/.travis.yml index 3cffaf72..bae3d487 100644 --- a/.travis.yml +++ b/.travis.yml @@ -27,8 +27,8 @@ script: - cd $TRAVIS_BUILD_DIR - git clone https://github.com/TRIQS/triqs --branch unstable - mkdir triqs/build && cd triqs/build - - cmake .. -DCMAKE_CXX_COMPILER=/usr/bin/${CXX} -DBuild_Tests=OFF -DCMAKE_INSTALL_PREFIX=$INSTALL_DIR - - make -j8 install + - cmake .. -DCMAKE_CXX_COMPILER=/usr/bin/${CXX} -DBuild_Tests=OFF -DCMAKE_INSTALL_PREFIX=$INSTALL_DIR -DCMAKE_BUILD_TYPE=Debug + - make -j2 install - source $INSTALL_DIR/share/triqsvars.sh # ===== Set up app4triqs and test - cd $TRAVIS_BUILD_DIR @@ -39,4 +39,4 @@ script: - export UBSAN_OPTIONS=symbolize=1:print_stacktrace=1 - export ASAN_OPTIONS=symbolize=1:detect_leaks=0 - export CTEST_OUTPUT_ON_FAILURE=1 - - make -j8 && make test + - make -j2 && make test From 24f49da39c771aaceeecb33b7d714948f379f50f Mon Sep 17 00:00:00 2001 From: Nils Wentzell Date: Wed, 26 Jun 2019 11:06:04 -0400 Subject: [PATCH 101/272] [cmake] Do not enable compiler warnings globally but instead through an interface target --- CMakeLists.txt | 22 ++++++++++++++++------ c++/app4triqs/CMakeLists.txt | 2 +- test/c++/CMakeLists.txt | 2 +- 3 files changed, 18 insertions(+), 8 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 736b0311..7cb817a1 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -17,13 +17,23 @@ set(BUILD_SHARED_LIBS OFF) # Export the list of compile-commands into compile_commands.json set(CMAKE_EXPORT_COMPILE_COMMANDS ON) -# Enable compiler warnings for the whole project +# Global compiler options add_compile_options( - -Wall - -Wextra - $<$:-Og> - $<$:-ggdb3> - ) + $<$:-Og> + $<$:-ggdb3> +) + +# Create an Interface target for compiler warnings +add_library(project_warnings INTERFACE) +install(TARGETS project_warnings EXPORT app4triqs-targets) +target_compile_options(project_warnings + INTERFACE + -Wall + -Wextra + -Wshadow + -Wpedantic + -Wno-sign-compare +) # Load Dependencies find_package(TRIQS 2.2 REQUIRED) diff --git a/c++/app4triqs/CMakeLists.txt b/c++/app4triqs/CMakeLists.txt index 53e038b5..7bf1b64c 100644 --- a/c++/app4triqs/CMakeLists.txt +++ b/c++/app4triqs/CMakeLists.txt @@ -2,7 +2,7 @@ file(GLOB_RECURSE sources *.cpp) add_library(app4triqs_c ${sources}) # Link against dependencies -target_link_libraries(app4triqs_c PUBLIC triqs) +target_link_libraries(app4triqs_c PUBLIC triqs PRIVATE project_warnings) # Configure compilation target_compile_options(app4triqs_c PUBLIC -fPIC) diff --git a/test/c++/CMakeLists.txt b/test/c++/CMakeLists.txt index b2961064..72d47886 100644 --- a/test/c++/CMakeLists.txt +++ b/test/c++/CMakeLists.txt @@ -10,7 +10,7 @@ set(all_tests toto) foreach(test ${all_tests}) get_filename_component(test_name ${test} NAME_WE) add_executable(${test_name} ${test}) - target_link_libraries(${test_name} app4triqs_c triqs::gtest) + target_link_libraries(${test_name} app4triqs_c triqs::gtest project_warnings) add_test(${test_name} ${test_name}) # Run clang-tidy if found if(CLANG_TIDY_EXECUTABLE) From b0bb95d61eeff01c98b912ae0a793091a12bb960 Mon Sep 17 00:00:00 2001 From: Nils Wentzell Date: Wed, 26 Jun 2019 11:35:20 -0400 Subject: [PATCH 102/272] [cmake] Use PROJECT_VERSION as defined through project(..) over APP4TRIQS_VERSION --- CMakeLists.txt | 24 ++++++++++-------------- share/cmake/app4triqs-config.cmake.in | 4 ++-- 2 files changed, 12 insertions(+), 16 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 7cb817a1..b6fb593e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,6 +1,6 @@ # Start configuration cmake_minimum_required(VERSION 3.0.2 FATAL_ERROR) -project(app4triqs CXX) +project(app4triqs VERSION 2.2.0 LANGUAGES CXX) if(POLICY CMP0074) cmake_policy(SET CMP0074 NEW) endif() @@ -47,12 +47,8 @@ endif() message(STATUS "-------- CMAKE_INSTALL_PREFIX: ${CMAKE_INSTALL_PREFIX} --------") # Define the app4triqs version numbers and get the git hash -set(APP4TRIQS_VERSION_MAJOR 2) -set(APP4TRIQS_VERSION_MINOR 2) -set(APP4TRIQS_VERSION_PATCH 0) -set(APP4TRIQS_VERSION ${APP4TRIQS_VERSION_MAJOR}.${APP4TRIQS_VERSION_MINOR}.${APP4TRIQS_VERSION_PATCH}) triqs_get_git_hash_of_source_dir(APP4TRIQS_GIT_HASH) -message(STATUS "app4triqs version : ${APP4TRIQS_VERSION}") +message(STATUS "app4triqs version : ${PROJECT_VERSION}") message(STATUS "Git hash: ${APP4TRIQS_GIT_HASH}") # Build and install the app4triqs library @@ -92,12 +88,12 @@ if(BUILD_DEBIAN_PACKAGE) if(NOT CMAKE_INSTALL_PREFIX STREQUAL "/usr") message(FATAL_ERROR "CMAKE_INSTALL_PREFIX must be /usr for packaging") endif() - SET(CPACK_GENERATOR "DEB") - SET(CPACK_PACKAGE_VERSION ${APP4TRIQS_VERSION}) - SET(CPACK_PACKAGE_CONTACT "https://github.com/TRIQS/app4triqs") - EXECUTE_PROCESS(COMMAND dpkg --print-architecture OUTPUT_VARIABLE CMAKE_DEBIAN_PACKAGE_ARCHITECTURE OUTPUT_STRIP_TRAILING_WHITESPACE) - SET(CPACK_DEBIAN_PACKAGE_DEPENDS "triqs (>= 2.2)") - SET(CPACK_DEBIAN_PACKAGE_SHLIBDEPS ON) - SET(CPACK_DEBIAN_PACKAGE_GENERATE_SHLIBS ON) - INCLUDE(CPack) + set(CPACK_GENERATOR "DEB") + set(CPACK_PACKAGE_VERSION ${PROJECT_VERSION}) + set(CPACK_PACKAGE_CONTACT "https://github.com/TRIQS/app4triqs") + execute_process(COMMAND dpkg --print-architecture OUTPUT_VARIABLE CMAKE_DEBIAN_PACKAGE_ARCHITECTURE OUTPUT_STRIP_TRAILING_WHITESPACE) + set(CPACK_DEBIAN_PACKAGE_DEPENDS "triqs (>= 2.2)") + set(CPACK_DEBIAN_PACKAGE_SHLIBDEPS ON) + set(CPACK_DEBIAN_PACKAGE_GENERATE_SHLIBS ON) + include(CPack) endif() diff --git a/share/cmake/app4triqs-config.cmake.in b/share/cmake/app4triqs-config.cmake.in index cc0c253c..7490c377 100644 --- a/share/cmake/app4triqs-config.cmake.in +++ b/share/cmake/app4triqs-config.cmake.in @@ -7,7 +7,7 @@ if(NOT APP4TRIQS_FOUND) set(APP4TRIQS_FOUND True) # version -set(APP4TRIQS_VERSION @APP4TRIQS_VERSION@) +set(APP4TRIQS_VERSION @PROJECT_VERSION@) set(APP4TRIQS_GIT_HASH @APP4TRIQS_GIT_HASH@) # Root of the installation @@ -16,7 +16,7 @@ set(APP4TRIQS_ROOT @CMAKE_INSTALL_PREFIX@) # Include the exported targets of this project include(@CMAKE_INSTALL_PREFIX@/lib/cmake/app4triqs/app4triqs-targets.cmake) -message(STATUS "Found app4triqs-config.cmake with version ${APP4TRIQS_VERSION}, hash = ${APP4TRIQS_GIT_HASH}") +message(STATUS "Found app4triqs-config.cmake with version @PROJECT_VERSION@, hash = @APP4TRIQS_GIT_HASH@") # Was the Project built with Documentation? set(APP4TRIQS_WITH_DOCUMENTATION @Build_Documentation@) From d02eff9ce350d337c0517386e96ede57f3234c1d Mon Sep 17 00:00:00 2001 From: Nils Wentzell Date: Wed, 26 Jun 2019 11:35:52 -0400 Subject: [PATCH 103/272] [cmake] Consistently use PROJECT_SOURCE_DIR over CMAKE_SOURCE_DIR --- c++/app4triqs/CMakeLists.txt | 2 +- doc/CMakeLists.txt | 2 +- doc/conf.py.in | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/c++/app4triqs/CMakeLists.txt b/c++/app4triqs/CMakeLists.txt index 7bf1b64c..26584a97 100644 --- a/c++/app4triqs/CMakeLists.txt +++ b/c++/app4triqs/CMakeLists.txt @@ -6,7 +6,7 @@ target_link_libraries(app4triqs_c PUBLIC triqs PRIVATE project_warnings) # Configure compilation target_compile_options(app4triqs_c PUBLIC -fPIC) -target_include_directories(app4triqs_c PUBLIC $) +target_include_directories(app4triqs_c PUBLIC $) target_compile_definitions(app4triqs_c PUBLIC APP4TRIQS_GIT_HASH=${APP4TRIQS_GIT_HASH} TRIQS_GIT_HASH=${TRIQS_GIT_HASH} diff --git a/doc/CMakeLists.txt b/doc/CMakeLists.txt index 2c1e3366..75f0ca56 100644 --- a/doc/CMakeLists.txt +++ b/doc/CMakeLists.txt @@ -49,7 +49,7 @@ macro(generate_docs header_file) ) endmacro(generate_docs) -generate_docs(${CMAKE_SOURCE_DIR}/c++/app4triqs/toto.hpp) +generate_docs(${PROJECT_SOURCE_DIR}/c++/app4triqs/toto.hpp) # --------------------------------- # Install diff --git a/doc/conf.py.in b/doc/conf.py.in index 32b6f1a3..fbeb2309 100644 --- a/doc/conf.py.in +++ b/doc/conf.py.in @@ -24,7 +24,7 @@ copyright = u'2017-2018 N. Wentzell, O. Parcollet 2018-2019 The Simons Foundatio version = '@APP4TRIQS_VERSION@' mathjax_path = "@TRIQS_MATHJAX_PATH@/MathJax.js?config=default" -templates_path = ['@CMAKE_SOURCE_DIR@/doc/_templates'] +templates_path = ['@PROJECT_SOURCE_DIR@/doc/_templates'] html_theme = 'triqs' html_theme_path = ['@TRIQS_THEMES_PATH@'] @@ -35,7 +35,7 @@ html_context = {'header_title': 'app4triqs', ['Documentation', 'documentation'], ['Issues', 'issues'], ['About app4triqs', 'about']]} -html_static_path = ['@CMAKE_SOURCE_DIR@/doc/_static'] +html_static_path = ['@PROJECT_SOURCE_DIR@/doc/_static'] html_sidebars = {'index': ['sideb.html', 'searchbox.html']} htmlhelp_basename = 'APP4TRIQSdoc' From c3114e313a88c73299a1d6acc9ec07b213139927 Mon Sep 17 00:00:00 2001 From: Philipp D Date: Wed, 26 Jun 2019 13:45:34 -0400 Subject: [PATCH 104/272] [cmake] streamline top-level cmake * enforces major.minor version check against triqs * adds header boilerplate * minor cleaning --- CMakeLists.txt | 80 ++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 62 insertions(+), 18 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index b6fb593e..48e08ead 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,15 +1,64 @@ -# Start configuration +# ############################################################################## +# +# app4triqs - An example application using triqs and cpp2py +# +# Copyright (C) ... +# +# app4triqs 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 3 of the License, or (at your option) any later +# version. +# +# app4triqs 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 +# app4triqs (in the file COPYING.txt in this directory). If not, see +# . +# +# ############################################################################## + cmake_minimum_required(VERSION 3.0.2 FATAL_ERROR) -project(app4triqs VERSION 2.2.0 LANGUAGES CXX) if(POLICY CMP0074) cmake_policy(SET CMP0074 NEW) endif() +# ############ +# Define Project + +project(APP4TRIQS VERSION 2.2.0 LANGUAGES CXX) + +# ############ +# Load TRIQS and CPP2PY +find_package(TRIQS 2.2 REQUIRED) +find_package(Cpp2Py 1.6 REQUIRED) + +# Get the git hash & print status +triqs_get_git_hash_of_source_dir(CMAKE_PROJECT_GIT_HASH) +message(STATUS "${PROJECT_NAME} version : ${PROJECT_VERSION}") +message(STATUS "${PROJECT_NAME} Git hash: ${CMAKE_PROJECT_GIT_HASH}") + +# Enforce Consistent Versioning +if(NOT ${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR} VERSION_EQUAL ${TRIQS_VERSION_MAJOR}.${TRIQS_VERSION_MINOR}) + message(FATAL_ERROR "The ${PROJECT_NAME} version ${PROJECT_VERSION} is not compatible with TRIQS version ${TRIQS_VERSION}.") +endif() + +# Default Install directory to TRIQS_ROOT if not given or invalid. +if(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT OR (NOT IS_ABSOLUTE ${CMAKE_INSTALL_PREFIX})) + message(STATUS "No install prefix given (or invalid). Defaulting to TRIQS_ROOT") + set(CMAKE_INSTALL_PREFIX ${TRIQS_ROOT} CACHE PATH "default install path" FORCE) +endif() +message(STATUS "-------- CMAKE_INSTALL_PREFIX: ${CMAKE_INSTALL_PREFIX} --------") + +# ############ +# Options + # Default to Release build type if(NOT CMAKE_BUILD_TYPE) set(CMAKE_BUILD_TYPE Release CACHE STRING "Type of build" FORCE) endif() -message( STATUS "-------- BUILD-TYPE: ${CMAKE_BUILD_TYPE} --------") +message(STATUS "-------- BUILD-TYPE: ${CMAKE_BUILD_TYPE} --------") # Build static libraries set(BUILD_SHARED_LIBS OFF) @@ -35,21 +84,12 @@ target_compile_options(project_warnings -Wno-sign-compare ) -# Load Dependencies -find_package(TRIQS 2.2 REQUIRED) -find_package(Cpp2Py 1.6 REQUIRED) +# ############# +# Load non-TRIQS Dependencies -# Default Install directory to TRIQS_ROOT if not given or invalid. -if(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT OR (NOT IS_ABSOLUTE ${CMAKE_INSTALL_PREFIX})) - message(STATUS "No install prefix given (or invalid). Defaulting to TRIQS_ROOT") - set(CMAKE_INSTALL_PREFIX ${TRIQS_ROOT} CACHE PATH "default install path" FORCE) -endif() -message(STATUS "-------- CMAKE_INSTALL_PREFIX: ${CMAKE_INSTALL_PREFIX} --------") -# Define the app4triqs version numbers and get the git hash -triqs_get_git_hash_of_source_dir(APP4TRIQS_GIT_HASH) -message(STATUS "app4triqs version : ${PROJECT_VERSION}") -message(STATUS "Git hash: ${APP4TRIQS_GIT_HASH}") +# ############# +# Build Project # Build and install the app4triqs library add_subdirectory(c++/app4triqs) @@ -69,25 +109,28 @@ if(TRIQS_WITH_PYTHON_SUPPORT) option(Build_Documentation "Build documentation" OFF) if(Build_Documentation) if(NOT TRIQS_WITH_DOCUMENTATION) - message(WARNING "TRIQS library has not been compiled with its documentation! Cannot build documentation.") + message(WARNING "TRIQS was installed without documentation! Cannot build documentation.") else() message(STATUS "Documentation Build enabled") add_subdirectory(doc) endif() endif() else() - message(WARNING "TRIQS library has been installed without Python support. Cannot build the Python Interface and Documentation.") + message(WARNING "TRIQS was installed without Python support. Cannot build the Python Interface and Documentation.") endif() # Additional configuration files add_subdirectory(share) +# ############# # Debian Package + option(BUILD_DEBIAN_PACKAGE "Build a deb package" OFF) if(BUILD_DEBIAN_PACKAGE) if(NOT CMAKE_INSTALL_PREFIX STREQUAL "/usr") message(FATAL_ERROR "CMAKE_INSTALL_PREFIX must be /usr for packaging") endif() + set(CPACK_PACKAGE_NAME app4triqs) set(CPACK_GENERATOR "DEB") set(CPACK_PACKAGE_VERSION ${PROJECT_VERSION}) set(CPACK_PACKAGE_CONTACT "https://github.com/TRIQS/app4triqs") @@ -97,3 +140,4 @@ if(BUILD_DEBIAN_PACKAGE) set(CPACK_DEBIAN_PACKAGE_GENERATE_SHLIBS ON) include(CPack) endif() + From bb3eb8ecad473c470db28ee306d75cd39b67fe67 Mon Sep 17 00:00:00 2001 From: Nils Wentzell Date: Tue, 16 Jul 2019 11:26:38 -0400 Subject: [PATCH 105/272] [cmake] Install svg figures together with documentation --- doc/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/CMakeLists.txt b/doc/CMakeLists.txt index 75f0ca56..8e51140a 100644 --- a/doc/CMakeLists.txt +++ b/doc/CMakeLists.txt @@ -56,6 +56,6 @@ generate_docs(${PROJECT_SOURCE_DIR}/c++/app4triqs/toto.hpp) # --------------------------------- install(DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/html/ COMPONENT documentation DESTINATION share/doc/app4triqs FILES_MATCHING - REGEX "\\.(html|pdf|png|gif|jpg|js|xsl|css|py|txt|inv|bib)$" + REGEX "\\.(html|pdf|png|gif|jpg|svg|js|xsl|css|py|txt|inv|bib)$" PATTERN "_*" ) From 45dc6e1b3cd4216da18c3e3a054b9a31ad297b1f Mon Sep 17 00:00:00 2001 From: Nils Wentzell Date: Tue, 16 Jul 2019 11:28:45 -0400 Subject: [PATCH 106/272] [travis] Build against sanitized version of triqs --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index bae3d487..e7b7172f 100644 --- a/.travis.yml +++ b/.travis.yml @@ -27,7 +27,7 @@ script: - cd $TRAVIS_BUILD_DIR - git clone https://github.com/TRIQS/triqs --branch unstable - mkdir triqs/build && cd triqs/build - - cmake .. -DCMAKE_CXX_COMPILER=/usr/bin/${CXX} -DBuild_Tests=OFF -DCMAKE_INSTALL_PREFIX=$INSTALL_DIR -DCMAKE_BUILD_TYPE=Debug + - cmake .. -DCMAKE_CXX_COMPILER=/usr/bin/${CXX} -DBuild_Tests=OFF -DCMAKE_INSTALL_PREFIX=$INSTALL_DIR -DASAN=ON -DUBSAN=ON - make -j2 install - source $INSTALL_DIR/share/triqsvars.sh # ===== Set up app4triqs and test From 99df95f8536a2175111902fc815659cf3d5eecc8 Mon Sep 17 00:00:00 2001 From: Nils Wentzell Date: Tue, 16 Jul 2019 11:29:51 -0400 Subject: [PATCH 107/272] [travis] Switch to gcc and clang version 8, clean dependency list --- .travis.yml | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/.travis.yml b/.travis.yml index e7b7172f..569b67fd 100644 --- a/.travis.yml +++ b/.travis.yml @@ -8,16 +8,16 @@ compiler: - clang before_install: - - sudo add-apt-repository 'deb http://apt.llvm.org/xenial/ llvm-toolchain-xenial-7 main' -y + - sudo add-apt-repository 'deb http://apt.llvm.org/xenial/ llvm-toolchain-xenial-8 main' -y - wget -O - https://apt.llvm.org/llvm-snapshot.gpg.key|sudo apt-key add - - sudo add-apt-repository ppa:ubuntu-toolchain-r/test -y - sudo apt-get update - sudo rm -f /var/lib/apt/lists/lock /var/cache/apt/archives/lock /var/lib/dpkg/lock # Avoid the occasional apt-get install failure for xenial image - - sudo apt-get install -y --allow-unauthenticated g++-7 clang-7 - - export LIBRARY_PATH=/usr/lib/llvm-7/lib:$LIBRARY_PATH - - sudo update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-7 60 --slave /usr/bin/g++ g++ /usr/bin/g++-7 - - sudo update-alternatives --install /usr/bin/clang clang /usr/bin/clang-7 60 --slave /usr/bin/clang++ clang++ /usr/bin/clang++-7 - - sudo apt-get install -y --allow-unauthenticated libboost-all-dev cmake git libgfortran3 gfortran openmpi-bin openmpi-common openmpi-doc libopenmpi-dev libblas-dev liblapack-dev libfftw3-dev libgmp-dev hdf5-tools libhdf5-serial-dev python-h5py python-dev python-numpy python-scipy python-jinja2 python-virtualenv python-matplotlib python-tornado python-zmq python-mpi4py python-mako clang-format-7 libclang-7-dev python-clang-7 python-sphinx libjs-mathjax valgrind libnfft3-dev + - sudo apt-get install -y --allow-unauthenticated g++-8 clang-8 + - export LIBRARY_PATH=/usr/lib/llvm-8/lib:$LIBRARY_PATH + - sudo update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-8 60 --slave /usr/bin/g++ g++ /usr/bin/g++-8 + - sudo update-alternatives --install /usr/bin/clang clang /usr/bin/clang-8 60 --slave /usr/bin/clang++ clang++ /usr/bin/clang++-8 + - sudo apt-get install -y --allow-unauthenticated cmake git hdf5-tools libblas-dev libboost-all-dev libfftw3-dev libgfortran3 libhdf5-serial-dev libgmp-dev liblapack-dev libopenmpi-dev libclang-8-dev python-clang-8 python-dev python-h5py python-mako python-matplotlib python-mpi4py python-numpy python-scipy python-sphinx libjs-mathjax libnfft3-dev install: true @@ -34,8 +34,8 @@ script: - cd $TRAVIS_BUILD_DIR - mkdir build && cd build - cmake .. -DCMAKE_CXX_COMPILER=/usr/bin/${CXX} -DASAN=ON -DUBSAN=ON - - export UBSAN_SYMBOLIZER_PATH=/usr/lib/llvm-7/bin/llvm-symbolizer - - export ASAN_SYMBOLIZER_PATH=/usr/lib/llvm-7/bin/llvm-symbolizer + - export UBSAN_SYMBOLIZER_PATH=/usr/lib/llvm-8/bin/llvm-symbolizer + - export ASAN_SYMBOLIZER_PATH=/usr/lib/llvm-8/bin/llvm-symbolizer - export UBSAN_OPTIONS=symbolize=1:print_stacktrace=1 - export ASAN_OPTIONS=symbolize=1:detect_leaks=0 - export CTEST_OUTPUT_ON_FAILURE=1 From 8d906ed6cc73bc6221a9eab9d743b6bc51d261a3 Mon Sep 17 00:00:00 2001 From: Nils Wentzell Date: Tue, 16 Jul 2019 11:54:32 -0400 Subject: [PATCH 108/272] [cmake] Use PROJECT_GIT_HASH instead to store git hash and adjust dependent files accordingly --- CMakeLists.txt | 4 ++-- c++/app4triqs/CMakeLists.txt | 2 +- python/app4triqs/version.py.in | 2 +- share/app4triqs.modulefile.in | 2 +- share/cmake/app4triqs-config.cmake.in | 4 ++-- 5 files changed, 7 insertions(+), 7 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 48e08ead..90b379e4 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -35,9 +35,9 @@ find_package(TRIQS 2.2 REQUIRED) find_package(Cpp2Py 1.6 REQUIRED) # Get the git hash & print status -triqs_get_git_hash_of_source_dir(CMAKE_PROJECT_GIT_HASH) +triqs_get_git_hash_of_source_dir(PROJECT_GIT_HASH) message(STATUS "${PROJECT_NAME} version : ${PROJECT_VERSION}") -message(STATUS "${PROJECT_NAME} Git hash: ${CMAKE_PROJECT_GIT_HASH}") +message(STATUS "${PROJECT_NAME} Git hash: ${PROJECT_GIT_HASH}") # Enforce Consistent Versioning if(NOT ${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR} VERSION_EQUAL ${TRIQS_VERSION_MAJOR}.${TRIQS_VERSION_MINOR}) diff --git a/c++/app4triqs/CMakeLists.txt b/c++/app4triqs/CMakeLists.txt index 26584a97..609eb2e0 100644 --- a/c++/app4triqs/CMakeLists.txt +++ b/c++/app4triqs/CMakeLists.txt @@ -8,7 +8,7 @@ target_link_libraries(app4triqs_c PUBLIC triqs PRIVATE project_warnings) target_compile_options(app4triqs_c PUBLIC -fPIC) target_include_directories(app4triqs_c PUBLIC $) target_compile_definitions(app4triqs_c PUBLIC - APP4TRIQS_GIT_HASH=${APP4TRIQS_GIT_HASH} + APP4TRIQS_GIT_HASH=${PROJECT_GIT_HASH} TRIQS_GIT_HASH=${TRIQS_GIT_HASH} $<$:APP4TRIQS_DEBUG> $<$:TRIQS_DEBUG> diff --git a/python/app4triqs/version.py.in b/python/app4triqs/version.py.in index d6c83d2d..d97a682a 100644 --- a/python/app4triqs/version.py.in +++ b/python/app4triqs/version.py.in @@ -23,7 +23,7 @@ version = "@APP4TRIQS_VERSION@" triqs_hash = "@TRIQS_GIT_HASH@" -app4triqs_hash = "@APP4TRIQS_GIT_HASH@" +app4triqs_hash = "@PROJECT_GIT_HASH@" def show_version(): print "\nYou are using app4triqs version %s\n"%version diff --git a/share/app4triqs.modulefile.in b/share/app4triqs.modulefile.in index 15b8baa0..cbca2b0b 100644 --- a/share/app4triqs.modulefile.in +++ b/share/app4triqs.modulefile.in @@ -5,7 +5,7 @@ set name app4triqs set version @APP4TRIQS_VERSION@ set root @CMAKE_INSTALL_PREFIX@ -set git_hash @APP4TRIQS_GIT_HASH@ +set git_hash @PROJECT_GIT_HASH@ set url "https://github.com/TRIQS/app4triqs" set description "An example application using cpp2py and triqs." diff --git a/share/cmake/app4triqs-config.cmake.in b/share/cmake/app4triqs-config.cmake.in index 7490c377..c2f0a7b3 100644 --- a/share/cmake/app4triqs-config.cmake.in +++ b/share/cmake/app4triqs-config.cmake.in @@ -8,7 +8,7 @@ set(APP4TRIQS_FOUND True) # version set(APP4TRIQS_VERSION @PROJECT_VERSION@) -set(APP4TRIQS_GIT_HASH @APP4TRIQS_GIT_HASH@) +set(APP4TRIQS_GIT_HASH @PROJECT_GIT_HASH@) # Root of the installation set(APP4TRIQS_ROOT @CMAKE_INSTALL_PREFIX@) @@ -16,7 +16,7 @@ set(APP4TRIQS_ROOT @CMAKE_INSTALL_PREFIX@) # Include the exported targets of this project include(@CMAKE_INSTALL_PREFIX@/lib/cmake/app4triqs/app4triqs-targets.cmake) -message(STATUS "Found app4triqs-config.cmake with version @PROJECT_VERSION@, hash = @APP4TRIQS_GIT_HASH@") +message(STATUS "Found app4triqs-config.cmake with version @PROJECT_VERSION@, hash = @PROJECT_GIT_HASH@") # Was the Project built with Documentation? set(APP4TRIQS_WITH_DOCUMENTATION @Build_Documentation@) From 7aaffab7e6a297892b3ca4d316807dddd94f3afa Mon Sep 17 00:00:00 2001 From: Dylan Simon Date: Fri, 26 Jul 2019 14:01:22 -0400 Subject: [PATCH 109/272] [jenkins] Preserve all installs by default as triqs does already --- Jenkinsfile | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/Jenkinsfile b/Jenkinsfile index 092729cf..7efdb8f2 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -5,8 +5,8 @@ def documentationPlatform = "ubuntu-clang" /* depend on triqs upstream branch/project */ def triqsBranch = env.CHANGE_TARGET ?: env.BRANCH_NAME def triqsProject = '/TRIQS/triqs/' + triqsBranch.replaceAll('/', '%2F') -/* whether to publish the results (disabled for template project) */ -def publish = !env.BRANCH_NAME.startsWith("PR-") +/* whether to keep and publish the results */ +def keepInstall = !env.BRANCH_NAME.startsWith("PR-") properties([ disableConcurrentBuilds(), @@ -38,8 +38,7 @@ for (int i = 0; i < dockerPlatforms.size(); i++) { """ /* build and tag */ def img = docker.build("flatironinstitute/${projectName}:${env.BRANCH_NAME}-${env.STAGE_NAME}", "--build-arg APPNAME=${projectName} --build-arg BUILD_DOC=${platform==documentationPlatform} .") - if (!publish || platform != documentationPlatform) { - /* but we don't need the tag so clean it up (except for documentation) */ + if (!keepInstall) { sh "docker rmi --no-prune ${img.imageName()}" } } } @@ -59,7 +58,7 @@ for (int i = 0; i < osxPlatforms.size(); i++) { def srcDir = pwd() def tmpDir = pwd(tmp:true) def buildDir = "$tmpDir/build" - def installDir = "$tmpDir/install" + def installDir = keepInstall ? "${env.HOME}/install/${projectName}/${env.BRANCH_NAME}/${platform}" : "$tmpDir/install" def triqsDir = "${env.HOME}/install/triqs/${triqsBranch}/${platform}" dir(installDir) { deleteDir() @@ -89,7 +88,7 @@ for (int i = 0; i < osxPlatforms.size(); i++) { /****************** wrap-up */ try { parallel platforms - if (publish) { node("docker") { + if (keepInstall) { node("docker") { /* Publish results */ stage("publish") { timeout(time: 1, unit: 'HOURS') { def commit = sh(returnStdout: true, script: "git rev-parse HEAD").trim() From b5278079deb9b224bf4c9bacdfa547c5204f86da Mon Sep 17 00:00:00 2001 From: Dylan Simon Date: Fri, 26 Jul 2019 15:04:01 -0400 Subject: [PATCH 110/272] [jenkins] remove myself from emails --- Jenkinsfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Jenkinsfile b/Jenkinsfile index 7efdb8f2..7744f4c9 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -145,7 +145,7 @@ Changes: End of build log: \${BUILD_LOG,maxLines=60} """, - to: 'nwentzell@flatironinstitute.org, dsimon@flatironinstitute.org', + to: 'nwentzell@flatironinstitute.org', recipientProviders: [ [$class: 'DevelopersRecipientProvider'], ], From e5a4cfb47e34535c58b0f28725dcbc6155c0ade5 Mon Sep 17 00:00:00 2001 From: Dylan Simon Date: Mon, 29 Jul 2019 14:42:20 -0400 Subject: [PATCH 111/272] Add requirements.txt for python package dependencies --- Jenkinsfile | 2 ++ requirements.txt | 1 + 2 files changed, 3 insertions(+) create mode 100644 requirements.txt diff --git a/Jenkinsfile b/Jenkinsfile index 7744f4c9..e0a0b2d9 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -71,6 +71,8 @@ for (int i = 0; i < osxPlatforms.size(); i++) { "LIBRARY_PATH=$triqsDir/lib:${env.BREW}/lib", "CMAKE_PREFIX_PATH=$triqsDir/lib/cmake/triqs"]) { deleteDir() + /* note: this is installing into the parent (triqs) venv (install dir), which is thus shared among apps and so not be completely safe */ + sh "pip install -r $srcDir/requirements.txt" sh "cmake $srcDir -DCMAKE_INSTALL_PREFIX=$installDir -DTRIQS_ROOT=$triqsDir" sh "make -j3" try { diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 00000000..21ccef9e --- /dev/null +++ b/requirements.txt @@ -0,0 +1 @@ +# Required python packages for this application (these should also be added to Dockerfile for Jenkins) From 63109a445b9727a2cef79074565835a0bb7413e2 Mon Sep 17 00:00:00 2001 From: Nils Wentzell Date: Wed, 31 Jul 2019 11:07:48 -0400 Subject: [PATCH 112/272] [cmake] Generalize test/c++/CMakeLists.txt file to allow subdirectories and globbing --- test/c++/CMakeLists.txt | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/test/c++/CMakeLists.txt b/test/c++/CMakeLists.txt index 72d47886..a2b6a9d5 100644 --- a/test/c++/CMakeLists.txt +++ b/test/c++/CMakeLists.txt @@ -5,11 +5,14 @@ foreach(file ${all_h5_ref_files}) endforeach() # List of all tests -set(all_tests toto) +set(all_tests *.cpp) +file(GLOB_RECURSE all_tests RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} ${all_tests}) foreach(test ${all_tests}) get_filename_component(test_name ${test} NAME_WE) + get_filename_component(test_dir ${test} DIRECTORY) add_executable(${test_name} ${test}) + set_property(TARGET ${test_name} PROPERTY RUNTIME_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/${test_dir}) target_link_libraries(${test_name} app4triqs_c triqs::gtest project_warnings) add_test(${test_name} ${test_name}) # Run clang-tidy if found From 907827562b585501de5140191b047a0ec0b7019c Mon Sep 17 00:00:00 2001 From: Dylan Simon Date: Wed, 31 Jul 2019 12:13:08 -0400 Subject: [PATCH 113/272] [jenkins] try to exclude large git packs from build --- .dockerignore | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.dockerignore b/.dockerignore index 6e7a76a5..b627e92a 100644 --- a/.dockerignore +++ b/.dockerignore @@ -1,2 +1,4 @@ +.travis.yml Dockerfile Jenkinsfile +.git/objects/pack From 81346f5e4dc8394542492da3d2aa7c4b0b7b2fb6 Mon Sep 17 00:00:00 2001 From: Dylan Simon Date: Wed, 31 Jul 2019 12:13:28 -0400 Subject: [PATCH 114/272] [jenkins] Make linux builds use requirements.txt --- Dockerfile | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index 1d7149fb..c65c6760 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,7 +1,10 @@ # See ../triqs/packaging for other options FROM flatironinstitute/triqs:master-ubuntu-clang - ARG APPNAME + +COPY requirements.txt /src/$APPNAME/requirements.txt +RUN pip install -r /src/$APPNAME/requirements.txt + COPY . $SRC/$APPNAME WORKDIR $BUILD/$APPNAME RUN chown build . From 3b1b412b4eee6901cbeb739e35ae4fea5734d88b Mon Sep 17 00:00:00 2001 From: Nils Wentzell Date: Fri, 2 Aug 2019 14:24:21 -0400 Subject: [PATCH 115/272] Correction to previous commit, run c++ tests in proper test directory --- test/c++/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/c++/CMakeLists.txt b/test/c++/CMakeLists.txt index a2b6a9d5..35748834 100644 --- a/test/c++/CMakeLists.txt +++ b/test/c++/CMakeLists.txt @@ -14,7 +14,7 @@ foreach(test ${all_tests}) add_executable(${test_name} ${test}) set_property(TARGET ${test_name} PROPERTY RUNTIME_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/${test_dir}) target_link_libraries(${test_name} app4triqs_c triqs::gtest project_warnings) - add_test(${test_name} ${test_name}) + add_test(NAME ${test_name} COMMAND ${test_name} WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/${test_dir}) # Run clang-tidy if found if(CLANG_TIDY_EXECUTABLE) set_target_properties(${test_name} PROPERTIES CXX_CLANG_TIDY "${CLANG_TIDY_EXECUTABLE}") From 4f863dc2a518d7c63ca3c457abd427ffbecabee9 Mon Sep 17 00:00:00 2001 From: Nils Wentzell Date: Tue, 6 Aug 2019 11:14:57 -0400 Subject: [PATCH 116/272] [cmake] Install all modules by default --- python/app4triqs/CMakeLists.txt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/python/app4triqs/CMakeLists.txt b/python/app4triqs/CMakeLists.txt index 2de26908..6ec57050 100644 --- a/python/app4triqs/CMakeLists.txt +++ b/python/app4triqs/CMakeLists.txt @@ -15,5 +15,6 @@ endforeach() # Install python module to proper location set(PYTHON_LIB_DEST ${TRIQS_PYTHON_LIB_DEST_ROOT}/app4triqs) -install(TARGETS toto_module DESTINATION ${PYTHON_LIB_DEST}) +get_property(CPP2PY_MODULES_LIST GLOBAL PROPERTY CPP2PY_MODULES_LIST) +install(TARGETS ${CPP2PY_MODULES_LIST} DESTINATION ${PYTHON_LIB_DEST}) install(FILES ${python_sources} ${CMAKE_CURRENT_BINARY_DIR}/version.py DESTINATION ${PYTHON_LIB_DEST}) From a2767f16c824858e4f1b1391774b200200fcc81f Mon Sep 17 00:00:00 2001 From: Nils Wentzell Date: Tue, 6 Aug 2019 11:32:02 -0400 Subject: [PATCH 117/272] [cmake] Exported targets should live in project namespace --- share/cmake/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/share/cmake/CMakeLists.txt b/share/cmake/CMakeLists.txt index 062ed6c6..bf97bfb8 100644 --- a/share/cmake/CMakeLists.txt +++ b/share/cmake/CMakeLists.txt @@ -7,4 +7,4 @@ install( DESTINATION lib/cmake/app4triqs ) -install(EXPORT app4triqs-targets DESTINATION lib/cmake/app4triqs) +install(EXPORT app4triqs-targets NAMESPACE app4triqs:: DESTINATION lib/cmake/app4triqs) From ce19003682e2ae79f723bf2a6972d9cddccc7e86 Mon Sep 17 00:00:00 2001 From: Nils Wentzell Date: Mon, 19 Aug 2019 18:10:26 -0400 Subject: [PATCH 118/272] [doc] Update triqs links in conf.py.in --- doc/conf.py.in | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/conf.py.in b/doc/conf.py.in index fbeb2309..08d29930 100644 --- a/doc/conf.py.in +++ b/doc/conf.py.in @@ -30,7 +30,7 @@ html_theme = 'triqs' html_theme_path = ['@TRIQS_THEMES_PATH@'] html_show_sphinx = False html_context = {'header_title': 'app4triqs', - 'header_subtitle': 'An example application using cpp2py and triqs', + 'header_subtitle': 'An example application using cpp2py and TRIQS', 'header_links': [['Install', 'install'], ['Documentation', 'documentation'], ['Issues', 'issues'], @@ -40,4 +40,4 @@ html_sidebars = {'index': ['sideb.html', 'searchbox.html']} htmlhelp_basename = 'APP4TRIQSdoc' -intersphinx_mapping = {'python': ('http://docs.python.org/2.7', None), 'triqslibs': ('https://triqs.github.io/triqs/master', None)} +intersphinx_mapping = {'python': ('http://docs.python.org/2.7', None), 'triqslibs': ('https://triqs.github.io/triqs/latest', None)} From cd758dd639d39eb936fd8dfabf9bc7f8f9b6bdc0 Mon Sep 17 00:00:00 2001 From: Nils Wentzell Date: Mon, 19 Aug 2019 18:25:15 -0400 Subject: [PATCH 119/272] [doc] Add triqs-link to welcome page --- doc/index.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/index.rst b/doc/index.rst index f2610ec6..16a8278d 100644 --- a/doc/index.rst +++ b/doc/index.rst @@ -8,7 +8,7 @@ app4triqs This is the homepage of app4triqs v2.2.0. For changes see the :ref:`changelog page `. -An example application using cpp2py and TRIQS. +An example application using cpp2py and :ref:`TRIQS `. This documentation is generated based on `rst `_ files and the comments in the sources and headers. From c87aceed37f483029f159ba8bf0ee1aca6c62fc8 Mon Sep 17 00:00:00 2001 From: Nils Wentzell Date: Tue, 20 Aug 2019 14:32:21 -0400 Subject: [PATCH 120/272] [cmake] Generate list of all tests through GLOB_RECURSE by default --- test/c++/CMakeLists.txt | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/test/c++/CMakeLists.txt b/test/c++/CMakeLists.txt index 35748834..7c1b3235 100644 --- a/test/c++/CMakeLists.txt +++ b/test/c++/CMakeLists.txt @@ -5,8 +5,7 @@ foreach(file ${all_h5_ref_files}) endforeach() # List of all tests -set(all_tests *.cpp) -file(GLOB_RECURSE all_tests RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} ${all_tests}) +file(GLOB_RECURSE all_tests RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} *.cpp) foreach(test ${all_tests}) get_filename_component(test_name ${test} NAME_WE) From 180d06284681ff8276b7b2a14f225d5538253553 Mon Sep 17 00:00:00 2001 From: Dylan Simon Date: Tue, 20 Aug 2019 16:01:55 -0400 Subject: [PATCH 121/272] [jenkins] Don't trigger PR builds on upstream changes --- Jenkinsfile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Jenkinsfile b/Jenkinsfile index e0a0b2d9..7a42331f 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -11,12 +11,12 @@ def keepInstall = !env.BRANCH_NAME.startsWith("PR-") properties([ disableConcurrentBuilds(), buildDiscarder(logRotator(numToKeepStr: '10', daysToKeepStr: '30')), - pipelineTriggers([ + pipelineTriggers(keepInstall ? [ upstream( threshold: 'SUCCESS', upstreamProjects: triqsProject ) - ]) + ] : []) ]) /* map of all builds to run, populated below */ From 3c94a87ca6c3ee8857b8d603b61b1406fa87fa66 Mon Sep 17 00:00:00 2001 From: Nils Wentzell Date: Tue, 27 Aug 2019 15:35:04 -0400 Subject: [PATCH 122/272] Update README file with more detailed instructions --- README.md | 63 ++++++++++++++++++++++++++++++++++++++++++------------- 1 file changed, 48 insertions(+), 15 deletions(-) diff --git a/README.md b/README.md index de67e629..aa2019a6 100644 --- a/README.md +++ b/README.md @@ -5,35 +5,68 @@ A skeleton for a TRIQS application ---------------------------------- -To adapt this skeleton for a new triqs application, the following steps are necessary: +**Caution**: The following instructions require the `util-linux` rename command. +Please confirm that you have the right version by running `rename --version`. +For the Perl rename command see instructions in the following section. + +To adapt this skeleton for a new TRIQS application, the following steps are necessary: * Create a repository, e.g. https://github.com/myuser/mynewapp -* Run the following commands (replacing myuser and mynewapp accordingly) +* Run the following commands in order after replacing myuser, mynewapp and MYNEWAPP accordingly ```bash -git clone https://github.com/triqs/app4triqs --branch unstable mynewapp -cd mynewapp -git remote set-url origin https://github.com/myuser/mynewapp -find . -type f | grep -v .git | xargs sed -i 's/app4triqs/mynewapp/g; s/APP4TRIQS/MYNEWAPP/g' -find . -type d | grep -v .git | xargs rename app4triqs mynewapp -find . -type f | grep -v .git | xargs rename app4triqs mynewapp -git add -A -git commit -m "Create mynewapp from github.com/triqs/app4triqs skeleton" -git push +github_username=myuser +app_name=mynewapp +capital_name=MYNEWAPP + +git clone https://github.com/triqs/app4triqs --branch unstable ${app_name} +cd ${app_name} +git reset $(git commit-tree HEAD\^{tree} -m "Create ${app_name} from github.com/triqs/app4triqs skeleton") +git merge --allow-unrelated-histories -s ours HEAD@{1} -m "Track app4triqs skeleton" +find . -type f | grep -v .git | xargs sed -i 's/app4triqs/${app_name}/g; s/APP4TRIQS/${capital_name}/g' +find . -type d | grep -v .git | xargs rename app4triqs ${app_name} +find . -type f | grep -v .git | xargs rename app4triqs ${app_name} +git add -A && git commit -m "Adjust app4triqs skeleton for ${app_name}" +git remote set-url origin https://github.com/${github_username}/${app_name} +git remote add app4triqs_remote https://github.com/triqs/app4triqs +git remote update && git remote prune origin ``` -Depending on which version of the rename command you are using you may -need to replace the aforementioned rename commands as follows +You can now push to your github repository ```bash -find . -type d | grep -v .git | xargs rename 's/app4triqs/mynewapp/' -find . -type f | grep -v .git | xargs rename 's/app4triqs/mynewapp/' +git push origin unstable ``` +Perl rename command +------------------- + +If you are using the Perl-based rename command you will need to + +```bash +find . -type d | grep -v .git | xargs rename 's/app4triqs/${app_name}/' +find . -type f | grep -v .git | xargs rename 's/app4triqs/${app_name}/' +``` + +Github SSH interface +-------------------- + If you prefer to use the SSH interface to the remote repository, replace the http link accordingly ``` https://github.com/myuser/mynewapp --> git@github.com:myuser/mynewapp ``` + +Merging app4triqs skeleton updates +---------------------------------- + +You can merge future changes to app4triqs into your project with the following commands + +```bash +git remote update +git merge app4triqs_remote -m "Merge latest app4triqs skeleton changes" +``` + +If you should encounter any conflicts resolve them and `git commit`. From 66f270e7416d9e5b40e1bf11bf9dd1e574ce9c23 Mon Sep 17 00:00:00 2001 From: Nils Wentzell Date: Tue, 27 Aug 2019 15:42:39 -0400 Subject: [PATCH 123/272] App4triqs changelog --- doc/ChangeLog.md | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/doc/ChangeLog.md b/doc/ChangeLog.md index ae187f62..c71910b2 100644 --- a/doc/ChangeLog.md +++ b/doc/ChangeLog.md @@ -1,7 +1,10 @@ Version 2.2.0 ------------- -Some Changes -~~~~~~~~~~~~ +App4triqs Version 2.2.0 provides a project +skeleton for TRIQS applications based on +the TRIQS Library Version 2.2.0. +It is intended for applications with both +Python and C++ components. -* ... +This is the initial release for this project. From f28f0e68a4e2829df14190e7a029ae562b71bbac Mon Sep 17 00:00:00 2001 From: Nils Wentzell Date: Wed, 14 Aug 2019 10:12:03 -0400 Subject: [PATCH 124/272] [doc] Add cpp2rst and example output generation to doc building --- doc/CMakeLists.txt | 53 ++++++++++++++++++++++++++++++++++------------ 1 file changed, 39 insertions(+), 14 deletions(-) diff --git a/doc/CMakeLists.txt b/doc/CMakeLists.txt index 8e51140a..cb7dacd7 100644 --- a/doc/CMakeLists.txt +++ b/doc/CMakeLists.txt @@ -1,20 +1,6 @@ # Generate the sphinx config file configure_file(${CMAKE_CURRENT_SOURCE_DIR}/conf.py.in ${CMAKE_CURRENT_BINARY_DIR}/conf.py @ONLY) -# --------------------------------- -# Top Sphinx target -# --------------------------------- -# Sphinx has internal caching, always run it -add_custom_target(docs_sphinx ALL) -add_custom_command( - TARGET docs_sphinx - COMMAND PYTHONPATH=${CMAKE_BINARY_DIR}/python:$ENV{PYTHONPATH} ${TRIQS_SPHINXBUILD_EXECUTABLE} -c . -j8 -b html ${CMAKE_CURRENT_SOURCE_DIR} html -) - -# Autodoc usage requires the python modules to be built first -get_property(CPP2PY_MODULES_LIST GLOBAL PROPERTY CPP2PY_MODULES_LIST) -add_dependencies(docs_sphinx ${CPP2PY_MODULES_LIST}) - # ----------------------------------------------------------------------------- # Create an optional target that allows us to regenerate the C++ doc with c++2rst # ----------------------------------------------------------------------------- @@ -51,6 +37,45 @@ endmacro(generate_docs) generate_docs(${PROJECT_SOURCE_DIR}/c++/app4triqs/toto.hpp) +# -------------------------------------------------------- +# Build & Run the C++ doc examples and capture the output +# -------------------------------------------------------- + +add_custom_target(docs_example_output) +file(GLOB_RECURSE ExampleList RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} *.cpp) +foreach(example ${ExampleList}) + get_filename_component(f ${example} NAME_WE) + get_filename_component(d ${example} DIRECTORY) + add_executable(doc_${f} EXCLUDE_FROM_ALL ${example}) + set_property(TARGET doc_${f} PROPERTY RUNTIME_OUTPUT_DIRECTORY ${d}) + target_link_libraries(doc_${f} triqs) + add_custom_command(TARGET doc_${f} + COMMAND doc_${f} > ${CMAKE_CURRENT_SOURCE_DIR}/${d}/${f}.output 2>/dev/null + WORKING_DIRECTORY ${d} + ) + add_dependencies(docs_example_output doc_${f}) +endforeach() + +# --------------------------------- +# Top Sphinx target +# --------------------------------- +# Sphinx has internal caching, always run it +add_custom_target(docs_sphinx ALL) +add_custom_command( + TARGET docs_sphinx + COMMAND PYTHONPATH=${CMAKE_BINARY_DIR}/python:$ENV{PYTHONPATH} ${TRIQS_SPHINXBUILD_EXECUTABLE} -c . -j8 -b html ${CMAKE_CURRENT_SOURCE_DIR} html +) + +option(Sphinx_Only "When building the documentation, skip the Python Modules and the generation of C++ Api and example outputs" OFF) +if(NOT Sphinx_Only) + # Autodoc usage requires the python modules to be built first + get_property(CPP2PY_MODULES_LIST GLOBAL PROPERTY CPP2PY_MODULES_LIST) + add_dependencies(docs_sphinx ${CPP2PY_MODULES_LIST}) + + # Generation of C++ Api and Example Outputs + add_dependencies(docs_sphinx docs_cpp2rst docs_example_output) +endif() + # --------------------------------- # Install # --------------------------------- From 5148de2c29f5171f13993dc3a6185e8373cba986 Mon Sep 17 00:00:00 2001 From: Nils Wentzell Date: Tue, 27 Aug 2019 15:54:56 -0400 Subject: [PATCH 125/272] Disable gcc in travis builds due to ld problem on xenial --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 569b67fd..1c867823 100644 --- a/.travis.yml +++ b/.travis.yml @@ -4,7 +4,7 @@ sudo: required dist: xenial compiler: - - gcc + #- gcc - clang before_install: From 058e39a6c2ed45fc08b658a0645e414ffa53c3f8 Mon Sep 17 00:00:00 2001 From: Dylan Simon Date: Tue, 27 Aug 2019 17:37:02 -0400 Subject: [PATCH 126/272] [jenkins] Put a mutex around packaging repo updates "correct" fix for race failures, though could use separate labeled resources for each repo --- Jenkinsfile | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/Jenkinsfile b/Jenkinsfile index 7a42331f..ec9ed427 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -92,10 +92,11 @@ try { parallel platforms if (keepInstall) { node("docker") { /* Publish results */ - stage("publish") { timeout(time: 1, unit: 'HOURS') { + stage("publish") { timeout(time: 5, unit: 'MINUTES') { def commit = sh(returnStdout: true, script: "git rev-parse HEAD").trim() def release = env.BRANCH_NAME == "master" || env.BRANCH_NAME == "unstable" || sh(returnStdout: true, script: "git describe --exact-match HEAD || true").trim() def workDir = pwd() + lock('triqs_publish') { /* Update documention on gh-pages branch */ dir("$workDir/gh-pages") { def subdir = "${projectName}/${env.BRANCH_NAME}" @@ -109,7 +110,7 @@ try { git commit --author='Flatiron Jenkins ' --allow-empty -m 'Generated documentation for ${subdir}' -m '${env.BUILD_TAG} ${commit}' """ // note: credentials used above don't work (need JENKINS-28335) - sh "git push origin master || { git pull --rebase origin master && git push origin master ; }" + sh "git push origin master" } /* Update packaging repo submodule */ if (release) { dir("$workDir/packaging") { try { @@ -120,12 +121,13 @@ try { [[ -d triqs_\$dir ]] && dir=triqs_\$dir || [[ -d \$dir ]] echo "160000 commit ${commit}\t\$dir" | git update-index --index-info git commit --author='Flatiron Jenkins ' -m 'Autoupdate ${projectName}' -m '${env.BUILD_TAG}' - git push origin ${env.BRANCH_NAME} || { git pull --rebase origin ${env.BRANCH_NAME} && git push origin ${env.BRANCH_NAME} ; } + git push origin ${env.BRANCH_NAME} """ } catch (err) { /* Ignore, non-critical -- might not exist on this branch */ echo "Failed to update packaging repo" } } } + } } } } } } catch (err) { From 36a21ee81906edf6a5716e533f5a96ae66e1e76d Mon Sep 17 00:00:00 2001 From: Nils Wentzell Date: Wed, 28 Aug 2019 11:11:49 -0400 Subject: [PATCH 127/272] [jenkins] Change permissions for application sources in Dockerfile --- Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index c65c6760..d9c870f4 100644 --- a/Dockerfile +++ b/Dockerfile @@ -7,7 +7,7 @@ RUN pip install -r /src/$APPNAME/requirements.txt COPY . $SRC/$APPNAME WORKDIR $BUILD/$APPNAME -RUN chown build . +RUN chown -R build $SRC/$APPNAME . USER build ARG BUILD_DOC=0 RUN cmake $SRC/$APPNAME -DTRIQS_ROOT=${INSTALL} -DBuild_Documentation=${BUILD_DOC} && make -j2 && make test CTEST_OUTPUT_ON_FAILURE=1 From 5cb8bbf0424f90297eec8fe022247f637d445d76 Mon Sep 17 00:00:00 2001 From: Nils Wentzell Date: Wed, 4 Sep 2019 16:17:51 -0400 Subject: [PATCH 128/272] [cmake] Add -Wno-gcc-compat to project_warnings target --- CMakeLists.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index 90b379e4..752397fd 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -82,6 +82,7 @@ target_compile_options(project_warnings -Wshadow -Wpedantic -Wno-sign-compare + $<$:-Wno-gcc-compat> ) # ############# From 445e15d15385bf6094e3b2e6031f34e41ebf670e Mon Sep 17 00:00:00 2001 From: Nils Wentzell Date: Wed, 4 Sep 2019 17:30:07 -0400 Subject: [PATCH 129/272] [app4triqs] Improved README --- README.md | 42 +++++++++++++++++++++++++++++++++--------- 1 file changed, 33 insertions(+), 9 deletions(-) diff --git a/README.md b/README.md index aa2019a6..469806b5 100644 --- a/README.md +++ b/README.md @@ -1,9 +1,9 @@ [![Build Status](https://travis-ci.org/TRIQS/app4triqs.svg?branch=unstable)](https://travis-ci.org/TRIQS/app4triqs) -# app4triqs +# app4triqs - A skeleton for a TRIQS application -A skeleton for a TRIQS application ----------------------------------- +Initial Setup +------------- **Caution**: The following instructions require the `util-linux` rename command. Please confirm that you have the right version by running `rename --version`. @@ -39,8 +39,7 @@ You can now push to your github repository git push origin unstable ``` -Perl rename command -------------------- +### Perl rename command ### If you are using the Perl-based rename command you will need to @@ -49,8 +48,7 @@ find . -type d | grep -v .git | xargs rename 's/app4triqs/${app_name}/' find . -type f | grep -v .git | xargs rename 's/app4triqs/${app_name}/' ``` -Github SSH interface --------------------- +### Github SSH interface ### If you prefer to use the SSH interface to the remote repository, replace the http link accordingly @@ -59,8 +57,7 @@ replace the http link accordingly https://github.com/myuser/mynewapp --> git@github.com:myuser/mynewapp ``` -Merging app4triqs skeleton updates ----------------------------------- +### Merging app4triqs skeleton updates ### You can merge future changes to app4triqs into your project with the following commands @@ -70,3 +67,30 @@ git merge app4triqs_remote -m "Merge latest app4triqs skeleton changes" ``` If you should encounter any conflicts resolve them and `git commit`. + +Getting Started +--------------- + +After setting up your application as described above you should customize the following files and directories +according to your needs (replace app4triqs in the following by the name of your application) + +* In the `c++/app4triqs` subdirectory adjust the example files `app4triqs.hpp` and `app4triqs.cpp` or add your own source files. +* In the `test/c++` subdirectory adjust the example test `basic.cpp` or add your own tests. +* In the `python/app4triqs` subdirectory add your Python source files. + Be sure to remove the `app4triqs_module_desc.py` file unless you want to generate a Python module from your C++ source code. +* In the `test/c++` subdirectory adjust the example test `basic.cpp` or add your own tests. +* The build and install process is identical to the one outline [here](https://triqs.github.io/app4triqs/unstable/install.html). + +### Optional ### +---------------- +* If you want to wrap C++ classes and/or functions provided in the `c++/app4triqs/app4triqs.hpp` rerun the `c++2py` tool with +```bash +c++2py -r app4triqs_module_desc.py +``` +* Add your email address to the bottom section of `Jenkinsfile` for Jenkins CI notification emails +``` +End of build log: +\${BUILD_LOG,maxLines=60} + """, + to: 'user@domain.org', +``` From 28d600f149ff1c8e82367026a1180a03f03b6844 Mon Sep 17 00:00:00 2001 From: Nils Wentzell Date: Wed, 4 Sep 2019 17:34:00 -0400 Subject: [PATCH 130/272] [app4triqs] Rename files and Python module from toto to app4triqs -Automatically detect any wrap generator files -rename tests to basic/Py_Basic --- c++/app4triqs/{toto.cpp => app4triqs.cpp} | 2 +- c++/app4triqs/{toto.hpp => app4triqs.hpp} | 22 +------------------ doc/CMakeLists.txt | 2 +- doc/contents.rst | 1 - doc/documentation.rst | 5 ++--- python/app4triqs/CMakeLists.txt | 13 ++++++----- python/app4triqs/__init__.py | 2 +- ...odule_desc.py => app4triqs_module_desc.py} | 11 ++++------ test/c++/{toto.cpp => basic.cpp} | 2 +- test/python/{Toto.py => Basic.py} | 10 ++++++++- test/python/CMakeLists.txt | 6 ++--- test/python/chain.py | 17 -------------- 12 files changed, 31 insertions(+), 62 deletions(-) rename c++/app4triqs/{toto.cpp => app4triqs.cpp} (97%) rename c++/app4triqs/{toto.hpp => app4triqs.hpp} (81%) rename python/app4triqs/{toto_module_desc.py => app4triqs_module_desc.py} (78%) rename test/c++/{toto.cpp => basic.cpp} (92%) rename test/python/{Toto.py => Basic.py} (78%) delete mode 100644 test/python/chain.py diff --git a/c++/app4triqs/toto.cpp b/c++/app4triqs/app4triqs.cpp similarity index 97% rename from c++/app4triqs/toto.cpp rename to c++/app4triqs/app4triqs.cpp index 6186f754..4e9ab6ab 100644 --- a/c++/app4triqs/toto.cpp +++ b/c++/app4triqs/app4triqs.cpp @@ -1,5 +1,5 @@ #include -#include "./toto.hpp" +#include "./app4triqs.hpp" namespace app4triqs { diff --git a/c++/app4triqs/toto.hpp b/c++/app4triqs/app4triqs.hpp similarity index 81% rename from c++/app4triqs/toto.hpp rename to c++/app4triqs/app4triqs.hpp index 92353c44..88f7550d 100644 --- a/c++/app4triqs/toto.hpp +++ b/c++/app4triqs/app4triqs.hpp @@ -7,6 +7,7 @@ namespace app4triqs { * A very useful and important class * * @note A Useful note + * @include app4triqs/app4triqs.hpp */ class toto { @@ -73,26 +74,5 @@ namespace app4triqs { * @remark */ int chain(int i, int j); - - /** - * Chain digits of three integers - * - * @param i The first integer - * @param j The second integer - * @param k The third integer - * @return An integer containing the digits of both i and j - * - * @remark - */ - int chain(int i, int j, int k); - - /** - * Chain digits of one integers - * - * @param i The first integer - * - * @remark - */ - int chain(int i); } // namespace app4triqs diff --git a/doc/CMakeLists.txt b/doc/CMakeLists.txt index cb7dacd7..0d26b4a9 100644 --- a/doc/CMakeLists.txt +++ b/doc/CMakeLists.txt @@ -35,7 +35,7 @@ macro(generate_docs header_file) ) endmacro(generate_docs) -generate_docs(${PROJECT_SOURCE_DIR}/c++/app4triqs/toto.hpp) +generate_docs(${PROJECT_SOURCE_DIR}/c++/app4triqs/app4triqs.hpp) # -------------------------------------------------------- # Build & Run the C++ doc examples and capture the output diff --git a/doc/contents.rst b/doc/contents.rst index 725589f8..4f990b6a 100644 --- a/doc/contents.rst +++ b/doc/contents.rst @@ -10,4 +10,3 @@ Table of contents issues changelog about - diff --git a/doc/documentation.rst b/doc/documentation.rst index 4f59764e..3a01e533 100644 --- a/doc/documentation.rst +++ b/doc/documentation.rst @@ -36,8 +36,7 @@ Python reference manual .. automodule:: app4triqs :members: -.. autoclass:: app4triqs.toto_module.Toto +.. autoclass:: app4triqs.app4triqs_module.Toto :members: -.. autofunction:: app4triqs.toto_module.chain - +.. autofunction:: app4triqs.app4triqs_module.chain diff --git a/python/app4triqs/CMakeLists.txt b/python/app4triqs/CMakeLists.txt index 6ec57050..7b8b47dd 100644 --- a/python/app4triqs/CMakeLists.txt +++ b/python/app4triqs/CMakeLists.txt @@ -1,7 +1,3 @@ -# Build the python module -add_cpp2py_module(toto_module) -target_link_libraries(toto_module app4triqs_c) - # Configure the version configure_file(version.py.in version.py) @@ -13,7 +9,14 @@ foreach(file ${python_sources}) configure_file(${file} ${file} COPYONLY) endforeach() -# Install python module to proper location +# Build any python modules +foreach(gen ${wrap_generators}) + string(REPLACE "_desc.py" "" module_name ${gen}) + add_cpp2py_module(${module_name}) + target_link_libraries(${module_name} app4triqs_c) +endforeach() + +# Install python modules to proper location set(PYTHON_LIB_DEST ${TRIQS_PYTHON_LIB_DEST_ROOT}/app4triqs) get_property(CPP2PY_MODULES_LIST GLOBAL PROPERTY CPP2PY_MODULES_LIST) install(TARGETS ${CPP2PY_MODULES_LIST} DESTINATION ${PYTHON_LIB_DEST}) diff --git a/python/app4triqs/__init__.py b/python/app4triqs/__init__.py index 591133ee..2fabf532 100644 --- a/python/app4triqs/__init__.py +++ b/python/app4triqs/__init__.py @@ -25,6 +25,6 @@ r""" DOC """ -from toto_module import Toto, chain +from app4triqs_module import Toto, chain __all__ = ['Toto', 'chain'] diff --git a/python/app4triqs/toto_module_desc.py b/python/app4triqs/app4triqs_module_desc.py similarity index 78% rename from python/app4triqs/toto_module_desc.py rename to python/app4triqs/app4triqs_module_desc.py index e7eea446..74872947 100644 --- a/python/app4triqs/toto_module_desc.py +++ b/python/app4triqs/app4triqs_module_desc.py @@ -1,15 +1,14 @@ # Generated automatically using the command : -# c++2py ../../c++/app4triqs/toto.hpp -p --members_read_only -N app4triqs -a app4triqs -m toto_module -o toto_module -C pytriqs --cxxflags="-std=c++17 " +# c++2py ../../c++/app4triqs/app4triqs.hpp -p --members_read_only -N app4triqs -a app4triqs -m app4triqs_module -o app4triqs_module -C pytriqs --cxxflags="-std=c++17 " from cpp2py.wrap_generator import * # The module -module = module_(full_name = "toto_module", doc = "", app_name = "app4triqs") +module = module_(full_name = "app4triqs_module", doc = r"", app_name = "app4triqs") # Imports -module.add_imports(*[]) # Add here all includes -module.add_include("app4triqs/toto.hpp") +module.add_include("app4triqs/app4triqs.hpp") # Add here anything to add in the C++ code at the start, e.g. namespace using module.add_preamble(""" @@ -54,14 +53,12 @@ c.add_method("""std::string hdf5_scheme ()""", c.add_property(name = "i", getter = cfunction("int get_i ()"), - doc = """Simple accessor""") + doc = r"""Simple accessor""") module.add_class(c) module.add_function ("int app4triqs::chain (int i, int j)", doc = r"""Chain digits of two integers - Chain the decimal digits of two integers i and j, and return the result - Parameters ---------- i diff --git a/test/c++/toto.cpp b/test/c++/basic.cpp similarity index 92% rename from test/c++/toto.cpp rename to test/c++/basic.cpp index a94b4946..f8866fa7 100644 --- a/test/c++/toto.cpp +++ b/test/c++/basic.cpp @@ -1,5 +1,5 @@ #include -#include +#include using namespace app4triqs; diff --git a/test/python/Toto.py b/test/python/Basic.py similarity index 78% rename from test/python/Toto.py rename to test/python/Basic.py index 744235f9..9576522d 100644 --- a/test/python/Toto.py +++ b/test/python/Basic.py @@ -2,7 +2,7 @@ import unittest -from app4triqs import Toto +from app4triqs import Toto, chain from pytriqs.archive import * from pytriqs.utility import mpi @@ -37,6 +37,14 @@ class test_toto(unittest.TestCase): self.assertEqual(a, Toto(1)) +class test_chain(unittest.TestCase): + + def test_chain(self): + + i = 111 + j = 222 + ij = chain(i,j) + self.assertEqual(ij, 111222) if __name__ == '__main__': unittest.main() diff --git a/test/python/CMakeLists.txt b/test/python/CMakeLists.txt index e4a2c0c6..da8f6dcb 100644 --- a/test/python/CMakeLists.txt +++ b/test/python/CMakeLists.txt @@ -5,11 +5,11 @@ foreach(file ${all_h5_ref_files}) endforeach() # List of all tests -set(all_tests Toto chain) +set(all_tests Basic) foreach(test ${all_tests}) get_filename_component(test_name ${test} NAME_WE) get_filename_component(test_dir ${test} DIRECTORY) - add_test(NAME ${test_name} COMMAND ${TRIQS_PYTHON_INTERPRETER} ${CMAKE_CURRENT_SOURCE_DIR}/${test_dir}/${test_name}.py WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/${test_dir}) - set_property(TEST ${test_name} APPEND PROPERTY ENVIRONMENT PYTHONPATH=${CMAKE_BINARY_DIR}/python:$ENV{PYTHONPATH} ${SANITIZER_RT_PRELOAD}) + add_test(NAME Py_${test_name} COMMAND ${TRIQS_PYTHON_INTERPRETER} ${CMAKE_CURRENT_SOURCE_DIR}/${test_dir}/${test_name}.py WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/${test_dir}) + set_property(TEST Py_${test_name} APPEND PROPERTY ENVIRONMENT PYTHONPATH=${CMAKE_BINARY_DIR}/python:$ENV{PYTHONPATH} ${SANITIZER_RT_PRELOAD}) endforeach() diff --git a/test/python/chain.py b/test/python/chain.py deleted file mode 100644 index e0dcfc8e..00000000 --- a/test/python/chain.py +++ /dev/null @@ -1,17 +0,0 @@ -#!/usr/bin/env python - -import unittest - -from app4triqs import chain - -class test_chain(unittest.TestCase): - - def test_chain(self): - - i = 111 - j = 222 - ij = chain(i,j) - self.assertEqual(ij, 111222) - -if __name__ == '__main__': - unittest.main() From bdf91fa925d51a02a66dfb31a54272a8629bbcf3 Mon Sep 17 00:00:00 2001 From: Nils Wentzell Date: Wed, 4 Sep 2019 17:35:41 -0400 Subject: [PATCH 131/272] [app4triqs] Include cpp2rst_generated/contents in toctree --- doc/documentation.rst | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/doc/documentation.rst b/doc/documentation.rst index 3a01e533..e4408d16 100644 --- a/doc/documentation.rst +++ b/doc/documentation.rst @@ -27,8 +27,7 @@ C++ reference manual .. toctree:: :maxdepth: 5 - cpp2rst_generated/app4triqs/toto - cpp2rst_generated/app4triqs/chain + cpp2rst_generated/contents Python reference manual ----------------------- From a69a449a430349722fc4531a5c736069189eadb0 Mon Sep 17 00:00:00 2001 From: Nils Wentzell Date: Thu, 5 Sep 2019 15:08:10 -0400 Subject: [PATCH 132/272] Move setup files into separate bash scripts and adjust README * Treat Linux and Darwin differently --- README.md | 65 +++++++++++++------------------------ share/replace_and_rename.sh | 29 +++++++++++++++++ share/squash_history.sh | 6 ++++ 3 files changed, 58 insertions(+), 42 deletions(-) create mode 100755 share/replace_and_rename.sh create mode 100755 share/squash_history.sh diff --git a/README.md b/README.md index 469806b5..444a59b1 100644 --- a/README.md +++ b/README.md @@ -5,68 +5,47 @@ Initial Setup ------------- -**Caution**: The following instructions require the `util-linux` rename command. -Please confirm that you have the right version by running `rename --version`. -For the Perl rename command see instructions in the following section. - To adapt this skeleton for a new TRIQS application, the following steps are necessary: -* Create a repository, e.g. https://github.com/myuser/mynewapp +* Create a repository, e.g. https://github.com/username/appname -* Run the following commands in order after replacing myuser, mynewapp and MYNEWAPP accordingly +* Run the following commands in order after replacing **appname** accordingly ```bash -github_username=myuser -app_name=mynewapp -capital_name=MYNEWAPP - -git clone https://github.com/triqs/app4triqs --branch unstable ${app_name} -cd ${app_name} -git reset $(git commit-tree HEAD\^{tree} -m "Create ${app_name} from github.com/triqs/app4triqs skeleton") -git merge --allow-unrelated-histories -s ours HEAD@{1} -m "Track app4triqs skeleton" -find . -type f | grep -v .git | xargs sed -i 's/app4triqs/${app_name}/g; s/APP4TRIQS/${capital_name}/g' -find . -type d | grep -v .git | xargs rename app4triqs ${app_name} -find . -type f | grep -v .git | xargs rename app4triqs ${app_name} -git add -A && git commit -m "Adjust app4triqs skeleton for ${app_name}" -git remote set-url origin https://github.com/${github_username}/${app_name} -git remote add app4triqs_remote https://github.com/triqs/app4triqs -git remote update && git remote prune origin +git clone https://github.com/triqs/app4triqs --branch unstable appname +cd appname +./share/squash_history.sh +./share/replace_and_rename.sh appname +git add -A && git commit -m "Adjust app4triqs skeleton for appname" ``` -You can now push to your github repository +You can now add your github repository and push to it ```bash +git remote add origin https://github.com/username/appname +git remote update git push origin unstable ``` -### Perl rename command ### - -If you are using the Perl-based rename command you will need to - -```bash -find . -type d | grep -v .git | xargs rename 's/app4triqs/${app_name}/' -find . -type f | grep -v .git | xargs rename 's/app4triqs/${app_name}/' -``` - -### Github SSH interface ### - -If you prefer to use the SSH interface to the remote repository, -replace the http link accordingly - -``` -https://github.com/myuser/mynewapp --> git@github.com:myuser/mynewapp -``` +If you prefer to use the [SSH interface](https://help.github.com/en/articles/connecting-to-github-with-ssh) +to the remote repository, replace the http link with e.g. `git@github.com:username/appname`. ### Merging app4triqs skeleton updates ### -You can merge future changes to app4triqs into your project with the following commands +You can merge future changes to the app4triqs skeleton into your project with the following commands ```bash git remote update -git merge app4triqs_remote -m "Merge latest app4triqs skeleton changes" +git merge app4triqs_remote/unstable -m "Merge latest app4triqs skeleton changes" ``` If you should encounter any conflicts resolve them and `git commit`. +Finally we repeat the replace and rename command from the initial setup. + +```bash +./share/replace_and_rename.sh appname +git commit --amend +``` Getting Started --------------- @@ -74,15 +53,17 @@ Getting Started After setting up your application as described above you should customize the following files and directories according to your needs (replace app4triqs in the following by the name of your application) +* Adjust or remove the `README.md` and `doc/ChangeLog.md` file * In the `c++/app4triqs` subdirectory adjust the example files `app4triqs.hpp` and `app4triqs.cpp` or add your own source files. * In the `test/c++` subdirectory adjust the example test `basic.cpp` or add your own tests. * In the `python/app4triqs` subdirectory add your Python source files. Be sure to remove the `app4triqs_module_desc.py` file unless you want to generate a Python module from your C++ source code. -* In the `test/c++` subdirectory adjust the example test `basic.cpp` or add your own tests. +* In the `test/python` subdirectory adjust the example test `Basic.py` or add your own tests. * The build and install process is identical to the one outline [here](https://triqs.github.io/app4triqs/unstable/install.html). ### Optional ### ---------------- + * If you want to wrap C++ classes and/or functions provided in the `c++/app4triqs/app4triqs.hpp` rerun the `c++2py` tool with ```bash c++2py -r app4triqs_module_desc.py diff --git a/share/replace_and_rename.sh b/share/replace_and_rename.sh new file mode 100755 index 00000000..8ae0bab5 --- /dev/null +++ b/share/replace_and_rename.sh @@ -0,0 +1,29 @@ +#!/usr/bin/env bash + +if [ $# -ne 1 ]; then + echo "Please pass the application name" + exit 1 +fi +app_name=$1 +capital_name=$(printf '%s' "$1" | awk '{ print toupper($0) }') + +# Move app4triqs directories if necessary +[ -d c++/app4triqs ] && mv c++/app4triqs c++/${app_name} +[ -d python/app4triqs ] && mv python/app4triqs python/${app_name} + +# Replace app4triqs and APP4TRIQS for our application in all files and filenames +if [ $(uname -s) == Linux ]; then + find . -type f \ + -not -path "./.git/*" \ + -not -path "*/replace_and_rename.sh" \ + -not -path "*/squash_history.sh" \ + -exec sed -i "s/app4triqs/${app_name}/g; s/APP4TRIQS/${capital_name}/g" {} \; + find . -type f -not -path "./.git/*" -exec rename app4triqs ${app_name} {} &> /dev/null \; +elif [ $(uname -s) == Darwin ]; then + LC_CTYPE=C LANG=C find . -type f \ + -not -path "./.git/*" \ + -not -path "*/replace_and_rename.sh" \ + -not -path "*/squash_history.sh" \ + -exec sed -i '' -e "s/app4triqs/${app_name}/g; s/APP4TRIQS/${capital_name}/g" {} \; + find . -type f -not -path "./.git/*" -exec rename "s/app4triqs/${app_name}/" {} &> /dev/null \; +fi diff --git a/share/squash_history.sh b/share/squash_history.sh new file mode 100755 index 00000000..8c03c08f --- /dev/null +++ b/share/squash_history.sh @@ -0,0 +1,6 @@ +#!/usr/bin/env bash + +git reset $(git commit-tree HEAD\^{tree} -m "Initialize project from github.com/triqs/app4triqs@$(git rev-parse --short HEAD)") +git merge --allow-unrelated-histories -s ours HEAD@{1} -m "Track app4triqs skeleton" +git remote rm origin +git remote add app4triqs_remote https://github.com/triqs/app4triqs From 7ab1e6af221bc0d11fc39d6bcbe8682d361e9b03 Mon Sep 17 00:00:00 2001 From: Nils Wentzell Date: Fri, 6 Sep 2019 15:27:55 -0400 Subject: [PATCH 133/272] Add C to Project Languages --- CMakeLists.txt | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 752397fd..087ea427 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -26,8 +26,7 @@ endif() # ############ # Define Project - -project(APP4TRIQS VERSION 2.2.0 LANGUAGES CXX) +project(APP4TRIQS VERSION 2.2.0 LANGUAGES C CXX) # ############ # Load TRIQS and CPP2PY From f5b936317d4d3a1382474b5363027c243868aaf2 Mon Sep 17 00:00:00 2001 From: Nils Wentzell Date: Fri, 6 Sep 2019 16:12:03 -0400 Subject: [PATCH 134/272] Squashed 'test/c++/gtest/' content from commit 3f05f651 git-subtree-dir: test/c++/gtest git-subtree-split: 3f05f651ae3621db58468153e32016bc1397800b --- .clang-format | 4 + .gitignore | 84 + .travis.yml | 73 + BUILD.bazel | 179 + CMakeLists.txt | 36 + CONTRIBUTING.md | 142 + LICENSE | 28 + README.md | 134 + WORKSPACE | 23 + appveyor.yml | 154 + ci/build-linux-bazel.sh | 37 + ci/build-platformio.sh | 2 + ci/env-linux.sh | 41 + ci/env-osx.sh | 47 + ci/get-nprocessors.sh | 48 + ci/install-linux.sh | 49 + ci/install-osx.sh | 40 + ci/install-platformio.sh | 5 + ci/log-config.sh | 51 + ci/travis.sh | 44 + googlemock/CMakeLists.txt | 233 + googlemock/CONTRIBUTORS | 40 + googlemock/LICENSE | 28 + googlemock/README.md | 44 + googlemock/cmake/gmock.pc.in | 11 + googlemock/cmake/gmock_main.pc.in | 11 + googlemock/docs/cheat_sheet.md | 770 ++ googlemock/docs/cook_book.md | 4269 ++++++++++ googlemock/docs/for_dummies.md | 700 ++ googlemock/docs/gmock_faq.md | 396 + googlemock/include/gmock/gmock-actions.h | 1141 +++ .../include/gmock/gmock-cardinalities.h | 153 + .../include/gmock/gmock-function-mocker.h | 253 + .../include/gmock/gmock-generated-actions.h | 1884 +++++ .../gmock/gmock-generated-actions.h.pump | 627 ++ .../gmock/gmock-generated-function-mockers.h | 752 ++ .../gmock-generated-function-mockers.h.pump | 227 + .../include/gmock/gmock-generated-matchers.h | 1097 +++ .../gmock/gmock-generated-matchers.h.pump | 346 + googlemock/include/gmock/gmock-matchers.h | 4566 ++++++++++ googlemock/include/gmock/gmock-more-actions.h | 162 + .../include/gmock/gmock-more-matchers.h | 92 + googlemock/include/gmock/gmock-nice-strict.h | 215 + .../include/gmock/gmock-spec-builders.h | 1982 +++++ googlemock/include/gmock/gmock.h | 101 + .../include/gmock/internal/custom/README.md | 16 + .../internal/custom/gmock-generated-actions.h | 10 + .../custom/gmock-generated-actions.h.pump | 12 + .../gmock/internal/custom/gmock-matchers.h | 36 + .../gmock/internal/custom/gmock-port.h | 39 + .../gmock/internal/gmock-internal-utils.h | 514 ++ .../include/gmock/internal/gmock-port.h | 87 + googlemock/include/gmock/internal/gmock-pp.h | 317 + googlemock/scripts/fuse_gmock_files.py | 240 + googlemock/scripts/generator/LICENSE | 203 + googlemock/scripts/generator/README | 34 + googlemock/scripts/generator/README.cppclean | 115 + googlemock/scripts/generator/cpp/__init__.py | 0 googlemock/scripts/generator/cpp/ast.py | 1736 ++++ .../scripts/generator/cpp/gmock_class.py | 227 + .../scripts/generator/cpp/gmock_class_test.py | 466 + googlemock/scripts/generator/cpp/keywords.py | 59 + googlemock/scripts/generator/cpp/tokenize.py | 287 + googlemock/scripts/generator/cpp/utils.py | 41 + googlemock/scripts/generator/gmock_gen.py | 31 + googlemock/scripts/gmock-config.in | 303 + googlemock/scripts/gmock_doctor.py | 640 ++ googlemock/scripts/upload.py | 1387 +++ googlemock/scripts/upload_gmock.py | 78 + googlemock/src/gmock-all.cc | 46 + googlemock/src/gmock-cardinalities.cc | 155 + googlemock/src/gmock-internal-utils.cc | 200 + googlemock/src/gmock-matchers.cc | 462 + googlemock/src/gmock-spec-builders.cc | 887 ++ googlemock/src/gmock.cc | 213 + googlemock/src/gmock_main.cc | 65 + googlemock/test/BUILD.bazel | 110 + googlemock/test/gmock-actions_test.cc | 1445 ++++ googlemock/test/gmock-cardinalities_test.cc | 427 + googlemock/test/gmock-function-mocker_nc.cc | 16 + .../test/gmock-function-mocker_nc_test.py | 43 + googlemock/test/gmock-function-mocker_test.cc | 660 ++ .../test/gmock-generated-actions_test.cc | 1064 +++ .../gmock-generated-function-mockers_test.cc | 659 ++ .../test/gmock-generated-matchers_test.cc | 1324 +++ googlemock/test/gmock-internal-utils_test.cc | 728 ++ googlemock/test/gmock-matchers_test.cc | 6792 +++++++++++++++ googlemock/test/gmock-more-actions_test.cc | 699 ++ googlemock/test/gmock-nice-strict_test.cc | 500 ++ googlemock/test/gmock-port_test.cc | 42 + googlemock/test/gmock-pp-string_test.cc | 206 + googlemock/test/gmock-pp_test.cc | 73 + googlemock/test/gmock-spec-builders_test.cc | 2773 ++++++ googlemock/test/gmock_all_test.cc | 49 + googlemock/test/gmock_ex_test.cc | 80 + googlemock/test/gmock_leak_test.py | 104 + googlemock/test/gmock_leak_test_.cc | 99 + googlemock/test/gmock_link2_test.cc | 39 + googlemock/test/gmock_link_test.cc | 39 + googlemock/test/gmock_link_test.h | 690 ++ googlemock/test/gmock_output_test.py | 183 + googlemock/test/gmock_output_test_.cc | 309 + googlemock/test/gmock_output_test_golden.txt | 317 + googlemock/test/gmock_stress_test.cc | 240 + googlemock/test/gmock_test.cc | 181 + googlemock/test/gmock_test_utils.py | 108 + googletest/CMakeLists.txt | 328 + googletest/CONTRIBUTORS | 37 + googletest/LICENSE | 28 + googletest/README.md | 244 + googletest/cmake/Config.cmake.in | 9 + googletest/cmake/gtest.pc.in | 10 + googletest/cmake/gtest_main.pc.in | 11 + googletest/cmake/internal_utils.cmake | 358 + googletest/cmake/libgtest.la.in | 21 + googletest/docs/advanced.md | 2566 ++++++ googletest/docs/faq.md | 753 ++ googletest/docs/pkgconfig.md | 141 + googletest/docs/primer.md | 568 ++ googletest/docs/pump_manual.md | 190 + googletest/docs/samples.md | 22 + googletest/include/gtest/gtest-death-test.h | 343 + googletest/include/gtest/gtest-matchers.h | 750 ++ googletest/include/gtest/gtest-message.h | 218 + googletest/include/gtest/gtest-param-test.h | 503 ++ googletest/include/gtest/gtest-printers.h | 928 ++ googletest/include/gtest/gtest-spi.h | 238 + googletest/include/gtest/gtest-test-part.h | 184 + googletest/include/gtest/gtest-typed-test.h | 330 + googletest/include/gtest/gtest.h | 2477 ++++++ googletest/include/gtest/gtest_pred_impl.h | 359 + googletest/include/gtest/gtest_prod.h | 61 + .../include/gtest/internal/custom/README.md | 56 + .../gtest/internal/custom/gtest-port.h | 37 + .../gtest/internal/custom/gtest-printers.h | 42 + .../include/gtest/internal/custom/gtest.h | 37 + .../internal/gtest-death-test-internal.h | 304 + .../include/gtest/internal/gtest-filepath.h | 211 + .../include/gtest/internal/gtest-internal.h | 1386 +++ .../include/gtest/internal/gtest-param-util.h | 883 ++ .../include/gtest/internal/gtest-port-arch.h | 107 + .../include/gtest/internal/gtest-port.h | 2237 +++++ .../include/gtest/internal/gtest-string.h | 170 + .../include/gtest/internal/gtest-type-util.h | 3335 ++++++++ .../gtest/internal/gtest-type-util.h.pump | 302 + googletest/samples/prime_tables.h | 126 + googletest/samples/sample1.cc | 66 + googletest/samples/sample1.h | 41 + googletest/samples/sample10_unittest.cc | 139 + googletest/samples/sample1_unittest.cc | 151 + googletest/samples/sample2.cc | 54 + googletest/samples/sample2.h | 81 + googletest/samples/sample2_unittest.cc | 107 + googletest/samples/sample3-inl.h | 172 + googletest/samples/sample3_unittest.cc | 149 + googletest/samples/sample4.cc | 54 + googletest/samples/sample4.h | 53 + googletest/samples/sample4_unittest.cc | 53 + googletest/samples/sample5_unittest.cc | 196 + googletest/samples/sample6_unittest.cc | 224 + googletest/samples/sample7_unittest.cc | 117 + googletest/samples/sample8_unittest.cc | 154 + googletest/samples/sample9_unittest.cc | 156 + googletest/scripts/common.py | 83 + googletest/scripts/fuse_gtest_files.py | 253 + googletest/scripts/gen_gtest_pred_impl.py | 730 ++ googletest/scripts/gtest-config.in | 274 + googletest/scripts/pump.py | 855 ++ googletest/scripts/release_docs.py | 158 + googletest/scripts/test/Makefile | 59 + googletest/scripts/upload.py | 1387 +++ googletest/scripts/upload_gtest.py | 78 + googletest/src/gtest-all.cc | 48 + googletest/src/gtest-death-test.cc | 1653 ++++ googletest/src/gtest-filepath.cc | 379 + googletest/src/gtest-internal-inl.h | 1210 +++ googletest/src/gtest-matchers.cc | 97 + googletest/src/gtest-port.cc | 1402 +++ googletest/src/gtest-printers.cc | 442 + googletest/src/gtest-test-part.cc | 104 + googletest/src/gtest-typed-test.cc | 118 + googletest/src/gtest.cc | 6181 ++++++++++++++ googletest/src/gtest_main.cc | 47 + googletest/test/BUILD.bazel | 521 ++ .../googletest-break-on-failure-unittest.py | 208 + .../googletest-break-on-failure-unittest_.cc | 86 + .../test/googletest-catch-exceptions-test.py | 236 + .../test/googletest-catch-exceptions-test_.cc | 293 + googletest/test/googletest-color-test.py | 127 + googletest/test/googletest-color-test_.cc | 62 + googletest/test/googletest-death-test-test.cc | 1516 ++++ .../test/googletest-death-test_ex_test.cc | 92 + googletest/test/googletest-env-var-test.py | 117 + googletest/test/googletest-env-var-test_.cc | 122 + googletest/test/googletest-filepath-test.cc | 649 ++ googletest/test/googletest-filter-unittest.py | 639 ++ .../test/googletest-filter-unittest_.cc | 137 + .../test/googletest-json-outfiles-test.py | 191 + .../test/googletest-json-output-unittest.py | 778 ++ .../test/googletest-list-tests-unittest.py | 205 + .../test/googletest-list-tests-unittest_.cc | 156 + googletest/test/googletest-listener-test.cc | 518 ++ googletest/test/googletest-message-test.cc | 158 + googletest/test/googletest-options-test.cc | 216 + .../googletest-output-test-golden-lin.txt | 1140 +++ googletest/test/googletest-output-test.py | 346 + googletest/test/googletest-output-test_.cc | 1157 +++ ...oogletest-param-test-invalid-name1-test.py | 63 + ...ogletest-param-test-invalid-name1-test_.cc | 50 + ...oogletest-param-test-invalid-name2-test.py | 62 + ...ogletest-param-test-invalid-name2-test_.cc | 55 + googletest/test/googletest-param-test-test.cc | 1055 +++ googletest/test/googletest-param-test-test.h | 51 + .../test/googletest-param-test2-test.cc | 61 + googletest/test/googletest-port-test.cc | 1272 +++ googletest/test/googletest-printers-test.cc | 1620 ++++ googletest/test/googletest-shuffle-test.py | 323 + googletest/test/googletest-shuffle-test_.cc | 101 + googletest/test/googletest-test-part-test.cc | 230 + googletest/test/googletest-test2_test.cc | 61 + .../test/googletest-throw-on-failure-test.py | 168 + .../test/googletest-throw-on-failure-test_.cc | 71 + .../test/googletest-uninitialized-test.py | 67 + .../test/googletest-uninitialized-test_.cc | 42 + googletest/test/gtest-typed-test2_test.cc | 44 + googletest/test/gtest-typed-test_test.cc | 462 + googletest/test/gtest-typed-test_test.h | 65 + googletest/test/gtest-unittest-api_test.cc | 340 + googletest/test/gtest_all_test.cc | 46 + .../test/gtest_assert_by_exception_test.cc | 116 + googletest/test/gtest_environment_test.cc | 188 + googletest/test/gtest_help_test.py | 170 + googletest/test/gtest_help_test_.cc | 45 + googletest/test/gtest_json_test_utils.py | 60 + googletest/test/gtest_list_output_unittest.py | 141 + .../test/gtest_list_output_unittest_.cc | 51 + googletest/test/gtest_main_unittest.cc | 44 + googletest/test/gtest_no_test_unittest.cc | 54 + googletest/test/gtest_pred_impl_unittest.cc | 2427 ++++++ googletest/test/gtest_premature_exit_test.cc | 126 + googletest/test/gtest_prod_test.cc | 56 + googletest/test/gtest_repeat_test.cc | 233 + ...test_skip_environment_check_output_test.py | 54 + .../gtest_skip_in_environment_setup_test.cc | 49 + googletest/test/gtest_skip_test.cc | 55 + googletest/test/gtest_sole_header_test.cc | 56 + googletest/test/gtest_stress_test.cc | 248 + .../gtest_test_macro_stack_footprint_test.cc | 89 + googletest/test/gtest_test_utils.py | 313 + googletest/test/gtest_testbridge_test.py | 63 + googletest/test/gtest_testbridge_test_.cc | 43 + .../test/gtest_throw_on_failure_ex_test.cc | 90 + googletest/test/gtest_unittest.cc | 7494 +++++++++++++++++ googletest/test/gtest_xml_outfile1_test_.cc | 43 + googletest/test/gtest_xml_outfile2_test_.cc | 43 + googletest/test/gtest_xml_outfiles_test.py | 135 + googletest/test/gtest_xml_output_unittest.py | 389 + googletest/test/gtest_xml_output_unittest_.cc | 188 + googletest/test/gtest_xml_test_utils.py | 196 + googletest/test/production.cc | 35 + googletest/test/production.h | 54 + library.json | 59 + platformio.ini | 31 + 263 files changed, 118078 insertions(+) create mode 100644 .clang-format create mode 100644 .gitignore create mode 100644 .travis.yml create mode 100644 BUILD.bazel create mode 100644 CMakeLists.txt create mode 100644 CONTRIBUTING.md create mode 100644 LICENSE create mode 100644 README.md create mode 100644 WORKSPACE create mode 100644 appveyor.yml create mode 100755 ci/build-linux-bazel.sh create mode 100644 ci/build-platformio.sh create mode 100755 ci/env-linux.sh create mode 100755 ci/env-osx.sh create mode 100755 ci/get-nprocessors.sh create mode 100755 ci/install-linux.sh create mode 100755 ci/install-osx.sh create mode 100644 ci/install-platformio.sh create mode 100755 ci/log-config.sh create mode 100755 ci/travis.sh create mode 100644 googlemock/CMakeLists.txt create mode 100644 googlemock/CONTRIBUTORS create mode 100644 googlemock/LICENSE create mode 100644 googlemock/README.md create mode 100644 googlemock/cmake/gmock.pc.in create mode 100644 googlemock/cmake/gmock_main.pc.in create mode 100644 googlemock/docs/cheat_sheet.md create mode 100644 googlemock/docs/cook_book.md create mode 100644 googlemock/docs/for_dummies.md create mode 100644 googlemock/docs/gmock_faq.md create mode 100644 googlemock/include/gmock/gmock-actions.h create mode 100644 googlemock/include/gmock/gmock-cardinalities.h create mode 100644 googlemock/include/gmock/gmock-function-mocker.h create mode 100644 googlemock/include/gmock/gmock-generated-actions.h create mode 100644 googlemock/include/gmock/gmock-generated-actions.h.pump create mode 100644 googlemock/include/gmock/gmock-generated-function-mockers.h create mode 100644 googlemock/include/gmock/gmock-generated-function-mockers.h.pump create mode 100644 googlemock/include/gmock/gmock-generated-matchers.h create mode 100644 googlemock/include/gmock/gmock-generated-matchers.h.pump create mode 100644 googlemock/include/gmock/gmock-matchers.h create mode 100644 googlemock/include/gmock/gmock-more-actions.h create mode 100644 googlemock/include/gmock/gmock-more-matchers.h create mode 100644 googlemock/include/gmock/gmock-nice-strict.h create mode 100644 googlemock/include/gmock/gmock-spec-builders.h create mode 100644 googlemock/include/gmock/gmock.h create mode 100644 googlemock/include/gmock/internal/custom/README.md create mode 100644 googlemock/include/gmock/internal/custom/gmock-generated-actions.h create mode 100644 googlemock/include/gmock/internal/custom/gmock-generated-actions.h.pump create mode 100644 googlemock/include/gmock/internal/custom/gmock-matchers.h create mode 100644 googlemock/include/gmock/internal/custom/gmock-port.h create mode 100644 googlemock/include/gmock/internal/gmock-internal-utils.h create mode 100644 googlemock/include/gmock/internal/gmock-port.h create mode 100644 googlemock/include/gmock/internal/gmock-pp.h create mode 100755 googlemock/scripts/fuse_gmock_files.py create mode 100644 googlemock/scripts/generator/LICENSE create mode 100644 googlemock/scripts/generator/README create mode 100644 googlemock/scripts/generator/README.cppclean create mode 100755 googlemock/scripts/generator/cpp/__init__.py create mode 100755 googlemock/scripts/generator/cpp/ast.py create mode 100755 googlemock/scripts/generator/cpp/gmock_class.py create mode 100755 googlemock/scripts/generator/cpp/gmock_class_test.py create mode 100755 googlemock/scripts/generator/cpp/keywords.py create mode 100755 googlemock/scripts/generator/cpp/tokenize.py create mode 100755 googlemock/scripts/generator/cpp/utils.py create mode 100755 googlemock/scripts/generator/gmock_gen.py create mode 100755 googlemock/scripts/gmock-config.in create mode 100755 googlemock/scripts/gmock_doctor.py create mode 100755 googlemock/scripts/upload.py create mode 100755 googlemock/scripts/upload_gmock.py create mode 100644 googlemock/src/gmock-all.cc create mode 100644 googlemock/src/gmock-cardinalities.cc create mode 100644 googlemock/src/gmock-internal-utils.cc create mode 100644 googlemock/src/gmock-matchers.cc create mode 100644 googlemock/src/gmock-spec-builders.cc create mode 100644 googlemock/src/gmock.cc create mode 100644 googlemock/src/gmock_main.cc create mode 100644 googlemock/test/BUILD.bazel create mode 100644 googlemock/test/gmock-actions_test.cc create mode 100644 googlemock/test/gmock-cardinalities_test.cc create mode 100644 googlemock/test/gmock-function-mocker_nc.cc create mode 100644 googlemock/test/gmock-function-mocker_nc_test.py create mode 100644 googlemock/test/gmock-function-mocker_test.cc create mode 100644 googlemock/test/gmock-generated-actions_test.cc create mode 100644 googlemock/test/gmock-generated-function-mockers_test.cc create mode 100644 googlemock/test/gmock-generated-matchers_test.cc create mode 100644 googlemock/test/gmock-internal-utils_test.cc create mode 100644 googlemock/test/gmock-matchers_test.cc create mode 100644 googlemock/test/gmock-more-actions_test.cc create mode 100644 googlemock/test/gmock-nice-strict_test.cc create mode 100644 googlemock/test/gmock-port_test.cc create mode 100644 googlemock/test/gmock-pp-string_test.cc create mode 100644 googlemock/test/gmock-pp_test.cc create mode 100644 googlemock/test/gmock-spec-builders_test.cc create mode 100644 googlemock/test/gmock_all_test.cc create mode 100644 googlemock/test/gmock_ex_test.cc create mode 100755 googlemock/test/gmock_leak_test.py create mode 100644 googlemock/test/gmock_leak_test_.cc create mode 100644 googlemock/test/gmock_link2_test.cc create mode 100644 googlemock/test/gmock_link_test.cc create mode 100644 googlemock/test/gmock_link_test.h create mode 100755 googlemock/test/gmock_output_test.py create mode 100644 googlemock/test/gmock_output_test_.cc create mode 100644 googlemock/test/gmock_output_test_golden.txt create mode 100644 googlemock/test/gmock_stress_test.cc create mode 100644 googlemock/test/gmock_test.cc create mode 100755 googlemock/test/gmock_test_utils.py create mode 100644 googletest/CMakeLists.txt create mode 100644 googletest/CONTRIBUTORS create mode 100644 googletest/LICENSE create mode 100644 googletest/README.md create mode 100644 googletest/cmake/Config.cmake.in create mode 100644 googletest/cmake/gtest.pc.in create mode 100644 googletest/cmake/gtest_main.pc.in create mode 100644 googletest/cmake/internal_utils.cmake create mode 100644 googletest/cmake/libgtest.la.in create mode 100644 googletest/docs/advanced.md create mode 100644 googletest/docs/faq.md create mode 100644 googletest/docs/pkgconfig.md create mode 100644 googletest/docs/primer.md create mode 100644 googletest/docs/pump_manual.md create mode 100644 googletest/docs/samples.md create mode 100644 googletest/include/gtest/gtest-death-test.h create mode 100644 googletest/include/gtest/gtest-matchers.h create mode 100644 googletest/include/gtest/gtest-message.h create mode 100644 googletest/include/gtest/gtest-param-test.h create mode 100644 googletest/include/gtest/gtest-printers.h create mode 100644 googletest/include/gtest/gtest-spi.h create mode 100644 googletest/include/gtest/gtest-test-part.h create mode 100644 googletest/include/gtest/gtest-typed-test.h create mode 100644 googletest/include/gtest/gtest.h create mode 100644 googletest/include/gtest/gtest_pred_impl.h create mode 100644 googletest/include/gtest/gtest_prod.h create mode 100644 googletest/include/gtest/internal/custom/README.md create mode 100644 googletest/include/gtest/internal/custom/gtest-port.h create mode 100644 googletest/include/gtest/internal/custom/gtest-printers.h create mode 100644 googletest/include/gtest/internal/custom/gtest.h create mode 100644 googletest/include/gtest/internal/gtest-death-test-internal.h create mode 100644 googletest/include/gtest/internal/gtest-filepath.h create mode 100644 googletest/include/gtest/internal/gtest-internal.h create mode 100644 googletest/include/gtest/internal/gtest-param-util.h create mode 100644 googletest/include/gtest/internal/gtest-port-arch.h create mode 100644 googletest/include/gtest/internal/gtest-port.h create mode 100644 googletest/include/gtest/internal/gtest-string.h create mode 100644 googletest/include/gtest/internal/gtest-type-util.h create mode 100644 googletest/include/gtest/internal/gtest-type-util.h.pump create mode 100644 googletest/samples/prime_tables.h create mode 100644 googletest/samples/sample1.cc create mode 100644 googletest/samples/sample1.h create mode 100644 googletest/samples/sample10_unittest.cc create mode 100644 googletest/samples/sample1_unittest.cc create mode 100644 googletest/samples/sample2.cc create mode 100644 googletest/samples/sample2.h create mode 100644 googletest/samples/sample2_unittest.cc create mode 100644 googletest/samples/sample3-inl.h create mode 100644 googletest/samples/sample3_unittest.cc create mode 100644 googletest/samples/sample4.cc create mode 100644 googletest/samples/sample4.h create mode 100644 googletest/samples/sample4_unittest.cc create mode 100644 googletest/samples/sample5_unittest.cc create mode 100644 googletest/samples/sample6_unittest.cc create mode 100644 googletest/samples/sample7_unittest.cc create mode 100644 googletest/samples/sample8_unittest.cc create mode 100644 googletest/samples/sample9_unittest.cc create mode 100644 googletest/scripts/common.py create mode 100755 googletest/scripts/fuse_gtest_files.py create mode 100755 googletest/scripts/gen_gtest_pred_impl.py create mode 100755 googletest/scripts/gtest-config.in create mode 100755 googletest/scripts/pump.py create mode 100755 googletest/scripts/release_docs.py create mode 100644 googletest/scripts/test/Makefile create mode 100755 googletest/scripts/upload.py create mode 100755 googletest/scripts/upload_gtest.py create mode 100644 googletest/src/gtest-all.cc create mode 100644 googletest/src/gtest-death-test.cc create mode 100644 googletest/src/gtest-filepath.cc create mode 100644 googletest/src/gtest-internal-inl.h create mode 100644 googletest/src/gtest-matchers.cc create mode 100644 googletest/src/gtest-port.cc create mode 100644 googletest/src/gtest-printers.cc create mode 100644 googletest/src/gtest-test-part.cc create mode 100644 googletest/src/gtest-typed-test.cc create mode 100644 googletest/src/gtest.cc create mode 100644 googletest/src/gtest_main.cc create mode 100644 googletest/test/BUILD.bazel create mode 100755 googletest/test/googletest-break-on-failure-unittest.py create mode 100644 googletest/test/googletest-break-on-failure-unittest_.cc create mode 100755 googletest/test/googletest-catch-exceptions-test.py create mode 100644 googletest/test/googletest-catch-exceptions-test_.cc create mode 100755 googletest/test/googletest-color-test.py create mode 100644 googletest/test/googletest-color-test_.cc create mode 100644 googletest/test/googletest-death-test-test.cc create mode 100644 googletest/test/googletest-death-test_ex_test.cc create mode 100755 googletest/test/googletest-env-var-test.py create mode 100644 googletest/test/googletest-env-var-test_.cc create mode 100644 googletest/test/googletest-filepath-test.cc create mode 100755 googletest/test/googletest-filter-unittest.py create mode 100644 googletest/test/googletest-filter-unittest_.cc create mode 100644 googletest/test/googletest-json-outfiles-test.py create mode 100644 googletest/test/googletest-json-output-unittest.py create mode 100755 googletest/test/googletest-list-tests-unittest.py create mode 100644 googletest/test/googletest-list-tests-unittest_.cc create mode 100644 googletest/test/googletest-listener-test.cc create mode 100644 googletest/test/googletest-message-test.cc create mode 100644 googletest/test/googletest-options-test.cc create mode 100644 googletest/test/googletest-output-test-golden-lin.txt create mode 100755 googletest/test/googletest-output-test.py create mode 100644 googletest/test/googletest-output-test_.cc create mode 100644 googletest/test/googletest-param-test-invalid-name1-test.py create mode 100644 googletest/test/googletest-param-test-invalid-name1-test_.cc create mode 100644 googletest/test/googletest-param-test-invalid-name2-test.py create mode 100644 googletest/test/googletest-param-test-invalid-name2-test_.cc create mode 100644 googletest/test/googletest-param-test-test.cc create mode 100644 googletest/test/googletest-param-test-test.h create mode 100644 googletest/test/googletest-param-test2-test.cc create mode 100644 googletest/test/googletest-port-test.cc create mode 100644 googletest/test/googletest-printers-test.cc create mode 100755 googletest/test/googletest-shuffle-test.py create mode 100644 googletest/test/googletest-shuffle-test_.cc create mode 100644 googletest/test/googletest-test-part-test.cc create mode 100644 googletest/test/googletest-test2_test.cc create mode 100755 googletest/test/googletest-throw-on-failure-test.py create mode 100644 googletest/test/googletest-throw-on-failure-test_.cc create mode 100755 googletest/test/googletest-uninitialized-test.py create mode 100644 googletest/test/googletest-uninitialized-test_.cc create mode 100644 googletest/test/gtest-typed-test2_test.cc create mode 100644 googletest/test/gtest-typed-test_test.cc create mode 100644 googletest/test/gtest-typed-test_test.h create mode 100644 googletest/test/gtest-unittest-api_test.cc create mode 100644 googletest/test/gtest_all_test.cc create mode 100644 googletest/test/gtest_assert_by_exception_test.cc create mode 100644 googletest/test/gtest_environment_test.cc create mode 100755 googletest/test/gtest_help_test.py create mode 100644 googletest/test/gtest_help_test_.cc create mode 100644 googletest/test/gtest_json_test_utils.py create mode 100644 googletest/test/gtest_list_output_unittest.py create mode 100644 googletest/test/gtest_list_output_unittest_.cc create mode 100644 googletest/test/gtest_main_unittest.cc create mode 100644 googletest/test/gtest_no_test_unittest.cc create mode 100644 googletest/test/gtest_pred_impl_unittest.cc create mode 100644 googletest/test/gtest_premature_exit_test.cc create mode 100644 googletest/test/gtest_prod_test.cc create mode 100644 googletest/test/gtest_repeat_test.cc create mode 100755 googletest/test/gtest_skip_environment_check_output_test.py create mode 100644 googletest/test/gtest_skip_in_environment_setup_test.cc create mode 100644 googletest/test/gtest_skip_test.cc create mode 100644 googletest/test/gtest_sole_header_test.cc create mode 100644 googletest/test/gtest_stress_test.cc create mode 100644 googletest/test/gtest_test_macro_stack_footprint_test.cc create mode 100755 googletest/test/gtest_test_utils.py create mode 100755 googletest/test/gtest_testbridge_test.py create mode 100644 googletest/test/gtest_testbridge_test_.cc create mode 100644 googletest/test/gtest_throw_on_failure_ex_test.cc create mode 100644 googletest/test/gtest_unittest.cc create mode 100644 googletest/test/gtest_xml_outfile1_test_.cc create mode 100644 googletest/test/gtest_xml_outfile2_test_.cc create mode 100755 googletest/test/gtest_xml_outfiles_test.py create mode 100755 googletest/test/gtest_xml_output_unittest.py create mode 100644 googletest/test/gtest_xml_output_unittest_.cc create mode 100755 googletest/test/gtest_xml_test_utils.py create mode 100644 googletest/test/production.cc create mode 100644 googletest/test/production.h create mode 100644 library.json create mode 100644 platformio.ini diff --git a/.clang-format b/.clang-format new file mode 100644 index 00000000..5b9bfe6d --- /dev/null +++ b/.clang-format @@ -0,0 +1,4 @@ +# Run manually to reformat a file: +# clang-format -i --style=file +Language: Cpp +BasedOnStyle: Google diff --git a/.gitignore b/.gitignore new file mode 100644 index 00000000..f08cb72a --- /dev/null +++ b/.gitignore @@ -0,0 +1,84 @@ +# Ignore CI build directory +build/ +xcuserdata +cmake-build-debug/ +.idea/ +bazel-bin +bazel-genfiles +bazel-googletest +bazel-out +bazel-testlogs +# python +*.pyc + +# Visual Studio files +.vs +*.sdf +*.opensdf +*.VC.opendb +*.suo +*.user +_ReSharper.Caches/ +Win32-Debug/ +Win32-Release/ +x64-Debug/ +x64-Release/ + +# Ignore autoconf / automake files +Makefile.in +aclocal.m4 +configure +build-aux/ +autom4te.cache/ +googletest/m4/libtool.m4 +googletest/m4/ltoptions.m4 +googletest/m4/ltsugar.m4 +googletest/m4/ltversion.m4 +googletest/m4/lt~obsolete.m4 +googlemock/m4 + +# Ignore generated directories. +googlemock/fused-src/ +googletest/fused-src/ + +# macOS files +.DS_Store +googletest/.DS_Store +googletest/xcode/.DS_Store + +# Ignore cmake generated directories and files. +CMakeFiles +CTestTestfile.cmake +Makefile +cmake_install.cmake +googlemock/CMakeFiles +googlemock/CTestTestfile.cmake +googlemock/Makefile +googlemock/cmake_install.cmake +googlemock/gtest +/bin +/googlemock/gmock.dir +/googlemock/gmock_main.dir +/googlemock/RUN_TESTS.vcxproj.filters +/googlemock/RUN_TESTS.vcxproj +/googlemock/INSTALL.vcxproj.filters +/googlemock/INSTALL.vcxproj +/googlemock/gmock_main.vcxproj.filters +/googlemock/gmock_main.vcxproj +/googlemock/gmock.vcxproj.filters +/googlemock/gmock.vcxproj +/googlemock/gmock.sln +/googlemock/ALL_BUILD.vcxproj.filters +/googlemock/ALL_BUILD.vcxproj +/lib +/Win32 +/ZERO_CHECK.vcxproj.filters +/ZERO_CHECK.vcxproj +/RUN_TESTS.vcxproj.filters +/RUN_TESTS.vcxproj +/INSTALL.vcxproj.filters +/INSTALL.vcxproj +/googletest-distribution.sln +/CMakeCache.txt +/ALL_BUILD.vcxproj.filters +/ALL_BUILD.vcxproj diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 00000000..56f7d7c1 --- /dev/null +++ b/.travis.yml @@ -0,0 +1,73 @@ +# Build matrix / environment variable are explained on: +# https://docs.travis-ci.com/user/customizing-the-build/ +# This file can be validated on: +# http://lint.travis-ci.org/ + +language: cpp + +# Define the matrix explicitly, manually expanding the combinations of (os, compiler, env). +# It is more tedious, but grants us far more flexibility. +matrix: + include: + - os: linux + before_install: chmod -R +x ./ci/*platformio.sh + install: ./ci/install-platformio.sh + script: ./ci/build-platformio.sh + - os: linux + dist: xenial + compiler: gcc + install: ./ci/install-linux.sh && ./ci/log-config.sh + script: ./ci/build-linux-bazel.sh + - os: linux + dist: xenial + compiler: clang + install: ./ci/install-linux.sh && ./ci/log-config.sh + script: ./ci/build-linux-bazel.sh + - os: linux + compiler: gcc + env: BUILD_TYPE=Debug VERBOSE=1 CXX_FLAGS=-std=c++11 + - os: linux + compiler: clang + env: BUILD_TYPE=Release VERBOSE=1 CXX_FLAGS=-std=c++11 -Wgnu-zero-variadic-macro-arguments + - os: linux + compiler: clang + env: BUILD_TYPE=Release VERBOSE=1 CXX_FLAGS=-std=c++11 NO_EXCEPTION=ON NO_RTTI=ON COMPILER_IS_GNUCXX=ON + - os: osx + compiler: gcc + env: BUILD_TYPE=Release VERBOSE=1 CXX_FLAGS=-std=c++11 HOMEBREW_LOGS=~/homebrew-logs HOMEBREW_TEMP=~/homebrew-temp + - os: osx + compiler: clang + env: BUILD_TYPE=Release VERBOSE=1 CXX_FLAGS=-std=c++11 HOMEBREW_LOGS=~/homebrew-logs HOMEBREW_TEMP=~/homebrew-temp + +# These are the install and build (script) phases for the most common entries in the matrix. They could be included +# in each entry in the matrix, but that is just repetitive. +install: + - ./ci/install-${TRAVIS_OS_NAME}.sh + - . ./ci/env-${TRAVIS_OS_NAME}.sh + - ./ci/log-config.sh + +script: ./ci/travis.sh + +# This section installs the necessary dependencies. +addons: + apt: + # List of whitelisted in travis packages for ubuntu-precise can be found here: + # https://github.com/travis-ci/apt-package-whitelist/blob/master/ubuntu-precise + # List of whitelisted in travis apt-sources: + # https://github.com/travis-ci/apt-source-whitelist/blob/master/ubuntu.json + sources: + - ubuntu-toolchain-r-test + - llvm-toolchain-precise-3.9 + packages: + - g++-4.9 + - clang-3.9 + update: true + homebrew: + packages: + - ccache + - gcc@4.9 + - llvm@3.9 + update: true + +notifications: + email: false diff --git a/BUILD.bazel b/BUILD.bazel new file mode 100644 index 00000000..9b48aee5 --- /dev/null +++ b/BUILD.bazel @@ -0,0 +1,179 @@ +# Copyright 2017 Google Inc. +# All Rights Reserved. +# +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above +# copyright notice, this list of conditions and the following disclaimer +# in the documentation and/or other materials provided with the +# distribution. +# * Neither the name of Google Inc. nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# Bazel Build for Google C++ Testing Framework(Google Test) + +load("@rules_cc//cc:defs.bzl", "cc_library", "cc_test") + +package(default_visibility = ["//visibility:public"]) + +licenses(["notice"]) + +config_setting( + name = "windows", + constraint_values = ["@bazel_tools//platforms:windows"], +) + +config_setting( + name = "has_absl", + values = {"define": "absl=1"}, +) + +# Library that defines the FRIEND_TEST macro. +cc_library( + name = "gtest_prod", + hdrs = ["googletest/include/gtest/gtest_prod.h"], + includes = ["googletest/include"], +) + +# Google Test including Google Mock +cc_library( + name = "gtest", + srcs = glob( + include = [ + "googletest/src/*.cc", + "googletest/src/*.h", + "googletest/include/gtest/**/*.h", + "googlemock/src/*.cc", + "googlemock/include/gmock/**/*.h", + ], + exclude = [ + "googletest/src/gtest-all.cc", + "googletest/src/gtest_main.cc", + "googlemock/src/gmock-all.cc", + "googlemock/src/gmock_main.cc", + ], + ), + hdrs = glob([ + "googletest/include/gtest/*.h", + "googlemock/include/gmock/*.h", + ]), + copts = select({ + ":windows": [], + "//conditions:default": ["-pthread"], + }), + defines = select({ + ":has_absl": ["GTEST_HAS_ABSL=1"], + "//conditions:default": [], + }), + features = select({ + ":windows": ["windows_export_all_symbols"], + "//conditions:default": [], + }), + includes = [ + "googlemock", + "googlemock/include", + "googletest", + "googletest/include", + ], + linkopts = select({ + ":windows": [], + "//conditions:default": ["-pthread"], + }), + deps = select({ + ":has_absl": [ + "@com_google_absl//absl/debugging:failure_signal_handler", + "@com_google_absl//absl/debugging:stacktrace", + "@com_google_absl//absl/debugging:symbolize", + "@com_google_absl//absl/strings", + "@com_google_absl//absl/types:optional", + "@com_google_absl//absl/types:variant", + ], + "//conditions:default": [], + }), +) + +cc_library( + name = "gtest_main", + srcs = ["googlemock/src/gmock_main.cc"], + features = select({ + ":windows": ["windows_export_all_symbols"], + "//conditions:default": [], + }), + deps = [":gtest"], +) + +# The following rules build samples of how to use gTest. +cc_library( + name = "gtest_sample_lib", + srcs = [ + "googletest/samples/sample1.cc", + "googletest/samples/sample2.cc", + "googletest/samples/sample4.cc", + ], + hdrs = [ + "googletest/samples/prime_tables.h", + "googletest/samples/sample1.h", + "googletest/samples/sample2.h", + "googletest/samples/sample3-inl.h", + "googletest/samples/sample4.h", + ], + features = select({ + ":windows": ["windows_export_all_symbols"], + "//conditions:default": [], + }), +) + +cc_test( + name = "gtest_samples", + size = "small", + # All Samples except: + # sample9 (main) + # sample10 (main and takes a command line option and needs to be separate) + srcs = [ + "googletest/samples/sample1_unittest.cc", + "googletest/samples/sample2_unittest.cc", + "googletest/samples/sample3_unittest.cc", + "googletest/samples/sample4_unittest.cc", + "googletest/samples/sample5_unittest.cc", + "googletest/samples/sample6_unittest.cc", + "googletest/samples/sample7_unittest.cc", + "googletest/samples/sample8_unittest.cc", + ], + linkstatic = 0, + deps = [ + "gtest_sample_lib", + ":gtest_main", + ], +) + +cc_test( + name = "sample9_unittest", + size = "small", + srcs = ["googletest/samples/sample9_unittest.cc"], + deps = [":gtest"], +) + +cc_test( + name = "sample10_unittest", + size = "small", + srcs = ["googletest/samples/sample10_unittest.cc"], + deps = [":gtest"], +) diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 00000000..3fae2f96 --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,36 @@ +# Note: CMake support is community-based. The maintainers do not use CMake +# internally. + +cmake_minimum_required(VERSION 2.8.8) + +if (POLICY CMP0048) + cmake_policy(SET CMP0048 NEW) +endif (POLICY CMP0048) + +project(googletest-distribution) +set(GOOGLETEST_VERSION 1.9.0) + +if (CMAKE_VERSION VERSION_LESS "3.1") + add_definitions(-std=c++11) +else() + set(CMAKE_CXX_STANDARD 11) + set(CMAKE_CXX_STANDARD_REQUIRED ON) + if(NOT CYGWIN) + set(CMAKE_CXX_EXTENSIONS OFF) + endif() +endif() + +enable_testing() + +include(CMakeDependentOption) +include(GNUInstallDirs) + +#Note that googlemock target already builds googletest +option(BUILD_GMOCK "Builds the googlemock subproject" ON) +option(INSTALL_GTEST "Enable installation of googletest. (Projects embedding googletest may want to turn this OFF.)" ON) + +if(BUILD_GMOCK) + add_subdirectory( googlemock ) +else() + add_subdirectory( googletest ) +endif() diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 00000000..30c8d890 --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,142 @@ +# How to become a contributor and submit your own code + +## Contributor License Agreements + +We'd love to accept your patches! Before we can take them, we have to jump a +couple of legal hurdles. + +Please fill out either the individual or corporate Contributor License Agreement +(CLA). + +* If you are an individual writing original source code and you're sure you + own the intellectual property, then you'll need to sign an + [individual CLA](https://developers.google.com/open-source/cla/individual). +* If you work for a company that wants to allow you to contribute your work, + then you'll need to sign a + [corporate CLA](https://developers.google.com/open-source/cla/corporate). + +Follow either of the two links above to access the appropriate CLA and +instructions for how to sign and return it. Once we receive it, we'll be able to +accept your pull requests. + +## Are you a Googler? + +If you are a Googler, please make an attempt to submit an internal change rather +than a GitHub Pull Request. If you are not able to submit an internal change a +PR is acceptable as an alternative. + +## Contributing A Patch + +1. Submit an issue describing your proposed change to the + [issue tracker](https://github.com/google/googletest). +2. Please don't mix more than one logical change per submittal, because it + makes the history hard to follow. If you want to make a change that doesn't + have a corresponding issue in the issue tracker, please create one. +3. Also, coordinate with team members that are listed on the issue in question. + This ensures that work isn't being duplicated and communicating your plan + early also generally leads to better patches. +4. If your proposed change is accepted, and you haven't already done so, sign a + Contributor License Agreement (see details above). +5. Fork the desired repo, develop and test your code changes. +6. Ensure that your code adheres to the existing style in the sample to which + you are contributing. +7. Ensure that your code has an appropriate set of unit tests which all pass. +8. Submit a pull request. + +## The Google Test and Google Mock Communities + +The Google Test community exists primarily through the +[discussion group](http://groups.google.com/group/googletestframework) and the +GitHub repository. Likewise, the Google Mock community exists primarily through +their own [discussion group](http://groups.google.com/group/googlemock). You are +definitely encouraged to contribute to the discussion and you can also help us +to keep the effectiveness of the group high by following and promoting the +guidelines listed here. + +### Please Be Friendly + +Showing courtesy and respect to others is a vital part of the Google culture, +and we strongly encourage everyone participating in Google Test development to +join us in accepting nothing less. Of course, being courteous is not the same as +failing to constructively disagree with each other, but it does mean that we +should be respectful of each other when enumerating the 42 technical reasons +that a particular proposal may not be the best choice. There's never a reason to +be antagonistic or dismissive toward anyone who is sincerely trying to +contribute to a discussion. + +Sure, C++ testing is serious business and all that, but it's also a lot of fun. +Let's keep it that way. Let's strive to be one of the friendliest communities in +all of open source. + +As always, discuss Google Test in the official GoogleTest discussion group. You +don't have to actually submit code in order to sign up. Your participation +itself is a valuable contribution. + +## Style + +To keep the source consistent, readable, diffable and easy to merge, we use a +fairly rigid coding style, as defined by the +[google-styleguide](https://github.com/google/styleguide) project. All patches +will be expected to conform to the style outlined +[here](https://google.github.io/styleguide/cppguide.html). Use +[.clang-format](https://github.com/google/googletest/blob/master/.clang-format) +to check your formatting + +## Requirements for Contributors + +If you plan to contribute a patch, you need to build Google Test, Google Mock, +and their own tests from a git checkout, which has further requirements: + +* [Python](https://www.python.org/) v2.3 or newer (for running some of the + tests and re-generating certain source files from templates) +* [CMake](https://cmake.org/) v2.6.4 or newer + +## Developing Google Test and Google Mock + +This section discusses how to make your own changes to the Google Test project. + +### Testing Google Test and Google Mock Themselves + +To make sure your changes work as intended and don't break existing +functionality, you'll want to compile and run Google Test and GoogleMock's own +tests. For that you can use CMake: + + mkdir mybuild + cd mybuild + cmake -Dgtest_build_tests=ON -Dgmock_build_tests=ON ${GTEST_REPO_DIR} + +To choose between building only Google Test or Google Mock, you may modify your +cmake command to be one of each + + cmake -Dgtest_build_tests=ON ${GTEST_DIR} # sets up Google Test tests + cmake -Dgmock_build_tests=ON ${GMOCK_DIR} # sets up Google Mock tests + +Make sure you have Python installed, as some of Google Test's tests are written +in Python. If the cmake command complains about not being able to find Python +(`Could NOT find PythonInterp (missing: PYTHON_EXECUTABLE)`), try telling it +explicitly where your Python executable can be found: + + cmake -DPYTHON_EXECUTABLE=path/to/python ... + +Next, you can build Google Test and / or Google Mock and all desired tests. On +\*nix, this is usually done by + + make + +To run the tests, do + + make test + +All tests should pass. + +### Regenerating Source Files + +Some of Google Test's source files are generated from templates (not in the C++ +sense) using a script. For example, the file +include/gtest/internal/gtest-type-util.h.pump is used to generate +gtest-type-util.h in the same directory. + +You don't need to worry about regenerating the source files unless you need to +modify them. You would then modify the corresponding `.pump` files and run the +'[pump.py](googletest/scripts/pump.py)' generator script. See the +[Pump Manual](googletest/docs/pump_manual.md). diff --git a/LICENSE b/LICENSE new file mode 100644 index 00000000..1941a11f --- /dev/null +++ b/LICENSE @@ -0,0 +1,28 @@ +Copyright 2008, Google Inc. +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the following disclaimer +in the documentation and/or other materials provided with the +distribution. + * Neither the name of Google Inc. nor the names of its +contributors may be used to endorse or promote products derived from +this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/README.md b/README.md new file mode 100644 index 00000000..5b417fa8 --- /dev/null +++ b/README.md @@ -0,0 +1,134 @@ +# Google Test + +#### OSS Builds Status: + +[![Build Status](https://api.travis-ci.org/google/googletest.svg?branch=master)](https://travis-ci.org/google/googletest) +[![Build status](https://ci.appveyor.com/api/projects/status/4o38plt0xbo1ubc8/branch/master?svg=true)](https://ci.appveyor.com/project/GoogleTestAppVeyor/googletest/branch/master) + +### Future Plans + +#### 1.8.x Release: + +[the 1.8.x](https://github.com/google/googletest/releases/tag/release-1.8.1) is +the last release that works with pre-C++11 compilers. The 1.8.x will not accept +any requests for any new features and any bugfix requests will only be accepted +if proven "critical" + +#### Post 1.8.x: + +On-going work to improve/cleanup/pay technical debt. When this work is completed +there will be a 1.9.x tagged release + +#### Post 1.9.x + +Post 1.9.x googletest will follow +[Abseil Live at Head philosophy](https://abseil.io/about/philosophy) + +## Welcome to **Google Test**, Google's C++ test framework! + +This repository is a merger of the formerly separate GoogleTest and GoogleMock +projects. These were so closely related that it makes sense to maintain and +release them together. + +Please subscribe to the mailing list at googletestframework@googlegroups.com for +questions, discussions, and development. + +### Getting started: + +The information for **Google Test** is available in the +[Google Test Primer](googletest/docs/primer.md) documentation. + +**Google Mock** is an extension to Google Test for writing and using C++ mock +classes. See the separate [Google Mock documentation](googlemock/README.md). + +More detailed documentation for googletest is in its interior +[googletest/README.md](googletest/README.md) file. + +## Features + +* An [xUnit](https://en.wikipedia.org/wiki/XUnit) test framework. +* Test discovery. +* A rich set of assertions. +* User-defined assertions. +* Death tests. +* Fatal and non-fatal failures. +* Value-parameterized tests. +* Type-parameterized tests. +* Various options for running the tests. +* XML test report generation. + +## Platforms + +Google test has been used on a variety of platforms: + +* Linux +* Mac OS X +* Windows +* Cygwin +* MinGW +* Windows Mobile +* Symbian +* PlatformIO + +## Who Is Using Google Test? + +In addition to many internal projects at Google, Google Test is also used by the +following notable projects: + +* The [Chromium projects](http://www.chromium.org/) (behind the Chrome browser + and Chrome OS). +* The [LLVM](http://llvm.org/) compiler. +* [Protocol Buffers](https://github.com/google/protobuf), Google's data + interchange format. +* The [OpenCV](http://opencv.org/) computer vision library. +* [tiny-dnn](https://github.com/tiny-dnn/tiny-dnn): header only, + dependency-free deep learning framework in C++11. + +## Related Open Source Projects + +[GTest Runner](https://github.com/nholthaus/gtest-runner) is a Qt5 based +automated test-runner and Graphical User Interface with powerful features for +Windows and Linux platforms. + +[Google Test UI](https://github.com/ospector/gtest-gbar) is test runner that +runs your test binary, allows you to track its progress via a progress bar, and +displays a list of test failures. Clicking on one shows failure text. Google +Test UI is written in C#. + +[GTest TAP Listener](https://github.com/kinow/gtest-tap-listener) is an event +listener for Google Test that implements the +[TAP protocol](https://en.wikipedia.org/wiki/Test_Anything_Protocol) for test +result output. If your test runner understands TAP, you may find it useful. + +[gtest-parallel](https://github.com/google/gtest-parallel) is a test runner that +runs tests from your binary in parallel to provide significant speed-up. + +[GoogleTest Adapter](https://marketplace.visualstudio.com/items?itemName=DavidSchuldenfrei.gtest-adapter) +is a VS Code extension allowing to view Google Tests in a tree view, and +run/debug your tests. + +## Requirements + +Google Test is designed to have fairly minimal requirements to build and use +with your projects, but there are some. If you notice any problems on your +platform, please notify +[googletestframework@googlegroups.com](https://groups.google.com/forum/#!forum/googletestframework). +Patches for fixing them are welcome! + +### Build Requirements + +These are the base requirements to build and use Google Test from a source +package: + +* [Bazel](https://bazel.build/) or [CMake](https://cmake.org/). NOTE: Bazel is + the build system that googletest is using internally and tests against. + CMake is community-supported. + +* a C++11-standard-compliant compiler + +## Contributing change + +Please read the [`CONTRIBUTING.md`](CONTRIBUTING.md) for details on how to +contribute to this project. + +Happy testing! diff --git a/WORKSPACE b/WORKSPACE new file mode 100644 index 00000000..2289bdb7 --- /dev/null +++ b/WORKSPACE @@ -0,0 +1,23 @@ +workspace(name = "com_google_googletest") + +load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive") + +# Abseil +http_archive( + name = "com_google_absl", + urls = ["https://github.com/abseil/abseil-cpp/archive/master.zip"], + strip_prefix = "abseil-cpp-master", +) + +http_archive( + name = "rules_cc", + strip_prefix = "rules_cc-master", + urls = ["https://github.com/bazelbuild/rules_cc/archive/master.zip"], +) + +http_archive( + name = "rules_python", + strip_prefix = "rules_python-master", + urls = ["https://github.com/bazelbuild/rules_python/archive/master.zip"], +) + diff --git a/appveyor.yml b/appveyor.yml new file mode 100644 index 00000000..a58b7687 --- /dev/null +++ b/appveyor.yml @@ -0,0 +1,154 @@ +version: '{build}' + +os: Visual Studio 2015 + +environment: + matrix: + - compiler: msvc-15-seh + generator: "Visual Studio 15 2017" + build_system: cmake + APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017 + + - compiler: msvc-15-seh + generator: "Visual Studio 15 2017 Win64" + build_system: cmake + APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017 + enabled_on_pr: yes + + - compiler: msvc-15-seh + build_system: bazel + APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017 + enabled_on_pr: yes + + - compiler: msvc-14-seh + build_system: cmake + generator: "Visual Studio 14 2015" + enabled_on_pr: yes + + - compiler: msvc-14-seh + build_system: cmake + generator: "Visual Studio 14 2015 Win64" + + - compiler: gcc-6.3.0-posix + build_system: cmake + generator: "MinGW Makefiles" + cxx_path: 'C:\mingw-w64\i686-6.3.0-posix-dwarf-rt_v5-rev1\mingw32\bin' + enabled_on_pr: yes + +configuration: + - Debug + +build: + verbosity: minimal + +install: +- ps: | + Write-Output "Compiler: $env:compiler" + Write-Output "Generator: $env:generator" + Write-Output "Env:Configuation: $env:configuration" + Write-Output "Env: $env" + if (-not (Test-Path env:APPVEYOR_PULL_REQUEST_NUMBER)) { + Write-Output "This is *NOT* a pull request build" + } else { + Write-Output "This is a pull request build" + if (-not (Test-Path env:enabled_on_pr) -or $env:enabled_on_pr -ne "yes") { + Write-Output "PR builds are *NOT* explicitly enabled" + } + } + + # install Bazel + if ($env:build_system -eq "bazel") { + appveyor DownloadFile https://github.com/bazelbuild/bazel/releases/download/0.28.1/bazel-0.28.1-windows-x86_64.exe -FileName bazel.exe + } + + if ($env:build_system -eq "cmake") { + # git bash conflicts with MinGW makefiles + if ($env:generator -eq "MinGW Makefiles") { + $env:path = $env:path.replace("C:\Program Files\Git\usr\bin;", "") + if ($env:cxx_path -ne "") { + $env:path += ";$env:cxx_path" + } + } + } + +before_build: +- ps: | + $env:root=$env:APPVEYOR_BUILD_FOLDER + Write-Output "env:root: $env:root" + +build_script: +- ps: | + # Only enable some builds for pull requests, the AppVeyor queue is too long. + if ((Test-Path env:APPVEYOR_PULL_REQUEST_NUMBER) -And (-not (Test-Path env:enabled_on_pr) -or $env:enabled_on_pr -ne "yes")) { + return + } else { + # special case - build with Bazel + if ($env:build_system -eq "bazel") { + & $env:root\bazel.exe build -c opt //:gtest_samples + if ($LastExitCode -eq 0) { # bazel writes to StdErr and PowerShell interprets it as an error + $host.SetShouldExit(0) + } else { # a real error + throw "Exec: $ErrorMessage" + } + return + } + } + # by default build with CMake + md _build -Force | Out-Null + cd _build + + $conf = if ($env:generator -eq "MinGW Makefiles") {"-DCMAKE_BUILD_TYPE=$env:configuration"} else {"-DCMAKE_CONFIGURATION_TYPES=Debug;Release"} + # Disable test for MinGW (gtest tests fail, gmock tests can not build) + $gtest_build_tests = if ($env:generator -eq "MinGW Makefiles") {"-Dgtest_build_tests=OFF"} else {"-Dgtest_build_tests=ON"} + $gmock_build_tests = if ($env:generator -eq "MinGW Makefiles") {"-Dgmock_build_tests=OFF"} else {"-Dgmock_build_tests=ON"} + & cmake -G "$env:generator" $conf -Dgtest_build_samples=ON $gtest_build_tests $gmock_build_tests .. + if ($LastExitCode -ne 0) { + throw "Exec: $ErrorMessage" + } + $cmake_parallel = if ($env:generator -eq "MinGW Makefiles") {"-j2"} else {"/m"} + & cmake --build . --config $env:configuration -- $cmake_parallel + if ($LastExitCode -ne 0) { + throw "Exec: $ErrorMessage" + } + + +skip_commits: + files: + - '**/*.md' + +test_script: +- ps: | + # Only enable some builds for pull requests, the AppVeyor queue is too long. + if ((Test-Path env:APPVEYOR_PULL_REQUEST_NUMBER) -And (-not (Test-Path env:enabled_on_pr) -or $env:enabled_on_pr -ne "yes")) { + return + } + if ($env:build_system -eq "bazel") { + # special case - testing with Bazel + & $env:root\bazel.exe test //:gtest_samples + if ($LastExitCode -eq 0) { # bazel writes to StdErr and PowerShell interprets it as an error + $host.SetShouldExit(0) + } else { # a real error + throw "Exec: $ErrorMessage" + } + } + if ($env:build_system -eq "cmake") { + # built with CMake - test with CTest + if ($env:generator -eq "MinGW Makefiles") { + return # No test available for MinGW + } + + & ctest -C $env:configuration --timeout 600 --output-on-failure + if ($LastExitCode -ne 0) { + throw "Exec: $ErrorMessage" + } + } + +artifacts: + - path: '_build/CMakeFiles/*.log' + name: logs + - path: '_build/Testing/**/*.xml' + name: test_results + - path: 'bazel-testlogs/**/test.log' + name: test_logs + - path: 'bazel-testlogs/**/test.xml' + name: test_results diff --git a/ci/build-linux-bazel.sh b/ci/build-linux-bazel.sh new file mode 100755 index 00000000..ae8fb758 --- /dev/null +++ b/ci/build-linux-bazel.sh @@ -0,0 +1,37 @@ +#!/usr/bin/env bash +# Copyright 2017 Google Inc. +# All Rights Reserved. +# +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above +# copyright notice, this list of conditions and the following disclaimer +# in the documentation and/or other materials provided with the +# distribution. +# * Neither the name of Google Inc. nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +set -e + +bazel version +bazel build --curses=no //...:all +bazel test --curses=no //...:all +bazel test --curses=no //...:all --define absl=1 diff --git a/ci/build-platformio.sh b/ci/build-platformio.sh new file mode 100644 index 00000000..1d7658d8 --- /dev/null +++ b/ci/build-platformio.sh @@ -0,0 +1,2 @@ +# run PlatformIO builds +platformio run diff --git a/ci/env-linux.sh b/ci/env-linux.sh new file mode 100755 index 00000000..37800d6a --- /dev/null +++ b/ci/env-linux.sh @@ -0,0 +1,41 @@ +#!/usr/bin/env bash +# Copyright 2017 Google Inc. +# All Rights Reserved. +# +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above +# copyright notice, this list of conditions and the following disclaimer +# in the documentation and/or other materials provided with the +# distribution. +# * Neither the name of Google Inc. nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +# +# This file should be sourced, and not executed as a standalone script. +# + +# TODO() - we can check if this is being sourced using $BASH_VERSION and $BASH_SOURCE[0] != ${0}. + +if [ "${TRAVIS_OS_NAME}" = "linux" ]; then + if [ "$CXX" = "g++" ]; then export CXX="g++-4.9" CC="gcc-4.9"; fi + if [ "$CXX" = "clang++" ]; then export CXX="clang++-3.9" CC="clang-3.9"; fi +fi diff --git a/ci/env-osx.sh b/ci/env-osx.sh new file mode 100755 index 00000000..9c421e14 --- /dev/null +++ b/ci/env-osx.sh @@ -0,0 +1,47 @@ +#!/usr/bin/env bash +# Copyright 2017 Google Inc. +# All Rights Reserved. +# +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above +# copyright notice, this list of conditions and the following disclaimer +# in the documentation and/or other materials provided with the +# distribution. +# * Neither the name of Google Inc. nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +# +# This file should be sourced, and not executed as a standalone script. +# + +# TODO() - we can check if this is being sourced using $BASH_VERSION and $BASH_SOURCE[0] != ${0}. +# + +if [ "${TRAVIS_OS_NAME}" = "osx" ]; then + if [ "$CXX" = "clang++" ]; then + # $PATH needs to be adjusted because the llvm tap doesn't install the + # package to /usr/local/bin, etc, like the gcc tap does. + # See: https://github.com/Homebrew/legacy-homebrew/issues/29733 + clang_version=3.9 + export PATH="/usr/local/opt/llvm@${clang_version}/bin:$PATH"; + fi +fi diff --git a/ci/get-nprocessors.sh b/ci/get-nprocessors.sh new file mode 100755 index 00000000..43635e76 --- /dev/null +++ b/ci/get-nprocessors.sh @@ -0,0 +1,48 @@ +#!/usr/bin/env bash +# Copyright 2017 Google Inc. +# All Rights Reserved. +# +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above +# copyright notice, this list of conditions and the following disclaimer +# in the documentation and/or other materials provided with the +# distribution. +# * Neither the name of Google Inc. nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +# This file is typically sourced by another script. +# if possible, ask for the precise number of processors, +# otherwise take 2 processors as reasonable default; see +# https://docs.travis-ci.com/user/speeding-up-the-build/#Makefile-optimization +if [ -x /usr/bin/getconf ]; then + NPROCESSORS=$(/usr/bin/getconf _NPROCESSORS_ONLN) +else + NPROCESSORS=2 +fi + +# as of 2017-09-04 Travis CI reports 32 processors, but GCC build +# crashes if parallelized too much (maybe memory consumption problem), +# so limit to 4 processors for the time being. +if [ $NPROCESSORS -gt 4 ] ; then + echo "$0:Note: Limiting processors to use by make from $NPROCESSORS to 4." + NPROCESSORS=4 +fi diff --git a/ci/install-linux.sh b/ci/install-linux.sh new file mode 100755 index 00000000..05e2cb28 --- /dev/null +++ b/ci/install-linux.sh @@ -0,0 +1,49 @@ +#!/usr/bin/env bash +# Copyright 2017 Google Inc. +# All Rights Reserved. +# +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above +# copyright notice, this list of conditions and the following disclaimer +# in the documentation and/or other materials provided with the +# distribution. +# * Neither the name of Google Inc. nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +set -eu + +if [ "${TRAVIS_OS_NAME}" != linux ]; then + echo "Not a Linux build; skipping installation" + exit 0 +fi + + +if [ "${TRAVIS_SUDO}" = "true" ]; then + echo "deb [arch=amd64] http://storage.googleapis.com/bazel-apt stable jdk1.8" | \ + sudo tee /etc/apt/sources.list.d/bazel.list + curl https://bazel.build/bazel-release.pub.gpg | sudo apt-key add - + sudo apt-get update && sudo apt-get install -y bazel gcc-4.9 g++-4.9 clang-3.9 +elif [ "${CXX}" = "clang++" ]; then + # Use ccache, assuming $HOME/bin is in the path, which is true in the Travis build environment. + ln -sf /usr/bin/ccache $HOME/bin/${CXX}; + ln -sf /usr/bin/ccache $HOME/bin/${CC}; +fi diff --git a/ci/install-osx.sh b/ci/install-osx.sh new file mode 100755 index 00000000..f2baebd2 --- /dev/null +++ b/ci/install-osx.sh @@ -0,0 +1,40 @@ +#!/usr/bin/env bash +# Copyright 2017 Google Inc. +# All Rights Reserved. +# +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above +# copyright notice, this list of conditions and the following disclaimer +# in the documentation and/or other materials provided with the +# distribution. +# * Neither the name of Google Inc. nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +set -eu + +if [ "${TRAVIS_OS_NAME}" != "osx" ]; then + echo "Not a macOS build; skipping installation" + exit 0 +fi + +brew update +brew install ccache gcc@4.9 llvm@3.9 diff --git a/ci/install-platformio.sh b/ci/install-platformio.sh new file mode 100644 index 00000000..4d7860a5 --- /dev/null +++ b/ci/install-platformio.sh @@ -0,0 +1,5 @@ +# install PlatformIO +sudo pip install -U platformio + +# update PlatformIO +platformio update diff --git a/ci/log-config.sh b/ci/log-config.sh new file mode 100755 index 00000000..5fef1194 --- /dev/null +++ b/ci/log-config.sh @@ -0,0 +1,51 @@ +#!/usr/bin/env bash +# Copyright 2017 Google Inc. +# All Rights Reserved. +# +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above +# copyright notice, this list of conditions and the following disclaimer +# in the documentation and/or other materials provided with the +# distribution. +# * Neither the name of Google Inc. nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +set -e + +# ccache on OS X needs installation first +# reset ccache statistics +ccache --zero-stats + +echo PATH=${PATH} + +echo "Compiler configuration:" +echo CXX=${CXX} +echo CC=${CC} +echo CXXFLAGS=${CXXFLAGS} + +echo "C++ compiler version:" +${CXX} --version || echo "${CXX} does not seem to support the --version flag" +${CXX} -v || echo "${CXX} does not seem to support the -v flag" + +echo "C compiler version:" +${CC} --version || echo "${CXX} does not seem to support the --version flag" +${CC} -v || echo "${CXX} does not seem to support the -v flag" diff --git a/ci/travis.sh b/ci/travis.sh new file mode 100755 index 00000000..9ff3bad3 --- /dev/null +++ b/ci/travis.sh @@ -0,0 +1,44 @@ +#!/usr/bin/env sh +set -evx + +. ci/get-nprocessors.sh + +# if possible, ask for the precise number of processors, +# otherwise take 2 processors as reasonable default; see +# https://docs.travis-ci.com/user/speeding-up-the-build/#Makefile-optimization +if [ -x /usr/bin/getconf ]; then + NPROCESSORS=$(/usr/bin/getconf _NPROCESSORS_ONLN) +else + NPROCESSORS=2 +fi +# as of 2017-09-04 Travis CI reports 32 processors, but GCC build +# crashes if parallelized too much (maybe memory consumption problem), +# so limit to 4 processors for the time being. +if [ $NPROCESSORS -gt 4 ] ; then + echo "$0:Note: Limiting processors to use by make from $NPROCESSORS to 4." + NPROCESSORS=4 +fi +# Tell make to use the processors. No preceding '-' required. +MAKEFLAGS="j${NPROCESSORS}" +export MAKEFLAGS + +env | sort + +# Set default values to OFF for these variables if not specified. +: "${NO_EXCEPTION:=OFF}" +: "${NO_RTTI:=OFF}" +: "${COMPILER_IS_GNUCXX:=OFF}" + +mkdir build || true +cd build +cmake -Dgtest_build_samples=ON \ + -Dgtest_build_tests=ON \ + -Dgmock_build_tests=ON \ + -Dcxx_no_exception=$NO_EXCEPTION \ + -Dcxx_no_rtti=$NO_RTTI \ + -DCMAKE_COMPILER_IS_GNUCXX=$COMPILER_IS_GNUCXX \ + -DCMAKE_CXX_FLAGS=$CXX_FLAGS \ + -DCMAKE_BUILD_TYPE=$BUILD_TYPE \ + .. +make +CTEST_OUTPUT_ON_FAILURE=1 make test diff --git a/googlemock/CMakeLists.txt b/googlemock/CMakeLists.txt new file mode 100644 index 00000000..d32b70b5 --- /dev/null +++ b/googlemock/CMakeLists.txt @@ -0,0 +1,233 @@ +######################################################################## +# Note: CMake support is community-based. The maintainers do not use CMake +# internally. +# +# CMake build script for Google Mock. +# +# To run the tests for Google Mock itself on Linux, use 'make test' or +# ctest. You can select which tests to run using 'ctest -R regex'. +# For more options, run 'ctest --help'. + +option(gmock_build_tests "Build all of Google Mock's own tests." OFF) + +# A directory to find Google Test sources. +if (EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/gtest/CMakeLists.txt") + set(gtest_dir gtest) +else() + set(gtest_dir ../googletest) +endif() + +# Defines pre_project_set_up_hermetic_build() and set_up_hermetic_build(). +include("${gtest_dir}/cmake/hermetic_build.cmake" OPTIONAL) + +if (COMMAND pre_project_set_up_hermetic_build) + # Google Test also calls hermetic setup functions from add_subdirectory, + # although its changes will not affect things at the current scope. + pre_project_set_up_hermetic_build() +endif() + +######################################################################## +# +# Project-wide settings + +# Name of the project. +# +# CMake files in this project can refer to the root source directory +# as ${gmock_SOURCE_DIR} and to the root binary directory as +# ${gmock_BINARY_DIR}. +# Language "C" is required for find_package(Threads). +if (CMAKE_VERSION VERSION_LESS 3.0) + project(gmock CXX C) +else() + cmake_policy(SET CMP0048 NEW) + project(gmock VERSION ${GOOGLETEST_VERSION} LANGUAGES CXX C) +endif() +cmake_minimum_required(VERSION 2.6.4) + +if (COMMAND set_up_hermetic_build) + set_up_hermetic_build() +endif() + +# Instructs CMake to process Google Test's CMakeLists.txt and add its +# targets to the current scope. We are placing Google Test's binary +# directory in a subdirectory of our own as VC compilation may break +# if they are the same (the default). +add_subdirectory("${gtest_dir}" "${gmock_BINARY_DIR}/${gtest_dir}") + + +# These commands only run if this is the main project +if(CMAKE_PROJECT_NAME STREQUAL "gmock" OR CMAKE_PROJECT_NAME STREQUAL "googletest-distribution") + # BUILD_SHARED_LIBS is a standard CMake variable, but we declare it here to + # make it prominent in the GUI. + option(BUILD_SHARED_LIBS "Build shared libraries (DLLs)." OFF) +else() + mark_as_advanced(gmock_build_tests) +endif() + +# Although Google Test's CMakeLists.txt calls this function, the +# changes there don't affect the current scope. Therefore we have to +# call it again here. +config_compiler_and_linker() # from ${gtest_dir}/cmake/internal_utils.cmake + +# Adds Google Mock's and Google Test's header directories to the search path. +set(gmock_build_include_dirs + "${gmock_SOURCE_DIR}/include" + "${gmock_SOURCE_DIR}" + "${gtest_SOURCE_DIR}/include" + # This directory is needed to build directly from Google Test sources. + "${gtest_SOURCE_DIR}") +include_directories(${gmock_build_include_dirs}) + +######################################################################## +# +# Defines the gmock & gmock_main libraries. User tests should link +# with one of them. + +# Google Mock libraries. We build them using more strict warnings than what +# are used for other targets, to ensure that Google Mock can be compiled by +# a user aggressive about warnings. +if (MSVC) + cxx_library(gmock + "${cxx_strict}" + "${gtest_dir}/src/gtest-all.cc" + src/gmock-all.cc) + + cxx_library(gmock_main + "${cxx_strict}" + "${gtest_dir}/src/gtest-all.cc" + src/gmock-all.cc + src/gmock_main.cc) +else() + cxx_library(gmock "${cxx_strict}" src/gmock-all.cc) + target_link_libraries(gmock PUBLIC gtest) + cxx_library(gmock_main "${cxx_strict}" src/gmock_main.cc) + target_link_libraries(gmock_main PUBLIC gmock) +endif() +# If the CMake version supports it, attach header directory information +# to the targets for when we are part of a parent build (ie being pulled +# in via add_subdirectory() rather than being a standalone build). +if (DEFINED CMAKE_VERSION AND NOT "${CMAKE_VERSION}" VERSION_LESS "2.8.11") + target_include_directories(gmock SYSTEM INTERFACE + "$" + "$/${CMAKE_INSTALL_INCLUDEDIR}>") + target_include_directories(gmock_main SYSTEM INTERFACE + "$" + "$/${CMAKE_INSTALL_INCLUDEDIR}>") +endif() + +######################################################################## +# +# Install rules +install_project(gmock gmock_main) + +######################################################################## +# +# Google Mock's own tests. +# +# You can skip this section if you aren't interested in testing +# Google Mock itself. +# +# The tests are not built by default. To build them, set the +# gmock_build_tests option to ON. You can do it by running ccmake +# or specifying the -Dgmock_build_tests=ON flag when running cmake. + +if (gmock_build_tests) + # This must be set in the root directory for the tests to be run by + # 'make test' or ctest. + enable_testing() + + if (WIN32) + file(GENERATE OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/$/RunTest.ps1" + CONTENT +"$project_bin = \"${CMAKE_BINARY_DIR}/bin/$\" +$env:Path = \"$project_bin;$env:Path\" +& $args") + elseif (MINGW OR CYGWIN) + file(GENERATE OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/RunTest.ps1" + CONTENT +"$project_bin = (cygpath --windows ${CMAKE_BINARY_DIR}/bin) +$env:Path = \"$project_bin;$env:Path\" +& $args") + endif() + + if (MINGW OR CYGWIN) + if (CMAKE_VERSION VERSION_LESS "2.8.12") + add_compile_options("-Wa,-mbig-obj") + else() + add_definitions("-Wa,-mbig-obj") + endif() + endif() + + ############################################################ + # C++ tests built with standard compiler flags. + + cxx_test(gmock-actions_test gmock_main) + cxx_test(gmock-cardinalities_test gmock_main) + cxx_test(gmock_ex_test gmock_main) + cxx_test(gmock-function-mocker_test gmock_main) + cxx_test(gmock-generated-actions_test gmock_main) + cxx_test(gmock-generated-function-mockers_test gmock_main) + cxx_test(gmock-generated-matchers_test gmock_main) + cxx_test(gmock-internal-utils_test gmock_main) + cxx_test(gmock-matchers_test gmock_main) + cxx_test(gmock-more-actions_test gmock_main) + cxx_test(gmock-nice-strict_test gmock_main) + cxx_test(gmock-port_test gmock_main) + cxx_test(gmock-spec-builders_test gmock_main) + cxx_test(gmock_link_test gmock_main test/gmock_link2_test.cc) + cxx_test(gmock_test gmock_main) + + if (DEFINED GTEST_HAS_PTHREAD) + cxx_test(gmock_stress_test gmock) + endif() + + # gmock_all_test is commented to save time building and running tests. + # Uncomment if necessary. + # cxx_test(gmock_all_test gmock_main) + + ############################################################ + # C++ tests built with non-standard compiler flags. + + if (MSVC) + cxx_library(gmock_main_no_exception "${cxx_no_exception}" + "${gtest_dir}/src/gtest-all.cc" src/gmock-all.cc src/gmock_main.cc) + + cxx_library(gmock_main_no_rtti "${cxx_no_rtti}" + "${gtest_dir}/src/gtest-all.cc" src/gmock-all.cc src/gmock_main.cc) + + else() + cxx_library(gmock_main_no_exception "${cxx_no_exception}" src/gmock_main.cc) + target_link_libraries(gmock_main_no_exception PUBLIC gmock) + + cxx_library(gmock_main_no_rtti "${cxx_no_rtti}" src/gmock_main.cc) + target_link_libraries(gmock_main_no_rtti PUBLIC gmock) + endif() + cxx_test_with_flags(gmock-more-actions_no_exception_test "${cxx_no_exception}" + gmock_main_no_exception test/gmock-more-actions_test.cc) + + cxx_test_with_flags(gmock_no_rtti_test "${cxx_no_rtti}" + gmock_main_no_rtti test/gmock-spec-builders_test.cc) + + cxx_shared_library(shared_gmock_main "${cxx_default}" + "${gtest_dir}/src/gtest-all.cc" src/gmock-all.cc src/gmock_main.cc) + + # Tests that a binary can be built with Google Mock as a shared library. On + # some system configurations, it may not possible to run the binary without + # knowing more details about the system configurations. We do not try to run + # this binary. To get a more robust shared library coverage, configure with + # -DBUILD_SHARED_LIBS=ON. + cxx_executable_with_flags(shared_gmock_test_ "${cxx_default}" + shared_gmock_main test/gmock-spec-builders_test.cc) + set_target_properties(shared_gmock_test_ + PROPERTIES + COMPILE_DEFINITIONS "GTEST_LINKED_AS_SHARED_LIBRARY=1") + + ############################################################ + # Python tests. + + cxx_executable(gmock_leak_test_ test gmock_main) + py_test(gmock_leak_test) + + cxx_executable(gmock_output_test_ test gmock) + py_test(gmock_output_test) +endif() diff --git a/googlemock/CONTRIBUTORS b/googlemock/CONTRIBUTORS new file mode 100644 index 00000000..6e9ae362 --- /dev/null +++ b/googlemock/CONTRIBUTORS @@ -0,0 +1,40 @@ +# This file contains a list of people who've made non-trivial +# contribution to the Google C++ Mocking Framework project. People +# who commit code to the project are encouraged to add their names +# here. Please keep the list sorted by first names. + +Benoit Sigoure +Bogdan Piloca +Chandler Carruth +Dave MacLachlan +David Anderson +Dean Sturtevant +Gene Volovich +Hal Burch +Jeffrey Yasskin +Jim Keller +Joe Walnes +Jon Wray +Keir Mierle +Keith Ray +Kostya Serebryany +Lev Makhlis +Manuel Klimek +Mario Tanev +Mark Paskin +Markus Heule +Matthew Simmons +Mike Bland +Neal Norwitz +Nermin Ozkiranartli +Owen Carlsen +Paneendra Ba +Paul Menage +Piotr Kaminski +Russ Rufer +Sverre Sundsdal +Takeshi Yoshino +Vadim Berman +Vlad Losev +Wolfgang Klier +Zhanyong Wan diff --git a/googlemock/LICENSE b/googlemock/LICENSE new file mode 100644 index 00000000..1941a11f --- /dev/null +++ b/googlemock/LICENSE @@ -0,0 +1,28 @@ +Copyright 2008, Google Inc. +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the following disclaimer +in the documentation and/or other materials provided with the +distribution. + * Neither the name of Google Inc. nor the names of its +contributors may be used to endorse or promote products derived from +this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/googlemock/README.md b/googlemock/README.md new file mode 100644 index 00000000..183fdb81 --- /dev/null +++ b/googlemock/README.md @@ -0,0 +1,44 @@ +# Googletest Mocking (gMock) Framework + +### Overview + +Google's framework for writing and using C++ mock classes. It can help you +derive better designs of your system and write better tests. + +It is inspired by: + +* [jMock](http://www.jmock.org/), +* [EasyMock](http://www.easymock.org/), and +* [Hamcrest](http://code.google.com/p/hamcrest/), + +and designed with C++'s specifics in mind. + +gMock: + +- provides a declarative syntax for defining mocks, +- can define partial (hybrid) mocks, which are a cross of real and mock + objects, +- handles functions of arbitrary types and overloaded functions, +- comes with a rich set of matchers for validating function arguments, +- uses an intuitive syntax for controlling the behavior of a mock, +- does automatic verification of expectations (no record-and-replay needed), +- allows arbitrary (partial) ordering constraints on function calls to be + expressed, +- lets a user extend it by defining new matchers and actions. +- does not use exceptions, and +- is easy to learn and use. + +Details and examples can be found here: + +* [gMock for Dummies](docs/for_dummies.md) +* [Legacy gMock FAQ](docs/gmock_faq.md) +* [gMock Cookbook](docs/cook_book.md) +* [gMock Cheat Sheet](docs/cheat_sheet.md) + +Please note that code under scripts/generator/ is from the [cppclean +project](http://code.google.com/p/cppclean/) and under the Apache +License, which is different from Google Mock's license. + +Google Mock is a part of +[Google Test C++ testing framework](http://github.com/google/googletest/) and a +subject to the same requirements. diff --git a/googlemock/cmake/gmock.pc.in b/googlemock/cmake/gmock.pc.in new file mode 100644 index 00000000..08e04547 --- /dev/null +++ b/googlemock/cmake/gmock.pc.in @@ -0,0 +1,11 @@ +prefix=${pcfiledir}/../.. +libdir=${prefix}/@CMAKE_INSTALL_LIBDIR@ +includedir=${prefix}/@CMAKE_INSTALL_INCLUDEDIR@ + +Name: gmock +Description: GoogleMock (without main() function) +Version: @PROJECT_VERSION@ +URL: https://github.com/google/googletest +Requires: gtest +Libs: -L${libdir} -lgmock @CMAKE_THREAD_LIBS_INIT@ +Cflags: -I${includedir} @GTEST_HAS_PTHREAD_MACRO@ @CMAKE_THREAD_LIBS_INIT@ diff --git a/googlemock/cmake/gmock_main.pc.in b/googlemock/cmake/gmock_main.pc.in new file mode 100644 index 00000000..b22fe614 --- /dev/null +++ b/googlemock/cmake/gmock_main.pc.in @@ -0,0 +1,11 @@ +prefix=${pcfiledir}/../.. +libdir=${prefix}/@CMAKE_INSTALL_LIBDIR@ +includedir=${prefix}/@CMAKE_INSTALL_INCLUDEDIR@ + +Name: gmock_main +Description: GoogleMock (with main() function) +Version: @PROJECT_VERSION@ +URL: https://github.com/google/googletest +Requires: gmock +Libs: -L${libdir} -lgmock_main @CMAKE_THREAD_LIBS_INIT@ +Cflags: -I${includedir} @GTEST_HAS_PTHREAD_MACRO@ @CMAKE_THREAD_LIBS_INIT@ diff --git a/googlemock/docs/cheat_sheet.md b/googlemock/docs/cheat_sheet.md new file mode 100644 index 00000000..239a4c6d --- /dev/null +++ b/googlemock/docs/cheat_sheet.md @@ -0,0 +1,770 @@ +## gMock Cheat Sheet + + + + + +### Defining a Mock Class + +#### Mocking a Normal Class {#MockClass} + +Given + +```cpp +class Foo { + ... + virtual ~Foo(); + virtual int GetSize() const = 0; + virtual string Describe(const char* name) = 0; + virtual string Describe(int type) = 0; + virtual bool Process(Bar elem, int count) = 0; +}; +``` + +(note that `~Foo()` **must** be virtual) we can define its mock as + +```cpp +#include "gmock/gmock.h" + +class MockFoo : public Foo { + ... + MOCK_METHOD(int, GetSize, (), (const, override)); + MOCK_METHOD(string, Describe, (const char* name), (override)); + MOCK_METHOD(string, Describe, (int type), (override)); + MOCK_METHOD(bool, Process, (Bar elem, int count), (override)); +}; +``` + +To create a "nice" mock, which ignores all uninteresting calls, a "naggy" mock, +which warns on all uninteresting calls, or a "strict" mock, which treats them as +failures: + +```cpp +using ::testing::NiceMock; +using ::testing::NaggyMock; +using ::testing::StrictMock; + +NiceMock nice_foo; // The type is a subclass of MockFoo. +NaggyMock naggy_foo; // The type is a subclass of MockFoo. +StrictMock strict_foo; // The type is a subclass of MockFoo. +``` + +**Note:** A mock object is currently naggy by default. We may make it nice by +default in the future. + +#### Mocking a Class Template {#MockTemplate} + +Class templates can be mocked just like any class. + +To mock + +```cpp +template +class StackInterface { + ... + virtual ~StackInterface(); + virtual int GetSize() const = 0; + virtual void Push(const Elem& x) = 0; +}; +``` + +(note that all member functions that are mocked, including `~StackInterface()` +**must** be virtual). + +```cpp +template +class MockStack : public StackInterface { + ... + MOCK_METHOD(int, GetSize, (), (const, override)); + MOCK_METHOD(void, Push, (const Elem& x), (override)); +}; +``` + +#### Specifying Calling Conventions for Mock Functions + +If your mock function doesn't use the default calling convention, you can +specify it by adding `Calltype(convention)` to `MOCK_METHOD`'s 4th parameter. +For example, + +```cpp + MOCK_METHOD(bool, Foo, (int n), (Calltype(STDMETHODCALLTYPE))); + MOCK_METHOD(int, Bar, (double x, double y), + (const, Calltype(STDMETHODCALLTYPE))); +``` + +where `STDMETHODCALLTYPE` is defined by `` on Windows. + +### Using Mocks in Tests {#UsingMocks} + +The typical work flow is: + +1. Import the gMock names you need to use. All gMock symbols are in the + `testing` namespace unless they are macros or otherwise noted. +2. Create the mock objects. +3. Optionally, set the default actions of the mock objects. +4. Set your expectations on the mock objects (How will they be called? What + will they do?). +5. Exercise code that uses the mock objects; if necessary, check the result + using googletest assertions. +6. When a mock object is destructed, gMock automatically verifies that all + expectations on it have been satisfied. + +Here's an example: + +```cpp +using ::testing::Return; // #1 + +TEST(BarTest, DoesThis) { + MockFoo foo; // #2 + + ON_CALL(foo, GetSize()) // #3 + .WillByDefault(Return(1)); + // ... other default actions ... + + EXPECT_CALL(foo, Describe(5)) // #4 + .Times(3) + .WillRepeatedly(Return("Category 5")); + // ... other expectations ... + + EXPECT_EQ("good", MyProductionFunction(&foo)); // #5 +} // #6 +``` + +### Setting Default Actions {#OnCall} + +gMock has a **built-in default action** for any function that returns `void`, +`bool`, a numeric value, or a pointer. In C++11, it will additionally returns +the default-constructed value, if one exists for the given type. + +To customize the default action for functions with return type *`T`*: + +```cpp +using ::testing::DefaultValue; + +// Sets the default value to be returned. T must be CopyConstructible. +DefaultValue::Set(value); +// Sets a factory. Will be invoked on demand. T must be MoveConstructible. +// T MakeT(); +DefaultValue::SetFactory(&MakeT); +// ... use the mocks ... +// Resets the default value. +DefaultValue::Clear(); +``` + +Example usage: + +```cpp + // Sets the default action for return type std::unique_ptr to + // creating a new Buzz every time. + DefaultValue>::SetFactory( + [] { return MakeUnique(AccessLevel::kInternal); }); + + // When this fires, the default action of MakeBuzz() will run, which + // will return a new Buzz object. + EXPECT_CALL(mock_buzzer_, MakeBuzz("hello")).Times(AnyNumber()); + + auto buzz1 = mock_buzzer_.MakeBuzz("hello"); + auto buzz2 = mock_buzzer_.MakeBuzz("hello"); + EXPECT_NE(nullptr, buzz1); + EXPECT_NE(nullptr, buzz2); + EXPECT_NE(buzz1, buzz2); + + // Resets the default action for return type std::unique_ptr, + // to avoid interfere with other tests. + DefaultValue>::Clear(); +``` + +To customize the default action for a particular method of a specific mock +object, use `ON_CALL()`. `ON_CALL()` has a similar syntax to `EXPECT_CALL()`, +but it is used for setting default behaviors (when you do not require that the +mock method is called). See [here](cook_book.md#UseOnCall) for a more detailed +discussion. + +```cpp +ON_CALL(mock-object, method(matchers)) + .With(multi-argument-matcher) ? + .WillByDefault(action); +``` + +### Setting Expectations {#ExpectCall} + +`EXPECT_CALL()` sets **expectations** on a mock method (How will it be called? +What will it do?): + +```cpp +EXPECT_CALL(mock-object, method (matchers)?) + .With(multi-argument-matcher) ? + .Times(cardinality) ? + .InSequence(sequences) * + .After(expectations) * + .WillOnce(action) * + .WillRepeatedly(action) ? + .RetiresOnSaturation(); ? +``` + +If `(matchers)` is omitted, the expectation is the same as if the matchers were +set to anything matchers (for example, `(_, _, _, _)` for a four-arg method). + +If `Times()` is omitted, the cardinality is assumed to be: + +* `Times(1)` when there is neither `WillOnce()` nor `WillRepeatedly()`; +* `Times(n)` when there are `n` `WillOnce()`s but no `WillRepeatedly()`, where + `n` >= 1; or +* `Times(AtLeast(n))` when there are `n` `WillOnce()`s and a + `WillRepeatedly()`, where `n` >= 0. + +A method with no `EXPECT_CALL()` is free to be invoked *any number of times*, +and the default action will be taken each time. + +### Matchers {#MatcherList} + + + +A **matcher** matches a *single* argument. You can use it inside `ON_CALL()` or +`EXPECT_CALL()`, or use it to validate a value directly: + + +| Matcher | Description | +| :----------------------------------- | :------------------------------------ | +| `EXPECT_THAT(actual_value, matcher)` | Asserts that `actual_value` matches `matcher`. | +| `ASSERT_THAT(actual_value, matcher)` | The same as `EXPECT_THAT(actual_value, matcher)`, except that it generates a **fatal** failure. | + + +Built-in matchers (where `argument` is the function argument) are divided into +several categories: + +#### Wildcard + +Matcher | Description +:-------------------------- | :----------------------------------------------- +`_` | `argument` can be any value of the correct type. +`A()` or `An()` | `argument` can be any value of type `type`. + +#### Generic Comparison + + +| Matcher | Description | +| :--------------------- | :-------------------------------------------------- | +| `Eq(value)` or `value` | `argument == value` | +| `Ge(value)` | `argument >= value` | +| `Gt(value)` | `argument > value` | +| `Le(value)` | `argument <= value` | +| `Lt(value)` | `argument < value` | +| `Ne(value)` | `argument != value` | +| `IsNull()` | `argument` is a `NULL` pointer (raw or smart). | +| `NotNull()` | `argument` is a non-null pointer (raw or smart). | +| `Optional(m)` | `argument` is `optional<>` that contains a value matching `m`. | +| `VariantWith(m)` | `argument` is `variant<>` that holds the alternative of type T with a value matching `m`. | +| `Ref(variable)` | `argument` is a reference to `variable`. | +| `TypedEq(value)` | `argument` has type `type` and is equal to `value`. You may need to use this instead of `Eq(value)` when the mock function is overloaded. | + + +Except `Ref()`, these matchers make a *copy* of `value` in case it's modified or +destructed later. If the compiler complains that `value` doesn't have a public +copy constructor, try wrap it in `ByRef()`, e.g. +`Eq(ByRef(non_copyable_value))`. If you do that, make sure `non_copyable_value` +is not changed afterwards, or the meaning of your matcher will be changed. + +#### Floating-Point Matchers {#FpMatchers} + + +| Matcher | Description | +| :------------------------------- | :--------------------------------- | +| `DoubleEq(a_double)` | `argument` is a `double` value approximately equal to `a_double`, treating two NaNs as unequal. | +| `FloatEq(a_float)` | `argument` is a `float` value approximately equal to `a_float`, treating two NaNs as unequal. | +| `NanSensitiveDoubleEq(a_double)` | `argument` is a `double` value approximately equal to `a_double`, treating two NaNs as equal. | +| `NanSensitiveFloatEq(a_float)` | `argument` is a `float` value approximately equal to `a_float`, treating two NaNs as equal. | + + +The above matchers use ULP-based comparison (the same as used in googletest). +They automatically pick a reasonable error bound based on the absolute value of +the expected value. `DoubleEq()` and `FloatEq()` conform to the IEEE standard, +which requires comparing two NaNs for equality to return false. The +`NanSensitive*` version instead treats two NaNs as equal, which is often what a +user wants. + + +| Matcher | Description | +| :------------------------------------------------ | :----------------------- | +| `DoubleNear(a_double, max_abs_error)` | `argument` is a `double` value close to `a_double` (absolute error <= `max_abs_error`), treating two NaNs as unequal. | +| `FloatNear(a_float, max_abs_error)` | `argument` is a `float` value close to `a_float` (absolute error <= `max_abs_error`), treating two NaNs as unequal. | +| `NanSensitiveDoubleNear(a_double, max_abs_error)` | `argument` is a `double` value close to `a_double` (absolute error <= `max_abs_error`), treating two NaNs as equal. | +| `NanSensitiveFloatNear(a_float, max_abs_error)` | `argument` is a `float` value close to `a_float` (absolute error <= `max_abs_error`), treating two NaNs as equal. | + + +#### String Matchers + +The `argument` can be either a C string or a C++ string object: + + +| Matcher | Description | +| :---------------------- | :------------------------------------------------- | +| `ContainsRegex(string)` | `argument` matches the given regular expression. | +| `EndsWith(suffix)` | `argument` ends with string `suffix`. | +| `HasSubstr(string)` | `argument` contains `string` as a sub-string. | +| `MatchesRegex(string)` | `argument` matches the given regular expression with the match starting at the first character and ending at the last character. | +| `StartsWith(prefix)` | `argument` starts with string `prefix`. | +| `StrCaseEq(string)` | `argument` is equal to `string`, ignoring case. | +| `StrCaseNe(string)` | `argument` is not equal to `string`, ignoring case. | +| `StrEq(string)` | `argument` is equal to `string`. | +| `StrNe(string)` | `argument` is not equal to `string`. | + + +`ContainsRegex()` and `MatchesRegex()` take ownership of the `RE` object. They +use the regular expression syntax defined +[here](../../googletest/docs/advanced.md#regular-expression-syntax). +`StrCaseEq()`, `StrCaseNe()`, `StrEq()`, and `StrNe()` work for wide strings as +well. + +#### Container Matchers + +Most STL-style containers support `==`, so you can use `Eq(expected_container)` +or simply `expected_container` to match a container exactly. If you want to +write the elements in-line, match them more flexibly, or get more informative +messages, you can use: + + +| Matcher | Description | +| :---------------------------------------- | :------------------------------- | +| `BeginEndDistanceIs(m)` | `argument` is a container whose `begin()` and `end()` iterators are separated by a number of increments matching `m`. E.g. `BeginEndDistanceIs(2)` or `BeginEndDistanceIs(Lt(2))`. For containers that define a `size()` method, `SizeIs(m)` may be more efficient. | +| `ContainerEq(container)` | The same as `Eq(container)` except that the failure message also includes which elements are in one container but not the other. | +| `Contains(e)` | `argument` contains an element that matches `e`, which can be either a value or a matcher. | +| `Each(e)` | `argument` is a container where *every* element matches `e`, which can be either a value or a matcher. | +| `ElementsAre(e0, e1, ..., en)` | `argument` has `n + 1` elements, where the *i*-th element matches `ei`, which can be a value or a matcher. | +| `ElementsAreArray({e0, e1, ..., en})`, `ElementsAreArray(a_container)`, `ElementsAreArray(begin, end)`, `ElementsAreArray(array)`, or `ElementsAreArray(array, count)` | The same as `ElementsAre()` except that the expected element values/matchers come from an initializer list, STL-style container, iterator range, or C-style array. | +| `IsEmpty()` | `argument` is an empty container (`container.empty()`). | +| `IsFalse()` | `argument` evaluates to `false` in a Boolean context. | +| `IsSubsetOf({e0, e1, ..., en})`, `IsSubsetOf(a_container)`, `IsSubsetOf(begin, end)`, `IsSubsetOf(array)`, or `IsSubsetOf(array, count)` | `argument` matches `UnorderedElementsAre(x0, x1, ..., xk)` for some subset `{x0, x1, ..., xk}` of the expected matchers. | +| `IsSupersetOf({e0, e1, ..., en})`, `IsSupersetOf(a_container)`, `IsSupersetOf(begin, end)`, `IsSupersetOf(array)`, or `IsSupersetOf(array, count)` | Some subset of `argument` matches `UnorderedElementsAre(`expected matchers`)`. | +| `IsTrue()` | `argument` evaluates to `true` in a Boolean context. | +| `Pointwise(m, container)`, `Pointwise(m, {e0, e1, ..., en})` | `argument` contains the same number of elements as in `container`, and for all i, (the i-th element in `argument`, the i-th element in `container`) match `m`, which is a matcher on 2-tuples. E.g. `Pointwise(Le(), upper_bounds)` verifies that each element in `argument` doesn't exceed the corresponding element in `upper_bounds`. See more detail below. | +| `SizeIs(m)` | `argument` is a container whose size matches `m`. E.g. `SizeIs(2)` or `SizeIs(Lt(2))`. | +| `UnorderedElementsAre(e0, e1, ..., en)` | `argument` has `n + 1` elements, and under *some* permutation of the elements, each element matches an `ei` (for a different `i`), which can be a value or a matcher. | +| `UnorderedElementsAreArray({e0, e1, ..., en})`, `UnorderedElementsAreArray(a_container)`, `UnorderedElementsAreArray(begin, end)`, `UnorderedElementsAreArray(array)`, or `UnorderedElementsAreArray(array, count)` | The same as `UnorderedElementsAre()` except that the expected element values/matchers come from an initializer list, STL-style container, iterator range, or C-style array. | +| `UnorderedPointwise(m, container)`, `UnorderedPointwise(m, {e0, e1, ..., en})` | Like `Pointwise(m, container)`, but ignores the order of elements. | +| `WhenSorted(m)` | When `argument` is sorted using the `<` operator, it matches container matcher `m`. E.g. `WhenSorted(ElementsAre(1, 2, 3))` verifies that `argument` contains elements 1, 2, and 3, ignoring order. | +| `WhenSortedBy(comparator, m)` | The same as `WhenSorted(m)`, except that the given comparator instead of `<` is used to sort `argument`. E.g. `WhenSortedBy(std::greater(), ElementsAre(3, 2, 1))`. | + + +**Notes:** + +* These matchers can also match: + 1. a native array passed by reference (e.g. in `Foo(const int (&a)[5])`), + and + 2. an array passed as a pointer and a count (e.g. in `Bar(const T* buffer, + int len)` -- see [Multi-argument Matchers](#MultiArgMatchers)). +* The array being matched may be multi-dimensional (i.e. its elements can be + arrays). +* `m` in `Pointwise(m, ...)` should be a matcher for `::std::tuple` + where `T` and `U` are the element type of the actual container and the + expected container, respectively. For example, to compare two `Foo` + containers where `Foo` doesn't support `operator==`, one might write: + + ```cpp + using ::std::get; + MATCHER(FooEq, "") { + return std::get<0>(arg).Equals(std::get<1>(arg)); + } + ... + EXPECT_THAT(actual_foos, Pointwise(FooEq(), expected_foos)); + ``` + +#### Member Matchers + + +| Matcher | Description | +| :------------------------------ | :----------------------------------------- | +| `Field(&class::field, m)` | `argument.field` (or `argument->field` when `argument` is a plain pointer) matches matcher `m`, where `argument` is an object of type _class_. | +| `Key(e)` | `argument.first` matches `e`, which can be either a value or a matcher. E.g. `Contains(Key(Le(5)))` can verify that a `map` contains a key `<= 5`. | +| `Pair(m1, m2)` | `argument` is an `std::pair` whose `first` field matches `m1` and `second` field matches `m2`. | +| `Property(&class::property, m)` | `argument.property()` (or `argument->property()` when `argument` is a plain pointer) matches matcher `m`, where `argument` is an object of type _class_. | + + +#### Matching the Result of a Function, Functor, or Callback + + +| Matcher | Description | +| :--------------- | :------------------------------------------------ | +| `ResultOf(f, m)` | `f(argument)` matches matcher `m`, where `f` is a function or functor. | + + +#### Pointer Matchers + + +| Matcher | Description | +| :------------------------ | :---------------------------------------------- | +| `Pointee(m)` | `argument` (either a smart pointer or a raw pointer) points to a value that matches matcher `m`. | +| `WhenDynamicCastTo(m)` | when `argument` is passed through `dynamic_cast()`, it matches matcher `m`. | + + + + + + +#### Multi-argument Matchers {#MultiArgMatchers} + +Technically, all matchers match a *single* value. A "multi-argument" matcher is +just one that matches a *tuple*. The following matchers can be used to match a +tuple `(x, y)`: + +Matcher | Description +:------ | :---------- +`Eq()` | `x == y` +`Ge()` | `x >= y` +`Gt()` | `x > y` +`Le()` | `x <= y` +`Lt()` | `x < y` +`Ne()` | `x != y` + +You can use the following selectors to pick a subset of the arguments (or +reorder them) to participate in the matching: + + +| Matcher | Description | +| :------------------------- | :---------------------------------------------- | +| `AllArgs(m)` | Equivalent to `m`. Useful as syntactic sugar in `.With(AllArgs(m))`. | +| `Args(m)` | The tuple of the `k` selected (using 0-based indices) arguments matches `m`, e.g. `Args<1, 2>(Eq())`. | + + +#### Composite Matchers + +You can make a matcher from one or more other matchers: + + +| Matcher | Description | +| :------------------------------- | :-------------------------------------- | +| `AllOf(m1, m2, ..., mn)` | `argument` matches all of the matchers `m1` to `mn`. | +| `AllOfArray({m0, m1, ..., mn})`, `AllOfArray(a_container)`, `AllOfArray(begin, end)`, `AllOfArray(array)`, or `AllOfArray(array, count)` | The same as `AllOf()` except that the matchers come from an initializer list, STL-style container, iterator range, or C-style array. | +| `AnyOf(m1, m2, ..., mn)` | `argument` matches at least one of the matchers `m1` to `mn`. | +| `AnyOfArray({m0, m1, ..., mn})`, `AnyOfArray(a_container)`, `AnyOfArray(begin, end)`, `AnyOfArray(array)`, or `AnyOfArray(array, count)` | The same as `AnyOf()` except that the matchers come from an initializer list, STL-style container, iterator range, or C-style array. | +| `Not(m)` | `argument` doesn't match matcher `m`. | + + + + +#### Adapters for Matchers + + +| Matcher | Description | +| :---------------------- | :------------------------------------ | +| `MatcherCast(m)` | casts matcher `m` to type `Matcher`. | +| `SafeMatcherCast(m)` | [safely casts](cook_book.md#casting-matchers) matcher `m` to type `Matcher`. | +| `Truly(predicate)` | `predicate(argument)` returns something considered by C++ to be true, where `predicate` is a function or functor. | + + +`AddressSatisfies(callback)` and `Truly(callback)` take ownership of `callback`, +which must be a permanent callback. + +#### Using Matchers as Predicates {#MatchersAsPredicatesCheat} + + +| Matcher | Description | +| :---------------------------- | :------------------------------------------ | +| `Matches(m)(value)` | evaluates to `true` if `value` matches `m`. You can use `Matches(m)` alone as a unary functor. | +| `ExplainMatchResult(m, value, result_listener)` | evaluates to `true` if `value` matches `m`, explaining the result to `result_listener`. | +| `Value(value, m)` | evaluates to `true` if `value` matches `m`. | + + +#### Defining Matchers + + +| Matcher | Description | +| :----------------------------------- | :------------------------------------ | +| `MATCHER(IsEven, "") { return (arg % 2) == 0; }` | Defines a matcher `IsEven()` to match an even number. | +| `MATCHER_P(IsDivisibleBy, n, "") { *result_listener << "where the remainder is " << (arg % n); return (arg % n) == 0; }` | Defines a macher `IsDivisibleBy(n)` to match a number divisible by `n`. | +| `MATCHER_P2(IsBetween, a, b, std::string(negation ? "isn't" : "is") + " between " + PrintToString(a) + " and " + PrintToString(b)) { return a <= arg && arg <= b; }` | Defines a matcher `IsBetween(a, b)` to match a value in the range [`a`, `b`]. | + + +**Notes:** + +1. The `MATCHER*` macros cannot be used inside a function or class. +2. The matcher body must be *purely functional* (i.e. it cannot have any side + effect, and the result must not depend on anything other than the value + being matched and the matcher parameters). +3. You can use `PrintToString(x)` to convert a value `x` of any type to a + string. + +### Actions {#ActionList} + +**Actions** specify what a mock function should do when invoked. + +#### Returning a Value + + +| | | +| :-------------------------- | :-------------------------------------------- | +| `Return()` | Return from a `void` mock function. | +| `Return(value)` | Return `value`. If the type of `value` is different to the mock function's return type, `value` is converted to the latter type at the time the expectation is set, not when the action is executed. | +| `ReturnArg()` | Return the `N`-th (0-based) argument. | +| `ReturnNew(a1, ..., ak)` | Return `new T(a1, ..., ak)`; a different object is created each time. | +| `ReturnNull()` | Return a null pointer. | +| `ReturnPointee(ptr)` | Return the value pointed to by `ptr`. | +| `ReturnRef(variable)` | Return a reference to `variable`. | +| `ReturnRefOfCopy(value)` | Return a reference to a copy of `value`; the copy lives as long as the action. | + + +#### Side Effects + + +| | | +| :--------------------------------- | :-------------------------------------- | +| `Assign(&variable, value)` | Assign `value` to variable. | +| `DeleteArg()` | Delete the `N`-th (0-based) argument, which must be a pointer. | +| `SaveArg(pointer)` | Save the `N`-th (0-based) argument to `*pointer`. | +| `SaveArgPointee(pointer)` | Save the value pointed to by the `N`-th (0-based) argument to `*pointer`. | +| `SetArgReferee(value)` | Assign value to the variable referenced by the `N`-th (0-based) argument. | +| `SetArgPointee(value)` | Assign `value` to the variable pointed by the `N`-th (0-based) argument. | +| `SetArgumentPointee(value)` | Same as `SetArgPointee(value)`. Deprecated. Will be removed in v1.7.0. | +| `SetArrayArgument(first, last)` | Copies the elements in source range [`first`, `last`) to the array pointed to by the `N`-th (0-based) argument, which can be either a pointer or an iterator. The action does not take ownership of the elements in the source range. | +| `SetErrnoAndReturn(error, value)` | Set `errno` to `error` and return `value`. | +| `Throw(exception)` | Throws the given exception, which can be any copyable value. Available since v1.1.0. | + + +#### Using a Function, Functor, or Lambda as an Action + +In the following, by "callable" we mean a free function, `std::function`, +functor, or lambda. + + +| | | +| :---------------------------------- | :------------------------------------- | +| `f` | Invoke f with the arguments passed to the mock function, where f is a callable. | +| `Invoke(f)` | Invoke `f` with the arguments passed to the mock function, where `f` can be a global/static function or a functor. | +| `Invoke(object_pointer, &class::method)` | Invoke the method on the object with the arguments passed to the mock function. | +| `InvokeWithoutArgs(f)` | Invoke `f`, which can be a global/static function or a functor. `f` must take no arguments. | +| `InvokeWithoutArgs(object_pointer, &class::method)` | Invoke the method on the object, which takes no arguments. | +| `InvokeArgument(arg1, arg2, ..., argk)` | Invoke the mock function's `N`-th (0-based) argument, which must be a function or a functor, with the `k` arguments. | + + +The return value of the invoked function is used as the return value of the +action. + +When defining a callable to be used with `Invoke*()`, you can declare any unused +parameters as `Unused`: + +```cpp +using ::testing::Invoke; +double Distance(Unused, double x, double y) { return sqrt(x*x + y*y); } +... +EXPECT_CALL(mock, Foo("Hi", _, _)).WillOnce(Invoke(Distance)); +``` + +`Invoke(callback)` and `InvokeWithoutArgs(callback)` take ownership of +`callback`, which must be permanent. The type of `callback` must be a base +callback type instead of a derived one, e.g. + +```cpp + BlockingClosure* done = new BlockingClosure; + ... Invoke(done) ...; // This won't compile! + + Closure* done2 = new BlockingClosure; + ... Invoke(done2) ...; // This works. +``` + +In `InvokeArgument(...)`, if an argument needs to be passed by reference, +wrap it inside `ByRef()`. For example, + +```cpp +using ::testing::ByRef; +using ::testing::InvokeArgument; +... +InvokeArgument<2>(5, string("Hi"), ByRef(foo)) +``` + +calls the mock function's #2 argument, passing to it `5` and `string("Hi")` by +value, and `foo` by reference. + +#### Default Action + + +| Matcher | Description | +| :------------ | :----------------------------------------------------- | +| `DoDefault()` | Do the default action (specified by `ON_CALL()` or the built-in one). | + + +**Note:** due to technical reasons, `DoDefault()` cannot be used inside a +composite action - trying to do so will result in a run-time error. + + + +#### Composite Actions + + +| | | +| :----------------------------- | :------------------------------------------ | +| `DoAll(a1, a2, ..., an)` | Do all actions `a1` to `an` and return the result of `an` in each invocation. The first `n - 1` sub-actions must return void. | +| `IgnoreResult(a)` | Perform action `a` and ignore its result. `a` must not return void. | +| `WithArg(a)` | Pass the `N`-th (0-based) argument of the mock function to action `a` and perform it. | +| `WithArgs(a)` | Pass the selected (0-based) arguments of the mock function to action `a` and perform it. | +| `WithoutArgs(a)` | Perform action `a` without any arguments. | + + +#### Defining Actions + + + + + + + +
    `struct SumAction {`
    +  `template `
    +  `T operator()(T x, Ty) { return x + y; }`
    + `};` +
    Defines a generic functor that can be used as an action summing its + arguments.
    + + +| | | +| :--------------------------------- | :-------------------------------------- | +| `ACTION(Sum) { return arg0 + arg1; }` | Defines an action `Sum()` to return the sum of the mock function's argument #0 and #1. | +| `ACTION_P(Plus, n) { return arg0 + n; }` | Defines an action `Plus(n)` to return the sum of the mock function's argument #0 and `n`. | +| `ACTION_Pk(Foo, p1, ..., pk) { statements; }` | Defines a parameterized action `Foo(p1, ..., pk)` to execute the given `statements`. | + + +The `ACTION*` macros cannot be used inside a function or class. + +### Cardinalities {#CardinalityList} + +These are used in `Times()` to specify how many times a mock function will be +called: + + +| | | +| :---------------- | :----------------------------------------------------- | +| `AnyNumber()` | The function can be called any number of times. | +| `AtLeast(n)` | The call is expected at least `n` times. | +| `AtMost(n)` | The call is expected at most `n` times. | +| `Between(m, n)` | The call is expected between `m` and `n` (inclusive) times. | +| `Exactly(n) or n` | The call is expected exactly `n` times. In particular, the call should never happen when `n` is 0. | + + +### Expectation Order + +By default, the expectations can be matched in *any* order. If some or all +expectations must be matched in a given order, there are two ways to specify it. +They can be used either independently or together. + +#### The After Clause {#AfterClause} + +```cpp +using ::testing::Expectation; +... +Expectation init_x = EXPECT_CALL(foo, InitX()); +Expectation init_y = EXPECT_CALL(foo, InitY()); +EXPECT_CALL(foo, Bar()) + .After(init_x, init_y); +``` + +says that `Bar()` can be called only after both `InitX()` and `InitY()` have +been called. + +If you don't know how many pre-requisites an expectation has when you write it, +you can use an `ExpectationSet` to collect them: + +```cpp +using ::testing::ExpectationSet; +... +ExpectationSet all_inits; +for (int i = 0; i < element_count; i++) { + all_inits += EXPECT_CALL(foo, InitElement(i)); +} +EXPECT_CALL(foo, Bar()) + .After(all_inits); +``` + +says that `Bar()` can be called only after all elements have been initialized +(but we don't care about which elements get initialized before the others). + +Modifying an `ExpectationSet` after using it in an `.After()` doesn't affect the +meaning of the `.After()`. + +#### Sequences {#UsingSequences} + +When you have a long chain of sequential expectations, it's easier to specify +the order using **sequences**, which don't require you to given each expectation +in the chain a different name. *All expected calls* in the same sequence must +occur in the order they are specified. + +```cpp +using ::testing::Return; +using ::testing::Sequence; +Sequence s1, s2; +... +EXPECT_CALL(foo, Reset()) + .InSequence(s1, s2) + .WillOnce(Return(true)); +EXPECT_CALL(foo, GetSize()) + .InSequence(s1) + .WillOnce(Return(1)); +EXPECT_CALL(foo, Describe(A())) + .InSequence(s2) + .WillOnce(Return("dummy")); +``` + +says that `Reset()` must be called before *both* `GetSize()` *and* `Describe()`, +and the latter two can occur in any order. + +To put many expectations in a sequence conveniently: + +```cpp +using ::testing::InSequence; +{ + InSequence seq; + + EXPECT_CALL(...)...; + EXPECT_CALL(...)...; + ... + EXPECT_CALL(...)...; +} +``` + +says that all expected calls in the scope of `seq` must occur in strict order. +The name `seq` is irrelevant. + +### Verifying and Resetting a Mock + +gMock will verify the expectations on a mock object when it is destructed, or +you can do it earlier: + +```cpp +using ::testing::Mock; +... +// Verifies and removes the expectations on mock_obj; +// returns true if successful. +Mock::VerifyAndClearExpectations(&mock_obj); +... +// Verifies and removes the expectations on mock_obj; +// also removes the default actions set by ON_CALL(); +// returns true if successful. +Mock::VerifyAndClear(&mock_obj); +``` + +You can also tell gMock that a mock object can be leaked and doesn't need to be +verified: + +```cpp +Mock::AllowLeak(&mock_obj); +``` + +### Mock Classes + +gMock defines a convenient mock class template + +```cpp +class MockFunction { + public: + MOCK_METHOD(R, Call, (A1, ..., An)); +}; +``` + +See this [recipe](cook_book.md#using-check-points) for one application of it. + +### Flags + + +| Flag | Description | +| :----------------------------- | :---------------------------------------- | +| `--gmock_catch_leaked_mocks=0` | Don't report leaked mock objects as failures. | +| `--gmock_verbose=LEVEL` | Sets the default verbosity level (`info`, `warning`, or `error`) of Google Mock messages. | + diff --git a/googlemock/docs/cook_book.md b/googlemock/docs/cook_book.md new file mode 100644 index 00000000..28f7ba1d --- /dev/null +++ b/googlemock/docs/cook_book.md @@ -0,0 +1,4269 @@ +## gMock Cookbook + + + +You can find recipes for using gMock here. If you haven't yet, please read +[this](for_dummies.md) first to make sure you understand the basics. + +**Note:** gMock lives in the `testing` name space. For readability, it is +recommended to write `using ::testing::Foo;` once in your file before using the +name `Foo` defined by gMock. We omit such `using` statements in this section for +brevity, but you should do it in your own code. + +### Creating Mock Classes + +Mock classes are defined as normal classes, using the `MOCK_METHOD` macro to +generate mocked methods. The macro gets 3 or 4 parameters: + +```cpp +class MyMock { + public: + MOCK_METHOD(ReturnType, MethodName, (Args...)); + MOCK_METHOD(ReturnType, MethodName, (Args...), (Specs...)); +}; +``` + +The first 3 parameters are simply the method declaration, split into 3 parts. +The 4th parameter accepts a closed list of qualifiers, which affect the +generated method: + +* **`const`** - Makes the mocked method a `const` method. Required if + overriding a `const` method. +* **`override`** - Marks the method with `override`. Recommended if overriding + a `virtual` method. +* **`noexcept`** - Marks the method with `noexcept`. Required if overriding a + `noexcept` method. +* **`Calltype(...)`** - Sets the call type for the method (e.g. to + `STDMETHODCALLTYPE`), useful in Windows. + +#### Dealing with unprotected commas + +Unprotected commas, i.e. commas which are not surrounded by parentheses, prevent +`MOCK_METHOD` from parsing its arguments correctly: + +```cpp {.bad} +class MockFoo { + public: + MOCK_METHOD(std::pair, GetPair, ()); // Won't compile! + MOCK_METHOD(bool, CheckMap, (std::map, bool)); // Won't compile! +}; +``` + +Solution 1 - wrap with parentheses: + +```cpp {.good} +class MockFoo { + public: + MOCK_METHOD((std::pair), GetPair, ()); + MOCK_METHOD(bool, CheckMap, ((std::map), bool)); +}; +``` + +Note that wrapping a return or argument type with parentheses is, in general, +invalid C++. `MOCK_METHOD` removes the parentheses. + +Solution 2 - define an alias: + +```cpp {.good} +class MockFoo { + public: + using BoolAndInt = std::pair; + MOCK_METHOD(BoolAndInt, GetPair, ()); + using MapIntDouble = std::map; + MOCK_METHOD(bool, CheckMap, (MapIntDouble, bool)); +}; +``` + +#### Mocking Private or Protected Methods + +You must always put a mock method definition (`MOCK_METHOD`) in a `public:` +section of the mock class, regardless of the method being mocked being `public`, +`protected`, or `private` in the base class. This allows `ON_CALL` and +`EXPECT_CALL` to reference the mock function from outside of the mock class. +(Yes, C++ allows a subclass to change the access level of a virtual function in +the base class.) Example: + +```cpp +class Foo { + public: + ... + virtual bool Transform(Gadget* g) = 0; + + protected: + virtual void Resume(); + + private: + virtual int GetTimeOut(); +}; + +class MockFoo : public Foo { + public: + ... + MOCK_METHOD(bool, Transform, (Gadget* g), (override)); + + // The following must be in the public section, even though the + // methods are protected or private in the base class. + MOCK_METHOD(void, Resume, (), (override)); + MOCK_METHOD(int, GetTimeOut, (), (override)); +}; +``` + +#### Mocking Overloaded Methods + +You can mock overloaded functions as usual. No special attention is required: + +```cpp +class Foo { + ... + + // Must be virtual as we'll inherit from Foo. + virtual ~Foo(); + + // Overloaded on the types and/or numbers of arguments. + virtual int Add(Element x); + virtual int Add(int times, Element x); + + // Overloaded on the const-ness of this object. + virtual Bar& GetBar(); + virtual const Bar& GetBar() const; +}; + +class MockFoo : public Foo { + ... + MOCK_METHOD(int, Add, (Element x), (override)); + MOCK_METHOD(int, Add, (int times, Element x), (override)); + + MOCK_METHOD(Bar&, GetBar, (), (override)); + MOCK_METHOD(const Bar&, GetBar, (), (const, override)); +}; +``` + +**Note:** if you don't mock all versions of the overloaded method, the compiler +will give you a warning about some methods in the base class being hidden. To +fix that, use `using` to bring them in scope: + +```cpp +class MockFoo : public Foo { + ... + using Foo::Add; + MOCK_METHOD(int, Add, (Element x), (override)); + // We don't want to mock int Add(int times, Element x); + ... +}; +``` + +#### Mocking Class Templates + +You can mock class templates just like any class. + +```cpp +template +class StackInterface { + ... + // Must be virtual as we'll inherit from StackInterface. + virtual ~StackInterface(); + + virtual int GetSize() const = 0; + virtual void Push(const Elem& x) = 0; +}; + +template +class MockStack : public StackInterface { + ... + MOCK_METHOD(int, GetSize, (), (override)); + MOCK_METHOD(void, Push, (const Elem& x), (override)); +}; +``` + +#### Mocking Non-virtual Methods {#MockingNonVirtualMethods} + +gMock can mock non-virtual functions to be used in Hi-perf dependency +injection. + +In this case, instead of sharing a common base class with the real class, your +mock class will be *unrelated* to the real class, but contain methods with the +same signatures. The syntax for mocking non-virtual methods is the *same* as +mocking virtual methods (just don't add `override`): + +```cpp +// A simple packet stream class. None of its members is virtual. +class ConcretePacketStream { + public: + void AppendPacket(Packet* new_packet); + const Packet* GetPacket(size_t packet_number) const; + size_t NumberOfPackets() const; + ... +}; + +// A mock packet stream class. It inherits from no other, but defines +// GetPacket() and NumberOfPackets(). +class MockPacketStream { + public: + MOCK_METHOD(const Packet*, GetPacket, (size_t packet_number), (const)); + MOCK_METHOD(size_t, NumberOfPackets, (), (const)); + ... +}; +``` + +Note that the mock class doesn't define `AppendPacket()`, unlike the real class. +That's fine as long as the test doesn't need to call it. + +Next, you need a way to say that you want to use `ConcretePacketStream` in +production code, and use `MockPacketStream` in tests. Since the functions are +not virtual and the two classes are unrelated, you must specify your choice at +*compile time* (as opposed to run time). + +One way to do it is to templatize your code that needs to use a packet stream. +More specifically, you will give your code a template type argument for the type +of the packet stream. In production, you will instantiate your template with +`ConcretePacketStream` as the type argument. In tests, you will instantiate the +same template with `MockPacketStream`. For example, you may write: + +```cpp +template +void CreateConnection(PacketStream* stream) { ... } + +template +class PacketReader { + public: + void ReadPackets(PacketStream* stream, size_t packet_num); +}; +``` + +Then you can use `CreateConnection()` and +`PacketReader` in production code, and use +`CreateConnection()` and `PacketReader` in +tests. + +```cpp + MockPacketStream mock_stream; + EXPECT_CALL(mock_stream, ...)...; + .. set more expectations on mock_stream ... + PacketReader reader(&mock_stream); + ... exercise reader ... +``` + +#### Mocking Free Functions + +It's possible to use gMock to mock a free function (i.e. a C-style function or a +static method). You just need to rewrite your code to use an interface (abstract +class). + +Instead of calling a free function (say, `OpenFile`) directly, introduce an +interface for it and have a concrete subclass that calls the free function: + +```cpp +class FileInterface { + public: + ... + virtual bool Open(const char* path, const char* mode) = 0; +}; + +class File : public FileInterface { + public: + ... + virtual bool Open(const char* path, const char* mode) { + return OpenFile(path, mode); + } +}; +``` + +Your code should talk to `FileInterface` to open a file. Now it's easy to mock +out the function. + +This may seem like a lot of hassle, but in practice you often have multiple +related functions that you can put in the same interface, so the per-function +syntactic overhead will be much lower. + +If you are concerned about the performance overhead incurred by virtual +functions, and profiling confirms your concern, you can combine this with the +recipe for [mocking non-virtual methods](#MockingNonVirtualMethods). + +#### Old-Style `MOCK_METHODn` Macros + +Before the generic `MOCK_METHOD` macro was introduced, mocks where created using +a family of macros collectively called `MOCK_METHODn`. These macros are still +supported, though migration to the new `MOCK_METHOD` is recommended. + +The macros in the `MOCK_METHODn` family differ from `MOCK_METHOD`: + +* The general structure is `MOCK_METHODn(MethodName, ReturnType(Args))`, + instead of `MOCK_METHOD(ReturnType, MethodName, (Args))`. +* The number `n` must equal the number of arguments. +* When mocking a const method, one must use `MOCK_CONST_METHODn`. +* When mocking a class template, the macro name must be suffixed with `_T`. +* In order to specify the call type, the macro name must be suffixed with + `_WITH_CALLTYPE`, and the call type is the first macro argument. + +Old macros and their new equivalents: + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    Simple
    Old `MOCK_METHOD1(Foo, bool(int))`
    New `MOCK_METHOD(bool, Foo, (int))`
    Const Method
    Old +`MOCK_CONST_METHOD1(Foo, bool(int))`
    New +`MOCK_METHOD(bool, Foo, (int), (const))`
    Method in a Class Template
    Old `MOCK_METHOD1_T(Foo, bool(int))`
    New +`MOCK_METHOD(bool, Foo, (int))`
    Const Method in a Class Template
    Old + `MOCK_CONST_METHOD1_T(Foo, bool(int))`
    New + `MOCK_METHOD(bool, Foo, (int), (const))`
    Method with Call Type
    Old +`MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, Foo, bool(int))`
    New `MOCK_METHOD(bool, Foo, (int), +(Calltype(STDMETHODCALLTYPE)))`
    Const Method with Call Type
    Old `MOCK_CONST_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, Foo, bool(int))`
    New `MOCK_METHOD(bool, Foo, (int), (const, +Calltype(STDMETHODCALLTYPE)))`
    Method with Call Type in a Class Template
    Old `MOCK_METHOD1_T_WITH_CALLTYPE(STDMETHODCALLTYPE, Foo, +bool(int))`
    New `MOCK_METHOD(bool, Foo, (int), +(Calltype(STDMETHODCALLTYPE)))`
    Const Method with Call Type in a Class Template
    Old `MOCK_CONST_METHOD1_T_WITH_CALLTYPE(STDMETHODCALLTYPE, +Foo, bool(int))`
    New `MOCK_METHOD(bool, Foo, +(int), (const, Calltype(STDMETHODCALLTYPE)))`
    + +#### The Nice, the Strict, and the Naggy {#NiceStrictNaggy} + +If a mock method has no `EXPECT_CALL` spec but is called, we say that it's an +"uninteresting call", and the default action (which can be specified using +`ON_CALL()`) of the method will be taken. Currently, an uninteresting call will +also by default cause gMock to print a warning. (In the future, we might remove +this warning by default.) + +However, sometimes you may want to ignore these uninteresting calls, and +sometimes you may want to treat them as errors. gMock lets you make the decision +on a per-mock-object basis. + +Suppose your test uses a mock class `MockFoo`: + +```cpp +TEST(...) { + MockFoo mock_foo; + EXPECT_CALL(mock_foo, DoThis()); + ... code that uses mock_foo ... +} +``` + +If a method of `mock_foo` other than `DoThis()` is called, you will get a +warning. However, if you rewrite your test to use `NiceMock` instead, +you can suppress the warning: + +```cpp +using ::testing::NiceMock; + +TEST(...) { + NiceMock mock_foo; + EXPECT_CALL(mock_foo, DoThis()); + ... code that uses mock_foo ... +} +``` + +`NiceMock` is a subclass of `MockFoo`, so it can be used wherever +`MockFoo` is accepted. + +It also works if `MockFoo`'s constructor takes some arguments, as +`NiceMock` "inherits" `MockFoo`'s constructors: + +```cpp +using ::testing::NiceMock; + +TEST(...) { + NiceMock mock_foo(5, "hi"); // Calls MockFoo(5, "hi"). + EXPECT_CALL(mock_foo, DoThis()); + ... code that uses mock_foo ... +} +``` + +The usage of `StrictMock` is similar, except that it makes all uninteresting +calls failures: + +```cpp +using ::testing::StrictMock; + +TEST(...) { + StrictMock mock_foo; + EXPECT_CALL(mock_foo, DoThis()); + ... code that uses mock_foo ... + + // The test will fail if a method of mock_foo other than DoThis() + // is called. +} +``` + +NOTE: `NiceMock` and `StrictMock` only affects *uninteresting* calls (calls of +*methods* with no expectations); they do not affect *unexpected* calls (calls of +methods with expectations, but they don't match). See +[Understanding Uninteresting vs Unexpected Calls](#uninteresting-vs-unexpected). + +There are some caveats though (I dislike them just as much as the next guy, but +sadly they are side effects of C++'s limitations): + +1. `NiceMock` and `StrictMock` only work for mock methods + defined using the `MOCK_METHOD` macro **directly** in the `MockFoo` class. + If a mock method is defined in a **base class** of `MockFoo`, the "nice" or + "strict" modifier may not affect it, depending on the compiler. In + particular, nesting `NiceMock` and `StrictMock` (e.g. + `NiceMock >`) is **not** supported. +2. `NiceMock` and `StrictMock` may not work correctly if the + destructor of `MockFoo` is not virtual. We would like to fix this, but it + requires cleaning up existing tests. http://b/28934720 tracks the issue. +3. During the constructor or destructor of `MockFoo`, the mock object is *not* + nice or strict. This may cause surprises if the constructor or destructor + calls a mock method on `this` object. (This behavior, however, is consistent + with C++'s general rule: if a constructor or destructor calls a virtual + method of `this` object, that method is treated as non-virtual. In other + words, to the base class's constructor or destructor, `this` object behaves + like an instance of the base class, not the derived class. This rule is + required for safety. Otherwise a base constructor may use members of a + derived class before they are initialized, or a base destructor may use + members of a derived class after they have been destroyed.) + +Finally, you should be **very cautious** about when to use naggy or strict +mocks, as they tend to make tests more brittle and harder to maintain. When you +refactor your code without changing its externally visible behavior, ideally you +shouldn't need to update any tests. If your code interacts with a naggy mock, +however, you may start to get spammed with warnings as the result of your +change. Worse, if your code interacts with a strict mock, your tests may start +to fail and you'll be forced to fix them. Our general recommendation is to use +nice mocks (not yet the default) most of the time, use naggy mocks (the current +default) when developing or debugging tests, and use strict mocks only as the +last resort. + +#### Simplifying the Interface without Breaking Existing Code {#SimplerInterfaces} + +Sometimes a method has a long list of arguments that is mostly uninteresting. +For example: + +```cpp +class LogSink { + public: + ... + virtual void send(LogSeverity severity, const char* full_filename, + const char* base_filename, int line, + const struct tm* tm_time, + const char* message, size_t message_len) = 0; +}; +``` + +This method's argument list is lengthy and hard to work with (the `message` +argument is not even 0-terminated). If we mock it as is, using the mock will be +awkward. If, however, we try to simplify this interface, we'll need to fix all +clients depending on it, which is often infeasible. + +The trick is to redispatch the method in the mock class: + +```cpp +class ScopedMockLog : public LogSink { + public: + ... + virtual void send(LogSeverity severity, const char* full_filename, + const char* base_filename, int line, const tm* tm_time, + const char* message, size_t message_len) { + // We are only interested in the log severity, full file name, and + // log message. + Log(severity, full_filename, std::string(message, message_len)); + } + + // Implements the mock method: + // + // void Log(LogSeverity severity, + // const string& file_path, + // const string& message); + MOCK_METHOD(void, Log, + (LogSeverity severity, const string& file_path, + const string& message)); +}; +``` + +By defining a new mock method with a trimmed argument list, we make the mock +class more user-friendly. + +This technique may also be applied to make overloaded methods more amenable to +mocking. For example, when overloads have been used to implement default +arguments: + +```cpp +class MockTurtleFactory : public TurtleFactory { + public: + Turtle* MakeTurtle(int length, int weight) override { ... } + Turtle* MakeTurtle(int length, int weight, int speed) override { ... } + + // the above methods delegate to this one: + MOCK_METHOD(Turtle*, DoMakeTurtle, ()); +}; +``` + +This allows tests that don't care which overload was invoked to avoid specifying +argument matchers: + +```cpp +ON_CALL(factory, DoMakeTurtle) + .WillByDefault(MakeMockTurtle()); +``` + +#### Alternative to Mocking Concrete Classes + +Often you may find yourself using classes that don't implement interfaces. In +order to test your code that uses such a class (let's call it `Concrete`), you +may be tempted to make the methods of `Concrete` virtual and then mock it. + +Try not to do that. + +Making a non-virtual function virtual is a big decision. It creates an extension +point where subclasses can tweak your class' behavior. This weakens your control +on the class because now it's harder to maintain the class invariants. You +should make a function virtual only when there is a valid reason for a subclass +to override it. + +Mocking concrete classes directly is problematic as it creates a tight coupling +between the class and the tests - any small change in the class may invalidate +your tests and make test maintenance a pain. + +To avoid such problems, many programmers have been practicing "coding to +interfaces": instead of talking to the `Concrete` class, your code would define +an interface and talk to it. Then you implement that interface as an adaptor on +top of `Concrete`. In tests, you can easily mock that interface to observe how +your code is doing. + +This technique incurs some overhead: + +* You pay the cost of virtual function calls (usually not a problem). +* There is more abstraction for the programmers to learn. + +However, it can also bring significant benefits in addition to better +testability: + +* `Concrete`'s API may not fit your problem domain very well, as you may not + be the only client it tries to serve. By designing your own interface, you + have a chance to tailor it to your need - you may add higher-level + functionalities, rename stuff, etc instead of just trimming the class. This + allows you to write your code (user of the interface) in a more natural way, + which means it will be more readable, more maintainable, and you'll be more + productive. +* If `Concrete`'s implementation ever has to change, you don't have to rewrite + everywhere it is used. Instead, you can absorb the change in your + implementation of the interface, and your other code and tests will be + insulated from this change. + +Some people worry that if everyone is practicing this technique, they will end +up writing lots of redundant code. This concern is totally understandable. +However, there are two reasons why it may not be the case: + +* Different projects may need to use `Concrete` in different ways, so the best + interfaces for them will be different. Therefore, each of them will have its + own domain-specific interface on top of `Concrete`, and they will not be the + same code. +* If enough projects want to use the same interface, they can always share it, + just like they have been sharing `Concrete`. You can check in the interface + and the adaptor somewhere near `Concrete` (perhaps in a `contrib` + sub-directory) and let many projects use it. + +You need to weigh the pros and cons carefully for your particular problem, but +I'd like to assure you that the Java community has been practicing this for a +long time and it's a proven effective technique applicable in a wide variety of +situations. :-) + +#### Delegating Calls to a Fake {#DelegatingToFake} + +Some times you have a non-trivial fake implementation of an interface. For +example: + +```cpp +class Foo { + public: + virtual ~Foo() {} + virtual char DoThis(int n) = 0; + virtual void DoThat(const char* s, int* p) = 0; +}; + +class FakeFoo : public Foo { + public: + char DoThis(int n) override { + return (n > 0) ? '+' : + (n < 0) ? '-' : '0'; + } + + void DoThat(const char* s, int* p) override { + *p = strlen(s); + } +}; +``` + +Now you want to mock this interface such that you can set expectations on it. +However, you also want to use `FakeFoo` for the default behavior, as duplicating +it in the mock object is, well, a lot of work. + +When you define the mock class using gMock, you can have it delegate its default +action to a fake class you already have, using this pattern: + +```cpp +class MockFoo : public Foo { + public: + // Normal mock method definitions using gMock. + MOCK_METHOD(char, DoThis, (int n), (override)); + MOCK_METHOD(void, DoThat, (const char* s, int* p), (override)); + + // Delegates the default actions of the methods to a FakeFoo object. + // This must be called *before* the custom ON_CALL() statements. + void DelegateToFake() { + ON_CALL(*this, DoThis).WillByDefault([this](int n) { + return fake_.DoThis(n); + }); + ON_CALL(*this, DoThat).WillByDefault([this](const char* s, int* p) { + fake_.DoThat(s, p); + }); + } + + private: + FakeFoo fake_; // Keeps an instance of the fake in the mock. +}; +``` + +With that, you can use `MockFoo` in your tests as usual. Just remember that if +you don't explicitly set an action in an `ON_CALL()` or `EXPECT_CALL()`, the +fake will be called upon to do it.: + +```cpp +using ::testing::_; + +TEST(AbcTest, Xyz) { + MockFoo foo; + + foo.DelegateToFake(); // Enables the fake for delegation. + + // Put your ON_CALL(foo, ...)s here, if any. + + // No action specified, meaning to use the default action. + EXPECT_CALL(foo, DoThis(5)); + EXPECT_CALL(foo, DoThat(_, _)); + + int n = 0; + EXPECT_EQ('+', foo.DoThis(5)); // FakeFoo::DoThis() is invoked. + foo.DoThat("Hi", &n); // FakeFoo::DoThat() is invoked. + EXPECT_EQ(2, n); +} +``` + +**Some tips:** + +* If you want, you can still override the default action by providing your own + `ON_CALL()` or using `.WillOnce()` / `.WillRepeatedly()` in `EXPECT_CALL()`. +* In `DelegateToFake()`, you only need to delegate the methods whose fake + implementation you intend to use. + +* The general technique discussed here works for overloaded methods, but + you'll need to tell the compiler which version you mean. To disambiguate a + mock function (the one you specify inside the parentheses of `ON_CALL()`), + use [this technique](#SelectOverload); to disambiguate a fake function (the + one you place inside `Invoke()`), use a `static_cast` to specify the + function's type. For instance, if class `Foo` has methods `char DoThis(int + n)` and `bool DoThis(double x) const`, and you want to invoke the latter, + you need to write `Invoke(&fake_, static_cast(&FakeFoo::DoThis))` instead of `Invoke(&fake_, &FakeFoo::DoThis)` + (The strange-looking thing inside the angled brackets of `static_cast` is + the type of a function pointer to the second `DoThis()` method.). + +* Having to mix a mock and a fake is often a sign of something gone wrong. + Perhaps you haven't got used to the interaction-based way of testing yet. Or + perhaps your interface is taking on too many roles and should be split up. + Therefore, **don't abuse this**. We would only recommend to do it as an + intermediate step when you are refactoring your code. + +Regarding the tip on mixing a mock and a fake, here's an example on why it may +be a bad sign: Suppose you have a class `System` for low-level system +operations. In particular, it does file and I/O operations. And suppose you want +to test how your code uses `System` to do I/O, and you just want the file +operations to work normally. If you mock out the entire `System` class, you'll +have to provide a fake implementation for the file operation part, which +suggests that `System` is taking on too many roles. + +Instead, you can define a `FileOps` interface and an `IOOps` interface and split +`System`'s functionalities into the two. Then you can mock `IOOps` without +mocking `FileOps`. + +#### Delegating Calls to a Real Object + +When using testing doubles (mocks, fakes, stubs, and etc), sometimes their +behaviors will differ from those of the real objects. This difference could be +either intentional (as in simulating an error such that you can test the error +handling code) or unintentional. If your mocks have different behaviors than the +real objects by mistake, you could end up with code that passes the tests but +fails in production. + +You can use the *delegating-to-real* technique to ensure that your mock has the +same behavior as the real object while retaining the ability to validate calls. +This technique is very similar to the [delegating-to-fake](#DelegatingToFake) +technique, the difference being that we use a real object instead of a fake. +Here's an example: + +```cpp +using ::testing::AtLeast; + +class MockFoo : public Foo { + public: + MockFoo() { + // By default, all calls are delegated to the real object. + ON_CALL(*this, DoThis).WillByDefault([this](int n) { + return real_.DoThis(n); + }); + ON_CALL(*this, DoThat).WillByDefault([this](const char* s, int* p) { + real_.DoThat(s, p); + }); + ... + } + MOCK_METHOD(char, DoThis, ...); + MOCK_METHOD(void, DoThat, ...); + ... + private: + Foo real_; +}; + +... + MockFoo mock; + EXPECT_CALL(mock, DoThis()) + .Times(3); + EXPECT_CALL(mock, DoThat("Hi")) + .Times(AtLeast(1)); + ... use mock in test ... +``` + +With this, gMock will verify that your code made the right calls (with the right +arguments, in the right order, called the right number of times, etc), and a +real object will answer the calls (so the behavior will be the same as in +production). This gives you the best of both worlds. + +#### Delegating Calls to a Parent Class + +Ideally, you should code to interfaces, whose methods are all pure virtual. In +reality, sometimes you do need to mock a virtual method that is not pure (i.e, +it already has an implementation). For example: + +```cpp +class Foo { + public: + virtual ~Foo(); + + virtual void Pure(int n) = 0; + virtual int Concrete(const char* str) { ... } +}; + +class MockFoo : public Foo { + public: + // Mocking a pure method. + MOCK_METHOD(void, Pure, (int n), (override)); + // Mocking a concrete method. Foo::Concrete() is shadowed. + MOCK_METHOD(int, Concrete, (const char* str), (override)); +}; +``` + +Sometimes you may want to call `Foo::Concrete()` instead of +`MockFoo::Concrete()`. Perhaps you want to do it as part of a stub action, or +perhaps your test doesn't need to mock `Concrete()` at all (but it would be +oh-so painful to have to define a new mock class whenever you don't need to mock +one of its methods). + +The trick is to leave a back door in your mock class for accessing the real +methods in the base class: + +```cpp +class MockFoo : public Foo { + public: + // Mocking a pure method. + MOCK_METHOD(void, Pure, (int n), (override)); + // Mocking a concrete method. Foo::Concrete() is shadowed. + MOCK_METHOD(int, Concrete, (const char* str), (override)); + + // Use this to call Concrete() defined in Foo. + int FooConcrete(const char* str) { return Foo::Concrete(str); } +}; +``` + +Now, you can call `Foo::Concrete()` inside an action by: + +```cpp +... + EXPECT_CALL(foo, Concrete).WillOnce([&foo](const char* str) { + return foo.FooConcrete(str); + }); +``` + +or tell the mock object that you don't want to mock `Concrete()`: + +```cpp +... + ON_CALL(foo, Concrete).WillByDefault([&foo](const char* str) { + return foo.FooConcrete(str); + }); +``` + +(Why don't we just write `{ return foo.Concrete(str); }`? If you do that, +`MockFoo::Concrete()` will be called (and cause an infinite recursion) since +`Foo::Concrete()` is virtual. That's just how C++ works.) + +### Using Matchers + +#### Matching Argument Values Exactly + +You can specify exactly which arguments a mock method is expecting: + +```cpp +using ::testing::Return; +... + EXPECT_CALL(foo, DoThis(5)) + .WillOnce(Return('a')); + EXPECT_CALL(foo, DoThat("Hello", bar)); +``` + +#### Using Simple Matchers + +You can use matchers to match arguments that have a certain property: + +```cpp +using ::testing::NotNull; +using ::testing::Return; +... + EXPECT_CALL(foo, DoThis(Ge(5))) // The argument must be >= 5. + .WillOnce(Return('a')); + EXPECT_CALL(foo, DoThat("Hello", NotNull())); + // The second argument must not be NULL. +``` + +A frequently used matcher is `_`, which matches anything: + +```cpp + EXPECT_CALL(foo, DoThat(_, NotNull())); +``` + + +#### Combining Matchers {#CombiningMatchers} + +You can build complex matchers from existing ones using `AllOf()`, +`AllOfArray()`, `AnyOf()`, `AnyOfArray()` and `Not()`: + +```cpp +using ::testing::AllOf; +using ::testing::Gt; +using ::testing::HasSubstr; +using ::testing::Ne; +using ::testing::Not; +... + // The argument must be > 5 and != 10. + EXPECT_CALL(foo, DoThis(AllOf(Gt(5), + Ne(10)))); + + // The first argument must not contain sub-string "blah". + EXPECT_CALL(foo, DoThat(Not(HasSubstr("blah")), + NULL)); +``` + +#### Casting Matchers {#SafeMatcherCast} + +gMock matchers are statically typed, meaning that the compiler can catch your +mistake if you use a matcher of the wrong type (for example, if you use `Eq(5)` +to match a `string` argument). Good for you! + +Sometimes, however, you know what you're doing and want the compiler to give you +some slack. One example is that you have a matcher for `long` and the argument +you want to match is `int`. While the two types aren't exactly the same, there +is nothing really wrong with using a `Matcher` to match an `int` - after +all, we can first convert the `int` argument to a `long` losslessly before +giving it to the matcher. + +To support this need, gMock gives you the `SafeMatcherCast(m)` function. It +casts a matcher `m` to type `Matcher`. To ensure safety, gMock checks that +(let `U` be the type `m` accepts : + +1. Type `T` can be *implicitly* cast to type `U`; +2. When both `T` and `U` are built-in arithmetic types (`bool`, integers, and + floating-point numbers), the conversion from `T` to `U` is not lossy (in + other words, any value representable by `T` can also be represented by `U`); + and +3. When `U` is a reference, `T` must also be a reference (as the underlying + matcher may be interested in the address of the `U` value). + +The code won't compile if any of these conditions isn't met. + +Here's one example: + +```cpp +using ::testing::SafeMatcherCast; + +// A base class and a child class. +class Base { ... }; +class Derived : public Base { ... }; + +class MockFoo : public Foo { + public: + MOCK_METHOD(void, DoThis, (Derived* derived), (override)); +}; + +... + MockFoo foo; + // m is a Matcher we got from somewhere. + EXPECT_CALL(foo, DoThis(SafeMatcherCast(m))); +``` + +If you find `SafeMatcherCast(m)` too limiting, you can use a similar function +`MatcherCast(m)`. The difference is that `MatcherCast` works as long as you +can `static_cast` type `T` to type `U`. + +`MatcherCast` essentially lets you bypass C++'s type system (`static_cast` isn't +always safe as it could throw away information, for example), so be careful not +to misuse/abuse it. + +#### Selecting Between Overloaded Functions {#SelectOverload} + +If you expect an overloaded function to be called, the compiler may need some +help on which overloaded version it is. + +To disambiguate functions overloaded on the const-ness of this object, use the +`Const()` argument wrapper. + +```cpp +using ::testing::ReturnRef; + +class MockFoo : public Foo { + ... + MOCK_METHOD(Bar&, GetBar, (), (override)); + MOCK_METHOD(const Bar&, GetBar, (), (const, override)); +}; + +... + MockFoo foo; + Bar bar1, bar2; + EXPECT_CALL(foo, GetBar()) // The non-const GetBar(). + .WillOnce(ReturnRef(bar1)); + EXPECT_CALL(Const(foo), GetBar()) // The const GetBar(). + .WillOnce(ReturnRef(bar2)); +``` + +(`Const()` is defined by gMock and returns a `const` reference to its argument.) + +To disambiguate overloaded functions with the same number of arguments but +different argument types, you may need to specify the exact type of a matcher, +either by wrapping your matcher in `Matcher()`, or using a matcher whose +type is fixed (`TypedEq`, `An()`, etc): + +```cpp +using ::testing::An; +using ::testing::Matcher; +using ::testing::TypedEq; + +class MockPrinter : public Printer { + public: + MOCK_METHOD(void, Print, (int n), (override)); + MOCK_METHOD(void, Print, (char c), (override)); +}; + +TEST(PrinterTest, Print) { + MockPrinter printer; + + EXPECT_CALL(printer, Print(An())); // void Print(int); + EXPECT_CALL(printer, Print(Matcher(Lt(5)))); // void Print(int); + EXPECT_CALL(printer, Print(TypedEq('a'))); // void Print(char); + + printer.Print(3); + printer.Print(6); + printer.Print('a'); +} +``` + +#### Performing Different Actions Based on the Arguments + +When a mock method is called, the *last* matching expectation that's still +active will be selected (think "newer overrides older"). So, you can make a +method do different things depending on its argument values like this: + +```cpp +using ::testing::_; +using ::testing::Lt; +using ::testing::Return; +... + // The default case. + EXPECT_CALL(foo, DoThis(_)) + .WillRepeatedly(Return('b')); + // The more specific case. + EXPECT_CALL(foo, DoThis(Lt(5))) + .WillRepeatedly(Return('a')); +``` + +Now, if `foo.DoThis()` is called with a value less than 5, `'a'` will be +returned; otherwise `'b'` will be returned. + +#### Matching Multiple Arguments as a Whole + +Sometimes it's not enough to match the arguments individually. For example, we +may want to say that the first argument must be less than the second argument. +The `With()` clause allows us to match all arguments of a mock function as a +whole. For example, + +```cpp +using ::testing::_; +using ::testing::Ne; +using ::testing::Lt; +... + EXPECT_CALL(foo, InRange(Ne(0), _)) + .With(Lt()); +``` + +says that the first argument of `InRange()` must not be 0, and must be less than +the second argument. + +The expression inside `With()` must be a matcher of type +`Matcher< ::std::tuple >`, where `A1`, ..., `An` are the types of +the function arguments. + +You can also write `AllArgs(m)` instead of `m` inside `.With()`. The two forms +are equivalent, but `.With(AllArgs(Lt()))` is more readable than `.With(Lt())`. + +You can use `Args(m)` to match the `n` selected arguments (as a +tuple) against `m`. For example, + +```cpp +using ::testing::_; +using ::testing::AllOf; +using ::testing::Args; +using ::testing::Lt; +... + EXPECT_CALL(foo, Blah) + .With(AllOf(Args<0, 1>(Lt()), Args<1, 2>(Lt()))); +``` + +says that `Blah` will be called with arguments `x`, `y`, and `z` where `x < y < +z`. Note that in this example, it wasn't necessary specify the positional +matchers. + +As a convenience and example, gMock provides some matchers for 2-tuples, +including the `Lt()` matcher above. See [here](#MultiArgMatchers) for the +complete list. + +Note that if you want to pass the arguments to a predicate of your own (e.g. +`.With(Args<0, 1>(Truly(&MyPredicate)))`), that predicate MUST be written to +take a `::std::tuple` as its argument; gMock will pass the `n` selected +arguments as *one* single tuple to the predicate. + +#### Using Matchers as Predicates + +Have you noticed that a matcher is just a fancy predicate that also knows how to +describe itself? Many existing algorithms take predicates as arguments (e.g. +those defined in STL's `` header), and it would be a shame if gMock +matchers were not allowed to participate. + +Luckily, you can use a matcher where a unary predicate functor is expected by +wrapping it inside the `Matches()` function. For example, + +```cpp +#include +#include + +using ::testing::Matches; +using ::testing::Ge; + +vector v; +... +// How many elements in v are >= 10? +const int count = count_if(v.begin(), v.end(), Matches(Ge(10))); +``` + +Since you can build complex matchers from simpler ones easily using gMock, this +gives you a way to conveniently construct composite predicates (doing the same +using STL's `` header is just painful). For example, here's a +predicate that's satisfied by any number that is >= 0, <= 100, and != 50: + +```cpp +using testing::AllOf; +using testing::Ge; +using testing::Le; +using testing::Matches; +using testing::Ne; +... +Matches(AllOf(Ge(0), Le(100), Ne(50))) +``` + +#### Using Matchers in googletest Assertions + +Since matchers are basically predicates that also know how to describe +themselves, there is a way to take advantage of them in googletest assertions. +It's called `ASSERT_THAT` and `EXPECT_THAT`: + +```cpp + ASSERT_THAT(value, matcher); // Asserts that value matches matcher. + EXPECT_THAT(value, matcher); // The non-fatal version. +``` + +For example, in a googletest test you can write: + +```cpp +#include "gmock/gmock.h" + +using ::testing::AllOf; +using ::testing::Ge; +using ::testing::Le; +using ::testing::MatchesRegex; +using ::testing::StartsWith; + +... + EXPECT_THAT(Foo(), StartsWith("Hello")); + EXPECT_THAT(Bar(), MatchesRegex("Line \\d+")); + ASSERT_THAT(Baz(), AllOf(Ge(5), Le(10))); +``` + +which (as you can probably guess) executes `Foo()`, `Bar()`, and `Baz()`, and +verifies that: + +* `Foo()` returns a string that starts with `"Hello"`. +* `Bar()` returns a string that matches regular expression `"Line \\d+"`. +* `Baz()` returns a number in the range [5, 10]. + +The nice thing about these macros is that *they read like English*. They +generate informative messages too. For example, if the first `EXPECT_THAT()` +above fails, the message will be something like: + +```cpp +Value of: Foo() + Actual: "Hi, world!" +Expected: starts with "Hello" +``` + +**Credit:** The idea of `(ASSERT|EXPECT)_THAT` was borrowed from Joe Walnes' +Hamcrest project, which adds `assertThat()` to JUnit. + +#### Using Predicates as Matchers + +gMock provides a [built-in set](#MatcherList) of matchers. In case you find them +lacking, you can use an arbitrary unary predicate function or functor as a +matcher - as long as the predicate accepts a value of the type you want. You do +this by wrapping the predicate inside the `Truly()` function, for example: + +```cpp +using ::testing::Truly; + +int IsEven(int n) { return (n % 2) == 0 ? 1 : 0; } +... + // Bar() must be called with an even number. + EXPECT_CALL(foo, Bar(Truly(IsEven))); +``` + +Note that the predicate function / functor doesn't have to return `bool`. It +works as long as the return value can be used as the condition in in statement +`if (condition) ...`. + + + +#### Matching Arguments that Are Not Copyable + +When you do an `EXPECT_CALL(mock_obj, Foo(bar))`, gMock saves away a copy of +`bar`. When `Foo()` is called later, gMock compares the argument to `Foo()` with +the saved copy of `bar`. This way, you don't need to worry about `bar` being +modified or destroyed after the `EXPECT_CALL()` is executed. The same is true +when you use matchers like `Eq(bar)`, `Le(bar)`, and so on. + +But what if `bar` cannot be copied (i.e. has no copy constructor)? You could +define your own matcher function or callback and use it with `Truly()`, as the +previous couple of recipes have shown. Or, you may be able to get away from it +if you can guarantee that `bar` won't be changed after the `EXPECT_CALL()` is +executed. Just tell gMock that it should save a reference to `bar`, instead of a +copy of it. Here's how: + +```cpp +using ::testing::ByRef; +using ::testing::Eq; +using ::testing::Lt; +... + // Expects that Foo()'s argument == bar. + EXPECT_CALL(mock_obj, Foo(Eq(ByRef(bar)))); + + // Expects that Foo()'s argument < bar. + EXPECT_CALL(mock_obj, Foo(Lt(ByRef(bar)))); +``` + +Remember: if you do this, don't change `bar` after the `EXPECT_CALL()`, or the +result is undefined. + +#### Validating a Member of an Object + +Often a mock function takes a reference to object as an argument. When matching +the argument, you may not want to compare the entire object against a fixed +object, as that may be over-specification. Instead, you may need to validate a +certain member variable or the result of a certain getter method of the object. +You can do this with `Field()` and `Property()`. More specifically, + +```cpp +Field(&Foo::bar, m) +``` + +is a matcher that matches a `Foo` object whose `bar` member variable satisfies +matcher `m`. + +```cpp +Property(&Foo::baz, m) +``` + +is a matcher that matches a `Foo` object whose `baz()` method returns a value +that satisfies matcher `m`. + +For example: + + +| Expression | Description | +| :--------------------------- | :--------------------------------------- | +| `Field(&Foo::number, Ge(3))` | Matches `x` where `x.number >= 3`. | +| `Property(&Foo::name, StartsWith("John "))` | Matches `x` where `x.name()` starts with `"John "`. | + + +Note that in `Property(&Foo::baz, ...)`, method `baz()` must take no argument +and be declared as `const`. + +BTW, `Field()` and `Property()` can also match plain pointers to objects. For +instance, + +```cpp +using ::testing::Field; +using ::testing::Ge; +... +Field(&Foo::number, Ge(3)) +``` + +matches a plain pointer `p` where `p->number >= 3`. If `p` is `NULL`, the match +will always fail regardless of the inner matcher. + +What if you want to validate more than one members at the same time? Remember +that there are [`AllOf()` and `AllOfArray()`](#CombiningMatchers). + +Finally `Field()` and `Property()` provide overloads that take the field or +property names as the first argument to include it in the error message. This +can be useful when creating combined matchers. + +```cpp +using ::testing::AllOf; +using ::testing::Field; +using ::testing::Matcher; +using ::testing::SafeMatcherCast; + +Matcher IsFoo(const Foo& foo) { + return AllOf(Field("some_field", &Foo::some_field, foo.some_field), + Field("other_field", &Foo::other_field, foo.other_field), + Field("last_field", &Foo::last_field, foo.last_field)); +} +``` + +#### Validating the Value Pointed to by a Pointer Argument + +C++ functions often take pointers as arguments. You can use matchers like +`IsNull()`, `NotNull()`, and other comparison matchers to match a pointer, but +what if you want to make sure the value *pointed to* by the pointer, instead of +the pointer itself, has a certain property? Well, you can use the `Pointee(m)` +matcher. + +`Pointee(m)` matches a pointer if `m` matches the value the pointer points to. +For example: + +```cpp +using ::testing::Ge; +using ::testing::Pointee; +... + EXPECT_CALL(foo, Bar(Pointee(Ge(3)))); +``` + +expects `foo.Bar()` to be called with a pointer that points to a value greater +than or equal to 3. + +One nice thing about `Pointee()` is that it treats a `NULL` pointer as a match +failure, so you can write `Pointee(m)` instead of + +```cpp +using ::testing::AllOf; +using ::testing::NotNull; +using ::testing::Pointee; +... + AllOf(NotNull(), Pointee(m)) +``` + +without worrying that a `NULL` pointer will crash your test. + +Also, did we tell you that `Pointee()` works with both raw pointers **and** +smart pointers (`std::unique_ptr`, `std::shared_ptr`, etc)? + +What if you have a pointer to pointer? You guessed it - you can use nested +`Pointee()` to probe deeper inside the value. For example, +`Pointee(Pointee(Lt(3)))` matches a pointer that points to a pointer that points +to a number less than 3 (what a mouthful...). + +#### Testing a Certain Property of an Object + +Sometimes you want to specify that an object argument has a certain property, +but there is no existing matcher that does this. If you want good error +messages, you should [define a matcher](#NewMatchers). If you want to do it +quick and dirty, you could get away with writing an ordinary function. + +Let's say you have a mock function that takes an object of type `Foo`, which has +an `int bar()` method and an `int baz()` method, and you want to constrain that +the argument's `bar()` value plus its `baz()` value is a given number. Here's +how you can define a matcher to do it: + +```cpp +using ::testing::Matcher; +using ::testing::MatcherInterface; +using ::testing::MatchResultListener; + +class BarPlusBazEqMatcher : public MatcherInterface { + public: + explicit BarPlusBazEqMatcher(int expected_sum) + : expected_sum_(expected_sum) {} + + bool MatchAndExplain(const Foo& foo, + MatchResultListener* /* listener */) const override { + return (foo.bar() + foo.baz()) == expected_sum_; + } + + void DescribeTo(::std::ostream* os) const override { + *os << "bar() + baz() equals " << expected_sum_; + } + + void DescribeNegationTo(::std::ostream* os) const override { + *os << "bar() + baz() does not equal " << expected_sum_; + } + private: + const int expected_sum_; +}; + +Matcher BarPlusBazEq(int expected_sum) { + return MakeMatcher(new BarPlusBazEqMatcher(expected_sum)); +} + +... + EXPECT_CALL(..., DoThis(BarPlusBazEq(5)))...; +``` + +#### Matching Containers + +Sometimes an STL container (e.g. list, vector, map, ...) is passed to a mock +function and you may want to validate it. Since most STL containers support the +`==` operator, you can write `Eq(expected_container)` or simply +`expected_container` to match a container exactly. + +Sometimes, though, you may want to be more flexible (for example, the first +element must be an exact match, but the second element can be any positive +number, and so on). Also, containers used in tests often have a small number of +elements, and having to define the expected container out-of-line is a bit of a +hassle. + +You can use the `ElementsAre()` or `UnorderedElementsAre()` matcher in such +cases: + +```cpp +using ::testing::_; +using ::testing::ElementsAre; +using ::testing::Gt; +... + MOCK_METHOD(void, Foo, (const vector& numbers), (override)); +... + EXPECT_CALL(mock, Foo(ElementsAre(1, Gt(0), _, 5))); +``` + +The above matcher says that the container must have 4 elements, which must be 1, +greater than 0, anything, and 5 respectively. + +If you instead write: + +```cpp +using ::testing::_; +using ::testing::Gt; +using ::testing::UnorderedElementsAre; +... + MOCK_METHOD(void, Foo, (const vector& numbers), (override)); +... + EXPECT_CALL(mock, Foo(UnorderedElementsAre(1, Gt(0), _, 5))); +``` + +It means that the container must have 4 elements, which (under some permutation) +must be 1, greater than 0, anything, and 5 respectively. + +As an alternative you can place the arguments in a C-style array and use +`ElementsAreArray()` or `UnorderedElementsAreArray()` instead: + +```cpp +using ::testing::ElementsAreArray; +... + // ElementsAreArray accepts an array of element values. + const int expected_vector1[] = {1, 5, 2, 4, ...}; + EXPECT_CALL(mock, Foo(ElementsAreArray(expected_vector1))); + + // Or, an array of element matchers. + Matcher expected_vector2[] = {1, Gt(2), _, 3, ...}; + EXPECT_CALL(mock, Foo(ElementsAreArray(expected_vector2))); +``` + +In case the array needs to be dynamically created (and therefore the array size +cannot be inferred by the compiler), you can give `ElementsAreArray()` an +additional argument to specify the array size: + +```cpp +using ::testing::ElementsAreArray; +... + int* const expected_vector3 = new int[count]; + ... fill expected_vector3 with values ... + EXPECT_CALL(mock, Foo(ElementsAreArray(expected_vector3, count))); +``` + +Use `Pair` when comparing maps or other associative containers. + +```cpp +using testing::ElementsAre; +using testing::Pair; +... + std::map m = {{"a", 1}, {"b", 2}, {"c", 3}}; + EXPECT_THAT(m, ElementsAre(Pair("a", 1), Pair("b", 2), Pair("c", 3))); +``` + +**Tips:** + +* `ElementsAre*()` can be used to match *any* container that implements the + STL iterator pattern (i.e. it has a `const_iterator` type and supports + `begin()/end()`), not just the ones defined in STL. It will even work with + container types yet to be written - as long as they follows the above + pattern. +* You can use nested `ElementsAre*()` to match nested (multi-dimensional) + containers. +* If the container is passed by pointer instead of by reference, just write + `Pointee(ElementsAre*(...))`. +* The order of elements *matters* for `ElementsAre*()`. If you are using it + with containers whose element order are undefined (e.g. `hash_map`) you + should use `WhenSorted` around `ElementsAre`. + +#### Sharing Matchers + +Under the hood, a gMock matcher object consists of a pointer to a ref-counted +implementation object. Copying matchers is allowed and very efficient, as only +the pointer is copied. When the last matcher that references the implementation +object dies, the implementation object will be deleted. + +Therefore, if you have some complex matcher that you want to use again and +again, there is no need to build it everytime. Just assign it to a matcher +variable and use that variable repeatedly! For example, + +```cpp +using ::testing::AllOf; +using ::testing::Gt; +using ::testing::Le; +using ::testing::Matcher; +... + Matcher in_range = AllOf(Gt(5), Le(10)); + ... use in_range as a matcher in multiple EXPECT_CALLs ... +``` + +#### Matchers must have no side-effects {#PureMatchers} + +WARNING: gMock does not guarantee when or how many times a matcher will be +invoked. Therefore, all matchers must be *purely functional*: they cannot have +any side effects, and the match result must not depend on anything other than +the matcher's parameters and the value being matched. + +This requirement must be satisfied no matter how a matcher is defined (e.g., if +it is one of the standard matchers, or a custom matcher). In particular, a +matcher can never call a mock function, as that will affect the state of the +mock object and gMock. + +### Setting Expectations + +#### Knowing When to Expect {#UseOnCall} + + + +**`ON_CALL`** is likely the *single most under-utilized construct* in gMock. + +There are basically two constructs for defining the behavior of a mock object: +`ON_CALL` and `EXPECT_CALL`. The difference? `ON_CALL` defines what happens when +a mock method is called, but doesn't imply any expectation on the method +being called. `EXPECT_CALL` not only defines the behavior, but also sets an +expectation that the method will be called with the given arguments, for the +given number of times (and *in the given order* when you specify the order +too). + +Since `EXPECT_CALL` does more, isn't it better than `ON_CALL`? Not really. Every +`EXPECT_CALL` adds a constraint on the behavior of the code under test. Having +more constraints than necessary is *baaad* - even worse than not having enough +constraints. + +This may be counter-intuitive. How could tests that verify more be worse than +tests that verify less? Isn't verification the whole point of tests? + +The answer lies in *what* a test should verify. **A good test verifies the +contract of the code.** If a test over-specifies, it doesn't leave enough +freedom to the implementation. As a result, changing the implementation without +breaking the contract (e.g. refactoring and optimization), which should be +perfectly fine to do, can break such tests. Then you have to spend time fixing +them, only to see them broken again the next time the implementation is changed. + +Keep in mind that one doesn't have to verify more than one property in one test. +In fact, **it's a good style to verify only one thing in one test.** If you do +that, a bug will likely break only one or two tests instead of dozens (which +case would you rather debug?). If you are also in the habit of giving tests +descriptive names that tell what they verify, you can often easily guess what's +wrong just from the test log itself. + +So use `ON_CALL` by default, and only use `EXPECT_CALL` when you actually intend +to verify that the call is made. For example, you may have a bunch of `ON_CALL`s +in your test fixture to set the common mock behavior shared by all tests in the +same group, and write (scarcely) different `EXPECT_CALL`s in different `TEST_F`s +to verify different aspects of the code's behavior. Compared with the style +where each `TEST` has many `EXPECT_CALL`s, this leads to tests that are more +resilient to implementational changes (and thus less likely to require +maintenance) and makes the intent of the tests more obvious (so they are easier +to maintain when you do need to maintain them). + +If you are bothered by the "Uninteresting mock function call" message printed +when a mock method without an `EXPECT_CALL` is called, you may use a `NiceMock` +instead to suppress all such messages for the mock object, or suppress the +message for specific methods by adding `EXPECT_CALL(...).Times(AnyNumber())`. DO +NOT suppress it by blindly adding an `EXPECT_CALL(...)`, or you'll have a test +that's a pain to maintain. + +#### Ignoring Uninteresting Calls + +If you are not interested in how a mock method is called, just don't say +anything about it. In this case, if the method is ever called, gMock will +perform its default action to allow the test program to continue. If you are not +happy with the default action taken by gMock, you can override it using +`DefaultValue::Set()` (described [here](#DefaultValue)) or `ON_CALL()`. + +Please note that once you expressed interest in a particular mock method (via +`EXPECT_CALL()`), all invocations to it must match some expectation. If this +function is called but the arguments don't match any `EXPECT_CALL()` statement, +it will be an error. + +#### Disallowing Unexpected Calls + +If a mock method shouldn't be called at all, explicitly say so: + +```cpp +using ::testing::_; +... + EXPECT_CALL(foo, Bar(_)) + .Times(0); +``` + +If some calls to the method are allowed, but the rest are not, just list all the +expected calls: + +```cpp +using ::testing::AnyNumber; +using ::testing::Gt; +... + EXPECT_CALL(foo, Bar(5)); + EXPECT_CALL(foo, Bar(Gt(10))) + .Times(AnyNumber()); +``` + +A call to `foo.Bar()` that doesn't match any of the `EXPECT_CALL()` statements +will be an error. + +#### Understanding Uninteresting vs Unexpected Calls {#uninteresting-vs-unexpected} + +*Uninteresting* calls and *unexpected* calls are different concepts in gMock. +*Very* different. + +A call `x.Y(...)` is **uninteresting** if there's *not even a single* +`EXPECT_CALL(x, Y(...))` set. In other words, the test isn't interested in the +`x.Y()` method at all, as evident in that the test doesn't care to say anything +about it. + +A call `x.Y(...)` is **unexpected** if there are *some* `EXPECT_CALL(x, +Y(...))`s set, but none of them matches the call. Put another way, the test is +interested in the `x.Y()` method (therefore it explicitly sets some +`EXPECT_CALL` to verify how it's called); however, the verification fails as the +test doesn't expect this particular call to happen. + +**An unexpected call is always an error,** as the code under test doesn't behave +the way the test expects it to behave. + +**By default, an uninteresting call is not an error,** as it violates no +constraint specified by the test. (gMock's philosophy is that saying nothing +means there is no constraint.) However, it leads to a warning, as it *might* +indicate a problem (e.g. the test author might have forgotten to specify a +constraint). + +In gMock, `NiceMock` and `StrictMock` can be used to make a mock class "nice" or +"strict". How does this affect uninteresting calls and unexpected calls? + +A **nice mock** suppresses uninteresting call *warnings*. It is less chatty than +the default mock, but otherwise is the same. If a test fails with a default +mock, it will also fail using a nice mock instead. And vice versa. Don't expect +making a mock nice to change the test's result. + +A **strict mock** turns uninteresting call warnings into errors. So making a +mock strict may change the test's result. + +Let's look at an example: + +```cpp +TEST(...) { + NiceMock mock_registry; + EXPECT_CALL(mock_registry, GetDomainOwner("google.com")) + .WillRepeatedly(Return("Larry Page")); + + // Use mock_registry in code under test. + ... &mock_registry ... +} +``` + +The sole `EXPECT_CALL` here says that all calls to `GetDomainOwner()` must have +`"google.com"` as the argument. If `GetDomainOwner("yahoo.com")` is called, it +will be an unexpected call, and thus an error. *Having a nice mock doesn't +change the severity of an unexpected call.* + +So how do we tell gMock that `GetDomainOwner()` can be called with some other +arguments as well? The standard technique is to add a "catch all" `EXPECT_CALL`: + +```cpp + EXPECT_CALL(mock_registry, GetDomainOwner(_)) + .Times(AnyNumber()); // catches all other calls to this method. + EXPECT_CALL(mock_registry, GetDomainOwner("google.com")) + .WillRepeatedly(Return("Larry Page")); +``` + +Remember that `_` is the wildcard matcher that matches anything. With this, if +`GetDomainOwner("google.com")` is called, it will do what the second +`EXPECT_CALL` says; if it is called with a different argument, it will do what +the first `EXPECT_CALL` says. + +Note that the order of the two `EXPECT_CALL`s is important, as a newer +`EXPECT_CALL` takes precedence over an older one. + +For more on uninteresting calls, nice mocks, and strict mocks, read +["The Nice, the Strict, and the Naggy"](#NiceStrictNaggy). + +#### Ignoring Uninteresting Arguments {#ParameterlessExpectations} + +If your test doesn't care about the parameters (it only cares about the number +or order of calls), you can often simply omit the parameter list: + +```cpp + // Expect foo.Bar( ... ) twice with any arguments. + EXPECT_CALL(foo, Bar).Times(2); + + // Delegate to the given method whenever the factory is invoked. + ON_CALL(foo_factory, MakeFoo) + .WillByDefault(&BuildFooForTest); +``` + +This functionality is only available when a method is not overloaded; to prevent +unexpected behavior it is a compilation error to try to set an expectation on a +method where the specific overload is ambiguous. You can work around this by +supplying a [simpler mock interface](#SimplerInterfaces) than the mocked class +provides. + +This pattern is also useful when the arguments are interesting, but match logic +is substantially complex. You can leave the argument list unspecified and use +SaveArg actions to [save the values for later verification](#SaveArgVerify). If +you do that, you can easily differentiate calling the method the wrong number of +times from calling it with the wrong arguments. + +#### Expecting Ordered Calls {#OrderedCalls} + +Although an `EXPECT_CALL()` statement defined earlier takes precedence when +gMock tries to match a function call with an expectation, by default calls don't +have to happen in the order `EXPECT_CALL()` statements are written. For example, +if the arguments match the matchers in the third `EXPECT_CALL()`, but not those +in the first two, then the third expectation will be used. + +If you would rather have all calls occur in the order of the expectations, put +the `EXPECT_CALL()` statements in a block where you define a variable of type +`InSequence`: + +```cpp +using ::testing::_; +using ::testing::InSequence; + + { + InSequence s; + + EXPECT_CALL(foo, DoThis(5)); + EXPECT_CALL(bar, DoThat(_)) + .Times(2); + EXPECT_CALL(foo, DoThis(6)); + } +``` + +In this example, we expect a call to `foo.DoThis(5)`, followed by two calls to +`bar.DoThat()` where the argument can be anything, which are in turn followed by +a call to `foo.DoThis(6)`. If a call occurred out-of-order, gMock will report an +error. + +#### Expecting Partially Ordered Calls {#PartialOrder} + +Sometimes requiring everything to occur in a predetermined order can lead to +brittle tests. For example, we may care about `A` occurring before both `B` and +`C`, but aren't interested in the relative order of `B` and `C`. In this case, +the test should reflect our real intent, instead of being overly constraining. + +gMock allows you to impose an arbitrary DAG (directed acyclic graph) on the +calls. One way to express the DAG is to use the [After](#AfterClause) clause of +`EXPECT_CALL`. + +Another way is via the `InSequence()` clause (not the same as the `InSequence` +class), which we borrowed from jMock 2. It's less flexible than `After()`, but +more convenient when you have long chains of sequential calls, as it doesn't +require you to come up with different names for the expectations in the chains. +Here's how it works: + +If we view `EXPECT_CALL()` statements as nodes in a graph, and add an edge from +node A to node B wherever A must occur before B, we can get a DAG. We use the +term "sequence" to mean a directed path in this DAG. Now, if we decompose the +DAG into sequences, we just need to know which sequences each `EXPECT_CALL()` +belongs to in order to be able to reconstruct the original DAG. + +So, to specify the partial order on the expectations we need to do two things: +first to define some `Sequence` objects, and then for each `EXPECT_CALL()` say +which `Sequence` objects it is part of. + +Expectations in the same sequence must occur in the order they are written. For +example, + +```cpp +using ::testing::Sequence; +... + Sequence s1, s2; + + EXPECT_CALL(foo, A()) + .InSequence(s1, s2); + EXPECT_CALL(bar, B()) + .InSequence(s1); + EXPECT_CALL(bar, C()) + .InSequence(s2); + EXPECT_CALL(foo, D()) + .InSequence(s2); +``` + +specifies the following DAG (where `s1` is `A -> B`, and `s2` is `A -> C -> D`): + +```text + +---> B + | + A ---| + | + +---> C ---> D +``` + +This means that A must occur before B and C, and C must occur before D. There's +no restriction about the order other than these. + +#### Controlling When an Expectation Retires + +When a mock method is called, gMock only considers expectations that are still +active. An expectation is active when created, and becomes inactive (aka +*retires*) when a call that has to occur later has occurred. For example, in + +```cpp +using ::testing::_; +using ::testing::Sequence; +... + Sequence s1, s2; + + EXPECT_CALL(log, Log(WARNING, _, "File too large.")) // #1 + .Times(AnyNumber()) + .InSequence(s1, s2); + EXPECT_CALL(log, Log(WARNING, _, "Data set is empty.")) // #2 + .InSequence(s1); + EXPECT_CALL(log, Log(WARNING, _, "User not found.")) // #3 + .InSequence(s2); +``` + +as soon as either #2 or #3 is matched, #1 will retire. If a warning `"File too +large."` is logged after this, it will be an error. + +Note that an expectation doesn't retire automatically when it's saturated. For +example, + +```cpp +using ::testing::_; +... + EXPECT_CALL(log, Log(WARNING, _, _)); // #1 + EXPECT_CALL(log, Log(WARNING, _, "File too large.")); // #2 +``` + +says that there will be exactly one warning with the message `"File too +large."`. If the second warning contains this message too, #2 will match again +and result in an upper-bound-violated error. + +If this is not what you want, you can ask an expectation to retire as soon as it +becomes saturated: + +```cpp +using ::testing::_; +... + EXPECT_CALL(log, Log(WARNING, _, _)); // #1 + EXPECT_CALL(log, Log(WARNING, _, "File too large.")) // #2 + .RetiresOnSaturation(); +``` + +Here #2 can be used only once, so if you have two warnings with the message +`"File too large."`, the first will match #2 and the second will match #1 - +there will be no error. + +### Using Actions + +#### Returning References from Mock Methods + +If a mock function's return type is a reference, you need to use `ReturnRef()` +instead of `Return()` to return a result: + +```cpp +using ::testing::ReturnRef; + +class MockFoo : public Foo { + public: + MOCK_METHOD(Bar&, GetBar, (), (override)); +}; +... + MockFoo foo; + Bar bar; + EXPECT_CALL(foo, GetBar()) + .WillOnce(ReturnRef(bar)); +... +``` + +#### Returning Live Values from Mock Methods + +The `Return(x)` action saves a copy of `x` when the action is created, and +always returns the same value whenever it's executed. Sometimes you may want to +instead return the *live* value of `x` (i.e. its value at the time when the +action is *executed*.). Use either `ReturnRef()` or `ReturnPointee()` for this +purpose. + +If the mock function's return type is a reference, you can do it using +`ReturnRef(x)`, as shown in the previous recipe ("Returning References from Mock +Methods"). However, gMock doesn't let you use `ReturnRef()` in a mock function +whose return type is not a reference, as doing that usually indicates a user +error. So, what shall you do? + +Though you may be tempted, DO NOT use `ByRef()`: + +```cpp +using testing::ByRef; +using testing::Return; + +class MockFoo : public Foo { + public: + MOCK_METHOD(int, GetValue, (), (override)); +}; +... + int x = 0; + MockFoo foo; + EXPECT_CALL(foo, GetValue()) + .WillRepeatedly(Return(ByRef(x))); // Wrong! + x = 42; + EXPECT_EQ(42, foo.GetValue()); +``` + +Unfortunately, it doesn't work here. The above code will fail with error: + +```text +Value of: foo.GetValue() + Actual: 0 +Expected: 42 +``` + +The reason is that `Return(*value*)` converts `value` to the actual return type +of the mock function at the time when the action is *created*, not when it is +*executed*. (This behavior was chosen for the action to be safe when `value` is +a proxy object that references some temporary objects.) As a result, `ByRef(x)` +is converted to an `int` value (instead of a `const int&`) when the expectation +is set, and `Return(ByRef(x))` will always return 0. + +`ReturnPointee(pointer)` was provided to solve this problem specifically. It +returns the value pointed to by `pointer` at the time the action is *executed*: + +```cpp +using testing::ReturnPointee; +... + int x = 0; + MockFoo foo; + EXPECT_CALL(foo, GetValue()) + .WillRepeatedly(ReturnPointee(&x)); // Note the & here. + x = 42; + EXPECT_EQ(42, foo.GetValue()); // This will succeed now. +``` + +#### Combining Actions + +Want to do more than one thing when a function is called? That's fine. `DoAll()` +allow you to do sequence of actions every time. Only the return value of the +last action in the sequence will be used. + +```cpp +using ::testing::_; +using ::testing::DoAll; + +class MockFoo : public Foo { + public: + MOCK_METHOD(bool, Bar, (int n), (override)); +}; +... + EXPECT_CALL(foo, Bar(_)) + .WillOnce(DoAll(action_1, + action_2, + ... + action_n)); +``` + +#### Verifying Complex Arguments {#SaveArgVerify} + +If you want to verify that a method is called with a particular argument but the +match criteria is complex, it can be difficult to distinguish between +cardinality failures (calling the method the wrong number of times) and argument +match failures. Similarly, if you are matching multiple parameters, it may not +be easy to distinguishing which argument failed to match. For example: + +```cpp + // Not ideal: this could fail because of a problem with arg1 or arg2, or maybe + // just the method wasn't called. + EXPECT_CALL(foo, SendValues(_, ElementsAre(1, 4, 4, 7), EqualsProto( ... ))); +``` + +You can instead save the arguments and test them individually: + +```cpp + EXPECT_CALL(foo, SendValues) + .WillOnce(DoAll(SaveArg<1>(&actual_array), SaveArg<2>(&actual_proto))); + ... run the test + EXPECT_THAT(actual_array, ElementsAre(1, 4, 4, 7)); + EXPECT_THAT(actual_proto, EqualsProto( ... )); +``` + +#### Mocking Side Effects {#MockingSideEffects} + +Sometimes a method exhibits its effect not via returning a value but via side +effects. For example, it may change some global state or modify an output +argument. To mock side effects, in general you can define your own action by +implementing `::testing::ActionInterface`. + +If all you need to do is to change an output argument, the built-in +`SetArgPointee()` action is convenient: + +```cpp +using ::testing::_; +using ::testing::SetArgPointee; + +class MockMutator : public Mutator { + public: + MOCK_METHOD(void, Mutate, (bool mutate, int* value), (override)); + ... +} +... + MockMutator mutator; + EXPECT_CALL(mutator, Mutate(true, _)) + .WillOnce(SetArgPointee<1>(5)); +``` + +In this example, when `mutator.Mutate()` is called, we will assign 5 to the +`int` variable pointed to by argument #1 (0-based). + +`SetArgPointee()` conveniently makes an internal copy of the value you pass to +it, removing the need to keep the value in scope and alive. The implication +however is that the value must have a copy constructor and assignment operator. + +If the mock method also needs to return a value as well, you can chain +`SetArgPointee()` with `Return()` using `DoAll()`, remembering to put the +`Return()` statement last: + +```cpp +using ::testing::_; +using ::testing::Return; +using ::testing::SetArgPointee; + +class MockMutator : public Mutator { + public: + ... + MOCK_METHOD(bool, MutateInt, (int* value), (override)); +} +... + MockMutator mutator; + EXPECT_CALL(mutator, MutateInt(_)) + .WillOnce(DoAll(SetArgPointee<0>(5), + Return(true))); +``` + +Note, however, that if you use the `ReturnOKWith()` method, it will override the +values provided by `SetArgPointee()` in the response parameters of your function +call. + +If the output argument is an array, use the `SetArrayArgument(first, last)` +action instead. It copies the elements in source range `[first, last)` to the +array pointed to by the `N`-th (0-based) argument: + +```cpp +using ::testing::NotNull; +using ::testing::SetArrayArgument; + +class MockArrayMutator : public ArrayMutator { + public: + MOCK_METHOD(void, Mutate, (int* values, int num_values), (override)); + ... +} +... + MockArrayMutator mutator; + int values[5] = {1, 2, 3, 4, 5}; + EXPECT_CALL(mutator, Mutate(NotNull(), 5)) + .WillOnce(SetArrayArgument<0>(values, values + 5)); +``` + +This also works when the argument is an output iterator: + +```cpp +using ::testing::_; +using ::testing::SetArrayArgument; + +class MockRolodex : public Rolodex { + public: + MOCK_METHOD(void, GetNames, (std::back_insert_iterator>), + (override)); + ... +} +... + MockRolodex rolodex; + vector names; + names.push_back("George"); + names.push_back("John"); + names.push_back("Thomas"); + EXPECT_CALL(rolodex, GetNames(_)) + .WillOnce(SetArrayArgument<0>(names.begin(), names.end())); +``` + +#### Changing a Mock Object's Behavior Based on the State + +If you expect a call to change the behavior of a mock object, you can use +`::testing::InSequence` to specify different behaviors before and after the +call: + +```cpp +using ::testing::InSequence; +using ::testing::Return; + +... + { + InSequence seq; + EXPECT_CALL(my_mock, IsDirty()) + .WillRepeatedly(Return(true)); + EXPECT_CALL(my_mock, Flush()); + EXPECT_CALL(my_mock, IsDirty()) + .WillRepeatedly(Return(false)); + } + my_mock.FlushIfDirty(); +``` + +This makes `my_mock.IsDirty()` return `true` before `my_mock.Flush()` is called +and return `false` afterwards. + +If the behavior change is more complex, you can store the effects in a variable +and make a mock method get its return value from that variable: + +```cpp +using ::testing::_; +using ::testing::SaveArg; +using ::testing::Return; + +ACTION_P(ReturnPointee, p) { return *p; } +... + int previous_value = 0; + EXPECT_CALL(my_mock, GetPrevValue) + .WillRepeatedly(ReturnPointee(&previous_value)); + EXPECT_CALL(my_mock, UpdateValue) + .WillRepeatedly(SaveArg<0>(&previous_value)); + my_mock.DoSomethingToUpdateValue(); +``` + +Here `my_mock.GetPrevValue()` will always return the argument of the last +`UpdateValue()` call. + +#### Setting the Default Value for a Return Type {#DefaultValue} + +If a mock method's return type is a built-in C++ type or pointer, by default it +will return 0 when invoked. Also, in C++ 11 and above, a mock method whose +return type has a default constructor will return a default-constructed value by +default. You only need to specify an action if this default value doesn't work +for you. + +Sometimes, you may want to change this default value, or you may want to specify +a default value for types gMock doesn't know about. You can do this using the +`::testing::DefaultValue` class template: + +```cpp +using ::testing::DefaultValue; + +class MockFoo : public Foo { + public: + MOCK_METHOD(Bar, CalculateBar, (), (override)); +}; + + +... + Bar default_bar; + // Sets the default return value for type Bar. + DefaultValue::Set(default_bar); + + MockFoo foo; + + // We don't need to specify an action here, as the default + // return value works for us. + EXPECT_CALL(foo, CalculateBar()); + + foo.CalculateBar(); // This should return default_bar. + + // Unsets the default return value. + DefaultValue::Clear(); +``` + +Please note that changing the default value for a type can make you tests hard +to understand. We recommend you to use this feature judiciously. For example, +you may want to make sure the `Set()` and `Clear()` calls are right next to the +code that uses your mock. + +#### Setting the Default Actions for a Mock Method + +You've learned how to change the default value of a given type. However, this +may be too coarse for your purpose: perhaps you have two mock methods with the +same return type and you want them to have different behaviors. The `ON_CALL()` +macro allows you to customize your mock's behavior at the method level: + +```cpp +using ::testing::_; +using ::testing::AnyNumber; +using ::testing::Gt; +using ::testing::Return; +... + ON_CALL(foo, Sign(_)) + .WillByDefault(Return(-1)); + ON_CALL(foo, Sign(0)) + .WillByDefault(Return(0)); + ON_CALL(foo, Sign(Gt(0))) + .WillByDefault(Return(1)); + + EXPECT_CALL(foo, Sign(_)) + .Times(AnyNumber()); + + foo.Sign(5); // This should return 1. + foo.Sign(-9); // This should return -1. + foo.Sign(0); // This should return 0. +``` + +As you may have guessed, when there are more than one `ON_CALL()` statements, +the newer ones in the order take precedence over the older ones. In other words, +the **last** one that matches the function arguments will be used. This matching +order allows you to set up the common behavior in a mock object's constructor or +the test fixture's set-up phase and specialize the mock's behavior later. + +Note that both `ON_CALL` and `EXPECT_CALL` have the same "later statements take +precedence" rule, but they don't interact. That is, `EXPECT_CALL`s have their +own precedence order distinct from the `ON_CALL` precedence order. + +#### Using Functions/Methods/Functors/Lambdas as Actions {#FunctionsAsActions} + +If the built-in actions don't suit you, you can use an existing callable +(function, `std::function`, method, functor, lambda as an action. + + + +```cpp +using ::testing::_; using ::testing::Invoke; + +class MockFoo : public Foo { + public: + MOCK_METHOD(int, Sum, (int x, int y), (override)); + MOCK_METHOD(bool, ComplexJob, (int x), (override)); +}; + +int CalculateSum(int x, int y) { return x + y; } +int Sum3(int x, int y, int z) { return x + y + z; } + +class Helper { + public: + bool ComplexJob(int x); +}; + +... + MockFoo foo; + Helper helper; + EXPECT_CALL(foo, Sum(_, _)) + .WillOnce(&CalculateSum) + .WillRepeatedly(Invoke(NewPermanentCallback(Sum3, 1))); + EXPECT_CALL(foo, ComplexJob(_)) + .WillOnce(Invoke(&helper, &Helper::ComplexJob)); + .WillRepeatedly([](int x) { return x > 0; }); + + foo.Sum(5, 6); // Invokes CalculateSum(5, 6). + foo.Sum(2, 3); // Invokes Sum3(1, 2, 3). + foo.ComplexJob(10); // Invokes helper.ComplexJob(10). + foo.ComplexJob(-1); // Invokes the inline lambda. +``` + +The only requirement is that the type of the function, etc must be *compatible* +with the signature of the mock function, meaning that the latter's arguments can +be implicitly converted to the corresponding arguments of the former, and the +former's return type can be implicitly converted to that of the latter. So, you +can invoke something whose type is *not* exactly the same as the mock function, +as long as it's safe to do so - nice, huh? + +**`Note:`{.escaped}** + +* The action takes ownership of the callback and will delete it when the + action itself is destructed. +* If the type of a callback is derived from a base callback type `C`, you need + to implicitly cast it to `C` to resolve the overloading, e.g. + + ```cpp + using ::testing::Invoke; + ... + ResultCallback* is_ok = ...; + ... Invoke(is_ok) ...; // This works. + + BlockingClosure* done = new BlockingClosure; + ... Invoke(implicit_cast(done)) ...; // The cast is necessary. + ``` + +#### Using Functions with Extra Info as Actions + +The function or functor you call using `Invoke()` must have the same number of +arguments as the mock function you use it for. Sometimes you may have a function +that takes more arguments, and you are willing to pass in the extra arguments +yourself to fill the gap. You can do this in gMock using callbacks with +pre-bound arguments. Here's an example: + +```cpp +using ::testing::Invoke; + +class MockFoo : public Foo { + public: + MOCK_METHOD(char, DoThis, (int n), (override)); +}; + +char SignOfSum(int x, int y) { + const int sum = x + y; + return (sum > 0) ? '+' : (sum < 0) ? '-' : '0'; +} + +TEST_F(FooTest, Test) { + MockFoo foo; + + EXPECT_CALL(foo, DoThis(2)) + .WillOnce(Invoke(NewPermanentCallback(SignOfSum, 5))); + EXPECT_EQ('+', foo.DoThis(2)); // Invokes SignOfSum(5, 2). +} +``` + +#### Invoking a Function/Method/Functor/Lambda/Callback Without Arguments + +`Invoke()` is very useful for doing actions that are more complex. It passes the +mock function's arguments to the function, etc being invoked such that the +callee has the full context of the call to work with. If the invoked function is +not interested in some or all of the arguments, it can simply ignore them. + +Yet, a common pattern is that a test author wants to invoke a function without +the arguments of the mock function. `Invoke()` allows her to do that using a +wrapper function that throws away the arguments before invoking an underlining +nullary function. Needless to say, this can be tedious and obscures the intent +of the test. + +`InvokeWithoutArgs()` solves this problem. It's like `Invoke()` except that it +doesn't pass the mock function's arguments to the callee. Here's an example: + +```cpp +using ::testing::_; +using ::testing::InvokeWithoutArgs; + +class MockFoo : public Foo { + public: + MOCK_METHOD(bool, ComplexJob, (int n), (override)); +}; + +bool Job1() { ... } +bool Job2(int n, char c) { ... } + +... + MockFoo foo; + EXPECT_CALL(foo, ComplexJob(_)) + .WillOnce(InvokeWithoutArgs(Job1)) + .WillOnce(InvokeWithoutArgs(NewPermanentCallback(Job2, 5, 'a'))); + + foo.ComplexJob(10); // Invokes Job1(). + foo.ComplexJob(20); // Invokes Job2(5, 'a'). +``` + +**`Note:`{.escaped}** + +* The action takes ownership of the callback and will delete it when the + action itself is destructed. +* If the type of a callback is derived from a base callback type `C`, you need + to implicitly cast it to `C` to resolve the overloading, e.g. + + ```cpp + using ::testing::InvokeWithoutArgs; + ... + ResultCallback* is_ok = ...; + ... InvokeWithoutArgs(is_ok) ...; // This works. + + BlockingClosure* done = ...; + ... InvokeWithoutArgs(implicit_cast(done)) ...; + // The cast is necessary. + ``` + +#### Invoking an Argument of the Mock Function + +Sometimes a mock function will receive a function pointer, a functor (in other +words, a "callable") as an argument, e.g. + +```cpp +class MockFoo : public Foo { + public: + MOCK_METHOD(bool, DoThis, (int n, (ResultCallback1* callback)), + (override)); +}; +``` + +and you may want to invoke this callable argument: + +```cpp +using ::testing::_; +... + MockFoo foo; + EXPECT_CALL(foo, DoThis(_, _)) + .WillOnce(...); + // Will execute callback->Run(5), where callback is the + // second argument DoThis() receives. +``` + +NOTE: The section below is legacy documentation from before C++ had lambdas: + +Arghh, you need to refer to a mock function argument but C++ has no lambda +(yet), so you have to define your own action. :-( Or do you really? + +Well, gMock has an action to solve *exactly* this problem: + +```cpp +InvokeArgument(arg_1, arg_2, ..., arg_m) +``` + +will invoke the `N`-th (0-based) argument the mock function receives, with +`arg_1`, `arg_2`, ..., and `arg_m`. No matter if the argument is a function +pointer, a functor, or a callback. gMock handles them all. + +With that, you could write: + +```cpp +using ::testing::_; +using ::testing::InvokeArgument; +... + EXPECT_CALL(foo, DoThis(_, _)) + .WillOnce(InvokeArgument<1>(5)); + // Will execute callback->Run(5), where callback is the + // second argument DoThis() receives. +``` + +What if the callable takes an argument by reference? No problem - just wrap it +inside `ByRef()`: + +```cpp + ... + MOCK_METHOD(bool, Bar, + ((ResultCallback2* callback)), + (override)); + ... + using ::testing::_; + using ::testing::ByRef; + using ::testing::InvokeArgument; + ... + MockFoo foo; + Helper helper; + ... + EXPECT_CALL(foo, Bar(_)) + .WillOnce(InvokeArgument<0>(5, ByRef(helper))); + // ByRef(helper) guarantees that a reference to helper, not a copy of it, + // will be passed to the callback. +``` + +What if the callable takes an argument by reference and we do **not** wrap the +argument in `ByRef()`? Then `InvokeArgument()` will *make a copy* of the +argument, and pass a *reference to the copy*, instead of a reference to the +original value, to the callable. This is especially handy when the argument is a +temporary value: + +```cpp + ... + MOCK_METHOD(bool, DoThat, (bool (*f)(const double& x, const string& s)), + (override)); + ... + using ::testing::_; + using ::testing::InvokeArgument; + ... + MockFoo foo; + ... + EXPECT_CALL(foo, DoThat(_)) + .WillOnce(InvokeArgument<0>(5.0, string("Hi"))); + // Will execute (*f)(5.0, string("Hi")), where f is the function pointer + // DoThat() receives. Note that the values 5.0 and string("Hi") are + // temporary and dead once the EXPECT_CALL() statement finishes. Yet + // it's fine to perform this action later, since a copy of the values + // are kept inside the InvokeArgument action. +``` + +#### Ignoring an Action's Result + +Sometimes you have an action that returns *something*, but you need an action +that returns `void` (perhaps you want to use it in a mock function that returns +`void`, or perhaps it needs to be used in `DoAll()` and it's not the last in the +list). `IgnoreResult()` lets you do that. For example: + +```cpp +using ::testing::_; +using ::testing::DoAll; +using ::testing::IgnoreResult; +using ::testing::Return; + +int Process(const MyData& data); +string DoSomething(); + +class MockFoo : public Foo { + public: + MOCK_METHOD(void, Abc, (const MyData& data), (override)); + MOCK_METHOD(bool, Xyz, (), (override)); +}; + + ... + MockFoo foo; + EXPECT_CALL(foo, Abc(_)) + // .WillOnce(Invoke(Process)); + // The above line won't compile as Process() returns int but Abc() needs + // to return void. + .WillOnce(IgnoreResult(Process)); + EXPECT_CALL(foo, Xyz()) + .WillOnce(DoAll(IgnoreResult(DoSomething), + // Ignores the string DoSomething() returns. + Return(true))); +``` + +Note that you **cannot** use `IgnoreResult()` on an action that already returns +`void`. Doing so will lead to ugly compiler errors. + +#### Selecting an Action's Arguments {#SelectingArgs} + +Say you have a mock function `Foo()` that takes seven arguments, and you have a +custom action that you want to invoke when `Foo()` is called. Trouble is, the +custom action only wants three arguments: + +```cpp +using ::testing::_; +using ::testing::Invoke; +... + MOCK_METHOD(bool, Foo, + (bool visible, const string& name, int x, int y, + (const map>), double& weight, double min_weight, + double max_wight)); +... +bool IsVisibleInQuadrant1(bool visible, int x, int y) { + return visible && x >= 0 && y >= 0; +} +... + EXPECT_CALL(mock, Foo) + .WillOnce(Invoke(IsVisibleInQuadrant1)); // Uh, won't compile. :-( +``` + +To please the compiler God, you need to define an "adaptor" that has the same +signature as `Foo()` and calls the custom action with the right arguments: + +```cpp +using ::testing::_; +using ::testing::Invoke; +... +bool MyIsVisibleInQuadrant1(bool visible, const string& name, int x, int y, + const map, double>& weight, + double min_weight, double max_wight) { + return IsVisibleInQuadrant1(visible, x, y); +} +... + EXPECT_CALL(mock, Foo) + .WillOnce(Invoke(MyIsVisibleInQuadrant1)); // Now it works. +``` + +But isn't this awkward? + +gMock provides a generic *action adaptor*, so you can spend your time minding +more important business than writing your own adaptors. Here's the syntax: + +```cpp +WithArgs(action) +``` + +creates an action that passes the arguments of the mock function at the given +indices (0-based) to the inner `action` and performs it. Using `WithArgs`, our +original example can be written as: + +```cpp +using ::testing::_; +using ::testing::Invoke; +using ::testing::WithArgs; +... + EXPECT_CALL(mock, Foo) + .WillOnce(WithArgs<0, 2, 3>(Invoke(IsVisibleInQuadrant1))); // No need to define your own adaptor. +``` + +For better readability, gMock also gives you: + +* `WithoutArgs(action)` when the inner `action` takes *no* argument, and +* `WithArg(action)` (no `s` after `Arg`) when the inner `action` takes + *one* argument. + +As you may have realized, `InvokeWithoutArgs(...)` is just syntactic sugar for +`WithoutArgs(Invoke(...))`. + +Here are more tips: + +* The inner action used in `WithArgs` and friends does not have to be + `Invoke()` -- it can be anything. +* You can repeat an argument in the argument list if necessary, e.g. + `WithArgs<2, 3, 3, 5>(...)`. +* You can change the order of the arguments, e.g. `WithArgs<3, 2, 1>(...)`. +* The types of the selected arguments do *not* have to match the signature of + the inner action exactly. It works as long as they can be implicitly + converted to the corresponding arguments of the inner action. For example, + if the 4-th argument of the mock function is an `int` and `my_action` takes + a `double`, `WithArg<4>(my_action)` will work. + +#### Ignoring Arguments in Action Functions + +The [selecting-an-action's-arguments](#SelectingArgs) recipe showed us one way +to make a mock function and an action with incompatible argument lists fit +together. The downside is that wrapping the action in `WithArgs<...>()` can get +tedious for people writing the tests. + +If you are defining a function (or method, functor, lambda, callback) to be used +with `Invoke*()`, and you are not interested in some of its arguments, an +alternative to `WithArgs` is to declare the uninteresting arguments as `Unused`. +This makes the definition less cluttered and less fragile in case the types of +the uninteresting arguments change. It could also increase the chance the action +function can be reused. For example, given + +```cpp + public: + MOCK_METHOD(double, Foo, double(const string& label, double x, double y), + (override)); + MOCK_METHOD(double, Bar, (int index, double x, double y), (override)); +``` + +instead of + +```cpp +using ::testing::_; +using ::testing::Invoke; + +double DistanceToOriginWithLabel(const string& label, double x, double y) { + return sqrt(x*x + y*y); +} +double DistanceToOriginWithIndex(int index, double x, double y) { + return sqrt(x*x + y*y); +} +... + EXPECT_CALL(mock, Foo("abc", _, _)) + .WillOnce(Invoke(DistanceToOriginWithLabel)); + EXPECT_CALL(mock, Bar(5, _, _)) + .WillOnce(Invoke(DistanceToOriginWithIndex)); +``` + +you could write + +```cpp +using ::testing::_; +using ::testing::Invoke; +using ::testing::Unused; + +double DistanceToOrigin(Unused, double x, double y) { + return sqrt(x*x + y*y); +} +... + EXPECT_CALL(mock, Foo("abc", _, _)) + .WillOnce(Invoke(DistanceToOrigin)); + EXPECT_CALL(mock, Bar(5, _, _)) + .WillOnce(Invoke(DistanceToOrigin)); +``` + +#### Sharing Actions + +Just like matchers, a gMock action object consists of a pointer to a ref-counted +implementation object. Therefore copying actions is also allowed and very +efficient. When the last action that references the implementation object dies, +the implementation object will be deleted. + +If you have some complex action that you want to use again and again, you may +not have to build it from scratch everytime. If the action doesn't have an +internal state (i.e. if it always does the same thing no matter how many times +it has been called), you can assign it to an action variable and use that +variable repeatedly. For example: + +```cpp +using ::testing::Action; +using ::testing::DoAll; +using ::testing::Return; +using ::testing::SetArgPointee; +... + Action set_flag = DoAll(SetArgPointee<0>(5), + Return(true)); + ... use set_flag in .WillOnce() and .WillRepeatedly() ... +``` + +However, if the action has its own state, you may be surprised if you share the +action object. Suppose you have an action factory `IncrementCounter(init)` which +creates an action that increments and returns a counter whose initial value is +`init`, using two actions created from the same expression and using a shared +action will exhibit different behaviors. Example: + +```cpp + EXPECT_CALL(foo, DoThis()) + .WillRepeatedly(IncrementCounter(0)); + EXPECT_CALL(foo, DoThat()) + .WillRepeatedly(IncrementCounter(0)); + foo.DoThis(); // Returns 1. + foo.DoThis(); // Returns 2. + foo.DoThat(); // Returns 1 - Blah() uses a different + // counter than Bar()'s. +``` + +versus + +```cpp +using ::testing::Action; +... + Action increment = IncrementCounter(0); + EXPECT_CALL(foo, DoThis()) + .WillRepeatedly(increment); + EXPECT_CALL(foo, DoThat()) + .WillRepeatedly(increment); + foo.DoThis(); // Returns 1. + foo.DoThis(); // Returns 2. + foo.DoThat(); // Returns 3 - the counter is shared. +``` + +#### Testing Asynchronous Behavior + +One oft-encountered problem with gMock is that it can be hard to test +asynchronous behavior. Suppose you had a `EventQueue` class that you wanted to +test, and you created a separate `EventDispatcher` interface so that you could +easily mock it out. However, the implementation of the class fired all the +events on a background thread, which made test timings difficult. You could just +insert `sleep()` statements and hope for the best, but that makes your test +behavior nondeterministic. A better way is to use gMock actions and +`Notification` objects to force your asynchronous test to behave synchronously. + +```cpp +using ::testing::DoAll; +using ::testing::InvokeWithoutArgs; +using ::testing::Return; + +class MockEventDispatcher : public EventDispatcher { + MOCK_METHOD(bool, DispatchEvent, (int32), (override)); +}; + +ACTION_P(Notify, notification) { + notification->Notify(); +} + +TEST(EventQueueTest, EnqueueEventTest) { + MockEventDispatcher mock_event_dispatcher; + EventQueue event_queue(&mock_event_dispatcher); + + const int32 kEventId = 321; + Notification done; + EXPECT_CALL(mock_event_dispatcher, DispatchEvent(kEventId)) + .WillOnce(Notify(&done)); + + event_queue.EnqueueEvent(kEventId); + done.WaitForNotification(); +} +``` + +In the example above, we set our normal gMock expectations, but then add an +additional action to notify the `Notification` object. Now we can just call +`Notification::WaitForNotification()` in the main thread to wait for the +asynchronous call to finish. After that, our test suite is complete and we can +safely exit. + +Note: this example has a downside: namely, if the expectation is not satisfied, +our test will run forever. It will eventually time-out and fail, but it will +take longer and be slightly harder to debug. To alleviate this problem, you can +use `WaitForNotificationWithTimeout(ms)` instead of `WaitForNotification()`. + +### Misc Recipes on Using gMock + +#### Mocking Methods That Use Move-Only Types + +C++11 introduced *move-only types*. A move-only-typed value can be moved from +one object to another, but cannot be copied. `std::unique_ptr` is probably +the most commonly used move-only type. + +Mocking a method that takes and/or returns move-only types presents some +challenges, but nothing insurmountable. This recipe shows you how you can do it. +Note that the support for move-only method arguments was only introduced to +gMock in April 2017; in older code, you may find more complex +[workarounds](#LegacyMoveOnly) for lack of this feature. + +Let’s say we are working on a fictional project that lets one post and share +snippets called “buzzes”. Your code uses these types: + +```cpp +enum class AccessLevel { kInternal, kPublic }; + +class Buzz { + public: + explicit Buzz(AccessLevel access) { ... } + ... +}; + +class Buzzer { + public: + virtual ~Buzzer() {} + virtual std::unique_ptr MakeBuzz(StringPiece text) = 0; + virtual bool ShareBuzz(std::unique_ptr buzz, int64_t timestamp) = 0; + ... +}; +``` + +A `Buzz` object represents a snippet being posted. A class that implements the +`Buzzer` interface is capable of creating and sharing `Buzz`es. Methods in +`Buzzer` may return a `unique_ptr` or take a `unique_ptr`. Now we +need to mock `Buzzer` in our tests. + +To mock a method that accepts or returns move-only types, you just use the +familiar `MOCK_METHOD` syntax as usual: + +```cpp +class MockBuzzer : public Buzzer { + public: + MOCK_METHOD(std::unique_ptr, MakeBuzz, (StringPiece text), (override)); + MOCK_METHOD(bool, ShareBuzz, (std::unique_ptr buzz, int64_t timestamp), + (override)); +}; +``` + +Now that we have the mock class defined, we can use it in tests. In the +following code examples, we assume that we have defined a `MockBuzzer` object +named `mock_buzzer_`: + +```cpp + MockBuzzer mock_buzzer_; +``` + +First let’s see how we can set expectations on the `MakeBuzz()` method, which +returns a `unique_ptr`. + +As usual, if you set an expectation without an action (i.e. the `.WillOnce()` or +`.WillRepeatedly()` clause), when that expectation fires, the default action for +that method will be taken. Since `unique_ptr<>` has a default constructor that +returns a null `unique_ptr`, that’s what you’ll get if you don’t specify an +action: + +```cpp + // Use the default action. + EXPECT_CALL(mock_buzzer_, MakeBuzz("hello")); + + // Triggers the previous EXPECT_CALL. + EXPECT_EQ(nullptr, mock_buzzer_.MakeBuzz("hello")); +``` + +If you are not happy with the default action, you can tweak it as usual; see +[Setting Default Actions](#OnCall). + +If you just need to return a pre-defined move-only value, you can use the +`Return(ByMove(...))` action: + +```cpp + // When this fires, the unique_ptr<> specified by ByMove(...) will + // be returned. + EXPECT_CALL(mock_buzzer_, MakeBuzz("world")) + .WillOnce(Return(ByMove(MakeUnique(AccessLevel::kInternal)))); + + EXPECT_NE(nullptr, mock_buzzer_.MakeBuzz("world")); +``` + +Note that `ByMove()` is essential here - if you drop it, the code won’t compile. + +Quiz time! What do you think will happen if a `Return(ByMove(...))` action is +performed more than once (e.g. you write `... +.WillRepeatedly(Return(ByMove(...)));`)? Come think of it, after the first time +the action runs, the source value will be consumed (since it’s a move-only +value), so the next time around, there’s no value to move from -- you’ll get a +run-time error that `Return(ByMove(...))` can only be run once. + +If you need your mock method to do more than just moving a pre-defined value, +remember that you can always use a lambda or a callable object, which can do +pretty much anything you want: + +```cpp + EXPECT_CALL(mock_buzzer_, MakeBuzz("x")) + .WillRepeatedly([](StringPiece text) { + return MakeUnique(AccessLevel::kInternal); + }); + + EXPECT_NE(nullptr, mock_buzzer_.MakeBuzz("x")); + EXPECT_NE(nullptr, mock_buzzer_.MakeBuzz("x")); +``` + +Every time this `EXPECT_CALL` fires, a new `unique_ptr` will be created +and returned. You cannot do this with `Return(ByMove(...))`. + +That covers returning move-only values; but how do we work with methods +accepting move-only arguments? The answer is that they work normally, although +some actions will not compile when any of method's arguments are move-only. You +can always use `Return`, or a [lambda or functor](#FunctionsAsActions): + +```cpp + using ::testing::Unused; + + EXPECT_CALL(mock_buzzer_, ShareBuzz(NotNull(), _)).WillOnce(Return(true)); + EXPECT_TRUE(mock_buzzer_.ShareBuzz(MakeUnique(AccessLevel::kInternal)), + 0); + + EXPECT_CALL(mock_buzzer_, ShareBuzz(_, _)).WillOnce( + [](std::unique_ptr buzz, Unused) { return buzz != nullptr; }); + EXPECT_FALSE(mock_buzzer_.ShareBuzz(nullptr, 0)); +``` + +Many built-in actions (`WithArgs`, `WithoutArgs`,`DeleteArg`, `SaveArg`, ...) +could in principle support move-only arguments, but the support for this is not +implemented yet. If this is blocking you, please file a bug. + +A few actions (e.g. `DoAll`) copy their arguments internally, so they can never +work with non-copyable objects; you'll have to use functors instead. + +##### Legacy workarounds for move-only types {#LegacyMoveOnly} + +Support for move-only function arguments was only introduced to gMock in April +2017. In older code, you may encounter the following workaround for the lack of +this feature (it is no longer necessary - we're including it just for +reference): + +```cpp +class MockBuzzer : public Buzzer { + public: + MOCK_METHOD(bool, DoShareBuzz, (Buzz* buzz, Time timestamp)); + bool ShareBuzz(std::unique_ptr buzz, Time timestamp) override { + return DoShareBuzz(buzz.get(), timestamp); + } +}; +``` + +The trick is to delegate the `ShareBuzz()` method to a mock method (let’s call +it `DoShareBuzz()`) that does not take move-only parameters. Then, instead of +setting expectations on `ShareBuzz()`, you set them on the `DoShareBuzz()` mock +method: + +```cpp + MockBuzzer mock_buzzer_; + EXPECT_CALL(mock_buzzer_, DoShareBuzz(NotNull(), _)); + + // When one calls ShareBuzz() on the MockBuzzer like this, the call is + // forwarded to DoShareBuzz(), which is mocked. Therefore this statement + // will trigger the above EXPECT_CALL. + mock_buzzer_.ShareBuzz(MakeUnique(AccessLevel::kInternal), 0); +``` + +#### Making the Compilation Faster + +Believe it or not, the *vast majority* of the time spent on compiling a mock +class is in generating its constructor and destructor, as they perform +non-trivial tasks (e.g. verification of the expectations). What's more, mock +methods with different signatures have different types and thus their +constructors/destructors need to be generated by the compiler separately. As a +result, if you mock many different types of methods, compiling your mock class +can get really slow. + +If you are experiencing slow compilation, you can move the definition of your +mock class' constructor and destructor out of the class body and into a `.cc` +file. This way, even if you `#include` your mock class in N files, the compiler +only needs to generate its constructor and destructor once, resulting in a much +faster compilation. + +Let's illustrate the idea using an example. Here's the definition of a mock +class before applying this recipe: + +```cpp +// File mock_foo.h. +... +class MockFoo : public Foo { + public: + // Since we don't declare the constructor or the destructor, + // the compiler will generate them in every translation unit + // where this mock class is used. + + MOCK_METHOD(int, DoThis, (), (override)); + MOCK_METHOD(bool, DoThat, (const char* str), (override)); + ... more mock methods ... +}; +``` + +After the change, it would look like: + +```cpp +// File mock_foo.h. +... +class MockFoo : public Foo { + public: + // The constructor and destructor are declared, but not defined, here. + MockFoo(); + virtual ~MockFoo(); + + MOCK_METHOD(int, DoThis, (), (override)); + MOCK_METHOD(bool, DoThat, (const char* str), (override)); + ... more mock methods ... +}; +``` + +and + +```cpp +// File mock_foo.cc. +#include "path/to/mock_foo.h" + +// The definitions may appear trivial, but the functions actually do a +// lot of things through the constructors/destructors of the member +// variables used to implement the mock methods. +MockFoo::MockFoo() {} +MockFoo::~MockFoo() {} +``` + +#### Forcing a Verification + +When it's being destroyed, your friendly mock object will automatically verify +that all expectations on it have been satisfied, and will generate googletest +failures if not. This is convenient as it leaves you with one less thing to +worry about. That is, unless you are not sure if your mock object will be +destroyed. + +How could it be that your mock object won't eventually be destroyed? Well, it +might be created on the heap and owned by the code you are testing. Suppose +there's a bug in that code and it doesn't delete the mock object properly - you +could end up with a passing test when there's actually a bug. + +Using a heap checker is a good idea and can alleviate the concern, but its +implementation is not 100% reliable. So, sometimes you do want to *force* gMock +to verify a mock object before it is (hopefully) destructed. You can do this +with `Mock::VerifyAndClearExpectations(&mock_object)`: + +```cpp +TEST(MyServerTest, ProcessesRequest) { + using ::testing::Mock; + + MockFoo* const foo = new MockFoo; + EXPECT_CALL(*foo, ...)...; + // ... other expectations ... + + // server now owns foo. + MyServer server(foo); + server.ProcessRequest(...); + + // In case that server's destructor will forget to delete foo, + // this will verify the expectations anyway. + Mock::VerifyAndClearExpectations(foo); +} // server is destroyed when it goes out of scope here. +``` + +**Tip:** The `Mock::VerifyAndClearExpectations()` function returns a `bool` to +indicate whether the verification was successful (`true` for yes), so you can +wrap that function call inside a `ASSERT_TRUE()` if there is no point going +further when the verification has failed. + +#### Using Check Points {#UsingCheckPoints} + +Sometimes you may want to "reset" a mock object at various check points in your +test: at each check point, you verify that all existing expectations on the mock +object have been satisfied, and then you set some new expectations on it as if +it's newly created. This allows you to work with a mock object in "phases" whose +sizes are each manageable. + +One such scenario is that in your test's `SetUp()` function, you may want to put +the object you are testing into a certain state, with the help from a mock +object. Once in the desired state, you want to clear all expectations on the +mock, such that in the `TEST_F` body you can set fresh expectations on it. + +As you may have figured out, the `Mock::VerifyAndClearExpectations()` function +we saw in the previous recipe can help you here. Or, if you are using +`ON_CALL()` to set default actions on the mock object and want to clear the +default actions as well, use `Mock::VerifyAndClear(&mock_object)` instead. This +function does what `Mock::VerifyAndClearExpectations(&mock_object)` does and +returns the same `bool`, **plus** it clears the `ON_CALL()` statements on +`mock_object` too. + +Another trick you can use to achieve the same effect is to put the expectations +in sequences and insert calls to a dummy "check-point" function at specific +places. Then you can verify that the mock function calls do happen at the right +time. For example, if you are exercising code: + +```cpp + Foo(1); + Foo(2); + Foo(3); +``` + +and want to verify that `Foo(1)` and `Foo(3)` both invoke `mock.Bar("a")`, but +`Foo(2)` doesn't invoke anything. You can write: + +```cpp +using ::testing::MockFunction; + +TEST(FooTest, InvokesBarCorrectly) { + MyMock mock; + // Class MockFunction has exactly one mock method. It is named + // Call() and has type F. + MockFunction check; + { + InSequence s; + + EXPECT_CALL(mock, Bar("a")); + EXPECT_CALL(check, Call("1")); + EXPECT_CALL(check, Call("2")); + EXPECT_CALL(mock, Bar("a")); + } + Foo(1); + check.Call("1"); + Foo(2); + check.Call("2"); + Foo(3); +} +``` + +The expectation spec says that the first `Bar("a")` must happen before check +point "1", the second `Bar("a")` must happen after check point "2", and nothing +should happen between the two check points. The explicit check points make it +easy to tell which `Bar("a")` is called by which call to `Foo()`. + +#### Mocking Destructors + +Sometimes you want to make sure a mock object is destructed at the right time, +e.g. after `bar->A()` is called but before `bar->B()` is called. We already know +that you can specify constraints on the [order](#OrderedCalls) of mock function +calls, so all we need to do is to mock the destructor of the mock function. + +This sounds simple, except for one problem: a destructor is a special function +with special syntax and special semantics, and the `MOCK_METHOD` macro doesn't +work for it: + +```cpp +MOCK_METHOD(void, ~MockFoo, ()); // Won't compile! +``` + +The good news is that you can use a simple pattern to achieve the same effect. +First, add a mock function `Die()` to your mock class and call it in the +destructor, like this: + +```cpp +class MockFoo : public Foo { + ... + // Add the following two lines to the mock class. + MOCK_METHOD(void, Die, ()); + virtual ~MockFoo() { Die(); } +}; +``` + +(If the name `Die()` clashes with an existing symbol, choose another name.) Now, +we have translated the problem of testing when a `MockFoo` object dies to +testing when its `Die()` method is called: + +```cpp + MockFoo* foo = new MockFoo; + MockBar* bar = new MockBar; + ... + { + InSequence s; + + // Expects *foo to die after bar->A() and before bar->B(). + EXPECT_CALL(*bar, A()); + EXPECT_CALL(*foo, Die()); + EXPECT_CALL(*bar, B()); + } +``` + +And that's that. + +#### Using gMock and Threads {#UsingThreads} + +In a **unit** test, it's best if you could isolate and test a piece of code in a +single-threaded context. That avoids race conditions and dead locks, and makes +debugging your test much easier. + +Yet most programs are multi-threaded, and sometimes to test something we need to +pound on it from more than one thread. gMock works for this purpose too. + +Remember the steps for using a mock: + +1. Create a mock object `foo`. +2. Set its default actions and expectations using `ON_CALL()` and + `EXPECT_CALL()`. +3. The code under test calls methods of `foo`. +4. Optionally, verify and reset the mock. +5. Destroy the mock yourself, or let the code under test destroy it. The + destructor will automatically verify it. + +If you follow the following simple rules, your mocks and threads can live +happily together: + +* Execute your *test code* (as opposed to the code being tested) in *one* + thread. This makes your test easy to follow. +* Obviously, you can do step #1 without locking. +* When doing step #2 and #5, make sure no other thread is accessing `foo`. + Obvious too, huh? +* #3 and #4 can be done either in one thread or in multiple threads - anyway + you want. gMock takes care of the locking, so you don't have to do any - + unless required by your test logic. + +If you violate the rules (for example, if you set expectations on a mock while +another thread is calling its methods), you get undefined behavior. That's not +fun, so don't do it. + +gMock guarantees that the action for a mock function is done in the same thread +that called the mock function. For example, in + +```cpp + EXPECT_CALL(mock, Foo(1)) + .WillOnce(action1); + EXPECT_CALL(mock, Foo(2)) + .WillOnce(action2); +``` + +if `Foo(1)` is called in thread 1 and `Foo(2)` is called in thread 2, gMock will +execute `action1` in thread 1 and `action2` in thread 2. + +gMock does *not* impose a sequence on actions performed in different threads +(doing so may create deadlocks as the actions may need to cooperate). This means +that the execution of `action1` and `action2` in the above example *may* +interleave. If this is a problem, you should add proper synchronization logic to +`action1` and `action2` to make the test thread-safe. + +Also, remember that `DefaultValue` is a global resource that potentially +affects *all* living mock objects in your program. Naturally, you won't want to +mess with it from multiple threads or when there still are mocks in action. + +#### Controlling How Much Information gMock Prints + +When gMock sees something that has the potential of being an error (e.g. a mock +function with no expectation is called, a.k.a. an uninteresting call, which is +allowed but perhaps you forgot to explicitly ban the call), it prints some +warning messages, including the arguments of the function, the return value, and +the stack trace. Hopefully this will remind you to take a look and see if there +is indeed a problem. + +Sometimes you are confident that your tests are correct and may not appreciate +such friendly messages. Some other times, you are debugging your tests or +learning about the behavior of the code you are testing, and wish you could +observe every mock call that happens (including argument values, the return +value, and the stack trace). Clearly, one size doesn't fit all. + +You can control how much gMock tells you using the `--gmock_verbose=LEVEL` +command-line flag, where `LEVEL` is a string with three possible values: + +* `info`: gMock will print all informational messages, warnings, and errors + (most verbose). At this setting, gMock will also log any calls to the + `ON_CALL/EXPECT_CALL` macros. It will include a stack trace in + "uninteresting call" warnings. +* `warning`: gMock will print both warnings and errors (less verbose); it will + omit the stack traces in "uninteresting call" warnings. This is the default. +* `error`: gMock will print errors only (least verbose). + +Alternatively, you can adjust the value of that flag from within your tests like +so: + +```cpp + ::testing::FLAGS_gmock_verbose = "error"; +``` + +If you find gMock printing too many stack frames with its informational or +warning messages, remember that you can control their amount with the +`--gtest_stack_trace_depth=max_depth` flag. + +Now, judiciously use the right flag to enable gMock serve you better! + +#### Gaining Super Vision into Mock Calls + +You have a test using gMock. It fails: gMock tells you some expectations aren't +satisfied. However, you aren't sure why: Is there a typo somewhere in the +matchers? Did you mess up the order of the `EXPECT_CALL`s? Or is the code under +test doing something wrong? How can you find out the cause? + +Won't it be nice if you have X-ray vision and can actually see the trace of all +`EXPECT_CALL`s and mock method calls as they are made? For each call, would you +like to see its actual argument values and which `EXPECT_CALL` gMock thinks it +matches? If you still need some help to figure out who made these calls, how +about being able to see the complete stack trace at each mock call? + +You can unlock this power by running your test with the `--gmock_verbose=info` +flag. For example, given the test program: + +```cpp +#include "gmock/gmock.h" + +using testing::_; +using testing::HasSubstr; +using testing::Return; + +class MockFoo { + public: + MOCK_METHOD(void, F, (const string& x, const string& y)); +}; + +TEST(Foo, Bar) { + MockFoo mock; + EXPECT_CALL(mock, F(_, _)).WillRepeatedly(Return()); + EXPECT_CALL(mock, F("a", "b")); + EXPECT_CALL(mock, F("c", HasSubstr("d"))); + + mock.F("a", "good"); + mock.F("a", "b"); +} +``` + +if you run it with `--gmock_verbose=info`, you will see this output: + +```shell +[ RUN ] Foo.Bar + +foo_test.cc:14: EXPECT_CALL(mock, F(_, _)) invoked +Stack trace: ... + +foo_test.cc:15: EXPECT_CALL(mock, F("a", "b")) invoked +Stack trace: ... + +foo_test.cc:16: EXPECT_CALL(mock, F("c", HasSubstr("d"))) invoked +Stack trace: ... + +foo_test.cc:14: Mock function call matches EXPECT_CALL(mock, F(_, _))... + Function call: F(@0x7fff7c8dad40"a",@0x7fff7c8dad10"good") +Stack trace: ... + +foo_test.cc:15: Mock function call matches EXPECT_CALL(mock, F("a", "b"))... + Function call: F(@0x7fff7c8dada0"a",@0x7fff7c8dad70"b") +Stack trace: ... + +foo_test.cc:16: Failure +Actual function call count doesn't match EXPECT_CALL(mock, F("c", HasSubstr("d")))... + Expected: to be called once + Actual: never called - unsatisfied and active +[ FAILED ] Foo.Bar +``` + +Suppose the bug is that the `"c"` in the third `EXPECT_CALL` is a typo and +should actually be `"a"`. With the above message, you should see that the actual +`F("a", "good")` call is matched by the first `EXPECT_CALL`, not the third as +you thought. From that it should be obvious that the third `EXPECT_CALL` is +written wrong. Case solved. + +If you are interested in the mock call trace but not the stack traces, you can +combine `--gmock_verbose=info` with `--gtest_stack_trace_depth=0` on the test +command line. + + + +#### Running Tests in Emacs + +If you build and run your tests in Emacs using the `M-x google-compile` command +(as many googletest users do), the source file locations of gMock and googletest +errors will be highlighted. Just press `` on one of them and you'll be +taken to the offending line. Or, you can just type `C-x`` to jump to the next +error. + +To make it even easier, you can add the following lines to your `~/.emacs` file: + +```text +(global-set-key "\M-m" 'google-compile) ; m is for make +(global-set-key [M-down] 'next-error) +(global-set-key [M-up] '(lambda () (interactive) (next-error -1))) +``` + +Then you can type `M-m` to start a build (if you want to run the test as well, +just make sure `foo_test.run` or `runtests` is in the build command you supply +after typing `M-m`), or `M-up`/`M-down` to move back and forth between errors. + +### Extending gMock + +#### Writing New Matchers Quickly {#NewMatchers} + +WARNING: gMock does not guarantee when or how many times a matcher will be +invoked. Therefore, all matchers must be functionally pure. See +[this section](#PureMatchers) for more details. + +The `MATCHER*` family of macros can be used to define custom matchers easily. +The syntax: + +```cpp +MATCHER(name, description_string_expression) { statements; } +``` + +will define a matcher with the given name that executes the statements, which +must return a `bool` to indicate if the match succeeds. Inside the statements, +you can refer to the value being matched by `arg`, and refer to its type by +`arg_type`. + +The *description string* is a `string`-typed expression that documents what the +matcher does, and is used to generate the failure message when the match fails. +It can (and should) reference the special `bool` variable `negation`, and should +evaluate to the description of the matcher when `negation` is `false`, or that +of the matcher's negation when `negation` is `true`. + +For convenience, we allow the description string to be empty (`""`), in which +case gMock will use the sequence of words in the matcher name as the +description. + +For example: + +```cpp +MATCHER(IsDivisibleBy7, "") { return (arg % 7) == 0; } +``` + +allows you to write + +```cpp + // Expects mock_foo.Bar(n) to be called where n is divisible by 7. + EXPECT_CALL(mock_foo, Bar(IsDivisibleBy7())); +``` + +or, + +```cpp + using ::testing::Not; + ... + // Verifies that two values are divisible by 7. + EXPECT_THAT(some_expression, IsDivisibleBy7()); + EXPECT_THAT(some_other_expression, Not(IsDivisibleBy7())); +``` + +If the above assertions fail, they will print something like: + +```shell + Value of: some_expression + Expected: is divisible by 7 + Actual: 27 + ... + Value of: some_other_expression + Expected: not (is divisible by 7) + Actual: 21 +``` + +where the descriptions `"is divisible by 7"` and `"not (is divisible by 7)"` are +automatically calculated from the matcher name `IsDivisibleBy7`. + +As you may have noticed, the auto-generated descriptions (especially those for +the negation) may not be so great. You can always override them with a `string` +expression of your own: + +```cpp +MATCHER(IsDivisibleBy7, + absl::StrCat(negation ? "isn't" : "is", " divisible by 7")) { + return (arg % 7) == 0; +} +``` + +Optionally, you can stream additional information to a hidden argument named +`result_listener` to explain the match result. For example, a better definition +of `IsDivisibleBy7` is: + +```cpp +MATCHER(IsDivisibleBy7, "") { + if ((arg % 7) == 0) + return true; + + *result_listener << "the remainder is " << (arg % 7); + return false; +} +``` + +With this definition, the above assertion will give a better message: + +```shell + Value of: some_expression + Expected: is divisible by 7 + Actual: 27 (the remainder is 6) +``` + +You should let `MatchAndExplain()` print *any additional information* that can +help a user understand the match result. Note that it should explain why the +match succeeds in case of a success (unless it's obvious) - this is useful when +the matcher is used inside `Not()`. There is no need to print the argument value +itself, as gMock already prints it for you. + +NOTE: The type of the value being matched (`arg_type`) is determined by the +context in which you use the matcher and is supplied to you by the compiler, so +you don't need to worry about declaring it (nor can you). This allows the +matcher to be polymorphic. For example, `IsDivisibleBy7()` can be used to match +any type where the value of `(arg % 7) == 0` can be implicitly converted to a +`bool`. In the `Bar(IsDivisibleBy7())` example above, if method `Bar()` takes an +`int`, `arg_type` will be `int`; if it takes an `unsigned long`, `arg_type` will +be `unsigned long`; and so on. + +#### Writing New Parameterized Matchers Quickly + +Sometimes you'll want to define a matcher that has parameters. For that you can +use the macro: + +```cpp +MATCHER_P(name, param_name, description_string) { statements; } +``` + +where the description string can be either `""` or a `string` expression that +references `negation` and `param_name`. + +For example: + +```cpp +MATCHER_P(HasAbsoluteValue, value, "") { return abs(arg) == value; } +``` + +will allow you to write: + +```cpp + EXPECT_THAT(Blah("a"), HasAbsoluteValue(n)); +``` + +which may lead to this message (assuming `n` is 10): + +```shell + Value of: Blah("a") + Expected: has absolute value 10 + Actual: -9 +``` + +Note that both the matcher description and its parameter are printed, making the +message human-friendly. + +In the matcher definition body, you can write `foo_type` to reference the type +of a parameter named `foo`. For example, in the body of +`MATCHER_P(HasAbsoluteValue, value)` above, you can write `value_type` to refer +to the type of `value`. + +gMock also provides `MATCHER_P2`, `MATCHER_P3`, ..., up to `MATCHER_P10` to +support multi-parameter matchers: + +```cpp +MATCHER_Pk(name, param_1, ..., param_k, description_string) { statements; } +``` + +Please note that the custom description string is for a particular *instance* of +the matcher, where the parameters have been bound to actual values. Therefore +usually you'll want the parameter values to be part of the description. gMock +lets you do that by referencing the matcher parameters in the description string +expression. + +For example, + +```cpp +using ::testing::PrintToString; +MATCHER_P2(InClosedRange, low, hi, + absl::StrFormat("%s in range [%s, %s]", negation ? "isn't" : "is", + PrintToString(low), PrintToString(hi))) { + return low <= arg && arg <= hi; +} +... +EXPECT_THAT(3, InClosedRange(4, 6)); +``` + +would generate a failure that contains the message: + +```shell + Expected: is in range [4, 6] +``` + +If you specify `""` as the description, the failure message will contain the +sequence of words in the matcher name followed by the parameter values printed +as a tuple. For example, + +```cpp + MATCHER_P2(InClosedRange, low, hi, "") { ... } + ... + EXPECT_THAT(3, InClosedRange(4, 6)); +``` + +would generate a failure that contains the text: + +```shell + Expected: in closed range (4, 6) +``` + +For the purpose of typing, you can view + +```cpp +MATCHER_Pk(Foo, p1, ..., pk, description_string) { ... } +``` + +as shorthand for + +```cpp +template +FooMatcherPk +Foo(p1_type p1, ..., pk_type pk) { ... } +``` + +When you write `Foo(v1, ..., vk)`, the compiler infers the types of the +parameters `v1`, ..., and `vk` for you. If you are not happy with the result of +the type inference, you can specify the types by explicitly instantiating the +template, as in `Foo(5, false)`. As said earlier, you don't get to +(or need to) specify `arg_type` as that's determined by the context in which the +matcher is used. + +You can assign the result of expression `Foo(p1, ..., pk)` to a variable of type +`FooMatcherPk`. This can be useful when composing +matchers. Matchers that don't have a parameter or have only one parameter have +special types: you can assign `Foo()` to a `FooMatcher`-typed variable, and +assign `Foo(p)` to a `FooMatcherP`-typed variable. + +While you can instantiate a matcher template with reference types, passing the +parameters by pointer usually makes your code more readable. If, however, you +still want to pass a parameter by reference, be aware that in the failure +message generated by the matcher you will see the value of the referenced object +but not its address. + +You can overload matchers with different numbers of parameters: + +```cpp +MATCHER_P(Blah, a, description_string_1) { ... } +MATCHER_P2(Blah, a, b, description_string_2) { ... } +``` + +While it's tempting to always use the `MATCHER*` macros when defining a new +matcher, you should also consider implementing `MatcherInterface` or using +`MakePolymorphicMatcher()` instead (see the recipes that follow), especially if +you need to use the matcher a lot. While these approaches require more work, +they give you more control on the types of the value being matched and the +matcher parameters, which in general leads to better compiler error messages +that pay off in the long run. They also allow overloading matchers based on +parameter types (as opposed to just based on the number of parameters). + +#### Writing New Monomorphic Matchers + +A matcher of argument type `T` implements `::testing::MatcherInterface` and +does two things: it tests whether a value of type `T` matches the matcher, and +can describe what kind of values it matches. The latter ability is used for +generating readable error messages when expectations are violated. + +The interface looks like this: + +```cpp +class MatchResultListener { + public: + ... + // Streams x to the underlying ostream; does nothing if the ostream + // is NULL. + template + MatchResultListener& operator<<(const T& x); + + // Returns the underlying ostream. + ::std::ostream* stream(); +}; + +template +class MatcherInterface { + public: + virtual ~MatcherInterface(); + + // Returns true if the matcher matches x; also explains the match + // result to 'listener'. + virtual bool MatchAndExplain(T x, MatchResultListener* listener) const = 0; + + // Describes this matcher to an ostream. + virtual void DescribeTo(::std::ostream* os) const = 0; + + // Describes the negation of this matcher to an ostream. + virtual void DescribeNegationTo(::std::ostream* os) const; +}; +``` + +If you need a custom matcher but `Truly()` is not a good option (for example, +you may not be happy with the way `Truly(predicate)` describes itself, or you +may want your matcher to be polymorphic as `Eq(value)` is), you can define a +matcher to do whatever you want in two steps: first implement the matcher +interface, and then define a factory function to create a matcher instance. The +second step is not strictly needed but it makes the syntax of using the matcher +nicer. + +For example, you can define a matcher to test whether an `int` is divisible by 7 +and then use it like this: + +```cpp +using ::testing::MakeMatcher; +using ::testing::Matcher; +using ::testing::MatcherInterface; +using ::testing::MatchResultListener; + +class DivisibleBy7Matcher : public MatcherInterface { + public: + bool MatchAndExplain(int n, + MatchResultListener* /* listener */) const override { + return (n % 7) == 0; + } + + void DescribeTo(::std::ostream* os) const override { + *os << "is divisible by 7"; + } + + void DescribeNegationTo(::std::ostream* os) const override { + *os << "is not divisible by 7"; + } +}; + +Matcher DivisibleBy7() { + return MakeMatcher(new DivisibleBy7Matcher); +} + +... + EXPECT_CALL(foo, Bar(DivisibleBy7())); +``` + +You may improve the matcher message by streaming additional information to the +`listener` argument in `MatchAndExplain()`: + +```cpp +class DivisibleBy7Matcher : public MatcherInterface { + public: + bool MatchAndExplain(int n, + MatchResultListener* listener) const override { + const int remainder = n % 7; + if (remainder != 0) { + *listener << "the remainder is " << remainder; + } + return remainder == 0; + } + ... +}; +``` + +Then, `EXPECT_THAT(x, DivisibleBy7());` may generate a message like this: + +```shell +Value of: x +Expected: is divisible by 7 + Actual: 23 (the remainder is 2) +``` + +#### Writing New Polymorphic Matchers + +You've learned how to write your own matchers in the previous recipe. Just one +problem: a matcher created using `MakeMatcher()` only works for one particular +type of arguments. If you want a *polymorphic* matcher that works with arguments +of several types (for instance, `Eq(x)` can be used to match a *`value`* as long +as `value == x` compiles -- *`value`* and `x` don't have to share the same +type), you can learn the trick from `testing/base/public/gmock-matchers.h` but +it's a bit involved. + +Fortunately, most of the time you can define a polymorphic matcher easily with +the help of `MakePolymorphicMatcher()`. Here's how you can define `NotNull()` as +an example: + +```cpp +using ::testing::MakePolymorphicMatcher; +using ::testing::MatchResultListener; +using ::testing::PolymorphicMatcher; + +class NotNullMatcher { + public: + // To implement a polymorphic matcher, first define a COPYABLE class + // that has three members MatchAndExplain(), DescribeTo(), and + // DescribeNegationTo(), like the following. + + // In this example, we want to use NotNull() with any pointer, so + // MatchAndExplain() accepts a pointer of any type as its first argument. + // In general, you can define MatchAndExplain() as an ordinary method or + // a method template, or even overload it. + template + bool MatchAndExplain(T* p, + MatchResultListener* /* listener */) const { + return p != NULL; + } + + // Describes the property of a value matching this matcher. + void DescribeTo(::std::ostream* os) const { *os << "is not NULL"; } + + // Describes the property of a value NOT matching this matcher. + void DescribeNegationTo(::std::ostream* os) const { *os << "is NULL"; } +}; + +// To construct a polymorphic matcher, pass an instance of the class +// to MakePolymorphicMatcher(). Note the return type. +PolymorphicMatcher NotNull() { + return MakePolymorphicMatcher(NotNullMatcher()); +} + +... + + EXPECT_CALL(foo, Bar(NotNull())); // The argument must be a non-NULL pointer. +``` + +**Note:** Your polymorphic matcher class does **not** need to inherit from +`MatcherInterface` or any other class, and its methods do **not** need to be +virtual. + +Like in a monomorphic matcher, you may explain the match result by streaming +additional information to the `listener` argument in `MatchAndExplain()`. + +#### Writing New Cardinalities + +A cardinality is used in `Times()` to tell gMock how many times you expect a +call to occur. It doesn't have to be exact. For example, you can say +`AtLeast(5)` or `Between(2, 4)`. + +If the [built-in set](cheat_sheet.md#CardinalityList) of cardinalities doesn't +suit you, you are free to define your own by implementing the following +interface (in namespace `testing`): + +```cpp +class CardinalityInterface { + public: + virtual ~CardinalityInterface(); + + // Returns true if call_count calls will satisfy this cardinality. + virtual bool IsSatisfiedByCallCount(int call_count) const = 0; + + // Returns true if call_count calls will saturate this cardinality. + virtual bool IsSaturatedByCallCount(int call_count) const = 0; + + // Describes self to an ostream. + virtual void DescribeTo(::std::ostream* os) const = 0; +}; +``` + +For example, to specify that a call must occur even number of times, you can +write + +```cpp +using ::testing::Cardinality; +using ::testing::CardinalityInterface; +using ::testing::MakeCardinality; + +class EvenNumberCardinality : public CardinalityInterface { + public: + bool IsSatisfiedByCallCount(int call_count) const override { + return (call_count % 2) == 0; + } + + bool IsSaturatedByCallCount(int call_count) const override { + return false; + } + + void DescribeTo(::std::ostream* os) const { + *os << "called even number of times"; + } +}; + +Cardinality EvenNumber() { + return MakeCardinality(new EvenNumberCardinality); +} + +... + EXPECT_CALL(foo, Bar(3)) + .Times(EvenNumber()); +``` + +#### Writing New Actions Quickly {#QuickNewActions} + +If the built-in actions don't work for you, you can easily define your own one. +Just define a functor class with a (possibly templated) call operator, matching +the signature of your action. + +```cpp +struct Increment { + template + T operator()(T* arg) { + return ++(*arg); + } +} +``` + +The same approach works with stateful functors (or any callable, really): + +``` +struct MultiplyBy { + template + T operator()(T arg) { return arg * multiplier; } + + int multiplier; +} + +// Then use: +// EXPECT_CALL(...).WillOnce(MultiplyBy{7}); +``` + +##### Legacy macro-based Actions + +Before C++11, the functor-based actions were not supported; the old way of +writing actions was through a set of `ACTION*` macros. We suggest to avoid them +in new code; they hide a lot of logic behind the macro, potentially leading to +harder-to-understand compiler errors. Nevertheless, we cover them here for +completeness. + +By writing + +```cpp +ACTION(name) { statements; } +``` + +in a namespace scope (i.e. not inside a class or function), you will define an +action with the given name that executes the statements. The value returned by +`statements` will be used as the return value of the action. Inside the +statements, you can refer to the K-th (0-based) argument of the mock function as +`argK`. For example: + +```cpp +ACTION(IncrementArg1) { return ++(*arg1); } +``` + +allows you to write + +```cpp +... WillOnce(IncrementArg1()); +``` + +Note that you don't need to specify the types of the mock function arguments. +Rest assured that your code is type-safe though: you'll get a compiler error if +`*arg1` doesn't support the `++` operator, or if the type of `++(*arg1)` isn't +compatible with the mock function's return type. + +Another example: + +```cpp +ACTION(Foo) { + (*arg2)(5); + Blah(); + *arg1 = 0; + return arg0; +} +``` + +defines an action `Foo()` that invokes argument #2 (a function pointer) with 5, +calls function `Blah()`, sets the value pointed to by argument #1 to 0, and +returns argument #0. + +For more convenience and flexibility, you can also use the following pre-defined +symbols in the body of `ACTION`: + +`argK_type` | The type of the K-th (0-based) argument of the mock function +:-------------- | :----------------------------------------------------------- +`args` | All arguments of the mock function as a tuple +`args_type` | The type of all arguments of the mock function as a tuple +`return_type` | The return type of the mock function +`function_type` | The type of the mock function + +For example, when using an `ACTION` as a stub action for mock function: + +```cpp +int DoSomething(bool flag, int* ptr); +``` + +we have: + +Pre-defined Symbol | Is Bound To +------------------ | --------------------------------- +`arg0` | the value of `flag` +`arg0_type` | the type `bool` +`arg1` | the value of `ptr` +`arg1_type` | the type `int*` +`args` | the tuple `(flag, ptr)` +`args_type` | the type `std::tuple` +`return_type` | the type `int` +`function_type` | the type `int(bool, int*)` + +##### Legacy macro-based parameterized Actions + +Sometimes you'll want to parameterize an action you define. For that we have +another macro + +```cpp +ACTION_P(name, param) { statements; } +``` + +For example, + +```cpp +ACTION_P(Add, n) { return arg0 + n; } +``` + +will allow you to write + +```cpp +// Returns argument #0 + 5. +... WillOnce(Add(5)); +``` + +For convenience, we use the term *arguments* for the values used to invoke the +mock function, and the term *parameters* for the values used to instantiate an +action. + +Note that you don't need to provide the type of the parameter either. Suppose +the parameter is named `param`, you can also use the gMock-defined symbol +`param_type` to refer to the type of the parameter as inferred by the compiler. +For example, in the body of `ACTION_P(Add, n)` above, you can write `n_type` for +the type of `n`. + +gMock also provides `ACTION_P2`, `ACTION_P3`, and etc to support multi-parameter +actions. For example, + +```cpp +ACTION_P2(ReturnDistanceTo, x, y) { + double dx = arg0 - x; + double dy = arg1 - y; + return sqrt(dx*dx + dy*dy); +} +``` + +lets you write + +```cpp +... WillOnce(ReturnDistanceTo(5.0, 26.5)); +``` + +You can view `ACTION` as a degenerated parameterized action where the number of +parameters is 0. + +You can also easily define actions overloaded on the number of parameters: + +```cpp +ACTION_P(Plus, a) { ... } +ACTION_P2(Plus, a, b) { ... } +``` + +#### Restricting the Type of an Argument or Parameter in an ACTION + +For maximum brevity and reusability, the `ACTION*` macros don't ask you to +provide the types of the mock function arguments and the action parameters. +Instead, we let the compiler infer the types for us. + +Sometimes, however, we may want to be more explicit about the types. There are +several tricks to do that. For example: + +```cpp +ACTION(Foo) { + // Makes sure arg0 can be converted to int. + int n = arg0; + ... use n instead of arg0 here ... +} + +ACTION_P(Bar, param) { + // Makes sure the type of arg1 is const char*. + ::testing::StaticAssertTypeEq(); + + // Makes sure param can be converted to bool. + bool flag = param; +} +``` + +where `StaticAssertTypeEq` is a compile-time assertion in googletest that +verifies two types are the same. + +#### Writing New Action Templates Quickly + +Sometimes you want to give an action explicit template parameters that cannot be +inferred from its value parameters. `ACTION_TEMPLATE()` supports that and can be +viewed as an extension to `ACTION()` and `ACTION_P*()`. + +The syntax: + +```cpp +ACTION_TEMPLATE(ActionName, + HAS_m_TEMPLATE_PARAMS(kind1, name1, ..., kind_m, name_m), + AND_n_VALUE_PARAMS(p1, ..., p_n)) { statements; } +``` + +defines an action template that takes *m* explicit template parameters and *n* +value parameters, where *m* is in [1, 10] and *n* is in [0, 10]. `name_i` is the +name of the *i*-th template parameter, and `kind_i` specifies whether it's a +`typename`, an integral constant, or a template. `p_i` is the name of the *i*-th +value parameter. + +Example: + +```cpp +// DuplicateArg(output) converts the k-th argument of the mock +// function to type T and copies it to *output. +ACTION_TEMPLATE(DuplicateArg, + // Note the comma between int and k: + HAS_2_TEMPLATE_PARAMS(int, k, typename, T), + AND_1_VALUE_PARAMS(output)) { + *output = T(::std::get(args)); +} +``` + +To create an instance of an action template, write: + +```cpp +ActionName(v1, ..., v_n) +``` + +where the `t`s are the template arguments and the `v`s are the value arguments. +The value argument types are inferred by the compiler. For example: + +```cpp +using ::testing::_; +... + int n; + EXPECT_CALL(mock, Foo).WillOnce(DuplicateArg<1, unsigned char>(&n)); +``` + +If you want to explicitly specify the value argument types, you can provide +additional template arguments: + +```cpp +ActionName(v1, ..., v_n) +``` + +where `u_i` is the desired type of `v_i`. + +`ACTION_TEMPLATE` and `ACTION`/`ACTION_P*` can be overloaded on the number of +value parameters, but not on the number of template parameters. Without the +restriction, the meaning of the following is unclear: + +```cpp + OverloadedAction(x); +``` + +Are we using a single-template-parameter action where `bool` refers to the type +of `x`, or a two-template-parameter action where the compiler is asked to infer +the type of `x`? + +#### Using the ACTION Object's Type + +If you are writing a function that returns an `ACTION` object, you'll need to +know its type. The type depends on the macro used to define the action and the +parameter types. The rule is relatively simple: + +| Given Definition | Expression | Has Type | +| ----------------------------- | ------------------- | --------------------- | +| `ACTION(Foo)` | `Foo()` | `FooAction` | +| `ACTION_TEMPLATE(Foo,` | `Foo()` : t_m>` : +: `AND_0_VALUE_PARAMS())` : : : +| `ACTION_P(Bar, param)` | `Bar(int_value)` | `BarActionP` | +| `ACTION_TEMPLATE(Bar,` | `Bar` | `FooActionP` : +: `AND_1_VALUE_PARAMS(p1))` : : : +| `ACTION_P2(Baz, p1, p2)` | `Baz(bool_value,` | `BazActionP2` : +| `ACTION_TEMPLATE(Baz,` | `Baz` | `FooActionP2` : +: `AND_2_VALUE_PARAMS(p1, p2))` : `int_value)` : : +| ... | ... | ... | + +Note that we have to pick different suffixes (`Action`, `ActionP`, `ActionP2`, +and etc) for actions with different numbers of value parameters, or the action +definitions cannot be overloaded on the number of them. + +#### Writing New Monomorphic Actions {#NewMonoActions} + +While the `ACTION*` macros are very convenient, sometimes they are +inappropriate. For example, despite the tricks shown in the previous recipes, +they don't let you directly specify the types of the mock function arguments and +the action parameters, which in general leads to unoptimized compiler error +messages that can baffle unfamiliar users. They also don't allow overloading +actions based on parameter types without jumping through some hoops. + +An alternative to the `ACTION*` macros is to implement +`::testing::ActionInterface`, where `F` is the type of the mock function in +which the action will be used. For example: + +```cpp +template +class ActionInterface { + public: + virtual ~ActionInterface(); + + // Performs the action. Result is the return type of function type + // F, and ArgumentTuple is the tuple of arguments of F. + // + + // For example, if F is int(bool, const string&), then Result would + // be int, and ArgumentTuple would be ::std::tuple. + virtual Result Perform(const ArgumentTuple& args) = 0; +}; +``` + +```cpp +using ::testing::_; +using ::testing::Action; +using ::testing::ActionInterface; +using ::testing::MakeAction; + +typedef int IncrementMethod(int*); + +class IncrementArgumentAction : public ActionInterface { + public: + int Perform(const ::std::tuple& args) override { + int* p = ::std::get<0>(args); // Grabs the first argument. + return *p++; + } +}; + +Action IncrementArgument() { + return MakeAction(new IncrementArgumentAction); +} + +... + EXPECT_CALL(foo, Baz(_)) + .WillOnce(IncrementArgument()); + + int n = 5; + foo.Baz(&n); // Should return 5 and change n to 6. +``` + +#### Writing New Polymorphic Actions {#NewPolyActions} + +The previous recipe showed you how to define your own action. This is all good, +except that you need to know the type of the function in which the action will +be used. Sometimes that can be a problem. For example, if you want to use the +action in functions with *different* types (e.g. like `Return()` and +`SetArgPointee()`). + +If an action can be used in several types of mock functions, we say it's +*polymorphic*. The `MakePolymorphicAction()` function template makes it easy to +define such an action: + +```cpp +namespace testing { +template +PolymorphicAction MakePolymorphicAction(const Impl& impl); +} // namespace testing +``` + +As an example, let's define an action that returns the second argument in the +mock function's argument list. The first step is to define an implementation +class: + +```cpp +class ReturnSecondArgumentAction { + public: + template + Result Perform(const ArgumentTuple& args) const { + // To get the i-th (0-based) argument, use ::std::get(args). + return ::std::get<1>(args); + } +}; +``` + +This implementation class does *not* need to inherit from any particular class. +What matters is that it must have a `Perform()` method template. This method +template takes the mock function's arguments as a tuple in a **single** +argument, and returns the result of the action. It can be either `const` or not, +but must be invokable with exactly one template argument, which is the result +type. In other words, you must be able to call `Perform(args)` where `R` is +the mock function's return type and `args` is its arguments in a tuple. + +Next, we use `MakePolymorphicAction()` to turn an instance of the implementation +class into the polymorphic action we need. It will be convenient to have a +wrapper for this: + +```cpp +using ::testing::MakePolymorphicAction; +using ::testing::PolymorphicAction; + +PolymorphicAction ReturnSecondArgument() { + return MakePolymorphicAction(ReturnSecondArgumentAction()); +} +``` + +Now, you can use this polymorphic action the same way you use the built-in ones: + +```cpp +using ::testing::_; + +class MockFoo : public Foo { + public: + MOCK_METHOD(int, DoThis, (bool flag, int n), (override)); + MOCK_METHOD(string, DoThat, (int x, const char* str1, const char* str2), + (override)); +}; + + ... + MockFoo foo; + EXPECT_CALL(foo, DoThis).WillOnce(ReturnSecondArgument()); + EXPECT_CALL(foo, DoThat).WillOnce(ReturnSecondArgument()); + ... + foo.DoThis(true, 5); // Will return 5. + foo.DoThat(1, "Hi", "Bye"); // Will return "Hi". +``` + +#### Teaching gMock How to Print Your Values + +When an uninteresting or unexpected call occurs, gMock prints the argument +values and the stack trace to help you debug. Assertion macros like +`EXPECT_THAT` and `EXPECT_EQ` also print the values in question when the +assertion fails. gMock and googletest do this using googletest's user-extensible +value printer. + +This printer knows how to print built-in C++ types, native arrays, STL +containers, and any type that supports the `<<` operator. For other types, it +prints the raw bytes in the value and hopes that you the user can figure it out. +[googletest's advanced guide](../../googletest/docs/advanced.md#teaching-googletest-how-to-print-your-values) +explains how to extend the printer to do a better job at printing your +particular type than to dump the bytes. + +### Useful Mocks Created Using gMock + + + + +#### Mock std::function {#MockFunction} + +`std::function` is a general function type introduced in C++11. It is a +preferred way of passing callbacks to new interfaces. Functions are copiable, +and are not usually passed around by pointer, which makes them tricky to mock. +But fear not - `MockFunction` can help you with that. + +`MockFunction` has a mock method `Call()` with the signature: + +```cpp + R Call(T1, ..., Tn); +``` + +It also has a `AsStdFunction()` method, which creates a `std::function` proxy +forwarding to Call: + +```cpp + std::function AsStdFunction(); +``` + +To use `MockFunction`, first create `MockFunction` object and set up +expectations on its `Call` method. Then pass proxy obtained from +`AsStdFunction()` to the code you are testing. For example: + +```cpp +TEST(FooTest, RunsCallbackWithBarArgument) { + // 1. Create a mock object. + MockFunction mock_function; + + // 2. Set expectations on Call() method. + EXPECT_CALL(mock_function, Call("bar")).WillOnce(Return(1)); + + // 3. Exercise code that uses std::function. + Foo(mock_function.AsStdFunction()); + // Foo's signature can be either of: + // void Foo(const std::function& fun); + // void Foo(std::function fun); + + // 4. All expectations will be verified when mock_function + // goes out of scope and is destroyed. +} +``` + +Remember that function objects created with `AsStdFunction()` are just +forwarders. If you create multiple of them, they will share the same set of +expectations. + +Although `std::function` supports unlimited number of arguments, `MockFunction` +implementation is limited to ten. If you ever hit that limit... well, your +callback has bigger problems than being mockable. :-) + + diff --git a/googlemock/docs/for_dummies.md b/googlemock/docs/for_dummies.md new file mode 100644 index 00000000..e11c18d9 --- /dev/null +++ b/googlemock/docs/for_dummies.md @@ -0,0 +1,700 @@ +## gMock for Dummies {#GMockForDummies} + + + +### What Is gMock? + +When you write a prototype or test, often it's not feasible or wise to rely on +real objects entirely. A **mock object** implements the same interface as a real +object (so it can be used as one), but lets you specify at run time how it will +be used and what it should do (which methods will be called? in which order? how +many times? with what arguments? what will they return? etc). + +**Note:** It is easy to confuse the term *fake objects* with mock objects. Fakes +and mocks actually mean very different things in the Test-Driven Development +(TDD) community: + +* **Fake** objects have working implementations, but usually take some + shortcut (perhaps to make the operations less expensive), which makes them + not suitable for production. An in-memory file system would be an example of + a fake. +* **Mocks** are objects pre-programmed with *expectations*, which form a + specification of the calls they are expected to receive. + +If all this seems too abstract for you, don't worry - the most important thing +to remember is that a mock allows you to check the *interaction* between itself +and code that uses it. The difference between fakes and mocks shall become much +clearer once you start to use mocks. + +**gMock** is a library (sometimes we also call it a "framework" to make it sound +cool) for creating mock classes and using them. It does to C++ what +jMock/EasyMock does to Java (well, more or less). + +When using gMock, + +1. first, you use some simple macros to describe the interface you want to + mock, and they will expand to the implementation of your mock class; +2. next, you create some mock objects and specify its expectations and behavior + using an intuitive syntax; +3. then you exercise code that uses the mock objects. gMock will catch any + violation to the expectations as soon as it arises. + +### Why gMock? + +While mock objects help you remove unnecessary dependencies in tests and make +them fast and reliable, using mocks manually in C++ is *hard*: + +* Someone has to implement the mocks. The job is usually tedious and + error-prone. No wonder people go great distance to avoid it. +* The quality of those manually written mocks is a bit, uh, unpredictable. You + may see some really polished ones, but you may also see some that were + hacked up in a hurry and have all sorts of ad hoc restrictions. +* The knowledge you gained from using one mock doesn't transfer to the next + one. + +In contrast, Java and Python programmers have some fine mock frameworks (jMock, +EasyMock, [Mox](http://wtf/mox), etc), which automate the creation of mocks. As +a result, mocking is a proven effective technique and widely adopted practice in +those communities. Having the right tool absolutely makes the difference. + +gMock was built to help C++ programmers. It was inspired by jMock and EasyMock, +but designed with C++'s specifics in mind. It is your friend if any of the +following problems is bothering you: + +* You are stuck with a sub-optimal design and wish you had done more + prototyping before it was too late, but prototyping in C++ is by no means + "rapid". +* Your tests are slow as they depend on too many libraries or use expensive + resources (e.g. a database). +* Your tests are brittle as some resources they use are unreliable (e.g. the + network). +* You want to test how your code handles a failure (e.g. a file checksum + error), but it's not easy to cause one. +* You need to make sure that your module interacts with other modules in the + right way, but it's hard to observe the interaction; therefore you resort to + observing the side effects at the end of the action, but it's awkward at + best. +* You want to "mock out" your dependencies, except that they don't have mock + implementations yet; and, frankly, you aren't thrilled by some of those + hand-written mocks. + +We encourage you to use gMock as + +* a *design* tool, for it lets you experiment with your interface design early + and often. More iterations lead to better designs! +* a *testing* tool to cut your tests' outbound dependencies and probe the + interaction between your module and its collaborators. + +### Getting Started + +gMock is bundled with googletest. + +### A Case for Mock Turtles + +Let's look at an example. Suppose you are developing a graphics program that +relies on a [LOGO](http://en.wikipedia.org/wiki/Logo_programming_language)-like +API for drawing. How would you test that it does the right thing? Well, you can +run it and compare the screen with a golden screen snapshot, but let's admit it: +tests like this are expensive to run and fragile (What if you just upgraded to a +shiny new graphics card that has better anti-aliasing? Suddenly you have to +update all your golden images.). It would be too painful if all your tests are +like this. Fortunately, you learned about +[Dependency Injection](http://en.wikipedia.org/wiki/Dependency_injection) and know the right thing +to do: instead of having your application talk to the system API directly, wrap +the API in an interface (say, `Turtle`) and code to that interface: + +```cpp +class Turtle { + ... + virtual ~Turtle() {}; + virtual void PenUp() = 0; + virtual void PenDown() = 0; + virtual void Forward(int distance) = 0; + virtual void Turn(int degrees) = 0; + virtual void GoTo(int x, int y) = 0; + virtual int GetX() const = 0; + virtual int GetY() const = 0; +}; +``` + +(Note that the destructor of `Turtle` **must** be virtual, as is the case for +**all** classes you intend to inherit from - otherwise the destructor of the +derived class will not be called when you delete an object through a base +pointer, and you'll get corrupted program states like memory leaks.) + +You can control whether the turtle's movement will leave a trace using `PenUp()` +and `PenDown()`, and control its movement using `Forward()`, `Turn()`, and +`GoTo()`. Finally, `GetX()` and `GetY()` tell you the current position of the +turtle. + +Your program will normally use a real implementation of this interface. In +tests, you can use a mock implementation instead. This allows you to easily +check what drawing primitives your program is calling, with what arguments, and +in which order. Tests written this way are much more robust (they won't break +because your new machine does anti-aliasing differently), easier to read and +maintain (the intent of a test is expressed in the code, not in some binary +images), and run *much, much faster*. + +### Writing the Mock Class + +If you are lucky, the mocks you need to use have already been implemented by +some nice people. If, however, you find yourself in the position to write a mock +class, relax - gMock turns this task into a fun game! (Well, almost.) + +#### How to Define It + +Using the `Turtle` interface as example, here are the simple steps you need to +follow: + +* Derive a class `MockTurtle` from `Turtle`. +* Take a *virtual* function of `Turtle` (while it's possible to + [mock non-virtual methods using templates](cook_book.md#MockingNonVirtualMethods), + it's much more involved). +* In the `public:` section of the child class, write `MOCK_METHOD();` +* Now comes the fun part: you take the function signature, cut-and-paste it + into the macro, and add two commas - one between the return type and the + name, another between the name and the argument list. +* If you're mocking a const method, add a 4th parameter containing `(const)` + (the parentheses are required). +* Since you're overriding a virtual method, we suggest adding the `override` + keyword. For const methods the 4th parameter becomes `(const, override)`, + for non-const methods just `(override)`. This isn't mandatory. +* Repeat until all virtual functions you want to mock are done. (It goes + without saying that *all* pure virtual methods in your abstract class must + be either mocked or overridden.) + +After the process, you should have something like: + +```cpp +#include "gmock/gmock.h" // Brings in gMock. + +class MockTurtle : public Turtle { + public: + ... + MOCK_METHOD(void, PenUp, (), (override)); + MOCK_METHOD(void, PenDown, (), (override)); + MOCK_METHOD(void, Forward, (int distance), (override)); + MOCK_METHOD(void, Turn, (int degrees), (override)); + MOCK_METHOD(void, GoTo, (int x, int y), (override)); + MOCK_METHOD(int, GetX, (), (const, override)); + MOCK_METHOD(int, GetY, (), (const, override)); +}; +``` + +You don't need to define these mock methods somewhere else - the `MOCK_METHOD` +macro will generate the definitions for you. It's that simple! + +#### Where to Put It + +When you define a mock class, you need to decide where to put its definition. +Some people put it in a `_test.cc`. This is fine when the interface being mocked +(say, `Foo`) is owned by the same person or team. Otherwise, when the owner of +`Foo` changes it, your test could break. (You can't really expect `Foo`'s +maintainer to fix every test that uses `Foo`, can you?) + +So, the rule of thumb is: if you need to mock `Foo` and it's owned by others, +define the mock class in `Foo`'s package (better, in a `testing` sub-package +such that you can clearly separate production code and testing utilities), put +it in a `.h` and a `cc_library`. Then everyone can reference them from their +tests. If `Foo` ever changes, there is only one copy of `MockFoo` to change, and +only tests that depend on the changed methods need to be fixed. + +Another way to do it: you can introduce a thin layer `FooAdaptor` on top of +`Foo` and code to this new interface. Since you own `FooAdaptor`, you can absorb +changes in `Foo` much more easily. While this is more work initially, carefully +choosing the adaptor interface can make your code easier to write and more +readable (a net win in the long run), as you can choose `FooAdaptor` to fit your +specific domain much better than `Foo` does. + + + +### Using Mocks in Tests + +Once you have a mock class, using it is easy. The typical work flow is: + +1. Import the gMock names from the `testing` namespace such that you can use + them unqualified (You only have to do it once per file. Remember that + namespaces are a good idea. +2. Create some mock objects. +3. Specify your expectations on them (How many times will a method be called? + With what arguments? What should it do? etc.). +4. Exercise some code that uses the mocks; optionally, check the result using + googletest assertions. If a mock method is called more than expected or with + wrong arguments, you'll get an error immediately. +5. When a mock is destructed, gMock will automatically check whether all + expectations on it have been satisfied. + +Here's an example: + +```cpp +#include "path/to/mock-turtle.h" +#include "gmock/gmock.h" +#include "gtest/gtest.h" + +using ::testing::AtLeast; // #1 + +TEST(PainterTest, CanDrawSomething) { + MockTurtle turtle; // #2 + EXPECT_CALL(turtle, PenDown()) // #3 + .Times(AtLeast(1)); + + Painter painter(&turtle); // #4 + + EXPECT_TRUE(painter.DrawCircle(0, 0, 10)); // #5 +} +``` + +As you might have guessed, this test checks that `PenDown()` is called at least +once. If the `painter` object didn't call this method, your test will fail with +a message like this: + +```text +path/to/my_test.cc:119: Failure +Actual function call count doesn't match this expectation: +Actually: never called; +Expected: called at least once. +Stack trace: +... +``` + +**Tip 1:** If you run the test from an Emacs buffer, you can hit on the +line number to jump right to the failed expectation. + +**Tip 2:** If your mock objects are never deleted, the final verification won't +happen. Therefore it's a good idea to turn on the heap checker in your tests +when you allocate mocks on the heap. You get that automatically if you use the +`gtest_main` library already. + +**Important note:** gMock requires expectations to be set **before** the mock +functions are called, otherwise the behavior is **undefined**. In particular, +you mustn't interleave `EXPECT_CALL()s` and calls to the mock functions. + +This means `EXPECT_CALL()` should be read as expecting that a call will occur +*in the future*, not that a call has occurred. Why does gMock work like that? +Well, specifying the expectation beforehand allows gMock to report a violation +as soon as it rises, when the context (stack trace, etc) is still available. +This makes debugging much easier. + +Admittedly, this test is contrived and doesn't do much. You can easily achieve +the same effect without using gMock. However, as we shall reveal soon, gMock +allows you to do *so much more* with the mocks. + +### Setting Expectations + +The key to using a mock object successfully is to set the *right expectations* +on it. If you set the expectations too strict, your test will fail as the result +of unrelated changes. If you set them too loose, bugs can slip through. You want +to do it just right such that your test can catch exactly the kind of bugs you +intend it to catch. gMock provides the necessary means for you to do it "just +right." + +#### General Syntax + +In gMock we use the `EXPECT_CALL()` macro to set an expectation on a mock +method. The general syntax is: + +```cpp +EXPECT_CALL(mock_object, method(matchers)) + .Times(cardinality) + .WillOnce(action) + .WillRepeatedly(action); +``` + +The macro has two arguments: first the mock object, and then the method and its +arguments. Note that the two are separated by a comma (`,`), not a period (`.`). +(Why using a comma? The answer is that it was necessary for technical reasons.) +If the method is not overloaded, the macro can also be called without matchers: + +```cpp +EXPECT_CALL(mock_object, non-overloaded-method) + .Times(cardinality) + .WillOnce(action) + .WillRepeatedly(action); +``` + +This syntax allows the test writer to specify "called with any arguments" +without explicitly specifying the number or types of arguments. To avoid +unintended ambiguity, this syntax may only be used for methods which are not +overloaded + +Either form of the macro can be followed by some optional *clauses* that provide +more information about the expectation. We'll discuss how each clause works in +the coming sections. + +This syntax is designed to make an expectation read like English. For example, +you can probably guess that + +```cpp +using ::testing::Return; +... +EXPECT_CALL(turtle, GetX()) + .Times(5) + .WillOnce(Return(100)) + .WillOnce(Return(150)) + .WillRepeatedly(Return(200)); +``` + +says that the `turtle` object's `GetX()` method will be called five times, it +will return 100 the first time, 150 the second time, and then 200 every time. +Some people like to call this style of syntax a Domain-Specific Language (DSL). + +**Note:** Why do we use a macro to do this? Well it serves two purposes: first +it makes expectations easily identifiable (either by `gsearch` or by a human +reader), and second it allows gMock to include the source file location of a +failed expectation in messages, making debugging easier. + +#### Matchers: What Arguments Do We Expect? + +When a mock function takes arguments, we may specify what arguments we are +expecting, for example: + +```cpp +// Expects the turtle to move forward by 100 units. +EXPECT_CALL(turtle, Forward(100)); +``` + +Oftentimes you do not want to be too specific. Remember that talk about tests +being too rigid? Over specification leads to brittle tests and obscures the +intent of tests. Therefore we encourage you to specify only what's necessary—no +more, no less. If you aren't interested in the value of an argument, write `_` +as the argument, which means "anything goes": + +```cpp +using ::testing::_; +... +// Expects that the turtle jumps to somewhere on the x=50 line. +EXPECT_CALL(turtle, GoTo(50, _)); +``` + +`_` is an instance of what we call **matchers**. A matcher is like a predicate +and can test whether an argument is what we'd expect. You can use a matcher +inside `EXPECT_CALL()` wherever a function argument is expected. `_` is a +convenient way of saying "any value". + +In the above examples, `100` and `50` are also matchers; implicitly, they are +the same as `Eq(100)` and `Eq(50)`, which specify that the argument must be +equal (using `operator==`) to the matcher argument. There are many +[built-in matchers](#MatcherList) for common types (as well as +[custom matchers](cook_book.md#NewMatchers)); for example: + +```cpp +using ::testing::Ge; +... +// Expects the turtle moves forward by at least 100. +EXPECT_CALL(turtle, Forward(Ge(100))); +``` + +If you don't care about *any* arguments, rather than specify `_` for each of +them you may instead omit the parameter list: + +```cpp +// Expects the turtle to move forward. +EXPECT_CALL(turtle, Forward); +// Expects the turtle to jump somewhere. +EXPECT_CALL(turtle, GoTo); +``` + +This works for all non-overloaded methods; if a method is overloaded, you need +to help gMock resolve which overload is expected by specifying the number of +arguments and possibly also the +[types of the arguments](cook_book.md#SelectOverload). + +#### Cardinalities: How Many Times Will It Be Called? + +The first clause we can specify following an `EXPECT_CALL()` is `Times()`. We +call its argument a **cardinality** as it tells *how many times* the call should +occur. It allows us to repeat an expectation many times without actually writing +it as many times. More importantly, a cardinality can be "fuzzy", just like a +matcher can be. This allows a user to express the intent of a test exactly. + +An interesting special case is when we say `Times(0)`. You may have guessed - it +means that the function shouldn't be called with the given arguments at all, and +gMock will report a googletest failure whenever the function is (wrongfully) +called. + +We've seen `AtLeast(n)` as an example of fuzzy cardinalities earlier. For the +list of built-in cardinalities you can use, see +[here](cheat_sheet.md#CardinalityList). + +The `Times()` clause can be omitted. **If you omit `Times()`, gMock will infer +the cardinality for you.** The rules are easy to remember: + +* If **neither** `WillOnce()` **nor** `WillRepeatedly()` is in the + `EXPECT_CALL()`, the inferred cardinality is `Times(1)`. +* If there are *n* `WillOnce()`'s but **no** `WillRepeatedly()`, where *n* >= + 1, the cardinality is `Times(n)`. +* If there are *n* `WillOnce()`'s and **one** `WillRepeatedly()`, where *n* >= + 0, the cardinality is `Times(AtLeast(n))`. + +**Quick quiz:** what do you think will happen if a function is expected to be +called twice but actually called four times? + +#### Actions: What Should It Do? + +Remember that a mock object doesn't really have a working implementation? We as +users have to tell it what to do when a method is invoked. This is easy in +gMock. + +First, if the return type of a mock function is a built-in type or a pointer, +the function has a **default action** (a `void` function will just return, a +`bool` function will return `false`, and other functions will return 0). In +addition, in C++ 11 and above, a mock function whose return type is +default-constructible (i.e. has a default constructor) has a default action of +returning a default-constructed value. If you don't say anything, this behavior +will be used. + +Second, if a mock function doesn't have a default action, or the default action +doesn't suit you, you can specify the action to be taken each time the +expectation matches using a series of `WillOnce()` clauses followed by an +optional `WillRepeatedly()`. For example, + +```cpp +using ::testing::Return; +... +EXPECT_CALL(turtle, GetX()) + .WillOnce(Return(100)) + .WillOnce(Return(200)) + .WillOnce(Return(300)); +``` + +says that `turtle.GetX()` will be called *exactly three times* (gMock inferred +this from how many `WillOnce()` clauses we've written, since we didn't +explicitly write `Times()`), and will return 100, 200, and 300 respectively. + +```cpp +using ::testing::Return; +... +EXPECT_CALL(turtle, GetY()) + .WillOnce(Return(100)) + .WillOnce(Return(200)) + .WillRepeatedly(Return(300)); +``` + +says that `turtle.GetY()` will be called *at least twice* (gMock knows this as +we've written two `WillOnce()` clauses and a `WillRepeatedly()` while having no +explicit `Times()`), will return 100 and 200 respectively the first two times, +and 300 from the third time on. + +Of course, if you explicitly write a `Times()`, gMock will not try to infer the +cardinality itself. What if the number you specified is larger than there are +`WillOnce()` clauses? Well, after all `WillOnce()`s are used up, gMock will do +the *default* action for the function every time (unless, of course, you have a +`WillRepeatedly()`.). + +What can we do inside `WillOnce()` besides `Return()`? You can return a +reference using `ReturnRef(*variable*)`, or invoke a pre-defined function, among +[others](cook_book.md#using-actions). + +**Important note:** The `EXPECT_CALL()` statement evaluates the action clause +only once, even though the action may be performed many times. Therefore you +must be careful about side effects. The following may not do what you want: + +```cpp +using ::testing::Return; +... +int n = 100; +EXPECT_CALL(turtle, GetX()) + .Times(4) + .WillRepeatedly(Return(n++)); +``` + +Instead of returning 100, 101, 102, ..., consecutively, this mock function will +always return 100 as `n++` is only evaluated once. Similarly, `Return(new Foo)` +will create a new `Foo` object when the `EXPECT_CALL()` is executed, and will +return the same pointer every time. If you want the side effect to happen every +time, you need to define a custom action, which we'll teach in the +[cook book](http://). + +Time for another quiz! What do you think the following means? + +```cpp +using ::testing::Return; +... +EXPECT_CALL(turtle, GetY()) + .Times(4) + .WillOnce(Return(100)); +``` + +Obviously `turtle.GetY()` is expected to be called four times. But if you think +it will return 100 every time, think twice! Remember that one `WillOnce()` +clause will be consumed each time the function is invoked and the default action +will be taken afterwards. So the right answer is that `turtle.GetY()` will +return 100 the first time, but **return 0 from the second time on**, as +returning 0 is the default action for `int` functions. + +#### Using Multiple Expectations {#MultiExpectations} + +So far we've only shown examples where you have a single expectation. More +realistically, you'll specify expectations on multiple mock methods which may be +from multiple mock objects. + +By default, when a mock method is invoked, gMock will search the expectations in +the **reverse order** they are defined, and stop when an active expectation that +matches the arguments is found (you can think of it as "newer rules override +older ones."). If the matching expectation cannot take any more calls, you will +get an upper-bound-violated failure. Here's an example: + +```cpp +using ::testing::_; +... +EXPECT_CALL(turtle, Forward(_)); // #1 +EXPECT_CALL(turtle, Forward(10)) // #2 + .Times(2); +``` + +If `Forward(10)` is called three times in a row, the third time it will be an +error, as the last matching expectation (#2) has been saturated. If, however, +the third `Forward(10)` call is replaced by `Forward(20)`, then it would be OK, +as now #1 will be the matching expectation. + +**Note:** Why does gMock search for a match in the *reverse* order of the +expectations? The reason is that this allows a user to set up the default +expectations in a mock object's constructor or the test fixture's set-up phase +and then customize the mock by writing more specific expectations in the test +body. So, if you have two expectations on the same method, you want to put the +one with more specific matchers **after** the other, or the more specific rule +would be shadowed by the more general one that comes after it. + +**Tip:** It is very common to start with a catch-all expectation for a method +and `Times(AnyNumber())` (omitting arguments, or with `_` for all arguments, if +overloaded). This makes any calls to the method expected. This is not necessary +for methods that are not mentioned at all (these are "uninteresting"), but is +useful for methods that have some expectations, but for which other calls are +ok. See +[Understanding Uninteresting vs Unexpected Calls](cook_book.md#uninteresting-vs-unexpected). + +#### Ordered vs Unordered Calls {#OrderedCalls} + +By default, an expectation can match a call even though an earlier expectation +hasn't been satisfied. In other words, the calls don't have to occur in the +order the expectations are specified. + +Sometimes, you may want all the expected calls to occur in a strict order. To +say this in gMock is easy: + +```cpp +using ::testing::InSequence; +... +TEST(FooTest, DrawsLineSegment) { + ... + { + InSequence seq; + + EXPECT_CALL(turtle, PenDown()); + EXPECT_CALL(turtle, Forward(100)); + EXPECT_CALL(turtle, PenUp()); + } + Foo(); +} +``` + +By creating an object of type `InSequence`, all expectations in its scope are +put into a *sequence* and have to occur *sequentially*. Since we are just +relying on the constructor and destructor of this object to do the actual work, +its name is really irrelevant. + +In this example, we test that `Foo()` calls the three expected functions in the +order as written. If a call is made out-of-order, it will be an error. + +(What if you care about the relative order of some of the calls, but not all of +them? Can you specify an arbitrary partial order? The answer is ... yes! The +details can be found [here](cook_book.md#OrderedCalls).) + +#### All Expectations Are Sticky (Unless Said Otherwise) {#StickyExpectations} + +Now let's do a quick quiz to see how well you can use this mock stuff already. +How would you test that the turtle is asked to go to the origin *exactly twice* +(you want to ignore any other instructions it receives)? + +After you've come up with your answer, take a look at ours and compare notes +(solve it yourself first - don't cheat!): + +```cpp +using ::testing::_; +using ::testing::AnyNumber; +... +EXPECT_CALL(turtle, GoTo(_, _)) // #1 + .Times(AnyNumber()); +EXPECT_CALL(turtle, GoTo(0, 0)) // #2 + .Times(2); +``` + +Suppose `turtle.GoTo(0, 0)` is called three times. In the third time, gMock will +see that the arguments match expectation #2 (remember that we always pick the +last matching expectation). Now, since we said that there should be only two +such calls, gMock will report an error immediately. This is basically what we've +told you in the [Using Multiple Expectations](#MultiExpectations) section above. + +This example shows that **expectations in gMock are "sticky" by default**, in +the sense that they remain active even after we have reached their invocation +upper bounds. This is an important rule to remember, as it affects the meaning +of the spec, and is **different** to how it's done in many other mocking +frameworks (Why'd we do that? Because we think our rule makes the common cases +easier to express and understand.). + +Simple? Let's see if you've really understood it: what does the following code +say? + +```cpp +using ::testing::Return; +... +for (int i = n; i > 0; i--) { + EXPECT_CALL(turtle, GetX()) + .WillOnce(Return(10*i)); +} +``` + +If you think it says that `turtle.GetX()` will be called `n` times and will +return 10, 20, 30, ..., consecutively, think twice! The problem is that, as we +said, expectations are sticky. So, the second time `turtle.GetX()` is called, +the last (latest) `EXPECT_CALL()` statement will match, and will immediately +lead to an "upper bound violated" error - this piece of code is not very useful! + +One correct way of saying that `turtle.GetX()` will return 10, 20, 30, ..., is +to explicitly say that the expectations are *not* sticky. In other words, they +should *retire* as soon as they are saturated: + +```cpp +using ::testing::Return; +... +for (int i = n; i > 0; i--) { + EXPECT_CALL(turtle, GetX()) + .WillOnce(Return(10*i)) + .RetiresOnSaturation(); +} +``` + +And, there's a better way to do it: in this case, we expect the calls to occur +in a specific order, and we line up the actions to match the order. Since the +order is important here, we should make it explicit using a sequence: + +```cpp +using ::testing::InSequence; +using ::testing::Return; +... +{ + InSequence s; + + for (int i = 1; i <= n; i++) { + EXPECT_CALL(turtle, GetX()) + .WillOnce(Return(10*i)) + .RetiresOnSaturation(); + } +} +``` + +By the way, the other situation where an expectation may *not* be sticky is when +it's in a sequence - as soon as another expectation that comes after it in the +sequence has been used, it automatically retires (and will never be used to +match any call). + +#### Uninteresting Calls + +A mock object may have many methods, and not all of them are that interesting. +For example, in some tests we may not care about how many times `GetX()` and +`GetY()` get called. + +In gMock, if you are not interested in a method, just don't say anything about +it. If a call to this method occurs, you'll see a warning in the test output, +but it won't be a failure. This is called "naggy" behavior; to change, see +[The Nice, the Strict, and the Naggy](cook_book.md#NiceStrictNaggy). diff --git a/googlemock/docs/gmock_faq.md b/googlemock/docs/gmock_faq.md new file mode 100644 index 00000000..214aabf1 --- /dev/null +++ b/googlemock/docs/gmock_faq.md @@ -0,0 +1,396 @@ +## Legacy gMock FAQ {#GMockFaq} + + + +### When I call a method on my mock object, the method for the real object is invoked instead. What's the problem? + +In order for a method to be mocked, it must be *virtual*, unless you use the +[high-perf dependency injection technique](#MockingNonVirtualMethods). + +### Can I mock a variadic function? + +You cannot mock a variadic function (i.e. a function taking ellipsis (`...`) +arguments) directly in gMock. + +The problem is that in general, there is *no way* for a mock object to know how +many arguments are passed to the variadic method, and what the arguments' types +are. Only the *author of the base class* knows the protocol, and we cannot look +into his or her head. + +Therefore, to mock such a function, the *user* must teach the mock object how to +figure out the number of arguments and their types. One way to do it is to +provide overloaded versions of the function. + +Ellipsis arguments are inherited from C and not really a C++ feature. They are +unsafe to use and don't work with arguments that have constructors or +destructors. Therefore we recommend to avoid them in C++ as much as possible. + +### MSVC gives me warning C4301 or C4373 when I define a mock method with a const parameter. Why? + +If you compile this using Microsoft Visual C++ 2005 SP1: + +```cpp +class Foo { + ... + virtual void Bar(const int i) = 0; +}; + +class MockFoo : public Foo { + ... + MOCK_METHOD(void, Bar, (const int i), (override)); +}; +``` + +You may get the following warning: + +```shell +warning C4301: 'MockFoo::Bar': overriding virtual function only differs from 'Foo::Bar' by const/volatile qualifier +``` + +This is a MSVC bug. The same code compiles fine with gcc, for example. If you +use Visual C++ 2008 SP1, you would get the warning: + +```shell +warning C4373: 'MockFoo::Bar': virtual function overrides 'Foo::Bar', previous versions of the compiler did not override when parameters only differed by const/volatile qualifiers +``` + +In C++, if you *declare* a function with a `const` parameter, the `const` +modifier is ignored. Therefore, the `Foo` base class above is equivalent to: + +```cpp +class Foo { + ... + virtual void Bar(int i) = 0; // int or const int? Makes no difference. +}; +``` + +In fact, you can *declare* `Bar()` with an `int` parameter, and define it with a +`const int` parameter. The compiler will still match them up. + +Since making a parameter `const` is meaningless in the method declaration, we +recommend to remove it in both `Foo` and `MockFoo`. That should workaround the +VC bug. + +Note that we are talking about the *top-level* `const` modifier here. If the +function parameter is passed by pointer or reference, declaring the pointee or +referee as `const` is still meaningful. For example, the following two +declarations are *not* equivalent: + +```cpp +void Bar(int* p); // Neither p nor *p is const. +void Bar(const int* p); // p is not const, but *p is. +``` + + + +### I can't figure out why gMock thinks my expectations are not satisfied. What should I do? + +You might want to run your test with `--gmock_verbose=info`. This flag lets +gMock print a trace of every mock function call it receives. By studying the +trace, you'll gain insights on why the expectations you set are not met. + +If you see the message "The mock function has no default action set, and its +return type has no default value set.", then try +[adding a default action](for_dummies.md#DefaultValue). Due to a known issue, +unexpected calls on mocks without default actions don't print out a detailed +comparison between the actual arguments and the expected arguments. + +### My program crashed and `ScopedMockLog` spit out tons of messages. Is it a gMock bug? + +gMock and `ScopedMockLog` are likely doing the right thing here. + +When a test crashes, the failure signal handler will try to log a lot of +information (the stack trace, and the address map, for example). The messages +are compounded if you have many threads with depth stacks. When `ScopedMockLog` +intercepts these messages and finds that they don't match any expectations, it +prints an error for each of them. + +You can learn to ignore the errors, or you can rewrite your expectations to make +your test more robust, for example, by adding something like: + +```cpp +using ::testing::AnyNumber; +using ::testing::Not; +... + // Ignores any log not done by us. + EXPECT_CALL(log, Log(_, Not(EndsWith("/my_file.cc")), _)) + .Times(AnyNumber()); +``` + +### How can I assert that a function is NEVER called? + +```cpp +using ::testing::_; +... + EXPECT_CALL(foo, Bar(_)) + .Times(0); +``` + + + +### I have a failed test where gMock tells me TWICE that a particular expectation is not satisfied. Isn't this redundant? + +When gMock detects a failure, it prints relevant information (the mock function +arguments, the state of relevant expectations, and etc) to help the user debug. +If another failure is detected, gMock will do the same, including printing the +state of relevant expectations. + +Sometimes an expectation's state didn't change between two failures, and you'll +see the same description of the state twice. They are however *not* redundant, +as they refer to *different points in time*. The fact they are the same *is* +interesting information. + +### I get a heapcheck failure when using a mock object, but using a real object is fine. What can be wrong? + +Does the class (hopefully a pure interface) you are mocking have a virtual +destructor? + +Whenever you derive from a base class, make sure its destructor is virtual. +Otherwise Bad Things will happen. Consider the following code: + +```cpp +class Base { + public: + // Not virtual, but should be. + ~Base() { ... } + ... +}; + +class Derived : public Base { + public: + ... + private: + std::string value_; +}; + +... + Base* p = new Derived; + ... + delete p; // Surprise! ~Base() will be called, but ~Derived() will not + // - value_ is leaked. +``` + +By changing `~Base()` to virtual, `~Derived()` will be correctly called when +`delete p` is executed, and the heap checker will be happy. + +### The "newer expectations override older ones" rule makes writing expectations awkward. Why does gMock do that? + +When people complain about this, often they are referring to code like: + +```cpp +using ::testing::Return; +... + // foo.Bar() should be called twice, return 1 the first time, and return + // 2 the second time. However, I have to write the expectations in the + // reverse order. This sucks big time!!! + EXPECT_CALL(foo, Bar()) + .WillOnce(Return(2)) + .RetiresOnSaturation(); + EXPECT_CALL(foo, Bar()) + .WillOnce(Return(1)) + .RetiresOnSaturation(); +``` + +The problem, is that they didn't pick the **best** way to express the test's +intent. + +By default, expectations don't have to be matched in *any* particular order. If +you want them to match in a certain order, you need to be explicit. This is +gMock's (and jMock's) fundamental philosophy: it's easy to accidentally +over-specify your tests, and we want to make it harder to do so. + +There are two better ways to write the test spec. You could either put the +expectations in sequence: + +```cpp +using ::testing::Return; +... + // foo.Bar() should be called twice, return 1 the first time, and return + // 2 the second time. Using a sequence, we can write the expectations + // in their natural order. + { + InSequence s; + EXPECT_CALL(foo, Bar()) + .WillOnce(Return(1)) + .RetiresOnSaturation(); + EXPECT_CALL(foo, Bar()) + .WillOnce(Return(2)) + .RetiresOnSaturation(); + } +``` + +or you can put the sequence of actions in the same expectation: + +```cpp +using ::testing::Return; +... + // foo.Bar() should be called twice, return 1 the first time, and return + // 2 the second time. + EXPECT_CALL(foo, Bar()) + .WillOnce(Return(1)) + .WillOnce(Return(2)) + .RetiresOnSaturation(); +``` + +Back to the original questions: why does gMock search the expectations (and +`ON_CALL`s) from back to front? Because this allows a user to set up a mock's +behavior for the common case early (e.g. in the mock's constructor or the test +fixture's set-up phase) and customize it with more specific rules later. If +gMock searches from front to back, this very useful pattern won't be possible. + +### gMock prints a warning when a function without EXPECT_CALL is called, even if I have set its behavior using ON_CALL. Would it be reasonable not to show the warning in this case? + +When choosing between being neat and being safe, we lean toward the latter. So +the answer is that we think it's better to show the warning. + +Often people write `ON_CALL`s in the mock object's constructor or `SetUp()`, as +the default behavior rarely changes from test to test. Then in the test body +they set the expectations, which are often different for each test. Having an +`ON_CALL` in the set-up part of a test doesn't mean that the calls are expected. +If there's no `EXPECT_CALL` and the method is called, it's possibly an error. If +we quietly let the call go through without notifying the user, bugs may creep in +unnoticed. + +If, however, you are sure that the calls are OK, you can write + +```cpp +using ::testing::_; +... + EXPECT_CALL(foo, Bar(_)) + .WillRepeatedly(...); +``` + +instead of + +```cpp +using ::testing::_; +... + ON_CALL(foo, Bar(_)) + .WillByDefault(...); +``` + +This tells gMock that you do expect the calls and no warning should be printed. + +Also, you can control the verbosity by specifying `--gmock_verbose=error`. Other +values are `info` and `warning`. If you find the output too noisy when +debugging, just choose a less verbose level. + +### How can I delete the mock function's argument in an action? + +If your mock function takes a pointer argument and you want to delete that +argument, you can use testing::DeleteArg() to delete the N'th (zero-indexed) +argument: + +```cpp +using ::testing::_; + ... + MOCK_METHOD(void, Bar, (X* x, const Y& y)); + ... + EXPECT_CALL(mock_foo_, Bar(_, _)) + .WillOnce(testing::DeleteArg<0>())); +``` + +### How can I perform an arbitrary action on a mock function's argument? + +If you find yourself needing to perform some action that's not supported by +gMock directly, remember that you can define your own actions using +[`MakeAction()`](#NewMonoActions) or +[`MakePolymorphicAction()`](#NewPolyActions), or you can write a stub function +and invoke it using [`Invoke()`](#FunctionsAsActions). + +```cpp +using ::testing::_; +using ::testing::Invoke; + ... + MOCK_METHOD(void, Bar, (X* p)); + ... + EXPECT_CALL(mock_foo_, Bar(_)) + .WillOnce(Invoke(MyAction(...))); +``` + +### My code calls a static/global function. Can I mock it? + +You can, but you need to make some changes. + +In general, if you find yourself needing to mock a static function, it's a sign +that your modules are too tightly coupled (and less flexible, less reusable, +less testable, etc). You are probably better off defining a small interface and +call the function through that interface, which then can be easily mocked. It's +a bit of work initially, but usually pays for itself quickly. + +This Google Testing Blog +[post](https://testing.googleblog.com/2008/06/defeat-static-cling.html) says it +excellently. Check it out. + +### My mock object needs to do complex stuff. It's a lot of pain to specify the actions. gMock sucks! + +I know it's not a question, but you get an answer for free any way. :-) + +With gMock, you can create mocks in C++ easily. And people might be tempted to +use them everywhere. Sometimes they work great, and sometimes you may find them, +well, a pain to use. So, what's wrong in the latter case? + +When you write a test without using mocks, you exercise the code and assert that +it returns the correct value or that the system is in an expected state. This is +sometimes called "state-based testing". + +Mocks are great for what some call "interaction-based" testing: instead of +checking the system state at the very end, mock objects verify that they are +invoked the right way and report an error as soon as it arises, giving you a +handle on the precise context in which the error was triggered. This is often +more effective and economical to do than state-based testing. + +If you are doing state-based testing and using a test double just to simulate +the real object, you are probably better off using a fake. Using a mock in this +case causes pain, as it's not a strong point for mocks to perform complex +actions. If you experience this and think that mocks suck, you are just not +using the right tool for your problem. Or, you might be trying to solve the +wrong problem. :-) + +### I got a warning "Uninteresting function call encountered - default action taken.." Should I panic? + +By all means, NO! It's just an FYI. :-) + +What it means is that you have a mock function, you haven't set any expectations +on it (by gMock's rule this means that you are not interested in calls to this +function and therefore it can be called any number of times), and it is called. +That's OK - you didn't say it's not OK to call the function! + +What if you actually meant to disallow this function to be called, but forgot to +write `EXPECT_CALL(foo, Bar()).Times(0)`? While one can argue that it's the +user's fault, gMock tries to be nice and prints you a note. + +So, when you see the message and believe that there shouldn't be any +uninteresting calls, you should investigate what's going on. To make your life +easier, gMock dumps the stack trace when an uninteresting call is encountered. +From that you can figure out which mock function it is, and how it is called. + +### I want to define a custom action. Should I use Invoke() or implement the ActionInterface interface? + +Either way is fine - you want to choose the one that's more convenient for your +circumstance. + +Usually, if your action is for a particular function type, defining it using +`Invoke()` should be easier; if your action can be used in functions of +different types (e.g. if you are defining `Return(*value*)`), +`MakePolymorphicAction()` is easiest. Sometimes you want precise control on what +types of functions the action can be used in, and implementing `ActionInterface` +is the way to go here. See the implementation of `Return()` in +`testing/base/public/gmock-actions.h` for an example. + +### I use SetArgPointee() in WillOnce(), but gcc complains about "conflicting return type specified". What does it mean? + +You got this error as gMock has no idea what value it should return when the +mock method is called. `SetArgPointee()` says what the side effect is, but +doesn't say what the return value should be. You need `DoAll()` to chain a +`SetArgPointee()` with a `Return()` that provides a value appropriate to the API +being mocked. + +See this [recipe](cook_book.md#mocking-side-effects) for more details and an +example. + +### I have a huge mock class, and Microsoft Visual C++ runs out of memory when compiling it. What can I do? + +We've noticed that when the `/clr` compiler flag is used, Visual C++ uses 5~6 +times as much memory when compiling a mock class. We suggest to avoid `/clr` +when compiling native C++ mocks. diff --git a/googlemock/include/gmock/gmock-actions.h b/googlemock/include/gmock/gmock-actions.h new file mode 100644 index 00000000..9605c43a --- /dev/null +++ b/googlemock/include/gmock/gmock-actions.h @@ -0,0 +1,1141 @@ +// Copyright 2007, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + +// Google Mock - a framework for writing C++ mock classes. +// +// This file implements some commonly used actions. + +// GOOGLETEST_CM0002 DO NOT DELETE + +#ifndef GMOCK_INCLUDE_GMOCK_GMOCK_ACTIONS_H_ +#define GMOCK_INCLUDE_GMOCK_GMOCK_ACTIONS_H_ + +#ifndef _WIN32_WCE +# include +#endif + +#include +#include +#include +#include +#include +#include + +#include "gmock/internal/gmock-internal-utils.h" +#include "gmock/internal/gmock-port.h" + +#ifdef _MSC_VER +# pragma warning(push) +# pragma warning(disable:4100) +#endif + +namespace testing { + +// To implement an action Foo, define: +// 1. a class FooAction that implements the ActionInterface interface, and +// 2. a factory function that creates an Action object from a +// const FooAction*. +// +// The two-level delegation design follows that of Matcher, providing +// consistency for extension developers. It also eases ownership +// management as Action objects can now be copied like plain values. + +namespace internal { + +// BuiltInDefaultValueGetter::Get() returns a +// default-constructed T value. BuiltInDefaultValueGetter::Get() crashes with an error. +// +// This primary template is used when kDefaultConstructible is true. +template +struct BuiltInDefaultValueGetter { + static T Get() { return T(); } +}; +template +struct BuiltInDefaultValueGetter { + static T Get() { + Assert(false, __FILE__, __LINE__, + "Default action undefined for the function return type."); + return internal::Invalid(); + // The above statement will never be reached, but is required in + // order for this function to compile. + } +}; + +// BuiltInDefaultValue::Get() returns the "built-in" default value +// for type T, which is NULL when T is a raw pointer type, 0 when T is +// a numeric type, false when T is bool, or "" when T is string or +// std::string. In addition, in C++11 and above, it turns a +// default-constructed T value if T is default constructible. For any +// other type T, the built-in default T value is undefined, and the +// function will abort the process. +template +class BuiltInDefaultValue { + public: + // This function returns true if type T has a built-in default value. + static bool Exists() { + return ::std::is_default_constructible::value; + } + + static T Get() { + return BuiltInDefaultValueGetter< + T, ::std::is_default_constructible::value>::Get(); + } +}; + +// This partial specialization says that we use the same built-in +// default value for T and const T. +template +class BuiltInDefaultValue { + public: + static bool Exists() { return BuiltInDefaultValue::Exists(); } + static T Get() { return BuiltInDefaultValue::Get(); } +}; + +// This partial specialization defines the default values for pointer +// types. +template +class BuiltInDefaultValue { + public: + static bool Exists() { return true; } + static T* Get() { return nullptr; } +}; + +// The following specializations define the default values for +// specific types we care about. +#define GMOCK_DEFINE_DEFAULT_ACTION_FOR_RETURN_TYPE_(type, value) \ + template <> \ + class BuiltInDefaultValue { \ + public: \ + static bool Exists() { return true; } \ + static type Get() { return value; } \ + } + +GMOCK_DEFINE_DEFAULT_ACTION_FOR_RETURN_TYPE_(void, ); // NOLINT +GMOCK_DEFINE_DEFAULT_ACTION_FOR_RETURN_TYPE_(::std::string, ""); +GMOCK_DEFINE_DEFAULT_ACTION_FOR_RETURN_TYPE_(bool, false); +GMOCK_DEFINE_DEFAULT_ACTION_FOR_RETURN_TYPE_(unsigned char, '\0'); +GMOCK_DEFINE_DEFAULT_ACTION_FOR_RETURN_TYPE_(signed char, '\0'); +GMOCK_DEFINE_DEFAULT_ACTION_FOR_RETURN_TYPE_(char, '\0'); + +// There's no need for a default action for signed wchar_t, as that +// type is the same as wchar_t for gcc, and invalid for MSVC. +// +// There's also no need for a default action for unsigned wchar_t, as +// that type is the same as unsigned int for gcc, and invalid for +// MSVC. +#if GMOCK_WCHAR_T_IS_NATIVE_ +GMOCK_DEFINE_DEFAULT_ACTION_FOR_RETURN_TYPE_(wchar_t, 0U); // NOLINT +#endif + +GMOCK_DEFINE_DEFAULT_ACTION_FOR_RETURN_TYPE_(unsigned short, 0U); // NOLINT +GMOCK_DEFINE_DEFAULT_ACTION_FOR_RETURN_TYPE_(signed short, 0); // NOLINT +GMOCK_DEFINE_DEFAULT_ACTION_FOR_RETURN_TYPE_(unsigned int, 0U); +GMOCK_DEFINE_DEFAULT_ACTION_FOR_RETURN_TYPE_(signed int, 0); +GMOCK_DEFINE_DEFAULT_ACTION_FOR_RETURN_TYPE_(unsigned long, 0UL); // NOLINT +GMOCK_DEFINE_DEFAULT_ACTION_FOR_RETURN_TYPE_(signed long, 0L); // NOLINT +GMOCK_DEFINE_DEFAULT_ACTION_FOR_RETURN_TYPE_(UInt64, 0); +GMOCK_DEFINE_DEFAULT_ACTION_FOR_RETURN_TYPE_(Int64, 0); +GMOCK_DEFINE_DEFAULT_ACTION_FOR_RETURN_TYPE_(float, 0); +GMOCK_DEFINE_DEFAULT_ACTION_FOR_RETURN_TYPE_(double, 0); + +#undef GMOCK_DEFINE_DEFAULT_ACTION_FOR_RETURN_TYPE_ + +} // namespace internal + +// When an unexpected function call is encountered, Google Mock will +// let it return a default value if the user has specified one for its +// return type, or if the return type has a built-in default value; +// otherwise Google Mock won't know what value to return and will have +// to abort the process. +// +// The DefaultValue class allows a user to specify the +// default value for a type T that is both copyable and publicly +// destructible (i.e. anything that can be used as a function return +// type). The usage is: +// +// // Sets the default value for type T to be foo. +// DefaultValue::Set(foo); +template +class DefaultValue { + public: + // Sets the default value for type T; requires T to be + // copy-constructable and have a public destructor. + static void Set(T x) { + delete producer_; + producer_ = new FixedValueProducer(x); + } + + // Provides a factory function to be called to generate the default value. + // This method can be used even if T is only move-constructible, but it is not + // limited to that case. + typedef T (*FactoryFunction)(); + static void SetFactory(FactoryFunction factory) { + delete producer_; + producer_ = new FactoryValueProducer(factory); + } + + // Unsets the default value for type T. + static void Clear() { + delete producer_; + producer_ = nullptr; + } + + // Returns true if the user has set the default value for type T. + static bool IsSet() { return producer_ != nullptr; } + + // Returns true if T has a default return value set by the user or there + // exists a built-in default value. + static bool Exists() { + return IsSet() || internal::BuiltInDefaultValue::Exists(); + } + + // Returns the default value for type T if the user has set one; + // otherwise returns the built-in default value. Requires that Exists() + // is true, which ensures that the return value is well-defined. + static T Get() { + return producer_ == nullptr ? internal::BuiltInDefaultValue::Get() + : producer_->Produce(); + } + + private: + class ValueProducer { + public: + virtual ~ValueProducer() {} + virtual T Produce() = 0; + }; + + class FixedValueProducer : public ValueProducer { + public: + explicit FixedValueProducer(T value) : value_(value) {} + T Produce() override { return value_; } + + private: + const T value_; + GTEST_DISALLOW_COPY_AND_ASSIGN_(FixedValueProducer); + }; + + class FactoryValueProducer : public ValueProducer { + public: + explicit FactoryValueProducer(FactoryFunction factory) + : factory_(factory) {} + T Produce() override { return factory_(); } + + private: + const FactoryFunction factory_; + GTEST_DISALLOW_COPY_AND_ASSIGN_(FactoryValueProducer); + }; + + static ValueProducer* producer_; +}; + +// This partial specialization allows a user to set default values for +// reference types. +template +class DefaultValue { + public: + // Sets the default value for type T&. + static void Set(T& x) { // NOLINT + address_ = &x; + } + + // Unsets the default value for type T&. + static void Clear() { address_ = nullptr; } + + // Returns true if the user has set the default value for type T&. + static bool IsSet() { return address_ != nullptr; } + + // Returns true if T has a default return value set by the user or there + // exists a built-in default value. + static bool Exists() { + return IsSet() || internal::BuiltInDefaultValue::Exists(); + } + + // Returns the default value for type T& if the user has set one; + // otherwise returns the built-in default value if there is one; + // otherwise aborts the process. + static T& Get() { + return address_ == nullptr ? internal::BuiltInDefaultValue::Get() + : *address_; + } + + private: + static T* address_; +}; + +// This specialization allows DefaultValue::Get() to +// compile. +template <> +class DefaultValue { + public: + static bool Exists() { return true; } + static void Get() {} +}; + +// Points to the user-set default value for type T. +template +typename DefaultValue::ValueProducer* DefaultValue::producer_ = nullptr; + +// Points to the user-set default value for type T&. +template +T* DefaultValue::address_ = nullptr; + +// Implement this interface to define an action for function type F. +template +class ActionInterface { + public: + typedef typename internal::Function::Result Result; + typedef typename internal::Function::ArgumentTuple ArgumentTuple; + + ActionInterface() {} + virtual ~ActionInterface() {} + + // Performs the action. This method is not const, as in general an + // action can have side effects and be stateful. For example, a + // get-the-next-element-from-the-collection action will need to + // remember the current element. + virtual Result Perform(const ArgumentTuple& args) = 0; + + private: + GTEST_DISALLOW_COPY_AND_ASSIGN_(ActionInterface); +}; + +// An Action is a copyable and IMMUTABLE (except by assignment) +// object that represents an action to be taken when a mock function +// of type F is called. The implementation of Action is just a +// std::shared_ptr to const ActionInterface. Don't inherit from Action! +// You can view an object implementing ActionInterface as a +// concrete action (including its current state), and an Action +// object as a handle to it. +template +class Action { + // Adapter class to allow constructing Action from a legacy ActionInterface. + // New code should create Actions from functors instead. + struct ActionAdapter { + // Adapter must be copyable to satisfy std::function requirements. + ::std::shared_ptr> impl_; + + template + typename internal::Function::Result operator()(Args&&... args) { + return impl_->Perform( + ::std::forward_as_tuple(::std::forward(args)...)); + } + }; + + public: + typedef typename internal::Function::Result Result; + typedef typename internal::Function::ArgumentTuple ArgumentTuple; + + // Constructs a null Action. Needed for storing Action objects in + // STL containers. + Action() {} + + // Construct an Action from a specified callable. + // This cannot take std::function directly, because then Action would not be + // directly constructible from lambda (it would require two conversions). + template , G>::value>::type> + Action(G&& fun) : fun_(::std::forward(fun)) {} // NOLINT + + // Constructs an Action from its implementation. + explicit Action(ActionInterface* impl) + : fun_(ActionAdapter{::std::shared_ptr>(impl)}) {} + + // This constructor allows us to turn an Action object into an + // Action, as long as F's arguments can be implicitly converted + // to Func's and Func's return type can be implicitly converted to F's. + template + explicit Action(const Action& action) : fun_(action.fun_) {} + + // Returns true if this is the DoDefault() action. + bool IsDoDefault() const { return fun_ == nullptr; } + + // Performs the action. Note that this method is const even though + // the corresponding method in ActionInterface is not. The reason + // is that a const Action means that it cannot be re-bound to + // another concrete action, not that the concrete action it binds to + // cannot change state. (Think of the difference between a const + // pointer and a pointer to const.) + Result Perform(ArgumentTuple args) const { + if (IsDoDefault()) { + internal::IllegalDoDefault(__FILE__, __LINE__); + } + return internal::Apply(fun_, ::std::move(args)); + } + + private: + template + friend class Action; + + // fun_ is an empty function if this is the DoDefault() action. + ::std::function fun_; +}; + +// The PolymorphicAction class template makes it easy to implement a +// polymorphic action (i.e. an action that can be used in mock +// functions of than one type, e.g. Return()). +// +// To define a polymorphic action, a user first provides a COPYABLE +// implementation class that has a Perform() method template: +// +// class FooAction { +// public: +// template +// Result Perform(const ArgumentTuple& args) const { +// // Processes the arguments and returns a result, using +// // std::get(args) to get the N-th (0-based) argument in the tuple. +// } +// ... +// }; +// +// Then the user creates the polymorphic action using +// MakePolymorphicAction(object) where object has type FooAction. See +// the definition of Return(void) and SetArgumentPointee(value) for +// complete examples. +template +class PolymorphicAction { + public: + explicit PolymorphicAction(const Impl& impl) : impl_(impl) {} + + template + operator Action() const { + return Action(new MonomorphicImpl(impl_)); + } + + private: + template + class MonomorphicImpl : public ActionInterface { + public: + typedef typename internal::Function::Result Result; + typedef typename internal::Function::ArgumentTuple ArgumentTuple; + + explicit MonomorphicImpl(const Impl& impl) : impl_(impl) {} + + Result Perform(const ArgumentTuple& args) override { + return impl_.template Perform(args); + } + + private: + Impl impl_; + + GTEST_DISALLOW_ASSIGN_(MonomorphicImpl); + }; + + Impl impl_; + + GTEST_DISALLOW_ASSIGN_(PolymorphicAction); +}; + +// Creates an Action from its implementation and returns it. The +// created Action object owns the implementation. +template +Action MakeAction(ActionInterface* impl) { + return Action(impl); +} + +// Creates a polymorphic action from its implementation. This is +// easier to use than the PolymorphicAction constructor as it +// doesn't require you to explicitly write the template argument, e.g. +// +// MakePolymorphicAction(foo); +// vs +// PolymorphicAction(foo); +template +inline PolymorphicAction MakePolymorphicAction(const Impl& impl) { + return PolymorphicAction(impl); +} + +namespace internal { + +// Helper struct to specialize ReturnAction to execute a move instead of a copy +// on return. Useful for move-only types, but could be used on any type. +template +struct ByMoveWrapper { + explicit ByMoveWrapper(T value) : payload(std::move(value)) {} + T payload; +}; + +// Implements the polymorphic Return(x) action, which can be used in +// any function that returns the type of x, regardless of the argument +// types. +// +// Note: The value passed into Return must be converted into +// Function::Result when this action is cast to Action rather than +// when that action is performed. This is important in scenarios like +// +// MOCK_METHOD1(Method, T(U)); +// ... +// { +// Foo foo; +// X x(&foo); +// EXPECT_CALL(mock, Method(_)).WillOnce(Return(x)); +// } +// +// In the example above the variable x holds reference to foo which leaves +// scope and gets destroyed. If copying X just copies a reference to foo, +// that copy will be left with a hanging reference. If conversion to T +// makes a copy of foo, the above code is safe. To support that scenario, we +// need to make sure that the type conversion happens inside the EXPECT_CALL +// statement, and conversion of the result of Return to Action is a +// good place for that. +// +// The real life example of the above scenario happens when an invocation +// of gtl::Container() is passed into Return. +// +template +class ReturnAction { + public: + // Constructs a ReturnAction object from the value to be returned. + // 'value' is passed by value instead of by const reference in order + // to allow Return("string literal") to compile. + explicit ReturnAction(R value) : value_(new R(std::move(value))) {} + + // This template type conversion operator allows Return(x) to be + // used in ANY function that returns x's type. + template + operator Action() const { // NOLINT + // Assert statement belongs here because this is the best place to verify + // conditions on F. It produces the clearest error messages + // in most compilers. + // Impl really belongs in this scope as a local class but can't + // because MSVC produces duplicate symbols in different translation units + // in this case. Until MS fixes that bug we put Impl into the class scope + // and put the typedef both here (for use in assert statement) and + // in the Impl class. But both definitions must be the same. + typedef typename Function::Result Result; + GTEST_COMPILE_ASSERT_( + !std::is_reference::value, + use_ReturnRef_instead_of_Return_to_return_a_reference); + static_assert(!std::is_void::value, + "Can't use Return() on an action expected to return `void`."); + return Action(new Impl(value_)); + } + + private: + // Implements the Return(x) action for a particular function type F. + template + class Impl : public ActionInterface { + public: + typedef typename Function::Result Result; + typedef typename Function::ArgumentTuple ArgumentTuple; + + // The implicit cast is necessary when Result has more than one + // single-argument constructor (e.g. Result is std::vector) and R + // has a type conversion operator template. In that case, value_(value) + // won't compile as the compiler doesn't known which constructor of + // Result to call. ImplicitCast_ forces the compiler to convert R to + // Result without considering explicit constructors, thus resolving the + // ambiguity. value_ is then initialized using its copy constructor. + explicit Impl(const std::shared_ptr& value) + : value_before_cast_(*value), + value_(ImplicitCast_(value_before_cast_)) {} + + Result Perform(const ArgumentTuple&) override { return value_; } + + private: + GTEST_COMPILE_ASSERT_(!std::is_reference::value, + Result_cannot_be_a_reference_type); + // We save the value before casting just in case it is being cast to a + // wrapper type. + R value_before_cast_; + Result value_; + + GTEST_DISALLOW_COPY_AND_ASSIGN_(Impl); + }; + + // Partially specialize for ByMoveWrapper. This version of ReturnAction will + // move its contents instead. + template + class Impl, F> : public ActionInterface { + public: + typedef typename Function::Result Result; + typedef typename Function::ArgumentTuple ArgumentTuple; + + explicit Impl(const std::shared_ptr& wrapper) + : performed_(false), wrapper_(wrapper) {} + + Result Perform(const ArgumentTuple&) override { + GTEST_CHECK_(!performed_) + << "A ByMove() action should only be performed once."; + performed_ = true; + return std::move(wrapper_->payload); + } + + private: + bool performed_; + const std::shared_ptr wrapper_; + + GTEST_DISALLOW_ASSIGN_(Impl); + }; + + const std::shared_ptr value_; + + GTEST_DISALLOW_ASSIGN_(ReturnAction); +}; + +// Implements the ReturnNull() action. +class ReturnNullAction { + public: + // Allows ReturnNull() to be used in any pointer-returning function. In C++11 + // this is enforced by returning nullptr, and in non-C++11 by asserting a + // pointer type on compile time. + template + static Result Perform(const ArgumentTuple&) { + return nullptr; + } +}; + +// Implements the Return() action. +class ReturnVoidAction { + public: + // Allows Return() to be used in any void-returning function. + template + static void Perform(const ArgumentTuple&) { + CompileAssertTypesEqual(); + } +}; + +// Implements the polymorphic ReturnRef(x) action, which can be used +// in any function that returns a reference to the type of x, +// regardless of the argument types. +template +class ReturnRefAction { + public: + // Constructs a ReturnRefAction object from the reference to be returned. + explicit ReturnRefAction(T& ref) : ref_(ref) {} // NOLINT + + // This template type conversion operator allows ReturnRef(x) to be + // used in ANY function that returns a reference to x's type. + template + operator Action() const { + typedef typename Function::Result Result; + // Asserts that the function return type is a reference. This + // catches the user error of using ReturnRef(x) when Return(x) + // should be used, and generates some helpful error message. + GTEST_COMPILE_ASSERT_(std::is_reference::value, + use_Return_instead_of_ReturnRef_to_return_a_value); + return Action(new Impl(ref_)); + } + + private: + // Implements the ReturnRef(x) action for a particular function type F. + template + class Impl : public ActionInterface { + public: + typedef typename Function::Result Result; + typedef typename Function::ArgumentTuple ArgumentTuple; + + explicit Impl(T& ref) : ref_(ref) {} // NOLINT + + Result Perform(const ArgumentTuple&) override { return ref_; } + + private: + T& ref_; + + GTEST_DISALLOW_ASSIGN_(Impl); + }; + + T& ref_; + + GTEST_DISALLOW_ASSIGN_(ReturnRefAction); +}; + +// Implements the polymorphic ReturnRefOfCopy(x) action, which can be +// used in any function that returns a reference to the type of x, +// regardless of the argument types. +template +class ReturnRefOfCopyAction { + public: + // Constructs a ReturnRefOfCopyAction object from the reference to + // be returned. + explicit ReturnRefOfCopyAction(const T& value) : value_(value) {} // NOLINT + + // This template type conversion operator allows ReturnRefOfCopy(x) to be + // used in ANY function that returns a reference to x's type. + template + operator Action() const { + typedef typename Function::Result Result; + // Asserts that the function return type is a reference. This + // catches the user error of using ReturnRefOfCopy(x) when Return(x) + // should be used, and generates some helpful error message. + GTEST_COMPILE_ASSERT_( + std::is_reference::value, + use_Return_instead_of_ReturnRefOfCopy_to_return_a_value); + return Action(new Impl(value_)); + } + + private: + // Implements the ReturnRefOfCopy(x) action for a particular function type F. + template + class Impl : public ActionInterface { + public: + typedef typename Function::Result Result; + typedef typename Function::ArgumentTuple ArgumentTuple; + + explicit Impl(const T& value) : value_(value) {} // NOLINT + + Result Perform(const ArgumentTuple&) override { return value_; } + + private: + T value_; + + GTEST_DISALLOW_ASSIGN_(Impl); + }; + + const T value_; + + GTEST_DISALLOW_ASSIGN_(ReturnRefOfCopyAction); +}; + +// Implements the polymorphic DoDefault() action. +class DoDefaultAction { + public: + // This template type conversion operator allows DoDefault() to be + // used in any function. + template + operator Action() const { return Action(); } // NOLINT +}; + +// Implements the Assign action to set a given pointer referent to a +// particular value. +template +class AssignAction { + public: + AssignAction(T1* ptr, T2 value) : ptr_(ptr), value_(value) {} + + template + void Perform(const ArgumentTuple& /* args */) const { + *ptr_ = value_; + } + + private: + T1* const ptr_; + const T2 value_; + + GTEST_DISALLOW_ASSIGN_(AssignAction); +}; + +#if !GTEST_OS_WINDOWS_MOBILE + +// Implements the SetErrnoAndReturn action to simulate return from +// various system calls and libc functions. +template +class SetErrnoAndReturnAction { + public: + SetErrnoAndReturnAction(int errno_value, T result) + : errno_(errno_value), + result_(result) {} + template + Result Perform(const ArgumentTuple& /* args */) const { + errno = errno_; + return result_; + } + + private: + const int errno_; + const T result_; + + GTEST_DISALLOW_ASSIGN_(SetErrnoAndReturnAction); +}; + +#endif // !GTEST_OS_WINDOWS_MOBILE + +// Implements the SetArgumentPointee(x) action for any function +// whose N-th argument (0-based) is a pointer to x's type. +template +struct SetArgumentPointeeAction { + A value; + + template + void operator()(const Args&... args) const { + *::std::get(std::tie(args...)) = value; + } +}; + +// Implements the Invoke(object_ptr, &Class::Method) action. +template +struct InvokeMethodAction { + Class* const obj_ptr; + const MethodPtr method_ptr; + + template + auto operator()(Args&&... args) const + -> decltype((obj_ptr->*method_ptr)(std::forward(args)...)) { + return (obj_ptr->*method_ptr)(std::forward(args)...); + } +}; + +// Implements the InvokeWithoutArgs(f) action. The template argument +// FunctionImpl is the implementation type of f, which can be either a +// function pointer or a functor. InvokeWithoutArgs(f) can be used as an +// Action as long as f's type is compatible with F. +template +struct InvokeWithoutArgsAction { + FunctionImpl function_impl; + + // Allows InvokeWithoutArgs(f) to be used as any action whose type is + // compatible with f. + template + auto operator()(const Args&...) -> decltype(function_impl()) { + return function_impl(); + } +}; + +// Implements the InvokeWithoutArgs(object_ptr, &Class::Method) action. +template +struct InvokeMethodWithoutArgsAction { + Class* const obj_ptr; + const MethodPtr method_ptr; + + using ReturnType = typename std::result_of::type; + + template + ReturnType operator()(const Args&...) const { + return (obj_ptr->*method_ptr)(); + } +}; + +// Implements the IgnoreResult(action) action. +template +class IgnoreResultAction { + public: + explicit IgnoreResultAction(const A& action) : action_(action) {} + + template + operator Action() const { + // Assert statement belongs here because this is the best place to verify + // conditions on F. It produces the clearest error messages + // in most compilers. + // Impl really belongs in this scope as a local class but can't + // because MSVC produces duplicate symbols in different translation units + // in this case. Until MS fixes that bug we put Impl into the class scope + // and put the typedef both here (for use in assert statement) and + // in the Impl class. But both definitions must be the same. + typedef typename internal::Function::Result Result; + + // Asserts at compile time that F returns void. + CompileAssertTypesEqual(); + + return Action(new Impl(action_)); + } + + private: + template + class Impl : public ActionInterface { + public: + typedef typename internal::Function::Result Result; + typedef typename internal::Function::ArgumentTuple ArgumentTuple; + + explicit Impl(const A& action) : action_(action) {} + + void Perform(const ArgumentTuple& args) override { + // Performs the action and ignores its result. + action_.Perform(args); + } + + private: + // Type OriginalFunction is the same as F except that its return + // type is IgnoredValue. + typedef typename internal::Function::MakeResultIgnoredValue + OriginalFunction; + + const Action action_; + + GTEST_DISALLOW_ASSIGN_(Impl); + }; + + const A action_; + + GTEST_DISALLOW_ASSIGN_(IgnoreResultAction); +}; + +template +struct WithArgsAction { + InnerAction action; + + // The inner action could be anything convertible to Action. + // We use the conversion operator to detect the signature of the inner Action. + template + operator Action() const { // NOLINT + Action>::type...)> + converted(action); + + return [converted](Args... args) -> R { + return converted.Perform(std::forward_as_tuple( + std::get(std::forward_as_tuple(std::forward(args)...))...)); + }; + } +}; + +template +struct DoAllAction { + private: + template + std::vector> Convert(IndexSequence) const { + return {std::get(actions)...}; + } + + public: + std::tuple actions; + + template + operator Action() const { // NOLINT + struct Op { + std::vector> converted; + Action last; + R operator()(Args... args) const { + auto tuple_args = std::forward_as_tuple(std::forward(args)...); + for (auto& a : converted) { + a.Perform(tuple_args); + } + return last.Perform(tuple_args); + } + }; + return Op{Convert(MakeIndexSequence()), + std::get(actions)}; + } +}; + +} // namespace internal + +// An Unused object can be implicitly constructed from ANY value. +// This is handy when defining actions that ignore some or all of the +// mock function arguments. For example, given +// +// MOCK_METHOD3(Foo, double(const string& label, double x, double y)); +// MOCK_METHOD3(Bar, double(int index, double x, double y)); +// +// instead of +// +// double DistanceToOriginWithLabel(const string& label, double x, double y) { +// return sqrt(x*x + y*y); +// } +// double DistanceToOriginWithIndex(int index, double x, double y) { +// return sqrt(x*x + y*y); +// } +// ... +// EXPECT_CALL(mock, Foo("abc", _, _)) +// .WillOnce(Invoke(DistanceToOriginWithLabel)); +// EXPECT_CALL(mock, Bar(5, _, _)) +// .WillOnce(Invoke(DistanceToOriginWithIndex)); +// +// you could write +// +// // We can declare any uninteresting argument as Unused. +// double DistanceToOrigin(Unused, double x, double y) { +// return sqrt(x*x + y*y); +// } +// ... +// EXPECT_CALL(mock, Foo("abc", _, _)).WillOnce(Invoke(DistanceToOrigin)); +// EXPECT_CALL(mock, Bar(5, _, _)).WillOnce(Invoke(DistanceToOrigin)); +typedef internal::IgnoredValue Unused; + +// Creates an action that does actions a1, a2, ..., sequentially in +// each invocation. +template +internal::DoAllAction::type...> DoAll( + Action&&... action) { + return {std::forward_as_tuple(std::forward(action)...)}; +} + +// WithArg(an_action) creates an action that passes the k-th +// (0-based) argument of the mock function to an_action and performs +// it. It adapts an action accepting one argument to one that accepts +// multiple arguments. For convenience, we also provide +// WithArgs(an_action) (defined below) as a synonym. +template +internal::WithArgsAction::type, k> +WithArg(InnerAction&& action) { + return {std::forward(action)}; +} + +// WithArgs(an_action) creates an action that passes +// the selected arguments of the mock function to an_action and +// performs it. It serves as an adaptor between actions with +// different argument lists. +template +internal::WithArgsAction::type, k, ks...> +WithArgs(InnerAction&& action) { + return {std::forward(action)}; +} + +// WithoutArgs(inner_action) can be used in a mock function with a +// non-empty argument list to perform inner_action, which takes no +// argument. In other words, it adapts an action accepting no +// argument to one that accepts (and ignores) arguments. +template +internal::WithArgsAction::type> +WithoutArgs(InnerAction&& action) { + return {std::forward(action)}; +} + +// Creates an action that returns 'value'. 'value' is passed by value +// instead of const reference - otherwise Return("string literal") +// will trigger a compiler error about using array as initializer. +template +internal::ReturnAction Return(R value) { + return internal::ReturnAction(std::move(value)); +} + +// Creates an action that returns NULL. +inline PolymorphicAction ReturnNull() { + return MakePolymorphicAction(internal::ReturnNullAction()); +} + +// Creates an action that returns from a void function. +inline PolymorphicAction Return() { + return MakePolymorphicAction(internal::ReturnVoidAction()); +} + +// Creates an action that returns the reference to a variable. +template +inline internal::ReturnRefAction ReturnRef(R& x) { // NOLINT + return internal::ReturnRefAction(x); +} + +// Creates an action that returns the reference to a copy of the +// argument. The copy is created when the action is constructed and +// lives as long as the action. +template +inline internal::ReturnRefOfCopyAction ReturnRefOfCopy(const R& x) { + return internal::ReturnRefOfCopyAction(x); +} + +// Modifies the parent action (a Return() action) to perform a move of the +// argument instead of a copy. +// Return(ByMove()) actions can only be executed once and will assert this +// invariant. +template +internal::ByMoveWrapper ByMove(R x) { + return internal::ByMoveWrapper(std::move(x)); +} + +// Creates an action that does the default action for the give mock function. +inline internal::DoDefaultAction DoDefault() { + return internal::DoDefaultAction(); +} + +// Creates an action that sets the variable pointed by the N-th +// (0-based) function argument to 'value'. +template +internal::SetArgumentPointeeAction SetArgPointee(T x) { + return {std::move(x)}; +} + +// The following version is DEPRECATED. +template +internal::SetArgumentPointeeAction SetArgumentPointee(T x) { + return {std::move(x)}; +} + +// Creates an action that sets a pointer referent to a given value. +template +PolymorphicAction > Assign(T1* ptr, T2 val) { + return MakePolymorphicAction(internal::AssignAction(ptr, val)); +} + +#if !GTEST_OS_WINDOWS_MOBILE + +// Creates an action that sets errno and returns the appropriate error. +template +PolymorphicAction > +SetErrnoAndReturn(int errval, T result) { + return MakePolymorphicAction( + internal::SetErrnoAndReturnAction(errval, result)); +} + +#endif // !GTEST_OS_WINDOWS_MOBILE + +// Various overloads for Invoke(). + +// Legacy function. +// Actions can now be implicitly constructed from callables. No need to create +// wrapper objects. +// This function exists for backwards compatibility. +template +typename std::decay::type Invoke(FunctionImpl&& function_impl) { + return std::forward(function_impl); +} + +// Creates an action that invokes the given method on the given object +// with the mock function's arguments. +template +internal::InvokeMethodAction Invoke(Class* obj_ptr, + MethodPtr method_ptr) { + return {obj_ptr, method_ptr}; +} + +// Creates an action that invokes 'function_impl' with no argument. +template +internal::InvokeWithoutArgsAction::type> +InvokeWithoutArgs(FunctionImpl function_impl) { + return {std::move(function_impl)}; +} + +// Creates an action that invokes the given method on the given object +// with no argument. +template +internal::InvokeMethodWithoutArgsAction InvokeWithoutArgs( + Class* obj_ptr, MethodPtr method_ptr) { + return {obj_ptr, method_ptr}; +} + +// Creates an action that performs an_action and throws away its +// result. In other words, it changes the return type of an_action to +// void. an_action MUST NOT return void, or the code won't compile. +template +inline internal::IgnoreResultAction IgnoreResult(const A& an_action) { + return internal::IgnoreResultAction(an_action); +} + +// Creates a reference wrapper for the given L-value. If necessary, +// you can explicitly specify the type of the reference. For example, +// suppose 'derived' is an object of type Derived, ByRef(derived) +// would wrap a Derived&. If you want to wrap a const Base& instead, +// where Base is a base class of Derived, just write: +// +// ByRef(derived) +// +// N.B. ByRef is redundant with std::ref, std::cref and std::reference_wrapper. +// However, it may still be used for consistency with ByMove(). +template +inline ::std::reference_wrapper ByRef(T& l_value) { // NOLINT + return ::std::reference_wrapper(l_value); +} + +} // namespace testing + +#ifdef _MSC_VER +# pragma warning(pop) +#endif + + +#endif // GMOCK_INCLUDE_GMOCK_GMOCK_ACTIONS_H_ diff --git a/googlemock/include/gmock/gmock-cardinalities.h b/googlemock/include/gmock/gmock-cardinalities.h new file mode 100644 index 00000000..4b269a3e --- /dev/null +++ b/googlemock/include/gmock/gmock-cardinalities.h @@ -0,0 +1,153 @@ +// Copyright 2007, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + +// Google Mock - a framework for writing C++ mock classes. +// +// This file implements some commonly used cardinalities. More +// cardinalities can be defined by the user implementing the +// CardinalityInterface interface if necessary. + +// GOOGLETEST_CM0002 DO NOT DELETE + +#ifndef GMOCK_INCLUDE_GMOCK_GMOCK_CARDINALITIES_H_ +#define GMOCK_INCLUDE_GMOCK_GMOCK_CARDINALITIES_H_ + +#include +#include +#include // NOLINT +#include "gmock/internal/gmock-port.h" +#include "gtest/gtest.h" + +GTEST_DISABLE_MSC_WARNINGS_PUSH_(4251 \ +/* class A needs to have dll-interface to be used by clients of class B */) + +namespace testing { + +// To implement a cardinality Foo, define: +// 1. a class FooCardinality that implements the +// CardinalityInterface interface, and +// 2. a factory function that creates a Cardinality object from a +// const FooCardinality*. +// +// The two-level delegation design follows that of Matcher, providing +// consistency for extension developers. It also eases ownership +// management as Cardinality objects can now be copied like plain values. + +// The implementation of a cardinality. +class CardinalityInterface { + public: + virtual ~CardinalityInterface() {} + + // Conservative estimate on the lower/upper bound of the number of + // calls allowed. + virtual int ConservativeLowerBound() const { return 0; } + virtual int ConservativeUpperBound() const { return INT_MAX; } + + // Returns true if call_count calls will satisfy this cardinality. + virtual bool IsSatisfiedByCallCount(int call_count) const = 0; + + // Returns true if call_count calls will saturate this cardinality. + virtual bool IsSaturatedByCallCount(int call_count) const = 0; + + // Describes self to an ostream. + virtual void DescribeTo(::std::ostream* os) const = 0; +}; + +// A Cardinality is a copyable and IMMUTABLE (except by assignment) +// object that specifies how many times a mock function is expected to +// be called. The implementation of Cardinality is just a std::shared_ptr +// to const CardinalityInterface. Don't inherit from Cardinality! +class GTEST_API_ Cardinality { + public: + // Constructs a null cardinality. Needed for storing Cardinality + // objects in STL containers. + Cardinality() {} + + // Constructs a Cardinality from its implementation. + explicit Cardinality(const CardinalityInterface* impl) : impl_(impl) {} + + // Conservative estimate on the lower/upper bound of the number of + // calls allowed. + int ConservativeLowerBound() const { return impl_->ConservativeLowerBound(); } + int ConservativeUpperBound() const { return impl_->ConservativeUpperBound(); } + + // Returns true if call_count calls will satisfy this cardinality. + bool IsSatisfiedByCallCount(int call_count) const { + return impl_->IsSatisfiedByCallCount(call_count); + } + + // Returns true if call_count calls will saturate this cardinality. + bool IsSaturatedByCallCount(int call_count) const { + return impl_->IsSaturatedByCallCount(call_count); + } + + // Returns true if call_count calls will over-saturate this + // cardinality, i.e. exceed the maximum number of allowed calls. + bool IsOverSaturatedByCallCount(int call_count) const { + return impl_->IsSaturatedByCallCount(call_count) && + !impl_->IsSatisfiedByCallCount(call_count); + } + + // Describes self to an ostream + void DescribeTo(::std::ostream* os) const { impl_->DescribeTo(os); } + + // Describes the given actual call count to an ostream. + static void DescribeActualCallCountTo(int actual_call_count, + ::std::ostream* os); + + private: + std::shared_ptr impl_; +}; + +// Creates a cardinality that allows at least n calls. +GTEST_API_ Cardinality AtLeast(int n); + +// Creates a cardinality that allows at most n calls. +GTEST_API_ Cardinality AtMost(int n); + +// Creates a cardinality that allows any number of calls. +GTEST_API_ Cardinality AnyNumber(); + +// Creates a cardinality that allows between min and max calls. +GTEST_API_ Cardinality Between(int min, int max); + +// Creates a cardinality that allows exactly n calls. +GTEST_API_ Cardinality Exactly(int n); + +// Creates a cardinality from its implementation. +inline Cardinality MakeCardinality(const CardinalityInterface* c) { + return Cardinality(c); +} + +} // namespace testing + +GTEST_DISABLE_MSC_WARNINGS_POP_() // 4251 + +#endif // GMOCK_INCLUDE_GMOCK_GMOCK_CARDINALITIES_H_ diff --git a/googlemock/include/gmock/gmock-function-mocker.h b/googlemock/include/gmock/gmock-function-mocker.h new file mode 100644 index 00000000..cc1535c8 --- /dev/null +++ b/googlemock/include/gmock/gmock-function-mocker.h @@ -0,0 +1,253 @@ +// Copyright 2007, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// Google Mock - a framework for writing C++ mock classes. +// +// This file implements MOCK_METHOD. + +// GOOGLETEST_CM0002 DO NOT DELETE + +#ifndef THIRD_PARTY_GOOGLETEST_GOOGLEMOCK_INCLUDE_GMOCK_INTERNAL_GMOCK_FUNCTION_MOCKER_H_ // NOLINT +#define THIRD_PARTY_GOOGLETEST_GOOGLEMOCK_INCLUDE_GMOCK_INTERNAL_GMOCK_FUNCTION_MOCKER_H_ // NOLINT + +#include "gmock/gmock-generated-function-mockers.h" // NOLINT +#include "gmock/internal/gmock-pp.h" + +#define MOCK_METHOD(...) \ + GMOCK_PP_VARIADIC_CALL(GMOCK_INTERNAL_MOCK_METHOD_ARG_, __VA_ARGS__) + +#define GMOCK_INTERNAL_MOCK_METHOD_ARG_1(...) \ + GMOCK_INTERNAL_WRONG_ARITY(__VA_ARGS__) + +#define GMOCK_INTERNAL_MOCK_METHOD_ARG_2(...) \ + GMOCK_INTERNAL_WRONG_ARITY(__VA_ARGS__) + +#define GMOCK_INTERNAL_MOCK_METHOD_ARG_3(_Ret, _MethodName, _Args) \ + GMOCK_INTERNAL_MOCK_METHOD_ARG_4(_Ret, _MethodName, _Args, ()) + +#define GMOCK_INTERNAL_MOCK_METHOD_ARG_4(_Ret, _MethodName, _Args, _Spec) \ + GMOCK_INTERNAL_ASSERT_PARENTHESIS(_Args); \ + GMOCK_INTERNAL_ASSERT_PARENTHESIS(_Spec); \ + GMOCK_INTERNAL_ASSERT_VALID_SIGNATURE( \ + GMOCK_PP_NARG0 _Args, GMOCK_INTERNAL_SIGNATURE(_Ret, _Args)); \ + GMOCK_INTERNAL_ASSERT_VALID_SPEC(_Spec) \ + GMOCK_INTERNAL_MOCK_METHOD_IMPL( \ + GMOCK_PP_NARG0 _Args, _MethodName, GMOCK_INTERNAL_HAS_CONST(_Spec), \ + GMOCK_INTERNAL_HAS_OVERRIDE(_Spec), GMOCK_INTERNAL_HAS_FINAL(_Spec), \ + GMOCK_INTERNAL_HAS_NOEXCEPT(_Spec), GMOCK_INTERNAL_GET_CALLTYPE(_Spec), \ + (GMOCK_INTERNAL_SIGNATURE(_Ret, _Args))) + +#define GMOCK_INTERNAL_MOCK_METHOD_ARG_5(...) \ + GMOCK_INTERNAL_WRONG_ARITY(__VA_ARGS__) + +#define GMOCK_INTERNAL_MOCK_METHOD_ARG_6(...) \ + GMOCK_INTERNAL_WRONG_ARITY(__VA_ARGS__) + +#define GMOCK_INTERNAL_MOCK_METHOD_ARG_7(...) \ + GMOCK_INTERNAL_WRONG_ARITY(__VA_ARGS__) + +#define GMOCK_INTERNAL_WRONG_ARITY(...) \ + static_assert( \ + false, \ + "MOCK_METHOD must be called with 3 or 4 arguments. _Ret, " \ + "_MethodName, _Args and optionally _Spec. _Args and _Spec must be " \ + "enclosed in parentheses. If _Ret is a type with unprotected commas, " \ + "it must also be enclosed in parentheses.") + +#define GMOCK_INTERNAL_ASSERT_PARENTHESIS(_Tuple) \ + static_assert( \ + GMOCK_PP_IS_ENCLOSED_PARENS(_Tuple), \ + GMOCK_PP_STRINGIZE(_Tuple) " should be enclosed in parentheses.") + +#define GMOCK_INTERNAL_ASSERT_VALID_SIGNATURE(_N, ...) \ + static_assert( \ + std::is_function<__VA_ARGS__>::value, \ + "Signature must be a function type, maybe return type contains " \ + "unprotected comma."); \ + static_assert( \ + ::testing::tuple_size::ArgumentTuple>::value == _N, \ + "This method does not take " GMOCK_PP_STRINGIZE( \ + _N) " arguments. Parenthesize all types with unproctected commas.") + +#define GMOCK_INTERNAL_ASSERT_VALID_SPEC(_Spec) \ + GMOCK_PP_FOR_EACH(GMOCK_INTERNAL_ASSERT_VALID_SPEC_ELEMENT, ~, _Spec) + +#define GMOCK_INTERNAL_MOCK_METHOD_IMPL(_N, _MethodName, _Constness, \ + _Override, _Final, _Noexcept, \ + _CallType, _Signature) \ + typename ::testing::internal::Function::Result \ + GMOCK_INTERNAL_EXPAND(_CallType) \ + _MethodName(GMOCK_PP_REPEAT(GMOCK_INTERNAL_PARAMETER, _Signature, _N)) \ + GMOCK_PP_IF(_Constness, const, ) GMOCK_PP_IF(_Noexcept, noexcept, ) \ + GMOCK_PP_IF(_Override, override, ) \ + GMOCK_PP_IF(_Final, final, ) { \ + GMOCK_MOCKER_(_N, _Constness, _MethodName) \ + .SetOwnerAndName(this, #_MethodName); \ + return GMOCK_MOCKER_(_N, _Constness, _MethodName) \ + .Invoke(GMOCK_PP_REPEAT(GMOCK_INTERNAL_FORWARD_ARG, _Signature, _N)); \ + } \ + ::testing::MockSpec gmock_##_MethodName( \ + GMOCK_PP_REPEAT(GMOCK_INTERNAL_MATCHER_PARAMETER, _Signature, _N)) \ + GMOCK_PP_IF(_Constness, const, ) { \ + GMOCK_MOCKER_(_N, _Constness, _MethodName).RegisterOwner(this); \ + return GMOCK_MOCKER_(_N, _Constness, _MethodName) \ + .With(GMOCK_PP_REPEAT(GMOCK_INTERNAL_MATCHER_ARGUMENT, , _N)); \ + } \ + ::testing::MockSpec gmock_##_MethodName( \ + const ::testing::internal::WithoutMatchers&, \ + GMOCK_PP_IF(_Constness, const, )::testing::internal::Function< \ + GMOCK_PP_REMOVE_PARENS(_Signature)>*) \ + const GMOCK_PP_IF(_Noexcept, noexcept, ) { \ + return GMOCK_PP_CAT(::testing::internal::AdjustConstness_, \ + GMOCK_PP_IF(_Constness, const, ))(this) \ + ->gmock_##_MethodName(GMOCK_PP_REPEAT( \ + GMOCK_INTERNAL_A_MATCHER_ARGUMENT, _Signature, _N)); \ + } \ + mutable ::testing::FunctionMocker \ + GMOCK_MOCKER_(_N, _Constness, _MethodName) + +#define GMOCK_INTERNAL_EXPAND(...) __VA_ARGS__ + +// Five Valid modifiers. +#define GMOCK_INTERNAL_HAS_CONST(_Tuple) \ + GMOCK_PP_HAS_COMMA(GMOCK_PP_FOR_EACH(GMOCK_INTERNAL_DETECT_CONST, ~, _Tuple)) + +#define GMOCK_INTERNAL_HAS_OVERRIDE(_Tuple) \ + GMOCK_PP_HAS_COMMA( \ + GMOCK_PP_FOR_EACH(GMOCK_INTERNAL_DETECT_OVERRIDE, ~, _Tuple)) + +#define GMOCK_INTERNAL_HAS_FINAL(_Tuple) \ + GMOCK_PP_HAS_COMMA(GMOCK_PP_FOR_EACH(GMOCK_INTERNAL_DETECT_FINAL, ~, _Tuple)) + +#define GMOCK_INTERNAL_HAS_NOEXCEPT(_Tuple) \ + GMOCK_PP_HAS_COMMA( \ + GMOCK_PP_FOR_EACH(GMOCK_INTERNAL_DETECT_NOEXCEPT, ~, _Tuple)) + +#define GMOCK_INTERNAL_GET_CALLTYPE(_Tuple) \ + GMOCK_PP_FOR_EACH(GMOCK_INTERNAL_GET_CALLTYPE_IMPL, ~, _Tuple) + +#define GMOCK_INTERNAL_ASSERT_VALID_SPEC_ELEMENT(_i, _, _elem) \ + static_assert( \ + (GMOCK_PP_HAS_COMMA(GMOCK_INTERNAL_DETECT_CONST(_i, _, _elem)) + \ + GMOCK_PP_HAS_COMMA(GMOCK_INTERNAL_DETECT_OVERRIDE(_i, _, _elem)) + \ + GMOCK_PP_HAS_COMMA(GMOCK_INTERNAL_DETECT_FINAL(_i, _, _elem)) + \ + GMOCK_PP_HAS_COMMA(GMOCK_INTERNAL_DETECT_NOEXCEPT(_i, _, _elem)) + \ + GMOCK_INTERNAL_IS_CALLTYPE(_elem)) == 1, \ + GMOCK_PP_STRINGIZE( \ + _elem) " cannot be recognized as a valid specification modifier."); + +// Modifiers implementation. +#define GMOCK_INTERNAL_DETECT_CONST(_i, _, _elem) \ + GMOCK_PP_CAT(GMOCK_INTERNAL_DETECT_CONST_I_, _elem) + +#define GMOCK_INTERNAL_DETECT_CONST_I_const , + +#define GMOCK_INTERNAL_DETECT_OVERRIDE(_i, _, _elem) \ + GMOCK_PP_CAT(GMOCK_INTERNAL_DETECT_OVERRIDE_I_, _elem) + +#define GMOCK_INTERNAL_DETECT_OVERRIDE_I_override , + +#define GMOCK_INTERNAL_DETECT_FINAL(_i, _, _elem) \ + GMOCK_PP_CAT(GMOCK_INTERNAL_DETECT_FINAL_I_, _elem) + +#define GMOCK_INTERNAL_DETECT_FINAL_I_final , + +// TODO(iserna): Maybe noexcept should accept an argument here as well. +#define GMOCK_INTERNAL_DETECT_NOEXCEPT(_i, _, _elem) \ + GMOCK_PP_CAT(GMOCK_INTERNAL_DETECT_NOEXCEPT_I_, _elem) + +#define GMOCK_INTERNAL_DETECT_NOEXCEPT_I_noexcept , + +#define GMOCK_INTERNAL_GET_CALLTYPE_IMPL(_i, _, _elem) \ + GMOCK_PP_IF(GMOCK_INTERNAL_IS_CALLTYPE(_elem), \ + GMOCK_INTERNAL_GET_VALUE_CALLTYPE, GMOCK_PP_EMPTY) \ + (_elem) + +// TODO(iserna): GMOCK_INTERNAL_IS_CALLTYPE and +// GMOCK_INTERNAL_GET_VALUE_CALLTYPE needed more expansions to work on windows +// maybe they can be simplified somehow. +#define GMOCK_INTERNAL_IS_CALLTYPE(_arg) \ + GMOCK_INTERNAL_IS_CALLTYPE_I( \ + GMOCK_PP_CAT(GMOCK_INTERNAL_IS_CALLTYPE_HELPER_, _arg)) +#define GMOCK_INTERNAL_IS_CALLTYPE_I(_arg) GMOCK_PP_IS_ENCLOSED_PARENS(_arg) + +#define GMOCK_INTERNAL_GET_VALUE_CALLTYPE(_arg) \ + GMOCK_INTERNAL_GET_VALUE_CALLTYPE_I( \ + GMOCK_PP_CAT(GMOCK_INTERNAL_IS_CALLTYPE_HELPER_, _arg)) +#define GMOCK_INTERNAL_GET_VALUE_CALLTYPE_I(_arg) \ + GMOCK_PP_CAT(GMOCK_PP_IDENTITY, _arg) + +#define GMOCK_INTERNAL_IS_CALLTYPE_HELPER_Calltype + +#define GMOCK_INTERNAL_SIGNATURE(_Ret, _Args) \ + GMOCK_PP_IF(GMOCK_PP_IS_BEGIN_PARENS(_Ret), GMOCK_PP_REMOVE_PARENS, \ + GMOCK_PP_IDENTITY) \ + (_Ret)(GMOCK_PP_FOR_EACH(GMOCK_INTERNAL_GET_TYPE, _, _Args)) + +#define GMOCK_INTERNAL_GET_TYPE(_i, _, _elem) \ + GMOCK_PP_COMMA_IF(_i) \ + GMOCK_PP_IF(GMOCK_PP_IS_BEGIN_PARENS(_elem), GMOCK_PP_REMOVE_PARENS, \ + GMOCK_PP_IDENTITY) \ + (_elem) + +#define GMOCK_INTERNAL_PARAMETER(_i, _Signature, _) \ + GMOCK_PP_COMMA_IF(_i) \ + GMOCK_INTERNAL_ARG_O(typename, GMOCK_PP_INC(_i), \ + GMOCK_PP_REMOVE_PARENS(_Signature)) \ + gmock_a##_i + +#define GMOCK_INTERNAL_FORWARD_ARG(_i, _Signature, _) \ + GMOCK_PP_COMMA_IF(_i) \ + ::std::forward( \ + gmock_a##_i) + +#define GMOCK_INTERNAL_MATCHER_PARAMETER(_i, _Signature, _) \ + GMOCK_PP_COMMA_IF(_i) \ + GMOCK_INTERNAL_MATCHER_O(typename, GMOCK_PP_INC(_i), \ + GMOCK_PP_REMOVE_PARENS(_Signature)) \ + gmock_a##_i + +#define GMOCK_INTERNAL_MATCHER_ARGUMENT(_i, _1, _2) \ + GMOCK_PP_COMMA_IF(_i) \ + gmock_a##_i + +#define GMOCK_INTERNAL_A_MATCHER_ARGUMENT(_i, _Signature, _) \ + GMOCK_PP_COMMA_IF(_i) \ + ::testing::A() + +#define GMOCK_INTERNAL_ARG_O(_tn, _i, ...) GMOCK_ARG_(_tn, _i, __VA_ARGS__) + +#define GMOCK_INTERNAL_MATCHER_O(_tn, _i, ...) \ + GMOCK_MATCHER_(_tn, _i, __VA_ARGS__) + +#endif // THIRD_PARTY_GOOGLETEST_GOOGLEMOCK_INCLUDE_GMOCK_INTERNAL_GMOCK_FUNCTION_MOCKER_H_ diff --git a/googlemock/include/gmock/gmock-generated-actions.h b/googlemock/include/gmock/gmock-generated-actions.h new file mode 100644 index 00000000..981af78f --- /dev/null +++ b/googlemock/include/gmock/gmock-generated-actions.h @@ -0,0 +1,1884 @@ +// This file was GENERATED by command: +// pump.py gmock-generated-actions.h.pump +// DO NOT EDIT BY HAND!!! + +// Copyright 2007, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + +// Google Mock - a framework for writing C++ mock classes. +// +// This file implements some commonly used variadic actions. + +// GOOGLETEST_CM0002 DO NOT DELETE + +#ifndef GMOCK_INCLUDE_GMOCK_GMOCK_GENERATED_ACTIONS_H_ +#define GMOCK_INCLUDE_GMOCK_GMOCK_GENERATED_ACTIONS_H_ + +#include +#include + +#include "gmock/gmock-actions.h" +#include "gmock/internal/gmock-port.h" + +namespace testing { +namespace internal { + +// A macro from the ACTION* family (defined later in this file) +// defines an action that can be used in a mock function. Typically, +// these actions only care about a subset of the arguments of the mock +// function. For example, if such an action only uses the second +// argument, it can be used in any mock function that takes >= 2 +// arguments where the type of the second argument is compatible. +// +// Therefore, the action implementation must be prepared to take more +// arguments than it needs. The ExcessiveArg type is used to +// represent those excessive arguments. In order to keep the compiler +// error messages tractable, we define it in the testing namespace +// instead of testing::internal. However, this is an INTERNAL TYPE +// and subject to change without notice, so a user MUST NOT USE THIS +// TYPE DIRECTLY. +struct ExcessiveArg {}; + +// A helper class needed for implementing the ACTION* macros. +template +class ActionHelper { + public: + static Result Perform(Impl* impl, const ::std::tuple<>& args) { + return impl->template gmock_PerformImpl<>(args, ExcessiveArg(), + ExcessiveArg(), ExcessiveArg(), ExcessiveArg(), ExcessiveArg(), + ExcessiveArg(), ExcessiveArg(), ExcessiveArg(), ExcessiveArg(), + ExcessiveArg()); + } + + template + static Result Perform(Impl* impl, const ::std::tuple& args) { + return impl->template gmock_PerformImpl(args, std::get<0>(args), + ExcessiveArg(), ExcessiveArg(), ExcessiveArg(), ExcessiveArg(), + ExcessiveArg(), ExcessiveArg(), ExcessiveArg(), ExcessiveArg(), + ExcessiveArg()); + } + + template + static Result Perform(Impl* impl, const ::std::tuple& args) { + return impl->template gmock_PerformImpl(args, std::get<0>(args), + std::get<1>(args), ExcessiveArg(), ExcessiveArg(), ExcessiveArg(), + ExcessiveArg(), ExcessiveArg(), ExcessiveArg(), ExcessiveArg(), + ExcessiveArg()); + } + + template + static Result Perform(Impl* impl, const ::std::tuple& args) { + return impl->template gmock_PerformImpl(args, + std::get<0>(args), std::get<1>(args), std::get<2>(args), + ExcessiveArg(), ExcessiveArg(), ExcessiveArg(), ExcessiveArg(), + ExcessiveArg(), ExcessiveArg(), ExcessiveArg()); + } + + template + static Result Perform(Impl* impl, const ::std::tuple& args) { + return impl->template gmock_PerformImpl(args, + std::get<0>(args), std::get<1>(args), std::get<2>(args), + std::get<3>(args), ExcessiveArg(), ExcessiveArg(), ExcessiveArg(), + ExcessiveArg(), ExcessiveArg(), ExcessiveArg()); + } + + template + static Result Perform(Impl* impl, const ::std::tuple& args) { + return impl->template gmock_PerformImpl(args, + std::get<0>(args), std::get<1>(args), std::get<2>(args), + std::get<3>(args), std::get<4>(args), ExcessiveArg(), ExcessiveArg(), + ExcessiveArg(), ExcessiveArg(), ExcessiveArg()); + } + + template + static Result Perform(Impl* impl, const ::std::tuple& args) { + return impl->template gmock_PerformImpl(args, + std::get<0>(args), std::get<1>(args), std::get<2>(args), + std::get<3>(args), std::get<4>(args), std::get<5>(args), + ExcessiveArg(), ExcessiveArg(), ExcessiveArg(), ExcessiveArg()); + } + + template + static Result Perform(Impl* impl, const ::std::tuple& args) { + return impl->template gmock_PerformImpl(args, + std::get<0>(args), std::get<1>(args), std::get<2>(args), + std::get<3>(args), std::get<4>(args), std::get<5>(args), + std::get<6>(args), ExcessiveArg(), ExcessiveArg(), ExcessiveArg()); + } + + template + static Result Perform(Impl* impl, const ::std::tuple& args) { + return impl->template gmock_PerformImpl(args, std::get<0>(args), std::get<1>(args), std::get<2>(args), + std::get<3>(args), std::get<4>(args), std::get<5>(args), + std::get<6>(args), std::get<7>(args), ExcessiveArg(), ExcessiveArg()); + } + + template + static Result Perform(Impl* impl, const ::std::tuple& args) { + return impl->template gmock_PerformImpl(args, std::get<0>(args), std::get<1>(args), std::get<2>(args), + std::get<3>(args), std::get<4>(args), std::get<5>(args), + std::get<6>(args), std::get<7>(args), std::get<8>(args), + ExcessiveArg()); + } + + template + static Result Perform(Impl* impl, const ::std::tuple& args) { + return impl->template gmock_PerformImpl(args, std::get<0>(args), std::get<1>(args), std::get<2>(args), + std::get<3>(args), std::get<4>(args), std::get<5>(args), + std::get<6>(args), std::get<7>(args), std::get<8>(args), + std::get<9>(args)); + } +}; + +} // namespace internal +} // namespace testing + +// The ACTION* family of macros can be used in a namespace scope to +// define custom actions easily. The syntax: +// +// ACTION(name) { statements; } +// +// will define an action with the given name that executes the +// statements. The value returned by the statements will be used as +// the return value of the action. Inside the statements, you can +// refer to the K-th (0-based) argument of the mock function by +// 'argK', and refer to its type by 'argK_type'. For example: +// +// ACTION(IncrementArg1) { +// arg1_type temp = arg1; +// return ++(*temp); +// } +// +// allows you to write +// +// ...WillOnce(IncrementArg1()); +// +// You can also refer to the entire argument tuple and its type by +// 'args' and 'args_type', and refer to the mock function type and its +// return type by 'function_type' and 'return_type'. +// +// Note that you don't need to specify the types of the mock function +// arguments. However rest assured that your code is still type-safe: +// you'll get a compiler error if *arg1 doesn't support the ++ +// operator, or if the type of ++(*arg1) isn't compatible with the +// mock function's return type, for example. +// +// Sometimes you'll want to parameterize the action. For that you can use +// another macro: +// +// ACTION_P(name, param_name) { statements; } +// +// For example: +// +// ACTION_P(Add, n) { return arg0 + n; } +// +// will allow you to write: +// +// ...WillOnce(Add(5)); +// +// Note that you don't need to provide the type of the parameter +// either. If you need to reference the type of a parameter named +// 'foo', you can write 'foo_type'. For example, in the body of +// ACTION_P(Add, n) above, you can write 'n_type' to refer to the type +// of 'n'. +// +// We also provide ACTION_P2, ACTION_P3, ..., up to ACTION_P10 to support +// multi-parameter actions. +// +// For the purpose of typing, you can view +// +// ACTION_Pk(Foo, p1, ..., pk) { ... } +// +// as shorthand for +// +// template +// FooActionPk Foo(p1_type p1, ..., pk_type pk) { ... } +// +// In particular, you can provide the template type arguments +// explicitly when invoking Foo(), as in Foo(5, false); +// although usually you can rely on the compiler to infer the types +// for you automatically. You can assign the result of expression +// Foo(p1, ..., pk) to a variable of type FooActionPk. This can be useful when composing actions. +// +// You can also overload actions with different numbers of parameters: +// +// ACTION_P(Plus, a) { ... } +// ACTION_P2(Plus, a, b) { ... } +// +// While it's tempting to always use the ACTION* macros when defining +// a new action, you should also consider implementing ActionInterface +// or using MakePolymorphicAction() instead, especially if you need to +// use the action a lot. While these approaches require more work, +// they give you more control on the types of the mock function +// arguments and the action parameters, which in general leads to +// better compiler error messages that pay off in the long run. They +// also allow overloading actions based on parameter types (as opposed +// to just based on the number of parameters). +// +// CAVEAT: +// +// ACTION*() can only be used in a namespace scope as templates cannot be +// declared inside of a local class. +// Users can, however, define any local functors (e.g. a lambda) that +// can be used as actions. +// +// MORE INFORMATION: +// +// To learn more about using these macros, please search for 'ACTION' on +// https://github.com/google/googletest/blob/master/googlemock/docs/cook_book.md + +// An internal macro needed for implementing ACTION*(). +#define GMOCK_ACTION_ARG_TYPES_AND_NAMES_UNUSED_\ + const args_type& args GTEST_ATTRIBUTE_UNUSED_, \ + const arg0_type& arg0 GTEST_ATTRIBUTE_UNUSED_, \ + const arg1_type& arg1 GTEST_ATTRIBUTE_UNUSED_, \ + const arg2_type& arg2 GTEST_ATTRIBUTE_UNUSED_, \ + const arg3_type& arg3 GTEST_ATTRIBUTE_UNUSED_, \ + const arg4_type& arg4 GTEST_ATTRIBUTE_UNUSED_, \ + const arg5_type& arg5 GTEST_ATTRIBUTE_UNUSED_, \ + const arg6_type& arg6 GTEST_ATTRIBUTE_UNUSED_, \ + const arg7_type& arg7 GTEST_ATTRIBUTE_UNUSED_, \ + const arg8_type& arg8 GTEST_ATTRIBUTE_UNUSED_, \ + const arg9_type& arg9 GTEST_ATTRIBUTE_UNUSED_ + +// Sometimes you want to give an action explicit template parameters +// that cannot be inferred from its value parameters. ACTION() and +// ACTION_P*() don't support that. ACTION_TEMPLATE() remedies that +// and can be viewed as an extension to ACTION() and ACTION_P*(). +// +// The syntax: +// +// ACTION_TEMPLATE(ActionName, +// HAS_m_TEMPLATE_PARAMS(kind1, name1, ..., kind_m, name_m), +// AND_n_VALUE_PARAMS(p1, ..., p_n)) { statements; } +// +// defines an action template that takes m explicit template +// parameters and n value parameters. name_i is the name of the i-th +// template parameter, and kind_i specifies whether it's a typename, +// an integral constant, or a template. p_i is the name of the i-th +// value parameter. +// +// Example: +// +// // DuplicateArg(output) converts the k-th argument of the mock +// // function to type T and copies it to *output. +// ACTION_TEMPLATE(DuplicateArg, +// HAS_2_TEMPLATE_PARAMS(int, k, typename, T), +// AND_1_VALUE_PARAMS(output)) { +// *output = T(::std::get(args)); +// } +// ... +// int n; +// EXPECT_CALL(mock, Foo(_, _)) +// .WillOnce(DuplicateArg<1, unsigned char>(&n)); +// +// To create an instance of an action template, write: +// +// ActionName(v1, ..., v_n) +// +// where the ts are the template arguments and the vs are the value +// arguments. The value argument types are inferred by the compiler. +// If you want to explicitly specify the value argument types, you can +// provide additional template arguments: +// +// ActionName(v1, ..., v_n) +// +// where u_i is the desired type of v_i. +// +// ACTION_TEMPLATE and ACTION/ACTION_P* can be overloaded on the +// number of value parameters, but not on the number of template +// parameters. Without the restriction, the meaning of the following +// is unclear: +// +// OverloadedAction(x); +// +// Are we using a single-template-parameter action where 'bool' refers +// to the type of x, or are we using a two-template-parameter action +// where the compiler is asked to infer the type of x? +// +// Implementation notes: +// +// GMOCK_INTERNAL_*_HAS_m_TEMPLATE_PARAMS and +// GMOCK_INTERNAL_*_AND_n_VALUE_PARAMS are internal macros for +// implementing ACTION_TEMPLATE. The main trick we use is to create +// new macro invocations when expanding a macro. For example, we have +// +// #define ACTION_TEMPLATE(name, template_params, value_params) +// ... GMOCK_INTERNAL_DECL_##template_params ... +// +// which causes ACTION_TEMPLATE(..., HAS_1_TEMPLATE_PARAMS(typename, T), ...) +// to expand to +// +// ... GMOCK_INTERNAL_DECL_HAS_1_TEMPLATE_PARAMS(typename, T) ... +// +// Since GMOCK_INTERNAL_DECL_HAS_1_TEMPLATE_PARAMS is a macro, the +// preprocessor will continue to expand it to +// +// ... typename T ... +// +// This technique conforms to the C++ standard and is portable. It +// allows us to implement action templates using O(N) code, where N is +// the maximum number of template/value parameters supported. Without +// using it, we'd have to devote O(N^2) amount of code to implement all +// combinations of m and n. + +// Declares the template parameters. +#define GMOCK_INTERNAL_DECL_HAS_1_TEMPLATE_PARAMS(kind0, name0) kind0 name0 +#define GMOCK_INTERNAL_DECL_HAS_2_TEMPLATE_PARAMS(kind0, name0, kind1, \ + name1) kind0 name0, kind1 name1 +#define GMOCK_INTERNAL_DECL_HAS_3_TEMPLATE_PARAMS(kind0, name0, kind1, name1, \ + kind2, name2) kind0 name0, kind1 name1, kind2 name2 +#define GMOCK_INTERNAL_DECL_HAS_4_TEMPLATE_PARAMS(kind0, name0, kind1, name1, \ + kind2, name2, kind3, name3) kind0 name0, kind1 name1, kind2 name2, \ + kind3 name3 +#define GMOCK_INTERNAL_DECL_HAS_5_TEMPLATE_PARAMS(kind0, name0, kind1, name1, \ + kind2, name2, kind3, name3, kind4, name4) kind0 name0, kind1 name1, \ + kind2 name2, kind3 name3, kind4 name4 +#define GMOCK_INTERNAL_DECL_HAS_6_TEMPLATE_PARAMS(kind0, name0, kind1, name1, \ + kind2, name2, kind3, name3, kind4, name4, kind5, name5) kind0 name0, \ + kind1 name1, kind2 name2, kind3 name3, kind4 name4, kind5 name5 +#define GMOCK_INTERNAL_DECL_HAS_7_TEMPLATE_PARAMS(kind0, name0, kind1, name1, \ + kind2, name2, kind3, name3, kind4, name4, kind5, name5, kind6, \ + name6) kind0 name0, kind1 name1, kind2 name2, kind3 name3, kind4 name4, \ + kind5 name5, kind6 name6 +#define GMOCK_INTERNAL_DECL_HAS_8_TEMPLATE_PARAMS(kind0, name0, kind1, name1, \ + kind2, name2, kind3, name3, kind4, name4, kind5, name5, kind6, name6, \ + kind7, name7) kind0 name0, kind1 name1, kind2 name2, kind3 name3, \ + kind4 name4, kind5 name5, kind6 name6, kind7 name7 +#define GMOCK_INTERNAL_DECL_HAS_9_TEMPLATE_PARAMS(kind0, name0, kind1, name1, \ + kind2, name2, kind3, name3, kind4, name4, kind5, name5, kind6, name6, \ + kind7, name7, kind8, name8) kind0 name0, kind1 name1, kind2 name2, \ + kind3 name3, kind4 name4, kind5 name5, kind6 name6, kind7 name7, \ + kind8 name8 +#define GMOCK_INTERNAL_DECL_HAS_10_TEMPLATE_PARAMS(kind0, name0, kind1, \ + name1, kind2, name2, kind3, name3, kind4, name4, kind5, name5, kind6, \ + name6, kind7, name7, kind8, name8, kind9, name9) kind0 name0, \ + kind1 name1, kind2 name2, kind3 name3, kind4 name4, kind5 name5, \ + kind6 name6, kind7 name7, kind8 name8, kind9 name9 + +// Lists the template parameters. +#define GMOCK_INTERNAL_LIST_HAS_1_TEMPLATE_PARAMS(kind0, name0) name0 +#define GMOCK_INTERNAL_LIST_HAS_2_TEMPLATE_PARAMS(kind0, name0, kind1, \ + name1) name0, name1 +#define GMOCK_INTERNAL_LIST_HAS_3_TEMPLATE_PARAMS(kind0, name0, kind1, name1, \ + kind2, name2) name0, name1, name2 +#define GMOCK_INTERNAL_LIST_HAS_4_TEMPLATE_PARAMS(kind0, name0, kind1, name1, \ + kind2, name2, kind3, name3) name0, name1, name2, name3 +#define GMOCK_INTERNAL_LIST_HAS_5_TEMPLATE_PARAMS(kind0, name0, kind1, name1, \ + kind2, name2, kind3, name3, kind4, name4) name0, name1, name2, name3, \ + name4 +#define GMOCK_INTERNAL_LIST_HAS_6_TEMPLATE_PARAMS(kind0, name0, kind1, name1, \ + kind2, name2, kind3, name3, kind4, name4, kind5, name5) name0, name1, \ + name2, name3, name4, name5 +#define GMOCK_INTERNAL_LIST_HAS_7_TEMPLATE_PARAMS(kind0, name0, kind1, name1, \ + kind2, name2, kind3, name3, kind4, name4, kind5, name5, kind6, \ + name6) name0, name1, name2, name3, name4, name5, name6 +#define GMOCK_INTERNAL_LIST_HAS_8_TEMPLATE_PARAMS(kind0, name0, kind1, name1, \ + kind2, name2, kind3, name3, kind4, name4, kind5, name5, kind6, name6, \ + kind7, name7) name0, name1, name2, name3, name4, name5, name6, name7 +#define GMOCK_INTERNAL_LIST_HAS_9_TEMPLATE_PARAMS(kind0, name0, kind1, name1, \ + kind2, name2, kind3, name3, kind4, name4, kind5, name5, kind6, name6, \ + kind7, name7, kind8, name8) name0, name1, name2, name3, name4, name5, \ + name6, name7, name8 +#define GMOCK_INTERNAL_LIST_HAS_10_TEMPLATE_PARAMS(kind0, name0, kind1, \ + name1, kind2, name2, kind3, name3, kind4, name4, kind5, name5, kind6, \ + name6, kind7, name7, kind8, name8, kind9, name9) name0, name1, name2, \ + name3, name4, name5, name6, name7, name8, name9 + +// Declares the types of value parameters. +#define GMOCK_INTERNAL_DECL_TYPE_AND_0_VALUE_PARAMS() +#define GMOCK_INTERNAL_DECL_TYPE_AND_1_VALUE_PARAMS(p0) , typename p0##_type +#define GMOCK_INTERNAL_DECL_TYPE_AND_2_VALUE_PARAMS(p0, p1) , \ + typename p0##_type, typename p1##_type +#define GMOCK_INTERNAL_DECL_TYPE_AND_3_VALUE_PARAMS(p0, p1, p2) , \ + typename p0##_type, typename p1##_type, typename p2##_type +#define GMOCK_INTERNAL_DECL_TYPE_AND_4_VALUE_PARAMS(p0, p1, p2, p3) , \ + typename p0##_type, typename p1##_type, typename p2##_type, \ + typename p3##_type +#define GMOCK_INTERNAL_DECL_TYPE_AND_5_VALUE_PARAMS(p0, p1, p2, p3, p4) , \ + typename p0##_type, typename p1##_type, typename p2##_type, \ + typename p3##_type, typename p4##_type +#define GMOCK_INTERNAL_DECL_TYPE_AND_6_VALUE_PARAMS(p0, p1, p2, p3, p4, p5) , \ + typename p0##_type, typename p1##_type, typename p2##_type, \ + typename p3##_type, typename p4##_type, typename p5##_type +#define GMOCK_INTERNAL_DECL_TYPE_AND_7_VALUE_PARAMS(p0, p1, p2, p3, p4, p5, \ + p6) , typename p0##_type, typename p1##_type, typename p2##_type, \ + typename p3##_type, typename p4##_type, typename p5##_type, \ + typename p6##_type +#define GMOCK_INTERNAL_DECL_TYPE_AND_8_VALUE_PARAMS(p0, p1, p2, p3, p4, p5, \ + p6, p7) , typename p0##_type, typename p1##_type, typename p2##_type, \ + typename p3##_type, typename p4##_type, typename p5##_type, \ + typename p6##_type, typename p7##_type +#define GMOCK_INTERNAL_DECL_TYPE_AND_9_VALUE_PARAMS(p0, p1, p2, p3, p4, p5, \ + p6, p7, p8) , typename p0##_type, typename p1##_type, typename p2##_type, \ + typename p3##_type, typename p4##_type, typename p5##_type, \ + typename p6##_type, typename p7##_type, typename p8##_type +#define GMOCK_INTERNAL_DECL_TYPE_AND_10_VALUE_PARAMS(p0, p1, p2, p3, p4, p5, \ + p6, p7, p8, p9) , typename p0##_type, typename p1##_type, \ + typename p2##_type, typename p3##_type, typename p4##_type, \ + typename p5##_type, typename p6##_type, typename p7##_type, \ + typename p8##_type, typename p9##_type + +// Initializes the value parameters. +#define GMOCK_INTERNAL_INIT_AND_0_VALUE_PARAMS()\ + () +#define GMOCK_INTERNAL_INIT_AND_1_VALUE_PARAMS(p0)\ + (p0##_type gmock_p0) : p0(::std::move(gmock_p0)) +#define GMOCK_INTERNAL_INIT_AND_2_VALUE_PARAMS(p0, p1)\ + (p0##_type gmock_p0, p1##_type gmock_p1) : p0(::std::move(gmock_p0)), \ + p1(::std::move(gmock_p1)) +#define GMOCK_INTERNAL_INIT_AND_3_VALUE_PARAMS(p0, p1, p2)\ + (p0##_type gmock_p0, p1##_type gmock_p1, \ + p2##_type gmock_p2) : p0(::std::move(gmock_p0)), \ + p1(::std::move(gmock_p1)), p2(::std::move(gmock_p2)) +#define GMOCK_INTERNAL_INIT_AND_4_VALUE_PARAMS(p0, p1, p2, p3)\ + (p0##_type gmock_p0, p1##_type gmock_p1, p2##_type gmock_p2, \ + p3##_type gmock_p3) : p0(::std::move(gmock_p0)), \ + p1(::std::move(gmock_p1)), p2(::std::move(gmock_p2)), \ + p3(::std::move(gmock_p3)) +#define GMOCK_INTERNAL_INIT_AND_5_VALUE_PARAMS(p0, p1, p2, p3, p4)\ + (p0##_type gmock_p0, p1##_type gmock_p1, p2##_type gmock_p2, \ + p3##_type gmock_p3, p4##_type gmock_p4) : p0(::std::move(gmock_p0)), \ + p1(::std::move(gmock_p1)), p2(::std::move(gmock_p2)), \ + p3(::std::move(gmock_p3)), p4(::std::move(gmock_p4)) +#define GMOCK_INTERNAL_INIT_AND_6_VALUE_PARAMS(p0, p1, p2, p3, p4, p5)\ + (p0##_type gmock_p0, p1##_type gmock_p1, p2##_type gmock_p2, \ + p3##_type gmock_p3, p4##_type gmock_p4, \ + p5##_type gmock_p5) : p0(::std::move(gmock_p0)), \ + p1(::std::move(gmock_p1)), p2(::std::move(gmock_p2)), \ + p3(::std::move(gmock_p3)), p4(::std::move(gmock_p4)), \ + p5(::std::move(gmock_p5)) +#define GMOCK_INTERNAL_INIT_AND_7_VALUE_PARAMS(p0, p1, p2, p3, p4, p5, p6)\ + (p0##_type gmock_p0, p1##_type gmock_p1, p2##_type gmock_p2, \ + p3##_type gmock_p3, p4##_type gmock_p4, p5##_type gmock_p5, \ + p6##_type gmock_p6) : p0(::std::move(gmock_p0)), \ + p1(::std::move(gmock_p1)), p2(::std::move(gmock_p2)), \ + p3(::std::move(gmock_p3)), p4(::std::move(gmock_p4)), \ + p5(::std::move(gmock_p5)), p6(::std::move(gmock_p6)) +#define GMOCK_INTERNAL_INIT_AND_8_VALUE_PARAMS(p0, p1, p2, p3, p4, p5, p6, p7)\ + (p0##_type gmock_p0, p1##_type gmock_p1, p2##_type gmock_p2, \ + p3##_type gmock_p3, p4##_type gmock_p4, p5##_type gmock_p5, \ + p6##_type gmock_p6, p7##_type gmock_p7) : p0(::std::move(gmock_p0)), \ + p1(::std::move(gmock_p1)), p2(::std::move(gmock_p2)), \ + p3(::std::move(gmock_p3)), p4(::std::move(gmock_p4)), \ + p5(::std::move(gmock_p5)), p6(::std::move(gmock_p6)), \ + p7(::std::move(gmock_p7)) +#define GMOCK_INTERNAL_INIT_AND_9_VALUE_PARAMS(p0, p1, p2, p3, p4, p5, p6, \ + p7, p8)\ + (p0##_type gmock_p0, p1##_type gmock_p1, p2##_type gmock_p2, \ + p3##_type gmock_p3, p4##_type gmock_p4, p5##_type gmock_p5, \ + p6##_type gmock_p6, p7##_type gmock_p7, \ + p8##_type gmock_p8) : p0(::std::move(gmock_p0)), \ + p1(::std::move(gmock_p1)), p2(::std::move(gmock_p2)), \ + p3(::std::move(gmock_p3)), p4(::std::move(gmock_p4)), \ + p5(::std::move(gmock_p5)), p6(::std::move(gmock_p6)), \ + p7(::std::move(gmock_p7)), p8(::std::move(gmock_p8)) +#define GMOCK_INTERNAL_INIT_AND_10_VALUE_PARAMS(p0, p1, p2, p3, p4, p5, p6, \ + p7, p8, p9)\ + (p0##_type gmock_p0, p1##_type gmock_p1, p2##_type gmock_p2, \ + p3##_type gmock_p3, p4##_type gmock_p4, p5##_type gmock_p5, \ + p6##_type gmock_p6, p7##_type gmock_p7, p8##_type gmock_p8, \ + p9##_type gmock_p9) : p0(::std::move(gmock_p0)), \ + p1(::std::move(gmock_p1)), p2(::std::move(gmock_p2)), \ + p3(::std::move(gmock_p3)), p4(::std::move(gmock_p4)), \ + p5(::std::move(gmock_p5)), p6(::std::move(gmock_p6)), \ + p7(::std::move(gmock_p7)), p8(::std::move(gmock_p8)), \ + p9(::std::move(gmock_p9)) + +// Declares the fields for storing the value parameters. +#define GMOCK_INTERNAL_DEFN_AND_0_VALUE_PARAMS() +#define GMOCK_INTERNAL_DEFN_AND_1_VALUE_PARAMS(p0) p0##_type p0; +#define GMOCK_INTERNAL_DEFN_AND_2_VALUE_PARAMS(p0, p1) p0##_type p0; \ + p1##_type p1; +#define GMOCK_INTERNAL_DEFN_AND_3_VALUE_PARAMS(p0, p1, p2) p0##_type p0; \ + p1##_type p1; p2##_type p2; +#define GMOCK_INTERNAL_DEFN_AND_4_VALUE_PARAMS(p0, p1, p2, p3) p0##_type p0; \ + p1##_type p1; p2##_type p2; p3##_type p3; +#define GMOCK_INTERNAL_DEFN_AND_5_VALUE_PARAMS(p0, p1, p2, p3, \ + p4) p0##_type p0; p1##_type p1; p2##_type p2; p3##_type p3; p4##_type p4; +#define GMOCK_INTERNAL_DEFN_AND_6_VALUE_PARAMS(p0, p1, p2, p3, p4, \ + p5) p0##_type p0; p1##_type p1; p2##_type p2; p3##_type p3; p4##_type p4; \ + p5##_type p5; +#define GMOCK_INTERNAL_DEFN_AND_7_VALUE_PARAMS(p0, p1, p2, p3, p4, p5, \ + p6) p0##_type p0; p1##_type p1; p2##_type p2; p3##_type p3; p4##_type p4; \ + p5##_type p5; p6##_type p6; +#define GMOCK_INTERNAL_DEFN_AND_8_VALUE_PARAMS(p0, p1, p2, p3, p4, p5, p6, \ + p7) p0##_type p0; p1##_type p1; p2##_type p2; p3##_type p3; p4##_type p4; \ + p5##_type p5; p6##_type p6; p7##_type p7; +#define GMOCK_INTERNAL_DEFN_AND_9_VALUE_PARAMS(p0, p1, p2, p3, p4, p5, p6, \ + p7, p8) p0##_type p0; p1##_type p1; p2##_type p2; p3##_type p3; \ + p4##_type p4; p5##_type p5; p6##_type p6; p7##_type p7; p8##_type p8; +#define GMOCK_INTERNAL_DEFN_AND_10_VALUE_PARAMS(p0, p1, p2, p3, p4, p5, p6, \ + p7, p8, p9) p0##_type p0; p1##_type p1; p2##_type p2; p3##_type p3; \ + p4##_type p4; p5##_type p5; p6##_type p6; p7##_type p7; p8##_type p8; \ + p9##_type p9; + +// Lists the value parameters. +#define GMOCK_INTERNAL_LIST_AND_0_VALUE_PARAMS() +#define GMOCK_INTERNAL_LIST_AND_1_VALUE_PARAMS(p0) p0 +#define GMOCK_INTERNAL_LIST_AND_2_VALUE_PARAMS(p0, p1) p0, p1 +#define GMOCK_INTERNAL_LIST_AND_3_VALUE_PARAMS(p0, p1, p2) p0, p1, p2 +#define GMOCK_INTERNAL_LIST_AND_4_VALUE_PARAMS(p0, p1, p2, p3) p0, p1, p2, p3 +#define GMOCK_INTERNAL_LIST_AND_5_VALUE_PARAMS(p0, p1, p2, p3, p4) p0, p1, \ + p2, p3, p4 +#define GMOCK_INTERNAL_LIST_AND_6_VALUE_PARAMS(p0, p1, p2, p3, p4, p5) p0, \ + p1, p2, p3, p4, p5 +#define GMOCK_INTERNAL_LIST_AND_7_VALUE_PARAMS(p0, p1, p2, p3, p4, p5, \ + p6) p0, p1, p2, p3, p4, p5, p6 +#define GMOCK_INTERNAL_LIST_AND_8_VALUE_PARAMS(p0, p1, p2, p3, p4, p5, p6, \ + p7) p0, p1, p2, p3, p4, p5, p6, p7 +#define GMOCK_INTERNAL_LIST_AND_9_VALUE_PARAMS(p0, p1, p2, p3, p4, p5, p6, \ + p7, p8) p0, p1, p2, p3, p4, p5, p6, p7, p8 +#define GMOCK_INTERNAL_LIST_AND_10_VALUE_PARAMS(p0, p1, p2, p3, p4, p5, p6, \ + p7, p8, p9) p0, p1, p2, p3, p4, p5, p6, p7, p8, p9 + +// Lists the value parameter types. +#define GMOCK_INTERNAL_LIST_TYPE_AND_0_VALUE_PARAMS() +#define GMOCK_INTERNAL_LIST_TYPE_AND_1_VALUE_PARAMS(p0) , p0##_type +#define GMOCK_INTERNAL_LIST_TYPE_AND_2_VALUE_PARAMS(p0, p1) , p0##_type, \ + p1##_type +#define GMOCK_INTERNAL_LIST_TYPE_AND_3_VALUE_PARAMS(p0, p1, p2) , p0##_type, \ + p1##_type, p2##_type +#define GMOCK_INTERNAL_LIST_TYPE_AND_4_VALUE_PARAMS(p0, p1, p2, p3) , \ + p0##_type, p1##_type, p2##_type, p3##_type +#define GMOCK_INTERNAL_LIST_TYPE_AND_5_VALUE_PARAMS(p0, p1, p2, p3, p4) , \ + p0##_type, p1##_type, p2##_type, p3##_type, p4##_type +#define GMOCK_INTERNAL_LIST_TYPE_AND_6_VALUE_PARAMS(p0, p1, p2, p3, p4, p5) , \ + p0##_type, p1##_type, p2##_type, p3##_type, p4##_type, p5##_type +#define GMOCK_INTERNAL_LIST_TYPE_AND_7_VALUE_PARAMS(p0, p1, p2, p3, p4, p5, \ + p6) , p0##_type, p1##_type, p2##_type, p3##_type, p4##_type, p5##_type, \ + p6##_type +#define GMOCK_INTERNAL_LIST_TYPE_AND_8_VALUE_PARAMS(p0, p1, p2, p3, p4, p5, \ + p6, p7) , p0##_type, p1##_type, p2##_type, p3##_type, p4##_type, \ + p5##_type, p6##_type, p7##_type +#define GMOCK_INTERNAL_LIST_TYPE_AND_9_VALUE_PARAMS(p0, p1, p2, p3, p4, p5, \ + p6, p7, p8) , p0##_type, p1##_type, p2##_type, p3##_type, p4##_type, \ + p5##_type, p6##_type, p7##_type, p8##_type +#define GMOCK_INTERNAL_LIST_TYPE_AND_10_VALUE_PARAMS(p0, p1, p2, p3, p4, p5, \ + p6, p7, p8, p9) , p0##_type, p1##_type, p2##_type, p3##_type, p4##_type, \ + p5##_type, p6##_type, p7##_type, p8##_type, p9##_type + +// Declares the value parameters. +#define GMOCK_INTERNAL_DECL_AND_0_VALUE_PARAMS() +#define GMOCK_INTERNAL_DECL_AND_1_VALUE_PARAMS(p0) p0##_type p0 +#define GMOCK_INTERNAL_DECL_AND_2_VALUE_PARAMS(p0, p1) p0##_type p0, \ + p1##_type p1 +#define GMOCK_INTERNAL_DECL_AND_3_VALUE_PARAMS(p0, p1, p2) p0##_type p0, \ + p1##_type p1, p2##_type p2 +#define GMOCK_INTERNAL_DECL_AND_4_VALUE_PARAMS(p0, p1, p2, p3) p0##_type p0, \ + p1##_type p1, p2##_type p2, p3##_type p3 +#define GMOCK_INTERNAL_DECL_AND_5_VALUE_PARAMS(p0, p1, p2, p3, \ + p4) p0##_type p0, p1##_type p1, p2##_type p2, p3##_type p3, p4##_type p4 +#define GMOCK_INTERNAL_DECL_AND_6_VALUE_PARAMS(p0, p1, p2, p3, p4, \ + p5) p0##_type p0, p1##_type p1, p2##_type p2, p3##_type p3, p4##_type p4, \ + p5##_type p5 +#define GMOCK_INTERNAL_DECL_AND_7_VALUE_PARAMS(p0, p1, p2, p3, p4, p5, \ + p6) p0##_type p0, p1##_type p1, p2##_type p2, p3##_type p3, p4##_type p4, \ + p5##_type p5, p6##_type p6 +#define GMOCK_INTERNAL_DECL_AND_8_VALUE_PARAMS(p0, p1, p2, p3, p4, p5, p6, \ + p7) p0##_type p0, p1##_type p1, p2##_type p2, p3##_type p3, p4##_type p4, \ + p5##_type p5, p6##_type p6, p7##_type p7 +#define GMOCK_INTERNAL_DECL_AND_9_VALUE_PARAMS(p0, p1, p2, p3, p4, p5, p6, \ + p7, p8) p0##_type p0, p1##_type p1, p2##_type p2, p3##_type p3, \ + p4##_type p4, p5##_type p5, p6##_type p6, p7##_type p7, p8##_type p8 +#define GMOCK_INTERNAL_DECL_AND_10_VALUE_PARAMS(p0, p1, p2, p3, p4, p5, p6, \ + p7, p8, p9) p0##_type p0, p1##_type p1, p2##_type p2, p3##_type p3, \ + p4##_type p4, p5##_type p5, p6##_type p6, p7##_type p7, p8##_type p8, \ + p9##_type p9 + +// The suffix of the class template implementing the action template. +#define GMOCK_INTERNAL_COUNT_AND_0_VALUE_PARAMS() +#define GMOCK_INTERNAL_COUNT_AND_1_VALUE_PARAMS(p0) P +#define GMOCK_INTERNAL_COUNT_AND_2_VALUE_PARAMS(p0, p1) P2 +#define GMOCK_INTERNAL_COUNT_AND_3_VALUE_PARAMS(p0, p1, p2) P3 +#define GMOCK_INTERNAL_COUNT_AND_4_VALUE_PARAMS(p0, p1, p2, p3) P4 +#define GMOCK_INTERNAL_COUNT_AND_5_VALUE_PARAMS(p0, p1, p2, p3, p4) P5 +#define GMOCK_INTERNAL_COUNT_AND_6_VALUE_PARAMS(p0, p1, p2, p3, p4, p5) P6 +#define GMOCK_INTERNAL_COUNT_AND_7_VALUE_PARAMS(p0, p1, p2, p3, p4, p5, p6) P7 +#define GMOCK_INTERNAL_COUNT_AND_8_VALUE_PARAMS(p0, p1, p2, p3, p4, p5, p6, \ + p7) P8 +#define GMOCK_INTERNAL_COUNT_AND_9_VALUE_PARAMS(p0, p1, p2, p3, p4, p5, p6, \ + p7, p8) P9 +#define GMOCK_INTERNAL_COUNT_AND_10_VALUE_PARAMS(p0, p1, p2, p3, p4, p5, p6, \ + p7, p8, p9) P10 + +// The name of the class template implementing the action template. +#define GMOCK_ACTION_CLASS_(name, value_params)\ + GTEST_CONCAT_TOKEN_(name##Action, GMOCK_INTERNAL_COUNT_##value_params) + +#define ACTION_TEMPLATE(name, template_params, value_params)\ + template \ + class GMOCK_ACTION_CLASS_(name, value_params) {\ + public:\ + explicit GMOCK_ACTION_CLASS_(name, value_params)\ + GMOCK_INTERNAL_INIT_##value_params {}\ + template \ + class gmock_Impl : public ::testing::ActionInterface {\ + public:\ + typedef F function_type;\ + typedef typename ::testing::internal::Function::Result return_type;\ + typedef typename ::testing::internal::Function::ArgumentTuple\ + args_type;\ + explicit gmock_Impl GMOCK_INTERNAL_INIT_##value_params {}\ + virtual return_type Perform(const args_type& args) {\ + return ::testing::internal::ActionHelper::\ + Perform(this, args);\ + }\ + template \ + return_type gmock_PerformImpl(const args_type& args, \ + const arg0_type& arg0, const arg1_type& arg1, \ + const arg2_type& arg2, const arg3_type& arg3, \ + const arg4_type& arg4, const arg5_type& arg5, \ + const arg6_type& arg6, const arg7_type& arg7, \ + const arg8_type& arg8, const arg9_type& arg9) const;\ + GMOCK_INTERNAL_DEFN_##value_params\ + private:\ + GTEST_DISALLOW_ASSIGN_(gmock_Impl);\ + };\ + template operator ::testing::Action() const {\ + return ::testing::Action(\ + new gmock_Impl(GMOCK_INTERNAL_LIST_##value_params));\ + }\ + GMOCK_INTERNAL_DEFN_##value_params\ + private:\ + GTEST_DISALLOW_ASSIGN_(GMOCK_ACTION_CLASS_(name, value_params));\ + };\ + template \ + inline GMOCK_ACTION_CLASS_(name, value_params)<\ + GMOCK_INTERNAL_LIST_##template_params\ + GMOCK_INTERNAL_LIST_TYPE_##value_params> name(\ + GMOCK_INTERNAL_DECL_##value_params) {\ + return GMOCK_ACTION_CLASS_(name, value_params)<\ + GMOCK_INTERNAL_LIST_##template_params\ + GMOCK_INTERNAL_LIST_TYPE_##value_params>(\ + GMOCK_INTERNAL_LIST_##value_params);\ + }\ + template \ + template \ + template \ + typename ::testing::internal::Function::Result\ + GMOCK_ACTION_CLASS_(name, value_params)<\ + GMOCK_INTERNAL_LIST_##template_params\ + GMOCK_INTERNAL_LIST_TYPE_##value_params>::gmock_Impl::\ + gmock_PerformImpl(\ + GMOCK_ACTION_ARG_TYPES_AND_NAMES_UNUSED_) const + +#define ACTION(name)\ + class name##Action {\ + public:\ + name##Action() {}\ + template \ + class gmock_Impl : public ::testing::ActionInterface {\ + public:\ + typedef F function_type;\ + typedef typename ::testing::internal::Function::Result return_type;\ + typedef typename ::testing::internal::Function::ArgumentTuple\ + args_type;\ + gmock_Impl() {}\ + virtual return_type Perform(const args_type& args) {\ + return ::testing::internal::ActionHelper::\ + Perform(this, args);\ + }\ + template \ + return_type gmock_PerformImpl(const args_type& args, \ + const arg0_type& arg0, const arg1_type& arg1, \ + const arg2_type& arg2, const arg3_type& arg3, \ + const arg4_type& arg4, const arg5_type& arg5, \ + const arg6_type& arg6, const arg7_type& arg7, \ + const arg8_type& arg8, const arg9_type& arg9) const;\ + private:\ + GTEST_DISALLOW_ASSIGN_(gmock_Impl);\ + };\ + template operator ::testing::Action() const {\ + return ::testing::Action(new gmock_Impl());\ + }\ + private:\ + GTEST_DISALLOW_ASSIGN_(name##Action);\ + };\ + inline name##Action name() {\ + return name##Action();\ + }\ + template \ + template \ + typename ::testing::internal::Function::Result\ + name##Action::gmock_Impl::gmock_PerformImpl(\ + GMOCK_ACTION_ARG_TYPES_AND_NAMES_UNUSED_) const + +#define ACTION_P(name, p0)\ + template \ + class name##ActionP {\ + public:\ + explicit name##ActionP(p0##_type gmock_p0) : \ + p0(::std::forward(gmock_p0)) {}\ + template \ + class gmock_Impl : public ::testing::ActionInterface {\ + public:\ + typedef F function_type;\ + typedef typename ::testing::internal::Function::Result return_type;\ + typedef typename ::testing::internal::Function::ArgumentTuple\ + args_type;\ + explicit gmock_Impl(p0##_type gmock_p0) : \ + p0(::std::forward(gmock_p0)) {}\ + virtual return_type Perform(const args_type& args) {\ + return ::testing::internal::ActionHelper::\ + Perform(this, args);\ + }\ + template \ + return_type gmock_PerformImpl(const args_type& args, \ + const arg0_type& arg0, const arg1_type& arg1, \ + const arg2_type& arg2, const arg3_type& arg3, \ + const arg4_type& arg4, const arg5_type& arg5, \ + const arg6_type& arg6, const arg7_type& arg7, \ + const arg8_type& arg8, const arg9_type& arg9) const;\ + p0##_type p0;\ + private:\ + GTEST_DISALLOW_ASSIGN_(gmock_Impl);\ + };\ + template operator ::testing::Action() const {\ + return ::testing::Action(new gmock_Impl(p0));\ + }\ + p0##_type p0;\ + private:\ + GTEST_DISALLOW_ASSIGN_(name##ActionP);\ + };\ + template \ + inline name##ActionP name(p0##_type p0) {\ + return name##ActionP(p0);\ + }\ + template \ + template \ + template \ + typename ::testing::internal::Function::Result\ + name##ActionP::gmock_Impl::gmock_PerformImpl(\ + GMOCK_ACTION_ARG_TYPES_AND_NAMES_UNUSED_) const + +#define ACTION_P2(name, p0, p1)\ + template \ + class name##ActionP2 {\ + public:\ + name##ActionP2(p0##_type gmock_p0, \ + p1##_type gmock_p1) : p0(::std::forward(gmock_p0)), \ + p1(::std::forward(gmock_p1)) {}\ + template \ + class gmock_Impl : public ::testing::ActionInterface {\ + public:\ + typedef F function_type;\ + typedef typename ::testing::internal::Function::Result return_type;\ + typedef typename ::testing::internal::Function::ArgumentTuple\ + args_type;\ + gmock_Impl(p0##_type gmock_p0, \ + p1##_type gmock_p1) : p0(::std::forward(gmock_p0)), \ + p1(::std::forward(gmock_p1)) {}\ + virtual return_type Perform(const args_type& args) {\ + return ::testing::internal::ActionHelper::\ + Perform(this, args);\ + }\ + template \ + return_type gmock_PerformImpl(const args_type& args, \ + const arg0_type& arg0, const arg1_type& arg1, \ + const arg2_type& arg2, const arg3_type& arg3, \ + const arg4_type& arg4, const arg5_type& arg5, \ + const arg6_type& arg6, const arg7_type& arg7, \ + const arg8_type& arg8, const arg9_type& arg9) const;\ + p0##_type p0;\ + p1##_type p1;\ + private:\ + GTEST_DISALLOW_ASSIGN_(gmock_Impl);\ + };\ + template operator ::testing::Action() const {\ + return ::testing::Action(new gmock_Impl(p0, p1));\ + }\ + p0##_type p0;\ + p1##_type p1;\ + private:\ + GTEST_DISALLOW_ASSIGN_(name##ActionP2);\ + };\ + template \ + inline name##ActionP2 name(p0##_type p0, \ + p1##_type p1) {\ + return name##ActionP2(p0, p1);\ + }\ + template \ + template \ + template \ + typename ::testing::internal::Function::Result\ + name##ActionP2::gmock_Impl::gmock_PerformImpl(\ + GMOCK_ACTION_ARG_TYPES_AND_NAMES_UNUSED_) const + +#define ACTION_P3(name, p0, p1, p2)\ + template \ + class name##ActionP3 {\ + public:\ + name##ActionP3(p0##_type gmock_p0, p1##_type gmock_p1, \ + p2##_type gmock_p2) : p0(::std::forward(gmock_p0)), \ + p1(::std::forward(gmock_p1)), \ + p2(::std::forward(gmock_p2)) {}\ + template \ + class gmock_Impl : public ::testing::ActionInterface {\ + public:\ + typedef F function_type;\ + typedef typename ::testing::internal::Function::Result return_type;\ + typedef typename ::testing::internal::Function::ArgumentTuple\ + args_type;\ + gmock_Impl(p0##_type gmock_p0, p1##_type gmock_p1, \ + p2##_type gmock_p2) : p0(::std::forward(gmock_p0)), \ + p1(::std::forward(gmock_p1)), \ + p2(::std::forward(gmock_p2)) {}\ + virtual return_type Perform(const args_type& args) {\ + return ::testing::internal::ActionHelper::\ + Perform(this, args);\ + }\ + template \ + return_type gmock_PerformImpl(const args_type& args, \ + const arg0_type& arg0, const arg1_type& arg1, \ + const arg2_type& arg2, const arg3_type& arg3, \ + const arg4_type& arg4, const arg5_type& arg5, \ + const arg6_type& arg6, const arg7_type& arg7, \ + const arg8_type& arg8, const arg9_type& arg9) const;\ + p0##_type p0;\ + p1##_type p1;\ + p2##_type p2;\ + private:\ + GTEST_DISALLOW_ASSIGN_(gmock_Impl);\ + };\ + template operator ::testing::Action() const {\ + return ::testing::Action(new gmock_Impl(p0, p1, p2));\ + }\ + p0##_type p0;\ + p1##_type p1;\ + p2##_type p2;\ + private:\ + GTEST_DISALLOW_ASSIGN_(name##ActionP3);\ + };\ + template \ + inline name##ActionP3 name(p0##_type p0, \ + p1##_type p1, p2##_type p2) {\ + return name##ActionP3(p0, p1, p2);\ + }\ + template \ + template \ + template \ + typename ::testing::internal::Function::Result\ + name##ActionP3::gmock_Impl::gmock_PerformImpl(\ + GMOCK_ACTION_ARG_TYPES_AND_NAMES_UNUSED_) const + +#define ACTION_P4(name, p0, p1, p2, p3)\ + template \ + class name##ActionP4 {\ + public:\ + name##ActionP4(p0##_type gmock_p0, p1##_type gmock_p1, \ + p2##_type gmock_p2, \ + p3##_type gmock_p3) : p0(::std::forward(gmock_p0)), \ + p1(::std::forward(gmock_p1)), \ + p2(::std::forward(gmock_p2)), \ + p3(::std::forward(gmock_p3)) {}\ + template \ + class gmock_Impl : public ::testing::ActionInterface {\ + public:\ + typedef F function_type;\ + typedef typename ::testing::internal::Function::Result return_type;\ + typedef typename ::testing::internal::Function::ArgumentTuple\ + args_type;\ + gmock_Impl(p0##_type gmock_p0, p1##_type gmock_p1, p2##_type gmock_p2, \ + p3##_type gmock_p3) : p0(::std::forward(gmock_p0)), \ + p1(::std::forward(gmock_p1)), \ + p2(::std::forward(gmock_p2)), \ + p3(::std::forward(gmock_p3)) {}\ + virtual return_type Perform(const args_type& args) {\ + return ::testing::internal::ActionHelper::\ + Perform(this, args);\ + }\ + template \ + return_type gmock_PerformImpl(const args_type& args, \ + const arg0_type& arg0, const arg1_type& arg1, \ + const arg2_type& arg2, const arg3_type& arg3, \ + const arg4_type& arg4, const arg5_type& arg5, \ + const arg6_type& arg6, const arg7_type& arg7, \ + const arg8_type& arg8, const arg9_type& arg9) const;\ + p0##_type p0;\ + p1##_type p1;\ + p2##_type p2;\ + p3##_type p3;\ + private:\ + GTEST_DISALLOW_ASSIGN_(gmock_Impl);\ + };\ + template operator ::testing::Action() const {\ + return ::testing::Action(new gmock_Impl(p0, p1, p2, p3));\ + }\ + p0##_type p0;\ + p1##_type p1;\ + p2##_type p2;\ + p3##_type p3;\ + private:\ + GTEST_DISALLOW_ASSIGN_(name##ActionP4);\ + };\ + template \ + inline name##ActionP4 name(p0##_type p0, p1##_type p1, p2##_type p2, \ + p3##_type p3) {\ + return name##ActionP4(p0, p1, \ + p2, p3);\ + }\ + template \ + template \ + template \ + typename ::testing::internal::Function::Result\ + name##ActionP4::gmock_Impl::gmock_PerformImpl(\ + GMOCK_ACTION_ARG_TYPES_AND_NAMES_UNUSED_) const + +#define ACTION_P5(name, p0, p1, p2, p3, p4)\ + template \ + class name##ActionP5 {\ + public:\ + name##ActionP5(p0##_type gmock_p0, p1##_type gmock_p1, \ + p2##_type gmock_p2, p3##_type gmock_p3, \ + p4##_type gmock_p4) : p0(::std::forward(gmock_p0)), \ + p1(::std::forward(gmock_p1)), \ + p2(::std::forward(gmock_p2)), \ + p3(::std::forward(gmock_p3)), \ + p4(::std::forward(gmock_p4)) {}\ + template \ + class gmock_Impl : public ::testing::ActionInterface {\ + public:\ + typedef F function_type;\ + typedef typename ::testing::internal::Function::Result return_type;\ + typedef typename ::testing::internal::Function::ArgumentTuple\ + args_type;\ + gmock_Impl(p0##_type gmock_p0, p1##_type gmock_p1, p2##_type gmock_p2, \ + p3##_type gmock_p3, \ + p4##_type gmock_p4) : p0(::std::forward(gmock_p0)), \ + p1(::std::forward(gmock_p1)), \ + p2(::std::forward(gmock_p2)), \ + p3(::std::forward(gmock_p3)), \ + p4(::std::forward(gmock_p4)) {}\ + virtual return_type Perform(const args_type& args) {\ + return ::testing::internal::ActionHelper::\ + Perform(this, args);\ + }\ + template \ + return_type gmock_PerformImpl(const args_type& args, \ + const arg0_type& arg0, const arg1_type& arg1, \ + const arg2_type& arg2, const arg3_type& arg3, \ + const arg4_type& arg4, const arg5_type& arg5, \ + const arg6_type& arg6, const arg7_type& arg7, \ + const arg8_type& arg8, const arg9_type& arg9) const;\ + p0##_type p0;\ + p1##_type p1;\ + p2##_type p2;\ + p3##_type p3;\ + p4##_type p4;\ + private:\ + GTEST_DISALLOW_ASSIGN_(gmock_Impl);\ + };\ + template operator ::testing::Action() const {\ + return ::testing::Action(new gmock_Impl(p0, p1, p2, p3, p4));\ + }\ + p0##_type p0;\ + p1##_type p1;\ + p2##_type p2;\ + p3##_type p3;\ + p4##_type p4;\ + private:\ + GTEST_DISALLOW_ASSIGN_(name##ActionP5);\ + };\ + template \ + inline name##ActionP5 name(p0##_type p0, p1##_type p1, p2##_type p2, p3##_type p3, \ + p4##_type p4) {\ + return name##ActionP5(p0, p1, p2, p3, p4);\ + }\ + template \ + template \ + template \ + typename ::testing::internal::Function::Result\ + name##ActionP5::gmock_Impl::gmock_PerformImpl(\ + GMOCK_ACTION_ARG_TYPES_AND_NAMES_UNUSED_) const + +#define ACTION_P6(name, p0, p1, p2, p3, p4, p5)\ + template \ + class name##ActionP6 {\ + public:\ + name##ActionP6(p0##_type gmock_p0, p1##_type gmock_p1, \ + p2##_type gmock_p2, p3##_type gmock_p3, p4##_type gmock_p4, \ + p5##_type gmock_p5) : p0(::std::forward(gmock_p0)), \ + p1(::std::forward(gmock_p1)), \ + p2(::std::forward(gmock_p2)), \ + p3(::std::forward(gmock_p3)), \ + p4(::std::forward(gmock_p4)), \ + p5(::std::forward(gmock_p5)) {}\ + template \ + class gmock_Impl : public ::testing::ActionInterface {\ + public:\ + typedef F function_type;\ + typedef typename ::testing::internal::Function::Result return_type;\ + typedef typename ::testing::internal::Function::ArgumentTuple\ + args_type;\ + gmock_Impl(p0##_type gmock_p0, p1##_type gmock_p1, p2##_type gmock_p2, \ + p3##_type gmock_p3, p4##_type gmock_p4, \ + p5##_type gmock_p5) : p0(::std::forward(gmock_p0)), \ + p1(::std::forward(gmock_p1)), \ + p2(::std::forward(gmock_p2)), \ + p3(::std::forward(gmock_p3)), \ + p4(::std::forward(gmock_p4)), \ + p5(::std::forward(gmock_p5)) {}\ + virtual return_type Perform(const args_type& args) {\ + return ::testing::internal::ActionHelper::\ + Perform(this, args);\ + }\ + template \ + return_type gmock_PerformImpl(const args_type& args, \ + const arg0_type& arg0, const arg1_type& arg1, \ + const arg2_type& arg2, const arg3_type& arg3, \ + const arg4_type& arg4, const arg5_type& arg5, \ + const arg6_type& arg6, const arg7_type& arg7, \ + const arg8_type& arg8, const arg9_type& arg9) const;\ + p0##_type p0;\ + p1##_type p1;\ + p2##_type p2;\ + p3##_type p3;\ + p4##_type p4;\ + p5##_type p5;\ + private:\ + GTEST_DISALLOW_ASSIGN_(gmock_Impl);\ + };\ + template operator ::testing::Action() const {\ + return ::testing::Action(new gmock_Impl(p0, p1, p2, p3, p4, p5));\ + }\ + p0##_type p0;\ + p1##_type p1;\ + p2##_type p2;\ + p3##_type p3;\ + p4##_type p4;\ + p5##_type p5;\ + private:\ + GTEST_DISALLOW_ASSIGN_(name##ActionP6);\ + };\ + template \ + inline name##ActionP6 name(p0##_type p0, p1##_type p1, p2##_type p2, \ + p3##_type p3, p4##_type p4, p5##_type p5) {\ + return name##ActionP6(p0, p1, p2, p3, p4, p5);\ + }\ + template \ + template \ + template \ + typename ::testing::internal::Function::Result\ + name##ActionP6::gmock_Impl::gmock_PerformImpl(\ + GMOCK_ACTION_ARG_TYPES_AND_NAMES_UNUSED_) const + +#define ACTION_P7(name, p0, p1, p2, p3, p4, p5, p6)\ + template \ + class name##ActionP7 {\ + public:\ + name##ActionP7(p0##_type gmock_p0, p1##_type gmock_p1, \ + p2##_type gmock_p2, p3##_type gmock_p3, p4##_type gmock_p4, \ + p5##_type gmock_p5, \ + p6##_type gmock_p6) : p0(::std::forward(gmock_p0)), \ + p1(::std::forward(gmock_p1)), \ + p2(::std::forward(gmock_p2)), \ + p3(::std::forward(gmock_p3)), \ + p4(::std::forward(gmock_p4)), \ + p5(::std::forward(gmock_p5)), \ + p6(::std::forward(gmock_p6)) {}\ + template \ + class gmock_Impl : public ::testing::ActionInterface {\ + public:\ + typedef F function_type;\ + typedef typename ::testing::internal::Function::Result return_type;\ + typedef typename ::testing::internal::Function::ArgumentTuple\ + args_type;\ + gmock_Impl(p0##_type gmock_p0, p1##_type gmock_p1, p2##_type gmock_p2, \ + p3##_type gmock_p3, p4##_type gmock_p4, p5##_type gmock_p5, \ + p6##_type gmock_p6) : p0(::std::forward(gmock_p0)), \ + p1(::std::forward(gmock_p1)), \ + p2(::std::forward(gmock_p2)), \ + p3(::std::forward(gmock_p3)), \ + p4(::std::forward(gmock_p4)), \ + p5(::std::forward(gmock_p5)), \ + p6(::std::forward(gmock_p6)) {}\ + virtual return_type Perform(const args_type& args) {\ + return ::testing::internal::ActionHelper::\ + Perform(this, args);\ + }\ + template \ + return_type gmock_PerformImpl(const args_type& args, \ + const arg0_type& arg0, const arg1_type& arg1, \ + const arg2_type& arg2, const arg3_type& arg3, \ + const arg4_type& arg4, const arg5_type& arg5, \ + const arg6_type& arg6, const arg7_type& arg7, \ + const arg8_type& arg8, const arg9_type& arg9) const;\ + p0##_type p0;\ + p1##_type p1;\ + p2##_type p2;\ + p3##_type p3;\ + p4##_type p4;\ + p5##_type p5;\ + p6##_type p6;\ + private:\ + GTEST_DISALLOW_ASSIGN_(gmock_Impl);\ + };\ + template operator ::testing::Action() const {\ + return ::testing::Action(new gmock_Impl(p0, p1, p2, p3, p4, p5, \ + p6));\ + }\ + p0##_type p0;\ + p1##_type p1;\ + p2##_type p2;\ + p3##_type p3;\ + p4##_type p4;\ + p5##_type p5;\ + p6##_type p6;\ + private:\ + GTEST_DISALLOW_ASSIGN_(name##ActionP7);\ + };\ + template \ + inline name##ActionP7 name(p0##_type p0, p1##_type p1, \ + p2##_type p2, p3##_type p3, p4##_type p4, p5##_type p5, \ + p6##_type p6) {\ + return name##ActionP7(p0, p1, p2, p3, p4, p5, p6);\ + }\ + template \ + template \ + template \ + typename ::testing::internal::Function::Result\ + name##ActionP7::gmock_Impl::gmock_PerformImpl(\ + GMOCK_ACTION_ARG_TYPES_AND_NAMES_UNUSED_) const + +#define ACTION_P8(name, p0, p1, p2, p3, p4, p5, p6, p7)\ + template \ + class name##ActionP8 {\ + public:\ + name##ActionP8(p0##_type gmock_p0, p1##_type gmock_p1, \ + p2##_type gmock_p2, p3##_type gmock_p3, p4##_type gmock_p4, \ + p5##_type gmock_p5, p6##_type gmock_p6, \ + p7##_type gmock_p7) : p0(::std::forward(gmock_p0)), \ + p1(::std::forward(gmock_p1)), \ + p2(::std::forward(gmock_p2)), \ + p3(::std::forward(gmock_p3)), \ + p4(::std::forward(gmock_p4)), \ + p5(::std::forward(gmock_p5)), \ + p6(::std::forward(gmock_p6)), \ + p7(::std::forward(gmock_p7)) {}\ + template \ + class gmock_Impl : public ::testing::ActionInterface {\ + public:\ + typedef F function_type;\ + typedef typename ::testing::internal::Function::Result return_type;\ + typedef typename ::testing::internal::Function::ArgumentTuple\ + args_type;\ + gmock_Impl(p0##_type gmock_p0, p1##_type gmock_p1, p2##_type gmock_p2, \ + p3##_type gmock_p3, p4##_type gmock_p4, p5##_type gmock_p5, \ + p6##_type gmock_p6, \ + p7##_type gmock_p7) : p0(::std::forward(gmock_p0)), \ + p1(::std::forward(gmock_p1)), \ + p2(::std::forward(gmock_p2)), \ + p3(::std::forward(gmock_p3)), \ + p4(::std::forward(gmock_p4)), \ + p5(::std::forward(gmock_p5)), \ + p6(::std::forward(gmock_p6)), \ + p7(::std::forward(gmock_p7)) {}\ + virtual return_type Perform(const args_type& args) {\ + return ::testing::internal::ActionHelper::\ + Perform(this, args);\ + }\ + template \ + return_type gmock_PerformImpl(const args_type& args, \ + const arg0_type& arg0, const arg1_type& arg1, \ + const arg2_type& arg2, const arg3_type& arg3, \ + const arg4_type& arg4, const arg5_type& arg5, \ + const arg6_type& arg6, const arg7_type& arg7, \ + const arg8_type& arg8, const arg9_type& arg9) const;\ + p0##_type p0;\ + p1##_type p1;\ + p2##_type p2;\ + p3##_type p3;\ + p4##_type p4;\ + p5##_type p5;\ + p6##_type p6;\ + p7##_type p7;\ + private:\ + GTEST_DISALLOW_ASSIGN_(gmock_Impl);\ + };\ + template operator ::testing::Action() const {\ + return ::testing::Action(new gmock_Impl(p0, p1, p2, p3, p4, p5, \ + p6, p7));\ + }\ + p0##_type p0;\ + p1##_type p1;\ + p2##_type p2;\ + p3##_type p3;\ + p4##_type p4;\ + p5##_type p5;\ + p6##_type p6;\ + p7##_type p7;\ + private:\ + GTEST_DISALLOW_ASSIGN_(name##ActionP8);\ + };\ + template \ + inline name##ActionP8 name(p0##_type p0, \ + p1##_type p1, p2##_type p2, p3##_type p3, p4##_type p4, p5##_type p5, \ + p6##_type p6, p7##_type p7) {\ + return name##ActionP8(p0, p1, p2, p3, p4, p5, \ + p6, p7);\ + }\ + template \ + template \ + template \ + typename ::testing::internal::Function::Result\ + name##ActionP8::gmock_Impl::gmock_PerformImpl(\ + GMOCK_ACTION_ARG_TYPES_AND_NAMES_UNUSED_) const + +#define ACTION_P9(name, p0, p1, p2, p3, p4, p5, p6, p7, p8)\ + template \ + class name##ActionP9 {\ + public:\ + name##ActionP9(p0##_type gmock_p0, p1##_type gmock_p1, \ + p2##_type gmock_p2, p3##_type gmock_p3, p4##_type gmock_p4, \ + p5##_type gmock_p5, p6##_type gmock_p6, p7##_type gmock_p7, \ + p8##_type gmock_p8) : p0(::std::forward(gmock_p0)), \ + p1(::std::forward(gmock_p1)), \ + p2(::std::forward(gmock_p2)), \ + p3(::std::forward(gmock_p3)), \ + p4(::std::forward(gmock_p4)), \ + p5(::std::forward(gmock_p5)), \ + p6(::std::forward(gmock_p6)), \ + p7(::std::forward(gmock_p7)), \ + p8(::std::forward(gmock_p8)) {}\ + template \ + class gmock_Impl : public ::testing::ActionInterface {\ + public:\ + typedef F function_type;\ + typedef typename ::testing::internal::Function::Result return_type;\ + typedef typename ::testing::internal::Function::ArgumentTuple\ + args_type;\ + gmock_Impl(p0##_type gmock_p0, p1##_type gmock_p1, p2##_type gmock_p2, \ + p3##_type gmock_p3, p4##_type gmock_p4, p5##_type gmock_p5, \ + p6##_type gmock_p6, p7##_type gmock_p7, \ + p8##_type gmock_p8) : p0(::std::forward(gmock_p0)), \ + p1(::std::forward(gmock_p1)), \ + p2(::std::forward(gmock_p2)), \ + p3(::std::forward(gmock_p3)), \ + p4(::std::forward(gmock_p4)), \ + p5(::std::forward(gmock_p5)), \ + p6(::std::forward(gmock_p6)), \ + p7(::std::forward(gmock_p7)), \ + p8(::std::forward(gmock_p8)) {}\ + virtual return_type Perform(const args_type& args) {\ + return ::testing::internal::ActionHelper::\ + Perform(this, args);\ + }\ + template \ + return_type gmock_PerformImpl(const args_type& args, \ + const arg0_type& arg0, const arg1_type& arg1, \ + const arg2_type& arg2, const arg3_type& arg3, \ + const arg4_type& arg4, const arg5_type& arg5, \ + const arg6_type& arg6, const arg7_type& arg7, \ + const arg8_type& arg8, const arg9_type& arg9) const;\ + p0##_type p0;\ + p1##_type p1;\ + p2##_type p2;\ + p3##_type p3;\ + p4##_type p4;\ + p5##_type p5;\ + p6##_type p6;\ + p7##_type p7;\ + p8##_type p8;\ + private:\ + GTEST_DISALLOW_ASSIGN_(gmock_Impl);\ + };\ + template operator ::testing::Action() const {\ + return ::testing::Action(new gmock_Impl(p0, p1, p2, p3, p4, p5, \ + p6, p7, p8));\ + }\ + p0##_type p0;\ + p1##_type p1;\ + p2##_type p2;\ + p3##_type p3;\ + p4##_type p4;\ + p5##_type p5;\ + p6##_type p6;\ + p7##_type p7;\ + p8##_type p8;\ + private:\ + GTEST_DISALLOW_ASSIGN_(name##ActionP9);\ + };\ + template \ + inline name##ActionP9 name(p0##_type p0, p1##_type p1, p2##_type p2, p3##_type p3, \ + p4##_type p4, p5##_type p5, p6##_type p6, p7##_type p7, \ + p8##_type p8) {\ + return name##ActionP9(p0, p1, p2, \ + p3, p4, p5, p6, p7, p8);\ + }\ + template \ + template \ + template \ + typename ::testing::internal::Function::Result\ + name##ActionP9::gmock_Impl::gmock_PerformImpl(\ + GMOCK_ACTION_ARG_TYPES_AND_NAMES_UNUSED_) const + +#define ACTION_P10(name, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9)\ + template \ + class name##ActionP10 {\ + public:\ + name##ActionP10(p0##_type gmock_p0, p1##_type gmock_p1, \ + p2##_type gmock_p2, p3##_type gmock_p3, p4##_type gmock_p4, \ + p5##_type gmock_p5, p6##_type gmock_p6, p7##_type gmock_p7, \ + p8##_type gmock_p8, \ + p9##_type gmock_p9) : p0(::std::forward(gmock_p0)), \ + p1(::std::forward(gmock_p1)), \ + p2(::std::forward(gmock_p2)), \ + p3(::std::forward(gmock_p3)), \ + p4(::std::forward(gmock_p4)), \ + p5(::std::forward(gmock_p5)), \ + p6(::std::forward(gmock_p6)), \ + p7(::std::forward(gmock_p7)), \ + p8(::std::forward(gmock_p8)), \ + p9(::std::forward(gmock_p9)) {}\ + template \ + class gmock_Impl : public ::testing::ActionInterface {\ + public:\ + typedef F function_type;\ + typedef typename ::testing::internal::Function::Result return_type;\ + typedef typename ::testing::internal::Function::ArgumentTuple\ + args_type;\ + gmock_Impl(p0##_type gmock_p0, p1##_type gmock_p1, p2##_type gmock_p2, \ + p3##_type gmock_p3, p4##_type gmock_p4, p5##_type gmock_p5, \ + p6##_type gmock_p6, p7##_type gmock_p7, p8##_type gmock_p8, \ + p9##_type gmock_p9) : p0(::std::forward(gmock_p0)), \ + p1(::std::forward(gmock_p1)), \ + p2(::std::forward(gmock_p2)), \ + p3(::std::forward(gmock_p3)), \ + p4(::std::forward(gmock_p4)), \ + p5(::std::forward(gmock_p5)), \ + p6(::std::forward(gmock_p6)), \ + p7(::std::forward(gmock_p7)), \ + p8(::std::forward(gmock_p8)), \ + p9(::std::forward(gmock_p9)) {}\ + virtual return_type Perform(const args_type& args) {\ + return ::testing::internal::ActionHelper::\ + Perform(this, args);\ + }\ + template \ + return_type gmock_PerformImpl(const args_type& args, \ + const arg0_type& arg0, const arg1_type& arg1, \ + const arg2_type& arg2, const arg3_type& arg3, \ + const arg4_type& arg4, const arg5_type& arg5, \ + const arg6_type& arg6, const arg7_type& arg7, \ + const arg8_type& arg8, const arg9_type& arg9) const;\ + p0##_type p0;\ + p1##_type p1;\ + p2##_type p2;\ + p3##_type p3;\ + p4##_type p4;\ + p5##_type p5;\ + p6##_type p6;\ + p7##_type p7;\ + p8##_type p8;\ + p9##_type p9;\ + private:\ + GTEST_DISALLOW_ASSIGN_(gmock_Impl);\ + };\ + template operator ::testing::Action() const {\ + return ::testing::Action(new gmock_Impl(p0, p1, p2, p3, p4, p5, \ + p6, p7, p8, p9));\ + }\ + p0##_type p0;\ + p1##_type p1;\ + p2##_type p2;\ + p3##_type p3;\ + p4##_type p4;\ + p5##_type p5;\ + p6##_type p6;\ + p7##_type p7;\ + p8##_type p8;\ + p9##_type p9;\ + private:\ + GTEST_DISALLOW_ASSIGN_(name##ActionP10);\ + };\ + template \ + inline name##ActionP10 name(p0##_type p0, p1##_type p1, p2##_type p2, p3##_type p3, \ + p4##_type p4, p5##_type p5, p6##_type p6, p7##_type p7, p8##_type p8, \ + p9##_type p9) {\ + return name##ActionP10(p0, \ + p1, p2, p3, p4, p5, p6, p7, p8, p9);\ + }\ + template \ + template \ + template \ + typename ::testing::internal::Function::Result\ + name##ActionP10::gmock_Impl::gmock_PerformImpl(\ + GMOCK_ACTION_ARG_TYPES_AND_NAMES_UNUSED_) const + +namespace testing { + + +// The ACTION*() macros trigger warning C4100 (unreferenced formal +// parameter) in MSVC with -W4. Unfortunately they cannot be fixed in +// the macro definition, as the warnings are generated when the macro +// is expanded and macro expansion cannot contain #pragma. Therefore +// we suppress them here. +#ifdef _MSC_VER +# pragma warning(push) +# pragma warning(disable:4100) +#endif + +// Various overloads for InvokeArgument(). +// +// The InvokeArgument(a1, a2, ..., a_k) action invokes the N-th +// (0-based) argument, which must be a k-ary callable, of the mock +// function, with arguments a1, a2, ..., a_k. +// +// Notes: +// +// 1. The arguments are passed by value by default. If you need to +// pass an argument by reference, wrap it inside ByRef(). For +// example, +// +// InvokeArgument<1>(5, string("Hello"), ByRef(foo)) +// +// passes 5 and string("Hello") by value, and passes foo by +// reference. +// +// 2. If the callable takes an argument by reference but ByRef() is +// not used, it will receive the reference to a copy of the value, +// instead of the original value. For example, when the 0-th +// argument of the mock function takes a const string&, the action +// +// InvokeArgument<0>(string("Hello")) +// +// makes a copy of the temporary string("Hello") object and passes a +// reference of the copy, instead of the original temporary object, +// to the callable. This makes it easy for a user to define an +// InvokeArgument action from temporary values and have it performed +// later. + +namespace internal { +namespace invoke_argument { + +// Appears in InvokeArgumentAdl's argument list to help avoid +// accidental calls to user functions of the same name. +struct AdlTag {}; + +// InvokeArgumentAdl - a helper for InvokeArgument. +// The basic overloads are provided here for generic functors. +// Overloads for other custom-callables are provided in the +// internal/custom/callback-actions.h header. + +template +R InvokeArgumentAdl(AdlTag, F f) { + return f(); +} +template +R InvokeArgumentAdl(AdlTag, F f, A1 a1) { + return f(a1); +} +template +R InvokeArgumentAdl(AdlTag, F f, A1 a1, A2 a2) { + return f(a1, a2); +} +template +R InvokeArgumentAdl(AdlTag, F f, A1 a1, A2 a2, A3 a3) { + return f(a1, a2, a3); +} +template +R InvokeArgumentAdl(AdlTag, F f, A1 a1, A2 a2, A3 a3, A4 a4) { + return f(a1, a2, a3, a4); +} +template +R InvokeArgumentAdl(AdlTag, F f, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5) { + return f(a1, a2, a3, a4, a5); +} +template +R InvokeArgumentAdl(AdlTag, F f, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6) { + return f(a1, a2, a3, a4, a5, a6); +} +template +R InvokeArgumentAdl(AdlTag, F f, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, + A7 a7) { + return f(a1, a2, a3, a4, a5, a6, a7); +} +template +R InvokeArgumentAdl(AdlTag, F f, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, + A7 a7, A8 a8) { + return f(a1, a2, a3, a4, a5, a6, a7, a8); +} +template +R InvokeArgumentAdl(AdlTag, F f, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, + A7 a7, A8 a8, A9 a9) { + return f(a1, a2, a3, a4, a5, a6, a7, a8, a9); +} +template +R InvokeArgumentAdl(AdlTag, F f, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, + A7 a7, A8 a8, A9 a9, A10 a10) { + return f(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10); +} +} // namespace invoke_argument +} // namespace internal + +ACTION_TEMPLATE(InvokeArgument, + HAS_1_TEMPLATE_PARAMS(int, k), + AND_0_VALUE_PARAMS()) { + using internal::invoke_argument::InvokeArgumentAdl; + return InvokeArgumentAdl( + internal::invoke_argument::AdlTag(), + ::std::get(args)); +} + +ACTION_TEMPLATE(InvokeArgument, + HAS_1_TEMPLATE_PARAMS(int, k), + AND_1_VALUE_PARAMS(p0)) { + using internal::invoke_argument::InvokeArgumentAdl; + return InvokeArgumentAdl( + internal::invoke_argument::AdlTag(), + ::std::get(args), p0); +} + +ACTION_TEMPLATE(InvokeArgument, + HAS_1_TEMPLATE_PARAMS(int, k), + AND_2_VALUE_PARAMS(p0, p1)) { + using internal::invoke_argument::InvokeArgumentAdl; + return InvokeArgumentAdl( + internal::invoke_argument::AdlTag(), + ::std::get(args), p0, p1); +} + +ACTION_TEMPLATE(InvokeArgument, + HAS_1_TEMPLATE_PARAMS(int, k), + AND_3_VALUE_PARAMS(p0, p1, p2)) { + using internal::invoke_argument::InvokeArgumentAdl; + return InvokeArgumentAdl( + internal::invoke_argument::AdlTag(), + ::std::get(args), p0, p1, p2); +} + +ACTION_TEMPLATE(InvokeArgument, + HAS_1_TEMPLATE_PARAMS(int, k), + AND_4_VALUE_PARAMS(p0, p1, p2, p3)) { + using internal::invoke_argument::InvokeArgumentAdl; + return InvokeArgumentAdl( + internal::invoke_argument::AdlTag(), + ::std::get(args), p0, p1, p2, p3); +} + +ACTION_TEMPLATE(InvokeArgument, + HAS_1_TEMPLATE_PARAMS(int, k), + AND_5_VALUE_PARAMS(p0, p1, p2, p3, p4)) { + using internal::invoke_argument::InvokeArgumentAdl; + return InvokeArgumentAdl( + internal::invoke_argument::AdlTag(), + ::std::get(args), p0, p1, p2, p3, p4); +} + +ACTION_TEMPLATE(InvokeArgument, + HAS_1_TEMPLATE_PARAMS(int, k), + AND_6_VALUE_PARAMS(p0, p1, p2, p3, p4, p5)) { + using internal::invoke_argument::InvokeArgumentAdl; + return InvokeArgumentAdl( + internal::invoke_argument::AdlTag(), + ::std::get(args), p0, p1, p2, p3, p4, p5); +} + +ACTION_TEMPLATE(InvokeArgument, + HAS_1_TEMPLATE_PARAMS(int, k), + AND_7_VALUE_PARAMS(p0, p1, p2, p3, p4, p5, p6)) { + using internal::invoke_argument::InvokeArgumentAdl; + return InvokeArgumentAdl( + internal::invoke_argument::AdlTag(), + ::std::get(args), p0, p1, p2, p3, p4, p5, p6); +} + +ACTION_TEMPLATE(InvokeArgument, + HAS_1_TEMPLATE_PARAMS(int, k), + AND_8_VALUE_PARAMS(p0, p1, p2, p3, p4, p5, p6, p7)) { + using internal::invoke_argument::InvokeArgumentAdl; + return InvokeArgumentAdl( + internal::invoke_argument::AdlTag(), + ::std::get(args), p0, p1, p2, p3, p4, p5, p6, p7); +} + +ACTION_TEMPLATE(InvokeArgument, + HAS_1_TEMPLATE_PARAMS(int, k), + AND_9_VALUE_PARAMS(p0, p1, p2, p3, p4, p5, p6, p7, p8)) { + using internal::invoke_argument::InvokeArgumentAdl; + return InvokeArgumentAdl( + internal::invoke_argument::AdlTag(), + ::std::get(args), p0, p1, p2, p3, p4, p5, p6, p7, p8); +} + +ACTION_TEMPLATE(InvokeArgument, + HAS_1_TEMPLATE_PARAMS(int, k), + AND_10_VALUE_PARAMS(p0, p1, p2, p3, p4, p5, p6, p7, p8, p9)) { + using internal::invoke_argument::InvokeArgumentAdl; + return InvokeArgumentAdl( + internal::invoke_argument::AdlTag(), + ::std::get(args), p0, p1, p2, p3, p4, p5, p6, p7, p8, p9); +} + +// Various overloads for ReturnNew(). +// +// The ReturnNew(a1, a2, ..., a_k) action returns a pointer to a new +// instance of type T, constructed on the heap with constructor arguments +// a1, a2, ..., and a_k. The caller assumes ownership of the returned value. +ACTION_TEMPLATE(ReturnNew, + HAS_1_TEMPLATE_PARAMS(typename, T), + AND_0_VALUE_PARAMS()) { + return new T(); +} + +ACTION_TEMPLATE(ReturnNew, + HAS_1_TEMPLATE_PARAMS(typename, T), + AND_1_VALUE_PARAMS(p0)) { + return new T(p0); +} + +ACTION_TEMPLATE(ReturnNew, + HAS_1_TEMPLATE_PARAMS(typename, T), + AND_2_VALUE_PARAMS(p0, p1)) { + return new T(p0, p1); +} + +ACTION_TEMPLATE(ReturnNew, + HAS_1_TEMPLATE_PARAMS(typename, T), + AND_3_VALUE_PARAMS(p0, p1, p2)) { + return new T(p0, p1, p2); +} + +ACTION_TEMPLATE(ReturnNew, + HAS_1_TEMPLATE_PARAMS(typename, T), + AND_4_VALUE_PARAMS(p0, p1, p2, p3)) { + return new T(p0, p1, p2, p3); +} + +ACTION_TEMPLATE(ReturnNew, + HAS_1_TEMPLATE_PARAMS(typename, T), + AND_5_VALUE_PARAMS(p0, p1, p2, p3, p4)) { + return new T(p0, p1, p2, p3, p4); +} + +ACTION_TEMPLATE(ReturnNew, + HAS_1_TEMPLATE_PARAMS(typename, T), + AND_6_VALUE_PARAMS(p0, p1, p2, p3, p4, p5)) { + return new T(p0, p1, p2, p3, p4, p5); +} + +ACTION_TEMPLATE(ReturnNew, + HAS_1_TEMPLATE_PARAMS(typename, T), + AND_7_VALUE_PARAMS(p0, p1, p2, p3, p4, p5, p6)) { + return new T(p0, p1, p2, p3, p4, p5, p6); +} + +ACTION_TEMPLATE(ReturnNew, + HAS_1_TEMPLATE_PARAMS(typename, T), + AND_8_VALUE_PARAMS(p0, p1, p2, p3, p4, p5, p6, p7)) { + return new T(p0, p1, p2, p3, p4, p5, p6, p7); +} + +ACTION_TEMPLATE(ReturnNew, + HAS_1_TEMPLATE_PARAMS(typename, T), + AND_9_VALUE_PARAMS(p0, p1, p2, p3, p4, p5, p6, p7, p8)) { + return new T(p0, p1, p2, p3, p4, p5, p6, p7, p8); +} + +ACTION_TEMPLATE(ReturnNew, + HAS_1_TEMPLATE_PARAMS(typename, T), + AND_10_VALUE_PARAMS(p0, p1, p2, p3, p4, p5, p6, p7, p8, p9)) { + return new T(p0, p1, p2, p3, p4, p5, p6, p7, p8, p9); +} + +#ifdef _MSC_VER +# pragma warning(pop) +#endif + +} // namespace testing + +// Include any custom callback actions added by the local installation. +// We must include this header at the end to make sure it can use the +// declarations from this file. +#include "gmock/internal/custom/gmock-generated-actions.h" + +#endif // GMOCK_INCLUDE_GMOCK_GMOCK_GENERATED_ACTIONS_H_ diff --git a/googlemock/include/gmock/gmock-generated-actions.h.pump b/googlemock/include/gmock/gmock-generated-actions.h.pump new file mode 100644 index 00000000..209603c5 --- /dev/null +++ b/googlemock/include/gmock/gmock-generated-actions.h.pump @@ -0,0 +1,627 @@ +$$ -*- mode: c++; -*- +$$ This is a Pump source file. Please use Pump to convert it to +$$ gmock-generated-actions.h. +$$ +$var n = 10 $$ The maximum arity we support. +$$}} This meta comment fixes auto-indentation in editors. +// Copyright 2007, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + +// Google Mock - a framework for writing C++ mock classes. +// +// This file implements some commonly used variadic actions. + +// GOOGLETEST_CM0002 DO NOT DELETE + +#ifndef GMOCK_INCLUDE_GMOCK_GMOCK_GENERATED_ACTIONS_H_ +#define GMOCK_INCLUDE_GMOCK_GMOCK_GENERATED_ACTIONS_H_ + +#include +#include + +#include "gmock/gmock-actions.h" +#include "gmock/internal/gmock-port.h" + +namespace testing { +namespace internal { + +// A macro from the ACTION* family (defined later in this file) +// defines an action that can be used in a mock function. Typically, +// these actions only care about a subset of the arguments of the mock +// function. For example, if such an action only uses the second +// argument, it can be used in any mock function that takes >= 2 +// arguments where the type of the second argument is compatible. +// +// Therefore, the action implementation must be prepared to take more +// arguments than it needs. The ExcessiveArg type is used to +// represent those excessive arguments. In order to keep the compiler +// error messages tractable, we define it in the testing namespace +// instead of testing::internal. However, this is an INTERNAL TYPE +// and subject to change without notice, so a user MUST NOT USE THIS +// TYPE DIRECTLY. +struct ExcessiveArg {}; + +// A helper class needed for implementing the ACTION* macros. +template +class ActionHelper { + public: +$range i 0..n +$for i + +[[ +$var template = [[$if i==0 [[]] $else [[ +$range j 0..i-1 + template <$for j, [[typename A$j]]> +]]]] +$range j 0..i-1 +$var As = [[$for j, [[A$j]]]] +$var as = [[$for j, [[std::get<$j>(args)]]]] +$range k 1..n-i +$var eas = [[$for k, [[ExcessiveArg()]]]] +$var arg_list = [[$if (i==0) | (i==n) [[$as$eas]] $else [[$as, $eas]]]] +$template + static Result Perform(Impl* impl, const ::std::tuple<$As>& args) { + return impl->template gmock_PerformImpl<$As>(args, $arg_list); + } + +]] +}; + +} // namespace internal +} // namespace testing + +// The ACTION* family of macros can be used in a namespace scope to +// define custom actions easily. The syntax: +// +// ACTION(name) { statements; } +// +// will define an action with the given name that executes the +// statements. The value returned by the statements will be used as +// the return value of the action. Inside the statements, you can +// refer to the K-th (0-based) argument of the mock function by +// 'argK', and refer to its type by 'argK_type'. For example: +// +// ACTION(IncrementArg1) { +// arg1_type temp = arg1; +// return ++(*temp); +// } +// +// allows you to write +// +// ...WillOnce(IncrementArg1()); +// +// You can also refer to the entire argument tuple and its type by +// 'args' and 'args_type', and refer to the mock function type and its +// return type by 'function_type' and 'return_type'. +// +// Note that you don't need to specify the types of the mock function +// arguments. However rest assured that your code is still type-safe: +// you'll get a compiler error if *arg1 doesn't support the ++ +// operator, or if the type of ++(*arg1) isn't compatible with the +// mock function's return type, for example. +// +// Sometimes you'll want to parameterize the action. For that you can use +// another macro: +// +// ACTION_P(name, param_name) { statements; } +// +// For example: +// +// ACTION_P(Add, n) { return arg0 + n; } +// +// will allow you to write: +// +// ...WillOnce(Add(5)); +// +// Note that you don't need to provide the type of the parameter +// either. If you need to reference the type of a parameter named +// 'foo', you can write 'foo_type'. For example, in the body of +// ACTION_P(Add, n) above, you can write 'n_type' to refer to the type +// of 'n'. +// +// We also provide ACTION_P2, ACTION_P3, ..., up to ACTION_P$n to support +// multi-parameter actions. +// +// For the purpose of typing, you can view +// +// ACTION_Pk(Foo, p1, ..., pk) { ... } +// +// as shorthand for +// +// template +// FooActionPk Foo(p1_type p1, ..., pk_type pk) { ... } +// +// In particular, you can provide the template type arguments +// explicitly when invoking Foo(), as in Foo(5, false); +// although usually you can rely on the compiler to infer the types +// for you automatically. You can assign the result of expression +// Foo(p1, ..., pk) to a variable of type FooActionPk. This can be useful when composing actions. +// +// You can also overload actions with different numbers of parameters: +// +// ACTION_P(Plus, a) { ... } +// ACTION_P2(Plus, a, b) { ... } +// +// While it's tempting to always use the ACTION* macros when defining +// a new action, you should also consider implementing ActionInterface +// or using MakePolymorphicAction() instead, especially if you need to +// use the action a lot. While these approaches require more work, +// they give you more control on the types of the mock function +// arguments and the action parameters, which in general leads to +// better compiler error messages that pay off in the long run. They +// also allow overloading actions based on parameter types (as opposed +// to just based on the number of parameters). +// +// CAVEAT: +// +// ACTION*() can only be used in a namespace scope as templates cannot be +// declared inside of a local class. +// Users can, however, define any local functors (e.g. a lambda) that +// can be used as actions. +// +// MORE INFORMATION: +// +// To learn more about using these macros, please search for 'ACTION' on +// https://github.com/google/googletest/blob/master/googlemock/docs/cook_book.md + +$range i 0..n +$range k 0..n-1 + +// An internal macro needed for implementing ACTION*(). +#define GMOCK_ACTION_ARG_TYPES_AND_NAMES_UNUSED_\ + const args_type& args GTEST_ATTRIBUTE_UNUSED_ +$for k [[, \ + const arg$k[[]]_type& arg$k GTEST_ATTRIBUTE_UNUSED_]] + + +// Sometimes you want to give an action explicit template parameters +// that cannot be inferred from its value parameters. ACTION() and +// ACTION_P*() don't support that. ACTION_TEMPLATE() remedies that +// and can be viewed as an extension to ACTION() and ACTION_P*(). +// +// The syntax: +// +// ACTION_TEMPLATE(ActionName, +// HAS_m_TEMPLATE_PARAMS(kind1, name1, ..., kind_m, name_m), +// AND_n_VALUE_PARAMS(p1, ..., p_n)) { statements; } +// +// defines an action template that takes m explicit template +// parameters and n value parameters. name_i is the name of the i-th +// template parameter, and kind_i specifies whether it's a typename, +// an integral constant, or a template. p_i is the name of the i-th +// value parameter. +// +// Example: +// +// // DuplicateArg(output) converts the k-th argument of the mock +// // function to type T and copies it to *output. +// ACTION_TEMPLATE(DuplicateArg, +// HAS_2_TEMPLATE_PARAMS(int, k, typename, T), +// AND_1_VALUE_PARAMS(output)) { +// *output = T(::std::get(args)); +// } +// ... +// int n; +// EXPECT_CALL(mock, Foo(_, _)) +// .WillOnce(DuplicateArg<1, unsigned char>(&n)); +// +// To create an instance of an action template, write: +// +// ActionName(v1, ..., v_n) +// +// where the ts are the template arguments and the vs are the value +// arguments. The value argument types are inferred by the compiler. +// If you want to explicitly specify the value argument types, you can +// provide additional template arguments: +// +// ActionName(v1, ..., v_n) +// +// where u_i is the desired type of v_i. +// +// ACTION_TEMPLATE and ACTION/ACTION_P* can be overloaded on the +// number of value parameters, but not on the number of template +// parameters. Without the restriction, the meaning of the following +// is unclear: +// +// OverloadedAction(x); +// +// Are we using a single-template-parameter action where 'bool' refers +// to the type of x, or are we using a two-template-parameter action +// where the compiler is asked to infer the type of x? +// +// Implementation notes: +// +// GMOCK_INTERNAL_*_HAS_m_TEMPLATE_PARAMS and +// GMOCK_INTERNAL_*_AND_n_VALUE_PARAMS are internal macros for +// implementing ACTION_TEMPLATE. The main trick we use is to create +// new macro invocations when expanding a macro. For example, we have +// +// #define ACTION_TEMPLATE(name, template_params, value_params) +// ... GMOCK_INTERNAL_DECL_##template_params ... +// +// which causes ACTION_TEMPLATE(..., HAS_1_TEMPLATE_PARAMS(typename, T), ...) +// to expand to +// +// ... GMOCK_INTERNAL_DECL_HAS_1_TEMPLATE_PARAMS(typename, T) ... +// +// Since GMOCK_INTERNAL_DECL_HAS_1_TEMPLATE_PARAMS is a macro, the +// preprocessor will continue to expand it to +// +// ... typename T ... +// +// This technique conforms to the C++ standard and is portable. It +// allows us to implement action templates using O(N) code, where N is +// the maximum number of template/value parameters supported. Without +// using it, we'd have to devote O(N^2) amount of code to implement all +// combinations of m and n. + +// Declares the template parameters. + +$range j 1..n +$for j [[ +$range m 0..j-1 +#define GMOCK_INTERNAL_DECL_HAS_$j[[]] +_TEMPLATE_PARAMS($for m, [[kind$m, name$m]]) $for m, [[kind$m name$m]] + + +]] + +// Lists the template parameters. + +$for j [[ +$range m 0..j-1 +#define GMOCK_INTERNAL_LIST_HAS_$j[[]] +_TEMPLATE_PARAMS($for m, [[kind$m, name$m]]) $for m, [[name$m]] + + +]] + +// Declares the types of value parameters. + +$for i [[ +$range j 0..i-1 +#define GMOCK_INTERNAL_DECL_TYPE_AND_$i[[]] +_VALUE_PARAMS($for j, [[p$j]]) $for j [[, typename p$j##_type]] + + +]] + +// Initializes the value parameters. + +$for i [[ +$range j 0..i-1 +#define GMOCK_INTERNAL_INIT_AND_$i[[]]_VALUE_PARAMS($for j, [[p$j]])\ + ($for j, [[p$j##_type gmock_p$j]])$if i>0 [[ : ]]$for j, [[p$j(::std::move(gmock_p$j))]] + + +]] + +// Declares the fields for storing the value parameters. + +$for i [[ +$range j 0..i-1 +#define GMOCK_INTERNAL_DEFN_AND_$i[[]] +_VALUE_PARAMS($for j, [[p$j]]) $for j [[p$j##_type p$j; ]] + + +]] + +// Lists the value parameters. + +$for i [[ +$range j 0..i-1 +#define GMOCK_INTERNAL_LIST_AND_$i[[]] +_VALUE_PARAMS($for j, [[p$j]]) $for j, [[p$j]] + + +]] + +// Lists the value parameter types. + +$for i [[ +$range j 0..i-1 +#define GMOCK_INTERNAL_LIST_TYPE_AND_$i[[]] +_VALUE_PARAMS($for j, [[p$j]]) $for j [[, p$j##_type]] + + +]] + +// Declares the value parameters. + +$for i [[ +$range j 0..i-1 +#define GMOCK_INTERNAL_DECL_AND_$i[[]]_VALUE_PARAMS($for j, [[p$j]]) [[]] +$for j, [[p$j##_type p$j]] + + +]] + +// The suffix of the class template implementing the action template. +$for i [[ + + +$range j 0..i-1 +#define GMOCK_INTERNAL_COUNT_AND_$i[[]]_VALUE_PARAMS($for j, [[p$j]]) [[]] +$if i==1 [[P]] $elif i>=2 [[P$i]] +]] + + +// The name of the class template implementing the action template. +#define GMOCK_ACTION_CLASS_(name, value_params)\ + GTEST_CONCAT_TOKEN_(name##Action, GMOCK_INTERNAL_COUNT_##value_params) + +$range k 0..n-1 + +#define ACTION_TEMPLATE(name, template_params, value_params)\ + template \ + class GMOCK_ACTION_CLASS_(name, value_params) {\ + public:\ + explicit GMOCK_ACTION_CLASS_(name, value_params)\ + GMOCK_INTERNAL_INIT_##value_params {}\ + template \ + class gmock_Impl : public ::testing::ActionInterface {\ + public:\ + typedef F function_type;\ + typedef typename ::testing::internal::Function::Result return_type;\ + typedef typename ::testing::internal::Function::ArgumentTuple\ + args_type;\ + explicit gmock_Impl GMOCK_INTERNAL_INIT_##value_params {}\ + virtual return_type Perform(const args_type& args) {\ + return ::testing::internal::ActionHelper::\ + Perform(this, args);\ + }\ + template <$for k, [[typename arg$k[[]]_type]]>\ + return_type gmock_PerformImpl(const args_type& args[[]] +$for k [[, const arg$k[[]]_type& arg$k]]) const;\ + GMOCK_INTERNAL_DEFN_##value_params\ + private:\ + GTEST_DISALLOW_ASSIGN_(gmock_Impl);\ + };\ + template operator ::testing::Action() const {\ + return ::testing::Action(\ + new gmock_Impl(GMOCK_INTERNAL_LIST_##value_params));\ + }\ + GMOCK_INTERNAL_DEFN_##value_params\ + private:\ + GTEST_DISALLOW_ASSIGN_(GMOCK_ACTION_CLASS_(name, value_params));\ + };\ + template \ + inline GMOCK_ACTION_CLASS_(name, value_params)<\ + GMOCK_INTERNAL_LIST_##template_params\ + GMOCK_INTERNAL_LIST_TYPE_##value_params> name(\ + GMOCK_INTERNAL_DECL_##value_params) {\ + return GMOCK_ACTION_CLASS_(name, value_params)<\ + GMOCK_INTERNAL_LIST_##template_params\ + GMOCK_INTERNAL_LIST_TYPE_##value_params>(\ + GMOCK_INTERNAL_LIST_##value_params);\ + }\ + template \ + template \ + template \ + typename ::testing::internal::Function::Result\ + GMOCK_ACTION_CLASS_(name, value_params)<\ + GMOCK_INTERNAL_LIST_##template_params\ + GMOCK_INTERNAL_LIST_TYPE_##value_params>::gmock_Impl::\ + gmock_PerformImpl(\ + GMOCK_ACTION_ARG_TYPES_AND_NAMES_UNUSED_) const + +$for i + +[[ +$var template = [[$if i==0 [[]] $else [[ +$range j 0..i-1 + + template <$for j, [[typename p$j##_type]]>\ +]]]] +$var class_name = [[name##Action[[$if i==0 [[]] $elif i==1 [[P]] + $else [[P$i]]]]]] +$range j 0..i-1 +$var ctor_param_list = [[$for j, [[p$j##_type gmock_p$j]]]] +$var param_types_and_names = [[$for j, [[p$j##_type p$j]]]] +$var inits = [[$if i==0 [[]] $else [[ : $for j, [[p$j(::std::forward(gmock_p$j))]]]]]] +$var param_field_decls = [[$for j +[[ + + p$j##_type p$j;\ +]]]] +$var param_field_decls2 = [[$for j +[[ + + p$j##_type p$j;\ +]]]] +$var params = [[$for j, [[p$j]]]] +$var param_types = [[$if i==0 [[]] $else [[<$for j, [[p$j##_type]]>]]]] +$var typename_arg_types = [[$for k, [[typename arg$k[[]]_type]]]] +$var arg_types_and_names = [[$for k, [[const arg$k[[]]_type& arg$k]]]] +$var macro_name = [[$if i==0 [[ACTION]] $elif i==1 [[ACTION_P]] + $else [[ACTION_P$i]]]] + +#define $macro_name(name$for j [[, p$j]])\$template + class $class_name {\ + public:\ + [[$if i==1 [[explicit ]]]]$class_name($ctor_param_list)$inits {}\ + template \ + class gmock_Impl : public ::testing::ActionInterface {\ + public:\ + typedef F function_type;\ + typedef typename ::testing::internal::Function::Result return_type;\ + typedef typename ::testing::internal::Function::ArgumentTuple\ + args_type;\ + [[$if i==1 [[explicit ]]]]gmock_Impl($ctor_param_list)$inits {}\ + virtual return_type Perform(const args_type& args) {\ + return ::testing::internal::ActionHelper::\ + Perform(this, args);\ + }\ + template <$typename_arg_types>\ + return_type gmock_PerformImpl(const args_type& args, [[]] +$arg_types_and_names) const;\$param_field_decls + private:\ + GTEST_DISALLOW_ASSIGN_(gmock_Impl);\ + };\ + template operator ::testing::Action() const {\ + return ::testing::Action(new gmock_Impl($params));\ + }\$param_field_decls2 + private:\ + GTEST_DISALLOW_ASSIGN_($class_name);\ + };\$template + inline $class_name$param_types name($param_types_and_names) {\ + return $class_name$param_types($params);\ + }\$template + template \ + template <$typename_arg_types>\ + typename ::testing::internal::Function::Result\ + $class_name$param_types::gmock_Impl::gmock_PerformImpl(\ + GMOCK_ACTION_ARG_TYPES_AND_NAMES_UNUSED_) const +]] +$$ } // This meta comment fixes auto-indentation in Emacs. It won't +$$ // show up in the generated code. + + +namespace testing { + + +// The ACTION*() macros trigger warning C4100 (unreferenced formal +// parameter) in MSVC with -W4. Unfortunately they cannot be fixed in +// the macro definition, as the warnings are generated when the macro +// is expanded and macro expansion cannot contain #pragma. Therefore +// we suppress them here. +#ifdef _MSC_VER +# pragma warning(push) +# pragma warning(disable:4100) +#endif + +// Various overloads for InvokeArgument(). +// +// The InvokeArgument(a1, a2, ..., a_k) action invokes the N-th +// (0-based) argument, which must be a k-ary callable, of the mock +// function, with arguments a1, a2, ..., a_k. +// +// Notes: +// +// 1. The arguments are passed by value by default. If you need to +// pass an argument by reference, wrap it inside ByRef(). For +// example, +// +// InvokeArgument<1>(5, string("Hello"), ByRef(foo)) +// +// passes 5 and string("Hello") by value, and passes foo by +// reference. +// +// 2. If the callable takes an argument by reference but ByRef() is +// not used, it will receive the reference to a copy of the value, +// instead of the original value. For example, when the 0-th +// argument of the mock function takes a const string&, the action +// +// InvokeArgument<0>(string("Hello")) +// +// makes a copy of the temporary string("Hello") object and passes a +// reference of the copy, instead of the original temporary object, +// to the callable. This makes it easy for a user to define an +// InvokeArgument action from temporary values and have it performed +// later. + +namespace internal { +namespace invoke_argument { + +// Appears in InvokeArgumentAdl's argument list to help avoid +// accidental calls to user functions of the same name. +struct AdlTag {}; + +// InvokeArgumentAdl - a helper for InvokeArgument. +// The basic overloads are provided here for generic functors. +// Overloads for other custom-callables are provided in the +// internal/custom/callback-actions.h header. + +$range i 0..n +$for i +[[ +$range j 1..i + +template +R InvokeArgumentAdl(AdlTag, F f[[$for j [[, A$j a$j]]]]) { + return f([[$for j, [[a$j]]]]); +} +]] + +} // namespace invoke_argument +} // namespace internal + +$range i 0..n +$for i [[ +$range j 0..i-1 + +ACTION_TEMPLATE(InvokeArgument, + HAS_1_TEMPLATE_PARAMS(int, k), + AND_$i[[]]_VALUE_PARAMS($for j, [[p$j]])) { + using internal::invoke_argument::InvokeArgumentAdl; + return InvokeArgumentAdl( + internal::invoke_argument::AdlTag(), + ::std::get(args)$for j [[, p$j]]); +} + +]] + +// Various overloads for ReturnNew(). +// +// The ReturnNew(a1, a2, ..., a_k) action returns a pointer to a new +// instance of type T, constructed on the heap with constructor arguments +// a1, a2, ..., and a_k. The caller assumes ownership of the returned value. +$range i 0..n +$for i [[ +$range j 0..i-1 +$var ps = [[$for j, [[p$j]]]] + +ACTION_TEMPLATE(ReturnNew, + HAS_1_TEMPLATE_PARAMS(typename, T), + AND_$i[[]]_VALUE_PARAMS($ps)) { + return new T($ps); +} + +]] + +#ifdef _MSC_VER +# pragma warning(pop) +#endif + +} // namespace testing + +// Include any custom callback actions added by the local installation. +// We must include this header at the end to make sure it can use the +// declarations from this file. +#include "gmock/internal/custom/gmock-generated-actions.h" + +#endif // GMOCK_INCLUDE_GMOCK_GMOCK_GENERATED_ACTIONS_H_ diff --git a/googlemock/include/gmock/gmock-generated-function-mockers.h b/googlemock/include/gmock/gmock-generated-function-mockers.h new file mode 100644 index 00000000..cd957817 --- /dev/null +++ b/googlemock/include/gmock/gmock-generated-function-mockers.h @@ -0,0 +1,752 @@ +// This file was GENERATED by command: +// pump.py gmock-generated-function-mockers.h.pump +// DO NOT EDIT BY HAND!!! + +// Copyright 2007, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + +// Google Mock - a framework for writing C++ mock classes. +// +// This file implements function mockers of various arities. + +// GOOGLETEST_CM0002 DO NOT DELETE + +#ifndef GMOCK_INCLUDE_GMOCK_GMOCK_GENERATED_FUNCTION_MOCKERS_H_ +#define GMOCK_INCLUDE_GMOCK_GMOCK_GENERATED_FUNCTION_MOCKERS_H_ + +#include +#include + +#include "gmock/gmock-spec-builders.h" +#include "gmock/internal/gmock-internal-utils.h" + +namespace testing { +namespace internal { +// Removes the given pointer; this is a helper for the expectation setter method +// for parameterless matchers. +// +// We want to make sure that the user cannot set a parameterless expectation on +// overloaded methods, including methods which are overloaded on const. Example: +// +// class MockClass { +// MOCK_METHOD0(GetName, string&()); +// MOCK_CONST_METHOD0(GetName, const string&()); +// }; +// +// TEST() { +// // This should be an error, as it's not clear which overload is expected. +// EXPECT_CALL(mock, GetName).WillOnce(ReturnRef(value)); +// } +// +// Here are the generated expectation-setter methods: +// +// class MockClass { +// // Overload 1 +// MockSpec gmock_GetName() { ... } +// // Overload 2. Declared const so that the compiler will generate an +// // error when trying to resolve between this and overload 4 in +// // 'gmock_GetName(WithoutMatchers(), nullptr)'. +// MockSpec gmock_GetName( +// const WithoutMatchers&, const Function*) const { +// // Removes const from this, calls overload 1 +// return AdjustConstness_(this)->gmock_GetName(); +// } +// +// // Overload 3 +// const string& gmock_GetName() const { ... } +// // Overload 4 +// MockSpec gmock_GetName( +// const WithoutMatchers&, const Function*) const { +// // Does not remove const, calls overload 3 +// return AdjustConstness_const(this)->gmock_GetName(); +// } +// } +// +template +const MockType* AdjustConstness_const(const MockType* mock) { + return mock; +} + +// Removes const from and returns the given pointer; this is a helper for the +// expectation setter method for parameterless matchers. +template +MockType* AdjustConstness_(const MockType* mock) { + return const_cast(mock); +} + +} // namespace internal + +// The style guide prohibits "using" statements in a namespace scope +// inside a header file. However, the FunctionMocker class template +// is meant to be defined in the ::testing namespace. The following +// line is just a trick for working around a bug in MSVC 8.0, which +// cannot handle it if we define FunctionMocker in ::testing. +using internal::FunctionMocker; + +// GMOCK_RESULT_(tn, F) expands to the result type of function type F. +// We define this as a variadic macro in case F contains unprotected +// commas (the same reason that we use variadic macros in other places +// in this file). +// INTERNAL IMPLEMENTATION - DON'T USE IN USER CODE!!! +#define GMOCK_RESULT_(tn, ...) \ + tn ::testing::internal::Function<__VA_ARGS__>::Result + +// The type of argument N of the given function type. +// INTERNAL IMPLEMENTATION - DON'T USE IN USER CODE!!! +#define GMOCK_ARG_(tn, N, ...) \ + tn ::testing::internal::Function<__VA_ARGS__>::template Arg::type + +// The matcher type for argument N of the given function type. +// INTERNAL IMPLEMENTATION - DON'T USE IN USER CODE!!! +#define GMOCK_MATCHER_(tn, N, ...) \ + const ::testing::Matcher& + +// The variable for mocking the given method. +// INTERNAL IMPLEMENTATION - DON'T USE IN USER CODE!!! +#define GMOCK_MOCKER_(arity, constness, Method) \ + GTEST_CONCAT_TOKEN_(gmock##constness##arity##_##Method##_, __LINE__) + +// INTERNAL IMPLEMENTATION - DON'T USE IN USER CODE!!! +#define GMOCK_METHOD0_(tn, constness, ct, Method, ...) \ + static_assert(0 == \ + ::testing::internal::Function<__VA_ARGS__>::ArgumentCount, \ + "MOCK_METHOD must match argument count.");\ + GMOCK_RESULT_(tn, __VA_ARGS__) ct Method( \ + ) constness { \ + GMOCK_MOCKER_(0, constness, Method).SetOwnerAndName(this, #Method); \ + return GMOCK_MOCKER_(0, constness, Method).Invoke(); \ + } \ + ::testing::MockSpec<__VA_ARGS__> \ + gmock_##Method() constness { \ + GMOCK_MOCKER_(0, constness, Method).RegisterOwner(this); \ + return GMOCK_MOCKER_(0, constness, Method).With(); \ + } \ + ::testing::MockSpec<__VA_ARGS__> gmock_##Method( \ + const ::testing::internal::WithoutMatchers&, \ + constness ::testing::internal::Function<__VA_ARGS__>* ) const { \ + return ::testing::internal::AdjustConstness_##constness(this)-> \ + gmock_##Method(); \ + } \ + mutable ::testing::FunctionMocker<__VA_ARGS__> GMOCK_MOCKER_(0, constness, \ + Method) + +// INTERNAL IMPLEMENTATION - DON'T USE IN USER CODE!!! +#define GMOCK_METHOD1_(tn, constness, ct, Method, ...) \ + static_assert(1 == \ + ::testing::internal::Function<__VA_ARGS__>::ArgumentCount, \ + "MOCK_METHOD must match argument count.");\ + GMOCK_RESULT_(tn, __VA_ARGS__) ct Method( \ + GMOCK_ARG_(tn, 1, __VA_ARGS__) gmock_a1) constness { \ + GMOCK_MOCKER_(1, constness, Method).SetOwnerAndName(this, #Method); \ + return GMOCK_MOCKER_(1, constness, \ + Method).Invoke(::std::forward(gmock_a1)); \ + } \ + ::testing::MockSpec<__VA_ARGS__> \ + gmock_##Method(GMOCK_MATCHER_(tn, 1, __VA_ARGS__) gmock_a1) constness { \ + GMOCK_MOCKER_(1, constness, Method).RegisterOwner(this); \ + return GMOCK_MOCKER_(1, constness, Method).With(gmock_a1); \ + } \ + ::testing::MockSpec<__VA_ARGS__> gmock_##Method( \ + const ::testing::internal::WithoutMatchers&, \ + constness ::testing::internal::Function<__VA_ARGS__>* ) const { \ + return ::testing::internal::AdjustConstness_##constness(this)-> \ + gmock_##Method(::testing::A()); \ + } \ + mutable ::testing::FunctionMocker<__VA_ARGS__> GMOCK_MOCKER_(1, constness, \ + Method) + +// INTERNAL IMPLEMENTATION - DON'T USE IN USER CODE!!! +#define GMOCK_METHOD2_(tn, constness, ct, Method, ...) \ + static_assert(2 == \ + ::testing::internal::Function<__VA_ARGS__>::ArgumentCount, \ + "MOCK_METHOD must match argument count.");\ + GMOCK_RESULT_(tn, __VA_ARGS__) ct Method( \ + GMOCK_ARG_(tn, 1, __VA_ARGS__) gmock_a1, GMOCK_ARG_(tn, 2, \ + __VA_ARGS__) gmock_a2) constness { \ + GMOCK_MOCKER_(2, constness, Method).SetOwnerAndName(this, #Method); \ + return GMOCK_MOCKER_(2, constness, \ + Method).Invoke(::std::forward(gmock_a1), \ + ::std::forward(gmock_a2)); \ + } \ + ::testing::MockSpec<__VA_ARGS__> \ + gmock_##Method(GMOCK_MATCHER_(tn, 1, __VA_ARGS__) gmock_a1, \ + GMOCK_MATCHER_(tn, 2, __VA_ARGS__) gmock_a2) constness { \ + GMOCK_MOCKER_(2, constness, Method).RegisterOwner(this); \ + return GMOCK_MOCKER_(2, constness, Method).With(gmock_a1, gmock_a2); \ + } \ + ::testing::MockSpec<__VA_ARGS__> gmock_##Method( \ + const ::testing::internal::WithoutMatchers&, \ + constness ::testing::internal::Function<__VA_ARGS__>* ) const { \ + return ::testing::internal::AdjustConstness_##constness(this)-> \ + gmock_##Method(::testing::A(), \ + ::testing::A()); \ + } \ + mutable ::testing::FunctionMocker<__VA_ARGS__> GMOCK_MOCKER_(2, constness, \ + Method) + +// INTERNAL IMPLEMENTATION - DON'T USE IN USER CODE!!! +#define GMOCK_METHOD3_(tn, constness, ct, Method, ...) \ + static_assert(3 == \ + ::testing::internal::Function<__VA_ARGS__>::ArgumentCount, \ + "MOCK_METHOD must match argument count.");\ + GMOCK_RESULT_(tn, __VA_ARGS__) ct Method( \ + GMOCK_ARG_(tn, 1, __VA_ARGS__) gmock_a1, GMOCK_ARG_(tn, 2, \ + __VA_ARGS__) gmock_a2, GMOCK_ARG_(tn, 3, \ + __VA_ARGS__) gmock_a3) constness { \ + GMOCK_MOCKER_(3, constness, Method).SetOwnerAndName(this, #Method); \ + return GMOCK_MOCKER_(3, constness, \ + Method).Invoke(::std::forward(gmock_a1), \ + ::std::forward(gmock_a2), \ + ::std::forward(gmock_a3)); \ + } \ + ::testing::MockSpec<__VA_ARGS__> \ + gmock_##Method(GMOCK_MATCHER_(tn, 1, __VA_ARGS__) gmock_a1, \ + GMOCK_MATCHER_(tn, 2, __VA_ARGS__) gmock_a2, \ + GMOCK_MATCHER_(tn, 3, __VA_ARGS__) gmock_a3) constness { \ + GMOCK_MOCKER_(3, constness, Method).RegisterOwner(this); \ + return GMOCK_MOCKER_(3, constness, Method).With(gmock_a1, gmock_a2, \ + gmock_a3); \ + } \ + ::testing::MockSpec<__VA_ARGS__> gmock_##Method( \ + const ::testing::internal::WithoutMatchers&, \ + constness ::testing::internal::Function<__VA_ARGS__>* ) const { \ + return ::testing::internal::AdjustConstness_##constness(this)-> \ + gmock_##Method(::testing::A(), \ + ::testing::A(), \ + ::testing::A()); \ + } \ + mutable ::testing::FunctionMocker<__VA_ARGS__> GMOCK_MOCKER_(3, constness, \ + Method) + +// INTERNAL IMPLEMENTATION - DON'T USE IN USER CODE!!! +#define GMOCK_METHOD4_(tn, constness, ct, Method, ...) \ + static_assert(4 == \ + ::testing::internal::Function<__VA_ARGS__>::ArgumentCount, \ + "MOCK_METHOD must match argument count.");\ + GMOCK_RESULT_(tn, __VA_ARGS__) ct Method( \ + GMOCK_ARG_(tn, 1, __VA_ARGS__) gmock_a1, GMOCK_ARG_(tn, 2, \ + __VA_ARGS__) gmock_a2, GMOCK_ARG_(tn, 3, __VA_ARGS__) gmock_a3, \ + GMOCK_ARG_(tn, 4, __VA_ARGS__) gmock_a4) constness { \ + GMOCK_MOCKER_(4, constness, Method).SetOwnerAndName(this, #Method); \ + return GMOCK_MOCKER_(4, constness, \ + Method).Invoke(::std::forward(gmock_a1), \ + ::std::forward(gmock_a2), \ + ::std::forward(gmock_a3), \ + ::std::forward(gmock_a4)); \ + } \ + ::testing::MockSpec<__VA_ARGS__> \ + gmock_##Method(GMOCK_MATCHER_(tn, 1, __VA_ARGS__) gmock_a1, \ + GMOCK_MATCHER_(tn, 2, __VA_ARGS__) gmock_a2, \ + GMOCK_MATCHER_(tn, 3, __VA_ARGS__) gmock_a3, \ + GMOCK_MATCHER_(tn, 4, __VA_ARGS__) gmock_a4) constness { \ + GMOCK_MOCKER_(4, constness, Method).RegisterOwner(this); \ + return GMOCK_MOCKER_(4, constness, Method).With(gmock_a1, gmock_a2, \ + gmock_a3, gmock_a4); \ + } \ + ::testing::MockSpec<__VA_ARGS__> gmock_##Method( \ + const ::testing::internal::WithoutMatchers&, \ + constness ::testing::internal::Function<__VA_ARGS__>* ) const { \ + return ::testing::internal::AdjustConstness_##constness(this)-> \ + gmock_##Method(::testing::A(), \ + ::testing::A(), \ + ::testing::A(), \ + ::testing::A()); \ + } \ + mutable ::testing::FunctionMocker<__VA_ARGS__> GMOCK_MOCKER_(4, constness, \ + Method) + +// INTERNAL IMPLEMENTATION - DON'T USE IN USER CODE!!! +#define GMOCK_METHOD5_(tn, constness, ct, Method, ...) \ + static_assert(5 == \ + ::testing::internal::Function<__VA_ARGS__>::ArgumentCount, \ + "MOCK_METHOD must match argument count.");\ + GMOCK_RESULT_(tn, __VA_ARGS__) ct Method( \ + GMOCK_ARG_(tn, 1, __VA_ARGS__) gmock_a1, GMOCK_ARG_(tn, 2, \ + __VA_ARGS__) gmock_a2, GMOCK_ARG_(tn, 3, __VA_ARGS__) gmock_a3, \ + GMOCK_ARG_(tn, 4, __VA_ARGS__) gmock_a4, GMOCK_ARG_(tn, 5, \ + __VA_ARGS__) gmock_a5) constness { \ + GMOCK_MOCKER_(5, constness, Method).SetOwnerAndName(this, #Method); \ + return GMOCK_MOCKER_(5, constness, \ + Method).Invoke(::std::forward(gmock_a1), \ + ::std::forward(gmock_a2), \ + ::std::forward(gmock_a3), \ + ::std::forward(gmock_a4), \ + ::std::forward(gmock_a5)); \ + } \ + ::testing::MockSpec<__VA_ARGS__> \ + gmock_##Method(GMOCK_MATCHER_(tn, 1, __VA_ARGS__) gmock_a1, \ + GMOCK_MATCHER_(tn, 2, __VA_ARGS__) gmock_a2, \ + GMOCK_MATCHER_(tn, 3, __VA_ARGS__) gmock_a3, \ + GMOCK_MATCHER_(tn, 4, __VA_ARGS__) gmock_a4, \ + GMOCK_MATCHER_(tn, 5, __VA_ARGS__) gmock_a5) constness { \ + GMOCK_MOCKER_(5, constness, Method).RegisterOwner(this); \ + return GMOCK_MOCKER_(5, constness, Method).With(gmock_a1, gmock_a2, \ + gmock_a3, gmock_a4, gmock_a5); \ + } \ + ::testing::MockSpec<__VA_ARGS__> gmock_##Method( \ + const ::testing::internal::WithoutMatchers&, \ + constness ::testing::internal::Function<__VA_ARGS__>* ) const { \ + return ::testing::internal::AdjustConstness_##constness(this)-> \ + gmock_##Method(::testing::A(), \ + ::testing::A(), \ + ::testing::A(), \ + ::testing::A(), \ + ::testing::A()); \ + } \ + mutable ::testing::FunctionMocker<__VA_ARGS__> GMOCK_MOCKER_(5, constness, \ + Method) + +// INTERNAL IMPLEMENTATION - DON'T USE IN USER CODE!!! +#define GMOCK_METHOD6_(tn, constness, ct, Method, ...) \ + static_assert(6 == \ + ::testing::internal::Function<__VA_ARGS__>::ArgumentCount, \ + "MOCK_METHOD must match argument count.");\ + GMOCK_RESULT_(tn, __VA_ARGS__) ct Method( \ + GMOCK_ARG_(tn, 1, __VA_ARGS__) gmock_a1, GMOCK_ARG_(tn, 2, \ + __VA_ARGS__) gmock_a2, GMOCK_ARG_(tn, 3, __VA_ARGS__) gmock_a3, \ + GMOCK_ARG_(tn, 4, __VA_ARGS__) gmock_a4, GMOCK_ARG_(tn, 5, \ + __VA_ARGS__) gmock_a5, GMOCK_ARG_(tn, 6, \ + __VA_ARGS__) gmock_a6) constness { \ + GMOCK_MOCKER_(6, constness, Method).SetOwnerAndName(this, #Method); \ + return GMOCK_MOCKER_(6, constness, \ + Method).Invoke(::std::forward(gmock_a1), \ + ::std::forward(gmock_a2), \ + ::std::forward(gmock_a3), \ + ::std::forward(gmock_a4), \ + ::std::forward(gmock_a5), \ + ::std::forward(gmock_a6)); \ + } \ + ::testing::MockSpec<__VA_ARGS__> \ + gmock_##Method(GMOCK_MATCHER_(tn, 1, __VA_ARGS__) gmock_a1, \ + GMOCK_MATCHER_(tn, 2, __VA_ARGS__) gmock_a2, \ + GMOCK_MATCHER_(tn, 3, __VA_ARGS__) gmock_a3, \ + GMOCK_MATCHER_(tn, 4, __VA_ARGS__) gmock_a4, \ + GMOCK_MATCHER_(tn, 5, __VA_ARGS__) gmock_a5, \ + GMOCK_MATCHER_(tn, 6, __VA_ARGS__) gmock_a6) constness { \ + GMOCK_MOCKER_(6, constness, Method).RegisterOwner(this); \ + return GMOCK_MOCKER_(6, constness, Method).With(gmock_a1, gmock_a2, \ + gmock_a3, gmock_a4, gmock_a5, gmock_a6); \ + } \ + ::testing::MockSpec<__VA_ARGS__> gmock_##Method( \ + const ::testing::internal::WithoutMatchers&, \ + constness ::testing::internal::Function<__VA_ARGS__>* ) const { \ + return ::testing::internal::AdjustConstness_##constness(this)-> \ + gmock_##Method(::testing::A(), \ + ::testing::A(), \ + ::testing::A(), \ + ::testing::A(), \ + ::testing::A(), \ + ::testing::A()); \ + } \ + mutable ::testing::FunctionMocker<__VA_ARGS__> GMOCK_MOCKER_(6, constness, \ + Method) + +// INTERNAL IMPLEMENTATION - DON'T USE IN USER CODE!!! +#define GMOCK_METHOD7_(tn, constness, ct, Method, ...) \ + static_assert(7 == \ + ::testing::internal::Function<__VA_ARGS__>::ArgumentCount, \ + "MOCK_METHOD must match argument count.");\ + GMOCK_RESULT_(tn, __VA_ARGS__) ct Method( \ + GMOCK_ARG_(tn, 1, __VA_ARGS__) gmock_a1, GMOCK_ARG_(tn, 2, \ + __VA_ARGS__) gmock_a2, GMOCK_ARG_(tn, 3, __VA_ARGS__) gmock_a3, \ + GMOCK_ARG_(tn, 4, __VA_ARGS__) gmock_a4, GMOCK_ARG_(tn, 5, \ + __VA_ARGS__) gmock_a5, GMOCK_ARG_(tn, 6, __VA_ARGS__) gmock_a6, \ + GMOCK_ARG_(tn, 7, __VA_ARGS__) gmock_a7) constness { \ + GMOCK_MOCKER_(7, constness, Method).SetOwnerAndName(this, #Method); \ + return GMOCK_MOCKER_(7, constness, \ + Method).Invoke(::std::forward(gmock_a1), \ + ::std::forward(gmock_a2), \ + ::std::forward(gmock_a3), \ + ::std::forward(gmock_a4), \ + ::std::forward(gmock_a5), \ + ::std::forward(gmock_a6), \ + ::std::forward(gmock_a7)); \ + } \ + ::testing::MockSpec<__VA_ARGS__> \ + gmock_##Method(GMOCK_MATCHER_(tn, 1, __VA_ARGS__) gmock_a1, \ + GMOCK_MATCHER_(tn, 2, __VA_ARGS__) gmock_a2, \ + GMOCK_MATCHER_(tn, 3, __VA_ARGS__) gmock_a3, \ + GMOCK_MATCHER_(tn, 4, __VA_ARGS__) gmock_a4, \ + GMOCK_MATCHER_(tn, 5, __VA_ARGS__) gmock_a5, \ + GMOCK_MATCHER_(tn, 6, __VA_ARGS__) gmock_a6, \ + GMOCK_MATCHER_(tn, 7, __VA_ARGS__) gmock_a7) constness { \ + GMOCK_MOCKER_(7, constness, Method).RegisterOwner(this); \ + return GMOCK_MOCKER_(7, constness, Method).With(gmock_a1, gmock_a2, \ + gmock_a3, gmock_a4, gmock_a5, gmock_a6, gmock_a7); \ + } \ + ::testing::MockSpec<__VA_ARGS__> gmock_##Method( \ + const ::testing::internal::WithoutMatchers&, \ + constness ::testing::internal::Function<__VA_ARGS__>* ) const { \ + return ::testing::internal::AdjustConstness_##constness(this)-> \ + gmock_##Method(::testing::A(), \ + ::testing::A(), \ + ::testing::A(), \ + ::testing::A(), \ + ::testing::A(), \ + ::testing::A(), \ + ::testing::A()); \ + } \ + mutable ::testing::FunctionMocker<__VA_ARGS__> GMOCK_MOCKER_(7, constness, \ + Method) + +// INTERNAL IMPLEMENTATION - DON'T USE IN USER CODE!!! +#define GMOCK_METHOD8_(tn, constness, ct, Method, ...) \ + static_assert(8 == \ + ::testing::internal::Function<__VA_ARGS__>::ArgumentCount, \ + "MOCK_METHOD must match argument count.");\ + GMOCK_RESULT_(tn, __VA_ARGS__) ct Method( \ + GMOCK_ARG_(tn, 1, __VA_ARGS__) gmock_a1, GMOCK_ARG_(tn, 2, \ + __VA_ARGS__) gmock_a2, GMOCK_ARG_(tn, 3, __VA_ARGS__) gmock_a3, \ + GMOCK_ARG_(tn, 4, __VA_ARGS__) gmock_a4, GMOCK_ARG_(tn, 5, \ + __VA_ARGS__) gmock_a5, GMOCK_ARG_(tn, 6, __VA_ARGS__) gmock_a6, \ + GMOCK_ARG_(tn, 7, __VA_ARGS__) gmock_a7, GMOCK_ARG_(tn, 8, \ + __VA_ARGS__) gmock_a8) constness { \ + GMOCK_MOCKER_(8, constness, Method).SetOwnerAndName(this, #Method); \ + return GMOCK_MOCKER_(8, constness, \ + Method).Invoke(::std::forward(gmock_a1), \ + ::std::forward(gmock_a2), \ + ::std::forward(gmock_a3), \ + ::std::forward(gmock_a4), \ + ::std::forward(gmock_a5), \ + ::std::forward(gmock_a6), \ + ::std::forward(gmock_a7), \ + ::std::forward(gmock_a8)); \ + } \ + ::testing::MockSpec<__VA_ARGS__> \ + gmock_##Method(GMOCK_MATCHER_(tn, 1, __VA_ARGS__) gmock_a1, \ + GMOCK_MATCHER_(tn, 2, __VA_ARGS__) gmock_a2, \ + GMOCK_MATCHER_(tn, 3, __VA_ARGS__) gmock_a3, \ + GMOCK_MATCHER_(tn, 4, __VA_ARGS__) gmock_a4, \ + GMOCK_MATCHER_(tn, 5, __VA_ARGS__) gmock_a5, \ + GMOCK_MATCHER_(tn, 6, __VA_ARGS__) gmock_a6, \ + GMOCK_MATCHER_(tn, 7, __VA_ARGS__) gmock_a7, \ + GMOCK_MATCHER_(tn, 8, __VA_ARGS__) gmock_a8) constness { \ + GMOCK_MOCKER_(8, constness, Method).RegisterOwner(this); \ + return GMOCK_MOCKER_(8, constness, Method).With(gmock_a1, gmock_a2, \ + gmock_a3, gmock_a4, gmock_a5, gmock_a6, gmock_a7, gmock_a8); \ + } \ + ::testing::MockSpec<__VA_ARGS__> gmock_##Method( \ + const ::testing::internal::WithoutMatchers&, \ + constness ::testing::internal::Function<__VA_ARGS__>* ) const { \ + return ::testing::internal::AdjustConstness_##constness(this)-> \ + gmock_##Method(::testing::A(), \ + ::testing::A(), \ + ::testing::A(), \ + ::testing::A(), \ + ::testing::A(), \ + ::testing::A(), \ + ::testing::A(), \ + ::testing::A()); \ + } \ + mutable ::testing::FunctionMocker<__VA_ARGS__> GMOCK_MOCKER_(8, constness, \ + Method) + +// INTERNAL IMPLEMENTATION - DON'T USE IN USER CODE!!! +#define GMOCK_METHOD9_(tn, constness, ct, Method, ...) \ + static_assert(9 == \ + ::testing::internal::Function<__VA_ARGS__>::ArgumentCount, \ + "MOCK_METHOD must match argument count.");\ + GMOCK_RESULT_(tn, __VA_ARGS__) ct Method( \ + GMOCK_ARG_(tn, 1, __VA_ARGS__) gmock_a1, GMOCK_ARG_(tn, 2, \ + __VA_ARGS__) gmock_a2, GMOCK_ARG_(tn, 3, __VA_ARGS__) gmock_a3, \ + GMOCK_ARG_(tn, 4, __VA_ARGS__) gmock_a4, GMOCK_ARG_(tn, 5, \ + __VA_ARGS__) gmock_a5, GMOCK_ARG_(tn, 6, __VA_ARGS__) gmock_a6, \ + GMOCK_ARG_(tn, 7, __VA_ARGS__) gmock_a7, GMOCK_ARG_(tn, 8, \ + __VA_ARGS__) gmock_a8, GMOCK_ARG_(tn, 9, \ + __VA_ARGS__) gmock_a9) constness { \ + GMOCK_MOCKER_(9, constness, Method).SetOwnerAndName(this, #Method); \ + return GMOCK_MOCKER_(9, constness, \ + Method).Invoke(::std::forward(gmock_a1), \ + ::std::forward(gmock_a2), \ + ::std::forward(gmock_a3), \ + ::std::forward(gmock_a4), \ + ::std::forward(gmock_a5), \ + ::std::forward(gmock_a6), \ + ::std::forward(gmock_a7), \ + ::std::forward(gmock_a8), \ + ::std::forward(gmock_a9)); \ + } \ + ::testing::MockSpec<__VA_ARGS__> \ + gmock_##Method(GMOCK_MATCHER_(tn, 1, __VA_ARGS__) gmock_a1, \ + GMOCK_MATCHER_(tn, 2, __VA_ARGS__) gmock_a2, \ + GMOCK_MATCHER_(tn, 3, __VA_ARGS__) gmock_a3, \ + GMOCK_MATCHER_(tn, 4, __VA_ARGS__) gmock_a4, \ + GMOCK_MATCHER_(tn, 5, __VA_ARGS__) gmock_a5, \ + GMOCK_MATCHER_(tn, 6, __VA_ARGS__) gmock_a6, \ + GMOCK_MATCHER_(tn, 7, __VA_ARGS__) gmock_a7, \ + GMOCK_MATCHER_(tn, 8, __VA_ARGS__) gmock_a8, \ + GMOCK_MATCHER_(tn, 9, __VA_ARGS__) gmock_a9) constness { \ + GMOCK_MOCKER_(9, constness, Method).RegisterOwner(this); \ + return GMOCK_MOCKER_(9, constness, Method).With(gmock_a1, gmock_a2, \ + gmock_a3, gmock_a4, gmock_a5, gmock_a6, gmock_a7, gmock_a8, \ + gmock_a9); \ + } \ + ::testing::MockSpec<__VA_ARGS__> gmock_##Method( \ + const ::testing::internal::WithoutMatchers&, \ + constness ::testing::internal::Function<__VA_ARGS__>* ) const { \ + return ::testing::internal::AdjustConstness_##constness(this)-> \ + gmock_##Method(::testing::A(), \ + ::testing::A(), \ + ::testing::A(), \ + ::testing::A(), \ + ::testing::A(), \ + ::testing::A(), \ + ::testing::A(), \ + ::testing::A(), \ + ::testing::A()); \ + } \ + mutable ::testing::FunctionMocker<__VA_ARGS__> GMOCK_MOCKER_(9, constness, \ + Method) + +// INTERNAL IMPLEMENTATION - DON'T USE IN USER CODE!!! +#define GMOCK_METHOD10_(tn, constness, ct, Method, ...) \ + static_assert(10 == \ + ::testing::internal::Function<__VA_ARGS__>::ArgumentCount, \ + "MOCK_METHOD must match argument count.");\ + GMOCK_RESULT_(tn, __VA_ARGS__) ct Method( \ + GMOCK_ARG_(tn, 1, __VA_ARGS__) gmock_a1, GMOCK_ARG_(tn, 2, \ + __VA_ARGS__) gmock_a2, GMOCK_ARG_(tn, 3, __VA_ARGS__) gmock_a3, \ + GMOCK_ARG_(tn, 4, __VA_ARGS__) gmock_a4, GMOCK_ARG_(tn, 5, \ + __VA_ARGS__) gmock_a5, GMOCK_ARG_(tn, 6, __VA_ARGS__) gmock_a6, \ + GMOCK_ARG_(tn, 7, __VA_ARGS__) gmock_a7, GMOCK_ARG_(tn, 8, \ + __VA_ARGS__) gmock_a8, GMOCK_ARG_(tn, 9, __VA_ARGS__) gmock_a9, \ + GMOCK_ARG_(tn, 10, __VA_ARGS__) gmock_a10) constness { \ + GMOCK_MOCKER_(10, constness, Method).SetOwnerAndName(this, #Method); \ + return GMOCK_MOCKER_(10, constness, \ + Method).Invoke(::std::forward(gmock_a1), \ + ::std::forward(gmock_a2), \ + ::std::forward(gmock_a3), \ + ::std::forward(gmock_a4), \ + ::std::forward(gmock_a5), \ + ::std::forward(gmock_a6), \ + ::std::forward(gmock_a7), \ + ::std::forward(gmock_a8), \ + ::std::forward(gmock_a9), \ + ::std::forward(gmock_a10)); \ + } \ + ::testing::MockSpec<__VA_ARGS__> \ + gmock_##Method(GMOCK_MATCHER_(tn, 1, __VA_ARGS__) gmock_a1, \ + GMOCK_MATCHER_(tn, 2, __VA_ARGS__) gmock_a2, \ + GMOCK_MATCHER_(tn, 3, __VA_ARGS__) gmock_a3, \ + GMOCK_MATCHER_(tn, 4, __VA_ARGS__) gmock_a4, \ + GMOCK_MATCHER_(tn, 5, __VA_ARGS__) gmock_a5, \ + GMOCK_MATCHER_(tn, 6, __VA_ARGS__) gmock_a6, \ + GMOCK_MATCHER_(tn, 7, __VA_ARGS__) gmock_a7, \ + GMOCK_MATCHER_(tn, 8, __VA_ARGS__) gmock_a8, \ + GMOCK_MATCHER_(tn, 9, __VA_ARGS__) gmock_a9, \ + GMOCK_MATCHER_(tn, 10, \ + __VA_ARGS__) gmock_a10) constness { \ + GMOCK_MOCKER_(10, constness, Method).RegisterOwner(this); \ + return GMOCK_MOCKER_(10, constness, Method).With(gmock_a1, gmock_a2, \ + gmock_a3, gmock_a4, gmock_a5, gmock_a6, gmock_a7, gmock_a8, gmock_a9, \ + gmock_a10); \ + } \ + ::testing::MockSpec<__VA_ARGS__> gmock_##Method( \ + const ::testing::internal::WithoutMatchers&, \ + constness ::testing::internal::Function<__VA_ARGS__>* ) const { \ + return ::testing::internal::AdjustConstness_##constness(this)-> \ + gmock_##Method(::testing::A(), \ + ::testing::A(), \ + ::testing::A(), \ + ::testing::A(), \ + ::testing::A(), \ + ::testing::A(), \ + ::testing::A(), \ + ::testing::A(), \ + ::testing::A(), \ + ::testing::A()); \ + } \ + mutable ::testing::FunctionMocker<__VA_ARGS__> GMOCK_MOCKER_(10, constness, \ + Method) + +#define MOCK_METHOD0(m, ...) GMOCK_METHOD0_(, , , m, __VA_ARGS__) +#define MOCK_METHOD1(m, ...) GMOCK_METHOD1_(, , , m, __VA_ARGS__) +#define MOCK_METHOD2(m, ...) GMOCK_METHOD2_(, , , m, __VA_ARGS__) +#define MOCK_METHOD3(m, ...) GMOCK_METHOD3_(, , , m, __VA_ARGS__) +#define MOCK_METHOD4(m, ...) GMOCK_METHOD4_(, , , m, __VA_ARGS__) +#define MOCK_METHOD5(m, ...) GMOCK_METHOD5_(, , , m, __VA_ARGS__) +#define MOCK_METHOD6(m, ...) GMOCK_METHOD6_(, , , m, __VA_ARGS__) +#define MOCK_METHOD7(m, ...) GMOCK_METHOD7_(, , , m, __VA_ARGS__) +#define MOCK_METHOD8(m, ...) GMOCK_METHOD8_(, , , m, __VA_ARGS__) +#define MOCK_METHOD9(m, ...) GMOCK_METHOD9_(, , , m, __VA_ARGS__) +#define MOCK_METHOD10(m, ...) GMOCK_METHOD10_(, , , m, __VA_ARGS__) + +#define MOCK_CONST_METHOD0(m, ...) GMOCK_METHOD0_(, const, , m, __VA_ARGS__) +#define MOCK_CONST_METHOD1(m, ...) GMOCK_METHOD1_(, const, , m, __VA_ARGS__) +#define MOCK_CONST_METHOD2(m, ...) GMOCK_METHOD2_(, const, , m, __VA_ARGS__) +#define MOCK_CONST_METHOD3(m, ...) GMOCK_METHOD3_(, const, , m, __VA_ARGS__) +#define MOCK_CONST_METHOD4(m, ...) GMOCK_METHOD4_(, const, , m, __VA_ARGS__) +#define MOCK_CONST_METHOD5(m, ...) GMOCK_METHOD5_(, const, , m, __VA_ARGS__) +#define MOCK_CONST_METHOD6(m, ...) GMOCK_METHOD6_(, const, , m, __VA_ARGS__) +#define MOCK_CONST_METHOD7(m, ...) GMOCK_METHOD7_(, const, , m, __VA_ARGS__) +#define MOCK_CONST_METHOD8(m, ...) GMOCK_METHOD8_(, const, , m, __VA_ARGS__) +#define MOCK_CONST_METHOD9(m, ...) GMOCK_METHOD9_(, const, , m, __VA_ARGS__) +#define MOCK_CONST_METHOD10(m, ...) GMOCK_METHOD10_(, const, , m, __VA_ARGS__) + +#define MOCK_METHOD0_T(m, ...) GMOCK_METHOD0_(typename, , , m, __VA_ARGS__) +#define MOCK_METHOD1_T(m, ...) GMOCK_METHOD1_(typename, , , m, __VA_ARGS__) +#define MOCK_METHOD2_T(m, ...) GMOCK_METHOD2_(typename, , , m, __VA_ARGS__) +#define MOCK_METHOD3_T(m, ...) GMOCK_METHOD3_(typename, , , m, __VA_ARGS__) +#define MOCK_METHOD4_T(m, ...) GMOCK_METHOD4_(typename, , , m, __VA_ARGS__) +#define MOCK_METHOD5_T(m, ...) GMOCK_METHOD5_(typename, , , m, __VA_ARGS__) +#define MOCK_METHOD6_T(m, ...) GMOCK_METHOD6_(typename, , , m, __VA_ARGS__) +#define MOCK_METHOD7_T(m, ...) GMOCK_METHOD7_(typename, , , m, __VA_ARGS__) +#define MOCK_METHOD8_T(m, ...) GMOCK_METHOD8_(typename, , , m, __VA_ARGS__) +#define MOCK_METHOD9_T(m, ...) GMOCK_METHOD9_(typename, , , m, __VA_ARGS__) +#define MOCK_METHOD10_T(m, ...) GMOCK_METHOD10_(typename, , , m, __VA_ARGS__) + +#define MOCK_CONST_METHOD0_T(m, ...) \ + GMOCK_METHOD0_(typename, const, , m, __VA_ARGS__) +#define MOCK_CONST_METHOD1_T(m, ...) \ + GMOCK_METHOD1_(typename, const, , m, __VA_ARGS__) +#define MOCK_CONST_METHOD2_T(m, ...) \ + GMOCK_METHOD2_(typename, const, , m, __VA_ARGS__) +#define MOCK_CONST_METHOD3_T(m, ...) \ + GMOCK_METHOD3_(typename, const, , m, __VA_ARGS__) +#define MOCK_CONST_METHOD4_T(m, ...) \ + GMOCK_METHOD4_(typename, const, , m, __VA_ARGS__) +#define MOCK_CONST_METHOD5_T(m, ...) \ + GMOCK_METHOD5_(typename, const, , m, __VA_ARGS__) +#define MOCK_CONST_METHOD6_T(m, ...) \ + GMOCK_METHOD6_(typename, const, , m, __VA_ARGS__) +#define MOCK_CONST_METHOD7_T(m, ...) \ + GMOCK_METHOD7_(typename, const, , m, __VA_ARGS__) +#define MOCK_CONST_METHOD8_T(m, ...) \ + GMOCK_METHOD8_(typename, const, , m, __VA_ARGS__) +#define MOCK_CONST_METHOD9_T(m, ...) \ + GMOCK_METHOD9_(typename, const, , m, __VA_ARGS__) +#define MOCK_CONST_METHOD10_T(m, ...) \ + GMOCK_METHOD10_(typename, const, , m, __VA_ARGS__) + +#define MOCK_METHOD0_WITH_CALLTYPE(ct, m, ...) \ + GMOCK_METHOD0_(, , ct, m, __VA_ARGS__) +#define MOCK_METHOD1_WITH_CALLTYPE(ct, m, ...) \ + GMOCK_METHOD1_(, , ct, m, __VA_ARGS__) +#define MOCK_METHOD2_WITH_CALLTYPE(ct, m, ...) \ + GMOCK_METHOD2_(, , ct, m, __VA_ARGS__) +#define MOCK_METHOD3_WITH_CALLTYPE(ct, m, ...) \ + GMOCK_METHOD3_(, , ct, m, __VA_ARGS__) +#define MOCK_METHOD4_WITH_CALLTYPE(ct, m, ...) \ + GMOCK_METHOD4_(, , ct, m, __VA_ARGS__) +#define MOCK_METHOD5_WITH_CALLTYPE(ct, m, ...) \ + GMOCK_METHOD5_(, , ct, m, __VA_ARGS__) +#define MOCK_METHOD6_WITH_CALLTYPE(ct, m, ...) \ + GMOCK_METHOD6_(, , ct, m, __VA_ARGS__) +#define MOCK_METHOD7_WITH_CALLTYPE(ct, m, ...) \ + GMOCK_METHOD7_(, , ct, m, __VA_ARGS__) +#define MOCK_METHOD8_WITH_CALLTYPE(ct, m, ...) \ + GMOCK_METHOD8_(, , ct, m, __VA_ARGS__) +#define MOCK_METHOD9_WITH_CALLTYPE(ct, m, ...) \ + GMOCK_METHOD9_(, , ct, m, __VA_ARGS__) +#define MOCK_METHOD10_WITH_CALLTYPE(ct, m, ...) \ + GMOCK_METHOD10_(, , ct, m, __VA_ARGS__) + +#define MOCK_CONST_METHOD0_WITH_CALLTYPE(ct, m, ...) \ + GMOCK_METHOD0_(, const, ct, m, __VA_ARGS__) +#define MOCK_CONST_METHOD1_WITH_CALLTYPE(ct, m, ...) \ + GMOCK_METHOD1_(, const, ct, m, __VA_ARGS__) +#define MOCK_CONST_METHOD2_WITH_CALLTYPE(ct, m, ...) \ + GMOCK_METHOD2_(, const, ct, m, __VA_ARGS__) +#define MOCK_CONST_METHOD3_WITH_CALLTYPE(ct, m, ...) \ + GMOCK_METHOD3_(, const, ct, m, __VA_ARGS__) +#define MOCK_CONST_METHOD4_WITH_CALLTYPE(ct, m, ...) \ + GMOCK_METHOD4_(, const, ct, m, __VA_ARGS__) +#define MOCK_CONST_METHOD5_WITH_CALLTYPE(ct, m, ...) \ + GMOCK_METHOD5_(, const, ct, m, __VA_ARGS__) +#define MOCK_CONST_METHOD6_WITH_CALLTYPE(ct, m, ...) \ + GMOCK_METHOD6_(, const, ct, m, __VA_ARGS__) +#define MOCK_CONST_METHOD7_WITH_CALLTYPE(ct, m, ...) \ + GMOCK_METHOD7_(, const, ct, m, __VA_ARGS__) +#define MOCK_CONST_METHOD8_WITH_CALLTYPE(ct, m, ...) \ + GMOCK_METHOD8_(, const, ct, m, __VA_ARGS__) +#define MOCK_CONST_METHOD9_WITH_CALLTYPE(ct, m, ...) \ + GMOCK_METHOD9_(, const, ct, m, __VA_ARGS__) +#define MOCK_CONST_METHOD10_WITH_CALLTYPE(ct, m, ...) \ + GMOCK_METHOD10_(, const, ct, m, __VA_ARGS__) + +#define MOCK_METHOD0_T_WITH_CALLTYPE(ct, m, ...) \ + GMOCK_METHOD0_(typename, , ct, m, __VA_ARGS__) +#define MOCK_METHOD1_T_WITH_CALLTYPE(ct, m, ...) \ + GMOCK_METHOD1_(typename, , ct, m, __VA_ARGS__) +#define MOCK_METHOD2_T_WITH_CALLTYPE(ct, m, ...) \ + GMOCK_METHOD2_(typename, , ct, m, __VA_ARGS__) +#define MOCK_METHOD3_T_WITH_CALLTYPE(ct, m, ...) \ + GMOCK_METHOD3_(typename, , ct, m, __VA_ARGS__) +#define MOCK_METHOD4_T_WITH_CALLTYPE(ct, m, ...) \ + GMOCK_METHOD4_(typename, , ct, m, __VA_ARGS__) +#define MOCK_METHOD5_T_WITH_CALLTYPE(ct, m, ...) \ + GMOCK_METHOD5_(typename, , ct, m, __VA_ARGS__) +#define MOCK_METHOD6_T_WITH_CALLTYPE(ct, m, ...) \ + GMOCK_METHOD6_(typename, , ct, m, __VA_ARGS__) +#define MOCK_METHOD7_T_WITH_CALLTYPE(ct, m, ...) \ + GMOCK_METHOD7_(typename, , ct, m, __VA_ARGS__) +#define MOCK_METHOD8_T_WITH_CALLTYPE(ct, m, ...) \ + GMOCK_METHOD8_(typename, , ct, m, __VA_ARGS__) +#define MOCK_METHOD9_T_WITH_CALLTYPE(ct, m, ...) \ + GMOCK_METHOD9_(typename, , ct, m, __VA_ARGS__) +#define MOCK_METHOD10_T_WITH_CALLTYPE(ct, m, ...) \ + GMOCK_METHOD10_(typename, , ct, m, __VA_ARGS__) + +#define MOCK_CONST_METHOD0_T_WITH_CALLTYPE(ct, m, ...) \ + GMOCK_METHOD0_(typename, const, ct, m, __VA_ARGS__) +#define MOCK_CONST_METHOD1_T_WITH_CALLTYPE(ct, m, ...) \ + GMOCK_METHOD1_(typename, const, ct, m, __VA_ARGS__) +#define MOCK_CONST_METHOD2_T_WITH_CALLTYPE(ct, m, ...) \ + GMOCK_METHOD2_(typename, const, ct, m, __VA_ARGS__) +#define MOCK_CONST_METHOD3_T_WITH_CALLTYPE(ct, m, ...) \ + GMOCK_METHOD3_(typename, const, ct, m, __VA_ARGS__) +#define MOCK_CONST_METHOD4_T_WITH_CALLTYPE(ct, m, ...) \ + GMOCK_METHOD4_(typename, const, ct, m, __VA_ARGS__) +#define MOCK_CONST_METHOD5_T_WITH_CALLTYPE(ct, m, ...) \ + GMOCK_METHOD5_(typename, const, ct, m, __VA_ARGS__) +#define MOCK_CONST_METHOD6_T_WITH_CALLTYPE(ct, m, ...) \ + GMOCK_METHOD6_(typename, const, ct, m, __VA_ARGS__) +#define MOCK_CONST_METHOD7_T_WITH_CALLTYPE(ct, m, ...) \ + GMOCK_METHOD7_(typename, const, ct, m, __VA_ARGS__) +#define MOCK_CONST_METHOD8_T_WITH_CALLTYPE(ct, m, ...) \ + GMOCK_METHOD8_(typename, const, ct, m, __VA_ARGS__) +#define MOCK_CONST_METHOD9_T_WITH_CALLTYPE(ct, m, ...) \ + GMOCK_METHOD9_(typename, const, ct, m, __VA_ARGS__) +#define MOCK_CONST_METHOD10_T_WITH_CALLTYPE(ct, m, ...) \ + GMOCK_METHOD10_(typename, const, ct, m, __VA_ARGS__) + +} // namespace testing + +#endif // GMOCK_INCLUDE_GMOCK_GMOCK_GENERATED_FUNCTION_MOCKERS_H_ diff --git a/googlemock/include/gmock/gmock-generated-function-mockers.h.pump b/googlemock/include/gmock/gmock-generated-function-mockers.h.pump new file mode 100644 index 00000000..a56e132f --- /dev/null +++ b/googlemock/include/gmock/gmock-generated-function-mockers.h.pump @@ -0,0 +1,227 @@ +$$ -*- mode: c++; -*- +$$ This is a Pump source file. Please use Pump to convert +$$ it to gmock-generated-function-mockers.h. +$$ +$var n = 10 $$ The maximum arity we support. +// Copyright 2007, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + +// Google Mock - a framework for writing C++ mock classes. +// +// This file implements function mockers of various arities. + +// GOOGLETEST_CM0002 DO NOT DELETE + +#ifndef GMOCK_INCLUDE_GMOCK_GMOCK_GENERATED_FUNCTION_MOCKERS_H_ +#define GMOCK_INCLUDE_GMOCK_GMOCK_GENERATED_FUNCTION_MOCKERS_H_ + +#include +#include + +#include "gmock/gmock-spec-builders.h" +#include "gmock/internal/gmock-internal-utils.h" + +namespace testing { +namespace internal { + +$range i 0..n +// Removes the given pointer; this is a helper for the expectation setter method +// for parameterless matchers. +// +// We want to make sure that the user cannot set a parameterless expectation on +// overloaded methods, including methods which are overloaded on const. Example: +// +// class MockClass { +// MOCK_METHOD0(GetName, string&()); +// MOCK_CONST_METHOD0(GetName, const string&()); +// }; +// +// TEST() { +// // This should be an error, as it's not clear which overload is expected. +// EXPECT_CALL(mock, GetName).WillOnce(ReturnRef(value)); +// } +// +// Here are the generated expectation-setter methods: +// +// class MockClass { +// // Overload 1 +// MockSpec gmock_GetName() { ... } +// // Overload 2. Declared const so that the compiler will generate an +// // error when trying to resolve between this and overload 4 in +// // 'gmock_GetName(WithoutMatchers(), nullptr)'. +// MockSpec gmock_GetName( +// const WithoutMatchers&, const Function*) const { +// // Removes const from this, calls overload 1 +// return AdjustConstness_(this)->gmock_GetName(); +// } +// +// // Overload 3 +// const string& gmock_GetName() const { ... } +// // Overload 4 +// MockSpec gmock_GetName( +// const WithoutMatchers&, const Function*) const { +// // Does not remove const, calls overload 3 +// return AdjustConstness_const(this)->gmock_GetName(); +// } +// } +// +template +const MockType* AdjustConstness_const(const MockType* mock) { + return mock; +} + +// Removes const from and returns the given pointer; this is a helper for the +// expectation setter method for parameterless matchers. +template +MockType* AdjustConstness_(const MockType* mock) { + return const_cast(mock); +} + +} // namespace internal + +// The style guide prohibits "using" statements in a namespace scope +// inside a header file. However, the FunctionMocker class template +// is meant to be defined in the ::testing namespace. The following +// line is just a trick for working around a bug in MSVC 8.0, which +// cannot handle it if we define FunctionMocker in ::testing. +using internal::FunctionMocker; + +// GMOCK_RESULT_(tn, F) expands to the result type of function type F. +// We define this as a variadic macro in case F contains unprotected +// commas (the same reason that we use variadic macros in other places +// in this file). +// INTERNAL IMPLEMENTATION - DON'T USE IN USER CODE!!! +#define GMOCK_RESULT_(tn, ...) \ + tn ::testing::internal::Function<__VA_ARGS__>::Result + +// The type of argument N of the given function type. +// INTERNAL IMPLEMENTATION - DON'T USE IN USER CODE!!! +#define GMOCK_ARG_(tn, N, ...) \ + tn ::testing::internal::Function<__VA_ARGS__>::template Arg::type + +// The matcher type for argument N of the given function type. +// INTERNAL IMPLEMENTATION - DON'T USE IN USER CODE!!! +#define GMOCK_MATCHER_(tn, N, ...) \ + const ::testing::Matcher& + +// The variable for mocking the given method. +// INTERNAL IMPLEMENTATION - DON'T USE IN USER CODE!!! +#define GMOCK_MOCKER_(arity, constness, Method) \ + GTEST_CONCAT_TOKEN_(gmock##constness##arity##_##Method##_, __LINE__) + + +$for i [[ +$range j 1..i +$var arg_as = [[$for j, [[GMOCK_ARG_(tn, $j, __VA_ARGS__) gmock_a$j]]]] +$var as = [[$for j, \ + [[::std::forward(gmock_a$j)]]]] +$var matcher_arg_as = [[$for j, \ + [[GMOCK_MATCHER_(tn, $j, __VA_ARGS__) gmock_a$j]]]] +$var matcher_as = [[$for j, [[gmock_a$j]]]] +$var anything_matchers = [[$for j, \ + [[::testing::A()]]]] +// INTERNAL IMPLEMENTATION - DON'T USE IN USER CODE!!! +#define GMOCK_METHOD$i[[]]_(tn, constness, ct, Method, ...) \ + static_assert($i == ::testing::internal::Function<__VA_ARGS__>::ArgumentCount, "MOCK_METHOD must match argument count.");\ + GMOCK_RESULT_(tn, __VA_ARGS__) ct Method( \ + $arg_as) constness { \ + GMOCK_MOCKER_($i, constness, Method).SetOwnerAndName(this, #Method); \ + return GMOCK_MOCKER_($i, constness, Method).Invoke($as); \ + } \ + ::testing::MockSpec<__VA_ARGS__> \ + gmock_##Method($matcher_arg_as) constness { \ + GMOCK_MOCKER_($i, constness, Method).RegisterOwner(this); \ + return GMOCK_MOCKER_($i, constness, Method).With($matcher_as); \ + } \ + ::testing::MockSpec<__VA_ARGS__> gmock_##Method( \ + const ::testing::internal::WithoutMatchers&, \ + constness ::testing::internal::Function<__VA_ARGS__>* ) const { \ + return ::testing::internal::AdjustConstness_##constness(this)-> \ + gmock_##Method($anything_matchers); \ + } \ + mutable ::testing::FunctionMocker<__VA_ARGS__> GMOCK_MOCKER_($i, constness, Method) + + +]] +$for i [[ +#define MOCK_METHOD$i(m, ...) GMOCK_METHOD$i[[]]_(, , , m, __VA_ARGS__) + +]] + + +$for i [[ +#define MOCK_CONST_METHOD$i(m, ...) GMOCK_METHOD$i[[]]_(, const, , m, __VA_ARGS__) + +]] + + +$for i [[ +#define MOCK_METHOD$i[[]]_T(m, ...) GMOCK_METHOD$i[[]]_(typename, , , m, __VA_ARGS__) + +]] + + +$for i [[ +#define MOCK_CONST_METHOD$i[[]]_T(m, ...) \ + GMOCK_METHOD$i[[]]_(typename, const, , m, __VA_ARGS__) + +]] + + +$for i [[ +#define MOCK_METHOD$i[[]]_WITH_CALLTYPE(ct, m, ...) \ + GMOCK_METHOD$i[[]]_(, , ct, m, __VA_ARGS__) + +]] + + +$for i [[ +#define MOCK_CONST_METHOD$i[[]]_WITH_CALLTYPE(ct, m, ...) \ + GMOCK_METHOD$i[[]]_(, const, ct, m, __VA_ARGS__) + +]] + + +$for i [[ +#define MOCK_METHOD$i[[]]_T_WITH_CALLTYPE(ct, m, ...) \ + GMOCK_METHOD$i[[]]_(typename, , ct, m, __VA_ARGS__) + +]] + + +$for i [[ +#define MOCK_CONST_METHOD$i[[]]_T_WITH_CALLTYPE(ct, m, ...) \ + GMOCK_METHOD$i[[]]_(typename, const, ct, m, __VA_ARGS__) + +]] + +} // namespace testing + +#endif // GMOCK_INCLUDE_GMOCK_GMOCK_GENERATED_FUNCTION_MOCKERS_H_ diff --git a/googlemock/include/gmock/gmock-generated-matchers.h b/googlemock/include/gmock/gmock-generated-matchers.h new file mode 100644 index 00000000..690a57f1 --- /dev/null +++ b/googlemock/include/gmock/gmock-generated-matchers.h @@ -0,0 +1,1097 @@ +// This file was GENERATED by command: +// pump.py gmock-generated-matchers.h.pump +// DO NOT EDIT BY HAND!!! + +// Copyright 2008, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// Google Mock - a framework for writing C++ mock classes. +// +// This file implements some commonly used variadic matchers. + +// GOOGLETEST_CM0002 DO NOT DELETE + +#ifndef GMOCK_INCLUDE_GMOCK_GMOCK_GENERATED_MATCHERS_H_ +#define GMOCK_INCLUDE_GMOCK_GMOCK_GENERATED_MATCHERS_H_ + +#include +#include +#include +#include +#include +#include "gmock/gmock-matchers.h" + +// The MATCHER* family of macros can be used in a namespace scope to +// define custom matchers easily. +// +// Basic Usage +// =========== +// +// The syntax +// +// MATCHER(name, description_string) { statements; } +// +// defines a matcher with the given name that executes the statements, +// which must return a bool to indicate if the match succeeds. Inside +// the statements, you can refer to the value being matched by 'arg', +// and refer to its type by 'arg_type'. +// +// The description string documents what the matcher does, and is used +// to generate the failure message when the match fails. Since a +// MATCHER() is usually defined in a header file shared by multiple +// C++ source files, we require the description to be a C-string +// literal to avoid possible side effects. It can be empty, in which +// case we'll use the sequence of words in the matcher name as the +// description. +// +// For example: +// +// MATCHER(IsEven, "") { return (arg % 2) == 0; } +// +// allows you to write +// +// // Expects mock_foo.Bar(n) to be called where n is even. +// EXPECT_CALL(mock_foo, Bar(IsEven())); +// +// or, +// +// // Verifies that the value of some_expression is even. +// EXPECT_THAT(some_expression, IsEven()); +// +// If the above assertion fails, it will print something like: +// +// Value of: some_expression +// Expected: is even +// Actual: 7 +// +// where the description "is even" is automatically calculated from the +// matcher name IsEven. +// +// Argument Type +// ============= +// +// Note that the type of the value being matched (arg_type) is +// determined by the context in which you use the matcher and is +// supplied to you by the compiler, so you don't need to worry about +// declaring it (nor can you). This allows the matcher to be +// polymorphic. For example, IsEven() can be used to match any type +// where the value of "(arg % 2) == 0" can be implicitly converted to +// a bool. In the "Bar(IsEven())" example above, if method Bar() +// takes an int, 'arg_type' will be int; if it takes an unsigned long, +// 'arg_type' will be unsigned long; and so on. +// +// Parameterizing Matchers +// ======================= +// +// Sometimes you'll want to parameterize the matcher. For that you +// can use another macro: +// +// MATCHER_P(name, param_name, description_string) { statements; } +// +// For example: +// +// MATCHER_P(HasAbsoluteValue, value, "") { return abs(arg) == value; } +// +// will allow you to write: +// +// EXPECT_THAT(Blah("a"), HasAbsoluteValue(n)); +// +// which may lead to this message (assuming n is 10): +// +// Value of: Blah("a") +// Expected: has absolute value 10 +// Actual: -9 +// +// Note that both the matcher description and its parameter are +// printed, making the message human-friendly. +// +// In the matcher definition body, you can write 'foo_type' to +// reference the type of a parameter named 'foo'. For example, in the +// body of MATCHER_P(HasAbsoluteValue, value) above, you can write +// 'value_type' to refer to the type of 'value'. +// +// We also provide MATCHER_P2, MATCHER_P3, ..., up to MATCHER_P10 to +// support multi-parameter matchers. +// +// Describing Parameterized Matchers +// ================================= +// +// The last argument to MATCHER*() is a string-typed expression. The +// expression can reference all of the matcher's parameters and a +// special bool-typed variable named 'negation'. When 'negation' is +// false, the expression should evaluate to the matcher's description; +// otherwise it should evaluate to the description of the negation of +// the matcher. For example, +// +// using testing::PrintToString; +// +// MATCHER_P2(InClosedRange, low, hi, +// std::string(negation ? "is not" : "is") + " in range [" + +// PrintToString(low) + ", " + PrintToString(hi) + "]") { +// return low <= arg && arg <= hi; +// } +// ... +// EXPECT_THAT(3, InClosedRange(4, 6)); +// EXPECT_THAT(3, Not(InClosedRange(2, 4))); +// +// would generate two failures that contain the text: +// +// Expected: is in range [4, 6] +// ... +// Expected: is not in range [2, 4] +// +// If you specify "" as the description, the failure message will +// contain the sequence of words in the matcher name followed by the +// parameter values printed as a tuple. For example, +// +// MATCHER_P2(InClosedRange, low, hi, "") { ... } +// ... +// EXPECT_THAT(3, InClosedRange(4, 6)); +// EXPECT_THAT(3, Not(InClosedRange(2, 4))); +// +// would generate two failures that contain the text: +// +// Expected: in closed range (4, 6) +// ... +// Expected: not (in closed range (2, 4)) +// +// Types of Matcher Parameters +// =========================== +// +// For the purpose of typing, you can view +// +// MATCHER_Pk(Foo, p1, ..., pk, description_string) { ... } +// +// as shorthand for +// +// template +// FooMatcherPk +// Foo(p1_type p1, ..., pk_type pk) { ... } +// +// When you write Foo(v1, ..., vk), the compiler infers the types of +// the parameters v1, ..., and vk for you. If you are not happy with +// the result of the type inference, you can specify the types by +// explicitly instantiating the template, as in Foo(5, +// false). As said earlier, you don't get to (or need to) specify +// 'arg_type' as that's determined by the context in which the matcher +// is used. You can assign the result of expression Foo(p1, ..., pk) +// to a variable of type FooMatcherPk. This +// can be useful when composing matchers. +// +// While you can instantiate a matcher template with reference types, +// passing the parameters by pointer usually makes your code more +// readable. If, however, you still want to pass a parameter by +// reference, be aware that in the failure message generated by the +// matcher you will see the value of the referenced object but not its +// address. +// +// Explaining Match Results +// ======================== +// +// Sometimes the matcher description alone isn't enough to explain why +// the match has failed or succeeded. For example, when expecting a +// long string, it can be very helpful to also print the diff between +// the expected string and the actual one. To achieve that, you can +// optionally stream additional information to a special variable +// named result_listener, whose type is a pointer to class +// MatchResultListener: +// +// MATCHER_P(EqualsLongString, str, "") { +// if (arg == str) return true; +// +// *result_listener << "the difference: " +/// << DiffStrings(str, arg); +// return false; +// } +// +// Overloading Matchers +// ==================== +// +// You can overload matchers with different numbers of parameters: +// +// MATCHER_P(Blah, a, description_string1) { ... } +// MATCHER_P2(Blah, a, b, description_string2) { ... } +// +// Caveats +// ======= +// +// When defining a new matcher, you should also consider implementing +// MatcherInterface or using MakePolymorphicMatcher(). These +// approaches require more work than the MATCHER* macros, but also +// give you more control on the types of the value being matched and +// the matcher parameters, which may leads to better compiler error +// messages when the matcher is used wrong. They also allow +// overloading matchers based on parameter types (as opposed to just +// based on the number of parameters). +// +// MATCHER*() can only be used in a namespace scope as templates cannot be +// declared inside of a local class. +// +// More Information +// ================ +// +// To learn more about using these macros, please search for 'MATCHER' +// on +// https://github.com/google/googletest/blob/master/googlemock/docs/cook_book.md + +#define MATCHER(name, description)\ + class name##Matcher {\ + public:\ + template \ + class gmock_Impl : public ::testing::MatcherInterface<\ + GTEST_REFERENCE_TO_CONST_(arg_type)> {\ + public:\ + gmock_Impl()\ + {}\ + virtual bool MatchAndExplain(\ + GTEST_REFERENCE_TO_CONST_(arg_type) arg,\ + ::testing::MatchResultListener* result_listener) const;\ + virtual void DescribeTo(::std::ostream* gmock_os) const {\ + *gmock_os << FormatDescription(false);\ + }\ + virtual void DescribeNegationTo(::std::ostream* gmock_os) const {\ + *gmock_os << FormatDescription(true);\ + }\ + private:\ + ::std::string FormatDescription(bool negation) const {\ + ::std::string gmock_description = (description);\ + if (!gmock_description.empty()) {\ + return gmock_description;\ + }\ + return ::testing::internal::FormatMatcherDescription(\ + negation, #name, \ + ::testing::internal::UniversalTersePrintTupleFieldsToStrings(\ + ::std::tuple<>()));\ + }\ + };\ + template \ + operator ::testing::Matcher() const {\ + return ::testing::Matcher(\ + new gmock_Impl());\ + }\ + name##Matcher() {\ + }\ + private:\ + };\ + inline name##Matcher name() {\ + return name##Matcher();\ + }\ + template \ + bool name##Matcher::gmock_Impl::MatchAndExplain(\ + GTEST_REFERENCE_TO_CONST_(arg_type) arg,\ + ::testing::MatchResultListener* result_listener GTEST_ATTRIBUTE_UNUSED_)\ + const + +#define MATCHER_P(name, p0, description)\ + template \ + class name##MatcherP {\ + public:\ + template \ + class gmock_Impl : public ::testing::MatcherInterface<\ + GTEST_REFERENCE_TO_CONST_(arg_type)> {\ + public:\ + explicit gmock_Impl(p0##_type gmock_p0)\ + : p0(::std::move(gmock_p0)) {}\ + virtual bool MatchAndExplain(\ + GTEST_REFERENCE_TO_CONST_(arg_type) arg,\ + ::testing::MatchResultListener* result_listener) const;\ + virtual void DescribeTo(::std::ostream* gmock_os) const {\ + *gmock_os << FormatDescription(false);\ + }\ + virtual void DescribeNegationTo(::std::ostream* gmock_os) const {\ + *gmock_os << FormatDescription(true);\ + }\ + p0##_type const p0;\ + private:\ + ::std::string FormatDescription(bool negation) const {\ + ::std::string gmock_description = (description);\ + if (!gmock_description.empty()) {\ + return gmock_description;\ + }\ + return ::testing::internal::FormatMatcherDescription(\ + negation, #name, \ + ::testing::internal::UniversalTersePrintTupleFieldsToStrings(\ + ::std::tuple(p0)));\ + }\ + };\ + template \ + operator ::testing::Matcher() const {\ + return ::testing::Matcher(\ + new gmock_Impl(p0));\ + }\ + explicit name##MatcherP(p0##_type gmock_p0) : p0(::std::move(gmock_p0)) {\ + }\ + p0##_type const p0;\ + private:\ + };\ + template \ + inline name##MatcherP name(p0##_type p0) {\ + return name##MatcherP(p0);\ + }\ + template \ + template \ + bool name##MatcherP::gmock_Impl::MatchAndExplain(\ + GTEST_REFERENCE_TO_CONST_(arg_type) arg,\ + ::testing::MatchResultListener* result_listener GTEST_ATTRIBUTE_UNUSED_)\ + const + +#define MATCHER_P2(name, p0, p1, description)\ + template \ + class name##MatcherP2 {\ + public:\ + template \ + class gmock_Impl : public ::testing::MatcherInterface<\ + GTEST_REFERENCE_TO_CONST_(arg_type)> {\ + public:\ + gmock_Impl(p0##_type gmock_p0, p1##_type gmock_p1)\ + : p0(::std::move(gmock_p0)), p1(::std::move(gmock_p1)) {}\ + virtual bool MatchAndExplain(\ + GTEST_REFERENCE_TO_CONST_(arg_type) arg,\ + ::testing::MatchResultListener* result_listener) const;\ + virtual void DescribeTo(::std::ostream* gmock_os) const {\ + *gmock_os << FormatDescription(false);\ + }\ + virtual void DescribeNegationTo(::std::ostream* gmock_os) const {\ + *gmock_os << FormatDescription(true);\ + }\ + p0##_type const p0;\ + p1##_type const p1;\ + private:\ + ::std::string FormatDescription(bool negation) const {\ + ::std::string gmock_description = (description);\ + if (!gmock_description.empty()) {\ + return gmock_description;\ + }\ + return ::testing::internal::FormatMatcherDescription(\ + negation, #name, \ + ::testing::internal::UniversalTersePrintTupleFieldsToStrings(\ + ::std::tuple(p0, p1)));\ + }\ + };\ + template \ + operator ::testing::Matcher() const {\ + return ::testing::Matcher(\ + new gmock_Impl(p0, p1));\ + }\ + name##MatcherP2(p0##_type gmock_p0, \ + p1##_type gmock_p1) : p0(::std::move(gmock_p0)), \ + p1(::std::move(gmock_p1)) {\ + }\ + p0##_type const p0;\ + p1##_type const p1;\ + private:\ + };\ + template \ + inline name##MatcherP2 name(p0##_type p0, \ + p1##_type p1) {\ + return name##MatcherP2(p0, p1);\ + }\ + template \ + template \ + bool name##MatcherP2::gmock_Impl::MatchAndExplain(\ + GTEST_REFERENCE_TO_CONST_(arg_type) arg,\ + ::testing::MatchResultListener* result_listener GTEST_ATTRIBUTE_UNUSED_)\ + const + +#define MATCHER_P3(name, p0, p1, p2, description)\ + template \ + class name##MatcherP3 {\ + public:\ + template \ + class gmock_Impl : public ::testing::MatcherInterface<\ + GTEST_REFERENCE_TO_CONST_(arg_type)> {\ + public:\ + gmock_Impl(p0##_type gmock_p0, p1##_type gmock_p1, p2##_type gmock_p2)\ + : p0(::std::move(gmock_p0)), p1(::std::move(gmock_p1)), \ + p2(::std::move(gmock_p2)) {}\ + virtual bool MatchAndExplain(\ + GTEST_REFERENCE_TO_CONST_(arg_type) arg,\ + ::testing::MatchResultListener* result_listener) const;\ + virtual void DescribeTo(::std::ostream* gmock_os) const {\ + *gmock_os << FormatDescription(false);\ + }\ + virtual void DescribeNegationTo(::std::ostream* gmock_os) const {\ + *gmock_os << FormatDescription(true);\ + }\ + p0##_type const p0;\ + p1##_type const p1;\ + p2##_type const p2;\ + private:\ + ::std::string FormatDescription(bool negation) const {\ + ::std::string gmock_description = (description);\ + if (!gmock_description.empty()) {\ + return gmock_description;\ + }\ + return ::testing::internal::FormatMatcherDescription(\ + negation, #name, \ + ::testing::internal::UniversalTersePrintTupleFieldsToStrings(\ + ::std::tuple(p0, p1, p2)));\ + }\ + };\ + template \ + operator ::testing::Matcher() const {\ + return ::testing::Matcher(\ + new gmock_Impl(p0, p1, p2));\ + }\ + name##MatcherP3(p0##_type gmock_p0, p1##_type gmock_p1, \ + p2##_type gmock_p2) : p0(::std::move(gmock_p0)), \ + p1(::std::move(gmock_p1)), p2(::std::move(gmock_p2)) {\ + }\ + p0##_type const p0;\ + p1##_type const p1;\ + p2##_type const p2;\ + private:\ + };\ + template \ + inline name##MatcherP3 name(p0##_type p0, \ + p1##_type p1, p2##_type p2) {\ + return name##MatcherP3(p0, p1, p2);\ + }\ + template \ + template \ + bool name##MatcherP3::gmock_Impl::MatchAndExplain(\ + GTEST_REFERENCE_TO_CONST_(arg_type) arg,\ + ::testing::MatchResultListener* result_listener GTEST_ATTRIBUTE_UNUSED_)\ + const + +#define MATCHER_P4(name, p0, p1, p2, p3, description)\ + template \ + class name##MatcherP4 {\ + public:\ + template \ + class gmock_Impl : public ::testing::MatcherInterface<\ + GTEST_REFERENCE_TO_CONST_(arg_type)> {\ + public:\ + gmock_Impl(p0##_type gmock_p0, p1##_type gmock_p1, p2##_type gmock_p2, \ + p3##_type gmock_p3)\ + : p0(::std::move(gmock_p0)), p1(::std::move(gmock_p1)), \ + p2(::std::move(gmock_p2)), p3(::std::move(gmock_p3)) {}\ + virtual bool MatchAndExplain(\ + GTEST_REFERENCE_TO_CONST_(arg_type) arg,\ + ::testing::MatchResultListener* result_listener) const;\ + virtual void DescribeTo(::std::ostream* gmock_os) const {\ + *gmock_os << FormatDescription(false);\ + }\ + virtual void DescribeNegationTo(::std::ostream* gmock_os) const {\ + *gmock_os << FormatDescription(true);\ + }\ + p0##_type const p0;\ + p1##_type const p1;\ + p2##_type const p2;\ + p3##_type const p3;\ + private:\ + ::std::string FormatDescription(bool negation) const {\ + ::std::string gmock_description = (description);\ + if (!gmock_description.empty()) {\ + return gmock_description;\ + }\ + return ::testing::internal::FormatMatcherDescription(\ + negation, #name, \ + ::testing::internal::UniversalTersePrintTupleFieldsToStrings(\ + ::std::tuple(p0, \ + p1, p2, p3)));\ + }\ + };\ + template \ + operator ::testing::Matcher() const {\ + return ::testing::Matcher(\ + new gmock_Impl(p0, p1, p2, p3));\ + }\ + name##MatcherP4(p0##_type gmock_p0, p1##_type gmock_p1, \ + p2##_type gmock_p2, p3##_type gmock_p3) : p0(::std::move(gmock_p0)), \ + p1(::std::move(gmock_p1)), p2(::std::move(gmock_p2)), \ + p3(::std::move(gmock_p3)) {\ + }\ + p0##_type const p0;\ + p1##_type const p1;\ + p2##_type const p2;\ + p3##_type const p3;\ + private:\ + };\ + template \ + inline name##MatcherP4 name(p0##_type p0, p1##_type p1, p2##_type p2, \ + p3##_type p3) {\ + return name##MatcherP4(p0, \ + p1, p2, p3);\ + }\ + template \ + template \ + bool name##MatcherP4::gmock_Impl::MatchAndExplain(\ + GTEST_REFERENCE_TO_CONST_(arg_type) arg,\ + ::testing::MatchResultListener* result_listener GTEST_ATTRIBUTE_UNUSED_)\ + const + +#define MATCHER_P5(name, p0, p1, p2, p3, p4, description)\ + template \ + class name##MatcherP5 {\ + public:\ + template \ + class gmock_Impl : public ::testing::MatcherInterface<\ + GTEST_REFERENCE_TO_CONST_(arg_type)> {\ + public:\ + gmock_Impl(p0##_type gmock_p0, p1##_type gmock_p1, p2##_type gmock_p2, \ + p3##_type gmock_p3, p4##_type gmock_p4)\ + : p0(::std::move(gmock_p0)), p1(::std::move(gmock_p1)), \ + p2(::std::move(gmock_p2)), p3(::std::move(gmock_p3)), \ + p4(::std::move(gmock_p4)) {}\ + virtual bool MatchAndExplain(\ + GTEST_REFERENCE_TO_CONST_(arg_type) arg,\ + ::testing::MatchResultListener* result_listener) const;\ + virtual void DescribeTo(::std::ostream* gmock_os) const {\ + *gmock_os << FormatDescription(false);\ + }\ + virtual void DescribeNegationTo(::std::ostream* gmock_os) const {\ + *gmock_os << FormatDescription(true);\ + }\ + p0##_type const p0;\ + p1##_type const p1;\ + p2##_type const p2;\ + p3##_type const p3;\ + p4##_type const p4;\ + private:\ + ::std::string FormatDescription(bool negation) const {\ + ::std::string gmock_description = (description);\ + if (!gmock_description.empty()) {\ + return gmock_description;\ + }\ + return ::testing::internal::FormatMatcherDescription(\ + negation, #name, \ + ::testing::internal::UniversalTersePrintTupleFieldsToStrings(\ + ::std::tuple(p0, p1, p2, p3, p4)));\ + }\ + };\ + template \ + operator ::testing::Matcher() const {\ + return ::testing::Matcher(\ + new gmock_Impl(p0, p1, p2, p3, p4));\ + }\ + name##MatcherP5(p0##_type gmock_p0, p1##_type gmock_p1, \ + p2##_type gmock_p2, p3##_type gmock_p3, \ + p4##_type gmock_p4) : p0(::std::move(gmock_p0)), \ + p1(::std::move(gmock_p1)), p2(::std::move(gmock_p2)), \ + p3(::std::move(gmock_p3)), p4(::std::move(gmock_p4)) {\ + }\ + p0##_type const p0;\ + p1##_type const p1;\ + p2##_type const p2;\ + p3##_type const p3;\ + p4##_type const p4;\ + private:\ + };\ + template \ + inline name##MatcherP5 name(p0##_type p0, p1##_type p1, p2##_type p2, p3##_type p3, \ + p4##_type p4) {\ + return name##MatcherP5(p0, p1, p2, p3, p4);\ + }\ + template \ + template \ + bool name##MatcherP5::gmock_Impl::MatchAndExplain(\ + GTEST_REFERENCE_TO_CONST_(arg_type) arg,\ + ::testing::MatchResultListener* result_listener GTEST_ATTRIBUTE_UNUSED_)\ + const + +#define MATCHER_P6(name, p0, p1, p2, p3, p4, p5, description)\ + template \ + class name##MatcherP6 {\ + public:\ + template \ + class gmock_Impl : public ::testing::MatcherInterface<\ + GTEST_REFERENCE_TO_CONST_(arg_type)> {\ + public:\ + gmock_Impl(p0##_type gmock_p0, p1##_type gmock_p1, p2##_type gmock_p2, \ + p3##_type gmock_p3, p4##_type gmock_p4, p5##_type gmock_p5)\ + : p0(::std::move(gmock_p0)), p1(::std::move(gmock_p1)), \ + p2(::std::move(gmock_p2)), p3(::std::move(gmock_p3)), \ + p4(::std::move(gmock_p4)), p5(::std::move(gmock_p5)) {}\ + virtual bool MatchAndExplain(\ + GTEST_REFERENCE_TO_CONST_(arg_type) arg,\ + ::testing::MatchResultListener* result_listener) const;\ + virtual void DescribeTo(::std::ostream* gmock_os) const {\ + *gmock_os << FormatDescription(false);\ + }\ + virtual void DescribeNegationTo(::std::ostream* gmock_os) const {\ + *gmock_os << FormatDescription(true);\ + }\ + p0##_type const p0;\ + p1##_type const p1;\ + p2##_type const p2;\ + p3##_type const p3;\ + p4##_type const p4;\ + p5##_type const p5;\ + private:\ + ::std::string FormatDescription(bool negation) const {\ + ::std::string gmock_description = (description);\ + if (!gmock_description.empty()) {\ + return gmock_description;\ + }\ + return ::testing::internal::FormatMatcherDescription(\ + negation, #name, \ + ::testing::internal::UniversalTersePrintTupleFieldsToStrings(\ + ::std::tuple(p0, p1, p2, p3, p4, p5)));\ + }\ + };\ + template \ + operator ::testing::Matcher() const {\ + return ::testing::Matcher(\ + new gmock_Impl(p0, p1, p2, p3, p4, p5));\ + }\ + name##MatcherP6(p0##_type gmock_p0, p1##_type gmock_p1, \ + p2##_type gmock_p2, p3##_type gmock_p3, p4##_type gmock_p4, \ + p5##_type gmock_p5) : p0(::std::move(gmock_p0)), \ + p1(::std::move(gmock_p1)), p2(::std::move(gmock_p2)), \ + p3(::std::move(gmock_p3)), p4(::std::move(gmock_p4)), \ + p5(::std::move(gmock_p5)) {\ + }\ + p0##_type const p0;\ + p1##_type const p1;\ + p2##_type const p2;\ + p3##_type const p3;\ + p4##_type const p4;\ + p5##_type const p5;\ + private:\ + };\ + template \ + inline name##MatcherP6 name(p0##_type p0, p1##_type p1, p2##_type p2, \ + p3##_type p3, p4##_type p4, p5##_type p5) {\ + return name##MatcherP6(p0, p1, p2, p3, p4, p5);\ + }\ + template \ + template \ + bool name##MatcherP6::gmock_Impl::MatchAndExplain(\ + GTEST_REFERENCE_TO_CONST_(arg_type) arg,\ + ::testing::MatchResultListener* result_listener GTEST_ATTRIBUTE_UNUSED_)\ + const + +#define MATCHER_P7(name, p0, p1, p2, p3, p4, p5, p6, description)\ + template \ + class name##MatcherP7 {\ + public:\ + template \ + class gmock_Impl : public ::testing::MatcherInterface<\ + GTEST_REFERENCE_TO_CONST_(arg_type)> {\ + public:\ + gmock_Impl(p0##_type gmock_p0, p1##_type gmock_p1, p2##_type gmock_p2, \ + p3##_type gmock_p3, p4##_type gmock_p4, p5##_type gmock_p5, \ + p6##_type gmock_p6)\ + : p0(::std::move(gmock_p0)), p1(::std::move(gmock_p1)), \ + p2(::std::move(gmock_p2)), p3(::std::move(gmock_p3)), \ + p4(::std::move(gmock_p4)), p5(::std::move(gmock_p5)), \ + p6(::std::move(gmock_p6)) {}\ + virtual bool MatchAndExplain(\ + GTEST_REFERENCE_TO_CONST_(arg_type) arg,\ + ::testing::MatchResultListener* result_listener) const;\ + virtual void DescribeTo(::std::ostream* gmock_os) const {\ + *gmock_os << FormatDescription(false);\ + }\ + virtual void DescribeNegationTo(::std::ostream* gmock_os) const {\ + *gmock_os << FormatDescription(true);\ + }\ + p0##_type const p0;\ + p1##_type const p1;\ + p2##_type const p2;\ + p3##_type const p3;\ + p4##_type const p4;\ + p5##_type const p5;\ + p6##_type const p6;\ + private:\ + ::std::string FormatDescription(bool negation) const {\ + ::std::string gmock_description = (description);\ + if (!gmock_description.empty()) {\ + return gmock_description;\ + }\ + return ::testing::internal::FormatMatcherDescription(\ + negation, #name, \ + ::testing::internal::UniversalTersePrintTupleFieldsToStrings(\ + ::std::tuple(p0, p1, p2, p3, p4, p5, \ + p6)));\ + }\ + };\ + template \ + operator ::testing::Matcher() const {\ + return ::testing::Matcher(\ + new gmock_Impl(p0, p1, p2, p3, p4, p5, p6));\ + }\ + name##MatcherP7(p0##_type gmock_p0, p1##_type gmock_p1, \ + p2##_type gmock_p2, p3##_type gmock_p3, p4##_type gmock_p4, \ + p5##_type gmock_p5, p6##_type gmock_p6) : p0(::std::move(gmock_p0)), \ + p1(::std::move(gmock_p1)), p2(::std::move(gmock_p2)), \ + p3(::std::move(gmock_p3)), p4(::std::move(gmock_p4)), \ + p5(::std::move(gmock_p5)), p6(::std::move(gmock_p6)) {\ + }\ + p0##_type const p0;\ + p1##_type const p1;\ + p2##_type const p2;\ + p3##_type const p3;\ + p4##_type const p4;\ + p5##_type const p5;\ + p6##_type const p6;\ + private:\ + };\ + template \ + inline name##MatcherP7 name(p0##_type p0, p1##_type p1, \ + p2##_type p2, p3##_type p3, p4##_type p4, p5##_type p5, \ + p6##_type p6) {\ + return name##MatcherP7(p0, p1, p2, p3, p4, p5, p6);\ + }\ + template \ + template \ + bool name##MatcherP7::gmock_Impl::MatchAndExplain(\ + GTEST_REFERENCE_TO_CONST_(arg_type) arg,\ + ::testing::MatchResultListener* result_listener GTEST_ATTRIBUTE_UNUSED_)\ + const + +#define MATCHER_P8(name, p0, p1, p2, p3, p4, p5, p6, p7, description)\ + template \ + class name##MatcherP8 {\ + public:\ + template \ + class gmock_Impl : public ::testing::MatcherInterface<\ + GTEST_REFERENCE_TO_CONST_(arg_type)> {\ + public:\ + gmock_Impl(p0##_type gmock_p0, p1##_type gmock_p1, p2##_type gmock_p2, \ + p3##_type gmock_p3, p4##_type gmock_p4, p5##_type gmock_p5, \ + p6##_type gmock_p6, p7##_type gmock_p7)\ + : p0(::std::move(gmock_p0)), p1(::std::move(gmock_p1)), \ + p2(::std::move(gmock_p2)), p3(::std::move(gmock_p3)), \ + p4(::std::move(gmock_p4)), p5(::std::move(gmock_p5)), \ + p6(::std::move(gmock_p6)), p7(::std::move(gmock_p7)) {}\ + virtual bool MatchAndExplain(\ + GTEST_REFERENCE_TO_CONST_(arg_type) arg,\ + ::testing::MatchResultListener* result_listener) const;\ + virtual void DescribeTo(::std::ostream* gmock_os) const {\ + *gmock_os << FormatDescription(false);\ + }\ + virtual void DescribeNegationTo(::std::ostream* gmock_os) const {\ + *gmock_os << FormatDescription(true);\ + }\ + p0##_type const p0;\ + p1##_type const p1;\ + p2##_type const p2;\ + p3##_type const p3;\ + p4##_type const p4;\ + p5##_type const p5;\ + p6##_type const p6;\ + p7##_type const p7;\ + private:\ + ::std::string FormatDescription(bool negation) const {\ + ::std::string gmock_description = (description);\ + if (!gmock_description.empty()) {\ + return gmock_description;\ + }\ + return ::testing::internal::FormatMatcherDescription(\ + negation, #name, \ + ::testing::internal::UniversalTersePrintTupleFieldsToStrings(\ + ::std::tuple(p0, p1, p2, \ + p3, p4, p5, p6, p7)));\ + }\ + };\ + template \ + operator ::testing::Matcher() const {\ + return ::testing::Matcher(\ + new gmock_Impl(p0, p1, p2, p3, p4, p5, p6, p7));\ + }\ + name##MatcherP8(p0##_type gmock_p0, p1##_type gmock_p1, \ + p2##_type gmock_p2, p3##_type gmock_p3, p4##_type gmock_p4, \ + p5##_type gmock_p5, p6##_type gmock_p6, \ + p7##_type gmock_p7) : p0(::std::move(gmock_p0)), \ + p1(::std::move(gmock_p1)), p2(::std::move(gmock_p2)), \ + p3(::std::move(gmock_p3)), p4(::std::move(gmock_p4)), \ + p5(::std::move(gmock_p5)), p6(::std::move(gmock_p6)), \ + p7(::std::move(gmock_p7)) {\ + }\ + p0##_type const p0;\ + p1##_type const p1;\ + p2##_type const p2;\ + p3##_type const p3;\ + p4##_type const p4;\ + p5##_type const p5;\ + p6##_type const p6;\ + p7##_type const p7;\ + private:\ + };\ + template \ + inline name##MatcherP8 name(p0##_type p0, \ + p1##_type p1, p2##_type p2, p3##_type p3, p4##_type p4, p5##_type p5, \ + p6##_type p6, p7##_type p7) {\ + return name##MatcherP8(p0, p1, p2, p3, p4, p5, \ + p6, p7);\ + }\ + template \ + template \ + bool name##MatcherP8::gmock_Impl::MatchAndExplain(\ + GTEST_REFERENCE_TO_CONST_(arg_type) arg,\ + ::testing::MatchResultListener* result_listener GTEST_ATTRIBUTE_UNUSED_)\ + const + +#define MATCHER_P9(name, p0, p1, p2, p3, p4, p5, p6, p7, p8, description)\ + template \ + class name##MatcherP9 {\ + public:\ + template \ + class gmock_Impl : public ::testing::MatcherInterface<\ + GTEST_REFERENCE_TO_CONST_(arg_type)> {\ + public:\ + gmock_Impl(p0##_type gmock_p0, p1##_type gmock_p1, p2##_type gmock_p2, \ + p3##_type gmock_p3, p4##_type gmock_p4, p5##_type gmock_p5, \ + p6##_type gmock_p6, p7##_type gmock_p7, p8##_type gmock_p8)\ + : p0(::std::move(gmock_p0)), p1(::std::move(gmock_p1)), \ + p2(::std::move(gmock_p2)), p3(::std::move(gmock_p3)), \ + p4(::std::move(gmock_p4)), p5(::std::move(gmock_p5)), \ + p6(::std::move(gmock_p6)), p7(::std::move(gmock_p7)), \ + p8(::std::move(gmock_p8)) {}\ + virtual bool MatchAndExplain(\ + GTEST_REFERENCE_TO_CONST_(arg_type) arg,\ + ::testing::MatchResultListener* result_listener) const;\ + virtual void DescribeTo(::std::ostream* gmock_os) const {\ + *gmock_os << FormatDescription(false);\ + }\ + virtual void DescribeNegationTo(::std::ostream* gmock_os) const {\ + *gmock_os << FormatDescription(true);\ + }\ + p0##_type const p0;\ + p1##_type const p1;\ + p2##_type const p2;\ + p3##_type const p3;\ + p4##_type const p4;\ + p5##_type const p5;\ + p6##_type const p6;\ + p7##_type const p7;\ + p8##_type const p8;\ + private:\ + ::std::string FormatDescription(bool negation) const {\ + ::std::string gmock_description = (description);\ + if (!gmock_description.empty()) {\ + return gmock_description;\ + }\ + return ::testing::internal::FormatMatcherDescription(\ + negation, #name, \ + ::testing::internal::UniversalTersePrintTupleFieldsToStrings(\ + ::std::tuple(p0, p1, p2, p3, p4, p5, p6, p7, p8)));\ + }\ + };\ + template \ + operator ::testing::Matcher() const {\ + return ::testing::Matcher(\ + new gmock_Impl(p0, p1, p2, p3, p4, p5, p6, p7, p8));\ + }\ + name##MatcherP9(p0##_type gmock_p0, p1##_type gmock_p1, \ + p2##_type gmock_p2, p3##_type gmock_p3, p4##_type gmock_p4, \ + p5##_type gmock_p5, p6##_type gmock_p6, p7##_type gmock_p7, \ + p8##_type gmock_p8) : p0(::std::move(gmock_p0)), \ + p1(::std::move(gmock_p1)), p2(::std::move(gmock_p2)), \ + p3(::std::move(gmock_p3)), p4(::std::move(gmock_p4)), \ + p5(::std::move(gmock_p5)), p6(::std::move(gmock_p6)), \ + p7(::std::move(gmock_p7)), p8(::std::move(gmock_p8)) {\ + }\ + p0##_type const p0;\ + p1##_type const p1;\ + p2##_type const p2;\ + p3##_type const p3;\ + p4##_type const p4;\ + p5##_type const p5;\ + p6##_type const p6;\ + p7##_type const p7;\ + p8##_type const p8;\ + private:\ + };\ + template \ + inline name##MatcherP9 name(p0##_type p0, p1##_type p1, p2##_type p2, p3##_type p3, \ + p4##_type p4, p5##_type p5, p6##_type p6, p7##_type p7, \ + p8##_type p8) {\ + return name##MatcherP9(p0, p1, p2, \ + p3, p4, p5, p6, p7, p8);\ + }\ + template \ + template \ + bool name##MatcherP9::gmock_Impl::MatchAndExplain(\ + GTEST_REFERENCE_TO_CONST_(arg_type) arg,\ + ::testing::MatchResultListener* result_listener GTEST_ATTRIBUTE_UNUSED_)\ + const + +#define MATCHER_P10(name, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, description)\ + template \ + class name##MatcherP10 {\ + public:\ + template \ + class gmock_Impl : public ::testing::MatcherInterface<\ + GTEST_REFERENCE_TO_CONST_(arg_type)> {\ + public:\ + gmock_Impl(p0##_type gmock_p0, p1##_type gmock_p1, p2##_type gmock_p2, \ + p3##_type gmock_p3, p4##_type gmock_p4, p5##_type gmock_p5, \ + p6##_type gmock_p6, p7##_type gmock_p7, p8##_type gmock_p8, \ + p9##_type gmock_p9)\ + : p0(::std::move(gmock_p0)), p1(::std::move(gmock_p1)), \ + p2(::std::move(gmock_p2)), p3(::std::move(gmock_p3)), \ + p4(::std::move(gmock_p4)), p5(::std::move(gmock_p5)), \ + p6(::std::move(gmock_p6)), p7(::std::move(gmock_p7)), \ + p8(::std::move(gmock_p8)), p9(::std::move(gmock_p9)) {}\ + virtual bool MatchAndExplain(\ + GTEST_REFERENCE_TO_CONST_(arg_type) arg,\ + ::testing::MatchResultListener* result_listener) const;\ + virtual void DescribeTo(::std::ostream* gmock_os) const {\ + *gmock_os << FormatDescription(false);\ + }\ + virtual void DescribeNegationTo(::std::ostream* gmock_os) const {\ + *gmock_os << FormatDescription(true);\ + }\ + p0##_type const p0;\ + p1##_type const p1;\ + p2##_type const p2;\ + p3##_type const p3;\ + p4##_type const p4;\ + p5##_type const p5;\ + p6##_type const p6;\ + p7##_type const p7;\ + p8##_type const p8;\ + p9##_type const p9;\ + private:\ + ::std::string FormatDescription(bool negation) const {\ + ::std::string gmock_description = (description);\ + if (!gmock_description.empty()) {\ + return gmock_description;\ + }\ + return ::testing::internal::FormatMatcherDescription(\ + negation, #name, \ + ::testing::internal::UniversalTersePrintTupleFieldsToStrings(\ + ::std::tuple(p0, p1, p2, p3, p4, p5, p6, p7, p8, p9)));\ + }\ + };\ + template \ + operator ::testing::Matcher() const {\ + return ::testing::Matcher(\ + new gmock_Impl(p0, p1, p2, p3, p4, p5, p6, p7, p8, p9));\ + }\ + name##MatcherP10(p0##_type gmock_p0, p1##_type gmock_p1, \ + p2##_type gmock_p2, p3##_type gmock_p3, p4##_type gmock_p4, \ + p5##_type gmock_p5, p6##_type gmock_p6, p7##_type gmock_p7, \ + p8##_type gmock_p8, p9##_type gmock_p9) : p0(::std::move(gmock_p0)), \ + p1(::std::move(gmock_p1)), p2(::std::move(gmock_p2)), \ + p3(::std::move(gmock_p3)), p4(::std::move(gmock_p4)), \ + p5(::std::move(gmock_p5)), p6(::std::move(gmock_p6)), \ + p7(::std::move(gmock_p7)), p8(::std::move(gmock_p8)), \ + p9(::std::move(gmock_p9)) {\ + }\ + p0##_type const p0;\ + p1##_type const p1;\ + p2##_type const p2;\ + p3##_type const p3;\ + p4##_type const p4;\ + p5##_type const p5;\ + p6##_type const p6;\ + p7##_type const p7;\ + p8##_type const p8;\ + p9##_type const p9;\ + private:\ + };\ + template \ + inline name##MatcherP10 name(p0##_type p0, p1##_type p1, p2##_type p2, p3##_type p3, \ + p4##_type p4, p5##_type p5, p6##_type p6, p7##_type p7, p8##_type p8, \ + p9##_type p9) {\ + return name##MatcherP10(p0, \ + p1, p2, p3, p4, p5, p6, p7, p8, p9);\ + }\ + template \ + template \ + bool name##MatcherP10::gmock_Impl::MatchAndExplain(\ + GTEST_REFERENCE_TO_CONST_(arg_type) arg,\ + ::testing::MatchResultListener* result_listener GTEST_ATTRIBUTE_UNUSED_)\ + const + +#endif // GMOCK_INCLUDE_GMOCK_GMOCK_GENERATED_MATCHERS_H_ diff --git a/googlemock/include/gmock/gmock-generated-matchers.h.pump b/googlemock/include/gmock/gmock-generated-matchers.h.pump new file mode 100644 index 00000000..ae90917c --- /dev/null +++ b/googlemock/include/gmock/gmock-generated-matchers.h.pump @@ -0,0 +1,346 @@ +$$ -*- mode: c++; -*- +$$ This is a Pump source file. Please use Pump to convert +$$ it to gmock-generated-matchers.h. +$$ +$var n = 10 $$ The maximum arity we support. +$$ }} This line fixes auto-indentation of the following code in Emacs. +// Copyright 2008, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// Google Mock - a framework for writing C++ mock classes. +// +// This file implements some commonly used variadic matchers. + +// GOOGLETEST_CM0002 DO NOT DELETE + +#ifndef GMOCK_INCLUDE_GMOCK_GMOCK_GENERATED_MATCHERS_H_ +#define GMOCK_INCLUDE_GMOCK_GMOCK_GENERATED_MATCHERS_H_ + +#include +#include +#include +#include +#include +#include "gmock/gmock-matchers.h" + +// The MATCHER* family of macros can be used in a namespace scope to +// define custom matchers easily. +// +// Basic Usage +// =========== +// +// The syntax +// +// MATCHER(name, description_string) { statements; } +// +// defines a matcher with the given name that executes the statements, +// which must return a bool to indicate if the match succeeds. Inside +// the statements, you can refer to the value being matched by 'arg', +// and refer to its type by 'arg_type'. +// +// The description string documents what the matcher does, and is used +// to generate the failure message when the match fails. Since a +// MATCHER() is usually defined in a header file shared by multiple +// C++ source files, we require the description to be a C-string +// literal to avoid possible side effects. It can be empty, in which +// case we'll use the sequence of words in the matcher name as the +// description. +// +// For example: +// +// MATCHER(IsEven, "") { return (arg % 2) == 0; } +// +// allows you to write +// +// // Expects mock_foo.Bar(n) to be called where n is even. +// EXPECT_CALL(mock_foo, Bar(IsEven())); +// +// or, +// +// // Verifies that the value of some_expression is even. +// EXPECT_THAT(some_expression, IsEven()); +// +// If the above assertion fails, it will print something like: +// +// Value of: some_expression +// Expected: is even +// Actual: 7 +// +// where the description "is even" is automatically calculated from the +// matcher name IsEven. +// +// Argument Type +// ============= +// +// Note that the type of the value being matched (arg_type) is +// determined by the context in which you use the matcher and is +// supplied to you by the compiler, so you don't need to worry about +// declaring it (nor can you). This allows the matcher to be +// polymorphic. For example, IsEven() can be used to match any type +// where the value of "(arg % 2) == 0" can be implicitly converted to +// a bool. In the "Bar(IsEven())" example above, if method Bar() +// takes an int, 'arg_type' will be int; if it takes an unsigned long, +// 'arg_type' will be unsigned long; and so on. +// +// Parameterizing Matchers +// ======================= +// +// Sometimes you'll want to parameterize the matcher. For that you +// can use another macro: +// +// MATCHER_P(name, param_name, description_string) { statements; } +// +// For example: +// +// MATCHER_P(HasAbsoluteValue, value, "") { return abs(arg) == value; } +// +// will allow you to write: +// +// EXPECT_THAT(Blah("a"), HasAbsoluteValue(n)); +// +// which may lead to this message (assuming n is 10): +// +// Value of: Blah("a") +// Expected: has absolute value 10 +// Actual: -9 +// +// Note that both the matcher description and its parameter are +// printed, making the message human-friendly. +// +// In the matcher definition body, you can write 'foo_type' to +// reference the type of a parameter named 'foo'. For example, in the +// body of MATCHER_P(HasAbsoluteValue, value) above, you can write +// 'value_type' to refer to the type of 'value'. +// +// We also provide MATCHER_P2, MATCHER_P3, ..., up to MATCHER_P$n to +// support multi-parameter matchers. +// +// Describing Parameterized Matchers +// ================================= +// +// The last argument to MATCHER*() is a string-typed expression. The +// expression can reference all of the matcher's parameters and a +// special bool-typed variable named 'negation'. When 'negation' is +// false, the expression should evaluate to the matcher's description; +// otherwise it should evaluate to the description of the negation of +// the matcher. For example, +// +// using testing::PrintToString; +// +// MATCHER_P2(InClosedRange, low, hi, +// std::string(negation ? "is not" : "is") + " in range [" + +// PrintToString(low) + ", " + PrintToString(hi) + "]") { +// return low <= arg && arg <= hi; +// } +// ... +// EXPECT_THAT(3, InClosedRange(4, 6)); +// EXPECT_THAT(3, Not(InClosedRange(2, 4))); +// +// would generate two failures that contain the text: +// +// Expected: is in range [4, 6] +// ... +// Expected: is not in range [2, 4] +// +// If you specify "" as the description, the failure message will +// contain the sequence of words in the matcher name followed by the +// parameter values printed as a tuple. For example, +// +// MATCHER_P2(InClosedRange, low, hi, "") { ... } +// ... +// EXPECT_THAT(3, InClosedRange(4, 6)); +// EXPECT_THAT(3, Not(InClosedRange(2, 4))); +// +// would generate two failures that contain the text: +// +// Expected: in closed range (4, 6) +// ... +// Expected: not (in closed range (2, 4)) +// +// Types of Matcher Parameters +// =========================== +// +// For the purpose of typing, you can view +// +// MATCHER_Pk(Foo, p1, ..., pk, description_string) { ... } +// +// as shorthand for +// +// template +// FooMatcherPk +// Foo(p1_type p1, ..., pk_type pk) { ... } +// +// When you write Foo(v1, ..., vk), the compiler infers the types of +// the parameters v1, ..., and vk for you. If you are not happy with +// the result of the type inference, you can specify the types by +// explicitly instantiating the template, as in Foo(5, +// false). As said earlier, you don't get to (or need to) specify +// 'arg_type' as that's determined by the context in which the matcher +// is used. You can assign the result of expression Foo(p1, ..., pk) +// to a variable of type FooMatcherPk. This +// can be useful when composing matchers. +// +// While you can instantiate a matcher template with reference types, +// passing the parameters by pointer usually makes your code more +// readable. If, however, you still want to pass a parameter by +// reference, be aware that in the failure message generated by the +// matcher you will see the value of the referenced object but not its +// address. +// +// Explaining Match Results +// ======================== +// +// Sometimes the matcher description alone isn't enough to explain why +// the match has failed or succeeded. For example, when expecting a +// long string, it can be very helpful to also print the diff between +// the expected string and the actual one. To achieve that, you can +// optionally stream additional information to a special variable +// named result_listener, whose type is a pointer to class +// MatchResultListener: +// +// MATCHER_P(EqualsLongString, str, "") { +// if (arg == str) return true; +// +// *result_listener << "the difference: " +/// << DiffStrings(str, arg); +// return false; +// } +// +// Overloading Matchers +// ==================== +// +// You can overload matchers with different numbers of parameters: +// +// MATCHER_P(Blah, a, description_string1) { ... } +// MATCHER_P2(Blah, a, b, description_string2) { ... } +// +// Caveats +// ======= +// +// When defining a new matcher, you should also consider implementing +// MatcherInterface or using MakePolymorphicMatcher(). These +// approaches require more work than the MATCHER* macros, but also +// give you more control on the types of the value being matched and +// the matcher parameters, which may leads to better compiler error +// messages when the matcher is used wrong. They also allow +// overloading matchers based on parameter types (as opposed to just +// based on the number of parameters). +// +// MATCHER*() can only be used in a namespace scope as templates cannot be +// declared inside of a local class. +// +// More Information +// ================ +// +// To learn more about using these macros, please search for 'MATCHER' +// on +// https://github.com/google/googletest/blob/master/googlemock/docs/cook_book.md + +$range i 0..n +$for i + +[[ +$var macro_name = [[$if i==0 [[MATCHER]] $elif i==1 [[MATCHER_P]] + $else [[MATCHER_P$i]]]] +$var class_name = [[name##Matcher[[$if i==0 [[]] $elif i==1 [[P]] + $else [[P$i]]]]]] +$range j 0..i-1 +$var template = [[$if i==0 [[]] $else [[ + + template <$for j, [[typename p$j##_type]]>\ +]]]] +$var ctor_param_list = [[$for j, [[p$j##_type gmock_p$j]]]] +$var impl_ctor_param_list = [[$for j, [[p$j##_type gmock_p$j]]]] +$var impl_inits = [[$if i==0 [[]] $else [[ : $for j, [[p$j(::std::move(gmock_p$j))]]]]]] +$var inits = [[$if i==0 [[]] $else [[ : $for j, [[p$j(::std::move(gmock_p$j))]]]]]] +$var params = [[$for j, [[p$j]]]] +$var param_types = [[$if i==0 [[]] $else [[<$for j, [[p$j##_type]]>]]]] +$var param_types_and_names = [[$for j, [[p$j##_type p$j]]]] +$var param_field_decls = [[$for j +[[ + + p$j##_type const p$j;\ +]]]] +$var param_field_decls2 = [[$for j +[[ + + p$j##_type const p$j;\ +]]]] + +#define $macro_name(name$for j [[, p$j]], description)\$template + class $class_name {\ + public:\ + template \ + class gmock_Impl : public ::testing::MatcherInterface<\ + GTEST_REFERENCE_TO_CONST_(arg_type)> {\ + public:\ + [[$if i==1 [[explicit ]]]]gmock_Impl($impl_ctor_param_list)\ + $impl_inits {}\ + virtual bool MatchAndExplain(\ + GTEST_REFERENCE_TO_CONST_(arg_type) arg,\ + ::testing::MatchResultListener* result_listener) const;\ + virtual void DescribeTo(::std::ostream* gmock_os) const {\ + *gmock_os << FormatDescription(false);\ + }\ + virtual void DescribeNegationTo(::std::ostream* gmock_os) const {\ + *gmock_os << FormatDescription(true);\ + }\$param_field_decls + private:\ + ::std::string FormatDescription(bool negation) const {\ + ::std::string gmock_description = (description);\ + if (!gmock_description.empty()) {\ + return gmock_description;\ + }\ + return ::testing::internal::FormatMatcherDescription(\ + negation, #name, \ + ::testing::internal::UniversalTersePrintTupleFieldsToStrings(\ + ::std::tuple<$for j, [[p$j##_type]]>($for j, [[p$j]])));\ + }\ + };\ + template \ + operator ::testing::Matcher() const {\ + return ::testing::Matcher(\ + new gmock_Impl($params));\ + }\ + [[$if i==1 [[explicit ]]]]$class_name($ctor_param_list)$inits {\ + }\$param_field_decls2 + private:\ + };\$template + inline $class_name$param_types name($param_types_and_names) {\ + return $class_name$param_types($params);\ + }\$template + template \ + bool $class_name$param_types::gmock_Impl::MatchAndExplain(\ + GTEST_REFERENCE_TO_CONST_(arg_type) arg,\ + ::testing::MatchResultListener* result_listener GTEST_ATTRIBUTE_UNUSED_)\ + const +]] + + +#endif // GMOCK_INCLUDE_GMOCK_GMOCK_GENERATED_MATCHERS_H_ diff --git a/googlemock/include/gmock/gmock-matchers.h b/googlemock/include/gmock/gmock-matchers.h new file mode 100644 index 00000000..70092157 --- /dev/null +++ b/googlemock/include/gmock/gmock-matchers.h @@ -0,0 +1,4566 @@ +// Copyright 2007, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + +// Google Mock - a framework for writing C++ mock classes. +// +// This file implements some commonly used argument matchers. More +// matchers can be defined by the user implementing the +// MatcherInterface interface if necessary. +// +// See googletest/include/gtest/gtest-matchers.h for the definition of class +// Matcher, class MatcherInterface, and others. + +// GOOGLETEST_CM0002 DO NOT DELETE + +#ifndef GMOCK_INCLUDE_GMOCK_GMOCK_MATCHERS_H_ +#define GMOCK_INCLUDE_GMOCK_GMOCK_MATCHERS_H_ + +#include +#include +#include +#include +#include +#include +#include // NOLINT +#include +#include +#include +#include +#include +#include "gmock/internal/gmock-internal-utils.h" +#include "gmock/internal/gmock-port.h" +#include "gtest/gtest.h" + +// MSVC warning C5046 is new as of VS2017 version 15.8. +#if defined(_MSC_VER) && _MSC_VER >= 1915 +#define GMOCK_MAYBE_5046_ 5046 +#else +#define GMOCK_MAYBE_5046_ +#endif + +GTEST_DISABLE_MSC_WARNINGS_PUSH_( + 4251 GMOCK_MAYBE_5046_ /* class A needs to have dll-interface to be used by + clients of class B */ + /* Symbol involving type with internal linkage not defined */) + +namespace testing { + +// To implement a matcher Foo for type T, define: +// 1. a class FooMatcherImpl that implements the +// MatcherInterface interface, and +// 2. a factory function that creates a Matcher object from a +// FooMatcherImpl*. +// +// The two-level delegation design makes it possible to allow a user +// to write "v" instead of "Eq(v)" where a Matcher is expected, which +// is impossible if we pass matchers by pointers. It also eases +// ownership management as Matcher objects can now be copied like +// plain values. + +// A match result listener that stores the explanation in a string. +class StringMatchResultListener : public MatchResultListener { + public: + StringMatchResultListener() : MatchResultListener(&ss_) {} + + // Returns the explanation accumulated so far. + std::string str() const { return ss_.str(); } + + // Clears the explanation accumulated so far. + void Clear() { ss_.str(""); } + + private: + ::std::stringstream ss_; + + GTEST_DISALLOW_COPY_AND_ASSIGN_(StringMatchResultListener); +}; + +// Anything inside the 'internal' namespace IS INTERNAL IMPLEMENTATION +// and MUST NOT BE USED IN USER CODE!!! +namespace internal { + +// The MatcherCastImpl class template is a helper for implementing +// MatcherCast(). We need this helper in order to partially +// specialize the implementation of MatcherCast() (C++ allows +// class/struct templates to be partially specialized, but not +// function templates.). + +// This general version is used when MatcherCast()'s argument is a +// polymorphic matcher (i.e. something that can be converted to a +// Matcher but is not one yet; for example, Eq(value)) or a value (for +// example, "hello"). +template +class MatcherCastImpl { + public: + static Matcher Cast(const M& polymorphic_matcher_or_value) { + // M can be a polymorphic matcher, in which case we want to use + // its conversion operator to create Matcher. Or it can be a value + // that should be passed to the Matcher's constructor. + // + // We can't call Matcher(polymorphic_matcher_or_value) when M is a + // polymorphic matcher because it'll be ambiguous if T has an implicit + // constructor from M (this usually happens when T has an implicit + // constructor from any type). + // + // It won't work to unconditionally implict_cast + // polymorphic_matcher_or_value to Matcher because it won't trigger + // a user-defined conversion from M to T if one exists (assuming M is + // a value). + return CastImpl(polymorphic_matcher_or_value, + std::is_convertible>{}, + std::is_convertible{}); + } + + private: + template + static Matcher CastImpl(const M& polymorphic_matcher_or_value, + std::true_type /* convertible_to_matcher */, + bool_constant) { + // M is implicitly convertible to Matcher, which means that either + // M is a polymorphic matcher or Matcher has an implicit constructor + // from M. In both cases using the implicit conversion will produce a + // matcher. + // + // Even if T has an implicit constructor from M, it won't be called because + // creating Matcher would require a chain of two user-defined conversions + // (first to create T from M and then to create Matcher from T). + return polymorphic_matcher_or_value; + } + + // M can't be implicitly converted to Matcher, so M isn't a polymorphic + // matcher. It's a value of a type implicitly convertible to T. Use direct + // initialization to create a matcher. + static Matcher CastImpl(const M& value, + std::false_type /* convertible_to_matcher */, + std::true_type /* convertible_to_T */) { + return Matcher(ImplicitCast_(value)); + } + + // M can't be implicitly converted to either Matcher or T. Attempt to use + // polymorphic matcher Eq(value) in this case. + // + // Note that we first attempt to perform an implicit cast on the value and + // only fall back to the polymorphic Eq() matcher afterwards because the + // latter calls bool operator==(const Lhs& lhs, const Rhs& rhs) in the end + // which might be undefined even when Rhs is implicitly convertible to Lhs + // (e.g. std::pair vs. std::pair). + // + // We don't define this method inline as we need the declaration of Eq(). + static Matcher CastImpl(const M& value, + std::false_type /* convertible_to_matcher */, + std::false_type /* convertible_to_T */); +}; + +// This more specialized version is used when MatcherCast()'s argument +// is already a Matcher. This only compiles when type T can be +// statically converted to type U. +template +class MatcherCastImpl > { + public: + static Matcher Cast(const Matcher& source_matcher) { + return Matcher(new Impl(source_matcher)); + } + + private: + class Impl : public MatcherInterface { + public: + explicit Impl(const Matcher& source_matcher) + : source_matcher_(source_matcher) {} + + // We delegate the matching logic to the source matcher. + bool MatchAndExplain(T x, MatchResultListener* listener) const override { + using FromType = typename std::remove_cv::type>::type>::type; + using ToType = typename std::remove_cv::type>::type>::type; + // Do not allow implicitly converting base*/& to derived*/&. + static_assert( + // Do not trigger if only one of them is a pointer. That implies a + // regular conversion and not a down_cast. + (std::is_pointer::type>::value != + std::is_pointer::type>::value) || + std::is_same::value || + !std::is_base_of::value, + "Can't implicitly convert from to "); + + return source_matcher_.MatchAndExplain(static_cast(x), listener); + } + + void DescribeTo(::std::ostream* os) const override { + source_matcher_.DescribeTo(os); + } + + void DescribeNegationTo(::std::ostream* os) const override { + source_matcher_.DescribeNegationTo(os); + } + + private: + const Matcher source_matcher_; + + GTEST_DISALLOW_ASSIGN_(Impl); + }; +}; + +// This even more specialized version is used for efficiently casting +// a matcher to its own type. +template +class MatcherCastImpl > { + public: + static Matcher Cast(const Matcher& matcher) { return matcher; } +}; + +} // namespace internal + +// In order to be safe and clear, casting between different matcher +// types is done explicitly via MatcherCast(m), which takes a +// matcher m and returns a Matcher. It compiles only when T can be +// statically converted to the argument type of m. +template +inline Matcher MatcherCast(const M& matcher) { + return internal::MatcherCastImpl::Cast(matcher); +} + +// Implements SafeMatcherCast(). +// +// FIXME: The intermediate SafeMatcherCastImpl class was introduced as a +// workaround for a compiler bug, and can now be removed. +template +class SafeMatcherCastImpl { + public: + // This overload handles polymorphic matchers and values only since + // monomorphic matchers are handled by the next one. + template + static inline Matcher Cast(const M& polymorphic_matcher_or_value) { + return internal::MatcherCastImpl::Cast(polymorphic_matcher_or_value); + } + + // This overload handles monomorphic matchers. + // + // In general, if type T can be implicitly converted to type U, we can + // safely convert a Matcher to a Matcher (i.e. Matcher is + // contravariant): just keep a copy of the original Matcher, convert the + // argument from type T to U, and then pass it to the underlying Matcher. + // The only exception is when U is a reference and T is not, as the + // underlying Matcher may be interested in the argument's address, which + // is not preserved in the conversion from T to U. + template + static inline Matcher Cast(const Matcher& matcher) { + // Enforce that T can be implicitly converted to U. + GTEST_COMPILE_ASSERT_((std::is_convertible::value), + "T must be implicitly convertible to U"); + // Enforce that we are not converting a non-reference type T to a reference + // type U. + GTEST_COMPILE_ASSERT_( + std::is_reference::value || !std::is_reference::value, + cannot_convert_non_reference_arg_to_reference); + // In case both T and U are arithmetic types, enforce that the + // conversion is not lossy. + typedef GTEST_REMOVE_REFERENCE_AND_CONST_(T) RawT; + typedef GTEST_REMOVE_REFERENCE_AND_CONST_(U) RawU; + const bool kTIsOther = GMOCK_KIND_OF_(RawT) == internal::kOther; + const bool kUIsOther = GMOCK_KIND_OF_(RawU) == internal::kOther; + GTEST_COMPILE_ASSERT_( + kTIsOther || kUIsOther || + (internal::LosslessArithmeticConvertible::value), + conversion_of_arithmetic_types_must_be_lossless); + return MatcherCast(matcher); + } +}; + +template +inline Matcher SafeMatcherCast(const M& polymorphic_matcher) { + return SafeMatcherCastImpl::Cast(polymorphic_matcher); +} + +// A() returns a matcher that matches any value of type T. +template +Matcher A(); + +// Anything inside the 'internal' namespace IS INTERNAL IMPLEMENTATION +// and MUST NOT BE USED IN USER CODE!!! +namespace internal { + +// If the explanation is not empty, prints it to the ostream. +inline void PrintIfNotEmpty(const std::string& explanation, + ::std::ostream* os) { + if (explanation != "" && os != nullptr) { + *os << ", " << explanation; + } +} + +// Returns true if the given type name is easy to read by a human. +// This is used to decide whether printing the type of a value might +// be helpful. +inline bool IsReadableTypeName(const std::string& type_name) { + // We consider a type name readable if it's short or doesn't contain + // a template or function type. + return (type_name.length() <= 20 || + type_name.find_first_of("<(") == std::string::npos); +} + +// Matches the value against the given matcher, prints the value and explains +// the match result to the listener. Returns the match result. +// 'listener' must not be NULL. +// Value cannot be passed by const reference, because some matchers take a +// non-const argument. +template +bool MatchPrintAndExplain(Value& value, const Matcher& matcher, + MatchResultListener* listener) { + if (!listener->IsInterested()) { + // If the listener is not interested, we do not need to construct the + // inner explanation. + return matcher.Matches(value); + } + + StringMatchResultListener inner_listener; + const bool match = matcher.MatchAndExplain(value, &inner_listener); + + UniversalPrint(value, listener->stream()); +#if GTEST_HAS_RTTI + const std::string& type_name = GetTypeName(); + if (IsReadableTypeName(type_name)) + *listener->stream() << " (of type " << type_name << ")"; +#endif + PrintIfNotEmpty(inner_listener.str(), listener->stream()); + + return match; +} + +// An internal helper class for doing compile-time loop on a tuple's +// fields. +template +class TuplePrefix { + public: + // TuplePrefix::Matches(matcher_tuple, value_tuple) returns true + // if the first N fields of matcher_tuple matches the first N + // fields of value_tuple, respectively. + template + static bool Matches(const MatcherTuple& matcher_tuple, + const ValueTuple& value_tuple) { + return TuplePrefix::Matches(matcher_tuple, value_tuple) && + std::get(matcher_tuple).Matches(std::get(value_tuple)); + } + + // TuplePrefix::ExplainMatchFailuresTo(matchers, values, os) + // describes failures in matching the first N fields of matchers + // against the first N fields of values. If there is no failure, + // nothing will be streamed to os. + template + static void ExplainMatchFailuresTo(const MatcherTuple& matchers, + const ValueTuple& values, + ::std::ostream* os) { + // First, describes failures in the first N - 1 fields. + TuplePrefix::ExplainMatchFailuresTo(matchers, values, os); + + // Then describes the failure (if any) in the (N - 1)-th (0-based) + // field. + typename std::tuple_element::type matcher = + std::get(matchers); + typedef typename std::tuple_element::type Value; + const Value& value = std::get(values); + StringMatchResultListener listener; + if (!matcher.MatchAndExplain(value, &listener)) { + *os << " Expected arg #" << N - 1 << ": "; + std::get(matchers).DescribeTo(os); + *os << "\n Actual: "; + // We remove the reference in type Value to prevent the + // universal printer from printing the address of value, which + // isn't interesting to the user most of the time. The + // matcher's MatchAndExplain() method handles the case when + // the address is interesting. + internal::UniversalPrint(value, os); + PrintIfNotEmpty(listener.str(), os); + *os << "\n"; + } + } +}; + +// The base case. +template <> +class TuplePrefix<0> { + public: + template + static bool Matches(const MatcherTuple& /* matcher_tuple */, + const ValueTuple& /* value_tuple */) { + return true; + } + + template + static void ExplainMatchFailuresTo(const MatcherTuple& /* matchers */, + const ValueTuple& /* values */, + ::std::ostream* /* os */) {} +}; + +// TupleMatches(matcher_tuple, value_tuple) returns true if all +// matchers in matcher_tuple match the corresponding fields in +// value_tuple. It is a compiler error if matcher_tuple and +// value_tuple have different number of fields or incompatible field +// types. +template +bool TupleMatches(const MatcherTuple& matcher_tuple, + const ValueTuple& value_tuple) { + // Makes sure that matcher_tuple and value_tuple have the same + // number of fields. + GTEST_COMPILE_ASSERT_(std::tuple_size::value == + std::tuple_size::value, + matcher_and_value_have_different_numbers_of_fields); + return TuplePrefix::value>::Matches(matcher_tuple, + value_tuple); +} + +// Describes failures in matching matchers against values. If there +// is no failure, nothing will be streamed to os. +template +void ExplainMatchFailureTupleTo(const MatcherTuple& matchers, + const ValueTuple& values, + ::std::ostream* os) { + TuplePrefix::value>::ExplainMatchFailuresTo( + matchers, values, os); +} + +// TransformTupleValues and its helper. +// +// TransformTupleValuesHelper hides the internal machinery that +// TransformTupleValues uses to implement a tuple traversal. +template +class TransformTupleValuesHelper { + private: + typedef ::std::tuple_size TupleSize; + + public: + // For each member of tuple 't', taken in order, evaluates '*out++ = f(t)'. + // Returns the final value of 'out' in case the caller needs it. + static OutIter Run(Func f, const Tuple& t, OutIter out) { + return IterateOverTuple()(f, t, out); + } + + private: + template + struct IterateOverTuple { + OutIter operator() (Func f, const Tup& t, OutIter out) const { + *out++ = f(::std::get(t)); + return IterateOverTuple()(f, t, out); + } + }; + template + struct IterateOverTuple { + OutIter operator() (Func /* f */, const Tup& /* t */, OutIter out) const { + return out; + } + }; +}; + +// Successively invokes 'f(element)' on each element of the tuple 't', +// appending each result to the 'out' iterator. Returns the final value +// of 'out'. +template +OutIter TransformTupleValues(Func f, const Tuple& t, OutIter out) { + return TransformTupleValuesHelper::Run(f, t, out); +} + +// Implements A(). +template +class AnyMatcherImpl : public MatcherInterface { + public: + bool MatchAndExplain(const T& /* x */, + MatchResultListener* /* listener */) const override { + return true; + } + void DescribeTo(::std::ostream* os) const override { *os << "is anything"; } + void DescribeNegationTo(::std::ostream* os) const override { + // This is mostly for completeness' safe, as it's not very useful + // to write Not(A()). However we cannot completely rule out + // such a possibility, and it doesn't hurt to be prepared. + *os << "never matches"; + } +}; + +// Implements _, a matcher that matches any value of any +// type. This is a polymorphic matcher, so we need a template type +// conversion operator to make it appearing as a Matcher for any +// type T. +class AnythingMatcher { + public: + template + operator Matcher() const { return A(); } +}; + +// Implements the polymorphic IsNull() matcher, which matches any raw or smart +// pointer that is NULL. +class IsNullMatcher { + public: + template + bool MatchAndExplain(const Pointer& p, + MatchResultListener* /* listener */) const { + return p == nullptr; + } + + void DescribeTo(::std::ostream* os) const { *os << "is NULL"; } + void DescribeNegationTo(::std::ostream* os) const { + *os << "isn't NULL"; + } +}; + +// Implements the polymorphic NotNull() matcher, which matches any raw or smart +// pointer that is not NULL. +class NotNullMatcher { + public: + template + bool MatchAndExplain(const Pointer& p, + MatchResultListener* /* listener */) const { + return p != nullptr; + } + + void DescribeTo(::std::ostream* os) const { *os << "isn't NULL"; } + void DescribeNegationTo(::std::ostream* os) const { + *os << "is NULL"; + } +}; + +// Ref(variable) matches any argument that is a reference to +// 'variable'. This matcher is polymorphic as it can match any +// super type of the type of 'variable'. +// +// The RefMatcher template class implements Ref(variable). It can +// only be instantiated with a reference type. This prevents a user +// from mistakenly using Ref(x) to match a non-reference function +// argument. For example, the following will righteously cause a +// compiler error: +// +// int n; +// Matcher m1 = Ref(n); // This won't compile. +// Matcher m2 = Ref(n); // This will compile. +template +class RefMatcher; + +template +class RefMatcher { + // Google Mock is a generic framework and thus needs to support + // mocking any function types, including those that take non-const + // reference arguments. Therefore the template parameter T (and + // Super below) can be instantiated to either a const type or a + // non-const type. + public: + // RefMatcher() takes a T& instead of const T&, as we want the + // compiler to catch using Ref(const_value) as a matcher for a + // non-const reference. + explicit RefMatcher(T& x) : object_(x) {} // NOLINT + + template + operator Matcher() const { + // By passing object_ (type T&) to Impl(), which expects a Super&, + // we make sure that Super is a super type of T. In particular, + // this catches using Ref(const_value) as a matcher for a + // non-const reference, as you cannot implicitly convert a const + // reference to a non-const reference. + return MakeMatcher(new Impl(object_)); + } + + private: + template + class Impl : public MatcherInterface { + public: + explicit Impl(Super& x) : object_(x) {} // NOLINT + + // MatchAndExplain() takes a Super& (as opposed to const Super&) + // in order to match the interface MatcherInterface. + bool MatchAndExplain(Super& x, + MatchResultListener* listener) const override { + *listener << "which is located @" << static_cast(&x); + return &x == &object_; + } + + void DescribeTo(::std::ostream* os) const override { + *os << "references the variable "; + UniversalPrinter::Print(object_, os); + } + + void DescribeNegationTo(::std::ostream* os) const override { + *os << "does not reference the variable "; + UniversalPrinter::Print(object_, os); + } + + private: + const Super& object_; + + GTEST_DISALLOW_ASSIGN_(Impl); + }; + + T& object_; + + GTEST_DISALLOW_ASSIGN_(RefMatcher); +}; + +// Polymorphic helper functions for narrow and wide string matchers. +inline bool CaseInsensitiveCStringEquals(const char* lhs, const char* rhs) { + return String::CaseInsensitiveCStringEquals(lhs, rhs); +} + +inline bool CaseInsensitiveCStringEquals(const wchar_t* lhs, + const wchar_t* rhs) { + return String::CaseInsensitiveWideCStringEquals(lhs, rhs); +} + +// String comparison for narrow or wide strings that can have embedded NUL +// characters. +template +bool CaseInsensitiveStringEquals(const StringType& s1, + const StringType& s2) { + // Are the heads equal? + if (!CaseInsensitiveCStringEquals(s1.c_str(), s2.c_str())) { + return false; + } + + // Skip the equal heads. + const typename StringType::value_type nul = 0; + const size_t i1 = s1.find(nul), i2 = s2.find(nul); + + // Are we at the end of either s1 or s2? + if (i1 == StringType::npos || i2 == StringType::npos) { + return i1 == i2; + } + + // Are the tails equal? + return CaseInsensitiveStringEquals(s1.substr(i1 + 1), s2.substr(i2 + 1)); +} + +// String matchers. + +// Implements equality-based string matchers like StrEq, StrCaseNe, and etc. +template +class StrEqualityMatcher { + public: + StrEqualityMatcher(const StringType& str, bool expect_eq, + bool case_sensitive) + : string_(str), expect_eq_(expect_eq), case_sensitive_(case_sensitive) {} + +#if GTEST_HAS_ABSL + bool MatchAndExplain(const absl::string_view& s, + MatchResultListener* listener) const { + // This should fail to compile if absl::string_view is used with wide + // strings. + const StringType& str = std::string(s); + return MatchAndExplain(str, listener); + } +#endif // GTEST_HAS_ABSL + + // Accepts pointer types, particularly: + // const char* + // char* + // const wchar_t* + // wchar_t* + template + bool MatchAndExplain(CharType* s, MatchResultListener* listener) const { + if (s == nullptr) { + return !expect_eq_; + } + return MatchAndExplain(StringType(s), listener); + } + + // Matches anything that can convert to StringType. + // + // This is a template, not just a plain function with const StringType&, + // because absl::string_view has some interfering non-explicit constructors. + template + bool MatchAndExplain(const MatcheeStringType& s, + MatchResultListener* /* listener */) const { + const StringType& s2(s); + const bool eq = case_sensitive_ ? s2 == string_ : + CaseInsensitiveStringEquals(s2, string_); + return expect_eq_ == eq; + } + + void DescribeTo(::std::ostream* os) const { + DescribeToHelper(expect_eq_, os); + } + + void DescribeNegationTo(::std::ostream* os) const { + DescribeToHelper(!expect_eq_, os); + } + + private: + void DescribeToHelper(bool expect_eq, ::std::ostream* os) const { + *os << (expect_eq ? "is " : "isn't "); + *os << "equal to "; + if (!case_sensitive_) { + *os << "(ignoring case) "; + } + UniversalPrint(string_, os); + } + + const StringType string_; + const bool expect_eq_; + const bool case_sensitive_; + + GTEST_DISALLOW_ASSIGN_(StrEqualityMatcher); +}; + +// Implements the polymorphic HasSubstr(substring) matcher, which +// can be used as a Matcher as long as T can be converted to a +// string. +template +class HasSubstrMatcher { + public: + explicit HasSubstrMatcher(const StringType& substring) + : substring_(substring) {} + +#if GTEST_HAS_ABSL + bool MatchAndExplain(const absl::string_view& s, + MatchResultListener* listener) const { + // This should fail to compile if absl::string_view is used with wide + // strings. + const StringType& str = std::string(s); + return MatchAndExplain(str, listener); + } +#endif // GTEST_HAS_ABSL + + // Accepts pointer types, particularly: + // const char* + // char* + // const wchar_t* + // wchar_t* + template + bool MatchAndExplain(CharType* s, MatchResultListener* listener) const { + return s != nullptr && MatchAndExplain(StringType(s), listener); + } + + // Matches anything that can convert to StringType. + // + // This is a template, not just a plain function with const StringType&, + // because absl::string_view has some interfering non-explicit constructors. + template + bool MatchAndExplain(const MatcheeStringType& s, + MatchResultListener* /* listener */) const { + const StringType& s2(s); + return s2.find(substring_) != StringType::npos; + } + + // Describes what this matcher matches. + void DescribeTo(::std::ostream* os) const { + *os << "has substring "; + UniversalPrint(substring_, os); + } + + void DescribeNegationTo(::std::ostream* os) const { + *os << "has no substring "; + UniversalPrint(substring_, os); + } + + private: + const StringType substring_; + + GTEST_DISALLOW_ASSIGN_(HasSubstrMatcher); +}; + +// Implements the polymorphic StartsWith(substring) matcher, which +// can be used as a Matcher as long as T can be converted to a +// string. +template +class StartsWithMatcher { + public: + explicit StartsWithMatcher(const StringType& prefix) : prefix_(prefix) { + } + +#if GTEST_HAS_ABSL + bool MatchAndExplain(const absl::string_view& s, + MatchResultListener* listener) const { + // This should fail to compile if absl::string_view is used with wide + // strings. + const StringType& str = std::string(s); + return MatchAndExplain(str, listener); + } +#endif // GTEST_HAS_ABSL + + // Accepts pointer types, particularly: + // const char* + // char* + // const wchar_t* + // wchar_t* + template + bool MatchAndExplain(CharType* s, MatchResultListener* listener) const { + return s != nullptr && MatchAndExplain(StringType(s), listener); + } + + // Matches anything that can convert to StringType. + // + // This is a template, not just a plain function with const StringType&, + // because absl::string_view has some interfering non-explicit constructors. + template + bool MatchAndExplain(const MatcheeStringType& s, + MatchResultListener* /* listener */) const { + const StringType& s2(s); + return s2.length() >= prefix_.length() && + s2.substr(0, prefix_.length()) == prefix_; + } + + void DescribeTo(::std::ostream* os) const { + *os << "starts with "; + UniversalPrint(prefix_, os); + } + + void DescribeNegationTo(::std::ostream* os) const { + *os << "doesn't start with "; + UniversalPrint(prefix_, os); + } + + private: + const StringType prefix_; + + GTEST_DISALLOW_ASSIGN_(StartsWithMatcher); +}; + +// Implements the polymorphic EndsWith(substring) matcher, which +// can be used as a Matcher as long as T can be converted to a +// string. +template +class EndsWithMatcher { + public: + explicit EndsWithMatcher(const StringType& suffix) : suffix_(suffix) {} + +#if GTEST_HAS_ABSL + bool MatchAndExplain(const absl::string_view& s, + MatchResultListener* listener) const { + // This should fail to compile if absl::string_view is used with wide + // strings. + const StringType& str = std::string(s); + return MatchAndExplain(str, listener); + } +#endif // GTEST_HAS_ABSL + + // Accepts pointer types, particularly: + // const char* + // char* + // const wchar_t* + // wchar_t* + template + bool MatchAndExplain(CharType* s, MatchResultListener* listener) const { + return s != nullptr && MatchAndExplain(StringType(s), listener); + } + + // Matches anything that can convert to StringType. + // + // This is a template, not just a plain function with const StringType&, + // because absl::string_view has some interfering non-explicit constructors. + template + bool MatchAndExplain(const MatcheeStringType& s, + MatchResultListener* /* listener */) const { + const StringType& s2(s); + return s2.length() >= suffix_.length() && + s2.substr(s2.length() - suffix_.length()) == suffix_; + } + + void DescribeTo(::std::ostream* os) const { + *os << "ends with "; + UniversalPrint(suffix_, os); + } + + void DescribeNegationTo(::std::ostream* os) const { + *os << "doesn't end with "; + UniversalPrint(suffix_, os); + } + + private: + const StringType suffix_; + + GTEST_DISALLOW_ASSIGN_(EndsWithMatcher); +}; + +// Implements a matcher that compares the two fields of a 2-tuple +// using one of the ==, <=, <, etc, operators. The two fields being +// compared don't have to have the same type. +// +// The matcher defined here is polymorphic (for example, Eq() can be +// used to match a std::tuple, a std::tuple, +// etc). Therefore we use a template type conversion operator in the +// implementation. +template +class PairMatchBase { + public: + template + operator Matcher<::std::tuple>() const { + return Matcher<::std::tuple>(new Impl&>); + } + template + operator Matcher&>() const { + return MakeMatcher(new Impl&>); + } + + private: + static ::std::ostream& GetDesc(::std::ostream& os) { // NOLINT + return os << D::Desc(); + } + + template + class Impl : public MatcherInterface { + public: + bool MatchAndExplain(Tuple args, + MatchResultListener* /* listener */) const override { + return Op()(::std::get<0>(args), ::std::get<1>(args)); + } + void DescribeTo(::std::ostream* os) const override { + *os << "are " << GetDesc; + } + void DescribeNegationTo(::std::ostream* os) const override { + *os << "aren't " << GetDesc; + } + }; +}; + +class Eq2Matcher : public PairMatchBase { + public: + static const char* Desc() { return "an equal pair"; } +}; +class Ne2Matcher : public PairMatchBase { + public: + static const char* Desc() { return "an unequal pair"; } +}; +class Lt2Matcher : public PairMatchBase { + public: + static const char* Desc() { return "a pair where the first < the second"; } +}; +class Gt2Matcher : public PairMatchBase { + public: + static const char* Desc() { return "a pair where the first > the second"; } +}; +class Le2Matcher : public PairMatchBase { + public: + static const char* Desc() { return "a pair where the first <= the second"; } +}; +class Ge2Matcher : public PairMatchBase { + public: + static const char* Desc() { return "a pair where the first >= the second"; } +}; + +// Implements the Not(...) matcher for a particular argument type T. +// We do not nest it inside the NotMatcher class template, as that +// will prevent different instantiations of NotMatcher from sharing +// the same NotMatcherImpl class. +template +class NotMatcherImpl : public MatcherInterface { + public: + explicit NotMatcherImpl(const Matcher& matcher) + : matcher_(matcher) {} + + bool MatchAndExplain(const T& x, + MatchResultListener* listener) const override { + return !matcher_.MatchAndExplain(x, listener); + } + + void DescribeTo(::std::ostream* os) const override { + matcher_.DescribeNegationTo(os); + } + + void DescribeNegationTo(::std::ostream* os) const override { + matcher_.DescribeTo(os); + } + + private: + const Matcher matcher_; + + GTEST_DISALLOW_ASSIGN_(NotMatcherImpl); +}; + +// Implements the Not(m) matcher, which matches a value that doesn't +// match matcher m. +template +class NotMatcher { + public: + explicit NotMatcher(InnerMatcher matcher) : matcher_(matcher) {} + + // This template type conversion operator allows Not(m) to be used + // to match any type m can match. + template + operator Matcher() const { + return Matcher(new NotMatcherImpl(SafeMatcherCast(matcher_))); + } + + private: + InnerMatcher matcher_; + + GTEST_DISALLOW_ASSIGN_(NotMatcher); +}; + +// Implements the AllOf(m1, m2) matcher for a particular argument type +// T. We do not nest it inside the BothOfMatcher class template, as +// that will prevent different instantiations of BothOfMatcher from +// sharing the same BothOfMatcherImpl class. +template +class AllOfMatcherImpl : public MatcherInterface { + public: + explicit AllOfMatcherImpl(std::vector > matchers) + : matchers_(std::move(matchers)) {} + + void DescribeTo(::std::ostream* os) const override { + *os << "("; + for (size_t i = 0; i < matchers_.size(); ++i) { + if (i != 0) *os << ") and ("; + matchers_[i].DescribeTo(os); + } + *os << ")"; + } + + void DescribeNegationTo(::std::ostream* os) const override { + *os << "("; + for (size_t i = 0; i < matchers_.size(); ++i) { + if (i != 0) *os << ") or ("; + matchers_[i].DescribeNegationTo(os); + } + *os << ")"; + } + + bool MatchAndExplain(const T& x, + MatchResultListener* listener) const override { + // If either matcher1_ or matcher2_ doesn't match x, we only need + // to explain why one of them fails. + std::string all_match_result; + + for (size_t i = 0; i < matchers_.size(); ++i) { + StringMatchResultListener slistener; + if (matchers_[i].MatchAndExplain(x, &slistener)) { + if (all_match_result.empty()) { + all_match_result = slistener.str(); + } else { + std::string result = slistener.str(); + if (!result.empty()) { + all_match_result += ", and "; + all_match_result += result; + } + } + } else { + *listener << slistener.str(); + return false; + } + } + + // Otherwise we need to explain why *both* of them match. + *listener << all_match_result; + return true; + } + + private: + const std::vector > matchers_; + + GTEST_DISALLOW_ASSIGN_(AllOfMatcherImpl); +}; + +// VariadicMatcher is used for the variadic implementation of +// AllOf(m_1, m_2, ...) and AnyOf(m_1, m_2, ...). +// CombiningMatcher is used to recursively combine the provided matchers +// (of type Args...). +template

    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�%6(VbrAkY5+_2UD8QDEvL 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 z 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 literal 0 HcmV?d00001 From bb518a3e4cccc0ddf09d4d0362a1a08e23c15924 Mon Sep 17 00:00:00 2001 From: Nils Wentzell Date: Tue, 16 Apr 2019 17:54:36 -0400 Subject: [PATCH 071/272] [doc] Small fix in conf.py.in --- doc/conf.py.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/conf.py.in b/doc/conf.py.in index 1d95c317..ff1b11f9 100644 --- a/doc/conf.py.in +++ b/doc/conf.py.in @@ -21,7 +21,7 @@ source_suffix = '.rst' project = u'APP4TRIQS - An example triqs application' copyright = u'2018 - The TRIQS Developers' -version = '@APP4TRIQS_VERSION' +version = '@APP4TRIQS_VERSION@' mathjax_path = "@TRIQS_MATHJAX_PATH@/MathJax.js?config=default" templates_path = ['@CMAKE_SOURCE_DIR@/doc/_templates'] From 87a67e8d06ac833665eeae7fafa336727d2dd667 Mon Sep 17 00:00:00 2001 From: Nils Wentzell Date: Mon, 22 Apr 2019 11:24:53 -0400 Subject: [PATCH 072/272] [cmake] Add -Wextra compiler warnings globally --- CMakeLists.txt | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 18eb0de3..75fcf704 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -18,10 +18,12 @@ set(BUILD_SHARED_LIBS OFF) set(CMAKE_EXPORT_COMPILE_COMMANDS ON) # Enable compiler warnings for the whole project -add_compile_options(-Wall - $<$:-Og> - $<$:-ggdb3> - ) +add_compile_options( + -Wall + -Wextra + $<$:-Og> + $<$:-ggdb3> + ) # Load Dependencies find_package(TRIQS 2.2 REQUIRED) From 9315b028006d742cb0c04bfa3d99ade4da1737de Mon Sep 17 00:00:00 2001 From: Nils Wentzell Date: Mon, 22 Apr 2019 11:25:20 -0400 Subject: [PATCH 073/272] We should be using the triqs::gtest target for linking --- test/c++/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/c++/CMakeLists.txt b/test/c++/CMakeLists.txt index 533922e1..b2961064 100644 --- a/test/c++/CMakeLists.txt +++ b/test/c++/CMakeLists.txt @@ -10,7 +10,7 @@ set(all_tests toto) foreach(test ${all_tests}) get_filename_component(test_name ${test} NAME_WE) add_executable(${test_name} ${test}) - target_link_libraries(${test_name} app4triqs_c gtest) + target_link_libraries(${test_name} app4triqs_c triqs::gtest) add_test(${test_name} ${test_name}) # Run clang-tidy if found if(CLANG_TIDY_EXECUTABLE) From 6289a962362b58705c623249752e51f2a3772c78 Mon Sep 17 00:00:00 2001 From: Nils Wentzell Date: Tue, 23 Apr 2019 11:57:54 -0400 Subject: [PATCH 074/272] Regenerate python module after latest cpp2py adjustments --- python/app4triqs/toto_module_desc.py | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/python/app4triqs/toto_module_desc.py b/python/app4triqs/toto_module_desc.py index a9117fc2..d19a7e24 100644 --- a/python/app4triqs/toto_module_desc.py +++ b/python/app4triqs/toto_module_desc.py @@ -6,6 +6,7 @@ from cpp2py.wrap_generator import * module = module_(full_name = "toto_module", doc = "", app_name = "app4triqs") # Imports +module.add_imports(*[]) # Add here all includes module.add_include("app4triqs/toto.hpp") @@ -25,9 +26,6 @@ c = class_( c_type = "app4triqs::toto", # name of the C++ class doc = """A very useful and important class\n\n @note A Useful note""", # doc of the C++ class hdf5 = True, - arithmetic = ("add_only"), - comparisons = "==", - serializable = "tuple", ) c.add_constructor("""()""", doc = """""") @@ -44,8 +42,8 @@ c.add_property(name = "i", module.add_class(c) -module.add_function ("int app4triqs::chain (int i, int j)", doc = """Chain digits of two integers\n\n Chain the decimal digits of two integers i and j, and return a new \n\n @param :math:`i` The first integer\n @param :math:`j` The second integer \n @return An integer containing the digits of both i and j\n\n @remark""") +module.add_function ("int app4triqs::chain (int i, int j)", doc = """Chain digits of two integers\n\n Chain the decimal digits of two integers i and j, and return the result\n\n @param :math:`i` The first integer\n @param :math:`j` The second integer\n @return An integer containing the digits of both i and j\n\n @remark""") -module.generate_code() +module.generate_code() \ No newline at end of file From 815b39733394c28e10c65676b276fab951d24ef8 Mon Sep 17 00:00:00 2001 From: Nils Wentzell Date: Tue, 23 Apr 2019 12:58:11 -0400 Subject: [PATCH 075/272] Add back manual adjustments to toto_module_desc.py --- python/app4triqs/toto_module_desc.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/python/app4triqs/toto_module_desc.py b/python/app4triqs/toto_module_desc.py index d19a7e24..859b72bc 100644 --- a/python/app4triqs/toto_module_desc.py +++ b/python/app4triqs/toto_module_desc.py @@ -26,6 +26,9 @@ c = class_( c_type = "app4triqs::toto", # name of the C++ class doc = """A very useful and important class\n\n @note A Useful note""", # doc of the C++ class hdf5 = True, + arithmetic = ("add_only"), + comparisons = "==", + serializable = "tuple" ) c.add_constructor("""()""", doc = """""") From 60671ba75bc786511e89d0464f168ce6bc097746 Mon Sep 17 00:00:00 2001 From: "Hugo U. R. Strand" Date: Tue, 23 Apr 2019 14:14:34 -0400 Subject: [PATCH 076/272] [autodoc] adding python autodoc of c++ wrapped python module --- doc/contents.rst | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/doc/contents.rst b/doc/contents.rst index 217ae295..ed14d6b1 100644 --- a/doc/contents.rst +++ b/doc/contents.rst @@ -15,11 +15,20 @@ Contents changelog about -Reference manual ----------------- +C++ reference manual +-------------------- .. toctree:: :maxdepth: 5 cpp2rst_generated/app4triqs/toto cpp2rst_generated/app4triqs/chain + +Python reference manual +----------------------- + +.. autoclass:: app4triqs.toto_module.toto + :members: + +.. autofunction:: app4triqs.toto_module.chain + From e05590249699ad6f0212d8acfd7ff09cd6bf4229 Mon Sep 17 00:00:00 2001 From: Olivier Parcollet Date: Tue, 23 Apr 2019 13:33:57 -0400 Subject: [PATCH 077/272] Make doc a bit more complex --- c++/app4triqs/toto.hpp | 13 +++++++-- doc/conf.py.in | 2 +- doc/contents.rst | 12 ++++++++ python/app4triqs/toto_module_desc.py | 42 +++++++++++++++++++++++----- 4 files changed, 58 insertions(+), 11 deletions(-) diff --git a/c++/app4triqs/toto.hpp b/c++/app4triqs/toto.hpp index ea4f3052..4509e741 100644 --- a/c++/app4triqs/toto.hpp +++ b/c++/app4triqs/toto.hpp @@ -18,7 +18,7 @@ namespace app4triqs { /** * Construct from integer * - * @param i_ a scalar + * @param i_ a scalar :math:`G(\tau)` */ explicit toto(int i_) : i(i_) {} @@ -35,6 +35,13 @@ namespace app4triqs { /// Simple accessor int get_i() const { return i; } + /** + * A simple function with :math:`G(\tau)` + * + * @param u Nothing useful + */ + int f(int u) { return u;} + /// Arithmetic operations toto operator+(toto const &b) const; toto &operator+=(toto const &b); @@ -57,8 +64,8 @@ namespace app4triqs { * * Chain the decimal digits of two integers i and j, and return the result * - * @param :math:`i` The first integer - * @param :math:`j` The second integer + * @param i The first integer + * @param j The second integer * @return An integer containing the digits of both i and j * * @remark diff --git a/doc/conf.py.in b/doc/conf.py.in index ff1b11f9..4f7cb541 100644 --- a/doc/conf.py.in +++ b/doc/conf.py.in @@ -13,8 +13,8 @@ extensions = ['sphinx.ext.autodoc', 'sphinx.ext.todo', 'sphinx.ext.viewcode', 'sphinx.ext.autosummary', - 'plot_directive', 'numpydoc', + 'plot_directive', 'autorun'] source_suffix = '.rst' diff --git a/doc/contents.rst b/doc/contents.rst index 217ae295..727af951 100644 --- a/doc/contents.rst +++ b/doc/contents.rst @@ -6,6 +6,12 @@ Documentation Contents -------- +.. math:: + + (a + b)^2 &= (a + b)(a + b) \\ + &= a^2 + 2ab + b^2 + + .. toctree:: :maxdepth: 5 @@ -15,6 +21,12 @@ Contents changelog about +Python +------ + +.. automodule:: app4triqs + :members: + Reference manual ---------------- diff --git a/python/app4triqs/toto_module_desc.py b/python/app4triqs/toto_module_desc.py index 859b72bc..e7eea446 100644 --- a/python/app4triqs/toto_module_desc.py +++ b/python/app4triqs/toto_module_desc.py @@ -1,5 +1,5 @@ # Generated automatically using the command : -# c++2py ../../c++/app4triqs/toto.hpp -p --members_read_only -N app4triqs -a app4triqs -m toto_module -o toto_module -C pytriqs --cxxflags="-std=c++17" +# c++2py ../../c++/app4triqs/toto.hpp -p --members_read_only -N app4triqs -a app4triqs -m toto_module -o toto_module -C pytriqs --cxxflags="-std=c++17 " from cpp2py.wrap_generator import * # The module @@ -24,20 +24,33 @@ using namespace app4triqs; c = class_( py_type = "Toto", # name of the python class c_type = "app4triqs::toto", # name of the C++ class - doc = """A very useful and important class\n\n @note A Useful note""", # doc of the C++ class + doc = r"""A very useful and important class""", # doc of the C++ class hdf5 = True, arithmetic = ("add_only"), comparisons = "==", serializable = "tuple" ) -c.add_constructor("""()""", doc = """""") +c.add_constructor("""()""", doc = r"""""") -c.add_constructor("""(int i_)""", doc = """Construct from integer\n\n :param i_: a scalar""") +c.add_constructor("""(int i_)""", doc = r"""Construct from integer + +Parameters +---------- +i_ + a scalar :math:`G(\tau)`""") + +c.add_method("""int f (int u)""", + doc = r"""A simple function with :math:`G(\tau)` + +Parameters +---------- +u + Nothing useful""") c.add_method("""std::string hdf5_scheme ()""", is_static = True, - doc = """HDF5""") + doc = r"""HDF5""") c.add_property(name = "i", getter = cfunction("int get_i ()"), @@ -45,8 +58,23 @@ c.add_property(name = "i", module.add_class(c) -module.add_function ("int app4triqs::chain (int i, int j)", doc = """Chain digits of two integers\n\n Chain the decimal digits of two integers i and j, and return the result\n\n @param :math:`i` The first integer\n @param :math:`j` The second integer\n @return An integer containing the digits of both i and j\n\n @remark""") +module.add_function ("int app4triqs::chain (int i, int j)", doc = r"""Chain digits of two integers + + Chain the decimal digits of two integers i and j, and return the result + +Parameters +---------- +i + The first integer + +j + The second integer + +Returns +------- +out + An integer containing the digits of both i and j""") -module.generate_code() \ No newline at end of file +module.generate_code() From 7811ee514e43f4b4a823df40ddc5264dc08f2706 Mon Sep 17 00:00:00 2001 From: Olivier Parcollet Date: Tue, 23 Apr 2019 16:53:50 -0400 Subject: [PATCH 078/272] Enable doc building on Jenkins --- Jenkinsfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Jenkinsfile b/Jenkinsfile index b7d3e649..c45f79e2 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -6,7 +6,7 @@ def documentationPlatform = "ubuntu-clang" def triqsBranch = env.CHANGE_TARGET ?: env.BRANCH_NAME def triqsProject = '/TRIQS/triqs/' + triqsBranch.replaceAll('/', '%2F') /* whether to publish the results (disabled for template project) */ -def publish = !env.BRANCH_NAME.startsWith("PR-") && projectName != "app4triqs" +def publish = !env.BRANCH_NAME.startsWith("PR-") properties([ disableConcurrentBuilds(), From 984ead7f5d8e45fc2a1681d67296d33e62d3df7f Mon Sep 17 00:00:00 2001 From: Dylan Simon Date: Wed, 24 Apr 2019 14:08:48 -0400 Subject: [PATCH 079/272] [jenkins] only update docker submodule if it exists --- Jenkinsfile | 1 + 1 file changed, 1 insertion(+) diff --git a/Jenkinsfile b/Jenkinsfile index c45f79e2..e5a6e8b0 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -113,6 +113,7 @@ try { /* Update docker repo submodule */ if (release) { dir("$workDir/docker") { try { git(url: "ssh://git@github.com/TRIQS/docker.git", branch: env.BRANCH_NAME, credentialsId: "ssh", changelog: false) + sh "test -d ${projectName}" sh "echo '160000 commit ${commit}\t${projectName}' | git update-index --index-info" sh """ git commit --author='Flatiron Jenkins ' --allow-empty -m 'Autoupdate ${projectName}' -m '${env.BUILD_TAG}' From e329acfa06246805ae0b4eaebbe31af87282aa64 Mon Sep 17 00:00:00 2001 From: Nils Wentzell Date: Thu, 25 Apr 2019 13:52:22 -0400 Subject: [PATCH 080/272] Remove warning about unused variable --- c++/app4triqs/toto.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/c++/app4triqs/toto.hpp b/c++/app4triqs/toto.hpp index 4509e741..024d619c 100644 --- a/c++/app4triqs/toto.hpp +++ b/c++/app4triqs/toto.hpp @@ -56,7 +56,7 @@ namespace app4triqs { friend void h5_read(triqs::h5::group grp, std::string subgroup_name, toto &m); /// Serialization - template void serialize(Archive &ar, const unsigned int version) { ar &i; } + template void serialize(Archive &ar, const unsigned int) { ar &i; } }; /** From e03eb002cf5762a9d00898394fb4a7220244ce36 Mon Sep 17 00:00:00 2001 From: Nils Wentzell Date: Thu, 25 Apr 2019 13:53:33 -0400 Subject: [PATCH 081/272] [cmake] docs_sphinx target should depend on generated module due to autodoc usage, Fix #2 --- doc/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/CMakeLists.txt b/doc/CMakeLists.txt index 3b0d75e5..ed7d1c4b 100644 --- a/doc/CMakeLists.txt +++ b/doc/CMakeLists.txt @@ -13,7 +13,7 @@ add_custom_command(OUTPUT ${sphinx_top} DEPENDS ${sources} add_custom_target(docs_sphinx ALL DEPENDS ${sphinx_top} ${CMAKE_CURRENT_BINARY_DIR}) # Application must be compiled first -add_dependencies(docs_sphinx app4triqs_c) +add_dependencies(docs_sphinx app4triqs_c toto_module) # ------------------------------------------------------------------------------------------------ # Copy the directory substructure and link all files with relevant extensions From a113230ffecfc416608859a070c423246db98839 Mon Sep 17 00:00:00 2001 From: Nils Wentzell Date: Thu, 25 Apr 2019 13:54:23 -0400 Subject: [PATCH 082/272] [cmake] Avoid use of list(FILTER ..) to restore cmake version 3.0.2 compatibility --- python/app4triqs/CMakeLists.txt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/python/app4triqs/CMakeLists.txt b/python/app4triqs/CMakeLists.txt index 3eb11b72..2de26908 100644 --- a/python/app4triqs/CMakeLists.txt +++ b/python/app4triqs/CMakeLists.txt @@ -7,7 +7,8 @@ configure_file(version.py.in version.py) # All Python files. Copy them in the build dir to have a complete package for the tests. file(GLOB_RECURSE python_sources RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} *.py) -list(FILTER python_sources EXCLUDE REGEX "_desc.py") +file(GLOB_RECURSE wrap_generators RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} *_desc.py) +list(REMOVE_ITEM python_sources "${wrap_generators}") foreach(file ${python_sources}) configure_file(${file} ${file} COPYONLY) endforeach() From 171dbcdecfaaeef3853a893875674d695b956fcb Mon Sep 17 00:00:00 2001 From: "Hugo U. R. Strand" Date: Wed, 24 Apr 2019 15:19:25 -0400 Subject: [PATCH 083/272] [doc] install and first page + github logo --- doc/_static/logo_github.png | Bin 0 -> 13001 bytes doc/_templates/sideb.html | 2 +- doc/index.rst | 8 ++++---- doc/install.rst | 24 +++++++++++------------- 4 files changed, 16 insertions(+), 18 deletions(-) create mode 100644 doc/_static/logo_github.png diff --git a/doc/_static/logo_github.png b/doc/_static/logo_github.png new file mode 100644 index 0000000000000000000000000000000000000000..e03d8dd8bcf0d851fe1eb89f93a39de843e5c69c GIT binary patch literal 13001 zcmeIYXHb*d+bJ(fiT{_ zrFjnmIkp6W(4?K92XEetxHEt+c7&E0!U*ny2(#uLisrxp$v>2QJ#)+PFGcwc@-bZg9*Hy5%#Vd%{9OgB`8m1B-_z9o&syL~>8cw7;VUmH8WOI*T11@Oo#eIEpxWZ%P$@B}gqV!1xVXBc zl)9$6xCB&97AhyFCid?f|J_&(by=vay0(_2tR$F2OHxfnQ(Rq2OhQ6kLQ_m!Tl(Lz zw|)E(_CAiz|E}u}*8R^|&Hr(%yoR5%Jp%4$42OIDYXNuN;0U zQbI=a>VL*M{lAf#C?H0ZY99ZGx%~SI*dX=ie;Ge`_%HWy_5nWQ2b|+<`2HIRL}cf- zrke4?@n2IXUvu40g|0_m`CBzSIp6u|`!$8G{71amyydlGm>aW?=48*}zT%b^R~H{) zzQ@Xczj33y>vO@es55k*n!C=HKjHd?aQpO9^~B!voba2>=XnkO@WA1>GiyQ91svQ< zC8)kSa#8^h9S(`{GePA5>JB zr3dLY`Tzne5zwg3v)6edR5m?6QrCi=-6QSy;ab6Ef`ACcf zUsc&`;SA4~8D8U9@{abDsR&QpxwR*M1DgpC7s)mii7n-d;lfrYjF%Uc#6p8i*zs#o z^}@ttzaT@p9oC)`bO;E94nc#?rQOpm8xtgM!4!0g9b68CYiBMZ(fHx{-|;6_MBN#w z_DEYFJ{_;BEY1SIsS)%}`s-u0Ucto{n^{$+19RR)NvDr-LjXIDx>`!sA# zC`FH*Qhf`G-FL+A!4|d6j$)FjMoi^|6#3h<-5~+jirG%!fVU|KWROF(@TsttXYUWA z{?iL8o2?^eSWp!97qR~nVHum8hY^V-JD>V>e#F)No~dct8Q_(#tQN8|!8Vx%q`*VfgwD)WvAJP2Gn{EKX%clQP6dyBiKa z8j}a-8FVzKIOb~O13pB(BPmOANl%x5Ttjz{$iCr+um9%bgBNYomvU9TyP~ODz{O)= z5~Vw1Vq;mk+H261$GOW@z$k`EF4-d|c&?AdN$+G!B$tUk*)~%@?ZN(ah*gj$j_iUj zME)gM+UJ&;Z}hb0nT3i+1O`beMzq1d;0j_!2z5+aQohYEdpHTGkHa89cxOW$um*ep-JvE5LM<{`X+7~w>QA z-ud-`wMAl3ke$$Kl>ED;gE;%a^IOZa@Ix^Vb|X4~<1${HRdvKDUsAC#K0~pvArcO! z51Vxal|@qovM#TuOIMa(o0i*FxNIu_c!izfc9SB)*$&}N~45b zzgNnAFCT;G_M>9h(O}PVyhPj|5gR}(6j;KdEMQQMwQo31!D@p}Eq$ChPs_Q|!m2y` zR0D~;&}%Bxx+hStR@+$90ylWFu*m6H24~!V-F$a9n(${GyVky4vjZ6q^i;NS)pDPT z?VL?>siG1Obvz594VO{%H;sTlCFt>lutS+?TyW|tF*Nt)aVm+JPkrahWHtHO>;mx8 zmn^b&T>FP2rUtmET7B|_gs@%*_8|P_+Mr7s(EBqlezv?9UoU8HFMo;zp(_|CI zvt{CKr@WwT4a?d3LRfghxs5=U+C|eq?(!Sdt!AG%!Pzm(mSIQZv%IpFZj-b1O}66D z=brJ>*}Y@irwO4K2^SCKtqj)h;jysA4y&e5dMsecQcqb!SN;Pbk4HZ5Aw~jHwnNQ! zQ(wsqYQwas&7cW0D=Ylkue`qYdibR)6c$lSNOzn>l>RH?GUc_E=A_S{cp0T{|ju4A2121~hDx?UsW9LzvZf#xH?b z*kg1gmPt+d91sX{R&Hs<-we+&-hZB8G3(l$<;t`hWW(Gom*Ml!WL`8&Bt})S=F#%j zB5qhB4H_6kphgquouJJFlDxQ+sOFS4JVIr(?5%t0Fg57D$@B_IP;{JRjuFNNM2*XNbYhTFp|XR7 zJ*Y_~Bcb;Rj?)S}m;YXWKVf@A+{)5*}5;mNcM;_h^ zby}nP_q3wEGAc9x@5=XP+MA>C>iYuEuSV#bpUC57lTySI`Avb0P@d(3DGX9ZlgpZG zVqK>K1Ssm#ZMl50`!c>mLoa?OXq`y&VmTwQp6~g4t@NA6ks>h*JMz}PyTxk+xSVO} z;3InlMUOiX)llm|N*qr338^uu;Mb8OqbcQ=*$yd=7sNbN#3lln5Z8W%as21zGMCz>5uesMg29#&22t>M|{<=V>TO?ddYU!(a~CI=Q5QAcT|0SL-Yt=rQgoV2_+tZ zQl0#|E0i>|#s;^ki0tTlVk%v?sBs8tB#)_eTA0`!KH-ujjem88vQzdj?6?N1-r%sQ zEYv?1=z(JMF|_C-w6@RrIomive--*G*On*7 z8)LxvL`6l~W7O;^JhcGpASX;^weV;7otoumxIlU9*J_cQ1(<1OmF8>2>GQjZ?lz&4 z9*MgRDeN?BtPqH@ue6n+>CR(`=RdD=Jqt0U%hHLJ&^SX3yOkqHe1G=%mN~3btC%Nj zc?p+VPX)CG<)-+@XKI#fPbjl;+C;Js+D4Is4r=Z3mRJMfh^^UL8Db*Lvu*9L0LOsj zfP`NMh=pFb6T29w74(K<?T&u}P4nJ6VlFFkTI&=4RyQn(xgd zS(crv%?os7>)Vzj9(`<5VWG$a%tKn_*!=iSxMC$pgeVz#2|^98=}^~drOuu09VIU_ zDlFQp|3WxHu7Gv2fl?7L0~25dLvvV@FK&sU_=y>4&u3a{xItE+wI^P#zD5^a0dWJz z9ryrlqN-9{)3SC_1Lz1_2tsdrWt47r5~dz|{bF$huA6b!a8X<7{^1)DQ~j*PU@RGP zcu)Bz15J~-P0B#^LBB68?Zvq4AOY`=u8kZr{M%uCX8#HSnMndYsb z@JlgHPWeTM?q`!NL~1qLsK-LQQghiSgFH9uBuG}tE& zT@@dsMGbqu_!4kXkmGa$uDXx+?ad9=vO2fi>^wYe<&ZImv@aE1R+aP`3y2~+Zu&dg z%6_7y$P(Anib*!G{SMFI(TCoBB?H0pK4r2kxY4}l`&!;cmGRjUyJa@TA=YSFkEAnD zarD4?4zAU~vM*|$b*}1R%?lo-%!uaitd7JUZFa9NJy;7AbLL~9XZ&GvZ|e+lwg zx88hQA%>_@=OUH6zt||F%*1u^3PpG2T>tUSc9IjGG4ev>#m}Z9Gr6{Be+m*#L7Y~2 zh0So%nEY1-jYpaa)Z}?rB#w1JFY*FCSMN~8oiJu;7!(3Iyq;mbKDS#`X)mP0%dKY=kL1p6H9#CYD#F;wO%`;5}7nHH^R5~ zO5+g7`@0M}8CQ zo{4#`ti~DH>ksrZ;E7n)+JA<##wLqzu@Lug>DYLX=mZ-pfbjVKKKAemkquDHYI?Sy zR^?uVZ)S;M-3<>0BcJ~5SoyzDJM||BB90J9c9$||mZf1-U$LQk`**o^N>aV#SfsnO zS*OMmlKt%j$N@$M0=XMuwRIa1!#dh_raGsFez`W|t&Gj@=Vto`ZS{kFfT z;5}mNGW=c86fNX=6(X!uqw*sIrG4N&X)DX+1W-=&t})p0*uYdz3s-ge_s?7blb`2g zDK3z?k`0x}R`I0vIwg1KG_Wnev)yJBwxF;$J!bgV^w4nABbgIR8dV`ZqhZN^dbm8pQ7Y{R^k>6JvC3fL z_nEQvO2kauQw(<;QPk6AZzlH`cFMV!qbdmR0$Y|YG6mLEcax7=krXPagVktSb0f|1 zNg$u!VcJRA0tw9dm?rFY!g%55BfB3yWj%VDeKt}_bes9UiLz{&i&fbyFqN&fF*OK8=?r$I4SL|{V!u3)lhirp4oTV&$ zITdpKwrhK+jB-jYXCI~V^YRB`b%_RRf80&6F=!hiZNE=`qhYRRDT;$(^UFZGX!;e1 z({(O!L!EaCaXWRc0=soT+jbA0`&`~xW8Vr<$D6=s=yo?424?R;6i7zlxUHin1U zh6x$;*%^&Urhz$tL?Mvh0U%U~eGvm4H@tdATPDuYLR3dY5>Q186Yt~gFZMGyMp7%= z#`i%AsaGaju#jGM&(O3+NAvVj%%(B0*^oO3X!J2ic%$|6k1}^8VrfyUG)m@QKp+A0 z#HU%3yv@FW>0>1LKyXL{F7H&-n7+RvJ#&VEWwGorOQZT(oqkivSV-LZ3QmEueuYqm zIr2CKVGO*F&zH728f8WreFcpqsG5|&@X6b{5r?}dI=f+)2lc^3)%qp9p+ zeMkEDjec74Ri&37WxUKHkZ)Yx(Lg>pG_-UqHy8b2?q{9f0Fk5tptdK`rE~1mtX4|C zMfQRMtbIR3U+7TTBiS6B8@3*~SCoKV6*6H2OI-cTNpu8G zP=I?dY;b58?Q&3y#_yg#Bpun*dj180Z0(rEjW%_!pInN__=#j%N*}Sm#+SR(K0Ep1 zumJ>P6|o)~$mj521?RS#tE3$_z*O8Hrj%fFNFLW+y3LQDe;BMff$sT0J>YpMYbD73A2mp_&x~^F{=vh&esyOl z#gQPX0pPh}Lh@UD6XP`qNCs?Np-$yoo;wI6+)EZz{_+c7e~UB()^8cDxcW2mmn(S5 ztJgjJaBAvr8&#e+piY-sRx6p{FK{^-j}m=6s%)+9?LU0hIvfKh(1M=x~A9zLC51?+Va zzjysXABQpxx*u$@nepv$?B0Vvv;p)lm&oZ@R&E8#(2$nHdViac902qQB9+^%LDig- ztG`o|5(BV(xEBJDoFx%LOTKG;UK)yBk*ft(qTdQozWGwgM!f>C5hi`$IGbjZZw9W% z#gJdV0Den@ekDh3>Hhh(da)nWPxKiDsfh#DEe)94)45M)Iw=a&90Y7E)*uau!DRM% zr4MpVF-cVdyY&>Lt||sreNIIZtT8c?la+Hd2)#s-K#1)#f zw~f9*WKfrfh&@Ukp=C?kZOqIJvsu(Bnu1?Ez8P?Q!PqI+#DqQ{JMv5_?3x@h2=lNU}FApq}O67%v9@^ z?dWrjxw^lZ`)_-?(MSnox18I04mg~^00ESnO-?@VnUW%QoFJ@0fA_lyy3_Q3LEi}( zG1KL=^PSx)cM*~)+PFT+l}fzEcN2i278y6olsNgD0d#~{JHuy`qz1<=Ac(Pi3rNIv zd|K(zO5|Ntcnt!&(;Vqd`WqIgdF$v7p3Vru;miq*r<3;*6b@G_-2YZw143O>F|fwL zjLERc5Bi2WLoJ+0(-5;GH~dSNV^ZoUy21EyNRqT#h-q{H_;w& zTmm>2b-v|Yo`h{?*}B{K_E4Gl95>%{_H}8UwC$0`+*Z>Y`^UOzFFwjN=7XX*HXA#O zmd)s?w(WuPalL=-A+-oUDQxC76Hk7KuZ`TfVx3-ZXkOvC_#jB=hz(?Ak-(c_3PZdj z*W!BUVd*;Frj-UcmP2^wi+4)*$OXQKd$>LhT>x1BLg&l3%+k2K55>XKf^RlZZbazU z$(Mh$;uFXY)Vx#DIotj+9uuYxJ#?{Re-tQuBzJsU!7-H>?-yk2VT)%TXmx#Bm#AxR zpDH0$WLC+2Y}lx>`ET38Gd~EuLy2FJbeq+35;noE?aSNpttV+w48PLj&vhs-bVbwW zDxGpQTyR-q8x?fuZMqwQr1;@w*f$S2h745KD&d;w_h(|hs=SBWj2uk=8XVYihxtd3 zNK;7M-fJA|qLe}(W9PkKXGuA)<+3W?t4 zP-6XVzi+tx6WtX@zl~-bvm=jW=*3U{g_!A=KB1QMq)HJ-{Zj2)uDSiWtcsD*!_EeV#zM$kEx(kE}Y zwJDOcHDvCLqfXXm|oL*NQkSD)MtjUXJVrK1>$T)>E08}6}82MH+ zaayY{`Eb~Z4>A1@tX6wn!%X|i|houvhulrJ2#rYRstsxCljs%2A*8jN(fgbHlIUcWgw*2nB%HXt@4hm z9;a9U00A4Fm`O2^RKV?KacV;TN^z$Vk}=dvRSCRB|L(f=cJMophTT6&2xKi@9-y%a zc){|)!O{dIciG%o!B?4;-Z9dmlGMrOWxMePka^`RN`<>384&sRVYhi6!ADPKtB1Zj zPK&yPRwi0`Lv&k)Xg?et|2#PdYZ<1eY4QU>eW7jk`zOigf3v_%z~zvitB-%5WInN! zbcSHq?vRDkK^)^)i^c)Am%;_H+<1DsS3S|>GAd0>1g6eeVb~Dp(Ik2+P)g}GfB4y7 zwl>l2H|1$!%Wc~Zm&8Guy1d>IG{@2JYx~c6l0v-I1TG&>@cb!;RZIeFYv7;WjnUzQQL6x5hQkkI$QOkBi;t z^rR6xl^H|E08)@=2@MxZZa>XmJys&9_~-#H$ON zz^o22y5;t1^$gQz_hg92B?|m1^Hl{moUgU+0ijKB{vzN6^mM6hO-d zIoPP%F){T+W#v)DLO`zw&tR})ndgsz8~vJD&(ca5Rnt{0b1VFn&1Ll%mKui~vivgv zQFTo(dZSUc2fG9uE0T_bG;V0y&y~ll%CId;_|?daq+QD1bV^I`j0n#prMuTxkkT>S z1B?qlZg@6_+Eg0o9CxchB=<&)LlCOoqF=ub6RI23h#cgZi8yuBub=0Q8 zu*kN*VUoyWZlptJKcV=Mli6_w&(JXq)u)%@LX7kantd)Jt9_&l>RCTBVPs;1eDedO zX17AUg{DgZ54lW((|Vt$nqVp;k?{=@#8yy!f$nMS&%xHBc#M?t`Qm)l@GRo1I@)p( z81vGdic?Tan(-F+?UcdG7m&|!Uj)f_v|MxI+oe~*jwVeV!a=xiLZtw zRynp!TJ~-wI+SVPy)6b!YLb6Ue&nOcpn;e4X`;nLtynNO zloes&iB7|Es&eiK6C$=UpYRbfUT%LQ2TU9ncyYulNaQyJ4i)TJ|NSU&bbXd)BE$NGv7YLnHCep94S8qDKRl=rFEUsi%EJ43< zg3<_2O|-m{?uWwWZ?Kl=arq9P8XT$W@sq}mK0yl|h|d6HcHDmQW?NKC4B79;d9Rq| zPq@+i{o}&le^;t_4n)6AukM{uclWws|RDyX0jd<&6aF~j;CV=IajW0 zEw3i^5q0Mk0lS7~k{tkOsoZy)B8C!2D^gpUhX^l#(0N#zA0Hd9fv0kACGBqXJW20A z+gS&$`!MZ9)%#pIn!wT!ZSsPl!Fy^Mo_el)h#7VVJ212 zxh)=Ev-YWS$M+!}UksZ2^6PkCLQn7$qt!N{89BZUBgn~>n~#|s6f>jARtL2{1LWC> zxD?x))`#Wpn*=5x&!J}M1Uq5jFRkU0wFYg94zv25C%MpHn_6E4#LqHlW>_|>nST4p zv9rHG-&8#$>&?EEiU}IcuOUer?_kXsh=_8L` zd5J?nmy%*ewp>~SLoCO9{JZaF`e>H>Y${~@-k!q|q{kymS+^R`igWE9dAHh(R$!Z1 zRSX1F#AJSS*SHg6I%N)909qqj3qR|@`qd4e>iywO4b*yJl z?HbRrPUq`7e{0?K77huQJJ{+PkUyrH{kmV7`7~|y0>z`k&g`RDlQ^a2;<>_yM6%d| z7Wv%ERr`LU#QO#_lVM`0FqcGrhu8_fvRz+1KW3yCA(;^W;Ls&~KRNz&NSO=zmMwei02|53P;|*-fFDoUgT>-0nX=|KbzYJkAQfkz0ri9P85xEr8 z4Q{INV1E=kgA?`3?53g5%Jy$0e7jwSep>yYVNf2z)k;o&31UR+VeM(M7p6Ag{IZs9Yo=;~R;+_vuNkW%fEkk9%Eo zi3>5fUT{@ToPOv|PfMJ&yn;u~Zw;+eV%<*bX?g`hhgXUG8MU|dH-)Ay3!-6lUX0`y ztBN5OK~M)$Q(^F&+2wnct9AE~?pYw!hy}TV)G|PAt{K4QbRJF)&g-&jQSvp` z&g&&-JsWHc3x1-)%6MNsad8IIYv4K`H=f@3htr5@c42UDuS-{90sN<#L)+2jPsfVuH~9XURn|PnAWm!|K=Em6hd<>X`&|g!%Lr#H0}*@ zHKy71d*042LQ{c@qVM`~3XWiJn+yZjoQ_F9+3xYIK1tBSfooB$O-6<9)qmqa^+R;p zz`Y5xRkVfhe<$2EZ^7>EK;D)|JBI4j9c#Ewj2!#B$!+t?_pS5*U&7fQg`}k3m*29l zmNp8Bu;+tJr2_ zH@evG)C8gR2#?u%^L5jE&s%HRMbAiS?nPu%sA*KY%lvY{98Kwu`wHtc3R6NGtL1}O z9=OP|a;d^+kCvAr72k5*tglvS)g|0cDA%=J5*2?`_;OpWCMBu&v7RmMw8?1qXr=_;UL~44=CaKJ8(j;725uL zaem?L#qG|sW@oSS=IY$ZgSWUQs}v0N?bG9JyXLXZH^RowKVZXq1`;H21*5)(dnl`F ztL6~vVANFef#!2WYa!z47AwdBUl6KNn(GXqSwT`t{wAh51N*Nwo0}~L$QQygelH?C z4o;Eq-D?zg6-l2DeHGwNMfa#j-wna078RRS&wF_dy)&yDca6OcMep}glDhgniJGFq ztm}(5=KUta<&J*y{mK+v3`ITa-26>iWuBijWJn)W%V#ByaRwQKTb!Ug14=mH034K- zRsTFwFN*&2{7=)L=YN|1Z&y%F`~R=Zc$toD!)YKlzdF1(8xBPSHA8M|8EBTM+dcYU Dq_KSN literal 0 HcmV?d00001 diff --git a/doc/_templates/sideb.html b/doc/_templates/sideb.html index 7df7dffd..9e3966a5 100644 --- a/doc/_templates/sideb.html +++ b/doc/_templates/sideb.html @@ -10,5 +10,5 @@

  • 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 LBGHGvHP@Z{hochaTZkH^_*Nu!0Q((F_F=o&f1u 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

    + CEA + Ecole Polytechnique +
    + CNRS +ERC +