1/****************************************************************************
2**
3** Copyright (C) 2014 Klaralvdalens Datakonsult AB (KDAB).
4** Contact: https://www.qt.io/licensing/
5**
6** This file is part of the Qt3D module of the Qt Toolkit.
7**
8** $QT_BEGIN_LICENSE:GPL-EXCEPT$
9** Commercial License Usage
10** Licensees holding valid commercial Qt licenses may use this file in
11** accordance with the commercial license agreement provided with the
12** Software or, alternatively, in accordance with the terms contained in
13** a written agreement between you and The Qt Company. For licensing terms
14** and conditions see https://www.qt.io/terms-conditions. For further
15** information use the contact form at https://www.qt.io/contact-us.
16**
17** GNU General Public License Usage
18** Alternatively, this file may be used under the terms of the GNU
19** General Public License version 3 as published by the Free Software
20** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
21** included in the packaging of this file. Please review the following
22** information to ensure the GNU General Public License requirements will
23** be met: https://www.gnu.org/licenses/gpl-3.0.html.
24**
25** $QT_END_LICENSE$
26**
27****************************************************************************/
28
29#include <QObject>
30#include <QtTest/QtTest>
31
32#include <Qt3DCore/private/qboundedcircularbuffer_p.h>
33
34using namespace Qt3DCore;
35
36class tst_QBoundedCircularBuffer : public QObject
37{
38 Q_OBJECT
39private Q_SLOTS:
40 void construction();
41 void clear();
42 void push();
43 void pop();
44 void at();
45 void producerConsumer();
46};
47
48class MyComplexType
49{
50public:
51 MyComplexType(int xx = 0)
52 : x(xx),
53 magicCheck(ms_magic)
54 {
55 ++ms_activeCount;
56 }
57
58 MyComplexType(const MyComplexType &other)
59 : x(other.x),
60 magicCheck(other.magicCheck)
61 {
62 ++ms_activeCount;
63 }
64
65 ~MyComplexType()
66 {
67 // Check that the constructor was actually called
68 QVERIFY(ms_magic == magicCheck);
69 --ms_activeCount;
70 }
71
72 MyComplexType &operator=(const MyComplexType &other)
73 {
74 if (this == &other)
75 return *this;
76 x = other.x;
77 magicCheck = other.magicCheck;
78 return *this;
79 }
80
81 int x;
82 int magicCheck;
83
84 static const int ms_magic = 0xfefefefe;
85 static int ms_activeCount;
86};
87
88int MyComplexType::ms_activeCount = 0;
89
90void tst_QBoundedCircularBuffer::construction()
91{
92 QBoundedCircularBuffer<int> buffer(10);
93 QVERIFY(buffer.capacity() == 10);
94 QVERIFY(buffer.freeSize() == 10);
95 QVERIFY(buffer.size() == 0);
96 QVERIFY(buffer.isEmpty() == true);
97 QVERIFY(buffer.isFull() == false);
98}
99
100void tst_QBoundedCircularBuffer::clear()
101{
102 QBoundedCircularBuffer<int> buffer(10);
103 buffer.clear();
104 QVERIFY(buffer.capacity() == 10);
105 QVERIFY(buffer.freeSize() == 10);
106 QVERIFY(buffer.size() == 0);
107 QVERIFY(buffer.isEmpty() == true);
108 QVERIFY(buffer.isFull() == false);
109}
110
111void tst_QBoundedCircularBuffer::push()
112{
113 QBoundedCircularBuffer<MyComplexType> buffer(20);
114 QVERIFY(buffer.freeSize() == 20);
115 for (int i = 0; i < 15; i++) {
116 const MyComplexType value(i);
117 buffer.push(t: value);
118 const MyComplexType testValue = buffer.back();
119 QVERIFY(testValue.x == value.x);
120 }
121 QVERIFY(buffer.freeSize() == 5);
122 QVERIFY(buffer.size() == 15);
123}
124
125void tst_QBoundedCircularBuffer::pop()
126{
127 QBoundedCircularBuffer<MyComplexType> buffer(20);
128 for (int i = 0; i < 15; i++) {
129 const MyComplexType value(i);
130 buffer.push(t: value);
131 }
132
133 for (int j = 0; j < 10; j++) {
134 const MyComplexType value = buffer.pop();
135 QVERIFY(value.x == j);
136 }
137 QVERIFY(buffer.freeSize() == 15);
138 QVERIFY(buffer.size() == 5);
139}
140
141void tst_QBoundedCircularBuffer::at()
142{
143 QBoundedCircularBuffer<MyComplexType> buffer(20);
144 for (int i = 0; i < 10; i++) {
145 const MyComplexType value(i);
146 buffer.append(t: value);
147 }
148
149 for (int i = 0; i < 10; i++)
150 QVERIFY(buffer.at(i).x == i);
151}
152
153class MyProducer : public QThread
154{
155 Q_OBJECT
156public:
157 MyProducer(QBoundedCircularBuffer<MyComplexType> *buffer)
158 : QThread(),
159 m_buffer(buffer)
160 {
161 }
162
163 void run()
164 {
165 for (int i = 0; i < 10000; i++ ) {
166 //qDebug() << "Producing" << i;
167 const MyComplexType value(i);
168 //if ( m_buffer->isFull() )
169 // qDebug() << i << "The buffer is full. Waiting for consumer...";
170 m_buffer->push(t: value);
171
172 // Uncomment and adjust this to slow the producer down
173 // usleep(130);
174 }
175 }
176
177private:
178 QBoundedCircularBuffer<MyComplexType>* m_buffer;
179};
180
181class MyConsumer : public QThread
182{
183 Q_OBJECT
184public:
185 MyConsumer(QBoundedCircularBuffer<MyComplexType>* buffer)
186 : QThread(),
187 m_buffer(buffer)
188 {}
189
190 void run()
191 {
192 for (int i = 0; i < 10000; i++) {
193 //qDebug() << "Consuming" << i;
194 //if (m_buffer->isEmpty())
195 // qDebug() << i << "The buffer is empty. Waiting for producer...";
196 const MyComplexType value = m_buffer->pop();
197 QVERIFY(value.x == i);
198
199 // Uncomment and adjust this to slow the consumer down
200 //usleep(100);
201 }
202 }
203
204private:
205 QBoundedCircularBuffer<MyComplexType>* m_buffer;
206};
207
208void tst_QBoundedCircularBuffer::producerConsumer()
209{
210 QBoundedCircularBuffer<MyComplexType> *buffer = new QBoundedCircularBuffer<MyComplexType>(20);
211 MyProducer producer(buffer);
212 MyConsumer consumer(buffer);
213
214 // Produce and consume...
215 producer.start();
216 consumer.start();
217
218 // Wait until both threads are done
219 producer.wait();
220 consumer.wait();
221
222 // Check all items have been consumed
223 QVERIFY(buffer->freeSize() == 20);
224 QVERIFY(buffer->size() == 0);
225
226 // Cleanup
227 delete buffer;
228}
229
230QTEST_APPLESS_MAIN(tst_QBoundedCircularBuffer)
231#include "tst_qboundedcircularbuffer.moc"
232

source code of qt3d/tests/auto/core/qboundedcircularbuffer/tst_qboundedcircularbuffer.cpp