cmdline: tests
Signed-off-by: Intel
This commit is contained in:
parent
ab971e5628
commit
dbb860e03e
@ -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
49
app/cmdline_test/Makefile
Normal 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
|
65
app/cmdline_test/cmdline_test.c
Normal file
65
app/cmdline_test/cmdline_test.c
Normal 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;
|
||||
}
|
47
app/cmdline_test/cmdline_test.h
Normal file
47
app/cmdline_test/cmdline_test.h
Normal 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
115
app/cmdline_test/cmdline_test.py
Executable 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)
|
||||
|
313
app/cmdline_test/cmdline_test_data.py
Normal file
313
app/cmdline_test/cmdline_test_data.py
Normal 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
390
app/cmdline_test/commands.c
Normal 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,
|
||||
};
|
@ -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)
|
||||
|
@ -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 = {
|
||||
|
@ -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
94
app/test/test_cmdline.c
Normal 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
74
app/test/test_cmdline.h
Normal 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_ */
|
1331
app/test/test_cmdline_cirbuf.c
Normal file
1331
app/test/test_cmdline_cirbuf.c
Normal file
File diff suppressed because it is too large
Load Diff
254
app/test/test_cmdline_etheraddr.c
Normal file
254
app/test/test_cmdline_etheraddr.c
Normal 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;
|
||||
}
|
707
app/test/test_cmdline_ipaddr.c
Normal file
707
app/test/test_cmdline_ipaddr.c
Normal 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
264
app/test/test_cmdline_lib.c
Normal 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
624
app/test/test_cmdline_num.c
Normal 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;
|
||||
}
|
257
app/test/test_cmdline_portlist.c
Normal file
257
app/test/test_cmdline_portlist.c
Normal 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;
|
||||
}
|
402
app/test/test_cmdline_string.c
Normal file
402
app/test/test_cmdline_string.c
Normal 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;
|
||||
}
|
Loading…
Reference in New Issue
Block a user