TaskCarousel java

Помогите разобраться почему не проходит тест, хотя при запуске кода в Main вручную, вывод валидный.

Каждый раз при вызове метода execute(), карусель должна переключаться на следующую задачу внутри и выполнять ее. Класс каждый раз, когда вызывается метод execute() класса CountDownLatch, это значение уменьшается на единицу, пока не достигнет нуля. После этого метод execute больше не уменьшает значение, и задача считается завершенной.

Исключение теста: org.opentest4j.AssertionFailedError: Assertion fail on step [false, false, 3, 2, 1, 0, true] ==> Expected :3 Actual :4

public class Main {

    public static void main(String[] args) {
        TaskCarousel carousel = new TaskCarousel(4);

        CountDownTask task1 = new CountDownTask(4);
        CountDownTask task2 = new CountDownTask(3);
        CountDownTask task3 = new CountDownTask(2);
        CountDownTask task4 = new CountDownTask(1);

        System.out.println(carousel.addTask(task1));
        System.out.println(carousel.addTask(task2));
        System.out.println(carousel.addTask(task3));
        System.out.println(carousel.addTask(task4));

        System.out.println(task1.getValue());
        System.out.println(task2.getValue());
        System.out.println(task3.getValue());
        System.out.println(task4.getValue());

        System.out.println(carousel.execute()); // 3
        System.out.println(carousel.execute()); // 2
        System.out.println(carousel.execute()); // 1
        System.out.println(carousel.execute()); // 0

//        System.out.println(carousel.execute()); // 2
//        System.out.println(carousel.execute()); // 1
//        System.out.println(carousel.execute()); // 0
//
//        System.out.println(carousel.execute()); // 1
//        System.out.println(carousel.execute()); // 0
//
//        System.out.println(carousel.execute()); // 0

        System.out.println(task1.getValue());
        System.out.println(task2.getValue());
        System.out.println(task3.getValue());
        System.out.println(task4.getValue());

    }
}

public class TaskCarousel {

    private final List<Task> tasks;
    private final int capacity;
    private int counter = -1;

    public TaskCarousel(int capacity) {
        this.capacity = capacity;
        this.tasks = new LinkedList<>();
    }

    public boolean addTask(Task task) {
        int value = 1;
        if(task instanceof CountDownTask) value = ((CountDownTask) task).getValue();
        if(!task.isFinished() && !isFull() && value != 0) {
            return tasks.add(task);
        }
        return false;
    }

    public boolean execute() {
        counter++;
        if (!isEmpty()) {
            if(counter == tasks.size()) counter = 0;
            Task task = tasks.get(counter);

            // вызывается метод CountDownLatch
            task.execute();

            if(task.isFinished()) {
                tasks.remove(task);
                counter--;
            }
            return true;
        }
        return false;
    }

    public boolean isFull() {
        return tasks.size() == capacity;
    }

    public boolean isEmpty() {
        return tasks.isEmpty();
    }

}
public class CountDownTask implements Task{

    private int value;
    public CountDownTask(int value) {
        if(value < 0) this.value = 0;
        else this.value = value;
    }

    public int getValue() {
        return value;
    }


    @Override
    public void execute() {
        if(!isFinished()) value--;
    }

    @Override
    public boolean isFinished() {
        return value == 0;
    }
}

А вот код теста:

@Test
    void testFourTasksWorkflow2() {
        TaskCarousel carousel = new TaskCarousel(4);

        assertTrue(carousel.isEmpty());
        assertFalse(carousel.isFull());
        assertFalse(carousel.execute());

        CountDownTask[] tasks = new CountDownTask[4];
        for (int i = 0; i < 4; i++) {
            tasks[i] = new CountDownTask(4 - i);
            assertTrue(carousel.addTask(tasks[i]));
        }

        Object[][] expectedSteps = new Object[][]{
                {false, true, 4, 3, 2, 1, true},
                {false, false, 3, 2, 1, 0, true},
                {false, false, 2, 1, 0, 0, true},
                {false, false, 1, 0, 0, 0, true},
                {true, false, 0, 0, 0, 0, false}
        };

        for (Object[] expectedStep : expectedSteps) {
            String errMsg = "Assertion fail on step " + Arrays.deepToString(expectedStep);

            assertEquals(expectedStep[0], carousel.isEmpty(), errMsg);
            assertEquals(expectedStep[1], carousel.isFull(), errMsg);
            assertEquals(expectedStep[2], tasks[0].getValue(), errMsg);
            assertEquals(expectedStep[3], tasks[1].getValue(), errMsg);
            assertEquals(expectedStep[4], tasks[2].getValue(), errMsg);
            assertEquals(expectedStep[5], tasks[3].getValue(), errMsg);

            for (final CountDownTask task : tasks) {
                if (!task.isFinished()) {
                    assertEquals(expectedStep[6], carousel.execute(), errMsg);
                }
            }
        }
    }

Ответы (1 шт):

Автор решения: 丹尼尔

Просто добавьте counter в проверку if (!isEmpty()) в методе execute:

public boolean execute() {
    
    if (!isEmpty()) {counter++;
        if(counter == tasks.size()) counter = 0;
        Task task = tasks.get(counter);

        // вызывается метод CountDownLatch
        task.execute();

        if(task.isFinished()) {
            tasks.remove(task);
            counter--;
        }
        return true;
    }
    return false;
}
→ Ссылка