view tests/scripttest.cpp @ 0:a4671277546c tip

created the repository for the thymian project
author ferencd
date Tue, 17 Aug 2021 11:19:54 +0200
parents
children
line wrap: on
line source
#include "tests.h"
#include "nbci.h"
#include "gtest/gtest.h"

#include "compiler.h"
#include "nap_runtime.h"

TEST(Simple, Printing)
{
    SCRIPT_START
    "                                    \
            print(\"Hello World\n\");    \
    "
    SCRIPT_END

    SCRIPT_SHUTDOWN
    (void)found_indicator;

}

TEST(Assembly, PushPop)
{
  nap_runtime* runtime = nap_runtime_create("$");
  ASSERT_FALSE(runtime == NULL);
  int found_indicator;
  nap_bytecode_chunk* bytecode = nap_runtime_compile(runtime,
  "                        \
  int a;                   \
  asm                      \
  {                        \
       push 23;            \
       pop global.a;       \
  }                        \
  "
  SCRIPT_END

  ASSERT_EQ(23, VAR_INT(a));

  SCRIPT_SHUTDOWN
}

TEST(Definitions, CodeBlocksWithScope)
{
    SCRIPT_START
    "                                    \
            int a = 1;                   \
            {  int c = 3;int a = 2;}     \
            int b = 2;                   \
    "
    SCRIPT_END
    ASSERT_TRUE( 1 == VAR_INT(a));
    ASSERT_TRUE( 2 == VAR_INT(b));

    SCRIPT_SHUTDOWN
}

TEST(Floats, BasicRealOperations)
{
    SCRIPT_START
    "                                    \
        real a = 5.6;                    \
        real b = a * 10;                 \
    "
    SCRIPT_END
	double _b = (double)VAR_REAL(b);
    ASSERT_DOUBLE_EQ((double)56.0, _b);

    SCRIPT_SHUTDOWN
}

TEST(Operations, UnaryMathOperations)
{
    SCRIPT_START
    "                                 \
        int a = 5;                    \
        int b = -5;                   \
        int c = +b;                   \
        int d = -a;                   \
        int e = 3 - (-2);             \
    "
    SCRIPT_END

    ASSERT_EQ(5, VAR_INT(c));
    ASSERT_EQ(-5, VAR_INT(d));
    ASSERT_EQ(5, VAR_INT(e));

    SCRIPT_SHUTDOWN

}

TEST(Operations, BasicIntVariableOperations)
{

    SCRIPT_START
    "                               \
        int a;                      \
        int b;                      \
        int a_plus_b;               \
        int a_minus_b;              \
        int a_mul_b;                \
        int a_div_b;                \
        int a_mod_b;                \
        a = 9;                      \
        b = 3;                      \
        a_plus_b = a + b;           \
        a_minus_b = a - b;          \
        a_mul_b = a * b;            \
        a_div_b = a / b;            \
        a_mod_b = a % b;            \
    "
    SCRIPT_END

    ASSERT_TRUE( 9 == VAR_INT(a));
    ASSERT_TRUE( 3 == VAR_INT(b));
    ASSERT_TRUE(12 == VAR_INT(a_plus_b));
    ASSERT_TRUE( 6 == VAR_INT(a_minus_b));
    ASSERT_TRUE( 3 == VAR_INT(a_div_b));
    ASSERT_TRUE(27 == VAR_INT(a_mul_b));
    ASSERT_TRUE( 0 == VAR_INT(a_mod_b));

    SCRIPT_SHUTDOWN
}

TEST(Operations, BasicBitwiseOperations)
{

    SCRIPT_START
    "                                    \
            int a1 = 1;                  \
            int a2 = 2;                  \
            int a3 = 3;                  \
            int a4 = 1;                  \
            int a5 = 2;                  \
            int a6 = 2;                  \
            int b1 = a1 << 1;            \
            int b2 = a2 >> 1;            \
            int b3 = a3 &  1;            \
            int b4 = a4 |  2;            \
            int b5 = a5 ^  1;            \
            int b6 = ~a6;                \
    "
    SCRIPT_END

    ASSERT_TRUE( 2 == VAR_INT(b1));
    ASSERT_TRUE( 1 == VAR_INT(b2));
    ASSERT_TRUE( 1 == VAR_INT(b3));
    ASSERT_TRUE( 3 == VAR_INT(b4));
    ASSERT_TRUE( 3 == VAR_INT(b5));
    ASSERT_TRUE(-3 == VAR_INT(b6));

    SCRIPT_SHUTDOWN
}


TEST(Operations, BasicStringVariableOperations1)
{

    SCRIPT_START
    "                               \
        string a = \"AA\";          \
        string b = \"BB\";          \
        string a_plus_b;            \
        a_plus_b = a + b;           \
    "
    SCRIPT_END

    SCRIPT_ASSERT_STREQ("AABB", a_plus_b);

    SCRIPT_SHUTDOWN
}

TEST(Operations, BasicStringVariableOperations2)
{

    SCRIPT_START
    "                               \
        string a = \"A\";           \
        string b = a + \"B\";       \
    "
    SCRIPT_END

    SCRIPT_ASSERT_STREQ("AB", b);

    SCRIPT_SHUTDOWN
}

TEST(Operations, BasicStringVariableOperations4)
{

    SCRIPT_START
    "                                      \
        string sa = \"A\";                 \
        string sb ;                        \
        asm                                \
        {                                  \
        mov reg string(0), global.sa       \
        mov reg string(1), \"B\"           \
        add reg string(0), reg string(1)   \
        mov global.sb, reg string(0)       \
        }                                  \
    "
    SCRIPT_END

    SCRIPT_ASSERT_STREQ("AB", sb);

    SCRIPT_SHUTDOWN
}

/* Define a string variable, copy out one character from it into an int register
   see that the conversion succeeded.*/
TEST(Operations, BasicStringVariableOperations5)
{

    SCRIPT_START
    "                                        \
        string sa = \"A123B\";               \
        int ib = 9;                          \
        asm                                  \
        {                                    \
        mov reg idx(0), 1                    \
        mov reg int(0), @#ccidx(global.sa, 1)\
        mov global.ib, reg int (0)           \
        }                                    \
    "
    SCRIPT_END

    ASSERT_EQ(1, VAR_INT(ib));

    SCRIPT_SHUTDOWN
}

/* Define a string variable, copy out a substring from it into an int register
   see that the conversion succeeded.*/
TEST(Operations, BasicStringVariableOperations6)
{

    SCRIPT_START
    "                                        \
        string sa = \"A123B\";               \
        int ib = 9;                          \
        asm                                  \
        {                                    \
        mov reg idx(0), 1                    \
        mov reg idx(1), 3                    \
        mov reg int(0), @#ccidx(global.sa, 2)\
        mov global.ib, reg int (0)           \
        }                                    \
    "
    SCRIPT_END

    ASSERT_EQ(123, VAR_INT(ib));

    SCRIPT_SHUTDOWN
}


TEST(Operations, BasicImmediateOperations)
{
    SCRIPT_START
    "                               \
        int a_plus_b;               \
        int a_minus_b;              \
        int a_mul_b;                \
        int a_div_b;                \
        int a_mod_b;                \
        a_plus_b = 9 + 3;           \
        a_minus_b = 9 - 3;          \
        a_mul_b = 9 * 3;            \
        a_div_b = 9 / 3;            \
        a_mod_b = 9 % 3;            \
    "
    SCRIPT_END

    ASSERT_TRUE(12 == VAR_INT(a_plus_b));
    ASSERT_TRUE( 6 == VAR_INT(a_minus_b));
    ASSERT_TRUE( 3 == VAR_INT(a_div_b));
    ASSERT_TRUE(27 == VAR_INT(a_mul_b));
    ASSERT_TRUE( 0 == VAR_INT(a_mod_b));

    SCRIPT_SHUTDOWN
}

TEST(Definitions, InvalidVariableName)
{
    nap_runtime* runtime = nap_runtime_create(0);
    ASSERT_TRUE(runtime != NULL);
    nap_bytecode_chunk* bytecode = nap_runtime_compile(runtime,
    "              \
    int a_ plus_b; \
    "
    ,0);

    ASSERT_TRUE(bytecode == NULL);
    SCRIPT_SHUTDOWN
}

TEST(StringToIntConversion, DifferentBases)
{
    SCRIPT_START
    "                                          \
    int binary = 0;                            \
    int decimal = 0;                           \
    int zero = 1;                              \
    int hexa = 0;                              \
    int octal = 0;                             \
    asm                                        \
    {                                          \
        mov reg string 0, \"9877\"             \
        mov reg int 0, reg string 0            \
        mov global.decimal, reg int 0          \
        mov reg string 0, \"0xABCDE\"          \
        mov reg int 0, reg string 0            \
        mov global.hexa, reg int 0             \
        mov reg string 0, \"0665544\"          \
        mov reg int 0, reg string 0            \
        mov global.octal, reg int 0            \
        mov reg string 0, \"0b1001001\"        \
        mov reg int 0, reg string 0            \
        mov global.binary, reg int 0           \
        mov reg string 0, \"0\"                \
        mov reg int 0, reg string 0            \
        mov global.zero, reg int 0             \
    }                                          \
    "
    SCRIPT_END

    ASSERT_TRUE(9877   == VAR_INT(decimal));
    ASSERT_TRUE(703710 == VAR_INT(hexa));
    ASSERT_TRUE(224100 == VAR_INT(octal));
    ASSERT_TRUE(73     == VAR_INT(binary));
    ASSERT_TRUE(0      == VAR_INT(zero));

    SCRIPT_SHUTDOWN
}

TEST(Operations, PostPreIncrement)
{
    SCRIPT_START
            "               \
            int i=0;        \
            int y = i++;    \
            int z = ++i;    \
            "
    SCRIPT_END

    ASSERT_TRUE(2 == VAR_INT(i));
    ASSERT_TRUE(0 == VAR_INT(y));
    ASSERT_TRUE(2 == VAR_INT(z));

    SCRIPT_SHUTDOWN
}

TEST(Keywords, Break)
{
    SCRIPT_START
    "                             \
    int y = 1;                    \
    for(int i = 0; i< 11; i++)    \
    {                             \
      int t = y ++;               \
      if (t == 7)                 \
      {                           \
        break;                    \
      }                           \
    }                             \
    "
    SCRIPT_END
    ASSERT_EQ(8, VAR_INT(y));

    SCRIPT_SHUTDOWN
}

TEST(InvalidSyntax, PostPreIncMess)
{

    nap_runtime* runtime = nap_runtime_create(0);
    ASSERT_TRUE(runtime != NULL);
    nap_bytecode_chunk* bytecode = nap_runtime_compile(runtime,
    "                              \
     int z = 3;                    \
     int g = z++ ++;               \
    "
    ,0);

    ASSERT_TRUE(bytecode == NULL);
    SCRIPT_SHUTDOWN
}

TEST(RuntimeCompilation, SimpleCheck)
{
    SCRIPT_START
    "                                   \
    int a = 2;                          \
    int b = 3;                          \
    int c;                              \
    nap_execute(\"c = a + b\");         \
    "
    SCRIPT_END

    ASSERT_EQ(5, VAR_INT(c));

    SCRIPT_SHUTDOWN
}

TEST(RuntimeCompilation, CompoundedExpression)
{
    SCRIPT_START
    "                                   \
    int a = 2;                          \
    int b = 3;                          \
    int c;                              \
    string sa = \"c=a\";                \
    string sb = \"+b\";                 \
    nap_execute(sa + sb);               \
    "
    SCRIPT_END

    ASSERT_EQ(5, VAR_INT(c));

    SCRIPT_SHUTDOWN
}

/*
 * TESTS FOR FUNCTIONS AND THEIR ASSOCIATED BEHAVIOUR
 */

/* Define a function returning an in which takes in an int parameter. Return the
 next value of the parameter (ie: par + 1). Check in the calling code the
 value. */
TEST(Functions, SimpleFunctionCall)
{
    SCRIPT_START
    "                               \
        int func(int a)             \
        {                           \
            return a + 1;           \
        }                           \
        int a = 5;                  \
        a = func(a);                \
    "
    SCRIPT_END

    ASSERT_EQ(6, VAR_INT(a));

    SCRIPT_SHUTDOWN;
}

/* Define a function returning and int. Do not put return statements in the body.
 * Use the function, see that it returns the default return value (0).
 */
TEST(Functions, DefaultReturnValue)
{
    SCRIPT_START
    "                             \
    int func()                    \
    {                             \
    }                             \
    int z = func();               \
    "
    SCRIPT_END
    ASSERT_EQ(0, VAR_INT(z));

    SCRIPT_SHUTDOWN
}

/* Define an external function, also implement it in the test file.
 * Use the function, see that it does not fail.
 */
TEST(Functions, ExternalCalling)
{
    nap_runtime* runtime = nap_runtime_create("a");
    ASSERT_FALSE(runtime == NULL);

    int found_indicator;
    nap_bytecode_chunk* bytecode = nap_runtime_compile(runtime,    "  \
    extern void external_callee(int, int);                            \
    external_callee(1,2);                                             \
    "
    ,0);
    ASSERT_FALSE(bytecode == NULL);
    nap_runtime_execute(runtime, bytecode);
    SCRIPT_SHUTDOWN

    UNUSED(found_indicator);
}

/* Define a function with an int reference as parameter. Assign a value to
 * the parameter in the function body and see that the caller gets modified */
TEST(Functions, IntReference)
{
    SCRIPT_START
    "                             \
    void func(int& a)             \
    {                             \
        a = 6;                    \
    }                             \
    int z = 7; func(z);           \
    "
    SCRIPT_END
    ASSERT_EQ(6, VAR_INT(z));

    SCRIPT_SHUTDOWN
}

/* Define a function with an byte reference as parameter. Assign a value to
 * the parameter in the function body and see that the caller gets modified */
TEST(Functions, ByteReference)
{
    SCRIPT_START
    "                             \
    void func(byte& a)            \
    {                             \
        a = 6;                    \
    }                             \
    byte z = 7; func(z);          \
    "
    SCRIPT_END
    ASSERT_EQ(6, VAR_BYTE(z));

    SCRIPT_SHUTDOWN
}

/* Define a function with an real reference as parameter. Assign a value to
 * the parameter in the function body and see that the caller gets modified */
TEST(Functions, RealReference)
{
    SCRIPT_START
    "                             \
    void func(real& a)            \
    {                             \
        a = 6.7;                  \
    }                             \
    real z = 7.8; func(z);        \
    "
    SCRIPT_END
    double _z = (double)VAR_REAL(z);
    ASSERT_DOUBLE_EQ((double)6.7, _z);
    SCRIPT_SHUTDOWN
}

/* Define a function with a real array as parameter. Assign a value to
 * the parameter in the function body and see that the caller does not get
 * modified */
TEST(Functions, RealArray)
{
    SCRIPT_START
    "                           \
    void func(real a[])         \
    {                           \
        a[0] = 6.7;             \
    }                           \
    real z[10];                 \
    z[0] = 7.8; func(z);        \
    real b = z[0];              \
    "
    SCRIPT_END
    double _b = (double)VAR_REAL(b);
    ASSERT_DOUBLE_EQ((double)7.8, _b);
    SCRIPT_SHUTDOWN
}

/* Define a function with an int array as parameter. Assign a value to
 * the parameter in the function body and see that the caller does not get
 * modified */
TEST(Functions, IntArray)
{
    SCRIPT_START
    "                           \
    void func(int a[])          \
    {                           \
        a[0] = 6;               \
    }                           \
    int z[10];                  \
    z[0] = 8; func(z);          \
    int b = z[0];               \
    "
    SCRIPT_END
    ASSERT_EQ(8, VAR_INT(b));

    SCRIPT_SHUTDOWN
}

/* Define a function with a byte array as parameter. Assign a value to
 * the parameter in the function body and see that the caller does not get
 * modified */
TEST(Functions, ByteArray)
{
    SCRIPT_START
    "                           \
    void func(byte a[])         \
    {                           \
        a[0] = 6;               \
    }                           \
    byte z[10];                 \
    z[0] = 8; func(z);          \
    byte b = z[0];              \
    "
    SCRIPT_END
    ASSERT_EQ(8, VAR_BYTE(b));

    SCRIPT_SHUTDOWN
}

/* Define a function with a byte array reference parameter. Assign a value to
 * the parameter in the function body and see that the caller does get
 * modified */
TEST(Functions, ByteArrayReference)
{
    SCRIPT_START
    "                           \
    void func(byte& a[])        \
    {                           \
        a[0] = 6;               \
    }                           \
    byte z[10];                 \
    z[0] = 8; func(z);          \
    byte b = z[0];              \
    "
    SCRIPT_END
    ASSERT_EQ(6, VAR_BYTE(b));

    SCRIPT_SHUTDOWN
}

/* Define a function with an int array reference parameter. Assign a value to
 * the parameter in the function body and see that the caller does get
 * modified */
TEST(Functions, IntArrayReference)
{
    SCRIPT_START
    "                           \
    void func(int& a[])         \
    {                           \
        a[0] = 6;               \
    }                           \
    int z[10];                  \
    z[0] = 8; func(z);          \
    int b = z[0];               \
    "
    SCRIPT_END
    ASSERT_EQ(6, VAR_INT(b));

    SCRIPT_SHUTDOWN
}

/* Define a function with a real array as parameter. Assign a value to
 * the parameter in the function body and see that the caller does not get
 * modified */
TEST(Functions, RealArrayReference)
{
    SCRIPT_START
    "                           \
    void func(real& a[])        \
    {                           \
        a[0] = 6.7;             \
    }                           \
    real z[10];                 \
    z[0] = 7.8; func(z);        \
    real b = z[0];              \
    "
    SCRIPT_END
    double _b = (double)VAR_REAL(b);
    ASSERT_DOUBLE_EQ((double)6.7, _b);
    SCRIPT_SHUTDOWN
}

TEST(General, FibonacciAsIntArrayReference)
{
    SCRIPT_START
    "                                                \
    void fibo1(int& res[], int n)                    \
    {                                                \
       int first = 0, second = 1, next, c;           \
       int i = 0;                                    \
       for ( c = 0 ; c < n ; c++ )                   \
       {                                             \
          if ( c <= 1 )                              \
             next = c;                               \
          else                                       \
          {                                          \
             next = first + second;                  \
             first = second;                         \
             second = next;                          \
          }                                          \
          res[i++] = next;                           \
       }                                             \
    }                                                \
                                                     \
    int cnt = 20, i;                                 \
                                                     \
    int fib_it[cnt];                                 \
    fibo1(fib_it, fib_it.len());                     \
    int a = fib_it[9];                               \
    "
    SCRIPT_END
    ASSERT_EQ(34, VAR_INT(a));

    SCRIPT_SHUTDOWN
}


/*
 * Push an int, peek an int variable
 */
TEST(PushPeek, Ints)
{
    SCRIPT_START
    "                             \
            int a;                \
            asm                   \
            {                     \
                 push 23;         \
                 peek int 0 global.a; \
            }                     \
    "
    SCRIPT_END
    ASSERT_EQ(23, VAR_INT(a));

    SCRIPT_SHUTDOWN
}


NAP_EXPORTS
void external_callee(nap_int_t a, nap_int_t b)
{
    printf("%" PRINT_d " %" PRINT_d "\n", a, b);
    if(a != 1 || b != 2) FAIL();
}

TEST(FeatureTable, RegisterIntToRegisterXAndRegisterXToVariableX)
{
    SCRIPT_START
    "                             \
            int iv = 1;           \
            real vrv = 1.0;       \
            string sv = \"1\";    \
            byte bv = 1;          \
            asm                   \
            {                     \
                mov reg int 0, 5;                \
                /* RI->RI */                     \
                mov reg int 1, reg int 0;        \
                /* RI->VI */                     \
                mov global.iv, reg int 1;        \
                /* RI->RR */                     \
                mov reg real 0, reg int 0;       \
                /* RR->VR */                     \
                mov global.vrv, reg real 0;      \
                /* RI->RB */                     \
                mov reg byte 0, reg int 0;       \
                /* RB->VB */                     \
                mov global.bv, reg byte 0;       \
                /* RI-> RS*/                     \
                mov reg string 0, reg int 0;     \
                /* RS->VS */                     \
                mov global.sv, reg string 0;     \
            }                                    \
    "
    SCRIPT_END
    ASSERT_EQ(5, VAR_INT(iv));
    ASSERT_EQ(5, VAR_BYTE(bv));

    double vrv = (double)VAR_REAL(vrv);
    ASSERT_DOUBLE_EQ((double)5.0, vrv);

    SCRIPT_ASSERT_STREQ("5", sv);


    SCRIPT_SHUTDOWN
}


TEST(FeatureTable, RegisterByteToRegisterX)
{
    SCRIPT_START
    "                             \
            int iv = 1;           \
            real vrv = 1.0;       \
            string sv = \"1\";    \
            byte bv = 1;          \
            asm                   \
            {                     \
                mov reg byte 0, 5;                \
                /* RB->RI */                     \
                mov reg int 0, reg byte 0;        \
                mov global.iv, reg int 0;        \
                /* RB->RR */                     \
                mov reg real 0, reg byte 0;       \
                mov global.vrv, reg real 0;      \
                /* RB->RB */                     \
                mov reg byte 1, reg byte 0;       \
                mov global.bv, reg byte 1;       \
                /* RB-> RS*/                     \
                mov reg string 0, reg byte 0;     \
                mov global.sv, reg string 0;     \
            }                                    \
    "
    SCRIPT_END
    ASSERT_EQ(5, VAR_INT(iv));
    ASSERT_EQ(5, VAR_BYTE(bv));

    double vrv = (double)VAR_REAL(vrv);
    ASSERT_DOUBLE_EQ((double)5.0, vrv);

    SCRIPT_ASSERT_STREQ("5", sv);


    SCRIPT_SHUTDOWN
}

TEST(FeatureTable, DISABLED_RegisterRealToRegisterX)
{
    SCRIPT_START
    "                             \
            int iv = 1;           \
            real vrv = 1.0;       \
            string sv = \"1\";    \
            byte bv = 1;          \
            asm                   \
            {                     \
                mov reg real 0, 5.0;                \
                /* RR->RI */                     \
                mov reg int 0, reg real 0;        \
                mov global.iv, reg int 0;        \
                /* RR->RR */                     \
                mov reg real 1, reg real  0;       \
                mov global.vrv, reg real 1;      \
                /* RR->RB */                     \
                mov reg byte 1, reg real  0;       \
                mov global.bv, reg byte 1;       \
                /* RR-> RS*/                     \
                mov reg string 0, reg real  0;     \
                mov global.sv, reg string 0;     \
            }                                    \
    "
    SCRIPT_END
    ASSERT_EQ(5, VAR_INT(iv));
    ASSERT_EQ(5, VAR_BYTE(bv));

    double vrv = (double)VAR_REAL(vrv);
    ASSERT_DOUBLE_EQ((double)5.0, vrv);

    SCRIPT_ASSERT_STREQ("5", sv);


    SCRIPT_SHUTDOWN
}