Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 34 additions & 0 deletions system/nxinit/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -38,4 +38,38 @@ if(CONFIG_SYSTEM_NXINIT)
SRCS
${CSRCS})

if(CONFIG_SYSTEM_NXINIT_TEST)

# NxInit unit tests (cmocka). Unlike the Makefile build (which folds the
# test sources into the same CSRCS used by the "init" program above, so
# parser/action/service are compiled once and shared), CMake compiles
# action.c/parser.c/service.c a second time into this separate
# nxinit_unit_test target.

set(TEST_SRCS
test/test_nxinit.c
action.c
parser.c
service.c
test/test_nxinit_common.c
test/test_nxinit_parser.c
test/test_nxinit_action.c
test/test_nxinit_service.c)

nuttx_add_application(
NAME
nxinit_unit_test
PRIORITY
${CONFIG_SYSTEM_NXINIT_TEST_PRIORITY}
STACKSIZE
${CONFIG_SYSTEM_NXINIT_TEST_STACKSIZE}
MODULE
${CONFIG_SYSTEM_NXINIT}
DEPENDS
cmocka
SRCS
${TEST_SRCS})

endif()

endif()
42 changes: 41 additions & 1 deletion system/nxinit/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ config SYSTEM_NXINIT_RC_FILE_PATH
config SYSTEM_NXINIT_RC_LINE_MAX
int "Max line length of RC file"
default 128
range 64 4096
---help---
Maximum line length of RC file.
More details: https://android.googlesource.com/platform/system/core/+/master/init/README.md
Expand Down Expand Up @@ -69,7 +70,7 @@ config SYSTEM_NXINIT_ACTION_WARN_SLOW

config SYSTEM_NXINIT_ACTION_EVENTS_MAX
int "Max number of events"
default 1
default 2
range 1 64
---help---
Maximum number of event and action events.
Expand Down Expand Up @@ -110,6 +111,45 @@ config SYSTEM_NXINIT_SERVICE_RESTART_PERIOD
int "Service restart period in ms"
default 5000

comment "NXInit Testing"

config SYSTEM_NXINIT_TEST
bool "NxInit unit tests"
default n
depends on TESTING_CMOCKA
---help---
Enable cmocka-based unit tests covering NxInit's argument/config
parser, action event matching, and service conflict detection.
Builds a separate "nxinit_unit_test" program. Under the CMake
build the test sources compile into a dedicated target and the
"init" program is unaffected; under the Make build the test
sources are appended to the shared CSRCS list, so they are also
linked into "init", enlarging it and pulling in the cmocka
dependency. Keep this disabled for production Make builds.

if SYSTEM_NXINIT_TEST

config SYSTEM_NXINIT_TEST_PRIORITY
int "Test task priority"
default 100

config SYSTEM_NXINIT_TEST_STACKSIZE
int "Test task stack size"
default 8192
---help---
Several of the parser test cases build multi-hundred-byte
buffers on the stack (e.g. lines several times
CONFIG_SYSTEM_NXINIT_RC_LINE_MAX long) on top of cmocka's own
framework overhead. On at least one real embedded target this
overflowed the default DEFAULT_TASK_STACKSIZE (2048) silently
(no crash dump, no watchdog reset, the test task just stopped
producing output), which is far harder to diagnose than an
outright test failure. 8192 has been verified to run all test
cases cleanly on that target; lower it back down only if you
have confirmed your target's stack usage stays within bounds.

endif # SYSTEM_NXINIT_TEST

comment "NXInit Log level"

config SYSTEM_NXINIT_ERR
Expand Down
23 changes: 19 additions & 4 deletions system/nxinit/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -24,17 +24,32 @@ include $(APPDIR)/Make.defs

# NuttX Init

MAINSRC = init.c
MAINSRC += init.c
CSRCS += builtin.c
CSRCS += parser.c
CSRCS += action.c
CSRCS += service.c
CSRCS += import.c
CSRCS += property_simple.c

PROGNAME = $(CONFIG_SYSTEM_NXINIT_PROGNAME)
PRIORITY = $(CONFIG_SYSTEM_NXINIT_PRIORITY)
STACKSIZE = $(CONFIG_SYSTEM_NXINIT_STACKSIZE)
PROGNAME += $(CONFIG_SYSTEM_NXINIT_PROGNAME)
PRIORITY += $(CONFIG_SYSTEM_NXINIT_PRIORITY)
STACKSIZE += $(CONFIG_SYSTEM_NXINIT_STACKSIZE)
MODULE = $(CONFIG_SYSTEM_NXINIT)

# NxInit unit tests (cmocka), reusing the same parser/action/service CSRCS
# built above.

ifneq ($(CONFIG_SYSTEM_NXINIT_TEST),)
CSRCS += test/test_nxinit_common.c
CSRCS += test/test_nxinit_parser.c
CSRCS += test/test_nxinit_action.c
CSRCS += test/test_nxinit_service.c
MAINSRC += test/test_nxinit.c

PROGNAME += nxinit_unit_test
PRIORITY += $(CONFIG_SYSTEM_NXINIT_TEST_PRIORITY)
STACKSIZE += $(CONFIG_SYSTEM_NXINIT_TEST_STACKSIZE)
endif

include $(APPDIR)/Application.mk
11 changes: 4 additions & 7 deletions system/nxinit/parser.c
Original file line number Diff line number Diff line change
Expand Up @@ -56,10 +56,6 @@ static int init_parse_config_lines(FAR const struct parser_s *parser,
*(nl++) = '\0';
*len -= nl - buf;
init_debug("Line %-3zu '%s'", ++*line, buf);
if (*buf == '\0')
{
continue;
}

/* Skip empty lines and lines containing only whitespace */

Expand Down Expand Up @@ -100,8 +96,8 @@ static int init_parse_config_lines(FAR const struct parser_s *parser,
return 0;
}

static int init_parse_config_buffer(FAR const struct parser_s *parser,
FAR const char *buf, size_t len)
int init_parse_config_buffer(FAR const struct parser_s *parser,
FAR const char *buf, size_t len)
{
char tmp[CONFIG_SYSTEM_NXINIT_RC_LINE_MAX];
FAR const struct parser_s *cur = NULL;
Expand All @@ -113,7 +109,7 @@ static int init_parse_config_buffer(FAR const struct parser_s *parser,

for (; ; )
{
r = MIN(len - off, sizeof(tmp));
r = MIN(len - off, sizeof(tmp) - n);
memcpy(&tmp[n], &buf[off], r);
if (r == 0)
{
Expand Down Expand Up @@ -273,6 +269,7 @@ int init_parse_config_file(FAR const struct parser_s *parser,
for (; ; )
{
ssize_t r = read(fd, &buf[n], sizeof(buf) - n);

if (r < 0)
{
if (errno == EINTR)
Expand Down
4 changes: 4 additions & 0 deletions system/nxinit/parser.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
****************************************************************************/

#include <stdbool.h>
#include <stddef.h>

/****************************************************************************
* Public Types
Expand Down Expand Up @@ -56,4 +57,7 @@ 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
65 changes: 65 additions & 0 deletions system/nxinit/test/test_nxinit.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
/****************************************************************************
* apps/system/nxinit/test/test_nxinit.c
*
* 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.
*
****************************************************************************/

/****************************************************************************
* Included Files
****************************************************************************/

#include <setjmp.h>
#include <stdarg.h>
#include <stddef.h>
#include <stdint.h>
#include <cmocka.h>

#include "test_nxinit.h"

/****************************************************************************
* Public Functions
****************************************************************************/

int main(int argc, FAR char *argv[])
{
const struct CMUnitTest nxinit_tests[] =
{
cmocka_unit_test(test_nxinit_parser_arguments_spaces),
cmocka_unit_test(test_nxinit_parser_arguments_quoted),
cmocka_unit_test(test_nxinit_parser_arguments_dashdash_separator),
cmocka_unit_test(test_nxinit_parser_arguments_long_option),
cmocka_unit_test(test_nxinit_parser_arguments_truncate),
cmocka_unit_test(test_nxinit_parser_config_sections),
cmocka_unit_test(test_nxinit_parser_config_skip_blank_lines),
cmocka_unit_test(test_nxinit_parser_config_unknown_section),
cmocka_unit_test(test_nxinit_parser_config_line_too_long),
cmocka_unit_test(test_nxinit_parser_config_line_crosses_boundary),
cmocka_unit_test(test_nxinit_parser_config_buffer_crosses_boundary),
cmocka_unit_test(test_nxinit_action_event_match_exact),
cmocka_unit_test(test_nxinit_action_event_match_invert),
cmocka_unit_test(test_nxinit_action_event_match_fnmatch),
cmocka_unit_test(test_nxinit_action_event_and_semantics),
cmocka_unit_test(test_nxinit_service_duplicate_conflict),
cmocka_unit_test(test_nxinit_service_override_replaces_duplicate),
cmocka_unit_test(test_nxinit_service_args_max_boundary),
};

return cmocka_run_group_tests(nxinit_tests, test_nxinit_group_setup,
test_nxinit_group_teardown);
}
81 changes: 81 additions & 0 deletions system/nxinit/test/test_nxinit.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
/****************************************************************************
* apps/system/nxinit/test/test_nxinit.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_TEST_TEST_NXINIT_H
#define __APPS_SYSTEM_NXINIT_TEST_TEST_NXINIT_H

/****************************************************************************
* Included Files
****************************************************************************/

#include <nuttx/compiler.h>

/****************************************************************************
* Public Function Prototypes
****************************************************************************/

/****************************************************************************
* Name: test_nxinit_group_setup
****************************************************************************/

int test_nxinit_group_setup(FAR void **state);

/****************************************************************************
* Name: test_nxinit_group_teardown
****************************************************************************/

int test_nxinit_group_teardown(FAR void **state);

/****************************************************************************
* Name: test_nxinit_parser_*
****************************************************************************/

void test_nxinit_parser_arguments_spaces(FAR void **state);
void test_nxinit_parser_arguments_quoted(FAR void **state);
void test_nxinit_parser_arguments_dashdash_separator(FAR void **state);
void test_nxinit_parser_arguments_long_option(FAR void **state);
void test_nxinit_parser_arguments_truncate(FAR void **state);
void test_nxinit_parser_config_sections(FAR void **state);
void test_nxinit_parser_config_skip_blank_lines(FAR void **state);
void test_nxinit_parser_config_unknown_section(FAR void **state);
void test_nxinit_parser_config_line_too_long(FAR void **state);
void test_nxinit_parser_config_line_crosses_boundary(FAR void **state);
void test_nxinit_parser_config_buffer_crosses_boundary(FAR void **state);

/****************************************************************************
* Name: test_nxinit_action_*
****************************************************************************/

void test_nxinit_action_event_match_exact(FAR void **state);
void test_nxinit_action_event_match_invert(FAR void **state);
void test_nxinit_action_event_match_fnmatch(FAR void **state);
void test_nxinit_action_event_and_semantics(FAR void **state);

/****************************************************************************
* Name: test_nxinit_service_*
****************************************************************************/

void test_nxinit_service_duplicate_conflict(FAR void **state);
void test_nxinit_service_override_replaces_duplicate(FAR void **state);
void test_nxinit_service_args_max_boundary(FAR void **state);

#endif /* __APPS_SYSTEM_NXINIT_TEST_TEST_NXINIT_H */
Loading
Loading