cmdline: tests

Signed-off-by: Intel
This commit is contained in:
Intel 2012-12-20 00:00:00 +01:00 committed by Thomas Monjalon
parent ab971e5628
commit dbb860e03e
19 changed files with 4999 additions and 0 deletions

View File

@ -36,6 +36,7 @@ DIRS-$(CONFIG_RTE_APP_TEST) += test
DIRS-$(CONFIG_RTE_TEST_PMD) += test-pmd
DIRS-$(CONFIG_RTE_APP_CHKINCS) += chkincs
DIRS-$(CONFIG_RTE_LIBRTE_EAL_LINUXAPP) += cmdline_test
DIRS-$(CONFIG_RTE_LIBRTE_EAL_LINUXAPP) += dump_cfg
include $(RTE_SDK)/mk/rte.subdir.mk

49
app/cmdline_test/Makefile Normal file
View File

@ -0,0 +1,49 @@
# BSD LICENSE
#
# Copyright(c) 2010-2012 Intel Corporation. All rights reserved.
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
#
# * Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# * Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in
# the documentation and/or other materials provided with the
# distribution.
# * Neither the name of Intel Corporation nor the names of its
# contributors may be used to endorse or promote products derived
# from this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
include $(RTE_SDK)/mk/rte.vars.mk
#
# library name
#
APP = cmdline_test
#
# all sources are stored in SRCS-y
#
SRCS-$(CONFIG_RTE_APP_TEST) += cmdline_test.c
SRCS-$(CONFIG_RTE_APP_TEST) += commands.c
CFLAGS += -O3
CFLAGS += $(WERROR_FLAGS)
include $(RTE_SDK)/mk/rte.app.mk

View File

@ -0,0 +1,65 @@
/*-
* BSD LICENSE
*
* Copyright(c) 2010-2012 Intel Corporation. All rights reserved.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Intel Corporation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#include <string.h>
#include <stdio.h>
#include <stdint.h>
#include <stdarg.h>
#include <stdlib.h>
#include <errno.h>
#include <termios.h>
#include <ctype.h>
#include <sys/queue.h>
#include <cmdline_rdline.h>
#include <cmdline_parse.h>
#include <cmdline_socket.h>
#include <cmdline.h>
#include "cmdline_test.h"
int
main(int __attribute__((unused)) argc, char __attribute__((unused)) ** argv)
{
struct cmdline *cl;
cl = cmdline_stdin_new(main_ctx, "CMDLINE_TEST>>");
if (cl == NULL) {
return -1;
}
cmdline_interact(cl);
cmdline_stdin_exit(cl);
return 0;
}

View File

@ -0,0 +1,47 @@
/*-
* BSD LICENSE
*
* Copyright(c) 2010-2012 Intel Corporation. All rights reserved.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Intel Corporation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#ifndef _CMDLINE_TEST_H_
#define _CMDLINE_TEST_H_
/* icc on baremetal gives us troubles with function named 'main' */
#ifdef RTE_EXEC_ENV_BAREMETAL
#define main _main
#endif
extern cmdline_parse_ctx_t main_ctx[];
int main(int argc, char **argv);
#endif

115
app/cmdline_test/cmdline_test.py Executable file
View File

@ -0,0 +1,115 @@
#!/usr/bin/python
# BSD LICENSE
#
# Copyright(c) 2010-2012 Intel Corporation. All rights reserved.
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
#
# * Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# * Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in
# the documentation and/or other materials provided with the
# distribution.
# * Neither the name of Intel Corporation nor the names of its
# contributors may be used to endorse or promote products derived
# from this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
# Script that runs cmdline_test app and feeds keystrokes into it.
import sys, pexpect, string, os, cmdline_test_data
#
# function to run test
#
def runTest(child,test):
child.send(test["Sequence"])
if test["Result"] == None:
return 0
child.expect(test["Result"],1)
#
# history test is a special case
#
# This test does the following:
# 1) fills the history with garbage up to its full capacity
# (just enough to remove last entry)
# 2) scrolls back history to the very beginning
# 3) checks if the output is as expected, that is, the first
# number in the sequence (not the last entry before it)
#
# This is a self-contained test, it needs only a pexpect child
#
def runHistoryTest(child):
# find out history size
child.sendline(cmdline_test_data.CMD_GET_BUFSIZE)
child.expect("History buffer size: \\d+", timeout=1)
history_size = int(child.after[len(cmdline_test_data.BUFSIZE_TEMPLATE):])
i = 0
# fill the history with numbers
while i < history_size / 10:
# add 1 to prevent from parsing as octals
child.send("1" + str(i).zfill(8) + cmdline_test_data.ENTER)
# the app will simply print out the number
child.expect(str(i + 100000000), timeout=1)
i += 1
# scroll back history
child.send(cmdline_test_data.UP * (i + 2) + cmdline_test_data.ENTER)
child.expect("100000000", timeout=1)
# the path to cmdline_test executable is supplied via command-line.
if len(sys.argv) < 2:
print "Error: please supply cmdline_test app path"
sys.exit(1)
test_app_path = sys.argv[1]
if not os.path.exists(test_app_path):
print "Error: please supply cmdline_test app path"
sys.exit(1)
child = pexpect.spawn(test_app_path)
print "Running command-line tests..."
for test in cmdline_test_data.tests:
print (test["Name"] + ":").ljust(30),
try:
runTest(child,test)
print "PASS"
except:
print "FAIL"
print child
sys.exit(1)
# since last test quits the app, run new instance
child = pexpect.spawn(test_app_path)
print ("History fill test:").ljust(30),
try:
runHistoryTest(child)
print "PASS"
except:
print "FAIL"
print child
sys.exit(1)
child.close()
sys.exit(0)

View File

@ -0,0 +1,313 @@
#!/usr/bin/python
# BSD LICENSE
#
# Copyright(c) 2010-2012 Intel Corporation. All rights reserved.
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
#
# * Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# * Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in
# the documentation and/or other materials provided with the
# distribution.
# * Neither the name of Intel Corporation nor the names of its
# contributors may be used to endorse or promote products derived
# from this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
# collection of static data
import sys
# keycode constants
CTRL_A = chr(1)
CTRL_B = chr(2)
CTRL_C = chr(3)
CTRL_D = chr(4)
CTRL_E = chr(5)
CTRL_F = chr(6)
CTRL_K = chr(11)
CTRL_L = chr(12)
CTRL_N = chr(14)
CTRL_P = chr(16)
CTRL_W = chr(23)
CTRL_Y = chr(25)
ALT_B = chr(27) + chr(98)
ALT_D = chr(27) + chr(100)
ALT_F = chr(27) + chr(102)
ALT_BKSPACE = chr(27) + chr(127)
DEL = chr(27) + chr(91) + chr(51) + chr(126)
TAB = chr(9)
HELP = chr(63)
BKSPACE = chr(127)
RIGHT = chr(27) + chr(91) + chr(67)
DOWN = chr(27) + chr(91) + chr(66)
LEFT = chr(27) + chr(91) + chr(68)
UP = chr(27) + chr(91) + chr(65)
ENTER2 = '\r'
ENTER = '\n'
# expected result constants
NOT_FOUND = "Command not found"
BAD_ARG = "Bad arguments"
AMBIG = "Ambiguous command"
CMD1 = "Command 1 parsed!"
CMD2 = "Command 2 parsed!"
SINGLE = "Single word command parsed!"
SINGLE_LONG = "Single long word command parsed!"
AUTO1 = "Autocomplete command 1 parsed!"
AUTO2 = "Autocomplete command 2 parsed!"
# misc defines
CMD_QUIT = "quit"
CMD_GET_BUFSIZE = "get_history_bufsize"
BUFSIZE_TEMPLATE = "History buffer size: "
PROMPT = "CMDLINE_TEST>>"
# test defines
# each test tests progressively diverse set of keys. this way for example
# if we want to use some key sequence in the test, we first need to test
# that it itself does what it is expected to do. Most of the tests are
# designed that way.
#
# example: "arrows & delete test 1". we enter a partially valid command,
# then move 3 chars left and use delete three times. this way we get to
# know that "delete", "left" and "ctrl+B" all work (because if any of
# them fails, the whole test will fail and next tests won't be run).
#
# each test consists of name, character sequence to send to child,
# and expected output (if any).
tests = [
# test basic commands
{"Name" : "command test 1",
"Sequence" : "ambiguous first" + ENTER,
"Result" : CMD1},
{"Name" : "command test 2",
"Sequence" : "ambiguous second" + ENTER,
"Result" : CMD2},
{"Name" : "command test 3",
"Sequence" : "ambiguous ambiguous" + ENTER,
"Result" : AMBIG},
{"Name" : "command test 4",
"Sequence" : "ambiguous ambiguous2" + ENTER,
"Result" : AMBIG},
{"Name" : "invalid command test 1",
"Sequence" : "ambiguous invalid" + ENTER,
"Result" : BAD_ARG},
# test invalid commands
{"Name" : "invalid command test 2",
"Sequence" : "invalid" + ENTER,
"Result" : NOT_FOUND},
{"Name" : "invalid command test 3",
"Sequence" : "ambiguousinvalid" + ENTER2,
"Result" : NOT_FOUND},
# test arrows and deletes
{"Name" : "arrows & delete test 1",
"Sequence" : "singlebad" + LEFT*2 + CTRL_B + DEL*3 + ENTER,
"Result" : SINGLE},
{"Name" : "arrows & delete test 2",
"Sequence" : "singlebad" + LEFT*5 + RIGHT + CTRL_F + DEL*3 + ENTER,
"Result" : SINGLE},
# test backspace
{"Name" : "backspace test",
"Sequence" : "singlebad" + BKSPACE*3 + ENTER,
"Result" : SINGLE},
# test goto left and goto right
{"Name" : "goto left test",
"Sequence" : "biguous first" + CTRL_A + "am" + ENTER,
"Result" : CMD1},
{"Name" : "goto right test",
"Sequence" : "biguous fir" + CTRL_A + "am" + CTRL_E + "st" + ENTER,
"Result" : CMD1},
# test goto words
{"Name" : "goto left word test",
"Sequence" : "ambiguous st" + ALT_B + "fir" + ENTER,
"Result" : CMD1},
{"Name" : "goto right word test",
"Sequence" : "ambig first" + CTRL_A + ALT_F + "uous" + ENTER,
"Result" : CMD1},
# test removing words
{"Name" : "remove left word 1",
"Sequence" : "single invalid" + CTRL_W + ENTER,
"Result" : SINGLE},
{"Name" : "remove left word 2",
"Sequence" : "single invalid" + ALT_BKSPACE + ENTER,
"Result" : SINGLE},
{"Name" : "remove right word",
"Sequence" : "single invalid" + ALT_B + ALT_D + ENTER,
"Result" : SINGLE},
# test kill buffer (copy and paste)
{"Name" : "killbuffer test 1",
"Sequence" : "ambiguous" + CTRL_A + CTRL_K + " first" + CTRL_A + CTRL_Y + ENTER,
"Result" : CMD1},
{"Name" : "killbuffer test 2",
"Sequence" : "ambiguous" + CTRL_A + CTRL_K + CTRL_Y*26 + ENTER,
"Result" : NOT_FOUND},
# test newline
{"Name" : "newline test",
"Sequence" : "invalid" + CTRL_C + "single" + ENTER,
"Result" : SINGLE},
# test redisplay (nothing should really happen)
{"Name" : "redisplay test",
"Sequence" : "single" + CTRL_L + ENTER,
"Result" : SINGLE},
# test autocomplete
{"Name" : "autocomplete test 1",
"Sequence" : "si" + TAB + ENTER,
"Result" : SINGLE},
{"Name" : "autocomplete test 2",
"Sequence" : "si" + TAB + "_" + TAB + ENTER,
"Result" : SINGLE_LONG},
{"Name" : "autocomplete test 3",
"Sequence" : "in" + TAB + ENTER,
"Result" : NOT_FOUND},
{"Name" : "autocomplete test 4",
"Sequence" : "am" + TAB + ENTER,
"Result" : BAD_ARG},
{"Name" : "autocomplete test 5",
"Sequence" : "am" + TAB + "fir" + TAB + ENTER,
"Result" : CMD1},
{"Name" : "autocomplete test 6",
"Sequence" : "am" + TAB + "fir" + TAB + TAB + ENTER,
"Result" : CMD1},
{"Name" : "autocomplete test 7",
"Sequence" : "am" + TAB + "fir" + TAB + " " + TAB + ENTER,
"Result" : CMD1},
{"Name" : "autocomplete test 8",
"Sequence" : "am" + TAB + " am" + TAB + " " + ENTER,
"Result" : AMBIG},
{"Name" : "autocomplete test 9",
"Sequence" : "am" + TAB + "inv" + TAB + ENTER,
"Result" : BAD_ARG},
{"Name" : "autocomplete test 10",
"Sequence" : "au" + TAB + ENTER,
"Result" : NOT_FOUND},
{"Name" : "autocomplete test 11",
"Sequence" : "au" + TAB + "1" + ENTER,
"Result" : AUTO1},
{"Name" : "autocomplete test 12",
"Sequence" : "au" + TAB + "2" + ENTER,
"Result" : AUTO2},
{"Name" : "autocomplete test 13",
"Sequence" : "au" + TAB + "2" + TAB + ENTER,
"Result" : AUTO2},
{"Name" : "autocomplete test 14",
"Sequence" : "au" + TAB + "2 " + TAB + ENTER,
"Result" : AUTO2},
{"Name" : "autocomplete test 15",
"Sequence" : "24" + TAB + ENTER,
"Result" : "24"},
# test history
{"Name" : "history test 1",
"Sequence" : "invalid" + ENTER + "single" + ENTER + "invalid" + ENTER + UP + CTRL_P + ENTER,
"Result" : SINGLE},
{"Name" : "history test 2",
"Sequence" : "invalid" + ENTER + "ambiguous first" + ENTER + "invalid" + ENTER + "single" + ENTER + UP * 3 + CTRL_N + DOWN + ENTER,
"Result" : SINGLE},
#
# tests that improve coverage
#
# empty space tests
{"Name" : "empty space test 1",
"Sequence" : RIGHT + LEFT + CTRL_B + CTRL_F + ENTER,
"Result" : PROMPT},
{"Name" : "empty space test 2",
"Sequence" : BKSPACE + ENTER,
"Result" : PROMPT},
{"Name" : "empty space test 3",
"Sequence" : CTRL_E*2 + CTRL_A*2 + ENTER,
"Result" : PROMPT},
{"Name" : "empty space test 4",
"Sequence" : ALT_F*2 + ALT_B*2 + ENTER,
"Result" : PROMPT},
{"Name" : "empty space test 5",
"Sequence" : " " + CTRL_E*2 + CTRL_A*2 + ENTER,
"Result" : PROMPT},
{"Name" : "empty space test 6",
"Sequence" : " " + CTRL_A + ALT_F*2 + ALT_B*2 + ENTER,
"Result" : PROMPT},
{"Name" : "empty space test 7",
"Sequence" : " " + CTRL_A + CTRL_D + CTRL_E + CTRL_D + ENTER,
"Result" : PROMPT},
{"Name" : "empty space test 8",
"Sequence" : " space" + CTRL_W*2 + ENTER,
"Result" : PROMPT},
{"Name" : "empty space test 9",
"Sequence" : " space" + ALT_BKSPACE*2 + ENTER,
"Result" : PROMPT},
{"Name" : "empty space test 10",
"Sequence" : " space " + CTRL_A + ALT_D*3 + ENTER,
"Result" : PROMPT},
# non-printable char tests
{"Name" : "non-printable test 1",
"Sequence" : chr(27) + chr(47) + ENTER,
"Result" : PROMPT},
{"Name" : "non-printable test 2",
"Sequence" : chr(27) + chr(128) + ENTER*7,
"Result" : PROMPT},
{"Name" : "non-printable test 3",
"Sequence" : chr(27) + chr(91) + chr(127) + ENTER*6,
"Result" : PROMPT},
# miscellaneous tests
{"Name" : "misc test 1",
"Sequence" : ENTER,
"Result" : PROMPT},
{"Name" : "misc test 2",
"Sequence" : "single #comment" + ENTER,
"Result" : SINGLE},
{"Name" : "misc test 3",
"Sequence" : "#empty line" + ENTER,
"Result" : PROMPT},
{"Name" : "misc test 4",
"Sequence" : " single " + ENTER,
"Result" : SINGLE},
{"Name" : "misc test 5",
"Sequence" : "single#" + ENTER,
"Result" : SINGLE},
{"Name" : "misc test 6",
"Sequence" : 'a' * 257 + ENTER,
"Result" : NOT_FOUND},
{"Name" : "misc test 7",
"Sequence" : "clear_history" + UP*5 + DOWN*5 + ENTER,
"Result" : PROMPT},
{"Name" : "misc test 8",
"Sequence" : "a" + HELP + CTRL_C,
"Result" : PROMPT},
{"Name" : "misc test 9",
"Sequence" : CTRL_D*3,
"Result" : None},
]

390
app/cmdline_test/commands.c Normal file
View File

@ -0,0 +1,390 @@
/*-
* BSD LICENSE
*
* Copyright(c) 2010-2012 Intel Corporation. All rights reserved.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Intel Corporation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#include <stdio.h>
#include <stdlib.h>
#include <termios.h>
#include <inttypes.h>
#include <cmdline_rdline.h>
#include <cmdline_parse.h>
#include <cmdline_parse_string.h>
#include <cmdline_parse_num.h>
#include <cmdline.h>
#include "cmdline_test.h"
/*** quit ***/
/* exit application */
struct cmd_quit_result {
cmdline_fixed_string_t quit;
};
static void
cmd_quit_parsed(__attribute__((unused)) void *parsed_result,
struct cmdline *cl,
__attribute__((unused)) void *data)
{
cmdline_quit(cl);
}
cmdline_parse_token_string_t cmd_quit_tok =
TOKEN_STRING_INITIALIZER(struct cmd_quit_result, quit,
"quit");
cmdline_parse_inst_t cmd_quit = {
.f = cmd_quit_parsed, /* function to call */
.data = NULL, /* 2nd arg of func */
.help_str = "exit application",
.tokens = { /* token list, NULL terminated */
(void *)&cmd_quit_tok,
NULL,
},
};
/*** single ***/
/* a simple single-word command */
struct cmd_single_result {
cmdline_fixed_string_t single;
};
static void
cmd_single_parsed(__attribute__((unused)) void *parsed_result,
struct cmdline *cl,
__attribute__((unused)) void *data)
{
cmdline_printf(cl, "Single word command parsed!\n");
}
cmdline_parse_token_string_t cmd_single_tok =
TOKEN_STRING_INITIALIZER(struct cmd_single_result, single,
"single");
cmdline_parse_inst_t cmd_single = {
.f = cmd_single_parsed, /* function to call */
.data = NULL, /* 2nd arg of func */
.help_str = "a simple single-word command",
.tokens = { /* token list, NULL terminated */
(void *)&cmd_single_tok,
NULL,
},
};
/*** single_long ***/
/* a variant of "single" command. useful to test autocomplete */
struct cmd_single_long_result {
cmdline_fixed_string_t single_long;
};
static void
cmd_single_long_parsed(__attribute__((unused)) void *parsed_result,
struct cmdline *cl,
__attribute__((unused)) void *data)
{
cmdline_printf(cl, "Single long word command parsed!\n");
}
cmdline_parse_token_string_t cmd_single_long_tok =
TOKEN_STRING_INITIALIZER(struct cmd_single_long_result, single_long,
"single_long");
cmdline_parse_inst_t cmd_single_long = {
.f = cmd_single_long_parsed, /* function to call */
.data = NULL, /* 2nd arg of func */
.help_str = "a variant of \"single\" command, useful to test autocomplete",
.tokens = { /* token list, NULL terminated */
(void *)&cmd_single_long_tok,
NULL,
},
};
/*** autocomplete_1 ***/
/* first command to test autocomplete when multiple commands have chars
* in common but none should complete due to ambiguity
*/
struct cmd_autocomplete_1_result {
cmdline_fixed_string_t token;
};
static void
cmd_autocomplete_1_parsed(__attribute__((unused)) void *parsed_result,
struct cmdline *cl,
__attribute__((unused)) void *data)
{
cmdline_printf(cl, "Autocomplete command 1 parsed!\n");
}
cmdline_parse_token_string_t cmd_autocomplete_1_tok =
TOKEN_STRING_INITIALIZER(struct cmd_autocomplete_1_result, token,
"autocomplete_1");
cmdline_parse_inst_t cmd_autocomplete_1 = {
.f = cmd_autocomplete_1_parsed, /* function to call */
.data = NULL, /* 2nd arg of func */
.help_str = "first ambiguous autocomplete command",
.tokens = { /* token list, NULL terminated */
(void *)&cmd_autocomplete_1_tok,
NULL,
},
};
/*** autocomplete_2 ***/
/* second command to test autocomplete when multiple commands have chars
* in common but none should complete due to ambiguity
*/
struct cmd_autocomplete_2_result {
cmdline_fixed_string_t token;
};
static void
cmd_autocomplete_2_parsed(__attribute__((unused)) void *parsed_result,
struct cmdline *cl,
__attribute__((unused)) void *data)
{
cmdline_printf(cl, "Autocomplete command 2 parsed!\n");
}
cmdline_parse_token_string_t cmd_autocomplete_2_tok =
TOKEN_STRING_INITIALIZER(struct cmd_autocomplete_2_result, token,
"autocomplete_2");
cmdline_parse_inst_t cmd_autocomplete_2 = {
.f = cmd_autocomplete_2_parsed, /* function to call */
.data = NULL, /* 2nd arg of func */
.help_str = "second ambiguous autocomplete command",
.tokens = { /* token list, NULL terminated */
(void *)&cmd_autocomplete_2_tok,
NULL,
},
};
/*** number command ***/
/* a command that simply returns whatever (uint32) number is supplied to it */
struct cmd_num_result {
unsigned num;
};
static void
cmd_num_parsed(void *parsed_result,
struct cmdline *cl,
__attribute__((unused)) void *data)
{
unsigned result = ((struct cmd_num_result*)parsed_result)->num;
cmdline_printf(cl, "%u\n", result);
}
cmdline_parse_token_num_t cmd_num_tok =
TOKEN_NUM_INITIALIZER(struct cmd_num_result, num, UINT32);
cmdline_parse_inst_t cmd_num = {
.f = cmd_num_parsed, /* function to call */
.data = NULL, /* 2nd arg of func */
.help_str = "a command that simply returns whatever number is entered",
.tokens = { /* token list, NULL terminated */
(void *)&cmd_num_tok,
NULL,
},
};
/*** ambiguous first|ambiguous ***/
/* first command used to test command ambiguity */
struct cmd_ambig_result_1 {
cmdline_fixed_string_t common_part;
cmdline_fixed_string_t ambig_part;
};
static void
cmd_ambig_1_parsed(__attribute__((unused)) void *parsed_result,
struct cmdline *cl,
__attribute__((unused)) void *data)
{
cmdline_printf(cl, "Command 1 parsed!\n");
}
cmdline_parse_token_string_t cmd_ambig_common_1 =
TOKEN_STRING_INITIALIZER(struct cmd_ambig_result_1, common_part,
"ambiguous");
cmdline_parse_token_string_t cmd_ambig_ambig_1 =
TOKEN_STRING_INITIALIZER(struct cmd_ambig_result_1, ambig_part,
"first#ambiguous#ambiguous2");
cmdline_parse_inst_t cmd_ambig_1 = {
.f = cmd_ambig_1_parsed, /* function to call */
.data = NULL, /* 2nd arg of func */
.help_str = "first command used to test command ambiguity",
.tokens = { /* token list, NULL terminated */
(void *)&cmd_ambig_common_1,
(void*)&cmd_ambig_ambig_1,
NULL,
},
};
/*** ambiguous second|ambiguous ***/
/* second command used to test command ambiguity */
struct cmd_ambig_result_2 {
cmdline_fixed_string_t common_part;
cmdline_fixed_string_t ambig_part;
};
static void
cmd_ambig_2_parsed(__attribute__((unused)) void *parsed_result,
struct cmdline *cl,
__attribute__((unused)) void *data)
{
cmdline_printf(cl, "Command 2 parsed!\n");
}
cmdline_parse_token_string_t cmd_ambig_common_2 =
TOKEN_STRING_INITIALIZER(struct cmd_ambig_result_2, common_part,
"ambiguous");
cmdline_parse_token_string_t cmd_ambig_ambig_2 =
TOKEN_STRING_INITIALIZER(struct cmd_ambig_result_2, ambig_part,
"second#ambiguous#ambiguous2");
cmdline_parse_inst_t cmd_ambig_2 = {
.f = cmd_ambig_2_parsed, /* function to call */
.data = NULL, /* 2nd arg of func */
.help_str = "second command used to test command ambiguity",
.tokens = { /* token list, NULL terminated */
(void *)&cmd_ambig_common_2,
(void*)&cmd_ambig_ambig_2,
NULL,
},
};
/*** get_history_bufsize ***/
/* command that displays total space in history buffer
* this will be useful for testing history (to fill it up just enough to
* remove the last entry, we need to know how big it is).
*/
struct cmd_get_history_bufsize_result {
cmdline_fixed_string_t str;
};
static void
cmd_get_history_bufsize_parsed(__attribute__((unused)) void *parsed_result,
struct cmdline *cl,
__attribute__((unused)) void *data)
{
cmdline_printf(cl, "History buffer size: %u\n",
sizeof(cl->rdl.history_buf));
}
cmdline_parse_token_string_t cmd_get_history_bufsize_tok =
TOKEN_STRING_INITIALIZER(struct cmd_get_history_bufsize_result, str,
"get_history_bufsize");
cmdline_parse_inst_t cmd_get_history_bufsize = {
.f = cmd_get_history_bufsize_parsed, /* function to call */
.data = NULL, /* 2nd arg of func */
.help_str = "command that displays total space in history buffer",
.tokens = { /* token list, NULL terminated */
(void *)&cmd_get_history_bufsize_tok,
NULL,
},
};
/*** clear_history ***/
/* clears history buffer */
struct cmd_clear_history_result {
cmdline_fixed_string_t str;
};
static void
cmd_clear_history_parsed(__attribute__((unused)) void *parsed_result,
struct cmdline *cl,
__attribute__((unused)) void *data)
{
rdline_clear_history(&cl->rdl);
}
cmdline_parse_token_string_t cmd_clear_history_tok =
TOKEN_STRING_INITIALIZER(struct cmd_clear_history_result, str,
"clear_history");
cmdline_parse_inst_t cmd_clear_history = {
.f = cmd_clear_history_parsed, /* function to call */
.data = NULL, /* 2nd arg of func */
.help_str = "clear command history",
.tokens = { /* token list, NULL terminated */
(void *)&cmd_clear_history_tok,
NULL,
},
};
/****************/
cmdline_parse_ctx_t main_ctx[] = {
(cmdline_parse_inst_t *)&cmd_quit,
(cmdline_parse_inst_t *)&cmd_ambig_1,
(cmdline_parse_inst_t *)&cmd_ambig_2,
(cmdline_parse_inst_t *)&cmd_single,
(cmdline_parse_inst_t *)&cmd_single_long,
(cmdline_parse_inst_t *)&cmd_num,
(cmdline_parse_inst_t *)&cmd_get_history_bufsize,
(cmdline_parse_inst_t *)&cmd_clear_history,
(cmdline_parse_inst_t *)&cmd_autocomplete_1,
(cmdline_parse_inst_t *)&cmd_autocomplete_2,
NULL,
};

View File

@ -72,6 +72,14 @@ SRCS-$(CONFIG_RTE_APP_TEST) += test_alarm.c
SRCS-$(CONFIG_RTE_APP_TEST) += test_interrupts.c
SRCS-$(CONFIG_RTE_APP_TEST) += test_version.c
SRCS-$(CONFIG_RTE_APP_TEST) += test_eal_fs.c
SRCS-$(CONFIG_RTE_APP_TEST) += test_cmdline.c
SRCS-$(CONFIG_RTE_APP_TEST) += test_cmdline_num.c
SRCS-$(CONFIG_RTE_APP_TEST) += test_cmdline_etheraddr.c
SRCS-$(CONFIG_RTE_APP_TEST) += test_cmdline_portlist.c
SRCS-$(CONFIG_RTE_APP_TEST) += test_cmdline_ipaddr.c
SRCS-$(CONFIG_RTE_APP_TEST) += test_cmdline_cirbuf.c
SRCS-$(CONFIG_RTE_APP_TEST) += test_cmdline_string.c
SRCS-$(CONFIG_RTE_APP_TEST) += test_cmdline_lib.c
CFLAGS += -O3
CFLAGS += $(WERROR_FLAGS)

View File

@ -129,6 +129,8 @@ static void cmd_autotest_parsed(void *parsed_result,
ret |= test_lpm();
if (all || !strcmp(res->autotest, "cpuflags_autotest"))
ret |= test_cpuflags();
if (all || !strcmp(res->autotest, "cmdline_autotest"))
ret |= test_cmdline();
/* tailq autotest must go after all lpm and hashs tests or any other
* tests which need to create tailq objects (ring and mempool are implicitly
* created in earlier tests so can go later)
@ -180,6 +182,7 @@ cmdline_parse_token_string_t cmd_autotest_autotest =
"cpuflags_autotest#eal_flags_autotest#"
"alarm_autotest#interrupt_autotest#"
"version_autotest#eal_fs_autotest#"
"cmdline_autotest#"
"all_autotests");
cmdline_parse_inst_t cmd_autotest = {

View File

@ -80,6 +80,7 @@ int test_alarm(void);
int test_interrupt(void);
int test_version(void);
int test_eal_fs(void);
int test_cmdline(void);
int test_pci_run;

94
app/test/test_cmdline.c Normal file
View File

@ -0,0 +1,94 @@
/*-
* BSD LICENSE
*
* Copyright(c) 2010-2012 Intel Corporation. All rights reserved.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Intel Corporation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#include <stdio.h>
#include <cmdline_parse.h>
#include "test.h"
#include "test_cmdline.h"
int
test_cmdline(void)
{
printf("Testind parsing ethernet addresses...\n");
if (test_parse_etheraddr_valid() < 0)
return -1;
if (test_parse_etheraddr_invalid_data() < 0)
return -1;
if (test_parse_etheraddr_invalid_param() < 0)
return -1;
printf("Testind parsing port lists...\n");
if (test_parse_portlist_valid() < 0)
return -1;
if (test_parse_portlist_invalid_data() < 0)
return -1;
if (test_parse_portlist_invalid_param() < 0)
return -1;
printf("Testind parsing numbers...\n");
if (test_parse_num_valid() < 0)
return -1;
if (test_parse_num_invalid_data() < 0)
return -1;
if (test_parse_num_invalid_param() < 0)
return -1;
printf("Testing parsing IP addresses...\n");
if (test_parse_ipaddr_valid() < 0)
return -1;
if (test_parse_ipaddr_invalid_data() < 0)
return -1;
if (test_parse_ipaddr_invalid_param() < 0)
return -1;
printf("Testing parsing strings...\n");
if (test_parse_string_valid() < 0)
return -1;
if (test_parse_string_invalid_data() < 0)
return -1;
if (test_parse_string_invalid_param() < 0)
return -1;
printf("Testing circular buffer...\n");
if (test_cirbuf_char() < 0)
return -1;
if (test_cirbuf_string() < 0)
return -1;
if (test_cirbuf_align() < 0)
return -1;
if (test_cirbuf_invalid_param() < 0)
return -1;
printf("Testing library functions...\n");
if (test_cmdline_lib() < 0)
return -1;
return 0;
}

74
app/test/test_cmdline.h Normal file
View File

@ -0,0 +1,74 @@
/*-
* BSD LICENSE
*
* Copyright(c) 2010-2012 Intel Corporation. All rights reserved.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Intel Corporation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#ifndef TEST_CMDLINE_H_
#define TEST_CMDLINE_H_
#define CMDLINE_TEST_BUFSIZE 64
/* cmdline_parse_num tests */
int test_parse_num_valid(void);
int test_parse_num_invalid_data(void);
int test_parse_num_invalid_param(void);
/* cmdline_parse_etheraddr tests */
int test_parse_etheraddr_valid(void);
int test_parse_etheraddr_invalid_data(void);
int test_parse_etheraddr_invalid_param(void);
/* cmdline_parse_portlist tests */
int test_parse_portlist_valid(void);
int test_parse_portlist_invalid_data(void);
int test_parse_portlist_invalid_param(void);
/* cmdline_parse_ipaddr tests */
int test_parse_ipaddr_valid(void);
int test_parse_ipaddr_invalid_data(void);
int test_parse_ipaddr_invalid_param(void);
/* cmdline_parse_string tests */
int test_parse_string_valid(void);
int test_parse_string_invalid_data(void);
int test_parse_string_invalid_param(void);
/* cmdline_cirbuf tests */
int test_cirbuf_invalid_param(void);
int test_cirbuf_char(void);
int test_cirbuf_string(void);
int test_cirbuf_align(void);
/* test the rest of the library */
int test_cmdline_lib(void);
#endif /* TEST_CMDLINE_H_ */

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,254 @@
/*-
* BSD LICENSE
*
* Copyright(c) 2010-2012 Intel Corporation. All rights reserved.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Intel Corporation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#include <stdio.h>
#include <string.h>
#include <inttypes.h>
#include <rte_ether.h>
#include <rte_string_fns.h>
#include <cmdline_parse.h>
#include <cmdline_parse_etheraddr.h>
#include "test_cmdline.h"
struct ether_addr_str {
const char * str;
uint64_t address;
};
/* valid strings */
const struct ether_addr_str ether_addr_valid_strs[] = {
{"01:23:45:67:89:AB", 0xAB8967452301ULL},
{"4567:89AB:CDEF", 0xEFCDAB896745ULL},
};
/* valid strings with various garbage at the end.
* these strings are still valid because parser checks for
* end of token, which is either space chars, null char or
* a hash sign.
*/
const char * ether_addr_garbage_strs[] = {
"00:11:22:33:44:55\0garbage",
"00:11:22:33:44:55#garbage",
"00:11:22:33:44:55 garbage",
"00:11:22:33:44:55\tgarbage",
"00:11:22:33:44:55\ngarbage",
"00:11:22:33:44:55\rgarbage",
"00:11:22:33:44:55#",
"00:11:22:33:44:55 ",
"00:11:22:33:44:55\t",
"00:11:22:33:44:55\n",
"00:11:22:33:44:55\r",
};
#define GARBAGE_ETHERADDR 0x554433221100ULL /* corresponding address */
const char * ether_addr_invalid_strs[] = {
/* valid chars, invalid syntax */
"0123:45:67:89:AB",
"01:23:4567:89:AB",
"01:23:45:67:89AB",
"012:345:678:9AB",
"01:23:45:67:89:ABC",
"01:23:45:67:89:A",
"01:23:45:67:89",
"01:23:45:67:89:AB:CD",
/* invalid chars, valid syntax */
"IN:VA:LI:DC:HA:RS",
"INVA:LIDC:HARS",
/* misc */
"01 23 45 67 89 AB",
"01.23.45.67.89.AB",
"01,23,45,67,89,AB",
"01:23:45\0:67:89:AB",
"01:23:45#:67:89:AB",
"random invalid text",
"random text",
"",
"\0",
" ",
};
#define ETHERADDR_VALID_STRS_SIZE \
(sizeof(ether_addr_valid_strs) / sizeof(ether_addr_valid_strs[0]))
#define ETHERADDR_GARBAGE_STRS_SIZE \
(sizeof(ether_addr_garbage_strs) / sizeof(ether_addr_garbage_strs[0]))
#define ETHERADDR_INVALID_STRS_SIZE \
(sizeof(ether_addr_invalid_strs) / sizeof(ether_addr_invalid_strs[0]))
static int
is_addr_different(const struct ether_addr addr, uint64_t num)
{
int i;
for (i = 0; i < ETHER_ADDR_LEN; i++, num >>= 8)
if (addr.addr_bytes[i] != (num & 0xFF)) {
return 1;
}
return 0;
}
/* test invalid parameters */
int
test_parse_etheraddr_invalid_param(void)
{
char buf[CMDLINE_TEST_BUFSIZE];
struct ether_addr result;
int ret = 0;
/* try all null */
ret = cmdline_parse_etheraddr(NULL, NULL, NULL);
if (ret != -1) {
printf("Error: parser accepted null parameters!\n");
return -1;
}
/* try null buf */
ret = cmdline_parse_etheraddr(NULL, NULL, (void*)&result);
if (ret != -1) {
printf("Error: parser accepted null string!\n");
return -1;
}
/* try null result */
/* copy string to buffer */
rte_snprintf(buf, sizeof(buf), "%s",
ether_addr_valid_strs[0]);
ret = cmdline_parse_etheraddr(NULL, buf, NULL);
if (ret == -1) {
printf("Error: parser rejected null result!\n");
return -1;
}
/* token is not used in ether_parse anyway so there's no point in
* testing it */
/* test help function */
memset(&buf, 0, sizeof(buf));
/* try null buf */
ret = cmdline_get_help_etheraddr(NULL, NULL, sizeof(buf));
if (ret != -1) {
printf("Error: help function accepted null buffer!\n");
return -1;
}
/* coverage! */
ret = cmdline_get_help_etheraddr(NULL, buf, sizeof(buf));
if (ret < 0) {
printf("Error: help function failed with valid parameters!\n");
return -1;
}
return 0;
}
/* test valid parameters but invalid data */
int
test_parse_etheraddr_invalid_data(void)
{
int ret = 0;
unsigned i;
struct ether_addr result;
/* test full strings */
for (i = 0; i < ETHERADDR_INVALID_STRS_SIZE; i++) {
memset(&result, 0, sizeof(struct ether_addr));
ret = cmdline_parse_etheraddr(NULL, ether_addr_invalid_strs[i],
(void*)&result);
if (ret != -1) {
printf("Error: parsing %s succeeded!\n",
ether_addr_invalid_strs[i]);
return -1;
}
}
return 0;
}
/* test valid parameters and data */
int
test_parse_etheraddr_valid(void)
{
int ret = 0;
unsigned i;
struct ether_addr result;
/* test full strings */
for (i = 0; i < ETHERADDR_VALID_STRS_SIZE; i++) {
memset(&result, 0, sizeof(struct ether_addr));
ret = cmdline_parse_etheraddr(NULL, ether_addr_valid_strs[i].str,
(void*)&result);
if (ret < 0) {
printf("Error: parsing %s failed!\n",
ether_addr_valid_strs[i].str);
return -1;
}
if (is_addr_different(result, ether_addr_valid_strs[i].address)) {
printf("Error: parsing %s failed: address mismatch!\n",
ether_addr_valid_strs[i].str);
return -1;
}
}
/* test garbage strings */
for (i = 0; i < ETHERADDR_GARBAGE_STRS_SIZE; i++) {
memset(&result, 0, sizeof(struct ether_addr));
ret = cmdline_parse_etheraddr(NULL, ether_addr_garbage_strs[i],
(void*)&result);
if (ret < 0) {
printf("Error: parsing %s failed!\n",
ether_addr_garbage_strs[i]);
return -1;
}
if (is_addr_different(result, GARBAGE_ETHERADDR)) {
printf("Error: parsing %s failed: address mismatch!\n",
ether_addr_garbage_strs[i]);
return -1;
}
}
return 0;
}

View File

@ -0,0 +1,707 @@
/*-
* BSD LICENSE
*
* Copyright(c) 2010-2012 Intel Corporation. All rights reserved.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Intel Corporation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#include <stdio.h>
#include <string.h>
#include <inttypes.h>
#include <netinet/in.h>
#ifndef __linux__
#include <net/socket.h>
#endif
#include <rte_string_fns.h>
#include <cmdline_parse.h>
#include <cmdline_parse_ipaddr.h>
#include "test_cmdline.h"
#define IP4(a,b,c,d) {((uint32_t)(((a) & 0xff)) | \
(((b) & 0xff) << 8) | \
(((c) & 0xff) << 16) | \
((d) & 0xff) << 24)}
#define U16_SWAP(x) \
(((x & 0xFF) << 8) | ((x & 0xFF00) >> 8))
/* create IPv6 address, swapping bytes where needed */
#define IP6(a,b,c,d,e,f,g,h) .ipv6 = \
{.s6_addr16 = \
{U16_SWAP(a),U16_SWAP(b),U16_SWAP(c),U16_SWAP(d),\
U16_SWAP(e),U16_SWAP(f),U16_SWAP(g),U16_SWAP(h)}}
/** these are defined in netinet/in.h but not present in linux headers */
#ifdef __linux__
#define NIPQUAD_FMT "%u.%u.%u.%u"
#define NIPQUAD(addr) \
(unsigned)((unsigned char *)&addr)[0], \
(unsigned)((unsigned char *)&addr)[1], \
(unsigned)((unsigned char *)&addr)[2], \
(unsigned)((unsigned char *)&addr)[3]
#define NIP6_FMT "%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x"
#define NIP6(addr) \
(unsigned)((addr).s6_addr[0]), \
(unsigned)((addr).s6_addr[1]), \
(unsigned)((addr).s6_addr[2]), \
(unsigned)((addr).s6_addr[3]), \
(unsigned)((addr).s6_addr[4]), \
(unsigned)((addr).s6_addr[5]), \
(unsigned)((addr).s6_addr[6]), \
(unsigned)((addr).s6_addr[7]), \
(unsigned)((addr).s6_addr[8]), \
(unsigned)((addr).s6_addr[9]), \
(unsigned)((addr).s6_addr[10]), \
(unsigned)((addr).s6_addr[11]), \
(unsigned)((addr).s6_addr[12]), \
(unsigned)((addr).s6_addr[13]), \
(unsigned)((addr).s6_addr[14]), \
(unsigned)((addr).s6_addr[15])
#endif
struct ipaddr_str {
const char * str;
cmdline_ipaddr_t addr;
unsigned flags;
};
const struct ipaddr_str ipaddr_valid_strs[] = {
{"0.0.0.0", {AF_INET, {IP4(0,0,0,0)}, 0},
CMDLINE_IPADDR_V4},
{"0.0.0.0/0", {AF_INET, {IP4(0,0,0,0)}, 0},
CMDLINE_IPADDR_V4 | CMDLINE_IPADDR_NETWORK},
{"0.0.0.0/24", {AF_INET, {IP4(0,0,0,0)}, 24},
CMDLINE_IPADDR_V4 | CMDLINE_IPADDR_NETWORK},
{"192.168.1.0/24", {AF_INET, {IP4(192,168,1,0)}, 24},
CMDLINE_IPADDR_V4 | CMDLINE_IPADDR_NETWORK},
{"012.34.56.78/24", {AF_INET, {IP4(12,34,56,78)}, 24},
CMDLINE_IPADDR_V4 | CMDLINE_IPADDR_NETWORK},
{"34.56.78.90/1", {AF_INET, {IP4(34,56,78,90)}, 1},
CMDLINE_IPADDR_V4 | CMDLINE_IPADDR_NETWORK},
{"::", {AF_INET6, {IP6(0,0,0,0,0,0,0,0)}, 0},
CMDLINE_IPADDR_V6},
{"::1", {AF_INET6, {IP6(0,0,0,0,0,0,0,1)}, 0},
CMDLINE_IPADDR_V6},
{"::1/32", {AF_INET6, {IP6(0,0,0,0,0,0,0,1)}, 32},
CMDLINE_IPADDR_V6 | CMDLINE_IPADDR_NETWORK},
{"::/32", {AF_INET6, {IP6(0,0,0,0,0,0,0,0)}, 32},
CMDLINE_IPADDR_V6 | CMDLINE_IPADDR_NETWORK},
/* RFC5952 requests that only lowercase should be used */
{"1234:5678:90ab:cdef:4321:8765:BA09:FEDC", {AF_INET6,
{IP6(0x1234,0x5678,0x90AB,0xCDEF,0x4321,0x8765,0xBA09,0xFEDC)},
0},
CMDLINE_IPADDR_V6},
{"1234::1234/64", {AF_INET6,
{IP6(0x1234,0,0,0,0,0,0,0x1234)},
64},
CMDLINE_IPADDR_V6 | CMDLINE_IPADDR_NETWORK},
{"1234::/64", {AF_INET6,
{IP6(0x1234,0,0,0,0,0,0,0)},
64},
CMDLINE_IPADDR_V6 | CMDLINE_IPADDR_NETWORK},
{"1:1::1/32", {AF_INET6,
{IP6(1,1,0,0,0,0,0,1)},
32},
CMDLINE_IPADDR_V6 | CMDLINE_IPADDR_NETWORK},
{"1:2:3:4::/64", {AF_INET6,
{IP6(1,2,3,4,0,0,0,0)},
64},
CMDLINE_IPADDR_V6 | CMDLINE_IPADDR_NETWORK},
{"::ffff:192.168.1.0/64", {AF_INET6,
{IP6(0,0,0,0,0,0xFFFF,0xC0A8,0x100)},
64},
CMDLINE_IPADDR_V6 | CMDLINE_IPADDR_NETWORK},
/* RFC5952 requests not using :: to skip one block of zeros*/
{"1::2:3:4:5:6:7", {AF_INET6,
{IP6(1,0,2,3,4,5,6,7)},
0},
CMDLINE_IPADDR_V6},
};
const char * ipaddr_garbage_addr4_strs[] = {
/* IPv4 */
"192.168.1.0 garbage",
"192.168.1.0\0garbage",
"192.168.1.0#garbage",
"192.168.1.0\tgarbage",
"192.168.1.0\rgarbage",
"192.168.1.0\ngarbage",
};
#define IPv4_GARBAGE_ADDR IP4(192,168,1,0)
const char * ipaddr_garbage_addr6_strs[] = {
/* IPv6 */
"1:2:3:4::8 garbage",
"1:2:3:4::8#garbage",
"1:2:3:4::8\0garbage",
"1:2:3:4::8\rgarbage",
"1:2:3:4::8\ngarbage",
"1:2:3:4::8\tgarbage",
};
#define IPv6_GARBAGE_ADDR {IP6(1,2,3,4,0,0,0,8)}
const char * ipaddr_garbage_network4_strs[] = {
/* IPv4 */
"192.168.1.0/24 garbage",
"192.168.1.0/24\0garbage",
"192.168.1.0/24#garbage",
"192.168.1.0/24\tgarbage",
"192.168.1.0/24\rgarbage",
"192.168.1.0/24\ngarbage",
};
#define IPv4_GARBAGE_PREFIX 24
const char * ipaddr_garbage_network6_strs[] = {
/* IPv6 */
"1:2:3:4::8/64 garbage",
"1:2:3:4::8/64#garbage",
"1:2:3:4::8/64\0garbage",
"1:2:3:4::8/64\rgarbage",
"1:2:3:4::8/64\ngarbage",
"1:2:3:4::8/64\tgarbage",
};
#define IPv6_GARBAGE_PREFIX 64
const char * ipaddr_invalid_strs[] = {
/** IPv4 **/
/* invalid numbers */
"0.0.0.-1",
"0.0.-1.0",
"0.-1.0.0",
"-1.0.0.0",
"0.0.0.-1/24",
"256.123.123.123",
"255.256.123.123",
"255.255.256.123",
"255.255.255.256",
"256.123.123.123/24",
"255.256.123.123/24",
"255.255.256.123/24",
"255.255.255.256/24",
/* invalid network mask */
"1.2.3.4/33",
"1.2.3.4/33231313",
"1.2.3.4/-1",
"1.2.3.4/24/33",
"1.2.3.4/24/-1",
"1.2.3.4/24/",
/* wrong format */
"1/24"
"/24"
"123.123.123",
"123.123.123.",
"123.123.123.123.",
"123.123.123..123",
"123.123.123.123.123",
".123.123.123",
".123.123.123.123",
"123.123.123/24",
"123.123.123./24",
"123.123.123.123./24",
"123.123.123..123/24",
"123.123.123.123.123/24",
".123.123.123/24",
".123.123.123.123/24",
/* invalid characters */
"123.123.123.12F",
"123.123.12F.123",
"123.12F.123.123",
"12F.123.123.123",
"12J.123.123.123",
"123,123,123,123",
"123!123!123!12F",
"123.123.123.123/4F",
/** IPv6 **/
/* wrong format */
"::fffff",
"ffff:",
"1:2:3:4:5:6:7:192.168.1.1",
"1234:192.168.1.1:ffff::",
"1:2:3:4:5:6:7:890ab",
"1:2:3:4:5:6:7890a:b",
"1:2:3:4:5:67890:a:b",
"1:2:3:4:56789:0:a:b",
"1:2:3:45678:9:0:a:b",
"1:2:34567:8:9:0:a:b",
"1:23456:7:8:9:0:a:b",
"12345:6:7:8:9:0:a:b",
"1:::2",
"1::::2",
"::fffff/64",
"1::2::3",
"1::2::3/64",
":1:2",
":1:2/64",
":1::2",
":1::2/64",
"1::2:3:4:5:6:7:8/64",
/* invalid network mask */
"1:2:3:4:5:6:7:8/129",
"1:2:3:4:5:6:7:8/-1",
/* invalid characters */
"a:b:c:d:e:f:g::",
/** misc **/
/* too long */
"1234:1234:1234:1234:1234:1234:1234:1234:1234:1234:1234"
"random invalid text",
"",
"\0",
" ",
};
#define IPADDR_VALID_STRS_SIZE \
(sizeof(ipaddr_valid_strs) / sizeof(ipaddr_valid_strs[0]))
#define IPADDR_GARBAGE_ADDR4_STRS_SIZE \
(sizeof(ipaddr_garbage_addr4_strs) / sizeof(ipaddr_garbage_addr4_strs[0]))
#define IPADDR_GARBAGE_ADDR6_STRS_SIZE \
(sizeof(ipaddr_garbage_addr6_strs) / sizeof(ipaddr_garbage_addr6_strs[0]))
#define IPADDR_GARBAGE_NETWORK4_STRS_SIZE \
(sizeof(ipaddr_garbage_network4_strs) / sizeof(ipaddr_garbage_network4_strs[0]))
#define IPADDR_GARBAGE_NETWORK6_STRS_SIZE \
(sizeof(ipaddr_garbage_network6_strs) / sizeof(ipaddr_garbage_network6_strs[0]))
#define IPADDR_INVALID_STRS_SIZE \
(sizeof(ipaddr_invalid_strs) / sizeof(ipaddr_invalid_strs[0]))
static void
dump_addr(cmdline_ipaddr_t addr)
{
switch (addr.family) {
case AF_INET:
{
printf(NIPQUAD_FMT " prefixlen=%u\n",
NIPQUAD(addr.addr.ipv4.s_addr), addr.prefixlen);
break;
}
case AF_INET6:
{
printf(NIP6_FMT " prefixlen=%u\n",
NIP6(addr.addr.ipv6), addr.prefixlen);
break;
}
default:
printf("Can't dump: unknown address family.\n");
return;
}
}
static int
is_addr_different(cmdline_ipaddr_t addr1, cmdline_ipaddr_t addr2)
{
if (addr1.family != addr2.family)
return 1;
if (addr1.prefixlen != addr2.prefixlen)
return 1;
switch (addr1.family) {
/* IPv4 */
case AF_INET:
if (memcmp(&addr1.addr.ipv4, &addr2.addr.ipv4,
sizeof(struct in_addr)) != 0)
return 1;
break;
/* IPv6 */
case AF_INET6:
{
if (memcmp(&addr1.addr.ipv6, &addr2.addr.ipv6,
sizeof(struct in6_addr)) != 0)
return 1;
break;
}
/* thing that should not be */
default:
return -1;
}
return 0;
}
static int
can_parse_addr(unsigned addr_flags, unsigned test_flags)
{
if ((test_flags & addr_flags) == addr_flags) {
/* if we are not trying to parse network addresses */
if (test_flags < CMDLINE_IPADDR_NETWORK)
return 1;
/* if this is a network address */
else if (addr_flags & CMDLINE_IPADDR_NETWORK)
return 1;
}
return 0;
}
int
test_parse_ipaddr_valid(void)
{
cmdline_parse_token_ipaddr_t token;
char buf[CMDLINE_TEST_BUFSIZE];
cmdline_ipaddr_t result;
unsigned i;
uint8_t flags;
int ret;
/* cover all cases in help */
for (flags = 0x1; flags < 0x8; flags++) {
token.ipaddr_data.flags = flags;
memset(buf, 0, sizeof(buf));
if (cmdline_get_help_ipaddr((cmdline_parse_token_hdr_t*)&token,
buf, sizeof(buf)) == -1) {
printf("Error: help rejected valid parameters!\n");
return -1;
}
}
/* test valid strings */
for (i = 0; i < IPADDR_VALID_STRS_SIZE; i++) {
/* test each valid string against different flags */
for (flags = 1; flags < 0x8; flags++) {
/* skip bad flag */
if (flags == CMDLINE_IPADDR_NETWORK)
continue;
/* clear out everything */
memset(buf, 0, sizeof(buf));
memset(&result, 0, sizeof(result));
memset(&token, 0, sizeof(token));
token.ipaddr_data.flags = flags;
cmdline_get_help_ipaddr((cmdline_parse_token_hdr_t*)&token,
buf, sizeof(buf));
ret = cmdline_parse_ipaddr((cmdline_parse_token_hdr_t*)&token,
ipaddr_valid_strs[i].str, (void*)&result);
/* if should have passed, or should have failed */
if ((ret < 0) ==
(can_parse_addr(ipaddr_valid_strs[i].flags, flags))) {
printf("Error: unexpected behavior when parsing %s as %s!\n",
ipaddr_valid_strs[i].str, buf);
printf("Parsed result: ");
dump_addr(result);
printf("Expected result: ");
dump_addr(ipaddr_valid_strs[i].addr);
return -1;
}
if (ret != -1 &&
is_addr_different(result, ipaddr_valid_strs[i].addr)) {
printf("Error: result mismatch when parsing %s as %s!\n",
ipaddr_valid_strs[i].str, buf);
printf("Parsed result: ");
dump_addr(result);
printf("Expected result: ");
dump_addr(ipaddr_valid_strs[i].addr);
return -1;
}
}
}
/* test garbage ipv4 address strings */
for (i = 0; i < IPADDR_GARBAGE_ADDR4_STRS_SIZE; i++) {
struct in_addr tmp = IPv4_GARBAGE_ADDR;
/* test each valid string against different flags */
for (flags = 1; flags < 0x8; flags++) {
/* skip bad flag */
if (flags == CMDLINE_IPADDR_NETWORK)
continue;
/* clear out everything */
memset(buf, 0, sizeof(buf));
memset(&result, 0, sizeof(result));
memset(&token, 0, sizeof(token));
token.ipaddr_data.flags = flags;
cmdline_get_help_ipaddr((cmdline_parse_token_hdr_t*)&token,
buf, sizeof(buf));
ret = cmdline_parse_ipaddr((cmdline_parse_token_hdr_t*)&token,
ipaddr_garbage_addr4_strs[i], (void*)&result);
/* if should have passed, or should have failed */
if ((ret < 0) ==
(can_parse_addr(CMDLINE_IPADDR_V4, flags))) {
printf("Error: unexpected behavior when parsing %s as %s!\n",
ipaddr_garbage_addr4_strs[i], buf);
return -1;
}
if (ret != -1 &&
memcmp(&result.addr.ipv4, &tmp, sizeof(tmp))) {
printf("Error: result mismatch when parsing %s as %s!\n",
ipaddr_garbage_addr4_strs[i], buf);
return -1;
}
}
}
/* test garbage ipv6 address strings */
for (i = 0; i < IPADDR_GARBAGE_ADDR6_STRS_SIZE; i++) {
cmdline_ipaddr_t tmp = {.addr = IPv6_GARBAGE_ADDR};
/* test each valid string against different flags */
for (flags = 1; flags < 0x8; flags++) {
/* skip bad flag */
if (flags == CMDLINE_IPADDR_NETWORK)
continue;
/* clear out everything */
memset(buf, 0, sizeof(buf));
memset(&result, 0, sizeof(result));
memset(&token, 0, sizeof(token));
token.ipaddr_data.flags = flags;
cmdline_get_help_ipaddr((cmdline_parse_token_hdr_t*)&token,
buf, sizeof(buf));
ret = cmdline_parse_ipaddr((cmdline_parse_token_hdr_t*)&token,
ipaddr_garbage_addr6_strs[i], (void*)&result);
/* if should have passed, or should have failed */
if ((ret < 0) ==
(can_parse_addr(CMDLINE_IPADDR_V6, flags))) {
printf("Error: unexpected behavior when parsing %s as %s!\n",
ipaddr_garbage_addr6_strs[i], buf);
return -1;
}
if (ret != -1 &&
memcmp(&result.addr.ipv6, &tmp.addr.ipv6, sizeof(struct in6_addr))) {
printf("Error: result mismatch when parsing %s as %s!\n",
ipaddr_garbage_addr6_strs[i], buf);
return -1;
}
}
}
/* test garbage ipv4 network strings */
for (i = 0; i < IPADDR_GARBAGE_NETWORK4_STRS_SIZE; i++) {
struct in_addr tmp = IPv4_GARBAGE_ADDR;
/* test each valid string against different flags */
for (flags = 1; flags < 0x8; flags++) {
/* skip bad flag */
if (flags == CMDLINE_IPADDR_NETWORK)
continue;
/* clear out everything */
memset(buf, 0, sizeof(buf));
memset(&result, 0, sizeof(result));
memset(&token, 0, sizeof(token));
token.ipaddr_data.flags = flags;
cmdline_get_help_ipaddr((cmdline_parse_token_hdr_t*)&token,
buf, sizeof(buf));
ret = cmdline_parse_ipaddr((cmdline_parse_token_hdr_t*)&token,
ipaddr_garbage_network4_strs[i], (void*)&result);
/* if should have passed, or should have failed */
if ((ret < 0) ==
(can_parse_addr(CMDLINE_IPADDR_V4 | CMDLINE_IPADDR_NETWORK, flags))) {
printf("Error: unexpected behavior when parsing %s as %s!\n",
ipaddr_garbage_network4_strs[i], buf);
return -1;
}
if (ret != -1 &&
memcmp(&result.addr.ipv4, &tmp, sizeof(tmp))) {
printf("Error: result mismatch when parsing %s as %s!\n",
ipaddr_garbage_network4_strs[i], buf);
return -1;
}
}
}
/* test garbage ipv6 address strings */
for (i = 0; i < IPADDR_GARBAGE_NETWORK6_STRS_SIZE; i++) {
cmdline_ipaddr_t tmp = {.addr = IPv6_GARBAGE_ADDR};
/* test each valid string against different flags */
for (flags = 1; flags < 0x8; flags++) {
/* skip bad flag */
if (flags == CMDLINE_IPADDR_NETWORK)
continue;
/* clear out everything */
memset(buf, 0, sizeof(buf));
memset(&result, 0, sizeof(result));
memset(&token, 0, sizeof(token));
token.ipaddr_data.flags = flags;
cmdline_get_help_ipaddr((cmdline_parse_token_hdr_t*)&token,
buf, sizeof(buf));
ret = cmdline_parse_ipaddr((cmdline_parse_token_hdr_t*)&token,
ipaddr_garbage_network6_strs[i], (void*)&result);
/* if should have passed, or should have failed */
if ((ret < 0) ==
(can_parse_addr(CMDLINE_IPADDR_V6 | CMDLINE_IPADDR_NETWORK, flags))) {
printf("Error: unexpected behavior when parsing %s as %s!\n",
ipaddr_garbage_network6_strs[i], buf);
return -1;
}
if (ret != -1 &&
memcmp(&result.addr.ipv6, &tmp.addr.ipv6, sizeof(struct in6_addr))) {
printf("Error: result mismatch when parsing %s as %s!\n",
ipaddr_garbage_network6_strs[i], buf);
return -1;
}
}
}
return 0;
}
int
test_parse_ipaddr_invalid_data(void)
{
cmdline_parse_token_ipaddr_t token;
char buf[CMDLINE_TEST_BUFSIZE];
cmdline_ipaddr_t result;
unsigned i;
uint8_t flags;
int ret;
memset(&result, 0, sizeof(result));
/* test invalid strings */
for (i = 0; i < IPADDR_INVALID_STRS_SIZE; i++) {
/* test each valid string against different flags */
for (flags = 1; flags < 0x8; flags++) {
/* skip bad flag */
if (flags == CMDLINE_IPADDR_NETWORK)
continue;
/* clear out everything */
memset(buf, 0, sizeof(buf));
memset(&token, 0, sizeof(token));
token.ipaddr_data.flags = flags;
cmdline_get_help_ipaddr((cmdline_parse_token_hdr_t*)&token,
buf, sizeof(buf));
ret = cmdline_parse_ipaddr((cmdline_parse_token_hdr_t*)&token,
ipaddr_invalid_strs[i], (void*)&result);
if (ret != -1) {
printf("Error: parsing %s as %s succeeded!\n",
ipaddr_invalid_strs[i], buf);
printf("Parsed result: ");
dump_addr(result);
return -1;
}
}
}
return 0;
}
int
test_parse_ipaddr_invalid_param(void)
{
cmdline_parse_token_ipaddr_t token;
char buf[CMDLINE_TEST_BUFSIZE];
cmdline_ipaddr_t result;
rte_snprintf(buf, sizeof(buf), "1.2.3.4");
token.ipaddr_data.flags = CMDLINE_IPADDR_V4;
/* null token */
if (cmdline_parse_ipaddr(NULL, buf, (void*)&result) != -1) {
printf("Error: parser accepted invalid parameters!\n");
return -1;
}
/* null buffer */
if (cmdline_parse_ipaddr((cmdline_parse_token_hdr_t*)&token,
NULL, (void*)&result) != -1) {
printf("Error: parser accepted invalid parameters!\n");
return -1;
}
/* empty buffer */
if (cmdline_parse_ipaddr((cmdline_parse_token_hdr_t*)&token,
"", (void*)&result) != -1) {
printf("Error: parser accepted invalid parameters!\n");
return -1;
}
/* null result */
if (cmdline_parse_ipaddr((cmdline_parse_token_hdr_t*)&token,
buf, NULL) == -1) {
printf("Error: parser rejected null result!\n");
return -1;
}
/* null token */
if (cmdline_get_help_ipaddr(NULL, buf, 0) != -1) {
printf("Error: help accepted invalid parameters!\n");
return -1;
}
/* null buffer */
if (cmdline_get_help_ipaddr((cmdline_parse_token_hdr_t*)&token,
NULL, 0) != -1) {
printf("Error: help accepted invalid parameters!\n");
return -1;
}
return 0;
}

264
app/test/test_cmdline_lib.c Normal file
View File

@ -0,0 +1,264 @@
/*-
* BSD LICENSE
*
* Copyright(c) 2010-2012 Intel Corporation. All rights reserved.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Intel Corporation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#include <string.h>
#include <stdio.h>
#include <stdint.h>
#include <stdarg.h>
#include <stdlib.h>
#include <errno.h>
#include <termios.h>
#include <ctype.h>
#include <sys/queue.h>
#include <cmdline_vt100.h>
#include <cmdline_rdline.h>
#include <cmdline_parse.h>
#include <cmdline_socket.h>
#include <cmdline.h>
#include "test_cmdline.h"
/****************************************************************/
/* static functions required for some tests */
static void
valid_buffer(__attribute__((unused))struct rdline *rdl,
__attribute__((unused))const char *buf,
__attribute__((unused)) unsigned int size)
{
}
static int
complete_buffer(__attribute__((unused)) struct rdline *rdl,
__attribute__((unused)) const char *buf,
__attribute__((unused)) char *dstbuf,
__attribute__((unused)) unsigned int dstsize,
__attribute__((unused)) int *state)
{
return 0;
}
/****************************************************************/
static int
test_cmdline_parse_fns(void)
{
struct cmdline cl;
int i = 0;
char dst[CMDLINE_TEST_BUFSIZE];
if (cmdline_parse(NULL, "buffer") >= 0)
goto error;
if (cmdline_parse(&cl, NULL) >= 0)
goto error;
if (cmdline_complete(NULL, "buffer", &i, dst, sizeof(dst)) >= 0)
goto error;
if (cmdline_complete(&cl, NULL, &i, dst, sizeof(dst)) >= 0)
goto error;
if (cmdline_complete(&cl, "buffer", NULL, dst, sizeof(dst)) >= 0)
goto error;
if (cmdline_complete(&cl, "buffer", &i, NULL, sizeof(dst)) >= 0)
goto error;
return 0;
error:
printf("Error: function accepted null parameter!\n");
return -1;
}
static int
test_cmdline_rdline_fns(void)
{
struct rdline rdl;
rdline_write_char_t *wc = &cmdline_write_char;
rdline_validate_t *v = &valid_buffer;
rdline_complete_t *c = &complete_buffer;
if (rdline_init(NULL, wc, v, c) >= 0)
goto error;
if (rdline_init(&rdl, NULL, v, c) >= 0)
goto error;
if (rdline_init(&rdl, wc, NULL, c) >= 0)
goto error;
if (rdline_init(&rdl, wc, v, NULL) >= 0)
goto error;
if (rdline_char_in(NULL, 0) >= 0)
goto error;
if (rdline_get_buffer(NULL) != NULL)
goto error;
if (rdline_add_history(NULL, "history") >= 0)
goto error;
if (rdline_add_history(&rdl, NULL) >= 0)
goto error;
if (rdline_get_history_item(NULL, 0) != NULL)
goto error;
/* void functions */
rdline_newline(NULL, "prompt");
rdline_newline(&rdl, NULL);
rdline_stop(NULL);
rdline_quit(NULL);
rdline_restart(NULL);
rdline_redisplay(NULL);
rdline_reset(NULL);
rdline_clear_history(NULL);
return 0;
error:
printf("Error: function accepted null parameter!\n");
return -1;
}
static int
test_cmdline_vt100_fns(void)
{
if (vt100_parser(NULL, 0) >= 0) {
printf("Error: function accepted null parameter!\n");
return -1;
}
/* void functions */
vt100_init(NULL);
return 0;
}
static int
test_cmdline_socket_fns(void)
{
cmdline_parse_ctx_t ctx;
if (cmdline_stdin_new(NULL, "prompt") != NULL)
goto error;
if (cmdline_stdin_new(&ctx, NULL) != NULL)
goto error;
if (cmdline_file_new(NULL, "prompt", "/dev/null") != NULL)
goto error;
if (cmdline_file_new(&ctx, NULL, "/dev/null") != NULL)
goto error;
if (cmdline_file_new(&ctx, "prompt", NULL) != NULL)
goto error;
if (cmdline_file_new(&ctx, "prompt", "-/invalid/~/path") != NULL) {
printf("Error: succeeded in opening invalid file for reading!");
return -1;
}
if (cmdline_file_new(&ctx, "prompt", "/dev/null") == NULL) {
printf("Error: failed to open /dev/null for reading!");
return -1;
}
/* void functions */
cmdline_stdin_exit(NULL);
return 0;
error:
printf("Error: function accepted null parameter!\n");
return -1;
}
static int
test_cmdline_fns(void)
{
cmdline_parse_ctx_t ctx;
struct cmdline cl, *tmp;
memset(&ctx, 0, sizeof(ctx));
tmp = cmdline_new(&ctx, "test", -1, -1);
if (tmp == NULL)
goto error;
if (cmdline_new(NULL, "prompt", 0, 0) != NULL)
goto error;
if (cmdline_new(&ctx, NULL, 0, 0) != NULL)
goto error;
if (cmdline_in(NULL, "buffer", CMDLINE_TEST_BUFSIZE) >= 0)
goto error;
if (cmdline_in(&cl, NULL, CMDLINE_TEST_BUFSIZE) >= 0)
goto error;
if (cmdline_write_char(NULL, 0) >= 0)
goto error;
/* void functions */
cmdline_set_prompt(NULL, "prompt");
cmdline_free(NULL);
cmdline_printf(NULL, "format");
/* this should fail as stream handles are invalid */
cmdline_printf(tmp, "format");
cmdline_interact(NULL);
cmdline_quit(NULL);
/* check if void calls change anything when they should fail */
cl = *tmp;
cmdline_printf(&cl, NULL);
if (memcmp(&cl, tmp, sizeof(cl))) goto mismatch;
cmdline_set_prompt(&cl, NULL);
if (memcmp(&cl, tmp, sizeof(cl))) goto mismatch;
cmdline_in(&cl, NULL, CMDLINE_TEST_BUFSIZE);
if (memcmp(&cl, tmp, sizeof(cl))) goto mismatch;
cmdline_free(tmp);
return 0;
error:
printf("Error: function accepted null parameter!\n");
return -1;
mismatch:
printf("Error: data changed!\n");
return -1;
}
/* test library functions. the point of these tests is not so much to test
* functions' behaviour as it is to make sure there are no segfaults if
* they are called with invalid parameters.
*/
int
test_cmdline_lib(void)
{
if (test_cmdline_parse_fns() < 0)
return -1;
if (test_cmdline_rdline_fns() < 0)
return -1;
if (test_cmdline_vt100_fns() < 0)
return -1;
if (test_cmdline_socket_fns() < 0)
return -1;
if (test_cmdline_fns() < 0)
return -1;
return 0;
}

624
app/test/test_cmdline_num.c Normal file
View File

@ -0,0 +1,624 @@
/*-
* BSD LICENSE
*
* Copyright(c) 2010-2012 Intel Corporation. All rights reserved.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Intel Corporation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#include <string.h>
#include <inttypes.h>
#include <rte_string_fns.h>
#include <cmdline_parse.h>
#include <cmdline_parse_num.h>
#include "test_cmdline.h"
struct num_unsigned_str {
const char * str;
uint64_t result;
};
struct num_signed_str {
const char * str;
int64_t result;
};
const struct num_unsigned_str num_valid_positive_strs[] = {
/* decimal positive */
{"0", 0 },
{"127", INT8_MAX },
{"128", INT8_MAX + 1 },
{"255", UINT8_MAX },
{"256", UINT8_MAX + 1 },
{"32767", INT16_MAX },
{"32768", INT16_MAX + 1 },
{"65535", UINT16_MAX },
{"65536", UINT16_MAX + 1 },
{"2147483647", INT32_MAX },
{"2147483648", INT32_MAX + 1U },
{"4294967295", UINT32_MAX },
{"4294967296", UINT32_MAX + 1ULL },
{"9223372036854775807", INT64_MAX },
{"9223372036854775808", INT64_MAX + 1ULL},
{"18446744073709551615", UINT64_MAX },
/* hexadecimal (no leading zeroes) */
{"0x0", 0 },
{"0x7F", INT8_MAX },
{"0x80", INT8_MAX + 1 },
{"0xFF", UINT8_MAX },
{"0x100", UINT8_MAX + 1 },
{"0x7FFF", INT16_MAX },
{"0x8000", INT16_MAX + 1 },
{"0xFFFF", UINT16_MAX },
{"0x10000", UINT16_MAX + 1 },
{"0x7FFFFFFF", INT32_MAX },
{"0x80000000", INT32_MAX + 1U },
{"0xFFFFFFFF", UINT32_MAX },
{"0x100000000", UINT32_MAX + 1ULL },
{"0x7FFFFFFFFFFFFFFF", INT64_MAX },
{"0x8000000000000000", INT64_MAX + 1ULL},
{"0xFFFFFFFFFFFFFFFF", UINT64_MAX },
/* hexadecimal (with leading zeroes) */
{"0x00", 0 },
{"0x7F", INT8_MAX },
{"0x80", INT8_MAX + 1 },
{"0xFF", UINT8_MAX },
{"0x0100", UINT8_MAX + 1 },
{"0x7FFF", INT16_MAX },
{"0x8000", INT16_MAX + 1 },
{"0xFFFF", UINT16_MAX },
{"0x00010000", UINT16_MAX + 1 },
{"0x7FFFFFFF", INT32_MAX },
{"0x80000000", INT32_MAX + 1U },
{"0xFFFFFFFF", UINT32_MAX },
{"0x0000000100000000", UINT32_MAX + 1ULL },
{"0x7FFFFFFFFFFFFFFF", INT64_MAX },
{"0x8000000000000000", INT64_MAX + 1ULL},
{"0xFFFFFFFFFFFFFFFF", UINT64_MAX },
/* check all characters */
{"0x1234567890ABCDEF", 0x1234567890ABCDEFULL },
{"0x1234567890abcdef", 0x1234567890ABCDEFULL },
/* binary (no leading zeroes) */
{"0b0", 0 },
{"0b1111111", INT8_MAX },
{"0b10000000", INT8_MAX + 1 },
{"0b11111111", UINT8_MAX },
{"0b100000000", UINT8_MAX + 1 },
{"0b111111111111111", INT16_MAX },
{"0b1000000000000000", INT16_MAX + 1 },
{"0b1111111111111111", UINT16_MAX },
{"0b10000000000000000", UINT16_MAX + 1 },
{"0b1111111111111111111111111111111", INT32_MAX },
{"0b10000000000000000000000000000000", INT32_MAX + 1U },
{"0b11111111111111111111111111111111", UINT32_MAX },
{"0b100000000000000000000000000000000", UINT32_MAX + 1ULL },
{"0b111111111111111111111111111111111111111111111111111111111111111",
INT64_MAX },
{"0b1000000000000000000000000000000000000000000000000000000000000000",
INT64_MAX + 1ULL},
{"0b1111111111111111111111111111111111111111111111111111111111111111",
UINT64_MAX },
/* binary (with leading zeroes) */
{"0b01111111", INT8_MAX },
{"0b0000000100000000", UINT8_MAX + 1 },
{"0b0111111111111111", INT16_MAX },
{"0b00000000000000010000000000000000", UINT16_MAX + 1 },
{"0b01111111111111111111111111111111", INT32_MAX },
{"0b0000000000000000000000000000000100000000000000000000000000000000",
UINT32_MAX + 1ULL },
{"0b0111111111111111111111111111111111111111111111111111111111111111",
INT64_MAX },
/* octal */
{"00", 0 },
{"0177", INT8_MAX },
{"0200", INT8_MAX + 1 },
{"0377", UINT8_MAX },
{"0400", UINT8_MAX + 1 },
{"077777", INT16_MAX },
{"0100000", INT16_MAX + 1 },
{"0177777", UINT16_MAX },
{"0200000", UINT16_MAX + 1 },
{"017777777777", INT32_MAX },
{"020000000000", INT32_MAX + 1U },
{"037777777777", UINT32_MAX },
{"040000000000", UINT32_MAX + 1ULL },
{"0777777777777777777777", INT64_MAX },
{"01000000000000000000000", INT64_MAX + 1ULL},
{"01777777777777777777777", UINT64_MAX },
/* check all numbers */
{"012345670", 012345670 },
{"076543210", 076543210 },
};
const struct num_signed_str num_valid_negative_strs[] = {
/* deciman negative */
{"-128", INT8_MIN },
{"-129", INT8_MIN - 1 },
{"-32768", INT16_MIN },
{"-32769", INT16_MIN - 1 },
{"-2147483648", INT32_MIN },
{"-2147483649", INT32_MIN - 1LL },
{"-9223372036854775808", INT64_MIN },
};
const struct num_unsigned_str num_garbage_positive_strs[] = {
/* valid strings with garbage on the end, should still be valid */
/* decimal */
{"9223372036854775807\0garbage", INT64_MAX },
{"9223372036854775807\tgarbage", INT64_MAX },
{"9223372036854775807\rgarbage", INT64_MAX },
{"9223372036854775807\ngarbage", INT64_MAX },
{"9223372036854775807#garbage", INT64_MAX },
{"9223372036854775807 garbage", INT64_MAX },
/* hex */
{"0x7FFFFFFFFFFFFFFF\0garbage", INT64_MAX },
{"0x7FFFFFFFFFFFFFFF\tgarbage", INT64_MAX },
{"0x7FFFFFFFFFFFFFFF\rgarbage", INT64_MAX },
{"0x7FFFFFFFFFFFFFFF\ngarbage", INT64_MAX },
{"0x7FFFFFFFFFFFFFFF#garbage", INT64_MAX },
{"0x7FFFFFFFFFFFFFFF garbage", INT64_MAX },
/* binary */
{"0b1111111111111111111111111111111\0garbage", INT32_MAX },
{"0b1111111111111111111111111111111\rgarbage", INT32_MAX },
{"0b1111111111111111111111111111111\tgarbage", INT32_MAX },
{"0b1111111111111111111111111111111\ngarbage", INT32_MAX },
{"0b1111111111111111111111111111111#garbage", INT32_MAX },
{"0b1111111111111111111111111111111 garbage", INT32_MAX },
/* octal */
{"01777777777777777777777\0garbage", UINT64_MAX },
{"01777777777777777777777\rgarbage", UINT64_MAX },
{"01777777777777777777777\tgarbage", UINT64_MAX },
{"01777777777777777777777\ngarbage", UINT64_MAX },
{"01777777777777777777777#garbage", UINT64_MAX },
{"01777777777777777777777 garbage", UINT64_MAX },
};
const struct num_signed_str num_garbage_negative_strs[] = {
/* valid strings with garbage on the end, should still be valid */
{"-9223372036854775808\0garbage", INT64_MIN },
{"-9223372036854775808\rgarbage", INT64_MIN },
{"-9223372036854775808\tgarbage", INT64_MIN },
{"-9223372036854775808\ngarbage", INT64_MIN },
{"-9223372036854775808#garbage", INT64_MIN },
{"-9223372036854775808 garbage", INT64_MIN },
};
const char * num_invalid_strs[] = {
"18446744073709551616", /* out of range unsigned */
"-9223372036854775809", /* out of range negative signed */
"0x10000000000000000", /* out of range hex */
/* out of range binary */
"0b10000000000000000000000000000000000000000000000000000000000000000",
"020000000000000000000000", /* out of range octal */
/* wrong chars */
"0123456239",
"0x1234580AGE",
"0b0111010101g001",
"0b01110101017001",
/* false negative numbers */
"-12345F623",
"-0x1234580A",
"-0b0111010101",
/* too long (128+ chars) */
"0b1111000011110000111100001111000011110000111100001111000011110000"
"1111000011110000111100001111000011110000111100001111000011110000",
"1E3",
"0A",
"-B",
"+4",
"1.23G",
"",
" ",
"#",
"\r",
"\t",
"\n",
"\0",
};
#define NUM_POSITIVE_STRS_SIZE \
(sizeof(num_valid_positive_strs) / sizeof(num_valid_positive_strs[0]))
#define NUM_NEGATIVE_STRS_SIZE \
(sizeof(num_valid_negative_strs) / sizeof(num_valid_negative_strs[0]))
#define NUM_POSITIVE_GARBAGE_STRS_SIZE \
(sizeof(num_garbage_positive_strs) / sizeof(num_garbage_positive_strs[0]))
#define NUM_NEGATIVE_GARBAGE_STRS_SIZE \
(sizeof(num_garbage_negative_strs) / sizeof(num_garbage_negative_strs[0]))
#define NUM_INVALID_STRS_SIZE \
(sizeof(num_invalid_strs) / sizeof(num_invalid_strs[0]))
static int
can_parse_unsigned(uint64_t expected_result, enum cmdline_numtype type)
{
switch (type) {
case UINT8:
if (expected_result > UINT8_MAX)
return 0;
break;
case UINT16:
if (expected_result > UINT16_MAX)
return 0;
break;
case UINT32:
if (expected_result > UINT32_MAX)
return 0;
break;
case INT8:
if (expected_result > INT8_MAX)
return 0;
break;
case INT16:
if (expected_result > INT16_MAX)
return 0;
break;
case INT32:
if (expected_result > INT32_MAX)
return 0;
break;
case INT64:
if (expected_result > INT64_MAX)
return 0;
break;
default:
return 1;
}
return 1;
}
static int
can_parse_signed(int64_t expected_result, enum cmdline_numtype type)
{
switch (type) {
case UINT8:
if (expected_result > UINT8_MAX || expected_result < 0)
return 0;
break;
case UINT16:
if (expected_result > UINT16_MAX || expected_result < 0)
return 0;
break;
case UINT32:
if (expected_result > UINT32_MAX || expected_result < 0)
return 0;
break;
case UINT64:
if (expected_result < 0)
return 0;
case INT8:
if (expected_result > INT8_MAX || expected_result < INT8_MIN)
return 0;
break;
case INT16:
if (expected_result > INT16_MAX || expected_result < INT16_MIN)
return 0;
break;
case INT32:
if (expected_result > INT32_MAX || expected_result < INT32_MIN)
return 0;
break;
default:
return 1;
}
return 1;
}
/* test invalid parameters */
int
test_parse_num_invalid_param(void)
{
char buf[CMDLINE_TEST_BUFSIZE];
uint32_t result;
cmdline_parse_token_num_t token;
int ret = 0;
/* set up a token */
token.num_data.type = UINT32;
/* copy string to buffer */
rte_snprintf(buf, sizeof(buf), "%s",
num_valid_positive_strs[0].str);
/* try all null */
ret = cmdline_parse_num(NULL, NULL, NULL);
if (ret != -1) {
printf("Error: parser accepted null parameters!\n");
return -1;
}
/* try null token */
ret = cmdline_parse_num(NULL, buf, (void*)&result);
if (ret != -1) {
printf("Error: parser accepted null token!\n");
return -1;
}
/* try null buf */
ret = cmdline_parse_num((cmdline_parse_token_hdr_t*)&token, NULL,
(void*)&result);
if (ret != -1) {
printf("Error: parser accepted null string!\n");
return -1;
}
/* try null result */
ret = cmdline_parse_num((cmdline_parse_token_hdr_t*)&token, buf, NULL);
if (ret == -1) {
printf("Error: parser rejected null result!\n");
return -1;
}
/* test help function */
memset(&buf, 0, sizeof(buf));
/* try all null */
ret = cmdline_get_help_num(NULL, NULL, 0);
if (ret != -1) {
printf("Error: help function accepted null parameters!\n");
return -1;
}
/* try null token */
ret = cmdline_get_help_num(NULL, buf, sizeof(buf));
if (ret != -1) {
printf("Error: help function accepted null token!\n");
return -1;
}
/* try null buf */
ret = cmdline_get_help_num((cmdline_parse_token_hdr_t*)&token, NULL, sizeof(buf));
if (ret != -1) {
printf("Error: help function accepted null buffer!\n");
return -1;
}
/* coverage! */
ret = cmdline_get_help_num((cmdline_parse_token_hdr_t*)&token, buf, sizeof(buf));
if (ret < 0) {
printf("Error: help function failed with valid parameters!\n");
return -1;
}
return 0;
}
/* test valid parameters but invalid data */
int
test_parse_num_invalid_data(void)
{
enum cmdline_numtype type;
int ret = 0;
unsigned i;
char buf[CMDLINE_TEST_BUFSIZE];
uint64_t result; /* pick largest buffer */
cmdline_parse_token_num_t token;
/* cycle through all possible parsed types */
for (type = UINT8; type <= INT64; type++) {
token.num_data.type = type;
/* test full strings */
for (i = 0; i < NUM_INVALID_STRS_SIZE; i++) {
memset(&result, 0, sizeof(uint64_t));
memset(&buf, 0, sizeof(buf));
ret = cmdline_parse_num((cmdline_parse_token_hdr_t*)&token,
num_invalid_strs[i], (void*)&result);
if (ret != -1) {
/* get some info about what we are trying to parse */
cmdline_get_help_num((cmdline_parse_token_hdr_t*)&token,
buf, sizeof(buf));
printf("Error: parsing %s as %s succeeded!\n",
num_invalid_strs[i], buf);
return -1;
}
}
}
return 0;
}
/* test valid parameters and data */
int
test_parse_num_valid(void)
{
int ret = 0;
enum cmdline_numtype type;
unsigned i;
char buf[CMDLINE_TEST_BUFSIZE];
uint64_t result;
cmdline_parse_token_num_t token;
/** valid strings **/
/* cycle through all possible parsed types */
for (type = UINT8; type <= INT64; type++) {
token.num_data.type = type;
/* test positive strings */
for (i = 0; i < NUM_POSITIVE_STRS_SIZE; i++) {
result = 0;
memset(&buf, 0, sizeof(buf));
cmdline_get_help_num((cmdline_parse_token_hdr_t*)&token,
buf, sizeof(buf));
ret = cmdline_parse_num((cmdline_parse_token_hdr_t*) &token, num_valid_positive_strs[i].str,
(void*)&result);
/* if it should have passed but didn't, or if it should have failed but didn't */
if ((ret < 0) == (can_parse_unsigned(num_valid_positive_strs[i].result, type) > 0)) {
printf("Error: parser behaves unexpectedly when parsing %s as %s!\n",
num_valid_positive_strs[i].str, buf);
return -1;
}
/* check if result matches what it should have matched
* since unsigned numbers don't care about number of bits, we can just convert
* everything to uint64_t without any worries. */
if (ret > 0 && num_valid_positive_strs[i].result != result) {
printf("Error: parsing %s as %s failed: result mismatch!\n",
num_valid_positive_strs[i].str, buf);
return -1;
}
}
/* test negative strings */
for (i = 0; i < NUM_NEGATIVE_STRS_SIZE; i++) {
result = 0;
memset(&buf, 0, sizeof(buf));
cmdline_get_help_num((cmdline_parse_token_hdr_t*)&token,
buf, sizeof(buf));
ret = cmdline_parse_num((cmdline_parse_token_hdr_t*) &token, num_valid_negative_strs[i].str,
(void*)&result);
/* if it should have passed but didn't, or if it should have failed but didn't */
if ((ret < 0) == (can_parse_signed(num_valid_negative_strs[i].result, type) > 0)) {
printf("Error: parser behaves unexpectedly when parsing %s as %s!\n",
num_valid_negative_strs[i].str, buf);
return -1;
}
/* check if result matches what it should have matched
* the result is signed in this case, so we have to account for that */
if (ret > 0) {
/* detect negative */
switch (type) {
case INT8:
result = (int8_t) result;
break;
case INT16:
result = (int16_t) result;
break;
case INT32:
result = (int32_t) result;
break;
default:
break;
}
if (num_valid_negative_strs[i].result == (int64_t) result)
continue;
printf("Error: parsing %s as %s failed: result mismatch!\n",
num_valid_negative_strs[i].str, buf);
return -1;
}
}
}
/** garbage strings **/
/* cycle through all possible parsed types */
for (type = UINT8; type <= INT64; type++) {
token.num_data.type = type;
/* test positive garbage strings */
for (i = 0; i < NUM_POSITIVE_GARBAGE_STRS_SIZE; i++) {
result = 0;
memset(&buf, 0, sizeof(buf));
cmdline_get_help_num((cmdline_parse_token_hdr_t*)&token,
buf, sizeof(buf));
ret = cmdline_parse_num((cmdline_parse_token_hdr_t*) &token, num_garbage_positive_strs[i].str,
(void*)&result);
/* if it should have passed but didn't, or if it should have failed but didn't */
if ((ret < 0) == (can_parse_unsigned(num_garbage_positive_strs[i].result, type) > 0)) {
printf("Error: parser behaves unexpectedly when parsing %s as %s!\n",
num_garbage_positive_strs[i].str, buf);
return -1;
}
/* check if result matches what it should have matched
* since unsigned numbers don't care about number of bits, we can just convert
* everything to uint64_t without any worries. */
if (ret > 0 && num_garbage_positive_strs[i].result != result) {
printf("Error: parsing %s as %s failed: result mismatch!\n",
num_garbage_positive_strs[i].str, buf);
return -1;
}
}
/* test negative strings */
for (i = 0; i < NUM_NEGATIVE_GARBAGE_STRS_SIZE; i++) {
result = 0;
memset(&buf, 0, sizeof(buf));
cmdline_get_help_num((cmdline_parse_token_hdr_t*)&token,
buf, sizeof(buf));
ret = cmdline_parse_num((cmdline_parse_token_hdr_t*) &token, num_garbage_negative_strs[i].str,
(void*)&result);
/* if it should have passed but didn't, or if it should have failed but didn't */
if ((ret < 0) == (can_parse_signed(num_garbage_negative_strs[i].result, type) > 0)) {
printf("Error: parser behaves unexpectedly when parsing %s as %s!\n",
num_garbage_negative_strs[i].str, buf);
return -1;
}
/* check if result matches what it should have matched
* the result is signed in this case, so we have to account for that */
if (ret > 0) {
/* detect negative */
switch (type) {
case INT8:
if (result & (INT8_MAX + 1))
result |= 0xFFFFFFFFFFFFFF00ULL;
break;
case INT16:
if (result & (INT16_MAX + 1))
result |= 0xFFFFFFFFFFFF0000ULL;
break;
case INT32:
if (result & (INT32_MAX + 1ULL))
result |= 0xFFFFFFFF00000000ULL;
break;
default:
break;
}
if (num_garbage_negative_strs[i].result == (int64_t) result)
continue;
printf("Error: parsing %s as %s failed: result mismatch!\n",
num_garbage_negative_strs[i].str, buf);
return -1;
}
}
}
memset(&buf, 0, sizeof(buf));
/* coverage! */
cmdline_get_help_num((cmdline_parse_token_hdr_t*)&token,
buf, sizeof(buf));
return 0;
}

View File

@ -0,0 +1,257 @@
/*-
* BSD LICENSE
*
* Copyright(c) 2010-2012 Intel Corporation. All rights reserved.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Intel Corporation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#include <stdio.h>
#include <string.h>
#include <inttypes.h>
#include <cmdline_parse.h>
#include <cmdline_parse_portlist.h>
#include "test_cmdline.h"
struct portlist_str {
const char * str;
uint32_t portmap;
};
/* valid strings */
const struct portlist_str portlist_valid_strs[] = {
{"0", 0x1U },
{"0-10", 0x7FFU},
{"10-20", 0x1FFC00U},
{"all", UINT32_MAX},
{"0,1,2,3", 0xFU},
{"0,1-5", 0x3FU},
{"0,0,0", 0x1U},
{"31,0-10,15", 0x800087FFU},
{"0000", 0x1U},
{"00,01,02,03", 0xFU},
{"000,001,002,003", 0xFU},
};
/* valid strings but with garbage at the end.
* these strings should still be valid because parser checks
* for end of token, which is either a space/tab, a newline/return,
* or a hash sign.
*/
const char * portlist_garbage_strs[] = {
"0-31 garbage",
"0-31#garbage",
"0-31\0garbage",
"0-31\ngarbage",
"0-31\rgarbage",
"0-31\tgarbage",
"0,1,2,3-31 garbage",
"0,1,2,3-31#garbage",
"0,1,2,3-31\0garbage",
"0,1,2,3-31\ngarbage",
"0,1,2,3-31\rgarbage",
"0,1,2,3-31\tgarbage",
"all garbage",
"all#garbage",
"all\0garbage",
"all\ngarbage",
"all\rgarbage",
"all\tgarbage",
};
/* invalid strings */
const char * portlist_invalid_strs[] = {
/* valid syntax, invalid chars */
"A-B",
"0-S",
"1,2,3,4,Q",
"A-4,3-15",
"0-31invalid",
/* valid chars, invalid syntax */
"1, 2",
"1- 4",
",2",
",2 ",
"-1, 4",
"5-1",
"2-",
/* misc */
"-"
"a",
"A",
",",
"#",
" ",
"\0",
"",
/* too long */
"0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,"
"0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,2",
};
#define PORTLIST_VALID_STRS_SIZE \
(sizeof(portlist_valid_strs) / sizeof(portlist_valid_strs[0]))
#define PORTLIST_GARBAGE_STRS_SIZE \
(sizeof(portlist_garbage_strs) / sizeof(portlist_garbage_strs[0]))
#define PORTLIST_INVALID_STRS_SIZE \
(sizeof(portlist_invalid_strs) / sizeof(portlist_invalid_strs[0]))
/* test invalid parameters */
int
test_parse_portlist_invalid_param(void)
{
cmdline_portlist_t result;
char buf[CMDLINE_TEST_BUFSIZE];
int ret;
memset(&buf, 0, sizeof(buf));
memset(&result, 0, sizeof(cmdline_portlist_t));
/* try all null */
ret = cmdline_parse_portlist(NULL, NULL, NULL);
if (ret != -1) {
printf("Error: parser accepted null parameters!\n");
return -1;
}
/* try null buf */
ret = cmdline_parse_portlist(NULL, NULL, (void*)&result);
if (ret != -1) {
printf("Error: parser accepted null string!\n");
return -1;
}
/* try null result */
ret = cmdline_parse_portlist(NULL, portlist_valid_strs[0].str, NULL);
if (ret == -1) {
printf("Error: parser rejected null result!\n");
return -1;
}
/* token is not used in ether_parse anyway so there's no point in
* testing it */
/* test help function */
/* try null buf */
ret = cmdline_get_help_portlist(NULL, NULL, sizeof(buf));
if (ret != -1) {
printf("Error: help function accepted null buffer!\n");
return -1;
}
/* coverage! */
ret = cmdline_get_help_portlist(NULL, buf, sizeof(buf));
if (ret < 0) {
printf("Error: help function failed with valid parameters!\n");
return -1;
}
return 0;
}
/* test valid parameters but invalid data */
int
test_parse_portlist_invalid_data(void)
{
int ret = 0;
unsigned i;
cmdline_portlist_t result;
/* test invalid strings */
for (i = 0; i < PORTLIST_INVALID_STRS_SIZE; i++) {
memset(&result, 0, sizeof(cmdline_portlist_t));
ret = cmdline_parse_portlist(NULL, portlist_invalid_strs[i],
(void*)&result);
if (ret != -1) {
printf("Error: parsing %s succeeded!\n",
portlist_invalid_strs[i]);
return -1;
}
}
return 0;
}
/* test valid parameters and data */
int
test_parse_portlist_valid(void)
{
int ret = 0;
unsigned i;
cmdline_portlist_t result;
/* test full strings */
for (i = 0; i < PORTLIST_VALID_STRS_SIZE; i++) {
memset(&result, 0, sizeof(cmdline_portlist_t));
ret = cmdline_parse_portlist(NULL, portlist_valid_strs[i].str,
(void*)&result);
if (ret < 0) {
printf("Error: parsing %s failed!\n",
portlist_valid_strs[i].str);
return -1;
}
if (result.map != portlist_valid_strs[i].portmap) {
printf("Error: parsing %s failed: map mismatch!\n",
portlist_valid_strs[i].str);
return -1;
}
}
/* test garbage strings */
for (i = 0; i < PORTLIST_GARBAGE_STRS_SIZE; i++) {
memset(&result, 0, sizeof(cmdline_portlist_t));
ret = cmdline_parse_portlist(NULL, portlist_garbage_strs[i],
(void*)&result);
if (ret < 0) {
printf("Error: parsing %s failed!\n",
portlist_garbage_strs[i]);
return -1;
}
if (result.map != UINT32_MAX) {
printf("Error: parsing %s failed: map mismatch!\n",
portlist_garbage_strs[i]);
return -1;
}
}
return 0;
}

View File

@ -0,0 +1,402 @@
/*-
* BSD LICENSE
*
* Copyright(c) 2010-2012 Intel Corporation. All rights reserved.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Intel Corporation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#include <stdio.h>
#include <string.h>
#include <inttypes.h>
#include <rte_string_fns.h>
#include <cmdline_parse.h>
#include <cmdline_parse_string.h>
#include "test_cmdline.h"
/* structures needed to run tests */
struct string_elt_str {
const char * str; /* parsed string */
const char * result; /* expected string */
int idx; /* position at which result is expected to be */
};
struct string_elt_str string_elt_strs[] = {
{"one#two#three", "three", 2},
{"one#two with spaces#three", "three", 2},
{"one#two\twith\ttabs#three", "three", 2},
{"one#two\rwith\rreturns#three", "three", 2},
{"one#two\nwith\nnewlines#three", "three", 2},
{"one#two#three", "one", 0},
{"one#two#three", "two", 1},
{"one#two\0three", "two", 1},
{"one#two with spaces#three", "two with spaces", 1},
{"one#two\twith\ttabs#three", "two\twith\ttabs", 1},
{"one#two\rwith\rreturns#three", "two\rwith\rreturns", 1},
{"one#two\nwith\nnewlines#three", "two\nwith\nnewlines", 1},
};
struct string_nb_str {
const char * str; /* parsed string */
int nb_strs; /* expected number of strings in str */
};
struct string_nb_str string_nb_strs[] = {
{"one#two#three", 3},
{"one", 1},
{"one# \t two \r # three \n #four", 4},
};
struct string_parse_str {
const char * str; /* parsed string */
const char * fixed_str; /* parsing mode (any, fixed or multi) */
const char * result; /* expected result */
};
struct string_parse_str string_parse_strs[] = {
{"one", NULL, "one"}, /* any string */
{"two", "one#two#three", "two"}, /* multiple choice string */
{"three", "three", "three"}, /* fixed string */
{"three", "one#two with\rgarbage\tcharacters\n#three", "three"},
{"two with\rgarbage\tcharacters\n",
"one#two with\rgarbage\tcharacters\n#three",
"two with\rgarbage\tcharacters\n"},
};
struct string_invalid_str {
const char * str; /* parsed string */
const char * fixed_str; /* parsing mode (any, fixed or multi) */
};
struct string_invalid_str string_invalid_strs[] = {
{"invalid", "one"}, /* fixed string */
{"invalid", "one#two#three"}, /* multiple choice string */
{"invalid", "invalidone"}, /* string that starts the same */
{"invalidone", "invalid"}, /* string that starts the same */
{"toolong!!!toolong!!!toolong!!!toolong!!!toolong!!!toolong!!!"
"toolong!!!toolong!!!toolong!!!toolong!!!toolong!!!toolong!!!"
"toolong!!!", NULL },
{"toolong!!!toolong!!!toolong!!!toolong!!!toolong!!!toolong!!!"
"toolong!!!toolong!!!toolong!!!toolong!!!toolong!!!toolong!!!"
"toolong!!!", "fixed" },
{"toolong!!!toolong!!!toolong!!!toolong!!!toolong!!!toolong!!!"
"toolong!!!toolong!!!toolong!!!toolong!!!toolong!!!toolong!!!"
"toolong!!!", "multi#choice#string" },
{"invalid",
"toolong!!!toolong!!!toolong!!!toolong!!!toolong!!!toolong!!!"
"toolong!!!toolong!!!toolong!!!toolong!!!toolong!!!toolong!!!"
"toolong!!!" },
{"invalid", ""},
{"", "invalid"}
};
const char * string_help_strs[] = {
NULL,
"fixed_str",
"multi#str",
};
#define STRING_PARSE_STRS_SIZE \
(sizeof(string_parse_strs) / sizeof(string_parse_strs[0]))
#define STRING_HELP_STRS_SIZE \
(sizeof(string_help_strs) / sizeof(string_help_strs[0]))
#define STRING_ELT_STRS_SIZE \
(sizeof(string_elt_strs) / sizeof(string_elt_strs[0]))
#define STRING_NB_STRS_SIZE \
(sizeof(string_nb_strs) / sizeof(string_nb_strs[0]))
#define STRING_INVALID_STRS_SIZE \
(sizeof(string_invalid_strs) / sizeof(string_invalid_strs[0]))
#define SMALL_BUF 8
/* test invalid parameters */
int
test_parse_string_invalid_param(void)
{
cmdline_parse_token_string_t token;
int result;
char buf[CMDLINE_TEST_BUFSIZE];
memset(&token, 0, sizeof(token));
rte_snprintf(buf, sizeof(buf), "buffer");
/* test null token */
if (cmdline_get_help_string(
NULL, buf, 0) != -1) {
printf("Error: function accepted null token!\n");
return -1;
}
if (cmdline_complete_get_elt_string(
NULL, 0, buf, 0) != -1) {
printf("Error: function accepted null token!\n");
return -1;
}
if (cmdline_complete_get_nb_string(NULL) != -1) {
printf("Error: function accepted null token!\n");
return -1;
}
if (cmdline_parse_string(NULL, buf, NULL) != -1) {
printf("Error: function accepted null token!\n");
return -1;
}
/* test null buffer */
if (cmdline_complete_get_elt_string(
(cmdline_parse_token_hdr_t*)&token, 0, NULL, 0) != -1) {
printf("Error: function accepted null buffer!\n");
return -1;
}
if (cmdline_parse_string(
(cmdline_parse_token_hdr_t*)&token, NULL, (void*)&result) != -1) {
printf("Error: function accepted null buffer!\n");
return -1;
}
if (cmdline_get_help_string(
(cmdline_parse_token_hdr_t*)&token, NULL, 0) != -1) {
printf("Error: function accepted null buffer!\n");
return -1;
}
/* test null result */
if (cmdline_parse_string(
(cmdline_parse_token_hdr_t*)&token, buf, NULL) == -1) {
printf("Error: function rejected null result!\n");
return -1;
}
/* test negative index */
if (cmdline_complete_get_elt_string(
(cmdline_parse_token_hdr_t*)&token, -1, buf, 0) != -1) {
printf("Error: function accepted negative index!\n");
return -1;
}
return 0;
}
/* test valid parameters but invalid data */
int
test_parse_string_invalid_data(void)
{
cmdline_parse_token_string_t token;
cmdline_parse_token_string_t help_token;
char buf[CMDLINE_TEST_BUFSIZE];
char help_str[CMDLINE_TEST_BUFSIZE];
char small_buf[SMALL_BUF];
unsigned i;
/* test parsing invalid strings */
for (i = 0; i < STRING_INVALID_STRS_SIZE; i++) {
memset(&token, 0, sizeof(token));
memset(buf, 0, sizeof(buf));
/* prepare test token data */
token.string_data.str = string_invalid_strs[i].fixed_str;
if (cmdline_parse_string((cmdline_parse_token_hdr_t*)&token,
string_invalid_strs[i].str, (void*)buf) != -1) {
memset(help_str, 0, sizeof(help_str));
memset(&help_token, 0, sizeof(help_token));
help_token.string_data.str = string_invalid_strs[i].fixed_str;
/* get parse type so we can give a good error message */
cmdline_get_help_string((cmdline_parse_token_hdr_t*)&token, help_str,
sizeof(help_str));
printf("Error: parsing %s as %s succeeded!\n",
string_invalid_strs[i].str, help_str);
return -1;
}
}
/* misc tests (big comments signify test cases) */
memset(&token, 0, sizeof(token));
memset(small_buf, 0, sizeof(small_buf));
/*
* try to get element from a null token
*/
token.string_data.str = NULL;
if (cmdline_complete_get_elt_string(
(cmdline_parse_token_hdr_t*)&token, 1,
buf, sizeof(buf)) != -1) {
printf("Error: getting token from null token string!\n");
return -1;
}
/*
* try to get element into a buffer that is too small
*/
token.string_data.str = "too_small_buffer";
if (cmdline_complete_get_elt_string(
(cmdline_parse_token_hdr_t*)&token, 0,
small_buf, sizeof(small_buf)) != -1) {
printf("Error: writing token into too small a buffer succeeded!\n");
return -1;
}
/*
* get help string written into a buffer smaller than help string
* truncation should occur
*/
token.string_data.str = NULL;
if (cmdline_get_help_string(
(cmdline_parse_token_hdr_t*)&token,
small_buf, sizeof(small_buf)) == -1) {
printf("Error: writing help string into too small a buffer failed!\n");
return -1;
}
/* get help string for "any string" so we can compare it with small_buf */
cmdline_get_help_string((cmdline_parse_token_hdr_t*)&token, help_str,
sizeof(help_str));
if (strncmp(small_buf, help_str, sizeof(small_buf) - 1)) {
printf("Error: help string mismatch!\n");
return -1;
}
/* check null terminator */
if (small_buf[sizeof(small_buf) - 1] != '\0') {
printf("Error: small buffer doesn't have a null terminator!\n");
return -1;
}
/*
* try to count tokens in a null token
*/
token.string_data.str = NULL;
if (cmdline_complete_get_nb_string(
(cmdline_parse_token_hdr_t*)&token) != 0) {
printf("Error: getting token count from null token succeeded!\n");
return -1;
}
return 0;
}
/* test valid parameters and data */
int
test_parse_string_valid(void)
{
cmdline_parse_token_string_t token;
cmdline_parse_token_string_t help_token;
char buf[CMDLINE_TEST_BUFSIZE];
char help_str[CMDLINE_TEST_BUFSIZE];
unsigned i;
/* test parsing strings */
for (i = 0; i < STRING_PARSE_STRS_SIZE; i++) {
memset(&token, 0, sizeof(token));
memset(buf, 0, sizeof(buf));
token.string_data.str = string_parse_strs[i].fixed_str;
if (cmdline_parse_string((cmdline_parse_token_hdr_t*)&token,
string_parse_strs[i].str, (void*)buf) < 0) {
/* clean help data */
memset(&help_token, 0, sizeof(help_token));
memset(help_str, 0, sizeof(help_str));
/* prepare help token */
help_token.string_data.str = string_parse_strs[i].fixed_str;
/* get help string so that we get an informative error message */
cmdline_get_help_string((cmdline_parse_token_hdr_t*)&token, help_str,
sizeof(help_str));
printf("Error: parsing %s as %s failed!\n",
string_parse_strs[i].str, help_str);
return -1;
}
if (strncmp(buf, string_parse_strs[i].result,
sizeof(string_parse_strs[i].result) - 1) != 0) {
printf("Error: result mismatch!\n");
return -1;
}
}
/* get number of string tokens and verify it's correct */
for (i = 0; i < STRING_NB_STRS_SIZE; i++) {
memset(&token, 0, sizeof(token));
token.string_data.str = string_nb_strs[i].str;
if (cmdline_complete_get_nb_string(
(cmdline_parse_token_hdr_t*)&token) <
string_nb_strs[i].nb_strs) {
printf("Error: strings count mismatch!\n");
return -1;
}
}
/* get token at specified position and verify it's correct */
for (i = 0; i < STRING_ELT_STRS_SIZE; i++) {
memset(&token, 0, sizeof(token));
memset(buf, 0, sizeof(buf));
token.string_data.str = string_elt_strs[i].str;
if (cmdline_complete_get_elt_string(
(cmdline_parse_token_hdr_t*)&token, string_elt_strs[i].idx,
buf, sizeof(buf)) < 0) {
printf("Error: getting string element failed!\n");
return -1;
}
if (strncmp(buf, string_elt_strs[i].result,
sizeof(string_elt_strs[i].result)) != 0) {
printf("Error: result mismatch!\n");
return -1;
}
}
/* cover all cases with help strings */
for (i = 0; i < STRING_HELP_STRS_SIZE; i++) {
memset(&help_token, 0, sizeof(help_token));
memset(help_str, 0, sizeof(help_str));
help_token.string_data.str = string_help_strs[i];
if (cmdline_get_help_string((cmdline_parse_token_hdr_t*)&help_token,
help_str, sizeof(help_str)) < 0) {
printf("Error: help operation failed!\n");
return -1;
}
}
return 0;
}