blob: f29b03e21a88e782c60f3cedf17c2a88139c4966 [file] [log] [blame]
Alex Vakulenkoaa3a5592014-08-07 07:24:06 -07001// Copyright 2014 The Chromium OS Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
Alex Deymof6cbe322014-11-10 19:55:35 -08005#include "buffet/commands/command_queue.h"
6
Alex Vakulenko515b42b2014-08-07 15:46:31 -07007#include <set>
Alex Vakulenkoaa3a5592014-08-07 07:24:06 -07008#include <string>
Alex Vakulenko515b42b2014-08-07 15:46:31 -07009#include <vector>
Alex Vakulenkoaa3a5592014-08-07 07:24:06 -070010
Vitaly Bukaae0f3a12015-05-11 16:27:30 -070011#include <base/bind.h>
12#include <base/memory/weak_ptr.h>
Alex Vakulenkoa8b95bc2014-08-27 11:00:57 -070013#include <chromeos/strings/string_utils.h>
Alex Vakulenkoaa3a5592014-08-07 07:24:06 -070014#include <gtest/gtest.h>
15
Anton Muhincfde8692014-11-25 03:36:59 +040016#include "buffet/commands/command_definition.h"
Anton Muhincfde8692014-11-25 03:36:59 +040017#include "buffet/commands/object_schema.h"
Alex Vakulenkoaa3a5592014-08-07 07:24:06 -070018
Vitaly Buka2a9b30f2015-04-01 10:51:59 -070019namespace buffet {
Alex Vakulenkoaa3a5592014-08-07 07:24:06 -070020
Alex Vakulenko5ef75792015-03-19 15:50:44 -070021class CommandQueueTest : public testing::Test {
22 public:
Vitaly Buka2a9b30f2015-04-01 10:51:59 -070023 std::unique_ptr<CommandInstance> CreateDummyCommandInstance(
24 const std::string& name,
25 const std::string& id) {
26 std::unique_ptr<CommandInstance> cmd{
Alex Vakulenkof784e212015-04-20 12:33:52 -070027 new CommandInstance{name, "local", &command_definition_, {}}};
Alex Vakulenko5ef75792015-03-19 15:50:44 -070028 cmd->SetID(id);
29 return cmd;
30 }
31
Vitaly Buka2a9b30f2015-04-01 10:51:59 -070032 bool Remove(const std::string& id) { return queue_.Remove(id); }
33
34 void Cleanup(const base::TimeDelta& interval) {
35 queue_.SetNowForTest(base::Time::Now() + interval);
36 return queue_.Cleanup();
37 }
38
39 CommandQueue queue_;
40
Alex Vakulenko5ef75792015-03-19 15:50:44 -070041 private:
Vitaly Buka2a9b30f2015-04-01 10:51:59 -070042 CommandDefinition command_definition_{"powerd",
43 ObjectSchema::Create(),
Vitaly Buka4129dfa2015-04-29 12:16:58 -070044 ObjectSchema::Create(),
Vitaly Buka2a9b30f2015-04-01 10:51:59 -070045 ObjectSchema::Create()};
Alex Vakulenko5ef75792015-03-19 15:50:44 -070046};
Alex Vakulenkoaa3a5592014-08-07 07:24:06 -070047
Vitaly Bukaae0f3a12015-05-11 16:27:30 -070048// Keeps track of commands being added to and removed from the queue_.
Alex Vakulenko515b42b2014-08-07 15:46:31 -070049// Aborts if duplicate commands are added or non-existent commands are removed.
Vitaly Bukaae0f3a12015-05-11 16:27:30 -070050class FakeDispatcher {
Alex Vakulenko515b42b2014-08-07 15:46:31 -070051 public:
Vitaly Bukaae0f3a12015-05-11 16:27:30 -070052 explicit FakeDispatcher(CommandQueue* queue) {
53 queue->AddOnCommandAddedCallback(
54 base::Bind(&FakeDispatcher::OnCommandAdded,
55 weak_ptr_factory_.GetWeakPtr()));
56 queue->AddOnCommandRemovedCallback(
57 base::Bind(&FakeDispatcher::OnCommandRemoved,
58 weak_ptr_factory_.GetWeakPtr()));
59 }
60
61 void OnCommandAdded(CommandInstance* command_instance) {
Alex Vakulenkofedc4872014-08-20 12:38:43 -070062 CHECK(ids_.insert(command_instance->GetID()).second)
63 << "Command ID already exists: " << command_instance->GetID();
Alex Vakulenko515b42b2014-08-07 15:46:31 -070064 CHECK(commands_.insert(command_instance).second)
65 << "Command instance already exists";
66 }
67
Vitaly Bukaae0f3a12015-05-11 16:27:30 -070068 void OnCommandRemoved(CommandInstance* command_instance) {
69 CHECK_EQ(1u, ids_.erase(command_instance->GetID()))
Alex Vakulenkofedc4872014-08-20 12:38:43 -070070 << "Command ID not found: " << command_instance->GetID();
Vitaly Bukaae0f3a12015-05-11 16:27:30 -070071 CHECK_EQ(1u, commands_.erase(command_instance))
Alex Vakulenko515b42b2014-08-07 15:46:31 -070072 << "Command instance not found";
73 }
74
75 // Get the comma-separated list of command IDs currently accumulated in the
Vitaly Buka2a9b30f2015-04-01 10:51:59 -070076 // command queue_.
Alex Vakulenko515b42b2014-08-07 15:46:31 -070077 std::string GetIDs() const {
Alex Vakulenkob8fc1df2014-08-20 15:38:07 -070078 using chromeos::string_utils::Join;
Vitaly Bukadb770e72015-03-10 19:33:33 -070079 return Join(",", std::vector<std::string>(ids_.begin(), ids_.end()));
Alex Vakulenko515b42b2014-08-07 15:46:31 -070080 }
81
82 private:
83 std::set<std::string> ids_;
Vitaly Buka2a9b30f2015-04-01 10:51:59 -070084 std::set<CommandInstance*> commands_;
Vitaly Bukaae0f3a12015-05-11 16:27:30 -070085 base::WeakPtrFactory<FakeDispatcher> weak_ptr_factory_{this};
Alex Vakulenko515b42b2014-08-07 15:46:31 -070086};
87
Alex Vakulenko5ef75792015-03-19 15:50:44 -070088TEST_F(CommandQueueTest, Empty) {
Vitaly Buka2a9b30f2015-04-01 10:51:59 -070089 EXPECT_TRUE(queue_.IsEmpty());
90 EXPECT_EQ(0, queue_.GetCount());
Alex Vakulenkoaa3a5592014-08-07 07:24:06 -070091}
92
Alex Vakulenko5ef75792015-03-19 15:50:44 -070093TEST_F(CommandQueueTest, Add) {
Vitaly Buka2a9b30f2015-04-01 10:51:59 -070094 queue_.Add(CreateDummyCommandInstance("base.reboot", "id1"));
95 queue_.Add(CreateDummyCommandInstance("base.reboot", "id2"));
96 queue_.Add(CreateDummyCommandInstance("base.reboot", "id3"));
97 EXPECT_EQ(3, queue_.GetCount());
98 EXPECT_FALSE(queue_.IsEmpty());
Alex Vakulenkoaa3a5592014-08-07 07:24:06 -070099}
100
Alex Vakulenko5ef75792015-03-19 15:50:44 -0700101TEST_F(CommandQueueTest, Remove) {
Anton Muhin5191e812014-10-30 17:49:48 +0400102 const std::string id1 = "id1";
103 const std::string id2 = "id2";
Vitaly Buka2a9b30f2015-04-01 10:51:59 -0700104 queue_.Add(CreateDummyCommandInstance("base.reboot", id1));
105 queue_.Add(CreateDummyCommandInstance("base.reboot", id2));
106 EXPECT_FALSE(queue_.IsEmpty());
107 EXPECT_FALSE(Remove("dummy"));
108 EXPECT_EQ(2, queue_.GetCount());
109 EXPECT_TRUE(Remove(id1));
110 EXPECT_EQ(1, queue_.GetCount());
111 EXPECT_FALSE(Remove(id1));
112 EXPECT_EQ(1, queue_.GetCount());
113 EXPECT_TRUE(Remove(id2));
114 EXPECT_EQ(0, queue_.GetCount());
115 EXPECT_FALSE(Remove(id2));
116 EXPECT_EQ(0, queue_.GetCount());
117 EXPECT_TRUE(queue_.IsEmpty());
118}
119
120TEST_F(CommandQueueTest, DelayedRemove) {
121 const std::string id1 = "id1";
122 queue_.Add(CreateDummyCommandInstance("base.reboot", id1));
123 EXPECT_EQ(1, queue_.GetCount());
124
125 queue_.DelayedRemove(id1);
126 EXPECT_EQ(1, queue_.GetCount());
127
128 Cleanup(base::TimeDelta::FromMinutes(1));
129 EXPECT_EQ(1, queue_.GetCount());
130
131 Cleanup(base::TimeDelta::FromMinutes(15));
132 EXPECT_EQ(0, queue_.GetCount());
Alex Vakulenkoaa3a5592014-08-07 07:24:06 -0700133}
134
Alex Vakulenko5ef75792015-03-19 15:50:44 -0700135TEST_F(CommandQueueTest, Dispatch) {
Vitaly Bukaae0f3a12015-05-11 16:27:30 -0700136 FakeDispatcher dispatch(&queue_);
Anton Muhin5191e812014-10-30 17:49:48 +0400137 const std::string id1 = "id1";
138 const std::string id2 = "id2";
Vitaly Buka2a9b30f2015-04-01 10:51:59 -0700139 queue_.Add(CreateDummyCommandInstance("base.reboot", id1));
140 queue_.Add(CreateDummyCommandInstance("base.reboot", id2));
Alex Vakulenko515b42b2014-08-07 15:46:31 -0700141 std::set<std::string> ids{id1, id2}; // Make sure they are sorted properly.
Alex Vakulenkob8fc1df2014-08-20 15:38:07 -0700142 std::string expected_set = chromeos::string_utils::Join(
Vitaly Bukadb770e72015-03-10 19:33:33 -0700143 ",", std::vector<std::string>(ids.begin(), ids.end()));
Alex Vakulenko515b42b2014-08-07 15:46:31 -0700144 EXPECT_EQ(expected_set, dispatch.GetIDs());
Vitaly Buka2a9b30f2015-04-01 10:51:59 -0700145 Remove(id1);
Alex Vakulenko515b42b2014-08-07 15:46:31 -0700146 EXPECT_EQ(id2, dispatch.GetIDs());
Vitaly Buka2a9b30f2015-04-01 10:51:59 -0700147 Remove(id2);
Alex Vakulenko515b42b2014-08-07 15:46:31 -0700148 EXPECT_EQ("", dispatch.GetIDs());
149}
150
Alex Vakulenko5ef75792015-03-19 15:50:44 -0700151TEST_F(CommandQueueTest, Find) {
Anton Muhin5191e812014-10-30 17:49:48 +0400152 const std::string id1 = "id1";
153 const std::string id2 = "id2";
Vitaly Buka2a9b30f2015-04-01 10:51:59 -0700154 queue_.Add(CreateDummyCommandInstance("base.reboot", id1));
155 queue_.Add(CreateDummyCommandInstance("base.shutdown", id2));
156 EXPECT_EQ(nullptr, queue_.Find("dummy"));
157 auto cmd1 = queue_.Find(id1);
Alex Vakulenkoaa3a5592014-08-07 07:24:06 -0700158 EXPECT_NE(nullptr, cmd1);
159 EXPECT_EQ("base.reboot", cmd1->GetName());
Alex Vakulenkofedc4872014-08-20 12:38:43 -0700160 EXPECT_EQ(id1, cmd1->GetID());
Vitaly Buka2a9b30f2015-04-01 10:51:59 -0700161 auto cmd2 = queue_.Find(id2);
Alex Vakulenkoaa3a5592014-08-07 07:24:06 -0700162 EXPECT_NE(nullptr, cmd2);
163 EXPECT_EQ("base.shutdown", cmd2->GetName());
Alex Vakulenkofedc4872014-08-20 12:38:43 -0700164 EXPECT_EQ(id2, cmd2->GetID());
Alex Vakulenkoaa3a5592014-08-07 07:24:06 -0700165}
Vitaly Buka2a9b30f2015-04-01 10:51:59 -0700166
167} // namespace buffet