1package ProFTPD::Tests::Commands::HELP;
2
3use lib qw(t/lib);
4use base qw(ProFTPD::TestSuite::Child);
5use strict;
6
7use File::Spec;
8use IO::Handle;
9
10use ProFTPD::TestSuite::FTP;
11use ProFTPD::TestSuite::Utils qw(:auth :config :features :running :test :testsuite);
12
13$| = 1;
14
15my $order = 0;
16
17my $TESTS = {
18  help_ok => {
19    order => ++$order,
20    test_class => [qw(forking)],
21  },
22
23};
24
25sub new {
26  return shift()->SUPER::new(@_);
27}
28
29sub list_tests {
30  return testsuite_get_runnable_tests($TESTS);
31}
32
33sub help_ok {
34  my $self = shift;
35  my $tmpdir = $self->{tmpdir};
36
37  my $config_file = "$tmpdir/cmds.conf";
38  my $pid_file = File::Spec->rel2abs("$tmpdir/cmds.pid");
39  my $scoreboard_file = File::Spec->rel2abs("$tmpdir/cmds.scoreboard");
40
41  my $log_file = test_get_logfile();
42
43  my $auth_user_file = File::Spec->rel2abs("$tmpdir/cmds.passwd");
44  my $auth_group_file = File::Spec->rel2abs("$tmpdir/cmds.group");
45
46  my $user = 'proftpd';
47  my $passwd = 'test';
48  my $group = 'ftpd';
49  my $home_dir = File::Spec->rel2abs($tmpdir);
50  my $uid = 500;
51  my $gid = 500;
52
53  # Make sure that, if we're running as root, that the home directory has
54  # permissions/privs set for the account we create
55  if ($< == 0) {
56    unless (chmod(0755, $home_dir)) {
57      die("Can't set perms on $home_dir to 0755: $!");
58    }
59
60    unless (chown($uid, $gid, $home_dir)) {
61      die("Can't set owner of $home_dir to $uid/$gid: $!");
62    }
63  }
64
65  auth_user_write($auth_user_file, $user, $passwd, $uid, $gid, $home_dir,
66    '/bin/bash');
67  auth_group_write($auth_group_file, $group, $gid, $user);
68
69  my $config = {
70    PidFile => $pid_file,
71    ScoreboardFile => $scoreboard_file,
72    SystemLog => $log_file,
73
74    AuthUserFile => $auth_user_file,
75    AuthGroupFile => $auth_group_file,
76
77    IfModules => {
78      'mod_delay.c' => {
79        DelayEngine => 'off',
80      },
81    },
82  };
83
84  my ($port, $config_user, $config_group) = config_write($config_file, $config);
85
86  my $auth_helps = [
87    ' NOOP    FEAT    OPTS    AUTH*   CCC*    CONF*   ENC*    MIC*    ',
88    ' PBSZ*   PROT*   TYPE    STRU    MODE    RETR    STOR    STOU    ',
89  ];
90
91  # Open pipes, for use between the parent and child processes.  Specifically,
92  # the child will indicate when it's done with its test by writing a message
93  # to the parent.
94  my ($rfh, $wfh);
95  unless (pipe($rfh, $wfh)) {
96    die("Can't open pipe: $!");
97  }
98
99  my $ex;
100
101  # Fork child
102  $self->handle_sigchld();
103  defined(my $pid = fork()) or die("Can't fork: $!");
104  if ($pid) {
105    eval {
106      my $client = ProFTPD::TestSuite::FTP->new('127.0.0.1', $port);
107
108      $client->help();
109      my $resp_code = $client->response_code();
110      my $resp_msgs = $client->response_msgs();
111
112      my $expected;
113
114      $expected = 214;
115      $self->assert($expected == $resp_code,
116        test_msg("Expected $expected, got $resp_code"));
117
118      $expected = 9;
119      my $nhelp = scalar(@$resp_msgs);
120      $self->assert($expected == $nhelp,
121        test_msg("Expected $expected, got $nhelp"));
122
123      my $helps = [(
124        'The following commands are recognized (* =>\'s unimplemented):',
125        ' CWD     XCWD    CDUP    XCUP    SMNT*   QUIT    PORT    PASV    ',
126        ' EPRT    EPSV    ALLO*   RNFR    RNTO    DELE    MDTM    RMD     ',
127        ' XRMD    MKD     XMKD    PWD     XPWD    SIZE    SYST    HELP    ',
128        @$auth_helps,
129        ' APPE    REST    ABOR    USER    PASS    ACCT*   REIN*   LIST    ',
130        ' NLST    STAT    SITE    MLSD    MLST    ',
131        'Direct comments to root@127.0.0.1',
132      )];
133
134      for (my $i = 0; $i < $nhelp; $i++) {
135        $expected = $helps->[$i];
136        $self->assert($expected eq $resp_msgs->[$i],
137          test_msg("Expected '$expected', got '$resp_msgs->[$i]'"));
138      }
139    };
140
141    if ($@) {
142      $ex = $@;
143    }
144
145    $wfh->print("done\n");
146    $wfh->flush();
147
148  } else {
149    eval { server_wait($config_file, $rfh) };
150    if ($@) {
151      warn($@);
152      exit 1;
153    }
154
155    exit 0;
156  }
157
158  # Stop server
159  server_stop($pid_file);
160
161  $self->assert_child_ok($pid);
162
163  if ($ex) {
164    test_append_logfile($log_file, $ex);
165    unlink($log_file);
166
167    die($ex);
168  }
169
170  unlink($log_file);
171}
172
1731;
174