28
29
from itertools import takewhile
32
from gi.repository import Click
34
from gi.repository import Click, GLib
34
36
from click.json_helpers import json_array_to_python, json_object_to_python
35
37
from click.tests.gimock_types import Passwd
36
38
from click.tests.helpers import TestCase, mkfile, touch
41
class TestClickInstalledPackage(TestCase):
43
super(TestClickInstalledPackage, self).setUp()
44
self.foo = Click.InstalledPackage.new(
45
"foo", "1.0", "/path/to/foo/1.0", False)
46
self.foo_clone = Click.InstalledPackage.new(
47
"foo", "1.0", "/path/to/foo/1.0", False)
48
self.foo_different_version = Click.InstalledPackage.new(
49
"foo", "2.0", "/path/to/foo/1.0", False)
50
self.foo_different_path = Click.InstalledPackage.new(
51
"foo", "1.0", "/path/to/foo/2.0", False)
52
self.foo_different_writeable = Click.InstalledPackage.new(
53
"foo", "1.0", "/path/to/foo/1.0", True)
54
self.bar = Click.InstalledPackage.new(
55
"bar", "1.0", "/path/to/foo/1.0", False)
58
self.assertIsInstance(self.foo.hash(), int)
59
self.assertEqual(self.foo.hash(), self.foo_clone.hash())
60
self.assertNotEqual(self.foo.hash(), self.foo_different_version.hash())
61
self.assertNotEqual(self.foo.hash(), self.foo_different_path.hash())
63
self.foo.hash(), self.foo_different_writeable.hash())
64
self.assertNotEqual(self.foo.hash(), self.bar.hash())
66
# GLib doesn't allow passing an InstalledPackage as an argument here.
67
@unittest.expectedFailure
68
def test_equal_to(self):
69
self.assertTrue(self.foo.equal_to(self.foo_clone))
70
self.assertFalse(self.foo.equal_to(self.foo_different_version))
71
self.assertFalse(self.foo.equal_to(self.foo_different_path))
72
self.assertFalse(self.foo.equal_to(self.foo_different_writeable))
73
self.assertFalse(self.foo.equal_to(self.bar))
39
76
class TestClickSingleDB(TestCase):
41
78
super(TestClickSingleDB, self).setUp()
66
103
self.assertRaisesDatabaseError(
67
104
Click.DatabaseError.DOES_NOT_EXIST, self.db.get_path, "a", "1.1")
106
def test_has_package_version(self):
107
os.makedirs(os.path.join(self.temp_dir, "a", "1.0"))
108
self.assertTrue(self.db.has_package_version("a", "1.0"))
109
self.assertFalse(self.db.has_package_version("a", "1.1"))
69
111
def test_packages_current(self):
70
112
os.makedirs(os.path.join(self.temp_dir, "a", "1.0"))
71
113
os.makedirs(os.path.join(self.temp_dir, "a", "1.1"))
107
149
def test_manifest(self):
108
150
manifest_path = os.path.join(
109
151
self.temp_dir, "a", "1.0", ".click", "info", "a.manifest")
110
manifest_obj = {"name": "a", "version": "1.0", "hooks": {"a-app": {}}}
153
"name": "a", "version": "1.0", "hooks": {"a-app": {}},
154
"_should_be_removed": "",
111
156
with mkfile(manifest_path) as manifest:
112
157
json.dump(manifest_obj, manifest)
158
del manifest_obj["_should_be_removed"]
113
159
manifest_obj["_directory"] = os.path.join(self.temp_dir, "a", "1.0")
114
160
self.assertEqual(
124
170
Click.DatabaseError.DOES_NOT_EXIST,
125
171
self.db.get_manifest_as_string, "a", "1.1")
173
def test_manifest_bad(self):
174
manifest_path = os.path.join(
175
self.temp_dir, "a", "1.0", ".click", "info", "a.manifest")
176
with mkfile(manifest_path) as manifest:
177
print("{bad syntax", file=manifest)
178
self.assertRaisesDatabaseError(
179
Click.DatabaseError.BAD_MANIFEST, self.db.get_manifest, "a", "1.0")
180
self.assertRaisesDatabaseError(
181
Click.DatabaseError.BAD_MANIFEST,
182
self.db.get_manifest_as_string, "a", "1.0")
183
manifest_path = os.path.join(
184
self.temp_dir, "a", "1.1", ".click", "info", "a.manifest")
185
with mkfile(manifest_path) as manifest:
186
print("[0]", file=manifest)
187
self.assertRaisesDatabaseError(
188
Click.DatabaseError.BAD_MANIFEST, self.db.get_manifest, "a", "1.1")
189
self.assertRaisesDatabaseError(
190
Click.DatabaseError.BAD_MANIFEST,
191
self.db.get_manifest_as_string, "a", "1.1")
127
193
def test_app_running(self):
128
194
with self.run_in_subprocess(
129
195
"click_find_on_path", "g_spawn_sync",
193
259
self.g_spawn_sync_side_effect, {b"ubuntu-app-pid": 0})
194
260
self.assertFalse(self.db.any_app_running("a", "1.0"))
262
def test_any_app_running_missing_app(self):
263
with self.run_in_subprocess("click_find_on_path") as (enter, preloads):
265
preloads["click_find_on_path"].side_effect = (
266
lambda command: command == b"ubuntu-app-pid")
267
self.assertRaisesDatabaseError(
268
Click.DatabaseError.DOES_NOT_EXIST,
269
self.db.any_app_running, "a", "1.0")
271
def test_any_app_running_bad_manifest(self):
272
with self.run_in_subprocess(
273
"click_find_on_path", "g_spawn_sync",
274
) as (enter, preloads):
276
manifest_path = os.path.join(
277
self.temp_dir, "a", "1.0", ".click", "info", "a.manifest")
278
with mkfile(manifest_path) as manifest:
279
print("{bad syntax", file=manifest)
280
preloads["click_find_on_path"].side_effect = (
281
lambda command: command == b"ubuntu-app-pid")
282
self.assertFalse(self.db.any_app_running("a", "1.0"))
283
self.assertFalse(preloads["g_spawn_sync"].called)
285
def test_any_app_running_no_hooks(self):
286
with self.run_in_subprocess(
287
"click_find_on_path", "g_spawn_sync",
288
) as (enter, preloads):
290
manifest_path = os.path.join(
291
self.temp_dir, "a", "1.0", ".click", "info", "a.manifest")
292
with mkfile(manifest_path) as manifest:
293
json.dump({}, manifest)
294
preloads["click_find_on_path"].side_effect = (
295
lambda command: command == b"ubuntu-app-pid")
296
self.assertFalse(self.db.any_app_running("a", "1.0"))
297
self.assertFalse(preloads["g_spawn_sync"].called)
196
299
def test_maybe_remove_registered(self):
197
300
with self.run_in_subprocess(
198
301
"click_find_on_path", "g_spawn_sync",
263
366
def test_gc(self):
264
367
with self.run_in_subprocess(
265
"click_find_on_path", "g_spawn_sync",
368
"click_find_on_path", "g_spawn_sync", "getpwnam"
266
369
) as (enter, preloads):
371
preloads["getpwnam"].side_effect = (
372
lambda name: self.make_pointer(Passwd(pw_uid=1, pw_gid=1)))
268
373
os.environ["TEST_QUIET"] = "1"
269
374
a_path = os.path.join(self.temp_dir, "a", "1.0")
270
375
a_manifest_path = os.path.join(
298
403
self.assertTrue(os.path.exists(c_path))
300
405
def test_gc_ignores_non_directory(self):
301
a_path = os.path.join(self.temp_dir, "a", "1.0")
302
a_manifest_path = os.path.join(
303
a_path, ".click", "info", "a.manifest")
304
with mkfile(a_manifest_path) as manifest:
305
json.dump({"hooks": {"a-app": {}}}, manifest)
306
a_user_path = os.path.join(
307
self.temp_dir, ".click", "users", "test-user", "a")
308
os.makedirs(os.path.dirname(a_user_path))
309
os.symlink(a_path, a_user_path)
310
touch(os.path.join(self.temp_dir, "file"))
312
self.assertTrue(os.path.exists(a_path))
406
with self.run_in_subprocess(
408
) as (enter, preloads):
410
preloads["getpwnam"].side_effect = (
411
lambda name: self.make_pointer(Passwd(pw_uid=1, pw_gid=1)))
412
a_path = os.path.join(self.temp_dir, "a", "1.0")
413
a_manifest_path = os.path.join(
414
a_path, ".click", "info", "a.manifest")
415
with mkfile(a_manifest_path) as manifest:
416
json.dump({"hooks": {"a-app": {}}}, manifest)
417
a_user_path = os.path.join(
418
self.temp_dir, ".click", "users", "test-user", "a")
419
os.makedirs(os.path.dirname(a_user_path))
420
os.symlink(a_path, a_user_path)
421
touch(os.path.join(self.temp_dir, "file"))
423
self.assertTrue(os.path.exists(a_path))
314
425
def _make_ownership_test(self):
315
426
path = os.path.join(self.temp_dir, "a", "1.0")
397
508
set(args[0][1:] for args in preloads["chown"].call_args_list))
510
def test_ensure_ownership_missing_clickpkg_user(self):
511
with self.run_in_subprocess("getpwnam") as (enter, preloads):
513
preloads["getpwnam"].return_value = None
514
self.assertRaisesDatabaseError(
515
Click.DatabaseError.ENSURE_OWNERSHIP, self.db.ensure_ownership)
517
def test_ensure_ownership_failed_chown(self):
518
def stat_side_effect(name, limit, ver, path, buf):
519
st = self.convert_stat_pointer(name, buf)
525
self.delegate_to_original(name)
528
with self.run_in_subprocess(
529
"chown", "getpwnam", "__xstat", "__xstat64",
530
) as (enter, preloads):
532
preloads["chown"].return_value = -1
533
preloads["getpwnam"].side_effect = (
534
lambda name: self.make_pointer(Passwd(pw_uid=1, pw_gid=1)))
535
self._set_stat_side_effect(
536
preloads, stat_side_effect, self.db.props.root)
538
self._make_ownership_test()
539
self.assertRaisesDatabaseError(
540
Click.DatabaseError.ENSURE_OWNERSHIP, self.db.ensure_ownership)
400
543
class TestClickDB(TestCase):
430
573
self.assertEqual(0, db.props.size)
575
def test_read_nonexistent(self):
577
db.read(db_dir=os.path.join(self.temp_dir, "nonexistent"))
578
self.assertEqual(0, db.props.size)
580
def test_read_not_directory(self):
581
path = os.path.join(self.temp_dir, "file")
584
self.assertRaisesFileError(GLib.FileError.NOTDIR, db.read, db_dir=path)
432
586
def test_add(self):
434
588
self.assertEqual(0, db.props.size)
474
628
os.path.join(self.temp_dir, "b", "pkg", "1.1"),
475
629
db.get_path("pkg", "1.1"))
631
def test_has_package_version(self):
632
with open(os.path.join(self.temp_dir, "a.conf"), "w") as a:
633
print("[Click Database]", file=a)
634
print("root = %s" % os.path.join(self.temp_dir, "a"), file=a)
635
with open(os.path.join(self.temp_dir, "b.conf"), "w") as b:
636
print("[Click Database]", file=b)
637
print("root = %s" % os.path.join(self.temp_dir, "b"), file=b)
639
db.read(db_dir=self.temp_dir)
640
self.assertFalse(db.has_package_version("pkg", "1.0"))
641
os.makedirs(os.path.join(self.temp_dir, "a", "pkg", "1.0"))
642
self.assertTrue(db.has_package_version("pkg", "1.0"))
643
self.assertFalse(db.has_package_version("pkg", "1.1"))
644
os.makedirs(os.path.join(self.temp_dir, "b", "pkg", "1.0"))
645
self.assertTrue(db.has_package_version("pkg", "1.0"))
646
os.makedirs(os.path.join(self.temp_dir, "b", "pkg", "1.1"))
647
self.assertTrue(db.has_package_version("pkg", "1.1"))
477
649
def test_packages_current(self):
478
650
with open(os.path.join(self.temp_dir, "a.conf"), "w") as a:
479
651
print("[Click Database]", file=a)
571
743
json.loads(db.get_manifest_as_string("pkg", "1.1")))
745
def test_manifest_bad(self):
746
with open(os.path.join(self.temp_dir, "a.conf"), "w") as a:
747
print("[Click Database]", file=a)
748
print("root = %s" % os.path.join(self.temp_dir, "a"), file=a)
750
db.read(db_dir=self.temp_dir)
751
manifest_path = os.path.join(
752
self.temp_dir, "a", "pkg", "1.0", ".click", "info", "pkg.manifest")
753
with mkfile(manifest_path) as manifest:
754
print("{bad syntax", file=manifest)
755
self.assertRaisesDatabaseError(
756
Click.DatabaseError.BAD_MANIFEST, db.get_manifest, "pkg", "1.0")
757
self.assertRaisesDatabaseError(
758
Click.DatabaseError.BAD_MANIFEST,
759
db.get_manifest_as_string, "pkg", "1.0")
760
manifest_path = os.path.join(
761
self.temp_dir, "a", "pkg", "1.1", ".click", "info", "pkg.manifest")
762
with mkfile(manifest_path) as manifest:
763
print("[0]", file=manifest)
764
self.assertRaisesDatabaseError(
765
Click.DatabaseError.BAD_MANIFEST, db.get_manifest, "pkg", "1.0")
766
self.assertRaisesDatabaseError(
767
Click.DatabaseError.BAD_MANIFEST,
768
db.get_manifest_as_string, "pkg", "1.0")
573
770
def test_manifests_current(self):
574
771
with open(os.path.join(self.temp_dir, "a.conf"), "w") as a:
575
772
print("[Click Database]", file=a)