blob: 08d1d055fc65a3152e2b53d129ec7c15a0e09bd6 [file] [log] [blame]
Nigel Taofb0b1722019-08-06 16:15:09 +10001// Copyright 2019 The Wuffs Authors.
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// https://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
Nigel Tao788479d2021-08-22 10:52:51 +100015//go:build ignore
Nigel Taofb0b1722019-08-06 16:15:09 +100016// +build ignore
17
18package main
19
20// rac-random-seek-test.go compresses stdin to the RAC file format, then checks
21// that repeatedly randomly accessing that RAC file recovers the original input.
22//
23// Usage: go run rac-random-seek-test.go < input
24
25import (
26 "bytes"
27 "fmt"
28 "io"
29 "io/ioutil"
30 "math/rand"
31 "os"
32
33 "github.com/google/wuffs/lib/rac"
34 "github.com/google/wuffs/lib/raczlib"
35)
36
37func main() {
38 if err := main1(); err != nil {
39 os.Stderr.WriteString(err.Error() + "\n")
40 os.Exit(1)
41 }
42}
43
44func main1() error {
45 input, err := ioutil.ReadAll(os.Stdin)
46 if err != nil {
47 return err
48 }
49 buf := &bytes.Buffer{}
50 const dChunkSize = 256
Nigel Taof53bee32019-08-24 07:56:53 +100051 w := &rac.Writer{
52 Writer: buf,
53 CodecWriter: &raczlib.CodecWriter{},
54 DChunkSize: dChunkSize,
Nigel Taofb0b1722019-08-06 16:15:09 +100055 }
56 if _, err := w.Write(input); err != nil {
57 return err
58 }
59 if err := w.Close(); err != nil {
60 return err
61 }
62 compressed := buf.Bytes()
Nigel Taof53bee32019-08-24 07:56:53 +100063 r := &rac.Reader{
Nigel Taoca4a6c82019-08-24 09:34:12 +100064 ReadSeeker: bytes.NewReader(compressed),
65 CompressedSize: int64(buf.Len()),
66 CodecReaders: []rac.CodecReader{&raczlib.CodecReader{}},
Nigel Taofb0b1722019-08-06 16:15:09 +100067 }
68 numChunks, err := countRACChunks(compressed)
69 if err != nil {
70 return err
71 }
72 if want := (len(input) + dChunkSize - 1) / dChunkSize; numChunks != want {
73 return fmt.Errorf("numChunks: got %d, want %d", numChunks, want)
74 }
75
76 fmt.Printf("%8d uncompressed bytes\n", len(input))
77 fmt.Printf("%8d compressed bytes\n", len(compressed))
78 fmt.Printf("%8d RAC chunks\n", numChunks)
79
80 got := make([]byte, len(input))
81 if _, err := io.ReadFull(r, got); err != nil {
82 return fmt.Errorf("ReadFull: %v", err)
83 } else if !bytes.Equal(got, input) {
84 return fmt.Errorf("ReadFull: mismatch")
85 }
86
87 for i, rng := uint64(0), rand.New(rand.NewSource(1)); ; i++ {
88 m := rng.Intn(len(input) + 1)
89 n := rng.Intn(len(input) + 1)
90 if m > n {
91 m, n = n, m
92 }
93
94 got = got[:n-m]
95 if _, err := r.Seek(int64(m), io.SeekStart); err != nil {
96 return fmt.Errorf("i=%d, m=%d, n=%d: Seek: %v", i, m, n, err)
97 }
98 if _, err := io.ReadFull(r, got); err != nil {
99 return fmt.Errorf("i=%d, m=%d, n=%d: ReadFull: %v", i, m, n, err)
100 }
101
102 want := input[m:n]
103 if !bytes.Equal(got, want) {
104 return fmt.Errorf("i=%d, m=%d, n=%d: mismatch", i, m, n)
105 }
106
107 if i%1024 == 0 {
108 fmt.Printf("i=%d: ok\n", i)
109 }
110 }
111}
112
113func countRACChunks(compressed []byte) (int, error) {
Nigel Taof53bee32019-08-24 07:56:53 +1000114 r := &rac.ChunkReader{
Nigel Taoca4a6c82019-08-24 09:34:12 +1000115 ReadSeeker: bytes.NewReader(compressed),
116 CompressedSize: int64(len(compressed)),
Nigel Taofb0b1722019-08-06 16:15:09 +1000117 }
118 for n := 0; ; n++ {
Nigel Taof53bee32019-08-24 07:56:53 +1000119 if _, err := r.NextChunk(); err == io.EOF {
Nigel Taofb0b1722019-08-06 16:15:09 +1000120 return n, nil
121 } else if err != nil {
122 return 0, err
123 }
124 }
125}