// Copyright 2015 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 <errno.h>
#include <fcntl.h>
#include <stddef.h>
#include <stdlib.h>
#include <unistd.h>
#include <string>
#include <vector>

#include "src/main/cpp/blaze_util.h"
#include "src/main/cpp/util/file.h"
#include "gtest/gtest.h"

namespace blaze {

using std::string;

static bool Symlink(const string& old_path, const string& new_path) {
  return symlink(old_path.c_str(), new_path.c_str()) == 0;
}

static bool CreateEmptyFile(const string& path) {
  int fd = open(path.c_str(), O_CREAT | O_WRONLY);
  if (fd == -1) {
    return false;
  }
  return close(fd) == 0;
}

class BlazeUtilTest : public ::testing::Test {
 protected:
  BlazeUtilTest() {
  }

  virtual ~BlazeUtilTest() {
  }

  static void ForkAndWrite(int fds[], string input1, string input2) {
    int r = fork();
    if (r == 0) {
      close(fds[0]);
      write(fds[1], input1.c_str(), input1.size());
      usleep(500);  // sleep for 50ms
      write(fds[1], input2.c_str(), input2.size());
      close(fds[1]);
      exit(0);
    } else if (r < 0) {
      perror("fork()");
      FAIL();
    } else {
      close(fds[1]);
    }
  }

  static int WriteFileDescriptor2(string input1, string input2) {
    // create a fd for the input string
    int fds[2];
    if (pipe(fds) == -1) {
      return -1;
    }
    if (fcntl(fds[0], F_SETFL, O_NONBLOCK) == -1
        || fcntl(fds[1], F_SETFL, O_NONBLOCK) == -1) {
      return -1;
    }
    if (input2.size() > 0) {
      ForkAndWrite(fds, input1, input2);
    } else {
      write(fds[1], input1.c_str(), input1.size());
      close(fds[1]);
    }
    return fds[0];
  }

  static void AssertReadFileDescriptor2(string input1, string input2) {
    int fd = WriteFileDescriptor2(input1, input2);
    if (fd < 0) {
      FAIL() << "Unable to create a pipe!";
    } else {
      string result;
      if (!ReadFileDescriptor(fd, &result)) {
        perror("ReadFileDescriptor");
        FAIL() << "Unable to read file descriptor!";
      } else {
        ASSERT_EQ(input1 + input2, result);
      }
    }
  }

  static void AssertReadFileDescriptor(string input) {
    AssertReadFileDescriptor2(input, "");
  }

  static void AssertReadJvmVersion(string expected, string input) {
    ASSERT_EQ(expected, ReadJvmVersion(input));
  }

  void ReadFileDescriptorTest() const {
    AssertReadFileDescriptor("DummyJDK Blabla\n"
                             "More DummyJDK Blabla\n");
    AssertReadFileDescriptor("dummyjdk version \"1.42.qual\"\n"
                         "DummyJDK Blabla\n"
                             "More DummyJDK Blabla\n");
    AssertReadFileDescriptor2("first_line\n",
                              "second line version \"1.4.2_0\"\n");
  }

  void ReadJvmVersionTest() const {
    AssertReadJvmVersion("1.42", "dummyjdk version \"1.42\"\n"
                         "DummyJDK Blabla\n"
                         "More DummyJDK Blabla\n");
    AssertReadJvmVersion("1.42.qual", "dummyjdk version \"1.42.qual\"\n"
                         "DummyJDK Blabla\n"
                         "More DummyJDK Blabla\n");
    AssertReadJvmVersion("1.42.qualifie", "dummyjdk version \"1.42.qualifie");
    AssertReadJvmVersion("", "dummyjdk version ");
    AssertReadJvmVersion("1.4.2_0",
                          "first_line\nsecond line version \"1.4.2_0\"\n");
  }

  void CheckJavaVersionIsAtLeastTest() const {
    ASSERT_TRUE(CheckJavaVersionIsAtLeast("1.7.0-ver-specifier-42", ""));
    ASSERT_TRUE(CheckJavaVersionIsAtLeast("1.7.0-ver-specifier-42", "0"));
    ASSERT_TRUE(CheckJavaVersionIsAtLeast("1.7.0-ver-specifier-42", "1"));
    ASSERT_TRUE(CheckJavaVersionIsAtLeast("1.7.0-ver-specifier-42", "1.7"));
    ASSERT_TRUE(CheckJavaVersionIsAtLeast("1.7.0-ver-specifier-42", "1.7.0"));
    ASSERT_TRUE(CheckJavaVersionIsAtLeast("1.7.0-ver-specifier-42", "1.0"));
    ASSERT_TRUE(CheckJavaVersionIsAtLeast("1.7.0-ver-specifier-42", "1.6"));
    ASSERT_TRUE(CheckJavaVersionIsAtLeast("1.42", "1"));
    ASSERT_TRUE(CheckJavaVersionIsAtLeast("1.42", "1.7"));
    ASSERT_TRUE(CheckJavaVersionIsAtLeast("1.42", "1.11"));
    ASSERT_TRUE(CheckJavaVersionIsAtLeast("1.42.42", "1.11"));
    ASSERT_TRUE(CheckJavaVersionIsAtLeast("1.42.42", "1.11.11"));

    ASSERT_FALSE(CheckJavaVersionIsAtLeast("1.7.0-ver-specifier-42", "42"));
    ASSERT_FALSE(CheckJavaVersionIsAtLeast("1.7.0-ver-specifier-42", "2"));
    ASSERT_FALSE(CheckJavaVersionIsAtLeast("1.7.0-ver-specifier-42", "1.8"));
    ASSERT_FALSE(CheckJavaVersionIsAtLeast("1.7.0-ver-specifier-42", "1.7.1"));
    ASSERT_FALSE(CheckJavaVersionIsAtLeast("1.7.0-ver-specifier-42", "1.42"));
    ASSERT_FALSE(CheckJavaVersionIsAtLeast("1.42", "2"));
    ASSERT_FALSE(CheckJavaVersionIsAtLeast("1.42", "1.69"));
    ASSERT_FALSE(CheckJavaVersionIsAtLeast("1.42", "1.42.1"));
    ASSERT_FALSE(CheckJavaVersionIsAtLeast("1.42.42", "1.42.43"));
    ASSERT_FALSE(CheckJavaVersionIsAtLeast("1.42.42.0", "1.42.42.1"));
  }
};

TEST_F(BlazeUtilTest, CheckJavaVersionIsAtLeast) {
  CheckJavaVersionIsAtLeastTest();
}

TEST_F(BlazeUtilTest, ReadFileDescriptor) {
  ReadFileDescriptorTest();
}

TEST_F(BlazeUtilTest, ReadJvmVersion) {
  ReadJvmVersionTest();
}

TEST_F(BlazeUtilTest, MakeDirectories) {
  const char* tmp_dir = getenv("TEST_TMPDIR");
  ASSERT_STRNE(tmp_dir, NULL);
  const char* test_src_dir = getenv("TEST_SRCDIR");
  ASSERT_STRNE(NULL, test_src_dir);

  string dir = blaze_util::JoinPath(tmp_dir, "x/y/z");
  int ok = MakeDirectories(dir, 0755);
  ASSERT_EQ(0, ok);

  // Changing permissions on an existing dir should work.
  ok = MakeDirectories(dir, 0750);
  ASSERT_EQ(0, ok);
  struct stat filestat = {};
  ASSERT_EQ(0, stat(dir.c_str(), &filestat));
  ASSERT_EQ(0750, filestat.st_mode & 0777);

  // srcdir shouldn't be writable.
  string srcdir = blaze_util::JoinPath(test_src_dir, "x/y/z");
  ok = MakeDirectories(srcdir, 0755);
  ASSERT_EQ(-1, ok);
  ASSERT_EQ(EACCES, errno);

  // Can't make a dir out of a file.
  string non_dir = blaze_util::JoinPath(dir, "w");
  ASSERT_TRUE(CreateEmptyFile(non_dir));
  ok = MakeDirectories(non_dir, 0755);
  ASSERT_EQ(-1, ok);
  ASSERT_EQ(ENOTDIR, errno);

  // Valid symlink should work.
  string symlink = blaze_util::JoinPath(tmp_dir, "z");
  ASSERT_TRUE(Symlink(dir, symlink));
  ok = MakeDirectories(symlink, 0755);
  ASSERT_EQ(0, ok);

  // Error: Symlink to a file.
  symlink = blaze_util::JoinPath(tmp_dir, "w");
  ASSERT_TRUE(Symlink(non_dir, symlink));
  ok = MakeDirectories(symlink, 0755);
  ASSERT_EQ(-1, ok);
  ASSERT_EQ(ENOTDIR, errno);

  // Error: Symlink to a dir with wrong perms.
  symlink = blaze_util::JoinPath(tmp_dir, "s");
  ASSERT_TRUE(Symlink("/", symlink));

  // These perms will force a chmod()
  ok = MakeDirectories(symlink, 0000);
  ASSERT_EQ(-1, ok);
  ASSERT_EQ(EPERM, errno);

  // Edge cases.
  ASSERT_EQ(-1, MakeDirectories("", 0755));
  ASSERT_EQ(EACCES, errno);
  ASSERT_EQ(-1, MakeDirectories("/", 0755));
  ASSERT_EQ(EACCES, errno);
}

TEST_F(BlazeUtilTest, HammerMakeDirectories) {
  const char* tmp_dir = getenv("TEST_TMPDIR");
  ASSERT_STRNE(tmp_dir, NULL);

  string path = blaze_util::JoinPath(tmp_dir, "x/y/z");
  ASSERT_LE(0, fork());
  ASSERT_EQ(0, MakeDirectories(path, 0755));
}

}  // namespace blaze
