#include <cstdlib>
#include <cstdio>

#include "TestDesc.h"
#if defined(EMBEDDED)
#include "FPGA.h"
#else
#include "Semihosting.h"
#endif
#include "IORunner.h"
#include "ArrayMemory.h"
using namespace std;

#ifdef BENCHMARK
#define MEMSIZE 300000
#else
#define MEMSIZE 230000
#endif

// Dummy (will be generated by python scripts)
// char* array describing the tests and the input patterns.
// Reference patterns are ignored in this case.
#include "TestDrive.h"

extern "C" void testmain_hook      (void) __attribute__ ((weak));

void testmain_hook(void)
{

}

int testmain(const char *patterns)
{
    testmain_hook();
    char *memoryBuf=NULL;

    memoryBuf = (char*)malloc(MEMSIZE);
    if (memoryBuf !=NULL)
    {
        try
        {
           // Choice of a memory manager.
           // Here we choose the Array one (only implemented one)
           Client::ArrayMemory memory(memoryBuf,MEMSIZE);

           // There is also possibility of using "FPGA" io
           #if defined(EMBEDDED)
              Client::FPGA io(testDesc,patterns);
           #else
              Client::Semihosting io("../TestDesc.txt","../Patterns","../Output","../Parameters");
           #endif


           // Pattern Manager making the link between IO and Memory
           Client::PatternMgr mgr(&io,&memory);

    
           // A Runner to run the test.
           // An IO runner is driven by some IO
           // In future one may have a client/server runner driven
           // by a server running on a host.
           #if defined(EMBEDDED)
           Client::IORunner runner(&io,&mgr,Testing::kTestOnly);
           //Client::IORunner runner(&io,&mgr,Testing::kTestAndDump);
           #else
           // Works also in embedded but slower since data is dumped
           Client::IORunner runner(&io,&mgr,Testing::kTestAndDump);
           #endif

    
           // Root object containing all the tests
           Root d(1);

           // Runner applied to the tree of tests
           d.accept(&runner);
    
        }
        catch(...)
        {
            printf("Exception\n");
        }
        
        
        free(memoryBuf);
    }
    else
    {
      printf("NOT ENOUGH MEMORY\n");
    }

    /* code */
    return 0;
}
