18bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)// Copyright 2013 The Chromium Authors. All rights reserved.
28bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
38bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)// found in the LICENSE file.
48bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
58bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)#include "base/basictypes.h"
68bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)#include "base/sync_socket.h"
78bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)#include "base/threading/simple_thread.h"
88bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)#include "base/time/time.h"
98bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)#include "testing/gtest/include/gtest/gtest.h"
108bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
118bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)namespace {
128bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
138bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)const int kReceiveTimeoutInMilliseconds = 750;
148bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
158bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)class HangingReceiveThread : public base::DelegateSimpleThread::Delegate {
168bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) public:
178bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  explicit HangingReceiveThread(base::SyncSocket* socket)
188bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)      : socket_(socket),
198bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)        thread_(this, "HangingReceiveThread") {
208bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    thread_.Start();
218bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  }
228bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
238bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  virtual ~HangingReceiveThread() {}
248bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
258bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  virtual void Run() OVERRIDE {
268bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    int data = 0;
278bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    ASSERT_EQ(socket_->Peek(), 0u);
288bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
298bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    // Use receive with timeout so we don't hang the test harness indefinitely.
308bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    ASSERT_EQ(0u, socket_->ReceiveWithTimeout(
318bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)        &data, sizeof(data), base::TimeDelta::FromMilliseconds(
328bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)            kReceiveTimeoutInMilliseconds)));
338bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  }
348bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
358bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  void Stop() {
368bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    thread_.Join();
378bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  }
388bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
398bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) private:
408bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  base::SyncSocket* socket_;
418bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  base::DelegateSimpleThread thread_;
428bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
438bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(HangingReceiveThread);
448bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)};
458bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
468bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)// Tests sending data between two SyncSockets.  Uses ASSERT() and thus will exit
478bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)// early upon failure.  Callers should use ASSERT_NO_FATAL_FAILURE() if testing
488bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)// continues after return.
498bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)void SendReceivePeek(base::SyncSocket* socket_a, base::SyncSocket* socket_b) {
508bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  int received = 0;
518bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  const int kSending = 123;
528bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  COMPILE_ASSERT(sizeof(kSending) == sizeof(received), Invalid_Data_Size);
538bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
548bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  ASSERT_EQ(0u, socket_a->Peek());
558bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  ASSERT_EQ(0u, socket_b->Peek());
568bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
578bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  // Verify |socket_a| can send to |socket_a| and |socket_a| can Receive from
588bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  // |socket_a|.
598bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  ASSERT_EQ(sizeof(kSending), socket_a->Send(&kSending, sizeof(kSending)));
608bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  ASSERT_EQ(sizeof(kSending), socket_b->Peek());
618bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  ASSERT_EQ(sizeof(kSending), socket_b->Receive(&received, sizeof(kSending)));
628bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  ASSERT_EQ(kSending, received);
638bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
648bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  ASSERT_EQ(0u, socket_a->Peek());
658bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  ASSERT_EQ(0u, socket_b->Peek());
668bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
678bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  // Now verify the reverse.
688bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  received = 0;
698bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  ASSERT_EQ(sizeof(kSending), socket_b->Send(&kSending, sizeof(kSending)));
708bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  ASSERT_EQ(sizeof(kSending), socket_a->Peek());
718bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  ASSERT_EQ(sizeof(kSending), socket_a->Receive(&received, sizeof(kSending)));
728bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  ASSERT_EQ(kSending, received);
738bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
748bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  ASSERT_EQ(0u, socket_a->Peek());
758bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  ASSERT_EQ(0u, socket_b->Peek());
768bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
778bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  ASSERT_TRUE(socket_a->Close());
788bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  ASSERT_TRUE(socket_b->Close());
798bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)}
808bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
818bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)template <class SocketType>
828bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)void NormalSendReceivePeek() {
838bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  SocketType socket_a, socket_b;
848bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  ASSERT_TRUE(SocketType::CreatePair(&socket_a, &socket_b));
858bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  SendReceivePeek(&socket_a, &socket_b);
868bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)}
878bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
888bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)template <class SocketType>
898bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)void ClonedSendReceivePeek() {
908bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  SocketType socket_a, socket_b;
918bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  ASSERT_TRUE(SocketType::CreatePair(&socket_a, &socket_b));
928bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
938bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  // Create new SyncSockets from the paired handles.
948bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  SocketType socket_c(socket_a.handle()), socket_d(socket_b.handle());
958bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  SendReceivePeek(&socket_c, &socket_d);
968bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)}
978bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
988bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)}  // namespace
998bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
1008bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)TEST(SyncSocket, NormalSendReceivePeek) {
1018bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  NormalSendReceivePeek<base::SyncSocket>();
1028bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)}
1038bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
1048bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)TEST(SyncSocket, ClonedSendReceivePeek) {
1058bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  ClonedSendReceivePeek<base::SyncSocket>();
1068bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)}
1078bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
1088bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)TEST(CancelableSyncSocket, NormalSendReceivePeek) {
1098bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  NormalSendReceivePeek<base::CancelableSyncSocket>();
1108bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)}
1118bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
1128bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)TEST(CancelableSyncSocket, ClonedSendReceivePeek) {
1138bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  ClonedSendReceivePeek<base::CancelableSyncSocket>();
1148bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)}
1158bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
1168bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)TEST(CancelableSyncSocket, CancelReceiveShutdown) {
1178bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  base::CancelableSyncSocket socket_a, socket_b;
1188bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  ASSERT_TRUE(base::CancelableSyncSocket::CreatePair(&socket_a, &socket_b));
1198bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
1208bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  base::TimeTicks start = base::TimeTicks::Now();
1218bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  HangingReceiveThread thread(&socket_b);
1228bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  ASSERT_TRUE(socket_b.Shutdown());
1238bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  thread.Stop();
1248bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
1258bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  // Ensure the receive didn't just timeout.
1268bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  ASSERT_LT((base::TimeTicks::Now() - start).InMilliseconds(),
1278bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)            kReceiveTimeoutInMilliseconds);
1288bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
1298bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  ASSERT_TRUE(socket_a.Close());
1308bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  ASSERT_TRUE(socket_b.Close());
1318bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)}
132