Back to index

nux  3.0.0
nux_automated_test_framework.cpp
Go to the documentation of this file.
00001 /*
00002  * Copyright 2010 Inalogic Inc.
00003  *
00004  * This program is free software: you can redistribute it and/or modify it
00005  * under the terms of the GNU General Public License version 3, as published
00006  * by the  Free Software Foundation.
00007  *
00008  * This program is distributed in the hope that it will be useful, but
00009  * WITHOUT ANY WARRANTY; without even the implied warranties of
00010  * MERCHANTABILITY, SATISFACTORY QUALITY or FITNESS FOR A PARTICULAR
00011  * PURPOSE.  See the GNU General Public License for more details.
00012  *
00013  * You should have received a copy of the GNU General Public License
00014  * version 3 along with this program.  If not, see
00015  * <http://www.gnu.org/licenses/>
00016  *
00017  * Authored by: Jay Taoko <jaytaoko@inalogic.com>
00018  *
00019  */
00020 
00021 #include "Nux/Nux.h"
00022 #include <X11/extensions/XTest.h>
00023 #include <X11/keysym.h> 
00024 #include "nux_automated_test_framework.h"
00025 
00026 
00027 int NuxAutomatedTestFramework::mouse_motion_time_span = 1000; // milliseconds
00028 int NuxAutomatedTestFramework::mouse_click_time_span = 300;   // milliseconds
00029 int NuxAutomatedTestFramework::minimum_sleep_time = 600;      // milliseconds
00030 int NuxAutomatedTestFramework::safety_border_inside_view = 1; // pixels
00031 
00032 NuxAutomatedTestFramework::NuxAutomatedTestFramework(nux::WindowThread *window_thread)
00033 {
00034   ready_to_start_ = false;
00035   display_ = NULL;
00036   window_thread_ = window_thread;
00037   window_x_ = 0;
00038   window_y_ = 0;
00039   window_width_ = 0;
00040   window_height_ = 0;
00041   terminate_when_test_over_ = false;
00042 }
00043 
00044 NuxAutomatedTestFramework::~NuxAutomatedTestFramework()
00045 {
00046   XCloseDisplay(display_);
00047 }
00048 
00049 void NuxAutomatedTestFramework::SetTerminateProgramWhenDone(bool terminate)
00050 {
00051   terminate_when_test_over_ = terminate;
00052 }
00053 
00054 bool NuxAutomatedTestFramework::WhenDoneTerminateProgram()
00055 {
00056   return terminate_when_test_over_;
00057 }
00058 
00059 void NuxAutomatedTestFramework::Startup()
00060 {
00061   display_ = XOpenDisplay(NULL);
00062   nux::Geometry rect = window_thread_->GetGraphicsDisplay().GetWindowGeometry();
00063   //nuxDebugMsg("Window geometry: (%d, %d, %d, %d)", rect.x, rect.y, rect.width, rect.height);
00064 
00065   window_x_ = rect.x;
00066   window_y_ = rect.y;
00067   window_width_ = rect.width;
00068   window_height_ = rect.height;
00069 }
00070 
00071 void NuxAutomatedTestFramework::ViewSendMouseClick(nux::View *view, int button)
00072 {
00073   nux::Rect r;
00074   if (view)
00075   {
00076     r = view->GetAbsoluteGeometry();
00077     r.OffsetPosition(window_x_ + r.width/2, window_y_ + r.height/2);
00078   }
00079   else
00080   {
00081     r = window_thread_->GetGraphicsDisplay().GetWindowGeometry();
00082     r.OffsetPosition(r.width/2, r.height/2);
00083   }
00084 
00085   SendFakeMouseMotionEvent(r.x, r.y, NuxAutomatedTestFramework::mouse_motion_time_span);
00086   SendFakeMouseEvent(button, true);
00087   nux::SleepForMilliseconds(NuxAutomatedTestFramework::mouse_click_time_span);
00088   SendFakeMouseEvent(button, false);
00089 
00090   XSync(display_, False);
00091   nux::SleepForMilliseconds(NuxAutomatedTestFramework::minimum_sleep_time);
00092 }
00093 
00094 void NuxAutomatedTestFramework::ViewSendMouseDoubleClick(nux::View *view, int button)
00095 {
00096   nux::Rect r;
00097   if (view)
00098   {
00099     r = view->GetAbsoluteGeometry();
00100     r.OffsetPosition(window_x_ + r.width/2, window_y_ + r.height/2);
00101   }
00102   else
00103   {
00104     r = window_thread_->GetGraphicsDisplay().GetWindowGeometry();
00105     r.OffsetPosition(r.width/2, r.height/2);
00106   }
00107     
00108   // Send the mouse to the center of the view
00109   SendFakeMouseMotionEvent(r.x, r.y, NuxAutomatedTestFramework::mouse_motion_time_span);
00110 
00111   XTestFakeButtonEvent(display_, button, true,  CurrentTime);
00112   XTestFakeButtonEvent(display_, button, false,  CurrentTime);
00113   XTestFakeButtonEvent(display_, button, true,  CurrentTime);
00114   XTestFakeButtonEvent(display_, button, false,  CurrentTime);
00115   XSync(display_, False);
00116   nux::SleepForMilliseconds(NuxAutomatedTestFramework::minimum_sleep_time);
00117 }
00118 
00119 void NuxAutomatedTestFramework::ViewSendMouseDown(nux::View *view, int button)
00120 {
00121   XEvent event;
00122   /* Get the current pointer position */  
00123   XQueryPointer(display_, RootWindow(display_, 0),  
00124         &event.xbutton.root, &event.xbutton.window,  
00125         &event.xbutton.x_root, &event.xbutton.y_root,  
00126         &event.xbutton.x, &event.xbutton.y,  
00127         &event.xbutton.state);
00128 
00129   int current_x = event.xbutton.x - window_x_;
00130   int current_y = event.xbutton.y - window_y_;
00131 
00132   nux::Rect r = view->GetAbsoluteGeometry();
00133 
00134   if (!r.IsInside(nux::Point(current_x, current_y)))
00135   {
00136     // The mouse pointer is not inside the view.
00137     // Move the mouse pointer to the center of the view.
00138     r.OffsetPosition(window_x_, window_y_);
00139 
00140     // Go to the center of the view
00141     int view_center_x = r.x + r.width/2;
00142     int view_center_y = r.y + r.height/2;
00143     SendFakeMouseMotionEvent(view_center_x, view_center_y, NuxAutomatedTestFramework::mouse_motion_time_span);
00144     nux::SleepForMilliseconds(minimum_sleep_time);
00145   }
00146   SendFakeMouseEvent(button, true);
00147 }
00148 
00149 void NuxAutomatedTestFramework::ViewSendMouseUp(nux::View *view, int button)
00150 {
00151   //   nux::Rect r = view->GetAbsoluteGeometry();
00152   // r.OffsetPosition(window_x_, window_y_);
00153 
00154   // int view_center_x = r.x + r.width/2;
00155   // int view_center_y = r.y + r.height/2;
00156 
00157   // SendFakeMouseMotionEvent(view_center_x, view_center_y, 1000);
00158   // nux::SleepForMilliseconds(minimum_sleep_time);
00159   SendFakeMouseEvent(button, false);
00160 }
00161 
00162 void NuxAutomatedTestFramework::ViewSendMouseDrag(nux::View *view, int button_index, int x0, int y0, int x1, int y1)
00163 {
00164   nux::Rect r0 = view->GetAbsoluteGeometry();
00165   nux::Rect r1 = view->GetAbsoluteGeometry();
00166   r0.OffsetPosition(window_x_ + x0, window_y_ + y0);
00167   r1.OffsetPosition(window_x_ + x1, window_y_ + y1);
00168 
00169   // Go to first point
00170   SendFakeMouseMotionEvent(r0.x, r0.y, NuxAutomatedTestFramework::mouse_motion_time_span);
00171   nux::SleepForMilliseconds(minimum_sleep_time);
00172   
00173   // Mouse down
00174   ViewSendMouseDown(view, button_index);
00175 
00176   // Drag to second point
00177   SendFakeMouseMotionEvent(r1.x, r1.y, NuxAutomatedTestFramework::mouse_motion_time_span);
00178   nux::SleepForMilliseconds(minimum_sleep_time);
00179 
00180   // Mouse up
00181   ViewSendMouseUp(view, button_index);
00182 }
00183 
00184 void NuxAutomatedTestFramework::ViewSendMouseMotionTo(nux::View *view, int x, int y)
00185 {
00186   nux::Rect r;
00187   if (view)
00188   {
00189     r = view->GetAbsoluteGeometry();
00190     r.OffsetPosition(window_x_ + x, window_y_ + y);
00191   }
00192   else
00193   {
00194     r = window_thread_->GetGraphicsDisplay().GetWindowGeometry();
00195     r.OffsetPosition(x, y);
00196   }
00197 
00198   SendFakeMouseMotionEvent(r.x, r.y, NuxAutomatedTestFramework::mouse_motion_time_span);
00199 }
00200 
00201 void NuxAutomatedTestFramework::ViewSendMouseMotionToCenter(nux::View *view)
00202 {
00203   nux::Rect r;
00204   if (view)
00205   {
00206     r = view->GetAbsoluteGeometry();
00207     r.OffsetPosition(window_x_, window_y_);
00208   }
00209   else
00210   {
00211     r = window_thread_->GetGraphicsDisplay().GetWindowGeometry();
00212   }
00213 
00214   int view_center_x = r.x + r.width/2;
00215   int view_center_y = r.y + r.height/2;
00216 
00217   SendFakeMouseMotionEvent(view_center_x, view_center_y, NuxAutomatedTestFramework::mouse_motion_time_span);
00218 }
00219 
00220 void NuxAutomatedTestFramework::ViewSendMouseMotionToTopLeft(nux::View *view)
00221 {
00222   nux::Rect r = view->GetAbsoluteGeometry();
00223   r.OffsetPosition(window_x_, window_y_);
00224 
00225   SendFakeMouseMotionEvent(r.x + safety_border_inside_view, r.y + safety_border_inside_view, NuxAutomatedTestFramework::mouse_motion_time_span);
00226 }
00227 
00228 void NuxAutomatedTestFramework::ViewSendMouseMotionToTopRight(nux::View *view)
00229 {
00230   nux::Rect r = view->GetAbsoluteGeometry();
00231   r.OffsetPosition(window_x_, window_y_);
00232 
00233   SendFakeMouseMotionEvent(r.x + r.width-1, r.y+safety_border_inside_view, NuxAutomatedTestFramework::mouse_motion_time_span);
00234 }
00235 
00236 void NuxAutomatedTestFramework::ViewSendMouseMotionToBottomLeft(nux::View *view)
00237 {
00238   nux::Rect r = view->GetAbsoluteGeometry();
00239   r.OffsetPosition(window_x_, window_y_);
00240 
00241   SendFakeMouseMotionEvent(r.x+safety_border_inside_view, r.y + r.height-1, NuxAutomatedTestFramework::mouse_motion_time_span);
00242 }
00243 
00244 void NuxAutomatedTestFramework::ViewSendMouseMotionToBottomRight(nux::View *view)
00245 {
00246   nux::Rect r = view->GetAbsoluteGeometry();
00247   r.OffsetPosition(window_x_, window_y_);
00248 
00249   SendFakeMouseMotionEvent(r.x + r.width-1, r.y + r.height-1, NuxAutomatedTestFramework::mouse_motion_time_span);
00250 }
00251 
00252 void NuxAutomatedTestFramework::ViewSendChar(const char c)
00253 {
00254   KeySym modifier = 0;
00255 
00256   if ((c >= 'A') && (c <= 'Z'))
00257   {
00258     modifier = XK_Shift_L;
00259   }
00260 
00261   std::string s(1, c);
00262 
00263   if (c == ' ')
00264   {
00265     SendFakeKeyEvent(XK_space, modifier);
00266   }
00267   else
00268   {   
00269     SendFakeKeyEvent(XStringToKeysym(s.c_str()), modifier);
00270   }
00271 
00272   nux::SleepForMilliseconds(300);
00273 }
00274 
00275 void NuxAutomatedTestFramework::ViewSendString(const std::string &str)
00276 {
00277   int l = str.length();
00278   if (l == 0)
00279     return;
00280   
00281   int i = 0;
00282 
00283   while (i < l)
00284   {
00285     KeySym modifier = 0;
00286     char c = str[i++];
00287 
00288     if ((c >= 'A') && (c <= 'Z'))
00289     {
00290       modifier = XK_Shift_L;
00291     }
00292 
00293     std::string s(1, c);
00294 
00295     if (c == ' ')
00296     {
00297       SendFakeKeyEvent(XK_space, modifier);
00298     }
00299     else if (c == '^')
00300     {
00301       SendFakeKeyEvent(XK_asciicircum, XK_Shift_L);
00302     }
00303     else if (c == '~')
00304     {
00305       SendFakeKeyEvent(XK_asciitilde, XK_Shift_L);
00306     }
00307     else if (c == '`')
00308     {
00309       SendFakeKeyEvent(XK_asciitilde, 0);
00310     }
00311     else if (c == '=')
00312     {
00313       SendFakeKeyEvent(XK_equal, 0);
00314     }
00315     else if (c == '\"')
00316     {
00317       SendFakeKeyEvent(XK_quotedbl, XK_Shift_L);
00318     }
00319     else if (c == '!')
00320     {
00321       SendFakeKeyEvent(XK_exclam, XK_Shift_L);
00322     }
00323     else if (c == '|')
00324     {
00325       SendFakeKeyEvent(XK_bar, XK_Shift_L);
00326     }
00327     else if (c == '/')
00328     {
00329       SendFakeKeyEvent(XK_slash, 0);
00330     }
00331     else if (c == '\\')
00332     {
00333       SendFakeKeyEvent(XK_backslash, 0);
00334     }
00335     else if (c == '-')
00336     {
00337       SendFakeKeyEvent(XK_minus, 0);
00338     }
00339     else if (c == '+')
00340     {
00341       SendFakeKeyEvent(XK_plus, XK_Shift_L);
00342     }
00343     else if (c == ',')
00344     {
00345       SendFakeKeyEvent(XK_comma, 0);
00346     }
00347     else if (c == '_')
00348     {
00349       SendFakeKeyEvent(XK_underscore, XK_Shift_L);
00350     }
00351     else if (c == '<')
00352     { 
00353       SendFakeKeyEvent(XK_comma, XK_Shift_L);
00354     }
00355     else if (c == '>')
00356     {
00357       SendFakeKeyEvent(XK_greater, XK_Shift_L);
00358     }
00359     else if (c == '.')
00360     {
00361       SendFakeKeyEvent(XK_period, 0);
00362     }
00363     else if (c == '?')
00364     {
00365       SendFakeKeyEvent(XK_question, XK_Shift_L);
00366     }
00367     else if (c == '\'')
00368     {
00369       SendFakeKeyEvent(XK_quoteright, 0);
00370     }
00371     else if (c == ';')
00372     {
00373       SendFakeKeyEvent(XK_semicolon, 0);
00374     }
00375     else if (c == ':')
00376     {
00377       SendFakeKeyEvent(XK_colon, XK_Shift_L);
00378     }
00379     else if (c == '%')
00380     {
00381       SendFakeKeyEvent(XK_percent, XK_Shift_L);
00382     }
00383     else if (c == '(')
00384     {
00385       SendFakeKeyEvent(XK_parenleft, XK_Shift_L);
00386     }
00387     else if (c == ')')
00388     {
00389       SendFakeKeyEvent(XK_parenright, XK_Shift_L);
00390     }
00391     else
00392     {   
00393       SendFakeKeyEvent(XStringToKeysym(s.c_str()), modifier);
00394     }
00395     nux::SleepForMilliseconds(300);
00396   }
00397 }
00398 
00399 void NuxAutomatedTestFramework::ViewSendCompositionKeys(const std::string& str)
00400 {
00401   int l = str.length();
00402   if (l == 0)
00403     return;
00404   
00405   SendFakeKeyEvent(XK_Multi_key, 0);
00406   ViewSendString(str);
00407 }
00408 
00409 void NuxAutomatedTestFramework::ViewSendKeyCombo(KeySym modsym0, KeySym modsym1, KeySym modsym2, const char c)
00410 {
00411   KeyCode keycode = 0;
00412   KeyCode modcode0 = 0;
00413   KeyCode modcode1 = 0;
00414   KeyCode modcode2 = 0;
00415   
00416   if (c != 0)
00417   {
00418     printf("ViewSendKeyCombo");
00419     std::string s(1, c);
00420     keycode = XKeysymToKeycode(display_, XStringToKeysym(s.c_str()));
00421   }
00422   XTestGrabControl(display_, True);
00423   
00424   /* Generate modkey press */
00425   if (modsym0 != 0)
00426   {
00427     modcode0 = XKeysymToKeycode(display_, modsym0);
00428     XTestFakeKeyEvent(display_, modcode0, True, 0);
00429   }
00430   if (modsym1 != 0)
00431   {
00432     modcode1 = XKeysymToKeycode(display_, modsym1);
00433     XTestFakeKeyEvent(display_, modcode1, True, 0);
00434   }
00435   if (modsym2 != 0)
00436   {
00437     modcode2 = XKeysymToKeycode(display_, modsym2);
00438     XTestFakeKeyEvent(display_, modcode2, True, 0);
00439   }
00440       
00441   /* Generate regular key press and release */
00442   if (keycode)
00443   {
00444     XTestFakeKeyEvent(display_, keycode, True, 0);
00445     XTestFakeKeyEvent(display_, keycode, False, 0);
00446   }
00447   
00448   /* Generate modkey release */
00449   if (modsym0 != 0)
00450   {
00451     XTestFakeKeyEvent(display_, modcode0, False, 0);
00452   }
00453   if (modsym1 != 0)
00454   {
00455     XTestFakeKeyEvent(display_, modcode1, False, 0);
00456   }
00457   if (modsym2 != 0)
00458   {
00459     XTestFakeKeyEvent(display_, modcode2, False, 0);
00460   }
00461     
00462   XSync(display_, False);
00463   XTestGrabControl(display_, False);  
00464 }
00465 
00466 void NuxAutomatedTestFramework::ViewSendCtrlA()
00467 {
00468   ViewSendKeyCombo(XK_Control_L, 0, 0, 'a');
00469 }
00470 
00471 void NuxAutomatedTestFramework::ViewSendDelete()
00472 {
00473   SendFakeKeyEvent(XK_Delete, 0);
00474 }
00475 
00476 void NuxAutomatedTestFramework::ViewSendBackspace()
00477 {
00478   SendFakeKeyEvent(XK_BackSpace, 0);  
00479 }
00480 
00481 void NuxAutomatedTestFramework::ViewSendEscape()
00482 {
00483   SendFakeKeyEvent(XK_Escape, 0);  
00484 }
00485 
00486 void NuxAutomatedTestFramework::ViewSendTab()
00487 {
00488   SendFakeKeyEvent(XK_Tab, 0);
00489 }
00490 
00491 void NuxAutomatedTestFramework::ViewSendReturn()
00492 {
00493   SendFakeKeyEvent(XK_Return, 0);
00494 }
00495 
00496 void NuxAutomatedTestFramework::ViewSendRight()
00497 {
00498   SendFakeKeyEvent(XK_Right, 0);
00499 }
00500 
00501 void NuxAutomatedTestFramework::ViewSendLeft()
00502 {
00503   SendFakeKeyEvent(XK_Left, 0);
00504 }
00505 
00506 void NuxAutomatedTestFramework::ViewSendUp()
00507 {
00508   SendFakeKeyEvent(XK_Up, 0);
00509 }
00510 
00511 void NuxAutomatedTestFramework::ViewSendDown()
00512 {
00513   SendFakeKeyEvent(XK_Down, 0);
00514 }
00515 
00516 void NuxAutomatedTestFramework::ViewSendIBusToggle()
00517 {
00518   KeyCode modcode0 = 0;
00519   KeyCode modcode1 = 0;
00520 
00521   modcode0 = XKeysymToKeycode(display_, XK_Control_L);
00522   XTestFakeKeyEvent(display_, modcode0, True, 0);
00523 
00524   modcode1 = XKeysymToKeycode(display_, XK_space);
00525   XTestFakeKeyEvent(display_, modcode1, True, 0);
00526 
00527   // release
00528   /* Generate modkey release */
00529   XTestFakeKeyEvent(display_, modcode1, False, 0);
00530   XTestFakeKeyEvent(display_, modcode0, False, 0);
00531 
00532 }
00533 
00534 void NuxAutomatedTestFramework::PutMouseAt(int x, int y)
00535 {
00536   XTestFakeMotionEvent(display_, XScreenNumberOfScreen(DefaultScreenOfDisplay(display_)), x, y, CurrentTime);  
00537   XSync(display_, False);
00538 }
00539 
00540 void NuxAutomatedTestFramework::SendFakeKeyEvent(KeySym keysym, KeySym modsym)
00541 {
00542   KeyCode keycode = 0;
00543   KeyCode modcode = 0;
00544   
00545   keycode = XKeysymToKeycode(display_, keysym);
00546   XTestGrabControl(display_, True);
00547   
00548   /* Generate modkey press */
00549   if (modsym != 0)
00550   {
00551     modcode = XKeysymToKeycode(display_, modsym);
00552     XTestFakeKeyEvent(display_, modcode, True, 0);
00553   }
00554   
00555   /* Generate regular key press and release */
00556   XTestFakeKeyEvent(display_, keycode, True, 0);
00557   XTestFakeKeyEvent(display_, keycode, False, 0);
00558   
00559   /* Generate modkey release */
00560   if (modsym != 0)
00561   {
00562     XTestFakeKeyEvent(display_, modcode, False, 0);
00563   }
00564 
00565   XSync(display_, False);
00566   XTestGrabControl(display_, False);
00567 }
00568 
00569 void NuxAutomatedTestFramework::SendFakeMouseEvent(int mouse_button_index, bool pressed)
00570 {
00571   XTestFakeButtonEvent(display_, mouse_button_index, pressed,  CurrentTime);
00572   XSync(display_, False);  
00573 }
00574 
00575 void NuxAutomatedTestFramework::SendFakeMouseMotionEvent(int x, int y, int ms_delay)
00576 {
00577   XEvent event;
00578   /* Get the current pointer position */
00579   XQueryPointer(display_, RootWindow(display_, 0),
00580         &event.xbutton.root, &event.xbutton.window,
00581         &event.xbutton.x_root, &event.xbutton.y_root,
00582         &event.xbutton.x, &event.xbutton.y,
00583         &event.xbutton.state);
00584 
00585   int old_x = event.xbutton.x;
00586   int old_y = event.xbutton.y;
00587 
00588   int n_iteration = ms_delay / 16.0f;
00589 
00590   //nuxDebugMsg("n_iteration: %d", n_iteration);
00591 
00592   if (n_iteration < 1)
00593   {
00594     n_iteration = 1;
00595   }
00596 
00597   XSync(display_, False);
00598 
00599   for (int i = 0; i < n_iteration; i++)
00600   {
00601     float t = ((float)i + 1.0f) / n_iteration;
00602 
00603     int cx = (1.0f - t) * old_x + t * x;
00604     int cy = (1.0f - t) * old_y + t * y;
00605     XTestFakeMotionEvent(display_, XScreenNumberOfScreen(DefaultScreenOfDisplay(display_)), cx, cy, CurrentTime);
00606     XSync(display_, False);
00607     usleep(16*1000);
00608   }
00609 
00610   XTestFakeMotionEvent(display_, XScreenNumberOfScreen(DefaultScreenOfDisplay(display_)), x, y, CurrentTime);  
00611   XSync(display_, False);
00612   nux::SleepForMilliseconds(NuxAutomatedTestFramework::minimum_sleep_time);
00613 }
00614 
00615 void NuxAutomatedTestFramework::TestReportMsg(bool b, const char* msg)
00616 {
00617   if (b)
00618   {
00619     nuxOkMsg("%s: %s", msg, "Ok");
00620   }
00621   else
00622   {
00623     nuxAlertMsg("%s: %s", msg, "Failed");
00624   }  
00625 }