All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.hazelcast.simulator.tests.concurrent.lock.LockTest Maven / Gradle / Ivy

/*
 * Copyright (c) 2008-2016, Hazelcast, Inc. All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.hazelcast.simulator.tests.concurrent.lock;

import com.hazelcast.core.IAtomicLong;
import com.hazelcast.core.ILock;
import com.hazelcast.simulator.test.AbstractTest;
import com.hazelcast.simulator.test.BaseThreadState;
import com.hazelcast.simulator.test.TestException;
import com.hazelcast.simulator.test.annotations.Setup;
import com.hazelcast.simulator.test.annotations.Teardown;
import com.hazelcast.simulator.test.annotations.TimeStep;
import com.hazelcast.simulator.test.annotations.Verify;
import com.hazelcast.simulator.test.annotations.Warmup;

import static java.lang.String.format;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;

public class LockTest extends AbstractTest {

    // properties
    public int lockCount = 500;
    public int initialAmount = 1000;
    public int amount = 50;

    private IAtomicLong lockCounter;

    @Setup
    public void setup() {
        lockCounter = targetInstance.getAtomicLong(name + ":LockCounter");
    }

    @Warmup(global = true)
    public void warmup() {
        for (int i = 0; i < lockCount; i++) {
            long key = lockCounter.getAndIncrement();
            targetInstance.getLock(getLockId(key));
            IAtomicLong account = targetInstance.getAtomicLong(getAccountId(key));
            account.set(initialAmount);
        }
    }

    @TimeStep
    public void timeStep(ThreadState state) {
        long key1 = state.getRandomAccountKey();
        long key2 = state.getRandomAccountKey();
        int randomAmount = state.randomInt(amount);

        ILock lock1 = targetInstance.getLock(getLockId(key1));
        ILock lock2 = targetInstance.getLock(getLockId(key2));
        IAtomicLong account1 = targetInstance.getAtomicLong(getAccountId(key1));
        IAtomicLong account2 = targetInstance.getAtomicLong(getAccountId(key2));

        if (!lock1.tryLock()) {
            return;
        }
        try {
            if (!lock2.tryLock()) {
                return;
            }
            try {
                if (account1.get() < 0 || account2.get() < 0) {
                    throw new TestException("Amount on account can't be smaller than 0");
                }
                if (account1.get() < randomAmount) {
                    return;
                }
                account1.set(account1.get() - randomAmount);
                account2.set(account2.get() + randomAmount);
            } finally {
                lock2.unlock();
            }
        } finally {
            lock1.unlock();
        }
    }

    public class ThreadState extends BaseThreadState {

        private long getRandomAccountKey() {
            long key = randomLong() % lockCounter.get();
            return (key < 0) ? -key : key;
        }
    }

    private String getLockId(long key) {
        return name + '-' + key;
    }

    private String getAccountId(long key) {
        return name + '-' + key;
    }

    @Verify
    public void verify() {
        long actual = 0;
        for (long i = 0; i < lockCounter.get(); i++) {
            ILock lock = targetInstance.getLock(getLockId(i));
            assertFalse("Lock should be unlocked", lock.isLocked());

            long accountAmount = targetInstance.getAtomicLong(getAccountId(i)).get();
            assertTrue("Amount on account can't be smaller than 0", accountAmount >= 0);
            actual += accountAmount;
        }

        long expected = initialAmount * lockCounter.get();
        assertEquals(format("%s: Money was lost or created (%d)", name, expected - actual), expected, actual);
    }

    @Teardown
    public void teardown() {
        lockCounter.destroy();

        for (long i = 0; i < lockCounter.get(); i++) {
            targetInstance.getLock(getLockId(i)).destroy();
            targetInstance.getAtomicLong(getAccountId(i)).destroy();
        }
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy