| 1 |
Overview: |
| 2 |
- Records and playbacks QEvents in any dynamically-linked Qt application |
| 3 |
- Useful for testing |
| 4 |
- Useful for macros |
| 5 |
- Useful for pseudo-screencasts (in a significantly bandwidth-reduced form) |
| 6 |
|
| 7 |
Requirements: |
| 8 |
- Qt 4.5 |
| 9 |
- QScintilla |
| 10 |
- The qtscriptgenerator-generated QtScript bindings |
| 11 |
|
| 12 |
Directories: |
| 13 |
- common: classes used in multiple places. |
| 14 |
- hooq: GUI application for day to day use - uses hooqInjector, and generates QtScript |
| 15 |
files from the socket XML. When replaying, the QtScript scripts create the XML which |
| 16 |
is sent back to the application. |
| 17 |
- hooqbackup: CLI application for manipulating .hqt backup files |
| 18 |
- hooqcli: CLI application for testing - uses hooqInjector, and deals with the raw |
| 19 |
XML that goes over the socket between hooqInjector and injectedHooq. |
| 20 |
- hooqInjector: library for injecting injectedHooq into another process. |
| 21 |
- injectedHooq: spy/event injection library inserted into the other process. |
| 22 |
- qscripthighlighter: verbatim copy of a QSyntaxHighlighter for QtScript taken from Qt Creator. |
| 23 |
Used by the hooq GUI application. |
| 24 |
- uilib: UI classes that may be directly useful in other applications. |
| 25 |
|
| 26 |
Method: |
| 27 |
- The logger/player libraries are injected into any Qt application's process |
| 28 |
- The logger receives all QEvents via QInternal::registerCallback() (sorry for QInternal) |
| 29 |
- The player posts events via QCoreApplication::postEvent() |
| 30 |
|
| 31 |
Injection method: |
| 32 |
- Linux/OSX: gdb/gdbserver is attached to the process; then, the extra library is loaded |
| 33 |
via dlopen(), and "startHooq()" is called. |
| 34 |
- Windows: we install injectedHooq as a Windows Message hook for the main thread for the |
| 35 |
process; this makes Windows map the DLL into the other processes' memory. On the |
| 36 |
first windows message received in that thread, Hooq gets started; we trigger this |
| 37 |
by sending a WM_NULL message. Previously, LoadLibrary was called via |
| 38 |
CreateRemoteThread - while simpler, this approach didn't end up working, as we need |
| 39 |
our setup code to be ran from the GUI thread to setup the network socket. |