2
* This file is part of Checkbox
4
* Copyright 2013 Canonical Ltd.
7
* - Andrew Haigh <andrew.haigh@cellsoftware.co.uk>
9
* This program is free software; you can redistribute it and/or modify
10
* it under the terms of the GNU General Public License as published by
11
* the Free Software Foundation; version 3.
13
* This program is distributed in the hope that it will be useful,
14
* but WITHOUT ANY WARRANTY; without even the implied warranty of
15
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16
* GNU General Public License for more details.
18
* You should have received a copy of the GNU General Public License
19
* along with this program. If not, see <http://www.gnu.org/licenses/>.
22
#ifndef PLAINBOX_GUI_H
23
#define PLAINBOX_GUI_H
25
#include <QtQml/qqml.h>
26
#include <QtQml/QQmlExtensionPlugin>
27
#include <QtDBus/QtDBus>
28
#include <QtXml/QDomDocument>
30
#include "PBJsonUtils.h"
32
#include <QtWidgets/QFileDialog>
34
class GuiEnginePlugin : public QQmlExtensionPlugin
37
Q_PLUGIN_METADATA(IID "guiengine")
41
// inherited from QQmlExtensionPlugin
42
void registerTypes(const char *uri);
48
#include "PBTreeNode.h"
50
#include "JobTreeNode.h"
52
// Currently used for the metadata Title of saved sessions in Plainbox
53
static const QString GUI_ENGINE_NAME_STR("GuiEngine");
56
/* We need to extract the signature of GetEstimatedDuration(): (dd) */
57
struct EstimatedDuration{
58
double automated_duration;
59
double manual_duration;
62
Q_DECLARE_METATYPE(EstimatedDuration);
64
/* This class embodies the wrapper which can call Plainbox APIs over D-Bus
66
* Its intended clients are Test Suite selection, test selection etc.
68
* There should only be one instance of this class
70
class GuiEngine : public QObject
81
GuiEngine( QObject*parent = 0);
85
/* Called by the QML/Qt GUI */
87
// Manage GuiEngine lifetime
88
bool Initialise(void);
91
// Returns whitelist object path, whitelist name
92
QMap<QDBusObjectPath,QString> GetWhiteListPathsAndNames(void);
94
void SetWhiteList(const QDBusObjectPath opath, const bool check);
96
void SetRealJobsList(const QList<QDBusObjectPath> &real_jobs) {
97
m_final_run_list = real_jobs;
100
void SetRerunJobsList(const QList<QDBusObjectPath> &rerun_jobs) {
101
m_rerun_list = rerun_jobs;
104
/* Run all the jobs of type "local" in order to generate the true
105
* list of tests from which the user can select.
107
void RunLocalJobs(void);
109
// Helper which prepares the corrected run-list from plainbox
110
int PrepareJobs(void);
114
// Used when running the real tests
118
// Session estimated duration
119
QVariantMap GetEstimatedDuration();
121
/* Signal receivers from Plainbox
123
void InterfacesAdded(QDBusMessage msg);
124
void InterfacesRemoved(QDBusMessage msg);
126
void CatchallShowInteractiveUISignalsHandler(QDBusMessage msg);
127
void CatchallAskForOutcomeSignalsHandler(QDBusMessage msg);
128
void CatchallIOLogGeneratedSignalsHandler(QDBusMessage msg);
129
void CatchallLocalJobResultAvailableSignalsHandler(QDBusMessage msg);
130
void CatchallJobResultAvailableSignalsHandler(QDBusMessage msg);
131
/* Helper functions for logging and testing
134
// Used by the test program test-gui-engine
135
void AcknowledgeJobsDone(void);
136
void AcknowledgeLocalJobsDone(void);
137
void ManualTest(const int outcome);
139
// Returns a list of DBus Object Paths for valid tests
140
const QList<QDBusObjectPath>& GetValidRunList(void);
142
/* Returns a list of DBusObjectPaths representing tests
143
* which are relevant for human beings (i.e. excludes resource jobs)
145
const QList<QDBusObjectPath>& GetVisibleRunList(void);
147
/* Returns a list of DBusObjectPaths representing tests
148
* which are relevant for human beings (i.e. excludes resource jobs)
150
void SetVisibleJobsList(const QList<QDBusObjectPath> &visible_jobs) {
151
m_visible_run_list = visible_jobs;
154
// Useful for the progress bar in the run manager
155
int ValidRunListCount(void);
157
// Resume after dealing with Manual Interaction Dialog
158
void ResumeFromManualInteractionDialog(bool run_test, \
159
const QString outcome, \
160
const QString comments);
162
// Convenience functions for the GUI
163
QString GuiExportSessionAsXML(void);
164
QString GuiExportSessionAsHTML(void);
165
QString GuiExportSessionAsXLSX(void);
166
QString GuiExportSessionAsJSON(void);
168
bool GuiExportSessionToFileAsXML(const QString& output_file,
169
const QStringList& option_list,
170
const QString& exporter_unit);
171
bool GuiExportSessionToFileAsHTML(const QString& output_file,
172
const QStringList& option_list,
173
const QString& exporter_unit);
174
bool GuiExportSessionToFileAsXLSX(const QString& output_file,
175
const QStringList& option_list,
176
const QString& exporter_unit);
177
bool GuiExportSessionToFileAsJSON(const QString& output_file,
178
const QStringList& option_list,
179
const QString& exporter_unit);
181
const QString SendSubmissionViaCertificationTransport( \
182
const QString &submission_path,
183
const QString &secure_id,
184
const bool submitToHexr);
186
const QString SendSubmissionViaLaunchpadTransport( \
187
const QString &submission_path,
188
const QString &email);
190
// Convenience until we move to Qt 5.1 and the FileDialog component
191
QString GetSaveFileName(const QString& defaultName, const QString& text);
193
// Session management from the GUI
194
void GuiSessionRemove(void);
195
const QString GuiPreviousSessionFile(void);
197
const QString GetIOLog(const QString& job);
199
// Retrieve all the previous session data
200
void GuiResumeSession(const bool re_run, const bool continue_pass = false);
201
void GuiCreateSession(void);
204
// Returns a list of all the jobnodes
205
QList<PBTreeNode*> GetJobNodes(void);
207
// Returns a tree of all the jobs
208
JobTreeNode* GetJobTreeNodes();
210
// Obtain The Results
211
const QString ExportSession(const QDBusObjectPath session, \
212
const QString& output_format, \
213
const QStringList& option_list);
216
const QString ExportSessionToFile(const QDBusObjectPath session, \
217
const QString& output_format, \
218
const QStringList& option_list,
219
const QString& exporter_unit, \
220
const QString& output_file);
222
QString SendDataViaTransport(const QDBusObjectPath session, \
223
const QString &transport, \
224
const QString &url, \
225
const QString &option_list, \
226
const QString &data);
228
// Suspend and Resume Session
229
void SessionPersistentSave(const QDBusObjectPath session);
230
void SessionRemove(const QDBusObjectPath session);
231
const QString PreviousSessionFile(const QDBusObjectPath session);
233
// Ensure the RunManager view is updated with the recovered data
234
void ResumeGetOutcomes(void);
237
// Instruct the GUI to update itself
238
void localJobsCompleted(void);
240
// When starting a run of jobs
241
void jobsBegin(void);
243
void updateGuiBeginJob(const QString& job_id, \
244
const int current_job_index,
245
const QString& test_name);
247
// When a job has completed
248
void updateGuiEndJob(const QString& job_id, \
249
const int current_job_index,
251
const QString& test_name);
253
// When all jobs are completed
254
void jobsCompleted(void);
256
// Manual Interaction Dialog
257
void raiseManualInteractionDialog(const int suggested_outcome /* from PB */, bool show_test);
259
void updateManualInteractionDialog(const int suggested_outcome, bool show_test);
261
void closeManualInteractionDialog(void);
264
// Helper function when generating the desired local and real jobs
265
QList<QDBusObjectPath> GenerateDesiredJobList();
267
bool RefreshPBObjects(void);
269
const PBTreeNode* GetRootJobsNode(const PBTreeNode *node);
270
const PBTreeNode* GetRootWhiteListNode(const PBTreeNode *node);
272
QList<PBTreeNode*> GetWhiteListNodes(void);
274
bool WhiteListDesignates(const QDBusObjectPath white_opath, \
275
const QDBusObjectPath job_opath);
277
QDBusObjectPath CreateSession(QList<QDBusObjectPath> job_list);
280
void ConnectJobReceivers(void);
281
QList<QDBusObjectPath> GetLocalJobs(const QList<QDBusObjectPath> &job_list);
283
QList<QDBusObjectPath> GetAllJobs(void);
286
// SessionState methods
287
QStringList UpdateDesiredJobList(const QDBusObjectPath session, \
288
QList<QDBusObjectPath> desired_job_list);
290
void SessionResume(const QDBusObjectPath session);
291
// SessionState Properties
292
QList<QDBusObjectPath> SessionStateDesiredJobList(const QDBusObjectPath session);
293
QList<QDBusObjectPath> SessionStateRunList(const QDBusObjectPath session);
294
QList<QDBusObjectPath> SessionStateJobList(const QDBusObjectPath session);
295
void SetSessionStateMetadata(const QDBusObjectPath session, \
296
const QString& flags, \
297
const QString& running_job_name, \
298
const QString& title,
299
const QByteArray& app_blob,
300
const QString& app_id);
302
const QVariantMap SessionStateMetadata(const QDBusObjectPath session);
303
// Encode/decode of internal state of this class
304
void EncodeGuiEngineStateAsJSON(void);
305
void DecodeGuiEngineStateFromJSON(void);
307
void UpdateJobResult(const QDBusObjectPath session, \
308
const QDBusObjectPath &job_path, \
309
const QDBusObjectPath &result_path);
312
void RunCommand(const QDBusObjectPath& runner);
313
void SetOutcome(const QDBusObjectPath& runner, \
314
const QString& outcome, \
315
const QString& comments);
317
/* A synthesised method. This is needed in the case of skipping tests
318
* on resuming a session, since in this circumstance, there is no
319
* runner object to serve as a means of setting the outcome.
321
QDBusObjectPath SetJobOutcome(const QDBusObjectPath& job_path, \
322
const QString& outcome, \
323
const QString& comments);
325
bool JobCanStart(const QDBusObjectPath& job_path);
326
const QString GetReadinessDescription(const QDBusObjectPath& job_path);
329
QString GetCommand(const QDBusObjectPath& opath);
332
void RunJob(const QDBusObjectPath session, const QDBusObjectPath opath);
334
// Convenience functions
335
int GetOutcomeFromJobResultPath(const QDBusObjectPath &opath);
336
int GetOutcomeFromJobPath(const QDBusObjectPath &opath);
337
const QString GetIOLogFromJobPath(const QDBusObjectPath &opath);
339
const QString ConvertOutcome(const int outcome);
341
// Find the next real job index to run based on current index through m_run_list
342
int NextRunJobIndex(int index);
344
protected: // for test purposes only
346
jsm_t GetJobStateMap(void);
348
void GetJobStates(void);
350
void GetJobResults(void);
353
const QString JobNameFromObjectPath(const QDBusObjectPath& opath);
355
const QDBusObjectPath GetCurrentSession(void);
358
EngineState enginestate;
360
/* Contains our Tree of Plainbox objects (Methods, results, tests etc)
361
* Structure is as exposed on DBus.
363
PBTreeNode* pb_objects;
365
// Have we got valid tree of PlainBox objects?
366
bool valid_pb_objects;
368
// These may go later, but are helpful for now
370
// A list of the selected whitelists from the user
371
QMap<QDBusObjectPath, bool> whitelist;
373
// A user-selected list of tests. We store the object path
374
QMap<QDBusObjectPath, bool> tests;
376
// All the jobs ultimately selected by the user
377
QList<QDBusObjectPath> m_final_run_list;
379
// We only care about one session
380
QDBusObjectPath m_session;
382
// Job Tree as defined by the "via" properties
383
JobTreeNode* job_tree;
385
QList<QDBusObjectPath> m_job_list;
387
QList<QDBusObjectPath> m_desired_job_list;
389
QList<QDBusObjectPath> m_run_list;
391
QList<QDBusObjectPath> m_local_job_list;
393
QList<QDBusObjectPath> m_local_run_list;
395
QList<QDBusObjectPath> m_desired_local_job_list;
397
/* Re-run list. First time round it contains ALL m_run_list
398
* but on subsequent rounds its only those selected by the user
400
QList<QDBusObjectPath> m_rerun_list;
402
/* Visible job list; this is mainly for the benefit
403
* of the gui, which needs to show real jobs being run,
404
* together with local jobs used to group the real tests being
407
* Its not ideal, just an interim solution. Ultimately,
408
* it would be best to be able to populate the gui with a single
409
* call to extract all the relevant data from the gui-engine.
411
QList<QDBusObjectPath> m_visible_run_list;
413
// The currently running job as an index into m_run_list
414
int m_current_job_index;
416
// The current job path (for tests being run)
417
QDBusObjectPath m_current_job_path;
422
// Job State List (NB: These are NOT in pb_objects!)
423
QList<PBTreeNode*> m_job_state_list;
425
/* Job Results. These could be either DiskJobResults or MemoryJobResults
427
* (NB: These are NOT in pb_objects!)
429
QList<PBTreeNode*> m_job_state_results;
431
// Are we running tests or not? (Used for Pause/Resume)
433
bool m_waiting_result;
435
// Are we resuming a session?
438
// Are we resuming a session and forcing the previous test result?
439
bool m_resuming_force_result;
441
// Used to preserve interim data from Manual Interaction event
442
QDBusObjectPath m_runner;
444
/* lets us choose whether to raise the manual interaction dialog
445
* or simply update it
447
bool m_running_manual_job;
449
/* Records whether the results of running the tests have been submitted
450
* Note that depending on the GUI, this may simply mean saved to disk,
451
* or submitted to a validation website. it may not even matter. But this
452
* is here in order to allow the state to be preserved by plainbox
453
* in a saved session.
456
// Used by the test program
458
bool m_local_jobs_done;
462
bool m_testing_manual_job;