/*
   This file is part of Fennix Kernel.

   Fennix Kernel 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.

   Fennix Kernel 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 Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
*/

#ifdef DEBUG

#include <types.h>
#include <memory.hpp>
#include <convert.h>

extern bool EnableExternalMemoryTracer;
extern bool DebuggerIsAttached;

__constructor void TestMemoryOperations()
{
    if (EnableExternalMemoryTracer || DebuggerIsAttached)
    {
        debug("The test is disabled when the external memory tracer or a debugger is enabled.");
        return;
    }

    int arr1[5] = {1, 2, 3, 4, 5};
    int arr2[5] = {0, 0, 0, 0, 0};
    char str1[] = "Hello";
    char str2[] = "World";

    memcpy_unsafe(arr2, arr1, sizeof(arr1));
    debug("memcpy: arr2[0]=%d, arr2[1]=%d, arr2[2]=%d, arr2[3]=%d, arr2[4]=%d",
          arr2[0], arr2[1], arr2[2], arr2[3], arr2[4]);
    if (memcmp(arr1, arr2, sizeof(arr1)) != 0)
    {
        error("memcpy failed!");
        inf_loop;
    }

    memset_unsafe(arr2, 0, sizeof(arr2));
    debug("memset: arr2[0]=%d, arr2[1]=%d, arr2[2]=%d, arr2[3]=%d, arr2[4]=%d",
          arr2[0], arr2[1], arr2[2], arr2[3], arr2[4]);
    if (memcmp(arr1, arr2, sizeof(arr1)) == 0)
    {
        error("memset failed!");
        inf_loop;
    }

    memmove_unsafe(str1 + 3, str1, strlen(str1) + 1);
    debug("memmove: str1=%s", str1);
    if (strcmp(str1, "HelHello") != 0)
    {
        error("memmove failed!");
        inf_loop;
    }

    char carr[1024];
    char carrFull[1024];
    char carrTo[16];

    for (size_t i = 0; i < 512; i++)
    {
        for (size_t i = 0; i < 16; i++)
            carrTo[i] = 'a';

        for (size_t i = 0; i < 1024; i += 16)
            memcpy_unsafe(carr + i, carrTo, 16);

        for (size_t i = 0; i < 1024; i++)
        {
            if (carr[i] != 'a')
            {
                error("memcpy failed!");
                while (1)
                    ;
            }
        }

        for (size_t i = 0; i < 1024; i++)
            carrFull[i] = 'b';

        memcpy_unsafe(carr, carrFull, 1024);

        for (size_t i = 0; i < 1024; i++)
        {
            if (carr[i] != 'b')
            {
                error("memcpy failed!");
                while (1)
                    ;
            }
        }
    }

    for (size_t i = 0; i < 512; i++)
    {
        for (size_t i = 0; i < 1024; i += 16)
            memset_unsafe(carr + i, 'c', 16);

        for (size_t i = 0; i < 1024; i++)
        {
            if (carr[i] != 'c')
            {
                error("memcpy failed!");
                while (1)
                    ;
            }
        }
    }

    for (size_t i = 0; i < 512; i++)
    {
        memset_unsafe(carr, 'd', 1024);

        for (size_t i = 0; i < 1024; i++)
        {
            if (carr[i] != 'd')
            {
                error("memset failed!");
                while (1)
                    ;
            }
        }
    }

    debug("Memory operations test passed");
}

#endif