Merge branch '11507-deleted-bufferblocks' refs #11507
[arvados.git] / services / fuse / tests / test_inodes.py
1 import arvados_fuse
2 import mock
3 import unittest
4 import llfuse
5 import logging
6
7 class InodeTests(unittest.TestCase):
8     def test_inodes_basic(self):
9         cache = arvados_fuse.InodeCache(1000, 4)
10         inodes = arvados_fuse.Inodes(cache)
11
12         # Check that ent1 gets added to inodes
13         ent1 = mock.MagicMock()
14         ent1.in_use.return_value = False
15         ent1.has_ref.return_value = False
16         ent1.persisted.return_value = True
17         ent1.objsize.return_value = 500
18         inodes.add_entry(ent1)
19         self.assertIn(ent1.inode, inodes)
20         self.assertIs(inodes[ent1.inode], ent1)
21         self.assertEqual(500, cache.total())
22
23     def test_inodes_not_persisted(self):
24         cache = arvados_fuse.InodeCache(1000, 4)
25         inodes = arvados_fuse.Inodes(cache)
26
27         ent1 = mock.MagicMock()
28         ent1.in_use.return_value = False
29         ent1.has_ref.return_value = False
30         ent1.persisted.return_value = True
31         ent1.objsize.return_value = 500
32         inodes.add_entry(ent1)
33
34         # ent2 is not persisted, so it doesn't
35         # affect the cache total
36         ent2 = mock.MagicMock()
37         ent2.in_use.return_value = False
38         ent2.has_ref.return_value = False
39         ent2.persisted.return_value = False
40         ent2.objsize.return_value = 600
41         inodes.add_entry(ent2)
42         self.assertEqual(500, cache.total())
43
44     def test_inode_cleared(self):
45         cache = arvados_fuse.InodeCache(1000, 4)
46         inodes = arvados_fuse.Inodes(cache)
47
48         # Check that ent1 gets added to inodes
49         ent1 = mock.MagicMock()
50         ent1.in_use.return_value = False
51         ent1.has_ref.return_value = False
52         ent1.persisted.return_value = True
53         ent1.objsize.return_value = 500
54         inodes.add_entry(ent1)
55
56         # ent3 is persisted, adding it should cause ent1 to get cleared
57         ent3 = mock.MagicMock()
58         ent3.in_use.return_value = False
59         ent3.has_ref.return_value = False
60         ent3.persisted.return_value = True
61         ent3.objsize.return_value = 600
62
63         self.assertFalse(ent1.clear.called)
64         inodes.add_entry(ent3)
65
66         # Won't clear anything because min_entries = 4
67         self.assertEqual(2, len(cache._entries))
68         self.assertFalse(ent1.clear.called)
69         self.assertEqual(1100, cache.total())
70
71         # Change min_entries
72         cache.min_entries = 1
73         cache.cap_cache()
74         self.assertEqual(600, cache.total())
75         self.assertTrue(ent1.clear.called)
76
77         # Touching ent1 should cause ent3 to get cleared
78         self.assertFalse(ent3.clear.called)
79         cache.touch(ent1)
80         self.assertTrue(ent3.clear.called)
81         self.assertEqual(500, cache.total())
82
83     def test_clear_in_use(self):
84         cache = arvados_fuse.InodeCache(1000, 4)
85         inodes = arvados_fuse.Inodes(cache)
86
87         ent1 = mock.MagicMock()
88         ent1.in_use.return_value = True
89         ent1.has_ref.return_value = False
90         ent1.persisted.return_value = True
91         ent1.objsize.return_value = 500
92         inodes.add_entry(ent1)
93
94         ent3 = mock.MagicMock()
95         ent3.in_use.return_value = False
96         ent3.has_ref.return_value = True
97         ent3.persisted.return_value = True
98         ent3.objsize.return_value = 600
99         inodes.add_entry(ent3)
100
101         cache.min_entries = 1
102
103         # ent1, ent3 in use, has ref, can't be cleared
104         ent1.clear.called = False
105         ent3.clear.called = False
106         self.assertFalse(ent1.clear.called)
107         self.assertFalse(ent3.clear.called)
108         cache.touch(ent3)
109         self.assertFalse(ent1.clear.called)
110         self.assertFalse(ent3.clear.called)
111         self.assertTrue(ent3.kernel_invalidate.called)
112         self.assertEqual(1100, cache.total())
113
114         # ent1 still in use, ent3 doesn't have ref,
115         # so ent3 gets cleared
116         ent3.has_ref.return_value = False
117         ent1.clear.called = False
118         ent3.clear.called = False
119         cache.touch(ent3)
120         self.assertFalse(ent1.clear.called)
121         self.assertTrue(ent3.clear.called)
122         self.assertEqual(500, cache.total())
123
124     def test_delete(self):
125         cache = arvados_fuse.InodeCache(1000, 4)
126         inodes = arvados_fuse.Inodes(cache)
127
128         ent1 = mock.MagicMock()
129         ent1.in_use.return_value = False
130         ent1.has_ref.return_value = False
131         ent1.persisted.return_value = True
132         ent1.objsize.return_value = 500
133         inodes.add_entry(ent1)
134
135         ent3 = mock.MagicMock()
136         ent3.in_use.return_value = False
137         ent3.has_ref.return_value = False
138         ent3.persisted.return_value = True
139         ent3.objsize.return_value = 600
140
141         # Delete ent1
142         self.assertEqual(500, cache.total())
143         ent1.ref_count = 0
144         with llfuse.lock:
145             inodes.del_entry(ent1)
146         self.assertEqual(0, cache.total())
147         cache.touch(ent3)
148         self.assertEqual(600, cache.total())