Beispiel #1
0
class TestMutex(TestCase):

    def setUp(self):
        self.mutex_path = '../mutex.txt'
        self.logger = Logger(off=True)
        self.other_ids = [i for i in range(1, 10)]
        self.other_ports = [8100 + i for i in range(1, 10)]

        self.mutex = LamportMutex(self.mutex_path, 0, 8000,
                                  self.other_ids, self.other_ports, self.logger)
        self.mutex.tear_down()  # kill real connection

        # mock API
        mock_api = MockAPI(self.other_ids)
        self.mutex.api = mock_api

    def test__mutex_lock(self):
        # acquire mutex
        self.assertEqual(self.mutex.lock(), True)

        # if mutex was locked resource must be unavailable:
        with open(self.mutex_path, 'w') as f:
            with self.assertRaises(BlockingIOError):
                fcntl.flock(f, fcntl.LOCK_EX | fcntl.LOCK_NB)

        self.mutex.unlock()  # release mutex

    def test__mutex_unlock(self):
        # acquire mutex
        self.assertEqual(self.mutex.lock(), True)
        self.mutex.unlock()  # release mutex

        # resource must be available:
        with open(self.mutex_path, 'w') as f:
            fcntl.flock(f, fcntl.LOCK_EX | fcntl.LOCK_NB)
Beispiel #2
0
class TestAPI(TestCase):

    def setUp(self):
        self.mutex_path = '../mutex.txt'
        self.logger = Logger(off=True)
        self.logger.warn('Ignore logger error during tests!')
        self.other_ids = [i for i in range(1, 10)]
        self.other_ports = [8100 + i for i in range(1, 10)]

        self.mutex = LamportMutex(self.mutex_path, 0, 8000,
                                  self.other_ids, self.other_ports, self.logger)
        self.mutex.tear_down()  # kill real connection

        # mock connection
        self.mock_connection = MockConnection(0, 8000, self.other_ids,
                                              self.other_ports, self.mutex.api.on_response)
        self.mutex.api.connection = self.mock_connection

    def test__API_with_correct_answers(self):
        """
        mock connection works correctly
        """
        self.mock_connection.state = MockConnection.CORRECT_NUM_OF_CONFIRMATIONS

        # mutex must be acquired
        self.assertEqual(self.mutex.lock(), True)  # acquire mutex
        self.mutex.unlock()  # release mutex

    def test__API_with_wrong_answer(self):
        """
        mock connection send less confirmation than required
        """
        self.mock_connection.state = MockConnection.WRONG_NUM_OF_CONFIRMATIONS

        # timeout supposed to be here
        self.assertEqual(self.mutex.lock(), False)  # acquire mutex

    def test__API_without_answer(self):
        """
        actually is the same that previous one
        """
        self.mock_connection.state = MockConnection.NO_CONFIRMATIONS

        # timeout supposed to be here
        self.assertEqual(self.mutex.lock(), False)  # acquire mutex

    def test__API_increment_clock(self):
        """
        test whether clock increment works correctly
        """
        self.mock_connection.state = MockConnection.CORRECT_NUM_OF_CONFIRMATIONS

        # simulate request
        other_time = 10
        self.mock_connection.simulate_request_from_other_process(other_time)  # time bigger than ours
        # add 1 after receiving
        # add one more 1 after sending confirmation
        self.assertEqual(self.mutex.api.clock, other_time + 2)

        # now out time is equal to other_time + 2
        # let's receive 'release' message with older time than ours now:
        self.mock_connection.simulate_release_from_other_process(other_time + 1, 0)
        # our time is supposed to be equal to other_time + 3 now:
        # because we only increment it once when receive 'release' message
        self.assertEqual(self.mutex.api.clock, other_time + 3)

    def test__API_other_locks_earlier(self):
        """
        check that we await until mutex is released before lock it
        """
        # mock connection
        self. mock_connection.state = MockConnection.CORRECT_NUM_OF_CONFIRMATIONS

        # simulate request
        self.mock_connection.simulate_request_from_other_process(-1)  # earlier than our time

        # simulate release after 1.5s
        delay = 2
        thread = Thread(target=self.mock_connection.simulate_release_from_other_process, args=(2, delay))
        thread.start()

        start = time()
        self.mutex.lock()

        # locked only after ~2s => OK
        self.assertGreaterEqual(time(), start + delay)

        self.mutex.unlock()

    def test__API_other_locks_later(self):
        """
        lock mutex if our process is first in the queue
        """
        self.mock_connection.state = MockConnection.CORRECT_NUM_OF_CONFIRMATIONS

        # simulate release after 1.5s
        delay = 1.5
        thread = Thread(target=self.mock_connection.simulate_release_from_other_process, args=(1, delay))
        thread.start()

        start = time()
        self.mutex.lock()

        # simulate request
        self.mock_connection.simulate_request_from_other_process(10)  # later than our time

        # locked before delay passed=> OK
        self.assertLess(time(), start + delay)

        self.mutex.unlock()