/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you 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 <fcntl.h>
#include <gtest/gtest.h>
#include <sys/stat.h>

#include <cstring>
#include <string>

#include "common/tsfile_common.h"
#include "file/read_file.h"
#include "file/restorable_tsfile_io_writer.h"
#include "file/utf8_file_open.h"
#include "file/write_file.h"
#include "writer/tsfile_writer.h"

#ifdef _WIN32
#include <io.h>
#include <windows.h>
#else
#include <unistd.h>
#endif

extern "C" {
typedef void* CWriteFile;
CWriteFile write_file_new(const char* pathname, int32_t* err_code);
void free_write_file(CWriteFile* write_file);
}

// Note: storage::WriteFile / storage::ReadFile are named after Win32 API
// functions that <windows.h> declares at global scope, so the class names are
// always written qualified here.
using namespace common;

namespace {

// The path bytes are spelled with explicit escapes so the test does not depend
// on how the compiler re-encodes non-ASCII literals from the source charset.
// UTF-8 for U+6D4B U+8BD5 ("test" in Chinese) followed by U+00E9 ("e-acute").
const char* kUtf8Stem = "\xE6\xB5\x8B\xE8\xAF\x95_\xC3\xA9_";

// Every gtest case runs as its own process (gtest_discover_tests) in a
// shared working directory, and ctest starts several of them at once
// (--parallel N).  A fixed file name would let one case's SetUp/TearDown
// unlink the file another case is mid-test with, so each case gets its
// own name, suffixed with the gtest case name (which is plain ASCII).
std::string Utf8Name() {
    const ::testing::TestInfo* info =
        ::testing::UnitTest::GetInstance()->current_test_info();
    return std::string(kUtf8Stem) +
           (info != nullptr ? info->name() : "unknown") + ".tsfile";
}

#ifdef _WIN32
// Same name as Utf8Name(), spelled as UTF-16 code units.  Test names are
// ASCII, so widening them is a plain char-by-char copy.
std::wstring WideName() {
    const ::testing::TestInfo* info =
        ::testing::UnitTest::GetInstance()->current_test_info();
    std::wstring wide(L"\x6D4B\x8BD5_\x00E9_");
    const char* tag = info != nullptr ? info->name() : "unknown";
    while (*tag != '\0') {
        wide += static_cast<wchar_t>(*tag++);
    }
    wide += L".tsfile";
    return wide;
}
#endif

// Smallest byte sequence that counts as a complete TsFile: head magic, the
// current version byte, then the tail magic. This is what ReadFile::open()
// requires (>= MIN_FILE_SIZE bytes, magic at both ends) and also what
// RestorableTsFileIOWriter's self check treats as complete.
//
// Built on first use rather than at file scope: VERSION_NUM_BYTE is defined in
// another translation unit, so a file-scope initializer would depend on static
// initialization order.
const std::string& MinimalTsFile() {
    static const std::string bytes = std::string(storage::MAGIC_STRING_TSFILE) +
                                     storage::VERSION_NUM_BYTE +
                                     storage::MAGIC_STRING_TSFILE;
    return bytes;
}

// Remove both spellings: the intended wide name, and the mojibake name the
// narrow CRT produces from the UTF-8 bytes under a non-UTF-8 code page. Leaving
// the latter behind would let one test's stray file satisfy the next test.
void RemoveTestFiles() {
#ifdef _WIN32
    ::_wunlink(WideName().c_str());
    ::_unlink(Utf8Name().c_str());
#else
    ::unlink(Utf8Name().c_str());
#endif
}

// Existence check that never routes the name through the narrow CRT, so it
// cannot be fooled by the same encoding bug the test is about.
bool ExistsByWidePath() {
#ifdef _WIN32
    return ::GetFileAttributesW(WideName().c_str()) != INVALID_FILE_ATTRIBUTES;
#else
    struct stat st;
    return ::stat(Utf8Name().c_str(), &st) == 0;
#endif
}

// Create the fixture through the wide API on Windows, so the file on disk
// really carries the non-ASCII name regardless of the active code page.
bool CreateFixtureByWidePath() {
#ifdef _WIN32
    const int fd = ::_wopen(WideName().c_str(),
                            _O_WRONLY | _O_CREAT | _O_TRUNC | _O_BINARY,
                            _S_IREAD | _S_IWRITE);
#else
    const int fd =
        ::open(Utf8Name().c_str(), O_WRONLY | O_CREAT | O_TRUNC, 0666);
#endif
    if (fd < 0) {
        return false;
    }
    const std::string& content = MinimalTsFile();
    const int written = static_cast<int>(
        ::write(fd, content.data(), static_cast<unsigned>(content.size())));
#ifdef _WIN32
    ::_close(fd);
#else
    ::close(fd);
#endif
    return written == static_cast<int>(content.size());
}

bool MinimalTsFileIsUnchanged() {
    storage::ReadFile read_file;
    std::string buf(MinimalTsFile().size(), '\0');
    int32_t read_len = 0;
    const bool opened = read_file.open(Utf8Name()) == E_OK;
    const bool read_ok =
        opened &&
        read_file.file_size() == static_cast<int64_t>(MinimalTsFile().size()) &&
        read_file.read(0, &buf[0], static_cast<int32_t>(buf.size()),
                       read_len) == E_OK &&
        read_len == static_cast<int32_t>(buf.size()) && buf == MinimalTsFile();
    read_file.close();
    return read_ok;
}

class Utf8PathTest : public ::testing::Test {
   protected:
    void SetUp() override { RemoveTestFiles(); }
    void TearDown() override { RemoveTestFiles(); }
};

}  // namespace

// WriteFile must create the file under the UTF-8 name it was given. On Windows
// the narrow ::open() interprets the bytes in the active code page, so the file
// lands under a mojibake name (or not at all) and the wide-path lookup fails.
TEST_F(Utf8PathTest, WriteFileCreatesUtf8Path) {
    storage::WriteFile write_file;
    ASSERT_EQ(write_file.create(Utf8Name(), O_WRONLY | O_CREAT | O_TRUNC, 0666),
              E_OK);
    ASSERT_TRUE(write_file.file_opened());
    const std::string& content = MinimalTsFile();
    ASSERT_EQ(
        write_file.write(content.data(), static_cast<uint32_t>(content.size())),
        E_OK);
    ASSERT_EQ(write_file.close(), E_OK);

    EXPECT_TRUE(ExistsByWidePath())
        << "the file was not created under the UTF-8 path that was requested";
}

TEST_F(Utf8PathTest, ExistingUtf8PathIsRejectedByTsFileWriter) {
    ASSERT_TRUE(CreateFixtureByWidePath());

    storage::TsFileWriter writer;
    int flags = O_WRONLY | O_CREAT | O_TRUNC;
#ifdef _WIN32
    flags |= O_BINARY;
#endif
    EXPECT_EQ(writer.open(Utf8Name(), flags, 0666), E_ALREADY_EXIST);
    EXPECT_TRUE(MinimalTsFileIsUnchanged());
}

TEST_F(Utf8PathTest, ExistingUtf8PathIsRejectedByCWrapper) {
    ASSERT_TRUE(CreateFixtureByWidePath());

    int32_t error_code = E_OK;
    CWriteFile file = write_file_new(Utf8Name().c_str(), &error_code);
    EXPECT_EQ(file, nullptr);
    EXPECT_EQ(error_code, E_ALREADY_EXIST);
    if (file != nullptr) {
        free_write_file(&file);
    }
    EXPECT_TRUE(MinimalTsFileIsUnchanged());
}

// ReadFile must find a file that exists on disk under a non-ASCII name.
TEST_F(Utf8PathTest, ReadFileOpensUtf8Path) {
    ASSERT_TRUE(CreateFixtureByWidePath());
    ASSERT_TRUE(ExistsByWidePath());

    storage::ReadFile read_file;
    EXPECT_EQ(read_file.open(Utf8Name()), E_OK)
        << "an existing file with a non-ASCII name could not be opened";
    EXPECT_TRUE(read_file.is_opened());
    read_file.close();
}

// Round trip through both classes: what WriteFile wrote, ReadFile must read.
// The wide-path check matters even though the round trip alone would succeed
// while both sides are equally broken -- a consistently mangled name still
// round trips, so only the on-disk name proves the bytes were honoured.
TEST_F(Utf8PathTest, Utf8PathRoundTripsBetweenWriteAndRead) {
    storage::WriteFile write_file;
    ASSERT_EQ(write_file.create(Utf8Name(), O_WRONLY | O_CREAT | O_TRUNC, 0666),
              E_OK);
    const std::string& content = MinimalTsFile();
    ASSERT_EQ(
        write_file.write(content.data(), static_cast<uint32_t>(content.size())),
        E_OK);
    ASSERT_EQ(write_file.close(), E_OK);

    ASSERT_TRUE(ExistsByWidePath())
        << "the round trip used a name that is not the requested UTF-8 path";

    storage::ReadFile read_file;
    ASSERT_EQ(read_file.open(Utf8Name()), E_OK);
    EXPECT_EQ(read_file.file_size(), static_cast<int64_t>(content.size()));

    std::string buf(content.size(), '\0');
    int32_t read_len = 0;
    ASSERT_EQ(
        read_file.read(0, &buf[0], static_cast<int32_t>(buf.size()), read_len),
        E_OK);
    EXPECT_EQ(read_len, static_cast<int32_t>(content.size()));
    EXPECT_EQ(buf, content);
    read_file.close();
}

// The third caller of open_utf8() is the self-check reader inside
// RestorableTsFileIOWriter. Given a complete file under a non-ASCII name, the
// self check must recognise it as complete. When the name is mangled instead,
// the writer creates an empty file under the wrong name and reports a crashed
// file that may be written from scratch -- which would silently discard data.
TEST_F(Utf8PathTest, RestorableWriterSelfChecksUtf8Path) {
    ASSERT_TRUE(CreateFixtureByWidePath());

    storage::RestorableTsFileIOWriter writer;
    ASSERT_EQ(writer.open(Utf8Name(), true), E_OK);
    EXPECT_EQ(writer.get_truncated_size(), storage::TSFILE_CHECK_COMPLETE)
        << "the self check did not see the existing complete file";
    EXPECT_FALSE(writer.has_crashed());
    EXPECT_FALSE(writer.can_write());
    writer.close();
}

#ifdef _WIN32
// Rejection paths of the conversion helper. These are Windows-only: the POSIX
// branch hands the bytes to ::open() unchanged, where a path holding a NUL
// would silently be truncated at it rather than rejected.
TEST_F(Utf8PathTest, OpenUtf8RejectsInvalidPaths) {
    errno = 0;
    EXPECT_EQ(storage::file_internal::open_utf8("", O_RDONLY), -1);
    EXPECT_EQ(errno, ENOENT);

    std::string embedded_nul("a\0b.tsfile", 10);
    errno = 0;
    EXPECT_EQ(storage::file_internal::open_utf8(embedded_nul, O_RDONLY), -1);
    EXPECT_EQ(errno, EINVAL);

    // 0xFF 0xFE is not a valid UTF-8 sequence, so the conversion must fail
    // rather than fall back to a lossy interpretation.
    errno = 0;
    EXPECT_EQ(
        storage::file_internal::open_utf8("\xFF\xFE_bad.tsfile", O_RDONLY), -1);
    EXPECT_EQ(errno, EINVAL);
}
#endif
