Skip to content

Add unit tests for sSerialAttrToStr#10

Closed
zknpr wants to merge 1 commit intosecurity-fixes-and-community-prsfrom
add-serial-tests-4500608520212156328
Closed

Add unit tests for sSerialAttrToStr#10
zknpr wants to merge 1 commit intosecurity-fixes-and-community-prsfrom
add-serial-tests-4500608520212156328

Conversation

@zknpr
Copy link
Copy Markdown
Owner

@zknpr zknpr commented Feb 7, 2026

This PR adds unit tests for sSerialAttrToStr in src/serial.c. It introduces a new tests directory and integrates testing into the CMake build system.

Changes:

  • Added tests/test_serial.c: Contains test cases for sSerialAttrToStr.
  • Modified CMakeLists.txt: Enabled testing and added test_serial executable.

Verification:

  • Ran tests locally and verified they pass.
  • Verified compilation and linking of the test executable.
  • Handled potential 32-bit/64-bit differences in test cases.

PR created automatically by Jules for task 4500608520212156328 started by @zknpr

- Create `tests/test_serial.c` with test cases covering standard, complex, edge, and overflow scenarios.
- Update `CMakeLists.txt` to enable testing and add `test_serial` target.
- Verify tests pass and handle potential truncation correctly.

Co-authored-by: zknpr <96851588+zknpr@users.noreply.github.com>
@google-labs-jules
Copy link
Copy Markdown

👋 Jules, reporting for duty! I'm here to lend a hand with this pull request.

When you start a review, I'll add a 👀 emoji to each comment to let you know I've read it. I'll focus on feedback directed at me and will do my best to stay out of conversations between you and other bots or reviewers to keep the noise down.

I'll push a commit with your requested changes shortly after. Please note there might be a delay between these steps, but rest assured I'm on the job!

For more direct control, you can switch me to Reactive Mode. When this mode is on, I will only act on comments where you specifically mention me with @jules. You can find this option in the Pull Request section of your global Jules UI settings. You can always switch back!

New to Jules? Learn more at jules.google/docs.


For security, I will only act on instructions from the user who triggered this task.

@gemini-code-assist
Copy link
Copy Markdown

Summary of Changes

Hello @zknpr, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request significantly enhances the reliability of the sSerialAttrToStr function by introducing a dedicated suite of unit tests. The changes involve setting up a new testing framework within the existing CMake build system and creating a new test file that covers various scenarios for serial attribute string conversion. This ensures that future modifications to the function can be validated automatically, reducing the risk of regressions and improving overall code quality.

Highlights

  • Unit Test Introduction: Added comprehensive unit tests for the sSerialAttrToStr function, ensuring its correctness across various serial port configurations.
  • New Test Directory: Introduced a new tests directory to house the unit test files, promoting better organization of testing-related code.
  • CMake Integration: Integrated the new unit tests into the CMake build system, enabling automated testing as part of the project's build process.

🧠 New Feature in Public Preview: You can now enable Memory to help Gemini Code Assist learn from your team's feedback. This makes future code reviews more consistent and personalized to your project's style. Click here to enable Memory in your admin console.

Changelog
  • CMakeLists.txt
    • Enabled testing functionality using enable_testing().
    • Added a new executable target test_serial which compiles tests/test_serial.c and links it with src/serial.c.
    • Configured test_serial to include headers from the src directory.
    • Registered test_serial as a CTest test, allowing it to be run with ctest.
  • tests/test_serial.c
    • New file created to contain unit tests for the sSerialAttrToStr function.
    • Includes test cases for standard serial configurations, complex settings (e.g., parity, flow control), RS485 specific flow control, and different stop bit values.
    • Contains tests to verify handling of truncation for large baud rates and potential overflow scenarios, with consideration for 32-bit/64-bit system differences.
    • Uses assert for verifying test outcomes and prints results to the console.
Activity
  • The author ran tests locally and verified that all test cases passed.
  • Compilation and linking of the new test executable were verified.
  • Potential differences between 32-bit and 64-bit systems were considered and handled in the test cases.
  • The pull request was automatically created by Jules for a task started by @zknpr.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

Copy link
Copy Markdown

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces unit tests for the sSerialAttrToStr function, which is a great addition for improving code quality and reliability. The changes to CMakeLists.txt correctly integrate the new tests into the build system. My review focuses on improving the structure and robustness of the new test file tests/test_serial.c. I've suggested refactoring the test runner to ensure all tests are executed and to provide a clear summary of results, which is a common best practice for unit testing.

Comment on lines +1 to +107
#include <stdio.h>
#include <string.h>
#include <assert.h>
#include "serial.h"

void test_standard_case() {
xSerialIos ios;
ios.baud = 9600;
ios.dbits = SERIAL_DATABIT_8;
ios.parity = SERIAL_PARITY_NONE;
ios.sbits = SERIAL_STOPBIT_ONE;
ios.flow = SERIAL_FLOW_NONE;

const char *result = sSerialAttrToStr(&ios);
// Format: BBBBBBBBBB-DPSF
// " 9600-8N1 "
printf("Test Standard Case: '%s'\n", result);
assert(strcmp(result, " 9600-8N1 ") == 0);
}

void test_complex_case() {
xSerialIos ios;
ios.baud = 115200;
ios.dbits = SERIAL_DATABIT_8;
ios.parity = SERIAL_PARITY_EVEN;
ios.sbits = SERIAL_STOPBIT_TWO;
ios.flow = SERIAL_FLOW_RTSCTS;

const char *result = sSerialAttrToStr(&ios);
// " 115200-8E2H"
printf("Test Complex Case: '%s'\n", result);
assert(strcmp(result, " 115200-8E2H") == 0);
}

void test_rs485_case() {
xSerialIos ios;
ios.baud = 19200;
ios.dbits = SERIAL_DATABIT_8;
ios.parity = SERIAL_PARITY_NONE;
ios.sbits = SERIAL_STOPBIT_ONE;
ios.flow = SERIAL_FLOW_RS485_RTS_AFTER_SEND;

const char *result = sSerialAttrToStr(&ios);
// " 19200-8N1R"
printf("Test RS485 Case: '%s'\n", result);
assert(strcmp(result, " 19200-8N1R") == 0);
}

void test_stopbit_onehalf_case() {
xSerialIos ios;
ios.baud = 9600;
ios.dbits = SERIAL_DATABIT_8;
ios.parity = SERIAL_PARITY_NONE;
ios.sbits = SERIAL_STOPBIT_ONEHALF;
ios.flow = SERIAL_FLOW_NONE;

const char *result = sSerialAttrToStr(&ios);
// " 9600-8N3 " (Wait, 1.5 is enum value 3)
printf("Test StopBit 1.5 Case: '%s'\n", result);
assert(strcmp(result, " 9600-8N3 ") == 0);
}

void test_truncation_case() {
xSerialIos ios;
ios.baud = 1234567890; // 10 digits
ios.dbits = SERIAL_DATABIT_8;
ios.parity = SERIAL_PARITY_NONE;
ios.sbits = SERIAL_STOPBIT_ONE;
ios.flow = SERIAL_FLOW_NONE;

const char *result = sSerialAttrToStr(&ios);
// "1234567890-8N1 "
printf("Test Truncation Case (10 digits): '%s'\n", result);
assert(strcmp(result, "1234567890-8N1 ") == 0);
}

void test_overflow_case() {
xSerialIos ios;
ios.dbits = SERIAL_DATABIT_8;
ios.parity = SERIAL_PARITY_NONE;
ios.sbits = SERIAL_STOPBIT_ONE;
ios.flow = SERIAL_FLOW_NONE;

// Check if long is large enough to hold the value
if (sizeof(long) > 4) {
ios.baud = 12345678901L; // 11 digits (if long is 64-bit)
const char *result = sSerialAttrToStr(&ios);
printf("Test Overflow Case (11 digits): '%s'\n", result);
// Expected: "12345678901-8N1" (15 chars)
// because snprintf truncates to size-1.
assert(strcmp(result, "12345678901-8N1") == 0);
} else {
printf("Skipping Test Overflow Case (long is 32-bit)\n");
}
}

int main() {
test_standard_case();
test_complex_case();
test_rs485_case();
test_stopbit_onehalf_case();
test_truncation_case();
test_overflow_case();

printf("All tests passed!\n");
return 0;
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The current test implementation uses assert(), which will cause the test executable to abort on the first failure. This prevents subsequent tests from running, making it harder to get a full picture of any issues. It's better to have a test runner that executes all tests and reports a summary of successes and failures at the end.

I suggest a small refactoring to introduce a simple test harness. This involves:

  1. Replacing assert() with a custom macro that records failures but doesn't halt execution.
  2. Updating main() to iterate through all tests and provide a summary report, returning a non-zero exit code if any test fails (which is standard for ctest).
  3. Removing diagnostic printf() calls from individual test cases to keep the test output clean for ctest.

This approach makes the test suite more robust and provides more comprehensive feedback.

#include <stdio.h>
#include <string.h>
#include "serial.h"

// --- Simple Test Harness ---
static int tests_run = 0;
static int tests_failed = 0;

// A simple assertion macro that reports failures without aborting.
#define ASSERT_STR_EQ(actual, expected, test_name) \
    do { \
        tests_run++; \
        if (strcmp(actual, expected) != 0) { \
            fprintf(stderr, "FAIL in %s: expected \"%s\", got \"%s\"\n", test_name, expected, actual); \
            tests_failed++; \
        } \
    } while (0)
// --- End Test Harness ---

void test_standard_case() {
    xSerialIos ios;
    ios.baud = 9600;
    ios.dbits = SERIAL_DATABIT_8;
    ios.parity = SERIAL_PARITY_NONE;
    ios.sbits = SERIAL_STOPBIT_ONE;
    ios.flow = SERIAL_FLOW_NONE;

    const char *result = sSerialAttrToStr(&ios);
    ASSERT_STR_EQ(result, "      9600-8N1 ", "test_standard_case");
}

void test_complex_case() {
    xSerialIos ios;
    ios.baud = 115200;
    ios.dbits = SERIAL_DATABIT_8;
    ios.parity = SERIAL_PARITY_EVEN;
    ios.sbits = SERIAL_STOPBIT_TWO;
    ios.flow = SERIAL_FLOW_RTSCTS;

    const char *result = sSerialAttrToStr(&ios);
    ASSERT_STR_EQ(result, "    115200-8E2H", "test_complex_case");
}

void test_rs485_case() {
    xSerialIos ios;
    ios.baud = 19200;
    ios.dbits = SERIAL_DATABIT_8;
    ios.parity = SERIAL_PARITY_NONE;
    ios.sbits = SERIAL_STOPBIT_ONE;
    ios.flow = SERIAL_FLOW_RS485_RTS_AFTER_SEND;

    const char *result = sSerialAttrToStr(&ios);
    ASSERT_STR_EQ(result, "     19200-8N1R", "test_rs485_case");
}

void test_stopbit_onehalf_case() {
    xSerialIos ios;
    ios.baud = 9600;
    ios.dbits = SERIAL_DATABIT_8;
    ios.parity = SERIAL_PARITY_NONE;
    ios.sbits = SERIAL_STOPBIT_ONEHALF;
    ios.flow = SERIAL_FLOW_NONE;

    const char *result = sSerialAttrToStr(&ios);
    ASSERT_STR_EQ(result, "      9600-8N3 ", "test_stopbit_onehalf_case");
}

void test_truncation_case() {
    xSerialIos ios;
    ios.baud = 1234567890; // 10 digits
    ios.dbits = SERIAL_DATABIT_8;
    ios.parity = SERIAL_PARITY_NONE;
    ios.sbits = SERIAL_STOPBIT_ONE;
    ios.flow = SERIAL_FLOW_NONE;

    const char *result = sSerialAttrToStr(&ios);
    ASSERT_STR_EQ(result, "1234567890-8N1 ", "test_truncation_case");
}

void test_overflow_case() {
    xSerialIos ios;
    ios.dbits = SERIAL_DATABIT_8;
    ios.parity = SERIAL_PARITY_NONE;
    ios.sbits = SERIAL_STOPBIT_ONE;
    ios.flow = SERIAL_FLOW_NONE;

    // Check if long is large enough to hold the value
    if (sizeof(long) > 4) {
        ios.baud = 12345678901L; // 11 digits (if long is 64-bit)
        const char *result = sSerialAttrToStr(&ios);
        ASSERT_STR_EQ(result, "12345678901-8N1", "test_overflow_case");
    } else {
        printf("Skipping Test Overflow Case (long is 32-bit)\n");
    }
}

int main() {
    test_standard_case();
    test_complex_case();
    test_rs485_case();
    test_stopbit_onehalf_case();
    test_truncation_case();
    test_overflow_case();

    if (tests_failed > 0) {
        fprintf(stderr, "\n%d of %d tests failed.\n", tests_failed, tests_run);
        return 1;
    }

    printf("All tests passed!\n");
    return 0;
}

@zknpr
Copy link
Copy Markdown
Owner Author

zknpr commented Feb 7, 2026

Tests merged into v1.5.3 as combined test suite. Thank you Jules!

@zknpr zknpr closed this Feb 7, 2026
@google-labs-jules
Copy link
Copy Markdown

Tests merged into v1.5.3 as combined test suite. Thank you Jules!

You're welcome! Glad to hear the tests were useful and merged successfully.

@zknpr zknpr deleted the add-serial-tests-4500608520212156328 branch February 7, 2026 18:19
zknpr added a commit that referenced this pull request Feb 7, 2026
Add comprehensive test suite for serial port configuration functions:
- sSerialFlowToStr: flow control type conversion
- sSerialDataBitsToStr: data bits conversion
- sSerialStopBitsToStr: stop bits conversion
- sSerialParityToStr: parity conversion

Test infrastructure:
- tests/test_serial.c: All serial function tests
- tests/CMakeLists.txt: CTest integration
- BUILD_TESTING option in main CMakeLists.txt

Based on Jules AI contributions from PRs #10, #11, #14, #15
Reviewed by: Gemini Code Assist

Co-Authored-By: google-labs-jules[bot] <161369871+google-labs-jules[bot]@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant