// 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/log/test_net_log_util.h"

#include <cstddef>

namespace net {

namespace {

// Takes the list of entries and an offset, and returns an index into the array.
// If |offset| is positive, just returns |offset|.  If it's negative, it
// indicates a position relative to the end of the array.
size_t GetIndex(const TestNetLogEntry::List& entries, int offset) {
  if (offset >= 0)
    return static_cast<size_t>(offset);

  size_t abs_offset = static_cast<size_t>(-offset);
  // If offset indicates a position before the start of the array, just return
  // the end of the list.
  if (abs_offset > entries.size())
    return entries.size();
  return entries.size() - abs_offset;
}

}  // namespace

::testing::AssertionResult LogContainsEvent(
    const TestNetLogEntry::List& entries,
    int offset,
    NetLog::EventType expected_event,
    NetLog::EventPhase expected_phase) {
  size_t index = GetIndex(entries, offset);
  if (index >= entries.size())
    return ::testing::AssertionFailure() << index << " is out of bounds.";
  const TestNetLogEntry& entry = entries[index];
  if (expected_event != entry.type) {
    return ::testing::AssertionFailure()
           << "Actual event: " << NetLog::EventTypeToString(entry.type)
           << ". Expected event: " << NetLog::EventTypeToString(expected_event)
           << ".";
  }
  if (expected_phase != entry.phase) {
    return ::testing::AssertionFailure()
           << "Actual phase: " << entry.phase
           << ". Expected phase: " << expected_phase << ".";
  }
  return ::testing::AssertionSuccess();
}

::testing::AssertionResult LogContainsBeginEvent(
    const TestNetLogEntry::List& entries,
    int offset,
    NetLog::EventType expected_event) {
  return LogContainsEvent(entries, offset, expected_event, NetLog::PHASE_BEGIN);
}

::testing::AssertionResult LogContainsEndEvent(
    const TestNetLogEntry::List& entries,
    int offset,
    NetLog::EventType expected_event) {
  return LogContainsEvent(entries, offset, expected_event, NetLog::PHASE_END);
}

::testing::AssertionResult LogContainsEntryWithType(
    const TestNetLogEntry::List& entries,
    int offset,
    NetLog::EventType type) {
  size_t index = GetIndex(entries, offset);
  if (index >= entries.size())
    return ::testing::AssertionFailure() << index << " is out of bounds.";
  const TestNetLogEntry& entry = entries[index];
  if (entry.type != type)
    return ::testing::AssertionFailure() << "Type does not match.";
  return ::testing::AssertionSuccess();
}

::testing::AssertionResult LogContainsEntryWithTypeAfter(
    const TestNetLogEntry::List& entries,
    int start_offset,
    NetLog::EventType type) {
  for (size_t i = GetIndex(entries, start_offset); i < entries.size(); ++i) {
    const TestNetLogEntry& entry = entries[i];
    if (entry.type == type)
      return ::testing::AssertionSuccess();
  }
  return ::testing::AssertionFailure();
}

size_t ExpectLogContainsSomewhere(const TestNetLogEntry::List& entries,
                                  size_t min_offset,
                                  NetLog::EventType expected_event,
                                  NetLog::EventPhase expected_phase) {
  size_t min_index = GetIndex(entries, min_offset);
  size_t i = 0;
  for (; i < entries.size(); ++i) {
    const TestNetLogEntry& entry = entries[i];
    if (entry.type == expected_event && entry.phase == expected_phase)
      break;
  }
  EXPECT_LT(i, entries.size());
  EXPECT_GE(i, min_index);
  return i;
}

size_t ExpectLogContainsSomewhereAfter(const TestNetLogEntry::List& entries,
                                       size_t start_offset,
                                       NetLog::EventType expected_event,
                                       NetLog::EventPhase expected_phase) {
  size_t i = GetIndex(entries, start_offset);
  for (; i < entries.size(); ++i) {
    const TestNetLogEntry& entry = entries[i];
    if (entry.type == expected_event && entry.phase == expected_phase)
      break;
  }
  EXPECT_LT(i, entries.size());
  return i;
}

}  // namespace net
