int main() { EXPECT_EXCEPTION( quickbook::post_process("</thing>"), "Succeeded with unbalanced tag"); EXPECT_EXCEPTION( quickbook::post_process("<"), "Succeeded with badly formed tag"); return boost::report_errors(); }
void vmxon_ut::test_stop_vmxoff_check_failure() { MockRepository mocks; auto in = bfn::mock_shared<intrinsics_intel_x64>(mocks); auto intrinsics = in.get(); auto l_mm = bfn::mock_shared<memory_manager>(mocks); mm = l_mm.get(); // execute_vmxoff mocks.OnCall(intrinsics, intrinsics_intel_x64::vmxoff).Return(true); // disable_vmx_operation Call &cr4_0 = mocks.ExpectCall(intrinsics, intrinsics_intel_x64::read_cr4).Return(0); mocks.OnCall(intrinsics, intrinsics_intel_x64::write_cr4).Do(stubbed_write_cr4); // is_vmx_operation_enabled mocks.ExpectCall(intrinsics, intrinsics_intel_x64::read_cr4).After(cr4_0).Return(CR4_VMXE_VMX_ENABLE_BIT); RUN_UNITTEST_WITH_MOCKS(mocks, [&] { vmxon_intel_x64 vmxon(in); EXPECT_EXCEPTION(vmxon.stop(), bfn::vmxon_failure_error); }); }
void vmxon_ut::test_start_check_vmx_capabilities_msr_addr_width_failure() { MockRepository mocks; auto in = bfn::mock_shared<intrinsics_intel_x64>(mocks); auto intrinsics = in.get(); auto l_mm = bfn::mock_shared<memory_manager>(mocks); mm = l_mm.get(); // is_vmx_operation_enabled mocks.ExpectCall(intrinsics, intrinsics_intel_x64::read_cr4).Return(0); // check_cpuid_vmx_supported mocks.OnCall(intrinsics, intrinsics_intel_x64::cpuid_ecx).With(1).Return((1 << 5)); // check_vmx_capabilities_msr auto basic = ((1ULL << 55) | ((~(1ULL << 48)))); mocks.OnCall(intrinsics, intrinsics_intel_x64::read_msr).With(IA32_VMX_BASIC_MSR).Return(basic); RUN_UNITTEST_WITH_MOCKS(mocks, [&] { vmxon_intel_x64 vmxon(in); EXPECT_EXCEPTION(vmxon.start(), bfn::vmxon_capabilities_failure_error); }); }
void vmxon_ut::test_start_check_ia32_feature_control_msr() { MockRepository mocks; auto in = bfn::mock_shared<intrinsics_intel_x64>(mocks); auto intrinsics = in.get(); auto l_mm = bfn::mock_shared<memory_manager>(mocks); mm = l_mm.get(); // is_vmx_operation_enabled mocks.OnCall(intrinsics, intrinsics_intel_x64::read_cr4).Return(0); // check_cpuid_vmx_supported mocks.OnCall(intrinsics, intrinsics_intel_x64::cpuid_ecx).With(1).Return((1 << 5)); // check_vmx_capabilities_msr auto basic = ((1ULL << 55) | ((6ULL << 50) & (~(1ULL << 48)))); mocks.OnCall(intrinsics, intrinsics_intel_x64::read_msr).With(IA32_VMX_BASIC_MSR).Return(basic); // check_ia32_vmx_cr0_fixed_msr mocks.OnCall(intrinsics, intrinsics_intel_x64::read_cr0).Return((0xffffffff)); mocks.OnCall(intrinsics, intrinsics_intel_x64::read_msr).With(IA32_VMX_CR0_FIXED0_MSR).Return(0); mocks.OnCall(intrinsics, intrinsics_intel_x64::read_msr).With(IA32_VMX_CR0_FIXED1_MSR).Return(0xffffffff); // check_ia32_feature_control_msr mocks.OnCall(intrinsics, intrinsics_intel_x64::read_msr).With(IA32_FEATURE_CONTROL_MSR).Return(0); RUN_UNITTEST_WITH_MOCKS(mocks, [&] { vmxon_intel_x64 vmxon(in); EXPECT_EXCEPTION(vmxon.start(), bfn::vmxon_failure_error); }); }
void PrettifySegfault:: test() { // Skip test if running through gdb if (DetectGdb::is_running_through_gdb() || DetectGdb::was_started_through_gdb ()) { TaskInfo("Running through debugger, skipping PrettifySegfault test"); return; } // It should attempt to capture any null-pointer exception (SIGSEGV and // SIGILL) in the program, log a backtrace, and then throw a regular C++ // exception from the location causing the signal. { enable_signal_print = false; // In order for the EXPECT_EXCEPTION macro to catch the exception the call // must not be inlined as the function causing the signal will first return and // then throw the exception. #ifdef _DEBUG EXPECT_EXCEPTION(segfault_sigill_exception, throw_catchable_segfault_exception()); EXPECT_EXCEPTION(segfault_sigill_exception, throw_catchable_segfault_exception2()); EXPECT_EXCEPTION(segfault_sigill_exception, throw_catchable_segfault_exception3()); EXPECT_EXCEPTION(segfault_sigill_exception, throw_catchable_segfault_exception4()); EXPECT_EXCEPTION(segfault_sigill_exception, throw_catchable_segfault_exception5()); #else EXPECT_EXCEPTION(segfault_sigill_exception, throw_catchable_segfault_exception_noinline()); EXPECT_EXCEPTION(segfault_sigill_exception, throw_catchable_segfault_exception2_noinline()); EXPECT_EXCEPTION(segfault_sigill_exception, throw_catchable_segfault_exception3_noinline()); EXPECT_EXCEPTION(segfault_sigill_exception, throw_catchable_segfault_exception4_noinline()); EXPECT_EXCEPTION(segfault_sigill_exception, throw_catchable_segfault_exception5_noinline()); #endif enable_signal_print = true; } // It returns immediately from the signalling function without unwinding // that scope and thus break the RAII assumption that a destructor will // always be called (does not apply in windows) { EXCEPTION_ASSERT(breaks_RAII_assumptions::constructor_was_called); #ifndef _MSC_VER EXCEPTION_ASSERT(!breaks_RAII_assumptions::destructor_was_called); breaks_RAII_assumptions(); // This calls the destructor #endif EXCEPTION_ASSERT(breaks_RAII_assumptions::destructor_was_called); } }
void vmxon_ut::test_start_check_ia32_vmx_cr4_fixed0_msr_failure() { MockRepository mocks; auto in = bfn::mock_shared<intrinsics_intel_x64>(mocks); auto intrinsics = in.get(); auto l_mm = bfn::mock_shared<memory_manager>(mocks); mm = l_mm.get(); // is_vmx_operation_enabled Call &cr4_0 = mocks.ExpectCall(intrinsics, intrinsics_intel_x64::read_cr4).Return(0); // check_cpuid_vmx_supported mocks.OnCall(intrinsics, intrinsics_intel_x64::cpuid_ecx).With(1).Return((1 << 5)); // check_vmx_capabilities_msr auto basic = ((1ULL << 55) | ((6ULL << 50) & (~(1ULL << 48)))); mocks.OnCall(intrinsics, intrinsics_intel_x64::read_msr).With(IA32_VMX_BASIC_MSR).Return(basic); // check_ia32_vmx_cr0_fixed_msr mocks.OnCall(intrinsics, intrinsics_intel_x64::read_cr0).Return((0xffffffff)); mocks.OnCall(intrinsics, intrinsics_intel_x64::read_msr).With(IA32_VMX_CR0_FIXED0_MSR).Return(0); mocks.OnCall(intrinsics, intrinsics_intel_x64::read_msr).With(IA32_VMX_CR0_FIXED1_MSR).Return(0xffffffff); // check_ia32_feature_control_msr mocks.OnCall(intrinsics, intrinsics_intel_x64::read_msr).With(IA32_FEATURE_CONTROL_MSR).Return((1 << 0)); // check_v8086_disabled mocks.OnCall(intrinsics, intrinsics_intel_x64::read_rflags).Return(~RFLAGS_VM_VIRTUAL_8086_MODE); // create_vmxon_region mocks.OnCallFunc(memory_manager::instance).Do(fake_memory_manager); mocks.OnCall(mm, memory_manager::malloc_aligned).Do(stubbed_malloc_aligned); mocks.OnCall(mm, memory_manager::virt_to_phys).Return((void *)0xDEADBEEFDEAF1000); // enable_vmx_operation Call &cr4_1 = mocks.ExpectCall(intrinsics, intrinsics_intel_x64::read_cr4).After(cr4_0).Return(0); mocks.OnCall(intrinsics, intrinsics_intel_x64::write_cr4).Do(stubbed_write_cr4); // is_vmx_operation_enabled Call &cr4_2 = mocks.ExpectCall(intrinsics, intrinsics_intel_x64::read_cr4).After(cr4_1).Return(CR4_VMXE_VMX_ENABLE_BIT); // check_ia32_vmx_cr4_fixed_msr *** mocks.ExpectCall(intrinsics, intrinsics_intel_x64::read_cr4).After(cr4_2).Return(0xDEADBEEF); mocks.OnCall(intrinsics, intrinsics_intel_x64::read_msr).With(IA32_VMX_CR4_FIXED0_MSR).Return(0xFEEDBEEF); mocks.OnCall(intrinsics, intrinsics_intel_x64::read_msr).With(IA32_VMX_CR4_FIXED1_MSR).Return(0xDEADBEEF); // Handle rollbacks mocks.OnCall(intrinsics, intrinsics_intel_x64::read_cr4).Return(0); mocks.OnCall(intrinsics, intrinsics_intel_x64::vmxoff).Return(true); mocks.OnCall(intrinsics, intrinsics_intel_x64::write_cr4).Do(stubbed_write_cr4); RUN_UNITTEST_WITH_MOCKS(mocks, [&] { vmxon_intel_x64 vmxon(in); EXPECT_EXCEPTION(vmxon.start(), bfn::vmxon_fixed_msr_failure_error); }); }
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. { } }
void vmxon_ut::test_stop_vmxoff_failure() { MockRepository mocks; auto in = bfn::mock_shared<intrinsics_intel_x64>(mocks); auto intrinsics = in.get(); auto l_mm = bfn::mock_shared<memory_manager>(mocks); mm = l_mm.get(); // execute_vmxoff mocks.OnCall(intrinsics, intrinsics_intel_x64::vmxoff).Return(false); RUN_UNITTEST_WITH_MOCKS(mocks, [&] { vmxon_intel_x64 vmxon(in); vmxon.m_vmxon_enabled = true; EXPECT_EXCEPTION(vmxon.stop(), bfn::vmxon_failure_error); }); }
void vmxon_ut::test_start_vmxon_already_enabled_failure() { MockRepository mocks; auto in = bfn::mock_shared<intrinsics_intel_x64>(mocks); auto intrinsics = in.get(); auto l_mm = bfn::mock_shared<memory_manager>(mocks); mm = l_mm.get(); // is_vmx_operation_enabled mocks.ExpectCall(intrinsics, intrinsics_intel_x64::read_cr4).Return(CR4_VMXE_VMX_ENABLE_BIT); RUN_UNITTEST_WITH_MOCKS(mocks, [&] { vmxon_intel_x64 vmxon(in); EXPECT_EXCEPTION(vmxon.start(), bfn::vmxon_failure_error); }); }
void vmxon_ut::test_start_check_cpuid_vmx_supported_failure() { MockRepository mocks; auto in = bfn::mock_shared<intrinsics_intel_x64>(mocks); auto intrinsics = in.get(); auto l_mm = bfn::mock_shared<memory_manager>(mocks); mm = l_mm.get(); // is_vmx_operation_enabled mocks.ExpectCall(intrinsics, intrinsics_intel_x64::read_cr4).Return(0); // check_cpuid_vmx_supported mocks.OnCall(intrinsics, intrinsics_intel_x64::cpuid_ecx).With(1).Return(~(1 << 5)); RUN_UNITTEST_WITH_MOCKS(mocks, [&] { vmxon_intel_x64 vmxon(in); EXPECT_EXCEPTION(vmxon.start(), bfn::vmxon_failure_error); }); }
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); } }
/* * A shared method to test proper deactivation during IdleTracker_Shutdown() * or a direct call to IdleTracker_DeactivateProcess() during regular * deactivation of an active process when a proper cleanup was not possible * (e.g., a transaction is in progress). */ static void CheckForDeactivationWithoutCleanup(void (*testFunc)(void)) { static EventVersion fakeCurrentVersion = 10; CurrentVersion = &fakeCurrentVersion; InitFakeSessionState(1 /* activeProcessCount */, CLEANUP_COUNTDOWN_BEFORE_RUNAWAY /* cleanupCountdown */, RunawayStatus_NotRunaway /* runawayStatus */, 1 /* pinCount */, 0 /* vmem */); EventVersion oldVersion = *CurrentVersion; /* Ensure we have a pending runaway event */ EventVersion fakeLatestRunawayVersion = *CurrentVersion - 1; latestRunawayVersion = &fakeLatestRunawayVersion; activationVersion = 0; deactivationVersion = 0; assert_true(*CurrentVersion != activationVersion); assert_true(*CurrentVersion != deactivationVersion); /* * Set to true as we want to verify that it gets set to false * once the testFunc() call returns */ isProcessActive = true; assert_true(MySessionState->activeProcessCount == 1); /* * Deactivation must call RunawayCleaner_StartCleanup before finishing deactivation * to check for cleanup requirement for any pending runaway event. The method is * supposed to throw an exception, but for this test we are mocking the function * without side effect. I.e., the function behaves as if a proper cleanup is not * possible */ will_be_called(RunawayCleaner_StartCleanup); #ifdef USE_ASSERT_CHECKING will_return(RunawayCleaner_IsCleanupInProgress, true); /* * Expecting an exception as we are indicating an ongoing cleanup * and yet returning to IdleTracker_DactivateProcess */ EXPECT_EXCEPTION(); #endif PG_TRY(); { testFunc(); #ifdef USE_ASSERT_CHECKING assert_false("Expected an assertion failure"); #endif } PG_CATCH(); { } PG_END_TRY(); assert_true(activationVersion == 0); assert_true(deactivationVersion == *CurrentVersion); assert_true(isProcessActive == false); assert_true(MySessionState->activeProcessCount == 0); }
/* * A shared method to test that the IdleTracker_DeactivateProcess ignores * deactivation for an already idle process when the proc_exit_inprogress * is set to true */ static void PreventDuplicateDeactivationDuringProcExit(void (*testFunc)(void)) { static EventVersion fakeCurrentVersion = 10; CurrentVersion = &fakeCurrentVersion; InitFakeSessionState(1 /* activeProcessCount */, CLEANUP_COUNTDOWN_BEFORE_RUNAWAY /* cleanupCountdown */, RunawayStatus_NotRunaway /* runawayStatus */, 1 /* pinCount */, 0 /* vmem */); EventVersion oldVersion = *CurrentVersion; /* Ensure we have a pending runaway event */ EventVersion fakeLatestRunawayVersion = *CurrentVersion - 1; latestRunawayVersion = &fakeLatestRunawayVersion; activationVersion = 0; deactivationVersion = 0; assert_true(*CurrentVersion != activationVersion); assert_true(*CurrentVersion != deactivationVersion); /* * Set to false to mark the process as deactivated */ isProcessActive = false; assert_true(MySessionState->activeProcessCount == 1); /* * Setting proc_exit_inprogress to true means we won't try to * deactivate an already idle process */ proc_exit_inprogress = true; /* Interrupts should be held off during proc_exit_inprogress*/ InterruptHoldoffCount = 1; /* Now the deactivation should succeed as we have held off interrupts */ testFunc(); InterruptHoldoffCount = 0; assert_true(activationVersion == deactivationVersion); assert_true(deactivationVersion != *CurrentVersion); assert_true(isProcessActive == false); /* We haven't reduced the activeProcessCount */ assert_true(MySessionState->activeProcessCount == 1); #ifdef USE_ASSERT_CHECKING /* * Now test that the testFunc fails assert if we try to deactivate an already * idle process during a normal execution (i.e., not proc_exit_inprogress) */ proc_exit_inprogress = false; EXPECT_EXCEPTION(); PG_TRY(); { testFunc(); assert_false("Expected assertion failure"); } PG_CATCH(); { } PG_END_TRY(); #endif }
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 ()); } }