Update the integration test for Minecraft 1.7.2.
Dieser Commit ist enthalten in:
Ursprung
12286ebaa7
Commit
8bd177daf5
@ -11,6 +11,8 @@ import java.util.Map;
|
||||
import java.util.concurrent.Callable;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import org.apache.logging.log4j.simple.SimpleLogger;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.plugin.Plugin;
|
||||
import org.bukkit.plugin.PluginDescriptionFile;
|
||||
@ -20,6 +22,7 @@ import org.junit.AfterClass;
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.powermock.core.classloader.annotations.PowerMockIgnore;
|
||||
import org.powermock.core.classloader.annotations.PrepareForTest;
|
||||
|
||||
import com.comphenix.protocol.ProtocolLibrary;
|
||||
@ -29,6 +32,7 @@ import com.google.common.io.Files;
|
||||
|
||||
// Damn final classes ...
|
||||
@RunWith(org.powermock.modules.junit4.PowerMockRunner.class)
|
||||
@PowerMockIgnore({ "org.apache.log4j.*", "org.apache.logging.*", "org.bukkit.craftbukkit.libs.jline.*" })
|
||||
@PrepareForTest(PluginDescriptionFile.class)
|
||||
public class SimpleCraftBukkitITCase {
|
||||
// The fake plugin
|
||||
@ -50,7 +54,14 @@ public class SimpleCraftBukkitITCase {
|
||||
@BeforeClass
|
||||
public static void setupCraftBukkit() throws Exception {
|
||||
setupPlugins();
|
||||
|
||||
try {
|
||||
org.bukkit.craftbukkit.Main.main(new String[0]);
|
||||
} finally {
|
||||
System.out.println("Current class loader: " + Thread.currentThread().getContextClassLoader());
|
||||
System.out.println("Loader of SimpleLogger: " + SimpleLogger.class.getClassLoader());
|
||||
System.out.println("Loader of Logger: " + Logger.class.getClassLoader());
|
||||
}
|
||||
|
||||
// We need to wait until the server object is ready
|
||||
while (Bukkit.getServer() == null)
|
||||
@ -67,6 +78,7 @@ public class SimpleCraftBukkitITCase {
|
||||
@Override
|
||||
public Object call() throws Exception {
|
||||
initializePlugin(FAKE_PLUGIN);
|
||||
ProtocolLibrary.getConfiguration().setDebug(true);
|
||||
return null;
|
||||
}
|
||||
}).get(TIMEOUT_MS, TimeUnit.MILLISECONDS);
|
||||
@ -98,7 +110,9 @@ public class SimpleCraftBukkitITCase {
|
||||
int bestLength = Integer.MAX_VALUE;
|
||||
|
||||
// Copy the ProtocolLib plugin to the server
|
||||
if (pluginDirectory.exists()) {
|
||||
Files.deleteDirectoryContents(pluginDirectory);
|
||||
}
|
||||
|
||||
for (File file : new File("../").listFiles()) {
|
||||
String name = file.getName();
|
||||
@ -108,6 +122,7 @@ public class SimpleCraftBukkitITCase {
|
||||
bestFile = file;
|
||||
}
|
||||
}
|
||||
pluginDirectory.mkdirs();
|
||||
Files.copy(bestFile, new File(pluginDirectory, bestFile.getName()));
|
||||
}
|
||||
|
||||
|
@ -1,5 +1,8 @@
|
||||
package com.comphenix.integration.protocol;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.DataInputStream;
|
||||
import java.io.DataOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
@ -7,24 +10,24 @@ import java.io.InputStreamReader;
|
||||
import java.io.OutputStream;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.net.Socket;
|
||||
import java.nio.charset.Charset;
|
||||
|
||||
import com.comphenix.protocol.utility.MinecraftVersion;
|
||||
import com.google.common.base.Charsets;
|
||||
import com.comphenix.protocol.PacketType;
|
||||
import com.comphenix.protocol.PacketType.Protocol;
|
||||
import com.comphenix.protocol.PacketType.Sender;
|
||||
import com.comphenix.protocol.utility.StreamSerializer;
|
||||
import com.google.common.io.ByteStreams;
|
||||
|
||||
public class SimpleMinecraftClient {
|
||||
private static final int CONNECT_TIMEOUT = 2500;
|
||||
private static final int READ_TIMEOUT = 15000;
|
||||
|
||||
// The version after which we must send a plugin message with the host name
|
||||
private static final String PLUGIN_MESSAGE_VERSION = "1.6.0";
|
||||
|
||||
// Current Minecraft version
|
||||
private final MinecraftVersion version;
|
||||
private final int protocolVersion;
|
||||
|
||||
public SimpleMinecraftClient(MinecraftVersion version, int protocolVersion) {
|
||||
this.version = version;
|
||||
// Typical Minecraft serializer
|
||||
private static StreamSerializer serializer = StreamSerializer.getDefault();
|
||||
|
||||
public SimpleMinecraftClient(int protocolVersion) {
|
||||
this.protocolVersion = protocolVersion;
|
||||
}
|
||||
|
||||
@ -49,9 +52,6 @@ public class SimpleMinecraftClient {
|
||||
InputStream input = null;
|
||||
InputStreamReader reader = null;
|
||||
|
||||
// UTF-16!
|
||||
Charset charset = Charsets.UTF_16BE;
|
||||
|
||||
try {
|
||||
socket = new Socket();
|
||||
socket.connect(address, CONNECT_TIMEOUT);
|
||||
@ -62,42 +62,20 @@ public class SimpleMinecraftClient {
|
||||
// Retrieve sockets
|
||||
output = socket.getOutputStream();
|
||||
input = socket.getInputStream();
|
||||
reader = new InputStreamReader(input, charset);
|
||||
|
||||
// Get the server to send a MOTD
|
||||
output.write(new byte[] { (byte) 0xFE, (byte) 0x01 });
|
||||
|
||||
// For 1.6
|
||||
if (version.compareTo(new MinecraftVersion(PLUGIN_MESSAGE_VERSION)) >= 0) {
|
||||
// The output writer
|
||||
DataOutputStream data = new DataOutputStream(output);
|
||||
String host = address.getHostName();
|
||||
|
||||
data.writeByte(0xFA);
|
||||
writeString(data, "MC|PingHost");
|
||||
data.writeShort(3 + 2 * host.length() + 4);
|
||||
|
||||
data.writeByte(protocolVersion);
|
||||
writeString(data, host);
|
||||
data.writeInt(address.getPort());
|
||||
// Request a server information packet
|
||||
writePacket(data, new HandshakePacket(protocolVersion, address.getHostName(), address.getPort(), 1));
|
||||
writePacket(data, new RequestPacket());
|
||||
data.flush();
|
||||
}
|
||||
|
||||
int packetId = input.read();
|
||||
int length = reader.read();
|
||||
// Read a single packet, and close the connection
|
||||
SimplePacket packet = readPacket(new DataInputStream(input), Protocol.STATUS);
|
||||
|
||||
if (packetId != 255)
|
||||
throw new IOException("Invalid packet ID: " + packetId);
|
||||
if (length <= 0)
|
||||
throw new IOException("Invalid string length.");
|
||||
|
||||
char[] chars = new char[length];
|
||||
|
||||
// Read all the characters
|
||||
if (reader.read(chars, 0, length) != length) {
|
||||
throw new IOException("Premature end of stream.");
|
||||
}
|
||||
|
||||
return new String(chars);
|
||||
socket.close();
|
||||
return ((ResponsePacket) packet).getPingJson();
|
||||
|
||||
} finally {
|
||||
if (reader != null)
|
||||
@ -111,10 +89,136 @@ public class SimpleMinecraftClient {
|
||||
}
|
||||
}
|
||||
|
||||
private void writeString(DataOutputStream output, String text) throws IOException {
|
||||
if (text.length() > 32767)
|
||||
throw new IOException("String too big: " + text.length());
|
||||
output.writeShort(text.length());
|
||||
output.writeChars(text);
|
||||
private void writePacket(DataOutputStream output, SimplePacket packet) throws IOException {
|
||||
ByteArrayOutputStream packetBuffer = new ByteArrayOutputStream();
|
||||
DataOutputStream packetOutput = new DataOutputStream(packetBuffer);
|
||||
|
||||
// Prefix the packet with a length field
|
||||
packet.write(packetOutput);
|
||||
writeByteArray(output, packetBuffer.toByteArray());
|
||||
}
|
||||
|
||||
private SimplePacket readPacket(DataInputStream input, Protocol protocol) throws IOException {
|
||||
while (true) {
|
||||
byte[] buffer = readByteArray(input);
|
||||
|
||||
// Skip empty packets
|
||||
if (buffer.length == 0)
|
||||
continue;
|
||||
|
||||
DataInputStream data = getDataInput(buffer);
|
||||
PacketType type = PacketType.findCurrent(protocol, Sender.SERVER, serializer.deserializeVarInt(data));
|
||||
|
||||
if (type == PacketType.Status.Server.OUT_SERVER_INFO) {
|
||||
ResponsePacket response = new ResponsePacket();
|
||||
response.read(type, data);
|
||||
return response;
|
||||
} else {
|
||||
throw new IllegalArgumentException("Unsuppported and unexpected type: " + type);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Wrap an input stream around a byte array.
|
||||
* @param bytes - the array.
|
||||
* @return The wrapped input stream.
|
||||
*/
|
||||
private DataInputStream getDataInput(byte[] bytes) {
|
||||
return new DataInputStream(new ByteArrayInputStream(bytes));
|
||||
}
|
||||
|
||||
/**
|
||||
* Write a byte array to the output stream, prefixed by a length.
|
||||
* @param output - the stream.
|
||||
* @param data - the data to write.
|
||||
*/
|
||||
private static void writeByteArray(DataOutputStream output, byte[] data) throws IOException {
|
||||
StreamSerializer.getDefault().serializeVarInt(output, data.length);
|
||||
|
||||
if (data.length > 0) {
|
||||
output.write(data);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Read a byte array from an input stream, prefixed by length.
|
||||
* @param input - the input stream.
|
||||
* @return The read byte array.
|
||||
*/
|
||||
private static byte[] readByteArray(DataInputStream input) throws IOException {
|
||||
int length = serializer.deserializeVarInt(input);
|
||||
byte[] data = new byte[length];
|
||||
|
||||
ByteStreams.readFully(input, data);
|
||||
return data;
|
||||
}
|
||||
|
||||
private static class RequestPacket extends SimplePacket {
|
||||
public RequestPacket() {
|
||||
super(PacketType.Status.Client.IN_START);
|
||||
}
|
||||
}
|
||||
|
||||
private static class ResponsePacket extends SimplePacket {
|
||||
private String ping;
|
||||
|
||||
public ResponsePacket() {
|
||||
super(PacketType.Status.Server.OUT_SERVER_INFO);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void read(PacketType type, DataInputStream input) throws IOException {
|
||||
super.read(type, input);
|
||||
ping = serializer.deserializeString(input, 32000);
|
||||
}
|
||||
|
||||
public String getPingJson() {
|
||||
return ping;
|
||||
}
|
||||
}
|
||||
|
||||
private static class HandshakePacket extends SimplePacket {
|
||||
private int protocol;
|
||||
private String host;
|
||||
private int port;
|
||||
private int nextState;
|
||||
|
||||
public HandshakePacket(int protocol, String host, int port, int nextState) {
|
||||
super(PacketType.Handshake.Client.SET_PROTOCOL);
|
||||
this.protocol = protocol;
|
||||
this.host = host;
|
||||
this.port = port;
|
||||
this.nextState = nextState;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(DataOutputStream output) throws IOException {
|
||||
super.write(output);
|
||||
serializer.serializeVarInt(output, protocol);
|
||||
serializer.serializeString(output, host);
|
||||
output.writeShort(port);
|
||||
serializer.serializeVarInt(output, nextState);
|
||||
}
|
||||
}
|
||||
|
||||
private static class SimplePacket {
|
||||
protected final PacketType type;
|
||||
protected final StreamSerializer serializer = StreamSerializer.getDefault();
|
||||
|
||||
public SimplePacket(PacketType type) {
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
public void write(DataOutputStream output) throws IOException {
|
||||
serializer.serializeVarInt(output, type.getCurrentId());
|
||||
}
|
||||
|
||||
public void read(PacketType type, DataInputStream input) throws IOException {
|
||||
// Note - we don't read the packet id
|
||||
if (this.type != type) {
|
||||
throw new IllegalArgumentException("Unexpected type: " + type);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -10,18 +10,14 @@ import java.util.concurrent.TimeUnit;
|
||||
|
||||
import org.bukkit.plugin.Plugin;
|
||||
|
||||
import com.comphenix.protocol.Packets;
|
||||
import com.comphenix.protocol.PacketType;
|
||||
import com.comphenix.protocol.ProtocolLibrary;
|
||||
import com.comphenix.protocol.events.ConnectionSide;
|
||||
import com.comphenix.protocol.events.PacketAdapter;
|
||||
import com.comphenix.protocol.events.PacketEvent;
|
||||
import com.comphenix.protocol.injector.GamePhase;
|
||||
import com.comphenix.protocol.utility.MinecraftVersion;
|
||||
|
||||
public class TestPingPacket {
|
||||
// Current versions
|
||||
private static final String CRAFTBUKKIT_VERSION = "1.6.2";
|
||||
private static final int PROTOCOL_VERSION = 74;
|
||||
private static final int PROTOCOL_VERSION = 4;
|
||||
|
||||
// Timeout
|
||||
private static final int TIMEOUT_PING_MS = 10000;
|
||||
@ -52,7 +48,7 @@ public class TestPingPacket {
|
||||
|
||||
// Make sure it's the same
|
||||
System.out.println("Server string: " + transmitted);
|
||||
assertEquals(transmitted, source);
|
||||
assertEquals(source, transmitted);
|
||||
} catch (ExecutionException e) {
|
||||
throw e.getCause();
|
||||
}
|
||||
@ -60,10 +56,10 @@ public class TestPingPacket {
|
||||
|
||||
private Future<String> testInterception(Plugin test) {
|
||||
ProtocolLibrary.getProtocolManager().addPacketListener(
|
||||
new PacketAdapter(test, ConnectionSide.SERVER_SIDE, GamePhase.LOGIN, Packets.Server.KICK_DISCONNECT) {
|
||||
new PacketAdapter(test, PacketType.Status.Server.OUT_SERVER_INFO) {
|
||||
@Override
|
||||
public void onPacketSending(PacketEvent event) {
|
||||
source = event.getPacket().getStrings().read(0);
|
||||
source = event.getPacket().getServerPings().read(0).toJson();
|
||||
}
|
||||
});
|
||||
|
||||
@ -71,8 +67,7 @@ public class TestPingPacket {
|
||||
return Executors.newSingleThreadExecutor().submit(new Callable<String>() {
|
||||
@Override
|
||||
public String call() throws Exception {
|
||||
SimpleMinecraftClient client = new SimpleMinecraftClient(
|
||||
new MinecraftVersion(CRAFTBUKKIT_VERSION), PROTOCOL_VERSION);
|
||||
SimpleMinecraftClient client = new SimpleMinecraftClient(PROTOCOL_VERSION);
|
||||
String information = client.queryLocalPing();
|
||||
|
||||
// Wait for the listener to catch up
|
||||
|
@ -41,6 +41,7 @@ import org.bukkit.potion.PotionEffectType;
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.powermock.core.classloader.annotations.PowerMockIgnore;
|
||||
import org.powermock.core.classloader.annotations.PrepareForTest;
|
||||
|
||||
import com.comphenix.protocol.BukkitInitialization;
|
||||
@ -50,7 +51,6 @@ import com.comphenix.protocol.PacketType.Sender;
|
||||
import com.comphenix.protocol.injector.PacketConstructor;
|
||||
import com.comphenix.protocol.reflect.EquivalentConverter;
|
||||
import com.comphenix.protocol.reflect.StructureModifier;
|
||||
import com.comphenix.protocol.utility.MinecraftMethods;
|
||||
import com.comphenix.protocol.utility.MinecraftReflection;
|
||||
import com.comphenix.protocol.wrappers.BukkitConverters;
|
||||
import com.comphenix.protocol.wrappers.ChunkPosition;
|
||||
@ -65,6 +65,7 @@ import com.google.common.collect.Lists;
|
||||
|
||||
// Ensure that the CraftItemFactory is mockable
|
||||
@RunWith(org.powermock.modules.junit4.PowerMockRunner.class)
|
||||
@PowerMockIgnore({ "org.apache.log4j.*", "org.apache.logging.*", "org.bukkit.craftbukkit.libs.jline.*" })
|
||||
@PrepareForTest(CraftItemFactory.class)
|
||||
public class PacketContainerTest {
|
||||
// Helper converters
|
||||
|
@ -18,6 +18,7 @@ import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.invocation.InvocationOnMock;
|
||||
import org.mockito.stubbing.Answer;
|
||||
import org.powermock.core.classloader.annotations.PowerMockIgnore;
|
||||
import org.powermock.core.classloader.annotations.PrepareForTest;
|
||||
import com.comphenix.protocol.injector.PluginVerifier.VerificationResult;
|
||||
import com.google.common.base.Objects;
|
||||
@ -25,6 +26,7 @@ import com.google.common.collect.Lists;
|
||||
|
||||
// Damn final classes
|
||||
@RunWith(org.powermock.modules.junit4.PowerMockRunner.class)
|
||||
@PowerMockIgnore({ "org.apache.log4j.*", "org.apache.logging.*", "org.bukkit.craftbukkit.libs.jline.*" })
|
||||
@PrepareForTest(PluginDescriptionFile.class)
|
||||
public class PluginVerifierTest {
|
||||
@Test
|
||||
|
@ -16,6 +16,7 @@ import org.bukkit.inventory.ItemStack;
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.powermock.core.classloader.annotations.PowerMockIgnore;
|
||||
import org.powermock.core.classloader.annotations.PrepareForTest;
|
||||
|
||||
import com.comphenix.protocol.BukkitInitialization;
|
||||
@ -23,6 +24,7 @@ import com.comphenix.protocol.wrappers.nbt.NbtCompound;
|
||||
import com.comphenix.protocol.wrappers.nbt.NbtFactory;
|
||||
|
||||
@RunWith(org.powermock.modules.junit4.PowerMockRunner.class)
|
||||
@PowerMockIgnore({ "org.apache.log4j.*", "org.apache.logging.*", "org.bukkit.craftbukkit.libs.jline.*" })
|
||||
@PrepareForTest(CraftItemFactory.class)
|
||||
public class StreamSerializerTest {
|
||||
@BeforeClass
|
||||
|
@ -8,11 +8,13 @@ import org.bukkit.inventory.ItemStack;
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.powermock.core.classloader.annotations.PowerMockIgnore;
|
||||
import org.powermock.core.classloader.annotations.PrepareForTest;
|
||||
|
||||
import com.comphenix.protocol.BukkitInitialization;
|
||||
|
||||
@RunWith(org.powermock.modules.junit4.PowerMockRunner.class)
|
||||
@PowerMockIgnore({ "org.apache.log4j.*", "org.apache.logging.*", "org.bukkit.craftbukkit.libs.jline.*" })
|
||||
@PrepareForTest(CraftItemFactory.class)
|
||||
public class WrappedWatchableObjectTest {
|
||||
@BeforeClass
|
||||
|
@ -32,6 +32,7 @@ import org.bukkit.inventory.ItemStack;
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.powermock.core.classloader.annotations.PowerMockIgnore;
|
||||
import org.powermock.core.classloader.annotations.PrepareForTest;
|
||||
|
||||
import com.comphenix.protocol.BukkitInitialization;
|
||||
@ -39,6 +40,7 @@ import com.comphenix.protocol.utility.MinecraftReflection;
|
||||
import com.comphenix.protocol.wrappers.nbt.io.NbtBinarySerializer;
|
||||
|
||||
@RunWith(org.powermock.modules.junit4.PowerMockRunner.class)
|
||||
@PowerMockIgnore({ "org.apache.log4j.*", "org.apache.logging.*", "org.bukkit.craftbukkit.libs.jline.*" })
|
||||
@PrepareForTest(CraftItemFactory.class)
|
||||
public class NbtFactoryTest {
|
||||
@BeforeClass
|
||||
|
In neuem Issue referenzieren
Einen Benutzer sperren