nuttx-apps/system/nxinit/parser.h
wangjianyu3 63698738a8 system/nxinit: add cmocka unit tests for parser/action/service
Add a test/ subdirectory (mirroring apps/system/uorb/test/) with
cmocka-based unit tests covering the NxInit logic most prone to
regression:

- init_parse_arguments(): plain/quoted arguments, "--" separator vs.
  "--option" long options (regression coverage for a previously fixed
  bug), argv-capacity truncation (asserting the exact folded contents
  of the last slot, not just its presence).
- init_parse_config_file()/init_parse_config_lines()/
  init_parse_config_buffer(): section routing, blank/whitespace-only
  line skipping, unknown-section rejection, over-length line rejection,
  and a line straddling two read-buffer refills, exercised through both
  the file-based and buffer-based entry points.
- Action event matching: exact match, invert (!=), fnmatch wildcards,
  and AND semantics across multiple events per action.
- Service conflict detection: duplicate service name rejection,
  override replacing an earlier duplicate, and the SERVICE_ARGS_MAX
  boundary built dynamically from CONFIG_SYSTEM_NXINIT_SERVICE_ARGS_MAX
  rather than a hardcoded value.

Test sources compile action.c/parser.c/service.c a second time into a
separate nxinit_unit_test program, gated behind new
CONFIG_SYSTEM_NXINIT_TEST (depends on TESTING_CMOCKA); the default init
program is unaffected. The CMake path builds a dedicated
nxinit_unit_test target (with test/test_nxinit.c placed first in SRCS
so nuttx_add_application() renames its main() correctly); the Make path
appends the test sources into the shared CSRCS list.

Supporting bits required to make the suite exercise the real code:

- init_parse_config_buffer() is declared in parser.h and made
  non-static so the buffer-based boundary test can call it directly,
  alongside the existing init_parse_config_file() entry point.
- CONFIG_SYSTEM_NXINIT_ACTION_EVENTS_MAX default is raised from 1 to 2
  so an action can carry more than one event ("on evA && evB"), which
  the multi-event AND-semantics test exercises; a single event slot
  made that test dead code.
- CONFIG_SYSTEM_NXINIT_TEST_STACKSIZE defaults to 8192: several parser
  test cases build multi-hundred-byte stack buffers on top of cmocka's
  own overhead, and the previous DEFAULT_TASK_STACKSIZE (2048)
  overflowed the test task's stack silently on real hardware (no crash
  dump, no watchdog reset, output just stopped) partway through the
  suite.

Testing:
Built via `make CROSSDEV=riscv-none-elf-` for
esp32p4-pico-wifi-wareshare:nsh (CONFIG_SYSTEM_NXINIT_TEST=y) and ran
nxinit_unit_test on real esp32p4-pico-wifi-wareshare hardware over
UART:

  nsh> nxinit_unit_test
  [==========] nxinit_tests: Running 18 test(s).
  ...
  [==========] nxinit_tests: 18 test(s) run.
  [  PASSED  ] 18 test(s).

nxstyle clean on all touched files.

Assisted-by: GitHubCopilot:claude-sonnet-5
Signed-off-by: wangjianyu3 <wangjianyu3@xiaomi.com>
2026-08-28 09:33:47 -03:00

63 lines
2.3 KiB
C

/****************************************************************************
* apps/system/nxinit/parser.h
*
* SPDX-License-Identifier: Apache-2.0
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership. The
* ASF licenses this file to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance with the
* License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*
****************************************************************************/
#ifndef __APPS_SYSTEM_NXINIT_PARSER_H
#define __APPS_SYSTEM_NXINIT_PARSER_H
/****************************************************************************
* Included Files
****************************************************************************/
#include <stdbool.h>
#include <stddef.h>
/****************************************************************************
* Public Types
****************************************************************************/
struct parser_s
{
FAR const char *key;
CODE int (*parse)(FAR const struct parser_s *, bool, FAR char *);
CODE int (*check)(FAR const struct parser_s *);
/* Type
* a. struct action_manager_s
* b. struct service_manager_s
*/
FAR void *priv;
};
/****************************************************************************
* Public Function Prototypes
****************************************************************************/
int init_parse_arguments(FAR char *buf, bool dup, int argc, FAR char **argv);
int init_parse_configs(FAR const struct parser_s *parser);
int init_parse_config_file(FAR const struct parser_s *parser,
FAR const char *file);
int init_parse_config_buffer(FAR const struct parser_s *parser,
FAR const char *buf, size_t len);
#endif