Skip to content

Commit 3a70510

Browse files
phlogistonjohnmergify[bot]
authored andcommitted
tests: add unit tests for smbconf_samba
Add unit(ish) tests for smbconf_samba. We have to work around an (IMO) annoying behavior of samba's. When using the registry backend once the registry tdb file is opened it is never closed and subsequent calls to smbconf's init_reg or similar end up reusing whatever first tdb file got opened. (I looked at samba master code, this is still the case AFAICT.) So we do a bit of hackery with regards to test fixtures to get a "clean" SMBConf for each test. This shouldn't be much of an issue outside of tests as you typically only have one smb.conf and/or one data dir with a registry.tdb in it. Signed-off-by: John Mulligan <[email protected]>
1 parent 62741c9 commit 3a70510

File tree

1 file changed

+188
-0
lines changed

1 file changed

+188
-0
lines changed

tests/test_smbconf_samba.py

Lines changed: 188 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,188 @@
1+
#
2+
# sambacc: a samba container configuration tool
3+
# Copyright (C) 2023 John Mulligan
4+
#
5+
# This program is free software: you can redistribute it and/or modify
6+
# it under the terms of the GNU General Public License as published by
7+
# the Free Software Foundation, either version 3 of the License, or
8+
# (at your option) any later version.
9+
#
10+
# This program is distributed in the hope that it will be useful,
11+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
12+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13+
# GNU General Public License for more details.
14+
#
15+
# You should have received a copy of the GNU General Public License
16+
# along with this program. If not, see <http://www.gnu.org/licenses/>
17+
#
18+
19+
import pytest
20+
21+
import sambacc.smbconf_api
22+
import sambacc.smbconf_samba
23+
24+
smb_conf_reg_stub = """
25+
[global]
26+
cache directory = {path}
27+
state directory = {path}
28+
private dir = {path}
29+
include = registry
30+
"""
31+
32+
smb_conf_sample = """
33+
[global]
34+
realm = my.kingdom.fora.horse
35+
36+
[share_a]
37+
path = /foo/bar/baz
38+
read only = no
39+
[share_b]
40+
path = /foo/x/b
41+
read only = no
42+
[share_c]
43+
path = /foo/x/c
44+
read only = no
45+
[share_d]
46+
path = /foo/x/d
47+
read only = no
48+
[share_e]
49+
path = /foo/x/e
50+
read only = no
51+
"""
52+
53+
54+
def _import_probe():
55+
try:
56+
import samba.smbconf # type: ignore
57+
import samba.samba3.smbconf # type: ignore # noqa
58+
except ImportError:
59+
pytest.skip("unable to load samba smbconf modules")
60+
61+
62+
def _smb_data(path, smb_conf_text):
63+
data_path = path / "_samba"
64+
data_path.mkdir()
65+
smb_conf_path = path / "smb.conf"
66+
smb_conf_path.write_text(smb_conf_text.format(path=data_path))
67+
return smb_conf_path
68+
69+
70+
@pytest.fixture(scope="session")
71+
def smbconf_reg_once(tmp_path_factory):
72+
_import_probe()
73+
tmp_path = tmp_path_factory.mktemp("smb_reg")
74+
smb_conf_path = _smb_data(tmp_path, smb_conf_reg_stub)
75+
76+
return sambacc.smbconf_samba.SMBConf.from_registry(str(smb_conf_path))
77+
78+
79+
@pytest.fixture(scope="function")
80+
def smbconf_reg(smbconf_reg_once):
81+
# IMPORTANT: Reminder, samba doesn't release the registry db once opened.
82+
smbconf_reg_once._smbconf.drop()
83+
return smbconf_reg_once
84+
85+
86+
@pytest.fixture(scope="function")
87+
def smbconf_file(tmp_path):
88+
_import_probe()
89+
smb_conf_path = _smb_data(tmp_path, smb_conf_sample)
90+
91+
return sambacc.smbconf_samba.SMBConf.from_file(str(smb_conf_path))
92+
93+
94+
def test_smbconf_file_read(smbconf_file):
95+
assert smbconf_file["global"] == [("realm", "my.kingdom.fora.horse")]
96+
assert smbconf_file["share_a"] == [
97+
("path", "/foo/bar/baz"),
98+
("read only", "no"),
99+
]
100+
with pytest.raises(KeyError):
101+
smbconf_file["not_there"]
102+
assert list(smbconf_file) == [
103+
"global",
104+
"share_a",
105+
"share_b",
106+
"share_c",
107+
"share_d",
108+
"share_e",
109+
]
110+
111+
112+
def test_smbconf_write(smbconf_file):
113+
assert not smbconf_file.writeable
114+
with pytest.raises(Exception):
115+
smbconf_file.import_smbconf(sambacc.smbconf_api.SimpleConfigStore())
116+
117+
118+
def test_smbconf_reg_write_read(smbconf_reg):
119+
assert smbconf_reg.writeable
120+
assert list(smbconf_reg) == []
121+
smbconf_reg["global"] = [("test:one", "1"), ("test:two", "2")]
122+
assert smbconf_reg["global"] == [("test:one", "1"), ("test:two", "2")]
123+
smbconf_reg["global"] = [("test:one", "1"), ("test:two", "22")]
124+
assert smbconf_reg["global"] == [("test:one", "1"), ("test:two", "22")]
125+
126+
127+
def test_smbconf_reg_write_txn_read(smbconf_reg):
128+
assert smbconf_reg.writeable
129+
assert list(smbconf_reg) == []
130+
with smbconf_reg:
131+
smbconf_reg["global"] = [("test:one", "1"), ("test:two", "2")]
132+
assert smbconf_reg["global"] == [("test:one", "1"), ("test:two", "2")]
133+
with smbconf_reg:
134+
smbconf_reg["global"] = [("test:one", "1"), ("test:two", "22")]
135+
assert smbconf_reg["global"] == [("test:one", "1"), ("test:two", "22")]
136+
137+
# transaction with error
138+
with pytest.raises(ValueError):
139+
with smbconf_reg:
140+
smbconf_reg["global"] = [("test:one", "1"), ("test:two", "2222")]
141+
raise ValueError("foo")
142+
assert smbconf_reg["global"] == [("test:one", "1"), ("test:two", "22")]
143+
144+
# no transaction with error
145+
with pytest.raises(ValueError):
146+
smbconf_reg["global"] = [("test:one", "1"), ("test:two", "2222")]
147+
raise ValueError("foo")
148+
assert smbconf_reg["global"] == [("test:one", "1"), ("test:two", "2222")]
149+
150+
151+
def test_smbconf_reg_import_batched(smbconf_reg, smbconf_file):
152+
assert list(smbconf_reg) == []
153+
smbconf_reg.import_smbconf(smbconf_file, batch_size=4)
154+
assert smbconf_reg["global"] == [("realm", "my.kingdom.fora.horse")]
155+
assert smbconf_reg["share_a"] == [
156+
("path", "/foo/bar/baz"),
157+
("read only", "no"),
158+
]
159+
with pytest.raises(KeyError):
160+
smbconf_reg["not_there"]
161+
assert list(smbconf_reg) == [
162+
"global",
163+
"share_a",
164+
"share_b",
165+
"share_c",
166+
"share_d",
167+
"share_e",
168+
]
169+
170+
171+
def test_smbconf_reg_import_unbatched(smbconf_reg, smbconf_file):
172+
assert list(smbconf_reg) == []
173+
smbconf_reg.import_smbconf(smbconf_file, batch_size=None)
174+
assert smbconf_reg["global"] == [("realm", "my.kingdom.fora.horse")]
175+
assert smbconf_reg["share_a"] == [
176+
("path", "/foo/bar/baz"),
177+
("read only", "no"),
178+
]
179+
with pytest.raises(KeyError):
180+
smbconf_reg["not_there"]
181+
assert list(smbconf_reg) == [
182+
"global",
183+
"share_a",
184+
"share_b",
185+
"share_c",
186+
"share_d",
187+
"share_e",
188+
]

0 commit comments

Comments
 (0)