Exemple #1
0
 def test_permission(self):
     key = Key.generate()
     view = View(self.log, key)
     view.build()
     path = os.path.join(os.sep, utils.random_ascii())
     with self.assertRaises(exceptions.PermissionDenied):
         view.mkdir(path)
Exemple #2
0
 def test_dir_file_exists_conflict(self):
     view = View(self.log, self.root_key)
     view.build()
     path = os.path.join(os.sep, utils.random_ascii())
     content = utils.random_ascii()
     view.write(path, content)
     with self.assertRaises(exceptions.Exists):
         view.mkdir(path)
Exemple #3
0
 def test_dir_file_exists_conflict(self):
     view = View(self.log, self.root_key)
     view.build()
     path = os.path.join(os.sep, utils.random_ascii())
     content = utils.random_ascii()
     view.write(path, content)
     with self.assertRaises(exceptions.Exists):
         view.mkdir(path)
Exemple #4
0
 def init(self):
     __, self.logpath = tempfile.mkstemp()
     __, self.logpath_b = tempfile.mkstemp()
     self.addCleanup(os.remove, self.logpath)
     self.addCleanup(os.remove, self.logpath_b)
     self.log, self.root_key = utils.bootstrap(self.logpath)
     shutil.copy2(self.logpath, self.logpath_b)
     self.log_b = Log(self.logpath_b)
     self.log.load()
     self.log_b.load()
     self.view = View(self.log, self.root_key)
     self.view_b = View(self.log_b, self.root_key)
     self.view.build()
     self.view_b.build()
     protocol = BasefsSyncProtocol(self.log)
     protocol_b = BasefsSyncProtocol(self.log_b)
     protocol.transport = utils.Socket()
     protocol_b.transport = utils.Socket()
     return protocol, protocol_b
Exemple #5
0
 def init(self):
     __, self.logpath = tempfile.mkstemp()
     __, self.logpath_b = tempfile.mkstemp()
     self.addCleanup(os.remove, self.logpath)
     self.addCleanup(os.remove, self.logpath_b)
     self.log, self.root_key = utils.bootstrap(self.logpath)
     shutil.copy2(self.logpath, self.logpath_b)
     self.log_b = Log(self.logpath_b)
     self.log.load()
     self.log_b.load()
     self.view = View(self.log, self.root_key)
     self.view_b = View(self.log_b, self.root_key)
     self.view.build()
     self.view_b.build()
     protocol = BasefsSyncProtocol(self.log)
     protocol_b = BasefsSyncProtocol(self.log_b)
     protocol.transport = utils.Socket()
     protocol_b.transport = utils.Socket()
     return protocol, protocol_b
Exemple #6
0
 def test_permission(self):
     key = Key.generate()
     view = View(self.log, key)
     view.build()
     path = os.path.join(os.sep, utils.random_ascii())
     with self.assertRaises(exceptions.PermissionDenied):
         view.mkdir(path)
Exemple #7
0
 def test_build(self):
     view = View(self.log, self.root_key)
     view.build()
     path = os.path.join(os.sep, '.cluster')
     self.assertEqual(b'127.0.0.1\n', view.get(path).content)
Exemple #8
0
class HandlerTests(unittest.TestCase):
    def init(self):
        __, self.logpath = tempfile.mkstemp()
        __, self.logpath_b = tempfile.mkstemp()
        self.addCleanup(os.remove, self.logpath)
        self.addCleanup(os.remove, self.logpath_b)
        self.log, self.root_key = utils.bootstrap(self.logpath)
        shutil.copy2(self.logpath, self.logpath_b)
        self.log_b = Log(self.logpath_b)
        self.log.load()
        self.log_b.load()
        self.view = View(self.log, self.root_key)
        self.view_b = View(self.log_b, self.root_key)
        self.view.build()
        self.view_b.build()
        protocol = BasefsSyncProtocol(self.log)
        protocol_b = BasefsSyncProtocol(self.log_b)
        protocol.transport = utils.Socket()
        protocol_b.transport = utils.Socket()
        return protocol, protocol_b

    def test_sync(self):
        protocol, protocol_b = self.init()
        self.assertEqual(protocol.initial_request(),
                         protocol_b.initial_request())
        path = os.path.join(os.sep, 'home-' + utils.random_ascii())
        node = self.view.mkdir(path)
        protocol.update_merkle(node.entry)
        self.assertNotEqual(protocol.initial_request(),
                            protocol_b.initial_request())
        # 1
        request = protocol_b.initial_request()
        # 2
        protocol.data_received(request)
        response = protocol.transport.read()
        protocol.transport = utils.Socket()
        self.assertEqual(protocol.LS, response.decode().splitlines()[0])
        self.assertEqual('*/ ' + self.log.root.hash,
                         response.decode().splitlines()[1])
        # 3
        protocol_b.data_received(response)
        response = protocol_b.transport.read()
        protocol_b.transport = utils.Socket()
        self.assertEqual(protocol.PATH_REQ, response.decode().splitlines()[0])
        self.assertEqual(path, response.decode().splitlines()[1])
        self.assertEqual(2, len(response.decode().splitlines()))
        # 4
        protocol.data_received(response)
        response = protocol.transport.read()
        with self.assertRaises(ValueError):
            protocol.transport.read(close_check=True)
        protocol.transport = utils.Socket()
        self.assertEqual(protocol.ENTRIES, response.decode().splitlines()[0])
        self.assertEqual(3, len(response.decode().splitlines()))
        self.assertEqual(protocol.CLOSE, response.decode().splitlines()[-1])
        # 5
        protocol_b.data_received(response)
        with self.assertRaises(ValueError):
            protocol_b.transport.read(close_check=True)
        self.assertEqual(self.log.print_tree(), self.log_b.print_tree())
        self.assertDictEqual(protocol.merkle, protocol_b.merkle)

        # delete
        dnode = self.view.delete(path)
        protocol.update_merkle(dnode.entry)
        request = protocol_b.initial_request()
        # 2
        protocol.data_received(request)
        response = protocol.transport.read()
        protocol.transport = utils.Socket()
        self.assertEqual(protocol.LS, response.decode().splitlines()[0])
        self.assertEqual('*/ ' + self.log.root.hash,
                         response.decode().splitlines()[1])
        # 3
        protocol_b.data_received(response)
        response = protocol_b.transport.read()
        protocol_b.transport = utils.Socket()
        self.assertEqual(protocol.LS, response.decode().splitlines()[0])
        self.assertEqual('*%s %s' % (path, node.entry.hash),
                         response.decode().splitlines()[1])
        self.assertEqual(2, len(response.decode().splitlines()))
        # 4
        protocol.data_received(response)
        response = protocol.transport.read()
        with self.assertRaises(ValueError):
            protocol.transport.read(close_check=True)
        protocol.transport = utils.Socket()
        self.assertEqual(protocol.ENTRIES, response.decode().splitlines()[0])
        self.assertEqual(3, len(response.decode().splitlines()))
        self.assertEqual(protocol.CLOSE, response.decode().splitlines()[-1])
        # 5
        protocol_b.data_received(response)
        with self.assertRaises(ValueError):
            protocol_b.transport.read(close_check=True)
        self.assertEqual(self.log.print_tree(), self.log_b.print_tree())
        self.assertDictEqual(protocol.merkle, protocol_b.merkle)

    def test_sync_reverse(self):
        # Reverse communication
        protocol, protocol_b = self.init()
        path = os.path.join(os.sep, 'home-' + utils.random_ascii())
        node = self.view.mkdir(path)
        protocol.update_merkle(node.entry)
        # 1
        request = protocol.initial_request()
        # 2
        protocol_b.data_received(request)
        response = protocol_b.transport.read()
        protocol_b.transport = utils.Socket()
        self.assertEqual(protocol.LS, response.decode().splitlines()[0])
        self.assertEqual('*/ ' + self.log.root.hash,
                         response.decode().splitlines()[1])
        # 3
        protocol.data_received(response)
        with self.assertRaises(ValueError):
            protocol.transport.read(close_check=True)
        response = protocol.transport.read()
        self.assertEqual(protocol.ENTRIES, response.decode().splitlines()[0])
        self.assertEqual(3, len(response.decode().splitlines()))
        self.assertEqual(protocol.CLOSE, response.decode().splitlines()[-1])
        # 4
        protocol_b.data_received(response)
        with self.assertRaises(ValueError):
            protocol_b.transport.read(close_check=True)
        with self.assertRaises(ValueError):
            protocol.transport.read(close_check=True)
        self.assertEqual(self.log.print_tree(), self.log_b.print_tree())
        self.assertDictEqual(protocol.merkle, protocol_b.merkle)

        # delete
        dnode = self.view.delete(path)
        protocol.update_merkle(dnode.entry)
        request = protocol.initial_request()
        # 2
        protocol_b.data_received(request)
        response = protocol_b.transport.read()
        protocol_b.transport = utils.Socket()
        self.assertEqual(protocol.LS, response.decode().splitlines()[0])
        self.assertEqual('*/ ' + self.log.root.hash,
                         response.decode().splitlines()[1])
        # 3
        protocol.data_received(response)
        response = protocol.transport.read()
        protocol.transport = utils.Socket()
        self.assertEqual(protocol.LS, response.decode().splitlines()[0])
        self.assertEqual(
            '*%s %s %s' % (path, node.entry.hash, dnode.entry.hash),
            response.decode().splitlines()[1])
        self.assertEqual(2, len(response.decode().splitlines()))
        # 4
        protocol_b.data_received(response)
        response = protocol_b.transport.read()
        protocol_b.transport = utils.Socket()
        self.assertEqual(protocol.ENTRY_REQ, response.decode().splitlines()[0])
        self.assertEqual(dnode.entry.hash, response.decode().splitlines()[1])
        # 5
        protocol.data_received(response)
        response = protocol.transport.read()
        with self.assertRaises(ValueError):
            protocol.transport.read(close_check=True)
        protocol.transport = utils.Socket()
        self.assertEqual(protocol.ENTRIES, response.decode().splitlines()[0])
        self.assertEqual(protocol.CLOSE, response.decode().splitlines()[-1])
        self.assertEqual(3, len(response.decode().splitlines()))
        # BAD request
        before = self.log.print_tree()
        protocol.data_received(response)
        self.assertEqual(before, self.log.print_tree())
        # 6
        protocol_b.data_received(response)
        with self.assertRaises(ValueError):
            protocol_b.transport.read(close_check=True)
        self.assertDictEqual(protocol.merkle, protocol_b.merkle)
        self.assertEqual(self.log.print_tree(), self.log_b.print_tree())
Exemple #9
0
 def test_deleted_nested_dir(self):
     view = View(self.log, self.root_key)
     view.build()
     home_path = os.path.join(os.sep, 'home-' + utils.random_ascii())
     user_path = os.path.join(home_path, 'user-' + utils.random_ascii())
     view.mkdir(home_path)
     view.mkdir(user_path)
     view.delete(home_path)
     self.assertEqual(LogEntry.DELETE, view.get(home_path).entry.action)
     with self.assertRaises(exceptions.DoesNotExist):
         view.get(user_path)
     self.rebuild(view)
     self.assertEqual(LogEntry.DELETE, view.get(home_path).entry.action)
     with self.assertRaises(exceptions.DoesNotExist):
         view.get(user_path)
Exemple #10
0
 def test_build(self):
     view = View(self.log, self.root_key)
     view.build()
     path = os.path.join(os.sep, '.cluster')
     self.assertEqual(b'127.0.0.1\n', view.get(path).content)
Exemple #11
0
    def test_revoke(self):
        root_view = View(self.log, self.root_key)
        root_view.build()
        home_path = os.path.join(os.sep, 'home-' + utils.random_ascii())
        root_view.mkdir(home_path)
        key = Key.generate()
        root_view.grant(home_path, 'user', key)

        view = View(self.log, key)
        view.build()
        user_path = os.path.join(home_path, 'user-' + utils.random_ascii())
        view.mkdir(user_path)

        root_view.build()
        file_path = os.path.join(user_path, 'file2-' + utils.random_ascii())
        file_content = ('content1-' + utils.random_ascii(1024)) * 32
        root_view.write(file_path, file_content)
        self.assertEqual(file_content.encode(),
                         root_view.get(file_path).content)
        root_view.revoke(home_path, 'user')
        self.assertEqual(file_content.encode(),
                         root_view.get(file_path).content)
        self.assertEqual(file_path, root_view.get(file_path).path)

        view.build()

        #        with open(self.logpath, 'r') as r:
        #            print(r.read())
        print(self.log.print_tree(view=view, color=True))
        root_view.build()
        # TODO tree eq after build, except the revoke brancj
        # TODO test maintain current state (file writen by revoked user)
        print(self.log.print_tree(view=root_view, color=True))
        alt_file_content = 'content2-' + utils.random_ascii()
        with self.assertRaises(exceptions.DoesNotExist):
            view.write(file_path, alt_file_content)
Exemple #12
0
 def test_grant(self):
     view = View(self.log, self.root_key)
     view.build()
     home_path = os.path.join(os.sep, utils.random_ascii())
     view.mkdir(home_path)
     key = Key.generate()
     view.grant(home_path, 'user', key)
     prev = str(view.root)
     view.build()
     self.assertEqual(len(prev), len(str(view.root)))
     # Change key
     view = View(self.log, key)
     view.build()
     content = utils.random_ascii()
     file_path = os.path.join(os.sep, utils.random_ascii())
     with self.assertRaises(exceptions.PermissionDenied):
         view.write(file_path, content)
     user_path = os.path.join(home_path, utils.random_ascii())
     view.mkdir(user_path)
     self.assertEqual(LogEntry.MKDIR, view.get(user_path).entry.action)
     file_path = os.path.join(user_path, utils.random_ascii())
     content = utils.random_ascii()
     view.write(file_path, content)
     self.assertEqual(content.encode(), view.get(file_path).content)
     view = View(self.log, self.root_key)
     view.build()
     view.write(file_path, content)
     self.assertEqual(content.encode(), view.get(file_path).content)
     file_path = os.path.join(user_path, utils.random_ascii())
     content = utils.random_ascii()
     view.write(file_path, content)
     self.assertEqual(content.encode(), view.get(file_path).content)
     self.rebuild(view)
Exemple #13
0
 def test_delete(self):
     view = View(self.log, self.root_key)
     view.build()
     # Delete File
     file_path = os.path.join(os.sep, utils.random_ascii())
     content = utils.random_ascii()
     view.write(file_path, content)
     self.assertEqual(LogEntry.WRITE, view.get(file_path).entry.action)
     self.assertEqual(content.encode(), view.get(file_path).content)
     view.delete(file_path)
     self.assertEqual(LogEntry.DELETE, view.get(file_path).entry.action)
     # Reload
     self.rebuild(view)
     self.assertEqual(LogEntry.DELETE, view.get(file_path).entry.action)
     # Delete Dir
     home_path = os.path.join(os.sep, utils.random_ascii())
     view.mkdir(home_path)
     self.assertEqual(LogEntry.MKDIR,
                      view.paths.get(home_path).entry.action)
     view.delete(home_path)
     self.assertEqual(LogEntry.DELETE, view.get(home_path).entry.action)
Exemple #14
0
 def test_recreate_deleted(self):
     view = View(self.log, self.root_key)
     view.build()
     home_path = os.path.join(os.sep, 'home-' + utils.random_ascii())
     user_path = os.path.join(home_path, 'user-' + utils.random_ascii())
     view.mkdir(home_path)
     view.mkdir(user_path)
     file_path = os.path.join(user_path, utils.random_ascii())
     file_content = utils.random_ascii()
     view.write(file_path, file_content)
     self.assertEqual(file_content.encode(), view.get(file_path).content)
     view.delete(home_path)
     with self.assertRaises(exceptions.DoesNotExist):
         view.get(file_path)
     view.mkdir(home_path)
     with self.assertRaises(exceptions.DoesNotExist):
         view.get(file_path)
     with self.assertRaises(exceptions.DoesNotExist):
         view.get(user_path)
     # File
     view.mkdir(user_path)
     new_file_content = utils.random_ascii()
     view.write(file_path, new_file_content)
     self.assertEqual(new_file_content.encode(),
                      view.get(file_path).content)
     # Reload
     self.rebuild(view)
     self.assertEqual(new_file_content.encode(),
                      view.get(file_path).content)
     view.get(user_path)
     view.delete(file_path)
     new_file_content = utils.random_ascii()
     view.write(file_path, new_file_content)
     self.assertEqual(new_file_content.encode(),
                      view.get(file_path).content)
Exemple #15
0
 def test_revert(self):
     view = View(self.log, self.root_key)
     view.build()
     rata_node = view.mkdir('/rata')
Exemple #16
0
 def test_hardlink(self):
     view = View(self.log, self.root_key)
     view.build()
     rata_node = view.mkdir('/rata')
     view.link('/home', rata_node.entry.hash)
     print(view.get('/home') == rata_node)
     kakas_node = view.write('/kakas', b'hola')
     view.link('/kakas_link', kakas_node.entry.hash)
     self.assertEqual(b'hola', view.get('/kakas_link').content)
     view.delete('/kakas')
     self.assertEqual(b'hola', view.get('/kakas_link').content)
     print(view.get('/kakas').content)
Exemple #17
0
 def test_symlink(self):
     view = View(self.log, self.root_key)
     view.build()
     view.symlink('/kakas', '/rata')
     print(view.get('/kakas').content)
Exemple #18
0
 def test_branch_conflict(self):
     view = View(self.log, self.root_key)
     view.build()
     home_path = os.path.join(os.sep, 'home-' + utils.random_ascii())
     view.mkdir(home_path)
     key = Key.generate()
     view.grant(home_path, 'user', key)
     view = View(self.log, key)
     view.build()
     parent_node = view.get(home_path)
     user_path = os.path.join(home_path, 'user-' + utils.random_ascii())
     max_hash = None
     enc_content = ''
     for ix in range(12):
         content = 'content-' + utils.random_ascii(32)
         prev = enc_content
         enc_content = bsdiff4.diff(enc_content, content)
         entry = self.log.write(parent_node.entry, user_path, key, attachment=enc_content)
         max_hash = max(max_hash, entry.hash) if max_hash else entry.hash
     view = View(self.log, self.root_key)
     view.build()
     self.assertEqual(bsdiff4.patch(prev, self.log.entries[max_hash].get_content()), view.get(user_path).content)
     # Admin branch more power
     admin_content = 'content-' + utils.random_ascii(32)
     content = bsdiff4.diff(enc_content, admin_content)
     self.log.write(parent_node.entry, user_path, self.root_key, attachment=content)
     view.build()
     self.assertEqual(admin_content.encode(), view.get(user_path).content)
     alt_content = bsdiff4.diff(content, ('content-' + utils.random_ascii(32)).encode())
     self.log.write(parent_node.entry, user_path, key, attachment=alt_content)
     self.assertEqual(admin_content.encode(), view.get(user_path).content)
     # Grant consistency with prev state
     view.grant(os.sep, 'user', key)
     self.assertEqual(admin_content.encode(), view.get(user_path).content)
     view.build()
     self.assertEqual(admin_content.encode(), view.get(user_path).content)
     # Test prints
     self.log.print_tree(view=view, color=True)
     self.log.print_tree(view=view, ascii=True)
Exemple #19
0
    def test_revoke(self):
        root_view = View(self.log, self.root_key)
        root_view.build()
        home_path = os.path.join(os.sep, 'home-' + utils.random_ascii())
        root_view.mkdir(home_path)
        key = Key.generate()
        root_view.grant(home_path, 'user', key)
        
        view = View(self.log, key)
        view.build()
        user_path = os.path.join(home_path, 'user-' + utils.random_ascii())
        view.mkdir(user_path)
        
        root_view.build()
        file_path = os.path.join(user_path, 'file2-' + utils.random_ascii())
        file_content = ('content1-' + utils.random_ascii(1024))*32
        root_view.write(file_path, file_content)
        self.assertEqual(file_content.encode(), root_view.get(file_path).content)
        root_view.revoke(home_path, 'user')
        self.assertEqual(file_content.encode(), root_view.get(file_path).content)
        self.assertEqual(file_path, root_view.get(file_path).path)
        
        view.build()
        
#        with open(self.logpath, 'r') as r:
#            print(r.read())
        print(self.log.print_tree(view=view, color=True))
        root_view.build()
        # TODO tree eq after build, except the revoke brancj
        # TODO test maintain current state (file writen by revoked user)
        print(self.log.print_tree(view=root_view, color=True))
        alt_file_content = 'content2-' + utils.random_ascii()
        with self.assertRaises(exceptions.DoesNotExist):
            view.write(file_path, alt_file_content)
Exemple #20
0
 def test_deleted_nested_dir(self):
     view = View(self.log, self.root_key)
     view.build()
     home_path = os.path.join(os.sep, 'home-' + utils.random_ascii())
     user_path = os.path.join(home_path, 'user-' + utils.random_ascii())
     view.mkdir(home_path)
     view.mkdir(user_path)
     view.delete(home_path)
     self.assertEqual(LogEntry.DELETE, view.get(home_path).entry.action)
     with self.assertRaises(exceptions.DoesNotExist):
         view.get(user_path)
     self.rebuild(view)
     self.assertEqual(LogEntry.DELETE, view.get(home_path).entry.action)
     with self.assertRaises(exceptions.DoesNotExist):
         view.get(user_path)
Exemple #21
0
 def test_mkdir(self):
     view = View(self.log, self.root_key)
     view.build()
     home_path = os.sep + utils.random_ascii()
     view.mkdir(home_path)
     self.assertEqual(LogEntry.MKDIR, view.paths.get(home_path).entry.action)
     user_path = os.path.join(home_path, utils.random_ascii())
     view.mkdir(user_path)
     self.assertEqual(LogEntry.MKDIR, view.get(user_path).entry.action)
     not_path = os.path.join(os.sep, utils.random_ascii(), utils.random_ascii())
     with self.assertRaises(exceptions.DoesNotExist):
         view.mkdir(not_path)
     with self.assertRaises(exceptions.DoesNotExist):
         view.get(not_path)
     self.rebuild(view)
     self.assertEqual(LogEntry.MKDIR, view.get(home_path).entry.action)
     self.assertEqual(LogEntry.MKDIR, view.get(user_path).entry.action)
     with self.assertRaises(exceptions.DoesNotExist):
         view.get(not_path)
Exemple #22
0
 def test_grant(self):
     view = View(self.log, self.root_key)
     view.build()
     home_path = os.path.join(os.sep, utils.random_ascii())
     view.mkdir(home_path)
     key = Key.generate()
     view.grant(home_path, 'user', key)
     prev = str(view.root)
     view.build()
     self.assertEqual(len(prev), len(str(view.root)))
     # Change key
     view = View(self.log, key)
     view.build()
     content = utils.random_ascii()
     file_path = os.path.join(os.sep, utils.random_ascii())
     with self.assertRaises(exceptions.PermissionDenied):
         view.write(file_path, content)
     user_path = os.path.join(home_path, utils.random_ascii())
     view.mkdir(user_path)
     self.assertEqual(LogEntry.MKDIR, view.get(user_path).entry.action)
     file_path = os.path.join(user_path, utils.random_ascii())
     content = utils.random_ascii()
     view.write(file_path, content)
     self.assertEqual(content.encode(), view.get(file_path).content)
     view = View(self.log, self.root_key)
     view.build()
     view.write(file_path, content)
     self.assertEqual(content.encode(), view.get(file_path).content)
     file_path = os.path.join(user_path, utils.random_ascii())
     content = utils.random_ascii()
     view.write(file_path, content)
     self.assertEqual(content.encode(), view.get(file_path).content)
     self.rebuild(view)
Exemple #23
0
 def test_branch_conflict(self):
     view = View(self.log, self.root_key)
     view.build()
     home_path = os.path.join(os.sep, 'home-' + utils.random_ascii())
     view.mkdir(home_path)
     key = Key.generate()
     view.grant(home_path, 'user', key)
     view = View(self.log, key)
     view.build()
     parent_node = view.get(home_path)
     user_path = os.path.join(home_path, 'user-' + utils.random_ascii())
     max_hash = None
     enc_content = ''
     for ix in range(12):
         content = 'content-' + utils.random_ascii(32)
         prev = enc_content
         enc_content = bsdiff4.diff(enc_content, content)
         entry = self.log.write(parent_node.entry,
                                user_path,
                                key,
                                attachment=enc_content)
         max_hash = max(max_hash, entry.hash) if max_hash else entry.hash
     view = View(self.log, self.root_key)
     view.build()
     self.assertEqual(
         bsdiff4.patch(prev, self.log.entries[max_hash].get_content()),
         view.get(user_path).content)
     # Admin branch more power
     admin_content = 'content-' + utils.random_ascii(32)
     content = bsdiff4.diff(enc_content, admin_content)
     self.log.write(parent_node.entry,
                    user_path,
                    self.root_key,
                    attachment=content)
     view.build()
     self.assertEqual(admin_content.encode(), view.get(user_path).content)
     alt_content = bsdiff4.diff(content, ('content-' +
                                          utils.random_ascii(32)).encode())
     self.log.write(parent_node.entry,
                    user_path,
                    key,
                    attachment=alt_content)
     self.assertEqual(admin_content.encode(), view.get(user_path).content)
     # Grant consistency with prev state
     view.grant(os.sep, 'user', key)
     self.assertEqual(admin_content.encode(), view.get(user_path).content)
     view.build()
     self.assertEqual(admin_content.encode(), view.get(user_path).content)
     # Test prints
     self.log.print_tree(view=view, color=True)
     self.log.print_tree(view=view, ascii=True)
Exemple #24
0
 def test_hardlink(self):
     view = View(self.log, self.root_key)
     view.build()
     rata_node = view.mkdir('/rata')
     view.link('/home', rata_node.entry.hash)
     print(view.get('/home') == rata_node)
     kakas_node = view.write('/kakas', b'hola')
     view.link('/kakas_link', kakas_node.entry.hash)
     self.assertEqual(b'hola', view.get('/kakas_link').content)
     view.delete('/kakas')
     self.assertEqual(b'hola', view.get('/kakas_link').content)
     print(view.get('/kakas').content)
Exemple #25
0
 def test_recreate_deleted(self):
     view = View(self.log, self.root_key)
     view.build()
     home_path = os.path.join(os.sep, 'home-' + utils.random_ascii())
     user_path = os.path.join(home_path, 'user-' + utils.random_ascii())
     view.mkdir(home_path)
     view.mkdir(user_path)
     file_path = os.path.join(user_path, utils.random_ascii())
     file_content = utils.random_ascii()
     view.write(file_path, file_content)
     self.assertEqual(file_content.encode(), view.get(file_path).content)
     view.delete(home_path)
     with self.assertRaises(exceptions.DoesNotExist):
         view.get(file_path)
     view.mkdir(home_path)
     with self.assertRaises(exceptions.DoesNotExist):
         view.get(file_path)
     with self.assertRaises(exceptions.DoesNotExist):
         view.get(user_path)
     # File
     view.mkdir(user_path)
     new_file_content = utils.random_ascii()
     view.write(file_path, new_file_content)
     self.assertEqual(new_file_content.encode(), view.get(file_path).content)
     # Reload
     self.rebuild(view)
     self.assertEqual(new_file_content.encode(), view.get(file_path).content)
     view.get(user_path)
     view.delete(file_path)
     new_file_content = utils.random_ascii()
     view.write(file_path, new_file_content)
     self.assertEqual(new_file_content.encode(), view.get(file_path).content)
Exemple #26
0
 def test_symlink(self):
     view = View(self.log, self.root_key)
     view.build()
     view.symlink('/kakas', '/rata')
     print(view.get('/kakas').content)
Exemple #27
0
 def test_write(self):
     view = View(self.log, self.root_key)
     view.build()
     path = os.path.join(os.sep, utils.random_ascii())
     content = utils.random_ascii()
     view.write(path, content)
     self.assertEqual(LogEntry.WRITE, view.get(path).entry.action)
     self.assertEqual(content.encode(), view.get(path).content)
     self.rebuild(view)
     self.assertEqual(content.encode(), view.get(path).content)
     with self.assertRaises(exceptions.Exists):
         view.mkdir(path)
     view.delete(path)
     view.mkdir(path)
     path = os.path.join(path, 'content-%s' % utils.random_ascii())
     alt_content = utils.random_ascii()
     view.write(path, alt_content)
     self.assertEqual(alt_content.encode(), view.get(path).content)
     alt_content += utils.random_ascii()
     view.write(path, alt_content)
     self.assertEqual(alt_content.encode(), view.get(path).content)
     alt_content = utils.random_ascii(512**2)
     view.write(path, alt_content)
     self.assertEqual(alt_content.encode(), view.get(path).content)
     view.delete(path)
     self.assertEqual(LogEntry.DELETE, view.get(path).entry.action)
     view.mkdir(path)
     self.assertEqual(LogEntry.MKDIR, view.get(path).entry.action)
     view.delete(path)
     self.assertEqual(LogEntry.DELETE, view.get(path).entry.action)
     view.write(path, alt_content)
     self.assertEqual(alt_content.encode(), view.get(path).content)
Exemple #28
0
 def test_revert(self):
     view = View(self.log, self.root_key)
     view.build()
     rata_node = view.mkdir('/rata')
Exemple #29
0
def command(mount=False, arg_parser=None):
    if arg_parser is None:
        # Invoking from code, not basefs bin
        set_parser(parser)
        arg_parser = parser
    args = arg_parser.parse_args()
    context = get_context(args.logpath, defaults)
    logpath = context.fs.logpath
    if context.mount_info:
        mountpoint = context.mount_info.mountpoint
        sys.stderr.write("Error: log %s already mounted in %s\n" % (logpath, mountpoint))
        sys.exit(4)
    ip, *port = args.bind.split(':')
    if port:
        port = int(port[0])
    else:
        port = context.fs.port
    if args.iface:
        iface_ip = utils.get_ip_address(args.iface)
        if ip != '0.0.0.0' and ip != iface_ip:
            sys.stderr.write("-bind and -iface ip addresses do not match %s != %s\n" % (ip, iface_ip))
            sys.exit(9)
        ip = iface_ip
#    logpath = args.logpath
    config = get_or_create_config(defaults)
    hostname = args.hostname
    section = config[context.fs.name]
    if not hostname:
        if context.fs.name in config:
            hostname = section['hostname']
        else:
            hostname = defaults.hostname
    
    rpc_port = port+1
    sync_port = port+2
    logpath = os.path.normpath(logpath)
    keypath = os.path.normpath(args.keypath)
    logging.basicConfig(
        level=logging.DEBUG if args.debug else logging.INFO,
        format='%(asctime)-15s [%(levelname)s] %(name)s: %(message)s',
    )
    logpath = os.path.normpath(logpath)
    log = Log(logpath)
    log.load()
    if keypath == defaults.keypath and not os.path.exists(keypath):
        view = View(log)
    else:
        key = Key.load(keypath)
        view = View(log, key)
    view.build()
    serf = None
    serf_agent = None
    if args.serf:
        join = args.join.split(',') if args.join else []
        serf, serf_agent = gossip.run(section, view, ip, port, hostname, join)
        if args.watcher:
            handler = handlers.Handler(args.watcher, view.log, state=serf.blockstate)
    else:
        if args.watcher:
            handler = handlers.Handler(args.watcher, view.log)
    if mount:
        init_function = lambda: None
        if args.serf:
            # Eventloop needs to run on a separated thread when using FUSE
            init_function = lambda: loop.run_thread(view, serf, port+2, config=section)
        mountpoint = args.mountpoint
        sys.stdout.write('Mounting %s into %s\n' % (logpath, mountpoint))
        fs = FileSystem(view, serf=serf, serf_agent=serf_agent, init_function=init_function)
        fsname = '%s:%i' % (logpath, sync_port)
        foreground = args.foreground or args.debug
        FUSE(fs, mountpoint, fsname=fsname, nothreads=False, foreground=foreground)
    else:
        try:
            loop.run(view, serf, port+2, config=section)
        except KeyboardInterrupt:
            pass
        finally:
            serf_agent.stop()
Exemple #30
0
 def test_mkdir(self):
     view = View(self.log, self.root_key)
     view.build()
     home_path = os.sep + utils.random_ascii()
     view.mkdir(home_path)
     self.assertEqual(LogEntry.MKDIR,
                      view.paths.get(home_path).entry.action)
     user_path = os.path.join(home_path, utils.random_ascii())
     view.mkdir(user_path)
     self.assertEqual(LogEntry.MKDIR, view.get(user_path).entry.action)
     not_path = os.path.join(os.sep, utils.random_ascii(),
                             utils.random_ascii())
     with self.assertRaises(exceptions.DoesNotExist):
         view.mkdir(not_path)
     with self.assertRaises(exceptions.DoesNotExist):
         view.get(not_path)
     self.rebuild(view)
     self.assertEqual(LogEntry.MKDIR, view.get(home_path).entry.action)
     self.assertEqual(LogEntry.MKDIR, view.get(user_path).entry.action)
     with self.assertRaises(exceptions.DoesNotExist):
         view.get(not_path)
Exemple #31
0
class HandlerTests(unittest.TestCase):
    def init(self):
        __, self.logpath = tempfile.mkstemp()
        __, self.logpath_b = tempfile.mkstemp()
        self.addCleanup(os.remove, self.logpath)
        self.addCleanup(os.remove, self.logpath_b)
        self.log, self.root_key = utils.bootstrap(self.logpath)
        shutil.copy2(self.logpath, self.logpath_b)
        self.log_b = Log(self.logpath_b)
        self.log.load()
        self.log_b.load()
        self.view = View(self.log, self.root_key)
        self.view_b = View(self.log_b, self.root_key)
        self.view.build()
        self.view_b.build()
        protocol = BasefsSyncProtocol(self.log)
        protocol_b = BasefsSyncProtocol(self.log_b)
        protocol.transport = utils.Socket()
        protocol_b.transport = utils.Socket()
        return protocol, protocol_b
    
    def test_sync(self):
        protocol, protocol_b = self.init()
        self.assertEqual(protocol.initial_request(), protocol_b.initial_request())
        path = os.path.join(os.sep, 'home-' + utils.random_ascii())
        node = self.view.mkdir(path)
        protocol.update_merkle(node.entry)
        self.assertNotEqual(protocol.initial_request(), protocol_b.initial_request())
        # 1
        request = protocol_b.initial_request()
        # 2
        protocol.data_received(request)
        response = protocol.transport.read()
        protocol.transport = utils.Socket()
        self.assertEqual(protocol.LS, response.decode().splitlines()[0])
        self.assertEqual('*/ ' + self.log.root.hash, response.decode().splitlines()[1])
        # 3
        protocol_b.data_received(response)
        response = protocol_b.transport.read()
        protocol_b.transport = utils.Socket()
        self.assertEqual(protocol.PATH_REQ, response.decode().splitlines()[0])
        self.assertEqual(path, response.decode().splitlines()[1])
        self.assertEqual(2, len(response.decode().splitlines()))
        # 4
        protocol.data_received(response)
        response = protocol.transport.read()
        with self.assertRaises(ValueError):
            protocol.transport.read(close_check=True)
        protocol.transport = utils.Socket()
        self.assertEqual(protocol.ENTRIES, response.decode().splitlines()[0])
        self.assertEqual(3, len(response.decode().splitlines()))
        self.assertEqual(protocol.CLOSE, response.decode().splitlines()[-1])
        # 5
        protocol_b.data_received(response)
        with self.assertRaises(ValueError):
            protocol_b.transport.read(close_check=True)
        self.assertEqual(self.log.print_tree(), self.log_b.print_tree())
        self.assertDictEqual(protocol.merkle, protocol_b.merkle)
        
        # delete
        dnode = self.view.delete(path)
        protocol.update_merkle(dnode.entry)
        request = protocol_b.initial_request()
        # 2
        protocol.data_received(request)
        response = protocol.transport.read()
        protocol.transport = utils.Socket()
        self.assertEqual(protocol.LS, response.decode().splitlines()[0])
        self.assertEqual('*/ ' + self.log.root.hash, response.decode().splitlines()[1])
        # 3
        protocol_b.data_received(response)
        response = protocol_b.transport.read()
        protocol_b.transport = utils.Socket()
        self.assertEqual(protocol.LS, response.decode().splitlines()[0])
        self.assertEqual('*%s %s' % (path, node.entry.hash), response.decode().splitlines()[1])
        self.assertEqual(2, len(response.decode().splitlines()))
        # 4 
        protocol.data_received(response)
        response = protocol.transport.read()
        with self.assertRaises(ValueError):
            protocol.transport.read(close_check=True)
        protocol.transport = utils.Socket()
        self.assertEqual(protocol.ENTRIES, response.decode().splitlines()[0])
        self.assertEqual(3, len(response.decode().splitlines()))
        self.assertEqual(protocol.CLOSE, response.decode().splitlines()[-1])
        # 5
        protocol_b.data_received(response)
        with self.assertRaises(ValueError):
            protocol_b.transport.read(close_check=True)
        self.assertEqual(self.log.print_tree(), self.log_b.print_tree())
        self.assertDictEqual(protocol.merkle, protocol_b.merkle)
        
    def test_sync_reverse(self):
        # Reverse communication
        protocol, protocol_b = self.init()
        path = os.path.join(os.sep, 'home-' + utils.random_ascii())
        node = self.view.mkdir(path)
        protocol.update_merkle(node.entry)
        # 1
        request = protocol.initial_request()
        # 2
        protocol_b.data_received(request)
        response = protocol_b.transport.read()
        protocol_b.transport = utils.Socket()
        self.assertEqual(protocol.LS, response.decode().splitlines()[0])
        self.assertEqual('*/ ' + self.log.root.hash, response.decode().splitlines()[1])
        # 3
        protocol.data_received(response)
        with self.assertRaises(ValueError):
            protocol.transport.read(close_check=True)
        response = protocol.transport.read()
        self.assertEqual(protocol.ENTRIES, response.decode().splitlines()[0])
        self.assertEqual(3, len(response.decode().splitlines()))
        self.assertEqual(protocol.CLOSE, response.decode().splitlines()[-1])
        # 4
        protocol_b.data_received(response)
        with self.assertRaises(ValueError):
            protocol_b.transport.read(close_check=True)
        with self.assertRaises(ValueError):
            protocol.transport.read(close_check=True)
        self.assertEqual(self.log.print_tree(), self.log_b.print_tree())
        self.assertDictEqual(protocol.merkle, protocol_b.merkle)
        
        # delete
        dnode = self.view.delete(path)
        protocol.update_merkle(dnode.entry)
        request = protocol.initial_request()
        # 2
        protocol_b.data_received(request)
        response = protocol_b.transport.read()
        protocol_b.transport = utils.Socket()
        self.assertEqual(protocol.LS, response.decode().splitlines()[0])
        self.assertEqual('*/ ' + self.log.root.hash, response.decode().splitlines()[1])
        # 3
        protocol.data_received(response)
        response = protocol.transport.read()
        protocol.transport = utils.Socket()
        self.assertEqual(protocol.LS, response.decode().splitlines()[0])
        self.assertEqual('*%s %s %s' % (path, node.entry.hash, dnode.entry.hash), response.decode().splitlines()[1])
        self.assertEqual(2, len(response.decode().splitlines()))
        # 4 
        protocol_b.data_received(response)
        response = protocol_b.transport.read()
        protocol_b.transport = utils.Socket()
        self.assertEqual(protocol.ENTRY_REQ, response.decode().splitlines()[0])
        self.assertEqual(dnode.entry.hash, response.decode().splitlines()[1])
        # 5
        protocol.data_received(response)
        response = protocol.transport.read()
        with self.assertRaises(ValueError):
            protocol.transport.read(close_check=True)
        protocol.transport = utils.Socket()
        self.assertEqual(protocol.ENTRIES, response.decode().splitlines()[0])
        self.assertEqual(protocol.CLOSE, response.decode().splitlines()[-1])
        self.assertEqual(3, len(response.decode().splitlines()))
        # BAD request
        before = self.log.print_tree()
        protocol.data_received(response)
        self.assertEqual(before, self.log.print_tree())
        # 6
        protocol_b.data_received(response)
        with self.assertRaises(ValueError):
            protocol_b.transport.read(close_check=True)
        self.assertDictEqual(protocol.merkle, protocol_b.merkle)
        self.assertEqual(self.log.print_tree(), self.log_b.print_tree())
Exemple #32
0
 def test_write(self):
     view = View(self.log, self.root_key)
     view.build()
     path = os.path.join(os.sep, utils.random_ascii())
     content = utils.random_ascii()
     view.write(path, content)
     self.assertEqual(LogEntry.WRITE, view.get(path).entry.action)
     self.assertEqual(content.encode(), view.get(path).content)
     self.rebuild(view)
     self.assertEqual(content.encode(), view.get(path).content)
     with self.assertRaises(exceptions.Exists):
         view.mkdir(path)
     view.delete(path)
     view.mkdir(path)
     path = os.path.join(path, 'content-%s' % utils.random_ascii())
     alt_content = utils.random_ascii()
     view.write(path, alt_content)
     self.assertEqual(alt_content.encode(), view.get(path).content)
     alt_content += utils.random_ascii()
     view.write(path, alt_content)
     self.assertEqual(alt_content.encode(), view.get(path).content)
     alt_content = utils.random_ascii(512**2)
     view.write(path, alt_content)
     self.assertEqual(alt_content.encode(), view.get(path).content)
     view.delete(path)
     self.assertEqual(LogEntry.DELETE, view.get(path).entry.action)
     view.mkdir(path)
     self.assertEqual(LogEntry.MKDIR, view.get(path).entry.action)
     view.delete(path)
     self.assertEqual(LogEntry.DELETE, view.get(path).entry.action)
     view.write(path, alt_content)
     self.assertEqual(alt_content.encode(), view.get(path).content)
Exemple #33
0
 def test_delete(self):
     view = View(self.log, self.root_key)
     view.build()
     # Delete File
     file_path = os.path.join(os.sep, utils.random_ascii())
     content = utils.random_ascii()
     view.write(file_path, content)
     self.assertEqual(LogEntry.WRITE, view.get(file_path).entry.action)
     self.assertEqual(content.encode(), view.get(file_path).content)
     view.delete(file_path)
     self.assertEqual(LogEntry.DELETE, view.get(file_path).entry.action)
     # Reload
     self.rebuild(view)
     self.assertEqual(LogEntry.DELETE, view.get(file_path).entry.action)
     # Delete Dir
     home_path = os.path.join(os.sep, utils.random_ascii())
     view.mkdir(home_path)
     self.assertEqual(LogEntry.MKDIR, view.paths.get(home_path).entry.action)
     view.delete(home_path)
     self.assertEqual(LogEntry.DELETE, view.get(home_path).entry.action)