1 : // Copyright 2013 Google Inc. All Rights Reserved.
2 : //
3 : // Licensed under the Apache License, Version 2.0 (the "License");
4 : // you may not use this file except in compliance with the License.
5 : // You may obtain a copy of the License at
6 : //
7 : // http://www.apache.org/licenses/LICENSE-2.0
8 : //
9 : // Unless required by applicable law or agreed to in writing, software
10 : // distributed under the License is distributed on an "AS IS" BASIS,
11 : // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 : // See the License for the specific language governing permissions and
13 : // limitations under the License.
14 :
15 : #include "syzygy/trace/common/service.h"
16 :
17 : #include "base/bind.h"
18 : #include "gmock/gmock.h"
19 : #include "gtest/gtest.h"
20 :
21 : namespace trace {
22 : namespace common {
23 :
24 : namespace {
25 :
26 : using testing::_;
27 : using testing::Invoke;
28 : using testing::Return;
29 :
30 : const wchar_t kTestServiceName[] = L"TestService";
31 :
32 : class TestService : public Service {
33 : public:
34 E : TestService() : Service(kTestServiceName) { }
35 :
36 : // Initially we leave the callbacks empty. This plumbs the callbacks into our
37 : // base class.
38 E : void SetCallbacks() {
39 E : set_started_callback(base::Bind(&InvokeStartedCallback));
40 E : set_interrupted_callback(base::Bind(&InvokeInterruptedCallback));
41 E : set_stopped_callback(base::Bind(&InvokeStoppedCallback));
42 E : }
43 :
44 E : MOCK_METHOD0(StartImpl, bool());
45 E : MOCK_METHOD0(StopImpl, bool());
46 i : MOCK_METHOD0(JoinImpl, bool());
47 :
48 : // Testing seam callback that is invoked on state changes.
49 E : MOCK_METHOD2(OnStateChange, void(State, State));
50 :
51 : // Callbacks that will be invoked by the appropriate hooks in the base class.
52 E : MOCK_METHOD0(StartedCallback, bool());
53 E : MOCK_METHOD0(InterruptedCallback, bool());
54 E : MOCK_METHOD0(StoppedCallback, bool());
55 :
56 : // Used to simulate a startup sequence.
57 E : bool InitFailsStartup() {
58 E : return false;
59 E : }
60 E : bool InitSucceedsStartup() {
61 E : OnInitialized();
62 E : return false;
63 E : }
64 E : bool SuccessfulStartup() {
65 E : OnInitialized();
66 E : OnStarted();
67 E : return true;
68 E : }
69 :
70 : // Used to simulate a successful stop.
71 E : bool SuccessfulStop() {
72 E : OnStopped();
73 E : return true;
74 E : }
75 :
76 : // Exposed for testing.
77 : using Service::OnInterrupted;
78 :
79 : private:
80 : // @{
81 : // We use these to register callbacks with our base class, and plumb them
82 : // into the mocked methods above.
83 :
84 E : static bool InvokeStartedCallback(Service* service) {
85 E : DCHECK(service != NULL);
86 E : TestService* test_service = static_cast<TestService*>(service);
87 E : return test_service->StartedCallback();
88 E : }
89 :
90 E : static bool InvokeInterruptedCallback(Service* service) {
91 E : DCHECK(service != NULL);
92 E : TestService* test_service = static_cast<TestService*>(service);
93 E : return test_service->InterruptedCallback();
94 E : }
95 :
96 E : static bool InvokeStoppedCallback(Service* service) {
97 E : DCHECK(service != NULL);
98 E : TestService* test_service = static_cast<TestService*>(service);
99 E : return test_service->StoppedCallback();
100 E : }
101 : // @}
102 : };
103 : typedef testing::StrictMock<TestService> StrictTestService;
104 :
105 : } // namespace
106 :
107 E : TEST(ServiceTest, MutatorsAndAccessors) {
108 E : StrictTestService t;
109 E : EXPECT_EQ(kTestServiceName, t.name());
110 E : EXPECT_TRUE(t.instance_id().empty());
111 E : EXPECT_EQ(Service::kUnused, t.state());
112 :
113 E : std::wstring instance_id = L"Foobar";
114 E : t.set_instance_id(instance_id);
115 E : EXPECT_EQ(instance_id, t.instance_id());
116 :
117 E : t.SetCallbacks();
118 E : }
119 :
120 E : TEST(ServiceTest, FailedInit) {
121 E : StrictTestService t;
122 E : t.SetCallbacks();
123 :
124 E : EXPECT_EQ(Service::kUnused, t.state());
125 : EXPECT_CALL(t, StartImpl()).Times(1).
126 E : WillOnce(Invoke(&t, &TestService::InitFailsStartup));
127 E : EXPECT_CALL(t, OnStateChange(Service::kUnused, Service::kErrored));
128 E : EXPECT_FALSE(t.Start());
129 E : EXPECT_EQ(Service::kErrored, t.state());
130 E : }
131 :
132 E : TEST(ServiceTest, SuccessfulInitFailedStartup) {
133 E : StrictTestService t;
134 E : t.SetCallbacks();
135 :
136 E : EXPECT_EQ(Service::kUnused, t.state());
137 : EXPECT_CALL(t, StartImpl()).Times(1).
138 E : WillOnce(Invoke(&t, &TestService::InitSucceedsStartup));
139 E : EXPECT_CALL(t, OnStateChange(Service::kUnused, Service::kInitialized));
140 E : EXPECT_CALL(t, OnStateChange(Service::kInitialized, Service::kErrored));
141 E : EXPECT_FALSE(t.Start());
142 E : EXPECT_EQ(Service::kErrored, t.state());
143 E : }
144 :
145 E : TEST(ServiceTest, SuccessfulStartupFailedStop) {
146 E : StrictTestService t;
147 E : t.SetCallbacks();
148 :
149 E : EXPECT_EQ(Service::kUnused, t.state());
150 : EXPECT_CALL(t, StartImpl()).Times(1).
151 E : WillOnce(Invoke(&t, &TestService::SuccessfulStartup));
152 E : EXPECT_CALL(t, StartedCallback()).Times(1).WillOnce(Return(true));
153 E : EXPECT_CALL(t, OnStateChange(Service::kUnused, Service::kInitialized));
154 E : EXPECT_CALL(t, OnStateChange(Service::kInitialized, Service::kRunning));
155 E : EXPECT_TRUE(t.Start());
156 E : EXPECT_EQ(Service::kRunning, t.state());
157 :
158 E : EXPECT_CALL(t, StopImpl()).Times(1).WillOnce(Return(false));
159 E : EXPECT_CALL(t, OnStateChange(Service::kRunning, Service::kStopping));
160 E : EXPECT_CALL(t, OnStateChange(Service::kStopping, Service::kErrored));
161 E : EXPECT_FALSE(t.Stop());
162 E : EXPECT_EQ(Service::kErrored, t.state());
163 E : }
164 :
165 E : TEST(ServiceTest, SuccessfulStartupSuccessfulStop) {
166 E : StrictTestService t;
167 E : t.SetCallbacks();
168 :
169 E : EXPECT_EQ(Service::kUnused, t.state());
170 : EXPECT_CALL(t, StartImpl()).Times(1).
171 E : WillOnce(Invoke(&t, &TestService::SuccessfulStartup));
172 E : EXPECT_CALL(t, StartedCallback()).Times(1).WillOnce(Return(true));
173 E : EXPECT_CALL(t, OnStateChange(Service::kUnused, Service::kInitialized));
174 E : EXPECT_CALL(t, OnStateChange(Service::kInitialized, Service::kRunning));
175 E : EXPECT_TRUE(t.Start());
176 E : EXPECT_EQ(Service::kRunning, t.state());
177 :
178 : EXPECT_CALL(t, StopImpl()).Times(1).
179 E : WillOnce(Invoke(&t, &TestService::SuccessfulStop));
180 E : EXPECT_CALL(t, StoppedCallback()).Times(1).WillOnce(Return(true));
181 E : EXPECT_CALL(t, OnStateChange(Service::kRunning, Service::kStopping));
182 E : EXPECT_CALL(t, OnStateChange(Service::kStopping, Service::kStopped));
183 E : EXPECT_TRUE(t.Stop());
184 E : EXPECT_EQ(Service::kStopped, t.state());
185 E : }
186 :
187 E : TEST(ServiceTest, InterruptCallbackWorks) {
188 E : StrictTestService t;
189 E : t.SetCallbacks();
190 :
191 E : EXPECT_CALL(t, InterruptedCallback());
192 E : t.OnInterrupted();
193 E : }
194 :
195 : } // namespace common
196 : } // namespace trace
|