// Copyright 2016 The Bazel Authors. All rights reserved.
//
// 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 "src/tools/singlejar/test_util.h"

#include <fcntl.h>
#include <stdarg.h>
#include <stdlib.h>
#include <sys/types.h>

#include <string>

#include "src/main/cpp/util/file.h"
#include "src/main/cpp/util/file_platform.h"
#include "src/main/cpp/util/strings.h"

#include "gtest/gtest.h"

namespace singlejar_test_util {

bool AllocateFile(const string &name, size_t size) {
  int fd = open(name.c_str(), O_CREAT | O_RDWR | O_TRUNC, 0777);
  if (fd < 0) {
    perror(name.c_str());
    return false;
  }
  if (size) {
    if (ftruncate(fd, size) == 0) {
      return close(fd) == 0;
    } else {
      auto last_error = errno;
      close(fd);
      errno = last_error;
      return false;
    }
  } else {
    return close(fd) == 0;
  }
}

int RunCommand(const char *cmd, ...) {
  string args_string(cmd);
  va_list ap;
  va_start(ap, cmd);
  for (const char *arg = va_arg(ap, const char *); arg;
       arg = va_arg(ap, const char *)) {
    args_string += ' ';
    args_string += arg;
  }
  va_end(ap);
  fprintf(stderr, "Arguments: %s\n", args_string.c_str());
  return system(args_string.c_str());
}

// List zip file contents.
void LsZip(const char *zip_name) {
#if !defined(__APPLE__)
  RunCommand("unzip", "-v", zip_name, nullptr);
#endif
}

string OutputFilePath(const string &relpath) {
  const char *out_dir = getenv("TEST_TMPDIR");
  return blaze_util::JoinPath((nullptr == out_dir) ? "." : out_dir,
                              relpath.c_str());
}

int VerifyZip(const string &zip_path) {
  string verify_command;
  blaze_util::StringPrintf(&verify_command, "zip -Tv %s", zip_path.c_str());
  return system(verify_command.c_str());
}

string GetEntryContents(const string &zip_path, const string &entry_name) {
  string contents;
  string command;
  blaze_util::StringPrintf(&command, "unzip -p %s %s", zip_path.c_str(),
                           entry_name.c_str());
  FILE *fp = popen(command.c_str(), "r");
  if (!fp) {
    ADD_FAILURE() << "Command " << command << " failed.";
    return string("");
  }

  char buf[1024];
  while (fgets(buf, sizeof(buf), fp)) {
    contents.append(buf);
  }
  if (feof(fp) && !ferror(fp) && !pclose(fp)) {
    return contents;
  }
  ADD_FAILURE() << "Command " << command << " failed on close.";
  return string("");
}

string CreateTextFile(const string& relpath, const char *contents) {
  string out_path = OutputFilePath(relpath);
  blaze_util::MakeDirectories(blaze_util::Dirname(out_path), 0777);
  if (blaze_util::WriteFile(contents, out_path)) {
    return out_path;
  }
  ADD_FAILURE() << "Cannot write " << out_path;
  return string("");
}

}  // namespace singlejar_test_util
