OSDN Git Service

Hulk did something
[bytom/vapor.git] / vendor / github.com / syndtr / goleveldb / leveldb / journal / journal_test.go
1 // Copyright 2011 The LevelDB-Go Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file.
4
5 // Taken from: https://code.google.com/p/leveldb-go/source/browse/leveldb/record/record_test.go?r=df1fa28f7f3be6c3935548169002309c12967135
6 // License, authors and contributors informations can be found at bellow URLs respectively:
7 //      https://code.google.com/p/leveldb-go/source/browse/LICENSE
8 //      https://code.google.com/p/leveldb-go/source/browse/AUTHORS
9 //  https://code.google.com/p/leveldb-go/source/browse/CONTRIBUTORS
10
11 package journal
12
13 import (
14         "bytes"
15         "encoding/binary"
16         "fmt"
17         "io"
18         "io/ioutil"
19         "math/rand"
20         "strings"
21         "testing"
22 )
23
24 type dropper struct {
25         t *testing.T
26 }
27
28 func (d dropper) Drop(err error) {
29         d.t.Log(err)
30 }
31
32 func short(s string) string {
33         if len(s) < 64 {
34                 return s
35         }
36         return fmt.Sprintf("%s...(skipping %d bytes)...%s", s[:20], len(s)-40, s[len(s)-20:])
37 }
38
39 // big returns a string of length n, composed of repetitions of partial.
40 func big(partial string, n int) string {
41         return strings.Repeat(partial, n/len(partial)+1)[:n]
42 }
43
44 func TestEmpty(t *testing.T) {
45         buf := new(bytes.Buffer)
46         r := NewReader(buf, dropper{t}, true, true)
47         if _, err := r.Next(); err != io.EOF {
48                 t.Fatalf("got %v, want %v", err, io.EOF)
49         }
50 }
51
52 func testGenerator(t *testing.T, reset func(), gen func() (string, bool)) {
53         buf := new(bytes.Buffer)
54
55         reset()
56         w := NewWriter(buf)
57         for {
58                 s, ok := gen()
59                 if !ok {
60                         break
61                 }
62                 ww, err := w.Next()
63                 if err != nil {
64                         t.Fatal(err)
65                 }
66                 if _, err := ww.Write([]byte(s)); err != nil {
67                         t.Fatal(err)
68                 }
69         }
70         if err := w.Close(); err != nil {
71                 t.Fatal(err)
72         }
73
74         reset()
75         r := NewReader(buf, dropper{t}, true, true)
76         for {
77                 s, ok := gen()
78                 if !ok {
79                         break
80                 }
81                 rr, err := r.Next()
82                 if err != nil {
83                         t.Fatal(err)
84                 }
85                 x, err := ioutil.ReadAll(rr)
86                 if err != nil {
87                         t.Fatal(err)
88                 }
89                 if string(x) != s {
90                         t.Fatalf("got %q, want %q", short(string(x)), short(s))
91                 }
92         }
93         if _, err := r.Next(); err != io.EOF {
94                 t.Fatalf("got %v, want %v", err, io.EOF)
95         }
96 }
97
98 func testLiterals(t *testing.T, s []string) {
99         var i int
100         reset := func() {
101                 i = 0
102         }
103         gen := func() (string, bool) {
104                 if i == len(s) {
105                         return "", false
106                 }
107                 i++
108                 return s[i-1], true
109         }
110         testGenerator(t, reset, gen)
111 }
112
113 func TestMany(t *testing.T) {
114         const n = 1e5
115         var i int
116         reset := func() {
117                 i = 0
118         }
119         gen := func() (string, bool) {
120                 if i == n {
121                         return "", false
122                 }
123                 i++
124                 return fmt.Sprintf("%d.", i-1), true
125         }
126         testGenerator(t, reset, gen)
127 }
128
129 func TestRandom(t *testing.T) {
130         const n = 1e2
131         var (
132                 i int
133                 r *rand.Rand
134         )
135         reset := func() {
136                 i, r = 0, rand.New(rand.NewSource(0))
137         }
138         gen := func() (string, bool) {
139                 if i == n {
140                         return "", false
141                 }
142                 i++
143                 return strings.Repeat(string(uint8(i)), r.Intn(2*blockSize+16)), true
144         }
145         testGenerator(t, reset, gen)
146 }
147
148 func TestBasic(t *testing.T) {
149         testLiterals(t, []string{
150                 strings.Repeat("a", 1000),
151                 strings.Repeat("b", 97270),
152                 strings.Repeat("c", 8000),
153         })
154 }
155
156 func TestBoundary(t *testing.T) {
157         for i := blockSize - 16; i < blockSize+16; i++ {
158                 s0 := big("abcd", i)
159                 for j := blockSize - 16; j < blockSize+16; j++ {
160                         s1 := big("ABCDE", j)
161                         testLiterals(t, []string{s0, s1})
162                         testLiterals(t, []string{s0, "", s1})
163                         testLiterals(t, []string{s0, "x", s1})
164                 }
165         }
166 }
167
168 func TestFlush(t *testing.T) {
169         buf := new(bytes.Buffer)
170         w := NewWriter(buf)
171         // Write a couple of records. Everything should still be held
172         // in the record.Writer buffer, so that buf.Len should be 0.
173         w0, _ := w.Next()
174         w0.Write([]byte("0"))
175         w1, _ := w.Next()
176         w1.Write([]byte("11"))
177         if got, want := buf.Len(), 0; got != want {
178                 t.Fatalf("buffer length #0: got %d want %d", got, want)
179         }
180         // Flush the record.Writer buffer, which should yield 17 bytes.
181         // 17 = 2*7 + 1 + 2, which is two headers and 1 + 2 payload bytes.
182         if err := w.Flush(); err != nil {
183                 t.Fatal(err)
184         }
185         if got, want := buf.Len(), 17; got != want {
186                 t.Fatalf("buffer length #1: got %d want %d", got, want)
187         }
188         // Do another write, one that isn't large enough to complete the block.
189         // The write should not have flowed through to buf.
190         w2, _ := w.Next()
191         w2.Write(bytes.Repeat([]byte("2"), 10000))
192         if got, want := buf.Len(), 17; got != want {
193                 t.Fatalf("buffer length #2: got %d want %d", got, want)
194         }
195         // Flushing should get us up to 10024 bytes written.
196         // 10024 = 17 + 7 + 10000.
197         if err := w.Flush(); err != nil {
198                 t.Fatal(err)
199         }
200         if got, want := buf.Len(), 10024; got != want {
201                 t.Fatalf("buffer length #3: got %d want %d", got, want)
202         }
203         // Do a bigger write, one that completes the current block.
204         // We should now have 32768 bytes (a complete block), without
205         // an explicit flush.
206         w3, _ := w.Next()
207         w3.Write(bytes.Repeat([]byte("3"), 40000))
208         if got, want := buf.Len(), 32768; got != want {
209                 t.Fatalf("buffer length #4: got %d want %d", got, want)
210         }
211         // Flushing should get us up to 50038 bytes written.
212         // 50038 = 10024 + 2*7 + 40000. There are two headers because
213         // the one record was split into two chunks.
214         if err := w.Flush(); err != nil {
215                 t.Fatal(err)
216         }
217         if got, want := buf.Len(), 50038; got != want {
218                 t.Fatalf("buffer length #5: got %d want %d", got, want)
219         }
220         // Check that reading those records give the right lengths.
221         r := NewReader(buf, dropper{t}, true, true)
222         wants := []int64{1, 2, 10000, 40000}
223         for i, want := range wants {
224                 rr, _ := r.Next()
225                 n, err := io.Copy(ioutil.Discard, rr)
226                 if err != nil {
227                         t.Fatalf("read #%d: %v", i, err)
228                 }
229                 if n != want {
230                         t.Fatalf("read #%d: got %d bytes want %d", i, n, want)
231                 }
232         }
233 }
234
235 func TestNonExhaustiveRead(t *testing.T) {
236         const n = 100
237         buf := new(bytes.Buffer)
238         p := make([]byte, 10)
239         rnd := rand.New(rand.NewSource(1))
240
241         w := NewWriter(buf)
242         for i := 0; i < n; i++ {
243                 length := len(p) + rnd.Intn(3*blockSize)
244                 s := string(uint8(i)) + "123456789abcdefgh"
245                 ww, _ := w.Next()
246                 ww.Write([]byte(big(s, length)))
247         }
248         if err := w.Close(); err != nil {
249                 t.Fatal(err)
250         }
251
252         r := NewReader(buf, dropper{t}, true, true)
253         for i := 0; i < n; i++ {
254                 rr, _ := r.Next()
255                 _, err := io.ReadFull(rr, p)
256                 if err != nil {
257                         t.Fatal(err)
258                 }
259                 want := string(uint8(i)) + "123456789"
260                 if got := string(p); got != want {
261                         t.Fatalf("read #%d: got %q want %q", i, got, want)
262                 }
263         }
264 }
265
266 func TestStaleReader(t *testing.T) {
267         buf := new(bytes.Buffer)
268
269         w := NewWriter(buf)
270         w0, err := w.Next()
271         if err != nil {
272                 t.Fatal(err)
273         }
274         w0.Write([]byte("0"))
275         w1, err := w.Next()
276         if err != nil {
277                 t.Fatal(err)
278         }
279         w1.Write([]byte("11"))
280         if err := w.Close(); err != nil {
281                 t.Fatal(err)
282         }
283
284         r := NewReader(buf, dropper{t}, true, true)
285         r0, err := r.Next()
286         if err != nil {
287                 t.Fatal(err)
288         }
289         r1, err := r.Next()
290         if err != nil {
291                 t.Fatal(err)
292         }
293         p := make([]byte, 1)
294         if _, err := r0.Read(p); err == nil || !strings.Contains(err.Error(), "stale") {
295                 t.Fatalf("stale read #0: unexpected error: %v", err)
296         }
297         if _, err := r1.Read(p); err != nil {
298                 t.Fatalf("fresh read #1: got %v want nil error", err)
299         }
300         if p[0] != '1' {
301                 t.Fatalf("fresh read #1: byte contents: got '%c' want '1'", p[0])
302         }
303 }
304
305 func TestStaleWriter(t *testing.T) {
306         buf := new(bytes.Buffer)
307
308         w := NewWriter(buf)
309         w0, err := w.Next()
310         if err != nil {
311                 t.Fatal(err)
312         }
313         w1, err := w.Next()
314         if err != nil {
315                 t.Fatal(err)
316         }
317         if _, err := w0.Write([]byte("0")); err == nil || !strings.Contains(err.Error(), "stale") {
318                 t.Fatalf("stale write #0: unexpected error: %v", err)
319         }
320         if _, err := w1.Write([]byte("11")); err != nil {
321                 t.Fatalf("fresh write #1: got %v want nil error", err)
322         }
323         if err := w.Flush(); err != nil {
324                 t.Fatalf("flush: %v", err)
325         }
326         if _, err := w1.Write([]byte("0")); err == nil || !strings.Contains(err.Error(), "stale") {
327                 t.Fatalf("stale write #1: unexpected error: %v", err)
328         }
329 }
330
331 func TestCorrupt_MissingLastBlock(t *testing.T) {
332         buf := new(bytes.Buffer)
333
334         w := NewWriter(buf)
335
336         // First record.
337         ww, err := w.Next()
338         if err != nil {
339                 t.Fatal(err)
340         }
341         if _, err := ww.Write(bytes.Repeat([]byte("0"), blockSize-1024)); err != nil {
342                 t.Fatalf("write #0: unexpected error: %v", err)
343         }
344
345         // Second record.
346         ww, err = w.Next()
347         if err != nil {
348                 t.Fatal(err)
349         }
350         if _, err := ww.Write(bytes.Repeat([]byte("0"), blockSize-headerSize)); err != nil {
351                 t.Fatalf("write #1: unexpected error: %v", err)
352         }
353
354         if err := w.Close(); err != nil {
355                 t.Fatal(err)
356         }
357
358         // Cut the last block.
359         b := buf.Bytes()[:blockSize]
360         r := NewReader(bytes.NewReader(b), dropper{t}, false, true)
361
362         // First read.
363         rr, err := r.Next()
364         if err != nil {
365                 t.Fatal(err)
366         }
367         n, err := io.Copy(ioutil.Discard, rr)
368         if err != nil {
369                 t.Fatalf("read #0: %v", err)
370         }
371         if n != blockSize-1024 {
372                 t.Fatalf("read #0: got %d bytes want %d", n, blockSize-1024)
373         }
374
375         // Second read.
376         rr, err = r.Next()
377         if err != nil {
378                 t.Fatal(err)
379         }
380         n, err = io.Copy(ioutil.Discard, rr)
381         if err != io.ErrUnexpectedEOF {
382                 t.Fatalf("read #1: unexpected error: %v", err)
383         }
384
385         if _, err := r.Next(); err != io.EOF {
386                 t.Fatalf("last next: unexpected error: %v", err)
387         }
388 }
389
390 func TestCorrupt_CorruptedFirstBlock(t *testing.T) {
391         buf := new(bytes.Buffer)
392
393         w := NewWriter(buf)
394
395         // First record.
396         ww, err := w.Next()
397         if err != nil {
398                 t.Fatal(err)
399         }
400         if _, err := ww.Write(bytes.Repeat([]byte("0"), blockSize/2)); err != nil {
401                 t.Fatalf("write #0: unexpected error: %v", err)
402         }
403
404         // Second record.
405         ww, err = w.Next()
406         if err != nil {
407                 t.Fatal(err)
408         }
409         if _, err := ww.Write(bytes.Repeat([]byte("0"), blockSize-headerSize)); err != nil {
410                 t.Fatalf("write #1: unexpected error: %v", err)
411         }
412
413         // Third record.
414         ww, err = w.Next()
415         if err != nil {
416                 t.Fatal(err)
417         }
418         if _, err := ww.Write(bytes.Repeat([]byte("0"), (blockSize-headerSize)+1)); err != nil {
419                 t.Fatalf("write #2: unexpected error: %v", err)
420         }
421
422         // Fourth record.
423         ww, err = w.Next()
424         if err != nil {
425                 t.Fatal(err)
426         }
427         if _, err := ww.Write(bytes.Repeat([]byte("0"), (blockSize-headerSize)+2)); err != nil {
428                 t.Fatalf("write #3: unexpected error: %v", err)
429         }
430
431         if err := w.Close(); err != nil {
432                 t.Fatal(err)
433         }
434
435         b := buf.Bytes()
436         // Corrupting block #0.
437         for i := 0; i < 1024; i++ {
438                 b[i] = '1'
439         }
440
441         r := NewReader(bytes.NewReader(b), dropper{t}, false, true)
442
443         // First read (third record).
444         rr, err := r.Next()
445         if err != nil {
446                 t.Fatal(err)
447         }
448         n, err := io.Copy(ioutil.Discard, rr)
449         if err != nil {
450                 t.Fatalf("read #0: %v", err)
451         }
452         if want := int64(blockSize-headerSize) + 1; n != want {
453                 t.Fatalf("read #0: got %d bytes want %d", n, want)
454         }
455
456         // Second read (fourth record).
457         rr, err = r.Next()
458         if err != nil {
459                 t.Fatal(err)
460         }
461         n, err = io.Copy(ioutil.Discard, rr)
462         if err != nil {
463                 t.Fatalf("read #1: %v", err)
464         }
465         if want := int64(blockSize-headerSize) + 2; n != want {
466                 t.Fatalf("read #1: got %d bytes want %d", n, want)
467         }
468
469         if _, err := r.Next(); err != io.EOF {
470                 t.Fatalf("last next: unexpected error: %v", err)
471         }
472 }
473
474 func TestCorrupt_CorruptedMiddleBlock(t *testing.T) {
475         buf := new(bytes.Buffer)
476
477         w := NewWriter(buf)
478
479         // First record.
480         ww, err := w.Next()
481         if err != nil {
482                 t.Fatal(err)
483         }
484         if _, err := ww.Write(bytes.Repeat([]byte("0"), blockSize/2)); err != nil {
485                 t.Fatalf("write #0: unexpected error: %v", err)
486         }
487
488         // Second record.
489         ww, err = w.Next()
490         if err != nil {
491                 t.Fatal(err)
492         }
493         if _, err := ww.Write(bytes.Repeat([]byte("0"), blockSize-headerSize)); err != nil {
494                 t.Fatalf("write #1: unexpected error: %v", err)
495         }
496
497         // Third record.
498         ww, err = w.Next()
499         if err != nil {
500                 t.Fatal(err)
501         }
502         if _, err := ww.Write(bytes.Repeat([]byte("0"), (blockSize-headerSize)+1)); err != nil {
503                 t.Fatalf("write #2: unexpected error: %v", err)
504         }
505
506         // Fourth record.
507         ww, err = w.Next()
508         if err != nil {
509                 t.Fatal(err)
510         }
511         if _, err := ww.Write(bytes.Repeat([]byte("0"), (blockSize-headerSize)+2)); err != nil {
512                 t.Fatalf("write #3: unexpected error: %v", err)
513         }
514
515         if err := w.Close(); err != nil {
516                 t.Fatal(err)
517         }
518
519         b := buf.Bytes()
520         // Corrupting block #1.
521         for i := 0; i < 1024; i++ {
522                 b[blockSize+i] = '1'
523         }
524
525         r := NewReader(bytes.NewReader(b), dropper{t}, false, true)
526
527         // First read (first record).
528         rr, err := r.Next()
529         if err != nil {
530                 t.Fatal(err)
531         }
532         n, err := io.Copy(ioutil.Discard, rr)
533         if err != nil {
534                 t.Fatalf("read #0: %v", err)
535         }
536         if want := int64(blockSize / 2); n != want {
537                 t.Fatalf("read #0: got %d bytes want %d", n, want)
538         }
539
540         // Second read (second record).
541         rr, err = r.Next()
542         if err != nil {
543                 t.Fatal(err)
544         }
545         n, err = io.Copy(ioutil.Discard, rr)
546         if err != io.ErrUnexpectedEOF {
547                 t.Fatalf("read #1: unexpected error: %v", err)
548         }
549
550         // Third read (fourth record).
551         rr, err = r.Next()
552         if err != nil {
553                 t.Fatal(err)
554         }
555         n, err = io.Copy(ioutil.Discard, rr)
556         if err != nil {
557                 t.Fatalf("read #2: %v", err)
558         }
559         if want := int64(blockSize-headerSize) + 2; n != want {
560                 t.Fatalf("read #2: got %d bytes want %d", n, want)
561         }
562
563         if _, err := r.Next(); err != io.EOF {
564                 t.Fatalf("last next: unexpected error: %v", err)
565         }
566 }
567
568 func TestCorrupt_CorruptedLastBlock(t *testing.T) {
569         buf := new(bytes.Buffer)
570
571         w := NewWriter(buf)
572
573         // First record.
574         ww, err := w.Next()
575         if err != nil {
576                 t.Fatal(err)
577         }
578         if _, err := ww.Write(bytes.Repeat([]byte("0"), blockSize/2)); err != nil {
579                 t.Fatalf("write #0: unexpected error: %v", err)
580         }
581
582         // Second record.
583         ww, err = w.Next()
584         if err != nil {
585                 t.Fatal(err)
586         }
587         if _, err := ww.Write(bytes.Repeat([]byte("0"), blockSize-headerSize)); err != nil {
588                 t.Fatalf("write #1: unexpected error: %v", err)
589         }
590
591         // Third record.
592         ww, err = w.Next()
593         if err != nil {
594                 t.Fatal(err)
595         }
596         if _, err := ww.Write(bytes.Repeat([]byte("0"), (blockSize-headerSize)+1)); err != nil {
597                 t.Fatalf("write #2: unexpected error: %v", err)
598         }
599
600         // Fourth record.
601         ww, err = w.Next()
602         if err != nil {
603                 t.Fatal(err)
604         }
605         if _, err := ww.Write(bytes.Repeat([]byte("0"), (blockSize-headerSize)+2)); err != nil {
606                 t.Fatalf("write #3: unexpected error: %v", err)
607         }
608
609         if err := w.Close(); err != nil {
610                 t.Fatal(err)
611         }
612
613         b := buf.Bytes()
614         // Corrupting block #3.
615         for i := len(b) - 1; i > len(b)-1024; i-- {
616                 b[i] = '1'
617         }
618
619         r := NewReader(bytes.NewReader(b), dropper{t}, false, true)
620
621         // First read (first record).
622         rr, err := r.Next()
623         if err != nil {
624                 t.Fatal(err)
625         }
626         n, err := io.Copy(ioutil.Discard, rr)
627         if err != nil {
628                 t.Fatalf("read #0: %v", err)
629         }
630         if want := int64(blockSize / 2); n != want {
631                 t.Fatalf("read #0: got %d bytes want %d", n, want)
632         }
633
634         // Second read (second record).
635         rr, err = r.Next()
636         if err != nil {
637                 t.Fatal(err)
638         }
639         n, err = io.Copy(ioutil.Discard, rr)
640         if err != nil {
641                 t.Fatalf("read #1: %v", err)
642         }
643         if want := int64(blockSize - headerSize); n != want {
644                 t.Fatalf("read #1: got %d bytes want %d", n, want)
645         }
646
647         // Third read (third record).
648         rr, err = r.Next()
649         if err != nil {
650                 t.Fatal(err)
651         }
652         n, err = io.Copy(ioutil.Discard, rr)
653         if err != nil {
654                 t.Fatalf("read #2: %v", err)
655         }
656         if want := int64(blockSize-headerSize) + 1; n != want {
657                 t.Fatalf("read #2: got %d bytes want %d", n, want)
658         }
659
660         // Fourth read (fourth record).
661         rr, err = r.Next()
662         if err != nil {
663                 t.Fatal(err)
664         }
665         n, err = io.Copy(ioutil.Discard, rr)
666         if err != io.ErrUnexpectedEOF {
667                 t.Fatalf("read #3: unexpected error: %v", err)
668         }
669
670         if _, err := r.Next(); err != io.EOF {
671                 t.Fatalf("last next: unexpected error: %v", err)
672         }
673 }
674
675 func TestCorrupt_FirstChuckLengthOverflow(t *testing.T) {
676         buf := new(bytes.Buffer)
677
678         w := NewWriter(buf)
679
680         // First record.
681         ww, err := w.Next()
682         if err != nil {
683                 t.Fatal(err)
684         }
685         if _, err := ww.Write(bytes.Repeat([]byte("0"), blockSize/2)); err != nil {
686                 t.Fatalf("write #0: unexpected error: %v", err)
687         }
688
689         // Second record.
690         ww, err = w.Next()
691         if err != nil {
692                 t.Fatal(err)
693         }
694         if _, err := ww.Write(bytes.Repeat([]byte("0"), blockSize-headerSize)); err != nil {
695                 t.Fatalf("write #1: unexpected error: %v", err)
696         }
697
698         // Third record.
699         ww, err = w.Next()
700         if err != nil {
701                 t.Fatal(err)
702         }
703         if _, err := ww.Write(bytes.Repeat([]byte("0"), (blockSize-headerSize)+1)); err != nil {
704                 t.Fatalf("write #2: unexpected error: %v", err)
705         }
706
707         if err := w.Close(); err != nil {
708                 t.Fatal(err)
709         }
710
711         b := buf.Bytes()
712         // Corrupting record #1.
713         x := blockSize
714         binary.LittleEndian.PutUint16(b[x+4:], 0xffff)
715
716         r := NewReader(bytes.NewReader(b), dropper{t}, false, true)
717
718         // First read (first record).
719         rr, err := r.Next()
720         if err != nil {
721                 t.Fatal(err)
722         }
723         n, err := io.Copy(ioutil.Discard, rr)
724         if err != nil {
725                 t.Fatalf("read #0: %v", err)
726         }
727         if want := int64(blockSize / 2); n != want {
728                 t.Fatalf("read #0: got %d bytes want %d", n, want)
729         }
730
731         // Second read (second record).
732         rr, err = r.Next()
733         if err != nil {
734                 t.Fatal(err)
735         }
736         n, err = io.Copy(ioutil.Discard, rr)
737         if err != io.ErrUnexpectedEOF {
738                 t.Fatalf("read #1: unexpected error: %v", err)
739         }
740
741         if _, err := r.Next(); err != io.EOF {
742                 t.Fatalf("last next: unexpected error: %v", err)
743         }
744 }
745
746 func TestCorrupt_MiddleChuckLengthOverflow(t *testing.T) {
747         buf := new(bytes.Buffer)
748
749         w := NewWriter(buf)
750
751         // First record.
752         ww, err := w.Next()
753         if err != nil {
754                 t.Fatal(err)
755         }
756         if _, err := ww.Write(bytes.Repeat([]byte("0"), blockSize/2)); err != nil {
757                 t.Fatalf("write #0: unexpected error: %v", err)
758         }
759
760         // Second record.
761         ww, err = w.Next()
762         if err != nil {
763                 t.Fatal(err)
764         }
765         if _, err := ww.Write(bytes.Repeat([]byte("0"), blockSize-headerSize)); err != nil {
766                 t.Fatalf("write #1: unexpected error: %v", err)
767         }
768
769         // Third record.
770         ww, err = w.Next()
771         if err != nil {
772                 t.Fatal(err)
773         }
774         if _, err := ww.Write(bytes.Repeat([]byte("0"), (blockSize-headerSize)+1)); err != nil {
775                 t.Fatalf("write #2: unexpected error: %v", err)
776         }
777
778         if err := w.Close(); err != nil {
779                 t.Fatal(err)
780         }
781
782         b := buf.Bytes()
783         // Corrupting record #1.
784         x := blockSize/2 + headerSize
785         binary.LittleEndian.PutUint16(b[x+4:], 0xffff)
786
787         r := NewReader(bytes.NewReader(b), dropper{t}, false, true)
788
789         // First read (first record).
790         rr, err := r.Next()
791         if err != nil {
792                 t.Fatal(err)
793         }
794         n, err := io.Copy(ioutil.Discard, rr)
795         if err != nil {
796                 t.Fatalf("read #0: %v", err)
797         }
798         if want := int64(blockSize / 2); n != want {
799                 t.Fatalf("read #0: got %d bytes want %d", n, want)
800         }
801
802         // Second read (third record).
803         rr, err = r.Next()
804         if err != nil {
805                 t.Fatal(err)
806         }
807         n, err = io.Copy(ioutil.Discard, rr)
808         if err != nil {
809                 t.Fatalf("read #1: %v", err)
810         }
811         if want := int64(blockSize-headerSize) + 1; n != want {
812                 t.Fatalf("read #1: got %d bytes want %d", n, want)
813         }
814
815         if _, err := r.Next(); err != io.EOF {
816                 t.Fatalf("last next: unexpected error: %v", err)
817         }
818 }