OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "net/spdy/spdy_session.h" | 5 #include "net/spdy/spdy_session.h" |
6 | 6 |
| 7 #include "base/memory/scoped_ptr.h" |
| 8 #include "base/memory/scoped_vector.h" |
7 #include "net/base/cert_test_util.h" | 9 #include "net/base/cert_test_util.h" |
8 #include "net/base/host_cache.h" | 10 #include "net/base/host_cache.h" |
| 11 #include "net/base/io_buffer.h" |
9 #include "net/base/ip_endpoint.h" | 12 #include "net/base/ip_endpoint.h" |
10 #include "net/base/net_log_unittest.h" | 13 #include "net/base/net_log_unittest.h" |
11 #include "net/base/test_data_directory.h" | 14 #include "net/base/test_data_directory.h" |
| 15 #include "net/base/test_data_stream.h" |
12 #include "net/spdy/spdy_io_buffer.h" | 16 #include "net/spdy/spdy_io_buffer.h" |
13 #include "net/spdy/spdy_session_pool.h" | 17 #include "net/spdy/spdy_session_pool.h" |
| 18 #include "net/spdy/spdy_session_test_util.h" |
14 #include "net/spdy/spdy_stream.h" | 19 #include "net/spdy/spdy_stream.h" |
15 #include "net/spdy/spdy_test_util_spdy2.h" | 20 #include "net/spdy/spdy_test_util_spdy2.h" |
16 #include "testing/platform_test.h" | 21 #include "testing/platform_test.h" |
17 | 22 |
18 using namespace net::test_spdy2; | 23 using namespace net::test_spdy2; |
19 | 24 |
20 namespace net { | 25 namespace net { |
21 | 26 |
22 namespace { | 27 namespace { |
23 | 28 |
(...skipping 1591 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1615 EXPECT_EQ(OK, session->InitializeWithSocket(connection.release(), true, OK)); | 1620 EXPECT_EQ(OK, session->InitializeWithSocket(connection.release(), true, OK)); |
1616 | 1621 |
1617 EXPECT_FALSE(session->NeedsCredentials()); | 1622 EXPECT_FALSE(session->NeedsCredentials()); |
1618 | 1623 |
1619 // Flush the SpdySession::OnReadComplete() task. | 1624 // Flush the SpdySession::OnReadComplete() task. |
1620 MessageLoop::current()->RunUntilIdle(); | 1625 MessageLoop::current()->RunUntilIdle(); |
1621 | 1626 |
1622 spdy_session_pool_->Remove(session); | 1627 spdy_session_pool_->Remove(session); |
1623 } | 1628 } |
1624 | 1629 |
| 1630 // Test that SpdySession::DoRead reads data from the socket without yielding. |
| 1631 // This test makes 32k - 1 bytes of data available on the socket for reading. It |
| 1632 // then verifies that it has read all the available data without yielding. |
| 1633 TEST_F(SpdySessionSpdy2Test, ReadDataWithoutYielding) { |
| 1634 MockConnect connect_data(SYNCHRONOUS, OK); |
| 1635 BufferedSpdyFramer framer(2, false); |
| 1636 |
| 1637 scoped_ptr<SpdyFrame> req1(ConstructSpdyGet(NULL, 0, false, 1, MEDIUM)); |
| 1638 MockWrite writes[] = { |
| 1639 CreateMockWrite(*req1, 0), |
| 1640 }; |
| 1641 |
| 1642 // Build buffer of size kMaxReadBytes / 4 (-spdy_data_frame_size). |
| 1643 ASSERT_EQ(32 * 1024, kMaxReadBytes); |
| 1644 const int kPayloadSize = kMaxReadBytes / 4 - SpdyDataFrame::size(); |
| 1645 TestDataStream test_stream; |
| 1646 scoped_refptr<net::IOBuffer> payload(new net::IOBuffer(kPayloadSize)); |
| 1647 char* payload_data = payload->data(); |
| 1648 test_stream.GetBytes(payload_data, kPayloadSize); |
| 1649 |
| 1650 scoped_ptr<SpdyFrame> partial_data_frame( |
| 1651 framer.CreateDataFrame(1, payload_data, kPayloadSize, DATA_FLAG_NONE)); |
| 1652 scoped_ptr<SpdyFrame> finish_data_frame( |
| 1653 framer.CreateDataFrame(1, payload_data, kPayloadSize - 1, DATA_FLAG_FIN)); |
| 1654 |
| 1655 scoped_ptr<SpdyFrame> resp1(ConstructSpdyGetSynReply(NULL, 0, 1)); |
| 1656 |
| 1657 // Write 1 byte less than kMaxReadBytes to check that DoRead reads up to 32k |
| 1658 // bytes. |
| 1659 MockRead reads[] = { |
| 1660 CreateMockRead(*resp1, 1), |
| 1661 CreateMockRead(*partial_data_frame, 2), |
| 1662 CreateMockRead(*partial_data_frame, 3, SYNCHRONOUS), |
| 1663 CreateMockRead(*partial_data_frame, 4, SYNCHRONOUS), |
| 1664 CreateMockRead(*finish_data_frame, 5, SYNCHRONOUS), |
| 1665 MockRead(ASYNC, 0, 6) // EOF |
| 1666 }; |
| 1667 |
| 1668 // Create SpdySession and SpdyStream and send the request. |
| 1669 DeterministicSocketData data(reads, arraysize(reads), |
| 1670 writes, arraysize(writes)); |
| 1671 data.set_connect_data(connect_data); |
| 1672 session_deps_.host_resolver->set_synchronous_mode(true); |
| 1673 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data); |
| 1674 |
| 1675 SSLSocketDataProvider ssl(SYNCHRONOUS, OK); |
| 1676 session_deps_.deterministic_socket_factory->AddSSLSocketDataProvider(&ssl); |
| 1677 |
| 1678 CreateDeterministicNetworkSession(); |
| 1679 |
| 1680 scoped_refptr<SpdySession> session = CreateInitializedSession(); |
| 1681 |
| 1682 scoped_refptr<SpdyStream> spdy_stream1; |
| 1683 TestCompletionCallback callback1; |
| 1684 GURL url1("http://www.google.com"); |
| 1685 EXPECT_EQ(OK, session->CreateStream(url1, MEDIUM, &spdy_stream1, |
| 1686 BoundNetLog(), callback1.callback())); |
| 1687 EXPECT_EQ(0u, spdy_stream1->stream_id()); |
| 1688 |
| 1689 scoped_ptr<SpdyHeaderBlock> headers(new SpdyHeaderBlock); |
| 1690 (*headers)["method"] = "GET"; |
| 1691 (*headers)["scheme"] = url1.scheme(); |
| 1692 (*headers)["host"] = url1.host(); |
| 1693 (*headers)["url"] = url1.path(); |
| 1694 (*headers)["version"] = "HTTP/1.1"; |
| 1695 |
| 1696 spdy_stream1->set_spdy_headers(headers.Pass()); |
| 1697 EXPECT_TRUE(spdy_stream1->HasUrl()); |
| 1698 spdy_stream1->SendRequest(false); |
| 1699 |
| 1700 // Set up the TaskObserver to verify SpdySession::DoRead doesn't post a task. |
| 1701 SpdySessionTestTaskObserver observer("spdy_session.cc", "DoRead"); |
| 1702 |
| 1703 // Run until 1st read. |
| 1704 EXPECT_EQ(0u, spdy_stream1->stream_id()); |
| 1705 data.RunFor(2); |
| 1706 EXPECT_EQ(1u, spdy_stream1->stream_id()); |
| 1707 EXPECT_EQ(0u, observer.executed_count()); |
| 1708 |
| 1709 // Read all the data and verify SpdySession::DoRead has not posted a task. |
| 1710 data.RunFor(4); |
| 1711 |
| 1712 // Verify task observer's executed_count is zero, which indicates DoRead read |
| 1713 // all the available data. |
| 1714 EXPECT_EQ(0u, observer.executed_count()); |
| 1715 EXPECT_TRUE(data.at_write_eof()); |
| 1716 EXPECT_TRUE(data.at_read_eof()); |
| 1717 } |
| 1718 |
| 1719 // Test that SpdySession::DoRead yields while reading the data. This test makes |
| 1720 // 32k + 1 bytes of data available on the socket for reading. It then verifies |
| 1721 // that DoRead has yielded even though there is data available for it to read |
| 1722 // (i.e, socket()->Read didn't return ERR_IO_PENDING during socket reads). |
| 1723 TEST_F(SpdySessionSpdy2Test, TestYieldingDuringReadData) { |
| 1724 MockConnect connect_data(SYNCHRONOUS, OK); |
| 1725 BufferedSpdyFramer framer(2, false); |
| 1726 |
| 1727 scoped_ptr<SpdyFrame> req1(ConstructSpdyGet(NULL, 0, false, 1, MEDIUM)); |
| 1728 MockWrite writes[] = { |
| 1729 CreateMockWrite(*req1, 0), |
| 1730 }; |
| 1731 |
| 1732 // Build buffer of size kMaxReadBytes / 4 (-spdy_data_frame_size). |
| 1733 ASSERT_EQ(32 * 1024, kMaxReadBytes); |
| 1734 const int kPayloadSize = kMaxReadBytes / 4 - SpdyDataFrame::size(); |
| 1735 TestDataStream test_stream; |
| 1736 scoped_refptr<net::IOBuffer> payload(new net::IOBuffer(kPayloadSize)); |
| 1737 char* payload_data = payload->data(); |
| 1738 test_stream.GetBytes(payload_data, kPayloadSize); |
| 1739 |
| 1740 scoped_ptr<SpdyFrame> partial_data_frame( |
| 1741 framer.CreateDataFrame(1, payload_data, kPayloadSize, DATA_FLAG_NONE)); |
| 1742 scoped_ptr<SpdyFrame> finish_data_frame( |
| 1743 framer.CreateDataFrame(1, "h", 1, DATA_FLAG_FIN)); |
| 1744 |
| 1745 scoped_ptr<SpdyFrame> resp1(ConstructSpdyGetSynReply(NULL, 0, 1)); |
| 1746 |
| 1747 // Write 1 byte more than kMaxReadBytes to check that DoRead yields. |
| 1748 MockRead reads[] = { |
| 1749 CreateMockRead(*resp1, 1), |
| 1750 CreateMockRead(*partial_data_frame, 2), |
| 1751 CreateMockRead(*partial_data_frame, 3, SYNCHRONOUS), |
| 1752 CreateMockRead(*partial_data_frame, 4, SYNCHRONOUS), |
| 1753 CreateMockRead(*partial_data_frame, 5, SYNCHRONOUS), |
| 1754 CreateMockRead(*finish_data_frame, 6, SYNCHRONOUS), |
| 1755 MockRead(ASYNC, 0, 7) // EOF |
| 1756 }; |
| 1757 |
| 1758 // Create SpdySession and SpdyStream and send the request. |
| 1759 DeterministicSocketData data(reads, arraysize(reads), |
| 1760 writes, arraysize(writes)); |
| 1761 data.set_connect_data(connect_data); |
| 1762 session_deps_.host_resolver->set_synchronous_mode(true); |
| 1763 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data); |
| 1764 |
| 1765 SSLSocketDataProvider ssl(SYNCHRONOUS, OK); |
| 1766 session_deps_.deterministic_socket_factory->AddSSLSocketDataProvider(&ssl); |
| 1767 |
| 1768 CreateDeterministicNetworkSession(); |
| 1769 |
| 1770 scoped_refptr<SpdySession> session = CreateInitializedSession(); |
| 1771 |
| 1772 scoped_refptr<SpdyStream> spdy_stream1; |
| 1773 TestCompletionCallback callback1; |
| 1774 GURL url1("http://www.google.com"); |
| 1775 EXPECT_EQ(OK, session->CreateStream(url1, MEDIUM, &spdy_stream1, |
| 1776 BoundNetLog(), callback1.callback())); |
| 1777 EXPECT_EQ(0u, spdy_stream1->stream_id()); |
| 1778 |
| 1779 scoped_ptr<SpdyHeaderBlock> headers(new SpdyHeaderBlock); |
| 1780 (*headers)["method"] = "GET"; |
| 1781 (*headers)["scheme"] = url1.scheme(); |
| 1782 (*headers)["host"] = url1.host(); |
| 1783 (*headers)["url"] = url1.path(); |
| 1784 (*headers)["version"] = "HTTP/1.1"; |
| 1785 |
| 1786 spdy_stream1->set_spdy_headers(headers.Pass()); |
| 1787 EXPECT_TRUE(spdy_stream1->HasUrl()); |
| 1788 spdy_stream1->SendRequest(false); |
| 1789 |
| 1790 // Set up the TaskObserver to verify SpdySession::DoRead posts a task. |
| 1791 SpdySessionTestTaskObserver observer("spdy_session.cc", "DoRead"); |
| 1792 |
| 1793 // Run until 1st read. |
| 1794 EXPECT_EQ(0u, spdy_stream1->stream_id()); |
| 1795 data.RunFor(2); |
| 1796 EXPECT_EQ(1u, spdy_stream1->stream_id()); |
| 1797 EXPECT_EQ(0u, observer.executed_count()); |
| 1798 |
| 1799 // Read all the data and verify SpdySession::DoRead has posted a task. |
| 1800 data.RunFor(6); |
| 1801 |
| 1802 // Verify task observer's executed_count is 1, which indicates DoRead has |
| 1803 // posted only one task and thus yielded though there is data available for it |
| 1804 // to read. |
| 1805 EXPECT_EQ(1u, observer.executed_count()); |
| 1806 EXPECT_TRUE(data.at_write_eof()); |
| 1807 EXPECT_TRUE(data.at_read_eof()); |
| 1808 } |
| 1809 |
| 1810 // Test that SpdySession::DoRead yields while reading the data. This test makes |
| 1811 // 4 reads of kMaxReadBytes / 4 (-spdy_data_frame_size), one read of |
| 1812 // kMaxReadBytes (-spdy_data_frame_size), and some reads of kMaxReadBytes + 8k |
| 1813 // (-spdy_data_frame_size), bytes of data available on the socket for reading. |
| 1814 // It then verifies that DoRead has yielded even though there is data available |
| 1815 // for it to read (i.e, socket()->Read didn't return ERR_IO_PENDING during |
| 1816 // socket reads). Also verifies that SpdySession reads only |
| 1817 // SpdySession::kReadBufferSize data from the underlying transport. |
| 1818 // TODO(rtennti): Make this test work after fixes to DeterministicSocketData. |
| 1819 TEST_F(SpdySessionSpdy2Test, DISABLED_TestYieldingDuringLargeReadData) { |
| 1820 MockConnect connect_data(SYNCHRONOUS, OK); |
| 1821 BufferedSpdyFramer framer(2, false); |
| 1822 |
| 1823 scoped_ptr<SpdyFrame> req1(ConstructSpdyGet(NULL, 0, false, 1, MEDIUM)); |
| 1824 MockWrite writes[] = { |
| 1825 CreateMockWrite(*req1, 0), |
| 1826 }; |
| 1827 |
| 1828 // Build buffer of size kMaxReadBytes / 4 (-spdy_data_frame_size). |
| 1829 ASSERT_EQ(32 * 1024, kMaxReadBytes); |
| 1830 TestDataStream test_stream; |
| 1831 const int kSmallPayloadSize = kMaxReadBytes / 4 - SpdyDataFrame::size(); |
| 1832 scoped_refptr<net::IOBuffer> small_payload( |
| 1833 new net::IOBuffer(kSmallPayloadSize)); |
| 1834 char* small_payload_data = small_payload->data(); |
| 1835 test_stream.GetBytes(small_payload_data, kSmallPayloadSize); |
| 1836 |
| 1837 // Build buffer of size kMaxReadBytes - (-spdy_data_frame_size). |
| 1838 TestDataStream test_stream1; |
| 1839 const int kMaxReadBytesPayloadSize = kMaxReadBytes - SpdyDataFrame::size(); |
| 1840 scoped_refptr<net::IOBuffer> max_bytes_payload( |
| 1841 new net::IOBuffer(kMaxReadBytesPayloadSize)); |
| 1842 char* max_bytes_payload_data = max_bytes_payload->data(); |
| 1843 test_stream1.GetBytes(max_bytes_payload_data, kMaxReadBytesPayloadSize); |
| 1844 |
| 1845 // Build buffer of size kMaxReadBytes + kSmallPayloadSize |
| 1846 // (-spdy_data_frame_size). |
| 1847 TestDataStream test_stream2; |
| 1848 const int kLargePayloadSize = |
| 1849 kMaxReadBytes + kSmallPayloadSize - SpdyDataFrame::size(); |
| 1850 scoped_refptr<net::IOBuffer> large_payload( |
| 1851 new net::IOBuffer(kLargePayloadSize)); |
| 1852 char* large_payload_data = large_payload->data(); |
| 1853 test_stream2.GetBytes(large_payload_data, kLargePayloadSize); |
| 1854 |
| 1855 scoped_ptr<SpdyFrame> small_data_frame(framer.CreateDataFrame( |
| 1856 1, small_payload_data, kSmallPayloadSize, DATA_FLAG_NONE)); |
| 1857 scoped_ptr<SpdyFrame> max_bytes_data_frame(framer.CreateDataFrame( |
| 1858 1, max_bytes_payload_data, kMaxReadBytesPayloadSize, DATA_FLAG_NONE)); |
| 1859 scoped_ptr<SpdyFrame> large_data_frame(framer.CreateDataFrame( |
| 1860 1, large_payload_data, kLargePayloadSize, DATA_FLAG_NONE)); |
| 1861 scoped_ptr<SpdyFrame> finish_data_frame(framer.CreateDataFrame( |
| 1862 1, "h", 1, DATA_FLAG_FIN)); |
| 1863 |
| 1864 scoped_ptr<SpdyFrame> resp1(ConstructSpdyGetSynReply(NULL, 0, 1)); |
| 1865 |
| 1866 MockRead reads[] = { |
| 1867 CreateMockRead(*resp1, 1), |
| 1868 CreateMockRead(*small_data_frame, 2), |
| 1869 CreateMockRead(*small_data_frame, 3, SYNCHRONOUS), |
| 1870 CreateMockRead(*small_data_frame, 4, SYNCHRONOUS), |
| 1871 CreateMockRead(*small_data_frame, 5, SYNCHRONOUS), |
| 1872 CreateMockRead(*max_bytes_data_frame, 6), |
| 1873 CreateMockRead(*large_data_frame, 7, SYNCHRONOUS), |
| 1874 CreateMockRead(*finish_data_frame, 8, SYNCHRONOUS), |
| 1875 MockRead(ASYNC, 0, 9) // EOF |
| 1876 }; |
| 1877 |
| 1878 // Create SpdySession and SpdyStream and send the request. |
| 1879 DeterministicSocketData data(reads, arraysize(reads), |
| 1880 writes, arraysize(writes)); |
| 1881 data.set_connect_data(connect_data); |
| 1882 session_deps_.host_resolver->set_synchronous_mode(true); |
| 1883 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data); |
| 1884 |
| 1885 SSLSocketDataProvider ssl(SYNCHRONOUS, OK); |
| 1886 session_deps_.deterministic_socket_factory->AddSSLSocketDataProvider(&ssl); |
| 1887 |
| 1888 CreateDeterministicNetworkSession(); |
| 1889 |
| 1890 scoped_refptr<SpdySession> session = CreateInitializedSession(); |
| 1891 |
| 1892 scoped_refptr<SpdyStream> spdy_stream1; |
| 1893 TestCompletionCallback callback1; |
| 1894 GURL url1("http://www.google.com"); |
| 1895 EXPECT_EQ(OK, session->CreateStream(url1, MEDIUM, &spdy_stream1, |
| 1896 BoundNetLog(), callback1.callback())); |
| 1897 EXPECT_EQ(0u, spdy_stream1->stream_id()); |
| 1898 |
| 1899 scoped_ptr<SpdyHeaderBlock> headers(new SpdyHeaderBlock); |
| 1900 (*headers)["method"] = "GET"; |
| 1901 (*headers)["scheme"] = url1.scheme(); |
| 1902 (*headers)["host"] = url1.host(); |
| 1903 (*headers)["url"] = url1.path(); |
| 1904 (*headers)["version"] = "HTTP/1.1"; |
| 1905 |
| 1906 spdy_stream1->set_spdy_headers(headers.Pass()); |
| 1907 EXPECT_TRUE(spdy_stream1->HasUrl()); |
| 1908 spdy_stream1->SendRequest(false); |
| 1909 |
| 1910 // Set up the TaskObserver to verify SpdySession::DoRead posts a task. |
| 1911 SpdySessionTestTaskObserver observer("spdy_session.cc", "DoRead"); |
| 1912 |
| 1913 // Run until 1st read. |
| 1914 EXPECT_EQ(0u, spdy_stream1->stream_id()); |
| 1915 data.RunFor(2); |
| 1916 EXPECT_EQ(1u, spdy_stream1->stream_id()); |
| 1917 EXPECT_EQ(0u, observer.executed_count()); |
| 1918 |
| 1919 // Read all the data and verify SpdySession::DoRead has posted a task. |
| 1920 data.RunFor(10); |
| 1921 |
| 1922 // Verify task observer's executed_count is 1, which indicates DoRead has |
| 1923 // posted only one task and thus yielded though there is data available for |
| 1924 // it to read. |
| 1925 EXPECT_EQ(1u, observer.executed_count()); |
| 1926 EXPECT_TRUE(data.at_write_eof()); |
| 1927 EXPECT_TRUE(data.at_read_eof()); |
| 1928 } |
| 1929 |
1625 } // namespace net | 1930 } // namespace net |
OLD | NEW |