tcp_test.cpp 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227
  1. /*
  2. * Copyright (C) 2016 The Android Open Source Project
  3. * All rights reserved.
  4. *
  5. * Redistribution and use in source and binary forms, with or without
  6. * modification, are permitted provided that the following conditions
  7. * are met:
  8. * * Redistributions of source code must retain the above copyright
  9. * notice, this list of conditions and the following disclaimer.
  10. * * Redistributions in binary form must reproduce the above copyright
  11. * notice, this list of conditions and the following disclaimer in
  12. * the documentation and/or other materials provided with the
  13. * distribution.
  14. *
  15. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  16. * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  17. * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
  18. * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
  19. * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
  20. * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
  21. * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
  22. * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
  23. * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
  24. * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
  25. * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  26. * SUCH DAMAGE.
  27. */
  28. #include "tcp.h"
  29. #include <gtest/gtest.h>
  30. #include "socket_mock.h"
  31. TEST(TcpConnectTest, TestSuccess) {
  32. std::unique_ptr<SocketMock> mock(new SocketMock);
  33. mock->ExpectSend("FB01");
  34. mock->AddReceive("FB01");
  35. std::string error;
  36. EXPECT_NE(nullptr, tcp::internal::Connect(std::move(mock), &error));
  37. EXPECT_EQ("", error);
  38. }
  39. TEST(TcpConnectTest, TestNewerVersionSuccess) {
  40. std::unique_ptr<SocketMock> mock(new SocketMock);
  41. mock->ExpectSend("FB01");
  42. mock->AddReceive("FB99");
  43. std::string error;
  44. EXPECT_NE(nullptr, tcp::internal::Connect(std::move(mock), &error));
  45. EXPECT_EQ("", error);
  46. }
  47. TEST(TcpConnectTest, TestSendFailure) {
  48. std::unique_ptr<SocketMock> mock(new SocketMock);
  49. mock->ExpectSendFailure("FB01");
  50. std::string error;
  51. EXPECT_EQ(nullptr, tcp::internal::Connect(std::move(mock), &error));
  52. EXPECT_NE(std::string::npos, error.find("Failed to send initialization message"));
  53. }
  54. TEST(TcpConnectTest, TestNoResponseFailure) {
  55. std::unique_ptr<SocketMock> mock(new SocketMock);
  56. mock->ExpectSend("FB01");
  57. mock->AddReceiveFailure();
  58. std::string error;
  59. EXPECT_EQ(nullptr, tcp::internal::Connect(std::move(mock), &error));
  60. EXPECT_NE(std::string::npos, error.find("No initialization message received"));
  61. }
  62. TEST(TcpConnectTest, TestBadResponseFailure) {
  63. std::unique_ptr<SocketMock> mock(new SocketMock);
  64. mock->ExpectSend("FB01");
  65. mock->AddReceive("XX01");
  66. std::string error;
  67. EXPECT_EQ(nullptr, tcp::internal::Connect(std::move(mock), &error));
  68. EXPECT_NE(std::string::npos, error.find("Unrecognized initialization message"));
  69. }
  70. TEST(TcpConnectTest, TestUnknownVersionFailure) {
  71. std::unique_ptr<SocketMock> mock(new SocketMock);
  72. mock->ExpectSend("FB01");
  73. mock->AddReceive("FB00");
  74. std::string error;
  75. EXPECT_EQ(nullptr, tcp::internal::Connect(std::move(mock), &error));
  76. EXPECT_EQ("Unknown TCP protocol version 00 (host version 01)", error);
  77. }
  78. // Fixture to configure a SocketMock for a successful TCP connection.
  79. class TcpTest : public ::testing::Test {
  80. protected:
  81. void SetUp() override {
  82. mock_ = new SocketMock;
  83. mock_->ExpectSend("FB01");
  84. mock_->AddReceive("FB01");
  85. std::string error;
  86. transport_ = tcp::internal::Connect(std::unique_ptr<Socket>(mock_), &error);
  87. ASSERT_NE(nullptr, transport_);
  88. ASSERT_EQ("", error);
  89. };
  90. // Writes |message| to |transport_|, returns true on success.
  91. bool Write(const std::string& message) {
  92. return transport_->Write(message.data(), message.length()) ==
  93. static_cast<ssize_t>(message.length());
  94. }
  95. // Reads from |transport_|, returns true if it matches |message|.
  96. bool Read(const std::string& message) {
  97. std::string buffer(message.length(), '\0');
  98. return transport_->Read(&buffer[0], buffer.length()) ==
  99. static_cast<ssize_t>(message.length()) &&
  100. buffer == message;
  101. }
  102. // Use a raw SocketMock* here because we pass ownership to the Transport object, but we still
  103. // need access to configure mock expectations.
  104. SocketMock* mock_ = nullptr;
  105. std::unique_ptr<Transport> transport_;
  106. };
  107. TEST_F(TcpTest, TestWriteSuccess) {
  108. mock_->ExpectSend(std::string{0, 0, 0, 0, 0, 0, 0, 3} + "foo");
  109. EXPECT_TRUE(Write("foo"));
  110. }
  111. TEST_F(TcpTest, TestReadSuccess) {
  112. mock_->AddReceive(std::string{0, 0, 0, 0, 0, 0, 0, 3});
  113. mock_->AddReceive("foo");
  114. EXPECT_TRUE(Read("foo"));
  115. }
  116. // Tests that fragmented TCP reads are handled properly.
  117. TEST_F(TcpTest, TestReadFragmentSuccess) {
  118. mock_->AddReceive(std::string{0, 0, 0, 0});
  119. mock_->AddReceive(std::string{0, 0, 0, 3});
  120. mock_->AddReceive("f");
  121. mock_->AddReceive("o");
  122. mock_->AddReceive("o");
  123. EXPECT_TRUE(Read("foo"));
  124. }
  125. TEST_F(TcpTest, TestLargeWriteSuccess) {
  126. // 0x100000 = 1MiB.
  127. std::string data(0x100000, '\0');
  128. for (size_t i = 0; i < data.length(); ++i) {
  129. data[i] = i;
  130. }
  131. mock_->ExpectSend(std::string{0, 0, 0, 0, 0, 0x10, 0, 0} + data);
  132. EXPECT_TRUE(Write(data));
  133. }
  134. TEST_F(TcpTest, TestLargeReadSuccess) {
  135. // 0x100000 = 1MiB.
  136. std::string data(0x100000, '\0');
  137. for (size_t i = 0; i < data.length(); ++i) {
  138. data[i] = i;
  139. }
  140. mock_->AddReceive(std::string{0, 0, 0, 0, 0, 0x10, 0, 0});
  141. mock_->AddReceive(data);
  142. EXPECT_TRUE(Read(data));
  143. }
  144. // Tests a few sample fastboot protocol commands.
  145. TEST_F(TcpTest, TestFastbootProtocolSuccess) {
  146. mock_->ExpectSend(std::string{0, 0, 0, 0, 0, 0, 0, 14} + "getvar:version");
  147. mock_->AddReceive(std::string{0, 0, 0, 0, 0, 0, 0, 7});
  148. mock_->AddReceive("OKAY0.4");
  149. mock_->ExpectSend(std::string{0, 0, 0, 0, 0, 0, 0, 10} + "getvar:all");
  150. mock_->AddReceive(std::string{0, 0, 0, 0, 0, 0, 0, 16});
  151. mock_->AddReceive("INFOversion: 0.4");
  152. mock_->AddReceive(std::string{0, 0, 0, 0, 0, 0, 0, 12});
  153. mock_->AddReceive("INFOfoo: bar");
  154. mock_->AddReceive(std::string{0, 0, 0, 0, 0, 0, 0, 4});
  155. mock_->AddReceive("OKAY");
  156. EXPECT_TRUE(Write("getvar:version"));
  157. EXPECT_TRUE(Read("OKAY0.4"));
  158. EXPECT_TRUE(Write("getvar:all"));
  159. EXPECT_TRUE(Read("INFOversion: 0.4"));
  160. EXPECT_TRUE(Read("INFOfoo: bar"));
  161. EXPECT_TRUE(Read("OKAY"));
  162. }
  163. TEST_F(TcpTest, TestReadLengthFailure) {
  164. mock_->AddReceiveFailure();
  165. char buffer[16];
  166. EXPECT_EQ(-1, transport_->Read(buffer, sizeof(buffer)));
  167. }
  168. TEST_F(TcpTest, TestReadDataFailure) {
  169. mock_->AddReceive(std::string{0, 0, 0, 0, 0, 0, 0, 3});
  170. mock_->AddReceiveFailure();
  171. char buffer[16];
  172. EXPECT_EQ(-1, transport_->Read(buffer, sizeof(buffer)));
  173. }
  174. TEST_F(TcpTest, TestWriteFailure) {
  175. mock_->ExpectSendFailure(std::string{0, 0, 0, 0, 0, 0, 0, 3} + "foo");
  176. EXPECT_EQ(-1, transport_->Write("foo", 3));
  177. }
  178. TEST_F(TcpTest, TestTransportClose) {
  179. EXPECT_EQ(0, transport_->Close());
  180. // After closing, Transport Read()/Write() should return -1 without actually attempting any
  181. // network operations.
  182. char buffer[16];
  183. EXPECT_EQ(-1, transport_->Read(buffer, sizeof(buffer)));
  184. EXPECT_EQ(-1, transport_->Write("foo", 3));
  185. }