1package ProFTPD::Tests::Config::MaxInstances;
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 :running :test :testsuite);
12
13$| = 1;
14
15my $order = 0;
16
17my $TESTS = {
18  maxinstances_one => {
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 maxinstances_one {
34  my $self = shift;
35  my $tmpdir = $self->{tmpdir};
36
37  my $config_file = "$tmpdir/config.conf";
38  my $pid_file = File::Spec->rel2abs("$tmpdir/config.pid");
39  my $scoreboard_file = File::Spec->rel2abs("$tmpdir/config.scoreboard");
40
41  my $log_file = File::Spec->rel2abs('tests.log');
42
43  my $auth_user_file = File::Spec->rel2abs("$tmpdir/config.passwd");
44  my $auth_group_file = File::Spec->rel2abs("$tmpdir/config.group");
45
46  my $user = 'proftpd';
47  my $passwd = 'test';
48  my $home_dir = File::Spec->rel2abs($tmpdir);
49
50  auth_user_write($auth_user_file, $user, $passwd, 500, 500, $home_dir,
51    '/bin/bash');
52  auth_group_write($auth_group_file, 'ftpd', 500, $user);
53
54  my $max_instances = 1;
55
56  my $config = {
57    PidFile => $pid_file,
58    ScoreboardFile => $scoreboard_file,
59    SystemLog => $log_file,
60
61    AuthUserFile => $auth_user_file,
62    AuthGroupFile => $auth_group_file,
63
64    MaxInstances => $max_instances,
65
66    IfModules => {
67      'mod_delay.c' => {
68        DelayEngine => 'off',
69      },
70    },
71  };
72
73  my ($port, $config_user, $config_group) = config_write($config_file, $config);
74
75  # Open pipes, for use between the parent and child processes.  Specifically,
76  # the child will indicate when it's done with its test by writing a message
77  # to the parent.
78  my ($rfh, $wfh);
79  unless (pipe($rfh, $wfh)) {
80    die("Can't open pipe: $!");
81  }
82
83  my $ex;
84
85  # Fork child
86  $self->handle_sigchld();
87  defined(my $pid = fork()) or die("Can't fork: $!");
88  if ($pid) {
89    eval {
90      # First client should be able to connect and log in...
91      my $client1 = ProFTPD::TestSuite::FTP->new('127.0.0.1', $port);
92      $client1->login($user, $passwd);
93
94      # ...but the second client should not be able to connect.
95      eval { my $client2 = ProFTPD::TestSuite::FTP->new('127.0.0.1', $port,
96        undef, 1) };
97      unless ($@) {
98        die("Connect succeeded unexpectedly");
99      }
100
101      $client1->quit();
102    };
103
104    if ($@) {
105      $ex = $@;
106    }
107
108    $wfh->print("done\n");
109    $wfh->flush();
110
111  } else {
112    eval { server_wait($config_file, $rfh) };
113    if ($@) {
114      warn($@);
115      exit 1;
116    }
117
118    exit 0;
119  }
120
121  # Stop server
122  server_stop($pid_file);
123
124  $self->assert_child_ok($pid);
125
126  if ($ex) {
127    die($ex);
128  }
129
130  unlink($log_file);
131}
132
1331;
134