Exemplo n.º 1
0
 def setUp(self):
     self._driver = FakeDriver()
     self._epoch = 1
     self._result = Queue.Queue()
     self._elector = MySQLMasterElector(self._driver, "cluster0",
                                        self._epoch,
                                        lambda x: self._result.put(x),
                                        Amount(1, Time.SECONDS),
                                        Amount(150, Time.MILLISECONDS))
     self._elector.start()
Exemplo n.º 2
0
 def setUp(self):
   self._driver = FakeDriver()
   self._epoch = 1
   self._result = Queue.Queue()
   self._elector = MySQLMasterElector(
       self._driver,
       "cluster0",
       self._epoch,
       lambda x: self._result.put(x),
       Amount(1, Time.SECONDS),
       Amount(150, Time.MILLISECONDS))
   self._elector.start()
Exemplo n.º 3
0
class TestElector(unittest.TestCase):
    def setUp(self):
        self._driver = FakeDriver()
        self._epoch = 1
        self._result = Queue.Queue()
        self._elector = MySQLMasterElector(self._driver, "cluster0",
                                           self._epoch,
                                           lambda x: self._result.put(x),
                                           Amount(1, Time.SECONDS),
                                           Amount(150, Time.MILLISECONDS))
        self._elector.start()

    def tearDown(self):
        if self._elector:  # Terminate the elector if it's not used in the test.
            self._elector.abort()
            self._elector.join()

    def test_single_slave(self):
        slave1 = ("task_id1", "slave_id1")
        self._elector.add_slave(*slave1)
        self._elector.update_position(self._epoch, slave1[0], 1)

        assert self._result.get(True, 1) == slave1[0]

    def test_two_slaves(self):
        slave1 = ("task_id1", "slave_id1")
        slave2 = ("task_id2", "slave_id2")
        self._elector.add_slave(*slave1)
        self._elector.add_slave(*slave2)

        self._elector.update_position(self._epoch, slave1[0], 1)
        self._elector.update_position(self._epoch, slave2[0], 2)

        assert self._result.get(True, 1) == slave2[0]

    def test_two_slaves_complex_position(self):
        slave1 = ("task_id1", "slave_id1")
        slave2 = ("task_id2", "slave_id2")
        self._elector.add_slave(*slave1)
        self._elector.add_slave(*slave2)

        # The positions are sequences of numeric strings.
        self._elector.update_position(self._epoch, slave1[0], ["1", "2"])
        self._elector.update_position(self._epoch, slave2[0], ["2", "1"])

        assert self._result.get(True, 1) == slave2[0]

    def test_delayed_update(self):
        slave1 = ("task_id1", "slave_id1")
        slave2 = ("task_id2", "slave_id2")
        self._elector.add_slave(*slave1)
        self._elector.add_slave(*slave2)
        self._elector.update_position(self._epoch, slave2[0], 2)

        # Force an election (after timing out) and test that slave2 is elected because it's the only
        # slave that responded.
        self._elector._elect(timedout=True)
        assert self._result.get(True, 1) == slave2[0]

    def test_position_for_invalid_slave(self):
        slave1 = ("task_id1", "slave_id1")
        slave2 = ("task_id2", "slave_id2")
        self._elector.update_position(self._epoch, slave1[0],
                                      100)  # This update is ignored.
        self._elector.add_slave(*slave1)
        self._elector.add_slave(*slave2)
        self._elector.update_position(self._epoch, slave2[0], 1)

        # Timeout is 1 second. Testing the organic 'timeout' of the thread.
        assert self._result.get(True, 2) == slave2[0]

    def test_position_for_previous_epoch(self):
        slave1 = ("task_id1", "slave_id1")
        slave2 = ("task_id2", "slave_id2")
        self._elector.add_slave(*slave1)
        self._elector.add_slave(*slave2)

        self._elector.update_position(self._epoch - 1, slave1[0],
                                      100)  # Update from a previous epoch.
        self._elector.update_position(self._epoch, slave2[0], 1)

        # Induce an election after it timed out.
        self._elector._elect(timedout=True)
        assert self._result.get(True, 1) == slave2[0]

    def test_remove_slave_after_election(self):
        slave1 = ("task_id1", "slave_id1")
        slave2 = ("task_id2", "slave_id2")
        self._elector.add_slave(*slave1)
        self._elector.add_slave(*slave2)

        self._elector.update_position(self._epoch, slave1[0], 1)
        self._elector.update_position(self._epoch, slave2[0], 2)

        assert self._result.get(True, 1) == slave2[0]

        # At this point a master is already elected. Slave removal is ignored.
        self._elector.remove_slave(slave2[0])

        assert len(self._elector._positions) == 2

    def test_remove_slave_during_election(self):
        slave1 = ("task_id1", "slave_id1")
        slave2 = ("task_id2", "slave_id2")
        self._elector.add_slave(*slave1)
        self._elector.add_slave(*slave2)

        self._elector.update_position(self._epoch, slave2[0], 2)

        # Election still ongoing. Removing slave2 allows slave1 to be elected.
        self._elector.remove_slave(slave2[0])
        self._elector.update_position(self._epoch, slave1[0], 1)

        self._elector._elect()
        assert self._result.get(True, 1) == slave1[0]
Exemplo n.º 4
0
class TestElector(unittest.TestCase):
  def setUp(self):
    self._driver = FakeDriver()
    self._epoch = 1
    self._result = Queue.Queue()
    self._elector = MySQLMasterElector(
        self._driver,
        "cluster0",
        self._epoch,
        lambda x: self._result.put(x),
        Amount(1, Time.SECONDS),
        Amount(150, Time.MILLISECONDS))
    self._elector.start()

  def tearDown(self):
    if self._elector:  # Terminate the elector if it's not used in the test.
      self._elector.abort()
      self._elector.join()

  def test_single_slave(self):
    slave1 = ("task_id1", "slave_id1")
    self._elector.add_slave(*slave1)
    self._elector.update_position(self._epoch, slave1[0], 1)

    assert self._result.get(True, 1) == slave1[0]

  def test_two_slaves(self):
    slave1 = ("task_id1", "slave_id1")
    slave2 = ("task_id2", "slave_id2")
    self._elector.add_slave(*slave1)
    self._elector.add_slave(*slave2)

    self._elector.update_position(self._epoch, slave1[0], 1)
    self._elector.update_position(self._epoch, slave2[0], 2)

    assert self._result.get(True, 1) == slave2[0]

  def test_two_slaves_complex_position(self):
    slave1 = ("task_id1", "slave_id1")
    slave2 = ("task_id2", "slave_id2")
    self._elector.add_slave(*slave1)
    self._elector.add_slave(*slave2)

    # The positions are sequences of numeric strings.
    self._elector.update_position(self._epoch, slave1[0], ["1", "2"])
    self._elector.update_position(self._epoch, slave2[0], ["2", "1"])

    assert self._result.get(True, 1) == slave2[0]

  def test_delayed_update(self):
    slave1 = ("task_id1", "slave_id1")
    slave2 = ("task_id2", "slave_id2")
    self._elector.add_slave(*slave1)
    self._elector.add_slave(*slave2)
    self._elector.update_position(self._epoch, slave2[0], 2)

    # Force an election (after timing out) and test that slave2 is elected because it's the only
    # slave that responded.
    self._elector._elect(timedout=True)
    assert self._result.get(True, 1) == slave2[0]

  def test_position_for_invalid_slave(self):
    slave1 = ("task_id1", "slave_id1")
    slave2 = ("task_id2", "slave_id2")
    self._elector.update_position(self._epoch, slave1[0], 100)  # This update is ignored.
    self._elector.add_slave(*slave1)
    self._elector.add_slave(*slave2)
    self._elector.update_position(self._epoch, slave2[0], 1)

    # Timeout is 1 second. Testing the organic 'timeout' of the thread.
    assert self._result.get(True, 2) == slave2[0]

  def test_position_for_previous_epoch(self):
    slave1 = ("task_id1", "slave_id1")
    slave2 = ("task_id2", "slave_id2")
    self._elector.add_slave(*slave1)
    self._elector.add_slave(*slave2)

    self._elector.update_position(self._epoch - 1, slave1[0], 100)  # Update from a previous epoch.
    self._elector.update_position(self._epoch, slave2[0], 1)

    # Induce an election after it timed out.
    self._elector._elect(timedout=True)
    assert self._result.get(True, 1) == slave2[0]

  def test_remove_slave_after_election(self):
    slave1 = ("task_id1", "slave_id1")
    slave2 = ("task_id2", "slave_id2")
    self._elector.add_slave(*slave1)
    self._elector.add_slave(*slave2)

    self._elector.update_position(self._epoch, slave1[0], 1)
    self._elector.update_position(self._epoch, slave2[0], 2)

    assert self._result.get(True, 1) == slave2[0]

    # At this point a master is already elected. Slave removal is ignored.
    self._elector.remove_slave(slave2[0])

    assert len(self._elector._positions) == 2

  def test_remove_slave_during_election(self):
    slave1 = ("task_id1", "slave_id1")
    slave2 = ("task_id2", "slave_id2")
    self._elector.add_slave(*slave1)
    self._elector.add_slave(*slave2)

    self._elector.update_position(self._epoch, slave2[0], 2)

    # Election still ongoing. Removing slave2 allows slave1 to be elected.
    self._elector.remove_slave(slave2[0])
    self._elector.update_position(self._epoch, slave1[0], 1)

    self._elector._elect()
    assert self._result.get(True, 1) == slave1[0]