@@ -403,11 +403,11 @@ impl<'a, T> ExactSize<&'a mut T> for MutItems<'a, T> {}
403
403
fn grow < T > ( nelts : uint , loptr : & mut uint , elts : & mut Vec < Option < T > > ) {
404
404
assert_eq ! ( nelts, elts. len( ) ) ;
405
405
let lo = * loptr;
406
- let newlen = nelts * 2 ;
407
- elts. reserve ( newlen ) ;
406
+ elts . reserve ( nelts * 2 ) ;
407
+ let newlen = elts. capacity ( ) ;
408
408
409
409
/* fill with None */
410
- for _ in range ( elts. len ( ) , elts . capacity ( ) ) {
410
+ for _ in range ( elts. len ( ) , newlen ) {
411
411
elts. push ( None ) ;
412
412
}
413
413
@@ -750,6 +750,47 @@ mod tests {
750
750
assert_eq ! ( d. len( ) , 1 ) ;
751
751
}
752
752
753
+ #[ test]
754
+ fn test_with_capacity_non_power_two ( ) {
755
+ let mut d3 = RingBuf :: with_capacity ( 3 ) ;
756
+ d3. push ( 1 i) ;
757
+
758
+ // X = None, | = lo
759
+ // [|1, X, X]
760
+ assert_eq ! ( d3. pop_front( ) , Some ( 1 ) ) ;
761
+ // [X, |X, X]
762
+ assert_eq ! ( d3. front( ) , None ) ;
763
+
764
+ // [X, |3, X]
765
+ d3. push ( 3 ) ;
766
+ // [X, |3, 6]
767
+ d3. push ( 6 ) ;
768
+ // [X, X, |6]
769
+ assert_eq ! ( d3. pop_front( ) , Some ( 3 ) ) ;
770
+
771
+ // Pushing the lo past half way point to trigger
772
+ // the 'B' scenario for growth
773
+ // [9, X, |6]
774
+ d3. push ( 9 ) ;
775
+ // [9, 12, |6]
776
+ d3. push ( 12 ) ;
777
+
778
+ d3. push ( 15 ) ;
779
+ // There used to be a bug here about how the
780
+ // RingBuf made growth assumptions about the
781
+ // underlying Vec which didn't hold and lead
782
+ // to corruption.
783
+ // (Vec grows to next power of two)
784
+ //good- [9, 12, 15, X, X, X, X, |6]
785
+ //bug- [15, 12, X, X, X, |6, X, X]
786
+ assert_eq ! ( d3. pop_front( ) , Some ( 6 ) ) ;
787
+
788
+ // Which leads us to the following state which
789
+ // would be a failure case.
790
+ //bug- [15, 12, X, X, X, X, |X, X]
791
+ assert_eq ! ( d3. front( ) , Some ( & 9 ) ) ;
792
+ }
793
+
753
794
#[ test]
754
795
fn test_reserve_exact ( ) {
755
796
let mut d = RingBuf :: new ( ) ;
0 commit comments