Merge "tests: Add tests for ScreenRecoveryUI." am: 8c6f699b36
am: ca88c67135
Change-Id: I238b8b412046c883863828d2b7578d51dadef9e0
This commit is contained in:
+11
-10
@@ -169,19 +169,20 @@ LOCAL_STATIC_LIBRARIES := \
|
|||||||
LOCAL_STATIC_LIBRARIES += \
|
LOCAL_STATIC_LIBRARIES += \
|
||||||
librecovery \
|
librecovery \
|
||||||
$(TARGET_RECOVERY_UI_LIB) \
|
$(TARGET_RECOVERY_UI_LIB) \
|
||||||
libverifier \
|
|
||||||
libbootloader_message \
|
|
||||||
libfs_mgr \
|
|
||||||
libext4_utils \
|
|
||||||
libsparse \
|
|
||||||
libziparchive \
|
|
||||||
libotautil \
|
|
||||||
libminadbd \
|
|
||||||
libasyncio \
|
|
||||||
libfusesideload \
|
|
||||||
librecovery_ui \
|
librecovery_ui \
|
||||||
libminui \
|
libminui \
|
||||||
|
libverifier \
|
||||||
|
libbootloader_message \
|
||||||
|
libfusesideload \
|
||||||
|
libminadbd \
|
||||||
|
libotautil \
|
||||||
|
libasyncio \
|
||||||
|
libbatterymonitor \
|
||||||
|
libfs_mgr \
|
||||||
|
libext4_utils \
|
||||||
libpng \
|
libpng \
|
||||||
|
libsparse \
|
||||||
|
libziparchive \
|
||||||
libcrypto_utils \
|
libcrypto_utils \
|
||||||
libcrypto \
|
libcrypto \
|
||||||
libvintf_recovery \
|
libvintf_recovery \
|
||||||
|
|||||||
@@ -82,3 +82,6 @@ class PngHandler {
|
|||||||
// After initialization, we'll keep the file pointer open before destruction of PngHandler.
|
// After initialization, we'll keep the file pointer open before destruction of PngHandler.
|
||||||
std::unique_ptr<FILE, decltype(&fclose)> png_fp_{ nullptr, fclose };
|
std::unique_ptr<FILE, decltype(&fclose)> png_fp_{ nullptr, fclose };
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Overrides the default resource dir, for testing purpose.
|
||||||
|
void res_set_resource_dir(const std::string&);
|
||||||
|
|||||||
+7
-2
@@ -32,7 +32,6 @@
|
|||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#include <android-base/stringprintf.h>
|
|
||||||
#include <android-base/strings.h>
|
#include <android-base/strings.h>
|
||||||
#include <png.h>
|
#include <png.h>
|
||||||
|
|
||||||
@@ -40,6 +39,8 @@
|
|||||||
|
|
||||||
#define SURFACE_DATA_ALIGNMENT 8
|
#define SURFACE_DATA_ALIGNMENT 8
|
||||||
|
|
||||||
|
static std::string g_resource_dir{ "/res/images" };
|
||||||
|
|
||||||
static GRSurface* malloc_surface(size_t data_size) {
|
static GRSurface* malloc_surface(size_t data_size) {
|
||||||
size_t size = sizeof(GRSurface) + data_size + SURFACE_DATA_ALIGNMENT;
|
size_t size = sizeof(GRSurface) + data_size + SURFACE_DATA_ALIGNMENT;
|
||||||
unsigned char* temp = static_cast<unsigned char*>(malloc(size));
|
unsigned char* temp = static_cast<unsigned char*>(malloc(size));
|
||||||
@@ -51,7 +52,7 @@ static GRSurface* malloc_surface(size_t data_size) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
PngHandler::PngHandler(const std::string& name) {
|
PngHandler::PngHandler(const std::string& name) {
|
||||||
std::string res_path = android::base::StringPrintf("/res/images/%s.png", name.c_str());
|
std::string res_path = g_resource_dir + "/" + name + ".png";
|
||||||
png_fp_.reset(fopen(res_path.c_str(), "rbe"));
|
png_fp_.reset(fopen(res_path.c_str(), "rbe"));
|
||||||
// Try to read from |name| if the resource path does not work.
|
// Try to read from |name| if the resource path does not work.
|
||||||
if (!png_fp_) {
|
if (!png_fp_) {
|
||||||
@@ -340,6 +341,10 @@ int res_create_alpha_surface(const char* name, GRSurface** pSurface) {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void res_set_resource_dir(const std::string& dirname) {
|
||||||
|
g_resource_dir = dirname;
|
||||||
|
}
|
||||||
|
|
||||||
// This function tests if a locale string stored in PNG (prefix) matches
|
// This function tests if a locale string stored in PNG (prefix) matches
|
||||||
// the locale string provided by the system (locale).
|
// the locale string provided by the system (locale).
|
||||||
bool matches_locale(const std::string& prefix, const std::string& locale) {
|
bool matches_locale(const std::string& prefix, const std::string& locale) {
|
||||||
|
|||||||
@@ -48,6 +48,13 @@ class Paths {
|
|||||||
last_command_file_ = last_command_file;
|
last_command_file_ = last_command_file;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::string resource_dir() const {
|
||||||
|
return resource_dir_;
|
||||||
|
}
|
||||||
|
void set_resource_dir(const std::string& resource_dir) {
|
||||||
|
resource_dir_ = resource_dir;
|
||||||
|
}
|
||||||
|
|
||||||
std::string stash_directory_base() const {
|
std::string stash_directory_base() const {
|
||||||
return stash_directory_base_;
|
return stash_directory_base_;
|
||||||
}
|
}
|
||||||
@@ -85,6 +92,9 @@ class Paths {
|
|||||||
// Path to the last command file.
|
// Path to the last command file.
|
||||||
std::string last_command_file_;
|
std::string last_command_file_;
|
||||||
|
|
||||||
|
// Path to the resource dir;
|
||||||
|
std::string resource_dir_;
|
||||||
|
|
||||||
// Path to the base directory to write stashes during update.
|
// Path to the base directory to write stashes during update.
|
||||||
std::string stash_directory_base_;
|
std::string stash_directory_base_;
|
||||||
|
|
||||||
|
|||||||
@@ -19,6 +19,7 @@
|
|||||||
constexpr const char kDefaultCacheLogDirectory[] = "/cache/recovery";
|
constexpr const char kDefaultCacheLogDirectory[] = "/cache/recovery";
|
||||||
constexpr const char kDefaultCacheTempSource[] = "/cache/saved.file";
|
constexpr const char kDefaultCacheTempSource[] = "/cache/saved.file";
|
||||||
constexpr const char kDefaultLastCommandFile[] = "/cache/recovery/last_command";
|
constexpr const char kDefaultLastCommandFile[] = "/cache/recovery/last_command";
|
||||||
|
constexpr const char kDefaultResourceDirectory[] = "/res/images";
|
||||||
constexpr const char kDefaultStashDirectoryBase[] = "/cache/recovery";
|
constexpr const char kDefaultStashDirectoryBase[] = "/cache/recovery";
|
||||||
constexpr const char kDefaultTemporaryInstallFile[] = "/tmp/last_install";
|
constexpr const char kDefaultTemporaryInstallFile[] = "/tmp/last_install";
|
||||||
constexpr const char kDefaultTemporaryLogFile[] = "/tmp/recovery.log";
|
constexpr const char kDefaultTemporaryLogFile[] = "/tmp/recovery.log";
|
||||||
@@ -32,6 +33,7 @@ Paths::Paths()
|
|||||||
: cache_log_directory_(kDefaultCacheLogDirectory),
|
: cache_log_directory_(kDefaultCacheLogDirectory),
|
||||||
cache_temp_source_(kDefaultCacheTempSource),
|
cache_temp_source_(kDefaultCacheTempSource),
|
||||||
last_command_file_(kDefaultLastCommandFile),
|
last_command_file_(kDefaultLastCommandFile),
|
||||||
|
resource_dir_(kDefaultResourceDirectory),
|
||||||
stash_directory_base_(kDefaultStashDirectoryBase),
|
stash_directory_base_(kDefaultStashDirectoryBase),
|
||||||
temporary_install_file_(kDefaultTemporaryInstallFile),
|
temporary_install_file_(kDefaultTemporaryInstallFile),
|
||||||
temporary_log_file_(kDefaultTemporaryLogFile) {}
|
temporary_log_file_(kDefaultTemporaryLogFile) {}
|
||||||
|
|||||||
+4
-2
@@ -41,9 +41,10 @@
|
|||||||
#include <android-base/properties.h>
|
#include <android-base/properties.h>
|
||||||
#include <android-base/stringprintf.h>
|
#include <android-base/stringprintf.h>
|
||||||
#include <android-base/strings.h>
|
#include <android-base/strings.h>
|
||||||
#include <minui/minui.h>
|
|
||||||
|
|
||||||
#include "device.h"
|
#include "device.h"
|
||||||
|
#include "minui/minui.h"
|
||||||
|
#include "otautil/paths.h"
|
||||||
#include "ui.h"
|
#include "ui.h"
|
||||||
|
|
||||||
// Return the current time as a double (including fractions of a second).
|
// Return the current time as a double (including fractions of a second).
|
||||||
@@ -756,7 +757,8 @@ std::string ScreenRecoveryUI::GetLocale() const {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void ScreenRecoveryUI::LoadAnimation() {
|
void ScreenRecoveryUI::LoadAnimation() {
|
||||||
std::unique_ptr<DIR, decltype(&closedir)> dir(opendir("/res/images"), closedir);
|
std::unique_ptr<DIR, decltype(&closedir)> dir(opendir(Paths::Get().resource_dir().c_str()),
|
||||||
|
closedir);
|
||||||
dirent* de;
|
dirent* de;
|
||||||
std::vector<std::string> intro_frame_names;
|
std::vector<std::string> intro_frame_names;
|
||||||
std::vector<std::string> loop_frame_names;
|
std::vector<std::string> loop_frame_names;
|
||||||
|
|||||||
@@ -27,6 +27,7 @@ LOCAL_STATIC_LIBRARIES := \
|
|||||||
libminui \
|
libminui \
|
||||||
libotautil \
|
libotautil \
|
||||||
libupdater \
|
libupdater \
|
||||||
|
libpng \
|
||||||
libziparchive \
|
libziparchive \
|
||||||
libutils \
|
libutils \
|
||||||
libz \
|
libz \
|
||||||
|
|||||||
Vendored
BIN
Binary file not shown.
|
After Width: | Height: | Size: 24 KiB |
Vendored
BIN
Binary file not shown.
|
After Width: | Height: | Size: 5.8 KiB |
@@ -16,11 +16,19 @@
|
|||||||
|
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
|
|
||||||
|
#include <functional>
|
||||||
|
#include <map>
|
||||||
|
#include <memory>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
|
#include <android-base/logging.h>
|
||||||
#include <gtest/gtest.h>
|
#include <gtest/gtest.h>
|
||||||
|
|
||||||
|
#include "common/test_constants.h"
|
||||||
|
#include "device.h"
|
||||||
|
#include "otautil/paths.h"
|
||||||
|
#include "private/resources.h"
|
||||||
#include "screen_ui.h"
|
#include "screen_ui.h"
|
||||||
|
|
||||||
static const std::vector<std::string> HEADERS{ "header" };
|
static const std::vector<std::string> HEADERS{ "header" };
|
||||||
@@ -185,3 +193,162 @@ TEST(ScreenUITest, WearMenuSelectItemsOverflow) {
|
|||||||
ASSERT_EQ(0u, menu.MenuStart());
|
ASSERT_EQ(0u, menu.MenuStart());
|
||||||
ASSERT_EQ(3u, menu.MenuEnd());
|
ASSERT_EQ(3u, menu.MenuEnd());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static constexpr int kMagicAction = 101;
|
||||||
|
|
||||||
|
enum class KeyCode : int {
|
||||||
|
TIMEOUT = -1,
|
||||||
|
NO_OP = 0,
|
||||||
|
UP = 1,
|
||||||
|
DOWN = 2,
|
||||||
|
ENTER = 3,
|
||||||
|
MAGIC = 1001,
|
||||||
|
LAST,
|
||||||
|
};
|
||||||
|
|
||||||
|
static const std::map<KeyCode, int> kKeyMapping{
|
||||||
|
// clang-format off
|
||||||
|
{ KeyCode::NO_OP, Device::kNoAction },
|
||||||
|
{ KeyCode::UP, Device::kHighlightUp },
|
||||||
|
{ KeyCode::DOWN, Device::kHighlightDown },
|
||||||
|
{ KeyCode::ENTER, Device::kInvokeItem },
|
||||||
|
{ KeyCode::MAGIC, kMagicAction },
|
||||||
|
// clang-format on
|
||||||
|
};
|
||||||
|
|
||||||
|
class TestableScreenRecoveryUI : public ScreenRecoveryUI {
|
||||||
|
public:
|
||||||
|
int WaitKey() override;
|
||||||
|
|
||||||
|
void SetKeyBuffer(const std::vector<KeyCode>& buffer);
|
||||||
|
|
||||||
|
int KeyHandler(int key, bool visible) const;
|
||||||
|
|
||||||
|
bool GetRtlLocale() const {
|
||||||
|
return rtl_locale_;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::vector<KeyCode> key_buffer_;
|
||||||
|
size_t key_buffer_index_;
|
||||||
|
};
|
||||||
|
|
||||||
|
void TestableScreenRecoveryUI::SetKeyBuffer(const std::vector<KeyCode>& buffer) {
|
||||||
|
key_buffer_ = buffer;
|
||||||
|
key_buffer_index_ = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int TestableScreenRecoveryUI::KeyHandler(int key, bool) const {
|
||||||
|
KeyCode key_code = static_cast<KeyCode>(key);
|
||||||
|
if (kKeyMapping.find(key_code) != kKeyMapping.end()) {
|
||||||
|
return kKeyMapping.at(key_code);
|
||||||
|
}
|
||||||
|
return Device::kNoAction;
|
||||||
|
}
|
||||||
|
|
||||||
|
int TestableScreenRecoveryUI::WaitKey() {
|
||||||
|
CHECK_LT(key_buffer_index_, key_buffer_.size());
|
||||||
|
return static_cast<int>(key_buffer_[key_buffer_index_++]);
|
||||||
|
}
|
||||||
|
|
||||||
|
class ScreenRecoveryUITest : public ::testing::Test {
|
||||||
|
protected:
|
||||||
|
const std::string kTestLocale = "en-US";
|
||||||
|
const std::string kTestRtlLocale = "ar";
|
||||||
|
const std::string kTestRtlLocaleWithSuffix = "ar_EG";
|
||||||
|
|
||||||
|
void SetUp() override {
|
||||||
|
ui_ = std::make_unique<TestableScreenRecoveryUI>();
|
||||||
|
|
||||||
|
std::string testdata_dir = from_testdata_base("");
|
||||||
|
Paths::Get().set_resource_dir(testdata_dir);
|
||||||
|
res_set_resource_dir(testdata_dir);
|
||||||
|
|
||||||
|
ASSERT_TRUE(ui_->Init(kTestLocale));
|
||||||
|
}
|
||||||
|
|
||||||
|
std::unique_ptr<TestableScreenRecoveryUI> ui_;
|
||||||
|
};
|
||||||
|
|
||||||
|
TEST_F(ScreenRecoveryUITest, Init) {
|
||||||
|
ASSERT_EQ(kTestLocale, ui_->GetLocale());
|
||||||
|
ASSERT_FALSE(ui_->GetRtlLocale());
|
||||||
|
ASSERT_FALSE(ui_->IsTextVisible());
|
||||||
|
ASSERT_FALSE(ui_->WasTextEverVisible());
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(ScreenRecoveryUITest, ShowText) {
|
||||||
|
ASSERT_FALSE(ui_->IsTextVisible());
|
||||||
|
ui_->ShowText(true);
|
||||||
|
ASSERT_TRUE(ui_->IsTextVisible());
|
||||||
|
ASSERT_TRUE(ui_->WasTextEverVisible());
|
||||||
|
|
||||||
|
ui_->ShowText(false);
|
||||||
|
ASSERT_FALSE(ui_->IsTextVisible());
|
||||||
|
ASSERT_TRUE(ui_->WasTextEverVisible());
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(ScreenRecoveryUITest, RtlLocale) {
|
||||||
|
ASSERT_TRUE(ui_->Init(kTestRtlLocale));
|
||||||
|
ASSERT_TRUE(ui_->GetRtlLocale());
|
||||||
|
|
||||||
|
ASSERT_TRUE(ui_->Init(kTestRtlLocaleWithSuffix));
|
||||||
|
ASSERT_TRUE(ui_->GetRtlLocale());
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(ScreenRecoveryUITest, ShowMenu) {
|
||||||
|
ui_->SetKeyBuffer({
|
||||||
|
KeyCode::UP,
|
||||||
|
KeyCode::DOWN,
|
||||||
|
KeyCode::UP,
|
||||||
|
KeyCode::DOWN,
|
||||||
|
KeyCode::ENTER,
|
||||||
|
});
|
||||||
|
ASSERT_EQ(3u, ui_->ShowMenu(HEADERS, ITEMS, 3, true,
|
||||||
|
std::bind(&TestableScreenRecoveryUI::KeyHandler, ui_.get(),
|
||||||
|
std::placeholders::_1, std::placeholders::_2)));
|
||||||
|
|
||||||
|
ui_->SetKeyBuffer({
|
||||||
|
KeyCode::UP,
|
||||||
|
KeyCode::UP,
|
||||||
|
KeyCode::NO_OP,
|
||||||
|
KeyCode::NO_OP,
|
||||||
|
KeyCode::UP,
|
||||||
|
KeyCode::ENTER,
|
||||||
|
});
|
||||||
|
ASSERT_EQ(2u, ui_->ShowMenu(HEADERS, ITEMS, 0, true,
|
||||||
|
std::bind(&TestableScreenRecoveryUI::KeyHandler, ui_.get(),
|
||||||
|
std::placeholders::_1, std::placeholders::_2)));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(ScreenRecoveryUITest, ShowMenu_NotMenuOnly) {
|
||||||
|
ui_->SetKeyBuffer({
|
||||||
|
KeyCode::MAGIC,
|
||||||
|
});
|
||||||
|
ASSERT_EQ(static_cast<size_t>(kMagicAction),
|
||||||
|
ui_->ShowMenu(HEADERS, ITEMS, 3, false,
|
||||||
|
std::bind(&TestableScreenRecoveryUI::KeyHandler, ui_.get(),
|
||||||
|
std::placeholders::_1, std::placeholders::_2)));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(ScreenRecoveryUITest, ShowMenu_TimedOut) {
|
||||||
|
ui_->SetKeyBuffer({
|
||||||
|
KeyCode::TIMEOUT,
|
||||||
|
});
|
||||||
|
ASSERT_EQ(static_cast<size_t>(-1), ui_->ShowMenu(HEADERS, ITEMS, 3, true, nullptr));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(ScreenRecoveryUITest, ShowMenu_TimedOut_TextWasEverVisible) {
|
||||||
|
ui_->ShowText(true);
|
||||||
|
ui_->ShowText(false);
|
||||||
|
ASSERT_TRUE(ui_->WasTextEverVisible());
|
||||||
|
|
||||||
|
ui_->SetKeyBuffer({
|
||||||
|
KeyCode::TIMEOUT,
|
||||||
|
KeyCode::DOWN,
|
||||||
|
KeyCode::ENTER,
|
||||||
|
});
|
||||||
|
ASSERT_EQ(4u, ui_->ShowMenu(HEADERS, ITEMS, 3, true,
|
||||||
|
std::bind(&TestableScreenRecoveryUI::KeyHandler, ui_.get(),
|
||||||
|
std::placeholders::_1, std::placeholders::_2)));
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user