Added new unit tests which lead to bug fix
This commit is contained in:
8
Makefile
8
Makefile
@@ -10,13 +10,14 @@ TESTS_SRC = tests
|
|||||||
TARGET = usage
|
TARGET = usage
|
||||||
TEST_V_TARGET = test_vector
|
TEST_V_TARGET = test_vector
|
||||||
TEST_M_TARGET = test_map
|
TEST_M_TARGET = test_map
|
||||||
|
TEST_B_TARGET = test_bigint
|
||||||
|
|
||||||
LIB_OBJS = $(OBJ_DIR)/vector.o $(OBJ_DIR)/map.o $(OBJ_DIR)/bigint.o
|
LIB_OBJS = $(OBJ_DIR)/vector.o $(OBJ_DIR)/map.o $(OBJ_DIR)/bigint.o
|
||||||
PROG_OBJS = $(OBJ_DIR)/usage.o
|
PROG_OBJS = $(OBJ_DIR)/usage.o
|
||||||
|
|
||||||
.PHONY: all clean
|
.PHONY: all clean
|
||||||
|
|
||||||
all: $(TARGET) $(TEST_V_TARGET) $(TEST_M_TARGET)
|
all: $(TARGET) $(TEST_V_TARGET) $(TEST_M_TARGET) $(TEST_B_TARGET)
|
||||||
|
|
||||||
$(TARGET): $(PROG_OBJS) $(LIB_OBJS)
|
$(TARGET): $(PROG_OBJS) $(LIB_OBJS)
|
||||||
$(CC) $(CFLAGS) -o $@ $^
|
$(CC) $(CFLAGS) -o $@ $^
|
||||||
@@ -27,6 +28,9 @@ $(TEST_V_TARGET): $(OBJ_DIR)/test_vector.o $(OBJ_DIR)/vector.o
|
|||||||
$(TEST_M_TARGET): $(OBJ_DIR)/test_map.o $(OBJ_DIR)/map.o
|
$(TEST_M_TARGET): $(OBJ_DIR)/test_map.o $(OBJ_DIR)/map.o
|
||||||
$(CC) $(CFLAGS) -o $@ $^
|
$(CC) $(CFLAGS) -o $@ $^
|
||||||
|
|
||||||
|
$(TEST_B_TARGET): $(OBJ_DIR)/test_bigint.o $(OBJ_DIR)/bigint.o $(OBJ_DIR)/vector.o
|
||||||
|
$(CC) $(CFLAGS) -o $@ $^
|
||||||
|
|
||||||
$(OBJ_DIR)/%.o: $(SRC_DIR)/%.c | $(OBJ_DIR)
|
$(OBJ_DIR)/%.o: $(SRC_DIR)/%.c | $(OBJ_DIR)
|
||||||
$(CC) $(CFLAGS) -c -o $@ $<
|
$(CC) $(CFLAGS) -c -o $@ $<
|
||||||
|
|
||||||
@@ -40,4 +44,4 @@ $(OBJ_DIR):
|
|||||||
mkdir -p $(OBJ_DIR)
|
mkdir -p $(OBJ_DIR)
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
rm -rf $(OBJ_DIR) $(TARGET) $(TEST_V_TARGET) $(TEST_M_TARGET)
|
rm -rf $(OBJ_DIR) $(TARGET) $(TEST_V_TARGET) $(TEST_M_TARGET) $(TEST_B_TARGET)
|
||||||
|
|||||||
17
src/bigint.c
17
src/bigint.c
@@ -61,33 +61,34 @@ bigint_result_t bigint_from_int(long long value) {
|
|||||||
number->digits = vec_res.value.vector;
|
number->digits = vec_res.value.vector;
|
||||||
number->is_negative = (value < 0);
|
number->is_negative = (value < 0);
|
||||||
|
|
||||||
if (value < 0) {
|
// Discard the sign since we don't need it anymore
|
||||||
value = -value;
|
unsigned long long abs_val = value < 0 ? -(unsigned long long)value : (unsigned long long)value;
|
||||||
} else if (value == 0) {
|
|
||||||
|
if(abs_val == 0) {
|
||||||
int zero = 0;
|
int zero = 0;
|
||||||
vector_result_t push_res = vector_push(number->digits, &zero);
|
vector_result_t push_res = vector_push(number->digits, &zero);
|
||||||
if (push_res.status != VECTOR_OK) {
|
if (push_res.status != VECTOR_OK) {
|
||||||
vector_destroy(number->digits);
|
vector_destroy(number->digits);
|
||||||
free(number);
|
free(number);
|
||||||
result.status = BIGINT_ERR_INVALID;
|
result.status = BIGINT_ERR_INVALID;
|
||||||
COPY_MSG(result, vec_res.message);
|
COPY_MSG(result, push_res.message);
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
while (value > 0) {
|
while (abs_val != 0) {
|
||||||
int digit = value % BIGINT_BASE;
|
int digit = abs_val % BIGINT_BASE;
|
||||||
vector_result_t push_res = vector_push(number->digits, &digit);
|
vector_result_t push_res = vector_push(number->digits, &digit);
|
||||||
if (push_res.status != VECTOR_OK) {
|
if (push_res.status != VECTOR_OK) {
|
||||||
vector_destroy(number->digits);
|
vector_destroy(number->digits);
|
||||||
free(number);
|
free(number);
|
||||||
result.status = BIGINT_ERR_INVALID;
|
result.status = BIGINT_ERR_INVALID;
|
||||||
COPY_MSG(result, vec_res.message);
|
COPY_MSG(result, push_res.message);
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
value /= BIGINT_BASE;
|
abs_val /= BIGINT_BASE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
63
tests/test_bigint.c
Normal file
63
tests/test_bigint.c
Normal file
@@ -0,0 +1,63 @@
|
|||||||
|
/*
|
||||||
|
* Unit tests for BigInt data type
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define TEST(NAME) do { \
|
||||||
|
printf("Running test_%s...", #NAME); \
|
||||||
|
test_##NAME(); \
|
||||||
|
printf(" PASSED\n"); \
|
||||||
|
} while(0)
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <assert.h>
|
||||||
|
|
||||||
|
#include "../src/bigint.h"
|
||||||
|
|
||||||
|
static void bigint_eq(const bigint_t *number, const char *expected) {
|
||||||
|
bigint_result_t to_str = bigint_to_string(number);
|
||||||
|
assert(to_str.status == BIGINT_OK);
|
||||||
|
assert(!strcmp(to_str.value.string_num, expected));
|
||||||
|
|
||||||
|
free(to_str.value.string_num);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test creating big integers from int
|
||||||
|
void test_bigint_from_int() {
|
||||||
|
bigint_result_t res = bigint_from_int(0);
|
||||||
|
|
||||||
|
assert(res.status == BIGINT_OK);
|
||||||
|
bigint_eq(res.value.number, "0");
|
||||||
|
bigint_destroy(res.value.number);
|
||||||
|
|
||||||
|
res = bigint_from_int(10);
|
||||||
|
assert(res.status == BIGINT_OK);
|
||||||
|
bigint_eq(res.value.number, "10");
|
||||||
|
bigint_destroy(res.value.number);
|
||||||
|
|
||||||
|
res = bigint_from_int(-12345678900LL);
|
||||||
|
assert(res.status == BIGINT_OK);
|
||||||
|
bigint_eq(res.value.number, "-12345678900");
|
||||||
|
bigint_destroy(res.value.number);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test creating big integers from string
|
||||||
|
void test_bigint_from_string() {
|
||||||
|
bigint_result_t res = bigint_from_string("00000123");
|
||||||
|
|
||||||
|
assert(res.status == BIGINT_OK);
|
||||||
|
bigint_eq(res.value.number, "123");
|
||||||
|
bigint_destroy(res.value.number);
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(void) {
|
||||||
|
printf("=== Running BigInt unit tests ===\n\n");
|
||||||
|
|
||||||
|
TEST(bigint_from_int);
|
||||||
|
TEST(bigint_from_string);
|
||||||
|
|
||||||
|
printf("\n=== All tests passed ===\n");
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user