File size: 7,206 Bytes
78d2150 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 |
#include "../../unity/unity.h"
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
/* We rely on being included after the fmt implementation, so we can
access static functions and globals like get_paragraph, set_prefix,
get_prefix, word, word_limit, etc. */
/* Helper: persistent buffer for set_prefix. */
static char prefix_buf[64];
/* Reset core global state to a known baseline before each test. */
static void reset_state(void)
{
/* Options */
crown = false;
tagged = false;
split = false;
uniform = false;
/* Prefix: empty */
strcpy(prefix_buf, "");
set_prefix(prefix_buf);
/* Widths: defaults safe; fmt_paragraph isn't called by get_paragraph,
but keep sane values anyway. */
max_width = 75; /* WIDTH */
goal_width = (max_width * (100 - 7)) / 100; /* LEEWAY = 7 */
/* Dynamic state */
in_column = 0;
out_column = 0;
tabs = false;
prefix_indent = 0;
first_indent = 0;
other_indent = 0;
next_char = 0;
next_prefix_indent = 0;
last_line_length = 0;
/* Paragraph buffers */
wptr = parabuf;
word_limit = word;
}
/* Helper: create a FILE* from a string using tmpfile. */
static FILE *make_file(const char *s)
{
FILE *f = tmpfile();
TEST_ASSERT_NOT_NULL_MESSAGE(f, "tmpfile() failed");
if (fputs(s, f) == EOF)
{
fclose(f);
TEST_FAIL_MESSAGE("fputs() to tmpfile failed");
}
rewind(f);
return f;
}
/* Count words currently parsed for the paragraph. */
static int count_words(void)
{
return (int)(word_limit - word);
}
void setUp(void)
{
/* Setup code here */
reset_state();
}
void tearDown(void)
{
/* Cleanup code here */
}
/* 1) Basic: single-line paragraph, no prefix, default mode */
static void test_get_paragraph_basic_single_line(void)
{
const char *input = "hello world\n\n"; /* paragraph then blank line */
FILE *f = make_file(input);
/* Initialize next_char as fmt() would */
next_char = get_prefix(f);
TEST_ASSERT_TRUE_MESSAGE(get_paragraph(f), "get_paragraph should find a paragraph");
/* Should have parsed two words: hello, world */
TEST_ASSERT_EQUAL_INT(2, count_words());
/* Indentation expectations */
TEST_ASSERT_EQUAL_INT(0, prefix_indent);
TEST_ASSERT_EQUAL_INT(0, first_indent);
TEST_ASSERT_EQUAL_INT(0, other_indent);
/* Words content and flags */
TEST_ASSERT_EQUAL_INT(5, word[0].length);
TEST_ASSERT_TRUE(!word[0].final);
TEST_ASSERT_TRUE(word_limit[-1].final);
TEST_ASSERT_TRUE(word_limit[-1].period); /* get_paragraph forces last word period=true */
/* After paragraph, next_char should be '\n' for the following blank line */
TEST_ASSERT_EQUAL_INT('\n', next_char);
fclose(f);
}
/* 2) Crown mode: second+ lines must have same indent as second line */
static void test_get_paragraph_crown_mode(void)
{
crown = true;
const char *input =
"one\n"
" two words\n"
" three\n"
" four\n"; /* fourth line different indent -> next paragraph */
FILE *f = make_file(input);
next_char = get_prefix(f);
TEST_ASSERT_TRUE_MESSAGE(get_paragraph(f), "crown: should read a paragraph");
/* First three lines included: 1 + 2 + 1 = 4 words */
TEST_ASSERT_EQUAL_INT(4, count_words());
/* First line indent 0, secondary indent equals second line's indent (2). */
TEST_ASSERT_EQUAL_INT(0, first_indent);
TEST_ASSERT_EQUAL_INT(2, other_indent);
/* Next char should be 'f' from " four" */
TEST_ASSERT_EQUAL_INT('f', next_char);
/* Last word of the paragraph is final and period-marked by get_paragraph */
TEST_ASSERT_TRUE(word_limit[-1].final);
TEST_ASSERT_TRUE(word_limit[-1].period);
fclose(f);
}
/* 3) Tagged mode: first and second lines must have different indents.
If equal, paragraph is just the first line, and other_indent updated. */
static void test_get_paragraph_tagged_mode_requires_diff_indent(void)
{
tagged = true;
const char *input =
"first\n"
"second\n"; /* same indent (0), so only first line included */
FILE *f = make_file(input);
next_char = get_prefix(f);
TEST_ASSERT_TRUE_MESSAGE(get_paragraph(f), "tagged: should read a paragraph");
/* Only the first line included: 1 word */
TEST_ASSERT_EQUAL_INT(1, count_words());
/* First indent 0; other_indent should become DEF_INDENT when identical */
TEST_ASSERT_EQUAL_INT(0, first_indent);
TEST_ASSERT_EQUAL_INT(DEF_INDENT, other_indent);
/* Next paragraph starts at 's' from second line */
TEST_ASSERT_EQUAL_INT('s', next_char);
fclose(f);
}
/* 4) Split-only mode: a paragraph is a single non-blank line */
static void test_get_paragraph_split_only_single_line(void)
{
split = true;
const char *input =
"aaa bbb\n"
"ccc ddd\n";
FILE *f = make_file(input);
next_char = get_prefix(f);
TEST_ASSERT_TRUE_MESSAGE(get_paragraph(f), "split: should read a single-line paragraph");
/* Only first line included: 2 words */
TEST_ASSERT_EQUAL_INT(2, count_words());
/* other_indent must equal first_indent in split mode */
TEST_ASSERT_EQUAL_INT(first_indent, other_indent);
/* Next char should be 'c' from second line */
TEST_ASSERT_EQUAL_INT('c', next_char);
fclose(f);
}
/* 5) Prefix handling: lines must begin with the prefix; words exclude the prefix. */
static void test_get_paragraph_with_prefix_included_lines(void)
{
/* Set a non-empty prefix ">>" */
strcpy(prefix_buf, ">>");
set_prefix(prefix_buf);
const char *input =
">> a b\n"
">> c\n";
FILE *f = make_file(input);
next_char = get_prefix(f);
TEST_ASSERT_TRUE_MESSAGE(get_paragraph(f), "prefix: should read a paragraph with prefixed lines");
/* Words from after the prefix should be captured: a, b, c */
TEST_ASSERT_EQUAL_INT(3, count_words());
/* The first word should be 'a' */
TEST_ASSERT_EQUAL_INT(1, word[0].length);
TEST_ASSERT_EQUAL_CHAR('a', word[0].text[0]);
/* prefix_indent should be 0 given no leading spaces before prefix */
TEST_ASSERT_EQUAL_INT(0, prefix_indent);
/* Next char should be EOF (end of file) */
TEST_ASSERT_EQUAL_INT(EOF, next_char);
/* Last word flags */
TEST_ASSERT_TRUE(word_limit[-1].final);
TEST_ASSERT_TRUE(word_limit[-1].period);
fclose(f);
}
/* 6) EOF before any paragraph: should return false and not touch buffers */
static void test_get_paragraph_empty_file_returns_false(void)
{
const char *input = ""; /* empty file */
FILE *f = make_file(input);
next_char = get_prefix(f); /* sets to EOF */
TEST_ASSERT_FALSE_MESSAGE(get_paragraph(f), "Empty file: should return false");
fclose(f);
}
int main(void)
{
UNITY_BEGIN();
RUN_TEST(test_get_paragraph_basic_single_line);
RUN_TEST(test_get_paragraph_crown_mode);
RUN_TEST(test_get_paragraph_tagged_mode_requires_diff_indent);
RUN_TEST(test_get_paragraph_split_only_single_line);
RUN_TEST(test_get_paragraph_with_prefix_included_lines);
RUN_TEST(test_get_paragraph_empty_file_returns_false);
return UNITY_END();
} |