Tried to fix test, but LeastPicker and SequentialFilling do no passing

This commit is contained in:
Andrey Terentev 2024-03-16 15:43:47 +07:00 committed by Andrey Terentev
parent 8b655bfb4b
commit e38410a1ea
10 changed files with 46 additions and 36 deletions

View File

@ -35,9 +35,9 @@ public class NodeContainer {
private @NotNull RoomPicker initPicker() { private @NotNull RoomPicker initPicker() {
return switch (node.getPickingMethod()) { return switch (node.getPickingMethod()) {
case SEQUENTIAL_FILLING -> new SequentialFillingPicker(); case SEQUENTIAL_FILLING -> new SequentialFillingPicker(this);
case ROUND_ROBIN -> new RoundRobinPicker(); case ROUND_ROBIN -> new RoundRobinPicker(this);
case LEAST_PICKED -> new LeastPickedPicker(); case LEAST_PICKED -> new LeastPickedPicker(this);
}; };
} }
@ -93,10 +93,12 @@ public class NodeContainer {
} }
public @NotNull Room pick(@NotNull Set<User> users) { public @NotNull Room pick(@NotNull Set<User> users) {
synchronized (picker) {
var room = picker.pick(users); var room = picker.pick(users);
transactionListener.accept(new UserTransaction(room.getRoom(), users)); transactionListener.accept(new UserTransaction(room.getRoom(), users));
return room.getRoom(); return room.getRoom();
} }
}
public @NotNull RoomPicker getPicker() { public @NotNull RoomPicker getPicker() {
return picker; return picker;

View File

@ -90,6 +90,7 @@ public class RoomContainer {
} }
public boolean canBePicked(int users) { public boolean canBePicked(int users) {
usersLock.readLock().lock();
try { try {
return !room.isLocked() && canAdd0(users); return !room.isLocked() && canAdd0(users);
} finally { } finally {

View File

@ -1,16 +1,21 @@
package ru.dragonestia.picker.repository.impl.picker; package ru.dragonestia.picker.repository.impl.picker;
import lombok.RequiredArgsConstructor;
import ru.dragonestia.picker.api.exception.NoRoomsAvailableException;
import ru.dragonestia.picker.api.model.node.PickingMethod; import ru.dragonestia.picker.api.model.node.PickingMethod;
import ru.dragonestia.picker.model.Room; import ru.dragonestia.picker.model.Room;
import ru.dragonestia.picker.model.User; import ru.dragonestia.picker.model.User;
import ru.dragonestia.picker.repository.UserRepository; import ru.dragonestia.picker.repository.UserRepository;
import ru.dragonestia.picker.repository.impl.collection.DynamicSortedMap; import ru.dragonestia.picker.repository.impl.collection.DynamicSortedMap;
import ru.dragonestia.picker.repository.impl.container.NodeContainer;
import ru.dragonestia.picker.repository.impl.container.RoomContainer; import ru.dragonestia.picker.repository.impl.container.RoomContainer;
import java.util.Collection; import java.util.Collection;
@RequiredArgsConstructor
public class LeastPickedPicker implements RoomPicker { public class LeastPickedPicker implements RoomPicker {
private final NodeContainer container;
private final DynamicSortedMap<RoomWrapper> map = new DynamicSortedMap<>(); private final DynamicSortedMap<RoomWrapper> map = new DynamicSortedMap<>();
@Override @Override
@ -37,7 +42,7 @@ public class LeastPickedPicker implements RoomPicker {
if (!wrapper.canAddUnits(users.size())) throw new RuntimeException(); if (!wrapper.canAddUnits(users.size())) throw new RuntimeException();
} catch (RuntimeException ex) { } catch (RuntimeException ex) {
throw new RuntimeException("There are no rooms available"); throw new NoRoomsAvailableException(container.getNode().getIdentifier());
} }
} }

View File

@ -1,15 +1,20 @@
package ru.dragonestia.picker.repository.impl.picker; package ru.dragonestia.picker.repository.impl.picker;
import lombok.RequiredArgsConstructor;
import ru.dragonestia.picker.api.exception.NoRoomsAvailableException;
import ru.dragonestia.picker.api.model.node.PickingMethod; import ru.dragonestia.picker.api.model.node.PickingMethod;
import ru.dragonestia.picker.model.User; import ru.dragonestia.picker.model.User;
import ru.dragonestia.picker.repository.impl.collection.QueuedLinkedList; import ru.dragonestia.picker.repository.impl.collection.QueuedLinkedList;
import ru.dragonestia.picker.repository.impl.container.NodeContainer;
import ru.dragonestia.picker.repository.impl.container.RoomContainer; import ru.dragonestia.picker.repository.impl.container.RoomContainer;
import java.util.Collection; import java.util.Collection;
import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicInteger;
@RequiredArgsConstructor
public class RoundRobinPicker implements RoomPicker { public class RoundRobinPicker implements RoomPicker {
private final NodeContainer container;
private final AtomicInteger addition = new AtomicInteger(0); private final AtomicInteger addition = new AtomicInteger(0);
private final QueuedLinkedList<RoomWrapper> list = new QueuedLinkedList<>(wrapper -> wrapper.canAddUnits(addition.get())); private final QueuedLinkedList<RoomWrapper> list = new QueuedLinkedList<>(wrapper -> wrapper.canAddUnits(addition.get()));
@ -37,7 +42,7 @@ public class RoundRobinPicker implements RoomPicker {
addition.set(amount); addition.set(amount);
wrapper = list.pick(); wrapper = list.pick();
} catch (RuntimeException ex) { } catch (RuntimeException ex) {
throw new RuntimeException("There are no rooms available"); throw new NoRoomsAvailableException(container.getNode().getIdentifier());
} }
} }

View File

@ -1,15 +1,20 @@
package ru.dragonestia.picker.repository.impl.picker; package ru.dragonestia.picker.repository.impl.picker;
import lombok.RequiredArgsConstructor;
import ru.dragonestia.picker.api.exception.NoRoomsAvailableException;
import ru.dragonestia.picker.api.model.node.PickingMethod; import ru.dragonestia.picker.api.model.node.PickingMethod;
import ru.dragonestia.picker.model.User; import ru.dragonestia.picker.model.User;
import ru.dragonestia.picker.repository.impl.container.NodeContainer;
import ru.dragonestia.picker.repository.impl.container.RoomContainer; import ru.dragonestia.picker.repository.impl.container.RoomContainer;
import java.util.Collection; import java.util.Collection;
import java.util.LinkedHashMap; import java.util.LinkedHashMap;
import java.util.Map; import java.util.Map;
@RequiredArgsConstructor
public class SequentialFillingPicker implements RoomPicker { public class SequentialFillingPicker implements RoomPicker {
private final NodeContainer container;
private final Map<String, RoomWrapper> wrappers = new LinkedHashMap<>(); private final Map<String, RoomWrapper> wrappers = new LinkedHashMap<>();
@Override @Override
@ -38,7 +43,7 @@ public class SequentialFillingPicker implements RoomPicker {
} }
} }
throw new RuntimeException("There are no rooms available"); throw new NoRoomsAvailableException(container.getNode().getIdentifier());
} }
@Override @Override

View File

@ -10,6 +10,7 @@ import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.test.context.SpringBootTest; import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.context.annotation.Import; import org.springframework.context.annotation.Import;
import ru.dragonestia.picker.api.exception.NoRoomsAvailableException;
import ru.dragonestia.picker.config.FillingNodesConfig; import ru.dragonestia.picker.config.FillingNodesConfig;
import ru.dragonestia.picker.model.Node; import ru.dragonestia.picker.model.Node;
import ru.dragonestia.picker.repository.RoomRepository; import ru.dragonestia.picker.repository.RoomRepository;
@ -40,14 +41,12 @@ public class LeastPickedTests {
@ParameterizedTest @ParameterizedTest
@ArgumentsSource(PickingArgumentProvider.class) @ArgumentsSource(PickingArgumentProvider.class)
void testPicking(String expectedRoomId, int usersAmount) { void testPicking(String expectedRoomId, int usersAmount) {
var roomOpt = roomRepository.pick(node, userFiller.createRandomUsers(usersAmount)); var room = roomRepository.pick(node, userFiller.createRandomUsers(usersAmount));
Assertions.assertTrue(roomOpt.isPresent());
var room = roomOpt.get();
var slots = room.getMaxSlots(); var slots = room.getMaxSlots();
var users = userRepository.usersOf(room); var users = userRepository.usersOf(room);
Assertions.assertTrue(slots == -1 || slots >= users.size()); // check slots limitation Assertions.assertTrue(slots == -1 || slots >= users.size()); // check slots limitation
System.out.printf("Room(%s) has %s/%s users. Expected: %s, added: %s%n", room.getIdentifier(), users.size(), slots, expectedRoomId, usersAmount);
Assertions.assertEquals(expectedRoomId, room.getIdentifier()); Assertions.assertEquals(expectedRoomId, room.getIdentifier());
} }
@ -73,7 +72,6 @@ public class LeastPickedTests {
@Timeout(value = 1, threadMode = Timeout.ThreadMode.SEPARATE_THREAD) @Timeout(value = 1, threadMode = Timeout.ThreadMode.SEPARATE_THREAD)
@Test @Test
void testNoOneRoomExpected() { // Take 9 users. expected none result void testNoOneRoomExpected() { // Take 9 users. expected none result
var roomOpt = roomRepository.pick(node, userFiller.createRandomUsers(9)); Assertions.assertThrows(NoRoomsAvailableException.class, () -> roomRepository.pick(node, userFiller.createRandomUsers(9)));
Assertions.assertTrue(roomOpt.isEmpty());
} }
} }

View File

@ -8,6 +8,7 @@ import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.test.context.SpringBootTest; import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.context.annotation.Import; import org.springframework.context.annotation.Import;
import ru.dragonestia.picker.api.exception.NoRoomsAvailableException;
import ru.dragonestia.picker.config.FillingNodesConfig; import ru.dragonestia.picker.config.FillingNodesConfig;
import ru.dragonestia.picker.model.Node; import ru.dragonestia.picker.model.Node;
import ru.dragonestia.picker.repository.RoomRepository; import ru.dragonestia.picker.repository.RoomRepository;
@ -38,10 +39,7 @@ public class RoundRobinTests {
@ParameterizedTest @ParameterizedTest
@ArgumentsSource(PickingArgumentProvider.class) @ArgumentsSource(PickingArgumentProvider.class)
void testPicking(String expectedRoomId, int usersAmount) { void testPicking(String expectedRoomId, int usersAmount) {
var roomOpt = roomRepository.pick(node, userFiller.createRandomUsers(usersAmount)); var room = roomRepository.pick(node, userFiller.createRandomUsers(usersAmount));
Assertions.assertTrue(roomOpt.isPresent());
var room = roomOpt.get();
var slots = room.getMaxSlots(); var slots = room.getMaxSlots();
var users = userRepository.usersOf(room); var users = userRepository.usersOf(room);
Assertions.assertTrue(slots == -1 || slots >= users.size()); // check slots limitation Assertions.assertTrue(slots == -1 || slots >= users.size()); // check slots limitation
@ -68,7 +66,6 @@ public class RoundRobinTests {
@Timeout(value = 1, threadMode = Timeout.ThreadMode.SEPARATE_THREAD) @Timeout(value = 1, threadMode = Timeout.ThreadMode.SEPARATE_THREAD)
@Test @Test
void testNoOneRoomExpected() { // Take 9 users. expected none result void testNoOneRoomExpected() { // Take 9 users. expected none result
var roomOpt = roomRepository.pick(node, userFiller.createRandomUsers(9)); Assertions.assertThrows(NoRoomsAvailableException.class, () -> roomRepository.pick(node, userFiller.createRandomUsers(9)));
Assertions.assertTrue(roomOpt.isEmpty());
} }
} }

View File

@ -10,6 +10,7 @@ import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.test.context.SpringBootTest; import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.context.annotation.Import; import org.springframework.context.annotation.Import;
import ru.dragonestia.picker.api.exception.NoRoomsAvailableException;
import ru.dragonestia.picker.config.FillingNodesConfig; import ru.dragonestia.picker.config.FillingNodesConfig;
import ru.dragonestia.picker.model.Node; import ru.dragonestia.picker.model.Node;
import ru.dragonestia.picker.repository.RoomRepository; import ru.dragonestia.picker.repository.RoomRepository;
@ -40,14 +41,12 @@ public class SequentialFillingTests {
@ParameterizedTest @ParameterizedTest
@ArgumentsSource(PickingArgumentProvider.class) @ArgumentsSource(PickingArgumentProvider.class)
void testPicking(String expectedRoomId, int usersAmount) { void testPicking(String expectedRoomId, int usersAmount) {
var roomOpt = roomRepository.pick(node, userFiller.createRandomUsers(usersAmount)); var room = roomRepository.pick(node, userFiller.createRandomUsers(usersAmount));
Assertions.assertTrue(roomOpt.isPresent());
var room = roomOpt.get();
var slots = room.getMaxSlots(); var slots = room.getMaxSlots();
var users = userRepository.usersOf(room); var users = userRepository.usersOf(room);
Assertions.assertTrue(slots == -1 || slots >= users.size()); // check slots limitation Assertions.assertTrue(slots == -1 || slots >= users.size()); // check slots limitation
System.out.printf("Room(%s) has %s/%s users. Expected: %s, added: %s%n", room.getIdentifier(), users.size(), slots, expectedRoomId, usersAmount);
Assertions.assertEquals(expectedRoomId, room.getIdentifier()); Assertions.assertEquals(expectedRoomId, room.getIdentifier());
} }
@ -70,7 +69,6 @@ public class SequentialFillingTests {
@Timeout(value = 1, threadMode = Timeout.ThreadMode.SEPARATE_THREAD) @Timeout(value = 1, threadMode = Timeout.ThreadMode.SEPARATE_THREAD)
@Test @Test
void testNoOneRoomExpected() { // Take 9 users. expected none result void testNoOneRoomExpected() { // Take 9 users. expected none result
var roomOpt = roomRepository.pick(node, userFiller.createRandomUsers(9)); Assertions.assertThrows(NoRoomsAvailableException.class, () -> roomRepository.pick(node, userFiller.createRandomUsers(9)));
Assertions.assertTrue(roomOpt.isEmpty());
} }
} }

View File

@ -21,6 +21,7 @@ import ru.dragonestia.picker.model.factory.RoomFactory;
import ru.dragonestia.picker.model.type.SlotLimit; import ru.dragonestia.picker.model.type.SlotLimit;
import java.util.List; import java.util.List;
import java.util.Set;
@SpringBootTest @SpringBootTest
public class RoomServiceTests { public class RoomServiceTests {
@ -93,7 +94,7 @@ public class RoomServiceTests {
rooms.forEach(room -> roomService.create(room)); rooms.forEach(room -> roomService.create(room));
var users = List.of( var users = Set.of(
new User(UserIdentifier.of("1")), new User(UserIdentifier.of("1")),
new User(UserIdentifier.of("2")), new User(UserIdentifier.of("2")),
new User(UserIdentifier.of("3")), new User(UserIdentifier.of("3")),
@ -121,6 +122,6 @@ public class RoomServiceTests {
Assertions.assertThrows(NodeNotFoundException.class, () -> roomService.create(room)); Assertions.assertThrows(NodeNotFoundException.class, () -> roomService.create(room));
Assertions.assertThrows(NodeNotFoundException.class, () -> roomService.remove(room)); Assertions.assertThrows(NodeNotFoundException.class, () -> roomService.remove(room));
Assertions.assertThrows(NodeNotFoundException.class, () -> roomService.find(node, "Bruh")); Assertions.assertThrows(NodeNotFoundException.class, () -> roomService.find(node, "Bruh"));
Assertions.assertThrows(NodeNotFoundException.class, () -> roomService.pickAvailable(node, List.of(new User(UserIdentifier.of("1"))))); Assertions.assertThrows(NodeNotFoundException.class, () -> roomService.pickAvailable(node, Set.of(new User(UserIdentifier.of("1")))));
} }
} }

View File

@ -4,18 +4,16 @@ import org.springframework.boot.test.context.TestComponent;
import ru.dragonestia.picker.api.repository.type.UserIdentifier; import ru.dragonestia.picker.api.repository.type.UserIdentifier;
import ru.dragonestia.picker.model.User; import ru.dragonestia.picker.model.User;
import java.util.LinkedList; import java.util.*;
import java.util.List;
import java.util.UUID;
@TestComponent @TestComponent
public class UserFiller { public class UserFiller {
public List<User> createRandomUsers(int amount) { public Set<User> createRandomUsers(int amount) {
var list = new LinkedList<User>(); var set = new HashSet<User>();
for (int i = 0; i < amount; i++) { for (int i = 0; i < amount; i++) {
list.add(new User(UserIdentifier.of(UUID.randomUUID().toString()))); set.add(new User(UserIdentifier.of(UUID.randomUUID().toString())));
} }
return list; return set;
} }
} }