blob: 08e81025bcea7f5ec1732622713602fd4e1c3b21 [file] [log] [blame]
Vitaly Buka4615e0d2015-10-14 15:35:12 -07001// Copyright 2015 The Weave Authors. All rights reserved.
Alex Vakulenkoaa3a5592014-08-07 07:24:06 -07002// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
Stefan Sauer2d16dfa2015-09-25 17:08:35 +02005#include "src/commands/command_queue.h"
Alex Deymof6cbe322014-11-10 19:55:35 -08006
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 Vakulenkoaa3a5592014-08-07 07:24:06 -070013#include <gtest/gtest.h>
14
Stefan Sauer2d16dfa2015-09-25 17:08:35 +020015#include "src/string_utils.h"
Alex Vakulenkoaa3a5592014-08-07 07:24:06 -070016
Vitaly Bukab6f015a2015-07-09 14:59:23 -070017namespace weave {
Alex Vakulenkoaa3a5592014-08-07 07:24:06 -070018
Alex Vakulenko5ef75792015-03-19 15:50:44 -070019class CommandQueueTest : public testing::Test {
20 public:
Vitaly Buka2a9b30f2015-04-01 10:51:59 -070021 std::unique_ptr<CommandInstance> CreateDummyCommandInstance(
22 const std::string& name,
23 const std::string& id) {
Vitaly Buka15f59092015-07-24 16:54:32 -070024 std::unique_ptr<CommandInstance> cmd{new CommandInstance{
Alex Vakulenko2c7740a2015-11-30 08:51:29 -080025 name, Command::Origin::kLocal, {}}};
Alex Vakulenko5ef75792015-03-19 15:50:44 -070026 cmd->SetID(id);
27 return cmd;
28 }
29
Vitaly Buka2a9b30f2015-04-01 10:51:59 -070030 bool Remove(const std::string& id) { return queue_.Remove(id); }
31
32 void Cleanup(const base::TimeDelta& interval) {
33 queue_.SetNowForTest(base::Time::Now() + interval);
34 return queue_.Cleanup();
35 }
36
37 CommandQueue queue_;
Alex Vakulenko5ef75792015-03-19 15:50:44 -070038};
Alex Vakulenkoaa3a5592014-08-07 07:24:06 -070039
Vitaly Bukaae0f3a12015-05-11 16:27:30 -070040// Keeps track of commands being added to and removed from the queue_.
Alex Vakulenko515b42b2014-08-07 15:46:31 -070041// Aborts if duplicate commands are added or non-existent commands are removed.
Vitaly Bukaae0f3a12015-05-11 16:27:30 -070042class FakeDispatcher {
Alex Vakulenko515b42b2014-08-07 15:46:31 -070043 public:
Vitaly Bukaae0f3a12015-05-11 16:27:30 -070044 explicit FakeDispatcher(CommandQueue* queue) {
Vitaly Buka553a7622015-10-05 13:53:20 -070045 queue->AddCommandAddedCallback(base::Bind(&FakeDispatcher::OnCommandAdded,
46 weak_ptr_factory_.GetWeakPtr()));
47 queue->AddCommandRemovedCallback(base::Bind(
Vitaly Bukaa647c852015-07-06 14:51:01 -070048 &FakeDispatcher::OnCommandRemoved, weak_ptr_factory_.GetWeakPtr()));
Vitaly Bukaae0f3a12015-05-11 16:27:30 -070049 }
50
Vitaly Buka12affd82015-07-23 18:45:35 -070051 void OnCommandAdded(Command* command) {
52 CHECK(ids_.insert(command->GetID()).second) << "Command ID already exists: "
53 << command->GetID();
54 CHECK(commands_.insert(command).second)
Alex Vakulenko515b42b2014-08-07 15:46:31 -070055 << "Command instance already exists";
56 }
57
Vitaly Buka12affd82015-07-23 18:45:35 -070058 void OnCommandRemoved(Command* command) {
59 CHECK_EQ(1u, ids_.erase(command->GetID())) << "Command ID not found: "
60 << command->GetID();
61 CHECK_EQ(1u, commands_.erase(command)) << "Command instance not found";
Alex Vakulenko515b42b2014-08-07 15:46:31 -070062 }
63
64 // Get the comma-separated list of command IDs currently accumulated in the
Vitaly Buka2a9b30f2015-04-01 10:51:59 -070065 // command queue_.
Alex Vakulenko515b42b2014-08-07 15:46:31 -070066 std::string GetIDs() const {
Vitaly Bukadb770e72015-03-10 19:33:33 -070067 return Join(",", std::vector<std::string>(ids_.begin(), ids_.end()));
Alex Vakulenko515b42b2014-08-07 15:46:31 -070068 }
69
70 private:
71 std::set<std::string> ids_;
Vitaly Buka12affd82015-07-23 18:45:35 -070072 std::set<Command*> commands_;
Vitaly Bukaae0f3a12015-05-11 16:27:30 -070073 base::WeakPtrFactory<FakeDispatcher> weak_ptr_factory_{this};
Alex Vakulenko515b42b2014-08-07 15:46:31 -070074};
75
Alex Vakulenko5ef75792015-03-19 15:50:44 -070076TEST_F(CommandQueueTest, Empty) {
Vitaly Buka2a9b30f2015-04-01 10:51:59 -070077 EXPECT_TRUE(queue_.IsEmpty());
Vitaly Buka52d006a2015-11-21 17:14:51 -080078 EXPECT_EQ(0u, queue_.GetCount());
Alex Vakulenkoaa3a5592014-08-07 07:24:06 -070079}
80
Alex Vakulenko5ef75792015-03-19 15:50:44 -070081TEST_F(CommandQueueTest, Add) {
Vitaly Buka2a9b30f2015-04-01 10:51:59 -070082 queue_.Add(CreateDummyCommandInstance("base.reboot", "id1"));
83 queue_.Add(CreateDummyCommandInstance("base.reboot", "id2"));
84 queue_.Add(CreateDummyCommandInstance("base.reboot", "id3"));
Vitaly Buka52d006a2015-11-21 17:14:51 -080085 EXPECT_EQ(3u, queue_.GetCount());
Vitaly Buka2a9b30f2015-04-01 10:51:59 -070086 EXPECT_FALSE(queue_.IsEmpty());
Alex Vakulenkoaa3a5592014-08-07 07:24:06 -070087}
88
Alex Vakulenko5ef75792015-03-19 15:50:44 -070089TEST_F(CommandQueueTest, Remove) {
Anton Muhin5191e812014-10-30 17:49:48 +040090 const std::string id1 = "id1";
91 const std::string id2 = "id2";
Vitaly Buka2a9b30f2015-04-01 10:51:59 -070092 queue_.Add(CreateDummyCommandInstance("base.reboot", id1));
93 queue_.Add(CreateDummyCommandInstance("base.reboot", id2));
94 EXPECT_FALSE(queue_.IsEmpty());
95 EXPECT_FALSE(Remove("dummy"));
Vitaly Buka52d006a2015-11-21 17:14:51 -080096 EXPECT_EQ(2u, queue_.GetCount());
Vitaly Buka2a9b30f2015-04-01 10:51:59 -070097 EXPECT_TRUE(Remove(id1));
Vitaly Buka52d006a2015-11-21 17:14:51 -080098 EXPECT_EQ(1u, queue_.GetCount());
Vitaly Buka2a9b30f2015-04-01 10:51:59 -070099 EXPECT_FALSE(Remove(id1));
Vitaly Buka52d006a2015-11-21 17:14:51 -0800100 EXPECT_EQ(1u, queue_.GetCount());
Vitaly Buka2a9b30f2015-04-01 10:51:59 -0700101 EXPECT_TRUE(Remove(id2));
Vitaly Buka52d006a2015-11-21 17:14:51 -0800102 EXPECT_EQ(0u, queue_.GetCount());
Vitaly Buka2a9b30f2015-04-01 10:51:59 -0700103 EXPECT_FALSE(Remove(id2));
Vitaly Buka52d006a2015-11-21 17:14:51 -0800104 EXPECT_EQ(0u, queue_.GetCount());
Vitaly Buka2a9b30f2015-04-01 10:51:59 -0700105 EXPECT_TRUE(queue_.IsEmpty());
106}
107
108TEST_F(CommandQueueTest, DelayedRemove) {
109 const std::string id1 = "id1";
110 queue_.Add(CreateDummyCommandInstance("base.reboot", id1));
Vitaly Buka52d006a2015-11-21 17:14:51 -0800111 EXPECT_EQ(1u, queue_.GetCount());
Vitaly Buka2a9b30f2015-04-01 10:51:59 -0700112
113 queue_.DelayedRemove(id1);
Vitaly Buka52d006a2015-11-21 17:14:51 -0800114 EXPECT_EQ(1u, queue_.GetCount());
Vitaly Buka2a9b30f2015-04-01 10:51:59 -0700115
116 Cleanup(base::TimeDelta::FromMinutes(1));
Vitaly Buka52d006a2015-11-21 17:14:51 -0800117 EXPECT_EQ(1u, queue_.GetCount());
Vitaly Buka2a9b30f2015-04-01 10:51:59 -0700118
119 Cleanup(base::TimeDelta::FromMinutes(15));
Vitaly Buka52d006a2015-11-21 17:14:51 -0800120 EXPECT_EQ(0u, queue_.GetCount());
Alex Vakulenkoaa3a5592014-08-07 07:24:06 -0700121}
122
Alex Vakulenko5ef75792015-03-19 15:50:44 -0700123TEST_F(CommandQueueTest, Dispatch) {
Vitaly Bukaae0f3a12015-05-11 16:27:30 -0700124 FakeDispatcher dispatch(&queue_);
Anton Muhin5191e812014-10-30 17:49:48 +0400125 const std::string id1 = "id1";
126 const std::string id2 = "id2";
Vitaly Buka2a9b30f2015-04-01 10:51:59 -0700127 queue_.Add(CreateDummyCommandInstance("base.reboot", id1));
128 queue_.Add(CreateDummyCommandInstance("base.reboot", id2));
Alex Vakulenko515b42b2014-08-07 15:46:31 -0700129 std::set<std::string> ids{id1, id2}; // Make sure they are sorted properly.
Vitaly Buka24d6fd52015-08-13 23:22:48 -0700130 std::string expected_set =
131 Join(",", std::vector<std::string>(ids.begin(), ids.end()));
Alex Vakulenko515b42b2014-08-07 15:46:31 -0700132 EXPECT_EQ(expected_set, dispatch.GetIDs());
Vitaly Buka2a9b30f2015-04-01 10:51:59 -0700133 Remove(id1);
Alex Vakulenko515b42b2014-08-07 15:46:31 -0700134 EXPECT_EQ(id2, dispatch.GetIDs());
Vitaly Buka2a9b30f2015-04-01 10:51:59 -0700135 Remove(id2);
Alex Vakulenko515b42b2014-08-07 15:46:31 -0700136 EXPECT_EQ("", dispatch.GetIDs());
137}
138
Alex Vakulenko5ef75792015-03-19 15:50:44 -0700139TEST_F(CommandQueueTest, Find) {
Anton Muhin5191e812014-10-30 17:49:48 +0400140 const std::string id1 = "id1";
141 const std::string id2 = "id2";
Vitaly Buka2a9b30f2015-04-01 10:51:59 -0700142 queue_.Add(CreateDummyCommandInstance("base.reboot", id1));
143 queue_.Add(CreateDummyCommandInstance("base.shutdown", id2));
144 EXPECT_EQ(nullptr, queue_.Find("dummy"));
145 auto cmd1 = queue_.Find(id1);
Alex Vakulenkoaa3a5592014-08-07 07:24:06 -0700146 EXPECT_NE(nullptr, cmd1);
147 EXPECT_EQ("base.reboot", cmd1->GetName());
Alex Vakulenkofedc4872014-08-20 12:38:43 -0700148 EXPECT_EQ(id1, cmd1->GetID());
Vitaly Buka2a9b30f2015-04-01 10:51:59 -0700149 auto cmd2 = queue_.Find(id2);
Alex Vakulenkoaa3a5592014-08-07 07:24:06 -0700150 EXPECT_NE(nullptr, cmd2);
151 EXPECT_EQ("base.shutdown", cmd2->GetName());
Alex Vakulenkofedc4872014-08-20 12:38:43 -0700152 EXPECT_EQ(id2, cmd2->GetID());
Alex Vakulenkoaa3a5592014-08-07 07:24:06 -0700153}
Vitaly Buka2a9b30f2015-04-01 10:51:59 -0700154
Vitaly Bukab6f015a2015-07-09 14:59:23 -0700155} // namespace weave