68 lines
2.1 KiB
Go
68 lines
2.1 KiB
Go
|
|
// Package echo provides the conformance fixture adapters.
|
||
|
|
//
|
||
|
|
// Two revisions over the same data: R-1 exposes only a collection, R-2 adds the
|
||
|
|
// convenience resource. Both are ordinary deterministic HTTP handlers, which is
|
||
|
|
// the point — an adapter is a normal service, and fluid-core sits in front of
|
||
|
|
// it without asking anything of it.
|
||
|
|
package echo
|
||
|
|
|
||
|
|
import (
|
||
|
|
"encoding/json"
|
||
|
|
"net/http"
|
||
|
|
"sort"
|
||
|
|
"time"
|
||
|
|
)
|
||
|
|
|
||
|
|
// Entry is one record the fixture serves.
|
||
|
|
type Entry struct {
|
||
|
|
ID string `json:"id"`
|
||
|
|
Title string `json:"title"`
|
||
|
|
CreatedAt time.Time `json:"created_at"`
|
||
|
|
}
|
||
|
|
|
||
|
|
// Data returns a deterministic set of entries.
|
||
|
|
//
|
||
|
|
// Fixed timestamps rather than time.Now: a conformance suite whose fixture
|
||
|
|
// changes between runs cannot distinguish a regression from the clock.
|
||
|
|
func Data() []Entry {
|
||
|
|
base := time.Date(2026, 9, 1, 12, 0, 0, 0, time.UTC)
|
||
|
|
return []Entry{
|
||
|
|
{ID: "e-1", Title: "the river reached the forge", CreatedAt: base},
|
||
|
|
{ID: "e-2", Title: "nine doors stayed honest", CreatedAt: base.Add(24 * time.Hour)},
|
||
|
|
{ID: "e-3", Title: "the reviewing side", CreatedAt: base.Add(48 * time.Hour)},
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
// NewR1 returns the collection-only adapter.
|
||
|
|
//
|
||
|
|
// A consumer wanting the newest entry must fetch the whole collection, sort it
|
||
|
|
// and discard the rest. That is the interface pressure the fixture generates.
|
||
|
|
func NewR1() http.Handler {
|
||
|
|
mux := http.NewServeMux()
|
||
|
|
mux.HandleFunc("/v1/entries", func(w http.ResponseWriter, r *http.Request) {
|
||
|
|
writeJSON(w, Data())
|
||
|
|
})
|
||
|
|
return mux
|
||
|
|
}
|
||
|
|
|
||
|
|
// NewR2 returns the adapter with the convenience resource added.
|
||
|
|
func NewR2() http.Handler {
|
||
|
|
mux := http.NewServeMux()
|
||
|
|
mux.HandleFunc("/v1/entries", func(w http.ResponseWriter, r *http.Request) {
|
||
|
|
writeJSON(w, Data())
|
||
|
|
})
|
||
|
|
mux.HandleFunc("/v1/entries/latest", func(w http.ResponseWriter, r *http.Request) {
|
||
|
|
entries := Data()
|
||
|
|
sort.Slice(entries, func(i, j int) bool {
|
||
|
|
return entries[i].CreatedAt.After(entries[j].CreatedAt)
|
||
|
|
})
|
||
|
|
writeJSON(w, entries[0])
|
||
|
|
})
|
||
|
|
return mux
|
||
|
|
}
|
||
|
|
|
||
|
|
func writeJSON(w http.ResponseWriter, v any) {
|
||
|
|
w.Header().Set("Content-Type", "application/json")
|
||
|
|
_ = json.NewEncoder(w).Encode(v)
|
||
|
|
}
|