fastboot: Introduce ParseNetworkSerial unit tests

Introduced positive and negative unit tests to cover
ParseNetworkSerial logic. Alongside with that move
result related stuff to the separate header.

Test: atest fastboot_test
Test: manually checked basic functionality works fine
Bug: 271155012
Change-Id: Icac6053c11b5a36daa64555209555826ea28cc61
Signed-off-by: Dmitrii Merkurev <dimorinny@google.com>
This commit is contained in:
Dmitrii Merkurev 2023-03-01 23:50:05 +00:00
parent 18b6e9b819
commit cdbfa7a3e8
5 changed files with 119 additions and 45 deletions

View file

@ -336,28 +336,7 @@ static int list_devices_callback(usb_ifc_info* info) {
return -1;
}
struct NetworkSerial {
Socket::Protocol protocol;
std::string address;
int port;
};
class ParseNetworkAddressError {
public:
enum Type { WRONG_PREFIX = 1, WRONG_ADDRESS = 2 };
ParseNetworkAddressError(Type&& type) : type_(std::forward<Type>(type)) {}
Type value() const { return type_; }
operator Type() const { return value(); }
std::string print() const { return ""; }
private:
Type type_;
};
static Result<NetworkSerial, ParseNetworkAddressError> ParseNetworkSerial(
const std::string& serial) {
Result<NetworkSerial, FastbootError> ParseNetworkSerial(const std::string& serial) {
Socket::Protocol protocol;
const char* net_address = nullptr;
int port = 0;
@ -371,7 +350,7 @@ static Result<NetworkSerial, ParseNetworkAddressError> ParseNetworkSerial(
net_address = serial.c_str() + strlen("udp:");
port = udp::kDefaultPort;
} else {
return Error<ParseNetworkAddressError>(ParseNetworkAddressError::Type::WRONG_PREFIX)
return Error<FastbootError>(FastbootError::Type::NETWORK_SERIAL_WRONG_PREFIX)
<< "protocol prefix ('tcp:' or 'udp:') is missed: " << serial << ". "
<< "Expected address format:\n"
<< "<protocol>:<address>:<port> (tcp:localhost:5554)";
@ -380,7 +359,7 @@ static Result<NetworkSerial, ParseNetworkAddressError> ParseNetworkSerial(
std::string error;
std::string host;
if (!android::base::ParseNetAddress(net_address, &host, &port, nullptr, &error)) {
return Error<ParseNetworkAddressError>(ParseNetworkAddressError::Type::WRONG_ADDRESS)
return Error<FastbootError>(FastbootError::Type::NETWORK_SERIAL_WRONG_ADDRESS)
<< "invalid network address '" << net_address << "': " << error;
}
@ -399,8 +378,7 @@ static Result<NetworkSerial, ParseNetworkAddressError> ParseNetworkSerial(
// object, and the caller should not attempt to delete the returned Transport.
static Transport* open_device(const char* local_serial, bool wait_for_device = true,
bool announce = true) {
const Result<NetworkSerial, ParseNetworkAddressError> network_serial =
ParseNetworkSerial(local_serial);
const Result<NetworkSerial, FastbootError> network_serial = ParseNetworkSerial(local_serial);
Transport* transport = nullptr;
while (true) {
@ -417,7 +395,8 @@ static Transport* open_device(const char* local_serial, bool wait_for_device = t
if (transport == nullptr && announce) {
LOG(ERROR) << "error: " << error;
}
} else if (network_serial.error().code() == ParseNetworkAddressError::Type::WRONG_PREFIX) {
} else if (network_serial.error().code() ==
FastbootError::Type::NETWORK_SERIAL_WRONG_PREFIX) {
// WRONG_PREFIX is special because it happens when user wants to communicate with USB
// device
transport = usb_open(match_fastboot(local_serial));

View file

@ -31,6 +31,10 @@
#include <bootimg.h>
#include "result.h"
#include "socket.h"
#include "util.h"
class FastBootTool {
public:
int Main(int argc, char* argv[]);
@ -48,3 +52,11 @@ void do_for_partitions(const std::string& part, const std::string& slot,
std::string find_item(const std::string& item);
void reboot_to_userspace_fastboot();
void syntax_error(const char* fmt, ...);
struct NetworkSerial {
Socket::Protocol protocol;
std::string address;
int port;
};
Result<NetworkSerial, FastbootError> ParseNetworkSerial(const std::string& serial);

View file

@ -203,6 +203,54 @@ TEST(FastBoot, ParseRequirementLineMalformed) {
ParseRequirementLineTestMalformed("require-for-product :");
}
static void ParseNetworkSerialTest(const std::string& description, const std::string& serial,
const std::string& expected_address,
const Socket::Protocol expected_protocol,
const int expected_port) {
const Result<NetworkSerial, FastbootError> parsed = ParseNetworkSerial(serial);
ASSERT_RESULT_OK(parsed) << description;
const NetworkSerial network_serial = parsed.value();
EXPECT_EQ(network_serial.address, expected_address) << description;
EXPECT_EQ(network_serial.protocol, expected_protocol) << description;
EXPECT_EQ(network_serial.port, expected_port) << description;
}
static void ParseNetworkSerialNegativeTest(const std::string& description,
const std::string& serial,
const FastbootError::Type expected_error) {
const Result<NetworkSerial, FastbootError> parsed = ParseNetworkSerial(serial);
EXPECT_FALSE(parsed.ok()) << description;
EXPECT_EQ(parsed.error().code(), expected_error) << description;
}
TEST(FastBoot, ParseNetworkSerial) {
ParseNetworkSerialTest("tcp IPv4 parsed", "tcp:192.168.1.0", "192.168.1.0",
Socket::Protocol::kTcp, 5554);
ParseNetworkSerialTest("udp IPv4 parsed", "udp:192.168.1.0", "192.168.1.0",
Socket::Protocol::kUdp, 5554);
ParseNetworkSerialTest("port parsed", "udp:192.168.1.0:9999", "192.168.1.0",
Socket::Protocol::kUdp, 9999);
ParseNetworkSerialTest("IPv6 parsed", "tcp:2001:db8:3333:4444:5555:6666:7777:8888",
"2001:db8:3333:4444:5555:6666:7777:8888", Socket::Protocol::kTcp, 5554);
ParseNetworkSerialTest("empty IPv6 parsed", "tcp:::", "::", Socket::Protocol::kTcp, 5554);
ParseNetworkSerialNegativeTest("wrong prefix", "tcpa:192.168.1.0",
FastbootError::Type::NETWORK_SERIAL_WRONG_PREFIX);
ParseNetworkSerialNegativeTest("no prefix", "192.168.1.0",
FastbootError::Type::NETWORK_SERIAL_WRONG_PREFIX);
ParseNetworkSerialNegativeTest("wrong port", "tcp:192.168.1.0:-1",
FastbootError::Type::NETWORK_SERIAL_WRONG_ADDRESS);
}
int main(int argc, char* argv[]) {
::testing::InitGoogleTest(&argc, argv);
android::base::InitLogging(argv);

53
fastboot/result.h Normal file
View file

@ -0,0 +1,53 @@
/*
* Copyright (C) 2023 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.
*/
#pragma once
#include <string>
#include <android-base/result.h>
#include "util.h"
using android::base::ErrnoError;
using android::base::Error;
using android::base::Result;
using android::base::ResultError;
class FastbootError {
public:
enum Type { NETWORK_SERIAL_WRONG_PREFIX = 1, NETWORK_SERIAL_WRONG_ADDRESS = 2 };
FastbootError(Type&& type) : type_(std::forward<Type>(type)) {}
Type value() const { return type_; }
operator Type() const { return value(); }
std::string print() const { return ""; }
private:
Type type_;
};
template <typename T, typename U>
inline T Expect(Result<T, U> r) {
if (r.ok()) {
return r.value();
}
die(r.error().message());
return r.value();
}

View file

@ -6,29 +6,11 @@
#include <string>
#include <vector>
#include <android-base/logging.h>
#include <android-base/result.h>
#include <android-base/unique_fd.h>
#include <bootimg.h>
#include <liblp/liblp.h>
#include <sparse/sparse.h>
using android::base::ErrnoError;
using android::base::Error;
using android::base::Result;
using android::base::ResultError;
template <typename T, typename U>
inline T Expect(Result<T, U> r) {
if (r.ok()) {
return r.value();
}
LOG(FATAL) << r.error().message();
return r.value();
}
using SparsePtr = std::unique_ptr<sparse_file, decltype(&sparse_file_destroy)>;
/* util stuff */