blob: 93a6647bc9b97696bbe304d2ca8aeaab2f9310d5 [file] [log] [blame]
// Copyright 2017 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 "net/spdy/chromium/http2_push_promise_index.h"
#include "base/run_loop.h"
#include "net/base/host_port_pair.h"
#include "net/base/privacy_mode.h"
#include "net/log/test_net_log.h"
#include "net/socket/socket_test_util.h"
#include "net/spdy/chromium/spdy_session.h"
#include "net/spdy/chromium/spdy_test_util_common.h"
#include "net/test/cert_test_util.h"
#include "net/test/test_data_directory.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "url/gurl.h"
namespace net {
namespace test {
class Http2PushPromiseIndexTest : public testing::Test {
protected:
Http2PushPromiseIndexTest()
: url1_("https://www.example.org"),
url2_("https://mail.example.com"),
host_port_pair1_(HostPortPair::FromURL(url1_)),
host_port_pair2_(HostPortPair::FromURL(url2_)),
key1_(host_port_pair1_, ProxyServer::Direct(), PRIVACY_MODE_ENABLED),
key2_(host_port_pair2_, ProxyServer::Direct(), PRIVACY_MODE_ENABLED),
http_network_session_(
SpdySessionDependencies::SpdyCreateSession(&session_deps_)) {}
NetLogWithSource log_;
const GURL url1_;
const GURL url2_;
const HostPortPair host_port_pair1_;
const HostPortPair host_port_pair2_;
const SpdySessionKey key1_;
const SpdySessionKey key2_;
SpdySessionDependencies session_deps_;
std::unique_ptr<HttpNetworkSession> http_network_session_;
Http2PushPromiseIndex index_;
};
TEST_F(Http2PushPromiseIndexTest, Empty) {
EXPECT_FALSE(index_.Find(key1_, url1_));
EXPECT_FALSE(index_.Find(key2_, url2_));
}
TEST_F(Http2PushPromiseIndexTest, FindMultipleSessionsWithDifferentUrl) {
MockRead reads[] = {MockRead(SYNCHRONOUS, ERR_IO_PENDING, 0)};
SSLSocketDataProvider ssl(SYNCHRONOUS, OK);
ssl.cert = ImportCertFromFile(GetTestCertsDirectory(), "spdy_pooling.pem");
// For first session.
SequencedSocketData data1(reads, arraysize(reads), nullptr, 0);
session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
session_deps_.socket_factory->AddSocketDataProvider(&data1);
// For second session.
SequencedSocketData data2(reads, arraysize(reads), nullptr, 0);
session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
session_deps_.socket_factory->AddSocketDataProvider(&data2);
base::WeakPtr<SpdySession> spdy_session1 =
CreateSpdySession(http_network_session_.get(), key1_, log_);
base::WeakPtr<SpdySession> spdy_session2 =
CreateSpdySession(http_network_session_.get(), key2_, log_);
// Read hanging socket data.
base::RunLoop().RunUntilIdle();
EXPECT_FALSE(index_.Find(key1_, url1_));
EXPECT_FALSE(index_.Find(key2_, url2_));
index_.RegisterUnclaimedPushedStream(url1_, spdy_session1);
EXPECT_EQ(spdy_session1.get(), index_.Find(key1_, url1_).get());
EXPECT_FALSE(index_.Find(key2_, url2_));
index_.RegisterUnclaimedPushedStream(url2_, spdy_session2);
EXPECT_EQ(spdy_session1.get(), index_.Find(key1_, url1_).get());
EXPECT_EQ(spdy_session2.get(), index_.Find(key2_, url2_).get());
index_.UnregisterUnclaimedPushedStream(url1_, spdy_session1.get());
EXPECT_FALSE(index_.Find(key1_, url1_));
EXPECT_EQ(spdy_session2.get(), index_.Find(key2_, url2_).get());
index_.UnregisterUnclaimedPushedStream(url2_, spdy_session2.get());
EXPECT_FALSE(index_.Find(key1_, url1_));
EXPECT_FALSE(index_.Find(key2_, url2_));
// SpdySession weak pointers must still be valid,
// otherwise comparisons above are not meaningful.
EXPECT_TRUE(spdy_session1);
EXPECT_TRUE(spdy_session2);
EXPECT_TRUE(data1.AllReadDataConsumed());
EXPECT_TRUE(data1.AllWriteDataConsumed());
EXPECT_TRUE(data2.AllReadDataConsumed());
EXPECT_TRUE(data2.AllWriteDataConsumed());
}
TEST_F(Http2PushPromiseIndexTest, MultipleSessionsForSingleUrl) {
MockRead reads[] = {MockRead(SYNCHRONOUS, ERR_IO_PENDING, 0)};
SSLSocketDataProvider ssl(SYNCHRONOUS, OK);
ssl.cert = ImportCertFromFile(GetTestCertsDirectory(), "spdy_pooling.pem");
// For first session.
SequencedSocketData data1(reads, arraysize(reads), nullptr, 0);
session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
session_deps_.socket_factory->AddSocketDataProvider(&data1);
// For second session.
SequencedSocketData data2(reads, arraysize(reads), nullptr, 0);
session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
session_deps_.socket_factory->AddSocketDataProvider(&data2);
base::WeakPtr<SpdySession> spdy_session1 =
CreateSpdySession(http_network_session_.get(), key1_, log_);
base::WeakPtr<SpdySession> spdy_session2 =
CreateSpdySession(http_network_session_.get(), key2_, log_);
// Read hanging socket data.
base::RunLoop().RunUntilIdle();
EXPECT_FALSE(index_.Find(key1_, url1_));
EXPECT_FALSE(index_.Find(key2_, url1_));
EXPECT_FALSE(index_.Find(key1_, url2_));
EXPECT_FALSE(index_.Find(key2_, url2_));
index_.RegisterUnclaimedPushedStream(url1_, spdy_session1);
// Note that Find() only uses its SpdySessionKey argument to verify proxy and
// privacy mode. Cross-origin pooling is supported, therefore HostPortPair of
// SpdySessionKey does not matter.
EXPECT_EQ(spdy_session1.get(), index_.Find(key1_, url1_).get());
EXPECT_EQ(spdy_session1.get(), index_.Find(key2_, url1_).get());
EXPECT_FALSE(index_.Find(key1_, url2_));
EXPECT_FALSE(index_.Find(key2_, url2_));
index_.RegisterUnclaimedPushedStream(url1_, spdy_session2);
// Find returns the first SpdySession if there are multiple for the same URL.
EXPECT_EQ(spdy_session1.get(), index_.Find(key1_, url1_).get());
EXPECT_EQ(spdy_session1.get(), index_.Find(key2_, url1_).get());
EXPECT_FALSE(index_.Find(key1_, url2_));
EXPECT_FALSE(index_.Find(key2_, url2_));
index_.UnregisterUnclaimedPushedStream(url1_, spdy_session1.get());
EXPECT_EQ(spdy_session2.get(), index_.Find(key1_, url1_).get());
EXPECT_EQ(spdy_session2.get(), index_.Find(key2_, url1_).get());
EXPECT_FALSE(index_.Find(key1_, url2_));
EXPECT_FALSE(index_.Find(key2_, url2_));
index_.UnregisterUnclaimedPushedStream(url1_, spdy_session2.get());
EXPECT_FALSE(index_.Find(key1_, url1_));
EXPECT_FALSE(index_.Find(key2_, url1_));
EXPECT_FALSE(index_.Find(key1_, url2_));
EXPECT_FALSE(index_.Find(key2_, url2_));
// SpdySession weak pointers must still be valid,
// otherwise comparisons above are not meaningful.
EXPECT_TRUE(spdy_session1);
EXPECT_TRUE(spdy_session2);
EXPECT_TRUE(data1.AllReadDataConsumed());
EXPECT_TRUE(data1.AllWriteDataConsumed());
EXPECT_TRUE(data2.AllReadDataConsumed());
EXPECT_TRUE(data2.AllWriteDataConsumed());
}
} // namespace test
} // namespace net