Добавить испытания и прогрессию по LevelID
This commit is contained in:
+53
@@ -0,0 +1,53 @@
|
||||
package com.projectsacrifice.game;
|
||||
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
import androidx.test.core.app.ActivityScenario;
|
||||
import androidx.test.ext.junit.runners.AndroidJUnit4;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
@RunWith(AndroidJUnit4.class)
|
||||
public final class ChallengeCollectibleIntegrationTest {
|
||||
@Test
|
||||
public void collectedCacheSurvivesRecreationAndRestartResetsAttemptState() {
|
||||
try (ActivityScenario<MainActivity> activity = ActivityScenario.launch(MainActivity.class)) {
|
||||
activity.onActivity(current -> {
|
||||
GameView view = current.gameViewForAutomation();
|
||||
view.enableDeterministicAutomationClock();
|
||||
view.startLevelForAutomation(18);
|
||||
assertTrue(view.automationSnapshot().collectibleVisible());
|
||||
view.setAutomationInput(false, true, false);
|
||||
for (int decision = 0; decision < 400
|
||||
&& view.automationSnapshot().playerX() < 650f; decision++) {
|
||||
view.advanceDeterministicAutomation(16L);
|
||||
}
|
||||
assertTrue("approach x=" + view.automationSnapshot().playerX(),
|
||||
view.automationSnapshot().playerX() >= 650f);
|
||||
view.setAutomationInput(false, true, true);
|
||||
for (int decision = 0; decision < 180
|
||||
&& !view.automationSnapshot().collectibleFound(); decision++) {
|
||||
view.advanceDeterministicAutomation(16L);
|
||||
}
|
||||
view.setAutomationInput(false, false, false);
|
||||
assertTrue(view.automationSnapshot().collectibleFound());
|
||||
assertFalse(view.automationSnapshot().collectibleVisible());
|
||||
assertTrue(view.sessionSnapshotForAutomation().collectibleFound());
|
||||
});
|
||||
|
||||
activity.recreate();
|
||||
|
||||
activity.onActivity(current -> {
|
||||
GameView view = current.gameViewForAutomation();
|
||||
assertTrue(view.automationSnapshot().visiblyPaused());
|
||||
assertTrue(view.automationSnapshot().collectibleFound());
|
||||
assertFalse(view.automationSnapshot().collectibleVisible());
|
||||
view.startLevelForAutomation(18);
|
||||
assertFalse(view.automationSnapshot().collectibleFound());
|
||||
assertTrue(view.automationSnapshot().collectibleVisible());
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,95 @@
|
||||
package com.projectsacrifice.game;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
import android.app.Instrumentation;
|
||||
import android.content.Context;
|
||||
|
||||
import androidx.test.core.app.ActivityScenario;
|
||||
import androidx.test.ext.junit.runners.AndroidJUnit4;
|
||||
import androidx.test.platform.app.InstrumentationRegistry;
|
||||
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
@RunWith(AndroidJUnit4.class)
|
||||
public final class ChallengePlaythroughTest {
|
||||
private Context context;
|
||||
|
||||
@Before
|
||||
public void resetProgress() {
|
||||
context = InstrumentationRegistry.getInstrumentation().getTargetContext();
|
||||
context.getSharedPreferences("project_sacrifice_progress_v1", Context.MODE_PRIVATE)
|
||||
.edit().clear().commit();
|
||||
}
|
||||
|
||||
@After
|
||||
public void cleanProgress() {
|
||||
context.getSharedPreferences("project_sacrifice_progress_v1", Context.MODE_PRIVATE)
|
||||
.edit().clear().commit();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void intendedRouteEarnsAndPersistsAllThreeStarsThreeTimes() {
|
||||
try (ActivityScenario<MainActivity> activity = ActivityScenario.launch(MainActivity.class)) {
|
||||
Driver driver = Driver.from(activity);
|
||||
for (int run = 1; run <= 3; run++) {
|
||||
LevelPlaytestBot.Result result = new LevelPlaytestBot().run(
|
||||
driver, ChallengeScenarios.levelEighteen(), 20_000L);
|
||||
assertTrue("run=" + run + "; " + result.diagnostic(), result.completed());
|
||||
assertEquals(0, result.deaths());
|
||||
assertTrue(driver.snapshot().collectibleFound());
|
||||
assertEquals(3, driver.result().challengeResult().stars());
|
||||
assertEquals(3, driver.result().bestStars());
|
||||
}
|
||||
assertEquals(3, new ProgressStore(context).earnedStars(LevelCatalog.get(17)));
|
||||
}
|
||||
}
|
||||
|
||||
private static final class Driver implements LevelPlaytestBot.Driver {
|
||||
private final Instrumentation instrumentation;
|
||||
private final GameView view;
|
||||
|
||||
private Driver(Instrumentation instrumentation, GameView view) {
|
||||
this.instrumentation = instrumentation;
|
||||
this.view = view;
|
||||
}
|
||||
|
||||
static Driver from(ActivityScenario<MainActivity> activity) {
|
||||
GameView[] target = new GameView[1];
|
||||
activity.onActivity(current -> target[0] = current.gameViewForAutomation());
|
||||
return new Driver(InstrumentationRegistry.getInstrumentation(), target[0]);
|
||||
}
|
||||
|
||||
@Override public void startLevel(int oneBasedLevelNumber) {
|
||||
instrumentation.runOnMainSync(() -> {
|
||||
view.enableDeterministicAutomationClock();
|
||||
view.startLevelForAutomation(oneBasedLevelNumber);
|
||||
});
|
||||
}
|
||||
|
||||
@Override public void setInput(boolean left, boolean right, boolean jump) {
|
||||
instrumentation.runOnMainSync(() -> view.setAutomationInput(left, right, jump));
|
||||
}
|
||||
|
||||
@Override public GameView.AutomationSnapshot snapshot() {
|
||||
GameView.AutomationSnapshot[] value = new GameView.AutomationSnapshot[1];
|
||||
instrumentation.runOnMainSync(() -> value[0] = view.automationSnapshot());
|
||||
return value[0];
|
||||
}
|
||||
|
||||
CompletionResult result() {
|
||||
CompletionResult[] value = new CompletionResult[1];
|
||||
instrumentation.runOnMainSync(() -> value[0] = view.completionResultForAutomation());
|
||||
return value[0];
|
||||
}
|
||||
|
||||
@Override public void waitForNextDecision(long millis) {
|
||||
instrumentation.runOnMainSync(() ->
|
||||
view.advanceDeterministicAutomation(Math.max(16L, millis)));
|
||||
}
|
||||
}
|
||||
}
|
||||
+77
@@ -0,0 +1,77 @@
|
||||
package com.projectsacrifice.game;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.SharedPreferences;
|
||||
|
||||
import androidx.test.ext.junit.runners.AndroidJUnit4;
|
||||
import androidx.test.platform.app.InstrumentationRegistry;
|
||||
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
@RunWith(AndroidJUnit4.class)
|
||||
public final class ChallengeProgressPersistenceTest {
|
||||
private Context context;
|
||||
private SharedPreferences raw;
|
||||
|
||||
@Before
|
||||
public void clearProgress() {
|
||||
context = InstrumentationRegistry.getInstrumentation().getTargetContext();
|
||||
raw = context.getSharedPreferences("project_sacrifice_progress_v1", Context.MODE_PRIVATE);
|
||||
raw.edit().clear().commit();
|
||||
}
|
||||
|
||||
@After
|
||||
public void cleanProgress() {
|
||||
raw.edit().clear().commit();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void numericV2ProgressMigratesToStableLevelIdWithoutLoss() {
|
||||
LevelDefinition level = LevelCatalog.get(0);
|
||||
raw.edit().putInt("save_version", 2)
|
||||
.putBoolean("level_1_completed", true)
|
||||
.putInt("level_1_deaths", 2)
|
||||
.putLong("level_1_time", 41_000L)
|
||||
.commit();
|
||||
|
||||
ProgressStore progress = new ProgressStore(context);
|
||||
|
||||
assertEquals(3, progress.saveVersion());
|
||||
assertTrue(progress.isCompleted(level.levelId));
|
||||
assertEquals(2, progress.bestDeaths(level.levelId));
|
||||
assertEquals(41_000L, progress.bestTimeMs(level.levelId));
|
||||
assertTrue(raw.contains("level_id_" + level.levelId + "_completed"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void independentRunsAccumulateBestThreeStarsByLevelId() {
|
||||
LevelDefinition base = LevelCatalog.get(0);
|
||||
LevelDefinition level = new LevelDefinition(
|
||||
base.formatVersion, base.physicsVersion, "foundations.star-lab", "foundations",
|
||||
base.number, base.title, base.hint, base.titleRu, base.hintRu,
|
||||
base.worldWidth, base.worldHeight, base.spawnX, base.spawnY, base.goal,
|
||||
base.targetDeaths, base.targetSeconds,
|
||||
new LevelDefinition.Box(500f, 700f, 50f, 50f), base.objects,
|
||||
base.platforms, base.hazards, base.switches, base.doors);
|
||||
ProgressStore progress = new ProgressStore(context);
|
||||
|
||||
progress.recordCompletion(level, base.targetDeaths,
|
||||
base.targetSeconds * 1_000L + 5_000L, false);
|
||||
assertEquals(1, progress.earnedStars(level));
|
||||
|
||||
progress.recordCompletion(level, base.targetDeaths + 2,
|
||||
base.targetSeconds * 1_000L - 1_000L, true);
|
||||
|
||||
assertEquals(3, progress.earnedStars(level));
|
||||
assertTrue(progress.collectibleFound(level.levelId));
|
||||
assertEquals(base.targetDeaths, progress.bestDeaths(level.levelId));
|
||||
assertEquals(base.targetSeconds * 1_000L - 1_000L,
|
||||
progress.bestTimeMs(level.levelId));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
package com.projectsacrifice.game;
|
||||
|
||||
/** Production-input route for the first three-goal challenge level. */
|
||||
final class ChallengeScenarios {
|
||||
private ChallengeScenarios() {}
|
||||
|
||||
static LevelPlaytestBot.Scenario levelEighteen() {
|
||||
return LevelPlaytestBot.Scenario.builder(18, "Level 18 - threefold proof")
|
||||
.step("Approach the optional cache", 3_000L,
|
||||
LevelPlaytestBot.Input.right(),
|
||||
LevelPlaytestBot.whileDeathsAtMost(0,
|
||||
LevelPlaytestBot.groundedAliveAtOrBeyond(650f)))
|
||||
.step("Jump through the optional cache", 2_000L,
|
||||
LevelPlaytestBot.Input.rightJump(),
|
||||
LevelPlaytestBot.whileDeathsAtMost(0,
|
||||
snapshot -> snapshot.playerAlive()
|
||||
&& snapshot.collectibleFound()))
|
||||
.step("Land beyond the cache", 2_500L,
|
||||
LevelPlaytestBot.Input.right(),
|
||||
LevelPlaytestBot.whileDeathsAtMost(0,
|
||||
LevelPlaytestBot.groundedAliveAtOrBeyond(1_050f)))
|
||||
.step("Reach the relic within both efficiency targets", 5_000L,
|
||||
LevelPlaytestBot.Input.right(),
|
||||
LevelPlaytestBot.whileDeathsAtMost(0,
|
||||
GameView.AutomationSnapshot::completed))
|
||||
.build();
|
||||
}
|
||||
}
|
||||
@@ -218,8 +218,10 @@ public final class LateLevelPlaythroughTest {
|
||||
|
||||
@Override
|
||||
public void startLevel(int oneBasedLevelNumber) {
|
||||
instrumentation.runOnMainSync(
|
||||
() -> gameView.startLevelForAutomation(oneBasedLevelNumber));
|
||||
instrumentation.runOnMainSync(() -> {
|
||||
gameView.enableDeterministicAutomationClock();
|
||||
gameView.startLevelForAutomation(oneBasedLevelNumber);
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -238,19 +240,16 @@ public final class LateLevelPlaythroughTest {
|
||||
|
||||
@Override
|
||||
public void waitForNextDecision(long millis) {
|
||||
try {
|
||||
boolean inFinalTraversalWindow = throttleFinalTraversalOnly
|
||||
&& lastSnapshot != null
|
||||
&& lastSnapshot.levelNumber() == 10
|
||||
&& lastSnapshot.deaths() == 3
|
||||
&& lastSnapshot.playerX() >= 1_200f
|
||||
&& lastSnapshot.playerX() <= 2_200f;
|
||||
Thread.sleep(inFinalTraversalWindow
|
||||
? Math.max(millis, minimumDecisionMillis) : millis);
|
||||
} catch (InterruptedException interrupted) {
|
||||
Thread.currentThread().interrupt();
|
||||
throw new AssertionError("Late-level bot interrupted", interrupted);
|
||||
}
|
||||
boolean inFinalTraversalWindow = throttleFinalTraversalOnly
|
||||
&& lastSnapshot != null
|
||||
&& lastSnapshot.levelNumber() == 10
|
||||
&& lastSnapshot.deaths() == 3
|
||||
&& lastSnapshot.playerX() >= 1_200f
|
||||
&& lastSnapshot.playerX() <= 2_200f;
|
||||
long decisionMillis = inFinalTraversalWindow
|
||||
? Math.max(millis, minimumDecisionMillis) : millis;
|
||||
instrumentation.runOnMainSync(
|
||||
() -> gameView.advanceDeterministicAutomation(decisionMillis));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -38,6 +38,7 @@ public final class LevelPaginationTest {
|
||||
assertTrue(visible.contains("Steam Charge"));
|
||||
assertTrue(visible.contains("Ashen Counterweight"));
|
||||
assertTrue(visible.contains("The Whole Weight"));
|
||||
assertTrue(visible.contains("Threefold Proof"));
|
||||
assertFalse(visible.contains("The Volunteer"));
|
||||
assertTrue(visible.contains("Page 2 of 2"));
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user