1 /* -*- Mode: C++; tab-width: 9; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4  * License, v. 2.0. If a copy of the MPL was not distributed with this file,
5  * You can obtain one at http://mozilla.org/MPL/2.0/. */
6 
7 // This is included first to ensure it doesn't implicitly depend on anything
8 // else.
9 #include "mozilla/BufferList.h"
10 
11 // It would be nice if we could use the InfallibleAllocPolicy from mozalloc,
12 // but MFBT cannot use mozalloc.
13 class InfallibleAllocPolicy {
14  public:
15   template <typename T>
pod_malloc(size_t aNumElems)16   T* pod_malloc(size_t aNumElems) {
17     if (aNumElems & mozilla::tl::MulOverflowMask<sizeof(T)>::value) {
18       MOZ_CRASH("TestBufferList.cpp: overflow");
19     }
20     T* rv = static_cast<T*>(malloc(aNumElems * sizeof(T)));
21     if (!rv) {
22       MOZ_CRASH("TestBufferList.cpp: out of memory");
23     }
24     return rv;
25   }
26 
27   template <typename T>
free_(T * aPtr,size_t aNumElems=0)28   void free_(T* aPtr, size_t aNumElems = 0) {
29     free(aPtr);
30   }
31 
reportAllocOverflow() const32   void reportAllocOverflow() const {}
33 
checkSimulatedOOM() const34   bool checkSimulatedOOM() const { return true; }
35 };
36 
37 typedef mozilla::BufferList<InfallibleAllocPolicy> BufferList;
38 
main(void)39 int main(void) {
40   const size_t kInitialSize = 16;
41   const size_t kInitialCapacity = 24;
42   const size_t kStandardCapacity = 32;
43 
44   BufferList bl(kInitialSize, kInitialCapacity, kStandardCapacity);
45 
46   memset(bl.Start(), 0x0c, kInitialSize);
47   MOZ_RELEASE_ASSERT(bl.Size() == kInitialSize);
48 
49   // Simple iteration and access.
50 
51   BufferList::IterImpl iter(bl.Iter());
52   MOZ_RELEASE_ASSERT(iter.RemainingInSegment() == kInitialSize);
53   MOZ_RELEASE_ASSERT(iter.HasRoomFor(kInitialSize));
54   MOZ_RELEASE_ASSERT(!iter.HasRoomFor(kInitialSize + 1));
55   MOZ_RELEASE_ASSERT(!iter.HasRoomFor(size_t(-1)));
56   MOZ_RELEASE_ASSERT(*iter.Data() == 0x0c);
57   MOZ_RELEASE_ASSERT(!iter.Done());
58 
59   iter.Advance(bl, 4);
60   MOZ_RELEASE_ASSERT(iter.RemainingInSegment() == kInitialSize - 4);
61   MOZ_RELEASE_ASSERT(iter.HasRoomFor(kInitialSize - 4));
62   MOZ_RELEASE_ASSERT(*iter.Data() == 0x0c);
63   MOZ_RELEASE_ASSERT(!iter.Done());
64 
65   iter.Advance(bl, 11);
66   MOZ_RELEASE_ASSERT(iter.RemainingInSegment() == kInitialSize - 4 - 11);
67   MOZ_RELEASE_ASSERT(iter.HasRoomFor(kInitialSize - 4 - 11));
68   MOZ_RELEASE_ASSERT(!iter.HasRoomFor(kInitialSize - 4 - 11 + 1));
69   MOZ_RELEASE_ASSERT(*iter.Data() == 0x0c);
70   MOZ_RELEASE_ASSERT(!iter.Done());
71 
72   iter.Advance(bl, kInitialSize - 4 - 11);
73   MOZ_RELEASE_ASSERT(iter.RemainingInSegment() == 0);
74   MOZ_RELEASE_ASSERT(!iter.HasRoomFor(1));
75   MOZ_RELEASE_ASSERT(iter.Done());
76 
77   // Writing to the buffer.
78 
79   const size_t kSmallWrite = 16;
80 
81   char toWrite[kSmallWrite];
82   memset(toWrite, 0x0a, kSmallWrite);
83   MOZ_ALWAYS_TRUE(bl.WriteBytes(toWrite, kSmallWrite));
84 
85   MOZ_RELEASE_ASSERT(bl.Size() == kInitialSize + kSmallWrite);
86 
87   iter = bl.Iter();
88   iter.Advance(bl, kInitialSize);
89   MOZ_RELEASE_ASSERT(!iter.Done());
90   MOZ_RELEASE_ASSERT(iter.RemainingInSegment() ==
91                      kInitialCapacity - kInitialSize);
92   MOZ_RELEASE_ASSERT(iter.HasRoomFor(kInitialCapacity - kInitialSize));
93   MOZ_RELEASE_ASSERT(*iter.Data() == 0x0a);
94 
95   // AdvanceAcrossSegments.
96 
97   iter = bl.Iter();
98   MOZ_RELEASE_ASSERT(iter.AdvanceAcrossSegments(bl, kInitialCapacity - 4));
99   MOZ_RELEASE_ASSERT(!iter.Done());
100   MOZ_RELEASE_ASSERT(iter.RemainingInSegment() == 4);
101   MOZ_RELEASE_ASSERT(iter.HasRoomFor(4));
102   MOZ_RELEASE_ASSERT(*iter.Data() == 0x0a);
103 
104   iter = bl.Iter();
105   MOZ_RELEASE_ASSERT(
106       iter.AdvanceAcrossSegments(bl, kInitialSize + kSmallWrite - 4));
107   MOZ_RELEASE_ASSERT(!iter.Done());
108   MOZ_RELEASE_ASSERT(iter.RemainingInSegment() == 4);
109   MOZ_RELEASE_ASSERT(iter.HasRoomFor(4));
110   MOZ_RELEASE_ASSERT(*iter.Data() == 0x0a);
111 
112   MOZ_RELEASE_ASSERT(
113       bl.Iter().AdvanceAcrossSegments(bl, kInitialSize + kSmallWrite - 1));
114   MOZ_RELEASE_ASSERT(
115       bl.Iter().AdvanceAcrossSegments(bl, kInitialSize + kSmallWrite));
116   MOZ_RELEASE_ASSERT(
117       !bl.Iter().AdvanceAcrossSegments(bl, kInitialSize + kSmallWrite + 1));
118   MOZ_RELEASE_ASSERT(!bl.Iter().AdvanceAcrossSegments(bl, size_t(-1)));
119 
120   // Reading non-contiguous bytes.
121 
122   char toRead[kSmallWrite];
123   iter = bl.Iter();
124   iter.Advance(bl, kInitialSize);
125   bl.ReadBytes(iter, toRead, kSmallWrite);
126   MOZ_RELEASE_ASSERT(memcmp(toRead, toWrite, kSmallWrite) == 0);
127   MOZ_RELEASE_ASSERT(iter.Done());
128 
129   // Make sure reading up to the end of a segment advances the iter to the next
130   // segment.
131   iter = bl.Iter();
132   bl.ReadBytes(iter, toRead, kInitialSize);
133   MOZ_RELEASE_ASSERT(!iter.Done());
134   MOZ_RELEASE_ASSERT(iter.RemainingInSegment() ==
135                      kInitialCapacity - kInitialSize);
136 
137   const size_t kBigWrite = 1024;
138 
139   char* toWriteBig = static_cast<char*>(malloc(kBigWrite));
140   for (unsigned i = 0; i < kBigWrite; i++) {
141     toWriteBig[i] = i % 37;
142   }
143   MOZ_ALWAYS_TRUE(bl.WriteBytes(toWriteBig, kBigWrite));
144 
145   char* toReadBig = static_cast<char*>(malloc(kBigWrite));
146   iter = bl.Iter();
147   MOZ_RELEASE_ASSERT(
148       iter.AdvanceAcrossSegments(bl, kInitialSize + kSmallWrite));
149   bl.ReadBytes(iter, toReadBig, kBigWrite);
150   MOZ_RELEASE_ASSERT(memcmp(toReadBig, toWriteBig, kBigWrite) == 0);
151   MOZ_RELEASE_ASSERT(iter.Done());
152 
153   free(toReadBig);
154   free(toWriteBig);
155 
156   // Currently bl contains these segments:
157   // #0: offset 0, [0x0c]*16 + [0x0a]*8, size 24
158   // #1: offset 24, [0x0a]*8 + [i%37 for i in 0..24], size 32
159   // #2: offset 56, [i%37 for i in 24..56, size 32
160   // ...
161   // #32: offset 1016, [i%37 for i in 984..1016], size 32
162   // #33: offset 1048, [i%37 for i in 1016..1024], size 8
163 
164   static size_t kTotalSize = kInitialSize + kSmallWrite + kBigWrite;
165 
166   MOZ_RELEASE_ASSERT(bl.Size() == kTotalSize);
167 
168   static size_t kLastSegmentSize =
169       (kTotalSize - kInitialCapacity) % kStandardCapacity;
170 
171   iter = bl.Iter();
172   MOZ_RELEASE_ASSERT(iter.AdvanceAcrossSegments(
173       bl, kTotalSize - kLastSegmentSize - kStandardCapacity));
174   MOZ_RELEASE_ASSERT(iter.RemainingInSegment() == kStandardCapacity);
175   iter.Advance(bl, kStandardCapacity);
176   MOZ_RELEASE_ASSERT(iter.RemainingInSegment() == kLastSegmentSize);
177   MOZ_RELEASE_ASSERT(
178       unsigned(*iter.Data()) ==
179       (kTotalSize - kLastSegmentSize - kInitialSize - kSmallWrite) % 37);
180 
181   // Clear.
182 
183   bl.Clear();
184   MOZ_RELEASE_ASSERT(bl.Size() == 0);
185   MOZ_RELEASE_ASSERT(bl.Iter().Done());
186 
187   // Move assignment.
188 
189   const size_t kSmallCapacity = 8;
190 
191   BufferList bl2(0, kSmallCapacity, kSmallCapacity);
192   MOZ_ALWAYS_TRUE(bl2.WriteBytes(toWrite, kSmallWrite));
193   MOZ_ALWAYS_TRUE(bl2.WriteBytes(toWrite, kSmallWrite));
194   MOZ_ALWAYS_TRUE(bl2.WriteBytes(toWrite, kSmallWrite));
195 
196   bl = std::move(bl2);
197   MOZ_RELEASE_ASSERT(bl2.Size() == 0);
198   MOZ_RELEASE_ASSERT(bl2.Iter().Done());
199 
200   iter = bl.Iter();
201   MOZ_RELEASE_ASSERT(iter.AdvanceAcrossSegments(bl, kSmallWrite * 3));
202   MOZ_RELEASE_ASSERT(iter.Done());
203 
204   // MoveFallible
205 
206   bool success;
207   bl2 = bl.MoveFallible<InfallibleAllocPolicy>(&success);
208   MOZ_RELEASE_ASSERT(success);
209   MOZ_RELEASE_ASSERT(bl.Size() == 0);
210   MOZ_RELEASE_ASSERT(bl.Iter().Done());
211   MOZ_RELEASE_ASSERT(bl2.Size() == kSmallWrite * 3);
212 
213   iter = bl2.Iter();
214   MOZ_RELEASE_ASSERT(iter.AdvanceAcrossSegments(bl2, kSmallWrite * 3));
215   MOZ_RELEASE_ASSERT(iter.Done());
216 
217   bl = bl2.MoveFallible<InfallibleAllocPolicy>(&success);
218 
219   // Borrowing.
220 
221   const size_t kBorrowStart = 4;
222   const size_t kBorrowSize = 24;
223 
224   iter = bl.Iter();
225   iter.Advance(bl, kBorrowStart);
226   bl2 = bl.Borrow<InfallibleAllocPolicy>(iter, kBorrowSize, &success);
227   MOZ_RELEASE_ASSERT(success);
228   MOZ_RELEASE_ASSERT(bl2.Size() == kBorrowSize);
229 
230   MOZ_RELEASE_ASSERT(iter.AdvanceAcrossSegments(
231       bl, kSmallWrite * 3 - kBorrowSize - kBorrowStart));
232   MOZ_RELEASE_ASSERT(iter.Done());
233 
234   iter = bl2.Iter();
235   MOZ_RELEASE_ASSERT(iter.AdvanceAcrossSegments(bl2, kBorrowSize));
236   MOZ_RELEASE_ASSERT(iter.Done());
237 
238   BufferList::IterImpl iter1(bl.Iter()), iter2(bl2.Iter());
239   iter1.Advance(bl, kBorrowStart);
240   MOZ_RELEASE_ASSERT(iter1.Data() == iter2.Data());
241   MOZ_RELEASE_ASSERT(iter1.AdvanceAcrossSegments(bl, kBorrowSize - 5));
242   MOZ_RELEASE_ASSERT(iter2.AdvanceAcrossSegments(bl2, kBorrowSize - 5));
243   MOZ_RELEASE_ASSERT(iter1.Data() == iter2.Data());
244 
245   // Extracting.
246 
247   const size_t kExtractStart = 8;
248   const size_t kExtractSize = 24;
249   const size_t kExtractOverSize = 1000;
250 
251   iter = bl.Iter();
252   iter.Advance(bl, kExtractStart);
253   bl2 = bl.Extract(iter, kExtractSize, &success);
254   MOZ_RELEASE_ASSERT(success);
255   MOZ_RELEASE_ASSERT(bl2.Size() == kExtractSize);
256 
257   BufferList bl3 = bl.Extract(iter, kExtractOverSize, &success);
258   MOZ_RELEASE_ASSERT(!success);
259 
260   iter = bl2.Iter();
261   MOZ_RELEASE_ASSERT(iter.AdvanceAcrossSegments(bl2, kExtractSize));
262   MOZ_RELEASE_ASSERT(iter.Done());
263 
264   BufferList bl4(8, 8, 8);
265   MOZ_ALWAYS_TRUE(bl4.WriteBytes("abcd1234", 8));
266   iter = bl4.Iter();
267   iter.Advance(bl4, 8);
268 
269   BufferList bl5 = bl4.Extract(iter, kExtractSize, &success);
270   MOZ_RELEASE_ASSERT(!success);
271 
272   BufferList bl6(0, 0, 16);
273   MOZ_ALWAYS_TRUE(bl6.WriteBytes("abcdefgh12345678", 16));
274   MOZ_ALWAYS_TRUE(bl6.WriteBytes("ijklmnop87654321", 16));
275   iter = bl6.Iter();
276   iter.Advance(bl6, 8);
277   BufferList bl7 = bl6.Extract(iter, 16, &success);
278   MOZ_RELEASE_ASSERT(success);
279   char data[16];
280   MOZ_RELEASE_ASSERT(bl6.ReadBytes(iter, data, 8));
281   MOZ_RELEASE_ASSERT(memcmp(data, "87654321", 8) == 0);
282   iter = bl7.Iter();
283   MOZ_RELEASE_ASSERT(bl7.ReadBytes(iter, data, 16));
284   MOZ_RELEASE_ASSERT(memcmp(data, "12345678ijklmnop", 16) == 0);
285 
286   BufferList bl8(0, 0, 16);
287   MOZ_ALWAYS_TRUE(bl8.WriteBytes("abcdefgh12345678", 16));
288   iter = bl8.Iter();
289   BufferList bl9 = bl8.Extract(iter, 8, &success);
290   MOZ_RELEASE_ASSERT(success);
291   MOZ_RELEASE_ASSERT(bl9.Size() == 8);
292   MOZ_RELEASE_ASSERT(!iter.Done());
293 
294   BufferList bl10(0, 0, 8);
295   MOZ_ALWAYS_TRUE(bl10.WriteBytes("abcdefgh", 8));
296   MOZ_ALWAYS_TRUE(bl10.WriteBytes("12345678", 8));
297   iter = bl10.Iter();
298   BufferList bl11 = bl10.Extract(iter, 16, &success);
299   MOZ_RELEASE_ASSERT(success);
300   MOZ_RELEASE_ASSERT(bl11.Size() == 16);
301   MOZ_RELEASE_ASSERT(iter.Done());
302   MOZ_RELEASE_ASSERT(iter.AdvanceAcrossSegments(bl10, 0));
303   MOZ_RELEASE_ASSERT(iter.Done());
304   iter = bl11.Iter();
305   MOZ_RELEASE_ASSERT(bl11.ReadBytes(iter, data, 16));
306   MOZ_RELEASE_ASSERT(memcmp(data, "abcdefgh12345678", 16) == 0);
307 
308   // RangeLength.
309 
310   BufferList bl12(0, 0, 8);
311   MOZ_ALWAYS_TRUE(bl12.WriteBytes("abcdefgh", 8));
312   MOZ_ALWAYS_TRUE(bl12.WriteBytes("12345678", 8));
313 
314   // |iter| is at position 0 (1st segment).
315   iter = bl12.Iter();
316   iter1 = bl12.Iter();
317   MOZ_RELEASE_ASSERT(bl12.RangeLength(iter, iter1) == 0);
318   MOZ_RELEASE_ASSERT(iter1.AdvanceAcrossSegments(bl12, 4));
319   MOZ_RELEASE_ASSERT(bl12.RangeLength(iter, iter1) == 4);
320   MOZ_RELEASE_ASSERT(iter1.AdvanceAcrossSegments(bl12, 4));
321   MOZ_RELEASE_ASSERT(bl12.RangeLength(iter, iter1) == 8);
322   MOZ_RELEASE_ASSERT(iter1.AdvanceAcrossSegments(bl12, 4));
323   MOZ_RELEASE_ASSERT(bl12.RangeLength(iter, iter1) == 12);
324   MOZ_RELEASE_ASSERT(iter1.AdvanceAcrossSegments(bl12, 3));
325   MOZ_RELEASE_ASSERT(bl12.RangeLength(iter, iter1) == 15);
326   MOZ_RELEASE_ASSERT(iter1.AdvanceAcrossSegments(bl12, 1));
327   MOZ_RELEASE_ASSERT(iter1.Done());
328 
329   // |iter| is at position 1 (1st segment).
330   iter = bl12.Iter();
331   iter1 = bl12.Iter();
332   MOZ_RELEASE_ASSERT(iter.AdvanceAcrossSegments(bl12, 1));
333   MOZ_RELEASE_ASSERT(iter1.AdvanceAcrossSegments(bl12, 1));
334   MOZ_RELEASE_ASSERT(bl12.RangeLength(iter, iter1) == 0);
335   MOZ_RELEASE_ASSERT(iter1.AdvanceAcrossSegments(bl12, 4));
336   MOZ_RELEASE_ASSERT(bl12.RangeLength(iter, iter1) == 4);
337   MOZ_RELEASE_ASSERT(iter1.AdvanceAcrossSegments(bl12, 4));
338   MOZ_RELEASE_ASSERT(bl12.RangeLength(iter, iter1) == 8);
339   MOZ_RELEASE_ASSERT(iter1.AdvanceAcrossSegments(bl12, 4));
340   MOZ_RELEASE_ASSERT(bl12.RangeLength(iter, iter1) == 12);
341   MOZ_RELEASE_ASSERT(iter1.AdvanceAcrossSegments(bl12, 2));
342   MOZ_RELEASE_ASSERT(bl12.RangeLength(iter, iter1) == 14);
343   MOZ_RELEASE_ASSERT(iter1.AdvanceAcrossSegments(bl12, 1));
344   MOZ_RELEASE_ASSERT(iter1.Done());
345 
346   // |iter| is at position 8 (2nd segment).
347   iter = bl12.Iter();
348   iter1 = bl12.Iter();
349   MOZ_RELEASE_ASSERT(iter.AdvanceAcrossSegments(bl12, 8));
350   MOZ_RELEASE_ASSERT(iter1.AdvanceAcrossSegments(bl12, 8));
351   MOZ_RELEASE_ASSERT(bl12.RangeLength(iter, iter1) == 0);
352   MOZ_RELEASE_ASSERT(iter1.AdvanceAcrossSegments(bl12, 4));
353   MOZ_RELEASE_ASSERT(bl12.RangeLength(iter, iter1) == 4);
354   MOZ_RELEASE_ASSERT(iter1.AdvanceAcrossSegments(bl12, 3));
355   MOZ_RELEASE_ASSERT(bl12.RangeLength(iter, iter1) == 7);
356   MOZ_RELEASE_ASSERT(iter1.AdvanceAcrossSegments(bl12, 1));
357   MOZ_RELEASE_ASSERT(iter1.Done());
358 
359   // |iter| is at position 9 (2nd segment).
360   iter = bl12.Iter();
361   iter1 = bl12.Iter();
362   MOZ_RELEASE_ASSERT(iter.AdvanceAcrossSegments(bl12, 9));
363   MOZ_RELEASE_ASSERT(iter1.AdvanceAcrossSegments(bl12, 9));
364   MOZ_RELEASE_ASSERT(bl12.RangeLength(iter, iter1) == 0);
365   MOZ_RELEASE_ASSERT(iter1.AdvanceAcrossSegments(bl12, 4));
366   MOZ_RELEASE_ASSERT(bl12.RangeLength(iter, iter1) == 4);
367   MOZ_RELEASE_ASSERT(iter1.AdvanceAcrossSegments(bl12, 2));
368   MOZ_RELEASE_ASSERT(bl12.RangeLength(iter, iter1) == 6);
369   MOZ_RELEASE_ASSERT(iter1.AdvanceAcrossSegments(bl12, 1));
370   MOZ_RELEASE_ASSERT(iter1.Done());
371 
372   BufferList bl13(0, 0, 8);
373   MOZ_ALWAYS_TRUE(bl13.WriteBytes("abcdefgh", 8));
374   MOZ_ALWAYS_TRUE(bl13.WriteBytes("12345678", 8));
375   MOZ_ALWAYS_TRUE(bl13.WriteBytes("ABCDEFGH", 8));
376   MOZ_RELEASE_ASSERT(bl13.Size() == 24);
377 
378   // At segment border
379   iter = bl13.Iter();
380   MOZ_RELEASE_ASSERT(iter.AdvanceAcrossSegments(bl13, 8));
381   MOZ_RELEASE_ASSERT(bl13.Truncate(iter) == 16);
382   MOZ_RELEASE_ASSERT(iter.Done());
383   MOZ_RELEASE_ASSERT(bl13.Size() == 8);
384 
385   // Restore state
386   MOZ_ALWAYS_TRUE(bl13.WriteBytes("12345678", 8));
387   MOZ_ALWAYS_TRUE(bl13.WriteBytes("ABCDEFGH", 8));
388   MOZ_RELEASE_ASSERT(bl13.Size() == 24);
389 
390   // Before segment border
391   iter = bl13.Iter();
392   MOZ_RELEASE_ASSERT(iter.AdvanceAcrossSegments(bl13, 7));
393   MOZ_RELEASE_ASSERT(bl13.Truncate(iter) == 17);
394   MOZ_RELEASE_ASSERT(iter.Done());
395   MOZ_RELEASE_ASSERT(bl13.Size() == 7);
396 
397   // Restore state
398   MOZ_ALWAYS_TRUE(bl13.WriteBytes("h", 1));
399   MOZ_ALWAYS_TRUE(bl13.WriteBytes("12345678", 8));
400   MOZ_ALWAYS_TRUE(bl13.WriteBytes("ABCDEFGH", 8));
401   MOZ_RELEASE_ASSERT(bl13.Size() == 24);
402 
403   // In last segment
404   iter = bl13.Iter();
405   MOZ_RELEASE_ASSERT(iter.AdvanceAcrossSegments(bl13, 20));
406   MOZ_RELEASE_ASSERT(bl13.Truncate(iter) == 4);
407   MOZ_RELEASE_ASSERT(iter.Done());
408   MOZ_RELEASE_ASSERT(bl13.Size() == 20);
409 
410   // No-op truncate
411   MOZ_RELEASE_ASSERT(bl13.Truncate(iter) == 0);
412   MOZ_RELEASE_ASSERT(iter.Done());
413   MOZ_RELEASE_ASSERT(bl13.Size() == 20);
414 
415   // No-op truncate with fresh iterator
416   iter = bl13.Iter();
417   MOZ_RELEASE_ASSERT(iter.AdvanceAcrossSegments(bl13, 20));
418   MOZ_RELEASE_ASSERT(bl13.Truncate(iter) == 0);
419   MOZ_RELEASE_ASSERT(iter.Done());
420   MOZ_RELEASE_ASSERT(bl13.Size() == 20);
421 
422   // Truncate at start of buffer
423   iter = bl13.Iter();
424   MOZ_RELEASE_ASSERT(bl13.Truncate(iter) == 20);
425   MOZ_RELEASE_ASSERT(iter.Done());
426   MOZ_RELEASE_ASSERT(bl13.Size() == 0);
427 
428   // No-op truncate at start of buffer
429   iter = bl13.Iter();
430   MOZ_RELEASE_ASSERT(bl13.Truncate(iter) == 0);
431   MOZ_RELEASE_ASSERT(iter.Done());
432   MOZ_RELEASE_ASSERT(bl13.Size() == 0);
433 
434   return 0;
435 }
436