Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(666)

Side by Side Diff: base/task_scheduler/scheduler_worker_unittest.cc

Issue 2430633003: TaskScheduler: Record TaskScheduler.NumTasksBeforeDetach.* from OnDetach(). (Closed)
Patch Set: CR gab #3 rebase Created 4 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2016 The Chromium Authors. All rights reserved. 1 // Copyright 2016 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "base/task_scheduler/scheduler_worker.h" 5 #include "base/task_scheduler/scheduler_worker.h"
6 6
7 #include <stddef.h> 7 #include <stddef.h>
8 8
9 #include <memory> 9 #include <memory>
10 #include <vector> 10 #include <vector>
(...skipping 23 matching lines...) Expand all
34 namespace internal { 34 namespace internal {
35 namespace { 35 namespace {
36 36
37 const size_t kNumSequencesPerTest = 150; 37 const size_t kNumSequencesPerTest = 150;
38 38
39 class SchedulerWorkerDefaultDelegate : public SchedulerWorker::Delegate { 39 class SchedulerWorkerDefaultDelegate : public SchedulerWorker::Delegate {
40 public: 40 public:
41 SchedulerWorkerDefaultDelegate() = default; 41 SchedulerWorkerDefaultDelegate() = default;
42 42
43 // SchedulerWorker::Delegate: 43 // SchedulerWorker::Delegate:
44 void OnMainEntry(SchedulerWorker* worker, 44 void OnMainEntry(SchedulerWorker* worker) override {}
45 const TimeDelta& detach_duration) override {}
46 scoped_refptr<Sequence> GetWork(SchedulerWorker* worker) override { 45 scoped_refptr<Sequence> GetWork(SchedulerWorker* worker) override {
47 return nullptr; 46 return nullptr;
48 } 47 }
49 void DidRunTaskWithPriority(TaskPriority task_priority, 48 void DidRunTaskWithPriority(TaskPriority task_priority,
50 const TimeDelta& task_latency) override { 49 const TimeDelta& task_latency) override {
51 ADD_FAILURE() << "Unexpected call to DidRunTaskWithPriority()"; 50 ADD_FAILURE() << "Unexpected call to DidRunTaskWithPriority()";
52 } 51 }
53 void ReEnqueueSequence(scoped_refptr<Sequence> sequence) override { 52 void ReEnqueueSequence(scoped_refptr<Sequence> sequence) override {
54 ADD_FAILURE() << "Unexpected call to ReEnqueueSequence()"; 53 ADD_FAILURE() << "Unexpected call to ReEnqueueSequence()";
55 } 54 }
56 TimeDelta GetSleepTimeout() override { return TimeDelta::Max(); } 55 TimeDelta GetSleepTimeout() override { return TimeDelta::Max(); }
57 bool CanDetach(SchedulerWorker* worker) override { return false; } 56 bool CanDetach(SchedulerWorker* worker) override { return false; }
57 void OnDetach() override { ADD_FAILURE() << "Unexpected call to OnDetach()"; }
58 58
59 private: 59 private:
60 DISALLOW_COPY_AND_ASSIGN(SchedulerWorkerDefaultDelegate); 60 DISALLOW_COPY_AND_ASSIGN(SchedulerWorkerDefaultDelegate);
61 }; 61 };
62 62
63 // The test parameter is the number of Tasks per Sequence returned by GetWork(). 63 // The test parameter is the number of Tasks per Sequence returned by GetWork().
64 class TaskSchedulerWorkerTest : public testing::TestWithParam<size_t> { 64 class TaskSchedulerWorkerTest : public testing::TestWithParam<size_t> {
65 protected: 65 protected:
66 TaskSchedulerWorkerTest() 66 TaskSchedulerWorkerTest()
67 : main_entry_called_(WaitableEvent::ResetPolicy::MANUAL, 67 : main_entry_called_(WaitableEvent::ResetPolicy::MANUAL,
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after
124 class TestSchedulerWorkerDelegate : public SchedulerWorkerDefaultDelegate { 124 class TestSchedulerWorkerDelegate : public SchedulerWorkerDefaultDelegate {
125 public: 125 public:
126 TestSchedulerWorkerDelegate(TaskSchedulerWorkerTest* outer) 126 TestSchedulerWorkerDelegate(TaskSchedulerWorkerTest* outer)
127 : outer_(outer) {} 127 : outer_(outer) {}
128 128
129 ~TestSchedulerWorkerDelegate() override { 129 ~TestSchedulerWorkerDelegate() override {
130 EXPECT_FALSE(IsCallToDidRunTaskWithPriorityExpected()); 130 EXPECT_FALSE(IsCallToDidRunTaskWithPriorityExpected());
131 } 131 }
132 132
133 // SchedulerWorker::Delegate: 133 // SchedulerWorker::Delegate:
134 void OnMainEntry(SchedulerWorker* worker, 134 void OnMainEntry(SchedulerWorker* worker) override {
135 const TimeDelta& detach_duration) override {
136 outer_->worker_set_.Wait(); 135 outer_->worker_set_.Wait();
137 EXPECT_EQ(outer_->worker_.get(), worker); 136 EXPECT_EQ(outer_->worker_.get(), worker);
138 EXPECT_FALSE(IsCallToDidRunTaskWithPriorityExpected()); 137 EXPECT_FALSE(IsCallToDidRunTaskWithPriorityExpected());
139 138
140 // Without synchronization, OnMainEntry() could be called twice without 139 // Without synchronization, OnMainEntry() could be called twice without
141 // generating an error. 140 // generating an error.
142 AutoSchedulerLock auto_lock(outer_->lock_); 141 AutoSchedulerLock auto_lock(outer_->lock_);
143 EXPECT_FALSE(outer_->main_entry_called_.IsSignaled()); 142 EXPECT_FALSE(outer_->main_entry_called_.IsSignaled());
144 outer_->main_entry_called_.Signal(); 143 outer_->main_entry_called_.Signal();
145 } 144 }
(...skipping 210 matching lines...) Expand 10 before | Expand all | Expand 10 after
356 355
357 namespace { 356 namespace {
358 357
359 class ControllableDetachDelegate : public SchedulerWorkerDefaultDelegate { 358 class ControllableDetachDelegate : public SchedulerWorkerDefaultDelegate {
360 public: 359 public:
361 ControllableDetachDelegate(TaskTracker* task_tracker) 360 ControllableDetachDelegate(TaskTracker* task_tracker)
362 : task_tracker_(task_tracker), 361 : task_tracker_(task_tracker),
363 work_processed_(WaitableEvent::ResetPolicy::MANUAL, 362 work_processed_(WaitableEvent::ResetPolicy::MANUAL,
364 WaitableEvent::InitialState::NOT_SIGNALED), 363 WaitableEvent::InitialState::NOT_SIGNALED),
365 detach_requested_(WaitableEvent::ResetPolicy::MANUAL, 364 detach_requested_(WaitableEvent::ResetPolicy::MANUAL,
366 WaitableEvent::InitialState::NOT_SIGNALED) { 365 WaitableEvent::InitialState::NOT_SIGNALED),
366 detached_(WaitableEvent::ResetPolicy::MANUAL,
367 WaitableEvent::InitialState::NOT_SIGNALED) {
367 EXPECT_TRUE(task_tracker_); 368 EXPECT_TRUE(task_tracker_);
368 } 369 }
369 370
370 ~ControllableDetachDelegate() override = default; 371 ~ControllableDetachDelegate() override = default;
371 372
372 // SchedulerWorker::Delegate: 373 // SchedulerWorker::Delegate:
373 MOCK_METHOD2(OnMainEntry, 374 MOCK_METHOD1(OnMainEntry, void(SchedulerWorker* worker));
374 void(SchedulerWorker* worker, const TimeDelta& detach_duration));
375 375
376 scoped_refptr<Sequence> GetWork(SchedulerWorker* worker) 376 scoped_refptr<Sequence> GetWork(SchedulerWorker* worker)
377 override { 377 override {
378 // Sends one item of work to signal |work_processed_|. On subsequent calls, 378 // Sends one item of work to signal |work_processed_|. On subsequent calls,
379 // sends nullptr to indicate there's no more work to be done. 379 // sends nullptr to indicate there's no more work to be done.
380 if (work_requested_) 380 if (work_requested_)
381 return nullptr; 381 return nullptr;
382 382
383 work_requested_ = true; 383 work_requested_ = true;
384 scoped_refptr<Sequence> sequence(new Sequence); 384 scoped_refptr<Sequence> sequence(new Sequence);
385 std::unique_ptr<Task> task(new Task( 385 std::unique_ptr<Task> task(new Task(
386 FROM_HERE, Bind(&WaitableEvent::Signal, Unretained(&work_processed_)), 386 FROM_HERE, Bind(&WaitableEvent::Signal, Unretained(&work_processed_)),
387 TaskTraits(), TimeDelta())); 387 TaskTraits(), TimeDelta()));
388 EXPECT_TRUE(task_tracker_->WillPostTask(task.get())); 388 EXPECT_TRUE(task_tracker_->WillPostTask(task.get()));
389 sequence->PushTask(std::move(task)); 389 sequence->PushTask(std::move(task));
390 return sequence; 390 return sequence;
391 } 391 }
392 392
393 void DidRunTaskWithPriority(TaskPriority task, 393 void DidRunTaskWithPriority(TaskPriority task,
394 const TimeDelta& task_latency) override {} 394 const TimeDelta& task_latency) override {}
395 395
396 bool CanDetach(SchedulerWorker* worker) override { 396 bool CanDetach(SchedulerWorker* worker) override {
397 detach_requested_.Signal(); 397 detach_requested_.Signal();
398 return can_detach_; 398 return can_detach_;
399 } 399 }
400 400
401 void OnDetach() override {
402 EXPECT_TRUE(can_detach_);
403 EXPECT_TRUE(detach_requested_.IsSignaled());
404 detached_.Signal();
405 }
406
401 void WaitForWorkToRun() { 407 void WaitForWorkToRun() {
402 work_processed_.Wait(); 408 work_processed_.Wait();
403 } 409 }
404 410
405 void WaitForDetachRequest() { 411 void WaitForDetachRequest() {
406 detach_requested_.Wait(); 412 detach_requested_.Wait();
407 } 413 }
408 414
415 void WaitForDetach() { detached_.Wait(); }
416
409 void ResetState() { 417 void ResetState() {
410 work_requested_ = false; 418 work_requested_ = false;
411 work_processed_.Reset(); 419 work_processed_.Reset();
412 detach_requested_.Reset(); 420 detach_requested_.Reset();
413 } 421 }
414 422
415 void set_can_detach(bool can_detach) { can_detach_ = can_detach; } 423 void set_can_detach(bool can_detach) { can_detach_ = can_detach; }
416 424
417 private: 425 private:
418 TaskTracker* const task_tracker_; 426 TaskTracker* const task_tracker_;
419 bool work_requested_ = false; 427 bool work_requested_ = false;
420 bool can_detach_ = false; 428 bool can_detach_ = false;
421 WaitableEvent work_processed_; 429 WaitableEvent work_processed_;
422 WaitableEvent detach_requested_; 430 WaitableEvent detach_requested_;
431 WaitableEvent detached_;
423 432
424 DISALLOW_COPY_AND_ASSIGN(ControllableDetachDelegate); 433 DISALLOW_COPY_AND_ASSIGN(ControllableDetachDelegate);
425 }; 434 };
426 435
427 } // namespace 436 } // namespace
428 437
429 TEST(TaskSchedulerWorkerTest, WorkerDetaches) { 438 TEST(TaskSchedulerWorkerTest, WorkerDetaches) {
430 TaskTracker task_tracker; 439 TaskTracker task_tracker;
431 // Will be owned by SchedulerWorker. 440 // Will be owned by SchedulerWorker.
432 ControllableDetachDelegate* delegate = 441 ControllableDetachDelegate* delegate =
433 new StrictMock<ControllableDetachDelegate>(&task_tracker); 442 new StrictMock<ControllableDetachDelegate>(&task_tracker);
434 delegate->set_can_detach(true); 443 delegate->set_can_detach(true);
435 EXPECT_CALL(*delegate, OnMainEntry(_, TimeDelta::Max())); 444 EXPECT_CALL(*delegate, OnMainEntry(_));
436 std::unique_ptr<SchedulerWorker> worker = 445 std::unique_ptr<SchedulerWorker> worker =
437 SchedulerWorker::Create( 446 SchedulerWorker::Create(
438 ThreadPriority::NORMAL, WrapUnique(delegate), &task_tracker, 447 ThreadPriority::NORMAL, WrapUnique(delegate), &task_tracker,
439 SchedulerWorker::InitialState::ALIVE); 448 SchedulerWorker::InitialState::ALIVE);
440 worker->WakeUp(); 449 worker->WakeUp();
441 delegate->WaitForWorkToRun(); 450 delegate->WaitForWorkToRun();
442 Mock::VerifyAndClear(delegate); 451 Mock::VerifyAndClear(delegate);
443 delegate->WaitForDetachRequest(); 452 delegate->WaitForDetachRequest();
444 // Sleep to give a chance for the detach to happen. A yield is too short. 453 delegate->WaitForDetach();
445 PlatformThread::Sleep(TimeDelta::FromMilliseconds(50));
446 ASSERT_FALSE(worker->ThreadAliveForTesting()); 454 ASSERT_FALSE(worker->ThreadAliveForTesting());
447 } 455 }
448 456
449 TEST(TaskSchedulerWorkerTest, WorkerDetachesAndWakes) { 457 TEST(TaskSchedulerWorkerTest, WorkerDetachesAndWakes) {
450 TaskTracker task_tracker; 458 TaskTracker task_tracker;
451 // Will be owned by SchedulerWorker. 459 // Will be owned by SchedulerWorker.
452 ControllableDetachDelegate* delegate = 460 ControllableDetachDelegate* delegate =
453 new StrictMock<ControllableDetachDelegate>(&task_tracker); 461 new StrictMock<ControllableDetachDelegate>(&task_tracker);
454 delegate->set_can_detach(true); 462 delegate->set_can_detach(true);
455 EXPECT_CALL(*delegate, OnMainEntry(_, TimeDelta::Max())); 463 EXPECT_CALL(*delegate, OnMainEntry(_));
456 std::unique_ptr<SchedulerWorker> worker = 464 std::unique_ptr<SchedulerWorker> worker =
457 SchedulerWorker::Create( 465 SchedulerWorker::Create(
458 ThreadPriority::NORMAL, WrapUnique(delegate), &task_tracker, 466 ThreadPriority::NORMAL, WrapUnique(delegate), &task_tracker,
459 SchedulerWorker::InitialState::ALIVE); 467 SchedulerWorker::InitialState::ALIVE);
460 worker->WakeUp(); 468 worker->WakeUp();
461 delegate->WaitForWorkToRun(); 469 delegate->WaitForWorkToRun();
462 Mock::VerifyAndClear(delegate); 470 Mock::VerifyAndClear(delegate);
463 delegate->WaitForDetachRequest(); 471 delegate->WaitForDetachRequest();
464 // Sleep to give a chance for the detach to happen. A yield is too short. 472 delegate->WaitForDetach();
465 PlatformThread::Sleep(TimeDelta::FromMilliseconds(50));
466 ASSERT_FALSE(worker->ThreadAliveForTesting()); 473 ASSERT_FALSE(worker->ThreadAliveForTesting());
467 474
468 delegate->ResetState(); 475 delegate->ResetState();
469 delegate->set_can_detach(false); 476 delegate->set_can_detach(false);
470 // When SchedulerWorker recreates its thread, expect OnMainEntry() to be 477 // Expect OnMainEntry() to be called when SchedulerWorker recreates its
471 // called with a detach duration which is not TimeDelta::Max(). 478 // thread.
472 EXPECT_CALL(*delegate, OnMainEntry(worker.get(), Ne(TimeDelta::Max()))); 479 EXPECT_CALL(*delegate, OnMainEntry(worker.get()));
473 worker->WakeUp(); 480 worker->WakeUp();
474 delegate->WaitForWorkToRun(); 481 delegate->WaitForWorkToRun();
475 Mock::VerifyAndClear(delegate); 482 Mock::VerifyAndClear(delegate);
476 delegate->WaitForDetachRequest(); 483 delegate->WaitForDetachRequest();
477 PlatformThread::Sleep(TimeDelta::FromMilliseconds(50)); 484 delegate->WaitForDetach();
478 ASSERT_TRUE(worker->ThreadAliveForTesting()); 485 ASSERT_TRUE(worker->ThreadAliveForTesting());
479 worker->JoinForTesting(); 486 worker->JoinForTesting();
480 } 487 }
481 488
482 TEST(TaskSchedulerWorkerTest, CreateDetached) { 489 TEST(TaskSchedulerWorkerTest, CreateDetached) {
483 TaskTracker task_tracker; 490 TaskTracker task_tracker;
484 // Will be owned by SchedulerWorker. 491 // Will be owned by SchedulerWorker.
485 ControllableDetachDelegate* delegate = 492 ControllableDetachDelegate* delegate =
486 new StrictMock<ControllableDetachDelegate>(&task_tracker); 493 new StrictMock<ControllableDetachDelegate>(&task_tracker);
487 std::unique_ptr<SchedulerWorker> worker = 494 std::unique_ptr<SchedulerWorker> worker =
488 SchedulerWorker::Create( 495 SchedulerWorker::Create(
489 ThreadPriority::NORMAL, WrapUnique(delegate), &task_tracker, 496 ThreadPriority::NORMAL, WrapUnique(delegate), &task_tracker,
490 SchedulerWorker::InitialState::DETACHED); 497 SchedulerWorker::InitialState::DETACHED);
491 ASSERT_FALSE(worker->ThreadAliveForTesting()); 498 ASSERT_FALSE(worker->ThreadAliveForTesting());
492 EXPECT_CALL(*delegate, OnMainEntry(worker.get(), TimeDelta::Max())); 499 EXPECT_CALL(*delegate, OnMainEntry(worker.get()));
493 worker->WakeUp(); 500 worker->WakeUp();
494 delegate->WaitForWorkToRun(); 501 delegate->WaitForWorkToRun();
495 Mock::VerifyAndClear(delegate); 502 Mock::VerifyAndClear(delegate);
496 delegate->WaitForDetachRequest(); 503 delegate->WaitForDetachRequest();
497 ASSERT_TRUE(worker->ThreadAliveForTesting()); 504 ASSERT_TRUE(worker->ThreadAliveForTesting());
498 worker->JoinForTesting(); 505 worker->JoinForTesting();
499 } 506 }
500 507
501 namespace { 508 namespace {
502 509
503 class ExpectThreadPriorityDelegate : public SchedulerWorkerDefaultDelegate { 510 class ExpectThreadPriorityDelegate : public SchedulerWorkerDefaultDelegate {
504 public: 511 public:
505 ExpectThreadPriorityDelegate() 512 ExpectThreadPriorityDelegate()
506 : priority_verified_in_get_work_event_( 513 : priority_verified_in_get_work_event_(
507 WaitableEvent::ResetPolicy::AUTOMATIC, 514 WaitableEvent::ResetPolicy::AUTOMATIC,
508 WaitableEvent::InitialState::NOT_SIGNALED), 515 WaitableEvent::InitialState::NOT_SIGNALED),
509 expected_thread_priority_(ThreadPriority::BACKGROUND) {} 516 expected_thread_priority_(ThreadPriority::BACKGROUND) {}
510 517
511 void SetExpectedThreadPriority(ThreadPriority expected_thread_priority) { 518 void SetExpectedThreadPriority(ThreadPriority expected_thread_priority) {
512 expected_thread_priority_ = expected_thread_priority; 519 expected_thread_priority_ = expected_thread_priority;
513 } 520 }
514 521
515 void WaitForPriorityVerifiedInGetWork() { 522 void WaitForPriorityVerifiedInGetWork() {
516 priority_verified_in_get_work_event_.Wait(); 523 priority_verified_in_get_work_event_.Wait();
517 } 524 }
518 525
519 // SchedulerWorker::Delegate: 526 // SchedulerWorker::Delegate:
520 void OnMainEntry(SchedulerWorker* worker, 527 void OnMainEntry(SchedulerWorker* worker) override { VerifyThreadPriority(); }
521 const TimeDelta& detach_duration) override {
522 VerifyThreadPriority();
523 }
524 scoped_refptr<Sequence> GetWork(SchedulerWorker* worker) override { 528 scoped_refptr<Sequence> GetWork(SchedulerWorker* worker) override {
525 VerifyThreadPriority(); 529 VerifyThreadPriority();
526 priority_verified_in_get_work_event_.Signal(); 530 priority_verified_in_get_work_event_.Signal();
527 return nullptr; 531 return nullptr;
528 } 532 }
529 533
530 private: 534 private:
531 void VerifyThreadPriority() { 535 void VerifyThreadPriority() {
532 AutoSchedulerLock auto_lock(expected_thread_priority_lock_); 536 AutoSchedulerLock auto_lock(expected_thread_priority_lock_);
533 EXPECT_EQ(expected_thread_priority_, 537 EXPECT_EQ(expected_thread_priority_,
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after
597 // OnMainEntry() and GetWork() are called. 601 // OnMainEntry() and GetWork() are called.
598 worker->WakeUp(); 602 worker->WakeUp();
599 delegate_raw->WaitForPriorityVerifiedInGetWork(); 603 delegate_raw->WaitForPriorityVerifiedInGetWork();
600 604
601 worker->JoinForTesting(); 605 worker->JoinForTesting();
602 } 606 }
603 607
604 } // namespace 608 } // namespace
605 } // namespace internal 609 } // namespace internal
606 } // namespace base 610 } // namespace base
OLDNEW
« no previous file with comments | « base/task_scheduler/scheduler_worker_stack_unittest.cc ('k') | tools/metrics/histograms/histograms.xml » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698