Compare commits
1
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
6ff59fd5f6 |
@@ -433,22 +433,9 @@ func TestService_Get_Caching(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// TestService_Get_ServesSourceAndVariantCachedTwoDaysAgo caches a source and
|
// TestService_Get_ServesSourceAndVariantCachedTwoDaysAgo caches a source and
|
||||||
// a variant of it and sets back two days every time pixa stored for them.
|
// a variant of it, sets their stored fetch and creation times back two days,
|
||||||
// For the source: fetched_at in source_metadata and in source_content, the
|
// and checks that the variant is still served from the cache and that a new
|
||||||
// fetched_at in its metadata file, and the access and modification times of
|
// variant is made from the cached source without fetching it again.
|
||||||
// its file and of its metadata file. For the variant: created_at in
|
|
||||||
// variant_content, the created_at in its .meta file, and the access and
|
|
||||||
// modification times of its file and of its .meta file. It then checks that
|
|
||||||
// the variant is still served from the cache and that a new variant is made
|
|
||||||
// from the cached source without fetching it again.
|
|
||||||
//
|
|
||||||
// Left at the present: last_accessed_at in source_content and variant_content,
|
|
||||||
// which is when eviction last saw the entry used, not when it was cached; the
|
|
||||||
// files' status change and birth times, which a program cannot set; and the
|
|
||||||
// times of the directories holding the files, which other entries share. The
|
|
||||||
// source's stored response headers are empty, as the mock fetcher sends none.
|
|
||||||
// expires_at, etag and last_modified in source_metadata and in the metadata
|
|
||||||
// file are never written, nor are the request_cache and output_content tables.
|
|
||||||
func TestService_Get_ServesSourceAndVariantCachedTwoDaysAgo(t *testing.T) {
|
func TestService_Get_ServesSourceAndVariantCachedTwoDaysAgo(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
|
|
||||||
@@ -462,9 +449,45 @@ func TestService_Get_ServesSourceAndVariantCachedTwoDaysAgo(t *testing.T) {
|
|||||||
|
|
||||||
_ = resp.Content.Close()
|
_ = resp.Content.Close()
|
||||||
|
|
||||||
|
for _, statement := range []string{
|
||||||
|
`UPDATE source_metadata SET fetched_at = datetime('now', '-2 days')`,
|
||||||
|
`UPDATE source_content SET fetched_at = datetime('now', '-2 days')`,
|
||||||
|
`UPDATE variant_content SET created_at = datetime('now', '-2 days')`,
|
||||||
|
} {
|
||||||
|
result, err := svc.cache.db.ExecContext(t.Context(), statement)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("%s: %v", statement, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
rows, err := result.RowsAffected()
|
||||||
|
if err != nil || rows != 1 {
|
||||||
|
t.Fatalf("%s: rows = %d, error = %v, want 1 row", statement, rows, err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// The variant's creation time is also its file's modification time
|
||||||
|
// and the created_at in its .meta file
|
||||||
twoDaysAgo := time.Now().AddDate(0, 0, -2)
|
twoDaysAgo := time.Now().AddDate(0, 0, -2)
|
||||||
backdateSource(t, svc.cache, variant, twoDaysAgo)
|
variantPath := svc.cache.variants.keyToPath(CacheKey(variant))
|
||||||
backdateVariant(t, svc.cache, variant, twoDaysAgo)
|
|
||||||
|
err = os.Chtimes(variantPath, twoDaysAgo, twoDaysAgo)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("setting the variant file's modification time back: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
meta, err := json.Marshal(VariantMeta{
|
||||||
|
ContentType: resp.ContentType,
|
||||||
|
Size: resp.ContentLength,
|
||||||
|
CreatedAt: twoDaysAgo.Unix(),
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("encoding .meta file: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
err = os.WriteFile(variantPath+".meta", meta, StorageFilePerm)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("writing .meta file: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
resp, err = svc.Get(t.Context(), variant)
|
resp, err = svc.Get(t.Context(), variant)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -492,110 +515,6 @@ func TestService_Get_ServesSourceAndVariantCachedTwoDaysAgo(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// backdateSource sets every time pixa stored for req's cached source to when,
|
|
||||||
// as listed on TestService_Get_ServesSourceAndVariantCachedTwoDaysAgo.
|
|
||||||
func backdateSource(
|
|
||||||
t *testing.T, cache *Cache, req *ImageRequest, when time.Time,
|
|
||||||
) {
|
|
||||||
t.Helper()
|
|
||||||
|
|
||||||
pathHash := HashPath(req.SourcePath + "?" + req.SourceQuery)
|
|
||||||
|
|
||||||
meta, err := cache.srcMetadata.Load(req.SourceHost, pathHash)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("reading the source's metadata file: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
meta.FetchedAt = when.Unix()
|
|
||||||
|
|
||||||
err = cache.srcMetadata.Store(req.SourceHost, pathHash, meta)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("writing the source's metadata file: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
dbTime := when.UTC().Format(sqliteTimestampFormat)
|
|
||||||
|
|
||||||
updateOneRow(t, cache, `
|
|
||||||
UPDATE source_metadata SET fetched_at = ?
|
|
||||||
WHERE source_host = ? AND source_path = ? AND source_query = ?
|
|
||||||
`, dbTime, req.SourceHost, req.SourcePath, req.SourceQuery)
|
|
||||||
updateOneRow(t, cache,
|
|
||||||
`UPDATE source_content SET fetched_at = ? WHERE content_hash = ?`,
|
|
||||||
dbTime, meta.ContentHash)
|
|
||||||
|
|
||||||
for _, path := range []string{
|
|
||||||
cache.srcContent.hashToPath(ContentHash(meta.ContentHash)),
|
|
||||||
cache.srcMetadata.metaPath(req.SourceHost, pathHash),
|
|
||||||
} {
|
|
||||||
err = os.Chtimes(path, when, when)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("setting back the times of %s: %v", path, err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// backdateVariant sets every time pixa stored for the cached variant req asks
|
|
||||||
// for to when, as listed on
|
|
||||||
// TestService_Get_ServesSourceAndVariantCachedTwoDaysAgo.
|
|
||||||
func backdateVariant(
|
|
||||||
t *testing.T, cache *Cache, req *ImageRequest, when time.Time,
|
|
||||||
) {
|
|
||||||
t.Helper()
|
|
||||||
|
|
||||||
key := CacheKey(req)
|
|
||||||
|
|
||||||
content, size, contentType, err := cache.variants.LoadWithMeta(key)
|
|
||||||
if err != nil || contentType == "" {
|
|
||||||
t.Fatalf("reading the variant's .meta file: content type %q, error %v",
|
|
||||||
contentType, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
_ = content.Close()
|
|
||||||
|
|
||||||
meta, err := json.Marshal(VariantMeta{
|
|
||||||
ContentType: contentType,
|
|
||||||
Size: size,
|
|
||||||
CreatedAt: when.Unix(),
|
|
||||||
})
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("encoding the variant's .meta file: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
path := cache.variants.keyToPath(key)
|
|
||||||
|
|
||||||
err = os.WriteFile(path+variantMetaSuffix, meta, StorageFilePerm)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("writing the variant's .meta file: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
updateOneRow(t, cache,
|
|
||||||
`UPDATE variant_content SET created_at = ? WHERE cache_key = ?`,
|
|
||||||
when.UTC().Format(sqliteTimestampFormat), string(key))
|
|
||||||
|
|
||||||
for _, file := range []string{path, path + variantMetaSuffix} {
|
|
||||||
err = os.Chtimes(file, when, when)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("setting back the times of %s: %v", file, err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// updateOneRow runs the UPDATE statement query and fails the test unless it
|
|
||||||
// changed exactly one row.
|
|
||||||
func updateOneRow(t *testing.T, cache *Cache, query string, args ...any) {
|
|
||||||
t.Helper()
|
|
||||||
|
|
||||||
result, err := cache.db.ExecContext(t.Context(), query, args...)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("%s: %v", query, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
rows, err := result.RowsAffected()
|
|
||||||
if err != nil || rows != 1 {
|
|
||||||
t.Fatalf("%s: rows = %d, error = %v, want 1 row", query, rows, err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestService_Get_DifferentSizes(t *testing.T) {
|
func TestService_Get_DifferentSizes(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
|
|
||||||
|
|||||||
Reference in new issue
Block a user