Skip to content

Commit 94aec78

Browse files
author
Jasper Geurtz
committed
Add unit tests for BWAPI 4.4.0 alignment fixes
1 parent e3fe0fd commit 94aec78

8 files changed

Lines changed: 398 additions & 57 deletions

File tree

‎src/main/java/bwapi/BuildingPlacer.java‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -284,6 +284,8 @@ static void ReserveDefault(final PlacementReserve reserve, final UnitType type,
284284
}
285285
}
286286

287+
// Note: In C++ BWAPI 4.4.0 (Game.cpp), this loop calls reserve.setValue(p, 0) instead of
288+
// reserve.setValue(x, y, 0), which makes the loop a no-op since reserve is already 0 wherever original is 0.
287289
switch (type) {
288290
case Terran_Barracks:
289291
case Terran_Factory:

‎src/main/java/bwapi/Game.java‎

Lines changed: 57 additions & 57 deletions
Large diffs are not rendered by default.
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
package bwapi;
2+
3+
import org.junit.Test;
4+
5+
import static org.junit.Assert.assertFalse;
6+
import static org.junit.Assert.assertTrue;
7+
import static org.mockito.Mockito.mock;
8+
import static org.mockito.Mockito.when;
9+
10+
public class BulletTest {
11+
12+
@Test
13+
public void isVisibleShouldFallbackToAnyPlayerWhenSelfIsNullAndCheckValidPlayerId() {
14+
Game game = mock(Game.class);
15+
when(game.self()).thenReturn(null);
16+
17+
ClientData.BulletData bulletData = mock(ClientData.BulletData.class);
18+
Bullet bullet = new Bullet(bulletData, 0, game);
19+
20+
assertFalse(bullet.isVisible());
21+
22+
when(bulletData.isVisible(2)).thenReturn(true);
23+
assertTrue(bullet.isVisible());
24+
assertTrue(bullet.isVisible(null));
25+
26+
ClientData.PlayerData neutralData = mock(ClientData.PlayerData.class);
27+
when(neutralData.getName()).thenReturn("Neutral");
28+
Player neutral = new Player(neutralData, 11, game);
29+
when(bulletData.isVisible(11)).thenReturn(true);
30+
assertFalse(bullet.isVisible(neutral));
31+
}
32+
}
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
package bwapi;
2+
3+
import org.junit.Test;
4+
5+
import java.util.Collections;
6+
7+
import static org.junit.Assert.assertEquals;
8+
import static org.mockito.Mockito.doReturn;
9+
import static org.mockito.Mockito.mock;
10+
import static org.mockito.Mockito.spy;
11+
import static org.mockito.Mockito.when;
12+
13+
public class CommandTempTest {
14+
15+
@Test
16+
public void upgradeShouldSubtractGasInsteadOfAdding() {
17+
Game game = spy(new Game());
18+
doReturn(10).when(game).getFrameCount();
19+
20+
ClientData.PlayerData playerData = mock(ClientData.PlayerData.class);
21+
when(playerData.getName()).thenReturn("Self");
22+
when(playerData.getMinerals()).thenReturn(500);
23+
when(playerData.getGas()).thenReturn(500);
24+
Player player = new Player(playerData, 0, game);
25+
26+
Unit unit = spy(new Unit(mock(ClientData.UnitData.class), 0, game));
27+
doReturn(true).when(unit).exists();
28+
doReturn(player).when(unit).getPlayer();
29+
30+
UpgradeType upgrade = UpgradeType.Terran_Infantry_Weapons;
31+
CommandTemp cmd = new CommandTemp(UnitCommand.upgrade(unit, upgrade), game);
32+
cmd.execute(false);
33+
34+
assertEquals(500 - upgrade.mineralPrice(1), player.minerals());
35+
assertEquals(500 - upgrade.gasPrice(1), player.gas());
36+
}
37+
38+
@Test
39+
public void cancelTrainSlotShouldShiftQueueWithoutIndexOutOfBounds() {
40+
Game game = spy(new Game());
41+
doReturn(10).when(game).getFrameCount();
42+
43+
ClientData.PlayerData playerData = mock(ClientData.PlayerData.class);
44+
when(playerData.getName()).thenReturn("Self");
45+
Player player = new Player(playerData, 0, game);
46+
47+
ClientData.UnitData unitData = mock(ClientData.UnitData.class);
48+
when(unitData.getExists()).thenReturn(true);
49+
when(unitData.getTrainingQueueCount()).thenReturn(2);
50+
when(unitData.getTrainingQueue(0)).thenReturn(UnitType.Terran_Marine.id);
51+
when(unitData.getTrainingQueue(1)).thenReturn(UnitType.Terran_Medic.id);
52+
when(unitData.getTrainingQueue(2)).thenReturn(UnitType.None.id);
53+
when(unitData.getTrainingQueue(3)).thenReturn(UnitType.None.id);
54+
when(unitData.getTrainingQueue(4)).thenReturn(UnitType.None.id);
55+
56+
Unit unit = spy(new Unit(unitData, 0, game));
57+
doReturn(player).when(unit).getPlayer();
58+
59+
CommandTemp cmd = new CommandTemp(UnitCommand.cancelTrain(unit, 1), game);
60+
cmd.execute(false);
61+
62+
assertEquals(Collections.singletonList(UnitType.Terran_Marine), unit.getTrainingQueue());
63+
}
64+
}

‎src/test/java/bwapi/GameTest.java‎

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
import org.junit.runner.RunWith;
1010

1111
import java.io.IOException;
12+
import java.util.Arrays;
1213
import java.util.Collections;
1314
import java.util.List;
1415

@@ -174,4 +175,39 @@ public void setMapWithEmptyStringShouldReturnFalseInsteadOfThrowing() {
174175
Game game = new Game();
175176
assertFalse(game.setMap(""));
176177
}
178+
179+
@Test
180+
public void onFrameShouldRefreshPlayersAndExcludeDefeatedOrLeftPlayers() {
181+
Game game = spy(new Game());
182+
Player self = mock(Player.class);
183+
Player ally = mock(Player.class);
184+
Player enemy = mock(Player.class);
185+
Player defeatedEnemy = mock(Player.class);
186+
Player leftAlly = mock(Player.class);
187+
Player observer = mock(Player.class);
188+
189+
when(self.isAlly(ally)).thenReturn(true);
190+
when(self.isAlly(leftAlly)).thenReturn(true);
191+
when(self.isEnemy(enemy)).thenReturn(true);
192+
when(self.isEnemy(defeatedEnemy)).thenReturn(true);
193+
194+
when(defeatedEnemy.isDefeated()).thenReturn(true);
195+
when(leftAlly.leftGame()).thenReturn(true);
196+
when(observer.isObserver()).thenReturn(true);
197+
198+
doReturn(self).when(game).self();
199+
doReturn(Arrays.asList(self, ally, enemy, defeatedEnemy, leftAlly, observer)).when(game).getPlayers();
200+
game.setAllUnits(Collections.emptyList());
201+
202+
game.onFrame(0);
203+
204+
assertEquals(Collections.singletonList(ally), game.allies());
205+
assertEquals(Collections.singletonList(enemy), game.enemies());
206+
assertEquals(Collections.singletonList(observer), game.observers());
207+
208+
when(enemy.isDefeated()).thenReturn(true);
209+
game.onFrame(1);
210+
211+
assertTrue(game.enemies().isEmpty());
212+
}
177213
}

‎src/test/java/bwapi/PlayerTest.java‎

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
import static org.junit.Assert.assertEquals;
66
import static org.junit.Assert.assertFalse;
7+
import static org.junit.Assert.assertTrue;
78
import static org.mockito.Mockito.mock;
89
import static org.mockito.Mockito.when;
910

@@ -28,4 +29,46 @@ public void getTextColorShouldReturnDarkGreenForColorGreen() {
2829

2930
assertEquals(Text.DarkGreen, player.getTextColor());
3031
}
32+
33+
@Test
34+
public void isEnemyAndIsNeutralShouldDelegateToPlayerData() {
35+
Game game = mock(Game.class);
36+
ClientData.PlayerData selfData = mock(ClientData.PlayerData.class);
37+
ClientData.PlayerData otherData = mock(ClientData.PlayerData.class);
38+
when(selfData.getName()).thenReturn("Self");
39+
when(otherData.getName()).thenReturn("Other");
40+
when(selfData.isParticipating()).thenReturn(true);
41+
when(otherData.isParticipating()).thenReturn(true);
42+
// Neither ally nor enemy in PlayerData:
43+
when(selfData.isAlly(1)).thenReturn(false);
44+
when(selfData.isEnemy(1)).thenReturn(false);
45+
46+
Player self = new Player(selfData, 0, game);
47+
Player other = new Player(otherData, 1, game);
48+
49+
assertFalse(self.isEnemy(other));
50+
51+
when(selfData.isEnemy(1)).thenReturn(true);
52+
assertTrue(self.isEnemy(other));
53+
54+
when(otherData.isNeutral()).thenReturn(true);
55+
assertTrue(other.isNeutral());
56+
}
57+
58+
@Test
59+
public void supplyTotalAndSupplyUsedShouldHandleRaceNoneAndInvalidRace() {
60+
Game game = mock(Game.class);
61+
ClientData.PlayerData playerData = mock(ClientData.PlayerData.class);
62+
when(playerData.getName()).thenReturn("Self");
63+
when(playerData.getRace()).thenReturn(Race.Terran.id);
64+
when(playerData.getSupplyTotal(Race.Terran.id)).thenReturn(40);
65+
when(playerData.getSupplyUsed(Race.Terran.id)).thenReturn(24);
66+
67+
Player player = new Player(playerData, 0, game);
68+
69+
assertEquals(40, player.supplyTotal(Race.None));
70+
assertEquals(24, player.supplyUsed(Race.None));
71+
assertEquals(0, player.supplyTotal(Race.Unknown));
72+
assertEquals(0, player.supplyUsed(Race.Unknown));
73+
}
3174
}
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
package bwapi;
2+
3+
import org.junit.Test;
4+
5+
import static org.junit.Assert.assertEquals;
6+
import static org.mockito.Mockito.mock;
7+
import static org.mockito.Mockito.when;
8+
9+
public class RegionTest {
10+
11+
@Test
12+
public void updateNeighboursShouldDetermineAccessibilityByComparingRegionGroupId() {
13+
Game game = mock(Game.class);
14+
15+
ClientData.RegionData originData = mock(ClientData.RegionData.class);
16+
when(originData.getId()).thenReturn(0);
17+
when(originData.islandID()).thenReturn(10);
18+
when(originData.getCenter_x()).thenReturn(100);
19+
when(originData.getCenter_y()).thenReturn(100);
20+
when(originData.isAccessible()).thenReturn(true);
21+
when(originData.getNeighborCount()).thenReturn(2);
22+
when(originData.getNeighbors(0)).thenReturn(1);
23+
when(originData.getNeighbors(1)).thenReturn(2);
24+
25+
// Neighbor 1 is closer and walkable (isAccessible == true), but on a different island/group
26+
ClientData.RegionData diffGroupData = mock(ClientData.RegionData.class);
27+
when(diffGroupData.getId()).thenReturn(1);
28+
when(diffGroupData.islandID()).thenReturn(20);
29+
when(diffGroupData.getCenter_x()).thenReturn(120);
30+
when(diffGroupData.getCenter_y()).thenReturn(100);
31+
when(diffGroupData.isAccessible()).thenReturn(true);
32+
33+
// Neighbor 2 is farther, but in the same region group
34+
ClientData.RegionData sameGroupData = mock(ClientData.RegionData.class);
35+
when(sameGroupData.getId()).thenReturn(2);
36+
when(sameGroupData.islandID()).thenReturn(10);
37+
when(sameGroupData.getCenter_x()).thenReturn(200);
38+
when(sameGroupData.getCenter_y()).thenReturn(100);
39+
when(sameGroupData.isAccessible()).thenReturn(true);
40+
41+
Region origin = new Region(originData, game);
42+
Region diffGroupNeighbor = new Region(diffGroupData, game);
43+
Region sameGroupNeighbor = new Region(sameGroupData, game);
44+
45+
when(game.getRegion(1)).thenReturn(diffGroupNeighbor);
46+
when(game.getRegion(2)).thenReturn(sameGroupNeighbor);
47+
48+
origin.updateNeighbours();
49+
50+
assertEquals(sameGroupNeighbor, origin.getClosestAccessibleRegion());
51+
assertEquals(diffGroupNeighbor, origin.getClosestInaccessibleRegion());
52+
}
53+
}

‎src/test/java/bwapi/UnitTest.java‎

Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,12 @@
1010

1111
import static org.junit.Assert.assertEquals;
1212
import static org.junit.Assert.assertFalse;
13+
import static org.junit.Assert.assertTrue;
1314
import static org.mockito.ArgumentMatchers.any;
1415
import static org.mockito.Mockito.doReturn;
1516
import static org.mockito.Mockito.mock;
1617
import static org.mockito.Mockito.spy;
18+
import static org.mockito.Mockito.verify;
1719
import static org.mockito.Mockito.when;
1820

1921

@@ -269,4 +271,113 @@ public void canUseTechUnitHealingShouldRejectEnemyTarget() {
269271

270272
assertFalse(medic.canUseTechUnit(TechType.Healing, enemyMarine, false, false, false, false));
271273
}
274+
275+
@Test
276+
public void isVisibleShouldFallbackToAnyPlayerWhenSelfIsNullAndCheckValidPlayerId() {
277+
Game game = mock(Game.class);
278+
when(game.self()).thenReturn(null);
279+
280+
ClientData.UnitData unitData = mock(ClientData.UnitData.class);
281+
Unit unit = new Unit(unitData, 0, game);
282+
283+
assertFalse(unit.isVisible());
284+
285+
when(unitData.isVisible(3)).thenReturn(true);
286+
assertTrue(unit.isVisible());
287+
assertTrue(unit.isVisible(null));
288+
289+
ClientData.PlayerData neutralData = mock(ClientData.PlayerData.class);
290+
when(neutralData.getName()).thenReturn("Neutral");
291+
Player neutral = new Player(neutralData, 11, game);
292+
when(unitData.isVisible(11)).thenReturn(true);
293+
assertFalse(unit.isVisible(neutral));
294+
}
295+
296+
@Test
297+
public void isTargetableShouldRequireVisibilityWhenCompleteMapInfoDisabled() {
298+
Game game = mock(Game.class);
299+
Unit unit = spy(new Unit(mock(ClientData.UnitData.class), 0, game));
300+
doReturn(true).when(unit).exists();
301+
doReturn(false).when(unit).isVisible();
302+
doReturn(true).when(unit).isCompleted();
303+
doReturn(UnitType.Terran_Marine).when(unit).getType();
304+
305+
when(game.isFlagEnabled(Flag.CompleteMapInformation)).thenReturn(false);
306+
assertFalse(unit.isTargetable());
307+
308+
when(game.isFlagEnabled(Flag.CompleteMapInformation)).thenReturn(true);
309+
assertTrue(unit.isTargetable());
310+
}
311+
312+
@Test
313+
public void canTargetUnitShouldCheckCommandabilityByDefaultAndDelegateToIsTargetable() {
314+
Game game = mock(Game.class);
315+
Unit source = spy(new Unit(mock(ClientData.UnitData.class), 0, game));
316+
Unit target = mock(Unit.class);
317+
when(target.exists()).thenReturn(true);
318+
when(target.isCompleted()).thenReturn(true);
319+
when(target.getType()).thenReturn(UnitType.Terran_Marine);
320+
when(target.isTargetable()).thenReturn(true);
321+
322+
doReturn(false).when(source).canCommand();
323+
assertFalse(source.canTargetUnit(target));
324+
assertTrue(source.canTargetUnit(target, false));
325+
326+
doReturn(true).when(source).canCommand();
327+
when(target.isTargetable()).thenReturn(false);
328+
assertFalse(source.canTargetUnit(target));
329+
}
330+
331+
@Test
332+
public void buildWithNonePositionAndTrainWithNoneUnitTypeShouldRedirectToCarrierAndReaverAmmo() {
333+
Game game = mock(Game.class);
334+
Unit carrier = spy(new Unit(mock(ClientData.UnitData.class), 0, game));
335+
doReturn(UnitType.Protoss_Carrier).when(carrier).getType();
336+
doReturn(true).when(carrier).issueCommand(any(UnitCommand.class));
337+
338+
assertTrue(carrier.build(UnitType.None, TilePosition.None));
339+
verify(carrier).issueCommand(UnitCommand.train(carrier, UnitType.Protoss_Interceptor));
340+
341+
Unit reaver = spy(new Unit(mock(ClientData.UnitData.class), 1, game));
342+
doReturn(UnitType.Protoss_Reaver).when(reaver).getType();
343+
doReturn(true).when(reaver).issueCommand(any(UnitCommand.class));
344+
345+
assertTrue(reaver.build(UnitType.None));
346+
verify(reaver).issueCommand(UnitCommand.train(reaver, UnitType.Protoss_Scarab));
347+
}
348+
349+
@Test
350+
public void useTechWithNullUnitTargetShouldIssueTargetlessUseTechCommand() {
351+
Game game = mock(Game.class);
352+
Unit marine = spy(new Unit(mock(ClientData.UnitData.class), 0, game));
353+
doReturn(true).when(marine).issueCommand(any(UnitCommand.class));
354+
355+
assertTrue(marine.useTech(TechType.Stim_Packs, (Unit) null));
356+
verify(marine).issueCommand(UnitCommand.useTech(marine, TechType.Stim_Packs));
357+
}
358+
359+
@Test
360+
public void canAttackGroupedPositionShouldOnlyCheckCanAttackMoveGrouped() {
361+
Game game = mock(Game.class);
362+
Unit unit = spy(new Unit(mock(ClientData.UnitData.class), 0, game));
363+
doReturn(false).when(unit).canAttackMoveGrouped(false, false);
364+
doReturn(true).when(unit).canAttackUnitGrouped(false, false);
365+
366+
assertFalse(unit.canAttackGrouped(new Position(100, 100), false, true, false, false));
367+
}
368+
369+
@Test
370+
public void canBuildAddonWithUnitTypeShouldCheckCanBuildAddonWithoutRecursingOnUnitType() {
371+
Game game = mock(Game.class);
372+
when(game.canMake(any(UnitType.class), any(Unit.class))).thenReturn(true);
373+
when(game.canBuildHere(any(TilePosition.class), any(UnitType.class), any(Unit.class))).thenReturn(true);
374+
375+
Unit factory = spy(new Unit(mock(ClientData.UnitData.class), 0, game));
376+
doReturn(UnitType.Terran_Factory).when(factory).getType();
377+
doReturn(new TilePosition(10, 10)).when(factory).getTilePosition();
378+
// Not completed -> canBuildAddon(false) is false
379+
doReturn(false).when(factory).isCompleted();
380+
381+
assertFalse(factory.canBuildAddon(UnitType.Terran_Machine_Shop, true, false));
382+
}
272383
}

0 commit comments

Comments
 (0)