This commit is contained in:
@@ -44,3 +44,4 @@ bin/
|
|||||||
/jacoco-reporter/.venv/
|
/jacoco-reporter/.venv/
|
||||||
/.claude/settings.local.json
|
/.claude/settings.local.json
|
||||||
.metals/
|
.metals/
|
||||||
|
.metals/
|
||||||
|
|||||||
@@ -1,239 +0,0 @@
|
|||||||
error id: file://<WORKSPACE>/modules/core/src/test/scala/de/nowchess/chess/engine/GameEngineEdgeCasesTest.scala:Matchers.
|
|
||||||
file://<WORKSPACE>/modules/core/src/test/scala/de/nowchess/chess/engine/GameEngineEdgeCasesTest.scala
|
|
||||||
empty definition using pc, found symbol in pc:
|
|
||||||
empty definition using semanticdb
|
|
||||||
empty definition using fallback
|
|
||||||
non-local guesses:
|
|
||||||
-org/scalatest/matchers/should/Matchers.
|
|
||||||
-org/scalatest/matchers/should/Matchers#
|
|
||||||
-org/scalatest/matchers/should/Matchers().
|
|
||||||
-Matchers.
|
|
||||||
-Matchers#
|
|
||||||
-Matchers().
|
|
||||||
-scala/Predef.Matchers.
|
|
||||||
-scala/Predef.Matchers#
|
|
||||||
-scala/Predef.Matchers().
|
|
||||||
offset: 362
|
|
||||||
uri: file://<WORKSPACE>/modules/core/src/test/scala/de/nowchess/chess/engine/GameEngineEdgeCasesTest.scala
|
|
||||||
text:
|
|
||||||
```scala
|
|
||||||
package de.nowchess.chess.engine
|
|
||||||
|
|
||||||
import scala.collection.mutable
|
|
||||||
import de.nowchess.api.board.{Board, Color}
|
|
||||||
import de.nowchess.chess.logic.GameHistory
|
|
||||||
import de.nowchess.chess.observer.{Observer, GameEvent, MoveExecutedEvent, CheckDetectedEvent, BoardResetEvent, InvalidMoveEvent}
|
|
||||||
import org.scalatest.funsuite.AnyFunSuite
|
|
||||||
import org.scalatest.matchers.should.@@Matchers
|
|
||||||
|
|
||||||
/** Tests for GameEngine edge cases and uncovered paths */
|
|
||||||
class GameEngineEdgeCasesTest extends AnyFunSuite with Matchers:
|
|
||||||
|
|
||||||
test("GameEngine handles empty input"):
|
|
||||||
val engine = new GameEngine()
|
|
||||||
val observer = new MockObserver()
|
|
||||||
engine.subscribe(observer)
|
|
||||||
|
|
||||||
engine.processUserInput("")
|
|
||||||
|
|
||||||
observer.events.size shouldBe 1
|
|
||||||
observer.events.head shouldBe an[InvalidMoveEvent]
|
|
||||||
val event = observer.events.head.asInstanceOf[InvalidMoveEvent]
|
|
||||||
event.reason should include("Please enter a valid move or command")
|
|
||||||
|
|
||||||
test("GameEngine processes quit command"):
|
|
||||||
val engine = new GameEngine()
|
|
||||||
val observer = new MockObserver()
|
|
||||||
engine.subscribe(observer)
|
|
||||||
|
|
||||||
engine.processUserInput("quit")
|
|
||||||
// Quit just returns, no events
|
|
||||||
observer.events.isEmpty shouldBe true
|
|
||||||
|
|
||||||
test("GameEngine processes q command (short form)"):
|
|
||||||
val engine = new GameEngine()
|
|
||||||
val observer = new MockObserver()
|
|
||||||
engine.subscribe(observer)
|
|
||||||
|
|
||||||
engine.processUserInput("q")
|
|
||||||
observer.events.isEmpty shouldBe true
|
|
||||||
|
|
||||||
test("GameEngine handles uppercase quit"):
|
|
||||||
val engine = new GameEngine()
|
|
||||||
val observer = new MockObserver()
|
|
||||||
engine.subscribe(observer)
|
|
||||||
|
|
||||||
engine.processUserInput("QUIT")
|
|
||||||
observer.events.isEmpty shouldBe true
|
|
||||||
|
|
||||||
test("GameEngine handles undo on empty history"):
|
|
||||||
val engine = new GameEngine()
|
|
||||||
val observer = new MockObserver()
|
|
||||||
engine.subscribe(observer)
|
|
||||||
|
|
||||||
engine.canUndo shouldBe false
|
|
||||||
engine.processUserInput("undo")
|
|
||||||
|
|
||||||
observer.events.size shouldBe 1
|
|
||||||
observer.events.head shouldBe an[InvalidMoveEvent]
|
|
||||||
val event = observer.events.head.asInstanceOf[InvalidMoveEvent]
|
|
||||||
event.reason should include("Nothing to undo")
|
|
||||||
|
|
||||||
test("GameEngine handles redo on empty redo history"):
|
|
||||||
val engine = new GameEngine()
|
|
||||||
val observer = new MockObserver()
|
|
||||||
engine.subscribe(observer)
|
|
||||||
|
|
||||||
engine.canRedo shouldBe false
|
|
||||||
engine.processUserInput("redo")
|
|
||||||
|
|
||||||
observer.events.size shouldBe 1
|
|
||||||
observer.events.head shouldBe an[InvalidMoveEvent]
|
|
||||||
val event = observer.events.head.asInstanceOf[InvalidMoveEvent]
|
|
||||||
event.reason should include("Nothing to redo")
|
|
||||||
|
|
||||||
test("GameEngine parses invalid move format"):
|
|
||||||
val engine = new GameEngine()
|
|
||||||
val observer = new MockObserver()
|
|
||||||
engine.subscribe(observer)
|
|
||||||
|
|
||||||
engine.processUserInput("invalid_move_format")
|
|
||||||
|
|
||||||
observer.events.size shouldBe 1
|
|
||||||
observer.events.head shouldBe an[InvalidMoveEvent]
|
|
||||||
val event = observer.events.head.asInstanceOf[InvalidMoveEvent]
|
|
||||||
event.reason should include("Invalid move format")
|
|
||||||
|
|
||||||
test("GameEngine handles lowercase input normalization"):
|
|
||||||
val engine = new GameEngine()
|
|
||||||
val observer = new MockObserver()
|
|
||||||
engine.subscribe(observer)
|
|
||||||
|
|
||||||
engine.processUserInput(" UNDO ") // With spaces and uppercase
|
|
||||||
|
|
||||||
observer.events.size shouldBe 1
|
|
||||||
observer.events.head shouldBe an[InvalidMoveEvent] // No moves to undo yet
|
|
||||||
|
|
||||||
test("GameEngine preserves board state on invalid move"):
|
|
||||||
val engine = new GameEngine()
|
|
||||||
val initialBoard = engine.board
|
|
||||||
|
|
||||||
engine.processUserInput("invalid")
|
|
||||||
|
|
||||||
engine.board shouldBe initialBoard
|
|
||||||
|
|
||||||
test("GameEngine preserves turn on invalid move"):
|
|
||||||
val engine = new GameEngine()
|
|
||||||
val initialTurn = engine.turn
|
|
||||||
|
|
||||||
engine.processUserInput("invalid")
|
|
||||||
|
|
||||||
engine.turn shouldBe initialTurn
|
|
||||||
|
|
||||||
test("GameEngine undo with no commands available"):
|
|
||||||
val engine = new GameEngine()
|
|
||||||
val observer = new MockObserver()
|
|
||||||
engine.subscribe(observer)
|
|
||||||
|
|
||||||
// Make a valid move
|
|
||||||
engine.processUserInput("e2e4")
|
|
||||||
observer.events.clear()
|
|
||||||
|
|
||||||
// Undo it
|
|
||||||
engine.processUserInput("undo")
|
|
||||||
|
|
||||||
// Board should be reset
|
|
||||||
engine.board shouldBe Board.initial
|
|
||||||
engine.turn shouldBe Color.White
|
|
||||||
|
|
||||||
test("GameEngine redo after undo"):
|
|
||||||
val engine = new GameEngine()
|
|
||||||
val observer = new MockObserver()
|
|
||||||
engine.subscribe(observer)
|
|
||||||
|
|
||||||
engine.processUserInput("e2e4")
|
|
||||||
val boardAfterMove = engine.board
|
|
||||||
val turnAfterMove = engine.turn
|
|
||||||
observer.events.clear()
|
|
||||||
|
|
||||||
engine.processUserInput("undo")
|
|
||||||
engine.processUserInput("redo")
|
|
||||||
|
|
||||||
engine.board shouldBe boardAfterMove
|
|
||||||
engine.turn shouldBe turnAfterMove
|
|
||||||
|
|
||||||
test("GameEngine canUndo flag tracks state correctly"):
|
|
||||||
val engine = new GameEngine()
|
|
||||||
|
|
||||||
engine.canUndo shouldBe false
|
|
||||||
engine.processUserInput("e2e4")
|
|
||||||
engine.canUndo shouldBe true
|
|
||||||
engine.processUserInput("undo")
|
|
||||||
engine.canUndo shouldBe false
|
|
||||||
|
|
||||||
test("GameEngine canRedo flag tracks state correctly"):
|
|
||||||
val engine = new GameEngine()
|
|
||||||
|
|
||||||
engine.canRedo shouldBe false
|
|
||||||
engine.processUserInput("e2e4")
|
|
||||||
engine.canRedo shouldBe false
|
|
||||||
engine.processUserInput("undo")
|
|
||||||
engine.canRedo shouldBe true
|
|
||||||
|
|
||||||
test("GameEngine command history is accessible"):
|
|
||||||
val engine = new GameEngine()
|
|
||||||
|
|
||||||
engine.commandHistory.isEmpty shouldBe true
|
|
||||||
engine.processUserInput("e2e4")
|
|
||||||
engine.commandHistory.size shouldBe 1
|
|
||||||
|
|
||||||
test("GameEngine processes multiple moves in sequence"):
|
|
||||||
val engine = new GameEngine()
|
|
||||||
val observer = new MockObserver()
|
|
||||||
engine.subscribe(observer)
|
|
||||||
observer.events.clear()
|
|
||||||
|
|
||||||
engine.processUserInput("e2e4")
|
|
||||||
engine.processUserInput("e7e5")
|
|
||||||
|
|
||||||
observer.events.size shouldBe 2
|
|
||||||
engine.commandHistory.size shouldBe 2
|
|
||||||
|
|
||||||
test("GameEngine can undo multiple moves"):
|
|
||||||
val engine = new GameEngine()
|
|
||||||
|
|
||||||
engine.processUserInput("e2e4")
|
|
||||||
engine.processUserInput("e7e5")
|
|
||||||
|
|
||||||
engine.processUserInput("undo")
|
|
||||||
engine.turn shouldBe Color.Black
|
|
||||||
|
|
||||||
engine.processUserInput("undo")
|
|
||||||
engine.turn shouldBe Color.White
|
|
||||||
|
|
||||||
test("GameEngine thread-safe operations"):
|
|
||||||
val engine = new GameEngine()
|
|
||||||
|
|
||||||
// Access from synchronized methods
|
|
||||||
val board = engine.board
|
|
||||||
val history = engine.history
|
|
||||||
val turn = engine.turn
|
|
||||||
val canUndo = engine.canUndo
|
|
||||||
val canRedo = engine.canRedo
|
|
||||||
|
|
||||||
board shouldBe Board.initial
|
|
||||||
canUndo shouldBe false
|
|
||||||
canRedo shouldBe false
|
|
||||||
|
|
||||||
private class MockObserver extends Observer:
|
|
||||||
val events = mutable.ListBuffer[GameEvent]()
|
|
||||||
|
|
||||||
override def onGameEvent(event: GameEvent): Unit =
|
|
||||||
events += event
|
|
||||||
|
|
||||||
```
|
|
||||||
|
|
||||||
|
|
||||||
#### Short summary:
|
|
||||||
|
|
||||||
empty definition using pc, found symbol in pc:
|
|
||||||
@@ -1,6 +0,0 @@
|
|||||||
#FileLock
|
|
||||||
#Mon Mar 30 19:30:47 CEST 2026
|
|
||||||
hostName=localhost
|
|
||||||
id=19d3fcc4dcfa8c83c3d300e9ee4e47676131485b9f0
|
|
||||||
method=file
|
|
||||||
server=localhost\:42185
|
|
||||||
Reference in New Issue
Block a user