Make tests fail if error occurs during platform
This commit is contained in:
8 files changed
+133
-25
No files matched your search
@@ -81,8 +81,9 @@ public class MappingDataLoader {
|
|||||||
for (final Map.Entry<String, Tag> entry : globalIdentifiers.entrySet()) {
|
for (final Map.Entry<String, Tag> entry : globalIdentifiers.entrySet()) {
|
||||||
//noinspection unchecked
|
//noinspection unchecked
|
||||||
final ListTag<StringTag> value = (ListTag<StringTag>) entry.getValue();
|
final ListTag<StringTag> value = (ListTag<StringTag>) entry.getValue();
|
||||||
final String[] array = new String[value.size()];
|
final int size = value.size();
|
||||||
for (int i = 0, size = value.size(); i < size; i++) {
|
final String[] array = new String[size];
|
||||||
|
for (int i = 0; i < size; i++) {
|
||||||
array[i] = value.get(i).getValue();
|
array[i] = value.get(i).getValue();
|
||||||
}
|
}
|
||||||
GLOBAL_IDENTIFIER_INDEXES.put(entry.getKey(), array);
|
GLOBAL_IDENTIFIER_INDEXES.put(entry.getKey(), array);
|
||||||
|
|||||||
@@ -249,7 +249,17 @@ public interface ProtocolManager {
|
|||||||
*
|
*
|
||||||
* @return true if the executor has now been shut down
|
* @return true if the executor has now been shut down
|
||||||
*/
|
*/
|
||||||
boolean checkForMappingCompletion();
|
default boolean checkForMappingCompletion() {
|
||||||
|
return checkForMappingCompletion(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Shuts down the executor and uncaches mappings if all futures have been completed.
|
||||||
|
*
|
||||||
|
* @param propagateErrors whether to propagate errors from the futures to the caller
|
||||||
|
* @return true if the executor has now been shut down
|
||||||
|
*/
|
||||||
|
boolean checkForMappingCompletion(boolean propagateErrors);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Executes the given runnable asynchronously, adding a {@link CompletableFuture}
|
* Executes the given runnable asynchronously, adding a {@link CompletableFuture}
|
||||||
|
|||||||
@@ -49,6 +49,20 @@ public final class NMSUtil {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static Class<?> nms(String className, String... fallbackFullClassNames) throws ClassNotFoundException {
|
||||||
|
try {
|
||||||
|
return Class.forName(NMS + "." + className);
|
||||||
|
} catch (ClassNotFoundException ignored) {
|
||||||
|
}
|
||||||
|
for (final String fallbackFullClassName : fallbackFullClassNames) {
|
||||||
|
try {
|
||||||
|
return Class.forName(fallbackFullClassName);
|
||||||
|
} catch (ClassNotFoundException ignored) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
throw new ClassNotFoundException(className);
|
||||||
|
}
|
||||||
|
|
||||||
public static Class<?> obc(String className) throws ClassNotFoundException {
|
public static Class<?> obc(String className) throws ClassNotFoundException {
|
||||||
return Class.forName(BASE + "." + className);
|
return Class.forName(BASE + "." + className);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -97,6 +97,7 @@ import it.unimi.dsi.fastutil.objects.Object2ObjectLinkedOpenHashMap;
|
|||||||
import it.unimi.dsi.fastutil.objects.Object2ObjectMap;
|
import it.unimi.dsi.fastutil.objects.Object2ObjectMap;
|
||||||
import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap;
|
import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap;
|
||||||
import it.unimi.dsi.fastutil.objects.Object2ObjectSortedMap;
|
import it.unimi.dsi.fastutil.objects.Object2ObjectSortedMap;
|
||||||
|
import it.unimi.dsi.fastutil.objects.Reference2ObjectOpenHashMap;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
@@ -115,9 +116,7 @@ import java.util.concurrent.ForkJoinWorkerThread;
|
|||||||
import java.util.concurrent.atomic.AtomicInteger;
|
import java.util.concurrent.atomic.AtomicInteger;
|
||||||
import java.util.concurrent.locks.ReadWriteLock;
|
import java.util.concurrent.locks.ReadWriteLock;
|
||||||
import java.util.concurrent.locks.ReentrantReadWriteLock;
|
import java.util.concurrent.locks.ReentrantReadWriteLock;
|
||||||
import java.util.function.Function;
|
|
||||||
import java.util.logging.Level;
|
import java.util.logging.Level;
|
||||||
import it.unimi.dsi.fastutil.objects.Reference2ObjectOpenHashMap;
|
|
||||||
import org.checkerframework.checker.nullness.qual.Nullable;
|
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||||
|
|
||||||
public class ProtocolManagerImpl implements ProtocolManager {
|
public class ProtocolManagerImpl implements ProtocolManager {
|
||||||
@@ -499,7 +498,7 @@ public class ProtocolManagerImpl implements ProtocolManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean checkForMappingCompletion() {
|
public boolean checkForMappingCompletion(final boolean propagateErrors) {
|
||||||
mappingLoaderLock.readLock().lock();
|
mappingLoaderLock.readLock().lock();
|
||||||
try {
|
try {
|
||||||
if (mappingsLoaded) {
|
if (mappingsLoaded) {
|
||||||
@@ -511,6 +510,9 @@ public class ProtocolManagerImpl implements ProtocolManager {
|
|||||||
if (!future.isDone()) {
|
if (!future.isDone()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
if (propagateErrors) {
|
||||||
|
future.join();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
shutdownLoaderExecutor();
|
shutdownLoaderExecutor();
|
||||||
@@ -522,7 +524,8 @@ public class ProtocolManagerImpl implements ProtocolManager {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void addMappingLoaderFuture(Class<? extends Protocol> protocolClass, Runnable runnable) {
|
public void addMappingLoaderFuture(Class<? extends Protocol> protocolClass, Runnable runnable) {
|
||||||
CompletableFuture<Void> future = CompletableFuture.runAsync(runnable, mappingLoaderExecutor).exceptionally(mappingLoaderThrowable(protocolClass));
|
CompletableFuture<Void> future = CompletableFuture.runAsync(runnable, mappingLoaderExecutor)
|
||||||
|
.whenComplete(($, t) -> logIfErrored(protocolClass, t));
|
||||||
|
|
||||||
mappingLoaderLock.writeLock().lock();
|
mappingLoaderLock.writeLock().lock();
|
||||||
try {
|
try {
|
||||||
@@ -534,8 +537,8 @@ public class ProtocolManagerImpl implements ProtocolManager {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void addMappingLoaderFuture(Class<? extends Protocol> protocolClass, Class<? extends Protocol> dependsOn, Runnable runnable) {
|
public void addMappingLoaderFuture(Class<? extends Protocol> protocolClass, Class<? extends Protocol> dependsOn, Runnable runnable) {
|
||||||
CompletableFuture<Void> future = getMappingLoaderFuture(dependsOn)
|
CompletableFuture<Void> future = getMappingLoaderFuture(dependsOn).thenRunAsync(runnable, mappingLoaderExecutor)
|
||||||
.whenCompleteAsync((v, throwable) -> runnable.run(), mappingLoaderExecutor).exceptionally(mappingLoaderThrowable(protocolClass));
|
.whenComplete(($, t) -> logIfErrored(protocolClass, t));
|
||||||
|
|
||||||
mappingLoaderLock.writeLock().lock();
|
mappingLoaderLock.writeLock().lock();
|
||||||
try {
|
try {
|
||||||
@@ -586,10 +589,9 @@ public class ProtocolManagerImpl implements ProtocolManager {
|
|||||||
MappingDataLoader.INSTANCE.clearCache();
|
MappingDataLoader.INSTANCE.clearCache();
|
||||||
}
|
}
|
||||||
|
|
||||||
private Function<Throwable, Void> mappingLoaderThrowable(Class<? extends Protocol> protocolClass) {
|
private void logIfErrored(final Class<? extends Protocol> protocolClass, @Nullable final Throwable throwable) {
|
||||||
return throwable -> {
|
if (throwable != null) {
|
||||||
Via.getPlatform().getLogger().log(Level.SEVERE, "Error during loading of " + protocolClass.getSimpleName(), throwable);
|
Via.getPlatform().getLogger().log(Level.SEVERE, "Error during loading of " + protocolClass.getSimpleName(), throwable);
|
||||||
return null;
|
}
|
||||||
};
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,28 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
|
||||||
|
* Copyright (C) 2016-2025 ViaVersion and contributors
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
package com.viaversion.viaversion.common;
|
||||||
|
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
final class APlatformBootstrapTest {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void platformLoads() throws InterruptedException {
|
||||||
|
PlatformTestLoader.ensureLoaded();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -17,23 +17,12 @@
|
|||||||
*/
|
*/
|
||||||
package com.viaversion.viaversion.common;
|
package com.viaversion.viaversion.common;
|
||||||
|
|
||||||
import com.viaversion.viaversion.ViaManagerImpl;
|
|
||||||
import com.viaversion.viaversion.api.Via;
|
|
||||||
import com.viaversion.viaversion.platform.NoopInjector;
|
|
||||||
import com.viaversion.viaversion.api.platform.ViaPlatformLoader;
|
|
||||||
import com.viaversion.viaversion.commands.ViaCommandHandler;
|
|
||||||
import com.viaversion.viaversion.common.dummy.TestPlatform;
|
|
||||||
import org.junit.jupiter.api.BeforeAll;
|
import org.junit.jupiter.api.BeforeAll;
|
||||||
|
|
||||||
public abstract class PlatformTestBase {
|
public abstract class PlatformTestBase {
|
||||||
|
|
||||||
@BeforeAll
|
@BeforeAll
|
||||||
static void loadPlatform() throws InterruptedException {
|
static void loadPlatform() throws InterruptedException {
|
||||||
if (!Via.isLoaded()) {
|
PlatformTestLoader.ensureLoaded();
|
||||||
ViaManagerImpl.initAndLoad(new TestPlatform(), new NoopInjector(), new ViaCommandHandler(), ViaPlatformLoader.NOOP);
|
|
||||||
}
|
|
||||||
while (!Via.getManager().getProtocolManager().hasLoadedMappings()) {
|
|
||||||
Thread.sleep(100);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,63 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
|
||||||
|
* Copyright (C) 2016-2025 ViaVersion and contributors
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
package com.viaversion.viaversion.common;
|
||||||
|
|
||||||
|
import com.viaversion.viaversion.ViaManagerImpl;
|
||||||
|
import com.viaversion.viaversion.api.Via;
|
||||||
|
import com.viaversion.viaversion.api.platform.ViaPlatformLoader;
|
||||||
|
import com.viaversion.viaversion.commands.ViaCommandHandler;
|
||||||
|
import com.viaversion.viaversion.common.dummy.TestPlatform;
|
||||||
|
import com.viaversion.viaversion.platform.NoopInjector;
|
||||||
|
import java.util.concurrent.CompletionException;
|
||||||
|
|
||||||
|
final class PlatformTestLoader {
|
||||||
|
|
||||||
|
private static boolean loaded;
|
||||||
|
private static Throwable failure;
|
||||||
|
|
||||||
|
static synchronized void ensureLoaded() throws InterruptedException {
|
||||||
|
if (loaded) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (failure != null) {
|
||||||
|
throw new AssertionError("Platform bootstrap previously failed", failure);
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
if (!Via.isLoaded()) {
|
||||||
|
ViaManagerImpl.initAndLoad(new TestPlatform(), new NoopInjector(), new ViaCommandHandler(false), ViaPlatformLoader.NOOP);
|
||||||
|
}
|
||||||
|
|
||||||
|
while (!Via.getManager().getProtocolManager().checkForMappingCompletion(true)) {
|
||||||
|
Thread.sleep(100);
|
||||||
|
}
|
||||||
|
|
||||||
|
loaded = true;
|
||||||
|
} catch (final CompletionException e) {
|
||||||
|
failure = e.getCause();
|
||||||
|
throw new AssertionError("Async mapping loading failed", e.getCause());
|
||||||
|
} catch (final InterruptedException e) {
|
||||||
|
failure = e;
|
||||||
|
Thread.currentThread().interrupt();
|
||||||
|
throw e;
|
||||||
|
} catch (final Throwable t) {
|
||||||
|
failure = t;
|
||||||
|
throw t;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
junit.jupiter.testclass.order.default = org.junit.jupiter.api.ClassOrderer$ClassName
|
||||||
Reference in new issue
Block a user