diff --git a/pom.xml b/pom.xml
index 41ae5ba3d4..2ee0c93f03 100644
--- a/pom.xml
+++ b/pom.xml
@@ -111,10 +111,24 @@
jar
provided
+
junit
- junit
+ junit-dep
${junit.version}
+ test
+
+
+ hamcrest-core
+ org.hamcrest
+
+
+
+
+ org.hamcrest
+ hamcrest-library
+ 1.2.1
+ test
diff --git a/src/test/java/org/bukkit/AchievementTest.java b/src/test/java/org/bukkit/AchievementTest.java
new file mode 100644
index 0000000000..3492821c5f
--- /dev/null
+++ b/src/test/java/org/bukkit/AchievementTest.java
@@ -0,0 +1,41 @@
+package org.bukkit;
+
+import static org.hamcrest.Matchers.hasSize;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertThat;
+
+import java.util.List;
+
+import net.minecraft.server.Statistic;
+import net.minecraft.server.StatisticList;
+
+import org.bukkit.support.Util;
+import org.junit.Test;
+
+import com.google.common.collect.Lists;
+
+public class AchievementTest {
+ @Test
+ @SuppressWarnings("unchecked")
+ public void verifyMapping() throws IllegalArgumentException, SecurityException, IllegalAccessException, NoSuchFieldException {
+ List achievements = Lists.newArrayList(Achievement.values());
+
+ for (Statistic statistic : (List) StatisticList.b) {
+ int id = statistic.e;
+ String hash = statistic.g;
+
+ if ((id & Achievement.STATISTIC_OFFSET) != Achievement.STATISTIC_OFFSET) continue;
+ if (hash == null) continue;
+
+ String name = Util.getInternalState(Statistic.class, statistic, "a");
+ String message = String.format("org.bukkit.Achievement is missing id: %d named: '%s'", id - Achievement.STATISTIC_OFFSET, name);
+
+ Achievement subject = Achievement.getById(id);
+ assertNotNull(message, subject);
+
+ achievements.remove(subject);
+ }
+
+ assertThat("org.bukkit.Achievement has too many achievements", achievements, hasSize(0));
+ }
+}
diff --git a/src/test/java/org/bukkit/ArtTest.java b/src/test/java/org/bukkit/ArtTest.java
new file mode 100644
index 0000000000..2b44537004
--- /dev/null
+++ b/src/test/java/org/bukkit/ArtTest.java
@@ -0,0 +1,43 @@
+package org.bukkit;
+
+import static org.hamcrest.CoreMatchers.is;
+import static org.hamcrest.Matchers.hasSize;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertThat;
+
+import java.util.List;
+
+import net.minecraft.server.EnumArt;
+
+import org.junit.Test;
+
+import com.google.common.collect.Lists;
+
+public class ArtTest {
+ private static final int UNIT_MULTIPLIER = 16;
+
+ @Test
+ public void verifyMapping() {
+ List arts = Lists.newArrayList(Art.values());
+
+ for (EnumArt enumArt : EnumArt.values()) {
+ int id = enumArt.ordinal();
+ String name = enumArt.A;
+ int width = enumArt.B / UNIT_MULTIPLIER;
+ int height = enumArt.C / UNIT_MULTIPLIER;
+
+ Art subject = Art.getById(id);
+
+ String message = String.format("org.bukkit.Art is missing id: %d named: '%s'", id - Achievement.STATISTIC_OFFSET, name);
+ assertNotNull(message, subject);
+
+ assertThat(Art.getByName(name), is(subject));
+ assertThat("Art." + subject + "'s width", subject.getBlockWidth(), is(width));
+ assertThat("Art." + subject + "'s height", subject.getBlockHeight(), is(height));
+
+ arts.remove(subject);
+ }
+
+ assertThat("org.bukkit.Art has too many arts", arts, hasSize(0));
+ }
+}
diff --git a/src/test/java/org/bukkit/MaterialTest.java b/src/test/java/org/bukkit/MaterialTest.java
new file mode 100644
index 0000000000..f4464fd884
--- /dev/null
+++ b/src/test/java/org/bukkit/MaterialTest.java
@@ -0,0 +1,68 @@
+package org.bukkit;
+
+import static org.hamcrest.CoreMatchers.is;
+import static org.hamcrest.Matchers.hasSize;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertThat;
+
+import java.util.Map;
+
+import net.minecraft.server.Item;
+import net.minecraft.server.ItemFood;
+
+import org.bukkit.support.AbstractTestingBase;
+import org.junit.Test;
+
+import com.google.common.collect.Maps;
+
+public class MaterialTest extends AbstractTestingBase {
+ @Test
+ public void verifyMapping() {
+ Map materials = Maps.newHashMap();
+ for (Material material : Material.values()) {
+ materials.put(material.getId(), material);
+ }
+ materials.remove(0); // Purge air.
+
+ for (Item item : Item.byId) {
+ if (item == null) continue;
+
+ int id = item.id;
+ String name = item.getName();
+ int maxStackSize = item.getMaxStackSize();
+ int maxDurability = item.getMaxDurability();
+
+ Material material = materials.remove(id);
+
+ assertNotNull(String.format("org.bukkit.Material is missing id: %d named: %s", id, name), material);
+
+ assertThat(String.format("org.bukkit.Material.%s maxStackSize:", material), material.getMaxStackSize(), is(maxStackSize));
+ assertThat(String.format("org.bukkit.Material.%s maxDurability:", material), material.getMaxDurability(), is((short) maxDurability));
+ }
+
+ assertThat("org.bukkit.Material has too many entries", materials.values(), hasSize(0));
+ }
+
+ @Test
+ public void verifyIsEdible() {
+ Map materials = Maps.newHashMap();
+ for (Material material : Material.values()) {
+ if (!material.isEdible()) continue;
+ materials.put(material.getId(), material);
+ }
+
+ for (Item item : Item.byId) {
+ if (item == null) continue;
+ if (!(item instanceof ItemFood)) continue;
+
+ int id = item.id;
+ String name = item.getName();
+
+ Material material = materials.remove(id);
+
+ assertNotNull(String.format("org.bukkit.Material does not list id: %d named: %s edible", id, name), material);
+ }
+
+ assertThat("org.bukkit.Material has entries marked edible that are not ItemFood", materials.values(), hasSize(0));
+ }
+}
diff --git a/src/test/java/org/bukkit/support/AbstractTestingBase.java b/src/test/java/org/bukkit/support/AbstractTestingBase.java
new file mode 100644
index 0000000000..ca14db9bd8
--- /dev/null
+++ b/src/test/java/org/bukkit/support/AbstractTestingBase.java
@@ -0,0 +1,21 @@
+package org.bukkit.support;
+
+import net.minecraft.server.StatisticList;
+
+import org.junit.BeforeClass;
+
+/**
+ * If you are getting: java.lang.ExceptionInInitializerError
+ * at net.minecraft.server.StatisticList.(SourceFile:58)
+ * at net.minecraft.server.Item.(SourceFile:252)
+ * at net.minecraft.server.Block.(Block.java:577)
+ *
+ * extend this class to solve it.
+ */
+public abstract class AbstractTestingBase {
+
+ @BeforeClass
+ public static void setup() {
+ StatisticList.a();
+ }
+}
\ No newline at end of file
diff --git a/src/test/java/org/bukkit/support/Util.java b/src/test/java/org/bukkit/support/Util.java
new file mode 100644
index 0000000000..2f24d9a408
--- /dev/null
+++ b/src/test/java/org/bukkit/support/Util.java
@@ -0,0 +1,31 @@
+package org.bukkit.support;
+
+import java.lang.reflect.Field;
+
+public class Util {
+ /*
+ public static T getInternalState(Object object, String fieldName) {
+ return getInternalState(object.getClass(), object, fieldName);
+ }
+ */
+
+ @SuppressWarnings("unchecked")
+ public static T getInternalState(Class> clazz, Object object, String fieldName) {
+ Field field;
+ try {
+ field = clazz.getDeclaredField(fieldName);
+ } catch (SecurityException e) {
+ throw new RuntimeException("Not allowed to access " + clazz, e);
+ } catch (NoSuchFieldException e) {
+ throw new RuntimeException("Unable to find field " + fieldName, e);
+ }
+
+ field.setAccessible(true);
+ try {
+ return (T) field.get(object);
+ } catch (IllegalArgumentException e) {
+ } catch (IllegalAccessException e) {
+ }
+ throw new RuntimeException("Unable to get internal value");
+ }
+}