// Copyright 2013 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #include "components/drive/job_queue.h" #include "testing/gtest/include/gtest/gtest.h" namespace drive { TEST(JobQueueTest, BasicJobQueueOperations) { const size_t kNumMaxConcurrentJobs = 3; const size_t kNumPriorityLevels = 2; const size_t kNumMaxBatchJob = 0; const size_t kMaxBatchSize = 0; enum {HIGH_PRIORITY, LOW_PRIORITY}; // Create a queue. Number of jobs are initially zero. JobQueue queue(kNumMaxConcurrentJobs, kNumPriorityLevels, kNumMaxBatchJob, kMaxBatchSize); EXPECT_EQ(0U, queue.GetNumberOfJobs()); // Push 4 jobs. queue.Push(101, LOW_PRIORITY, false, 0); queue.Push(102, HIGH_PRIORITY, false, 0); queue.Push(103, LOW_PRIORITY, false, 0); queue.Push(104, HIGH_PRIORITY, false, 0); // High priority jobs should be popped first. std::vector ids; queue.PopForRun(LOW_PRIORITY, &ids); ASSERT_EQ(1u, ids.size()); EXPECT_EQ(102, ids[0]); queue.PopForRun(LOW_PRIORITY, &ids); ASSERT_EQ(1u, ids.size()); EXPECT_EQ(104, ids[0]); // Then low priority jobs follow. queue.PopForRun(LOW_PRIORITY, &ids); ASSERT_EQ(1u, ids.size()); EXPECT_EQ(101, ids[0]); // The queue allows at most 3 parallel runs. So returns false here. queue.PopForRun(LOW_PRIORITY, &ids); ASSERT_EQ(0u, ids.size()); // No jobs finished yet, so the job count is four. EXPECT_EQ(4U, queue.GetNumberOfJobs()); // Mark one job as finished. queue.MarkFinished(104); EXPECT_EQ(3U, queue.GetNumberOfJobs()); // Then the next jobs can be popped. queue.PopForRun(LOW_PRIORITY, &ids); ASSERT_EQ(1u, ids.size()); EXPECT_EQ(103, ids[0]); // Push 1 more job. queue.Push(105, LOW_PRIORITY, false, 0); // Finish all 3 running jobs. queue.MarkFinished(101); queue.MarkFinished(102); queue.MarkFinished(103); EXPECT_EQ(1U, queue.GetNumberOfJobs()); // The remaining jobs is of low priority, so under HIGH_PRIORITY context, it // cannot be popped for running. queue.PopForRun(HIGH_PRIORITY, &ids); ASSERT_EQ(0u, ids.size()); // Under the low priority context, it is fine. queue.PopForRun(LOW_PRIORITY, &ids); ASSERT_EQ(1u, ids.size()); EXPECT_EQ(105, ids[0]); } TEST(JobQueueTest, JobQueueRemove) { const size_t kNumMaxConcurrentJobs = 3; const size_t kNumPriorityLevels = 2; const size_t kNumMaxBatchJob = 0; const size_t kMaxBatchSize = 0; enum {HIGH_PRIORITY, LOW_PRIORITY}; // Create a queue. Number of jobs are initially zero. JobQueue queue(kNumMaxConcurrentJobs, kNumPriorityLevels, kNumMaxBatchJob, kMaxBatchSize); EXPECT_EQ(0U, queue.GetNumberOfJobs()); // Push 4 jobs. queue.Push(101, LOW_PRIORITY, false, 0); queue.Push(102, HIGH_PRIORITY, false, 0); queue.Push(103, LOW_PRIORITY, false, 0); queue.Push(104, HIGH_PRIORITY, false, 0); EXPECT_EQ(4U, queue.GetNumberOfJobs()); // Remove 2. queue.Remove(101); queue.Remove(104); EXPECT_EQ(2U, queue.GetNumberOfJobs()); // Pop the 2 jobs. std::vector ids; queue.PopForRun(LOW_PRIORITY, &ids); ASSERT_EQ(1u, ids.size()); EXPECT_EQ(102, ids[0]); queue.PopForRun(LOW_PRIORITY, &ids); ASSERT_EQ(1u, ids.size()); EXPECT_EQ(103, ids[0]); queue.MarkFinished(102); queue.MarkFinished(103); // 0 job left. EXPECT_EQ(0U, queue.GetNumberOfJobs()); queue.PopForRun(LOW_PRIORITY, &ids); ASSERT_EQ(0u, ids.size()); } TEST(JobQueueTest, BatchRequest) { const size_t kNumMaxConcurrentJobs = 1; const size_t kNumPriorityLevels = 2; const size_t kNumMaxBatchJob = 100; const size_t kMaxBatchSize = 5; enum { HIGH_PRIORITY, LOW_PRIORITY }; // Create a queue. Number of jobs are initially zero. JobQueue queue(kNumMaxConcurrentJobs, kNumPriorityLevels, kNumMaxBatchJob, kMaxBatchSize); EXPECT_EQ(0U, queue.GetNumberOfJobs()); // Push 6 jobs. queue.Push(101, LOW_PRIORITY, true, 1); queue.Push(102, HIGH_PRIORITY, true, 1); queue.Push(103, LOW_PRIORITY, false, 1); queue.Push(104, HIGH_PRIORITY, true, 1); queue.Push(105, LOW_PRIORITY, true, 1); queue.Push(106, HIGH_PRIORITY, true, 10); EXPECT_EQ(6U, queue.GetNumberOfJobs()); // Pop the 6 jobs. std::vector ids; queue.PopForRun(LOW_PRIORITY, &ids); ASSERT_EQ(2u, ids.size()); EXPECT_EQ(102, ids[0]); EXPECT_EQ(104, ids[1]); queue.MarkFinished(102); queue.MarkFinished(104); queue.PopForRun(LOW_PRIORITY, &ids); ASSERT_EQ(1u, ids.size()); EXPECT_EQ(106, ids[0]); queue.MarkFinished(106); queue.PopForRun(LOW_PRIORITY, &ids); ASSERT_EQ(1u, ids.size()); EXPECT_EQ(101, ids[0]); queue.MarkFinished(101); queue.PopForRun(LOW_PRIORITY, &ids); ASSERT_EQ(1u, ids.size()); EXPECT_EQ(103, ids[0]); queue.MarkFinished(103); queue.PopForRun(LOW_PRIORITY, &ids); ASSERT_EQ(1u, ids.size()); EXPECT_EQ(105, ids[0]); queue.MarkFinished(105); queue.PopForRun(LOW_PRIORITY, &ids); EXPECT_EQ(0u, ids.size()); } TEST(JobQueueTest, BatchRequstNumMaxJobs) { const size_t kNumMaxConcurrentJobs = 1; const size_t kNumPriorityLevels = 2; const size_t kNumMaxBatchJob = 5; const size_t kMaxBatchSize = 100; enum { HIGH_PRIORITY, LOW_PRIORITY }; // Create a queue. Number of jobs are initially zero. JobQueue queue(kNumMaxConcurrentJobs, kNumPriorityLevels, kNumMaxBatchJob, kMaxBatchSize); EXPECT_EQ(0U, queue.GetNumberOfJobs()); // Push 6 jobs. queue.Push(101, LOW_PRIORITY, true, 1); queue.Push(102, LOW_PRIORITY, true, 1); queue.Push(103, LOW_PRIORITY, true, 1); queue.Push(104, LOW_PRIORITY, true, 1); queue.Push(105, LOW_PRIORITY, true, 1); queue.Push(106, LOW_PRIORITY, true, 1); EXPECT_EQ(6U, queue.GetNumberOfJobs()); // Pop the 5 of 6 jobs. std::vector ids; queue.PopForRun(LOW_PRIORITY, &ids); EXPECT_EQ(5u, ids.size()); } } // namespace drive