// Copyright (c) 2012 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/quic/test_tools/quic_session_peer.h"

#include "net/quic/quic_session.h"
#include "net/quic/reliable_quic_stream.h"

using std::map;

namespace net {
namespace test {

// static
void QuicSessionPeer::SetNextStreamId(QuicSession* session, QuicStreamId id) {
  session->next_stream_id_ = id;
}

// static
void QuicSessionPeer::SetMaxOpenStreams(QuicSession* session,
                                        uint32 max_streams) {
  session->max_open_streams_ = max_streams;
}

// static
QuicCryptoStream* QuicSessionPeer::GetCryptoStream(QuicSession* session) {
  return session->GetCryptoStream();
}

// static
QuicHeadersStream* QuicSessionPeer::GetHeadersStream(QuicSession* session) {
  return session->headers_stream_.get();
}

// static
void QuicSessionPeer::SetHeadersStream(QuicSession* session,
                                       QuicHeadersStream* headers_stream) {
  session->headers_stream_.reset(headers_stream);
}

// static
QuicWriteBlockedList* QuicSessionPeer::GetWriteBlockedStreams(
    QuicSession* session) {
  return &session->write_blocked_streams_;
}

// static
QuicDataStream* QuicSessionPeer::GetIncomingDataStream(
    QuicSession* session,
    QuicStreamId stream_id) {
  return session->GetIncomingDataStream(stream_id);
}

// static
map<QuicStreamId, QuicStreamOffset>&
QuicSessionPeer::GetLocallyClosedStreamsHighestOffset(QuicSession* session) {
  return session->locally_closed_streams_highest_offset_;
}

}  // namespace test
}  // namespace net
