diff --git a/fastboot/Android.bp b/fastboot/Android.bp index 76aaf7bcd..3c110ee40 100644 --- a/fastboot/Android.bp +++ b/fastboot/Android.bp @@ -375,6 +375,7 @@ cc_test_host { defaults: ["fastboot_host_defaults"], srcs: [ + "fastboot_driver_test.cpp", "fastboot_test.cpp", "socket_mock.cpp", "socket_test.cpp", @@ -383,7 +384,10 @@ cc_test_host { "udp_test.cpp", ], - static_libs: ["libfastboot"], + static_libs: [ + "libfastboot", + "libgmock", + ], target: { windows: { diff --git a/fastboot/fastboot_driver_test.cpp b/fastboot/fastboot_driver_test.cpp new file mode 100644 index 000000000..e874c3a87 --- /dev/null +++ b/fastboot/fastboot_driver_test.cpp @@ -0,0 +1,60 @@ +// +// 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. +// + +#include "fastboot_driver.h" + +#include + +#include +#include "mock_transport.h" + +using namespace ::testing; +using namespace fastboot; + +class DriverTest : public ::testing::Test { + protected: + InSequence s_; +}; + +TEST_F(DriverTest, GetVar) { + MockTransport transport; + FastBootDriver driver(&transport); + + EXPECT_CALL(transport, Write(_, _)) + .With(AllArgs(RawData("getvar:version"))) + .WillOnce(ReturnArg<1>()); + EXPECT_CALL(transport, Read(_, _)).WillOnce(Invoke(CopyData("OKAY0.4"))); + + std::string output; + ASSERT_EQ(driver.GetVar("version", &output), SUCCESS) << driver.Error(); + ASSERT_EQ(output, "0.4"); +} + +TEST_F(DriverTest, InfoMessage) { + MockTransport transport; + FastBootDriver driver(&transport); + + EXPECT_CALL(transport, Write(_, _)) + .With(AllArgs(RawData("oem dmesg"))) + .WillOnce(ReturnArg<1>()); + EXPECT_CALL(transport, Read(_, _)).WillOnce(Invoke(CopyData("INFOthis is an info line"))); + EXPECT_CALL(transport, Read(_, _)).WillOnce(Invoke(CopyData("OKAY"))); + + std::vector info; + ASSERT_EQ(driver.RawCommand("oem dmesg", "", nullptr, &info), SUCCESS) << driver.Error(); + ASSERT_EQ(info.size(), size_t(1)); + ASSERT_EQ(info[0], "this is an info line"); +} diff --git a/fastboot/mock_transport.h b/fastboot/mock_transport.h new file mode 100644 index 000000000..cc3840ce7 --- /dev/null +++ b/fastboot/mock_transport.h @@ -0,0 +1,67 @@ +// +// 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 + +#include +#include + +#include +#include "transport.h" + +class MockTransport : public Transport { + public: + MOCK_METHOD(ssize_t, Read, (void* data, size_t len), (override)); + MOCK_METHOD(ssize_t, Write, (const void* data, size_t len), (override)); + MOCK_METHOD(int, Close, (), (override)); + MOCK_METHOD(int, Reset, (), (override)); +}; + +class RawDataMatcher { + public: + explicit RawDataMatcher(const char* data) : data_(data) {} + explicit RawDataMatcher(std::string_view data) : data_(data) {} + + bool MatchAndExplain(std::tuple args, + ::testing::MatchResultListener*) const { + const void* expected_data = std::get<0>(args); + size_t expected_len = std::get<1>(args); + if (expected_len != data_.size()) { + return false; + } + return memcmp(expected_data, data_.data(), expected_len) == 0; + } + void DescribeTo(std::ostream* os) const { *os << "raw data is"; } + void DescribeNegationTo(std::ostream* os) const { *os << "raw data is not"; } + + private: + std::string_view data_; +}; + +template +static inline ::testing::PolymorphicMatcher RawData(T data) { + return ::testing::MakePolymorphicMatcher(RawDataMatcher(data)); +} + +static inline auto CopyData(const char* source) { + return [source](void* buffer, size_t size) -> ssize_t { + size_t to_copy = std::min(size, strlen(source)); + memcpy(buffer, source, to_copy); + return to_copy; + }; +};