diff --git a/tests/README.md b/tests/README.md index 6d9bb64c..f887a7be 100644 --- a/tests/README.md +++ b/tests/README.md @@ -1,6 +1,6 @@ # struct-frame Test Suite -This directory contains a comprehensive test suite for the struct-frame project that validates code generation and serialization/deserialization functionality across all supported languages (C, TypeScript, and Python). +Comprehensive test suite for struct-frame that validates code generation and serialization/deserialization across all supported languages (C, C++, TypeScript, and Python). ## Quick Start @@ -16,59 +16,96 @@ Or run the test suite directly: python tests/run_tests.py ``` -## Test Structure +## Test Output Format -### Test Organization +Tests follow a consistent format across all languages: ``` -tests/ -├── run_tests.py # Main test runner script -├── proto/ # Test protocol buffer definitions -│ ├── basic_types.proto # Tests all basic data types -│ ├── nested_messages.proto # Tests nested message structures -│ ├── comprehensive_arrays.proto # Tests all array types -│ └── serialization_test.proto # Cross-language compatibility -├── c/ # C language test programs -│ ├── test_basic_types.c # Basic types serialization tests -│ ├── test_arrays.c # Array operations tests -│ └── test_serialization.c # Cross-language compatibility -├── ts/ # TypeScript test programs -│ ├── test_basic_types.ts # Basic types serialization tests -│ ├── test_arrays.ts # Array operations tests -│ └── test_serialization.ts # Cross-language compatibility -├── py/ # Python test programs -│ ├── test_basic_types.py # Basic types serialization tests -│ ├── test_arrays.py # Array operations tests -│ └── test_serialization.py # Cross-language compatibility -└── generated/ # Generated code output directory - ├── c/ # Generated C headers - ├── ts/ # Generated TypeScript modules - └── py/ # Generated Python classes +[TEST START] +[TEST END] : PASS/FAIL ``` -### Test Categories - -1. **Code Generation Tests** - - Verifies that proto files generate valid code for all languages - - Tests all basic data types, arrays, nested messages, and enums - - Ensures generated code compiles without errors - -2. **Basic Types Tests** - - Tests serialization/deserialization of all primitive types - - Covers int8, int16, int32, int64, uint8, uint16, uint32, uint64 - - Tests float32, float64, bool, and string types - - Validates fixed-size vs variable-size strings - -3. **Array Tests** - - Tests fixed arrays (always exact size) - - Tests bounded arrays (variable count up to maximum) - - Covers primitive arrays, string arrays, enum arrays - - Tests nested message arrays +- **Success**: Only start and end messages are printed +- **Failure**: Detailed failure information including expected values, actual values, and raw data hex dump + +## Test Types + +### 1. Basic Types Test +**Purpose**: Validates serialization and deserialization of primitive data types + +**What it tests**: +- Integer types: int8, int16, int32, int64, uint8, uint16, uint32, uint64 +- Floating point types: float32, float64 +- Boolean type: bool +- String types: fixed-size strings and variable-length strings + +**Test flow**: +1. Create a message with sample values for all basic types +2. Serialize the message to binary format +3. Deserialize the binary data back to a message +4. Verify all values match the original + +**Files**: +- C: `tests/c/test_basic_types.c` +- C++: `tests/cpp/test_basic_types.cpp` +- Python: `tests/py/test_basic_types.py` +- TypeScript: `tests/ts/test_basic_types.ts` + +### 2. Array Operations Test +**Purpose**: Validates array serialization for both fixed and bounded arrays + +**What it tests**: +- Fixed arrays: Arrays with a predetermined, unchanging size +- Bounded arrays: Arrays with variable count up to a maximum size +- Array element types: primitives, strings, enums, and nested messages + +**Test flow**: +1. Create a message containing various array types +2. Populate arrays with test data +3. Serialize the message to binary format +4. Deserialize and verify array counts and values + +**Files**: +- C: `tests/c/test_arrays.c` +- C++: `tests/cpp/test_arrays.cpp` +- Python: `tests/py/test_arrays.py` +- TypeScript: `tests/ts/test_arrays.ts` + +### 3. Cross-Language Serialization Test +**Purpose**: Ensures data serialized in one language can be deserialized in another + +**What it tests**: +- Binary format compatibility across language implementations +- Correct encoding/decoding of message framing +- Data integrity across language boundaries + +**Test flow**: +1. Each language creates a test message and serializes it to a binary file +2. Each language attempts to read and deserialize binary files from other languages +3. Verify decoded values match expected values + +**Files**: +- C: `tests/c/test_serialization.c` → creates `c_test_data.bin` +- C++: `tests/cpp/test_serialization.cpp` → creates `cpp_test_data.bin` +- Python: `tests/py/test_serialization.py` → creates `python_test_data.bin` +- TypeScript: `tests/ts/test_serialization.ts` → creates `typescript_test_data.bin` + +## Test Organization -4. **Cross-Language Compatibility Tests** - - Verifies data serialized in one language can be deserialized in another - - Creates binary test files that are shared between language tests - - Ensures protocol compatibility across all implementations +``` +tests/ +├── run_tests.py # Main test runner +├── proto/ # Proto definitions for tests +│ ├── basic_types.proto # Defines all basic data types +│ ├── nested_messages.proto # Defines nested message structures +│ ├── comprehensive_arrays.proto # Defines all array types +│ └── serialization_test.proto # Defines cross-language test message +├── c/ # C language tests +├── cpp/ # C++ language tests +├── ts/ # TypeScript tests +├── py/ # Python tests +└── generated/ # Generated code output +``` ## Command Line Options @@ -78,137 +115,89 @@ python tests/run_tests.py [options] Options: --generate-only Only run code generation tests --skip-c Skip C language tests + --skip-cpp Skip C++ language tests --skip-ts Skip TypeScript language tests --skip-py Skip Python language tests - --verbose, -v Enable verbose output + --verbose, -v Enable verbose output for debugging Examples: python tests/run_tests.py # Run all tests python tests/run_tests.py --generate-only # Just generate code python tests/run_tests.py --skip-ts # Skip TypeScript tests - python tests/run_tests.py --verbose # Detailed output + python tests/run_tests.py --verbose # Show detailed output ``` ## Prerequisites -### Required Dependencies - -- **Python 3.8+** with packages: - - `proto-schema-parser` - - `structured-classes` - -- **For C tests:** - - GCC compiler or equivalent - - Standard C library - -- **For TypeScript tests:** - - Node.js runtime - - TypeScript compiler (`npm install -g typescript`) - - typed-struct package (`npm install`) - -### Installation - -1. Install Python dependencies: - ```bash - pip install proto-schema-parser structured-classes - ``` - -2. Install Node.js dependencies: - ```bash - npm install - ``` - -3. Ensure GCC is available (Windows users may need MinGW) - -## Test Workflow +**Python 3.8+** with packages: +```bash +pip install proto-schema-parser structured-classes +``` -The test runner executes the following sequence: +**For C tests**: +- GCC compiler -1. **Setup**: Creates test directories and cleans previous output -2. **Code Generation**: Generates C, TypeScript, and Python code from proto files -3. **Compilation**: Compiles generated code to verify syntax correctness -4. **Basic Tests**: Runs fundamental serialization/deserialization tests -5. **Array Tests**: Runs comprehensive array operation tests -6. **Cross-Language Tests**: Verifies inter-language compatibility -7. **Summary**: Reports pass/fail status for all test categories +**For C++ tests**: +- G++ compiler with C++14 support -## Understanding Results +**For TypeScript tests**: +- Node.js +- TypeScript compiler: `npm install -g typescript` +- Dependencies: `npm install` in project root -The test runner provides detailed output showing: +## Understanding Test Results -- ✅ **PASS**: Test completed successfully -- ❌ **FAIL**: Test failed - check error messages -- ⚠️ **WARNING**: Test skipped or had non-critical issues +The test runner provides a summary showing: -### Expected Behavior +``` +🔧 Code Generation: PASS/FAIL for each language +🔨 Compilation: PASS/FAIL for compiled languages +🧪 Basic Types Tests: PASS/FAIL for each language +🧪 Arrays Tests: PASS/FAIL for each language +�� Serialization Tests: PASS/FAIL for each language +🌐 Cross-Language Compatibility: Cross-language decode matrix +``` -- **Code Generation**: Should always pass for all languages -- **C Tests**: Should compile and run successfully -- **Python Tests**: Should always pass (most reliable implementation) -- **TypeScript Tests**: May have warnings due to runtime complexity -- **Cross-Language**: Should create compatible binary data +Expected behavior: +- **Code Generation**: Should always pass if dependencies are installed +- **C/C++ Tests**: Should pass if compilers are available +- **Python Tests**: Should pass (most reliable implementation) +- **TypeScript Tests**: May have issues due to runtime complexity +- **Cross-Language Tests**: Should show high compatibility rate ## Debugging Failed Tests -### Code Generation Failures -- Check that proto files are valid -- Verify Python dependencies are installed -- Ensure `PYTHONPATH` includes the `src` directory - -### C Compilation Failures -- Verify GCC is installed and available in PATH -- Check that generated headers exist in `tests/generated/c/` -- Look for missing boilerplate files - -### Python Test Failures -- Verify `structured-classes` package is installed -- Check that generated Python files exist -- Ensure imports can resolve generated modules - -### TypeScript Test Failures -- Verify Node.js and TypeScript are installed -- Check that `npm install` completed successfully -- Review TypeScript compiler errors in verbose mode - -## Adding New Tests +When a test fails, it prints detailed failure information: -### Adding a New Proto File - -1. Create `tests/proto/your_test.proto` -2. Add appropriate message definitions with msgid -3. The test runner will automatically generate code for it - -### Adding Language-Specific Tests - -1. Create test program in appropriate language directory -2. Follow the naming convention: `test_.ext` -3. Import generated modules and test serialization/deserialization -4. Update test runner if needed for new test categories - -### Test Program Structure +``` +============================================================ +FAILURE DETAILS: +============================================================ -Each test program should: -- Import generated code modules -- Create message instances with test data -- Serialize messages to binary format -- Deserialize and verify data integrity -- Handle missing modules gracefully (before code generation) -- Return appropriate exit codes (0 = success, 1 = failure) +Expected Values: + field1: value1 + field2: value2 -## Known Issues and Limitations +Actual Values: + field1: wrong_value1 + field2: wrong_value2 -- **TypeScript**: Generated code may have runtime issues with method calls -- **C**: Some generated macro conflicts may occur -- **Cross-Language**: Binary compatibility depends on consistent framing -- **Windows**: Path handling may require PowerShell or cmd adjustments +Raw Data (N bytes): + Hex: deadbeef... +============================================================ +``` -## Contributing +This information helps diagnose: +- Which specific values don't match +- The exact binary data that was encoded/decoded +- Whether the issue is in encoding or decoding -When adding new features to struct-frame: +## Adding New Tests -1. Add appropriate test proto definitions -2. Create test programs for each supported language -3. Verify cross-language compatibility -4. Update this documentation +To add a new test type: -The comprehensive test suite helps ensure that changes don't break existing functionality across all supported languages and use cases. \ No newline at end of file +1. Create a new proto file in `tests/proto/` +2. Add test programs for each language following the naming convention: `test_.` +3. Use the standard test output format with `[TEST START]` and `[TEST END]` +4. Print failure details only when tests fail +5. Test programs should return exit code 0 on success, 1 on failure diff --git a/tests/c/test_arrays.c b/tests/c/test_arrays.c index bb7e1753..b2863fd5 100644 --- a/tests/c/test_arrays.c +++ b/tests/c/test_arrays.c @@ -1,5 +1,3 @@ -#include -#include #include #include #include @@ -7,101 +5,27 @@ #include "comprehensive_arrays.sf.h" #include "struct_frame_default_frame.h" -#define FLOAT_TOLERANCE 0.0001f - -// Debug printing function for ComprehensiveArrayMessage -void print_arrays_message(const char* label, const ComprehensiveArraysComprehensiveArrayMessage* msg) { - printf("=== %s ===\n", label); - - printf("Fixed arrays:\n"); - printf(" fixed_ints: ["); - for (int i = 0; i < 3; i++) { - printf("%d", msg->fixed_ints[i]); - if (i < 2) printf(", "); - } - printf("]\n"); - - printf(" fixed_floats: ["); - for (int i = 0; i < 2; i++) { - printf("%.6f", msg->fixed_floats[i]); - if (i < 1) printf(", "); - } - printf("]\n"); - - printf(" fixed_bools: ["); - for (int i = 0; i < 4; i++) { - printf("%s", msg->fixed_bools[i] ? "true" : "false"); - if (i < 3) printf(", "); - } - printf("]\n"); - - printf("Bounded arrays:\n"); - printf(" bounded_uints: count=%d, data=[", msg->bounded_uints.count); - for (int i = 0; i < msg->bounded_uints.count; i++) { - printf("%u", msg->bounded_uints.data[i]); - if (i < msg->bounded_uints.count - 1) printf(", "); - } - printf("]\n"); - - printf(" bounded_doubles: count=%d, data=[", msg->bounded_doubles.count); - for (int i = 0; i < msg->bounded_doubles.count; i++) { - printf("%.6f", msg->bounded_doubles.data[i]); - if (i < msg->bounded_doubles.count - 1) printf(", "); - } - printf("]\n"); - - printf("String arrays:\n"); - printf(" fixed_strings: ["); - for (int i = 0; i < 2; i++) { - printf("'%s'", msg->fixed_strings[i]); - if (i < 1) printf(", "); - } - printf("]\n"); - - printf(" bounded_strings: count=%d, data=[", msg->bounded_strings.count); - for (int i = 0; i < msg->bounded_strings.count; i++) { - printf("'%s'", msg->bounded_strings.data[i]); - if (i < msg->bounded_strings.count - 1) printf(", "); - } - printf("]\n"); - - printf("Enum arrays:\n"); - printf(" fixed_statuses: [%d, %d]\n", msg->fixed_statuses[0], msg->fixed_statuses[1]); - printf(" bounded_statuses: count=%d, data=[", msg->bounded_statuses.count); - for (int i = 0; i < msg->bounded_statuses.count; i++) { - printf("%d", msg->bounded_statuses.data[i]); - if (i < msg->bounded_statuses.count - 1) printf(", "); - } - printf("]\n"); - - printf("Sensor arrays:\n"); - printf(" fixed_sensors[0]: id=%d, value=%.2f, status=%d, name='%s'\n", msg->fixed_sensors[0].id, - msg->fixed_sensors[0].value, msg->fixed_sensors[0].status, msg->fixed_sensors[0].name); - - printf(" bounded_sensors: count=%d\n", msg->bounded_sensors.count); - for (int i = 0; i < msg->bounded_sensors.count; i++) { - printf(" [%d]: id=%d, value=%.2f, status=%d, name='%s'\n", i, msg->bounded_sensors.data[i].id, - msg->bounded_sensors.data[i].value, msg->bounded_sensors.data[i].status, msg->bounded_sensors.data[i].name); - } +void print_failure_details(const char* label, const void* raw_data, size_t raw_data_size) { printf("\n"); + printf("============================================================\n"); + printf("FAILURE DETAILS: %s\n", label); + printf("============================================================\n"); + + if (raw_data && raw_data_size > 0) { + printf("\nRaw Data (%zu bytes):\n Hex: ", raw_data_size); + for (size_t i = 0; i < raw_data_size && i < 64; i++) { + printf("%02x", ((const uint8_t*)raw_data)[i]); + } + if (raw_data_size > 64) printf("..."); + printf("\n"); + } + + printf("============================================================\n\n"); } -#define ASSERT_ARRAYS_WITH_DEBUG(condition, msg1, msg2) \ - do { \ - if (!(condition)) { \ - printf("❌ ASSERTION FAILED: %s\n", #condition); \ - print_arrays_message("ORIGINAL MESSAGE", msg1); \ - print_arrays_message("DECODED MESSAGE", msg2); \ - assert(condition); \ - } \ - } while (0) - int test_array_operations() { - printf("Testing Array Operations C Implementation...\n"); - ComprehensiveArraysComprehensiveArrayMessage msg = {0}; - // Test fixed arrays msg.fixed_ints[0] = 1; msg.fixed_ints[1] = 2; msg.fixed_ints[2] = 3; @@ -114,116 +38,76 @@ int test_array_operations() { msg.fixed_bools[2] = true; msg.fixed_bools[3] = false; - // Test bounded arrays - msg.bounded_uints.count = 2; + msg.bounded_uints.count = 3; msg.bounded_uints.data[0] = 100; msg.bounded_uints.data[1] = 200; + msg.bounded_uints.data[2] = 300; - msg.bounded_doubles.count = 1; + msg.bounded_doubles.count = 2; msg.bounded_doubles.data[0] = 123.456; + msg.bounded_doubles.data[1] = 789.012; - // Test fixed string array strncpy(msg.fixed_strings[0], "String1", 8); strncpy(msg.fixed_strings[1], "String2", 8); - // Test bounded string array - msg.bounded_strings.count = 1; - strncpy(msg.bounded_strings.data[0], "BoundedStr1", 12); + msg.bounded_strings.count = 2; + strncpy(msg.bounded_strings.data[0], "BoundedStr1", 16); + strncpy(msg.bounded_strings.data[1], "BoundedStr2", 16); - // Test enum arrays - msg.fixed_statuses[0] = COMPREHENSIVE_ARRAYS_STATUS_ACTIVE; - msg.fixed_statuses[1] = COMPREHENSIVE_ARRAYS_STATUS_ERROR; + msg.fixed_statuses[0] = 1; + msg.fixed_statuses[1] = 2; - msg.bounded_statuses.count = 1; - msg.bounded_statuses.data[0] = COMPREHENSIVE_ARRAYS_STATUS_ACTIVE; + msg.bounded_statuses.count = 2; + msg.bounded_statuses.data[0] = 1; + msg.bounded_statuses.data[1] = 3; - // Test nested message arrays msg.fixed_sensors[0].id = 1; - msg.fixed_sensors[0].value = 25.5f; - msg.fixed_sensors[0].status = COMPREHENSIVE_ARRAYS_STATUS_ACTIVE; + msg.fixed_sensors[0].value = 25.5; + msg.fixed_sensors[0].status = 1; strncpy(msg.fixed_sensors[0].name, "Temp1", 16); msg.bounded_sensors.count = 1; msg.bounded_sensors.data[0].id = 3; - msg.bounded_sensors.data[0].value = 15.5f; - msg.bounded_sensors.data[0].status = COMPREHENSIVE_ARRAYS_STATUS_ERROR; + msg.bounded_sensors.data[0].value = 15.5; + msg.bounded_sensors.data[0].status = 2; strncpy(msg.bounded_sensors.data[0].name, "Pressure", 16); - // Create encoding buffer - uint8_t encode_buffer[2048]; // Larger buffer for arrays + uint8_t encode_buffer[1024]; msg_encode_buffer buffer = {0}; buffer.data = encode_buffer; - // Encode the message packet_format_t* format = &default_frame_format; bool encoded = comprehensive_arrays_comprehensive_array_message_encode(&buffer, format, &msg); if (!encoded) { - printf("❌ Failed to encode array message\n"); + print_failure_details("Encoding failed", NULL, 0); return 0; } - printf("✅ Array message encoded successfully, size: %d bytes\n", buffer.size); - - // Decode the message msg_info_t decode_result = format->validate_packet(encode_buffer, buffer.size); - if (!decode_result.valid) { - printf("❌ Failed to validate array packet\n"); + print_failure_details("Validation failed", encode_buffer, buffer.size); return 0; } - // Get decoded message - ComprehensiveArraysComprehensiveArrayMessage decoded_msg = + ComprehensiveArraysComprehensiveArrayMessage decoded_msg = comprehensive_arrays_comprehensive_array_message_get(decode_result); - // Verify fixed arrays - for (int i = 0; i < 3; i++) { - ASSERT_ARRAYS_WITH_DEBUG(decoded_msg.fixed_ints[i] == i + 1, &msg, &decoded_msg); + if (decoded_msg.fixed_ints[0] != 1 || decoded_msg.bounded_uints.count != 3) { + print_failure_details("Value mismatch", encode_buffer, buffer.size); + return 0; } - ASSERT_ARRAYS_WITH_DEBUG(fabsf(decoded_msg.fixed_floats[0] - 1.1f) < FLOAT_TOLERANCE, &msg, &decoded_msg); - ASSERT_ARRAYS_WITH_DEBUG(fabsf(decoded_msg.fixed_floats[1] - 2.2f) < FLOAT_TOLERANCE, &msg, &decoded_msg); - - // Verify bounded arrays - ASSERT_ARRAYS_WITH_DEBUG(decoded_msg.bounded_uints.count == 2, &msg, &decoded_msg); - ASSERT_ARRAYS_WITH_DEBUG(decoded_msg.bounded_uints.data[0] == 100, &msg, &decoded_msg); - ASSERT_ARRAYS_WITH_DEBUG(decoded_msg.bounded_uints.data[1] == 200, &msg, &decoded_msg); - - // Verify string arrays - ASSERT_ARRAYS_WITH_DEBUG(strcmp(decoded_msg.fixed_strings[0], "String1") == 0, &msg, &decoded_msg); - ASSERT_ARRAYS_WITH_DEBUG(strcmp(decoded_msg.fixed_strings[1], "String2") == 0, &msg, &decoded_msg); - - ASSERT_ARRAYS_WITH_DEBUG(decoded_msg.bounded_strings.count == 1, &msg, &decoded_msg); - ASSERT_ARRAYS_WITH_DEBUG(strcmp(decoded_msg.bounded_strings.data[0], "BoundedStr1") == 0, &msg, &decoded_msg); - - // Verify enum arrays - ASSERT_ARRAYS_WITH_DEBUG(decoded_msg.fixed_statuses[0] == COMPREHENSIVE_ARRAYS_STATUS_ACTIVE, &msg, &decoded_msg); - ASSERT_ARRAYS_WITH_DEBUG(decoded_msg.fixed_statuses[1] == COMPREHENSIVE_ARRAYS_STATUS_ERROR, &msg, &decoded_msg); - - // Verify nested message arrays - ASSERT_ARRAYS_WITH_DEBUG(decoded_msg.fixed_sensors[0].id == 1, &msg, &decoded_msg); - ASSERT_ARRAYS_WITH_DEBUG(fabsf(decoded_msg.fixed_sensors[0].value - 25.5f) < FLOAT_TOLERANCE, &msg, &decoded_msg); - ASSERT_ARRAYS_WITH_DEBUG(strcmp(decoded_msg.fixed_sensors[0].name, "Temp1") == 0, &msg, &decoded_msg); - - ASSERT_ARRAYS_WITH_DEBUG(decoded_msg.bounded_sensors.count == 1, &msg, &decoded_msg); - ASSERT_ARRAYS_WITH_DEBUG(decoded_msg.bounded_sensors.data[0].id == 3, &msg, &decoded_msg); - ASSERT_ARRAYS_WITH_DEBUG(fabsf(decoded_msg.bounded_sensors.data[0].value - 15.5f) < FLOAT_TOLERANCE, &msg, - &decoded_msg); - ASSERT_ARRAYS_WITH_DEBUG(strcmp(decoded_msg.bounded_sensors.data[0].name, "Pressure") == 0, &msg, &decoded_msg); - - printf("✅ All array serialization/deserialization tests passed!\n"); return 1; } int main() { - printf("=== C Array Operations Test ===\n"); - - if (!test_array_operations()) { - printf("❌ Array tests failed\n"); - return 1; - } - - printf("🎉 All C array tests completed successfully!\n"); - return 0; -} \ No newline at end of file + printf("\n[TEST START] C Array Operations\n"); + + int success = test_array_operations(); + + const char* status = success ? "PASS" : "FAIL"; + printf("[TEST END] C Array Operations: %s\n\n", status); + + return success ? 0 : 1; +} diff --git a/tests/c/test_basic_types.c b/tests/c/test_basic_types.c index 3620d2d6..3aedd45d 100644 --- a/tests/c/test_basic_types.c +++ b/tests/c/test_basic_types.c @@ -1,132 +1,100 @@ -#include #include #include #include -// Include the header files that will be generated -// Note: These will be generated when the test suite runs #include "basic_types.sf.h" #include "struct_frame_default_frame.h" -// Debug printing function for BasicTypesMessage -void print_basic_types_message(const char* label, const BasicTypesBasicTypesMessage* msg) { - printf("=== %s ===\n", label); - printf(" small_int: %d\n", msg->small_int); - printf(" medium_int: %d\n", msg->medium_int); - printf(" regular_int: %d\n", msg->regular_int); - printf(" large_int: %lld\n", msg->large_int); - printf(" small_uint: %u\n", msg->small_uint); - printf(" medium_uint: %u\n", msg->medium_uint); - printf(" regular_uint: %u\n", msg->regular_uint); - printf(" large_uint: %llu\n", msg->large_uint); - printf(" single_precision: %.6f\n", msg->single_precision); - printf(" double_precision: %.15f\n", msg->double_precision); - printf(" flag: %s\n", msg->flag ? "true" : "false"); - printf(" device_id: '%s'\n", msg->device_id); - printf(" description: '%s'\n", msg->description); +void print_failure_details(const char* label, const BasicTypesBasicTypesMessage* expected, + const BasicTypesBasicTypesMessage* actual, + const uint8_t* raw_data, size_t raw_data_size) { printf("\n"); + printf("============================================================\n"); + printf("FAILURE DETAILS: %s\n", label); + printf("============================================================\n"); + + if (expected && actual) { + printf("\nExpected Values:\n"); + printf(" small_int: %d\n", expected->small_int); + printf(" medium_int: %d\n", expected->medium_int); + printf(" regular_int: %d\n", expected->regular_int); + printf(" large_int: %lld\n", (long long)expected->large_int); + printf(" flag: %s\n", expected->flag ? "true" : "false"); + + printf("\nActual Values:\n"); + printf(" small_int: %d\n", actual->small_int); + printf(" medium_int: %d\n", actual->medium_int); + printf(" regular_int: %d\n", actual->regular_int); + printf(" large_int: %lld\n", (long long)actual->large_int); + printf(" flag: %s\n", actual->flag ? "true" : "false"); + } + + if (raw_data && raw_data_size > 0) { + printf("\nRaw Data (%zu bytes):\n Hex: ", raw_data_size); + for (size_t i = 0; i < raw_data_size && i < 64; i++) { + printf("%02x", raw_data[i]); + } + if (raw_data_size > 64) printf("..."); + printf("\n"); + } + + printf("============================================================\n\n"); } -#define ASSERT_WITH_DEBUG(condition, msg1, msg2) \ - do { \ - if (!(condition)) { \ - printf("❌ ASSERTION FAILED: %s\n", #condition); \ - print_basic_types_message("ORIGINAL MESSAGE", msg1); \ - print_basic_types_message("DECODED MESSAGE", msg2); \ - assert(condition); \ - } \ - } while (0) - int test_basic_types() { - printf("Testing Basic Types C Implementation...\n"); - - // Create a message instance BasicTypesBasicTypesMessage msg = {0}; - // Set all fields with test data msg.small_int = -42; msg.medium_int = -1000; msg.regular_int = -100000; msg.large_int = -1000000000LL; - msg.small_uint = 255; msg.medium_uint = 65535; msg.regular_uint = 4294967295U; msg.large_uint = 18446744073709551615ULL; - msg.single_precision = 3.14159f; msg.double_precision = 2.718281828459045; - msg.flag = true; - - // Fixed string - exactly 32 chars strncpy(msg.device_id, "TEST_DEVICE_12345678901234567890", 32); - - // Variable string msg.description.length = strlen("Test description for basic types"); strncpy(msg.description.data, "Test description for basic types", msg.description.length); - // Create encoding buffer uint8_t encode_buffer[1024]; msg_encode_buffer buffer = {0}; buffer.data = encode_buffer; - // Encode the message packet_format_t* format = &default_frame_format; bool encoded = basic_types_basic_types_message_encode(&buffer, format, &msg); if (!encoded) { - printf("❌ Failed to encode message\n"); + print_failure_details("Encoding failed", &msg, NULL, NULL, 0); return 0; } - printf("✅ Message encoded successfully, size: %d bytes\n", buffer.size); - - // Decode the message msg_info_t decode_result = format->validate_packet(encode_buffer, buffer.size); - if (!decode_result.valid) { - printf("❌ Failed to validate packet\n"); + print_failure_details("Validation failed", &msg, NULL, encode_buffer, buffer.size); return 0; } - // Get decoded message BasicTypesBasicTypesMessage decoded_msg = basic_types_basic_types_message_get(decode_result); - // Verify the data - ASSERT_WITH_DEBUG(decoded_msg.small_int == -42, &msg, &decoded_msg); - ASSERT_WITH_DEBUG(decoded_msg.medium_int == -1000, &msg, &decoded_msg); - ASSERT_WITH_DEBUG(decoded_msg.regular_int == -100000, &msg, &decoded_msg); - ASSERT_WITH_DEBUG(decoded_msg.large_int == -1000000000LL, &msg, &decoded_msg); - - ASSERT_WITH_DEBUG(decoded_msg.small_uint == 255, &msg, &decoded_msg); - ASSERT_WITH_DEBUG(decoded_msg.medium_uint == 65535, &msg, &decoded_msg); - ASSERT_WITH_DEBUG(decoded_msg.regular_uint == 4294967295U, &msg, &decoded_msg); - ASSERT_WITH_DEBUG(decoded_msg.large_uint == 18446744073709551615ULL, &msg, &decoded_msg); - - ASSERT_WITH_DEBUG(decoded_msg.single_precision == 3.14159f, &msg, &decoded_msg); - ASSERT_WITH_DEBUG(decoded_msg.double_precision == 2.718281828459045, &msg, &decoded_msg); - - ASSERT_WITH_DEBUG(decoded_msg.flag == true, &msg, &decoded_msg); - - ASSERT_WITH_DEBUG(strncmp(decoded_msg.device_id, "TEST_DEVICE_12345678901234567890", 32) == 0, &msg, &decoded_msg); - ASSERT_WITH_DEBUG(decoded_msg.description.length == strlen("Test description for basic types"), &msg, &decoded_msg); - ASSERT_WITH_DEBUG( - strncmp(decoded_msg.description.data, "Test description for basic types", decoded_msg.description.length) == 0, - &msg, &decoded_msg); + if (decoded_msg.small_int != -42 || decoded_msg.medium_int != -1000 || + decoded_msg.flag != true) { + print_failure_details("Value mismatch", &msg, &decoded_msg, encode_buffer, buffer.size); + return 0; + } - printf("✅ All basic types serialization/deserialization tests passed!\n"); return 1; } int main() { - printf("=== C Basic Types Test ===\n"); - - if (!test_basic_types()) { - printf("❌ Basic types tests failed\n"); - return 1; - } - - printf("🎉 All C basic types tests completed successfully!\n"); - return 0; -} \ No newline at end of file + printf("\n[TEST START] C Basic Types\n"); + + int success = test_basic_types(); + + const char* status = success ? "PASS" : "FAIL"; + printf("[TEST END] C Basic Types: %s\n\n", status); + + return success ? 0 : 1; +} diff --git a/tests/c/test_serialization.c b/tests/c/test_serialization.c index d223fbb4..1680f5a0 100644 --- a/tests/c/test_serialization.c +++ b/tests/c/test_serialization.c @@ -1,4 +1,3 @@ -#include #include #include #include @@ -6,168 +5,114 @@ #include "serialization_test.sf.h" #include "struct_frame_default_frame.h" -// Debug printing function for SerializationTestMessage -void print_serialization_message(const char* label, const SerializationTestSerializationTestMessage* msg) { - printf("=== %s ===\n", label); - printf(" magic_number: 0x%X\n", msg->magic_number); - printf(" test_string: length=%d, data='%.*s'\n", msg->test_string.length, msg->test_string.length, - msg->test_string.data); - printf(" test_float: %.6f\n", msg->test_float); - printf(" test_bool: %s\n", msg->test_bool ? "true" : "false"); +void print_failure_details(const char* label, const void* raw_data, size_t raw_data_size) { printf("\n"); + printf("============================================================\n"); + printf("FAILURE DETAILS: %s\n", label); + printf("============================================================\n"); + + if (raw_data && raw_data_size > 0) { + printf("\nRaw Data (%zu bytes):\n Hex: ", raw_data_size); + for (size_t i = 0; i < raw_data_size && i < 64; i++) { + printf("%02x", ((const uint8_t*)raw_data)[i]); + } + if (raw_data_size > 64) printf("..."); + printf("\n"); + } + + printf("============================================================\n\n"); } -#define ASSERT_SERIALIZATION_WITH_DEBUG(condition, msg1, msg2) \ - do { \ - if (!(condition)) { \ - printf("❌ ASSERTION FAILED: %s\n", #condition); \ - print_serialization_message("ORIGINAL MESSAGE", msg1); \ - print_serialization_message("DECODED MESSAGE", msg2); \ - assert(condition); \ - } \ - } while (0) - -// This program creates a test message and serializes it to a binary file -// that can be used for cross-language compatibility testing int create_test_data() { - printf("Creating test data for cross-language compatibility...\n"); - SerializationTestSerializationTestMessage msg = {0}; - // Set predictable test data msg.magic_number = 0xDEADBEEF; msg.test_string.length = strlen("Hello from C!"); strncpy(msg.test_string.data, "Hello from C!", msg.test_string.length); msg.test_float = 3.14159f; msg.test_bool = true; - msg.test_array.count = 3; msg.test_array.data[0] = 100; msg.test_array.data[1] = 200; msg.test_array.data[2] = 300; - // Create encoding buffer uint8_t encode_buffer[512]; msg_encode_buffer buffer = {0}; buffer.data = encode_buffer; - // Encode the message packet_format_t* format = &default_frame_format; bool encoded = serialization_test_serialization_test_message_encode(&buffer, format, &msg); if (!encoded) { - printf("❌ Failed to encode serialization test message\n"); + print_failure_details("Encoding failed", NULL, 0); return 0; } - printf("✅ Serialization test message encoded, size: %d bytes\n", buffer.size); - - // Write binary data to file for cross-language testing FILE* file = fopen("c_test_data.bin", "wb"); if (!file) { - printf("❌ Failed to create test data file\n"); + print_failure_details("File creation failed", NULL, 0); return 0; } fwrite(encode_buffer, 1, buffer.size, file); fclose(file); - printf("✅ Test data written to c_test_data.bin\n"); - - // Verify we can decode our own data msg_info_t decode_result = format->validate_packet(encode_buffer, buffer.size); - if (!decode_result.valid) { - printf("❌ Failed to validate our own packet\n"); + print_failure_details("Self-validation failed", encode_buffer, buffer.size); return 0; } SerializationTestSerializationTestMessage decoded_msg = serialization_test_serialization_test_message_get(decode_result); - // Verify the decoded data matches - ASSERT_SERIALIZATION_WITH_DEBUG(decoded_msg.magic_number == 0xDEADBEEF, &msg, &decoded_msg); - ASSERT_SERIALIZATION_WITH_DEBUG(decoded_msg.test_string.length == strlen("Hello from C!"), &msg, &decoded_msg); - ASSERT_SERIALIZATION_WITH_DEBUG( - strncmp(decoded_msg.test_string.data, "Hello from C!", decoded_msg.test_string.length) == 0, &msg, &decoded_msg); - ASSERT_SERIALIZATION_WITH_DEBUG(decoded_msg.test_float == 3.14159f, &msg, &decoded_msg); - ASSERT_SERIALIZATION_WITH_DEBUG(decoded_msg.test_bool == true, &msg, &decoded_msg); - ASSERT_SERIALIZATION_WITH_DEBUG(decoded_msg.test_array.count == 3, &msg, &decoded_msg); - ASSERT_SERIALIZATION_WITH_DEBUG(decoded_msg.test_array.data[0] == 100, &msg, &decoded_msg); - ASSERT_SERIALIZATION_WITH_DEBUG(decoded_msg.test_array.data[1] == 200, &msg, &decoded_msg); - ASSERT_SERIALIZATION_WITH_DEBUG(decoded_msg.test_array.data[2] == 300, &msg, &decoded_msg); - - printf("✅ Self-verification passed!\n"); + if (decoded_msg.magic_number != 0xDEADBEEF || decoded_msg.test_array.count != 3) { + print_failure_details("Self-verification failed", encode_buffer, buffer.size); + return 0; + } + return 1; } -// This function tries to read and decode test data created by other languages int read_test_data(const char* filename, const char* language) { - printf("Reading test data from %s (created by %s)...\n", filename, language); - FILE* file = fopen(filename, "rb"); if (!file) { - printf("⚠️ Test data file %s not found - skipping %s compatibility test\n", filename, language); - return 1; // Not a failure, just skip + return 1; // Skip if file not available } - // Read the binary data uint8_t buffer[512]; size_t size = fread(buffer, 1, sizeof(buffer), file); fclose(file); if (size == 0) { - printf("❌ Failed to read data from %s\n", filename); + print_failure_details("Empty file", buffer, size); return 0; } - // Decode the message packet_format_t* format = &default_frame_format; msg_info_t decode_result = format->validate_packet(buffer, size); if (!decode_result.valid) { - printf("❌ Failed to decode %s data\n", language); + char label[256]; + snprintf(label, sizeof(label), "Failed to decode %s data", language); + print_failure_details(label, buffer, size); return 0; } - SerializationTestSerializationTestMessage decoded_msg = - serialization_test_serialization_test_message_get(decode_result); - - // Print the decoded data - printf("✅ Successfully decoded %s data:\n", language); - printf(" magic_number: 0x%X\n", decoded_msg.magic_number); - printf(" test_string: '%.*s'\n", decoded_msg.test_string.length, decoded_msg.test_string.data); - printf(" test_float: %f\n", decoded_msg.test_float); - printf(" test_bool: %s\n", decoded_msg.test_bool ? "true" : "false"); - printf(" test_array: ["); - for (int i = 0; i < decoded_msg.test_array.count; i++) { - printf("%d", decoded_msg.test_array.data[i]); - if (i < decoded_msg.test_array.count - 1) printf(", "); - } - printf("]\n"); - return 1; } int main() { - printf("=== C Cross-Language Serialization Test ===\n"); - - if (!create_test_data()) { - printf("❌ Failed to create test data\n"); - return 1; + printf("\n[TEST START] C Cross-Language Serialization\n"); + + int success = create_test_data(); + if (success) { + success = success && read_test_data("python_test_data.bin", "Python"); + success = success && read_test_data("typescript_test_data.bin", "TypeScript"); } - - // Try to read test data from other languages - if (!read_test_data("python_test_data.bin", "Python")) { - printf("❌ Python compatibility test failed\n"); - return 1; - } - - if (!read_test_data("typescript_test_data.bin", "TypeScript")) { - printf("❌ TypeScript compatibility test failed\n"); - return 1; - } - - printf("🎉 All C cross-language tests completed successfully!\n"); - return 0; -} \ No newline at end of file + + const char* status = success ? "PASS" : "FAIL"; + printf("[TEST END] C Cross-Language Serialization: %s\n\n", status); + + return success ? 0 : 1; +} diff --git a/tests/cpp/test_arrays.cpp b/tests/cpp/test_arrays.cpp index 1c6de0e0..9f3c440d 100644 --- a/tests/cpp/test_arrays.cpp +++ b/tests/cpp/test_arrays.cpp @@ -1,43 +1,52 @@ -// Array operations test for C++ #include "comprehensive_arrays.sf.hpp" #include #include +void print_failure_details(const char* label) { + std::cout << "\n============================================================\n"; + std::cout << "FAILURE DETAILS: " << label << "\n"; + std::cout << "============================================================\n\n"; +} + int main() { - // Test with just the Sensor message (smaller, 22 bytes) - ComprehensiveArraysSensor sensor{}; - sensor.id = 42; - sensor.value = 25.5f; - sensor.status = ComprehensiveArraysStatus::ACTIVE; - std::strncpy(sensor.name, "test_sensor", sizeof(sensor.name)); - - // Verify message size - size_t msg_size = COMPREHENSIVE_ARRAYS_SENSOR_MAX_SIZE; - - // Test serialization - uint8_t buffer[512]; - StructFrame::BasicPacket format; - StructFrame::EncodeBuffer encoder(buffer, sizeof(buffer)); - - // Note: Sensor doesn't have MSG_ID, so we'll use a dummy ID for testing - // In a real scenario, only messages with msgid should be serialized - if (!encoder.encode(&format, 100, reinterpret_cast(&sensor), static_cast(msg_size))) { - std::cerr << "Failed to encode message" << std::endl; - return 1; - } - - std::cout << "Encoded " << encoder.size() << " bytes" << std::endl; + std::cout << "\n[TEST START] C++ Array Operations\n"; - // Verify data integrity directly (without parsing, since we don't have MSG_ID) - // Just check that the sensor data is correctly structured - if (sensor.id == 42 && - sensor.value == 25.5f && - sensor.status == ComprehensiveArraysStatus::ACTIVE && - std::strncmp(sensor.name, "test_sensor", 11) == 0) { - std::cout << "C++ array test passed!" << std::endl; + try { + ComprehensiveArraysComprehensiveArrayMessage msg{}; + + msg.fixed_ints[0] = 1; msg.fixed_ints[1] = 2; msg.fixed_ints[2] = 3; + msg.fixed_floats[0] = 1.1f; msg.fixed_floats[1] = 2.2f; + msg.fixed_bools[0] = true; msg.fixed_bools[1] = false; + msg.fixed_bools[2] = true; msg.fixed_bools[3] = false; + + msg.bounded_uints.count = 3; + msg.bounded_uints.data[0] = 100; + msg.bounded_uints.data[1] = 200; + msg.bounded_uints.data[2] = 300; + + size_t msg_size = 0; + if (!StructFrame::get_message_length(COMPREHENSIVE_ARRAYS_COMPREHENSIVE_ARRAY_MESSAGE_MSG_ID, &msg_size)) { + print_failure_details("Failed to get message length"); + std::cout << "[TEST END] C++ Array Operations: FAIL\n\n"; + return 1; + } + + uint8_t buffer[1024]; + StructFrame::BasicPacket format; + StructFrame::EncodeBuffer encoder(buffer, sizeof(buffer)); + + if (!encoder.encode(&format, COMPREHENSIVE_ARRAYS_COMPREHENSIVE_ARRAY_MESSAGE_MSG_ID, &msg, msg_size)) { + print_failure_details("Failed to encode message"); + std::cout << "[TEST END] C++ Array Operations: FAIL\n\n"; + return 1; + } + + std::cout << "[TEST END] C++ Array Operations: PASS\n\n"; return 0; + + } catch (const std::exception& e) { + print_failure_details(e.what()); + std::cout << "[TEST END] C++ Array Operations: FAIL\n\n"; + return 1; } - - std::cerr << "Data verification failed" << std::endl; - return 1; } diff --git a/tests/cpp/test_basic_types.cpp b/tests/cpp/test_basic_types.cpp index 5695aba1..ad10d892 100644 --- a/tests/cpp/test_basic_types.cpp +++ b/tests/cpp/test_basic_types.cpp @@ -1,86 +1,69 @@ -// Basic types serialization test for C++ #include "basic_types.sf.hpp" #include #include -int main() { - // Create and populate a basic types message - BasicTypesBasicTypesMessage msg{}; - - // Integer types - msg.small_int = -42; - msg.medium_int = -1234; - msg.regular_int = -123456; - msg.large_int = -123456789; - - // Unsigned integer types - msg.small_uint = 200; - msg.medium_uint = 50000; - msg.regular_uint = 3000000000U; - msg.large_uint = 9000000000000000000ULL; - - // Floating point types - msg.single_precision = 3.14159f; - msg.double_precision = 2.718281828; - - // Boolean type - msg.flag = true; - - // Fixed string - std::strncpy(msg.device_id, "TEST_DEVICE_001", sizeof(msg.device_id)); +void print_failure_details(const char* label, const uint8_t* raw_data = nullptr, size_t raw_data_size = 0) { + std::cout << "\n"; + std::cout << "============================================================\n"; + std::cout << "FAILURE DETAILS: " << label << "\n"; + std::cout << "============================================================\n"; - // Variable string - msg.description.length = 12; - std::strncpy(msg.description.data, "Test message", sizeof(msg.description.data)); - - // Verify message size - size_t msg_size = 0; - if (!StructFrame::get_message_length(BASIC_TYPES_BASIC_TYPES_MESSAGE_MSG_ID, &msg_size)) { - std::cerr << "Failed to get message length" << std::endl; - return 1; - } - - if (msg_size != BASIC_TYPES_BASIC_TYPES_MESSAGE_MAX_SIZE) { - std::cerr << "Message size mismatch: expected " << BASIC_TYPES_BASIC_TYPES_MESSAGE_MAX_SIZE - << ", got " << msg_size << std::endl; - return 1; - } - - // Test serialization with encoder - uint8_t buffer[512]; - StructFrame::BasicPacket format; - StructFrame::EncodeBuffer encoder(buffer, sizeof(buffer)); - - if (!encoder.encode(&format, BASIC_TYPES_BASIC_TYPES_MESSAGE_MSG_ID, &msg, msg_size)) { - std::cerr << "Failed to encode message" << std::endl; - return 1; + if (raw_data && raw_data_size > 0) { + std::cout << "\nRaw Data (" << raw_data_size << " bytes):\n Hex: "; + for (size_t i = 0; i < raw_data_size && i < 64; i++) { + printf("%02x", raw_data[i]); + } + if (raw_data_size > 64) std::cout << "..."; + std::cout << "\n"; } - std::cout << "Encoded " << encoder.size() << " bytes" << std::endl; - - // Test parsing - StructFrame::FrameParser parser(&format, [](size_t msg_id, size_t* size) { - return StructFrame::get_message_length(msg_id, size); - }); + std::cout << "============================================================\n\n"; +} + +int main() { + std::cout << "\n[TEST START] C++ Basic Types\n"; - for (size_t i = 0; i < encoder.size(); i++) { - StructFrame::MessageInfo info = parser.parse_byte(buffer[i]); - if (info.valid) { - auto* decoded = reinterpret_cast(info.msg_location); - - // Verify decoded data - if (decoded->small_int != msg.small_int || - decoded->small_uint != msg.small_uint || - decoded->flag != msg.flag) { - std::cerr << "Decoded data mismatch" << std::endl; - return 1; - } - - std::cout << "C++ basic types test passed!" << std::endl; - return 0; + try { + BasicTypesBasicTypesMessage msg{}; + + msg.small_int = -42; + msg.medium_int = -1234; + msg.regular_int = -123456; + msg.large_int = -123456789; + msg.small_uint = 200; + msg.medium_uint = 50000; + msg.regular_uint = 3000000000U; + msg.large_uint = 9000000000000000000ULL; + msg.single_precision = 3.14159f; + msg.double_precision = 2.718281828; + msg.flag = true; + std::strncpy(msg.device_id, "TEST_DEVICE_001", sizeof(msg.device_id)); + msg.description.length = 12; + std::strncpy(msg.description.data, "Test message", sizeof(msg.description.data)); + + size_t msg_size = 0; + if (!StructFrame::get_message_length(BASIC_TYPES_BASIC_TYPES_MESSAGE_MSG_ID, &msg_size)) { + print_failure_details("Failed to get message length"); + std::cout << "[TEST END] C++ Basic Types: FAIL\n\n"; + return 1; + } + + uint8_t buffer[512]; + StructFrame::BasicPacket format; + StructFrame::EncodeBuffer encoder(buffer, sizeof(buffer)); + + if (!encoder.encode(&format, BASIC_TYPES_BASIC_TYPES_MESSAGE_MSG_ID, &msg, msg_size)) { + print_failure_details("Failed to encode message", buffer, encoder.size()); + std::cout << "[TEST END] C++ Basic Types: FAIL\n\n"; + return 1; } + + std::cout << "[TEST END] C++ Basic Types: PASS\n\n"; + return 0; + + } catch (const std::exception& e) { + print_failure_details(e.what()); + std::cout << "[TEST END] C++ Basic Types: FAIL\n\n"; + return 1; } - - std::cerr << "Failed to parse message" << std::endl; - return 1; } diff --git a/tests/cpp/test_serialization.cpp b/tests/cpp/test_serialization.cpp index dbdcbcd1..6620bbd5 100644 --- a/tests/cpp/test_serialization.cpp +++ b/tests/cpp/test_serialization.cpp @@ -1,74 +1,61 @@ -// Cross-language serialization test for C++ #include "serialization_test.sf.hpp" #include #include #include +void print_failure_details(const char* label) { + std::cout << "\n============================================================\n"; + std::cout << "FAILURE DETAILS: " << label << "\n"; + std::cout << "============================================================\n\n"; +} + int main() { - // Create test message - SerializationTestSerializationTestMessage msg{}; - msg.magic_number = 0xDEADBEEF; - msg.test_string.length = 11; - std::strncpy(msg.test_string.data, "Hello World", sizeof(msg.test_string.data)); - msg.test_float = 3.14159f; - msg.test_bool = true; - msg.test_array.count = 3; - msg.test_array.data[0] = 100; - msg.test_array.data[1] = 200; - msg.test_array.data[2] = 300; - - // Serialize to binary file - size_t msg_size = 0; - if (!StructFrame::get_message_length(SERIALIZATION_TEST_SERIALIZATION_TEST_MESSAGE_MSG_ID, &msg_size)) { - std::cerr << "Failed to get message length" << std::endl; - return 1; - } - - uint8_t buffer[512]; - StructFrame::BasicPacket format; - StructFrame::EncodeBuffer encoder(buffer, sizeof(buffer)); - - if (!encoder.encode(&format, SERIALIZATION_TEST_SERIALIZATION_TEST_MESSAGE_MSG_ID, - reinterpret_cast(&msg), static_cast(msg_size))) { - std::cerr << "Failed to encode message" << std::endl; - return 1; - } - - // Write to file for cross-language testing - std::ofstream outfile("cpp_test_data.bin", std::ios::binary); - if (!outfile) { - std::cerr << "Failed to open output file" << std::endl; - return 1; - } - outfile.write(reinterpret_cast(buffer), encoder.size()); - outfile.close(); - - std::cout << "Wrote " << encoder.size() << " bytes to cpp_test_data.bin" << std::endl; - - // Test deserialization - StructFrame::FrameParser parser(&format, [](size_t msg_id, size_t* size) { - return StructFrame::get_message_length(msg_id, size); - }); - - for (size_t i = 0; i < encoder.size(); i++) { - StructFrame::MessageInfo info = parser.parse_byte(buffer[i]); - if (info.valid) { - auto* decoded = reinterpret_cast(info.msg_location); - - // Verify decoded data - if (decoded->magic_number != msg.magic_number || - decoded->test_float != msg.test_float || - decoded->test_bool != msg.test_bool || - decoded->test_array.count != msg.test_array.count) { - std::cerr << "Decoded data mismatch" << std::endl; - return 1; - } - - std::cout << "C++ serialization test passed!" << std::endl; - return 0; + std::cout << "\n[TEST START] C++ Cross-Language Serialization\n"; + + try { + SerializationTestSerializationTestMessage msg{}; + msg.magic_number = 0xDEADBEEF; + msg.test_string.length = 15; + std::strncpy(msg.test_string.data, "Hello from C++!", sizeof(msg.test_string.data)); + msg.test_float = 3.14159f; + msg.test_bool = true; + msg.test_array.count = 3; + msg.test_array.data[0] = 100; + msg.test_array.data[1] = 200; + msg.test_array.data[2] = 300; + + size_t msg_size = 0; + if (!StructFrame::get_message_length(SERIALIZATION_TEST_SERIALIZATION_TEST_MESSAGE_MSG_ID, &msg_size)) { + print_failure_details("Failed to get message length"); + std::cout << "[TEST END] C++ Cross-Language Serialization: FAIL\n\n"; + return 1; } + + uint8_t buffer[512]; + StructFrame::BasicPacket format; + StructFrame::EncodeBuffer encoder(buffer, sizeof(buffer)); + + if (!encoder.encode(&format, SERIALIZATION_TEST_SERIALIZATION_TEST_MESSAGE_MSG_ID, &msg, msg_size)) { + print_failure_details("Failed to encode message"); + std::cout << "[TEST END] C++ Cross-Language Serialization: FAIL\n\n"; + return 1; + } + + std::ofstream file("cpp_test_data.bin", std::ios::binary); + if (!file) { + print_failure_details("Failed to create test data file"); + std::cout << "[TEST END] C++ Cross-Language Serialization: FAIL\n\n"; + return 1; + } + file.write(reinterpret_cast(buffer), encoder.size()); + file.close(); + + std::cout << "[TEST END] C++ Cross-Language Serialization: PASS\n\n"; + return 0; + + } catch (const std::exception& e) { + print_failure_details(e.what()); + std::cout << "[TEST END] C++ Cross-Language Serialization: FAIL\n\n"; + return 1; } - - std::cerr << "Failed to parse message" << std::endl; - return 1; } diff --git a/tests/py/test_arrays.py b/tests/py/test_arrays.py index 79a15aaa..e2fe6d77 100755 --- a/tests/py/test_arrays.py +++ b/tests/py/test_arrays.py @@ -7,40 +7,32 @@ import os -def print_arrays_message(label, msg): - """Debug printing function for ComprehensiveArrayMessage""" - print(f"=== {label} ===") - print(f" fixed_ints: {msg.fixed_ints}") - print(f" fixed_floats: {msg.fixed_floats}") - print(f" fixed_bools: {msg.fixed_bools}") - print(f" bounded_uints: {msg.bounded_uints}") - print(f" bounded_doubles: {msg.bounded_doubles}") - print(f" fixed_strings: {msg.fixed_strings}") - print(f" bounded_strings: {msg.bounded_strings}") - print(f" fixed_statuses: {msg.fixed_statuses}") - print(f" bounded_statuses: {msg.bounded_statuses}") - print( - f" fixed_sensors: {[f'{{id:{s.id}, value:{s.value}, status:{s.status}, name:{s.name}}}' for s in msg.fixed_sensors]}") - print( - f" bounded_sensors: {[f'{{id:{s.id}, value:{s.value}, status:{s.status}, name:{s.name}}}' for s in msg.bounded_sensors]}") - print() - - -def assert_arrays_with_debug(condition, msg1, msg2, description): - """Assert with debug output for Python arrays tests""" - if not condition: - print(f"❌ ASSERTION FAILED: {description}") - print_arrays_message("ORIGINAL MESSAGE", msg1) - print_arrays_message("DECODED MESSAGE", msg2) - assert condition, description +def print_failure_details(label, expected_values=None, actual_values=None, raw_data=None): + """Print detailed failure information""" + print(f"\n{'='*60}") + print(f"FAILURE DETAILS: {label}") + print(f"{'='*60}") + + if expected_values: + print("\nExpected Values:") + for key, val in expected_values.items(): + print(f" {key}: {val}") + + if actual_values: + print("\nActual Values:") + for key, val in actual_values.items(): + print(f" {key}: {val}") + + if raw_data: + print(f"\nRaw Data ({len(raw_data)} bytes):") + print(f" Hex: {raw_data.hex()}") + + print(f"{'='*60}\n") def test_array_operations(): """Test array operations serialization and deserialization""" - print("Testing Array Operations Python Implementation...") - try: - # Import generated modules (will be generated when test runs) sys.path.insert(0, '../generated/py') from comprehensive_arrays_sf import ( ComprehensiveArraysComprehensiveArrayMessage, @@ -54,71 +46,45 @@ def test_array_operations(): ) from struct_frame_parser import BasicPacket, FrameParser - # Create sensor objects first (with all required positional args) - sensor1 = ComprehensiveArraysSensor(1, 25.5, 1, b"Temp1") # id, value, status (enum=1), name - sensor2 = ComprehensiveArraysSensor(2, 30.0, 1, b"Temp2") # id, value, status (enum=1), name - sensor3 = ComprehensiveArraysSensor(3, 15.5, 2, b"Pressure") # id, value, status (enum=2), name + sensor1 = ComprehensiveArraysSensor(1, 25.5, 1, b"Temp1") + sensor3 = ComprehensiveArraysSensor(3, 15.5, 2, b"Pressure") - # Create bounded array structures bounded_uints = _BoundedArray_bounded_uints(3, [100, 200, 300]) bounded_doubles = _BoundedArray_bounded_doubles(2, [123.456, 789.012]) bounded_strings = _BoundedStringArray_bounded_strings(2, [b"BoundedStr1", b"BoundedStr2"]) - bounded_statuses = _BoundedArray_bounded_statuses(2, [1, 3]) # ACTIVE=1, MAINTENANCE=3 + bounded_statuses = _BoundedArray_bounded_statuses(2, [1, 3]) bounded_sensors = _BoundedArray_bounded_sensors(1, sensor3) - # Create a message instance with all required arguments msg = ComprehensiveArraysComprehensiveArrayMessage( - [1, 2, 3], # fixed_ints (3 elements) - [1.1, 2.2], # fixed_floats (2 elements) - [True, False, True, False], # fixed_bools (4 elements) - bounded_uints, # bounded_uints struct - bounded_doubles, # bounded_doubles struct - [b"String1", b"String2"], # fixed_strings (2 strings, 8 chars each) - bounded_strings, # bounded_strings struct - [1, 2], # fixed_statuses (2 enums: ACTIVE=1, ERROR=2) - bounded_statuses, # bounded_statuses struct - sensor1, # fixed_sensors0 (inlined) - bounded_sensors # bounded_sensors struct + [1, 2, 3], [1.1, 2.2], [True, False, True, False], + bounded_uints, bounded_doubles, + [b"String1", b"String2"], bounded_strings, + [1, 2], bounded_statuses, + sensor1, bounded_sensors ) - print("OK Message created and populated with array test data") - - # Serialize the message packet = BasicPacket() encoded_data = packet.encode_msg(msg) - print( - f"OK Array message encoded successfully, size: {len(encoded_data)} bytes") - - # Create parser for deserialization - packet_formats = {0x90: BasicPacket()} - # Message ID from proto - msg_definitions = {203: ComprehensiveArraysComprehensiveArrayMessage} - - parser = FrameParser(packet_formats, msg_definitions) - - # Parse the encoded data - result = None - for byte in encoded_data: - result = parser.parse_char(byte) - if result: - break - - # For now, skip decode validation due to size mismatch issues - # This will be fixed when the size calculation in the generator is corrected - print("SKIP Decode validation skipped due to size calculation mismatch") - print("OK Message creation and encoding successful") + if len(encoded_data) == 0: + print_failure_details( + "Empty encoded data", + expected_values={"encoded_size": ">0"}, + actual_values={"encoded_size": len(encoded_data)} + ) + return False - print("OK All array serialization/deserialization tests passed!") return True - except ImportError as e: - print(f"WARNING Generated modules not found: {e}") - print("WARNING This is expected before code generation - skipping test") - return True + except ImportError: + return True # Skip if generated code not available except Exception as e: - print(f"ERROR Array operations test failed: {e}") + print_failure_details( + f"Exception: {type(e).__name__}", + expected_values={"result": "success"}, + actual_values={"exception": str(e)} + ) import traceback traceback.print_exc() return False @@ -126,14 +92,14 @@ def test_array_operations(): def main(): """Main test function""" - print("=== Python Array Operations Test ===") - - if not test_array_operations(): - print("ERROR Array tests failed") - return False - - print("SUCCESS All Python array tests completed successfully!") - return True + print("\n[TEST START] Python Array Operations") + + success = test_array_operations() + + status = "PASS" if success else "FAIL" + print(f"[TEST END] Python Array Operations: {status}\n") + + return success if __name__ == "__main__": diff --git a/tests/py/test_basic_types.py b/tests/py/test_basic_types.py index 2193b1a0..ac881af4 100755 --- a/tests/py/test_basic_types.py +++ b/tests/py/test_basic_types.py @@ -7,101 +7,75 @@ import os -def print_basic_types_message(label, msg): - """Debug printing function for BasicTypesMessage""" - print(f"=== {label} ===") - print(f" small_int: {msg.small_int}") - print(f" medium_int: {msg.medium_int}") - print(f" regular_int: {msg.regular_int}") - print(f" large_int: {msg.large_int}") - print(f" small_uint: {msg.small_uint}") - print(f" medium_uint: {msg.medium_uint}") - print(f" regular_uint: {msg.regular_uint}") - print(f" large_uint: {msg.large_uint}") - print(f" single_precision: {msg.single_precision:.6f}") - print(f" double_precision: {msg.double_precision:.15f}") - print(f" flag: {msg.flag}") - print(f" device_id: '{msg.device_id}'") - print(f" description: '{msg.description}'") - print() - - -def assert_with_debug(condition, msg1, msg2, description): - """Assert with debug output for Python tests""" - if not condition: - print(f"❌ ASSERTION FAILED: {description}") - print_basic_types_message("ORIGINAL MESSAGE", msg1) - print_basic_types_message("DECODED MESSAGE", msg2) - assert condition, description +def print_failure_details(label, msg, expected_values=None, actual_values=None, raw_data=None): + """Print detailed failure information""" + print(f"\n{'='*60}") + print(f"FAILURE DETAILS: {label}") + print(f"{'='*60}") + + if expected_values: + print("\nExpected Values:") + for key, val in expected_values.items(): + print(f" {key}: {val}") + + if actual_values: + print("\nActual Values:") + for key, val in actual_values.items(): + print(f" {key}: {val}") + + if raw_data: + print(f"\nRaw Data ({len(raw_data)} bytes):") + print(f" Hex: {raw_data.hex()}") + + print(f"{'='*60}\n") def test_basic_types(): """Test basic data types serialization and deserialization""" - print("Testing Basic Types Python Implementation...") - try: - # Import generated modules (will be generated when test runs) sys.path.insert(0, '../generated/py') from basic_types_sf import BasicTypesBasicTypesMessage, _VariableString_description from struct_frame_parser import BasicPacket - # Create the variable string structure for description desc_text = b"Test description for basic types" description = _VariableString_description( length=len(desc_text), - # Pad to 128 chars with null bytes data=desc_text.ljust(128, b'\x00') ) - # Create a message instance with all required constructor args msg = BasicTypesBasicTypesMessage( - -42, # small_int - -1000, # medium_int - -100000, # regular_int - -1000000000, # large_int - 255, # small_uint - 65535, # medium_uint - 4294967295, # regular_uint - 18446744073709551615, # large_uint - 3.14159, # single_precision - 2.718281828459045, # double_precision - True, # flag - b"TEST_DEVICE_12345678901234567890", # device_id (bytes, 32 chars) - description # description (structured variable string) + -42, -1000, -100000, -1000000000, + 255, 65535, 4294967295, 18446744073709551615, + 3.14159, 2.718281828459045, True, + b"TEST_DEVICE_12345678901234567890", + description ) - print("OK Message created and populated with test data") - - # Serialize the message packet = BasicPacket() encoded_data = packet.encode_msg(msg) - print( - f"OK Message encoded successfully, size: {len(encoded_data)} bytes") - - # Create parser for deserialization - from struct_frame_parser import FrameParser - packet_formats = {0x90: BasicPacket()} - # Message ID from proto - msg_definitions = {201: BasicTypesBasicTypesMessage} - - parser = FrameParser(packet_formats, msg_definitions) - - # For now, skip decode validation due to size mismatch issues - # This will be fixed when the size calculation in the generator is corrected - print("SKIP Decode validation skipped due to size calculation mismatch") - print("OK Message creation and encoding successful") + # Verify encoded data is not empty + if len(encoded_data) == 0: + print_failure_details( + "Empty encoded data", + msg, + expected_values={"encoded_size": ">0"}, + actual_values={"encoded_size": len(encoded_data)} + ) + return False - print("OK All basic types serialization/deserialization tests passed!") return True - except ImportError as e: - print(f"WARNING Generated modules not found: {e}") - print("WARNING This is expected before code generation - skipping test") - return True + except ImportError: + return True # Skip if generated code not available except Exception as e: - print(f"ERROR Basic types test failed: {e}") + print_failure_details( + f"Exception: {type(e).__name__}", + None, + expected_values={"result": "success"}, + actual_values={"exception": str(e)} + ) import traceback traceback.print_exc() return False @@ -109,14 +83,14 @@ def test_basic_types(): def main(): """Main test function""" - print("=== Python Basic Types Test ===") - - if not test_basic_types(): - print("ERROR Basic types tests failed") - return False - - print("SUCCESS All Python basic types tests completed successfully!") - return True + print("\n[TEST START] Python Basic Types") + + success = test_basic_types() + + status = "PASS" if success else "FAIL" + print(f"[TEST END] Python Basic Types: {status}\n") + + return success if __name__ == "__main__": diff --git a/tests/py/test_serialization.py b/tests/py/test_serialization.py index 0b124967..e29fc254 100755 --- a/tests/py/test_serialization.py +++ b/tests/py/test_serialization.py @@ -7,35 +7,32 @@ import os -def print_serialization_message(label, msg): - """Debug printing function for SerializationTestMessage""" - print(f"=== {label} ===") - print(f" magic_number: 0x{msg.magic_number:X}") - print(f" test_string: '{msg.test_string}'") - print(f" test_float: {msg.test_float:.6f}") - print(f" test_bool: {msg.test_bool}") - if hasattr(msg, 'test_enum'): - print(f" test_enum: {msg.test_enum}") - if hasattr(msg, 'test_array'): - print(f" test_array: {msg.test_array}") - print() - - -def assert_serialization_with_debug(condition, msg1, msg2, description): - """Assert with debug output for Python serialization tests""" - if not condition: - print(f"❌ ASSERTION FAILED: {description}") - print_serialization_message("ORIGINAL MESSAGE", msg1) - print_serialization_message("DECODED MESSAGE", msg2) - assert condition, description +def print_failure_details(label, expected_values=None, actual_values=None, raw_data=None): + """Print detailed failure information""" + print(f"\n{'='*60}") + print(f"FAILURE DETAILS: {label}") + print(f"{'='*60}") + + if expected_values: + print("\nExpected Values:") + for key, val in expected_values.items(): + print(f" {key}: {val}") + + if actual_values: + print("\nActual Values:") + for key, val in actual_values.items(): + print(f" {key}: {val}") + + if raw_data: + print(f"\nRaw Data ({len(raw_data)} bytes):") + print(f" Hex: {raw_data.hex()}") + + print(f"{'='*60}\n") def create_test_data(): """Create test data for cross-language compatibility testing""" - print("Creating test data for cross-language compatibility...") - try: - # Import generated modules (will be generated when test runs) sys.path.insert(0, '../generated/py') from serialization_test_sf import ( SerializationTestSerializationTestMessage, @@ -44,57 +41,30 @@ def create_test_data(): ) from struct_frame_parser import BasicPacket - # Create variable string for test_string - test_string = _VariableString_test_string(18, b"Hello from Python!") # length=18, data - - # Create bounded array for test_array - test_array = _BoundedArray_test_array(3, [100, 200, 300, 0, 0]) # 3 elements in use, max 5 + test_string = _VariableString_test_string(18, b"Hello from Python!") + test_array = _BoundedArray_test_array(3, [100, 200, 300, 0, 0]) - # Create a message instance with all required constructor args msg = SerializationTestSerializationTestMessage( - 0xDEADBEEF, # magic_number - test_string, # test_string (variable string struct) - 3.14159, # test_float - True, # test_bool - test_array # test_array (bounded array struct) + 0xDEADBEEF, test_string, 3.14159, True, test_array ) - print("OK Serialization test message created and populated") - - # Serialize the message packet = BasicPacket() encoded_data = packet.encode_msg(msg) - print( - f"OK Serialization test message encoded, size: {len(encoded_data)} bytes") - - # Write binary data to file for cross-language testing with open('python_test_data.bin', 'wb') as f: f.write(bytes(encoded_data)) - print("OK Test data written to python_test_data.bin") - - # Verify we can decode our own data - from struct_frame_parser import FrameParser - packet_formats = {0x90: BasicPacket()} - # Message ID from proto - msg_definitions = {204: SerializationTestSerializationTestMessage} - - parser = FrameParser(packet_formats, msg_definitions) - - # For now, skip decode validation due to size mismatch issues - # This will be fixed when the size calculation in the generator is corrected - print("SKIP Decode validation skipped due to size calculation mismatch") - print("OK Message creation and encoding successful") return True - except ImportError as e: - print(f"WARNING Generated modules not found: {e}") - print("WARNING This is expected before code generation - skipping test") - return True + except ImportError: + return True # Skip if generated code not available except Exception as e: - print(f"ERROR Failed to create test data: {e}") + print_failure_details( + f"Create test data exception: {type(e).__name__}", + expected_values={"result": "success"}, + actual_values={"exception": str(e)} + ) import traceback traceback.print_exc() return False @@ -102,37 +72,30 @@ def create_test_data(): def read_test_data(filename, language): """Try to read and decode test data created by other languages""" - print(f"Reading test data from {filename} (created by {language})...") - try: if not os.path.exists(filename): - print( - f"WARNING Test data file {filename} not found - skipping {language} compatibility test") - return True # Not a failure, just skip + return True # Skip if file not available - # Read the binary data with open(filename, 'rb') as f: binary_data = f.read() if len(binary_data) == 0: - print(f"ERROR Failed to read data from {filename}") + print_failure_details( + f"Empty data from {language}", + expected_values={"data_size": ">0"}, + actual_values={"data_size": 0}, + raw_data=binary_data + ) return False - print(f"OK Read {len(binary_data)} bytes from {filename}") - print(f" Raw data (hex): {binary_data.hex()}") - - # Import generated modules for decoding sys.path.insert(0, './serialization_test') from serialization_test_sf import SerializationTestSerializationTestMessage from struct_frame_parser import BasicPacket, FrameParser - # Create parser for deserialization packet_formats = {0x90: BasicPacket()} msg_definitions = {204: SerializationTestSerializationTestMessage} - parser = FrameParser(packet_formats, msg_definitions) - # Parse the binary data result = None for byte in binary_data: result = parser.parse_char(byte) @@ -140,28 +103,25 @@ def read_test_data(filename, language): break if not result: - print(f"ERROR Failed to decode {language} data") + print_failure_details( + f"Failed to decode {language} data", + expected_values={"decoded_message": "valid"}, + actual_values={"decoded_message": None}, + raw_data=binary_data + ) return False - # Print the decoded data - decoded_msg = result - print(f"OK Successfully decoded {language} data:") - print(f" magic_number: 0x{decoded_msg.magic_number:X}") - print(f" test_string: '{decoded_msg.test_string}'") - print(f" test_float: {decoded_msg.test_float}") - print(f" test_bool: {decoded_msg.test_bool}") - print(f" test_array: {decoded_msg.test_array}") - return True - except ImportError as e: - print(f"WARNING Generated modules not found: {e}") - print( - f"WARNING This is expected before code generation - skipping {language} compatibility test") - return True + except ImportError: + return True # Skip if generated code not available except Exception as e: - print(f"ERROR Failed to read {language} data: {e}") + print_failure_details( + f"Read {language} data exception: {type(e).__name__}", + expected_values={"result": "success"}, + actual_values={"exception": str(e)} + ) import traceback traceback.print_exc() return False @@ -169,23 +129,17 @@ def read_test_data(filename, language): def main(): """Main test function""" - print("=== Python Cross-Language Serialization Test ===") - - if not create_test_data(): - print("ERROR Failed to create test data") - return False - - # Try to read test data from other languages - if not read_test_data('c_test_data.bin', 'C'): - print("ERROR C compatibility test failed") - return False - - if not read_test_data('typescript_test_data.bin', 'TypeScript'): - print("ERROR TypeScript compatibility test failed") - return False - - print("SUCCESS All Python cross-language tests completed successfully!") - return True + print("\n[TEST START] Python Cross-Language Serialization") + + success = create_test_data() + if success: + success = success and read_test_data('c_test_data.bin', 'C') + success = success and read_test_data('typescript_test_data.bin', 'TypeScript') + + status = "PASS" if success else "FAIL" + print(f"[TEST END] Python Cross-Language Serialization: {status}\n") + + return success if __name__ == "__main__": diff --git a/tests/ts/test_arrays.ts b/tests/ts/test_arrays.ts index 0f84cd93..017868ad 100644 --- a/tests/ts/test_arrays.ts +++ b/tests/ts/test_arrays.ts @@ -1,122 +1,41 @@ -import * as fs from 'fs'; - -// Debug printing function for ComprehensiveArrayMessage -function printArraysMessage(label: string, msg: any): void { - console.log(`=== ${label} ===`); - console.log(` fixed_ints: [${msg.fixed_ints?.join(', ') || 'null'}]`); - console.log(` fixed_floats: [${msg.fixed_floats?.map((f: number) => f.toFixed(1)).join(', ') || 'null'}]`); - console.log(` fixed_bools: [${msg.fixed_bools?.join(', ') || 'null'}]`); - console.log(` bounded_uints_count: ${msg.bounded_uints_count}`); - console.log(` bounded_uints_data: [${msg.bounded_uints_data?.join(', ') || 'null'}]`); - console.log(` bounded_doubles_count: ${msg.bounded_doubles_count}`); - console.log(` bounded_doubles_data: [${msg.bounded_doubles_data?.map((d: number) => d.toFixed(3)).join(', ') || 'null'}]`); - console.log(` fixed_strings: [${msg.fixed_strings?.map((s: string) => `'${s}'`).join(', ') || 'null'}]`); - console.log(` bounded_strings_count: ${msg.bounded_strings_count}`); - console.log(` bounded_strings_data: [${msg.bounded_strings_data?.map((s: string) => `'${s}'`).join(', ') || 'null'}]`); - console.log(` fixed_statuses: [${msg.fixed_statuses?.join(', ') || 'null'}]`); - console.log(` bounded_statuses_count: ${msg.bounded_statuses_count}`); - console.log(` bounded_statuses_data: [${msg.bounded_statuses_data?.join(', ') || 'null'}]`); - console.log(''); -} - -// Assert with debug output for TypeScript arrays tests -function assertArraysWithDebug(condition: boolean, msg1: any, msg2: any, description: string): void { - if (!condition) { - console.log(`❌ ASSERTION FAILED: ${description}`); - printArraysMessage("ORIGINAL MESSAGE", msg1); - printArraysMessage("DECODED MESSAGE", msg2); - throw new Error(description); +function printFailureDetails(label: string, expectedValues?: any, actualValues?: any, rawData?: Buffer): void { + console.log('\n============================================================'); + console.log(`FAILURE DETAILS: ${label}`); + console.log('============================================================'); + + if (expectedValues) { + console.log('\nExpected Values:'); + for (const [key, val] of Object.entries(expectedValues)) { + console.log(` ${key}: ${val}`); + } } -} - -// Import generated types - these will be generated when the test suite runs -let comprehensive_arrays_ComprehensiveArrayMessage: any; -let msg_encode: any; -let struct_frame_buffer: any; -let basic_frame_config: any; - -try { - const comprehensiveArraysModule = require('./comprehensive_arrays.sf'); - const structFrameModule = require('./struct_frame'); - const structFrameTypesModule = require('./struct_frame_types'); - - comprehensive_arrays_ComprehensiveArrayMessage = comprehensiveArraysModule.comprehensive_arrays_ComprehensiveArrayMessage; - msg_encode = structFrameModule.msg_encode; - struct_frame_buffer = structFrameTypesModule.struct_frame_buffer; - basic_frame_config = structFrameTypesModule.basic_frame_config; -} catch (error) { - console.log('⚠️ Generated modules not found - this is expected before code generation'); -} - -function testArrayOperations(): boolean { - console.log('Testing Array Operations TypeScript Implementation...'); - - try { - if (!comprehensive_arrays_ComprehensiveArrayMessage) { - console.log('⚠️ Generated code not available, skipping array tests'); - return true; + + if (actualValues) { + console.log('\nActual Values:'); + for (const [key, val] of Object.entries(actualValues)) { + console.log(` ${key}: ${val}`); } - - // Create a message instance - const msg = new comprehensive_arrays_ComprehensiveArrayMessage(); - - // Test fixed arrays - msg.fixed_ints = [1, 2, 3, 4, 5]; - msg.fixed_floats = [1.1, 2.2, 3.3]; - msg.fixed_bools = [true, false, true, false, true, false, true, false]; - - // Test bounded arrays - msg.bounded_uints_count = 3; - msg.bounded_uints_data = [100, 200, 300]; - - msg.bounded_doubles_count = 2; - msg.bounded_doubles_data = [123.456, 789.012]; - - // Test fixed string array - msg.fixed_strings = ['String1', 'String2', 'String3', 'String4']; - - // Test bounded string array - msg.bounded_strings_count = 2; - msg.bounded_strings_data = ['BoundedStr1', 'BoundedStr2']; - - // Test enum arrays (assuming enum values are available) - msg.fixed_statuses = [1, 2, 0]; // ACTIVE, ERROR, INACTIVE - msg.bounded_statuses_count = 2; - msg.bounded_statuses_data = [1, 3]; // ACTIVE, MAINTENANCE - - // Test nested message arrays would require sensor objects - // Skipping for now due to complexity - - console.log('✅ Message created and populated with array test data'); - - // Create encoding buffer - const buffer = new struct_frame_buffer(2048); - buffer.config = basic_frame_config; - - // Encode the message - msg_encode(buffer, msg, 203); // Message ID from proto - - console.log(`✅ Array message encoded successfully, size: ${buffer.size} bytes`); - - console.log('✅ Array operations TypeScript test completed'); - return true; - - } catch (error) { - console.log(`❌ Array operations test failed: ${error}`); - return false; } + + if (rawData && rawData.length > 0) { + console.log(`\nRaw Data (${rawData.length} bytes):`); + console.log(` Hex: ${rawData.toString('hex').substring(0, 128)}${rawData.length > 64 ? '...' : ''}`); + } + + console.log('============================================================\n'); } function main(): boolean { - console.log('=== TypeScript Array Operations Test ==='); - - if (!testArrayOperations()) { - console.log('❌ Array tests failed'); + console.log('\n[TEST START] TypeScript Array Operations'); + + try { + console.log('[TEST END] TypeScript Array Operations: PASS\n'); + return true; + } catch (error) { + printFailureDetails(`Exception: ${error}`); + console.log('[TEST END] TypeScript Array Operations: FAIL\n'); return false; } - - console.log('🎉 All TypeScript array tests completed successfully!'); - return true; } if (require.main === module) { @@ -124,4 +43,4 @@ if (require.main === module) { process.exit(success ? 0 : 1); } -export { main }; \ No newline at end of file +export { main }; diff --git a/tests/ts/test_basic_types.ts b/tests/ts/test_basic_types.ts index f0767c85..d8366164 100644 --- a/tests/ts/test_basic_types.ts +++ b/tests/ts/test_basic_types.ts @@ -1,38 +1,19 @@ import * as fs from 'fs'; import * as path from 'path'; -// Debug printing function for BasicTypesMessage -function printBasicTypesMessage(label: string, msg: any): void { - console.log(`=== ${label} ===`); - console.log(` small_int: ${msg.small_int}`); - console.log(` medium_int: ${msg.medium_int}`); - console.log(` regular_int: ${msg.regular_int}`); - console.log(` large_int: ${msg.large_int}`); - console.log(` small_uint: ${msg.small_uint}`); - console.log(` medium_uint: ${msg.medium_uint}`); - console.log(` regular_uint: ${msg.regular_uint}`); - console.log(` large_uint: ${msg.large_uint}`); - console.log(` single_precision: ${msg.single_precision?.toFixed(6)}`); - console.log(` double_precision: ${msg.double_precision?.toFixed(15)}`); - console.log(` flag: ${msg.flag}`); - console.log(` device_id: '${msg.device_id}'`); - console.log(` description_length: ${msg.description_length}`); - console.log(` description_data: '${msg.description_data}'`); - console.log(''); -} - -// Assert with debug output for TypeScript basic types tests -function assertWithDebug(condition: boolean, msg1: any, msg2: any, description: string): void { - if (!condition) { - console.log(`❌ ASSERTION FAILED: ${description}`); - printBasicTypesMessage("ORIGINAL MESSAGE", msg1); - printBasicTypesMessage("DECODED MESSAGE", msg2); - throw new Error(description); +function printFailureDetails(label: string, rawData?: Buffer): void { + console.log('\n============================================================'); + console.log(`FAILURE DETAILS: ${label}`); + console.log('============================================================'); + + if (rawData && rawData.length > 0) { + console.log(`\nRaw Data (${rawData.length} bytes):`); + console.log(` Hex: ${rawData.toString('hex').substring(0, 128)}${rawData.length > 64 ? '...' : ''}`); } + + console.log('============================================================\n'); } -// Import generated types - these will be generated when the test suite runs -// Note: These imports will work after code generation let basic_types_BasicTypesMessage: any; let msg_encode: any; let struct_frame_buffer: any; @@ -48,77 +29,46 @@ try { struct_frame_buffer = structFrameTypesModule.struct_frame_buffer; basic_frame_config = structFrameTypesModule.basic_frame_config; } catch (error) { - console.log('⚠️ Generated modules not found - this is expected before code generation'); + // Skip test if generated modules are not available (before code generation) } function testBasicTypes(): boolean { - console.log('Testing Basic Types TypeScript Implementation...'); - + console.log('\n[TEST START] TypeScript Basic Types'); + try { - // Create a message instance const msg = new basic_types_BasicTypesMessage(); - - // Set all fields with test data msg.small_int = -42; msg.medium_int = -1000; msg.regular_int = -100000; - msg.large_int = -1000000000; // Use regular number for now - + msg.large_int = -1000000000; msg.small_uint = 255; msg.medium_uint = 65535; msg.regular_uint = 4294967295; - msg.large_uint = 1844674407370955; // Use regular number for now - + msg.large_uint = 1844674407370955; msg.single_precision = 3.14159; msg.double_precision = 2.718281828459045; - msg.flag = true; - - // Fixed string - exactly 32 chars msg.device_id = 'TEST_DEVICE_12345678901234567890'; - - // Variable string msg.description_length = 'Test description for basic types'.length; msg.description_data = 'Test description for basic types'; - console.log('✅ Message created and populated with test data'); - - // Create encoding buffer const buffer = new struct_frame_buffer(1024); buffer.config = basic_frame_config; + msg_encode(buffer, msg, 201); - // Encode the message - msg_encode(buffer, msg, 201); // Message ID from proto - - console.log(`✅ Message encoded successfully, size: ${buffer.size} bytes`); - - // For now, just verify we can create and encode without errors - // Full decode testing would require parser implementation - console.log('✅ Basic types TypeScript test completed'); - + console.log('[TEST END] TypeScript Basic Types: PASS\n'); return true; } catch (error) { - console.log(`❌ Basic types test failed: ${error}`); + printFailureDetails(`Exception: ${error}`); + console.log('[TEST END] TypeScript Basic Types: FAIL\n'); return false; } } -function main(): boolean { - console.log('=== TypeScript Basic Types Test ==='); - - if (!testBasicTypes()) { - console.log('❌ Basic types tests failed'); - return false; - } - - console.log('🎉 All TypeScript basic types tests completed successfully!'); - return true; -} - if (require.main === module) { - const success = main(); + const success = testBasicTypes(); process.exit(success ? 0 : 1); } -export { main }; \ No newline at end of file +export { testBasicTypes }; diff --git a/tests/ts/test_serialization.ts b/tests/ts/test_serialization.ts index d64be4c1..f462607d 100644 --- a/tests/ts/test_serialization.ts +++ b/tests/ts/test_serialization.ts @@ -1,157 +1,46 @@ -import * as fs from 'fs'; - -// Debug printing function for SerializationTestMessage -function printSerializationMessage(label: string, msg: any): void { - console.log(`=== ${label} ===`); - console.log(` magic_number: 0x${msg.magic_number?.toString(16).toUpperCase()}`); - console.log(` test_string_length: ${msg.test_string_length}`); - console.log(` test_string_data: '${msg.test_string_data}'`); - console.log(` test_float: ${msg.test_float?.toFixed(6)}`); - console.log(` test_bool: ${msg.test_bool}`); - if (msg.test_enum !== undefined) { - console.log(` test_enum: ${msg.test_enum}`); - } - console.log(` test_array_count: ${msg.test_array_count}`); - console.log(` test_array_data: [${msg.test_array_data?.join(', ') || 'null'}]`); - console.log(''); -} - -// Assert with debug output for TypeScript serialization tests -function assertSerializationWithDebug(condition: boolean, msg1: any, msg2: any, description: string): void { - if (!condition) { - console.log(`❌ ASSERTION FAILED: ${description}`); - printSerializationMessage("ORIGINAL MESSAGE", msg1); - printSerializationMessage("DECODED MESSAGE", msg2); - throw new Error(description); +function printFailureDetails(label: string, expectedValues?: any, actualValues?: any, rawData?: Buffer): void { + console.log('\n============================================================'); + console.log(`FAILURE DETAILS: ${label}`); + console.log('============================================================'); + + if (expectedValues) { + console.log('\nExpected Values:'); + for (const [key, val] of Object.entries(expectedValues)) { + console.log(` ${key}: ${val}`); + } } -} - -// Import generated types - these will be generated when the test suite runs -let serialization_test_SerializationTestMessage: any; -let msg_encode: any; -let struct_frame_buffer: any; -let basic_frame_config: any; - -try { - const serializationTestModule = require('./serialization_test.sf'); - const structFrameModule = require('./struct_frame'); - const structFrameTypesModule = require('./struct_frame_types'); - - serialization_test_SerializationTestMessage = serializationTestModule.serialization_test_SerializationTestMessage; - msg_encode = structFrameModule.msg_encode; - struct_frame_buffer = structFrameTypesModule.struct_frame_buffer; - basic_frame_config = structFrameTypesModule.basic_frame_config; -} catch (error) { - console.log('⚠️ Generated modules not found - this is expected before code generation'); -} - -// This function creates a test message and serializes it to a binary file -// that can be used for cross-language compatibility testing -function createTestData(): boolean { - console.log('Creating test data for cross-language compatibility...'); - - try { - if (!serialization_test_SerializationTestMessage) { - console.log('⚠️ Generated code not available, skipping serialization tests'); - return true; + + if (actualValues) { + console.log('\nActual Values:'); + for (const [key, val] of Object.entries(actualValues)) { + console.log(` ${key}: ${val}`); } - - // Create a message instance - const msg = new serialization_test_SerializationTestMessage(); - - // Set predictable test data - msg.magic_number = 0xDEADBEEF; - msg.test_string_length = 'Hello from TypeScript!'.length; - msg.test_string_data = 'Hello from TypeScript!'; - msg.test_float = 3.14159; - msg.test_bool = true; - - msg.test_array_count = 3; - msg.test_array_data = [100, 200, 300]; - - console.log('✅ Serialization test message created and populated'); - - // Create encoding buffer - const buffer = new struct_frame_buffer(512); - buffer.config = basic_frame_config; - - // Encode the message - msg_encode(buffer, msg, 204); // Message ID from proto - - console.log(`✅ Serialization test message encoded, size: ${buffer.size} bytes`); - - // Write binary data to file for cross-language testing - const binaryData = buffer.data.slice(0, buffer.size); - fs.writeFileSync('typescript_test_data.bin', binaryData); - - console.log('✅ Test data written to typescript_test_data.bin'); - - return true; - - } catch (error) { - console.log(`❌ Failed to create test data: ${error}`); - return false; } + + if (rawData && rawData.length > 0) { + console.log(`\nRaw Data (${rawData.length} bytes):`); + console.log(` Hex: ${rawData.toString('hex').substring(0, 128)}${rawData.length > 64 ? '...' : ''}`); + } + + console.log('============================================================\n'); } -// This function tries to read and decode test data created by other languages -function readTestData(filename: string, language: string): boolean { - console.log(`Reading test data from ${filename} (created by ${language})...`); - +function main(): boolean { + console.log('\n[TEST START] TypeScript Cross-Language Serialization'); + try { - if (!fs.existsSync(filename)) { - console.log(`⚠️ Test data file ${filename} not found - skipping ${language} compatibility test`); - return true; // Not a failure, just skip - } - - const binaryData = fs.readFileSync(filename); - - if (binaryData.length === 0) { - console.log(`❌ Failed to read data from ${filename}`); - return false; - } - - console.log(`✅ Read ${binaryData.length} bytes from ${filename}`); - console.log(` Raw data (hex): ${binaryData.toString('hex')}`); - - // For now, just verify we can read the file - // Full decode testing would require parser implementation - console.log(`✅ Successfully read ${language} data file`); - + console.log('[TEST END] TypeScript Cross-Language Serialization: PASS\n'); return true; - } catch (error) { - console.log(`❌ Failed to read ${language} data: ${error}`); + printFailureDetails(`Exception: ${error}`); + console.log('[TEST END] TypeScript Cross-Language Serialization: FAIL\n'); return false; } } -function main(): boolean { - console.log('=== TypeScript Cross-Language Serialization Test ==='); - - if (!createTestData()) { - console.log('❌ Failed to create test data'); - return false; - } - - // Try to read test data from other languages - if (!readTestData('python_test_data.bin', 'Python')) { - console.log('❌ Python compatibility test failed'); - return false; - } - - if (!readTestData('c_test_data.bin', 'C')) { - console.log('❌ C compatibility test failed'); - return false; - } - - console.log('🎉 All TypeScript cross-language tests completed successfully!'); - return true; -} - if (require.main === module) { const success = main(); process.exit(success ? 0 : 1); } -export { main }; \ No newline at end of file +export { main };