Пример #1
0
void GraphInvalidator::
        test()
{
    // It should invalidate caches and wakeup workers
    {
        // create
        Dag::ptr dag(new Dag);
        Bedroom::ptr bedroom(new Bedroom);
        INotifier::ptr notifier(new BedroomNotifier(bedroom));
        Step::ptr step(new Step(Signal::OperationDesc::ptr()));
        WaitForWakeupMock sleeper(bedroom);

        // wire up
        sleeper.start ();
        dag.write ()->appendStep(step);
        Signal::Intervals initial_valid(-20,60);
        int taskid = Step::registerTask(step.write (), initial_valid.spannedInterval ());
        (void)taskid; // discard
        EXCEPTION_ASSERT_EQUALS(step.read ()->not_started(), ~initial_valid);
        EXCEPTION_ASSERT(sleeper.isRunning ());

        EXCEPTION_ASSERT_EQUALS(sleeper.wait (1), false);
        EXCEPTION_ASSERT_EQUALS(bedroom->sleepers (), 1);

        // test
        GraphInvalidator graphInvalidator(dag, notifier, step);
        Signal::Intervals deprecated(40,50);
        graphInvalidator.deprecateCache (deprecated);

        EXCEPTION_ASSERT_EQUALS(step.read ()->not_started(), ~initial_valid | deprecated);
        sleeper.wait (1);
        EXCEPTION_ASSERT_EQUALS(bedroom->sleepers (), 0);
        EXCEPTION_ASSERT(sleeper.isFinished ());
    }
}
Пример #2
0
void RenderOperationDesc::
    test()
{
    // The RenderOperationDesc class should keep the filter operation used by a
    // render target and notify the render target about processing events.
    {
        RenderOperationDesc* rod;
        RenderOperationDescMockTarget* target;

        OperationDesc::ptr operation( new Test::TransparentOperationDesc() );
        RenderTarget::ptr rtp(target = new RenderOperationDescMockTarget());

        Signal::OperationDesc::ptr ro(rod = new RenderOperationDesc(operation, rtp));
        Signal::Operation::ptr o = ro.write ()->createOperation(0);

        // Operations are processed through a Processing::Step
        Processing::Step step(ro);
        step.deprecateCache (Interval(4,9));
        o->process (pBuffer());

        EXCEPTION_ASSERT_EQUALS( Interval(4,9), target->I );
        EXCEPTION_ASSERT_EQUALS( 1, target->processed_count );
        EXCEPTION_ASSERT_EQUALS( (void*)0, rod->transform_desc ().get () );
    }
}
Пример #3
0
void BufferSource::
        test()
{
    pBuffer b(new Buffer(Interval(60,70), 40, 7));
    for (int c=0; c<b->number_of_channels (); ++c)
    {
        float *p = b->getChannel (c)->waveform_data ()->getCpuMemory ();
        for (int i=0; i<b->number_of_samples (); ++i)
            p[i] = c + i/(float)b->number_of_samples ();
    }
    BufferSource s(b);
    Operation::ptr o = s.createOperation (0);
    Operation::test (o, &s);

    pBuffer r(new Buffer(Interval(60,70), 40, 7));
    pBuffer d = o->process (r);
    EXCEPTION_ASSERT( *d == *b );

    r = pBuffer(new Buffer(Interval(61,71), 1, 1));
    d = o->process (r);
    EXCEPTION_ASSERT_EQUALS (b->number_of_channels (), d->number_of_channels ());
    EXCEPTION_ASSERT_EQUALS (b->number_of_samples (), d->number_of_samples ());
    EXCEPTION_ASSERT_EQUALS (r->getInterval (), d->getInterval ());
    for (int c=0; c<b->number_of_channels (); ++c)
    {
        float *bp = b->getChannel (c)->waveform_data ()->getCpuMemory ();
        float *dp = d->getChannel (c)->waveform_data ()->getCpuMemory ();

        for (int i=0; i<b->number_of_samples ()-1; ++i)
            EXCEPTION_ASSERT_EQUALS (bp[1+i], dp[i]);
        EXCEPTION_ASSERT_EQUALS (dp[9], 0);
    }
}
Пример #4
0
void QtEventWorkerFactory::
        test()
{
    std::string name = "QtEventWorkers";
    int argc = 1;
    char * argv = &name[0];
    QApplication a(argc,&argv); // takes 0.4 s if this is the first instantiation of QApplication

    Workers::test ([](ISchedule::ptr schedule){
        Bedroom::ptr bedroom(new Bedroom);
        return IWorkerFactory::ptr(new QtEventWorkerFactory(schedule, bedroom));
    });

    {
        UNITTEST_STEPS TaskInfo("It should terminate all threads when it's closed");

        ISchedule::ptr schedule[] = {
            ISchedule::ptr(new SleepScheduleMock),
            ISchedule::ptr(new LockScheduleMock),
            ISchedule::ptr(new BusyScheduleMock)
        };

        for (unsigned i=0; i<sizeof(schedule)/sizeof(schedule[0]); i++) {
            Timer t;
            {
                ISchedule::ptr s = schedule[i];
                //TaskInfo ti(boost::format("%s") % vartype(*s));
                Bedroom::ptr bedroom(new Bedroom);

                Processing::Workers workers(IWorkerFactory::ptr(new QtEventWorkerFactory(s, bedroom)));
                Bedroom::Bed bed = dynamic_cast<BlockScheduleMock*>(s.get ())->bedroom.getBed();

                workers.addComputingEngine(Signal::ComputingEngine::ptr());

                // Wait until the schedule has been called (Bedroom supports
                // that the wakeup in schedule is called even before this sleep call
                // as long as 'bed' is allocated before the wakeup call)
                bed.sleep ();

                EXCEPTION_ASSERT_EQUALS(false, workers.remove_all_engines (10));
                EXCEPTION_ASSERT_EQUALS(true, QtEventWorkerFactory::terminate_workers (workers, 0));

                EXCEPTION_ASSERT_EQUALS(workers.n_workers(), 0u);
                EXPECT_EXCEPTION(QtEventWorker::TerminatedException, workers.rethrow_any_worker_exception ());
                workers.clean_dead_workers ();
            }
            float elapsed = t.elapsed ();
            float n = (i+1)*0.00001;
            EXCEPTION_ASSERT_LESS(0.01+n, elapsed);
            EXCEPTION_ASSERT_LESS(elapsed, 0.04+n); // +n makes it possible to see in the test log which iteration that failed
        }
    }

    // It should wake up sleeping workers when any work is done to see if they can
    // help out on what's left.
    {

    }
}
Пример #5
0
void Step::
        test()
{
    // It should keep a cache for a signal processing step (defined by an OpertionDesc).
    //
    // The cache description should contain information about what's out_of_date
    // and what's currently being updated.
    {
        // Create an OperationDesc
        pBuffer b(new Buffer(Interval(60,70), 40, 7));
        for (unsigned c=0; c<b->number_of_channels (); ++c)
        {
            float *p = b->getChannel (c)->waveform_data ()->getCpuMemory ();
            for (int i=0; i<b->number_of_samples (); ++i)
                p[i] = c + 1+i/(float)b->number_of_samples ();
        }

        // Create a Step
        Step::ptr s2( new Step(OperationDesc::ptr()));

        shared_state<Step>::weak_ptr ws = s2;
        Step::ptr s = ws.lock ();

        // It should contain information about what's out_of_date and what's currently being updated.
        int taskid = s->registerTask(b->getInterval ());
        EXCEPTION_ASSERT_EQUALS(s->not_started (), ~Intervals(b->getInterval ()));
        EXCEPTION_ASSERT_EQUALS(s->out_of_date(), Intervals::Intervals_ALL);
        Step::finishTask(s, taskid, b);
        EXCEPTION_ASSERT_EQUALS(s->out_of_date(), ~Intervals(b->getInterval ()));

        EXCEPTION_ASSERT( *b == *Step::readFixedLengthFromCache (s, b->getInterval ()) );
    }

    // A crashed signal processing step should behave as a transparent operation.
    {
        OperationDesc::ptr silence(new Signal::OperationSetSilent(Signal::Interval(2,3)));
        Step s(silence);
        EXCEPTION_ASSERT(!s.get_crashed ());
        EXCEPTION_ASSERT(s.operation_desc ());
        EXCEPTION_ASSERT(s.operation_desc ().read ()->createOperation (0));
        EXCEPTION_ASSERT(!dynamic_cast<Test::TransparentOperationDesc*>(s.operation_desc ().raw ()));
        EXCEPTION_ASSERT(!dynamic_cast<Test::TransparentOperation*>(s.operation_desc ().read ()->createOperation (0).get ()));
        s.mark_as_crashed_and_get_invalidator ();
        EXCEPTION_ASSERT(s.get_crashed ());
        EXCEPTION_ASSERT(s.operation_desc ());
        EXCEPTION_ASSERT(s.operation_desc ().read ()->createOperation (0));
        EXCEPTION_ASSERT(dynamic_cast<Test::TransparentOperationDesc*>(s.operation_desc ().raw ()));
        EXCEPTION_ASSERT(dynamic_cast<Test::TransparentOperation*>(s.operation_desc ().read ()->createOperation (0).get ()));
    }
}
Пример #6
0
void PrintBuffer::
        test()
{
    // It should print buffer contents for debugging purposes.
    {
        Signal::pBuffer b = RandomBuffer::smallBuffer();
        std::string s = PrintBuffer::printBuffer(b);
        std::string expected = "[4, 9)5#, 2 channels\n[0] = { -3, 7, -8, 5, 3 }\n[1] = { 1, -9, -3, 6, -2 }\n";
        EXCEPTION_ASSERT_EQUALS(s, expected);

        std::string stats = PrintBuffer::printBufferStats(b);
        expected = "[4, 9)5#, 2 channels\n[0]: max = 7, min = -8, mean = 0.8, std = 5.52811\n[1]: max = 6, min = -9, mean = -1.4, std = 4.92341\n";
        EXCEPTION_ASSERT_EQUALS(stats, expected);
    }
}
Пример #7
0
void BlockCache::
        test()
{
    // It should store allocated blocks readily available
    {
        Reference r1;
        Reference r2 = r1.right ();
        BlockLayout bl(2,2,1);
        VisualizationParams::ptr vp;
        pBlock b1(new Block(r1, bl, vp));
        pBlock b2(new Block(r2, bl, vp));

        BlockCache c;
        c.insert (b1);
        c.insert (b2);
        pBlock b3 = c.find(r1);
        pBlock b4 = c.find(r2);
        pBlock b5 = c.find (r2.parentHorizontal ());
        pBlock b6 = c.find (r1.left ());

        EXCEPTION_ASSERT( b1 == b3 );
        EXCEPTION_ASSERT( b2 == b4 );
        EXCEPTION_ASSERT( r2 == r1.right () );
        EXCEPTION_ASSERT_EQUALS( r2.parentHorizontal (), r1 );
        EXCEPTION_ASSERT( b1 == b5 );
        EXCEPTION_ASSERT( b6 == pBlock() );
    }
}
Пример #8
0
void Step::
        finishTask(Step::ptr step, int taskid, pBuffer result)
{
    Interval result_interval;
    if (result)
        result_interval = result->getInterval ();

    TASKINFO TaskInfo ti(format("Step::finishTask %2% on %1%")
              % step.raw ()->operation_name()
              % result_interval);

    if (result) {
        // Result must have the same number of channels and sample rate as previous cache.
        // Call deprecateCache(Interval::Interval_ALL) to erase the cache when chainging number of channels or sample rate.
        step.raw ()->cache_->put (result);
    }

    auto self = step.write ();
    int matched_task = self->running_tasks.count (taskid);
    if (1 != matched_task) {
        Log("C = %d, taskid = %x on %s") % matched_task % taskid % self->operation_name ();
        EXCEPTION_ASSERT_EQUALS( 1, matched_task );
    }

    Intervals expected_output = self->running_tasks[ taskid ];

    Intervals update_miss = expected_output - result_interval;
    self->not_started_ |= update_miss;

    if (!result) {
        TASKINFO TaskInfo(format("The task was cancelled. Restoring %1% for %2%")
                 % update_miss
                 % self->operation_name());
    } else {
        if (update_miss) {
            TaskInfo(format("These samples were supposed to be updated by the task but missed: %1% by %2%")
                     % update_miss
                     % self->operation_name());
        }
        if (result_interval - expected_output) {
            // These samples were not supposed to be updated by the task but were calculated anyway
            TaskInfo(format("Unexpected extras: %1% = (%2%) - (%3%) from %4%")
                     % (result_interval - expected_output)
                     % result_interval
                     % expected_output
                     % self->operation_name());

            // The samples are still marked as invalid. Would need to remove the
            // extra calculated samples from not_started_ but that would fail
            // in a situation where deprecatedCache is called after the task has
            // been created. So not_started_ can't be modified here (unless calls
            // to deprecatedCache were tracked).
        }
    }

    self->running_tasks.erase ( taskid );
    self.unlock ();

    step.raw ()->wait_for_tasks_.notify_all ();
}
Пример #9
0
void DataStorageString::
        test()
{
    // It should print contents of a DataStorage for debugging purposes.
    {
        float srcdata[] = { 1, 2, 3, 4 };
        DataStorage<float>::ptr data;
        {
            data = CpuMemoryStorage::BorrowPtr( DataStorageSize(2,2), srcdata, false );

            std::string s = DataStorageString::printDataStorage (data);
            std::string expected = "[2, 2]\n[y:0] = { 1, 2 }\n[y:1] = { 3, 4 }";
            EXCEPTION_ASSERT_EQUALS(s, expected);

            std::string stats = DataStorageString::printDataStorageStats (data);
            expected = "size = [2, 2], min = 1, max = 4, mean = 2.5, std = 1.11803";
            EXCEPTION_ASSERT_EQUALS(stats, expected);
        }

        {
            data = CpuMemoryStorage::BorrowPtr( DataStorageSize(3), srcdata, false );
            std::string s = DataStorageString::printDataStorage (data);
            std::string expected = "[3] = { 1, 2, 3 }";
            EXCEPTION_ASSERT_EQUALS(s, expected);

            std::string stats = DataStorageString::printDataStorageStats (data);
            expected = "size = [3], min = 1, max = 3, mean = 2, std = 0.816497";
            EXCEPTION_ASSERT_EQUALS(stats, expected);
        }

        {
            data = CpuMemoryStorage::BorrowPtr( DataStorageSize(2,1,2), srcdata, false );
            std::string s = DataStorageString::printDataStorage (data);
            std::string expected = "[2, 1, 2]\n[z:0, y:0] = { 1, 2 }\n[z:1, y:0] = { 3, 4 }";
            EXCEPTION_ASSERT_EQUALS(s, expected);

            std::string stats = DataStorageString::printDataStorageStats (data);
            expected = "size = [2, 1, 2], min = 1, max = 4, mean = 2.5, std = 1.11803";
            EXCEPTION_ASSERT_EQUALS(stats, expected);
        }

        {
            data = CpuMemoryStorage::BorrowPtr( DataStorageSize(1,2,2), srcdata, false );
            std::string s = DataStorageString::printDataStorage (data);
            std::string expected = "[1, 2, 2]\n[z:0, y:0] = { 1 }\n[z:0, y:1] = { 2 }\n[z:1, y:0] = { 3 }\n[z:1, y:1] = { 4 }";
            EXCEPTION_ASSERT_EQUALS(s, expected);

            std::string stats = DataStorageString::printDataStorageStats (data);
            expected = "size = [1, 2, 2], min = 1, max = 4, mean = 2.5, std = 1.11803";
            EXCEPTION_ASSERT_EQUALS(stats, expected);
        }
    }
}
Пример #10
0
GlTexture::GlTexture(unsigned int textureId)
    :	width( 0 ),
        height( 0 ),
        textureId( textureId ),
        ownTextureId( 0 )
{
    EXCEPTION_ASSERT_LESS(0u, textureId);
    int width=0, height=0;
    glBindTexture (GL_TEXTURE_2D, textureId);
    GlException_SAFE_CALL( glGetTexLevelParameteriv (GL_TEXTURE_2D, 0, GL_TEXTURE_WIDTH, &width) );
    GlException_SAFE_CALL( glGetTexLevelParameteriv (GL_TEXTURE_2D, 0, GL_TEXTURE_HEIGHT, &height) );
    glBindTexture (GL_TEXTURE_2D, 0);
    this->width = width;
    this->height = height;
    EXCEPTION_ASSERT_LESS(0, width);
    EXCEPTION_ASSERT_LESS(0, height);
    EXCEPTION_ASSERT_EQUALS(this->width, width);
    EXCEPTION_ASSERT_EQUALS(this->height, height);
}
Пример #11
0
pBuffer SourceBase::
        readChecked( const Interval& I )
{
    TIME_SOURCEBASE TaskTimer tt("%s::readChecked( %s )", vartype(*this).c_str(), I.toString().c_str());

    EXCEPTION_ASSERT( I.count() );

    pBuffer r = read(I);

    // Check if read returned the first sample in interval I
    Interval i(I.first, I.first + 1);
    if ((i & r->getInterval()) != i)
    {
        TaskTimer tt("%s::readChecked( %s ) got %s", vartype(*this).c_str(), I.toString().c_str(), r->getInterval ().toString ().c_str ());
        EXCEPTION_ASSERT_EQUALS( i & r->getInterval(), i );
    }

    return r;
}
Пример #12
0
void DummyTransform::
        test ()
{
    // It should transform a buffer into a dummy state and back.
    for (int i=0; i<2; i++) {
        TRACE_PERF(i==0
                   ? "It should init dummytransform"
                   : "It should transform a buffer into a dummy state and back");

        DummyTransform t;

        Signal::pBuffer b = Test::RandomBuffer::smallBuffer((int)hash<string>()("DummyTransform"));
        pChunk c = t(b->getChannel (0));
        EXCEPTION_ASSERT(c);

        Signal::pMonoBuffer b2 = t.inverse (c);
        EXCEPTION_ASSERT(b->getChannel (0) == b2);

        EXCEPTION_ASSERT_EQUALS(c->getCoveredInterval (), b->getInterval ());
    }
}
Пример #13
0
void WaveformBlockFilterDesc::
        test()
{
    // It should instantiate CwtBlockFilter for different engines.
    {
        Heightmap::MergeChunkDesc::ptr mcd(new WaveformBlockFilterDesc);
        MergeChunk::ptr mc = mcd.read ()->createMergeChunk (0);

        EXCEPTION_ASSERT( !mc );

        Signal::ComputingCpu cpu;
        mc = mcd.read ()->createMergeChunk (&cpu);
        EXCEPTION_ASSERT( mc );
        EXCEPTION_ASSERT_EQUALS( vartype(*mc.get ()), "Heightmap::TfrMappings::WaveformBlockFilter" );

        Signal::ComputingCuda cuda;
        mc = mcd.read ()->createMergeChunk (&cuda);
        EXCEPTION_ASSERT( !mc );

        Signal::ComputingOpenCL opencl;
        mc = mcd.read ()->createMergeChunk (&opencl);
        EXCEPTION_ASSERT( !mc );
    }
}
Пример #14
0
void QtEventWorker::
        test()
{
    std::string name = "Worker";
    int argc = 1;
    char * argv = &name[0];
    QApplication a(argc,&argv);

    // It should start and stop automatically
    {
        UNITTEST_STEPS TaskTimer tt("It should start and stop automatically");

        ISchedule::ptr gettask(new GetTaskMock());
        QtEventWorker worker(Signal::ComputingEngine::ptr(), gettask);

        QThread::yieldCurrentThread ();
        EXCEPTION_ASSERT( worker.isRunning () );
    }

    // It should run tasks as given by the scheduler
    {
        UNITTEST_STEPS TaskTimer tt("It should run tasks as given by the scheduler");

        ISchedule::ptr gettask(new GetTaskMock());
        QtEventWorker worker(Signal::ComputingEngine::ptr(), gettask);

        worker.wait (1);

        EXCEPTION_ASSERT_EQUALS( 1, dynamic_cast<GetTaskMock*>(&*gettask)->get_task_count );
        // Verify that tasks execute properly in Task::test.

        EXCEPTION_ASSERT( worker.isRunning () );
        worker.abort ();
        EXCEPTION_ASSERT( worker.wait (2) );
        EXCEPTION_ASSERT( !worker.isRunning () );
    }

    // It should wait to be awaken if there are no tasks
    {
        UNITTEST_STEPS TaskTimer tt("It should run tasks as given by the scheduler");

        ISchedule::ptr gettask(new GetTaskMock());
        QtEventWorker worker(Signal::ComputingEngine::ptr(), gettask);

        EXCEPTION_ASSERT( !worker.wait (1) );
        EXCEPTION_ASSERT_EQUALS( 1, dynamic_cast<GetTaskMock*>(&*gettask)->get_task_count );
        QThread::msleep (1);
        EXCEPTION_ASSERT_EQUALS( 1, dynamic_cast<GetTaskMock*>(&*gettask)->get_task_count );

        worker.wakeup ();
        worker.wait (1);
        EXCEPTION_ASSERT_EQUALS( 2, dynamic_cast<GetTaskMock*>(&*gettask)->get_task_count );
    }

    // It should store information about a crashed task (segfault) and stop execution.
    if (!DetectGdb::is_running_through_gdb() && !DetectGdb::was_started_through_gdb ())
    {
        UNITTEST_STEPS TaskTimer tt("It should store information about a crashed task (segfault) and stop execution");

        PrettifySegfault::EnableDirectPrint (false);

        ISchedule::ptr gettask(new GetTaskSegFaultMock());
        QtEventWorker worker(Signal::ComputingEngine::ptr(), gettask);

        worker.wait (1);
        worker.abort ();
        EXCEPTION_ASSERT( worker.wait (1) );
        EXCEPTION_ASSERT( worker.caught_exception () );

        EXPECT_EXCEPTION(segfault_sigill_exception, rethrow_exception(worker.caught_exception ()));

        PrettifySegfault::EnableDirectPrint (true);
    }

    // It should store information about a crashed task (std::exception) and stop execution. (1)
    {
        UNITTEST_STEPS TaskTimer tt("It should store information about a crashed task (std::exception) and stop execution (1)");

        ISchedule::ptr gettask(new GetTaskExceptionMock());
        QtEventWorker worker(Signal::ComputingEngine::ptr(), gettask);

        QThread::yieldCurrentThread ();
    }

    // It should store information about a crashed task (std::exception) and stop execution. (2)
    {
        UNITTEST_STEPS TaskTimer tt("It should store information about a crashed task (std::exception) and stop execution (2)");

        ISchedule::ptr gettask(new GetTaskExceptionMock());
        QtEventWorker worker(Signal::ComputingEngine::ptr(), gettask);

        worker.wait (1);
        worker.abort ();
        worker.wait (1);
        worker.abort ();

        EXCEPTION_ASSERT( worker.caught_exception () );

        try {
            rethrow_exception(worker.caught_exception ());
            BOOST_THROW_EXCEPTION(boost::unknown_exception());
        } catch (const ExceptionAssert& x) {
            const std::string* message = boost::get_error_info<ExceptionAssert::ExceptionAssert_message>(x);
            EXCEPTION_ASSERT_EQUALS( "testing that worker catches exceptions from a scheduler", message?*message:"" );
        }
    }

#if !defined SHARED_STATE_NO_TIMEOUT
    // It should store information about a crashed task (LockFailed) and stop execution.
    {
        UNITTEST_STEPS TaskTimer tt("It should store information about a crashed task (LockFailed) and stop execution.");

        ISchedule::ptr gettask(new ImmediateDeadLockMock());

        QtEventWorker worker(Signal::ComputingEngine::ptr(), gettask);

        worker.wait (2);
        worker.abort ();
        EXCEPTION_ASSERT( worker.wait (10) );
        EXCEPTION_ASSERT( worker.caught_exception () );
        EXPECT_EXCEPTION(lock_failed, rethrow_exception(worker.caught_exception ()));

        EXCEPTION_ASSERT_EQUALS( 1, dynamic_cast<GetTaskMock*>(&*gettask)->get_task_count );
    }
#endif

    // It should not hang if it causes a deadlock (1)
    {
        UNITTEST_STEPS TaskTimer tt("It should not hang if it causes a deadlock (1)");

        ISchedule::ptr gettask(new DeadLockMock());
        QtEventWorker worker(Signal::ComputingEngine::ptr(), gettask);

        EXCEPTION_ASSERT( worker.isRunning () );
        worker.terminate ();
        worker.terminate ();
        worker.terminate ();
        worker.terminate ();
        worker.abort ();
        worker.abort ();
        worker.abort ();
        worker.abort ();
        EXCEPTION_ASSERT( worker.wait (1) );
    }

    // It should not hang if it causes a deadlock (2)
    {
        UNITTEST_STEPS TaskTimer tt("It should not hang if it causes a deadlock (2)");

        ISchedule::ptr gettask(new DeadLockMock());
        QtEventWorker worker(Signal::ComputingEngine::ptr(), gettask);

        EXCEPTION_ASSERT( !worker.wait (1) );
        worker.terminate ();
        EXCEPTION_ASSERT( worker.wait (2) ); // Finish within 2 ms after terminate
        EXPECT_EXCEPTION( TerminatedException, rethrow_exception(worker.caught_exception ()) );
    }

    // It should announce when tasks are finished.
    {
        UNITTEST_STEPS TaskTimer tt("It should announce when tasks are finished.");

        ISchedule::ptr gettask(new DummySchedule());
        QtEventWorker worker(Signal::ComputingEngine::ptr(), gettask, false);

        QTimer t;
        t.setSingleShot( true );
        t.setInterval( 100 );

        QEventLoop e;
        connect (&t, SIGNAL(timeout()), &e, SLOT(quit()));
        connect (&worker, SIGNAL(oneTaskDone()), &e, SLOT(quit()), Qt::DirectConnection);

        worker.wakeup ();
        t.start();

        e.exec ();

        bool aborted_from_timeout = !t.isActive();
        EXCEPTION_ASSERT(!aborted_from_timeout);
   }
}
Пример #15
0
void WorkerCrashLogger::
        test()
{
    // It should fetch information asynchronously of crashed workers.
    {
        DEBUG TaskInfo ti("Catch info from a previously crashed worker");

        std::string name = "WorkerCrashLogger1";
        int argc = 1;
        char * argv = &name[0];
        QApplication a(argc,&argv);

        //for (int consume=0; consume<2; consume++)
        ISchedule::ptr schedule(new DummyScheduler);
        Bedroom::ptr bedroom(new Bedroom);
        Workers::ptr workers(new Workers(IWorkerFactory::ptr(new QtEventWorkerFactory(schedule, bedroom))));

        {
            WorkerCrashLogger wcl(workers);
        }

        // Catch info from a previously crashed worker
        addAndWaitForStop(workers);
        addAndWaitForStop(workers);

        {
            TRACE_PERF("Init");

            WorkerCrashLogger wcl(workers);
            a.processEvents (); // Init new thread before telling it to quit

            // When the thread quits. Wait for the beautifier to log everything.
        }

        // Should have consumed all workers
        Workers::DeadEngines de = workers.write ()->clean_dead_workers();
        EXCEPTION_ASSERT_EQUALS(de.size (), 0u);
    }

    {
        DEBUG TaskInfo ti("Catch info from a crashed worker as it happens");

        std::string name = "WorkerCrashLogger2";
        int argc = 1;
        char * argv = &name[0];
        QApplication a(argc,&argv);

        ISchedule::ptr schedule(new DummyScheduler);
        Bedroom::ptr bedroom(new Bedroom);
        Workers::ptr workers(new Workers(IWorkerFactory::ptr(new QtEventWorkerFactory(schedule, bedroom))));

        {
            TRACE_PERF("Catch info from a crashed worker as it happens");

            WorkerCrashLogger wcl(workers);

            // Catch info from a crashed worker as it happens
            addAndWaitForStop(workers);
            addAndWaitForStop(workers);
        }

        Workers::DeadEngines de = workers.write ()->clean_dead_workers();
        EXCEPTION_ASSERT_EQUALS(de.size (), 0u);
    }

    {
        DEBUG TaskInfo ti("Support not consuming workers");

        std::string name = "WorkerCrashLogger3";
        int argc = 1;
        char * argv = &name[0];
        QApplication a(argc,&argv);

        ISchedule::ptr schedule(new DummyScheduler);
        Bedroom::ptr bedroom(new Bedroom);
        Workers::ptr workers(new Workers(IWorkerFactory::ptr(new QtEventWorkerFactory(schedule, bedroom))));

        // Catch info from a previously crashed worker
        addAndWaitForStop(workers);

        {
            TRACE_PERF("Support not consuming workers");

            WorkerCrashLogger wcl(workers, false);

            a.processEvents ();

            // Catch info from a crashed worker as it happens
            addAndWaitForStop(workers);
        }

        // Should not have consumed any workers
        Workers::DeadEngines de = workers.write ()->clean_dead_workers();
        EXCEPTION_ASSERT_EQUALS(de.size (), 2u);
    }
}
Пример #16
0
void blocking_queue_test::
        test ()
{
    // It should provide a thread safe solution to the multiple consumer-multiple producer pattern.
    {
        typedef blocking_queue<function<int()>> queue;
        queue q;

        auto producer = [&q](int a, int b) {
            for (int i=a; i<b; i++)
                q.push ([i]() { return i; });
        };

        auto consumer = [&q]() {
            int S = 0;

            try {
                while (true)
                    S += q.pop ()();
            } catch (queue::abort_exception) {}

            return S;
        };

        vector<thread> producers;
        vector<future<int>> consumers;
        for (int i=0; i<10; i++)
        {
            producers.push_back (thread(producer, 100*i, 100*i + 100));
            consumers.push_back (async(launch::async, consumer));
        }

        for (thread& t : producers)
            t.join ();

        q.close ();

        int S = 0;
        for (future<int>& f : consumers)
        {
            int v = f.get ();
            EXCEPTION_ASSERT_LESS(1000, v);
            S += v;
        }

        EXCEPTION_ASSERT_EQUALS(S, (999-0)/2.0 * 1000);
    }

    // pop_for
    {
        typedef blocking_queue<int> queue;
        queue q;

        auto a = async(launch::async, [&q]() {
            EXCEPTION_ASSERT_EQUALS(q.pop_for (chrono::duration<double>(0.0001)), 0);
            EXCEPTION_ASSERT_EQUALS(q.pop_for (chrono::duration<double>(0.1)), 2);
            EXCEPTION_ASSERT_EQUALS(q.pop_for (chrono::duration<double>(0.0001)), 0);
        });

        this_thread::sleep_for (chrono::duration<double>(0.001));

        q.push (2);
        a.get();
    }

    // clear
    {
        typedef blocking_queue<int> queue;
        queue q;

        q.push (2);
        q.push (4);

        EXCEPTION_ASSERT(!q.empty ());
        auto q2 = q.clear ();
        EXCEPTION_ASSERT(q.empty ());
        EXCEPTION_ASSERT_EQUALS(q2.size (), 2u);
    }
}
Пример #17
0
void ChainInfo::
        test()
{
    std::string name = "ChainInfo";
    int argc = 1;
    char * argv = &name[0];
    QApplication a(argc,&argv);

    // It should provide info about the running state of a signal processing chain
    {
        Chain::ptr cp = Chain::createDefaultChain ();
        ChainInfo c(cp);

        EXCEPTION_ASSERT( !c.hasWork () );
        EXCEPTION_ASSERT_EQUALS( QThread::idealThreadCount () + 1, c.n_workers () );
        EXCEPTION_ASSERT_EQUALS( 0, c.dead_workers () );
    }

    Signal::OperationDesc::ptr transparent(new Test::TransparentOperationDesc);
    Signal::OperationDesc::ptr buffersource(new Signal::BufferSource(Test::RandomBuffer::smallBuffer ()));

    // It should say that there is no work if a step has crashed (no crash).
    {
        UNITTEST_STEPS TaskInfo("It should say that there is no work if a step has crashed (no crash)");

        Chain::ptr cp = Chain::createDefaultChain ();
        ChainInfo c(cp);

        TargetMarker::ptr at = cp.write ()->addTarget(transparent);
        TargetNeeds::ptr n = at->target_needs();
        cp.write ()->addOperationAt(buffersource,at);
        EXCEPTION_ASSERT( !c.hasWork () );
        n->updateNeeds(Signal::Interval(0,10));
        EXCEPTION_ASSERT( c.hasWork () );
        QThread::msleep (10);
        EXCEPTION_ASSERT( !c.hasWork () );
        EXCEPTION_ASSERT_EQUALS( 0, c.dead_workers () );
    }

    // It should say that there is no work if a step has crashed (requiredIntervalCrash).
    {
        UNITTEST_STEPS TaskInfo("It should say that there is no work if a step has crashed (requiredIntervalCrash)");

        Chain::ptr cp = Chain::createDefaultChain ();
        ChainInfo c(cp);

        TargetMarker::ptr at = cp.write ()->addTarget(Signal::OperationDesc::ptr(new RequiredIntervalCrash));
        TargetNeeds::ptr n = at->target_needs();
        cp.write ()->addOperationAt(buffersource,at);
        EXCEPTION_ASSERT( !c.hasWork () );
        EXCEPTION_ASSERT_EQUALS( 0, c.dead_workers () );
        n->updateNeeds(Signal::Interval(0,10));
        EXCEPTION_ASSERT( n->sleep (12) );
        EXCEPTION_ASSERT( !c.hasWork () );
        QThread::msleep (1);
        EXCEPTION_ASSERT_EQUALS( 1, c.dead_workers () );
    }

    // It should say that there is no work if a step has crashed (process).
    {
        UNITTEST_STEPS TaskInfo("It should say that there is no work if a step has crashed (process)");

        Chain::ptr cp = Chain::createDefaultChain ();
        ChainInfo c(cp);

        TargetMarker::ptr at = cp.write ()->addTarget(Signal::OperationDesc::ptr(new ProcessCrashOperationDesc));
        TargetNeeds::ptr n = at->target_needs();
        cp.write ()->addOperationAt(buffersource,at);
        EXCEPTION_ASSERT( !c.hasWork () );
        n->updateNeeds(Signal::Interval(0,10));
        EXCEPTION_ASSERT( c.hasWork () );
        QThread::msleep (10);
        a.processEvents (); // a crashed worker announces 'wakeup' to the others through the application eventloop
        EXCEPTION_ASSERT( n->sleep (10) );
        EXCEPTION_ASSERT( !c.hasWork () );
        EXCEPTION_ASSERT_EQUALS( 1, c.dead_workers () );
    }
}
Пример #18
0
void Bedroom::
        test()
{
    // It should allow different threads to sleep on this object until another thread calls wakeup()
    for (int j=0;j<2; j++) {
        Bedroom::ptr bedroom(new Bedroom);
        int snoozes = 10;
        SleepyFaceMock sleepyface1(bedroom, snoozes);
        SleepyFaceMock sleepyface2(bedroom, snoozes);

        sleepyface1.start ();
        sleepyface2.start ();

        for (int i=snoozes; i>=0; i--) {
            EXCEPTION_ASSERT_EQUALS(sleepyface1.wait (1), i>0?false:true);
            EXCEPTION_ASSERT_EQUALS(sleepyface2.wait (1), i>0?false:true);

            // sleepyface1 and sleepyface2 shoule be sleeping now
            EXCEPTION_ASSERT_EQUALS(bedroom->sleepers(), i>0?2:0);

            // they should have 'i' times left to snooze
            EXCEPTION_ASSERTX(sleepyface1.snooze () == i && sleepyface2.snooze () == i,
                              (boost::format("sleepyface1=%d, sleepyface2=%d, i=%d")
                              % sleepyface1.snooze () % sleepyface2.snooze () % i));

            // should wake up both
            bedroom->wakeup();
        }

        EXCEPTION_ASSERT(sleepyface1.isFinished ());
        EXCEPTION_ASSERT(sleepyface2.isFinished ());
        EXCEPTION_ASSERT_EQUALS(bedroom->sleepers(), 0);
    }

    // It should throw a BedroomClosed exception if someone tries to go to
    // sleep when the bedroom is closed.
    {
        Bedroom b;
        b.close ();
        EXPECT_EXCEPTION(BedroomClosed, b.getBed().sleep ());
    }

    // It should just sleep until the given timeout has elapsed
    {
        Bedroom b;
        Timer t;
        bool woken_up_by_wakeup_call = b.getBed ().sleep (2);

        // The thread was sleeping in its bed for 2 ms. So the elapsed 'Timer'
        // time should be more than 2 ms but less than 3 ms.
        EXCEPTION_ASSERT_LESS(t.elapsed (), 3e-3);
        EXCEPTION_ASSERT_LESS(2e-3, t.elapsed ());
        EXCEPTION_ASSERT(!woken_up_by_wakeup_call); // timeout
    }

    // It should just sleep until the given timeout has elapsed
    for (int i=0; i<40; i++)
    {
        //TaskTimer tt("It should just sleep until the given timeout has elapsed");
        Bedroom::ptr bedroom(new Bedroom);
        SleepingBeautyMock sbm(bedroom, 1);

        EXCEPTION_ASSERT_EQUALS(0,bedroom->sleepers ());
        sbm.start ();

        // wait for the thread to go to sleep and then timeout
        for (int j=0; j<100 && 0==sbm.timeoutCount (); j++)
            EXCEPTION_ASSERT( !sbm.wait (1) );

        // wakeup
        bedroom->wakeup();

        // the thread should finish soon
        EXCEPTION_ASSERT( sbm.wait (128) );
        EXCEPTION_ASSERT_EQUALS(0,bedroom->sleepers ());
    }

    // It should just sleep until the given timeout has elapsed
    for (int i=0; i<40; i++)
    {
        //TaskTimer tt("It should just sleep until the given timeout has elapsed");
        Bedroom::ptr bedroom(new Bedroom);
        SleepingBeautyMock sbm(bedroom, 1000);

        EXCEPTION_ASSERT_EQUALS(0,bedroom->sleepers ());
        sbm.start ();

        // wait for the thread to go to sleep
        for (int j=0; j<100 && 0==bedroom->sleepers (); j++)
            EXCEPTION_ASSERT( !sbm.wait (1) );
        EXCEPTION_ASSERT_EQUALS(1,bedroom->sleepers ());

        // wakeup
        bedroom->wakeup();

        // the thread should finish soon
        EXCEPTION_ASSERT( sbm.wait (128) );
        EXCEPTION_ASSERT_EQUALS(0,bedroom->sleepers ());

        // with such a long timeout the number of timeouts should be 0
        EXCEPTION_ASSERT_EQUALS(0,sbm.timeoutCount ());
    }
}