aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMartin Kagamino Lehoux <martin@lehoux.net>2026-01-15 23:03:12 +0100
committerMartin Kagamino Lehoux <martin@lehoux.net>2026-01-15 23:03:12 +0100
commitd1e361f74e0d424b4d6a99adea1463982d9f1475 (patch)
tree5a4cebb4c9fc09d0094c252fcb14a16d624945b2
parent13626410c4d6db7fdc15ded5ee7865fcdbf0b88a (diff)
First integration test
-rw-r--r--README.md6
-rw-r--r--integration_test.go64
-rw-r--r--main.go4
3 files changed, 74 insertions, 0 deletions
diff --git a/README.md b/README.md
index e3ba5a5..e4cca5c 100644
--- a/README.md
+++ b/README.md
@@ -2,6 +2,11 @@
- Restart after kernel update until `glxinfo | grep "OpenGL version"` works
+## Testing
+
+- **Integration tests** Use `Update()` to run N ticks.
+- **Performance benchmarks**
+
## TODO
- see the current action (debug?)
@@ -19,6 +24,7 @@
- perf: measure frame budget
- rename Selection to Selectable
- extract todos in todo list
+- abstraction between ebiten and update to handle inputs in a simulation?
## Bugs
diff --git a/integration_test.go b/integration_test.go
new file mode 100644
index 0000000..8305719
--- /dev/null
+++ b/integration_test.go
@@ -0,0 +1,64 @@
+package main
+
+import (
+ "testing"
+ "time"
+
+ "age_of_empires/physics"
+)
+
+func TestGatherLoop(t *testing.T) {
+ // Initialize Game
+ game := &Game{}
+
+ // Town Center (Storage) at -100,0 (different grid cell from unit at 0,0)
+ tcBuilder := NewEntityBuilder().
+ WithPosition(physics.Point{X: -100, Y: 0}).
+ WithResourceStorage()
+ _ = game.Append(tcBuilder.Build())
+
+ // Mine (Source) at 0, 200
+ mineBuilder := NewEntityBuilder().
+ WithPosition(physics.Point{X: 0, Y: 200}).
+ WithResourceSource(100)
+ mineID := game.Append(mineBuilder.Build())
+
+ // Unit (Gatherer) at 0, 0
+ unitBuilder := NewEntityBuilder().
+ WithPosition(physics.Point{X: 0, Y: 0}).
+ WithMove().
+ WithOrder().
+ WithResourceGatherer(10)
+ unitID := game.Append(unitBuilder.Build())
+
+ // Set up simulated time
+ simTime := time.Now()
+ game.NowFunc = func() time.Time { return simTime }
+
+ // Simulate user selection: select the unit
+ game.GlobalSelection.Selected = append(game.GlobalSelection.Selected, unitID)
+
+ // Simulate right-click on mine position to trigger Gather via MainAction
+ minePosition := game.Position[mineID]
+ MainAction(game, unitID, minePosition, game.getMoveMap())
+
+ initialResources := game.ResourceAmount
+ dt := 16 * time.Millisecond
+ maxTicks := 100_000
+
+ deposited := false
+
+ for i := 0; i < maxTicks; i++ {
+ simTime = simTime.Add(dt)
+ game.Update()
+
+ if game.ResourceAmount > initialResources {
+ deposited = true
+ break
+ }
+ }
+
+ if !deposited {
+ t.Errorf("Unit failed to gather resources within %d ticks. ResourceAmount: %d", maxTicks, game.ResourceAmount)
+ }
+}
diff --git a/main.go b/main.go
index e67e50b..80ee064 100644
--- a/main.go
+++ b/main.go
@@ -36,6 +36,7 @@ type Game struct {
ResourceAmount int
FaceSource *text.GoTextFaceSource
UnitBuilder EntityBuilder
+ NowFunc func() time.Time
// Components
Mask []ecs.Mask
// Entities []*Entity
@@ -53,6 +54,9 @@ type Game struct {
}
func (g Game) Now() time.Time {
+ if g.NowFunc != nil {
+ return g.NowFunc()
+ }
return time.Now()
}