@@ -461,4 +461,171 @@ public void reverse_bitwise_comparer_works_with_duplicate_values()
461461
462462 cursor . NextDuplicate ( ) . Item1 . ShouldBe ( MDBResultCode . NotFound ) ;
463463 }
464+
465+ public void guid_comparer_sorts_guids_by_byte_order ( )
466+ {
467+ using var env = CreateEnvironment ( ) ;
468+ env . Open ( ) ;
469+
470+ var config = new DatabaseConfiguration { Flags = DatabaseOpenFlags . Create } ;
471+ config . CompareWith ( GuidComparer . Instance ) ;
472+
473+ using var txn = env . BeginTransaction ( ) ;
474+ using var db = txn . OpenDatabase ( configuration : config ) ;
475+
476+ // Create GUIDs with known byte patterns for predictable ordering
477+ // First byte differs: 0x01 < 0x02 < 0xFF
478+ var guid1 = new Guid ( new byte [ ] { 0x01 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 } ) ;
479+ var guid2 = new Guid ( new byte [ ] { 0x02 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 } ) ;
480+ var guid3 = new Guid ( new byte [ ] { 0xFF , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 } ) ;
481+
482+ txn . Put ( db , guid2 . ToByteArray ( ) , new byte [ ] { 2 } ) ;
483+ txn . Put ( db , guid3 . ToByteArray ( ) , new byte [ ] { 3 } ) ;
484+ txn . Put ( db , guid1 . ToByteArray ( ) , new byte [ ] { 1 } ) ;
485+
486+ using var cursor = txn . CreateCursor ( db ) ;
487+
488+ cursor . Next ( ) . Item1 . ShouldBe ( MDBResultCode . Success ) ;
489+ new Guid ( cursor . GetCurrent ( ) . key . CopyToNewArray ( ) ) . ShouldBe ( guid1 ) ;
490+
491+ cursor . Next ( ) . Item1 . ShouldBe ( MDBResultCode . Success ) ;
492+ new Guid ( cursor . GetCurrent ( ) . key . CopyToNewArray ( ) ) . ShouldBe ( guid2 ) ;
493+
494+ cursor . Next ( ) . Item1 . ShouldBe ( MDBResultCode . Success ) ;
495+ new Guid ( cursor . GetCurrent ( ) . key . CopyToNewArray ( ) ) . ShouldBe ( guid3 ) ;
496+
497+ cursor . Next ( ) . Item1 . ShouldBe ( MDBResultCode . NotFound ) ;
498+ }
499+
500+ public void guid_comparer_sorts_by_second_half_when_first_half_equal ( )
501+ {
502+ using var env = CreateEnvironment ( ) ;
503+ env . Open ( ) ;
504+
505+ var config = new DatabaseConfiguration { Flags = DatabaseOpenFlags . Create } ;
506+ config . CompareWith ( GuidComparer . Instance ) ;
507+
508+ using var txn = env . BeginTransaction ( ) ;
509+ using var db = txn . OpenDatabase ( configuration : config ) ;
510+
511+ // Same first 8 bytes, differ in second half (byte 8)
512+ var guid1 = new Guid ( new byte [ ] { 0xAA , 0xBB , 0xCC , 0xDD , 0xEE , 0xFF , 0x00 , 0x11 , 0x01 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 } ) ;
513+ var guid2 = new Guid ( new byte [ ] { 0xAA , 0xBB , 0xCC , 0xDD , 0xEE , 0xFF , 0x00 , 0x11 , 0x02 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 } ) ;
514+ var guid3 = new Guid ( new byte [ ] { 0xAA , 0xBB , 0xCC , 0xDD , 0xEE , 0xFF , 0x00 , 0x11 , 0xFF , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 } ) ;
515+
516+ txn . Put ( db , guid3 . ToByteArray ( ) , new byte [ ] { 3 } ) ;
517+ txn . Put ( db , guid1 . ToByteArray ( ) , new byte [ ] { 1 } ) ;
518+ txn . Put ( db , guid2 . ToByteArray ( ) , new byte [ ] { 2 } ) ;
519+
520+ using var cursor = txn . CreateCursor ( db ) ;
521+
522+ cursor . Next ( ) . Item1 . ShouldBe ( MDBResultCode . Success ) ;
523+ new Guid ( cursor . GetCurrent ( ) . key . CopyToNewArray ( ) ) . ShouldBe ( guid1 ) ;
524+
525+ cursor . Next ( ) . Item1 . ShouldBe ( MDBResultCode . Success ) ;
526+ new Guid ( cursor . GetCurrent ( ) . key . CopyToNewArray ( ) ) . ShouldBe ( guid2 ) ;
527+
528+ cursor . Next ( ) . Item1 . ShouldBe ( MDBResultCode . Success ) ;
529+ new Guid ( cursor . GetCurrent ( ) . key . CopyToNewArray ( ) ) . ShouldBe ( guid3 ) ;
530+
531+ cursor . Next ( ) . Item1 . ShouldBe ( MDBResultCode . NotFound ) ;
532+ }
533+
534+ public void reverse_guid_comparer_sorts_guids_descending ( )
535+ {
536+ using var env = CreateEnvironment ( ) ;
537+ env . Open ( ) ;
538+
539+ var config = new DatabaseConfiguration { Flags = DatabaseOpenFlags . Create } ;
540+ config . CompareWith ( ReverseGuidComparer . Instance ) ;
541+
542+ using var txn = env . BeginTransaction ( ) ;
543+ using var db = txn . OpenDatabase ( configuration : config ) ;
544+
545+ var guid1 = new Guid ( new byte [ ] { 0x01 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 } ) ;
546+ var guid2 = new Guid ( new byte [ ] { 0x02 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 } ) ;
547+ var guid3 = new Guid ( new byte [ ] { 0xFF , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 } ) ;
548+
549+ txn . Put ( db , guid1 . ToByteArray ( ) , new byte [ ] { 1 } ) ;
550+ txn . Put ( db , guid2 . ToByteArray ( ) , new byte [ ] { 2 } ) ;
551+ txn . Put ( db , guid3 . ToByteArray ( ) , new byte [ ] { 3 } ) ;
552+
553+ using var cursor = txn . CreateCursor ( db ) ;
554+
555+ // Reverse order: FF, 02, 01
556+ cursor . Next ( ) . Item1 . ShouldBe ( MDBResultCode . Success ) ;
557+ new Guid ( cursor . GetCurrent ( ) . key . CopyToNewArray ( ) ) . ShouldBe ( guid3 ) ;
558+
559+ cursor . Next ( ) . Item1 . ShouldBe ( MDBResultCode . Success ) ;
560+ new Guid ( cursor . GetCurrent ( ) . key . CopyToNewArray ( ) ) . ShouldBe ( guid2 ) ;
561+
562+ cursor . Next ( ) . Item1 . ShouldBe ( MDBResultCode . Success ) ;
563+ new Guid ( cursor . GetCurrent ( ) . key . CopyToNewArray ( ) ) . ShouldBe ( guid1 ) ;
564+
565+ cursor . Next ( ) . Item1 . ShouldBe ( MDBResultCode . NotFound ) ;
566+ }
567+
568+ public void guid_comparer_falls_back_for_non_16_byte_values ( )
569+ {
570+ using var env = CreateEnvironment ( ) ;
571+ env . Open ( ) ;
572+
573+ var config = new DatabaseConfiguration { Flags = DatabaseOpenFlags . Create } ;
574+ config . CompareWith ( GuidComparer . Instance ) ;
575+
576+ using var txn = env . BeginTransaction ( ) ;
577+ using var db = txn . OpenDatabase ( configuration : config ) ;
578+
579+ // Non-16-byte keys should still work via fallback to SequenceCompareTo
580+ txn . Put ( db , new byte [ ] { 0xFF , 0xFF } , new byte [ ] { 1 } ) ;
581+ txn . Put ( db , new byte [ ] { 0x00 , 0x00 } , new byte [ ] { 2 } ) ;
582+ txn . Put ( db , new byte [ ] { 0x80 , 0x80 } , new byte [ ] { 3 } ) ;
583+
584+ using var cursor = txn . CreateCursor ( db ) ;
585+
586+ cursor . Next ( ) . Item1 . ShouldBe ( MDBResultCode . Success ) ;
587+ cursor . GetCurrent ( ) . key . CopyToNewArray ( ) . ShouldBe ( new byte [ ] { 0x00 , 0x00 } ) ;
588+
589+ cursor . Next ( ) . Item1 . ShouldBe ( MDBResultCode . Success ) ;
590+ cursor . GetCurrent ( ) . key . CopyToNewArray ( ) . ShouldBe ( new byte [ ] { 0x80 , 0x80 } ) ;
591+
592+ cursor . Next ( ) . Item1 . ShouldBe ( MDBResultCode . Success ) ;
593+ cursor . GetCurrent ( ) . key . CopyToNewArray ( ) . ShouldBe ( new byte [ ] { 0xFF , 0xFF } ) ;
594+
595+ cursor . Next ( ) . Item1 . ShouldBe ( MDBResultCode . NotFound ) ;
596+ }
597+
598+ public void guid_comparer_works_with_duplicate_values ( )
599+ {
600+ using var env = CreateEnvironment ( ) ;
601+ env . Open ( ) ;
602+
603+ var config = new DatabaseConfiguration { Flags = DatabaseOpenFlags . Create | DatabaseOpenFlags . DuplicatesSort } ;
604+ config . FindDuplicatesWith ( GuidComparer . Instance ) ;
605+
606+ using var txn = env . BeginTransaction ( ) ;
607+ using var db = txn . OpenDatabase ( configuration : config ) ;
608+
609+ var key = new byte [ ] { 1 } ;
610+ var val1 = new Guid ( new byte [ ] { 0x01 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 } ) ;
611+ var val2 = new Guid ( new byte [ ] { 0x02 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 } ) ;
612+ var val3 = new Guid ( new byte [ ] { 0xFF , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 } ) ;
613+
614+ txn . Put ( db , key , val3 . ToByteArray ( ) ) ;
615+ txn . Put ( db , key , val1 . ToByteArray ( ) ) ;
616+ txn . Put ( db , key , val2 . ToByteArray ( ) ) ;
617+
618+ using var cursor = txn . CreateCursor ( db ) ;
619+ cursor . SetKey ( key ) ;
620+
621+ new Guid ( cursor . GetCurrent ( ) . value . CopyToNewArray ( ) ) . ShouldBe ( val1 ) ;
622+
623+ cursor . NextDuplicate ( ) . Item1 . ShouldBe ( MDBResultCode . Success ) ;
624+ new Guid ( cursor . GetCurrent ( ) . value . CopyToNewArray ( ) ) . ShouldBe ( val2 ) ;
625+
626+ cursor . NextDuplicate ( ) . Item1 . ShouldBe ( MDBResultCode . Success ) ;
627+ new Guid ( cursor . GetCurrent ( ) . value . CopyToNewArray ( ) ) . ShouldBe ( val3 ) ;
628+
629+ cursor . NextDuplicate ( ) . Item1 . ShouldBe ( MDBResultCode . NotFound ) ;
630+ }
464631}
0 commit comments