Package com.comphenix.protocol.events

Source Code of com.comphenix.protocol.events.PacketContainerTest

/*
*  ProtocolLib - Bukkit server library that allows access to the Minecraft protocol.
*  Copyright (C) 2012 Kristian S. Stangeland
*
*  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 2 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, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
*  02111-1307 USA
*/

package com.comphenix.protocol.events;

import static org.junit.Assert.*;
import java.lang.reflect.Array;
import java.util.List;
import java.util.UUID;

import net.minecraft.server.v1_7_R3.AttributeModifier;
import net.minecraft.server.v1_7_R3.AttributeSnapshot;
import net.minecraft.server.v1_7_R3.PacketPlayOutUpdateAttributes;

import org.apache.commons.lang.SerializationUtils;
import org.apache.commons.lang.builder.ToStringBuilder;
import org.apache.commons.lang.builder.ToStringStyle;
// Will have to be updated for every version though
import org.bukkit.craftbukkit.v1_7_R3.inventory.CraftItemFactory;

import org.bukkit.ChatColor;
import org.bukkit.Material;
import org.bukkit.WorldType;
import org.bukkit.inventory.ItemStack;
import org.bukkit.potion.PotionEffect;
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;
import com.comphenix.protocol.PacketType;
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.MinecraftReflection;
import com.comphenix.protocol.wrappers.BukkitConverters;
import com.comphenix.protocol.wrappers.ChunkPosition;
import com.comphenix.protocol.wrappers.WrappedChatComponent;
import com.comphenix.protocol.wrappers.WrappedDataWatcher;
import com.comphenix.protocol.wrappers.WrappedGameProfile;
import com.comphenix.protocol.wrappers.WrappedWatchableObject;
import com.comphenix.protocol.wrappers.nbt.NbtCompound;
import com.comphenix.protocol.wrappers.nbt.NbtFactory;

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
  private EquivalentConverter<WrappedDataWatcher> watchConvert = BukkitConverters.getDataWatcherConverter();
  private EquivalentConverter<ItemStack> itemConvert = BukkitConverters.getItemStackConverter();
 
  @BeforeClass
  public static void initializeBukkit() throws IllegalAccessException {
    BukkitInitialization.initializeItemMeta();
  }
 
  private <T> void testPrimitive(StructureModifier<T> modifier, int index, T initialValue, T testValue) {
    // Check initial value
    assertEquals(initialValue, modifier.read(index));

    // Test assignment
    modifier.write(index, testValue);
    assertEquals(testValue, modifier.read(0));
  }
 
  private <T> void testObjectArray(StructureModifier<T[]> modifier, int index, T[] initialValue, T[] testValue) {
    // Check initial value
    assertNull(modifier.read(index));
    modifier.writeDefaults();

    // Test initial
    assertArrayEquals(initialValue, modifier.read(index));
   
    // Test assignment
    modifier.write(index, testValue);
    assertArrayEquals(testValue, modifier.read(0));
  }

  @Test
  public void testGetByteArrays() {
    // Contains a byte array we will test
    PacketContainer customPayload = new PacketContainer(PacketType.Play.Server.CUSTOM_PAYLOAD);
    StructureModifier<byte[]> bytes = customPayload.getByteArrays();
    byte[] testArray = new byte[] { 1, 2, 3 };
   
    // It's NULL at first
    assertArrayEquals(null, (byte[]) bytes.read(0));
    customPayload.getModifier().writeDefaults();
   
    // Then it should create an empty array
    assertArrayEquals(new byte[0], (byte[]) bytes.read(0));
   
    // Check and see if we can write to it
    bytes.write(0, testArray);
    assertArrayEquals(testArray, (byte[]) bytes.read(0));
  }
 
  @Test
  public void testGetBytes() {
    PacketContainer spawnMob = new PacketContainer(PacketType.Play.Server.SPAWN_ENTITY_LIVING);
    testPrimitive(spawnMob.getBytes(), 0, (byte)0, (byte)1);
  }
 
  @Test
  public void testGetShorts() {
    PacketContainer itemData = new PacketContainer(PacketType.Play.Server.TRANSACTION);
    testPrimitive(itemData.getShorts(), 0, (short)0, (short)1);
  }

  @Test
  public void testGetIntegers() {
    PacketContainer updateSign = new PacketContainer(PacketType.Play.Server.UPDATE_SIGN);
    testPrimitive(updateSign.getIntegers(), 0, (int)0, (int)1);
  }

  @Test
  public void testGetLongs() {
    PacketContainer updateTime = new PacketContainer(PacketType.Play.Server.UPDATE_TIME);
    testPrimitive(updateTime.getLongs(), 0, (long)0, (long)1);
  }

  @Test
  public void testGetFloat() {
    PacketContainer explosion = new PacketContainer(PacketType.Play.Server.EXPLOSION);
    testPrimitive(explosion.getFloat(), 0, (float)0, (float)0.8);
  }

  @Test
  public void testGetDoubles() {
    PacketContainer explosion = new PacketContainer(PacketType.Play.Server.EXPLOSION);
    testPrimitive(explosion.getDoubles(), 0, (double)0, (double)0.8);
  }

  @Test
  public void testGetStrings() {
    PacketContainer explosion = new PacketContainer(PacketType.Play.Client.CHAT);
    testPrimitive(explosion.getStrings(), 0, null, "hello");
  }

  @Test
  public void testGetStringArrays() {
    PacketContainer explosion = new PacketContainer(PacketType.Play.Server.UPDATE_SIGN);
    testObjectArray(explosion.getStringArrays(), 0, new String[0], new String[] { "hello", "world" });
  }

  @Test
  public void testGetIntegerArrays() {
    // Contains a byte array we will test
    PacketContainer mapChunkBulk = new PacketContainer(PacketType.Play.Server.MAP_CHUNK_BULK);
    StructureModifier<int[]> integers = mapChunkBulk.getIntegerArrays();
    int[] testArray = new int[] { 1, 2, 3 };
   
    // Pre and post conditions
    assertArrayEquals(null, (int[]) integers.read(0));
    mapChunkBulk.getModifier().writeDefaults();
    assertArrayEquals(new int[0], (int[]) integers.read(0));
   
    integers.write(0, testArray);
    assertArrayEquals(testArray, (int[]) integers.read(0));
  }

  @Test
  public void testGetItemModifier() {
    PacketContainer windowClick = new PacketContainer(PacketType.Play.Client.WINDOW_CLICK);
   
    StructureModifier<ItemStack> items = windowClick.getItemModifier();
    ItemStack goldAxe = new ItemStack(Material.GOLD_AXE);
   
    assertNotNull(goldAxe.getType());
    assertNull(items.read(0));
   
    // Insert the goldaxe and check if it's there
    items.write(0, goldAxe);
    assertTrue("Item " + goldAxe + " != " + items.read(0), equivalentItem(goldAxe, items.read(0)));
  }
  @Test
  public void testGetItemArrayModifier() {
    PacketContainer windowItems = new PacketContainer(PacketType.Play.Server.WINDOW_ITEMS);
    StructureModifier<ItemStack[]> itemAccess = windowItems.getItemArrayModifier();
   
    ItemStack[] itemArray = new ItemStack[] {
        new ItemStack(Material.GOLD_AXE),
        new ItemStack(Material.DIAMOND_AXE)
    };
   
    assertNull(itemAccess.read(0));
   
    // Insert and check that it was succesful
    itemAccess.write(0, itemArray);
   
    // Read back array
    ItemStack[] comparision = itemAccess.read(0);
    assertEquals(itemArray.length, comparision.length);
   
    // Check that it is equivalent
    for (int i = 0; i < itemArray.length; i++) {
      assertTrue(String.format("Array element %s is not the same: %s != %s",
            i, itemArray[i], comparision[i]), equivalentItem(itemArray[i], comparision[i]));
    }
  }
 
  private boolean equivalentItem(ItemStack first, ItemStack second) {
    if (first == null) {
      return second == null;
    } else if (second == null) {
      return false;
    } else {
      return first.getType().equals(second.getType());
    }
  }
 
  @Test
  public void testGetWorldTypeModifier() {
    // Not used in Netty
    if (MinecraftReflection.isUsingNetty())
      return;
   
    PacketContainer loginPacket = new PacketContainer(PacketType.Play.Server.LOGIN);
    StructureModifier<WorldType> worldAccess = loginPacket.getWorldTypeModifier();
   
    WorldType testValue = WorldType.LARGE_BIOMES;
   
    assertNull(worldAccess.read(0));
   
    // Insert and read back
    worldAccess.write(0, testValue);
    assertEquals(testValue, worldAccess.read(0));
  }

  @Test
  public void testGetNbtModifier() {
    PacketContainer updateTileEntity = new PacketContainer(PacketType.Play.Server.TILE_ENTITY_DATA);
   
    NbtCompound compound = NbtFactory.ofCompound("test");
    compound.put("test", "name");
    compound.put(NbtFactory.ofList("ages", 1, 2, 3));
   
    updateTileEntity.getNbtModifier().write(0, compound);
   
    NbtCompound result = (NbtCompound) updateTileEntity.getNbtModifier().read(0);
   
    assertEquals(compound.getString("test"), result.getString("test"));
    assertEquals(compound.getList("ages"), result.getList("ages"));
  }
 
  @Test
  public void testGetDataWatcherModifier() {
    PacketContainer mobSpawnPacket = new PacketContainer(PacketType.Play.Server.SPAWN_ENTITY_LIVING);
    StructureModifier<WrappedDataWatcher> watcherAccessor = mobSpawnPacket.getDataWatcherModifier();
       
    WrappedDataWatcher dataWatcher = new WrappedDataWatcher();
    dataWatcher.setObject(1, 100);
    dataWatcher.setObject(2, 125);
   
    assertNull(watcherAccessor.read(0));
   
    // Insert and read back
    watcherAccessor.write(0, dataWatcher);
    assertEquals(dataWatcher, watcherAccessor.read(0));
  }

  // Unfortunately, it might be too difficult to mock this one
  //
  //  @Test
  //  public void testGetEntityModifier() { }

  // No packet expose this type directly.
  //
  //  @Test
  //  public void testGetPositionModifier() { }

  @Test
  public void testGetPositionCollectionModifier() {
    PacketContainer explosionPacket = new PacketContainer(PacketType.Play.Server.EXPLOSION);
    StructureModifier<List<ChunkPosition>> positionAccessor = explosionPacket.getPositionCollectionModifier();
   
    assertNull(positionAccessor.read(0));
   
    List<ChunkPosition> positions = Lists.newArrayList();
    positions.add(new ChunkPosition(1, 2, 3));
    positions.add(new ChunkPosition(3, 4, 5));
 
    // Insert and read back
    positionAccessor.write(0, positions);
    List<ChunkPosition> cloned = positionAccessor.read(0);
   
    assertEquals(positions, cloned);
  }

  @Test
  public void testGetWatchableCollectionModifier() {
    PacketContainer entityMetadata = new PacketContainer(PacketType.Play.Server.ENTITY_METADATA);
    StructureModifier<List<WrappedWatchableObject>> watchableAccessor =
        entityMetadata.getWatchableCollectionModifier();
   
    assertNull(watchableAccessor.read(0));
   
    WrappedDataWatcher watcher = new WrappedDataWatcher();
    watcher.setObject(1, 10);
    watcher.setObject(8, 10);
   
    List<WrappedWatchableObject> list = watcher.getWatchableObjects();
   
    // Insert and read back
    watchableAccessor.write(0, list);
    assertEquals(list, watchableAccessor.read(0));
  }
 
  @Test
  public void testGameProfiles() {
    PacketContainer spawnEntity = new PacketContainer(PacketType.Play.Server.NAMED_ENTITY_SPAWN);
    WrappedGameProfile profile = new WrappedGameProfile("d7047a08-3150-4aa8-a2f2-7c1e2b17e298", "name");
    spawnEntity.getGameProfiles().write(0, profile);
   
    assertEquals(profile, spawnEntity.getGameProfiles().read(0));
  }
 
  @Test
  public void testChatComponents() {
    PacketContainer chatPacket = new PacketContainer(PacketType.Play.Server.CHAT);
    chatPacket.getChatComponents().write(0,
        WrappedChatComponent.fromChatMessage("You shall not " + ChatColor.ITALIC + "pass!")[0]);
   
    assertEquals("{\"extra\":[\"You shall not \",{\"italic\":true,\"text\":\"pass!\"}],\"text\":\"\"}",
             chatPacket.getChatComponents().read(0).getJson());
  }
 
  @Test
  public void testSerialization() {
    PacketContainer chat = new PacketContainer(PacketType.Play.Client.CHAT);
    chat.getStrings().write(0, "Test");
   
    PacketContainer copy = (PacketContainer) SerializationUtils.clone(chat);
   
    assertEquals(PacketType.Play.Client.CHAT, copy.getType());
    assertEquals("Test", copy.getStrings().read(0));
  }
 
  @Test
  public void testAttributeList() {
    PacketContainer attribute = new PacketContainer(PacketType.Play.Server.UPDATE_ATTRIBUTES);
    attribute.getIntegers().write(0, 123); // Entity ID
   
    // Initialize some test data
    List<AttributeModifier> modifiers = Lists.newArrayList(
      new AttributeModifier(UUID.randomUUID(), "Unknown synced attribute modifier", 10, 0));
    AttributeSnapshot snapshot = new AttributeSnapshot(
        (PacketPlayOutUpdateAttributes) attribute.getHandle(), "generic.Maxhealth", 20.0, modifiers);
   
    attribute.getSpecificModifier(List.class).write(0, Lists.newArrayList(snapshot));
    PacketContainer cloned = attribute.deepClone();
    AttributeSnapshot clonedSnapshot = (AttributeSnapshot) cloned.getSpecificModifier(List.class).read(0).get(0);
   
    assertEquals(
        ToStringBuilder.reflectionToString(snapshot, ToStringStyle.SHORT_PREFIX_STYLE),
        ToStringBuilder.reflectionToString(clonedSnapshot, ToStringStyle.SHORT_PREFIX_STYLE));
  }
 
  @Test
  public void testBlocks() {
    PacketContainer blockAction = new PacketContainer(PacketType.Play.Server.BLOCK_ACTION);
    blockAction.getBlocks().write(0, Material.STONE);
   
    assertEquals(Material.STONE, blockAction.getBlocks().read(0));
  }

  @SuppressWarnings("deprecation")
  @Test
  public void testPotionEffect() {
    PotionEffect effect = new PotionEffect(PotionEffectType.FIRE_RESISTANCE, 20 * 60, 1);
   
    // The constructor we want to call
    PacketConstructor creator = PacketConstructor.DEFAULT.withPacket(
        PacketType.Play.Server.ENTITY_EFFECT, new Class<?>[] { int.class, PotionEffect.class });
    PacketContainer packet = creator.createPacket(1, effect);
   
    assertEquals(1, (int) packet.getIntegers().read(0));
    assertEquals(effect.getType().getId(), (byte) packet.getBytes().read(0));
    assertEquals(effect.getAmplifier(), (byte) packet.getBytes().read(1));
    assertEquals(effect.getDuration(), (short) packet.getShorts().read(0));
  }
 
  @Test
  public void testDeepClone() {
    // Try constructing all the packets
    for (PacketType type : PacketType.values()) {
      // Whether or not this packet has been registered
      boolean registered = type.isSupported();
     
      try {
        PacketContainer constructed = new PacketContainer(type);
     
        if (!registered) {
          fail("Expected IllegalArgumentException(Packet " + type + " not registered");
        }
         
        // Initialize default values
        constructed.getModifier().writeDefaults();
       
        // Clone the packet
        PacketContainer cloned = constructed.deepClone();
       
        // Make sure they're equivalent
        StructureModifier<Object> firstMod = constructed.getModifier(), secondMod = cloned.getModifier();
        assertEquals(firstMod.size(), secondMod.size());

        if (PacketType.Status.Server.OUT_SERVER_INFO.equals(type)) {
          assertArrayEquals(SerializationUtils.serialize(constructed), SerializationUtils.serialize(cloned));

        } else {
          // Make sure all the fields are equivalent
          for (int i = 0; i < firstMod.size(); i++) {
            if (firstMod.getField(i).getType().isArray())
              assertArrayEquals(getArray(firstMod.read(i)), getArray(secondMod.read(i)));
            else
              testEquality(firstMod.read(i), secondMod.read(i));
          }
        }
       
      } catch (IllegalArgumentException e) {
        if (!registered) {
          // Check the same
          assertEquals(e.getMessage(), "The packet ID " + type + " is not registered.");
        } else {
          // Something is very wrong
          throw e;
        }
      }
    }
  }
 
  @Test
  public void testPacketType() {
    assertEquals(PacketType.Legacy.Server.SET_CREATIVE_SLOT, PacketType.findLegacy(107, Sender.SERVER));
  }
 
  // Convert to objects that support equals()
  private void testEquality(Object a, Object b) {
    if (a != null && b != null) {
      if (MinecraftReflection.isDataWatcher(a)) {
        a = watchConvert.getSpecific(a);
        b = watchConvert.getSpecific(b);
      } else if (MinecraftReflection.isItemStack(a)) {
        a = itemConvert.getSpecific(a);
        b = itemConvert.getSpecific(b);
      }
    }
   
    assertEquals(a, b);
  }
 
  /**
   * Get the underlying array as an object array.
   * @param val - array wrapped as an Object.
   * @return An object array.
   */
  private Object[] getArray(Object val) {
    if (val instanceof Object[])
      return (Object[]) val;
    if (val == null)
      return null;

    int arrlength = Array.getLength(val);
    Object[] outputArray = new Object[arrlength];
    for (int i = 0; i < arrlength; ++i)
      outputArray[i] = Array.get(val, i);
    return outputArray;
  }
}
TOP

Related Classes of com.comphenix.protocol.events.PacketContainerTest

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.