@@ -68,19 +68,35 @@ func TestMain(m *testing.M) {
6868// - DUT software version is the same after the reboot.
6969//
7070// Topology:
71- // dut:port1 <--> ate:port1
7271//
73- // Test notes:
74- // - A RebootRequest requests the specified target be rebooted using the specified
75- // method after the specified delay. Only the DEFAULT method with a delay of 0
76- // is guaranteed to be accepted for all target types.
77- // - A RebootMethod determines what should be done with a target when a Reboot is
78- // requested. Only the COLD method is required to be supported by all
79- // targets. Methods the target does not support should result in failure.
72+ // dut:port1 <--> ate:port1
8073//
81- // - gnoi operation commands can be sent and tested using CLI command grpcurl.
82- // https://github.com/fullstorydev/grpcurl
74+ // Test notes:
75+ // - A RebootRequest requests the specified target be rebooted using the specified
76+ // method after the specified delay. Only the DEFAULT method with a delay of 0
77+ // is guaranteed to be accepted for all target types.
78+ // - A RebootMethod determines what should be done with a target when a Reboot is
79+ // requested. Only the COLD method is required to be supported by all
80+ // targets. Methods the target does not support should result in failure.
8381//
82+ // - gnoi operation commands can be sent and tested using CLI command grpcurl.
83+ // https://github.com/fullstorydev/grpcurl
84+
85+ // activeCompSet returns the set of component names whose oper-status is ACTIVE.
86+ // Using only ACTIVE components for the pre/post reboot comparison makes the check
87+ // platform-agnostic: it does not depend on whether a platform reports DISABLED,
88+ // UNSET, INACTIVE, or other transient states consistently across reboots.
89+ func activeCompSet (t * testing.T , dut * ondatra.DUTDevice ) map [string ]bool {
90+ t .Helper ()
91+ comps := gnmi .GetAll (t , dut , gnmi .OC ().ComponentAny ().State ())
92+ active := make (map [string ]bool )
93+ for _ , c := range comps {
94+ if c .GetOperStatus () == oc .PlatformTypes_COMPONENT_OPER_STATUS_ACTIVE {
95+ active [c .GetName ()] = true
96+ }
97+ }
98+ return active
99+ }
84100
85101func TestChassisReboot (t * testing.T ) {
86102 dut := ondatra .DUT (t , "dut" )
@@ -107,20 +123,27 @@ func TestChassisReboot(t *testing.T) {
107123 }},
108124 }
109125
110- versions := gnmi .GetAll (t , dut , gnmi .OC ().ComponentAny ().SoftwareVersion ().State ())
111- expectedVersion := uniqueSortedStrings (t , versions )
112- t .Logf ("DUT software version: %v" , expectedVersion )
113-
114- preRebootCompStatus := gnmi .GetAll (t , dut , gnmi .OC ().ComponentAny ().OperStatus ().State ())
115- preRebootCompDebug := gnmi .GetAll (t , dut , gnmi .OC ().ComponentAny ().State ())
116- var preCompMatrix []string
117- for _ , preComp := range preRebootCompDebug {
118- if preComp .GetOperStatus () != oc .PlatformTypes_COMPONENT_OPER_STATUS_UNSET {
119- preCompMatrix = append (preCompMatrix , preComp .GetName ()+ ":" + preComp .GetOperStatus ().String ())
120- }
121- }
122126 for _ , tc := range cases {
123127 t .Run (tc .desc , func (t * testing.T ) {
128+ // Capture pre-reboot baseline inside each subtest so that each reboot
129+ // is compared against the actual state of the DUT at the start of that
130+ // iteration, rather than a potentially stale snapshot from before a
131+ // prior reboot.
132+ versions := gnmi .GetAll (t , dut , gnmi .OC ().ComponentAny ().SoftwareVersion ().State ())
133+ expectedVersion := uniqueSortedStrings (t , versions )
134+ t .Logf ("DUT software version before reboot: %v" , expectedVersion )
135+
136+ preActiveComps := activeCompSet (t , dut )
137+ t .Logf ("Pre-reboot active component count: %v" , len (preActiveComps ))
138+
139+ preRebootCompDebug := gnmi .GetAll (t , dut , gnmi .OC ().ComponentAny ().State ())
140+ var preCompMatrix []string
141+ for _ , preComp := range preRebootCompDebug {
142+ if preComp .GetOperStatus () != oc .PlatformTypes_COMPONENT_OPER_STATUS_UNSET {
143+ preCompMatrix = append (preCompMatrix , preComp .GetName ()+ ":" + preComp .GetOperStatus ().String ())
144+ }
145+ }
146+
124147 gnoiClient , err := dut .RawAPIs ().BindingDUT ().DialGNOI (t .Context ())
125148 if err != nil {
126149 t .Fatalf ("Error dialing gNOI: %v" , err )
@@ -215,7 +238,7 @@ func TestChassisReboot(t *testing.T) {
215238 }
216239
217240 startComp := time .Now ()
218- t .Logf ("Wait for all the components on DUT to come up ." )
241+ t .Logf ("Wait for all previously active components on DUT to become ACTIVE ." )
219242 {
220243 ticker := time .NewTicker (componentPollInterval )
221244 defer ticker .Stop ()
@@ -225,6 +248,14 @@ func TestChassisReboot(t *testing.T) {
225248 for {
226249 select {
227250 case <- timeout :
251+ postActiveComps := activeCompSet (t , dut )
252+ var missing []string
253+ for name := range preActiveComps {
254+ if ! postActiveComps [name ] {
255+ missing = append (missing , name )
256+ }
257+ }
258+ sort .Strings (missing )
228259 postRebootCompDebug := gnmi .GetAll (t , dut , gnmi .OC ().ComponentAny ().State ())
229260 var postCompMatrix []string
230261 for _ , postComp := range postRebootCompDebug {
@@ -235,12 +266,18 @@ func TestChassisReboot(t *testing.T) {
235266 if rebootDiff := cmp .Diff (preCompMatrix , postCompMatrix ); rebootDiff != "" {
236267 t .Logf ("[DEBUG] Unexpected diff after reboot (-component missing from pre reboot, +component added from pre reboot): %v." , rebootDiff )
237268 }
238- postRebootCompStatus := gnmi .GetAll (t , dut , gnmi .OC ().ComponentAny ().OperStatus ().State ())
239- t .Fatalf ("Timeout exceeded: There's a difference in components obtained in pre reboot: %v and post reboot: %v." , len (preRebootCompStatus ), len (postRebootCompStatus ))
269+ t .Fatalf ("Timeout exceeded: the following components were ACTIVE before reboot but are not ACTIVE after reboot: %v" , missing )
240270 case <- ticker .C :
241- postRebootCompStatus := gnmi .GetAll (t , dut , gnmi .OC ().ComponentAny ().OperStatus ().State ())
242- if len (preRebootCompStatus ) == len (postRebootCompStatus ) {
243- t .Logf ("All components on the DUT are in responsive state after %.2f seconds." , time .Since (startComp ).Seconds ())
271+ postActiveComps := activeCompSet (t , dut )
272+ allUp := true
273+ for name := range preActiveComps {
274+ if ! postActiveComps [name ] {
275+ allUp = false
276+ break
277+ }
278+ }
279+ if allUp {
280+ t .Logf ("All previously active components on the DUT are ACTIVE again after %.2f seconds." , time .Since (startComp ).Seconds ())
244281 break compLoop
245282 }
246283 }
0 commit comments