1ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// Copyright (c) 2011 The Chromium Authors. All rights reserved.
2c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Use of this source code is governed by a BSD-style license that can be
3c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// found in the LICENSE file.
4c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
5c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#ifndef NET_BASE_LISTEN_SOCKET_UNITTEST_H_
6c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#define NET_BASE_LISTEN_SOCKET_UNITTEST_H_
73345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#pragma once
8c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
9c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "build/build_config.h"
10c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
11c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#if defined(OS_WIN)
12c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include <winsock2.h>
13c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#elif defined(OS_POSIX)
14c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include <sys/socket.h>
15c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include <errno.h>
16c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include <arpa/inet.h>
17c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#endif
18c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
19c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "base/basictypes.h"
20ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "base/memory/scoped_ptr.h"
21c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "base/message_loop.h"
22c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "base/string_util.h"
233f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen#include "base/synchronization/condition_variable.h"
243f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen#include "base/synchronization/lock.h"
253f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen#include "base/threading/thread.h"
26c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "net/base/listen_socket.h"
273345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#include "net/base/net_util.h"
28c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "net/base/winsock_init.h"
29c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "testing/gtest/include/gtest/gtest.h"
30c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
31c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#if defined(OS_POSIX)
32c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Used same name as in Windows to avoid #ifdef where refrenced
33c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#define SOCKET int
34c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottconst int INVALID_SOCKET = -1;
35c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottconst int SOCKET_ERROR = -1;
36c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#endif
37c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
38c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottenum ActionType {
39c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  ACTION_NONE = 0,
40c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  ACTION_LISTEN = 1,
41c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  ACTION_ACCEPT = 2,
42c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  ACTION_READ = 3,
43c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  ACTION_SEND = 4,
44c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  ACTION_CLOSE = 5,
45c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  ACTION_SHUTDOWN = 6
46c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott};
47c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
48c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottclass ListenSocketTestAction {
49c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott public:
50c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  ListenSocketTestAction() : action_(ACTION_NONE) {}
51c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  explicit ListenSocketTestAction(ActionType action) : action_(action) {}
52c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  ListenSocketTestAction(ActionType action, std::string data)
53c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      : action_(action),
54c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        data_(data) {}
55c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
56c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  const std::string data() const { return data_; }
57c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  ActionType type() const { return action_; }
58c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
59c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott private:
60c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  ActionType action_;
61c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  std::string data_;
62c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott};
63c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
64c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
65c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// This had to be split out into a separate class because I couldn't
66c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// make a the testing::Test class refcounted.
67c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottclass ListenSocketTester :
68c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    public ListenSocket::ListenSocketDelegate,
69c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    public base::RefCountedThreadSafe<ListenSocketTester> {
70c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
71c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott public:
7272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  ListenSocketTester();
73c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
7472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  void SetUp();
7572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  void TearDown();
76c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
77c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  void ReportAction(const ListenSocketTestAction& action);
783345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  void NextAction();
79c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
80c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // read all pending data from the test socket
81c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  int ClearTestSocket();
82c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // Release the connection and server sockets
83c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  void Shutdown();
84c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  void Listen();
85c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  void SendFromTester();
86c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // verify the send/read from client to server
87c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  void TestClientSend();
88c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // verify send/read of a longer string
89c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  void TestClientSendLong();
90c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // verify a send/read from server to client
91c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  void TestServerSend();
92c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
9372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  virtual bool Send(SOCKET sock, const std::string& str);
9472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
9572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  // ListenSocket::ListenSocketDelegate:
9672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  virtual void DidAccept(ListenSocket *server, ListenSocket *connection);
9772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  virtual void DidRead(ListenSocket *connection, const char* data, int len);
9872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  virtual void DidClose(ListenSocket *sock);
9972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
100c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  scoped_ptr<base::Thread> thread_;
101c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  MessageLoopForIO* loop_;
102c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  ListenSocket* server_;
103c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  ListenSocket* connection_;
104c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  ListenSocketTestAction last_action_;
1053345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
106c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  SOCKET test_socket_;
107c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  static const int kTestPort;
1083345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
1093f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen  base::Lock lock_;  // protects |queue_| and wraps |cv_|
1103f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen  base::ConditionVariable cv_;
1113345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  std::deque<ListenSocketTestAction> queue_;
11272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
11372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen protected:
11472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  friend class base::RefCountedThreadSafe<ListenSocketTester>;
11572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
11672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  virtual ~ListenSocketTester();
11772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
11872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  virtual ListenSocket* DoListen();
119c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott};
120c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
121c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#endif  // NET_BASE_LISTEN_SOCKET_UNITTEST_H_
122