summaryrefslogtreecommitdiffstats
path: root/base/sync_socket_unittest.cc
blob: 97a1aec47d3a5b06b9a5952900efe02116eff40e (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
// Copyright 2013 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "base/macros.h"
#include "base/sync_socket.h"
#include "base/threading/simple_thread.h"
#include "base/time/time.h"
#include "testing/gtest/include/gtest/gtest.h"

namespace {

const int kReceiveTimeoutInMilliseconds = 750;

class HangingReceiveThread : public base::DelegateSimpleThread::Delegate {
 public:
  explicit HangingReceiveThread(base::SyncSocket* socket)
      : socket_(socket),
        thread_(this, "HangingReceiveThread") {
    thread_.Start();
  }

  ~HangingReceiveThread() override {}

  void Run() override {
    int data = 0;
    ASSERT_EQ(socket_->Peek(), 0u);

    // Use receive with timeout so we don't hang the test harness indefinitely.
    ASSERT_EQ(0u, socket_->ReceiveWithTimeout(
        &data, sizeof(data), base::TimeDelta::FromMilliseconds(
            kReceiveTimeoutInMilliseconds)));
  }

  void Stop() {
    thread_.Join();
  }

 private:
  base::SyncSocket* socket_;
  base::DelegateSimpleThread thread_;

  DISALLOW_COPY_AND_ASSIGN(HangingReceiveThread);
};

// Tests sending data between two SyncSockets.  Uses ASSERT() and thus will exit
// early upon failure.  Callers should use ASSERT_NO_FATAL_FAILURE() if testing
// continues after return.
void SendReceivePeek(base::SyncSocket* socket_a, base::SyncSocket* socket_b) {
  int received = 0;
  const int kSending = 123;
  static_assert(sizeof(kSending) == sizeof(received), "invalid data size");

  ASSERT_EQ(0u, socket_a->Peek());
  ASSERT_EQ(0u, socket_b->Peek());

  // Verify |socket_a| can send to |socket_a| and |socket_a| can Receive from
  // |socket_a|.
  ASSERT_EQ(sizeof(kSending), socket_a->Send(&kSending, sizeof(kSending)));
  ASSERT_EQ(sizeof(kSending), socket_b->Peek());
  ASSERT_EQ(sizeof(kSending), socket_b->Receive(&received, sizeof(kSending)));
  ASSERT_EQ(kSending, received);

  ASSERT_EQ(0u, socket_a->Peek());
  ASSERT_EQ(0u, socket_b->Peek());

  // Now verify the reverse.
  received = 0;
  ASSERT_EQ(sizeof(kSending), socket_b->Send(&kSending, sizeof(kSending)));
  ASSERT_EQ(sizeof(kSending), socket_a->Peek());
  ASSERT_EQ(sizeof(kSending), socket_a->Receive(&received, sizeof(kSending)));
  ASSERT_EQ(kSending, received);

  ASSERT_EQ(0u, socket_a->Peek());
  ASSERT_EQ(0u, socket_b->Peek());

  ASSERT_TRUE(socket_a->Close());
  ASSERT_TRUE(socket_b->Close());
}

template <class SocketType>
void NormalSendReceivePeek() {
  SocketType socket_a, socket_b;
  ASSERT_TRUE(SocketType::CreatePair(&socket_a, &socket_b));
  SendReceivePeek(&socket_a, &socket_b);
}

template <class SocketType>
void ClonedSendReceivePeek() {
  SocketType socket_a, socket_b;
  ASSERT_TRUE(SocketType::CreatePair(&socket_a, &socket_b));

  // Create new SyncSockets from the paired handles.
  SocketType socket_c(socket_a.handle()), socket_d(socket_b.handle());
  SendReceivePeek(&socket_c, &socket_d);
}

}  // namespace

TEST(SyncSocket, NormalSendReceivePeek) {
  NormalSendReceivePeek<base::SyncSocket>();
}

TEST(SyncSocket, ClonedSendReceivePeek) {
  ClonedSendReceivePeek<base::SyncSocket>();
}

TEST(CancelableSyncSocket, NormalSendReceivePeek) {
  NormalSendReceivePeek<base::CancelableSyncSocket>();
}

TEST(CancelableSyncSocket, ClonedSendReceivePeek) {
  ClonedSendReceivePeek<base::CancelableSyncSocket>();
}

TEST(CancelableSyncSocket, CancelReceiveShutdown) {
  base::CancelableSyncSocket socket_a, socket_b;
  ASSERT_TRUE(base::CancelableSyncSocket::CreatePair(&socket_a, &socket_b));

  base::TimeTicks start = base::TimeTicks::Now();
  HangingReceiveThread thread(&socket_b);
  ASSERT_TRUE(socket_b.Shutdown());
  thread.Stop();

  // Ensure the receive didn't just timeout.
  ASSERT_LT((base::TimeTicks::Now() - start).InMilliseconds(),
            kReceiveTimeoutInMilliseconds);

  ASSERT_TRUE(socket_a.Close());
  ASSERT_TRUE(socket_b.Close());
}