Manual pages: mcmcdiffmceditmcview

root/tests/src/editor/edit_replace_cmd.c

/* [previous][next][first][last][top][bottom][index][help]  */

DEFINITIONS

This source file includes following definitions.
  1. message
  2. status_msg_init
  3. status_msg_deinit
  4. edit_search_update_callback
  5. edit_dialog_replace_show
  6. edit_dialog_replace_prompt_show
  7. edit_load_syntax
  8. edit_get_syntax_color
  9. edit_load_macro_cmd
  10. setup
  11. teardown
  12. test_replace_check
  13. START_TEST
  14. START_TEST
  15. START_TEST
  16. START_TEST
  17. START_TEST
  18. START_TEST
  19. START_TEST
  20. main

   1 /*
   2    src/editor - tests for edit_replace_cmd() function
   3 
   4    Copyright (C) 2025
   5    Free Software Foundation, Inc.
   6 
   7    Written by:
   8    Andrew Borodin <aborodin@vmail.ru>, 2025
   9 
  10    This file is part of the Midnight Commander.
  11 
  12    The Midnight Commander is free software: you can redistribute it
  13    and/or modify it under the terms of the GNU General Public License as
  14    published by the Free Software Foundation, either version 3 of the License,
  15    or (at your option) any later version.
  16 
  17    The Midnight Commander is distributed in the hope that it will be useful,
  18    but WITHOUT ANY WARRANTY; without even the implied warranty of
  19    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  20    GNU General Public License for more details.
  21 
  22    You should have received a copy of the GNU General Public License
  23    along with this program.  If not, see <https://www.gnu.org/licenses/>.
  24  */
  25 
  26 #define TEST_SUITE_NAME "/src/editor"
  27 
  28 #include "tests/mctest.h"
  29 
  30 #include <ctype.h>
  31 
  32 #include "lib/charsets.h"
  33 #include "src/selcodepage.h"
  34 
  35 #include "src/editor/editwidget.h"
  36 #include "src/editor/editmacros.h"  // edit_load_macro_cmd()
  37 #include "src/editor/editsearch.h"
  38 
  39 static WGroup owner;
  40 static WEdit *test_edit;
  41 static const char **replace_regex__from;
  42 static const char **replace_regex__to;
  43 static gboolean only_in_selection = FALSE;
  44 
  45 // input text: entire text
  46 static const char *test_regex_in = "qwe\n"   //
  47                                    "qwe\n"   //
  48                                    "qwe\n"   //
  49                                    "qwe\n"   //
  50                                    "qwe\n"   //
  51                                    "qwe\n"   //
  52                                    "qwe\n"   //
  53                                    "qwe\n";  //
  54 
  55 // insert char at begin of string:
  56 // s/^.*/X\\0
  57 // s/^/X
  58 // not in selection
  59 static const char *test_regex_out1 = "Xqwe\n"   //
  60                                      "Xqwe\n"   //
  61                                      "Xqwe\n"   //
  62                                      "Xqwe\n"   //
  63                                      "Xqwe\n"   //
  64                                      "Xqwe\n"   //
  65                                      "Xqwe\n"   //
  66                                      "Xqwe\n";  //
  67 
  68 // replace first char of string:
  69 // s/^./X
  70 // not in selection
  71 static const char *test_regex_out2 = "Xwe\n"   //
  72                                      "Xwe\n"   //
  73                                      "Xwe\n"   //
  74                                      "Xwe\n"   //
  75                                      "Xwe\n"   //
  76                                      "Xwe\n"   //
  77                                      "Xwe\n"   //
  78                                      "Xwe\n";  //
  79 
  80 // input text: selected
  81 static const char *test_regex_selected_in = "qwe\n"   //
  82                                             "qwe\n"   //
  83                                             "qwe\n"   // selected, mark1 = 8 (begin of string) or 9
  84                                             "qwe\n"   // selected
  85                                             "qwe\n"   // selected
  86                                             "qwe\n"   // mark2 = 20, begin of string
  87                                             "qwe\n"   //
  88                                             "qwe\n";  //
  89 
  90 // insert char at begin of string:
  91 // s/^.*/X\\0
  92 // in selection from begin of string
  93 static const char *test1_regex_selected_out = "qwe\n"   //
  94                                               "qwe\n"   //
  95                                               "Xqwe\n"  // selected, mark1 = 8 (begin of string)
  96                                               "Xqwe\n"  // selected
  97                                               "Xqwe\n"  // selected
  98                                               "qwe\n"   // mark2 = 20, begin of string
  99                                               "qwe\n"   //
 100                                               "qwe\n";  //
 101 
 102 // insert char at begin of string:
 103 // s/^.*/X\\0
 104 // in selection not from begin of string
 105 static const char *test2_regex_selected_out = "qwe\n"   //
 106                                               "qwe\n"   //
 107                                               "qwe\n"   // selected, mark1 = 9 (not begin of string)
 108                                               "Xqwe\n"  // selected
 109                                               "Xqwe\n"  // selected
 110                                               "qwe\n"   // mark2 = 20, begin of string
 111                                               "qwe\n"   //
 112                                               "qwe\n";  //
 113 
 114 static const char *replace_regex_entire_string__from = "^.*";
 115 static const char *replace_regex_entire_string__to = "X\\0";
 116 
 117 static const char *replace_regex_insert_char_at_begin_of_string__from = "^";
 118 static const char *replace_regex_replace_first_char_of_string__from = "^.";
 119 static const char *replace_regex_begin_of_string__to = "X";
 120 
 121 /* --------------------------------------------------------------------------------------------- */
 122 
 123 void edit_dialog_replace_show (WEdit *edit, const char *search_default, const char *replace_default,
 124                                char **search_text, char **replace_text);
 125 int edit_dialog_replace_prompt_show (WEdit *edit, char *from_text, char *to_text, int xpos,
 126                                      int ypos);
 127 
 128 /* --------------------------------------------------------------------------------------------- */
 129 /* @Mock */
 130 void
 131 message (int flags, const char *title, const char *text, ...)
     /* [previous][next][first][last][top][bottom][index][help]  */
 132 {
 133     (void) flags;
 134     (void) title;
 135     (void) text;
 136 }
 137 
 138 /* --------------------------------------------------------------------------------------------- */
 139 /* @Mock */
 140 void
 141 status_msg_init (status_msg_t *sm, const char *title, double delay, status_msg_cb init_cb,
     /* [previous][next][first][last][top][bottom][index][help]  */
 142                  status_msg_update_cb update_cb, status_msg_cb deinit_cb)
 143 {
 144     (void) sm;
 145     (void) title;
 146     (void) delay;
 147     (void) init_cb;
 148     (void) update_cb;
 149     (void) deinit_cb;
 150 }
 151 
 152 /* --------------------------------------------------------------------------------------------- */
 153 /* @Mock */
 154 void
 155 status_msg_deinit (status_msg_t *sm)
     /* [previous][next][first][last][top][bottom][index][help]  */
 156 {
 157     (void) sm;
 158 }
 159 
 160 /* --------------------------------------------------------------------------------------------- */
 161 /* @Mock */
 162 mc_search_cbret_t
 163 edit_search_update_callback (const void *user_data, off_t char_offset)
     /* [previous][next][first][last][top][bottom][index][help]  */
 164 {
 165     (void) user_data;
 166     (void) char_offset;
 167 
 168     return MC_SEARCH_CB_OK;
 169 }
 170 
 171 /* --------------------------------------------------------------------------------------------- */
 172 /* @Mock */
 173 void
 174 edit_dialog_replace_show (WEdit *edit, const char *search_default, const char *replace_default,
     /* [previous][next][first][last][top][bottom][index][help]  */
 175                           char **search_text, char **replace_text)
 176 {
 177     (void) edit;
 178     (void) search_default;
 179     (void) replace_default;
 180 
 181     *search_text = g_strdup (*replace_regex__from);
 182     *replace_text = g_strdup (*replace_regex__to);
 183 
 184     edit_search_options.type = MC_SEARCH_T_REGEX;
 185     edit_search_options.only_in_selection = only_in_selection;
 186 }
 187 
 188 /* --------------------------------------------------------------------------------------------- */
 189 /* @Mock */
 190 int
 191 edit_dialog_replace_prompt_show (WEdit *edit, char *from_text, char *to_text, int xpos, int ypos)
     /* [previous][next][first][last][top][bottom][index][help]  */
 192 {
 193     (void) edit;
 194     (void) from_text;
 195     (void) to_text;
 196     (void) xpos;
 197     (void) ypos;
 198 
 199     return B_REPLACE_ALL;
 200 }
 201 
 202 /* --------------------------------------------------------------------------------------------- */
 203 /* @Mock */
 204 void
 205 edit_load_syntax (WEdit *edit, GPtrArray *pnames, const char *type)
     /* [previous][next][first][last][top][bottom][index][help]  */
 206 {
 207     (void) edit;
 208     (void) pnames;
 209     (void) type;
 210 }
 211 
 212 /* --------------------------------------------------------------------------------------------- */
 213 
 214 /* @Mock */
 215 int
 216 edit_get_syntax_color (WEdit *edit, off_t byte_index)
     /* [previous][next][first][last][top][bottom][index][help]  */
 217 {
 218     (void) edit;
 219     (void) byte_index;
 220 
 221     return 0;
 222 }
 223 
 224 /* --------------------------------------------------------------------------------------------- */
 225 
 226 /* @Mock */
 227 gboolean
 228 edit_load_macro_cmd (WEdit *edit)
     /* [previous][next][first][last][top][bottom][index][help]  */
 229 {
 230     (void) edit;
 231 
 232     return FALSE;
 233 }
 234 
 235 /* --------------------------------------------------------------------------------------------- */
 236 
 237 /* @Before */
 238 static void
 239 setup (void)
     /* [previous][next][first][last][top][bottom][index][help]  */
 240 {
 241     WRect r;
 242 
 243     str_init_strings (NULL);
 244 
 245     mc_global.sysconfig_dir = (char *) TEST_SHARE_DIR;
 246     load_codepages_list ();
 247 
 248     edit_options.filesize_threshold = (char *) "64M";
 249 
 250     rect_init (&r, 0, 0, 24, 80);
 251     test_edit = edit_init (NULL, &r, NULL);
 252     memset (&owner, 0, sizeof (owner));
 253     group_add_widget (&owner, WIDGET (test_edit));
 254 
 255     mc_global.source_codepage = 0;
 256     mc_global.display_codepage = 0;
 257     cp_source = "ASCII";
 258     cp_display = "ASCII";
 259 
 260     do_set_codepage (0);
 261     edit_set_codeset (test_edit);
 262 }
 263 
 264 /* --------------------------------------------------------------------------------------------- */
 265 
 266 /* @After */
 267 static void
 268 teardown (void)
     /* [previous][next][first][last][top][bottom][index][help]  */
 269 {
 270     edit_clean (test_edit);
 271     group_remove_widget (test_edit);
 272     g_free (test_edit);
 273 
 274     free_codepages_list ();
 275     str_uninit_strings ();
 276 }
 277 
 278 /* --------------------------------------------------------------------------------------------- */
 279 
 280 static void
 281 test_replace_check (const char *test_out)
     /* [previous][next][first][last][top][bottom][index][help]  */
 282 {
 283     GString *actual_replaced_str;
 284 
 285     actual_replaced_str = g_string_new ("");
 286 
 287     for (off_t i = 0; i < test_edit->buffer.size; i++)
 288     {
 289         const int chr = edit_buffer_get_byte (&test_edit->buffer, i);
 290 
 291         g_string_append_c (actual_replaced_str, chr);
 292     }
 293 
 294     mctest_assert_str_eq (actual_replaced_str->str, test_out);
 295     g_string_free (actual_replaced_str, TRUE);
 296 }
 297 
 298 /* --------------------------------------------------------------------------------------------- */
 299 
 300 // replace entire string
 301 START_TEST (test_replace_regex__entire_string)
     /* [previous][next][first][last][top][bottom][index][help]  */
 302 {
 303     // given
 304     only_in_selection = FALSE;
 305     replace_regex__from = &replace_regex_entire_string__from;
 306     replace_regex__to = &replace_regex_entire_string__to;
 307     test_edit->mark1 = 0;
 308     test_edit->mark2 = 0;
 309 
 310     for (const char *ti = test_regex_in; *ti != '\0'; ti++)
 311         edit_buffer_insert (&test_edit->buffer, *ti);
 312 
 313     // when
 314     edit_cursor_move (test_edit, 0);
 315     edit_replace_cmd (test_edit, FALSE);
 316 
 317     // then
 318     test_replace_check (test_regex_out1);
 319 }
 320 END_TEST
 321 
 322 /* --------------------------------------------------------------------------------------------- */
 323 
 324 // insert first char in string
 325 START_TEST (test_replace_regex__insert_char_at_begin_of_string)
     /* [previous][next][first][last][top][bottom][index][help]  */
 326 {
 327     // given
 328     only_in_selection = FALSE;
 329     replace_regex__from = &replace_regex_insert_char_at_begin_of_string__from;
 330     replace_regex__to = &replace_regex_begin_of_string__to;
 331     test_edit->mark1 = 0;
 332     test_edit->mark2 = 0;
 333 
 334     for (const char *ti = test_regex_in; *ti != '\0'; ti++)
 335         edit_buffer_insert (&test_edit->buffer, *ti);
 336 
 337     // when
 338     edit_cursor_move (test_edit, 0);
 339     edit_replace_cmd (test_edit, FALSE);
 340 
 341     // then
 342     test_replace_check (test_regex_out1);
 343 }
 344 END_TEST
 345 
 346 /* --------------------------------------------------------------------------------------------- */
 347 
 348 // replace first char of string
 349 START_TEST (test_replace_regex__replace_first_char_of_string)
     /* [previous][next][first][last][top][bottom][index][help]  */
 350 {
 351     // given
 352     only_in_selection = FALSE;
 353     replace_regex__from = &replace_regex_replace_first_char_of_string__from;
 354     replace_regex__to = &replace_regex_begin_of_string__to;
 355     test_edit->mark1 = 0;
 356     test_edit->mark2 = 0;
 357 
 358     for (const char *ti = test_regex_in; *ti != '\0'; ti++)
 359         edit_buffer_insert (&test_edit->buffer, *ti);
 360 
 361     // when
 362     edit_cursor_move (test_edit, 0);
 363     edit_replace_cmd (test_edit, FALSE);
 364 
 365     // then
 366     test_replace_check (test_regex_out2);
 367 }
 368 END_TEST
 369 
 370 /* --------------------------------------------------------------------------------------------- */
 371 
 372 // replace from begin of string in selection
 373 START_TEST (test_replace_regex__in_selection_top_down_1)
     /* [previous][next][first][last][top][bottom][index][help]  */
 374 {
 375     // given
 376     only_in_selection = TRUE;
 377     replace_regex__from = &replace_regex_entire_string__from;
 378     replace_regex__to = &replace_regex_entire_string__to;
 379     test_edit->mark1 = 8;
 380     test_edit->mark2 = 20;
 381 
 382     for (const char *ti = test_regex_selected_in; *ti != '\0'; ti++)
 383         edit_buffer_insert (&test_edit->buffer, *ti);
 384 
 385     // when
 386     edit_cursor_move (test_edit, 0);
 387     edit_replace_cmd (test_edit, FALSE);
 388 
 389     // then
 390     test_replace_check (test1_regex_selected_out);
 391 }
 392 END_TEST
 393 
 394 /* --------------------------------------------------------------------------------------------- */
 395 
 396 // replace not from begin of string in selection
 397 START_TEST (test_replace_regex__in_selection_top_down_2)
     /* [previous][next][first][last][top][bottom][index][help]  */
 398 {
 399     // given
 400     only_in_selection = TRUE;
 401     replace_regex__from = &replace_regex_entire_string__from;
 402     replace_regex__to = &replace_regex_entire_string__to;
 403     test_edit->mark1 = 9;
 404     test_edit->mark2 = 20;
 405 
 406     for (const char *ti = test_regex_selected_in; *ti != '\0'; ti++)
 407         edit_buffer_insert (&test_edit->buffer, *ti);
 408 
 409     // when
 410     edit_cursor_move (test_edit, 0);
 411     edit_replace_cmd (test_edit, FALSE);
 412 
 413     // then
 414     test_replace_check (test2_regex_selected_out);
 415 }
 416 END_TEST
 417 
 418 /* --------------------------------------------------------------------------------------------- */
 419 
 420 // replace from begin of string in selection
 421 START_TEST (test_replace_regex__in_selection_bottom_up_1)
     /* [previous][next][first][last][top][bottom][index][help]  */
 422 {
 423     // given
 424     only_in_selection = TRUE;
 425     replace_regex__from = &replace_regex_entire_string__from;
 426     replace_regex__to = &replace_regex_entire_string__to;
 427     test_edit->mark1 = 20;
 428     test_edit->mark2 = 8;
 429 
 430     for (const char *ti = test_regex_selected_in; *ti != '\0'; ti++)
 431         edit_buffer_insert (&test_edit->buffer, *ti);
 432 
 433     // when
 434     edit_cursor_move (test_edit, 0);
 435     edit_replace_cmd (test_edit, FALSE);
 436 
 437     // then
 438     test_replace_check (test1_regex_selected_out);
 439 }
 440 END_TEST
 441 
 442 /* --------------------------------------------------------------------------------------------- */
 443 
 444 // replace not from begin of string in selection
 445 START_TEST (test_replace_regex__in_selection_bottom_up_2)
     /* [previous][next][first][last][top][bottom][index][help]  */
 446 {
 447     // given
 448     only_in_selection = TRUE;
 449     replace_regex__from = &replace_regex_entire_string__from;
 450     replace_regex__to = &replace_regex_entire_string__to;
 451     test_edit->mark1 = 20;
 452     test_edit->mark2 = 9;
 453 
 454     for (const char *ti = test_regex_selected_in; *ti != '\0'; ti++)
 455         edit_buffer_insert (&test_edit->buffer, *ti);
 456 
 457     // when
 458     edit_cursor_move (test_edit, 0);
 459     edit_replace_cmd (test_edit, FALSE);
 460 
 461     // then
 462     test_replace_check (test2_regex_selected_out);
 463 }
 464 END_TEST
 465 
 466 /* --------------------------------------------------------------------------------------------- */
 467 
 468 int
 469 main (void)
     /* [previous][next][first][last][top][bottom][index][help]  */
 470 {
 471     TCase *tc_core;
 472 
 473     tc_core = tcase_create ("Core");
 474 
 475     tcase_add_checked_fixture (tc_core, setup, teardown);
 476 
 477     // Add new tests here: ***************
 478     tcase_add_test (tc_core, test_replace_regex__entire_string);
 479     tcase_add_test (tc_core, test_replace_regex__insert_char_at_begin_of_string);
 480     tcase_add_test (tc_core, test_replace_regex__replace_first_char_of_string);
 481     tcase_add_test (tc_core, test_replace_regex__in_selection_top_down_1);
 482     tcase_add_test (tc_core, test_replace_regex__in_selection_top_down_2);
 483     tcase_add_test (tc_core, test_replace_regex__in_selection_bottom_up_1);
 484     tcase_add_test (tc_core, test_replace_regex__in_selection_bottom_up_2);
 485     // ***********************************
 486 
 487     return mctest_run_all (tc_core);
 488 }
 489 
 490 /* --------------------------------------------------------------------------------------------- */

/* [previous][next][first][last][top][bottom][index][help]  */