blob: 9ee4ae2fbade33bc7ade890e7c63803f7387f2c0 [file] [log] [blame]
Serge Bazanski48e9bab2023-02-20 15:28:59 +01001package bmdb
2
3import (
Serge Bazanski3ea40da2023-04-19 14:32:37 +02004 "context"
Serge Bazanski48e9bab2023-02-20 15:28:59 +01005 "testing"
Serge Bazanski3ea40da2023-04-19 14:32:37 +02006
7 "source.monogon.dev/cloud/bmaas/bmdb/model"
Serge Bazanski48e9bab2023-02-20 15:28:59 +01008)
9
10// TestMigrateUpDown performs a full-up and full-down migration test on an
11// in-memory database twice.
12//
13// Doing this the first time allows us to check the up migrations are valid and
14// that the down migrations clean up enough after themselves for earlier down
15// migrations to success.
16//
17// Doing this the second time allows us to make sure the down migrations cleaned
18// up enough after themselves that they have left no table/type behind.
19func TestMigrateUpDown(t *testing.T) {
20 // Start with an empty database.
21 b := dut()
22 _, err := b.Open(false)
23 if err != nil {
24 t.Fatalf("Starting empty database failed: %v", err)
25 }
26
27 // Migrations go up.
28 if err := b.Database.MigrateUp(); err != nil {
29 t.Fatalf("Initial up migration failed: %v", err)
30 }
31 // Migrations go down.
32 if err := b.Database.MigrateDownDangerDanger(); err != nil {
33 t.Fatalf("Initial down migration failed: %v", err)
34 }
35 // Migrations go up.
36 if err := b.Database.MigrateUp(); err != nil {
37 t.Fatalf("Second up migration failed: %v", err)
38 }
39 // Migrations go down.
40 if err := b.Database.MigrateDownDangerDanger(); err != nil {
41 t.Fatalf("Second down migration failed: %v", err)
42 }
43}
Serge Bazanski6963c632023-04-06 14:55:49 +020044
45// TestMigrateTwice makes sure we don't hit https://review.monogon.dev/1502 again.
46func TestMigrateTwice(t *testing.T) {
47 // Start with an empty database.
48 b := dut()
49 _, err := b.Open(false)
50 if err != nil {
51 t.Fatalf("Starting empty database failed: %v", err)
52 }
53
54 // Migrations go up.
55 if err := b.Database.MigrateUp(); err != nil {
56 t.Fatalf("Initial up migration failed: %v", err)
57 }
58 // Migrations go up again.
59 if err := b.Database.MigrateUp(); err != nil {
60 t.Fatalf("Initial up migration failed: %v", err)
61 }
62}
Serge Bazanski3ea40da2023-04-19 14:32:37 +020063
64func TestMigration1681826233(t *testing.T) {
65 // This migration adds a new nullable field to backoffs.
66
67 // This guarantees that versions [prev, ver] can run concurrently in a cluster.
68 min := uint(1672749980)
69 max := uint(1681826233)
70
71 ctx, ctxC := context.WithCancel(context.Background())
72 defer t.Cleanup(ctxC)
73
74 b := dut()
75 conn, err := b.Open(false)
76 if err != nil {
77 t.Fatalf("Starting empty database failed: %v", err)
78 }
79
80 // First, make sure the change can actually progress if we have some backoffs
81 // already.
82 if err := b.Database.MigrateUpToIncluding(min); err != nil {
83 t.Fatalf("Migration to minimum version failed: %v", err)
84 }
85
86 // Create machine and old-style backoff.
87 q := model.New(conn.db)
88 machine, err := q.NewMachine(ctx)
89 if err != nil {
90 t.Fatalf("Could not create machine: %v", err)
91 }
92 _, err = conn.db.Exec(`
93 INSERT INTO work_backoff
94 (machine_id, process, until, cause)
95 VALUES
96 ($1, 'UnitTest1', now(), 'test');
97 `, machine.MachineID)
98 if err != nil {
99 t.Fatalf("Could not create old-style backoff on old version: %v", err)
100 }
101
102 // Migrate to newer version.
103 if err := b.Database.MigrateUpToIncluding(max); err != nil {
104 t.Fatalf("Migration to maximum version failed: %v", err)
105 }
106
107 // The migration should be read succesfully.
108 boffs, err := q.WorkBackoffOf(ctx, model.WorkBackoffOfParams{
109 MachineID: machine.MachineID,
110 Process: "UnitTest1",
111 })
112 if err != nil {
113 t.Fatalf("Reading backoff failed: %v", err)
114 }
115 if len(boffs) != 1 {
116 t.Errorf("No backoff found")
117 } else {
118 boff := boffs[0]
119 if boff.LastIntervalSeconds.Valid {
120 t.Errorf("Expected interval to be NULL")
121 }
122 }
123
124 // Simultaneously, any concurrently running bmdb user on an older version should
125 // still be able to insert and read backoffs old style.
126 _, err = conn.db.Exec(`
127 INSERT INTO work_backoff
128 (machine_id, process, until, cause)
129 VALUES
130 ($1, 'UnitTest2', now(), 'test');
131 `, machine.MachineID)
132 if err != nil {
133 t.Fatalf("Could not create old-style backoff on new version: %v", err)
134 }
135 rows, err := conn.db.Query(`
136 SELECT machine_id, process, until, cause FROM work_backoff
137 `)
138 for rows.Next() {
139 var mid, process, until, cause string
140 if err := rows.Scan(&mid, &process, &until, &cause); err != nil {
141 t.Errorf("Scan failed: %v", err)
142 }
143 }
144}