/* Goxel 3D voxels editor
 *
 * copyright (c) 2018 Guillaume Chereau <guillaume@noctua-software.com>
 *
 * Goxel is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License as published by the Free Software
 * Foundation, either version 3 of the License, or (at your option) any later
 * version.

 * Goxel is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 * FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
 * details.

 * You should have received a copy of the GNU General Public License along with
 * goxel.  If not, see <http://www.gnu.org/licenses/>.
 */

#include "goxel.h"

#include "utils/b64.h"

#define TEST(cond) \
    do { \
        if (!(cond)) { \
            LOG_E("Test fail: %s (%s: %d)", __func__, __FILE__, __LINE__); \
            exit(-1); \
        } \
    } while(0)

static void test_file(const char *b64_data, uint32_t crc32)
{
    FILE *file;
    size_t data_size;
    uint8_t *data;
    if (DEFINED(WIN32)) return; // Don't test on Windows for the moment!
    data = calloc(b64_decode(b64_data, NULL), 1);
    data_size = b64_decode(b64_data, data);
    file = fopen("/tmp/goxel_test.gox", "w");
    fwrite(data, data_size, 1, file);
    fclose(file);
    free(data);
    action_exec2("import", "p", "/tmp/goxel_test.gox");
    TEST(mesh_crc32(goxel.image->active_layer->mesh) == crc32);
    image_delete(goxel.image);
    goxel.image = image_new();
}

static void test_load_file_v2(void)
{
    // Load a simple file.
    const char *b64_data =
        "R09YIAIAAABJTUcgAAAAAAAAAABCTDE2LAEAAIlQTkcNChoKAAAADUlIRFIA"
        "AABAAAAAQAgGAAAAqmlx3gAAAPNJREFUeF5j/A8EDAwMjAwUgO+MjP85//8n"
        "14z/A2k/E8MwABQEPgMjJAEwjFjAxDDCAROjyvf/lIYB43cVss0YaPuHRQr4"
        "z3mH7EJ8tAwY8WXAaACM9FpgNAWMpoCRHQKjLcHRMmC0DBgtA0Z0CIwWgqOF"
        "4GghOFoIjhaCIzkERmuB0VpgtBYYrQVGa4HRWmAEh8BoNThaDY5Wg6PV4Gg1"
        "OFoNjlaDIzcERtsBo+2A0XbAaDtgtB0w2g4YbQeMtgNGbAiMNoRGG0KjDaHR"
        "htBoQ2i0ITTaEBptCI02hEZqCIy2BEdbgqMtwdGW4GhLcCSHAACDDx/OAZLa"
        "WgAAAABJRU5ErkJgggAAAABMQVlSmgAAAAEAAAAAAAAAAAAAAAAAAAAAAAAA"
        "AAAAAAQAAABuYW1lCgAAAGJhY2tncm91bmQDAAAAbWF0QAAAAAAAgD8AAAAA"
        "AAAAAAAAAAAAAAAAAACAPwAAAAAAAAAAAAAAAAAAAAAAAIA/AAAAAAAAAAAA"
        "AAAAAAAAAAAAgD8CAAAAaWQEAAAAAQAAAAcAAABiYXNlX2lkBAAAAAAAAAAA"
        "AAAA";
    test_file(b64_data, 0xc7c4c9ff);
}

static void test_load_file_v1_with_preview(void)
{
    // Load a simple file in v1 of goxel format, with embedded preview,
    // as generated by the mobile version 0.7.1.
    const char *b64_data =
        "R09YIAEAAABJTUcgAAAAAAAAAABQUkVWPAUAAIlQTkcNChoKAAAADUlIRFIA"
        "AACAAAAAgAgGAAAAwz5hywAABQNJREFUeF5jGAWjITAaAqMhMBoCoyEwGgKj"
        "ITAaAqMhMBoCoyEwGgKjITAaAqMhMBoCoyEwGgKjITAaAqMhMBoCoyEwGgKj"
        "ITAaAqMhMBoCoyEwGgKjITAaAqMhMBoCoyEwGgKjITAaAqMhMBoCoyEwGgKj"
        "ITAaAqMhMBoCoyEwGgKjITAaAqMhMBoCoyEwGgKjITAaAqMhMBoCoyEwGgKj"
        "ITAaAqMhMBoCoyEwGgKjITAaAqMhMBoCoyEwGgKjITAaAqMhMBoCoyEwGgKj"
        "ITAaAqMhMBoCoyEwGgKjITAaAqMhMBoCoyEwGgKjITAaAqMhMBoCoyEwGgKj"
        "ITAaAqMhMDhCQIeNzT6Yi6t+ND5GYAhU8fPvP6Cl9R+EuyQl9yszMNgPx2Bg"
        "Hk3dqCGgxsRkP1dO7oG2sLACI1AKhGU4ORU8+PgSvv38yXD99++DwynMGEcT"
        "ACIEirm59/vJyztghAkjIphOvHt3YObz5w33GBiGRUIYLQGAsa0ELN5nAXO9"
        "kZiYAjjyQRGOjJFSBKg08BxGpcGITwAhvLz1TYqKC3g5ORkYYJGOpViEVQcg"
        "moWFhcFCUNBBg4XF4d6XLw/eMzA8HKolKdNIrwL+//7d8O7vX5RgQI5sGBuu"
        "AJpIOIAJhvHfPwdgADoM5TAc8Qng2Y8fDH137jAcef2agZmZmQGjUYSlOvj6"
        "5w/Dgrt3Gfa+fDnk8w8LwygAh8CWV68Yrn//zhAqLs4gyMGBNVQYgYnh2b9/"
        "DAtv3GD4O0zCbcT3AiwZGP4jxyWoURQhL8+gx8sLaQ9CJVnZ2BjWPXzIcPHt"
        "W5SoP83A4PBuCPcIRnwVwGdpiRKhoJy9FBjRix4/ZvgBbRt8BlYNfRcuYEQ+"
        "j74+w7sh3h0c8SWAj48PuAT4ePw4wx+03A2qCJxlZBgOP3mCkkjYgNUEj4EB"
        "A5uEBMPChQuHdBiOtgGgUcsPLAl+AxPAJ2BCgMX2DyBjDzDy2ZGiHxT5Qh4e"
        "DMMFjCYApJhkFRZmAFUJ327dwigNQMqE3N3BuZ5hGIERPxD09u3bA7Kysgmw"
        "OGXm4mLgkJUFc0FVAiuQxQks8vltbFAi//fv3wy7d+92+Pr168OhnB5G5wKg"
        "sWdpablfWFgYZVAHVCWwff7MIGRsjBLHL168OHDmzJkGYOIZ8vMBo3MB0Kh9"
        "8uTJQhATORGASgNeYGkAGiCCpYB79+4d2Ldvn+P3798fDoeaYDQBIMUiKEeD"
        "qgQuLi4FEAZJcQAHhUAJAFTk79q1y+H69euNDMMIjFYBOCITViXw8fExvHz5"
        "8sDevXsdGUbByAoBYHVgr6mpObokbDThj4bAaAiMhsBoCIyGwGgIjIbAaAiM"
        "hsBoCIyGwGgIjIbAaAiMhsBoCIyGwGgIjIbAaAiMhsBoCIyGwGgIjIbAaAiM"
        "hsBoCIyGwGgIjIbAaAiMhsBoCIyGwGgIjIbAaAiMhsBoCIyGwGgIjIbAaAiM"
        "hsBoCIyGwGgIjIbAaAiMhsBoCIyGwGgIjIbAaAiMhsBoCIyGwGgIjIbAaAiM"
        "hsBoCIyGwGgIjIbAaAiMhsBoCIyGwGgIjIbAaAiMhsBoCIyGwGgIjIbAaAiM"
        "hsBoCIyGwGgIjIbAaAiMhsBoCIyGwGgIjIbAaAiMhsBoCIyGwGgIjIbAaAiM"
        "hsBoCIyGwGgIjIbAaAiMhsBoCIyGwGgIjIbAaAiMhsBoCIyGwGgIkBgCADB4"
        "2BRvDISwAAAAAElFTkSuQmCCAAAAAEJMMTb1AAAAiVBORw0KGgoAAAANSUhE"
        "UgAAAEAAAABACAYAAACqaXHeAAAAvElEQVR4XmMYBaMhMBoCoyEwGgKjITAa"
        "AqMhMBoCoyEwGgKjITAaAqMhMBoCoyEwGgKjITAaAqMhMBoCoyEwGgKjITAa"
        "AqMhMBoCoyEwGgKjITAaAqMhMBoCIz0E/kMBueFAqf7RFDgaAqMhMLAhsI+B"
        "4T8Ik+sKSvWPxv9oCIyGwGgIjIbAaAiMhsBoCIyGwGgIjIbAaAiMhsBoCIyG"
        "wGgIjIbAaAiMhsBoCIyGwGgIjIbAaAiMhgCVQgAAwAEW5Yj9s+cAAAAASUVO"
        "RK5CYIIAAAAATEFZUpoAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAA"
        "bmFtZQoAAABiYWNrZ3JvdW5kAwAAAG1hdEAAAAAAAIA/AAAAAAAAAAAAAAAA"
        "AAAAAAAAgD8AAAAAAAAAAAAAAAAAAAAAAACAPwAAAAAAAAAAAAAAAAAAAAAA"
        "AIA/AgAAAGlkBAAAAAEAAAAHAAAAYmFzZV9pZAQAAAAAAAAAAAAAAA==";
    test_file(b64_data, 0xb5e8d973);
}

static void test_load_corrupt(void)
{
    FILE *file;
    if (DEFINED(WIN32)) return; // Don't test on Windows for the moment!
    file = fopen("/tmp/goxel_test.gox", "w");
    fclose(file);
    action_exec2("import", "p", "/tmp/goxel_test.gox");
}

static void test_meta(void)
{
    val_t val;
    val = obj_get_attr(&goxel.obj, "hide_box");
    assert(val.type == TYPE_BOOL);
    val_free(val);

    val = obj_get_attr(&goxel.obj, "does not exist");
    assert(val.type == TYPE_ERROR);
    val_free(val);

    val = obj_get_attr(&goxel.obj, "tool");
    val_free(val);
}

void tests_run(void)
{
    test_load_file_v2();
    test_load_file_v1_with_preview();
    test_load_corrupt();
    test_meta();
}
