blob: 2b76944b1f172f756b2f56b9cf89b260042ca8d2 [file] [log] [blame]
Tianjie Xu5fe5eb62018-03-20 16:07:39 -07001/*
2 * Copyright (C) 2018 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
Tao Bao1fe1afe2018-05-01 15:56:05 -070017#include <stddef.h>
Tao Bao152e0eb2018-05-13 00:34:45 -070018#include <stdio.h>
Tianjie Xu5fe5eb62018-03-20 16:07:39 -070019
Tao Bao6cd81682018-05-03 21:53:11 -070020#include <functional>
21#include <map>
22#include <memory>
Tianjie Xu5fe5eb62018-03-20 16:07:39 -070023#include <string>
Tao Bao1fe1afe2018-05-01 15:56:05 -070024#include <vector>
Tianjie Xu5fe5eb62018-03-20 16:07:39 -070025
Tao Bao6cd81682018-05-03 21:53:11 -070026#include <android-base/logging.h>
Tao Bao152e0eb2018-05-13 00:34:45 -070027#include <android-base/stringprintf.h>
28#include <android-base/test_utils.h>
Tianjie Xu5fe5eb62018-03-20 16:07:39 -070029#include <gtest/gtest.h>
30
Tao Bao6cd81682018-05-03 21:53:11 -070031#include "common/test_constants.h"
32#include "device.h"
Tao Bao51f16ec2018-06-04 11:40:20 -070033#include "minui/minui.h"
Tao Bao6cd81682018-05-03 21:53:11 -070034#include "otautil/paths.h"
35#include "private/resources.h"
Tao Bao1fe1afe2018-05-01 15:56:05 -070036#include "screen_ui.h"
37
38static const std::vector<std::string> HEADERS{ "header" };
39static const std::vector<std::string> ITEMS{ "item1", "item2", "item3", "item4", "1234567890" };
Tianjie Xu5fe5eb62018-03-20 16:07:39 -070040
Tianjie Xu66dbf632018-10-11 16:54:50 -070041// TODO(xunchang) check if some draw functions are called when drawing menus.
42class MockDrawFunctions : public DrawInterface {
43 void SetColor(UIElement /* element */) const override {}
44 void DrawHighlightBar(int /* x */, int /* y */, int /* width */,
Tao Bao65815b62018-10-23 10:54:02 -070045 int /* height */) const override {}
Tianjie Xu66dbf632018-10-11 16:54:50 -070046 int DrawHorizontalRule(int /* y */) const override {
47 return 0;
Tao Bao65815b62018-10-23 10:54:02 -070048 }
Tianjie Xu66dbf632018-10-11 16:54:50 -070049 int DrawTextLine(int /* x */, int /* y */, const std::string& /* line */,
50 bool /* bold */) const override {
51 return 0;
Tao Bao65815b62018-10-23 10:54:02 -070052 }
53 void DrawSurface(const GRSurface* /* surface */, int /* sx */, int /* sy */, int /* w */,
54 int /* h */, int /* dx */, int /* dy */) const override {}
55 void DrawFill(int /* x */, int /* y */, int /* w */, int /* h */) const override {}
56 void DrawTextIcon(int /* x */, int /* y */, const GRSurface* /* surface */) const override {}
Tianjie Xu66dbf632018-10-11 16:54:50 -070057 int DrawTextLines(int /* x */, int /* y */,
58 const std::vector<std::string>& /* lines */) const override {
59 return 0;
Tao Bao65815b62018-10-23 10:54:02 -070060 }
Tianjie Xu66dbf632018-10-11 16:54:50 -070061 int DrawWrappedTextLines(int /* x */, int /* y */,
62 const std::vector<std::string>& /* lines */) const override {
63 return 0;
Tao Bao65815b62018-10-23 10:54:02 -070064 }
Tianjie Xu66dbf632018-10-11 16:54:50 -070065};
66
67class ScreenUITest : public testing::Test {
68 protected:
69 MockDrawFunctions draw_funcs_;
70};
71
72TEST_F(ScreenUITest, StartPhoneMenuSmoke) {
73 TextMenu menu(false, 10, 20, HEADERS, ITEMS, 0, 20, draw_funcs_);
Tianjie Xu5fe5eb62018-03-20 16:07:39 -070074 ASSERT_FALSE(menu.scrollable());
Tao Bao1fe1afe2018-05-01 15:56:05 -070075 ASSERT_EQ(HEADERS[0], menu.text_headers()[0]);
Tianjie Xu5fe5eb62018-03-20 16:07:39 -070076 ASSERT_EQ(5u, menu.ItemsCount());
77
78 std::string message;
79 ASSERT_FALSE(menu.ItemsOverflow(&message));
80 for (size_t i = 0; i < menu.ItemsCount(); i++) {
81 ASSERT_EQ(ITEMS[i], menu.TextItem(i));
82 }
83
84 ASSERT_EQ(0, menu.selection());
85}
86
Tianjie Xu66dbf632018-10-11 16:54:50 -070087TEST_F(ScreenUITest, StartWearMenuSmoke) {
88 TextMenu menu(true, 10, 8, HEADERS, ITEMS, 1, 20, draw_funcs_);
Tianjie Xu5fe5eb62018-03-20 16:07:39 -070089 ASSERT_TRUE(menu.scrollable());
Tao Bao1fe1afe2018-05-01 15:56:05 -070090 ASSERT_EQ(HEADERS[0], menu.text_headers()[0]);
Tianjie Xu5fe5eb62018-03-20 16:07:39 -070091 ASSERT_EQ(5u, menu.ItemsCount());
92
93 std::string message;
94 ASSERT_FALSE(menu.ItemsOverflow(&message));
95 for (size_t i = 0; i < menu.ItemsCount() - 1; i++) {
96 ASSERT_EQ(ITEMS[i], menu.TextItem(i));
97 }
98 // Test of the last item is truncated
99 ASSERT_EQ("12345678", menu.TextItem(4));
100 ASSERT_EQ(1, menu.selection());
101}
102
Tianjie Xu66dbf632018-10-11 16:54:50 -0700103TEST_F(ScreenUITest, StartPhoneMenuItemsOverflow) {
104 TextMenu menu(false, 1, 20, HEADERS, ITEMS, 0, 20, draw_funcs_);
Tianjie Xu5fe5eb62018-03-20 16:07:39 -0700105 ASSERT_FALSE(menu.scrollable());
Tianjie Xu5fe5eb62018-03-20 16:07:39 -0700106 ASSERT_EQ(1u, menu.ItemsCount());
107
108 std::string message;
109 ASSERT_FALSE(menu.ItemsOverflow(&message));
110 for (size_t i = 0; i < menu.ItemsCount(); i++) {
111 ASSERT_EQ(ITEMS[i], menu.TextItem(i));
112 }
113
114 ASSERT_EQ(0u, menu.MenuStart());
115 ASSERT_EQ(1u, menu.MenuEnd());
116}
117
Tianjie Xu66dbf632018-10-11 16:54:50 -0700118TEST_F(ScreenUITest, StartWearMenuItemsOverflow) {
119 TextMenu menu(true, 1, 20, HEADERS, ITEMS, 0, 20, draw_funcs_);
Tianjie Xu5fe5eb62018-03-20 16:07:39 -0700120 ASSERT_TRUE(menu.scrollable());
Tianjie Xu5fe5eb62018-03-20 16:07:39 -0700121 ASSERT_EQ(5u, menu.ItemsCount());
122
123 std::string message;
124 ASSERT_TRUE(menu.ItemsOverflow(&message));
125 ASSERT_EQ("Current item: 1/5", message);
126
127 for (size_t i = 0; i < menu.ItemsCount(); i++) {
128 ASSERT_EQ(ITEMS[i], menu.TextItem(i));
129 }
130
131 ASSERT_EQ(0u, menu.MenuStart());
132 ASSERT_EQ(1u, menu.MenuEnd());
133}
134
Tianjie Xu66dbf632018-10-11 16:54:50 -0700135TEST_F(ScreenUITest, PhoneMenuSelectSmoke) {
Tianjie Xu5fe5eb62018-03-20 16:07:39 -0700136 int sel = 0;
Tianjie Xu66dbf632018-10-11 16:54:50 -0700137 TextMenu menu(false, 10, 20, HEADERS, ITEMS, sel, 20, draw_funcs_);
Tianjie Xu5fe5eb62018-03-20 16:07:39 -0700138 // Mimic down button 10 times (2 * items size)
139 for (int i = 0; i < 10; i++) {
140 sel = menu.Select(++sel);
141 ASSERT_EQ(sel, menu.selection());
142
143 // Wraps the selection for unscrollable menu when it reaches the boundary.
144 int expected = (i + 1) % 5;
145 ASSERT_EQ(expected, menu.selection());
146
147 ASSERT_EQ(0u, menu.MenuStart());
148 ASSERT_EQ(5u, menu.MenuEnd());
149 }
150
151 // Mimic up button 10 times
152 for (int i = 0; i < 10; i++) {
153 sel = menu.Select(--sel);
154 ASSERT_EQ(sel, menu.selection());
155
156 int expected = (9 - i) % 5;
157 ASSERT_EQ(expected, menu.selection());
158
159 ASSERT_EQ(0u, menu.MenuStart());
160 ASSERT_EQ(5u, menu.MenuEnd());
161 }
162}
163
Tianjie Xu66dbf632018-10-11 16:54:50 -0700164TEST_F(ScreenUITest, WearMenuSelectSmoke) {
Tianjie Xu5fe5eb62018-03-20 16:07:39 -0700165 int sel = 0;
Tianjie Xu66dbf632018-10-11 16:54:50 -0700166 TextMenu menu(true, 10, 20, HEADERS, ITEMS, sel, 20, draw_funcs_);
Tianjie Xu5fe5eb62018-03-20 16:07:39 -0700167 // Mimic pressing down button 10 times (2 * items size)
168 for (int i = 0; i < 10; i++) {
169 sel = menu.Select(++sel);
170 ASSERT_EQ(sel, menu.selection());
171
172 // Stops the selection at the boundary if the menu is scrollable.
173 int expected = std::min(i + 1, 4);
174 ASSERT_EQ(expected, menu.selection());
175
176 ASSERT_EQ(0u, menu.MenuStart());
177 ASSERT_EQ(5u, menu.MenuEnd());
178 }
179
180 // Mimic pressing up button 10 times
181 for (int i = 0; i < 10; i++) {
182 sel = menu.Select(--sel);
183 ASSERT_EQ(sel, menu.selection());
184
185 int expected = std::max(3 - i, 0);
186 ASSERT_EQ(expected, menu.selection());
187
188 ASSERT_EQ(0u, menu.MenuStart());
189 ASSERT_EQ(5u, menu.MenuEnd());
190 }
191}
192
Tianjie Xu66dbf632018-10-11 16:54:50 -0700193TEST_F(ScreenUITest, WearMenuSelectItemsOverflow) {
Tianjie Xu5fe5eb62018-03-20 16:07:39 -0700194 int sel = 1;
Tianjie Xu66dbf632018-10-11 16:54:50 -0700195 TextMenu menu(true, 3, 20, HEADERS, ITEMS, sel, 20, draw_funcs_);
Tianjie Xu5fe5eb62018-03-20 16:07:39 -0700196 ASSERT_EQ(5u, menu.ItemsCount());
197
198 // Scroll the menu to the end, and check the start & end of menu.
199 for (int i = 0; i < 3; i++) {
200 sel = menu.Select(++sel);
201 ASSERT_EQ(i + 2, sel);
202 ASSERT_EQ(static_cast<size_t>(i), menu.MenuStart());
203 ASSERT_EQ(static_cast<size_t>(i + 3), menu.MenuEnd());
204 }
205
206 // Press down button one more time won't change the MenuStart() and MenuEnd().
207 sel = menu.Select(++sel);
208 ASSERT_EQ(4, sel);
209 ASSERT_EQ(2u, menu.MenuStart());
210 ASSERT_EQ(5u, menu.MenuEnd());
211
212 // Scroll the menu to the top.
213 // The expected menu sel, start & ends are:
214 // sel 3, start 2, end 5
215 // sel 2, start 2, end 5
216 // sel 1, start 1, end 4
217 // sel 0, start 0, end 3
218 for (int i = 0; i < 4; i++) {
219 sel = menu.Select(--sel);
220 ASSERT_EQ(3 - i, sel);
221 ASSERT_EQ(static_cast<size_t>(std::min(3 - i, 2)), menu.MenuStart());
222 ASSERT_EQ(static_cast<size_t>(std::min(6 - i, 5)), menu.MenuEnd());
223 }
224
225 // Press up button one more time won't change the MenuStart() and MenuEnd().
226 sel = menu.Select(--sel);
227 ASSERT_EQ(0, sel);
228 ASSERT_EQ(0u, menu.MenuStart());
229 ASSERT_EQ(3u, menu.MenuEnd());
230}
Tao Bao6cd81682018-05-03 21:53:11 -0700231
Tianjie Xub99e6062018-10-16 15:13:09 -0700232TEST_F(ScreenUITest, GraphicMenuSelection) {
Tao Bao44820ac2018-10-30 23:34:50 -0700233 auto header = GRSurface::Create(50, 50, 50, 1, 50 * 50);
234 auto item = GRSurface::Create(50, 50, 50, 1, 50 * 50);
235 std::vector<GRSurface*> items = {
236 item.get(),
237 item.get(),
238 item.get(),
239 };
240 GraphicMenu menu(header.get(), items, 0, draw_funcs_);
Tianjie Xub99e6062018-10-16 15:13:09 -0700241
242 ASSERT_EQ(0, menu.selection());
243
244 int sel = 0;
245 for (int i = 0; i < 3; i++) {
246 sel = menu.Select(++sel);
247 ASSERT_EQ((i + 1) % 3, sel);
248 ASSERT_EQ(sel, menu.selection());
249 }
250
251 sel = 0;
252 for (int i = 0; i < 3; i++) {
253 sel = menu.Select(--sel);
254 ASSERT_EQ(2 - i, sel);
255 ASSERT_EQ(sel, menu.selection());
256 }
257}
258
259TEST_F(ScreenUITest, GraphicMenuValidate) {
Tao Bao44820ac2018-10-30 23:34:50 -0700260 auto header = GRSurface::Create(50, 50, 50, 1, 50 * 50);
261 auto item = GRSurface::Create(50, 50, 50, 1, 50 * 50);
262 std::vector<GRSurface*> items = {
263 item.get(),
264 item.get(),
265 item.get(),
266 };
Tianjie Xub99e6062018-10-16 15:13:09 -0700267
Tao Bao44820ac2018-10-30 23:34:50 -0700268 ASSERT_TRUE(GraphicMenu::Validate(200, 200, header.get(), items));
Tianjie Xub99e6062018-10-16 15:13:09 -0700269
270 // Menu exceeds the horizontal boundary.
Tao Bao44820ac2018-10-30 23:34:50 -0700271 auto wide_surface = GRSurface::Create(300, 50, 300, 1, 300 * 50);
272 ASSERT_FALSE(GraphicMenu::Validate(299, 200, wide_surface.get(), items));
Tianjie Xub99e6062018-10-16 15:13:09 -0700273
274 // Menu exceeds the vertical boundary.
Tao Bao44820ac2018-10-30 23:34:50 -0700275 items.push_back(item.get());
276 ASSERT_FALSE(GraphicMenu::Validate(200, 249, header.get(), items));
Tianjie Xub99e6062018-10-16 15:13:09 -0700277}
278
Tao Bao6cd81682018-05-03 21:53:11 -0700279static constexpr int kMagicAction = 101;
280
281enum class KeyCode : int {
282 TIMEOUT = -1,
283 NO_OP = 0,
284 UP = 1,
285 DOWN = 2,
286 ENTER = 3,
287 MAGIC = 1001,
288 LAST,
289};
290
291static const std::map<KeyCode, int> kKeyMapping{
292 // clang-format off
293 { KeyCode::NO_OP, Device::kNoAction },
294 { KeyCode::UP, Device::kHighlightUp },
295 { KeyCode::DOWN, Device::kHighlightDown },
296 { KeyCode::ENTER, Device::kInvokeItem },
297 { KeyCode::MAGIC, kMagicAction },
298 // clang-format on
299};
300
301class TestableScreenRecoveryUI : public ScreenRecoveryUI {
302 public:
303 int WaitKey() override;
304
305 void SetKeyBuffer(const std::vector<KeyCode>& buffer);
306
307 int KeyHandler(int key, bool visible) const;
308
Tao Bao152e0eb2018-05-13 00:34:45 -0700309 // The following functions expose the protected members for test purpose.
310 void RunLoadAnimation() {
311 LoadAnimation();
312 }
313
314 size_t GetLoopFrames() const {
315 return loop_frames;
316 }
317
318 size_t GetIntroFrames() const {
319 return intro_frames;
320 }
321
Tao Bao6cd81682018-05-03 21:53:11 -0700322 bool GetRtlLocale() const {
323 return rtl_locale_;
324 }
325
326 private:
327 std::vector<KeyCode> key_buffer_;
328 size_t key_buffer_index_;
329};
330
331void TestableScreenRecoveryUI::SetKeyBuffer(const std::vector<KeyCode>& buffer) {
332 key_buffer_ = buffer;
333 key_buffer_index_ = 0;
334}
335
336int TestableScreenRecoveryUI::KeyHandler(int key, bool) const {
337 KeyCode key_code = static_cast<KeyCode>(key);
338 if (kKeyMapping.find(key_code) != kKeyMapping.end()) {
339 return kKeyMapping.at(key_code);
340 }
341 return Device::kNoAction;
342}
343
344int TestableScreenRecoveryUI::WaitKey() {
Jerry Zhangb76af932018-05-22 12:08:35 -0700345 if (IsKeyInterrupted()) {
346 return static_cast<int>(RecoveryUI::KeyError::INTERRUPTED);
347 }
348
Tao Bao6cd81682018-05-03 21:53:11 -0700349 CHECK_LT(key_buffer_index_, key_buffer_.size());
350 return static_cast<int>(key_buffer_[key_buffer_index_++]);
351}
352
353class ScreenRecoveryUITest : public ::testing::Test {
354 protected:
355 const std::string kTestLocale = "en-US";
356 const std::string kTestRtlLocale = "ar";
Tao Bao347a6592018-05-08 15:58:29 -0700357 const std::string kTestRtlLocaleWithSuffix = "ar-EG";
Tao Bao6cd81682018-05-03 21:53:11 -0700358
359 void SetUp() override {
Tao Bao51f16ec2018-06-04 11:40:20 -0700360 has_graphics_ = gr_init() == 0;
361 gr_exit();
362
363 if (has_graphics_) {
364 ui_ = std::make_unique<TestableScreenRecoveryUI>();
365 }
Tao Bao6cd81682018-05-03 21:53:11 -0700366
Tao Bao152e0eb2018-05-13 00:34:45 -0700367 testdata_dir_ = from_testdata_base("");
368 Paths::Get().set_resource_dir(testdata_dir_);
369 res_set_resource_dir(testdata_dir_);
Tao Bao6cd81682018-05-03 21:53:11 -0700370 }
371
Tao Bao51f16ec2018-06-04 11:40:20 -0700372 bool has_graphics_;
Tao Bao6cd81682018-05-03 21:53:11 -0700373 std::unique_ptr<TestableScreenRecoveryUI> ui_;
Tao Bao152e0eb2018-05-13 00:34:45 -0700374 std::string testdata_dir_;
Tao Bao6cd81682018-05-03 21:53:11 -0700375};
376
Tao Bao51f16ec2018-06-04 11:40:20 -0700377#define RETURN_IF_NO_GRAPHICS \
378 do { \
379 if (!has_graphics_) { \
380 GTEST_LOG_(INFO) << "Test skipped due to no available graphics device"; \
381 return; \
382 } \
383 } while (false)
384
Tao Bao6cd81682018-05-03 21:53:11 -0700385TEST_F(ScreenRecoveryUITest, Init) {
Tao Bao51f16ec2018-06-04 11:40:20 -0700386 RETURN_IF_NO_GRAPHICS;
387
Tao Bao26ea9592018-05-09 16:32:02 -0700388 ASSERT_TRUE(ui_->Init(kTestLocale));
Tao Bao6cd81682018-05-03 21:53:11 -0700389 ASSERT_EQ(kTestLocale, ui_->GetLocale());
390 ASSERT_FALSE(ui_->GetRtlLocale());
391 ASSERT_FALSE(ui_->IsTextVisible());
392 ASSERT_FALSE(ui_->WasTextEverVisible());
393}
394
Tao Bao94371fd2018-06-06 07:38:54 -0700395TEST_F(ScreenRecoveryUITest, dtor_NotCallingInit) {
396 ui_.reset();
397 ASSERT_FALSE(ui_);
398}
399
Tao Bao6cd81682018-05-03 21:53:11 -0700400TEST_F(ScreenRecoveryUITest, ShowText) {
Tao Bao51f16ec2018-06-04 11:40:20 -0700401 RETURN_IF_NO_GRAPHICS;
402
Tao Bao26ea9592018-05-09 16:32:02 -0700403 ASSERT_TRUE(ui_->Init(kTestLocale));
Tao Bao6cd81682018-05-03 21:53:11 -0700404 ASSERT_FALSE(ui_->IsTextVisible());
405 ui_->ShowText(true);
406 ASSERT_TRUE(ui_->IsTextVisible());
407 ASSERT_TRUE(ui_->WasTextEverVisible());
408
409 ui_->ShowText(false);
410 ASSERT_FALSE(ui_->IsTextVisible());
411 ASSERT_TRUE(ui_->WasTextEverVisible());
412}
413
414TEST_F(ScreenRecoveryUITest, RtlLocale) {
Tao Bao51f16ec2018-06-04 11:40:20 -0700415 RETURN_IF_NO_GRAPHICS;
416
Tao Bao6cd81682018-05-03 21:53:11 -0700417 ASSERT_TRUE(ui_->Init(kTestRtlLocale));
418 ASSERT_TRUE(ui_->GetRtlLocale());
Tao Bao26ea9592018-05-09 16:32:02 -0700419}
Tao Bao6cd81682018-05-03 21:53:11 -0700420
Tao Bao26ea9592018-05-09 16:32:02 -0700421TEST_F(ScreenRecoveryUITest, RtlLocaleWithSuffix) {
Tao Bao51f16ec2018-06-04 11:40:20 -0700422 RETURN_IF_NO_GRAPHICS;
423
Tao Bao6cd81682018-05-03 21:53:11 -0700424 ASSERT_TRUE(ui_->Init(kTestRtlLocaleWithSuffix));
425 ASSERT_TRUE(ui_->GetRtlLocale());
426}
427
428TEST_F(ScreenRecoveryUITest, ShowMenu) {
Tao Bao51f16ec2018-06-04 11:40:20 -0700429 RETURN_IF_NO_GRAPHICS;
430
Tao Bao26ea9592018-05-09 16:32:02 -0700431 ASSERT_TRUE(ui_->Init(kTestLocale));
Tao Bao6cd81682018-05-03 21:53:11 -0700432 ui_->SetKeyBuffer({
433 KeyCode::UP,
434 KeyCode::DOWN,
435 KeyCode::UP,
436 KeyCode::DOWN,
437 KeyCode::ENTER,
438 });
439 ASSERT_EQ(3u, ui_->ShowMenu(HEADERS, ITEMS, 3, true,
440 std::bind(&TestableScreenRecoveryUI::KeyHandler, ui_.get(),
441 std::placeholders::_1, std::placeholders::_2)));
442
443 ui_->SetKeyBuffer({
444 KeyCode::UP,
445 KeyCode::UP,
446 KeyCode::NO_OP,
447 KeyCode::NO_OP,
448 KeyCode::UP,
449 KeyCode::ENTER,
450 });
451 ASSERT_EQ(2u, ui_->ShowMenu(HEADERS, ITEMS, 0, true,
452 std::bind(&TestableScreenRecoveryUI::KeyHandler, ui_.get(),
453 std::placeholders::_1, std::placeholders::_2)));
454}
455
456TEST_F(ScreenRecoveryUITest, ShowMenu_NotMenuOnly) {
Tao Bao51f16ec2018-06-04 11:40:20 -0700457 RETURN_IF_NO_GRAPHICS;
458
Tao Bao26ea9592018-05-09 16:32:02 -0700459 ASSERT_TRUE(ui_->Init(kTestLocale));
Tao Bao6cd81682018-05-03 21:53:11 -0700460 ui_->SetKeyBuffer({
461 KeyCode::MAGIC,
462 });
463 ASSERT_EQ(static_cast<size_t>(kMagicAction),
464 ui_->ShowMenu(HEADERS, ITEMS, 3, false,
465 std::bind(&TestableScreenRecoveryUI::KeyHandler, ui_.get(),
466 std::placeholders::_1, std::placeholders::_2)));
467}
468
469TEST_F(ScreenRecoveryUITest, ShowMenu_TimedOut) {
Tao Bao51f16ec2018-06-04 11:40:20 -0700470 RETURN_IF_NO_GRAPHICS;
471
Tao Bao26ea9592018-05-09 16:32:02 -0700472 ASSERT_TRUE(ui_->Init(kTestLocale));
Tao Bao6cd81682018-05-03 21:53:11 -0700473 ui_->SetKeyBuffer({
474 KeyCode::TIMEOUT,
475 });
Jerry Zhangb76af932018-05-22 12:08:35 -0700476 ASSERT_EQ(static_cast<size_t>(RecoveryUI::KeyError::TIMED_OUT),
477 ui_->ShowMenu(HEADERS, ITEMS, 3, true, nullptr));
Tao Bao6cd81682018-05-03 21:53:11 -0700478}
479
480TEST_F(ScreenRecoveryUITest, ShowMenu_TimedOut_TextWasEverVisible) {
Tao Bao51f16ec2018-06-04 11:40:20 -0700481 RETURN_IF_NO_GRAPHICS;
482
Tao Bao26ea9592018-05-09 16:32:02 -0700483 ASSERT_TRUE(ui_->Init(kTestLocale));
Tao Bao6cd81682018-05-03 21:53:11 -0700484 ui_->ShowText(true);
485 ui_->ShowText(false);
486 ASSERT_TRUE(ui_->WasTextEverVisible());
487
488 ui_->SetKeyBuffer({
489 KeyCode::TIMEOUT,
490 KeyCode::DOWN,
491 KeyCode::ENTER,
492 });
493 ASSERT_EQ(4u, ui_->ShowMenu(HEADERS, ITEMS, 3, true,
494 std::bind(&TestableScreenRecoveryUI::KeyHandler, ui_.get(),
495 std::placeholders::_1, std::placeholders::_2)));
496}
Tao Bao152e0eb2018-05-13 00:34:45 -0700497
Jerry Zhangb76af932018-05-22 12:08:35 -0700498TEST_F(ScreenRecoveryUITest, ShowMenuWithInterrupt) {
499 RETURN_IF_NO_GRAPHICS;
500
501 ASSERT_TRUE(ui_->Init(kTestLocale));
502 ui_->SetKeyBuffer({
503 KeyCode::UP,
504 KeyCode::DOWN,
505 KeyCode::UP,
506 KeyCode::DOWN,
507 KeyCode::ENTER,
508 });
509
510 ui_->InterruptKey();
511 ASSERT_EQ(static_cast<size_t>(RecoveryUI::KeyError::INTERRUPTED),
512 ui_->ShowMenu(HEADERS, ITEMS, 3, true,
513 std::bind(&TestableScreenRecoveryUI::KeyHandler, ui_.get(),
514 std::placeholders::_1, std::placeholders::_2)));
515
516 ui_->SetKeyBuffer({
517 KeyCode::UP,
518 KeyCode::UP,
519 KeyCode::NO_OP,
520 KeyCode::NO_OP,
521 KeyCode::UP,
522 KeyCode::ENTER,
523 });
524 ASSERT_EQ(static_cast<size_t>(RecoveryUI::KeyError::INTERRUPTED),
525 ui_->ShowMenu(HEADERS, ITEMS, 0, true,
526 std::bind(&TestableScreenRecoveryUI::KeyHandler, ui_.get(),
527 std::placeholders::_1, std::placeholders::_2)));
528}
529
Tao Bao152e0eb2018-05-13 00:34:45 -0700530TEST_F(ScreenRecoveryUITest, LoadAnimation) {
Tao Bao51f16ec2018-06-04 11:40:20 -0700531 RETURN_IF_NO_GRAPHICS;
532
Tao Bao26ea9592018-05-09 16:32:02 -0700533 ASSERT_TRUE(ui_->Init(kTestLocale));
Tao Bao152e0eb2018-05-13 00:34:45 -0700534 // Make a few copies of loop00000.png from testdata.
535 std::string image_data;
536 ASSERT_TRUE(android::base::ReadFileToString(testdata_dir_ + "/loop00000.png", &image_data));
537
538 std::vector<std::string> tempfiles;
539 TemporaryDir resource_dir;
540 for (const auto& name : { "00002", "00100", "00050" }) {
541 tempfiles.push_back(android::base::StringPrintf("%s/loop%s.png", resource_dir.path, name));
542 ASSERT_TRUE(android::base::WriteStringToFile(image_data, tempfiles.back()));
543 }
544 for (const auto& name : { "00", "01" }) {
545 tempfiles.push_back(android::base::StringPrintf("%s/intro%s.png", resource_dir.path, name));
546 ASSERT_TRUE(android::base::WriteStringToFile(image_data, tempfiles.back()));
547 }
548 Paths::Get().set_resource_dir(resource_dir.path);
549
550 ui_->RunLoadAnimation();
551
552 ASSERT_EQ(2u, ui_->GetIntroFrames());
553 ASSERT_EQ(3u, ui_->GetLoopFrames());
554
555 for (const auto& name : tempfiles) {
556 ASSERT_EQ(0, unlink(name.c_str()));
557 }
558}
559
560TEST_F(ScreenRecoveryUITest, LoadAnimation_MissingAnimation) {
Tao Bao51f16ec2018-06-04 11:40:20 -0700561 RETURN_IF_NO_GRAPHICS;
562
Tao Bao26ea9592018-05-09 16:32:02 -0700563 ASSERT_TRUE(ui_->Init(kTestLocale));
Tao Baob1c5b622018-07-12 11:49:05 -0700564 // We need a dir that doesn't contain any animation. However, using TemporaryDir will give
565 // leftovers since this is a death test where TemporaryDir::~TemporaryDir() won't be called.
566 Paths::Get().set_resource_dir("/proc/self");
Tao Bao42be0d42018-06-05 14:03:34 -0700567
568 ::testing::FLAGS_gtest_death_test_style = "threadsafe";
Tao Bao152e0eb2018-05-13 00:34:45 -0700569 ASSERT_EXIT(ui_->RunLoadAnimation(), ::testing::KilledBySignal(SIGABRT), "");
570}
Tao Bao51f16ec2018-06-04 11:40:20 -0700571
572#undef RETURN_IF_NO_GRAPHICS