// Copyright (c) 2012 The Chromium OS 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 "chromiumos-wide-profiling/scoped_temp_path.h"

#include <sys/stat.h>

#include <vector>

#include "base/logging.h"
#include "chromiumos-wide-profiling/compat/test.h"

namespace {

// For testing the creation of multiple temp paths.
const int kNumMultiplePaths = 32;

// When testing non-empty directories, populate them with this many files.
const int kNumFilesPerNonEmptyDirectory = 10;

// Tests if |path| exists on the file system.
bool PathExists(const string& path) {
  struct stat buf;
  // stat() returns 0 on success, i.e. if the path exists and is valid.
  return !stat(path.c_str(), &buf);
}

// Creates some files in a directory. Returns the number of files created.
int PopulateDirectoryWithFiles(const string& dir, int num_files) {
  // The last six characters of the file template must be "XXXXXX".
  const char kPathTemplateSuffix[] = "/testXXXXXX";

  // The string providing the path template for creating temp files must not be
  // constant, so allocate some space here.
  size_t buf_size = dir.size() + strlen(kPathTemplateSuffix) + 1;
  char* path_template = new char[buf_size];

  int num_files_created = 0;
  for (int i = 0; i < num_files; ++i) {
    // Construct the mutable path template.
    snprintf(path_template, buf_size, "%s%s", dir.c_str(), kPathTemplateSuffix);
    // Create the file and make sure it is valid.
    int fd = mkstemp(path_template);
    if (fd == -1) {
      LOG(ERROR) << "Could not create file, errno=" << errno;
      continue;
    }
    ++num_files_created;
    close(fd);
  }
  delete [] path_template;

  return num_files_created;
}

}  // namespace

namespace quipper {

// Create one file and make sure it is deleted when out of scope.
TEST(ScopedTempPathTest, OneFile) {
  string path;
  {
    ScopedTempFile temp_file;
    path = temp_file.path();
    EXPECT_TRUE(PathExists(path)) << path;
  }
  EXPECT_FALSE(PathExists(path)) << path;
}

// Create many files and make sure they are deleted when out of scope.
TEST(ScopedTempPathTest, MultipleFiles) {
  std::vector<string> paths(kNumMultiplePaths);
  {
    std::vector<ScopedTempFile> temp_files(kNumMultiplePaths);
    for (size_t i = 0; i < kNumMultiplePaths; ++i) {
      paths[i] = temp_files[i].path();
      EXPECT_TRUE(PathExists(paths[i])) << paths[i];
    }
  }
  for (size_t i = 0; i < kNumMultiplePaths; ++i) {
    EXPECT_FALSE(PathExists(paths[i])) << paths[i];
  }
}

// Create one empty directory and make sure it is deleted when out of scope.
TEST(ScopedTempPathTest, OneEmptyDir) {
  string path;
  {
    ScopedTempDir temp_path;
    path = temp_path.path();
    EXPECT_TRUE(PathExists(path)) << path;
  }
  EXPECT_FALSE(PathExists(path)) << path;
}

// Create many empty directories and make sure they are deleted when out of
// scope.
TEST(ScopedTempPathTest, MultipleEmptyDirs) {
  std::vector<string> paths(kNumMultiplePaths);
  {
    std::vector<ScopedTempDir> temp_dirs(kNumMultiplePaths);
    for (size_t i = 0; i < kNumMultiplePaths; ++i) {
      paths[i] = temp_dirs[i].path();
      EXPECT_TRUE(PathExists(paths[i])) << paths[i];
    }
  }
  for (size_t i = 0; i < kNumMultiplePaths; ++i) {
    EXPECT_FALSE(PathExists(paths[i])) << paths[i];
  }
}

// Create a directory with some files in it, and make sure it is deleted when
// out of scope.
TEST(ScopedTempPathTest, OneNonEmptyDir) {
  string path;
  {
    ScopedTempDir temp_path;
    path = temp_path.path();
    EXPECT_TRUE(PathExists(path)) << path;
    // Populate the directory with files.
    EXPECT_EQ(kNumFilesPerNonEmptyDirectory,
              PopulateDirectoryWithFiles(path, kNumFilesPerNonEmptyDirectory));
  }
  EXPECT_FALSE(PathExists(path)) << path;
}

// Create many empty directories with files in them, and make sure they are
// deleted when out of scope.
TEST(ScopedTempPathTest, MultipleNonEmptyDirs) {
  std::vector<string> paths(kNumMultiplePaths);
  {
    std::vector<ScopedTempDir> temp_dirs(kNumMultiplePaths);
    for (size_t i = 0; i < kNumMultiplePaths; ++i) {
      paths[i] = temp_dirs[i].path();
      EXPECT_TRUE(PathExists(paths[i])) << paths[i];
      // Populate the directory with files.
      EXPECT_EQ(
          kNumFilesPerNonEmptyDirectory,
          PopulateDirectoryWithFiles(paths[i], kNumFilesPerNonEmptyDirectory));
    }
  }
  for (size_t i = 0; i < kNumMultiplePaths; ++i) {
    EXPECT_FALSE(PathExists(paths[i])) << paths[i];
  }
}

}  // namespace quipper

int main(int argc, char * argv[]) {
  ::testing::InitGoogleTest(&argc, argv);
  return RUN_ALL_TESTS();
}
