WebKit/gtk/tests/testatk.c
changeset 0 4f2f89ce4247
equal deleted inserted replaced
-1:000000000000 0:4f2f89ce4247
       
     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 const char* contentsInTable = "<html><body><table><tr><td>foo</td><td>bar</td></tr></table></body></html>";
       
    42 
       
    43 static const char* contentsInTableWithHeaders = "<html><body><table><tr><th>foo</th><th>bar</th><th colspan='2'>baz</th></tr><tr><th>qux</th><td>1</td><td>2</td><td>3</td></tr><tr><th rowspan='2'>quux</th><td>4</td><td>5</td><td>6</td></tr><tr><td>6</td><td>7</td><td>8</td></tr><tr><th>corge</th><td>9</td><td>10</td><td>11</td></tr></table><table><tr><td>1</td><td>2</td></tr><tr><td>3</td><td>4</td></tr></table></body></html>";
       
    44 
       
    45 static const char* textWithAttributes = "<html><head><style>.st1 {font-family: monospace; color:rgb(120,121,122);} .st2 {text-decoration:underline; background-color:rgb(80,81,82);}</style></head><body><p style=\"font-size:14; text-align:right;\">This is the <i>first</i><b> sentence of this text.</b></p><p class=\"st1\">This sentence should have an style applied <span class=\"st2\">and this part should have another one</span>.</p><p>x<sub>1</sub><sup>2</sup>=x<sub>2</sub><sup>3</sup></p><p style=\"text-align:center;\">This sentence is the <strike>last</strike> one.</p></body></html>";
       
    46 
       
    47 static gboolean bail_out(GMainLoop* loop)
       
    48 {
       
    49     if (g_main_loop_is_running(loop))
       
    50         g_main_loop_quit(loop);
       
    51 
       
    52     return FALSE;
       
    53 }
       
    54 
       
    55 typedef gchar* (*AtkGetTextFunction) (AtkText*, gint, AtkTextBoundary, gint*, gint*);
       
    56 
       
    57 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)
       
    58 {
       
    59     gint start_offset, end_offset;
       
    60     char* text;
       
    61 
       
    62     text = fn(text_obj, offset, boundary, &start_offset, &end_offset);
       
    63     g_assert_cmpstr(text, ==, text_result);
       
    64     g_assert_cmpint(start_offset, ==, start_offset_result);
       
    65     g_assert_cmpint(end_offset, ==, end_offset_result);
       
    66     g_free(text);
       
    67 }
       
    68 
       
    69 static void run_get_text_tests(AtkText* text_obj)
       
    70 {
       
    71     char* text = atk_text_get_text(text_obj, 0, -1);
       
    72     g_assert_cmpstr(text, ==, "This is a test. This is the second sentence. And this the third.");
       
    73     g_free(text);
       
    74 
       
    75     /* ATK_TEXT_BOUNDARY_CHAR */
       
    76     test_get_text_function(text_obj, atk_text_get_text_at_offset, ATK_TEXT_BOUNDARY_CHAR,
       
    77                            0, "T", 0, 1);
       
    78 
       
    79     test_get_text_function(text_obj, atk_text_get_text_after_offset, ATK_TEXT_BOUNDARY_CHAR,
       
    80                            0, "h", 1, 2);
       
    81 
       
    82     test_get_text_function(text_obj, atk_text_get_text_before_offset, ATK_TEXT_BOUNDARY_CHAR,
       
    83                            0, "", 0, 0);
       
    84 
       
    85     test_get_text_function(text_obj, atk_text_get_text_before_offset, ATK_TEXT_BOUNDARY_CHAR,
       
    86                            1, "T", 0, 1);
       
    87     
       
    88     /* ATK_TEXT_BOUNDARY_WORD_START */
       
    89     test_get_text_function(text_obj, atk_text_get_text_at_offset, ATK_TEXT_BOUNDARY_WORD_START,
       
    90                            0, "This ", 0, 5);
       
    91 
       
    92     test_get_text_function(text_obj, atk_text_get_text_at_offset, ATK_TEXT_BOUNDARY_WORD_START,
       
    93                            4, "This ", 0, 5);
       
    94 
       
    95     test_get_text_function(text_obj, atk_text_get_text_at_offset, ATK_TEXT_BOUNDARY_WORD_START,
       
    96                            10, "test. ", 10, 16);
       
    97 
       
    98     test_get_text_function(text_obj, atk_text_get_text_at_offset, ATK_TEXT_BOUNDARY_WORD_START,
       
    99                            58, "third.", 58, 64);
       
   100 
       
   101     test_get_text_function(text_obj, atk_text_get_text_before_offset, ATK_TEXT_BOUNDARY_WORD_START,
       
   102                            5, "This ", 0, 5);
       
   103 
       
   104     test_get_text_function(text_obj, atk_text_get_text_before_offset, ATK_TEXT_BOUNDARY_WORD_START,
       
   105                            7, "This ", 0, 5);
       
   106 
       
   107     test_get_text_function(text_obj, atk_text_get_text_after_offset, ATK_TEXT_BOUNDARY_WORD_START,
       
   108                            0, "is ", 5, 8);
       
   109 
       
   110     test_get_text_function(text_obj, atk_text_get_text_after_offset, ATK_TEXT_BOUNDARY_WORD_START,
       
   111                            4, "is ", 5, 8);
       
   112 
       
   113     test_get_text_function(text_obj, atk_text_get_text_after_offset, ATK_TEXT_BOUNDARY_WORD_START,
       
   114                            3, "is ", 5, 8);
       
   115 
       
   116     /* ATK_TEXT_BOUNDARY_WORD_END */
       
   117     test_get_text_function(text_obj, atk_text_get_text_at_offset, ATK_TEXT_BOUNDARY_WORD_END,
       
   118                            0, "This", 0, 4);
       
   119 
       
   120     test_get_text_function(text_obj, atk_text_get_text_at_offset, ATK_TEXT_BOUNDARY_WORD_END,
       
   121                            4, " is", 4, 7);
       
   122 
       
   123     test_get_text_function(text_obj, atk_text_get_text_at_offset, ATK_TEXT_BOUNDARY_WORD_END,
       
   124                            5, " is", 4, 7);
       
   125 
       
   126     test_get_text_function(text_obj, atk_text_get_text_at_offset, ATK_TEXT_BOUNDARY_WORD_END,
       
   127                            9, " test", 9, 14);
       
   128 
       
   129     test_get_text_function(text_obj, atk_text_get_text_before_offset, ATK_TEXT_BOUNDARY_WORD_END,
       
   130                            5, "This", 0, 4);
       
   131 
       
   132     test_get_text_function(text_obj, atk_text_get_text_before_offset, ATK_TEXT_BOUNDARY_WORD_END,
       
   133                            4, "This", 0, 4);
       
   134 
       
   135     test_get_text_function(text_obj, atk_text_get_text_before_offset, ATK_TEXT_BOUNDARY_WORD_END,
       
   136                            7, " is", 4, 7);
       
   137 
       
   138     test_get_text_function(text_obj, atk_text_get_text_after_offset, ATK_TEXT_BOUNDARY_WORD_END,
       
   139                            5, " a", 7, 9);
       
   140 
       
   141     test_get_text_function(text_obj, atk_text_get_text_after_offset, ATK_TEXT_BOUNDARY_WORD_END,
       
   142                            4, " a", 7, 9);
       
   143 
       
   144     test_get_text_function(text_obj, atk_text_get_text_at_offset, ATK_TEXT_BOUNDARY_WORD_END,
       
   145                            58, " third", 57, 63);
       
   146 
       
   147     /* ATK_TEXT_BOUNDARY_SENTENCE_START */
       
   148     test_get_text_function(text_obj, atk_text_get_text_at_offset, ATK_TEXT_BOUNDARY_SENTENCE_START,
       
   149                            0, "This is a test. ", 0, 16);
       
   150 
       
   151     test_get_text_function(text_obj, atk_text_get_text_at_offset, ATK_TEXT_BOUNDARY_SENTENCE_START,
       
   152                            15, "This is a test. ", 0, 16);
       
   153 
       
   154     test_get_text_function(text_obj, atk_text_get_text_after_offset, ATK_TEXT_BOUNDARY_SENTENCE_START,
       
   155                            0, "This is the second sentence. ", 16, 45);
       
   156 
       
   157     test_get_text_function(text_obj, atk_text_get_text_after_offset, ATK_TEXT_BOUNDARY_SENTENCE_START,
       
   158                            15, "This is the second sentence. ", 16, 45);
       
   159 
       
   160     test_get_text_function(text_obj, atk_text_get_text_before_offset, ATK_TEXT_BOUNDARY_SENTENCE_START,
       
   161                            16, "This is a test. ", 0, 16);
       
   162 
       
   163     test_get_text_function(text_obj, atk_text_get_text_before_offset, ATK_TEXT_BOUNDARY_SENTENCE_START,
       
   164                            44, "This is a test. ", 0, 16);
       
   165 
       
   166     test_get_text_function(text_obj, atk_text_get_text_before_offset, ATK_TEXT_BOUNDARY_SENTENCE_START,
       
   167                            15, "", 0, 0);
       
   168 
       
   169     /* ATK_TEXT_BOUNDARY_SENTENCE_END */
       
   170     test_get_text_function(text_obj, atk_text_get_text_at_offset, ATK_TEXT_BOUNDARY_SENTENCE_END,
       
   171                            0, "This is a test.", 0, 15);
       
   172 
       
   173     test_get_text_function(text_obj, atk_text_get_text_at_offset, ATK_TEXT_BOUNDARY_SENTENCE_END,
       
   174                            15, " This is the second sentence.", 15, 44);
       
   175 
       
   176     test_get_text_function(text_obj, atk_text_get_text_at_offset, ATK_TEXT_BOUNDARY_SENTENCE_END,
       
   177                            16, " This is the second sentence.", 15, 44);
       
   178 
       
   179     test_get_text_function(text_obj, atk_text_get_text_at_offset, ATK_TEXT_BOUNDARY_SENTENCE_END,
       
   180                            17, " This is the second sentence.", 15, 44);
       
   181 
       
   182     test_get_text_function(text_obj, atk_text_get_text_after_offset, ATK_TEXT_BOUNDARY_SENTENCE_END,
       
   183                            0, " This is the second sentence.", 15, 44);
       
   184 
       
   185     test_get_text_function(text_obj, atk_text_get_text_after_offset, ATK_TEXT_BOUNDARY_SENTENCE_END,
       
   186                            15, " And this the third.", 44, 64);
       
   187 
       
   188     test_get_text_function(text_obj, atk_text_get_text_before_offset, ATK_TEXT_BOUNDARY_SENTENCE_END,
       
   189                            16, "This is a test.", 0, 15);
       
   190 
       
   191     test_get_text_function(text_obj, atk_text_get_text_before_offset, ATK_TEXT_BOUNDARY_SENTENCE_END,
       
   192                            15, "This is a test.", 0, 15);
       
   193 
       
   194     test_get_text_function(text_obj, atk_text_get_text_before_offset, ATK_TEXT_BOUNDARY_SENTENCE_END,
       
   195                            14, "", 0, 0);
       
   196 
       
   197     test_get_text_function(text_obj, atk_text_get_text_before_offset, ATK_TEXT_BOUNDARY_SENTENCE_END,
       
   198                            44, " This is the second sentence.", 15, 44);
       
   199 
       
   200     /* It's trick to test these properly right now, since our a11y
       
   201        implementation splits different lines in different a11y
       
   202        items */
       
   203     /* ATK_TEXT_BOUNDARY_LINE_START */
       
   204     test_get_text_function(text_obj, atk_text_get_text_at_offset, ATK_TEXT_BOUNDARY_LINE_START,
       
   205                            0, "This is a test. This is the second sentence. And this the third.", 0, 64);
       
   206 
       
   207     /* ATK_TEXT_BOUNDARY_LINE_END */
       
   208     test_get_text_function(text_obj, atk_text_get_text_at_offset, ATK_TEXT_BOUNDARY_LINE_END,
       
   209                            0, "This is a test. This is the second sentence. And this the third.", 0, 64);
       
   210 }
       
   211 
       
   212 static void test_webkit_atk_get_text_at_offset_forms(void)
       
   213 {
       
   214     WebKitWebView* webView;
       
   215     AtkObject* obj;
       
   216     GMainLoop* loop;
       
   217     AtkText* text_obj;
       
   218 
       
   219     webView = WEBKIT_WEB_VIEW(webkit_web_view_new());
       
   220     g_object_ref_sink(webView);
       
   221     GtkAllocation alloc = { 0, 0, 800, 600 };
       
   222     gtk_widget_size_allocate(GTK_WIDGET(webView), &alloc);
       
   223     webkit_web_view_load_string(webView, contents, NULL, NULL, NULL);
       
   224     loop = g_main_loop_new(NULL, TRUE);
       
   225 
       
   226     g_idle_add((GSourceFunc)bail_out, loop);
       
   227     g_main_loop_run(loop);
       
   228 
       
   229     /* Get to the inner AtkText object */
       
   230     obj = gtk_widget_get_accessible(GTK_WIDGET(webView));
       
   231     g_assert(obj);
       
   232     obj = atk_object_ref_accessible_child(obj, 0);
       
   233     g_assert(obj);
       
   234 
       
   235     text_obj = ATK_TEXT(obj);
       
   236     g_assert(ATK_IS_TEXT(text_obj));
       
   237 
       
   238     run_get_text_tests(text_obj);
       
   239 
       
   240     g_object_unref(webView);
       
   241 }
       
   242 
       
   243 static void test_webkit_atk_get_text_at_offset(void)
       
   244 {
       
   245     WebKitWebView* webView;
       
   246     AtkObject* obj;
       
   247     GMainLoop* loop;
       
   248     AtkText* text_obj;
       
   249 
       
   250     webView = WEBKIT_WEB_VIEW(webkit_web_view_new());
       
   251     g_object_ref_sink(webView);
       
   252     GtkAllocation alloc = { 0, 0, 800, 600 };
       
   253     gtk_widget_size_allocate(GTK_WIDGET(webView), &alloc);
       
   254     webkit_web_view_load_string(webView, contents, NULL, NULL, NULL);
       
   255     loop = g_main_loop_new(NULL, TRUE);
       
   256 
       
   257     g_idle_add((GSourceFunc)bail_out, loop);
       
   258     g_main_loop_run(loop);
       
   259 
       
   260     /* Get to the inner AtkText object */
       
   261     obj = gtk_widget_get_accessible(GTK_WIDGET(webView));
       
   262     g_assert(obj);
       
   263     obj = atk_object_ref_accessible_child(obj, 0);
       
   264     g_assert(obj);
       
   265 
       
   266     text_obj = ATK_TEXT(obj);
       
   267     g_assert(ATK_IS_TEXT(text_obj));
       
   268 
       
   269     run_get_text_tests(text_obj);
       
   270 
       
   271     g_object_unref(webView);
       
   272 }
       
   273 
       
   274 static void test_webkit_atk_get_text_at_offset_newlines(void)
       
   275 {
       
   276     WebKitWebView* webView;
       
   277     AtkObject* obj;
       
   278     GMainLoop* loop;
       
   279     AtkText* text_obj;
       
   280 
       
   281     webView = WEBKIT_WEB_VIEW(webkit_web_view_new());
       
   282     g_object_ref_sink(webView);
       
   283     GtkAllocation alloc = { 0, 0, 800, 600 };
       
   284     gtk_widget_size_allocate(GTK_WIDGET(webView), &alloc);
       
   285     webkit_web_view_load_string(webView, contentsWithNewlines, NULL, NULL, NULL);
       
   286     loop = g_main_loop_new(NULL, TRUE);
       
   287 
       
   288     g_idle_add((GSourceFunc)bail_out, loop);
       
   289     g_main_loop_run(loop);
       
   290 
       
   291     /* Get to the inner AtkText object */
       
   292     obj = gtk_widget_get_accessible(GTK_WIDGET(webView));
       
   293     g_assert(obj);
       
   294     obj = atk_object_ref_accessible_child(obj, 0);
       
   295     g_assert(obj);
       
   296 
       
   297     text_obj = ATK_TEXT(obj);
       
   298     g_assert(ATK_IS_TEXT(text_obj));
       
   299 
       
   300     run_get_text_tests(text_obj);
       
   301 
       
   302     g_object_unref(webView);
       
   303 }
       
   304 
       
   305 static void test_webkit_atk_get_text_at_offset_textarea(void)
       
   306 {
       
   307     WebKitWebView* webView;
       
   308     AtkObject* obj;
       
   309     GMainLoop* loop;
       
   310     AtkText* text_obj;
       
   311 
       
   312     webView = WEBKIT_WEB_VIEW(webkit_web_view_new());
       
   313     g_object_ref_sink(webView);
       
   314     GtkAllocation alloc = { 0, 0, 800, 600 };
       
   315     gtk_widget_size_allocate(GTK_WIDGET(webView), &alloc);
       
   316     webkit_web_view_load_string(webView, contentsInTextarea, NULL, NULL, NULL);
       
   317     loop = g_main_loop_new(NULL, TRUE);
       
   318 
       
   319     g_idle_add((GSourceFunc)bail_out, loop);
       
   320     g_main_loop_run(loop);
       
   321 
       
   322     /* Get to the inner AtkText object */
       
   323     obj = gtk_widget_get_accessible(GTK_WIDGET(webView));
       
   324     g_assert(obj);
       
   325     obj = atk_object_ref_accessible_child(obj, 0);
       
   326     g_assert(obj);
       
   327     obj = atk_object_ref_accessible_child(obj, 0);
       
   328     g_assert(obj);
       
   329 
       
   330     text_obj = ATK_TEXT(obj);
       
   331     g_assert(ATK_IS_TEXT(text_obj));
       
   332 
       
   333     run_get_text_tests(text_obj);
       
   334 
       
   335     g_object_unref(webView);
       
   336 }
       
   337 
       
   338 static void test_webkit_atk_get_text_at_offset_text_input(void)
       
   339 {
       
   340     WebKitWebView* webView;
       
   341     AtkObject* obj;
       
   342     GMainLoop* loop;
       
   343     AtkText* text_obj;
       
   344 
       
   345     webView = WEBKIT_WEB_VIEW(webkit_web_view_new());
       
   346     g_object_ref_sink(webView);
       
   347     GtkAllocation alloc = { 0, 0, 800, 600 };
       
   348     gtk_widget_size_allocate(GTK_WIDGET(webView), &alloc);
       
   349     webkit_web_view_load_string(webView, contentsInTextInput, NULL, NULL, NULL);
       
   350     loop = g_main_loop_new(NULL, TRUE);
       
   351 
       
   352     g_idle_add((GSourceFunc)bail_out, loop);
       
   353     g_main_loop_run(loop);
       
   354 
       
   355     /* Get to the inner AtkText object */
       
   356     obj = gtk_widget_get_accessible(GTK_WIDGET(webView));
       
   357     g_assert(obj);
       
   358     obj = atk_object_ref_accessible_child(obj, 0);
       
   359     g_assert(obj);
       
   360     obj = atk_object_ref_accessible_child(obj, 0);
       
   361     g_assert(obj);
       
   362 
       
   363     text_obj = ATK_TEXT(obj);
       
   364     g_assert(ATK_IS_TEXT(text_obj));
       
   365 
       
   366     run_get_text_tests(text_obj);
       
   367 
       
   368     g_object_unref(webView);
       
   369 }
       
   370 
       
   371 static void testWebkitAtkGetTextInParagraphAndBodySimple(void)
       
   372 {
       
   373     WebKitWebView* webView;
       
   374     AtkObject* obj;
       
   375     AtkObject* obj1;
       
   376     AtkObject* obj2;
       
   377     GMainLoop* loop;
       
   378     AtkText* textObj1;
       
   379     AtkText* textObj2;
       
   380 
       
   381     webView = WEBKIT_WEB_VIEW(webkit_web_view_new());
       
   382     g_object_ref_sink(webView);
       
   383     GtkAllocation alloc = { 0, 0, 800, 600 };
       
   384     gtk_widget_size_allocate(GTK_WIDGET(webView), &alloc);
       
   385     webkit_web_view_load_string(webView, contentsInParagraphAndBodySimple, NULL, NULL, NULL);
       
   386     loop = g_main_loop_new(NULL, TRUE);
       
   387 
       
   388     g_idle_add((GSourceFunc)bail_out, loop);
       
   389     g_main_loop_run(loop);
       
   390 
       
   391     /* Get to the inner AtkText object */
       
   392     obj = gtk_widget_get_accessible(GTK_WIDGET(webView));
       
   393     g_assert(obj);
       
   394     obj1 = atk_object_ref_accessible_child(obj, 0);
       
   395     g_assert(obj1);
       
   396     obj2 = atk_object_ref_accessible_child(obj, 1);
       
   397     g_assert(obj2);
       
   398 
       
   399     textObj1 = ATK_TEXT(obj1);
       
   400     g_assert(ATK_IS_TEXT(textObj1));
       
   401     textObj2 = ATK_TEXT(obj2);
       
   402     g_assert(ATK_IS_TEXT(textObj2));
       
   403 
       
   404     char *text = atk_text_get_text(textObj1, 0, -1);
       
   405     g_assert_cmpstr(text, ==, "This is a test.");
       
   406 
       
   407     text = atk_text_get_text(textObj2, 0, 12);
       
   408     g_assert_cmpstr(text, ==, "Hello world.");
       
   409 
       
   410     g_object_unref(obj1);
       
   411     g_object_unref(obj2);
       
   412     g_object_unref(webView);
       
   413 }
       
   414 
       
   415 static void testWebkitAtkGetTextInParagraphAndBodyModerate(void)
       
   416 {
       
   417     WebKitWebView* webView;
       
   418     AtkObject* obj;
       
   419     AtkObject* obj1;
       
   420     AtkObject* obj2;
       
   421     GMainLoop* loop;
       
   422     AtkText* textObj1;
       
   423     AtkText* textObj2;
       
   424 
       
   425     webView = WEBKIT_WEB_VIEW(webkit_web_view_new());
       
   426     g_object_ref_sink(webView);
       
   427     GtkAllocation alloc = { 0, 0, 800, 600 };
       
   428     gtk_widget_size_allocate(GTK_WIDGET(webView), &alloc);
       
   429     webkit_web_view_load_string(webView, contentsInParagraphAndBodyModerate, NULL, NULL, NULL);
       
   430     loop = g_main_loop_new(NULL, TRUE);
       
   431 
       
   432     g_idle_add((GSourceFunc)bail_out, loop);
       
   433     g_main_loop_run(loop);
       
   434 
       
   435     /* Get to the inner AtkText object */
       
   436     obj = gtk_widget_get_accessible(GTK_WIDGET(webView));
       
   437     g_assert(obj);
       
   438     obj1 = atk_object_ref_accessible_child(obj, 0);
       
   439     g_assert(obj1);
       
   440     obj2 = atk_object_ref_accessible_child(obj, 1);
       
   441     g_assert(obj2);
       
   442 
       
   443     textObj1 = ATK_TEXT(obj1);
       
   444     g_assert(ATK_IS_TEXT(textObj1));
       
   445     textObj2 = ATK_TEXT(obj2);
       
   446     g_assert(ATK_IS_TEXT(textObj2));
       
   447 
       
   448     char *text = atk_text_get_text(textObj1, 0, -1);
       
   449     g_assert_cmpstr(text, ==, "This is a test.");
       
   450 
       
   451     text = atk_text_get_text(textObj2, 0, 53);
       
   452     g_assert_cmpstr(text, ==, "Hello world.\nThis sentence is green.\nThis one is not.");
       
   453 
       
   454     g_object_unref(obj1);
       
   455     g_object_unref(obj2);
       
   456     g_object_unref(webView);
       
   457 }
       
   458 
       
   459 static void testWebkitAtkGetTextInTable(void)
       
   460 {
       
   461     WebKitWebView* webView;
       
   462     AtkObject* obj;
       
   463     GMainLoop* loop;
       
   464 
       
   465     webView = WEBKIT_WEB_VIEW(webkit_web_view_new());
       
   466     g_object_ref_sink(webView);
       
   467     GtkAllocation alloc = { 0, 0, 800, 600 };
       
   468     gtk_widget_size_allocate(GTK_WIDGET(webView), &alloc);
       
   469     webkit_web_view_load_string(webView, contentsInTable, NULL, NULL, NULL);
       
   470     loop = g_main_loop_new(NULL, TRUE);
       
   471 
       
   472     g_idle_add((GSourceFunc)bail_out, loop);
       
   473     g_main_loop_run(loop);
       
   474 
       
   475     obj = gtk_widget_get_accessible(GTK_WIDGET(webView));
       
   476     g_assert(obj);
       
   477     obj = atk_object_ref_accessible_child(obj, 0);
       
   478     g_assert(obj);
       
   479 
       
   480     /* Tables should not implement AtkText */
       
   481     g_assert(G_TYPE_INSTANCE_GET_INTERFACE(obj, ATK_TYPE_TEXT, AtkTextIface) == NULL);
       
   482 
       
   483     g_object_unref(obj);
       
   484     g_object_unref(webView);
       
   485 }
       
   486 
       
   487 static void testWebkitAtkGetHeadersInTable(void)
       
   488 {
       
   489     WebKitWebView* webView;
       
   490     AtkObject* axWebView;
       
   491     AtkObject* table;
       
   492     AtkObject* colHeader;
       
   493     AtkObject* rowHeader;
       
   494     GMainLoop* loop;
       
   495 
       
   496     webView = WEBKIT_WEB_VIEW(webkit_web_view_new());
       
   497     g_object_ref_sink(webView);
       
   498     GtkAllocation alloc = { 0, 0, 800, 600 };
       
   499     gtk_widget_size_allocate(GTK_WIDGET(webView), &alloc);
       
   500     webkit_web_view_load_string(webView, contentsInTableWithHeaders, NULL, NULL, NULL);
       
   501     loop = g_main_loop_new(NULL, TRUE);
       
   502 
       
   503     g_idle_add((GSourceFunc)bail_out, loop);
       
   504     g_main_loop_run(loop);
       
   505 
       
   506     axWebView = gtk_widget_get_accessible(GTK_WIDGET(webView));
       
   507     g_assert(axWebView);
       
   508 
       
   509     // Check table with both column and row headers
       
   510     table = atk_object_ref_accessible_child(axWebView, 0);
       
   511     g_assert(table);
       
   512     g_assert(atk_object_get_role(table) == ATK_ROLE_TABLE);
       
   513 
       
   514     colHeader = atk_table_get_column_header(ATK_TABLE(table), 0);
       
   515     g_assert(colHeader);
       
   516     g_assert(atk_object_get_role(colHeader) == ATK_ROLE_TABLE_CELL);
       
   517     g_assert(atk_object_get_index_in_parent(colHeader) == 0);
       
   518 
       
   519     colHeader = atk_table_get_column_header(ATK_TABLE(table), 1);
       
   520     g_assert(colHeader);
       
   521     g_assert(atk_object_get_role(colHeader) == ATK_ROLE_TABLE_CELL);
       
   522     g_assert(atk_object_get_index_in_parent(colHeader) == 1);
       
   523 
       
   524     colHeader = atk_table_get_column_header(ATK_TABLE(table), 2);
       
   525     g_assert(colHeader);
       
   526     g_assert(atk_object_get_role(colHeader) == ATK_ROLE_TABLE_CELL);
       
   527     g_assert(atk_object_get_index_in_parent(colHeader) == 2);
       
   528 
       
   529     colHeader = atk_table_get_column_header(ATK_TABLE(table), 3);
       
   530     g_assert(colHeader);
       
   531     g_assert(atk_object_get_role(colHeader) == ATK_ROLE_TABLE_CELL);
       
   532     g_assert(atk_object_get_index_in_parent(colHeader) == 2);
       
   533 
       
   534     rowHeader = atk_table_get_row_header(ATK_TABLE(table), 0);
       
   535     g_assert(rowHeader);
       
   536     g_assert(atk_object_get_role(rowHeader) == ATK_ROLE_TABLE_CELL);
       
   537     g_assert(atk_object_get_index_in_parent(rowHeader) == 0);
       
   538 
       
   539     rowHeader = atk_table_get_row_header(ATK_TABLE(table), 1);
       
   540     g_assert(rowHeader);
       
   541     g_assert(atk_object_get_role(rowHeader) == ATK_ROLE_TABLE_CELL);
       
   542     g_assert(atk_object_get_index_in_parent(rowHeader) == 3);
       
   543 
       
   544     rowHeader = atk_table_get_row_header(ATK_TABLE(table), 2);
       
   545     g_assert(rowHeader);
       
   546     g_assert(atk_object_get_role(rowHeader) == ATK_ROLE_TABLE_CELL);
       
   547     g_assert(atk_object_get_index_in_parent(rowHeader) == 7);
       
   548 
       
   549     rowHeader = atk_table_get_row_header(ATK_TABLE(table), 3);
       
   550     g_assert(rowHeader);
       
   551     g_assert(atk_object_get_role(rowHeader) == ATK_ROLE_TABLE_CELL);
       
   552     g_assert(atk_object_get_index_in_parent(rowHeader) == 7);
       
   553 
       
   554     g_object_unref(table);
       
   555 
       
   556     // Check table with no headers at all
       
   557     table = atk_object_ref_accessible_child(axWebView, 1);
       
   558     g_assert(table);
       
   559     g_assert(atk_object_get_role(table) == ATK_ROLE_TABLE);
       
   560 
       
   561     colHeader = atk_table_get_column_header(ATK_TABLE(table), 0);
       
   562     g_assert(colHeader == 0);
       
   563 
       
   564     colHeader = atk_table_get_column_header(ATK_TABLE(table), 1);
       
   565     g_assert(colHeader == 0);
       
   566 
       
   567     rowHeader = atk_table_get_row_header(ATK_TABLE(table), 0);
       
   568     g_assert(rowHeader == 0);
       
   569 
       
   570     rowHeader = atk_table_get_row_header(ATK_TABLE(table), 1);
       
   571     g_assert(rowHeader == 0);
       
   572 
       
   573     g_object_unref(table);
       
   574     g_object_unref(webView);
       
   575 }
       
   576 
       
   577 static gint compAtkAttribute(AtkAttribute* a1, AtkAttribute* a2)
       
   578 {
       
   579     gint strcmpVal;
       
   580     strcmpVal = g_strcmp0(a1->name, a2->name);
       
   581     if (strcmpVal)
       
   582         return strcmpVal;
       
   583     return g_strcmp0(a1->value, a2->value);
       
   584 }
       
   585 
       
   586 static gint compAtkAttributeName(AtkAttribute* a1, AtkAttribute* a2)
       
   587 {
       
   588     return g_strcmp0(a1->name, a2->name);
       
   589 }
       
   590 
       
   591 static gboolean atkAttributeSetAttributeHasValue(AtkAttributeSet* set, AtkTextAttribute attribute, const gchar* value)
       
   592 {
       
   593     GSList *element;
       
   594     AtkAttribute at;
       
   595     gboolean result;
       
   596     at.name = (gchar *)atk_text_attribute_get_name(attribute);
       
   597     element = g_slist_find_custom(set, &at, (GCompareFunc)compAtkAttributeName);
       
   598     result = element && !g_strcmp0(((AtkAttribute*)(element->data))->value, value);
       
   599     return result;
       
   600 }
       
   601 
       
   602 static gboolean atkAttributeSetAreEqual(AtkAttributeSet* set1, AtkAttributeSet* set2)
       
   603 {
       
   604     if (!set1)
       
   605         return !set2;
       
   606 
       
   607     set1 = g_slist_sort(set1, (GCompareFunc)compAtkAttribute);
       
   608     set2 = g_slist_sort(set2, (GCompareFunc)compAtkAttribute);
       
   609 
       
   610     while (set1) {
       
   611         if (!set2 || compAtkAttribute(set1->data, set2->data))
       
   612             return FALSE;
       
   613 
       
   614         set1 = set1->next;
       
   615         set2 = set2->next;
       
   616     }
       
   617 
       
   618     return (!set2);
       
   619 }
       
   620 
       
   621 static void testWebkitAtkTextAttributes(void)
       
   622 {
       
   623     WebKitWebView* webView;
       
   624     AtkObject* obj;
       
   625     AtkObject* child;
       
   626     GMainLoop* loop;
       
   627     AtkText* childText;
       
   628     AtkAttributeSet* set1;
       
   629     AtkAttributeSet* set2;
       
   630     AtkAttributeSet* set3;
       
   631     AtkAttributeSet* set4;
       
   632     gint startOffset, endOffset;
       
   633 
       
   634     webView = WEBKIT_WEB_VIEW(webkit_web_view_new());
       
   635     g_object_ref_sink(webView);
       
   636     GtkAllocation alloc = { 0, 0, 800, 600 };
       
   637     gtk_widget_size_allocate(GTK_WIDGET(webView), &alloc);
       
   638 
       
   639     webkit_web_view_load_string(webView, textWithAttributes, NULL, NULL, NULL);
       
   640     loop = g_main_loop_new(NULL, TRUE);
       
   641 
       
   642     g_idle_add((GSourceFunc)bail_out, loop);
       
   643     g_main_loop_run(loop);
       
   644 
       
   645     obj = gtk_widget_get_accessible(GTK_WIDGET(webView));
       
   646     g_assert(obj);
       
   647 
       
   648     child = atk_object_ref_accessible_child(obj, 0);
       
   649     g_assert(child && ATK_IS_TEXT(child));
       
   650     childText = ATK_TEXT(child);
       
   651     set1 = atk_text_get_run_attributes(childText, 0, &startOffset, &endOffset);
       
   652     g_assert_cmpint(startOffset, ==, 0);
       
   653     g_assert_cmpint(endOffset, ==, 12);
       
   654     g_assert(atkAttributeSetAreEqual(set1, NULL));
       
   655 
       
   656     set2 = atk_text_get_run_attributes(childText, 15, &startOffset, &endOffset);
       
   657     g_assert_cmpint(startOffset, ==, 12);
       
   658     g_assert_cmpint(endOffset, ==, 17);
       
   659     g_assert(atkAttributeSetAttributeHasValue(set2, ATK_TEXT_ATTR_STYLE, "italic"));
       
   660 
       
   661     set3 = atk_text_get_run_attributes(childText, 17, &startOffset, &endOffset);
       
   662     g_assert_cmpint(startOffset, ==, 17);
       
   663     g_assert_cmpint(endOffset, ==, 40);
       
   664     g_assert(atkAttributeSetAttributeHasValue(set3, ATK_TEXT_ATTR_WEIGHT, "700"));
       
   665 
       
   666     set4 = atk_text_get_default_attributes(childText);
       
   667     g_assert(atkAttributeSetAttributeHasValue(set4, ATK_TEXT_ATTR_STYLE, "normal"));
       
   668     g_assert(atkAttributeSetAttributeHasValue(set4, ATK_TEXT_ATTR_JUSTIFICATION, "right"));
       
   669     g_assert(atkAttributeSetAttributeHasValue(set4, ATK_TEXT_ATTR_SIZE, "14"));
       
   670     atk_attribute_set_free(set1);
       
   671     atk_attribute_set_free(set2);
       
   672     atk_attribute_set_free(set3);
       
   673     atk_attribute_set_free(set4);
       
   674 
       
   675     child = atk_object_ref_accessible_child(obj, 1);
       
   676     g_assert(child && ATK_IS_TEXT(child));
       
   677     childText = ATK_TEXT(child);
       
   678 
       
   679     set1 = atk_text_get_default_attributes(childText);
       
   680     g_assert(atkAttributeSetAttributeHasValue(set1, ATK_TEXT_ATTR_FAMILY_NAME, "monospace"));
       
   681     g_assert(atkAttributeSetAttributeHasValue(set1, ATK_TEXT_ATTR_STYLE, "normal"));
       
   682     g_assert(atkAttributeSetAttributeHasValue(set1, ATK_TEXT_ATTR_STRIKETHROUGH, "false"));
       
   683     g_assert(atkAttributeSetAttributeHasValue(set1, ATK_TEXT_ATTR_WEIGHT, "400"));
       
   684     g_assert(atkAttributeSetAttributeHasValue(set1, ATK_TEXT_ATTR_FG_COLOR, "120,121,122"));
       
   685 
       
   686     set2 = atk_text_get_run_attributes(childText, 43, &startOffset, &endOffset);
       
   687     g_assert_cmpint(startOffset, ==, 43);
       
   688     g_assert_cmpint(endOffset, ==, 80);
       
   689     // Checks that default attributes of text are not returned when called to atk_text_get_run_attributes
       
   690     g_assert(!atkAttributeSetAttributeHasValue(set2, ATK_TEXT_ATTR_FG_COLOR, "120,121,122"));
       
   691     g_assert(atkAttributeSetAttributeHasValue(set2, ATK_TEXT_ATTR_UNDERLINE, "single"));
       
   692     g_assert(atkAttributeSetAttributeHasValue(set2, ATK_TEXT_ATTR_BG_COLOR, "80,81,82"));
       
   693     atk_attribute_set_free(set1);
       
   694     atk_attribute_set_free(set2);
       
   695 
       
   696     child = atk_object_ref_accessible_child(obj, 2);
       
   697     g_assert(child && ATK_IS_TEXT(child));
       
   698     childText = ATK_TEXT(child);
       
   699 
       
   700     set1 = atk_text_get_run_attributes(childText, 0, &startOffset, &endOffset);
       
   701     set2 = atk_text_get_run_attributes(childText, 3, &startOffset, &endOffset);
       
   702     g_assert(atkAttributeSetAreEqual(set1, set2));
       
   703     atk_attribute_set_free(set2);
       
   704 
       
   705     set2 = atk_text_get_run_attributes(childText, 1, &startOffset, &endOffset);
       
   706     set3 = atk_text_get_run_attributes(childText, 5, &startOffset, &endOffset);
       
   707     g_assert(atkAttributeSetAreEqual(set2, set3));
       
   708     g_assert(!atkAttributeSetAreEqual(set1, set2));
       
   709     atk_attribute_set_free(set3);
       
   710 
       
   711     set3 = atk_text_get_run_attributes(childText, 2, &startOffset, &endOffset);
       
   712     set4 = atk_text_get_run_attributes(childText, 6, &startOffset, &endOffset);
       
   713     g_assert(atkAttributeSetAreEqual(set3, set4));
       
   714     g_assert(!atkAttributeSetAreEqual(set1, set3));
       
   715     g_assert(!atkAttributeSetAreEqual(set2, set3));
       
   716     atk_attribute_set_free(set1);
       
   717     atk_attribute_set_free(set2);
       
   718     atk_attribute_set_free(set3);
       
   719     atk_attribute_set_free(set4);
       
   720 
       
   721     child = atk_object_ref_accessible_child(obj, 3);
       
   722     g_assert(child && ATK_IS_TEXT(child));
       
   723     childText = ATK_TEXT(child);
       
   724     set1 = atk_text_get_run_attributes(childText, 24, &startOffset, &endOffset);
       
   725     g_assert_cmpint(startOffset, ==, 21);
       
   726     g_assert_cmpint(endOffset, ==, 25);
       
   727     g_assert(atkAttributeSetAttributeHasValue(set1, ATK_TEXT_ATTR_STRIKETHROUGH, "true"));
       
   728 
       
   729     set2 = atk_text_get_run_attributes(childText, 25, &startOffset, &endOffset);
       
   730     g_assert_cmpint(startOffset, ==, 25);
       
   731     g_assert_cmpint(endOffset, ==, 30);
       
   732     g_assert(atkAttributeSetAreEqual(set2, NULL));
       
   733 
       
   734     set3 = atk_text_get_default_attributes(childText);
       
   735     g_assert(atkAttributeSetAttributeHasValue(set3, ATK_TEXT_ATTR_JUSTIFICATION, "center"));
       
   736     atk_attribute_set_free(set1);
       
   737     atk_attribute_set_free(set2);
       
   738     atk_attribute_set_free(set3);
       
   739 }
       
   740 
       
   741 int main(int argc, char** argv)
       
   742 {
       
   743     g_thread_init(NULL);
       
   744     gtk_test_init(&argc, &argv, NULL);
       
   745 
       
   746     g_test_bug_base("https://bugs.webkit.org/");
       
   747     g_test_add_func("/webkit/atk/get_text_at_offset", test_webkit_atk_get_text_at_offset);
       
   748     g_test_add_func("/webkit/atk/get_text_at_offset_forms", test_webkit_atk_get_text_at_offset_forms);
       
   749     g_test_add_func("/webkit/atk/get_text_at_offset_newlines", test_webkit_atk_get_text_at_offset_newlines);
       
   750     g_test_add_func("/webkit/atk/get_text_at_offset_textarea", test_webkit_atk_get_text_at_offset_textarea);
       
   751     g_test_add_func("/webkit/atk/get_text_at_offset_text_input", test_webkit_atk_get_text_at_offset_text_input);
       
   752     g_test_add_func("/webkit/atk/getTextInParagraphAndBodySimple", testWebkitAtkGetTextInParagraphAndBodySimple);
       
   753     g_test_add_func("/webkit/atk/getTextInParagraphAndBodyModerate", testWebkitAtkGetTextInParagraphAndBodyModerate);
       
   754     g_test_add_func("/webkit/atk/getTextInTable", testWebkitAtkGetTextInTable);
       
   755     g_test_add_func("/webkit/atk/getHeadersInTable", testWebkitAtkGetHeadersInTable);
       
   756     g_test_add_func("/webkit/atk/textAttributes", testWebkitAtkTextAttributes);
       
   757     return g_test_run ();
       
   758 }
       
   759 
       
   760 #else
       
   761 int main(int argc, char** argv)
       
   762 {
       
   763     g_critical("You will need at least glib-2.16.0 and gtk-2.14.0 to run the unit tests. Doing nothing now.");
       
   764     return 0;
       
   765 }
       
   766 
       
   767 #endif