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) }