blob: f571ea3e087a8a6749a1adccd6c53d7331d4de43 [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"
Nigel Taofb0b1722019-08-06 16:15:09 +100029 "math/rand"
30 "os"
31
32 "github.com/google/wuffs/lib/rac"
33 "github.com/google/wuffs/lib/raczlib"
34)
35
36func main() {
37 if err := main1(); err != nil {
38 os.Stderr.WriteString(err.Error() + "\n")
39 os.Exit(1)
40 }
41}
42
43func main1() error {
Nigel Tao226c4762021-08-22 11:05:43 +100044 input, err := io.ReadAll(os.Stdin)
Nigel Taofb0b1722019-08-06 16:15:09 +100045 if err != nil {
46 return err
47 }
48 buf := &bytes.Buffer{}
49 const dChunkSize = 256
Nigel Taof53bee32019-08-24 07:56:53 +100050 w := &rac.Writer{
51 Writer: buf,
52 CodecWriter: &raczlib.CodecWriter{},
53 DChunkSize: dChunkSize,
Nigel Taofb0b1722019-08-06 16:15:09 +100054 }
55 if _, err := w.Write(input); err != nil {
56 return err
57 }
58 if err := w.Close(); err != nil {
59 return err
60 }
61 compressed := buf.Bytes()
Nigel Taof53bee32019-08-24 07:56:53 +100062 r := &rac.Reader{
Nigel Taoca4a6c82019-08-24 09:34:12 +100063 ReadSeeker: bytes.NewReader(compressed),
64 CompressedSize: int64(buf.Len()),
65 CodecReaders: []rac.CodecReader{&raczlib.CodecReader{}},
Nigel Taofb0b1722019-08-06 16:15:09 +100066 }
67 numChunks, err := countRACChunks(compressed)
68 if err != nil {
69 return err
70 }
71 if want := (len(input) + dChunkSize - 1) / dChunkSize; numChunks != want {
72 return fmt.Errorf("numChunks: got %d, want %d", numChunks, want)
73 }
74
75 fmt.Printf("%8d uncompressed bytes\n", len(input))
76 fmt.Printf("%8d compressed bytes\n", len(compressed))
77 fmt.Printf("%8d RAC chunks\n", numChunks)
78
79 got := make([]byte, len(input))
80 if _, err := io.ReadFull(r, got); err != nil {
81 return fmt.Errorf("ReadFull: %v", err)
82 } else if !bytes.Equal(got, input) {
83 return fmt.Errorf("ReadFull: mismatch")
84 }
85
86 for i, rng := uint64(0), rand.New(rand.NewSource(1)); ; i++ {
87 m := rng.Intn(len(input) + 1)
88 n := rng.Intn(len(input) + 1)
89 if m > n {
90 m, n = n, m
91 }
92
93 got = got[:n-m]
94 if _, err := r.Seek(int64(m), io.SeekStart); err != nil {
95 return fmt.Errorf("i=%d, m=%d, n=%d: Seek: %v", i, m, n, err)
96 }
97 if _, err := io.ReadFull(r, got); err != nil {
98 return fmt.Errorf("i=%d, m=%d, n=%d: ReadFull: %v", i, m, n, err)
99 }
100
101 want := input[m:n]
102 if !bytes.Equal(got, want) {
103 return fmt.Errorf("i=%d, m=%d, n=%d: mismatch", i, m, n)
104 }
105
106 if i%1024 == 0 {
107 fmt.Printf("i=%d: ok\n", i)
108 }
109 }
110}
111
112func countRACChunks(compressed []byte) (int, error) {
Nigel Taof53bee32019-08-24 07:56:53 +1000113 r := &rac.ChunkReader{
Nigel Taoca4a6c82019-08-24 09:34:12 +1000114 ReadSeeker: bytes.NewReader(compressed),
115 CompressedSize: int64(len(compressed)),
Nigel Taofb0b1722019-08-06 16:15:09 +1000116 }
117 for n := 0; ; n++ {
Nigel Taof53bee32019-08-24 07:56:53 +1000118 if _, err := r.NextChunk(); err == io.EOF {
Nigel Taofb0b1722019-08-06 16:15:09 +1000119 return n, nil
120 } else if err != nil {
121 return 0, err
122 }
123 }
124}