diff --git a/src/lib/shell/MainLoopCYW30739.cpp b/src/lib/shell/MainLoopCYW30739.cpp index 7f7044d342e6e9..920e33f666ee1d 100644 --- a/src/lib/shell/MainLoopCYW30739.cpp +++ b/src/lib/shell/MainLoopCYW30739.cpp @@ -82,6 +82,11 @@ int TokenizeLine(char * buffer, char ** tokens, int max_tokens) } } } + // If for too many arguments, overwrite last entry with guard. + if (cursor >= max_tokens) + { + cursor = max_tokens - 1; + } tokens[cursor] = nullptr; diff --git a/src/lib/shell/MainLoopDefault.cpp b/src/lib/shell/MainLoopDefault.cpp index 9b1f8434fa30f2..fba29a7238f161 100644 --- a/src/lib/shell/MainLoopDefault.cpp +++ b/src/lib/shell/MainLoopDefault.cpp @@ -142,6 +142,11 @@ int TokenizeLine(char * buffer, char ** tokens, int max_tokens) } } } + // If for too many arguments, overwrite last entry with guard. + if (cursor >= max_tokens) + { + cursor = max_tokens - 1; + } tokens[cursor] = nullptr; diff --git a/src/lib/shell/MainLoopEFR32.cpp b/src/lib/shell/MainLoopEFR32.cpp index 7d993ccbad9966..7996300e2f5aac 100644 --- a/src/lib/shell/MainLoopEFR32.cpp +++ b/src/lib/shell/MainLoopEFR32.cpp @@ -137,6 +137,11 @@ int TokenizeLine(char * buffer, char ** tokens, int max_tokens) } } } + // If for too many arguments, overwrite last entry with guard. + if (cursor >= max_tokens) + { + cursor = max_tokens - 1; + } tokens[cursor] = nullptr; diff --git a/src/lib/shell/tests/BUILD.gn b/src/lib/shell/tests/BUILD.gn index 6180de017c3312..a0ecaea94c862c 100644 --- a/src/lib/shell/tests/BUILD.gn +++ b/src/lib/shell/tests/BUILD.gn @@ -21,9 +21,9 @@ import("${chip_root}/build/chip/chip_test_suite.gni") chip_test_suite("tests") { output_name = "libTestShell" - sources = [ - "TestStreamerStdio.cpp", - "TestStreamerStdio.h", + test_sources = [ + "TestShellStreamerStdio.cpp", + "TestShellTokenizeLine.cpp", ] cflags = [ "-Wconversion" ] @@ -33,6 +33,4 @@ chip_test_suite("tests") { "${chip_root}/src/lib/shell", "${nlunit_test_root}:nlunit-test", ] - - tests = [ "TestStreamerStdio" ] } diff --git a/src/lib/shell/tests/TestStreamerStdio.cpp b/src/lib/shell/tests/TestShellStreamerStdio.cpp similarity index 92% rename from src/lib/shell/tests/TestStreamerStdio.cpp rename to src/lib/shell/tests/TestShellStreamerStdio.cpp index b8c72be4dac85f..f0db26bdca3452 100644 --- a/src/lib/shell/tests/TestStreamerStdio.cpp +++ b/src/lib/shell/tests/TestShellStreamerStdio.cpp @@ -15,7 +15,7 @@ * limitations under the License. */ -#include "TestStreamerStdio.h" +#include #include #include @@ -75,14 +75,14 @@ static void TestStreamer_Output(nlTestSuite * inSuite, void * inContext) */ static const nlTest sTests[] = { - NL_TEST_DEF("Test Streamer: TestStreamer_Output", TestStreamer_Output), + NL_TEST_DEF("Test Shell: TestStreamer_Output", TestStreamer_Output), NL_TEST_SENTINEL() }; int TestStreamerStdio(void) { - nlTestSuite theSuite = { "CHIP Streamer tests", &sTests[0], nullptr, nullptr }; + nlTestSuite theSuite = { "Test Shell: Streamer", &sTests[0], nullptr, nullptr }; // Run test suit againt one context. nlTestRunner(&theSuite, nullptr); diff --git a/src/lib/shell/tests/TestShellTokenizeLine.cpp b/src/lib/shell/tests/TestShellTokenizeLine.cpp new file mode 100644 index 00000000000000..e88f9fe901aeb7 --- /dev/null +++ b/src/lib/shell/tests/TestShellTokenizeLine.cpp @@ -0,0 +1,148 @@ +/* + * + * Copyright (c) 2020 Project CHIP Authors + * + * Licensed 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. + */ + +#include + +#include +#include + +// Include entire C++ file to have access to functions-under-test +// such as TokenizeLine despite them being declared within an anonymous namespace. +#include "../MainLoopDefault.cpp" + +using namespace chip; +using namespace chip::Shell; +using namespace chip::Logging; + +constexpr int TEST_SHELL_MAX_TOKENS = 5; + +// ================================= +// Test Vectors +// ================================= + +struct test_shell_vector +{ + const char * line; + const char ** argv; + int argc; +}; + +static const struct test_shell_vector test_vector_shell_tokenizer[] = { + { + .line = "hello how are you?", + .argv = (const char *[]){ "hello", "how", "are", "you?" }, + .argc = 4, + }, + { + .line = "hey yo yo", + .argv = (const char *[]){ "hey", "yo", "yo" }, + .argc = 3, + }, + { + .line = "This has double spaces", + .argv = (const char *[]){ "This", "has", "double", "spaces" }, + .argc = 4, + }, + { + .line = " leading space", + .argv = (const char *[]){ "leading", "space" }, + .argc = 2, + }, + { + .line = "trailing space ", + .argv = (const char *[]){ "trailing", "space", "" }, + .argc = 3, + }, + { + .line = "no_space", + .argv = (const char *[]){ "no_space" }, + .argc = 1, + }, + { + .line = " ", + .argv = (const char *[]){}, + .argc = 0, + }, + { + .line = "", + .argv = (const char *[]){}, + .argc = 0, + }, + { + .line = "hey 1 2 3 4 5 6 7 max out", + .argv = + (const char *[]){ + "hey", + "1", + "2", + "3", + }, + .argc = TEST_SHELL_MAX_TOKENS - 1, + }, +}; + +// ================================= +// Unit tests +// ================================= + +static void TestShell_Tokenizer(nlTestSuite * inSuite, void * inContext) +{ + int numOfTestVectors = ArraySize(test_vector_shell_tokenizer); + int numOfTestsRan = 0; + const struct test_shell_vector * test_params; + + char line[128]; + + for (int vectorIndex = 0; vectorIndex < numOfTestVectors; vectorIndex++) + { + test_params = &test_vector_shell_tokenizer[vectorIndex]; + strcpy(line, test_params->line); + + char * argv[TEST_SHELL_MAX_TOKENS]; + int argc = TokenizeLine(line, argv, TEST_SHELL_MAX_TOKENS); + + NL_TEST_ASSERT(inSuite, argc == test_params->argc); + + for (int i = 0; i < argc; i++) + { + NL_TEST_ASSERT(inSuite, strcmp(argv[i], test_params->argv[i]) == 0); + } + numOfTestsRan++; + } + NL_TEST_ASSERT(inSuite, numOfTestsRan > 0); +} + +/** + * Test Suite. It lists all the test functions. + */ +static const nlTest sTests[] = { + + NL_TEST_DEF("Test Shell: TestShell_Tokenizer", TestShell_Tokenizer), + + NL_TEST_SENTINEL() +}; + +int TestShellTokenizeLine(void) +{ + nlTestSuite theSuite = { "Test Shell: MainLoop", &sTests[0], nullptr, nullptr }; + + // Run test suit againt one context. + nlTestRunner(&theSuite, nullptr); + return nlTestRunnerStats(&theSuite); +} + +CHIP_REGISTER_TEST_SUITE(TestShellTokenizeLine) diff --git a/src/lib/shell/tests/TestStreamerStdio.h b/src/lib/shell/tests/TestStreamerStdio.h deleted file mode 100644 index 64e1904edde935..00000000000000 --- a/src/lib/shell/tests/TestStreamerStdio.h +++ /dev/null @@ -1,37 +0,0 @@ -/* - * - * Copyright (c) 2020 Project CHIP Authors - * - * Licensed 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. - */ - -/** - * @file - * This file declares test entry points for CHIP system layer - * library unit tests. - * - */ - -#pragma once - -#include - -#ifdef __cplusplus -extern "C" { -#endif - -int TestStreamerStdio(void); - -#ifdef __cplusplus -} -#endif diff --git a/src/lib/shell/tests/TestStreamerStdioDriver.cpp b/src/lib/shell/tests/TestStreamerStdioDriver.cpp deleted file mode 100644 index f10f8fecdad611..00000000000000 --- a/src/lib/shell/tests/TestStreamerStdioDriver.cpp +++ /dev/null @@ -1,34 +0,0 @@ -/* - * - * Copyright (c) 2020 Project CHIP Authors - * - * Licensed 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. - */ - -/** - * @file - * This file implements a standalone/native program executable - * test driver for the CHIP system layer library timer unit - * tests. - * - */ - -#include "TestStreamerStdio.h" - -int main(int argc, char * argv[]) -{ - // Generate machine-readable, comma-separated value (CSV) output. - nlTestSetOutputStyle(OUTPUT_CSV); - - return (TestStreamerStdio()); -}