Создание тестов для класса с использованием семафоров - PullRequest
0 голосов
/ 16 декабря 2018

У меня есть класс, задачи которого таковы: -ввести в систему только x пользователей, -обработать только y запросов от данного пользователя, -обработать только z запросов от всех пользователей вместе, каждый запрос может подождать, пока будет обработано указанное время

import lombok.Getter;
import lombok.Setter;

import java.util.Date;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.Semaphore;
import java.util.concurrent.TimeUnit;

@Setter
@Getter
public class RequestsLimiter {

    private int maxNumberOfRequestsFromSingleUser;
    private long waitTimeInMillis;
    private Semaphore usersLimiter;
    private Semaphore requestsLimiter;
    private ConcurrentHashMap<String, Semaphore> requestsPerUserLimiter = new ConcurrentHashMap<>();


    public RequestsLimiter(int maxNumberOfUsers, int maxNumberOFRequestsPerUser, int maxNumberOfRequests, long waitTimeInMillis) {
        usersLimiter = new Semaphore(maxNumberOfUsers);
        this.maxNumberOfRequestsFromSingleUser = maxNumberOFRequestsPerUser;
        requestsLimiter = new Semaphore(maxNumberOfRequests);
        this.waitTimeInMillis = waitTimeInMillis;
    }


    public boolean work(String user) throws InterruptedException {
        long startTime = new Date().getTime();
        if (tryLogin(user) && tryPassRequestFromUser(user, startTime) && trySendRequest(user, startTime)) {
            TimeUnit.MILLISECONDS.sleep((int) (Math.random() * 2000));
            return true;
        } else {
            return false;
        }
    }

    private boolean trySendRequest(String user, long startTime) throws InterruptedException {
        try {
            return checkIfRequestCanBeSend(startTime);
        } finally {
            requestsLimiter.release();
        }
    }

    private boolean tryPassRequestFromUser(String user, long startTime) throws InterruptedException {
        try {
            return checkIfUserCanGenerateRequest(user, startTime);
        } finally {
            releaseSlotForGivenUser(user);
        }
    }

    private boolean tryLogin(String user) throws InterruptedException {
        if (requestsPerUserLimiter.containsKey(user)) {
            return true;
        } else {
            return usersLimiter.tryAcquire(waitTimeInMillis, TimeUnit.MILLISECONDS);
        }
    }

    private boolean checkIfUserCanGenerateRequest(String user, long startTime) throws InterruptedException {
        if (!requestsPerUserLimiter.containsKey(user))
            requestsPerUserLimiter.put(user, new Semaphore(maxNumberOfRequestsFromSingleUser));
        return requestsPerUserLimiter.get(user).tryAcquire(waitTimeInMillis - (new Date().getTime() - startTime), TimeUnit.MILLISECONDS);
    }

    private boolean checkIfRequestCanBeSend(long startTime) throws InterruptedException {
        return requestsLimiter.tryAcquire(waitTimeInMillis - (new Date().getTime() - startTime), TimeUnit.MILLISECONDS);
    }


    private void releaseSlotForGivenUser(String user) {
        requestsPerUserLimiter.get(user).release();
        if (requestsPerUserLimiter.get(user).availablePermits() == maxNumberOfRequestsFromSingleUser) {
            requestsPerUserLimiter.remove(user);
            usersLimiter.release();
        }
    }

}

Могу ли я попросить вас дать несколько советов о том, как правильно его проверить?Мне было очень трудно понять это

...