Extract match_outer_shape() function in 'remove' module

This commit is contained in:
Thomas Jensen 2023-07-31 22:10:29 +02:00
parent c4982a15df
commit cde5ecc26a
No known key found for this signature in database
GPG Key ID: A4ACEE270D0FB7DB
6 changed files with 511 additions and 39 deletions

View File

@ -94,14 +94,11 @@ typedef struct _remove_ctx_t {
typedef struct _shape_line_ctx_t {
/** flag indicating whether the shape is empty */
/** flag indicating whether the (entire!) shape is empty */
int empty;
/** one line of a shape, possibly trimmed, with invisible characters filtered according to the comparison type */
uint32_t *text;
/** the length of `text` in characters */
size_t length;
/** one line of a shape, with invisible characters filtered according to the comparison type */
bxstr_t *text;
/** flag indicating whether the shape to which this line belongs is elastic */
int elastic;
@ -170,13 +167,13 @@ static int hmm(shape_line_ctx_t *shapes_relevant, uint32_t *cur_pos, size_t shap
else if (shapes_relevant[shape_idx].empty) {
result = hmm(shapes_relevant, cur_pos, shape_idx + 1, end_pos);
}
else if (u32_strncmp(cur_pos, shapes_relevant[shape_idx].text, shapes_relevant[shape_idx].length) == 0) {
else if (u32_strncmp(cur_pos, shapes_relevant[shape_idx].text->memory, shapes_relevant[shape_idx].text->num_chars) == 0) {
int rc = 0;
if (shapes_relevant[shape_idx].elastic) {
rc = hmm(shapes_relevant, cur_pos + shapes_relevant[shape_idx].length, shape_idx, end_pos);
rc = hmm(shapes_relevant, cur_pos + shapes_relevant[shape_idx].text->num_chars, shape_idx, end_pos);
}
if (rc == 0) {
result = hmm(shapes_relevant, cur_pos + shapes_relevant[shape_idx].length, shape_idx + 1, end_pos);
result = hmm(shapes_relevant, cur_pos + shapes_relevant[shape_idx].text->num_chars, shape_idx + 1, end_pos);
}
}
@ -196,10 +193,11 @@ static shape_line_ctx_t *prepare_comp_shapes_horiz(int hside, comparison_t comp_
for (size_t i = 0; i < SHAPES_PER_SIDE; i++) {
shapes_relevant[i].empty = isempty(opt.design->shape + side_shapes[i]);
if (!shapes_relevant[i].empty) {
shapes_relevant[i].text = prepare_comp_shape(opt.design, side_shapes[i], shape_line_idx, comp_type, 0,
uint32_t *s = prepare_comp_shape(opt.design, side_shapes[i], shape_line_idx, comp_type, 0,
i == SHAPES_PER_SIDE - 1);
shapes_relevant[i].length = u32_strlen(shapes_relevant[i].text);
shapes_relevant[i].text = bxs_from_unicode(s);
shapes_relevant[i].elastic = opt.design->shape[side_shapes[i]].elastic;
BFREE(s);
}
}
@ -207,6 +205,73 @@ static shape_line_ctx_t *prepare_comp_shapes_horiz(int hside, comparison_t comp_
}
static match_result_t *new_match_result(uint32_t *p, size_t p_idx, size_t len, int shiftable)
{
match_result_t *result = (match_result_t *) calloc(1, sizeof(match_result_t));
result->p = p;
result->p_idx = p_idx;
result->len = len;
result->shiftable = shiftable;
return result;
}
/**
* Match a `shape_line` at the beginning (`vside` == `BLEF`) or the end (`vside` == `BRIG`) of an `input_line`.
* Both `input_line` and `shape_line` may contain invisible characters, who are then matched, too, just like any other
* characters.
* @param vside BLEF or BRIG
* @param input_line the input line to examine. We expect that it was NOT trimmed.
* @param shape_line the shape line to match, also NOT trimmed
* @return pointer to the match result (in existing memory of `input_line->memory`), or `NULL` if no match
*/
match_result_t *match_outer_shape(int vside, bxstr_t *input_line, bxstr_t *shape_line)
{
if (input_line == NULL || shape_line == NULL) {
return NULL;
}
if (vside == BLEF) {
if (bxs_is_blank(shape_line)) {
return new_match_result(input_line->memory, 0, 0, 1);
}
for (uint32_t *s = shape_line->memory; s == shape_line->memory || is_blank(*s); s++) {
uint32_t *p = u32_strstr(input_line->memory, s);
size_t p_idx = p != NULL ? p - input_line->memory : 0;
if (p == NULL || p_idx > input_line->first_char[input_line->indent]) {
continue; /* not found or found too far in */
}
return new_match_result(p, p_idx, shape_line->num_chars - (s - shape_line->memory), 0);
}
}
else {
if (bxs_is_blank(shape_line)) {
uint32_t *p = bxs_last_char_ptr(input_line);
size_t p_idx = p - input_line->memory;
return new_match_result(p, p_idx, 0, 1);
}
int slen = shape_line->num_chars;
uint32_t *s = u32_strdup(shape_line->memory);
for (; slen == (int) shape_line->num_chars || is_blank(s[slen]); slen--) {
s[slen] = char_nul;
uint32_t *p = u32_strnrstr(input_line->memory, s, slen, 0);
size_t p_idx = p != NULL ? p - input_line->memory : 0;
if (p == NULL || p_idx + slen
< input_line->first_char[input_line->num_chars_visible - input_line->trailing]) {
continue; /* not found or found too far in */
}
BFREE(s);
return new_match_result(p, p_idx, (size_t) slen, 0);
}
BFREE(s);
}
return NULL;
}
// TODO gdb --args out/boxes -n UTF-8 -d diamonds -ac -m test/117_unicode_ansi_mending.input.tmp
static int match_horiz_line(remove_ctx_t *ctx, int hside, size_t input_line_idx, size_t shape_line_idx)
{
@ -229,8 +294,8 @@ static int match_horiz_line(remove_ctx_t *ctx, int hside, size_t input_line_idx,
fprintf(stderr, "-");
}
else {
char *out_shp_text = u32_strconv_to_output(shapes_relevant[ds].text);
fprintf(stderr, "\"%s\"(%d%s)", out_shp_text, (int) shapes_relevant[ds].length,
char *out_shp_text = bxs_to_output(shapes_relevant[ds].text);
fprintf(stderr, "\"%s\"(%d%s)", out_shp_text, (int) shapes_relevant[ds].text->num_chars,
shapes_relevant[ds].elastic ? "E" : "");
BFREE(out_shp_text);
}
@ -242,36 +307,36 @@ static int match_horiz_line(remove_ctx_t *ctx, int hside, size_t input_line_idx,
#endif
uint32_t *cur_pos = NULL;
uint32_t *input_prepped = prepare_comp_input(input_line_idx, 0, comp_type, 0, NULL, NULL);
bxstr_t *input_prepped = bxs_from_unicode(prepare_comp_input(input_line_idx, 0, comp_type, 0, NULL, NULL));
#ifdef DEBUG
char *out_input_prepped = u32_strconv_to_output(input_prepped);
char *out_input_prepped = bxs_to_output(input_prepped);
fprintf(stderr, " input_prepped = \"%s\"\n", out_input_prepped);
BFREE(out_input_prepped);
#endif
if (input_prepped != NULL && (shapes_relevant[0].length == 0
|| u32_strncmp(input_prepped, shapes_relevant[0].text, shapes_relevant[0].length) == 0))
if (input_prepped != NULL && (shapes_relevant[0].text->num_chars == 0
|| u32_strncmp(input_prepped->memory, shapes_relevant[0].text->memory, shapes_relevant[0].text->num_chars) == 0))
{
cur_pos = input_prepped + shapes_relevant[0].length; // TODO check cur_pos and end_pos
cur_pos = input_prepped->memory + shapes_relevant[0].text->num_chars; // TODO check cur_pos and end_pos
}
uint32_t *end_pos = NULL;
input_prepped = prepare_comp_input(
input_line_idx, 0, comp_type, shapes_relevant[SHAPES_PER_SIDE - 1].length, NULL, NULL);
input_prepped = bxs_from_unicode(prepare_comp_input(
input_line_idx, 0, comp_type, shapes_relevant[SHAPES_PER_SIDE - 1].text->num_chars, NULL, NULL));
if (input_prepped != NULL) {
if (shapes_relevant[SHAPES_PER_SIDE - 1].length == 0) {
end_pos = input_prepped + u32_strlen(input_prepped); // point to NUL terminator
if (shapes_relevant[SHAPES_PER_SIDE - 1].text->num_chars == 0) {
end_pos = input_prepped->memory + input_prepped->num_chars; // point to NUL terminator
}
else if (u32_strncmp(input_prepped, shapes_relevant[SHAPES_PER_SIDE - 1].text,
shapes_relevant[SHAPES_PER_SIDE - 1].length) == 0)
else if (u32_strncmp(input_prepped->memory, shapes_relevant[SHAPES_PER_SIDE - 1].text->memory,
shapes_relevant[SHAPES_PER_SIDE - 1].text->num_chars) == 0)
{
end_pos = input_prepped;
end_pos = input_prepped->memory;
}
}
#ifdef DEBUG
char *out_cur_pos = u32_strconv_to_output(cur_pos);
char *out_end_pos = u32_strconv_to_output(end_pos);
fprintf(stderr, " cur_pos = \"%s\" (index %d)\n", out_cur_pos, (int) BMAX(cur_pos - input_prepped, 0));
fprintf(stderr, " end_pos = \"%s\" (index %d)\n", out_end_pos, (int) BMAX(end_pos - input_prepped, 0));
fprintf(stderr, " cur_pos = \"%s\" (index %d)\n", out_cur_pos, (int) BMAX(cur_pos - input_prepped->memory, 0));
fprintf(stderr, " end_pos = \"%s\" (index %d)\n", out_end_pos, (int) BMAX(end_pos - input_prepped->memory, 0));
BFREE(out_cur_pos);
BFREE(out_end_pos);
#endif
@ -281,7 +346,7 @@ static int match_horiz_line(remove_ctx_t *ctx, int hside, size_t input_line_idx,
}
for (size_t i = 0; i < SHAPES_PER_SIDE; i++) {
BFREE(shapes_relevant[i].text);
bxs_free(shapes_relevant[i].text);
}
BFREE(shapes_relevant);
@ -384,12 +449,14 @@ static shape_line_ctx_t **prepare_comp_shapes_vert(int vside, comparison_t comp_
for (size_t shape_idx = 0, i = 0; shape_idx < SHAPES_PER_SIDE - CORNERS_PER_SIDE; shape_idx++) {
if (!isempty(opt.design->shape + side_shapes[shape_idx])) {
int deep_empty = isdeepempty(opt.design->shape + side_shapes[shape_idx]);
shape_lines[i] = (shape_line_ctx_t *) calloc(1, sizeof(shape_line_ctx_t));
for (size_t slno = 0; slno < opt.design->shape[side_shapes[shape_idx]].height; slno++, i++) {
shape_lines[i]->text = prepare_comp_shape(opt.design, side_shapes[shape_idx], slno, comp_type, 0, 0);
shape_lines[i]->empty = u32_is_blank(shape_lines[i]->text);
shape_lines[i]->length = u32_strlen(shape_lines[i]->text);
uint32_t *s = prepare_comp_shape(opt.design, side_shapes[shape_idx], slno, comp_type, 0, 0);
shape_lines[i]->text = bxs_from_unicode(s);
shape_lines[i]->empty = deep_empty;
shape_lines[i]->elastic = opt.design->shape[side_shapes[shape_idx]].elastic;
BFREE(s);
}
}
}
@ -403,7 +470,7 @@ static void free_shape_lines(shape_line_ctx_t **shape_lines)
{
if (shape_lines != NULL) {
for (shape_line_ctx_t **p = shape_lines; *p != NULL; p++) {
BFREE((*p)->text);
bxs_free((*p)->text);
BFREE(*p);
}
BFREE(shape_lines);
@ -421,9 +488,9 @@ static void free_shape_lines(shape_line_ctx_t **shape_lines)
*/
static uint32_t *shorten(shape_line_ctx_t *shape_line_ctx, size_t *quality, int prefer_left)
{
uint32_t *s = shape_line_ctx->text;
uint32_t *e = shape_line_ctx->text + shape_line_ctx->length;
size_t reduction_steps = shape_line_ctx->length - *quality + 1;
uint32_t *s = shape_line_ctx->text->memory;
uint32_t *e = shape_line_ctx->text->memory + shape_line_ctx->text->num_chars;
size_t reduction_steps = shape_line_ctx->text->num_chars - *quality + 1;
for (size_t i = 0; i < reduction_steps; i++) {
if (prefer_left) {
if (is_blank(*s) && s < e) {
@ -471,9 +538,9 @@ static void match_vertical_side(remove_ctx_t *ctx, int vside, shape_line_ctx_t *
continue;
}
size_t max_quality = (*shape_line_ctx)->length;
size_t max_quality = (*shape_line_ctx)->text->num_chars;
size_t quality = max_quality;
uint32_t *shape_text = (*shape_line_ctx)->text;
uint32_t *shape_text = (*shape_line_ctx)->text->memory;
uint32_t *to_free = NULL;
while(shape_text != NULL) {
uint32_t *p;

View File

@ -21,6 +21,23 @@
#define REMOVE_H
/** the result of a match operation at the beginning or end of a line */
typedef struct _match_result_t {
/** pointer to the matched position */
uint32_t *p;
/** index of the matched position in the haystack string */
size_t p_idx;
/** number of characters matched (between 1 and shape_line->num_chars) */
size_t len;
/** flag indicating the match was secured by including non-blank characters (0) or only blanks were matched (1) */
int shiftable;
} match_result_t;
/**
* Remove box from input.
* @return == 0: success;

View File

@ -19,8 +19,8 @@ SRC_DIR = ../src
UTEST_DIR = ../utest
VPATH = $(SRC_DIR):$(SRC_DIR)/misc:$(UTEST_DIR)
UTEST_NORM = global_mock.c bxstring_test.o cmdline_test.c tools_test.c regulex_test.o main.o unicode_test.o \
utest_tools.o
UTEST_NORM = global_mock.c bxstring_test.o cmdline_test.c tools_test.c regulex_test.o remove_test.o main.o \
unicode_test.o utest_tools.o
.PHONY: check_dir flags_unix flags_win32 flags_ utest
@ -71,6 +71,7 @@ bxstring_test.o: bxstring_test.c bxstring_test.h boxes.h bxstring.h global_mock.
cmdline_test.o: cmdline_test.c cmdline_test.h boxes.h cmdline.h global_mock.h tools.h config.h | check_dir
tools_test.o: tools_test.c tools_test.h tools.h unicode.h config.h | check_dir
regulex_test.o: regulex_test.c regulex_test.h boxes.h global_mock.h regulex.h config.h | check_dir
remove_test.o: remove_test.c remove_test.h boxes.h remove.h tools.h unicode.h global_mock.h utest_tools.h config.h | check_dir
main.o: main.c bxstring_test.h cmdline_test.h global_mock.h tools_test.h regulex_test.h unicode_test.h config.h | check_dir
unicode_test.o: unicode_test.c unicode_test.h boxes.h tools.h unicode.h config.h | check_dir
utest_tools.o: utest_tools.c utest_tools.h config.h | check_dir

View File

@ -30,6 +30,7 @@
#include "cmdline_test.h"
#include "tools_test.h"
#include "regulex_test.h"
#include "remove_test.h"
#include "unicode_test.h"
@ -178,12 +179,31 @@ int main(void)
cmocka_unit_test_setup(test_bxs_concat_nullarg, beforeTest)
};
const struct CMUnitTest remove_tests[] = {
cmocka_unit_test_setup(test_match_outer_shape_null, beforeTest),
cmocka_unit_test_setup(test_match_outer_shape_left_anchored, beforeTest),
cmocka_unit_test_setup(test_match_outer_shape_left_shiftable, beforeTest),
cmocka_unit_test_setup(test_match_outer_shape_left_shortened, beforeTest),
cmocka_unit_test_setup(test_match_outer_shape_left_not_found, beforeTest),
cmocka_unit_test_setup(test_match_outer_shape_left_too_far_in, beforeTest),
cmocka_unit_test_setup(test_match_outer_shape_left_edge, beforeTest),
cmocka_unit_test_setup(test_match_outer_shape_right_anchored, beforeTest),
cmocka_unit_test_setup(test_match_outer_shape_right_shiftable, beforeTest),
cmocka_unit_test_setup(test_match_outer_shape_right_shortened, beforeTest),
cmocka_unit_test_setup(test_match_outer_shape_right_shortened2, beforeTest),
cmocka_unit_test_setup(test_match_outer_shape_right_not_found, beforeTest),
cmocka_unit_test_setup(test_match_outer_shape_right_too_far_in, beforeTest),
cmocka_unit_test_setup(test_match_outer_shape_right_edge, beforeTest)
};
int num_failed = 0;
num_failed += cmocka_run_group_tests(cmdline_tests, NULL, NULL);
num_failed += cmocka_run_group_tests(regulex_tests, NULL, NULL);
num_failed += cmocka_run_group_tests(tools_tests, NULL, NULL);
num_failed += cmocka_run_group_tests(unicode_tests, NULL, NULL);
num_failed += cmocka_run_group_tests(bxstring_tests, NULL, NULL);
num_failed += cmocka_run_group_tests(remove_tests, NULL, NULL);
teardown();
return num_failed;

318
utest/remove_test.c Normal file
View File

@ -0,0 +1,318 @@
/*
* boxes - Command line filter to draw/remove ASCII boxes around text
* Copyright (c) 1999-2023 Thomas Jensen and the boxes contributors
*
* This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public
* License, version 3, as published by the Free Software Foundation.
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied
* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
* details.
* You should have received a copy of the GNU General Public License along with this program.
* If not, see <https://www.gnu.org/licenses/>.
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
*/
/*
* Unit tests of the 'remove' module
*/
#include "config.h"
#include <setjmp.h>
#include <stdarg.h>
#include <stddef.h>
#include <unistr.h>
#include <cmocka.h>
#include "boxes.h"
#include "unicode.h"
#include "tools.h"
#include "remove_test.h"
#include "global_mock.h"
#include "utest_tools.h"
void test_match_outer_shape_null(void **state)
{
UNUSED(state);
bxstr_t *input_line = bxs_from_ascii(" xx x xx ");
bxstr_t *shape_line = bxs_from_ascii(" xx ");
match_result_t *actual = match_outer_shape(BLEF, NULL, shape_line);
assert_null(actual);
actual = match_outer_shape(BLEF, input_line, NULL);
assert_null(actual);
bxs_free(input_line);
bxs_free(shape_line);
}
void test_match_outer_shape_left_anchored(void **state)
{
UNUSED(state);
bxstr_t *input_line = bxs_from_ascii(" xx x xx ");
bxstr_t *shape_line = bxs_from_ascii(" xx ");
match_result_t *actual = match_outer_shape(BLEF, input_line, shape_line);
uint32_t *expected_p = bxs_first_char_ptr(input_line, 3);
assert_non_null(actual);
assert_int_equal(3, (int) actual->p_idx);
assert_int_equal(0, u32_strcmp(expected_p, actual->p));
assert_int_equal(4, actual->len);
assert_int_equal(0, actual->shiftable);
BFREE(actual);
bxs_free(input_line);
bxs_free(shape_line);
}
void test_match_outer_shape_left_shiftable(void **state)
{
UNUSED(state);
bxstr_t *input_line = bxs_from_ascii(" xx x xx ");
bxstr_t *shape_line = bxs_from_ascii(" ");
match_result_t *actual = match_outer_shape(BLEF, input_line, shape_line);
assert_non_null(actual);
assert_int_equal(0, (int) actual->p_idx);
assert_int_equal(0, u32_strcmp(input_line->memory, actual->p));
assert_int_equal(0, actual->len);
assert_int_equal(1, actual->shiftable);
BFREE(actual);
bxs_free(input_line);
bxs_free(shape_line);
}
void test_match_outer_shape_left_shortened(void **state)
{
UNUSED(state);
bxstr_t *input_line = bxs_from_ascii(" xx x xx ");
bxstr_t *shape_line = bxs_from_ascii(" xx"); /* length 6 */
match_result_t *actual = match_outer_shape(BLEF, input_line, shape_line);
assert_non_null(actual);
assert_int_equal(0, (int) actual->p_idx);
assert_int_equal(0, u32_strcmp(input_line->memory, actual->p));
assert_int_equal(4, actual->len); /* only 4 characters matched */
assert_int_equal(0, actual->shiftable);
BFREE(actual);
bxs_free(input_line);
bxs_free(shape_line);
}
void test_match_outer_shape_left_not_found(void **state)
{
UNUSED(state);
bxstr_t *input_line = bxs_from_ascii(" xx x xx ");
bxstr_t *shape_line = bxs_from_ascii(" ---");
match_result_t *actual = match_outer_shape(BLEF, input_line, shape_line);
assert_null(actual);
bxs_free(input_line);
bxs_free(shape_line);
}
void test_match_outer_shape_left_too_far_in(void **state)
{
UNUSED(state);
bxstr_t *input_line = bxs_from_ascii(" xx M xx ");
bxstr_t *shape_line = bxs_from_ascii("x M");
match_result_t *actual = match_outer_shape(BLEF, input_line, shape_line);
assert_null(actual);
bxs_free(input_line);
bxs_free(shape_line);
}
void test_match_outer_shape_left_edge(void **state)
{
UNUSED(state);
bxstr_t *input_line = bxs_from_ascii(" x yy");
bxstr_t *shape_line = bxs_from_ascii("x");
match_result_t *actual = match_outer_shape(BLEF, input_line, shape_line);
uint32_t *expected_p = bxs_first_char_ptr(input_line, 3);
assert_non_null(actual);
assert_int_equal(3, (int) actual->p_idx);
assert_int_equal(0, u32_strcmp(expected_p, actual->p));
assert_int_equal(1, actual->len);
assert_int_equal(0, actual->shiftable);
BFREE(actual);
bxs_free(input_line);
bxs_free(shape_line);
}
void test_match_outer_shape_right_anchored(void **state)
{
UNUSED(state);
bxstr_t *input_line = bxs_from_ascii(" xx x xx ");
bxstr_t *shape_line = bxs_from_ascii(" xx ");
match_result_t *actual = match_outer_shape(BRIG, input_line, shape_line);
uint32_t *expected_p = bxs_first_char_ptr(input_line, 8);
assert_non_null(actual);
assert_int_equal(8, (int) actual->p_idx);
assert_int_equal(0, u32_strcmp(expected_p, actual->p));
assert_int_equal(4, actual->len);
assert_int_equal(0, actual->shiftable);
BFREE(actual);
bxs_free(input_line);
bxs_free(shape_line);
}
void test_match_outer_shape_right_shiftable(void **state)
{
UNUSED(state);
bxstr_t *input_line = bxs_from_ascii(" xx x xx ");
bxstr_t *shape_line = bxs_from_ascii(" ");
match_result_t *actual = match_outer_shape(BRIG, input_line, shape_line);
assert_non_null(actual);
assert_int_equal(15, (int) actual->p_idx);
assert_int_equal(1, is_char_at(actual->p, 0, char_nul));
assert_int_equal(0, actual->len);
assert_int_equal(1, actual->shiftable);
BFREE(actual);
bxs_free(input_line);
bxs_free(shape_line);
}
void test_match_outer_shape_right_shortened(void **state)
{
UNUSED(state);
bxstr_t *input_line = bxs_from_ascii(" xx x xx ");
bxstr_t *shape_line = bxs_from_ascii("xx "); /* length 6 */
match_result_t *actual = match_outer_shape(BRIG, input_line, shape_line);
uint32_t *expected_p = bxs_first_char_ptr(input_line, 7);
assert_non_null(actual);
assert_int_equal(7, (int) actual->p_idx);
assert_int_equal(0, u32_strcmp(expected_p, actual->p));
assert_int_equal(4, actual->len); /* only 4 characters matched */
assert_int_equal(0, actual->shiftable);
BFREE(actual);
bxs_free(input_line);
bxs_free(shape_line);
}
void test_match_outer_shape_right_not_found(void **state)
{
UNUSED(state);
bxstr_t *input_line = bxs_from_ascii(" xx x xx ");
bxstr_t *shape_line = bxs_from_ascii("--- ");
match_result_t *actual = match_outer_shape(BRIG, input_line, shape_line);
assert_null(actual);
bxs_free(input_line);
bxs_free(shape_line);
}
void test_match_outer_shape_right_too_far_in(void **state)
{
UNUSED(state);
bxstr_t *input_line = bxs_from_ascii(" xx M xx ");
bxstr_t *shape_line = bxs_from_ascii("M x");
match_result_t *actual = match_outer_shape(BRIG, input_line, shape_line);
assert_null(actual);
bxs_free(input_line);
bxs_free(shape_line);
}
void test_match_outer_shape_right_shortened2(void **state)
{
UNUSED(state);
bxstr_t *input_line = bxs_from_ascii(" x Y");
bxstr_t *shape_line = bxs_from_ascii("Y ");
match_result_t *actual = match_outer_shape(BRIG, input_line, shape_line);
uint32_t *expected_p = bxs_first_char_ptr(input_line, 4);
assert_non_null(actual);
assert_int_equal(4, (int) actual->p_idx);
assert_int_equal(0, u32_strcmp(expected_p, actual->p));
assert_int_equal(1, actual->len);
assert_int_equal(0, actual->shiftable);
BFREE(actual);
bxs_free(input_line);
bxs_free(shape_line);
}
void test_match_outer_shape_right_edge(void **state)
{
UNUSED(state);
bxstr_t *input_line = bxs_from_ascii("x");
bxstr_t *shape_line = bxs_from_ascii("x");
match_result_t *actual = match_outer_shape(BRIG, input_line, shape_line);
assert_non_null(actual);
assert_int_equal(0, (int) actual->p_idx);
assert_int_equal(0, u32_strcmp(input_line->memory, actual->p));
assert_int_equal(1, actual->len);
assert_int_equal(0, actual->shiftable);
BFREE(actual);
bxs_free(input_line);
bxs_free(shape_line);
}
/* vim: set cindent sw=4: */

49
utest/remove_test.h Normal file
View File

@ -0,0 +1,49 @@
/*
* boxes - Command line filter to draw/remove ASCII boxes around text
* Copyright (c) 1999-2023 Thomas Jensen and the boxes contributors
*
* This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public
* License, version 3, as published by the Free Software Foundation.
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied
* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
* details.
* You should have received a copy of the GNU General Public License along with this program.
* If not, see <https://www.gnu.org/licenses/>.
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
*/
/*
* Unit tests of the 'remove' module
*/
#ifndef REMOVE_TEST_H
#define REMOVE_TEST_H
#include "bxstring.h"
#include "remove.h"
/* defined here and not in remove.h because it's only visible for testing */
match_result_t *match_outer_shape(int vside, bxstr_t *input_line, bxstr_t *shape_line);
void test_match_outer_shape_null(void **state);
void test_match_outer_shape_left_anchored(void **state);
void test_match_outer_shape_left_shiftable(void **state);
void test_match_outer_shape_left_shortened(void **state);
void test_match_outer_shape_left_not_found(void **state);
void test_match_outer_shape_left_too_far_in(void **state);
void test_match_outer_shape_left_edge(void **state);
void test_match_outer_shape_right_anchored(void **state);
void test_match_outer_shape_right_shiftable(void **state);
void test_match_outer_shape_right_shortened(void **state);
void test_match_outer_shape_right_shortened2(void **state);
void test_match_outer_shape_right_not_found(void **state);
void test_match_outer_shape_right_too_far_in(void **state);
void test_match_outer_shape_right_edge(void **state);
#endif
/* vim: set cindent sw=4: */