/*
* Copyright 2016 Red Hat, Inc. and/or its affiliates.
*
* 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 org.optaplanner.core.impl.partitionedsearch.queue;
import java.util.Iterator;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import org.junit.After;
import org.junit.Test;
import org.optaplanner.core.impl.partitionedsearch.scope.PartitionChangeMove;
import org.optaplanner.core.impl.testdata.domain.TestdataSolution;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import static org.junit.Assert.*;
public class PartitionQueueTest {
private static final Logger logger = LoggerFactory.getLogger(PartitionQueueTest.class);
private final ExecutorService executorService = Executors.newFixedThreadPool(2);
@After
public void tearDown() throws InterruptedException {
executorService.shutdownNow();
if (!executorService.awaitTermination(1, TimeUnit.MILLISECONDS)) {
logger.warn("Thread pool didn't terminate within the timeout.");
}
}
@Test
public void addMove() throws ExecutionException, InterruptedException {
PartitionQueue<TestdataSolution> partitionQueue = new PartitionQueue<>(3);
Iterator<PartitionChangeMove<TestdataSolution>> it = partitionQueue.iterator();
PartitionChangeMove<TestdataSolution> moveA1 = buildMove();
executorService.submit(() -> partitionQueue.addMove(0, moveA1)).get();
assertSame(moveA1, it.next());
PartitionChangeMove<TestdataSolution> moveB1 = buildMove();
executorService.submit(() -> partitionQueue.addMove(1, moveB1)).get(); // Skipped
PartitionChangeMove<TestdataSolution> moveB2 = buildMove();
executorService.submit(() -> partitionQueue.addMove(1, moveB2)).get(); // Skipped
PartitionChangeMove<TestdataSolution> moveB3 = buildMove();
executorService.submit(() -> partitionQueue.addMove(1, moveB3)).get();
assertSame(moveB3, it.next());
PartitionChangeMove<TestdataSolution> moveA2 = buildMove();
executorService.submit(() -> partitionQueue.addMove(0, moveA2)).get(); // Skipped
PartitionChangeMove<TestdataSolution> moveA3 = buildMove();
executorService.submit(() -> partitionQueue.addMove(0, moveA3)).get();
PartitionChangeMove<TestdataSolution> moveB4 = buildMove();
executorService.submit(() -> partitionQueue.addMove(1, moveB4)).get();
assertSame(moveA3, it.next());
assertSame(moveB4, it.next());
PartitionChangeMove<TestdataSolution> moveB5 = buildMove();
executorService.submit(() -> partitionQueue.addMove(1, moveB5)).get(); // Skipped
PartitionChangeMove<TestdataSolution> moveA4 = buildMove();
executorService.submit(() -> partitionQueue.addMove(0, moveA4)).get(); // Skipped
PartitionChangeMove<TestdataSolution> moveA5 = buildMove();
executorService.submit(() -> partitionQueue.addMove(0, moveA5)).get(); // Skipped
PartitionChangeMove<TestdataSolution> moveB6 = buildMove();
executorService.submit(() -> partitionQueue.addMove(1, moveB6)).get();
PartitionChangeMove<TestdataSolution> moveC1 = buildMove();
executorService.submit(() -> partitionQueue.addMove(2, moveC1)).get();
PartitionChangeMove<TestdataSolution> moveA6 = buildMove();
executorService.submit(() -> partitionQueue.addMove(0, moveA6)).get();
assertSame(moveB6, it.next());
assertSame(moveA6, it.next());
assertSame(moveC1, it.next());
executorService.submit(() -> partitionQueue.addFinish(0)).get();
PartitionChangeMove<TestdataSolution> moveC2 = buildMove();
executorService.submit(() -> partitionQueue.addMove(2, moveC2)).get();
executorService.submit(() -> partitionQueue.addFinish(1)).get();
assertSame(moveC2, it.next());
executorService.submit(() -> partitionQueue.addFinish(2)).get();
assertSame(false, it.hasNext());
}
@Test
public void addFinishWithNonEmptyQueue() throws ExecutionException, InterruptedException {
PartitionQueue<TestdataSolution> partitionQueue = new PartitionQueue<>(3);
Iterator<PartitionChangeMove<TestdataSolution>> it = partitionQueue.iterator();
PartitionChangeMove<TestdataSolution> moveA1 = buildMove();
executorService.submit(() -> partitionQueue.addMove(0, moveA1)).get();
executorService.submit(() -> partitionQueue.addFinish(0)).get();
PartitionChangeMove<TestdataSolution> moveC1 = buildMove();
executorService.submit(() -> partitionQueue.addMove(2, moveC1)).get();
PartitionChangeMove<TestdataSolution> moveC2 = buildMove();
executorService.submit(() -> partitionQueue.addMove(2, moveC2)).get();
executorService.submit(() -> partitionQueue.addFinish(2)).get();
executorService.submit(() -> partitionQueue.addFinish(1)).get();
assertSame(true, it.hasNext());
assertSame(moveA1, it.next());
assertSame(true, it.hasNext());
assertSame(moveC2, it.next());
assertSame(false, it.hasNext());
}
@Test()
public void addExceptionWithNonEmptyQueue() throws ExecutionException, InterruptedException {
PartitionQueue<TestdataSolution> partitionQueue = new PartitionQueue<>(3);
Iterator<PartitionChangeMove<TestdataSolution>> it = partitionQueue.iterator();
PartitionChangeMove<TestdataSolution> moveA1 = buildMove();
executorService.submit(() -> partitionQueue.addMove(0, moveA1)).get();
executorService.submit(() -> partitionQueue.addFinish(0)).get();
PartitionChangeMove<TestdataSolution> moveC1 = buildMove();
executorService.submit(() -> partitionQueue.addMove(2, moveC1)).get();
PartitionChangeMove<TestdataSolution> moveC2 = buildMove();
executorService.submit(() -> partitionQueue.addMove(2, moveC2)).get();
IllegalArgumentException exception = new IllegalArgumentException();
executorService.submit(() -> partitionQueue.addExceptionThrown(1, exception)).get();
PartitionChangeMove<TestdataSolution> moveB1 = buildMove();
executorService.submit(() -> partitionQueue.addMove(1, moveB1)).get();
executorService.submit(() -> partitionQueue.addFinish(1)).get();
assertSame(true, it.hasNext());
assertSame(moveA1, it.next());
assertSame(true, it.hasNext());
assertSame(moveC2, it.next());
try {
it.hasNext();
fail("There was no RuntimeException thrown.");
} catch (RuntimeException e) {
assertSame(exception, e.getCause());
}
}
public PartitionChangeMove<TestdataSolution> buildMove() {
return new PartitionChangeMove<>(null);
}
}