diff options
author | Jocelyn Turcotte <jturcotte@woboq.com> | 2017-08-14 19:49:44 +0300 |
---|---|---|
committer | Jocelyn Turcotte <jturcotte@woboq.com> | 2017-08-22 12:18:22 +0300 |
commit | 5c9827a33c92dbf14b16a22e1cac3d1b324492ed (patch) | |
tree | 5c9ef9f9a09d54cc3ef9611c49168b49dfa5419c /test | |
parent | f0362b23322ac64f52d5a6333a571deed1b8d00e (diff) |
Move csync/tests to test/csync
Diffstat (limited to 'test')
29 files changed, 4678 insertions, 0 deletions
diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 860f140e9..ebf349207 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -61,3 +61,9 @@ list(APPEND FolderMan_SRC stub.cpp ) owncloud_add_test(FolderMan "${FolderMan_SRC}") configure_file(test_journal.db "${PROJECT_BINARY_DIR}/bin/test_journal.db" COPYONLY) + +find_package(CMocka) +if (CMOCKA_FOUND) + include(AddCMockaTest) + add_subdirectory(csync) +endif (CMOCKA_FOUND) diff --git a/test/csync/AUTHORS b/test/csync/AUTHORS new file mode 100644 index 000000000..5fd81c08e --- /dev/null +++ b/test/csync/AUTHORS @@ -0,0 +1,3 @@ +Andreas Schneider <asn@cryptomilk.org> +Klaas Freitag <freitag@owncloud.com> +Olivier Goffart <olivier> diff --git a/test/csync/CMakeLists.txt b/test/csync/CMakeLists.txt new file mode 100644 index 000000000..e92c15e2d --- /dev/null +++ b/test/csync/CMakeLists.txt @@ -0,0 +1,56 @@ +project(tests C) + +set(TORTURE_LIBRARY torture) + +include_directories( + ${CMAKE_CURRENT_SOURCE_DIR} + ${CSYNC_PUBLIC_INCLUDE_DIRS} + ${CSTDLIB_PUBLIC_INCLUDE_DIRS} + ${CMAKE_BINARY_DIR} + ${CMOCKA_INCLUDE_DIR} +) + +include_directories(${CHECK_INCLUDE_DIRS}) +# create test library +add_library(${TORTURE_LIBRARY} STATIC torture.c cmdline.c) +target_link_libraries(${TORTURE_LIBRARY} ${CMOCKA_LIBRARIES} ${CSYNC_LIBRARY} ${CSTDLIB_LIBRARY}) + +set(TEST_TARGET_LIBRARIES ${TORTURE_LIBRARY}) + +# create tests + +# std +add_cmocka_test(check_std_c_alloc std_tests/check_std_c_alloc.c ${TEST_TARGET_LIBRARIES}) +add_cmocka_test(check_std_c_jhash std_tests/check_std_c_jhash.c ${TEST_TARGET_LIBRARIES}) +add_cmocka_test(check_std_c_path std_tests/check_std_c_path.c ${TEST_TARGET_LIBRARIES}) +add_cmocka_test(check_std_c_rbtree std_tests/check_std_c_rbtree.c ${TEST_TARGET_LIBRARIES}) +add_cmocka_test(check_std_c_str std_tests/check_std_c_str.c ${TEST_TARGET_LIBRARIES}) +add_cmocka_test(check_std_c_time std_tests/check_std_c_time.c ${TEST_TARGET_LIBRARIES}) + +# csync tests +# This will be rewritten soon anyway. +#add_cmocka_test(check_logger log_tests/check_log.c ${TEST_TARGET_LIBRARIES}) + +add_cmocka_test(check_csync_create csync_tests/check_csync_create.c ${TEST_TARGET_LIBRARIES}) +add_cmocka_test(check_csync_log csync_tests/check_csync_log.c ${TEST_TARGET_LIBRARIES}) +add_cmocka_test(check_csync_exclude csync_tests/check_csync_exclude.c ${TEST_TARGET_LIBRARIES}) +add_cmocka_test(check_csync_statedb_load csync_tests/check_csync_statedb_load.c ${TEST_TARGET_LIBRARIES}) +add_cmocka_test(check_csync_util csync_tests/check_csync_util.c ${TEST_TARGET_LIBRARIES}) +add_cmocka_test(check_csync_misc csync_tests/check_csync_misc.c ${TEST_TARGET_LIBRARIES}) + +# csync tests which require init +add_cmocka_test(check_csync_init csync_tests/check_csync_init.c ${TEST_TARGET_LIBRARIES}) +add_cmocka_test(check_csync_statedb_query csync_tests/check_csync_statedb_query.c ${TEST_TARGET_LIBRARIES}) +add_cmocka_test(check_csync_commit csync_tests/check_csync_commit.c ${TEST_TARGET_LIBRARIES}) + +# vio +add_cmocka_test(check_vio_file_stat vio_tests/check_vio_file_stat.c ${TEST_TARGET_LIBRARIES}) +add_cmocka_test(check_vio vio_tests/check_vio.c ${TEST_TARGET_LIBRARIES}) +add_cmocka_test(check_vio_ext vio_tests/check_vio_ext.c ${TEST_TARGET_LIBRARIES}) + +# sync +add_cmocka_test(check_csync_update csync_tests/check_csync_update.c ${TEST_TARGET_LIBRARIES}) + +# encoding +add_cmocka_test(check_encoding_functions encoding_tests/check_encoding.c ${TEST_TARGET_LIBRARIES}) + diff --git a/test/csync/COPYING b/test/csync/COPYING new file mode 100644 index 000000000..4362b4915 --- /dev/null +++ b/test/csync/COPYING @@ -0,0 +1,502 @@ + GNU LESSER GENERAL PUBLIC LICENSE + Version 2.1, February 1999 + + Copyright (C) 1991, 1999 Free Software Foundation, Inc. + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + +[This is the first released version of the Lesser GPL. It also counts + as the successor of the GNU Library Public License, version 2, hence + the version number 2.1.] + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +Licenses are intended to guarantee your freedom to share and change +free software--to make sure the software is free for all its users. + + This license, the Lesser General Public License, applies to some +specially designated software packages--typically libraries--of the +Free Software Foundation and other authors who decide to use it. You +can use it too, but we suggest you first think carefully about whether +this license or the ordinary General Public License is the better +strategy to use in any particular case, based on the explanations below. + + When we speak of free software, we are referring to freedom of use, +not price. Our General Public Licenses are designed to make sure that +you have the freedom to distribute copies of free software (and charge +for this service if you wish); that you receive source code or can get +it if you want it; that you can change the software and use pieces of +it in new free programs; and that you are informed that you can do +these things. + + To protect your rights, we need to make restrictions that forbid +distributors to deny you these rights or to ask you to surrender these +rights. These restrictions translate to certain responsibilities for +you if you distribute copies of the library or if you modify it. + + For example, if you distribute copies of the library, whether gratis +or for a fee, you must give the recipients all the rights that we gave +you. You must make sure that they, too, receive or can get the source +code. If you link other code with the library, you must provide +complete object files to the recipients, so that they can relink them +with the library after making changes to the library and recompiling +it. And you must show them these terms so they know their rights. + + We protect your rights with a two-step method: (1) we copyright the +library, and (2) we offer you this license, which gives you legal +permission to copy, distribute and/or modify the library. + + To protect each distributor, we want to make it very clear that +there is no warranty for the free library. Also, if the library is +modified by someone else and passed on, the recipients should know +that what they have is not the original version, so that the original +author's reputation will not be affected by problems that might be +introduced by others. + + Finally, software patents pose a constant threat to the existence of +any free program. We wish to make sure that a company cannot +effectively restrict the users of a free program by obtaining a +restrictive license from a patent holder. Therefore, we insist that +any patent license obtained for a version of the library must be +consistent with the full freedom of use specified in this license. + + Most GNU software, including some libraries, is covered by the +ordinary GNU General Public License. This license, the GNU Lesser +General Public License, applies to certain designated libraries, and +is quite different from the ordinary General Public License. We use +this license for certain libraries in order to permit linking those +libraries into non-free programs. + + When a program is linked with a library, whether statically or using +a shared library, the combination of the two is legally speaking a +combined work, a derivative of the original library. The ordinary +General Public License therefore permits such linking only if the +entire combination fits its criteria of freedom. The Lesser General +Public License permits more lax criteria for linking other code with +the library. + + We call this license the "Lesser" General Public License because it +does Less to protect the user's freedom than the ordinary General +Public License. It also provides other free software developers Less +of an advantage over competing non-free programs. These disadvantages +are the reason we use the ordinary General Public License for many +libraries. However, the Lesser license provides advantages in certain +special circumstances. + + For example, on rare occasions, there may be a special need to +encourage the widest possible use of a certain library, so that it becomes +a de-facto standard. To achieve this, non-free programs must be +allowed to use the library. A more frequent case is that a free +library does the same job as widely used non-free libraries. In this +case, there is little to gain by limiting the free library to free +software only, so we use the Lesser General Public License. + + In other cases, permission to use a particular library in non-free +programs enables a greater number of people to use a large body of +free software. For example, permission to use the GNU C Library in +non-free programs enables many more people to use the whole GNU +operating system, as well as its variant, the GNU/Linux operating +system. + + Although the Lesser General Public License is Less protective of the +users' freedom, it does ensure that the user of a program that is +linked with the Library has the freedom and the wherewithal to run +that program using a modified version of the Library. + + The precise terms and conditions for copying, distribution and +modification follow. Pay close attention to the difference between a +"work based on the library" and a "work that uses the library". The +former contains code derived from the library, whereas the latter must +be combined with the library in order to run. + + GNU LESSER GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License Agreement applies to any software library or other +program which contains a notice placed by the copyright holder or +other authorized party saying it may be distributed under the terms of +this Lesser General Public License (also called "this License"). +Each licensee is addressed as "you". + + A "library" means a collection of software functions and/or data +prepared so as to be conveniently linked with application programs +(which use some of those functions and data) to form executables. + + The "Library", below, refers to any such software library or work +which has been distributed under these terms. A "work based on the +Library" means either the Library or any derivative work under +copyright law: that is to say, a work containing the Library or a +portion of it, either verbatim or with modifications and/or translated +straightforwardly into another language. (Hereinafter, translation is +included without limitation in the term "modification".) + + "Source code" for a work means the preferred form of the work for +making modifications to it. For a library, complete source code means +all the source code for all modules it contains, plus any associated +interface definition files, plus the scripts used to control compilation +and installation of the library. + + Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running a program using the Library is not restricted, and output from +such a program is covered only if its contents constitute a work based +on the Library (independent of the use of the Library in a tool for +writing it). Whether that is true depends on what the Library does +and what the program that uses the Library does. + + 1. You may copy and distribute verbatim copies of the Library's +complete source code as you receive it, in any medium, provided that +you conspicuously and appropriately publish on each copy an +appropriate copyright notice and disclaimer of warranty; keep intact +all the notices that refer to this License and to the absence of any +warranty; and distribute a copy of this License along with the +Library. + + You may charge a fee for the physical act of transferring a copy, +and you may at your option offer warranty protection in exchange for a +fee. + + 2. You may modify your copy or copies of the Library or any portion +of it, thus forming a work based on the Library, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) The modified work must itself be a software library. + + b) You must cause the files modified to carry prominent notices + stating that you changed the files and the date of any change. + + c) You must cause the whole of the work to be licensed at no + charge to all third parties under the terms of this License. + + d) If a facility in the modified Library refers to a function or a + table of data to be supplied by an application program that uses + the facility, other than as an argument passed when the facility + is invoked, then you must make a good faith effort to ensure that, + in the event an application does not supply such function or + table, the facility still operates, and performs whatever part of + its purpose remains meaningful. + + (For example, a function in a library to compute square roots has + a purpose that is entirely well-defined independent of the + application. Therefore, Subsection 2d requires that any + application-supplied function or table used by this function must + be optional: if the application does not supply it, the square + root function must still compute square roots.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Library, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Library, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote +it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Library. + +In addition, mere aggregation of another work not based on the Library +with the Library (or with a work based on the Library) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may opt to apply the terms of the ordinary GNU General Public +License instead of this License to a given copy of the Library. To do +this, you must alter all the notices that refer to this License, so +that they refer to the ordinary GNU General Public License, version 2, +instead of to this License. (If a newer version than version 2 of the +ordinary GNU General Public License has appeared, then you can specify +that version instead if you wish.) Do not make any other change in +these notices. + + Once this change is made in a given copy, it is irreversible for +that copy, so the ordinary GNU General Public License applies to all +subsequent copies and derivative works made from that copy. + + This option is useful when you wish to copy part of the code of +the Library into a program that is not a library. + + 4. You may copy and distribute the Library (or a portion or +derivative of it, under Section 2) in object code or executable form +under the terms of Sections 1 and 2 above provided that you accompany +it with the complete corresponding machine-readable source code, which +must be distributed under the terms of Sections 1 and 2 above on a +medium customarily used for software interchange. + + If distribution of object code is made by offering access to copy +from a designated place, then offering equivalent access to copy the +source code from the same place satisfies the requirement to +distribute the source code, even though third parties are not +compelled to copy the source along with the object code. + + 5. A program that contains no derivative of any portion of the +Library, but is designed to work with the Library by being compiled or +linked with it, is called a "work that uses the Library". Such a +work, in isolation, is not a derivative work of the Library, and +therefore falls outside the scope of this License. + + However, linking a "work that uses the Library" with the Library +creates an executable that is a derivative of the Library (because it +contains portions of the Library), rather than a "work that uses the +library". The executable is therefore covered by this License. +Section 6 states terms for distribution of such executables. + + When a "work that uses the Library" uses material from a header file +that is part of the Library, the object code for the work may be a +derivative work of the Library even though the source code is not. +Whether this is true is especially significant if the work can be +linked without the Library, or if the work is itself a library. The +threshold for this to be true is not precisely defined by law. + + If such an object file uses only numerical parameters, data +structure layouts and accessors, and small macros and small inline +functions (ten lines or less in length), then the use of the object +file is unrestricted, regardless of whether it is legally a derivative +work. (Executables containing this object code plus portions of the +Library will still fall under Section 6.) + + Otherwise, if the work is a derivative of the Library, you may +distribute the object code for the work under the terms of Section 6. +Any executables containing that work also fall under Section 6, +whether or not they are linked directly with the Library itself. + + 6. As an exception to the Sections above, you may also combine or +link a "work that uses the Library" with the Library to produce a +work containing portions of the Library, and distribute that work +under terms of your choice, provided that the terms permit +modification of the work for the customer's own use and reverse +engineering for debugging such modifications. + + You must give prominent notice with each copy of the work that the +Library is used in it and that the Library and its use are covered by +this License. You must supply a copy of this License. If the work +during execution displays copyright notices, you must include the +copyright notice for the Library among them, as well as a reference +directing the user to the copy of this License. Also, you must do one +of these things: + + a) Accompany the work with the complete corresponding + machine-readable source code for the Library including whatever + changes were used in the work (which must be distributed under + Sections 1 and 2 above); and, if the work is an executable linked + with the Library, with the complete machine-readable "work that + uses the Library", as object code and/or source code, so that the + user can modify the Library and then relink to produce a modified + executable containing the modified Library. (It is understood + that the user who changes the contents of definitions files in the + Library will not necessarily be able to recompile the application + to use the modified definitions.) + + b) Use a suitable shared library mechanism for linking with the + Library. A suitable mechanism is one that (1) uses at run time a + copy of the library already present on the user's computer system, + rather than copying library functions into the executable, and (2) + will operate properly with a modified version of the library, if + the user installs one, as long as the modified version is + interface-compatible with the version that the work was made with. + + c) Accompany the work with a written offer, valid for at + least three years, to give the same user the materials + specified in Subsection 6a, above, for a charge no more + than the cost of performing this distribution. + + d) If distribution of the work is made by offering access to copy + from a designated place, offer equivalent access to copy the above + specified materials from the same place. + + e) Verify that the user has already received a copy of these + materials or that you have already sent this user a copy. + + For an executable, the required form of the "work that uses the +Library" must include any data and utility programs needed for +reproducing the executable from it. However, as a special exception, +the materials to be distributed need not include anything that is +normally distributed (in either source or binary form) with the major +components (compiler, kernel, and so on) of the operating system on +which the executable runs, unless that component itself accompanies +the executable. + + It may happen that this requirement contradicts the license +restrictions of other proprietary libraries that do not normally +accompany the operating system. Such a contradiction means you cannot +use both them and the Library together in an executable that you +distribute. + + 7. You may place library facilities that are a work based on the +Library side-by-side in a single library together with other library +facilities not covered by this License, and distribute such a combined +library, provided that the separate distribution of the work based on +the Library and of the other library facilities is otherwise +permitted, and provided that you do these two things: + + a) Accompany the combined library with a copy of the same work + based on the Library, uncombined with any other library + facilities. This must be distributed under the terms of the + Sections above. + + b) Give prominent notice with the combined library of the fact + that part of it is a work based on the Library, and explaining + where to find the accompanying uncombined form of the same work. + + 8. You may not copy, modify, sublicense, link with, or distribute +the Library except as expressly provided under this License. Any +attempt otherwise to copy, modify, sublicense, link with, or +distribute the Library is void, and will automatically terminate your +rights under this License. However, parties who have received copies, +or rights, from you under this License will not have their licenses +terminated so long as such parties remain in full compliance. + + 9. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Library or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Library (or any work based on the +Library), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Library or works based on it. + + 10. Each time you redistribute the Library (or any work based on the +Library), the recipient automatically receives a license from the +original licensor to copy, distribute, link with or modify the Library +subject to these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties with +this License. + + 11. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Library at all. For example, if a patent +license would not permit royalty-free redistribution of the Library by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Library. + +If any portion of this section is held invalid or unenforceable under any +particular circumstance, the balance of the section is intended to apply, +and the section as a whole is intended to apply in other circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 12. If the distribution and/or use of the Library is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Library under this License may add +an explicit geographical distribution limitation excluding those countries, +so that distribution is permitted only in or among countries not thus +excluded. In such case, this License incorporates the limitation as if +written in the body of this License. + + 13. The Free Software Foundation may publish revised and/or new +versions of the Lesser 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 Library +specifies a version number of this License which applies to it and +"any later version", you have the option of following the terms and +conditions either of that version or of any later version published by +the Free Software Foundation. If the Library does not specify a +license version number, you may choose any version ever published by +the Free Software Foundation. + + 14. If you wish to incorporate parts of the Library into other free +programs whose distribution conditions are incompatible with these, +write to the author to ask for permission. For software which is +copyrighted by the Free Software Foundation, write to the Free +Software Foundation; we sometimes make exceptions for this. Our +decision will be guided by the two goals of preserving the free status +of all derivatives of our free software and of promoting the sharing +and reuse of software generally. + + NO WARRANTY + + 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO +WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. +EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR +OTHER PARTIES PROVIDE THE LIBRARY "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 +LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME +THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN +WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY +AND/OR REDISTRIBUTE THE LIBRARY 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 +LIBRARY (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 LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF +SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH +DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Libraries + + If you develop a new library, and you want it to be of the greatest +possible use to the public, we recommend making it free software that +everyone can redistribute and change. You can do so by permitting +redistribution under these terms (or, alternatively, under the terms of the +ordinary General Public License). + + To apply these terms, attach the following notices to the library. It is +safest to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least the +"copyright" line and a pointer to where the full notice is found. + + <one line to give the library's name and a brief idea of what it does.> + Copyright (C) <year> <name of author> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +Also add information on how to contact you by electronic and paper mail. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the library, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the + library `Frob' (a library for tweaking knobs) written by James Random Hacker. + + <signature of Ty Coon>, 1 April 1990 + Ty Coon, President of Vice + +That's all there is to it! diff --git a/test/csync/cmdline.c b/test/csync/cmdline.c new file mode 100644 index 000000000..459c77f46 --- /dev/null +++ b/test/csync/cmdline.c @@ -0,0 +1,90 @@ +/* + * libcsync -- a library to sync a directory with another + * + * Copyright (c) 2008-2013 by Andreas Schneider <asn@cryptomilk.org> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ +#include "config_csync.h" +#include "torture.h" + +#ifdef HAVE_ARGP_H +#include <argp.h> + +const char *argp_program_version = "csync test 0.2"; +const char *argp_program_bug_address = "<csync-devel@csync.org>"; + +static char **cmdline; + +/* Program documentation. */ +static char doc[] = "csync test"; + +/* The options we understand. */ +static struct argp_option options[] = { + { + .name = "verbose", + .key = 'v', + .arg = NULL, + .flags = 0, + .doc = "Make csync test more verbose", + .group = 0 + }, + {NULL, 0, NULL, 0, NULL, 0} +}; + +/* Parse a single option. */ +static error_t parse_opt (int key, char *arg, struct argp_state *state) { + /* Get the input argument from argp_parse, which we + * know is a pointer to our arguments structure. + */ + struct argument_s *arguments = state->input; + + /* arg is currently not used */ + (void) arg; + + switch (key) { + case 'v': + arguments->verbose++; + break; + case ARGP_KEY_ARG: + /* End processing here. */ + cmdline = &state->argv [state->next - 1]; + state->next = state->argc; + break; + default: + return ARGP_ERR_UNKNOWN; + } + + return 0; +} + +/* Our argp parser. */ +/* static struct argp argp = {options, parse_opt, args_doc, doc, NULL, NULL, NULL}; */ +static struct argp argp = {options, parse_opt, NULL, doc, NULL, NULL, NULL}; +#endif /* HAVE_ARGP_H */ + +void torture_cmdline_parse(int argc, char **argv, struct argument_s *arguments) { + /* + * Parse our arguments; every option seen by parse_opt will + * be reflected in arguments. + */ +#ifdef HAVE_ARGP_H + argp_parse(&argp, argc, argv, 0, 0, arguments); +#else + (void) argc; + (void) argv; + (void) arguments; +#endif /* HAVE_ARGP_H */ +} diff --git a/test/csync/csync_tests/check_csync_commit.c b/test/csync/csync_tests/check_csync_commit.c new file mode 100644 index 000000000..16c89bf9e --- /dev/null +++ b/test/csync/csync_tests/check_csync_commit.c @@ -0,0 +1,103 @@ +/* + * libcsync -- a library to sync a directory with another + * + * Copyright (c) 2008-2013 by Andreas Schneider <asn@cryptomilk.org> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ +#include <string.h> + +#include "torture.h" + +#include "csync_private.h" + +static int setup(void **state) { + CSYNC *csync; + int rc; + + rc = system("mkdir -p /tmp/check_csync1"); + assert_int_equal(rc, 0); + + csync_create(&csync, "/tmp/check_csync1"); + + *state = csync; + + return 0; +} + +static int setup_module(void **state) { + CSYNC *csync; + int rc; + + rc = system("mkdir -p /tmp/check_csync1"); + assert_int_equal(rc, 0); + + csync_create(&csync, "/tmp/check_csync1"); + + csync_init(csync, "foo"); + *state = csync; + + return 0; +} + +static int teardown(void **state) { + CSYNC *csync = *state; + int rc; + + rc = csync_destroy(csync); + + rc = system("rm -rf /tmp/check_csync"); + assert_int_equal(rc, 0); + + rc = system("rm -rf /tmp/check_csync1"); + assert_int_equal(rc, 0); + + *state = NULL; + + return 0; +} + +static void check_csync_commit(void **state) +{ + CSYNC *csync = *state; + int rc; + + rc = csync_commit(csync); + assert_int_equal(rc, 0); + + assert_int_equal(csync->status & CSYNC_STATUS_INIT, 1); +} + +static void check_csync_commit_dummy(void **state) +{ + CSYNC *csync = *state; + int rc; + + rc = csync_commit(csync); + assert_int_equal(rc, 0); + + assert_int_equal(csync->status & CSYNC_STATUS_INIT, 1); + +} + +int torture_run_tests(void) +{ + const struct CMUnitTest tests[] = { + cmocka_unit_test_setup_teardown(check_csync_commit, setup, teardown), + cmocka_unit_test_setup_teardown(check_csync_commit_dummy, setup_module, teardown), + }; + + return cmocka_run_group_tests(tests, NULL, NULL); +} diff --git a/test/csync/csync_tests/check_csync_create.c b/test/csync/csync_tests/check_csync_create.c new file mode 100644 index 000000000..082ef26b8 --- /dev/null +++ b/test/csync/csync_tests/check_csync_create.c @@ -0,0 +1,60 @@ +/* + * libcsync -- a library to sync a directory with another + * + * Copyright (c) 2008-2013 by Andreas Schneider <asn@cryptomilk.org> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ +#include <stdlib.h> +#include <stdio.h> + +#include "torture.h" + +#include "csync_private.h" + + +static void check_csync_destroy_null(void **state) +{ + int rc; + + (void) state; /* unused */ + + rc = csync_destroy(NULL); + assert_int_equal(rc, -1); +} + +static void check_csync_create(void **state) +{ + CSYNC *csync; + int rc; + + (void) state; /* unused */ + + csync_create(&csync, "/tmp/csync1"); + + rc = csync_destroy(csync); + assert_int_equal(rc, 0); +} + +int torture_run_tests(void) +{ + const struct CMUnitTest tests[] = { + cmocka_unit_test(check_csync_destroy_null), + cmocka_unit_test(check_csync_create), + }; + + return cmocka_run_group_tests(tests, NULL, NULL); +} + diff --git a/test/csync/csync_tests/check_csync_exclude.c b/test/csync/csync_tests/check_csync_exclude.c new file mode 100644 index 000000000..ea9ca0e2f --- /dev/null +++ b/test/csync/csync_tests/check_csync_exclude.c @@ -0,0 +1,419 @@ +/* + * libcsync -- a library to sync a directory with another + * + * Copyright (c) 2008-2013 by Andreas Schneider <asn@cryptomilk.org> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ +#include "config_csync.h" +#include <string.h> +#include <time.h> +#include <sys/time.h> + +#include "torture.h" + +#define CSYNC_TEST 1 +#include "csync_exclude.c" + +#define EXCLUDE_LIST_FILE SOURCEDIR"/../sync-exclude.lst" + +static int setup(void **state) { + CSYNC *csync; + + csync_create(&csync, "/tmp/check_csync1"); + + *state = csync; + return 0; +} + +static int setup_init(void **state) { + CSYNC *csync; + int rc; + + csync_create(&csync, "/tmp/check_csync1"); + + rc = csync_exclude_load(EXCLUDE_LIST_FILE, &(csync->excludes)); + assert_int_equal(rc, 0); + + /* and add some unicode stuff */ + rc = _csync_exclude_add(&(csync->excludes), "*.💩"); + assert_int_equal(rc, 0); + rc = _csync_exclude_add(&(csync->excludes), "пятницы.*"); + assert_int_equal(rc, 0); + rc = _csync_exclude_add(&(csync->excludes), "*/*.out"); + assert_int_equal(rc, 0); + rc = _csync_exclude_add(&(csync->excludes), "latex*/*.run.xml"); + assert_int_equal(rc, 0); + rc = _csync_exclude_add(&(csync->excludes), "latex/*/*.tex.tmp"); + assert_int_equal(rc, 0); + + *state = csync; + return 0; +} + +static int teardown(void **state) { + CSYNC *csync = *state; + int rc; + + rc = csync_destroy(csync); + assert_int_equal(rc, 0); + + rc = system("rm -rf /tmp/check_csync1"); + assert_int_equal(rc, 0); + rc = system("rm -rf /tmp/check_csync2"); + assert_int_equal(rc, 0); + + *state = NULL; + + return 0; +} + +static void check_csync_exclude_add(void **state) +{ + CSYNC *csync = *state; + _csync_exclude_add(&(csync->excludes), "/tmp/check_csync1/*"); + assert_string_equal(csync->excludes->vector[0], "/tmp/check_csync1/*"); +} + +static void check_csync_exclude_load(void **state) +{ + CSYNC *csync = *state; + int rc; + + rc = csync_exclude_load(EXCLUDE_LIST_FILE, &(csync->excludes) ); + assert_int_equal(rc, 0); + + assert_string_equal(csync->excludes->vector[0], "*~"); + assert_int_not_equal(csync->excludes->count, 0); +} + +static void check_csync_excluded(void **state) +{ + CSYNC *csync = *state; + int rc; + + rc = csync_excluded_no_ctx(csync->excludes, "", CSYNC_FTW_TYPE_FILE); + assert_int_equal(rc, CSYNC_NOT_EXCLUDED); + rc = csync_excluded_no_ctx(csync->excludes, "/", CSYNC_FTW_TYPE_FILE); + assert_int_equal(rc, CSYNC_NOT_EXCLUDED); + + rc = csync_excluded_no_ctx(csync->excludes, "krawel_krawel", CSYNC_FTW_TYPE_FILE); + assert_int_equal(rc, CSYNC_NOT_EXCLUDED); + rc = csync_excluded_no_ctx(csync->excludes, ".kde/share/config/kwin.eventsrc", CSYNC_FTW_TYPE_FILE); + assert_int_equal(rc, CSYNC_NOT_EXCLUDED); + rc = csync_excluded_no_ctx(csync->excludes, ".directory/cache-maximegalon/cache1.txt", CSYNC_FTW_TYPE_FILE); + assert_int_equal(rc, CSYNC_FILE_EXCLUDE_LIST); + rc = csync_excluded_no_ctx(csync->excludes, "mozilla/.directory", CSYNC_FTW_TYPE_DIR); + assert_int_equal(rc, CSYNC_FILE_EXCLUDE_LIST); + + /* + * Test for patterns in subdirs. '.beagle' is defined as a pattern and has + * to be found in top dir as well as in directories underneath. + */ + rc = csync_excluded_no_ctx(csync->excludes, ".apdisk", CSYNC_FTW_TYPE_DIR); + assert_int_equal(rc, CSYNC_FILE_EXCLUDE_LIST); + rc = csync_excluded_no_ctx(csync->excludes, "foo/.apdisk", CSYNC_FTW_TYPE_DIR); + assert_int_equal(rc, CSYNC_FILE_EXCLUDE_LIST); + rc = csync_excluded_no_ctx(csync->excludes, "foo/bar/.apdisk", CSYNC_FTW_TYPE_DIR); + assert_int_equal(rc, CSYNC_FILE_EXCLUDE_LIST); + + rc = csync_excluded_no_ctx(csync->excludes, ".java", CSYNC_FTW_TYPE_FILE); + assert_int_equal(rc, CSYNC_NOT_EXCLUDED); + + /* Files in the ignored dir .java will also be ignored. */ + rc = csync_excluded_no_ctx(csync->excludes, ".apdisk/totally_amazing.jar", CSYNC_FTW_TYPE_FILE); + assert_int_equal(rc, CSYNC_FILE_EXCLUDE_LIST); + + /* and also in subdirs */ + rc = csync_excluded_no_ctx(csync->excludes, "projects/.apdisk/totally_amazing.jar", CSYNC_FTW_TYPE_FILE); + assert_int_equal(rc, CSYNC_FILE_EXCLUDE_LIST); + + /* csync-journal is ignored in general silently. */ + rc = csync_excluded_no_ctx(csync->excludes, ".csync_journal.db", CSYNC_FTW_TYPE_FILE); + assert_int_equal(rc, CSYNC_FILE_SILENTLY_EXCLUDED); + rc = csync_excluded_no_ctx(csync->excludes, ".csync_journal.db.ctmp", CSYNC_FTW_TYPE_FILE); + assert_int_equal(rc, CSYNC_FILE_SILENTLY_EXCLUDED); + rc = csync_excluded_no_ctx(csync->excludes, "subdir/.csync_journal.db", CSYNC_FTW_TYPE_FILE); + assert_int_equal(rc, CSYNC_FILE_SILENTLY_EXCLUDED); + + /* also the new form of the database name */ + rc = csync_excluded_no_ctx(csync->excludes, "._sync_5bdd60bdfcfa.db", CSYNC_FTW_TYPE_FILE); + assert_int_equal(rc, CSYNC_FILE_SILENTLY_EXCLUDED); + rc = csync_excluded_no_ctx(csync->excludes, "._sync_5bdd60bdfcfa.db.ctmp", CSYNC_FTW_TYPE_FILE); + assert_int_equal(rc, CSYNC_FILE_SILENTLY_EXCLUDED); + rc = csync_excluded_no_ctx(csync->excludes, "._sync_5bdd60bdfcfa.db-shm", CSYNC_FTW_TYPE_FILE); + assert_int_equal(rc, CSYNC_FILE_SILENTLY_EXCLUDED); + rc = csync_excluded_no_ctx(csync->excludes, "subdir/._sync_5bdd60bdfcfa.db", CSYNC_FTW_TYPE_FILE); + assert_int_equal(rc, CSYNC_FILE_SILENTLY_EXCLUDED); + + rc = csync_excluded_no_ctx(csync->excludes, ".sync_5bdd60bdfcfa.db", CSYNC_FTW_TYPE_FILE); + assert_int_equal(rc, CSYNC_FILE_SILENTLY_EXCLUDED); + rc = csync_excluded_no_ctx(csync->excludes, ".sync_5bdd60bdfcfa.db.ctmp", CSYNC_FTW_TYPE_FILE); + assert_int_equal(rc, CSYNC_FILE_SILENTLY_EXCLUDED); + rc = csync_excluded_no_ctx(csync->excludes, ".sync_5bdd60bdfcfa.db-shm", CSYNC_FTW_TYPE_FILE); + assert_int_equal(rc, CSYNC_FILE_SILENTLY_EXCLUDED); + rc = csync_excluded_no_ctx(csync->excludes, "subdir/.sync_5bdd60bdfcfa.db", CSYNC_FTW_TYPE_FILE); + assert_int_equal(rc, CSYNC_FILE_SILENTLY_EXCLUDED); + + + /* pattern ]*.directory - ignore and remove */ + rc = csync_excluded_no_ctx(csync->excludes, "my.~directory", CSYNC_FTW_TYPE_FILE); + assert_int_equal(rc, CSYNC_FILE_EXCLUDE_AND_REMOVE); + + rc = csync_excluded_no_ctx(csync->excludes, "/a_folder/my.~directory", CSYNC_FTW_TYPE_FILE); + assert_int_equal(rc, CSYNC_FILE_EXCLUDE_AND_REMOVE); + + /* Not excluded because the pattern .netscape/cache requires directory. */ + rc = csync_excluded_no_ctx(csync->excludes, ".netscape/cache", CSYNC_FTW_TYPE_FILE); + assert_int_equal(rc, CSYNC_NOT_EXCLUDED); + + /* Not excluded */ + rc = csync_excluded_no_ctx(csync->excludes, "unicode/中文.hé", CSYNC_FTW_TYPE_FILE); + assert_int_equal(rc, CSYNC_NOT_EXCLUDED); + /* excluded */ + rc = csync_excluded_no_ctx(csync->excludes, "unicode/пятницы.txt", CSYNC_FTW_TYPE_FILE); + assert_int_equal(rc, CSYNC_FILE_EXCLUDE_LIST); + rc = csync_excluded_no_ctx(csync->excludes, "unicode/中文.💩", CSYNC_FTW_TYPE_FILE); + assert_int_equal(rc, CSYNC_FILE_EXCLUDE_LIST); + + /* path wildcards */ + rc = csync_excluded_no_ctx(csync->excludes, "foobar/my_manuscript.out", CSYNC_FTW_TYPE_FILE); + assert_int_equal(rc, CSYNC_FILE_EXCLUDE_LIST); + + rc = csync_excluded_no_ctx(csync->excludes, "latex_tmp/my_manuscript.run.xml", CSYNC_FTW_TYPE_FILE); + assert_int_equal(rc, CSYNC_FILE_EXCLUDE_LIST); + + rc = csync_excluded_no_ctx(csync->excludes, "word_tmp/my_manuscript.run.xml", CSYNC_FTW_TYPE_FILE); + assert_int_equal(rc, CSYNC_NOT_EXCLUDED); + + rc = csync_excluded_no_ctx(csync->excludes, "latex/my_manuscript.tex.tmp", CSYNC_FTW_TYPE_FILE); + assert_int_equal(rc, CSYNC_NOT_EXCLUDED); + + rc = csync_excluded_no_ctx(csync->excludes, "latex/songbook/my_manuscript.tex.tmp", CSYNC_FTW_TYPE_FILE); + assert_int_equal(rc, CSYNC_FILE_EXCLUDE_LIST); + +#ifdef _WIN32 + rc = csync_excluded_no_ctx(csync->excludes, "file_trailing_space ", CSYNC_FTW_TYPE_FILE); + assert_int_equal(rc, CSYNC_FILE_EXCLUDE_TRAILING_SPACE); + + rc = csync_excluded_no_ctx(csync->excludes, "file_trailing_dot.", CSYNC_FTW_TYPE_FILE); + assert_int_equal(rc, CSYNC_FILE_EXCLUDE_INVALID_CHAR); + + rc = csync_excluded_no_ctx(csync->excludes, "AUX", CSYNC_FTW_TYPE_FILE); + assert_int_equal(rc, CSYNC_FILE_EXCLUDE_INVALID_CHAR); + + rc = csync_excluded_no_ctx(csync->excludes, "file_invalid_char<", CSYNC_FTW_TYPE_FILE); + assert_int_equal(rc, CSYNC_FILE_EXCLUDE_INVALID_CHAR); +#endif +} + +static void check_csync_excluded_traversal(void **state) +{ + CSYNC *csync = *state; + int rc; + + _csync_exclude_add( &(csync->excludes), "/exclude" ); + + /* Check toplevel dir, the pattern only works for toplevel dir. */ + rc = csync_excluded_traversal(csync->excludes, "/exclude", CSYNC_FTW_TYPE_DIR); + assert_int_equal(rc, CSYNC_FILE_EXCLUDE_LIST); + + rc = csync_excluded_traversal(csync->excludes, "/foo/exclude", CSYNC_FTW_TYPE_DIR); + assert_int_equal(rc, CSYNC_NOT_EXCLUDED); + + /* check for a file called exclude. Must still work */ + rc = csync_excluded_traversal(csync->excludes, "/exclude", CSYNC_FTW_TYPE_FILE); + assert_int_equal(rc, CSYNC_FILE_EXCLUDE_LIST); + + rc = csync_excluded_traversal(csync->excludes, "/foo/exclude", CSYNC_FTW_TYPE_FILE); + assert_int_equal(rc, CSYNC_NOT_EXCLUDED); + + /* Add an exclude for directories only: excl/ */ + _csync_exclude_add( &(csync->excludes), "excl/" ); + rc = csync_excluded_traversal(csync->excludes, "/excl", CSYNC_FTW_TYPE_DIR); + assert_int_equal(rc, CSYNC_FILE_EXCLUDE_LIST); + + rc = csync_excluded_traversal(csync->excludes, "meep/excl", CSYNC_FTW_TYPE_DIR); + assert_int_equal(rc, CSYNC_FILE_EXCLUDE_LIST); + + rc = csync_excluded_traversal(csync->excludes, "meep/excl/file", CSYNC_FTW_TYPE_FILE); + assert_int_equal(rc, CSYNC_NOT_EXCLUDED); // because leading dirs aren't checked! + + rc = csync_excluded_traversal(csync->excludes, "/excl", CSYNC_FTW_TYPE_FILE); + assert_int_equal(rc, CSYNC_NOT_EXCLUDED); + + _csync_exclude_add(&csync->excludes, "/excludepath/withsubdir"); + + rc = csync_excluded_traversal(csync->excludes, "/excludepath/withsubdir", CSYNC_FTW_TYPE_DIR); + assert_int_equal(rc, CSYNC_FILE_EXCLUDE_LIST); + + rc = csync_excluded_traversal(csync->excludes, "/excludepath/withsubdir", CSYNC_FTW_TYPE_FILE); + assert_int_equal(rc, CSYNC_FILE_EXCLUDE_LIST); + + rc = csync_excluded_traversal(csync->excludes, "/excludepath/withsubdir2", CSYNC_FTW_TYPE_DIR); + assert_int_equal(rc, CSYNC_NOT_EXCLUDED); + + rc = csync_excluded_traversal(csync->excludes, "/excludepath/withsubdir/foo", CSYNC_FTW_TYPE_DIR); + assert_int_equal(rc, CSYNC_NOT_EXCLUDED); // because leading dirs aren't checked! +} + +static void check_csync_pathes(void **state) +{ + CSYNC *csync = *state; + int rc; + + _csync_exclude_add( &(csync->excludes), "/exclude" ); + + /* Check toplevel dir, the pattern only works for toplevel dir. */ + rc = csync_excluded_no_ctx(csync->excludes, "/exclude", CSYNC_FTW_TYPE_DIR); + assert_int_equal(rc, CSYNC_FILE_EXCLUDE_LIST); + + rc = csync_excluded_no_ctx(csync->excludes, "/foo/exclude", CSYNC_FTW_TYPE_DIR); + assert_int_equal(rc, CSYNC_NOT_EXCLUDED); + + /* check for a file called exclude. Must still work */ + rc = csync_excluded_no_ctx(csync->excludes, "/exclude", CSYNC_FTW_TYPE_FILE); + assert_int_equal(rc, CSYNC_FILE_EXCLUDE_LIST); + + rc = csync_excluded_no_ctx(csync->excludes, "/foo/exclude", CSYNC_FTW_TYPE_FILE); + assert_int_equal(rc, CSYNC_NOT_EXCLUDED); + + /* Add an exclude for directories only: excl/ */ + _csync_exclude_add( &(csync->excludes), "excl/" ); + rc = csync_excluded_no_ctx(csync->excludes, "/excl", CSYNC_FTW_TYPE_DIR); + assert_int_equal(rc, CSYNC_FILE_EXCLUDE_LIST); + + rc = csync_excluded_no_ctx(csync->excludes, "meep/excl", CSYNC_FTW_TYPE_DIR); + assert_int_equal(rc, CSYNC_FILE_EXCLUDE_LIST); + + rc = csync_excluded_no_ctx(csync->excludes, "meep/excl/file", CSYNC_FTW_TYPE_FILE); + assert_int_equal(rc, CSYNC_FILE_EXCLUDE_LIST); + + rc = csync_excluded_no_ctx(csync->excludes, "/excl", CSYNC_FTW_TYPE_FILE); + assert_int_equal(rc, CSYNC_NOT_EXCLUDED); + + _csync_exclude_add(&csync->excludes, "/excludepath/withsubdir"); + + rc = csync_excluded_no_ctx(csync->excludes, "/excludepath/withsubdir", CSYNC_FTW_TYPE_DIR); + assert_int_equal(rc, CSYNC_FILE_EXCLUDE_LIST); + + rc = csync_excluded_no_ctx(csync->excludes, "/excludepath/withsubdir", CSYNC_FTW_TYPE_FILE); + assert_int_equal(rc, CSYNC_FILE_EXCLUDE_LIST); + + rc = csync_excluded_no_ctx(csync->excludes, "/excludepath/withsubdir2", CSYNC_FTW_TYPE_DIR); + assert_int_equal(rc, CSYNC_NOT_EXCLUDED); + + rc = csync_excluded_no_ctx(csync->excludes, "/excludepath/withsubdir/foo", CSYNC_FTW_TYPE_DIR); + assert_int_equal(rc, CSYNC_FILE_EXCLUDE_LIST); +} + +static void check_csync_is_windows_reserved_word() { + assert_true(csync_is_windows_reserved_word("CON")); + assert_true(csync_is_windows_reserved_word("con")); + assert_true(csync_is_windows_reserved_word("CON.")); + assert_true(csync_is_windows_reserved_word("con.")); + assert_true(csync_is_windows_reserved_word("CON.ference")); + assert_false(csync_is_windows_reserved_word("CONference")); + assert_false(csync_is_windows_reserved_word("conference")); + assert_false(csync_is_windows_reserved_word("conf.erence")); + assert_false(csync_is_windows_reserved_word("co")); + assert_true(csync_is_windows_reserved_word("A:")); + assert_true(csync_is_windows_reserved_word("a:")); + assert_true(csync_is_windows_reserved_word("z:")); + assert_true(csync_is_windows_reserved_word("Z:")); + assert_true(csync_is_windows_reserved_word("M:")); + assert_true(csync_is_windows_reserved_word("m:")); +} + +static void check_csync_excluded_performance(void **state) +{ + CSYNC *csync = *state; + + const int N = 10000; + int totalRc = 0; + int i = 0; + + // Being able to use QElapsedTimer for measurement would be nice... + { + struct timeval before, after; + gettimeofday(&before, 0); + + for (i = 0; i < N; ++i) { + totalRc += csync_excluded_no_ctx(csync->excludes, "/this/is/quite/a/long/path/with/many/components", CSYNC_FTW_TYPE_DIR); + totalRc += csync_excluded_no_ctx(csync->excludes, "/1/2/3/4/5/6/7/8/9/10/11/12/13/14/15/16/17/18/19/20/21/22/23/24/25/26/27/29", CSYNC_FTW_TYPE_FILE); + } + assert_int_equal(totalRc, CSYNC_NOT_EXCLUDED); // mainly to avoid optimization + + gettimeofday(&after, 0); + + const double total = (after.tv_sec - before.tv_sec) + + (after.tv_usec - before.tv_usec) / 1.0e6; + const double perCallMs = total / 2 / N * 1000; + printf("csync_excluded: %f ms per call\n", perCallMs); + } + + { + struct timeval before, after; + gettimeofday(&before, 0); + + for (i = 0; i < N; ++i) { + totalRc += csync_excluded_traversal(csync->excludes, "/this/is/quite/a/long/path/with/many/components", CSYNC_FTW_TYPE_DIR); + totalRc += csync_excluded_traversal(csync->excludes, "/1/2/3/4/5/6/7/8/9/10/11/12/13/14/15/16/17/18/19/20/21/22/23/24/25/26/27/29", CSYNC_FTW_TYPE_FILE); + } + assert_int_equal(totalRc, CSYNC_NOT_EXCLUDED); // mainly to avoid optimization + + gettimeofday(&after, 0); + + const double total = (after.tv_sec - before.tv_sec) + + (after.tv_usec - before.tv_usec) / 1.0e6; + const double perCallMs = total / 2 / N * 1000; + printf("csync_excluded_traversal: %f ms per call\n", perCallMs); + } +} + +static void check_csync_exclude_expand_escapes(void **state) +{ + (void)state; + + const char *str = csync_exclude_expand_escapes( + "keep \\' \\\" \\? \\\\ \\a \\b \\f \\n \\r \\t \\v \\z"); + assert_true(0 == strcmp( + str, "keep ' \" ? \\ \a \b \f \n \r \t \v \\z")); + SAFE_FREE(str); + + str = csync_exclude_expand_escapes(""); + assert_true(0 == strcmp(str, "")); + SAFE_FREE(str); + + str = csync_exclude_expand_escapes("\\"); + assert_true(0 == strcmp(str, "\\")); + SAFE_FREE(str); +} + +int torture_run_tests(void) +{ + const struct CMUnitTest tests[] = { + cmocka_unit_test_setup_teardown(check_csync_exclude_add, setup, teardown), + cmocka_unit_test_setup_teardown(check_csync_exclude_load, setup, teardown), + cmocka_unit_test_setup_teardown(check_csync_excluded, setup_init, teardown), + cmocka_unit_test_setup_teardown(check_csync_excluded_traversal, setup_init, teardown), + cmocka_unit_test_setup_teardown(check_csync_pathes, setup_init, teardown), + cmocka_unit_test_setup_teardown(check_csync_is_windows_reserved_word, setup_init, teardown), + cmocka_unit_test_setup_teardown(check_csync_excluded_performance, setup_init, teardown), + cmocka_unit_test(check_csync_exclude_expand_escapes), + }; + + return cmocka_run_group_tests(tests, NULL, NULL); +} diff --git a/test/csync/csync_tests/check_csync_init.c b/test/csync/csync_tests/check_csync_init.c new file mode 100644 index 000000000..41876d638 --- /dev/null +++ b/test/csync/csync_tests/check_csync_init.c @@ -0,0 +1,88 @@ +/* + * libcsync -- a library to sync a directory with another + * + * Copyright (c) 2008-2013 by Andreas Schneider <asn@cryptomilk.org> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ +#include <string.h> + +#include "torture.h" + +#include "csync_private.h" + +static int setup(void **state) { + CSYNC *csync; + int rc; + + rc = system("mkdir -p /tmp/check_csync1"); + assert_int_equal(rc, 0); + + csync_create(&csync, "/tmp/check_csync1"); + + *state = csync; + return 0; +} + +static int setup_module(void **state) { + CSYNC *csync; + int rc; + + rc = system("mkdir -p /tmp/check_csync1"); + assert_int_equal(rc, 0); + + csync_create(&csync, "/tmp/check_csync1"); + + *state = csync; + return 0; +} + +static int teardown(void **state) { + CSYNC *csync = *state; + int rc; + + rc = csync_destroy(csync); + + rc = system("rm -rf /tmp/check_csync"); + assert_int_equal(rc, 0); + + rc = system("rm -rf /tmp/check_csync1"); + assert_int_equal(rc, 0); + + *state = NULL; + + return 0; +} + +static void check_csync_init(void **state) +{ + CSYNC *csync = *state; + + csync_init(csync, ""); + + assert_int_equal(csync->status & CSYNC_STATUS_INIT, 1); + +} + +int torture_run_tests(void) +{ + const struct CMUnitTest tests[] = { + cmocka_unit_test_setup_teardown(check_csync_init, setup, teardown), + cmocka_unit_test_setup_teardown(check_csync_init, setup_module, teardown), + }; + + return cmocka_run_group_tests(tests, NULL, NULL); +} + diff --git a/test/csync/csync_tests/check_csync_log.c b/test/csync/csync_tests/check_csync_log.c new file mode 100644 index 000000000..9523d9627 --- /dev/null +++ b/test/csync/csync_tests/check_csync_log.c @@ -0,0 +1,145 @@ +/* + * libcsync -- a library to sync a directory with another + * + * Copyright (c) 2008-2013 by Andreas Schneider <asn@cryptomilk.org> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ +#include <sys/types.h> +#include <sys/stat.h> + +#include "torture.h" + +#include "csync.h" +#include "csync_log.c" +#include "c_private.h" + +static int setup(void **state) { + CSYNC *csync; + int rc; + + rc = system("mkdir -p /tmp/check_csync1"); + assert_int_equal(rc, 0); + + csync_create(&csync, "/tmp/check_csync1"); + + *state = csync; + + return 0; +} + +static int teardown(void **state) { + CSYNC *csync = *state; + int rc; + + rc = csync_destroy(csync); + + rc = system("rm -rf /tmp/check_csync"); + assert_int_equal(rc, 0); + + rc = system("rm -rf /tmp/check_csync1"); + assert_int_equal(rc, 0); + + *state = NULL; + + return 0; +} + +static void check_log_callback(int verbosity, + const char *function, + const char *buffer) +{ + int rc; + + assert_true(verbosity >= 0); + assert_non_null(function); + assert_false(function[0] == '\0'); + assert_non_null(buffer); + assert_false(buffer[0] == '\0'); + + rc = system("touch /tmp/check_csync1/cb_called"); + assert_int_equal(rc, 0); +} + +static void check_set_log_level(void **state) +{ + int rc; + + (void) state; + + rc = csync_set_log_level(-5); + assert_int_equal(rc, -1); + + rc = csync_set_log_level(5); + assert_int_equal(rc, 0); + + rc = csync_get_log_level(); + assert_int_equal(rc, 5); +} + +static void check_set_auth_callback(void **state) +{ + csync_log_callback log_fn; + int rc; + + (void) state; + + rc = csync_set_log_callback(NULL); + assert_int_equal(rc, -1); + + rc = csync_set_log_callback(check_log_callback); + assert_int_equal(rc, 0); + + log_fn = csync_get_log_callback(); + assert_non_null(log_fn); + assert_true(log_fn == &check_log_callback); +} + +static void check_logging(void **state) +{ + int rc; + csync_stat_t sb; + mbchar_t *path; + path = c_utf8_path_to_locale("/tmp/check_csync1/cb_called"); + + (void) state; /* unused */ + + assert_non_null(path); + + rc = csync_set_log_level(1); + assert_int_equal(rc, 0); + + rc = csync_set_log_callback(check_log_callback); + assert_int_equal(rc, 0); + + csync_log(1, __func__, "rc = %d", rc); + + rc = _tstat(path, &sb); + + c_free_locale_string(path); + + assert_int_equal(rc, 0); +} + +int torture_run_tests(void) +{ + const struct CMUnitTest tests[] = { + cmocka_unit_test(check_set_log_level), + cmocka_unit_test(check_set_auth_callback), + cmocka_unit_test_setup_teardown(check_logging, setup, teardown), + }; + + return cmocka_run_group_tests(tests, NULL, NULL); +} diff --git a/test/csync/csync_tests/check_csync_misc.c b/test/csync/csync_tests/check_csync_misc.c new file mode 100644 index 000000000..80736b825 --- /dev/null +++ b/test/csync/csync_tests/check_csync_misc.c @@ -0,0 +1,57 @@ +/* + * libcsync -- a library to sync a directory with another + * + * Copyright (c) 2008-2013 by Andreas Schneider <asn@cryptomilk.org> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ +#include "torture.h" + +#include "csync_misc.h" +#include <stdlib.h> + +static void check_csync_normalize_etag(void **state) +{ + char *str; + + (void) state; /* unused */ + +#define CHECK_NORMALIZE_ETAG(TEST, EXPECT) \ + str = csync_normalize_etag(TEST); \ + assert_string_equal(str, EXPECT); \ + free(str); + + + CHECK_NORMALIZE_ETAG("foo", "foo"); + CHECK_NORMALIZE_ETAG("\"foo\"", "foo"); + CHECK_NORMALIZE_ETAG("\"nar123\"", "nar123"); + CHECK_NORMALIZE_ETAG("", ""); + CHECK_NORMALIZE_ETAG("\"\"", ""); + + /* Test with -gzip (all combinaison) */ + CHECK_NORMALIZE_ETAG("foo-gzip", "foo"); + CHECK_NORMALIZE_ETAG("\"foo\"-gzip", "foo"); + CHECK_NORMALIZE_ETAG("\"foo-gzip\"", "foo"); +} + +int torture_run_tests(void) +{ + const struct CMUnitTest tests[] = { + cmocka_unit_test(check_csync_normalize_etag), + }; + + return cmocka_run_group_tests(tests, NULL, NULL); +} + diff --git a/test/csync/csync_tests/check_csync_statedb_load.c b/test/csync/csync_tests/check_csync_statedb_load.c new file mode 100644 index 000000000..c4b34b500 --- /dev/null +++ b/test/csync/csync_tests/check_csync_statedb_load.c @@ -0,0 +1,130 @@ +/* + * libcsync -- a library to sync a directory with another + * + * Copyright (c) 2008-2013 by Andreas Schneider <asn@cryptomilk.org> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ +#include <string.h> + +#include "torture.h" + +#define CSYNC_TEST 1 +#include "csync_statedb.c" + +#define TESTDB "/tmp/check_csync1/test.db" + +static int setup(void **state) { + CSYNC *csync; + int rc; + + rc = system("rm -rf /tmp/check_csync1"); + assert_int_equal(rc, 0); + + rc = system("mkdir -p /tmp/check_csync1"); + assert_int_equal(rc, 0); + + csync_create(&csync, "/tmp/check_csync1"); + + csync->statedb.file = c_strdup( TESTDB ); + *state = csync; + + sqlite3 *db = NULL; + rc = sqlite3_open_v2(TESTDB, &db, SQLITE_OPEN_CREATE | SQLITE_OPEN_READWRITE, NULL); + assert_int_equal(rc, SQLITE_OK); + + rc = sqlite3_close(db); + assert_int_equal(rc, SQLITE_OK); + + return 0; +} + +static int teardown(void **state) { + CSYNC *csync = *state; + int rc; + + rc = csync_destroy(csync); + assert_int_equal(rc, 0); + + rc = system("rm -rf /tmp/check_csync1"); + assert_int_equal(rc, 0); + + *state = NULL; + + return 0; +} + +static void check_csync_statedb_load(void **state) +{ + CSYNC *csync = *state; + int rc; + + rc = csync_statedb_load(csync, TESTDB, &csync->statedb.db); + assert_int_equal(rc, 0); + + sqlite3_close(csync->statedb.db); +} + +static void check_csync_statedb_close(void **state) +{ + CSYNC *csync = *state; + csync_stat_t sb; + time_t modtime; + mbchar_t *testdb = c_utf8_path_to_locale(TESTDB); + int rc; + + /* statedb not written */ + csync_statedb_load(csync, TESTDB, &csync->statedb.db); + + rc = _tstat(testdb, &sb); + assert_int_equal(rc, 0); + modtime = sb.st_mtime; + + rc = csync_statedb_close(csync); + assert_int_equal(rc, 0); + + rc = _tstat(testdb, &sb); + assert_int_equal(rc, 0); + assert_int_equal(modtime, sb.st_mtime); + + csync_statedb_load(csync, TESTDB, &csync->statedb.db); + + rc = _tstat(testdb, &sb); + assert_int_equal(rc, 0); + modtime = sb.st_mtime; + + /* wait a sec or the modtime will be the same */ + sleep(1); + + /* statedb written */ + rc = csync_statedb_close(csync); + assert_int_equal(rc, 0); + + rc = _tstat(testdb, &sb); + assert_int_equal(rc, 0); + + c_free_locale_string(testdb); +} + +int torture_run_tests(void) +{ + const struct CMUnitTest tests[] = { + cmocka_unit_test_setup_teardown(check_csync_statedb_load, setup, teardown), + cmocka_unit_test_setup_teardown(check_csync_statedb_close, setup, teardown), + }; + + return cmocka_run_group_tests(tests, NULL, NULL); +} + diff --git a/test/csync/csync_tests/check_csync_statedb_query.c b/test/csync/csync_tests/check_csync_statedb_query.c new file mode 100644 index 000000000..603195e8c --- /dev/null +++ b/test/csync/csync_tests/check_csync_statedb_query.c @@ -0,0 +1,224 @@ +/* + * libcsync -- a library to sync a directory with another + * + * Copyright (c) 2008-2013 by Andreas Schneider <asn@cryptomilk.org> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ +#include "torture.h" + +#define CSYNC_TEST 1 +#include "csync_statedb.c" + +#define TESTDB "/tmp/check_csync1/test.db" +#define TESTDBTMP "/tmp/check_csync1/test.db.ctmp" + + + +static int setup(void **state) +{ + CSYNC *csync; + int rc = 0; + + rc = system("rm -rf /tmp/check_csync1"); + assert_int_equal(rc, 0); + rc = system("mkdir -p /tmp/check_csync1"); + assert_int_equal(rc, 0); + rc = system("mkdir -p /tmp/check_csync"); + assert_int_equal(rc, 0); + csync_create(&csync, "/tmp/check_csync1"); + csync_init(csync, TESTDB); + + sqlite3 *db = NULL; + rc = sqlite3_open_v2(TESTDB, &db, SQLITE_OPEN_CREATE | SQLITE_OPEN_READWRITE, NULL); + assert_int_equal(rc, SQLITE_OK); + rc = sqlite3_close(db); + assert_int_equal(rc, SQLITE_OK); + + rc = csync_statedb_load(csync, TESTDB, &csync->statedb.db); + assert_int_equal(rc, 0); + + *state = csync; + + return 0; +} + +static int setup_db(void **state) +{ + char *errmsg; + int rc = 0; + sqlite3 *db = NULL; + + const char *sql = "CREATE TABLE IF NOT EXISTS metadata (" + "phash INTEGER(8)," + "pathlen INTEGER," + "path VARCHAR(4096)," + "inode INTEGER," + "uid INTEGER," + "gid INTEGER," + "mode INTEGER," + "modtime INTEGER(8)," + "type INTEGER," + "md5 VARCHAR(32)," + "PRIMARY KEY(phash)" + ");"; + + const char *sql2 = "INSERT INTO metadata" + "(phash, pathlen, path, inode, uid, gid, mode, modtime, type, md5) VALUES" + "(42, 42, 'Its funny stuff', 23, 42, 43, 55, 66, 2, 54);"; + + + setup(state); + rc = sqlite3_open( TESTDB, &db); + assert_int_equal(rc, SQLITE_OK); + + rc = sqlite3_exec( db, sql, NULL, NULL, &errmsg ); + assert_int_equal(rc, SQLITE_OK); + + rc = sqlite3_exec( db, sql2, NULL, NULL, &errmsg ); + assert_int_equal(rc, SQLITE_OK); + + sqlite3_close(db); + + return 0; + +} + +static int teardown(void **state) { + CSYNC *csync = *state; + int rc = 0; + + rc = csync_destroy(csync); + assert_int_equal(rc, 0); + rc = system("rm -rf /tmp/check_csync"); + assert_int_equal(rc, 0); + rc = system("rm -rf /tmp/check_csync1"); + assert_int_equal(rc, 0); + + *state = NULL; + + return 0; +} + + +static void check_csync_statedb_query_statement(void **state) +{ + CSYNC *csync = *state; + c_strlist_t *result; + + result = csync_statedb_query(csync->statedb.db, ""); + assert_null(result); + if (result != NULL) { + c_strlist_destroy(result); + } + + result = csync_statedb_query(csync->statedb.db, "SELECT;"); + assert_null(result); + if (result != NULL) { + c_strlist_destroy(result); + } +} + +static void check_csync_statedb_drop_tables(void **state) +{ + // CSYNC *csync = *state; + int rc = 0; + (void) state; + + // rc = csync_statedb_drop_tables(csync->statedb.db); + assert_int_equal(rc, 0); + // rc = csync_statedb_create_tables(csync->statedb.db); + assert_int_equal(rc, 0); + // rc = csync_statedb_drop_tables(csync->statedb.db); + assert_int_equal(rc, 0); +} + +static void check_csync_statedb_insert_metadata(void **state) +{ + CSYNC *csync = *state; + csync_file_stat_t *st; + int i, rc = 0; + + // rc = csync_statedb_create_tables(csync->statedb.db); + assert_int_equal(rc, 0); + + for (i = 0; i < 100; i++) { + st = c_malloc(sizeof(csync_file_stat_t) + 30 ); + snprintf(st->path, 29, "file_%d" , i ); + st->phash = i; + + rc = c_rbtree_insert(csync->local.tree, (void *) st); + assert_int_equal(rc, 0); + } + + // rc = csync_statedb_insert_metadata(csync, csync->statedb.db); + assert_int_equal(rc, 0); +} + +static void check_csync_statedb_write(void **state) +{ + CSYNC *csync = *state; + csync_file_stat_t *st; + int i, rc; + + for (i = 0; i < 100; i++) { + st = c_malloc(sizeof(csync_file_stat_t) + 30); + snprintf(st->path, 29, "file_%d" , i ); + st->phash = i; + + rc = c_rbtree_insert(csync->local.tree, (void *) st); + assert_int_equal(rc, 0); + } + + // rc = csync_statedb_write(csync, csync->statedb.db); + assert_int_equal(rc, 0); +} + + +static void check_csync_statedb_get_stat_by_hash_not_found(void **state) +{ + CSYNC *csync = *state; + csync_file_stat_t *tmp; + + tmp = csync_statedb_get_stat_by_hash(csync, (uint64_t) 666); + assert_null(tmp); + + free(tmp); +} + + +static void check_csync_statedb_get_stat_by_inode_not_found(void **state) +{ + CSYNC *csync = *state; + csync_file_stat_t *tmp; + + tmp = csync_statedb_get_stat_by_inode(csync, (ino_t) 666); + assert_null(tmp); +} + +int torture_run_tests(void) +{ + const struct CMUnitTest tests[] = { + cmocka_unit_test_setup_teardown(check_csync_statedb_query_statement, setup, teardown), + cmocka_unit_test_setup_teardown(check_csync_statedb_drop_tables, setup, teardown), + cmocka_unit_test_setup_teardown(check_csync_statedb_insert_metadata, setup, teardown), + cmocka_unit_test_setup_teardown(check_csync_statedb_write, setup, teardown), + cmocka_unit_test_setup_teardown(check_csync_statedb_get_stat_by_hash_not_found, setup_db, teardown), + cmocka_unit_test_setup_teardown(check_csync_statedb_get_stat_by_inode_not_found, setup_db, teardown), + }; + + return cmocka_run_group_tests(tests, NULL, NULL); +} + diff --git a/test/csync/csync_tests/check_csync_update.c b/test/csync/csync_tests/check_csync_update.c new file mode 100644 index 000000000..695616b2c --- /dev/null +++ b/test/csync/csync_tests/check_csync_update.c @@ -0,0 +1,457 @@ +/* + * libcsync -- a library to sync a directory with another + * + * Copyright (c) 2008-2013 by Andreas Schneider <asn@cryptomilk.org> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ +#include "torture.h" + +#include "csync_update.c" + +#define TESTDB "/tmp/check_csync/journal.db" + +static int firstrun = 1; + +static void statedb_create_metadata_table(sqlite3 *db) +{ + int rc = 0; + + if( db ) { + const char *sql = "CREATE TABLE IF NOT EXISTS metadata(" + "phash INTEGER(8)," + "pathlen INTEGER," + "path VARCHAR(4096)," + "inode INTEGER," + "uid INTEGER," + "gid INTEGER," + "mode INTEGER," + "modtime INTEGER(8)," + "type INTEGER," + "md5 VARCHAR(32)," + "fileid VARCHAR(128)," + "remotePerm VARCHAR(128)," + "filesize BIGINT," + "ignoredChildrenRemote INT," + "contentChecksum TEXT," + "contentChecksumTypeId INTEGER," + "PRIMARY KEY(phash));"; + + rc = sqlite3_exec(db, sql, NULL, NULL, NULL); + //const char *msg = sqlite3_errmsg(db); + assert_int_equal( rc, SQLITE_OK ); + + sql = "CREATE TABLE IF NOT EXISTS checksumtype(" + "id INTEGER PRIMARY KEY," + "name TEXT UNIQUE" + ");"; + rc = sqlite3_exec(db, sql, NULL, NULL, NULL); + assert_int_equal( rc, SQLITE_OK ); + } +} + +static void statedb_insert_metadata(sqlite3 *db) +{ + int rc = 0; + + if( db ) { + char *stmt = sqlite3_mprintf("INSERT INTO metadata" + "(phash, pathlen, path, inode, uid, gid, mode, modtime,type,md5) VALUES" + "(%lld, %d, '%q', %d, %d, %d, %d, %lld, %d, '%q');", + (long long signed int)42, + 42, + "I_was_wurst_before_I_became_wurstsalat", + 619070, + 42, + 42, + 42, + (long long signed int)42, + 0, + "4711"); + + char *errmsg; + rc = sqlite3_exec(db, stmt, NULL, NULL, &errmsg); + sqlite3_free(stmt); + assert_int_equal( rc, SQLITE_OK ); + } +} + +static int setup(void **state) +{ + CSYNC *csync; + int rc; + + unlink(TESTDB); + rc = system("mkdir -p /tmp/check_csync"); + assert_int_equal(rc, 0); + rc = system("mkdir -p /tmp/check_csync1"); + assert_int_equal(rc, 0); + csync_create(&csync, "/tmp/check_csync1"); + csync_init(csync, TESTDB); + + /* Create a new db with metadata */ + sqlite3 *db; + csync->statedb.file = c_strdup(TESTDB); + rc = sqlite3_open(csync->statedb.file, &db); + statedb_create_metadata_table(db); + if( firstrun ) { + statedb_insert_metadata(db); + firstrun = 0; + } + sqlite3_close(db); + + rc = csync_statedb_load(csync, TESTDB, &csync->statedb.db); + assert_int_equal(rc, 0); + + *state = csync; + + return 0; +} + +static int setup_ftw(void **state) +{ + CSYNC *csync; + int rc; + + rc = system("mkdir -p /tmp/check_csync"); + assert_int_equal(rc, 0); + rc = system("mkdir -p /tmp/check_csync1"); + assert_int_equal(rc, 0); + csync_create(&csync, "/tmp"); + csync_init(csync, TESTDB); + + sqlite3 *db = NULL; + rc = sqlite3_open_v2(TESTDB, &db, SQLITE_OPEN_CREATE | SQLITE_OPEN_READWRITE, NULL); + assert_int_equal(rc, SQLITE_OK); + statedb_create_metadata_table(db); + rc = sqlite3_close(db); + assert_int_equal(rc, SQLITE_OK); + + rc = csync_statedb_load(csync, TESTDB, &csync->statedb.db); + assert_int_equal(rc, 0); + + csync->statedb.file = c_strdup( TESTDB ); + *state = csync; + + return 0; +} + +static int teardown(void **state) +{ + CSYNC *csync = *state; + int rc; + + unlink( csync->statedb.file); + rc = csync_destroy(csync); + assert_int_equal(rc, 0); + + *state = NULL; + + return 0; +} + +static int teardown_rm(void **state) { + int rc; + + teardown(state); + + rc = system("rm -rf /tmp/check_csync"); + assert_int_equal(rc, 0); + rc = system("rm -rf /tmp/check_csync1"); + assert_int_equal(rc, 0); + + return 0; +} + +/* create a file stat, caller must free memory */ +static csync_vio_file_stat_t* create_fstat(const char *name, + ino_t inode, + time_t mtime) +{ + csync_vio_file_stat_t *fs = NULL; + time_t t; + + fs = csync_vio_file_stat_new(); + if (fs == NULL) { + return NULL; + } + + if (name && *name) { + fs->name = c_strdup(name); + } else { + fs->name = c_strdup("file.txt"); + } + + if (fs->name == NULL) { + csync_vio_file_stat_destroy(fs); + return NULL; + } + + fs->fields = CSYNC_VIO_FILE_STAT_FIELDS_NONE; + + fs->type = CSYNC_VIO_FILE_TYPE_REGULAR; + fs->fields |= CSYNC_VIO_FILE_STAT_FIELDS_TYPE; + + + if (inode == 0) { + fs->inode = 619070; + } else { + fs->inode = inode; + } + fs->fields |= CSYNC_VIO_FILE_STAT_FIELDS_INODE; + + + fs->size = 157459; + fs->fields |= CSYNC_VIO_FILE_STAT_FIELDS_SIZE; + + + + if (mtime == 0) { + fs->atime = fs->ctime = fs->mtime = time(&t); + } else { + fs->atime = fs->ctime = fs->mtime = mtime; + } + fs->fields |= CSYNC_VIO_FILE_STAT_FIELDS_ATIME; + fs->fields |= CSYNC_VIO_FILE_STAT_FIELDS_CTIME; + fs->fields |= CSYNC_VIO_FILE_STAT_FIELDS_MTIME; + + return fs; +} + +static int failing_fn(CSYNC *ctx, + const char *file, + const csync_vio_file_stat_t *fs, + enum csync_ftw_flags_e flag) +{ + (void) ctx; + (void) file; + (void) fs; + (void) flag; + + return -1; +} + +/* detect a new file */ +static void check_csync_detect_update(void **state) +{ + CSYNC *csync = *state; + csync_file_stat_t *st; + csync_vio_file_stat_t *fs; + int rc; + + fs = create_fstat("file.txt", 0, 1217597845); + assert_non_null(fs); + + rc = _csync_detect_update(csync, + "/tmp/check_csync1/file.txt", + fs, + CSYNC_FTW_TYPE_FILE); + assert_int_equal(rc, 0); + + /* the instruction should be set to new */ + st = c_rbtree_node_data(csync->local.tree->root); + assert_int_equal(st->instruction, CSYNC_INSTRUCTION_NEW); + + /* create a statedb */ + csync_set_status(csync, 0xFFFF); + + csync_vio_file_stat_destroy(fs); +} + +/* Test behaviour in case no db is there. For that its important that the + * test before this one uses teardown_rm. + */ +static void check_csync_detect_update_db_none(void **state) +{ + CSYNC *csync = *state; + csync_file_stat_t *st; + csync_vio_file_stat_t *fs; + int rc; + + fs = create_fstat("file.txt", 0, 1217597845); + assert_non_null(fs); + + rc = _csync_detect_update(csync, + "/tmp/check_csync1/file.txt", + fs, + CSYNC_FTW_TYPE_FILE); + assert_int_equal(rc, 0); + + /* the instruction should be set to new */ + st = c_rbtree_node_data(csync->local.tree->root); + assert_int_equal(st->instruction, CSYNC_INSTRUCTION_NEW); + + + /* create a statedb */ + csync_set_status(csync, 0xFFFF); + + csync_vio_file_stat_destroy(fs); +} + +static void check_csync_detect_update_db_eval(void **state) +{ + CSYNC *csync = *state; + csync_file_stat_t *st; + csync_vio_file_stat_t *fs; + int rc; + + fs = create_fstat("file.txt", 0, 42); + assert_non_null(fs); + + rc = _csync_detect_update(csync, + "/tmp/check_csync1/file.txt", + fs, + CSYNC_FTW_TYPE_FILE); + assert_int_equal(rc, 0); + + /* the instruction should be set to new */ + st = c_rbtree_node_data(csync->local.tree->root); + assert_int_equal(st->instruction, CSYNC_INSTRUCTION_NEW); + + /* create a statedb */ + csync_set_status(csync, 0xFFFF); + + csync_vio_file_stat_destroy(fs); +} + + +static void check_csync_detect_update_db_rename(void **state) +{ + CSYNC *csync = *state; + // csync_file_stat_t *st; + + csync_vio_file_stat_t *fs; + int rc = 0; + + fs = create_fstat("wurst.txt", 0, 42); + assert_non_null(fs); + csync_set_statedb_exists(csync, 1); + + rc = _csync_detect_update(csync, + "/tmp/check_csync1/wurst.txt", + fs, + CSYNC_FTW_TYPE_FILE); + assert_int_equal(rc, 0); + + /* the instruction should be set to rename */ + /* + * temporarily broken. + st = c_rbtree_node_data(csync->local.tree->root); + assert_int_equal(st->instruction, CSYNC_INSTRUCTION_RENAME); + + st->instruction = CSYNC_INSTRUCTION_UPDATED; + */ + /* create a statedb */ + csync_set_status(csync, 0xFFFF); + + csync_vio_file_stat_destroy(fs); +} + +static void check_csync_detect_update_db_new(void **state) +{ + CSYNC *csync = *state; + csync_file_stat_t *st; + csync_vio_file_stat_t *fs; + int rc; + + fs = create_fstat("file.txt", 42000, 0); + assert_non_null(fs); + + rc = _csync_detect_update(csync, + "/tmp/check_csync1/file.txt", + fs, + CSYNC_FTW_TYPE_FILE); + assert_int_equal(rc, 0); + + /* the instruction should be set to new */ + st = c_rbtree_node_data(csync->local.tree->root); + assert_int_equal(st->instruction, CSYNC_INSTRUCTION_NEW); + + + /* create a statedb */ + csync_set_status(csync, 0xFFFF); + + csync_vio_file_stat_destroy(fs); +} + +static void check_csync_detect_update_null(void **state) +{ + CSYNC *csync = *state; + csync_vio_file_stat_t *fs; + int rc; + + fs = create_fstat("file.txt", 0, 0); + assert_non_null(fs); + + rc = _csync_detect_update(csync, + NULL, + fs, + CSYNC_FTW_TYPE_FILE); + assert_int_equal(rc, -1); + + rc = _csync_detect_update(csync, + "/tmp/check_csync1/file.txt", + NULL, + CSYNC_FTW_TYPE_FILE); + assert_int_equal(rc, -1); + + csync_vio_file_stat_destroy(fs); +} + +static void check_csync_ftw(void **state) +{ + CSYNC *csync = *state; + int rc; + + rc = csync_ftw(csync, "/tmp", csync_walker, MAX_DEPTH); + assert_int_equal(rc, 0); +} + +static void check_csync_ftw_empty_uri(void **state) +{ + CSYNC *csync = *state; + int rc; + + rc = csync_ftw(csync, "", csync_walker, MAX_DEPTH); + assert_int_equal(rc, -1); +} + +static void check_csync_ftw_failing_fn(void **state) +{ + CSYNC *csync = *state; + int rc; + + rc = csync_ftw(csync, "/tmp", failing_fn, MAX_DEPTH); + assert_int_equal(rc, -1); +} + +int torture_run_tests(void) +{ + const struct CMUnitTest tests[] = { + cmocka_unit_test_setup_teardown(check_csync_detect_update, setup, teardown_rm), + cmocka_unit_test_setup_teardown(check_csync_detect_update_db_none, setup, teardown), + cmocka_unit_test_setup_teardown(check_csync_detect_update_db_eval, setup, teardown), + cmocka_unit_test_setup_teardown(check_csync_detect_update_db_rename, setup, teardown), + cmocka_unit_test_setup_teardown(check_csync_detect_update_db_new, setup, teardown_rm), + cmocka_unit_test_setup_teardown(check_csync_detect_update_null, setup, teardown_rm), + + cmocka_unit_test_setup_teardown(check_csync_ftw, setup_ftw, teardown_rm), + cmocka_unit_test_setup_teardown(check_csync_ftw_empty_uri, setup_ftw, teardown_rm), + cmocka_unit_test_setup_teardown(check_csync_ftw_failing_fn, setup_ftw, teardown_rm), + }; + + return cmocka_run_group_tests(tests, NULL, NULL); +} + diff --git a/test/csync/csync_tests/check_csync_util.c b/test/csync/csync_tests/check_csync_util.c new file mode 100644 index 000000000..e55c4ce77 --- /dev/null +++ b/test/csync/csync_tests/check_csync_util.c @@ -0,0 +1,53 @@ +/* + * libcsync -- a library to sync a directory with another + * + * Copyright (c) 2008-2013 by Andreas Schneider <asn@cryptomilk.org> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ +#include "torture.h" + +#include "csync_util.h" + +static void check_csync_instruction_str(void **state) +{ + const char *str; + + (void) state; /* unused */ + + str = csync_instruction_str(CSYNC_INSTRUCTION_ERROR); + assert_string_equal(str, "INSTRUCTION_ERROR"); + + str = csync_instruction_str(0xFFFF); + assert_string_equal(str, "ERROR!"); +} + +static void check_csync_memstat(void **state) +{ + (void) state; /* unused */ + + csync_memstat_check(); +} + +int torture_run_tests(void) +{ + const struct CMUnitTest tests[] = { + cmocka_unit_test(check_csync_instruction_str), + cmocka_unit_test(check_csync_memstat), + }; + + return cmocka_run_group_tests(tests, NULL, NULL); +} + diff --git a/test/csync/encoding_tests/check_encoding.c b/test/csync/encoding_tests/check_encoding.c new file mode 100644 index 000000000..eb761d318 --- /dev/null +++ b/test/csync/encoding_tests/check_encoding.c @@ -0,0 +1,205 @@ +/* + * libcsync -- a library to sync a directory with another + * + * Copyright (c) 2013 by Klaas Freitag <freitag@owncloud.com> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ +#include "torture.h" +#include <stdio.h> +#include "c_string.h" +#include "c_path.h" + +#ifdef _WIN32 +#include <string.h> +#endif + + +static void setup(void **state) +{ + (void) state; /* unused */ +} + +static void teardown(void **state) +{ + (void) state; /* unused */ +} + +static void check_iconv_to_native_normalization(void **state) +{ + mbchar_t *out = NULL; + const char *in= "\x48\xc3\xa4"; // UTF8 +#ifdef __APPLE__ + const char *exp_out = "\x48\x61\xcc\x88"; // UTF-8-MAC +#else + const char *exp_out = "\x48\xc3\xa4"; // UTF8 +#endif + + out = c_utf8_path_to_locale(in); + assert_string_equal(out, exp_out); + + c_free_locale_string(out); + assert_null(out); + + (void) state; /* unused */ +} + +static void check_iconv_from_native_normalization(void **state) +{ + char *out = NULL; +#ifdef _WIN32 + const mbchar_t *in = L"\x48\xc3\xa4"; // UTF-8 +#else +#ifdef __APPLE__ + const mbchar_t *in = "\x48\x61\xcc\x88"; // UTF-8-MAC +#else + const mbchar_t *in = "\x48\xc3\xa4"; // UTF-8 +#endif +#endif + const char *exp_out = "\x48\xc3\xa4"; // UTF-8 + + out = c_utf8_from_locale(in); + assert_string_equal(out, exp_out); + + c_free_locale_string(out); + assert_null(out); + + (void) state; /* unused */ +} + +static void check_iconv_ascii(void **state) +{ +#ifdef _WIN32 + const mbchar_t *in = L"abc/ABC\\123"; // UTF-8 +#else +#ifdef __APPLE__ + const mbchar_t *in = "abc/ABC\\123"; // UTF-8-MAC +#else + const mbchar_t *in = "abc/ABC\\123"; // UTF-8 +#endif +#endif + char *out = NULL; + const char *exp_out = "abc/ABC\\123"; + + out = c_utf8_from_locale(in); + assert_string_equal(out, exp_out); + + c_free_locale_string(out); + assert_null(out); + + (void) state; /* unused */ +} + +#define TESTSTRING "#cA\\#fߧ4" +#define LTESTSTRING L"#cA\\#fߧ4" + +static void check_to_multibyte(void **state) +{ + int rc = -1; + + mbchar_t *mb_string = c_utf8_path_to_locale( TESTSTRING ); + mbchar_t *mb_null = c_utf8_path_to_locale( NULL ); + + (void) state; + +#ifdef _WIN32 + assert_int_equal( wcscmp( LTESTSTRING, mb_string), 0 ); +#else + assert_string_equal(mb_string, TESTSTRING); +#endif + assert_true( mb_null == NULL ); + assert_int_equal(rc, -1); + + c_free_locale_string(mb_string); + c_free_locale_string(mb_null); +} + +static void check_long_win_path(void **state) +{ + (void) state; /* unused */ + + { + const char *path = "C://DATA/FILES/MUSIC/MY_MUSIC.mp3"; // check a short path + const char *exp_path = "\\\\?\\C:\\\\DATA\\FILES\\MUSIC\\MY_MUSIC.mp3"; + const char *new_short = c_path_to_UNC(path); + assert_string_equal(new_short, exp_path); + SAFE_FREE(new_short); + } + + { + const char *path = "\\\\foo\\bar/MY_MUSIC.mp3"; + const char *exp_path = "\\\\foo\\bar\\MY_MUSIC.mp3"; + const char *new_short = c_path_to_UNC(path); + assert_string_equal(new_short, exp_path); + SAFE_FREE(new_short); + } + + { + const char *path = "//foo\\bar/MY_MUSIC.mp3"; + const char *exp_path = "\\\\foo\\bar\\MY_MUSIC.mp3"; + const char *new_short = c_path_to_UNC(path); + assert_string_equal(new_short, exp_path); + SAFE_FREE(new_short); + } + + { + const char *path = "\\foo\\bar"; + const char *exp_path = "\\\\?\\foo\\bar"; + const char *new_short = c_path_to_UNC(path); + assert_string_equal(new_short, exp_path); + SAFE_FREE(new_short); + } + + { + const char *path = "/foo/bar"; + const char *exp_path = "\\\\?\\foo\\bar"; + const char *new_short = c_path_to_UNC(path); + assert_string_equal(new_short, exp_path); + SAFE_FREE(new_short); + } + + const char *longPath = "D://alonglonglonglong/blonglonglonglong/clonglonglonglong/dlonglonglonglong/" + "elonglonglonglong/flonglonglonglong/glonglonglonglong/hlonglonglonglong/ilonglonglonglong/" + "jlonglonglonglong/klonglonglonglong/llonglonglonglong/mlonglonglonglong/nlonglonglonglong/" + "olonglonglonglong/file.txt"; + const char *longPathConv = "\\\\?\\D:\\\\alonglonglonglong\\blonglonglonglong\\clonglonglonglong\\dlonglonglonglong\\" + "elonglonglonglong\\flonglonglonglong\\glonglonglonglong\\hlonglonglonglong\\ilonglonglonglong\\" + "jlonglonglonglong\\klonglonglonglong\\llonglonglonglong\\mlonglonglonglong\\nlonglonglonglong\\" + "olonglonglonglong\\file.txt"; + + const char *new_long = c_path_to_UNC(longPath); + // printf( "XXXXXXXXXXXX %s %d\n", new_long, mem_reserved); + + assert_string_equal(new_long, longPathConv); + + // printf( "YYYYYYYYYYYY %ld\n", strlen(new_long)); + assert_int_equal( strlen(new_long), 286); + SAFE_FREE(new_long); +} + +int torture_run_tests(void) +{ + const UnitTest tests[] = { + unit_test_setup_teardown(check_long_win_path, setup, teardown), + unit_test_setup_teardown(check_to_multibyte, setup, teardown), + unit_test_setup_teardown(check_iconv_ascii, setup, teardown), + unit_test_setup_teardown(check_iconv_to_native_normalization, setup, teardown), + unit_test_setup_teardown(check_iconv_from_native_normalization, setup, teardown), + + }; + + return run_tests(tests); +} + diff --git a/test/csync/log_tests/check_log.c b/test/csync/log_tests/check_log.c new file mode 100644 index 000000000..f5f961f72 --- /dev/null +++ b/test/csync/log_tests/check_log.c @@ -0,0 +1,98 @@ +/* + * libcsync -- a library to sync a directory with another + * + * Copyright (c) 2008-2013 by Andreas Schneider <asn@cryptomilk.org> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ +#include <string.h> + +#include "support.h" + +#include "config_csync.h" +#include "csync_log.h" + +static void setup(void) { + csync_log_init(); +} + +static void teardown(void) { + csync_log_fini(); +} + +START_TEST (log_create) +{ + fail_unless((csync_log_init() == 0), NULL); + fail_unless((csync_log_fini() == 0), NULL); +} +END_TEST + +START_TEST (log_load) +{ + char buf[256]; + snprintf(buf, (size_t) 256 - 1, "%s/%s", SOURCEDIR, "config/ocsync_log.conf"); + fail_unless(csync_log_load(buf) == 0); +} +END_TEST + +START_TEST (log_prio) +{ + CSYNC_LOG(CSYNC_LOG_PRIORITY_FATAL, "log %s", "test"); + CSYNC_LOG(CSYNC_LOG_PRIORITY_FATAL, "log %s", "test"); + CSYNC_LOG(CSYNC_LOG_PRIORITY_ALERT, "log %s", "test"); + CSYNC_LOG(CSYNC_LOG_PRIORITY_CRIT, "log %s", "test"); + CSYNC_LOG(CSYNC_LOG_PRIORITY_ERROR, "log %s", "test"); + CSYNC_LOG(CSYNC_LOG_PRIORITY_WARN, "log %s", "test"); + CSYNC_LOG(CSYNC_LOG_PRIORITY_NOTICE, "log %s", "test"); + CSYNC_LOG(CSYNC_LOG_PRIORITY_INFO, "log %s", "test"); + CSYNC_LOG(CSYNC_LOG_PRIORITY_DEBUG, "log %s", "test"); + CSYNC_LOG(CSYNC_LOG_PRIORITY_TRACE, "log %s", "test"); + CSYNC_LOG(CSYNC_LOG_PRIORITY_NOTSET, "log %s", "test"); + CSYNC_LOG(CSYNC_LOG_PRIORITY_UNKNOWN, "log %s", "test"); +} +END_TEST + +START_TEST (log_null) +{ + char *z = NULL; + CSYNC_LOG(CSYNC_LOG_PRIORITY_UNKNOWN, "log %s", z); +} +END_TEST + +static Suite *log_suite(void) { + Suite *s = suite_create("Logger"); + + create_case(s, "log_create", log_create); + create_case_fixture(s, "log_load", log_load, setup, teardown); + create_case_fixture(s, "log_prio", log_prio, setup, teardown); + create_case_fixture(s, "log_null", log_null, setup, teardown); + + return s; +} + +int main(void) { + int nf; + + Suite *s = log_suite(); + + SRunner *sr; + sr = srunner_create(s); + srunner_run_all(sr, CK_VERBOSE); + nf = srunner_ntests_failed(sr); + srunner_free(sr); + + return (nf == 0) ? EXIT_SUCCESS : EXIT_FAILURE; +} + diff --git a/test/csync/std_tests/check_std_c_alloc.c b/test/csync/std_tests/check_std_c_alloc.c new file mode 100644 index 000000000..80a6a58da --- /dev/null +++ b/test/csync/std_tests/check_std_c_alloc.c @@ -0,0 +1,89 @@ +/* + * libcsync -- a library to sync a directory with another + * + * Copyright (c) 2008-2013 by Andreas Schneider <asn@cryptomilk.org> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ +#include "torture.h" + +#include "std/c_alloc.h" + +struct test_s { + int answer; +}; + +static void check_c_malloc(void **state) +{ + struct test_s *p = NULL; + + (void) state; /* unused */ + + p = c_malloc(sizeof(struct test_s)); + assert_non_null(p); + assert_int_equal(p->answer, 0); + p->answer = 42; + assert_int_equal(p->answer, 42); + free(p); +} + +static void check_c_malloc_zero(void **state) +{ + void *p; + + (void) state; /* unused */ + + p = c_malloc((size_t) 0); + assert_null(p); +} + +static void check_c_strdup(void **state) +{ + const char *str = "test"; + char *tdup = NULL; + + (void) state; /* unused */ + + tdup = c_strdup(str); + assert_string_equal(tdup, str); + + free(tdup); +} + +static void check_c_strndup(void **state) +{ + const char *str = "test"; + char *tdup = NULL; + + (void) state; /* unused */ + + tdup = c_strndup(str, 3); + assert_memory_equal(tdup, "tes", 3); + + free(tdup); +} + +int torture_run_tests(void) +{ + const UnitTest tests[] = { + unit_test(check_c_malloc), + unit_test(check_c_malloc_zero), + unit_test(check_c_strdup), + unit_test(check_c_strndup), + }; + + return run_tests(tests); +} + diff --git a/test/csync/std_tests/check_std_c_jhash.c b/test/csync/std_tests/check_std_c_jhash.c new file mode 100644 index 000000000..9d8384de9 --- /dev/null +++ b/test/csync/std_tests/check_std_c_jhash.c @@ -0,0 +1,292 @@ +/* + * Tests are taken form lookup2.c and lookup8.c + * by Bob Jenkins, December 1996, Public Domain. + * + * See http://burtleburtle.net/bob/hash/evahash.html + */ +#include "torture.h" + +#include "std/c_jhash.h" + +#define HASHSTATE 1 +#define HASHLEN 1 +#define MAXPAIR 80 +#define MAXLEN 70 + +static void check_c_jhash_trials(void **state) +{ + uint8_t qa[MAXLEN+1], qb[MAXLEN+2], *a = &qa[0], *b = &qb[1]; + uint32_t c[HASHSTATE], d[HASHSTATE], i, j=0, k, l, m, z; + uint32_t e[HASHSTATE],f[HASHSTATE],g[HASHSTATE],h[HASHSTATE]; + uint32_t x[HASHSTATE],y[HASHSTATE]; + uint32_t hlen; + + (void) state; /* unused */ + + for (hlen=0; hlen < MAXLEN; ++hlen) { + z=0; + for (i=0; i<hlen; ++i) { /*----------------------- for each input byte, */ + for (j=0; j<8; ++j) { /*------------------------ for each input bit, */ + for (m=1; m<8; ++m) { /*------------ for serveral possible initvals, */ + for (l=0; l<HASHSTATE; ++l) e[l]=f[l]=g[l]=h[l]=x[l]=y[l]=~((uint32_t)0); + + /*---- check that every output bit is affected by that input bit */ + for (k=0; k<MAXPAIR; k+=2) { + uint32_t finished=1; + /* keys have one bit different */ + for (l=0; l<hlen+1; ++l) {a[l] = b[l] = (uint8_t)0;} + /* have a and b be two keys differing in only one bit */ + a[i] ^= (k<<j); + a[i] ^= (k>>(8-j)); + c[0] = c_jhash(a, hlen, m); + b[i] ^= ((k+1)<<j); + b[i] ^= ((k+1)>>(8-j)); + d[0] = c_jhash(b, hlen, m); + /* check every bit is 1, 0, set, and not set at least once */ + for (l=0; l<HASHSTATE; ++l) { + e[l] &= (c[l]^d[l]); + f[l] &= ~(c[l]^d[l]); + g[l] &= c[l]; + h[l] &= ~c[l]; + x[l] &= d[l]; + y[l] &= ~d[l]; + if (e[l]|f[l]|g[l]|h[l]|x[l]|y[l]) finished=0; + } + if (finished) break; + } + if (k>z) z=k; + if (k==MAXPAIR) { + print_error("Some bit didn't change: "); + print_error("%.8x %.8x %.8x %.8x %.8x %.8x ", + e[0], f[0], g[0], h[0], x[0], y[0]); + print_error("i %d j %d m %d len %d\n",i,j,m,hlen); + } + if (z==MAXPAIR) goto done; + } + } + } + done: + if (z < MAXPAIR) { + assert_true(z < MAXPAIR); + // print_error("%u trials needed, should be less than 40\n", z/2); + } + } +} + +static void check_c_jhash_alignment_problems(void **state) +{ + uint32_t test; + uint8_t buf[MAXLEN+20], *b; + uint32_t len; + uint8_t q[] = "This is the time for all good men to come to the aid of their country"; + uint8_t qq[] = "xThis is the time for all good men to come to the aid of their country"; + uint8_t qqq[] = "xxThis is the time for all good men to come to the aid of their country"; + uint8_t qqqq[] = "xxxThis is the time for all good men to come to the aid of their country"; + uint32_t h,i,j,ref,x,y; + + (void) state; /* unused */ + + test = c_jhash(q, sizeof(q)-1, (uint32_t)0); + assert_true(test == c_jhash(qq+1, sizeof(q)-1, (uint32_t)0)); + assert_true(test == c_jhash(qq+1, sizeof(q)-1, (uint32_t)0)); + assert_true(test == c_jhash(qqq+2, sizeof(q)-1, (uint32_t)0)); + assert_true(test == c_jhash(qqqq+3, sizeof(q)-1, (uint32_t)0)); + for (h=0, b=buf+1; h<8; ++h, ++b) { + for (i=0; i<MAXLEN; ++i) { + len = i; + for (j=0; j<i; ++j) *(b+j)=0; + + /* these should all be equal */ + ref = c_jhash(b, len, (uint32_t)1); + *(b+i)=(uint8_t)~0; + *(b-1)=(uint8_t)~0; + x = c_jhash(b, len, (uint32_t)1); + y = c_jhash(b, len, (uint32_t)1); + assert_false((ref != x) || (ref != y)); + } + } +} + +static void check_c_jhash_null_strings(void **state) +{ + uint8_t buf[1]; + uint32_t h, i, t; + + (void) state; /* unused */ + + buf[0] = ~0; + for (i=0, h=0; i<8; ++i) { + t = h; + h = c_jhash(buf, (uint32_t)0, h); + assert_false(t == h); + // print_error("0-byte-string check failed: t = %.8x, h = %.8x", t, h); + } +} + +static void check_c_jhash64_trials(void **state) +{ + uint8_t qa[MAXLEN + 1], qb[MAXLEN + 2]; + uint8_t *a, *b; + uint64_t c[HASHSTATE], d[HASHSTATE], i, j=0, k, l, m, z; + uint64_t e[HASHSTATE],f[HASHSTATE],g[HASHSTATE],h[HASHSTATE]; + uint64_t x[HASHSTATE],y[HASHSTATE]; + uint64_t hlen; + + (void) state; /* unused */ + + a = &qa[0]; + b = &qb[1]; + + for (hlen=0; hlen < MAXLEN; ++hlen) { + z=0; + for (i=0; i<hlen; ++i) { /*----------------------- for each byte, */ + for (j=0; j<8; ++j) { /*------------------------ for each bit, */ + for (m=0; m<8; ++m) { /*-------- for serveral possible levels, */ + for (l=0; l<HASHSTATE; ++l) e[l]=f[l]=g[l]=h[l]=x[l]=y[l]=~((uint64_t)0); + + /*---- check that every input bit affects every output bit */ + for (k=0; k<MAXPAIR; k+=2) { + uint64_t finished=1; + /* keys have one bit different */ + for (l=0; l<hlen+1; ++l) {a[l] = b[l] = (uint8_t)0;} + /* have a and b be two keys differing in only one bit */ + a[i] ^= (k<<j); + a[i] ^= (k>>(8-j)); + c[0] = c_jhash64(a, hlen, m); + b[i] ^= ((k+1)<<j); + b[i] ^= ((k+1)>>(8-j)); + d[0] = c_jhash64(b, hlen, m); + /* check every bit is 1, 0, set, and not set at least once */ + for (l=0; l<HASHSTATE; ++l) + { + e[l] &= (c[l]^d[l]); + f[l] &= ~(c[l]^d[l]); + g[l] &= c[l]; + h[l] &= ~c[l]; + x[l] &= d[l]; + y[l] &= ~d[l]; + if (e[l]|f[l]|g[l]|h[l]|x[l]|y[l]) finished=0; + } + if (finished) break; + } + if (k>z) z=k; + if (k==MAXPAIR) { +#if 0 + print_error("Some bit didn't change: "); + print_error("%.8llx %.8llx %.8llx %.8llx %.8llx %.8llx ", + (long long unsigned int) e[0], + (long long unsigned int) f[0], + (long long unsigned int) g[0], + (long long unsigned int) h[0], + (long long unsigned int) x[0], + (long long unsigned int) y[0]); + print_error("i %d j %d m %d len %d\n", + (uint32_t)i,(uint32_t)j,(uint32_t)m,(uint32_t)hlen); +#endif + } + if (z==MAXPAIR) goto done; + } + } + } + done: + if (z < MAXPAIR) { +#if 0 + print_error("%lu trials needed, should be less than 40", z/2); +#endif + assert_true(z < MAXPAIR); + } + } +} + +static void check_c_jhash64_alignment_problems(void **state) +{ + uint8_t buf[MAXLEN+20], *b; + uint64_t len; + uint8_t q[] = "This is the time for all good men to come to the aid of their country"; + uint8_t qq[] = "xThis is the time for all good men to come to the aid of their country"; + uint8_t qqq[] = "xxThis is the time for all good men to come to the aid of their country"; + uint8_t qqqq[] = "xxxThis is the time for all good men to come to the aid of their country"; + uint8_t o[] = "xxxxThis is the time for all good men to come to the aid of their country"; + uint8_t oo[] = "xxxxxThis is the time for all good men to come to the aid of their country"; + uint8_t ooo[] = "xxxxxxThis is the time for all good men to come to the aid of their country"; + uint8_t oooo[] = "xxxxxxxThis is the time for all good men to come to the aid of their country"; + uint64_t h,i,j,ref,t,x,y; + + (void) state; /* unused */ + + h = c_jhash64(q+0, (uint64_t)(sizeof(q)-1), (uint64_t)0); + t = h; + assert_true(t == h); + // , "%.8lx%.8lx\n", (uint32_t)h, (uint32_t)(h>>32)); + h = c_jhash64(qq+1, (uint64_t)(sizeof(q)-1), (uint64_t)0); + assert_true(t == h); + // , "%.8lx%.8lx\n", (uint32_t)h, (uint32_t)(h>>32)); + h = c_jhash64(qqq+2, (uint64_t)(sizeof(q)-1), (uint64_t)0); + assert_true(t == h); + // , "%.8lx%.8lx\n", (uint32_t)h, (uint32_t)(h>>32)); + h = c_jhash64(qqqq+3, (uint64_t)(sizeof(q)-1), (uint64_t)0); + assert_true(t == h); + // , "%.8lx%.8lx\n", (uint32_t)h, (uint32_t)(h>>32)); + h = c_jhash64(o+4, (uint64_t)(sizeof(q)-1), (uint64_t)0); + assert_true(t == h); + // , "%.8lx%.8lx\n", (uint32_t)h, (uint32_t)(h>>32)); + h = c_jhash64(oo+5, (uint64_t)(sizeof(q)-1), (uint64_t)0); + assert_true(t == h); + // , "%.8lx%.8lx\n", (uint32_t)h, (uint32_t)(h>>32)); + h = c_jhash64(ooo+6, (uint64_t)(sizeof(q)-1), (uint64_t)0); + assert_true(t == h); + // , "%.8lx%.8lx\n", (uint32_t)h, (uint32_t)(h>>32)); + h = c_jhash64(oooo+7, (uint64_t)(sizeof(q)-1), (uint64_t)0); + assert_true(t == h); + // , "%.8lx%.8lx\n", (uint32_t)h, (uint32_t)(h>>32)); + for (h=0, b=buf+1; h<8; ++h, ++b) { + for (i=0; i<MAXLEN; ++i) { + len = i; + for (j=0; j<i; ++j) *(b+j)=0; + + /* these should all be equal */ + ref = c_jhash64(b, len, (uint64_t)1); + *(b+i)=(uint8_t)~0; + *(b-1)=(uint8_t)~0; + x = c_jhash64(b, len, (uint64_t)1); + y = c_jhash64(b, len, (uint64_t)1); + assert_false((ref != x) || (ref != y)); +#if 0 + print_error("alignment error: %.8lx %.8lx %.8lx %ld %ld\n", ref, x, y, h, i); +#endif + } + } +} + +static void check_c_jhash64_null_strings(void **state) +{ + uint8_t buf[1]; + uint64_t h, i, t; + + (void) state; /* unused */ + + buf[0] = ~0; + for (i=0, h=0; i<8; ++i) { + t = h; + h = c_jhash64(buf, (uint64_t)0, h); + assert_false(t == h); +#if 0 + print_error("0-byte-string check failed: t = %.8lx, h = %.8lx", t, h); +#endif + } +} + +int torture_run_tests(void) +{ + const UnitTest tests[] = { + unit_test(check_c_jhash_trials), + unit_test(check_c_jhash_alignment_problems), + unit_test(check_c_jhash_null_strings), + unit_test(check_c_jhash64_trials), + unit_test(check_c_jhash64_alignment_problems), + unit_test(check_c_jhash64_null_strings), + }; + + return run_tests(tests); +} + diff --git a/test/csync/std_tests/check_std_c_path.c b/test/csync/std_tests/check_std_c_path.c new file mode 100644 index 000000000..208a0b90a --- /dev/null +++ b/test/csync/std_tests/check_std_c_path.c @@ -0,0 +1,185 @@ +/* + * libcsync -- a library to sync a directory with another + * + * Copyright (c) 2008-2013 by Andreas Schneider <asn@cryptomilk.org> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ +#include <string.h> +#include <stdlib.h> +#include <stdio.h> +#include <time.h> + +#include "torture.h" + +#include "std/c_path.h" + +static void check_c_basename(void **state) +{ + char *bname; + + (void) state; /* unused */ + + bname = c_basename("/usr/lib"); + assert_string_equal(bname, "lib"); + free(bname); + + bname = c_basename("/usr//"); + assert_string_equal(bname, "usr"); + free(bname); + + bname = c_basename("usr"); + assert_string_equal(bname, "usr"); + free(bname); + + bname = c_basename("///"); + assert_string_equal(bname, "/"); + free(bname); + + bname = c_basename("/"); + assert_string_equal(bname, "/"); + free(bname); + + bname = c_basename("."); + assert_string_equal(bname, "."); + free(bname); + + bname = c_basename(".."); + assert_string_equal(bname, ".."); + free(bname); + + bname = c_basename(""); + assert_string_equal(bname, "."); + free(bname); + + bname = c_basename(NULL); + assert_string_equal(bname, "."); + free(bname); +} + +static void check_c_basename_uri(void **state) +{ + char *bname = NULL; + + (void) state; /* unused */ + + bname = c_basename("smb://server/share/dir/"); + assert_string_equal(bname, "dir"); + free(bname); +} + +static void check_c_dirname(void **state) +{ + char *dname; + + (void) state; /* unused */ + + dname = c_dirname("/usr/lib"); + assert_string_equal(dname, "/usr"); + free(dname); + + dname = c_dirname("/usr//"); + assert_string_equal(dname, "/"); + free(dname); + + dname = c_dirname("usr"); + assert_string_equal(dname, "."); + free(dname); + + dname = c_dirname("/"); + assert_string_equal(dname, "/"); + free(dname); + + dname = c_dirname("///"); + assert_string_equal(dname, "/"); + free(dname); + + dname = c_dirname("."); + assert_string_equal(dname, "."); + free(dname); + + dname = c_dirname(".."); + assert_string_equal(dname, "."); + free(dname); + + dname = c_dirname(NULL); + assert_string_equal(dname, "."); + free(dname); +} + +static void check_c_dirname_uri(void **state) +{ + char *dname; + + (void) state; /* unused */ + + dname = c_dirname("smb://server/share/dir"); + assert_string_equal(dname, "smb://server/share"); + free(dname); +} + +static void check_c_parse_uri(void **state) +{ + const char *test_scheme = "git+ssh"; + const char *test_user = "gladiac"; + const char *test_passwd = "secret"; + const char *test_host = "git.csync.org"; + const char *test_path = "/srv/git/csync.git"; + + char *scheme = NULL; + char *user = NULL; + char *passwd = NULL; + char *host = NULL; + unsigned int port; + char *path = NULL; + char uri[1024] = {0}; + int rc; + + (void) state; /* unused */ + + rc = snprintf(uri, sizeof(uri), "%s://%s:%s@%s:22%s", + test_scheme, test_user, test_passwd, test_host, test_path); + assert_true(rc); + + rc = c_parse_uri(uri, &scheme, &user, &passwd, &host, &port, &path); + assert_int_equal(rc, 0); + + assert_string_equal(test_scheme, scheme); + assert_string_equal(test_user, user); + assert_string_equal(test_passwd, passwd); + assert_string_equal(test_host, host); + assert_int_equal(port, 22); + assert_string_equal(test_path, path); + + free(scheme); + free(user); + free(passwd); + free(host); + free(path); +} + +int torture_run_tests(void) +{ + const UnitTest tests[] = { + unit_test(check_c_basename), + unit_test(check_c_basename_uri), + unit_test(check_c_dirname), + unit_test(check_c_dirname_uri), + unit_test(check_c_parse_uri), + }; + + return run_tests(tests); +} + diff --git a/test/csync/std_tests/check_std_c_rbtree.c b/test/csync/std_tests/check_std_c_rbtree.c new file mode 100644 index 000000000..735096541 --- /dev/null +++ b/test/csync/std_tests/check_std_c_rbtree.c @@ -0,0 +1,363 @@ +/* + * libcsync -- a library to sync a directory with another + * + * Copyright (c) 2008-2013 by Andreas Schneider <asn@cryptomilk.org> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ +#include <errno.h> +#include <time.h> + +#include "torture.h" + +#include "std/c_alloc.h" +#include "std/c_rbtree.h" + +typedef struct test_s { + int key; + int number; +} test_t; + +static int data_cmp(const void *key, const void *data) { + test_t *a, *b; + + a = (test_t *) key; + b = (test_t *) data; + + if (a->key < b->key) { + return -1; + } else if (a->key > b->key) { + return 1; + } + + return 0; +} + +static int key_cmp(const void *key, const void *data) { + int a; + test_t *b; + + a = POINTER_TO_INT(key); + b = (test_t *) data; + + if (a < b->key) { + return -1; + } else if (a > b->key) { + return 1; + } + + return 0; +} + +static int visitor(void *obj, void *data) { + test_t *a; + test_t *b; + + a = (test_t *) obj; + b = (test_t *) data; + + if (a->key == b->key) { + a->number = 42; + } + + return 0; +} + +static void destructor(void *data) { + test_t *freedata = NULL; + + freedata = (test_t *) data; + SAFE_FREE(freedata); +} + +static void setup(void **state) { + c_rbtree_t *tree = NULL; + + c_rbtree_create(&tree, key_cmp, data_cmp); + + *state = tree; +} + +static void setup_complete_tree(void **state) { + c_rbtree_t *tree = NULL; + int i = 0; + int rc; + + c_rbtree_create(&tree, key_cmp, data_cmp); + + for (i = 0; i < 100; i++) { + test_t *testdata = NULL; + + testdata = c_malloc(sizeof(test_t)); + assert_non_null(testdata); + + testdata->key = i; + + rc = c_rbtree_insert(tree, (void *) testdata); + assert_int_equal(rc, 0); + } + + *state = tree; +} + +static void teardown(void **state) { + c_rbtree_t *tree = *state; + + c_rbtree_destroy(tree, destructor); + c_rbtree_free(tree); + + *state = NULL; +} + +static void check_c_rbtree_create_free(void **state) +{ + c_rbtree_t *tree = NULL; + int rc; + + (void) state; /* unused */ + + c_rbtree_create(&tree, key_cmp, data_cmp); + assert_int_equal(tree->size, 0); + + rc = c_rbtree_free(tree); + assert_int_equal(rc, 0); +} + +static void check_c_rbtree_free_null(void **state) +{ + int rc; + + (void) state; /* unused */ + + rc = c_rbtree_free(NULL); + assert_int_equal(rc, -1); +} + +static void check_c_rbtree_insert_delete(void **state) +{ + c_rbtree_t *tree = NULL; + c_rbnode_t *node = NULL; + test_t *testdata = NULL; + int rc; + + (void) state; /* unused */ + + c_rbtree_create(&tree, key_cmp, data_cmp); + + testdata = malloc(sizeof(test_t)); + testdata->key = 42; + + rc = c_rbtree_insert(tree, (void *) testdata); + assert_int_equal(rc, 0); + + node = c_rbtree_head(tree); + assert_non_null(node); + + testdata = c_rbtree_node_data(node); + SAFE_FREE(testdata); + rc = c_rbtree_node_delete(node); + assert_int_equal(rc, 0); + + c_rbtree_free(tree); +} + +static void check_c_rbtree_insert_random(void **state) +{ + c_rbtree_t *tree = *state; + int i = 0, rc; + + for (i = 0; i < 100; i++) { + test_t *testdata = NULL; + + testdata = malloc(sizeof(test_t)); + assert_non_null(testdata); + + testdata->key = i; + + rc = c_rbtree_insert(tree, testdata); + assert_int_equal(rc, 0); + + } + rc = c_rbtree_check_sanity(tree); + assert_int_equal(rc, 0); +} + +static void check_c_rbtree_insert_duplicate(void **state) +{ + c_rbtree_t *tree = *state; + test_t *testdata; + int rc; + + testdata = malloc(sizeof(test_t)); + assert_non_null(testdata); + + testdata->key = 42; + + rc = c_rbtree_insert(tree, (void *) testdata); + assert_int_equal(rc, 0); + + /* add again */ + testdata = malloc(sizeof(test_t)); + assert_non_null(testdata); + + testdata->key = 42; + + /* check for duplicate */ + rc = c_rbtree_insert(tree, (void *) testdata); + assert_int_equal(rc, 1); + + free(testdata); +} + +static void check_c_rbtree_find(void **state) +{ + c_rbtree_t *tree = *state; + int rc, i = 42; + c_rbnode_t *node; + test_t *testdata; + + rc = c_rbtree_check_sanity(tree); + assert_int_equal(rc, 0); + + /* find the node with the key 42 */ + node = c_rbtree_find(tree, (void *) &i); + assert_non_null(node); + + testdata = (test_t *) c_rbtree_node_data(node); + assert_int_equal(testdata->key, 42); +} + +static void check_c_rbtree_delete(void **state) +{ + c_rbtree_t *tree = *state; + int rc, i = 42; + c_rbnode_t *node = NULL; + test_t *freedata = NULL; + + rc = c_rbtree_check_sanity(tree); + assert_int_equal(rc, 0); + + node = c_rbtree_find(tree, (void *) &i); + assert_non_null(node); + + freedata = (test_t *) c_rbtree_node_data(node); + free(freedata); + rc = c_rbtree_node_delete(node); + assert_int_equal(rc, 0); + + rc = c_rbtree_check_sanity(tree); + assert_int_equal(rc, 0); +} + +static void check_c_rbtree_walk(void **state) +{ + c_rbtree_t *tree = *state; + int rc, i = 42; + test_t *testdata; + c_rbnode_t *node; + + rc = c_rbtree_check_sanity(tree); + assert_int_equal(rc, 0); + + testdata = (test_t *) c_malloc(sizeof(test_t)); + testdata->key = 42; + + rc = c_rbtree_walk(tree, testdata, visitor); + assert_int_equal(rc, 0); + + /* find the node with the key 42 */ + node = c_rbtree_find(tree, (void *) &i); + assert_non_null(node); + free(testdata); + + testdata = (test_t *) c_rbtree_node_data(node); + assert_int_equal(testdata->number, 42); +} + +static void check_c_rbtree_walk_null(void **state) +{ + c_rbtree_t *tree = *state; + int rc, i = 42; + test_t *testdata; + c_rbnode_t *node; + + rc = c_rbtree_check_sanity(tree); + assert_int_equal(rc, 0); + + testdata = (test_t *) malloc(sizeof(test_t)); + testdata->key = 42; + + rc = c_rbtree_walk(NULL, testdata, visitor); + assert_int_equal(rc, -1); + assert_int_equal(errno, EINVAL); + + rc = c_rbtree_walk(tree, NULL, visitor); + assert_int_equal(rc, -1); + assert_int_equal(errno, EINVAL); + + rc = c_rbtree_walk(tree, testdata, NULL); + assert_int_equal(rc, -1); + assert_int_equal(errno, EINVAL); + + /* find the node with the key 42 */ + node = c_rbtree_find(tree, (void *) &i); + assert_non_null(node); + + free(testdata); +} + +static void check_c_rbtree_dup(void **state) +{ + c_rbtree_t *tree = *state; + c_rbtree_t *duptree = NULL; + int rc = -1; + + duptree = c_rbtree_dup(tree); + assert_non_null(duptree); + + rc = c_rbtree_check_sanity(duptree); + assert_int_equal(rc, 0); + + c_rbtree_free(duptree); +} + +#if 0 +static void check_c_rbtree_x) +{ + int rc = -1; + + rc = c_rbtree_check_sanity(tree); + fail_unless(rc == 0, "c_rbtree_check_sanity failed with return code %d", rc); +} +#endif + +int torture_run_tests(void) +{ + const UnitTest tests[] = { + unit_test(check_c_rbtree_create_free), + unit_test(check_c_rbtree_free_null), + unit_test(check_c_rbtree_insert_delete), + unit_test_setup_teardown(check_c_rbtree_insert_random, setup, teardown), + unit_test_setup_teardown(check_c_rbtree_insert_duplicate, setup, teardown), + unit_test_setup_teardown(check_c_rbtree_find, setup_complete_tree, teardown), + unit_test_setup_teardown(check_c_rbtree_delete, setup_complete_tree, teardown), + unit_test_setup_teardown(check_c_rbtree_walk, setup_complete_tree, teardown), + unit_test_setup_teardown(check_c_rbtree_walk_null, setup_complete_tree, teardown), + unit_test_setup_teardown(check_c_rbtree_dup, setup_complete_tree, teardown), + }; + + return run_tests(tests); +} + diff --git a/test/csync/std_tests/check_std_c_str.c b/test/csync/std_tests/check_std_c_str.c new file mode 100644 index 000000000..08cb1aac7 --- /dev/null +++ b/test/csync/std_tests/check_std_c_str.c @@ -0,0 +1,131 @@ +/* + * libcsync -- a library to sync a directory with another + * + * Copyright (c) 2008-2013 by Andreas Schneider <asn@cryptomilk.org> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ +#include <errno.h> +#include <stdlib.h> +#include <string.h> +#include <stdio.h> + +#include "torture.h" + +#include "std/c_string.h" + +static void check_c_streq_equal(void **state) +{ + (void) state; /* unused */ + + assert_true(c_streq("test", "test")); +} + +static void check_c_streq_not_equal(void **state) +{ + (void) state; /* unused */ + + assert_false(c_streq("test", "test2")); +} + +static void check_c_streq_null(void **state) +{ + (void) state; /* unused */ + + assert_false(c_streq(NULL, "test")); + assert_false(c_streq("test", NULL)); + assert_false(c_streq(NULL, NULL)); +} + +static void check_c_strlist_new(void **state) +{ + c_strlist_t *strlist = NULL; + + (void) state; /* unused */ + + strlist = c_strlist_new(42); + assert_non_null(strlist); + assert_int_equal(strlist->size, 42); + assert_int_equal(strlist->count, 0); + + c_strlist_destroy(strlist); +} + +static void check_c_strlist_add(void **state) +{ + int rc; + size_t i = 0; + c_strlist_t *strlist = NULL; + + (void) state; /* unused */ + + strlist = c_strlist_new(42); + assert_non_null(strlist); + assert_int_equal(strlist->size, 42); + assert_int_equal(strlist->count, 0); + + for (i = 0; i < strlist->size; i++) { + rc = c_strlist_add(strlist, (char *) "foobar"); + assert_int_equal(rc, 0); + } + + assert_int_equal(strlist->count, 42); + assert_string_equal(strlist->vector[0], "foobar"); + assert_string_equal(strlist->vector[41], "foobar"); + + c_strlist_destroy(strlist); +} + +static void check_c_strlist_expand(void **state) +{ + c_strlist_t *strlist; + size_t i = 0; + int rc; + + (void) state; /* unused */ + + strlist = c_strlist_new(42); + assert_non_null(strlist); + assert_int_equal(strlist->size, 42); + assert_int_equal(strlist->count, 0); + + strlist = c_strlist_expand(strlist, 84); + assert_non_null(strlist); + assert_int_equal(strlist->size, 84); + + for (i = 0; i < strlist->size; i++) { + rc = c_strlist_add(strlist, (char *) "foobar"); + assert_int_equal(rc, 0); + } + + c_strlist_destroy(strlist); +} + + + +int torture_run_tests(void) +{ + const UnitTest tests[] = { + unit_test(check_c_streq_equal), + unit_test(check_c_streq_not_equal), + unit_test(check_c_streq_null), + unit_test(check_c_strlist_new), + unit_test(check_c_strlist_add), + unit_test(check_c_strlist_expand), + }; + + return run_tests(tests); +} + diff --git a/test/csync/std_tests/check_std_c_time.c b/test/csync/std_tests/check_std_c_time.c new file mode 100644 index 000000000..df1abbe05 --- /dev/null +++ b/test/csync/std_tests/check_std_c_time.c @@ -0,0 +1,100 @@ +/* + * libcsync -- a library to sync a directory with another + * + * Copyright (c) 2008-2013 by Andreas Schneider <asn@cryptomilk.org> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ +#include <string.h> + +#include "torture.h" + +#include "csync_time.h" +#include "std/c_time.h" + +static void check_c_tspecdiff(void **state) +{ + struct timespec start, finish, diff; + + (void) state; /* unused */ + + csync_gettime(&start); + csync_gettime(&finish); + + diff = c_tspecdiff(finish, start); + + assert_int_equal(diff.tv_sec, 0); + assert_true(diff.tv_nsec >= 0); +} + +static void check_c_tspecdiff_five(void **state) +{ + struct timespec start, finish, diff; + + (void) state; /* unused */ + + csync_gettime(&start); + sleep(5); + csync_gettime(&finish); + + diff = c_tspecdiff(finish, start); + + assert_int_equal(diff.tv_sec, 5); + assert_true(diff.tv_nsec > 0); +} + +static void check_c_secdiff(void **state) +{ + struct timespec start, finish; + double diff; + + (void) state; /* unused */ + + csync_gettime(&start); + csync_gettime(&finish); + + diff = c_secdiff(finish, start); + + assert_true(diff >= 0.00 && diff < 1.00); +} + +static void check_c_secdiff_three(void **state) +{ + struct timespec start, finish; + double diff; + + (void) state; /* unused */ + + csync_gettime(&start); + sleep(3); + csync_gettime(&finish); + + diff = c_secdiff(finish, start); + + assert_true(diff > 3.00 && diff < 4.00); +} + +int torture_run_tests(void) +{ + const UnitTest tests[] = { + unit_test(check_c_tspecdiff), + unit_test(check_c_tspecdiff_five), + unit_test(check_c_secdiff), + unit_test(check_c_secdiff_three), + }; + + return run_tests(tests); +} + diff --git a/test/csync/torture.c b/test/csync/torture.c new file mode 100644 index 000000000..403fafb9f --- /dev/null +++ b/test/csync/torture.c @@ -0,0 +1,41 @@ +/* + * libcsync -- a library to sync a directory with another + * + * Copyright (c) 2008-2013 by Andreas Schneider <asn@cryptomilk.org> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ +#include "config_csync.h" + +#include "torture.h" + +static int verbosity; + +int torture_csync_verbosity(void) +{ + return verbosity; +} + +int main(int argc, char **argv) +{ + struct argument_s arguments; + + arguments.verbose = 0; + torture_cmdline_parse(argc, argv, &arguments); + verbosity = arguments.verbose; + + return torture_run_tests(); +} + diff --git a/test/csync/torture.h b/test/csync/torture.h new file mode 100644 index 000000000..b3272b8c1 --- /dev/null +++ b/test/csync/torture.h @@ -0,0 +1,44 @@ +/* + * libcsync -- a library to sync a directory with another + * + * Copyright (c) 2008-2013 by Andreas Schneider <asn@cryptomilk.org> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ +#ifndef _TORTURE_H +#define _TORTURE_H + +#include <stdarg.h> +#include <stddef.h> +#include <setjmp.h> + +#include <cmocka.h> + +/* Used by main to communicate with parse_opt. */ +struct argument_s { + char *args[2]; + int verbose; +}; + +void torture_cmdline_parse(int argc, char **argv, struct argument_s *arguments); + +int torture_csync_verbosity(void); + +/* + * This function must be defined in every unit test file. + */ +int torture_run_tests(void); + +#endif /* _TORTURE_H */ diff --git a/test/csync/valgrind-csync.supp b/test/csync/valgrind-csync.supp new file mode 100644 index 000000000..c4d10e40c --- /dev/null +++ b/test/csync/valgrind-csync.supp @@ -0,0 +1,61 @@ +### SQLITE3 + +{ + Invalid read of size 4 in sqlite3 + Memcheck:Addr4 + obj:/usr/lib*/libsqlite3.so* + fun:sqlite3_close + fun:csync_statedb_close +} + +{ + sqlite3 jump on uninit value + Memcheck:Cond + obj:/usr/lib*/libsqlite3.so* + fun:sqlite3_vmprintf + fun:sqlite3_mprintf +} + +{ + sqlite3 uninit value + Memcheck:Value8 + obj:/usr/lib*/libsqlite3.so* + fun:sqlite3_vmprintf + fun:sqlite3_mprintf +} + +### GLIBC + +{ + glibc dlopen leak + Memcheck:Leak + fun:calloc + obj:/lib*/libdl-2.*.so + fun:dlopen +} + +{ + glibc dlopen leak + Memcheck:Leak + fun:calloc + fun:_dlerror_run + fun:dlopen@@GLIBC_2.2.5 + fun:csync_vio_init +} + +{ + glibc dlerror leak + Memcheck:Leak + fun:realloc + fun:vasprintf + fun:asprintf + fun:dlerror +} + +{ + glibc fnmatch invalid read + Memcheck:Addr1 + fun:__GI_strlen + fun:fnmatch@@GLIBC_* + fun:csync_fnmatch +} diff --git a/test/csync/vio_tests/check_vio.c b/test/csync/vio_tests/check_vio.c new file mode 100644 index 000000000..6d4afd7ef --- /dev/null +++ b/test/csync/vio_tests/check_vio.c @@ -0,0 +1,167 @@ +/* + * libcsync -- a library to sync a directory with another + * + * Copyright (c) 2008-2013 by Andreas Schneider <asn@cryptomilk.org> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <string.h> +#include <errno.h> + +#include "torture.h" + +#include "csync_private.h" +#include "vio/csync_vio.h" + +#define CSYNC_TEST_DIR "/tmp/csync_test/" +#define CSYNC_TEST_DIRS "/tmp/csync_test/this/is/a/mkdirs/test" +#define CSYNC_TEST_FILE "/tmp/csync_test/file.txt" + +#define MKDIR_MASK (S_IRWXU |S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH) + +#define WD_BUFFER_SIZE 255 + +static char wd_buffer[WD_BUFFER_SIZE]; + +static void setup(void **state) +{ + CSYNC *csync; + int rc; + + assert_non_null(getcwd(wd_buffer, WD_BUFFER_SIZE)); + + rc = system("rm -rf /tmp/csync_test"); + assert_int_equal(rc, 0); + + csync_create(&csync, "/tmp/csync1"); + + csync->replica = LOCAL_REPLICA; + + *state = csync; +} + +static void setup_dir(void **state) { + int rc; + mbchar_t *dir = c_utf8_path_to_locale(CSYNC_TEST_DIR); + + setup(state); + + rc = _tmkdir(dir, MKDIR_MASK); + c_free_locale_string(dir); + assert_int_equal(rc, 0); + + assert_non_null(getcwd(wd_buffer, WD_BUFFER_SIZE)); + + rc = chdir(CSYNC_TEST_DIR); + assert_int_equal(rc, 0); +} + +static void teardown(void **state) { + CSYNC *csync = *state; + int rc; + + rc = csync_destroy(csync); + assert_int_equal(rc, 0); + + rc = chdir(wd_buffer); + assert_int_equal(rc, 0); + + rc = system("rm -rf /tmp/csync_test/"); + assert_int_equal(rc, 0); + + *state = NULL; +} + + +/* + * Test directory function + */ + +static void check_csync_vio_opendir(void **state) +{ + CSYNC *csync = *state; + csync_vio_handle_t *dh; + int rc; + + dh = csync_vio_opendir(csync, CSYNC_TEST_DIR); + assert_non_null(dh); + + rc = csync_vio_closedir(csync, dh); + assert_int_equal(rc, 0); +} + +static void check_csync_vio_opendir_perm(void **state) +{ + CSYNC *csync = *state; + csync_vio_handle_t *dh; + int rc; + mbchar_t *dir = c_utf8_path_to_locale(CSYNC_TEST_DIR); + + assert_non_null(dir); + + rc = _tmkdir(dir, (S_IWUSR|S_IXUSR)); + assert_int_equal(rc, 0); + + dh = csync_vio_opendir(csync, CSYNC_TEST_DIR); + assert_null(dh); + assert_int_equal(errno, EACCES); + + _tchmod(dir, MKDIR_MASK); + c_free_locale_string(dir); +} + +static void check_csync_vio_closedir_null(void **state) +{ + CSYNC *csync = *state; + int rc; + + rc = csync_vio_closedir(csync, NULL); + assert_int_equal(rc, -1); +} + +static void check_csync_vio_readdir(void **state) +{ + CSYNC *csync = *state; + csync_vio_handle_t *dh; + csync_vio_file_stat_t *dirent; + int rc; + + dh = csync_vio_opendir(csync, CSYNC_TEST_DIR); + assert_non_null(dh); + + dirent = csync_vio_readdir(csync, dh); + assert_non_null(dirent); + + csync_vio_file_stat_destroy(dirent); + rc = csync_vio_closedir(csync, dh); + assert_int_equal(rc, 0); +} + + +int torture_run_tests(void) +{ + const UnitTest tests[] = { + unit_test_setup_teardown(check_csync_vio_opendir, setup_dir, teardown), + unit_test_setup_teardown(check_csync_vio_opendir_perm, setup, teardown), + unit_test(check_csync_vio_closedir_null), + unit_test_setup_teardown(check_csync_vio_readdir, setup_dir, teardown), + }; + + return run_tests(tests); +} + diff --git a/test/csync/vio_tests/check_vio_ext.c b/test/csync/vio_tests/check_vio_ext.c new file mode 100644 index 000000000..c34e708c0 --- /dev/null +++ b/test/csync/vio_tests/check_vio_ext.c @@ -0,0 +1,464 @@ +/* + * libcsync -- a library to sync a directory with another + * + * Copyright (c) 2015-2013 by Klaas Freitag <freitag@owncloud.com> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <string.h> +#include <errno.h> +#include <stdio.h> + +#include "torture.h" + +#include "csync_private.h" +#include "vio/csync_vio.h" + +#ifdef _WIN32 +#include <windows.h> + +#define CSYNC_TEST_DIR "C:/tmp/csync_test" +#else +#define CSYNC_TEST_DIR "/tmp/csync_test" +#endif +#define MKDIR_MASK (S_IRWXU |S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH) + +#define WD_BUFFER_SIZE 255 + +static mbchar_t wd_buffer[WD_BUFFER_SIZE]; + +typedef struct { + CSYNC *csync; + char *result; + char *ignored_dir; +} statevar; + +/* remove the complete test dir */ +static int wipe_testdir() +{ + int rc = 0; + +#ifdef _WIN32 + /* The windows system call to rd bails out if the dir is not existing + * Check first. + */ + WIN32_FIND_DATA FindFileData; + + mbchar_t *dir = c_utf8_path_to_locale(CSYNC_TEST_DIR); + HANDLE handle = FindFirstFile(dir, &FindFileData); + c_free_locale_string(dir); + int found = handle != INVALID_HANDLE_VALUE; + + if(found) { + FindClose(handle); + rc = system("rd /s /q C:\\tmp\\csync_test"); + } +#else + rc = system("rm -rf /tmp/csync_test/"); +#endif + return rc; +} + +static void setup_testenv(void **state) { + int rc; + + rc = wipe_testdir(); + assert_int_equal(rc, 0); + + mbchar_t *dir = c_utf8_path_to_locale(CSYNC_TEST_DIR); + + rc = _tmkdir(dir, MKDIR_MASK); + assert_int_equal(rc, 0); + + assert_non_null(_tgetcwd(wd_buffer, WD_BUFFER_SIZE)); + + rc = _tchdir(dir); + assert_int_equal(rc, 0); + + c_free_locale_string(dir); + + /* --- initialize csync */ + statevar *mystate = malloc( sizeof(statevar) ); + mystate->result = NULL; + + csync_create(&(mystate->csync), "/tmp/csync1"); + + mystate->csync->replica = LOCAL_REPLICA; + + *state = mystate; +} + +static void output( const char *text ) +{ + mbchar_t *wtext = c_utf8_string_to_locale(text); + + #ifdef _WIN32 + wprintf(L"OOOO %ls (%ld)\n", wtext, strlen(text)); + #else + printf("%s\n", wtext); + #endif + c_free_locale_string(wtext); +} + +static void teardown(void **state) { + statevar *sv = (statevar*) *state; + CSYNC *csync = sv->csync; + int rc; + + output("================== Tearing down!\n"); + + rc = csync_destroy(csync); + assert_int_equal(rc, 0); + + rc = _tchdir(wd_buffer); + assert_int_equal(rc, 0); + + rc = wipe_testdir(); + assert_int_equal(rc, 0); + + *state = NULL; +} + +/* This function takes a relative path, prepends it with the CSYNC_TEST_DIR + * and creates each sub directory. + */ +static void create_dirs( const char *path ) +{ + int rc; + char *mypath = c_malloc( 2+strlen(CSYNC_TEST_DIR)+strlen(path)); + *mypath = '\0'; + strcat(mypath, CSYNC_TEST_DIR); + strcat(mypath, "/"); + strcat(mypath, path); + + char *p = mypath+strlen(CSYNC_TEST_DIR)+1; /* start behind the offset */ + int i = 0; + + assert_non_null(path); + + while( *(p+i) ) { + if( *(p+i) == '/' ) { + p[i] = '\0'; + + mbchar_t *mb_dir = c_utf8_path_to_locale(mypath); + /* wprintf(L"OOOO %ls (%ld)\n", mb_dir, strlen(mypath)); */ + rc = _tmkdir(mb_dir, MKDIR_MASK); + c_free_locale_string(mb_dir); + + assert_int_equal(rc, 0); + p[i] = '/'; + } + i++; + } + SAFE_FREE(mypath); +} + +/* + * This function uses the vio_opendir, vio_readdir and vio_closedir functions + * to traverse a file tree that was created before by the create_dir function. + * + * It appends a listing to the result member of the incoming struct in *state + * that can be compared later to what was expected in the calling functions. + * + * The int parameter cnt contains the number of seen files (not dirs) in the + * whole tree. + * + */ +static void traverse_dir(void **state, const char *dir, int *cnt) +{ + csync_vio_handle_t *dh; + csync_vio_file_stat_t *dirent; + statevar *sv = (statevar*) *state; + CSYNC *csync = sv->csync; + char *subdir; + char *subdir_out; + int rc; + int is_dir; + + /* Format: Smuggle in the C: for unix platforms as its urgently needed + * on Windows and the test can be nicely cross platform this way. */ +#ifdef _WIN32 + const char *format_str = "%s %s"; +#else + const char *format_str = "%s C:%s"; +#endif + + dh = csync_vio_opendir(csync, dir); + assert_non_null(dh); + + while( (dirent = csync_vio_readdir(csync, dh)) ) { + assert_non_null(dirent); + if (dirent->original_name) { + sv->ignored_dir = c_strdup(dirent->original_name); + continue; + } + + assert_non_null(dirent->name); + assert_int_equal( dirent->fields & CSYNC_VIO_FILE_STAT_FIELDS_TYPE, CSYNC_VIO_FILE_STAT_FIELDS_TYPE ); + + if( c_streq( dirent->name, "..") || c_streq( dirent->name, "." )) { + continue; + } + + is_dir = (dirent->type == CSYNC_VIO_FILE_TYPE_DIRECTORY) ? 1:0; + + assert_int_not_equal( asprintf( &subdir, "%s/%s", dir, dirent->name ), -1 ); + + assert_int_not_equal( asprintf( &subdir_out, format_str, + is_dir ? "<DIR>":" ", + subdir), -1 ); + + if( is_dir ) { + if( !sv->result ) { + sv->result = c_strdup( subdir_out); + } else { + int newlen = 1+strlen(sv->result)+strlen(subdir_out); + char *tmp = sv->result; + sv->result = c_malloc(newlen); + strcpy( sv->result, tmp); + SAFE_FREE(tmp); + + strcat( sv->result, subdir_out ); + } + } else { + *cnt = *cnt +1; + } + output(subdir_out); + if( is_dir ) { + traverse_dir( state, subdir, cnt); + } + + SAFE_FREE(subdir); + SAFE_FREE(subdir_out); + } + + csync_vio_file_stat_destroy(dirent); + rc = csync_vio_closedir(csync, dh); + assert_int_equal(rc, 0); + +} + +static void create_file( const char *path, const char *name, const char *content) +{ +#ifdef _WIN32 + + char *filepath = c_malloc( 2+strlen(CSYNC_TEST_DIR)+strlen(path) + strlen(name) ); + *filepath = '\0'; + strcpy(filepath, CSYNC_TEST_DIR); + strcat(filepath, "/"); + strcat(filepath, path); + strcat(filepath, name); + + DWORD dwWritten; // number of bytes written to file + HANDLE hFile; + + mbchar_t *w_fname = c_utf8_path_to_locale(filepath); + + hFile=CreateFile(w_fname, GENERIC_READ|GENERIC_WRITE, FILE_SHARE_READ|FILE_SHARE_WRITE, 0, + CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0); + + assert_int_equal( 0, hFile==INVALID_HANDLE_VALUE ); + + int len = strlen(content); + mbchar_t *dst = NULL; + + dst = c_utf8_string_to_locale(content); + WriteFile(hFile, dst, len * sizeof(mbchar_t), &dwWritten, 0); + + CloseHandle(hFile); + SAFE_FREE(dst); + c_free_locale_string(w_fname); +#else + char *filepath = c_malloc( 1+strlen(path) + strlen(name) ); + *filepath = '\0'; + + strcpy(filepath, path); + strcat(filepath, name); + + FILE *sink; + sink = fopen(filepath,"w"); + + fprintf (sink, "we got: %s",content); + fclose(sink); + SAFE_FREE(filepath); +#endif + +} + +static void check_readdir_shorttree(void **state) +{ + statevar *sv = (statevar*) *state; + + const char *t1 = "alibaba/und/die/vierzig/räuber/"; + create_dirs( t1 ); + int files_cnt = 0; + + traverse_dir(state, CSYNC_TEST_DIR, &files_cnt); + + assert_string_equal( sv->result, + "<DIR> C:/tmp/csync_test/alibaba" + "<DIR> C:/tmp/csync_test/alibaba/und" + "<DIR> C:/tmp/csync_test/alibaba/und/die" + "<DIR> C:/tmp/csync_test/alibaba/und/die/vierzig" + "<DIR> C:/tmp/csync_test/alibaba/und/die/vierzig/räuber" ); + assert_int_equal(files_cnt, 0); +} + +static void check_readdir_with_content(void **state) +{ + statevar *sv = (statevar*) *state; + int files_cnt = 0; + + const char *t1 = "warum/nur/40/Räuber/"; + create_dirs( t1 ); + + create_file( t1, "Räuber Max.txt", "Der Max ist ein schlimmer finger"); + create_file( t1, "пя́тница.txt", "Am Freitag tanzt der Ürk"); + + + traverse_dir(state, CSYNC_TEST_DIR, &files_cnt); + + assert_string_equal( sv->result, + "<DIR> C:/tmp/csync_test/warum" + "<DIR> C:/tmp/csync_test/warum/nur" + "<DIR> C:/tmp/csync_test/warum/nur/40" + "<DIR> C:/tmp/csync_test/warum/nur/40/Räuber"); + /* " C:/tmp/csync_test/warum/nur/40/Räuber/Räuber Max.txt" + " C:/tmp/csync_test/warum/nur/40/Räuber/пя́тница.txt"); */ + assert_int_equal(files_cnt, 2); /* Two files in the sub dir */ +} + +static void check_readdir_longtree(void **state) +{ + statevar *sv = (statevar*) *state; + + /* Strange things here: Compilers only support strings with length of 4k max. + * The expected result string is longer, so it needs to be split up in r1, r2 and r3 + */ + + /* create the test tree */ + const char *t1 = "vierzig/mann/auf/des/toten/Mann/kiste/ooooooooooooooooooooooh/and/ne/bottle/voll/rum/und/so/singen/wir/VIERZIG/MANN/AUF/DES/TOTEN/MANNS/KISTE/OOOOOOOOH/AND/NE/BOTTLE/VOLL/RUM/undnochmalallezusammen/VierZig/MannaufDesTotenManns/KISTE/ooooooooooooooooooooooooooohhhhhh/und/BESSER/ZWEI/Butteln/VOLL RUM/"; + create_dirs( t1 ); + + const char *r1 = +"<DIR> C:/tmp/csync_test/vierzig" +"<DIR> C:/tmp/csync_test/vierzig/mann" +"<DIR> C:/tmp/csync_test/vierzig/mann/auf" +"<DIR> C:/tmp/csync_test/vierzig/mann/auf/des" +"<DIR> C:/tmp/csync_test/vierzig/mann/auf/des/toten" +"<DIR> C:/tmp/csync_test/vierzig/mann/auf/des/toten/Mann" +"<DIR> C:/tmp/csync_test/vierzig/mann/auf/des/toten/Mann/kiste" +"<DIR> C:/tmp/csync_test/vierzig/mann/auf/des/toten/Mann/kiste/ooooooooooooooooooooooh" +"<DIR> C:/tmp/csync_test/vierzig/mann/auf/des/toten/Mann/kiste/ooooooooooooooooooooooh/and" +"<DIR> C:/tmp/csync_test/vierzig/mann/auf/des/toten/Mann/kiste/ooooooooooooooooooooooh/and/ne" +"<DIR> C:/tmp/csync_test/vierzig/mann/auf/des/toten/Mann/kiste/ooooooooooooooooooooooh/and/ne/bottle" +"<DIR> C:/tmp/csync_test/vierzig/mann/auf/des/toten/Mann/kiste/ooooooooooooooooooooooh/and/ne/bottle/voll" +"<DIR> C:/tmp/csync_test/vierzig/mann/auf/des/toten/Mann/kiste/ooooooooooooooooooooooh/and/ne/bottle/voll/rum"; + + + const char *r2 = +"<DIR> C:/tmp/csync_test/vierzig/mann/auf/des/toten/Mann/kiste/ooooooooooooooooooooooh/and/ne/bottle/voll/rum/und" +"<DIR> C:/tmp/csync_test/vierzig/mann/auf/des/toten/Mann/kiste/ooooooooooooooooooooooh/and/ne/bottle/voll/rum/und/so" +"<DIR> C:/tmp/csync_test/vierzig/mann/auf/des/toten/Mann/kiste/ooooooooooooooooooooooh/and/ne/bottle/voll/rum/und/so/singen" +"<DIR> C:/tmp/csync_test/vierzig/mann/auf/des/toten/Mann/kiste/ooooooooooooooooooooooh/and/ne/bottle/voll/rum/und/so/singen/wir" +"<DIR> C:/tmp/csync_test/vierzig/mann/auf/des/toten/Mann/kiste/ooooooooooooooooooooooh/and/ne/bottle/voll/rum/und/so/singen/wir/VIERZIG" +"<DIR> C:/tmp/csync_test/vierzig/mann/auf/des/toten/Mann/kiste/ooooooooooooooooooooooh/and/ne/bottle/voll/rum/und/so/singen/wir/VIERZIG/MANN" +"<DIR> C:/tmp/csync_test/vierzig/mann/auf/des/toten/Mann/kiste/ooooooooooooooooooooooh/and/ne/bottle/voll/rum/und/so/singen/wir/VIERZIG/MANN/AUF" +"<DIR> C:/tmp/csync_test/vierzig/mann/auf/des/toten/Mann/kiste/ooooooooooooooooooooooh/and/ne/bottle/voll/rum/und/so/singen/wir/VIERZIG/MANN/AUF/DES" +"<DIR> C:/tmp/csync_test/vierzig/mann/auf/des/toten/Mann/kiste/ooooooooooooooooooooooh/and/ne/bottle/voll/rum/und/so/singen/wir/VIERZIG/MANN/AUF/DES/TOTEN" +"<DIR> C:/tmp/csync_test/vierzig/mann/auf/des/toten/Mann/kiste/ooooooooooooooooooooooh/and/ne/bottle/voll/rum/und/so/singen/wir/VIERZIG/MANN/AUF/DES/TOTEN/MANNS" +"<DIR> C:/tmp/csync_test/vierzig/mann/auf/des/toten/Mann/kiste/ooooooooooooooooooooooh/and/ne/bottle/voll/rum/und/so/singen/wir/VIERZIG/MANN/AUF/DES/TOTEN/MANNS/KISTE" +"<DIR> C:/tmp/csync_test/vierzig/mann/auf/des/toten/Mann/kiste/ooooooooooooooooooooooh/and/ne/bottle/voll/rum/und/so/singen/wir/VIERZIG/MANN/AUF/DES/TOTEN/MANNS/KISTE/OOOOOOOOH"; + + + const char *r3 = +"<DIR> C:/tmp/csync_test/vierzig/mann/auf/des/toten/Mann/kiste/ooooooooooooooooooooooh/and/ne/bottle/voll/rum/und/so/singen/wir/VIERZIG/MANN/AUF/DES/TOTEN/MANNS/KISTE/OOOOOOOOH/AND" +"<DIR> C:/tmp/csync_test/vierzig/mann/auf/des/toten/Mann/kiste/ooooooooooooooooooooooh/and/ne/bottle/voll/rum/und/so/singen/wir/VIERZIG/MANN/AUF/DES/TOTEN/MANNS/KISTE/OOOOOOOOH/AND/NE" +"<DIR> C:/tmp/csync_test/vierzig/mann/auf/des/toten/Mann/kiste/ooooooooooooooooooooooh/and/ne/bottle/voll/rum/und/so/singen/wir/VIERZIG/MANN/AUF/DES/TOTEN/MANNS/KISTE/OOOOOOOOH/AND/NE/BOTTLE" +"<DIR> C:/tmp/csync_test/vierzig/mann/auf/des/toten/Mann/kiste/ooooooooooooooooooooooh/and/ne/bottle/voll/rum/und/so/singen/wir/VIERZIG/MANN/AUF/DES/TOTEN/MANNS/KISTE/OOOOOOOOH/AND/NE/BOTTLE/VOLL" +"<DIR> C:/tmp/csync_test/vierzig/mann/auf/des/toten/Mann/kiste/ooooooooooooooooooooooh/and/ne/bottle/voll/rum/und/so/singen/wir/VIERZIG/MANN/AUF/DES/TOTEN/MANNS/KISTE/OOOOOOOOH/AND/NE/BOTTLE/VOLL/RUM" +"<DIR> C:/tmp/csync_test/vierzig/mann/auf/des/toten/Mann/kiste/ooooooooooooooooooooooh/and/ne/bottle/voll/rum/und/so/singen/wir/VIERZIG/MANN/AUF/DES/TOTEN/MANNS/KISTE/OOOOOOOOH/AND/NE/BOTTLE/VOLL/RUM/undnochmalallezusammen" +"<DIR> C:/tmp/csync_test/vierzig/mann/auf/des/toten/Mann/kiste/ooooooooooooooooooooooh/and/ne/bottle/voll/rum/und/so/singen/wir/VIERZIG/MANN/AUF/DES/TOTEN/MANNS/KISTE/OOOOOOOOH/AND/NE/BOTTLE/VOLL/RUM/undnochmalallezusammen/VierZig" +"<DIR> C:/tmp/csync_test/vierzig/mann/auf/des/toten/Mann/kiste/ooooooooooooooooooooooh/and/ne/bottle/voll/rum/und/so/singen/wir/VIERZIG/MANN/AUF/DES/TOTEN/MANNS/KISTE/OOOOOOOOH/AND/NE/BOTTLE/VOLL/RUM/undnochmalallezusammen/VierZig/MannaufDesTotenManns" +"<DIR> C:/tmp/csync_test/vierzig/mann/auf/des/toten/Mann/kiste/ooooooooooooooooooooooh/and/ne/bottle/voll/rum/und/so/singen/wir/VIERZIG/MANN/AUF/DES/TOTEN/MANNS/KISTE/OOOOOOOOH/AND/NE/BOTTLE/VOLL/RUM/undnochmalallezusammen/VierZig/MannaufDesTotenManns/KISTE" +"<DIR> C:/tmp/csync_test/vierzig/mann/auf/des/toten/Mann/kiste/ooooooooooooooooooooooh/and/ne/bottle/voll/rum/und/so/singen/wir/VIERZIG/MANN/AUF/DES/TOTEN/MANNS/KISTE/OOOOOOOOH/AND/NE/BOTTLE/VOLL/RUM/undnochmalallezusammen/VierZig/MannaufDesTotenManns/KISTE/ooooooooooooooooooooooooooohhhhhh" +"<DIR> C:/tmp/csync_test/vierzig/mann/auf/des/toten/Mann/kiste/ooooooooooooooooooooooh/and/ne/bottle/voll/rum/und/so/singen/wir/VIERZIG/MANN/AUF/DES/TOTEN/MANNS/KISTE/OOOOOOOOH/AND/NE/BOTTLE/VOLL/RUM/undnochmalallezusammen/VierZig/MannaufDesTotenManns/KISTE/ooooooooooooooooooooooooooohhhhhh/und" +"<DIR> C:/tmp/csync_test/vierzig/mann/auf/des/toten/Mann/kiste/ooooooooooooooooooooooh/and/ne/bottle/voll/rum/und/so/singen/wir/VIERZIG/MANN/AUF/DES/TOTEN/MANNS/KISTE/OOOOOOOOH/AND/NE/BOTTLE/VOLL/RUM/undnochmalallezusammen/VierZig/MannaufDesTotenManns/KISTE/ooooooooooooooooooooooooooohhhhhh/und/BESSER" +"<DIR> C:/tmp/csync_test/vierzig/mann/auf/des/toten/Mann/kiste/ooooooooooooooooooooooh/and/ne/bottle/voll/rum/und/so/singen/wir/VIERZIG/MANN/AUF/DES/TOTEN/MANNS/KISTE/OOOOOOOOH/AND/NE/BOTTLE/VOLL/RUM/undnochmalallezusammen/VierZig/MannaufDesTotenManns/KISTE/ooooooooooooooooooooooooooohhhhhh/und/BESSER/ZWEI" +"<DIR> C:/tmp/csync_test/vierzig/mann/auf/des/toten/Mann/kiste/ooooooooooooooooooooooh/and/ne/bottle/voll/rum/und/so/singen/wir/VIERZIG/MANN/AUF/DES/TOTEN/MANNS/KISTE/OOOOOOOOH/AND/NE/BOTTLE/VOLL/RUM/undnochmalallezusammen/VierZig/MannaufDesTotenManns/KISTE/ooooooooooooooooooooooooooohhhhhh/und/BESSER/ZWEI/Butteln" +"<DIR> C:/tmp/csync_test/vierzig/mann/auf/des/toten/Mann/kiste/ooooooooooooooooooooooh/and/ne/bottle/voll/rum/und/so/singen/wir/VIERZIG/MANN/AUF/DES/TOTEN/MANNS/KISTE/OOOOOOOOH/AND/NE/BOTTLE/VOLL/RUM/undnochmalallezusammen/VierZig/MannaufDesTotenManns/KISTE/ooooooooooooooooooooooooooohhhhhh/und/BESSER/ZWEI/Butteln/VOLL RUM"; + + /* assemble the result string ... */ + int overall_len = 1+strlen(r1)+strlen(r2)+strlen(r3); + int files_cnt = 0; + char *result = c_malloc(overall_len); + *result = '\0'; + + strcat(result, r1); + strcat(result, r2); + strcat(result, r3); + + traverse_dir(state, CSYNC_TEST_DIR, &files_cnt); + assert_int_equal(files_cnt, 0); + /* and compare. */ + assert_string_equal( sv->result, result); +} + +// https://github.com/owncloud/client/issues/3128 https://github.com/owncloud/client/issues/2777 +static void check_readdir_bigunicode(void **state) +{ + statevar *sv = (statevar*) *state; +// 1: ? ASCII: 239 - EF +// 2: ? ASCII: 187 - BB +// 3: ? ASCII: 191 - BF +// 4: ASCII: 32 - 20 + + char *p = 0; + asprintf( &p, "%s/%s", CSYNC_TEST_DIR, "goodone/" ); + int rc = _tmkdir(p, MKDIR_MASK); + assert_int_equal(rc, 0); + SAFE_FREE(p); + + const char *t1 = "goodone/ugly\xEF\xBB\xBF\x32" ".txt"; // file with encoding error + asprintf( &p, "%s/%s", CSYNC_TEST_DIR, t1 ); + rc = _tmkdir(p, MKDIR_MASK); + SAFE_FREE(p); + + assert_int_equal(rc, 0); + + int files_cnt = 0; + traverse_dir(state, CSYNC_TEST_DIR, &files_cnt); + const char *expected_result = "<DIR> C:/tmp/csync_test/goodone" + "<DIR> C:/tmp/csync_test/goodone/ugly\xEF\xBB\xBF\x32" ".txt" + ; + assert_string_equal( sv->result, expected_result); + + assert_int_equal(files_cnt, 0); +} + +int torture_run_tests(void) +{ + const UnitTest tests[] = { + unit_test_setup_teardown(check_readdir_shorttree, setup_testenv, teardown), + unit_test_setup_teardown(check_readdir_with_content, setup_testenv, teardown), + unit_test_setup_teardown(check_readdir_longtree, setup_testenv, teardown), + unit_test_setup_teardown(check_readdir_bigunicode, setup_testenv, teardown), + }; + + return run_tests(tests); +} diff --git a/test/csync/vio_tests/check_vio_file_stat.c b/test/csync/vio_tests/check_vio_file_stat.c new file mode 100644 index 000000000..a67255e81 --- /dev/null +++ b/test/csync/vio_tests/check_vio_file_stat.c @@ -0,0 +1,45 @@ +/* + * libcsync -- a library to sync a directory with another + * + * Copyright (c) 2008-2013 by Andreas Schneider <asn@cryptomilk.org> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ +#include "torture.h" + +#include "csync.h" + +static void check_csync_vio_file_stat_new(void **state) +{ + csync_vio_file_stat_t *tstat; + + (void) state; /* unused */ + + tstat = csync_vio_file_stat_new(); + assert_non_null(tstat); + + csync_vio_file_stat_destroy(tstat); +} + + +int torture_run_tests(void) +{ + const UnitTest tests[] = { + unit_test(check_csync_vio_file_stat_new), + }; + + return run_tests(tests); +} + |