/*
 * Unit tests for SHA512 hash implementation:
 * - Known NIST test vectors
 * - Empty input
 * - Consistency (same input → same output)
 * - Large input
 */
#include <gtest/gtest.h>
#include <string>
#include <cstring>

#include "hash.h"
#include "hash/sha512.h"

using namespace authdb;

TEST(SHA512Test, EmptyString) {
    sha512 hasher;
    std::string out;
    hasher.hash("", out);
    // SHA-512("") = cf83e1357eefb8bd...
    EXPECT_EQ(out.substr(0, 8), "cf83e135");
    EXPECT_EQ(out.size(), 128u); // 64 bytes = 128 hex chars
}

TEST(SHA512Test, KnownVectorABC) {
    sha512 hasher;
    std::string out;
    hasher.hash("abc", out);
    // NIST SHA-512("abc") starts with ddaf35a193617aba...
    EXPECT_EQ(out.substr(0, 16), "ddaf35a193617aba");
}

TEST(SHA512Test, Consistency) {
    sha512 h1, h2;
    std::string out1, out2;
    h1.hash("test input data", out1);
    h2.hash("test input data", out2);
    EXPECT_EQ(out1, out2);
}

TEST(SHA512Test, DifferentInputsDifferentOutput) {
    sha512 h1, h2;
    std::string out1, out2;
    h1.hash("input_a", out1);
    h2.hash("input_b", out2);
    EXPECT_NE(out1, out2);
}

TEST(SHA512Test, LargeInput) {
    sha512 hasher;
    std::string bigInput(10000, 'A');
    std::string out;
    hasher.hash(bigInput, out);
    EXPECT_EQ(out.size(), 128u);
}

TEST(SHA512Test, BinaryLikeInput) {
    sha512 hasher;
    std::string input;
    for (int i = 0; i < 256; ++i)
        input += static_cast<char>(i);
    std::string out;
    hasher.hash(input, out);
    EXPECT_EQ(out.size(), 128u);
}

// ── Hash facade ──

TEST(HashTest, FacadeProducesSameAsRaw) {
    Hash facade;
    sha512 raw;
    std::string out_facade, out_raw;
    facade.hash("hello", out_facade);
    raw.hash("hello", out_raw);
    EXPECT_EQ(out_facade, out_raw);
}
