@@ -461,3 +461,159 @@ func TestMany2ManyDuplicateBelongsToAssociation(t *testing.T) {
461461 tests .AssertEqual (t , nil , err )
462462 tests .AssertEqual (t , user2 , findUser2 )
463463}
464+
465+ func TestMany2ManyEmptyAssociations (t * testing.T ) {
466+ user := User {Name : "TestEmptyAssociations" }
467+
468+ // Create user with no associations
469+ if err := DB .Create (& user ).Error ; err != nil {
470+ t .Fatalf ("errors happened when create user: %v" , err )
471+ }
472+
473+ var languages []Language
474+ if err := DB .Model (& user ).Association ("Languages" ).Find (& languages ); err != nil {
475+ t .Errorf ("Error finding empty associations: %v" , err )
476+ }
477+
478+ if len (languages ) != 0 {
479+ t .Errorf ("Expected 0 languages, got %d" , len (languages ))
480+ }
481+
482+ count := DB .Model (& user ).Association ("Languages" ).Count ()
483+ if count != 0 {
484+ t .Errorf ("Expected count 0 for empty association, got %d" , count )
485+ }
486+
487+ if err := DB .Model (& user ).Association ("Languages" ).Clear (); err != nil {
488+ t .Errorf ("Error clearing empty association: %v" , err )
489+ }
490+
491+ if err := DB .Model (& user ).Association ("Languages" ).Delete (& Language {}); err != nil {
492+ t .Errorf ("Error deleting from empty association: %v" , err )
493+ }
494+ }
495+
496+ func TestMany2ManyAssociationCountValidation (t * testing.T ) {
497+ user := * GetUser ("count-validation" , Config {Languages : 3 })
498+
499+ if err := DB .Create (& user ).Error ; err != nil {
500+ t .Fatalf ("errors happened when create: %v" , err )
501+ }
502+
503+ // Initial count check
504+ initialCount := DB .Model (& user ).Association ("Languages" ).Count ()
505+ if initialCount != 3 {
506+ t .Fatalf ("Expected initial count 3, got %d" , initialCount )
507+ }
508+
509+ newLanguages := []Language {
510+ {Code : "count-test-1" , Name : "Count Test 1" },
511+ {Code : "count-test-2" , Name : "Count Test 2" },
512+ }
513+ DB .Create (& newLanguages )
514+
515+ if err := DB .Model (& user ).Association ("Languages" ).Append (& newLanguages ); err != nil {
516+ t .Fatalf ("Error appending languages: %v" , err )
517+ }
518+
519+ // Check count after append
520+ countAfterAppend := DB .Model (& user ).Association ("Languages" ).Count ()
521+ if countAfterAppend != 5 {
522+ t .Errorf ("Expected count 5 after append, got %d" , countAfterAppend )
523+ }
524+
525+ replaceLanguage := Language {Code : "count-replace" , Name : "Count Replace" }
526+ DB .Create (& replaceLanguage )
527+
528+ if err := DB .Model (& user ).Association ("Languages" ).Replace (& replaceLanguage ); err != nil {
529+ t .Fatalf ("Error replacing languages: %v" , err )
530+ }
531+
532+ // Check count after replace
533+ countAfterReplace := DB .Model (& user ).Association ("Languages" ).Count ()
534+ if countAfterReplace != 1 {
535+ t .Errorf ("Expected count 1 after replace, got %d" , countAfterReplace )
536+ }
537+
538+ // Verify actual data matches count
539+ var actualLanguages []Language
540+ DB .Model (& user ).Association ("Languages" ).Find (& actualLanguages )
541+ if len (actualLanguages ) != int (countAfterReplace ) {
542+ t .Errorf ("Count mismatch: Count() returned %d but Find() returned %d languages" ,
543+ countAfterReplace , len (actualLanguages ))
544+ }
545+ }
546+
547+ func TestMany2ManyConstraintViolations (t * testing.T ) {
548+ user := * GetUser ("constraint-test" , Config {Languages : 1 })
549+
550+ if err := DB .Create (& user ).Error ; err != nil {
551+ t .Fatalf ("errors happened when create: %v" , err )
552+ }
553+
554+ existingLanguage := user .Languages [0 ]
555+
556+ // append the same language again
557+ if err := DB .Model (& user ).Association ("Languages" ).Append (& existingLanguage ); err != nil {
558+ t .Logf ("Appending duplicate language resulted in: %v" , err )
559+ }
560+
561+ // Verify count is still correct
562+ count := DB .Model (& user ).Association ("Languages" ).Count ()
563+ if count > 1 {
564+ t .Errorf ("Expected count 1 after duplicate append, got %d" , count )
565+ }
566+
567+ tempLanguage := Language {Code : "temp-invalid" , Name : "Temp Invalid" }
568+ if err := DB .Create (& tempLanguage ).Error ; err != nil {
569+ t .Logf ("Could not create temp language for FK test: %v" , err )
570+ return
571+ }
572+
573+ // append, then delete the language record to create inconsistency
574+ if err := DB .Model (& user ).Association ("Languages" ).Append (& tempLanguage ); err != nil {
575+ t .Logf ("Could not append temp language: %v" , err )
576+ }
577+
578+ // Delete the language record directly
579+ DB .Unscoped ().Delete (& tempLanguage )
580+
581+ // access associations after deleting referenced record
582+ var languages []Language
583+ if err := DB .Model (& user ).Association ("Languages" ).Find (& languages ); err != nil {
584+ t .Logf ("Finding associations after FK deletion resulted in: %v" , err )
585+ }
586+
587+ var manyLanguages []Language
588+ for i := 0 ; i < 10 ; i ++ {
589+ manyLanguages = append (manyLanguages , Language {
590+ Code : fmt .Sprintf ("mass-test-%d" , i ),
591+ Name : fmt .Sprintf ("Mass Test %d" , i ),
592+ })
593+ }
594+
595+ // Create the languages first
596+ if err := DB .Create (& manyLanguages ).Error ; err != nil {
597+ t .Logf ("Creating many languages failed: %v" , err )
598+ return
599+ }
600+
601+ // append all at once
602+ if err := DB .Model (& user ).Association ("Languages" ).Append (& manyLanguages ); err != nil {
603+ t .Logf ("Mass append operation resulted in: %v" , err )
604+ }
605+
606+ // Verify the operation completed
607+ finalCount := DB .Model (& user ).Association ("Languages" ).Count ()
608+ t .Logf ("Final language count after mass operation: %d" , finalCount )
609+
610+ if err := DB .Model (& user ).Association ("Languages" ).Clear (); err != nil {
611+ t .Errorf ("Error clearing associations after mass operation: %v" , err )
612+ }
613+
614+ // Verify clear worked
615+ countAfterClear := DB .Model (& user ).Association ("Languages" ).Count ()
616+ if countAfterClear != 0 {
617+ t .Errorf ("Expected count 0 after clear, got %d" , countAfterClear )
618+ }
619+ }
0 commit comments