diff --git a/CMakeLists.txt b/CMakeLists.txt index 128d2671b..5363a7a6c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -99,6 +99,7 @@ option(ENABLE_TRIGGER "Enable Trigger plugin" ON) option(ENABLE_XFER "Enable Xfer plugin" ON) option(ENABLE_MAN "Enable build of man page" OFF) option(ENABLE_DOC "Enable build of documentation" OFF) +option(ENABLE_TESTS "Enable tests" OFF) # option WEECHAT_HOME if(NOT DEFINED WEECHAT_HOME OR "${WEECHAT_HOME}" STREQUAL "") @@ -204,6 +205,11 @@ endif() add_subdirectory( src ) add_subdirectory( doc ) +if(ENABLE_TESTS) + enable_testing() + add_subdirectory( tests ) +endif() + configure_file(config.h.cmake config.h @ONLY) # set the git version in "config-git.h" diff --git a/cmake/FindCppUTest.cmake b/cmake/FindCppUTest.cmake new file mode 100644 index 000000000..bf0b027f6 --- /dev/null +++ b/cmake/FindCppUTest.cmake @@ -0,0 +1,37 @@ +# +# Copyright (C) 2014 Sébastien Helleu +# +# This file is part of WeeChat, the extensible chat client. +# +# WeeChat is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. +# +# WeeChat is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with WeeChat. If not, see . +# + +# - Find CppUTest +# This module finds if Guile is installed and determines where the include files +# and libraries are. It also determines what the name of the library is. This +# code sets the following variables: +# +# CPPUTEST_FOUND = CppUTest is installed +# CPPUTEST_INCLUDE_DIRS = CppUTest include directory +# CPPUTEST_LIBRARIES = Link options to compile with CppUTest + +if(CPPUTEST_FOUND) + # Already in cache, be silent + set(CPPUTEST_FIND_QUIETLY TRUE) +endif() + +find_package(PkgConfig) +if(PKG_CONFIG_FOUND) + pkg_search_module(CPPUTEST REQUIRED cpputest) +endif() diff --git a/doc/de/weechat_user.de.asciidoc b/doc/de/weechat_user.de.asciidoc index 399f53b37..8761feb38 100644 --- a/doc/de/weechat_user.de.asciidoc +++ b/doc/de/weechat_user.de.asciidoc @@ -103,6 +103,8 @@ welche Pakete optional genutzt werden können. | source-highlight | | | Syntax Highlight für Quelltext in Dokumentation | xsltproc, docbook-xml, docbook-xsl | | | Erstellt man page +// TRANSLATION MISSING +| libcpputest-dev | | | Run tests |=== [NOTE] @@ -240,6 +242,10 @@ Liste von häufig verwendeten Optionen: | ENABLE_XFER | `ON`, `OFF` | ON | kompiliert <>. + +// TRANSLATION MISSING +| ENABLE_TESTS | `ON`, `OFF` | OFF | + Compile tests. |=== Weitere Optionen können mit folgendem Befehl angezeigt werden: diff --git a/doc/en/weechat_dev.en.asciidoc b/doc/en/weechat_dev.en.asciidoc index eb150b2ee..29ae8593f 100644 --- a/doc/en/weechat_dev.en.asciidoc +++ b/doc/en/weechat_dev.en.asciidoc @@ -68,6 +68,9 @@ The main WeeChat directories are: | guile/ | Guile (scheme) scripting API | trigger/ | Trigger plugin | xfer/ | Xfer plugin (IRC DCC file/chat) +| tests/ | Tests +| unit/ | Unit tests +| core/ | Unit tests for core functions | doc/ | Documentation | po/ | Translations files (gettext) | test/ | Tools/files to test WeeChat (like Weercd, an IRC server) @@ -281,6 +284,25 @@ WeeChat "core" is located in following directories: | xfer-upgrade.c | Save/restore of xfer data when upgrading WeeChat |=== +[[sources_tests]] +==== Tests + +[width="100%",cols="1v,5",options="header"] +|=== +| Path/file | Description +| tests/ | Root of tests +| unit/ | Root of unit tests +| test-eval.cpp | Tests: evaluation of expressions +| test-hashtble.cpp | Tests: hashtables +| test-hdata.cpp | Tests: hdata +| test-infolist.cpp | Tests: infolists +| test-list.cpp | Tests: lists +| test-string.cpp | Tests: strings +| test-url.cpp | Tests: URLs +| test-utf8.cpp | Tests: UTF-8 +| test-util.cpp | Tests: util functions +|=== + [[documentation_translations]] === Documentation / translations diff --git a/doc/en/weechat_user.en.asciidoc b/doc/en/weechat_user.en.asciidoc index 32f7d857a..35bcf188d 100644 --- a/doc/en/weechat_user.en.asciidoc +++ b/doc/en/weechat_user.en.asciidoc @@ -102,6 +102,7 @@ compile WeeChat. | source-highlight | | | Syntax highlight for sources in documentation | xsltproc, docbook-xml, docbook-xsl | | | Build of man page +| libcpputest-dev | | | Run tests |=== [NOTE] @@ -239,6 +240,9 @@ List of commonly used options: | ENABLE_XFER | `ON`, `OFF` | ON | Compile <>. + +| ENABLE_TESTS | `ON`, `OFF` | OFF | + Compile tests. |=== The other options can be displayed with this command: diff --git a/doc/fr/weechat_dev.fr.asciidoc b/doc/fr/weechat_dev.fr.asciidoc index 5a9269115..d95652176 100644 --- a/doc/fr/weechat_dev.fr.asciidoc +++ b/doc/fr/weechat_dev.fr.asciidoc @@ -69,6 +69,9 @@ Les répertoires principaux de WeeChat sont : | guile/ | API script Guile (scheme) | trigger/ | Extension Trigger | xfer/ | Extension Xfer (IRC DCC fichier/discussion) +| tests/ | Tests +| unit/ | Tests unitaires +| core/ | Tests unitaires pour les fonctions du cœur | doc/ | Documentation | po/ | Fichiers de traductions (gettext) | test/ | Outils/fichiers pour tester WeeChat (comme Weercd, un serveur IRC) @@ -282,6 +285,25 @@ Le cœur de WeeChat est situé dans les répertoires suivants : | xfer-upgrade.c | Sauvegarde/restauration des données Xfer lors de la mise à jour de WeeChat |=== +[[sources_tests]] +==== Tests + +[width="100%",cols="1v,5",options="header"] +|=== +| Chemin/fichier | Description +| tests/ | Racine des tests +| unit/ | Racine des tests unitaires +| test-eval.cpp | Tests : évaluation d'expressions +| test-hashtble.cpp | Tests : tables de hachage +| test-hdata.cpp | Tests : hdata +| test-infolist.cpp | Tests : infolists +| test-list.cpp | Tests : listes +| test-string.cpp | Tests : chaînes +| test-url.cpp | Tests : URLs +| test-utf8.cpp | Tests : UTF-8 +| test-util.cpp | Tests : fonctions utiles +|=== + [[documentation_translations]] === Documentation / traductions diff --git a/doc/fr/weechat_user.fr.asciidoc b/doc/fr/weechat_user.fr.asciidoc index 7365a31bf..0580659f7 100644 --- a/doc/fr/weechat_user.fr.asciidoc +++ b/doc/fr/weechat_user.fr.asciidoc @@ -104,6 +104,7 @@ compiler WeeChat. | source-highlight | | | Coloration des sources dans la documentation | xsltproc, docbook-xml, docbook-xsl | | | Construction de la page de manuel +| libcpputest-dev | | | Run tests |=== [NOTE] @@ -241,6 +242,9 @@ Liste des options couramment utilisées : | ENABLE_XFER | `ON`, `OFF` | ON | Compiler <>. + +| ENABLE_TESTS | `ON`, `OFF` | OFF | + Compiler les tests. |=== Les autres options peuvent être affichées avec cette commande : diff --git a/doc/it/weechat_user.it.asciidoc b/doc/it/weechat_user.it.asciidoc index 2dbbbf08f..978b699c9 100644 --- a/doc/it/weechat_user.it.asciidoc +++ b/doc/it/weechat_user.it.asciidoc @@ -112,6 +112,8 @@ compilare WeeChat. // TRANSLATION MISSING | xsltproc, docbook-xml, docbook-xsl | | | Build of man page +// TRANSLATION MISSING +| libcpputest-dev | | | Run tests |=== [NOTE] @@ -252,6 +254,10 @@ List of commonly used options: | ENABLE_XFER | `ON`, `OFF` | ON | Compile <>. + +// TRANSLATION MISSING +| ENABLE_TESTS | `ON`, `OFF` | OFF | + Compile tests. |=== The other options can be displayed with this command: diff --git a/doc/ja/weechat_dev.ja.asciidoc b/doc/ja/weechat_dev.ja.asciidoc index 329c42e8e..a43fde0cc 100644 --- a/doc/ja/weechat_dev.ja.asciidoc +++ b/doc/ja/weechat_dev.ja.asciidoc @@ -68,6 +68,12 @@ WeeChat の主要なリポジトリは 2 つあります: | guile/ | guile (scheme) スクリプト用 API | trigger/ | trigger プラグイン | xfer/ | xfer (IRC DCC ファイル/チャット) +// TRANSLATION MISSING +| tests/ | Tests +// TRANSLATION MISSING +| unit/ | Unit tests +// TRANSLATION MISSING +| core/ | Unit tests for core functions | doc/ | 文書 | po/ | 翻訳ファイル (gettext) | test/ | WeeChat をテストするためのツールおよびファイル (Weercd IRC サーバなど) @@ -281,6 +287,27 @@ WeeChat "core" は以下のディレクトリに配置されています: | xfer-upgrade.c | WeeChat をアップグレードする際の xfer データの保存および回復 |=== +// TRANSLATION MISSING +[[sources_tests]] +==== Tests + +// TRANSLATION MISSING +[width="100%",cols="1v,5",options="header"] +|=== +| パス/ファイル名 | 説明 +| tests/ | Root of tests +| unit/ | Root of unit tests +| test-eval.cpp | Tests: evaluation of expressions +| test-hashtble.cpp | Tests: hashtables +| test-hdata.cpp | Tests: hdata +| test-infolist.cpp | Tests: infolists +| test-list.cpp | Tests: lists +| test-string.cpp | Tests: strings +| test-url.cpp | Tests: URLs +| test-utf8.cpp | Tests: UTF-8 +| test-util.cpp | Tests: util functions +|=== + [[documentation_translations]] === 文書 / 翻訳 diff --git a/doc/ja/weechat_user.ja.asciidoc b/doc/ja/weechat_user.ja.asciidoc index 5f2a1b09d..c757ef7c8 100644 --- a/doc/ja/weechat_user.ja.asciidoc +++ b/doc/ja/weechat_user.ja.asciidoc @@ -102,6 +102,8 @@ WeeChat は cmake または autotools を使ってコンパイルできます (c | source-highlight | | | 文書中のソースに対するシンタックスハイライト | xsltproc, docbook-xml, docbook-xsl | | | man ページのビルド +// TRANSLATION MISSING +| libcpputest-dev | | | Run tests |=== [NOTE] @@ -238,6 +240,10 @@ cmake に対するオプションを指定するには、以下のフォーマ | ENABLE_XFER | `ON`, `OFF` | ON | <>のコンパイル + +// TRANSLATION MISSING +| ENABLE_TESTS | `ON`, `OFF` | OFF | + Compile tests. |=== その他のオプションは以下のコマンドで確認してください: diff --git a/doc/pl/weechat_user.pl.asciidoc b/doc/pl/weechat_user.pl.asciidoc index e5dcecd50..c50a7825d 100644 --- a/doc/pl/weechat_user.pl.asciidoc +++ b/doc/pl/weechat_user.pl.asciidoc @@ -102,6 +102,8 @@ WeeChat. | source-highlight | | | Podświetlanie składni dla kodów źródłowych w dokumentacji | xsltproc, docbook-xml, docbook-xsl | | | Tworzenie strony man +// TRANSLATION MISSING +| libcpputest-dev | | | Run tests |=== [NOTE] @@ -239,6 +241,10 @@ Lista popularnych opcji: | ENABLE_XFER | `ON`, `OFF` | ON | Kompilacja <>. + +// TRANSLATION MISSING +| ENABLE_TESTS | `ON`, `OFF` | OFF | + Compile tests. |=== Pozostałe opcje można wyświetlić poleceniem: diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt new file mode 100644 index 000000000..0aa08d9ee --- /dev/null +++ b/tests/CMakeLists.txt @@ -0,0 +1,69 @@ +# +# Copyright (C) 2014 Sébastien Helleu +# +# This file is part of WeeChat, the extensible chat client. +# +# WeeChat is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. +# +# WeeChat is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with WeeChat. If not, see . +# + +enable_language(CXX) + +find_package(CppUTest REQUIRED) + +# fake ncurses lib (it does nothing) +set(LIB_WEECHAT_NCURSES_FAKE_SRC ncurses-fake.c) +add_library(weechat_ncurses_fake STATIC ${LIB_WEECHAT_NCURSES_FAKE_SRC}) + +remove_definitions(-DHAVE_CONFIG_H) +include_directories(${CPPUTEST_INCLUDE_DIRS}) +include_directories(${PROJECT_BINARY_DIR}) + +# unit tests +set(LIB_WEECHAT_UNIT_TESTS_SRC + unit/core/test-eval.cpp + unit/core/test-hashtable.cpp + unit/core/test-hdata.cpp + unit/core/test-infolist.cpp + unit/core/test-list.cpp + unit/core/test-string.cpp + unit/core/test-url.cpp + unit/core/test-utf8.cpp + unit/core/test-util.cpp +) +add_library(weechat_unit_tests STATIC ${LIB_WEECHAT_UNIT_TESTS_SRC}) + +# binary to run tests +set(WEECHAT_TESTS_SRC tests.cpp) +add_executable(tests ${WEECHAT_TESTS_SRC}) +set(LIBS + ${LIBS} + ${EXTRA_LIBS} + ${CPPUTEST_LIBRARIES} + ${PROJECT_BINARY_DIR}/src/core/libweechat_core.a + ${PROJECT_BINARY_DIR}/src/plugins/libweechat_plugins.a + ${PROJECT_BINARY_DIR}/src/gui/libweechat_gui_common.a + ${PROJECT_BINARY_DIR}/src/gui/curses/libweechat_gui_curses.a + ${CURL_LIBRARIES} + ${CMAKE_CURRENT_BINARY_DIR}/libweechat_ncurses_fake.a + ${CMAKE_CURRENT_BINARY_DIR}/libweechat_unit_tests.a) +target_link_libraries(tests ${LIBS}) +add_dependencies(tests + weechat_core weechat_plugins weechat_gui_common weechat_gui_curses + weechat_ncurses_fake + weechat_unit_tests) + +# test for cmake (ctest) +add_test(NAME unit + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} + COMMAND tests) diff --git a/tests/ncurses-fake.c b/tests/ncurses-fake.c new file mode 100644 index 000000000..dc444f02a --- /dev/null +++ b/tests/ncurses-fake.c @@ -0,0 +1,295 @@ +/* + * ncurses.c - fake ncurses lib used for tests + * + * Copyright (C) 2014 Sébastien Helleu + * + * This file is part of WeeChat, the extensible chat client. + * + * WeeChat is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * WeeChat is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with WeeChat. If not, see . + */ + +#define ERR (-1) +#define OK (0) + +struct _window +{ + int _cury, _curx; + int _maxy, _maxx; + int _begy, _begx; +}; +typedef struct _window WINDOW; + +typedef unsigned char bool; +typedef int attr_t; +typedef unsigned chtype; + +/* simulate 80x25 terminal */ +WINDOW stdscr = { 0, 0, 24, 79, 0, 0 }; +chtype acs_map[256]; + + +WINDOW +*initscr () +{ + return &stdscr; +} + +int +endwin () +{ + return OK; +} + +WINDOW +*newwin () +{ + return &stdscr; +} + +int +delwin () +{ + return OK; +} + +int +wmove (WINDOW *win, int y, int x) +{ + (void)win; + (void)y; + (void)x; + return OK; +} + +int +wattr_on (WINDOW *win, attr_t attrs, void *opts) +{ + (void) win; + (void) attrs; + (void) opts; + return OK; +} + +int +wattr_off (WINDOW *win, attr_t attrs, void *opts) +{ + (void) win; + (void) attrs; + (void) opts; + return OK; +} + +int +waddnstr(WINDOW *win, const char *str, int n) +{ + (void) win; + (void) str; + (void) n; + return OK; +} + +int +wclrtobot(WINDOW *win) +{ + (void) win; + return OK; +} + +int +wrefresh(WINDOW *win) +{ + (void) win; + return OK; +} + +int +wnoutrefresh(WINDOW *win) +{ + (void) win; + return OK; +} + +int +wclrtoeol(WINDOW *win) +{ + (void) win; + return OK; +} + +int +mvwprintw(WINDOW *win, int y, int x, const char *fmt, ...) +{ + (void) win; + (void) y; + (void) x; + (void) fmt; + return OK; +} + +int +init_pair(short pair, short f, short b) +{ + (void) pair; + (void) f; + (void) b; + return OK; +} + +int +has_colors() +{ + return 1; +} + +int +cbreak() +{ + return OK; +} + +int +start_color() +{ + return OK; +} + +int +noecho() +{ + return OK; +} + +int +wclear(WINDOW *win) +{ + (void) win; + return OK; +} + +int +wgetch(WINDOW *win) +{ + (void) win; + return OK; +} + +int +can_change_color() +{ + /* not supported in WeeChat anyway */ + return 0; +} + +int +curs_set(int visibility) +{ + (void) visibility; + return 1; /* 0 == invisible, 1 == normal, 2 == very visible */ +} + +int +nodelay(WINDOW *win, bool bf) +{ + (void) win; + (void) bf; + return OK; +} + +int +werase(WINDOW *win) +{ + (void) win; + return OK; +} + +int +wbkgdset(WINDOW *win, chtype ch) +{ + (void) win; + (void) ch; + return OK; +} + +void +wchgat(WINDOW *win, int n, attr_t attr, short color, const void *opts) +{ + (void) win; + (void) n; + (void) attr; + (void) color; + (void) opts; +} + +void +whline() +{ +} + +void +wvline() +{ +} + +void +raw() +{ +} + +void +wcolor_set() +{ +} + +void +cur_term() +{ +} + +void +use_default_colors() +{ +} + +void +resizeterm() +{ +} + +int +COLS() +{ + /* simulate 80x25 terminal */ + return 80; +} + +int +LINES() +{ + /* simulate 80x25 terminal */ + return 25; +} + +int +COLORS() +{ + /* simulate 256-color terminal */ + return 256; +} + +int +COLOR_PAIRS() +{ + /* simulate 256-color terminal */ + return 256; +} diff --git a/tests/tests.cpp b/tests/tests.cpp new file mode 100644 index 000000000..a0608a3fc --- /dev/null +++ b/tests/tests.cpp @@ -0,0 +1,150 @@ +/* + * tests.cpp - run WeeChat tests + * + * Copyright (C) 2014 Sébastien Helleu + * + * This file is part of WeeChat, the extensible chat client. + * + * WeeChat is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * WeeChat is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with WeeChat. If not, see . + */ + +#include +#include +#include +#include +#include +#include + +extern "C" +{ +#define HAVE_CONFIG_H +#include "../src/core/weechat.h" +#include "../src/core/wee-hook.h" +#include "../src/core/wee-input.h" +#include "../src/plugins/plugin.h" +#include "../src/gui/gui-main.h" +#include "../src/gui/gui-buffer.h" +#include "../src/gui/curses/gui-curses.h" +} + +#include "CppUTest/CommandLineTestRunner.h" + +/* import tests from libs */ +IMPORT_TEST_GROUP(Eval); +IMPORT_TEST_GROUP(Hashtable); +IMPORT_TEST_GROUP(Hdata); +IMPORT_TEST_GROUP(Infolist); +IMPORT_TEST_GROUP(List); +IMPORT_TEST_GROUP(String); +IMPORT_TEST_GROUP(Url); +IMPORT_TEST_GROUP(Utf8); +IMPORT_TEST_GROUP(Util); + + +/* + * Callback for any message displayed by WeeChat or a plugin. + */ + +int +test_print_cb (void *data, struct t_gui_buffer *buffer, + time_t date, int tags_count, + const char **tags, int displayed, + int highlight, const char *prefix, + const char *message) +{ + /* make C compiler happy */ + (void) data; + (void) buffer; + (void) date; + (void) tags_count; + (void) tags; + (void) displayed; + (void) highlight; + + printf ("%s%s%s\n", /* with color: "\33[34m%s%s%s\33[0m\n" */ + (prefix && prefix[0]) ? prefix : "", + (prefix && prefix[0]) ? " " : "", + (message && message[0]) ? message : ""); + + return WEECHAT_RC_OK; +} + +/* + * Initializes GUI for tests. + */ + +void +test_gui_init () +{ + /* + * Catch all messages to display them directly on stdout + * (Curses library is not used for tests). + */ + hook_print (NULL, /* plugin */ + NULL, /* buffer */ + NULL, /* tags */ + NULL, /* message */ + 1, /* strip colors */ + &test_print_cb, + NULL); + + /* + * Call the function "gui_main_init" from Curses sources (all Curses + * calls are made with the fake ncurses library). + */ + gui_main_init (); +} + +/* + * Runs tests in WeeChat environment. + */ + +int +main (int argc, char *argv[]) +{ + int rc; + const char *weechat_argv[] = { NULL, "--dir", NULL, NULL }; + + /* setup environment: default language, no specific timezone */ + setenv ("LANG", "C", 1); + setenv ("TZ", "", 1); + + /* command line arguments: " --dir ./tmp_weechat_test" */ + weechat_argv[0] = argv[0]; + weechat_argv[2] = "./tmp_weechat_test"; + + /* init WeeChat */ + weechat_init (3, (char **)weechat_argv, &test_gui_init); + + /* display WeeChat version */ + input_data (gui_buffer_search_main (), "/command core version"); + + /* run all tests */ + printf ("\n"); + printf (">>>>>>>>>> TESTS >>>>>>>>>>\n"); + rc = CommandLineTestRunner::RunAllTests (argc, argv); + printf ("<<<<<<<<<< TESTS <<<<<<<<<<\n"); + printf ("\n"); + + /* end WeeChat */ + weechat_end (&gui_main_end); + + /* display status */ + printf ("\n"); + printf ("\33[%d;1m*** %s ***\33[0m\n", + (rc == 0) ? 32 : 31, /* 32 = green (OK), 31 = red (error) */ + (rc == 0) ? "OK" : "ERROR"); + + return rc; +} diff --git a/tests/unit/core/test-eval.cpp b/tests/unit/core/test-eval.cpp new file mode 100644 index 000000000..131bd8959 --- /dev/null +++ b/tests/unit/core/test-eval.cpp @@ -0,0 +1,203 @@ +/* + * test-eval.cpp - test evaluation functions + * + * Copyright (C) 2014 Sébastien Helleu + * + * This file is part of WeeChat, the extensible chat client. + * + * WeeChat is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * WeeChat is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with WeeChat. If not, see . + */ + +#include "CppUTest/TestHarness.h" + +extern "C" +{ +#include +#include "../src/core/wee-eval.h" +#include "../src/core/wee-config.h" +#include "../src/core/wee-hashtable.h" +#include "../src/core/wee-version.h" +#include "../src/plugins/plugin.h" +} + +#define WEE_CHECK_EVAL(__result, __expr) \ + value = eval_expression (__expr, NULL, extra_vars, NULL); \ + STRCMP_EQUAL(__result, value); \ + free (value); +#define WEE_CHECK_EVAL_COND(__result, __expr) \ + value = eval_expression (__expr, NULL, extra_vars, options); \ + STRCMP_EQUAL(__result, value); \ + free (value); + +TEST_GROUP(Eval) +{ +}; + +/* + * Tests functions: + * eval_is_true + */ + +TEST(Eval, Boolean) +{ + /* false */ + LONGS_EQUAL(0, eval_is_true (NULL)); + LONGS_EQUAL(0, eval_is_true ("")); + LONGS_EQUAL(0, eval_is_true ("0")); + + /* true */ + LONGS_EQUAL(1, eval_is_true ("00")); + LONGS_EQUAL(1, eval_is_true ("1")); + LONGS_EQUAL(1, eval_is_true ("A")); + LONGS_EQUAL(1, eval_is_true ("abcdef")); +} + +/* + * Tests functions: + * eval_expression (condition) + */ + +TEST(Eval, EvalCondition) +{ + struct t_hashtable *extra_vars, *options; + char *value; + + extra_vars = hashtable_new (32, + WEECHAT_HASHTABLE_STRING, + WEECHAT_HASHTABLE_STRING, + NULL, NULL); + hashtable_set (extra_vars, "test", "value"); + CHECK(extra_vars); + + options = hashtable_new (32, + WEECHAT_HASHTABLE_STRING, + WEECHAT_HASHTABLE_STRING, + NULL, NULL); + hashtable_set (options, "type", "condition"); + CHECK(options); + + POINTERS_EQUAL(NULL, eval_expression (NULL, NULL, NULL, options)); + + /* conditions evaluated as false */ + WEE_CHECK_EVAL_COND("0", ""); + WEE_CHECK_EVAL_COND("0", "0"); + WEE_CHECK_EVAL_COND("0", "1 == 2"); + WEE_CHECK_EVAL_COND("0", "1 >= 2"); + WEE_CHECK_EVAL_COND("0", "2 <= 1"); + WEE_CHECK_EVAL_COND("0", "2 != 2"); + WEE_CHECK_EVAL_COND("0", "18 < 5"); + WEE_CHECK_EVAL_COND("0", "5 > 18"); + WEE_CHECK_EVAL_COND("0", "1 == 5 > 18"); + WEE_CHECK_EVAL_COND("0", "abc == def"); + WEE_CHECK_EVAL_COND("0", "()"); + WEE_CHECK_EVAL_COND("0", "(5 > 26)"); + WEE_CHECK_EVAL_COND("0", "((5 > 26))"); + WEE_CHECK_EVAL_COND("0", "(26 < 5)"); + WEE_CHECK_EVAL_COND("0", "abc > def"); + WEE_CHECK_EVAL_COND("0", "1 && 0"); + WEE_CHECK_EVAL_COND("0", "abc && 0"); + WEE_CHECK_EVAL_COND("0", "0 || 0"); + WEE_CHECK_EVAL_COND("0", "0 || 0 || 0"); + WEE_CHECK_EVAL_COND("0", "0 || 1 && 0"); + WEE_CHECK_EVAL_COND("0", "0 || (1 && 0)"); + WEE_CHECK_EVAL_COND("0", "0 || (0 || (1 && 0))"); + WEE_CHECK_EVAL_COND("0", "1 && (0 || 0)"); + WEE_CHECK_EVAL_COND("0", "(0 || 1) && 0"); + WEE_CHECK_EVAL_COND("0", "((0 || 1) && 1) && 0"); + WEE_CHECK_EVAL_COND("0", "abcd =~ (?-i)^ABC"); + WEE_CHECK_EVAL_COND("0", "abcd =~ \\(abcd\\)"); + WEE_CHECK_EVAL_COND("0", "(abcd) =~ \\(\\(abcd\\)\\)"); + WEE_CHECK_EVAL_COND("0", "${test} == test"); + WEE_CHECK_EVAL_COND("0", "${test2} == value2"); + WEE_CHECK_EVAL_COND("0", "${buffer.number} == 2"); + WEE_CHECK_EVAL_COND("0", "${window.buffer.number} == 2"); + + /* conditions evaluated as true */ + WEE_CHECK_EVAL_COND("1", "1"); + WEE_CHECK_EVAL_COND("1", "123"); + WEE_CHECK_EVAL_COND("1", "abc"); + WEE_CHECK_EVAL_COND("1", "2 == 2"); + WEE_CHECK_EVAL_COND("1", "2 >= 1"); + WEE_CHECK_EVAL_COND("1", "1 <= 2"); + WEE_CHECK_EVAL_COND("1", "1 != 2"); + WEE_CHECK_EVAL_COND("1", "18 > 5"); + WEE_CHECK_EVAL_COND("1", "5 < 18"); + WEE_CHECK_EVAL_COND("1", "1 == 18 > 5"); + WEE_CHECK_EVAL_COND("1", "abc == abc"); + WEE_CHECK_EVAL_COND("1", "(26 > 5)"); + WEE_CHECK_EVAL_COND("1", "((26 > 5))"); + WEE_CHECK_EVAL_COND("1", "(5 < 26)"); + WEE_CHECK_EVAL_COND("1", "def > abc"); + WEE_CHECK_EVAL_COND("1", "1 && 1"); + WEE_CHECK_EVAL_COND("1", "abc && 1"); + WEE_CHECK_EVAL_COND("1", "0 || 1"); + WEE_CHECK_EVAL_COND("1", "0 || 0 || 1"); + WEE_CHECK_EVAL_COND("1", "1 || 1 && 0"); + WEE_CHECK_EVAL_COND("1", "0 || (1 && 1)"); + WEE_CHECK_EVAL_COND("1", "0 || (0 || (1 && 1))"); + WEE_CHECK_EVAL_COND("1", "1 && (0 || 1)"); + WEE_CHECK_EVAL_COND("1", "(0 || 1) && 1"); + WEE_CHECK_EVAL_COND("1", "((0 || 1) && 1) && 1"); + WEE_CHECK_EVAL_COND("1", "abcd =~ ^ABC"); + WEE_CHECK_EVAL_COND("1", "abcd =~ (?-i)^abc"); + WEE_CHECK_EVAL_COND("1", "(abcd) =~ (abcd)"); + WEE_CHECK_EVAL_COND("1", "(abcd) =~ \\(abcd\\)"); + WEE_CHECK_EVAL_COND("1", "((abcd)) =~ \\(\\(abcd\\)\\)"); + WEE_CHECK_EVAL_COND("1", "${test} == value"); + WEE_CHECK_EVAL_COND("1", "${test2} =="); + WEE_CHECK_EVAL_COND("1", "${buffer.number} == 1"); + WEE_CHECK_EVAL_COND("1", "${window.buffer.number} == 1"); + + hashtable_free (extra_vars); + hashtable_free (options); +} + +/* + * Tests functions: + * eval_expression (expression) + */ + +TEST(Eval, EvalExpression) +{ + struct t_hashtable *extra_vars; + char *value, str_value[256]; + void *toto; + + extra_vars = hashtable_new (32, + WEECHAT_HASHTABLE_STRING, + WEECHAT_HASHTABLE_STRING, + NULL, NULL); + hashtable_set (extra_vars, "test", "value"); + CHECK(extra_vars); + + POINTERS_EQUAL(NULL, eval_expression (NULL, NULL, NULL, NULL)); + WEE_CHECK_EVAL("", ""); + WEE_CHECK_EVAL("a b c", "a b c"); + WEE_CHECK_EVAL("$", "$"); + WEE_CHECK_EVAL("", "${"); + WEE_CHECK_EVAL("}", "}"); + WEE_CHECK_EVAL("", "${}"); + WEE_CHECK_EVAL("", "${xyz}"); + WEE_CHECK_EVAL("\t", "${\\t}"); + WEE_CHECK_EVAL(version_get_version (), "${info:version}"); + WEE_CHECK_EVAL("1", "${buffer.number}"); + WEE_CHECK_EVAL("1", "${window.buffer.number}"); + WEE_CHECK_EVAL("core.weechat", "${buffer.full_name}"); + WEE_CHECK_EVAL("core.weechat", "${window.buffer.full_name}"); + snprintf (str_value, sizeof (str_value), + "%d", CONFIG_INTEGER(config_look_scroll_amount)); + WEE_CHECK_EVAL(str_value, "${weechat.look.scroll_amount}"); + + hashtable_free (extra_vars); +} diff --git a/tests/unit/core/test-hashtable.cpp b/tests/unit/core/test-hashtable.cpp new file mode 100644 index 000000000..a7c35fab0 --- /dev/null +++ b/tests/unit/core/test-hashtable.cpp @@ -0,0 +1,140 @@ +/* + * test-hashtable.cpp - test hashtable functions + * + * Copyright (C) 2014 Sébastien Helleu + * + * This file is part of WeeChat, the extensible chat client. + * + * WeeChat is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * WeeChat is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with WeeChat. If not, see . + */ + +#include "CppUTest/TestHarness.h" + +extern "C" +{ +#include "../src/core/wee-hashtable.h" +} + +TEST_GROUP(Hashtable) +{ +}; + +/* + * Tests functions: + * hashtable_hash_key_djb2 + */ + +TEST(Hashtable, HashDbj2) +{ + /* TODO: write tests */ +} + +/* + * Tests functions: + * hashtable_new + */ + +TEST(Hashtable, New) +{ + /* TODO: write tests */ +} + +/* + * Tests functions: + * hashtable_set_with_size + * hashtable_set + */ + +TEST(Hashtable, Set) +{ + /* TODO: write tests */ +} + +/* + * Tests functions: + * hashtable_get_item + * hashtable_get + * hashtable_has_key + */ + +TEST(Hashtable, Get) +{ + /* TODO: write tests */ +} + +/* + * Tests functions: + * hashtable_map + * hashtable_map_string + */ + +TEST(Hashtable, Map) +{ + /* TODO: write tests */ +} + +/* + * Tests functions: + * hashtable_dup + */ + +TEST(Hashtable, Dup) +{ + /* TODO: write tests */ +} + +/* + * Tests functions: + * hashtable_get_list_keys + * hashtable_get_integer + * hashtable_get_string + * hashtable_set_pointer + */ + +TEST(Hashtable, Properties) +{ + /* TODO: write tests */ +} + +/* + * Tests functions: + * hashtable_add_to_infolist + */ + +TEST(Hashtable, Infolist) +{ + /* TODO: write tests */ +} + +/* + * Tests functions: + * hashtable_remove + * hashtable_remove_all + * hashtable_free + */ + +TEST(Hashtable, Free) +{ + /* TODO: write tests */ +} + +/* + * Tests functions: + * hashtable_print_log + */ + +TEST(Hashtable, PrintLog) +{ + /* TODO: write tests */ +} diff --git a/tests/unit/core/test-hdata.cpp b/tests/unit/core/test-hdata.cpp new file mode 100644 index 000000000..31af084a0 --- /dev/null +++ b/tests/unit/core/test-hdata.cpp @@ -0,0 +1,118 @@ +/* + * test-hdata.cpp - test hdata functions + * + * Copyright (C) 2014 Sébastien Helleu + * + * This file is part of WeeChat, the extensible chat client. + * + * WeeChat is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * WeeChat is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with WeeChat. If not, see . + */ + +#include "CppUTest/TestHarness.h" + +extern "C" +{ +#include "../src/core/wee-hdata.h" +} + +TEST_GROUP(Hdata) +{ +}; + +/* + * Tests functions: + * hdata_new + * hdata_new_var + * hdata_new_list + */ + +TEST(Hdata, New) +{ + /* TODO: write tests */ +} + +/* + * Tests functions: + * hdata_get_var_offset + * hdata_get_var_type + * hdata_get_var_type_string + * hdata_get_var_array_size + * hdata_get_var_array_size_string + * hdata_get_var_hdata + * hdata_get_var + * hdata_get_var_at_offset + * hdata_get_list + */ + +TEST(Hdata, Get) +{ + /* TODO: write tests */ +} + +/* + * Tests functions: + * hdata_check_pointer + */ + +TEST(Hdata, Check) +{ + /* TODO: write tests */ +} + +/* + * Tests functions: + * hdata_move + * hdata_search + */ + +TEST(Hdata, Move) +{ + /* TODO: write tests */ +} + +/* + * Tests functions: + * hdata_char + * hdata_integer + * hdata_long + * hdata_string + * hdata_pointer + * hdata_time + */ + +TEST(Hdata, Read) +{ + /* TODO: write tests */ +} + +/* + * Tests functions: + * hdata_free_all_plugin + * hdata_free_all + */ + +TEST(Hdata, Free) +{ + /* TODO: write tests */ +} + +/* + * Tests functions: + * hdata_print_log + */ + +TEST(Hdata, PrintLog) +{ + /* TODO: write tests */ +} diff --git a/tests/unit/core/test-infolist.cpp b/tests/unit/core/test-infolist.cpp new file mode 100644 index 000000000..6b7a67c11 --- /dev/null +++ b/tests/unit/core/test-infolist.cpp @@ -0,0 +1,114 @@ +/* + * test-infolist.cpp - test infolist functions + * + * Copyright (C) 2014 Sébastien Helleu + * + * This file is part of WeeChat, the extensible chat client. + * + * WeeChat is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * WeeChat is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with WeeChat. If not, see . + */ + +#include "CppUTest/TestHarness.h" + +extern "C" +{ +#include "../src/core/wee-infolist.h" +} + +TEST_GROUP(Infolist) +{ +}; + +/* + * Tests functions: + * infolist_new + * infolist_new_item + * infolist_new_var_integer + * infolist_new_var_string + * infolist_new_var_pointer + * infolist_new_var_buffer + * infolist_new_var_time + */ + +TEST(Infolist, New) +{ + /* TODO: write tests */ +} + +/* + * Tests functions: + * infolist_valid + */ + +TEST(Infolist, Valid) +{ + /* TODO: write tests */ +} + +/* + * Tests functions: + * infolist_search_var + */ + +TEST(Infolist, Search) +{ + /* TODO: write tests */ +} + +/* + * Tests functions: + * infolist_next + * infolist_prev + * infolist_reset_item_cursor + */ + +TEST(Infolist, Move) +{ + /* TODO: write tests */ +} + +/* + * Tests functions: + * infolist_integer + * infolist_string + * infolist_pointer + * infolist_buffer + * infolist_time + */ + +TEST(Infolist, Get) +{ + /* TODO: write tests */ +} + +/* + * Tests functions: + * infolist_free + * infolist_free_all_plugin + */ + +TEST(Infolist, Free) +{ + /* TODO: write tests */ +} + +/* + * Tests functions: + * infolist_print_log + */ + +TEST(Infolist, PrintLog) +{ + /* TODO: write tests */ +} diff --git a/tests/unit/core/test-list.cpp b/tests/unit/core/test-list.cpp new file mode 100644 index 000000000..7e804c1f2 --- /dev/null +++ b/tests/unit/core/test-list.cpp @@ -0,0 +1,118 @@ +/* + * test-list.cpp - test list functions + * + * Copyright (C) 2014 Sébastien Helleu + * + * This file is part of WeeChat, the extensible chat client. + * + * WeeChat is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * WeeChat is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with WeeChat. If not, see . + */ + +#include "CppUTest/TestHarness.h" + +extern "C" +{ +#include "../src/core/wee-list.h" +} + +TEST_GROUP(List) +{ +}; + +/* + * Tests functions: + * weelist_new + */ + +TEST(List, New) +{ + /* TODO: write tests */ +} + +/* + * Tests functions: + * weelist_add + */ + +TEST(List, Add) +{ + /* TODO: write tests */ +} + +/* + * Tests functions: + * weelist_search + * weelist_search_pos + * weelist_casesearch + * weelist_casesearch_pos + */ + +TEST(List, Search) +{ + /* TODO: write tests */ +} + +/* + * Tests functions: + * weelist_get + * weelist_string + */ + +TEST(List, Get) +{ + /* TODO: write tests */ +} + +/* + * Tests functions: + * weelist_set + */ + +TEST(List, Set) +{ + /* TODO: write tests */ +} + +/* + * Tests functions: + * weelist_next + * weelist_prev + */ + +TEST(List, Move) +{ + /* TODO: write tests */ +} + +/* + * Tests functions: + * weelist_remove + * weelist_remove_all + * weelist_free + */ + +TEST(List, Free) +{ + /* TODO: write tests */ +} + +/* + * Tests functions: + * weelist_print_log + */ + +TEST(List, PrintLog) +{ + /* TODO: write tests */ +} diff --git a/tests/unit/core/test-string.cpp b/tests/unit/core/test-string.cpp new file mode 100644 index 000000000..f430d870d --- /dev/null +++ b/tests/unit/core/test-string.cpp @@ -0,0 +1,710 @@ +/* + * test-string.cpp - test string functions + * + * Copyright (C) 2014 Sébastien Helleu + * + * This file is part of WeeChat, the extensible chat client. + * + * WeeChat is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * WeeChat is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with WeeChat. If not, see . + */ + +#include "CppUTest/TestHarness.h" + +extern "C" +{ +#include +#include +#include +#include "../src/core/wee-string.h" +} + +#define WEE_HAS_HL_STR(__result, __str, __words) \ + LONGS_EQUAL(__result, string_has_highlight (__str, __words)); + +#define WEE_HAS_HL_REGEX(__result_regex, __result_hl, __str, __regex) \ + LONGS_EQUAL(__result_hl, \ + string_has_highlight_regex (__str, __regex)); \ + LONGS_EQUAL(__result_regex, \ + string_regcomp (®ex, __regex, REG_ICASE)); \ + if (__result_regex == 0) \ + { \ + LONGS_EQUAL(__result_hl, \ + string_has_highlight_regex_compiled (__str, \ + ®ex)); \ + regfree(®ex); \ + } \ + +#define WEE_HAS_HL_REGEX_COMP(__result, __str, __regex) \ + + +TEST_GROUP(String) +{ +}; + +/* + * Tests functions: + * string_strndup + */ + +TEST(String, Duplicate) +{ + const char *str_test = "test"; + char *str; + + str = string_strndup (NULL, 0); + + str = string_strndup (str_test, 0); + CHECK(str); + CHECK(str != str_test); + STRCMP_EQUAL(str, ""); + free (str); + + str = string_strndup (str_test, 2); + CHECK(str); + CHECK(str != str_test); + STRCMP_EQUAL(str, "te"); + free (str); + + str = string_strndup (str_test, 500); + CHECK(str); + CHECK(str != str_test); + STRCMP_EQUAL(str, str_test); + free (str); +} + +/* + * Tests functions: + * string_tolower + * string_toupper + */ + +TEST(String, Case) +{ + char *str; + + str = strdup ("ABC"); + + string_tolower (str); + STRCMP_EQUAL("abc", str); + string_toupper (str); + STRCMP_EQUAL("ABC", str); + + free (str); +} + +/* + * Tests functions: + * string_strcasecmp + * string_strncasecmp + * string_strcasecmp_range + * string_strncasecmp_range + * string_strcmp_ignore_chars + */ + +TEST(String, Comparison) +{ + /* case-insensitive comparison */ + LONGS_EQUAL(0, string_strcasecmp (NULL, NULL)); + LONGS_EQUAL(-1, string_strcasecmp (NULL, "abc")); + LONGS_EQUAL(1, string_strcasecmp ("abc", NULL)); + LONGS_EQUAL(0, string_strcasecmp ("abc", "abc")); + LONGS_EQUAL(0, string_strcasecmp ("abc", "ABC")); + LONGS_EQUAL(0, string_strcasecmp ("ABC", "ABC")); + LONGS_EQUAL(-1, string_strcasecmp ("abc", "def")); + LONGS_EQUAL(-1, string_strcasecmp ("abc", "DEF")); + LONGS_EQUAL(-1, string_strcasecmp ("ABC", "def")); + LONGS_EQUAL(-1, string_strcasecmp ("ABC", "DEF")); + LONGS_EQUAL(1, string_strcasecmp ("def", "abc")); + LONGS_EQUAL(1, string_strcasecmp ("def", "ABC")); + LONGS_EQUAL(1, string_strcasecmp ("DEF", "abc")); + LONGS_EQUAL(1, string_strcasecmp ("DEF", "ABC")); + + /* case-insensitive comparison with max length */ + LONGS_EQUAL(0, string_strncasecmp (NULL, NULL, 3)); + LONGS_EQUAL(-1, string_strncasecmp (NULL, "abc", 3)); + LONGS_EQUAL(1, string_strncasecmp ("abc", NULL, 3)); + LONGS_EQUAL(0, string_strncasecmp ("abc", "abc", 3)); + LONGS_EQUAL(0, string_strncasecmp ("abcabc", "abcdef", 3)); + LONGS_EQUAL(-1, string_strncasecmp ("abcabc", "abcdef", 6)); + LONGS_EQUAL(0, string_strncasecmp ("abc", "ABC", 3)); + LONGS_EQUAL(0, string_strncasecmp ("abcabc", "ABCDEF", 3)); + LONGS_EQUAL(-1, string_strncasecmp ("abcabc", "ABCDEF", 6)); + LONGS_EQUAL(0, string_strncasecmp ("ABC", "ABC", 3)); + LONGS_EQUAL(0, string_strncasecmp ("ABCABC", "ABCDEF", 3)); + LONGS_EQUAL(-1, string_strncasecmp ("ABCABC", "ABCDEF", 6)); + LONGS_EQUAL(-1, string_strncasecmp ("abc", "def", 3)); + LONGS_EQUAL(-1, string_strncasecmp ("abc", "DEF", 3)); + LONGS_EQUAL(-1, string_strncasecmp ("ABC", "def", 3)); + LONGS_EQUAL(-1, string_strncasecmp ("ABC", "DEF", 3)); + LONGS_EQUAL(1, string_strncasecmp ("def", "abc", 3)); + LONGS_EQUAL(1, string_strncasecmp ("def", "ABC", 3)); + LONGS_EQUAL(1, string_strncasecmp ("DEF", "abc", 3)); + LONGS_EQUAL(1, string_strncasecmp ("DEF", "ABC", 3)); + + /* case-insensitive comparison with a range */ + LONGS_EQUAL(0, string_strcasecmp_range (NULL, NULL, 30)); + LONGS_EQUAL(-1, string_strcasecmp_range (NULL, "abc", 30)); + LONGS_EQUAL(1, string_strcasecmp_range ("abc", NULL, 30)); + LONGS_EQUAL(-1, string_strcasecmp_range ("A", "Z", 30)); + LONGS_EQUAL(1, string_strcasecmp_range ("Z", "A", 30)); + LONGS_EQUAL(0, string_strcasecmp_range ("A", "a", 30)); + LONGS_EQUAL(-1, string_strcasecmp_range ("ë", "€", 30)); + LONGS_EQUAL(0, string_strcasecmp_range ("[", "{", 30)); + LONGS_EQUAL(0, string_strcasecmp_range ("]", "}", 30)); + LONGS_EQUAL(0, string_strcasecmp_range ("\\", "|", 30)); + LONGS_EQUAL(0, string_strcasecmp_range ("^", "~", 30)); + LONGS_EQUAL(-1, string_strcasecmp_range ("[", "{", 26)); + LONGS_EQUAL(-1, string_strcasecmp_range ("]", "}", 26)); + LONGS_EQUAL(-1, string_strcasecmp_range ("\\", "|", 26)); + LONGS_EQUAL(-1, string_strcasecmp_range ("^", "~", 26)); + + /* case-insensitive comparison with max length and a range */ + LONGS_EQUAL(0, string_strncasecmp_range (NULL, NULL, 3, 30)); + LONGS_EQUAL(-1, string_strncasecmp_range (NULL, "abc", 3, 30)); + LONGS_EQUAL(1, string_strncasecmp_range ("abc", NULL, 3, 30)); + LONGS_EQUAL(-1, string_strncasecmp_range ("ABC", "ZZZ", 3, 30)); + LONGS_EQUAL(1, string_strncasecmp_range ("ZZZ", "ABC", 3, 30)); + LONGS_EQUAL(0, string_strncasecmp_range ("ABC", "abc", 3, 30)); + LONGS_EQUAL(0, string_strncasecmp_range ("ABCABC", "abcdef", 3, 30)); + LONGS_EQUAL(-1, string_strncasecmp_range ("ABCABC", "abcdef", 6, 30)); + LONGS_EQUAL(-1, string_strncasecmp_range ("ëëë", "€€€", 3, 30)); + LONGS_EQUAL(0, string_strncasecmp_range ("[[[", "{{{", 3, 30)); + LONGS_EQUAL(0, string_strncasecmp_range ("[[[abc", "{{{def", 3, 30)); + LONGS_EQUAL(-1, string_strncasecmp_range ("[[[abc", "{{{def", 6, 30)); + LONGS_EQUAL(0, string_strncasecmp_range ("]]]", "}}}", 3, 30)); + LONGS_EQUAL(0, string_strncasecmp_range ("]]]abc", "}}}def", 3, 30)); + LONGS_EQUAL(-1, string_strncasecmp_range ("]]]abc", "}}}def", 6, 30)); + LONGS_EQUAL(0, string_strncasecmp_range ("\\\\\\", "|||", 3, 30)); + LONGS_EQUAL(0, string_strncasecmp_range ("\\\\\\abc", "|||def", 3, 30)); + LONGS_EQUAL(-1, string_strncasecmp_range ("\\\\\\abc", "|||def", 6, 30)); + LONGS_EQUAL(0, string_strncasecmp_range ("^^^", "~~~", 3, 30)); + LONGS_EQUAL(0, string_strncasecmp_range ("^^^abc", "~~~def", 3, 30)); + LONGS_EQUAL(-1, string_strncasecmp_range ("^^^abc", "~~~def", 6, 30)); + LONGS_EQUAL(-1, string_strncasecmp_range ("[[[", "{{{", 3, 26)); + LONGS_EQUAL(-1, string_strncasecmp_range ("]]]", "}}}", 3, 26)); + LONGS_EQUAL(-1, string_strncasecmp_range ("\\\\\\", "|||", 3, 26)); + LONGS_EQUAL(-1, string_strncasecmp_range ("^^^", "~~~", 3, 26)); + + /* comparison with chars ignored */ + LONGS_EQUAL(0, string_strcmp_ignore_chars (NULL, NULL, "", 0)); + LONGS_EQUAL(-1, string_strcmp_ignore_chars (NULL, "abc", "", 0)); + LONGS_EQUAL(1, string_strcmp_ignore_chars ("abc", NULL, "", 0)); + LONGS_EQUAL(-1, string_strcmp_ignore_chars ("ABC", "ZZZ", "", 0)); + LONGS_EQUAL(1, string_strcmp_ignore_chars ("ZZZ", "ABC", "", 0)); + LONGS_EQUAL(0, string_strcmp_ignore_chars ("ABC", "abc", "", 0)); + LONGS_EQUAL(-1, string_strcmp_ignore_chars ("ABC", "abc", "", 1)); + LONGS_EQUAL(0, string_strcmp_ignore_chars ("abc..abc", "abcabc", ".", 0)); + LONGS_EQUAL(1, string_strcmp_ignore_chars ("abc..abc", "ABCABC", ".", 1)); + LONGS_EQUAL(0, string_strcmp_ignore_chars ("abc..abc", "abc-.-.abc", + ".-", 0)); + LONGS_EQUAL(1, string_strcmp_ignore_chars ("abc..abc", "ABC-.-.ABC", + ".-", 1)); +} + +/* + * Tests functions: + * string_strcasestr + */ + +TEST(String, Search) +{ + const char *str = "test"; + + /* case-insensitive search of string in a string */ + POINTERS_EQUAL(NULL, string_strcasestr (NULL, NULL)); + POINTERS_EQUAL(NULL, string_strcasestr (NULL, str)); + POINTERS_EQUAL(NULL, string_strcasestr (str, NULL)); + POINTERS_EQUAL(NULL, string_strcasestr (str, "")); + POINTERS_EQUAL(NULL, string_strcasestr (str, "zz")); + POINTERS_EQUAL(str + 1, string_strcasestr (str, "est")); + POINTERS_EQUAL(str + 1, string_strcasestr (str, "EST")); +} + +/* + * Tests functions: + * string_match + */ + +TEST(String, Match) +{ + LONGS_EQUAL(0, string_match (NULL, NULL, 0)); + LONGS_EQUAL(0, string_match (NULL, "test", 0)); + LONGS_EQUAL(0, string_match ("test", NULL, 0)); + LONGS_EQUAL(0, string_match ("", "", 0)); + LONGS_EQUAL(0, string_match ("", "test", 0)); + LONGS_EQUAL(0, string_match ("test", "", 0)); + LONGS_EQUAL(0, string_match ("test", "def", 0)); + LONGS_EQUAL(0, string_match ("test", "def", 1)); + LONGS_EQUAL(0, string_match ("test", "def*", 0)); + LONGS_EQUAL(0, string_match ("test", "def*", 1)); + LONGS_EQUAL(0, string_match ("test", "*def", 0)); + LONGS_EQUAL(0, string_match ("test", "*def", 1)); + LONGS_EQUAL(0, string_match ("test", "*def*", 0)); + LONGS_EQUAL(0, string_match ("test", "*def*", 1)); + LONGS_EQUAL(0, string_match ("test", "def", 0)); + LONGS_EQUAL(0, string_match ("test", "def", 1)); + LONGS_EQUAL(0, string_match ("test", "es", 0)); + LONGS_EQUAL(0, string_match ("test", "es", 1)); + LONGS_EQUAL(0, string_match ("test", "es*", 0)); + LONGS_EQUAL(0, string_match ("test", "es*", 1)); + LONGS_EQUAL(0, string_match ("test", "*es", 0)); + LONGS_EQUAL(0, string_match ("test", "*es", 1)); + LONGS_EQUAL(1, string_match ("test", "*es*", 0)); + LONGS_EQUAL(1, string_match ("test", "*es*", 1)); + LONGS_EQUAL(1, string_match ("test", "*ES*", 0)); + LONGS_EQUAL(0, string_match ("test", "*ES*", 1)); +} + +/* + * Tests functions: + * string_expand_home + */ + +TEST(String, ExpandHome) +{ + char *home, *result; + int length_home; + + home = getenv ("HOME"); + length_home = strlen (home); + + result = string_expand_home("~/abc.txt"); + CHECK(strncmp (result, home, length_home) == 0); + LONGS_EQUAL(length_home + 8, strlen (result)); + STRCMP_EQUAL(result + length_home, "/abc.txt"); + free (result); +} + +/* + * Tests functions: + * string_remove_quotes + */ + +TEST(String, RemoveQuotes) +{ + POINTERS_EQUAL(NULL, string_remove_quotes (NULL, NULL)); + POINTERS_EQUAL(NULL, string_remove_quotes (NULL, "abc")); + POINTERS_EQUAL(NULL, string_remove_quotes ("abc", NULL)); + STRCMP_EQUAL("", string_remove_quotes("", "")); + STRCMP_EQUAL("", string_remove_quotes("", "\"'")); + STRCMP_EQUAL("abc", string_remove_quotes("abc", "\"'")); + STRCMP_EQUAL(" abc ", string_remove_quotes(" abc ", "\"'")); + STRCMP_EQUAL("abc", string_remove_quotes("'abc'", "\"'")); + STRCMP_EQUAL("abc", string_remove_quotes(" 'abc' ", "\"'")); + STRCMP_EQUAL("'abc'", string_remove_quotes("\"'abc'\"", "\"'")); + STRCMP_EQUAL("'abc'", string_remove_quotes(" \"'abc'\" ", "\"'")); + STRCMP_EQUAL("'a'b'c'", string_remove_quotes("\"'a'b'c'\"", "\"'")); + STRCMP_EQUAL("'a'b'c'", string_remove_quotes(" \"'a'b'c'\" ", "\"'")); +} + +/* + * Tests functions: + * string_strip + */ + +TEST(String, Strip) +{ + POINTERS_EQUAL(NULL, string_strip (NULL, 1, 1, NULL)); + POINTERS_EQUAL(NULL, string_strip (NULL, 1, 1, ".;")); + STRCMP_EQUAL("test", string_strip ("test", 1, 1, NULL)); + STRCMP_EQUAL("test", string_strip ("test", 1, 1, ".;")); + STRCMP_EQUAL(".-test.-", string_strip (".-test.-", 0, 0, ".-")); + STRCMP_EQUAL("test", string_strip (".-test.-", 1, 1, ".-")); + STRCMP_EQUAL("test.-", string_strip (".-test.-", 1, 0, ".-")); + STRCMP_EQUAL(".-test", string_strip (".-test.-", 0, 1, ".-")); +} + +/* + * Tests functions: + * string_convert_escaped_chars + */ + +TEST(String, ConvertEscapedChars) +{ + POINTERS_EQUAL(NULL, string_convert_escaped_chars (NULL)); + STRCMP_EQUAL("", string_convert_escaped_chars ("")); + STRCMP_EQUAL("\"", string_convert_escaped_chars ("\\\"")); + STRCMP_EQUAL("\\", string_convert_escaped_chars ("\\\\")); + STRCMP_EQUAL("\a", string_convert_escaped_chars ("\\a")); + STRCMP_EQUAL("\a", string_convert_escaped_chars ("\\a")); + STRCMP_EQUAL("\b", string_convert_escaped_chars ("\\b")); + STRCMP_EQUAL("\e", string_convert_escaped_chars ("\\e")); + STRCMP_EQUAL("\f", string_convert_escaped_chars ("\\f")); + STRCMP_EQUAL("\n", string_convert_escaped_chars ("\\n")); + STRCMP_EQUAL("\r", string_convert_escaped_chars ("\\r")); + STRCMP_EQUAL("\t", string_convert_escaped_chars ("\\t")); + STRCMP_EQUAL("\v", string_convert_escaped_chars ("\\v")); + STRCMP_EQUAL("\123", string_convert_escaped_chars ("\\0123")); + STRCMP_EQUAL("\123", + string_convert_escaped_chars ("\\0123")); /* invalid */ + STRCMP_EQUAL("\x41", string_convert_escaped_chars ("\\x41")); + STRCMP_EQUAL("\x04z", string_convert_escaped_chars ("\\x4z")); + STRCMP_EQUAL("\u0012zz", string_convert_escaped_chars ("\\u12zz")); + STRCMP_EQUAL("\U00123456", string_convert_escaped_chars ("\\U00123456")); + STRCMP_EQUAL("\U00000123zzz", + string_convert_escaped_chars ("\\U00123zzz")); + STRCMP_EQUAL("", + string_convert_escaped_chars ("\\U12345678")); /* invalid */ +} + +/* + * Tests functions: + * string_is_word_char + */ + +/* +TEST(String, IsWordChar) +{ + LONGS_EQUAL(0, string_is_word_char (NULL)); + LONGS_EQUAL(0, string_is_word_char ("")); + LONGS_EQUAL(0, string_is_word_char ("&abc")); + LONGS_EQUAL(0, string_is_word_char ("+abc")); + LONGS_EQUAL(0, string_is_word_char ("$abc")); + LONGS_EQUAL(0, string_is_word_char ("*abc")); + LONGS_EQUAL(0, string_is_word_char ("/abc")); + + LONGS_EQUAL(1, string_is_word_char ("abc")); + LONGS_EQUAL(1, string_is_word_char ("-abc")); + LONGS_EQUAL(1, string_is_word_char ("_abc")); + LONGS_EQUAL(1, string_is_word_char ("|abc")); +} +*/ + +/* + * Tests functions: + * string_mask_to_regex + */ + +TEST(String, MaskToRegex) +{ + POINTERS_EQUAL(NULL, string_mask_to_regex (NULL)); + STRCMP_EQUAL("", string_mask_to_regex ("")); + STRCMP_EQUAL("test", string_mask_to_regex ("test")); + STRCMP_EQUAL("test.*", string_mask_to_regex ("test*")); + STRCMP_EQUAL(".*test.*", string_mask_to_regex ("*test*")); + STRCMP_EQUAL(".*te.*st.*", string_mask_to_regex ("*te*st*")); + STRCMP_EQUAL("test\\.\\[\\]\\{\\}\\(\\)\\?\\+\\|\\^\\$\\\\", + string_mask_to_regex ("test.[]{}()?+|^$\\")); +} + +/* + * Tests functions: + * string_regex_flags + * string_regcomp + */ + +TEST(String, Regex) +{ + int flags, rc; + const char *ptr; + regex_t regex; + + string_regex_flags (NULL, 0, NULL); + string_regex_flags ("", 0, NULL); + + string_regex_flags (NULL, 0, &flags); + LONGS_EQUAL(0, flags); + string_regex_flags ("", 0, &flags); + LONGS_EQUAL(0, flags); + string_regex_flags (NULL, REG_EXTENDED, &flags); + LONGS_EQUAL(REG_EXTENDED, flags); + string_regex_flags ("", REG_EXTENDED, &flags); + LONGS_EQUAL(REG_EXTENDED, flags); + + ptr = string_regex_flags ("test", REG_EXTENDED, &flags); + LONGS_EQUAL(REG_EXTENDED, flags); + STRCMP_EQUAL("test", ptr); + + string_regex_flags ("(?e)test", 0, &flags); + LONGS_EQUAL(REG_EXTENDED, flags); + STRCMP_EQUAL("test", ptr); + + string_regex_flags ("(?ei)test", 0, &flags); + LONGS_EQUAL(REG_EXTENDED | REG_ICASE, flags); + STRCMP_EQUAL("test", ptr); + + string_regex_flags ("(?eins)test", 0, &flags); + LONGS_EQUAL(REG_EXTENDED | REG_ICASE | REG_NEWLINE | REG_NOSUB, flags); + STRCMP_EQUAL("test", ptr); + + string_regex_flags ("(?ins)test", REG_EXTENDED, &flags); + LONGS_EQUAL(REG_EXTENDED | REG_ICASE | REG_NEWLINE | REG_NOSUB, flags); + STRCMP_EQUAL("test", ptr); + + string_regex_flags ("(?ins-e)test", REG_EXTENDED, &flags); + LONGS_EQUAL(REG_ICASE | REG_NEWLINE | REG_NOSUB, flags); + STRCMP_EQUAL("test", ptr); + + /* compile regular expression */ + LONGS_EQUAL(-1, string_regcomp (®ex, NULL, 0)); + LONGS_EQUAL(0, string_regcomp (®ex, "", 0)); + regfree (®ex); + LONGS_EQUAL(0, string_regcomp (®ex, "test", 0)); + regfree (®ex); + LONGS_EQUAL(0, string_regcomp (®ex, "test", REG_EXTENDED)); + regfree (®ex); + LONGS_EQUAL(0, string_regcomp (®ex, "(?ins)test", REG_EXTENDED)); + regfree (®ex); +} + +/* + * Tests functions: + * string_has_highlight + * string_has_highlight_regex_compiled + * string_has_highlight_regex + */ + +TEST(String, Highlight) +{ + regex_t regex; + + /* check highlight with a string */ + WEE_HAS_HL_STR(0, NULL, NULL); + WEE_HAS_HL_STR(0, NULL, ""); + WEE_HAS_HL_STR(0, "", NULL); + WEE_HAS_HL_STR(0, "", ""); + WEE_HAS_HL_STR(0, "test", ""); + WEE_HAS_HL_STR(0, "", "test"); + WEE_HAS_HL_STR(1, "test", "test"); + WEE_HAS_HL_STR(1, "this is a test", "test"); + WEE_HAS_HL_STR(1, "test here", "test"); + WEE_HAS_HL_STR(1, "this is a test here", "test"); + WEE_HAS_HL_STR(0, "this is a test here", "abc,def"); + WEE_HAS_HL_STR(1, "this is a test here", "abc,test"); + + /* + * check highlight with a regex, each call of macro + * checks with a regex as string, and then a compiled regex + */ + WEE_HAS_HL_REGEX(-1, 0, NULL, NULL); + WEE_HAS_HL_REGEX(0, 0, NULL, ""); + WEE_HAS_HL_REGEX(-1, 0, "", NULL); + WEE_HAS_HL_REGEX(0, 0, "", ""); + WEE_HAS_HL_REGEX(0, 0, "test", ""); + WEE_HAS_HL_REGEX(0, 0, "", "test"); + WEE_HAS_HL_REGEX(0, 1, "test", "test"); + WEE_HAS_HL_REGEX(0, 1, "this is a test", "test"); + WEE_HAS_HL_REGEX(0, 1, "abc tested", "test.*"); + WEE_HAS_HL_REGEX(0, 1, "abc tested here", "test.*"); + WEE_HAS_HL_REGEX(0, 1, "tested here", "test.*"); + WEE_HAS_HL_REGEX(0, 0, "this is a test", "teste.*"); + WEE_HAS_HL_REGEX(0, 0, "test here", "teste.*"); +} + +/* + * Tests functions: + * string_replace + * string_replace_regex + * string_replace_with_callback + */ + +TEST(String, Replace) +{ + POINTERS_EQUAL(NULL, string_replace (NULL, NULL, NULL)); + POINTERS_EQUAL(NULL, string_replace ("string", NULL, NULL)); + POINTERS_EQUAL(NULL, string_replace (NULL, "search", NULL)); + POINTERS_EQUAL(NULL, string_replace (NULL, NULL, "replace")); + POINTERS_EQUAL(NULL, string_replace ("string", "search", NULL)); + POINTERS_EQUAL(NULL, string_replace ("string", NULL, "replace")); + POINTERS_EQUAL(NULL, string_replace (NULL, "search", "replace")); + + STRCMP_EQUAL("test abc def", string_replace("test abc def", "xyz", "xxx")); + STRCMP_EQUAL("test xxx def", string_replace("test abc def", "abc", "xxx")); + STRCMP_EQUAL("xxx test xxx def xxx", + string_replace("abc test abc def abc", "abc", "xxx")); +} + +/* + * Tests functions: + * string_split + * string_split_shared + * string_split_shell + * string_free_split + * string_free_split_shared + * string_build_with_split_string + * string_split_command + * string_free_split_command + */ + +TEST(String, Split) +{ + char **argv, *str; + int argc; + + POINTERS_EQUAL(NULL, string_split (NULL, NULL, 0, 0, NULL)); + POINTERS_EQUAL(NULL, string_split (NULL, "", 0, 0, NULL)); + POINTERS_EQUAL(NULL, string_split ("", NULL, 0, 0, NULL)); + POINTERS_EQUAL(NULL, string_split ("", "", 0, 0, NULL)); + + argc = 1; + POINTERS_EQUAL(NULL, string_split (NULL, NULL, 0, 0, &argc)); + LONGS_EQUAL(0, argc); + argc = 1; + POINTERS_EQUAL(NULL, string_split (NULL, "", 0, 0, &argc)); + LONGS_EQUAL(0, argc); + argc = 1; + POINTERS_EQUAL(NULL, string_split ("", NULL, 0, 0, &argc)); + LONGS_EQUAL(0, argc); + argc = 1; + POINTERS_EQUAL(NULL, string_split ("", "", 0, 0, &argc)); + LONGS_EQUAL(0, argc); + + /* free split with NULL */ + string_free_split (NULL); + string_free_split_shared (NULL); + string_free_split_command (NULL); + + /* standard split */ + argv = string_split (" abc de fghi ", " ", 0, 0, &argc); + LONGS_EQUAL(3, argc); + STRCMP_EQUAL("abc", argv[0]); + STRCMP_EQUAL("de", argv[1]); + STRCMP_EQUAL("fghi", argv[2]); + POINTERS_EQUAL(NULL, argv[3]); + string_free_split (argv); + + /* max 2 items */ + argv = string_split (" abc de fghi ", " ", 0, 2, &argc); + LONGS_EQUAL(2, argc); + STRCMP_EQUAL("abc", argv[0]); + STRCMP_EQUAL("de", argv[1]); + POINTERS_EQUAL(NULL, argv[2]); + string_free_split (argv); + + /* keep eol */ + argv = string_split (" abc de fghi ", " ", 1, 0, &argc); + LONGS_EQUAL(3, argc); + STRCMP_EQUAL("abc de fghi", argv[0]); + STRCMP_EQUAL("de fghi", argv[1]); + STRCMP_EQUAL("fghi", argv[2]); + POINTERS_EQUAL(NULL, argv[3]); + string_free_split (argv); + + /* keep eol and max 2 items */ + argv = string_split (" abc de fghi ", " ", 1, 2, &argc); + LONGS_EQUAL(2, argc); + STRCMP_EQUAL("abc de fghi", argv[0]); + STRCMP_EQUAL("de fghi", argv[1]); + POINTERS_EQUAL(NULL, argv[2]); + string_free_split (argv); + + /* split with shared strings */ + argv = string_split_shared (" abc de abc ", " ", 0, 0, &argc); + LONGS_EQUAL(3, argc); + STRCMP_EQUAL("abc", argv[0]); + STRCMP_EQUAL("de", argv[1]); + STRCMP_EQUAL("abc", argv[2]); + POINTERS_EQUAL(NULL, argv[3]); + /* same content == same pointer for shared strings */ + POINTERS_EQUAL(argv[0], argv[2]); + string_free_split_shared (argv); + + /* build string with split string */ + str = string_build_with_split_string (NULL, NULL); + POINTERS_EQUAL(NULL, str); + argv = string_split (" abc de fghi ", " ", 0, 0, &argc); + str = string_build_with_split_string ((const char **)argv, NULL); + STRCMP_EQUAL("abcdefghi", str); + free (str); + str = string_build_with_split_string ((const char **)argv, ""); + STRCMP_EQUAL("abcdefghi", str); + free (str); + str = string_build_with_split_string ((const char **)argv, ";;"); + STRCMP_EQUAL("abc;;de;;fghi", str); + free (str); + string_free_split (argv); + + /* split command */ + POINTERS_EQUAL(NULL, string_split_command (NULL, ';')); + POINTERS_EQUAL(NULL, string_split_command ("", ';')); + argv = string_split_command ("abc;de;fghi", ';'); + LONGS_EQUAL(3, argc); + STRCMP_EQUAL("abc", argv[0]); + STRCMP_EQUAL("de", argv[1]); + STRCMP_EQUAL("fghi", argv[2]); + POINTERS_EQUAL(NULL, argv[3]); + string_free_split_command (argv); +} + +/* + * Tests functions: + * string_iconv + * string_iconv_to_internal + * string_iconv_from_internal + * string_iconv_fprintf + */ + +TEST(String, Iconv) +{ + const char *noel_utf8 = "no\xc3\xabl"; /* noël */ + const char *noel_iso = "no\xebl"; + char *str; + + /* TODO: write tests */ +} + +/* + * Tests functions: + * string_format_size + */ + +TEST(String, FormatSize) +{ + /* TODO: write tests */ +} + +/* + * Tests functions: + * string_encode_base16 + * string_decode_base16 + * string_encode_base64 + * string_decode_base64 + */ + +TEST(String, BaseN) +{ + /* TODO: write tests */ +} + +/* + * Tests functions: + * string_is_command_char + * string_input_for_buffer + */ + +TEST(String, Input) +{ + /* TODO: write tests */ +} + +/* + * Tests functions: + * string_is_command_char + */ + +TEST(String, CommandChar) +{ + /* TODO: write tests */ +} + +/* + * Tests functions: + * string_shared_get + * string_shared_free + */ + +TEST(String, Shared) +{ + /* TODO: write tests */ +} diff --git a/tests/unit/core/test-url.cpp b/tests/unit/core/test-url.cpp new file mode 100644 index 000000000..5401af156 --- /dev/null +++ b/tests/unit/core/test-url.cpp @@ -0,0 +1,51 @@ +/* + * test-url.cpp - test URL functions + * + * Copyright (C) 2014 Sébastien Helleu + * + * This file is part of WeeChat, the extensible chat client. + * + * WeeChat is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * WeeChat is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with WeeChat. If not, see . + */ + +#include "CppUTest/TestHarness.h" + +extern "C" +{ +#include "../src/core/wee-url.h" +} + +TEST_GROUP(Url) +{ +}; + +/* + * Tests functions: + * weeurl_download + */ + +TEST(Url, Download) +{ + /* TODO: write tests */ +} + +/* + * Tests functions: + * weeurl_option_add_to_infolist + */ + +TEST(Url, AddToInfolist) +{ + /* TODO: write tests */ +} diff --git a/tests/unit/core/test-utf8.cpp b/tests/unit/core/test-utf8.cpp new file mode 100644 index 000000000..6f226c91c --- /dev/null +++ b/tests/unit/core/test-utf8.cpp @@ -0,0 +1,336 @@ +/* + * test-utf8.cpp - test UTF-8 string functions + * + * Copyright (C) 2014 Sébastien Helleu + * + * This file is part of WeeChat, the extensible chat client. + * + * WeeChat is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * WeeChat is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with WeeChat. If not, see . + */ + +#include "CppUTest/TestHarness.h" + +extern "C" +{ +#include +#include +#include +#include "../src/core/wee-utf8.h" +} + +#define WEE_CHECK_STRNDUP(__result, __string, __length) \ + str = utf8_strndup (__string, __length); \ + STRCMP_EQUAL(__result, str); \ + free (str); + +const char *noel_valid = "no\xc3\xabl"; /* noël */ +const char *noel_invalid = "no\xc3l"; +const char *noel_invalid2 = "no\xff\xffl"; +const char *noel_invalid_norm = "no?l"; +const char *noel_invalid2_norm = "no??l"; +const char *han_char = "\xf0\xa4\xad\xa2"; /* U+24B62 */ +const char *han_char_z = "\xf0\xa4\xad\xa2Z"; + +TEST_GROUP(Utf8) +{ +}; + +/* + * Tests functions: + * utf8_has_8bits + * utf8_is_valid + */ + +TEST(Utf8, Validity) +{ + char *error; + + /* check 8 bits */ + LONGS_EQUAL(0, utf8_has_8bits (NULL)); + LONGS_EQUAL(0, utf8_has_8bits ("")); + LONGS_EQUAL(0, utf8_has_8bits ("abc")); + LONGS_EQUAL(1, utf8_has_8bits ("no\xc3\xabl")); + + /* check validity */ + LONGS_EQUAL(1, utf8_is_valid (NULL, NULL)); + LONGS_EQUAL(1, utf8_is_valid (NULL, &error)); + LONGS_EQUAL(1, utf8_is_valid ("", NULL)); + LONGS_EQUAL(1, utf8_is_valid ("", &error)); + LONGS_EQUAL(1, utf8_is_valid ("abc", &error)); + POINTERS_EQUAL(NULL, error); + LONGS_EQUAL(1, utf8_is_valid (noel_valid, &error)); + POINTERS_EQUAL(NULL, error); + LONGS_EQUAL(0, utf8_is_valid (noel_invalid, &error)); + POINTERS_EQUAL(noel_invalid + 2, error); + + /* 2 bytes: code point must be in range U+0080-07FF */ + //LONGS_EQUAL(0, utf8_is_valid ("\xc0\x80", NULL)); /* U+0 */ + //LONGS_EQUAL(0, utf8_is_valid ("\xc1\xbf", NULL)); /* U+7F */ + LONGS_EQUAL(1, utf8_is_valid ("\xc2\x80", NULL)); /* U+80 */ + LONGS_EQUAL(1, utf8_is_valid ("\xdf\xbf", NULL)); /* U+7FF */ + + /* 3 bytes: code point must be in range: U+0800-FFFF */ + //LONGS_EQUAL(0, utf8_is_valid ("\xe0\x80\x80", NULL)); /* U+0 */ + //LONGS_EQUAL(0, utf8_is_valid ("\xe0\x9f\xbf", NULL)); /* U+7FF */ + LONGS_EQUAL(1, utf8_is_valid ("\xe0\xa0\x80", NULL)); /* U+800 */ + LONGS_EQUAL(1, utf8_is_valid ("\xef\xbf\xbf", NULL)); /* U+FFFF */ + + /* 4 bytes: code point must be in range: U+10000-1FFFFF */ + //LONGS_EQUAL(0, utf8_is_valid ("\xf0\x80\x80\x80", NULL)); /* U+0 */ + //LONGS_EQUAL(0, utf8_is_valid ("\xf0\x8f\xbf\xbf", NULL)); /* U+FFFF */ + LONGS_EQUAL(1, utf8_is_valid ("\xf0\x90\x80\x80", NULL)); /* U+10000 */ + LONGS_EQUAL(1, utf8_is_valid ("\xf7\xbf\xbf\xbf", NULL)); /* U+1FFFFF */ +} + +/* + * Tests functions: + * utf8_normalize + */ + +TEST(Utf8, Normalize) +{ + char *str; + + str = strdup (noel_invalid); + utf8_normalize (NULL, '?'); + utf8_normalize (str, '?'); + STRCMP_EQUAL(noel_invalid_norm, str); + free (str); + + str = strdup (noel_invalid2); + utf8_normalize (str, '?'); + STRCMP_EQUAL(noel_invalid2_norm, str); + free (str); +} + +/* + * Tests functions: + * utf8_prev_char + * utf8_next_char + * utf8_add_offset + * utf8_real_pos + * utf8_pos + */ + +TEST(Utf8, Move) +{ + char *ptr; + + /* previous/next char */ + POINTERS_EQUAL(NULL, utf8_prev_char (NULL, NULL)); + POINTERS_EQUAL(NULL, utf8_next_char (NULL)); + ptr = utf8_next_char (noel_valid); + STRCMP_EQUAL("oël", ptr); + ptr = utf8_next_char (ptr); + STRCMP_EQUAL("ël", ptr); + ptr = utf8_next_char (ptr); + STRCMP_EQUAL("l", ptr); + ptr = utf8_prev_char (noel_valid, ptr); + ptr = utf8_prev_char (noel_valid, ptr); + ptr = utf8_prev_char (noel_valid, ptr); + STRCMP_EQUAL("noël", ptr); + POINTERS_EQUAL(noel_valid, ptr); + + /* add offset */ + ptr = utf8_add_offset (noel_valid, 0); + STRCMP_EQUAL(noel_valid, ptr); + ptr = utf8_add_offset (noel_valid, 1); + STRCMP_EQUAL("oël", ptr); + ptr = utf8_add_offset (noel_valid, 3); + STRCMP_EQUAL("l", ptr); + + /* real position */ + LONGS_EQUAL(0, utf8_real_pos (noel_valid, 0)); + LONGS_EQUAL(1, utf8_real_pos (noel_valid, 1)); + LONGS_EQUAL(2, utf8_real_pos (noel_valid, 2)); + LONGS_EQUAL(4, utf8_real_pos (noel_valid, 3)); + + /* position */ + LONGS_EQUAL(0, utf8_pos (noel_valid, 0)); + LONGS_EQUAL(1, utf8_pos (noel_valid, 1)); + LONGS_EQUAL(2, utf8_pos (noel_valid, 2)); + LONGS_EQUAL(3, utf8_pos (noel_valid, 4)); +} + +/* + * Tests functions: + * utf8_char_int + * utf8_int_string + * utf8_wide_char + */ + +TEST(Utf8, Convert) +{ + char result[5]; + + /* get UTF-8 char as integer */ + BYTES_EQUAL(0, utf8_char_int (NULL)); + BYTES_EQUAL(0, utf8_char_int ("")); + BYTES_EQUAL(65, utf8_char_int ("ABC")); + BYTES_EQUAL(235, utf8_char_int ("ë")); + BYTES_EQUAL(0x20ac, utf8_char_int ("€")); + BYTES_EQUAL(0x24b62, utf8_char_int (han_char)); + + BYTES_EQUAL(0x0, utf8_char_int ("\xc0\x80")); /* invalid */ + BYTES_EQUAL(0x7f, utf8_char_int ("\xc1\xbf")); /* invalid */ + BYTES_EQUAL(0x80, utf8_char_int ("\xc2\x80")); + BYTES_EQUAL(0x7ff, utf8_char_int ("\xdf\xbf")); + + BYTES_EQUAL(0x0, utf8_char_int ("\xe0\x80\x80")); /* invalid */ + BYTES_EQUAL(0x7ff, utf8_char_int ("\xe0\x9f\xbf")); /* invalid */ + BYTES_EQUAL(0x800, utf8_char_int ("\xe0\xa0\x80")); + BYTES_EQUAL(0xffff, utf8_char_int ("\xef\xbf\xbf")); + + BYTES_EQUAL(0x0, utf8_char_int ("\xf0\x80\x80\x80")); /* invalid */ + BYTES_EQUAL(0xffff, utf8_char_int ("\xf0\x8f\xbf\xbf")); /* invalid */ + BYTES_EQUAL(0x10000, utf8_char_int ("\xf0\x90\x80\x80")); + BYTES_EQUAL(0x1fffff, utf8_char_int ("\xf7\xbf\xbf\xbf")); + + /* convert unicode char to a string */ + utf8_int_string (0, NULL); + utf8_int_string (0, result); + STRCMP_EQUAL("", result); + utf8_int_string (235, result); + STRCMP_EQUAL("ë", result); + utf8_int_string (0x20ac, result); + STRCMP_EQUAL("€", result); + utf8_int_string (0x24b62, result); + STRCMP_EQUAL(han_char, result); + + /* get wide char */ + BYTES_EQUAL(WEOF, utf8_wide_char (NULL)); + BYTES_EQUAL(WEOF, utf8_wide_char ("")); + BYTES_EQUAL(65, utf8_wide_char ("A")); + BYTES_EQUAL(0xc3ab, utf8_wide_char ("ë")); + BYTES_EQUAL(0xe282ac, utf8_wide_char ("€")); + BYTES_EQUAL(0xf0a4ada2, utf8_wide_char (han_char)); +} + +/* + * Tests functions: + * utf8_char_size + * utf8_char_size_screen + * utf8_strlen + * utf8_strnlen + * utf8_strlen_screen + */ + +TEST(Utf8, Size) +{ + /* char size */ + LONGS_EQUAL(0, utf8_char_size (NULL)); + LONGS_EQUAL(1, utf8_char_size ("")); + LONGS_EQUAL(1, utf8_char_size ("A")); + LONGS_EQUAL(2, utf8_char_size ("ë")); + LONGS_EQUAL(3, utf8_char_size ("€")); + LONGS_EQUAL(4, utf8_char_size (han_char)); + + /* char size on screen */ + LONGS_EQUAL(0, utf8_char_size_screen (NULL)); + LONGS_EQUAL(0, utf8_char_size_screen ("")); + LONGS_EQUAL(1, utf8_char_size_screen ("A")); + LONGS_EQUAL(1, utf8_char_size_screen ("ë")); + LONGS_EQUAL(1, utf8_char_size_screen ("€")); + LONGS_EQUAL(1, utf8_char_size_screen (han_char)); + + /* length of string (in chars) */ + LONGS_EQUAL(0, utf8_strlen (NULL)); + LONGS_EQUAL(0, utf8_strlen ("")); + LONGS_EQUAL(1, utf8_strlen ("A")); + LONGS_EQUAL(1, utf8_strlen ("ë")); + LONGS_EQUAL(1, utf8_strlen ("€")); + LONGS_EQUAL(1, utf8_strlen (han_char)); + + /* length of string (in chars, for max N bytes) */ + LONGS_EQUAL(0, utf8_strnlen (NULL, 0)); + LONGS_EQUAL(0, utf8_strnlen ("", 0)); + LONGS_EQUAL(1, utf8_strnlen ("AZ", 1)); + LONGS_EQUAL(1, utf8_strnlen ("ëZ", 2)); + LONGS_EQUAL(1, utf8_strnlen ("€Z", 3)); + LONGS_EQUAL(1, utf8_strnlen (han_char_z, 4)); + + /* length of string on screen (in chars) */ + LONGS_EQUAL(0, utf8_strlen_screen (NULL)); + LONGS_EQUAL(0, utf8_strlen_screen ("")); + LONGS_EQUAL(1, utf8_strlen_screen ("A")); + LONGS_EQUAL(1, utf8_strlen_screen ("ë")); + LONGS_EQUAL(1, utf8_strlen_screen ("€")); + LONGS_EQUAL(1, utf8_strlen_screen (han_char)); + LONGS_EQUAL(1, utf8_strlen_screen ("\x7f")); +} + +/* + * Tests functions: + * utf8_charcmp + * utf8_charcasecmp + * utf8_charcasecmp_range + */ + +TEST(Utf8, Comparison) +{ + /* case-sensitive comparison */ + LONGS_EQUAL(0, utf8_charcmp (NULL, NULL)); + LONGS_EQUAL(-1, utf8_charcmp (NULL, "abc")); + LONGS_EQUAL(1, utf8_charcmp ("abc", NULL)); + LONGS_EQUAL(0, utf8_charcmp ("axx", "azz")); + LONGS_EQUAL(-1, utf8_charcmp ("A", "Z")); + LONGS_EQUAL(1, utf8_charcmp ("Z", "A")); + LONGS_EQUAL(-1, utf8_charcmp ("A", "a")); + LONGS_EQUAL(-1, utf8_charcmp ("ë", "€")); + + /* case-insensitive comparison */ + LONGS_EQUAL(0, utf8_charcasecmp (NULL, NULL)); + LONGS_EQUAL(-1, utf8_charcasecmp (NULL, "abc")); + LONGS_EQUAL(1, utf8_charcasecmp ("abc", NULL)); + LONGS_EQUAL(0, utf8_charcasecmp ("axx", "azz")); + LONGS_EQUAL(-1, utf8_charcasecmp ("A", "Z")); + LONGS_EQUAL(1, utf8_charcasecmp ("Z", "A")); + LONGS_EQUAL(0, utf8_charcasecmp ("A", "a")); + LONGS_EQUAL(-1, utf8_charcasecmp ("ë", "€")); + + /* case-insensitive comparison with a range */ + LONGS_EQUAL(0, utf8_charcasecmp_range (NULL, NULL, 30)); + LONGS_EQUAL(-1, utf8_charcasecmp_range (NULL, "abc", 30)); + LONGS_EQUAL(1, utf8_charcasecmp_range ("abc", NULL, 30)); + LONGS_EQUAL(0, utf8_charcasecmp_range ("axx", "azz", 30)); + LONGS_EQUAL(-1, utf8_charcasecmp_range ("A", "Z", 30)); + LONGS_EQUAL(1, utf8_charcasecmp_range ("Z", "A", 30)); + LONGS_EQUAL(0, utf8_charcasecmp_range ("A", "a", 30)); + LONGS_EQUAL(-1, utf8_charcasecmp_range ("ë", "€", 30)); + LONGS_EQUAL(0, utf8_charcasecmp_range ("[", "{", 30)); + LONGS_EQUAL(0, utf8_charcasecmp_range ("]", "}", 30)); + LONGS_EQUAL(0, utf8_charcasecmp_range ("\\", "|", 30)); + LONGS_EQUAL(0, utf8_charcasecmp_range ("^", "~", 30)); + LONGS_EQUAL(-1, utf8_charcasecmp_range ("[", "{", 26)); + LONGS_EQUAL(-1, utf8_charcasecmp_range ("]", "}", 26)); + LONGS_EQUAL(-1, utf8_charcasecmp_range ("\\", "|", 26)); + LONGS_EQUAL(-1, utf8_charcasecmp_range ("^", "~", 26)); +} + +/* + * Tests functions: + * utf8_strndup + */ + +TEST(Utf8, Duplicate) +{ + char *str; + + WEE_CHECK_STRNDUP("", noel_valid, 0); + WEE_CHECK_STRNDUP("n", noel_valid, 1); + WEE_CHECK_STRNDUP("no", noel_valid, 2); + WEE_CHECK_STRNDUP("noë", noel_valid, 3); + WEE_CHECK_STRNDUP("noël", noel_valid, 4); + WEE_CHECK_STRNDUP("noël", noel_valid, 5); +} diff --git a/tests/unit/core/test-util.cpp b/tests/unit/core/test-util.cpp new file mode 100644 index 000000000..96a930e0c --- /dev/null +++ b/tests/unit/core/test-util.cpp @@ -0,0 +1,168 @@ +/* + * test-util.cpp - test util functions + * + * Copyright (C) 2014 Sébastien Helleu + * + * This file is part of WeeChat, the extensible chat client. + * + * WeeChat is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * WeeChat is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with WeeChat. If not, see . + */ + +#include "CppUTest/TestHarness.h" + +extern "C" +{ +#include +#include +#include +#include +#include "../src/core/wee-util.h" +} + +TEST_GROUP(Util) +{ +}; + +/* + * Tests functions: + * util_timeval_cmp + * util_timeval_diff + * util_timeval_add + */ + +TEST(Util, Timeval) +{ + struct timeval tv1 = { 123456, 12000 }; + struct timeval tv2 = { 123456, 15000 }; + struct timeval tv3 = { 123457, 15000 }; + struct timeval tv; + + /* comparison */ + LONGS_EQUAL(0, util_timeval_cmp (NULL, NULL)); + LONGS_EQUAL(-1, util_timeval_cmp (NULL, &tv1)); + LONGS_EQUAL(1, util_timeval_cmp (&tv1, NULL)); + LONGS_EQUAL(0, util_timeval_cmp (&tv1, &tv1)); + LONGS_EQUAL(-1, util_timeval_cmp (&tv1, &tv2)); + LONGS_EQUAL(1, util_timeval_cmp (&tv2, &tv1)); + + /* difference */ + LONGS_EQUAL(0, util_timeval_diff (NULL, NULL)); + LONGS_EQUAL(0, util_timeval_diff (NULL, &tv1)); + LONGS_EQUAL(0, util_timeval_diff (&tv1, NULL)); + LONGS_EQUAL(3, util_timeval_diff (&tv1, &tv2)); + LONGS_EQUAL(1003, util_timeval_diff (&tv1, &tv3)); + + /* add interval */ + util_timeval_add (NULL, 0); + tv.tv_sec = 123456; + tv.tv_usec = 12000; + util_timeval_add (&tv, 10); + LONGS_EQUAL(123456, tv.tv_sec); + LONGS_EQUAL(22000, tv.tv_usec); + util_timeval_add (&tv, 4000); + LONGS_EQUAL(123460, tv.tv_sec); + LONGS_EQUAL(22000, tv.tv_usec); +} + +/* + * Tests functions: + * util_get_time_string + */ + +TEST(Util, GetTimeString) +{ + time_t date; + const char *str_date; + + date = 946684800; /* 2000-01-01 00:00 */ + str_date = util_get_time_string (&date); + STRCMP_EQUAL("Sat, 01 Jan 2000 00:00:00", str_date); +} + +/* + * Tests functions: + * util_signal_search + * util_catch_signal + */ + +TEST(Util, Signal) +{ + /* TODO: write tests */ +} + +/* + * Tests functions: + * util_mkdir_home + * util_mkdir + * util_mkdir_parents + */ + +TEST(Util, Mkdir) +{ + /* TODO: write tests */ +} + +/* + * Tests functions: + * util_exec_on_files + */ + +TEST(Util, ExecOnFiles) +{ + /* TODO: write tests */ +} + +/* + * Tests functions: + * util_search_full_lib_name + */ + +TEST(Util, LibName) +{ + /* TODO: write tests */ +} + +/* + * Tests functions: + * util_file_get_content + */ + +TEST(Util, FileGetContent) +{ + /* TODO: write tests */ +} + +/* + * Tests functions: + * util_version_number + */ + +TEST(Util, VersionNumber) +{ + BYTES_EQUAL(0x00030200, util_version_number ("0.3.2-dev")); + BYTES_EQUAL(0x00030200, util_version_number ("0.3.2-rc1")); + BYTES_EQUAL(0x00030200, util_version_number ("0.3.2")); + BYTES_EQUAL(0x00030101, util_version_number ("0.3.1.1")); + BYTES_EQUAL(0x00030100, util_version_number ("0.3.1")); + BYTES_EQUAL(0x00030000, util_version_number ("0.3.0")); + BYTES_EQUAL(0x01000000, util_version_number ("1.0")); + BYTES_EQUAL(0x01000000, util_version_number ("1.0.0")); + BYTES_EQUAL(0x01000000, util_version_number ("1.0.0.0")); + BYTES_EQUAL(0x01000100, util_version_number ("1.0.1")); + BYTES_EQUAL(0x01000200, util_version_number ("1.0.2")); + BYTES_EQUAL(0x01010000, util_version_number ("1.1")); + BYTES_EQUAL(0x01010100, util_version_number ("1.1.1")); + BYTES_EQUAL(0x01010200, util_version_number ("1.1.2")); + BYTES_EQUAL(0x01020304, util_version_number ("1.2.3.4")); +}