blob: 4e1aa1bd3e92f31647692c6b93a6eec78cf67109 [file] [log] [blame]
// Copyright (c) 2016 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/third_party/quiche/src/quic/core/http/quic_spdy_server_stream_base.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_ptr_util.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_test.h"
#include "net/third_party/quiche/src/quic/test_tools/quic_spdy_session_peer.h"
#include "net/third_party/quiche/src/quic/test_tools/quic_test_utils.h"
using testing::_;
namespace quic {
namespace test {
namespace {
class TestQuicSpdyServerStream : public QuicSpdyServerStreamBase {
public:
TestQuicSpdyServerStream(QuicStreamId id,
QuicSpdySession* session,
StreamType type)
: QuicSpdyServerStreamBase(id, session, type) {}
void OnBodyAvailable() override {}
};
class QuicSpdyServerStreamBaseTest : public QuicTest {
protected:
QuicSpdyServerStreamBaseTest()
: session_(new MockQuicConnection(&helper_,
&alarm_factory_,
Perspective::IS_SERVER)) {
stream_ = new TestQuicSpdyServerStream(
GetNthClientInitiatedBidirectionalStreamId(
session_.connection()->transport_version(), 0),
&session_, BIDIRECTIONAL);
session_.ActivateStream(QuicWrapUnique(stream_));
helper_.AdvanceTime(QuicTime::Delta::FromSeconds(1));
}
QuicSpdyServerStreamBase* stream_ = nullptr;
MockQuicConnectionHelper helper_;
MockAlarmFactory alarm_factory_;
MockQuicSpdySession session_;
};
TEST_F(QuicSpdyServerStreamBaseTest,
SendQuicRstStreamNoErrorWithEarlyResponse) {
stream_->StopReading();
EXPECT_CALL(session_, SendRstStream(_, QUIC_STREAM_NO_ERROR, _)).Times(1);
stream_->set_fin_sent(true);
stream_->CloseWriteSide();
}
TEST_F(QuicSpdyServerStreamBaseTest,
DoNotSendQuicRstStreamNoErrorWithRstReceived) {
EXPECT_FALSE(stream_->reading_stopped());
EXPECT_CALL(session_, SendRstStream(_, QUIC_STREAM_NO_ERROR, _)).Times(0);
if (session_.connection()->transport_version() != QUIC_VERSION_99) {
EXPECT_CALL(session_, SendRstStream(_, QUIC_RST_ACKNOWLEDGEMENT, _))
.Times(1);
} else {
// Intercept & check that the call to the QuicConnection's OnStreamReast
// has correct stream ID and error code -- for V99/IETF Quic, it should
// have the STREAM_CANCELLED error code, not RST_ACK... Capture
// OnStreamReset (rather than SendRstStream) because the V99 path bypasses
// SendRstStream, calling SendRstStreamInner directly. Mocking
// SendRstStreamInner is problematic since the test relies on it to perform
// the closing operations and getting the stream in the correct state.
EXPECT_CALL(*(static_cast<MockQuicConnection*>(session_.connection())),
OnStreamReset(stream_->id(), QUIC_STREAM_CANCELLED));
}
QuicRstStreamFrame rst_frame(kInvalidControlFrameId, stream_->id(),
QUIC_STREAM_CANCELLED, 1234);
stream_->OnStreamReset(rst_frame);
if (session_.connection()->transport_version() == QUIC_VERSION_99) {
// Create and inject a STOP SENDING frame to complete the close
// of the stream. This is only needed for version 99/IETF QUIC.
QuicStopSendingFrame stop_sending(
kInvalidControlFrameId, stream_->id(),
static_cast<QuicApplicationErrorCode>(QUIC_STREAM_CANCELLED));
session_.OnStopSendingFrame(stop_sending);
}
EXPECT_TRUE(stream_->reading_stopped());
EXPECT_TRUE(stream_->write_side_closed());
}
} // namespace
} // namespace test
} // namespace quic