| 1 | package console |
| 2 | |
| 3 | import ( |
| 4 | "context" |
| 5 | "errors" |
| 6 | "sync" |
| 7 | |
| 8 | "github.com/carlosframework/platform/internal/release" |
| 9 | ) |
| 10 | |
| 11 | // hookStore is the recording store the lifecycle tests drive failures |
| 12 | // through. failPut and failDelete map a key to how many more times it fails |
| 13 | // (a negative count fails forever); onDelete runs before each Delete, which is |
| 14 | // how a test observes the row at the moment a marker is removed; onGet runs |
| 15 | // before each Get. |
| 16 | type hookStore struct { |
| 17 | release.Store |
| 18 | mu sync.Mutex |
| 19 | failPut map[string]int |
| 20 | failDelete map[string]int |
| 21 | onDelete func(key string) |
| 22 | // onGet runs before each Get: how a test changes the bucket between two |
| 23 | // reads of one request (Task 8's ErrNotTrashed test). |
| 24 | onGet func(key string) |
| 25 | deletes []string |
| 26 | } |
| 27 | |
| 28 | func (h *hookStore) Get(ctx context.Context, key string) ([]byte, string, error) { |
| 29 | if h.onGet != nil { |
| 30 | h.onGet(key) |
| 31 | } |
| 32 | return h.Store.Get(ctx, key) |
| 33 | } |
| 34 | |
| 35 | func (h *hookStore) fails(m map[string]int, key string) bool { |
| 36 | h.mu.Lock() |
| 37 | defer h.mu.Unlock() |
| 38 | n, ok := m[key] |
| 39 | if !ok || n == 0 { |
| 40 | return false |
| 41 | } |
| 42 | if n > 0 { |
| 43 | m[key] = n - 1 |
| 44 | } |
| 45 | return true |
| 46 | } |
| 47 | |
| 48 | func (h *hookStore) Put(ctx context.Context, key string, body []byte, ifMatch string) (string, error) { |
| 49 | if h.fails(h.failPut, key) { |
| 50 | return "", errors.New("hookStore: put refused") |
| 51 | } |
| 52 | return h.Store.Put(ctx, key, body, ifMatch) |
| 53 | } |
| 54 | |
| 55 | func (h *hookStore) Delete(ctx context.Context, key string) error { |
| 56 | if h.onDelete != nil { |
| 57 | h.onDelete(key) |
| 58 | } |
| 59 | if h.fails(h.failDelete, key) { |
| 60 | return errors.New("hookStore: delete refused") |
| 61 | } |
| 62 | h.mu.Lock() |
| 63 | h.deletes = append(h.deletes, key) |
| 64 | h.mu.Unlock() |
| 65 | return h.Store.Delete(ctx, key) |
| 66 | } |
| 67 | |