blob: c5696e5c568163a415035c25c5d64496cf02b768 [file] [log] [blame]
// Copyright 2019 The Wuffs Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// +build ignore
package main
// rac-random-seek-test.go compresses stdin to the RAC file format, then checks
// that repeatedly randomly accessing that RAC file recovers the original input.
//
// Usage: go run rac-random-seek-test.go < input
import (
"bytes"
"fmt"
"io"
"io/ioutil"
"math/rand"
"os"
"github.com/google/wuffs/lib/rac"
"github.com/google/wuffs/lib/raczlib"
)
func main() {
if err := main1(); err != nil {
os.Stderr.WriteString(err.Error() + "\n")
os.Exit(1)
}
}
func main1() error {
input, err := ioutil.ReadAll(os.Stdin)
if err != nil {
return err
}
buf := &bytes.Buffer{}
const dChunkSize = 256
w := &rac.Writer{
Writer: buf,
CodecWriter: &raczlib.CodecWriter{},
DChunkSize: dChunkSize,
}
if _, err := w.Write(input); err != nil {
return err
}
if err := w.Close(); err != nil {
return err
}
compressed := buf.Bytes()
r := &rac.Reader{
ReadSeeker: bytes.NewReader(compressed),
CompressedSize: int64(buf.Len()),
CodecReaders: []rac.CodecReader{&raczlib.CodecReader{}},
}
numChunks, err := countRACChunks(compressed)
if err != nil {
return err
}
if want := (len(input) + dChunkSize - 1) / dChunkSize; numChunks != want {
return fmt.Errorf("numChunks: got %d, want %d", numChunks, want)
}
fmt.Printf("%8d uncompressed bytes\n", len(input))
fmt.Printf("%8d compressed bytes\n", len(compressed))
fmt.Printf("%8d RAC chunks\n", numChunks)
got := make([]byte, len(input))
if _, err := io.ReadFull(r, got); err != nil {
return fmt.Errorf("ReadFull: %v", err)
} else if !bytes.Equal(got, input) {
return fmt.Errorf("ReadFull: mismatch")
}
for i, rng := uint64(0), rand.New(rand.NewSource(1)); ; i++ {
m := rng.Intn(len(input) + 1)
n := rng.Intn(len(input) + 1)
if m > n {
m, n = n, m
}
got = got[:n-m]
if _, err := r.Seek(int64(m), io.SeekStart); err != nil {
return fmt.Errorf("i=%d, m=%d, n=%d: Seek: %v", i, m, n, err)
}
if _, err := io.ReadFull(r, got); err != nil {
return fmt.Errorf("i=%d, m=%d, n=%d: ReadFull: %v", i, m, n, err)
}
want := input[m:n]
if !bytes.Equal(got, want) {
return fmt.Errorf("i=%d, m=%d, n=%d: mismatch", i, m, n)
}
if i%1024 == 0 {
fmt.Printf("i=%d: ok\n", i)
}
}
}
func countRACChunks(compressed []byte) (int, error) {
r := &rac.ChunkReader{
ReadSeeker: bytes.NewReader(compressed),
CompressedSize: int64(len(compressed)),
}
for n := 0; ; n++ {
if _, err := r.NextChunk(); err == io.EOF {
return n, nil
} else if err != nil {
return 0, err
}
}
}