testClientHandler.py 8.92 KB
Newer Older
Aurel's avatar
Aurel committed
1
#
Grégory Wisniewski's avatar
Grégory Wisniewski committed
2
# Copyright (C) 2009-2010  Nexedi SA
3
#
Aurel's avatar
Aurel committed
4 5 6 7
# This program 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 2
# of the License, or (at your option) any later version.
8
#
Aurel's avatar
Aurel committed
9 10 11 12 13 14 15
# This program 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 this program; if not, write to the Free Software
16
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
Aurel's avatar
Aurel committed
17

18 19 20
import unittest
from mock import Mock
from struct import pack, unpack
21
from .. import NeoUnitTestBase
22
from neo.lib.protocol import NodeTypes, NodeStates, Packets
23
from neo.master.handlers.client import ClientServiceHandler
24 25
from neo.master.app import Application

26
class MasterClientHandlerTests(NeoUnitTestBase):
27 28

    def setUp(self):
29
        NeoUnitTestBase.setUp(self)
30
        # create an application object
31
        config = self.getMasterConfiguration(master_number=1, replicas=1)
32
        self.app = Application(config)
33
        self.app.pt.clear()
34
        self.app.pt.setID(1)
35
        self.app.em = Mock()
Grégory Wisniewski's avatar
Grégory Wisniewski committed
36
        self.app.loid = '\0' * 8
37
        self.app.tm.setLastTID('\0' * 8)
38
        self.service = ClientServiceHandler(self.app)
39 40 41 42
        # define some variable to simulate client and storage node
        self.client_port = 11022
        self.storage_port = 10021
        self.master_port = 10010
43 44 45
        self.master_address = ('127.0.0.1', self.master_port)
        self.client_address = ('127.0.0.1', self.client_port)
        self.storage_address = ('127.0.0.1', self.storage_port)
46
        self.storage_uuid = self.getNewUUID()
47
        # register the storage
48 49 50 51
        self.app.nm.createStorage(
            uuid=self.storage_uuid,
            address=self.storage_address,
        )
52

53 54 55
    def getLastUUID(self):
        return self.uuid

56
    def identifyToMasterNode(self, node_type=NodeTypes.STORAGE, ip="127.0.0.1",
57
                             port=10021):
58 59
        """Do first step of identification to MN """
        # register the master itself
60
        uuid = self.getNewUUID()
61 62
        self.app.nm.createFromNodeType(
            node_type,
63
            address=(ip, port),
64
            uuid=uuid,
65
            state=NodeStates.RUNNING,
66
        )
67 68 69
        return uuid

    # Tests
70
    def test_07_askBeginTransaction(self):
71 72
        tid1 = self.getNextTID()
        tid2 = self.getNextTID()
73
        service = self.service
74 75 76 77
        tm_org = self.app.tm
        self.app.tm = tm = Mock({
            'begin': '\x00\x00\x00\x00\x00\x00\x00\x01',
        })
78
        # client call it
79
        client_uuid = self.identifyToMasterNode(node_type=NodeTypes.CLIENT, port=self.client_port)
80
        client_node = self.app.nm.getByUUID(client_uuid)
81
        conn = self.getFakeConnection(client_uuid, self.client_address)
82
        service.askBeginTransaction(conn, None)
83 84
        calls = tm.mockGetNamedCalls('begin')
        self.assertEqual(len(calls), 1)
85
        calls[0].checkArgs(client_node, None)
Grégory Wisniewski's avatar
Grégory Wisniewski committed
86
        self.checkAnswerBeginTransaction(conn)
87
        # Client asks for a TID
Grégory Wisniewski's avatar
Grégory Wisniewski committed
88
        conn = self.getFakeConnection(client_uuid, self.client_address)
89 90
        self.app.tm = tm_org
        service.askBeginTransaction(conn, tid1)
Grégory Wisniewski's avatar
Grégory Wisniewski committed
91 92
        calls = tm.mockGetNamedCalls('begin')
        self.assertEqual(len(calls), 1)
93
        calls[0].checkArgs(client_node, None)
Grégory Wisniewski's avatar
Grégory Wisniewski committed
94 95
        args = self.checkAnswerBeginTransaction(conn, decode=True)
        self.assertEqual(args, (tid1, ))
96

97
    def test_08_askNewOIDs(self):
98
        service = self.service
99 100
        oid1, oid2 = self.getOID(1), self.getOID(2)
        self.app.tm.setLastOID(oid1)
101
        # client call it
102
        client_uuid = self.identifyToMasterNode(node_type=NodeTypes.CLIENT, port=self.client_port)
103
        conn = self.getFakeConnection(client_uuid, self.client_address)
104 105 106
        for node in self.app.nm.getStorageList():
            conn = self.getFakeConnection(node.getUUID(), node.getAddress())
            node.setConnection(conn)
107
        service.askNewOIDs(conn, 1)
108 109 110
        self.assertTrue(self.app.tm.getLastOID() > oid1)
        for node in self.app.nm.getStorageList():
            conn = node.getConnection()
111
            self.assertEqual(self.checkNotifyLastOID(conn, decode=True), (oid2,))
112

113
    def test_09_askFinishTransaction(self):
114 115
        service = self.service
        # do the right job
116
        client_uuid = self.identifyToMasterNode(node_type=NodeTypes.CLIENT, port=self.client_port)
117
        storage_uuid = self.storage_uuid
118
        storage_conn = self.getFakeConnection(storage_uuid, self.storage_address)
119
        storage2_uuid = self.identifyToMasterNode(port=10022)
120 121 122
        storage2_conn = self.getFakeConnection(storage2_uuid,
            (self.storage_address[0], self.storage_address[1] + 1))
        self.app.setStorageReady(storage2_uuid)
123
        conn = self.getFakeConnection(client_uuid, self.client_address)
124 125
        self.app.pt = Mock({
            'getPartition': 0,
126 127 128 129 130
            'getCellList': [
                Mock({'getUUID': storage_uuid}),
                Mock({'getUUID': storage2_uuid}),
            ],
            'getPartitions': 2,
131
        })
132 133
        ttid = self.getNextTID()
        service.askBeginTransaction(conn, ttid)
134
        oid_list = []
135
        conn = self.getFakeConnection(client_uuid, self.client_address)
136
        self.app.nm.getByUUID(storage_uuid).setConnection(storage_conn)
137 138
        # No packet sent if storage node is not ready
        self.assertFalse(self.app.isStorageReady(storage_uuid))
139
        service.askFinishTransaction(conn, ttid, oid_list)
140
        self.checkNoPacketSent(storage_conn)
141
        self.app.tm.abortFor(self.app.nm.getByUUID(client_uuid))
142 143 144
        # ...but AskLockInformation is sent if it is ready
        self.app.setStorageReady(storage_uuid)
        self.assertTrue(self.app.isStorageReady(storage_uuid))
145
        service.askFinishTransaction(conn, ttid, oid_list)
146
        self.checkAskLockInformation(storage_conn)
147
        self.assertEqual(len(self.app.tm.registerForNotification(storage_uuid)), 1)
148
        txn = self.app.tm[ttid]
149
        pending_ttid = list(self.app.tm.registerForNotification(storage_uuid))[0]
150 151 152
        self.assertEqual(ttid, pending_ttid)
        self.assertEqual(len(txn.getOIDList()), 0)
        self.assertEqual(len(txn.getUUIDList()), 1)
153

154 155 156 157 158 159 160 161 162 163 164 165
    def test_askNodeInformations(self):
        # check that only informations about master and storages nodes are
        # send to a client
        self.app.nm.createClient()
        conn = self.getFakeConnection()
        self.service.askNodeInformation(conn)
        calls = conn.mockGetNamedCalls('notify')
        self.assertEqual(len(calls), 1)
        packet = calls[0].getParam(0)
        (node_list, ) = packet.decode()
        self.assertEqual(len(node_list), 2)

166
    def test_connectionClosed(self):
167
        # give a client uuid which have unfinished transactions
168
        client_uuid = self.identifyToMasterNode(node_type=NodeTypes.CLIENT,
169
                                                port = self.client_port)
170
        conn = self.getFakeConnection(client_uuid, self.client_address)
171
        self.app.listening_conn = object() # mark as running
172
        lptid = self.app.pt.getID()
173
        self.assertEqual(self.app.nm.getByUUID(client_uuid).getState(),
174
                NodeStates.RUNNING)
175
        self.service.connectionClosed(conn)
176
        # node must be have been remove, and no more transaction must remains
177 178
        self.assertEqual(self.app.nm.getByUUID(client_uuid), None)
        self.assertEqual(lptid, self.app.pt.getID())
179

180 181 182 183 184 185
    def test_askPack(self):
        self.assertEqual(self.app.packing, None)
        self.app.nm.createClient()
        tid = self.getNextTID()
        peer_id = 42
        conn = self.getFakeConnection(peer_id=peer_id)
186
        storage_uuid = self.storage_uuid
187 188 189 190 191 192 193 194 195 196 197 198
        storage_conn = self.getFakeConnection(storage_uuid,
            self.storage_address)
        self.app.nm.getByUUID(storage_uuid).setConnection(storage_conn)
        self.service.askPack(conn, tid)
        self.checkNoPacketSent(conn)
        ptid = self.checkAskPacket(storage_conn, Packets.AskPack,
            decode=True)[0]
        self.assertEqual(ptid, tid)
        self.assertTrue(self.app.packing[0] is conn)
        self.assertEqual(self.app.packing[1], peer_id)
        self.assertEqual(self.app.packing[2], set([storage_uuid, ]))
        # Asking again to pack will cause an immediate error
199
        storage_uuid = self.identifyToMasterNode(port=10022)
200 201 202 203 204 205 206 207
        storage_conn = self.getFakeConnection(storage_uuid,
            self.storage_address)
        self.app.nm.getByUUID(storage_uuid).setConnection(storage_conn)
        self.service.askPack(conn, tid)
        self.checkNoPacketSent(storage_conn)
        status = self.checkAnswerPacket(conn, Packets.AnswerPack,
            decode=True)[0]
        self.assertFalse(status)
208 209 210 211

if __name__ == '__main__':
    unittest.main()