1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
|
# Copyright (C) 2009-2016 by the Free Software Foundation, Inc.
#
# This file is part of GNU Mailman.
#
# GNU Mailman is free software: you can redistribute it and/or modify it under
# the terms of the GNU General Public License as published by the Free
# Software Foundation, either version 3 of the License, or (at your option)
# any later version.
#
# GNU Mailman 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 General Public License for
# more details.
#
# You should have received a copy of the GNU General Public License along with
# GNU Mailman. If not, see <http://www.gnu.org/licenses/>.
"""Test configuration file searching."""
__all__ = [
'TestConfigFileBase',
'TestConfigFileSearch',
'TestConfigFileSearchWithChroot',
]
import os
import sys
import shutil
import tempfile
import unittest
from contextlib import contextmanager
from mailman.core.initialize import search_for_configuration_file
# Here are a couple of context managers that make our tests easier to read.
@contextmanager
def fakedirs(path):
"""Create and clean up a directory hierarchy."""
os.makedirs(path)
try:
yield
finally:
shutil.rmtree(path)
@contextmanager
def hackenv(envar, new_value):
"""Hack the environment temporarily, then reset it."""
old_value = os.getenv(envar)
os.environ[envar] = new_value
try:
yield
finally:
if old_value is None:
del os.environ[envar]
else:
os.environ[envar] = old_value
@contextmanager
def chdir(new_cwd):
"""Change to the directory, then back again."""
old_cwd = os.getcwd()
os.chdir(new_cwd)
try:
yield
finally:
os.chdir(old_cwd)
@contextmanager
def argv0(new_argv0):
"""Change argv0, then back again."""
old_argv0 = sys.argv[0]
sys.argv[0] = new_argv0
try:
yield
finally:
sys.argv[0] = old_argv0
class TestConfigFileBase(unittest.TestCase):
"""Common test infrastructure."""
def setUp(self):
self._root = tempfile.mkdtemp()
# Ensure that the environment can't cause test failures.
self.mailman_config_file = os.environ.get('MAILMAN_CONFIG_FILE')
if self.mailman_config_file is not None:
del os.environ['MAILMAN_CONFIG_FILE']
def tearDown(self):
shutil.rmtree(self._root)
# Restore the environment, though I'm not actually sure this is
# necessary.
if self.mailman_config_file is not None:
os.environ['MAILMAN_CONFIG_FILE'] = self.mailman_config_file
def _make_fake(self, path):
if path.startswith('/'):
path = path[1:]
return os.path.join(self._root, path)
class TestConfigFileSearch(TestConfigFileBase):
"""Test various aspects of searching for configuration files.
Note that the command line -C option is not tested here.
"""
def test_current_working_directory(self):
fake_cwd = '/home/alex/mailman/hacking'
fake_testdir = self._make_fake(fake_cwd)
config_file = os.path.realpath(
os.path.join(fake_testdir, 'mailman.cfg'))
with fakedirs(fake_testdir):
# Write a mostly empty configuration file.
with open(os.path.join(fake_testdir, 'mailman.cfg'), 'w') as fp:
print('# Fake mailman.cfg file', file=fp)
with chdir(fake_testdir):
# Sometimes symlinks bite us (eg. OS X /var -> /private/var).
found = os.path.realpath(search_for_configuration_file())
self.assertEqual(found, config_file)
class TestConfigFileSearchWithChroot(TestConfigFileBase):
"""Like `TestConfigFileSearch` but with a special os.path.exists()."""
def setUp(self):
TestConfigFileBase.setUp(self)
# We can't actually call os.chroot() unless we're root. Neither can
# we write to say /etc/mailman.cfg without being root (of course we
# wouldn't want to even if we could). The easiest way to fake a file
# system that we can write to and test is to hack os.path.exists() to
# prepend a temporary directory onto the path it tests.
self._os_path_exists = os.path.exists
def exists(path):
# Strip off the leading slash, otherwise we'll end up with path.
return self._os_path_exists(self._make_fake(path))
os.path.exists = exists
def tearDown(self):
os.path.exists = self._os_path_exists
TestConfigFileBase.tearDown(self)
def test_baseline(self):
# With nothing set, and no configuration files, just return None.
self.assertEqual(search_for_configuration_file(), None)
def test_environment_variable_to_missing_path(self):
# Test that $MAILMAN_CONFIG_FILE pointing to a non-existent path still
# returns None.
with hackenv('MAILMAN_CONFIG_FILE', '/does/not/exist'):
self.assertEqual(search_for_configuration_file(), None)
def test_environment_variable(self):
# Test that $MAILMAN_CONFIG_FILE pointing to an existing path returns
# that path.
fake_home = '/home/geddy/testing/mailman'
fake_testdir = self._make_fake(fake_home)
config_file = os.path.join(fake_home, 'mailman.cfg')
with fakedirs(fake_testdir):
# Write a mostly empty configuration file.
with open(os.path.join(fake_testdir, 'mailman.cfg'), 'w') as fp:
print('# Fake mailman.cfg file', file=fp)
with hackenv('MAILMAN_CONFIG_FILE', config_file):
self.assertEqual(search_for_configuration_file(), config_file)
def test_home_dot_file(self):
# Test ~/.mailman.cfg
fake_home = '/home/neil'
fake_testdir = self._make_fake(fake_home)
config_file = os.path.join(fake_home, '.mailman.cfg')
with fakedirs(fake_testdir):
# Write a mostly empty configuration file.
with open(os.path.join(fake_testdir, '.mailman.cfg'), 'w') as fp:
print('# Fake mailman.cfg file', file=fp)
with hackenv('HOME', '/home/neil'):
self.assertEqual(search_for_configuration_file(), config_file)
def test_etc_file(self):
# Test /etc/mailman.cfg
fake_etc = '/etc'
fake_testdir = self._make_fake(fake_etc)
config_file = os.path.join(fake_etc, 'mailman.cfg')
with fakedirs(fake_testdir):
# Write a mostly empty configuration file.
with open(os.path.join(fake_testdir, 'mailman.cfg'), 'w') as fp:
print('# Fake mailman.cfg file', file=fp)
self.assertEqual(search_for_configuration_file(), config_file)
def test_sibling_directory(self):
# Test $argv0/../../etc/mailman.cfg
fake_root = '/usr/local/mm3'
fake_testdir = self._make_fake(fake_root)
config_file = os.path.join(fake_testdir, 'etc', 'mailman.cfg')
fake_config_file = os.path.join(fake_root, 'etc', 'mailman.cfg')
fake_argv0 = os.path.join(fake_root, 'bin', 'mailman')
with fakedirs(fake_testdir):
with argv0(fake_argv0):
os.mkdir(os.path.dirname(config_file))
# Write a mostly empty configuration file.
with open(config_file, 'w') as fp:
print('# Fake mailman.cfg file', file=fp)
self.assertEqual(search_for_configuration_file(),
fake_config_file)
|