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