Skip to content

Commit cdbe999

Browse files
CopilotbedaHovorka
andcommitted
Replace assertions in Train.kt and SimpleTrack.kt
- Replaced 15 assertions + 2 NPE throws in Train.kt with require* functions - Replaced 7 assertions in SimpleTrack.kt with require* functions - All original error messages and comments preserved - Legacy null handling maintained Co-authored-by: bedaHovorka <5263405+bedaHovorka@users.noreply.github.com>
1 parent 07bc4b9 commit cdbe999

2 files changed

Lines changed: 35 additions & 31 deletions

File tree

src/main/kotlin/cz/vutbr/fit/interlockSim/objects/tracks/SimpleTrack.kt

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@
99
*/
1010
package cz.vutbr.fit.interlockSim.objects.tracks
1111

12+
import cz.vutbr.fit.interlockSim.exceptions.requireSimulation
13+
import cz.vutbr.fit.interlockSim.exceptions.requireSimulationNotNull
1214
import cz.vutbr.fit.interlockSim.objects.paths.PathElement
1315
import cz.vutbr.fit.interlockSim.objects.paths.PathSeparator
1416
import cz.vutbr.fit.interlockSim.sim.TrackOperationException
@@ -61,7 +63,7 @@ abstract class SimpleTrack(
6163
"${Process.time()} CONFLICT: Block $this collision! Existing occupant=${`in`}, occupant=$occupant"
6264
}
6365
}
64-
assert(`in` == null) // tak to zavani srazkou (posuny neimplementovany)
66+
requireSimulation(`in` == null) { "Track occupant collision - must be null on entry (shunting not implemented)" }
6567
assertGoodStateChange(TrackFacility.State.RESERVED, TrackFacility.State.OCCUPIED)
6668
`in` = occupant
6769
from = null
@@ -71,7 +73,7 @@ abstract class SimpleTrack(
7173
logger.info {
7274
"${Process.time()} Block $this EXIT: occupant=$occupant, state=OCCUPIED->FREE"
7375
}
74-
assert(`in` === occupant)
76+
requireSimulation(`in` === occupant) { "Track occupant mismatch on leave" }
7577
assertGoodStateChange(TrackFacility.State.OCCUPIED, TrackFacility.State.FREE)
7678
`in` = null
7779
}
@@ -96,12 +98,12 @@ abstract class SimpleTrack(
9698
}
9799

98100
override fun isSetUpPath(sep: PathSeparator): Boolean {
99-
assert(sep != null)
101+
requireSimulationNotNull(sep) { "Path separator must not be null" }
100102
val isSetUp: Boolean
101103
if (state == TrackFacility.State.RESERVED) {
102104
isSetUp = sep === from
103105
} else {
104-
assert(from == null)
106+
requireSimulation(from == null) { "From separator must be null when state is not RESERVED" }
105107
isSetUp = false
106108
}
107109
logger.debug { "Track $this isSetUpPath check: sep=$sep, state=$state, from=$from, result=$isSetUp" }
@@ -147,7 +149,7 @@ abstract class SimpleTrack(
147149
) {
148150
// mozna nekdy jina vyjimka...
149151
val stateChange = stateChange(from, to)
150-
assert(stateChange) { errorStateMessage(from) }
152+
requireSimulation(stateChange) { errorStateMessage(from) }
151153
}
152154

153155
override fun length(): Double = length
@@ -158,13 +160,13 @@ abstract class SimpleTrack(
158160

159161
override fun getTrackOccupant(): TrackOccupant {
160162
// Note: Track must be occupied when this method is called, but field is nullable for initialization
161-
// This violates the interface contract if called when track is free - assert checks this
162-
assert(`in` != null) { "Track occupant should not be null - must call when track is OCCUPIED" }
163+
// This violates the interface contract if called when track is free - requireSimulation checks this
164+
requireSimulationNotNull(`in`) { "Track occupant should not be null - must call when track is OCCUPIED" }
163165
return `in`!!
164166
}
165167

166168
override fun maxSpeed(from: PathSeparator?): Double {
167-
assert(isEnd(from!!))
169+
requireSimulation(isEnd(from!!)) { "Path separator must be an end of this track" }
168170
return speeds[from]!!
169171
}
170172
}

src/main/kotlin/cz/vutbr/fit/interlockSim/sim/Train.kt

Lines changed: 25 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@ package cz.vutbr.fit.interlockSim.sim
1111

1212
import cz.vutbr.fit.interlockSim.context.SimulationContext
1313
import cz.vutbr.fit.interlockSim.context.SimulationContext.ReportType
14+
import cz.vutbr.fit.interlockSim.exceptions.requireSimulation
15+
import cz.vutbr.fit.interlockSim.exceptions.requireSimulationNotNull
1416
import cz.vutbr.fit.interlockSim.objects.cells.InOut
1517
import cz.vutbr.fit.interlockSim.objects.cells.RailSemaphore
1618
import cz.vutbr.fit.interlockSim.objects.cells.RailSemaphore.Signal
@@ -87,7 +89,7 @@ class Train :
8789

8890
final override fun actions() {
8991
var where: PathSeparator = timetable.getIn()
90-
assert(where != null)
92+
requireSimulationNotNull(where) { "PathSeparator from timetable.getIn() must not be null" }
9193
// out se muze rovnat in => bude vyreseno "prepojenim lokomotivy"
9294

9395
while (true) {
@@ -102,7 +104,9 @@ class Train :
102104
separatorAction(where, current, next)
103105

104106
onNext = true
105-
assert(position.isActive && pv.isActive)
107+
requireSimulation(position.isActive && pv.isActive) {
108+
"Position and velocity integration must be active"
109+
}
106110
waitUntil {
107111
// dtmin - horni odhad zmeny pri poslednim kroku numericke metody behem dobrzdovani k uzlu
108112
position.state + dtMin >= nextLength
@@ -111,7 +115,7 @@ class Train :
111115
position.state -= nextLength
112116
totalLenghtOfPreviousBlocks += nextLength
113117
where = next!!.getSecondEnd(where)
114-
assert(where != null)
118+
requireSimulationNotNull(where) { "PathSeparator from getSecondEnd() must not be null" }
115119
current = next
116120
onNext = false
117121
}
@@ -173,8 +177,10 @@ class Train :
173177
next: TrackSection?
174178
) {
175179
// isSeparatorInDirection accepts nullable Track parameters
176-
assert(context.isSeparatorInDirection(separator as OrientedPathSeparator, next, current)) { semaphore }
177-
assert(semaphore.getSignal() != null)
180+
requireSimulation(context.isSeparatorInDirection(separator as OrientedPathSeparator, next, current)) {
181+
"Separator must be in direction, semaphore: $semaphore"
182+
}
183+
requireSimulationNotNull(semaphore.getSignal()) { "Semaphore signal must not be null" }
178184
logger.info {
179185
"${jDisco.Process.time()} SENSOR: Train $number detected at semaphore " +
180186
"${if (semaphore.getName() != null) semaphore.getName() else semaphore.hashCode()}, " +
@@ -185,7 +191,7 @@ class Train :
185191
// EXTENSION stanice
186192

187193
if (semaphore.getSignal() == RailSemaphore.Signal.STOP) {
188-
assert(getVelocity() >= 0)
194+
requireSimulation(getVelocity() >= 0) { "Velocity must be non-negative when approaching semaphore" }
189195
logger.debug { "Train $number approaching semaphore with STOP signal, halting" }
190196
fireStop()
191197
context.report(semaphore.getSignal().toString(), this@Train, ReportType.TRAIN_EVENTS)
@@ -247,7 +253,7 @@ class Train :
247253
}
248254

249255
private fun fireStop() {
250-
assert(getVelocity() >= 0)
256+
requireSimulation(getVelocity() >= 0) { "Velocity must be non-negative when stopping" }
251257
front.stop()
252258
tail.stop()
253259
this@Train.stop()
@@ -271,9 +277,9 @@ class Train :
271277
semaphore: RailSemaphore,
272278
path: Path?
273279
) {
274-
assert(path != null)
280+
requireSimulationNotNull(path) { "Path must not be null in accelerate method" }
275281
val thisSignal: Signal = semaphore.getSignal()
276-
assert(thisSignal.isAllowing()) { thisSignal }
282+
requireSimulation(thisSignal.isAllowing()) { "Signal must be allowing: $thisSignal" }
277283
@Suppress("RECEIVER_NULLABILITY_MISMATCH_BASED_ON_JAVA_ANNOTATIONS")
278284
val nextSemaphore: RailSemaphore = path!!.getLastPathSemaphore()
279285
val nextSignal: Signal = nextSemaphore.getSignal()
@@ -313,15 +319,17 @@ class Train :
313319
val semaphore: RailSemaphore = where
314320
semaphoreAction(semaphore, semaphore, current, next)
315321
} else if (where == timetable.getIn() && next != null) {
316-
assert(getAcceleration() != null)
322+
requireSimulationNotNull(getAcceleration()) { "Acceleration must not be null at timetable entry" }
317323
semaphoreAction((where as InOut).getInSemaphore(), where, current, next)
318324
} else {
319325
@Suppress("RECEIVER_NULLABILITY_MISMATCH_BASED_ON_JAVA_ANNOTATIONS")
320326
pathToSemaphore?.removeFirst()
321327
@Suppress("RECEIVER_NULLABILITY_MISMATCH_BASED_ON_JAVA_ANNOTATIONS")
322328
pathToSemaphore?.removeFirst()
323329
}
324-
assert(pathToSemaphore?.getFirst() == where) { pathToSemaphore ?: "null" }
330+
requireSimulation(pathToSemaphore?.getFirst() == where) {
331+
"Path to semaphore first element must match current position: ${pathToSemaphore ?: "null"}"
332+
}
325333
if (next != null) next.enter(this@Train)
326334
}
327335
}
@@ -358,7 +366,7 @@ class Train :
358366
Math.abs(front.getTotalDistance() - tail.getTotalDistance() - getLength()) <= maxAbsError
359367

360368
override fun report(reportObj: StringBuilder): StringBuilder {
361-
assert(reportObj != null)
369+
requireSimulationNotNull(reportObj) { "Report object must not be null" }
362370
reportObj.append(front.getTotalDistance()).append(' ').append(tail.getTotalDistance())
363371
return reportObj.append(' ').append(getLength())
364372
}
@@ -409,7 +417,7 @@ class Train :
409417
}
410418

411419
override fun iteration() {
412-
assert(currentCondition != null)
420+
requireSimulationNotNull(currentCondition) { "Current condition must not be null during iteration" }
413421
accelerate = true
414422
logger.trace {
415423
"Train $number motor iteration: target speed $targetSpeed, " +
@@ -433,7 +441,7 @@ class Train :
433441
speed: Double,
434442
test: AccelerationStopTest
435443
) {
436-
assert(speed >= 0)
444+
requireSimulation(speed >= 0) { "Speed must be non-negative: $speed" }
437445
targetSpeed = speed
438446
currentCondition = AccelerationStopCondition(test)
439447
cancelAccelerating()
@@ -469,7 +477,7 @@ class Train :
469477
}
470478
context.report("in on warning $normalSpeed", this@Train, ReportType._DEBUG)
471479

472-
assert(getVelocity() >= 0)
480+
requireSimulation(getVelocity() >= 0) { "Velocity must be non-negative in onWarning" }
473481
privateAccelerateTo(normalSpeed, AccelerationStopTest.TO_HALF_SPEED)
474482
}
475483

@@ -526,14 +534,8 @@ class Train :
526534
* @param timetable
527535
*/
528536
constructor(context: SimulationContext?, timetable: Timetable?) {
529-
if (context == null) {
530-
throw NullPointerException("context must not be null")
531-
}
532-
if (timetable == null) {
533-
throw NullPointerException("timetable must not be null")
534-
}
535-
this.context = context
536-
this.timetable = timetable
537+
this.context = requireSimulationNotNull(context) { "context must not be null" }
538+
this.timetable = requireSimulationNotNull(timetable) { "timetable must not be null" }
537539
this.length = timetable.getLength()
538540
number = ++count
539541
trainPrefix = "Train #$number"

0 commit comments

Comments
 (0)