103 lines
3.1 KiB
C
103 lines
3.1 KiB
C
|
|
/**
|
||
|
|
* @file value_compare.c
|
||
|
|
* @brief Tests the comparison operators across integer, float and string.
|
||
|
|
*/
|
||
|
|
|
||
|
|
#include <string.h>
|
||
|
|
|
||
|
|
#include <akbasic/error.h>
|
||
|
|
#include <akbasic/value.h>
|
||
|
|
|
||
|
|
#include "testutil.h"
|
||
|
|
|
||
|
|
static akbasic_Value A;
|
||
|
|
static akbasic_Value B;
|
||
|
|
static akbasic_Value SCRATCH;
|
||
|
|
|
||
|
|
static void set_int(akbasic_Value *v, int64_t n)
|
||
|
|
{
|
||
|
|
test_discard_error(akbasic_value_zero(v));
|
||
|
|
v->valuetype = AKBASIC_TYPE_INTEGER;
|
||
|
|
v->intval = n;
|
||
|
|
}
|
||
|
|
|
||
|
|
static void set_float(akbasic_Value *v, double n)
|
||
|
|
{
|
||
|
|
test_discard_error(akbasic_value_zero(v));
|
||
|
|
v->valuetype = AKBASIC_TYPE_FLOAT;
|
||
|
|
v->floatval = n;
|
||
|
|
}
|
||
|
|
|
||
|
|
static void set_string(akbasic_Value *v, const char *s)
|
||
|
|
{
|
||
|
|
test_discard_error(akbasic_value_zero(v));
|
||
|
|
v->valuetype = AKBASIC_TYPE_STRING;
|
||
|
|
strncpy(v->stringval, s, AKBASIC_MAX_STRING_LENGTH - 1);
|
||
|
|
}
|
||
|
|
|
||
|
|
#define EXPECT_BOOL(__call, __want) \
|
||
|
|
do { \
|
||
|
|
akbasic_Value *__out = NULL; \
|
||
|
|
TEST_REQUIRE_OK(__call(&A, &B, &SCRATCH, &__out)); \
|
||
|
|
TEST_REQUIRE(__out->valuetype == AKBASIC_TYPE_BOOLEAN, \
|
||
|
|
#__call " did not produce a boolean"); \
|
||
|
|
TEST_REQUIRE(akbasic_value_is_true(__out) == (__want), \
|
||
|
|
#__call " expected %s", ((__want) ? "true" : "false")); \
|
||
|
|
TEST_REQUIRE_INT(__out->boolvalue, ((__want) ? AKBASIC_TRUE : AKBASIC_FALSE)); \
|
||
|
|
} while ( 0 )
|
||
|
|
|
||
|
|
int main(void)
|
||
|
|
{
|
||
|
|
akbasic_Value *out = NULL;
|
||
|
|
|
||
|
|
TEST_REQUIRE_OK(akbasic_error_register());
|
||
|
|
|
||
|
|
/* Integers. */
|
||
|
|
set_int(&A, 3);
|
||
|
|
set_int(&B, 5);
|
||
|
|
EXPECT_BOOL(akbasic_value_less_than, true);
|
||
|
|
EXPECT_BOOL(akbasic_value_less_than_equal, true);
|
||
|
|
EXPECT_BOOL(akbasic_value_greater_than, false);
|
||
|
|
EXPECT_BOOL(akbasic_value_greater_than_equal, false);
|
||
|
|
EXPECT_BOOL(akbasic_value_is_equal, false);
|
||
|
|
EXPECT_BOOL(akbasic_value_is_not_equal, true);
|
||
|
|
|
||
|
|
set_int(&B, 3);
|
||
|
|
EXPECT_BOOL(akbasic_value_less_than, false);
|
||
|
|
EXPECT_BOOL(akbasic_value_less_than_equal, true);
|
||
|
|
EXPECT_BOOL(akbasic_value_greater_than_equal, true);
|
||
|
|
EXPECT_BOOL(akbasic_value_is_equal, true);
|
||
|
|
|
||
|
|
/* Floats. */
|
||
|
|
set_float(&A, 1.5);
|
||
|
|
set_float(&B, 2.5);
|
||
|
|
EXPECT_BOOL(akbasic_value_less_than, true);
|
||
|
|
EXPECT_BOOL(akbasic_value_greater_than, false);
|
||
|
|
|
||
|
|
/* Strings compare lexically. */
|
||
|
|
set_string(&A, "APPLE");
|
||
|
|
set_string(&B, "BANANA");
|
||
|
|
EXPECT_BOOL(akbasic_value_less_than, true);
|
||
|
|
EXPECT_BOOL(akbasic_value_greater_than, false);
|
||
|
|
EXPECT_BOOL(akbasic_value_is_equal, false);
|
||
|
|
set_string(&B, "APPLE");
|
||
|
|
EXPECT_BOOL(akbasic_value_is_equal, true);
|
||
|
|
EXPECT_BOOL(akbasic_value_less_than_equal, true);
|
||
|
|
EXPECT_BOOL(akbasic_value_greater_than_equal, true);
|
||
|
|
|
||
|
|
/* BASIC true is -1, not 1: the Commodore convention the README calls out. */
|
||
|
|
set_int(&A, 1);
|
||
|
|
set_int(&B, 1);
|
||
|
|
TEST_REQUIRE_OK(akbasic_value_is_equal(&A, &B, &SCRATCH, &out));
|
||
|
|
TEST_REQUIRE_INT(out->boolvalue, -1);
|
||
|
|
|
||
|
|
/* is_true is false for anything that is not a boolean. */
|
||
|
|
set_int(&A, -1);
|
||
|
|
TEST_REQUIRE(!akbasic_value_is_true(&A), "an integer -1 is not a BASIC true");
|
||
|
|
TEST_REQUIRE(!akbasic_value_is_true(NULL), "NULL is not true");
|
||
|
|
|
||
|
|
TEST_REQUIRE_STATUS(akbasic_value_is_equal(&A, NULL, &SCRATCH, &out), AKERR_NULLPOINTER);
|
||
|
|
|
||
|
|
return akbasic_test_failures;
|
||
|
|
}
|