1e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko#include <errno.h>
2e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko#include <fcntl.h>
352ea25cf06cef250ec73052611b48556b3fce4d5Corey Tabaka#include <poll.h>
4e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko#include <sys/epoll.h>
5e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko#include <sys/eventfd.h>
6e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko#include <unistd.h>
7e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
8e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko#include <array>
9e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko#include <atomic>
10e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko#include <memory>
11e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko#include <numeric>
12e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko#include <string>
13e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko#include <thread>
14e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
15e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko#include <gtest/gtest.h>
16e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko#include <pdx/channel_handle.h>
17e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko#include <pdx/client.h>
18e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko#include <pdx/file_handle.h>
19e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko#include <pdx/service.h>
205a244ed36c8e45fd95b89ff916caf083fb182ec1Alex Vakulenko#include <pdx/service_dispatcher.h>
21e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko#include <private/android_filesystem_config.h>
22e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko#include <uds/client_channel.h>
23e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko#include <uds/client_channel_factory.h>
24e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko#include <uds/service_endpoint.h>
25e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
26e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenkousing android::pdx::BorrowedChannelHandle;
27e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenkousing android::pdx::Channel;
28e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenkousing android::pdx::ChannelReference;
29e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenkousing android::pdx::ClientBase;
30186d77217aaf769ff0a91753971e23bd249afca7Corey Tabakausing android::pdx::ErrorStatus;
31e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenkousing android::pdx::LocalChannelHandle;
32e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenkousing android::pdx::LocalHandle;
33e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenkousing android::pdx::Message;
34e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenkousing android::pdx::MessageInfo;
35e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenkousing android::pdx::RemoteChannelHandle;
36e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenkousing android::pdx::ServiceBase;
37e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenkousing android::pdx::ServiceDispatcher;
38e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenkousing android::pdx::Status;
39e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenkousing android::pdx::Transaction;
40e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenkousing android::pdx::uds::Endpoint;
41e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
42e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenkonamespace {
43e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
44e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenkoconst size_t kLargeDataSize = 100000;
45e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
46e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenkoconst char kTestServicePath[] = "socket_test";
47e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenkoconst char kTestService1[] = "1";
48e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenkoconst char kTestService2[] = "2";
49e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
50e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenkoenum test_op_codes {
51e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  TEST_OP_GET_SERVICE_ID,
52e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  TEST_OP_SET_TEST_CHANNEL,
53e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  TEST_OP_GET_THIS_CHANNEL_ID,
54e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  TEST_OP_GET_TEST_CHANNEL_ID,
55e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  TEST_OP_CHECK_CHANNEL_ID,
56e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  TEST_OP_CHECK_CHANNEL_OBJECT,
57e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  TEST_OP_CHECK_CHANNEL_FROM_OTHER_SERVICE,
58e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  TEST_OP_GET_NEW_CHANNEL,
59e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  TEST_OP_GET_NEW_CHANNEL_FROM_OTHER_SERVICE,
60e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  TEST_OP_GET_THIS_PROCESS_ID,
61e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  TEST_OP_GET_THIS_THREAD_ID,
62e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  TEST_OP_GET_THIS_EUID,
63e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  TEST_OP_GET_THIS_EGID,
64e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  TEST_OP_IMPULSE,
65e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  TEST_OP_POLLHUP_FROM_SERVICE,
66e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  TEST_OP_POLLIN_FROM_SERVICE,
67e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  TEST_OP_SEND_LARGE_DATA_RETURN_SUM,
68e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko};
69e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
70e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenkousing ImpulsePayload = std::array<std::uint8_t, sizeof(MessageInfo::impulse)>;
71e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
72e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko// The test service creates a TestChannel for every client (channel) that
73e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko// connects. This represents the service-side context for each client.
74e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenkoclass TestChannel : public Channel {
75e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko public:
76e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  explicit TestChannel(int channel_id) : channel_id_(channel_id) {}
77e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
78e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  int channel_id() const { return channel_id_; }
79e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
80e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko private:
81e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  friend class TestService;
82e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
83e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  int channel_id_;
84e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
85e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  TestChannel(const TestChannel&) = delete;
86e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  void operator=(const TestChannel&) = delete;
87e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko};
88e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
89e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko// Test service that creates a TestChannel for each channel and responds to test
90e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko// messages.
91e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenkoclass TestService : public ServiceBase<TestService> {
92e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko public:
93e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  std::shared_ptr<Channel> OnChannelOpen(Message& message) override {
94e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    return std::make_shared<TestChannel>(message.GetChannelId());
95e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  }
96e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
97e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  void OnChannelClose(Message& /*message*/,
98e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko                      const std::shared_ptr<Channel>& channel) override {
99e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    if (test_channel_ == channel)
100e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko      test_channel_ = nullptr;
101e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  }
102e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
103e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  void HandleImpulse(Message& message) override {
104e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    switch (message.GetOp()) {
105e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko      case TEST_OP_SET_TEST_CHANNEL:
106e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko        test_channel_ = message.GetChannel<TestChannel>();
107e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko        break;
108e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
109e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko      case TEST_OP_IMPULSE: {
110e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko        impulse_payload_.fill(0);
111e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko        std::copy(message.ImpulseBegin(), message.ImpulseEnd(),
112e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko                  impulse_payload_.begin());
113e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko        break;
114e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko      }
115e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
116e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko      case TEST_OP_POLLHUP_FROM_SERVICE: {
117e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko        message.ModifyChannelEvents(0, EPOLLHUP);
118e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko        break;
119e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko      }
120e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    }
121e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  }
122e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
123f0a7bd033941e26e380232a0515e903cf8e678e5Alex Vakulenko  Status<void> HandleMessage(Message& message) override {
124e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    switch (message.GetOp()) {
125e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko      case TEST_OP_GET_SERVICE_ID:
126f0a7bd033941e26e380232a0515e903cf8e678e5Alex Vakulenko        REPLY_MESSAGE_RETURN(message, service_id_, {});
127e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
128e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko      // Set the test channel to the TestChannel for the current channel. Other
129e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko      // messages can use this to perform tests.
130e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko      case TEST_OP_SET_TEST_CHANNEL:
131e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko        test_channel_ = message.GetChannel<TestChannel>();
132f0a7bd033941e26e380232a0515e903cf8e678e5Alex Vakulenko        REPLY_MESSAGE_RETURN(message, 0, {});
133e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
134e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko      // Return the channel id for the current channel.
135e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko      case TEST_OP_GET_THIS_CHANNEL_ID:
136f0a7bd033941e26e380232a0515e903cf8e678e5Alex Vakulenko        REPLY_MESSAGE_RETURN(message, message.GetChannelId(), {});
137e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
138e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko      // Return the channel id for the test channel.
139e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko      case TEST_OP_GET_TEST_CHANNEL_ID:
140e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko        if (test_channel_)
141f0a7bd033941e26e380232a0515e903cf8e678e5Alex Vakulenko          REPLY_MESSAGE_RETURN(message, test_channel_->channel_id(), {});
142e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko        else
143f0a7bd033941e26e380232a0515e903cf8e678e5Alex Vakulenko          REPLY_ERROR_RETURN(message, ENOENT, {});
144e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
145e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko      // Test check channel feature.
146e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko      case TEST_OP_CHECK_CHANNEL_ID: {
147e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko        ChannelReference ref = 0;
148f0a7bd033941e26e380232a0515e903cf8e678e5Alex Vakulenko        if (!message.ReadAll(&ref, sizeof(ref)))
149f0a7bd033941e26e380232a0515e903cf8e678e5Alex Vakulenko          REPLY_ERROR_RETURN(message, EIO, {});
150e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
151e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko        const Status<int> ret = message.CheckChannel<TestChannel>(ref, nullptr);
152f0a7bd033941e26e380232a0515e903cf8e678e5Alex Vakulenko        REPLY_MESSAGE_RETURN(message, ret, {});
153e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko      }
154e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
155e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko      case TEST_OP_CHECK_CHANNEL_OBJECT: {
156e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko        std::shared_ptr<TestChannel> channel;
157e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko        ChannelReference ref = 0;
158f0a7bd033941e26e380232a0515e903cf8e678e5Alex Vakulenko        if (!message.ReadAll(&ref, sizeof(ref)))
159f0a7bd033941e26e380232a0515e903cf8e678e5Alex Vakulenko          REPLY_ERROR_RETURN(message, EIO, {});
160e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
161e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko        const Status<int> ret =
162e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko            message.CheckChannel<TestChannel>(ref, &channel);
163e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko        if (!ret)
164f0a7bd033941e26e380232a0515e903cf8e678e5Alex Vakulenko          REPLY_MESSAGE_RETURN(message, ret, {});
165e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
166e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko        if (channel != nullptr)
167f0a7bd033941e26e380232a0515e903cf8e678e5Alex Vakulenko          REPLY_MESSAGE_RETURN(message, channel->channel_id(), {});
168e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko        else
169f0a7bd033941e26e380232a0515e903cf8e678e5Alex Vakulenko          REPLY_ERROR_RETURN(message, ENODATA, {});
170e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko      }
171e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
172e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko      case TEST_OP_CHECK_CHANNEL_FROM_OTHER_SERVICE: {
173e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko        ChannelReference ref = 0;
174f0a7bd033941e26e380232a0515e903cf8e678e5Alex Vakulenko        if (!message.ReadAll(&ref, sizeof(ref)))
175f0a7bd033941e26e380232a0515e903cf8e678e5Alex Vakulenko          REPLY_ERROR_RETURN(message, EIO, {});
176e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
177e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko        const Status<int> ret = message.CheckChannel<TestChannel>(
178e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko            other_service_.get(), ref, nullptr);
179f0a7bd033941e26e380232a0515e903cf8e678e5Alex Vakulenko        REPLY_MESSAGE_RETURN(message, ret, {});
180e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko      }
181e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
182e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko      case TEST_OP_GET_NEW_CHANNEL: {
183e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko        auto channel = std::make_shared<TestChannel>(-1);
184e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko        Status<RemoteChannelHandle> channel_handle =
185e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko            message.PushChannel(0, channel, &channel->channel_id_);
186f0a7bd033941e26e380232a0515e903cf8e678e5Alex Vakulenko        REPLY_MESSAGE_RETURN(message, channel_handle, {});
187e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko      }
188e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
189e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko      case TEST_OP_GET_NEW_CHANNEL_FROM_OTHER_SERVICE: {
190e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko        if (!other_service_)
191f0a7bd033941e26e380232a0515e903cf8e678e5Alex Vakulenko          REPLY_ERROR_RETURN(message, EINVAL, {});
192e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
193e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko        auto channel = std::make_shared<TestChannel>(-1);
194e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko        Status<RemoteChannelHandle> channel_handle = message.PushChannel(
195e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko            other_service_.get(), 0, channel, &channel->channel_id_);
196f0a7bd033941e26e380232a0515e903cf8e678e5Alex Vakulenko        REPLY_MESSAGE_RETURN(message, channel_handle, {});
197e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko      }
198e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
199e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko      case TEST_OP_GET_THIS_PROCESS_ID:
200f0a7bd033941e26e380232a0515e903cf8e678e5Alex Vakulenko        REPLY_MESSAGE_RETURN(message, message.GetProcessId(), {});
201e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
202e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko      case TEST_OP_GET_THIS_THREAD_ID:
203f0a7bd033941e26e380232a0515e903cf8e678e5Alex Vakulenko        REPLY_MESSAGE_RETURN(message, message.GetThreadId(), {});
204e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
205e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko      case TEST_OP_GET_THIS_EUID:
206f0a7bd033941e26e380232a0515e903cf8e678e5Alex Vakulenko        REPLY_MESSAGE_RETURN(message, message.GetEffectiveUserId(), {});
207e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
208e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko      case TEST_OP_GET_THIS_EGID:
209f0a7bd033941e26e380232a0515e903cf8e678e5Alex Vakulenko        REPLY_MESSAGE_RETURN(message, message.GetEffectiveGroupId(), {});
210e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
211e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko      case TEST_OP_POLLIN_FROM_SERVICE:
212e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko        REPLY_MESSAGE_RETURN(message, message.ModifyChannelEvents(0, EPOLLIN),
213f0a7bd033941e26e380232a0515e903cf8e678e5Alex Vakulenko                             {});
214e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
215e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko      case TEST_OP_SEND_LARGE_DATA_RETURN_SUM: {
216e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko        std::array<int, kLargeDataSize> data_array;
217f0a7bd033941e26e380232a0515e903cf8e678e5Alex Vakulenko        size_t size_to_read = data_array.size() * sizeof(int);
218f0a7bd033941e26e380232a0515e903cf8e678e5Alex Vakulenko        if (!message.ReadAll(data_array.data(), size_to_read)) {
219f0a7bd033941e26e380232a0515e903cf8e678e5Alex Vakulenko          REPLY_ERROR_RETURN(message, EIO, {});
220f0a7bd033941e26e380232a0515e903cf8e678e5Alex Vakulenko        }
221e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko        int sum = std::accumulate(data_array.begin(), data_array.end(), 0);
222f0a7bd033941e26e380232a0515e903cf8e678e5Alex Vakulenko        REPLY_MESSAGE_RETURN(message, sum, {});
223e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko      }
224e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
225e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko      default:
226e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko        return Service::DefaultHandleMessage(message);
227e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    }
228e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  }
229e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
230e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  const ImpulsePayload& GetImpulsePayload() const { return impulse_payload_; }
231e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
232e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko private:
233e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  friend BASE;
234e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
235e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  std::shared_ptr<TestChannel> test_channel_;
236e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  std::shared_ptr<TestService> other_service_;
237e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  int service_id_;
238e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  ImpulsePayload impulse_payload_;
239e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
240e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  static std::atomic<int> service_counter_;
241e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
242e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  TestService(const std::string& name,
243e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko              const std::shared_ptr<TestService>& other_service)
244e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko      : TestService(name, other_service, false) {}
245e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
246e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  TestService(const std::string& name,
247e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko              const std::shared_ptr<TestService>& other_service, bool blocking)
248e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko      : BASE(std::string("TestService") + name,
249f0a7bd033941e26e380232a0515e903cf8e678e5Alex Vakulenko             Endpoint::CreateAndBindSocket(kTestServicePath + name, blocking)),
250e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko        other_service_(other_service),
251e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko        service_id_(service_counter_++) {}
252e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
253e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  explicit TestService(const std::string& name) : TestService(name, nullptr) {}
254e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
255e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  TestService(const TestService&) = delete;
256e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  void operator=(const TestService&) = delete;
257e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko};
258e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
259e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenkostd::atomic<int> TestService::service_counter_;
260e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
261e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko// Test client to send messages to the test service.
262e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenkoclass TestClient : public ClientBase<TestClient> {
263e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko public:
264e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  // Requests the service id of the service this channel is connected to.
265e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  int GetServiceId() {
266e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    Transaction trans{*this};
267e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    return ReturnStatusOrError(trans.Send<int>(TEST_OP_GET_SERVICE_ID));
268e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  }
269e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
270e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  // Requests the test channel to be set to this client's channel.
271e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  int SetTestChannel() {
272e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    Transaction trans{*this};
273e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    return ReturnStatusOrError(trans.Send<int>(TEST_OP_SET_TEST_CHANNEL));
274e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  }
275e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
276e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  // Request the test channel to be set to this client's channel using an async
277e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  // message.
278e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  int SetTestChannelAsync() {
279e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    return ReturnStatusOrError(SendImpulse(TEST_OP_SET_TEST_CHANNEL));
280e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  }
281e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
282e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  // Sends a test async message with payload.
283e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  int SendAsync(const void* buffer, size_t length) {
284e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    Transaction trans{*this};
285e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    return ReturnStatusOrError(SendImpulse(TEST_OP_IMPULSE, buffer, length));
286e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  }
287e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
288e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  // Requests the channel id for this client.
289e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  int GetThisChannelId() {
290e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    Transaction trans{*this};
291e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    return ReturnStatusOrError(trans.Send<int>(TEST_OP_GET_THIS_CHANNEL_ID));
292e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  }
293e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
294e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  // Requests the channel id of the test channel.
295e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  int GetTestChannelId() {
296e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    Transaction trans{*this};
297e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    return ReturnStatusOrError(trans.Send<int>(TEST_OP_GET_TEST_CHANNEL_ID));
298e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  }
299e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
300e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  // Checks whether the fd |channel_id| is a channel to the test service.
301e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  // Returns the channel id of the channel.
302e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  int CheckChannelIdArgument(BorrowedChannelHandle channel) {
303e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    Transaction trans{*this};
304f0a7bd033941e26e380232a0515e903cf8e678e5Alex Vakulenko    ChannelReference ref = trans.PushChannelHandle(channel).get();
305e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    return ReturnStatusOrError(trans.Send<int>(TEST_OP_CHECK_CHANNEL_ID, &ref,
306e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko                                               sizeof(ref), nullptr, 0));
307e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  }
308e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
309e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  // Checks whether the fd |channel_id| is a channel to the test service.
310e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  // Returns the channel id of the channel exercising the context pointer.
311e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  int CheckChannelObjectArgument(BorrowedChannelHandle channel) {
312e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    Transaction trans{*this};
313f0a7bd033941e26e380232a0515e903cf8e678e5Alex Vakulenko    ChannelReference ref = trans.PushChannelHandle(channel).get();
314e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    return ReturnStatusOrError(trans.Send<int>(TEST_OP_CHECK_CHANNEL_OBJECT,
315e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko                                               &ref, sizeof(ref), nullptr, 0));
316e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  }
317e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
318e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  // Checks whether the fd |channel_fd| is a channel to the other test service.
319e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  // Returns 0 on success.
320e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  int CheckChannelFromOtherService(BorrowedChannelHandle channel) {
321e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    Transaction trans{*this};
322f0a7bd033941e26e380232a0515e903cf8e678e5Alex Vakulenko    ChannelReference ref = trans.PushChannelHandle(channel).get();
323e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    return ReturnStatusOrError(
324e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko        trans.Send<int>(TEST_OP_CHECK_CHANNEL_FROM_OTHER_SERVICE, &ref,
325e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko                        sizeof(ref), nullptr, 0));
326e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  }
327e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
328e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  // Requests a new channel to the service.
329e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  std::unique_ptr<TestClient> GetNewChannel() {
330e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    Transaction trans{*this};
331e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    auto status = trans.Send<LocalChannelHandle>(TEST_OP_GET_NEW_CHANNEL);
332e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    if (status)
333e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko      return TestClient::Create(status.take());
334e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    else
335e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko      return nullptr;
336e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  }
337e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
338e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  // Requests a new channel to the other service.
339e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  std::unique_ptr<TestClient> GetNewChannelFromOtherService() {
340e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    Transaction trans{*this};
341e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    auto status = trans.Send<LocalChannelHandle>(
342e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko        TEST_OP_GET_NEW_CHANNEL_FROM_OTHER_SERVICE);
343e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    if (status)
344e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko      return TestClient::Create(status.take());
345e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    else
346e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko      return nullptr;
347e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  }
348e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
349e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  // Requests an id from the message description.
350e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  pid_t GetThisProcessId() {
351e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    Transaction trans{*this};
352e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    return ReturnStatusOrError(trans.Send<int>(TEST_OP_GET_THIS_PROCESS_ID));
353e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  }
354e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  pid_t GetThisThreadId() {
355e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    Transaction trans{*this};
356e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    return ReturnStatusOrError(trans.Send<int>(TEST_OP_GET_THIS_THREAD_ID));
357e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  }
358e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  uid_t GetThisEffectiveUserId() {
359e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    Transaction trans{*this};
360e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    return ReturnStatusOrError(trans.Send<int>(TEST_OP_GET_THIS_EUID));
361e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  }
362e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  gid_t GetThisEffectiveGroupId() {
363e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    Transaction trans{*this};
364e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    return ReturnStatusOrError(trans.Send<int>(TEST_OP_GET_THIS_EGID));
365e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  }
366e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
367e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  int SendPollHupEvent() {
368e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    return ReturnStatusOrError(SendImpulse(TEST_OP_POLLHUP_FROM_SERVICE));
369e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  }
370e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
371e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  int SendPollInEvent() {
372e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    Transaction trans{*this};
373e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    return ReturnStatusOrError(trans.Send<int>(TEST_OP_POLLIN_FROM_SERVICE));
374e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  }
375e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
376e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  int SendLargeDataReturnSum(
377e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko      const std::array<int, kLargeDataSize>& data_array) {
378e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    Transaction trans{*this};
379e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    return ReturnStatusOrError(
380e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko        trans.Send<int>(TEST_OP_SEND_LARGE_DATA_RETURN_SUM, data_array.data(),
381e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko                        data_array.size() * sizeof(int), nullptr, 0));
382e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  }
383e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
384186d77217aaf769ff0a91753971e23bd249afca7Corey Tabaka  Status<int> GetEventMask(int events) {
385186d77217aaf769ff0a91753971e23bd249afca7Corey Tabaka    if (auto* client_channel = GetChannel()) {
386186d77217aaf769ff0a91753971e23bd249afca7Corey Tabaka      return client_channel->GetEventMask(events);
387186d77217aaf769ff0a91753971e23bd249afca7Corey Tabaka    } else {
388186d77217aaf769ff0a91753971e23bd249afca7Corey Tabaka      return ErrorStatus(EINVAL);
389186d77217aaf769ff0a91753971e23bd249afca7Corey Tabaka    }
390186d77217aaf769ff0a91753971e23bd249afca7Corey Tabaka  }
391186d77217aaf769ff0a91753971e23bd249afca7Corey Tabaka
392e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  using ClientBase<TestClient>::event_fd;
393e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
394e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  enum : size_t { kMaxPayload = MAX_IMPULSE_LENGTH };
395e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
396e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko private:
397e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  friend BASE;
398e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
399e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  explicit TestClient(const std::string& name)
400e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko      : BASE{android::pdx::uds::ClientChannelFactory::Create(kTestServicePath +
401e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko                                                             name)} {}
402e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
403e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  explicit TestClient(LocalChannelHandle channel)
404e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko      : BASE{android::pdx::uds::ClientChannel::Create(std::move(channel))} {}
405e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
406e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  TestClient(const TestClient&) = delete;
407e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  void operator=(const TestClient&) = delete;
408e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko};
409e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
410e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko}  // anonymous namespace
411e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
412e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko// Use a test fixture to ensure proper order of cleanup between clients,
413e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko// services, and the dispatcher. These objects are cleaned up in the same
414e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko// thread, order is important; either the service or the client must be
415e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko// destroyed before the dispatcher is stopped. The reason for this is that
416e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko// clients send blocking "close" messages to their respective services on
417e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko// destruction. If this happens after the dispatcher is stopped the client
418e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko// destructor will get blocked waiting for a reply that will never come. In
419e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko// normal use of the service framework this is never an issue because clients
420e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko// and the dispatcher for the same service are never destructed in the same
421e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko// thread (they live in different processes).
422e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenkoclass ServiceFrameworkTest : public ::testing::Test {
423e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko protected:
424e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  std::unique_ptr<ServiceDispatcher> dispatcher_;
425e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  std::thread dispatch_thread_;
426e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
427e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  void SetUp() override {
428e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    // Create a dispatcher to handle messages to services.
4295a244ed36c8e45fd95b89ff916caf083fb182ec1Alex Vakulenko    dispatcher_ = android::pdx::ServiceDispatcher::Create();
430e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    ASSERT_NE(nullptr, dispatcher_);
431e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
432e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    // Start the message dispatch loop in a separate thread.
433e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    dispatch_thread_ = std::thread(
434e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko        std::bind(&ServiceDispatcher::EnterDispatchLoop, dispatcher_.get()));
435e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  }
436e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
437e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  void TearDown() override {
438e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    if (dispatcher_) {
439e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko      // Cancel the dispatcher and wait for the thread to terminate. Explicitly
440e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko      // join the thread so that destruction doesn't deallocate the dispatcher
441e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko      // before the thread finishes.
442e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko      dispatcher_->SetCanceled(true);
443e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko      dispatch_thread_.join();
444e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    }
445e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  }
446e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko};
447e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
448e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko// Test basic operation of TestService/TestClient classes.
449e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex VakulenkoTEST_F(ServiceFrameworkTest, BasicClientService) {
450e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  // Create a test service and add it to the dispatcher.
451e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  auto service = TestService::Create(kTestService1);
452e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  ASSERT_NE(nullptr, service);
453e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  ASSERT_EQ(0, dispatcher_->AddService(service));
454e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
455e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  // Create a client to service.
456e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  auto client = TestClient::Create(kTestService1);
457e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  ASSERT_NE(nullptr, client);
458e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
459e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  // Get the channel id that will be returned by the next tests.
460e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  const int channel_id = client->GetThisChannelId();
461e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  EXPECT_LE(0, channel_id);
462e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
463e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  // Check return value before test channel is set.
464e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  EXPECT_EQ(-ENOENT, client->GetTestChannelId());
465e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
466e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  // Set test channel and perform the test again.
467e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  EXPECT_EQ(0, client->SetTestChannel());
468e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  EXPECT_EQ(channel_id, client->GetTestChannelId());
469e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko}
470e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
471e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko// Test impulses.
472e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex VakulenkoTEST_F(ServiceFrameworkTest, Impulse) {
473e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  // Create a test service and add it to the dispatcher.
474e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  auto service = TestService::Create(kTestService1);
475e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  ASSERT_NE(nullptr, service);
476e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  ASSERT_EQ(0, dispatcher_->AddService(service));
477e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
478e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  auto client = TestClient::Create(kTestService1);
479e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  ASSERT_NE(nullptr, client);
480e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
481e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  // Get the channel id that will be returned by the next tests.
482e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  const int channel_id = client->GetThisChannelId();
483e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  EXPECT_LE(0, channel_id);
484e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
485e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  // Check return value before test channel is set.
486e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  EXPECT_EQ(-ENOENT, client->GetTestChannelId());
487e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
488e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  // Set test channel with an impulse and perform the test again.
489e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  EXPECT_EQ(0, client->SetTestChannelAsync());
490e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  EXPECT_EQ(channel_id, client->GetTestChannelId());
491e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
492e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  ImpulsePayload expected_payload = {{'a', 'b', 'c'}};
493e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  EXPECT_EQ(0, client->SendAsync(expected_payload.data(), 3));
494e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  // Send a synchronous message to make sure the async message is handled before
495e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  // we check the payload.
496e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  client->GetThisChannelId();
497e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  EXPECT_EQ(expected_payload, service->GetImpulsePayload());
498e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
499e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  // Impulse payloads are limited to 4 machine words.
500e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  EXPECT_EQ(
501e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko      0, client->SendAsync(expected_payload.data(), TestClient::kMaxPayload));
502e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  EXPECT_EQ(-EINVAL, client->SendAsync(expected_payload.data(),
503e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko                                       TestClient::kMaxPayload + 1));
504e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
505e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  // Test invalid pointer.
506e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  const std::uint8_t* invalid_pointer = nullptr;
507e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  EXPECT_EQ(-EINVAL, client->SendAsync(invalid_pointer, sizeof(int)));
508e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko}
509e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
51052ea25cf06cef250ec73052611b48556b3fce4d5Corey Tabaka// Test impulses.
51152ea25cf06cef250ec73052611b48556b3fce4d5Corey TabakaTEST_F(ServiceFrameworkTest, ImpulseHangup) {
51252ea25cf06cef250ec73052611b48556b3fce4d5Corey Tabaka  // Create a test service and add it to the dispatcher.
51352ea25cf06cef250ec73052611b48556b3fce4d5Corey Tabaka  auto service = TestService::Create(kTestService1);
51452ea25cf06cef250ec73052611b48556b3fce4d5Corey Tabaka  ASSERT_NE(nullptr, service);
51552ea25cf06cef250ec73052611b48556b3fce4d5Corey Tabaka  ASSERT_EQ(0, dispatcher_->AddService(service));
51652ea25cf06cef250ec73052611b48556b3fce4d5Corey Tabaka
51752ea25cf06cef250ec73052611b48556b3fce4d5Corey Tabaka  auto client = TestClient::Create(kTestService1);
51852ea25cf06cef250ec73052611b48556b3fce4d5Corey Tabaka  ASSERT_NE(nullptr, client);
51952ea25cf06cef250ec73052611b48556b3fce4d5Corey Tabaka
52052ea25cf06cef250ec73052611b48556b3fce4d5Corey Tabaka  const int kMaxIterations = 1000;
52152ea25cf06cef250ec73052611b48556b3fce4d5Corey Tabaka  for (int i = 0; i < kMaxIterations; i++) {
52252ea25cf06cef250ec73052611b48556b3fce4d5Corey Tabaka    auto impulse_client = TestClient::Create(kTestService1);
52352ea25cf06cef250ec73052611b48556b3fce4d5Corey Tabaka    ASSERT_NE(nullptr, impulse_client);
52452ea25cf06cef250ec73052611b48556b3fce4d5Corey Tabaka
52552ea25cf06cef250ec73052611b48556b3fce4d5Corey Tabaka    const uint8_t a = (i >> 0) & 0xff;
52652ea25cf06cef250ec73052611b48556b3fce4d5Corey Tabaka    const uint8_t b = (i >> 8) & 0xff;
52752ea25cf06cef250ec73052611b48556b3fce4d5Corey Tabaka    const uint8_t c = (i >> 16) & 0xff;
52852ea25cf06cef250ec73052611b48556b3fce4d5Corey Tabaka    const uint8_t d = (i >> 24) & 0xff;
52952ea25cf06cef250ec73052611b48556b3fce4d5Corey Tabaka    ImpulsePayload expected_payload = {{a, b, c, d}};
53052ea25cf06cef250ec73052611b48556b3fce4d5Corey Tabaka    EXPECT_EQ(0, impulse_client->SendAsync(expected_payload.data(), 4));
53152ea25cf06cef250ec73052611b48556b3fce4d5Corey Tabaka
53252ea25cf06cef250ec73052611b48556b3fce4d5Corey Tabaka    // Hangup the impulse test client, then send a sync message over client to
53352ea25cf06cef250ec73052611b48556b3fce4d5Corey Tabaka    // make sure the hangup message is handled before checking the impulse
53452ea25cf06cef250ec73052611b48556b3fce4d5Corey Tabaka    // payload.
53552ea25cf06cef250ec73052611b48556b3fce4d5Corey Tabaka    impulse_client = nullptr;
53652ea25cf06cef250ec73052611b48556b3fce4d5Corey Tabaka    client->GetThisChannelId();
53752ea25cf06cef250ec73052611b48556b3fce4d5Corey Tabaka    EXPECT_EQ(expected_payload, service->GetImpulsePayload());
53852ea25cf06cef250ec73052611b48556b3fce4d5Corey Tabaka  }
53952ea25cf06cef250ec73052611b48556b3fce4d5Corey Tabaka}
54052ea25cf06cef250ec73052611b48556b3fce4d5Corey Tabaka
541e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko// Test Message::PushChannel/Service::PushChannel API.
542e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex VakulenkoTEST_F(ServiceFrameworkTest, PushChannel) {
543e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  // Create a test service and add it to the dispatcher.
544e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  auto other_service = TestService::Create(kTestService1);
545e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  ASSERT_NE(nullptr, other_service);
546e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  ASSERT_EQ(0, dispatcher_->AddService(other_service));
547e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
548e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  // Create a second test service and add it to the dispatcher.
549e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  auto service = TestService::Create(kTestService2, other_service);
550e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  ASSERT_NE(nullptr, service);
551e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  ASSERT_EQ(0, dispatcher_->AddService(service));
552e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
553e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  // Create a client to the second test service.
554e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  auto client1 = TestClient::Create(kTestService2);
555e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  ASSERT_NE(nullptr, client1);
556e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
557e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  // Test the creation of new channels using the push APIs.
558e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  const int channel_id1 = client1->GetThisChannelId();
559e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  EXPECT_LE(0, channel_id1);
560e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
561e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  auto client2 = client1->GetNewChannel();
562e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  EXPECT_NE(nullptr, client2);
563e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  EXPECT_NE(client1->event_fd(), client2->event_fd());
564e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
565e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  const int channel_id2 = client2->GetThisChannelId();
566e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  EXPECT_LE(0, channel_id2);
567e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  EXPECT_NE(channel_id1, channel_id2);
568e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
569e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  auto client3 = client1->GetNewChannelFromOtherService();
570e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  EXPECT_NE(nullptr, client3);
571e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  EXPECT_NE(client1->event_fd(), client3->event_fd());
572e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
573e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  const int channel_id3 = client3->GetThisChannelId();
574e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  EXPECT_LE(0, channel_id3);
575e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
576e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  // Test which services the channels are connected to.
577e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  const int service_id1 = client1->GetServiceId();
578e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  EXPECT_LE(0, service_id1);
579e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
580e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  const int service_id2 = client2->GetServiceId();
581e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  EXPECT_LE(0, service_id2);
582e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
583e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  const int service_id3 = client3->GetServiceId();
584e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  EXPECT_LE(0, service_id3);
585e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
586e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  EXPECT_EQ(service_id1, service_id2);
587e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  EXPECT_NE(service_id1, service_id3);
588e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko}
589e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
590e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko// Tests process id, thread id, effective user id, and effective group id
591e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko// returned in the message description.
592e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex VakulenkoTEST_F(ServiceFrameworkTest, Ids) {
593e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  // Create a test service and add it to the dispatcher.
594e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  auto service = TestService::Create(kTestService1);
595e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  ASSERT_NE(nullptr, service);
596e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  ASSERT_EQ(0, dispatcher_->AddService(service));
597e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
598e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  // Create a client to service.
599e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  auto client = TestClient::Create(kTestService1);
600e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  ASSERT_NE(nullptr, client);
601e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
602e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  // Pids 0-2 are defined, no user task should have them.
603e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
604e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  const pid_t process_id1 = client->GetThisProcessId();
605e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  EXPECT_LT(2, process_id1);
606e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
607e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  pid_t process_id2;
608e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
60952ea25cf06cef250ec73052611b48556b3fce4d5Corey Tabaka  std::thread thread([&]() { process_id2 = client->GetThisProcessId(); });
610e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  thread.join();
611e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
612e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  EXPECT_LT(2, process_id2);
613e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  EXPECT_EQ(process_id1, process_id2);
614e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
615e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  // This test must run as root for the rest of these tests to work.
616e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  const int euid1 = client->GetThisEffectiveUserId();
617e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  ASSERT_EQ(0, euid1);
618e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
619e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  const int egid1 = client->GetThisEffectiveGroupId();
620e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  EXPECT_EQ(0, egid1);
621e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
622e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  // Set effective uid/gid to system.
623e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  ASSERT_EQ(0, setegid(AID_SYSTEM));
624e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  ASSERT_EQ(0, seteuid(AID_SYSTEM));
625e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
626e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  const int euid2 = client->GetThisEffectiveUserId();
627e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  EXPECT_EQ(AID_SYSTEM, euid2);
628e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
629e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  const int egid2 = client->GetThisEffectiveGroupId();
630e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  EXPECT_EQ(AID_SYSTEM, egid2);
631e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
632e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  // Set the euid/egid back to root.
633e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  ASSERT_EQ(0, setegid(0));
634e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  ASSERT_EQ(0, seteuid(0));
635e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko}
636e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
637e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex VakulenkoTEST_F(ServiceFrameworkTest, PollIn) {
638e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  // Create a test service and add it to the dispatcher.
639e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  auto service = TestService::Create(kTestService1);
640e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  ASSERT_NE(nullptr, service);
641e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  ASSERT_EQ(0, dispatcher_->AddService(service));
642e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
643e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  // Create a client to service.
644e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  auto client = TestClient::Create(kTestService1);
645e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  ASSERT_NE(nullptr, client);
646e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
64752ea25cf06cef250ec73052611b48556b3fce4d5Corey Tabaka  pollfd pfd{client->event_fd(), POLLIN, 0};
64852ea25cf06cef250ec73052611b48556b3fce4d5Corey Tabaka  int count = poll(&pfd, 1, 0);
649e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  ASSERT_EQ(0, count);
650e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
651e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  client->SendPollInEvent();
652e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
65352ea25cf06cef250ec73052611b48556b3fce4d5Corey Tabaka  count = poll(&pfd, 1, 10000 /*10s*/);
654e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  ASSERT_EQ(1, count);
65552ea25cf06cef250ec73052611b48556b3fce4d5Corey Tabaka  ASSERT_TRUE((POLLIN & pfd.revents) != 0);
656e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko}
657e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
658e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex VakulenkoTEST_F(ServiceFrameworkTest, PollHup) {
659e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  // Create a test service and add it to the dispatcher.
660e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  auto service = TestService::Create(kTestService1);
661e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  ASSERT_NE(nullptr, service);
662e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  ASSERT_EQ(0, dispatcher_->AddService(service));
663e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
664e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  // Create a client to service.
665e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  auto client = TestClient::Create(kTestService1);
666e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  ASSERT_NE(nullptr, client);
667e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
66852ea25cf06cef250ec73052611b48556b3fce4d5Corey Tabaka  pollfd pfd{client->event_fd(), POLLIN, 0};
66952ea25cf06cef250ec73052611b48556b3fce4d5Corey Tabaka  int count = poll(&pfd, 1, 0);
670e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  ASSERT_EQ(0, count);
671e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
672e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  client->SendPollHupEvent();
673e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
67452ea25cf06cef250ec73052611b48556b3fce4d5Corey Tabaka  count = poll(&pfd, 1, 10000 /*10s*/);
675e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  ASSERT_EQ(1, count);
67652ea25cf06cef250ec73052611b48556b3fce4d5Corey Tabaka  auto event_status = client->GetEventMask(pfd.revents);
677186d77217aaf769ff0a91753971e23bd249afca7Corey Tabaka  ASSERT_TRUE(event_status.ok());
678186d77217aaf769ff0a91753971e23bd249afca7Corey Tabaka  ASSERT_TRUE((EPOLLHUP & event_status.get()) != 0);
679e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko}
680e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
681e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex VakulenkoTEST_F(ServiceFrameworkTest, LargeDataSum) {
682e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  // Create a test service and add it to the dispatcher.
683e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  auto service = TestService::Create(kTestService1);
684e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  ASSERT_NE(nullptr, service);
685e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  ASSERT_EQ(0, dispatcher_->AddService(service));
686e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
687e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  // Create a client to service.
688e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  auto client = TestClient::Create(kTestService1);
689e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  ASSERT_NE(nullptr, client);
690e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
691e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  std::array<int, kLargeDataSize> data_array;
692e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  std::iota(data_array.begin(), data_array.end(), 0);
693e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  int expected_sum = std::accumulate(data_array.begin(), data_array.end(), 0);
694e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  int sum = client->SendLargeDataReturnSum(data_array);
695e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  ASSERT_EQ(expected_sum, sum);
696e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko}
697e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
698e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex VakulenkoTEST_F(ServiceFrameworkTest, Cancel) {
699e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  // Create a test service and add it to the dispatcher.
700e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  auto service = TestService::Create(kTestService1, nullptr, true);
701e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  ASSERT_NE(nullptr, service);
702e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  ASSERT_EQ(0, dispatcher_->AddService(service));
703e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
704e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  // Create a client to service.
705e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  auto client = TestClient::Create(kTestService1);
706e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  ASSERT_NE(nullptr, client);
707e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
708e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  auto previous_time = std::chrono::system_clock::now();
709e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  dispatcher_->ReceiveAndDispatch(100);  // 0.1 seconds should block.
710e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  auto time = std::chrono::system_clock::now();
711e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  ASSERT_LE(100, std::chrono::duration_cast<std::chrono::milliseconds>(
712e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko                     time - previous_time)
713e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko                     .count());
714e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  service->Cancel();
715e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  // Non-blocking. Return immediately.
716e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  dispatcher_->ReceiveAndDispatch(-1);
717e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  dispatcher_->ReceiveAndDispatch(-1);
718e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko}
719