From c82fd9ead5761274ddeafc84e2baf93e4205a64a Mon Sep 17 00:00:00 2001 From: Anuken Date: Wed, 3 Oct 2018 20:58:35 -0400 Subject: [PATCH] Added unit tests --- .gitignore | 4 +- build.gradle | 33 +-- .../sprites/blocks/units/revenant-factory.png | Bin 598 -> 607 bytes core/assets/sprites/sprites.png | Bin 104432 -> 104433 bytes core/src/io/anuke/mindustry/maps/Sector.java | 5 +- core/src/io/anuke/mindustry/maps/Sectors.java | 4 +- .../anuke/mindustry/net/Administration.java | 13 -- core/src/io/anuke/mindustry/net/EditLog.java | 21 -- .../mindustry/server/ServerLauncher.java | 28 +-- tests/src/test/java/ApplicationTests.java | 204 ++++++++++++++++++ tests/src/test/java/Tests.java | 9 - 11 files changed, 233 insertions(+), 88 deletions(-) delete mode 100644 core/src/io/anuke/mindustry/net/EditLog.java create mode 100644 tests/src/test/java/ApplicationTests.java delete mode 100644 tests/src/test/java/Tests.java diff --git a/.gitignore b/.gitignore index 12ca21bf90..fdf2b4f464 100644 --- a/.gitignore +++ b/.gitignore @@ -14,8 +14,10 @@ /core/assets-raw/sprites/generated/ /annotations/build/ /kryonet/build/ -/packer/build/ +/tools/build/ +/tests/build/ /server/build/ +/test_files/ /annotations/build/ /android/assets/mindustry-maps/ /android/assets/mindustry-saves/ diff --git a/build.gradle b/build.gradle index df4df532dc..9954ae113d 100644 --- a/build.gradle +++ b/build.gradle @@ -27,7 +27,7 @@ allprojects { appName = 'Mindustry' gdxVersion = '1.9.8' roboVMVersion = '2.3.0' - uCoreVersion = '00d05bd7d3e943c8a454ccf2cb69cdffb23afbb7' + uCoreVersion = '220916714cbe63664c34f95a9dc50a362feca732' getVersionString = { String buildVersion = getBuildVersion() @@ -119,20 +119,6 @@ project(":html") { } } -project(":tests"){ - apply plugin: "java" - - dependencies { - compile project(":core") - testImplementation('org.junit.jupiter:junit-jupiter-api:5.1.0') - testRuntimeOnly('org.junit.jupiter:junit-jupiter-engine:5.1.0') - } - - test { - useJUnitPlatform() - } -} - project(":ios") { apply plugin: "java" apply plugin: "robovm" @@ -218,6 +204,23 @@ project(":server") { } } +project(":tests"){ + apply plugin: "java" + + dependencies { + testImplementation project(":core") + testImplementation('org.junit.jupiter:junit-jupiter-api:5.1.0') + testRuntimeOnly('org.junit.jupiter:junit-jupiter-engine:5.1.0') + testImplementation "com.badlogicgames.gdx:gdx-backend-headless:$gdxVersion" + testImplementation "com.badlogicgames.gdx:gdx-platform:$gdxVersion:natives-desktop" + } + + test { + useJUnitPlatform() + workingDir = new File("../core/assets") + } +} + project(":tools") { apply plugin: "java" diff --git a/core/assets-raw/sprites/blocks/units/revenant-factory.png b/core/assets-raw/sprites/blocks/units/revenant-factory.png index 6182b7ea09a76ce2999604265617f66431617b71..a236936f62b4cb4836e7ac5378cd41b29bab9244 100644 GIT binary patch delta 529 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 delta 19111 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 DG;B%X diff --git a/core/src/io/anuke/mindustry/maps/Sector.java b/core/src/io/anuke/mindustry/maps/Sector.java index 7c363f7164..89f4a487fa 100644 --- a/core/src/io/anuke/mindustry/maps/Sector.java +++ b/core/src/io/anuke/mindustry/maps/Sector.java @@ -11,6 +11,7 @@ import io.anuke.mindustry.type.ItemStack; import io.anuke.ucore.util.Bits; import static io.anuke.mindustry.Vars.control; +import static io.anuke.mindustry.Vars.headless; @Serialize public class Sector{ @@ -46,11 +47,11 @@ public class Sector{ } public SaveSlot getSave(){ - return control.getSaves().getByID(saveID); + return !hasSave() ? null : control.getSaves().getByID(saveID); } public boolean hasSave(){ - return control.getSaves().getByID(saveID) != null; + return !headless && control.getSaves().getByID(saveID) != null; } public int packedPosition(){ diff --git a/core/src/io/anuke/mindustry/maps/Sectors.java b/core/src/io/anuke/mindustry/maps/Sectors.java index 11a48a92c9..3b629b379e 100644 --- a/core/src/io/anuke/mindustry/maps/Sectors.java +++ b/core/src/io/anuke/mindustry/maps/Sectors.java @@ -47,7 +47,9 @@ public class Sectors{ } world.loadSector(sector); logic.play(); - sector.saveID = control.getSaves().addSave("sector-" + sector.packedPosition()).index; + if(!headless){ + sector.saveID = control.getSaves().addSave("sector-" + sector.packedPosition()).index; + } world.sectors().save(); world.setSector(sector); sector.currentMission().onBegin(); diff --git a/core/src/io/anuke/mindustry/net/Administration.java b/core/src/io/anuke/mindustry/net/Administration.java index b303bf4d2a..e8ca496d2f 100644 --- a/core/src/io/anuke/mindustry/net/Administration.java +++ b/core/src/io/anuke/mindustry/net/Administration.java @@ -1,7 +1,6 @@ package io.anuke.mindustry.net; import com.badlogic.gdx.utils.Array; -import com.badlogic.gdx.utils.IntMap; import com.badlogic.gdx.utils.ObjectMap; import io.anuke.annotations.Annotations.Serialize; import io.anuke.ucore.core.Settings; @@ -16,8 +15,6 @@ public class Administration{ private ObjectMap playerInfo = new ObjectMap<>(); /**Maps UUIDs to trace infos. This is wiped when a player logs off.*/ private ObjectMap traceInfo = new ObjectMap<>(); - /** Maps packed coordinates to logs for that coordinate*/ - private IntMap> editLogs = new IntMap<>(); private Array bannedIPs = new Array<>(); public Administration(){ @@ -46,16 +43,6 @@ public class Administration{ Settings.save(); } - public void setAntiGriefParams(int maxBreak, int cooldown){ - Settings.putInt("antigrief-max", maxBreak); - Settings.putInt("antigrief-cooldown", cooldown); - Settings.save(); - } - - public IntMap> getEditLogs(){ - return editLogs; - } - /** * Call when a player joins to update their information here. */ diff --git a/core/src/io/anuke/mindustry/net/EditLog.java b/core/src/io/anuke/mindustry/net/EditLog.java deleted file mode 100644 index ab922ae8e0..0000000000 --- a/core/src/io/anuke/mindustry/net/EditLog.java +++ /dev/null @@ -1,21 +0,0 @@ -package io.anuke.mindustry.net; - -import io.anuke.mindustry.world.Block; - -public class EditLog{ - public String playername; - public Block block; - public int rotation; - public EditAction action; - - EditLog(String playername, Block block, int rotation, EditAction action){ - this.playername = playername; - this.block = block; - this.rotation = rotation; - this.action = action; - } - - public enum EditAction{ - PLACE, BREAK - } -} diff --git a/server/src/io/anuke/mindustry/server/ServerLauncher.java b/server/src/io/anuke/mindustry/server/ServerLauncher.java index 3ed3280250..17ce9d6a8d 100644 --- a/server/src/io/anuke/mindustry/server/ServerLauncher.java +++ b/server/src/io/anuke/mindustry/server/ServerLauncher.java @@ -1,7 +1,6 @@ package io.anuke.mindustry.server; import com.badlogic.gdx.ApplicationListener; -import com.badlogic.gdx.ApplicationLogger; import com.badlogic.gdx.Files.FileType; import com.badlogic.gdx.Gdx; import com.badlogic.gdx.Preferences; @@ -13,6 +12,7 @@ import io.anuke.kryonet.KryoClient; import io.anuke.kryonet.KryoServer; import io.anuke.mindustry.net.Net; import io.anuke.ucore.io.BinaryPreferences; +import io.anuke.ucore.util.EmptyLogger; import io.anuke.ucore.util.OS; import java.io.File; @@ -24,31 +24,7 @@ public class ServerLauncher extends HeadlessApplication{ super(listener, config); //don't do anything at all for GDX logging: don't want controller info and such - Gdx.app.setApplicationLogger(new ApplicationLogger(){ - @Override - public void log(String tag, String message){ - } - - @Override - public void log(String tag, String message, Throwable exception){ - } - - @Override - public void error(String tag, String message){ - } - - @Override - public void error(String tag, String message, Throwable exception){ - } - - @Override - public void debug(String tag, String message){ - } - - @Override - public void debug(String tag, String message, Throwable exception){ - } - }); + Gdx.app.setApplicationLogger(new EmptyLogger()); } public static void main(String[] args){ diff --git a/tests/src/test/java/ApplicationTests.java b/tests/src/test/java/ApplicationTests.java new file mode 100644 index 0000000000..5cee8a0c0a --- /dev/null +++ b/tests/src/test/java/ApplicationTests.java @@ -0,0 +1,204 @@ +import com.badlogic.gdx.Gdx; +import com.badlogic.gdx.backends.headless.HeadlessApplication; +import com.badlogic.gdx.backends.headless.HeadlessApplicationConfiguration; +import io.anuke.mindustry.Vars; +import io.anuke.mindustry.content.Items; +import io.anuke.mindustry.content.blocks.Blocks; +import io.anuke.mindustry.content.blocks.StorageBlocks; +import io.anuke.mindustry.core.GameState.State; +import io.anuke.mindustry.core.Logic; +import io.anuke.mindustry.core.NetServer; +import io.anuke.mindustry.core.World; +import io.anuke.mindustry.game.Content; +import io.anuke.mindustry.game.Team; +import io.anuke.mindustry.io.BundleLoader; +import io.anuke.mindustry.io.SaveIO; +import io.anuke.mindustry.maps.Map; +import io.anuke.mindustry.world.Tile; +import io.anuke.ucore.core.Timers; +import io.anuke.ucore.modules.ModuleCore; +import io.anuke.ucore.util.EmptyLogger; +import io.anuke.ucore.util.Log; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import java.io.File; + +import static io.anuke.mindustry.Vars.*; +import static org.junit.jupiter.api.Assertions.*; + +public class ApplicationTests{ + + @BeforeAll + static void launchApplication(){ + try{ + boolean[] begins = {false}; + Throwable[] exceptionThrown = {null}; + Log.setUseColors(false); + + ModuleCore core = new ModuleCore(){ + @Override + public void init(){ + Vars.init(); + + headless = true; + + BundleLoader.load(); + content.load(); + content.initialize(Content::init); + + module(logic = new Logic()); + module(world = new World()); + module(netServer = new NetServer()); + } + + @Override + public void postInit(){ + super.postInit(); + begins[0] = true; + } + }; + + HeadlessApplicationConfiguration config = new HeadlessApplicationConfiguration(); + config.preferencesDirectory = "test_files/"; + + new File("tests_files/").delete(); + + new HeadlessApplication(core, config){{ + Gdx.app.setApplicationLogger(new EmptyLogger()); + }}; + + for(Thread thread : Thread.getAllStackTraces().keySet()){ + if(thread.getName().equals("HeadlessApplication")){ + thread.setUncaughtExceptionHandler((t, throwable) -> exceptionThrown[0] = throwable); + break; + } + } + + while(!begins[0]){ + if(exceptionThrown[0] != null){ + fail(exceptionThrown[0]); + } + Thread.sleep(10); + } + }catch(Throwable r){ + fail(r); + } + } + + @BeforeEach + void resetWorld(){ + Timers.setDeltaProvider(() -> 1f); + logic.reset(); + state.set(State.menu); + } + + @Test + void initialization(){ + assertTrue(logic != null); + assertTrue(world != null); + assertTrue(content.getContentMap().length > 0); + } + + @Test + void loadSector(){ + world.sectors().createSector(0, 0); + world.sectors().playSector(world.sectors().get(0, 0)); + } + + @Test + void playMap(){ + assertTrue(world.maps().all().size > 0); + + world.loadMap(world.maps().all().first()); + } + + @Test + void spawnWaves(){ + world.loadMap(world.maps().all().first()); + logic.runWave(); + unitGroups[waveTeam.ordinal()].updateEvents(); + assertFalse(unitGroups[waveTeam.ordinal()].isEmpty()); + } + + @Test + void createMap(){ + assertTrue(world.maps().all().size > 0); + + Tile[][] tiles = world.createTiles(8, 8); + + world.beginMapLoad(); + for(int x = 0; x < tiles.length; x++){ + for(int y = 0; y < tiles[0].length; y++){ + tiles[x][y] = new Tile(x, y, (byte)0, (byte)0); + } + } + world.endMapLoad(); + } + + @Test + void multiblock(){ + createMap(); + int bx = 4; + int by = 4; + world.setBlock(world.tile(bx, by), StorageBlocks.core, Team.blue); + assertTrue(world.tile(bx, by).getTeam() == Team.blue); + for(int x = bx-1; x <= bx + 1; x++){ + for(int y = by-1; y <= by + 1; y++){ + if(x == bx && by == y){ + assertTrue(world.tile(x, y).block() == StorageBlocks.core); + }else{ + assertTrue(world.tile(x, y).block() == Blocks.blockpart && world.tile(x, y).getLinked() == world.tile(bx, by)); + } + } + } + } + + @Test + void blockInventories(){ + multiblock(); + Tile tile = world.tile(4, 4); + tile.entity.items.add(Items.coal, 5); + tile.entity.items.add(Items.titanium, 50); + assertTrue(tile.entity.items.total() == 55); + tile.entity.items.remove(Items.phasematter, 10); + tile.entity.items.remove(Items.titanium, 10); + assertTrue(tile.entity.items.total() == 45); + } + + @Test + void timers(){ + boolean[] ran = {false}; + Timers.run(1.9999f, () -> ran[0] = true); + + Timers.update(); + assertFalse(ran[0]); + Timers.update(); + assertTrue(ran[0]); + } + + @Test + void save(){ + assertTrue(world.maps().all().size > 0); + + world.loadMap(world.maps().all().first()); + SaveIO.saveToSlot(0); + } + + @Test + void load(){ + assertTrue(world.maps().all().size > 0); + + world.loadMap(world.maps().all().first()); + Map map = world.getMap(); + + SaveIO.saveToSlot(0); + resetWorld(); + SaveIO.loadFromSlot(0); + + assertTrue(world.getMap() == map); + assertTrue(world.width() == map.meta.width); + assertTrue(world.height() == map.meta.height); + } +} \ No newline at end of file diff --git a/tests/src/test/java/Tests.java b/tests/src/test/java/Tests.java deleted file mode 100644 index 261bc16c5f..0000000000 --- a/tests/src/test/java/Tests.java +++ /dev/null @@ -1,9 +0,0 @@ -import org.junit.jupiter.api.BeforeEach; - -public class Tests{ - - @BeforeEach - void launchApplication(){ - - } -} \ No newline at end of file