125 lines
3.6 KiB
Go
125 lines
3.6 KiB
Go
package hw3test
|
|
|
|
import (
|
|
"bytes"
|
|
"fmt"
|
|
"github.com/stretchr/testify/require"
|
|
"io"
|
|
"math/rand"
|
|
"os"
|
|
"path"
|
|
)
|
|
|
|
// RequireFileContent requires that the contents of the file match the contents of the reader.
|
|
func RequireFileContent(t *TC, workdir, p string, f *EnvFile) {
|
|
fullpath := path.Join(workdir, p)
|
|
file, err := os.Open(fullpath)
|
|
require.NoError(t, err, "failed to open file %s, expected it exists on disk", p)
|
|
defer file.Close()
|
|
|
|
stat, err := file.Stat()
|
|
require.NoError(t, err, "failed to stat file %s", p)
|
|
require.Equal(t, f.Size, stat.Size(), "file %s has wrong size", p)
|
|
require.NoError(t, CompareFileContent(t, file, f), "file %s has wrong content", p)
|
|
}
|
|
|
|
// CompareFileContent compares first f.Size bytes of the reader with generated content.
|
|
func CompareFileContent(t *TC, r io.Reader, f *EnvFile) error {
|
|
actual := make([]byte, 64*1024)
|
|
expected := make([]byte, len(actual))
|
|
var generator io.Reader
|
|
if f.TextOnly {
|
|
generator = f.Open()
|
|
} else {
|
|
generator = newComparisonReader(f.GenSeed)
|
|
}
|
|
for offset := int64(0); offset < f.Size; {
|
|
count := int64(len(actual))
|
|
if remaining := f.Size - offset; remaining < count {
|
|
count = remaining
|
|
}
|
|
if _, err := io.ReadFull(r, actual[:count]); err != nil {
|
|
return fmt.Errorf("unexpected file error at position %d: %w", offset, err)
|
|
}
|
|
if _, err := io.ReadFull(generator, expected[:count]); err != nil {
|
|
return fmt.Errorf("unexpected generator error at position %d: %w", offset, err)
|
|
}
|
|
if !bytes.Equal(actual[:count], expected[:count]) {
|
|
for i := int64(0); i < count; i++ {
|
|
if actual[i] != expected[i] {
|
|
return fmt.Errorf("position %d, expected byte %d, got %d", offset+i, expected[i], actual[i])
|
|
}
|
|
}
|
|
}
|
|
offset += count
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
// comparisonReader emits the same bytes as rand.New(source).Read, seven bytes
|
|
// from each Int63 value. It fills complete seven-byte groups without the
|
|
// per-byte branch in math/rand.Read. Request bodies still use EnvFile.Open.
|
|
type comparisonReader struct {
|
|
source rand.Source
|
|
value uint64
|
|
remaining uint8
|
|
}
|
|
|
|
func newComparisonReader(seed int64) *comparisonReader {
|
|
return &comparisonReader{source: rand.NewSource(seed)}
|
|
}
|
|
|
|
func (r *comparisonReader) Read(p []byte) (int, error) {
|
|
n := len(p)
|
|
for len(p) > 0 && r.remaining > 0 {
|
|
p[0] = byte(r.value)
|
|
r.value >>= 8
|
|
r.remaining--
|
|
p = p[1:]
|
|
}
|
|
for len(p) >= 7 {
|
|
value := uint64(r.source.Int63())
|
|
p[0] = byte(value)
|
|
p[1] = byte(value >> 8)
|
|
p[2] = byte(value >> 16)
|
|
p[3] = byte(value >> 24)
|
|
p[4] = byte(value >> 32)
|
|
p[5] = byte(value >> 40)
|
|
p[6] = byte(value >> 48)
|
|
p = p[7:]
|
|
}
|
|
if len(p) > 0 {
|
|
r.value = uint64(r.source.Int63())
|
|
r.remaining = 7
|
|
for i := range p {
|
|
p[i] = byte(r.value)
|
|
r.value >>= 8
|
|
r.remaining--
|
|
}
|
|
}
|
|
return n, nil
|
|
}
|
|
|
|
// RequireDir ensures that the directory exists on disk.
|
|
func RequireDir(t *TC, workdir string, p string, dir *EnvDir) {
|
|
fullpath := path.Join(workdir, p)
|
|
stat, err := os.Stat(fullpath)
|
|
require.NoError(t, err, "failed to stat directory %s, expected it exists on disk", p)
|
|
require.True(t, stat.IsDir(), "expected %s to be a directory", p)
|
|
}
|
|
|
|
// RequireNotExists ensures that the file/directory does not exist on disk.
|
|
func RequireNotExists(t *TC, workdir string, p string) {
|
|
fullpath := path.Join(workdir, p)
|
|
_, err := os.Stat(fullpath)
|
|
require.True(t, os.IsNotExist(err), "expected %s to not exist on disk", p)
|
|
}
|
|
|
|
// RequireExists ensures that the file/directory exists on disk.
|
|
func RequireExists(t *TC, workdir string, p string) {
|
|
fullpath := path.Join(workdir, p)
|
|
_, err := os.Stat(fullpath)
|
|
require.NoError(t, err, "failed to stat %s, expected it exists on disk", p)
|
|
}
|