blob: 394ae20bd1de65303d81af0f63e77426cdf53c2d [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/commands/command_definition.h"
16#include "src/commands/object_schema.h"
17#include "src/string_utils.h"
Alex Vakulenkoaa3a5592014-08-07 07:24:06 -070018
Vitaly Bukab6f015a2015-07-09 14:59:23 -070019namespace weave {
Alex Vakulenkoaa3a5592014-08-07 07:24:06 -070020
Alex Vakulenko5ef75792015-03-19 15:50:44 -070021class CommandQueueTest : public testing::Test {
22 public:
Alex Vakulenko7e894da2015-11-23 11:47:49 -080023 CommandQueueTest() {
24 command_definition_ = CommandDefinition::FromJson({}, nullptr);
25 }
26
Vitaly Buka2a9b30f2015-04-01 10:51:59 -070027 std::unique_ptr<CommandInstance> CreateDummyCommandInstance(
28 const std::string& name,
29 const std::string& id) {
Vitaly Buka15f59092015-07-24 16:54:32 -070030 std::unique_ptr<CommandInstance> cmd{new CommandInstance{
Alex Vakulenko7e894da2015-11-23 11:47:49 -080031 name, Command::Origin::kLocal, command_definition_.get(), {}}};
Alex Vakulenko5ef75792015-03-19 15:50:44 -070032 cmd->SetID(id);
33 return cmd;
34 }
35
Vitaly Buka2a9b30f2015-04-01 10:51:59 -070036 bool Remove(const std::string& id) { return queue_.Remove(id); }
37
38 void Cleanup(const base::TimeDelta& interval) {
39 queue_.SetNowForTest(base::Time::Now() + interval);
40 return queue_.Cleanup();
41 }
42
43 CommandQueue queue_;
44
Alex Vakulenko5ef75792015-03-19 15:50:44 -070045 private:
Alex Vakulenko7e894da2015-11-23 11:47:49 -080046 std::unique_ptr<CommandDefinition> command_definition_;
Alex Vakulenko5ef75792015-03-19 15:50:44 -070047};
Alex Vakulenkoaa3a5592014-08-07 07:24:06 -070048
Vitaly Bukaae0f3a12015-05-11 16:27:30 -070049// Keeps track of commands being added to and removed from the queue_.
Alex Vakulenko515b42b2014-08-07 15:46:31 -070050// Aborts if duplicate commands are added or non-existent commands are removed.
Vitaly Bukaae0f3a12015-05-11 16:27:30 -070051class FakeDispatcher {
Alex Vakulenko515b42b2014-08-07 15:46:31 -070052 public:
Vitaly Bukaae0f3a12015-05-11 16:27:30 -070053 explicit FakeDispatcher(CommandQueue* queue) {
Vitaly Buka553a7622015-10-05 13:53:20 -070054 queue->AddCommandAddedCallback(base::Bind(&FakeDispatcher::OnCommandAdded,
55 weak_ptr_factory_.GetWeakPtr()));
56 queue->AddCommandRemovedCallback(base::Bind(
Vitaly Bukaa647c852015-07-06 14:51:01 -070057 &FakeDispatcher::OnCommandRemoved, weak_ptr_factory_.GetWeakPtr()));
Vitaly Bukaae0f3a12015-05-11 16:27:30 -070058 }
59
Vitaly Buka12affd82015-07-23 18:45:35 -070060 void OnCommandAdded(Command* command) {
61 CHECK(ids_.insert(command->GetID()).second) << "Command ID already exists: "
62 << command->GetID();
63 CHECK(commands_.insert(command).second)
Alex Vakulenko515b42b2014-08-07 15:46:31 -070064 << "Command instance already exists";
65 }
66
Vitaly Buka12affd82015-07-23 18:45:35 -070067 void OnCommandRemoved(Command* command) {
68 CHECK_EQ(1u, ids_.erase(command->GetID())) << "Command ID not found: "
69 << command->GetID();
70 CHECK_EQ(1u, commands_.erase(command)) << "Command instance not found";
Alex Vakulenko515b42b2014-08-07 15:46:31 -070071 }
72
73 // Get the comma-separated list of command IDs currently accumulated in the
Vitaly Buka2a9b30f2015-04-01 10:51:59 -070074 // command queue_.
Alex Vakulenko515b42b2014-08-07 15:46:31 -070075 std::string GetIDs() const {
Vitaly Bukadb770e72015-03-10 19:33:33 -070076 return Join(",", std::vector<std::string>(ids_.begin(), ids_.end()));
Alex Vakulenko515b42b2014-08-07 15:46:31 -070077 }
78
79 private:
80 std::set<std::string> ids_;
Vitaly Buka12affd82015-07-23 18:45:35 -070081 std::set<Command*> commands_;
Vitaly Bukaae0f3a12015-05-11 16:27:30 -070082 base::WeakPtrFactory<FakeDispatcher> weak_ptr_factory_{this};
Alex Vakulenko515b42b2014-08-07 15:46:31 -070083};
84
Alex Vakulenko5ef75792015-03-19 15:50:44 -070085TEST_F(CommandQueueTest, Empty) {
Vitaly Buka2a9b30f2015-04-01 10:51:59 -070086 EXPECT_TRUE(queue_.IsEmpty());
Vitaly Buka52d006a2015-11-21 17:14:51 -080087 EXPECT_EQ(0u, queue_.GetCount());
Alex Vakulenkoaa3a5592014-08-07 07:24:06 -070088}
89
Alex Vakulenko5ef75792015-03-19 15:50:44 -070090TEST_F(CommandQueueTest, Add) {
Vitaly Buka2a9b30f2015-04-01 10:51:59 -070091 queue_.Add(CreateDummyCommandInstance("base.reboot", "id1"));
92 queue_.Add(CreateDummyCommandInstance("base.reboot", "id2"));
93 queue_.Add(CreateDummyCommandInstance("base.reboot", "id3"));
Vitaly Buka52d006a2015-11-21 17:14:51 -080094 EXPECT_EQ(3u, queue_.GetCount());
Vitaly Buka2a9b30f2015-04-01 10:51:59 -070095 EXPECT_FALSE(queue_.IsEmpty());
Alex Vakulenkoaa3a5592014-08-07 07:24:06 -070096}
97
Alex Vakulenko5ef75792015-03-19 15:50:44 -070098TEST_F(CommandQueueTest, Remove) {
Anton Muhin5191e812014-10-30 17:49:48 +040099 const std::string id1 = "id1";
100 const std::string id2 = "id2";
Vitaly Buka2a9b30f2015-04-01 10:51:59 -0700101 queue_.Add(CreateDummyCommandInstance("base.reboot", id1));
102 queue_.Add(CreateDummyCommandInstance("base.reboot", id2));
103 EXPECT_FALSE(queue_.IsEmpty());
104 EXPECT_FALSE(Remove("dummy"));
Vitaly Buka52d006a2015-11-21 17:14:51 -0800105 EXPECT_EQ(2u, queue_.GetCount());
Vitaly Buka2a9b30f2015-04-01 10:51:59 -0700106 EXPECT_TRUE(Remove(id1));
Vitaly Buka52d006a2015-11-21 17:14:51 -0800107 EXPECT_EQ(1u, queue_.GetCount());
Vitaly Buka2a9b30f2015-04-01 10:51:59 -0700108 EXPECT_FALSE(Remove(id1));
Vitaly Buka52d006a2015-11-21 17:14:51 -0800109 EXPECT_EQ(1u, queue_.GetCount());
Vitaly Buka2a9b30f2015-04-01 10:51:59 -0700110 EXPECT_TRUE(Remove(id2));
Vitaly Buka52d006a2015-11-21 17:14:51 -0800111 EXPECT_EQ(0u, queue_.GetCount());
Vitaly Buka2a9b30f2015-04-01 10:51:59 -0700112 EXPECT_FALSE(Remove(id2));
Vitaly Buka52d006a2015-11-21 17:14:51 -0800113 EXPECT_EQ(0u, queue_.GetCount());
Vitaly Buka2a9b30f2015-04-01 10:51:59 -0700114 EXPECT_TRUE(queue_.IsEmpty());
115}
116
117TEST_F(CommandQueueTest, DelayedRemove) {
118 const std::string id1 = "id1";
119 queue_.Add(CreateDummyCommandInstance("base.reboot", id1));
Vitaly Buka52d006a2015-11-21 17:14:51 -0800120 EXPECT_EQ(1u, queue_.GetCount());
Vitaly Buka2a9b30f2015-04-01 10:51:59 -0700121
122 queue_.DelayedRemove(id1);
Vitaly Buka52d006a2015-11-21 17:14:51 -0800123 EXPECT_EQ(1u, queue_.GetCount());
Vitaly Buka2a9b30f2015-04-01 10:51:59 -0700124
125 Cleanup(base::TimeDelta::FromMinutes(1));
Vitaly Buka52d006a2015-11-21 17:14:51 -0800126 EXPECT_EQ(1u, queue_.GetCount());
Vitaly Buka2a9b30f2015-04-01 10:51:59 -0700127
128 Cleanup(base::TimeDelta::FromMinutes(15));
Vitaly Buka52d006a2015-11-21 17:14:51 -0800129 EXPECT_EQ(0u, queue_.GetCount());
Alex Vakulenkoaa3a5592014-08-07 07:24:06 -0700130}
131
Alex Vakulenko5ef75792015-03-19 15:50:44 -0700132TEST_F(CommandQueueTest, Dispatch) {
Vitaly Bukaae0f3a12015-05-11 16:27:30 -0700133 FakeDispatcher dispatch(&queue_);
Anton Muhin5191e812014-10-30 17:49:48 +0400134 const std::string id1 = "id1";
135 const std::string id2 = "id2";
Vitaly Buka2a9b30f2015-04-01 10:51:59 -0700136 queue_.Add(CreateDummyCommandInstance("base.reboot", id1));
137 queue_.Add(CreateDummyCommandInstance("base.reboot", id2));
Alex Vakulenko515b42b2014-08-07 15:46:31 -0700138 std::set<std::string> ids{id1, id2}; // Make sure they are sorted properly.
Vitaly Buka24d6fd52015-08-13 23:22:48 -0700139 std::string expected_set =
140 Join(",", std::vector<std::string>(ids.begin(), ids.end()));
Alex Vakulenko515b42b2014-08-07 15:46:31 -0700141 EXPECT_EQ(expected_set, dispatch.GetIDs());
Vitaly Buka2a9b30f2015-04-01 10:51:59 -0700142 Remove(id1);
Alex Vakulenko515b42b2014-08-07 15:46:31 -0700143 EXPECT_EQ(id2, dispatch.GetIDs());
Vitaly Buka2a9b30f2015-04-01 10:51:59 -0700144 Remove(id2);
Alex Vakulenko515b42b2014-08-07 15:46:31 -0700145 EXPECT_EQ("", dispatch.GetIDs());
146}
147
Alex Vakulenko5ef75792015-03-19 15:50:44 -0700148TEST_F(CommandQueueTest, Find) {
Anton Muhin5191e812014-10-30 17:49:48 +0400149 const std::string id1 = "id1";
150 const std::string id2 = "id2";
Vitaly Buka2a9b30f2015-04-01 10:51:59 -0700151 queue_.Add(CreateDummyCommandInstance("base.reboot", id1));
152 queue_.Add(CreateDummyCommandInstance("base.shutdown", id2));
153 EXPECT_EQ(nullptr, queue_.Find("dummy"));
154 auto cmd1 = queue_.Find(id1);
Alex Vakulenkoaa3a5592014-08-07 07:24:06 -0700155 EXPECT_NE(nullptr, cmd1);
156 EXPECT_EQ("base.reboot", cmd1->GetName());
Alex Vakulenkofedc4872014-08-20 12:38:43 -0700157 EXPECT_EQ(id1, cmd1->GetID());
Vitaly Buka2a9b30f2015-04-01 10:51:59 -0700158 auto cmd2 = queue_.Find(id2);
Alex Vakulenkoaa3a5592014-08-07 07:24:06 -0700159 EXPECT_NE(nullptr, cmd2);
160 EXPECT_EQ("base.shutdown", cmd2->GetName());
Alex Vakulenkofedc4872014-08-20 12:38:43 -0700161 EXPECT_EQ(id2, cmd2->GetID());
Alex Vakulenkoaa3a5592014-08-07 07:24:06 -0700162}
Vitaly Buka2a9b30f2015-04-01 10:51:59 -0700163
Vitaly Bukab6f015a2015-07-09 14:59:23 -0700164} // namespace weave