carlos / platform Public

Clone
git clone https://amadan.net/carlos/platform

Plain git — no account needed to clone.

Download

Download this file

1package console
2
3import (
4 "errors"
5 "path/filepath"
6 "reflect"
7 "testing"
8 "time"
9
10 "github.com/carlosframework/platform/internal/plans"
11)
12
13func planStore(t *testing.T, accounts ...string) (*Store, map[string]int64) {
14 t.Helper()
15 st, err := Open(filepath.Join(t.TempDir(), "console.db"))
16 if err != nil {
17 t.Fatal(err)
18 }
19 t.Cleanup(func() { st.Close() })
20 ids := map[string]int64{}
21 for i, sqid := range accounts {
22 id := int64(100 + i)
23 if err := st.CreateAccount(id, sqid, sqid, sqid+"@example.com", time.Unix(1_700_000_000, 0)); err != nil {
24 t.Fatal(err)
25 }
26 ids[sqid] = id
27 }
28 return st, ids
29}
30
31var planNow = time.Unix(1_800_000_000, 0)
32
33func TestAccountPlanAbsentIsNil(t *testing.T) {
34 st, ids := planStore(t, "aaa")
35 row, err := st.AccountPlan(ids["aaa"])
36 if err != nil || row != nil {
37 t.Fatalf("got %+v, %v; want nil, nil", row, err)
38 }
39}
40
41func TestSetAccountPlanBumpsRevision(t *testing.T) {
42 st, ids := planStore(t, "aaa")
43 id := ids["aaa"]
44 sp := &plans.Limits{RunningThings: 12}
45 rev, err := st.SetAccountPlan(id, "personal", map[string]int{"apps": 2}, "sponsored", sp, "existing user", "ops@example.com", planNow)
46 if err != nil || rev != 1 {
47 t.Fatalf("first set: rev %d, %v", rev, err)
48 }
49 rev, err = st.SetAccountPlan(id, "personal", map[string]int{"apps": 3}, "sponsored", sp, "more apps", "ops@example.com", planNow)
50 if err != nil || rev != 2 {
51 t.Fatalf("second set: rev %d, %v", rev, err)
52 }
53 row, err := st.AccountPlan(id)
54 if err != nil || row == nil {
55 t.Fatalf("read back: %+v, %v", row, err)
56 }
57 if row.Sqid != "aaa" || row.Plan != "personal" || row.Source != "sponsored" || row.Reason != "more apps" ||
58 row.UpdatedBy != "ops@example.com" || row.Revision != 2 || !row.UpdatedAt.Equal(planNow) {
59 t.Fatalf("row %+v", row)
60 }
61 if !reflect.DeepEqual(row.Packs, map[string]int{"apps": 3}) {
62 t.Fatalf("packs %v", row.Packs)
63 }
64 if row.Sponsored == nil || *row.Sponsored != *sp {
65 t.Fatalf("sponsored %+v", row.Sponsored)
66 }
67 if _, err := st.SetAccountPlan(id, "free", nil, "operator", nil, "back to free", "ops@example.com", planNow); err != nil {
68 t.Fatal(err)
69 }
70 row, _ = st.AccountPlan(id)
71 if row.Sponsored != nil || len(row.Packs) != 0 {
72 t.Fatalf("cleared row kept sponsored %+v / packs %v", row.Sponsored, row.Packs)
73 }
74}
75
76func TestEnsureDefaultPlansInsertsOnlyMissing(t *testing.T) {
77 st, ids := planStore(t, "aaa", "bbb", "ccc")
78 if _, err := st.SetAccountPlan(ids["bbb"], "personal", nil, "operator", nil, "paid", "ops@example.com", planNow); err != nil {
79 t.Fatal(err)
80 }
81 n, err := st.EnsureDefaultPlans("free", planNow)
82 if err != nil || n != 2 {
83 t.Fatalf("inserted %d, %v; want 2", n, err)
84 }
85 b, _ := st.AccountPlan(ids["bbb"])
86 if b.Plan != "personal" || b.Revision != 1 {
87 t.Fatalf("existing row changed: %+v", b)
88 }
89 a, _ := st.AccountPlan(ids["aaa"])
90 if a == nil || a.Plan != "free" || a.Source != "default" || a.Revision != 1 || a.UpdatedBy != "plans" {
91 t.Fatalf("default row %+v", a)
92 }
93 if n, err := st.EnsureDefaultPlans("free", planNow); err != nil || n != 0 {
94 t.Fatalf("second ensure inserted %d, %v", n, err)
95 }
96}
97
98func TestEnsureDefaultPlansSkipsDeletedAccounts(t *testing.T) {
99 st, ids := planStore(t, "aaa", "gone")
100 if _, err := st.db.Exec(`UPDATE accounts SET deleted_at = ? WHERE id = ?`, planNow.Unix(), ids["gone"]); err != nil {
101 t.Fatal(err)
102 }
103 if n, err := st.EnsureDefaultPlans("free", planNow); err != nil || n != 1 {
104 t.Fatalf("inserted %d, %v; want 1", n, err)
105 }
106 if row, _ := st.AccountPlan(ids["gone"]); row != nil {
107 t.Fatalf("deleted account got a row: %+v", row)
108 }
109}
110
111func TestPlansToPublish(t *testing.T) {
112 st, ids := planStore(t, "aaa", "bbb", "ccc")
113 if _, err := st.EnsureDefaultPlans("free", planNow); err != nil {
114 t.Fatal(err)
115 }
116 rows, err := st.PlansToPublish("v1@abc", 0, 10)
117 if err != nil || len(rows) != 3 {
118 t.Fatalf("got %d rows, %v; want 3", len(rows), err)
119 }
120 if rows, _ := st.PlansToPublish("v1@abc", 0, 2); len(rows) != 2 {
121 t.Fatalf("limit ignored: %d rows", len(rows))
122 }
123 if err := st.MarkPlanPublished(ids["aaa"], 1, "v1@abc"); err != nil {
124 t.Fatal(err)
125 }
126 rows, _ = st.PlansToPublish("v1@abc", 0, 10)
127 for _, r := range rows {
128 if r.Sqid == "aaa" {
129 t.Fatal("published row still due for the same catalog")
130 }
131 }
132 if len(rows) != 2 {
133 t.Fatalf("got %d rows, want 2", len(rows))
134 }
135 rows, _ = st.PlansToPublish("v2@def", 0, 10)
136 if len(rows) != 3 {
137 t.Fatalf("catalog change: got %d rows, want 3", len(rows))
138 }
139 if _, err := st.db.Exec(`UPDATE accounts SET deleted_at = ? WHERE id = ?`, planNow.Unix(), ids["bbb"]); err != nil {
140 t.Fatal(err)
141 }
142 rows, _ = st.PlansToPublish("v2@def", 0, 10)
143 if len(rows) != 2 {
144 t.Fatalf("deleted account still due: got %d rows, want 2", len(rows))
145 }
146}
147
148func TestMarkPlanPublishedIgnoresAStaleRevision(t *testing.T) {
149 st, ids := planStore(t, "aaa")
150 id := ids["aaa"]
151 for range 2 {
152 if _, err := st.SetAccountPlan(id, "free", nil, "operator", nil, "r", "ops@example.com", planNow); err != nil {
153 t.Fatal(err)
154 }
155 }
156 if err := st.MarkPlanPublished(id, 1, "c"); err != nil {
157 t.Fatal(err)
158 }
159 if row, _ := st.AccountPlan(id); row.PublishedRevision != 0 {
160 t.Fatalf("stale publish marked: %d", row.PublishedRevision)
161 }
162 if err := st.MarkPlanPublished(id, 2, "c"); err != nil {
163 t.Fatal(err)
164 }
165 if row, _ := st.AccountPlan(id); row.PublishedRevision != 2 || row.PublishedCatalog != "c" {
166 t.Fatalf("published %d / %q", row.PublishedRevision, row.PublishedCatalog)
167 }
168}
169
170// Astra plans-1 finding 3: a plan write must not land on a deleted account.
171func TestSetAccountPlanRefusesADeletedAccount(t *testing.T) {
172 st, ids := planStore(t, "gone")
173 if _, err := st.db.Exec(`UPDATE accounts SET deleted_at = ? WHERE id = ?`, planNow.Unix(), ids["gone"]); err != nil {
174 t.Fatal(err)
175 }
176 if _, err := st.SetAccountPlan(ids["gone"], "free", nil, PlanSourceOperator, nil, "r", "ops@example.com", planNow); !errors.Is(err, ErrAccountGone) {
177 t.Fatalf("err %v, want ErrAccountGone", err)
178 }
179 if row, _ := st.AccountPlan(ids["gone"]); row != nil {
180 t.Fatalf("wrote %+v", row)
181 }
182 if _, err := st.SetAccountPlan(999999, "free", nil, PlanSourceOperator, nil, "r", "ops@example.com", planNow); !errors.Is(err, ErrAccountGone) {
183 t.Fatalf("unknown account: err %v, want ErrAccountGone", err)
184 }
185}
186