예제 #1
0
    def test_insert_balance(self):

        storage = MemoryBalanceStorage()

        insert = {str(a): a for a in range(10000)}
        storage.update(insert=insert, height=66)

        for a in range(10000):
            self.assertEqual(storage.get(str(a)), a)

        self.assertEqual(storage.height, 66)
예제 #2
0
    def test_delete_balance(self):
        storage = MemoryBalanceStorage()

        insert = {str(a): a for a in range(10000)}
        storage.update(insert=insert)

        for a in range(10000):
            self.assertEqual(storage.get(str(a)), a)

        delete = set([str(a) for a in range(5000)])
        storage.update(delete=delete, height=44)
        for a in range(5000):
            with self.assertRaises(KeyError):
                storage.get(str(a))

        self.assertEqual(storage.height, 44)
예제 #3
0
    def test_get_balance(self):

        storage = MemoryBalanceStorage()
        storage.update(insert={"addr1": 1, "addr2": 2}, height=33)

        self.assertEqual(storage.height, 33)
        self.assertEqual(storage.get("addr1", 1), 1)
        self.assertEqual(storage.get("addr2", 2), 2)

        # Missing address raise exception
        with self.assertRaises(KeyError):
            storage.get("addr3")

        # Check default keyword
        self.assertEqual(storage.get("addr3", 77), 77)
        self.assertEqual(storage.get("addr1", 77), 1)
        self.assertEqual(storage.get("addr2", 77), 2)
예제 #4
0
    def test_update_balance(self):
        storage = MemoryBalanceStorage()

        insert = {str(a): a for a in range(10000)}
        storage.update(insert=insert)

        for a in range(10000):
            self.assertEqual(storage.get(str(a)), a)

        update = {str(a): 10 for a in range(5000)}
        storage.update(update=update, height=88)

        for a in range(5000):
            self.assertEqual(storage.get(str(a)), 10)

        self.assertEqual(storage.height, 88)
예제 #5
0
    def test_get_bulk_balance(self):
        """ """
        storage = MemoryBalanceStorage()

        insert = {
            "addr1": 1,
            "addr2": 2,
            "addr3": 3,
        }

        storage.update(insert=insert)
        result = dict(storage.get_bulk(set(["addr1", "addr2", "addr4"])))
        self.assertEqual(len(result), 2)
        self.assertTrue('addr1' in result)
        self.assertTrue('addr2' in result)

        result = dict(storage.get_bulk({"addr4": 55}))
        self.assertEqual(len(result), 0)
예제 #6
0
 def setUp(self):
     self.balance_storage = BalanceProxyCache(MemoryBalanceStorage(), 10000)
예제 #7
0
 def setUp(self):
     self.storage = MemoryBalanceStorage()
예제 #8
0
class TestBalanceProxyCache(TestCase):
    def setUp(self):
        self.storage = MemoryBalanceStorage()

    def test_get(self):
        """Test balance is cached"""
        balance_proxy = BalanceProxyCache(self.storage, 1000)
        for a in range(1000):
            balance_proxy.update(str(a), a)

        for a in range(1000):
            self.assertEqual(balance_proxy.get(str(a)), a)

        for a in range(1000, 2000):
            self.assertEqual(balance_proxy.get(str(a)), 0)

        self.assertEqual(len(balance_proxy), 999)  # 0 Update Discarded
        balance_proxy.commit(12)
        self.assertEqual(len(balance_proxy), 0)

        # Update all address and try again
        for a in range(1000):
            balance_proxy.update(str(a), 44)

        for a in range(1000):
            self.assertEqual(balance_proxy.get(str(a)), a + 44)

        self.assertEqual(len(balance_proxy), 1000)
        balance_proxy.commit(14)
        self.assertEqual(len(balance_proxy), 0)

        for a in range(1000):
            self.assertEqual(balance_proxy.get(str(a)), a + 44)

        for a in range(1000, 2000):
            self.assertEqual(balance_proxy.get(str(a)), 0)

    def test_storate_insert_update_delete(self):
        """Test how BalanceProxyCache translate updates into
        insert, update and delete operations"""
        self.storage.update = MagicMock()
        balance_proxy = BalanceProxyCache(self.storage, 1000)

        # Insert
        balance_proxy.update('address_one', 1)  # Insert
        balance_proxy.update('address_two', 2)  # Insert
        self.storage.update.assert_not_called()
        balance_proxy.commit(33)

        args = self.storage.update.call_args[1]
        self.assertEqual(len(args['delete']), 0)
        self.assertEqual(len(args['update']), 0)
        self.assertEqual(len(args['insert']), 2)
        self.assertEqual(args['insert']['address_one'], 1)
        self.assertEqual(args['insert']['address_two'], 2)

        # Update + Insert
        self.storage.update.reset_mock()
        balance_proxy.update('address_two', 2)  # Update
        balance_proxy.update('address_three', 3)  # Insert
        balance_proxy.commit(44)

        args = self.storage.update.call_args[1]
        self.assertEqual(len(args['delete']), 0)
        self.assertEqual(len(args['update']), 1)
        self.assertEqual(len(args['insert']), 1)
        self.assertEqual(args['insert']['address_three'], 3)
        self.assertEqual(args['update']['address_two'], 4)

        # Update + Insert + Delete
        self.storage.update.reset_mock()
        balance_proxy.update('address_four', 4)  # Insert
        balance_proxy.update('address_three', 1)  # Update
        balance_proxy.update('address_one', -1)  # Delete
        balance_proxy.commit(55)

        args = self.storage.update.call_args[1]
        self.assertEqual(len(args['insert']), 1)
        self.assertEqual(len(args['update']), 1)
        self.assertEqual(len(args['delete']), 1)

        self.assertEqual(args['insert']['address_four'], 4)
        self.assertEqual(args['update']['address_three'], 4)
        self.assertTrue('address_one' in args['delete'])
        self.assertEqual(args['height'], 55)

    def test_cache_trim(self):
        """Test cache is trimed when it reaches max_size"""
        self.storage.get = MagicMock(return_value=0)
        balance_proxy = BalanceProxyCache(self.storage, 1000)

        # Completely fill cache
        for a in range(1000):
            balance_proxy.update(str(a), a + 1)

        balance_proxy.commit(10)

        # When the address is cached storage.get() isn't called:
        self.storage.get.reset_mock()
        for a in range(1000):
            self.assertEqual(balance_proxy.get(str(a)), a + 1)

        self.storage.get.assert_not_called()

        # Adding another address will cause the proxy to discard the oldest one
        self.assertEqual(len(balance_proxy._cache), 1000)
        balance_proxy.update('new_address', 44)
        balance_proxy.commit(444)

        # This will call storage.get because atleast one addr isn't cached
        self.storage.get.reset_mock()
        for a in range(1000):
            # WARNING: returned value is mangled because mock get allways
            # return 0
            balance_proxy.get(str(a))
        self.assertGreater(self.storage.get.call_count, 0)

    def test_commit(self):
        """Test data is stored correctly"""
        balance_proxy = BalanceProxyCache(self.storage, 50000)

        for a in range(2000):
            balance_proxy.update(str(a), a)

        balance_proxy.commit(1000)

        for a in range(1, 2000):
            self.assertEqual(self.storage.get(str(a)), a)

        # 0 updates are not stored
        with self.assertRaises(KeyError):
            self.storage.get('0')
        self.assertEqual(balance_proxy.get('0'), 0)

    @staticmethod
    def concurrent_get(balance_proxy, error_event):
        """ """
        time.sleep(0.1)  # Delay to allow commit to start
        for a in range(50000):
            if balance_proxy.get(str(a)) != a + 1:
                error_event.set()

    def test_concurrent_commit(self):
        """Test concurrent get() and commit() calls"""
        self.db_engine, self.db_session = create_memory_db()
        db_storage = SQLBalanceStorage(self.db_session)
        balance_proxy = BalanceProxyCache(db_storage, 50000)

        # Test get during a commit
        ###########################
        for a in range(100000):
            balance_proxy.update(str(a), a + 1)

        error_event = threading.Event()
        get_thread = threading.Thread(target=self.concurrent_get,
                                      args=(balance_proxy, error_event),
                                      daemon=True)
        get_thread.start()
        balance_proxy.commit(12)

        # Check no error was detected
        get_thread.join()
        self.assertFalse(error_event.is_set())

        # Cleanup database
        self.db_session.close()
        self.db_engine.dispose()

    def test_concurrent_update(self):
        """Test concurrent get() and update() calls"""
        self.db_engine, self.db_session = create_memory_db()
        db_storage = SQLBalanceStorage(self.db_session)
        balance_proxy = BalanceProxyCache(db_storage, 50000)

        # Test get during a commit
        ###########################
        for a in range(100000):
            balance_proxy.update(str(a), a + 1)

        balance_proxy.commit(12)

        error_event = threading.Event()
        get_thread = threading.Thread(target=self.concurrent_get,
                                      args=(balance_proxy, error_event),
                                      daemon=True)

        get_thread.start()

        for a in range(100000, 300000):
            balance_proxy.update(str(a), a)

        # Check no error was detected
        get_thread.join()
        self.assertFalse(error_event.is_set())

        # Verify  updated address
        for a in range(100000, 150000):
            self.assertEqual(balance_proxy.get(str(a)), a)

        # Cleanup database
        self.db_session.close()
        self.db_engine.dispose()
예제 #9
0
    def test_mix_ops(self):
        """Test mixin insert/update/delete operations"""
        storage = MemoryBalanceStorage()

        insert = {str(a): a for a in range(5000)}
        storage.update(insert=insert, height=77)

        for a in range(5000):
            self.assertEqual(storage.get(str(a)), a)

        # Mixed op
        insert = {str(a): a for a in range(10000, 15000)}
        update = {str(a): 66 for a in range(1000)}
        delete = [str(a) for a in range(1000, 3000)]

        storage.update(insert=insert, update=update, delete=delete, height=99)

        for a in range(10000, 15000):
            self.assertEqual(storage.get(str(a)), a)

        for a in range(3000, 5000):
            self.assertEqual(storage.get(str(a)), a)

        for a in range(1000):
            self.assertEqual(storage.get(str(a)), 66)

        for a in range(1000, 3000):
            with self.assertRaises(KeyError):
                storage.get(str(a))

        self.assertEqual(storage.height, 99)
예제 #10
0
 def test_init(self):
     storage = MemoryBalanceStorage()
     self.assertEqual(storage.height, -1)