1// Copyright 2013 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "net/quic/port_suggester.h"
6
7#include <set>
8
9#include "base/basictypes.h"
10#include "net/base/host_port_pair.h"
11#include "testing/gtest/include/gtest/gtest.h"
12
13namespace net {
14namespace test {
15
16class PortSuggesterTest : public ::testing::Test {
17 protected:
18  PortSuggesterTest()
19      : entropy_(1345689),
20        min_ephemeral_port_(1025),
21        max_ephemeral_port_(65535) {
22  }
23
24  uint64 entropy_;
25  int min_ephemeral_port_;
26  int max_ephemeral_port_;
27};
28
29TEST_F(PortSuggesterTest, SmallRangeTest) {
30  // When the range is small (one wide), we always get that as our answer.
31  scoped_refptr<PortSuggester> port_suggester =
32      new PortSuggester(HostPortPair("www.example.com", 443), entropy_);
33  // Test this for a few different (small) ranges.
34  for (int port = 2000; port < 2010; ++port) {
35    // Use |port| for both |min| and |max| delimiting the suggestion range.
36    EXPECT_EQ(port, port_suggester->SuggestPort(port, port));
37    EXPECT_EQ(port, port_suggester->previous_suggestion());
38  }
39}
40
41TEST_F(PortSuggesterTest, SuggestAllPorts) {
42  // We should eventually fill out any range, but we'll just ensure that we
43  // fill out a small range of ports.
44  scoped_refptr<PortSuggester> port_suggester =
45      new PortSuggester(HostPortPair("www.example.com", 443), entropy_);
46  std::set<int> ports;
47  const uint32 port_range = 20;
48  const int insertion_limit = 200;  // We should be done by then.
49  for (int i = 0; i < insertion_limit; ++i) {
50    ports.insert(port_suggester->SuggestPort(min_ephemeral_port_,
51        min_ephemeral_port_ + port_range - 1));
52    if (ports.size() == port_range) {
53      break;
54    }
55  }
56  EXPECT_EQ(port_range, ports.size());
57}
58
59TEST_F(PortSuggesterTest, AvoidDuplication) {
60  // When the range is large, duplicates are rare, but we'll ask for a few
61  // suggestions and make sure they are unique.
62  scoped_refptr<PortSuggester> port_suggester =
63      new PortSuggester(HostPortPair("www.example.com", 80), entropy_);
64  std::set<int> ports;
65  const size_t port_count = 200;
66  for (size_t i = 0; i < port_count; ++i) {
67    ports.insert(port_suggester->SuggestPort(min_ephemeral_port_,
68                                             max_ephemeral_port_));
69  }
70  EXPECT_EQ(port_suggester->call_count(), port_count);
71  EXPECT_EQ(port_count, ports.size());
72}
73
74TEST_F(PortSuggesterTest, ConsistentPorts) {
75  // For given hostname, port, and entropy, we should always get the same
76  // suggestions.
77  scoped_refptr<PortSuggester> port_suggester1 =
78      new PortSuggester(HostPortPair("www.example.com", 443), entropy_);
79  scoped_refptr<PortSuggester> port_suggester2 =
80      new PortSuggester(HostPortPair("www.example.com", 443), entropy_);
81  for (int test_count = 20; test_count > 0; --test_count) {
82    EXPECT_EQ(port_suggester1->SuggestPort(min_ephemeral_port_,
83                                           min_ephemeral_port_),
84              port_suggester2->SuggestPort(min_ephemeral_port_,
85                                           min_ephemeral_port_));
86  }
87}
88
89TEST_F(PortSuggesterTest, DifferentHostPortEntropy) {
90  // When we have different hosts, port, or entropy, we probably won't collide.
91  scoped_refptr<PortSuggester> port_suggester[] = {
92      new PortSuggester(HostPortPair("www.example.com", 80), entropy_),
93      new PortSuggester(HostPortPair("www.example.ORG", 80), entropy_),
94      new PortSuggester(HostPortPair("www.example.com", 443), entropy_),
95      new PortSuggester(HostPortPair("www.example.com", 80), entropy_ + 123456),
96  };
97
98  std::set<int> ports;
99  const int port_count = 40;
100  size_t insertion_count = 0;
101  for (size_t j = 0; j < arraysize(port_suggester); ++j) {
102    for (int i = 0; i < port_count; ++i) {
103     ports.insert(port_suggester[j]->SuggestPort(min_ephemeral_port_,
104                                                 max_ephemeral_port_));
105     ++insertion_count;
106    }
107  }
108  EXPECT_EQ(insertion_count, ports.size());
109}
110
111}  // namespace test
112}  // namespace net
113