Add fastboot_test.cpp and test --os-version/--os-patch-level parsing.

Also switch all remaining headers over to #pragma once, and actually
use FB_COMMAND_SZ.

Bug: http://b/77340848
Test: ran tests
Change-Id: I27107d054c206e66c39208099e36a55df604e08f
This commit is contained in:
Elliott Hughes 2018-04-10 14:22:13 -07:00
parent 20d2159803
commit 6ebec932d6
12 changed files with 108 additions and 54 deletions

View file

@ -83,6 +83,7 @@ LOCAL_MODULE_HOST_OS := darwin linux windows
LOCAL_CFLAGS := $(fastboot_cflags)
LOCAL_CFLAGS_darwin := $(fastboot_cflags_darwin)
LOCAL_CXX_STL := $(fastboot_stl)
LOCAL_HEADER_LIBRARIES := bootimg_headers
LOCAL_LDLIBS_darwin := $(fastboot_ldflags_darwin)
LOCAL_LDLIBS_windows := $(fastboot_ldlibs_windows)
LOCAL_REQUIRED_MODULES := mke2fs make_f2fs
@ -93,8 +94,6 @@ LOCAL_SRC_FILES := main.cpp
LOCAL_SHARED_LIBRARIES := $(fastboot_shared_libs)
LOCAL_SHARED_LIBRARIES_windows := AdbWinApi
LOCAL_STATIC_LIBRARIES := libfastboot $(fastboot_static_libs)
LOCAL_STATIC_LIBRARIES_darwin := libselinux
LOCAL_STATIC_LIBRARIES_linux := libselinux
include $(BUILD_HOST_EXECUTABLE)
#
@ -120,8 +119,10 @@ my_dist_files :=
include $(CLEAR_VARS)
LOCAL_MODULE := fastboot_test
LOCAL_MODULE_HOST_OS := darwin linux windows
LOCAL_MODULE_HOST_CROSS_ARCH := x86 # Avoid trying to build for win64.
LOCAL_SRC_FILES := \
fastboot_test.cpp \
socket_mock.cpp \
socket_test.cpp \
tcp_test.cpp \
@ -130,7 +131,10 @@ LOCAL_SRC_FILES := \
LOCAL_CFLAGS := $(fastboot_cflags)
LOCAL_CFLAGS_darwin := $(fastboot_cflags_darwin)
LOCAL_CXX_STL := $(fastboot_stl)
LOCAL_HEADER_LIBRARIES := bootimg_headers
LOCAL_LDLIBS_darwin := $(fastboot_ldflags_darwin)
LOCAL_LDLIBS_windows := $(fastboot_ldlibs_windows)
LOCAL_SHARED_LIBRARIES := $(fastboot_shared_libs)
LOCAL_SHARED_LIBRARIES_windows := AdbWinApi
LOCAL_STATIC_LIBRARIES := libfastboot $(fastboot_static_libs)
include $(BUILD_HOST_NATIVE_TEST)

View file

@ -1475,24 +1475,9 @@ int FastBoot::Main(int argc, char* argv[]) {
} else if (name == "kernel-offset") {
g_boot_img_hdr.kernel_addr = strtoul(optarg, 0, 16);
} else if (name == "os-patch-level") {
unsigned year, month, day;
if (sscanf(optarg, "%u-%u-%u", &year, &month, &day) != 3) {
syntax_error("OS patch level should be YYYY-MM-DD: %s", optarg);
}
if (year < 2000 || year >= 2128) syntax_error("year out of range: %d", year);
if (month < 1 || month > 12) syntax_error("month out of range: %d", month);
g_boot_img_hdr.SetOsPatchLevel(year, month);
ParseOsPatchLevel(&g_boot_img_hdr, optarg);
} else if (name == "os-version") {
unsigned major = 0, minor = 0, patch = 0;
std::vector<std::string> versions = android::base::Split(optarg, ".");
if (versions.size() < 1 || versions.size() > 3 ||
(versions.size() >= 1 && !android::base::ParseUint(versions[0], &major)) ||
(versions.size() >= 2 && !android::base::ParseUint(versions[1], &minor)) ||
(versions.size() == 3 && !android::base::ParseUint(versions[2], &patch)) ||
(major > 0x7f || minor > 0x7f || patch > 0x7f)) {
syntax_error("bad OS version: %s", optarg);
}
g_boot_img_hdr.SetOsVersion(major, minor, patch);
ParseOsVersion(&g_boot_img_hdr, optarg);
} else if (name == "page-size") {
g_boot_img_hdr.page_size = strtoul(optarg, nullptr, 0);
if (g_boot_img_hdr.page_size == 0) die("invalid page size");
@ -1801,3 +1786,26 @@ int FastBoot::Main(int argc, char* argv[]) {
fprintf(stderr, "Finished. Total time: %.3fs\n", (now() - start));
return status;
}
void FastBoot::ParseOsPatchLevel(boot_img_hdr_v1* hdr, const char* arg) {
unsigned year, month, day;
if (sscanf(arg, "%u-%u-%u", &year, &month, &day) != 3) {
syntax_error("OS patch level should be YYYY-MM-DD: %s", arg);
}
if (year < 2000 || year >= 2128) syntax_error("year out of range: %d", year);
if (month < 1 || month > 12) syntax_error("month out of range: %d", month);
hdr->SetOsPatchLevel(year, month);
}
void FastBoot::ParseOsVersion(boot_img_hdr_v1* hdr, const char* arg) {
unsigned major = 0, minor = 0, patch = 0;
std::vector<std::string> versions = android::base::Split(arg, ".");
if (versions.size() < 1 || versions.size() > 3 ||
(versions.size() >= 1 && !android::base::ParseUint(versions[0], &major)) ||
(versions.size() >= 2 && !android::base::ParseUint(versions[1], &minor)) ||
(versions.size() == 3 && !android::base::ParseUint(versions[2], &patch)) ||
(major > 0x7f || minor > 0x7f || patch > 0x7f)) {
syntax_error("bad OS version: %s", arg);
}
hdr->SetOsVersion(major, minor, patch);
}

View file

@ -26,14 +26,15 @@
* SUCH DAMAGE.
*/
#ifndef _FASTBOOT_H_
#define _FASTBOOT_H_
#pragma once
#include <inttypes.h>
#include <stdlib.h>
#include <string>
#include <bootimg.h>
class Transport;
struct sparse_file;
@ -99,6 +100,7 @@ extern char cur_product[FB_RESPONSE_SZ + 1];
class FastBoot {
public:
int Main(int argc, char* argv[]);
};
#endif
void ParseOsPatchLevel(boot_img_hdr_v1*, const char*);
void ParseOsVersion(boot_img_hdr_v1*, const char*);
};

View file

@ -0,0 +1,61 @@
/*
* Copyright (C) 2018 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "fastboot.h"
#include <gtest/gtest.h>
TEST(FastBoot, ParseOsPatchLevel) {
FastBoot fb;
boot_img_hdr_v1 hdr;
hdr = {};
fb.ParseOsPatchLevel(&hdr, "2018-01-05");
ASSERT_EQ(2018U, 2000U + ((hdr.os_version >> 4) & 0x7f));
ASSERT_EQ(1U, ((hdr.os_version >> 0) & 0xf));
EXPECT_DEATH(fb.ParseOsPatchLevel(&hdr, "2018"), "should be YYYY-MM-DD");
EXPECT_DEATH(fb.ParseOsPatchLevel(&hdr, "2018-01"), "should be YYYY-MM-DD");
EXPECT_DEATH(fb.ParseOsPatchLevel(&hdr, "2128-01-05"), "year out of range");
EXPECT_DEATH(fb.ParseOsPatchLevel(&hdr, "2018-13-05"), "month out of range");
}
TEST(FastBoot, ParseOsVersion) {
FastBoot fb;
boot_img_hdr_v1 hdr;
hdr = {};
fb.ParseOsVersion(&hdr, "1.2.3");
ASSERT_EQ(1U, ((hdr.os_version >> 25) & 0x7f));
ASSERT_EQ(2U, ((hdr.os_version >> 18) & 0x7f));
ASSERT_EQ(3U, ((hdr.os_version >> 11) & 0x7f));
fb.ParseOsVersion(&hdr, "1.2");
ASSERT_EQ(1U, ((hdr.os_version >> 25) & 0x7f));
ASSERT_EQ(2U, ((hdr.os_version >> 18) & 0x7f));
ASSERT_EQ(0U, ((hdr.os_version >> 11) & 0x7f));
fb.ParseOsVersion(&hdr, "1");
ASSERT_EQ(1U, ((hdr.os_version >> 25) & 0x7f));
ASSERT_EQ(0U, ((hdr.os_version >> 18) & 0x7f));
ASSERT_EQ(0U, ((hdr.os_version >> 11) & 0x7f));
EXPECT_DEATH(fb.ParseOsVersion(&hdr, ""), "bad OS version");
EXPECT_DEATH(fb.ParseOsVersion(&hdr, "1.2.3.4"), "bad OS version");
EXPECT_DEATH(fb.ParseOsVersion(&hdr, "128.2.3"), "bad OS version");
EXPECT_DEATH(fb.ParseOsVersion(&hdr, "1.128.3"), "bad OS version");
EXPECT_DEATH(fb.ParseOsVersion(&hdr, "1.2.128"), "bad OS version");
}

View file

@ -1,5 +1,4 @@
#ifndef _FS_H_
#define _FS_H_
#pragma once
#include <string>
#include <stdint.h>
@ -9,5 +8,3 @@ struct fs_generator;
const struct fs_generator* fs_get_generator(const std::string& fs_type);
int fs_generator_generate(const struct fs_generator* gen, const char* fileName, long long partSize,
const std::string& initial_dir, unsigned eraseBlkSize = 0, unsigned logicalBlkSize = 0);
#endif

View file

@ -57,10 +57,10 @@ const std::string fb_get_error() {
}
static int64_t check_response(Transport* transport, uint32_t size, char* response) {
char status[65];
char status[FB_RESPONSE_SZ + 1];
while (true) {
int r = transport->Read(status, 64);
int r = transport->Read(status, FB_RESPONSE_SZ);
if (r < 0) {
g_error = android::base::StringPrintf("status read failed (%s)", strerror(errno));
transport->Close();
@ -120,7 +120,7 @@ static int64_t check_response(Transport* transport, uint32_t size, char* respons
static int64_t _command_start(Transport* transport, const std::string& cmd, uint32_t size,
char* response) {
if (cmd.size() > 64) {
if (cmd.size() > FB_COMMAND_SZ) {
g_error = android::base::StringPrintf("command too large (%zu)", cmd.size());
return -1;
}

View file

@ -30,8 +30,7 @@
// engine should not be using this interface directly, but instead should use a higher-level
// interface that enforces the fastboot protocol.
#ifndef SOCKET_H_
#define SOCKET_H_
#pragma once
#include <functional>
#include <memory>
@ -125,5 +124,3 @@ class Socket {
DISALLOW_COPY_AND_ASSIGN(Socket);
};
#endif // SOCKET_H_

View file

@ -26,8 +26,7 @@
* SUCH DAMAGE.
*/
#ifndef SOCKET_MOCK_H_
#define SOCKET_MOCK_H_
#pragma once
#include <memory>
#include <queue>
@ -97,5 +96,3 @@ class SocketMock : public Socket {
DISALLOW_COPY_AND_ASSIGN(SocketMock);
};
#endif // SOCKET_MOCK_H_

View file

@ -26,8 +26,7 @@
* SUCH DAMAGE.
*/
#ifndef TCP_H_
#define TCP_H_
#pragma once
#include <memory>
#include <string>
@ -55,5 +54,3 @@ std::unique_ptr<Transport> Connect(std::unique_ptr<Socket> sock, std::string* er
} // namespace internal
} // namespace tcp
#endif // TCP_H_

View file

@ -14,8 +14,7 @@
* limitations under the License.
*/
#ifndef TRANSPORT_H_
#define TRANSPORT_H_
#pragma once
#include <android-base/macros.h>
@ -44,5 +43,3 @@ class Transport {
private:
DISALLOW_COPY_AND_ASSIGN(Transport);
};
#endif // TRANSPORT_H_

View file

@ -26,8 +26,7 @@
* SUCH DAMAGE.
*/
#ifndef UDP_H_
#define UDP_H_
#pragma once
#include <memory>
#include <string>
@ -77,5 +76,3 @@ std::unique_ptr<Transport> Connect(std::unique_ptr<Socket> sock, std::string* er
} // namespace internal
} // namespace udp
#endif // UDP_H_

View file

@ -26,8 +26,7 @@
* SUCH DAMAGE.
*/
#ifndef _USB_H_
#define _USB_H_
#pragma once
#include "transport.h"
@ -56,5 +55,3 @@ struct usb_ifc_info {
typedef int (*ifc_match_func)(usb_ifc_info *ifc);
Transport* usb_open(ifc_match_func callback);
#endif