/*
 * Copyright (C) 2019 The Android Open Source Project
 *
 * 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.
 */

#include "gtest/gtest.h"

#include <stdint.h>

#include "chre/util/system/debug_dump.h"

using chre::DebugDumpWrapper;

static constexpr size_t kStandardBufferSize = 4000;

TEST(DebugDumpWrapper, ZeroBuffersInitially) {
  DebugDumpWrapper debugDump(kStandardBufferSize);
  const auto &buffers = debugDump.getBuffers();
  EXPECT_TRUE(buffers.empty());
}

TEST(DebugDumpWrapper, OneBufferForOneString) {
  DebugDumpWrapper debugDump(kStandardBufferSize);
  const char *str = "Lorem ipsum";
  debugDump.print("%s", str);
  const auto &buffers = debugDump.getBuffers();
  EXPECT_EQ(buffers.size(), 1);
  EXPECT_TRUE(strcmp(buffers.front().get(), str) == 0);
}

TEST(DebugDumpWrapper, TwoStringsFitPerfectlyInOneBuffer) {
  DebugDumpWrapper debugDump(5);
  const char *str1 = "ab";
  const char *str2 = "cd";
  debugDump.print("%s", str1);
  debugDump.print("%s", str2);
  const auto &buffers = debugDump.getBuffers();
  EXPECT_EQ(buffers.size(), 1);
  char bothStr[5];
  strcpy(bothStr, str1);
  strcat(bothStr, str2);
  EXPECT_TRUE(strcmp(buffers.front().get(), bothStr) == 0);
}

TEST(DebugDumpWrapper, TooLargeOfStringToFit) {
  DebugDumpWrapper debugDump(1);
  const char *str = "a";
  debugDump.print("%s", str);
  const auto &buffers = debugDump.getBuffers();

  // One null-terminated buffer will be created for an empty wrapper.
  EXPECT_EQ(buffers.size(), 1);
  EXPECT_TRUE(strcmp(buffers.back().get(), "") == 0);

  // Once there's a buffer, it won't be updated.
  debugDump.print("%s", str);
  EXPECT_EQ(buffers.size(), 1);
  EXPECT_TRUE(strcmp(buffers.back().get(), "") == 0);
}

TEST(DebugDumpWrapper, TooLargeOfStringWithPartlyFilledBuffer) {
  DebugDumpWrapper debugDump(2);
  const char *str1 = "a";
  const char *str2 = "bc";
  debugDump.print("%s", str1);
  const auto &buffers = debugDump.getBuffers();
  EXPECT_EQ(buffers.size(), 1);
  debugDump.print("%s", str2);
  EXPECT_EQ(buffers.size(), 1);
  EXPECT_TRUE(strcmp(buffers.front().get(), str1) == 0);
}

TEST(DebugDumpWrapper, StringForcesNewBufferWithPartlyFilledBuffer) {
  DebugDumpWrapper debugDump(4);
  const char *str1 = "ab";
  const char *str2 = "bc";
  debugDump.print("%s", str1);
  debugDump.print("%s", str2);
  const auto &buffers = debugDump.getBuffers();
  EXPECT_EQ(buffers.size(), 2);
  EXPECT_TRUE(strcmp(buffers.front().get(), str1) == 0);
  EXPECT_TRUE(strcmp(buffers.back().get(), str2) == 0);
}

TEST(DebugDumpWrapper, ManyNewBuffersAllocated) {
  DebugDumpWrapper debugDump(kStandardBufferSize);
  const char *str = "aaaaaaaaa";
  // Should be 12000 chars added to debugDump
  constexpr size_t kNumPrints = 1200;
  for (size_t i = 0; i < kNumPrints; i++) {
    debugDump.print("%s", str);
  }
  const auto &buffers = debugDump.getBuffers();
  EXPECT_EQ(buffers.size(), 3);
}

TEST(DebugDumpWrapper, EmptyStringAllocsOneBuffer) {
  DebugDumpWrapper debugDump(kStandardBufferSize);
  debugDump.print("%s", "");
  const auto &buffers = debugDump.getBuffers();
  EXPECT_EQ(buffers.size(), 1);
}

TEST(DebugDumpWrapper, BuffersClear) {
  DebugDumpWrapper debugDump(4);
  const char *str1 = "ab";
  const char *str2 = "cd";
  const char *str3 = "ef";

  debugDump.print("%s", str1);
  debugDump.print("%s", str2);
  const auto &buffers = debugDump.getBuffers();
  EXPECT_EQ(buffers.size(), 2);
  EXPECT_TRUE(strcmp(buffers.front().get(), str1) == 0);
  EXPECT_TRUE(strcmp(buffers.back().get(), str2) == 0);

  debugDump.clear();
  EXPECT_EQ(buffers.size(), 0);

  debugDump.print("%s", str3);
  EXPECT_EQ(buffers.size(), 1);
  EXPECT_TRUE(strcmp(buffers.front().get(), str3) == 0);
}

void printVaList(DebugDumpWrapper *debugDump, const char *formatStr, ...) {
  va_list args;
  va_start(args, formatStr);
  debugDump->printVaList(formatStr, args);
  va_end(args);
}

TEST(DebugDumpWrapper, PrintVaListTwoStrings) {
  DebugDumpWrapper debugDump(5);
  const char *str1 = "ab";
  const char *str2 = "cd";
  printVaList(&debugDump, "%s", str1);
  printVaList(&debugDump, "%s", str2);
  const auto &buffers = debugDump.getBuffers();
  EXPECT_EQ(buffers.size(), 1);
  char bothStr[5];
  strcpy(bothStr, str1);
  strcat(bothStr, str2);
  EXPECT_TRUE(strcmp(buffers.front().get(), bothStr) == 0);
}
