Home | History | Annotate | Download | only in tests
      1 /*
      2  * Copyright (C) 2009 Igalia S.L.
      3  *
      4  * This library is free software; you can redistribute it and/or
      5  * modify it under the terms of the GNU Library General Public
      6  * License as published by the Free Software Foundation; either
      7  * version 2 of the License, or (at your option) any later version.
      8  *
      9  * This library is distributed in the hope that it will be useful,
     10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
     11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     12  * Library General Public License for more details.
     13  *
     14  * You should have received a copy of the GNU Library General Public License
     15  * along with this library; see the file COPYING.LIB.  If not, write to
     16  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
     17  * Boston, MA 02110-1301, USA.
     18  */
     19 
     20 #include <errno.h>
     21 #include <unistd.h>
     22 #include <glib.h>
     23 #include <glib/gstdio.h>
     24 #include <gtk/gtk.h>
     25 #include <webkit/webkit.h>
     26 
     27 #if GLIB_CHECK_VERSION(2, 16, 0) && GTK_CHECK_VERSION(2, 14, 0)
     28 
     29 static const char* contents = "<html><body><p>This is a test. This is the second sentence. And this the third.</p></body></html>";
     30 
     31 static const char* contentsWithNewlines = "<html><body><p>This is a test. \n\nThis\n is the second sentence. And this the third.</p></body></html>";
     32 
     33 static const char* contentsInTextarea = "<html><body><textarea cols='80'>This is a test. This is the second sentence. And this the third.</textarea></body></html>";
     34 
     35 static const char* contentsInTextInput = "<html><body><input type='text' size='80' value='This is a test. This is the second sentence. And this the third.'/></body></html>";
     36 
     37 static const char* contentsInParagraphAndBodySimple = "<html><body><p>This is a test.</p>Hello world.</body></html>";
     38 
     39 static const char* contentsInParagraphAndBodyModerate = "<html><body><p>This is a test.</p>Hello world.<br /><font color='#00cc00'>This sentence is green.</font><br />This one is not.</body></html>";
     40 
     41 static gboolean bail_out(GMainLoop* loop)
     42 {
     43     if (g_main_loop_is_running(loop))
     44         g_main_loop_quit(loop);
     45 
     46     return FALSE;
     47 }
     48 
     49 typedef gchar* (*AtkGetTextFunction) (AtkText*, gint, AtkTextBoundary, gint*, gint*);
     50 
     51 static void test_get_text_function(AtkText* text_obj, AtkGetTextFunction fn, AtkTextBoundary boundary, gint offset, const char* text_result, gint start_offset_result, gint end_offset_result)
     52 {
     53     gint start_offset, end_offset;
     54     char* text;
     55 
     56     text = fn(text_obj, offset, boundary, &start_offset, &end_offset);
     57     g_assert_cmpstr(text, ==, text_result);
     58     g_assert_cmpint(start_offset, ==, start_offset_result);
     59     g_assert_cmpint(end_offset, ==, end_offset_result);
     60     g_free(text);
     61 }
     62 
     63 static void run_get_text_tests(AtkText* text_obj)
     64 {
     65     char* text = atk_text_get_text(text_obj, 0, -1);
     66     g_assert_cmpstr(text, ==, "This is a test. This is the second sentence. And this the third.");
     67     g_free(text);
     68 
     69     /* ATK_TEXT_BOUNDARY_CHAR */
     70     test_get_text_function(text_obj, atk_text_get_text_at_offset, ATK_TEXT_BOUNDARY_CHAR,
     71                            0, "T", 0, 1);
     72 
     73     test_get_text_function(text_obj, atk_text_get_text_after_offset, ATK_TEXT_BOUNDARY_CHAR,
     74                            0, "h", 1, 2);
     75 
     76     test_get_text_function(text_obj, atk_text_get_text_before_offset, ATK_TEXT_BOUNDARY_CHAR,
     77                            0, "", 0, 0);
     78 
     79     test_get_text_function(text_obj, atk_text_get_text_before_offset, ATK_TEXT_BOUNDARY_CHAR,
     80                            1, "T", 0, 1);
     81 
     82     /* ATK_TEXT_BOUNDARY_WORD_START */
     83     test_get_text_function(text_obj, atk_text_get_text_at_offset, ATK_TEXT_BOUNDARY_WORD_START,
     84                            0, "This ", 0, 5);
     85 
     86     test_get_text_function(text_obj, atk_text_get_text_at_offset, ATK_TEXT_BOUNDARY_WORD_START,
     87                            4, "This ", 0, 5);
     88 
     89     test_get_text_function(text_obj, atk_text_get_text_at_offset, ATK_TEXT_BOUNDARY_WORD_START,
     90                            10, "test. ", 10, 16);
     91 
     92     test_get_text_function(text_obj, atk_text_get_text_at_offset, ATK_TEXT_BOUNDARY_WORD_START,
     93                            58, "third.", 58, 64);
     94 
     95     test_get_text_function(text_obj, atk_text_get_text_before_offset, ATK_TEXT_BOUNDARY_WORD_START,
     96                            5, "This ", 0, 5);
     97 
     98     test_get_text_function(text_obj, atk_text_get_text_before_offset, ATK_TEXT_BOUNDARY_WORD_START,
     99                            7, "This ", 0, 5);
    100 
    101     test_get_text_function(text_obj, atk_text_get_text_after_offset, ATK_TEXT_BOUNDARY_WORD_START,
    102                            0, "is ", 5, 8);
    103 
    104     test_get_text_function(text_obj, atk_text_get_text_after_offset, ATK_TEXT_BOUNDARY_WORD_START,
    105                            4, "is ", 5, 8);
    106 
    107     test_get_text_function(text_obj, atk_text_get_text_after_offset, ATK_TEXT_BOUNDARY_WORD_START,
    108                            3, "is ", 5, 8);
    109 
    110     /* ATK_TEXT_BOUNDARY_WORD_END */
    111     test_get_text_function(text_obj, atk_text_get_text_at_offset, ATK_TEXT_BOUNDARY_WORD_END,
    112                            0, "This", 0, 4);
    113 
    114     test_get_text_function(text_obj, atk_text_get_text_at_offset, ATK_TEXT_BOUNDARY_WORD_END,
    115                            4, " is", 4, 7);
    116 
    117     test_get_text_function(text_obj, atk_text_get_text_at_offset, ATK_TEXT_BOUNDARY_WORD_END,
    118                            5, " is", 4, 7);
    119 
    120     test_get_text_function(text_obj, atk_text_get_text_at_offset, ATK_TEXT_BOUNDARY_WORD_END,
    121                            9, " test", 9, 14);
    122 
    123     test_get_text_function(text_obj, atk_text_get_text_before_offset, ATK_TEXT_BOUNDARY_WORD_END,
    124                            5, "This", 0, 4);
    125 
    126     test_get_text_function(text_obj, atk_text_get_text_before_offset, ATK_TEXT_BOUNDARY_WORD_END,
    127                            4, "This", 0, 4);
    128 
    129     test_get_text_function(text_obj, atk_text_get_text_before_offset, ATK_TEXT_BOUNDARY_WORD_END,
    130                            7, " is", 4, 7);
    131 
    132     test_get_text_function(text_obj, atk_text_get_text_after_offset, ATK_TEXT_BOUNDARY_WORD_END,
    133                            5, " a", 7, 9);
    134 
    135     test_get_text_function(text_obj, atk_text_get_text_after_offset, ATK_TEXT_BOUNDARY_WORD_END,
    136                            4, " a", 7, 9);
    137 
    138     test_get_text_function(text_obj, atk_text_get_text_at_offset, ATK_TEXT_BOUNDARY_WORD_END,
    139                            58, " third", 57, 63);
    140 
    141     /* ATK_TEXT_BOUNDARY_SENTENCE_START */
    142     test_get_text_function(text_obj, atk_text_get_text_at_offset, ATK_TEXT_BOUNDARY_SENTENCE_START,
    143                            0, "This is a test. ", 0, 16);
    144 
    145     test_get_text_function(text_obj, atk_text_get_text_at_offset, ATK_TEXT_BOUNDARY_SENTENCE_START,
    146                            15, "This is a test. ", 0, 16);
    147 
    148     test_get_text_function(text_obj, atk_text_get_text_after_offset, ATK_TEXT_BOUNDARY_SENTENCE_START,
    149                            0, "This is the second sentence. ", 16, 45);
    150 
    151     test_get_text_function(text_obj, atk_text_get_text_after_offset, ATK_TEXT_BOUNDARY_SENTENCE_START,
    152                            15, "This is the second sentence. ", 16, 45);
    153 
    154     test_get_text_function(text_obj, atk_text_get_text_before_offset, ATK_TEXT_BOUNDARY_SENTENCE_START,
    155                            16, "This is a test. ", 0, 16);
    156 
    157     test_get_text_function(text_obj, atk_text_get_text_before_offset, ATK_TEXT_BOUNDARY_SENTENCE_START,
    158                            44, "This is a test. ", 0, 16);
    159 
    160     test_get_text_function(text_obj, atk_text_get_text_before_offset, ATK_TEXT_BOUNDARY_SENTENCE_START,
    161                            15, "", 0, 0);
    162 
    163     /* ATK_TEXT_BOUNDARY_SENTENCE_END */
    164     test_get_text_function(text_obj, atk_text_get_text_at_offset, ATK_TEXT_BOUNDARY_SENTENCE_END,
    165                            0, "This is a test.", 0, 15);
    166 
    167     test_get_text_function(text_obj, atk_text_get_text_at_offset, ATK_TEXT_BOUNDARY_SENTENCE_END,
    168                            15, " This is the second sentence.", 15, 44);
    169 
    170     test_get_text_function(text_obj, atk_text_get_text_at_offset, ATK_TEXT_BOUNDARY_SENTENCE_END,
    171                            16, " This is the second sentence.", 15, 44);
    172 
    173     test_get_text_function(text_obj, atk_text_get_text_at_offset, ATK_TEXT_BOUNDARY_SENTENCE_END,
    174                            17, " This is the second sentence.", 15, 44);
    175 
    176     test_get_text_function(text_obj, atk_text_get_text_after_offset, ATK_TEXT_BOUNDARY_SENTENCE_END,
    177                            0, " This is the second sentence.", 15, 44);
    178 
    179     test_get_text_function(text_obj, atk_text_get_text_after_offset, ATK_TEXT_BOUNDARY_SENTENCE_END,
    180                            15, " And this the third.", 44, 64);
    181 
    182     test_get_text_function(text_obj, atk_text_get_text_before_offset, ATK_TEXT_BOUNDARY_SENTENCE_END,
    183                            16, "This is a test.", 0, 15);
    184 
    185     test_get_text_function(text_obj, atk_text_get_text_before_offset, ATK_TEXT_BOUNDARY_SENTENCE_END,
    186                            15, "This is a test.", 0, 15);
    187 
    188     test_get_text_function(text_obj, atk_text_get_text_before_offset, ATK_TEXT_BOUNDARY_SENTENCE_END,
    189                            14, "", 0, 0);
    190 
    191     test_get_text_function(text_obj, atk_text_get_text_before_offset, ATK_TEXT_BOUNDARY_SENTENCE_END,
    192                            44, " This is the second sentence.", 15, 44);
    193 
    194     /* It's trick to test these properly right now, since our a11y
    195        implementation splits different lines in different a11y
    196        items */
    197     /* ATK_TEXT_BOUNDARY_LINE_START */
    198     test_get_text_function(text_obj, atk_text_get_text_at_offset, ATK_TEXT_BOUNDARY_LINE_START,
    199                            0, "This is a test. This is the second sentence. And this the third.", 0, 64);
    200 
    201     /* ATK_TEXT_BOUNDARY_LINE_END */
    202     test_get_text_function(text_obj, atk_text_get_text_at_offset, ATK_TEXT_BOUNDARY_LINE_END,
    203                            0, "This is a test. This is the second sentence. And this the third.", 0, 64);
    204 }
    205 
    206 static void test_webkit_atk_get_text_at_offset_forms(void)
    207 {
    208     WebKitWebView* webView;
    209     AtkObject* obj;
    210     GMainLoop* loop;
    211     AtkText* text_obj;
    212 
    213     webView = WEBKIT_WEB_VIEW(webkit_web_view_new());
    214     g_object_ref_sink(webView);
    215     GtkAllocation alloc = { 0, 0, 800, 600 };
    216     gtk_widget_size_allocate(GTK_WIDGET(webView), &alloc);
    217     webkit_web_view_load_string(webView, contents, NULL, NULL, NULL);
    218     loop = g_main_loop_new(NULL, TRUE);
    219 
    220     g_timeout_add(100, (GSourceFunc)bail_out, loop);
    221     g_main_loop_run(loop);
    222 
    223     /* Get to the inner AtkText object */
    224     obj = gtk_widget_get_accessible(GTK_WIDGET(webView));
    225     g_assert(obj);
    226     obj = atk_object_ref_accessible_child(obj, 0);
    227     g_assert(obj);
    228 
    229     text_obj = ATK_TEXT(obj);
    230     g_assert(ATK_IS_TEXT(text_obj));
    231 
    232     run_get_text_tests(text_obj);
    233 
    234     g_object_unref(webView);
    235 }
    236 
    237 static void test_webkit_atk_get_text_at_offset(void)
    238 {
    239     WebKitWebView* webView;
    240     AtkObject* obj;
    241     GMainLoop* loop;
    242     AtkText* text_obj;
    243 
    244     webView = WEBKIT_WEB_VIEW(webkit_web_view_new());
    245     g_object_ref_sink(webView);
    246     GtkAllocation alloc = { 0, 0, 800, 600 };
    247     gtk_widget_size_allocate(GTK_WIDGET(webView), &alloc);
    248     webkit_web_view_load_string(webView, contents, NULL, NULL, NULL);
    249     loop = g_main_loop_new(NULL, TRUE);
    250 
    251     g_timeout_add(100, (GSourceFunc)bail_out, loop);
    252     g_main_loop_run(loop);
    253 
    254     /* Get to the inner AtkText object */
    255     obj = gtk_widget_get_accessible(GTK_WIDGET(webView));
    256     g_assert(obj);
    257     obj = atk_object_ref_accessible_child(obj, 0);
    258     g_assert(obj);
    259 
    260     text_obj = ATK_TEXT(obj);
    261     g_assert(ATK_IS_TEXT(text_obj));
    262 
    263     run_get_text_tests(text_obj);
    264 
    265     g_object_unref(webView);
    266 }
    267 
    268 static void test_webkit_atk_get_text_at_offset_newlines(void)
    269 {
    270     WebKitWebView* webView;
    271     AtkObject* obj;
    272     GMainLoop* loop;
    273     AtkText* text_obj;
    274 
    275     webView = WEBKIT_WEB_VIEW(webkit_web_view_new());
    276     g_object_ref_sink(webView);
    277     GtkAllocation alloc = { 0, 0, 800, 600 };
    278     gtk_widget_size_allocate(GTK_WIDGET(webView), &alloc);
    279     webkit_web_view_load_string(webView, contentsWithNewlines, NULL, NULL, NULL);
    280     loop = g_main_loop_new(NULL, TRUE);
    281 
    282     g_timeout_add(100, (GSourceFunc)bail_out, loop);
    283     g_main_loop_run(loop);
    284 
    285     /* Get to the inner AtkText object */
    286     obj = gtk_widget_get_accessible(GTK_WIDGET(webView));
    287     g_assert(obj);
    288     obj = atk_object_ref_accessible_child(obj, 0);
    289     g_assert(obj);
    290 
    291     text_obj = ATK_TEXT(obj);
    292     g_assert(ATK_IS_TEXT(text_obj));
    293 
    294     run_get_text_tests(text_obj);
    295 
    296     g_object_unref(webView);
    297 }
    298 
    299 static void test_webkit_atk_get_text_at_offset_textarea(void)
    300 {
    301     WebKitWebView* webView;
    302     AtkObject* obj;
    303     GMainLoop* loop;
    304     AtkText* text_obj;
    305 
    306     webView = WEBKIT_WEB_VIEW(webkit_web_view_new());
    307     g_object_ref_sink(webView);
    308     GtkAllocation alloc = { 0, 0, 800, 600 };
    309     gtk_widget_size_allocate(GTK_WIDGET(webView), &alloc);
    310     webkit_web_view_load_string(webView, contentsInTextarea, NULL, NULL, NULL);
    311     loop = g_main_loop_new(NULL, TRUE);
    312 
    313     g_timeout_add(100, (GSourceFunc)bail_out, loop);
    314     g_main_loop_run(loop);
    315 
    316     /* Get to the inner AtkText object */
    317     obj = gtk_widget_get_accessible(GTK_WIDGET(webView));
    318     g_assert(obj);
    319     obj = atk_object_ref_accessible_child(obj, 0);
    320     g_assert(obj);
    321     obj = atk_object_ref_accessible_child(obj, 0);
    322     g_assert(obj);
    323 
    324     text_obj = ATK_TEXT(obj);
    325     g_assert(ATK_IS_TEXT(text_obj));
    326 
    327     run_get_text_tests(text_obj);
    328 
    329     g_object_unref(webView);
    330 }
    331 
    332 static void test_webkit_atk_get_text_at_offset_text_input(void)
    333 {
    334     WebKitWebView* webView;
    335     AtkObject* obj;
    336     GMainLoop* loop;
    337     AtkText* text_obj;
    338 
    339     webView = WEBKIT_WEB_VIEW(webkit_web_view_new());
    340     g_object_ref_sink(webView);
    341     GtkAllocation alloc = { 0, 0, 800, 600 };
    342     gtk_widget_size_allocate(GTK_WIDGET(webView), &alloc);
    343     webkit_web_view_load_string(webView, contentsInTextInput, NULL, NULL, NULL);
    344     loop = g_main_loop_new(NULL, TRUE);
    345 
    346     g_timeout_add(100, (GSourceFunc)bail_out, loop);
    347     g_main_loop_run(loop);
    348 
    349     /* Get to the inner AtkText object */
    350     obj = gtk_widget_get_accessible(GTK_WIDGET(webView));
    351     g_assert(obj);
    352     obj = atk_object_ref_accessible_child(obj, 0);
    353     g_assert(obj);
    354     obj = atk_object_ref_accessible_child(obj, 0);
    355     g_assert(obj);
    356 
    357     text_obj = ATK_TEXT(obj);
    358     g_assert(ATK_IS_TEXT(text_obj));
    359 
    360     run_get_text_tests(text_obj);
    361 
    362     g_object_unref(webView);
    363 }
    364 
    365 static void testWebkitAtkGetTextInParagraphAndBodySimple(void)
    366 {
    367     WebKitWebView* webView;
    368     AtkObject* obj;
    369     AtkObject* obj1;
    370     AtkObject* obj2;
    371     GMainLoop* loop;
    372     AtkText* textObj1;
    373     AtkText* textObj2;
    374 
    375     webView = WEBKIT_WEB_VIEW(webkit_web_view_new());
    376     g_object_ref_sink(webView);
    377     GtkAllocation alloc = { 0, 0, 800, 600 };
    378     gtk_widget_size_allocate(GTK_WIDGET(webView), &alloc);
    379     webkit_web_view_load_string(webView, contentsInParagraphAndBodySimple, NULL, NULL, NULL);
    380     loop = g_main_loop_new(NULL, TRUE);
    381 
    382     g_timeout_add(100, (GSourceFunc)bail_out, loop);
    383     g_main_loop_run(loop);
    384 
    385     /* Get to the inner AtkText object */
    386     obj = gtk_widget_get_accessible(GTK_WIDGET(webView));
    387     g_assert(obj);
    388     obj1 = atk_object_ref_accessible_child(obj, 0);
    389     g_assert(obj1);
    390     obj2 = atk_object_ref_accessible_child(obj, 1);
    391     g_assert(obj2);
    392 
    393     textObj1 = ATK_TEXT(obj1);
    394     g_assert(ATK_IS_TEXT(textObj1));
    395     textObj2 = ATK_TEXT(obj2);
    396     g_assert(ATK_IS_TEXT(textObj2));
    397 
    398     char *text = atk_text_get_text(textObj1, 0, -1);
    399     g_assert_cmpstr(text, ==, "This is a test.");
    400 
    401     text = atk_text_get_text(textObj2, 0, 12);
    402     g_assert_cmpstr(text, ==, "Hello world.");
    403 
    404     g_object_unref(obj1);
    405     g_object_unref(obj2);
    406     g_object_unref(webView);
    407 }
    408 
    409 static void testWebkitAtkGetTextInParagraphAndBodyModerate(void)
    410 {
    411     WebKitWebView* webView;
    412     AtkObject* obj;
    413     AtkObject* obj1;
    414     AtkObject* obj2;
    415     GMainLoop* loop;
    416     AtkText* textObj1;
    417     AtkText* textObj2;
    418 
    419     webView = WEBKIT_WEB_VIEW(webkit_web_view_new());
    420     g_object_ref_sink(webView);
    421     GtkAllocation alloc = { 0, 0, 800, 600 };
    422     gtk_widget_size_allocate(GTK_WIDGET(webView), &alloc);
    423     webkit_web_view_load_string(webView, contentsInParagraphAndBodyModerate, NULL, NULL, NULL);
    424     loop = g_main_loop_new(NULL, TRUE);
    425 
    426     g_timeout_add(100, (GSourceFunc)bail_out, loop);
    427     g_main_loop_run(loop);
    428 
    429     /* Get to the inner AtkText object */
    430     obj = gtk_widget_get_accessible(GTK_WIDGET(webView));
    431     g_assert(obj);
    432     obj1 = atk_object_ref_accessible_child(obj, 0);
    433     g_assert(obj1);
    434     obj2 = atk_object_ref_accessible_child(obj, 1);
    435     g_assert(obj2);
    436 
    437     textObj1 = ATK_TEXT(obj1);
    438     g_assert(ATK_IS_TEXT(textObj1));
    439     textObj2 = ATK_TEXT(obj2);
    440     g_assert(ATK_IS_TEXT(textObj2));
    441 
    442     char *text = atk_text_get_text(textObj1, 0, -1);
    443     g_assert_cmpstr(text, ==, "This is a test.");
    444 
    445     text = atk_text_get_text(textObj2, 0, 53);
    446     g_assert_cmpstr(text, ==, "Hello world.\nThis sentence is green.\nThis one is not.");
    447 
    448     g_object_unref(obj1);
    449     g_object_unref(obj2);
    450     g_object_unref(webView);
    451 }
    452 
    453 int main(int argc, char** argv)
    454 {
    455     g_thread_init(NULL);
    456     gtk_test_init(&argc, &argv, NULL);
    457 
    458     g_test_bug_base("https://bugs.webkit.org/");
    459     g_test_add_func("/webkit/atk/get_text_at_offset", test_webkit_atk_get_text_at_offset);
    460     g_test_add_func("/webkit/atk/get_text_at_offset_forms", test_webkit_atk_get_text_at_offset_forms);
    461     g_test_add_func("/webkit/atk/get_text_at_offset_newlines", test_webkit_atk_get_text_at_offset_newlines);
    462     g_test_add_func("/webkit/atk/get_text_at_offset_textarea", test_webkit_atk_get_text_at_offset_textarea);
    463     g_test_add_func("/webkit/atk/get_text_at_offset_text_input", test_webkit_atk_get_text_at_offset_text_input);
    464     g_test_add_func("/webkit/atk/getTextInParagraphAndBodySimple", testWebkitAtkGetTextInParagraphAndBodySimple);
    465     g_test_add_func("/webkit/atk/getTextInParagraphAndBodyModerate", testWebkitAtkGetTextInParagraphAndBodyModerate);
    466     return g_test_run ();
    467 }
    468 
    469 #else
    470 int main(int argc, char** argv)
    471 {
    472     g_critical("You will need at least glib-2.16.0 and gtk-2.14.0 to run the unit tests. Doing nothing now.");
    473     return 0;
    474 }
    475 
    476 #endif
    477