@@ -202,3 +202,124 @@ func TestReadSecurityInfo(t *testing.T) {
202202 })
203203 }
204204}
205+
206+ func TestSecurityInfoFlushInput (t * testing.T ) {
207+ // Test that securityInfo clears any stray input before querying.
208+ // This verifies the fix for the ESP32-S3 issue where SLIP frame delimiters
209+ // in the input buffer corrupted the response (command 0x14 failed: status=0xC0).
210+ buf20 := make ([]byte , 20 )
211+ binary .LittleEndian .PutUint32 (buf20 [0 :4 ], 0x05 )
212+ buf20 [4 ] = 0x03
213+ binary .LittleEndian .PutUint32 (buf20 [12 :16 ], 0x0009 )
214+
215+ mc := & mockConnection {
216+ securityInfoFunc : func () ([]byte , error ) {
217+ return buf20 , nil
218+ },
219+ }
220+ f := & Flasher {conn : mc }
221+
222+ si , err := f .readSecurityInfo ()
223+ if err != nil {
224+ t .Fatalf ("unexpected error: %v" , err )
225+ }
226+
227+ if si .Flags != 0x05 {
228+ t .Errorf ("Flags = 0x%x, want 0x05" , si .Flags )
229+ }
230+
231+ if si == nil {
232+ t .Error ("expected SecurityInfo to be populated" )
233+ }
234+ }
235+
236+ func TestSecurityInfoCaching (t * testing.T ) {
237+ // Test that security info is cached from the first call (ROM before stub loads)
238+ // and subsequent calls return the cached bytes without re-issuing the command.
239+ buf20 := make ([]byte , 20 )
240+ binary .LittleEndian .PutUint32 (buf20 [0 :4 ], 0x05 ) // flags
241+ buf20 [4 ] = 0x03 // FlashCryptCnt
242+ binary .LittleEndian .PutUint32 (buf20 [12 :16 ], 0x0009 ) // ChipID
243+
244+ callCount := 0
245+ mc := & mockConnection {
246+ securityInfoFunc : func () ([]byte , error ) {
247+ callCount ++
248+ return buf20 , nil
249+ },
250+ }
251+ f := & Flasher {conn : mc }
252+
253+ // First call should invoke the connection
254+ si1 , err := f .readSecurityInfo ()
255+ if err != nil {
256+ t .Fatalf ("first call: unexpected error: %v" , err )
257+ }
258+ if si1 .Flags != 0x05 {
259+ t .Errorf ("first call: Flags = 0x%x, want 0x05" , si1 .Flags )
260+ }
261+ if callCount != 1 {
262+ t .Errorf ("first call: expected 1 connection call, got %d" , callCount )
263+ }
264+
265+ // Second call should use the cached bytes without calling conn.securityInfo()
266+ si2 , err := f .readSecurityInfo ()
267+ if err != nil {
268+ t .Fatalf ("second call: unexpected error: %v" , err )
269+ }
270+ if si2 .Flags != 0x05 {
271+ t .Errorf ("second call: Flags = 0x%x, want 0x05" , si2 .Flags )
272+ }
273+ if callCount != 1 {
274+ t .Errorf ("second call: expected 1 total connection call, got %d" , callCount )
275+ }
276+
277+ // Results should be identical
278+ if si1 .Flags != si2 .Flags || si1 .FlashCryptCnt != si2 .FlashCryptCnt {
279+ t .Error ("cached result differs from initial result" )
280+ }
281+ }
282+
283+ func TestSecurityInfoCachingWithStubFailure (t * testing.T ) {
284+ // Test that when security info is cached from ROM, a stub failure (0xC0)
285+ // on a second call to GetSecurityInfo() returns the cached data instead.
286+ buf20 := make ([]byte , 20 )
287+ binary .LittleEndian .PutUint32 (buf20 [0 :4 ], 0x05 ) // flags
288+ buf20 [4 ] = 0x03 // FlashCryptCnt
289+ binary .LittleEndian .PutUint32 (buf20 [12 :16 ], 0x0009 ) // ChipID
290+
291+ callCount := 0
292+ mc := & mockConnection {
293+ securityInfoFunc : func () ([]byte , error ) {
294+ callCount ++
295+ if callCount == 1 {
296+ // First call (ROM) succeeds
297+ return buf20 , nil
298+ }
299+ // Second call (stub) would fail, but it won't be called
300+ return nil , errors .New ("stub does not support command 0x14" )
301+ },
302+ }
303+ f := & Flasher {conn : mc }
304+
305+ // First call succeeds and caches the data
306+ si1 , err := f .readSecurityInfo ()
307+ if err != nil {
308+ t .Fatalf ("first call: unexpected error: %v" , err )
309+ }
310+ if si1 .Flags != 0x05 {
311+ t .Errorf ("first call: Flags = 0x%x, want 0x05" , si1 .Flags )
312+ }
313+
314+ // Second call returns cached data without hitting the connection
315+ si2 , err := f .readSecurityInfo ()
316+ if err != nil {
317+ t .Fatalf ("second call: unexpected error: %v" , err )
318+ }
319+ if si2 .Flags != 0x05 {
320+ t .Errorf ("second call: Flags = 0x%x, want 0x05" , si2 .Flags )
321+ }
322+ if callCount != 1 {
323+ t .Errorf ("expected only 1 connection call (second should use cache), got %d" , callCount )
324+ }
325+ }
0 commit comments