/* SPDX-License-Identifier: GPL-2.0-only */

#include <ppm/manifest.h>

#include <stdio.h>
#include <string.h>

#define CHECK(expr) do {                                            \
    if (!(expr)) {                                                  \
        fprintf(stderr, "FAIL: %s:%d: %s\n", __FILE__, __LINE__, #expr); \
        return 1;                                                   \
    }                                                               \
} while (0)

static const char MINIMAL[] =
    "[package]\n"
    "name = \"hello\"\n"
    "version = \"0.1.0\"\n";

static const char FULL[] =
    "[package]\n"
    "name    = \"hello\"\n"
    "version = \"1.2.3-rc.1\"\n"
    "summary = \"Greets the world\"\n"
    "license = \"GPL-2.0-only\"\n"
    "authors = [\"Alice <a@example.org>\", \"Bob\"]\n"
    "homepage = \"https://example.org\"\n"
    "\n"
    "[source]\n"
    "url  = \"https://example.org/hello-1.2.3.tar.zst\"\n"
    "hash = \"sha512:cf83e1357eefb8bdf1542850d66d8007d620e4050b5715dc83f4a921d36ce9ce47d0d13c5d85f2b0ff8318d2877eec2f63b931bd47417a81a538327af927da3e\"\n"
    "\n"
    "[dependencies]\n"
    "libfoo = \"^1.0\"\n"
    "libbar = \">=2.0\"\n"
    "\n"
    "[build-dependencies]\n"
    "cmake = \"^3.20\"\n";

static const char NO_PACKAGE[] = "[whatever]\nname = \"x\"\n";

static const char BAD_NAME[] =
    "[package]\n"
    "name = \"-bad\"\n"
    "version = \"1.0.0\"\n";

static const char BAD_VERSION[] =
    "[package]\n"
    "name = \"x\"\n"
    "version = \"not-semver\"\n";

static const char BAD_HASH[] =
    "[package]\n"
    "name = \"x\"\n"
    "version = \"1.0.0\"\n"
    "[source]\n"
    "url = \"https://e.org/x.tar.zst\"\n"
    "hash = \"md5:abc\"\n";

int main(void) {
    /* Minimal manifest: valid in LOCAL mode, invalid in PUBLISHED mode. */
    ppm_manifest_t *m = NULL;
    CHECK(ppm_manifest_parse(MINIMAL, sizeof(MINIMAL) - 1, &m) == PPM_OK);
    CHECK(strcmp(m->name, "hello") == 0);
    CHECK(m->version.major == 0 && m->version.minor == 1 && m->version.patch == 0);
    CHECK(ppm_manifest_validate(m, PPM_MANIFEST_LOCAL)     == PPM_OK);
    CHECK(ppm_manifest_validate(m, PPM_MANIFEST_PUBLISHED) == PPM_ERR_PARSE);
    ppm_manifest_free(m);

    /* Full manifest round-trips every field. */
    m = NULL;
    CHECK(ppm_manifest_parse(FULL, sizeof(FULL) - 1, &m) == PPM_OK);
    CHECK(strcmp(m->name, "hello") == 0);
    CHECK(m->version.major == 1 && m->version.minor == 2 && m->version.patch == 3);
    CHECK(m->version.pre && strcmp(m->version.pre, "rc.1") == 0);
    CHECK(strcmp(m->summary, "Greets the world") == 0);
    CHECK(strcmp(m->license, "GPL-2.0-only") == 0);
    CHECK(strcmp(m->homepage, "https://example.org") == 0);
    CHECK(m->authors && m->authors[0] && m->authors[1] && !m->authors[2]);
    CHECK(strstr(m->source.url, "hello-1.2.3.tar.zst") != NULL);
    /* hash[0] = 0xcf */
    CHECK(m->source.hash.bytes[0] == 0xcf);
    CHECK(m->deps_len == 2);
    CHECK(strcmp(m->deps[0].name, "libfoo") == 0);
    CHECK(strcmp(m->deps[0].spec, "^1.0")   == 0);
    CHECK(m->build_deps_len == 1);
    CHECK(strcmp(m->build_deps[0].name, "cmake") == 0);
    CHECK(ppm_manifest_validate(m, PPM_MANIFEST_PUBLISHED) == PPM_OK);
    ppm_manifest_free(m);

    /* Error paths. */
    m = NULL;
    CHECK(ppm_manifest_parse(NO_PACKAGE, sizeof(NO_PACKAGE) - 1, &m) == PPM_ERR_PARSE);

    m = NULL;
    CHECK(ppm_manifest_parse(BAD_NAME, sizeof(BAD_NAME) - 1, &m) == PPM_OK);
    CHECK(ppm_manifest_validate(m, PPM_MANIFEST_LOCAL) == PPM_ERR_PARSE);
    ppm_manifest_free(m);

    m = NULL;
    CHECK(ppm_manifest_parse(BAD_VERSION, sizeof(BAD_VERSION) - 1, &m) == PPM_ERR_PARSE);

    m = NULL;
    CHECK(ppm_manifest_parse(BAD_HASH, sizeof(BAD_HASH) - 1, &m) == PPM_ERR_PARSE);

    printf("ok\n");
    return 0;
}
