Skip to content

Rtop 59 plugin driver layer unit tests#14

Merged
marconetsf merged 17 commits into
RTOP-52-Standard-Network-Driverfrom
RTOP-59-Plugin-driver-layer-unit-tests
Oct 7, 2025
Merged

Rtop 59 plugin driver layer unit tests#14
marconetsf merged 17 commits into
RTOP-52-Standard-Network-Driverfrom
RTOP-59-Plugin-driver-layer-unit-tests

Conversation

@marconetsf
Copy link
Copy Markdown
Contributor

Intro

A funcionalidade dos plugin drivers depende de que suas configurações e inicializações aconteçam com zero problemas.
Esta branch possui a implementação de funções que compoem a solução. É subdividida em duas partes. A primeira são os testes de configuração (Já que os plugins possuem um arquivo plugins.conf que ditam onde se encontram os requisitos necessários para rodar os plugins.

Testes de configuração

  • Parsing de arquivo de configuração válido: Verifica se o arquivo de configuração com plugins válidos é lido e interpretado corretamente.
  • Parsing de arquivo com mais plugins do que o limite: Testa se o parser respeita o limite máximo de plugins (MAX_PLUGINS) e ignora os extras.
  • Parsing de arquivo inexistente: Verifica se o parser retorna erro negativo ao tentar ler um arquivo que não existe.
  • Parsing de arquivo com linha malformada: Testa se o parser ignora linhas inválidas ou malformadas e processa apenas as válidas.
  • Parsing de arquivo contendo apenas comentários e linhas vazias: Verifica se o parser retorna zero plugins quando o arquivo não contém configurações válidas.

Teste de driver

  • Criação do driver com sucesso
    : Verifica se o driver é criado corretamente quando a alocação de memória e a inicialização do mutex funcionam.
  • Falha na alocação de memória
    : Testa se o driver retorna NULL quando a função calloc falha.
  • Falha na inicialização do mutex
    : Testa se o driver retorna NULL e libera a memória corretamente quando a inicialização do mutex falha.
  • Manipulação da estrutura de dados do driver
    : Verifica se as informações dos plugins são armazenadas corretamente na estrutura do driver.
  • Inicialização de plugin com falha
    : Testa o comportamento do driver quando a inicialização de um plugin falha (simulação simplificada).

@marconetsf marconetsf requested a review from Copilot October 6, 2025 13:07
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull Request Overview

Adds initial unit tests for plugin configuration parsing and plugin driver creation/initialization, introduces Ceedling/CMock configuration updates, and removes a Python header include from the driver interface. Key changes include: (1) new tests for config parsing edge cases and driver lifecycle paths, (2) support stubs and mockable headers for standard/pthread functions, (3) project.yml updated to enable mocks and Python/pthread linking while removing Python.h from the public driver header.

  • Adds comprehensive parsing tests (valid file, over limit, malformed, empty, missing file).
  • Adds driver creation and structural population tests plus a placeholder init failure test.
  • Adjusts public header by dropping Python.h include (now only leaves PY_SSIZE_T_CLEAN macro).

Reviewed Changes

Copilot reviewed 7 out of 7 changed files in this pull request and generated 6 comments.

Show a summary per file
File Description
tests/test_plugin_driver.c Adds driver allocation, failure-path, structure population, and placeholder init tests plus direct function redefinitions.
tests/test_plugin_config.c Adds multiple parsing behavior tests for plugin config files.
tests/support/test_plugin_driver_stubs.c Provides stubs for external buffers and plugin_manager_destroy.
tests/support/mockable_stdlib.h Declares mockable stdlib wrappers.
tests/support/mockable_pthread.h Declares mockable pthread wrappers.
project.yml Enables mocks, adds defines, Python/pthread libs, and test build configuration.
core/src/drivers/plugin_driver.h Removes Python.h include but leaves PY_SSIZE_T_CLEAN macro.

Tip: Customize your code reviews with copilot-instructions.md. Create the file or learn how to get started.

Comment thread tests/test_plugin_driver.c Outdated
Comment on lines +83 to +90
// Mock implementation for plugin_manager_destroy
// This is normally defined in plcapp_manager.c
void plugin_manager_destroy(PluginManager *manager)
{
(void)manager; // Suppress unused parameter warning
// Mock implementation - do nothing
}

Copy link

Copilot AI Oct 6, 2025

Choose a reason for hiding this comment

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

plugin_manager_destroy is already stubbed in tests/support/test_plugin_driver_stubs.c; this duplicate definition will cause a multiple definition error at link time. Remove one copy (prefer keeping it in the shared stub file).

Suggested change
// Mock implementation for plugin_manager_destroy
// This is normally defined in plcapp_manager.c
void plugin_manager_destroy(PluginManager *manager)
{
(void)manager; // Suppress unused parameter warning
// Mock implementation - do nothing
}

Copilot uses AI. Check for mistakes.
Comment thread core/src/drivers/plugin_driver.h Outdated
Comment on lines 3 to 4
#define PY_SSIZE_T_CLEAN
#include <Python.h>

Copy link

Copilot AI Oct 6, 2025

Choose a reason for hiding this comment

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

PY_SSIZE_T_CLEAN is intended to precede an inclusion of <Python.h>, but the header no longer includes Python.h. Either move both the macro and the include into the implementation (.c) file (if hiding the Python API is intended) or remove the macro here to avoid leaking a Python-specific macro into all includers.

Copilot uses AI. Check for mistakes.
Comment on lines +45 to +54
void free(void *ptr)
{
mock_free_call_count++;
// For test purposes, we track the call but don't actually free
// In a real scenario, you might want to call the real free
if (ptr)
{
// Could call real free here if needed: ((void(*)(void*))dlsym(RTLD_NEXT, "free"))(ptr);
}
}
Copy link

Copilot AI Oct 6, 2025

Choose a reason for hiding this comment

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

Overriding free without releasing the allocated memory causes intentional leaks that can accumulate across multiple tests and mask real lifetime issues. Consider invoking the real free (e.g., via wrapper or link-time wrapping) after incrementing the counter to avoid heap growth during the test suite.

Copilot uses AI. Check for mistakes.
Comment thread tests/test_plugin_config.c Outdated
TEST_ASSERT_EQUAL_STRING("../path/to/plugin1.py", configs[0].path);
TEST_ASSERT_EQUAL_INT(1, configs[0].enabled);
TEST_ASSERT_EQUAL_INT(0, configs[0].type); // 0 for Python from plugin_config.h
TEST_ASSERT_EQUAL_STRING("./config1.ini\n", configs[0].plugin_related_config_path);
Copy link

Copilot AI Oct 6, 2025

Choose a reason for hiding this comment

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

Expectation includes a trailing newline, while later similar assertion for plugin3 (line 81) omits it, creating inconsistent criteria that likely does not match intended parsing (newline should typically be stripped). Adjust to remove the newline (same issue also on line 73).

Copilot uses AI. Check for mistakes.
Comment thread tests/test_plugin_config.c Outdated
TEST_ASSERT_EQUAL_STRING("plugin1", configs[0].name);
TEST_ASSERT_EQUAL_STRING("../path/to/plugin1.py", configs[0].path);
TEST_ASSERT_EQUAL_INT(1, configs[0].enabled);
TEST_ASSERT_EQUAL_INT(0, configs[0].type); // 0 for Python from plugin_config.h
Copy link

Copilot AI Oct 6, 2025

Choose a reason for hiding this comment

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

[nitpick] Using magic numbers (0/1) for plugin types reduces readability; replace with the enum constants (e.g., PLUGIN_TYPE_PYTHON / PLUGIN_TYPE_NATIVE) for clarity and resilience to future enum reordering (also applies to lines 72 and 80).

Copilot uses AI. Check for mistakes.
@Autonomy-Logic Autonomy-Logic deleted a comment from Copilot AI Oct 7, 2025
@marconetsf marconetsf merged commit dbd7a06 into RTOP-52-Standard-Network-Driver Oct 7, 2025
@marconetsf marconetsf deleted the RTOP-59-Plugin-driver-layer-unit-tests branch October 7, 2025 09:53
marconetsf added a commit that referenced this pull request Oct 7, 2025
* Add plugin driver system with config parsing

Introduces a plugin driver framework supporting both native and Python plugins, including configuration parsing, driver management, and integration into the main PLC application. Updates CMake to link Python libraries and adds example configuration files for plugins. (WIP)

* sync plugin driver

* Adjusting python.h include

Accordingly with the documentation, python header should be the first called and for security, we have to define PY_SSIZE_T_CLEAN

* fix init driver's args encapsulation

* adjusting brackets position and function identation

Everything accordingly BARR Standard

* fix cmakelist

* adjust python_plugin_bridge.h identation

everything accordingly BARR standard

* python start funct running within a thread

deleting python cycle function since it will be running async

* fixing pointer dereferencing

for some reason, when init is called it can successfully link buffers and function address between runtime and plugin, but when the same previous parsed "struct" is called within start function, the buffer pointer was no longer pointing to the right address.

* Fix buffer access in Python plugin driver

Corrects how bool_output buffer values are read and written by accessing the actual value via .contents.value instead of the pointer. Updates example plugin to use SafeBufferAccess for safer buffer operations and improves output logging.

* deleting stop call

Stop is already being called within destroy function

* Remove unused _runtime_args_capsule variable

Eliminated the _runtime_args_capsule global variable and related code from example_python_plugin.py, simplifying state management and usage of runtime arguments.

* Refactor Python plugin threading and lifecycle management

Moved plugin thread creation to Python side and removed native thread management for Python plugins. Updated function names in python_binds_t for clarity. Improved plugin start, stop, and cleanup logic to use Python-side functions and ensured proper GIL handling. Cleaned up resource management and removed unused thread fields from plugin_instance_t.

* Refactor plugin driver cleanup and GIL management

Improves Python GIL state management in plugin_driver by using a static variable and ensuring proper acquisition/release during plugin lifecycle. Moves plugin driver cleanup earlier in plc_main to avoid double destruction and adds more informative logging during plugin stop.

* Refactor plugin loop to run in a separate thread

The plugin's main loop now runs in a background thread using Python's threading module. Added a stop event to allow graceful termination of the loop in stop_loop, improving plugin lifecycle management and preventing blocking the main thread.

* Refactor Modbus plugin for safer buffer access

Replaces manual ctypes structure and buffer access with type-safe wrappers from python_plugin_types. Updates OpenPLCModbusDataBlock to use SafeBufferAccess for reading and writing coil values, improving safety and error handling. Refactors plugin initialization and server startup for better diagnostics and reliability.

* Update Python plugin documentation and type safety

Revised README to clarify plugin type values, enhance Python plugin type safety, and document usage of the new python_plugin_types.py module. Added examples for thread-safe buffer access, advanced Modbus implementation, and improved plugin initialization with structure validation and error handling.

* moving examples and plugins to respective folder

* deleting unused plugins from config

* Expose plugin mutex helpers and use in PLC cycle

Made plugin_mutex_take and plugin_mutex_give functions public in plugin_driver.h and used them to protect buffer access in the PLC cycle thread. Also refactored plugin_driver variable to be global in plc_main.c for thread safety.

* Changing pluggins paths to meet exec.sh start path

* Rtop 58 plugin modbus slave (#6)

* thread safe and dump access in the same function

* adding batch functions that allows multiple reads/writes

* Providing wrappers for IS, IR and HR

* avoiding magical numbers

* avoiding generic exception handling

* fixing plugin's dedicated data retrieval

* RTOP 74 adding plugin individual venv usage

* Update scripts/manage_plugin_venvs.sh

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* Disabling initial plugin prints and avoiding code insertion

* install now has support for apt yum and dfs and plc program is being built

* adding proper build error and success logs

* [RTOP 74][WIP] implementing initialization scripts

* changing runtime venv from .venv to venvs/runtime/

* Add requirements.txt to the Modbus driver

* Add checks on install and start_openplc scripts

* Quick fix on start_openplc.sh

* [RTOP 59] plugin driver layer unit tests (#14)

* adding ceedling configuration and tests folder

* adding config parsing tests

* adding support folder for tests

* deleting unnecessary python include

* adding plugin driver tests

* updating tests to not use cmock

* deleting unused files

* deleting unused file

* removing PY_SSIZE_T_CLEAN define

* adding stubs to avoiding duplicated test codes

* releasing memory within test free override

* avoiding newline charactere within config structure

* adjusting clang format standard

* suppressing free tests warnings

* renaming stubs to avoid being recognized as a test

* updating plugins readme

* Update tests/test_plugin_driver.c

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* Update core/src/drivers/plugins/python/modbus_slave/simple_modbus.py

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* importing sys and os at example_python_plugin.py

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

---------

Co-authored-by: Thiago Alves <thiagoralves@gmail.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Autonomy Server <autonomyserver@Autonomys-Mac-mini.local>
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.

2 participants