Home | History | Annotate | Download | only in simpleperf
      1 /*
      2  * Copyright (C) 2016 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 #include "UnixSocket.h"
     18 
     19 #include <gtest/gtest.h>
     20 
     21 #include <string>
     22 #include <thread>
     23 
     24 TEST(UnixSocket, message_buffer_smoke) {
     25   struct Message {
     26     uint32_t len;
     27     uint32_t type;
     28     char data[10];
     29   } send_msg;
     30   constexpr size_t send_data_size = 1024;
     31   std::vector<char> send_data(send_data_size);
     32   std::vector<char> read_data;
     33   for (size_t i = 0; i < send_data_size; ++i) {
     34     send_data[i] = i & 0xff;
     35   }
     36   UnixSocketMessageBuffer buffer(100);
     37   size_t per_msg_bytes = 0;
     38   size_t send_bytes = 0;
     39   while (true) {
     40     // Send data as much as possible.
     41     while (send_bytes < send_data_size) {
     42       size_t n = std::min(per_msg_bytes, send_data_size - send_bytes);
     43       per_msg_bytes = (per_msg_bytes + 1) % 10;
     44       memcpy(send_msg.data, &send_data[send_bytes], n);
     45       send_msg.len = sizeof(UnixSocketMessage) + n;
     46       send_msg.type = n;
     47       if (!buffer.StoreMessage(
     48               *reinterpret_cast<UnixSocketMessage*>(&send_msg))) {
     49         break;
     50       }
     51       send_bytes += n;
     52     }
     53     if (buffer.Empty()) {
     54       break;
     55     }
     56     // Read one message.
     57     std::vector<char> read_buf;
     58     auto read_func = [&](size_t size) {
     59       while (read_buf.size() < size) {
     60         const char* p;
     61         size_t n = buffer.PeekData(&p);
     62         n = std::min(n, size - read_buf.size());
     63         read_buf.insert(read_buf.end(), p, p + n);
     64         buffer.CommitData(n);
     65       }
     66     };
     67     read_func(sizeof(UnixSocketMessage));
     68     Message* msg = reinterpret_cast<Message*>(read_buf.data());
     69     size_t aligned_len = Align(msg->len, UnixSocketMessageAlignment);
     70     read_func(aligned_len);
     71     msg = reinterpret_cast<Message*>(read_buf.data());
     72     ASSERT_EQ(msg->len, msg->type + sizeof(UnixSocketMessage));
     73     read_data.insert(read_data.end(), msg->data, msg->data + msg->type);
     74   }
     75   ASSERT_EQ(send_data, read_data);
     76 }
     77 
     78 static void ClientToTestUndelayedMessage(const std::string& path,
     79                                          bool& client_success) {
     80   std::unique_ptr<UnixSocketConnection> client =
     81       UnixSocketConnection::Connect(path, true);
     82   ASSERT_TRUE(client != nullptr);
     83   IOEventLoop loop;
     84   // For each message received from the server, the client replies a msg
     85   // with type + 1.
     86   auto receive_message_callback = [&](const UnixSocketMessage& msg) {
     87     if (msg.len != sizeof(UnixSocketMessage)) {
     88       return false;
     89     }
     90     UnixSocketMessage reply_msg;
     91     reply_msg.len = sizeof(UnixSocketMessage);
     92     reply_msg.type = msg.type + 1;
     93     return client->SendMessage(reply_msg, true);
     94   };
     95   auto close_connection_callback = [&]() { return loop.ExitLoop(); };
     96   ASSERT_TRUE(client->PrepareForIO(loop, receive_message_callback,
     97                                    close_connection_callback));
     98   ASSERT_TRUE(loop.RunLoop());
     99   client_success = true;
    100 }
    101 
    102 TEST(UnixSocket, undelayed_message) {
    103   std::string path = "unix_socket_test_" + std::to_string(getpid());
    104   std::unique_ptr<UnixSocketServer> server =
    105       UnixSocketServer::Create(path, true);
    106   ASSERT_TRUE(server != nullptr);
    107   bool client_success = false;
    108   std::thread thread(
    109       [&]() { ClientToTestUndelayedMessage(path, client_success); });
    110   std::unique_ptr<UnixSocketConnection> conn = server->AcceptConnection();
    111   ASSERT_TRUE(conn != nullptr);
    112   IOEventLoop loop;
    113   uint32_t need_reply_type = 1;
    114   // For each message received from the client, the server replies a msg
    115   // with type + 1, and exits when type reaches 10.
    116   auto receive_message_callback = [&](const UnixSocketMessage& msg) {
    117     if (msg.len != sizeof(UnixSocketMessage) || msg.type != need_reply_type) {
    118       return false;
    119     }
    120     if (need_reply_type >= 10) {
    121       return conn->NoMoreMessage();
    122     }
    123     UnixSocketMessage new_msg;
    124     new_msg.len = sizeof(UnixSocketMessage);
    125     new_msg.type = msg.type + 1;
    126     need_reply_type = msg.type + 2;
    127     return conn->SendMessage(new_msg, true);
    128   };
    129   auto close_connection_callback = [&]() { return loop.ExitLoop(); };
    130   ASSERT_TRUE(conn->PrepareForIO(loop, receive_message_callback,
    131                                  close_connection_callback));
    132   UnixSocketMessage msg;
    133   msg.len = sizeof(UnixSocketMessage);
    134   msg.type = 0;
    135   ASSERT_TRUE(conn->SendMessage(msg, true));
    136   ASSERT_TRUE(loop.RunLoop());
    137   thread.join();
    138   ASSERT_TRUE(client_success);
    139 }
    140 
    141 static void ClientToTestBufferedMessage(const std::string& path,
    142                                         bool& client_success) {
    143   std::unique_ptr<UnixSocketConnection> client =
    144       UnixSocketConnection::Connect(path, true);
    145   ASSERT_TRUE(client != nullptr);
    146   IOEventLoop loop;
    147   // The client exits once receiving a message from the server.
    148   auto receive_message_callback = [&](const UnixSocketMessage& msg) {
    149     if (msg.len != sizeof(UnixSocketMessage) || msg.type != 0) {
    150       return false;
    151     }
    152     return client->NoMoreMessage();
    153   };
    154   auto close_connection_callback = [&]() { return loop.ExitLoop(); };
    155   ASSERT_TRUE(client->PrepareForIO(loop, receive_message_callback,
    156                                    close_connection_callback));
    157   // The client sends buffered messages until the send buffer is full.
    158   UnixSocketMessage msg;
    159   msg.len = sizeof(UnixSocketMessage);
    160   msg.type = 0;
    161   while (true) {
    162     msg.type++;
    163     if (!client->SendMessage(msg, false)) {
    164       break;
    165     }
    166   }
    167   ASSERT_TRUE(loop.RunLoop());
    168   client_success = true;
    169 }
    170 
    171 TEST(UnixSocket, buffered_message) {
    172   std::string path = "unix_socket_test_" + std::to_string(getpid());
    173   std::unique_ptr<UnixSocketServer> server =
    174       UnixSocketServer::Create(path, true);
    175   ASSERT_TRUE(server != nullptr);
    176   bool client_success = false;
    177   std::thread thread(
    178       [&]() { ClientToTestBufferedMessage(path, client_success); });
    179   std::unique_ptr<UnixSocketConnection> conn = server->AcceptConnection();
    180   ASSERT_TRUE(conn != nullptr);
    181   IOEventLoop loop;
    182   uint32_t need_reply_type = 1;
    183   auto receive_message_callback = [&](const UnixSocketMessage& msg) {
    184     // The server checks if the type of received message is increased by one
    185     // each time.
    186     if (msg.len != sizeof(UnixSocketMessage) || msg.type != need_reply_type) {
    187       return false;
    188     }
    189     if (need_reply_type == 1) {
    190       // Notify the client to exit.
    191       UnixSocketMessage new_msg;
    192       new_msg.len = sizeof(UnixSocketMessage);
    193       new_msg.type = 0;
    194       if (!conn->SendMessage(new_msg, true)) {
    195         return false;
    196       }
    197     }
    198     need_reply_type++;
    199     return true;
    200   };
    201   auto close_connection_callback = [&]() { return loop.ExitLoop(); };
    202   ASSERT_TRUE(conn->PrepareForIO(loop, receive_message_callback,
    203                                  close_connection_callback));
    204   ASSERT_TRUE(loop.RunLoop());
    205   thread.join();
    206   ASSERT_TRUE(client_success);
    207 }
    208