1 #include "ksysguarddtest.h"
2 #include "processcore/processcore_debug.h"
3
4 KSGRD::SensorAgent *agent;
5
6 Q_DECLARE_METATYPE(KSGRD::SensorAgent *)
7
8 using namespace KSGRD;
initTestCase()9 void TestKsysguardd::initTestCase()
10 {
11 qRegisterMetaType<KSGRD::SensorAgent *>();
12 QCOMPARE(manager.count(), 0);
13 hostConnectionLostSpy = new QSignalSpy(&manager, SIGNAL(hostConnectionLost(QString)));
14 updateSpy = new QSignalSpy(&manager, SIGNAL(update()));
15 hostAddedSpy = new QSignalSpy(&manager, SIGNAL(hostAdded(KSGRD::SensorAgent *, QString)));
16 bool success = manager.engage("", "", "../../ksysguardd/ksysguardd", -1);
17 QCOMPARE(hostAddedSpy->count(), 1);
18 QVERIFY(success);
19 QVERIFY(manager.isConnected(""));
20 QCOMPARE(hostConnectionLostSpy->count(), 0);
21 QCOMPARE(updateSpy->count(), 0);
22 client = new SensorClientTest;
23 nextId = 0;
24 }
init()25 void TestKsysguardd::init()
26 {
27 }
cleanup()28 void TestKsysguardd::cleanup()
29 {
30 }
31
cleanupTestCase()32 void TestKsysguardd::cleanupTestCase()
33 {
34 QCOMPARE(hostAddedSpy->count(), 1);
35 QCOMPARE(manager.count(), 1);
36 manager.disengage("");
37 QCOMPARE(manager.count(), 0);
38 delete updateSpy;
39 delete hostConnectionLostSpy;
40 delete client;
41 }
42
testSetup()43 void TestKsysguardd::testSetup()
44 {
45 QCOMPARE(manager.count(), 1);
46 QString shell;
47 QString command;
48 int port;
49 bool success = manager.hostInfo("", shell, command, port);
50 QCOMPARE(success, true);
51 QCOMPARE(shell, QString(""));
52 QCOMPARE(command, QString("../../ksysguardd/ksysguardd"));
53 QCOMPARE(port, -1);
54
55 success = manager.hostInfo("nonexistent host", shell, command, port);
56 QCOMPARE(success, false);
57 }
58
59 /** Test the result from ksysguardd for each monitor info and monitor name follows the correct syntax */
testFormatting_data()60 void TestKsysguardd::testFormatting_data()
61 {
62 QTest::addColumn<QByteArray>("monitorName");
63 QTest::addColumn<QByteArray>("monitorType");
64 QTest::addColumn<QByteArray>("monitorInfoName");
65
66 int id = nextId++;
67 bool success = manager.sendRequest("", "monitors", client, id);
68 QVERIFY(success);
69
70 QCOMPARE(hostConnectionLostSpy->count(), 0);
71 QCOMPARE(updateSpy->count(), 0);
72
73 int timeout = 300; // Wait up to 30 seconds
74 while (!client->haveAnswer && !client->isSensorLost && timeout--)
75 QTest::qWait(100);
76 QVERIFY(client->haveAnswer);
77 QVERIFY(!client->isSensorLost);
78 QVERIFY(!client->answers[id].isSensorLost);
79 QCOMPARE(client->answers[id].id, id);
80
81 QList<QByteArray> monitors = client->answers[id].answer;
82 QVERIFY(!monitors.isEmpty());
83
84 // We now have a list of all the monitors
85 foreach (const QByteArray &monitor, monitors) {
86 QList<QByteArray> info = monitor.split('\t');
87 QCOMPARE(info.count(), 2);
88 QByteArray monitorName = info[0];
89 QByteArray monitorType = info[1];
90 QByteArray monitorInfoName = monitorName;
91 monitorInfoName.append('?');
92 client->haveAnswer = false;
93 QTest::newRow(monitorName.constData()) << monitorName << monitorType << monitorInfoName;
94 }
95 }
96
97 // Test each monitor for a correctly formatted info and correctly formatted data
testFormatting()98 void TestKsysguardd::testFormatting()
99 {
100 QFETCH(QByteArray, monitorName);
101 QFETCH(QByteArray, monitorType);
102 QFETCH(QByteArray, monitorInfoName);
103
104 // Query the monitor for its information
105 if (client->haveAnswer || client->isSensorLost)
106 return; // Skip rest of tests
107 int id = nextId++;
108 bool success = manager.sendRequest("", monitorInfoName, client, id);
109 QVERIFY(success);
110 int timeout = 50;
111 while (!client->haveAnswer && !client->isSensorLost && timeout--)
112 QTest::qWait(10);
113 QVERIFY(client->haveAnswer);
114 QVERIFY(!client->isSensorLost);
115 QVERIFY(!client->answers[id].isSensorLost);
116 QCOMPARE(client->answers[id].id, id);
117
118 QCOMPARE(updateSpy->count(), 0);
119 QCOMPARE(hostConnectionLostSpy->count(), 0);
120
121 QList<QByteArray> columnHeadings;
122 QList<QByteArray> columnTypes;
123
124 // Now check the answer that we got for the monitor information
125 if (monitorType == "integer") {
126 QCOMPARE(client->answers[id].answer.count(), 1);
127 QList<QByteArray> answer = client->answers[id].answer[0].split('\t');
128 QCOMPARE(answer.count(), 4); // Name, minimum value, maximum value, unit
129 QVERIFY(!answer[0].isEmpty()); // Name can't be empty
130 QVERIFY(!answer[1].isEmpty()); // Minimum value cannot be empty
131 QVERIFY(!answer[2].isEmpty()); // Maximum value cannot be empty. unit can be
132 // Make sure minimum and maximum values are numbers (doubles)
133 bool isNumber;
134 long min = answer[1].toLong(&isNumber); //(note that toLong is in C locale, which is what we want)
135 QVERIFY(isNumber);
136 long max = answer[2].toLong(&isNumber);
137 QVERIFY(isNumber);
138 QVERIFY(min <= max);
139 } else if (monitorType == "float") {
140 QCOMPARE(client->answers[id].answer.count(), 1);
141 QList<QByteArray> answer = client->answers[id].answer[0].split('\t');
142 QCOMPARE(answer.count(), 4); // Name, minimum value, maximum value, unit
143 QVERIFY(!answer[0].isEmpty()); // Name can't be empty
144 QVERIFY(!answer[1].isEmpty()); // Minimum value cannot be empty
145 QVERIFY(!answer[2].isEmpty()); // Maximum value cannot be empty. unit can be
146 // Make sure minimum and maximum values are numbers (doubles)
147 bool isNumber;
148 double min = answer[1].toDouble(&isNumber); //(note that toDouble is in C locale, which is what we want)
149 QVERIFY(isNumber);
150 double max = answer[2].toDouble(&isNumber);
151 QVERIFY(isNumber);
152 QVERIFY(min <= max);
153 } else if (monitorType == "logfile") {
154 QCOMPARE(client->answers[id].answer.count(), 1);
155 QList<QByteArray> answer = client->answers[id].answer[0].split('\t');
156 QCOMPARE(answer.count(), 1);
157 QCOMPARE(answer[0], QByteArray("LogFile"));
158 } else if (monitorType == "listview" || monitorType == "table") {
159 // listview is two lines. The first line is the column headings, the second line is the type of each column
160 QCOMPARE(client->answers[id].answer.count(), 2);
161 columnHeadings = client->answers[id].answer[0].split('\t');
162 columnTypes = client->answers[id].answer[1].split('\t');
163 QCOMPARE(columnHeadings.count(), columnTypes.count());
164 // column type is well defined
165 foreach (const QByteArray &columnType, columnTypes) {
166 switch (columnType[0]) {
167 case 's': // string
168 case 'S': // string to translate
169 case 'd': // integer
170 case 'D': // integer to display localized
171 case 'f': // floating point number
172 case 'M': // Disk stat - some special case
173 case '%': // Disk stat - some special case
174 QCOMPARE(columnType.size(), 1);
175 break;
176 case 'K': // Disk stat - some special case
177 QCOMPARE(columnType.size(), 2);
178 QCOMPARE(columnType, QByteArray("KB"));
179 break;
180 default:
181 QVERIFY(false);
182 }
183 }
184 } else if (monitorType == "string") {
185 // TODO Check for something in the answer?
186 } else {
187 QVERIFY(false);
188 }
189
190 // Now read the actual data for the sensor, and check that it's valid
191 client->haveAnswer = false;
192 id = nextId++;
193 success = manager.sendRequest("", monitorName, client, id);
194 QVERIFY(success);
195 QTime timer;
196 timer.start();
197 timeout = 300; // Wait up to 30 seconds
198 while (!client->haveAnswer && !client->isSensorLost && timeout--)
199 QTest::qWait(100);
200 QVERIFY(client->haveAnswer);
201 QVERIFY(!client->isSensorLost);
202 QCOMPARE(client->answers[id].id, id);
203 if (timer.elapsed() > 200)
204 qCDebug(LIBKSYSGUARD) << monitorName << "took" << timer.elapsed() << "ms";
205
206 if (monitorType == "integer") {
207 QList<QByteArray> answer = client->answers[id].answer[0].split('\t');
208 QCOMPARE(answer.count(), 1); // Just the number
209 QVERIFY(!answer[0].isEmpty()); // Value cannot be empty
210 // Make sure the value is valid
211 bool isNumber;
212 answer[0].toLong(&isNumber); //(note that toLong is in C locale, which is what we want)
213 QVERIFY(isNumber);
214 } else if (monitorType == "float") {
215 QList<QByteArray> answer = client->answers[id].answer[0].split('\t');
216 QCOMPARE(answer.count(), 1); // Just the number
217 QVERIFY(!answer[0].isEmpty()); // Value cannot be empty
218 // Make sure the value is valid
219 bool isNumber;
220 answer[0].toDouble(&isNumber); //(note that toDouble is in C locale, which is what we want)
221 QVERIFY(isNumber);
222 } else if (monitorType == "listview" || monitorType == "table") {
223 foreach (const QByteArray &row, client->answers[id].answer) {
224 QList<QByteArray> rowData = row.split('\t');
225 QCOMPARE(rowData.count(), columnHeadings.count());
226 for (int column = 0; column < columnHeadings.count(); column++) {
227 switch (columnTypes[column][0]) {
228 case 's': // string
229 case 'S': // string to translate
230 break;
231 case 'd': // integer
232 case 'D': { // integer to display localized
233 bool isNumber;
234 rowData[column].toLong(&isNumber);
235 QVERIFY2(isNumber, (QString("Row data was ") + row).toLatin1().constData());
236 }
237 case 'f': { // floating point number
238 bool isNumber;
239 rowData[column].toDouble(&isNumber);
240 QVERIFY(isNumber);
241 }
242 case 'M': // Disk stat - some special case
243 break;
244 }
245 }
246 }
247 }
248 client->haveAnswer = false;
249 }
250
testQueueing()251 void TestKsysguardd::testQueueing()
252 {
253 // Send lots of commands to ksysguardd, and check that they all return the right answer, in order
254
255 delete client; // Start with a new client
256 client = new SensorClientTest;
257
258 const int N = 1000;
259 for (int i = 0; i < N; i++) {
260 bool success = manager.sendRequest("", "ps", client, i);
261 QVERIFY(success);
262 }
263
264 int timeout = 300; // Wait up to 30 seconds for a single answer
265 int lastCount = 0;
266 while (client->answers.count() != N && !client->isSensorLost && timeout--) {
267 if (client->answers.count() != lastCount) {
268 lastCount = client->answers.count();
269 timeout = 300; // reset timeout as we get new answers
270 }
271 QTest::qWait(100);
272 }
273 QCOMPARE(client->answers.count(), N);
274
275 for (int i = 0; i < N; i++) {
276 QCOMPARE(client->answers[i].id, i);
277 }
278 }
279 QTEST_MAIN(TestKsysguardd)
280