2013-04-15 16:05:00 +04:00
/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
/***
This file is part of systemd .
Copyright 2013 Zbigniew Jędrzejewski - Szmek
systemd is free software ; you can redistribute it and / or modify it
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
( 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
Lesser General Public License for more details .
You should have received a copy of the GNU Lesser General Public License
along with systemd ; If not , see < http : //www.gnu.org/licenses/>.
* * */
2013-01-18 10:13:27 +04:00
# include "util.h"
# include "cgroup-util.h"
2013-07-18 10:30:06 +04:00
# include "test-helper.h"
2015-04-10 21:43:52 +03:00
# include "formats-util.h"
2015-04-10 20:10:00 +03:00
# include "process-util.h"
2013-01-18 10:13:27 +04:00
2013-04-16 06:36:06 +04:00
static void check_p_d_u ( const char * path , int code , const char * result ) {
2013-04-15 16:05:00 +04:00
_cleanup_free_ char * unit = NULL ;
2013-12-23 03:28:03 +04:00
int r ;
2013-01-18 10:13:27 +04:00
2013-12-23 03:28:03 +04:00
r = cg_path_decode_unit ( path , & unit ) ;
printf ( " %s: %s → %s %d expected %s %d \n " , __func__ , path , unit , r , result , code ) ;
assert_se ( r = = code ) ;
2013-04-15 16:05:00 +04:00
assert_se ( streq_ptr ( unit , result ) ) ;
}
2013-01-18 10:13:27 +04:00
2013-04-16 06:36:06 +04:00
static void test_path_decode_unit ( void ) {
2013-07-11 20:47:20 +04:00
check_p_d_u ( " getty@tty2.service " , 0 , " getty@tty2.service " ) ;
check_p_d_u ( " getty@tty2.service/ " , 0 , " getty@tty2.service " ) ;
check_p_d_u ( " getty@tty2.service/xxx " , 0 , " getty@tty2.service " ) ;
2015-04-29 22:40:54 +03:00
check_p_d_u ( " getty@.service/ " , - ENXIO , NULL ) ;
check_p_d_u ( " getty@.service " , - ENXIO , NULL ) ;
2013-04-16 06:36:06 +04:00
check_p_d_u ( " getty.service " , 0 , " getty.service " ) ;
2015-04-29 22:40:54 +03:00
check_p_d_u ( " getty " , - ENXIO , NULL ) ;
check_p_d_u ( " getty/waldo " , - ENXIO , NULL ) ;
2013-07-11 20:47:20 +04:00
check_p_d_u ( " _cpu.service " , 0 , " cpu.service " ) ;
2013-04-15 16:05:00 +04:00
}
static void check_p_g_u ( const char * path , int code , const char * result ) {
_cleanup_free_ char * unit = NULL ;
2013-12-23 03:28:03 +04:00
int r ;
2013-04-15 16:05:00 +04:00
2013-12-23 03:28:03 +04:00
r = cg_path_get_unit ( path , & unit ) ;
printf ( " %s: %s → %s %d expected %s %d \n " , __func__ , path , unit , r , result , code ) ;
assert_se ( r = = code ) ;
2013-04-15 16:05:00 +04:00
assert_se ( streq_ptr ( unit , result ) ) ;
}
2013-06-20 05:45:08 +04:00
static void test_path_get_unit ( void ) {
check_p_g_u ( " /system.slice/foobar.service/sdfdsaf " , 0 , " foobar.service " ) ;
2013-07-11 20:47:20 +04:00
check_p_g_u ( " /system.slice/getty@tty5.service " , 0 , " getty@tty5.service " ) ;
check_p_g_u ( " /system.slice/getty@tty5.service/aaa/bbb " , 0 , " getty@tty5.service " ) ;
check_p_g_u ( " /system.slice/getty@tty5.service/ " , 0 , " getty@tty5.service " ) ;
2013-06-20 05:45:08 +04:00
check_p_g_u ( " /system.slice/getty@tty6.service/tty5 " , 0 , " getty@tty6.service " ) ;
2015-04-29 22:40:54 +03:00
check_p_g_u ( " sadfdsafsda " , - ENXIO , NULL ) ;
check_p_g_u ( " /system.slice/getty####@tty6.service/xxx " , - ENXIO , NULL ) ;
2013-06-20 05:45:08 +04:00
check_p_g_u ( " /system.slice/system-waldo.slice/foobar.service/sdfdsaf " , 0 , " foobar.service " ) ;
2013-07-11 20:47:20 +04:00
check_p_g_u ( " /system.slice/system-waldo.slice/_cpu.service/sdfdsaf " , 0 , " cpu.service " ) ;
2013-12-23 03:28:03 +04:00
check_p_g_u ( " /user.slice/user-1000.slice/user@1000.service/server.service " , 0 , " user@1000.service " ) ;
2015-04-29 22:40:54 +03:00
check_p_g_u ( " /user.slice/user-1000.slice/user@.service/server.service " , - ENXIO , NULL ) ;
2013-06-20 05:45:08 +04:00
}
2013-04-15 16:05:00 +04:00
static void check_p_g_u_u ( const char * path , int code , const char * result ) {
_cleanup_free_ char * unit = NULL ;
2013-12-23 03:28:03 +04:00
int r ;
2013-04-15 16:05:00 +04:00
2013-12-23 03:28:03 +04:00
r = cg_path_get_user_unit ( path , & unit ) ;
printf ( " %s: %s → %s %d expected %s %d \n " , __func__ , path , unit , r , result , code ) ;
assert_se ( r = = code ) ;
2013-04-15 16:05:00 +04:00
assert_se ( streq_ptr ( unit , result ) ) ;
}
2013-06-20 05:45:08 +04:00
static void test_path_get_user_unit ( void ) {
2013-07-02 04:32:24 +04:00
check_p_g_u_u ( " /user.slice/user-1000.slice/session-2.scope/foobar.service " , 0 , " foobar.service " ) ;
check_p_g_u_u ( " /user.slice/user-1000.slice/session-2.scope/waldo.slice/foobar.service " , 0 , " foobar.service " ) ;
check_p_g_u_u ( " /user.slice/user-1002.slice/session-2.scope/foobar.service/waldo " , 0 , " foobar.service " ) ;
check_p_g_u_u ( " /user.slice/user-1000.slice/session-2.scope/foobar.service/waldo/uuuux " , 0 , " foobar.service " ) ;
2015-04-29 22:40:54 +03:00
check_p_g_u_u ( " /user.slice/user-1000.slice/session-2.scope/waldo/waldo/uuuux " , - ENXIO , NULL ) ;
2013-07-11 20:47:20 +04:00
check_p_g_u_u ( " /user.slice/user-1000.slice/session-2.scope/foobar@pie.service/pa/po " , 0 , " foobar@pie.service " ) ;
check_p_g_u_u ( " /session-2.scope/foobar@pie.service/pa/po " , 0 , " foobar@pie.service " ) ;
check_p_g_u_u ( " /xyz.slice/xyz-waldo.slice/session-77.scope/foobar@pie.service/pa/po " , 0 , " foobar@pie.service " ) ;
2015-04-29 22:40:54 +03:00
check_p_g_u_u ( " /meh.service " , - ENXIO , NULL ) ;
2013-07-11 20:47:20 +04:00
check_p_g_u_u ( " /session-3.scope/_cpu.service " , 0 , " cpu.service " ) ;
2013-12-23 03:28:03 +04:00
check_p_g_u_u ( " /user.slice/user-1000.slice/user@1000.service/server.service " , 0 , " server.service " ) ;
2015-02-04 04:07:37 +03:00
check_p_g_u_u ( " /user.slice/user-1000.slice/user@1000.service/foobar.slice/foobar@pie.service " , 0 , " foobar@pie.service " ) ;
2015-04-29 22:40:54 +03:00
check_p_g_u_u ( " /user.slice/user-1000.slice/user@.service/server.service " , - ENXIO , NULL ) ;
2013-04-16 06:36:06 +04:00
}
2013-04-15 16:05:00 +04:00
2013-06-20 05:45:08 +04:00
static void check_p_g_s ( const char * path , int code , const char * result ) {
_cleanup_free_ char * s = NULL ;
assert_se ( cg_path_get_session ( path , & s ) = = code ) ;
assert_se ( streq_ptr ( s , result ) ) ;
2013-01-18 10:13:27 +04:00
}
2013-06-20 05:45:08 +04:00
static void test_path_get_session ( void ) {
2013-07-02 04:32:24 +04:00
check_p_g_s ( " /user.slice/user-1000.slice/session-2.scope/foobar.service " , 0 , " 2 " ) ;
check_p_g_s ( " /session-3.scope " , 0 , " 3 " ) ;
2015-04-29 22:40:54 +03:00
check_p_g_s ( " /session-.scope " , - ENXIO , NULL ) ;
check_p_g_s ( " " , - ENXIO , NULL ) ;
2013-06-20 05:45:08 +04:00
}
2013-04-16 06:36:06 +04:00
2013-06-20 05:45:08 +04:00
static void check_p_g_o_u ( const char * path , int code , uid_t result ) {
uid_t uid = 0 ;
2013-04-16 06:36:06 +04:00
2013-06-20 05:45:08 +04:00
assert_se ( cg_path_get_owner_uid ( path , & uid ) = = code ) ;
assert_se ( uid = = result ) ;
}
static void test_path_get_owner_uid ( void ) {
2013-07-02 04:32:24 +04:00
check_p_g_o_u ( " /user.slice/user-1000.slice/session-2.scope/foobar.service " , 0 , 1000 ) ;
check_p_g_o_u ( " /user.slice/user-1006.slice " , 0 , 1006 ) ;
2015-04-29 22:40:54 +03:00
check_p_g_o_u ( " " , - ENXIO , 0 ) ;
2013-06-20 05:45:08 +04:00
}
2013-04-16 06:36:06 +04:00
2015-04-30 01:47:41 +03:00
static void check_p_g_slice ( const char * path , int code , const char * result ) {
_cleanup_free_ char * s = NULL ;
assert_se ( cg_path_get_slice ( path , & s ) = = code ) ;
assert_se ( streq_ptr ( s , result ) ) ;
}
static void test_path_get_slice ( void ) {
check_p_g_slice ( " /user.slice " , 0 , " user.slice " ) ;
check_p_g_slice ( " /foobar " , 0 , " -.slice " ) ;
check_p_g_slice ( " /user.slice/user-waldo.slice " , 0 , " user-waldo.slice " ) ;
check_p_g_slice ( " " , 0 , " -.slice " ) ;
check_p_g_slice ( " foobar " , 0 , " -.slice " ) ;
check_p_g_slice ( " foobar.slice " , 0 , " foobar.slice " ) ;
check_p_g_slice ( " foo.slice/foo-bar.slice/waldo.service " , 0 , " foo-bar.slice " ) ;
}
2015-04-30 12:58:06 +03:00
static void check_p_g_u_slice ( const char * path , int code , const char * result ) {
_cleanup_free_ char * s = NULL ;
assert_se ( cg_path_get_user_slice ( path , & s ) = = code ) ;
assert_se ( streq_ptr ( s , result ) ) ;
}
static void test_path_get_user_slice ( void ) {
check_p_g_u_slice ( " /user.slice " , - ENXIO , NULL ) ;
check_p_g_u_slice ( " /foobar " , - ENXIO , NULL ) ;
check_p_g_u_slice ( " /user.slice/user-waldo.slice " , - ENXIO , NULL ) ;
check_p_g_u_slice ( " " , - ENXIO , NULL ) ;
check_p_g_u_slice ( " foobar " , - ENXIO , NULL ) ;
check_p_g_u_slice ( " foobar.slice " , - ENXIO , NULL ) ;
check_p_g_u_slice ( " foo.slice/foo-bar.slice/waldo.service " , - ENXIO , NULL ) ;
check_p_g_u_slice ( " foo.slice/foo-bar.slice/user@1000.service " , 0 , " -.slice " ) ;
check_p_g_u_slice ( " foo.slice/foo-bar.slice/user@1000.service/ " , 0 , " -.slice " ) ;
check_p_g_u_slice ( " foo.slice/foo-bar.slice/user@1000.service/// " , 0 , " -.slice " ) ;
check_p_g_u_slice ( " foo.slice/foo-bar.slice/user@1000.service/waldo.service " , 0 , " -.slice " ) ;
check_p_g_u_slice ( " foo.slice/foo-bar.slice/user@1000.service/piep.slice/foo.service " , 0 , " piep.slice " ) ;
check_p_g_u_slice ( " /foo.slice//foo-bar.slice/user@1000.service/piep.slice//piep-pap.slice//foo.service " , 0 , " piep-pap.slice " ) ;
}
2013-06-20 05:45:08 +04:00
static void test_get_paths ( void ) {
_cleanup_free_ char * a = NULL ;
assert_se ( cg_get_root_path ( & a ) > = 0 ) ;
log_info ( " Root = %s " , a ) ;
2013-04-16 06:36:06 +04:00
}
2013-04-23 00:26:06 +04:00
static void test_proc ( void ) {
_cleanup_closedir_ DIR * d = NULL ;
struct dirent * de ;
int r ;
d = opendir ( " /proc " ) ;
assert_se ( d ) ;
FOREACH_DIRENT ( de , d , break ) {
2013-12-12 02:31:07 +04:00
_cleanup_free_ char * path = NULL , * path_shifted = NULL , * session = NULL , * unit = NULL , * user_unit = NULL , * machine = NULL , * slice = NULL ;
2013-04-23 00:26:06 +04:00
pid_t pid ;
2014-11-28 22:51:01 +03:00
uid_t uid = UID_INVALID ;
2013-04-23 00:26:06 +04:00
if ( de - > d_type ! = DT_DIR & &
de - > d_type ! = DT_UNKNOWN )
continue ;
r = parse_pid ( de - > d_name , & pid ) ;
if ( r < 0 )
continue ;
2013-04-23 06:10:13 +04:00
if ( is_kernel_thread ( pid ) )
continue ;
2013-04-23 00:26:06 +04:00
cg_pid_get_path ( SYSTEMD_CGROUP_CONTROLLER , pid , & path ) ;
2013-12-12 02:31:07 +04:00
cg_pid_get_path_shifted ( pid , NULL , & path_shifted ) ;
2013-04-23 06:10:13 +04:00
cg_pid_get_owner_uid ( pid , & uid ) ;
2013-04-23 00:26:06 +04:00
cg_pid_get_session ( pid , & session ) ;
cg_pid_get_unit ( pid , & unit ) ;
cg_pid_get_user_unit ( pid , & user_unit ) ;
cg_pid_get_machine_name ( pid , & machine ) ;
2013-06-21 03:46:27 +04:00
cg_pid_get_slice ( pid , & slice ) ;
2013-04-23 00:26:06 +04:00
2014-04-25 15:45:15 +04:00
printf ( PID_FMT " \t %s \t %s \t " UID_FMT " \t %s \t %s \t %s \t %s \t %s \n " ,
pid ,
2013-04-23 00:26:06 +04:00
path ,
path_shifted ,
2014-04-25 15:45:15 +04:00
uid ,
2013-04-23 00:26:06 +04:00
session ,
unit ,
user_unit ,
2013-06-21 03:46:27 +04:00
machine ,
slice ) ;
2013-04-23 00:26:06 +04:00
}
}
2013-04-23 06:10:13 +04:00
static void test_escape_one ( const char * s , const char * r ) {
_cleanup_free_ char * b ;
b = cg_escape ( s ) ;
assert_se ( b ) ;
assert_se ( streq ( b , r ) ) ;
assert_se ( streq ( cg_unescape ( b ) , s ) ) ;
}
static void test_escape ( void ) {
test_escape_one ( " foobar " , " foobar " ) ;
2013-05-03 21:02:24 +04:00
test_escape_one ( " .foobar " , " _.foobar " ) ;
2013-04-23 06:10:13 +04:00
test_escape_one ( " foobar.service " , " foobar.service " ) ;
test_escape_one ( " cgroup.service " , " _cgroup.service " ) ;
test_escape_one ( " tasks " , " _tasks " ) ;
2013-12-08 09:36:39 +04:00
if ( access ( " /sys/fs/cgroup/cpu " , F_OK ) = = 0 )
test_escape_one ( " cpu.service " , " _cpu.service " ) ;
2013-04-23 06:10:13 +04:00
test_escape_one ( " _foobar " , " __foobar " ) ;
2013-05-03 21:02:24 +04:00
test_escape_one ( " " , " _ " ) ;
test_escape_one ( " _ " , " __ " ) ;
test_escape_one ( " . " , " _. " ) ;
2013-04-23 06:10:13 +04:00
}
2013-04-25 02:01:29 +04:00
static void test_controller_is_valid ( void ) {
assert_se ( cg_controller_is_valid ( " foobar " , false ) ) ;
assert_se ( cg_controller_is_valid ( " foo_bar " , false ) ) ;
assert_se ( cg_controller_is_valid ( " name=foo " , true ) ) ;
assert_se ( ! cg_controller_is_valid ( " " , false ) ) ;
assert_se ( ! cg_controller_is_valid ( " name= " , true ) ) ;
assert_se ( ! cg_controller_is_valid ( " = " , false ) ) ;
assert_se ( ! cg_controller_is_valid ( " cpu,cpuacct " , false ) ) ;
assert_se ( ! cg_controller_is_valid ( " _ " , false ) ) ;
assert_se ( ! cg_controller_is_valid ( " _foobar " , false ) ) ;
assert_se ( ! cg_controller_is_valid ( " tatü " , false ) ) ;
}
2013-06-17 23:33:26 +04:00
static void test_slice_to_path_one ( const char * unit , const char * path , int error ) {
_cleanup_free_ char * ret = NULL ;
assert_se ( cg_slice_to_path ( unit , & ret ) = = error ) ;
assert_se ( streq_ptr ( ret , path ) ) ;
}
static void test_slice_to_path ( void ) {
test_slice_to_path_one ( " foobar.slice " , " foobar.slice " , 0 ) ;
test_slice_to_path_one ( " foobar-waldo.slice " , " foobar.slice/foobar-waldo.slice " , 0 ) ;
test_slice_to_path_one ( " foobar-waldo.service " , NULL , - EINVAL ) ;
2015-04-30 13:33:35 +03:00
test_slice_to_path_one ( " -.slice " , " " , 0 ) ;
test_slice_to_path_one ( " --.slice " , NULL , - EINVAL ) ;
test_slice_to_path_one ( " - " , NULL , - EINVAL ) ;
2013-06-17 23:33:26 +04:00
test_slice_to_path_one ( " -foo-.slice " , NULL , - EINVAL ) ;
test_slice_to_path_one ( " -foo.slice " , NULL , - EINVAL ) ;
2015-04-30 13:33:35 +03:00
test_slice_to_path_one ( " foo-.slice " , NULL , - EINVAL ) ;
test_slice_to_path_one ( " foo--bar.slice " , " foo.slice/foo-.slice/foo--bar.slice " , 0 ) ;
test_slice_to_path_one ( " foo.slice/foo--bar.slice " , NULL , - EINVAL ) ;
2013-06-17 23:33:26 +04:00
test_slice_to_path_one ( " a-b.slice " , " a.slice/a-b.slice " , 0 ) ;
test_slice_to_path_one ( " a-b-c-d-e.slice " , " a.slice/a-b.slice/a-b-c.slice/a-b-c-d.slice/a-b-c-d-e.slice " , 0 ) ;
}
2013-12-24 22:31:44 +04:00
static void test_shift_path_one ( const char * raw , const char * root , const char * shifted ) {
const char * s = NULL ;
assert_se ( cg_shift_path ( raw , root , & s ) > = 0 ) ;
assert_se ( streq ( s , shifted ) ) ;
}
static void test_shift_path ( void ) {
test_shift_path_one ( " /foobar/waldo " , " / " , " /foobar/waldo " ) ;
test_shift_path_one ( " /foobar/waldo " , " " , " /foobar/waldo " ) ;
test_shift_path_one ( " /foobar/waldo " , " /foobar " , " /waldo " ) ;
test_shift_path_one ( " /foobar/waldo " , " /fuckfuck " , " /foobar/waldo " ) ;
}
2013-01-18 10:13:27 +04:00
int main ( void ) {
2013-04-16 06:36:06 +04:00
test_path_decode_unit ( ) ;
2013-04-15 16:05:00 +04:00
test_path_get_unit ( ) ;
2013-04-16 06:36:06 +04:00
test_path_get_user_unit ( ) ;
2013-06-20 05:45:08 +04:00
test_path_get_session ( ) ;
test_path_get_owner_uid ( ) ;
2015-04-30 01:47:41 +03:00
test_path_get_slice ( ) ;
2015-04-30 12:58:06 +03:00
test_path_get_user_slice ( ) ;
2013-07-18 10:30:06 +04:00
TEST_REQ_RUNNING_SYSTEMD ( test_get_paths ( ) ) ;
2013-04-23 00:26:06 +04:00
test_proc ( ) ;
2013-07-18 10:30:06 +04:00
TEST_REQ_RUNNING_SYSTEMD ( test_escape ( ) ) ;
2013-04-25 02:01:29 +04:00
test_controller_is_valid ( ) ;
2013-06-17 23:33:26 +04:00
test_slice_to_path ( ) ;
2013-12-24 22:31:44 +04:00
test_shift_path ( ) ;
2013-01-18 10:13:27 +04:00
return 0 ;
}