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/location.h" |
| 8 #include "base/memory/scoped_ptr.h" |
| 9 #include "base/memory/scoped_vector.h" |
| 10 #include "base/pending_task.h" |
| 11 #include "base/string_util.h" |
7 #include "net/base/cert_test_util.h" | 12 #include "net/base/cert_test_util.h" |
8 #include "net/base/host_cache.h" | 13 #include "net/base/host_cache.h" |
| 14 #include "net/base/io_buffer.h" |
9 #include "net/base/ip_endpoint.h" | 15 #include "net/base/ip_endpoint.h" |
10 #include "net/base/net_log_unittest.h" | 16 #include "net/base/net_log_unittest.h" |
11 #include "net/base/test_data_directory.h" | 17 #include "net/base/test_data_directory.h" |
| 18 #include "net/base/test_data_stream.h" |
12 #include "net/spdy/spdy_io_buffer.h" | 19 #include "net/spdy/spdy_io_buffer.h" |
13 #include "net/spdy/spdy_session_pool.h" | 20 #include "net/spdy/spdy_session_pool.h" |
| 21 #include "net/spdy/spdy_session_test_util.h" |
14 #include "net/spdy/spdy_stream.h" | 22 #include "net/spdy/spdy_stream.h" |
15 #include "net/spdy/spdy_test_util_spdy3.h" | 23 #include "net/spdy/spdy_test_util_spdy3.h" |
16 #include "testing/platform_test.h" | 24 #include "testing/platform_test.h" |
17 | 25 |
18 using namespace net::test_spdy3; | 26 using namespace net::test_spdy3; |
19 | 27 |
20 namespace net { | 28 namespace net { |
21 | 29 |
22 namespace { | 30 namespace { |
23 | 31 |
(...skipping 1717 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1741 | 1749 |
1742 scoped_refptr<SpdyStream> spdy_stream2; | 1750 scoped_refptr<SpdyStream> spdy_stream2; |
1743 EXPECT_EQ(OK, session->CreateStream(test_url_, MEDIUM, &spdy_stream2, | 1751 EXPECT_EQ(OK, session->CreateStream(test_url_, MEDIUM, &spdy_stream2, |
1744 BoundNetLog(), callback1.callback())); | 1752 BoundNetLog(), callback1.callback())); |
1745 | 1753 |
1746 EXPECT_EQ(spdy_stream2->send_window_size(), window_size); | 1754 EXPECT_EQ(spdy_stream2->send_window_size(), window_size); |
1747 spdy_stream2->Cancel(); | 1755 spdy_stream2->Cancel(); |
1748 spdy_stream2 = NULL; | 1756 spdy_stream2 = NULL; |
1749 } | 1757 } |
1750 | 1758 |
| 1759 // Test that SpdySession::DoRead reads data from the socket without yielding. |
| 1760 // This test makes 32k - 1 bytes of data available on the socket for reading. It |
| 1761 // then verifies that it has read all the available data without yielding. |
| 1762 TEST_F(SpdySessionSpdy3Test, ReadDataWithoutYielding) { |
| 1763 MockConnect connect_data(SYNCHRONOUS, OK); |
| 1764 BufferedSpdyFramer framer(3, false); |
| 1765 |
| 1766 scoped_ptr<SpdyFrame> req1(ConstructSpdyGet(NULL, 0, false, 1, MEDIUM)); |
| 1767 MockWrite writes[] = { |
| 1768 CreateMockWrite(*req1, 0), |
| 1769 }; |
| 1770 |
| 1771 // Build buffers of size 8k. |
| 1772 ASSERT_EQ(32 * 1024, kMaxReadBytes); |
| 1773 const int kPayloadSize = kMaxReadBytes / 4 - SpdyDataFrame::size(); |
| 1774 TestDataStream test_stream; |
| 1775 scoped_refptr<net::IOBuffer> payload(new net::IOBuffer(kPayloadSize)); |
| 1776 char* payload_data = payload->data(); |
| 1777 test_stream.GetBytes(payload_data, kPayloadSize); |
| 1778 |
| 1779 scoped_ptr<SpdyFrame> data_frame1( |
| 1780 framer.CreateDataFrame(1, payload_data, kPayloadSize, DATA_FLAG_NONE)); |
| 1781 scoped_ptr<SpdyFrame> data_frame( |
| 1782 framer.CreateDataFrame(1, payload_data, kPayloadSize - 1, DATA_FLAG_FIN)); |
| 1783 |
| 1784 scoped_ptr<SpdyFrame> resp1(ConstructSpdyGetSynReply(NULL, 0, 1)); |
| 1785 |
| 1786 // Write 1 byte less than kMaxReadBytes to check that DoRead reads up to 32k |
| 1787 // bytes. |
| 1788 MockRead reads[] = { |
| 1789 CreateMockRead(*resp1, 1), |
| 1790 CreateMockRead(*data_frame1, 2), |
| 1791 CreateMockRead(*data_frame1, 3, SYNCHRONOUS), |
| 1792 CreateMockRead(*data_frame1, 4, SYNCHRONOUS), |
| 1793 CreateMockRead(*data_frame, 5, SYNCHRONOUS), |
| 1794 MockRead(ASYNC, 0, 6) // EOF |
| 1795 }; |
| 1796 |
| 1797 // Create SpdySession and SpdyStream and send the request. |
| 1798 DeterministicSocketData data(reads, arraysize(reads), |
| 1799 writes, arraysize(writes)); |
| 1800 data.set_connect_data(connect_data); |
| 1801 session_deps_.host_resolver->set_synchronous_mode(true); |
| 1802 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data); |
| 1803 |
| 1804 SSLSocketDataProvider ssl(SYNCHRONOUS, OK); |
| 1805 session_deps_.deterministic_socket_factory->AddSSLSocketDataProvider(&ssl); |
| 1806 |
| 1807 CreateDeterministicNetworkSession(); |
| 1808 |
| 1809 scoped_refptr<SpdySession> session = CreateInitializedSession(); |
| 1810 |
| 1811 scoped_refptr<SpdyStream> spdy_stream1; |
| 1812 TestCompletionCallback callback1; |
| 1813 GURL url1("http://www.google.com"); |
| 1814 EXPECT_EQ(OK, session->CreateStream(url1, MEDIUM, &spdy_stream1, |
| 1815 BoundNetLog(), callback1.callback())); |
| 1816 EXPECT_EQ(0u, spdy_stream1->stream_id()); |
| 1817 |
| 1818 scoped_ptr<SpdyHeaderBlock> headers(new SpdyHeaderBlock); |
| 1819 (*headers)[":method"] = "GET"; |
| 1820 (*headers)[":scheme"] = url1.scheme(); |
| 1821 (*headers)[":host"] = url1.host(); |
| 1822 (*headers)[":path"] = url1.path(); |
| 1823 (*headers)[":version"] = "HTTP/1.1"; |
| 1824 |
| 1825 spdy_stream1->set_spdy_headers(headers.Pass()); |
| 1826 EXPECT_TRUE(spdy_stream1->HasUrl()); |
| 1827 spdy_stream1->SendRequest(false); |
| 1828 |
| 1829 // Set up the TaskObserver to verify SpdySession::DoRead doesn't post a task. |
| 1830 SpdySessionTestTaskObserver observer("spdy_session.cc", "DoRead"); |
| 1831 |
| 1832 // Run until 1st read. |
| 1833 EXPECT_EQ(0u, spdy_stream1->stream_id()); |
| 1834 data.RunFor(2); |
| 1835 EXPECT_EQ(1u, spdy_stream1->stream_id()); |
| 1836 EXPECT_EQ(0u, observer.posted_count()); |
| 1837 |
| 1838 // Read all the data and verify SpdySession::DoRead has not posted a task. |
| 1839 data.RunFor(4); |
| 1840 |
| 1841 // Verify task observer's posted_count is zero, which indicates DoRead read |
| 1842 // all the available data. |
| 1843 EXPECT_EQ(0u, observer.posted_count()); |
| 1844 EXPECT_TRUE(data.at_write_eof()); |
| 1845 EXPECT_TRUE(data.at_read_eof()); |
| 1846 } |
| 1847 |
| 1848 // Test that SpdySession::DoRead yields while reading the data. This test makes |
| 1849 // 32k + 1 bytes of data available on the socket for reading. It then verifies |
| 1850 // that DoRead has yielded even though there is data available for it to read |
| 1851 // (i.e, socket()->Read didn't return ERR_IO_PENDING during socket reads). |
| 1852 TEST_F(SpdySessionSpdy3Test, TestYieldingDuringReadData) { |
| 1853 MockConnect connect_data(SYNCHRONOUS, OK); |
| 1854 BufferedSpdyFramer framer(3, false); |
| 1855 |
| 1856 scoped_ptr<SpdyFrame> req1(ConstructSpdyGet(NULL, 0, false, 1, MEDIUM)); |
| 1857 MockWrite writes[] = { |
| 1858 CreateMockWrite(*req1, 0), |
| 1859 }; |
| 1860 |
| 1861 // Build buffers of size 8k. |
| 1862 ASSERT_EQ(32 * 1024, kMaxReadBytes); |
| 1863 const int kPayloadSize = kMaxReadBytes / 4 - SpdyDataFrame::size(); |
| 1864 TestDataStream test_stream; |
| 1865 scoped_refptr<net::IOBuffer> payload(new net::IOBuffer(kPayloadSize)); |
| 1866 char* payload_data = payload->data(); |
| 1867 test_stream.GetBytes(payload_data, kPayloadSize); |
| 1868 |
| 1869 scoped_ptr<SpdyFrame> data_frame1( |
| 1870 framer.CreateDataFrame(1, payload_data, kPayloadSize, DATA_FLAG_NONE)); |
| 1871 scoped_ptr<SpdyFrame> data_frame( |
| 1872 framer.CreateDataFrame(1, "h", 1, DATA_FLAG_FIN)); |
| 1873 |
| 1874 scoped_ptr<SpdyFrame> resp1(ConstructSpdyGetSynReply(NULL, 0, 1)); |
| 1875 |
| 1876 // Write 1 byte more than kMaxReadBytes to check that DoRead yields. |
| 1877 MockRead reads[] = { |
| 1878 CreateMockRead(*resp1, 1), |
| 1879 CreateMockRead(*data_frame1, 2), |
| 1880 CreateMockRead(*data_frame1, 3, SYNCHRONOUS), |
| 1881 CreateMockRead(*data_frame1, 4, SYNCHRONOUS), |
| 1882 CreateMockRead(*data_frame1, 5, SYNCHRONOUS), |
| 1883 CreateMockRead(*data_frame, 6, SYNCHRONOUS), |
| 1884 MockRead(ASYNC, 0, 7) // EOF |
| 1885 }; |
| 1886 |
| 1887 // Create SpdySession and SpdyStream and send the request. |
| 1888 DeterministicSocketData data(reads, arraysize(reads), |
| 1889 writes, arraysize(writes)); |
| 1890 data.set_connect_data(connect_data); |
| 1891 session_deps_.host_resolver->set_synchronous_mode(true); |
| 1892 session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data); |
| 1893 |
| 1894 SSLSocketDataProvider ssl(SYNCHRONOUS, OK); |
| 1895 session_deps_.deterministic_socket_factory->AddSSLSocketDataProvider(&ssl); |
| 1896 |
| 1897 CreateDeterministicNetworkSession(); |
| 1898 |
| 1899 scoped_refptr<SpdySession> session = CreateInitializedSession(); |
| 1900 |
| 1901 scoped_refptr<SpdyStream> spdy_stream1; |
| 1902 TestCompletionCallback callback1; |
| 1903 GURL url1("http://www.google.com"); |
| 1904 EXPECT_EQ(OK, session->CreateStream(url1, MEDIUM, &spdy_stream1, |
| 1905 BoundNetLog(), callback1.callback())); |
| 1906 EXPECT_EQ(0u, spdy_stream1->stream_id()); |
| 1907 |
| 1908 scoped_ptr<SpdyHeaderBlock> headers(new SpdyHeaderBlock); |
| 1909 (*headers)[":method"] = "GET"; |
| 1910 (*headers)[":scheme"] = url1.scheme(); |
| 1911 (*headers)[":host"] = url1.host(); |
| 1912 (*headers)[":path"] = url1.path(); |
| 1913 (*headers)[":version"] = "HTTP/1.1"; |
| 1914 |
| 1915 spdy_stream1->set_spdy_headers(headers.Pass()); |
| 1916 EXPECT_TRUE(spdy_stream1->HasUrl()); |
| 1917 spdy_stream1->SendRequest(false); |
| 1918 |
| 1919 // Set up the TaskObserver to verify SpdySession::DoRead posts a task. |
| 1920 SpdySessionTestTaskObserver observer("spdy_session.cc", "DoRead"); |
| 1921 |
| 1922 // Run until 1st read. |
| 1923 EXPECT_EQ(0u, spdy_stream1->stream_id()); |
| 1924 data.RunFor(2); |
| 1925 EXPECT_EQ(1u, spdy_stream1->stream_id()); |
| 1926 EXPECT_EQ(0u, observer.posted_count()); |
| 1927 |
| 1928 // Read all the data and verify SpdySession::DoRead has posted a task. |
| 1929 data.RunFor(6); |
| 1930 |
| 1931 // Verify task observer's posted_count is 1, which indicates DoRead has posted |
| 1932 // only one task and thus yielded though there is data available for it to |
| 1933 // read. |
| 1934 EXPECT_EQ(1u, observer.posted_count()); |
| 1935 EXPECT_TRUE(data.at_write_eof()); |
| 1936 EXPECT_TRUE(data.at_read_eof()); |
| 1937 } |
| 1938 |
1751 } // namespace net | 1939 } // namespace net |
OLD | NEW |