MobArena/src/test/java/com/garbagemule/MobArena/formula/FormulaManagerIT.java

447 lines
12 KiB
Java

package com.garbagemule.MobArena.formula;
import com.garbagemule.MobArena.MonsterManager;
import com.garbagemule.MobArena.framework.Arena;
import com.garbagemule.MobArena.waves.WaveManager;
import org.bukkit.entity.LivingEntity;
import org.bukkit.entity.Player;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
import org.junit.experimental.runners.Enclosed;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import org.junit.runners.Parameterized.Parameters;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;
import static org.hamcrest.CoreMatchers.*;
import static org.hamcrest.MatcherAssert.*;
import static org.junit.Assert.assertThrows;
import static org.mockito.Mockito.*;
@RunWith(Enclosed.class)
public class FormulaManagerIT {
static Arena arena;
static FormulaManager subject;
static int finalWave = 13;
static int currentWave = finalWave - 2;
static int liveMonsters = 9;
static int initialPlayers = 7;
static int livePlayers = initialPlayers - 2;
static int deadPlayers = initialPlayers - livePlayers;
static int minPlayers = 3;
static int maxPlayers = initialPlayers + 3;
@BeforeClass
public static void setup() {
arena = mock(Arena.class);
WaveManager wm = mock(WaveManager.class);
when(wm.getWaveNumber()).thenReturn(currentWave);
when(wm.getFinalWave()).thenReturn(finalWave);
when(arena.getWaveManager()).thenReturn(wm);
Set<LivingEntity> monsters = new HashSet<>();
for (int i = 0; i < liveMonsters; i++) {
monsters.add(mock(LivingEntity.class));
}
MonsterManager mm = mock(MonsterManager.class);
when(mm.getMonsters()).thenReturn(monsters);
when(arena.getMonsterManager()).thenReturn(mm);
Set<Player> players = new HashSet<>();
for (int i = 0; i < livePlayers; i++) {
players.add(mock(Player.class));
}
when(arena.getPlayersInArena()).thenReturn(players);
when(arena.getPlayerCount()).thenReturn(initialPlayers);
when(arena.getMinPlayers()).thenReturn(minPlayers);
when(arena.getMaxPlayers()).thenReturn(maxPlayers);
subject = FormulaManager.createDefault();
}
@RunWith(Parameterized.class)
public static class NumberLiterals {
@Parameters(name = "{0}")
public static Iterable<Object[]> data() {
return Arrays.asList(new Object[][]{
{"0"},
{"1"},
{"-1"},
{"1337"},
{"3.14"},
{"1e4"},
{"-1e4"},
{"1e-4"},
{"-1e-4"},
});
}
String input;
double expected;
public NumberLiterals(String input) {
this.input = input;
this.expected = Double.parseDouble(input);
}
@Test
public void test() {
Formula formula = subject.parse(input);
double result = formula.evaluate(arena);
assertThat(result, equalTo(expected));
}
}
@RunWith(Parameterized.class)
public static class DefaultConstants {
@Parameters(name = "{0} = {1}")
public static Iterable<Object[]> data() {
return Arrays.asList(new Object[][]{
{"pi", Math.PI},
{"e", Math.E},
{"pi^e", Math.pow(Math.PI, Math.E)},
});
}
String input;
double expected;
public DefaultConstants(String input, double expected) {
this.input = input;
this.expected = expected;
}
@Test
public void test() {
Formula formula = subject.parse(input);
double result = formula.evaluate(arena);
assertThat(result, equalTo(expected));
}
}
/**
* With custom constants, we are manipulating the internal
* state of the manager, so we need to use a local subject.
*/
public static class CustomConstants {
FormulaManager subject;
@Before
public void setup() {
subject = FormulaManager.createDefault();
}
@Test
public void resolveRegisteredCustomConstant() {
subject.registerConstant("pie", 3.14);
Formula formula = subject.parse("pie * 2");
double result = formula.evaluate(arena);
double expected = 6.28;
assertThat(result, equalTo(expected));
}
}
@RunWith(Parameterized.class)
public static class DefaultVariables {
@Parameters(name = "{0} = {1}")
public static Iterable<Object[]> data() {
return Arrays.asList(new Object[][]{
{"<current-wave>", currentWave},
{"<final-wave>", finalWave},
{"<initial-players>", initialPlayers},
{"<live-players>", livePlayers},
{"<dead-players>", deadPlayers},
{"<min-players>", minPlayers},
{"<max-players>", maxPlayers},
{"<live-monsters>", liveMonsters},
});
}
String input;
double expected;
public DefaultVariables(String input, double expected) {
this.input = input;
this.expected = expected;
}
@Test
public void test() {
Formula formula = subject.parse(input);
double result = formula.evaluate(arena);
assertThat(result, equalTo(expected));
}
}
/**
* With custom variables, we are manipulating the internal
* state of the manager, so we need to use a local subject.
*/
public static class CustomVariables {
FormulaManager subject;
@Before
public void setup() {
subject = FormulaManager.createDefault();
}
@Test
public void resolveRegisteredCustomVariable() {
subject.registerVariable("bob", a -> 7.5);
Formula formula = subject.parse("2.5 + <bob>");
double result = formula.evaluate(arena);
double expected = 10;
assertThat(result, equalTo(expected));
}
@Test
public void throwsOnUnknownCustomVariable() {
assertThrows(
UnknownToken.class,
() -> subject.parse("2 + <bob>")
);
}
}
@RunWith(Parameterized.class)
public static class DefaultUnaryOperators {
@Parameters(name = "{0} = {1}")
public static Iterable<Object[]> data() {
return Arrays.asList(new Object[][]{
{"1 + +1.2", 1 + 1.2},
{"1 + -1.2", 1 + (-1.2)},
});
}
String input;
double expected;
public DefaultUnaryOperators(String input, double expected) {
this.input = input;
this.expected = expected;
}
@Test
public void test() {
Formula formula = subject.parse(input);
double result = formula.evaluate(arena);
assertThat(result, equalTo(expected));
}
}
@RunWith(Parameterized.class)
public static class DefaultOperators {
@Parameters(name = "{0} = {1}")
public static Iterable<Object[]> data() {
return Arrays.asList(new Object[][]{
{"1+-2", 1 + (-2)},
{"3-+4", 3 - 4},
{"3*7.5", 3 * 7.5},
{"10/2.5", 10 / 2.5},
{"9%4", 9 % 4},
{"2^-8", Math.pow(2, -8)},
{"-2^-8", -Math.pow(2, -8)},
{"(-2)^-8", Math.pow(-2, -8)},
});
}
String input;
double expected;
public DefaultOperators(String input, double expected) {
this.input = input;
this.expected = expected;
}
@Test
public void test() {
Formula formula = subject.parse(input);
double result = formula.evaluate(arena);
assertThat(result, equalTo(expected));
}
}
/**
* With custom operators, we are manipulating the internal
* state of the manager, so we need to use a local subject.
*/
public static class CustomOperators {
FormulaManager subject;
@Before
public void setup() {
subject = FormulaManager.createDefault();
}
@Test
public void resolveRegisteredCustomUnaryOperator() {
subject.registerUnaryOperator("_", 1, a -> a - 1);
Formula formula = subject.parse("_(1 + 1)");
double result = formula.evaluate(arena);
double expected = 1;
assertThat(result, equalTo(expected));
}
@Test
public void resolveRegisteredCustomBinaryOperator1() {
subject.registerBinaryOperator("?", 1, true, (a, b) -> (a >= 0) ? a : b);
Formula formula = subject.parse("5 ? 6");
double result = formula.evaluate(arena);
double expected = 5;
assertThat(result, equalTo(expected));
}
@Test
public void resolveRegisteredCustomBinaryOperator2() {
subject.registerBinaryOperator("?", 1, true, (a, b) -> (a >= 0) ? a : b);
Formula formula = subject.parse("(5 - 10) ? (3 + 3)");
double result = formula.evaluate(arena);
double expected = 6;
assertThat(result, equalTo(expected));
}
}
@RunWith(Parameterized.class)
public static class DefaultUnaryFunctions {
@Parameters(name = "{0} = {1}")
public static Iterable<Object[]> data() {
return Arrays.asList(new Object[][]{
{"sqrt(4)", 2},
{"sqrt(9)", 3},
{"abs(2)", 2},
{"abs(-2)", 2},
{"ceil(8.2)", 9},
{"ceil(8.7)", 9},
{"floor(8.2)", 8},
{"floor(8.7)", 8},
{"round(8.2)", 8},
{"round(8.7)", 9},
{"sin(pi / 2)", Math.sin(Math.PI / 2)},
{"cos(pi / 3)", Math.cos(Math.PI / 3)},
{"tan(pi / 4)", Math.tan(Math.PI / 4)},
});
}
String input;
double expected;
public DefaultUnaryFunctions(String input, double expected) {
this.input = input;
this.expected = expected;
}
@Test
public void test() {
Formula formula = subject.parse(input);
double result = formula.evaluate(arena);
assertThat(result, equalTo(expected));
}
}
@RunWith(Parameterized.class)
public static class DefaultBinaryFunctions {
@Parameters(name = "{0} = {1}")
public static Iterable<Object[]> data() {
return Arrays.asList(new Object[][]{
{"min(1, 2)", 1},
{"min(2, 1)", 1},
{"max(1, 2)", 2},
{"max(2, 1)", 2},
});
}
String input;
double expected;
public DefaultBinaryFunctions(String input, double expected) {
this.input = input;
this.expected = expected;
}
@Test
public void test() {
Formula formula = subject.parse(input);
double result = formula.evaluate(arena);
assertThat(result, equalTo(expected));
}
}
/**
* With custom functions, we are manipulating the internal
* state of the manager, so we need to use a local subject.
*/
public static class CustomFunctions {
FormulaManager subject;
@Before
public void setup() {
subject = FormulaManager.createDefault();
}
@Test
public void resolveRegisteredCustomFunctions() {
subject.registerUnaryFunction("flip", a -> -a);
subject.registerBinaryFunction("car", (a, b) -> a);
subject.registerBinaryFunction("cdr", (a, b) -> b);
Formula formula = subject.parse("flip(car(1, 2) + cdr(3, 4))");
double result = formula.evaluate(arena);
double expected = -(1 + 4);
assertThat(result, equalTo(expected));
}
@Test
public void throwsOnUnknownCustomFunction() {
assertThrows(
UnknownToken.class,
() -> subject.parse("flip(1)")
);
}
}
}