#include <stdio.h>
#include <stdint.h>
#include <stdbool.h>
#include <string.h>
#include <assert.h>
#include "../../include/synta.h"
static int test_count = 0;
static int pass_count = 0;
#define TEST(name) \
do { \
test_count++; \
printf("Test %d: %s ... ", test_count, name);
#define END_TEST() \
pass_count++; \
printf("PASS\n"); \
} while(0)
void test_invalid_tag(void) {
TEST("Invalid tag detection");
const uint8_t data[] = {0xFF, 0x01, 0x00};
SyntaDecoder* decoder = synta_decoder_new(data, sizeof(data), SyntaEncoding_Der);
assert(decoder != NULL);
bool value = false;
SyntaErrorCode err = synta_decode_boolean(decoder, &value);
assert(err != SyntaErrorCode_Success);
synta_decoder_free(decoder);
END_TEST();
}
void test_truncated_data(void) {
TEST("Truncated data detection");
const uint8_t data[] = {0x02, 0x05, 0x01, 0x02};
SyntaDecoder* decoder = synta_decoder_new(data, sizeof(data), SyntaEncoding_Der);
assert(decoder != NULL);
SyntaInteger* integer = NULL;
SyntaErrorCode err = synta_decode_integer(decoder, &integer);
assert(err != SyntaErrorCode_Success);
assert(err == SyntaErrorCode_UnexpectedEof || err == SyntaErrorCode_InvalidLength);
synta_decoder_free(decoder);
END_TEST();
}
void test_null_pointer_handling(void) {
TEST("NULL pointer handling");
SyntaDecoder* empty_decoder = synta_decoder_new(NULL, 0, SyntaEncoding_Der);
assert(empty_decoder != NULL);
synta_decoder_free(empty_decoder);
assert(synta_decoder_new(NULL, 10, SyntaEncoding_Der) == NULL);
const uint8_t data[] = {0x02, 0x01, 0x2A};
SyntaDecoder* decoder = synta_decoder_new(data, sizeof(data), SyntaEncoding_Der);
assert(decoder != NULL);
SyntaErrorCode err = synta_decode_integer(decoder, NULL);
assert(err == SyntaErrorCode_NullPointer);
synta_decoder_free(decoder);
SyntaEncoder* non_null_encoder = synta_encoder_new(SyntaEncoding_Der);
assert(non_null_encoder != NULL);
synta_encoder_free(non_null_encoder);
END_TEST();
}
void test_empty_data(void) {
TEST("Empty data handling");
const uint8_t data[] = {};
SyntaDecoder* decoder = synta_decoder_new(data, 0, SyntaEncoding_Der);
assert(decoder != NULL);
assert(synta_decoder_at_end(decoder) == true);
assert(synta_decoder_remaining(decoder) == 0);
bool value = false;
SyntaErrorCode err = synta_decode_boolean(decoder, &value);
assert(err != SyntaErrorCode_Success);
synta_decoder_free(decoder);
END_TEST();
}
void test_error_message_retrieval(void) {
TEST("Error message retrieval");
synta_clear_last_error();
const uint8_t data[] = {0x02, 0x05, 0x01}; SyntaDecoder* decoder = synta_decoder_new(data, sizeof(data), SyntaEncoding_Der);
assert(decoder != NULL);
SyntaInteger* integer = NULL;
SyntaErrorCode err = synta_decode_integer(decoder, &integer);
assert(err != SyntaErrorCode_Success);
const char* msg = synta_get_last_error_message();
assert(msg != NULL);
assert(strlen(msg) > 0);
const char* static_msg = synta_error_message(err);
assert(static_msg != NULL);
assert(strlen(static_msg) > 0);
synta_decoder_free(decoder);
synta_clear_last_error();
msg = synta_get_last_error_message();
assert(msg == NULL || strlen(msg) == 0);
END_TEST();
}
void test_invalid_utf8(void) {
TEST("Invalid UTF-8 detection");
const char invalid_utf8[] = {(char)0xC0, (char)0x80, 0x00};
SyntaEncoder* encoder = synta_encoder_new(SyntaEncoding_Der);
assert(encoder != NULL);
SyntaErrorCode err = synta_encode_utf8_string(encoder, invalid_utf8);
if (err == SyntaErrorCode_Success) {
SyntaByteArray encoded = {0};
synta_encoder_finish(encoder, &encoded);
synta_byte_array_free(&encoded);
} else {
synta_encoder_free(encoder);
}
END_TEST();
}
void test_integer_overflow(void) {
TEST("Integer overflow detection");
const uint8_t large_bytes[] = {
0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
};
SyntaInteger* integer = synta_integer_new_bytes(large_bytes, sizeof(large_bytes), false);
assert(integer != NULL);
int64_t value;
SyntaErrorCode err = synta_integer_to_i64(integer, &value);
assert(err == SyntaErrorCode_IntegerOverflow);
synta_integer_free(integer);
END_TEST();
}
void test_invalid_oid_string(void) {
TEST("Invalid OID string detection");
const char* invalid_oids[] = {
"",
".",
"1",
"1.",
".1.2",
"1.2.abc",
"1.2.-3",
"3.0.1", NULL
};
for (int i = 0; invalid_oids[i] != NULL; i++) {
SyntaObjectIdentifier* oid = synta_oid_from_string(invalid_oids[i]);
if (oid != NULL) {
synta_oid_free(oid);
}
}
END_TEST();
}
void test_sequence_mismatch(void) {
TEST("Sequence/tag mismatch detection");
const uint8_t data[] = {0x02, 0x01, 0x2A};
SyntaDecoder* decoder = synta_decoder_new(data, sizeof(data), SyntaEncoding_Der);
assert(decoder != NULL);
SyntaDecoder* seq_decoder = NULL;
SyntaErrorCode err = synta_decoder_enter_sequence(decoder, &seq_decoder);
assert(err != SyntaErrorCode_Success);
synta_decoder_free(decoder);
END_TEST();
}
int main(void) {
printf("=== Error Handling Integration Tests ===\n\n");
test_invalid_tag();
test_truncated_data();
test_null_pointer_handling();
test_empty_data();
test_error_message_retrieval();
test_invalid_utf8();
test_integer_overflow();
test_invalid_oid_string();
test_sequence_mismatch();
printf("\n=== Summary ===\n");
printf("Passed: %d/%d\n", pass_count, test_count);
synta_clear_last_error();
return (pass_count == test_count) ? 0 : 1;
}