Update tests.

This commit is contained in:
Florian Nücke
2022-02-13 17:01:47 +01:00
parent 5f15146676
commit 4b9b921df9
5 changed files with 541 additions and 173 deletions

View File

@@ -1,160 +0,0 @@
/* SPDX-License-Identifier: MIT */
package li.cil.oc2.common.bus;
import li.cil.oc2.api.bus.DeviceBusElement;
import li.cil.oc2.common.capabilities.Capabilities;
import net.minecraft.core.BlockPos;
import net.minecraft.world.level.ChunkPos;
import net.minecraft.world.level.LevelAccessor;
import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraftforge.common.capabilities.Capability;
import net.minecraftforge.common.util.LazyOptional;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.mockito.MockedStatic;
import java.util.HashMap;
import java.util.HashSet;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.Mockito.*;
public class BlockBusTests {
@SuppressWarnings("unchecked") private static final Capability<DeviceBusElement> DEVICE_BUS_ELEMENT_CAPABILITY = (Capability<DeviceBusElement>) mock(Capability.class);
private FakeLevel fakeLevel;
private LevelAccessor level;
private MockedStatic<Capabilities> capabilitiesMock;
@BeforeEach
public void setupEach() {
fakeLevel = new FakeLevel();
level = fakeLevel.getLevel();
capabilitiesMock = mockStatic(Capabilities.class);
capabilitiesMock.when(Capabilities::deviceBusElement).thenReturn(DEVICE_BUS_ELEMENT_CAPABILITY);
}
@AfterEach
public void teardownEach() {
capabilitiesMock.close();
}
@Test
public void busTouchingUnloadedChunkStaysIncomplete() {
final BlockDeviceBusController busController = createBusController(new BlockPos(0, 0, 0));
busController.scan();
assertEquals(CommonDeviceBusController.BusState.INCOMPLETE, busController.getState());
}
@Test
public void busNotTouchingUnloadedChunkCompletes() {
final BlockDeviceBusController busController = createBusController(new BlockPos(8, 0, 8));
busController.scan();
assertEquals(CommonDeviceBusController.BusState.READY, busController.getState());
}
@Test
public void busControllerDetectsBusElements() {
final BlockDeviceBusController busController = createBusController(new BlockPos(8, 0, 8));
final DeviceBusElement busElement = createBusElement(new BlockPos(9, 0, 8));
busController.scan();
assertEquals(CommonDeviceBusController.BusState.READY, busController.getState());
assertTrue(busElement.getControllers().contains(busController));
assertTrue(busController.getElements().contains(busElement));
}
private BlockDeviceBusController createBusController(final BlockPos pos) {
final TestBlockDeviceBusElement busElement = new TestBlockDeviceBusElement(level, pos);
final BlockEntity blockEntity = mock(BlockEntity.class);
when(blockEntity.getBlockPos()).thenReturn(pos);
when(blockEntity.getCapability(any(), any())).thenReturn(LazyOptional.empty());
final BlockDeviceBusController busController = new BlockDeviceBusController(busElement, 0, blockEntity);
fakeLevel.addBlockEntity(blockEntity);
fakeLevel.setChunkLoaded(new ChunkPos(pos), true);
return busController;
}
private AbstractBlockDeviceBusElement createBusElement(final BlockPos pos) {
final TestBlockDeviceBusElement busElement = new TestBlockDeviceBusElement(level, pos);
final BlockEntity blockEntity = mock(BlockEntity.class);
when(blockEntity.getBlockPos()).thenReturn(pos);
when(blockEntity.getCapability(any(), any())).thenReturn(LazyOptional.empty());
when(blockEntity.getCapability(eq(Capabilities.deviceBusElement()), any())).thenReturn(LazyOptional.of(() -> busElement));
fakeLevel.addBlockEntity(blockEntity);
fakeLevel.setChunkLoaded(new ChunkPos(pos), true);
return busElement;
}
private static final class FakeLevel {
private final LevelAccessor level = mock(LevelAccessor.class);
private final HashMap<BlockPos, BlockEntity> blockEntities = new HashMap<>();
private final HashSet<ChunkPos> loadedChunks = new HashSet<>();
public FakeLevel() {
when(level.getBlockEntity(any())).then(a -> blockEntities.get(a.<BlockPos>getArgument(0)));
when(level.hasChunk(anyInt(), anyInt())).then(a -> {
final int chunkX = a.getArgument(0);
final int chunkZ = a.getArgument(1);
return loadedChunks.contains(new ChunkPos(chunkX, chunkZ));
});
}
public LevelAccessor getLevel() {
return level;
}
public void addBlockEntity(final BlockEntity blockEntity) {
blockEntities.put(blockEntity.getBlockPos(), blockEntity);
}
public void removeBlockEntity(final BlockPos pos) {
blockEntities.remove(pos);
}
public void setChunkLoaded(final ChunkPos chunkPos, final boolean loaded) {
if (loaded) {
loadedChunks.add(chunkPos);
} else {
loadedChunks.remove(chunkPos);
}
}
}
private static final class TestBlockDeviceBusElement extends AbstractBlockDeviceBusElement {
private final LevelAccessor level;
private final BlockPos blockPos;
public TestBlockDeviceBusElement(final LevelAccessor level, final BlockPos blockPos) {
this.level = level;
this.blockPos = blockPos;
}
@Override
public LevelAccessor getLevel() {
return level;
}
@Override
public BlockPos getPosition() {
return blockPos;
}
}
}

View File

@@ -0,0 +1,521 @@
/* SPDX-License-Identifier: MIT */
package li.cil.oc2.common.bus;
import li.cil.oc2.api.API;
import li.cil.oc2.api.bus.DeviceBusElement;
import li.cil.oc2.api.bus.device.Device;
import li.cil.oc2.api.bus.device.ItemDevice;
import li.cil.oc2.api.bus.device.object.Callback;
import li.cil.oc2.api.bus.device.object.ObjectDevice;
import li.cil.oc2.api.bus.device.provider.BlockDeviceProvider;
import li.cil.oc2.api.bus.device.provider.BlockDeviceQuery;
import li.cil.oc2.api.bus.device.provider.ItemDeviceProvider;
import li.cil.oc2.api.bus.device.provider.ItemDeviceQuery;
import li.cil.oc2.api.util.Invalidatable;
import li.cil.oc2.common.Constants;
import li.cil.oc2.common.bus.device.provider.Providers;
import li.cil.oc2.common.capabilities.Capabilities;
import li.cil.oc2.common.util.LevelUtils;
import li.cil.sedna.api.device.serial.SerialDevice;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.level.ChunkPos;
import net.minecraft.world.level.LevelAccessor;
import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraftforge.common.capabilities.Capability;
import net.minecraftforge.common.util.LazyOptional;
import net.minecraftforge.registries.ForgeRegistryEntry;
import net.minecraftforge.registries.IForgeRegistry;
import org.jetbrains.annotations.Nullable;
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.mockito.MockedStatic;
import org.mockito.stubbing.OngoingStubbing;
import java.util.*;
import static org.junit.jupiter.api.Assertions.*;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.Mockito.*;
public class BlockDeviceBusControllerTests {
public static final IForgeRegistry<BlockDeviceProvider> BLOCK_DEVICE_PROVIDER_REGISTRY = createBlockDeviceProviderRegistry();
public static final IForgeRegistry<ItemDeviceProvider> ITEM_DEVICE_PROVIDER_REGISTRY = createItemDeviceProviderRegistry();
private static final Set<Class<?>> REGISTERED_CAPABILITIES = new HashSet<>();
private static MockedStatic<Capabilities> capabilitiesMock;
private static MockedStatic<Providers> providersMock;
private static MockedStatic<LevelUtils> levelUtilsMock;
private FakeLevel fakeLevel;
private LevelAccessor level;
///////////////////////////////////////////////////////////////////
@SuppressWarnings("ResultOfMethodCallIgnored")
@BeforeAll
public static void setup() {
capabilitiesMock = mockStatic(Capabilities.class);
registerCapability(capabilitiesMock.when(Capabilities::energyStorage));
registerCapability(capabilitiesMock.when(Capabilities::fluidHandler));
registerCapability(capabilitiesMock.when(Capabilities::itemHandler));
registerCapability(capabilitiesMock.when(Capabilities::deviceBusElement));
registerCapability(capabilitiesMock.when(Capabilities::device));
registerCapability(capabilitiesMock.when(Capabilities::redstoneEmitter));
registerCapability(capabilitiesMock.when(Capabilities::networkInterface));
registerCapability(capabilitiesMock.when(Capabilities::terminalUserProvider));
registerCapability(capabilitiesMock.when(Capabilities::robot));
Capabilities.registerCapabilities(type -> assertTrue(REGISTERED_CAPABILITIES.contains(type)));
providersMock = mockStatic(Providers.class);
providersMock.when(Providers::blockDeviceProviderRegistry).thenReturn(BLOCK_DEVICE_PROVIDER_REGISTRY);
providersMock.when(Providers::itemDeviceProviderRegistry).thenReturn(ITEM_DEVICE_PROVIDER_REGISTRY);
levelUtilsMock = mockStatic(LevelUtils.class);
levelUtilsMock.when(() -> LevelUtils.getBlockName(any(), any())).thenReturn("test_block");
}
@SuppressWarnings("unchecked")
private static <T> void registerCapability(final OngoingStubbing<Capability<T>> stubbing) {
final Capability<T> capability = mock(Capability.class);
stubbing.thenReturn(capability);
}
@AfterAll
public static void teardown() {
REGISTERED_CAPABILITIES.clear();
capabilitiesMock.close();
providersMock.close();
levelUtilsMock.close();
}
@BeforeEach
public void setupEach() {
fakeLevel = new FakeLevel();
level = fakeLevel.getLevel();
}
@Test
public void busTouchingUnloadedChunkStaysIncomplete() {
final BlockPos posAtChunkEdge = new BlockPos(0, 0, 0);
final BlockDeviceBusController busController = new TestBusControllerBlockEntity(posAtChunkEdge).getBusController();
busController.scan();
assertEquals(CommonDeviceBusController.BusState.INCOMPLETE, busController.getState());
}
@Test
public void busNotTouchingUnloadedChunkCompletes() {
final BlockPos posInsideChunk = new BlockPos(8, 0, 8);
final BlockDeviceBusController busController = new TestBusControllerBlockEntity(posInsideChunk).getBusController();
busController.scan();
assertEquals(CommonDeviceBusController.BusState.READY, busController.getState());
}
@Test
public void busControllerIgnoresNonAccessibleBusElements() {
final BlockPos controllerPos = new BlockPos(8, 0, 8);
final TestBusControllerBlockEntity busController = new TestBusControllerBlockEntity(controllerPos);
final BlockPos elementPos = controllerPos.east();
final TestBusElementBlockEntity busElement = new TestBusElementBlockEntity(elementPos);
busElement.setSideEnabled(Direction.WEST, false);
busController.getBusController().scan();
assertEquals(CommonDeviceBusController.BusState.READY, busController.getBusController().getState());
assertFalse(busElement.getBusElement().getControllers().contains(busController.getBusController()));
assertFalse(busController.getBusController().getElements().contains(busElement.getBusElement()));
}
@Test
public void busControllerDetectsBusElements() {
final BlockPos controllerPos = new BlockPos(8, 0, 8);
final BlockDeviceBusController busController = new TestBusControllerBlockEntity(controllerPos).getBusController();
final BlockPos elementPos = controllerPos.east();
final TestBusElementBlockEntity busElementInfo = new TestBusElementBlockEntity(elementPos);
final DeviceBusElement busElement = busElementInfo.getBusElement();
busController.scan();
assertTrue(busElement.getControllers().contains(busController));
assertTrue(busController.getElements().contains(busElement));
}
@Test
public void devicesInUnloadedChunksAreMarkedAsUnloaded() {
final BlockPos elementPos = new BlockPos(0, 0, 0);
final TestBusElementBlockEntity busElementInfo = new TestBusElementBlockEntity(elementPos);
final TestBlockDeviceBusElement busElement = busElementInfo.getBusElement();
busElement.updateDevicesForNeighbor(Direction.WEST);
verify(busElement, atLeastOnce()).setEntriesForGroupUnloaded(Direction.WEST.get3DDataValue());
}
@Test
public void devicesInLoadedChunksAreCollected() {
final BlockPos elementPos = new BlockPos(0, 0, 0);
final TestBusElementBlockEntity busElementInfo = new TestBusElementBlockEntity(elementPos);
final TestBlockDeviceBusElement busElement = busElementInfo.getBusElement();
final BlockPos devicePos = elementPos.east();
final TestDeviceBlockEntity deviceBlockEntity = new TestDeviceBlockEntity(devicePos);
busElement.updateDevicesForNeighbor(Direction.EAST);
verify(busElement, atLeastOnce()).setEntriesForGroup(eq(Direction.EAST.get3DDataValue()), any());
assertTrue(busElement.getDevices().contains(deviceBlockEntity.getObjectDevice()));
}
@Test
public void equalDevicesAreIgnored() {
final BlockPos elementPos = new BlockPos(0, 0, 0);
final TestBusElementBlockEntity busElementInfo = new TestBusElementBlockEntity(elementPos);
final TestBlockDeviceBusElement busElement = busElementInfo.getBusElement();
final BlockPos devicePos = elementPos.east();
final TestDeviceBlockEntity deviceBlockEntity = new TestDeviceBlockEntity(devicePos);
busElement.updateDevicesForNeighbor(Direction.EAST);
assertTrue(busElement.getDevices().contains(deviceBlockEntity.getObjectDevice()));
final ObjectDevice equalDevice = new ObjectDevice(deviceBlockEntity.getTestDevice());
deviceBlockEntity.setObjectDevice(equalDevice);
busElement.updateDevicesForNeighbor(Direction.EAST);
assertTrue(busElement.getDevices().contains(deviceBlockEntity.getObjectDevice()));
assertNotSame(busElement.getDevices().stream().findFirst().orElseThrow(), equalDevice);
}
@Test
public void busControllerDetectsDevices() {
final BlockPos controllerPos = new BlockPos(8, 0, 8);
final BlockDeviceBusController busController = new TestBusControllerBlockEntity(controllerPos).getBusController();
final BlockPos elementPos = controllerPos.east();
final TestBusElementBlockEntity busElementInfo = new TestBusElementBlockEntity(elementPos);
when(busElementInfo.getBlockEntity().getCapability(eq(Capabilities.deviceBusElement()), any())).thenReturn(LazyOptional.of(busElementInfo::getBusElement));
final BlockPos devicePos = elementPos.east();
final TestDeviceBlockEntity deviceBlockEntity = new TestDeviceBlockEntity(devicePos);
busElementInfo.getBusElement().updateDevicesForNeighbor(Direction.EAST);
busController.scan();
assertTrue(busController.getDevices().contains(deviceBlockEntity.getObjectDevice()));
}
@Test
public void devicesGetSerializedWhenUnloadedAndDeserializedWhenLoaded() {
final BlockPos controllerPos = new BlockPos(1, 0, 8);
final BlockDeviceBusController busController = new TestBusControllerBlockEntity(controllerPos).getBusController();
final BlockPos elementPos = controllerPos.west();
final TestBusElementBlockEntity busElementInfo = new TestBusElementBlockEntity(elementPos);
when(busElementInfo.getBlockEntity().getCapability(eq(Capabilities.deviceBusElement()), any())).thenReturn(LazyOptional.of(busElementInfo::getBusElement));
final BlockPos devicePos = elementPos.west();
final TestDeviceBlockEntity deviceBlockEntity = new TestDeviceBlockEntity(devicePos);
fakeLevel.setChunkLoaded(new ChunkPos(devicePos), false);
busController.scheduleBusScan();
final RPCDeviceBusAdapter rpcDeviceBusAdapter = new RPCDeviceBusAdapter(mock(SerialDevice.class));
busController.onBeforeDeviceScan.add(rpcDeviceBusAdapter::pause);
busController.onAfterDeviceScan.add(event -> rpcDeviceBusAdapter.resume(busController, event.didDevicesChange()));
busController.scan();
// Reminder: missing chunk -> bus scan cannot complete.
assertEquals(CommonDeviceBusController.BusState.INCOMPLETE, busController.getState());
final ObjectDevice objectDevice = spy(deviceBlockEntity.getObjectDevice());
deviceBlockEntity.setObjectDevice(objectDevice);
// Initialize with unloaded chunk.
busElementInfo.getBusElement().updateDevicesForNeighbor(Direction.WEST);
assertFalse(busController.getDevices().contains(objectDevice));
verify(objectDevice, never()).mount();
verify(objectDevice, never()).unmount();
verify(objectDevice, never()).dispose();
verify(objectDevice, never()).serializeNBT();
verify(objectDevice, never()).deserializeNBT(any());
// Load device chunk.
fakeLevel.setChunkLoaded(new ChunkPos(devicePos), true);
busController.scheduleBusScan();
busElementInfo.getBusElement().updateDevicesForNeighbor(Direction.WEST);
busController.scan();
assertEquals(CommonDeviceBusController.BusState.READY, busController.getState());
assertTrue(busController.getDevices().contains(objectDevice));
rpcDeviceBusAdapter.mountDevices();
verify(objectDevice, times(1)).mount();
verify(objectDevice, never()).unmount();
verify(objectDevice, never()).dispose();
verify(objectDevice, never()).serializeNBT();
verify(objectDevice, never()).deserializeNBT(any()); // no state to deserialize
// Unload device chunk.
fakeLevel.setChunkLoaded(new ChunkPos(devicePos), false);
busController.scheduleBusScan();
busElementInfo.getBusElement().updateDevicesForNeighbor(Direction.WEST);
busController.scan();
assertEquals(CommonDeviceBusController.BusState.INCOMPLETE, busController.getState());
assertFalse(busController.getDevices().contains(objectDevice));
verify(objectDevice, times(1)).mount();
verify(objectDevice, times(1)).unmount();
verify(objectDevice, never()).dispose();
verify(objectDevice, times(1)).serializeNBT();
verify(objectDevice, never()).deserializeNBT(any());
}
// TODO device in loaded chunk -> unloaded chunk + saved -> loaded chunk + loaded
///////////////////////////////////////////////////////////////////
@SuppressWarnings("unchecked")
private static IForgeRegistry<BlockDeviceProvider> createBlockDeviceProviderRegistry() {
final IForgeRegistry<BlockDeviceProvider> registry = mock(IForgeRegistry.class);
final Map<ResourceLocation, BlockDeviceProvider> blockDeviceProviders = new HashMap<>();
blockDeviceProviders.put(new ResourceLocation(API.MOD_ID, "test"), new TestBlockDeviceProvider());
when(registry.getValues()).thenReturn(blockDeviceProviders.values());
when(registry.getValue(notNull())).then(a -> blockDeviceProviders.get(a.<ResourceLocation>getArgument(0)));
return registry;
}
@SuppressWarnings("unchecked")
private static IForgeRegistry<ItemDeviceProvider> createItemDeviceProviderRegistry() {
final IForgeRegistry<ItemDeviceProvider> registry = mock(IForgeRegistry.class);
final Map<ResourceLocation, ItemDeviceProvider> itemDeviceProviders = new HashMap<>();
itemDeviceProviders.put(new ResourceLocation(API.MOD_ID, "test"), new TestItemDeviceProvider());
when(registry.getValues()).thenReturn(itemDeviceProviders.values());
when(registry.getValue(notNull())).then(a -> itemDeviceProviders.get(a.<ResourceLocation>getArgument(0)));
return registry;
}
///////////////////////////////////////////////////////////////////
private static final class FakeLevel {
private final LevelAccessor level = mock(LevelAccessor.class);
private final HashMap<BlockPos, BlockEntity> blockEntities = new HashMap<>();
private final HashSet<ChunkPos> loadedChunks = new HashSet<>();
public FakeLevel() {
when(level.getBlockEntity(any())).then(a -> blockEntities.get(a.<BlockPos>getArgument(0)));
when(level.hasChunk(anyInt(), anyInt())).then(a -> {
final int chunkX = a.getArgument(0);
final int chunkZ = a.getArgument(1);
return loadedChunks.contains(new ChunkPos(chunkX, chunkZ));
});
}
public LevelAccessor getLevel() {
return level;
}
public void addBlockEntity(final BlockEntity blockEntity) {
blockEntities.put(blockEntity.getBlockPos(), blockEntity);
}
public void removeBlockEntity(final BlockPos pos) {
blockEntities.remove(pos);
}
public void setChunkLoaded(final ChunkPos chunkPos, final boolean loaded) {
if (loaded) {
loadedChunks.add(chunkPos);
} else {
loadedChunks.remove(chunkPos);
}
}
}
private class TestBlockEntity {
private final BlockEntity blockEntity;
public TestBlockEntity(final BlockPos pos) {
blockEntity = mock(BlockEntity.class);
when(blockEntity.getBlockPos()).thenReturn(pos);
when(blockEntity.getCapability(any(), any())).thenReturn(LazyOptional.empty());
when(blockEntity.getCapability(any())).thenCallRealMethod();
fakeLevel.addBlockEntity(blockEntity);
fakeLevel.setChunkLoaded(new ChunkPos(pos), true);
}
public BlockEntity getBlockEntity() {
return blockEntity;
}
}
private class TestBusElementBlockEntity extends TestBlockEntity {
private final TestBlockDeviceBusElement busElement;
private final boolean[] enabledSides = new boolean[Constants.BLOCK_FACE_COUNT];
public TestBusElementBlockEntity(final BlockPos pos) {
super(pos);
busElement = spy(new TestBlockDeviceBusElement(level, pos));
when(getBlockEntity().getCapability(eq(Capabilities.deviceBusElement()), any())).then(a -> {
if (enabledSides[a.<Direction>getArgument(1).get3DDataValue()]) {
return LazyOptional.of(() -> busElement);
} else {
return LazyOptional.empty();
}
});
Arrays.fill(enabledSides, true);
}
public TestBlockDeviceBusElement getBusElement() {
return busElement;
}
public void setSideEnabled(final Direction side, final boolean value) {
enabledSides[side.get3DDataValue()] = value;
}
}
private class TestBusControllerBlockEntity extends TestBusElementBlockEntity {
private final BlockDeviceBusController busController;
public TestBusControllerBlockEntity(final BlockPos pos) {
super(pos);
busController = new BlockDeviceBusController(getBusElement(), 0, getBlockEntity());
}
public BlockDeviceBusController getBusController() {
return busController;
}
}
private class TestDeviceBlockEntity extends TestBlockEntity {
private final TestDevice testDevice;
private ObjectDevice objectDevice;
public TestDeviceBlockEntity(final BlockPos pos) {
super(pos);
testDevice = new TestDevice();
objectDevice = new ObjectDevice(testDevice);
when(getBlockEntity().getCapability(eq(Capabilities.device()), any())).thenReturn(LazyOptional.of(() -> objectDevice));
}
public TestDevice getTestDevice() {
return testDevice;
}
public ObjectDevice getObjectDevice() {
return objectDevice;
}
public void setObjectDevice(final ObjectDevice device) {
this.objectDevice = device;
}
}
private static final class TestBlockDeviceBusElement extends AbstractBlockDeviceBusElement {
private final LevelAccessor level;
private final BlockPos blockPos;
public TestBlockDeviceBusElement(final LevelAccessor level, final BlockPos blockPos) {
this.level = level;
this.blockPos = blockPos;
}
@Override
public LevelAccessor getLevel() {
return level;
}
@Override
public BlockPos getPosition() {
return blockPos;
}
}
private static class TestBlockDeviceProvider implements BlockDeviceProvider {
@Override
public BlockDeviceProvider setRegistryName(final ResourceLocation name) {
return this;
}
@Nullable
@Override
public ResourceLocation getRegistryName() {
return new ResourceLocation(API.MOD_ID, "test");
}
@Override
public Class<BlockDeviceProvider> getRegistryType() {
return BlockDeviceProvider.class;
}
@Override
public Invalidatable<Device> getDevice(final BlockDeviceQuery query) {
final LevelAccessor level = query.getLevel();
final BlockEntity blockEntity = level.getBlockEntity(query.getQueryPosition());
if (blockEntity != null) {
final Optional<Device> optional = blockEntity.getCapability(Capabilities.device()).resolve();
return optional.map(Invalidatable::of).orElseGet(Invalidatable::empty);
}
return Invalidatable.empty();
}
}
private static class TestItemDeviceProvider implements ItemDeviceProvider {
@Override
public ItemDeviceProvider setRegistryName(final ResourceLocation name) {
return this;
}
@Nullable
@Override
public ResourceLocation getRegistryName() {
return new ResourceLocation(API.MOD_ID, "test");
}
@Override
public Class<ItemDeviceProvider> getRegistryType() {
return ItemDeviceProvider.class;
}
@Override
public Optional<ItemDevice> getDevice(final ItemDeviceQuery query) {
return Optional.empty();
}
}
public static class TestDevice {
@Callback
public int test() {
return 42;
}
}
}

View File

@@ -15,7 +15,7 @@ import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.mockito.Mockito.*;
public class DeviceBusTests {
public class CommonDeviceBusControllerTests {
private CommonDeviceBusController busController;
private DeviceBusElement busControllerBusElement;

View File

@@ -13,7 +13,7 @@ import java.util.*;
import static org.mockito.Mockito.*;
public final class RPCDeviceTests {
public final class RPCDeviceBusAdapterTests {
private RPCDeviceBusAdapter adapter;
private Set<Device> busDevices;
private Map<Device, Set<UUID>> deviceIdentifiers;
@@ -56,7 +56,7 @@ public final class RPCDeviceTests {
}
@Test
public void mountedDevicesAreUnmountedAndDisposedWhenRemoved() {
public void mountedDevicesAreUnmountedWhenRemoved() {
final RPCDevice device = addDevice();
adapter.resume(controller, true);
adapter.mountDevices();
@@ -64,18 +64,18 @@ public final class RPCDeviceTests {
removeDevice(device);
adapter.resume(controller, true);
verify(device).unmount();
verify(device).dispose();
verify(device, never()).dispose();
}
@Test
public void unmountedDevicesAreDisposedWhenRemoved() {
public void unmountedDevicesAreSilentlyRemoved() {
final RPCDevice device = addDevice();
adapter.resume(controller, true);
removeDevice(device);
adapter.resume(controller, true);
verify(device, never()).unmount();
verify(device).dispose();
verify(device, never()).dispose();
}
@Test

View File

@@ -24,7 +24,7 @@ import static org.junit.jupiter.api.Assertions.*;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.*;
public final class VMDeviceTests {
public final class VMDeviceBusAdapterTests {
private MemoryMap memoryMap;
private InterruptController interruptController;
private R5MemoryRangeAllocationStrategy allocationStrategy;
@@ -106,7 +106,7 @@ public final class VMDeviceTests {
}
@Test
public void mountedDevicesAreUnmountedAndDisposedIfOtherMountFails() {
public void mountedDevicesAreUnmountedIfOtherMountFails() {
final VMDevice device1 = mock(VMDevice.class);
final VMDevice device2 = mock(VMDevice.class);
when(device1.mount(any())).thenReturn(VMDeviceLoadResult.success());
@@ -119,11 +119,11 @@ public final class VMDeviceTests {
verify(device1).mount(any());
verify(device2).mount(any());
verify(device1).unmount();
verify(device1).dispose();
verify(device1, never()).dispose();
}
@Test
public void mountedDevicesAreUnmountedAndDisposedWhenRemoved() {
public void mountedDevicesAreUnmountedWhenRemoved() {
final VMDevice device = mock(VMDevice.class);
when(device.mount(any())).thenReturn(VMDeviceLoadResult.success());
@@ -132,17 +132,24 @@ public final class VMDeviceTests {
adapter.removeDevices(Collections.singleton(device));
verify(device).unmount();
verify(device).dispose();
verify(device, never()).dispose();
}
@Test
public void unmountedDevicesAreDisposedWhenRemoved() {
public void unmountedDevicesAreSilentlyRemoved() {
final VMDevice device = mock(VMDevice.class);
when(device.mount(any())).thenReturn(VMDeviceLoadResult.success());
adapter.addDevices(Collections.singleton(device));
adapter.mountDevices();
verify(device).mount(any());
adapter.unmountDevices();
verify(device).unmount();
adapter.removeDevices(Collections.singleton(device));
verify(device).dispose();
verify(device, never()).dispose();
}
@Test