aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorGravatar ridiculousfish <corydoras@ridiculousfish.com>2015-04-25 18:47:17 -0700
committerGravatar ridiculousfish <corydoras@ridiculousfish.com>2015-04-25 18:47:17 -0700
commit3d9c24196dab141699bded97e78bce35f8dc27d1 (patch)
tree26068535e4d1fa1219e49e331a561fe978746df3
parent6f438f65de2b56e1d12bb0597cc48c83a1607308 (diff)
Add test for error messages
Preparation for issue #1228
-rw-r--r--fish_tests.cpp107
1 files changed, 107 insertions, 0 deletions
diff --git a/fish_tests.cpp b/fish_tests.cpp
index e3615eba..f5bca44c 100644
--- a/fish_tests.cpp
+++ b/fish_tests.cpp
@@ -3501,7 +3501,113 @@ static void test_new_parser_errors(void)
}
}
+}
+
+/* Given a format string, returns a list of non-empty strings separated by format specifiers. The format specifiers themselves are omitted. */
+static wcstring_list_t separate_by_format_specifiers(const wchar_t *format)
+{
+ wcstring_list_t result;
+ const wchar_t *cursor = format;
+ const wchar_t *end = format + wcslen(format);
+ while (cursor < end)
+ {
+ const wchar_t *next_specifier = wcschr(cursor, '%');
+ if (next_specifier == NULL)
+ {
+ next_specifier = end;
+ }
+ assert(next_specifier != NULL);
+
+ /* Don't return empty strings */
+ if (next_specifier > cursor)
+ {
+ result.push_back(wcstring(cursor, next_specifier - cursor));
+ }
+
+ /* Walk over the format specifier (if any) */
+ cursor = next_specifier;
+ if (*cursor == '%')
+ {
+ cursor++;
+ // Flag
+ if (wcschr(L"#0- +'", *cursor))
+ cursor++;
+ // Minimum field width
+ while (iswdigit(*cursor))
+ cursor++;
+ // Precision
+ if (*cursor == L'.')
+ {
+ cursor++;
+ while (iswdigit(*cursor))
+ cursor++;
+ }
+ // Length modifier
+ if (! wcsncmp(cursor, L"ll", 2) || ! wcsncmp(cursor, L"hh", 2))
+ {
+ cursor += 2;
+ }
+ else if (wcschr(L"hljtzqL", *cursor))
+ {
+ cursor++;
+ }
+ // The format specifier itself. We allow any character except NUL
+ if (*cursor != L'\0')
+ {
+ cursor += 1;
+ }
+ assert(cursor <= end);
+ }
+ }
+ return result;
+}
+/* Given a format string 'format', return true if the string may have been produced by that format string. We do this by splitting the format string around the format specifiers, and then ensuring that each of the remaining chunks is found (in order) in the string. */
+static bool string_matches_format(const wcstring &string, const wchar_t *format)
+{
+ bool result = true;
+ wcstring_list_t components = separate_by_format_specifiers(format);
+ size_t idx = 0;
+ for (size_t i=0; i < components.size(); i++)
+ {
+ const wcstring &component = components.at(i);
+ size_t where = string.find(component, idx);
+ if (where == wcstring::npos)
+ {
+ result = false;
+ break;
+ }
+ idx = where + component.size();
+ assert(idx <= string.size());
+ }
+ return result;
+}
+
+static void test_error_messages()
+{
+ say(L"Testing error messages");
+ const struct error_test_t
+ {
+ const wchar_t *src;
+ const wchar_t *error_text_format;
+ }
+ error_tests[] =
+ {
+ {L"echo $?", COMPLETE_YOU_WANT_STATUS}
+ };
+
+ parse_error_list_t errors;
+ for (size_t i=0; i < sizeof error_tests / sizeof *error_tests; i++)
+ {
+ const struct error_test_t *test = &error_tests[i];
+ errors.clear();
+ parse_util_detect_errors(test->src, &errors, false /* allow_incomplete */);
+ do_test(! errors.empty());
+ if (! errors.empty())
+ {
+ do_test(string_matches_format(errors.at(0).text, test->error_text_format));
+ }
+ }
}
static void test_highlighting(void)
@@ -3822,6 +3928,7 @@ int main(int argc, char **argv)
if (should_test_function("new_parser_correctness")) test_new_parser_correctness();
if (should_test_function("new_parser_ad_hoc")) test_new_parser_ad_hoc();
if (should_test_function("new_parser_errors")) test_new_parser_errors();
+ if (should_test_function("error_messages")) test_error_messages();
if (should_test_function("escape")) test_unescape_sane();
if (should_test_function("escape")) test_escape_crazy();
if (should_test_function("format")) test_format();