text: // Copyright 2013 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/write_blocked_list.h"
  
  #include <deque>
  
  #include "testing/gtest/include/gtest/gtest.h"
  
  namespace net {
  namespace test {
  
  class WriteBlockedListPeer {
   public:
    static std::deque<int>* GetWriteBlockedList(int i,
                                                WriteBlockedList<int>* list) {
      return &list->write_blocked_lists_[i];
    }
  };
  
  namespace {
  
  typedef WriteBlockedList<int> IntWriteBlockedList;
  
  class WriteBlockedListTest : public ::testing::Test {
   public:
    IntWriteBlockedList list;
  };
  
  TEST_F(WriteBlockedListTest, GetHighestPriority) {
    EXPECT_FALSE(list.HasWriteBlockedStreams());
    list.PushBack(1, 1);
    EXPECT_TRUE(list.HasWriteBlockedStreams());
    EXPECT_EQ(1, list.GetHighestPriorityWriteBlockedList());
    list.PushBack(1, 0);
    EXPECT_TRUE(list.HasWriteBlockedStreams());
    EXPECT_EQ(0, list.GetHighestPriorityWriteBlockedList());
  }
  
  TEST_F(WriteBlockedListTest, HasWriteBlockedStreamsOfGreaterThanPriority) {
    list.PushBack(1, 4);
    EXPECT_TRUE(list.HasWriteBlockedStreamsGreaterThanPriority(5));
    EXPECT_FALSE(list.HasWriteBlockedStreamsGreaterThanPriority(4));
    list.PushBack(2, 2);
    EXPECT_TRUE(list.HasWriteBlockedStreamsGreaterThanPriority(3));
    EXPECT_FALSE(list.HasWriteBlockedStreamsGreaterThanPriority(2));
  }
  
  TEST_F(WriteBlockedListTest, RemoveStreamFromWriteBlockedList) {
    list.PushBack(1, 4);
    EXPECT_TRUE(list.HasWriteBlockedStreams());
  
    list.RemoveStreamFromWriteBlockedList(1, 5);
    EXPECT_TRUE(list.HasWriteBlockedStreams());
  
    list.PushBack(2, 4);
    list.PushBack(1, 4);
    list.RemoveStreamFromWriteBlockedList(1, 4);
    list.RemoveStreamFromWriteBlockedList(2, 4);
    EXPECT_FALSE(list.HasWriteBlockedStreams());
  
    list.PushBack(1, 7);
    EXPECT_TRUE(list.HasWriteBlockedStreams());
  }
  
  TEST_F(WriteBlockedListTest, PopFront) {
    list.PushBack(1, 4);
    EXPECT_EQ(1u, list.NumBlockedStreams());
    list.PushBack(2, 4);
    list.PushBack(1, 4);
    list.PushBack(3, 4);
    EXPECT_EQ(3u, list.NumBlockedStreams());
  
    EXPECT_EQ(1, list.PopFront(4));
    EXPECT_EQ(2, list.PopFront(4));
    EXPECT_EQ(1u, list.NumBlockedStreams());
    EXPECT_EQ(3, list.PopFront(4));
  }
  
  TEST_F(WriteBlockedListTest, PushFront) {
    list.PushFront(1, 4);
    EXPECT_EQ(1u, list.NumBlockedStreams());
    list.PushFront(2, 4);
    list.PushFront(1, 4);
    list.PushFront(3, 4);
    EXPECT_EQ(3u, list.NumBlockedStreams());
  
    EXPECT_EQ(3, list.PopFront(4));
    EXPECT_EQ(2, list.PopFront(4));
    EXPECT_EQ(1u, list.NumBlockedStreams());
    EXPECT_EQ(1, list.PopFront(4));
  }
  
  TEST_F(WriteBlockedListTest, PushFrontAndBack) {
    list.PushFront(1, 4);
    list.PushBack(5, 4);
    list.PushFront(2, 4);
    list.PushBack(3, 4);
    list.PushFront(4, 4);
  
    EXPECT_EQ(4, list.PopFront(4));
    EXPECT_EQ(2, list.PopFront(4));
    EXPECT_EQ(1, list.PopFront(4));
    EXPECT_EQ(5, list.PopFront(4));
    EXPECT_EQ(3, list.PopFront(4));
  }
  
  TEST_F(WriteBlockedListTest, UpdateStreamPriorityInWriteBlockedList) {
    list.PushBack(1, 1);
    list.PushBack(2, 2);
    list.PushBack(3, 3);
    list.PushBack(1, 3);  // Re-prioritizes stream 1 at priority 3.
    list.PushBack(1, 3);  // No effect.
    EXPECT_EQ(3u, list.NumBlockedStreams());
    EXPECT_EQ(0u, WriteBlockedListPeer::GetWriteBlockedList(1, &list)->size());
    EXPECT_EQ(1u, WriteBlockedListPeer::GetWriteBlockedList(2, &list)->size());
    EXPECT_EQ(2u, WriteBlockedListPeer::GetWriteBlockedList(3, &list)->size());
  
    list.UpdateStreamPriorityInWriteBlockedList(1, 3, 2);
    EXPECT_EQ(0u, WriteBlockedListPeer::GetWriteBlockedList(1, &list)->size());
    EXPECT_EQ(2u, WriteBlockedListPeer::GetWriteBlockedList(2, &list)->size());
    list.UpdateStreamPriorityInWriteBlockedList(3, 3, 1);
    EXPECT_EQ(1u, WriteBlockedListPeer::GetWriteBlockedList(1, &list)->size());
    EXPECT_EQ(0u, WriteBlockedListPeer::GetWriteBlockedList(3, &list)->size());
  
    // Redundant update.
    list.UpdateStreamPriorityInWriteBlockedList(1, 2, 2);
    EXPECT_EQ(2u, WriteBlockedListPeer::GetWriteBlockedList(2, &list)->size());
  
    // No entries for given stream_id / old_priority pair.
    list.UpdateStreamPriorityInWriteBlockedList(4, 4, 1);
    EXPECT_EQ(1u, WriteBlockedListPeer::GetWriteBlockedList(1, &list)->size());
    EXPECT_EQ(2u, WriteBlockedListPeer::GetWriteBlockedList(2, &list)->size());
    EXPECT_EQ(0u, WriteBlockedListPeer::GetWriteBlockedList(4, &list)->size());
  
    EXPECT_EQ(3, list.PopFront(1));
    EXPECT_EQ(2, list.PopFront(2));
    EXPECT_EQ(1, list.PopFront(2));
    EXPECT_EQ(0u, list.NumBlockedStreams());
  }
  
  }  // namespace
  
  }  // namespace test
  }  // namespace net
  