1# 02-method.t
2# Method tests for BSD::Process
3#
4# Copyright (C) 2006-2007 David Landgren
5
6use strict;
7use Test::More;
8
9use BSD::Process;
10
11use Config;
12my $RUNNING_ON_FREEBSD_4 = $Config{osvers} =~ /^4/;
13my $RUNNING_ON_FREEBSD_5 = $Config{osvers} =~ /^5/;
14
15plan tests => 242
16    + BSD::Process::max_kernel_groups
17    + scalar(BSD::Process::attr_alias);
18
19{
20    my $pi = BSD::Process->new();   # implicit pid
21    my $pe = BSD::Process->new($$); # explicit pid
22
23    is( $pi->{pid}, $pe->{pid}, 'attribute pid' );
24    is( $pi->{sid}, $pe->{sid}, 'attribute sid' );
25    is( $pi->{tsid}, $pe->{tsid}, 'attribute tsid' );
26
27    is($pe->pid,         delete $pe->{pid},         'method pid' );
28    is($pe->ppid,        delete $pe->{ppid},        'method ppid');
29    is($pe->pgid,        delete $pe->{pgid},        'method pgid');
30    is($pe->tpgid,       delete $pe->{tpgid},       'method tpgid');
31    is($pe->sid,         delete $pe->{sid},         'method tpgid');
32    is($pe->jobc,        delete $pe->{jobc},        'method jobc');
33    is($pe->rssize,      delete $pe->{rssize},      'method rssize');
34    is($pe->swrss,       delete $pe->{swrss},       'method swrss');
35    is($pe->tsize,       delete $pe->{tsize},       'method tsize');
36    is($pe->xstat,       delete $pe->{xstat},       'method xstat');
37    is($pe->acflag,      delete $pe->{acflag},      'method acflag');
38    is($pe->pctcpu,      delete $pe->{pctcpu},      'method pctcpu');
39    is($pe->estcpu,      delete $pe->{estcpu},      'method estcpu');
40    is($pe->slptime,     delete $pe->{slptime},     'method slptime');
41    is($pe->swtime,      delete $pe->{swtime},      'method swtime');
42    is($pe->runtime,     delete $pe->{runtime},     'method runtime');
43    is($pe->flag,        delete $pe->{flag},        'method flag');
44    is($pe->nice,        delete $pe->{nice},        'method nice');
45    is($pe->lock,        delete $pe->{lock},        'method lock');
46    is($pe->rqindex,     delete $pe->{rqindex},     'method rqindex');
47    is($pe->oncpu,       delete $pe->{oncpu},       'method oncpu');
48    is($pe->lastcpu,     delete $pe->{lastcpu},     'method lastcpu');
49    is($pe->wmesg,       delete $pe->{wmesg},       'method wmesg');
50    is($pe->login,       delete $pe->{login},       'method login');
51    is($pe->comm,        delete $pe->{comm},        'method comm');
52
53    my $ngroups;
54    is($pe->args,        delete $pe->{args},        'method args' );
55    is($pe->tsid,        delete $pe->{tsid},        'method tsid');
56    is($pe->uid,         delete $pe->{uid},         'method uid');
57    is($pe->ruid,        delete $pe->{ruid},        'method ruid');
58    is($pe->svuid,       delete $pe->{svuid},       'method svuid');
59    is($pe->rgid,        delete $pe->{rgid},        'method rgid');
60    is($pe->svgid,       delete $pe->{svgid},       'method svgid');
61    is($pe->ngroups,     $ngroups = delete $pe->{ngroups}, 'method ngroups');
62    is($pe->size,        delete $pe->{size},        'method size');
63    is($pe->dsize,       delete $pe->{dsize},       'method dsize');
64    is($pe->ssize,       delete $pe->{ssize},       'method ssize');
65    is($pe->start,       delete $pe->{start},       'method start');
66    is($pe->childtime,   delete $pe->{childtime},   'method childtime');
67    is($pe->advlock,     delete $pe->{advlock},     'method advlock');
68    is($pe->controlt,    delete $pe->{controlt},    'method controlt');
69    is($pe->kthread,     delete $pe->{kthread},     'method kthread');
70    is($pe->noload,      delete $pe->{noload},      'method noload');
71    is($pe->ppwait,      delete $pe->{ppwait},      'method ppwait');
72    is($pe->profil,      delete $pe->{profil},      'method profil');
73    is($pe->stopprof,    delete $pe->{stopprof},    'method stopprof');
74    is($pe->sugid,       delete $pe->{sugid},       'method sugid');
75    is($pe->system,      delete $pe->{system},      'method system');
76    is($pe->single_exit, delete $pe->{single_exit}, 'method single_exit');
77    is($pe->traced,      delete $pe->{traced},      'method traced');
78    is($pe->waited,      delete $pe->{waited},      'method waited');
79    is($pe->wexit,       delete $pe->{wexit},       'method wexit');
80    is($pe->exec,        delete $pe->{exec},        'method exec');
81    is($pe->kiflag,      delete $pe->{kiflag},      'method kiflag');
82    is($pe->locked,      delete $pe->{locked},      'method locked');
83    is($pe->isctty,      delete $pe->{isctty},      'method isctty');
84    is($pe->issleader,   delete $pe->{issleader},   'method issleader');
85    is($pe->stat,        delete $pe->{stat},        'method stat');
86    is($pe->stat_1,      delete $pe->{stat_1},      'method stat_1');
87    is($pe->stat_2,      delete $pe->{stat_2},      'method stat_2');
88    is($pe->stat_3,      delete $pe->{stat_3},      'method stat_3');
89    is($pe->stat_4,      delete $pe->{stat_4},      'method stat_4');
90    is($pe->stat_5,      delete $pe->{stat_5},      'method stat_5');
91    is($pe->stat_6,      delete $pe->{stat_6},      'method stat_6');
92    is($pe->stat_7,      delete $pe->{stat_7},      'method stat_7');
93    is($pe->ocomm,       delete $pe->{ocomm},       'method ocomm');
94    is($pe->lockname,    delete $pe->{lockname},    'method lockname');
95    is($pe->pri_class,   delete $pe->{pri_class},   'method pri_class');
96    is($pe->pri_level,   delete $pe->{pri_level},   'method pri_level');
97    is($pe->pri_native,  delete $pe->{pri_native},  'method pri_native');
98    is($pe->pri_user,    delete $pe->{pri_user},    'method pri_user');
99    is($pe->utime,       delete $pe->{utime},       'method utime');
100    is($pe->stime,       delete $pe->{stime},       'method stime');
101    is($pe->time,        delete $pe->{time},        'method time (utime+stime)');
102    is($pe->maxrss,      delete $pe->{maxrss},      'method maxrss');
103    is($pe->ixrss,       delete $pe->{ixrss},       'method ixrss');
104    is($pe->idrss,       delete $pe->{idrss},       'method idrss');
105    is($pe->isrss,       delete $pe->{isrss},       'method isrss');
106    is($pe->minflt,      delete $pe->{minflt},      'method minflt');
107    is($pe->majflt,      delete $pe->{majflt},      'method majflt');
108    is($pe->nswap,       delete $pe->{nswap},       'method nswap');
109    is($pe->inblock,     delete $pe->{inblock},     'method inblock');
110    is($pe->oublock,     delete $pe->{oublock},     'method oublock');
111    is($pe->msgsnd,      delete $pe->{msgsnd},      'method msgsnd');
112    is($pe->msgrcv,      delete $pe->{msgrcv},      'method msgrcv');
113    is($pe->nsignals,    delete $pe->{nsignals},    'method nsignals');
114    is($pe->nvcsw,       delete $pe->{nvcsw},       'method nvcsw');
115    is($pe->nivcsw,      delete $pe->{nivcsw},      'method nivcsw');
116
117    my $grouplist = $pe->groups;
118    delete $pe->{groups};
119    ok( defined($grouplist), 'method groups' );
120    is( ref($grouplist), 'ARRAY', q{... it's a list} );
121    SKIP: {
122        skip( "not supported on FreeBSD 4.x", 1 )
123            if $RUNNING_ON_FREEBSD_4;
124        is( scalar(@$grouplist), $ngroups, "... of the expected size" )
125            or diag("grouplist = (@$grouplist)");
126    }
127
128    is($pe->hadthreads,  delete $pe->{hadthreads},  'method hadthreads');
129    is($pe->emul,        delete $pe->{emul},        'method emul');
130    is($pe->jid,         delete $pe->{jid},         'method jid');
131    is($pe->numthreads,  delete $pe->{numthreads},  'method numthreads');
132    is($pe->utime_ch,    delete $pe->{utime_ch},    'method utime_ch');
133    is($pe->stime_ch,    delete $pe->{stime_ch},    'method stime_ch');
134    is($pe->time_ch,     delete $pe->{time_ch},     'method time_ch (utime_ch+stime_ch');
135    is($pe->maxrss_ch,   delete $pe->{maxrss_ch},   'method maxrss_ch');
136    is($pe->ixrss_ch,    delete $pe->{ixrss_ch},    'method ixrss_ch');
137    is($pe->idrss_ch,    delete $pe->{idrss_ch},    'method idrss_ch');
138    is($pe->isrss_ch,    delete $pe->{isrss_ch},    'method isrss_ch');
139    is($pe->minflt_ch,   delete $pe->{minflt_ch},   'method minflt_ch');
140    is($pe->majflt_ch,   delete $pe->{majflt_ch},   'method majflt_ch');
141    is($pe->nswap_ch,    delete $pe->{nswap_ch},    'method nswap_ch');
142    is($pe->inblock_ch,  delete $pe->{inblock_ch},  'method inblock_ch');
143    is($pe->oublock_ch,  delete $pe->{oublock_ch},  'method oublock_ch');
144    is($pe->msgsnd_ch,   delete $pe->{msgsnd_ch},   'method msgsnd_ch');
145    is($pe->msgrcv_ch,   delete $pe->{msgrcv_ch},   'method msgrcv_ch');
146    is($pe->nsignals_ch, delete $pe->{nsignals_ch}, 'method nsignals_ch');
147    is($pe->nvcsw_ch,    delete $pe->{nvcsw_ch},    'method nvcsw_ch');
148    is($pe->nivcsw_ch,   delete $pe->{nivcsw_ch},   'method nivcsw_ch');
149    # check for typos in hv_store calls in Process.xs
150    is( scalar(grep {!/^_/} keys %$pe), 0, 'all methods have been accounted for' )
151        or diag( 'leftover: ' . join( ',', grep {!/^_/} keys %$pe ));
152
153    $pe->refresh;
154
155    # longhand method names
156    is($pe->process_pid,                   delete $pe->{pid},         'alias process_pid' );
157    is($pe->parent_pid,                    delete $pe->{ppid},        'alias parent_pid');
158    is($pe->process_group_id,              delete $pe->{pgid},        'alias process_group_id');
159    is($pe->tty_process_group_id,          delete $pe->{tpgid},       'alias tty_process_group_id');
160    is($pe->process_session_id,            delete $pe->{sid},         'alias tty_process_group_id');
161    is($pe->job_control_counter,           delete $pe->{jobc},        'alias job_control_counter');
162    is($pe->resident_set_size,             delete $pe->{rssize},      'alias resident_set_size');
163    is($pe->rssize_before_swap,            delete $pe->{swrss},       'alias rssize_before_swap');
164    is($pe->text_size,                     delete $pe->{tsize},       'alias text_size');
165    is($pe->exit_status,                   delete $pe->{xstat},       'alias exit_status');
166    is($pe->accounting_flags,              delete $pe->{acflag},      'alias accounting_flags');
167    is($pe->percent_cpu,                   delete $pe->{pctcpu},      'alias percent_cpu');
168    is($pe->estimated_cpu,                 delete $pe->{estcpu},      'alias estimated_cpu');
169    is($pe->sleep_time,                    delete $pe->{slptime},     'alias sleep_time');
170    is($pe->time_last_swap,                delete $pe->{swtime},      'alias time_last_swap');
171    is($pe->elapsed_time,                  delete $pe->{runtime},     'alias elapsed_time');
172    is($pe->process_flags,                 delete $pe->{flag},        'alias process_flags');
173    is($pe->nice_priority,                 delete $pe->{nice},        'alias nice_priority');
174    is($pe->process_lock_count,            delete $pe->{lock},        'alias process_lock_count');
175    is($pe->run_queue_index,               delete $pe->{rqindex},     'alias run_queue_index');
176    is($pe->current_cpu,                   delete $pe->{oncpu},       'alias current_cpu');
177    is($pe->last_cpu,                      delete $pe->{lastcpu},     'alias last_cpu');
178    is($pe->wchan_message,                 delete $pe->{wmesg},       'alias wchan_message');
179    is($pe->setlogin_name,                 delete $pe->{login},       'alias setlogin_name');
180    is($pe->command_name,                  delete $pe->{comm},        'alias command_name');
181
182    is($pe->process_args,                  delete $pe->{args},        'alias process_args' );
183    is($pe->terminal_session_id,           delete $pe->{tsid},        'alias terminal_session_id');
184    is($pe->effective_user_id,             delete $pe->{uid},         'alias effective_user_id');
185    is($pe->real_user_id,                  delete $pe->{ruid},        'alias real_user_id');
186    is($pe->saved_effective_user_id,       delete $pe->{svuid},       'alias saved_effective_user_id');
187    is($pe->real_group_id,                 delete $pe->{rgid},        'alias real_group_id');
188    is($pe->saved_effective_group_id,      delete $pe->{svgid},       'alias saved_effective_group_id');
189    is($pe->number_of_groups,              delete $pe->{ngroups},     'alias number_of_groups');
190    is($pe->virtual_size,                  delete $pe->{size},        'alias virtual_size');
191    is($pe->data_size,                     delete $pe->{dsize},       'alias data_size');
192    is($pe->stack_size,                    delete $pe->{ssize},       'alias stack_size');
193    is($pe->start_time,                    delete $pe->{start},       'alias start_time');
194    is($pe->children_time,                 delete $pe->{childtime},   'alias children_time');
195    is($pe->posix_advisory_lock,           delete $pe->{advlock},     'alias posix_advisory_lock');
196    is($pe->has_controlling_terminal,      delete $pe->{controlt},    'alias has_controlling_terminal');
197    is($pe->is_kernel_thread,              delete $pe->{kthread},     'alias is_kernel_thread');
198    is($pe->no_loadavg_calc,               delete $pe->{noload},      'alias no_loadavg_calc');
199    is($pe->parent_waiting,                delete $pe->{ppwait},      'alias parent_waiting');
200    is($pe->started_profiling,             delete $pe->{profil},      'alias started_profiling');
201    is($pe->stopped_profiling,             delete $pe->{stopprof},    'alias stopped_profiling');
202    is($pe->id_privs_set,                  delete $pe->{sugid},       'alias id_privs_set');
203    is($pe->system_process,                delete $pe->{system},      'alias system_process');
204    is($pe->single_exit_not_wait,          delete $pe->{single_exit}, 'alias single_exit_not_wait');
205    is($pe->traced_by_debugger,            delete $pe->{traced},      'alias traced_by_debugger');
206    is($pe->waited_on_by_other,            delete $pe->{waited},      'alias waited_on_by_other');
207    is($pe->working_on_exiting,            delete $pe->{wexit},       'alias working_on_exiting');
208    is($pe->process_called_exec,           delete $pe->{exec},        'alias process_called_exec');
209    is($pe->kernel_session_flag,           delete $pe->{kiflag},      'alias kernel_session_flag');
210    is($pe->is_locked,                     delete $pe->{locked},      'alias is_locked');
211    is($pe->controlling_tty_active,        delete $pe->{isctty},      'alias controlling_tty_active');
212    is($pe->is_session_leader,             delete $pe->{issleader},   'alias is_session_leader');
213    is($pe->process_status,                delete $pe->{stat},        'alias process_status');
214    is($pe->is_being_forked,               delete $pe->{stat_1},      'alias is_being_forked');
215    is($pe->is_runnable,                   delete $pe->{stat_2},      'alias is_runnable');
216    is($pe->is_sleeping_on_addr,           delete $pe->{stat_3},      'alias is_sleeping_on_addr');
217    is($pe->is_stopped,                    delete $pe->{stat_4},      'alias is_stopped');
218    is($pe->is_a_zombie,                   delete $pe->{stat_5},      'alias is_a_zombie');
219    is($pe->is_waiting_on_intr,            delete $pe->{stat_6},      'alias is_waiting_on_intr');
220    is($pe->is_blocked,                    delete $pe->{stat_7},      'alias is_blocked');
221    is($pe->old_command_name,              delete $pe->{ocomm},       'alias old_command_name');
222    is($pe->name_of_lock,                  delete $pe->{lockname},    'alias name_of_lock');
223    is($pe->priority_scheduling_class,     delete $pe->{pri_class},   'alias priority_scheduling_class');
224    is($pe->priority_level,                delete $pe->{pri_level},   'alias priority_level');
225    is($pe->priority_native,               delete $pe->{pri_native},  'alias priority_native');
226    is($pe->priority_user,                 delete $pe->{pri_user},    'alias priority_user');
227    is($pe->user_time,                     delete $pe->{utime},       'alias user_time');
228    is($pe->system_time,                   delete $pe->{stime},       'alias system_time');
229    is($pe->total_time,                    delete $pe->{time},        'alias total_time');
230    is($pe->max_resident_set_size,         delete $pe->{maxrss},      'alias max_resident_set_size');
231    is($pe->shared_memory_size,            delete $pe->{ixrss},       'alias shared_memory_size');
232    is($pe->unshared_data_size,            delete $pe->{idrss},       'alias unshared_data_size');
233    is($pe->unshared_stack_size,           delete $pe->{isrss},       'alias unshared_stack_size');
234    is($pe->page_reclaims,                 delete $pe->{minflt},      'alias page_reclaims');
235    is($pe->page_faults,                   delete $pe->{majflt},      'alias page_faults');
236    is($pe->number_of_swaps,               delete $pe->{nswap},       'alias number_of_swaps');
237    is($pe->block_input_ops,               delete $pe->{inblock},     'alias block_input_ops');
238    is($pe->block_output_ops,              delete $pe->{oublock},     'alias block_output_ops');
239    is($pe->messages_sent,                 delete $pe->{msgsnd},      'alias messages_sent');
240    is($pe->messages_received,             delete $pe->{msgrcv},      'alias messages_received');
241    is($pe->signals_received,              delete $pe->{nsignals},    'alias signals_received');
242    is($pe->voluntary_context_switch,      delete $pe->{nvcsw},       'alias voluntary_context_switch');
243    is($pe->involuntary_context_switch,    delete $pe->{nivcsw},      'alias involuntary_context_switch');
244    is($pe->process_had_threads,           delete $pe->{hadthreads},  'alias process_had_threads');
245    is($pe->emulation_name,                delete $pe->{emul},        'alias emulation_name');
246    is($pe->process_jail_id,               delete $pe->{jid},         'alias process_jail_id');
247    is($pe->number_of_threads,             delete $pe->{numthreads},  'alias number_of_threads');
248    is($pe->user_time_ch,                  delete $pe->{utime_ch},    'alias user_time');
249    is($pe->system_time_ch,                delete $pe->{stime_ch},    'alias system_time');
250    is($pe->total_time_ch,                 delete $pe->{time_ch},     'alias total_time');
251    is($pe->max_resident_set_size_ch,      delete $pe->{maxrss_ch},   'alias max_resident_set_size');
252    is($pe->shared_memory_size_ch,         delete $pe->{ixrss_ch},    'alias shared_memory_size');
253    is($pe->unshared_data_size_ch,         delete $pe->{idrss_ch},    'alias unshared_data_size');
254    is($pe->unshared_stack_size_ch,        delete $pe->{isrss_ch},    'alias unshared_stack_size');
255    is($pe->page_reclaims_ch,              delete $pe->{minflt_ch},   'alias page_reclaims');
256    is($pe->page_faults_ch,                delete $pe->{majflt_ch},   'alias page_faults');
257    is($pe->number_of_swaps_ch,            delete $pe->{nswap_ch},    'alias number_of_swaps');
258    is($pe->block_input_ops_ch,            delete $pe->{inblock_ch},  'alias block_input_ops');
259    is($pe->block_output_ops_ch,           delete $pe->{oublock_ch},  'alias block_output_ops');
260    is($pe->messages_sent_ch,              delete $pe->{msgsnd_ch},   'alias messages_sent');
261    is($pe->messages_received_ch,          delete $pe->{msgrcv_ch},   'alias messages_received');
262    is($pe->signals_received_ch,           delete $pe->{nsignals_ch}, 'alias signals_received');
263    is($pe->voluntary_context_switch_ch,   delete $pe->{nvcsw_ch},    'alias voluntary_context_switch');
264    is($pe->involuntary_context_switch_ch, delete $pe->{nivcsw_ch},   'alias involuntary_context_switch');
265
266    $grouplist = $pe->group_list;
267    delete $pe->{groups};
268    SKIP: {
269        skip( "not supported on FreeBSD 4.x", 3 )
270            if $RUNNING_ON_FREEBSD_4;
271        ok( defined($grouplist), 'alias group_list' );
272        is( ref($grouplist), 'ARRAY', q{... it's also a list} );
273        SKIP: {
274            skip( "didn't get an ARRAY in previous test", 1 )
275                unless ref($grouplist);
276            is( scalar(@$grouplist), $ngroups, "... also of the expected size" )
277                or diag("grouplist = (@$grouplist)");
278        }
279    }
280
281    # check for typos in hv_store calls in Process.xs
282    is( scalar(grep {!/^_/} keys %$pe), 0, 'all aliases have been accounted for' )
283        or diag( 'leftover: ' . join( ',', grep {!/^_/} keys %$pe ));
284
285    my $time = $pi->runtime;
286    cmp_ok( $pi->refresh->runtime, '>', $time, 'refresh updates counters' );
287
288    $pe->refresh;
289    for my $method (sort {$a cmp $b} BSD::Process::attr_alias) {
290        ok($pe->can($method), "can $method");
291    }
292}
293
294{
295    # check symbolic uids and gids
296    my $num = BSD::Process->new();
297    my $sym_imp = BSD::Process->new(     {resolve => 1} );
298    my $sym_exp = BSD::Process->new( $$, {resolve => 1} );
299
300    my $num_grouplist = $num->groups;
301    my $sym_grouplist = $sym_imp->group_list;
302
303    SKIP: {
304        skip( "not supported on FreeBSD 4.x", 13 )
305            if $RUNNING_ON_FREEBSD_4;
306        is( $num->uid,   scalar(getpwnam($sym_imp->uid)),   'implicit pid resolve muid' );
307        is( $num->ruid,  scalar(getpwnam($sym_imp->ruid)),  'implicit pid resolve ruid' );
308        is( $num->svuid, scalar(getpwnam($sym_imp->svuid)), 'implicit pid resolve svuid' );
309        is( $num->rgid,  scalar(getgrnam($sym_imp->rgid)),  'implicit pid resolve rgid' );
310        is( $num->svgid, scalar(getgrnam($sym_imp->svgid)), 'implicit pid resolve svgid' );
311
312        is( $num->uid,   scalar(getpwnam($sym_exp->uid)),   'explicit pid resolve uid' );
313        is( $num->ruid,  scalar(getpwnam($sym_exp->ruid)),  'explicit pid resolve ruid' );
314        is( $num->svuid, scalar(getpwnam($sym_exp->svuid)), 'explicit pid resolve svuid' );
315        is( $num->rgid,  scalar(getgrnam($sym_exp->rgid)),  'explicit pid resolve rgid' );
316        is( $num->svgid, scalar(getgrnam($sym_exp->svgid)), 'explicit pid resolve svgid' );
317
318        is( ref($num_grouplist), 'ARRAY', 'numeric grouplist is an ARRAY' );
319        is( ref($sym_grouplist), 'ARRAY', 'symbolic grouplist is an ARRAY' );
320
321        is( scalar(@$num_grouplist), scalar(@$sym_grouplist), 'groups counts' );
322    }
323
324    for my $gid (0..BSD::Process::max_kernel_groups) {
325        if ($gid < @$num_grouplist) {
326            is( $num_grouplist->[$gid],  scalar(getgrnam($sym_grouplist->[$gid])), "resolve group $gid" );
327        }
328        else {
329            pass( "resolve group $gid (none on this platform)" );
330        }
331    }
332}
333