source: tester.c @ 21bab95

release-1.10release-1.8release-1.9
Last change on this file since 21bab95 was f25df21, checked in by David Benjamin <davidben@mit.edu>, 14 years ago
Don't call owl_list_create in owl_dict_get_keys Until we get rid of this owl_list thing altogether, there should be a convention as to who initializes the thing. Otherwise, we leak memory from people initializing it too many times. Whoever reviews this probably wants to look over this very carefully in case I missed one of the owl_list_creates. Also kill the various wrappers over owl_list_cleanup as they are not the inverse of any operation.
  • Property mode set to 100644
File size: 26.9 KB
Line 
1#define OWL_PERL
2#define WINDOW FAKE_WINDOW
3#include "owl.h"
4#undef WINDOW
5
6#include <unistd.h>
7#include <stdlib.h>
8
9#undef instr
10#include <curses.h>
11
12owl_global g;
13
14int numtests;
15
16int owl_regtest(void);
17int owl_util_regtest(void);
18int owl_dict_regtest(void);
19int owl_variable_regtest(void);
20int owl_filter_regtest(void);
21int owl_obarray_regtest(void);
22int owl_editwin_regtest(void);
23int owl_fmtext_regtest(void);
24int owl_smartfilter_regtest(void);
25
26extern void owl_perl_xs_init(pTHX);
27
28int main(int argc, char **argv, char **env)
29{
30  FILE *rnull;
31  FILE *wnull;
32  char *perlerr;
33  int status = 0;
34
35  if (argc <= 1) {
36    fprintf(stderr, "Usage: %s --builtin|TEST.t|-le CODE\n", argv[0]);
37    return 1;
38  }
39
40  /* initialize a fake ncurses, detached from std{in,out} */
41  wnull = fopen("/dev/null", "w");
42  rnull = fopen("/dev/null", "r");
43  newterm("xterm", wnull, rnull);
44  /* initialize global structures */
45  owl_global_init(&g);
46
47  perlerr = owl_perlconfig_initperl(NULL, &argc, &argv, &env);
48  if (perlerr) {
49    endwin();
50    fprintf(stderr, "Internal perl error: %s\n", perlerr);
51    status = 1;
52    goto out;
53  }
54
55  owl_global_complete_setup(&g);
56  owl_global_setup_default_filters(&g);
57
58  owl_view_create(owl_global_get_current_view(&g), "main",
59                  owl_global_get_filter(&g, "all"),
60                  owl_global_get_style_by_name(&g, "default"));
61
62  owl_function_firstmsg();
63
64  ENTER;
65  SAVETMPS;
66
67  if (strcmp(argv[1], "--builtin") == 0) {
68    status = owl_regtest();
69  } else if (strcmp(argv[1], "-le") == 0 && argc > 2) {
70    /*
71     * 'prove' runs its harness perl with '-le CODE' to get some
72     * information out.
73     */
74    moreswitches("l");
75    eval_pv(argv[2], true);
76  } else {
77    sv_setpv(get_sv("0", false), argv[1]);
78    sv_setpv(get_sv("main::test_prog", TRUE), argv[1]);
79
80    eval_pv("do $main::test_prog; die($@) if($@)", true);
81  }
82
83  status = 0;
84
85  FREETMPS;
86  LEAVE;
87
88 out:
89  perl_destruct(owl_global_get_perlinterp(&g));
90  perl_free(owl_global_get_perlinterp(&g));
91  /* probably not necessary, but tear down the screen */
92  endwin();
93  fclose(rnull);
94  fclose(wnull);
95  return status;
96}
97
98int owl_regtest(void) {
99  numtests = 0;
100  int numfailures=0;
101  /*
102    printf("1..%d\n", OWL_UTIL_NTESTS+OWL_DICT_NTESTS+OWL_VARIABLE_NTESTS
103    +OWL_FILTER_NTESTS+OWL_OBARRAY_NTESTS);
104  */
105  numfailures += owl_util_regtest();
106  numfailures += owl_dict_regtest();
107  numfailures += owl_variable_regtest();
108  numfailures += owl_filter_regtest();
109  numfailures += owl_editwin_regtest();
110  numfailures += owl_fmtext_regtest();
111  numfailures += owl_smartfilter_regtest();
112  if (numfailures) {
113      fprintf(stderr, "# *** WARNING: %d failures total\n", numfailures);
114  }
115  printf("1..%d\n", numtests);
116
117  return(numfailures);
118}
119
120#define FAIL_UNLESS(desc,pred) do { int __pred = (pred);                \
121    numtests++;                                                         \
122    printf("%s %s", (__pred)?"ok":(numfailed++,"not ok"), desc);        \
123    if(!(__pred)) printf("\t(%s:%d)", __FILE__, __LINE__); printf("%c", '\n'); } while(0)
124
125
126int owl_util_regtest(void)
127{
128  int numfailed=0;
129
130  printf("# BEGIN testing owl_util\n");
131
132#define CHECK_STR_AND_FREE(desc, expected, expr)         \
133    do {                                                 \
134      char *__value = (expr);                            \
135      FAIL_UNLESS((desc), !strcmp((expected), __value)); \
136      g_free(__value);                                 \
137    } while (0)
138
139  CHECK_STR_AND_FREE("owl_text_substitute 2", "fYZYZ",
140                     owl_text_substitute("foo", "o", "YZ"));
141  CHECK_STR_AND_FREE("owl_text_substitute 3", "foo",
142                     owl_text_substitute("fYZYZ", "YZ", "o"));
143  CHECK_STR_AND_FREE("owl_text_substitute 4", "/u/foo/meep",
144                     owl_text_substitute("~/meep", "~", "/u/foo"));
145
146  FAIL_UNLESS("skiptokens 1", 
147              !strcmp("bar quux", skiptokens("foo bar quux", 1)));
148  FAIL_UNLESS("skiptokens 2", 
149              !strcmp("meep", skiptokens("foo 'bar quux' meep", 2)));
150
151  CHECK_STR_AND_FREE("expand_tabs 1", "        hi", owl_text_expand_tabs("\thi"));
152
153  CHECK_STR_AND_FREE("expand_tabs 2", "        hi\nword    tab",
154                     owl_text_expand_tabs("\thi\nword\ttab"));
155
156  CHECK_STR_AND_FREE("expand_tabs 3", "                2 tabs",
157                     owl_text_expand_tabs("\t\t2 tabs"));
158  CHECK_STR_AND_FREE("expand_tabs 4", "α       ααααααα!        ",
159                     owl_text_expand_tabs(\tααααααα!\t"));
160  CHECK_STR_AND_FREE("expand_tabs 5", "A      AAA!!        ",
161                     owl_text_expand_tabs("A\tAAA!!\t"));
162
163  FAIL_UNLESS("skiptokens 1",
164              !strcmp("world", skiptokens("hello world", 1)));
165
166  FAIL_UNLESS("skiptokens 2",
167              !strcmp("c d e", skiptokens("a   b c d e", 2)));
168
169  FAIL_UNLESS("skiptokens 3",
170              !strcmp("\"b\" c d e", skiptokens("a \"b\" c d e", 1)));
171
172  FAIL_UNLESS("skiptokens 4",
173              !strcmp("c d e", skiptokens("a \"b\" c d e", 2)));
174
175  FAIL_UNLESS("skiptokens 5",
176              !strcmp("c d e", skiptokens("a \"'\" c d e", 2)));
177
178#define CHECK_QUOTING(desc, unquoted, quoted)           \
179  do {                                                  \
180      int __argc;                                       \
181      char *__quoted = owl_arg_quote(unquoted);         \
182      char **__argv;                                    \
183      FAIL_UNLESS(desc, !strcmp(quoted, __quoted));     \
184      __argv = owl_parseline(__quoted, &__argc);        \
185      FAIL_UNLESS(desc " - arg count", __argc == 1);    \
186      FAIL_UNLESS(desc " - null-terminated",            \
187                  __argv[__argc] == NULL);              \
188      FAIL_UNLESS(desc " - parsed",                     \
189                  !strcmp(__argv[0], unquoted));        \
190      g_strfreev(__argv);                               \
191      g_free(__quoted);                         \
192    } while (0)
193
194  CHECK_QUOTING("boring text", "mango", "mango");
195  CHECK_QUOTING("spaces", "mangos are tasty", "'mangos are tasty'");
196  CHECK_QUOTING("single quotes", "mango's", "\"mango's\"");
197  CHECK_QUOTING("double quotes", "he said \"mangos are tasty\"",
198                "'he said \"mangos are tasty\"'");
199  CHECK_QUOTING("both quotes",
200                "he said \"mango's are tasty even when you put in "
201                "a random apostrophe\"",
202                "\"he said \"'\"'\"mango's are tasty even when you put in "
203                "a random apostrophe\"'\"'\"\"");
204  CHECK_QUOTING("quote monster", "'\"\"'\"'''\"",
205                "\""
206                "'"
207                "\"'\"'\""
208                "\"'\"'\""
209                "'"
210                "\"'\"'\""
211                "'"
212                "'"
213                "'"
214                "\"'\"'\""
215                "\"");
216
217  GString *g = g_string_new("");
218  owl_string_appendf_quoted(g, "%q foo %q%q %s %", "hello", "world is", "can't");
219  FAIL_UNLESS("owl_string_appendf",
220              !strcmp(g_string_free(g, false),
221                      "hello foo 'world is'\"can't\" %s %"));
222
223  /* if (numfailed) printf("*** WARNING: failures encountered with owl_util\n"); */
224  printf("# END testing owl_util (%d failures)\n", numfailed);
225  return(numfailed);
226}
227
228int owl_dict_regtest(void) {
229  owl_dict d;
230  owl_list l;
231  int numfailed=0;
232  char *av="aval", *bv="bval", *cv="cval", *dv="dval";
233
234  printf("# BEGIN testing owl_dict\n");
235  FAIL_UNLESS("create", 0==owl_dict_create(&d));
236  FAIL_UNLESS("insert b", 0==owl_dict_insert_element(&d, "b", bv, owl_dict_noop_delete));
237  FAIL_UNLESS("insert d", 0==owl_dict_insert_element(&d, "d", dv, owl_dict_noop_delete));
238  FAIL_UNLESS("insert a", 0==owl_dict_insert_element(&d, "a", av, owl_dict_noop_delete));
239  FAIL_UNLESS("insert c", 0==owl_dict_insert_element(&d, "c", cv, owl_dict_noop_delete));
240  FAIL_UNLESS("reinsert d (no replace)", -2==owl_dict_insert_element(&d, "d", dv, 0));
241  FAIL_UNLESS("find a", av==owl_dict_find_element(&d, "a"));
242  FAIL_UNLESS("find b", bv==owl_dict_find_element(&d, "b"));
243  FAIL_UNLESS("find c", cv==owl_dict_find_element(&d, "c"));
244  FAIL_UNLESS("find d", dv==owl_dict_find_element(&d, "d"));
245  FAIL_UNLESS("find e (non-existent)", NULL==owl_dict_find_element(&d, "e"));
246  FAIL_UNLESS("remove d", dv==owl_dict_remove_element(&d, "d"));
247  FAIL_UNLESS("find d (post-removal)", NULL==owl_dict_find_element(&d, "d"));
248
249  FAIL_UNLESS("get_size", 3==owl_dict_get_size(&d));
250  owl_list_create(&l);
251  FAIL_UNLESS("get_keys", 0==owl_dict_get_keys(&d, &l));
252  FAIL_UNLESS("get_keys result size", 3==owl_list_get_size(&l));
253 
254  /* these assume the returned keys are sorted */
255  FAIL_UNLESS("get_keys result val",0==strcmp("a",owl_list_get_element(&l,0)));
256  FAIL_UNLESS("get_keys result val",0==strcmp("b",owl_list_get_element(&l,1)));
257  FAIL_UNLESS("get_keys result val",0==strcmp("c",owl_list_get_element(&l,2)));
258
259  owl_list_cleanup(&l, g_free);
260  owl_dict_cleanup(&d, NULL);
261
262  /*  if (numfailed) printf("*** WARNING: failures encountered with owl_dict\n"); */
263  printf("# END testing owl_dict (%d failures)\n", numfailed);
264  return(numfailed);
265}
266
267int owl_variable_regtest(void) {
268  owl_vardict vd;
269  int numfailed=0;
270  char *value;
271  const void *v;
272
273  printf("# BEGIN testing owl_variable\n");
274  FAIL_UNLESS("setup", 0==owl_variable_dict_setup(&vd));
275
276  FAIL_UNLESS("get bool", 0==owl_variable_get_bool(&vd,"rxping"));
277  FAIL_UNLESS("get bool (no such)", -1==owl_variable_get_bool(&vd,"mumble"));
278  FAIL_UNLESS("get bool as string",
279              !strcmp((value = owl_variable_get_tostring(&vd,"rxping")), "off"));
280  g_free(value);
281  FAIL_UNLESS("set bool 1", 0==owl_variable_set_bool_on(&vd,"rxping"));
282  FAIL_UNLESS("get bool 2", 1==owl_variable_get_bool(&vd,"rxping"));
283  FAIL_UNLESS("set bool 3", 0==owl_variable_set_fromstring(&vd,"rxping","off",0,0));
284  FAIL_UNLESS("get bool 4", 0==owl_variable_get_bool(&vd,"rxping"));
285  FAIL_UNLESS("set bool 5", -1==owl_variable_set_fromstring(&vd,"rxping","xxx",0,0));
286  FAIL_UNLESS("get bool 6", 0==owl_variable_get_bool(&vd,"rxping"));
287
288
289  FAIL_UNLESS("get string", 0==strcmp("~/zlog/people", owl_variable_get_string(&vd,"logpath")));
290  FAIL_UNLESS("set string 7", 0==owl_variable_set_string(&vd,"logpath","whee"));
291  FAIL_UNLESS("get string", 0==strcmp("whee", owl_variable_get_string(&vd,"logpath")));
292
293  FAIL_UNLESS("get int", 8==owl_variable_get_int(&vd,"typewinsize"));
294  FAIL_UNLESS("get int (no such)", -1==owl_variable_get_int(&vd,"mmble"));
295  FAIL_UNLESS("get int as string",
296              !strcmp((value = owl_variable_get_tostring(&vd,"typewinsize")), "8"));
297  g_free(value);
298  FAIL_UNLESS("set int 1", 0==owl_variable_set_int(&vd,"typewinsize",12));
299  FAIL_UNLESS("get int 2", 12==owl_variable_get_int(&vd,"typewinsize"));
300  FAIL_UNLESS("set int 1b", -1==owl_variable_set_int(&vd,"typewinsize",-3));
301  FAIL_UNLESS("get int 2b", 12==owl_variable_get_int(&vd,"typewinsize"));
302  FAIL_UNLESS("set int 3", 0==owl_variable_set_fromstring(&vd,"typewinsize","9",0,0));
303  FAIL_UNLESS("get int 4", 9==owl_variable_get_int(&vd,"typewinsize"));
304  FAIL_UNLESS("set int 5", -1==owl_variable_set_fromstring(&vd,"typewinsize","xxx",0,0));
305  FAIL_UNLESS("set int 6", -1==owl_variable_set_fromstring(&vd,"typewinsize","",0,0));
306  FAIL_UNLESS("get int 7", 9==owl_variable_get_int(&vd,"typewinsize"));
307
308  owl_variable_dict_newvar_string(&vd, "stringvar", "", "", "testval");
309  FAIL_UNLESS("get new string var", NULL != (v = owl_variable_get(&vd, "stringvar", OWL_VARIABLE_STRING)));
310  FAIL_UNLESS("get new string val", !strcmp("testval", owl_variable_get_string(&vd, "stringvar")));
311  owl_variable_set_string(&vd, "stringvar", "new val");
312  FAIL_UNLESS("update string val", !strcmp("new val", owl_variable_get_string(&vd, "stringvar")));
313
314  owl_variable_dict_newvar_int(&vd, "intvar", "", "", 47);
315  FAIL_UNLESS("get new int var", NULL != (v = owl_variable_get(&vd, "intvar", OWL_VARIABLE_INT)));
316  FAIL_UNLESS("get new int val", 47 == owl_variable_get_int(&vd, "intvar"));
317  owl_variable_set_int(&vd, "intvar", 17);
318  FAIL_UNLESS("update bool val", 17 == owl_variable_get_int(&vd, "intvar"));
319
320  owl_variable_dict_newvar_bool(&vd, "boolvar", "", "", 1);
321  FAIL_UNLESS("get new bool var", NULL != (v = owl_variable_get(&vd, "boolvar", OWL_VARIABLE_BOOL)));
322  FAIL_UNLESS("get new bool val", owl_variable_get_bool(&vd, "boolvar"));
323  owl_variable_set_bool_off(&vd, "boolvar");
324  FAIL_UNLESS("update string val", !owl_variable_get_bool(&vd, "boolvar"));
325
326  owl_variable_dict_cleanup(&vd);
327
328  /* if (numfailed) printf("*** WARNING: failures encountered with owl_variable\n"); */
329  printf("# END testing owl_variable (%d failures)\n", numfailed);
330  return(numfailed);
331}
332
333static int owl_filter_test_string(const char *filt, const owl_message *m, int shouldmatch)
334{
335  owl_filter *f;
336  int ok;
337  int failed = 0;
338  if ((f = owl_filter_new_fromstring("test-filter", filt)) == NULL) {
339    printf("not ok can't parse %s\n", filt);
340    failed = 1;
341    goto out;
342  }
343  ok = owl_filter_message_match(f, m);
344  if((shouldmatch && !ok) || (!shouldmatch && ok)) {
345    printf("not ok match %s (got %d, expected %d)\n", filt, ok, shouldmatch);
346    failed = 1;
347  }
348 out:
349  owl_filter_delete(f);
350  if(!failed) {
351    printf("ok %s %s\n", shouldmatch ? "matches" : "doesn't match", filt);
352  }
353  return failed;
354}
355
356int owl_filter_regtest(void) {
357  int numfailed=0;
358  owl_message m;
359  owl_filter *f1, *f2, *f3, *f4, *f5;
360
361  owl_message_init(&m);
362  owl_message_set_type_zephyr(&m);
363  owl_message_set_direction_in(&m);
364  owl_message_set_class(&m, "owl");
365  owl_message_set_instance(&m, "tester");
366  owl_message_set_sender(&m, "owl-user");
367  owl_message_set_recipient(&m, "joe");
368  owl_message_set_attribute(&m, "foo", "bar");
369
370#define TEST_FILTER(f, e) do {                          \
371    numtests++;                                         \
372    numfailed += owl_filter_test_string(f, &m, e);      \
373      } while(0)
374
375  TEST_FILTER("true", 1);
376  TEST_FILTER("false", 0);
377  TEST_FILTER("( true )", 1);
378  TEST_FILTER("not false", 1);
379  TEST_FILTER("( true ) or ( false )", 1);
380  TEST_FILTER("true and false", 0);
381  TEST_FILTER("( true or true ) or ( ( false ) )", 1);
382
383  TEST_FILTER("class owl", 1);
384  TEST_FILTER("class ^owl$", 1);
385  TEST_FILTER("instance test", 1);
386  TEST_FILTER("instance ^test$", 0);
387  TEST_FILTER("instance ^tester$", 1);
388
389  TEST_FILTER("foo bar", 1);
390  TEST_FILTER("class owl and instance tester", 1);
391  TEST_FILTER("type ^zephyr$ and direction ^in$ and ( class ^owl$ or instance ^owl$ )", 1);
392
393  /* Order of operations and precedence */
394  TEST_FILTER("not true or false", 0);
395  TEST_FILTER("true or true and false", 0);
396  TEST_FILTER("true and true and false or true", 1);
397  TEST_FILTER("false and false or true", 1);
398  TEST_FILTER("true and false or false", 0);
399
400  f1 = owl_filter_new_fromstring("f1", "class owl");
401  owl_global_add_filter(&g, f1);
402  TEST_FILTER("filter f1", 1);
403  owl_global_remove_filter(&g, "f1");
404
405  /* Test recursion prevention */
406  FAIL_UNLESS("self reference", (f2 = owl_filter_new_fromstring("test", "filter test")) == NULL);
407  owl_filter_delete(f2);
408
409  /* mutual recursion */
410  f3 = owl_filter_new_fromstring("f3", "filter f4");
411  owl_global_add_filter(&g, f3);
412  FAIL_UNLESS("mutual recursion", (f4 = owl_filter_new_fromstring("f4", "filter f3")) == NULL);
413  owl_global_remove_filter(&g, "f3");
414  owl_filter_delete(f4);
415
416  /* support referencing a filter several times */
417  FAIL_UNLESS("DAG", (f5 = owl_filter_new_fromstring("dag", "filter f1 or filter f1")) != NULL);
418  owl_filter_delete(f5);
419
420  return 0;
421}
422
423int owl_editwin_regtest(void) {
424  int numfailed = 0;
425  const char *p;
426  owl_editwin *oe;
427  const char *autowrap_string = "we feel our owls should live "
428                                "closer to our ponies.";
429
430  printf("# BEGIN testing owl_editwin\n");
431
432  oe = owl_editwin_new(NULL, 80, 80, OWL_EDITWIN_STYLE_MULTILINE, NULL);
433
434  /* TODO: make the strings a little more lenient w.r.t trailing whitespace */
435
436  /* check paragraph fill */
437  owl_editwin_insert_string(oe, "blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah.\n\nblah");
438  owl_editwin_move_to_top(oe);
439  owl_editwin_fill_paragraph(oe);
440  p = owl_editwin_get_text(oe);
441  FAIL_UNLESS("text was correctly wrapped", p && !strcmp(p, "blah blah blah blah blah blah blah blah blah blah blah blah blah blah\n"
442                                                            "blah blah blah.\n"
443                                                            "\n"
444                                                            "blah"));
445
446  owl_editwin_unref(oe); oe = NULL;
447  oe = owl_editwin_new(NULL, 80, 80, OWL_EDITWIN_STYLE_MULTILINE, NULL);
448
449  /* check that lines ending with ". " correctly fill */
450  owl_editwin_insert_string(oe, "blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah. \n\nblah");
451  owl_editwin_move_to_top(oe);
452  owl_editwin_fill_paragraph(oe);
453  p = owl_editwin_get_text(oe);
454  FAIL_UNLESS("text was correctly wrapped", p && !strcmp(p, "blah blah blah blah blah blah blah blah blah blah blah blah blah blah\n"
455                                                            "blah blah blah. \n"
456                                                            "\n"
457                                                            "blah"));
458
459  owl_editwin_unref(oe); oe = NULL;
460
461  /* Test owl_editwin_move_to_beginning_of_line. */
462  oe = owl_editwin_new(NULL, 80, 80, OWL_EDITWIN_STYLE_MULTILINE, NULL);
463  owl_editwin_insert_string(oe, "\n");
464  owl_editwin_insert_string(oe, "12345678\n");
465  owl_editwin_insert_string(oe, "\n");
466  owl_editwin_insert_string(oe, "abcdefg\n");
467  owl_editwin_move_to_top(oe);
468  FAIL_UNLESS("already at beginning of line",
469              owl_editwin_move_to_beginning_of_line(oe) == 0);
470  owl_editwin_line_move(oe, 1);
471  owl_editwin_point_move(oe, 5);
472  FAIL_UNLESS("find beginning of line after empty first line",
473              owl_editwin_move_to_beginning_of_line(oe) == -5);
474  owl_editwin_line_move(oe, 1);
475  FAIL_UNLESS("find beginning empty middle line",
476              owl_editwin_move_to_beginning_of_line(oe) == 0);
477  owl_editwin_line_move(oe, 1);
478  owl_editwin_point_move(oe, 2);
479  FAIL_UNLESS("find beginning of line after empty middle line",
480              owl_editwin_move_to_beginning_of_line(oe) == -2);
481  owl_editwin_unref(oe); oe = NULL;
482
483  /* Test automatic line-wrapping. */
484  owl_global_set_edit_maxwrapcols(&g, 10);
485  oe = owl_editwin_new(NULL, 80, 80, OWL_EDITWIN_STYLE_MULTILINE, NULL);
486  for (p = autowrap_string; *p; p++) {
487    owl_input j;
488    j.ch = *p;
489    j.uch = *p; /* Assuming ASCII. */
490    owl_editwin_process_char(oe, j);
491  }
492  p = owl_editwin_get_text(oe);
493  FAIL_UNLESS("text was automatically wrapped",
494              p && !strcmp(p, "we feel\n"
495                           "our owls\n"
496                           "should\n"
497                           "live\n"
498                           "closer to\n"
499                           "our\n"
500                           "ponies."));
501  owl_editwin_unref(oe); oe = NULL;
502  owl_global_set_edit_maxwrapcols(&g, 70);
503
504  /* Test owl_editwin_current_column. */
505  oe = owl_editwin_new(NULL, 80, 80, OWL_EDITWIN_STYLE_MULTILINE, NULL);
506  FAIL_UNLESS("initial column zero", owl_editwin_current_column(oe) == 0);
507  owl_editwin_insert_string(oe, "abcdef");
508  FAIL_UNLESS("simple insert", owl_editwin_current_column(oe) == 6);
509  owl_editwin_insert_string(oe, "\t");
510  FAIL_UNLESS("insert tabs", owl_editwin_current_column(oe) == 8);
511  owl_editwin_insert_string(oe, "123\n12\t3");
512  FAIL_UNLESS("newline with junk", owl_editwin_current_column(oe) == 9);
513  owl_editwin_move_to_beginning_of_line(oe);
514  FAIL_UNLESS("beginning of line", owl_editwin_current_column(oe) == 0);
515  owl_editwin_unref(oe); oe = NULL;
516
517  printf("# END testing owl_editwin (%d failures)\n", numfailed);
518
519  return numfailed;
520}
521
522int owl_fmtext_regtest(void) {
523  int numfailed = 0;
524  int start, end;
525  owl_fmtext fm1;
526  owl_fmtext fm2;
527  owl_regex re;
528  char *str;
529
530  printf("# BEGIN testing owl_fmtext\n");
531
532  owl_fmtext_init_null(&fm1);
533  owl_fmtext_init_null(&fm2);
534
535  /* Verify text gets correctly appended. */
536  owl_fmtext_append_normal(&fm1, "1234567898");
537  owl_fmtext_append_fmtext(&fm2, &fm1);
538  FAIL_UNLESS("string lengths correct",
539              owl_fmtext_num_bytes(&fm2) == strlen(owl_fmtext_get_text(&fm2)));
540
541  /* Test owl_fmtext_num_lines. */
542  owl_fmtext_clear(&fm1);
543  FAIL_UNLESS("empty line correct", owl_fmtext_num_lines(&fm1) == 0);
544  owl_fmtext_append_normal(&fm1, "12345\n67898");
545  FAIL_UNLESS("trailing chars correct", owl_fmtext_num_lines(&fm1) == 2);
546  owl_fmtext_append_normal(&fm1, "\n");
547  FAIL_UNLESS("trailing newline correct", owl_fmtext_num_lines(&fm1) == 2);
548  owl_fmtext_append_bold(&fm1, "");
549  FAIL_UNLESS("trailing attributes correct", owl_fmtext_num_lines(&fm1) == 2);
550
551  /* Test owl_fmtext_truncate_lines */
552  owl_fmtext_clear(&fm1);
553  owl_fmtext_append_normal(&fm1, "0\n1\n2\n3\n4\n");
554
555  owl_fmtext_clear(&fm2);
556  owl_fmtext_truncate_lines(&fm1, 1, 3, &fm2);
557  str = owl_fmtext_print_plain(&fm2);
558  FAIL_UNLESS("lines corrected truncated",
559              str && !strcmp(str, "1\n2\n3\n"));
560  g_free(str);
561
562  owl_fmtext_clear(&fm2);
563  owl_fmtext_truncate_lines(&fm1, 1, 5, &fm2);
564  str = owl_fmtext_print_plain(&fm2);
565  FAIL_UNLESS("lines corrected truncated",
566              str && !strcmp(str, "1\n2\n3\n4\n"));
567  g_free(str);
568
569  /* Test owl_fmtext_truncate_cols. */
570  owl_fmtext_clear(&fm1);
571  owl_fmtext_append_normal(&fm1, "123456789012345\n");
572  owl_fmtext_append_normal(&fm1, "123456789\n");
573  owl_fmtext_append_normal(&fm1, "1234567890\n");
574
575  owl_fmtext_clear(&fm2);
576  owl_fmtext_truncate_cols(&fm1, 4, 9, &fm2);
577  str = owl_fmtext_print_plain(&fm2);
578  FAIL_UNLESS("columns correctly truncated",
579              str && !strcmp(str, "567890"
580                                  "56789\n"
581                                  "567890"));
582  g_free(str);
583
584  owl_fmtext_clear(&fm1);
585  owl_fmtext_append_normal(&fm1, "12\t1234");
586  owl_fmtext_append_bold(&fm1, "56\n");
587  owl_fmtext_append_bold(&fm1, "12345678\t\n");
588
589  owl_fmtext_clear(&fm2);
590  owl_fmtext_truncate_cols(&fm1, 4, 13, &fm2);
591  str = owl_fmtext_print_plain(&fm2);
592  FAIL_UNLESS("columns correctly truncated",
593              str && !strcmp(str, "    123456"
594                                  "5678      "));
595  g_free(str);
596
597  /* Test owl_fmtext_expand_tabs. */
598  owl_fmtext_clear(&fm1);
599  owl_fmtext_append_normal(&fm1, "12\t1234");
600  owl_fmtext_append_bold(&fm1, "567\t1\n12345678\t1");
601  owl_fmtext_clear(&fm2);
602  owl_fmtext_expand_tabs(&fm1, &fm2, 0);
603  str = owl_fmtext_print_plain(&fm2);
604  FAIL_UNLESS("no tabs remaining", strchr(str, '\t') == NULL);
605  FAIL_UNLESS("tabs corrected expanded",
606              str && !strcmp(str, "12      1234567 1\n"
607                                  "12345678        1"));
608  g_free(str);
609
610  owl_fmtext_clear(&fm2);
611  owl_fmtext_expand_tabs(&fm1, &fm2, 1);
612  str = owl_fmtext_print_plain(&fm2);
613  FAIL_UNLESS("no tabs remaining", strchr(str, '\t') == NULL);
614  FAIL_UNLESS("tabs corrected expanded",
615              str && !strcmp(str, "12     1234567 1\n"
616                                  "12345678       1"));
617  g_free(str);
618
619  /* Test owl_fmtext_search. */
620  owl_fmtext_clear(&fm1);
621  owl_fmtext_append_normal(&fm1, "123123123123");
622  owl_regex_create(&re, "12");
623  {
624    int count = 0, offset;
625    offset = owl_fmtext_search(&fm1, &re, 0);
626    while (offset >= 0) {
627      FAIL_UNLESS("search matches",
628                  !strncmp("12", owl_fmtext_get_text(&fm1) + offset, 2));
629      count++;
630      offset = owl_fmtext_search(&fm1, &re, offset+1);
631    }
632    FAIL_UNLESS("exactly four matches", count == 4);
633  }
634  owl_regex_cleanup(&re);
635
636  /* Test owl_fmtext_line_number. */
637  owl_fmtext_clear(&fm1);
638  owl_fmtext_append_normal(&fm1, "123\n456\n");
639  owl_fmtext_append_bold(&fm1, "");
640  FAIL_UNLESS("lines start at 0", 0 == owl_fmtext_line_number(&fm1, 0));
641  FAIL_UNLESS("trailing formatting characters part of false line",
642              2 == owl_fmtext_line_number(&fm1, owl_fmtext_num_bytes(&fm1)));
643  owl_regex_create_quoted(&re, "456");
644  FAIL_UNLESS("correctly find second line (line 1)",
645              1 == owl_fmtext_line_number(&fm1, owl_fmtext_search(&fm1, &re, 0)));
646  owl_regex_cleanup(&re);
647
648  /* Test owl_fmtext_line_extents. */
649  owl_fmtext_clear(&fm1);
650  owl_fmtext_append_normal(&fm1, "123\n456\n789");
651  owl_fmtext_line_extents(&fm1, 1, &start, &end);
652  FAIL_UNLESS("line contents",
653              !strncmp("456\n", owl_fmtext_get_text(&fm1)+start, end-start));
654  owl_fmtext_line_extents(&fm1, 2, &start, &end);
655  FAIL_UNLESS("point to end of buffer", end == owl_fmtext_num_bytes(&fm1));
656
657  owl_fmtext_cleanup(&fm1);
658  owl_fmtext_cleanup(&fm2);
659
660  printf("# END testing owl_fmtext (%d failures)\n", numfailed);
661
662  return numfailed;
663}
664
665static int owl_smartfilter_test_equals(const char *filtname, const char *expected) {
666  owl_filter *f = NULL;
667  char *filtstr = NULL;
668  int failed = 0;
669  f = owl_global_get_filter(&g, filtname);
670  if (f == NULL) {
671    printf("not ok filter missing: %s\n", filtname);
672    failed = 1;
673    goto out;
674  }
675
676  /* TODO: Come up with a better way to test this. */
677  filtstr = owl_filter_print(f);
678  if (strcmp(expected, filtstr)) {
679    printf("not ok filter incorrect: |%s| instead of |%s|\n",
680           filtstr, expected);
681    failed = 1;
682    goto out;
683  }
684
685 out:
686  g_free(filtstr);
687  return failed;
688}
689
690static int owl_classinstfilt_test(const char *c, const char *i, int related, const char *expected) {
691  char *filtname = NULL;
692  int failed = 0;
693
694  filtname = owl_function_classinstfilt(c, i, related);
695  if (filtname == NULL) {
696    printf("not ok null filtname: %s %s %s\n", c, i ? i : "(null)",
697           related ? "related" : "not related");
698    failed = 1;
699    goto out;
700  }
701  if (owl_smartfilter_test_equals(filtname, expected)) {
702    failed = 1;
703    goto out;
704  }
705 out:
706  if (!failed) {
707    printf("ok %s\n", filtname);
708  }
709  if (filtname)
710    owl_global_remove_filter(&g, filtname);
711  g_free(filtname);
712  return failed;
713}
714
715static int owl_zuserfilt_test(const char *longuser, const char *expected) {
716  char *filtname = NULL;
717  int failed = 0;
718
719  filtname = owl_function_zuserfilt(longuser);
720  if (filtname == NULL) {
721    printf("not ok null filtname: %s\n", longuser);
722    failed = 1;
723    goto out;
724  }
725  if (owl_smartfilter_test_equals(filtname, expected)) {
726    failed = 1;
727    goto out;
728  }
729 out:
730  if (!failed) {
731    printf("ok %s\n", filtname);
732  }
733  if (filtname)
734    owl_global_remove_filter(&g, filtname);
735  g_free(filtname);
736  return failed;
737}
738
739
740int owl_smartfilter_regtest(void) {
741  int numfailed = 0;
742
743  printf("# BEGIN testing owl_smartfilter\n");
744
745  /* Check classinst making. */
746
747#define TEST_CLASSINSTFILT(c, i, r, e) do {             \
748    numtests++;                                         \
749    numfailed += owl_classinstfilt_test(c, i, r, e);    \
750  } while (0)
751  TEST_CLASSINSTFILT("message", NULL, false,
752                     "class ^message$\n");
753  TEST_CLASSINSTFILT("message", NULL, true,
754                     "class ^(un)*message(\\.d)*$\n");
755  TEST_CLASSINSTFILT("message", "personal", false,
756                     "class ^message$ and instance ^personal$\n");
757  TEST_CLASSINSTFILT("message", "personal", true,
758                     "class ^(un)*message(\\.d)*$ and ( instance ^(un)*personal(\\.d)*$ )\n");
759
760  TEST_CLASSINSTFILT("message", "evil\tinstance", false,
761                     "class ^message$ and instance '^evil\tinstance$'\n");
762  TEST_CLASSINSTFILT("message", "evil instance", false,
763                     "class ^message$ and instance '^evil instance$'\n");
764  TEST_CLASSINSTFILT("message", "evil'instance", false,
765                     "class ^message$ and instance \"^evil'instance$\"\n");
766  TEST_CLASSINSTFILT("message", "evil\"instance", false,
767                     "class ^message$ and instance '^evil\"instance$'\n");
768  TEST_CLASSINSTFILT("message", "evil$instance", false,
769                     "class ^message$ and instance ^evil\\$instance$\n");
770
771#define TEST_ZUSERFILT(l, e) do {                       \
772    numtests++;                                         \
773    numfailed += owl_zuserfilt_test(l, e);              \
774  } while (0)
775  TEST_ZUSERFILT("user",
776                 "( type ^zephyr$ and filter personal and "
777                 "( ( direction ^in$ and sender "
778                 "^user$"
779                 " ) or ( direction ^out$ and recipient "
780                 "^user$"
781                 " ) ) ) or ( ( class ^login$ ) and ( sender "
782                 "^user$"
783                 " ) )\n");
784  TEST_ZUSERFILT("very evil\t.user",
785                 "( type ^zephyr$ and filter personal and "
786                 "( ( direction ^in$ and sender "
787                 "'^very evil\t\\.user$'"
788                 " ) or ( direction ^out$ and recipient "
789                 "'^very evil\t\\.user$'"
790                 " ) ) ) or ( ( class ^login$ ) and ( sender "
791                 "'^very evil\t\\.user$'"
792                 " ) )\n");
793
794  printf("# END testing owl_smartfilter (%d failures)\n", numfailed);
795
796  return numfailed;
797}
Note: See TracBrowser for help on using the repository browser.