tests/auto/qsemaphore/tst_qsemaphore.cpp
changeset 0 1918ee327afb
child 4 3b1da2848fc7
equal deleted inserted replaced
-1:000000000000 0:1918ee327afb
       
     1 /****************************************************************************
       
     2 **
       
     3 ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
       
     4 ** All rights reserved.
       
     5 ** Contact: Nokia Corporation (qt-info@nokia.com)
       
     6 **
       
     7 ** This file is part of the test suite of the Qt Toolkit.
       
     8 **
       
     9 ** $QT_BEGIN_LICENSE:LGPL$
       
    10 ** No Commercial Usage
       
    11 ** This file contains pre-release code and may not be distributed.
       
    12 ** You may use this file in accordance with the terms and conditions
       
    13 ** contained in the Technology Preview License Agreement accompanying
       
    14 ** this package.
       
    15 **
       
    16 ** GNU Lesser General Public License Usage
       
    17 ** Alternatively, this file may be used under the terms of the GNU Lesser
       
    18 ** General Public License version 2.1 as published by the Free Software
       
    19 ** Foundation and appearing in the file LICENSE.LGPL included in the
       
    20 ** packaging of this file.  Please review the following information to
       
    21 ** ensure the GNU Lesser General Public License version 2.1 requirements
       
    22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
       
    23 **
       
    24 ** In addition, as a special exception, Nokia gives you certain additional
       
    25 ** rights.  These rights are described in the Nokia Qt LGPL Exception
       
    26 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
       
    27 **
       
    28 ** If you have questions regarding the use of this file, please contact
       
    29 ** Nokia at qt-info@nokia.com.
       
    30 **
       
    31 **
       
    32 **
       
    33 **
       
    34 **
       
    35 **
       
    36 **
       
    37 **
       
    38 ** $QT_END_LICENSE$
       
    39 **
       
    40 ****************************************************************************/
       
    41 
       
    42 
       
    43 #include <QtTest/QtTest>
       
    44 
       
    45 
       
    46 #include <qcoreapplication.h>
       
    47 #include <qthread.h>
       
    48 #include <qsemaphore.h>
       
    49 
       
    50 //TESTED_CLASS=
       
    51 //TESTED_FILES=
       
    52 
       
    53 class tst_QSemaphore : public QObject
       
    54 {
       
    55     Q_OBJECT
       
    56 
       
    57 public:
       
    58     tst_QSemaphore();
       
    59     ~tst_QSemaphore();
       
    60 
       
    61 private slots:
       
    62     void acquire();
       
    63     void tryAcquire();
       
    64     void tryAcquireWithTimeout_data();
       
    65     void tryAcquireWithTimeout();
       
    66     void release();
       
    67     void available();
       
    68     void producerConsumer();
       
    69 };
       
    70 
       
    71 static QSemaphore *semaphore = 0;
       
    72 
       
    73 tst_QSemaphore::tst_QSemaphore()
       
    74 { }
       
    75 
       
    76 tst_QSemaphore::~tst_QSemaphore()
       
    77 { }
       
    78 
       
    79 class ThreadOne : public QThread
       
    80 {
       
    81 public:
       
    82     ThreadOne() {}
       
    83 
       
    84 protected:
       
    85     void run()
       
    86     {
       
    87 	int i = 0;
       
    88 	while ( i < 100 ) {
       
    89             semaphore->acquire();
       
    90 	    i++;
       
    91             semaphore->release();
       
    92 	}
       
    93     }
       
    94 };
       
    95 
       
    96 class ThreadN : public QThread
       
    97 {
       
    98     int N;
       
    99 
       
   100 public:
       
   101     ThreadN(int n) :N(n) { }
       
   102 
       
   103 protected:
       
   104     void run()
       
   105     {
       
   106 	int i = 0;
       
   107 	while ( i < 100 ) {
       
   108             semaphore->acquire(N);
       
   109 	    i++;
       
   110             semaphore->release(N);
       
   111 	}
       
   112     }
       
   113 };
       
   114 
       
   115 void tst_QSemaphore::acquire()
       
   116 {
       
   117     {
       
   118         // old incrementOne() test
       
   119         QVERIFY(!semaphore);
       
   120         semaphore = new QSemaphore;
       
   121         // make some "thing" available
       
   122         semaphore->release();
       
   123 
       
   124         ThreadOne t1;
       
   125         ThreadOne t2;
       
   126 
       
   127         t1.start();
       
   128         t2.start();
       
   129 
       
   130         QVERIFY(t1.wait(4000));
       
   131         QVERIFY(t2.wait(4000));
       
   132 
       
   133         delete semaphore;
       
   134         semaphore = 0;
       
   135     }
       
   136 
       
   137     // old incrementN() test
       
   138     {
       
   139         QVERIFY(!semaphore);
       
   140         semaphore = new QSemaphore;
       
   141         // make 4 "things" available
       
   142         semaphore->release(4);
       
   143 
       
   144         ThreadN t1(2);
       
   145         ThreadN t2(3);
       
   146 
       
   147         t1.start();
       
   148         t2.start();
       
   149 
       
   150         QVERIFY(t1.wait(4000));
       
   151         QVERIFY(t2.wait(4000));
       
   152 
       
   153         delete semaphore;
       
   154         semaphore = 0;
       
   155     }
       
   156 
       
   157     QSemaphore semaphore;
       
   158 
       
   159     QCOMPARE(semaphore.available(), 0);
       
   160     semaphore.release();
       
   161     QCOMPARE(semaphore.available(), 1);
       
   162     semaphore.release();
       
   163     QCOMPARE(semaphore.available(), 2);
       
   164     semaphore.release(10);
       
   165     QCOMPARE(semaphore.available(), 12);
       
   166     semaphore.release(10);
       
   167     QCOMPARE(semaphore.available(), 22);
       
   168 
       
   169     semaphore.acquire();
       
   170     QCOMPARE(semaphore.available(), 21);
       
   171     semaphore.acquire();
       
   172     QCOMPARE(semaphore.available(), 20);
       
   173     semaphore.acquire(10);
       
   174     QCOMPARE(semaphore.available(), 10);
       
   175     semaphore.acquire(10);
       
   176     QCOMPARE(semaphore.available(), 0);
       
   177 }
       
   178 
       
   179 void tst_QSemaphore::tryAcquire()
       
   180 {
       
   181     QSemaphore semaphore;
       
   182 
       
   183     QCOMPARE(semaphore.available(), 0);
       
   184 
       
   185     semaphore.release();
       
   186     QCOMPARE(semaphore.available(), 1);
       
   187     QVERIFY(!semaphore.tryAcquire(2));
       
   188     QCOMPARE(semaphore.available(), 1);
       
   189 
       
   190     semaphore.release();
       
   191     QCOMPARE(semaphore.available(), 2);
       
   192     QVERIFY(!semaphore.tryAcquire(3));
       
   193     QCOMPARE(semaphore.available(), 2);
       
   194 
       
   195     semaphore.release(10);
       
   196     QCOMPARE(semaphore.available(), 12);
       
   197     QVERIFY(!semaphore.tryAcquire(100));
       
   198     QCOMPARE(semaphore.available(), 12);
       
   199 
       
   200     semaphore.release(10);
       
   201     QCOMPARE(semaphore.available(), 22);
       
   202     QVERIFY(!semaphore.tryAcquire(100));
       
   203     QCOMPARE(semaphore.available(), 22);
       
   204 
       
   205     QVERIFY(semaphore.tryAcquire());
       
   206     QCOMPARE(semaphore.available(), 21);
       
   207 
       
   208     QVERIFY(semaphore.tryAcquire());
       
   209     QCOMPARE(semaphore.available(), 20);
       
   210 
       
   211     QVERIFY(semaphore.tryAcquire(10));
       
   212     QCOMPARE(semaphore.available(), 10);
       
   213 
       
   214     QVERIFY(semaphore.tryAcquire(10));
       
   215     QCOMPARE(semaphore.available(), 0);
       
   216 
       
   217     // should not be able to acquire more
       
   218     QVERIFY(!semaphore.tryAcquire());
       
   219     QCOMPARE(semaphore.available(), 0);
       
   220 
       
   221     QVERIFY(!semaphore.tryAcquire());
       
   222     QCOMPARE(semaphore.available(), 0);
       
   223 
       
   224     QVERIFY(!semaphore.tryAcquire(10));
       
   225     QCOMPARE(semaphore.available(), 0);
       
   226 
       
   227     QVERIFY(!semaphore.tryAcquire(10));
       
   228     QCOMPARE(semaphore.available(), 0);
       
   229 }
       
   230 
       
   231 void tst_QSemaphore::tryAcquireWithTimeout_data()
       
   232 {
       
   233     QTest::addColumn<int>("timeout");
       
   234 
       
   235     QTest::newRow("") << 1000;
       
   236     QTest::newRow("") << 10000;
       
   237 }
       
   238 
       
   239 void tst_QSemaphore::tryAcquireWithTimeout()
       
   240 {
       
   241     QFETCH(int, timeout);
       
   242 
       
   243     QSemaphore semaphore;
       
   244     QTime time;
       
   245 
       
   246 
       
   247     QCOMPARE(semaphore.available(), 0);
       
   248 
       
   249     semaphore.release();
       
   250     QCOMPARE(semaphore.available(), 1);
       
   251     time.start();
       
   252     QVERIFY(!semaphore.tryAcquire(2, timeout));
       
   253     QVERIFY(time.elapsed() >= timeout);
       
   254     QCOMPARE(semaphore.available(), 1);
       
   255 
       
   256     semaphore.release();
       
   257     QCOMPARE(semaphore.available(), 2);
       
   258     time.start();
       
   259     QVERIFY(!semaphore.tryAcquire(3, timeout));
       
   260     QVERIFY(time.elapsed() >= timeout);
       
   261     QCOMPARE(semaphore.available(), 2);
       
   262 
       
   263     semaphore.release(10);
       
   264     QCOMPARE(semaphore.available(), 12);
       
   265     time.start();
       
   266     QVERIFY(!semaphore.tryAcquire(100, timeout));
       
   267     QVERIFY(time.elapsed() >= timeout);
       
   268     QCOMPARE(semaphore.available(), 12);
       
   269 
       
   270     semaphore.release(10);
       
   271     QCOMPARE(semaphore.available(), 22);
       
   272     time.start();
       
   273     QVERIFY(!semaphore.tryAcquire(100, timeout));
       
   274     QVERIFY(time.elapsed() >= timeout);
       
   275     QCOMPARE(semaphore.available(), 22);
       
   276 
       
   277     time.start();
       
   278     QVERIFY(semaphore.tryAcquire(1, timeout));
       
   279     QVERIFY(time.elapsed() <= timeout);
       
   280     QCOMPARE(semaphore.available(), 21);
       
   281 
       
   282     time.start();
       
   283     QVERIFY(semaphore.tryAcquire(1, timeout));
       
   284     QVERIFY(time.elapsed() <= timeout);
       
   285     QCOMPARE(semaphore.available(), 20);
       
   286 
       
   287     time.start();
       
   288     QVERIFY(semaphore.tryAcquire(10, timeout));
       
   289     QVERIFY(time.elapsed() <= timeout);
       
   290     QCOMPARE(semaphore.available(), 10);
       
   291 
       
   292     time.start();
       
   293     QVERIFY(semaphore.tryAcquire(10, timeout));
       
   294     QVERIFY(time.elapsed() <= timeout);
       
   295     QCOMPARE(semaphore.available(), 0);
       
   296 
       
   297     // should not be able to acquire more
       
   298     time.start();
       
   299     QVERIFY(!semaphore.tryAcquire(1, timeout));
       
   300     QVERIFY(time.elapsed() >= timeout);
       
   301     QCOMPARE(semaphore.available(), 0);
       
   302 
       
   303     time.start();
       
   304     QVERIFY(!semaphore.tryAcquire(1, timeout));
       
   305     QVERIFY(time.elapsed() >= timeout);
       
   306     QCOMPARE(semaphore.available(), 0);
       
   307 
       
   308     time.start();
       
   309     QVERIFY(!semaphore.tryAcquire(10, timeout));
       
   310     QVERIFY(time.elapsed() >= timeout);
       
   311     QCOMPARE(semaphore.available(), 0);
       
   312 
       
   313     time.start();
       
   314     QVERIFY(!semaphore.tryAcquire(10, timeout));
       
   315     QVERIFY(time.elapsed() >= timeout);
       
   316     QCOMPARE(semaphore.available(), 0);
       
   317 }
       
   318 
       
   319 void tst_QSemaphore::release()
       
   320 { DEPENDS_ON("acquire"); }
       
   321 
       
   322 void tst_QSemaphore::available()
       
   323 { DEPENDS_ON("acquire"); }
       
   324 
       
   325 const char alphabet[] = "ACGTH";
       
   326 const int AlphabetSize = sizeof(alphabet) - 1;
       
   327 
       
   328 const int BufferSize = 4096; // GCD of BufferSize and alphabet size must be 1
       
   329 char buffer[BufferSize];
       
   330 
       
   331 #ifndef Q_OS_WINCE
       
   332 const int ProducerChunkSize = 3;
       
   333 const int ConsumerChunkSize = 7;
       
   334 const int Multiplier = 10;
       
   335 #else
       
   336 const int ProducerChunkSize = 2;
       
   337 const int ConsumerChunkSize = 5;
       
   338 const int Multiplier = 3;
       
   339 #endif
       
   340 
       
   341 // note: the code depends on the fact that DataSize is a multiple of
       
   342 // ProducerChunkSize, ConsumerChunkSize, and BufferSize
       
   343 const int DataSize = ProducerChunkSize * ConsumerChunkSize * BufferSize * Multiplier;
       
   344 
       
   345 QSemaphore freeSpace(BufferSize);
       
   346 QSemaphore usedSpace;
       
   347 
       
   348 class Producer : public QThread
       
   349 {
       
   350 public:
       
   351     void run();
       
   352 };
       
   353 
       
   354 void Producer::run()
       
   355 {
       
   356     for (int i = 0; i < DataSize; ++i) {
       
   357         freeSpace.acquire();
       
   358         buffer[i % BufferSize] = alphabet[i % AlphabetSize];
       
   359         usedSpace.release();
       
   360     }
       
   361     for (int i = 0; i < DataSize; ++i) {
       
   362         if ((i % ProducerChunkSize) == 0)
       
   363             freeSpace.acquire(ProducerChunkSize);
       
   364         buffer[i % BufferSize] = alphabet[i % AlphabetSize];
       
   365         if ((i % ProducerChunkSize) == (ProducerChunkSize - 1))
       
   366             usedSpace.release(ProducerChunkSize);
       
   367     }
       
   368 }
       
   369 
       
   370 class Consumer : public QThread
       
   371 {
       
   372 public:
       
   373     void run();
       
   374 };
       
   375 
       
   376 void Consumer::run()
       
   377 {
       
   378     for (int i = 0; i < DataSize; ++i) {
       
   379         usedSpace.acquire();
       
   380         QCOMPARE(buffer[i % BufferSize], alphabet[i % AlphabetSize]);
       
   381         freeSpace.release();
       
   382     }
       
   383     for (int i = 0; i < DataSize; ++i) {
       
   384         if ((i % ConsumerChunkSize) == 0)
       
   385             usedSpace.acquire(ConsumerChunkSize);
       
   386         QCOMPARE(buffer[i % BufferSize], alphabet[i % AlphabetSize]);
       
   387         if ((i % ConsumerChunkSize) == (ConsumerChunkSize - 1))
       
   388             freeSpace.release(ConsumerChunkSize);
       
   389     }
       
   390 }
       
   391 
       
   392 void tst_QSemaphore::producerConsumer()
       
   393 {
       
   394     Producer producer;
       
   395     Consumer consumer;
       
   396     producer.start();
       
   397     consumer.start();
       
   398     producer.wait();
       
   399     consumer.wait();
       
   400 }
       
   401 
       
   402 QTEST_MAIN(tst_QSemaphore)
       
   403 #include "tst_qsemaphore.moc"