package com.projectsacrifice.game; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; import android.content.Context; import android.content.SharedPreferences; 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; @RunWith(AndroidJUnit4.class) public final class GameSessionRestoreTest { @Test public void recreationRestoresActivePuzzleBodiesTimersAndPausedSafety() { GameSessionSnapshot[] before = new GameSessionSnapshot[1]; try (ActivityScenario activity = ActivityScenario.launch(MainActivity.class)) { GameView[] view = new GameView[1]; activity.onActivity(current -> { view[0] = current.gameViewForAutomation(); view[0].enableDeterministicAutomationClock(); view[0].startLevelForAutomation(5); view[0].setAutomationInput(false, true, false); for (int decision = 0; decision < 400 && view[0].automationSnapshot().deaths() == 0; decision++) { view[0].advanceDeterministicAutomation(16L); } assertEquals(1, view[0].automationSnapshot().deaths()); assertEquals(1, view[0].automationSnapshot().corpseCount()); view[0].setAutomationInput(false, false, false); before[0] = view[0].sessionSnapshotForAutomation(); }); activity.recreate(); activity.onActivity(current -> { view[0] = current.gameViewForAutomation(); GameSessionSnapshot after = view[0].sessionSnapshotForAutomation(); assertEquals(before[0].levelNumber(), after.levelNumber()); assertEquals(before[0].deaths(), after.deaths()); assertEquals(before[0].elapsedSeconds(), after.elapsedSeconds(), 0.001f); assertEquals(before[0].player().x(), after.player().x(), 0.001f); assertEquals(before[0].player().alive(), after.player().alive()); assertEquals(before[0].bodies().size(), after.bodies().size()); assertEquals(before[0].bodies().get(0).deathType(), after.bodies().get(0).deathType()); assertEquals(before[0].platformMotionTimes(), after.platformMotionTimes()); assertEquals(before[0].timedSignals(), after.timedSignals()); assertTrue(view[0].automationSnapshot().visiblyPaused()); assertFalse(view[0].automationSnapshot().inputActive()); current.onBackPressed(); view[0].enableDeterministicAutomationClock(); view[0].advanceDeterministicAutomation(1_000L); assertTrue(view[0].automationSnapshot().playerAlive()); }); } } @Test public void legacyProgressMigratesInPlaceWithoutLosingCompletion() { Context context = InstrumentationRegistry.getInstrumentation().getTargetContext(); SharedPreferences legacy = context.getSharedPreferences( "project_sacrifice_progress_v1", Context.MODE_PRIVATE); legacy.edit().clear() .putInt("unlocked", 6) .putBoolean("level_5_completed", true) .putInt("level_5_deaths", 3) .putLong("level_5_time", 42_000L) .commit(); ProgressStore migrated = new ProgressStore(context); assertEquals(ProgressStore.CURRENT_SAVE_VERSION, migrated.saveVersion()); assertEquals(6, migrated.unlockedCount()); assertTrue(migrated.isCompleted(5)); assertEquals(3, migrated.bestDeaths(5)); assertEquals(42_000L, migrated.bestTimeMs(5)); legacy.edit().clear().commit(); } }