class TestDynamoDBCounterTestCase(unittest.TestCase):

    """
    Create table 'test_counter' and 'test_counter_shard_index' before you run this test
    """

    def setUp(self):
        self.settings = DB_SETTINGS['dynamodb']
        self.db = DynamoDB(self.settings)
        self.db.create_table('test_counter', 5, 5)
        self.db.create_table('test_counter_shard_index', 5, 5)
        self.db.create_table('test_counter_%Y%m%d', 5, 5)
        self.db.create_table('test_counter_%Y%m%d', 5, 5,
                             transform_time=datetime.datetime.utcnow() - datetime.timedelta(1))

    def test_incr(self):
        table_name = 'test_counter'
        key = str(uuid4())
        self.db.incr(table_name, key)
        self.assertEqual(self.db.get_count(table_name, key), 1)
        self.db.incr(table_name, key, 2)
        self.assertEqual(self.db.get_count(table_name, key), 3)
        self.db.incr(table_name, key, -1)
        self.assertEqual(self.db.get_count(table_name, key), 2)
        self.db.delete_counter(table_name, key)

    def test_multithread_counter(self):
        table_name = 'test_counter'
        count = 20
        key = str(uuid4())

        def incr_counter():
            self.db.incr(table_name, key)

        start = self.db.get_count(table_name, key) or 0
        threadlist = []
        for _ in xrange(0, count):
            thread = Thread(target=incr_counter)
            thread.start()
            threadlist.append(thread)
            time.sleep(0.01)

        for t in threadlist:
            t.join(60)

        final = self.db.get_count(table_name, key)
        self.assertEqual(start + count, final)
        self.db.delete_counter(table_name, key)

    def test_shard_counter(self):
        table_name = 'test_counter'
        shard_count = 100
        key = str(uuid4())
        self.db.incr(table_name, key, 1, shard_count=shard_count)
        self.assertEqual(self.db.get_count(table_name, key, sharded=True), 1)
        self.db.incr(table_name, key, 2, shard_count=shard_count)
        self.assertEqual(self.db.get_count(table_name, key, sharded=True), 3)
        self.db.delete_counter(table_name, key)

    def test_multithread_shard_counter(self):
        table_name = 'test_counter'
        count = 50
        shard_count = 60
        key = str(uuid4())

        def incr_counter():
            self.db.incr(table_name, key, shard_count=shard_count)

        start = self.db.get_count(table_name, key) or 0
        threadlist = []
        for _ in xrange(0, count):
            thread = Thread(target=incr_counter)
            thread.start()
            threadlist.append(thread)
            time.sleep(0.01)

        for t in threadlist:
            t.join(60)

        final = self.db.get_count(table_name, key, sharded=True)
        self.assertEqual(start + count, final)
        self.db.delete_counter(table_name, key)