@@ -654,6 +654,39 @@ func TestDeletePanics(t *testing.T) {
654654 }
655655}
656656
657+ func TestDeleteClearTail (t * testing.T ) {
658+ mem := []* int {new (int ), new (int ), new (int ), new (int ), new (int ), new (int )}
659+ s := mem [0 :5 ] // there is 1 element beyond len(s), within cap(s)
660+
661+ s = Delete (s , 2 , 4 )
662+
663+ if mem [3 ] != nil || mem [4 ] != nil {
664+ // Check that potential memory leak is avoided
665+ t .Errorf ("Delete: want nil discarded elements, got %v, %v" , mem [3 ], mem [4 ])
666+ }
667+ if mem [5 ] == nil {
668+ t .Errorf ("Delete: want unchanged elements beyond original len, got nil" )
669+ }
670+ }
671+
672+ func TestDeleteFuncClearTail (t * testing.T ) {
673+ mem := []* int {new (int ), new (int ), new (int ), new (int ), new (int ), new (int )}
674+ * mem [2 ], * mem [3 ] = 42 , 42
675+ s := mem [0 :5 ] // there is 1 element beyond len(s), within cap(s)
676+
677+ s = DeleteFunc (s , func (i * int ) bool {
678+ return i != nil && * i == 42
679+ })
680+
681+ if mem [3 ] != nil || mem [4 ] != nil {
682+ // Check that potential memory leak is avoided
683+ t .Errorf ("DeleteFunc: want nil discarded elements, got %v, %v" , mem [3 ], mem [4 ])
684+ }
685+ if mem [5 ] == nil {
686+ t .Errorf ("DeleteFunc: want unchanged elements beyond original len, got nil" )
687+ }
688+ }
689+
657690func TestClone (t * testing.T ) {
658691 s1 := []int {1 , 2 , 3 }
659692 s2 := Clone (s1 )
@@ -757,6 +790,53 @@ func TestCompactFunc(t *testing.T) {
757790 }
758791}
759792
793+ func TestCompactClearTail (t * testing.T ) {
794+ one , two , three , four := 1 , 2 , 3 , 4
795+ mem := []* int {& one , & one , & two , & two , & three , & four }
796+ s := mem [0 :5 ] // there is 1 element beyond len(s), within cap(s)
797+ copy := Clone (s )
798+
799+ s = Compact (s )
800+
801+ if want := []* int {& one , & two , & three }; ! Equal (s , want ) {
802+ t .Errorf ("Compact(%v) = %v, want %v" , copy , s , want )
803+ }
804+
805+ if mem [3 ] != nil || mem [4 ] != nil {
806+ // Check that potential memory leak is avoided
807+ t .Errorf ("Compact: want nil discarded elements, got %v, %v" , mem [3 ], mem [4 ])
808+ }
809+ if mem [5 ] != & four {
810+ t .Errorf ("Compact: want unchanged element beyond original len, got %v" , mem [5 ])
811+ }
812+ }
813+
814+ func TestCompactFuncClearTail (t * testing.T ) {
815+ a , b , c , d , e , f := 1 , 1 , 2 , 2 , 3 , 4
816+ mem := []* int {& a , & b , & c , & d , & e , & f }
817+ s := mem [0 :5 ] // there is 1 element beyond len(s), within cap(s)
818+ copy := Clone (s )
819+
820+ s = CompactFunc (s , func (x , y * int ) bool {
821+ if x == nil || y == nil {
822+ return x == y
823+ }
824+ return * x == * y
825+ })
826+
827+ if want := []* int {& a , & c , & e }; ! Equal (s , want ) {
828+ t .Errorf ("CompactFunc(%v) = %v, want %v" , copy , s , want )
829+ }
830+
831+ if mem [3 ] != nil || mem [4 ] != nil {
832+ // Check that potential memory leak is avoided
833+ t .Errorf ("CompactFunc: want nil discarded elements, got %v, %v" , mem [3 ], mem [4 ])
834+ }
835+ if mem [5 ] != & f {
836+ t .Errorf ("CompactFunc: want unchanged elements beyond original len, got %v" , mem [5 ])
837+ }
838+ }
839+
760840func BenchmarkCompactFunc_Large (b * testing.B ) {
761841 type Large [4 * 1024 ]byte
762842
@@ -922,6 +1002,56 @@ func TestReplacePanics(t *testing.T) {
9221002 }
9231003}
9241004
1005+ func TestReplaceGrow (t * testing.T ) {
1006+ // When Replace needs to allocate a new slice, we want the original slice
1007+ // to not be changed.
1008+ a , b , c , d , e , f := 1 , 2 , 3 , 4 , 5 , 6
1009+ mem := []* int {& a , & b , & c , & d , & e , & f }
1010+ memcopy := Clone (mem )
1011+ s := mem [0 :5 ] // there is 1 element beyond len(s), within cap(s)
1012+ copy := Clone (s )
1013+ original := s
1014+
1015+ // The new elements don't fit within cap(s), so Replace will allocate.
1016+ z := 99
1017+ s = Replace (s , 1 , 3 , & z , & z , & z , & z )
1018+
1019+ if want := []* int {& a , & z , & z , & z , & z , & d , & e }; ! Equal (s , want ) {
1020+ t .Errorf ("Replace(%v, 1, 3, %v, %v, %v, %v) = %v, want %v" , copy , & z , & z , & z , & z , s , want )
1021+ }
1022+
1023+ if ! Equal (original , copy ) {
1024+ t .Errorf ("original slice has changed, got %v, want %v" , original , copy )
1025+ }
1026+
1027+ if ! Equal (mem , memcopy ) {
1028+ // Changing the original tail s[len(s):cap(s)] is unwanted
1029+ t .Errorf ("original backing memory has changed, got %v, want %v" , mem , memcopy )
1030+ }
1031+ }
1032+
1033+ func TestReplaceClearTail (t * testing.T ) {
1034+ a , b , c , d , e , f := 1 , 2 , 3 , 4 , 5 , 6
1035+ mem := []* int {& a , & b , & c , & d , & e , & f }
1036+ s := mem [0 :5 ] // there is 1 element beyond len(s), within cap(s)
1037+ copy := Clone (s )
1038+
1039+ y , z := 8 , 9
1040+ s = Replace (s , 1 , 4 , & y , & z )
1041+
1042+ if want := []* int {& a , & y , & z , & e }; ! Equal (s , want ) {
1043+ t .Errorf ("Replace(%v) = %v, want %v" , copy , s , want )
1044+ }
1045+
1046+ if mem [4 ] != nil {
1047+ // Check that potential memory leak is avoided
1048+ t .Errorf ("Replace: want nil discarded element, got %v" , mem [4 ])
1049+ }
1050+ if mem [5 ] != & f {
1051+ t .Errorf ("Replace: want unchanged elements beyond original len, got %v" , mem [5 ])
1052+ }
1053+ }
1054+
9251055func TestReplaceOverlap (t * testing.T ) {
9261056 const N = 10
9271057 a := make ([]int , N )
0 commit comments