2010-11-14 21:58:33 +03:00
/***
This file is part of systemd .
Copyright 2010 Lennart Poettering
2013-02-07 00:15:23 +04:00
Copyright 2013 Thomas H . P . Andersen
2010-11-14 21:58:33 +03:00
systemd is free software ; you can redistribute it and / or modify it
2012-04-12 02:20:58 +04:00
under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation ; either version 2.1 of the License , or
2010-11-14 21:58:33 +03:00
( at your option ) any later version .
systemd is distributed in the hope that it will be useful , but
WITHOUT ANY WARRANTY ; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the GNU
2012-04-12 02:20:58 +04:00
Lesser General Public License for more details .
2010-11-14 21:58:33 +03:00
2012-04-12 02:20:58 +04:00
You should have received a copy of the GNU Lesser General Public License
2010-11-14 21:58:33 +03:00
along with systemd ; If not , see < http : //www.gnu.org/licenses/>.
* * */
# include <string.h>
2011-01-07 01:51:52 +03:00
2015-10-27 05:01:06 +03:00
# include "alloc-util.h"
2011-01-07 01:51:52 +03:00
# include "specifier.h"
2015-10-24 23:58:24 +03:00
# include "string-util.h"
2013-01-31 00:45:40 +04:00
# include "strv.h"
2015-10-24 23:58:24 +03:00
# include "util.h"
2010-11-14 21:58:33 +03:00
2013-01-31 00:36:56 +04:00
static void test_specifier_printf ( void ) {
2013-09-17 20:02:02 +04:00
static const Specifier table [ ] = {
2011-01-07 01:51:52 +03:00
{ ' a ' , specifier_string , ( char * ) " AAAA " } ,
{ ' b ' , specifier_string , ( char * ) " BBBB " } ,
2013-09-17 19:03:46 +04:00
{ ' m ' , specifier_machine_id , NULL } ,
{ ' B ' , specifier_boot_id , NULL } ,
{ ' H ' , specifier_host_name , NULL } ,
{ ' v ' , specifier_kernel_release , NULL } ,
2013-09-17 20:02:02 +04:00
{ }
2011-01-07 01:51:52 +03:00
} ;
2013-09-17 20:02:02 +04:00
_cleanup_free_ char * w = NULL ;
int r ;
2013-09-17 19:03:46 +04:00
r = specifier_printf ( " xxx a=%a b=%b yyy " , table , NULL , & w ) ;
assert_se ( r > = 0 ) ;
assert_se ( w ) ;
2013-02-17 23:15:52 +04:00
puts ( w ) ;
2013-09-17 19:03:46 +04:00
assert_se ( streq ( w , " xxx a=AAAA b=BBBB yyy " ) ) ;
2013-02-17 23:15:52 +04:00
2013-09-17 19:03:46 +04:00
free ( w ) ;
r = specifier_printf ( " machine=%m, boot=%B, host=%H, version=%v " , table , NULL , & w ) ;
assert_se ( r > = 0 ) ;
2013-02-17 23:15:52 +04:00
assert_se ( w ) ;
2013-09-17 19:03:46 +04:00
puts ( w ) ;
2013-01-31 00:36:56 +04:00
}
2016-09-25 03:13:28 +03:00
static void test_str_in_set ( void ) {
assert_se ( STR_IN_SET ( " x " , " x " , " y " , " z " ) ) ;
assert_se ( ! STR_IN_SET ( " X " , " x " , " y " , " z " ) ) ;
assert_se ( ! STR_IN_SET ( " " , " x " , " y " , " z " ) ) ;
assert_se ( STR_IN_SET ( " x " , " w " , " x " ) ) ;
}
static void test_strptr_in_set ( void ) {
assert_se ( STRPTR_IN_SET ( " x " , " x " , " y " , " z " ) ) ;
assert_se ( ! STRPTR_IN_SET ( " X " , " x " , " y " , " z " ) ) ;
assert_se ( ! STRPTR_IN_SET ( " " , " x " , " y " , " z " ) ) ;
assert_se ( STRPTR_IN_SET ( " x " , " w " , " x " ) ) ;
assert_se ( ! STRPTR_IN_SET ( NULL , " x " , " y " , " z " ) ) ;
assert_se ( ! STRPTR_IN_SET ( NULL , " " ) ) ;
/* strv cannot contain a null, hence the result below */
assert_se ( ! STRPTR_IN_SET ( NULL , NULL ) ) ;
}
2013-08-31 22:28:09 +04:00
static const char * const input_table_multiple [ ] = {
" one " ,
" two " ,
" three " ,
NULL ,
} ;
static const char * const input_table_one [ ] = {
" one " ,
NULL ,
} ;
static const char * const input_table_none [ ] = {
NULL ,
} ;
basic/strv: fix strv_join for first empty argument
Empty strings were ignored in strv_join, but only if they were at the beginning
of the string. Empty strings after at least one non-empty item were treated
normally.
Previously:
{"x"} → "x"
{"x", ""} → "x"
{"x", "", ""} → "x::"
{""} → ""
{"", ""} → ""
{"", "", ""} → ""
{"", "x"} → "x"
{"", "x", ""} → "x:"
Now:
{"x"} → "x"
{"x", ""} → "x"
{"x", "", ""} → "x::"
{""} → ""
{"", ""} → ":"
{"", "", ""} → "::"
{"", "x"} → ":x"
{"", "x", ""} → ":x:"
2016-02-12 07:24:14 +03:00
static const char * const input_table_two_empties [ ] = {
" " ,
" " ,
NULL ,
} ;
static const char * const input_table_one_empty [ ] = {
" " ,
NULL ,
} ;
2013-08-31 22:28:09 +04:00
static const char * const input_table_quotes [ ] = {
" \" " ,
" ' " ,
" \" \" " ,
" \\ " ,
" \\ \\ " ,
NULL ,
} ;
# define QUOTES_STRING \
" \" \\ \" \" " \
" \" \\ \' \" " \
" \" \\ \" \\ \" \" " \
" \" \\ \\ \" " \
" \" \\ \\ \\ \\ \" "
static const char * const input_table_spaces [ ] = {
" " ,
" ' ' " ,
" \" " ,
" \" " ,
" \\ \\ " ,
NULL ,
} ;
# define SPACES_STRING \
" \" \" " \
" \" \\ ' \\ ' \" " \
" \" \\ \" \" " \
" \" \\ \" \" " \
" \" \\ \\ \\ \\ \" "
2013-02-07 00:15:23 +04:00
2013-08-31 22:28:09 +04:00
static void test_strv_find ( void ) {
assert_se ( strv_find ( ( char * * ) input_table_multiple , " three " ) ) ;
assert_se ( ! strv_find ( ( char * * ) input_table_multiple , " four " ) ) ;
2013-02-07 00:15:23 +04:00
}
static void test_strv_find_prefix ( void ) {
2013-08-31 22:28:09 +04:00
assert_se ( strv_find_prefix ( ( char * * ) input_table_multiple , " o " ) ) ;
assert_se ( strv_find_prefix ( ( char * * ) input_table_multiple , " one " ) ) ;
assert_se ( strv_find_prefix ( ( char * * ) input_table_multiple , " " ) ) ;
assert_se ( ! strv_find_prefix ( ( char * * ) input_table_multiple , " xxx " ) ) ;
assert_se ( ! strv_find_prefix ( ( char * * ) input_table_multiple , " onee " ) ) ;
2013-01-31 00:36:56 +04:00
}
2010-11-14 21:58:33 +03:00
2014-10-12 19:32:23 +04:00
static void test_strv_find_startswith ( void ) {
char * r ;
r = strv_find_startswith ( ( char * * ) input_table_multiple , " o " ) ;
assert_se ( r & & streq ( r , " ne " ) ) ;
r = strv_find_startswith ( ( char * * ) input_table_multiple , " one " ) ;
assert_se ( r & & streq ( r , " " ) ) ;
r = strv_find_startswith ( ( char * * ) input_table_multiple , " " ) ;
assert_se ( r & & streq ( r , " one " ) ) ;
assert_se ( ! strv_find_startswith ( ( char * * ) input_table_multiple , " xxx " ) ) ;
assert_se ( ! strv_find_startswith ( ( char * * ) input_table_multiple , " onee " ) ) ;
}
2013-01-31 00:45:40 +04:00
static void test_strv_join ( void ) {
basic/strv: fix strv_join for first empty argument
Empty strings were ignored in strv_join, but only if they were at the beginning
of the string. Empty strings after at least one non-empty item were treated
normally.
Previously:
{"x"} → "x"
{"x", ""} → "x"
{"x", "", ""} → "x::"
{""} → ""
{"", ""} → ""
{"", "", ""} → ""
{"", "x"} → "x"
{"", "x", ""} → "x:"
Now:
{"x"} → "x"
{"x", ""} → "x"
{"x", "", ""} → "x::"
{""} → ""
{"", ""} → ":"
{"", "", ""} → "::"
{"", "x"} → ":x"
{"", "x", ""} → ":x:"
2016-02-12 07:24:14 +03:00
_cleanup_free_ char * p = NULL , * q = NULL , * r = NULL , * s = NULL , * t = NULL , * v = NULL , * w = NULL ;
2013-01-31 00:45:40 +04:00
2013-02-07 00:15:23 +04:00
p = strv_join ( ( char * * ) input_table_multiple , " , " ) ;
2013-02-18 19:48:12 +04:00
assert_se ( p ) ;
2013-02-13 19:13:39 +04:00
assert_se ( streq ( p , " one, two, three " ) ) ;
2013-01-31 00:45:40 +04:00
2013-02-07 00:15:23 +04:00
q = strv_join ( ( char * * ) input_table_multiple , " ; " ) ;
2013-02-18 19:48:12 +04:00
assert_se ( q ) ;
2013-02-13 19:13:39 +04:00
assert_se ( streq ( q , " one;two;three " ) ) ;
2013-01-31 00:45:40 +04:00
r = strv_join ( ( char * * ) input_table_multiple , NULL ) ;
2013-02-18 19:48:12 +04:00
assert_se ( r ) ;
2013-02-13 19:13:39 +04:00
assert_se ( streq ( r , " one two three " ) ) ;
2013-02-07 00:15:23 +04:00
s = strv_join ( ( char * * ) input_table_one , " , " ) ;
2013-02-18 19:48:12 +04:00
assert_se ( s ) ;
2013-02-13 19:13:39 +04:00
assert_se ( streq ( s , " one " ) ) ;
2013-02-07 00:15:23 +04:00
t = strv_join ( ( char * * ) input_table_none , " , " ) ;
2013-02-18 19:48:12 +04:00
assert_se ( t ) ;
2013-02-13 19:13:39 +04:00
assert_se ( streq ( t , " " ) ) ;
basic/strv: fix strv_join for first empty argument
Empty strings were ignored in strv_join, but only if they were at the beginning
of the string. Empty strings after at least one non-empty item were treated
normally.
Previously:
{"x"} → "x"
{"x", ""} → "x"
{"x", "", ""} → "x::"
{""} → ""
{"", ""} → ""
{"", "", ""} → ""
{"", "x"} → "x"
{"", "x", ""} → "x:"
Now:
{"x"} → "x"
{"x", ""} → "x"
{"x", "", ""} → "x::"
{""} → ""
{"", ""} → ":"
{"", "", ""} → "::"
{"", "x"} → ":x"
{"", "x", ""} → ":x:"
2016-02-12 07:24:14 +03:00
v = strv_join ( ( char * * ) input_table_two_empties , " , " ) ;
assert_se ( v ) ;
assert_se ( streq ( v , " , " ) ) ;
w = strv_join ( ( char * * ) input_table_one_empty , " , " ) ;
assert_se ( w ) ;
assert_se ( streq ( w , " " ) ) ;
2013-01-31 00:45:40 +04:00
}
2013-08-31 22:28:09 +04:00
static void test_strv_quote_unquote ( const char * const * split , const char * quoted ) {
_cleanup_free_ char * p ;
2015-10-04 18:36:19 +03:00
_cleanup_strv_free_ char * * s = NULL ;
2013-08-31 22:28:09 +04:00
char * * t ;
2014-07-31 11:28:37 +04:00
int r ;
2013-08-31 22:28:09 +04:00
p = strv_join_quoted ( ( char * * ) split ) ;
2013-11-28 01:37:52 +04:00
assert_se ( p ) ;
2013-08-31 22:28:09 +04:00
printf ( " -%s- --- -%s- \n " , p , quoted ) ; /* fprintf deals with NULL, puts does not */
assert_se ( p ) ;
assert_se ( streq ( p , quoted ) ) ;
2015-06-19 18:24:34 +03:00
r = strv_split_extract ( & s , quoted , WHITESPACE , EXTRACT_QUOTES ) ;
2015-10-04 18:36:19 +03:00
assert_se ( r = = ( int ) strv_length ( s ) ) ;
2013-08-31 22:28:09 +04:00
assert_se ( s ) ;
STRV_FOREACH ( t , s ) {
assert_se ( * t ) ;
assert_se ( streq ( * t , * split ) ) ;
split + + ;
}
}
2014-12-19 01:01:42 +03:00
static void test_strv_unquote ( const char * quoted , char * * list ) {
2013-11-28 01:37:52 +04:00
_cleanup_strv_free_ char * * s ;
2014-07-30 06:01:36 +04:00
_cleanup_free_ char * j ;
2013-11-28 01:37:52 +04:00
unsigned i = 0 ;
char * * t ;
2014-07-31 11:28:37 +04:00
int r ;
2013-11-28 01:37:52 +04:00
2015-06-19 18:24:34 +03:00
r = strv_split_extract ( & s , quoted , WHITESPACE , EXTRACT_QUOTES ) ;
2015-10-04 18:36:19 +03:00
assert_se ( r = = ( int ) strv_length ( list ) ) ;
2013-11-28 01:37:52 +04:00
assert_se ( s ) ;
2014-07-30 06:01:36 +04:00
j = strv_join ( s , " | " ) ;
2014-10-05 01:51:45 +04:00
assert_se ( j ) ;
2014-07-30 06:01:36 +04:00
puts ( j ) ;
2013-11-28 01:37:52 +04:00
STRV_FOREACH ( t , s )
assert_se ( streq ( list [ i + + ] , * t ) ) ;
assert_se ( list [ i ] = = NULL ) ;
}
2014-07-30 06:01:36 +04:00
static void test_invalid_unquote ( const char * quoted ) {
2014-07-31 11:28:37 +04:00
char * * s = NULL ;
int r ;
2014-07-30 06:01:36 +04:00
2015-06-19 18:24:34 +03:00
r = strv_split_extract ( & s , quoted , WHITESPACE , EXTRACT_QUOTES ) ;
2014-10-05 01:51:45 +04:00
assert_se ( s = = NULL ) ;
assert_se ( r = = - EINVAL ) ;
2014-07-30 06:01:36 +04:00
}
2013-10-31 13:03:08 +04:00
static void test_strv_split ( void ) {
char * * s ;
unsigned i = 0 ;
_cleanup_strv_free_ char * * l = NULL ;
const char str [ ] = " one,two,three " ;
l = strv_split ( str , " , " ) ;
2014-10-05 01:51:45 +04:00
assert_se ( l ) ;
2013-10-31 13:03:08 +04:00
STRV_FOREACH ( s , l ) {
assert_se ( streq ( * s , input_table_multiple [ i + + ] ) ) ;
}
}
2015-06-19 18:24:34 +03:00
static void test_strv_split_extract ( void ) {
_cleanup_strv_free_ char * * l = NULL ;
const char * str = " :foo \\ :bar::waldo: " ;
int r ;
r = strv_split_extract ( & l , str , " : " , EXTRACT_DONT_COALESCE_SEPARATORS ) ;
2015-10-04 18:36:19 +03:00
assert_se ( r = = ( int ) strv_length ( l ) ) ;
2015-06-19 18:24:34 +03:00
assert_se ( streq_ptr ( l [ 0 ] , " " ) ) ;
assert_se ( streq_ptr ( l [ 1 ] , " foo:bar " ) ) ;
assert_se ( streq_ptr ( l [ 2 ] , " " ) ) ;
assert_se ( streq_ptr ( l [ 3 ] , " waldo " ) ) ;
assert_se ( streq_ptr ( l [ 4 ] , " " ) ) ;
assert_se ( streq_ptr ( l [ 5 ] , NULL ) ) ;
}
2013-10-31 13:03:08 +04:00
static void test_strv_split_newlines ( void ) {
unsigned i = 0 ;
char * * s ;
_cleanup_strv_free_ char * * l = NULL ;
const char str [ ] = " one \n two \n three " ;
l = strv_split_newlines ( str ) ;
2014-10-05 01:51:45 +04:00
assert_se ( l ) ;
2013-10-31 13:03:08 +04:00
STRV_FOREACH ( s , l ) {
assert_se ( streq ( * s , input_table_multiple [ i + + ] ) ) ;
}
}
2013-02-19 02:53:33 +04:00
static void test_strv_split_nulstr ( void ) {
_cleanup_strv_free_ char * * l = NULL ;
const char nulstr [ ] = " str0 \0 str1 \0 str2 \0 str3 \0 " ;
l = strv_split_nulstr ( nulstr ) ;
2013-02-18 19:48:12 +04:00
assert_se ( l ) ;
2013-02-19 02:53:33 +04:00
assert_se ( streq ( l [ 0 ] , " str0 " ) ) ;
assert_se ( streq ( l [ 1 ] , " str1 " ) ) ;
assert_se ( streq ( l [ 2 ] , " str2 " ) ) ;
assert_se ( streq ( l [ 3 ] , " str3 " ) ) ;
}
2013-02-07 03:33:58 +04:00
static void test_strv_parse_nulstr ( void ) {
_cleanup_strv_free_ char * * l = NULL ;
const char nulstr [ ] = " fuck \0 fuck2 \0 fuck3 \0 \0 fuck5 \0 \0 xxx " ;
l = strv_parse_nulstr ( nulstr , sizeof ( nulstr ) - 1 ) ;
2013-02-18 19:48:12 +04:00
assert_se ( l ) ;
2013-02-07 03:33:58 +04:00
puts ( " Parse nulstr: " ) ;
strv_print ( l ) ;
2013-02-13 19:13:39 +04:00
assert_se ( streq ( l [ 0 ] , " fuck " ) ) ;
assert_se ( streq ( l [ 1 ] , " fuck2 " ) ) ;
assert_se ( streq ( l [ 2 ] , " fuck3 " ) ) ;
assert_se ( streq ( l [ 3 ] , " " ) ) ;
assert_se ( streq ( l [ 4 ] , " fuck5 " ) ) ;
assert_se ( streq ( l [ 5 ] , " " ) ) ;
assert_se ( streq ( l [ 6 ] , " xxx " ) ) ;
2013-02-07 03:33:58 +04:00
}
2013-02-07 00:15:23 +04:00
static void test_strv_overlap ( void ) {
const char * const input_table [ ] = {
" one " ,
" two " ,
" three " ,
NULL
} ;
const char * const input_table_overlap [ ] = {
" two " ,
NULL
} ;
const char * const input_table_unique [ ] = {
" four " ,
" five " ,
" six " ,
NULL
} ;
2013-02-13 19:13:39 +04:00
assert_se ( strv_overlap ( ( char * * ) input_table , ( char * * ) input_table_overlap ) ) ;
assert_se ( ! strv_overlap ( ( char * * ) input_table , ( char * * ) input_table_unique ) ) ;
2013-02-07 00:15:23 +04:00
}
static void test_strv_sort ( void ) {
2013-04-05 08:31:59 +04:00
const char * input_table [ ] = {
2013-02-07 00:15:23 +04:00
" durian " ,
" apple " ,
" citrus " ,
" CAPITAL LETTERS FIRST " ,
" banana " ,
NULL
} ;
strv_sort ( ( char * * ) input_table ) ;
2013-02-13 19:13:39 +04:00
assert_se ( streq ( input_table [ 0 ] , " CAPITAL LETTERS FIRST " ) ) ;
assert_se ( streq ( input_table [ 1 ] , " apple " ) ) ;
assert_se ( streq ( input_table [ 2 ] , " banana " ) ) ;
assert_se ( streq ( input_table [ 3 ] , " citrus " ) ) ;
assert_se ( streq ( input_table [ 4 ] , " durian " ) ) ;
2013-01-31 00:36:56 +04:00
}
2010-11-16 01:49:02 +03:00
2014-01-04 05:35:27 +04:00
static void test_strv_extend_strv_concat ( void ) {
2015-08-06 01:31:09 +03:00
_cleanup_strv_free_ char * * a = NULL , * * b = NULL ;
2013-02-13 19:13:37 +04:00
2013-02-13 19:13:39 +04:00
a = strv_new ( " without " , " suffix " , NULL ) ;
b = strv_new ( " with " , " suffix " , NULL ) ;
2013-02-18 19:48:12 +04:00
assert_se ( a ) ;
assert_se ( b ) ;
2013-02-13 19:13:37 +04:00
2014-01-04 05:35:27 +04:00
assert_se ( strv_extend_strv_concat ( & a , b , " _suffix " ) > = 0 ) ;
2013-02-13 19:13:37 +04:00
2014-01-04 05:35:27 +04:00
assert_se ( streq ( a [ 0 ] , " without " ) ) ;
assert_se ( streq ( a [ 1 ] , " suffix " ) ) ;
assert_se ( streq ( a [ 2 ] , " with_suffix " ) ) ;
assert_se ( streq ( a [ 3 ] , " suffix_suffix " ) ) ;
2013-02-13 19:13:37 +04:00
}
2014-01-04 05:35:27 +04:00
static void test_strv_extend_strv ( void ) {
2016-04-14 04:09:32 +03:00
_cleanup_strv_free_ char * * a = NULL , * * b = NULL , * * n = NULL ;
2013-02-13 19:13:36 +04:00
2013-02-13 19:13:39 +04:00
a = strv_new ( " abc " , " def " , " ghi " , NULL ) ;
2015-10-07 12:26:10 +03:00
b = strv_new ( " jkl " , " mno " , " abc " , " pqr " , NULL ) ;
2013-02-18 19:48:12 +04:00
assert_se ( a ) ;
assert_se ( b ) ;
2013-02-13 19:13:36 +04:00
2015-10-07 12:26:10 +03:00
assert_se ( strv_extend_strv ( & a , b , true ) = = 3 ) ;
2013-02-13 19:13:36 +04:00
2014-01-04 05:35:27 +04:00
assert_se ( streq ( a [ 0 ] , " abc " ) ) ;
assert_se ( streq ( a [ 1 ] , " def " ) ) ;
assert_se ( streq ( a [ 2 ] , " ghi " ) ) ;
assert_se ( streq ( a [ 3 ] , " jkl " ) ) ;
assert_se ( streq ( a [ 4 ] , " mno " ) ) ;
assert_se ( streq ( a [ 5 ] , " pqr " ) ) ;
assert_se ( strv_length ( a ) = = 6 ) ;
2016-04-14 04:09:32 +03:00
assert_se ( strv_extend_strv ( & n , b , false ) > = 0 ) ;
assert_se ( streq ( n [ 0 ] , " jkl " ) ) ;
assert_se ( streq ( n [ 1 ] , " mno " ) ) ;
assert_se ( streq ( n [ 2 ] , " abc " ) ) ;
assert_se ( streq ( n [ 3 ] , " pqr " ) ) ;
assert_se ( strv_length ( n ) = = 4 ) ;
2013-02-13 19:13:36 +04:00
}
2014-01-04 05:35:27 +04:00
static void test_strv_extend ( void ) {
_cleanup_strv_free_ char * * a = NULL , * * b = NULL ;
2013-02-13 19:13:38 +04:00
a = strv_new ( " test " , " test1 " , NULL ) ;
2013-02-18 19:48:12 +04:00
assert_se ( a ) ;
2014-01-04 05:35:27 +04:00
assert_se ( strv_extend ( & a , " test2 " ) > = 0 ) ;
assert_se ( strv_extend ( & b , " test3 " ) > = 0 ) ;
2013-02-13 19:13:38 +04:00
2014-01-04 05:35:27 +04:00
assert_se ( streq ( a [ 0 ] , " test " ) ) ;
assert_se ( streq ( a [ 1 ] , " test1 " ) ) ;
assert_se ( streq ( a [ 2 ] , " test2 " ) ) ;
assert_se ( streq ( b [ 0 ] , " test3 " ) ) ;
2013-02-13 19:13:38 +04:00
}
2014-06-20 02:25:58 +04:00
static void test_strv_extendf ( void ) {
_cleanup_strv_free_ char * * a = NULL , * * b = NULL ;
a = strv_new ( " test " , " test1 " , NULL ) ;
assert_se ( a ) ;
assert_se ( strv_extendf ( & a , " test2 %s %d %s " , " foo " , 128 , " bar " ) > = 0 ) ;
assert_se ( strv_extendf ( & b , " test3 %s %s %d " , " bar " , " foo " , 128 ) > = 0 ) ;
assert_se ( streq ( a [ 0 ] , " test " ) ) ;
assert_se ( streq ( a [ 1 ] , " test1 " ) ) ;
assert_se ( streq ( a [ 2 ] , " test2 foo 128 bar " ) ) ;
assert_se ( streq ( b [ 0 ] , " test3 bar foo 128 " ) ) ;
}
2013-10-27 15:45:53 +04:00
static void test_strv_foreach ( void ) {
2013-10-29 22:53:43 +04:00
_cleanup_strv_free_ char * * a ;
unsigned i = 0 ;
char * * check ;
2013-10-27 15:45:53 +04:00
2013-10-29 22:53:43 +04:00
a = strv_new ( " one " , " two " , " three " , NULL ) ;
2013-10-27 15:45:53 +04:00
2013-10-29 22:53:43 +04:00
assert_se ( a ) ;
2013-10-27 15:45:53 +04:00
2013-10-29 22:53:43 +04:00
STRV_FOREACH ( check , a ) {
assert_se ( streq ( * check , input_table_multiple [ i + + ] ) ) ;
}
2013-10-27 15:45:53 +04:00
}
static void test_strv_foreach_backwards ( void ) {
2013-10-29 22:53:43 +04:00
_cleanup_strv_free_ char * * a ;
unsigned i = 2 ;
char * * check ;
2013-10-27 15:45:53 +04:00
2013-10-29 22:53:43 +04:00
a = strv_new ( " one " , " two " , " three " , NULL ) ;
2013-10-27 15:45:53 +04:00
2013-10-29 22:53:43 +04:00
assert_se ( a ) ;
2013-10-27 15:45:53 +04:00
2016-08-26 20:18:15 +03:00
STRV_FOREACH_BACKWARDS ( check , a )
2013-12-13 02:08:47 +04:00
assert_se ( streq_ptr ( * check , input_table_multiple [ i - - ] ) ) ;
2016-08-26 20:18:15 +03:00
STRV_FOREACH_BACKWARDS ( check , ( char * * ) NULL )
assert_not_reached ( " Let's see that we check empty strv right, too. " ) ;
STRV_FOREACH_BACKWARDS ( check , ( char * * ) { NULL } )
assert_not_reached ( " Let's see that we check empty strv right, too. " ) ;
2013-10-27 15:45:53 +04:00
}
2013-03-16 13:00:03 +04:00
static void test_strv_foreach_pair ( void ) {
_cleanup_strv_free_ char * * a = NULL ;
char * * x , * * y ;
a = strv_new ( " pair_one " , " pair_one " ,
" pair_two " , " pair_two " ,
" pair_three " , " pair_three " ,
NULL ) ;
STRV_FOREACH_PAIR ( x , y , a ) {
assert_se ( streq ( * x , * y ) ) ;
}
}
2013-10-29 23:09:16 +04:00
static void test_strv_from_stdarg_alloca_one ( char * * l , const char * first , . . . ) {
2013-10-29 22:53:43 +04:00
char * * j ;
unsigned i ;
j = strv_from_stdarg_alloca ( first ) ;
for ( i = 0 ; ; i + + ) {
assert_se ( streq_ptr ( l [ i ] , j [ i ] ) ) ;
if ( ! l [ i ] )
break ;
}
}
static void test_strv_from_stdarg_alloca ( void ) {
2013-10-29 23:09:16 +04:00
test_strv_from_stdarg_alloca_one ( STRV_MAKE ( " foo " , " bar " ) , " foo " , " bar " , NULL ) ;
test_strv_from_stdarg_alloca_one ( STRV_MAKE ( " foo " ) , " foo " , NULL ) ;
test_strv_from_stdarg_alloca_one ( STRV_MAKE_EMPTY , NULL ) ;
2013-10-29 22:53:43 +04:00
}
2014-10-12 19:32:23 +04:00
static void test_strv_push_prepend ( void ) {
_cleanup_strv_free_ char * * a = NULL ;
a = strv_new ( " foo " , " bar " , " three " , NULL ) ;
assert_se ( strv_push_prepend ( & a , strdup ( " first " ) ) > = 0 ) ;
assert_se ( streq ( a [ 0 ] , " first " ) ) ;
assert_se ( streq ( a [ 1 ] , " foo " ) ) ;
assert_se ( streq ( a [ 2 ] , " bar " ) ) ;
assert_se ( streq ( a [ 3 ] , " three " ) ) ;
assert_se ( ! a [ 4 ] ) ;
assert_se ( strv_consume_prepend ( & a , strdup ( " first2 " ) ) > = 0 ) ;
assert_se ( streq ( a [ 0 ] , " first2 " ) ) ;
assert_se ( streq ( a [ 1 ] , " first " ) ) ;
assert_se ( streq ( a [ 2 ] , " foo " ) ) ;
assert_se ( streq ( a [ 3 ] , " bar " ) ) ;
assert_se ( streq ( a [ 4 ] , " three " ) ) ;
assert_se ( ! a [ 5 ] ) ;
}
2014-12-03 20:31:51 +03:00
static void test_strv_push ( void ) {
_cleanup_strv_free_ char * * a = NULL ;
char * i , * j ;
assert_se ( i = strdup ( " foo " ) ) ;
assert_se ( strv_push ( & a , i ) > = 0 ) ;
assert_se ( i = strdup ( " a " ) ) ;
assert_se ( j = strdup ( " b " ) ) ;
assert_se ( strv_push_pair ( & a , i , j ) > = 0 ) ;
assert_se ( streq_ptr ( a [ 0 ] , " foo " ) ) ;
assert_se ( streq_ptr ( a [ 1 ] , " a " ) ) ;
assert_se ( streq_ptr ( a [ 2 ] , " b " ) ) ;
assert_se ( streq_ptr ( a [ 3 ] , NULL ) ) ;
}
2014-12-11 20:30:16 +03:00
static void test_strv_equal ( void ) {
_cleanup_strv_free_ char * * a = NULL ;
_cleanup_strv_free_ char * * b = NULL ;
_cleanup_strv_free_ char * * c = NULL ;
a = strv_new ( " one " , " two " , " three " , NULL ) ;
assert_se ( a ) ;
b = strv_new ( " one " , " two " , " three " , NULL ) ;
assert_se ( a ) ;
c = strv_new ( " one " , " two " , " three " , " four " , NULL ) ;
assert_se ( a ) ;
assert_se ( strv_equal ( a , a ) ) ;
assert_se ( strv_equal ( a , b ) ) ;
assert_se ( strv_equal ( NULL , NULL ) ) ;
assert_se ( ! strv_equal ( a , c ) ) ;
assert_se ( ! strv_equal ( b , c ) ) ;
assert_se ( ! strv_equal ( b , NULL ) ) ;
}
2014-12-19 03:31:59 +03:00
static void test_strv_is_uniq ( void ) {
_cleanup_strv_free_ char * * a = NULL , * * b = NULL , * * c = NULL , * * d = NULL ;
a = strv_new ( NULL , NULL ) ;
assert_se ( a ) ;
assert_se ( strv_is_uniq ( a ) ) ;
b = strv_new ( " foo " , NULL ) ;
assert_se ( b ) ;
assert_se ( strv_is_uniq ( b ) ) ;
c = strv_new ( " foo " , " bar " , NULL ) ;
assert_se ( c ) ;
assert_se ( strv_is_uniq ( c ) ) ;
d = strv_new ( " foo " , " bar " , " waldo " , " bar " , " piep " , NULL ) ;
assert_se ( d ) ;
assert_se ( ! strv_is_uniq ( d ) ) ;
}
static void test_strv_reverse ( void ) {
_cleanup_strv_free_ char * * a = NULL , * * b = NULL , * * c = NULL , * * d = NULL ;
a = strv_new ( NULL , NULL ) ;
assert_se ( a ) ;
strv_reverse ( a ) ;
assert_se ( strv_isempty ( a ) ) ;
b = strv_new ( " foo " , NULL ) ;
assert_se ( b ) ;
strv_reverse ( b ) ;
assert_se ( streq_ptr ( b [ 0 ] , " foo " ) ) ;
assert_se ( streq_ptr ( b [ 1 ] , NULL ) ) ;
c = strv_new ( " foo " , " bar " , NULL ) ;
assert_se ( c ) ;
strv_reverse ( c ) ;
assert_se ( streq_ptr ( c [ 0 ] , " bar " ) ) ;
assert_se ( streq_ptr ( c [ 1 ] , " foo " ) ) ;
assert_se ( streq_ptr ( c [ 2 ] , NULL ) ) ;
d = strv_new ( " foo " , " bar " , " waldo " , NULL ) ;
assert_se ( d ) ;
strv_reverse ( d ) ;
assert_se ( streq_ptr ( d [ 0 ] , " waldo " ) ) ;
assert_se ( streq_ptr ( d [ 1 ] , " bar " ) ) ;
assert_se ( streq_ptr ( d [ 2 ] , " foo " ) ) ;
assert_se ( streq_ptr ( d [ 3 ] , NULL ) ) ;
}
2015-06-23 13:57:41 +03:00
static void test_strv_shell_escape ( void ) {
_cleanup_strv_free_ char * * v = NULL ;
v = strv_new ( " foo:bar " , " bar,baz " , " wal \\ do " , NULL ) ;
assert_se ( v ) ;
assert_se ( strv_shell_escape ( v , " ,: " ) ) ;
assert_se ( streq_ptr ( v [ 0 ] , " foo \\ :bar " ) ) ;
assert_se ( streq_ptr ( v [ 1 ] , " bar \\ ,baz " ) ) ;
assert_se ( streq_ptr ( v [ 2 ] , " wal \\ \\ do " ) ) ;
assert_se ( streq_ptr ( v [ 3 ] , NULL ) ) ;
}
2015-09-24 13:23:21 +03:00
static void test_strv_skip_one ( char * * a , size_t n , char * * b ) {
a = strv_skip ( a , n ) ;
assert_se ( strv_equal ( a , b ) ) ;
}
static void test_strv_skip ( void ) {
test_strv_skip_one ( STRV_MAKE ( " foo " , " bar " , " baz " ) , 0 , STRV_MAKE ( " foo " , " bar " , " baz " ) ) ;
test_strv_skip_one ( STRV_MAKE ( " foo " , " bar " , " baz " ) , 1 , STRV_MAKE ( " bar " , " baz " ) ) ;
test_strv_skip_one ( STRV_MAKE ( " foo " , " bar " , " baz " ) , 2 , STRV_MAKE ( " baz " ) ) ;
test_strv_skip_one ( STRV_MAKE ( " foo " , " bar " , " baz " ) , 3 , STRV_MAKE ( NULL ) ) ;
test_strv_skip_one ( STRV_MAKE ( " foo " , " bar " , " baz " ) , 4 , STRV_MAKE ( NULL ) ) ;
test_strv_skip_one ( STRV_MAKE ( " foo " , " bar " , " baz " ) , 55 , STRV_MAKE ( NULL ) ) ;
test_strv_skip_one ( STRV_MAKE ( " quux " ) , 0 , STRV_MAKE ( " quux " ) ) ;
test_strv_skip_one ( STRV_MAKE ( " quux " ) , 1 , STRV_MAKE ( NULL ) ) ;
test_strv_skip_one ( STRV_MAKE ( " quux " ) , 55 , STRV_MAKE ( NULL ) ) ;
test_strv_skip_one ( STRV_MAKE ( NULL ) , 0 , STRV_MAKE ( NULL ) ) ;
test_strv_skip_one ( STRV_MAKE ( NULL ) , 1 , STRV_MAKE ( NULL ) ) ;
test_strv_skip_one ( STRV_MAKE ( NULL ) , 55 , STRV_MAKE ( NULL ) ) ;
}
2015-10-04 18:36:19 +03:00
static void test_strv_extend_n ( void ) {
_cleanup_strv_free_ char * * v = NULL ;
v = strv_new ( " foo " , " bar " , NULL ) ;
assert_se ( v ) ;
assert_se ( strv_extend_n ( & v , " waldo " , 3 ) > = 0 ) ;
assert_se ( strv_extend_n ( & v , " piep " , 2 ) > = 0 ) ;
assert_se ( streq ( v [ 0 ] , " foo " ) ) ;
assert_se ( streq ( v [ 1 ] , " bar " ) ) ;
assert_se ( streq ( v [ 2 ] , " waldo " ) ) ;
assert_se ( streq ( v [ 3 ] , " waldo " ) ) ;
assert_se ( streq ( v [ 4 ] , " waldo " ) ) ;
assert_se ( streq ( v [ 5 ] , " piep " ) ) ;
assert_se ( streq ( v [ 6 ] , " piep " ) ) ;
assert_se ( v [ 7 ] = = NULL ) ;
v = strv_free ( v ) ;
assert_se ( strv_extend_n ( & v , " foo " , 1 ) > = 0 ) ;
assert_se ( strv_extend_n ( & v , " bar " , 0 ) > = 0 ) ;
assert_se ( streq ( v [ 0 ] , " foo " ) ) ;
assert_se ( v [ 1 ] = = NULL ) ;
}
2015-10-07 12:26:10 +03:00
static void test_strv_make_nulstr_one ( char * * l ) {
_cleanup_free_ char * b = NULL , * c = NULL ;
_cleanup_strv_free_ char * * q = NULL ;
2016-07-09 03:38:00 +03:00
const char * s = NULL ;
2015-10-07 12:26:10 +03:00
size_t n , m ;
2016-07-09 03:38:00 +03:00
unsigned i = 0 ;
2015-10-07 12:26:10 +03:00
assert_se ( strv_make_nulstr ( l , & b , & n ) > = 0 ) ;
assert_se ( q = strv_parse_nulstr ( b , n ) ) ;
assert_se ( strv_equal ( l , q ) ) ;
assert_se ( strv_make_nulstr ( q , & c , & m ) > = 0 ) ;
assert_se ( m = = n ) ;
assert_se ( memcmp ( b , c , m ) = = 0 ) ;
2016-07-09 03:38:00 +03:00
2016-07-17 22:25:01 +03:00
NULSTR_FOREACH ( s , b )
2016-07-09 03:38:00 +03:00
assert_se ( streq ( s , l [ i + + ] ) ) ;
assert_se ( i = = strv_length ( l ) ) ;
2015-10-07 12:26:10 +03:00
}
static void test_strv_make_nulstr ( void ) {
test_strv_make_nulstr_one ( NULL ) ;
test_strv_make_nulstr_one ( STRV_MAKE ( NULL ) ) ;
test_strv_make_nulstr_one ( STRV_MAKE ( " foo " ) ) ;
test_strv_make_nulstr_one ( STRV_MAKE ( " foo " , " bar " ) ) ;
test_strv_make_nulstr_one ( STRV_MAKE ( " foo " , " bar " , " quuux " ) ) ;
}
2016-03-03 01:01:38 +03:00
static void test_foreach_string ( void ) {
const char * const t [ ] = {
" foo " ,
" bar " ,
" waldo " ,
NULL
} ;
const char * x ;
unsigned i = 0 ;
FOREACH_STRING ( x , " foo " , " bar " , " waldo " )
assert_se ( streq_ptr ( t [ i + + ] , x ) ) ;
assert_se ( i = = 3 ) ;
FOREACH_STRING ( x , " zzz " )
assert_se ( streq ( x , " zzz " ) ) ;
}
2016-06-27 15:47:37 +03:00
static void test_strv_fnmatch ( void ) {
2016-07-04 11:11:07 +03:00
_cleanup_strv_free_ char * * v = NULL ;
2016-06-27 15:47:37 +03:00
assert_se ( ! strv_fnmatch ( STRV_MAKE_EMPTY , " a " , 0 ) ) ;
v = strv_new ( " * \\ * " , NULL ) ;
assert_se ( ! strv_fnmatch ( v , " \\ " , 0 ) ) ;
assert_se ( strv_fnmatch ( v , " \\ " , FNM_NOESCAPE ) ) ;
}
2013-01-31 00:36:56 +04:00
int main ( int argc , char * argv [ ] ) {
test_specifier_printf ( ) ;
2016-09-25 03:13:28 +03:00
test_str_in_set ( ) ;
test_strptr_in_set ( ) ;
2013-10-27 15:45:53 +04:00
test_strv_foreach ( ) ;
test_strv_foreach_backwards ( ) ;
2013-03-16 13:00:03 +04:00
test_strv_foreach_pair ( ) ;
2013-02-07 00:15:23 +04:00
test_strv_find ( ) ;
test_strv_find_prefix ( ) ;
2014-10-12 19:32:23 +04:00
test_strv_find_startswith ( ) ;
2013-01-31 00:45:40 +04:00
test_strv_join ( ) ;
2013-08-31 22:28:09 +04:00
test_strv_quote_unquote ( input_table_multiple , " \" one \" \" two \" \" three \" " ) ;
test_strv_quote_unquote ( input_table_one , " \" one \" " ) ;
test_strv_quote_unquote ( input_table_none , " " ) ;
basic/strv: fix strv_join for first empty argument
Empty strings were ignored in strv_join, but only if they were at the beginning
of the string. Empty strings after at least one non-empty item were treated
normally.
Previously:
{"x"} → "x"
{"x", ""} → "x"
{"x", "", ""} → "x::"
{""} → ""
{"", ""} → ""
{"", "", ""} → ""
{"", "x"} → "x"
{"", "x", ""} → "x:"
Now:
{"x"} → "x"
{"x", ""} → "x"
{"x", "", ""} → "x::"
{""} → ""
{"", ""} → ":"
{"", "", ""} → "::"
{"", "x"} → ":x"
{"", "x", ""} → ":x:"
2016-02-12 07:24:14 +03:00
test_strv_quote_unquote ( input_table_one_empty , " \" \" " ) ;
test_strv_quote_unquote ( input_table_two_empties , " \" \" \" \" " ) ;
2013-08-31 22:28:09 +04:00
test_strv_quote_unquote ( input_table_quotes , QUOTES_STRING ) ;
test_strv_quote_unquote ( input_table_spaces , SPACES_STRING ) ;
2014-12-19 01:01:42 +03:00
test_strv_unquote ( " foo=bar \" waldo \" zzz " , STRV_MAKE ( " foo=bar " , " waldo " , " zzz " ) ) ;
test_strv_unquote ( " " , STRV_MAKE_EMPTY ) ;
test_strv_unquote ( " " , STRV_MAKE_EMPTY ) ;
test_strv_unquote ( " " , STRV_MAKE_EMPTY ) ;
test_strv_unquote ( " x " , STRV_MAKE ( " x " ) ) ;
test_strv_unquote ( " x " , STRV_MAKE ( " x " ) ) ;
test_strv_unquote ( " x " , STRV_MAKE ( " x " ) ) ;
test_strv_unquote ( " \" x \" " , STRV_MAKE ( " x " ) ) ;
test_strv_unquote ( " 'x' " , STRV_MAKE ( " x " ) ) ;
test_strv_unquote ( " 'x \" ' " , STRV_MAKE ( " x \" " ) ) ;
test_strv_unquote ( " \" x' \" " , STRV_MAKE ( " x' " ) ) ;
test_strv_unquote ( " a '--b=c \" d e \" ' " , STRV_MAKE ( " a " , " --b=c \" d e \" " ) ) ;
2014-07-29 04:01:56 +04:00
2014-12-19 01:51:38 +03:00
/* trailing backslashes */
test_strv_unquote ( " x \\ \\ " , STRV_MAKE ( " x \\ " ) ) ;
test_invalid_unquote ( " x \\ " ) ;
2014-11-11 01:44:34 +03:00
test_invalid_unquote ( " a --b='c \" d e \" '' " ) ;
test_invalid_unquote ( " a --b='c \" d e \" ' \" " ) ;
2014-07-30 06:01:36 +04:00
test_invalid_unquote ( " a --b='c \" d e \" garbage " ) ;
2014-07-31 11:28:37 +04:00
test_invalid_unquote ( " ' " ) ;
test_invalid_unquote ( " \" " ) ;
2014-11-11 01:44:34 +03:00
test_invalid_unquote ( " 'x'y'g " ) ;
2013-11-28 01:37:52 +04:00
2013-10-31 13:03:08 +04:00
test_strv_split ( ) ;
2015-06-19 18:24:34 +03:00
test_strv_split_extract ( ) ;
2013-10-31 13:03:08 +04:00
test_strv_split_newlines ( ) ;
2013-02-19 02:53:33 +04:00
test_strv_split_nulstr ( ) ;
2013-02-07 03:33:58 +04:00
test_strv_parse_nulstr ( ) ;
2013-02-07 00:15:23 +04:00
test_strv_overlap ( ) ;
test_strv_sort ( ) ;
2014-01-04 05:35:27 +04:00
test_strv_extend_strv ( ) ;
test_strv_extend_strv_concat ( ) ;
test_strv_extend ( ) ;
2014-06-20 02:25:58 +04:00
test_strv_extendf ( ) ;
2013-10-29 22:53:43 +04:00
test_strv_from_stdarg_alloca ( ) ;
2014-10-12 19:32:23 +04:00
test_strv_push_prepend ( ) ;
2014-12-03 20:31:51 +03:00
test_strv_push ( ) ;
2014-12-11 20:30:16 +03:00
test_strv_equal ( ) ;
2014-12-19 03:31:59 +03:00
test_strv_is_uniq ( ) ;
test_strv_reverse ( ) ;
2015-06-23 13:57:41 +03:00
test_strv_shell_escape ( ) ;
2015-09-24 13:23:21 +03:00
test_strv_skip ( ) ;
2015-10-04 18:36:19 +03:00
test_strv_extend_n ( ) ;
2015-10-07 12:26:10 +03:00
test_strv_make_nulstr ( ) ;
2011-01-07 01:51:52 +03:00
2016-03-03 01:01:38 +03:00
test_foreach_string ( ) ;
2016-06-27 15:47:37 +03:00
test_strv_fnmatch ( ) ;
2016-03-03 01:01:38 +03:00
2010-11-14 21:58:33 +03:00
return 0 ;
}