/*
 * Copyright 2011 Google Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

// Author: morlovich@google.com (Maksim Orlovich)

#include "pagespeed/kernel/base/chunking_writer.h"

#include "pagespeed/kernel/base/gtest.h"
#include "pagespeed/kernel/base/mock_message_handler.h"
#include "pagespeed/kernel/base/null_mutex.h"
#include "pagespeed/kernel/base/scoped_ptr.h"
#include "pagespeed/kernel/base/string.h"
#include "pagespeed/kernel/base/string_util.h"
#include "pagespeed/kernel/base/writer.h"

namespace net_instaweb {
class MessageHandler;

namespace {

// Records a traces of writes and flushes performed into recorded()
// as follows:
// 1) Write of "text" will append: W:text|
// 2) A flush will append: F|
//
// Also makes sure the passed in handler is correct, and let's one
// trigger failures on a given operation.
class TracingWriter : public Writer {
 public:
  explicit TracingWriter(MessageHandler* expected_handler) :
      expected_handler_(expected_handler), ops_(0), fail_on_op_(-1) {
  }

  virtual bool Write(const StringPiece& str, MessageHandler* handler) {
    EXPECT_EQ(expected_handler_, handler);
    if (ops_ == fail_on_op_) {
      // Still advance, so that we know we don't get called again
      ++ops_;
      return false;
    }
    ++ops_;

    recorded_.append("W:");
    recorded_.append(str.data(), str.size());
    recorded_.append("|");
    return true;
  }

  virtual bool Flush(MessageHandler* handler) {
    EXPECT_EQ(expected_handler_, handler);
    if (ops_ == fail_on_op_) {
      // Still advance, so that we know we don't get called again
      ++ops_;
      return false;
    }
    ++ops_;

    recorded_.append("F|");
    return true;
  }

  const GoogleString& recorded() const { return recorded_; }

  // Tells this filter to report a failure on n'th invocation exactly.
  // (starting from 0)
  void set_fail_on_op(int n) { fail_on_op_ = n; }

 private:
  MessageHandler* expected_handler_;
  GoogleString recorded_;
  int ops_;
  int fail_on_op_;
};


class ChunkingWriterTest : public testing::Test {
 public:
  ChunkingWriterTest() : message_handler_(new NullMutex) {}

  virtual void SetUp() {
    tracer_.reset(new TracingWriter(&message_handler_));
    SetUpWithLimit(0);
  }

  void SetUpWithLimit(int limit) {
    chunker_.reset(new ChunkingWriter(tracer_.get(), limit));
  }

 protected:
  MockMessageHandler message_handler_;
  scoped_ptr<TracingWriter> tracer_;
  scoped_ptr<ChunkingWriter> chunker_;
};

TEST_F(ChunkingWriterTest, UnchunkedBasic) {
  EXPECT_TRUE(chunker_->Write("abc", &message_handler_));
  EXPECT_TRUE(chunker_->Write("def", &message_handler_));
  EXPECT_TRUE(chunker_->Flush(&message_handler_));
  EXPECT_EQ("W:abc|W:def|F|", tracer_->recorded());
}

TEST_F(ChunkingWriterTest, ChunkedBasic) {
  SetUpWithLimit(2);
  EXPECT_TRUE(chunker_->Write("abc", &message_handler_));
  EXPECT_TRUE(chunker_->Write("def", &message_handler_));
  EXPECT_TRUE(chunker_->Flush(&message_handler_));
  EXPECT_EQ("W:ab|F|W:c|W:d|F|W:ef|F|F|", tracer_->recorded());
}

TEST_F(ChunkingWriterTest, ChunkedBasicLong) {
  SetUpWithLimit(4);
  EXPECT_TRUE(chunker_->Write("abcdefghijklmnopqrs", &message_handler_));
  EXPECT_TRUE(chunker_->Flush(&message_handler_));
  EXPECT_EQ("W:abcd|F|W:efgh|F|W:ijkl|F|W:mnop|F|W:qrs|F|",
            tracer_->recorded());
}

TEST_F(ChunkingWriterTest, ChunkedManualFlush) {
  SetUpWithLimit(4);
  EXPECT_TRUE(chunker_->Write("abc", &message_handler_));
  EXPECT_TRUE(chunker_->Flush(&message_handler_));
  EXPECT_TRUE(chunker_->Write("defgh", &message_handler_));
  EXPECT_EQ("W:abc|F|W:defg|F|W:h|", tracer_->recorded());
}

TEST_F(ChunkingWriterTest, UnchunkedFailureProp1) {
  tracer_->set_fail_on_op(1);
  EXPECT_TRUE(chunker_->Write("abc", &message_handler_));
  EXPECT_FALSE(chunker_->Write("def", &message_handler_));
  EXPECT_EQ("W:abc|", tracer_->recorded());
}

TEST_F(ChunkingWriterTest, UnchunkedFailureProp2) {
  tracer_->set_fail_on_op(2);
  EXPECT_TRUE(chunker_->Write("abc", &message_handler_));
  EXPECT_TRUE(chunker_->Write("def", &message_handler_));
  EXPECT_FALSE(chunker_->Flush(&message_handler_));
  EXPECT_EQ("W:abc|W:def|", tracer_->recorded());
}

TEST_F(ChunkingWriterTest, ChunkedFailureProp1) {
  tracer_->set_fail_on_op(1);
  SetUpWithLimit(4);
  EXPECT_FALSE(chunker_->Write("abcdefgh", &message_handler_));
  EXPECT_EQ("W:abcd|", tracer_->recorded());
}

TEST_F(ChunkingWriterTest, ChunkedFailureProp2) {
  tracer_->set_fail_on_op(2);
  SetUpWithLimit(4);
  EXPECT_FALSE(chunker_->Write("abcdefgh", &message_handler_));
  EXPECT_EQ("W:abcd|F|", tracer_->recorded());
}

TEST_F(ChunkingWriterTest, ChunkedFailureProp3) {
  tracer_->set_fail_on_op(3);
  SetUpWithLimit(4);
  EXPECT_FALSE(chunker_->Write("abcdefgh", &message_handler_));
  EXPECT_EQ("W:abcd|F|W:efgh|", tracer_->recorded());
}

TEST_F(ChunkingWriterTest, ChunkedFailureProp4) {
  tracer_->set_fail_on_op(4);
  SetUpWithLimit(4);
  EXPECT_TRUE(chunker_->Write("abcdefgh", &message_handler_));
  EXPECT_EQ("W:abcd|F|W:efgh|F|", tracer_->recorded());
}

}  // namespace

}  // namespace net_instaweb
