package com.projectsacrifice.game; import android.app.Instrumentation; import androidx.test.core.app.ActivityScenario; import androidx.test.ext.junit.runners.AndroidJUnit4; import androidx.test.platform.app.InstrumentationRegistry; import org.junit.Test; import org.junit.runner.RunWith; /** Acceptance test: a bot must finish the same level implementation shipped in the APK. */ @RunWith(AndroidJUnit4.class) public final class LevelFivePlaythroughTest { private static final int CONSECUTIVE_RUNS = 3; @Test public void testBotCompletesLevelFive() { try (ActivityScenario scenario = ActivityScenario.launch(MainActivity.class)) { final GameView[] view = new GameView[1]; scenario.onActivity(activity -> view[0] = activity.gameViewForAutomation()); LevelPlaytestBot bot = new LevelPlaytestBot(); AndroidDriver driver = new AndroidDriver( InstrumentationRegistry.getInstrumentation(), view[0]); for (int run = 1; run <= CONSECUTIVE_RUNS; run++) { LevelPlaytestBot.Result result = bot.proveLevelFive(driver, 25_000L); org.junit.Assert.assertTrue("run=" + run + "; " + result.diagnostic(), result.completed()); org.junit.Assert.assertEquals("run=" + run + "; exactly one volunteer is required", 1, result.deaths()); org.junit.Assert.assertEquals("run=" + run + "; delivered corpse must remain", 1, result.corpseCount()); org.junit.Assert.assertTrue("run=" + run + "; pressure-plate door must open", result.doorOpened()); } } } private static final class AndroidDriver implements LevelPlaytestBot.Driver { private final Instrumentation instrumentation; private final GameView gameView; AndroidDriver(Instrumentation instrumentation, GameView gameView) { this.instrumentation = instrumentation; this.gameView = gameView; } @Override public void startLevel(int oneBasedLevelNumber) { instrumentation.runOnMainSync(() -> gameView.startLevelForAutomation(oneBasedLevelNumber)); } @Override public void setInput(boolean moveLeft, boolean moveRight, boolean jump) { instrumentation.runOnMainSync(() -> gameView.setAutomationInput(moveLeft, moveRight, jump)); } @Override public GameView.AutomationSnapshot snapshot() { final GameView.AutomationSnapshot[] value = new GameView.AutomationSnapshot[1]; instrumentation.runOnMainSync(() -> value[0] = gameView.automationSnapshot()); return value[0]; } @Override public void waitForNextDecision(long millis) { try { Thread.sleep(millis); } catch (InterruptedException interrupted) { Thread.currentThread().interrupt(); throw new AssertionError("Bot interrupted", interrupted); } } } }