11package main
22
33import (
4+ "fmt"
45 "sync"
56 "testing"
67 "time"
@@ -11,6 +12,7 @@ import (
1112
1213func TestTracker_Update (t * testing.T ) {
1314 tracker := NewTracker (5 * time .Minute )
15+ defer tracker .Stop ()
1416
1517 loc := & LocationReport {
1618 VehicleID : "bus-1" ,
@@ -36,6 +38,7 @@ func TestTracker_Update(t *testing.T) {
3638
3739func TestTracker_UpdateOverwrites (t * testing.T ) {
3840 tracker := NewTracker (5 * time .Minute )
41+ defer tracker .Stop ()
3942
4043 tracker .Update (& LocationReport {VehicleID : "bus-1" , Latitude : 1.0 , Longitude : 2.0 , Timestamp : 1 })
4144 tracker .Update (& LocationReport {VehicleID : "bus-1" , Latitude : 3.0 , Longitude : 4.0 , Timestamp : 2 })
@@ -48,6 +51,7 @@ func TestTracker_UpdateOverwrites(t *testing.T) {
4851
4952func TestTracker_MultipleVehicles (t * testing.T ) {
5053 tracker := NewTracker (5 * time .Minute )
54+ defer tracker .Stop ()
5155
5256 tracker .Update (& LocationReport {VehicleID : "bus-1" , Latitude : 1 , Longitude : 2 , Timestamp : 1 })
5357 tracker .Update (& LocationReport {VehicleID : "bus-2" , Latitude : 3 , Longitude : 4 , Timestamp : 2 })
@@ -58,6 +62,7 @@ func TestTracker_MultipleVehicles(t *testing.T) {
5862
5963func TestTracker_Staleness (t * testing.T ) {
6064 tracker := NewTracker (1 * time .Millisecond )
65+ defer tracker .Stop ()
6166
6267 tracker .Update (& LocationReport {VehicleID : "bus-1" , Latitude : 1 , Longitude : 2 , Timestamp : 1 })
6368 time .Sleep (5 * time .Millisecond )
@@ -68,6 +73,7 @@ func TestTracker_Staleness(t *testing.T) {
6873
6974func TestTracker_Concurrent (t * testing.T ) {
7075 tracker := NewTracker (5 * time .Minute )
76+ defer tracker .Stop ()
7177 var wg sync.WaitGroup
7278
7379 for i := 0 ; i < 100 ; i ++ {
@@ -92,6 +98,25 @@ func TestTracker_Concurrent(t *testing.T) {
9298 assert .Len (t , active , 1 )
9399}
94100
101+ func TestTracker_ConcurrentWithCleanup (t * testing.T ) {
102+ tracker := NewTracker (5 * time .Millisecond )
103+ defer tracker .Stop ()
104+
105+ var wg sync.WaitGroup
106+ for i := 0 ; i < 100 ; i ++ {
107+ wg .Add (1 )
108+ go func (id int ) {
109+ defer wg .Done ()
110+ tracker .Update (& LocationReport {
111+ VehicleID : fmt .Sprintf ("bus-%d" , id ),
112+ Timestamp : 1 ,
113+ })
114+ tracker .ActiveVehicles ()
115+ }(i )
116+ }
117+ wg .Wait ()
118+ }
119+
95120func TestNewTracker_PanicsOnInvalidMaxAge (t * testing.T ) {
96121 assert .PanicsWithValue (t , "maxAge must be positive" , func () {
97122 NewTracker (0 )
@@ -101,3 +126,43 @@ func TestNewTracker_PanicsOnInvalidMaxAge(t *testing.T) {
101126 NewTracker (- 1 * time .Second )
102127 }, "NewTracker with negative duration should panic" )
103128}
129+
130+ func TestTracker_Cleanup (t * testing.T ) {
131+
132+ maxAge := 10 * time .Millisecond
133+ tracker := NewTracker (maxAge )
134+ defer tracker .Stop ()
135+
136+ tracker .Update (& LocationReport {VehicleID : "bus-1" , Timestamp : 1 })
137+
138+ assert .Eventually (t , func () bool {
139+ tracker .mu .RLock ()
140+ defer tracker .mu .RUnlock ()
141+ return len (tracker .vehicles ) == 0
142+ }, 100 * time .Millisecond , 5 * time .Millisecond , "stale vehicle should be deleted from internal map" )
143+ }
144+
145+ func TestTracker_StopIsIdempotent (t * testing.T ) {
146+ tracker := NewTracker (5 * time .Minute )
147+ tracker .Stop ()
148+ assert .NotPanics (t , func () { tracker .Stop () })
149+ }
150+
151+ func TestTracker_CleanupPreservesFreshVehicles (t * testing.T ) {
152+ maxAge := 50 * time .Millisecond
153+ tracker := NewTracker (maxAge )
154+ defer tracker .Stop ()
155+
156+ tracker .Update (& LocationReport {VehicleID : "old-bus" , Timestamp : 1 })
157+ time .Sleep (60 * time .Millisecond )
158+ tracker .Update (& LocationReport {VehicleID : "new-bus" , Timestamp : 2 })
159+
160+ assert .Eventually (t , func () bool {
161+ tracker .mu .RLock ()
162+ defer tracker .mu .RUnlock ()
163+ _ , hasOld := tracker .vehicles ["old-bus" ]
164+ _ , hasNew := tracker .vehicles ["new-bus" ]
165+ return ! hasOld && hasNew
166+ }, 200 * time .Millisecond , 5 * time .Millisecond ,
167+ "cleanup should remove old-bus but keep new-bus" )
168+ }
0 commit comments