Beispiel #1
0
class BasicTestCase(unittest.TestCase):
    """"""
    def setUp(self):
        self.store = storing.Store(stamp=0.0)
        self.timer = StoreTimer(store=self.store, duration=1.0)

        self.tempDirPath = tempfile.mkdtemp(prefix="raet",
                                            suffix="base",
                                            dir='/tmp')
        self.baseDirpath = os.path.join(self.tempDirPath, 'lane', 'keep')

        # main stack
        self.main = stacking.LaneStack(name='main',
                                       uid=1,
                                       lanename='cherry',
                                       sockdirpath=self.baseDirpath)

        #other stack
        self.other = stacking.LaneStack(name='other',
                                        uid=1,
                                        lanename='cherry',
                                        sockdirpath=self.baseDirpath)

    def tearDown(self):
        self.main.server.close()
        self.other.server.close()

    def service(self, duration=1.0, real=True):
        '''
        Utility method to service queues. Call from test method.
        '''
        self.timer.restart(duration=duration)
        while not self.timer.expired:
            self.other.serviceAll()
            self.main.serviceAll()
            self.store.advanceStamp(0.1)
            if real:
                time.sleep(0.1)

    def serviceOther(self, duration=1.0, real=True):
        '''
        Utility method to only service other queues. Call from test method.
        '''
        self.timer.restart(duration=duration)
        while not self.timer.expired:
            self.other.serviceAll()
            self.store.advanceStamp(0.1)
            if real:
                time.sleep(0.1)

    def serviceMain(self, duration=1.0, real=True):
        '''
        Utility method to only service main queues. Call from test method.
        '''
        self.timer.restart(duration=duration)
        while not self.timer.expired:
            self.main.serviceAll()
            self.store.advanceStamp(0.1)
            if real:
                time.sleep(0.1)

    def bootstrap(self, kind=raeting.packKinds.json):
        '''
        Basic messaging
        '''
        self.main.addRemote(
            yarding.RemoteYard(stack=self.main, ha=self.other.ha))
        self.other.addRemote(
            yarding.RemoteYard(stack=self.other, ha=self.main.ha))

        self.assertEqual(self.main.name, 'main')
        self.assertEqual(self.main.local.name, 'main')
        self.assertEqual(self.main.ha,
                         os.path.join(self.baseDirpath, 'cherry.main.uxd'))
        self.assertEqual(len(self.main.remotes), 1)
        remote = self.main.remotes.values()[0]
        self.assertEqual(remote.ha,
                         os.path.join(self.baseDirpath, 'cherry.other.uxd'))
        self.assertEqual(remote.name, 'other')
        self.assertTrue(remote.uid in self.main.remotes)
        self.assertTrue(remote.name in self.main.nameRemotes)
        self.assertTrue(remote.ha in self.main.haRemotes)
        self.assertIs(self.main.nameRemotes[remote.name], remote)
        self.assertIs(self.main.haRemotes[remote.ha], remote)

        self.assertEqual(self.other.name, 'other')
        self.assertEqual(self.other.local.name, 'other')
        self.assertEqual(self.other.ha,
                         os.path.join(self.baseDirpath, 'cherry.other.uxd'))
        self.assertEqual(len(self.other.remotes), 1)
        remote = self.other.remotes.values()[0]
        self.assertEqual(remote.ha,
                         os.path.join(self.baseDirpath, 'cherry.main.uxd'))
        self.assertEqual(remote.name, 'main')
        self.assertTrue(remote.uid in self.other.remotes)
        self.assertTrue(remote.name in self.other.nameRemotes)
        self.assertTrue(remote.ha in self.other.haRemotes)
        self.assertIs(self.other.nameRemotes[remote.name], remote)
        self.assertIs(self.other.haRemotes[remote.ha], remote)

        stacking.LaneStack.Pk = kind

    def message(self, mains, others, duration=1.0):
        '''
        Transmit and receive messages in mains and others lists
        '''
        for msg in mains:
            self.main.transmit(msg=msg)

        for msg in others:
            self.other.transmit(msg=msg)

        self.service(duration=duration)

        self.assertEqual(len(self.main.rxMsgs), len(others))
        for i, duple in enumerate(self.main.rxMsgs):
            console.terse("Yard '{0}' rxed:\n'{1}'\n".format(
                self.main.local.name, duple))
            self.assertDictEqual(others[i], duple[0])

        self.assertEqual(len(self.other.rxMsgs), len(mains))
        for i, duple in enumerate(self.other.rxMsgs):
            console.terse("Yard '{0}' rxed:\n'{1}'\n".format(
                self.other.local.name, duple))
            self.assertDictEqual(mains[i], duple[0])

    def createLaneData(self, name, uid, base, lanename):
        '''
        Creates odict and populates with data to setup lane stack
        {
            name: stack name
            dirpath: dirpath for keep files
            lanename: name of yard
        }
        '''
        data = odict()
        data['name'] = name
        data['uid'] = uid
        data['sockdirpath'] = os.path.join(base, name)
        data['lanename'] = lanename

        return data

    def createLaneStack(self, data, main=None):
        '''
        Creates stack and local yard from data
        returns stack

        '''
        stack = stacking.LaneStack(name=data['name'],
                                   uid=data['uid'],
                                   main=main,
                                   lanename=data['lanename'],
                                   sockdirpath=data['sockdirpath'])

        return stack

    def serviceMainOther(self, main, other, duration=1.0):
        '''
        Utility method to service queues. Call from test method.
        '''
        self.timer.restart(duration=duration)
        while not self.timer.expired:
            other.serviceAll()
            main.serviceAll()
            self.store.advanceStamp(0.1)
            time.sleep(0.1)

    def messageMainOther(self, main, other, mains, others, duration=1.0):
        '''
        Utility to send messages both ways
        '''
        for msg in mains:
            main.transmit(msg, duid=main.fetchUidByName(other.local.name))
        for msg in others:
            other.transmit(msg, duid=other.fetchUidByName(main.local.name))

        self.serviceMainOther(main, other, duration=duration)

        self.assertEqual(len(main.rxMsgs), len(others))
        for i, duple in enumerate(main.rxMsgs):
            console.terse("Yard '{0}' rxed:\n'{1}'\n".format(
                main.local.name, duple))
            self.assertDictEqual(others[i], duple[0])

        self.assertEqual(len(other.rxMsgs), len(mains))
        for i, duple in enumerate(other.rxMsgs):
            console.terse("Yard '{0}' rxed:\n'{1}'\n".format(
                other.local.name, duple))
            self.assertDictEqual(mains[i], duple[0])

    def serviceStackOneTx(self, stack):
        '''
        Utility method to service one packet on Tx queues. Call from test method.
        '''
        stack.serviceOneAllTx()
        time.sleep(0.1)
        self.store.advanceStamp(0.1)

    def serviceStackOneRx(self, stack):
        '''
        Utility method to service one packet on Rx queues. Call from test method.
        '''
        stack.serviceOneAllRx()
        time.sleep(0.1)
        self.store.advanceStamp(0.1)

    def serviceOneTx(self, main, other):
        '''
        Utility method to service one packet on Tx queues. Call from test method.
        '''
        other.serviceOneAllTx()
        main.serviceOneAllTx()
        time.sleep(0.1)
        self.store.advanceStamp(0.1)

    def serviceOneRx(self, main, other):
        '''
        Utility method to service one packet on Rx queues. Call from test method.
        '''
        other.serviceOneAllRx()
        main.serviceOneAllRx()
        time.sleep(0.1)
        self.store.advanceStamp(0.1)

    def serviceOneAll(self, main, other):
        '''
        Utility method to service one packet on all queues. Call from test method.
        '''
        self.serviceOneTx(main=main, other=other)
        self.serviceOneRx(main=main, other=other)

    def serviceStack(self, stack, duration=1.0):
        '''
        Utility method to service queues for one stack. Call from test method.
        '''
        self.timer.restart(duration=duration)
        while not self.timer.expired:
            stack.serviceAll()
            self.store.advanceStamp(0.1)
            time.sleep(0.1)

    def serviceStacks(self, stacks, duration=1.0):
        '''
        Utility method to service queues for list of stacks. Call from test method.
        '''
        self.timer.restart(duration=duration)
        while not self.timer.expired:
            for stack in stacks:
                stack.serviceAll()
            self.store.advanceStamp(0.1)
            time.sleep(0.1)

    def testMessageJson(self):
        '''
        Basic messaging with json packing
        '''
        console.terse("{0}\n".format(self.testMessageJson.__doc__))
        self.bootstrap(kind=raeting.packKinds.json)

        mains = []
        mains.append(
            odict(what="This is a message to the serf. Get to Work",
                  extra="Fix the fence."))

        others = []
        others.append(
            odict(what="This is a message to the lord. Let me be",
                  extra="Go away."))

        self.message(mains=mains, others=others)

    def testMessageMsgpack(self):
        '''
        Basic messaging with msgpack packing
        '''
        console.terse("{0}\n".format(self.testMessageMsgpack.__doc__))
        self.bootstrap(kind=raeting.packKinds.pack)

        mains = []
        mains.append(
            odict(what="This is a message to the serf. Get to Work",
                  extra="Fix the fence."))

        others = []
        others.append(
            odict(what="This is a message to the lord. Let me be",
                  extra="Go away."))

        self.message(mains=mains, others=others)

    def testMessageMultipleJson(self):
        '''
        Multiple messages with json packing
        '''
        console.terse("{0}\n".format(self.testMessageMultipleJson.__doc__))
        self.bootstrap(kind=raeting.packKinds.json)

        mains = []
        mains.append(odict([('house', "Mama mia1"), ('queue', "fix me")]))
        mains.append(odict([('house', "Mama mia2"), ('queue', "stop me")]))
        mains.append(odict([('house', "Mama mia3"), ('queue', "help me")]))
        mains.append(odict([('house', "Mama mia4"), ('queue', "run me")]))

        others = []
        others.append(odict([('house', "Papa pia1"), ('queue', "fix me")]))
        others.append(odict([('house', "Papa pia1"), ('queue', "stop me")]))
        others.append(odict([('house', "Papa pia1"), ('queue', "help me")]))
        others.append(odict([('house', "Papa pia1"), ('queue', "run me")]))

        self.message(mains=mains, others=others)

    def testMessageMultipleMsgpack(self):
        '''
        multiple messages with msgpack packing
        '''
        console.terse("{0}\n".format(self.testMessageMultipleMsgpack.__doc__))
        self.bootstrap(kind=raeting.packKinds.pack)

        mains = []
        mains.append(odict([('house', "Mama mia1"), ('queue', "fix me")]))
        mains.append(odict([('house', "Mama mia2"), ('queue', "stop me")]))
        mains.append(odict([('house', "Mama mia3"), ('queue', "help me")]))
        mains.append(odict([('house', "Mama mia4"), ('queue', "run me")]))

        others = []
        others.append(odict([('house', "Papa pia1"), ('queue', "fix me")]))
        others.append(odict([('house', "Papa pia1"), ('queue', "stop me")]))
        others.append(odict([('house', "Papa pia1"), ('queue', "help me")]))
        others.append(odict([('house', "Papa pia1"), ('queue', "run me")]))
        self.message(mains=mains, others=others)

    def testMessageSectionedJson(self):
        '''
        Sectioned messages with json packing
        '''
        console.terse("{0}\n".format(self.testMessageSectionedJson.__doc__))

        self.bootstrap(kind=raeting.packKinds.json)

        #big packets
        stuff = []
        for i in range(10000):
            stuff.append(str(i).rjust(10, " "))
        stuff = "".join(stuff)

        src = ['mayor', self.main.local.name, None]
        dst = ['citizen', self.other.local.name, None]
        route = odict([('src', src), ('dst', dst)])

        mains = []
        mains.append(odict([('route', route), ('content', stuff)]))

        src = ['citizen', self.other.local.name, None]
        dst = ['mayor', self.main.local.name, None]
        route = odict([('src', src), ('dst', dst)])

        others = []
        others.append(odict([('route', route), ('content', stuff)]))

        self.message(mains=mains, others=others, duration=2.0)

    def testMessageSectionedMsgpack(self):
        '''
        Sectioned messages with msgpack packing
        '''
        console.terse("{0}\n".format(self.testMessageSectionedMsgpack.__doc__))

        self.bootstrap(kind=raeting.packKinds.pack)

        #big packets
        stuff = []
        for i in range(10000):
            stuff.append(str(i).rjust(10, " "))
        stuff = "".join(stuff)

        src = ['mayor', self.main.local.name, None]
        dst = ['citizen', self.other.local.name, None]
        route = odict([('src', src), ('dst', dst)])

        mains = []
        mains.append(odict([('route', route), ('content', stuff)]))

        src = ['citizen', self.other.local.name, None]
        dst = ['mayor', self.main.local.name, None]
        route = odict([('src', src), ('dst', dst)])

        others = []
        others.append(odict([('route', route), ('content', stuff)]))

        self.message(mains=mains, others=others, duration=2.0)

    def testAutoAccept(self):
        '''
        Basic send auto accept message
        '''
        console.terse("{0}\n".format(self.testAutoAccept.__doc__))

        self.assertTrue(self.main.accept)

        # Don't add remote yard to main so only way to get message from other is
        # if auto acccept works
        self.other.addRemote(
            yarding.RemoteYard(stack=self.other, ha=self.main.ha))

        self.assertEqual(self.main.name, 'main')
        self.assertEqual(self.main.local.name, 'main')
        self.assertEqual(self.main.ha,
                         os.path.join(self.baseDirpath, 'cherry.main.uxd'))
        self.assertEqual(len(self.main.remotes), 0)

        self.assertEqual(self.other.name, 'other')
        self.assertEqual(self.other.local.name, 'other')
        self.assertEqual(self.other.ha,
                         os.path.join(self.baseDirpath, 'cherry.other.uxd'))
        self.assertEqual(len(self.other.remotes), 1)
        remote = self.other.remotes.values()[0]
        self.assertEqual(remote.ha,
                         os.path.join(self.baseDirpath, 'cherry.main.uxd'))
        self.assertEqual(remote.name, 'main')
        self.assertTrue(remote.uid in self.other.remotes)
        self.assertTrue(remote.name in self.other.nameRemotes)
        self.assertTrue(remote.ha in self.other.haRemotes)
        self.assertIs(self.other.nameRemotes[remote.name], remote)
        self.assertIs(self.other.haRemotes[remote.ha], remote)

        stacking.LaneStack.Pk = raeting.packKinds.pack

        others = []
        others.append(
            odict(what="This is a message to the lord. Let me be",
                  extra="Go away."))

        self.message(mains=[], others=others)

        self.assertEqual(len(self.main.remotes), 1)
        remote = self.main.remotes.values()[0]
        self.assertEqual(remote.ha,
                         os.path.join(self.baseDirpath, 'cherry.other.uxd'))
        self.assertEqual(remote.name, 'other')
        self.assertTrue(remote.uid in self.main.remotes)
        self.assertTrue(remote.name in self.main.nameRemotes)
        self.assertTrue(remote.ha in self.main.haRemotes)
        self.assertIs(self.main.nameRemotes[remote.name], remote)
        self.assertIs(self.main.haRemotes[remote.ha], remote)

        self.main.rxMsgs = deque()
        self.other.rxMsgs = deque()

        mains = []
        mains.append(
            odict(what="This is a message to the serf. Get to Work",
                  extra="Fix the fence."))

        self.message(mains=mains, others=[])

    def testAutoAcceptNot(self):
        '''
        Basic send non auto accept message
        '''
        console.terse("{0}\n".format(self.testAutoAcceptNot.__doc__))
        self.main.accept = False
        self.assertIs(self.main.accept, False)

        # Don't add remote yard to main so only way to get message from other is
        # if auto acccept works
        self.other.addRemote(
            yarding.RemoteYard(stack=self.other, ha=self.main.ha))

        self.assertEqual(self.main.name, 'main')
        self.assertEqual(self.main.local.name, 'main')
        self.assertEqual(self.main.ha,
                         os.path.join(self.baseDirpath, 'cherry.main.uxd'))
        self.assertEqual(len(self.main.remotes), 0)

        self.assertEqual(self.other.name, 'other')
        self.assertEqual(self.other.local.name, 'other')
        self.assertEqual(self.other.ha,
                         os.path.join(self.baseDirpath, 'cherry.other.uxd'))
        self.assertEqual(len(self.other.remotes), 1)
        remote = self.other.remotes.values()[0]
        self.assertEqual(remote.ha,
                         os.path.join(self.baseDirpath, 'cherry.main.uxd'))
        self.assertEqual(remote.name, 'main')

        self.assertTrue(remote.uid in self.other.remotes)
        self.assertTrue(remote.name in self.other.nameRemotes)
        self.assertTrue(remote.ha in self.other.haRemotes)
        self.assertIs(self.other.nameRemotes[remote.name], remote)
        self.assertIs(self.other.haRemotes[remote.ha], remote)

        stacking.LaneStack.Pk = raeting.packKinds.pack

        others = []
        others.append(
            odict(what="This is a message to the lord. Let me be",
                  extra="Go away."))

        for msg in others:
            self.other.transmit(msg=msg)

        self.service()

        self.assertEqual(len(self.main.rxMsgs), 0)
        self.assertEqual(len(self.main.remotes), 0)
        self.assertEqual(self.main.stats['unaccepted_source_yard'], 1)

    def testFetchRemoteFromHa(self):
        '''
        Fetching remote yard by HA
        '''
        console.terse("{0}\n".format(self.testFetchRemoteFromHa.__doc__))
        self.bootstrap(kind=raeting.packKinds.json)

        for remote in self.main.remotes.values():
            fetched = self.main.haRemotes.get(remote.ha)
            self.assertIs(remote, fetched)

        for remote in self.other.remotes.values():
            fetched = self.other.haRemotes.get(remote.ha)
            self.assertIs(remote, fetched)

    def testRestart(self):
        '''
        Test messaging after restart
        '''
        console.terse("{0}\n".format(self.testRestart.__doc__))

        stacking.LaneStack.Pk = raeting.packKinds.json

        mainData = self.createLaneData(name='main',
                                       uid=1,
                                       base=self.baseDirpath,
                                       lanename='apple')
        main = self.createLaneStack(data=mainData, main=True)
        self.assertTrue(main.ha.endswith('/lane/keep/main/apple.main.uxd'))
        self.assertTrue(main.main)

        otherData = self.createLaneData(name='other',
                                        uid=1,
                                        base=self.baseDirpath,
                                        lanename='apple')
        other = self.createLaneStack(data=otherData)
        self.assertTrue(other.ha.endswith('/lane/keep/other/apple.other.uxd'))

        main.addRemote(yarding.RemoteYard(stack=main, ha=other.ha))
        self.assertTrue('other' in main.nameRemotes)
        self.assertTrue(other.ha in main.haRemotes)
        other.addRemote(yarding.RemoteYard(stack=other, ha=main.ha))
        self.assertTrue('main' in other.nameRemotes)
        self.assertTrue(main.ha in other.haRemotes)

        src = ['mayor', main.local.name, None]  # (house, yard, queue)
        dst = ['citizen', other.local.name, None]
        route = odict([('src', src), ('dst', dst)])
        stuff = "This is my command"
        mains = []
        mains.append(odict([('route', route), ('content', stuff)]))

        src = ['citizen', other.local.name, None]
        dst = ['mayor', main.local.name, None]
        route = odict([('src', src), ('dst', dst)])
        stuff = "This is my reply."
        others = []
        others.append(odict([('route', route), ('content', stuff)]))

        self.messageMainOther(main, other, mains, others, duration=1.0)

        self.assertEqual(len(main.remotes), 1)
        self.assertTrue('other' in main.nameRemotes)
        self.assertEqual(len(other.remotes), 1)
        self.assertTrue('main' in other.nameRemotes)

        self.assertNotEqual(main.nameRemotes['other'].sid, 0)
        self.assertNotEqual(other.nameRemotes['main'].sid, 0)
        self.assertEqual(main.nameRemotes['other'].rsid,
                         other.nameRemotes['main'].sid)
        self.assertEqual(other.nameRemotes['main'].rsid,
                         main.nameRemotes['other'].sid)

        #now close down  make new stacks
        main.server.close()
        other.server.close()
        main = self.createLaneStack(data=mainData, main=True)
        other = self.createLaneStack(data=otherData)

        main.addRemote(yarding.RemoteYard(stack=main, ha=other.ha))
        self.assertTrue('other' in main.nameRemotes)
        other.addRemote(yarding.RemoteYard(stack=other, ha=main.ha))
        self.assertTrue('main' in other.nameRemotes)

        self.assertEqual(len(main.remotes), 1)
        self.assertEqual(len(other.remotes), 1)

        self.assertNotEqual(main.nameRemotes['other'].sid, 0)
        self.assertNotEqual(other.nameRemotes['main'].sid, 0)
        self.assertEqual(main.nameRemotes['other'].rsid, 0)
        self.assertEqual(other.nameRemotes['main'].rsid, 0)

        self.messageMainOther(main, other, mains, others, duration=1.0)

        self.assertEqual(main.nameRemotes['other'].rsid,
                         other.nameRemotes['main'].sid)
        self.assertEqual(other.nameRemotes['main'].rsid,
                         main.nameRemotes['other'].sid)

        #now close down  make new stacks
        main.server.close()
        other.server.close()
        main = self.createLaneStack(data=mainData, main=True)
        other = self.createLaneStack(data=otherData)

        main.addRemote(yarding.RemoteYard(stack=main, ha=other.ha))
        self.assertTrue('other' in main.nameRemotes)
        other.addRemote(yarding.RemoteYard(stack=other, ha=main.ha))
        self.assertTrue('main' in other.nameRemotes)

        self.assertEqual(len(main.remotes), 1)
        self.assertEqual(len(other.remotes), 1)

        self.assertNotEqual(main.nameRemotes['other'].sid, 0)
        self.assertNotEqual(other.nameRemotes['main'].sid, 0)
        self.assertEqual(main.nameRemotes['other'].rsid, 0)
        self.assertEqual(other.nameRemotes['main'].rsid, 0)

        # now send paginated messages
        src = ['mayor', main.local.name, None]  # (house, yard, queue)
        dst = ['citizen', other.local.name, None]
        route = odict([('src', src), ('dst', dst)])
        stuff = ["Do as I say."]
        for i in range(10000):
            stuff.append(str(i).rjust(10, " "))
        stuff = "".join(stuff)
        mains = []
        mains.append(odict([('route', route), ('content', stuff)]))

        src = ['citizen', other.local.name, None]
        dst = ['mayor', main.local.name, None]
        route = odict([('src', src), ('dst', dst)])
        stuff = ["As you wish."]
        for i in range(10000):
            stuff.append(str(i).rjust(10, " "))
        stuff = "".join(stuff)
        others = []
        others.append(odict([('route', route), ('content', stuff)]))

        self.messageMainOther(main, other, mains, others, duration=1.0)

        self.assertEqual(main.nameRemotes['other'].rsid,
                         other.nameRemotes['main'].sid)
        self.assertEqual(other.nameRemotes['main'].rsid,
                         main.nameRemotes['other'].sid)

        #now close down  make new stacks send page at a time
        main.server.close()
        other.server.close()
        main = self.createLaneStack(data=mainData, main=True)
        other = self.createLaneStack(data=otherData)

        main.addRemote(yarding.RemoteYard(stack=main, ha=other.ha))
        self.assertTrue('other' in main.nameRemotes)
        other.addRemote(yarding.RemoteYard(stack=other, ha=main.ha))
        self.assertTrue('main' in other.nameRemotes)

        self.assertEqual(len(main.remotes), 1)
        self.assertEqual(len(other.remotes), 1)

        self.assertNotEqual(main.nameRemotes['other'].sid, 0)
        self.assertNotEqual(other.nameRemotes['main'].sid, 0)
        self.assertEqual(main.nameRemotes['other'].rsid, 0)
        self.assertEqual(other.nameRemotes['main'].rsid, 0)

        for msg in mains:
            main.transmit(msg, duid=main.fetchUidByName(other.local.name))
        for msg in others:
            other.transmit(msg, duid=other.fetchUidByName(main.local.name))

        self.assertEqual(len(main.txMsgs), 1)
        self.assertEqual(len(other.txMsgs), 1)
        self.assertEqual(len(main.nameRemotes['other'].books), 0)
        self.assertEqual(len(other.nameRemotes['main'].books), 0)
        self.assertEqual(len(main.rxMsgs), 0)
        self.assertEqual(len(other.rxMsgs), 0)

        # Now only send and receive one page to/from each side
        self.serviceOneAll(main, other)

        self.assertEqual(len(main.txMsgs), 0)
        self.assertEqual(len(other.txMsgs), 0)
        self.assertEqual(len(main.txes), 1)
        self.assertEqual(len(other.txes), 1)
        self.assertEqual(len(main.nameRemotes['other'].books), 1)
        self.assertEqual(len(other.nameRemotes['main'].books), 1)
        self.assertEqual(len(main.rxMsgs), 0)
        self.assertEqual(len(other.rxMsgs), 0)

        self.assertEqual(main.nameRemotes['other'].rsid,
                         other.nameRemotes['main'].sid)
        self.assertEqual(other.nameRemotes['main'].rsid,
                         main.nameRemotes['other'].sid)

        # save sids
        mainSid = main.nameRemotes['other'].sid
        otherSid = other.nameRemotes['main'].sid

        #now close down one side only, make new stack
        main.server.close()
        main = self.createLaneStack(data=mainData, main=True)
        main.addRemote(yarding.RemoteYard(stack=main, ha=other.ha))

        self.assertEqual(len(main.remotes), 1)
        self.assertEqual(len(other.remotes), 1)

        self.assertNotEqual(main.nameRemotes['other'].sid, mainSid)
        self.assertEqual(other.nameRemotes['main'].sid, otherSid)
        self.assertEqual(main.nameRemotes['other'].rsid, 0)
        self.assertEqual(other.nameRemotes['main'].rsid, mainSid)

        self.assertEqual(len(main.txes), 0)
        self.assertEqual(len(other.txes), 1)
        self.assertEqual(len(main.nameRemotes['other'].books), 0)
        self.assertEqual(len(other.nameRemotes['main'].books), 1)
        self.assertEqual(len(main.rxMsgs), 0)
        self.assertEqual(len(other.rxMsgs), 0)

        # Now remaining page from other (there should be no pages from main)
        self.serviceOneAll(main, other)

        self.assertEqual(main.nameRemotes['other'].rsid,
                         other.nameRemotes['main'].sid)
        self.assertNotEqual(other.nameRemotes['main'].rsid,
                            main.nameRemotes['other'].sid)

        self.assertEqual(len(main.txes), 0)
        self.assertEqual(len(other.txes), 0)
        self.assertEqual(len(main.nameRemotes['other'].books), 0)
        self.assertEqual(len(other.nameRemotes['main'].books), 1)
        self.assertEqual(len(main.rxMsgs), 0)
        self.assertEqual(len(other.rxMsgs), 0)
        self.assertEqual(main.stats['missed_page'], 1)

        #send a new message from main and reap stale book from other
        for msg in mains:
            main.transmit(msg, duid=main.fetchUidByName(other.local.name))

        self.serviceMainOther(main, other, duration=1.0)

        self.assertEqual(main.nameRemotes['other'].rsid,
                         other.nameRemotes['main'].sid)
        self.assertEqual(other.nameRemotes['main'].rsid,
                         main.nameRemotes['other'].sid)
        self.assertEqual(len(main.txes), 0)
        self.assertEqual(len(other.txes), 0)
        self.assertEqual(len(main.nameRemotes['other'].books), 0)
        self.assertEqual(len(other.nameRemotes['main'].books), 0)
        self.assertEqual(len(main.rxMsgs), 0)
        self.assertEqual(len(main.rxMsgs), 0)
        self.assertEqual(len(other.rxMsgs), 1)
        self.assertEqual(other.stats['stale_book'], 1)

        self.assertEqual(len(other.rxMsgs), len(mains))
        for i, duple in enumerate(other.rxMsgs):
            console.terse("Yard '{0}' rxed:\n'{1}'\n".format(
                other.local.name, duple))
            self.assertDictEqual(mains[i], duple[0])

        # setup to test reset sid numbering by sending single pages to create stale books

        other.rxMsgs.pop()
        for msg in mains:
            main.transmit(msg, duid=main.fetchUidByName(other.local.name))
        for msg in others:
            other.transmit(msg, duid=other.fetchUidByName(main.local.name))

        self.serviceOneAll(main, other)

        self.assertEqual(main.nameRemotes['other'].rsid,
                         other.nameRemotes['main'].sid)
        self.assertEqual(other.nameRemotes['main'].rsid,
                         main.nameRemotes['other'].sid)

        self.assertEqual(len(main.txes), 1)
        self.assertEqual(len(other.txes), 1)
        self.assertEqual(len(main.nameRemotes['other'].books), 1)
        self.assertEqual(len(other.nameRemotes['main'].books), 1)
        self.assertEqual(len(main.rxMsgs), 0)
        self.assertEqual(len(other.rxMsgs), 0)

        # simulate restart that loses msg in queue
        main.txes.pop()
        other.txes.pop()

        src = ['mayor', main.local.name, None]  # (house, yard, queue)
        dst = ['citizen', other.local.name, None]
        route = odict([('src', src), ('dst', dst)])
        stuff = "This is my command"
        mains = []
        mains.append(odict([('route', route), ('content', stuff)]))

        src = ['citizen', other.local.name, None]
        dst = ['mayor', main.local.name, None]
        route = odict([('src', src), ('dst', dst)])
        stuff = "This is my reply."
        others = []
        others.append(odict([('route', route), ('content', stuff)]))

        mainSid = main.local.nextSid()
        otherSid = other.local.nextSid()
        main.nameRemotes['other'].sid = mainSid
        other.nameRemotes['main'].sid = otherSid
        for msg in mains:
            main.transmit(msg, duid=main.fetchUidByName(other.local.name))
        for msg in others:
            other.transmit(msg, duid=other.fetchUidByName(main.local.name))

        self.serviceOneAll(main, other)

        self.assertEqual(main.nameRemotes['other'].sid, mainSid)
        self.assertEqual(other.nameRemotes['main'].sid, otherSid)
        self.assertEqual(main.nameRemotes['other'].rsid, otherSid)
        self.assertEqual(other.nameRemotes['main'].rsid, mainSid)

        self.assertEqual(len(main.txes), 0)
        self.assertEqual(len(other.txes), 0)
        self.assertEqual(len(main.nameRemotes['other'].books), 0)
        self.assertEqual(len(other.nameRemotes['main'].books), 0)
        self.assertEqual(len(main.rxMsgs), 1)
        self.assertEqual(len(other.rxMsgs), 1)
        self.assertEqual(main.stats['stale_book'], 1)
        self.assertEqual(other.stats['stale_book'], 2)

        main.server.close()
        other.server.close()
Beispiel #2
0
class BasicTestCase(unittest.TestCase):
    """"""

    def setUp(self):
        self.store = storing.Store(stamp=0.0)

        dirpathBase='/tmp/raet/'

        #main stack
        mainName = "main"
        mainDirpath = os.path.join(dirpathBase, 'road', 'keep', mainName)
        signer = nacling.Signer()
        mainSignKeyHex = signer.keyhex
        privateer = nacling.Privateer()
        mainPriKeyHex = privateer.keyhex


        #other stack
        otherName = "other"
        otherDirpath = os.path.join(dirpathBase, 'road', 'keep', otherName)
        signer = nacling.Signer()
        otherSignKeyHex = signer.keyhex
        privateer = nacling.Privateer()
        otherPriKeyHex = privateer.keyhex


        keeping.clearAllKeepSafe(mainDirpath)
        keeping.clearAllKeepSafe(otherDirpath)

        local = estating.LocalEstate(eid=1,
                                     name=mainName,
                                     sigkey=mainSignKeyHex,
                                     prikey=mainPriKeyHex,)

        self.main = stacking.RoadStack(name=mainName,
                                         local=local,
                                         auto=True,
                                         main=True,
                                         dirpath=mainDirpath,
                                         store=self.store)

        local = estating.LocalEstate(eid=0,
                                     name=otherName,
                                     ha=("", raeting.RAET_TEST_PORT),
                                     sigkey=otherSignKeyHex,
                                     prikey=otherPriKeyHex,)

        self.other = stacking.RoadStack(name=otherName,
                                         local=local,
                                         dirpath=otherDirpath,
                                         store=self.store)

        self.timer = StoreTimer(store=self.store, duration=1.0)

    def tearDown(self):
        self.main.server.close()
        self.other.server.close()

        self.main.clearLocal()
        self.main.clearRemoteKeeps()
        self.other.clearLocal()
        self.other.clearRemoteKeeps()


    def join(self):
        '''
        Utility method to do join. Call from test method.
        '''
        console.terse("\nJoin Transaction **************\n")
        self.other.join()
        self.service()

    def allow(self):
        '''
        Utility method to do allow. Call from test method.
        '''
        console.terse("\nAllow Transaction **************\n")
        self.other.allow()
        self.service()

    def service(self, duration=1.0):
        '''
        Utility method to service queues. Call from test method.
        '''
        self.timer.restart(duration=duration)
        while not self.timer.expired:
            self.other.serviceAll()
            self.main.serviceAll()
            if not (self.main.transactions or self.other.transactions):
                break
            self.store.advanceStamp(0.1)
            time.sleep(0.1)


    def bootstrap(self, bk=raeting.bodyKinds.json):
        '''
        Initialize
            main on port 7530 with eid of 1
            other on port 7531 with eid of 0
        Complete
            main eid of 1 joined and allowed
            other eid of 2 joined and allowed
        '''
        stacking.RoadStack.Bk = bk

        self.join()
        console.terse("\nStack '{0}' uid= {1}\n".format(self.main.name, self.main.local.uid))
        self.assertEqual(self.main.local.uid, 1)
        self.assertEqual(self.main.name, 'main')
        self.assertEqual(len(self.main.transactions), 0)
        remote = self.main.remotes.values()[0]
        self.assertTrue(remote.joined)
        self.assertEqual(remote.uid, 2)
        self.assertTrue(2 in self.main.remotes)
        self.assertTrue(len(self.main.uids), 1)
        self.assertTrue(len(self.main.remotes), 1)
        self.assertEqual(remote.name, 'other')
        self.assertTrue('other' in self.main.uids)
        console.terse("Stack '{0}' estate name '{1}' joined with '{2}' = {3}\n".format(
                self.main.name, self.main.local.name, remote.name, remote.joined))

        console.terse("\nStack '{0}' uid= {1}\n".format(self.other.name, self.other.local.uid))
        self.assertEqual(self.other.local.uid, 2)
        self.assertEqual(self.other.name, 'other')
        self.assertEqual(len(self.other.transactions), 0)
        remote = self.other.remotes.values()[0]
        self.assertTrue(remote.joined)
        self.assertEqual(remote.uid, 1)
        self.assertTrue(1 in self.other.remotes)
        self.assertTrue(len(self.other.uids), 1)
        self.assertTrue(len(self.other.remotes), 1)
        self.assertEqual(remote.name, 'main')
        self.assertTrue('main' in self.other.uids)
        console.terse("Stack '{0}' estate name '{1}' joined with '{2}' = {3}\n".format(
                self.other.name, self.other.local.name, remote.name, remote.joined))

        self.allow()
        console.terse("\nStack '{0}' uid= {1}\n".format(self.main.name, self.main.local.uid))
        self.assertEqual(self.main.local.uid, 1)
        self.assertEqual(self.main.name, 'main')
        self.assertEqual(len(self.main.transactions), 0)
        remote = self.main.remotes.values()[0]
        self.assertTrue(remote.allowed)
        self.assertEqual(remote.uid, 2)
        self.assertTrue(2 in self.main.remotes)
        self.assertTrue(len(self.main.uids), 1)
        self.assertTrue(len(self.main.remotes), 1)
        self.assertEqual(remote.name, 'other')
        self.assertTrue('other' in self.main.uids)
        console.terse("Stack '{0}' estate name '{1}' allowd with '{2}' = {3}\n".format(
                self.main.name, self.main.local.name, remote.name, remote.allowed))

        console.terse("\nStack '{0}' uid= {1}\n".format(self.other.name, self.other.local.uid))
        self.assertEqual(self.other.local.uid, 2)
        self.assertEqual(self.other.name, 'other')
        self.assertEqual(len(self.other.transactions), 0)
        remote = self.other.remotes.values()[0]
        self.assertTrue(remote.allowed)
        self.assertEqual(remote.uid, 1)
        self.assertTrue(1 in self.other.remotes)
        self.assertTrue(len(self.other.uids), 1)
        self.assertTrue(len(self.other.remotes), 1)
        self.assertEqual(remote.name, 'main')
        self.assertTrue('main' in self.other.uids)
        console.terse("Stack '{0}' estate name '{1}' allowed with '{2}' = {3}\n".format(
                self.other.name, self.other.local.name, remote.name, remote.allowed))

        console.terse("\nMessage: other to main *********\n")
        body = odict(what="This is a message to the main estate. How are you", extra="I am fine.")
        self.other.txMsgs.append((body, self.main.local.uid))
        #self.other.message(body=body, deid=self.main.local.uid)
        self.service()

        console.terse("\nStack '{0}' uid= {1}\n".format(self.main.name, self.main.local.uid))
        self.assertEqual(len(self.main.transactions), 0)
        for msg in self.main.rxMsgs:
            console.terse("Estate '{0}' rxed:\n'{1}'\n".format(self.main.local.name, msg))
        self.assertDictEqual(body, self.main.rxMsgs[0])

        console.terse("\nMessage: main to other *********\n")
        body = odict(what="This is a message to the other estate. Get to Work", extra="Fix the fence.")
        self.main.txMsgs.append((body, self.other.local.uid))
        #self.main.message(body=body, deid=self.other.local.uid)
        self.service()

        console.terse("\nStack '{0}' uid= {1}\n".format(self.other.name, self.other.local.uid))
        self.assertEqual(len(self.other.transactions), 0)
        for msg in self.other.rxMsgs:
            console.terse("Estate '{0}' rxed:\n'{1}'\n".format(self.other.local.name, msg))
        self.assertDictEqual(body, self.other.rxMsgs[0])

    def bidirectional(self, bk=raeting.bodyKinds.json, mains=None, others=None, duration=3.0):
        '''
        Initialize
            main on port 7530 with eid of 1
            other on port 7531 with eid of 0
        Complete
            main eid of 1 joined and allowed
            other eid of 2 joined and allowed
        '''
        stacking.RoadStack.Bk = bk
        mains = mains or []
        other = others or []

        self.join()
        self.assertEqual(len(self.main.transactions), 0)
        remote = self.main.remotes.values()[0]
        self.assertTrue(remote.joined)
        self.assertEqual(len(self.other.transactions), 0)
        remote = self.other.remotes.values()[0]
        self.assertTrue(remote.joined)

        self.allow()
        self.assertEqual(len(self.main.transactions), 0)
        remote = self.main.remotes.values()[0]
        self.assertTrue(remote.allowed)
        self.assertEqual(len(self.other.transactions), 0)
        remote = self.other.remotes.values()[0]
        self.assertTrue(remote.allowed)

        console.terse("\nMessages Bidirectional *********\n")
        for msg in mains:
            self.main.transmit(msg)
            #self.main.txMsgs.append((msg, None))
            #self.main.message(body=msg, deid=self.other.local.uid)
        for msg in others:
            self.other.transmit(msg)
            #self.other.txMsgs.append((msg, None))
            #self.other.message(body=msg, deid=self.main.local.uid)

        self.service(duration=duration)

        console.terse("\nStack '{0}' uid= {1}\n".format(self.main.name, self.main.local.uid))
        self.assertEqual(len(self.main.transactions), 0)
        self.assertEqual(len(others), len(self.main.rxMsgs))
        for i, msg in enumerate(self.main.rxMsgs):
            console.terse("Estate '{0}' rxed:\n'{1}'\n".format(self.main.local.name, msg))
            self.assertDictEqual(others[i], msg)

        console.terse("\nStack '{0}' uid= {1}\n".format(self.other.name, self.other.local.uid))
        self.assertEqual(len(self.other.transactions), 0)
        self.assertEqual(len(mains), len(self.other.rxMsgs))
        for i, msg in enumerate(self.other.rxMsgs):
            console.terse("Estate '{0}' rxed:\n'{1}'\n".format(self.other.local.name, msg))
            self.assertDictEqual(mains[i], msg)

    def testBootstrapJson(self):
        '''
        Test join allow message transactions with JSON Serialization of body
        '''
        console.terse("{0}\n".format(self.testBootstrapJson.__doc__))
        self.bootstrap(bk=raeting.bodyKinds.json)

    def testBootstrapMsgBack(self):
        '''
        Test join allow message transactions with MsgPack Serialization of body
        '''
        console.terse("{0}\n".format(self.testBootstrapMsgBack.__doc__))
        self.bootstrap(bk=raeting.bodyKinds.msgpack)

    def testMsgBothwaysJson(self):
        '''
        Test message transactions
        '''
        console.terse("{0}\n".format(self.testMsgBothwaysJson.__doc__))

        others = []
        others.append(odict(house="Mama mia1", queue="fix me"))
        others.append(odict(house="Mama mia2", queue="help me"))
        others.append(odict(house="Mama mia3", queue="stop me"))
        others.append(odict(house="Mama mia4", queue="run me"))

        mains = []
        mains.append(odict(house="Papa pia1", queue="fix me"))
        mains.append(odict(house="Papa pia2", queue="help me"))
        mains.append(odict(house="Papa pia3", queue="stop me"))
        mains.append(odict(house="Papa pia4", queue="run me"))

        self.bidirectional(bk=raeting.bodyKinds.json, mains=mains, others=others)

    def testMsgBothwaysMsgpack(self):
        '''
        Test message transactions
        '''
        console.terse("{0}\n".format(self.testMsgBothwaysMsgpack.__doc__))

        others = []
        others.append(odict(house="Mama mia1", queue="fix me"))
        others.append(odict(house="Mama mia2", queue="help me"))
        others.append(odict(house="Mama mia3", queue="stop me"))
        others.append(odict(house="Mama mia4", queue="run me"))

        mains = []
        mains.append(odict(house="Papa pia1", queue="fix me"))
        mains.append(odict(house="Papa pia2", queue="help me"))
        mains.append(odict(house="Papa pia3", queue="stop me"))
        mains.append(odict(house="Papa pia4", queue="run me"))

        self.bidirectional(bk=raeting.bodyKinds.msgpack, mains=mains, others=others)

    def testSegmentedJson(self):
        '''
        Test segmented message transactions
        '''
        console.terse("{0}\n".format(self.testSegmentedJson.__doc__))

        stuff = []
        for i in range(300):
            stuff.append(str(i).rjust(10, " "))
        stuff = "".join(stuff)

        others = []
        mains = []
        others.append(odict(house="Snake eyes", queue="near stuff", stuff=stuff))
        mains.append(odict(house="Craps", queue="far stuff", stuff=stuff))

        bloat = []
        for i in range(300):
            bloat.append(str(i).rjust(100, " "))
        bloat = "".join(bloat)
        others.append(odict(house="Other", queue="big stuff", bloat=bloat))
        mains.append(odict(house="Main", queue="gig stuff", bloat=bloat))

        self.bidirectional(bk=raeting.bodyKinds.json, mains=mains, others=others)

    def testSegmentedMsgpack(self):
        '''
        Test segmented message transactions
        '''
        console.terse("{0}\n".format(self.testSegmentedJson.__doc__))

        stuff = []
        for i in range(300):
            stuff.append(str(i).rjust(10, " "))
        stuff = "".join(stuff)

        others = []
        mains = []
        others.append(odict(house="Snake eyes", queue="near stuff", stuff=stuff))
        mains.append(odict(house="Craps", queue="far stuff", stuff=stuff))

        bloat = []
        for i in range(300):
            bloat.append(str(i).rjust(100, " "))
        bloat = "".join(bloat)
        others.append(odict(house="Other", queue="big stuff", bloat=bloat))
        mains.append(odict(house="Main", queue="gig stuff", bloat=bloat))

        self.bidirectional(bk=raeting.bodyKinds.msgpack, mains=mains, others=others)
Beispiel #3
0
class BasicTestCase(unittest.TestCase):
    """"""
    def setUp(self):
        self.store = storing.Store(stamp=0.0)
        self.timer = StoreTimer(store=self.store, duration=1.0)

        self.baseDirpath = os.path.join(
            tempfile.mkdtemp(prefix="raet", suffix="base", dir='/tmp'), 'lane',
            'keep')

        # main stack
        self.main = stacking.LaneStack(name='main',
                                       yid=1,
                                       localname='main',
                                       lanename='cherry',
                                       basedirpath=self.baseDirpath,
                                       sockdirpath=self.baseDirpath)

        #other stack
        self.other = stacking.LaneStack(name='other',
                                        yid=1,
                                        localname='other',
                                        lanename='cherry',
                                        basedirpath=self.baseDirpath,
                                        sockdirpath=self.baseDirpath)

    def tearDown(self):
        self.main.server.close()
        self.other.server.close()

        if os.path.exists(self.baseDirpath):
            shutil.rmtree(self.baseDirpath)

    def service(self, duration=1.0, real=True):
        '''
        Utility method to service queues. Call from test method.
        '''
        self.timer.restart(duration=duration)
        while not self.timer.expired:
            self.other.serviceAll()
            self.main.serviceAll()
            self.store.advanceStamp(0.1)
            if real:
                time.sleep(0.1)

    def serviceOther(self, duration=1.0, real=True):
        '''
        Utility method to only service other queues. Call from test method.
        '''
        self.timer.restart(duration=duration)
        while not self.timer.expired:
            self.other.serviceAll()
            self.store.advanceStamp(0.1)
            if real:
                time.sleep(0.1)

    def serviceMain(self, duration=1.0, real=True):
        '''
        Utility method to only service main queues. Call from test method.
        '''
        self.timer.restart(duration=duration)
        while not self.timer.expired:
            self.main.serviceAll()
            self.store.advanceStamp(0.1)
            if real:
                time.sleep(0.1)

    def bootstrap(self, kind=raeting.packKinds.json):
        '''
        Basic messaging
        '''
        self.main.addRemote(
            yarding.RemoteYard(stack=self.main, ha=self.other.local.ha))
        self.other.addRemote(
            yarding.RemoteYard(stack=self.other, ha=self.main.local.ha))

        self.assertEqual(self.main.name, 'main')
        self.assertEqual(self.main.local.name, 'main')
        self.assertEqual(self.main.local.ha,
                         os.path.join(self.baseDirpath, 'cherry.main.uxd'))
        self.assertEqual(len(self.main.remotes), 1)
        remote = self.main.remotes.values()[0]
        self.assertEqual(remote.ha,
                         os.path.join(self.baseDirpath, 'cherry.other.uxd'))
        self.assertEqual(remote.name, 'other')
        self.assertTrue(remote.uid in self.main.remotes)
        self.assertTrue(remote.name in self.main.uids)
        self.assertIs(self.main.remotes[self.main.uids[remote.name]], remote)

        self.assertEqual(self.other.name, 'other')
        self.assertEqual(self.other.local.name, 'other')
        self.assertEqual(self.other.local.ha,
                         os.path.join(self.baseDirpath, 'cherry.other.uxd'))
        self.assertEqual(len(self.other.remotes), 1)
        remote = self.other.remotes.values()[0]
        self.assertEqual(remote.ha,
                         os.path.join(self.baseDirpath, 'cherry.main.uxd'))
        self.assertEqual(remote.name, 'main')
        self.assertTrue(remote.uid in self.other.remotes)
        self.assertTrue(remote.name in self.other.uids)
        self.assertIs(self.other.remotes[self.other.uids[remote.name]], remote)

        stacking.LaneStack.Pk = kind

    def message(self, mains, others, duration=1.0):
        '''
        Transmit and receive messages in mains and others lists
        '''
        for msg in mains:
            self.main.transmit(msg=msg)

        for msg in others:
            self.other.transmit(msg=msg)

        self.service(duration=duration)

        self.assertEqual(len(self.main.rxMsgs), len(others))
        for i, msg in enumerate(self.main.rxMsgs):
            console.terse("Yard '{0}' rxed:\n'{1}'\n".format(
                self.main.local.name, msg))
            self.assertDictEqual(others[i], msg)

        self.assertEqual(len(self.other.rxMsgs), len(mains))
        for i, msg in enumerate(self.other.rxMsgs):
            console.terse("Yard '{0}' rxed:\n'{1}'\n".format(
                self.other.local.name, msg))
            self.assertDictEqual(mains[i], msg)

    def testMessageJson(self):
        '''
        Basic messaging with json packing
        '''
        console.terse("{0}\n".format(self.testMessageJson.__doc__))
        self.bootstrap(kind=raeting.packKinds.json)

        mains = []
        mains.append(
            odict(what="This is a message to the serf. Get to Work",
                  extra="Fix the fence."))

        others = []
        others.append(
            odict(what="This is a message to the lord. Let me be",
                  extra="Go away."))

        self.message(mains=mains, others=others)

    def testMessageMsgpack(self):
        '''
        Basic messaging with msgpack packing
        '''
        console.terse("{0}\n".format(self.testMessageMsgpack.__doc__))
        self.bootstrap(kind=raeting.packKinds.pack)

        mains = []
        mains.append(
            odict(what="This is a message to the serf. Get to Work",
                  extra="Fix the fence."))

        others = []
        others.append(
            odict(what="This is a message to the lord. Let me be",
                  extra="Go away."))

        self.message(mains=mains, others=others)

    def testMessageMultipleJson(self):
        '''
        Multiple messages with json packing
        '''
        console.terse("{0}\n".format(self.testMessageMultipleJson.__doc__))
        self.bootstrap(kind=raeting.packKinds.json)

        mains = []
        mains.append(odict([('house', "Mama mia1"), ('queue', "fix me")]))
        mains.append(odict([('house', "Mama mia2"), ('queue', "stop me")]))
        mains.append(odict([('house', "Mama mia3"), ('queue', "help me")]))
        mains.append(odict([('house', "Mama mia4"), ('queue', "run me")]))

        others = []
        others.append(odict([('house', "Papa pia1"), ('queue', "fix me")]))
        others.append(odict([('house', "Papa pia1"), ('queue', "stop me")]))
        others.append(odict([('house', "Papa pia1"), ('queue', "help me")]))
        others.append(odict([('house', "Papa pia1"), ('queue', "run me")]))

        self.message(mains=mains, others=others)

    def testMessageMultipleMsgpack(self):
        '''
        multiple messages with msgpack packing
        '''
        console.terse("{0}\n".format(self.testMessageMultipleMsgpack.__doc__))
        self.bootstrap(kind=raeting.packKinds.pack)

        mains = []
        mains.append(odict([('house', "Mama mia1"), ('queue', "fix me")]))
        mains.append(odict([('house', "Mama mia2"), ('queue', "stop me")]))
        mains.append(odict([('house', "Mama mia3"), ('queue', "help me")]))
        mains.append(odict([('house', "Mama mia4"), ('queue', "run me")]))

        others = []
        others.append(odict([('house', "Papa pia1"), ('queue', "fix me")]))
        others.append(odict([('house', "Papa pia1"), ('queue', "stop me")]))
        others.append(odict([('house', "Papa pia1"), ('queue', "help me")]))
        others.append(odict([('house', "Papa pia1"), ('queue', "run me")]))
        self.message(mains=mains, others=others)

    def testMessageSectionedJson(self):
        '''
        Sectioned messages with json packing
        '''
        console.terse("{0}\n".format(self.testMessageSectionedJson.__doc__))

        self.bootstrap(kind=raeting.packKinds.json)

        #big packets
        stuff = []
        for i in range(10000):
            stuff.append(str(i).rjust(10, " "))
        stuff = "".join(stuff)

        src = ['mayor', self.main.local.name, None]
        dst = ['citizen', self.other.local.name, None]
        route = odict([('src', src), ('dst', dst)])

        mains = []
        mains.append(odict([('route', route), ('content', stuff)]))

        src = ['citizen', self.other.local.name, None]
        dst = ['mayor', self.main.local.name, None]
        route = odict([('src', src), ('dst', dst)])

        others = []
        others.append(odict([('route', route), ('content', stuff)]))

        self.message(mains=mains, others=others, duration=2.0)

    def testMessageSectionedMsgpack(self):
        '''
        Sectioned messages with msgpack packing
        '''
        console.terse("{0}\n".format(self.testMessageSectionedMsgpack.__doc__))

        self.bootstrap(kind=raeting.packKinds.pack)

        #big packets
        stuff = []
        for i in range(10000):
            stuff.append(str(i).rjust(10, " "))
        stuff = "".join(stuff)

        src = ['mayor', self.main.local.name, None]
        dst = ['citizen', self.other.local.name, None]
        route = odict([('src', src), ('dst', dst)])

        mains = []
        mains.append(odict([('route', route), ('content', stuff)]))

        src = ['citizen', self.other.local.name, None]
        dst = ['mayor', self.main.local.name, None]
        route = odict([('src', src), ('dst', dst)])

        others = []
        others.append(odict([('route', route), ('content', stuff)]))

        self.message(mains=mains, others=others, duration=2.0)

    def testAutoAccept(self):
        '''
        Basic send auto accept message
        '''
        console.terse("{0}\n".format(self.testAutoAccept.__doc__))

        self.assertTrue(self.main.accept)

        # Don't add remote yard to main so only way to get message from other is
        # if auto acccept works
        self.other.addRemote(
            yarding.RemoteYard(stack=self.other, ha=self.main.local.ha))

        self.assertEqual(self.main.name, 'main')
        self.assertEqual(self.main.local.name, 'main')
        self.assertEqual(self.main.local.ha,
                         os.path.join(self.baseDirpath, 'cherry.main.uxd'))
        self.assertEqual(len(self.main.remotes), 0)

        self.assertEqual(self.other.name, 'other')
        self.assertEqual(self.other.local.name, 'other')
        self.assertEqual(self.other.local.ha,
                         os.path.join(self.baseDirpath, 'cherry.other.uxd'))
        self.assertEqual(len(self.other.remotes), 1)
        remote = self.other.remotes.values()[0]
        self.assertEqual(remote.ha,
                         os.path.join(self.baseDirpath, 'cherry.main.uxd'))
        self.assertEqual(remote.name, 'main')
        self.assertTrue(remote.uid in self.other.remotes)
        self.assertTrue(remote.name in self.other.uids)
        self.assertIs(self.other.remotes[self.other.uids[remote.name]], remote)

        stacking.LaneStack.Pk = raeting.packKinds.pack

        others = []
        others.append(
            odict(what="This is a message to the lord. Let me be",
                  extra="Go away."))

        self.message(mains=[], others=others)

        self.assertEqual(len(self.main.remotes), 1)
        remote = self.main.remotes.values()[0]
        self.assertEqual(remote.ha,
                         os.path.join(self.baseDirpath, 'cherry.other.uxd'))
        self.assertEqual(remote.name, 'other')
        self.assertTrue(remote.uid in self.main.remotes)
        self.assertTrue(remote.name in self.main.uids)
        self.assertIs(self.main.remotes[self.main.uids[remote.name]], remote)

        self.main.rxMsgs = deque()
        self.other.rxMsgs = deque()

        mains = []
        mains.append(
            odict(what="This is a message to the serf. Get to Work",
                  extra="Fix the fence."))

        self.message(mains=mains, others=[])

    def testAutoAcceptNot(self):
        '''
        Basic send non auto accept message
        '''
        console.terse("{0}\n".format(self.testAutoAcceptNot.__doc__))
        self.main.accept = False
        self.assertIs(self.main.accept, False)

        # Don't add remote yard to main so only way to get message from other is
        # if auto acccept works
        self.other.addRemote(
            yarding.RemoteYard(stack=self.other, ha=self.main.local.ha))

        self.assertEqual(self.main.name, 'main')
        self.assertEqual(self.main.local.name, 'main')
        self.assertEqual(self.main.local.ha,
                         os.path.join(self.baseDirpath, 'cherry.main.uxd'))
        self.assertEqual(len(self.main.remotes), 0)

        self.assertEqual(self.other.name, 'other')
        self.assertEqual(self.other.local.name, 'other')
        self.assertEqual(self.other.local.ha,
                         os.path.join(self.baseDirpath, 'cherry.other.uxd'))
        self.assertEqual(len(self.other.remotes), 1)
        remote = self.other.remotes.values()[0]
        self.assertEqual(remote.ha,
                         os.path.join(self.baseDirpath, 'cherry.main.uxd'))
        self.assertEqual(remote.name, 'main')
        self.assertTrue(remote.uid in self.other.remotes)
        self.assertTrue(remote.name in self.other.uids)
        self.assertIs(self.other.remotes[self.other.uids[remote.name]], remote)

        stacking.LaneStack.Pk = raeting.packKinds.pack

        others = []
        others.append(
            odict(what="This is a message to the lord. Let me be",
                  extra="Go away."))

        for msg in others:
            self.other.transmit(msg=msg)

        self.service()

        self.assertEqual(len(self.main.rxMsgs), 0)
        self.assertEqual(len(self.main.remotes), 0)
        self.assertEqual(self.main.stats['unaccepted_source_yard'], 1)
Beispiel #4
0
class BasicTestCase(unittest.TestCase):
    """"""

    def setUp(self):
        self.store = storing.Store(stamp=0.0)
        self.timer = StoreTimer(store=self.store, duration=1.0)

        self.baseDirpath=tempfile.mkdtemp(prefix="raet",  suffix="base", dir='/tmp')
        stacking.RoadStack.Bk = raeting.bodyKinds.json

        #main stack
        mainName = "main"
        mainDirpath = os.path.join(self.baseDirpath, 'road', 'keep', mainName)
        signer = nacling.Signer()
        mainSignKeyHex = signer.keyhex
        privateer = nacling.Privateer()
        mainPriKeyHex = privateer.keyhex


        #other stack
        otherName = "other"
        otherDirpath = os.path.join(self.baseDirpath, 'road', 'keep', otherName)
        signer = nacling.Signer()
        otherSignKeyHex = signer.keyhex
        privateer = nacling.Privateer()
        otherPriKeyHex = privateer.keyhex


        keeping.clearAllKeep(mainDirpath)
        keeping.clearAllKeep(otherDirpath)

        local = estating.LocalEstate(eid=1,
                                     name=mainName,
                                     sigkey=mainSignKeyHex,
                                     prikey=mainPriKeyHex,)

        self.main = stacking.RoadStack(name=mainName,
                                         local=local,
                                         auto=True,
                                         main=True,
                                         dirpath=mainDirpath,
                                         store=self.store)

        local = estating.LocalEstate(eid=0,
                                     name=otherName,
                                     ha=("", raeting.RAET_TEST_PORT),
                                     sigkey=otherSignKeyHex,
                                     prikey=otherPriKeyHex,)

        self.other = stacking.RoadStack(name=otherName,
                                         local=local,
                                         dirpath=otherDirpath,
                                         store=self.store)



    def tearDown(self):
        self.main.server.close()
        self.other.server.close()

        #self.main.clearLocal()
        #self.main.clearRemoteKeeps()
        #self.other.clearLocal()
        #self.other.clearRemoteKeeps()

        self.main.clearAllDir()
        self.other.clearAllDir()

        if os.path.exists(self.baseDirpath):
            shutil.rmtree(self.baseDirpath)


    def join(self, mha=None, timeout=None):
        '''
        Utility method to do join. Call from test method.
        '''
        console.terse("\nJoin Transaction **************\n")
        self.other.join(ha=mha, timeout=timeout)
        self.service()

    def allow(self):
        '''
        Utility method to do allow. Call from test method.
        '''
        console.terse("\nAllow Transaction **************\n")
        self.other.allow()
        self.service()

    def alive(self, initiator, correspondent):
        '''
        Utility method to do alive. Call from test method.
        '''
        console.terse("\nAlive Transaction **************\n")
        initiator.alive(duid=correspondent.local.uid)
        self.service()

    def service(self, duration=1.0, real=True):
        '''
        Utility method to service queues. Call from test method.
        '''
        self.timer.restart(duration=duration)
        while not self.timer.expired:
            self.other.serviceAll()
            self.main.serviceAll()
            if not (self.main.transactions or self.other.transactions):
                break
            self.store.advanceStamp(0.1)
            if real:
                time.sleep(0.1)

    def serviceOther(self, duration=1.0, real=True):
        '''
        Utility method to only service other queues. Call from test method.
        '''
        self.timer.restart(duration=duration)
        while not self.timer.expired:
            self.other.serviceAll()
            if not (self.other.transactions):
                break
            self.store.advanceStamp(0.1)
            if real:
                time.sleep(0.1)

    def serviceMain(self, duration=1.0, real=True):
        '''
        Utility method to only service main queues. Call from test method.
        '''
        self.timer.restart(duration=duration)
        while not self.timer.expired:
            self.main.serviceAll()
            if not (self.main.transactions):
                break
            self.store.advanceStamp(0.1)
            if real:
                time.sleep(0.1)


    def bootstrap(self, bk=raeting.bodyKinds.json):
        '''
        Initialize
            main on port 7530 with eid of 1
            other on port 7531 with eid of 0
        Complete
            main eid of 1 joined and allowed
            other eid of 2 joined and allowed
        '''
        stacking.RoadStack.Bk = bk

        self.assertEqual(self.main.name, 'main')
        self.assertEqual(self.main.local.name, 'main')
        self.assertEqual(self.main.local.ha, ("0.0.0.0", raeting.RAET_PORT))

        self.assertEqual(self.other.name, 'other')
        self.assertEqual(self.other.local.name, 'other')
        self.assertEqual(self.other.local.ha, ("0.0.0.0", raeting.RAET_TEST_PORT))

        self.join()
        console.terse("\nStack '{0}' uid= {1}\n".format(self.main.name, self.main.local.uid))
        self.assertEqual(self.main.local.uid, 1)
        self.assertEqual(self.main.name, 'main')
        self.assertEqual(len(self.main.transactions), 0)
        remote = self.main.remotes.values()[0]
        self.assertTrue(remote.joined)
        self.assertEqual(remote.uid, 2)
        self.assertTrue(2 in self.main.remotes)
        self.assertTrue(remote.uid in self.main.remotes)
        self.assertTrue(len(self.main.remotes), 1)
        self.assertTrue(len(self.main.nameRemotes), 1)
        self.assertTrue(len(self.main.haRemotes), 1)
        self.assertEqual(remote.name, 'other')
        self.assertEqual(len(remote.transactions), 0)
        self.assertTrue('other' in self.main.nameRemotes)
        self.assertIs(self.main.nameRemotes[remote.name], remote)
        console.terse("Stack '{0}' estate name '{1}' joined with '{2}' = {3}\n".format(
                self.main.name, self.main.local.name, remote.name, remote.joined))

        console.terse("\nStack '{0}' uid= {1}\n".format(self.other.name, self.other.local.uid))
        self.assertEqual(self.other.local.uid, 2)
        self.assertEqual(self.other.name, 'other')
        self.assertEqual(len(self.other.transactions), 0)
        remote = self.other.remotes.values()[0]
        self.assertTrue(remote.joined)
        self.assertEqual(remote.uid, 1)
        self.assertTrue(1 in self.other.remotes)
        self.assertTrue(remote.uid in self.other.remotes)
        self.assertTrue(len(self.other.remotes), 1)
        self.assertTrue(len(self.other.nameRemotes), 1)
        self.assertTrue(len(self.other.haRemotes), 1)
        self.assertEqual(remote.name, 'main')
        self.assertEqual(len(remote.transactions), 0)
        self.assertTrue('main' in self.other.nameRemotes)
        self.assertIs(self.other.nameRemotes[remote.name], remote)
        console.terse("Stack '{0}' estate name '{1}' joined with '{2}' = {3}\n".format(
                self.other.name, self.other.local.name, remote.name, remote.joined))

        self.allow()
        console.terse("\nStack '{0}' uid= {1}\n".format(self.main.name, self.main.local.uid))
        self.assertEqual(self.main.local.uid, 1)
        self.assertEqual(self.main.name, 'main')
        self.assertEqual(len(self.main.transactions), 0)
        remote = self.main.remotes.values()[0]
        self.assertTrue(remote.allowed)
        self.assertEqual(remote.uid, 2)
        self.assertTrue(2 in self.main.remotes)
        self.assertTrue(len(self.main.remotes), 1)
        self.assertTrue(len(self.main.nameRemotes), 1)
        self.assertTrue(len(self.main.haRemotes), 1)
        self.assertEqual(remote.name, 'other')
        self.assertEqual(len(remote.transactions), 0)
        self.assertTrue('other' in self.main.nameRemotes)
        console.terse("Stack '{0}' estate name '{1}' allowd with '{2}' = {3}\n".format(
                self.main.name, self.main.local.name, remote.name, remote.allowed))

        console.terse("\nStack '{0}' uid= {1}\n".format(self.other.name, self.other.local.uid))
        self.assertEqual(self.other.local.uid, 2)
        self.assertEqual(self.other.name, 'other')
        self.assertEqual(len(self.other.transactions), 0)
        remote = self.other.remotes.values()[0]
        self.assertTrue(remote.allowed)
        self.assertEqual(remote.uid, 1)
        self.assertTrue(1 in self.other.remotes)
        self.assertTrue(len(self.other.remotes), 1)
        self.assertTrue(len(self.other.nameRemotes), 1)
        self.assertTrue(len(self.other.haRemotes), 1)
        self.assertEqual(remote.name, 'main')
        self.assertEqual(len(remote.transactions), 0)
        self.assertTrue('main' in self.other.nameRemotes)
        console.terse("Stack '{0}' estate name '{1}' allowed with '{2}' = {3}\n".format(
                self.other.name, self.other.local.name, remote.name, remote.allowed))

        console.terse("\nMessage: other to main *********\n")
        body = odict(what="This is a message to the main estate. How are you", extra="I am fine.")
        self.other.txMsgs.append((body, self.main.local.uid))
        #self.other.message(body=body, deid=self.main.local.uid)
        self.service()

        console.terse("\nStack '{0}' uid= {1}\n".format(self.main.name, self.main.local.uid))
        self.assertEqual(len(self.main.transactions), 0)
        for msg, name in self.main.rxMsgs:
            console.terse("Estate '{0}' rxed:\n'{1}'\n".format(self.main.local.name, msg))
        self.assertDictEqual(body, self.main.rxMsgs[0][0])

        console.terse("\nMessage: main to other *********\n")
        body = odict(what="This is a message to the other estate. Get to Work", extra="Fix the fence.")
        self.main.txMsgs.append((body, self.other.local.uid))
        #self.main.message(body=body, deid=self.other.local.uid)
        self.service()

        console.terse("\nStack '{0}' uid= {1}\n".format(self.other.name, self.other.local.uid))
        self.assertEqual(len(self.other.transactions), 0)
        for msg, name in self.other.rxMsgs:
            console.terse("Estate '{0}' rxed:\n'{1}'\n".format(self.other.local.name, msg))
        self.assertDictEqual(body, self.other.rxMsgs[0][0])

    def bidirectional(self, bk=raeting.bodyKinds.json, mains=None, others=None, duration=3.0):
        '''
        Initialize
            main on port 7530 with eid of 1
            other on port 7531 with eid of 0
        Complete
            main eid of 1 joined and allowed
            other eid of 2 joined and allowed
        '''
        stacking.RoadStack.Bk = bk
        mains = mains or []
        other = others or []

        self.join()
        self.assertEqual(len(self.main.transactions), 0)
        remote = self.main.remotes.values()[0]
        self.assertTrue(remote.joined)
        self.assertEqual(len(self.other.transactions), 0)
        remote = self.other.remotes.values()[0]
        self.assertTrue(remote.joined)

        self.allow()
        self.assertEqual(len(self.main.transactions), 0)
        remote = self.main.remotes.values()[0]
        self.assertTrue(remote.allowed)
        self.assertEqual(len(self.other.transactions), 0)
        remote = self.other.remotes.values()[0]
        self.assertTrue(remote.allowed)

        console.terse("\nMessages Bidirectional *********\n")
        for msg in mains:
            self.main.transmit(msg)
        for msg in others:
            self.other.transmit(msg)

        self.service(duration=duration)

        console.terse("\nStack '{0}' uid= {1}\n".format(self.main.name, self.main.local.uid))
        self.assertEqual(len(self.main.transactions), 0)
        self.assertEqual(len(others), len(self.main.rxMsgs))
        for i, duple in enumerate(self.main.rxMsgs):
            console.terse("Estate '{0}' rxed:\n'{1}'\n".format(self.main.local.name, duple))
            self.assertDictEqual(others[i], duple[0])

        console.terse("\nStack '{0}' uid= {1}\n".format(self.other.name, self.other.local.uid))
        self.assertEqual(len(self.other.transactions), 0)
        self.assertEqual(len(mains), len(self.other.rxMsgs))
        for i, duple in enumerate(self.other.rxMsgs):
            console.terse("Estate '{0}' rxed:\n'{1}'\n".format(self.other.local.name, duple))
            self.assertDictEqual(mains[i], duple[0])

    def testBootstrapJson(self):
        '''
        Test join allow message transactions with JSON Serialization of body
        '''
        console.terse("{0}\n".format(self.testBootstrapJson.__doc__))
        self.bootstrap(bk=raeting.bodyKinds.json)

    def testBootstrapMsgpack(self):
        '''
        Test join allow message transactions with MsgPack Serialization of body
        '''
        console.terse("{0}\n".format(self.testBootstrapMsgpack.__doc__))
        self.bootstrap(bk=raeting.bodyKinds.msgpack)

    def testMsgBothwaysJson(self):
        '''
        Test message transactions
        '''
        console.terse("{0}\n".format(self.testMsgBothwaysJson.__doc__))

        others = []
        others.append(odict(house="Mama mia1", queue="fix me"))
        others.append(odict(house="Mama mia2", queue="help me"))
        others.append(odict(house="Mama mia3", queue="stop me"))
        others.append(odict(house="Mama mia4", queue="run me"))

        mains = []
        mains.append(odict(house="Papa pia1", queue="fix me"))
        mains.append(odict(house="Papa pia2", queue="help me"))
        mains.append(odict(house="Papa pia3", queue="stop me"))
        mains.append(odict(house="Papa pia4", queue="run me"))

        self.bidirectional(bk=raeting.bodyKinds.json, mains=mains, others=others)

    def testMsgBothwaysMsgpack(self):
        '''
        Test message transactions
        '''
        console.terse("{0}\n".format(self.testMsgBothwaysMsgpack.__doc__))

        others = []
        others.append(odict(house="Mama mia1", queue="fix me"))
        others.append(odict(house="Mama mia2", queue="help me"))
        others.append(odict(house="Mama mia3", queue="stop me"))
        others.append(odict(house="Mama mia4", queue="run me"))

        mains = []
        mains.append(odict(house="Papa pia1", queue="fix me"))
        mains.append(odict(house="Papa pia2", queue="help me"))
        mains.append(odict(house="Papa pia3", queue="stop me"))
        mains.append(odict(house="Papa pia4", queue="run me"))

        self.bidirectional(bk=raeting.bodyKinds.msgpack, mains=mains, others=others)

    def testSegmentedJson(self):
        '''
        Test segmented message transactions
        '''
        console.terse("{0}\n".format(self.testSegmentedJson.__doc__))

        stuff = []
        for i in range(300):
            stuff.append(str(i).rjust(10, " "))
        stuff = "".join(stuff)

        others = []
        mains = []
        others.append(odict(house="Snake eyes", queue="near stuff", stuff=stuff))
        mains.append(odict(house="Craps", queue="far stuff", stuff=stuff))

        bloat = []
        for i in range(300):
            bloat.append(str(i).rjust(100, " "))
        bloat = "".join(bloat)
        others.append(odict(house="Other", queue="big stuff", bloat=bloat))
        mains.append(odict(house="Main", queue="gig stuff", bloat=bloat))

        self.bidirectional(bk=raeting.bodyKinds.json, mains=mains, others=others)

    def testSegmentedMsgpack(self):
        '''
        Test segmented message transactions
        '''
        console.terse("{0}\n".format(self.testSegmentedJson.__doc__))

        stuff = []
        for i in range(300):
            stuff.append(str(i).rjust(10, " "))
        stuff = "".join(stuff)

        others = []
        mains = []
        others.append(odict(house="Snake eyes", queue="near stuff", stuff=stuff))
        mains.append(odict(house="Craps", queue="far stuff", stuff=stuff))

        bloat = []
        for i in range(300):
            bloat.append(str(i).rjust(100, " "))
        bloat = "".join(bloat)
        others.append(odict(house="Other", queue="big stuff", bloat=bloat))
        mains.append(odict(house="Main", queue="gig stuff", bloat=bloat))

        self.bidirectional(bk=raeting.bodyKinds.msgpack, mains=mains, others=others)

    def testJoinForever(self):
        '''
        Test other joining with timeout set to 0.0 and default
        '''
        console.terse("{0}\n".format(self.testJoinForever.__doc__))

        self.other.join(timeout=0.0) #attempt to join forever with timeout 0.0
        self.serviceOther(duration=20.0, real=False) # only service other so no response

        console.terse("\nStack '{0}' uid= {1}\n".format(self.main.name, self.main.local.uid))
        self.assertEqual(self.main.local.uid, 1)
        self.assertEqual(self.main.name, 'main')
        self.assertEqual(len(self.main.transactions), 0)
        self.assertEqual(len(self.main.remotes), 0)

        console.terse("\nStack '{0}' uid= {1}\n".format(self.other.name, self.other.local.uid))
        self.assertEqual(self.other.local.uid, 0)
        self.assertEqual(self.other.name, 'other')
        self.assertEqual(len(self.other.transactions), 1)
        remote = self.other.remotes.values()[0]
        self.assertIs(remote.joined, None)
        self.assertEqual(remote.uid, 0)
        console.terse("Stack '{0}' estate name '{1}' joined with '{2}' = {3}\n".format(
                self.other.name, self.other.local.name, remote.name, remote.joined))


        console.terse("{0} Stats\n".format(self.main.name))
        for key, val in self.main.stats.items():
            console.terse("   {0}={1}\n".format(key, val))
        self.assertEqual(len(self.main.stats), 0)

        console.terse("{0} Stats\n".format(self.other.name))
        for key, val in self.other.stats.items():
            console.terse("   {0}={1}\n".format(key, val))
        self.assertEqual(self.other.stats.get('redo_join'), 6)

        # Now allow join to complete
        self.service()

        console.terse("\nStack '{0}' uid= {1}\n".format(self.main.name, self.main.local.uid))
        self.assertEqual(self.main.local.uid, 1)
        self.assertEqual(self.main.name, 'main')
        self.assertEqual(len(self.main.transactions), 0)
        remote = self.main.remotes.values()[0]
        self.assertTrue(remote.joined)
        self.assertEqual(remote.uid, 2)
        self.assertTrue(2 in self.main.remotes)
        self.assertTrue(len(self.main.remotes), 1)
        self.assertTrue(len(self.main.nameRemotes), 1)
        self.assertTrue(len(self.main.haRemotes), 1)
        self.assertEqual(remote.name, 'other')
        self.assertTrue('other' in self.main.nameRemotes)
        console.terse("Stack '{0}' estate name '{1}' joined with '{2}' = {3}\n".format(
                self.main.name, self.main.local.name, remote.name, remote.joined))

        console.terse("\nStack '{0}' uid= {1}\n".format(self.other.name, self.other.local.uid))
        self.assertEqual(self.other.local.uid, 2)
        self.assertEqual(self.other.name, 'other')
        self.assertEqual(len(self.other.transactions), 0)
        remote = self.other.remotes.values()[0]
        self.assertTrue(remote.joined)
        self.assertEqual(remote.uid, 1)
        self.assertTrue(1 in self.other.remotes)
        self.assertTrue(len(self.other.remotes), 1)
        self.assertTrue(len(self.other.nameRemotes), 1)
        self.assertTrue(len(self.other.haRemotes), 1)
        self.assertEqual(remote.name, 'main')
        self.assertTrue('main' in self.other.nameRemotes)
        console.terse("Stack '{0}' estate name '{1}' joined with '{2}' = {3}\n".format(
                self.other.name, self.other.local.name, remote.name, remote.joined))

        # Now try again with existing remote data
        self.other.join(timeout=0.0) #attempt to join forever with timeout 0.0
        self.serviceOther(duration=20.0, real=False) # only service other so no response

        # main will still have join results from previous join transaction
        console.terse("\nStack '{0}' uid= {1}\n".format(self.main.name, self.main.local.uid))
        self.assertEqual(self.main.local.uid, 1)
        self.assertEqual(self.main.name, 'main')
        self.assertEqual(len(self.main.transactions), 0)
        remote = self.main.remotes.values()[0]
        self.assertTrue(remote.joined)
        self.assertEqual(remote.uid, 2)
        self.assertTrue(2 in self.main.remotes)
        self.assertTrue(len(self.main.remotes), 1)
        self.assertTrue(len(self.main.nameRemotes), 1)
        self.assertTrue(len(self.main.haRemotes), 1)
        self.assertEqual(remote.name, 'other')
        self.assertTrue('other' in self.main.nameRemotes)
        console.terse("Stack '{0}' estate name '{1}' joined with '{2}' = {3}\n".format(
                self.main.name, self.main.local.name, remote.name, remote.joined))

        # Other will have outstanding join transaction
        console.terse("\nStack '{0}' uid= {1}\n".format(self.other.name, self.other.local.uid))
        self.assertEqual(self.other.local.uid, 2)
        self.assertEqual(self.other.name, 'other')
        self.assertEqual(len(self.other.transactions), 1)
        remote = self.other.remotes.values()[0]
        self.assertIs(remote.joined, None)
        self.assertEqual(remote.uid, 1)
        self.assertTrue(1 in self.other.remotes)
        self.assertTrue(len(self.other.remotes), 1)
        self.assertTrue(len(self.other.nameRemotes), 1)
        self.assertTrue(len(self.other.haRemotes), 1)
        self.assertEqual(remote.name, 'main')
        self.assertTrue('main' in self.other.nameRemotes)
        console.terse("Stack '{0}' estate name '{1}' joined with '{2}' = {3}\n".format(
                self.other.name, self.other.local.name, remote.name, remote.joined))

        console.terse("{0} Stats\n".format(self.main.name))
        for key, val in self.main.stats.items():
            console.terse("   {0}={1}\n".format(key, val))
        self.assertEqual(self.main.stats.get('join_correspond_complete'), 1)

        console.terse("{0} Stats\n".format(self.other.name))
        for key, val in self.other.stats.items():
            console.terse("   {0}={1}\n".format(key, val))
        self.assertEqual(self.other.stats.get('redo_join'), 12)
        self.assertEqual(self.other.stats.get('join_initiate_complete'), 1)

        # Now allow join to complete
        self.service()

        console.terse("\nStack '{0}' uid= {1}\n".format(self.main.name, self.main.local.uid))
        self.assertEqual(self.main.local.uid, 1)
        self.assertEqual(self.main.name, 'main')
        self.assertEqual(len(self.main.transactions), 0)
        remote = self.main.remotes.values()[0]
        self.assertTrue(remote.joined)
        self.assertEqual(remote.uid, 2)
        self.assertTrue(2 in self.main.remotes)
        self.assertTrue(len(self.main.remotes), 1)
        self.assertTrue(len(self.main.nameRemotes), 1)
        self.assertTrue(len(self.main.haRemotes), 1)
        self.assertEqual(remote.name, 'other')
        self.assertTrue('other' in self.main.nameRemotes)
        console.terse("Stack '{0}' estate name '{1}' joined with '{2}' = {3}\n".format(
                self.main.name, self.main.local.name, remote.name, remote.joined))

        console.terse("\nStack '{0}' uid= {1}\n".format(self.other.name, self.other.local.uid))
        self.assertEqual(self.other.local.uid, 2)
        self.assertEqual(self.other.name, 'other')
        self.assertEqual(len(self.other.transactions), 0)
        remote = self.other.remotes.values()[0]
        self.assertTrue(remote.joined)
        self.assertEqual(remote.uid, 1)
        self.assertTrue(1 in self.other.remotes)
        self.assertTrue(len(self.other.remotes), 1)
        self.assertTrue(len(self.other.nameRemotes), 1)
        self.assertTrue(len(self.other.haRemotes), 1)
        self.assertEqual(remote.name, 'main')
        self.assertTrue('main' in self.other.nameRemotes)
        console.terse("Stack '{0}' estate name '{1}' joined with '{2}' = {3}\n".format(
                self.other.name, self.other.local.name, remote.name, remote.joined))

    def testStaleNack(self):
        '''
        Test stale nack
        '''
        console.terse("{0}\n".format(self.testStaleNack.__doc__))

        self.join()
        self.assertEqual(len(self.main.transactions), 0)
        remote = self.main.remotes.values()[0]
        self.assertTrue(remote.joined)
        self.assertEqual(len(self.other.transactions), 0)
        remote = self.other.remotes.values()[0]
        self.assertTrue(remote.joined)

        self.allow()
        self.assertEqual(len(self.main.transactions), 0)
        remote = self.main.remotes.values()[0]
        self.assertTrue(remote.allowed)
        self.assertEqual(len(self.other.transactions), 0)
        remote = self.other.remotes.values()[0]
        self.assertTrue(remote.allowed)

        console.terse("\nMessage transaction *********\n")
        body = odict(what="This is a message to the main estate. How are you", extra="I am fine.")
        self.other.txMsgs.append((body, self.main.local.uid))
        self.timer.restart(duration=1.0)
        while not self.timer.expired:
            self.other.serviceAllTx() # transmit but leave receives in socket buffer
            self.main.serviceAllRx() # receive but leave transmits in queue

            self.store.advanceStamp(0.1)
            time.sleep(0.1)

        self.assertEqual(len(self.main.transactions), 0) #completed
        self.assertEqual(len(self.other.transactions), 1) # waiting for ack

        remote = self.other.remotes.values()[0]
        remote.transactions = odict() #clear transactions so RX is stale correspondent
        self.assertEqual(len(self.other.transactions), 0) # no initated transaction

        self.timer.restart(duration=2.0)
        while not self.timer.expired:
            self.main.serviceAll() # transmit stale ack
            self.other.serviceAll() # recieve ack
            self.store.advanceStamp(0.1)
            time.sleep(0.1)

        self.assertEqual(len(self.main.transactions), 0)
        self.assertEqual(len(self.other.transactions), 0)

        print "{0} Stats".format(self.main.name)
        for key, val in self.main.stats.items():
            print "   {0}={1}".format(key, val)
        print
        print "{0} Stats".format(self.other.name)
        for key, val in self.other.stats.items():
            print "   {0}={1}".format(key, val)
        print

        self.assertTrue(self.other.stats.get('stale_correspondent_attempt') >= 1)
        self.assertTrue(self.other.stats.get('stale_correspondent_nack') >= 1)
        self.assertTrue(self.main.stats.get('messagent_correspond_complete') >= 1)
        self.assertTrue(self.main.stats.get('stale_packet') >= 1)

    def testBasicAlive(self):
        '''
        Test basic alive transaction
        '''
        console.terse("{0}\n".format(self.testBasicAlive.__doc__))

        self.join()
        self.assertEqual(len(self.main.transactions), 0)
        remote = self.main.remotes.values()[0]
        self.assertTrue(remote.joined)
        self.assertEqual(len(self.other.transactions), 0)
        remote = self.other.remotes.values()[0]
        self.assertTrue(remote.joined)

        self.allow()
        self.assertEqual(len(self.main.transactions), 0)
        remote = self.main.remotes.values()[0]
        self.assertTrue(remote.allowed)
        self.assertEqual(len(self.other.transactions), 0)
        remote = self.other.remotes.values()[0]
        self.assertTrue(remote.allowed)

        console.terse("\nAlive Other to Main *********\n")
        otherRemote = self.main.remotes.values()[0]
        mainRemote = self.other.remotes.values()[0]
        self.assertIs(otherRemote.alived, None)
        self.assertIs(mainRemote.alived, None)

        self.alive(self.other, self.main)
        self.assertEqual(len(self.main.transactions), 0)
        self.assertTrue(otherRemote.alived)
        self.assertEqual(len(self.other.transactions), 0)
        self.assertTrue(mainRemote.alived)

        console.terse("\nAlive Main to Other *********\n")
        self.alive(self.main, self.other)
        self.assertEqual(len(self.main.transactions), 0)
        remote = self.main.remotes.values()[0]
        self.assertTrue(remote.alived)
        self.assertEqual(len(self.other.transactions), 0)
        remote = self.other.remotes.values()[0]
        self.assertTrue(remote.alived)
Beispiel #5
0
class BasicTestCase(unittest.TestCase):
    """"""

    def setUp(self):
        self.store = storing.Store(stamp=0.0)
        self.timer = StoreTimer(store=self.store, duration=1.0)

        self.base = tempfile.mkdtemp(prefix="raet",  suffix="base", dir='/tmp')

    def tearDown(self):
        if os.path.exists(self.base):
            shutil.rmtree(self.base)

    def createLaneData(self, name, yid, base, lanename, localname=''):
        '''
        Creates odict and populates with data to setup lane stack
        {
            name: stack name
            dirpath: dirpath for keep files
            lanename: name of yard
        }
        '''
        data = odict()
        data['name'] = name
        data['yid'] = yid
        data['basedirpath'] = os.path.join(base, 'lane', 'keep')
        data['dirpath'] = os.path.join(data['basedirpath'], name)
        data['lanename'] = lanename
        data['localname'] = localname or name

        return data

    def createLaneStack(self, data, main=None):
        '''
        Creates stack and local yard from data
        returns stack

        '''
        stack = stacking.LaneStack(name=data['name'],
                                   yid=data['yid'],
                                   localname=data['localname'],
                                   main=main,
                                   lanename=data['lanename'],
                                   basedirpath=data['basedirpath'],
                                   sockdirpath=data['dirpath'])

        return stack

    def message(self, main,  other, mains, others, duration=1.0):
        '''
        Utility to send messages both ways
        '''
        for msg in mains:
            main.transmit(msg, duid=main.uids[other.local.name])
        for msg in others:
            other.transmit(msg,  duid=other.uids[main.local.name])

        self.service(main, other, duration=duration)

        self.assertEqual(len(main.rxMsgs), len(others))
        for i, msg in enumerate(main.rxMsgs):
            console.terse("Yard '{0}' rxed:\n'{1}'\n".format(main.local.name, msg))
            self.assertDictEqual(others[i], msg)

        self.assertEqual(len(other.rxMsgs), len(mains))
        for i, msg in enumerate(other.rxMsgs):
            console.terse("Yard '{0}' rxed:\n'{1}'\n".format(other.local.name, msg))
            self.assertDictEqual(mains[i], msg)

    def serviceStackOneTx(self, stack):
        '''
        Utility method to service one packet on Tx queues. Call from test method.
        '''
        stack.serviceOneAllTx()
        time.sleep(0.1)
        self.store.advanceStamp(0.1)

    def serviceStackOneRx(self, stack):
        '''
        Utility method to service one packet on Rx queues. Call from test method.
        '''
        stack.serviceOneAllRx()
        time.sleep(0.1)
        self.store.advanceStamp(0.1)

    def serviceOneTx(self, main, other):
        '''
        Utility method to service one packet on Tx queues. Call from test method.
        '''
        other.serviceOneAllTx()
        main.serviceOneAllTx()
        time.sleep(0.1)
        self.store.advanceStamp(0.1)

    def serviceOneRx(self, main, other):
        '''
        Utility method to service one packet on Rx queues. Call from test method.
        '''
        other.serviceOneAllRx()
        main.serviceOneAllRx()
        time.sleep(0.1)
        self.store.advanceStamp(0.1)

    def serviceOneAll(self, main, other):
        '''
        Utility method to service one packet on all queues. Call from test method.
        '''
        self.serviceOneTx(main=main, other=other)
        self.serviceOneRx(main=main, other=other)

    def service(self, main, other, duration=1.0):
        '''
        Utility method to service queues. Call from test method.
        '''
        self.timer.restart(duration=duration)
        while not self.timer.expired:
            other.serviceAll()
            main.serviceAll()
            self.store.advanceStamp(0.1)
            time.sleep(0.1)

    def serviceStack(self, stack, duration=1.0):
        '''
        Utility method to service queues for one stack. Call from test method.
        '''
        self.timer.restart(duration=duration)
        while not self.timer.expired:
            stack.serviceAll()
            self.store.advanceStamp(0.1)
            time.sleep(0.1)

    def serviceStacks(self, stacks, duration=1.0):
        '''
        Utility method to service queues for list of stacks. Call from test method.
        '''
        self.timer.restart(duration=duration)
        while not self.timer.expired:
            for stack in stacks:
                stack.serviceAll()
            self.store.advanceStamp(0.1)
            time.sleep(0.1)

    def testBasic(self):
        '''
        Basic keep setup for stack keep persistence load and dump
        '''
        console.terse("{0}\n".format(self.testBasic.__doc__))
        mainData = self.createLaneData(name='main', yid=1, base=self.base, lanename='apple')
        keeping.clearAllKeep(mainData['dirpath'])
        stack = self.createLaneStack(data=mainData, main=True)

        console.terse("{0} keep dirpath = {1}\n".format(stack.name, stack.keep.dirpath))
        self.assertTrue(stack.keep.dirpath.endswith('/lane/keep/main'))
        self.assertTrue(stack.keep.localdirpath.endswith('/lane/keep/main/local'))
        self.assertTrue(stack.keep.remotedirpath.endswith('/lane/keep/main/remote'))
        self.assertTrue(stack.keep.localfilepath.endswith('/lane/keep/main/local/yard.json'))
        self.assertTrue(stack.local.ha.endswith('/lane/keep/main/apple.main.uxd'))

        # test round trip
        stack.clearLocal()
        stack.clearRemoteKeeps()

        stack.dumpLocal()
        stack.dumpRemotes()

        localKeepData = stack.keep.loadLocalData()
        console.terse("Local keep data = '{0}'\n".format(localKeepData))

        validLocalKeepData = odict([
                                ('uid', 1),
                                ('name', 'main'),
                                ('ha', stack.local.ha),
                                ('main', True),
                                ('sid', 0),
                                ('lanename', 'apple'),
                                ('stack', 'main'),
                                ('nyid', 1),
                                ('accept', True)
                              ])

        self.assertDictEqual(localKeepData, validLocalKeepData)
        self.assertTrue(localKeepData['ha'].endswith('lane/keep/main/apple.main.uxd'))

        remoteKeepData = stack.keep.loadAllRemoteData()
        console.terse("Remote keep data = '{0}'\n".format(remoteKeepData))
        self.assertDictEqual(remoteKeepData, {})

        # test round trip with stack methods
        stack.loadLocal()
        localKeepData = odict([
                                ('uid', stack.local.uid),
                                ('name', stack.local.name),
                                ('ha', stack.local.ha),
                                ('main', stack.local.main),
                                ('sid', stack.local.sid),
                                ('lanename', stack.local.lanename),
                                ('stack', stack.name),
                                ('nyid', stack.nyid),
                                ('accept', stack.accept),
                              ])
        self.assertDictEqual(localKeepData, validLocalKeepData)
        self.assertTrue(stack.local.ha.endswith('lane/keep/main/apple.main.uxd'))

        #stack.removeAllRemotes()
        stack.remotes = odict()
        stack.uids = odict()
        stack.loadRemotes()
        self.assertDictEqual(stack.remotes, {})

        # round trip with non empty remote data
        other1Data = self.createLaneData(name='other1',
                                         yid=0,
                                         base=self.base,
                                         lanename=stack.local.lanename)
        stack.addRemote(yarding.RemoteYard(stack=stack,
                                           name=other1Data['name'],
                                           lanename=other1Data['lanename'],
                                           dirpath=other1Data['dirpath']))

        other2Data = self.createLaneData(name='other2',
                                         yid=0,
                                         base=self.base,
                                         lanename=stack.local.lanename)
        stack.addRemote(yarding.RemoteYard(stack=stack,
                                           name=other2Data['name'],
                                           lanename=other2Data['lanename'],
                                           dirpath=other2Data['dirpath']))

        stack.dumpRemotes()
        remoteKeepData = stack.keep.loadAllRemoteData()
        console.terse("Remote keep data = '{0}'\n".format(remoteKeepData))
        validRemoteKeepData = {'2':
                                    {'uid': 2,
                                     'name': 'other1',
                                     'ha': '',
                                     'sid': 0},
                                '3':
                                    {'uid': 3,
                                     'name': 'other2',
                                     'ha': '',
                                     'sid': 0,}
                                }
        validRemoteKeepData['2']['ha'] = stack.remotes[2].ha
        validRemoteKeepData['3']['ha'] = stack.remotes[3].ha
        self.assertDictEqual(remoteKeepData, validRemoteKeepData)

        # stack method
        #convert string uid keys into int uid keys
        temp = validRemoteKeepData
        validRemoteKeepData = odict()
        for uid in temp:
            validRemoteKeepData[int(uid)] = temp[uid]

        #stack.removeAllRemotes()
        stack.remotes = odict()
        stack.uids = odict()
        stack.loadRemotes()
        remoteKeepData = odict()
        for remote in stack.remotes.values():
            remoteKeepData[remote.uid] = odict([
                                                ('uid', remote.uid),
                                                ('name', remote.name),
                                                ('ha', remote.ha),
                                                ('sid', remote.sid),
                                               ])
        self.assertDictEqual(remoteKeepData, validRemoteKeepData)
        stack.server.close()

        # bootstrap new stack from stored keepdata
        stack = stacking.LaneStack(name=mainData['name'],
                                   dirpath=mainData['dirpath'],
                                   store=self.store)
        localKeepData = odict([
                                ('uid', stack.local.uid),
                                ('name', stack.local.name),
                                ('ha', stack.local.ha),
                                ('main', stack.local.main),
                                ('sid', stack.local.sid),
                                ('lanename', stack.local.lanename),
                                ('stack', stack.name),
                                ('nyid', stack.nyid),
                                ('accept', stack.accept),
                              ])
        console.terse("Local keep data = '{0}'\n".format(localKeepData))
        self.assertDictEqual(localKeepData, validLocalKeepData)

        remoteKeepData = odict()
        for remote in stack.remotes.values():
            remoteKeepData[remote.uid] = odict([
                                                ('uid', remote.uid),
                                                ('name', remote.name),
                                                ('ha', remote.ha),
                                                ('sid', remote.sid),
                                               ])
            validRemoteKeepData[remote.uid]['sid'] += 1 # on load stack increments
        self.assertDictEqual(remoteKeepData, validRemoteKeepData)

        stack.server.close()
        stack.clearLocal()
        stack.clearRemoteKeeps()

    def testRestart(self):
        '''
        Test messaging after restart with saved data
        '''
        console.terse("{0}\n".format(self.testRestart.__doc__))

        stacking.LaneStack.Pk = raeting.packKinds.json

        mainData = self.createLaneData(name='main', yid=1, base=self.base, lanename='apple')
        keeping.clearAllKeep(mainData['dirpath'])
        main = self.createLaneStack(data=mainData, main=True)
        self.assertTrue(main.keep.dirpath.endswith('/lane/keep/main'))
        self.assertTrue(main.keep.localdirpath.endswith('/lane/keep/main/local'))
        self.assertTrue(main.keep.remotedirpath.endswith('/lane/keep/main/remote'))
        self.assertTrue(main.keep.localfilepath.endswith('/lane/keep/main/local/yard.json'))
        self.assertTrue(main.local.ha.endswith('/lane/keep/main/apple.main.uxd'))
        self.assertTrue(main.local.main)

        otherData = self.createLaneData(name='other', yid=1, base=self.base, lanename='apple')
        keeping.clearAllKeep(otherData['dirpath'])
        other = self.createLaneStack(data=otherData)
        self.assertTrue(other.keep.dirpath.endswith('/lane/keep/other'))
        self.assertTrue(other.keep.localdirpath.endswith('/lane/keep/other/local'))
        self.assertTrue(other.keep.remotedirpath.endswith('/lane/keep/other/remote'))
        self.assertTrue(other.keep.localfilepath.endswith('/lane/keep/other/local/yard.json'))
        self.assertTrue(other.local.ha.endswith('/lane/keep/other/apple.other.uxd'))

        main.addRemote(yarding.RemoteYard(stack=main, ha=other.local.ha))
        self.assertTrue('other' in main.uids)
        other.addRemote(yarding.RemoteYard(stack=other, ha=main.local.ha))
        self.assertTrue('main' in other.uids)

        src = ['mayor', main.local.name, None] # (house, yard, queue)
        dst = ['citizen', other.local.name, None]
        route = odict([('src', src), ('dst', dst)])
        stuff = "This is my command"
        mains = []
        mains.append(odict([('route', route), ('content', stuff)]))

        src = ['citizen', other.local.name, None]
        dst = ['mayor', main.local.name, None]
        route = odict([('src', src), ('dst', dst)])
        stuff = "This is my reply."
        others = []
        others.append(odict([('route', route), ('content', stuff)]))

        self.message(main,  other, mains, others, duration=1.0)

        self.assertEqual(len(main.remotes), 1)
        self.assertTrue('other' in main.uids)
        self.assertEqual(len(other.remotes), 1)
        self.assertTrue('main' in other.uids)

        self.assertEqual(main.remotes[main.uids['other']].sid, 0)
        self.assertEqual(other.remotes[other.uids['main']].sid, 0)
        self.assertEqual(main.remotes[main.uids['other']].rsid,
                         other.remotes[other.uids['main']].sid)
        self.assertEqual(other.remotes[other.uids['main']].rsid,
                         main.remotes[main.uids['other']].sid)

        main.dumpRemotes()
        other.dumpRemotes()

        #now close down and reload data, make new stacks with saved data
        main.server.close()
        other.server.close()
        main = stacking.LaneStack(dirpath=mainData['dirpath'], store=self.store)
        other = stacking.LaneStack(dirpath=otherData['dirpath'], store=self.store)

        self.assertEqual(len(main.remotes), 1)
        self.assertTrue('other' in main.uids)
        self.assertEqual(len(other.remotes), 1)
        self.assertTrue('main' in other.uids)

        self.assertEqual(main.remotes[main.uids['other']].sid, 1)
        self.assertEqual(other.remotes[other.uids['main']].sid, 1)
        self.assertEqual(main.remotes[main.uids['other']].rsid, 0)
        self.assertEqual(other.remotes[other.uids['main']].rsid, 0)

        self.message(main,  other, mains, others, duration=1.0)

        self.assertEqual(main.remotes[main.uids['other']].rsid,
                         other.remotes[other.uids['main']].sid)
        self.assertEqual(other.remotes[other.uids['main']].rsid,
                         main.remotes[main.uids['other']].sid)

        #now close down and reload data, make new stacks with saved data
        main.server.close()
        other.server.close()
        main = stacking.LaneStack(dirpath=mainData['dirpath'], store=self.store)
        other = stacking.LaneStack(dirpath=otherData['dirpath'], store=self.store)

        self.assertEqual(len(main.remotes), 1)
        self.assertTrue('other' in main.uids)
        self.assertEqual(len(other.remotes), 1)
        self.assertTrue('main' in other.uids)

        self.assertEqual(main.remotes[main.uids['other']].sid, 2)
        self.assertEqual(other.remotes[other.uids['main']].sid, 2)
        self.assertEqual(main.remotes[main.uids['other']].rsid, 0)
        self.assertEqual(other.remotes[other.uids['main']].rsid, 0)

        # now send paginated messages
        src = ['mayor', main.local.name, None] # (house, yard, queue)
        dst = ['citizen', other.local.name, None]
        route = odict([('src', src), ('dst', dst)])
        stuff = ["Do as I say."]
        for i in range(10000):
            stuff.append(str(i).rjust(10, " "))
        stuff = "".join(stuff)
        mains = []
        mains.append(odict([('route', route), ('content', stuff)]))

        src = ['citizen', other.local.name, None]
        dst = ['mayor', main.local.name, None]
        route = odict([('src', src), ('dst', dst)])
        stuff = ["As you wish."]
        for i in range(10000):
            stuff.append(str(i).rjust(10, " "))
        stuff = "".join(stuff)
        others = []
        others.append(odict([('route', route), ('content', stuff)]))

        self.message(main,  other, mains, others, duration=1.0)

        self.assertEqual(main.remotes[main.uids['other']].rsid,
                         other.remotes[other.uids['main']].sid)
        self.assertEqual(other.remotes[other.uids['main']].rsid,
                         main.remotes[main.uids['other']].sid)

        #now close down and reload data, make new stacks with saved data
        main.server.close()
        other.server.close()
        main = stacking.LaneStack(dirpath=mainData['dirpath'], store=self.store)
        other = stacking.LaneStack(dirpath=otherData['dirpath'], store=self.store)

        self.assertEqual(len(main.remotes), 1)
        self.assertTrue('other' in main.uids)
        self.assertEqual(len(other.remotes), 1)
        self.assertTrue('main' in other.uids)

        self.assertEqual(main.remotes[main.uids['other']].sid, 3)
        self.assertEqual(other.remotes[other.uids['main']].sid, 3)
        self.assertEqual(main.remotes[main.uids['other']].rsid, 0)
        self.assertEqual(other.remotes[other.uids['main']].rsid, 0)

        for msg in mains:
            main.transmit(msg, duid=main.uids[other.local.name])
        for msg in others:
            other.transmit(msg,  duid=other.uids[main.local.name])


        self.assertEqual(len(main.txMsgs), 1)
        self.assertEqual(len(other.txMsgs), 1)
        self.assertEqual(len(main.remotes[main.uids['other']].books), 0)
        self.assertEqual(len(other.remotes[other.uids['main']].books), 0)
        self.assertEqual(len(main.rxMsgs), 0)
        self.assertEqual(len(other.rxMsgs), 0)

        # Now only send and receive one page to/from each side
        self.serviceOneAll(main, other)

        self.assertEqual(len(main.txMsgs), 0)
        self.assertEqual(len(other.txMsgs), 0)
        self.assertEqual(len(main.txes), 1)
        self.assertEqual(len(other.txes), 1)
        self.assertEqual(len(main.remotes[main.uids['other']].books), 1)
        self.assertEqual(len(other.remotes[other.uids['main']].books), 1)
        self.assertEqual(len(main.rxMsgs), 0)
        self.assertEqual(len(other.rxMsgs), 0)

        self.assertEqual(main.remotes[main.uids['other']].rsid,
                         other.remotes[other.uids['main']].sid)
        self.assertEqual(other.remotes[other.uids['main']].rsid,
                         main.remotes[main.uids['other']].sid)

        #now close down one side only and reload data, make new stack with saved data
        main.server.close()
        main = stacking.LaneStack(dirpath=mainData['dirpath'], store=self.store)


        self.assertEqual(main.remotes[main.uids['other']].sid, 4)
        self.assertEqual(other.remotes[other.uids['main']].sid, 3)
        self.assertEqual(main.remotes[main.uids['other']].rsid, 0)
        self.assertEqual(other.remotes[other.uids['main']].rsid, 3)
        self.assertEqual(len(main.txes), 0)
        self.assertEqual(len(other.txes), 1)
        self.assertEqual(len(main.remotes[main.uids['other']].books), 0)
        self.assertEqual(len(other.remotes[other.uids['main']].books), 1)
        self.assertEqual(len(main.rxMsgs), 0)
        self.assertEqual(len(other.rxMsgs), 0)

        # Now remaining page from other (there should be no pages from main)
        self.serviceOneAll(main, other)

        self.assertEqual(main.remotes[main.uids['other']].sid, 4)
        self.assertEqual(other.remotes[other.uids['main']].sid, 3)
        self.assertEqual(main.remotes[main.uids['other']].rsid, 3)
        self.assertEqual(other.remotes[other.uids['main']].rsid, 3)
        self.assertEqual(len(main.txes), 0)
        self.assertEqual(len(other.txes), 0)
        self.assertEqual(len(main.remotes[main.uids['other']].books), 0)
        self.assertEqual(len(other.remotes[other.uids['main']].books), 1)
        self.assertEqual(len(main.rxMsgs), 0)
        self.assertEqual(len(other.rxMsgs), 0)
        self.assertEqual(main.stats['missed_page'], 1)


        #send a new message from main and reap stale book from other
        for msg in mains:
            main.transmit(msg, duid=main.uids[other.local.name])

        self.service(main, other, duration=1.0)

        self.assertEqual(main.remotes[main.uids['other']].sid, 4)
        self.assertEqual(other.remotes[other.uids['main']].sid, 3)
        self.assertEqual(main.remotes[main.uids['other']].rsid, 3)
        self.assertEqual(other.remotes[other.uids['main']].rsid, 4)
        self.assertEqual(len(main.txes), 0)
        self.assertEqual(len(other.txes), 0)
        self.assertEqual(len(main.remotes[main.uids['other']].books), 0)
        self.assertEqual(len(other.remotes[other.uids['main']].books), 0)
        self.assertEqual(len(main.rxMsgs), 0)
        self.assertEqual(len(other.rxMsgs), 1)
        self.assertEqual(other.stats['stale_book'], 1)

        self.assertEqual(len(other.rxMsgs), len(mains))
        for i, msg in enumerate(other.rxMsgs):
            console.terse("Yard '{0}' rxed:\n'{1}'\n".format(other.local.name, msg))
            self.assertDictEqual(mains[i], msg)


        # setup to test reset sid numbering by sending single pages to create stale books

        other.rxMsgs.pop()
        for msg in mains:
            main.transmit(msg, duid=main.uids[other.local.name])
        for msg in others:
            other.transmit(msg,  duid=other.uids[main.local.name])

        self.serviceOneAll(main, other)

        self.assertEqual(main.remotes[main.uids['other']].sid, 4)
        self.assertEqual(other.remotes[other.uids['main']].sid, 3)
        self.assertEqual(main.remotes[main.uids['other']].rsid, 3)
        self.assertEqual(other.remotes[other.uids['main']].rsid, 4)
        self.assertEqual(len(main.txes), 1)
        self.assertEqual(len(other.txes), 1)
        self.assertEqual(len(main.remotes[main.uids['other']].books), 1)
        self.assertEqual(len(other.remotes[other.uids['main']].books), 1)
        self.assertEqual(len(main.rxMsgs), 0)
        self.assertEqual(len(other.rxMsgs), 0)

        # simulate restart that loses msg in queue
        main.txes.pop()
        other.txes.pop()

        src = ['mayor', main.local.name, None] # (house, yard, queue)
        dst = ['citizen', other.local.name, None]
        route = odict([('src', src), ('dst', dst)])
        stuff = "This is my command"
        mains = []
        mains.append(odict([('route', route), ('content', stuff)]))

        src = ['citizen', other.local.name, None]
        dst = ['mayor', main.local.name, None]
        route = odict([('src', src), ('dst', dst)])
        stuff = "This is my reply."
        others = []
        others.append(odict([('route', route), ('content', stuff)]))

        main.remotes[main.uids['other']].sid = 0 #set to zero to reset
        other.remotes[other.uids['main']].sid = 0 #set to zero to reset
        for msg in mains:
            main.transmit(msg, duid=main.uids[other.local.name])
        for msg in others:
            other.transmit(msg,  duid=other.uids[main.local.name])

        self.serviceOneAll(main, other)

        self.assertEqual(main.remotes[main.uids['other']].sid, 0)
        self.assertEqual(other.remotes[other.uids['main']].sid, 0)
        self.assertEqual(main.remotes[main.uids['other']].rsid, 0)
        self.assertEqual(other.remotes[other.uids['main']].rsid, 0)
        self.assertEqual(len(main.txes), 0)
        self.assertEqual(len(other.txes), 0)
        self.assertEqual(len(main.remotes[main.uids['other']].books), 0)
        self.assertEqual(len(other.remotes[other.uids['main']].books), 0)
        self.assertEqual(len(main.rxMsgs), 1)
        self.assertEqual(len(other.rxMsgs), 1)
        self.assertEqual(main.stats['stale_book'], 1)
        self.assertEqual(other.stats['stale_book'], 2)

        main.server.close()
        main.clearLocal()
        main.clearRemoteKeeps()

        other.server.close()
        other.clearLocal()
        other.clearRemoteKeeps()
Beispiel #6
0
def test(preClearMaster=True, preClearMinion=True, postClearMaster=True, postClearMinion=True):
    """
    initially
    master on port 7530 with eid of 1
    minion on port 7531 with eid of 0
    eventually
    master eid of 1
    minion eid of 2
    """
    console.reinit(verbosity=console.Wordage.concise)

    store = storing.Store(stamp=0.0)

    # master stack
    masterName = "master"
    signer = nacling.Signer()
    masterSignKeyHex = signer.keyhex
    privateer = nacling.Privateer()
    masterPriKeyHex = privateer.keyhex
    masterDirpath = os.path.join("/tmp/raet/road", "keep", masterName)

    # minion0 stack
    minionName0 = "minion0"
    signer = nacling.Signer()
    minionSignKeyHex = signer.keyhex
    privateer = nacling.Privateer()
    minionPriKeyHex = privateer.keyhex
    m0Dirpath = os.path.join("/tmp/raet/road", "keep", minionName0)

    if preClearMaster:
        keeping.clearAllKeepSafe(masterDirpath)
    if preClearMinion:
        keeping.clearAllKeepSafe(m0Dirpath)

    local = estating.LocalEstate(eid=1, name=masterName, sigkey=masterSignKeyHex, prikey=masterPriKeyHex)
    stack0 = stacking.RoadStack(name=masterName, local=local, auto=True, store=store, main=True, dirpath=masterDirpath)

    local = estating.LocalEstate(
        eid=0, name=minionName0, ha=("", raeting.RAET_TEST_PORT), sigkey=minionSignKeyHex, prikey=minionPriKeyHex
    )
    stack1 = stacking.RoadStack(name=minionName0, local=local, store=store, dirpath=m0Dirpath)

    print "\n********* Join Forever Transaction **********"
    # transacting.Joiner.Timeout = 0 # make join go on forever
    stack1.join(timeout=0.0)  # make join go on forever
    timer = StoreTimer(store=store, duration=30.0)
    while (stack1.transactions or stack0.transactions) and not timer.expired:
        stack1.serviceAll()
        if timer.elapsed > 20.0:
            stack0.serviceAll()
        store.advanceStamp(0.1)

    for remote in stack0.remotes.values():
        print "{0} Remote Estate {1} joined= {2}".format(stack0.name, remote.eid, remote.joined)
    for remote in stack1.remotes.values():
        print "{0} Remote Estate {1} joined= {2}".format(stack1.name, remote.eid, remote.joined)

    print "{0} Stats".format(stack0.name)
    for key, val in stack0.stats.items():
        print "   {0}={1}".format(key, val)
    print
    print "{0} Stats".format(stack1.name)
    for key, val in stack1.stats.items():
        print "   {0}={1}".format(key, val)
    print

    print "\n********* Join Default Timeout Transaction **********"
    stack1.join(timeout=None)
    timer.restart()
    while (stack1.transactions or stack0.transactions) and not timer.expired:
        stack1.serviceAll()
        if timer.elapsed > 20.0:
            stack0.serviceAll()
        store.advanceStamp(0.1)

    for remote in stack0.remotes.values():
        print "{0} Remote Estate {1} joined= {2}".format(stack0.name, remote.eid, remote.joined)
    for remote in stack1.remotes.values():
        print "{0} Remote Estate {1} joined= {2}".format(stack1.name, remote.eid, remote.joined)
    print "{0} Stats".format(stack0.name)
    for key, val in stack0.stats.items():
        print "   {0}={1}".format(key, val)
    print
    print "{0} Stats".format(stack1.name)
    for key, val in stack1.stats.items():
        print "   {0}={1}".format(key, val)
    print

    for uid in stack0.remotes:
        stack0.removeRemote(uid)
    for uid in stack1.remotes:
        stack1.removeRemote(uid)

    if postClearMaster:
        keeping.clearAllKeepSafe(masterDirpath)
    if postClearMinion:
        keeping.clearAllKeepSafe(m0Dirpath)

    print "Road {0}".format(stack0.name)
    print stack0.keep.loadLocalData()
    print stack0.keep.loadAllRemoteData()
    print "Safe {0}".format(stack0.name)
    print stack0.safe.loadLocalData()
    print stack0.safe.loadAllRemoteData()
    print

    print "Road {0}".format(stack1.name)
    print stack1.keep.loadLocalData()
    print stack1.keep.loadAllRemoteData()
    print "Safe {0}".format(stack1.name)
    print stack1.safe.loadLocalData()
    print stack1.safe.loadAllRemoteData()
    print

    print "\n********* Join Default Timeout Transaction After Clear Keeps **********"
    stack1.join(timeout=None)
    timer.restart()
    while (stack1.transactions or stack0.transactions) and not timer.expired:
        stack1.serviceAll()
        if timer.elapsed > 20.0:
            stack0.serviceAll()
        store.advanceStamp(0.1)

    for remote in stack0.remotes.values():
        print "{0} Remote Estate {1} joined= {2}".format(stack0.name, remote.eid, remote.joined)
    for remote in stack1.remotes.values():
        print "{0} Remote Estate {1} joined= {2}".format(stack1.name, remote.eid, remote.joined)

    print "{0} Stats".format(stack0.name)
    for key, val in stack0.stats.items():
        print "   {0}={1}".format(key, val)
    print
    print "{0} Stats".format(stack1.name)
    for key, val in stack1.stats.items():
        print "   {0}={1}".format(key, val)
    print

    print "\n********* Join Forever Timeout Transaction After Clear Keeps**********"
    stack1.join(timeout=0.0)
    timer.restart()
    while (stack1.transactions or stack0.transactions) and not timer.expired:
        stack1.serviceAll()
        if timer.elapsed > 20.0:
            stack0.serviceAll()
        store.advanceStamp(0.1)

    for remote in stack0.remotes.values():
        print "{0} Remote Estate {1} joined= {2}".format(stack0.name, remote.eid, remote.joined)
    for remote in stack1.remotes.values():
        print "{0} Remote Estate {1} joined= {2}".format(stack1.name, remote.eid, remote.joined)

    print "{0} Stats".format(stack0.name)
    for key, val in stack0.stats.items():
        print "   {0}={1}".format(key, val)
    print
    print "{0} Stats".format(stack1.name)
    for key, val in stack1.stats.items():
        print "   {0}={1}".format(key, val)
    print

    stack0.server.close()
    stack1.server.close()

    if postClearMaster:
        keeping.clearAllKeepSafe(masterDirpath)
    if postClearMinion:
        keeping.clearAllKeepSafe(m0Dirpath)
Beispiel #7
0
class BasicTestCase(unittest.TestCase):
    """"""

    def setUp(self):
        self.store = storing.Store(stamp=0.0)
        self.timer = StoreTimer(store=self.store, duration=1.0)

        self.baseDirpath = os.path.join(
                tempfile.mkdtemp(prefix="raet",  suffix="base", dir='/tmp'),
                'lane')

        # main stack
        self.main = stacking.LaneStack(name='main',
                                    lanename='cherry',
                                    yardname='main',
                                    dirpath=self.baseDirpath,
                                    sockdirpath=self.baseDirpath)

        #other stack
        self.other = stacking.LaneStack(name='other',
                                    lanename='cherry',
                                    yardname='other',
                                    dirpath=self.baseDirpath,
                                    sockdirpath=self.baseDirpath)

    def tearDown(self):
        self.main.server.close()
        self.other.server.close()

        if os.path.exists(self.baseDirpath):
            shutil.rmtree(self.baseDirpath)

    def service(self, duration=1.0, real=True):
        '''
        Utility method to service queues. Call from test method.
        '''
        self.timer.restart(duration=duration)
        while not self.timer.expired:
            self.other.serviceAll()
            self.main.serviceAll()
            self.store.advanceStamp(0.1)
            if real:
                time.sleep(0.1)

    def serviceOther(self, duration=1.0, real=True):
        '''
        Utility method to only service other queues. Call from test method.
        '''
        self.timer.restart(duration=duration)
        while not self.timer.expired:
            self.other.serviceAll()
            self.store.advanceStamp(0.1)
            if real:
                time.sleep(0.1)

    def serviceMain(self, duration=1.0, real=True):
        '''
        Utility method to only service main queues. Call from test method.
        '''
        self.timer.restart(duration=duration)
        while not self.timer.expired:
            self.main.serviceAll()
            self.store.advanceStamp(0.1)
            if real:
                time.sleep(0.1)


    def bootstrap(self, kind=raeting.packKinds.json):
        '''
        Basic messaging
        '''
        self.main.addRemote(yarding.RemoteYard(ha=self.other.local.ha))
        self.other.addRemote(yarding.RemoteYard(ha=self.main.local.ha))

        self.assertEqual(self.main.name, 'main')
        self.assertEqual(self.main.local.name, 'main')
        self.assertEqual(self.main.local.ha, os.path.join(self.baseDirpath, 'cherry.main.uxd'))
        self.assertEqual(len(self.main.remotes), 1)
        remote = self.main.remotes.values()[0]
        self.assertEqual(remote.ha, os.path.join(self.baseDirpath, 'cherry.other.uxd'))
        self.assertEqual(remote.name, 'other')
        self.assertTrue(remote.uid in self.main.remotes)
        self.assertTrue(remote.name in self.main.uids)
        self.assertIs(self.main.remotes[self.main.uids[remote.name]], remote)


        self.assertEqual(self.other.name, 'other')
        self.assertEqual(self.other.local.name, 'other')
        self.assertEqual(self.other.local.ha, os.path.join(self.baseDirpath, 'cherry.other.uxd'))
        self.assertEqual(len(self.other.remotes), 1)
        remote = self.other.remotes.values()[0]
        self.assertEqual(remote.ha, os.path.join(self.baseDirpath, 'cherry.main.uxd'))
        self.assertEqual(remote.name, 'main')
        self.assertTrue(remote.uid in self.other.remotes)
        self.assertTrue(remote.name in self.other.uids)
        self.assertIs(self.other.remotes[self.other.uids[remote.name]], remote)

        stacking.LaneStack.Pk = kind

    def message(self, mains, others, duration=1.0):
        '''
        Transmit and reciev messages in mains and others lists
        '''
        for msg in mains:
            self.main.transmit(msg=msg)

        for msg in others:
            self.other.transmit(msg=msg)

        self.service(duration=duration)

        self.assertEqual(len(self.main.rxMsgs), len(others))
        for i, msg in enumerate(self.main.rxMsgs):
            console.terse("Yard '{0}' rxed:\n'{1}'\n".format(self.main.local.name, msg))
            self.assertDictEqual(others[i], msg)

        self.assertEqual(len(self.other.rxMsgs), len(mains))
        for i, msg in enumerate(self.other.rxMsgs):
            console.terse("Yard '{0}' rxed:\n'{1}'\n".format(self.other.local.name, msg))
            self.assertDictEqual(mains[i], msg)

    def testMessageJson(self):
        '''
        Basic messaging with json packing
        '''
        console.terse("{0}\n".format(self.testMessageJson.__doc__))
        self.bootstrap(kind=raeting.packKinds.json)

        mains = []
        mains.append(odict(what="This is a message to the serf. Get to Work", extra="Fix the fence."))

        others = []
        others.append(odict(what="This is a message to the lord. Let me be", extra="Go away."))

        self.message(mains=mains, others=others)

    def testMessageMsgpack(self):
        '''
        Basic messaging with msgpack packing
        '''
        console.terse("{0}\n".format(self.testMessageMsgpack.__doc__))
        self.bootstrap(kind=raeting.packKinds.pack)

        mains = []
        mains.append(odict(what="This is a message to the serf. Get to Work", extra="Fix the fence."))

        others = []
        others.append(odict(what="This is a message to the lord. Let me be", extra="Go away."))

        self.message(mains=mains, others=others)

    def testMessageMultipleJson(self):
        '''
        Multiple messages with json packing
        '''
        console.terse("{0}\n".format(self.testMessageMultipleJson.__doc__))
        self.bootstrap(kind=raeting.packKinds.json)

        mains = []
        mains.append(odict([('house', "Mama mia1"), ('queue', "fix me")]))
        mains.append(odict([('house', "Mama mia2"), ('queue', "stop me")]))
        mains.append(odict([('house', "Mama mia3"), ('queue', "help me")]))
        mains.append(odict([('house', "Mama mia4"), ('queue', "run me")]))


        others = []
        others.append(odict([('house', "Papa pia1"), ('queue', "fix me")]))
        others.append(odict([('house', "Papa pia1"), ('queue', "stop me")]))
        others.append(odict([('house', "Papa pia1"), ('queue', "help me")]))
        others.append(odict([('house', "Papa pia1"), ('queue', "run me")]))

        self.message(mains=mains, others=others)

    def testMessageMultipleMsgpack(self):
        '''
        multiple messages with msgpack packing
        '''
        console.terse("{0}\n".format(self.testMessageMultipleMsgpack.__doc__))
        self.bootstrap(kind=raeting.packKinds.pack)

        mains = []
        mains.append(odict([('house', "Mama mia1"), ('queue', "fix me")]))
        mains.append(odict([('house', "Mama mia2"), ('queue', "stop me")]))
        mains.append(odict([('house', "Mama mia3"), ('queue', "help me")]))
        mains.append(odict([('house', "Mama mia4"), ('queue', "run me")]))


        others = []
        others.append(odict([('house', "Papa pia1"), ('queue', "fix me")]))
        others.append(odict([('house', "Papa pia1"), ('queue', "stop me")]))
        others.append(odict([('house', "Papa pia1"), ('queue', "help me")]))
        others.append(odict([('house', "Papa pia1"), ('queue', "run me")]))
        self.message(mains=mains, others=others)

    def testMessageSectionedJson(self):
        '''
        Sectioned messages with json packing
        '''
        console.terse("{0}\n".format(self.testMessageSectionedJson.__doc__))

        self.bootstrap(kind=raeting.packKinds.json)

        #big packets
        stuff = []
        for i in range(10000):
            stuff.append(str(i).rjust(10, " "))
        stuff = "".join(stuff)

        src = ['mayor', self.main.local.name, None]
        dst = ['citizen', self.other.local.name, None]
        route = odict([('src', src), ('dst', dst)])


        mains = []
        mains.append(odict([('route', route), ('content', stuff)]))

        src = ['citizen', self.other.local.name, None]
        dst = ['mayor', self.main.local.name, None]
        route = odict([('src', src), ('dst', dst)])

        others = []
        others.append(odict([('route', route), ('content', stuff)]))

        self.message(mains=mains, others=others, duration=2.0)

    def testMessageSectionedMsgpack(self):
        '''
        Sectioned messages with msgpack packing
        '''
        console.terse("{0}\n".format(self.testMessageSectionedMsgpack.__doc__))

        self.bootstrap(kind=raeting.packKinds.pack)

        #big packets
        stuff = []
        for i in range(10000):
            stuff.append(str(i).rjust(10, " "))
        stuff = "".join(stuff)

        src = ['mayor', self.main.local.name, None]
        dst = ['citizen', self.other.local.name, None]
        route = odict([('src', src), ('dst', dst)])


        mains = []
        mains.append(odict([('route', route), ('content', stuff)]))

        src = ['citizen', self.other.local.name, None]
        dst = ['mayor', self.main.local.name, None]
        route = odict([('src', src), ('dst', dst)])

        others = []
        others.append(odict([('route', route), ('content', stuff)]))

        self.message(mains=mains, others=others, duration=2.0)

    def testAutoAccept(self):
        '''
        Basic send auto accept message
        '''
        console.terse("{0}\n".format(self.testAutoAccept.__doc__))

        self.assertTrue(self.main.accept)

        # Don't add remote yard to main so only way to get message from other is
        # if auto acccept works
        self.other.addRemote(yarding.RemoteYard(ha=self.main.local.ha))

        self.assertEqual(self.main.name, 'main')
        self.assertEqual(self.main.local.name, 'main')
        self.assertEqual(self.main.local.ha, os.path.join(self.baseDirpath, 'cherry.main.uxd'))
        self.assertEqual(len(self.main.remotes), 0)

        self.assertEqual(self.other.name, 'other')
        self.assertEqual(self.other.local.name, 'other')
        self.assertEqual(self.other.local.ha, os.path.join(self.baseDirpath, 'cherry.other.uxd'))
        self.assertEqual(len(self.other.remotes), 1)
        remote = self.other.remotes.values()[0]
        self.assertEqual(remote.ha, os.path.join(self.baseDirpath, 'cherry.main.uxd'))
        self.assertEqual(remote.name, 'main')
        self.assertTrue(remote.uid in self.other.remotes)
        self.assertTrue(remote.name in self.other.uids)
        self.assertIs(self.other.remotes[self.other.uids[remote.name]], remote)

        stacking.LaneStack.Pk = raeting.packKinds.pack

        others = []
        others.append(odict(what="This is a message to the lord. Let me be", extra="Go away."))

        self.message(mains=[], others=others)

        self.assertEqual(len(self.main.remotes), 1)
        remote = self.main.remotes.values()[0]
        self.assertEqual(remote.ha, os.path.join(self.baseDirpath, 'cherry.other.uxd'))
        self.assertEqual(remote.name, 'other')
        self.assertTrue(remote.uid in self.main.remotes)
        self.assertTrue(remote.name in self.main.uids)
        self.assertIs(self.main.remotes[self.main.uids[remote.name]], remote)

        self.main.rxMsgs = deque()
        self.other.rxMsgs = deque()

        mains = []
        mains.append(odict(what="This is a message to the serf. Get to Work", extra="Fix the fence."))

        self.message(mains=mains, others=[])

    def testAutoAcceptNot(self):
        '''
        Basic send non auto accept message
        '''
        console.terse("{0}\n".format(self.testAutoAcceptNot.__doc__))
        self.main.accept =  False
        self.assertIs(self.main.accept, False)

        # Don't add remote yard to main so only way to get message from other is
        # if auto acccept works
        self.other.addRemote(yarding.RemoteYard(ha=self.main.local.ha))

        self.assertEqual(self.main.name, 'main')
        self.assertEqual(self.main.local.name, 'main')
        self.assertEqual(self.main.local.ha, os.path.join(self.baseDirpath, 'cherry.main.uxd'))
        self.assertEqual(len(self.main.remotes), 0)

        self.assertEqual(self.other.name, 'other')
        self.assertEqual(self.other.local.name, 'other')
        self.assertEqual(self.other.local.ha, os.path.join(self.baseDirpath, 'cherry.other.uxd'))
        self.assertEqual(len(self.other.remotes), 1)
        remote = self.other.remotes.values()[0]
        self.assertEqual(remote.ha, os.path.join(self.baseDirpath, 'cherry.main.uxd'))
        self.assertEqual(remote.name, 'main')
        self.assertTrue(remote.uid in self.other.remotes)
        self.assertTrue(remote.name in self.other.uids)
        self.assertIs(self.other.remotes[self.other.uids[remote.name]], remote)

        stacking.LaneStack.Pk = raeting.packKinds.pack

        others = []
        others.append(odict(what="This is a message to the lord. Let me be", extra="Go away."))

        for msg in others:
            self.other.transmit(msg=msg)

        self.service()

        self.assertEqual(len(self.main.rxMsgs), 0)
        self.assertEqual(len(self.main.remotes), 0)
        self.assertEqual(self.main.stats['unaccepted_source_yard'], 1)
Beispiel #8
0
class BasicLoadTestCase(unittest.TestCase):
    '''
    Base class for load tests. Provides generic master/slave runners with flooding and checking logic.
    '''

    def __init__(self, *args, **kwargs):
        super(BasicLoadTestCase, self).__init__(*args, **kwargs)

    def setUp(self):
        self.store = storing.Store(stamp=0.0)
        self.timer = StoreTimer(store=self.store, duration=1.0)
        self.baseDirpath = tempfile.mkdtemp(prefix="raet",  suffix="base", dir=TEMPDIR)
        self.stack = None
        # This has to be set to True in the only one process that would perform tearDown steps
        self.engine = True
        stacking.RoadStack.BurstSize = 100

    def tearDown(self):
        # The only engine have to tear down stacks after all workers have done
        if not self.engine:
            if self.stack:
                self.stack.server.close()
                self.stack.clearAllDir()
        else:
            if os.path.exists(self.baseDirpath):
                shutil.rmtree(self.baseDirpath)

    def createStack(self, name, port):
        '''
        Create a RoadStack object bound to the specified port on localhost.

        :param name: stack name
        :param port: port to bind to
        :return: the stack
        '''
        dirpath = os.path.join(self.baseDirpath, 'road', 'keep', name)
        signer = nacling.Signer()
        mainSignKeyHex = signer.keyhex
        privateer = nacling.Privateer()
        mainPriKeyHex = privateer.keyhex

        keeping.clearAllKeep(dirpath)

        return stacking.RoadStack(store=self.store,
                                  name=name,
                                  main=True,
                                  auto=raeting.AutoMode.once.value,
                                  ha=("", port),
                                  sigkey=mainSignKeyHex,
                                  prikey=mainPriKeyHex,
                                  dirpath=dirpath,
                                  )

    def joinAll(self, initiator, correspondentAddresses, timeout=None, retryCount=1):
        '''
        Utility method to do join.

        :param initiator: join initiator stack
        :param correspondentAddresses: an iterable object containing ha tuples
        :param timeout: join timeout, will be passed to stack
        :param retryCount: retry join max the specified count of times until success
        '''
        console.terse("\nJoin Transaction **************\n")
        addresses = list(correspondentAddresses)
        for ha in addresses:
            initiator.addRemote(estating.RemoteEstate(stack=initiator,
                                                      fuid=0,  # vacuous join
                                                      sid=0,  # always 0 for join
                                                      ha=ha))
        while retryCount > 0:
            done = True
            for remote in initiator.remotes.values():
                if not remote.joined:
                    done = False
                    initiator.join(uid=remote.uid, timeout=timeout)
            self.serviceOne(initiator)
            if done:
                break
            retryCount -= 1

    def allowAll(self, initiator, timeout=None, retryCount=1):
        '''
        Utility method to do allow.

        :param initiator: allow initiator stack
        :param timeout: allow timeout, will be passed to stack
        :param retryCount: retry allow max the specified count of times until success
        '''
        console.terse("\nAllow Transaction **************\n")
        while retryCount > 0:
            done = True
            for remote in initiator.remotes.values():
                if not remote.allowed:
                    done = False
                    initiator.allow(uid=remote.uid, timeout=timeout)
            self.serviceOne(initiator)
            if done:
                break
            retryCount -= 1

    def serviceAll(self, stacks, duration=100.0, timeout=0.0, step=0.1, exitCase=None):
        '''
        Utility method to service queues.

        :param stacks: iterable containing stacks to service
        :param duration: max service duration, actually could finish earlier if there still no transactions to service
        :param timeout: time to continue service even if there are no transactions
        :param step: timer step
        :param exitCase: stop immediately if this function return true
        :return: actual exit reason, could be one of 'duration', 'exitCase' or 'timeout'
        '''
        self.timer.restart(duration=duration)
        empty = False
        elapsed = self.timer.getElapsed()
        retReason = 'duration'
        while not self.timer.expired:
            for stack in stacks:
                stack.serviceAll()
            if any(stack.transactions for stack in stacks):
                empty = False  # reset nop timeout
            else:
                if exitCase and exitCase():
                    retReason = 'exitCase'
                    break
                if empty:
                    if self.timer.getElapsed() - elapsed > timeout:
                        retReason = 'timeout'
                        break
                else:
                    empty = True
                    elapsed = self.timer.getElapsed()
            self.store.advanceStamp(step)
            time.sleep(step)
        return retReason

    def serviceOne(self, stack, duration=100.0, timeout=0.0, step=0.1, exitCase=None):
        '''
        Utility method to service one stack. See :func:`serviceStacks`.
        '''
        return self.serviceAll([stack], duration, timeout, step, exitCase)

    def bidirectional(self, stack, duration=3.0):
        '''
        Simultaneously sends and receives test messages.
            - self.msgSize: message size
            - self.msgCount: per remote message count

        :param stack: the stack to service
        :param duration: service duration to prevent hang
        '''
        console.terse("\nMessages Bidirectional {0} *********\n".format(stack.name))
        verifier = data.MessageVerifier(size=self.msgSize, msgCount=self.msgCount, remoteCount=len(stack.remotes),
                                        house='manor', queue='stuff')
        received = 0
        expected = len(stack.remotes) * self.msgCount
        maxTransactions = MAX_TRANSACTIONS * len(stack.remotes)
        for msg in data.generateMessages(name=stack.name, size=self.msgSize, count=self.msgCount):
            for remote in stack.remotes.values():
                # send message
                stack.transmit(msg, uid=remote.uid)
                # service while there are too much transactions (but loops at least once)
                while True:
                    self.serviceOne(stack, duration=0.01, step=0.01)
                    # check received
                    if stack.rxMsgs:
                        received += len(stack.rxMsgs)
                        while stack.rxMsgs:
                            verifier.verifyMessage(stack.rxMsgs.popleft())
                    # keep servicing if there are a lot of transactions
                    if len(stack.transactions) <= maxTransactions:
                        break

        # all sent, continue handle received
        while received < expected:
            self.serviceOne(stack, duration=duration, timeout=duration,
                            exitCase=lambda: stack.rxMsgs)
            # if received nothing during timeout, assume we're done
            if not stack.rxMsgs:
                break
            received += len(stack.rxMsgs)
            while stack.rxMsgs:
                verifier.verifyMessage(stack.rxMsgs.popleft())

        # wait remaining messenger transactions if any to be closed
        if stack.transactions:
            self.serviceOne(stack, duration=duration)

        # Done. Wait others
        self.doneCounter.inc()
        elapsed = 0.0  # be safe from engine unexpected stop
        step = 1.0
        while not self.stopFlag.get() and elapsed < duration * 2:
            self.serviceOne(stack, duration=step, timeout=step)
            elapsed += step

        # check result
        console.terse("\nStack '{0}' uid={1}\n\tTransactions: {2}\n\trcv/exp: {3}/{4}\n\tStats: {5}\n"
                      .format(stack.name, stack.local.uid, stack.transactions, received, expected, stack.stats))
        rcvErrors = verifier.checkAllDone()
        if rcvErrors:
            console.terse("{0} received message with the following errors:\n".format(stack.name))
            for s in rcvErrors:
                console.terse("\t{0} from {1}\n".format(stack.name, s))
        self.assertEqual(len(stack.transactions), 0)
        self.assertEqual(len(rcvErrors), 0)
        self.assertEqual(received, expected)

    def send(self, stack, duration=3.0):
        '''
        Sends test messages.
            - self.msgSize: message size
            - self.msgCount: per remote message count

        :param stack: the stack to service
        :param duration: service duration to prevent hang
        '''
        console.terse("\nMessages Sender {0} *********\n".format(stack.name))
        maxTransactions = MAX_TRANSACTIONS * len(stack.remotes)
        for msg in data.generateMessages(name=stack.name, size=self.msgSize, count=self.msgCount):
            for remote in stack.remotes.values():
                # send message
                stack.transmit(msg, uid=remote.uid)
                # service while there are too much transactions (but loops at least once)
                while True:
                    self.serviceOne(stack, duration=0.01, step=0.01)
                    if len(stack.transactions) <= maxTransactions:
                        break

        # done, wait others
        self.doneCounter.inc()
        elapsed = 0.0  # be safe from engine unexpected stop
        step = 1.0
        while not self.stopFlag.get() and elapsed < duration * 2:
            self.serviceOne(stack, duration=step, timeout=step)
            elapsed += step

        # check result
        console.terse("\nStack '{0}' uid={1}\n\tTransactions: {2}\n\tStats: {3}\n"
                      .format(stack.name, stack.local.uid, stack.transactions, stack.stats))
        self.assertEqual(len(stack.transactions), 0)
        self.assertEqual(len(stack.rxMsgs), 0)

    def receive(self, stack, duration=3.0):
        '''
        Receives test messages.
            - self.msgSize: message size
            - self.msgCount: per remote message count

        :param stack: the stack to service
        :param duration: service duration to prevent hang
        '''
        console.terse("\nMessages Receiver {0} *********\n".format(stack.name))
        verifier = data.MessageVerifier(size=self.msgSize, msgCount=self.msgCount, remoteCount=len(stack.remotes),
                                        house='manor', queue='stuff')

        # Receive messages
        received = 0
        expected = len(stack.remotes) * self.msgCount
        while received < expected:
            reason = self.serviceOne(stack, duration=duration, timeout=duration,
                                     exitCase=lambda: stack.rxMsgs)
            console.terse("{0} service exit reason: {1}, transactions: {2}\n".format(
                stack.name, reason, stack.transactions))
            # received nothing during timeout, assume there is nothing to receive
            if not stack.rxMsgs:
                break
            received += len(stack.rxMsgs)
            while stack.rxMsgs:
                verifier.verifyMessage(stack.rxMsgs.popleft())

        # Done. Wait others
        self.doneCounter.inc()
        elapsed = 0.0  # be safe from engine unexpected stop
        step = 1.0
        while not self.stopFlag.get() and elapsed < duration * 2:
            self.serviceOne(stack, duration=step, timeout=step)
            elapsed += step

        # Verify results
        console.terse("\nStack '{0}' uid={1}\n\tTransactions: {2}\n\trcv/exp: {3}/{4}\n\tStats: {5}\n"
                      .format(stack.name, stack.local.uid, stack.transactions, received, expected, stack.stats))
        for t in stack.transactions:
            if isinstance(t, transacting.Messengent):
                print("Tray lost segments: {0}\n".format([i for i, x in enumerate(t.tray.segments) if x is None]))
        rcvErrors = verifier.checkAllDone()
        if rcvErrors:
            console.terse("{0} received message with the following errors:\n".format(stack.name))
            for s in rcvErrors:
                console.terse("\t{0} from {1}\n".format(stack.name, s))
        self.assertEqual(len(stack.transactions), 0)
        self.assertEqual(len(rcvErrors), 0)
        self.assertEqual(received, expected)

    def masterPeer(self, name, port, minionCount, action):
        '''
        Master peer main function. It creates a RoadStack, sends/receives a bunch of test messages to remote peers and
        checks the result

        :param name: the name of this peer
        :param port: port to bind to
        :param minionCount: count of remote peers
        :param action: action function. Could be one of self.send, self.receive or self.bidirectional
        :return: if done without errors the process will end with 0 exit code
        '''
        self.engine = False
        # create stack
        self.stack = self.createStack(name, port)

        console.terse("\nCreated {0} at {1} *********\n".format(name, self.stack.ha))

        console.terse("\n{0} Waiting For Minions *********\n".format(name))

        # wait minions to join and allow
        def isBootstrapDone():
            if not self.stack.remotes:
                return False
            if len(self.stack.remotes) != minionCount:
                return False
            for rmt in self.stack.remotes.values():
                if not rmt.allowed:
                    return False
            return True

        serviceCode = self.serviceOne(self.stack, timeout=100.0, exitCase=isBootstrapDone)

        console.terse("\n{0} bootstrap done with code {1}".format(name, serviceCode))

        # verify all minions connected
        self.assertEqual(len(self.stack.transactions), 0)
        self.assertEqual(len(self.stack.remotes), minionCount)
        for remote in self.stack.remotes.values():
            self.assertTrue(remote.joined)
            self.assertTrue(remote.allowed)

        console.terse("\n{0} Bootstrap Done ({1}) *********\n".format(name, serviceCode))
        # do the job
        action(self.stack, duration=self.duration)

    def minionPeer(self, name, port, remoteAddresses, action):
        '''
        Slave peer main function. It creates a RoadStack, sends/receives a bunch of test messages to remote peers and
        checks the result

        :param name: the name of this peer
        :param port: port to bind to
        :param minionCount: count of remote peers
        :param action: action function. Could be one of self.send, self.receive or self.bidirectional
        :return: if done without errors the process will end with 0 exit code
        '''
        self.engine = False
        # Create stack
        self.stack = self.createStack(name, port)

        console.terse("\nCreated {0} at {1} *********\n".format(name, self.stack.ha))

        console.terse("\n{0} Joining Remotes *********\n".format(name))
        # join with all masters
        self.joinAll(self.stack, remoteAddresses, retryCount=10)
        self.assertEqual(len(self.stack.transactions), 0)
        self.assertEqual(len(self.stack.remotes), len(remoteAddresses))
        for remote in self.stack.remotes.values():
            self.assertTrue(remote.joined, "{0}: remote '{1}' at {2} is not joined".format(
                name, remote.name, remote.ha))

        console.terse("\n{0} Allowing Remotes *********\n".format(name))
        # allow all masters
        self.allowAll(self.stack, retryCount=10)
        self.assertEqual(len(self.stack.transactions), 0)
        self.assertEqual(len(self.stack.remotes), len(remoteAddresses))
        for remote in self.stack.remotes.values():
            self.assertTrue(remote.allowed, "{0}: remote '{1}' at {2} is not allowed".format(
                name, remote.name, remote.ha))

        console.terse("\n{0} Bootstrap Done *********\n".format(name))
        # do the job
        action(self.stack, duration=self.duration)

    def messagingMultiPeers(self,
                            masterCount,
                            minionCount,
                            msgSize,
                            msgCount,
                            duration,
                            direction):
        '''
        Perform the test. This function creates a number of processes which are master and slave network peers. Each
        process sends a bunch of messages to each process from the opposite group (for bidirectional case)

        :param masterCount: count of master peers
        :param minionCount: count of slave peers
        :param msgSize: size of the message stuff, actually the message would be bigger
        :param msgCount: count of messages to be sent from peer to peer
        :param duration: test duration limit, will be used in service calls so actual allowed duration will be greater
        :param direction: sending duration, could be one of DIR_TO_MASTER, DIR_FROM_MASTER or DIR_BIDIRECTIONAL
        :return: throw PyUnit assertion if fail
        '''
        self.masterCount = masterCount
        self.minionCount = minionCount
        self.msgSize = msgSize
        self.msgCount = msgCount
        self.duration = duration
        masterDir = {DIR_BIDIRECTIONAL: self.bidirectional,
                     DIR_TO_MASTER:     self.receive,
                     DIR_FROM_MASTER:   self.send}
        minionDir = {DIR_BIDIRECTIONAL: self.bidirectional,
                     DIR_TO_MASTER:     self.send,
                     DIR_FROM_MASTER:   self.receive}

        # create masters
        port = raeting.RAET_PORT
        masterHostAddresses = []
        masterProcs = []
        self.doneCounter = mp_helper.Counter()
        self.stopFlag = mp_helper.Counter()
        for i in xrange(masterCount):
            masterHostAddresses.append(('', port))
            name = 'master{0}'.format(i)
            masterProc = multiprocessing.Process(target=self.masterPeer,
                                                 name=name,
                                                 args=(name,
                                                       port,
                                                       minionCount,
                                                       masterDir[direction]))
            masterProcs.append(masterProc)
            port += 1

        # create minions
        minionProcs = []
        for i in xrange(minionCount):
            name = 'minion{0}'.format(i)
            minionProc = multiprocessing.Process(target=self.minionPeer,
                                                 name=name,
                                                 args=(name,
                                                       port,
                                                       masterHostAddresses,
                                                       minionDir[direction]))
            minionProcs.append(minionProc)
            port += 1

        # start masters first
        for proc in masterProcs:
            proc.start()
        time.sleep(1.0)  # let masters start
        # start minions
        for proc in minionProcs:
            proc.start()

        # wait until all workers done their job
        elapsed = 0.0  # be safe from worker unexpected stop
        step = 1.0
        while self.doneCounter.get() < masterCount + minionCount and elapsed < duration * 2:
            time.sleep(step)
            elapsed += step
        # set stop flag
        self.stopFlag.inc()

        # wait all processes exited
        for procs in (masterProcs, minionProcs):
            for proc in procs:
                proc.join()

        # ensure all workers successfully done
        for procs in (masterProcs, minionProcs):
            for proc in procs:
                self.assertEqual(proc.exitcode, 0, "'{0}' returned {1}".format(proc.name, proc.exitcode))
Beispiel #9
0
class BasicTestCase(unittest.TestCase):
    """"""

    def setUp(self):
        self.store = storing.Store(stamp=0.0)
        self.timer = StoreTimer(store=self.store, duration=1.0)

        self.tempDirPath = tempfile.mkdtemp(prefix="raet",  suffix="base", dir='/tmp')
        self.baseDirpath = os.path.join(self.tempDirPath, 'lane', 'keep')

        # main stack
        self.main = stacking.LaneStack(name='main',
                                       yid=1,
                                       lanename='cherry',
                                       sockdirpath=self.baseDirpath)

        #other stack
        self.other = stacking.LaneStack(name='other',
                                        yid=1,
                                        lanename='cherry',
                                        sockdirpath=self.baseDirpath)

    def tearDown(self):
        self.main.server.close()
        self.other.server.close()

    def service(self, duration=1.0, real=True):
        '''
        Utility method to service queues. Call from test method.
        '''
        self.timer.restart(duration=duration)
        while not self.timer.expired:
            self.other.serviceAll()
            self.main.serviceAll()
            self.store.advanceStamp(0.1)
            if real:
                time.sleep(0.1)

    def serviceOther(self, duration=1.0, real=True):
        '''
        Utility method to only service other queues. Call from test method.
        '''
        self.timer.restart(duration=duration)
        while not self.timer.expired:
            self.other.serviceAll()
            self.store.advanceStamp(0.1)
            if real:
                time.sleep(0.1)

    def serviceMain(self, duration=1.0, real=True):
        '''
        Utility method to only service main queues. Call from test method.
        '''
        self.timer.restart(duration=duration)
        while not self.timer.expired:
            self.main.serviceAll()
            self.store.advanceStamp(0.1)
            if real:
                time.sleep(0.1)

    def bootstrap(self, kind=raeting.packKinds.json):
        '''
        Basic messaging
        '''
        self.main.addRemote(yarding.RemoteYard(stack=self.main, ha=self.other.local.ha))
        self.other.addRemote(yarding.RemoteYard(stack=self.other, ha=self.main.local.ha))

        self.assertEqual(self.main.name, 'main')
        self.assertEqual(self.main.local.name, 'main')
        self.assertEqual(self.main.local.ha, os.path.join(self.baseDirpath, 'cherry.main.uxd'))
        self.assertEqual(len(self.main.remotes), 1)
        remote = self.main.remotes.values()[0]
        self.assertEqual(remote.ha, os.path.join(self.baseDirpath, 'cherry.other.uxd'))
        self.assertEqual(remote.name, 'other')
        self.assertTrue(remote.uid in self.main.remotes)
        self.assertTrue(remote.name in self.main.nameRemotes)
        self.assertTrue(remote.ha in self.main.haRemotes)
        self.assertIs(self.main.nameRemotes[remote.name], remote)
        self.assertIs(self.main.haRemotes[remote.ha], remote)


        self.assertEqual(self.other.name, 'other')
        self.assertEqual(self.other.local.name, 'other')
        self.assertEqual(self.other.local.ha, os.path.join(self.baseDirpath, 'cherry.other.uxd'))
        self.assertEqual(len(self.other.remotes), 1)
        remote = self.other.remotes.values()[0]
        self.assertEqual(remote.ha, os.path.join(self.baseDirpath, 'cherry.main.uxd'))
        self.assertEqual(remote.name, 'main')
        self.assertTrue(remote.uid in self.other.remotes)
        self.assertTrue(remote.name in self.other.nameRemotes)
        self.assertTrue(remote.ha in self.other.haRemotes)
        self.assertIs(self.other.nameRemotes[remote.name], remote)
        self.assertIs(self.other.haRemotes[remote.ha], remote)

        stacking.LaneStack.Pk = kind

    def message(self, mains, others, duration=1.0):
        '''
        Transmit and receive messages in mains and others lists
        '''
        for msg in mains:
            self.main.transmit(msg=msg)

        for msg in others:
            self.other.transmit(msg=msg)

        self.service(duration=duration)

        self.assertEqual(len(self.main.rxMsgs), len(others))
        for i, duple in enumerate(self.main.rxMsgs):
            console.terse("Yard '{0}' rxed:\n'{1}'\n".format(self.main.local.name, duple))
            self.assertDictEqual(others[i], duple[0])

        self.assertEqual(len(self.other.rxMsgs), len(mains))
        for i, duple in enumerate(self.other.rxMsgs):
            console.terse("Yard '{0}' rxed:\n'{1}'\n".format(self.other.local.name, duple))
            self.assertDictEqual(mains[i], duple[0])

    def createLaneData(self, name, yid, base, lanename, localname=''):
        '''
        Creates odict and populates with data to setup lane stack
        {
            name: stack name
            dirpath: dirpath for keep files
            lanename: name of yard
        }
        '''
        data = odict()
        data['name'] = name
        data['yid'] = yid
        data['sockdirpath'] = os.path.join(base, name)
        data['lanename'] = lanename
        data['localname'] = localname or name

        return data

    def createLaneStack(self, data, main=None):
        '''
        Creates stack and local yard from data
        returns stack

        '''
        stack = stacking.LaneStack(name=data['name'],
                                   yid=data['yid'],
                                   main=main,
                                   lanename=data['lanename'],
                                   sockdirpath=data['sockdirpath'])

        return stack

    def serviceMainOther(self, main, other, duration=1.0):
        '''
        Utility method to service queues. Call from test method.
        '''
        self.timer.restart(duration=duration)
        while not self.timer.expired:
            other.serviceAll()
            main.serviceAll()
            self.store.advanceStamp(0.1)
            time.sleep(0.1)


    def messageMainOther(self, main,  other, mains, others, duration=1.0):
        '''
        Utility to send messages both ways
        '''
        for msg in mains:
            main.transmit(msg, duid=main.fetchUidByName(other.local.name))
        for msg in others:
            other.transmit(msg,  duid=other.fetchUidByName(main.local.name))

        self.serviceMainOther(main, other, duration=duration)

        self.assertEqual(len(main.rxMsgs), len(others))
        for i, duple in enumerate(main.rxMsgs):
            console.terse("Yard '{0}' rxed:\n'{1}'\n".format(main.local.name, duple))
            self.assertDictEqual(others[i], duple[0])

        self.assertEqual(len(other.rxMsgs), len(mains))
        for i, duple in enumerate(other.rxMsgs):
            console.terse("Yard '{0}' rxed:\n'{1}'\n".format(other.local.name, duple))
            self.assertDictEqual(mains[i], duple[0])

    def serviceStackOneTx(self, stack):
        '''
        Utility method to service one packet on Tx queues. Call from test method.
        '''
        stack.serviceOneAllTx()
        time.sleep(0.1)
        self.store.advanceStamp(0.1)

    def serviceStackOneRx(self, stack):
        '''
        Utility method to service one packet on Rx queues. Call from test method.
        '''
        stack.serviceOneAllRx()
        time.sleep(0.1)
        self.store.advanceStamp(0.1)

    def serviceOneTx(self, main, other):
        '''
        Utility method to service one packet on Tx queues. Call from test method.
        '''
        other.serviceOneAllTx()
        main.serviceOneAllTx()
        time.sleep(0.1)
        self.store.advanceStamp(0.1)

    def serviceOneRx(self, main, other):
        '''
        Utility method to service one packet on Rx queues. Call from test method.
        '''
        other.serviceOneAllRx()
        main.serviceOneAllRx()
        time.sleep(0.1)
        self.store.advanceStamp(0.1)

    def serviceOneAll(self, main, other):
        '''
        Utility method to service one packet on all queues. Call from test method.
        '''
        self.serviceOneTx(main=main, other=other)
        self.serviceOneRx(main=main, other=other)


    def serviceStack(self, stack, duration=1.0):
        '''
        Utility method to service queues for one stack. Call from test method.
        '''
        self.timer.restart(duration=duration)
        while not self.timer.expired:
            stack.serviceAll()
            self.store.advanceStamp(0.1)
            time.sleep(0.1)

    def serviceStacks(self, stacks, duration=1.0):
        '''
        Utility method to service queues for list of stacks. Call from test method.
        '''
        self.timer.restart(duration=duration)
        while not self.timer.expired:
            for stack in stacks:
                stack.serviceAll()
            self.store.advanceStamp(0.1)
            time.sleep(0.1)

    def testMessageJson(self):
        '''
        Basic messaging with json packing
        '''
        console.terse("{0}\n".format(self.testMessageJson.__doc__))
        self.bootstrap(kind=raeting.packKinds.json)

        mains = []
        mains.append(odict(what="This is a message to the serf. Get to Work", extra="Fix the fence."))

        others = []
        others.append(odict(what="This is a message to the lord. Let me be", extra="Go away."))

        self.message(mains=mains, others=others)

    def testMessageMsgpack(self):
        '''
        Basic messaging with msgpack packing
        '''
        console.terse("{0}\n".format(self.testMessageMsgpack.__doc__))
        self.bootstrap(kind=raeting.packKinds.pack)

        mains = []
        mains.append(odict(what="This is a message to the serf. Get to Work", extra="Fix the fence."))

        others = []
        others.append(odict(what="This is a message to the lord. Let me be", extra="Go away."))

        self.message(mains=mains, others=others)

    def testMessageMultipleJson(self):
        '''
        Multiple messages with json packing
        '''
        console.terse("{0}\n".format(self.testMessageMultipleJson.__doc__))
        self.bootstrap(kind=raeting.packKinds.json)

        mains = []
        mains.append(odict([('house', "Mama mia1"), ('queue', "fix me")]))
        mains.append(odict([('house', "Mama mia2"), ('queue', "stop me")]))
        mains.append(odict([('house', "Mama mia3"), ('queue', "help me")]))
        mains.append(odict([('house', "Mama mia4"), ('queue', "run me")]))


        others = []
        others.append(odict([('house', "Papa pia1"), ('queue', "fix me")]))
        others.append(odict([('house', "Papa pia1"), ('queue', "stop me")]))
        others.append(odict([('house', "Papa pia1"), ('queue', "help me")]))
        others.append(odict([('house', "Papa pia1"), ('queue', "run me")]))

        self.message(mains=mains, others=others)

    def testMessageMultipleMsgpack(self):
        '''
        multiple messages with msgpack packing
        '''
        console.terse("{0}\n".format(self.testMessageMultipleMsgpack.__doc__))
        self.bootstrap(kind=raeting.packKinds.pack)

        mains = []
        mains.append(odict([('house', "Mama mia1"), ('queue', "fix me")]))
        mains.append(odict([('house', "Mama mia2"), ('queue', "stop me")]))
        mains.append(odict([('house', "Mama mia3"), ('queue', "help me")]))
        mains.append(odict([('house', "Mama mia4"), ('queue', "run me")]))


        others = []
        others.append(odict([('house', "Papa pia1"), ('queue', "fix me")]))
        others.append(odict([('house', "Papa pia1"), ('queue', "stop me")]))
        others.append(odict([('house', "Papa pia1"), ('queue', "help me")]))
        others.append(odict([('house', "Papa pia1"), ('queue', "run me")]))
        self.message(mains=mains, others=others)

    def testMessageSectionedJson(self):
        '''
        Sectioned messages with json packing
        '''
        console.terse("{0}\n".format(self.testMessageSectionedJson.__doc__))

        self.bootstrap(kind=raeting.packKinds.json)

        #big packets
        stuff = []
        for i in range(10000):
            stuff.append(str(i).rjust(10, " "))
        stuff = "".join(stuff)

        src = ['mayor', self.main.local.name, None]
        dst = ['citizen', self.other.local.name, None]
        route = odict([('src', src), ('dst', dst)])


        mains = []
        mains.append(odict([('route', route), ('content', stuff)]))

        src = ['citizen', self.other.local.name, None]
        dst = ['mayor', self.main.local.name, None]
        route = odict([('src', src), ('dst', dst)])

        others = []
        others.append(odict([('route', route), ('content', stuff)]))

        self.message(mains=mains, others=others, duration=2.0)

    def testMessageSectionedMsgpack(self):
        '''
        Sectioned messages with msgpack packing
        '''
        console.terse("{0}\n".format(self.testMessageSectionedMsgpack.__doc__))

        self.bootstrap(kind=raeting.packKinds.pack)

        #big packets
        stuff = []
        for i in range(10000):
            stuff.append(str(i).rjust(10, " "))
        stuff = "".join(stuff)

        src = ['mayor', self.main.local.name, None]
        dst = ['citizen', self.other.local.name, None]
        route = odict([('src', src), ('dst', dst)])


        mains = []
        mains.append(odict([('route', route), ('content', stuff)]))

        src = ['citizen', self.other.local.name, None]
        dst = ['mayor', self.main.local.name, None]
        route = odict([('src', src), ('dst', dst)])

        others = []
        others.append(odict([('route', route), ('content', stuff)]))

        self.message(mains=mains, others=others, duration=2.0)

    def testAutoAccept(self):
        '''
        Basic send auto accept message
        '''
        console.terse("{0}\n".format(self.testAutoAccept.__doc__))

        self.assertTrue(self.main.accept)

        # Don't add remote yard to main so only way to get message from other is
        # if auto acccept works
        self.other.addRemote(yarding.RemoteYard(stack=self.other, ha=self.main.local.ha))

        self.assertEqual(self.main.name, 'main')
        self.assertEqual(self.main.local.name, 'main')
        self.assertEqual(self.main.local.ha, os.path.join(self.baseDirpath, 'cherry.main.uxd'))
        self.assertEqual(len(self.main.remotes), 0)

        self.assertEqual(self.other.name, 'other')
        self.assertEqual(self.other.local.name, 'other')
        self.assertEqual(self.other.local.ha, os.path.join(self.baseDirpath, 'cherry.other.uxd'))
        self.assertEqual(len(self.other.remotes), 1)
        remote = self.other.remotes.values()[0]
        self.assertEqual(remote.ha, os.path.join(self.baseDirpath, 'cherry.main.uxd'))
        self.assertEqual(remote.name, 'main')
        self.assertTrue(remote.uid in self.other.remotes)
        self.assertTrue(remote.name in self.other.nameRemotes)
        self.assertTrue(remote.ha in self.other.haRemotes)
        self.assertIs(self.other.nameRemotes[remote.name], remote)
        self.assertIs(self.other.haRemotes[remote.ha], remote)

        stacking.LaneStack.Pk = raeting.packKinds.pack

        others = []
        others.append(odict(what="This is a message to the lord. Let me be", extra="Go away."))

        self.message(mains=[], others=others)

        self.assertEqual(len(self.main.remotes), 1)
        remote = self.main.remotes.values()[0]
        self.assertEqual(remote.ha, os.path.join(self.baseDirpath, 'cherry.other.uxd'))
        self.assertEqual(remote.name, 'other')
        self.assertTrue(remote.uid in self.main.remotes)
        self.assertTrue(remote.name in self.main.nameRemotes)
        self.assertTrue(remote.ha in self.main.haRemotes)
        self.assertIs(self.main.nameRemotes[remote.name], remote)
        self.assertIs(self.main.haRemotes[remote.ha], remote)

        self.main.rxMsgs = deque()
        self.other.rxMsgs = deque()

        mains = []
        mains.append(odict(what="This is a message to the serf. Get to Work", extra="Fix the fence."))

        self.message(mains=mains, others=[])

    def testAutoAcceptNot(self):
        '''
        Basic send non auto accept message
        '''
        console.terse("{0}\n".format(self.testAutoAcceptNot.__doc__))
        self.main.accept =  False
        self.assertIs(self.main.accept, False)

        # Don't add remote yard to main so only way to get message from other is
        # if auto acccept works
        self.other.addRemote(yarding.RemoteYard(stack=self.other, ha=self.main.local.ha))

        self.assertEqual(self.main.name, 'main')
        self.assertEqual(self.main.local.name, 'main')
        self.assertEqual(self.main.local.ha, os.path.join(self.baseDirpath, 'cherry.main.uxd'))
        self.assertEqual(len(self.main.remotes), 0)

        self.assertEqual(self.other.name, 'other')
        self.assertEqual(self.other.local.name, 'other')
        self.assertEqual(self.other.local.ha, os.path.join(self.baseDirpath, 'cherry.other.uxd'))
        self.assertEqual(len(self.other.remotes), 1)
        remote = self.other.remotes.values()[0]
        self.assertEqual(remote.ha, os.path.join(self.baseDirpath, 'cherry.main.uxd'))
        self.assertEqual(remote.name, 'main')

        self.assertTrue(remote.uid in self.other.remotes)
        self.assertTrue(remote.name in self.other.nameRemotes)
        self.assertTrue(remote.ha in self.other.haRemotes)
        self.assertIs(self.other.nameRemotes[remote.name], remote)
        self.assertIs(self.other.haRemotes[remote.ha], remote)

        stacking.LaneStack.Pk = raeting.packKinds.pack

        others = []
        others.append(odict(what="This is a message to the lord. Let me be", extra="Go away."))

        for msg in others:
            self.other.transmit(msg=msg)

        self.service()

        self.assertEqual(len(self.main.rxMsgs), 0)
        self.assertEqual(len(self.main.remotes), 0)
        self.assertEqual(self.main.stats['unaccepted_source_yard'], 1)

    def testFetchRemoteFromHa(self):
        '''
        Fetching remote yard by HA
        '''
        console.terse("{0}\n".format(self.testFetchRemoteFromHa.__doc__))
        self.bootstrap(kind=raeting.packKinds.json)

        for remote in self.main.remotes.values():
            fetched = self.main.haRemotes.get(remote.ha)
            self.assertIs(remote, fetched)


        for remote in self.other.remotes.values():
            fetched = self.other.haRemotes.get(remote.ha)
            self.assertIs(remote, fetched)

    def testRestart(self):
        '''
        Test messaging after restart
        '''
        console.terse("{0}\n".format(self.testRestart.__doc__))

        stacking.LaneStack.Pk = raeting.packKinds.json

        mainData = self.createLaneData(name='main',
                                       yid=1,
                                       base=self.baseDirpath,
                                       lanename='apple')
        main = self.createLaneStack(data=mainData, main=True)
        self.assertTrue(main.local.ha.endswith('/lane/keep/main/apple.main.uxd'))
        self.assertTrue(main.local.main)

        otherData = self.createLaneData(name='other',
                                        yid=1,
                                        base=self.baseDirpath,
                                        lanename='apple')
        other = self.createLaneStack(data=otherData)
        self.assertTrue(other.local.ha.endswith('/lane/keep/other/apple.other.uxd'))

        main.addRemote(yarding.RemoteYard(stack=main, ha=other.local.ha))
        self.assertTrue('other' in main.nameRemotes)
        self.assertTrue(other.local.ha in main.haRemotes)
        other.addRemote(yarding.RemoteYard(stack=other, ha=main.local.ha))
        self.assertTrue('main' in other.nameRemotes)
        self.assertTrue(main.local.ha in other.haRemotes)

        src = ['mayor', main.local.name, None] # (house, yard, queue)
        dst = ['citizen', other.local.name, None]
        route = odict([('src', src), ('dst', dst)])
        stuff = "This is my command"
        mains = []
        mains.append(odict([('route', route), ('content', stuff)]))

        src = ['citizen', other.local.name, None]
        dst = ['mayor', main.local.name, None]
        route = odict([('src', src), ('dst', dst)])
        stuff = "This is my reply."
        others = []
        others.append(odict([('route', route), ('content', stuff)]))

        self.messageMainOther(main,  other, mains, others, duration=1.0)

        self.assertEqual(len(main.remotes), 1)
        self.assertTrue('other' in main.nameRemotes)
        self.assertEqual(len(other.remotes), 1)
        self.assertTrue('main' in other.nameRemotes)

        self.assertNotEqual(main.nameRemotes['other'].sid, 0)
        self.assertNotEqual(other.nameRemotes['main'].sid, 0)
        self.assertEqual(main.nameRemotes['other'].rsid,
                         other.nameRemotes['main'].sid)
        self.assertEqual(other.nameRemotes['main'].rsid,
                         main.nameRemotes['other'].sid)

        #now close down  make new stacks
        main.server.close()
        other.server.close()
        main = self.createLaneStack(data=mainData, main=True)
        other = self.createLaneStack(data=otherData)

        main.addRemote(yarding.RemoteYard(stack=main, ha=other.local.ha))
        self.assertTrue('other' in main.nameRemotes)
        other.addRemote(yarding.RemoteYard(stack=other, ha=main.local.ha))
        self.assertTrue('main' in other.nameRemotes)

        self.assertEqual(len(main.remotes), 1)
        self.assertEqual(len(other.remotes), 1)

        self.assertNotEqual(main.nameRemotes['other'].sid, 0)
        self.assertNotEqual(other.nameRemotes['main'].sid, 0)
        self.assertEqual(main.nameRemotes['other'].rsid, 0)
        self.assertEqual(other.nameRemotes['main'].rsid, 0)

        self.messageMainOther(main, other, mains, others, duration=1.0)

        self.assertEqual(main.nameRemotes['other'].rsid,
                         other.nameRemotes['main'].sid)
        self.assertEqual(other.nameRemotes['main'].rsid,
                         main.nameRemotes['other'].sid)


        #now close down  make new stacks
        main.server.close()
        other.server.close()
        main = self.createLaneStack(data=mainData, main=True)
        other = self.createLaneStack(data=otherData)

        main.addRemote(yarding.RemoteYard(stack=main, ha=other.local.ha))
        self.assertTrue('other' in main.nameRemotes)
        other.addRemote(yarding.RemoteYard(stack=other, ha=main.local.ha))
        self.assertTrue('main' in other.nameRemotes)

        self.assertEqual(len(main.remotes), 1)
        self.assertEqual(len(other.remotes), 1)

        self.assertNotEqual(main.nameRemotes['other'].sid, 0)
        self.assertNotEqual(other.nameRemotes['main'].sid, 0)
        self.assertEqual(main.nameRemotes['other'].rsid, 0)
        self.assertEqual(other.nameRemotes['main'].rsid, 0)

        # now send paginated messages
        src = ['mayor', main.local.name, None] # (house, yard, queue)
        dst = ['citizen', other.local.name, None]
        route = odict([('src', src), ('dst', dst)])
        stuff = ["Do as I say."]
        for i in range(10000):
            stuff.append(str(i).rjust(10, " "))
        stuff = "".join(stuff)
        mains = []
        mains.append(odict([('route', route), ('content', stuff)]))

        src = ['citizen', other.local.name, None]
        dst = ['mayor', main.local.name, None]
        route = odict([('src', src), ('dst', dst)])
        stuff = ["As you wish."]
        for i in range(10000):
            stuff.append(str(i).rjust(10, " "))
        stuff = "".join(stuff)
        others = []
        others.append(odict([('route', route), ('content', stuff)]))

        self.messageMainOther(main, other, mains, others, duration=1.0)

        self.assertEqual(main.nameRemotes['other'].rsid,
                          other.nameRemotes['main'].sid)
        self.assertEqual(other.nameRemotes['main'].rsid,
                          main.nameRemotes['other'].sid)

        #now close down  make new stacks send page at a time
        main.server.close()
        other.server.close()
        main = self.createLaneStack(data=mainData, main=True)
        other = self.createLaneStack(data=otherData)

        main.addRemote(yarding.RemoteYard(stack=main, ha=other.local.ha))
        self.assertTrue('other' in main.nameRemotes)
        other.addRemote(yarding.RemoteYard(stack=other, ha=main.local.ha))
        self.assertTrue('main' in other.nameRemotes)

        self.assertEqual(len(main.remotes), 1)
        self.assertEqual(len(other.remotes), 1)

        self.assertNotEqual(main.nameRemotes['other'].sid, 0)
        self.assertNotEqual(other.nameRemotes['main'].sid, 0)
        self.assertEqual(main.nameRemotes['other'].rsid, 0)
        self.assertEqual(other.nameRemotes['main'].rsid, 0)

        for msg in mains:
            main.transmit(msg, duid=main.fetchUidByName(other.local.name))
        for msg in others:
            other.transmit(msg, duid=other.fetchUidByName(main.local.name))


        self.assertEqual(len(main.txMsgs), 1)
        self.assertEqual(len(other.txMsgs), 1)
        self.assertEqual(len(main.nameRemotes['other'].books), 0)
        self.assertEqual(len(other.nameRemotes['main'].books), 0)
        self.assertEqual(len(main.rxMsgs), 0)
        self.assertEqual(len(other.rxMsgs), 0)

        # Now only send and receive one page to/from each side
        self.serviceOneAll(main, other)

        self.assertEqual(len(main.txMsgs), 0)
        self.assertEqual(len(other.txMsgs), 0)
        self.assertEqual(len(main.txes), 1)
        self.assertEqual(len(other.txes), 1)
        self.assertEqual(len(main.nameRemotes['other'].books), 1)
        self.assertEqual(len(other.nameRemotes['main'].books), 1)
        self.assertEqual(len(main.rxMsgs), 0)
        self.assertEqual(len(other.rxMsgs), 0)

        self.assertEqual(main.nameRemotes['other'].rsid,
                          other.nameRemotes['main'].sid)
        self.assertEqual(other.nameRemotes['main'].rsid,
                          main.nameRemotes['other'].sid)

        # save sids
        mainSid = main.nameRemotes['other'].sid
        otherSid = other.nameRemotes['main'].sid

        #now close down one side only, make new stack
        main.server.close()
        main = self.createLaneStack(data=mainData, main=True)
        main.addRemote(yarding.RemoteYard(stack=main, ha=other.local.ha))

        self.assertEqual(len(main.remotes), 1)
        self.assertEqual(len(other.remotes), 1)

        self.assertNotEqual(main.nameRemotes['other'].sid, mainSid)
        self.assertEqual(other.nameRemotes['main'].sid, otherSid)
        self.assertEqual(main.nameRemotes['other'].rsid, 0)
        self.assertEqual(other.nameRemotes['main'].rsid, mainSid)

        self.assertEqual(len(main.txes), 0)
        self.assertEqual(len(other.txes), 1)
        self.assertEqual(len(main.nameRemotes['other'].books), 0)
        self.assertEqual(len(other.nameRemotes['main'].books), 1)
        self.assertEqual(len(main.rxMsgs), 0)
        self.assertEqual(len(other.rxMsgs), 0)

        # Now remaining page from other (there should be no pages from main)
        self.serviceOneAll(main, other)

        self.assertEqual(main.nameRemotes['other'].rsid,
                          other.nameRemotes['main'].sid)
        self.assertNotEqual(other.nameRemotes['main'].rsid,
                          main.nameRemotes['other'].sid)


        self.assertEqual(len(main.txes), 0)
        self.assertEqual(len(other.txes), 0)
        self.assertEqual(len(main.nameRemotes['other'].books), 0)
        self.assertEqual(len(other.nameRemotes['main'].books), 1)
        self.assertEqual(len(main.rxMsgs), 0)
        self.assertEqual(len(other.rxMsgs), 0)
        self.assertEqual(main.stats['missed_page'], 1)


        #send a new message from main and reap stale book from other
        for msg in mains:
            main.transmit(msg, duid=main.fetchUidByName(other.local.name))

        self.serviceMainOther(main, other, duration=1.0)

        self.assertEqual(main.nameRemotes['other'].rsid,
                          other.nameRemotes['main'].sid)
        self.assertEqual(other.nameRemotes['main'].rsid,
                          main.nameRemotes['other'].sid)
        self.assertEqual(len(main.txes), 0)
        self.assertEqual(len(other.txes), 0)
        self.assertEqual(len(main.nameRemotes['other'].books), 0)
        self.assertEqual(len(other.nameRemotes['main'].books), 0)
        self.assertEqual(len(main.rxMsgs), 0)
        self.assertEqual(len(main.rxMsgs), 0)
        self.assertEqual(len(other.rxMsgs), 1)
        self.assertEqual(other.stats['stale_book'], 1)

        self.assertEqual(len(other.rxMsgs), len(mains))
        for i, duple in enumerate(other.rxMsgs):
            console.terse("Yard '{0}' rxed:\n'{1}'\n".format(other.local.name, duple))
            self.assertDictEqual(mains[i], duple[0])


        # setup to test reset sid numbering by sending single pages to create stale books

        other.rxMsgs.pop()
        for msg in mains:
            main.transmit(msg, duid=main.fetchUidByName(other.local.name))
        for msg in others:
            other.transmit(msg, duid=other.fetchUidByName(main.local.name))

        self.serviceOneAll(main, other)

        self.assertEqual(main.nameRemotes['other'].rsid,
                          other.nameRemotes['main'].sid)
        self.assertEqual(other.nameRemotes['main'].rsid,
                          main.nameRemotes['other'].sid)


        self.assertEqual(len(main.txes), 1)
        self.assertEqual(len(other.txes), 1)
        self.assertEqual(len(main.nameRemotes['other'].books), 1)
        self.assertEqual(len(other.nameRemotes['main'].books), 1)
        self.assertEqual(len(main.rxMsgs), 0)
        self.assertEqual(len(other.rxMsgs), 0)

        # simulate restart that loses msg in queue
        main.txes.pop()
        other.txes.pop()

        src = ['mayor', main.local.name, None] # (house, yard, queue)
        dst = ['citizen', other.local.name, None]
        route = odict([('src', src), ('dst', dst)])
        stuff = "This is my command"
        mains = []
        mains.append(odict([('route', route), ('content', stuff)]))

        src = ['citizen', other.local.name, None]
        dst = ['mayor', main.local.name, None]
        route = odict([('src', src), ('dst', dst)])
        stuff = "This is my reply."
        others = []
        others.append(odict([('route', route), ('content', stuff)]))

        mainSid = main.local.nextSid()
        otherSid = other.local.nextSid()
        main.nameRemotes['other'].sid = mainSid
        other.nameRemotes['main'].sid = otherSid
        for msg in mains:
            main.transmit(msg, duid=main.fetchUidByName(other.local.name))
        for msg in others:
            other.transmit(msg,  duid=other.fetchUidByName(main.local.name))

        self.serviceOneAll(main, other)

        self.assertEqual(main.nameRemotes['other'].sid, mainSid)
        self.assertEqual(other.nameRemotes['main'].sid, otherSid)
        self.assertEqual(main.nameRemotes['other'].rsid, otherSid)
        self.assertEqual(other.nameRemotes['main'].rsid, mainSid)

        self.assertEqual(len(main.txes), 0)
        self.assertEqual(len(other.txes), 0)
        self.assertEqual(len(main.nameRemotes['other'].books), 0)
        self.assertEqual(len(other.nameRemotes['main'].books), 0)
        self.assertEqual(len(main.rxMsgs), 1)
        self.assertEqual(len(other.rxMsgs), 1)
        self.assertEqual(main.stats['stale_book'], 1)
        self.assertEqual(other.stats['stale_book'], 2)

        main.server.close()
        other.server.close()
Beispiel #10
0
class BasicTestCase(unittest.TestCase):
    """"""

    def setUp(self):
        self.store = storing.Store(stamp=0.0)
        self.timer = StoreTimer(store=self.store, duration=1.0)

        self.base = tempfile.mkdtemp(prefix="raet",  suffix="base", dir='/tmp')

    def tearDown(self):
        if os.path.exists(self.base):
            shutil.rmtree(self.base)

    def createRoadData(self, name, base, auto=None):
        '''
        Creates odict and populates with data to setup road stack
        {
            name: stack name local estate name
            dirpath: dirpath for keep files
            sighex: signing key
            verhex: verify key
            prihex: private key
            pubhex: public key
        }
        '''
        data = odict()
        data['name'] = name
        data['dirpath'] = os.path.join(base, 'road', 'keep', name)
        signer = nacling.Signer()
        data['sighex'] = signer.keyhex
        data['verhex'] = signer.verhex
        privateer = nacling.Privateer()
        data['prihex'] = privateer.keyhex
        data['pubhex'] = privateer.pubhex
        data['auto'] = auto

        return data

    def createRoadStack(self, data, eid=0, main=None, auto=None, ha=None):
        '''
        Creates stack and local estate from data with
        local estate.eid = eid
        stack.main = main
        stack.auto = auto
        stack.name = data['name']
        local estate.name = data['name']
        local estate.ha = ha

        returns stack

        '''
        local = estating.LocalEstate(eid=eid,
                                     name=data['name'],
                                     ha=ha,
                                     sigkey=data['sighex'],
                                     prikey=data['prihex'],)

        stack = stacking.RoadStack(name=data['name'],
                                   local=local,
                                   auto=auto if auto is not None else data['auto'],
                                   main=main,
                                   dirpath=data['dirpath'],
                                   store=self.store)

        return stack

    def join(self, initiator, correspondent, deid=None, mha=None, duration=1.0,
                cascade=False):
        '''
        Utility method to do join. Call from test method.
        '''
        console.terse("\nJoin Transaction **************\n")
        initiator.join(duid=deid, ha=mha, cascade=cascade)
        self.service(correspondent, initiator, duration=duration)

    def allow(self, initiator, correspondent, deid=None, mha=None, duration=1.0,
                cascade=False):
        '''
        Utility method to do allow. Call from test method.
        '''
        console.terse("\nAllow Transaction **************\n")
        initiator.allow(duid=deid, ha=mha, cascade=cascade)
        self.service(correspondent, initiator, duration=duration)

    def alive(self, initiator, correspondent, deid=None, mha=None, duration=1.0,
                cascade=False):
        '''
        Utility method to do alive. Call from test method.
        '''
        console.terse("\nAlive Transaction **************\n")
        initiator.alive(duid=deid, ha=mha, cascade=cascade)
        self.service(correspondent, initiator, duration=duration)

    def message(self, main,  other, mains, others, duration=2.0):
        '''
        Utility to send messages both ways
        '''
        for msg in mains:
            main.transmit(msg)
        for msg in others:
            other.transmit(msg)

        self.service(main, other, duration=duration)

    def service(self, main, other, duration=1.0):
        '''
        Utility method to service queues. Call from test method.
        '''
        self.timer.restart(duration=duration)
        while not self.timer.expired:
            other.serviceAll()
            main.serviceAll()
            if not (main.transactions or other.transactions):
                break
            self.store.advanceStamp(0.1)
            time.sleep(0.1)

    def serviceStack(self, stack, duration=1.0):
        '''
        Utility method to service queues for one stack. Call from test method.
        '''
        self.timer.restart(duration=duration)
        while not self.timer.expired:
            stack.serviceAll()
            if not (stack.transactions):
                break
            self.store.advanceStamp(0.1)
            time.sleep(0.1)

    def serviceStacks(self, stacks, duration=1.0):
        '''
        Utility method to service queues for list of stacks. Call from test method.
        '''
        self.timer.restart(duration=duration)
        while not self.timer.expired:
            for stack in stacks:
                stack.serviceAll()
            if all([not stack.transactions for stack in stacks]):
                break
            self.store.advanceStamp(0.1)
            time.sleep(0.1)


    def testAlive(self):
        '''
        Test basic alive transaction
        '''
        console.terse("{0}\n".format(self.testAlive.__doc__))

        mainData = self.createRoadData(name='main', base=self.base, auto=True)
        keeping.clearAllKeepSafe(mainData['dirpath'])
        main = self.createRoadStack(data=mainData,
                                     eid=1,
                                     main=True,
                                     auto=mainData['auto'],
                                     ha=None)

        otherData = self.createRoadData(name='other', base=self.base)
        keeping.clearAllKeepSafe(otherData['dirpath'])
        other = self.createRoadStack(data=otherData,
                                     eid=0,
                                     main=None,
                                     auto=None,
                                     ha=("", raeting.RAET_TEST_PORT))


        self.join(other, main)
        self.assertEqual(len(main.transactions), 0)
        self.assertEqual(len(other.transactions), 0)
        otherRemote = main.remotes[other.local.uid]
        mainRemote = other.remotes.values()[0]
        self.assertTrue(otherRemote.joined)
        self.assertTrue(mainRemote.joined)

        self.allow(other, main)
        self.assertEqual(len(main.transactions), 0)
        self.assertEqual(len(other.transactions), 0)
        otherRemote = main.remotes[other.local.uid]
        mainRemote = other.remotes.values()[0]
        self.assertTrue(otherRemote.allowed)
        self.assertTrue(mainRemote.allowed)

        console.terse("\nAlive Other to Main *********\n")
        otherRemote = main.remotes[other.local.uid]
        mainRemote = other.remotes.values()[0]
        self.assertIs(otherRemote.alived, None)
        self.assertIs(mainRemote.alived, None)

        self.alive(other, main, deid=main.local.uid)
        self.assertEqual(len(main.transactions), 0)
        self.assertEqual(len(other.transactions), 0)
        self.assertTrue(otherRemote.alived)
        self.assertTrue(mainRemote.alived)

        console.terse("\nAlive Main to Other *********\n")
        otherRemote.alived = None
        mainRemote.alived = None
        self.assertIs(otherRemote.alived, None)
        self.assertIs(mainRemote.alived, None)

        self.alive(main, other, deid=other.local.uid)
        self.assertEqual(len(main.transactions), 0)
        self.assertEqual(len(other.transactions), 0)
        self.assertTrue(otherRemote.alived)
        self.assertTrue(mainRemote.alived)


        console.terse("\nDead Other from Main *********\n")
        self.assertTrue(otherRemote.alived)
        self.assertTrue(mainRemote.alived)
        main.alive(duid=other.local.uid)
        self.serviceStack(main, duration=3.0)
        self.assertEqual(len(main.transactions), 0)
        self.assertFalse(otherRemote.alived)
        self.serviceStack(other, duration=3.0)

        console.terse("\nDead Main from Other *********\n")
        self.assertTrue(mainRemote.alived)
        other.alive(duid=main.local.uid)
        self.serviceStack(other, duration=3.0)
        self.assertEqual(len(other.transactions), 0)
        self.assertFalse(mainRemote.alived)
        self.serviceStack(main, duration=3.0)

        main.server.close()
        main.clearLocal()
        main.clearRemoteKeeps()

        other.server.close()
        other.clearLocal()
        other.clearRemoteKeeps()

    def testAliveUnjoinedOther(self):
        '''
        Test alive transaction for other to main unjoined on main
        '''
        console.terse("{0}\n".format(self.testAliveUnjoinedOther.__doc__))

        mainData = self.createRoadData(name='main', base=self.base, auto=True)
        keeping.clearAllKeepSafe(mainData['dirpath'])
        main = self.createRoadStack(data=mainData,
                                     eid=1,
                                     main=True,
                                     auto=mainData['auto'],
                                     ha=None)

        otherData = self.createRoadData(name='other', base=self.base)
        keeping.clearAllKeepSafe(otherData['dirpath'])
        other = self.createRoadStack(data=otherData,
                                     eid=0,
                                     main=None,
                                     auto=None,
                                     ha=("", raeting.RAET_TEST_PORT))

        console.terse("\nBoth unjoined Alive Other to Main *********\n")
        self.assertEqual(len(main.remotes), 0)
        self.assertEqual(len(other.remotes), 0)

        self.alive(other, main, mha=('127.0.0.1', main.local.port))
        self.assertEqual(len(main.transactions), 0)
        self.assertEqual(len(other.transactions), 0)
        otherRemote = main.remotes[other.local.uid]
        mainRemote = other.remotes[main.local.uid]
        self.assertIs(otherRemote.joined, True)
        self.assertIs(mainRemote.joined,  True)
        self.assertIs(otherRemote.alived,  None)
        self.assertIs(mainRemote.alived,  None)

        self.alive(other, main, deid=main.local.uid)
        self.assertEqual(len(main.transactions), 0)
        self.assertEqual(len(other.transactions), 0)
        self.assertIs(otherRemote.allowed, True)
        self.assertIs(mainRemote.allowed,  True)
        self.assertIs(otherRemote.alived,  None)
        self.assertIs(mainRemote.alived,  None)

        self.alive(other, main, deid=main.local.uid)
        self.assertEqual(len(main.transactions), 0)
        self.assertEqual(len(other.transactions), 0)
        self.assertIs(otherRemote.alived,  True)
        self.assertIs(mainRemote.alived,  True)

        console.terse("\nAlive Main to Other *********\n")
        otherRemote.alived = None
        mainRemote.alived = None
        self.assertIs(otherRemote.alived, None)
        self.assertIs(mainRemote.alived, None)

        self.alive(main, other, deid=other.local.uid)
        self.assertEqual(len(main.transactions), 0)
        self.assertEqual(len(other.transactions), 0)
        self.assertTrue(otherRemote.alived)
        self.assertTrue(mainRemote.alived)

        main.server.close()
        main.clearLocal()
        main.clearRemoteKeeps()

        other.server.close()
        other.clearLocal()
        other.clearRemoteKeeps()

    def testAllowUnjoinedOther(self):
        '''
        Test allow transaction for other to main unjoined on main
        '''
        console.terse("{0}\n".format(self.testAllowUnjoinedOther.__doc__))

        mainData = self.createRoadData(name='main', base=self.base, auto=True)
        keeping.clearAllKeepSafe(mainData['dirpath'])
        main = self.createRoadStack(data=mainData,
                                     eid=1,
                                     main=True,
                                     auto=mainData['auto'],
                                     ha=None)

        otherData = self.createRoadData(name='other', base=self.base)
        keeping.clearAllKeepSafe(otherData['dirpath'])
        other = self.createRoadStack(data=otherData,
                                     eid=0,
                                     main=None,
                                     auto=None,
                                     ha=("", raeting.RAET_TEST_PORT))

        console.terse("\nBoth unjoined Allow Other to Main *********\n")
        self.assertEqual(len(main.remotes), 0)
        self.assertEqual(len(other.remotes), 0)

        self.allow(other, main, mha=('127.0.0.1', main.local.port))
        self.assertEqual(len(main.transactions), 0)
        self.assertEqual(len(other.transactions), 0)
        otherRemote = main.remotes[other.local.uid]
        mainRemote = other.remotes[main.local.uid]
        self.assertIs(otherRemote.joined, True)
        self.assertIs(mainRemote.joined,  True)
        self.assertIs(otherRemote.allowed,  None)
        self.assertIs(mainRemote.allowed,  None)

        self.allow(other, main, deid=main.local.uid)
        self.assertEqual(len(main.transactions), 0)
        self.assertEqual(len(other.transactions), 0)
        self.assertIs(otherRemote.allowed, True)
        self.assertIs(mainRemote.allowed,  True)

        console.terse("\nAllow Main to Other *********\n")
        otherRemote.alived = None
        mainRemote.alived = None
        self.assertIs(otherRemote.alived, None)
        self.assertIs(mainRemote.alived, None)

        self.allow(main, other, deid=other.local.uid)
        self.assertEqual(len(main.transactions), 0)
        self.assertEqual(len(other.transactions), 0)
        self.assertTrue(otherRemote.allowed)
        self.assertTrue(mainRemote.allowed)

        console.terse("\nBoth unjoined Allow Other to Main Cascade *********\n")
        main.server.close()
        other.server.close()
        keeping.clearAllKeepSafe(mainData['dirpath'])
        main = self.createRoadStack(data=mainData,
                                     eid=1,
                                     main=True,
                                     auto=mainData['auto'],
                                     ha=None)

        keeping.clearAllKeepSafe(otherData['dirpath'])
        other = self.createRoadStack(data=otherData,
                                     eid=0,
                                     main=None,
                                     auto=None,
                                     ha=("", raeting.RAET_TEST_PORT))

        self.assertEqual(len(main.remotes), 0)
        self.assertEqual(len(other.remotes), 0)

        self.allow(other, main, mha=('127.0.0.1', main.local.port), cascade=True)
        self.assertEqual(len(main.transactions), 0)
        self.assertEqual(len(other.transactions), 0)
        otherRemote = main.remotes[other.local.uid]
        mainRemote = other.remotes[main.local.uid]
        self.assertIs(otherRemote.joined, True)
        self.assertIs(mainRemote.joined,  True)
        self.assertIs(otherRemote.allowed,  True)
        self.assertIs(mainRemote.allowed,  True)
        self.assertIs(otherRemote.alived,  True)
        self.assertIs(mainRemote.alived,  True)


        main.server.close()
        main.clearLocal()
        main.clearRemoteKeeps()

        other.server.close()
        other.clearLocal()
        other.clearRemoteKeeps()

    def testAliveUnjoinedMain(self):
        '''
        Test alive transaction for other to main unjoined on main
        '''
        console.terse("{0}\n".format(self.testAliveUnjoinedOther.__doc__))

        mainData = self.createRoadData(name='main', base=self.base, auto=True)
        keeping.clearAllKeepSafe(mainData['dirpath'])
        main = self.createRoadStack(data=mainData,
                                     eid=1,
                                     main=True,
                                     auto=mainData['auto'],
                                     ha=None)

        otherData = self.createRoadData(name='other', base=self.base)
        keeping.clearAllKeepSafe(otherData['dirpath'])
        other = self.createRoadStack(data=otherData,
                                     eid=0,
                                     main=None,
                                     auto=None,
                                     ha=("", raeting.RAET_TEST_PORT))

        # join and allow
        self.join(other, main)
        self.assertEqual(len(main.transactions), 0)
        self.assertEqual(len(other.transactions), 0)
        otherRemote = main.remotes[other.local.uid]
        mainRemote = other.remotes[main.local.uid]
        self.assertIs(otherRemote.joined, True)
        self.assertIs(mainRemote.joined,  True)

        self.allow(other, main)
        self.assertEqual(len(main.transactions), 0)
        self.assertEqual(len(other.transactions), 0)
        self.assertIs(otherRemote.allowed, True)
        self.assertIs(mainRemote.allowed,  True)

        console.terse("\nBoth unjoined Alive Other to Main *********\n")
        # set main's remote of other to not joined or allowed
        otherRemote.alived = None
        otherRemote.joined = None
        otherRemote.allowed = None

        self.alive(other, main, mha=('127.0.0.1', main.local.port))
        self.assertEqual(len(main.transactions), 0)
        self.assertEqual(len(other.transactions), 0)
        otherRemote = main.remotes[other.local.uid]
        mainRemote = other.remotes[main.local.uid]
        self.assertIs(otherRemote.joined, True)
        self.assertIs(mainRemote.joined,  True)
        self.assertIs(otherRemote.alived,  None)
        self.assertIs(mainRemote.alived,  None)

        self.alive(other, main, deid=main.local.uid)
        self.assertEqual(len(main.transactions), 0)
        self.assertEqual(len(other.transactions), 0)
        self.assertIs(otherRemote.allowed, True)
        self.assertIs(mainRemote.allowed,  True)
        self.assertIs(otherRemote.alived,  None)
        self.assertIs(mainRemote.alived,  None)

        self.alive(other, main, deid=main.local.uid)
        self.assertEqual(len(main.transactions), 0)
        self.assertEqual(len(other.transactions), 0)
        self.assertIs(otherRemote.alived,  True)
        self.assertIs(mainRemote.alived,  True)

        console.terse("\nAlive Main to Other *********\n")
        otherRemote.alived = None
        mainRemote.alived = None
        self.assertIs(otherRemote.alived, None)
        self.assertIs(mainRemote.alived, None)

        self.alive(main, other, deid=other.local.uid)
        self.assertEqual(len(main.transactions), 0)
        self.assertEqual(len(other.transactions), 0)
        self.assertTrue(otherRemote.alived)
        self.assertTrue(mainRemote.alived)

        main.server.close()
        main.clearLocal()
        main.clearRemoteKeeps()

        other.server.close()
        other.clearLocal()
        other.clearRemoteKeeps()

    def testAllowUnjoinedMain(self):
        '''
        Test allow transaction for main to other unjoined on other
        '''
        console.terse("{0}\n".format(self.testAllowUnjoinedMain.__doc__))

        mainData = self.createRoadData(name='main', base=self.base, auto=True)
        keeping.clearAllKeepSafe(mainData['dirpath'])
        main = self.createRoadStack(data=mainData,
                                     eid=1,
                                     main=True,
                                     auto=mainData['auto'],
                                     ha=None)

        otherData = self.createRoadData(name='other', base=self.base)
        keeping.clearAllKeepSafe(otherData['dirpath'])
        other = self.createRoadStack(data=otherData,
                                     eid=0,
                                     main=None,
                                     auto=None,
                                     ha=("", raeting.RAET_TEST_PORT))

        #now create remote for other and add to main
        main.addRemote(estating.RemoteEstate(stack=main,
                                             eid=2,
                                             name=otherData['name'],
                                             ha=('127.0.0.1', other.local.port),
                                             verkey=otherData['verhex'],
                                             pubkey=otherData['pubhex'],
                                             period=main.period,
                                             offset=main.offset))

        console.terse("\nBoth unjoined Allow Main to Other *********\n")
        self.assertEqual(len(main.remotes), 1)
        self.assertEqual(len(other.remotes), 0)

        self.allow(main, other, mha=('127.0.0.1', other.local.port))
        self.assertEqual(len(main.transactions), 0)
        self.assertEqual(len(other.transactions), 0)
        otherRemote = main.remotes[other.local.uid]
        mainRemote = other.remotes[main.local.uid]
        self.assertIs(otherRemote.joined, True)
        self.assertIs(mainRemote.joined,  True)
        self.assertIs(otherRemote.allowed,  None)
        self.assertIs(mainRemote.allowed,  None)

        self.allow(main, other, deid=other.local.uid)
        self.assertEqual(len(main.transactions), 0)
        self.assertEqual(len(other.transactions), 0)
        self.assertIs(otherRemote.allowed, True)
        self.assertIs(mainRemote.allowed,  True)

        console.terse("\nAllow Other to Main *********\n")
        otherRemote.alived = None
        mainRemote.alived = None
        self.assertIs(otherRemote.alived, None)
        self.assertIs(mainRemote.alived, None)

        self.allow(other, main, deid=main.local.uid)
        self.assertEqual(len(main.transactions), 0)
        self.assertEqual(len(other.transactions), 0)
        self.assertTrue(otherRemote.allowed)
        self.assertTrue(mainRemote.allowed)

        console.terse("\nBoth unjoined Allow Main to Other Cascade *********\n")
        main.server.close()
        other.server.close()
        keeping.clearAllKeepSafe(mainData['dirpath'])
        main = self.createRoadStack(data=mainData,
                                     eid=1,
                                     main=True,
                                     auto=mainData['auto'],
                                     ha=None)

        keeping.clearAllKeepSafe(otherData['dirpath'])
        other = self.createRoadStack(data=otherData,
                                     eid=0,
                                     main=None,
                                     auto=None,
                                     ha=("", raeting.RAET_TEST_PORT))

        #now create remote for other and add to main
        main.addRemote(estating.RemoteEstate(stack=main,
                                             eid=2,
                                             name=otherData['name'],
                                             ha=('127.0.0.1', other.local.port),
                                             verkey=otherData['verhex'],
                                             pubkey=otherData['pubhex'],
                                             period=main.period,
                                             offset=main.offset))

        self.assertEqual(len(main.remotes), 1)
        self.assertEqual(len(other.remotes), 0)

        self.allow(main, other, mha=('127.0.0.1', other.local.port), cascade=True)
        self.assertEqual(len(main.transactions), 0)
        self.assertEqual(len(other.transactions), 0)
        otherRemote = main.remotes[other.local.uid]
        mainRemote = other.remotes[main.local.uid]
        self.assertIs(otherRemote.joined, True)
        self.assertIs(mainRemote.joined,  True)
        self.assertIs(otherRemote.allowed,  True)
        self.assertIs(mainRemote.allowed,  True)
        self.assertIs(otherRemote.alived,  True)
        self.assertIs(mainRemote.alived,  True)

        main.server.close()
        main.clearLocal()
        main.clearRemoteKeeps()

        other.server.close()
        other.clearLocal()
        other.clearRemoteKeeps()


    def testAliveMultiple(self):
        '''
        Test alive transaction with multiple remotes
        '''
        console.terse("{0}\n".format(self.testAliveMultiple.__doc__))

        mainData = self.createRoadData(name='main', base=self.base, auto=True)
        keeping.clearAllKeepSafe(mainData['dirpath'])
        main = self.createRoadStack(data=mainData,
                                     eid=1,
                                     main=True,
                                     auto=mainData['auto'],
                                     ha=None)

        otherData = self.createRoadData(name='other', base=self.base)
        keeping.clearAllKeepSafe(otherData['dirpath'])
        other = self.createRoadStack(data=otherData,
                                     eid=0,
                                     main=None,
                                     auto=None,
                                     ha=("", raeting.RAET_TEST_PORT))


        self.join(other, main)
        self.assertEqual(len(main.transactions), 0)
        self.assertEqual(len(other.transactions), 0)
        otherRemote = main.remotes[other.local.uid]
        mainRemote = other.remotes.values()[0]
        self.assertTrue(otherRemote.joined)
        self.assertTrue(mainRemote.joined)

        self.allow(other, main)
        self.assertEqual(len(main.transactions), 0)
        self.assertEqual(len(other.transactions), 0)
        otherRemote = main.remotes[other.local.uid]
        mainRemote = other.remotes.values()[0]
        self.assertTrue(otherRemote.allowed)
        self.assertTrue(mainRemote.allowed)


        other1Data = self.createRoadData(name='other1', base=self.base)
        keeping.clearAllKeepSafe(other1Data['dirpath'])
        other1 = self.createRoadStack(data=other1Data,
                                     eid=0,
                                     main=None,
                                     auto=None,
                                     ha=("", 7532))


        self.join(other1, main)
        self.assertEqual(len(main.transactions), 0)
        self.assertEqual(len(other1.transactions), 0)
        other1Remote = main.remotes[other1.local.uid]
        main1Remote = other1.remotes.values()[0]
        self.assertTrue(other1Remote.joined)
        self.assertTrue(main1Remote.joined)

        self.allow(other1, main)
        self.assertEqual(len(main.transactions), 0)
        self.assertEqual(len(other1.transactions), 0)
        other1Remote = main.remotes[other1.local.uid]
        main1Remote = other1.remotes.values()[0]
        self.assertTrue(other1Remote.allowed)
        self.assertTrue(main1Remote.allowed)

        console.terse("\nAlive Other to Main *********\n")
        self.assertIs(otherRemote.alived, None)
        self.assertIs(mainRemote.alived, None)

        self.alive(other, main, deid=main.local.uid)
        self.assertEqual(len(main.transactions), 0)
        self.assertEqual(len(other.transactions), 0)
        self.assertTrue(otherRemote.alived)
        self.assertTrue(mainRemote.alived)

        console.terse("\nAlive Main to Other *********\n")
        otherRemote.alived = None
        mainRemote.alived = None
        self.assertIs(otherRemote.alived, None)
        self.assertIs(mainRemote.alived, None)

        self.alive(main, other, deid=other.local.uid)
        self.assertEqual(len(main.transactions), 0)
        self.assertEqual(len(other.transactions), 0)
        self.assertTrue(otherRemote.alived)
        self.assertTrue(mainRemote.alived)

        console.terse("\nAlive Other1 to Main *********\n")
        self.assertIs(other1Remote.alived, None)
        self.assertIs(main1Remote.alived, None)

        self.alive(other1, main, deid=main.local.uid)
        self.assertEqual(len(main.transactions), 0)
        self.assertEqual(len(other1.transactions), 0)
        self.assertTrue(other1Remote.alived)
        self.assertTrue(main1Remote.alived)

        console.terse("\nAlive Main to Other1 *********\n")
        other1Remote.alived = None
        main1Remote.alived = None
        self.assertIs(other1Remote.alived, None)
        self.assertIs(main1Remote.alived, None)

        self.alive(main, other1, deid=other1.local.uid)
        self.assertEqual(len(main.transactions), 0)
        self.assertEqual(len(other1.transactions), 0)
        self.assertTrue(other1Remote.alived)
        self.assertTrue(main1Remote.alived)

        console.terse("\nDead Other Alive Other1, from Main *********\n")
        self.assertTrue(main.remotes[other.local.uid].alived)
        self.assertTrue(main.remotes[other1.local.uid].alived)
        main.alive(duid=other.local.uid)
        main.alive(duid=other1.local.uid)
        # don't service other stack so it appears to be dead
        self.serviceStacks([main, other1], duration=3.0)
        self.assertEqual(len(main.transactions), 0)
        self.assertEqual(len(other1.transactions), 0)
        #self.assertTrue(other.local.uid not in main.remotes)
        self.assertIs(main.remotes[other.local.uid].alived, False)
        self.assertTrue(main.remotes[other1.local.uid].alived)

        self.serviceStacks([other, main], duration=3.0) #clean up
        self.assertEqual(len(main.transactions), 0)
        self.assertEqual(len(other.transactions), 0)
        self.assertEqual(len(other1.transactions), 0)

        #bring it back to life
        console.terse("\nReliven other *********\n")
        other.alive(duid=main.local.uid, cascade=True)
        self.serviceStacks([other, main], duration=3.0)
        self.assertIs(main.remotes[other.local.uid].alived, True)
        self.assertIs(other.remotes[main.local.uid].alived, True)

        console.terse("\nAlive Other Dead Other 1 from Main *********\n")
        main.alive(duid=other.local.uid)
        main.alive(duid=other1.local.uid)
        self.serviceStacks([main, other], duration=3.0)
        self.assertEqual(len(main.transactions), 0)
        self.assertEqual(len(other.transactions), 0)
        self.assertFalse(other1Remote.alived)
        self.assertTrue(otherRemote.alived)

        self.serviceStacks([other1,  main], duration=3.0)
        self.assertEqual(len(main.transactions), 0)
        self.assertEqual(len(other.transactions), 0)
        self.assertEqual(len(other1.transactions), 0)

        #bring it back to life
        console.terse("\nReliven other1 *********\n")
        other1.alive(duid=main.local.uid, cascade=True)
        self.serviceStacks([other1, main], duration=3.0)
        self.assertIs(main.remotes[other1.local.uid].alived, True)
        self.assertIs(other1.remotes[main.local.uid].alived, True)

        main.server.close()
        main.clearLocal()
        main.clearRemoteKeeps()

        other.server.close()
        other.clearLocal()
        other.clearRemoteKeeps()

        other1.server.close()
        other1.clearLocal()
        other1.clearRemoteKeeps()

    def testManage(self):
        '''
        Test stack manage remotes
        '''
        console.terse("{0}\n".format(self.testManage.__doc__))

        mainData = self.createRoadData(name='main', base=self.base, auto=True)
        keeping.clearAllKeepSafe(mainData['dirpath'])
        main = self.createRoadStack(data=mainData,
                                     eid=1,
                                     main=True,
                                     auto=mainData['auto'],
                                     ha=None)

        otherData = self.createRoadData(name='other', base=self.base)
        keeping.clearAllKeepSafe(otherData['dirpath'])
        other = self.createRoadStack(data=otherData,
                                     eid=0,
                                     main=None,
                                     auto=None,
                                     ha=("", raeting.RAET_TEST_PORT))

        other1Data = self.createRoadData(name='other1', base=self.base)
        keeping.clearAllKeepSafe(other1Data['dirpath'])
        other1 = self.createRoadStack(data=other1Data,
                                     eid=0,
                                     main=None,
                                     auto=None,
                                     ha=("", 7532))


        self.join(other, main)
        self.join(other1, main)
        self.allow(other, main)
        self.allow(other1, main)

        console.terse("\nTest manage remotes presence *********\n")
        console.terse("\nMake all alive *********\n")
        stacks = [main, other, other1]
        for remote in main.remotes.values(): #make all alive
            main.alive(duid=remote.uid)
        self.serviceStacks(stacks, duration=3.0)
        for remote in main.remotes.values():
            self.assertTrue(remote.alived)

        main.manage()
        for stack in stacks: # no alive transactions started
            self.assertEqual(len(stack.transactions), 0)

        console.terse("\nMake all expired so send alive *********\n")
        # advance clock so remote keep alive timers expire
        self.store.advanceStamp(estating.RemoteEstate.Period + estating.RemoteEstate.Offset)
        main.manage()
        for remote in main.remotes.values(): # should start
            self.assertIs(remote.alived, None)

        self.assertEqual(len(main.transactions), 2) # started 2 alive transactions

        self.serviceStacks(stacks, duration=3.0)
        for stack in stacks:
            self.assertEqual(len(stack.transactions), 0)
        for remote in main.remotes.values():
            self.assertTrue(remote.alived)


        main.server.close()
        main.clearLocal()
        main.clearRemoteKeeps()

        other.server.close()
        other.clearLocal()
        other.clearRemoteKeeps()

        other1.server.close()
        other1.clearLocal()
        other1.clearRemoteKeeps()

    def testJoinFromMain(self):
        '''
        Test join, allow, alive initiated by main
        '''
        console.terse("{0}\n".format(self.testJoinFromMain.__doc__))

        mainData = self.createRoadData(name='main', base=self.base, auto=True)
        keeping.clearAllKeepSafe(mainData['dirpath'])
        main = self.createRoadStack(data=mainData,
                                     eid=1,
                                     main=True,
                                     auto=mainData['auto'],
                                     ha=None)

        otherData = self.createRoadData(name='other', base=self.base)
        keeping.clearAllKeepSafe(otherData['dirpath'])
        other = self.createRoadStack(data=otherData,
                                     eid=0,
                                     main=None,
                                     auto=None,
                                     ha=("", raeting.RAET_TEST_PORT))

        console.terse("\nJoin Main to Other *********\n")
        self.join(main, other, mha=('127.0.0.1', other.local.port))
        self.assertEqual(len(main.transactions), 0)
        self.assertEqual(len(other.transactions), 0)
        self.assertEqual(len(main.remotes), 0)
        self.assertEqual(len(other.remotes), 0)

        #now create remote for other and add to main
        main.addRemote(estating.RemoteEstate(stack=main,
                                             eid=2,
                                             name=otherData['name'],
                                             ha=('127.0.0.1', other.local.port),
                                             verkey=otherData['verhex'],
                                             pubkey=otherData['pubhex'],
                                             period=main.period,
                                             offset=main.offset))

        console.terse("\nJoin Main to Other Again *********\n")
        self.join(main, other, deid=2)
        self.assertEqual(len(main.transactions), 0)
        self.assertEqual(len(other.transactions), 0)
        otherRemote = main.remotes[other.local.uid]
        mainRemote = other.remotes[main.local.uid]
        self.assertIs(otherRemote.joined, True)
        self.assertIs(mainRemote.joined, True)

        console.terse("\nAllow Main to Other *********\n")
        self.allow(main, other)
        self.assertEqual(len(main.transactions), 0)
        self.assertEqual(len(other.transactions), 0)
        otherRemote = main.remotes[other.local.uid]
        mainRemote = other.remotes.values()[0]
        self.assertTrue(otherRemote.allowed)
        self.assertTrue(mainRemote.allowed)

        console.terse("\nAlive Main to other *********\n")
        otherRemote = main.remotes[other.local.uid]
        mainRemote = other.remotes[main.local.uid]
        self.assertIs(otherRemote.alived, None)
        self.assertIs(mainRemote.alived, None)
        self.alive(main, other, deid=other.local.uid)
        self.assertEqual(len(main.transactions), 0)
        self.assertEqual(len(other.transactions), 0)
        self.assertTrue(otherRemote.alived)
        self.assertTrue(mainRemote.alived)

        console.terse("\nAlive Other to Main *********\n")
        otherRemote.alived = None
        mainRemote.alived = None
        self.assertIs(otherRemote.alived, None)
        self.assertIs(mainRemote.alived, None)
        self.alive(other, main, deid=main.local.uid)
        self.assertEqual(len(main.transactions), 0)
        self.assertEqual(len(other.transactions), 0)
        self.assertTrue(otherRemote.alived)
        self.assertTrue(mainRemote.alived)

        main.server.close()
        main.clearLocal()
        main.clearRemoteKeeps()

        other.server.close()
        other.clearLocal()
        other.clearRemoteKeeps()

    def testAliveUnjoinedFromMain(self):
        '''
        Test alive transaction for unjoined main to other
        '''
        console.terse("{0}\n".format(self.testAliveUnjoinedOther.__doc__))

        mainData = self.createRoadData(name='main', base=self.base, auto=True)
        keeping.clearAllKeepSafe(mainData['dirpath'])
        main = self.createRoadStack(data=mainData,
                                     eid=1,
                                     main=True,
                                     auto=mainData['auto'],
                                     ha=None)

        otherData = self.createRoadData(name='other', base=self.base)
        keeping.clearAllKeepSafe(otherData['dirpath'])
        other = self.createRoadStack(data=otherData,
                                     eid=0,
                                     main=None,
                                     auto=None,
                                     ha=("", raeting.RAET_TEST_PORT))

        console.terse("\nBoth unjoined Alive Main to Other *********\n")
        self.assertEqual(len(main.remotes), 0)
        self.assertEqual(len(other.remotes), 0)

        #now create remote for other and add to main
        main.addRemote(estating.RemoteEstate(stack=main,
                                             eid=2,
                                             name=otherData['name'],
                                             ha=('127.0.0.1', other.local.port),
                                             verkey=otherData['verhex'],
                                             pubkey=otherData['pubhex'],
                                             period=main.period,
                                             offset=main.offset))

        self.alive(main, other, mha=('127.0.0.1', other.local.port))
        self.assertEqual(len(main.transactions), 0)
        self.assertEqual(len(other.transactions), 0)
        otherRemote = main.remotes[other.local.uid]
        mainRemote = other.remotes[main.local.uid]
        self.assertIs(otherRemote.joined, True)
        self.assertIs(mainRemote.joined,  True)
        self.assertIs(otherRemote.alived,  None)
        self.assertIs(mainRemote.alived,  None)

        self.alive(main, other, deid=other.local.uid)
        self.assertEqual(len(main.transactions), 0)
        self.assertEqual(len(other.transactions), 0)
        self.assertIs(otherRemote.allowed, True)
        self.assertIs(mainRemote.allowed,  True)
        self.assertIs(otherRemote.alived,  None)
        self.assertIs(mainRemote.alived,  None)

        self.alive(main, other, deid=other.local.uid)
        self.assertEqual(len(main.transactions), 0)
        self.assertEqual(len(other.transactions), 0)
        self.assertIs(otherRemote.alived,  True)
        self.assertIs(mainRemote.alived,  True)

        console.terse("\nAlive Other to Main *********\n")
        otherRemote.alived = None
        mainRemote.alived = None
        self.assertIs(otherRemote.alived, None)
        self.assertIs(mainRemote.alived, None)

        self.alive(other, main, deid=main.local.uid)
        self.assertEqual(len(main.transactions), 0)
        self.assertEqual(len(other.transactions), 0)
        self.assertTrue(otherRemote.alived)
        self.assertTrue(mainRemote.alived)

        main.server.close()
        main.clearLocal()
        main.clearRemoteKeeps()

        other.server.close()
        other.clearLocal()
        other.clearRemoteKeeps()

    def testManageMainRebootCascade(self):
        '''
        Test stack manage remotes as if main were rebooted
        '''
        console.terse("{0}\n".format(self.testManageMainRebootCascade.__doc__))

        mainData = self.createRoadData(name='main', base=self.base, auto=True)
        mainDirpath = mainData['dirpath']
        keeping.clearAllKeepSafe(mainData['dirpath'])
        main = self.createRoadStack(data=mainData,
                                     eid=1,
                                     main=True,
                                     auto=mainData['auto'],
                                     ha=None)

        otherData = self.createRoadData(name='other', base=self.base)
        otherDirpath = otherData['dirpath']
        keeping.clearAllKeepSafe(otherData['dirpath'])
        other = self.createRoadStack(data=otherData,
                                     eid=0,
                                     main=None,
                                     auto=None,
                                     ha=("", raeting.RAET_TEST_PORT))

        other1Data = self.createRoadData(name='other1', base=self.base)
        other1Dirpath = other1Data['dirpath']
        keeping.clearAllKeepSafe(other1Data['dirpath'])
        other1 = self.createRoadStack(data=other1Data,
                                     eid=0,
                                     main=None,
                                     auto=None,
                                     ha=("", 7532))


        self.join(other, main)
        self.join(other1, main)
        self.allow(other, main)
        self.allow(other1, main)

        console.terse("\nTest manage remotes presence *********\n")
        console.terse("\nMake all alive *********\n")
        stacks = [main, other, other1]
        for remote in main.remotes.values(): #make all alive
            main.alive(duid=remote.uid)
        self.serviceStacks(stacks, duration=3.0)
        for remote in main.remotes.values():
            self.assertTrue(remote.alived)

        main.manage(immediate=True)
        self.assertEqual(len(main.transactions), 2) # started 2 alive transactions
        for remote in main.remotes.values(): # should reset alive to None
            self.assertIs(remote.alived, None)

        self.serviceStacks(stacks, duration=3.0)
        for stack in stacks:
            self.assertEqual(len(stack.transactions), 0)
        for remote in main.remotes.values():
            self.assertTrue(remote.alived)

        # now close down main and reload from saved data and manage
        console.terse("\nMake all alive with cascade after main reboots *********\n")
        main.server.close()
        main = stacking.RoadStack(dirpath=mainDirpath, store=self.store)
        stacks = [main, other, other1]

        for remote in main.remotes.values():
            self.assertIs(remote.joined, None)
            self.assertIs(remote.allowed, None)
            self.assertIs(remote.alived, None)

        main.manage(immediate=True, cascade=True)
        self.assertEqual(len(main.transactions), 2) # started 2 alive transactions
        for remote in main.remotes.values(): # should reset alive to None
            self.assertIs(remote.alived, None)
        self.serviceStacks(stacks, duration=3.0)
        for stack in stacks:
            self.assertEqual(len(stack.transactions), 0)
        for remote in main.remotes.values():
            self.assertIs(remote.joined, True)
            self.assertIs(remote.allowed, True)
            self.assertIs(remote.alived, True)

        # Now test as if others are rebooted
        console.terse("\nMake all alive with cascade after others reboot *********\n")
        other.server.close()
        other1.server.close()
        other = stacking.RoadStack(dirpath=otherDirpath, store=self.store)
        other1 = stacking.RoadStack(dirpath=other1Dirpath, store=self.store)
        stacks = [main, other, other1]

        self.assertIs(other.remotes[main.local.uid].joined, None)
        self.assertIs(other.remotes[main.local.uid].allowed, None)
        self.assertIs(other.remotes[main.local.uid].alived, None)
        self.assertIs(other1.remotes[main.local.uid].joined, None)
        self.assertIs(other1.remotes[main.local.uid].allowed, None)
        self.assertIs(other1.remotes[main.local.uid].alived, None)

        main.manage(immediate=True, cascade=True)
        self.assertEqual(len(main.transactions), 2) # started 2 alive transactions
        for remote in main.remotes.values(): # should reset alive to None
            self.assertIs(remote.alived, None)
        self.serviceStacks(stacks, duration=3.0)
        for stack in stacks:
            self.assertEqual(len(stack.transactions), 0)
        self.assertIs(other.remotes[main.local.uid].joined, True)
        self.assertIs(other.remotes[main.local.uid].allowed, True)
        self.assertIs(other.remotes[main.local.uid].alived, True)
        self.assertIs(other1.remotes[main.local.uid].joined, True)
        self.assertIs(other1.remotes[main.local.uid].allowed, True)
        self.assertIs(other1.remotes[main.local.uid].alived, True)

        main.server.close()
        main.clearLocal()
        main.clearRemoteKeeps()

        other.server.close()
        other.clearLocal()
        other.clearRemoteKeeps()

        other1.server.close()
        other1.clearLocal()
        other1.clearRemoteKeeps()
Beispiel #11
0
class BasicTestCase(unittest.TestCase):
    """"""
    def setUp(self):
        self.store = storing.Store(stamp=0.0)
        self.timer = StoreTimer(store=self.store, duration=1.0)

        self.baseDirpath = tempfile.mkdtemp(prefix="raet",
                                            suffix="base",
                                            dir=TEMPDIR)
        stacking.RoadStack.Bk = raeting.bodyKinds.json

        #main stack
        mainName = "main"
        mainDirpath = os.path.join(self.baseDirpath, 'road', 'keep', mainName)
        signer = nacling.Signer()
        mainSignKeyHex = signer.keyhex
        privateer = nacling.Privateer()
        mainPriKeyHex = privateer.keyhex

        #other stack
        otherName = "other"
        otherDirpath = os.path.join(self.baseDirpath, 'road', 'keep',
                                    otherName)
        signer = nacling.Signer()
        otherSignKeyHex = signer.keyhex
        privateer = nacling.Privateer()
        otherPriKeyHex = privateer.keyhex

        keeping.clearAllKeep(mainDirpath)
        keeping.clearAllKeep(otherDirpath)

        self.main = stacking.RoadStack(
            store=self.store,
            name=mainName,
            main=True,
            auto=raeting.autoModes.once,
            sigkey=mainSignKeyHex,
            prikey=mainPriKeyHex,
            dirpath=mainDirpath,
        )

        self.other = stacking.RoadStack(
            store=self.store,
            name=otherName,
            auto=raeting.autoModes.once,
            ha=("", raeting.RAET_TEST_PORT),
            sigkey=otherSignKeyHex,
            prikey=otherPriKeyHex,
            dirpath=otherDirpath,
        )

    def tearDown(self):
        self.main.server.close()
        self.other.server.close()

        self.main.clearAllDir()
        self.other.clearAllDir()

        if os.path.exists(self.baseDirpath):
            shutil.rmtree(self.baseDirpath)

    def join(self, timeout=None):
        '''
        Utility method to do join. Call from test method.
        '''
        console.terse("\nJoin Transaction **************\n")
        if not self.other.remotes:
            self.other.addRemote(
                estating.RemoteEstate(
                    stack=self.other,
                    #name=self.main.local.name,
                    fuid=0,  # vacuous join
                    sid=0,  # always 0 for join
                    ha=self.main.local.ha))
        self.other.join(timeout=timeout)
        self.service()

    def allow(self):
        '''
        Utility method to do allow. Call from test method.
        '''
        console.terse("\nAllow Transaction **************\n")
        self.other.allow()
        self.service()

    def alive(self, initiator, correspondent):
        '''
        Utility method to do alive. Call from test method.
        '''
        console.terse("\nAlive Transaction **************\n")
        initiator.alive()
        self.service()

    def service(self, duration=1.0, real=True):
        '''
        Utility method to service queues. Call from test method.
        '''
        self.timer.restart(duration=duration)
        while not self.timer.expired:
            self.other.serviceAll()
            self.main.serviceAll()
            if not (self.main.transactions or self.other.transactions):
                break
            self.store.advanceStamp(0.1)
            if real:
                time.sleep(0.1)

    def serviceOther(self, duration=1.0, real=True):
        '''
        Utility method to only service other queues. Call from test method.
        '''
        self.timer.restart(duration=duration)
        while not self.timer.expired:
            self.other.serviceAll()
            if not (self.other.transactions):
                break
            self.store.advanceStamp(0.1)
            if real:
                time.sleep(0.1)

    def serviceMain(self, duration=1.0, real=True):
        '''
        Utility method to only service main queues. Call from test method.
        '''
        self.timer.restart(duration=duration)
        while not self.timer.expired:
            self.main.serviceAll()
            if not (self.main.transactions):
                break
            self.store.advanceStamp(0.1)
            if real:
                time.sleep(0.1)

    def bootstrap(self, bk=raeting.bodyKinds.json):
        '''
        Initialize
            main on port 7530 with uid of 1
            other on port 7531 with uid of 1
        Complete
            main joined and allowed
            other  joined and allowed
        '''
        stacking.RoadStack.Bk = bk

        self.assertEqual(self.main.name, 'main')
        self.assertEqual(self.main.local.name, 'main')
        self.assertEqual(self.main.ha, ("0.0.0.0", raeting.RAET_PORT))

        self.assertEqual(self.other.name, 'other')
        self.assertEqual(self.other.local.name, 'other')
        self.assertEqual(self.other.ha, ("0.0.0.0", raeting.RAET_TEST_PORT))

        self.join()
        console.terse("\nStack '{0}' uid= {1}\n".format(
            self.main.name, self.main.local.uid))
        self.assertEqual(self.main.local.uid, 1)
        self.assertEqual(self.main.name, 'main')
        self.assertEqual(len(self.main.transactions), 0)
        remote = self.main.remotes.values()[0]
        self.assertTrue(remote.joined)
        self.assertEqual(remote.name, 'other')
        self.assertEqual(remote.uid, 2)
        self.assertEqual(remote.uid, remote.nuid)
        self.assertEqual(remote.fuid, 2)
        self.assertTrue(2 in self.main.remotes)
        self.assertTrue(remote.uid in self.main.remotes)
        self.assertTrue(len(self.main.remotes), 1)
        self.assertTrue(len(self.main.nameRemotes), 1)
        self.assertEqual(len(remote.transactions), 0)
        self.assertTrue('other' in self.main.nameRemotes)
        self.assertIs(self.main.nameRemotes[remote.name], remote)
        console.terse(
            "Stack '{0}' estate name '{1}' joined with '{2}' = {3}\n".format(
                self.main.name, self.main.local.name, remote.name,
                remote.joined))

        console.terse("\nStack '{0}' uid= {1}\n".format(
            self.other.name, self.other.local.uid))
        self.assertEqual(self.other.local.uid, 1)
        self.assertEqual(self.other.name, 'other')
        self.assertEqual(len(self.other.transactions), 0)
        remote = self.other.remotes.values()[0]
        self.assertTrue(remote.joined)
        self.assertEqual(remote.name, 'main')
        self.assertEqual(remote.uid, 2)
        self.assertEqual(remote.uid, remote.nuid)
        self.assertEqual(remote.fuid, 2)
        self.assertTrue(2 in self.other.remotes)
        self.assertTrue(remote.uid in self.other.remotes)
        self.assertTrue(len(self.other.remotes), 1)
        self.assertTrue(len(self.other.nameRemotes), 1)
        self.assertEqual(len(remote.transactions), 0)
        self.assertTrue('main' in self.other.nameRemotes)
        self.assertIs(self.other.nameRemotes[remote.name], remote)
        console.terse(
            "Stack '{0}' estate name '{1}' joined with '{2}' = {3}\n".format(
                self.other.name, self.other.local.name, remote.name,
                remote.joined))

        self.allow()
        console.terse("\nStack '{0}' uid= {1}\n".format(
            self.main.name, self.main.local.uid))
        self.assertEqual(len(self.main.transactions), 0)
        remote = self.main.remotes.values()[0]
        self.assertTrue(remote.allowed)
        self.assertEqual(len(remote.transactions), 0)
        console.terse(
            "Stack '{0}' estate name '{1}' allowd with '{2}' = {3}\n".format(
                self.main.name, self.main.local.name, remote.name,
                remote.allowed))

        console.terse("\nStack '{0}' uid= {1}\n".format(
            self.other.name, self.other.local.uid))
        self.assertEqual(len(self.other.transactions), 0)
        remote = self.other.remotes.values()[0]
        self.assertTrue(remote.allowed)
        self.assertEqual(len(remote.transactions), 0)
        console.terse(
            "Stack '{0}' estate name '{1}' allowed with '{2}' = {3}\n".format(
                self.other.name, self.other.local.name, remote.name,
                remote.allowed))

        console.terse("\nMessage: other to main *********\n")
        body = odict(what="This is a message to the main estate. How are you",
                     extra="I am fine.")
        self.other.txMsgs.append(
            (body, self.other.remotes.values()[0].fuid, None))
        #self.other.message(body=body, deid=self.main.local.uid)
        self.service()

        console.terse("\nStack '{0}' uid= {1}\n".format(
            self.main.name, self.main.local.uid))
        self.assertEqual(len(self.main.transactions), 0)
        for msg, name in self.main.rxMsgs:
            console.terse("Estate '{0}' rxed:\n'{1}'\n".format(
                self.main.local.name, msg))
        self.assertDictEqual(body, self.main.rxMsgs[0][0])

        console.terse("\nMessage: main to other *********\n")
        body = odict(what="This is a message to the other estate. Get to Work",
                     extra="Fix the fence.")
        self.main.txMsgs.append(
            (body, self.main.remotes.values()[0].fuid, None))
        #self.main.message(body=body, deid=self.other.local.uid)
        self.service()

        console.terse("\nStack '{0}' uid= {1}\n".format(
            self.other.name, self.other.local.uid))
        self.assertEqual(len(self.other.transactions), 0)
        for msg, name in self.other.rxMsgs:
            console.terse("Estate '{0}' rxed:\n'{1}'\n".format(
                self.other.local.name, msg))
        self.assertDictEqual(body, self.other.rxMsgs[0][0])

    def bidirectional(self,
                      bk=raeting.bodyKinds.json,
                      mains=None,
                      others=None,
                      duration=3.0):
        '''
        Initialize
            main on port 7530 with uid of 1
            other on port 7531 with uid of 0
        Complete
            main uid of 1 joined and allowed
            other uid of 2 joined and allowed
        '''
        stacking.RoadStack.Bk = bk
        mains = mains or []
        other = others or []

        self.join()
        self.assertEqual(len(self.main.transactions), 0)
        remote = self.main.remotes.values()[0]
        self.assertTrue(remote.joined)
        self.assertEqual(len(self.other.transactions), 0)
        remote = self.other.remotes.values()[0]
        self.assertTrue(remote.joined)

        self.allow()
        self.assertEqual(len(self.main.transactions), 0)
        remote = self.main.remotes.values()[0]
        self.assertTrue(remote.allowed)
        self.assertEqual(len(self.other.transactions), 0)
        remote = self.other.remotes.values()[0]
        self.assertTrue(remote.allowed)

        console.terse("\nMessages Bidirectional *********\n")
        for msg in mains:
            self.main.transmit(msg)
        for msg in others:
            self.other.transmit(msg)

        self.service(duration=duration)

        console.terse("\nStack '{0}' uid= {1}\n".format(
            self.main.name, self.main.local.uid))
        self.assertEqual(len(self.main.transactions), 0)
        self.assertEqual(len(others), len(self.main.rxMsgs))
        for i, duple in enumerate(self.main.rxMsgs):
            console.terse("Estate '{0}' rxed:\n'{1}'\n".format(
                self.main.local.name, duple))
            self.assertDictEqual(others[i], duple[0])

        console.terse("\nStack '{0}' uid= {1}\n".format(
            self.other.name, self.other.local.uid))
        self.assertEqual(len(self.other.transactions), 0)
        self.assertEqual(len(mains), len(self.other.rxMsgs))
        for i, duple in enumerate(self.other.rxMsgs):
            console.terse("Estate '{0}' rxed:\n'{1}'\n".format(
                self.other.local.name, duple))
            self.assertDictEqual(mains[i], duple[0])

    def testBootstrapJson(self):
        '''
        Test join allow message transactions with JSON Serialization of body
        '''
        console.terse("{0}\n".format(self.testBootstrapJson.__doc__))
        self.bootstrap(bk=raeting.bodyKinds.json)

    def testBootstrapMsgpack(self):
        '''
        Test join allow message transactions with MsgPack Serialization of body
        '''
        console.terse("{0}\n".format(self.testBootstrapMsgpack.__doc__))
        self.bootstrap(bk=raeting.bodyKinds.msgpack)

    def testMsgBothwaysJson(self):
        '''
        Test message transactions
        '''
        console.terse("{0}\n".format(self.testMsgBothwaysJson.__doc__))

        others = []
        others.append(odict(house="Mama mia1", queue="fix me"))
        others.append(odict(house="Mama mia2", queue="help me"))
        others.append(odict(house="Mama mia3", queue="stop me"))
        others.append(odict(house="Mama mia4", queue="run me"))

        mains = []
        mains.append(odict(house="Papa pia1", queue="fix me"))
        mains.append(odict(house="Papa pia2", queue="help me"))
        mains.append(odict(house="Papa pia3", queue="stop me"))
        mains.append(odict(house="Papa pia4", queue="run me"))

        self.bidirectional(bk=raeting.bodyKinds.json,
                           mains=mains,
                           others=others)

    def testMsgBothwaysMsgpack(self):
        '''
        Test message transactions
        '''
        console.terse("{0}\n".format(self.testMsgBothwaysMsgpack.__doc__))

        others = []
        others.append(odict(house="Mama mia1", queue="fix me"))
        others.append(odict(house="Mama mia2", queue="help me"))
        others.append(odict(house="Mama mia3", queue="stop me"))
        others.append(odict(house="Mama mia4", queue="run me"))

        mains = []
        mains.append(odict(house="Papa pia1", queue="fix me"))
        mains.append(odict(house="Papa pia2", queue="help me"))
        mains.append(odict(house="Papa pia3", queue="stop me"))
        mains.append(odict(house="Papa pia4", queue="run me"))

        self.bidirectional(bk=raeting.bodyKinds.msgpack,
                           mains=mains,
                           others=others)

    def testSegmentedJson(self):
        '''
        Test segmented message transactions
        '''
        console.terse("{0}\n".format(self.testSegmentedJson.__doc__))

        stuff = []
        for i in range(300):
            stuff.append(str(i).rjust(10, " "))
        stuff = "".join(stuff)

        others = []
        mains = []
        others.append(
            odict(house="Snake eyes", queue="near stuff", stuff=stuff))
        mains.append(odict(house="Craps", queue="far stuff", stuff=stuff))

        bloat = []
        for i in range(300):
            bloat.append(str(i).rjust(100, " "))
        bloat = "".join(bloat)
        others.append(odict(house="Other", queue="big stuff", bloat=bloat))
        mains.append(odict(house="Main", queue="gig stuff", bloat=bloat))

        self.bidirectional(bk=raeting.bodyKinds.json,
                           mains=mains,
                           others=others)

    def testSegmentedMsgpack(self):
        '''
        Test segmented message transactions
        '''
        console.terse("{0}\n".format(self.testSegmentedJson.__doc__))

        stuff = []
        for i in range(300):
            stuff.append(str(i).rjust(10, " "))
        stuff = "".join(stuff)

        others = []
        mains = []
        others.append(
            odict(house="Snake eyes", queue="near stuff", stuff=stuff))
        mains.append(odict(house="Craps", queue="far stuff", stuff=stuff))

        bloat = []
        for i in range(300):
            bloat.append(str(i).rjust(100, " "))
        bloat = "".join(bloat)
        others.append(odict(house="Other", queue="big stuff", bloat=bloat))
        mains.append(odict(house="Main", queue="gig stuff", bloat=bloat))

        self.bidirectional(bk=raeting.bodyKinds.msgpack,
                           mains=mains,
                           others=others)

    def testJoinForever(self):
        '''
        Test other joining with timeout set to 0.0 and default
        '''
        console.terse("{0}\n".format(self.testJoinForever.__doc__))
        self.other.addRemote(
            estating.RemoteEstate(
                stack=self.other,
                fuid=0,  # vacuous join
                sid=0,  # always 0 for join
                ha=self.main.local.ha))
        self.other.join(timeout=0.0)  #attempt to join forever with timeout 0.0
        self.serviceOther(duration=20.0,
                          real=False)  # only service other so no response

        console.terse("\nStack '{0}' uid= {1}\n".format(
            self.main.name, self.main.local.uid))
        self.assertEqual(self.main.local.uid, 1)
        self.assertEqual(self.main.name, 'main')
        self.assertEqual(len(self.main.transactions), 0)
        self.assertEqual(len(self.main.remotes), 0)

        console.terse("\nStack '{0}' uid= {1}\n".format(
            self.other.name, self.other.local.uid))
        self.assertEqual(self.other.local.uid, 1)
        self.assertEqual(self.other.name, 'other')
        self.assertEqual(len(self.other.transactions), 1)
        remote = self.other.remotes.values()[0]
        self.assertIs(remote.joined, None)
        self.assertEqual(remote.uid, 2)
        console.terse(
            "Stack '{0}' estate name '{1}' joined with '{2}' = {3}\n".format(
                self.other.name, self.other.local.name, remote.name,
                remote.joined))

        console.terse("{0} Stats\n".format(self.main.name))
        for key, val in self.main.stats.items():
            console.terse("   {0}={1}\n".format(key, val))
        self.assertEqual(len(self.main.stats), 0)

        console.terse("{0} Stats\n".format(self.other.name))
        for key, val in self.other.stats.items():
            console.terse("   {0}={1}\n".format(key, val))
        self.assertEqual(self.other.stats.get('joiner_tx_join_redo'), 6)

        # Now allow join to complete
        self.service()

        console.terse("\nStack '{0}' uid= {1}\n".format(
            self.main.name, self.main.local.uid))
        self.assertEqual(self.main.local.uid, 1)
        self.assertEqual(self.main.name, 'main')
        self.assertEqual(len(self.main.transactions), 0)
        remote = self.main.remotes.values()[0]
        self.assertTrue(remote.joined)
        self.assertEqual(remote.uid, 2)
        self.assertTrue(2 in self.main.remotes)
        self.assertTrue(len(self.main.remotes), 1)
        self.assertTrue(len(self.main.nameRemotes), 1)
        self.assertEqual(remote.name, 'other')
        self.assertTrue('other' in self.main.nameRemotes)
        console.terse(
            "Stack '{0}' estate name '{1}' joined with '{2}' = {3}\n".format(
                self.main.name, self.main.local.name, remote.name,
                remote.joined))

        console.terse("\nStack '{0}' uid= {1}\n".format(
            self.other.name, self.other.local.uid))
        self.assertEqual(self.other.local.uid, 1)
        self.assertEqual(self.other.name, 'other')
        self.assertEqual(len(self.other.transactions), 0)
        remote = self.other.remotes.values()[0]
        self.assertTrue(remote.joined)
        self.assertEqual(remote.uid, 2)
        self.assertTrue(2 in self.other.remotes)
        self.assertTrue(len(self.other.remotes), 1)
        self.assertTrue(len(self.other.nameRemotes), 1)
        self.assertEqual(remote.name, 'main')
        self.assertTrue('main' in self.other.nameRemotes)
        console.terse(
            "Stack '{0}' estate name '{1}' joined with '{2}' = {3}\n".format(
                self.other.name, self.other.local.name, remote.name,
                remote.joined))

        # Now try again with existing remote data
        self.other.join(timeout=0.0)  #attempt to join forever with timeout 0.0
        self.serviceOther(duration=20.0,
                          real=False)  # only service other so no response

        # main will still have join results from previous join transaction
        console.terse("\nStack '{0}' uid= {1}\n".format(
            self.main.name, self.main.local.uid))
        self.assertEqual(self.main.local.uid, 1)
        self.assertEqual(self.main.name, 'main')
        self.assertEqual(len(self.main.transactions), 0)
        remote = self.main.remotes.values()[0]
        self.assertTrue(remote.joined)
        self.assertEqual(remote.uid, 2)
        self.assertTrue(2 in self.main.remotes)
        self.assertTrue(len(self.main.remotes), 1)
        self.assertTrue(len(self.main.nameRemotes), 1)
        self.assertEqual(remote.name, 'other')
        self.assertTrue('other' in self.main.nameRemotes)
        console.terse(
            "Stack '{0}' estate name '{1}' joined with '{2}' = {3}\n".format(
                self.main.name, self.main.local.name, remote.name,
                remote.joined))

        # Other will have outstanding join transaction
        console.terse("\nStack '{0}' uid= {1}\n".format(
            self.other.name, self.other.local.uid))
        self.assertEqual(self.other.local.uid, 1)
        self.assertEqual(self.other.name, 'other')
        self.assertEqual(len(self.other.transactions), 1)
        remote = self.other.remotes.values()[0]
        self.assertIs(remote.joined, None)
        self.assertEqual(remote.uid, 2)
        self.assertTrue(2 in self.other.remotes)
        self.assertTrue(len(self.other.remotes), 1)
        self.assertTrue(len(self.other.nameRemotes), 1)
        self.assertEqual(remote.name, 'main')
        self.assertTrue('main' in self.other.nameRemotes)
        console.terse(
            "Stack '{0}' estate name '{1}' joined with '{2}' = {3}\n".format(
                self.other.name, self.other.local.name, remote.name,
                remote.joined))

        console.terse("{0} Stats\n".format(self.main.name))
        for key, val in self.main.stats.items():
            console.terse("   {0}={1}\n".format(key, val))
        self.assertEqual(self.main.stats.get('join_correspond_complete'), 1)

        console.terse("{0} Stats\n".format(self.other.name))
        for key, val in self.other.stats.items():
            console.terse("   {0}={1}\n".format(key, val))
        self.assertEqual(self.other.stats.get('joiner_tx_join_redo'), 12)
        self.assertEqual(self.other.stats.get('join_initiate_complete'), 1)

        # Now allow join to complete
        self.service()

        console.terse("\nStack '{0}' uid= {1}\n".format(
            self.main.name, self.main.local.uid))
        self.assertEqual(self.main.local.uid, 1)
        self.assertEqual(self.main.name, 'main')
        self.assertEqual(len(self.main.transactions), 0)
        remote = self.main.remotes.values()[0]
        self.assertTrue(remote.joined)
        self.assertEqual(remote.uid, 2)
        self.assertTrue(2 in self.main.remotes)
        self.assertTrue(len(self.main.remotes), 1)
        self.assertTrue(len(self.main.nameRemotes), 1)
        self.assertEqual(remote.name, 'other')
        self.assertTrue('other' in self.main.nameRemotes)
        console.terse(
            "Stack '{0}' estate name '{1}' joined with '{2}' = {3}\n".format(
                self.main.name, self.main.local.name, remote.name,
                remote.joined))

        console.terse("\nStack '{0}' uid= {1}\n".format(
            self.other.name, self.other.local.uid))
        self.assertEqual(self.other.local.uid, 1)
        self.assertEqual(self.other.name, 'other')
        self.assertEqual(len(self.other.transactions), 0)
        remote = self.other.remotes.values()[0]
        self.assertTrue(remote.joined)
        self.assertEqual(remote.uid, 2)
        self.assertTrue(2 in self.other.remotes)
        self.assertTrue(len(self.other.remotes), 1)
        self.assertTrue(len(self.other.nameRemotes), 1)
        self.assertEqual(remote.name, 'main')
        self.assertTrue('main' in self.other.nameRemotes)
        console.terse(
            "Stack '{0}' estate name '{1}' joined with '{2}' = {3}\n".format(
                self.other.name, self.other.local.name, remote.name,
                remote.joined))

    def testStaleNack(self):
        '''
        Test stale nack
        '''
        console.terse("{0}\n".format(self.testStaleNack.__doc__))

        self.join()
        self.assertEqual(len(self.main.transactions), 0)
        remote = self.main.remotes.values()[0]
        self.assertTrue(remote.joined)
        self.assertEqual(len(self.other.transactions), 0)
        remote = self.other.remotes.values()[0]
        self.assertTrue(remote.joined)

        self.allow()
        self.assertEqual(len(self.main.transactions), 0)
        remote = self.main.remotes.values()[0]
        self.assertTrue(remote.allowed)
        self.assertEqual(len(self.other.transactions), 0)
        remote = self.other.remotes.values()[0]
        self.assertTrue(remote.allowed)

        console.terse("\nMessage transaction *********\n")
        body = odict(what="This is a message to the main estate. How are you",
                     extra="I am fine.")
        self.other.txMsgs.append(
            (body, self.other.remotes.values()[0].fuid, None))
        self.timer.restart(duration=1.0)
        while not self.timer.expired:
            self.other.serviceAllTx(
            )  # transmit but leave receives in socket buffer
            self.main.serviceAllRx()  # receive but leave transmits in queue

            self.store.advanceStamp(0.1)
            time.sleep(0.1)

        self.assertEqual(len(self.main.transactions), 0)  #completed
        self.assertEqual(len(self.other.transactions), 1)  # waiting for ack

        remote = self.other.remotes.values()[0]
        remote.transactions = odict(
        )  #clear transactions so RX is stale correspondent
        self.assertEqual(len(self.other.transactions),
                         0)  # no initated transaction

        self.timer.restart(duration=2.0)
        while not self.timer.expired:
            self.main.serviceAll()  # transmit stale ack
            self.other.serviceAll()  # recieve ack
            self.store.advanceStamp(0.1)
            time.sleep(0.1)

        self.assertEqual(len(self.main.transactions), 0)
        self.assertEqual(len(self.other.transactions), 0)

        print("{0} Stats".format(self.main.name))
        for key, val in self.main.stats.items():
            print("   {0}={1}".format(key, val))
        print()
        print("{0} Stats".format(self.other.name))
        for key, val in self.other.stats.items():
            print("   {0}={1}".format(key, val))
        print()

        self.assertTrue(
            self.other.stats.get('stale_correspondent_attempt') >= 1)
        self.assertTrue(self.other.stats.get('stale_correspondent_nack') >= 1)
        self.assertTrue(
            self.main.stats.get('messagent_correspond_complete') >= 1)
        self.assertTrue(self.main.stats.get('stale_packet') >= 1)

    def testBasicAlive(self):
        '''
        Test basic alive transaction
        '''
        console.terse("{0}\n".format(self.testBasicAlive.__doc__))

        self.join()
        self.assertEqual(len(self.main.transactions), 0)
        remote = self.main.remotes.values()[0]
        self.assertTrue(remote.joined)
        self.assertEqual(len(self.other.transactions), 0)
        remote = self.other.remotes.values()[0]
        self.assertTrue(remote.joined)

        self.allow()
        self.assertEqual(len(self.main.transactions), 0)
        remote = self.main.remotes.values()[0]
        self.assertTrue(remote.allowed)
        self.assertEqual(len(self.other.transactions), 0)
        remote = self.other.remotes.values()[0]
        self.assertTrue(remote.allowed)

        console.terse("\nAlive Other to Main *********\n")
        otherRemote = self.main.remotes.values()[0]
        mainRemote = self.other.remotes.values()[0]
        self.assertIs(otherRemote.alived, None)
        self.assertIs(mainRemote.alived, None)

        self.alive(self.other, self.main)
        self.assertEqual(len(self.main.transactions), 0)
        self.assertTrue(otherRemote.alived)
        self.assertEqual(len(self.other.transactions), 0)
        self.assertTrue(mainRemote.alived)

        console.terse("\nAlive Main to Other *********\n")
        self.alive(self.main, self.other)
        self.assertEqual(len(self.main.transactions), 0)
        remote = self.main.remotes.values()[0]
        self.assertTrue(remote.alived)
        self.assertEqual(len(self.other.transactions), 0)
        remote = self.other.remotes.values()[0]
        self.assertTrue(remote.alived)
Beispiel #12
0
class BasicTestCase(unittest.TestCase):
    """"""

    def setUp(self):
        self.store = storing.Store(stamp=0.0)
        self.timer = StoreTimer(store=self.store, duration=1.0)

        self.mainDirpath = tempfile.mkdtemp(prefix="salt", suffix='main', dir='/tmp')
        opts = self.createOpts(self.mainDirpath, openMode=True, autoAccept=True)
        self.mainSafe = salting.SaltSafe(opts=opts)

        self.otherDirpath = tempfile.mkdtemp(prefix="salt", suffix='other', dir='/tmp')
        opts = self.createOpts(self.otherDirpath, openMode=True, autoAccept=True)
        self.otherSafe = salting.SaltSafe(opts=opts)

        self.baseDirpath = tempfile.mkdtemp(prefix="raet",  suffix="base", dir='/tmp')

    def tearDown(self):
        if os.path.exists(self.mainDirpath):
            shutil.rmtree(self.mainDirpath)

        if os.path.exists(self.otherDirpath):
            shutil.rmtree(self.otherDirpath)

        if os.path.exists(self.baseDirpath):
            shutil.rmtree(self.baseDirpath)

    def createOpts(self, dirpath, openMode=False, autoAccept=True):
        '''
        Create associated pki directories for stack and return opts
        '''

        pkiDirpath = os.path.join(dirpath, 'pki')
        if not os.path.exists(pkiDirpath):
                os.makedirs(pkiDirpath)

        acceptedDirpath = os.path.join(pkiDirpath, 'accepted')
        if not os.path.exists(acceptedDirpath):
            os.makedirs(acceptedDirpath)

        pendingDirpath = os.path.join(pkiDirpath, 'pending')
        if not os.path.exists(pendingDirpath):
            os.makedirs(pendingDirpath)

        rejectedDirpath = os.path.join(pkiDirpath, 'rejected')
        if not os.path.exists(rejectedDirpath):
            os.makedirs(rejectedDirpath)

        localFilepath = os.path.join(pkiDirpath, 'local.key')
        if os.path.exists(localFilepath):
            mode = os.stat(localFilepath).st_mode
            print mode
            os.chmod(localFilepath, mode | stat.S_IWUSR | stat.S_IWUSR)

        cacheDirpath = os.path.join(dirpath, 'cache')
        sockDirpath = os.path.join(dirpath, 'sock')

        opts = dict(
                     pki_dir=pkiDirpath,
                     sock_dir=sockDirpath,
                     cachedir=cacheDirpath,
                     open_mode=openMode,
                     auto_accept=autoAccept,
                     transport='raet',
                     )
        return opts

    def createRoadData(self, name, base):
        '''
        Creates odict and populates with data to setup road stack
        {
            name: stack name local estate name
            dirpath: dirpath for keep files
            sighex: signing key
            verhex: verify key
            prihex: private key
            pubhex: public key
        }
        '''
        data = odict()
        data['name'] = name
        data['dirpath'] = os.path.join(base, 'road', 'keep', name)
        signer = nacling.Signer()
        data['sighex'] = signer.keyhex
        data['verhex'] = signer.verhex
        privateer = nacling.Privateer()
        data['prihex'] = privateer.keyhex
        data['pubhex'] = privateer.pubhex

        return data

    def createRoadStack(self, data, eid=0, main=None, auto=None, ha=None, safe=None):
        '''
        Creates stack and local estate from data with
        local estate.eid = eid
        stack.main = main
        stack.auto = auto
        stack.name = data['name']
        local estate.name = data['name']
        local estate.ha = ha

        returns stack

        '''
        local = estating.LocalEstate(eid=eid,
                                     name=data['name'],
                                     ha=ha,
                                     sigkey=data['sighex'],
                                     prikey=data['prihex'],)

        stack = stacking.RoadStack(name=data['name'],
                                   local=local,
                                   main=main,
                                   dirpath=data['dirpath'],
                                   store=self.store,
                                   safe=safe,
                                   auto=auto,)

        return stack

    def join(self, other, main, duration=1.0):
        '''
        Utility method to do join. Call from test method.
        '''
        console.terse("\nJoin Transaction **************\n")
        other.join()
        self.service(main, other, duration=duration)

    def allow(self, other, main, duration=1.0):
        '''
        Utility method to do allow. Call from test method.
        '''
        console.terse("\nAllow Transaction **************\n")
        other.allow()
        self.service(main, other, duration=duration)

    def message(self, main,  other, mains, others, duration=2.0):
        '''
        Utility to send messages both ways
        '''
        for msg in mains:
            main.transmit(msg)
        for msg in others:
            other.transmit(msg)

        self.service(main, other, duration=duration)

    def service(self, main, other, duration=1.0):
        '''
        Utility method to service queues. Call from test method.
        '''
        self.timer.restart(duration=duration)
        while not self.timer.expired:
            other.serviceAll()
            main.serviceAll()
            if not (main.transactions or other.transactions):
                break
            self.store.advanceStamp(0.1)
            time.sleep(0.1)

    def testBasic(self):
        '''
        Basic keep setup for stack keep and safe persistence load and dump
        '''
        console.terse("{0}\n".format(self.testBasic.__doc__))

        self.assertEqual(self.mainSafe.loadLocalData(), None)
        self.assertEqual(self.mainSafe.loadAllRemoteData(), {})

        dataMain = self.createRoadData(name='main', base=self.baseDirpath)
        main = self.createRoadStack(data=dataMain,
                                     eid=1,
                                     main=True,
                                     ha=None, #default ha is ("", raeting.RAET_PORT)
                                     safe=self.mainSafe)

        console.terse("{0}\nkeep dirpath = {1}\nsafe dirpath = {2}\n".format(
                main.name, main.keep.dirpath, main.safe.dirpath))
        self.assertTrue(main.keep.dirpath.endswith('road/keep/main'))
        self.assertTrue(main.safe.dirpath.endswith('pki'))
        self.assertTrue(main.local.ha, ("0.0.0.0", raeting.RAET_PORT))
        self.assertTrue(main.safe.auto)
        self.assertDictEqual(main.keep.loadLocalData(), {'uid': 1,
                                                         'name': 'main',
                                                         'ha': ['0.0.0.0', 7530],
                                                         'main': True,
                                                         'sid': 0})
        self.assertDictEqual(main.safe.loadLocalData(), {'prihex': dataMain['prihex'],
                                                     'sighex': dataMain['sighex'],
                                                     'auto': True})


        data1 = self.createRoadData(name='remote1', base=self.baseDirpath)
        main.addRemote(estating.RemoteEstate(stack=main,
                                             eid=3,
                                             name=data1['name'],
                                             ha=('127.0.0.1', 7532),
                                             verkey=data1['verhex'],
                                             pubkey=data1['pubhex'],
                                             period=main.period,
                                             offset=main.offset, ))

        data2 = self.createRoadData(name='remote2', base=self.baseDirpath)
        main.addRemote(estating.RemoteEstate(stack=main,
                                             eid=4,
                                             name=data2['name'],
                                             ha=('127.0.0.1', 7533),
                                             verkey=data2['verhex'],
                                             pubkey=data2['pubhex'],
                                             period=main.period,
                                             offset=main.offset,))

        main.dumpRemotes()

        self.assertDictEqual(main.safe.loadAllRemoteData(),
            {'3':
                {'uid': 3,
                 'name': data1['name'],
                 'acceptance': 1,
                 'verhex': data1['verhex'],
                 'pubhex': data1['pubhex']},
            '4':
                {'uid': 4,
                 'name': data2['name'],
                 'acceptance': 1,
                 'verhex': data2['verhex'],
                 'pubhex': data2['pubhex']}})

        self.assertDictEqual(main.keep.loadAllRemoteData(),
            {'3':
                {'uid': 3,
                 'name': 'remote1',
                 'ha': ['127.0.0.1', 7532],
                 'sid': 0,
                 'rsid': 0},
            '4':
                {'uid': 4,
                 'name': 'remote2',
                 'ha': ['127.0.0.1', 7533],
                 'sid': 0,
                 'rsid': 0}})

        # now recreate with saved data
        main.server.close()
        main = stacking.RoadStack(name='main',
                                  dirpath=dataMain['dirpath'],
                                  store=self.store,
                                  safe=self.mainSafe)

        self.assertEqual(main.local.priver.keyhex, dataMain['prihex'])
        self.assertEqual(main.local.signer.keyhex, dataMain['sighex'])

        self.assertEqual(len(main.remotes.values()), 2)

        self.assertEqual(self.otherSafe.loadLocalData(), None)
        self.assertEqual(self.otherSafe.loadAllRemoteData(), {})

        # other stack

        dataOther = self.createRoadData(name='other', base=self.baseDirpath)
        other = self.createRoadStack(data=dataOther,
                                     eid=0,
                                     main=None,
                                     ha=("", raeting.RAET_TEST_PORT),
                                     safe=self.otherSafe)

        console.terse("{0} keep dirpath = {1} safe dirpath = {2}\n".format(
                other.name, other.keep.dirpath, other.safe.dirpath))
        self.assertTrue(other.keep.dirpath.endswith('road/keep/other'))
        self.assertTrue(other.safe.dirpath.endswith('pki'))
        self.assertEqual(other.local.ha, ("0.0.0.0", raeting.RAET_TEST_PORT))

        self.assertDictEqual(other.safe.loadLocalData(), {'prihex': dataOther['prihex'],
                                                        'sighex': dataOther['sighex'],
                                                        'auto': True,})

        data3 = self.createRoadData(name='remote3', base=self.baseDirpath)
        other.addRemote(estating.RemoteEstate(stack=other,
                                              eid=3,
                                              name=data3['name'],
                                              ha=('127.0.0.1', 7534),
                                              verkey=data3['verhex'],
                                              pubkey=data3['pubhex'],
                                              period=main.period,
                                              offset=main.offset,))

        data4 = self.createRoadData(name='remote4', base=self.baseDirpath)
        other.addRemote(estating.RemoteEstate(stack=other,
                                              eid=4,
                                              name=data4['name'],
                                              ha=('127.0.0.1', 7535),
                                              verkey=data4['verhex'],
                                              pubkey=data4['pubhex'],
                                             period=main.period,
                                             offset=main.offset,))

        other.dumpRemotes()
        self.assertDictEqual(other.safe.loadAllRemoteData(),
            {'3':
                {'uid': 3,
                 'name': data3['name'],
                 'acceptance': 1,
                 'verhex': data3['verhex'],
                 'pubhex': data3['pubhex']},
            '4':
                {'uid': 4,
                 'name': data4['name'],
                 'acceptance': 1,
                 'verhex': data4['verhex'],
                 'pubhex': data4['pubhex']}})
        other.server.close()

        self.assertDictEqual(other.keep.loadAllRemoteData(),
            {'3':
                {'uid': 3,
                 'name': 'remote3',
                 'ha': ['127.0.0.1', 7534],
                 'sid': 0,
                 'rsid': 0},
            '4':
                {'uid': 4,
                 'name': 'remote4',
                 'ha': ['127.0.0.1', 7535],
                 'sid': 0,
                 'rsid': 0}})

        main.server.close()
        other.server.close()

    def testBootstrapClean(self):
        '''
        Basic keep setup for stack keep and safe persistence load and dump
        '''
        console.terse("{0}\n".format(self.testBasic.__doc__))

        self.assertEqual(self.mainSafe.loadLocalData(), None)
        self.assertEqual(self.mainSafe.loadAllRemoteData(), {})

        dataMain = self.createRoadData(name='main', base=self.baseDirpath)
        main = self.createRoadStack(data=dataMain,
                                     eid=1,
                                     main=True,
                                     ha=None, #default ha is ("", raeting.RAET_PORT)
                                     safe=self.mainSafe)

        self.assertTrue(main.keep.dirpath.endswith('road/keep/main'))
        self.assertTrue(main.safe.dirpath.endswith('pki'))
        self.assertTrue(main.local.ha, ("0.0.0.0", raeting.RAET_PORT))
        self.assertTrue(main.safe.auto)
        self.assertDictEqual(main.keep.loadLocalData(), {'uid': 1,
                                                         'name': 'main',
                                                         'ha': ['0.0.0.0', 7530],
                                                         'main': True,
                                                         'sid': 0})
        self.assertDictEqual(main.safe.loadLocalData(), {'prihex': dataMain['prihex'],
                                                     'sighex': dataMain['sighex'],
                                                     'auto': True,})

        self.assertEqual(self.otherSafe.loadLocalData(), None)
        self.assertEqual(self.otherSafe.loadAllRemoteData(), {})

        dataOther = self.createRoadData(name='other', base=self.baseDirpath)
        other = self.createRoadStack(data=dataOther,
                                     eid=0,
                                     main=None,
                                     ha=("", raeting.RAET_TEST_PORT),
                                     safe=self.otherSafe)

        console.terse("{0} keep dirpath = {1} safe dirpath = {2}\n".format(
                other.name, other.keep.dirpath, other.safe.dirpath))
        self.assertTrue(other.keep.dirpath.endswith('road/keep/other'))
        self.assertTrue(other.safe.dirpath.endswith('pki'))
        self.assertEqual(other.local.ha, ("0.0.0.0", raeting.RAET_TEST_PORT))
        self.assertTrue(other.safe.auto)

        self.assertDictEqual(other.safe.loadLocalData(), {'prihex': dataOther['prihex'],
                                                        'sighex': dataOther['sighex'],
                                                        'auto': True,})

        self.join(other, main)
        self.assertEqual(len(main.transactions), 0)
        remote = main.remotes.values()[0]
        self.assertTrue(remote.joined)
        self.assertEqual(len(other.transactions), 0)
        remote = other.remotes.values()[0]
        self.assertTrue(remote.joined)

        self.allow(other, main)
        self.assertEqual(len(main.transactions), 0)
        remote = main.remotes.values()[0]
        self.assertTrue(remote.allowed)
        self.assertEqual(len(other.transactions), 0)
        remote = other.remotes.values()[0]
        self.assertTrue(remote.allowed)

        main.server.close()
        other.server.close()
Beispiel #13
0
def test(preClearMaster=True,
         preClearMinion=True,
         postClearMaster=True,
         postClearMinion=True):
    '''
    initially
    master on port 7530 with eid of 1
    minion on port 7531 with eid of 0
    eventually
    master eid of 1
    minion eid of 2
    '''
    console.reinit(verbosity=console.Wordage.concise)

    store = storing.Store(stamp=0.0)

    #master stack
    masterName = "master"
    signer = nacling.Signer()
    masterSignKeyHex = signer.keyhex
    privateer = nacling.Privateer()
    masterPriKeyHex = privateer.keyhex
    masterDirpath = os.path.join('/tmp/raet/road', 'keep', masterName)

    #minion0 stack
    minionName0 = "minion0"
    signer = nacling.Signer()
    minionSignKeyHex = signer.keyhex
    privateer = nacling.Privateer()
    minionPriKeyHex = privateer.keyhex
    m0Dirpath = os.path.join('/tmp/raet/road', 'keep', minionName0)

    if preClearMaster:
        keeping.clearAllKeepSafe(masterDirpath)
    if preClearMinion:
        keeping.clearAllKeepSafe(m0Dirpath)

    local = estating.LocalEstate(
        eid=1,
        name=masterName,
        sigkey=masterSignKeyHex,
        prikey=masterPriKeyHex,
    )
    stack0 = stacking.RoadStack(name=masterName,
                                local=local,
                                auto=True,
                                store=store,
                                main=True,
                                dirpath=masterDirpath)

    local = estating.LocalEstate(
        eid=0,
        name=minionName0,
        ha=("", raeting.RAET_TEST_PORT),
        sigkey=minionSignKeyHex,
        prikey=minionPriKeyHex,
    )
    stack1 = stacking.RoadStack(name=minionName0,
                                local=local,
                                store=store,
                                dirpath=m0Dirpath)

    print "\n********* Join Forever Transaction **********"
    #transacting.Joiner.Timeout = 0 # make join go on forever
    stack1.join(timeout=0.0)  # make join go on forever
    timer = StoreTimer(store=store, duration=30.0)
    while (stack1.transactions or stack0.transactions) and not timer.expired:
        stack1.serviceAll()
        if timer.elapsed > 20.0:
            stack0.serviceAll()
        store.advanceStamp(0.1)

    for remote in stack0.remotes.values():
        print "{0} Remote Estate {1} joined= {2}".format(
            stack0.name, remote.eid, remote.joined)
    for remote in stack1.remotes.values():
        print "{0} Remote Estate {1} joined= {2}".format(
            stack1.name, remote.eid, remote.joined)

    print "{0} Stats".format(stack0.name)
    for key, val in stack0.stats.items():
        print "   {0}={1}".format(key, val)
    print
    print "{0} Stats".format(stack1.name)
    for key, val in stack1.stats.items():
        print "   {0}={1}".format(key, val)
    print

    print "\n********* Join Default Timeout Transaction **********"
    stack1.join(timeout=None)
    timer.restart()
    while (stack1.transactions or stack0.transactions) and not timer.expired:
        stack1.serviceAll()
        if timer.elapsed > 20.0:
            stack0.serviceAll()
        store.advanceStamp(0.1)

    for remote in stack0.remotes.values():
        print "{0} Remote Estate {1} joined= {2}".format(
            stack0.name, remote.eid, remote.joined)
    for remote in stack1.remotes.values():
        print "{0} Remote Estate {1} joined= {2}".format(
            stack1.name, remote.eid, remote.joined)
    print "{0} Stats".format(stack0.name)
    for key, val in stack0.stats.items():
        print "   {0}={1}".format(key, val)
    print
    print "{0} Stats".format(stack1.name)
    for key, val in stack1.stats.items():
        print "   {0}={1}".format(key, val)
    print

    for uid in stack0.remotes:
        stack0.removeRemote(uid)
    for uid in stack1.remotes:
        stack1.removeRemote(uid)

    if postClearMaster:
        keeping.clearAllKeepSafe(masterDirpath)
    if postClearMinion:
        keeping.clearAllKeepSafe(m0Dirpath)

    print "Road {0}".format(stack0.name)
    print stack0.keep.loadLocalData()
    print stack0.keep.loadAllRemoteData()
    print "Safe {0}".format(stack0.name)
    print stack0.safe.loadLocalData()
    print stack0.safe.loadAllRemoteData()
    print

    print "Road {0}".format(stack1.name)
    print stack1.keep.loadLocalData()
    print stack1.keep.loadAllRemoteData()
    print "Safe {0}".format(stack1.name)
    print stack1.safe.loadLocalData()
    print stack1.safe.loadAllRemoteData()
    print

    print "\n********* Join Default Timeout Transaction After Clear Keeps **********"
    stack1.join(timeout=None)
    timer.restart()
    while (stack1.transactions or stack0.transactions) and not timer.expired:
        stack1.serviceAll()
        if timer.elapsed > 20.0:
            stack0.serviceAll()
        store.advanceStamp(0.1)

    for remote in stack0.remotes.values():
        print "{0} Remote Estate {1} joined= {2}".format(
            stack0.name, remote.eid, remote.joined)
    for remote in stack1.remotes.values():
        print "{0} Remote Estate {1} joined= {2}".format(
            stack1.name, remote.eid, remote.joined)

    print "{0} Stats".format(stack0.name)
    for key, val in stack0.stats.items():
        print "   {0}={1}".format(key, val)
    print
    print "{0} Stats".format(stack1.name)
    for key, val in stack1.stats.items():
        print "   {0}={1}".format(key, val)
    print

    print "\n********* Join Forever Timeout Transaction After Clear Keeps**********"
    stack1.join(timeout=0.0)
    timer.restart()
    while (stack1.transactions or stack0.transactions) and not timer.expired:
        stack1.serviceAll()
        if timer.elapsed > 20.0:
            stack0.serviceAll()
        store.advanceStamp(0.1)

    for remote in stack0.remotes.values():
        print "{0} Remote Estate {1} joined= {2}".format(
            stack0.name, remote.eid, remote.joined)
    for remote in stack1.remotes.values():
        print "{0} Remote Estate {1} joined= {2}".format(
            stack1.name, remote.eid, remote.joined)

    print "{0} Stats".format(stack0.name)
    for key, val in stack0.stats.items():
        print "   {0}={1}".format(key, val)
    print
    print "{0} Stats".format(stack1.name)
    for key, val in stack1.stats.items():
        print "   {0}={1}".format(key, val)
    print

    stack0.server.close()
    stack1.server.close()

    if postClearMaster:
        keeping.clearAllKeepSafe(masterDirpath)
    if postClearMinion:
        keeping.clearAllKeepSafe(m0Dirpath)
class BasicTestCase(unittest.TestCase):
    """"""

    def __init__(self, *args, **kwargs):
        super(BasicTestCase, self).__init__(*args, **kwargs)

    def setUp(self):
        self.store = storing.Store(stamp=0.0)
        self.timer = StoreTimer(store=self.store, duration=1.0)
        self.baseDirpath = tempfile.mkdtemp(prefix="raet",  suffix="base", dir=TEMPDIR)
        self.stack = None
        # This has to be set to True in the only one process that would perform tearDown steps
        self.engine = False

    def tearDown(self):
        # The only engine have to tear down stacks after all workers have done
        if not self.engine:
            if self.stack:
                self.stack.server.close()
                self.stack.clearAllDir()
        else:
            if os.path.exists(self.baseDirpath):
                shutil.rmtree(self.baseDirpath)

    def createStack(self, name, port):
        dirpath = os.path.join(self.baseDirpath, 'road', 'keep', name)
        signer = nacling.Signer()
        mainSignKeyHex = signer.keyhex
        privateer = nacling.Privateer()
        mainPriKeyHex = privateer.keyhex

        keeping.clearAllKeep(dirpath)

        return stacking.RoadStack(store=self.store,
                                  name=name,
                                  main=True,
                                  auto=raeting.AutoMode.once.value,
                                  ha=("", port),
                                  sigkey=mainSignKeyHex,
                                  prikey=mainPriKeyHex,
                                  dirpath=dirpath,
                                  )

    def joinAll(self, initiator, correspondentAddresses, timeout=None):
        '''
        Utility method to do join. Call from test method.
        '''
        console.terse("\nJoin Transaction **************\n")
        for ha in correspondentAddresses:
            remote = initiator.addRemote(estating.RemoteEstate(stack=initiator,
                                                               fuid=0,  # vacuous join
                                                               sid=0,  # always 0 for join
                                                               ha=ha))
            initiator.join(uid=remote.uid, timeout=timeout)
        self.serviceOne(initiator)

    def allowAll(self, initiator, timeout=None):
        '''
        Utility method to do allow. Call from test method.
        '''
        console.terse("\nAllow Transaction **************\n")
        for remote in initiator.remotes.values():
            initiator.allow(uid=remote.uid, timeout=timeout)
        self.serviceOne(initiator)

    def serviceAll(self, stacks, duration=100.0, timeout=0.0, step=0.1, exitCase=None):
        '''
        Utility method to service queues. Call from test method.
        '''
        self.timer.restart(duration=duration)
        empty = False
        elapsed = self.timer.getElapsed()
        retReason = 'duration'
        while not self.timer.expired:
            for stack in stacks:
                stack.serviceAll()
            if any(stack.transactions for stack in stacks):
                empty = False  # reset nop timeout
            else:
                if exitCase and exitCase():
                    retReason = 'exitCase'
                    break
                if empty:
                    if self.timer.getElapsed() - elapsed > timeout:
                        retReason = 'timeout'
                        break
                else:
                    empty = True
                    elapsed = self.timer.getElapsed()
            self.store.advanceStamp(step)
            time.sleep(step)
        return retReason

    def serviceOne(self, stack, duration=100.0, timeout=0.0, step=0.1, exitCase=None):
        return self.serviceAll([stack], duration, timeout, step, exitCase)

    def bidirectional(self, stack, duration=3.0):
        console.terse("\nMessages Bidirectional {0} *********\n".format(stack.name))
        verifier = MessageVerifier(size=self.msgSize, count=self.msgCount, house='manor', queue='stuff')
        received = 0
        expected = len(stack.remotes) * self.msgCount
        for msg in generateMessages(name=self.stack.name, size=self.msgSize, count=self.msgCount):
            for remote in stack.remotes.values():
                # send message
                stack.transmit(msg, uid=remote.uid)
                self.serviceOne(stack, duration=0.01, step=0.01)
                # check received
                if stack.rxMsgs:
                    received += len(stack.rxMsgs)
                    while stack.rxMsgs:
                        verifier.verifyMessage(stack.rxMsgs.popleft())

        while received < expected:
            self.serviceOne(stack, duration=3.0, timeout=3.0,
                            exitCase=lambda: stack.rxMsgs)
            # if received nothing during timeout, assume we're done
            if not stack.rxMsgs:
                break
            received += len(stack.rxMsgs)
            while stack.rxMsgs:
                verifier.verifyMessage(stack.rxMsgs.popleft())

        # wait remaining messenger transactions if any to be closed
        if stack.transactions:
            self.serviceOne(stack, duration=duration)

        console.terse("\nStack '{0}' uid={1}\n\tTransactions: {2}\n\trcv/exp: {3}/{4}\n\tStats: {5}\n"
                      .format(stack.name, stack.local.uid, stack.transactions, received, expected, stack.stats))
        rcvErrors = verifier.checkAllDone(remoteCount=len(stack.remotes), msgCount=self.msgCount)
        if rcvErrors:
            console.terse("{0} received message with the following errors:\n".format(stack.name))
            for s in rcvErrors:
                console.terse("\t{0} from {1}\n".format(stack.name, s))
        self.assertEqual(len(stack.transactions), 0)
        self.assertEqual(len(rcvErrors), 0)
        self.assertEqual(received, expected)

    def send(self, stack, duration=3.0):
        console.terse("\nMessages Sender {0} *********\n".format(stack.name))
        for msg in generateMessages(name=stack.name, size=self.msgSize, count=self.msgCount):
            for remote in stack.remotes.values():
                stack.transmit(msg, uid=remote.uid)
                self.serviceOne(stack, duration=0.01, step=0.01)

        serviceCode = self.serviceOne(stack, duration=duration, timeout=3.0)

        console.terse("\nStack '{0}' uid={1}\n\tTransactions: {2}\n\tStats: {3}\n"
                      .format(stack.name, stack.local.uid, stack.transactions, stack.stats))
        self.assertEqual(len(stack.transactions), 0)
        self.assertEqual(len(stack.rxMsgs), 0)

    def receive(self, stack, duration=3.0):
        console.terse("\nMessages Receiver {0} *********\n".format(stack.name))
        verifier = MessageVerifier(size=self.msgSize, count=self.msgCount, house='manor', queue='stuff')
        received = 0
        expected = len(stack.remotes) * self.msgCount
        while received < expected:
            reason = self.serviceOne(stack, duration=duration, timeout=duration,
                                     exitCase=lambda: stack.rxMsgs)
            console.terse("Service exit reason: {0}, transactions: {1}\n".format(reason, stack.transactions))
            # received nothing during timeout, assume there is nothing to receive
            if not stack.rxMsgs:
                break
            received += len(stack.rxMsgs)
            while stack.rxMsgs:
                verifier.verifyMessage(stack.rxMsgs.popleft())

        console.terse("\nStack '{0}' uid={1}\n\tTransactions: {2}\n\trcv/exp: {3}/{4}\n\tStats: {5}\n"
                      .format(stack.name, stack.local.uid, stack.transactions, received, expected, stack.stats))
        for t in stack.transactions:
            if isinstance(t, transacting.Messengent):
                print("Tray lost segments: {0}\n".format([i for i, x in enumerate(t.tray.segments) if x is None]))
        rcvErrors = verifier.checkAllDone(remoteCount=len(stack.remotes), msgCount=self.msgCount)
        if rcvErrors:
            console.terse("{0} received message with the following errors:\n".format(stack.name))
            for s in rcvErrors:
                console.terse("\t{0} from {1}\n".format(stack.name, s))
        self.assertEqual(len(stack.transactions), 0)
        self.assertEqual(len(rcvErrors), 0)
        self.assertEqual(received, expected)

    def masterPeer(self, name, port, minionCount, action):
        # create stack
        self.stack = self.createStack(name, port)

        console.terse("\n{0} Waiting For Minions *********\n".format(name))

        def isBootstrapDone():
            if not self.stack.remotes:
                return False
            if len(self.stack.remotes) != minionCount:
                return False
            for rmt in self.stack.remotes.values():
                if not rmt.allowed:
                    return False
            return True

        serviceCode = self.serviceOne(self.stack, timeout=10.0, exitCase=isBootstrapDone)

        self.assertEqual(len(self.stack.transactions), 0)
        self.assertEqual(len(self.stack.remotes), minionCount)
        for remote in self.stack.remotes.values():
            self.assertTrue(remote.joined)
            self.assertTrue(remote.allowed)

        console.terse("\n{0} Bootstrap Done ({1}) *********\n".format(name, serviceCode))

        action(self.stack, duration=self.duration)

    def minionPeer(self, name, port, remoteAddresses, action):
        # Create stack
        self.stack = self.createStack(name, port)

        console.terse("\n{0} Joining Remotes *********\n".format(name))

        self.joinAll(self.stack, remoteAddresses)
        self.assertEqual(len(self.stack.transactions), 0)
        self.assertEqual(len(self.stack.remotes), len(remoteAddresses))
        for remote in self.stack.remotes.values():
            self.assertTrue(remote.joined)

        console.terse("\n{0} Allowing Remotes *********\n".format(name))

        self.allowAll(self.stack)
        self.assertEqual(len(self.stack.transactions), 0)
        self.assertEqual(len(self.stack.remotes), len(remoteAddresses))
        for remote in self.stack.remotes.values():
            self.assertTrue(remote.allowed)

        console.terse("\n{0} Bootstrap Done *********\n".format(name))

        action(self.stack, duration=self.duration)

    # @parameterized.expand([
    #     ("To Master One To One",       1, 1, 1024, 10, 100.0, "to_master"),
    #     ("To Master Many To One",      1, 5, 1024, 10, 100.0, "to_master"),
    #     ("To Master One To Many",      3, 1, 1024, 10, 100.0, "to_master"),
    #     ("To Master Many To Many",     3, 5, 1024, 10, 100.0, "to_master"),
    #     ("From Master One To One",     1, 1, 1024, 10, 100.0, "from_master"),
    #     ("From Master Many To One",    1, 5, 1024, 10, 100.0, "from_master"),
    #     ("From Master One To Many",    3, 1, 1024, 10, 100.0, "from_master"),
    #     ("From Master Many To Many",   3, 5, 1024, 10, 100.0, "from_master"),
    #     ("Bidirectional One To One",   1, 1, 1024, 10, 100.0, "bidirectional"),
    #     ("Bidirectional Many To One",  1, 5, 1024, 10, 100.0, "bidirectional"),
    #     ("Bidirectional One To Many",  3, 1, 1024, 10, 100.0, "bidirectional"),
    #     ("Bidirectional Many To Many", 3, 5, 1024, 10, 100.0, "bidirectional")
    # ])
    # @data(
    #     ("To Master One To One",       1, 1, 1024, 10, 100.0, "to_master"),
    #     ("To Master Many To One",      1, 5, 1024, 10, 100.0, "to_master"),
    #     ("To Master One To Many",      3, 1, 1024, 10, 100.0, "to_master"),
    #     ("To Master Many To Many",     3, 5, 1024, 10, 100.0, "to_master"),
    #     ("From Master One To One",     1, 1, 1024, 10, 100.0, "from_master"),
    #     ("From Master Many To One",    1, 5, 1024, 10, 100.0, "from_master"),
    #     ("From Master One To Many",    3, 1, 1024, 10, 100.0, "from_master"),
    #     ("From Master Many To Many",   3, 5, 1024, 10, 100.0, "from_master"),
    #     ("Bidirectional One To One",   1, 1, 1024, 10, 100.0, "bidirectional"),
    #     ("Bidirectional Many To One",  1, 5, 1024, 10, 100.0, "bidirectional"),
    #     ("Bidirectional One To Many",  3, 1, 1024, 10, 100.0, "bidirectional"),
    #     ("Bidirectional Many To Many", 3, 5, 1024, 10, 100.0, "bidirectional"),
    # )
    # @unpack
    def messagingMultiPeers(self,
                            # name,
                            masterCount,
                            minionCount,
                            msgSize,
                            msgCount,
                            duration,
                            direction):
        self.masterCount = masterCount
        self.minionCount = minionCount
        self.msgSize = msgSize
        self.msgCount = msgCount
        self.duration = duration
        master_dir = {DIR_BIDIRECTIONAL: self.bidirectional,
                      DIR_TO_MASTER:     self.receive,
                      DIR_FROM_MASTER:   self.send}
        minion_dir = {DIR_BIDIRECTIONAL: self.bidirectional,
                      DIR_TO_MASTER:     self.send,
                      DIR_FROM_MASTER:   self.receive}

        port = raeting.RAET_PORT
        masterHostAddresses = []
        masterProcs = []
        for i in xrange(masterCount):
            masterHostAddresses.append(('', port))
            name = 'master{0}'.format(i)
            masterProc = multiprocessing.Process(target=self.masterPeer,
                                                 name=name,
                                                 args=(name,
                                                       port,
                                                       minionCount,
                                                       master_dir[direction]))
            masterProcs.append(masterProc)
            port += 1

        minionProcs = []
        for i in xrange(minionCount):
            name = 'minion{0}'.format(i)
            minionProc = multiprocessing.Process(target=self.minionPeer,
                                                 name=name,
                                                 args=(name,
                                                       port,
                                                       masterHostAddresses,
                                                       minion_dir[direction]))
            minionProcs.append(minionProc)
            port += 1

        for masterProc in masterProcs:
            masterProc.start()
        for minionProc in minionProcs:
            minionProc.start()
        self.engine = True

        for masterProc in masterProcs:
            masterProc.join()
        for minionProc in minionProcs:
            minionProc.join()

        for masterProc in masterProcs:
            self.assertEqual(masterProc.exitcode, 0)
        for minionProc in minionProcs:
            self.assertEqual(minionProc.exitcode, 0)

    def testOneToOneToMaster(self):
        console.terse("{0}\n".format(self.testOneToOneToMaster.__doc__))
        self.messagingMultiPeers(masterCount=1,
                                 minionCount=1,
                                 msgSize=MSG_SIZE_MED,
                                 msgCount=MSG_COUNT_MED,
                                 duration=100.0,
                                 direction=DIR_TO_MASTER)

    def testManyToOneToMaster(self):
        console.terse("{0}\n".format(self.testManyToOneToMaster.__doc__))
        self.messagingMultiPeers(masterCount=1,
                                 minionCount=MULTI_MINION_COUNT,
                                 msgSize=MSG_SIZE_MED,
                                 msgCount=MSG_COUNT_MED,
                                 duration=100.0,
                                 direction=DIR_TO_MASTER)

    def testOneToManyToMaster(self):
        console.terse("{0}\n".format(self.testOneToManyToMaster.__doc__))
        self.messagingMultiPeers(masterCount=MULTI_MASTER_COUNT,
                                 minionCount=1,
                                 msgSize=MSG_SIZE_MED,
                                 msgCount=MSG_COUNT_MED,
                                 duration=100.0,
                                 direction=DIR_TO_MASTER)

    def testManyToManyToMaster(self):
        console.terse("{0}\n".format(self.testManyToManyToMaster.__doc__))
        self.messagingMultiPeers(masterCount=MULTI_MASTER_COUNT,
                                 minionCount=MULTI_MINION_COUNT,
                                 msgSize=MSG_SIZE_MED,
                                 msgCount=MSG_COUNT_MED,
                                 duration=100.0,
                                 direction=DIR_TO_MASTER)

    def testOneToOneFromMaster(self):
        console.terse("{0}\n".format(self.testOneToOneFromMaster.__doc__))
        self.messagingMultiPeers(masterCount=1,
                                 minionCount=1,
                                 msgSize=MSG_SIZE_MED,
                                 msgCount=MSG_COUNT_MED,
                                 duration=100.0,
                                 direction=DIR_FROM_MASTER)

    def testManyToOneFromMaster(self):
        console.terse("{0}\n".format(self.testManyToOneFromMaster.__doc__))
        self.messagingMultiPeers(masterCount=1,
                                 minionCount=MULTI_MINION_COUNT,
                                 msgSize=MSG_SIZE_MED,
                                 msgCount=MSG_COUNT_MED,
                                 duration=100.0,
                                 direction=DIR_FROM_MASTER)

    def testOneToManyFromMaster(self):
        console.terse("{0}\n".format(self.testOneToManyFromMaster.__doc__))
        self.messagingMultiPeers(masterCount=MULTI_MASTER_COUNT,
                                 minionCount=1,
                                 msgSize=MSG_SIZE_MED,
                                 msgCount=MSG_COUNT_MED,
                                 duration=100.0,
                                 direction=DIR_FROM_MASTER)

    def testManyToManyFromMaster(self):
        console.terse("{0}\n".format(self.testManyToManyFromMaster.__doc__))
        self.messagingMultiPeers(masterCount=MULTI_MASTER_COUNT,
                                 minionCount=MULTI_MINION_COUNT,
                                 msgSize=MSG_SIZE_MED,
                                 msgCount=MSG_COUNT_MED,
                                 duration=100.0,
                                 direction=DIR_FROM_MASTER)

    def testOneToOneBidirectional(self):
        console.terse("{0}\n".format(self.testOneToOneBidirectional.__doc__))
        self.messagingMultiPeers(masterCount=1,
                                 minionCount=1,
                                 msgSize=MSG_SIZE_MED,
                                 msgCount=MSG_COUNT_MED,
                                 duration=100.0,
                                 direction=DIR_BIDIRECTIONAL)

    def testManyToOneBidirectional(self):
        console.terse("{0}\n".format(self.testManyToOneBidirectional.__doc__))
        self.messagingMultiPeers(masterCount=1,
                                 minionCount=MULTI_MINION_COUNT,
                                 msgSize=MSG_SIZE_MED,
                                 msgCount=MSG_COUNT_MED,
                                 duration=100.0,
                                 direction=DIR_BIDIRECTIONAL)

    def testOneToManyBidirectional(self):
        console.terse("{0}\n".format(self.testOneToManyBidirectional.__doc__))
        self.messagingMultiPeers(masterCount=MULTI_MASTER_COUNT,
                                 minionCount=1,
                                 msgSize=MSG_SIZE_MED,
                                 msgCount=MSG_COUNT_MED,
                                 duration=100.0,
                                 direction=DIR_BIDIRECTIONAL)

    def testManyToManyBidirectional(self):
        console.terse("{0}\n".format(self.testManyToManyBidirectional.__doc__))
        self.messagingMultiPeers(masterCount=MULTI_MASTER_COUNT,
                                 minionCount=MULTI_MINION_COUNT,
                                 msgSize=MSG_SIZE_MED,
                                 msgCount=MSG_COUNT_MED,
                                 duration=100.0,
                                 direction=DIR_BIDIRECTIONAL)

    def testManyToManyBidirectional1(self):
        from datetime import datetime as dt
        s = dt.now()
        console.terse("{0}\n".format(self.testManyToManyBidirectional.__doc__))
        self.messagingMultiPeers(masterCount=3,
                                 minionCount=5,
                                 msgSize=1024,
                                 msgCount=100,
                                 duration=100.0,
                                 direction=DIR_BIDIRECTIONAL)
        e = dt.now()
        console.terse('Test time: {0}'.format(e-s))

    def testManyToManyBidirectional2(self):
        from datetime import datetime as dt
        s = dt.now()
        console.terse("{0}\n".format(self.testManyToManyBidirectional.__doc__))
        self.messagingMultiPeers(masterCount=3,
                                 minionCount=5,
                                 msgSize=1024*10,
                                 msgCount=100,
                                 duration=100.0,
                                 direction=DIR_BIDIRECTIONAL)
        e = dt.now()
        console.terse('Test time: {0}'.format(e-s))

    def testManyToManyBidirectional3(self):
        from datetime import datetime as dt
        s = dt.now()
        console.terse("{0}\n".format(self.testManyToManyBidirectional.__doc__))
        self.messagingMultiPeers(masterCount=3,
                                 minionCount=5,
                                 msgSize=1024*100,
                                 msgCount=100,
                                 duration=1000.0,
                                 direction=DIR_BIDIRECTIONAL)
        e = dt.now()
        console.terse('Test time: {0}'.format(e-s))

    def testOneToOneToMasterBig(self):
        console.terse("{0}\n".format(self.testOneToOneToMaster.__doc__))
        self.messagingMultiPeers(masterCount=1,
                                 minionCount=1,
                                 msgSize=1024*1024*10,
                                 msgCount=1,
                                 duration=100.0,
                                 direction=DIR_TO_MASTER)
Beispiel #15
0
class BasicTestCase(unittest.TestCase):
    """"""
    def setUp(self):
        self.store = storing.Store(stamp=0.0)
        self.timer = StoreTimer(store=self.store, duration=1.0)

        self.base = tempfile.mkdtemp(prefix="raet", suffix="base", dir='/tmp')

    def tearDown(self):
        if os.path.exists(self.base):
            shutil.rmtree(self.base)

    def createRoadData(self,
                       base,
                       name='',
                       ha=None,
                       main=None,
                       auto=raeting.autoModes.never):
        '''
        name is local estate name (which is stack name property)
        base is the base directory for the keep files
        auto is the auto accept status mode ()
        Creates odict and populates with data to setup road stack

        '''
        data = odict()
        data['name'] = name
        data['ha'] = ha
        data['main'] = main
        data['auto'] = auto
        data['dirpath'] = os.path.join(base, 'road', 'keep', name)
        signer = nacling.Signer()
        data['sighex'] = signer.keyhex
        data['verhex'] = signer.verhex
        privateer = nacling.Privateer()
        data['prihex'] = privateer.keyhex
        data['pubhex'] = privateer.pubhex

        return data

    def createRoadStack(
        self,
        data,
        uid=None,
        ha=None,
        main=None,
        auto=None,
    ):
        '''
        Creates stack and local estate from data with
        and overrides with parameters

        returns stack

        '''
        stack = stacking.RoadStack(
            store=self.store,
            name=data['name'],
            uid=uid,
            ha=ha or data['ha'],
            sigkey=data['sighex'],
            prikey=data['prihex'],
            auto=auto or data['auto'],
            main=main or data['main'],
            dirpath=data['dirpath'],
        )

        return stack

    def join(self,
             initiator,
             correspondent,
             deid=None,
             duration=1.0,
             cascade=False,
             renewal=False):
        '''
        Utility method to do join. Call from test method.
        '''
        console.terse("\nJoin Transaction **************\n")
        if not initiator.remotes:
            remote = initiator.addRemote(
                estating.RemoteEstate(
                    stack=initiator,
                    fuid=0,  # vacuous join
                    sid=0,  # always 0 for join
                    ha=correspondent.local.ha))
            deid = remote.uid

        initiator.join(uid=deid, cascade=cascade, renewal=renewal)
        self.serviceStacks([correspondent, initiator], duration=duration)

    def allow(self,
              initiator,
              correspondent,
              deid=None,
              duration=1.0,
              cascade=False):
        '''
        Utility method to do allow. Call from test method.
        '''
        console.terse("\nAllow Transaction **************\n")
        initiator.allow(uid=deid, cascade=cascade)
        self.serviceStacks([correspondent, initiator], duration=duration)

    def alive(self,
              initiator,
              correspondent,
              duid=None,
              duration=1.0,
              cascade=False):
        '''
        Utility method to do alive. Call from test method.
        '''
        console.terse("\nAlive Transaction **************\n")
        initiator.alive(uid=duid, cascade=cascade)
        self.serviceStacks([correspondent, initiator], duration=duration)

    def flushReceives(self, stack):
        '''
        Flush any queued up udp packets in receive buffer
        '''
        stack.serviceReceives()
        while stack.rxes:
            stack.rxes.popleft()

    def serviceStacks(self, stacks, duration=1.0):
        '''
        Utility method to service queues for list of stacks. Call from test method.
        '''
        self.timer.restart(duration=duration)
        while not self.timer.expired:
            for stack in stacks:
                stack.serviceAll()
            if all([not stack.transactions for stack in stacks]):
                break
            self.store.advanceStamp(0.05)
            time.sleep(0.05)

    def getAcceptedStacks(self):
        alphaData = self.createRoadData(base=self.base,
                                        name='alpha',
                                        ha=("", raeting.RAET_PORT),
                                        main=True,
                                        auto=raeting.autoModes.once)
        keeping.clearAllKeep(alphaData['dirpath'])
        alpha = self.createRoadStack(data=alphaData)

        betaData = self.createRoadData(base=self.base,
                                       name='beta',
                                       ha=("", raeting.RAET_TEST_PORT),
                                       main=None,
                                       auto=raeting.autoModes.once)
        keeping.clearAllKeep(betaData['dirpath'])
        beta = self.createRoadStack(data=betaData)

        console.terse("\nJoin from Beta to Alpha *********\n")

        self.assertIs(alpha.main, True)
        self.assertIs(alpha.keep.auto, raeting.autoModes.once)
        self.assertEqual(len(alpha.remotes), 0)
        self.assertIs(beta.main, None)
        self.assertIs(beta.keep.auto, raeting.autoModes.once)
        self.assertEqual(len(beta.remotes), 0)
        self.assertIs(beta.mutable, None)
        self.assertIs(alpha.mutable, None)

        self.join(beta, alpha)
        for stack in [alpha, beta]:
            self.assertEqual(len(stack.transactions), 0)
            self.assertEqual(len(stack.remotes), 1)
            self.assertEqual(len(stack.nameRemotes), 1)
            for remote in stack.remotes.values():
                self.assertIs(remote.joined, True)
                self.assertIs(remote.allowed, None)
                self.assertIs(remote.alived, None)
        self.assertIs(beta.mutable, None)
        self.assertIs(alpha.mutable, None)

        return alpha, beta

    def bootstrapJoinedRemotes(self):
        alphaData = self.createRoadData(base=self.base,
                                        name='alpha',
                                        ha=("", raeting.RAET_PORT),
                                        main=True,
                                        auto=raeting.autoModes.once)
        keeping.clearAllKeep(alphaData['dirpath'])
        alpha = self.createRoadStack(data=alphaData)

        betaData = self.createRoadData(base=self.base,
                                       name='beta',
                                       ha=("", raeting.RAET_TEST_PORT),
                                       main=None,
                                       auto=raeting.autoModes.once)
        keeping.clearAllKeep(betaData['dirpath'])
        beta = self.createRoadStack(data=betaData)

        console.terse("\nJoin from Beta to Alpha *********\n")

        self.assertIs(alpha.main, True)
        self.assertIs(alpha.keep.auto, raeting.autoModes.once)
        self.assertEqual(len(alpha.remotes), 0)
        self.assertIs(beta.main, None)
        self.assertIs(beta.keep.auto, raeting.autoModes.once)
        self.assertEqual(len(beta.remotes), 0)
        self.assertIs(beta.mutable, None)
        self.assertIs(alpha.mutable, None)

        return alpha, beta

    def copyData(self, remote):
        keep = {}
        keep['role'] = remote.role
        keep['verhex'] = remote.verfer.keyhex
        keep['pubhex'] = remote.pubber.keyhex
        keep['name'] = remote.name
        keep['ha'] = remote.ha
        keep['fuid'] = remote.fuid
        keep['main'] = remote.main
        keep['kind'] = remote.kind
        return keep

    def sameRoleKeys(self, remote, data):
        '''
        Returns True if role and keys match, False otherwise
        '''
        return (remote.role == data['role']
                and remote.verfer.keyhex == data['verhex']
                and remote.pubber.keyhex == data['pubhex'])

    def sameAll(self, remote, data):
        return (self.sameRoleKeys(remote, data) and remote.name == data['name']
                and remote.ha == data['ha'] and remote.main == data['main']
                and remote.kind == data['kind'])

    def testJoinBasic(self):
        '''
        Test join
        '''
        console.terse("{0}\n".format(self.testJoinBasic.__doc__))

        alphaData = self.createRoadData(base=self.base,
                                        name='alpha',
                                        ha=("", raeting.RAET_PORT),
                                        main=True,
                                        auto=raeting.autoModes.once)
        keeping.clearAllKeep(alphaData['dirpath'])
        alpha = self.createRoadStack(data=alphaData)

        betaData = self.createRoadData(base=self.base,
                                       name='beta',
                                       ha=("", raeting.RAET_TEST_PORT),
                                       main=None,
                                       auto=raeting.autoModes.once)
        keeping.clearAllKeep(betaData['dirpath'])
        beta = self.createRoadStack(data=betaData)

        console.terse("\nJoin from Beta to Alpha *********\n")
        self.assertIs(alpha.main, True)
        self.assertIs(alpha.keep.auto, raeting.autoModes.once)
        self.assertEqual(len(alpha.remotes), 0)
        self.assertIs(beta.main, None)
        self.assertIs(beta.keep.auto, raeting.autoModes.once)
        self.assertEqual(len(beta.remotes), 0)
        self.join(beta, alpha)
        for stack in [alpha, beta]:
            self.assertEqual(len(stack.transactions), 0)
            self.assertEqual(len(stack.remotes), 1)
            self.assertEqual(len(stack.nameRemotes), 1)
            for remote in stack.remotes.values():
                self.assertIs(remote.joined, True)
                self.assertIs(remote.allowed, None)
                self.assertIs(remote.alived, None)

        console.terse("\nAllow Beta to Alpha *********\n")
        self.allow(beta, alpha)
        for stack in [alpha, beta]:
            self.assertEqual(len(stack.transactions), 0)
            self.assertEqual(len(stack.remotes), 1)
            self.assertEqual(len(stack.nameRemotes), 1)
            for remote in stack.remotes.values():
                self.assertIs(remote.joined, True)
                self.assertIs(remote.allowed, True)
                self.assertIs(remote.alived, None)

        for stack in [alpha, beta]:
            stack.server.close()
            stack.clearAllKeeps()

    def testJoinentVacuousAcceptNewMain(self):
        '''
        Test joinent accept vacuous join with an updated main (D1)
        '''
        console.terse("{0}\n".format(
            self.testJoinentVacuousAcceptNewMain.__doc__))

        # Status: Accepted (auto accept keys)
        # Mode: Never, Once, Always
        alpha, beta = self.bootstrapJoinedRemotes()
        # Mutable: Yes
        alpha.mutable = True

        # Vacuous: Yes
        betaRemote = beta.addRemote(
            estating.RemoteEstate(
                stack=beta,
                fuid=0,  # vacuous join
                sid=0,  # always 0 for join
                ha=alpha.local.ha))
        # Ephemeral: No Name (the name is known)
        alphaRemote = estating.RemoteEstate(stack=alpha,
                                            fuid=betaRemote.nuid,
                                            ha=beta.local.ha,
                                            name=beta.name,
                                            verkey=beta.local.signer.verhex,
                                            pubkey=beta.local.priver.pubhex)
        alpha.addRemote(alphaRemote)

        oldMain = None
        newMain = True
        # Name: Old
        # Main: New
        self.assertIs(beta.main, oldMain)
        beta.main = newMain
        # Appl: Either
        # RHA:  Either
        # Nuid: Computed
        # Fuid: Either
        # Leid: 0
        # Reid: Either
        # Role: Either
        # Keys: Either
        # Sameness: Not sameall
        keep = self.copyData(alphaRemote)

        # Test
        self.join(beta, alpha, deid=betaRemote.nuid)

        # Action: Accept, Dump
        for stack in [alpha, beta]:
            self.assertEqual(len(stack.transactions), 0)
            self.assertEqual(len(stack.remotes), 1)
            self.assertEqual(len(stack.nameRemotes), 1)
            for remote in stack.remotes.values():
                self.assertIs(remote.joined, True)
                self.assertIs(remote.allowed, None)
                self.assertIs(remote.alived, None)
        self.assertIs(beta.mutable, None)
        self.assertIs(alpha.mutable, True)
        #keep['main'] = new_main  # why?
        self.assertIs(self.sameAll(alphaRemote, keep), False)
        self.assertEqual(alphaRemote.main, newMain)

        self.assertEqual(alphaRemote.acceptance, raeting.acceptances.accepted)
        self.assertEqual(betaRemote.acceptance, raeting.acceptances.accepted)

        for stack in [alpha, beta]:
            stack.server.close()
            stack.clearAllKeeps()

    def testJoinentVacuousAcceptNewAppl(self):
        '''
        Test joinent accept vacuous join with updated application kind (D2)
        '''
        console.terse("{0}\n".format(
            self.testJoinentVacuousAcceptNewAppl.__doc__))

        # Status: Accepted (auto accept keys)
        # Mode: Never, Once, Always
        alpha, beta = self.bootstrapJoinedRemotes()
        # Mutable: Yes
        alpha.mutable = True

        # Vacuous: Yes
        betaRemote = beta.addRemote(
            estating.RemoteEstate(
                stack=beta,
                fuid=0,  # vacuous join
                sid=0,  # always 0 for join
                ha=alpha.local.ha))
        # Ephemeral: No Name (the name is known)
        alphaRemote = estating.RemoteEstate(stack=alpha,
                                            fuid=betaRemote.nuid,
                                            ha=beta.local.ha,
                                            name=beta.name,
                                            verkey=beta.local.signer.verhex,
                                            pubkey=beta.local.priver.pubhex)
        alpha.addRemote(alphaRemote)

        oldAppl = None
        newAppl = 33
        # Name: Old
        # Main: Either
        # Appl: New
        self.assertIs(beta.kind, oldAppl)
        beta.kind = newAppl
        # RHA:  Either
        # Nuid: Computed
        # Fuid: Either
        # Leid: 0
        # Reid: Either
        # Role: Either
        # Keys: Either
        # Sameness: Not sameall
        keep = self.copyData(alphaRemote)

        # Test
        self.join(beta, alpha, deid=betaRemote.nuid)

        # Action: Accept, Dump
        for stack in [alpha, beta]:
            self.assertEqual(len(stack.transactions), 0)
            self.assertEqual(len(stack.remotes), 1)
            self.assertEqual(len(stack.nameRemotes), 1)
            for remote in stack.remotes.values():
                self.assertIs(remote.joined, True)
                self.assertIs(remote.allowed, None)
                self.assertIs(remote.alived, None)
        self.assertIs(beta.mutable, None)
        self.assertIs(alpha.mutable, True)
        self.assertIs(self.sameAll(alphaRemote, keep), False)
        self.assertEqual(alphaRemote.kind, newAppl)
        self.assertEqual(alphaRemote.acceptance, raeting.acceptances.accepted)
        self.assertEqual(betaRemote.acceptance, raeting.acceptances.accepted)

        for stack in [alpha, beta]:
            stack.server.close()
            stack.clearAllKeeps()

    def testJoinentVacuousAcceptNewRha(self):
        '''
        Test joinent accept vacuous join with updated remote host address (D3)

        This test is not right
        '''
        console.terse("{0}\n".format(
            self.testJoinentVacuousAcceptNewRha.__doc__))

        # Status: Accepted (auto accept keys)
        # Mode: Never, Once, Always
        alpha, beta = self.bootstrapJoinedRemotes()
        # Mutable: Yes
        alpha.mutable = True

        newHa = ('127.0.0.5', beta.local.ha[1])
        oldHa = ('127.0.0.1', beta.local.ha[1])

        # Vacuous: Yes
        betaRemote = beta.addRemote(
            estating.RemoteEstate(
                stack=beta,
                fuid=0,  # vacuous join
                sid=0,  # always 0 for join
                ha=alpha.local.ha))
        # Ephemeral: No Name (the name is known)
        alphaRemote = estating.RemoteEstate(stack=alpha,
                                            fuid=betaRemote.nuid,
                                            ha=newHa,
                                            name=beta.name,
                                            verkey=beta.local.signer.verhex,
                                            pubkey=beta.local.priver.pubhex)
        alpha.addRemote(alphaRemote)

        # Name: Old
        # Main: Either
        # Appl: Either
        # RHA:  New: alpha remote ha is set to 127.0.0.5, beta actual ha is 127.0.0.1
        # Nuid: Computed
        # Fuid: Either
        # Leid: 0
        # Reid: Either
        # Role: Either
        # Keys: Either
        # Sameness: Not sameall
        self.assertEqual(alphaRemote.ha, newHa)
        keep = self.copyData(alphaRemote)

        # Test
        self.join(beta, alpha, deid=betaRemote.nuid)

        # Action: Accept, Dump
        for stack in [alpha, beta]:
            self.assertEqual(len(stack.transactions), 0)
            self.assertEqual(len(stack.remotes), 1)
            self.assertEqual(len(stack.nameRemotes), 1)
            for remote in stack.remotes.values():
                self.assertIs(remote.joined, True)
                self.assertIs(remote.allowed, None)
                self.assertIs(remote.alived, None)
        self.assertIs(beta.mutable, None)
        self.assertIs(alpha.mutable, True)
        self.assertIs(self.sameAll(alphaRemote, keep), False)
        self.assertEqual(alphaRemote.ha, oldHa)
        self.assertEqual(alphaRemote.acceptance, raeting.acceptances.accepted)
        self.assertEqual(betaRemote.acceptance, raeting.acceptances.accepted)

        for stack in [alpha, beta]:
            stack.server.close()
            stack.clearAllKeeps()

    def testJoinentVacuousAcceptNewFuid(self):
        '''
        Test joinent accept vacuous join with an updated fuid (D4)

        This test is not right.
        '''
        console.terse("{0}\n".format(
            self.testJoinentVacuousAcceptNewFuid.__doc__))

        # Status: Accepted (auto accept keys)
        # Mode: Never, Once, Always
        alpha, beta = self.bootstrapJoinedRemotes()
        # Mutable: Yes
        alpha.mutable = True

        # Vacuous: Yes
        betaRemote = beta.addRemote(
            estating.RemoteEstate(
                stack=beta,
                fuid=0,  # vacuous join
                sid=0,  # always 0 for join
                ha=alpha.local.ha))

        newFuid = 33
        oldFuid = betaRemote.nuid

        # Ephemeral: No Name (the name is known)
        alphaRemote = estating.RemoteEstate(stack=alpha,
                                            fuid=newFuid,
                                            ha=beta.local.ha,
                                            name=beta.name,
                                            verkey=beta.local.signer.verhex,
                                            pubkey=beta.local.priver.pubhex)
        alpha.addRemote(alphaRemote)

        # Name: Old
        # Main: Either
        # Appl: Either
        # RHA:  Either
        # Nuid: Computed
        # Fuid: New: alphaRemote has uid=33 that is 'old', betaRemote has uid=2
        # Leid: 0
        # Reid: Either
        # Role: Either
        # Keys: Either
        # Sameness: Not sameall
        keep = self.copyData(alphaRemote)

        # Test
        self.join(beta, alpha, deid=betaRemote.nuid)

        # Action: Accept, Dump
        for stack in [alpha, beta]:
            self.assertEqual(len(stack.transactions), 0)
            self.assertEqual(len(stack.remotes), 1)
            self.assertEqual(len(stack.nameRemotes), 1)
            for remote in stack.remotes.values():
                self.assertIs(remote.joined, True)
                self.assertIs(remote.allowed, None)
                self.assertIs(remote.alived, None)
        self.assertIs(beta.mutable, None)
        self.assertIs(alpha.mutable, True)
        self.assertIs(self.sameAll(alphaRemote, keep),
                      True)  # this test is backwards
        self.assertEqual(alphaRemote.fuid, oldFuid)
        self.assertEqual(alphaRemote.acceptance, raeting.acceptances.accepted)
        self.assertEqual(betaRemote.acceptance, raeting.acceptances.accepted)

        for stack in [alpha, beta]:
            stack.server.close()
            stack.clearAllKeeps()

    def testJoinentVacuousAcceptNewKeys(self):
        '''
        Test joinent accept vacuous join with an updated keys (D5)
        '''
        console.terse("{0}\n".format(
            self.testJoinentVacuousAcceptNewKeys.__doc__))

        # Status: Accepted (auto accept keys)
        # Mode: Never, Once, Always
        alpha, beta = self.bootstrapJoinedRemotes()
        # Mutable: Yes
        alpha.mutable = True

        # Vacuous: Yes
        betaRemote = beta.addRemote(
            estating.RemoteEstate(
                stack=beta,
                fuid=0,  # vacuous join
                sid=0,  # always 0 for join
                ha=alpha.local.ha))

        # Ephemeral: No Name (the name is known)
        alphaRemote = estating.RemoteEstate(stack=alpha,
                                            fuid=betaRemote.nuid,
                                            ha=beta.local.ha,
                                            name=beta.name,
                                            verkey=beta.local.signer.verhex,
                                            pubkey=beta.local.priver.pubhex)
        alpha.addRemote(alphaRemote)

        # Name: Old
        # Main: Either
        # Appl: Either
        # RHA:  Either
        # Nuid: Computed
        # Fuid: Either
        # Leid: 0
        # Reid: Either
        # Role: Old
        # Keys: New
        beta.local.signer = nacling.Signer()
        beta.local.priver = nacling.Privateer()
        # Sameness: Not sameall
        keep = self.copyData(alphaRemote)

        # Test
        self.join(beta, alpha, deid=betaRemote.nuid)

        # Action: Accept, Dump
        for stack in [alpha, beta]:
            self.assertEqual(len(stack.transactions), 0)
            self.assertEqual(len(stack.remotes), 1)
            self.assertEqual(len(stack.nameRemotes), 1)
            for remote in stack.remotes.values():
                self.assertIs(remote.joined, True)
                self.assertIs(remote.allowed, None)
                self.assertIs(remote.alived, None)
        self.assertIs(beta.mutable, None)
        self.assertIs(alpha.mutable, True)
        self.assertIs(self.sameAll(alphaRemote, keep), False)
        self.assertIs(self.sameRoleKeys(alphaRemote, keep), False)
        self.assertEqual(alphaRemote.verfer.keyhex, beta.local.signer.verhex)
        self.assertEqual(alphaRemote.pubber.keyhex, beta.local.priver.pubhex)
        self.assertEqual(alphaRemote.acceptance, raeting.acceptances.accepted)
        self.assertEqual(betaRemote.acceptance, raeting.acceptances.accepted)

        # Keys: New
        beta.local.priver = nacling.Privateer()
        betaRemote.fuid = 0
        betaRemote.sid = 0

        for stack in [alpha, beta]:
            stack.server.close()
            stack.clearAllKeeps()

    def testJoinentVacuousAcceptNewRole(self):
        '''
        Test joinent accept vacuous join with an updated role (D6)
        '''
        console.terse("{0}\n".format(
            self.testJoinentVacuousAcceptNewRole.__doc__))

        # Status: Accepted (auto accept keys)
        # Mode: Never, Once, Always
        alpha, beta = self.bootstrapJoinedRemotes()
        # Mutable: Yes
        alpha.mutable = True

        # Vacuous: Yes
        betaRemote = beta.addRemote(
            estating.RemoteEstate(
                stack=beta,
                fuid=0,  # vacuous join
                sid=0,  # always 0 for join
                ha=alpha.local.ha))
        # Ephemeral: No Name (the name is known)
        alphaRemote = estating.RemoteEstate(stack=alpha,
                                            fuid=betaRemote.nuid,
                                            ha=beta.local.ha,
                                            name=beta.name,
                                            verkey=beta.local.signer.verhex,
                                            pubkey=beta.local.priver.pubhex)
        alpha.addRemote(alphaRemote)

        oldRole = 'beta'
        newRole = 'beta_new'
        # Name: Old
        # Main: Either
        # Appl: Either
        # RHA:  Either
        # Nuid: Computed
        # Fuid: Either
        # Leid: 0
        # Reid: Either
        # Role: New
        self.assertIs(beta.local.role, oldRole)
        beta.local.role = newRole
        # Keys: Either
        # Sameness: Not sameall
        keep = self.copyData(alphaRemote)

        # Test
        self.join(beta, alpha, deid=betaRemote.nuid)

        # Action: Accept, Dump
        for stack in [alpha, beta]:
            self.assertEqual(len(stack.transactions), 0)
            self.assertEqual(len(stack.remotes), 1)
            self.assertEqual(len(stack.nameRemotes), 1)
            for remote in stack.remotes.values():
                self.assertIs(remote.joined, True)
                self.assertIs(remote.allowed, None)
                self.assertIs(remote.alived, None)
        self.assertIs(beta.mutable, None)
        self.assertIs(alpha.mutable, True)
        self.assertIs(self.sameAll(alphaRemote, keep), False)
        self.assertEqual(alphaRemote.role, newRole)
        self.assertEqual(alphaRemote.acceptance, raeting.acceptances.accepted)
        self.assertEqual(betaRemote.acceptance, raeting.acceptances.accepted)

        for stack in [alpha, beta]:
            stack.server.close()
            stack.clearAllKeeps()
Beispiel #16
0
class BasicTestCase(unittest.TestCase):
    """"""

    def setUp(self):
        self.store = storing.Store(stamp=0.0)
        self.timer = StoreTimer(store=self.store, duration=1.0)

        self.base = tempfile.mkdtemp(prefix="raet",  suffix="base", dir='/tmp')

    def tearDown(self):
        if os.path.exists(self.base):
            shutil.rmtree(self.base)

    def createRoadData(self,
                       base,
                       name='',
                       ha=None,
                       main=None,
                       auto=raeting.autoModes.never):
        '''
        name is local estate name (which is stack name property)
        base is the base directory for the keep files
        auto is the auto accept status mode ()
        Creates odict and populates with data to setup road stack

        '''
        data = odict()
        data['name'] = name
        data['ha'] = ha
        data['main'] =  main
        data['auto'] = auto
        data['dirpath'] = os.path.join(base, 'road', 'keep', name)
        signer = nacling.Signer()
        data['sighex'] = signer.keyhex
        data['verhex'] = signer.verhex
        privateer = nacling.Privateer()
        data['prihex'] = privateer.keyhex
        data['pubhex'] = privateer.pubhex

        return data

    def createRoadStack(self,
                        data,
                        uid=None,
                        ha=None,
                        main=None,
                        auto=None,):
        '''
        Creates stack and local estate from data with
        and overrides with parameters

        returns stack

        '''
        stack = stacking.RoadStack(store=self.store,
                                   name=data['name'],
                                   uid=uid,
                                   ha=ha or data['ha'],
                                   sigkey=data['sighex'],
                                   prikey=data['prihex'],
                                   auto=auto or data['auto'],
                                   main=main or data['main'],
                                   dirpath=data['dirpath'],)

        return stack

    def join(self, initiator, correspondent, deid=None, duration=1.0,
                cascade=False, renewal=False):
        '''
        Utility method to do join. Call from test method.
        '''
        console.terse("\nJoin Transaction **************\n")
        if not initiator.remotes:
            remote =  initiator.addRemote(estating.RemoteEstate(stack=initiator,
                                                      fuid=0, # vacuous join
                                                      sid=0, # always 0 for join
                                                      ha=correspondent.local.ha))
            deid = remote.uid

        initiator.join(uid=deid, cascade=cascade, renewal=renewal)
        self.serviceStacks([correspondent, initiator], duration=duration)

    def allow(self, initiator, correspondent, deid=None, duration=1.0,
                cascade=False):
        '''
        Utility method to do allow. Call from test method.
        '''
        console.terse("\nAllow Transaction **************\n")
        initiator.allow(uid=deid, cascade=cascade)
        self.serviceStacks([correspondent, initiator], duration=duration)

    def alive(self, initiator, correspondent, duid=None, duration=1.0,
                cascade=False):
        '''
        Utility method to do alive. Call from test method.
        '''
        console.terse("\nAlive Transaction **************\n")
        initiator.alive(uid=duid, cascade=cascade)
        self.serviceStacks([correspondent, initiator], duration=duration)

    def flushReceives(self, stack):
        '''
        Flush any queued up udp packets in receive buffer
        '''
        stack.serviceReceives()
        while stack.rxes:
            stack.rxes.popleft()

    def serviceStacks(self, stacks, duration=1.0):
        '''
        Utility method to service queues for list of stacks. Call from test method.
        '''
        self.timer.restart(duration=duration)
        while not self.timer.expired:
            for stack in stacks:
                stack.serviceAll()
            if all([not stack.transactions for stack in stacks]):
                break
            self.store.advanceStamp(0.05)
            time.sleep(0.05)

    def getAcceptedStacks(self):
        alphaData = self.createRoadData(base=self.base,
                                       name='alpha',
                                       ha=("", raeting.RAET_PORT),
                                       main=True,
                                       auto=raeting.autoModes.once)
        keeping.clearAllKeep(alphaData['dirpath'])
        alpha = self.createRoadStack(data=alphaData)

        betaData = self.createRoadData(base=self.base,
                                        name='beta',
                                        ha=("", raeting.RAET_TEST_PORT),
                                        main=None,
                                        auto=raeting.autoModes.once)
        keeping.clearAllKeep(betaData['dirpath'])
        beta = self.createRoadStack(data=betaData)

        console.terse("\nJoin from Beta to Alpha *********\n")

        self.assertIs(alpha.main, True)
        self.assertIs(alpha.keep.auto, raeting.autoModes.once)
        self.assertEqual(len(alpha.remotes), 0)
        self.assertIs(beta.main, None)
        self.assertIs(beta.keep.auto, raeting.autoModes.once)
        self.assertEqual(len(beta.remotes), 0)
        self.assertIs(beta.mutable, None)
        self.assertIs(alpha.mutable, None)

        self.join(beta, alpha)
        for stack in [alpha, beta]:
            self.assertEqual(len(stack.transactions), 0)
            self.assertEqual(len(stack.remotes), 1)
            self.assertEqual(len(stack.nameRemotes), 1)
            for remote in stack.remotes.values():
                self.assertIs(remote.joined, True)
                self.assertIs(remote.allowed, None)
                self.assertIs(remote.alived, None)
        self.assertIs(beta.mutable, None)
        self.assertIs(alpha.mutable, None)

        return alpha, beta

    def bootstrapJoinedRemotes(self):
        alphaData = self.createRoadData(base=self.base,
                                        name='alpha',
                                        ha=("", raeting.RAET_PORT),
                                        main=True,
                                        auto=raeting.autoModes.once)
        keeping.clearAllKeep(alphaData['dirpath'])
        alpha = self.createRoadStack(data=alphaData)

        betaData = self.createRoadData(base=self.base,
                                       name='beta',
                                       ha=("", raeting.RAET_TEST_PORT),
                                       main=None,
                                       auto=raeting.autoModes.once)
        keeping.clearAllKeep(betaData['dirpath'])
        beta = self.createRoadStack(data=betaData)

        console.terse("\nJoin from Beta to Alpha *********\n")

        self.assertIs(alpha.main, True)
        self.assertIs(alpha.keep.auto, raeting.autoModes.once)
        self.assertEqual(len(alpha.remotes), 0)
        self.assertIs(beta.main, None)
        self.assertIs(beta.keep.auto, raeting.autoModes.once)
        self.assertEqual(len(beta.remotes), 0)
        self.assertIs(beta.mutable, None)
        self.assertIs(alpha.mutable, None)

        return alpha, beta

    def copyData(self, remote):
        keep = {}
        keep['role'] = remote.role
        keep['verhex'] = remote.verfer.keyhex
        keep['pubhex'] = remote.pubber.keyhex
        keep['name'] = remote.name
        keep['ha'] = remote.ha
        keep['fuid'] = remote.fuid
        keep['main'] = remote.main
        keep['kind'] = remote.kind
        return keep

    def sameRoleKeys(self, remote, data):
        '''
        Returns True if role and keys match, False otherwise
        '''
        return (remote.role ==  data['role'] and
                remote.verfer.keyhex == data['verhex'] and
                remote.pubber.keyhex == data['pubhex'])

    def sameAll(self, remote, data):
        return (self.sameRoleKeys(remote, data) and
                remote.name == data['name'] and
                remote.ha == data['ha'] and
                remote.main == data['main'] and
                remote.kind == data['kind'])

    def testJoinBasic(self):
        '''
        Test join
        '''
        console.terse("{0}\n".format(self.testJoinBasic.__doc__))

        alphaData = self.createRoadData(base=self.base,
                                        name='alpha',
                                        ha=("", raeting.RAET_PORT),
                                        main=True,
                                        auto=raeting.autoModes.once)
        keeping.clearAllKeep(alphaData['dirpath'])
        alpha = self.createRoadStack(data=alphaData)

        betaData = self.createRoadData(base=self.base,
                                       name='beta',
                                       ha=("", raeting.RAET_TEST_PORT),
                                       main=None,
                                       auto=raeting.autoModes.once)
        keeping.clearAllKeep(betaData['dirpath'])
        beta = self.createRoadStack(data=betaData)

        console.terse("\nJoin from Beta to Alpha *********\n")
        self.assertIs(alpha.main, True)
        self.assertIs(alpha.keep.auto, raeting.autoModes.once)
        self.assertEqual(len(alpha.remotes), 0)
        self.assertIs(beta.main, None)
        self.assertIs(beta.keep.auto, raeting.autoModes.once)
        self.assertEqual(len(beta.remotes), 0)
        self.join(beta, alpha)
        for stack in [alpha, beta]:
            self.assertEqual(len(stack.transactions), 0)
            self.assertEqual(len(stack.remotes), 1)
            self.assertEqual(len(stack.nameRemotes), 1)
            for remote in stack.remotes.values():
                self.assertIs(remote.joined, True)
                self.assertIs(remote.allowed, None)
                self.assertIs(remote.alived, None)

        console.terse("\nAllow Beta to Alpha *********\n")
        self.allow(beta, alpha)
        for stack in [alpha, beta]:
            self.assertEqual(len(stack.transactions), 0)
            self.assertEqual(len(stack.remotes), 1)
            self.assertEqual(len(stack.nameRemotes), 1)
            for remote in stack.remotes.values():
                self.assertIs(remote.joined, True)
                self.assertIs(remote.allowed, True)
                self.assertIs(remote.alived, None)

        for stack in [alpha, beta]:
            stack.server.close()
            stack.clearAllKeeps()

    def testJoinentVacuousAcceptNewMain(self):
        '''
        Test joinent accept vacuous join with an updated main (D1)
        '''
        console.terse("{0}\n".format(self.testJoinentVacuousAcceptNewMain.__doc__))

        # Status: Accepted (auto accept keys)
        # Mode: Never, Once, Always
        alpha, beta = self.bootstrapJoinedRemotes()
        # Mutable: Yes
        alpha.mutable = True

        # Vacuous: Yes
        betaRemote = beta.addRemote(estating.RemoteEstate(stack=beta,
                                                           fuid=0, # vacuous join
                                                           sid=0, # always 0 for join
                                                           ha=alpha.local.ha))
        # Ephemeral: No Name (the name is known)
        alphaRemote = estating.RemoteEstate(stack=alpha,
                                             fuid=betaRemote.nuid,
                                             ha=beta.local.ha,
                                             name=beta.name,
                                             verkey=beta.local.signer.verhex,
                                             pubkey=beta.local.priver.pubhex)
        alpha.addRemote(alphaRemote)

        oldMain = None
        newMain = True
        # Name: Old
        # Main: New
        self.assertIs(beta.main, oldMain)
        beta.main = newMain
        # Appl: Either
        # RHA:  Either
        # Nuid: Computed
        # Fuid: Either
        # Leid: 0
        # Reid: Either
        # Role: Either
        # Keys: Either
        # Sameness: Not sameall
        keep = self.copyData(alphaRemote)

        # Test
        self.join(beta, alpha, deid=betaRemote.nuid)

        # Action: Accept, Dump
        for stack in [alpha, beta]:
            self.assertEqual(len(stack.transactions), 0)
            self.assertEqual(len(stack.remotes), 1)
            self.assertEqual(len(stack.nameRemotes), 1)
            for remote in stack.remotes.values():
                self.assertIs(remote.joined, True)
                self.assertIs(remote.allowed, None)
                self.assertIs(remote.alived, None)
        self.assertIs(beta.mutable, None)
        self.assertIs(alpha.mutable, True)
        #keep['main'] = new_main  # why?
        self.assertIs(self.sameAll(alphaRemote, keep), False)
        self.assertEqual(alphaRemote.main, newMain)

        self.assertEqual(alphaRemote.acceptance, raeting.acceptances.accepted)
        self.assertEqual(betaRemote.acceptance, raeting.acceptances.accepted)

        for stack in [alpha, beta]:
            stack.server.close()
            stack.clearAllKeeps()

    def testJoinentVacuousAcceptNewAppl(self):
        '''
        Test joinent accept vacuous join with updated application kind (D2)
        '''
        console.terse("{0}\n".format(self.testJoinentVacuousAcceptNewAppl.__doc__))

        # Status: Accepted (auto accept keys)
        # Mode: Never, Once, Always
        alpha, beta = self.bootstrapJoinedRemotes()
        # Mutable: Yes
        alpha.mutable = True

        # Vacuous: Yes
        betaRemote = beta.addRemote(estating.RemoteEstate(stack=beta,
                                                           fuid=0, # vacuous join
                                                           sid=0, # always 0 for join
                                                           ha=alpha.local.ha))
        # Ephemeral: No Name (the name is known)
        alphaRemote = estating.RemoteEstate(stack=alpha,
                                             fuid=betaRemote.nuid,
                                             ha=beta.local.ha,
                                             name=beta.name,
                                             verkey=beta.local.signer.verhex,
                                             pubkey=beta.local.priver.pubhex)
        alpha.addRemote(alphaRemote)

        oldAppl = None
        newAppl = 33
        # Name: Old
        # Main: Either
        # Appl: New
        self.assertIs(beta.kind, oldAppl)
        beta.kind = newAppl
        # RHA:  Either
        # Nuid: Computed
        # Fuid: Either
        # Leid: 0
        # Reid: Either
        # Role: Either
        # Keys: Either
        # Sameness: Not sameall
        keep = self.copyData(alphaRemote)

        # Test
        self.join(beta, alpha, deid=betaRemote.nuid)

        # Action: Accept, Dump
        for stack in [alpha, beta]:
            self.assertEqual(len(stack.transactions), 0)
            self.assertEqual(len(stack.remotes), 1)
            self.assertEqual(len(stack.nameRemotes), 1)
            for remote in stack.remotes.values():
                self.assertIs(remote.joined, True)
                self.assertIs(remote.allowed, None)
                self.assertIs(remote.alived, None)
        self.assertIs(beta.mutable, None)
        self.assertIs(alpha.mutable, True)
        self.assertIs(self.sameAll(alphaRemote, keep), False)
        self.assertEqual(alphaRemote.kind, newAppl)
        self.assertEqual(alphaRemote.acceptance, raeting.acceptances.accepted)
        self.assertEqual(betaRemote.acceptance, raeting.acceptances.accepted)

        for stack in [alpha, beta]:
            stack.server.close()
            stack.clearAllKeeps()

    def testJoinentVacuousAcceptNewRha(self):
        '''
        Test joinent accept vacuous join with updated remote host address (D3)

        This test is not right
        '''
        console.terse("{0}\n".format(self.testJoinentVacuousAcceptNewRha.__doc__))


        # Status: Accepted (auto accept keys)
        # Mode: Never, Once, Always
        alpha, beta = self.bootstrapJoinedRemotes()
        # Mutable: Yes
        alpha.mutable = True

        newHa = ('127.0.0.5', beta.local.ha[1])
        oldHa = ('127.0.0.1', beta.local.ha[1])

        # Vacuous: Yes
        betaRemote = beta.addRemote(estating.RemoteEstate(stack=beta,
                                                           fuid=0, # vacuous join
                                                           sid=0, # always 0 for join
                                                           ha=alpha.local.ha))
        # Ephemeral: No Name (the name is known)
        alphaRemote = estating.RemoteEstate(stack=alpha,
                                             fuid=betaRemote.nuid,
                                             ha=newHa,
                                             name=beta.name,
                                             verkey=beta.local.signer.verhex,
                                             pubkey=beta.local.priver.pubhex)
        alpha.addRemote(alphaRemote)

        # Name: Old
        # Main: Either
        # Appl: Either
        # RHA:  New: alpha remote ha is set to 127.0.0.5, beta actual ha is 127.0.0.1
        # Nuid: Computed
        # Fuid: Either
        # Leid: 0
        # Reid: Either
        # Role: Either
        # Keys: Either
        # Sameness: Not sameall
        self.assertEqual(alphaRemote.ha, newHa)
        keep = self.copyData(alphaRemote)

        # Test
        self.join(beta, alpha, deid=betaRemote.nuid)

        # Action: Accept, Dump
        for stack in [alpha, beta]:
            self.assertEqual(len(stack.transactions), 0)
            self.assertEqual(len(stack.remotes), 1)
            self.assertEqual(len(stack.nameRemotes), 1)
            for remote in stack.remotes.values():
                self.assertIs(remote.joined, True)
                self.assertIs(remote.allowed, None)
                self.assertIs(remote.alived, None)
        self.assertIs(beta.mutable, None)
        self.assertIs(alpha.mutable, True)
        self.assertIs(self.sameAll(alphaRemote, keep), False)
        self.assertEqual(alphaRemote.ha, oldHa)
        self.assertEqual(alphaRemote.acceptance, raeting.acceptances.accepted)
        self.assertEqual(betaRemote.acceptance, raeting.acceptances.accepted)

        for stack in [alpha, beta]:
            stack.server.close()
            stack.clearAllKeeps()

    def testJoinentVacuousAcceptNewFuid(self):
        '''
        Test joinent accept vacuous join with an updated fuid (D4)

        This test is not right.
        '''
        console.terse("{0}\n".format(self.testJoinentVacuousAcceptNewFuid.__doc__))

        # Status: Accepted (auto accept keys)
        # Mode: Never, Once, Always
        alpha, beta = self.bootstrapJoinedRemotes()
        # Mutable: Yes
        alpha.mutable = True

        # Vacuous: Yes
        betaRemote = beta.addRemote(estating.RemoteEstate(stack=beta,
                                                           fuid=0, # vacuous join
                                                           sid=0, # always 0 for join
                                                           ha=alpha.local.ha))

        newFuid = 33
        oldFuid = betaRemote.nuid

        # Ephemeral: No Name (the name is known)
        alphaRemote = estating.RemoteEstate(stack=alpha,
                                             fuid=newFuid,
                                             ha=beta.local.ha,
                                             name=beta.name,
                                             verkey=beta.local.signer.verhex,
                                             pubkey=beta.local.priver.pubhex)
        alpha.addRemote(alphaRemote)

        # Name: Old
        # Main: Either
        # Appl: Either
        # RHA:  Either
        # Nuid: Computed
        # Fuid: New: alphaRemote has uid=33 that is 'old', betaRemote has uid=2
        # Leid: 0
        # Reid: Either
        # Role: Either
        # Keys: Either
        # Sameness: Not sameall
        keep = self.copyData(alphaRemote)

        # Test
        self.join(beta, alpha, deid=betaRemote.nuid)

        # Action: Accept, Dump
        for stack in [alpha, beta]:
            self.assertEqual(len(stack.transactions), 0)
            self.assertEqual(len(stack.remotes), 1)
            self.assertEqual(len(stack.nameRemotes), 1)
            for remote in stack.remotes.values():
                self.assertIs(remote.joined, True)
                self.assertIs(remote.allowed, None)
                self.assertIs(remote.alived, None)
        self.assertIs(beta.mutable, None)
        self.assertIs(alpha.mutable, True)
        self.assertIs(self.sameAll(alphaRemote, keep), True) # this test is backwards
        self.assertEqual(alphaRemote.fuid, oldFuid)
        self.assertEqual(alphaRemote.acceptance, raeting.acceptances.accepted)
        self.assertEqual(betaRemote.acceptance, raeting.acceptances.accepted)

        for stack in [alpha, beta]:
            stack.server.close()
            stack.clearAllKeeps()

    def testJoinentVacuousAcceptNewKeys(self):
        '''
        Test joinent accept vacuous join with an updated keys (D5)
        '''
        console.terse("{0}\n".format(self.testJoinentVacuousAcceptNewKeys.__doc__))

        # Status: Accepted (auto accept keys)
        # Mode: Never, Once, Always
        alpha, beta = self.bootstrapJoinedRemotes()
        # Mutable: Yes
        alpha.mutable = True

        # Vacuous: Yes
        betaRemote = beta.addRemote(estating.RemoteEstate(stack=beta,
                                                           fuid=0, # vacuous join
                                                           sid=0, # always 0 for join
                                                           ha=alpha.local.ha))

        # Ephemeral: No Name (the name is known)
        alphaRemote = estating.RemoteEstate(stack=alpha,
                                             fuid=betaRemote.nuid,
                                             ha=beta.local.ha,
                                             name=beta.name,
                                             verkey=beta.local.signer.verhex,
                                             pubkey=beta.local.priver.pubhex)
        alpha.addRemote(alphaRemote)

        # Name: Old
        # Main: Either
        # Appl: Either
        # RHA:  Either
        # Nuid: Computed
        # Fuid: Either
        # Leid: 0
        # Reid: Either
        # Role: Old
        # Keys: New
        beta.local.signer = nacling.Signer()
        beta.local.priver = nacling.Privateer()
        # Sameness: Not sameall
        keep = self.copyData(alphaRemote)

        # Test
        self.join(beta, alpha, deid=betaRemote.nuid)

        # Action: Accept, Dump
        for stack in [alpha, beta]:
            self.assertEqual(len(stack.transactions), 0)
            self.assertEqual(len(stack.remotes), 1)
            self.assertEqual(len(stack.nameRemotes), 1)
            for remote in stack.remotes.values():
                self.assertIs(remote.joined, True)
                self.assertIs(remote.allowed, None)
                self.assertIs(remote.alived, None)
        self.assertIs(beta.mutable, None)
        self.assertIs(alpha.mutable, True)
        self.assertIs(self.sameAll(alphaRemote, keep), False)
        self.assertIs(self.sameRoleKeys(alphaRemote, keep), False)
        self.assertEqual(alphaRemote.verfer.keyhex, beta.local.signer.verhex)
        self.assertEqual(alphaRemote.pubber.keyhex, beta.local.priver.pubhex)
        self.assertEqual(alphaRemote.acceptance, raeting.acceptances.accepted)
        self.assertEqual(betaRemote.acceptance, raeting.acceptances.accepted)

        # Keys: New
        beta.local.priver = nacling.Privateer()
        betaRemote.fuid = 0
        betaRemote.sid = 0

        for stack in [alpha, beta]:
            stack.server.close()
            stack.clearAllKeeps()

    def testJoinentVacuousAcceptNewRole(self):
        '''
        Test joinent accept vacuous join with an updated role (D6)
        '''
        console.terse("{0}\n".format(self.testJoinentVacuousAcceptNewRole.__doc__))

        # Status: Accepted (auto accept keys)
        # Mode: Never, Once, Always
        alpha, beta = self.bootstrapJoinedRemotes()
        # Mutable: Yes
        alpha.mutable = True

        # Vacuous: Yes
        betaRemote = beta.addRemote(estating.RemoteEstate(stack=beta,
                                                           fuid=0, # vacuous join
                                                           sid=0, # always 0 for join
                                                           ha=alpha.local.ha))
        # Ephemeral: No Name (the name is known)
        alphaRemote = estating.RemoteEstate(stack=alpha,
                                             fuid=betaRemote.nuid,
                                             ha=beta.local.ha,
                                             name=beta.name,
                                             verkey=beta.local.signer.verhex,
                                             pubkey=beta.local.priver.pubhex)
        alpha.addRemote(alphaRemote)

        oldRole = 'beta'
        newRole = 'beta_new'
        # Name: Old
        # Main: Either
        # Appl: Either
        # RHA:  Either
        # Nuid: Computed
        # Fuid: Either
        # Leid: 0
        # Reid: Either
        # Role: New
        self.assertIs(beta.local.role, oldRole)
        beta.local.role = newRole
        # Keys: Either
        # Sameness: Not sameall
        keep = self.copyData(alphaRemote)

        # Test
        self.join(beta, alpha, deid=betaRemote.nuid)

        # Action: Accept, Dump
        for stack in [alpha, beta]:
            self.assertEqual(len(stack.transactions), 0)
            self.assertEqual(len(stack.remotes), 1)
            self.assertEqual(len(stack.nameRemotes), 1)
            for remote in stack.remotes.values():
                self.assertIs(remote.joined, True)
                self.assertIs(remote.allowed, None)
                self.assertIs(remote.alived, None)
        self.assertIs(beta.mutable, None)
        self.assertIs(alpha.mutable, True)
        self.assertIs(self.sameAll(alphaRemote, keep), False)
        self.assertEqual(alphaRemote.role, newRole)
        self.assertEqual(alphaRemote.acceptance, raeting.acceptances.accepted)
        self.assertEqual(betaRemote.acceptance, raeting.acceptances.accepted)

        for stack in [alpha, beta]:
            stack.server.close()
            stack.clearAllKeeps()