1/**
2 * Copyright (C) 2007 Brad Hards <bradh@frogmouth.net>
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 *
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 *
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
15 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
16 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
17 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
18 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
19 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
20 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
21 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
23 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24 */
25
26#include <QSignalSpy>
27#include <QTest>
28#include <QtCrypto>
29
30#ifdef QT_STATICPLUGIN
31#include "import_plugins.h"
32#endif
33
34#include <memory>
35
36class PipeUnitTest : public QObject
37{
38 Q_OBJECT
39
40private Q_SLOTS:
41 void initTestCase();
42 void cleanupTestCase();
43 void createPipeWithInsecureMemory();
44 void createPipeWithSecureMemory();
45 void readWrite();
46 void readWriteSecure();
47 void signalTests();
48 void signalTestsSecure();
49
50private:
51 QCA::Initializer *m_init;
52};
53
54void PipeUnitTest::initTestCase()
55{
56 m_init = new QCA::Initializer;
57}
58
59void PipeUnitTest::cleanupTestCase()
60{
61 QCA::unloadAllPlugins();
62 delete m_init;
63}
64
65void PipeUnitTest::createPipeWithInsecureMemory()
66{
67 QCA::QPipe pipe1;
68 // we haven't created the pipe yet, so it shouldn't be valid
69 QCOMPARE(pipe1.readEnd().isValid(), false);
70 QCOMPARE(pipe1.writeEnd().isValid(), false);
71
72 pipe1.create(); // insecure memory used
73 QVERIFY(pipe1.readEnd().isValid());
74 QVERIFY(pipe1.readEnd().type() == QCA::QPipeDevice::Read);
75 QVERIFY(pipe1.writeEnd().isValid());
76 QVERIFY(pipe1.writeEnd().type() == QCA::QPipeDevice::Write);
77
78 pipe1.reset();
79 QCOMPARE(pipe1.readEnd().isValid(), false);
80 QCOMPARE(pipe1.writeEnd().isValid(), false);
81}
82
83void PipeUnitTest::createPipeWithSecureMemory()
84{
85 QCA::QPipe pipe1;
86 // we haven't created the pipe yet, so it shouldn't be valid
87 QCOMPARE(pipe1.readEnd().isValid(), false);
88 QCOMPARE(pipe1.writeEnd().isValid(), false);
89
90 pipe1.create(secure: true); // secure memory used
91 QVERIFY(pipe1.readEnd().isValid());
92 QVERIFY(pipe1.readEnd().type() == QCA::QPipeDevice::Read);
93 QVERIFY(pipe1.writeEnd().isValid());
94 QVERIFY(pipe1.writeEnd().type() == QCA::QPipeDevice::Write);
95
96 pipe1.reset();
97 QCOMPARE(pipe1.readEnd().isValid(), false);
98 QCOMPARE(pipe1.writeEnd().isValid(), false);
99}
100
101void PipeUnitTest::readWrite()
102{
103 QCA::QPipe pipe1;
104 QByteArray testData1("Down the");
105 QByteArray testData2("pipe!");
106
107 pipe1.create();
108 QVERIFY(pipe1.writeEnd().isValid());
109 QVERIFY(pipe1.readEnd().isValid());
110
111 // enable the pipe ends for read/write
112 pipe1.writeEnd().enable();
113 pipe1.readEnd().enable();
114
115 pipe1.writeEnd().write(a: testData1);
116 QTest::qWait(ms: 1); // process events
117 QTest::qWait(ms: 1); // process events
118 QByteArray out1 = pipe1.readEnd().read(); // read all...
119 QCOMPARE(testData1, out1);
120
121 pipe1.writeEnd().write(a: testData1); // put it back in
122 QTest::qWait(ms: 1); // process events
123 QCOMPARE(pipe1.readEnd().bytesAvailable(), testData1.size());
124
125 pipe1.writeEnd().write(a: testData2); // add some more data
126 QTest::qWait(ms: 1); // process events
127 QCOMPARE(pipe1.readEnd().bytesAvailable(), testData1.size() + testData2.size());
128 QByteArray thisRead = pipe1.readEnd().read(bytes: 1);
129 QCOMPARE(thisRead, QByteArray("D"));
130 thisRead = pipe1.readEnd().read(bytes: 3);
131 QCOMPARE(thisRead, QByteArray("own"));
132 thisRead = pipe1.readEnd().read();
133 QCOMPARE(thisRead, QByteArray(" thepipe!"));
134}
135
136void PipeUnitTest::readWriteSecure()
137{
138 QCA::QPipe pipe1;
139 QCA::SecureArray testData1("Down the");
140 QCA::SecureArray testData2(" secure pipe!");
141
142 pipe1.create(secure: true);
143 QVERIFY(pipe1.writeEnd().isValid());
144 QVERIFY(pipe1.readEnd().isValid());
145
146 // enable the pipe ends for read/write
147 pipe1.writeEnd().enable();
148 pipe1.readEnd().enable();
149
150 pipe1.writeEnd().writeSecure(a: testData1);
151 QTest::qWait(ms: 1); // process events
152 QTest::qWait(ms: 1); // process events
153 QCA::SecureArray out1 = pipe1.readEnd().readSecure(); // read all...
154 QCOMPARE(testData1, out1);
155
156 pipe1.writeEnd().writeSecure(a: testData1); // put it back in
157 QTest::qWait(ms: 1); // process events
158 QCOMPARE(pipe1.readEnd().bytesAvailable(), testData1.size());
159
160 pipe1.writeEnd().writeSecure(a: testData2); // add some more data
161 QTest::qWait(ms: 1); // process events
162 QCOMPARE(pipe1.readEnd().bytesAvailable(), testData1.size() + testData2.size());
163 QCA::SecureArray thisRead = pipe1.readEnd().readSecure(bytes: 1);
164 QCOMPARE(thisRead, QCA::SecureArray("D"));
165 thisRead = pipe1.readEnd().readSecure(bytes: 3);
166 QCOMPARE(thisRead, QCA::SecureArray("own"));
167 thisRead = pipe1.readEnd().readSecure();
168 QCOMPARE(thisRead, QCA::SecureArray(" the secure pipe!"));
169}
170
171void PipeUnitTest::signalTests()
172{
173 std::unique_ptr<QCA::QPipe> pipe(new QCA::QPipe);
174 pipe->create();
175
176 QVERIFY(pipe->writeEnd().isValid());
177 pipe->writeEnd().enable();
178 QVERIFY(pipe->readEnd().isValid());
179 pipe->readEnd().enable();
180
181 QSignalSpy readyReadSpy(&(pipe->readEnd()), &QCA::QPipeEnd::readyRead);
182 QVERIFY(readyReadSpy.isValid());
183 QSignalSpy bytesWrittenSpy(&(pipe->writeEnd()), &QCA::QPipeEnd::bytesWritten);
184 QVERIFY(bytesWrittenSpy.isValid());
185 QSignalSpy closedWriteSpy(&(pipe->writeEnd()), &QCA::QPipeEnd::closed);
186 QVERIFY(closedWriteSpy.isValid());
187 QSignalSpy closedReadSpy(&(pipe->readEnd()), &QCA::QPipeEnd::closed);
188 QVERIFY(closedReadSpy.isValid());
189
190 QCOMPARE(readyReadSpy.count(), 0);
191 QCOMPARE(bytesWrittenSpy.count(), 0);
192 QCOMPARE(closedWriteSpy.count(), 0);
193 QCOMPARE(closedReadSpy.count(), 0);
194
195 QByteArray data("Far better, it is, to dare mighty things");
196 pipe->writeEnd().write(a: data);
197 QTest::qWait(ms: 1);
198 QTest::qWait(ms: 1);
199 QCOMPARE(readyReadSpy.count(), 1);
200 QCOMPARE(bytesWrittenSpy.count(), 1);
201 // this pulls out the first argument to the first signal as an integer
202 QCOMPARE(bytesWrittenSpy.takeFirst().at(0).toInt(), data.size());
203 QCOMPARE(pipe->readEnd().bytesAvailable(), data.size());
204
205 QCOMPARE(closedWriteSpy.count(), 0);
206 QCOMPARE(closedReadSpy.count(), 0);
207
208 pipe->readEnd().close();
209 QTest::qWait(ms: 1);
210 QCOMPARE(closedWriteSpy.count(), 0);
211 QCOMPARE(closedReadSpy.count(), 1);
212 pipe->writeEnd().close();
213 QTest::qWait(ms: 1);
214 QCOMPARE(closedWriteSpy.count(), 1);
215 QCOMPARE(closedReadSpy.count(), 1);
216}
217
218void PipeUnitTest::signalTestsSecure()
219{
220 std::unique_ptr<QCA::QPipe> pipe(new QCA::QPipe);
221 pipe->create(secure: true);
222
223 QVERIFY(pipe->writeEnd().isValid());
224 pipe->writeEnd().enable();
225 QVERIFY(pipe->readEnd().isValid());
226 pipe->readEnd().enable();
227
228 QSignalSpy readyReadSpy(&(pipe->readEnd()), &QCA::QPipeEnd::readyRead);
229 QVERIFY(readyReadSpy.isValid());
230 QSignalSpy bytesWrittenSpy(&(pipe->writeEnd()), &QCA::QPipeEnd::bytesWritten);
231 QVERIFY(bytesWrittenSpy.isValid());
232 QSignalSpy closedWriteSpy(&(pipe->writeEnd()), &QCA::QPipeEnd::closed);
233 QVERIFY(closedWriteSpy.isValid());
234 QSignalSpy closedReadSpy(&(pipe->readEnd()), &QCA::QPipeEnd::closed);
235 QVERIFY(closedReadSpy.isValid());
236
237 QCOMPARE(readyReadSpy.count(), 0);
238 QCOMPARE(bytesWrittenSpy.count(), 0);
239 QCOMPARE(closedWriteSpy.count(), 0);
240 QCOMPARE(closedReadSpy.count(), 0);
241
242 QCA::SecureArray data("Far better, it is, to dare mighty things");
243 pipe->writeEnd().writeSecure(a: data);
244 QTest::qWait(ms: 1);
245 QTest::qWait(ms: 1);
246 QCOMPARE(readyReadSpy.count(), 1);
247 QCOMPARE(bytesWrittenSpy.count(), 1);
248 // this pulls out the first argument to the first signal as an integer
249 QCOMPARE(bytesWrittenSpy.takeFirst().at(0).toInt(), data.size());
250 QCOMPARE(pipe->readEnd().bytesAvailable(), data.size());
251
252 QCOMPARE(closedWriteSpy.count(), 0);
253 QCOMPARE(closedReadSpy.count(), 0);
254
255 pipe->readEnd().close();
256 QTest::qWait(ms: 1);
257 QCOMPARE(closedWriteSpy.count(), 0);
258 QCOMPARE(closedReadSpy.count(), 1);
259 pipe->writeEnd().close();
260 QTest::qWait(ms: 1);
261 QCOMPARE(closedWriteSpy.count(), 1);
262 QCOMPARE(closedReadSpy.count(), 1);
263}
264
265QTEST_MAIN(PipeUnitTest)
266
267#include "pipeunittest.moc"
268

source code of qca/unittest/pipeunittest/pipeunittest.cpp