@@ -310,29 +310,38 @@ public void DeskCase_83099_InmutableDictionary ()
310310 {
311311 var testUsername = "testusername" ;
312312
313- //TEST 1: Save a keychain value
314- var test1 = SaveUserPassword ( testUsername , "testValue1" , out var queryCode , out var addCode , out var updateCode ) ;
315- Assert . IsTrue ( test1 , $ "Password could not be saved to keychain. queryCode: { queryCode } addCode: { addCode } updateCode: { updateCode } " ) ;
313+ // Clean up any stale keychain entries from previous test runs to avoid
314+ // the keychain returning ItemNotFound on query but DuplicateItem on add.
315+ ForceRemoveUserPassword ( testUsername ) ;
316316
317- //TEST 2: Get the saved keychain value
318- var test2 = GetUserPassword ( testUsername ) ;
319- Assert . IsTrue ( StringUtil . StringsEqual ( test2 , "testValue1" , false ) ) ;
317+ try {
318+ //TEST 1: Save a keychain value
319+ var test1 = SaveUserPassword ( testUsername , "testValue1" , out var queryCode , out var addCode , out var updateCode ) ;
320+ Assert . IsTrue ( test1 , $ "Password could not be saved to keychain. queryCode: { queryCode } addCode: { addCode } updateCode: { updateCode } ") ;
321+
322+ //TEST 2: Get the saved keychain value
323+ var test2 = GetUserPassword ( testUsername ) ;
324+ Assert . IsTrue ( StringUtil . StringsEqual ( test2 , "testValue1" , false ) ) ;
320325
321- //TEST 3: Update the keychain value
322- var test3 = SaveUserPassword ( testUsername , "testValue2" , out queryCode , out addCode , out updateCode ) ;
323- Assert . IsTrue ( test3 , "Password could not be saved to keychain. queryCode: {queryCode} addCode: {addCode} updateCode: {updateCode}" ) ;
326+ //TEST 3: Update the keychain value
327+ var test3 = SaveUserPassword ( testUsername , "testValue2" , out queryCode , out addCode , out updateCode ) ;
328+ Assert . IsTrue ( test3 , $ "Password could not be saved to keychain. queryCode: { queryCode } addCode: { addCode } updateCode: { updateCode } ") ;
324329
325- //TEST 4: Get the updated keychain value
326- var test4 = GetUserPassword ( testUsername ) ;
327- Assert . IsTrue ( StringUtil . StringsEqual ( test4 , "testValue2" , false ) ) ;
330+ //TEST 4: Get the updated keychain value
331+ var test4 = GetUserPassword ( testUsername ) ;
332+ Assert . IsTrue ( StringUtil . StringsEqual ( test4 , "testValue2" , false ) ) ;
328333
329- //TEST 5: Clear the keychain values
330- var test5 = ClearUserPassword ( testUsername ) ;
331- Assert . IsTrue ( test5 , "Password could not be cleared from keychain" ) ;
334+ //TEST 5: Clear the keychain values
335+ var test5 = ClearUserPassword ( testUsername ) ;
336+ Assert . IsTrue ( test5 , "Password could not be cleared from keychain" ) ;
332337
333- //TEST 6: Verify no keychain value
334- var test6 = GetUserPassword ( testUsername ) ;
335- Assert . IsNull ( test6 , "No password should exist here" ) ;
338+ //TEST 6: Verify no keychain value
339+ var test6 = GetUserPassword ( testUsername ) ;
340+ Assert . IsNull ( test6 , "No password should exist here" ) ;
341+ } finally {
342+ // Always clean up to avoid leaving stale entries for subsequent runs
343+ ForceRemoveUserPassword ( testUsername ) ;
344+ }
336345 }
337346
338347 public static string GetUserPassword ( string username )
@@ -367,6 +376,13 @@ record = CreateSecRecord (SecKind.InternetPassword,
367376 ) ;
368377 addCode = SecKeyChain . Add ( record ) ;
369378 success = ( addCode == SecStatusCode . Success ) ;
379+ // Handle inconsistent keychain state: query returned ItemNotFound
380+ // but add returned DuplicateItem. Force-remove and retry.
381+ if ( addCode == SecStatusCode . DuplicateItem ) {
382+ SecKeyChain . Remove ( searchRecord ) ;
383+ addCode = SecKeyChain . Add ( record ) ;
384+ success = ( addCode == SecStatusCode . Success ) ;
385+ }
370386 }
371387 if ( queryCode == SecStatusCode . Success && record is not null ) {
372388 record . ValueData = NSData . FromString ( password ) ;
@@ -376,6 +392,15 @@ record = CreateSecRecord (SecKind.InternetPassword,
376392 return success ;
377393 }
378394
395+ public static void ForceRemoveUserPassword ( string username )
396+ {
397+ var searchRecord = CreateSecRecord ( SecKind . InternetPassword ,
398+ server : "Test1" ,
399+ account : username . ToLower ( )
400+ ) ;
401+ SecKeyChain . Remove ( searchRecord ) ;
402+ }
403+
379404 public static bool ClearUserPassword ( string username )
380405 {
381406 var success = false ;
0 commit comments