owpengram-server/internal/loadharness/file_fixture.go

112 lines
3.6 KiB
Go

package loadharness
import (
"encoding/json"
"errors"
"fmt"
"os"
"path/filepath"
"strings"
"time"
"github.com/iamxvbaba/td/tg"
)
const (
fileFixtureVersion = 1
fixturePatternVersion = 1
)
// persistedFileFixture keeps only the stable location of a synthetic load-test
// document. It contains no auth key or login secret and is owner-readable so a
// test bundle can reuse the same server-side file across independent runs.
type persistedFileFixture struct {
Version int `json:"version"`
CreatedAt time.Time `json:"created_at"`
ServerAddress string `json:"server_address"`
DC int `json:"dc"`
SizeBytes int `json:"size_bytes"`
PatternVersion int `json:"pattern_version"`
DocumentID int64 `json:"document_id"`
AccessHash int64 `json:"access_hash"`
FileReference []byte `json:"file_reference"`
}
func (f *persistedFileFixture) validate(endpoint Endpoint, size int) error {
if f == nil {
return errors.New("nil file fixture")
}
if f.Version != fileFixtureVersion || f.PatternVersion != fixturePatternVersion {
return errors.New("file fixture version does not match the harness")
}
if f.ServerAddress != endpoint.Address || f.DC != endpoint.DC {
return errors.New("file fixture endpoint does not match the manifest")
}
if f.SizeBytes != size || f.SizeBytes <= 0 {
return fmt.Errorf("file fixture size %d does not match requested %d", f.SizeBytes, size)
}
if f.DocumentID == 0 || f.AccessHash == 0 || len(f.FileReference) == 0 {
return errors.New("file fixture has an incomplete document location")
}
return nil
}
func (f *persistedFileFixture) runtime(chunk int) *downloadFixture {
return &downloadFixture{
location: &tg.InputDocumentFileLocation{
ID: f.DocumentID, AccessHash: f.AccessHash,
FileReference: append([]byte(nil), f.FileReference...),
},
size: f.SizeBytes, chunk: chunk,
}
}
func persistedFixture(endpoint Endpoint, fixture *downloadFixture) *persistedFileFixture {
return &persistedFileFixture{
Version: fileFixtureVersion, CreatedAt: time.Now().UTC(),
ServerAddress: endpoint.Address, DC: endpoint.DC,
SizeBytes: fixture.size, PatternVersion: fixturePatternVersion,
DocumentID: fixture.location.ID, AccessHash: fixture.location.AccessHash,
FileReference: append([]byte(nil), fixture.location.FileReference...),
}
}
func resolveFileFixturePath(manifestPath, configured string) string {
configured = strings.TrimSpace(configured)
if configured == "" {
return filepath.Join(filepath.Dir(manifestPath), "file-fixture.json")
}
if filepath.IsAbs(configured) {
return configured
}
return filepath.Join(filepath.Dir(manifestPath), filepath.FromSlash(configured))
}
func loadPersistedFileFixture(path string, endpoint Endpoint, size, chunk int) (*downloadFixture, error) {
data, err := os.ReadFile(path)
if err != nil {
return nil, err
}
var fixture persistedFileFixture
decoder := json.NewDecoder(strings.NewReader(string(data)))
decoder.DisallowUnknownFields()
if err := decoder.Decode(&fixture); err != nil {
return nil, fmt.Errorf("decode file fixture: %w", err)
}
if err := fixture.validate(endpoint, size); err != nil {
return nil, err
}
return fixture.runtime(chunk), nil
}
func writePersistedFileFixture(path string, endpoint Endpoint, fixture *downloadFixture) error {
persisted := persistedFixture(endpoint, fixture)
if err := persisted.validate(endpoint, fixture.size); err != nil {
return err
}
data, err := json.MarshalIndent(persisted, "", " ")
if err != nil {
return fmt.Errorf("encode file fixture: %w", err)
}
return writeFileAtomic(path, append(data, '\n'), 0o600)
}