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 <QtCrypto>
27 #include <QtTest/QtTest>
28
29 #ifdef QT_STATICPLUGIN
30 #include "import_plugins.h"
31 #endif
32
33 class PipeUnitTest : public QObject
34 {
35 Q_OBJECT
36
37 private Q_SLOTS:
38 void initTestCase();
39 void cleanupTestCase();
40 void createPipeWithInsecureMemory();
41 void createPipeWithSecureMemory();
42 void readWrite();
43 void readWriteSecure();
44 void signalTests();
45 void signalTestsSecure();
46
47 private:
48 QCA::Initializer *m_init;
49 };
50
initTestCase()51 void PipeUnitTest::initTestCase()
52 {
53 m_init = new QCA::Initializer;
54 }
55
cleanupTestCase()56 void PipeUnitTest::cleanupTestCase()
57 {
58 QCA::unloadAllPlugins();
59 delete m_init;
60 }
61
createPipeWithInsecureMemory()62 void PipeUnitTest::createPipeWithInsecureMemory()
63 {
64 QCA::QPipe pipe1;
65 // we haven't created the pipe yet, so it shouldn't be valid
66 QCOMPARE(pipe1.readEnd().isValid(), false);
67 QCOMPARE(pipe1.writeEnd().isValid(), false);
68
69 pipe1.create(); // insecure memory used
70 QVERIFY(pipe1.readEnd().isValid());
71 QVERIFY(pipe1.readEnd().type() == QCA::QPipeDevice::Read);
72 QVERIFY(pipe1.writeEnd().isValid());
73 QVERIFY(pipe1.writeEnd().type() == QCA::QPipeDevice::Write);
74
75 pipe1.reset();
76 QCOMPARE(pipe1.readEnd().isValid(), false);
77 QCOMPARE(pipe1.writeEnd().isValid(), false);
78 }
79
createPipeWithSecureMemory()80 void PipeUnitTest::createPipeWithSecureMemory()
81 {
82 QCA::QPipe pipe1;
83 // we haven't created the pipe yet, so it shouldn't be valid
84 QCOMPARE(pipe1.readEnd().isValid(), false);
85 QCOMPARE(pipe1.writeEnd().isValid(), false);
86
87 pipe1.create(true); // secure memory used
88 QVERIFY(pipe1.readEnd().isValid());
89 QVERIFY(pipe1.readEnd().type() == QCA::QPipeDevice::Read);
90 QVERIFY(pipe1.writeEnd().isValid());
91 QVERIFY(pipe1.writeEnd().type() == QCA::QPipeDevice::Write);
92
93 pipe1.reset();
94 QCOMPARE(pipe1.readEnd().isValid(), false);
95 QCOMPARE(pipe1.writeEnd().isValid(), false);
96 }
97
readWrite()98 void PipeUnitTest::readWrite()
99 {
100 QCA::QPipe pipe1;
101 QByteArray testData1("Down the");
102 QByteArray testData2("pipe!");
103
104 pipe1.create();
105 QVERIFY(pipe1.writeEnd().isValid());
106 QVERIFY(pipe1.readEnd().isValid());
107
108 // enable the pipe ends for read/write
109 pipe1.writeEnd().enable();
110 pipe1.readEnd().enable();
111
112 pipe1.writeEnd().write(testData1);
113 QTest::qWait(1); // process events
114 QTest::qWait(1); // process events
115 QByteArray out1 = pipe1.readEnd().read(); // read all...
116 QCOMPARE(testData1, out1);
117
118 pipe1.writeEnd().write(testData1); // put it back in
119 QTest::qWait(1); // process events
120 QCOMPARE(pipe1.readEnd().bytesAvailable(), testData1.size());
121
122 pipe1.writeEnd().write(testData2); // add some more data
123 QTest::qWait(1); // process events
124 QCOMPARE(pipe1.readEnd().bytesAvailable(), testData1.size() + testData2.size());
125 QByteArray thisRead = pipe1.readEnd().read(1);
126 QCOMPARE(thisRead, QByteArray("D"));
127 thisRead = pipe1.readEnd().read(3);
128 QCOMPARE(thisRead, QByteArray("own"));
129 thisRead = pipe1.readEnd().read();
130 QCOMPARE(thisRead, QByteArray(" thepipe!"));
131 }
132
readWriteSecure()133 void PipeUnitTest::readWriteSecure()
134 {
135 QCA::QPipe pipe1;
136 QCA::SecureArray testData1("Down the");
137 QCA::SecureArray testData2(" secure pipe!");
138
139 pipe1.create(true);
140 QVERIFY(pipe1.writeEnd().isValid());
141 QVERIFY(pipe1.readEnd().isValid());
142
143 // enable the pipe ends for read/write
144 pipe1.writeEnd().enable();
145 pipe1.readEnd().enable();
146
147 pipe1.writeEnd().writeSecure(testData1);
148 QTest::qWait(1); // process events
149 QTest::qWait(1); // process events
150 QCA::SecureArray out1 = pipe1.readEnd().readSecure(); // read all...
151 QCOMPARE(testData1, out1);
152
153 pipe1.writeEnd().writeSecure(testData1); // put it back in
154 QTest::qWait(1); // process events
155 QCOMPARE(pipe1.readEnd().bytesAvailable(), testData1.size());
156
157 pipe1.writeEnd().writeSecure(testData2); // add some more data
158 QTest::qWait(1); // process events
159 QCOMPARE(pipe1.readEnd().bytesAvailable(), testData1.size() + testData2.size());
160 QCA::SecureArray thisRead = pipe1.readEnd().readSecure(1);
161 QCOMPARE(thisRead, QCA::SecureArray("D"));
162 thisRead = pipe1.readEnd().readSecure(3);
163 QCOMPARE(thisRead, QCA::SecureArray("own"));
164 thisRead = pipe1.readEnd().readSecure();
165 QCOMPARE(thisRead, QCA::SecureArray(" the secure pipe!"));
166 }
167
signalTests()168 void PipeUnitTest::signalTests()
169 {
170 std::unique_ptr<QCA::QPipe> pipe(new QCA::QPipe);
171 pipe->create();
172
173 QVERIFY(pipe->writeEnd().isValid());
174 pipe->writeEnd().enable();
175 QVERIFY(pipe->readEnd().isValid());
176 pipe->readEnd().enable();
177
178 QSignalSpy readyReadSpy(&(pipe->readEnd()), &QCA::QPipeEnd::readyRead);
179 QVERIFY(readyReadSpy.isValid());
180 QSignalSpy bytesWrittenSpy(&(pipe->writeEnd()), &QCA::QPipeEnd::bytesWritten);
181 QVERIFY(bytesWrittenSpy.isValid());
182 QSignalSpy closedWriteSpy(&(pipe->writeEnd()), &QCA::QPipeEnd::closed);
183 QVERIFY(closedWriteSpy.isValid());
184 QSignalSpy closedReadSpy(&(pipe->readEnd()), &QCA::QPipeEnd::closed);
185 QVERIFY(closedReadSpy.isValid());
186
187 QCOMPARE(readyReadSpy.count(), 0);
188 QCOMPARE(bytesWrittenSpy.count(), 0);
189 QCOMPARE(closedWriteSpy.count(), 0);
190 QCOMPARE(closedReadSpy.count(), 0);
191
192 QByteArray data("Far better, it is, to dare mighty things");
193 pipe->writeEnd().write(data);
194 QTest::qWait(1);
195 QTest::qWait(1);
196 QCOMPARE(readyReadSpy.count(), 1);
197 QCOMPARE(bytesWrittenSpy.count(), 1);
198 // this pulls out the first argument to the first signal as an integer
199 QCOMPARE(bytesWrittenSpy.takeFirst().at(0).toInt(), data.size());
200 QCOMPARE(pipe->readEnd().bytesAvailable(), data.size());
201
202 QCOMPARE(closedWriteSpy.count(), 0);
203 QCOMPARE(closedReadSpy.count(), 0);
204
205 pipe->readEnd().close();
206 QTest::qWait(1);
207 QCOMPARE(closedWriteSpy.count(), 0);
208 QCOMPARE(closedReadSpy.count(), 1);
209 pipe->writeEnd().close();
210 QTest::qWait(1);
211 QCOMPARE(closedWriteSpy.count(), 1);
212 QCOMPARE(closedReadSpy.count(), 1);
213 }
214
signalTestsSecure()215 void PipeUnitTest::signalTestsSecure()
216 {
217 std::unique_ptr<QCA::QPipe> pipe(new QCA::QPipe);
218 pipe->create(true);
219
220 QVERIFY(pipe->writeEnd().isValid());
221 pipe->writeEnd().enable();
222 QVERIFY(pipe->readEnd().isValid());
223 pipe->readEnd().enable();
224
225 QSignalSpy readyReadSpy(&(pipe->readEnd()), &QCA::QPipeEnd::readyRead);
226 QVERIFY(readyReadSpy.isValid());
227 QSignalSpy bytesWrittenSpy(&(pipe->writeEnd()), &QCA::QPipeEnd::bytesWritten);
228 QVERIFY(bytesWrittenSpy.isValid());
229 QSignalSpy closedWriteSpy(&(pipe->writeEnd()), &QCA::QPipeEnd::closed);
230 QVERIFY(closedWriteSpy.isValid());
231 QSignalSpy closedReadSpy(&(pipe->readEnd()), &QCA::QPipeEnd::closed);
232 QVERIFY(closedReadSpy.isValid());
233
234 QCOMPARE(readyReadSpy.count(), 0);
235 QCOMPARE(bytesWrittenSpy.count(), 0);
236 QCOMPARE(closedWriteSpy.count(), 0);
237 QCOMPARE(closedReadSpy.count(), 0);
238
239 QCA::SecureArray data("Far better, it is, to dare mighty things");
240 pipe->writeEnd().writeSecure(data);
241 QTest::qWait(1);
242 QTest::qWait(1);
243 QCOMPARE(readyReadSpy.count(), 1);
244 QCOMPARE(bytesWrittenSpy.count(), 1);
245 // this pulls out the first argument to the first signal as an integer
246 QCOMPARE(bytesWrittenSpy.takeFirst().at(0).toInt(), data.size());
247 QCOMPARE(pipe->readEnd().bytesAvailable(), data.size());
248
249 QCOMPARE(closedWriteSpy.count(), 0);
250 QCOMPARE(closedReadSpy.count(), 0);
251
252 pipe->readEnd().close();
253 QTest::qWait(1);
254 QCOMPARE(closedWriteSpy.count(), 0);
255 QCOMPARE(closedReadSpy.count(), 1);
256 pipe->writeEnd().close();
257 QTest::qWait(1);
258 QCOMPARE(closedWriteSpy.count(), 1);
259 QCOMPARE(closedReadSpy.count(), 1);
260 }
261
262 QTEST_MAIN(PipeUnitTest)
263
264 #include "pipeunittest.moc"
265